summaryrefslogtreecommitdiffstats
path: root/toolkit/crashreporter
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/crashreporter')
-rw-r--r--toolkit/crashreporter/CrashAnnotations.cpp38
-rw-r--r--toolkit/crashreporter/CrashAnnotations.h.in71
-rw-r--r--toolkit/crashreporter/CrashAnnotations.yaml978
-rw-r--r--toolkit/crashreporter/CrashReports.sys.mjs81
-rw-r--r--toolkit/crashreporter/CrashSubmit.sys.mjs666
-rw-r--r--toolkit/crashreporter/InjectCrashReporter.cpp77
-rw-r--r--toolkit/crashreporter/InjectCrashReporter.h27
-rw-r--r--toolkit/crashreporter/LoadLibraryRemote.cpp459
-rw-r--r--toolkit/crashreporter/LoadLibraryRemote.h23
-rw-r--r--toolkit/crashreporter/breakpad-client/linux/crash_generation/client_info.h68
-rw-r--r--toolkit/crashreporter/breakpad-client/linux/crash_generation/crash_generation_client.cc105
-rw-r--r--toolkit/crashreporter/breakpad-client/linux/crash_generation/crash_generation_client.h65
-rw-r--r--toolkit/crashreporter/breakpad-client/linux/crash_generation/crash_generation_server.cc378
-rw-r--r--toolkit/crashreporter/breakpad-client/linux/crash_generation/crash_generation_server.h135
-rw-r--r--toolkit/crashreporter/breakpad-client/linux/data/linux-gate-amd.sym3
-rw-r--r--toolkit/crashreporter/breakpad-client/linux/data/linux-gate-intel.sym3
-rw-r--r--toolkit/crashreporter/breakpad-client/linux/dump_writer_common/mapping_info.h75
-rw-r--r--toolkit/crashreporter/breakpad-client/linux/dump_writer_common/raw_context_cpu.h53
-rw-r--r--toolkit/crashreporter/breakpad-client/linux/dump_writer_common/thread_info.cc305
-rw-r--r--toolkit/crashreporter/breakpad-client/linux/dump_writer_common/thread_info.h91
-rw-r--r--toolkit/crashreporter/breakpad-client/linux/dump_writer_common/ucontext_reader.cc259
-rw-r--r--toolkit/crashreporter/breakpad-client/linux/dump_writer_common/ucontext_reader.h65
-rw-r--r--toolkit/crashreporter/breakpad-client/linux/handler/exception_handler.cc875
-rw-r--r--toolkit/crashreporter/breakpad-client/linux/handler/exception_handler.h289
-rw-r--r--toolkit/crashreporter/breakpad-client/linux/handler/exception_handler_unittest.cc1290
-rw-r--r--toolkit/crashreporter/breakpad-client/linux/handler/guid_generator.cc108
-rw-r--r--toolkit/crashreporter/breakpad-client/linux/handler/guid_generator.h48
-rw-r--r--toolkit/crashreporter/breakpad-client/linux/handler/microdump_extra_info.h52
-rw-r--r--toolkit/crashreporter/breakpad-client/linux/handler/minidump_descriptor.cc96
-rw-r--r--toolkit/crashreporter/breakpad-client/linux/handler/minidump_descriptor.h199
-rw-r--r--toolkit/crashreporter/breakpad-client/linux/log/log.cc84
-rw-r--r--toolkit/crashreporter/breakpad-client/linux/log/log.h55
-rw-r--r--toolkit/crashreporter/breakpad-client/linux/microdump_writer/microdump_writer.cc664
-rw-r--r--toolkit/crashreporter/breakpad-client/linux/microdump_writer/microdump_writer.h68
-rw-r--r--toolkit/crashreporter/breakpad-client/linux/microdump_writer/microdump_writer_unittest.cc421
-rw-r--r--toolkit/crashreporter/breakpad-client/linux/minidump_writer/cpu_set.h144
-rw-r--r--toolkit/crashreporter/breakpad-client/linux/minidump_writer/cpu_set_unittest.cc164
-rw-r--r--toolkit/crashreporter/breakpad-client/linux/minidump_writer/directory_reader.h106
-rw-r--r--toolkit/crashreporter/breakpad-client/linux/minidump_writer/directory_reader_unittest.cc78
-rw-r--r--toolkit/crashreporter/breakpad-client/linux/minidump_writer/line_reader.h131
-rw-r--r--toolkit/crashreporter/breakpad-client/linux/minidump_writer/line_reader_unittest.cc169
-rw-r--r--toolkit/crashreporter/breakpad-client/linux/minidump_writer/linux_core_dumper.cc308
-rw-r--r--toolkit/crashreporter/breakpad-client/linux/minidump_writer/linux_core_dumper.h130
-rw-r--r--toolkit/crashreporter/breakpad-client/linux/minidump_writer/linux_core_dumper_unittest.cc192
-rw-r--r--toolkit/crashreporter/breakpad-client/linux/minidump_writer/linux_dumper.cc999
-rw-r--r--toolkit/crashreporter/breakpad-client/linux/minidump_writer/linux_dumper.h333
-rw-r--r--toolkit/crashreporter/breakpad-client/linux/minidump_writer/linux_dumper_unittest_helper.cc95
-rw-r--r--toolkit/crashreporter/breakpad-client/linux/minidump_writer/linux_ptrace_dumper.cc403
-rw-r--r--toolkit/crashreporter/breakpad-client/linux/minidump_writer/linux_ptrace_dumper.h106
-rw-r--r--toolkit/crashreporter/breakpad-client/linux/minidump_writer/linux_ptrace_dumper_unittest.cc580
-rw-r--r--toolkit/crashreporter/breakpad-client/linux/minidump_writer/minidump_writer.cc1562
-rw-r--r--toolkit/crashreporter/breakpad-client/linux/minidump_writer/minidump_writer.h143
-rw-r--r--toolkit/crashreporter/breakpad-client/linux/minidump_writer/minidump_writer_unittest.cc934
-rw-r--r--toolkit/crashreporter/breakpad-client/linux/minidump_writer/minidump_writer_unittest_utils.cc66
-rw-r--r--toolkit/crashreporter/breakpad-client/linux/minidump_writer/minidump_writer_unittest_utils.h49
-rw-r--r--toolkit/crashreporter/breakpad-client/linux/minidump_writer/proc_cpuinfo_reader.h130
-rw-r--r--toolkit/crashreporter/breakpad-client/linux/minidump_writer/proc_cpuinfo_reader_unittest.cc199
-rw-r--r--toolkit/crashreporter/breakpad-client/linux/moz.build47
-rw-r--r--toolkit/crashreporter/breakpad-client/mac/crash_generation/client_info.h47
-rw-r--r--toolkit/crashreporter/breakpad-client/mac/crash_generation/crash_generation_client.cc74
-rw-r--r--toolkit/crashreporter/breakpad-client/mac/crash_generation/crash_generation_client.h66
-rw-r--r--toolkit/crashreporter/breakpad-client/mac/crash_generation/crash_generation_server.cc164
-rw-r--r--toolkit/crashreporter/breakpad-client/mac/crash_generation/crash_generation_server.h151
-rw-r--r--toolkit/crashreporter/breakpad-client/mac/crash_generation/moz.build18
-rw-r--r--toolkit/crashreporter/breakpad-client/mac/handler/breakpad_nlist_64.cc402
-rw-r--r--toolkit/crashreporter/breakpad-client/mac/handler/breakpad_nlist_64.h48
-rw-r--r--toolkit/crashreporter/breakpad-client/mac/handler/dynamic_images.cc625
-rw-r--r--toolkit/crashreporter/breakpad-client/mac/handler/dynamic_images.h386
-rw-r--r--toolkit/crashreporter/breakpad-client/mac/handler/exception_handler.cc990
-rw-r--r--toolkit/crashreporter/breakpad-client/mac/handler/exception_handler.h297
-rw-r--r--toolkit/crashreporter/breakpad-client/mac/handler/mach_vm_compat.h88
-rw-r--r--toolkit/crashreporter/breakpad-client/mac/handler/minidump_generator.cc2135
-rw-r--r--toolkit/crashreporter/breakpad-client/mac/handler/minidump_generator.h290
-rw-r--r--toolkit/crashreporter/breakpad-client/mac/handler/minidump_test.xcodeproj/project.pbxproj843
-rw-r--r--toolkit/crashreporter/breakpad-client/mac/handler/moz.build22
-rw-r--r--toolkit/crashreporter/breakpad-client/mac/handler/protected_memory_allocator.cc92
-rw-r--r--toolkit/crashreporter/breakpad-client/mac/handler/protected_memory_allocator.h85
-rw-r--r--toolkit/crashreporter/breakpad-client/mac/handler/testcases/DynamicImagesTests.cc79
-rw-r--r--toolkit/crashreporter/breakpad-client/mac/handler/testcases/DynamicImagesTests.h52
-rw-r--r--toolkit/crashreporter/breakpad-client/mac/handler/testcases/breakpad_nlist_test.cc106
-rw-r--r--toolkit/crashreporter/breakpad-client/mac/handler/testcases/breakpad_nlist_test.h62
-rw-r--r--toolkit/crashreporter/breakpad-client/mac/handler/testcases/dwarftests.h46
-rw-r--r--toolkit/crashreporter/breakpad-client/mac/handler/testcases/dwarftests.mm60
-rw-r--r--toolkit/crashreporter/breakpad-client/mac/handler/testcases/testdata/dump_syms_dwarf_databin0 -> 702795 bytes
-rw-r--r--toolkit/crashreporter/breakpad-client/mac/handler/testcases/testdata/dump_syms_i386_breakpad.sym5300
-rw-r--r--toolkit/crashreporter/breakpad-client/mac/handler/ucontext_compat.h47
-rw-r--r--toolkit/crashreporter/breakpad-client/mac/tests/BreakpadFramework_Test.mm217
-rw-r--r--toolkit/crashreporter/breakpad-client/mac/tests/crash_generation_server_test.cc398
-rw-r--r--toolkit/crashreporter/breakpad-client/mac/tests/exception_handler_test.cc714
-rw-r--r--toolkit/crashreporter/breakpad-client/mac/tests/minidump_generator_test.cc320
-rw-r--r--toolkit/crashreporter/breakpad-client/mac/tests/minidump_generator_test_helper.cc74
-rw-r--r--toolkit/crashreporter/breakpad-client/mac/tests/spawn_child_process.h149
-rw-r--r--toolkit/crashreporter/breakpad-client/mac/tests/testlogging.h9
-rw-r--r--toolkit/crashreporter/breakpad-client/minidump_file_writer-inl.h97
-rw-r--r--toolkit/crashreporter/breakpad-client/minidump_file_writer.cc402
-rw-r--r--toolkit/crashreporter/breakpad-client/minidump_file_writer.h281
-rw-r--r--toolkit/crashreporter/breakpad-client/minidump_file_writer_unittest.cc179
-rw-r--r--toolkit/crashreporter/breakpad-client/moz.build33
-rw-r--r--toolkit/crashreporter/breakpad-client/windows/common/auto_critical_section.h81
-rw-r--r--toolkit/crashreporter/breakpad-client/windows/common/ipc_protocol.h181
-rw-r--r--toolkit/crashreporter/breakpad-client/windows/common/minidump_callback.cc319
-rw-r--r--toolkit/crashreporter/breakpad-client/windows/common/minidump_callback.h78
-rw-r--r--toolkit/crashreporter/breakpad-client/windows/common/objs.mozbuild14
-rw-r--r--toolkit/crashreporter/breakpad-client/windows/crash_generation/ReadMe.txt58
-rw-r--r--toolkit/crashreporter/breakpad-client/windows/crash_generation/client_info.cc258
-rw-r--r--toolkit/crashreporter/breakpad-client/windows/crash_generation/client_info.h182
-rw-r--r--toolkit/crashreporter/breakpad-client/windows/crash_generation/crash_generation_client.cc406
-rw-r--r--toolkit/crashreporter/breakpad-client/windows/crash_generation/crash_generation_client.h182
-rw-r--r--toolkit/crashreporter/breakpad-client/windows/crash_generation/crash_generation_server.cc996
-rw-r--r--toolkit/crashreporter/breakpad-client/windows/crash_generation/crash_generation_server.h318
-rw-r--r--toolkit/crashreporter/breakpad-client/windows/crash_generation/minidump_generator.cc581
-rw-r--r--toolkit/crashreporter/breakpad-client/windows/crash_generation/minidump_generator.h203
-rw-r--r--toolkit/crashreporter/breakpad-client/windows/crash_generation/objs.mozbuild17
-rw-r--r--toolkit/crashreporter/breakpad-client/windows/handler/exception_handler.cc1121
-rw-r--r--toolkit/crashreporter/breakpad-client/windows/handler/exception_handler.h547
-rw-r--r--toolkit/crashreporter/breakpad-client/windows/handler/objs.mozbuild17
-rw-r--r--toolkit/crashreporter/breakpad-client/windows/sender/crash_report_sender.cc140
-rw-r--r--toolkit/crashreporter/breakpad-client/windows/sender/crash_report_sender.h122
-rw-r--r--toolkit/crashreporter/breakpad-client/windows/sender/objs.mozbuild14
-rw-r--r--toolkit/crashreporter/breakpad-client/windows/unittests/crash_generation_server_test.cc303
-rw-r--r--toolkit/crashreporter/breakpad-client/windows/unittests/dump_analysis.cc184
-rw-r--r--toolkit/crashreporter/breakpad-client/windows/unittests/dump_analysis.h102
-rw-r--r--toolkit/crashreporter/breakpad-client/windows/unittests/exception_handler_death_test.cc587
-rw-r--r--toolkit/crashreporter/breakpad-client/windows/unittests/exception_handler_nesting_test.cc327
-rw-r--r--toolkit/crashreporter/breakpad-client/windows/unittests/exception_handler_test.cc503
-rw-r--r--toolkit/crashreporter/breakpad-client/windows/unittests/exception_handler_test.h61
-rw-r--r--toolkit/crashreporter/breakpad-client/windows/unittests/minidump_test.cc332
-rw-r--r--toolkit/crashreporter/breakpad-patches/00-arm-exidx-rollup.patch1352
-rw-r--r--toolkit/crashreporter/breakpad-patches/02-define-print-mach-result.patch24
-rw-r--r--toolkit/crashreporter/breakpad-patches/03-strstr-libc-replacement.patch54
-rw-r--r--toolkit/crashreporter/breakpad-patches/04-update-headers.patch6039
-rw-r--r--toolkit/crashreporter/breakpad-patches/09-json-upload.patch333
-rw-r--r--toolkit/crashreporter/breakpad-patches/10-macho-cpu-subtype.patch47
-rw-r--r--toolkit/crashreporter/breakpad-patches/12-macho-cpu-subtype-fix.patch22
-rw-r--r--toolkit/crashreporter/breakpad-patches/13-improve-arm64-stack-walking.patch79
-rw-r--r--toolkit/crashreporter/breakpad-patches/14-handle-non-fixed-size-amd64-and-x86-contexts.patch344
-rw-r--r--toolkit/crashreporter/breakpad-patches/15-freebsd-profiler-support.patch107
-rw-r--r--toolkit/crashreporter/breakpad-patches/16-get-last-error.patch181
-rw-r--r--toolkit/crashreporter/breakpad-patches/17-unloaded-modules.patch251
-rw-r--r--toolkit/crashreporter/breakpad-patches/18-fastfail-codes.patch359
-rw-r--r--toolkit/crashreporter/breakpad-patches/19-updated-ntstatus.patch3500
-rw-r--r--toolkit/crashreporter/breakpad-patches/20-mac-crash-info.patch516
-rw-r--r--toolkit/crashreporter/breakpad-patches/21-thread-names.patch661
-rw-r--r--toolkit/crashreporter/breakpad-patches/22-winerror-codes.patch22069
-rw-r--r--toolkit/crashreporter/breakpad-patches/23-si-user-si-kernel-siginfo.patch76
-rw-r--r--toolkit/crashreporter/breakpad-patches/24-macos-exc-resource.patch155
-rw-r--r--toolkit/crashreporter/breakpad-patches/25-macos-exc-guard.patch349
-rw-r--r--toolkit/crashreporter/breakpad-patches/26-print-thread-tid.patch44
-rw-r--r--toolkit/crashreporter/breakpad-patches/27-fix-unified-builds-bug-1733547.patch22
-rw-r--r--toolkit/crashreporter/breakpad-patches/28-no-garbage-in-code-ids.patch34
-rw-r--r--toolkit/crashreporter/breakpad-patches/29-cpu-context-packing.patch118
-rw-r--r--toolkit/crashreporter/breakpad-patches/30-sign-compare.patch11
-rw-r--r--toolkit/crashreporter/breakpad-patches/README4
-rw-r--r--toolkit/crashreporter/breakpad-windows-libxul/moz.build29
-rw-r--r--toolkit/crashreporter/breakpad-windows-standalone/moz.build29
-rw-r--r--toolkit/crashreporter/client/Makefile.in19
-rw-r--r--toolkit/crashreporter/client/Throbber-small.avibin0 -> 3584 bytes
-rw-r--r--toolkit/crashreporter/client/Throbber-small.gifbin0 -> 825 bytes
-rw-r--r--toolkit/crashreporter/client/crashreporter.cpp833
-rw-r--r--toolkit/crashreporter/client/crashreporter.exe.manifest42
-rw-r--r--toolkit/crashreporter/client/crashreporter.h159
-rw-r--r--toolkit/crashreporter/client/crashreporter.icobin0 -> 25214 bytes
-rwxr-xr-xtoolkit/crashreporter/client/crashreporter.rc143
-rw-r--r--toolkit/crashreporter/client/crashreporter_gtk_common.cpp361
-rw-r--r--toolkit/crashreporter/client/crashreporter_gtk_common.h50
-rw-r--r--toolkit/crashreporter/client/crashreporter_linux.cpp525
-rw-r--r--toolkit/crashreporter/client/crashreporter_osx.h107
-rw-r--r--toolkit/crashreporter/client/crashreporter_osx.mm762
-rw-r--r--toolkit/crashreporter/client/crashreporter_unix_common.cpp139
-rw-r--r--toolkit/crashreporter/client/crashreporter_win.cpp1295
-rw-r--r--toolkit/crashreporter/client/macbuild/Contents/Info.plist36
-rw-r--r--toolkit/crashreporter/client/macbuild/Contents/PkgInfo2
-rw-r--r--toolkit/crashreporter/client/macbuild/Contents/Resources/English.lproj/InfoPlist.strings.in8
-rw-r--r--toolkit/crashreporter/client/macbuild/Contents/Resources/English.lproj/MainMenu.nib/classes.nib100
-rw-r--r--toolkit/crashreporter/client/macbuild/Contents/Resources/English.lproj/MainMenu.nib/info.nib18
-rw-r--r--toolkit/crashreporter/client/macbuild/Contents/Resources/English.lproj/MainMenu.nib/keyedobjects.nibbin0 -> 25518 bytes
-rw-r--r--toolkit/crashreporter/client/macbuild/Contents/Resources/English.lproj/MainMenuRTL.nib/classes.nib100
-rw-r--r--toolkit/crashreporter/client/macbuild/Contents/Resources/English.lproj/MainMenuRTL.nib/info.nib18
-rw-r--r--toolkit/crashreporter/client/macbuild/Contents/Resources/English.lproj/MainMenuRTL.nib/keyedobjects.nibbin0 -> 27032 bytes
-rw-r--r--toolkit/crashreporter/client/macbuild/Contents/Resources/crashreporter.icnsbin0 -> 61743 bytes
-rw-r--r--toolkit/crashreporter/client/moz.build96
-rw-r--r--toolkit/crashreporter/client/ping.cpp324
-rw-r--r--toolkit/crashreporter/client/resource.h35
-rw-r--r--toolkit/crashreporter/content/crashes.css70
-rw-r--r--toolkit/crashreporter/content/crashes.html99
-rw-r--r--toolkit/crashreporter/content/crashes.js316
-rw-r--r--toolkit/crashreporter/crashreporter.mozbuild34
-rw-r--r--toolkit/crashreporter/docs/Using_the_Mozilla_symbol_server.rst168
-rw-r--r--toolkit/crashreporter/docs/img/snip_20170901070042.pngbin0 -> 15434 bytes
-rw-r--r--toolkit/crashreporter/docs/img/snip_20170901081816.pngbin0 -> 3821 bytes
-rw-r--r--toolkit/crashreporter/docs/img/symbol-server-windbg-menu.jpgbin0 -> 17919 bytes
-rw-r--r--toolkit/crashreporter/docs/img/vs_tools_options.pngbin0 -> 12084 bytes
-rw-r--r--toolkit/crashreporter/docs/index.rst265
-rw-r--r--toolkit/crashreporter/generate_crash_reporter_sources.py205
-rw-r--r--toolkit/crashreporter/google-breakpad/.gitignore90
-rw-r--r--toolkit/crashreporter/google-breakpad/AUTHORS1
-rw-r--r--toolkit/crashreporter/google-breakpad/ChangeLog0
-rw-r--r--toolkit/crashreporter/google-breakpad/DEPS84
-rw-r--r--toolkit/crashreporter/google-breakpad/GIT-INFO1
-rw-r--r--toolkit/crashreporter/google-breakpad/INSTALL370
-rw-r--r--toolkit/crashreporter/google-breakpad/LICENSE50
-rw-r--r--toolkit/crashreporter/google-breakpad/Makefile.am1576
-rw-r--r--toolkit/crashreporter/google-breakpad/Makefile.in8223
-rw-r--r--toolkit/crashreporter/google-breakpad/NEWS0
-rw-r--r--toolkit/crashreporter/google-breakpad/README.ANDROID139
-rw-r--r--toolkit/crashreporter/google-breakpad/README.md82
-rw-r--r--toolkit/crashreporter/google-breakpad/aclocal.m41304
-rwxr-xr-xtoolkit/crashreporter/google-breakpad/android/common-functions.sh372
-rw-r--r--toolkit/crashreporter/google-breakpad/android/google_breakpad/Android.mk104
-rwxr-xr-xtoolkit/crashreporter/google-breakpad/android/run-checks.sh555
-rw-r--r--toolkit/crashreporter/google-breakpad/android/sample_app/README32
-rw-r--r--toolkit/crashreporter/google-breakpad/android/sample_app/jni/Android.mk44
-rw-r--r--toolkit/crashreporter/google-breakpad/android/sample_app/jni/Application.mk32
-rw-r--r--toolkit/crashreporter/google-breakpad/android/sample_app/jni/test_breakpad.cpp57
-rwxr-xr-xtoolkit/crashreporter/google-breakpad/android/test-driver131
-rwxr-xr-xtoolkit/crashreporter/google-breakpad/android/test-shell.sh131
-rw-r--r--toolkit/crashreporter/google-breakpad/breakpad-client.pc.in10
-rw-r--r--toolkit/crashreporter/google-breakpad/breakpad.pc.in10
-rw-r--r--toolkit/crashreporter/google-breakpad/codereview.settings3
-rwxr-xr-xtoolkit/crashreporter/google-breakpad/configure9231
-rw-r--r--toolkit/crashreporter/google-breakpad/configure.ac271
-rw-r--r--toolkit/crashreporter/google-breakpad/default.xml43
-rw-r--r--toolkit/crashreporter/google-breakpad/src/breakpad_googletest_includes.h57
-rw-r--r--toolkit/crashreporter/google-breakpad/src/build/all.gyp41
-rw-r--r--toolkit/crashreporter/google-breakpad/src/build/common.gypi1045
-rw-r--r--toolkit/crashreporter/google-breakpad/src/build/filename_rules.gypi57
-rwxr-xr-xtoolkit/crashreporter/google-breakpad/src/build/gyp_breakpad67
-rw-r--r--toolkit/crashreporter/google-breakpad/src/build/testing.gyp90
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/android/include/asm-mips/README.md9
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/android/include/asm-mips/asm.h270
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/android/include/asm-mips/fpregdef.h117
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/android/include/asm-mips/regdef.h125
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/android/include/elf.h157
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/android/include/link.h77
-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/user.h69
-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.h94
-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.gyp260
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/convert_UTF.cc591
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/convert_UTF.h159
-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.cc204
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/dwarf/cfi_assembler.h271
-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.h679
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/dwarf/dwarf2reader.cc2815
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/dwarf/dwarf2reader.h1331
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/dwarf/dwarf2reader_cfi_unittest.cc2582
-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.cc1274
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/dwarf/elf_reader.h166
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/dwarf/functioninfo.cc234
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/dwarf/functioninfo.h190
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/dwarf/line_state_machine.h61
-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.cc1243
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/dwarf_cu_to_module.h345
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/dwarf_cu_to_module_unittest.cc1854
-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/dwarf_range_list_handler.cc60
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/dwarf_range_list_handler.h79
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/language.cc197
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/language.h105
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/linux/breakpad_getcontext.S486
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/linux/breakpad_getcontext.h56
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/linux/breakpad_getcontext_unittest.cc194
-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.cc1218
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/linux/dump_symbols.h93
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/linux/dump_symbols_unittest.cc208
-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.h149
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/linux/elf_core_dump_unittest.cc265
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/linux/elf_gnu_compat.h51
-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.cc241
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/linux/elfutils.h135
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/linux/file_id.cc200
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/linux/file_id.h88
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/linux/file_id_unittest.cc372
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/linux/google_crashdump_uploader.cc207
-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.cc189
-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.cc210
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/linux/http_upload.h84
-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.cc338
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/linux/libcurl_wrapper.h119
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/linux/linux_libc_support.cc248
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/linux/linux_libc_support.h98
-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.build42
-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_collector_client.cc195
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/linux/symbol_collector_client.h88
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/linux/symbol_upload.cc284
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/linux/symbol_upload.h76
-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.cc329
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/linux/tests/crash_generator.h117
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/linux/ucontext_constants.h153
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/long_string_dictionary.cc178
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/long_string_dictionary.h87
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/long_string_dictionary_unittest.cc301
-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.h396
-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.m262
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/mac/MachIPC.h303
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/mac/MachIPC.mm306
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/mac/arch_utilities.cc264
-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.cc679
-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.cc558
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/mac/macho_reader.h464
-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.cc272
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/mac/macho_walker.h119
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/mac/moz.build27
-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/macros.h45
-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_allocator.h252
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/memory_allocator_unittest.cc124
-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/minidump_type_helper.h56
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/module.cc387
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/module.h376
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/module_unittest.cc674
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/moz.build19
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/path_helper.cc55
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/path_helper.h44
-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.h279
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/simple_string_dictionary_unittest.cc339
-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/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.cc199
-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/string_conversion_unittest.cc64
-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.gyp112
-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.cc493
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/windows/http_upload.h125
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/windows/module_info.h75
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/windows/objs.mozbuild15
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/windows/omap.cc716
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/windows/omap.h72
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/windows/omap_internal.h140
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/windows/omap_unittest.cc329
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/windows/pdb_source_line_writer.cc1194
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/windows/pdb_source_line_writer.h226
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/windows/pe_source_line_writer.cc77
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/windows/pe_source_line_writer.h69
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/windows/pe_util.cc407
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/windows/pe_util.h78
-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
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/windows/symbol_collector_client.cc155
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/windows/symbol_collector_client.h89
-rw-r--r--toolkit/crashreporter/google-breakpad/src/config.h.in94
-rw-r--r--toolkit/crashreporter/google-breakpad/src/google_breakpad/common/breakpad_types.h68
-rw-r--r--toolkit/crashreporter/google-breakpad/src/google_breakpad/common/minidump_cpu_amd64.h235
-rw-r--r--toolkit/crashreporter/google-breakpad/src/google_breakpad/common/minidump_cpu_arm.h151
-rw-r--r--toolkit/crashreporter/google-breakpad/src/google_breakpad/common/minidump_cpu_arm64.h192
-rw-r--r--toolkit/crashreporter/google-breakpad/src/google_breakpad/common/minidump_cpu_mips.h176
-rw-r--r--toolkit/crashreporter/google-breakpad/src/google_breakpad/common/minidump_cpu_ppc.h159
-rw-r--r--toolkit/crashreporter/google-breakpad/src/google_breakpad/common/minidump_cpu_ppc64.h134
-rw-r--r--toolkit/crashreporter/google-breakpad/src/google_breakpad/common/minidump_cpu_sparc.h163
-rw-r--r--toolkit/crashreporter/google-breakpad/src/google_breakpad/common/minidump_cpu_x86.h174
-rw-r--r--toolkit/crashreporter/google-breakpad/src/google_breakpad/common/minidump_exception_fuchsia.h58
-rw-r--r--toolkit/crashreporter/google-breakpad/src/google_breakpad/common/minidump_exception_linux.h129
-rw-r--r--toolkit/crashreporter/google-breakpad/src/google_breakpad/common/minidump_exception_mac.h314
-rw-r--r--toolkit/crashreporter/google-breakpad/src/google_breakpad/common/minidump_exception_ps3.h67
-rw-r--r--toolkit/crashreporter/google-breakpad/src/google_breakpad/common/minidump_exception_solaris.h94
-rw-r--r--toolkit/crashreporter/google-breakpad/src/google_breakpad/common/minidump_exception_win32.h5575
-rw-r--r--toolkit/crashreporter/google-breakpad/src/google_breakpad/common/minidump_format.h1178
-rw-r--r--toolkit/crashreporter/google-breakpad/src/google_breakpad/common/minidump_size.h113
-rw-r--r--toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/basic_source_line_resolver.h148
-rw-r--r--toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/call_stack.h97
-rw-r--r--toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/code_module.h104
-rw-r--r--toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/code_modules.h108
-rw-r--r--toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/dump_context.h116
-rw-r--r--toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/dump_object.h53
-rw-r--r--toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/exception_record.h124
-rw-r--r--toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/exploitability.h82
-rw-r--r--toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/fast_source_line_resolver.h100
-rw-r--r--toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/memory_region.h79
-rw-r--r--toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/microdump.h135
-rw-r--r--toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/microdump_processor.h64
-rw-r--r--toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/minidump.h1498
-rw-r--r--toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/minidump_processor.h147
-rw-r--r--toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/proc_maps_linux.h60
-rw-r--r--toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/process_result.h66
-rw-r--r--toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/process_state.h220
-rw-r--r--toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/source_line_resolver_base.h128
-rw-r--r--toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/source_line_resolver_interface.h117
-rw-r--r--toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/stack_frame.h144
-rw-r--r--toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/stack_frame_cpu.h405
-rw-r--r--toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/stack_frame_symbolizer.h110
-rw-r--r--toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/stackwalker.h257
-rw-r--r--toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/symbol_supplier.h99
-rw-r--r--toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/system_info.h106
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/address_map-inl.h93
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/address_map.h85
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/address_map_unittest.cc196
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/basic_code_module.h121
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/basic_code_modules.cc152
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/basic_code_modules.h97
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/basic_source_line_resolver.cc657
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/basic_source_line_resolver_types.h179
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/basic_source_line_resolver_unittest.cc744
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/call_stack.cc56
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/cfi_frame_info-inl.h119
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/cfi_frame_info.cc186
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/cfi_frame_info.h275
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/cfi_frame_info_unittest.cc546
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/contained_range_map-inl.h197
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/contained_range_map.h150
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/contained_range_map_unittest.cc263
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/convert_old_arm64_context.cc67
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/convert_old_arm64_context.h42
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/disassembler_x86.cc240
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/disassembler_x86.h127
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/disassembler_x86_unittest.cc233
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/dump_context.cc664
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/dump_object.cc39
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/exploitability.cc120
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/exploitability_linux.cc626
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/exploitability_linux.h129
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/exploitability_unittest.cc306
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/exploitability_win.cc283
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/exploitability_win.h55
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/fast_source_line_resolver.cc275
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/fast_source_line_resolver_types.h185
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/fast_source_line_resolver_unittest.cc492
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/linked_ptr.h193
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/logging.cc114
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/logging.h188
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/map_serializers-inl.h266
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/map_serializers.h168
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/map_serializers_unittest.cc386
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/microdump.cc405
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/microdump_processor.cc97
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/microdump_processor_unittest.cc285
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/microdump_stackwalk.cc181
-rwxr-xr-xtoolkit/crashreporter/google-breakpad/src/processor/microdump_stackwalk_machine_readable_test43
-rwxr-xr-xtoolkit/crashreporter/google-breakpad/src/processor/microdump_stackwalk_test43
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/microdump_stackwalk_test_vars1
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/minidump.cc6445
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/minidump_dump.cc291
-rwxr-xr-xtoolkit/crashreporter/google-breakpad/src/processor/minidump_dump_test36
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/minidump_processor.cc2146
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/minidump_processor_unittest.cc769
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/minidump_stackwalk.cc179
-rwxr-xr-xtoolkit/crashreporter/google-breakpad/src/processor/minidump_stackwalk_machine_readable_test37
-rwxr-xr-xtoolkit/crashreporter/google-breakpad/src/processor/minidump_stackwalk_test37
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/minidump_unittest.cc1628
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/module_comparer.cc302
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/module_comparer.h98
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/module_factory.h72
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/module_serializer.cc207
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/module_serializer.h127
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/moz.build76
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/pathname_stripper.cc56
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/pathname_stripper.h53
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/pathname_stripper_unittest.cc87
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/postfix_evaluator-inl.h363
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/postfix_evaluator.h179
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/postfix_evaluator_unittest.cc403
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/proc_maps_linux.cc106
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/proc_maps_linux_unittest.cc251
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/process_state.cc71
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/processor.gyp187
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/processor_tools.gypi57
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/proto/README20
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/proto/process_state.proto210
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/range_map-inl.h291
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/range_map.h171
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/range_map_truncate_lower_unittest.cc346
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/range_map_truncate_upper_unittest.cc354
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/range_map_unittest.cc559
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/simple_serializer-inl.h260
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/simple_serializer.h63
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/simple_symbol_supplier.cc204
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/simple_symbol_supplier.h140
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/source_line_resolver_base.cc341
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/source_line_resolver_base_types.h167
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/stack_frame_cpu.cc79
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/stack_frame_symbolizer.cc144
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/stackwalk_common.cc1036
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/stackwalk_common.h49
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/stackwalker.cc333
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/stackwalker_address_list.cc92
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/stackwalker_address_list.h72
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/stackwalker_address_list_unittest.cc197
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/stackwalker_amd64.cc326
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/stackwalker_amd64.h108
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/stackwalker_amd64_unittest.cc934
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/stackwalker_arm.cc297
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/stackwalker_arm.h107
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/stackwalker_arm64.cc351
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/stackwalker_arm64.h121
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/stackwalker_arm64_unittest.cc881
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/stackwalker_arm_unittest.cc979
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/stackwalker_mips.cc442
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/stackwalker_mips.h85
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/stackwalker_mips64_unittest.cc716
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/stackwalker_mips_unittest.cc704
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/stackwalker_ppc.cc155
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/stackwalker_ppc.h79
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/stackwalker_ppc64.cc146
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/stackwalker_ppc64.h77
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/stackwalker_selftest.cc433
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/stackwalker_selftest_sol.s111
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/stackwalker_sparc.cc147
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/stackwalker_sparc.h78
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/stackwalker_unittest_utils.h220
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/stackwalker_x86.cc680
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/stackwalker_x86.h117
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/stackwalker_x86_unittest.cc2266
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/static_address_map-inl.h71
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/static_address_map.h78
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/static_address_map_unittest.cc236
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/static_contained_range_map-inl.h92
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/static_contained_range_map.h96
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/static_contained_range_map_unittest.cc320
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/static_map-inl.h176
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/static_map.h144
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/static_map_iterator-inl.h147
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/static_map_iterator.h112
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/static_map_unittest.cc386
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/static_range_map-inl.h130
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/static_range_map.h106
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/static_range_map_unittest.cc421
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/symbolic_constants_win.cc10958
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/symbolic_constants_win.h61
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/synth_minidump.cc421
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/synth_minidump.h398
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/synth_minidump_unittest.cc336
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/synth_minidump_unittest_data.h418
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/tokenize.cc79
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/tokenize.h63
-rw-r--r--toolkit/crashreporter/google-breakpad/src/processor/windows_frame_info.h209
-rw-r--r--toolkit/crashreporter/google-breakpad/src/third_party/curl/COPYING22
-rw-r--r--toolkit/crashreporter/google-breakpad/src/third_party/curl/curl.h2864
-rw-r--r--toolkit/crashreporter/google-breakpad/src/third_party/curl/curlver.h77
-rw-r--r--toolkit/crashreporter/google-breakpad/src/third_party/curl/easy.h112
-rw-r--r--toolkit/crashreporter/google-breakpad/src/third_party/curl/multi.h441
-rw-r--r--toolkit/crashreporter/google-breakpad/src/third_party/curl/system.h493
-rw-r--r--toolkit/crashreporter/google-breakpad/src/third_party/curl/typecheck-gcc.h700
-rw-r--r--toolkit/crashreporter/google-breakpad/src/third_party/curl/urlapi.h122
-rw-r--r--toolkit/crashreporter/google-breakpad/src/third_party/glog/Makefile.in1553
-rw-r--r--toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/LICENSE137
-rw-r--r--toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/Makefile.am43
-rw-r--r--toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/README.breakpad9
-rw-r--r--toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/TODO43
-rw-r--r--toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/ia32_implicit.c422
-rw-r--r--toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/ia32_implicit.h13
-rw-r--r--toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/ia32_insn.c623
-rw-r--r--toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/ia32_insn.h506
-rw-r--r--toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/ia32_invariant.c313
-rw-r--r--toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/ia32_invariant.h11
-rw-r--r--toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/ia32_modrm.c310
-rw-r--r--toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/ia32_modrm.h13
-rw-r--r--toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/ia32_opcode_tables.c2939
-rw-r--r--toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/ia32_opcode_tables.h57
-rw-r--r--toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/ia32_operand.c425
-rw-r--r--toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/ia32_operand.h11
-rw-r--r--toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/ia32_reg.c234
-rw-r--r--toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/ia32_reg.h41
-rw-r--r--toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/ia32_settings.c13
-rw-r--r--toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/ia32_settings.h27
-rw-r--r--toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/libdis.h832
-rw-r--r--toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/libdisasm.gyp67
-rw-r--r--toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/qword.h14
-rw-r--r--toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/swig/Makefile70
-rw-r--r--toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/swig/README128
-rw-r--r--toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/swig/libdisasm.i508
-rw-r--r--toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/swig/libdisasm_oop.i1114
-rw-r--r--toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/swig/perl/Makefile-swig65
-rw-r--r--toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/swig/perl/Makefile.PL7
-rw-r--r--toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/swig/python/Makefile-swig64
-rw-r--r--toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/swig/ruby/Makefile-swig68
-rw-r--r--toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/swig/ruby/extconf.rb4
-rw-r--r--toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/swig/tcl/Makefile-swig63
-rw-r--r--toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/x86_disasm.c210
-rw-r--r--toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/x86_format.c1430
-rw-r--r--toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/x86_imm.c70
-rw-r--r--toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/x86_imm.h18
-rw-r--r--toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/x86_insn.c182
-rw-r--r--toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/x86_misc.c71
-rw-r--r--toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/x86_operand_list.c191
-rw-r--r--toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/x86_operand_list.h8
-rw-r--r--toolkit/crashreporter/google-breakpad/src/third_party/lss/.gitignore3
-rw-r--r--toolkit/crashreporter/google-breakpad/src/third_party/lss/README.md137
-rw-r--r--toolkit/crashreporter/google-breakpad/src/third_party/lss/codereview.settings5
-rw-r--r--toolkit/crashreporter/google-breakpad/src/third_party/lss/linux_syscall_support.h4553
-rw-r--r--toolkit/crashreporter/google-breakpad/src/third_party/lss/tests/.gitignore4
-rw-r--r--toolkit/crashreporter/google-breakpad/src/third_party/lss/tests/Makefile131
-rw-r--r--toolkit/crashreporter/google-breakpad/src/third_party/lss/tests/README.md52
-rw-r--r--toolkit/crashreporter/google-breakpad/src/third_party/lss/tests/fallocate.c67
-rw-r--r--toolkit/crashreporter/google-breakpad/src/third_party/lss/tests/sigtimedwait.c58
-rw-r--r--toolkit/crashreporter/google-breakpad/src/third_party/lss/tests/test_skel.h70
-rw-r--r--toolkit/crashreporter/google-breakpad/src/third_party/lss/tests/unlink.c48
-rw-r--r--toolkit/crashreporter/google-breakpad/src/third_party/mac_headers/README2
-rw-r--r--toolkit/crashreporter/google-breakpad/src/third_party/mac_headers/architecture/byte_order.h45
-rw-r--r--toolkit/crashreporter/google-breakpad/src/third_party/mac_headers/i386/_types.h34
-rw-r--r--toolkit/crashreporter/google-breakpad/src/third_party/mac_headers/mach-o/arch.h105
-rw-r--r--toolkit/crashreporter/google-breakpad/src/third_party/mac_headers/mach-o/fat.h64
-rw-r--r--toolkit/crashreporter/google-breakpad/src/third_party/mac_headers/mach-o/loader.h1402
-rw-r--r--toolkit/crashreporter/google-breakpad/src/third_party/mac_headers/mach-o/nlist.h312
-rw-r--r--toolkit/crashreporter/google-breakpad/src/third_party/mac_headers/mach/boolean.h88
-rw-r--r--toolkit/crashreporter/google-breakpad/src/third_party/mac_headers/mach/i386/boolean.h74
-rw-r--r--toolkit/crashreporter/google-breakpad/src/third_party/mac_headers/mach/i386/vm_param.h157
-rw-r--r--toolkit/crashreporter/google-breakpad/src/third_party/mac_headers/mach/i386/vm_types.h140
-rw-r--r--toolkit/crashreporter/google-breakpad/src/third_party/mac_headers/mach/machine.h347
-rw-r--r--toolkit/crashreporter/google-breakpad/src/third_party/mac_headers/mach/machine/boolean.h40
-rw-r--r--toolkit/crashreporter/google-breakpad/src/third_party/mac_headers/mach/machine/thread_state.h9
-rw-r--r--toolkit/crashreporter/google-breakpad/src/third_party/mac_headers/mach/machine/thread_status.h1
-rw-r--r--toolkit/crashreporter/google-breakpad/src/third_party/mac_headers/mach/machine/vm_types.h40
-rw-r--r--toolkit/crashreporter/google-breakpad/src/third_party/mac_headers/mach/thread_status.h94
-rw-r--r--toolkit/crashreporter/google-breakpad/src/third_party/mac_headers/mach/vm_prot.h140
-rw-r--r--toolkit/crashreporter/google-breakpad/src/third_party/musl/COPYRIGHT163
-rw-r--r--toolkit/crashreporter/google-breakpad/src/third_party/musl/README23
-rw-r--r--toolkit/crashreporter/google-breakpad/src/third_party/musl/README.breakpad3
-rw-r--r--toolkit/crashreporter/google-breakpad/src/third_party/musl/VERSION1
-rw-r--r--toolkit/crashreporter/google-breakpad/src/third_party/musl/include/elf.h3234
-rw-r--r--toolkit/crashreporter/google-breakpad/src/tools/linux/core2md/core2md.cc72
-rw-r--r--toolkit/crashreporter/google-breakpad/src/tools/linux/dump_syms/dump_syms.cc137
-rw-r--r--toolkit/crashreporter/google-breakpad/src/tools/linux/md2core/minidump-2-core.cc1428
-rw-r--r--toolkit/crashreporter/google-breakpad/src/tools/linux/md2core/minidump_memory_range.h89
-rw-r--r--toolkit/crashreporter/google-breakpad/src/tools/linux/md2core/minidump_memory_range_unittest.cc258
-rw-r--r--toolkit/crashreporter/google-breakpad/src/tools/linux/symupload/minidump_upload.cc153
-rw-r--r--toolkit/crashreporter/google-breakpad/src/tools/linux/symupload/sym_upload.cc210
-rw-r--r--toolkit/crashreporter/google-breakpad/src/tools/linux/tools_linux.gypi83
-rw-r--r--toolkit/crashreporter/google-breakpad/src/tools/mac/crash_report/crash_report.mm408
-rw-r--r--toolkit/crashreporter/google-breakpad/src/tools/mac/crash_report/crash_report.xcodeproj/project.pbxproj618
-rw-r--r--toolkit/crashreporter/google-breakpad/src/tools/mac/crash_report/on_demand_symbol_supplier.h111
-rw-r--r--toolkit/crashreporter/google-breakpad/src/tools/mac/crash_report/on_demand_symbol_supplier.mm314
-rw-r--r--toolkit/crashreporter/google-breakpad/src/tools/mac/dump_syms/dump_syms.xcodeproj/project.pbxproj1857
-rw-r--r--toolkit/crashreporter/google-breakpad/src/tools/mac/dump_syms/dump_syms_tool.cc264
-rw-r--r--toolkit/crashreporter/google-breakpad/src/tools/mac/dump_syms/macho_dump.cc203
-rw-r--r--toolkit/crashreporter/google-breakpad/src/tools/mac/symupload/minidump_upload.m135
-rw-r--r--toolkit/crashreporter/google-breakpad/src/tools/mac/symupload/symupload.m204
-rw-r--r--toolkit/crashreporter/google-breakpad/src/tools/mac/symupload/symupload.xcodeproj/project.pbxproj254
-rw-r--r--toolkit/crashreporter/google-breakpad/src/tools/mac/tools_mac.gypi116
-rw-r--r--toolkit/crashreporter/google-breakpad/src/tools/mac/upload_system_symbols/arch_constants.h67
-rw-r--r--toolkit/crashreporter/google-breakpad/src/tools/mac/upload_system_symbols/arch_reader.go69
-rw-r--r--toolkit/crashreporter/google-breakpad/src/tools/mac/upload_system_symbols/upload_system_symbols.go432
-rwxr-xr-xtoolkit/crashreporter/google-breakpad/src/tools/python/deps-to-manifest.py167
-rw-r--r--toolkit/crashreporter/google-breakpad/src/tools/python/filter_syms.py204
-rw-r--r--toolkit/crashreporter/google-breakpad/src/tools/python/tests/filter_syms_unittest.py138
-rw-r--r--toolkit/crashreporter/google-breakpad/src/tools/solaris/dump_syms/Makefile64
-rw-r--r--toolkit/crashreporter/google-breakpad/src/tools/solaris/dump_syms/Makefile.in5
-rw-r--r--toolkit/crashreporter/google-breakpad/src/tools/solaris/dump_syms/dump_syms.cc54
-rw-r--r--toolkit/crashreporter/google-breakpad/src/tools/solaris/dump_syms/run_regtest.sh51
-rw-r--r--toolkit/crashreporter/google-breakpad/src/tools/solaris/dump_syms/testdata/dump_syms_regtest.cc64
-rw-r--r--toolkit/crashreporter/google-breakpad/src/tools/solaris/dump_syms/testdata/dump_syms_regtest.obin0 -> 14204 bytes
-rw-r--r--toolkit/crashreporter/google-breakpad/src/tools/solaris/dump_syms/testdata/dump_syms_regtest.stabs129
-rw-r--r--toolkit/crashreporter/google-breakpad/src/tools/solaris/dump_syms/testdata/dump_syms_regtest.sym33
-rw-r--r--toolkit/crashreporter/google-breakpad/src/tools/tools.gyp38
-rw-r--r--toolkit/crashreporter/google-breakpad/src/tools/windows/binaries/dump_syms.exebin0 -> 141824 bytes
-rw-r--r--toolkit/crashreporter/google-breakpad/src/tools/windows/binaries/symupload.exebin0 -> 243712 bytes
-rw-r--r--toolkit/crashreporter/google-breakpad/src/tools/windows/converter/ms_symbol_server_converter.cc752
-rw-r--r--toolkit/crashreporter/google-breakpad/src/tools/windows/converter/ms_symbol_server_converter.gyp46
-rw-r--r--toolkit/crashreporter/google-breakpad/src/tools/windows/converter/ms_symbol_server_converter.h235
-rw-r--r--toolkit/crashreporter/google-breakpad/src/tools/windows/converter/ms_symbol_server_converter.vcproj368
-rw-r--r--toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/configure.cmd33
-rw-r--r--toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/converter.cc807
-rw-r--r--toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/converter.gyp57
-rw-r--r--toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/escaping.cc757
-rw-r--r--toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/escaping.h99
-rw-r--r--toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/http_client.h96
-rw-r--r--toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/http_download.cc326
-rw-r--r--toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/http_download.h62
-rw-r--r--toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/missing_symbols_test.txt5
-rw-r--r--toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/symsrv.yes2
-rw-r--r--toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/tokenizer.cc61
-rw-r--r--toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/tokenizer.h51
-rw-r--r--toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/winhttp_client.cc307
-rw-r--r--toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/winhttp_client.h40
-rw-r--r--toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/wininet_client.cc278
-rw-r--r--toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/wininet_client.h40
-rw-r--r--toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/winsymconv.cmd86
-rw-r--r--toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/winsymconv_test.cmd72
-rw-r--r--toolkit/crashreporter/google-breakpad/src/tools/windows/dump_syms/dump_syms.cc73
-rw-r--r--toolkit/crashreporter/google-breakpad/src/tools/windows/dump_syms/dump_syms.gyp64
-rw-r--r--toolkit/crashreporter/google-breakpad/src/tools/windows/dump_syms/dump_syms.vcproj242
-rw-r--r--toolkit/crashreporter/google-breakpad/src/tools/windows/dump_syms/dump_syms_unittest.cc244
-rwxr-xr-xtoolkit/crashreporter/google-breakpad/src/tools/windows/dump_syms/run_regtest.sh53
-rw-r--r--toolkit/crashreporter/google-breakpad/src/tools/windows/refresh_binaries.bat23
-rw-r--r--toolkit/crashreporter/google-breakpad/src/tools/windows/symupload/symupload.cc394
-rw-r--r--toolkit/crashreporter/google-breakpad/src/tools/windows/symupload/symupload.gyp50
-rw-r--r--toolkit/crashreporter/google-breakpad/src/tools/windows/tools_windows.gyp46
-rw-r--r--toolkit/crashreporter/injector/injector.cpp35
-rw-r--r--toolkit/crashreporter/injector/moz.build27
-rw-r--r--toolkit/crashreporter/jar.mn10
-rw-r--r--toolkit/crashreporter/mac_utils.h14
-rw-r--r--toolkit/crashreporter/mac_utils.mm29
-rw-r--r--toolkit/crashreporter/minidump-analyzer/MinidumpAnalyzerUtils.h115
-rw-r--r--toolkit/crashreporter/minidump-analyzer/MozStackFrameSymbolizer.cpp117
-rw-r--r--toolkit/crashreporter/minidump-analyzer/MozStackFrameSymbolizer.h48
-rw-r--r--toolkit/crashreporter/minidump-analyzer/Win64ModuleUnwindMetadata.cpp227
-rw-r--r--toolkit/crashreporter/minidump-analyzer/Win64ModuleUnwindMetadata.h56
-rw-r--r--toolkit/crashreporter/minidump-analyzer/minidump-analyzer.cpp604
-rw-r--r--toolkit/crashreporter/minidump-analyzer/minidump-analyzer.exe.manifest19
-rw-r--r--toolkit/crashreporter/minidump-analyzer/moz.build43
-rw-r--r--toolkit/crashreporter/moz.build139
-rw-r--r--toolkit/crashreporter/mozwer-rust/Cargo.toml20
-rw-r--r--toolkit/crashreporter/mozwer-rust/lib.rs1005
-rw-r--r--toolkit/crashreporter/mozwer-rust/moz.build11
-rw-r--r--toolkit/crashreporter/mozwer/moz.build17
-rw-r--r--toolkit/crashreporter/mozwer/mozwer.cpp20
-rw-r--r--toolkit/crashreporter/mozwer/mozwer.def5
-rw-r--r--toolkit/crashreporter/nsDummyExceptionHandler.cpp263
-rw-r--r--toolkit/crashreporter/nsExceptionHandler.cpp3864
-rw-r--r--toolkit/crashreporter/nsExceptionHandler.h342
-rw-r--r--toolkit/crashreporter/nsExceptionHandlerUtils.cpp51
-rw-r--r--toolkit/crashreporter/nsExceptionHandlerUtils.h12
-rw-r--r--toolkit/crashreporter/rust_minidump_writer_linux/Cargo.toml15
-rw-r--r--toolkit/crashreporter/rust_minidump_writer_linux/cbindgen.toml15
-rw-r--r--toolkit/crashreporter/rust_minidump_writer_linux/moz.build17
-rw-r--r--toolkit/crashreporter/rust_minidump_writer_linux/src/lib.rs132
-rw-r--r--toolkit/crashreporter/test/CrashTestUtils.sys.mjs100
-rw-r--r--toolkit/crashreporter/test/ExceptionThrower.cpp3
-rw-r--r--toolkit/crashreporter/test/ExceptionThrower.h1
-rw-r--r--toolkit/crashreporter/test/browser/browser.ini15
-rw-r--r--toolkit/crashreporter/test/browser/browser_aboutCrashes.js82
-rw-r--r--toolkit/crashreporter/test/browser/browser_aboutCrashesResubmit.js202
-rw-r--r--toolkit/crashreporter/test/browser/browser_bug471404.js61
-rw-r--r--toolkit/crashreporter/test/browser/browser_clearReports.js134
-rw-r--r--toolkit/crashreporter/test/browser/browser_cpu_microcode.js25
-rw-r--r--toolkit/crashreporter/test/browser/browser_sandbox_crash.js77
-rw-r--r--toolkit/crashreporter/test/browser/crashreport.sjs176
-rw-r--r--toolkit/crashreporter/test/browser/head.js163
-rw-r--r--toolkit/crashreporter/test/dumputils.cpp83
-rw-r--r--toolkit/crashreporter/test/moz.build67
-rw-r--r--toolkit/crashreporter/test/nsTestCrasher.cpp364
-rw-r--r--toolkit/crashreporter/test/unit/crasher_subprocess_head.js29
-rw-r--r--toolkit/crashreporter/test/unit/crasher_subprocess_tail.js20
-rw-r--r--toolkit/crashreporter/test/unit/head_crashreporter.js347
-rw-r--r--toolkit/crashreporter/test/unit/head_win64cfi.js215
-rw-r--r--toolkit/crashreporter/test/unit/test_crash_AsyncShutdown.js75
-rw-r--r--toolkit/crashreporter/test/unit/test_crash_abort.js17
-rw-r--r--toolkit/crashreporter/test/unit/test_crash_after_js_large_allocation_failure.js23
-rw-r--r--toolkit/crashreporter/test/unit/test_crash_after_js_large_allocation_failure_reporting.js27
-rw-r--r--toolkit/crashreporter/test/unit/test_crash_after_js_oom_recovered.js22
-rw-r--r--toolkit/crashreporter/test/unit/test_crash_after_js_oom_reported.js36
-rw-r--r--toolkit/crashreporter/test/unit/test_crash_after_js_oom_reported_2.js28
-rw-r--r--toolkit/crashreporter/test/unit/test_crash_backgroundtask_moz_crash.js25
-rw-r--r--toolkit/crashreporter/test/unit/test_crash_exc_guard.js30
-rw-r--r--toolkit/crashreporter/test/unit/test_crash_heap_corruption.js27
-rw-r--r--toolkit/crashreporter/test/unit/test_crash_modules.js44
-rw-r--r--toolkit/crashreporter/test/unit/test_crash_moz_crash.js17
-rw-r--r--toolkit/crashreporter/test/unit/test_crash_oom.js21
-rw-r--r--toolkit/crashreporter/test/unit/test_crash_phc.js59
-rw-r--r--toolkit/crashreporter/test/unit/test_crash_purevirtual.js29
-rw-r--r--toolkit/crashreporter/test/unit/test_crash_rust_panic.js15
-rw-r--r--toolkit/crashreporter/test/unit/test_crash_rust_panic_multiline.js15
-rw-r--r--toolkit/crashreporter/test/unit/test_crash_stack_overflow.js21
-rw-r--r--toolkit/crashreporter/test/unit/test_crash_terminator.js39
-rw-r--r--toolkit/crashreporter/test/unit/test_crash_uncaught_exception.js17
-rw-r--r--toolkit/crashreporter/test/unit/test_crash_win64cfi_alloc_large.js6
-rw-r--r--toolkit/crashreporter/test/unit/test_crash_win64cfi_alloc_small.js6
-rw-r--r--toolkit/crashreporter/test/unit/test_crash_win64cfi_epilog.js6
-rw-r--r--toolkit/crashreporter/test/unit/test_crash_win64cfi_infinite_code_chain.exebin0 -> 1440 bytes
-rw-r--r--toolkit/crashreporter/test/unit/test_crash_win64cfi_infinite_code_chain.js22
-rw-r--r--toolkit/crashreporter/test/unit/test_crash_win64cfi_infinite_entry_chain.exebin0 -> 1440 bytes
-rw-r--r--toolkit/crashreporter/test/unit/test_crash_win64cfi_infinite_entry_chain.js22
-rw-r--r--toolkit/crashreporter/test/unit/test_crash_win64cfi_invalid_exception_rva.exebin0 -> 1440 bytes
-rw-r--r--toolkit/crashreporter/test/unit/test_crash_win64cfi_invalid_exception_rva.js21
-rw-r--r--toolkit/crashreporter/test/unit/test_crash_win64cfi_not_a_pe.exe1
-rw-r--r--toolkit/crashreporter/test/unit/test_crash_win64cfi_not_a_pe.js20
-rw-r--r--toolkit/crashreporter/test/unit/test_crash_win64cfi_push_nonvol.js6
-rw-r--r--toolkit/crashreporter/test/unit/test_crash_win64cfi_save_nonvol.js6
-rw-r--r--toolkit/crashreporter/test/unit/test_crash_win64cfi_save_nonvol_far.js6
-rw-r--r--toolkit/crashreporter/test/unit/test_crash_win64cfi_save_xmm128.js6
-rw-r--r--toolkit/crashreporter/test/unit/test_crash_win64cfi_save_xmm128_far.js6
-rw-r--r--toolkit/crashreporter/test/unit/test_crash_win64cfi_unknown_op.js12
-rw-r--r--toolkit/crashreporter/test/unit/test_crash_with_memory_report.js49
-rw-r--r--toolkit/crashreporter/test/unit/test_crashreporter.js90
-rw-r--r--toolkit/crashreporter/test/unit/test_crashreporter_appmem.js13
-rw-r--r--toolkit/crashreporter/test/unit/test_crashreporter_crash.js223
-rw-r--r--toolkit/crashreporter/test/unit/test_event_files.js56
-rw-r--r--toolkit/crashreporter/test/unit/test_kill.js43
-rw-r--r--toolkit/crashreporter/test/unit/test_oom_annotation.js71
-rw-r--r--toolkit/crashreporter/test/unit/test_override_exception_handler.js11
-rw-r--r--toolkit/crashreporter/test/unit/xpcshell-phc.ini11
-rw-r--r--toolkit/crashreporter/test/unit/xpcshell.ini131
-rw-r--r--toolkit/crashreporter/test/unit_ipc/test_content_annotation.js33
-rw-r--r--toolkit/crashreporter/test/unit_ipc/test_content_exception_time_annotation.js21
-rw-r--r--toolkit/crashreporter/test/unit_ipc/test_content_large_annotation.js25
-rw-r--r--toolkit/crashreporter/test/unit_ipc/test_content_memory_list.js33
-rw-r--r--toolkit/crashreporter/test/unit_ipc/test_content_oom_annotation.js33
-rw-r--r--toolkit/crashreporter/test/unit_ipc/test_content_phc.js31
-rw-r--r--toolkit/crashreporter/test/unit_ipc/test_content_phc2.js34
-rw-r--r--toolkit/crashreporter/test/unit_ipc/test_content_phc3.js35
-rw-r--r--toolkit/crashreporter/test/unit_ipc/test_content_rust_panic.js23
-rw-r--r--toolkit/crashreporter/test/unit_ipc/test_content_rust_panic_multiline.js23
-rw-r--r--toolkit/crashreporter/test/unit_ipc/xpcshell-phc.ini11
-rw-r--r--toolkit/crashreporter/test/unit_ipc/xpcshell.ini17
-rw-r--r--toolkit/crashreporter/test/win64UnwindInfoTests.asm378
-rw-r--r--toolkit/crashreporter/tools/python.ini3
-rwxr-xr-xtoolkit/crashreporter/tools/symbolstore.py1096
-rwxr-xr-xtoolkit/crashreporter/tools/unit-symbolstore.py613
-rw-r--r--toolkit/crashreporter/tools/upload_symbols.py306
-rwxr-xr-xtoolkit/crashreporter/update-breakpad.sh72
893 files changed, 292073 insertions, 0 deletions
diff --git a/toolkit/crashreporter/CrashAnnotations.cpp b/toolkit/crashreporter/CrashAnnotations.cpp
new file mode 100644
index 0000000000..54c3ad1610
--- /dev/null
+++ b/toolkit/crashreporter/CrashAnnotations.cpp
@@ -0,0 +1,38 @@
+/* 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 "CrashAnnotations.h"
+
+#include <algorithm>
+#include <cstring>
+#include <iterator>
+
+using std::begin;
+using std::end;
+using std::find_if;
+
+namespace CrashReporter {
+
+bool AnnotationFromString(Annotation& aResult, const char* aValue) {
+ auto elem = find_if(
+ begin(kAnnotationStrings), end(kAnnotationStrings),
+ [&aValue](const char* aString) { return strcmp(aString, aValue) == 0; });
+
+ if (elem == end(kAnnotationStrings)) {
+ return false;
+ }
+
+ aResult = static_cast<Annotation>(elem - begin(kAnnotationStrings));
+ return true;
+}
+
+bool IsAnnotationAllowlistedForPing(Annotation aAnnotation) {
+ auto elem = find_if(
+ begin(kCrashPingAllowlist), end(kCrashPingAllowlist),
+ [&aAnnotation](Annotation aElement) { return aElement == aAnnotation; });
+
+ return elem != end(kCrashPingAllowlist);
+}
+
+} // namespace CrashReporter
diff --git a/toolkit/crashreporter/CrashAnnotations.h.in b/toolkit/crashreporter/CrashAnnotations.h.in
new file mode 100644
index 0000000000..c87ad4a2ea
--- /dev/null
+++ b/toolkit/crashreporter/CrashAnnotations.h.in
@@ -0,0 +1,71 @@
+/* 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/. */
+
+#ifndef CrashAnnotations_h
+#define CrashAnnotations_h
+
+#include <cstddef>
+#include <cstdint>
+
+namespace CrashReporter {
+
+// Typed enum representing all crash annotations
+enum class Annotation : uint32_t {
+${enum}
+};
+
+// Stringified crash annotation names
+const char* const kAnnotationStrings[] = {
+${strings}
+};
+
+// Allowlist of crash annotations that can be included in a crash ping
+const Annotation kCrashPingAllowlist[] = {
+${allowlist}
+};
+
+/**
+ * Return the string representation of a crash annotation.
+ *
+ * @param aAnnotation a crash annotation
+ * @returns A constant string holding the annotation name
+ */
+static inline const char* AnnotationToString(Annotation aAnnotation) {
+ return kAnnotationStrings[static_cast<uint32_t>(aAnnotation)];
+}
+
+/**
+ * Converts a string to its corresponding crash annotation.
+ *
+ * @param aResult a reference where the annotation will be stored
+ * @param aValue the string to be converted
+ * @return true if the string was successfully converted, false if it did not
+ * correspond to any known annotation
+ */
+bool AnnotationFromString(Annotation& aResult, const char* aValue);
+
+/**
+ * Checks if the given crash annotation is allowlisted for inclusion in the
+ * crash ping.
+ *
+ * @param aAnnotation the crash annotation to be checked
+ * @return true if the annotation can be included in the crash ping, false
+ * otherwise
+ */
+bool IsAnnotationAllowlistedForPing(Annotation aAnnotation);
+
+/**
+ * Abstract annotation writer, this is needed only for code that writes out
+ * annotations in the exception handler.
+ */
+class AnnotationWriter {
+ public:
+ virtual void Write(Annotation aAnnotation, const char* aValue,
+ size_t aLen = 0) = 0;
+ virtual void Write(Annotation aAnnotation, uint64_t aValue) = 0;
+};
+
+} // namespace CrashReporter
+
+#endif // CrashAnnotations_h
diff --git a/toolkit/crashreporter/CrashAnnotations.yaml b/toolkit/crashreporter/CrashAnnotations.yaml
new file mode 100644
index 0000000000..36e4e4192f
--- /dev/null
+++ b/toolkit/crashreporter/CrashAnnotations.yaml
@@ -0,0 +1,978 @@
+# This lists all the available crash annotations.
+#
+# Mandatory fields for each entry are:
+# - description: A string describing the annotation
+# - type: the annotation type, currently `string`, `integer` or `boolean`.
+# The latter are stringified to `1` for true and `0` for false.
+#
+# Additionally a field can have the following optional fields:
+# - altname: A string that will be used when writing out the annotation to the
+# .extra file instead of the annotation name
+# - ping: A boolean that indicates whether the annotation is allowlisted for
+# going into the crash ping, if not specified this defaults to false
+
+AbortMessage:
+ description: >
+ Message passed to NS_DebugBreak().
+ type: string
+
+Accessibility:
+ description: >
+ Set to "Active" by the accessibility service when it is active.
+ type: string
+
+AccessibilityClient:
+ description: >
+ Accessibility client ID.
+ type: string
+
+AccessibilityInProcClient:
+ description: >
+ Hexadecimal mask of in-process accessibility consumers, see
+ accessible/windows/msaa/Compatibility.h for the mappings.
+ type: string
+
+AdapterDeviceID:
+ description: >
+ Graphics adapter name.
+ type: string
+
+AdapterDriverVendor:
+ description: >
+ Graphics adapter driver vendor.
+ type: string
+
+AdapterDriverVersion:
+ description: >
+ Graphics adapter driver version.
+ type: string
+
+AdapterSubsysID:
+ description: >
+ Graphics adapter subsystem ID.
+ type: string
+
+AdapterVendorID:
+ description: >
+ Graphics adapter vendor name.
+ type: string
+
+additional_minidumps:
+ description: >
+ Comma separated list of additional minidumps for this crash, each element
+ in the list represent the suffix used in the dump filename. E.g. the
+ "browser" entry for crash fa909194-737b-4b93-b8da-da110ac785e0 implies the
+ existence of the fa909194-737b-4b93-b8da-da110ac785e0-browser.dmp file.
+ type: string
+
+Addons:
+ description: >
+ List of currently enabled add-ons.
+ type: string
+ altname: Add-ons
+
+AppInitDLLs:
+ description: >
+ List of DLLs loaded when launching any application on Windows, this
+ reflects the contents of the AppInit_DLLs registry key.
+ type: string
+
+ApplicationBuildID:
+ description: >
+ Product application's build ID.
+ type: string
+
+AsyncShutdownTimeout:
+ description: >
+ This annotation is present if a shutdown blocker was not released in time
+ and the browser was crashed instead of waiting for shutdown to finish. The
+ condition that caused the hang is contained in the annotation.
+ type: string
+ ping: true
+
+AvailablePageFile:
+ description: >
+ Available commit-space in bytes.
+ - Under Windows, computed from the PERFORMANCE_INFORMATION structure by substracting
+ the CommitTotal field from the CommitLimit field.
+ - Under Linux, computed from /proc/meminfo's CommitLimit - Committed_AS. Note that
+ the kernel is not guaranteed to enforce that CommittedLimit >= Committed_AS. If
+ Committed_AS > CommittedLimit, this value is set to 0.
+ - Not available on other platforms.
+ type: string
+ ping: true
+
+AvailablePhysicalMemory:
+ description: >
+ Amount of free physical memory in bytes.
+ - Under Windows, populated with the contents of the MEMORYSTATUSEX's structure
+ ullAvailPhys field.
+ - Under macOS, populated with vm_statistics64_data_t::free_count.
+ - Under Linux, populated with /proc/meminfo's MemFree.
+ - Not available on other platforms.
+ type: string
+ ping: true
+
+AvailableSwapMemory:
+ description: >
+ Amount of free swap space in bytes.
+ - Under macOS, populated with the contents of
+ sysctl "vm.swapusage" :: xsu_avail.
+ - Under Linux, populated with /proc/meminfo's SwapFree.
+ - Not available on other platforms.
+ type: string
+ ping: true
+
+AvailableVirtualMemory:
+ description: >
+ Amount of free virtual memory in bytes
+ - Under Windows, populated with the contents of the MEMORYSTATUSEX's structure ullAvailVirtual field.
+ - Under Linux, populated with /proc/meminfo's MemAvailable.
+ - Not available on other platforms.
+ - For macOS, see AvailableSwapMemory, AvailablePhysicalMemory and PurgeablePhysicalMemory.
+ type: string
+ ping: true
+
+BackgroundTaskMode:
+ description: >
+ True if the app was invoked in background task mode via `--backgroundtask ...`, false otherwise.
+ type: boolean
+
+BackgroundTaskName:
+ description: >
+ If the app was invoked in background task mode via `--backgroundtask <task name>`, the string "task name".
+ type: string
+ ping: true
+
+BlockedDllList:
+ description: >
+ Comma-separated list of blocked DLLS, Windows-only
+ type: string
+ ping: true
+
+BlocklistInitFailed:
+ description: >
+ Set to 1 if the DLL blocklist could not be initialized.
+ type: boolean
+ ping: true
+
+Breadcrumbs:
+ description: >
+ Trail of events that occurred before a report. this will consist of multiple breadcrumbs with
+ timestamp, message, category, level, type and data in JSON format.
+ type: string
+
+BuildID:
+ description: >
+ Application build ID, the format is YYYYMMDDHHMMSS.
+ type: string
+ ping: true
+
+ClassRegistrationInfoChild:
+ description: >
+ Microsoft COM class registration annotation for the child process.
+ type: string
+
+ClassRegistrationInfoParent:
+ description: >
+ Microsoft COM class registration annotation for the parent process.
+ type: string
+
+ContentSandboxCapabilities:
+ description: >
+ List of capabilities of the content process sandbox.
+ type: string
+
+ContentSandboxEnabled:
+ description: >
+ Set to 1 when content process sandboxing is enabled.
+ type: boolean
+
+ContentSandboxCapable:
+ description: >
+ Set to 1 if the client is capable of content sandboxing.
+ type: boolean
+
+ContentSandboxLevel:
+ description: >
+ Content sandbox level.
+ type: integer
+
+ContentSandboxWin32kState:
+ description: >
+ Content sandbox Win32k state
+ type: string
+
+GpuSandboxLevel:
+ description: >
+ GPU sandbox level.
+ type: integer
+
+CPUMicrocodeVersion:
+ description: >
+ Version of the CPU microcode.
+ type: string
+
+CrashAddressLikelyWrong:
+ description: >
+ Set to 1 if signal handling is broken, in which case the crash address is
+ likely to be wrong.
+ type: boolean
+
+CrashTime:
+ description: >
+ Crash time in seconds since the Epoch.
+ type: string
+ ping: true
+
+CycleCollector:
+ description: >
+ Reason why the cycle collector crashed.
+ type: string
+
+DesktopEnvironment:
+ description: >
+ Desktop environment used on Linux, e.g. GNOME, KDE, XFCE, etc.
+ type: string
+
+DeviceResetReason:
+ description: >
+ Reason why a DirectX device has been reset, Windows only.
+ type: string
+
+DistributionID:
+ description: >
+ Product application's distribution ID.
+ type: string
+
+DOMFissionEnabled:
+ description: >
+ Set to 1 when DOM fission is enabled, and subframes are potentially loaded
+ in a separate process.
+ type: boolean
+ ping: true
+
+DOMIPCEnabled:
+ description: >
+ Set to 1 when a tab is running in a content process
+ type: boolean
+
+DumperError:
+ description: >
+ Error message of the minidump writer, in case there was an error during dumping.
+ type: string
+
+EMCheckCompatibility:
+ description: >
+ Set to 1 if add-on compatibility checking is enabled.
+ type: boolean
+
+EventLoopNestingLevel:
+ description: >
+ Present only if higher than 0, indicates that we're running in a nested
+ event loop and indicates the nesting level.
+ type: integer
+ ping: true
+
+ExperimentalFeatures:
+ description: >
+ Comma-separated list of enabled experimental features from about:preferences#experimental.
+ type: string
+ ping: true
+
+FontName:
+ description: >
+ Set before attempting to load a font to help diagnose crashes during loading.
+ type: string
+ ping: true
+
+GMPLibraryPath:
+ description: >
+ Holds the path to the GMP plugin library.
+ type: string
+
+GMPPlugin:
+ description: >
+ Set to 1 if the GMP plugin is enabled.
+ type: boolean
+
+GPUProcessLaunchCount:
+ description: >
+ Number of times the GPU process was launched.
+ type: integer
+ ping: true
+
+GPUProcessStatus:
+ description: >
+ Status of the GPU process, can be set to "Running" or "Destroyed"
+ type: string
+
+GraphicsCompileShader:
+ description: >
+ Name of the shader we are in the process of compiling, if applicable. See
+ file names in gfx/wr/webrender/res/* for the possible values.
+ type: string
+
+GraphicsCriticalError:
+ description: >
+ Information of a critical error that occurred within the graphics code.
+ type: string
+
+GraphicsDrawShader:
+ description: >
+ Name of the shader that is currently bound for a draw call, if applicable.
+ See file names in gfx/wr/webrender/res/* for the possible values.
+ type: string
+
+GraphicsNumActiveRenderers:
+ description: >
+ Number of webrender renderer instances that are not in a paused state.
+ type: integer
+
+GraphicsNumRenderers:
+ description: >
+ Total number of webrender renderer instances.
+ type: integer
+
+GraphicsStartupTest:
+ description: >
+ Set to 1 by the graphics driver crash guard when it's activated.
+ type: boolean
+
+HeadlessMode:
+ description: >
+ True if the app was invoked in headless mode via `--headless ...` or `--backgroundtask ...`, false otherwise.
+ type: boolean
+ ping: true
+
+PHCKind:
+ description: >
+ The allocation kind, if the crash involved a bad access of a special PHC
+ allocation.
+ type: string
+
+PHCBaseAddress:
+ description: >
+ The allocation's base address, if the crash involved a bad access of a
+ special PHC allocation. Encoded as a decimal address.
+ type: string
+
+PHCUsableSize:
+ description: >
+ The allocation's usable size, if the crash involved a bad access of a
+ special PHC allocation.
+ # A 32-bit integer is enough because the maximum usable size of a special PHC
+ # allocation is far less than 2 GiB.
+ type: integer
+
+PHCAllocStack:
+ description: >
+ The allocation's allocation stack trace, if the crash involved a bad access
+ of a special PHC allocation. Encoded as a comma-separated list of decimal
+ addresses.
+ type: string
+
+PHCFreeStack:
+ description: >
+ The allocation's free stack trace, if the crash involved a bad access
+ of a special PHC allocation. Encoded as a comma-separated list of decimal
+ addresses.
+ type: string
+
+HasDeviceTouchScreen:
+ description: >
+ Set to 1 if the device had a touch-screen, this only applies to Firefox
+ desktop as on mobile devices we assume a touch-screen is always present.
+ type: boolean
+
+IAccessibleConfig:
+ description: >
+ Set when something is seriously wrong with the IAccessible configuration in
+ the computer's registry. The value is always set to "NoSystemTypeLibOrPS"
+ type: string
+
+InstallTime:
+ description: >
+ The time when Firefox was installed expressed as seconds since the Epoch
+ type: integer
+
+ipc_channel_error:
+ description: >
+ Set before a content process crashes because of an IPC channel error, holds
+ a description of the error.
+ type: string
+ ping: true
+
+IpcCreateEndpointsNsresult:
+ description: >
+ errno value retrieved after failing to create an IPC transport object.
+ type: integer
+
+IpcCreatePipeCloExecErrno:
+ description: >
+ errno value retrieved after failing to set the O_CLOEXEC flag on a pipe
+ used for IPC.
+ type: integer
+
+IpcCreatePipeFcntlErrno:
+ description: >
+ errno value retrieved after a call to fcntl() on a pipe used for IPC failed.
+ type: integer
+
+IpcCreatePipeSocketPairErrno:
+ description: >
+ errno value retrieved after a socketpair() call failed while creating an IPC
+ transport object.
+ type: integer
+
+IpcCreateTransportDupErrno:
+ description: >
+ errno value retrieved after a dup() call failed while creating an IPC
+ transport object.
+ type: integer
+
+IPCFatalErrorMsg:
+ description: >
+ Describes a fatal error that occurred during IPC operation.
+ type: string
+
+IPCFatalErrorProtocol:
+ description: >
+ Name of the protocol used by IPC when a fatal error occurred.
+ type: string
+
+IPCMessageName:
+ description: >
+ Name of the IPC message that caused a crash because it was too large.
+ type: string
+
+IPCMessageSize:
+ description: >
+ Size of the IPC message that caused a crash because it was too large.
+ type: integer
+
+IPCReadErrorReason:
+ description: >
+ Reason why reading an object via IPC failed.
+ type: string
+
+IPCShutdownState:
+ description: >
+ IPC shutdown state, can be set to either "RecvShutdown" or
+ "SendFinishShutdown" by a content process while it's shutting down.
+ type: string
+
+IPCSystemError:
+ description: >
+ Description of the last system error that occurred during IPC operation.
+ type: string
+
+IPCTransportFailureReason:
+ description: >
+ Reason why creating an IPC channel failed.
+ type: string
+
+IsGarbageCollecting:
+ description: >
+ If true then the JavaScript garbage collector was running when the crash
+ occurred.
+ type: boolean
+ ping: true
+
+IsWayland:
+ description: >
+ If true then the Wayland windowing system was in use.
+ type: boolean
+
+IsWebRenderResourcePathOverridden:
+ description: >
+ If true then the WebRender resources (i.e. shaders) are loaded from a user specified path.
+ type: boolean
+
+JavaException:
+ description: >
+ JSON structured Java stack trace, only present on Firefox for Android if we encounter an
+ uncaught Java exception.
+ type: string
+
+JavaStackTrace:
+ description: >
+ Java stack trace, only present on Firefox for Android if we encounter an
+ uncaught Java exception.
+ type: string
+
+JSActorMessage:
+ description: >
+ If an actor is currently treating a message, this is the name of the message.
+ Otherwise, empty.
+ type: string
+
+JSActorName:
+ description: >
+ If an actor is currently treating a message, this is the name of the actor.
+ Otherwise, empty.
+ type: string
+
+JSLargeAllocationFailure:
+ description: >
+ A large allocation couldn't be satisfied, check the JSOutOfMemory
+ description for the possible values of this annotation.
+ type: string
+
+JSModuleLoadError:
+ description: >
+ The error raised when attempting to import a critical JS module from C++
+ type: string
+
+JSOutOfMemory:
+ description: >
+ A small allocation couldn't be satisfied, the annotation may contain the
+ "Reporting", "Reported" or "Recovered" value. The first one means that
+ we crashed while responding to the OOM condition (possibly while running a
+ memory-pressure observers), the second that we crashed after having tried to
+ free some memory, and the last that the GC had managed to free enough memory
+ to satisfy the allocation.
+ type: string
+
+
+LastInteractionDuration:
+ description: >
+ How long the user had been inactive in seconds if the user was inactive
+ at crash. The value is not set if the user state was active.
+ type: integer
+ ping: true
+
+LastStartupWasCrash:
+ description: >
+ True if the last startup was detected to have been a crash.
+ type: boolean
+
+MacMemoryPressure:
+ description: >
+ The current memory pressure state as provided by the macOS memory pressure
+ dispatch source. The annotation value is one of "Normal" for no memory
+ pressure, "Unset" indicating a memory pressure event has not been received,
+ "Warning" or "Critical" mapping to the system memory pressure levels,
+ or "Unexpected" for an unexpected level. This is a Mac-specific annotation.
+ type: string
+
+MacMemoryPressureNormalTime:
+ description: >
+ The time when the memory pressure state last transitioned to 'Normal'
+ expressed as seconds since the Epoch.
+ type: string
+
+MacMemoryPressureWarningTime:
+ description: >
+ The time when the memory pressure state last transitioned to 'Warning'
+ expressed as seconds since the Epoch.
+ type: string
+
+MacMemoryPressureCriticalTime:
+ description: >
+ The time when the memory pressure state last transitioned to 'Critical'
+ expressed as seconds since the Epoch.
+ type: string
+
+MacMemoryPressureSysctl:
+ description: >
+ The value of the memory pressure sysctl
+ 'kern.memorystatus_vm_pressure_level'. Indicates which memory
+ pressure level the system is in at the time of the crash. The expected
+ values are one of 4 (Critical), 2 (Warning), or 1 (Normal).
+ type: integer
+
+MacAvailableMemorySysctl:
+ description: >
+ The value of the available memory sysctl 'kern.memorystatus_level'.
+ Expected to be a percentage integer value.
+ type: integer
+
+LinuxUnderMemoryPressure:
+ description: >
+ Set to true if the memory pressure watcher was under memory pressure when
+ the crash occurred.
+ type: boolean
+
+LauncherProcessState:
+ description: >
+ Launcher process enabled state. The integer value of this annotation must
+ match with one of the values in the
+ mozilla::LauncherRegistryInfo::EnableState enum
+ type: integer
+
+LowPhysicalMemoryEvents:
+ description: >
+ Number of times the available memory tracker has detected that free
+ physical memory is running low. This is a Windows-specific annotation.
+ type: integer
+ ping: true
+
+MainThreadRunnableName:
+ description: >
+ Name of the currently executing nsIRunnable on the main thread.
+ type: string
+ ping: true
+
+MozCrashReason:
+ description: >
+ Plaintext description of why Firefox crashed, this is usually set by
+ assertions and the like.
+ type: string
+ ping: true
+
+Notes:
+ description: >
+ Miscellaneous notes that can be appended to a crash.
+ type: string
+
+OOMAllocationSize:
+ description: >
+ Size of the allocation that caused an out-of-memory condition.
+ type: string
+ ping: true
+
+PluginFilename:
+ description: >
+ Plugin filename, only the process holding the plugin has this annotation.
+ type: string
+
+PluginName:
+ description: >
+ Display name of a plugin, only the process holding the plugin has this
+ annotation.
+ type: string
+
+PluginVersion:
+ description: >
+ Version of a plugin, only the process holding the plugin has this
+ annotation.
+ type: string
+
+ProcessType:
+ description: >
+ Type of the process that crashed, the possible values are defined in
+ GeckoProcessTypes.h.
+ type: string
+
+ProductName:
+ description: >
+ Application name (e.g. Firefox).
+ type: string
+ ping: true
+
+ProductID:
+ description: >
+ Application UUID (e.g. ec8030f7-c20a-464f-9b0e-13a3a9e97384).
+ type: string
+ ping: true
+
+ProfilerChildShutdownPhase:
+ description: >
+ When a child process shuts down, this describes if the profiler is running,
+ and the point the profiler shutdown sequence has reached.
+ type: string
+ ping: true
+
+PurgeablePhysicalMemory:
+ description: >
+ macOS only. Amount of physical memory currently allocated but which may
+ be deallocated by the system in case of memory pressure. Populated from
+ vm_statistics64_data_t::purgeable_count * vm_page_size.
+ type: string
+ ping: true
+
+QuotaManagerShutdownTimeout:
+ description: >
+ This annotation is present if the quota manager shutdown (resp. the shutdown
+ of the quota manager clients) was not finished in time and the browser was
+ crashed instead of waiting for the shutdown to finish. The status of objects
+ which were blocking completion of the shutdown when reaching the timeout
+ is contained in the annotation.
+
+ In the case of IndexedDB, objects are divided into three groups:
+ FactoryOperations, LiveDatabases and DatabaseMaintenances.
+
+ In the case of LocalStorage, objects are divided into three groups:
+ PrepareDatastoreOperations, Datastores and LiveDatabases.
+
+ In the case of Cache API, objects are in one group only:
+ Managers.
+
+ Each group is reported separately and contains the number of objects in the
+ group and the status of individual objects in the group (duplicate entries
+ are removed):
+ "GroupName: N (objectStatus1, objectStatus2, ...)" where N is the number of
+ objects in the group.
+
+ The status of individual objects is constructed by taking selected object
+ properties. Properties which contain origin strings are anonymized.
+
+ In addition, intermediate steps are recorded for change events after shutdown
+ started. These include the time difference and the type of object.
+ type: string
+ ping: true
+
+RDDProcessStatus:
+ description: >
+ Status of the RDD process, can be set to "Running" or "Destroyed"
+ type: string
+
+ReleaseChannel:
+ description: >
+ Application release channel (e.g. default, beta, ...)
+ type: string
+ ping: true
+
+RemoteType:
+ description: >
+ Type of the content process, can be set to "web", "file" or "extension".
+ type: string
+ ping: true
+
+SafeMode:
+ description: >
+ Set to 1 if the browser was started in safe mode.
+ type: boolean
+
+SecondsSinceLastCrash:
+ description: >
+ Time in seconds since the last crash occurred.
+ type: string
+ ping: true
+
+ServerURL:
+ description: >
+ URL used to post the crash report.
+ type: string
+
+ShutdownProgress:
+ description: >
+ Shutdown step at which the browser crashed, can be set to "quit-application",
+ "profile-change-teardown", "profile-before-change", "xpcom-will-shutdown" or
+ "xpcom-shutdown".
+ type: string
+ ping: true
+
+ShutdownReason:
+ description: >
+ One out of "Unknown", "AppClose", "AppRestart", "OSForceClose",
+ "OSSessionEnd", "OSShutdown" or "WinUnexpectedMozQuit".
+ type: string
+ ping: true
+
+StartupCacheValid:
+ description: >
+ True if the startup cache was deemed valid and usable. Will be false if the
+ last session used a different browser version or had a startup cache.
+ type: boolean
+
+StartupCrash:
+ description: >
+ If set to 1 then this crash occurred during startup.
+ type: boolean
+ ping: true
+
+StartupTime:
+ description: >
+ The time when Firefox was launched expressed in seconds since the Epoch.
+ type: integer
+
+StorageConnectionNotClosed:
+ description: >
+ This annotation is added when a mozStorage connection has not been properly
+ closed during shutdown. The annotation holds the filename of the database
+ associated with the connection.
+ type: string
+
+SubmittedFrom:
+ description: >
+ This annotation can hold one of the following five values depending on how
+ this crash was submitted by the user:
+ * Auto: the user had opted-in to auto-submission
+ * Infobar: the user clicked on the infobar to submit the crash
+ * AboutCrashes: the user sent the crash from the about:crashes page
+ * CrashedTab: the user sent the crash from a crashed tab page
+ * Client: the user sent the crash using the crash reporter client
+ type: string
+
+SystemMemoryUsePercentage:
+ description: >
+ Windows-only, percentage of physical memory in use. This annotation is
+ populated with the contents of the MEMORYSTATUSEX's structure dwMemoryLoad
+ field.
+ type: integer
+ ping: true
+
+TelemetryClientId:
+ description: >
+ Telemetry client ID.
+ type: string
+
+TelemetryEnvironment:
+ description: >
+ The telemetry environment in JSON format.
+ type: string
+
+TelemetryServerURL:
+ description: >
+ Telemetry server URL. Used to send main process crash pings directly from
+ the crashreporter client.
+ type: string
+
+TelemetrySessionId:
+ description: >
+ Telemetry session ID.
+ type: string
+
+TestKey:
+ description: >
+ Annotation used in tests.
+ type: string
+
+TestUnicode:
+ description: >
+ Annotation used in tests.
+ type: string
+
+TextureUsage:
+ description: >
+ Amount of memory in bytes consumed by textures.
+ type: string
+ ping: true
+
+Throttleable:
+ description: >
+ Whether Socorro can selectively discard this crash report or not. If set
+ to "0" the crash report will always be processed by Socorro. Do not set
+ this annotation within Gecko code, it's only supposed to be used by the
+ crash reporting machinery.
+ type: boolean
+
+TotalPageFile:
+ description: >
+ Maximum amount of memory that can be committed without extending the swap/page file.
+ - Under Windows, populated with the contents of the PERFORMANCE_INFORMATION's
+ structure CommitLimit field.
+ - Under Linux, populated with /proc/meminfo MemTotal + SwapTotal. The swap file
+ typically cannot be extended, so that's a hard limit.
+ - Not available on other systems.
+ type: string
+ ping: true
+
+TotalPhysicalMemory:
+ description: >
+ Amount of physical memory in bytes.
+ - Under Windows, populated with the contents of the MEMORYSTATUSEX's structure
+ ullTotalPhys field.
+ - Under macOS, populated with sysctl "hw.memsize".
+ - Under Linux, populated with /proc/meminfo's "MemTotal".
+ - Not available on other systems.
+ type: string
+ ping: true
+
+TotalVirtualMemory:
+ description: >
+ Size of the virtual address space.
+ - Under Windows, populated with the contents of the MEMORYSTATUSEX's structure
+ ullTotalVirtual field.
+ - Not available on other platforms.
+ type: string
+ ping: true
+
+UnknownNetAddrSocketFamily:
+ description: >
+ An unknown network address family was requested to Necko. The value is the
+ requested family number.
+ type: integer
+
+UptimeTS:
+ description: >
+ Uptime in seconds. This annotation uses a string instead of an integer
+ because it has a fractional component.
+ type: string
+ ping: true
+
+URL:
+ description: >
+ URL being loaded.
+ type: string
+
+URLSegments:
+ description: >
+ The offsets of the nsStandardURL segments that fail a sanity check
+ type: string
+
+User32BeforeBlocklist:
+ description: >
+ Set to 1 if user32.dll was loaded before we could install the DLL blocklist.
+ type: boolean
+ ping: true
+
+useragent_locale:
+ description: >
+ User-agent locale.
+ type: string
+
+UtilityProcessStatus:
+ description: >
+ Status of the Utility process, can be set to "Running" or "Destroyed"
+ type: string
+
+UtilityActorsName:
+ description: >
+ Comma-separated list of IPC actors name running on this Utility process instance
+ type: string
+ ping: true
+
+Vendor:
+ description: >
+ Application vendor (e.g. Mozilla).
+ type: string
+
+Version:
+ description: >
+ Product version.
+ type: string
+
+VRProcessStatus:
+ description: >
+ Status of the VR process, can be set to "Running" or "Destroyed"
+ type: string
+
+WasmLibrarySandboxMallocFailed:
+ description: >
+ Set to 1 if a rlbox wasm library sandbox ran out of memory, causing a
+ malloc inside the sandbox to fail.
+ type: boolean
+
+WindowsPackageFamilyName:
+ description: >
+ If running in a Windows package context, the package family name, per
+ https://docs.microsoft.com/en-us/windows/win32/api/appmodel/nf-appmodel-getcurrentpackagefamilyname.
+
+ The package family name is only included when it is likely to have been produced by Mozilla: it
+ starts "Mozilla." or "MozillaCorporation.".
+ type: string
+ ping: true
+
+WindowsErrorReporting:
+ description: >
+ Set to 1 if this crash was intercepted via the Windows Error Reporting
+ runtime exception module.
+ type: boolean
+ ping: true
+
+Winsock_LSP:
+ description: >
+ Information on winsock LSPs injected in our networking stack.
+ type: string
+
+XPCOMSpinEventLoopStack:
+ description: >
+ If we crash while some code is spinning manually the event loop on the
+ main thread, we will see the stack of nested annotations here.
+ If the crashing process was killed (e.g. due to an IPC error), this
+ annotation may refer to the parent process that killed it, look out for
+ the prefix ("default" means parent) and see bug 1741131 for details.
+ type: string
diff --git a/toolkit/crashreporter/CrashReports.sys.mjs b/toolkit/crashreporter/CrashReports.sys.mjs
new file mode 100644
index 0000000000..3f66da1ec3
--- /dev/null
+++ b/toolkit/crashreporter/CrashReports.sys.mjs
@@ -0,0 +1,81 @@
+/* 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/. */
+
+export var CrashReports = {
+ pendingDir: null,
+ reportsDir: null,
+ submittedDir: null,
+ getReports: function CrashReports_getReports() {
+ let reports = [];
+
+ try {
+ // Ignore any non http/https urls
+ if (!/^https?:/i.test(Services.prefs.getCharPref("breakpad.reportURL"))) {
+ return reports;
+ }
+ } catch (e) {}
+
+ if (this.submittedDir.exists() && this.submittedDir.isDirectory()) {
+ let entries = this.submittedDir.directoryEntries;
+ while (entries.hasMoreElements()) {
+ let file = entries.nextFile;
+ let leaf = file.leafName;
+ if (leaf.startsWith("bp-") && leaf.endsWith(".txt")) {
+ let entry = {
+ id: leaf.slice(0, -4),
+ date: file.lastModifiedTime,
+ pending: false,
+ };
+ reports.push(entry);
+ }
+ }
+ }
+
+ if (this.pendingDir.exists() && this.pendingDir.isDirectory()) {
+ let uuidRegex =
+ /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
+ let entries = this.pendingDir.directoryEntries;
+ while (entries.hasMoreElements()) {
+ let file = entries.nextFile;
+ let leaf = file.leafName;
+ let id = leaf.slice(0, -4);
+ if (leaf.endsWith(".dmp") && uuidRegex.test(id)) {
+ let entry = {
+ id,
+ date: file.lastModifiedTime,
+ pending: true,
+ };
+ reports.push(entry);
+ }
+ }
+ }
+
+ // Sort reports descending by date
+ return reports.sort((a, b) => b.date - a.date);
+ },
+};
+
+function CrashReports_pendingDir() {
+ let pendingDir = Services.dirsvc.get("UAppData", Ci.nsIFile);
+ pendingDir.append("Crash Reports");
+ pendingDir.append("pending");
+ return pendingDir;
+}
+
+function CrashReports_reportsDir() {
+ let reportsDir = Services.dirsvc.get("UAppData", Ci.nsIFile);
+ reportsDir.append("Crash Reports");
+ return reportsDir;
+}
+
+function CrashReports_submittedDir() {
+ let submittedDir = Services.dirsvc.get("UAppData", Ci.nsIFile);
+ submittedDir.append("Crash Reports");
+ submittedDir.append("submitted");
+ return submittedDir;
+}
+
+CrashReports.pendingDir = CrashReports_pendingDir();
+CrashReports.reportsDir = CrashReports_reportsDir();
+CrashReports.submittedDir = CrashReports_submittedDir();
diff --git a/toolkit/crashreporter/CrashSubmit.sys.mjs b/toolkit/crashreporter/CrashSubmit.sys.mjs
new file mode 100644
index 0000000000..28647c5a83
--- /dev/null
+++ b/toolkit/crashreporter/CrashSubmit.sys.mjs
@@ -0,0 +1,666 @@
+/* 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/. */
+
+import { FileUtils } from "resource://gre/modules/FileUtils.sys.mjs";
+
+const SUCCESS = "success";
+const FAILED = "failed";
+const SUBMITTING = "submitting";
+
+const UUID_REGEX =
+ /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
+const SUBMISSION_REGEX =
+ /^bp-[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
+
+// TODO: this is still synchronous; need an async INI parser to make it async
+function parseINIStrings(path) {
+ let file = new FileUtils.File(path);
+ let factory = Cc["@mozilla.org/xpcom/ini-parser-factory;1"].getService(
+ Ci.nsIINIParserFactory
+ );
+ let parser = factory.createINIParser(file);
+ let obj = {};
+ for (let key of parser.getKeys("Strings")) {
+ obj[key] = parser.getString("Strings", key);
+ }
+ return obj;
+}
+
+// Since we're basically re-implementing (with async) part of the crashreporter
+// client here, we'll just steal the strings we need from crashreporter.ini
+async function getL10nStrings() {
+ let path = PathUtils.join(
+ Services.dirsvc.get("GreD", Ci.nsIFile).path,
+ "crashreporter.ini"
+ );
+ let pathExists = await IOUtils.exists(path);
+
+ if (!pathExists) {
+ // we if we're on a mac
+ let parentDir = PathUtils.parent(path);
+ path = PathUtils.join(
+ parentDir,
+ "MacOS",
+ "crashreporter.app",
+ "Contents",
+ "Resources",
+ "crashreporter.ini"
+ );
+
+ let pathExists = await IOUtils.exists(path);
+
+ if (!pathExists) {
+ // This happens on Android where everything is in an APK.
+ // Android users can't see the contents of the submitted files
+ // anyway, so just hardcode some fallback strings.
+ return {
+ crashid: "Crash ID: %s",
+ reporturl: "You can view details of this crash at %s",
+ };
+ }
+ }
+
+ let crstrings = parseINIStrings(path);
+ let strings = {
+ crashid: crstrings.CrashID,
+ reporturl: crstrings.CrashDetailsURL,
+ };
+
+ path = PathUtils.join(
+ Services.dirsvc.get("XCurProcD", Ci.nsIFile).path,
+ "crashreporter-override.ini"
+ );
+ pathExists = await IOUtils.exists(path);
+
+ if (pathExists) {
+ crstrings = parseINIStrings(path);
+
+ if ("CrashID" in crstrings) {
+ strings.crashid = crstrings.CrashID;
+ }
+
+ if ("CrashDetailsURL" in crstrings) {
+ strings.reporturl = crstrings.CrashDetailsURL;
+ }
+ }
+
+ return strings;
+}
+
+function getDir(name) {
+ let uAppDataPath = Services.dirsvc.get("UAppData", Ci.nsIFile).path;
+ return PathUtils.join(uAppDataPath, "Crash Reports", name);
+}
+
+async function writeFileAsync(dirName, fileName, data) {
+ let dirPath = getDir(dirName);
+ let filePath = PathUtils.join(dirPath, fileName);
+ await IOUtils.makeDirectory(dirPath, { permissions: 0o700 });
+ await IOUtils.writeUTF8(filePath, data);
+}
+
+function getPendingMinidump(id) {
+ let pendingDir = getDir("pending");
+
+ return [".dmp", ".extra", ".memory.json.gz"].map(suffix => {
+ return PathUtils.join(pendingDir, `${id}${suffix}`);
+ });
+}
+
+async function writeSubmittedReportAsync(crashID, viewURL) {
+ let strings = await getL10nStrings();
+ let data = strings.crashid.replace("%s", crashID);
+
+ if (viewURL) {
+ data += "\n" + strings.reporturl.replace("%s", viewURL);
+ }
+
+ await writeFileAsync("submitted", `${crashID}.txt`, data);
+}
+
+// the Submitter class represents an individual submission.
+function Submitter(id, recordSubmission, noThrottle, extraExtraKeyVals) {
+ this.id = id;
+ this.recordSubmission = recordSubmission;
+ this.noThrottle = noThrottle;
+ this.additionalDumps = [];
+ this.extraKeyVals = extraExtraKeyVals;
+ // mimic deferred Promise behavior
+ this.submitStatusPromise = new Promise((resolve, reject) => {
+ this.resolveSubmitStatusPromise = resolve;
+ this.rejectSubmitStatusPromise = reject;
+ });
+}
+
+Submitter.prototype = {
+ submitSuccess: async function Submitter_submitSuccess(ret) {
+ // Write out the details file to submitted
+ await writeSubmittedReportAsync(ret.CrashID, ret.ViewURL);
+
+ try {
+ let toDelete = [this.dump, this.extra];
+
+ if (this.memory) {
+ toDelete.push(this.memory);
+ }
+
+ for (let entry of this.additionalDumps) {
+ toDelete.push(entry.dump);
+ }
+
+ await Promise.all(
+ toDelete.map(path => {
+ return IOUtils.remove(path, { ignoreAbsent: true });
+ })
+ );
+ } catch (ex) {
+ console.error(ex);
+ }
+
+ this.notifyStatus(SUCCESS, ret);
+ this.cleanup();
+ },
+
+ cleanup: function Submitter_cleanup() {
+ // drop some references just to be nice
+ this.iframe = null;
+ this.dump = null;
+ this.extra = null;
+ this.memory = null;
+ this.additionalDumps = null;
+ // remove this object from the list of active submissions
+ let idx = CrashSubmit._activeSubmissions.indexOf(this);
+ if (idx != -1) {
+ CrashSubmit._activeSubmissions.splice(idx, 1);
+ }
+ },
+
+ parseResponse: function Submitter_parseResponse(response) {
+ let parsedResponse = {};
+
+ for (let line of response.split("\n")) {
+ let data = line.split("=");
+
+ if (
+ (data.length == 2 &&
+ data[0] == "CrashID" &&
+ SUBMISSION_REGEX.test(data[1])) ||
+ data[0] == "ViewURL"
+ ) {
+ parsedResponse[data[0]] = data[1];
+ }
+ }
+
+ return parsedResponse;
+ },
+
+ submitForm: function Submitter_submitForm() {
+ if (!("ServerURL" in this.extraKeyVals)) {
+ return false;
+ }
+ let serverURL = this.extraKeyVals.ServerURL;
+ delete this.extraKeyVals.ServerURL;
+
+ // Override the submission URL from the environment
+ let envOverride = Services.env.get("MOZ_CRASHREPORTER_URL");
+ if (envOverride != "") {
+ serverURL = envOverride;
+ }
+
+ let xhr = new XMLHttpRequest();
+ xhr.open("POST", serverURL, true);
+
+ let formData = new FormData();
+
+ // tell the server not to throttle this if requested
+ this.extraKeyVals.Throttleable = this.noThrottle ? "0" : "1";
+
+ // add the data
+ let payload = Object.assign({}, this.extraKeyVals);
+ let json = new Blob([JSON.stringify(payload)], {
+ type: "application/json",
+ });
+ formData.append("extra", json);
+
+ // add the minidumps
+ let promises = [
+ File.createFromFileName(this.dump, {
+ type: "application/octet-stream",
+ }).then(file => {
+ formData.append("upload_file_minidump", file);
+ }),
+ ];
+
+ if (this.memory) {
+ promises.push(
+ File.createFromFileName(this.memory, {
+ type: "application/gzip",
+ }).then(file => {
+ formData.append("memory_report", file);
+ })
+ );
+ }
+
+ if (this.additionalDumps.length) {
+ let names = [];
+ for (let i of this.additionalDumps) {
+ names.push(i.name);
+ promises.push(
+ File.createFromFileName(i.dump, {
+ type: "application/octet-stream",
+ }).then(file => {
+ formData.append("upload_file_minidump_" + i.name, file);
+ })
+ );
+ }
+ }
+
+ let manager = Services.crashmanager;
+ let submissionID = manager.generateSubmissionID();
+
+ xhr.addEventListener("readystatechange", evt => {
+ if (xhr.readyState == 4) {
+ let ret =
+ xhr.status === 200 ? this.parseResponse(xhr.responseText) : {};
+ let submitted = !!ret.CrashID;
+ let p = Promise.resolve();
+
+ if (this.recordSubmission) {
+ let result = submitted
+ ? manager.SUBMISSION_RESULT_OK
+ : manager.SUBMISSION_RESULT_FAILED;
+ p = manager.addSubmissionResult(
+ this.id,
+ submissionID,
+ new Date(),
+ result
+ );
+ if (submitted) {
+ manager.setRemoteCrashID(this.id, ret.CrashID);
+ }
+ }
+
+ p.then(() => {
+ if (submitted) {
+ this.submitSuccess(ret);
+ } else {
+ this.notifyStatus(FAILED);
+ this.cleanup();
+ }
+ });
+ }
+ });
+
+ let p = Promise.all(promises);
+ let id = this.id;
+
+ if (this.recordSubmission) {
+ p = p.then(() => {
+ return manager.addSubmissionAttempt(id, submissionID, new Date());
+ });
+ }
+ p.then(() => {
+ xhr.send(formData);
+ });
+ return true;
+ },
+
+ notifyStatus: function Submitter_notify(status, ret) {
+ let propBag = Cc["@mozilla.org/hash-property-bag;1"].createInstance(
+ Ci.nsIWritablePropertyBag2
+ );
+ propBag.setPropertyAsAString("minidumpID", this.id);
+ if (status == SUCCESS) {
+ propBag.setPropertyAsAString("serverCrashID", ret.CrashID);
+ }
+
+ let extraKeyValsBag = Cc["@mozilla.org/hash-property-bag;1"].createInstance(
+ Ci.nsIWritablePropertyBag2
+ );
+ for (let key in this.extraKeyVals) {
+ extraKeyValsBag.setPropertyAsAString(key, this.extraKeyVals[key]);
+ }
+ propBag.setPropertyAsInterface("extra", extraKeyValsBag);
+
+ Services.obs.notifyObservers(propBag, "crash-report-status", status);
+
+ switch (status) {
+ case SUCCESS:
+ this.resolveSubmitStatusPromise(ret.CrashID);
+ break;
+ case FAILED:
+ this.rejectSubmitStatusPromise(FAILED);
+ break;
+ default:
+ // no callbacks invoked.
+ }
+ },
+
+ readAnnotations: async function Submitter_readAnnotations(extra) {
+ // These annotations are used only by the crash reporter client and should
+ // not be submitted to Socorro.
+ const strippedAnnotations = [
+ "StackTraces",
+ "TelemetryClientId",
+ "TelemetrySessionId",
+ "TelemetryServerURL",
+ ];
+ let extraKeyVals = await IOUtils.readJSON(extra);
+
+ this.extraKeyVals = { ...extraKeyVals, ...this.extraKeyVals };
+ strippedAnnotations.forEach(key => delete this.extraKeyVals[key]);
+ },
+
+ submit: async function Submitter_submit() {
+ if (this.recordSubmission) {
+ await Services.crashmanager.ensureCrashIsPresent(this.id);
+ }
+
+ let [dump, extra, memory] = getPendingMinidump(this.id);
+ let [dumpExists, extraExists, memoryExists] = await Promise.all([
+ IOUtils.exists(dump),
+ IOUtils.exists(extra),
+ IOUtils.exists(memory),
+ ]);
+
+ if (!dumpExists || !extraExists) {
+ this.notifyStatus(FAILED);
+ this.cleanup();
+ return this.submitStatusPromise;
+ }
+
+ this.dump = dump;
+ this.extra = extra;
+ this.memory = memoryExists ? memory : null;
+ await this.readAnnotations(extra);
+
+ let additionalDumps = [];
+
+ if ("additional_minidumps" in this.extraKeyVals) {
+ let dumpsExistsPromises = [];
+ let names = this.extraKeyVals.additional_minidumps.split(",");
+
+ for (let name of names) {
+ let [dump /* , extra, memory */] = getPendingMinidump(
+ this.id + "-" + name
+ );
+
+ dumpsExistsPromises.push(IOUtils.exists(dump));
+ additionalDumps.push({ name, dump });
+ }
+
+ let dumpsExist = await Promise.all(dumpsExistsPromises);
+ let allDumpsExist = dumpsExist.every(exists => exists);
+
+ if (!allDumpsExist) {
+ this.notifyStatus(FAILED);
+ this.cleanup();
+ return this.submitStatusPromise;
+ }
+ }
+
+ this.notifyStatus(SUBMITTING);
+ this.additionalDumps = additionalDumps;
+
+ if (!(await this.submitForm())) {
+ this.notifyStatus(FAILED);
+ this.cleanup();
+ }
+
+ return this.submitStatusPromise;
+ },
+};
+
+// ===================================
+// External API goes here
+export var CrashSubmit = {
+ // A set of strings representing how a user subnmitted a given crash
+ SUBMITTED_FROM_AUTO: "Auto",
+ SUBMITTED_FROM_INFOBAR: "Infobar",
+ SUBMITTED_FROM_ABOUT_CRASHES: "AboutCrashes",
+ SUBMITTED_FROM_CRASH_TAB: "CrashedTab",
+
+ /**
+ * Submit the crash report named id.dmp from the "pending" directory.
+ *
+ * @param id
+ * Filename (minus .dmp extension) of the minidump to submit.
+ * @param submittedFrom
+ * One of the SUBMITTED_FROM_* constants representing how the
+ * user submitted this crash.
+ * @param params
+ * An object containing any of the following optional parameters:
+ * - recordSubmission
+ * If true, a submission event is recorded in CrashManager.
+ * - noThrottle
+ * If true, this crash report should be submitted with
+ * the Throttleable annotation set to "0" indicating that
+ * it should be processed right away. This should be set
+ * when the report is being submitted and the user expects
+ * to see the results immediately. Defaults to false.
+ * - extraExtraKeyVals
+ * An object whose key-value pairs will be merged with the data from
+ * the ".extra" file submitted with the report. The properties of
+ * this object will override properties of the same name in the
+ * .extra file.
+ *
+ * @return a Promise that is fulfilled with the server crash ID when the
+ * submission succeeds and rejected otherwise.
+ */
+ submit: function CrashSubmit_submit(id, submittedFrom, params) {
+ params = params || {};
+ let recordSubmission = false;
+ let noThrottle = false;
+ let extraExtraKeyVals = {};
+
+ if ("recordSubmission" in params) {
+ recordSubmission = params.recordSubmission;
+ }
+
+ if ("noThrottle" in params) {
+ noThrottle = params.noThrottle;
+ }
+
+ if ("extraExtraKeyVals" in params) {
+ extraExtraKeyVals = params.extraExtraKeyVals;
+ }
+
+ extraExtraKeyVals.SubmittedFrom = submittedFrom;
+
+ let submitter = new Submitter(
+ id,
+ recordSubmission,
+ noThrottle,
+ extraExtraKeyVals
+ );
+ CrashSubmit._activeSubmissions.push(submitter);
+ return submitter.submit();
+ },
+
+ /**
+ * Delete the minidup from the "pending" directory.
+ *
+ * @param id
+ * Filename (minus .dmp extension) of the minidump to delete.
+ *
+ * @return a Promise that is fulfilled when the minidump is deleted and
+ * rejected otherwise
+ */
+ delete: async function CrashSubmit_delete(id) {
+ await Promise.all(
+ getPendingMinidump(id).map(path => {
+ return IOUtils.remove(path);
+ })
+ );
+ },
+
+ /**
+ * Add a .dmg.ignore file along side the .dmp file to indicate that the user
+ * shouldn't be prompted to submit this crash report again.
+ *
+ * @param id
+ * Filename (minus .dmp extension) of the report to ignore
+ *
+ * @return a Promise that is fulfilled when (if) the .dmg.ignore is created
+ * and rejected otherwise.
+ */
+ ignore: async function CrashSubmit_ignore(id) {
+ let [dump /* , extra, memory */] = getPendingMinidump(id);
+ const ignorePath = `${dump}.ignore`;
+ await IOUtils.writeUTF8(ignorePath, "", { mode: "create" });
+ },
+
+ /**
+ * Get the list of pending crash IDs, excluding those marked to be ignored
+ * @param minFileDate
+ * A Date object. Any files last modified before that date will be ignored
+ *
+ * @return a Promise that is fulfilled with an array of string, each
+ * being an ID as expected to be passed to submit() or ignore()
+ */
+ pendingIDs: async function CrashSubmit_pendingIDs(minFileDate) {
+ let ids = [];
+ let pendingDir = getDir("pending");
+
+ if (!(await IOUtils.exists(pendingDir))) {
+ return ids;
+ }
+
+ let children;
+ try {
+ children = await IOUtils.getChildren(pendingDir);
+ } catch (ex) {
+ console.error(ex);
+ throw ex;
+ }
+
+ try {
+ const entries = Object.create(null);
+ const ignored = Object.create(null);
+
+ for (const child of children) {
+ const info = await IOUtils.stat(child);
+
+ if (info.type !== "directory") {
+ const name = PathUtils.filename(child);
+ const matches = name.match(/(.+)\.dmp$/);
+ if (matches) {
+ const id = matches[1];
+
+ if (UUID_REGEX.test(id)) {
+ entries[id] = info;
+ }
+ } else {
+ // maybe it's a .ignore file
+ const matchesIgnore = name.match(/(.+)\.dmp.ignore$/);
+ if (matchesIgnore) {
+ const id = matchesIgnore[1];
+
+ if (UUID_REGEX.test(id)) {
+ ignored[id] = true;
+ }
+ }
+ }
+ }
+ }
+
+ for (const [id, info] of Object.entries(entries)) {
+ const accessDate = new Date(info.lastAccessed);
+ if (!(id in ignored) && accessDate > minFileDate) {
+ ids.push(id);
+ }
+ }
+ } catch (ex) {
+ console.error(ex);
+ throw ex;
+ }
+
+ return ids;
+ },
+
+ /**
+ * Prune the saved dumps.
+ *
+ * @return a Promise that is fulfilled when the daved dumps are deleted and
+ * rejected otherwise
+ */
+ pruneSavedDumps: async function CrashSubmit_pruneSavedDumps() {
+ const KEEP = 10;
+
+ let dirEntries = [];
+ let pendingDir = getDir("pending");
+
+ let children;
+ try {
+ children = await IOUtils.getChildren(pendingDir);
+ } catch (ex) {
+ if (DOMException.isInstance(ex) && ex.name === "NotFoundError") {
+ return [];
+ }
+
+ throw ex;
+ }
+
+ for (const path of children) {
+ let infoPromise;
+ try {
+ infoPromise = IOUtils.stat(path);
+ } catch (ex) {
+ console.error(ex);
+ throw ex;
+ }
+
+ const name = PathUtils.filename(path);
+
+ if (name.match(/(.+)\.extra$/)) {
+ dirEntries.push({
+ name,
+ path,
+ infoPromise,
+ });
+ }
+ }
+
+ dirEntries.sort(async (a, b) => {
+ let dateA = (await a.infoPromise).lastModified;
+ let dateB = (await b.infoPromise).lastModified;
+
+ if (dateA < dateB) {
+ return -1;
+ }
+
+ if (dateB < dateA) {
+ return 1;
+ }
+
+ return 0;
+ });
+
+ if (dirEntries.length > KEEP) {
+ let toDelete = [];
+
+ for (let i = 0; i < dirEntries.length - KEEP; ++i) {
+ let extra = dirEntries[i];
+ let matches = extra.leafName.match(/(.+)\.extra$/);
+
+ if (matches) {
+ let pathComponents = PathUtils.split(extra.path);
+ pathComponents[pathComponents.length - 1] = matches[1];
+ let path = PathUtils.join(...pathComponents);
+
+ toDelete.push(extra.path, `${path}.dmp`, `${path}.memory.json.gz`);
+ }
+ }
+
+ await Promise.all(
+ toDelete.map(path => {
+ return IOUtils.remove(path, { ignoreAbsent: true });
+ })
+ );
+ }
+ },
+
+ // List of currently active submit objects
+ _activeSubmissions: [],
+};
diff --git a/toolkit/crashreporter/InjectCrashReporter.cpp b/toolkit/crashreporter/InjectCrashReporter.cpp
new file mode 100644
index 0000000000..d9e6d062e5
--- /dev/null
+++ b/toolkit/crashreporter/InjectCrashReporter.cpp
@@ -0,0 +1,77 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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 "InjectCrashReporter.h"
+#include "nsDirectoryServiceUtils.h"
+#include "nsDirectoryServiceDefs.h"
+#include "windows/crash_generation/crash_generation_client.h"
+#include "nsExceptionHandler.h"
+#include "LoadLibraryRemote.h"
+#include "nsWindowsHelpers.h"
+
+using CrashReporter::GetChildNotificationPipe;
+using google_breakpad::CrashGenerationClient;
+
+namespace mozilla {
+
+InjectCrashRunnable::InjectCrashRunnable(DWORD pid)
+ : Runnable("InjectCrashRunnable"), mPID(pid) {
+ nsCOMPtr<nsIFile> dll;
+ nsresult rv = NS_GetSpecialDirectory(NS_GRE_DIR, getter_AddRefs(dll));
+ if (NS_SUCCEEDED(rv)) {
+ dll->Append(u"breakpadinjector.dll"_ns);
+ dll->GetPath(mInjectorPath);
+ }
+}
+
+NS_IMETHODIMP
+InjectCrashRunnable::Run() {
+ if (mInjectorPath.IsEmpty()) return NS_OK;
+
+ nsAutoHandle hProcess(OpenProcess(
+ PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_DUP_HANDLE |
+ PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ,
+ FALSE, mPID));
+ if (!hProcess) {
+ NS_WARNING(
+ "Unable to open remote process handle for crashreporter injection.");
+ return NS_OK;
+ }
+
+ void* proc =
+ LoadRemoteLibraryAndGetAddress(hProcess, mInjectorPath.get(), "Start");
+ if (!proc) {
+ NS_WARNING("Unable to inject crashreporter DLL.");
+ return NS_OK;
+ }
+
+ HANDLE hRemotePipe = CrashGenerationClient::DuplicatePipeToClientProcess(
+ NS_ConvertASCIItoUTF16(GetChildNotificationPipe()).get(), hProcess);
+ if (INVALID_HANDLE_VALUE == hRemotePipe) {
+ NS_WARNING("Unable to duplicate crash reporter pipe to process.");
+ return NS_OK;
+ }
+
+ nsAutoHandle hThread(CreateRemoteThread(hProcess, nullptr, 0,
+ (LPTHREAD_START_ROUTINE)proc,
+ (void*)hRemotePipe, 0, nullptr));
+ if (!hThread) {
+ NS_WARNING("Unable to CreateRemoteThread");
+
+ // We have to close the remote pipe or else our crash generation client
+ // will be stuck unable to accept other remote requests.
+ HANDLE toClose = INVALID_HANDLE_VALUE;
+ if (DuplicateHandle(hProcess, hRemotePipe, ::GetCurrentProcess(), &toClose,
+ 0, FALSE,
+ DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS)) {
+ CloseHandle(toClose);
+ return NS_OK;
+ }
+ }
+
+ return NS_OK;
+}
+
+} // namespace mozilla
diff --git a/toolkit/crashreporter/InjectCrashReporter.h b/toolkit/crashreporter/InjectCrashReporter.h
new file mode 100644
index 0000000000..a7a305f763
--- /dev/null
+++ b/toolkit/crashreporter/InjectCrashReporter.h
@@ -0,0 +1,27 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/. */
+
+#ifndef InjectCrashReporter_h
+#define InjectCrashReporter_h
+
+#include "nsThreadUtils.h"
+#include <windows.h>
+
+namespace mozilla {
+
+class InjectCrashRunnable : public Runnable {
+ public:
+ explicit InjectCrashRunnable(DWORD pid);
+
+ NS_IMETHOD Run() override;
+
+ private:
+ DWORD mPID;
+ nsString mInjectorPath;
+};
+
+} // Namespace mozilla
+
+#endif
diff --git a/toolkit/crashreporter/LoadLibraryRemote.cpp b/toolkit/crashreporter/LoadLibraryRemote.cpp
new file mode 100644
index 0000000000..d0422edd08
--- /dev/null
+++ b/toolkit/crashreporter/LoadLibraryRemote.cpp
@@ -0,0 +1,459 @@
+/* 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/. */
+
+#ifndef __GNUC__
+// disable warnings about pointer <-> DWORD conversions
+# pragma warning(disable : 4311 4312)
+#endif
+
+#ifdef _WIN64
+# define POINTER_TYPE ULONGLONG
+#else
+# define POINTER_TYPE DWORD
+#endif
+
+#include <windows.h>
+#include <winnt.h>
+#include <stdlib.h>
+#ifdef DEBUG_OUTPUT
+# include <stdio.h>
+#endif
+
+#include "nsWindowsHelpers.h"
+
+typedef const unsigned char* FileView;
+
+template <>
+class nsAutoRefTraits<FileView> {
+ public:
+ typedef FileView RawRef;
+ static FileView Void() { return nullptr; }
+
+ static void Release(RawRef aView) {
+ if (nullptr != aView) UnmapViewOfFile(aView);
+ }
+};
+
+#ifndef IMAGE_SIZEOF_BASE_RELOCATION
+// Vista SDKs no longer define IMAGE_SIZEOF_BASE_RELOCATION!?
+# define IMAGE_SIZEOF_BASE_RELOCATION (sizeof(IMAGE_BASE_RELOCATION))
+#endif
+
+#include "LoadLibraryRemote.h"
+
+typedef struct {
+ PIMAGE_NT_HEADERS headers;
+ unsigned char* localCodeBase;
+ unsigned char* remoteCodeBase;
+ HMODULE* modules;
+ int numModules;
+} MEMORYMODULE, *PMEMORYMODULE;
+
+typedef BOOL(WINAPI* DllEntryProc)(HINSTANCE hinstDLL, DWORD fdwReason,
+ LPVOID lpReserved);
+
+#define GET_HEADER_DICTIONARY(module, idx) \
+ &(module)->headers->OptionalHeader.DataDirectory[idx]
+
+#ifdef DEBUG_OUTPUT
+static void OutputLastError(const char* msg) {
+ char* tmp;
+ char* tmpmsg;
+ FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ nullptr, GetLastError(),
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&tmp, 0,
+ nullptr);
+ tmpmsg = (char*)LocalAlloc(LPTR, strlen(msg) + strlen(tmp) + 3);
+ sprintf(tmpmsg, "%s: %s", msg, tmp);
+ OutputDebugStringA(tmpmsg);
+ LocalFree(tmpmsg);
+ LocalFree(tmp);
+}
+#endif
+
+static void CopySections(const unsigned char* data,
+ PIMAGE_NT_HEADERS old_headers, PMEMORYMODULE module) {
+ int i;
+ unsigned char* codeBase = module->localCodeBase;
+ unsigned char* dest;
+ PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(module->headers);
+ for (i = 0; i < module->headers->FileHeader.NumberOfSections;
+ i++, section++) {
+ dest = codeBase + section->VirtualAddress;
+ memset(dest, 0, section->Misc.VirtualSize);
+ if (section->SizeOfRawData) {
+ memcpy(dest, data + section->PointerToRawData, section->SizeOfRawData);
+ }
+ // section->Misc.PhysicalAddress = (POINTER_TYPE) module->remoteCodeBase +
+ // section->VirtualAddress;
+ }
+}
+
+static bool CopyRegion(HANDLE hRemoteProcess, void* remoteAddress,
+ void* localAddress, DWORD size, DWORD protect) {
+ if (size > 0) {
+ // Copy the data from local->remote and set the memory protection
+ if (!VirtualAllocEx(hRemoteProcess, remoteAddress, size, MEM_COMMIT,
+ PAGE_READWRITE))
+ return false;
+
+ if (!WriteProcessMemory(hRemoteProcess, remoteAddress, localAddress, size,
+ nullptr)) {
+#ifdef DEBUG_OUTPUT
+ OutputLastError("Error writing remote memory.\n");
+#endif
+ return false;
+ }
+
+ DWORD oldProtect;
+ if (VirtualProtectEx(hRemoteProcess, remoteAddress, size, protect,
+ &oldProtect) == 0) {
+#ifdef DEBUG_OUTPUT
+ OutputLastError("Error protecting memory page");
+#endif
+ return false;
+ }
+ }
+ return true;
+}
+// Protection flags for memory pages (Executable, Readable, Writeable)
+static int ProtectionFlags[2][2][2] = {
+ {
+ // not executable
+ {PAGE_NOACCESS, PAGE_WRITECOPY},
+ {PAGE_READONLY, PAGE_READWRITE},
+ },
+ {
+ // executable
+ {PAGE_EXECUTE, PAGE_EXECUTE_WRITECOPY},
+ {PAGE_EXECUTE_READ, PAGE_EXECUTE_READWRITE},
+ },
+};
+
+static bool FinalizeSections(PMEMORYMODULE module, HANDLE hRemoteProcess) {
+#ifdef DEBUG_OUTPUT
+ fprintf(stderr, "Finalizing sections: local base %p, remote base %p\n",
+ module->localCodeBase, module->remoteCodeBase);
+#endif
+
+ int i;
+ int numSections = module->headers->FileHeader.NumberOfSections;
+
+ if (numSections < 1) return false;
+
+ PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(module->headers);
+
+ // Copy any data before the first section (i.e. the image header)
+ if (!CopyRegion(hRemoteProcess, module->remoteCodeBase, module->localCodeBase,
+ section->VirtualAddress, PAGE_READONLY))
+ return false;
+
+ // loop through all sections and change access flags
+ for (i = 0; i < numSections; i++, section++) {
+ DWORD protect, size;
+ int executable = (section->Characteristics & IMAGE_SCN_MEM_EXECUTE) != 0;
+ int readable = (section->Characteristics & IMAGE_SCN_MEM_READ) != 0;
+ int writeable = (section->Characteristics & IMAGE_SCN_MEM_WRITE) != 0;
+
+ // determine protection flags based on characteristics
+ protect = ProtectionFlags[executable][readable][writeable];
+ if (section->Characteristics & IMAGE_SCN_MEM_NOT_CACHED) {
+ protect |= PAGE_NOCACHE;
+ }
+
+ void* remoteAddress = module->remoteCodeBase + section->VirtualAddress;
+ void* localAddress = module->localCodeBase + section->VirtualAddress;
+
+ // determine size of region
+ size = section->Misc.VirtualSize;
+#ifdef DEBUG_OUTPUT
+ fprintf(stderr,
+ "Copying section %s to %p, size %x, executable %i readable %i "
+ "writeable %i\n",
+ section->Name, remoteAddress, size, executable, readable,
+ writeable);
+#endif
+ if (!CopyRegion(hRemoteProcess, remoteAddress, localAddress, size, protect))
+ return false;
+ }
+ return true;
+}
+
+static void PerformBaseRelocation(PMEMORYMODULE module, SIZE_T delta) {
+ DWORD i;
+ unsigned char* codeBase = module->localCodeBase;
+
+ PIMAGE_DATA_DIRECTORY directory =
+ GET_HEADER_DICTIONARY(module, IMAGE_DIRECTORY_ENTRY_BASERELOC);
+ if (directory->Size > 0) {
+ PIMAGE_BASE_RELOCATION relocation =
+ (PIMAGE_BASE_RELOCATION)(codeBase + directory->VirtualAddress);
+ for (; relocation->VirtualAddress > 0;) {
+ unsigned char* dest = codeBase + relocation->VirtualAddress;
+ unsigned short* relInfo = (unsigned short*)((unsigned char*)relocation +
+ IMAGE_SIZEOF_BASE_RELOCATION);
+ for (i = 0;
+ i < ((relocation->SizeOfBlock - IMAGE_SIZEOF_BASE_RELOCATION) / 2);
+ i++, relInfo++) {
+ DWORD* patchAddrHL;
+#ifdef _WIN64
+ ULONGLONG* patchAddr64;
+#endif
+ int type, offset;
+
+ // the upper 4 bits define the type of relocation
+ type = *relInfo >> 12;
+ // the lower 12 bits define the offset
+ offset = *relInfo & 0xfff;
+
+ switch (type) {
+ case IMAGE_REL_BASED_ABSOLUTE:
+ // skip relocation
+ break;
+
+ case IMAGE_REL_BASED_HIGHLOW:
+ // change complete 32 bit address
+ patchAddrHL = (DWORD*)(dest + offset);
+ *patchAddrHL += delta;
+ break;
+
+#ifdef _WIN64
+ case IMAGE_REL_BASED_DIR64:
+ patchAddr64 = (ULONGLONG*)(dest + offset);
+ *patchAddr64 += delta;
+ break;
+#endif
+
+ default:
+ // printf("Unknown relocation: %d\n", type);
+ break;
+ }
+ }
+
+ // advance to next relocation block
+ relocation = (PIMAGE_BASE_RELOCATION)(((char*)relocation) +
+ relocation->SizeOfBlock);
+ }
+ }
+}
+
+static int BuildImportTable(PMEMORYMODULE module) {
+ int result = 1;
+ unsigned char* codeBase = module->localCodeBase;
+
+ PIMAGE_DATA_DIRECTORY directory =
+ GET_HEADER_DICTIONARY(module, IMAGE_DIRECTORY_ENTRY_IMPORT);
+ if (directory->Size > 0) {
+ PIMAGE_IMPORT_DESCRIPTOR importDesc =
+ (PIMAGE_IMPORT_DESCRIPTOR)(codeBase + directory->VirtualAddress);
+ PIMAGE_IMPORT_DESCRIPTOR importEnd =
+ (PIMAGE_IMPORT_DESCRIPTOR)(codeBase + directory->VirtualAddress +
+ directory->Size);
+
+ for (; importDesc < importEnd && importDesc->Name; importDesc++) {
+ POINTER_TYPE* thunkRef;
+ FARPROC* funcRef;
+ HMODULE handle = GetModuleHandleA((LPCSTR)(codeBase + importDesc->Name));
+ if (handle == nullptr) {
+#if DEBUG_OUTPUT
+ OutputLastError("Can't load library");
+#endif
+ result = 0;
+ break;
+ }
+
+ module->modules = (HMODULE*)realloc(
+ module->modules, (module->numModules + 1) * (sizeof(HMODULE)));
+ if (module->modules == nullptr) {
+ result = 0;
+ break;
+ }
+
+ module->modules[module->numModules++] = handle;
+ if (importDesc->OriginalFirstThunk) {
+ thunkRef = (POINTER_TYPE*)(codeBase + importDesc->OriginalFirstThunk);
+ funcRef = (FARPROC*)(codeBase + importDesc->FirstThunk);
+ } else {
+ // no hint table
+ thunkRef = (POINTER_TYPE*)(codeBase + importDesc->FirstThunk);
+ funcRef = (FARPROC*)(codeBase + importDesc->FirstThunk);
+ }
+ for (; *thunkRef; thunkRef++, funcRef++) {
+ if (IMAGE_SNAP_BY_ORDINAL(*thunkRef)) {
+ *funcRef =
+ (FARPROC)GetProcAddress(handle, (LPCSTR)IMAGE_ORDINAL(*thunkRef));
+ } else {
+ PIMAGE_IMPORT_BY_NAME thunkData =
+ (PIMAGE_IMPORT_BY_NAME)(codeBase + (*thunkRef));
+ *funcRef = (FARPROC)GetProcAddress(handle, (LPCSTR)&thunkData->Name);
+ }
+ if (*funcRef == 0) {
+ result = 0;
+ break;
+ }
+ }
+
+ if (!result) {
+ break;
+ }
+ }
+ }
+
+ return result;
+}
+
+static void* MemoryGetProcAddress(PMEMORYMODULE module, const char* name);
+
+void* LoadRemoteLibraryAndGetAddress(HANDLE hRemoteProcess,
+ const WCHAR* library, const char* symbol) {
+ // Map the DLL into memory
+ nsAutoHandle hLibrary(CreateFile(library, GENERIC_READ, FILE_SHARE_READ,
+ nullptr, OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL, nullptr));
+ if (INVALID_HANDLE_VALUE == hLibrary) {
+#if DEBUG_OUTPUT
+ OutputLastError("Couldn't CreateFile the library.\n");
+#endif
+ return nullptr;
+ }
+
+ nsAutoHandle hMapping(
+ CreateFileMapping(hLibrary, nullptr, PAGE_READONLY, 0, 0, nullptr));
+ if (!hMapping) {
+#if DEBUG_OUTPUT
+ OutputLastError("Couldn't CreateFileMapping.\n");
+#endif
+ return nullptr;
+ }
+
+ nsAutoRef<FileView> data(
+ (const unsigned char*)MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0));
+ if (!data) {
+#if DEBUG_OUTPUT
+ OutputLastError("Couldn't MapViewOfFile.\n");
+#endif
+ return nullptr;
+ }
+
+ SIZE_T locationDelta;
+
+ PIMAGE_DOS_HEADER dos_header = (PIMAGE_DOS_HEADER)data.get();
+ if (dos_header->e_magic != IMAGE_DOS_SIGNATURE) {
+#if DEBUG_OUTPUT
+ OutputDebugStringA("Not a valid executable file.\n");
+#endif
+ return nullptr;
+ }
+
+ PIMAGE_NT_HEADERS old_header =
+ (PIMAGE_NT_HEADERS)(data + dos_header->e_lfanew);
+ if (old_header->Signature != IMAGE_NT_SIGNATURE) {
+#if DEBUG_OUTPUT
+ OutputDebugStringA("No PE header found.\n");
+#endif
+ return nullptr;
+ }
+
+ // reserve memory for image of library in this process and the target process
+ unsigned char* localCode = (unsigned char*)VirtualAlloc(
+ nullptr, old_header->OptionalHeader.SizeOfImage, MEM_RESERVE | MEM_COMMIT,
+ PAGE_READWRITE);
+ if (!localCode) {
+#if DEBUG_OUTPUT
+ OutputLastError("Can't reserve local memory.");
+#endif
+ }
+
+ unsigned char* remoteCode = (unsigned char*)VirtualAllocEx(
+ hRemoteProcess, nullptr, old_header->OptionalHeader.SizeOfImage,
+ MEM_RESERVE, PAGE_EXECUTE_READ);
+ if (!remoteCode) {
+#if DEBUG_OUTPUT
+ OutputLastError("Can't reserve remote memory.");
+#endif
+ }
+
+ MEMORYMODULE result;
+ result.localCodeBase = localCode;
+ result.remoteCodeBase = remoteCode;
+ result.numModules = 0;
+ result.modules = nullptr;
+
+ // copy PE header to code
+ memcpy(localCode, dos_header,
+ dos_header->e_lfanew + old_header->OptionalHeader.SizeOfHeaders);
+ result.headers =
+ reinterpret_cast<PIMAGE_NT_HEADERS>(localCode + dos_header->e_lfanew);
+
+ // update position
+ result.headers->OptionalHeader.ImageBase = (POINTER_TYPE)remoteCode;
+
+ // copy sections from DLL file block to new memory location
+ CopySections(data, old_header, &result);
+
+ // adjust base address of imported data
+ locationDelta = (SIZE_T)(remoteCode - old_header->OptionalHeader.ImageBase);
+ if (locationDelta != 0) {
+ PerformBaseRelocation(&result, locationDelta);
+ }
+
+ // load required dlls and adjust function table of imports
+ if (!BuildImportTable(&result)) {
+ return nullptr;
+ }
+
+ // mark memory pages depending on section headers and release
+ // sections that are marked as "discardable"
+ if (!FinalizeSections(&result, hRemoteProcess)) {
+ return nullptr;
+ }
+
+ return MemoryGetProcAddress(&result, symbol);
+}
+
+static void* MemoryGetProcAddress(PMEMORYMODULE module, const char* name) {
+ unsigned char* localCodeBase = module->localCodeBase;
+ int idx = -1;
+ DWORD i, *nameRef;
+ WORD* ordinal;
+ PIMAGE_EXPORT_DIRECTORY exports;
+ PIMAGE_DATA_DIRECTORY directory =
+ GET_HEADER_DICTIONARY(module, IMAGE_DIRECTORY_ENTRY_EXPORT);
+ if (directory->Size == 0) {
+ // no export table found
+ return nullptr;
+ }
+
+ exports =
+ (PIMAGE_EXPORT_DIRECTORY)(localCodeBase + directory->VirtualAddress);
+ if (exports->NumberOfNames == 0 || exports->NumberOfFunctions == 0) {
+ // DLL doesn't export anything
+ return nullptr;
+ }
+
+ // search function name in list of exported names
+ nameRef = (DWORD*)(localCodeBase + exports->AddressOfNames);
+ ordinal = (WORD*)(localCodeBase + exports->AddressOfNameOrdinals);
+ for (i = 0; i < exports->NumberOfNames; i++, nameRef++, ordinal++) {
+ if (stricmp(name, (const char*)(localCodeBase + (*nameRef))) == 0) {
+ idx = *ordinal;
+ break;
+ }
+ }
+
+ if (idx == -1) {
+ // exported symbol not found
+ return nullptr;
+ }
+
+ if ((DWORD)idx > exports->NumberOfFunctions) {
+ // name <-> ordinal number don't match
+ return nullptr;
+ }
+
+ // AddressOfFunctions contains the RVAs to the "real" functions
+ return module->remoteCodeBase +
+ (*(DWORD*)(localCodeBase + exports->AddressOfFunctions + (idx * 4)));
+}
diff --git a/toolkit/crashreporter/LoadLibraryRemote.h b/toolkit/crashreporter/LoadLibraryRemote.h
new file mode 100644
index 0000000000..4aa5d2df19
--- /dev/null
+++ b/toolkit/crashreporter/LoadLibraryRemote.h
@@ -0,0 +1,23 @@
+/* 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/. */
+
+#ifndef LoadLibraryRemote_h
+#define LoadLibraryRemote_h
+
+#include <windows.h>
+
+/**
+ * Inject a library into a remote process. This injection has the following
+ * restrictions:
+ *
+ * - The DLL being injected must only depend on kernel32 and user32.
+ * - The entry point of the DLL is not run. If the DLL uses the CRT, it is
+ * the responsibility of the caller to make sure that _CRT_INIT is called.
+ * - There is no support for unloading a library once it has been loaded.
+ * - The symbol must be a named symbol and not an ordinal.
+ */
+void* LoadRemoteLibraryAndGetAddress(HANDLE hRemoteProcess,
+ const WCHAR* library, const char* symbol);
+
+#endif // LoadLibraryRemote_h
diff --git a/toolkit/crashreporter/breakpad-client/linux/crash_generation/client_info.h b/toolkit/crashreporter/breakpad-client/linux/crash_generation/client_info.h
new file mode 100644
index 0000000000..3de2606b7b
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/linux/crash_generation/client_info.h
@@ -0,0 +1,68 @@
+// Copyright (c) 2010 Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef CLIENT_LINUX_CRASH_GENERATION_CLIENT_INFO_H_
+#define CLIENT_LINUX_CRASH_GENERATION_CLIENT_INFO_H_
+
+namespace google_breakpad {
+
+class CrashGenerationServer;
+
+class ClientInfo {
+ public:
+ ClientInfo(pid_t pid, CrashGenerationServer* crash_server)
+ : crash_server_(crash_server),
+ pid_(pid) {}
+
+ CrashGenerationServer* crash_server() const { return crash_server_; }
+ pid_t pid() const { return pid_; }
+ void set_error_msg(nsCString &error_msg) {
+ had_error_ = true;
+ error_msg_ = error_msg;
+ }
+
+ const nsCString* error_msg() const {
+ return &error_msg_;
+ }
+
+ bool had_error() const {
+ return had_error_;
+ }
+
+ private:
+ CrashGenerationServer* crash_server_;
+ pid_t pid_;
+ bool had_error_ = false;
+ nsCString error_msg_; // Possible error message of the minidumper in
+ // case there was an error during dumping
+};
+
+}
+
+#endif // CLIENT_LINUX_CRASH_GENERATION_CLIENT_INFO_H_
diff --git a/toolkit/crashreporter/breakpad-client/linux/crash_generation/crash_generation_client.cc b/toolkit/crashreporter/breakpad-client/linux/crash_generation/crash_generation_client.cc
new file mode 100644
index 0000000000..02dc66f355
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/linux/crash_generation/crash_generation_client.cc
@@ -0,0 +1,105 @@
+// 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 "linux/crash_generation/crash_generation_client.h"
+
+#include <stdio.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+
+#include <algorithm>
+
+#include "common/linux/eintr_wrapper.h"
+#include "common/linux/ignore_ret.h"
+#include "third_party/lss/linux_syscall_support.h"
+
+namespace google_breakpad {
+
+namespace {
+
+class CrashGenerationClientImpl : public CrashGenerationClient {
+ public:
+ explicit CrashGenerationClientImpl(int server_fd) : server_fd_(server_fd) {}
+ virtual ~CrashGenerationClientImpl() {}
+
+ virtual bool RequestDump(const void* blob, size_t blob_size) {
+ int fds[2];
+ if (sys_pipe(fds) < 0)
+ return false;
+ static const unsigned kControlMsgSize = CMSG_SPACE(sizeof(int));
+
+ struct kernel_iovec iov;
+ iov.iov_base = const_cast<void*>(blob);
+ iov.iov_len = blob_size;
+
+ struct kernel_msghdr msg = { 0 };
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+ char cmsg[kControlMsgSize] = "";
+ msg.msg_control = cmsg;
+ msg.msg_controllen = sizeof(cmsg);
+
+ struct cmsghdr* hdr = CMSG_FIRSTHDR(&msg);
+ hdr->cmsg_level = SOL_SOCKET;
+ hdr->cmsg_type = SCM_RIGHTS;
+ hdr->cmsg_len = CMSG_LEN(sizeof(int));
+ int* p = reinterpret_cast<int*>(CMSG_DATA(hdr));
+ *p = fds[1];
+
+ ssize_t ret = HANDLE_EINTR(sys_sendmsg(server_fd_, &msg, 0));
+ sys_close(fds[1]);
+ if (ret < 0) {
+ sys_close(fds[0]);
+ return false;
+ }
+
+ // Wait for an ACK from the server.
+ char b;
+ IGNORE_RET(HANDLE_EINTR(sys_read(fds[0], &b, 1)));
+ sys_close(fds[0]);
+
+ return true;
+ }
+
+ private:
+ int server_fd_;
+
+ DISALLOW_COPY_AND_ASSIGN(CrashGenerationClientImpl);
+};
+
+} // namespace
+
+// static
+CrashGenerationClient* CrashGenerationClient::TryCreate(int server_fd) {
+ if (server_fd < 0)
+ return NULL;
+ return new CrashGenerationClientImpl(server_fd);
+}
+
+} // namespace google_breakpad
diff --git a/toolkit/crashreporter/breakpad-client/linux/crash_generation/crash_generation_client.h b/toolkit/crashreporter/breakpad-client/linux/crash_generation/crash_generation_client.h
new file mode 100644
index 0000000000..4e68424ae8
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/linux/crash_generation/crash_generation_client.h
@@ -0,0 +1,65 @@
+// Copyright (c) 2010 Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef CLIENT_LINUX_CRASH_GENERATION_CRASH_GENERATION_CLIENT_H_
+#define CLIENT_LINUX_CRASH_GENERATION_CRASH_GENERATION_CLIENT_H_
+
+#include "common/basictypes.h"
+
+#include <stddef.h>
+
+namespace google_breakpad {
+
+// CrashGenerationClient is an interface for implementing out-of-process crash
+// dumping. The default implementation, accessed via the TryCreate() factory,
+// works in conjunction with the CrashGenerationServer to generate a minidump
+// via a remote process.
+class CrashGenerationClient {
+ public:
+ CrashGenerationClient() {}
+ virtual ~CrashGenerationClient() {}
+
+ // Request the crash server to generate a dump. |blob| is an opaque
+ // CrashContext pointer from exception_handler.h.
+ // Returns true if the dump was successful; false otherwise.
+ virtual bool RequestDump(const void* blob, size_t blob_size) = 0;
+
+ // Returns a new CrashGenerationClient if |server_fd| is valid and
+ // connects to a CrashGenerationServer. Otherwise, return NULL.
+ // The returned CrashGenerationClient* is owned by the caller of
+ // this function.
+ static CrashGenerationClient* TryCreate(int server_fd);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(CrashGenerationClient);
+};
+
+} // namespace google_breakpad
+
+#endif // CLIENT_LINUX_CRASH_GENERATION_CRASH_GENERATION_CLIENT_H_
diff --git a/toolkit/crashreporter/breakpad-client/linux/crash_generation/crash_generation_server.cc b/toolkit/crashreporter/breakpad-client/linux/crash_generation/crash_generation_server.cc
new file mode 100644
index 0000000000..ee3d785385
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/linux/crash_generation/crash_generation_server.cc
@@ -0,0 +1,378 @@
+// 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 <dirent.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <poll.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <vector>
+
+#include "nsThreadUtils.h"
+
+#include "linux/crash_generation/crash_generation_server.h"
+#include "linux/crash_generation/client_info.h"
+#include "linux/handler/exception_handler.h"
+#include "linux/handler/guid_generator.h"
+#include "linux/minidump_writer/minidump_writer.h"
+#include "common/linux/eintr_wrapper.h"
+#include "common/linux/safe_readlink.h"
+
+#if defined(MOZ_OXIDIZED_BREAKPAD)
+# include "mozilla/toolkit/crashreporter/rust_minidump_writer_linux_ffi_generated.h"
+# include <sys/signalfd.h>
+# include "nsString.h"
+#endif
+
+static const char kCommandQuit = 'x';
+
+namespace google_breakpad {
+
+CrashGenerationServer::CrashGenerationServer(
+ const int listen_fd,
+ OnClientDumpRequestCallback dump_callback,
+ void* dump_context,
+ OnClientExitingCallback exit_callback,
+ void* exit_context,
+ bool generate_dumps,
+ const string* dump_path) :
+ server_fd_(listen_fd),
+ dump_callback_(dump_callback),
+ dump_context_(dump_context),
+ exit_callback_(exit_callback),
+ exit_context_(exit_context),
+ generate_dumps_(generate_dumps),
+ started_(false)
+{
+ if (dump_path)
+ dump_dir_ = *dump_path;
+ else
+ dump_dir_ = "/tmp";
+}
+
+CrashGenerationServer::~CrashGenerationServer()
+{
+ if (started_)
+ Stop();
+}
+
+bool
+CrashGenerationServer::Start()
+{
+ if (started_ || 0 > server_fd_)
+ return false;
+
+ int control_pipe[2];
+ if (pipe(control_pipe))
+ return false;
+
+ if (fcntl(control_pipe[0], F_SETFD, FD_CLOEXEC))
+ return false;
+ if (fcntl(control_pipe[1], F_SETFD, FD_CLOEXEC))
+ return false;
+
+ if (fcntl(control_pipe[0], F_SETFL, O_NONBLOCK))
+ return false;
+
+ control_pipe_in_ = control_pipe[0];
+ control_pipe_out_ = control_pipe[1];
+
+ if (pthread_create(&thread_, NULL,
+ ThreadMain, reinterpret_cast<void*>(this)))
+ return false;
+
+ started_ = true;
+ return true;
+}
+
+void
+CrashGenerationServer::Stop()
+{
+ assert(pthread_self() != thread_);
+
+ if (!started_)
+ return;
+
+ HANDLE_EINTR(write(control_pipe_out_, &kCommandQuit, 1));
+
+ void* dummy;
+ pthread_join(thread_, &dummy);
+
+ close(control_pipe_in_);
+ close(control_pipe_out_);
+
+ started_ = false;
+}
+
+//static
+bool
+CrashGenerationServer::CreateReportChannel(int* server_fd, int* client_fd)
+{
+ int fds[2];
+
+ if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, fds))
+ return false;
+
+ static const int on = 1;
+ // Enable passcred on the server end of the socket
+ if (setsockopt(fds[1], SOL_SOCKET, SO_PASSCRED, &on, sizeof(on)))
+ return false;
+
+ if (fcntl(fds[1], F_SETFL, O_NONBLOCK))
+ return false;
+ if (fcntl(fds[1], F_SETFD, FD_CLOEXEC))
+ return false;
+
+ *client_fd = fds[0];
+ *server_fd = fds[1];
+ return true;
+}
+
+// The following methods/functions execute on the server thread
+
+void
+CrashGenerationServer::Run()
+{
+ struct pollfd pollfds[2];
+ memset(&pollfds, 0, sizeof(pollfds));
+
+ pollfds[0].fd = server_fd_;
+ pollfds[0].events = POLLIN;
+
+ pollfds[1].fd = control_pipe_in_;
+ pollfds[1].events = POLLIN;
+
+ while (true) {
+ // infinite timeout
+ int nevents = poll(pollfds, sizeof(pollfds)/sizeof(pollfds[0]), -1);
+ if (-1 == nevents) {
+ if (EINTR == errno) {
+ continue;
+ } else {
+ return;
+ }
+ }
+
+ if (pollfds[0].revents && !ClientEvent(pollfds[0].revents))
+ return;
+
+ if (pollfds[1].revents && !ControlEvent(pollfds[1].revents))
+ return;
+ }
+}
+
+bool
+CrashGenerationServer::ClientEvent(short revents)
+{
+ if (POLLHUP & revents)
+ return false;
+ assert(POLLIN & revents);
+
+ // A process has crashed and has signaled us by writing a datagram
+ // to the death signal socket. The datagram contains the crash context needed
+ // for writing the minidump as well as a file descriptor and a credentials
+ // block so that they can't lie about their pid.
+
+ // The length of the control message:
+ static const unsigned kControlMsgSize =
+ CMSG_SPACE(sizeof(int)) + CMSG_SPACE(sizeof(struct ucred));
+ // The length of the regular payload:
+ static const unsigned kCrashContextSize =
+ sizeof(google_breakpad::ExceptionHandler::CrashContext);
+
+ struct msghdr msg = {0};
+ struct iovec iov[1];
+ char crash_context[kCrashContextSize];
+ char control[kControlMsgSize];
+ const ssize_t expected_msg_size = sizeof(crash_context);
+
+ iov[0].iov_base = crash_context;
+ iov[0].iov_len = sizeof(crash_context);
+ msg.msg_iov = iov;
+ msg.msg_iovlen = sizeof(iov)/sizeof(iov[0]);
+ msg.msg_control = control;
+ msg.msg_controllen = kControlMsgSize;
+
+ const ssize_t msg_size = HANDLE_EINTR(recvmsg(server_fd_, &msg, 0));
+ if (msg_size != expected_msg_size)
+ return true;
+
+ if (msg.msg_controllen != kControlMsgSize ||
+ msg.msg_flags & ~MSG_TRUNC)
+ return true;
+
+ // Walk the control payload and extract the file descriptor and validated pid.
+ pid_t crashing_pid = -1;
+ int signal_fd = -1;
+ for (struct cmsghdr *hdr = CMSG_FIRSTHDR(&msg); hdr;
+ hdr = CMSG_NXTHDR(&msg, hdr)) {
+ if (hdr->cmsg_level != SOL_SOCKET)
+ continue;
+ if (hdr->cmsg_type == SCM_RIGHTS) {
+ const unsigned len = hdr->cmsg_len -
+ (((uint8_t*)CMSG_DATA(hdr)) - (uint8_t*)hdr);
+ assert(len % sizeof(int) == 0u);
+ const unsigned num_fds = len / sizeof(int);
+ if (num_fds > 1 || num_fds == 0) {
+ // A nasty process could try and send us too many descriptors and
+ // force a leak.
+ for (unsigned i = 0; i < num_fds; ++i)
+ close(reinterpret_cast<int*>(CMSG_DATA(hdr))[i]);
+ return true;
+ } else {
+ signal_fd = reinterpret_cast<int*>(CMSG_DATA(hdr))[0];
+ }
+ } else if (hdr->cmsg_type == SCM_CREDENTIALS) {
+ const struct ucred *cred =
+ reinterpret_cast<struct ucred*>(CMSG_DATA(hdr));
+ crashing_pid = cred->pid;
+ }
+ }
+
+ if (crashing_pid == -1 || signal_fd == -1) {
+ if (signal_fd != -1)
+ close(signal_fd);
+ return true;
+ }
+
+ string minidump_filename;
+ if (!MakeMinidumpFilename(minidump_filename))
+ return true;
+
+#if defined(MOZ_OXIDIZED_BREAKPAD)
+ ExceptionHandler::CrashContext* breakpad_cc =
+ reinterpret_cast<ExceptionHandler::CrashContext*>(crash_context);
+ nsCString error_msg;
+ siginfo_t& si = breakpad_cc->siginfo;
+ signalfd_siginfo signalfd_si = {};
+ signalfd_si.ssi_signo = si.si_signo;
+ signalfd_si.ssi_errno = si.si_errno;
+ signalfd_si.ssi_code = si.si_code;
+
+ switch (si.si_signo) {
+ case SIGILL:
+ case SIGFPE:
+ case SIGSEGV:
+ case SIGBUS:
+ case SIGSYS:
+ signalfd_si.ssi_addr = reinterpret_cast<size_t>(si.si_addr);
+ break;
+ }
+
+ // Ignoring the return-value here for now.
+ // The function always creates an empty minidump file even in case of an
+ // error. So we'll report that as well via the callback-functions.
+ bool res = write_minidump_linux_with_context(
+ minidump_filename.c_str(), crashing_pid, &breakpad_cc->context,
+ &breakpad_cc->float_state, &signalfd_si, breakpad_cc->tid, &error_msg);
+#else
+ if (!google_breakpad::WriteMinidump(minidump_filename.c_str(),
+ crashing_pid, crash_context,
+ kCrashContextSize)) {
+ close(signal_fd);
+ return true;
+ }
+#endif
+
+ ClientInfo info(crashing_pid, this);
+#if defined(MOZ_OXIDIZED_BREAKPAD)
+ if (!res) {
+ info.set_error_msg(error_msg);
+ }
+#endif
+ if (dump_callback_) {
+ dump_callback_(dump_context_, info, minidump_filename);
+ }
+
+ // Send the done signal to the process: it can exit now.
+ // (Closing this will make the child's sys_read unblock and return 0.)
+ close(signal_fd);
+
+ if (exit_callback_) {
+ exit_callback_(exit_context_, info);
+ }
+
+ return true;
+}
+
+bool
+CrashGenerationServer::ControlEvent(short revents)
+{
+ if (POLLHUP & revents)
+ return false;
+ assert(POLLIN & revents);
+
+ char command;
+ if (read(control_pipe_in_, &command, 1))
+ return false;
+
+ switch (command) {
+ case kCommandQuit:
+ return false;
+ default:
+ assert(0);
+ }
+
+ return true;
+}
+
+bool
+CrashGenerationServer::MakeMinidumpFilename(string& outFilename)
+{
+ GUID guid;
+ char guidString[kGUIDStringLength+1];
+
+ if (!(CreateGUID(&guid)
+ && GUIDToString(&guid, guidString, sizeof(guidString))))
+ return false;
+
+ char path[PATH_MAX];
+ snprintf(path, sizeof(path), "%s/%s.dmp", dump_dir_.c_str(), guidString);
+
+ outFilename = path;
+ return true;
+}
+
+// static
+void*
+CrashGenerationServer::ThreadMain(void *arg)
+{
+ NS_SetCurrentThreadName("Breakpad Server");
+ reinterpret_cast<CrashGenerationServer*>(arg)->Run();
+ return NULL;
+}
+
+} // namespace google_breakpad
diff --git a/toolkit/crashreporter/breakpad-client/linux/crash_generation/crash_generation_server.h b/toolkit/crashreporter/breakpad-client/linux/crash_generation/crash_generation_server.h
new file mode 100644
index 0000000000..83b626ab1e
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/linux/crash_generation/crash_generation_server.h
@@ -0,0 +1,135 @@
+// Copyright (c) 2010 Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef CLIENT_LINUX_CRASH_GENERATION_CRASH_GENERATION_SERVER_H_
+#define CLIENT_LINUX_CRASH_GENERATION_CRASH_GENERATION_SERVER_H_
+
+#include <pthread.h>
+
+#include <string>
+
+#include "common/using_std_string.h"
+
+namespace google_breakpad {
+
+class ClientInfo;
+
+class CrashGenerationServer {
+public:
+ // WARNING: callbacks may be invoked on a different thread
+ // than that which creates the CrashGenerationServer. They must
+ // be thread safe.
+ typedef void (*OnClientDumpRequestCallback)(void* context,
+ const ClientInfo& client_info,
+ const string& file_path);
+
+ typedef void (*OnClientExitingCallback)(void* context,
+ const ClientInfo& client_info);
+
+ // Create an instance with the given parameters.
+ //
+ // Parameter listen_fd: The server fd created by CreateReportChannel().
+ // Parameter dump_callback: Callback for a client crash dump request.
+ // Parameter dump_context: Context for client crash dump request callback.
+ // Parameter exit_callback: Callback for client process exit.
+ // Parameter exit_context: Context for client exit callback.
+ // Parameter generate_dumps: Whether to automatically generate dumps.
+ // Client code of this class might want to generate dumps explicitly
+ // in the crash dump request callback. In that case, false can be
+ // passed for this parameter.
+ // Parameter dump_path: Path for generating dumps; required only if true is
+ // passed for generateDumps parameter; NULL can be passed otherwise.
+ CrashGenerationServer(const int listen_fd,
+ OnClientDumpRequestCallback dump_callback,
+ void* dump_context,
+ OnClientExitingCallback exit_callback,
+ void* exit_context,
+ bool generate_dumps,
+ const string* dump_path);
+
+ ~CrashGenerationServer();
+
+ // Perform initialization steps needed to start listening to clients.
+ //
+ // Return true if initialization is successful; false otherwise.
+ bool Start();
+
+ // Stop the server.
+ void Stop();
+
+ // Create a "channel" that can be used by clients to report crashes
+ // to a CrashGenerationServer. |*server_fd| should be passed to
+ // this class's constructor, and |*client_fd| should be passed to
+ // the ExceptionHandler constructor in the client process.
+ static bool CreateReportChannel(int* server_fd, int* client_fd);
+
+private:
+ // Run the server's event loop
+ void Run();
+
+ // Invoked when an child process (client) event occurs
+ // Returning true => "keep running", false => "exit loop"
+ bool ClientEvent(short revents);
+
+ // Invoked when the controlling thread (main) event occurs
+ // Returning true => "keep running", false => "exit loop"
+ bool ControlEvent(short revents);
+
+ // Return a unique filename at which a minidump can be written
+ bool MakeMinidumpFilename(string& outFilename);
+
+ // Trampoline to |Run()|
+ static void* ThreadMain(void* arg);
+
+ int server_fd_;
+
+ OnClientDumpRequestCallback dump_callback_;
+ void* dump_context_;
+
+ OnClientExitingCallback exit_callback_;
+ void* exit_context_;
+
+ bool generate_dumps_;
+
+ string dump_dir_;
+
+ bool started_;
+
+ pthread_t thread_;
+ int control_pipe_in_;
+ int control_pipe_out_;
+
+ // disable these
+ CrashGenerationServer(const CrashGenerationServer&);
+ CrashGenerationServer& operator=(const CrashGenerationServer&);
+};
+
+} // namespace google_breakpad
+
+#endif // CLIENT_LINUX_CRASH_GENERATION_CRASH_GENERATION_SERVER_H_
diff --git a/toolkit/crashreporter/breakpad-client/linux/data/linux-gate-amd.sym b/toolkit/crashreporter/breakpad-client/linux/data/linux-gate-amd.sym
new file mode 100644
index 0000000000..e042a5ec42
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/linux/data/linux-gate-amd.sym
@@ -0,0 +1,3 @@
+MODULE Linux x86 B8CFDE93002D54DA1900A40AA1BD67690 linux-gate.so
+PUBLIC 400 0 __kernel_vsyscall
+STACK WIN 4 400 100 1 1 0 0 0 0 0 1
diff --git a/toolkit/crashreporter/breakpad-client/linux/data/linux-gate-intel.sym b/toolkit/crashreporter/breakpad-client/linux/data/linux-gate-intel.sym
new file mode 100644
index 0000000000..c20facaf08
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/linux/data/linux-gate-intel.sym
@@ -0,0 +1,3 @@
+MODULE Linux x86 4FBDA58B5A1DF5A379E3CF19A235EA090 linux-gate.so
+PUBLIC 400 0 __kernel_vsyscall
+STACK WIN 4 400 200 3 3 0 0 0 0 0 1
diff --git a/toolkit/crashreporter/breakpad-client/linux/dump_writer_common/mapping_info.h b/toolkit/crashreporter/breakpad-client/linux/dump_writer_common/mapping_info.h
new file mode 100644
index 0000000000..c358539f58
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/linux/dump_writer_common/mapping_info.h
@@ -0,0 +1,75 @@
+// 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 CLIENT_LINUX_DUMP_WRITER_COMMON_MAPPING_INFO_H_
+#define CLIENT_LINUX_DUMP_WRITER_COMMON_MAPPING_INFO_H_
+
+#include <limits.h>
+#include <list>
+#include <stdint.h>
+#include <vector>
+
+#include "google_breakpad/common/minidump_format.h"
+
+namespace google_breakpad {
+
+// One of these is produced for each mapping in the process (i.e. line in
+// /proc/$x/maps).
+struct MappingInfo {
+ // On Android, relocation packing can mean that the reported start
+ // address of the mapping must be adjusted by a bias in order to
+ // compensate for the compression of the relocation section. The
+ // following two members hold (after LateInit) the adjusted mapping
+ // range. See crbug.com/606972 for more information.
+ uintptr_t start_addr;
+ size_t size;
+ // When Android relocation packing causes |start_addr| and |size| to
+ // be modified with a load bias, we need to remember the unbiased
+ // address range. The following structure holds the original mapping
+ // address range as reported by the operating system.
+ struct {
+ uintptr_t start_addr;
+ uintptr_t end_addr;
+ } system_mapping_info;
+ size_t offset; // offset into the backed file.
+ bool exec; // true if the mapping has the execute bit set.
+ char name[NAME_MAX];
+};
+
+struct MappingEntry {
+ MappingInfo first;
+ std::vector<uint8_t> second;
+};
+
+// A list of <MappingInfo, GUID>
+typedef std::list<MappingEntry> MappingList;
+
+} // namespace google_breakpad
+
+#endif // CLIENT_LINUX_DUMP_WRITER_COMMON_MAPPING_INFO_H_
diff --git a/toolkit/crashreporter/breakpad-client/linux/dump_writer_common/raw_context_cpu.h b/toolkit/crashreporter/breakpad-client/linux/dump_writer_common/raw_context_cpu.h
new file mode 100644
index 0000000000..07d9171a0a
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/linux/dump_writer_common/raw_context_cpu.h
@@ -0,0 +1,53 @@
+// 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 CLIENT_LINUX_DUMP_WRITER_COMMON_RAW_CONTEXT_CPU_H
+#define CLIENT_LINUX_DUMP_WRITER_COMMON_RAW_CONTEXT_CPU_H
+
+#include "google_breakpad/common/minidump_format.h"
+
+namespace google_breakpad {
+
+#if defined(__i386__)
+typedef MDRawContextX86 RawContextCPU;
+#elif defined(__x86_64)
+typedef MDRawContextAMD64 RawContextCPU;
+#elif defined(__ARM_EABI__)
+typedef MDRawContextARM RawContextCPU;
+#elif defined(__aarch64__)
+typedef MDRawContextARM64_Old RawContextCPU;
+#elif defined(__mips__)
+typedef MDRawContextMIPS RawContextCPU;
+#else
+#error "This code has not been ported to your platform yet."
+#endif
+
+} // namespace google_breakpad
+
+#endif // CLIENT_LINUX_DUMP_WRITER_COMMON_RAW_CONTEXT_CPU_H
diff --git a/toolkit/crashreporter/breakpad-client/linux/dump_writer_common/thread_info.cc b/toolkit/crashreporter/breakpad-client/linux/dump_writer_common/thread_info.cc
new file mode 100644
index 0000000000..5d9708c70c
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/linux/dump_writer_common/thread_info.cc
@@ -0,0 +1,305 @@
+// 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 "linux/dump_writer_common/thread_info.h"
+
+#include <string.h>
+#include <assert.h>
+
+#include "common/linux/linux_libc_support.h"
+#include "google_breakpad/common/minidump_format.h"
+
+namespace {
+
+#if defined(__i386__)
+// Write a uint16_t to memory
+// out: memory location to write to
+// v: value to write.
+void U16(void* out, uint16_t v) {
+ my_memcpy(out, &v, sizeof(v));
+}
+
+// Write a uint32_t to memory
+// out: memory location to write to
+// v: value to write.
+void U32(void* out, uint32_t v) {
+ my_memcpy(out, &v, sizeof(v));
+}
+#endif
+
+}
+
+namespace google_breakpad {
+
+#if defined(__i386__)
+
+uintptr_t ThreadInfo::GetInstructionPointer() const {
+ return regs.eip;
+}
+
+void ThreadInfo::FillCPUContext(RawContextCPU* out) const {
+ out->context_flags = MD_CONTEXT_X86_ALL;
+
+ out->dr0 = dregs[0];
+ out->dr1 = dregs[1];
+ out->dr2 = dregs[2];
+ out->dr3 = dregs[3];
+ // 4 and 5 deliberatly omitted because they aren't included in the minidump
+ // format.
+ out->dr6 = dregs[6];
+ out->dr7 = dregs[7];
+
+ out->gs = regs.xgs;
+ out->fs = regs.xfs;
+ out->es = regs.xes;
+ out->ds = regs.xds;
+
+ out->edi = regs.edi;
+ out->esi = regs.esi;
+ out->ebx = regs.ebx;
+ out->edx = regs.edx;
+ out->ecx = regs.ecx;
+ out->eax = regs.eax;
+
+ out->ebp = regs.ebp;
+ out->eip = regs.eip;
+ out->cs = regs.xcs;
+ out->eflags = regs.eflags;
+ out->esp = regs.esp;
+ out->ss = regs.xss;
+
+ out->float_save.control_word = fpregs.cwd;
+ out->float_save.status_word = fpregs.swd;
+ out->float_save.tag_word = fpregs.twd;
+ out->float_save.error_offset = fpregs.fip;
+ out->float_save.error_selector = fpregs.fcs;
+ out->float_save.data_offset = fpregs.foo;
+ out->float_save.data_selector = fpregs.fos;
+
+ // 8 registers * 10 bytes per register.
+ my_memcpy(out->float_save.register_area, fpregs.st_space, 10 * 8);
+
+ // This matches the Intel fpsave format.
+ U16(out->extended_registers + 0, fpregs.cwd);
+ U16(out->extended_registers + 2, fpregs.swd);
+ U16(out->extended_registers + 4, fpregs.twd);
+ U16(out->extended_registers + 6, fpxregs.fop);
+ U32(out->extended_registers + 8, fpxregs.fip);
+ U16(out->extended_registers + 12, fpxregs.fcs);
+ U32(out->extended_registers + 16, fpregs.foo);
+ U16(out->extended_registers + 20, fpregs.fos);
+ U32(out->extended_registers + 24, fpxregs.mxcsr);
+
+ my_memcpy(out->extended_registers + 32, &fpxregs.st_space, 128);
+ my_memcpy(out->extended_registers + 160, &fpxregs.xmm_space, 128);
+}
+
+#elif defined(__x86_64)
+
+uintptr_t ThreadInfo::GetInstructionPointer() const {
+ return regs.rip;
+}
+
+void ThreadInfo::FillCPUContext(RawContextCPU* out) const {
+ out->context_flags = MD_CONTEXT_AMD64_FULL |
+ MD_CONTEXT_AMD64_SEGMENTS;
+
+ out->cs = regs.cs;
+
+ out->ds = regs.ds;
+ out->es = regs.es;
+ out->fs = regs.fs;
+ out->gs = regs.gs;
+
+ out->ss = regs.ss;
+ out->eflags = regs.eflags;
+
+ out->dr0 = dregs[0];
+ out->dr1 = dregs[1];
+ out->dr2 = dregs[2];
+ out->dr3 = dregs[3];
+ // 4 and 5 deliberatly omitted because they aren't included in the minidump
+ // format.
+ out->dr6 = dregs[6];
+ out->dr7 = dregs[7];
+
+ out->rax = regs.rax;
+ out->rcx = regs.rcx;
+ out->rdx = regs.rdx;
+ out->rbx = regs.rbx;
+
+ out->rsp = regs.rsp;
+
+ out->rbp = regs.rbp;
+ out->rsi = regs.rsi;
+ out->rdi = regs.rdi;
+ out->r8 = regs.r8;
+ out->r9 = regs.r9;
+ out->r10 = regs.r10;
+ out->r11 = regs.r11;
+ out->r12 = regs.r12;
+ out->r13 = regs.r13;
+ out->r14 = regs.r14;
+ out->r15 = regs.r15;
+
+ out->rip = regs.rip;
+
+ out->flt_save.control_word = fpregs.cwd;
+ out->flt_save.status_word = fpregs.swd;
+ out->flt_save.tag_word = fpregs.ftw;
+ out->flt_save.error_opcode = fpregs.fop;
+ out->flt_save.error_offset = fpregs.rip;
+ out->flt_save.error_selector = 0; // We don't have this.
+ out->flt_save.data_offset = fpregs.rdp;
+ out->flt_save.data_selector = 0; // We don't have this.
+ out->flt_save.mx_csr = fpregs.mxcsr;
+ out->flt_save.mx_csr_mask = fpregs.mxcr_mask;
+
+ my_memcpy(&out->flt_save.float_registers, &fpregs.st_space, 8 * 16);
+ my_memcpy(&out->flt_save.xmm_registers, &fpregs.xmm_space, 16 * 16);
+}
+
+#elif defined(__ARM_EABI__)
+
+uintptr_t ThreadInfo::GetInstructionPointer() const {
+ return regs.uregs[15];
+}
+
+void ThreadInfo::FillCPUContext(RawContextCPU* out) const {
+ out->context_flags = MD_CONTEXT_ARM_FULL;
+
+ for (int i = 0; i < MD_CONTEXT_ARM_GPR_COUNT; ++i)
+ out->iregs[i] = regs.uregs[i];
+ // No CPSR register in ThreadInfo(it's not accessible via ptrace)
+ out->cpsr = 0;
+#if !defined(__ANDROID__)
+ out->float_save.fpscr = fpregs.fpsr |
+ (static_cast<uint64_t>(fpregs.fpcr) << 32);
+ // TODO: sort this out, actually collect floating point registers
+ my_memset(&out->float_save.regs, 0, sizeof(out->float_save.regs));
+ my_memset(&out->float_save.extra, 0, sizeof(out->float_save.extra));
+#endif
+}
+
+#elif defined(__aarch64__)
+
+uintptr_t ThreadInfo::GetInstructionPointer() const {
+ return regs.pc;
+}
+
+void ThreadInfo::FillCPUContext(RawContextCPU* out) const {
+ out->context_flags = MD_CONTEXT_ARM64_FULL_OLD;
+
+ out->cpsr = static_cast<uint32_t>(regs.pstate);
+ for (int i = 0; i < MD_CONTEXT_ARM64_REG_SP; ++i)
+ out->iregs[i] = regs.regs[i];
+ out->iregs[MD_CONTEXT_ARM64_REG_SP] = regs.sp;
+ out->iregs[MD_CONTEXT_ARM64_REG_PC] = regs.pc;
+
+ out->float_save.fpsr = fpregs.fpsr;
+ out->float_save.fpcr = fpregs.fpcr;
+ my_memcpy(&out->float_save.regs, &fpregs.vregs,
+ MD_FLOATINGSAVEAREA_ARM64_FPR_COUNT * 16);
+}
+
+#elif defined(__mips__)
+
+uintptr_t ThreadInfo::GetInstructionPointer() const {
+ return mcontext.pc;
+}
+
+void ThreadInfo::FillCPUContext(RawContextCPU* out) const {
+#if _MIPS_SIM == _ABI64
+ out->context_flags = MD_CONTEXT_MIPS64_FULL;
+#elif _MIPS_SIM == _ABIO32
+ out->context_flags = MD_CONTEXT_MIPS_FULL;
+#else
+# error "This mips ABI is currently not supported (n32)"
+#endif
+
+ for (int i = 0; i < MD_CONTEXT_MIPS_GPR_COUNT; ++i)
+ out->iregs[i] = mcontext.gregs[i];
+
+ out->mdhi = mcontext.mdhi;
+ out->mdlo = mcontext.mdlo;
+ out->dsp_control = mcontext.dsp;
+
+ out->hi[0] = mcontext.hi1;
+ out->lo[0] = mcontext.lo1;
+ out->hi[1] = mcontext.hi2;
+ out->lo[1] = mcontext.lo2;
+ out->hi[2] = mcontext.hi3;
+ out->lo[2] = mcontext.lo3;
+
+ out->epc = mcontext.pc;
+ out->badvaddr = 0; // Not stored in mcontext
+ out->status = 0; // Not stored in mcontext
+ out->cause = 0; // Not stored in mcontext
+
+ for (int i = 0; i < MD_FLOATINGSAVEAREA_MIPS_FPR_COUNT; ++i)
+ out->float_save.regs[i] = mcontext.fpregs.fp_r.fp_fregs[i]._fp_fregs;
+
+ out->float_save.fpcsr = mcontext.fpc_csr;
+#if _MIPS_SIM == _ABIO32
+ out->float_save.fir = mcontext.fpc_eir;
+#endif
+}
+#endif // __mips__
+
+void ThreadInfo::GetGeneralPurposeRegisters(void** gp_regs, size_t* size) {
+ assert(gp_regs || size);
+#if defined(__mips__)
+ if (gp_regs)
+ *gp_regs = mcontext.gregs;
+ if (size)
+ *size = sizeof(mcontext.gregs);
+#else
+ if (gp_regs)
+ *gp_regs = &regs;
+ if (size)
+ *size = sizeof(regs);
+#endif
+}
+
+void ThreadInfo::GetFloatingPointRegisters(void** fp_regs, size_t* size) {
+ assert(fp_regs || size);
+#if defined(__mips__)
+ if (fp_regs)
+ *fp_regs = &mcontext.fpregs;
+ if (size)
+ *size = sizeof(mcontext.fpregs);
+#else
+ if (fp_regs)
+ *fp_regs = &fpregs;
+ if (size)
+ *size = sizeof(fpregs);
+#endif
+}
+
+} // namespace google_breakpad
diff --git a/toolkit/crashreporter/breakpad-client/linux/dump_writer_common/thread_info.h b/toolkit/crashreporter/breakpad-client/linux/dump_writer_common/thread_info.h
new file mode 100644
index 0000000000..4173d239c4
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/linux/dump_writer_common/thread_info.h
@@ -0,0 +1,91 @@
+// 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 CLIENT_LINUX_DUMP_WRITER_COMMON_THREAD_INFO_H_
+#define CLIENT_LINUX_DUMP_WRITER_COMMON_THREAD_INFO_H_
+
+#include <sys/ucontext.h>
+#include <sys/user.h>
+
+#include "linux/dump_writer_common/raw_context_cpu.h"
+#include "common/memory_allocator.h"
+#include "google_breakpad/common/minidump_format.h"
+
+namespace google_breakpad {
+
+#if defined(__i386) || defined(__x86_64)
+typedef __typeof__(((struct user*) 0)->u_debugreg[0]) debugreg_t;
+#endif
+
+// We produce one of these structures for each thread in the crashed process.
+struct ThreadInfo {
+ pid_t tgid; // thread group id
+ pid_t ppid; // parent process
+
+ uintptr_t stack_pointer; // thread stack pointer
+
+
+#if defined(__i386) || defined(__x86_64)
+ user_regs_struct regs;
+ user_fpregs_struct fpregs;
+ static const unsigned kNumDebugRegisters = 8;
+ debugreg_t dregs[8];
+#if defined(__i386)
+ user_fpxregs_struct fpxregs;
+#endif // defined(__i386)
+
+#elif defined(__ARM_EABI__)
+ // Mimicking how strace does this(see syscall.c, search for GETREGS)
+ struct user_regs regs;
+ struct user_fpregs fpregs;
+#elif defined(__aarch64__)
+ // Use the structures defined in <sys/user.h>
+ struct user_regs_struct regs;
+ struct user_fpsimd_struct fpregs;
+#elif defined(__mips__)
+ // Use the structure defined in <sys/ucontext.h>.
+ mcontext_t mcontext;
+#endif
+
+ // Returns the instruction pointer (platform-dependent impl.).
+ uintptr_t GetInstructionPointer() const;
+
+ // Fills a RawContextCPU using the context in the ThreadInfo object.
+ void FillCPUContext(RawContextCPU* out) const;
+
+ // Returns the pointer and size of general purpose register area.
+ void GetGeneralPurposeRegisters(void** gp_regs, size_t* size);
+
+ // Returns the pointer and size of float point register area.
+ void GetFloatingPointRegisters(void** fp_regs, size_t* size);
+};
+
+} // namespace google_breakpad
+
+#endif // CLIENT_LINUX_DUMP_WRITER_COMMON_THREAD_INFO_H_
diff --git a/toolkit/crashreporter/breakpad-client/linux/dump_writer_common/ucontext_reader.cc b/toolkit/crashreporter/breakpad-client/linux/dump_writer_common/ucontext_reader.cc
new file mode 100644
index 0000000000..5145ede3d8
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/linux/dump_writer_common/ucontext_reader.cc
@@ -0,0 +1,259 @@
+// 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 "linux/dump_writer_common/ucontext_reader.h"
+
+#include "common/linux/linux_libc_support.h"
+#include "google_breakpad/common/minidump_format.h"
+
+namespace google_breakpad {
+
+// Minidump defines register structures which are different from the raw
+// structures which we get from the kernel. These are platform specific
+// functions to juggle the ucontext_t and user structures into minidump format.
+
+#if defined(__i386__)
+
+uintptr_t UContextReader::GetStackPointer(const ucontext_t* uc) {
+ return uc->uc_mcontext.gregs[REG_ESP];
+}
+
+uintptr_t UContextReader::GetInstructionPointer(const ucontext_t* uc) {
+ return uc->uc_mcontext.gregs[REG_EIP];
+}
+
+void UContextReader::FillCPUContext(RawContextCPU *out, const ucontext_t *uc,
+ const fpstate_t* fp) {
+ const greg_t* regs = uc->uc_mcontext.gregs;
+
+ out->context_flags = MD_CONTEXT_X86_FULL |
+ MD_CONTEXT_X86_FLOATING_POINT;
+
+ out->gs = regs[REG_GS];
+ out->fs = regs[REG_FS];
+ out->es = regs[REG_ES];
+ out->ds = regs[REG_DS];
+
+ out->edi = regs[REG_EDI];
+ out->esi = regs[REG_ESI];
+ out->ebx = regs[REG_EBX];
+ out->edx = regs[REG_EDX];
+ out->ecx = regs[REG_ECX];
+ out->eax = regs[REG_EAX];
+
+ out->ebp = regs[REG_EBP];
+ out->eip = regs[REG_EIP];
+ out->cs = regs[REG_CS];
+ out->eflags = regs[REG_EFL];
+ out->esp = regs[REG_UESP];
+ out->ss = regs[REG_SS];
+
+ out->float_save.control_word = fp->cw;
+ out->float_save.status_word = fp->sw;
+ out->float_save.tag_word = fp->tag;
+ out->float_save.error_offset = fp->ipoff;
+ out->float_save.error_selector = fp->cssel;
+ out->float_save.data_offset = fp->dataoff;
+ out->float_save.data_selector = fp->datasel;
+
+ // 8 registers * 10 bytes per register.
+ my_memcpy(out->float_save.register_area, fp->_st, 10 * 8);
+}
+
+#elif defined(__x86_64)
+
+uintptr_t UContextReader::GetStackPointer(const ucontext_t* uc) {
+ return uc->uc_mcontext.gregs[REG_RSP];
+}
+
+uintptr_t UContextReader::GetInstructionPointer(const ucontext_t* uc) {
+ return uc->uc_mcontext.gregs[REG_RIP];
+}
+
+void UContextReader::FillCPUContext(RawContextCPU *out, const ucontext_t *uc,
+ const fpstate_t* fpregs) {
+ const greg_t* regs = uc->uc_mcontext.gregs;
+
+ out->context_flags = MD_CONTEXT_AMD64_FULL;
+
+ out->cs = regs[REG_CSGSFS] & 0xffff;
+
+ out->fs = (regs[REG_CSGSFS] >> 32) & 0xffff;
+ out->gs = (regs[REG_CSGSFS] >> 16) & 0xffff;
+
+ out->eflags = regs[REG_EFL];
+
+ out->rax = regs[REG_RAX];
+ out->rcx = regs[REG_RCX];
+ out->rdx = regs[REG_RDX];
+ out->rbx = regs[REG_RBX];
+
+ out->rsp = regs[REG_RSP];
+ out->rbp = regs[REG_RBP];
+ out->rsi = regs[REG_RSI];
+ out->rdi = regs[REG_RDI];
+ out->r8 = regs[REG_R8];
+ out->r9 = regs[REG_R9];
+ out->r10 = regs[REG_R10];
+ out->r11 = regs[REG_R11];
+ out->r12 = regs[REG_R12];
+ out->r13 = regs[REG_R13];
+ out->r14 = regs[REG_R14];
+ out->r15 = regs[REG_R15];
+
+ out->rip = regs[REG_RIP];
+
+ out->flt_save.control_word = fpregs->cwd;
+ out->flt_save.status_word = fpregs->swd;
+ out->flt_save.tag_word = fpregs->ftw;
+ out->flt_save.error_opcode = fpregs->fop;
+ out->flt_save.error_offset = fpregs->rip;
+ out->flt_save.data_offset = fpregs->rdp;
+ out->flt_save.error_selector = 0; // We don't have this.
+ out->flt_save.data_selector = 0; // We don't have this.
+ out->flt_save.mx_csr = fpregs->mxcsr;
+ out->flt_save.mx_csr_mask = fpregs->mxcr_mask;
+ my_memcpy(&out->flt_save.float_registers, &fpregs->_st, 8 * 16);
+ my_memcpy(&out->flt_save.xmm_registers, &fpregs->_xmm, 16 * 16);
+}
+
+#elif defined(__ARM_EABI__)
+
+uintptr_t UContextReader::GetStackPointer(const ucontext_t* uc) {
+ return uc->uc_mcontext.arm_sp;
+}
+
+uintptr_t UContextReader::GetInstructionPointer(const ucontext_t* uc) {
+ return uc->uc_mcontext.arm_pc;
+}
+
+void UContextReader::FillCPUContext(RawContextCPU *out, const ucontext_t *uc) {
+ out->context_flags = MD_CONTEXT_ARM_FULL;
+
+ out->iregs[0] = uc->uc_mcontext.arm_r0;
+ out->iregs[1] = uc->uc_mcontext.arm_r1;
+ out->iregs[2] = uc->uc_mcontext.arm_r2;
+ out->iregs[3] = uc->uc_mcontext.arm_r3;
+ out->iregs[4] = uc->uc_mcontext.arm_r4;
+ out->iregs[5] = uc->uc_mcontext.arm_r5;
+ out->iregs[6] = uc->uc_mcontext.arm_r6;
+ out->iregs[7] = uc->uc_mcontext.arm_r7;
+ out->iregs[8] = uc->uc_mcontext.arm_r8;
+ out->iregs[9] = uc->uc_mcontext.arm_r9;
+ out->iregs[10] = uc->uc_mcontext.arm_r10;
+
+ out->iregs[11] = uc->uc_mcontext.arm_fp;
+ out->iregs[12] = uc->uc_mcontext.arm_ip;
+ out->iregs[13] = uc->uc_mcontext.arm_sp;
+ out->iregs[14] = uc->uc_mcontext.arm_lr;
+ out->iregs[15] = uc->uc_mcontext.arm_pc;
+
+ out->cpsr = uc->uc_mcontext.arm_cpsr;
+
+ // TODO: fix this after fixing ExceptionHandler
+ out->float_save.fpscr = 0;
+ my_memset(&out->float_save.regs, 0, sizeof(out->float_save.regs));
+ my_memset(&out->float_save.extra, 0, sizeof(out->float_save.extra));
+}
+
+#elif defined(__aarch64__)
+
+uintptr_t UContextReader::GetStackPointer(const ucontext_t* uc) {
+ return uc->uc_mcontext.sp;
+}
+
+uintptr_t UContextReader::GetInstructionPointer(const ucontext_t* uc) {
+ return uc->uc_mcontext.pc;
+}
+
+void UContextReader::FillCPUContext(RawContextCPU *out, const ucontext_t *uc,
+ const struct fpsimd_context* fpregs) {
+ out->context_flags = MD_CONTEXT_ARM64_FULL_OLD;
+
+ out->cpsr = static_cast<uint32_t>(uc->uc_mcontext.pstate);
+ for (int i = 0; i < MD_CONTEXT_ARM64_REG_SP; ++i)
+ out->iregs[i] = uc->uc_mcontext.regs[i];
+ out->iregs[MD_CONTEXT_ARM64_REG_SP] = uc->uc_mcontext.sp;
+ out->iregs[MD_CONTEXT_ARM64_REG_PC] = uc->uc_mcontext.pc;
+
+ out->float_save.fpsr = fpregs->fpsr;
+ out->float_save.fpcr = fpregs->fpcr;
+ my_memcpy(&out->float_save.regs, &fpregs->vregs,
+ MD_FLOATINGSAVEAREA_ARM64_FPR_COUNT * 16);
+}
+
+#elif defined(__mips__)
+
+uintptr_t UContextReader::GetStackPointer(const ucontext_t* uc) {
+ return uc->uc_mcontext.gregs[MD_CONTEXT_MIPS_REG_SP];
+}
+
+uintptr_t UContextReader::GetInstructionPointer(const ucontext_t* uc) {
+ return uc->uc_mcontext.pc;
+}
+
+void UContextReader::FillCPUContext(RawContextCPU *out, const ucontext_t *uc) {
+#if _MIPS_SIM == _ABI64
+ out->context_flags = MD_CONTEXT_MIPS64_FULL;
+#elif _MIPS_SIM == _ABIO32
+ out->context_flags = MD_CONTEXT_MIPS_FULL;
+#else
+#error "This mips ABI is currently not supported (n32)"
+#endif
+
+ for (int i = 0; i < MD_CONTEXT_MIPS_GPR_COUNT; ++i)
+ out->iregs[i] = uc->uc_mcontext.gregs[i];
+
+ out->mdhi = uc->uc_mcontext.mdhi;
+ out->mdlo = uc->uc_mcontext.mdlo;
+
+ out->hi[0] = uc->uc_mcontext.hi1;
+ out->hi[1] = uc->uc_mcontext.hi2;
+ out->hi[2] = uc->uc_mcontext.hi3;
+ out->lo[0] = uc->uc_mcontext.lo1;
+ out->lo[1] = uc->uc_mcontext.lo2;
+ out->lo[2] = uc->uc_mcontext.lo3;
+ out->dsp_control = uc->uc_mcontext.dsp;
+
+ out->epc = uc->uc_mcontext.pc;
+ out->badvaddr = 0; // Not reported in signal context.
+ out->status = 0; // Not reported in signal context.
+ out->cause = 0; // Not reported in signal context.
+
+ for (int i = 0; i < MD_FLOATINGSAVEAREA_MIPS_FPR_COUNT; ++i)
+ out->float_save.regs[i] = uc->uc_mcontext.fpregs.fp_r.fp_dregs[i];
+
+ out->float_save.fpcsr = uc->uc_mcontext.fpc_csr;
+#if _MIPS_SIM == _ABIO32
+ out->float_save.fir = uc->uc_mcontext.fpc_eir; // Unused.
+#endif
+}
+#endif
+
+} // namespace google_breakpad
diff --git a/toolkit/crashreporter/breakpad-client/linux/dump_writer_common/ucontext_reader.h b/toolkit/crashreporter/breakpad-client/linux/dump_writer_common/ucontext_reader.h
new file mode 100644
index 0000000000..390520be41
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/linux/dump_writer_common/ucontext_reader.h
@@ -0,0 +1,65 @@
+// 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 CLIENT_LINUX_DUMP_WRITER_COMMON_UCONTEXT_READER_H
+#define CLIENT_LINUX_DUMP_WRITER_COMMON_UCONTEXT_READER_H
+
+#include <sys/ucontext.h>
+#include <sys/user.h>
+
+#include "linux/dump_writer_common/raw_context_cpu.h"
+#include "linux/minidump_writer/minidump_writer.h"
+#include "common/memory_allocator.h"
+#include "google_breakpad/common/minidump_format.h"
+
+namespace google_breakpad {
+
+// Wraps platform-dependent implementations of accessors to ucontext_t structs.
+struct UContextReader {
+ static uintptr_t GetStackPointer(const ucontext_t* uc);
+
+ static uintptr_t GetInstructionPointer(const ucontext_t* uc);
+
+ // Juggle a arch-specific ucontext into a minidump format
+ // out: the minidump structure
+ // info: the collection of register structures.
+#if defined(__i386__) || defined(__x86_64)
+ static void FillCPUContext(RawContextCPU *out, const ucontext_t *uc,
+ const fpstate_t* fp);
+#elif defined(__aarch64__)
+ static void FillCPUContext(RawContextCPU *out, const ucontext_t *uc,
+ const struct fpsimd_context* fpregs);
+#else
+ static void FillCPUContext(RawContextCPU *out, const ucontext_t *uc);
+#endif
+};
+
+} // namespace google_breakpad
+
+#endif // CLIENT_LINUX_DUMP_WRITER_COMMON_UCONTEXT_READER_H
diff --git a/toolkit/crashreporter/breakpad-client/linux/handler/exception_handler.cc b/toolkit/crashreporter/breakpad-client/linux/handler/exception_handler.cc
new file mode 100644
index 0000000000..ab17661ad7
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/linux/handler/exception_handler.cc
@@ -0,0 +1,875 @@
+// 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.
+
+// The ExceptionHandler object installs signal handlers for a number of
+// signals. We rely on the signal handler running on the thread which crashed
+// in order to identify it. This is true of the synchronous signals (SEGV etc),
+// but not true of ABRT. Thus, if you send ABRT to yourself in a program which
+// uses ExceptionHandler, you need to use tgkill to direct it to the current
+// thread.
+//
+// The signal flow looks like this:
+//
+// SignalHandler (uses a global stack of ExceptionHandler objects to find
+// | one to handle the signal. If the first rejects it, try
+// | the second etc...)
+// V
+// HandleSignal ----------------------------| (clones a new process which
+// | | shares an address space with
+// (wait for cloned | the crashed process. This
+// process) | allows us to ptrace the crashed
+// | | process)
+// V V
+// (set signal handler to ThreadEntry (static function to bounce
+// SIG_DFL and rethrow, | back into the object)
+// killing the crashed |
+// process) V
+// DoDump (writes minidump)
+// |
+// V
+// sys_exit
+//
+
+// This code is a little fragmented. Different functions of the ExceptionHandler
+// class run in a number of different contexts. Some of them run in a normal
+// context and are easy to code, others run in a compromised context and the
+// restrictions at the top of minidump_writer.cc apply: no libc and use the
+// alternative malloc. Each function should have comment above it detailing the
+// context which it runs in.
+
+#include "linux/handler/exception_handler.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <linux/limits.h>
+#include <pthread.h>
+#include <sched.h>
+#include <signal.h>
+#include <stdio.h>
+#include <sys/mman.h>
+#include <sys/prctl.h>
+#include <sys/syscall.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include <sys/ucontext.h>
+#include <sys/user.h>
+#include <ucontext.h>
+
+#include <algorithm>
+#include <utility>
+#include <vector>
+
+#include "common/basictypes.h"
+#include "common/linux/breakpad_getcontext.h"
+#include "common/linux/linux_libc_support.h"
+#include "common/memory_allocator.h"
+#include "linux/log/log.h"
+#include "linux/microdump_writer/microdump_writer.h"
+#include "linux/minidump_writer/linux_dumper.h"
+#include "linux/minidump_writer/minidump_writer.h"
+#include "common/linux/eintr_wrapper.h"
+#include "third_party/lss/linux_syscall_support.h"
+#if defined(MOZ_OXIDIZED_BREAKPAD)
+#include "nsString.h"
+#include "mozilla/toolkit/crashreporter/rust_minidump_writer_linux_ffi_generated.h"
+#endif
+
+#ifdef MOZ_PHC
+#include "replace_malloc_bridge.h"
+#endif
+
+#if defined(__ANDROID__)
+#include "linux/sched.h"
+#endif
+
+#ifndef PR_SET_PTRACER
+#define PR_SET_PTRACER 0x59616d61
+#endif
+
+#define SKIP_SIGILL(sig) if (g_skip_sigill_ && (sig == SIGILL)) continue;
+
+namespace google_breakpad {
+
+namespace {
+// The list of signals which we consider to be crashes. The default action for
+// all these signals must be Core (see man 7 signal) because we rethrow the
+// signal after handling it and expect that it'll be fatal.
+const int kExceptionSignals[] = {
+ SIGSEGV, SIGABRT, SIGFPE, SIGILL, SIGBUS, SIGTRAP
+};
+const int kNumHandledSignals =
+ sizeof(kExceptionSignals) / sizeof(kExceptionSignals[0]);
+struct sigaction old_handlers[kNumHandledSignals];
+bool handlers_installed = false;
+
+// InstallAlternateStackLocked will store the newly installed stack in new_stack
+// and (if it exists) the previously installed stack in old_stack.
+stack_t old_stack;
+stack_t new_stack;
+bool stack_installed = false;
+
+// Create an alternative stack to run the signal handlers on. This is done since
+// the signal might have been caused by a stack overflow.
+// Runs before crashing: normal context.
+void InstallAlternateStackLocked() {
+ if (stack_installed)
+ return;
+
+ memset(&old_stack, 0, sizeof(old_stack));
+ memset(&new_stack, 0, sizeof(new_stack));
+
+ // SIGSTKSZ may be too small to prevent the signal handlers from overrunning
+ // the alternative stack. Ensure that the size of the alternative stack is
+ // large enough.
+ static const size_t kSigStackSize = std::max(size_t(16384), size_t(SIGSTKSZ));
+
+ // Only set an alternative stack if there isn't already one, or if the current
+ // one is too small.
+ if (sys_sigaltstack(NULL, &old_stack) == -1 || !old_stack.ss_sp ||
+ old_stack.ss_size < kSigStackSize) {
+ new_stack.ss_sp = calloc(1, kSigStackSize);
+ new_stack.ss_size = kSigStackSize;
+
+ if (sys_sigaltstack(&new_stack, NULL) == -1) {
+ free(new_stack.ss_sp);
+ return;
+ }
+ stack_installed = true;
+ }
+}
+
+// Runs before crashing: normal context.
+void RestoreAlternateStackLocked() {
+ if (!stack_installed)
+ return;
+
+ stack_t current_stack;
+ if (sys_sigaltstack(NULL, &current_stack) == -1)
+ return;
+
+ // Only restore the old_stack if the current alternative stack is the one
+ // installed by the call to InstallAlternateStackLocked.
+ if (current_stack.ss_sp == new_stack.ss_sp) {
+ if (old_stack.ss_sp) {
+ if (sys_sigaltstack(&old_stack, NULL) == -1)
+ return;
+ } else {
+ stack_t disable_stack;
+ disable_stack.ss_flags = SS_DISABLE;
+ if (sys_sigaltstack(&disable_stack, NULL) == -1)
+ return;
+ }
+ }
+
+ free(new_stack.ss_sp);
+ stack_installed = false;
+}
+
+void InstallDefaultHandler(int sig) {
+#if defined(__ANDROID__)
+ // Android L+ expose signal and sigaction symbols that override the system
+ // ones. There is a bug in these functions where a request to set the handler
+ // to SIG_DFL is ignored. In that case, an infinite loop is entered as the
+ // signal is repeatedly sent to breakpad's signal handler.
+ // To work around this, directly call the system's sigaction.
+ struct kernel_sigaction sa;
+ memset(&sa, 0, sizeof(sa));
+ sys_sigemptyset(&sa.sa_mask);
+ sa.sa_handler_ = SIG_DFL;
+ sa.sa_flags = SA_RESTART;
+ sys_rt_sigaction(sig, &sa, NULL, sizeof(kernel_sigset_t));
+#else
+ signal(sig, SIG_DFL);
+#endif
+}
+
+// The global exception handler stack. This is needed because there may exist
+// multiple ExceptionHandler instances in a process. Each will have itself
+// registered in this stack.
+std::vector<ExceptionHandler*>* g_handler_stack_ = NULL;
+pthread_mutex_t g_handler_stack_mutex_ = PTHREAD_MUTEX_INITIALIZER;
+
+// sizeof(CrashContext) can be too big w.r.t the size of alternatate stack
+// for SignalHandler(). Keep the crash context as a .bss field. Exception
+// handlers are serialized by the |g_handler_stack_mutex_| and at most one at a
+// time can use |g_crash_context_|.
+ExceptionHandler::CrashContext g_crash_context_;
+
+FirstChanceHandler g_first_chance_handler_ = nullptr;
+bool g_skip_sigill_ = false;
+} // namespace
+
+// Runs before crashing: normal context.
+ExceptionHandler::ExceptionHandler(const MinidumpDescriptor& descriptor,
+ FilterCallback filter,
+ MinidumpCallback callback,
+ void* callback_context,
+ bool install_handler,
+ const int server_fd)
+ : filter_(filter),
+ callback_(callback),
+ callback_context_(callback_context),
+ minidump_descriptor_(descriptor),
+ crash_handler_(NULL) {
+
+ g_skip_sigill_ = getenv("MOZ_DISABLE_EXCEPTION_HANDLER_SIGILL") ? true : false;
+ if (server_fd >= 0)
+ crash_generation_client_.reset(CrashGenerationClient::TryCreate(server_fd));
+
+ if (!IsOutOfProcess() && !minidump_descriptor_.IsFD() &&
+ !minidump_descriptor_.IsMicrodumpOnConsole())
+ minidump_descriptor_.UpdatePath();
+
+#if defined(__ANDROID__)
+ if (minidump_descriptor_.IsMicrodumpOnConsole())
+ logger::initializeCrashLogWriter();
+#endif
+
+ pthread_mutex_lock(&g_handler_stack_mutex_);
+
+ // Pre-fault the crash context struct. This is to avoid failing due to OOM
+ // if handling an exception when the process ran out of virtual memory.
+ memset(&g_crash_context_, 0, sizeof(g_crash_context_));
+
+ if (!g_handler_stack_)
+ g_handler_stack_ = new std::vector<ExceptionHandler*>;
+ if (install_handler) {
+ InstallAlternateStackLocked();
+ InstallHandlersLocked();
+ }
+ g_handler_stack_->push_back(this);
+ pthread_mutex_unlock(&g_handler_stack_mutex_);
+}
+
+// Runs before crashing: normal context.
+ExceptionHandler::~ExceptionHandler() {
+ pthread_mutex_lock(&g_handler_stack_mutex_);
+ std::vector<ExceptionHandler*>::iterator handler =
+ std::find(g_handler_stack_->begin(), g_handler_stack_->end(), this);
+ g_handler_stack_->erase(handler);
+ if (g_handler_stack_->empty()) {
+ delete g_handler_stack_;
+ g_handler_stack_ = NULL;
+ RestoreAlternateStackLocked();
+ RestoreHandlersLocked();
+ }
+ pthread_mutex_unlock(&g_handler_stack_mutex_);
+}
+
+// Runs before crashing: normal context.
+// static
+bool ExceptionHandler::InstallHandlersLocked() {
+ if (handlers_installed)
+ return false;
+
+ // Fail if unable to store all the old handlers.
+ for (int i = 0; i < kNumHandledSignals; ++i) {
+ SKIP_SIGILL(kExceptionSignals[i]);
+ if (sigaction(kExceptionSignals[i], NULL, &old_handlers[i]) == -1)
+ return false;
+ }
+
+ struct sigaction sa;
+ memset(&sa, 0, sizeof(sa));
+ sigemptyset(&sa.sa_mask);
+
+ // Mask all exception signals when we're handling one of them.
+ for (int i = 0; i < kNumHandledSignals; ++i) {
+ SKIP_SIGILL(kExceptionSignals[i]);
+ sigaddset(&sa.sa_mask, kExceptionSignals[i]);
+ }
+
+ sa.sa_sigaction = SignalHandler;
+ sa.sa_flags = SA_ONSTACK | SA_SIGINFO;
+
+ for (int i = 0; i < kNumHandledSignals; ++i) {
+ SKIP_SIGILL(kExceptionSignals[i]);
+ if (sigaction(kExceptionSignals[i], &sa, NULL) == -1) {
+ // At this point it is impractical to back out changes, and so failure to
+ // install a signal is intentionally ignored.
+ }
+ }
+ handlers_installed = true;
+ return true;
+}
+
+// This function runs in a compromised context: see the top of the file.
+// Runs on the crashing thread.
+// static
+void ExceptionHandler::RestoreHandlersLocked() {
+ if (!handlers_installed)
+ return;
+
+ for (int i = 0; i < kNumHandledSignals; ++i) {
+ SKIP_SIGILL(kExceptionSignals[i]);
+ if (sigaction(kExceptionSignals[i], &old_handlers[i], NULL) == -1) {
+ InstallDefaultHandler(kExceptionSignals[i]);
+ }
+ }
+ handlers_installed = false;
+}
+
+// void ExceptionHandler::set_crash_handler(HandlerCallback callback) {
+// crash_handler_ = callback;
+// }
+
+// This function runs in a compromised context: see the top of the file.
+// Runs on the crashing thread.
+// static
+void ExceptionHandler::SignalHandler(int sig, siginfo_t* info, void* uc) {
+
+ // Give the first chance handler a chance to recover from this signal
+ //
+ // This is primarily used by V8. V8 uses guard regions to guarantee memory
+ // safety in WebAssembly. This means some signals might be expected if they
+ // originate from Wasm code while accessing the guard region. We give V8 the
+ // chance to handle and recover from these signals first.
+ if (g_first_chance_handler_ != nullptr &&
+ g_first_chance_handler_(sig, info, uc)) {
+ return;
+ }
+
+ // All the exception signals are blocked at this point.
+ pthread_mutex_lock(&g_handler_stack_mutex_);
+
+ // Sometimes, Breakpad runs inside a process where some other buggy code
+ // saves and restores signal handlers temporarily with 'signal'
+ // instead of 'sigaction'. This loses the SA_SIGINFO flag associated
+ // with this function. As a consequence, the values of 'info' and 'uc'
+ // become totally bogus, generally inducing a crash.
+ //
+ // The following code tries to detect this case. When it does, it
+ // resets the signal handlers with sigaction + SA_SIGINFO and returns.
+ // This forces the signal to be thrown again, but this time the kernel
+ // will call the function with the right arguments.
+ struct sigaction cur_handler;
+ if (sigaction(sig, NULL, &cur_handler) == 0 &&
+ cur_handler.sa_sigaction == SignalHandler &&
+ (cur_handler.sa_flags & SA_SIGINFO) == 0) {
+ // Reset signal handler with the right flags.
+ sigemptyset(&cur_handler.sa_mask);
+ sigaddset(&cur_handler.sa_mask, sig);
+
+ cur_handler.sa_sigaction = SignalHandler;
+ cur_handler.sa_flags = SA_ONSTACK | SA_SIGINFO;
+
+ if (sigaction(sig, &cur_handler, NULL) == -1) {
+ // When resetting the handler fails, try to reset the
+ // default one to avoid an infinite loop here.
+ InstallDefaultHandler(sig);
+ }
+ pthread_mutex_unlock(&g_handler_stack_mutex_);
+ return;
+ }
+
+ bool handled = false;
+ for (int i = g_handler_stack_->size() - 1; !handled && i >= 0; --i) {
+ handled = (*g_handler_stack_)[i]->HandleSignal(sig, info, uc);
+ }
+
+ // Upon returning from this signal handler, sig will become unmasked and then
+ // it will be retriggered. If one of the ExceptionHandlers handled it
+ // successfully, restore the default handler. Otherwise, restore the
+ // previously installed handler. Then, when the signal is retriggered, it will
+ // be delivered to the appropriate handler.
+ if (handled) {
+ InstallDefaultHandler(sig);
+ } else {
+ RestoreHandlersLocked();
+ }
+
+ pthread_mutex_unlock(&g_handler_stack_mutex_);
+
+ // info->si_code <= 0 iff SI_FROMUSER (SI_FROMKERNEL otherwise).
+ if (info->si_code <= 0 || sig == SIGABRT) {
+ // This signal was triggered by somebody sending us the signal with kill().
+ // In order to retrigger it, we have to queue a new signal by calling
+ // kill() ourselves. The special case (si_pid == 0 && sig == SIGABRT) is
+ // due to the kernel sending a SIGABRT from a user request via SysRQ.
+ if (sys_tgkill(getpid(), syscall(__NR_gettid), sig) < 0) {
+ // If we failed to kill ourselves (e.g. because a sandbox disallows us
+ // to do so), we instead resort to terminating our process. This will
+ // result in an incorrect exit code.
+ _exit(1);
+ }
+ } else {
+ // This was a synchronous signal triggered by a hard fault (e.g. SIGSEGV).
+ // No need to reissue the signal. It will automatically trigger again,
+ // when we return from the signal handler.
+ }
+}
+
+struct ThreadArgument {
+ pid_t pid; // the crashing process
+ const MinidumpDescriptor* minidump_descriptor;
+ ExceptionHandler* handler;
+ const void* context; // a CrashContext structure
+ size_t context_size;
+};
+
+// This is the entry function for the cloned process. We are in a compromised
+// context here: see the top of the file.
+// static
+int ExceptionHandler::ThreadEntry(void *arg) {
+ const ThreadArgument *thread_arg = reinterpret_cast<ThreadArgument*>(arg);
+
+ // Close the write end of the pipe. This allows us to fail if the parent dies
+ // while waiting for the continue signal.
+ sys_close(thread_arg->handler->fdes[1]);
+
+ // Block here until the crashing process unblocks us when
+ // we're allowed to use ptrace
+ thread_arg->handler->WaitForContinueSignal();
+ sys_close(thread_arg->handler->fdes[0]);
+
+ return thread_arg->handler->DoDump(thread_arg->pid, thread_arg->context,
+ thread_arg->context_size) == false;
+}
+
+#ifdef MOZ_PHC
+static void GetPHCAddrInfo(siginfo_t* siginfo,
+ mozilla::phc::AddrInfo* addr_info) {
+ // Is this a crash involving a PHC allocation?
+ if (siginfo->si_signo == SIGSEGV || siginfo->si_signo == SIGBUS) {
+ ReplaceMalloc::IsPHCAllocation(siginfo->si_addr, addr_info);
+ }
+}
+#endif
+
+// This function runs in a compromised context: see the top of the file.
+// Runs on the crashing thread.
+bool ExceptionHandler::HandleSignal(int /*sig*/, siginfo_t* info, void* uc) {
+ mozilla::phc::AddrInfo addr_info;
+#ifdef MOZ_PHC
+ GetPHCAddrInfo(info, &addr_info);
+#endif
+
+ if (filter_ && !filter_(callback_context_))
+ return false;
+
+ // Allow ourselves to be dumped if the signal is trusted.
+ bool signal_trusted = info->si_code > 0;
+ bool signal_pid_trusted = info->si_code == SI_USER ||
+ info->si_code == SI_TKILL;
+ if (signal_trusted || (signal_pid_trusted && info->si_pid == getpid())) {
+ sys_prctl(PR_SET_DUMPABLE, 1, 0, 0, 0);
+ }
+
+ // Fill in all the holes in the struct to make Valgrind happy.
+ memset(&g_crash_context_, 0, sizeof(g_crash_context_));
+ memcpy(&g_crash_context_.siginfo, info, sizeof(siginfo_t));
+ memcpy(&g_crash_context_.context, uc, sizeof(ucontext_t));
+#if defined(__aarch64__)
+ ucontext_t* uc_ptr = (ucontext_t*)uc;
+ struct fpsimd_context* fp_ptr =
+ (struct fpsimd_context*)&uc_ptr->uc_mcontext.__reserved;
+ if (fp_ptr->head.magic == FPSIMD_MAGIC) {
+ memcpy(&g_crash_context_.float_state, fp_ptr,
+ sizeof(g_crash_context_.float_state));
+ }
+#elif !defined(__ARM_EABI__) && !defined(__mips__)
+ // FP state is not part of user ABI on ARM Linux.
+ // In case of MIPS Linux FP state is already part of ucontext_t
+ // and 'float_state' is not a member of CrashContext.
+ ucontext_t* uc_ptr = (ucontext_t*)uc;
+ if (uc_ptr->uc_mcontext.fpregs) {
+ memcpy(&g_crash_context_.float_state, uc_ptr->uc_mcontext.fpregs,
+ sizeof(g_crash_context_.float_state));
+ }
+#endif
+ g_crash_context_.tid = syscall(__NR_gettid);
+ if (crash_handler_ != NULL) {
+ if (crash_handler_(&g_crash_context_, sizeof(g_crash_context_),
+ callback_context_)) {
+ return true;
+ }
+ }
+
+ return GenerateDump(&g_crash_context_, &addr_info);
+}
+
+// This is a public interface to HandleSignal that allows the client to
+// generate a crash dump. This function may run in a compromised context.
+bool ExceptionHandler::SimulateSignalDelivery(int sig) {
+ siginfo_t siginfo = {};
+ // Mimic a trusted signal to allow tracing the process (see
+ // ExceptionHandler::HandleSignal().
+ siginfo.si_code = SI_USER;
+ siginfo.si_pid = getpid();
+ ucontext_t context;
+ getcontext(&context);
+ return HandleSignal(sig, &siginfo, &context);
+}
+
+// This function may run in a compromised context: see the top of the file.
+bool ExceptionHandler::GenerateDump(
+ CrashContext *context, const mozilla::phc::AddrInfo* addr_info) {
+ if (IsOutOfProcess()) {
+ bool success =
+ crash_generation_client_->RequestDump(context, sizeof(*context));
+
+ if (callback_) {
+ success =
+ callback_(minidump_descriptor_, callback_context_, addr_info, success);
+ }
+
+ return success;
+ }
+
+ // Allocating too much stack isn't a problem, and better to err on the side
+ // of caution than smash it into random locations.
+ static const unsigned kChildStackSize = 16000;
+ PageAllocator allocator;
+ uint8_t* stack = reinterpret_cast<uint8_t*>(allocator.Alloc(kChildStackSize));
+ if (!stack)
+ return false;
+ // clone() needs the top-most address. (scrub just to be safe)
+ stack += kChildStackSize;
+ my_memset(stack - 16, 0, 16);
+
+ ThreadArgument thread_arg;
+ thread_arg.handler = this;
+ thread_arg.minidump_descriptor = &minidump_descriptor_;
+ thread_arg.pid = getpid();
+ thread_arg.context = context;
+ thread_arg.context_size = sizeof(*context);
+
+ // We need to explicitly enable ptrace of parent processes on some
+ // kernels, but we need to know the PID of the cloned process before we
+ // can do this. Create a pipe here which we can use to block the
+ // cloned process after creating it, until we have explicitly enabled ptrace
+ if (sys_pipe(fdes) == -1) {
+ // Creating the pipe failed. We'll log an error but carry on anyway,
+ // as we'll probably still get a useful crash report. All that will happen
+ // is the write() and read() calls will fail with EBADF
+ static const char no_pipe_msg[] = "ExceptionHandler::GenerateDump "
+ "sys_pipe failed:";
+ logger::write(no_pipe_msg, sizeof(no_pipe_msg) - 1);
+ logger::write(strerror(errno), strlen(strerror(errno)));
+ logger::write("\n", 1);
+
+ // Ensure fdes[0] and fdes[1] are invalid file descriptors.
+ fdes[0] = fdes[1] = -1;
+ }
+
+ const pid_t child = sys_clone(
+ ThreadEntry, stack, CLONE_FS | CLONE_UNTRACED, &thread_arg, NULL, NULL,
+ NULL);
+ if (child == -1) {
+ sys_close(fdes[0]);
+ sys_close(fdes[1]);
+ return false;
+ }
+
+ if (child != 0) {
+ static const char clonedMsg[] =
+ "ExceptionHandler::GenerateDump cloned child ";
+ char pidMsg[32] = {};
+
+ unsigned int pidLen = my_uint_len(child);
+ my_uitos(pidMsg, child, pidLen);
+
+ logger::write(clonedMsg, my_strlen(clonedMsg));
+ logger::write(pidMsg, pidLen);
+ logger::write("\n", 1);
+ } else {
+ static const char childMsg[] =
+ "ExceptionHandler::GenerateDump I'm the child\n";
+ logger::write(childMsg, my_strlen(childMsg));
+ }
+
+ // Close the read end of the pipe.
+ sys_close(fdes[0]);
+ // Allow the child to ptrace us
+ sys_prctl(PR_SET_PTRACER, child, 0, 0, 0);
+ SendContinueSignalToChild();
+ int status = 0;
+ const int r = HANDLE_EINTR(sys_waitpid(child, &status, __WALL));
+
+ sys_close(fdes[1]);
+
+ if (r == -1) {
+ static const char msg[] = "ExceptionHandler::GenerateDump waitpid failed:";
+ logger::write(msg, sizeof(msg) - 1);
+ logger::write(strerror(errno), strlen(strerror(errno)));
+ logger::write("\n", 1);
+ }
+
+ bool success = r != -1 && WIFEXITED(status) && WEXITSTATUS(status) == 0;
+ if (callback_)
+ success =
+ callback_(minidump_descriptor_, callback_context_, addr_info, success);
+ return success;
+}
+
+// This function runs in a compromised context: see the top of the file.
+void ExceptionHandler::SendContinueSignalToChild() {
+ static const char okToContinueMessage = 'a';
+ int r;
+ r = HANDLE_EINTR(sys_write(fdes[1], &okToContinueMessage, sizeof(char)));
+ if (r == -1) {
+ static const char msg[] = "ExceptionHandler::SendContinueSignalToChild "
+ "sys_write failed:";
+ logger::write(msg, sizeof(msg) - 1);
+ logger::write(strerror(errno), strlen(strerror(errno)));
+ logger::write("\n", 1);
+ }
+
+ const char* msg = "ExceptionHandler::SendContinueSignalToChild sent continue signal to child\n";
+ logger::write(msg, my_strlen(msg));
+}
+
+// This function runs in a compromised context: see the top of the file.
+// Runs on the cloned process.
+void ExceptionHandler::WaitForContinueSignal() {
+ int r;
+ char receivedMessage;
+
+ const char* waitMsg = "ExceptionHandler::WaitForContinueSignal waiting for continue signal...\n";
+ logger::write(waitMsg, my_strlen(waitMsg));
+
+ r = HANDLE_EINTR(sys_read(fdes[0], &receivedMessage, sizeof(char)));
+ if (r == -1) {
+ static const char msg[] = "ExceptionHandler::WaitForContinueSignal "
+ "sys_read failed:";
+ logger::write(msg, sizeof(msg) - 1);
+ logger::write(strerror(errno), strlen(strerror(errno)));
+ logger::write("\n", 1);
+ }
+}
+
+// This function runs in a compromised context: see the top of the file.
+// Runs on the cloned process.
+bool ExceptionHandler::DoDump(pid_t crashing_process, const void* context,
+ size_t context_size) {
+ const bool may_skip_dump =
+ minidump_descriptor_.skip_dump_if_principal_mapping_not_referenced();
+ const uintptr_t principal_mapping_address =
+ minidump_descriptor_.address_within_principal_mapping();
+ const bool sanitize_stacks = minidump_descriptor_.sanitize_stacks();
+ if (minidump_descriptor_.IsMicrodumpOnConsole()) {
+ return google_breakpad::WriteMicrodump(
+ crashing_process,
+ context,
+ context_size,
+ mapping_list_,
+ may_skip_dump,
+ principal_mapping_address,
+ sanitize_stacks,
+ *minidump_descriptor_.microdump_extra_info());
+ }
+ if (minidump_descriptor_.IsFD()) {
+ return google_breakpad::WriteMinidump(minidump_descriptor_.fd(),
+ minidump_descriptor_.size_limit(),
+ crashing_process,
+ context,
+ context_size,
+ mapping_list_,
+ app_memory_list_,
+ may_skip_dump,
+ principal_mapping_address,
+ sanitize_stacks);
+ }
+ return google_breakpad::WriteMinidump(minidump_descriptor_.path(),
+ minidump_descriptor_.size_limit(),
+ crashing_process,
+ context,
+ context_size,
+ mapping_list_,
+ app_memory_list_,
+ may_skip_dump,
+ principal_mapping_address,
+ sanitize_stacks);
+}
+
+// static
+bool ExceptionHandler::WriteMinidump(const string& dump_path,
+ MinidumpCallback callback,
+ void* callback_context) {
+ MinidumpDescriptor descriptor(dump_path);
+ ExceptionHandler eh(descriptor, NULL, callback, callback_context, false, -1);
+ return eh.WriteMinidump();
+}
+
+// In order to making using EBP to calculate the desired value for ESP
+// a valid operation, ensure that this function is compiled with a
+// frame pointer using the following attribute. This attribute
+// is supported on GCC but not on clang.
+#if defined(__i386__) && defined(__GNUC__) && !defined(__clang__)
+__attribute__((optimize("no-omit-frame-pointer")))
+#endif
+bool ExceptionHandler::WriteMinidump() {
+ if (!IsOutOfProcess() && !minidump_descriptor_.IsFD() &&
+ !minidump_descriptor_.IsMicrodumpOnConsole()) {
+ // Update the path of the minidump so that this can be called multiple times
+ // and new files are created for each minidump. This is done before the
+ // generation happens, as clients may want to access the MinidumpDescriptor
+ // after this call to find the exact path to the minidump file.
+ minidump_descriptor_.UpdatePath();
+ } else if (minidump_descriptor_.IsFD()) {
+ // Reposition the FD to its beginning and resize it to get rid of the
+ // previous minidump info.
+ lseek(minidump_descriptor_.fd(), 0, SEEK_SET);
+ ignore_result(ftruncate(minidump_descriptor_.fd(), 0));
+ }
+
+ // Allow this process to be dumped.
+ sys_prctl(PR_SET_DUMPABLE, 1, 0, 0, 0);
+
+ CrashContext context;
+ int getcontext_result = getcontext(&context.context);
+ if (getcontext_result)
+ return false;
+
+#if defined(__i386__)
+ // In CPUFillFromUContext in minidumpwriter.cc the stack pointer is retrieved
+ // from REG_UESP instead of from REG_ESP. REG_UESP is the user stack pointer
+ // and it only makes sense when running in kernel mode with a different stack
+ // pointer. When WriteMiniDump is called during normal processing REG_UESP is
+ // zero which leads to bad minidump files.
+ if (!context.context.uc_mcontext.gregs[REG_UESP]) {
+ // If REG_UESP is set to REG_ESP then that includes the stack space for the
+ // CrashContext object in this function, which is about 128 KB. Since the
+ // Linux dumper only records 32 KB of stack this would mean that nothing
+ // useful would be recorded. A better option is to set REG_UESP to REG_EBP,
+ // perhaps with a small negative offset in case there is any code that
+ // objects to them being equal.
+ context.context.uc_mcontext.gregs[REG_UESP] =
+ context.context.uc_mcontext.gregs[REG_EBP] - 16;
+ // The stack saving is based off of REG_ESP so it must be set to match the
+ // new REG_UESP.
+ context.context.uc_mcontext.gregs[REG_ESP] =
+ context.context.uc_mcontext.gregs[REG_UESP];
+ }
+#endif
+
+#if !defined(__ARM_EABI__) && !defined(__aarch64__) && !defined(__mips__)
+ // FPU state is not part of ARM EABI ucontext_t.
+ memcpy(&context.float_state, context.context.uc_mcontext.fpregs,
+ sizeof(context.float_state));
+#endif
+ context.tid = sys_gettid();
+
+ // Add an exception stream to the minidump for better reporting.
+ memset(&context.siginfo, 0, sizeof(context.siginfo));
+ context.siginfo.si_signo = MD_EXCEPTION_CODE_LIN_DUMP_REQUESTED;
+#if defined(__i386__)
+ context.siginfo.si_addr =
+ reinterpret_cast<void*>(context.context.uc_mcontext.gregs[REG_EIP]);
+#elif defined(__x86_64__)
+ context.siginfo.si_addr =
+ reinterpret_cast<void*>(context.context.uc_mcontext.gregs[REG_RIP]);
+#elif defined(__arm__)
+ context.siginfo.si_addr =
+ reinterpret_cast<void*>(context.context.uc_mcontext.arm_pc);
+#elif defined(__aarch64__)
+ context.siginfo.si_addr =
+ reinterpret_cast<void*>(context.context.uc_mcontext.pc);
+#elif defined(__mips__)
+ context.siginfo.si_addr =
+ reinterpret_cast<void*>(context.context.uc_mcontext.pc);
+#else
+#error "This code has not been ported to your platform yet."
+#endif
+
+ // nullptr here for phc::AddrInfo* is ok because this is not a crash.
+ return GenerateDump(&context, nullptr);
+}
+
+void ExceptionHandler::AddMappingInfo(const string& name,
+ const wasteful_vector<uint8_t>& identifier,
+ uintptr_t start_address,
+ size_t mapping_size,
+ size_t file_offset) {
+ MappingInfo info;
+ info.start_addr = start_address;
+ info.size = mapping_size;
+ info.offset = file_offset;
+ strncpy(info.name, name.c_str(), sizeof(info.name) - 1);
+ info.name[sizeof(info.name) - 1] = '\0';
+
+ MappingEntry mapping;
+ mapping.first = info;
+ mapping.second.assign(identifier.begin(), identifier.end());
+ mapping_list_.push_back(mapping);
+}
+
+void ExceptionHandler::RegisterAppMemory(void* ptr, size_t length) {
+ AppMemoryList::iterator iter =
+ std::find(app_memory_list_.begin(), app_memory_list_.end(), ptr);
+ if (iter != app_memory_list_.end()) {
+ // Don't allow registering the same pointer twice.
+ return;
+ }
+
+ AppMemory app_memory;
+ app_memory.ptr = ptr;
+ app_memory.length = length;
+ app_memory_list_.push_back(app_memory);
+}
+
+void ExceptionHandler::UnregisterAppMemory(void* ptr) {
+ AppMemoryList::iterator iter =
+ std::find(app_memory_list_.begin(), app_memory_list_.end(), ptr);
+ if (iter != app_memory_list_.end()) {
+ app_memory_list_.erase(iter);
+ }
+}
+
+// static
+bool ExceptionHandler::WriteMinidumpForChild(pid_t child,
+ pid_t child_blamed_thread,
+ const string& dump_path,
+ MinidumpCallback callback,
+ void* callback_context) {
+ // This function is not run in a compromised context.
+ MinidumpDescriptor descriptor(dump_path);
+ descriptor.UpdatePath();
+#if defined(MOZ_OXIDIZED_BREAKPAD)
+ nsCString error_msg;
+ if (!write_minidump_linux(descriptor.path(), child, child_blamed_thread, &error_msg))
+ return false;
+#else
+ if (!google_breakpad::WriteMinidump(descriptor.path(),
+ child,
+ child_blamed_thread))
+ return false;
+#endif
+
+ // nullptr here for phc::AddrInfo* is ok because this is not a crash.
+ return callback ? callback(descriptor, callback_context, nullptr, true)
+ : true;
+}
+
+void SetFirstChanceExceptionHandler(FirstChanceHandler callback) {
+ g_first_chance_handler_ = callback;
+}
+
+} // namespace google_breakpad
diff --git a/toolkit/crashreporter/breakpad-client/linux/handler/exception_handler.h b/toolkit/crashreporter/breakpad-client/linux/handler/exception_handler.h
new file mode 100644
index 0000000000..46ad399419
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/linux/handler/exception_handler.h
@@ -0,0 +1,289 @@
+// Copyright (c) 2010 Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef CLIENT_LINUX_HANDLER_EXCEPTION_HANDLER_H_
+#define CLIENT_LINUX_HANDLER_EXCEPTION_HANDLER_H_
+
+#include <signal.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <sys/ucontext.h>
+
+#include <string>
+
+#include "linux/crash_generation/crash_generation_client.h"
+#include "linux/handler/minidump_descriptor.h"
+#include "linux/minidump_writer/minidump_writer.h"
+#include "common/scoped_ptr.h"
+#include "common/using_std_string.h"
+#include "google_breakpad/common/minidump_format.h"
+
+#ifdef MOZ_PHC
+#include "PHC.h"
+#else
+namespace mozilla { namespace phc { class AddrInfo {}; } }
+#endif
+
+namespace google_breakpad {
+
+// ExceptionHandler
+//
+// ExceptionHandler can write a minidump file when an exception occurs,
+// or when WriteMinidump() is called explicitly by your program.
+//
+// To have the exception handler write minidumps when an uncaught exception
+// (crash) occurs, you should create an instance early in the execution
+// of your program, and keep it around for the entire time you want to
+// have crash handling active (typically, until shutdown).
+// (NOTE): There should be only be one this kind of exception handler
+// object per process.
+//
+// If you want to write minidumps without installing the exception handler,
+// you can create an ExceptionHandler with install_handler set to false,
+// then call WriteMinidump. You can also use this technique if you want to
+// use different minidump callbacks for different call sites.
+//
+// In either case, a callback function is called when a minidump is written,
+// which receives the full path or file descriptor of the minidump. The
+// caller can collect and write additional application state to that minidump,
+// and launch an external crash-reporting application.
+//
+// Caller should try to make the callbacks as crash-friendly as possible,
+// it should avoid use heap memory allocation as much as possible.
+
+class ExceptionHandler {
+ public:
+ // A callback function to run before Breakpad performs any substantial
+ // processing of an exception. A FilterCallback is called before writing
+ // a minidump. |context| is the parameter supplied by the user as
+ // callback_context when the handler was created.
+ //
+ // If a FilterCallback returns true, Breakpad will continue processing,
+ // attempting to write a minidump. If a FilterCallback returns false,
+ // Breakpad will immediately report the exception as unhandled without
+ // writing a minidump, allowing another handler the opportunity to handle it.
+ typedef bool (*FilterCallback)(void *context);
+
+ // A callback function to run after the minidump has been written.
+ // |descriptor| contains the file descriptor or file path containing the
+ // minidump. |context| is the parameter supplied by the user as
+ // callback_context when the handler was created. |succeeded| indicates
+ // whether a minidump file was successfully written.
+ //
+ // If an exception occurred and the callback returns true, Breakpad will
+ // treat the exception as fully-handled, suppressing any other handlers from
+ // being notified of the exception. If the callback returns false, Breakpad
+ // will treat the exception as unhandled, and allow another handler to handle
+ // it. If there are no other handlers, Breakpad will report the exception to
+ // the system as unhandled, allowing a debugger or native crash dialog the
+ // opportunity to handle the exception. Most callback implementations
+ // should normally return the value of |succeeded|, or when they wish to
+ // not report an exception of handled, false. Callbacks will rarely want to
+ // return true directly (unless |succeeded| is true).
+ typedef bool (*MinidumpCallback)(const MinidumpDescriptor& descriptor,
+ void* context,
+ const mozilla::phc::AddrInfo* addr_info,
+ bool succeeded);
+
+ // In certain cases, a user may wish to handle the generation of the minidump
+ // themselves. In this case, they can install a handler callback which is
+ // called when a crash has occurred. If this function returns true, no other
+ // processing of occurs and the process will shortly be crashed. If this
+ // returns false, the normal processing continues.
+ typedef bool (*HandlerCallback)(const void* crash_context,
+ size_t crash_context_size,
+ void* context);
+
+ // Creates a new ExceptionHandler instance to handle writing minidumps.
+ // Before writing a minidump, the optional |filter| callback will be called.
+ // Its return value determines whether or not Breakpad should write a
+ // minidump. The minidump content will be written to the file path or file
+ // descriptor from |descriptor|, and the optional |callback| is called after
+ // writing the dump file, as described above.
+ // If install_handler is true, then a minidump will be written whenever
+ // an unhandled exception occurs. If it is false, minidumps will only
+ // be written when WriteMinidump is called.
+ // If |server_fd| is valid, the minidump is generated out-of-process. If it
+ // is -1, in-process generation will always be used.
+ ExceptionHandler(const MinidumpDescriptor& descriptor,
+ FilterCallback filter,
+ MinidumpCallback callback,
+ void* callback_context,
+ bool install_handler,
+ const int server_fd);
+ ~ExceptionHandler();
+
+ const MinidumpDescriptor& minidump_descriptor() const {
+ return minidump_descriptor_;
+ }
+
+ void set_minidump_descriptor(const MinidumpDescriptor& descriptor) {
+ minidump_descriptor_ = descriptor;
+ }
+
+ void set_crash_handler(HandlerCallback callback) {
+ crash_handler_ = callback;
+ }
+
+ void set_crash_generation_client(CrashGenerationClient* client) {
+ crash_generation_client_.reset(client);
+ }
+
+ // Writes a minidump immediately. This can be used to capture the execution
+ // state independently of a crash.
+ // Returns true on success.
+ // If the ExceptionHandler has been created with a path, a new file is
+ // generated for each minidump. The file path can be retrieved in the
+ // MinidumpDescriptor passed to the MinidumpCallback or by accessing the
+ // MinidumpDescriptor directly from the ExceptionHandler (with
+ // minidump_descriptor()).
+ // If the ExceptionHandler has been created with a file descriptor, the file
+ // descriptor is repositioned to its beginning and the previous generated
+ // minidump is overwritten.
+ // Note that this method is not supposed to be called from a compromised
+ // context as it uses the heap.
+ bool WriteMinidump();
+
+ // Convenience form of WriteMinidump which does not require an
+ // ExceptionHandler instance.
+ static bool WriteMinidump(const string& dump_path,
+ MinidumpCallback callback,
+ void* callback_context);
+
+ // Write a minidump of |child| immediately. This can be used to
+ // capture the execution state of |child| independently of a crash.
+ // Pass a meaningful |child_blamed_thread| to make that thread in
+ // the child process the one from which a crash signature is
+ // extracted.
+ //
+ // WARNING: the return of this function *must* happen before
+ // the code that will eventually reap |child| executes.
+ // Otherwise there's a pernicious race condition in which |child|
+ // exits, is reaped, another process created with its pid, then that
+ // new process dumped.
+ static bool WriteMinidumpForChild(pid_t child,
+ pid_t child_blamed_thread,
+ const string& dump_path,
+ MinidumpCallback callback,
+ void* callback_context);
+
+ // This structure is passed to minidump_writer.h:WriteMinidump via an opaque
+ // blob. It shouldn't be needed in any user code.
+ struct CrashContext {
+ siginfo_t siginfo;
+ pid_t tid; // the crashing thread.
+ ucontext_t context;
+#if !defined(__ARM_EABI__) && !defined(__mips__)
+ // #ifdef this out because FP state is not part of user ABI for Linux ARM.
+ // In case of MIPS Linux FP state is already part of ucontext_t so
+ // 'float_state' is not required.
+ fpstate_t float_state;
+#endif
+ };
+
+ // Returns whether out-of-process dump generation is used or not.
+ bool IsOutOfProcess() const {
+ return crash_generation_client_.get() != NULL;
+ }
+
+ // Add information about a memory mapping. This can be used if
+ // a custom library loader is used that maps things in a way
+ // that the linux dumper can't handle by reading the maps file.
+ void AddMappingInfo(const string& name,
+ const wasteful_vector<uint8_t>& identifier,
+ uintptr_t start_address,
+ size_t mapping_size,
+ size_t file_offset);
+
+ // Register a block of memory of length bytes starting at address ptr
+ // to be copied to the minidump when a crash happens.
+ void RegisterAppMemory(void* ptr, size_t length);
+
+ // Unregister a block of memory that was registered with RegisterAppMemory.
+ void UnregisterAppMemory(void* ptr);
+
+ // Force signal handling for the specified signal.
+ bool SimulateSignalDelivery(int sig);
+
+ // Report a crash signal from an SA_SIGINFO signal handler.
+ bool HandleSignal(int sig, siginfo_t* info, void* uc);
+
+ private:
+ // Save the old signal handlers and install new ones.
+ static bool InstallHandlersLocked();
+ // Restore the old signal handlers.
+ static void RestoreHandlersLocked();
+
+ void PreresolveSymbols();
+ bool GenerateDump(CrashContext *context,
+ const mozilla::phc::AddrInfo* addr_info);
+ void SendContinueSignalToChild();
+ void WaitForContinueSignal();
+
+ static void SignalHandler(int sig, siginfo_t* info, void* uc);
+ static int ThreadEntry(void* arg);
+ bool DoDump(pid_t crashing_process, const void* context,
+ size_t context_size);
+
+ const FilterCallback filter_;
+ const MinidumpCallback callback_;
+ void* const callback_context_;
+
+ scoped_ptr<CrashGenerationClient> crash_generation_client_;
+
+ MinidumpDescriptor minidump_descriptor_;
+
+ // Must be volatile. The compiler is unaware of the code which runs in
+ // the signal handler which reads this variable. Without volatile the
+ // compiler is free to optimise away writes to this variable which it
+ // believes are never read.
+ volatile HandlerCallback crash_handler_;
+
+ // We need to explicitly enable ptrace of parent processes on some
+ // kernels, but we need to know the PID of the cloned process before we
+ // can do this. We create a pipe which we can use to block the
+ // cloned process after creating it, until we have explicitly enabled
+ // ptrace. This is used to store the file descriptors for the pipe
+ int fdes[2] = {-1, -1};
+
+ // Callers can add extra info about mappings for cases where the
+ // dumper code cannot extract enough information from /proc/<pid>/maps.
+ MappingList mapping_list_;
+
+ // Callers can request additional memory regions to be included in
+ // the dump.
+ AppMemoryList app_memory_list_;
+};
+
+typedef bool (*FirstChanceHandler)(int, siginfo_t*, void*);
+void SetFirstChanceExceptionHandler(FirstChanceHandler callback);
+
+} // namespace google_breakpad
+
+#endif // CLIENT_LINUX_HANDLER_EXCEPTION_HANDLER_H_
diff --git a/toolkit/crashreporter/breakpad-client/linux/handler/exception_handler_unittest.cc b/toolkit/crashreporter/breakpad-client/linux/handler/exception_handler_unittest.cc
new file mode 100644
index 0000000000..8fa59456c9
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/linux/handler/exception_handler_unittest.cc
@@ -0,0 +1,1290 @@
+// 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 <poll.h>
+#include <pthread.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <signal.h>
+#include <sys/mman.h>
+#include <sys/socket.h>
+#include <sys/uio.h>
+#include <sys/wait.h>
+#if defined(__mips__)
+#include <sys/cachectl.h>
+#endif
+
+#include <string>
+
+#include "breakpad_googletest_includes.h"
+#include "linux/handler/exception_handler.h"
+#include "linux/minidump_writer/minidump_writer.h"
+#include "common/linux/eintr_wrapper.h"
+#include "common/linux/ignore_ret.h"
+#include "common/linux/linux_libc_support.h"
+#include "common/tests/auto_tempdir.h"
+#include "common/using_std_string.h"
+#include "third_party/lss/linux_syscall_support.h"
+#include "google_breakpad/processor/minidump.h"
+
+using namespace google_breakpad;
+
+namespace {
+
+// Flush the instruction cache for a given memory range.
+// Only required on ARM and mips.
+void FlushInstructionCache(const char* memory, uint32_t memory_size) {
+#if defined(__arm__)
+ long begin = reinterpret_cast<long>(memory);
+ long end = begin + static_cast<long>(memory_size);
+# if defined(__ANDROID__)
+ // Provided by Android's <unistd.h>
+ cacheflush(begin, end, 0);
+# elif defined(__linux__)
+ // GLibc/ARM doesn't provide a wrapper for it, do a direct syscall.
+# ifndef __ARM_NR_cacheflush
+# define __ARM_NR_cacheflush 0xf0002
+# endif
+ syscall(__ARM_NR_cacheflush, begin, end, 0);
+# else
+# error "Your operating system is not supported yet"
+# endif
+#elif defined(__mips__)
+# if defined(__ANDROID__)
+ // Provided by Android's <unistd.h>
+ long begin = reinterpret_cast<long>(memory);
+ long end = begin + static_cast<long>(memory_size);
+#if _MIPS_SIM == _ABIO32
+ cacheflush(begin, end, 0);
+#else
+ syscall(__NR_cacheflush, begin, end, ICACHE);
+#endif
+# elif defined(__linux__)
+ // See http://www.linux-mips.org/wiki/Cacheflush_Syscall.
+ cacheflush(const_cast<char*>(memory), memory_size, ICACHE);
+# else
+# error "Your operating system is not supported yet"
+# endif
+#endif
+}
+
+void sigchld_handler(int signo) { }
+
+int CreateTMPFile(const string& dir, string* path) {
+ string file = dir + "/exception-handler-unittest.XXXXXX";
+ const char* c_file = file.c_str();
+ // Copy that string, mkstemp needs a C string it can modify.
+ char* c_path = strdup(c_file);
+ const int fd = mkstemp(c_path);
+ if (fd >= 0)
+ *path = c_path;
+ free(c_path);
+ return fd;
+}
+
+class ExceptionHandlerTest : public ::testing::Test {
+ protected:
+ void SetUp() {
+ // We need to be able to wait for children, so SIGCHLD cannot be SIG_IGN.
+ struct sigaction sa;
+ memset(&sa, 0, sizeof(sa));
+ sa.sa_handler = sigchld_handler;
+ ASSERT_NE(sigaction(SIGCHLD, &sa, &old_action), -1);
+ }
+
+ void TearDown() {
+ sigaction(SIGCHLD, &old_action, NULL);
+ }
+
+ struct sigaction old_action;
+};
+
+
+void WaitForProcessToTerminate(pid_t process_id, int expected_status) {
+ int status;
+ ASSERT_NE(HANDLE_EINTR(waitpid(process_id, &status, 0)), -1);
+ ASSERT_TRUE(WIFSIGNALED(status));
+ ASSERT_EQ(expected_status, WTERMSIG(status));
+}
+
+// Reads the minidump path sent over the pipe |fd| and sets it in |path|.
+void ReadMinidumpPathFromPipe(int fd, string* path) {
+ struct pollfd pfd;
+ memset(&pfd, 0, sizeof(pfd));
+ pfd.fd = fd;
+ pfd.events = POLLIN | POLLERR;
+
+ const int r = HANDLE_EINTR(poll(&pfd, 1, 0));
+ ASSERT_EQ(1, r);
+ ASSERT_TRUE(pfd.revents & POLLIN);
+
+ int32_t len;
+ ASSERT_EQ(static_cast<ssize_t>(sizeof(len)), read(fd, &len, sizeof(len)));
+ ASSERT_LT(len, 2048);
+ char* filename = static_cast<char*>(malloc(len + 1));
+ ASSERT_EQ(len, read(fd, filename, len));
+ filename[len] = 0;
+ close(fd);
+ *path = filename;
+ free(filename);
+}
+
+} // namespace
+
+TEST(ExceptionHandlerTest, SimpleWithPath) {
+ AutoTempDir temp_dir;
+ ExceptionHandler handler(
+ MinidumpDescriptor(temp_dir.path()), NULL, NULL, NULL, true, -1);
+ EXPECT_EQ(temp_dir.path(), handler.minidump_descriptor().directory());
+ string temp_subdir = temp_dir.path() + "/subdir";
+ handler.set_minidump_descriptor(MinidumpDescriptor(temp_subdir));
+ EXPECT_EQ(temp_subdir, handler.minidump_descriptor().directory());
+}
+
+TEST(ExceptionHandlerTest, SimpleWithFD) {
+ AutoTempDir temp_dir;
+ string path;
+ const int fd = CreateTMPFile(temp_dir.path(), &path);
+ ExceptionHandler handler(MinidumpDescriptor(fd), NULL, NULL, NULL, true, -1);
+ close(fd);
+}
+
+static bool DoneCallback(const MinidumpDescriptor& descriptor,
+ void* context,
+ bool succeeded) {
+ if (!succeeded)
+ return false;
+
+ if (!descriptor.IsFD()) {
+ int fd = reinterpret_cast<intptr_t>(context);
+ uint32_t len = 0;
+ len = my_strlen(descriptor.path());
+ IGNORE_RET(HANDLE_EINTR(sys_write(fd, &len, sizeof(len))));
+ IGNORE_RET(HANDLE_EINTR(sys_write(fd, descriptor.path(), len)));
+ }
+ return true;
+}
+
+#ifndef ADDRESS_SANITIZER
+
+// This is a replacement for "*reinterpret_cast<volatile int*>(NULL) = 0;"
+// It is needed because GCC is allowed to assume that the program will
+// not execute any undefined behavior (UB) operation. Further, when GCC
+// observes that UB statement is reached, it can assume that all statements
+// leading to the UB one are never executed either, and can completely
+// optimize them out. In the case of ExceptionHandlerTest::ExternalDumper,
+// GCC-4.9 optimized out the entire set up of ExceptionHandler, causing
+// test failure.
+volatile int *p_null; // external linkage, so GCC can't tell that it
+ // remains NULL. Volatile just for a good measure.
+static void DoNullPointerDereference() {
+ *p_null = 1;
+}
+
+void ChildCrash(bool use_fd) {
+ AutoTempDir temp_dir;
+ int fds[2] = {0};
+ int minidump_fd = -1;
+ string minidump_path;
+ if (use_fd) {
+ minidump_fd = CreateTMPFile(temp_dir.path(), &minidump_path);
+ } else {
+ ASSERT_NE(pipe(fds), -1);
+ }
+
+ const pid_t child = fork();
+ if (child == 0) {
+ {
+ google_breakpad::scoped_ptr<ExceptionHandler> handler;
+ if (use_fd) {
+ handler.reset(new ExceptionHandler(MinidumpDescriptor(minidump_fd),
+ NULL, NULL, NULL, true, -1));
+ } else {
+ close(fds[0]); // Close the reading end.
+ void* fd_param = reinterpret_cast<void*>(fds[1]);
+ handler.reset(new ExceptionHandler(MinidumpDescriptor(temp_dir.path()),
+ NULL, DoneCallback, fd_param,
+ true, -1));
+ }
+ // Crash with the exception handler in scope.
+ DoNullPointerDereference();
+ }
+ }
+ if (!use_fd)
+ close(fds[1]); // Close the writting end.
+
+ ASSERT_NO_FATAL_FAILURE(WaitForProcessToTerminate(child, SIGSEGV));
+
+ if (!use_fd)
+ ASSERT_NO_FATAL_FAILURE(ReadMinidumpPathFromPipe(fds[0], &minidump_path));
+
+ struct stat st;
+ ASSERT_EQ(0, stat(minidump_path.c_str(), &st));
+ ASSERT_GT(st.st_size, 0);
+ unlink(minidump_path.c_str());
+}
+
+TEST(ExceptionHandlerTest, ChildCrashWithPath) {
+ ASSERT_NO_FATAL_FAILURE(ChildCrash(false));
+}
+
+TEST(ExceptionHandlerTest, ChildCrashWithFD) {
+ ASSERT_NO_FATAL_FAILURE(ChildCrash(true));
+}
+
+#if !defined(__ANDROID_API__) || __ANDROID_API__ >= __ANDROID_API_N__
+static void* SleepFunction(void* unused) {
+ while (true) usleep(1000000);
+ return NULL;
+}
+
+static void* CrashFunction(void* b_ptr) {
+ pthread_barrier_t* b = reinterpret_cast<pthread_barrier_t*>(b_ptr);
+ pthread_barrier_wait(b);
+ DoNullPointerDereference();
+ return NULL;
+}
+
+// Tests that concurrent crashes do not enter a loop by alternately triggering
+// the signal handler.
+TEST(ExceptionHandlerTest, ParallelChildCrashesDontHang) {
+ AutoTempDir temp_dir;
+ const pid_t child = fork();
+ if (child == 0) {
+ google_breakpad::scoped_ptr<ExceptionHandler> handler(
+ new ExceptionHandler(MinidumpDescriptor(temp_dir.path()), NULL, NULL,
+ NULL, true, -1));
+
+ // We start a number of threads to make sure handling the signal takes
+ // enough time for the second thread to enter the signal handler.
+ int num_sleep_threads = 100;
+ google_breakpad::scoped_array<pthread_t> sleep_threads(
+ new pthread_t[num_sleep_threads]);
+ for (int i = 0; i < num_sleep_threads; ++i) {
+ ASSERT_EQ(0, pthread_create(&sleep_threads[i], NULL, SleepFunction,
+ NULL));
+ }
+
+ int num_crash_threads = 2;
+ google_breakpad::scoped_array<pthread_t> crash_threads(
+ new pthread_t[num_crash_threads]);
+ // Barrier to synchronize crashing both threads at the same time.
+ pthread_barrier_t b;
+ ASSERT_EQ(0, pthread_barrier_init(&b, NULL, num_crash_threads + 1));
+ for (int i = 0; i < num_crash_threads; ++i) {
+ ASSERT_EQ(0, pthread_create(&crash_threads[i], NULL, CrashFunction, &b));
+ }
+ pthread_barrier_wait(&b);
+ for (int i = 0; i < num_crash_threads; ++i) {
+ ASSERT_EQ(0, pthread_join(crash_threads[i], NULL));
+ }
+ }
+
+ // Wait a while until the child should have crashed.
+ usleep(1000000);
+ // Kill the child if it is still running.
+ kill(child, SIGKILL);
+
+ // If the child process terminated by itself, it will have returned SIGSEGV.
+ // If however it got stuck in a loop, it will have been killed by the
+ // SIGKILL.
+ ASSERT_NO_FATAL_FAILURE(WaitForProcessToTerminate(child, SIGSEGV));
+}
+#endif // !defined(__ANDROID_API__) || __ANDROID_API__ >= __ANDROID_API_N__
+
+static bool DoneCallbackReturnFalse(const MinidumpDescriptor& descriptor,
+ void* context,
+ bool succeeded) {
+ return false;
+}
+
+static bool DoneCallbackReturnTrue(const MinidumpDescriptor& descriptor,
+ void* context,
+ bool succeeded) {
+ return true;
+}
+
+static bool DoneCallbackRaiseSIGKILL(const MinidumpDescriptor& descriptor,
+ void* context,
+ bool succeeded) {
+ raise(SIGKILL);
+ return true;
+}
+
+static bool FilterCallbackReturnFalse(void* context) {
+ return false;
+}
+
+static bool FilterCallbackReturnTrue(void* context) {
+ return true;
+}
+
+// SIGKILL cannot be blocked and a handler cannot be installed for it. In the
+// following tests, if the child dies with signal SIGKILL, then the signal was
+// redelivered to this handler. If the child dies with SIGSEGV then it wasn't.
+static void RaiseSIGKILL(int sig) {
+ raise(SIGKILL);
+}
+
+static bool InstallRaiseSIGKILL() {
+ struct sigaction sa;
+ memset(&sa, 0, sizeof(sa));
+ sa.sa_handler = RaiseSIGKILL;
+ return sigaction(SIGSEGV, &sa, NULL) != -1;
+}
+
+static void CrashWithCallbacks(ExceptionHandler::FilterCallback filter,
+ ExceptionHandler::MinidumpCallback done,
+ string path) {
+ ExceptionHandler handler(
+ MinidumpDescriptor(path), filter, done, NULL, true, -1);
+ // Crash with the exception handler in scope.
+ DoNullPointerDereference();
+}
+
+TEST(ExceptionHandlerTest, RedeliveryOnFilterCallbackFalse) {
+ AutoTempDir temp_dir;
+
+ const pid_t child = fork();
+ if (child == 0) {
+ ASSERT_TRUE(InstallRaiseSIGKILL());
+ CrashWithCallbacks(FilterCallbackReturnFalse, NULL, temp_dir.path());
+ }
+
+ ASSERT_NO_FATAL_FAILURE(WaitForProcessToTerminate(child, SIGKILL));
+}
+
+TEST(ExceptionHandlerTest, RedeliveryOnDoneCallbackFalse) {
+ AutoTempDir temp_dir;
+
+ const pid_t child = fork();
+ if (child == 0) {
+ ASSERT_TRUE(InstallRaiseSIGKILL());
+ CrashWithCallbacks(NULL, DoneCallbackReturnFalse, temp_dir.path());
+ }
+
+ ASSERT_NO_FATAL_FAILURE(WaitForProcessToTerminate(child, SIGKILL));
+}
+
+TEST(ExceptionHandlerTest, NoRedeliveryOnDoneCallbackTrue) {
+ AutoTempDir temp_dir;
+
+ const pid_t child = fork();
+ if (child == 0) {
+ ASSERT_TRUE(InstallRaiseSIGKILL());
+ CrashWithCallbacks(NULL, DoneCallbackReturnTrue, temp_dir.path());
+ }
+
+ ASSERT_NO_FATAL_FAILURE(WaitForProcessToTerminate(child, SIGSEGV));
+}
+
+TEST(ExceptionHandlerTest, NoRedeliveryOnFilterCallbackTrue) {
+ AutoTempDir temp_dir;
+
+ const pid_t child = fork();
+ if (child == 0) {
+ ASSERT_TRUE(InstallRaiseSIGKILL());
+ CrashWithCallbacks(FilterCallbackReturnTrue, NULL, temp_dir.path());
+ }
+
+ ASSERT_NO_FATAL_FAILURE(WaitForProcessToTerminate(child, SIGSEGV));
+}
+
+TEST(ExceptionHandlerTest, RedeliveryToDefaultHandler) {
+ AutoTempDir temp_dir;
+
+ const pid_t child = fork();
+ if (child == 0) {
+ // Custom signal handlers, which may have been installed by a test launcher,
+ // are undesirable in this child.
+ signal(SIGSEGV, SIG_DFL);
+
+ CrashWithCallbacks(FilterCallbackReturnFalse, NULL, temp_dir.path());
+ }
+
+ // As RaiseSIGKILL wasn't installed, the redelivery should just kill the child
+ // with SIGSEGV.
+ ASSERT_NO_FATAL_FAILURE(WaitForProcessToTerminate(child, SIGSEGV));
+}
+
+// Check that saving and restoring the signal handler with 'signal'
+// instead of 'sigaction' doesn't make the Breakpad signal handler
+// crash. See comments in ExceptionHandler::SignalHandler for full
+// details.
+TEST(ExceptionHandlerTest, RedeliveryOnBadSignalHandlerFlag) {
+ AutoTempDir temp_dir;
+ const pid_t child = fork();
+ if (child == 0) {
+ // Install the RaiseSIGKILL handler for SIGSEGV.
+ ASSERT_TRUE(InstallRaiseSIGKILL());
+
+ // Create a new exception handler, this installs a new SIGSEGV
+ // handler, after saving the old one.
+ ExceptionHandler handler(
+ MinidumpDescriptor(temp_dir.path()), NULL,
+ DoneCallbackReturnFalse, NULL, true, -1);
+
+ // Install the default SIGSEGV handler, saving the current one.
+ // Then re-install the current one with 'signal', this loses the
+ // SA_SIGINFO flag associated with the Breakpad handler.
+ sighandler_t old_handler = signal(SIGSEGV, SIG_DFL);
+ ASSERT_NE(reinterpret_cast<void*>(old_handler),
+ reinterpret_cast<void*>(SIG_ERR));
+ ASSERT_NE(reinterpret_cast<void*>(signal(SIGSEGV, old_handler)),
+ reinterpret_cast<void*>(SIG_ERR));
+
+ // Crash with the exception handler in scope.
+ DoNullPointerDereference();
+ }
+ // SIGKILL means Breakpad's signal handler didn't crash.
+ ASSERT_NO_FATAL_FAILURE(WaitForProcessToTerminate(child, SIGKILL));
+}
+
+TEST(ExceptionHandlerTest, StackedHandlersDeliveredToTop) {
+ AutoTempDir temp_dir;
+
+ const pid_t child = fork();
+ if (child == 0) {
+ ExceptionHandler bottom(MinidumpDescriptor(temp_dir.path()),
+ NULL,
+ NULL,
+ NULL,
+ true,
+ -1);
+ CrashWithCallbacks(NULL, DoneCallbackRaiseSIGKILL, temp_dir.path());
+ }
+ ASSERT_NO_FATAL_FAILURE(WaitForProcessToTerminate(child, SIGKILL));
+}
+
+TEST(ExceptionHandlerTest, StackedHandlersNotDeliveredToBottom) {
+ AutoTempDir temp_dir;
+
+ const pid_t child = fork();
+ if (child == 0) {
+ ExceptionHandler bottom(MinidumpDescriptor(temp_dir.path()),
+ NULL,
+ DoneCallbackRaiseSIGKILL,
+ NULL,
+ true,
+ -1);
+ CrashWithCallbacks(NULL, NULL, temp_dir.path());
+ }
+ ASSERT_NO_FATAL_FAILURE(WaitForProcessToTerminate(child, SIGSEGV));
+}
+
+TEST(ExceptionHandlerTest, StackedHandlersFilteredToBottom) {
+ AutoTempDir temp_dir;
+
+ const pid_t child = fork();
+ if (child == 0) {
+ ExceptionHandler bottom(MinidumpDescriptor(temp_dir.path()),
+ NULL,
+ DoneCallbackRaiseSIGKILL,
+ NULL,
+ true,
+ -1);
+ CrashWithCallbacks(FilterCallbackReturnFalse, NULL, temp_dir.path());
+ }
+ ASSERT_NO_FATAL_FAILURE(WaitForProcessToTerminate(child, SIGKILL));
+}
+
+TEST(ExceptionHandlerTest, StackedHandlersUnhandledToBottom) {
+ AutoTempDir temp_dir;
+
+ const pid_t child = fork();
+ if (child == 0) {
+ ExceptionHandler bottom(MinidumpDescriptor(temp_dir.path()),
+ NULL,
+ DoneCallbackRaiseSIGKILL,
+ NULL,
+ true,
+ -1);
+ CrashWithCallbacks(NULL, DoneCallbackReturnFalse, temp_dir.path());
+ }
+ ASSERT_NO_FATAL_FAILURE(WaitForProcessToTerminate(child, SIGKILL));
+}
+
+namespace {
+const int kSimpleFirstChanceReturnStatus = 42;
+bool SimpleFirstChanceHandler(int, siginfo_t*, void*) {
+ _exit(kSimpleFirstChanceReturnStatus);
+}
+}
+
+TEST(ExceptionHandlerTest, FirstChanceHandlerRuns) {
+ AutoTempDir temp_dir;
+
+ const pid_t child = fork();
+ if (child == 0) {
+ ExceptionHandler handler(
+ MinidumpDescriptor(temp_dir.path()), NULL, NULL, NULL, true, -1);
+ google_breakpad::SetFirstChanceExceptionHandler(SimpleFirstChanceHandler);
+ DoNullPointerDereference();
+ }
+ int status;
+ ASSERT_NE(HANDLE_EINTR(waitpid(child, &status, 0)), -1);
+ ASSERT_TRUE(WIFEXITED(status));
+ ASSERT_EQ(kSimpleFirstChanceReturnStatus, WEXITSTATUS(status));
+}
+
+#endif // !ADDRESS_SANITIZER
+
+const unsigned char kIllegalInstruction[] = {
+#if defined(__mips__)
+ // mfc2 zero,Impl - usually illegal in userspace.
+ 0x48, 0x00, 0x00, 0x48
+#else
+ // This crashes with SIGILL on x86/x86-64/arm.
+ 0xff, 0xff, 0xff, 0xff
+#endif
+};
+
+// Test that memory around the instruction pointer is written
+// to the dump as a MinidumpMemoryRegion.
+TEST(ExceptionHandlerTest, InstructionPointerMemory) {
+ AutoTempDir temp_dir;
+ int fds[2];
+ ASSERT_NE(pipe(fds), -1);
+
+ // These are defined here so the parent can use them to check the
+ // data from the minidump afterwards.
+ const uint32_t kMemorySize = 256; // bytes
+ const int kOffset = kMemorySize / 2;
+
+ const pid_t child = fork();
+ if (child == 0) {
+ close(fds[0]);
+ ExceptionHandler handler(MinidumpDescriptor(temp_dir.path()), NULL,
+ DoneCallback, reinterpret_cast<void*>(fds[1]),
+ true, -1);
+ // Get some executable memory.
+ char* memory =
+ reinterpret_cast<char*>(mmap(NULL,
+ kMemorySize,
+ PROT_READ | PROT_WRITE | PROT_EXEC,
+ MAP_PRIVATE | MAP_ANON,
+ -1,
+ 0));
+ if (!memory)
+ exit(0);
+
+ // Write some instructions that will crash. Put them in the middle
+ // of the block of memory, because the minidump should contain 128
+ // bytes on either side of the instruction pointer.
+ memcpy(memory + kOffset, kIllegalInstruction, sizeof(kIllegalInstruction));
+ FlushInstructionCache(memory, kMemorySize);
+
+ // Now execute the instructions, which should crash.
+ typedef void (*void_function)(void);
+ void_function memory_function =
+ reinterpret_cast<void_function>(memory + kOffset);
+ memory_function();
+ }
+ close(fds[1]);
+
+ ASSERT_NO_FATAL_FAILURE(WaitForProcessToTerminate(child, SIGILL));
+
+ string minidump_path;
+ ASSERT_NO_FATAL_FAILURE(ReadMinidumpPathFromPipe(fds[0], &minidump_path));
+
+ struct stat st;
+ ASSERT_EQ(0, stat(minidump_path.c_str(), &st));
+ ASSERT_GT(st.st_size, 0);
+
+ // Read the minidump. Locate the exception record and the
+ // memory list, and then ensure that there is a memory region
+ // in the memory list that covers the instruction pointer from
+ // the exception record.
+ Minidump minidump(minidump_path);
+ ASSERT_TRUE(minidump.Read());
+
+ MinidumpException* exception = minidump.GetException();
+ MinidumpMemoryList* memory_list = minidump.GetMemoryList();
+ ASSERT_TRUE(exception);
+ ASSERT_TRUE(memory_list);
+ ASSERT_LT(0U, memory_list->region_count());
+
+ MinidumpContext* context = exception->GetContext();
+ ASSERT_TRUE(context);
+
+ uint64_t instruction_pointer;
+ ASSERT_TRUE(context->GetInstructionPointer(&instruction_pointer));
+
+ MinidumpMemoryRegion* region =
+ memory_list->GetMemoryRegionForAddress(instruction_pointer);
+ ASSERT_TRUE(region);
+
+ EXPECT_EQ(kMemorySize, region->GetSize());
+ const uint8_t* bytes = region->GetMemory();
+ ASSERT_TRUE(bytes);
+
+ uint8_t prefix_bytes[kOffset];
+ uint8_t suffix_bytes[kMemorySize - kOffset - sizeof(kIllegalInstruction)];
+ memset(prefix_bytes, 0, sizeof(prefix_bytes));
+ memset(suffix_bytes, 0, sizeof(suffix_bytes));
+ EXPECT_TRUE(memcmp(bytes, prefix_bytes, sizeof(prefix_bytes)) == 0);
+ EXPECT_TRUE(memcmp(bytes + kOffset, kIllegalInstruction,
+ sizeof(kIllegalInstruction)) == 0);
+ EXPECT_TRUE(memcmp(bytes + kOffset + sizeof(kIllegalInstruction),
+ suffix_bytes, sizeof(suffix_bytes)) == 0);
+
+ unlink(minidump_path.c_str());
+}
+
+// Test that the memory region around the instruction pointer is
+// bounded correctly on the low end.
+TEST(ExceptionHandlerTest, InstructionPointerMemoryMinBound) {
+ AutoTempDir temp_dir;
+ int fds[2];
+ ASSERT_NE(pipe(fds), -1);
+
+ // These are defined here so the parent can use them to check the
+ // data from the minidump afterwards.
+ const uint32_t kMemorySize = 256; // bytes
+ const int kOffset = 0;
+
+ const pid_t child = fork();
+ if (child == 0) {
+ close(fds[0]);
+ ExceptionHandler handler(MinidumpDescriptor(temp_dir.path()), NULL,
+ DoneCallback, reinterpret_cast<void*>(fds[1]),
+ true, -1);
+ // Get some executable memory.
+ char* memory =
+ reinterpret_cast<char*>(mmap(NULL,
+ kMemorySize,
+ PROT_READ | PROT_WRITE | PROT_EXEC,
+ MAP_PRIVATE | MAP_ANON,
+ -1,
+ 0));
+ if (!memory)
+ exit(0);
+
+ // Write some instructions that will crash. Put them in the middle
+ // of the block of memory, because the minidump should contain 128
+ // bytes on either side of the instruction pointer.
+ memcpy(memory + kOffset, kIllegalInstruction, sizeof(kIllegalInstruction));
+ FlushInstructionCache(memory, kMemorySize);
+
+ // Now execute the instructions, which should crash.
+ typedef void (*void_function)(void);
+ void_function memory_function =
+ reinterpret_cast<void_function>(memory + kOffset);
+ memory_function();
+ }
+ close(fds[1]);
+
+ ASSERT_NO_FATAL_FAILURE(WaitForProcessToTerminate(child, SIGILL));
+
+ string minidump_path;
+ ASSERT_NO_FATAL_FAILURE(ReadMinidumpPathFromPipe(fds[0], &minidump_path));
+
+ struct stat st;
+ ASSERT_EQ(0, stat(minidump_path.c_str(), &st));
+ ASSERT_GT(st.st_size, 0);
+
+ // Read the minidump. Locate the exception record and the
+ // memory list, and then ensure that there is a memory region
+ // in the memory list that covers the instruction pointer from
+ // the exception record.
+ Minidump minidump(minidump_path);
+ ASSERT_TRUE(minidump.Read());
+
+ MinidumpException* exception = minidump.GetException();
+ MinidumpMemoryList* memory_list = minidump.GetMemoryList();
+ ASSERT_TRUE(exception);
+ ASSERT_TRUE(memory_list);
+ ASSERT_LT(0U, memory_list->region_count());
+
+ MinidumpContext* context = exception->GetContext();
+ ASSERT_TRUE(context);
+
+ uint64_t instruction_pointer;
+ ASSERT_TRUE(context->GetInstructionPointer(&instruction_pointer));
+
+ MinidumpMemoryRegion* region =
+ memory_list->GetMemoryRegionForAddress(instruction_pointer);
+ ASSERT_TRUE(region);
+
+ EXPECT_EQ(kMemorySize / 2, region->GetSize());
+ const uint8_t* bytes = region->GetMemory();
+ ASSERT_TRUE(bytes);
+
+ uint8_t suffix_bytes[kMemorySize / 2 - sizeof(kIllegalInstruction)];
+ memset(suffix_bytes, 0, sizeof(suffix_bytes));
+ EXPECT_TRUE(memcmp(bytes + kOffset, kIllegalInstruction,
+ sizeof(kIllegalInstruction)) == 0);
+ EXPECT_TRUE(memcmp(bytes + kOffset + sizeof(kIllegalInstruction),
+ suffix_bytes, sizeof(suffix_bytes)) == 0);
+ unlink(minidump_path.c_str());
+}
+
+// Test that the memory region around the instruction pointer is
+// bounded correctly on the high end.
+TEST(ExceptionHandlerTest, InstructionPointerMemoryMaxBound) {
+ AutoTempDir temp_dir;
+ int fds[2];
+ ASSERT_NE(pipe(fds), -1);
+
+ // These are defined here so the parent can use them to check the
+ // data from the minidump afterwards.
+ // Use 4k here because the OS will hand out a single page even
+ // if a smaller size is requested, and this test wants to
+ // test the upper bound of the memory range.
+ const uint32_t kMemorySize = 4096; // bytes
+ const int kOffset = kMemorySize - sizeof(kIllegalInstruction);
+
+ const pid_t child = fork();
+ if (child == 0) {
+ close(fds[0]);
+ ExceptionHandler handler(MinidumpDescriptor(temp_dir.path()), NULL,
+ DoneCallback, reinterpret_cast<void*>(fds[1]),
+ true, -1);
+ // Get some executable memory.
+ char* memory =
+ reinterpret_cast<char*>(mmap(NULL,
+ kMemorySize,
+ PROT_READ | PROT_WRITE | PROT_EXEC,
+ MAP_PRIVATE | MAP_ANON,
+ -1,
+ 0));
+ if (!memory)
+ exit(0);
+
+ // Write some instructions that will crash. Put them in the middle
+ // of the block of memory, because the minidump should contain 128
+ // bytes on either side of the instruction pointer.
+ memcpy(memory + kOffset, kIllegalInstruction, sizeof(kIllegalInstruction));
+ FlushInstructionCache(memory, kMemorySize);
+
+ // Now execute the instructions, which should crash.
+ typedef void (*void_function)(void);
+ void_function memory_function =
+ reinterpret_cast<void_function>(memory + kOffset);
+ memory_function();
+ }
+ close(fds[1]);
+
+ ASSERT_NO_FATAL_FAILURE(WaitForProcessToTerminate(child, SIGILL));
+
+ string minidump_path;
+ ASSERT_NO_FATAL_FAILURE(ReadMinidumpPathFromPipe(fds[0], &minidump_path));
+
+ struct stat st;
+ ASSERT_EQ(0, stat(minidump_path.c_str(), &st));
+ ASSERT_GT(st.st_size, 0);
+
+ // Read the minidump. Locate the exception record and the memory list, and
+ // then ensure that there is a memory region in the memory list that covers
+ // the instruction pointer from the exception record.
+ Minidump minidump(minidump_path);
+ ASSERT_TRUE(minidump.Read());
+
+ MinidumpException* exception = minidump.GetException();
+ MinidumpMemoryList* memory_list = minidump.GetMemoryList();
+ ASSERT_TRUE(exception);
+ ASSERT_TRUE(memory_list);
+ ASSERT_LT(0U, memory_list->region_count());
+
+ MinidumpContext* context = exception->GetContext();
+ ASSERT_TRUE(context);
+
+ uint64_t instruction_pointer;
+ ASSERT_TRUE(context->GetInstructionPointer(&instruction_pointer));
+
+ MinidumpMemoryRegion* region =
+ memory_list->GetMemoryRegionForAddress(instruction_pointer);
+ ASSERT_TRUE(region);
+
+ const size_t kPrefixSize = 128; // bytes
+ EXPECT_EQ(kPrefixSize + sizeof(kIllegalInstruction), region->GetSize());
+ const uint8_t* bytes = region->GetMemory();
+ ASSERT_TRUE(bytes);
+
+ uint8_t prefix_bytes[kPrefixSize];
+ memset(prefix_bytes, 0, sizeof(prefix_bytes));
+ EXPECT_TRUE(memcmp(bytes, prefix_bytes, sizeof(prefix_bytes)) == 0);
+ EXPECT_TRUE(memcmp(bytes + kPrefixSize,
+ kIllegalInstruction, sizeof(kIllegalInstruction)) == 0);
+
+ unlink(minidump_path.c_str());
+}
+
+#ifndef ADDRESS_SANITIZER
+
+// Ensure that an extra memory block doesn't get added when the instruction
+// pointer is not in mapped memory.
+TEST(ExceptionHandlerTest, InstructionPointerMemoryNullPointer) {
+ AutoTempDir temp_dir;
+ int fds[2];
+ ASSERT_NE(pipe(fds), -1);
+
+ const pid_t child = fork();
+ if (child == 0) {
+ close(fds[0]);
+ ExceptionHandler handler(MinidumpDescriptor(temp_dir.path()), NULL,
+ DoneCallback, reinterpret_cast<void*>(fds[1]),
+ true, -1);
+ // Try calling a NULL pointer.
+ typedef void (*void_function)(void);
+ // Volatile markings are needed to keep Clang from generating invalid
+ // opcodes. See http://crbug.com/498354 for details.
+ volatile void_function memory_function =
+ reinterpret_cast<void_function>(NULL);
+ memory_function();
+ // not reached
+ exit(1);
+ }
+ close(fds[1]);
+
+ ASSERT_NO_FATAL_FAILURE(WaitForProcessToTerminate(child, SIGSEGV));
+
+ string minidump_path;
+ ASSERT_NO_FATAL_FAILURE(ReadMinidumpPathFromPipe(fds[0], &minidump_path));
+
+ struct stat st;
+ ASSERT_EQ(0, stat(minidump_path.c_str(), &st));
+ ASSERT_GT(st.st_size, 0);
+
+ // Read the minidump. Locate the exception record and the
+ // memory list, and then ensure that there is no memory region
+ // in the memory list that covers the instruction pointer from
+ // the exception record.
+ Minidump minidump(minidump_path);
+ ASSERT_TRUE(minidump.Read());
+
+ MinidumpException* exception = minidump.GetException();
+ ASSERT_TRUE(exception);
+
+ MinidumpContext* exception_context = exception->GetContext();
+ ASSERT_TRUE(exception_context);
+
+ uint64_t instruction_pointer;
+ ASSERT_TRUE(exception_context->GetInstructionPointer(&instruction_pointer));
+ EXPECT_EQ(instruction_pointer, 0u);
+
+ MinidumpMemoryList* memory_list = minidump.GetMemoryList();
+ ASSERT_TRUE(memory_list);
+
+ unsigned int region_count = memory_list->region_count();
+ ASSERT_GE(region_count, 1u);
+
+ for (unsigned int region_index = 0;
+ region_index < region_count;
+ ++region_index) {
+ MinidumpMemoryRegion* region =
+ memory_list->GetMemoryRegionAtIndex(region_index);
+ uint64_t region_base = region->GetBase();
+ EXPECT_FALSE(instruction_pointer >= region_base &&
+ instruction_pointer < region_base + region->GetSize());
+ }
+
+ unlink(minidump_path.c_str());
+}
+
+#endif // !ADDRESS_SANITIZER
+
+// Test that anonymous memory maps can be annotated with names and IDs.
+TEST(ExceptionHandlerTest, ModuleInfo) {
+ // These are defined here so the parent can use them to check the
+ // data from the minidump afterwards.
+ const uint32_t kMemorySize = sysconf(_SC_PAGESIZE);
+ const char* kMemoryName = "a fake module";
+ const uint8_t kModuleGUID[sizeof(MDGUID)] = {
+ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+ 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF
+ };
+ const string module_identifier = "33221100554477668899AABBCCDDEEFF0";
+
+ // Get some memory.
+ char* memory =
+ reinterpret_cast<char*>(mmap(NULL,
+ kMemorySize,
+ PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANON,
+ -1,
+ 0));
+ const uintptr_t kMemoryAddress = reinterpret_cast<uintptr_t>(memory);
+ ASSERT_TRUE(memory);
+
+ PageAllocator allocator;
+ auto_wasteful_vector<uint8_t, sizeof(MDGUID)> guid(&allocator);
+ guid.assign(std::begin(kModuleGUID), std::end(kModuleGUID));
+ AutoTempDir temp_dir;
+ ExceptionHandler handler(
+ MinidumpDescriptor(temp_dir.path()), NULL, NULL, NULL, true, -1);
+
+ // Add info about the anonymous memory mapping.
+ handler.AddMappingInfo(kMemoryName,
+ guid,
+ kMemoryAddress,
+ kMemorySize,
+ 0);
+ ASSERT_TRUE(handler.WriteMinidump());
+
+ const MinidumpDescriptor& minidump_desc = handler.minidump_descriptor();
+ // Read the minidump. Load the module list, and ensure that the mmap'ed
+ // |memory| is listed with the given module name and debug ID.
+ Minidump minidump(minidump_desc.path());
+ ASSERT_TRUE(minidump.Read());
+
+ MinidumpModuleList* module_list = minidump.GetModuleList();
+ ASSERT_TRUE(module_list);
+ const MinidumpModule* module =
+ module_list->GetModuleForAddress(kMemoryAddress);
+ ASSERT_TRUE(module);
+
+ EXPECT_EQ(kMemoryAddress, module->base_address());
+ EXPECT_EQ(kMemorySize, module->size());
+ EXPECT_EQ(kMemoryName, module->code_file());
+ EXPECT_EQ(module_identifier, module->debug_identifier());
+
+ unlink(minidump_desc.path());
+}
+
+#ifndef ADDRESS_SANITIZER
+
+static const unsigned kControlMsgSize =
+ CMSG_SPACE(sizeof(int)) + CMSG_SPACE(sizeof(struct ucred));
+
+static bool
+CrashHandler(const void* crash_context, size_t crash_context_size,
+ void* context) {
+ const int fd = (intptr_t) context;
+ int fds[2];
+ if (pipe(fds) == -1) {
+ // There doesn't seem to be any way to reliably handle
+ // this failure without the parent process hanging
+ // At least make sure that this process doesn't access
+ // unexpected file descriptors
+ fds[0] = -1;
+ fds[1] = -1;
+ }
+ struct kernel_msghdr msg = {0};
+ struct kernel_iovec iov;
+ iov.iov_base = const_cast<void*>(crash_context);
+ iov.iov_len = crash_context_size;
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+ char cmsg[kControlMsgSize];
+ memset(cmsg, 0, kControlMsgSize);
+ msg.msg_control = cmsg;
+ msg.msg_controllen = sizeof(cmsg);
+
+ struct cmsghdr *hdr = CMSG_FIRSTHDR(&msg);
+ hdr->cmsg_level = SOL_SOCKET;
+ hdr->cmsg_type = SCM_RIGHTS;
+ hdr->cmsg_len = CMSG_LEN(sizeof(int));
+ *((int*) CMSG_DATA(hdr)) = fds[1];
+ hdr = CMSG_NXTHDR((struct msghdr*) &msg, hdr);
+ hdr->cmsg_level = SOL_SOCKET;
+ hdr->cmsg_type = SCM_CREDENTIALS;
+ hdr->cmsg_len = CMSG_LEN(sizeof(struct ucred));
+ struct ucred *cred = reinterpret_cast<struct ucred*>(CMSG_DATA(hdr));
+ cred->uid = getuid();
+ cred->gid = getgid();
+ cred->pid = getpid();
+
+ ssize_t ret = HANDLE_EINTR(sys_sendmsg(fd, &msg, 0));
+ sys_close(fds[1]);
+ if (ret <= 0)
+ return false;
+
+ char b;
+ IGNORE_RET(HANDLE_EINTR(sys_read(fds[0], &b, 1)));
+
+ return true;
+}
+
+TEST(ExceptionHandlerTest, ExternalDumper) {
+ int fds[2];
+ ASSERT_NE(socketpair(AF_UNIX, SOCK_DGRAM, 0, fds), -1);
+ static const int on = 1;
+ setsockopt(fds[0], SOL_SOCKET, SO_PASSCRED, &on, sizeof(on));
+ setsockopt(fds[1], SOL_SOCKET, SO_PASSCRED, &on, sizeof(on));
+
+ const pid_t child = fork();
+ if (child == 0) {
+ close(fds[0]);
+ ExceptionHandler handler(MinidumpDescriptor("/tmp1"), NULL, NULL,
+ reinterpret_cast<void*>(fds[1]), true, -1);
+ handler.set_crash_handler(CrashHandler);
+ DoNullPointerDereference();
+ }
+ close(fds[1]);
+ struct msghdr msg = {0};
+ struct iovec iov;
+ static const unsigned kCrashContextSize =
+ sizeof(ExceptionHandler::CrashContext);
+ char context[kCrashContextSize];
+ char control[kControlMsgSize];
+ iov.iov_base = context;
+ iov.iov_len = kCrashContextSize;
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+ msg.msg_control = control;
+ msg.msg_controllen = kControlMsgSize;
+
+ const ssize_t n = HANDLE_EINTR(recvmsg(fds[0], &msg, 0));
+ ASSERT_EQ(static_cast<ssize_t>(kCrashContextSize), n);
+ ASSERT_EQ(kControlMsgSize, msg.msg_controllen);
+ ASSERT_EQ(static_cast<__typeof__(msg.msg_flags)>(0), msg.msg_flags);
+ ASSERT_EQ(0, close(fds[0]));
+
+ pid_t crashing_pid = -1;
+ int signal_fd = -1;
+ for (struct cmsghdr *hdr = CMSG_FIRSTHDR(&msg); hdr;
+ hdr = CMSG_NXTHDR(&msg, hdr)) {
+ if (hdr->cmsg_level != SOL_SOCKET)
+ continue;
+ if (hdr->cmsg_type == SCM_RIGHTS) {
+ const unsigned len = hdr->cmsg_len -
+ (((uint8_t*)CMSG_DATA(hdr)) - (uint8_t*)hdr);
+ ASSERT_EQ(sizeof(int), len);
+ signal_fd = *(reinterpret_cast<int*>(CMSG_DATA(hdr)));
+ } else if (hdr->cmsg_type == SCM_CREDENTIALS) {
+ const struct ucred *cred =
+ reinterpret_cast<struct ucred*>(CMSG_DATA(hdr));
+ crashing_pid = cred->pid;
+ }
+ }
+
+ ASSERT_NE(crashing_pid, -1);
+ ASSERT_NE(signal_fd, -1);
+
+ AutoTempDir temp_dir;
+ string templ = temp_dir.path() + "/exception-handler-unittest";
+ ASSERT_TRUE(WriteMinidump(templ.c_str(), crashing_pid, context,
+ kCrashContextSize));
+ static const char b = 0;
+ ASSERT_EQ(1, (HANDLE_EINTR(write(signal_fd, &b, 1))));
+ ASSERT_EQ(0, close(signal_fd));
+
+ ASSERT_NO_FATAL_FAILURE(WaitForProcessToTerminate(child, SIGSEGV));
+
+ struct stat st;
+ ASSERT_EQ(0, stat(templ.c_str(), &st));
+ ASSERT_GT(st.st_size, 0);
+ unlink(templ.c_str());
+}
+
+#endif // !ADDRESS_SANITIZER
+
+TEST(ExceptionHandlerTest, WriteMinidumpExceptionStream) {
+ AutoTempDir temp_dir;
+ ExceptionHandler handler(MinidumpDescriptor(temp_dir.path()), NULL, NULL,
+ NULL, false, -1);
+ ASSERT_TRUE(handler.WriteMinidump());
+
+ string minidump_path = handler.minidump_descriptor().path();
+
+ // Read the minidump and check the exception stream.
+ Minidump minidump(minidump_path);
+ ASSERT_TRUE(minidump.Read());
+ MinidumpException* exception = minidump.GetException();
+ ASSERT_TRUE(exception);
+ const MDRawExceptionStream* raw = exception->exception();
+ ASSERT_TRUE(raw);
+ EXPECT_EQ(MD_EXCEPTION_CODE_LIN_DUMP_REQUESTED,
+ raw->exception_record.exception_code);
+}
+
+TEST(ExceptionHandlerTest, GenerateMultipleDumpsWithFD) {
+ AutoTempDir temp_dir;
+ string path;
+ const int fd = CreateTMPFile(temp_dir.path(), &path);
+ ExceptionHandler handler(MinidumpDescriptor(fd), NULL, NULL, NULL, false, -1);
+ ASSERT_TRUE(handler.WriteMinidump());
+ // Check by the size of the data written to the FD that a minidump was
+ // generated.
+ off_t size = lseek(fd, 0, SEEK_CUR);
+ ASSERT_GT(size, 0);
+
+ // Generate another minidump.
+ ASSERT_TRUE(handler.WriteMinidump());
+ size = lseek(fd, 0, SEEK_CUR);
+ ASSERT_GT(size, 0);
+}
+
+TEST(ExceptionHandlerTest, GenerateMultipleDumpsWithPath) {
+ AutoTempDir temp_dir;
+ ExceptionHandler handler(MinidumpDescriptor(temp_dir.path()), NULL, NULL,
+ NULL, false, -1);
+ ASSERT_TRUE(handler.WriteMinidump());
+
+ const MinidumpDescriptor& minidump_1 = handler.minidump_descriptor();
+ struct stat st;
+ ASSERT_EQ(0, stat(minidump_1.path(), &st));
+ ASSERT_GT(st.st_size, 0);
+ string minidump_1_path(minidump_1.path());
+ // Check it is a valid minidump.
+ Minidump minidump1(minidump_1_path);
+ ASSERT_TRUE(minidump1.Read());
+ unlink(minidump_1.path());
+
+ // Generate another minidump, it should go to a different file.
+ ASSERT_TRUE(handler.WriteMinidump());
+ const MinidumpDescriptor& minidump_2 = handler.minidump_descriptor();
+ ASSERT_EQ(0, stat(minidump_2.path(), &st));
+ ASSERT_GT(st.st_size, 0);
+ string minidump_2_path(minidump_2.path());
+ // Check it is a valid minidump.
+ Minidump minidump2(minidump_2_path);
+ ASSERT_TRUE(minidump2.Read());
+ unlink(minidump_2.path());
+
+ // 2 distinct files should be produced.
+ ASSERT_STRNE(minidump_1_path.c_str(), minidump_2_path.c_str());
+}
+
+// Test that an additional memory region can be added to the minidump.
+TEST(ExceptionHandlerTest, AdditionalMemory) {
+ const uint32_t kMemorySize = sysconf(_SC_PAGESIZE);
+
+ // Get some heap memory.
+ uint8_t* memory = new uint8_t[kMemorySize];
+ const uintptr_t kMemoryAddress = reinterpret_cast<uintptr_t>(memory);
+ ASSERT_TRUE(memory);
+
+ // Stick some data into the memory so the contents can be verified.
+ for (uint32_t i = 0; i < kMemorySize; ++i) {
+ memory[i] = i % 255;
+ }
+
+ AutoTempDir temp_dir;
+ ExceptionHandler handler(
+ MinidumpDescriptor(temp_dir.path()), NULL, NULL, NULL, true, -1);
+
+ // Add the memory region to the list of memory to be included.
+ handler.RegisterAppMemory(memory, kMemorySize);
+ handler.WriteMinidump();
+
+ const MinidumpDescriptor& minidump_desc = handler.minidump_descriptor();
+
+ // Read the minidump. Ensure that the memory region is present
+ Minidump minidump(minidump_desc.path());
+ ASSERT_TRUE(minidump.Read());
+
+ MinidumpMemoryList* dump_memory_list = minidump.GetMemoryList();
+ ASSERT_TRUE(dump_memory_list);
+ const MinidumpMemoryRegion* region =
+ dump_memory_list->GetMemoryRegionForAddress(kMemoryAddress);
+ ASSERT_TRUE(region);
+
+ EXPECT_EQ(kMemoryAddress, region->GetBase());
+ EXPECT_EQ(kMemorySize, region->GetSize());
+
+ // Verify memory contents.
+ EXPECT_EQ(0, memcmp(region->GetMemory(), memory, kMemorySize));
+
+ delete[] memory;
+}
+
+// Test that a memory region that was previously registered
+// can be unregistered.
+TEST(ExceptionHandlerTest, AdditionalMemoryRemove) {
+ const uint32_t kMemorySize = sysconf(_SC_PAGESIZE);
+
+ // Get some heap memory.
+ uint8_t* memory = new uint8_t[kMemorySize];
+ const uintptr_t kMemoryAddress = reinterpret_cast<uintptr_t>(memory);
+ ASSERT_TRUE(memory);
+
+ AutoTempDir temp_dir;
+ ExceptionHandler handler(
+ MinidumpDescriptor(temp_dir.path()), NULL, NULL, NULL, true, -1);
+
+ // Add the memory region to the list of memory to be included.
+ handler.RegisterAppMemory(memory, kMemorySize);
+
+ // ...and then remove it
+ handler.UnregisterAppMemory(memory);
+ handler.WriteMinidump();
+
+ const MinidumpDescriptor& minidump_desc = handler.minidump_descriptor();
+
+ // Read the minidump. Ensure that the memory region is not present.
+ Minidump minidump(minidump_desc.path());
+ ASSERT_TRUE(minidump.Read());
+
+ MinidumpMemoryList* dump_memory_list = minidump.GetMemoryList();
+ ASSERT_TRUE(dump_memory_list);
+ const MinidumpMemoryRegion* region =
+ dump_memory_list->GetMemoryRegionForAddress(kMemoryAddress);
+ EXPECT_FALSE(region);
+
+ delete[] memory;
+}
+
+static bool SimpleCallback(const MinidumpDescriptor& descriptor,
+ void* context,
+ bool succeeded) {
+ string* filename = reinterpret_cast<string*>(context);
+ *filename = descriptor.path();
+ return true;
+}
+
+TEST(ExceptionHandlerTest, WriteMinidumpForChild) {
+ int fds[2];
+ ASSERT_NE(-1, pipe(fds));
+
+ const pid_t child = fork();
+ if (child == 0) {
+ close(fds[1]);
+ char b;
+ HANDLE_EINTR(read(fds[0], &b, sizeof(b)));
+ close(fds[0]);
+ syscall(__NR_exit);
+ }
+ close(fds[0]);
+
+ AutoTempDir temp_dir;
+ string minidump_filename;
+ ASSERT_TRUE(
+ ExceptionHandler::WriteMinidumpForChild(child, child,
+ temp_dir.path(), SimpleCallback,
+ (void*)&minidump_filename));
+
+ Minidump minidump(minidump_filename);
+ ASSERT_TRUE(minidump.Read());
+ // Check that the crashing thread is the main thread of |child|
+ MinidumpException* exception = minidump.GetException();
+ ASSERT_TRUE(exception);
+ uint32_t thread_id;
+ ASSERT_TRUE(exception->GetThreadID(&thread_id));
+ EXPECT_EQ(child, static_cast<int32_t>(thread_id));
+
+ const MDRawExceptionStream* raw = exception->exception();
+ ASSERT_TRUE(raw);
+ EXPECT_EQ(MD_EXCEPTION_CODE_LIN_DUMP_REQUESTED,
+ raw->exception_record.exception_code);
+
+ close(fds[1]);
+ unlink(minidump_filename.c_str());
+}
diff --git a/toolkit/crashreporter/breakpad-client/linux/handler/guid_generator.cc b/toolkit/crashreporter/breakpad-client/linux/handler/guid_generator.cc
new file mode 100644
index 0000000000..b0ef05bd9d
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/linux/handler/guid_generator.cc
@@ -0,0 +1,108 @@
+// 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 "linux/handler/guid_generator.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 uint16_t BytesToUInt16(const uint8_t bytes[]) {
+ return ((uint16_t) bytes[1] << 8) | ((uint16_t) bytes[0]);
+ }
+
+ // The last field in a GUID is 48 bits long so we're converting only 6 bytes
+ static uint64_t BytesToUInt48(const uint8_t bytes[]) {
+ return ((uint64_t) bytes[0] << 40) | ((uint64_t) bytes[1] << 32) |
+ ((uint64_t) bytes[2] << 24) | ((uint64_t) bytes[3] << 16) |
+ ((uint64_t) bytes[4] << 8) | (uint64_t) bytes[5];
+ }
+
+ 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, size_t 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::BytesToUInt16(&(guid->data4[0])),
+ GUIDGenerator::BytesToUInt48(&(guid->data4[2])));
+ if (num != kGUIDStringLength)
+ return false;
+
+ buf[num] = '\0';
+ return true;
+}
diff --git a/toolkit/crashreporter/breakpad-client/linux/handler/guid_generator.h b/toolkit/crashreporter/breakpad-client/linux/handler/guid_generator.h
new file mode 100644
index 0000000000..de97eda1cb
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/linux/handler/guid_generator.h
@@ -0,0 +1,48 @@
+// 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 LINUX_HANDLER_GUID_GENERATOR_H__
+#define LINUX_HANDLER_GUID_GENERATOR_H__
+
+#include "google_breakpad/common/minidump_format.h"
+
+typedef MDGUID GUID;
+
+// Format string for parsing GUID.
+const char kGUIDFormatString[] = "%08x-%04x-%04x-%04x-%012" PRIx64;
+// Length of GUID string. Don't count the ending '\0'.
+const size_t kGUIDStringLength = 36;
+
+// Create a guid.
+bool CreateGUID(GUID *guid);
+
+// Get the string from guid.
+bool GUIDToString(const GUID *guid, char *buf, size_t buf_len);
+
+#endif
diff --git a/toolkit/crashreporter/breakpad-client/linux/handler/microdump_extra_info.h b/toolkit/crashreporter/breakpad-client/linux/handler/microdump_extra_info.h
new file mode 100644
index 0000000000..bf01f0c7b1
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/linux/handler/microdump_extra_info.h
@@ -0,0 +1,52 @@
+// Copyright 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.
+
+#ifndef CLIENT_LINUX_HANDLER_MICRODUMP_EXTRA_INFO_H_
+#define CLIENT_LINUX_HANDLER_MICRODUMP_EXTRA_INFO_H_
+
+namespace google_breakpad {
+
+struct MicrodumpExtraInfo {
+ // Strings pointed to by this struct are not copied, and are
+ // expected to remain valid for the lifetime of the process.
+ const char* build_fingerprint;
+ const char* product_info;
+ const char* gpu_fingerprint;
+ const char* process_type;
+
+ MicrodumpExtraInfo()
+ : build_fingerprint(NULL),
+ product_info(NULL),
+ gpu_fingerprint(NULL),
+ process_type(NULL) {}
+};
+
+}
+
+#endif // CLIENT_LINUX_HANDLER_MICRODUMP_EXTRA_INFO_H_
diff --git a/toolkit/crashreporter/breakpad-client/linux/handler/minidump_descriptor.cc b/toolkit/crashreporter/breakpad-client/linux/handler/minidump_descriptor.cc
new file mode 100644
index 0000000000..21cf4b0dce
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/linux/handler/minidump_descriptor.cc
@@ -0,0 +1,96 @@
+// 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 <stdio.h>
+
+#include "linux/handler/guid_generator.h"
+#include "linux/handler/minidump_descriptor.h"
+
+namespace google_breakpad {
+
+//static
+const MinidumpDescriptor::MicrodumpOnConsole
+ MinidumpDescriptor::kMicrodumpOnConsole = {};
+
+MinidumpDescriptor::MinidumpDescriptor(const MinidumpDescriptor& descriptor)
+ : mode_(descriptor.mode_),
+ fd_(descriptor.fd_),
+ directory_(descriptor.directory_),
+ c_path_(NULL),
+ size_limit_(descriptor.size_limit_),
+ address_within_principal_mapping_(
+ descriptor.address_within_principal_mapping_),
+ skip_dump_if_principal_mapping_not_referenced_(
+ descriptor.skip_dump_if_principal_mapping_not_referenced_),
+ sanitize_stacks_(descriptor.sanitize_stacks_),
+ microdump_extra_info_(descriptor.microdump_extra_info_) {
+ // The copy constructor is not allowed to be called on a MinidumpDescriptor
+ // with a valid path_, as getting its c_path_ would require the heap which
+ // can cause problems in compromised environments.
+ assert(descriptor.path_.empty());
+}
+
+MinidumpDescriptor& MinidumpDescriptor::operator=(
+ const MinidumpDescriptor& descriptor) {
+ assert(descriptor.path_.empty());
+
+ mode_ = descriptor.mode_;
+ fd_ = descriptor.fd_;
+ directory_ = descriptor.directory_;
+ path_.clear();
+ if (c_path_) {
+ // This descriptor already had a path set, so generate a new one.
+ c_path_ = NULL;
+ UpdatePath();
+ }
+ size_limit_ = descriptor.size_limit_;
+ address_within_principal_mapping_ =
+ descriptor.address_within_principal_mapping_;
+ skip_dump_if_principal_mapping_not_referenced_ =
+ descriptor.skip_dump_if_principal_mapping_not_referenced_;
+ sanitize_stacks_ = descriptor.sanitize_stacks_;
+ microdump_extra_info_ = descriptor.microdump_extra_info_;
+ return *this;
+}
+
+void MinidumpDescriptor::UpdatePath() {
+ assert(mode_ == kWriteMinidumpToFile && !directory_.empty());
+
+ GUID guid;
+ char guid_str[kGUIDStringLength + 1];
+ if (!CreateGUID(&guid) || !GUIDToString(&guid, guid_str, sizeof(guid_str))) {
+ assert(false);
+ }
+
+ path_.clear();
+ path_ = directory_ + "/" + guid_str + ".dmp";
+ c_path_ = path_.c_str();
+}
+
+} // namespace google_breakpad
diff --git a/toolkit/crashreporter/breakpad-client/linux/handler/minidump_descriptor.h b/toolkit/crashreporter/breakpad-client/linux/handler/minidump_descriptor.h
new file mode 100644
index 0000000000..c3deae8a74
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/linux/handler/minidump_descriptor.h
@@ -0,0 +1,199 @@
+// 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 CLIENT_LINUX_HANDLER_MINIDUMP_DESCRIPTOR_H_
+#define CLIENT_LINUX_HANDLER_MINIDUMP_DESCRIPTOR_H_
+
+#include <assert.h>
+#include <sys/types.h>
+
+#include <string>
+
+#include "linux/handler/microdump_extra_info.h"
+#include "common/using_std_string.h"
+
+// This class describes how a crash dump should be generated, either:
+// - Writing a full minidump to a file in a given directory (the actual path,
+// inside the directory, is determined by this class).
+// - Writing a full minidump to a given fd.
+// - Writing a reduced microdump to the console (logcat on Android).
+namespace google_breakpad {
+
+class MinidumpDescriptor {
+ public:
+ struct MicrodumpOnConsole {};
+ static const MicrodumpOnConsole kMicrodumpOnConsole;
+
+ MinidumpDescriptor()
+ : mode_(kUninitialized),
+ fd_(-1),
+ size_limit_(-1),
+ address_within_principal_mapping_(0),
+ skip_dump_if_principal_mapping_not_referenced_(false) {}
+
+ explicit MinidumpDescriptor(const string& directory)
+ : mode_(kWriteMinidumpToFile),
+ fd_(-1),
+ directory_(directory),
+ c_path_(NULL),
+ size_limit_(-1),
+ address_within_principal_mapping_(0),
+ skip_dump_if_principal_mapping_not_referenced_(false),
+ sanitize_stacks_(false) {
+ assert(!directory.empty());
+ }
+
+ explicit MinidumpDescriptor(int fd)
+ : mode_(kWriteMinidumpToFd),
+ fd_(fd),
+ c_path_(NULL),
+ size_limit_(-1),
+ address_within_principal_mapping_(0),
+ skip_dump_if_principal_mapping_not_referenced_(false),
+ sanitize_stacks_(false) {
+ assert(fd != -1);
+ }
+
+ explicit MinidumpDescriptor(const MicrodumpOnConsole&)
+ : mode_(kWriteMicrodumpToConsole),
+ fd_(-1),
+ size_limit_(-1),
+ address_within_principal_mapping_(0),
+ skip_dump_if_principal_mapping_not_referenced_(false),
+ sanitize_stacks_(false) {}
+
+ explicit MinidumpDescriptor(const MinidumpDescriptor& descriptor);
+ MinidumpDescriptor& operator=(const MinidumpDescriptor& descriptor);
+
+ static MinidumpDescriptor getMicrodumpDescriptor();
+
+ bool IsFD() const { return mode_ == kWriteMinidumpToFd; }
+
+ int fd() const { return fd_; }
+
+ string directory() const { return directory_; }
+
+ const char* path() const { return c_path_; }
+
+ bool IsMicrodumpOnConsole() const {
+ return mode_ == kWriteMicrodumpToConsole;
+ }
+
+ // Updates the path so it is unique.
+ // Should be called from a normal context: this methods uses the heap.
+ void UpdatePath();
+
+ off_t size_limit() const { return size_limit_; }
+ void set_size_limit(off_t limit) { size_limit_ = limit; }
+
+ uintptr_t address_within_principal_mapping() const {
+ return address_within_principal_mapping_;
+ }
+ void set_address_within_principal_mapping(
+ uintptr_t address_within_principal_mapping) {
+ address_within_principal_mapping_ = address_within_principal_mapping;
+ }
+
+ bool skip_dump_if_principal_mapping_not_referenced() {
+ return skip_dump_if_principal_mapping_not_referenced_;
+ }
+ void set_skip_dump_if_principal_mapping_not_referenced(
+ bool skip_dump_if_principal_mapping_not_referenced) {
+ skip_dump_if_principal_mapping_not_referenced_ =
+ skip_dump_if_principal_mapping_not_referenced;
+ }
+
+ bool sanitize_stacks() const { return sanitize_stacks_; }
+ void set_sanitize_stacks(bool sanitize_stacks) {
+ sanitize_stacks_ = sanitize_stacks;
+ }
+
+ MicrodumpExtraInfo* microdump_extra_info() {
+ assert(IsMicrodumpOnConsole());
+ return &microdump_extra_info_;
+ }
+
+ private:
+ enum DumpMode {
+ kUninitialized = 0,
+ kWriteMinidumpToFile,
+ kWriteMinidumpToFd,
+ kWriteMicrodumpToConsole
+ };
+
+ // Specifies the dump mode (see DumpMode).
+ DumpMode mode_;
+
+ // The file descriptor where the minidump is generated.
+ int fd_;
+
+ // The directory where the minidump should be generated.
+ string directory_;
+
+ // The full path to the generated minidump.
+ string path_;
+
+ // The C string of |path_|. Precomputed so it can be access from a compromised
+ // context.
+ const char* c_path_;
+
+ off_t size_limit_;
+
+ // This member points somewhere into the main module for this
+ // process (the module that is considerered interesting for the
+ // purposes of debugging crashes).
+ uintptr_t address_within_principal_mapping_;
+
+ // If set, threads that do not reference the address range
+ // associated with |address_within_principal_mapping_| will not have their
+ // stacks logged.
+ bool skip_dump_if_principal_mapping_not_referenced_;
+
+ // If set, stacks are sanitized to remove PII. This involves
+ // overwriting any pointer-aligned words that are not either
+ // pointers into a process mapping or small integers (+/-4096). This
+ // leaves enough information to unwind stacks, and preserve some
+ // register values, but elides strings and other program data.
+ bool sanitize_stacks_;
+
+ // The extra microdump data (e.g. product name/version, build
+ // fingerprint, gpu fingerprint) that should be appended to the dump
+ // (microdump only). Microdumps don't have the ability of appending
+ // extra metadata after the dump is generated (as opposite to
+ // minidumps MIME fields), therefore the extra data must be provided
+ // upfront. Any memory pointed to by members of the
+ // MicrodumpExtraInfo struct must be valid for the lifetime of the
+ // process (read: the caller has to guarantee that it is stored in
+ // global static storage.)
+ MicrodumpExtraInfo microdump_extra_info_;
+};
+
+} // namespace google_breakpad
+
+#endif // CLIENT_LINUX_HANDLER_MINIDUMP_DESCRIPTOR_H_
diff --git a/toolkit/crashreporter/breakpad-client/linux/log/log.cc b/toolkit/crashreporter/breakpad-client/linux/log/log.cc
new file mode 100644
index 0000000000..3346acc6d8
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/linux/log/log.cc
@@ -0,0 +1,84 @@
+// 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 "linux/log/log.h"
+
+#if defined(__ANDROID__)
+#include <android/log.h>
+#include <dlfcn.h>
+#else
+#include "third_party/lss/linux_syscall_support.h"
+#endif
+
+namespace logger {
+
+#if defined(__ANDROID__)
+namespace {
+
+// __android_log_buf_write() is not exported in the NDK and is being used by
+// dynamic runtime linking. Its declaration is taken from Android's
+// system/core/include/log/log.h.
+using AndroidLogBufferWriteFunc = int (*)(int bufID, int prio, const char *tag,
+ const char *text);
+const int kAndroidCrashLogId = 4; // From LOG_ID_CRASH in log.h.
+const char kAndroidLogTag[] = "google-breakpad";
+
+bool g_crash_log_initialized = false;
+AndroidLogBufferWriteFunc g_android_log_buf_write = nullptr;
+
+} // namespace
+
+void initializeCrashLogWriter() {
+ if (g_crash_log_initialized)
+ return;
+ g_android_log_buf_write = reinterpret_cast<AndroidLogBufferWriteFunc>(
+ dlsym(RTLD_DEFAULT, "__android_log_buf_write"));
+ g_crash_log_initialized = true;
+}
+
+int writeToCrashLog(const char* buf) {
+ // Try writing to the crash log ring buffer. If not available, fall back to
+ // the standard log buffer.
+ if (g_android_log_buf_write) {
+ return g_android_log_buf_write(kAndroidCrashLogId, ANDROID_LOG_FATAL,
+ kAndroidLogTag, buf);
+ }
+ return __android_log_write(ANDROID_LOG_FATAL, kAndroidLogTag, buf);
+}
+#endif
+
+int write(const char* buf, size_t nbytes) {
+#if defined(__ANDROID__)
+ return __android_log_write(ANDROID_LOG_WARN, kAndroidLogTag, buf);
+#else
+ return sys_write(2, buf, nbytes);
+#endif
+}
+
+} // namespace logger
diff --git a/toolkit/crashreporter/breakpad-client/linux/log/log.h b/toolkit/crashreporter/breakpad-client/linux/log/log.h
new file mode 100644
index 0000000000..f94bbd5fb7
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/linux/log/log.h
@@ -0,0 +1,55 @@
+// 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 CLIENT_LINUX_LOG_LOG_H_
+#define CLIENT_LINUX_LOG_LOG_H_
+
+#include <stddef.h>
+
+namespace logger {
+
+int write(const char* buf, size_t nbytes);
+
+// In the case of Android the log can be written to the default system log
+// (default behavior of write() above, or to the crash log (see
+// writeToCrashLog() below).
+#if defined(__ANDROID__)
+
+// The logger must be initialized in a non-compromised context.
+void initializeCrashLogWriter();
+
+// Once initialized, writeToCrashLog is safe to use in a compromised context,
+// even if the initialization failed, in which case this will silently fall
+// back on write().
+int writeToCrashLog(const char* buf);
+#endif
+
+} // namespace logger
+
+#endif // CLIENT_LINUX_LOG_LOG_H_
diff --git a/toolkit/crashreporter/breakpad-client/linux/microdump_writer/microdump_writer.cc b/toolkit/crashreporter/breakpad-client/linux/microdump_writer/microdump_writer.cc
new file mode 100644
index 0000000000..8f25b7be02
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/linux/microdump_writer/microdump_writer.cc
@@ -0,0 +1,664 @@
+// 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.
+
+// This translation unit generates microdumps into the console (logcat on
+// Android). See crbug.com/410294 for more info and design docs.
+
+#include "linux/microdump_writer/microdump_writer.h"
+
+#include <limits>
+
+#include <sys/utsname.h>
+
+#include "linux/dump_writer_common/thread_info.h"
+#include "linux/dump_writer_common/ucontext_reader.h"
+#include "linux/handler/exception_handler.h"
+#include "linux/handler/microdump_extra_info.h"
+#include "linux/log/log.h"
+#include "linux/minidump_writer/linux_ptrace_dumper.h"
+#include "common/linux/file_id.h"
+#include "common/linux/linux_libc_support.h"
+#include "common/memory_allocator.h"
+
+namespace {
+
+using google_breakpad::auto_wasteful_vector;
+using google_breakpad::ExceptionHandler;
+using google_breakpad::kDefaultBuildIdSize;
+using google_breakpad::LinuxDumper;
+using google_breakpad::LinuxPtraceDumper;
+using google_breakpad::MappingInfo;
+using google_breakpad::MappingList;
+using google_breakpad::MicrodumpExtraInfo;
+using google_breakpad::RawContextCPU;
+using google_breakpad::ThreadInfo;
+using google_breakpad::UContextReader;
+
+const size_t kLineBufferSize = 2048;
+
+#if !defined(__LP64__)
+// The following are only used by DumpFreeSpace, so need to be compiled
+// in conditionally in the same way.
+
+template <typename Dst, typename Src>
+Dst saturated_cast(Src src) {
+ if (src >= std::numeric_limits<Dst>::max())
+ return std::numeric_limits<Dst>::max();
+ if (src <= std::numeric_limits<Dst>::min())
+ return std::numeric_limits<Dst>::min();
+ return static_cast<Dst>(src);
+}
+
+int Log2Floor(uint64_t n) {
+ // Copied from chromium src/base/bits.h
+ if (n == 0)
+ return -1;
+ int log = 0;
+ uint64_t value = n;
+ for (int i = 5; i >= 0; --i) {
+ int shift = (1 << i);
+ uint64_t x = value >> shift;
+ if (x != 0) {
+ value = x;
+ log += shift;
+ }
+ }
+ assert(value == 1u);
+ return log;
+}
+
+bool MappingsAreAdjacent(const MappingInfo& a, const MappingInfo& b) {
+ // Because of load biasing, we can end up with a situation where two
+ // mappings actually overlap. So we will define adjacency to also include a
+ // b start address that lies within a's address range (including starting
+ // immediately after a).
+ // Because load biasing only ever moves the start address backwards, the end
+ // address should still increase.
+ return a.start_addr <= b.start_addr && a.start_addr + a.size >= b.start_addr;
+}
+
+bool MappingLessThan(const MappingInfo* a, const MappingInfo* b) {
+ // Return true if mapping a is before mapping b.
+ // For the same reason (load biasing) we compare end addresses, which - unlike
+ // start addresses - will not have been modified.
+ return a->start_addr + a->size < b->start_addr + b->size;
+}
+
+size_t NextOrderedMapping(
+ const google_breakpad::wasteful_vector<MappingInfo*>& mappings,
+ size_t curr) {
+ // Find the mapping that directly follows mappings[curr].
+ // If no such mapping exists, return |invalid| to indicate this.
+ const size_t invalid = std::numeric_limits<size_t>::max();
+ size_t best = invalid;
+ for (size_t next = 0; next < mappings.size(); ++next) {
+ if (MappingLessThan(mappings[curr], mappings[next]) &&
+ (best == invalid || MappingLessThan(mappings[next], mappings[best]))) {
+ best = next;
+ }
+ }
+ return best;
+}
+
+#endif // !__LP64__
+
+class MicrodumpWriter {
+ public:
+ MicrodumpWriter(const ExceptionHandler::CrashContext* context,
+ const MappingList& mappings,
+ bool skip_dump_if_principal_mapping_not_referenced,
+ uintptr_t address_within_principal_mapping,
+ bool sanitize_stack,
+ const MicrodumpExtraInfo& microdump_extra_info,
+ LinuxDumper* dumper)
+ : ucontext_(context ? &context->context : NULL),
+#if !defined(__ARM_EABI__) && !defined(__mips__)
+ float_state_(context ? &context->float_state : NULL),
+#endif
+ dumper_(dumper),
+ mapping_list_(mappings),
+ skip_dump_if_principal_mapping_not_referenced_(
+ skip_dump_if_principal_mapping_not_referenced),
+ address_within_principal_mapping_(address_within_principal_mapping),
+ sanitize_stack_(sanitize_stack),
+ microdump_extra_info_(microdump_extra_info),
+ log_line_(NULL),
+ stack_copy_(NULL),
+ stack_len_(0),
+ stack_lower_bound_(0),
+ stack_pointer_(0) {
+ log_line_ = reinterpret_cast<char*>(Alloc(kLineBufferSize));
+ if (log_line_)
+ log_line_[0] = '\0'; // Clear out the log line buffer.
+ }
+
+ ~MicrodumpWriter() { dumper_->ThreadsResume(); }
+
+ bool Init() {
+ // In the exceptional case where the system was out of memory and there
+ // wasn't even room to allocate the line buffer, bail out. There is nothing
+ // useful we can possibly achieve without the ability to Log. At least let's
+ // try to not crash.
+ if (!dumper_->Init() || !log_line_)
+ return false;
+ return dumper_->ThreadsSuspend() && dumper_->LateInit();
+ }
+
+ void Dump() {
+ CaptureResult stack_capture_result = CaptureCrashingThreadStack(-1);
+ if (stack_capture_result == CAPTURE_UNINTERESTING) {
+ LogLine("Microdump skipped (uninteresting)");
+ return;
+ }
+
+ LogLine("-----BEGIN BREAKPAD MICRODUMP-----");
+ DumpProductInformation();
+ DumpOSInformation();
+ DumpProcessType();
+ DumpCrashReason();
+ DumpGPUInformation();
+#if !defined(__LP64__)
+ DumpFreeSpace();
+#endif
+ if (stack_capture_result == CAPTURE_OK)
+ DumpThreadStack();
+ DumpCPUState();
+ DumpMappings();
+ LogLine("-----END BREAKPAD MICRODUMP-----");
+ }
+
+ private:
+ enum CaptureResult { CAPTURE_OK, CAPTURE_FAILED, CAPTURE_UNINTERESTING };
+
+ // Writes one line to the system log.
+ void LogLine(const char* msg) {
+#if defined(__ANDROID__)
+ logger::writeToCrashLog(msg);
+#else
+ logger::write(msg, my_strlen(msg));
+ logger::write("\n", 1);
+#endif
+ }
+
+ // Stages the given string in the current line buffer.
+ void LogAppend(const char* str) {
+ my_strlcat(log_line_, str, kLineBufferSize);
+ }
+
+ // As above (required to take precedence over template specialization below).
+ void LogAppend(char* str) {
+ LogAppend(const_cast<const char*>(str));
+ }
+
+ // Stages the hex repr. of the given int type in the current line buffer.
+ template<typename T>
+ void LogAppend(T value) {
+ // Make enough room to hex encode the largest int type + NUL.
+ static const char HEX[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+ 'A', 'B', 'C', 'D', 'E', 'F'};
+ char hexstr[sizeof(T) * 2 + 1];
+ for (int i = sizeof(T) * 2 - 1; i >= 0; --i, value >>= 4)
+ hexstr[i] = HEX[static_cast<uint8_t>(value) & 0x0F];
+ hexstr[sizeof(T) * 2] = '\0';
+ LogAppend(hexstr);
+ }
+
+ // Stages the buffer content hex-encoded in the current line buffer.
+ void LogAppend(const void* buf, size_t length) {
+ const uint8_t* ptr = reinterpret_cast<const uint8_t*>(buf);
+ for (size_t i = 0; i < length; ++i, ++ptr)
+ LogAppend(*ptr);
+ }
+
+ // Writes out the current line buffer on the system log.
+ void LogCommitLine() {
+ LogLine(log_line_);
+ log_line_[0] = 0;
+ }
+
+ CaptureResult CaptureCrashingThreadStack(int max_stack_len) {
+ stack_pointer_ = UContextReader::GetStackPointer(ucontext_);
+
+ if (!dumper_->GetStackInfo(reinterpret_cast<const void**>(&stack_lower_bound_),
+ &stack_len_, stack_pointer_)) {
+ return CAPTURE_FAILED;
+ }
+
+ if (max_stack_len >= 0 &&
+ stack_len_ > static_cast<size_t>(max_stack_len)) {
+ stack_len_ = max_stack_len;
+ }
+
+ stack_copy_ = reinterpret_cast<uint8_t*>(Alloc(stack_len_));
+ dumper_->CopyFromProcess(stack_copy_, dumper_->crash_thread(),
+ reinterpret_cast<const void*>(stack_lower_bound_),
+ stack_len_);
+
+ if (!skip_dump_if_principal_mapping_not_referenced_) return CAPTURE_OK;
+
+ const MappingInfo* principal_mapping =
+ dumper_->FindMappingNoBias(address_within_principal_mapping_);
+ if (!principal_mapping) return CAPTURE_UNINTERESTING;
+
+ uintptr_t low_addr = principal_mapping->system_mapping_info.start_addr;
+ uintptr_t high_addr = principal_mapping->system_mapping_info.end_addr;
+ uintptr_t pc = UContextReader::GetInstructionPointer(ucontext_);
+ if (low_addr <= pc && pc <= high_addr) return CAPTURE_OK;
+
+ if (dumper_->StackHasPointerToMapping(stack_copy_, stack_len_,
+ stack_pointer_ - stack_lower_bound_,
+ *principal_mapping)) {
+ return CAPTURE_OK;
+ }
+ return CAPTURE_UNINTERESTING;
+ }
+
+ void DumpProductInformation() {
+ LogAppend("V ");
+ if (microdump_extra_info_.product_info) {
+ LogAppend(microdump_extra_info_.product_info);
+ } else {
+ LogAppend("UNKNOWN:0.0.0.0");
+ }
+ LogCommitLine();
+ }
+
+ void DumpProcessType() {
+ LogAppend("P ");
+ if (microdump_extra_info_.process_type) {
+ LogAppend(microdump_extra_info_.process_type);
+ } else {
+ LogAppend("UNKNOWN");
+ }
+ LogCommitLine();
+ }
+
+ void DumpCrashReason() {
+ LogAppend("R ");
+ LogAppend(dumper_->crash_signal());
+ LogAppend(" ");
+ LogAppend(dumper_->GetCrashSignalString());
+ LogAppend(" ");
+ LogAppend(dumper_->crash_address());
+ LogCommitLine();
+ }
+
+ void DumpOSInformation() {
+ const uint8_t n_cpus = static_cast<uint8_t>(sysconf(_SC_NPROCESSORS_CONF));
+
+#if defined(__ANDROID__)
+ const char kOSId[] = "A";
+#else
+ const char kOSId[] = "L";
+#endif
+
+// Dump the runtime architecture. On multiarch devices it might not match the
+// hw architecture (the one returned by uname()), for instance in the case of
+// a 32-bit app running on a aarch64 device.
+#if defined(__aarch64__)
+ const char kArch[] = "arm64";
+#elif defined(__ARMEL__)
+ const char kArch[] = "arm";
+#elif defined(__x86_64__)
+ const char kArch[] = "x86_64";
+#elif defined(__i386__)
+ const char kArch[] = "x86";
+#elif defined(__mips__)
+# if _MIPS_SIM == _ABIO32
+ const char kArch[] = "mips";
+# elif _MIPS_SIM == _ABI64
+ const char kArch[] = "mips64";
+# else
+# error "This mips ABI is currently not supported (n32)"
+#endif
+#else
+#error "This code has not been ported to your platform yet"
+#endif
+
+ LogAppend("O ");
+ LogAppend(kOSId);
+ LogAppend(" ");
+ LogAppend(kArch);
+ LogAppend(" ");
+ LogAppend(n_cpus);
+ LogAppend(" ");
+
+ // Dump the HW architecture (e.g., armv7l, aarch64).
+ struct utsname uts;
+ const bool has_uts_info = (uname(&uts) == 0);
+ const char* hwArch = has_uts_info ? uts.machine : "unknown_hw_arch";
+ LogAppend(hwArch);
+ LogAppend(" ");
+
+ // If the client has attached a build fingerprint to the MinidumpDescriptor
+ // use that one. Otherwise try to get some basic info from uname().
+ if (microdump_extra_info_.build_fingerprint) {
+ LogAppend(microdump_extra_info_.build_fingerprint);
+ } else if (has_uts_info) {
+ LogAppend(uts.release);
+ LogAppend(" ");
+ LogAppend(uts.version);
+ } else {
+ LogAppend("no build fingerprint available");
+ }
+ LogCommitLine();
+ }
+
+ void DumpGPUInformation() {
+ LogAppend("G ");
+ if (microdump_extra_info_.gpu_fingerprint) {
+ LogAppend(microdump_extra_info_.gpu_fingerprint);
+ } else {
+ LogAppend("UNKNOWN");
+ }
+ LogCommitLine();
+ }
+
+ void DumpThreadStack() {
+ if (sanitize_stack_) {
+ dumper_->SanitizeStackCopy(stack_copy_, stack_len_, stack_pointer_,
+ stack_pointer_ - stack_lower_bound_);
+ }
+
+ LogAppend("S 0 ");
+ LogAppend(stack_pointer_);
+ LogAppend(" ");
+ LogAppend(stack_lower_bound_);
+ LogAppend(" ");
+ LogAppend(stack_len_);
+ LogCommitLine();
+
+ const size_t STACK_DUMP_CHUNK_SIZE = 384;
+ for (size_t stack_off = 0; stack_off < stack_len_;
+ stack_off += STACK_DUMP_CHUNK_SIZE) {
+ LogAppend("S ");
+ LogAppend(stack_lower_bound_ + stack_off);
+ LogAppend(" ");
+ LogAppend(stack_copy_ + stack_off,
+ std::min(STACK_DUMP_CHUNK_SIZE, stack_len_ - stack_off));
+ LogCommitLine();
+ }
+ }
+
+ void DumpCPUState() {
+ RawContextCPU cpu;
+ my_memset(&cpu, 0, sizeof(RawContextCPU));
+#if !defined(__ARM_EABI__) && !defined(__mips__)
+ UContextReader::FillCPUContext(&cpu, ucontext_, float_state_);
+#else
+ UContextReader::FillCPUContext(&cpu, ucontext_);
+#endif
+ LogAppend("C ");
+ LogAppend(&cpu, sizeof(cpu));
+ LogCommitLine();
+ }
+
+ // If there is caller-provided information about this mapping
+ // in the mapping_list_ list, return true. Otherwise, return false.
+ bool HaveMappingInfo(const MappingInfo& mapping) {
+ for (MappingList::const_iterator iter = mapping_list_.begin();
+ iter != mapping_list_.end();
+ ++iter) {
+ // Ignore any mappings that are wholly contained within
+ // mappings in the mapping_info_ list.
+ if (mapping.start_addr >= iter->first.start_addr &&
+ (mapping.start_addr + mapping.size) <=
+ (iter->first.start_addr + iter->first.size)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ // Dump information about the provided |mapping|. If |identifier| is non-NULL,
+ // use it instead of calculating a file ID from the mapping.
+ void DumpModule(const MappingInfo& mapping,
+ bool member,
+ unsigned int mapping_id,
+ const std::vector<uint8_t>* identifier) {
+
+ auto_wasteful_vector<uint8_t, kDefaultBuildIdSize> identifier_bytes(
+ dumper_->allocator());
+
+ if (identifier) {
+ // GUID was provided by caller.
+ identifier_bytes.insert(identifier_bytes.end(),
+ identifier->begin(),
+ identifier->end());
+ } else {
+ dumper_->ElfFileIdentifierForMapping(
+ mapping,
+ member,
+ mapping_id,
+ identifier_bytes);
+ }
+
+ // Copy as many bytes of |identifier| as will fit into a MDGUID
+ MDGUID module_identifier = {0};
+ memcpy(&module_identifier, &identifier_bytes[0],
+ std::min(sizeof(MDGUID), identifier_bytes.size()));
+
+ char file_name[NAME_MAX];
+ char file_path[NAME_MAX];
+ dumper_->GetMappingEffectiveNameAndPath(
+ mapping, file_path, sizeof(file_path), file_name, sizeof(file_name));
+
+ LogAppend("M ");
+ LogAppend(static_cast<uintptr_t>(mapping.start_addr));
+ LogAppend(" ");
+ LogAppend(mapping.offset);
+ LogAppend(" ");
+ LogAppend(mapping.size);
+ LogAppend(" ");
+ LogAppend(module_identifier.data1);
+ LogAppend(module_identifier.data2);
+ LogAppend(module_identifier.data3);
+ LogAppend(module_identifier.data4[0]);
+ LogAppend(module_identifier.data4[1]);
+ LogAppend(module_identifier.data4[2]);
+ LogAppend(module_identifier.data4[3]);
+ LogAppend(module_identifier.data4[4]);
+ LogAppend(module_identifier.data4[5]);
+ LogAppend(module_identifier.data4[6]);
+ LogAppend(module_identifier.data4[7]);
+ LogAppend("0 "); // Age is always 0 on Linux.
+ LogAppend(file_name);
+ LogCommitLine();
+ }
+
+#if !defined(__LP64__)
+ void DumpFreeSpace() {
+ const MappingInfo* stack_mapping = nullptr;
+ ThreadInfo info;
+ if (dumper_->GetThreadInfoByIndex(dumper_->GetMainThreadIndex(), &info)) {
+ stack_mapping = dumper_->FindMappingNoBias(info.stack_pointer);
+ }
+
+ const google_breakpad::wasteful_vector<MappingInfo*>& mappings =
+ dumper_->mappings();
+ if (mappings.size() == 0) return;
+
+ // This is complicated by the fact that mappings is not in order. It should
+ // be mostly in order, however the mapping that contains the entry point for
+ // the process is always at the front of the vector.
+
+ static const int HBITS = sizeof(size_t) * 8;
+ size_t hole_histogram[HBITS];
+ my_memset(hole_histogram, 0, sizeof(hole_histogram));
+
+ // Find the lowest address mapping.
+ size_t curr = 0;
+ for (size_t i = 1; i < mappings.size(); ++i) {
+ if (mappings[i]->start_addr < mappings[curr]->start_addr) curr = i;
+ }
+
+ uintptr_t lo_addr = mappings[curr]->start_addr;
+
+ size_t hole_cnt = 0;
+ size_t hole_max = 0;
+ size_t hole_sum = 0;
+
+ while (true) {
+ // Skip to the end of an adjacent run of mappings. This is an optimization
+ // for the fact that mappings is mostly sorted.
+ while (curr != mappings.size() - 1 &&
+ MappingsAreAdjacent(*mappings[curr], *mappings[curr + 1])) {
+ ++curr;
+ }
+
+ if (mappings[curr] == stack_mapping) {
+ // Because we can't determine the top of userspace mappable
+ // memory we treat the start of the process stack as the top
+ // of the allocatable address space. Once we reach
+ // |stack_mapping| we are done scanning for free space regions.
+ break;
+ }
+
+ size_t next = NextOrderedMapping(mappings, curr);
+ if (next == std::numeric_limits<size_t>::max())
+ break;
+
+ uintptr_t hole_lo = mappings[curr]->start_addr + mappings[curr]->size;
+ uintptr_t hole_hi = mappings[next]->start_addr;
+
+ if (hole_hi > hole_lo) {
+ size_t hole_sz = hole_hi - hole_lo;
+ hole_sum += hole_sz;
+ hole_max = std::max(hole_sz, hole_max);
+ ++hole_cnt;
+ ++hole_histogram[Log2Floor(hole_sz)];
+ }
+ curr = next;
+ }
+
+ uintptr_t hi_addr = mappings[curr]->start_addr + mappings[curr]->size;
+
+ LogAppend("H ");
+ LogAppend(lo_addr);
+ LogAppend(" ");
+ LogAppend(hi_addr);
+ LogAppend(" ");
+ LogAppend(saturated_cast<uint16_t>(hole_cnt));
+ LogAppend(" ");
+ LogAppend(hole_max);
+ LogAppend(" ");
+ LogAppend(hole_sum);
+ for (unsigned int i = 0; i < HBITS; ++i) {
+ if (!hole_histogram[i]) continue;
+ LogAppend(" ");
+ LogAppend(saturated_cast<uint8_t>(i));
+ LogAppend(":");
+ LogAppend(saturated_cast<uint8_t>(hole_histogram[i]));
+ }
+ LogCommitLine();
+ }
+#endif
+
+ // Write information about the mappings in effect.
+ void DumpMappings() {
+ // First write all the mappings from the dumper
+ for (unsigned i = 0; i < dumper_->mappings().size(); ++i) {
+ const MappingInfo& mapping = *dumper_->mappings()[i];
+ if (mapping.name[0] == 0 || // only want modules with filenames.
+ !mapping.exec || // only want executable mappings.
+ mapping.size < 4096 || // too small to get a signature for.
+ HaveMappingInfo(mapping)) {
+ continue;
+ }
+
+ DumpModule(mapping, true, i, NULL);
+ }
+ // Next write all the mappings provided by the caller
+ for (MappingList::const_iterator iter = mapping_list_.begin();
+ iter != mapping_list_.end();
+ ++iter) {
+ DumpModule(iter->first, false, 0, &iter->second);
+ }
+ }
+
+ void* Alloc(unsigned bytes) { return dumper_->allocator()->Alloc(bytes); }
+
+ const ucontext_t* const ucontext_;
+#if !defined(__ARM_EABI__) && !defined(__mips__)
+ const google_breakpad::fpstate_t* const float_state_;
+#endif
+ LinuxDumper* dumper_;
+ const MappingList& mapping_list_;
+ bool skip_dump_if_principal_mapping_not_referenced_;
+ uintptr_t address_within_principal_mapping_;
+ bool sanitize_stack_;
+ const MicrodumpExtraInfo microdump_extra_info_;
+ char* log_line_;
+
+ // The local copy of crashed process stack memory, beginning at
+ // |stack_lower_bound_|.
+ uint8_t* stack_copy_;
+
+ // The length of crashed process stack copy.
+ size_t stack_len_;
+
+ // The address of the page containing the stack pointer in the
+ // crashed process. |stack_lower_bound_| <= |stack_pointer_|
+ uintptr_t stack_lower_bound_;
+
+ // The stack pointer of the crashed thread.
+ uintptr_t stack_pointer_;
+};
+} // namespace
+
+namespace google_breakpad {
+
+bool WriteMicrodump(pid_t crashing_process,
+ const void* blob,
+ size_t blob_size,
+ const MappingList& mappings,
+ bool skip_dump_if_principal_mapping_not_referenced,
+ uintptr_t address_within_principal_mapping,
+ bool sanitize_stack,
+ const MicrodumpExtraInfo& microdump_extra_info) {
+ LinuxPtraceDumper dumper(crashing_process);
+ const ExceptionHandler::CrashContext* context = NULL;
+ if (blob) {
+ if (blob_size != sizeof(ExceptionHandler::CrashContext))
+ return false;
+ context = reinterpret_cast<const ExceptionHandler::CrashContext*>(blob);
+ dumper.SetCrashInfoFromSigInfo(context->siginfo);
+ dumper.set_crash_thread(context->tid);
+ }
+ MicrodumpWriter writer(context, mappings,
+ skip_dump_if_principal_mapping_not_referenced,
+ address_within_principal_mapping, sanitize_stack,
+ microdump_extra_info, &dumper);
+ if (!writer.Init())
+ return false;
+ writer.Dump();
+ return true;
+}
+
+} // namespace google_breakpad
diff --git a/toolkit/crashreporter/breakpad-client/linux/microdump_writer/microdump_writer.h b/toolkit/crashreporter/breakpad-client/linux/microdump_writer/microdump_writer.h
new file mode 100644
index 0000000000..63b5463247
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/linux/microdump_writer/microdump_writer.h
@@ -0,0 +1,68 @@
+// 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 CLIENT_LINUX_MINIDUMP_WRITER_MICRODUMP_WRITER_H_
+#define CLIENT_LINUX_MINIDUMP_WRITER_MICRODUMP_WRITER_H_
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include "linux/dump_writer_common/mapping_info.h"
+
+namespace google_breakpad {
+
+struct MicrodumpExtraInfo;
+
+// Writes a microdump (a reduced dump containing only the state of the crashing
+// thread) on the console (logcat on Android). These functions do not malloc nor
+// use libc functions which may. Thus, it can be used in contexts where the
+// state of the heap may be corrupt.
+// Args:
+// crashing_process: the pid of the crashing process. This must be trusted.
+// blob: a blob of data from the crashing process. See exception_handler.h
+// blob_size: the length of |blob| in bytes.
+// mappings: a list of additional mappings provided by the application.
+// build_fingerprint: a (optional) C string which determines the OS
+// build fingerprint (e.g., aosp/occam/mako:5.1.1/LMY47W/1234:eng/dev-keys).
+// product_info: a (optional) C string which determines the product name and
+// version (e.g., WebView:42.0.2311.136).
+//
+// Returns true iff successful.
+bool WriteMicrodump(pid_t crashing_process,
+ const void* blob,
+ size_t blob_size,
+ const MappingList& mappings,
+ bool skip_dump_if_main_module_not_referenced,
+ uintptr_t address_within_main_module,
+ bool sanitize_stack,
+ const MicrodumpExtraInfo& microdump_extra_info);
+
+} // namespace google_breakpad
+
+#endif // CLIENT_LINUX_MINIDUMP_WRITER_MICRODUMP_WRITER_H_
diff --git a/toolkit/crashreporter/breakpad-client/linux/microdump_writer/microdump_writer_unittest.cc b/toolkit/crashreporter/breakpad-client/linux/microdump_writer/microdump_writer_unittest.cc
new file mode 100644
index 0000000000..6b7fb5f6ac
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/linux/microdump_writer/microdump_writer_unittest.cc
@@ -0,0 +1,421 @@
+// 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 <ctype.h>
+#include <sys/syscall.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <ucontext.h>
+
+#include <sstream>
+#include <string>
+
+#include "breakpad_googletest_includes.h"
+#include "linux/handler/exception_handler.h"
+#include "linux/handler/microdump_extra_info.h"
+#include "linux/microdump_writer/microdump_writer.h"
+#include "common/linux/breakpad_getcontext.h"
+#include "common/linux/eintr_wrapper.h"
+#include "common/linux/ignore_ret.h"
+#include "common/scoped_ptr.h"
+#include "common/tests/auto_tempdir.h"
+#include "common/using_std_string.h"
+
+using namespace google_breakpad;
+
+extern "C" {
+extern char __executable_start;
+extern char __etext;
+}
+
+namespace {
+
+typedef testing::Test MicrodumpWriterTest;
+
+MicrodumpExtraInfo MakeMicrodumpExtraInfo(
+ const char* build_fingerprint,
+ const char* product_info,
+ const char* gpu_fingerprint) {
+ MicrodumpExtraInfo info;
+ info.build_fingerprint = build_fingerprint;
+ info.product_info = product_info;
+ info.gpu_fingerprint = gpu_fingerprint;
+ info.process_type = "Browser";
+ return info;
+}
+
+bool ContainsMicrodump(const std::string& buf) {
+ return std::string::npos != buf.find("-----BEGIN BREAKPAD MICRODUMP-----") &&
+ std::string::npos != buf.find("-----END BREAKPAD MICRODUMP-----");
+}
+
+const char kIdentifiableString[] = "_IDENTIFIABLE_";
+const uintptr_t kCrashAddress = 0xdeaddeadu;
+
+void CrashAndGetMicrodump(const MappingList& mappings,
+ const MicrodumpExtraInfo& microdump_extra_info,
+ std::string* microdump,
+ bool skip_dump_if_principal_mapping_not_referenced = false,
+ uintptr_t address_within_principal_mapping = 0,
+ bool sanitize_stack = false) {
+ int fds[2];
+ ASSERT_NE(-1, pipe(fds));
+
+ AutoTempDir temp_dir;
+ string stderr_file = temp_dir.path() + "/stderr.log";
+ int err_fd = open(stderr_file.c_str(), O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
+ ASSERT_NE(-1, err_fd);
+
+ char identifiable_string[sizeof(kIdentifiableString)];
+
+ // This string should not appear in the resulting microdump if it
+ // has been sanitized.
+ strcpy(identifiable_string, kIdentifiableString);
+ // Force the strcpy to not be optimized away.
+ IGNORE_RET(write(STDOUT_FILENO, identifiable_string, 0));
+
+ const pid_t child = fork();
+ if (child == 0) {
+ close(fds[1]);
+ char b;
+ IGNORE_RET(HANDLE_EINTR(read(fds[0], &b, sizeof(b))));
+ close(fds[0]);
+ syscall(__NR_exit);
+ }
+ close(fds[0]);
+
+ ExceptionHandler::CrashContext context;
+ memset(&context, 0, sizeof(context));
+ // Pretend the current context is the child context (which is
+ // approximately right) so that we have a valid stack pointer, and
+ // can fetch child stack data via ptrace.
+ getcontext(&context.context);
+ // Set a non-zero tid to avoid tripping asserts.
+ context.tid = child;
+ context.siginfo.si_signo = MD_EXCEPTION_CODE_LIN_DUMP_REQUESTED;
+ context.siginfo.si_addr = reinterpret_cast<void*>(kCrashAddress);
+
+ // Redirect temporarily stderr to the stderr.log file.
+ int save_err = dup(STDERR_FILENO);
+ ASSERT_NE(-1, save_err);
+ ASSERT_NE(-1, dup2(err_fd, STDERR_FILENO));
+
+ ASSERT_TRUE(WriteMicrodump(child, &context, sizeof(context), mappings,
+ skip_dump_if_principal_mapping_not_referenced,
+ address_within_principal_mapping, sanitize_stack,
+ microdump_extra_info));
+
+ // Revert stderr back to the console.
+ dup2(save_err, STDERR_FILENO);
+ close(save_err);
+
+ // Read back the stderr file and check for the microdump marker.
+ fsync(err_fd);
+ lseek(err_fd, 0, SEEK_SET);
+
+ microdump->clear();
+ char buf[1024];
+
+ while (true) {
+ int bytes_read = IGNORE_EINTR(read(err_fd, buf, 1024));
+ if (bytes_read <= 0) break;
+ microdump->append(buf, buf + bytes_read);
+ }
+ close(err_fd);
+ close(fds[1]);
+}
+
+void ExtractMicrodumpStackContents(const string& microdump_content,
+ string* result) {
+ std::istringstream iss(microdump_content);
+ result->clear();
+ for (string line; std::getline(iss, line);) {
+ if (line.find("S ") == 0) {
+ std::istringstream stack_data(line);
+ std::string key;
+ std::string addr;
+ std::string data;
+ stack_data >> key >> addr >> data;
+ EXPECT_TRUE((data.size() & 1u) == 0u);
+ result->reserve(result->size() + data.size() / 2);
+ for (size_t i = 0; i < data.size(); i += 2) {
+ std::string byte = data.substr(i, 2);
+ result->push_back(static_cast<char>(strtoul(byte.c_str(), NULL, 16)));
+ }
+ }
+ }
+}
+
+void CheckMicrodumpContents(const string& microdump_content,
+ const MicrodumpExtraInfo& expected_info) {
+ std::istringstream iss(microdump_content);
+ bool did_find_os_info = false;
+ bool did_find_product_info = false;
+ bool did_find_process_type = false;
+ bool did_find_crash_reason = false;
+ bool did_find_gpu_info = false;
+ for (string line; std::getline(iss, line);) {
+ if (line.find("O ") == 0) {
+ std::istringstream os_info_tokens(line);
+ string token;
+ os_info_tokens.ignore(2); // Ignore the "O " preamble.
+ // Check the OS descriptor char (L=Linux, A=Android).
+ os_info_tokens >> token;
+ ASSERT_TRUE(token == "L" || token == "A");
+
+ os_info_tokens >> token; // HW architecture.
+ os_info_tokens >> token; // Number of cpus.
+ for (size_t i = 0; i < token.size(); ++i)
+ ASSERT_TRUE(isxdigit(token[i]));
+ os_info_tokens >> token; // SW architecture.
+
+ // Check that the build fingerprint is in the right place.
+ os_info_tokens >> token;
+ ASSERT_FALSE(os_info_tokens.fail());
+ if (expected_info.build_fingerprint)
+ ASSERT_EQ(expected_info.build_fingerprint, token);
+ did_find_os_info = true;
+ } else if (line.find("P ") == 0) {
+ if (expected_info.process_type)
+ ASSERT_EQ(string("P ") + expected_info.process_type, line);
+ did_find_process_type = true;
+ } else if (line.find("R ") == 0) {
+ std::istringstream crash_reason_tokens(line);
+ string token;
+ unsigned crash_reason;
+ string crash_reason_str;
+ uintptr_t crash_address;
+ crash_reason_tokens.ignore(2); // Ignore the "R " preamble.
+ crash_reason_tokens >> std::hex >> crash_reason >> crash_reason_str >>
+ crash_address;
+ ASSERT_FALSE(crash_reason_tokens.fail());
+ ASSERT_EQ(MD_EXCEPTION_CODE_LIN_DUMP_REQUESTED, crash_reason);
+ ASSERT_EQ("DUMP_REQUESTED", crash_reason_str);
+ ASSERT_EQ(kCrashAddress, crash_address);
+ did_find_crash_reason = true;
+ } else if (line.find("V ") == 0) {
+ if (expected_info.product_info)
+ ASSERT_EQ(string("V ") + expected_info.product_info, line);
+ did_find_product_info = true;
+ } else if (line.find("G ") == 0) {
+ if (expected_info.gpu_fingerprint)
+ ASSERT_EQ(string("G ") + expected_info.gpu_fingerprint, line);
+ did_find_gpu_info = true;
+ }
+ }
+ ASSERT_TRUE(did_find_os_info);
+ ASSERT_TRUE(did_find_product_info);
+ ASSERT_TRUE(did_find_process_type);
+ ASSERT_TRUE(did_find_crash_reason);
+ ASSERT_TRUE(did_find_gpu_info);
+}
+
+bool MicrodumpStackContains(const string& microdump_content,
+ const string& expected_content) {
+ string result;
+ ExtractMicrodumpStackContents(microdump_content, &result);
+ return result.find(kIdentifiableString) != string::npos;
+}
+
+void CheckMicrodumpContents(const string& microdump_content,
+ const string& expected_fingerprint,
+ const string& expected_product_info,
+ const string& expected_gpu_fingerprint) {
+ CheckMicrodumpContents(
+ microdump_content,
+ MakeMicrodumpExtraInfo(expected_fingerprint.c_str(),
+ expected_product_info.c_str(),
+ expected_gpu_fingerprint.c_str()));
+}
+
+TEST(MicrodumpWriterTest, BasicWithMappings) {
+ // Push some extra mapping to check the MappingList logic.
+ const uint32_t memory_size = sysconf(_SC_PAGESIZE);
+ const char* kMemoryName = "libfoo.so";
+ const uint8_t kModuleGUID[sizeof(MDGUID)] = {
+ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+ 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF
+ };
+
+ MappingInfo info;
+ info.start_addr = memory_size;
+ info.size = memory_size;
+ info.offset = 42;
+ strcpy(info.name, kMemoryName);
+
+ MappingList mappings;
+ MappingEntry mapping;
+ mapping.first = info;
+ mapping.second.assign(std::begin(kModuleGUID), std::end(kModuleGUID));
+ mappings.push_back(mapping);
+
+ std::string buf;
+ CrashAndGetMicrodump(mappings, MicrodumpExtraInfo(), &buf);
+ ASSERT_TRUE(ContainsMicrodump(buf));
+
+#ifdef __LP64__
+ ASSERT_NE(std::string::npos,
+ buf.find("M 0000000000001000 000000000000002A 0000000000001000 "
+ "33221100554477668899AABBCCDDEEFF0 libfoo.so"));
+#else
+ ASSERT_NE(std::string::npos,
+ buf.find("M 00001000 0000002A 00001000 "
+ "33221100554477668899AABBCCDDEEFF0 libfoo.so"));
+#endif
+
+ // In absence of a product info in the minidump, the writer should just write
+ // an unknown marker.
+ ASSERT_NE(std::string::npos, buf.find("V UNKNOWN:0.0.0.0"));
+}
+
+// Ensure that no output occurs if the interest region is set, but
+// doesn't overlap anything on the stack.
+TEST(MicrodumpWriterTest, NoOutputIfUninteresting) {
+ const char kProductInfo[] = "MockProduct:42.0.2311.99";
+ const char kBuildFingerprint[] =
+ "aosp/occam/mako:5.1.1/LMY47W/12345678:userdegbug/dev-keys";
+ const char kGPUFingerprint[] =
+ "Qualcomm;Adreno (TM) 330;OpenGL ES 3.0 V@104.0 AU@ (GIT@Id3510ff6dc)";
+ const MicrodumpExtraInfo kMicrodumpExtraInfo(
+ MakeMicrodumpExtraInfo(kBuildFingerprint, kProductInfo, kGPUFingerprint));
+
+ std::string buf;
+ MappingList no_mappings;
+
+ CrashAndGetMicrodump(no_mappings, kMicrodumpExtraInfo, &buf, true, 0);
+ ASSERT_FALSE(ContainsMicrodump(buf));
+}
+
+// Ensure that stack content does not contain an identifiable string if the
+// stack is sanitized.
+TEST(MicrodumpWriterTest, StringRemovedBySanitization) {
+ const char kProductInfo[] = "MockProduct:42.0.2311.99";
+ const char kBuildFingerprint[] =
+ "aosp/occam/mako:5.1.1/LMY47W/12345678:userdegbug/dev-keys";
+ const char kGPUFingerprint[] =
+ "Qualcomm;Adreno (TM) 330;OpenGL ES 3.0 V@104.0 AU@ (GIT@Id3510ff6dc)";
+
+ const MicrodumpExtraInfo kMicrodumpExtraInfo(
+ MakeMicrodumpExtraInfo(kBuildFingerprint, kProductInfo, kGPUFingerprint));
+
+ std::string buf;
+ MappingList no_mappings;
+
+ CrashAndGetMicrodump(no_mappings, kMicrodumpExtraInfo, &buf, false, 0u, true);
+ ASSERT_TRUE(ContainsMicrodump(buf));
+ ASSERT_FALSE(MicrodumpStackContains(buf, kIdentifiableString));
+}
+
+// Ensure that stack content does contain an identifiable string if the
+// stack is not sanitized.
+TEST(MicrodumpWriterTest, StringPresentIfNotSanitized) {
+ const char kProductInfo[] = "MockProduct:42.0.2311.99";
+ const char kBuildFingerprint[] =
+ "aosp/occam/mako:5.1.1/LMY47W/12345678:userdegbug/dev-keys";
+ const char kGPUFingerprint[] =
+ "Qualcomm;Adreno (TM) 330;OpenGL ES 3.0 V@104.0 AU@ (GIT@Id3510ff6dc)";
+
+ const MicrodumpExtraInfo kMicrodumpExtraInfo(
+ MakeMicrodumpExtraInfo(kBuildFingerprint, kProductInfo, kGPUFingerprint));
+
+ std::string buf;
+ MappingList no_mappings;
+
+ CrashAndGetMicrodump(no_mappings, kMicrodumpExtraInfo, &buf, false, 0u, false);
+ ASSERT_TRUE(ContainsMicrodump(buf));
+ ASSERT_TRUE(MicrodumpStackContains(buf, kIdentifiableString));
+}
+
+// Ensure that output occurs if the interest region is set, and
+// does overlap something on the stack.
+TEST(MicrodumpWriterTest, OutputIfInteresting) {
+ const char kProductInfo[] = "MockProduct:42.0.2311.99";
+ const char kBuildFingerprint[] =
+ "aosp/occam/mako:5.1.1/LMY47W/12345678:userdegbug/dev-keys";
+ const char kGPUFingerprint[] =
+ "Qualcomm;Adreno (TM) 330;OpenGL ES 3.0 V@104.0 AU@ (GIT@Id3510ff6dc)";
+
+ const MicrodumpExtraInfo kMicrodumpExtraInfo(
+ MakeMicrodumpExtraInfo(kBuildFingerprint, kProductInfo, kGPUFingerprint));
+
+ std::string buf;
+ MappingList no_mappings;
+
+ CrashAndGetMicrodump(no_mappings, kMicrodumpExtraInfo, &buf, true,
+ reinterpret_cast<uintptr_t>(CrashAndGetMicrodump));
+ ASSERT_TRUE(ContainsMicrodump(buf));
+}
+
+// Ensure that the product info and build fingerprint metadata show up in the
+// final microdump if present.
+TEST(MicrodumpWriterTest, BuildFingerprintAndProductInfo) {
+ const char kProductInfo[] = "MockProduct:42.0.2311.99";
+ const char kBuildFingerprint[] =
+ "aosp/occam/mako:5.1.1/LMY47W/12345678:userdegbug/dev-keys";
+ const char kGPUFingerprint[] =
+ "Qualcomm;Adreno (TM) 330;OpenGL ES 3.0 V@104.0 AU@ (GIT@Id3510ff6dc)";
+ const MicrodumpExtraInfo kMicrodumpExtraInfo(
+ MakeMicrodumpExtraInfo(kBuildFingerprint, kProductInfo, kGPUFingerprint));
+ std::string buf;
+ MappingList no_mappings;
+
+ CrashAndGetMicrodump(no_mappings, kMicrodumpExtraInfo, &buf);
+ ASSERT_TRUE(ContainsMicrodump(buf));
+ CheckMicrodumpContents(buf, kMicrodumpExtraInfo);
+}
+
+TEST(MicrodumpWriterTest, NoProductInfo) {
+ const char kBuildFingerprint[] = "foobar";
+ const char kGPUFingerprint[] = "bazqux";
+ std::string buf;
+ MappingList no_mappings;
+
+ const MicrodumpExtraInfo kMicrodumpExtraInfoNoProductInfo(
+ MakeMicrodumpExtraInfo(kBuildFingerprint, NULL, kGPUFingerprint));
+
+ CrashAndGetMicrodump(no_mappings, kMicrodumpExtraInfoNoProductInfo, &buf);
+ ASSERT_TRUE(ContainsMicrodump(buf));
+ CheckMicrodumpContents(buf, kBuildFingerprint, "UNKNOWN:0.0.0.0",
+ kGPUFingerprint);
+}
+
+TEST(MicrodumpWriterTest, NoGPUInfo) {
+ const char kProductInfo[] = "bazqux";
+ const char kBuildFingerprint[] = "foobar";
+ std::string buf;
+ MappingList no_mappings;
+
+ const MicrodumpExtraInfo kMicrodumpExtraInfoNoGPUInfo(
+ MakeMicrodumpExtraInfo(kBuildFingerprint, kProductInfo, NULL));
+
+ CrashAndGetMicrodump(no_mappings, kMicrodumpExtraInfoNoGPUInfo, &buf);
+ ASSERT_TRUE(ContainsMicrodump(buf));
+ CheckMicrodumpContents(buf, kBuildFingerprint, kProductInfo, "UNKNOWN");
+}
+} // namespace
diff --git a/toolkit/crashreporter/breakpad-client/linux/minidump_writer/cpu_set.h b/toolkit/crashreporter/breakpad-client/linux/minidump_writer/cpu_set.h
new file mode 100644
index 0000000000..1cca9aa5a0
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/linux/minidump_writer/cpu_set.h
@@ -0,0 +1,144 @@
+// 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 CLIENT_LINUX_MINIDUMP_WRITER_CPU_SET_H_
+#define CLIENT_LINUX_MINIDUMP_WRITER_CPU_SET_H_
+
+#include <stdint.h>
+#include <assert.h>
+#include <string.h>
+
+#include "common/linux/linux_libc_support.h"
+#include "third_party/lss/linux_syscall_support.h"
+
+namespace google_breakpad {
+
+// Helper class used to model a set of CPUs, as read from sysfs
+// files like /sys/devices/system/cpu/present
+// See See http://www.kernel.org/doc/Documentation/cputopology.txt
+class CpuSet {
+public:
+ // The maximum number of supported CPUs.
+ static const size_t kMaxCpus = 1024;
+
+ CpuSet() {
+ my_memset(mask_, 0, sizeof(mask_));
+ }
+
+ // Parse a sysfs file to extract the corresponding CPU set.
+ bool ParseSysFile(int fd) {
+ char buffer[512];
+ int ret = sys_read(fd, buffer, sizeof(buffer)-1);
+ if (ret < 0)
+ return false;
+
+ buffer[ret] = '\0';
+
+ // Expected format: comma-separated list of items, where each
+ // item can be a decimal integer, or two decimal integers separated
+ // by a dash.
+ // E.g.:
+ // 0
+ // 0,1,2,3
+ // 0-3
+ // 1,10-23
+ const char* p = buffer;
+ const char* p_end = p + ret;
+ while (p < p_end) {
+ // Skip leading space, if any
+ while (p < p_end && my_isspace(*p))
+ p++;
+
+ // Find start and size of current item.
+ const char* item = p;
+ size_t item_len = static_cast<size_t>(p_end - p);
+ const char* item_next =
+ static_cast<const char*>(my_memchr(p, ',', item_len));
+ if (item_next != NULL) {
+ p = item_next + 1;
+ item_len = static_cast<size_t>(item_next - item);
+ } else {
+ p = p_end;
+ item_next = p_end;
+ }
+
+ // Ignore trailing spaces.
+ while (item_next > item && my_isspace(item_next[-1]))
+ item_next--;
+
+ // skip empty items.
+ if (item_next == item)
+ continue;
+
+ // read first decimal value.
+ uintptr_t start = 0;
+ const char* next = my_read_decimal_ptr(&start, item);
+ uintptr_t end = start;
+ if (*next == '-')
+ my_read_decimal_ptr(&end, next+1);
+
+ while (start <= end)
+ SetBit(start++);
+ }
+ return true;
+ }
+
+ // Intersect this CPU set with another one.
+ void IntersectWith(const CpuSet& other) {
+ for (size_t nn = 0; nn < kMaskWordCount; ++nn)
+ mask_[nn] &= other.mask_[nn];
+ }
+
+ // Return the number of CPUs in this set.
+ int GetCount() {
+ int result = 0;
+ for (size_t nn = 0; nn < kMaskWordCount; ++nn) {
+ result += __builtin_popcount(mask_[nn]);
+ }
+ return result;
+ }
+
+private:
+ void SetBit(uintptr_t index) {
+ size_t nn = static_cast<size_t>(index);
+ if (nn < kMaxCpus)
+ mask_[nn / kMaskWordBits] |= (1U << (nn % kMaskWordBits));
+ }
+
+ typedef uint32_t MaskWordType;
+ static const size_t kMaskWordBits = 8*sizeof(MaskWordType);
+ static const size_t kMaskWordCount =
+ (kMaxCpus + kMaskWordBits - 1) / kMaskWordBits;
+
+ MaskWordType mask_[kMaskWordCount];
+};
+
+} // namespace google_breakpad
+
+#endif // CLIENT_LINUX_MINIDUMP_WRITER_CPU_SET_H_
diff --git a/toolkit/crashreporter/breakpad-client/linux/minidump_writer/cpu_set_unittest.cc b/toolkit/crashreporter/breakpad-client/linux/minidump_writer/cpu_set_unittest.cc
new file mode 100644
index 0000000000..75172e9938
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/linux/minidump_writer/cpu_set_unittest.cc
@@ -0,0 +1,164 @@
+// 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.
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+
+#include "breakpad_googletest_includes.h"
+#include "linux/minidump_writer/cpu_set.h"
+#include "common/linux/tests/auto_testfile.h"
+
+using namespace google_breakpad;
+
+namespace {
+
+typedef testing::Test CpuSetTest;
+
+// Helper class to write test text file to a temporary file and return
+// its file descriptor.
+class ScopedTestFile : public AutoTestFile {
+public:
+ explicit ScopedTestFile(const char* text)
+ : AutoTestFile("cpu_set", text) {
+ }
+};
+
+}
+
+TEST(CpuSetTest, EmptyCount) {
+ CpuSet set;
+ ASSERT_EQ(0, set.GetCount());
+}
+
+TEST(CpuSetTest, OneCpu) {
+ ScopedTestFile file("10");
+ ASSERT_TRUE(file.IsOk());
+
+ CpuSet set;
+ ASSERT_TRUE(set.ParseSysFile(file.GetFd()));
+ ASSERT_EQ(1, set.GetCount());
+}
+
+TEST(CpuSetTest, OneCpuTerminated) {
+ ScopedTestFile file("10\n");
+ ASSERT_TRUE(file.IsOk());
+
+ CpuSet set;
+ ASSERT_TRUE(set.ParseSysFile(file.GetFd()));
+ ASSERT_EQ(1, set.GetCount());
+}
+
+TEST(CpuSetTest, TwoCpusWithComma) {
+ ScopedTestFile file("1,10");
+ ASSERT_TRUE(file.IsOk());
+
+ CpuSet set;
+ ASSERT_TRUE(set.ParseSysFile(file.GetFd()));
+ ASSERT_EQ(2, set.GetCount());
+}
+
+TEST(CpuSetTest, TwoCpusWithRange) {
+ ScopedTestFile file("1-2");
+ ASSERT_TRUE(file.IsOk());
+
+ CpuSet set;
+ ASSERT_TRUE(set.ParseSysFile(file.GetFd()));
+ ASSERT_EQ(2, set.GetCount());
+}
+
+TEST(CpuSetTest, TenCpusWithRange) {
+ ScopedTestFile file("9-18");
+ ASSERT_TRUE(file.IsOk());
+
+ CpuSet set;
+ ASSERT_TRUE(set.ParseSysFile(file.GetFd()));
+ ASSERT_EQ(10, set.GetCount());
+}
+
+TEST(CpuSetTest, MultiItems) {
+ ScopedTestFile file("0, 2-4, 128");
+ ASSERT_TRUE(file.IsOk());
+
+ CpuSet set;
+ ASSERT_TRUE(set.ParseSysFile(file.GetFd()));
+ ASSERT_EQ(5, set.GetCount());
+}
+
+TEST(CpuSetTest, IntersectWith) {
+ ScopedTestFile file1("9-19");
+ ASSERT_TRUE(file1.IsOk());
+ CpuSet set1;
+ ASSERT_TRUE(set1.ParseSysFile(file1.GetFd()));
+ ASSERT_EQ(11, set1.GetCount());
+
+ ScopedTestFile file2("16-24");
+ ASSERT_TRUE(file2.IsOk());
+ CpuSet set2;
+ ASSERT_TRUE(set2.ParseSysFile(file2.GetFd()));
+ ASSERT_EQ(9, set2.GetCount());
+
+ set1.IntersectWith(set2);
+ ASSERT_EQ(4, set1.GetCount());
+ ASSERT_EQ(9, set2.GetCount());
+}
+
+TEST(CpuSetTest, SelfIntersection) {
+ ScopedTestFile file1("9-19");
+ ASSERT_TRUE(file1.IsOk());
+ CpuSet set1;
+ ASSERT_TRUE(set1.ParseSysFile(file1.GetFd()));
+ ASSERT_EQ(11, set1.GetCount());
+
+ set1.IntersectWith(set1);
+ ASSERT_EQ(11, set1.GetCount());
+}
+
+TEST(CpuSetTest, EmptyIntersection) {
+ ScopedTestFile file1("0-19");
+ ASSERT_TRUE(file1.IsOk());
+ CpuSet set1;
+ ASSERT_TRUE(set1.ParseSysFile(file1.GetFd()));
+ ASSERT_EQ(20, set1.GetCount());
+
+ ScopedTestFile file2("20-39");
+ ASSERT_TRUE(file2.IsOk());
+ CpuSet set2;
+ ASSERT_TRUE(set2.ParseSysFile(file2.GetFd()));
+ ASSERT_EQ(20, set2.GetCount());
+
+ set1.IntersectWith(set2);
+ ASSERT_EQ(0, set1.GetCount());
+
+ ASSERT_EQ(20, set2.GetCount());
+}
+
diff --git a/toolkit/crashreporter/breakpad-client/linux/minidump_writer/directory_reader.h b/toolkit/crashreporter/breakpad-client/linux/minidump_writer/directory_reader.h
new file mode 100644
index 0000000000..a4bde18031
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/linux/minidump_writer/directory_reader.h
@@ -0,0 +1,106 @@
+// 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 CLIENT_LINUX_MINIDUMP_WRITER_DIRECTORY_READER_H_
+#define CLIENT_LINUX_MINIDUMP_WRITER_DIRECTORY_READER_H_
+
+#include <stdint.h>
+#include <unistd.h>
+#include <limits.h>
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+
+#include "common/linux/linux_libc_support.h"
+#include "third_party/lss/linux_syscall_support.h"
+
+namespace google_breakpad {
+
+// A class for enumerating a directory without using diropen/readdir or other
+// functions which may allocate memory.
+class DirectoryReader {
+ public:
+ DirectoryReader(int fd)
+ : fd_(fd),
+ buf_used_(0) {
+ }
+
+ // Return the next entry from the directory
+ // name: (output) the NUL terminated entry name
+ //
+ // Returns true iff successful (false on EOF).
+ //
+ // After calling this, one must call |PopEntry| otherwise you'll get the same
+ // entry over and over.
+ bool GetNextEntry(const char** name) {
+ struct kernel_dirent* const dent =
+ reinterpret_cast<kernel_dirent*>(buf_);
+
+ if (buf_used_ == 0) {
+ // need to read more entries.
+ const int n = sys_getdents(fd_, dent, sizeof(buf_));
+ if (n < 0) {
+ return false;
+ } else if (n == 0) {
+ hit_eof_ = true;
+ } else {
+ buf_used_ += n;
+ }
+ }
+
+ if (buf_used_ == 0 && hit_eof_)
+ return false;
+
+ assert(buf_used_ > 0);
+
+ *name = dent->d_name;
+ return true;
+ }
+
+ void PopEntry() {
+ if (!buf_used_)
+ return;
+
+ const struct kernel_dirent* const dent =
+ reinterpret_cast<kernel_dirent*>(buf_);
+
+ buf_used_ -= dent->d_reclen;
+ my_memmove(buf_, buf_ + dent->d_reclen, buf_used_);
+ }
+
+ private:
+ const int fd_;
+ bool hit_eof_;
+ unsigned buf_used_;
+ uint8_t buf_[sizeof(struct kernel_dirent) + NAME_MAX + 1];
+};
+
+} // namespace google_breakpad
+
+#endif // CLIENT_LINUX_MINIDUMP_WRITER_DIRECTORY_READER_H_
diff --git a/toolkit/crashreporter/breakpad-client/linux/minidump_writer/directory_reader_unittest.cc b/toolkit/crashreporter/breakpad-client/linux/minidump_writer/directory_reader_unittest.cc
new file mode 100644
index 0000000000..b33507db95
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/linux/minidump_writer/directory_reader_unittest.cc
@@ -0,0 +1,78 @@
+// 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 <set>
+#include <string>
+
+#include <dirent.h>
+#include <fcntl.h>
+#include <sys/types.h>
+
+#include "linux/minidump_writer/directory_reader.h"
+#include "common/using_std_string.h"
+#include "breakpad_googletest_includes.h"
+
+using namespace google_breakpad;
+
+namespace {
+typedef testing::Test DirectoryReaderTest;
+}
+
+TEST(DirectoryReaderTest, CompareResults) {
+ std::set<string> dent_set;
+
+ DIR *const dir = opendir("/proc/self");
+ ASSERT_TRUE(dir != NULL);
+
+ struct dirent* dent;
+ while ((dent = readdir(dir)))
+ dent_set.insert(dent->d_name);
+
+ closedir(dir);
+
+ const int fd = open("/proc/self", O_DIRECTORY | O_RDONLY);
+ ASSERT_GE(fd, 0);
+
+ DirectoryReader dir_reader(fd);
+ unsigned seen = 0;
+
+ const char* name;
+ while (dir_reader.GetNextEntry(&name)) {
+ ASSERT_TRUE(dent_set.find(name) != dent_set.end());
+ seen++;
+ dir_reader.PopEntry();
+ }
+
+ ASSERT_TRUE(dent_set.find("status") != dent_set.end());
+ ASSERT_TRUE(dent_set.find("stat") != dent_set.end());
+ ASSERT_TRUE(dent_set.find("cmdline") != dent_set.end());
+
+ ASSERT_EQ(dent_set.size(), seen);
+ close(fd);
+}
diff --git a/toolkit/crashreporter/breakpad-client/linux/minidump_writer/line_reader.h b/toolkit/crashreporter/breakpad-client/linux/minidump_writer/line_reader.h
new file mode 100644
index 0000000000..d8e2dbcc11
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/linux/minidump_writer/line_reader.h
@@ -0,0 +1,131 @@
+// 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 CLIENT_LINUX_MINIDUMP_WRITER_LINE_READER_H_
+#define CLIENT_LINUX_MINIDUMP_WRITER_LINE_READER_H_
+
+#include <stdint.h>
+#include <assert.h>
+#include <string.h>
+
+#include "common/linux/linux_libc_support.h"
+#include "third_party/lss/linux_syscall_support.h"
+
+namespace google_breakpad {
+
+// A class for reading a file, line by line, without using fopen/fgets or other
+// functions which may allocate memory.
+class LineReader {
+ public:
+ LineReader(int fd)
+ : fd_(fd),
+ hit_eof_(false),
+ buf_used_(0) {
+ }
+
+ // The maximum length of a line.
+ static const size_t kMaxLineLen = 1024;
+
+ // Return the next line from the file.
+ // line: (output) a pointer to the start of the line. The line is NUL
+ // terminated.
+ // len: (output) the length of the line (not inc the NUL byte)
+ //
+ // Returns true iff successful (false on EOF).
+ //
+ // One must call |PopLine| after this function, otherwise you'll continue to
+ // get the same line over and over.
+ bool GetNextLine(const char **line, unsigned *len) {
+ for (;;) {
+ if (buf_used_ == 0 && hit_eof_)
+ return false;
+
+ for (unsigned i = 0; i < buf_used_; ++i) {
+ if (buf_[i] == '\n' || buf_[i] == 0) {
+ buf_[i] = 0;
+ *len = i;
+ *line = buf_;
+ return true;
+ }
+ }
+
+ if (buf_used_ == sizeof(buf_)) {
+ // we scanned the whole buffer and didn't find an end-of-line marker.
+ // This line is too long to process.
+ return false;
+ }
+
+ // We didn't find any end-of-line terminators in the buffer. However, if
+ // this is the last line in the file it might not have one:
+ if (hit_eof_) {
+ assert(buf_used_);
+ // There's room for the NUL because of the buf_used_ == sizeof(buf_)
+ // check above.
+ buf_[buf_used_] = 0;
+ *len = buf_used_;
+ buf_used_ += 1; // since we appended the NUL.
+ *line = buf_;
+ return true;
+ }
+
+ // Otherwise, we should pull in more data from the file
+ const ssize_t n = sys_read(fd_, buf_ + buf_used_,
+ sizeof(buf_) - buf_used_);
+ if (n < 0) {
+ return false;
+ } else if (n == 0) {
+ hit_eof_ = true;
+ } else {
+ buf_used_ += n;
+ }
+
+ // At this point, we have either set the hit_eof_ flag, or we have more
+ // data to process...
+ }
+ }
+
+ void PopLine(unsigned len) {
+ // len doesn't include the NUL byte at the end.
+
+ assert(buf_used_ >= len + 1);
+ buf_used_ -= len + 1;
+ my_memmove(buf_, buf_ + len + 1, buf_used_);
+ }
+
+ private:
+ const int fd_;
+
+ bool hit_eof_;
+ unsigned buf_used_;
+ char buf_[kMaxLineLen];
+};
+
+} // namespace google_breakpad
+
+#endif // CLIENT_LINUX_MINIDUMP_WRITER_LINE_READER_H_
diff --git a/toolkit/crashreporter/breakpad-client/linux/minidump_writer/line_reader_unittest.cc b/toolkit/crashreporter/breakpad-client/linux/minidump_writer/line_reader_unittest.cc
new file mode 100644
index 0000000000..576b8b5cdb
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/linux/minidump_writer/line_reader_unittest.cc
@@ -0,0 +1,169 @@
+// 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 <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+
+#include "linux/minidump_writer/line_reader.h"
+#include "breakpad_googletest_includes.h"
+#include "common/linux/tests/auto_testfile.h"
+
+using namespace google_breakpad;
+
+namespace {
+
+typedef testing::Test LineReaderTest;
+
+class ScopedTestFile : public AutoTestFile {
+public:
+ explicit ScopedTestFile(const char* text)
+ : AutoTestFile("line_reader", text) {
+ }
+
+ ScopedTestFile(const char* text, size_t text_len)
+ : AutoTestFile("line_reader", text, text_len) {
+ }
+};
+
+}
+
+TEST(LineReaderTest, EmptyFile) {
+ ScopedTestFile file("");
+ ASSERT_TRUE(file.IsOk());
+ LineReader reader(file.GetFd());
+
+ const char *line;
+ unsigned len;
+ ASSERT_FALSE(reader.GetNextLine(&line, &len));
+}
+
+TEST(LineReaderTest, OneLineTerminated) {
+ ScopedTestFile file("a\n");
+ ASSERT_TRUE(file.IsOk());
+ LineReader reader(file.GetFd());
+
+ const char *line;
+ unsigned int len;
+ ASSERT_TRUE(reader.GetNextLine(&line, &len));
+ ASSERT_EQ((unsigned int)1, len);
+ ASSERT_EQ('a', line[0]);
+ ASSERT_EQ('\0', line[1]);
+ reader.PopLine(len);
+
+ ASSERT_FALSE(reader.GetNextLine(&line, &len));
+}
+
+TEST(LineReaderTest, OneLine) {
+ ScopedTestFile file("a");
+ ASSERT_TRUE(file.IsOk());
+ LineReader reader(file.GetFd());
+
+ const char *line;
+ unsigned len;
+ ASSERT_TRUE(reader.GetNextLine(&line, &len));
+ ASSERT_EQ((unsigned)1, len);
+ ASSERT_EQ('a', line[0]);
+ ASSERT_EQ('\0', line[1]);
+ reader.PopLine(len);
+
+ ASSERT_FALSE(reader.GetNextLine(&line, &len));
+}
+
+TEST(LineReaderTest, TwoLinesTerminated) {
+ ScopedTestFile file("a\nb\n");
+ ASSERT_TRUE(file.IsOk());
+ LineReader reader(file.GetFd());
+
+ const char *line;
+ unsigned len;
+ ASSERT_TRUE(reader.GetNextLine(&line, &len));
+ ASSERT_EQ((unsigned)1, len);
+ ASSERT_EQ('a', line[0]);
+ ASSERT_EQ('\0', line[1]);
+ reader.PopLine(len);
+
+ ASSERT_TRUE(reader.GetNextLine(&line, &len));
+ ASSERT_EQ((unsigned)1, len);
+ ASSERT_EQ('b', line[0]);
+ ASSERT_EQ('\0', line[1]);
+ reader.PopLine(len);
+
+ ASSERT_FALSE(reader.GetNextLine(&line, &len));
+}
+
+TEST(LineReaderTest, TwoLines) {
+ ScopedTestFile file("a\nb");
+ ASSERT_TRUE(file.IsOk());
+ LineReader reader(file.GetFd());
+
+ const char *line;
+ unsigned len;
+ ASSERT_TRUE(reader.GetNextLine(&line, &len));
+ ASSERT_EQ((unsigned)1, len);
+ ASSERT_EQ('a', line[0]);
+ ASSERT_EQ('\0', line[1]);
+ reader.PopLine(len);
+
+ ASSERT_TRUE(reader.GetNextLine(&line, &len));
+ ASSERT_EQ((unsigned)1, len);
+ ASSERT_EQ('b', line[0]);
+ ASSERT_EQ('\0', line[1]);
+ reader.PopLine(len);
+
+ ASSERT_FALSE(reader.GetNextLine(&line, &len));
+}
+
+TEST(LineReaderTest, MaxLength) {
+ char l[LineReader::kMaxLineLen-1];
+ memset(l, 'a', sizeof(l));
+ ScopedTestFile file(l, sizeof(l));
+ ASSERT_TRUE(file.IsOk());
+ LineReader reader(file.GetFd());
+
+ const char *line;
+ unsigned len;
+ ASSERT_TRUE(reader.GetNextLine(&line, &len));
+ ASSERT_EQ(sizeof(l), len);
+ ASSERT_TRUE(memcmp(l, line, sizeof(l)) == 0);
+ ASSERT_EQ('\0', line[len]);
+}
+
+TEST(LineReaderTest, TooLong) {
+ // Note: this writes kMaxLineLen 'a' chars in the test file.
+ char l[LineReader::kMaxLineLen];
+ memset(l, 'a', sizeof(l));
+ ScopedTestFile file(l, sizeof(l));
+ ASSERT_TRUE(file.IsOk());
+ LineReader reader(file.GetFd());
+
+ const char *line;
+ unsigned len;
+ ASSERT_FALSE(reader.GetNextLine(&line, &len));
+}
diff --git a/toolkit/crashreporter/breakpad-client/linux/minidump_writer/linux_core_dumper.cc b/toolkit/crashreporter/breakpad-client/linux/minidump_writer/linux_core_dumper.cc
new file mode 100644
index 0000000000..38feb0aaa7
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/linux/minidump_writer/linux_core_dumper.cc
@@ -0,0 +1,308 @@
+// 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.
+
+// linux_core_dumper.cc: Implement google_breakpad::LinuxCoreDumper.
+// See linux_core_dumper.h for details.
+
+#include "linux/minidump_writer/linux_core_dumper.h"
+
+#include <asm/ptrace.h>
+#include <assert.h>
+#include <elf.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/procfs.h>
+#if defined(__mips__) && defined(__ANDROID__)
+// To get register definitions.
+#include <asm/reg.h>
+#endif
+
+#include "common/linux/elf_gnu_compat.h"
+#include "common/linux/linux_libc_support.h"
+
+namespace google_breakpad {
+
+LinuxCoreDumper::LinuxCoreDumper(pid_t pid,
+ const char* core_path,
+ const char* procfs_path,
+ const char* root_prefix)
+ : LinuxDumper(pid, root_prefix),
+ core_path_(core_path),
+ procfs_path_(procfs_path),
+ thread_infos_(&allocator_, 8) {
+ assert(core_path_);
+}
+
+bool LinuxCoreDumper::BuildProcPath(char* path, pid_t pid,
+ const char* node) const {
+ if (!path || !node)
+ return false;
+
+ size_t node_len = my_strlen(node);
+ if (node_len == 0)
+ return false;
+
+ size_t procfs_path_len = my_strlen(procfs_path_);
+ size_t total_length = procfs_path_len + 1 + node_len;
+ if (total_length >= NAME_MAX)
+ return false;
+
+ memcpy(path, procfs_path_, procfs_path_len);
+ path[procfs_path_len] = '/';
+ memcpy(path + procfs_path_len + 1, node, node_len);
+ path[total_length] = '\0';
+ return true;
+}
+
+bool LinuxCoreDumper::CopyFromProcess(void* dest, pid_t child,
+ const void* src, size_t length) {
+ ElfCoreDump::Addr virtual_address = reinterpret_cast<ElfCoreDump::Addr>(src);
+ // TODO(benchan): Investigate whether the data to be copied could span
+ // across multiple segments in the core dump file. ElfCoreDump::CopyData
+ // and this method do not handle that case yet.
+ if (!core_.CopyData(dest, virtual_address, length)) {
+ // If the data segment is not found in the core dump, fill the result
+ // with marker characters.
+ memset(dest, 0xab, length);
+ return false;
+ }
+ return true;
+}
+
+bool LinuxCoreDumper::GetThreadInfoByIndex(size_t index, ThreadInfo* info) {
+ if (index >= thread_infos_.size())
+ return false;
+
+ *info = thread_infos_[index];
+ const uint8_t* stack_pointer;
+#if defined(__i386)
+ memcpy(&stack_pointer, &info->regs.esp, sizeof(info->regs.esp));
+#elif defined(__x86_64)
+ memcpy(&stack_pointer, &info->regs.rsp, sizeof(info->regs.rsp));
+#elif defined(__ARM_EABI__)
+ memcpy(&stack_pointer, &info->regs.ARM_sp, sizeof(info->regs.ARM_sp));
+#elif defined(__aarch64__)
+ memcpy(&stack_pointer, &info->regs.sp, sizeof(info->regs.sp));
+#elif defined(__mips__)
+ stack_pointer =
+ reinterpret_cast<uint8_t*>(info->mcontext.gregs[MD_CONTEXT_MIPS_REG_SP]);
+#else
+#error "This code hasn't been ported to your platform yet."
+#endif
+ info->stack_pointer = reinterpret_cast<uintptr_t>(stack_pointer);
+ return true;
+}
+
+bool LinuxCoreDumper::GetThreadNameByIndex(size_t index, char* name,
+ size_t size) {
+ // Not implemented
+ return false;
+}
+
+bool LinuxCoreDumper::IsPostMortem() const {
+ return true;
+}
+
+bool LinuxCoreDumper::ThreadsSuspend() {
+ return true;
+}
+
+bool LinuxCoreDumper::ThreadsResume() {
+ return true;
+}
+
+bool LinuxCoreDumper::EnumerateThreads() {
+ if (!mapped_core_file_.Map(core_path_, 0)) {
+ fprintf(stderr, "Could not map core dump file into memory\n");
+ return false;
+ }
+
+ core_.SetContent(mapped_core_file_.content());
+ if (!core_.IsValid()) {
+ fprintf(stderr, "Invalid core dump file\n");
+ return false;
+ }
+
+ ElfCoreDump::Note note = core_.GetFirstNote();
+ if (!note.IsValid()) {
+ fprintf(stderr, "PT_NOTE section not found\n");
+ return false;
+ }
+
+ bool first_thread = true;
+ do {
+ ElfCoreDump::Word type = note.GetType();
+ MemoryRange name = note.GetName();
+ MemoryRange description = note.GetDescription();
+
+ if (type == 0 || name.IsEmpty() || description.IsEmpty()) {
+ fprintf(stderr, "Could not found a valid PT_NOTE.\n");
+ return false;
+ }
+
+ // 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_SIGINFO
+ // 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
+ //
+ // The following code only works if notes are ordered as expected.
+ switch (type) {
+ case NT_PRSTATUS: {
+ if (description.length() != sizeof(elf_prstatus)) {
+ fprintf(stderr, "Found NT_PRSTATUS descriptor of unexpected size\n");
+ return false;
+ }
+
+ const elf_prstatus* status =
+ reinterpret_cast<const elf_prstatus*>(description.data());
+ pid_t pid = status->pr_pid;
+ ThreadInfo info;
+ memset(&info, 0, sizeof(ThreadInfo));
+ info.tgid = status->pr_pgrp;
+ info.ppid = status->pr_ppid;
+#if defined(__mips__)
+#if defined(__ANDROID__)
+ for (int i = EF_R0; i <= EF_R31; i++)
+ info.mcontext.gregs[i - EF_R0] = status->pr_reg[i];
+#else // __ANDROID__
+ for (int i = EF_REG0; i <= EF_REG31; i++)
+ info.mcontext.gregs[i - EF_REG0] = status->pr_reg[i];
+#endif // __ANDROID__
+ info.mcontext.mdlo = status->pr_reg[EF_LO];
+ info.mcontext.mdhi = status->pr_reg[EF_HI];
+ info.mcontext.pc = status->pr_reg[EF_CP0_EPC];
+#else // __mips__
+ memcpy(&info.regs, status->pr_reg, sizeof(info.regs));
+#endif // __mips__
+ if (first_thread) {
+ crash_thread_ = pid;
+ crash_signal_ = status->pr_info.si_signo;
+ crash_signal_code_ = status->pr_info.si_code;
+ }
+ first_thread = false;
+ threads_.push_back(pid);
+ thread_infos_.push_back(info);
+ break;
+ }
+ case NT_SIGINFO: {
+ if (description.length() != sizeof(siginfo_t)) {
+ fprintf(stderr, "Found NT_SIGINFO descriptor of unexpected size\n");
+ return false;
+ }
+
+ const siginfo_t* info =
+ reinterpret_cast<const siginfo_t*>(description.data());
+
+ // Set crash_address when si_addr is valid for the signal.
+ switch (info->si_signo) {
+ case MD_EXCEPTION_CODE_LIN_SIGBUS:
+ case MD_EXCEPTION_CODE_LIN_SIGFPE:
+ case MD_EXCEPTION_CODE_LIN_SIGILL:
+ case MD_EXCEPTION_CODE_LIN_SIGSEGV:
+ case MD_EXCEPTION_CODE_LIN_SIGSYS:
+ case MD_EXCEPTION_CODE_LIN_SIGTRAP:
+ crash_address_ = reinterpret_cast<uintptr_t>(info->si_addr);
+ break;
+ }
+
+ // Set crash_exception_info for common signals. Since exception info is
+ // unsigned, but some of these fields might be signed, we always cast.
+ switch (info->si_signo) {
+ case MD_EXCEPTION_CODE_LIN_SIGKILL:
+ set_crash_exception_info({
+ static_cast<uint64_t>(info->si_pid),
+ static_cast<uint64_t>(info->si_uid),
+ });
+ break;
+ case MD_EXCEPTION_CODE_LIN_SIGSYS:
+#ifdef si_syscall
+ set_crash_exception_info({
+ static_cast<uint64_t>(info->si_syscall),
+ static_cast<uint64_t>(info->si_arch),
+ });
+#endif
+ break;
+ }
+ break;
+ }
+#if defined(__i386) || defined(__x86_64)
+ case NT_FPREGSET: {
+ if (thread_infos_.empty())
+ return false;
+
+ ThreadInfo* info = &thread_infos_.back();
+ if (description.length() != sizeof(info->fpregs)) {
+ fprintf(stderr, "Found NT_FPREGSET descriptor of unexpected size\n");
+ return false;
+ }
+
+ memcpy(&info->fpregs, description.data(), sizeof(info->fpregs));
+ break;
+ }
+#endif
+#if defined(__i386)
+ case NT_PRXFPREG: {
+ if (thread_infos_.empty())
+ return false;
+
+ ThreadInfo* info = &thread_infos_.back();
+ if (description.length() != sizeof(info->fpxregs)) {
+ fprintf(stderr, "Found NT_PRXFPREG descriptor of unexpected size\n");
+ return false;
+ }
+
+ memcpy(&info->fpxregs, description.data(), sizeof(info->fpxregs));
+ break;
+ }
+#endif
+ }
+ note = note.GetNextNote();
+ } while (note.IsValid());
+
+ return true;
+}
+
+} // namespace google_breakpad
diff --git a/toolkit/crashreporter/breakpad-client/linux/minidump_writer/linux_core_dumper.h b/toolkit/crashreporter/breakpad-client/linux/minidump_writer/linux_core_dumper.h
new file mode 100644
index 0000000000..7805854a33
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/linux/minidump_writer/linux_core_dumper.h
@@ -0,0 +1,130 @@
+// 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.
+
+// linux_core_dumper.h: Define the google_breakpad::LinuxCoreDumper
+// class, which is derived from google_breakpad::LinuxDumper to extract
+// information from a crashed process via its core dump and proc files.
+
+#ifndef CLIENT_LINUX_MINIDUMP_WRITER_LINUX_CORE_DUMPER_H_
+#define CLIENT_LINUX_MINIDUMP_WRITER_LINUX_CORE_DUMPER_H_
+
+#include "linux/minidump_writer/linux_dumper.h"
+#include "common/linux/elf_core_dump.h"
+#include "common/linux/memory_mapped_file.h"
+
+namespace google_breakpad {
+
+class LinuxCoreDumper : public LinuxDumper {
+ public:
+ // Constructs a dumper for extracting information of a given process
+ // with a process ID of |pid| via its core dump file at |core_path| and
+ // its proc files at |procfs_path|. If |procfs_path| is a copy of
+ // /proc/<pid>, it should contain the following files:
+ // auxv, cmdline, environ, exe, maps, status
+ // See LinuxDumper for the purpose of |root_prefix|.
+ LinuxCoreDumper(pid_t pid, const char* core_path, const char* procfs_path,
+ const char* root_prefix = "");
+
+ // Implements LinuxDumper::BuildProcPath().
+ // Builds a proc path for a certain pid for a node (/proc/<pid>/<node>).
+ // |path| is a character array of at least NAME_MAX bytes to return the
+ // result.|node| is the final node without any slashes. Return true on
+ // success.
+ //
+ // As this dumper performs a post-mortem dump and makes use of a copy
+ // of the proc files of the crashed process, this derived method does
+ // not actually make use of |pid| and always returns a subpath of
+ // |procfs_path_| regardless of whether |pid| corresponds to the main
+ // process or a thread of the process, i.e. assuming both the main process
+ // and its threads have the following proc files with the same content:
+ // auxv, cmdline, environ, exe, maps, status
+ virtual bool BuildProcPath(char* path, pid_t pid, const char* node) const;
+
+ // Implements LinuxDumper::CopyFromProcess().
+ // Copies content of |length| bytes from a given process |child|,
+ // starting from |src|, into |dest|. This method extracts the content
+ // the core dump and fills |dest| with a sequence of marker bytes
+ // if the expected data is not found in the core dump. Returns true if
+ // the expected data is found in the core dump.
+ virtual bool CopyFromProcess(void* dest, pid_t child, const void* src,
+ size_t length);
+
+ // Implements LinuxDumper::GetThreadInfoByIndex().
+ // Reads information about the |index|-th thread of |threads_|.
+ // Returns true on success. One must have called |ThreadsSuspend| first.
+ virtual bool GetThreadInfoByIndex(size_t index, ThreadInfo* info);
+
+ // Implements LinuxDumper::GetThreadNameByIndex().
+ // Reads the name of the |index|-th thread of |threads_|.
+ // Returns true on success. One must have called |ThreadsSuspend| first.
+ virtual bool GetThreadNameByIndex(size_t index, char* info, size_t size);
+
+ // Implements LinuxDumper::IsPostMortem().
+ // Always returns true to indicate that this dumper performs a
+ // post-mortem dump of a crashed process via a core dump file.
+ virtual bool IsPostMortem() const;
+
+ // Implements LinuxDumper::ThreadsSuspend().
+ // As the dumper performs a post-mortem dump via a core dump file,
+ // there is no threads to suspend. This method does nothing and
+ // always returns true.
+ virtual bool ThreadsSuspend();
+
+ // Implements LinuxDumper::ThreadsResume().
+ // As the dumper performs a post-mortem dump via a core dump file,
+ // there is no threads to resume. This method does nothing and
+ // always returns true.
+ virtual bool ThreadsResume();
+
+ protected:
+ // Implements LinuxDumper::EnumerateThreads().
+ // Enumerates all threads of the given process into |threads_|.
+ virtual bool EnumerateThreads();
+
+ private:
+ // Path of the core dump file.
+ const char* core_path_;
+
+ // Path of the directory containing the proc files of the given process,
+ // which is usually a copy of /proc/<pid>.
+ const char* procfs_path_;
+
+ // Memory-mapped core dump file at |core_path_|.
+ MemoryMappedFile mapped_core_file_;
+
+ // Content of the core dump file.
+ ElfCoreDump core_;
+
+ // Thread info found in the core dump file.
+ wasteful_vector<ThreadInfo> thread_infos_;
+};
+
+} // namespace google_breakpad
+
+#endif // CLIENT_LINUX_HANDLER_LINUX_CORE_DUMPER_H_
diff --git a/toolkit/crashreporter/breakpad-client/linux/minidump_writer/linux_core_dumper_unittest.cc b/toolkit/crashreporter/breakpad-client/linux/minidump_writer/linux_core_dumper_unittest.cc
new file mode 100644
index 0000000000..2e973167fd
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/linux/minidump_writer/linux_core_dumper_unittest.cc
@@ -0,0 +1,192 @@
+// 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.
+
+// linux_core_dumper_unittest.cc:
+// Unit tests for google_breakpad::LinuxCoreDumoer.
+
+#include <string>
+
+#include "breakpad_googletest_includes.h"
+#include "linux/minidump_writer/linux_core_dumper.h"
+#include "common/linux/tests/crash_generator.h"
+#include "common/using_std_string.h"
+
+using namespace google_breakpad;
+
+TEST(LinuxCoreDumperTest, GetMappingAbsolutePath) {
+ const LinuxCoreDumper dumper(getpid(), "core", "/tmp", "/mnt/root");
+ const MappingInfo mapping = {0, 0, {0, 0}, 0, false, "/usr/lib/libc.so"};
+
+ char path[PATH_MAX];
+ dumper.GetMappingAbsolutePath(mapping, path);
+
+ EXPECT_STREQ("/mnt/root/usr/lib/libc.so", path);
+}
+
+TEST(LinuxCoreDumperTest, BuildProcPath) {
+ const pid_t pid = getpid();
+ const char procfs_path[] = "/procfs_copy";
+ LinuxCoreDumper dumper(getpid(), "core_file", procfs_path);
+
+ char maps_path[NAME_MAX] = "";
+ char maps_path_expected[NAME_MAX];
+ snprintf(maps_path_expected, sizeof(maps_path_expected),
+ "%s/maps", procfs_path);
+ EXPECT_TRUE(dumper.BuildProcPath(maps_path, pid, "maps"));
+ EXPECT_STREQ(maps_path_expected, maps_path);
+
+ EXPECT_FALSE(dumper.BuildProcPath(NULL, pid, "maps"));
+ EXPECT_FALSE(dumper.BuildProcPath(maps_path, pid, ""));
+ EXPECT_FALSE(dumper.BuildProcPath(maps_path, pid, NULL));
+
+ char long_node[NAME_MAX];
+ size_t long_node_len = NAME_MAX - strlen(procfs_path) - 1;
+ memset(long_node, 'a', long_node_len);
+ long_node[long_node_len] = '\0';
+ EXPECT_FALSE(dumper.BuildProcPath(maps_path, pid, long_node));
+}
+
+TEST(LinuxCoreDumperTest, VerifyDumpWithMultipleThreads) {
+ CrashGenerator crash_generator;
+ if (!crash_generator.HasDefaultCorePattern()) {
+ fprintf(stderr, "LinuxCoreDumperTest.VerifyDumpWithMultipleThreads test "
+ "is skipped due to non-default core pattern\n");
+ return;
+ }
+
+ const unsigned kNumOfThreads = 3;
+ const unsigned kCrashThread = 1;
+ const int kCrashSignal = SIGABRT;
+ pid_t child_pid;
+ ASSERT_TRUE(crash_generator.CreateChildCrash(kNumOfThreads, kCrashThread,
+ kCrashSignal, &child_pid));
+
+ const string core_file = crash_generator.GetCoreFilePath();
+ const string procfs_path = crash_generator.GetDirectoryOfProcFilesCopy();
+
+#if defined(__ANDROID__)
+ struct stat st;
+ if (stat(core_file.c_str(), &st) != 0) {
+ fprintf(stderr, "LinuxCoreDumperTest.VerifyDumpWithMultipleThreads test is "
+ "skipped due to no core file being generated\n");
+ return;
+ }
+#endif
+
+ LinuxCoreDumper dumper(child_pid, core_file.c_str(), procfs_path.c_str());
+
+ EXPECT_TRUE(dumper.Init());
+
+ EXPECT_TRUE(dumper.IsPostMortem());
+
+ // These are no-ops and should always return true.
+ EXPECT_TRUE(dumper.ThreadsSuspend());
+ EXPECT_TRUE(dumper.ThreadsResume());
+
+ // Linux does not set the crash address with SIGABRT, so make sure it always
+ // sets the crash address to 0.
+ EXPECT_EQ(0U, dumper.crash_address());
+ EXPECT_EQ(kCrashSignal, dumper.crash_signal());
+ EXPECT_EQ(crash_generator.GetThreadId(kCrashThread),
+ dumper.crash_thread());
+
+#if defined(THREAD_SANITIZER)
+ EXPECT_GE(dumper.threads().size(), kNumOfThreads);
+#else
+ EXPECT_EQ(dumper.threads().size(), kNumOfThreads);
+#endif
+ for (unsigned i = 0; i < kNumOfThreads; ++i) {
+ ThreadInfo info;
+ EXPECT_TRUE(dumper.GetThreadInfoByIndex(i, &info));
+ const void* stack;
+ size_t stack_len;
+ EXPECT_TRUE(dumper.GetStackInfo(&stack, &stack_len, info.stack_pointer));
+ EXPECT_EQ(getpid(), info.ppid);
+ }
+}
+
+TEST(LinuxCoreDumperTest, VerifyExceptionDetails) {
+ CrashGenerator crash_generator;
+ if (!crash_generator.HasDefaultCorePattern()) {
+ fprintf(stderr, "LinuxCoreDumperTest.VerifyDumpWithMultipleThreads test "
+ "is skipped due to non-default core pattern\n");
+ return;
+ }
+
+#ifndef si_syscall
+ fprintf(stderr, "LinuxCoreDumperTest.VerifyDumpWithMultipleThreads test is "
+ "skipped due to old kernel/C library headers\n");
+ return;
+#endif
+
+ const unsigned kNumOfThreads = 2;
+ const unsigned kCrashThread = 1;
+ const int kCrashSignal = SIGSYS;
+ pid_t child_pid;
+ ASSERT_TRUE(crash_generator.CreateChildCrash(kNumOfThreads, kCrashThread,
+ kCrashSignal, &child_pid));
+
+ const string core_file = crash_generator.GetCoreFilePath();
+ const string procfs_path = crash_generator.GetDirectoryOfProcFilesCopy();
+
+#if defined(__ANDROID__)
+ struct stat st;
+ if (stat(core_file.c_str(), &st) != 0) {
+ fprintf(stderr, "LinuxCoreDumperTest.VerifyExceptionDetails test is "
+ "skipped due to no core file being generated\n");
+ return;
+ }
+#endif
+
+ LinuxCoreDumper dumper(child_pid, core_file.c_str(), procfs_path.c_str());
+
+ EXPECT_TRUE(dumper.Init());
+
+ EXPECT_TRUE(dumper.IsPostMortem());
+
+#if defined(__ANDROID__)
+ // TODO: For some reason, Android doesn't seem to pass this.
+ if (!dumper.crash_address()) {
+ fprintf(stderr, "LinuxCoreDumperTest.VerifyExceptionDetails test is "
+ "skipped due to missing signal details on Android\n");
+ return;
+ }
+#endif
+
+ // Check the exception details.
+ EXPECT_NE(0U, dumper.crash_address());
+ EXPECT_EQ(kCrashSignal, dumper.crash_signal());
+ EXPECT_EQ(crash_generator.GetThreadId(kCrashThread),
+ dumper.crash_thread());
+
+ // We check the length, but not the actual fields. We sent SIGSYS ourselves
+ // instead of the kernel, so the extended fields are garbage.
+ const std::vector<uint64_t> info(dumper.crash_exception_info());
+ EXPECT_EQ(2U, info.size());
+}
diff --git a/toolkit/crashreporter/breakpad-client/linux/minidump_writer/linux_dumper.cc b/toolkit/crashreporter/breakpad-client/linux/minidump_writer/linux_dumper.cc
new file mode 100644
index 0000000000..3b400ce8ca
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/linux/minidump_writer/linux_dumper.cc
@@ -0,0 +1,999 @@
+// 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.
+
+// linux_dumper.cc: Implement google_breakpad::LinuxDumper.
+// See linux_dumper.h for details.
+
+// This code deals with the mechanics of getting information about a crashed
+// process. Since this code may run in a compromised address space, the same
+// rules apply as detailed at the top of minidump_writer.h: no libc calls and
+// use the alternative allocator.
+
+#include "linux/minidump_writer/linux_dumper.h"
+
+#include <assert.h>
+#include <elf.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stddef.h>
+#include <string.h>
+
+#include "linux/minidump_writer/line_reader.h"
+#include "common/linux/elfutils.h"
+#include "common/linux/file_id.h"
+#include "common/linux/linux_libc_support.h"
+#include "common/linux/memory_mapped_file.h"
+#include "common/linux/safe_readlink.h"
+#include "google_breakpad/common/minidump_exception_linux.h"
+#include "third_party/lss/linux_syscall_support.h"
+
+#if defined(__ANDROID__)
+
+// Android packed relocations definitions are not yet available from the
+// NDK header files, so we have to provide them manually here.
+#ifndef DT_LOOS
+#define DT_LOOS 0x6000000d
+#endif
+#ifndef DT_ANDROID_REL
+static const int DT_ANDROID_REL = DT_LOOS + 2;
+#endif
+#ifndef DT_ANDROID_RELA
+static const int DT_ANDROID_RELA = DT_LOOS + 4;
+#endif
+
+#endif // __ANDROID __
+
+static const char kMappedFileUnsafePrefix[] = "/dev/";
+static const char kDeletedSuffix[] = " (deleted)";
+static const char kReservedFlags[] = " ---p";
+static const char kMozillaIpcPrefix[] = "org.mozilla.ipc.";
+
+inline static bool IsMappedFileOpenUnsafe(
+ const google_breakpad::MappingInfo& mapping) {
+ // It is unsafe to attempt to open a mapped file that lives under /dev,
+ // because the semantics of the open may be driver-specific so we'd risk
+ // hanging the crash dumper. And a file in /dev/ almost certainly has no
+ // ELF file identifier anyways.
+ return my_strncmp(mapping.name,
+ kMappedFileUnsafePrefix,
+ sizeof(kMappedFileUnsafePrefix) - 1) == 0;
+}
+
+namespace google_breakpad {
+
+namespace {
+
+bool MappingContainsAddress(const MappingInfo& mapping, uintptr_t address) {
+ return mapping.system_mapping_info.start_addr <= address &&
+ address < mapping.system_mapping_info.end_addr;
+}
+
+#if defined(__CHROMEOS__)
+
+// Recover memory mappings before writing dump on ChromeOS
+//
+// On Linux, breakpad relies on /proc/[pid]/maps to associate symbols from
+// addresses. ChromeOS' hugepage implementation replaces some segments with
+// anonymous private pages, which is a restriction of current implementation
+// in Linux kernel at the time of writing. Thus, breakpad can no longer
+// symbolize addresses from those text segments replaced with hugepages.
+//
+// This postprocess tries to recover the mappings. Because hugepages are always
+// inserted in between some .text sections, it tries to infer the names and
+// offsets of the segments, by looking at segments immediately precede and
+// succeed them.
+//
+// For example, a text segment before hugepage optimization
+// 02001000-03002000 r-xp /opt/google/chrome/chrome
+//
+// can be broken into
+// 02001000-02200000 r-xp /opt/google/chrome/chrome
+// 02200000-03000000 r-xp
+// 03000000-03002000 r-xp /opt/google/chrome/chrome
+//
+// For more details, see:
+// crbug.com/628040 ChromeOS' use of hugepages confuses crash symbolization
+
+// Copied from CrOS' hugepage implementation, which is unlikely to change.
+// The hugepage size is 2M.
+const unsigned int kHpageShift = 21;
+const size_t kHpageSize = (1 << kHpageShift);
+const size_t kHpageMask = (~(kHpageSize - 1));
+
+// Find and merge anonymous r-xp segments with surrounding named segments.
+// There are two cases:
+
+// Case 1: curr, next
+// curr is anonymous
+// curr is r-xp
+// curr.size >= 2M
+// curr.size is a multiple of 2M.
+// next is backed by some file.
+// curr and next are contiguous.
+// offset(next) == sizeof(curr)
+void TryRecoverMappings(MappingInfo *curr, MappingInfo *next) {
+ // Merged segments are marked with size = 0.
+ if (curr->size == 0 || next->size == 0)
+ return;
+
+ if (curr->size >= kHpageSize &&
+ curr->exec &&
+ (curr->size & kHpageMask) == curr->size &&
+ (curr->start_addr & kHpageMask) == curr->start_addr &&
+ curr->name[0] == '\0' &&
+ next->name[0] != '\0' &&
+ curr->start_addr + curr->size == next->start_addr &&
+ curr->size == next->offset) {
+
+ // matched
+ my_strlcpy(curr->name, next->name, NAME_MAX);
+ if (next->exec) {
+ // (curr, next)
+ curr->size += next->size;
+ next->size = 0;
+ }
+ }
+}
+
+// Case 2: prev, curr, next
+// curr is anonymous
+// curr is r-xp
+// curr.size >= 2M
+// curr.size is a multiple of 2M.
+// next and prev are backed by the same file.
+// prev, curr and next are contiguous.
+// offset(next) == offset(prev) + sizeof(prev) + sizeof(curr)
+void TryRecoverMappings(MappingInfo *prev, MappingInfo *curr,
+ MappingInfo *next) {
+ // Merged segments are marked with size = 0.
+ if (prev->size == 0 || curr->size == 0 || next->size == 0)
+ return;
+
+ if (curr->size >= kHpageSize &&
+ curr->exec &&
+ (curr->size & kHpageMask) == curr->size &&
+ (curr->start_addr & kHpageMask) == curr->start_addr &&
+ curr->name[0] == '\0' &&
+ next->name[0] != '\0' &&
+ curr->start_addr + curr->size == next->start_addr &&
+ prev->start_addr + prev->size == curr->start_addr &&
+ my_strncmp(prev->name, next->name, NAME_MAX) == 0 &&
+ next->offset == prev->offset + prev->size + curr->size) {
+
+ // matched
+ my_strlcpy(curr->name, prev->name, NAME_MAX);
+ if (prev->exec) {
+ curr->offset = prev->offset;
+ curr->start_addr = prev->start_addr;
+ if (next->exec) {
+ // (prev, curr, next)
+ curr->size += prev->size + next->size;
+ prev->size = 0;
+ next->size = 0;
+ } else {
+ // (prev, curr), next
+ curr->size += prev->size;
+ prev->size = 0;
+ }
+ } else {
+ curr->offset = prev->offset + prev->size;
+ if (next->exec) {
+ // prev, (curr, next)
+ curr->size += next->size;
+ next->size = 0;
+ } else {
+ // prev, curr, next
+ }
+ }
+ }
+}
+
+// mappings_ is sorted excepted for the first entry.
+// This function tries to merge segemnts into the first entry,
+// then check for other sorted entries.
+// See LinuxDumper::EnumerateMappings().
+void CrOSPostProcessMappings(wasteful_vector<MappingInfo*>& mappings) {
+ // Find the candidate "next" to first segment, which is the only one that
+ // could be out-of-order.
+ size_t l = 1;
+ size_t r = mappings.size();
+ size_t next = mappings.size();
+ while (l < r) {
+ int m = (l + r) / 2;
+ if (mappings[m]->start_addr > mappings[0]->start_addr)
+ r = next = m;
+ else
+ l = m + 1;
+ }
+
+ // Shows the range that contains the entry point is
+ // [first_start_addr, first_end_addr)
+ size_t first_start_addr = mappings[0]->start_addr;
+ size_t first_end_addr = mappings[0]->start_addr + mappings[0]->size;
+
+ // Put the out-of-order segment in order.
+ std::rotate(mappings.begin(), mappings.begin() + 1, mappings.begin() + next);
+
+ // Iterate through normal, sorted cases.
+ // Normal case 1.
+ for (size_t i = 0; i < mappings.size() - 1; i++)
+ TryRecoverMappings(mappings[i], mappings[i + 1]);
+
+ // Normal case 2.
+ for (size_t i = 0; i < mappings.size() - 2; i++)
+ TryRecoverMappings(mappings[i], mappings[i + 1], mappings[i + 2]);
+
+ // Collect merged (size == 0) segments.
+ size_t f, e;
+ for (f = e = 0; e < mappings.size(); e++)
+ if (mappings[e]->size > 0)
+ mappings[f++] = mappings[e];
+ mappings.resize(f);
+
+ // The entry point is in the first mapping. We want to find the location
+ // of the entry point after merging segment. To do this, we want to find
+ // the mapping that covers the first mapping from the original mapping list.
+ // If the mapping is not in the beginning, we move it to the begining via
+ // a right rotate by using reverse iterators.
+ for (l = 0; l < mappings.size(); l++) {
+ if (mappings[l]->start_addr <= first_start_addr
+ && (mappings[l]->start_addr + mappings[l]->size >= first_end_addr))
+ break;
+ }
+ if (l > 0) {
+ r = mappings.size();
+ std::rotate(mappings.rbegin() + r - l - 1, mappings.rbegin() + r - l,
+ mappings.rend());
+ }
+}
+
+#endif // __CHROMEOS__
+
+} // namespace
+
+// All interesting auvx entry types are below AT_SYSINFO_EHDR
+#define AT_MAX AT_SYSINFO_EHDR
+
+LinuxDumper::LinuxDumper(pid_t pid, const char* root_prefix)
+ : pid_(pid),
+ root_prefix_(root_prefix),
+ crash_address_(0),
+ crash_signal_(0),
+ crash_signal_code_(0),
+ crash_thread_(pid),
+ threads_(&allocator_, 8),
+ mappings_(&allocator_),
+ auxv_(&allocator_, AT_MAX + 1) {
+ assert(root_prefix_ && my_strlen(root_prefix_) < PATH_MAX);
+ // The passed-in size to the constructor (above) is only a hint.
+ // Must call .resize() to do actual initialization of the elements.
+ auxv_.resize(AT_MAX + 1);
+}
+
+LinuxDumper::~LinuxDumper() {
+}
+
+bool LinuxDumper::Init() {
+ return ReadAuxv() && EnumerateThreads() && EnumerateMappings();
+}
+
+bool LinuxDumper::LateInit() {
+#if defined(__ANDROID__)
+ LatePostprocessMappings();
+#endif
+
+#if defined(__CHROMEOS__)
+ CrOSPostProcessMappings(mappings_);
+#endif
+
+ return true;
+}
+
+bool
+LinuxDumper::ElfFileIdentifierForMapping(const MappingInfo& mapping,
+ bool member,
+ unsigned int mapping_id,
+ wasteful_vector<uint8_t>& identifier) {
+ assert(!member || mapping_id < mappings_.size());
+ if (IsMappedFileOpenUnsafe(mapping))
+ return false;
+
+ // Special-case linux-gate because it's not a real file.
+ if (my_strcmp(mapping.name, kLinuxGateLibraryName) == 0) {
+ void* linux_gate = NULL;
+ if (pid_ == sys_getpid()) {
+ linux_gate = reinterpret_cast<void*>(mapping.start_addr);
+ } else {
+ linux_gate = allocator_.Alloc(mapping.size);
+ CopyFromProcess(linux_gate, pid_,
+ reinterpret_cast<const void*>(mapping.start_addr),
+ mapping.size);
+ }
+ return FileID::ElfFileIdentifierFromMappedFile(linux_gate, identifier);
+ }
+
+ char filename[PATH_MAX];
+ if (!GetMappingAbsolutePath(mapping, filename))
+ return false;
+ bool filename_modified = HandleDeletedFileInMapping(filename);
+
+ MemoryMappedFile mapped_file(filename, mapping.offset);
+ if (!mapped_file.data() || mapped_file.size() < SELFMAG)
+ return false;
+
+ bool success =
+ FileID::ElfFileIdentifierFromMappedFile(mapped_file.data(), identifier);
+ if (success && member && filename_modified) {
+ mappings_[mapping_id]->name[my_strlen(mapping.name) -
+ sizeof(kDeletedSuffix) + 1] = '\0';
+ }
+
+ return success;
+}
+
+void LinuxDumper::SetCrashInfoFromSigInfo(const siginfo_t& siginfo) {
+ set_crash_address(reinterpret_cast<uintptr_t>(siginfo.si_addr));
+ set_crash_signal(siginfo.si_signo);
+ set_crash_signal_code(siginfo.si_code);
+}
+
+const char* LinuxDumper::GetCrashSignalString() const {
+ switch (static_cast<unsigned int>(crash_signal_)) {
+ case MD_EXCEPTION_CODE_LIN_SIGHUP:
+ return "SIGHUP";
+ case MD_EXCEPTION_CODE_LIN_SIGINT:
+ return "SIGINT";
+ case MD_EXCEPTION_CODE_LIN_SIGQUIT:
+ return "SIGQUIT";
+ case MD_EXCEPTION_CODE_LIN_SIGILL:
+ return "SIGILL";
+ case MD_EXCEPTION_CODE_LIN_SIGTRAP:
+ return "SIGTRAP";
+ case MD_EXCEPTION_CODE_LIN_SIGABRT:
+ return "SIGABRT";
+ case MD_EXCEPTION_CODE_LIN_SIGBUS:
+ return "SIGBUS";
+ case MD_EXCEPTION_CODE_LIN_SIGFPE:
+ return "SIGFPE";
+ case MD_EXCEPTION_CODE_LIN_SIGKILL:
+ return "SIGKILL";
+ case MD_EXCEPTION_CODE_LIN_SIGUSR1:
+ return "SIGUSR1";
+ case MD_EXCEPTION_CODE_LIN_SIGSEGV:
+ return "SIGSEGV";
+ case MD_EXCEPTION_CODE_LIN_SIGUSR2:
+ return "SIGUSR2";
+ case MD_EXCEPTION_CODE_LIN_SIGPIPE:
+ return "SIGPIPE";
+ case MD_EXCEPTION_CODE_LIN_SIGALRM:
+ return "SIGALRM";
+ case MD_EXCEPTION_CODE_LIN_SIGTERM:
+ return "SIGTERM";
+ case MD_EXCEPTION_CODE_LIN_SIGSTKFLT:
+ return "SIGSTKFLT";
+ case MD_EXCEPTION_CODE_LIN_SIGCHLD:
+ return "SIGCHLD";
+ case MD_EXCEPTION_CODE_LIN_SIGCONT:
+ return "SIGCONT";
+ case MD_EXCEPTION_CODE_LIN_SIGSTOP:
+ return "SIGSTOP";
+ case MD_EXCEPTION_CODE_LIN_SIGTSTP:
+ return "SIGTSTP";
+ case MD_EXCEPTION_CODE_LIN_SIGTTIN:
+ return "SIGTTIN";
+ case MD_EXCEPTION_CODE_LIN_SIGTTOU:
+ return "SIGTTOU";
+ case MD_EXCEPTION_CODE_LIN_SIGURG:
+ return "SIGURG";
+ case MD_EXCEPTION_CODE_LIN_SIGXCPU:
+ return "SIGXCPU";
+ case MD_EXCEPTION_CODE_LIN_SIGXFSZ:
+ return "SIGXFSZ";
+ case MD_EXCEPTION_CODE_LIN_SIGVTALRM:
+ return "SIGVTALRM";
+ case MD_EXCEPTION_CODE_LIN_SIGPROF:
+ return "SIGPROF";
+ case MD_EXCEPTION_CODE_LIN_SIGWINCH:
+ return "SIGWINCH";
+ case MD_EXCEPTION_CODE_LIN_SIGIO:
+ return "SIGIO";
+ case MD_EXCEPTION_CODE_LIN_SIGPWR:
+ return "SIGPWR";
+ case MD_EXCEPTION_CODE_LIN_SIGSYS:
+ return "SIGSYS";
+ case MD_EXCEPTION_CODE_LIN_DUMP_REQUESTED:
+ return "DUMP_REQUESTED";
+ default:
+ return "UNKNOWN";
+ }
+}
+
+bool LinuxDumper::GetMappingAbsolutePath(const MappingInfo& mapping,
+ char path[PATH_MAX]) const {
+ return my_strlcpy(path, root_prefix_, PATH_MAX) < PATH_MAX &&
+ my_strlcat(path, mapping.name, PATH_MAX) < PATH_MAX;
+}
+
+namespace {
+// Find the shared object name (SONAME) by examining the ELF information
+// for |mapping|. If the SONAME is found copy it into the passed buffer
+// |soname| and return true. The size of the buffer is |soname_size|.
+// The SONAME will be truncated if it is too long to fit in the buffer.
+bool ElfFileSoName(const LinuxDumper& dumper,
+ const MappingInfo& mapping, char* soname, size_t soname_size) {
+ if (IsMappedFileOpenUnsafe(mapping)) {
+ // Not safe
+ return false;
+ }
+
+ char filename[PATH_MAX];
+ if (!dumper.GetMappingAbsolutePath(mapping, filename))
+ return false;
+
+ MemoryMappedFile mapped_file(filename, mapping.offset);
+ if (!mapped_file.data() || mapped_file.size() < SELFMAG) {
+ // mmap failed
+ return false;
+ }
+
+ return ElfFileSoNameFromMappedFile(mapped_file.data(), soname, soname_size);
+}
+
+} // namespace
+
+
+void LinuxDumper::GetMappingEffectiveNameAndPath(const MappingInfo& mapping,
+ char* file_path,
+ size_t file_path_size,
+ char* file_name,
+ size_t file_name_size) {
+ my_strlcpy(file_path, mapping.name, file_path_size);
+
+ // Tools such as minidump_stackwalk use the name of the module to look up
+ // symbols produced by dump_syms. dump_syms will prefer to use a module's
+ // DT_SONAME as the module name, if one exists, and will fall back to the
+ // filesystem name of the module.
+
+ // Just use the filesystem name if no SONAME is present.
+ if (!ElfFileSoName(*this, mapping, file_name, file_name_size)) {
+ // file_path := /path/to/libname.so
+ // file_name := libname.so
+ const char* basename = my_strrchr(file_path, '/');
+ basename = basename == NULL ? file_path : (basename + 1);
+ my_strlcpy(file_name, basename, file_name_size);
+ return;
+ }
+
+ if (mapping.exec && mapping.offset != 0) {
+ // If an executable is mapped from a non-zero offset, this is likely because
+ // the executable was loaded directly from inside an archive file (e.g., an
+ // apk on Android).
+ // In this case, we append the file_name to the mapped archive path:
+ // file_name := libname.so
+ // file_path := /path/to/ARCHIVE.APK/libname.so
+ if (my_strlen(file_path) + 1 + my_strlen(file_name) < file_path_size) {
+ my_strlcat(file_path, "/", file_path_size);
+ my_strlcat(file_path, file_name, file_path_size);
+ }
+ } else {
+ // Otherwise, replace the basename with the SONAME.
+ char* basename = const_cast<char*>(my_strrchr(file_path, '/'));
+ if (basename) {
+ my_strlcpy(basename + 1, file_name,
+ file_path_size - my_strlen(file_path) +
+ my_strlen(basename + 1));
+ } else {
+ my_strlcpy(file_path, file_name, file_path_size);
+ }
+ }
+}
+
+bool LinuxDumper::ReadAuxv() {
+ char auxv_path[NAME_MAX];
+ if (!BuildProcPath(auxv_path, pid_, "auxv")) {
+ return false;
+ }
+
+ int fd = sys_open(auxv_path, O_RDONLY, 0);
+ if (fd < 0) {
+ return false;
+ }
+
+ elf_aux_entry one_aux_entry;
+ bool res = false;
+ while (sys_read(fd,
+ &one_aux_entry,
+ sizeof(elf_aux_entry)) == sizeof(elf_aux_entry) &&
+ one_aux_entry.a_type != AT_NULL) {
+ if (one_aux_entry.a_type <= AT_MAX) {
+ auxv_[one_aux_entry.a_type] = one_aux_entry.a_un.a_val;
+ res = true;
+ }
+ }
+ sys_close(fd);
+ return res;
+}
+
+bool LinuxDumper::IsIPCSharedMemorySegment(const char* name) {
+ if (my_strstr(name, kMozillaIpcPrefix) &&
+ my_strstr(name, kDeletedSuffix)) {
+ return true;
+ }
+
+ return false;
+}
+
+bool LinuxDumper::EnumerateMappings() {
+ char maps_path[NAME_MAX];
+ if (!BuildProcPath(maps_path, pid_, "maps"))
+ return false;
+
+ // linux_gate_loc is the beginning of the kernel's mapping of
+ // linux-gate.so in the process. It doesn't actually show up in the
+ // maps list as a filename, but it can be found using the AT_SYSINFO_EHDR
+ // aux vector entry, which gives the information necessary to special
+ // case its entry when creating the list of mappings.
+ // See http://www.trilithium.com/johan/2005/08/linux-gate/ for more
+ // information.
+ const void* linux_gate_loc =
+ reinterpret_cast<void *>(auxv_[AT_SYSINFO_EHDR]);
+ // Although the initial executable is usually the first mapping, it's not
+ // guaranteed (see http://crosbug.com/25355); therefore, try to use the
+ // actual entry point to find the mapping.
+ const void* entry_point_loc = reinterpret_cast<void *>(auxv_[AT_ENTRY]);
+
+ const int fd = sys_open(maps_path, O_RDONLY, 0);
+ if (fd < 0)
+ return false;
+ LineReader* const line_reader = new(allocator_) LineReader(fd);
+
+ const char* line;
+ unsigned line_len;
+ while (line_reader->GetNextLine(&line, &line_len)) {
+ uintptr_t start_addr, end_addr, offset;
+
+ const char* i1 = my_read_hex_ptr(&start_addr, line);
+ if (*i1 == '-') {
+ const char* i2 = my_read_hex_ptr(&end_addr, i1 + 1);
+ if (*i2 == ' ') {
+ bool exec = (*(i2 + 3) == 'x');
+ const char* i3 = my_read_hex_ptr(&offset, i2 + 6 /* skip ' rwxp ' */);
+ if (*i3 == ' ') {
+ const char* name = NULL;
+ // Only copy name if the name is a valid path name, or if
+ // it's the VDSO image.
+ if (((name = my_strchr(line, '/')) == NULL) &&
+ linux_gate_loc &&
+ reinterpret_cast<void*>(start_addr) == linux_gate_loc) {
+ name = kLinuxGateLibraryName;
+ offset = 0;
+ }
+ // Skip shared memory segments used for IPC
+ if (name && IsIPCSharedMemorySegment(name)) {
+ line_reader->PopLine(line_len);
+ continue;
+ }
+ // Merge adjacent mappings into one module, assuming they're a single
+ // library mapped by the dynamic linker.
+ if (name && !mappings_.empty()) {
+ MappingInfo* module = mappings_.back();
+ if ((start_addr == module->start_addr + module->size) &&
+ (my_strlen(name) == my_strlen(module->name)) &&
+ (my_strncmp(name, module->name, my_strlen(name)) == 0)) {
+ module->system_mapping_info.end_addr = end_addr;
+ module->size = end_addr - module->start_addr;
+ module->exec |= exec;
+ line_reader->PopLine(line_len);
+ continue;
+ }
+ }
+ // Also merge mappings that result from address ranges that the
+ // linker reserved but which a loaded library did not use. These
+ // appear as an anonymous private mapping with no access flags set
+ // and which directly follow an executable mapping.
+ if (!name && !mappings_.empty()) {
+ MappingInfo* module = mappings_.back();
+ uintptr_t module_end_addr = module->start_addr + module->size;
+ if ((start_addr == module_end_addr) &&
+ module->exec &&
+ module->name[0] == '/' &&
+ ((offset == 0) || (offset == module_end_addr)) &&
+ my_strncmp(i2, kReservedFlags,
+ sizeof(kReservedFlags) - 1) == 0) {
+ module->size = end_addr - module->start_addr;
+ line_reader->PopLine(line_len);
+ continue;
+ }
+ }
+ MappingInfo* const module = new(allocator_) MappingInfo;
+ mappings_.push_back(module);
+ my_memset(module, 0, sizeof(MappingInfo));
+ module->system_mapping_info.start_addr = start_addr;
+ module->system_mapping_info.end_addr = end_addr;
+ module->start_addr = start_addr;
+ module->size = end_addr - start_addr;
+ module->offset = offset;
+ module->exec = exec;
+ if (name != NULL) {
+ const unsigned l = my_strlen(name);
+ if (l < sizeof(module->name))
+ my_memcpy(module->name, name, l);
+ }
+ }
+ }
+ }
+ line_reader->PopLine(line_len);
+ }
+
+ if (entry_point_loc) {
+ for (size_t i = 0; i < mappings_.size(); ++i) {
+ MappingInfo* module = mappings_[i];
+
+ // If this module contains the entry-point, and it's not already the first
+ // one, then we need to make it be first. This is because the minidump
+ // format assumes the first module is the one that corresponds to the main
+ // executable (as codified in
+ // processor/minidump.cc:MinidumpModuleList::GetMainModule()).
+ if ((entry_point_loc >= reinterpret_cast<void*>(module->start_addr)) &&
+ (entry_point_loc <
+ reinterpret_cast<void*>(module->start_addr + module->size))) {
+ for (size_t j = i; j > 0; j--)
+ mappings_[j] = mappings_[j - 1];
+ mappings_[0] = module;
+ break;
+ }
+ }
+ }
+
+ sys_close(fd);
+
+ return !mappings_.empty();
+}
+
+#if defined(__ANDROID__)
+
+bool LinuxDumper::GetLoadedElfHeader(uintptr_t start_addr, ElfW(Ehdr)* ehdr) {
+ CopyFromProcess(ehdr, pid_,
+ reinterpret_cast<const void*>(start_addr),
+ sizeof(*ehdr));
+ return my_memcmp(&ehdr->e_ident, ELFMAG, SELFMAG) == 0;
+}
+
+void LinuxDumper::ParseLoadedElfProgramHeaders(ElfW(Ehdr)* ehdr,
+ uintptr_t start_addr,
+ uintptr_t* min_vaddr_ptr,
+ uintptr_t* dyn_vaddr_ptr,
+ size_t* dyn_count_ptr) {
+ uintptr_t phdr_addr = start_addr + ehdr->e_phoff;
+
+ const uintptr_t max_addr = UINTPTR_MAX;
+ uintptr_t min_vaddr = max_addr;
+ uintptr_t dyn_vaddr = 0;
+ size_t dyn_count = 0;
+
+ for (size_t i = 0; i < ehdr->e_phnum; ++i) {
+ ElfW(Phdr) phdr;
+ CopyFromProcess(&phdr, pid_,
+ reinterpret_cast<const void*>(phdr_addr),
+ sizeof(phdr));
+ if (phdr.p_type == PT_LOAD && phdr.p_vaddr < min_vaddr) {
+ min_vaddr = phdr.p_vaddr;
+ }
+ if (phdr.p_type == PT_DYNAMIC) {
+ dyn_vaddr = phdr.p_vaddr;
+ dyn_count = phdr.p_memsz / sizeof(ElfW(Dyn));
+ }
+ phdr_addr += sizeof(phdr);
+ }
+
+ *min_vaddr_ptr = min_vaddr;
+ *dyn_vaddr_ptr = dyn_vaddr;
+ *dyn_count_ptr = dyn_count;
+}
+
+bool LinuxDumper::HasAndroidPackedRelocations(uintptr_t load_bias,
+ uintptr_t dyn_vaddr,
+ size_t dyn_count) {
+ uintptr_t dyn_addr = load_bias + dyn_vaddr;
+ for (size_t i = 0; i < dyn_count; ++i) {
+ ElfW(Dyn) dyn;
+ CopyFromProcess(&dyn, pid_,
+ reinterpret_cast<const void*>(dyn_addr),
+ sizeof(dyn));
+ if (dyn.d_tag == DT_ANDROID_REL || dyn.d_tag == DT_ANDROID_RELA) {
+ return true;
+ }
+ dyn_addr += sizeof(dyn);
+ }
+ return false;
+}
+
+uintptr_t LinuxDumper::GetEffectiveLoadBias(ElfW(Ehdr)* ehdr,
+ uintptr_t start_addr) {
+ uintptr_t min_vaddr = 0;
+ uintptr_t dyn_vaddr = 0;
+ size_t dyn_count = 0;
+ ParseLoadedElfProgramHeaders(ehdr, start_addr,
+ &min_vaddr, &dyn_vaddr, &dyn_count);
+ // If |min_vaddr| is non-zero and we find Android packed relocation tags,
+ // return the effective load bias.
+ if (min_vaddr != 0) {
+ const uintptr_t load_bias = start_addr - min_vaddr;
+ if (HasAndroidPackedRelocations(load_bias, dyn_vaddr, dyn_count)) {
+ return load_bias;
+ }
+ }
+ // Either |min_vaddr| is zero, or it is non-zero but we did not find the
+ // expected Android packed relocations tags.
+ return start_addr;
+}
+
+void LinuxDumper::LatePostprocessMappings() {
+ for (size_t i = 0; i < mappings_.size(); ++i) {
+ // Only consider exec mappings that indicate a file path was mapped, and
+ // where the ELF header indicates a mapped shared library.
+ MappingInfo* mapping = mappings_[i];
+ if (!(mapping->exec && mapping->name[0] == '/')) {
+ continue;
+ }
+ ElfW(Ehdr) ehdr;
+ if (!GetLoadedElfHeader(mapping->start_addr, &ehdr)) {
+ continue;
+ }
+ if (ehdr.e_type == ET_DYN) {
+ // Compute the effective load bias for this mapped library, and update
+ // the mapping to hold that rather than |start_addr|, at the same time
+ // adjusting |size| to account for the change in |start_addr|. Where
+ // the library does not contain Android packed relocations,
+ // GetEffectiveLoadBias() returns |start_addr| and the mapping entry
+ // is not changed.
+ const uintptr_t load_bias = GetEffectiveLoadBias(&ehdr,
+ mapping->start_addr);
+ mapping->size += mapping->start_addr - load_bias;
+ mapping->start_addr = load_bias;
+ }
+ }
+}
+
+#endif // __ANDROID__
+
+// Get information about the stack, given the stack pointer. We don't try to
+// walk the stack since we might not have all the information needed to do
+// unwind. So we just grab, up to, 32k of stack.
+bool LinuxDumper::GetStackInfo(const void** stack, size_t* stack_len,
+ uintptr_t int_stack_pointer) {
+ // Move the stack pointer to the bottom of the page that it's in.
+ const uintptr_t page_size = getpagesize();
+
+ uint8_t* const stack_pointer =
+ reinterpret_cast<uint8_t*>(int_stack_pointer & ~(page_size - 1));
+
+ // The number of bytes of stack which we try to capture.
+ static const ptrdiff_t kStackToCapture = 32 * 1024;
+
+ const MappingInfo* mapping = FindMapping(stack_pointer);
+ if (!mapping)
+ return false;
+ const ptrdiff_t offset = stack_pointer -
+ reinterpret_cast<uint8_t*>(mapping->start_addr);
+ const ptrdiff_t distance_to_end =
+ static_cast<ptrdiff_t>(mapping->size) - offset;
+ *stack_len = distance_to_end > kStackToCapture ?
+ kStackToCapture : distance_to_end;
+ *stack = stack_pointer;
+ return true;
+}
+
+void LinuxDumper::SanitizeStackCopy(uint8_t* stack_copy, size_t stack_len,
+ uintptr_t stack_pointer,
+ uintptr_t sp_offset) {
+ // We optimize the search for containing mappings in three ways:
+ // 1) We expect that pointers into the stack mapping will be common, so
+ // we cache that address range.
+ // 2) The last referenced mapping is a reasonable predictor for the next
+ // referenced mapping, so we test that first.
+ // 3) We precompute a bitfield based upon bits 32:32-n of the start and
+ // stop addresses, and use that to short circuit any values that can
+ // not be pointers. (n=11)
+ const uintptr_t defaced =
+#if defined(__LP64__)
+ 0x0defaced0defaced;
+#else
+ 0x0defaced;
+#endif
+ // the bitfield length is 2^test_bits long.
+ const unsigned int test_bits = 11;
+ // byte length of the corresponding array.
+ const unsigned int array_size = 1 << (test_bits - 3);
+ const unsigned int array_mask = array_size - 1;
+ // The amount to right shift pointers by. This captures the top bits
+ // on 32 bit architectures. On 64 bit architectures this would be
+ // uninformative so we take the same range of bits.
+ const unsigned int shift = 32 - 11;
+ const MappingInfo* last_hit_mapping = nullptr;
+ const MappingInfo* hit_mapping = nullptr;
+ const MappingInfo* stack_mapping = FindMappingNoBias(stack_pointer);
+ // The magnitude below which integers are considered to be to be
+ // 'small', and not constitute a PII risk. These are included to
+ // avoid eliding useful register values.
+ const ssize_t small_int_magnitude = 4096;
+
+ char could_hit_mapping[array_size];
+ my_memset(could_hit_mapping, 0, array_size);
+
+ // Initialize the bitfield such that if the (pointer >> shift)'th
+ // bit, modulo the bitfield size, is not set then there does not
+ // exist a mapping in mappings_ that would contain that pointer.
+ for (size_t i = 0; i < mappings_.size(); ++i) {
+ if (!mappings_[i]->exec) continue;
+ // For each mapping, work out the (unmodulo'ed) range of bits to
+ // set.
+ uintptr_t start = mappings_[i]->start_addr;
+ uintptr_t end = start + mappings_[i]->size;
+ start >>= shift;
+ end >>= shift;
+ for (size_t bit = start; bit <= end; ++bit) {
+ // Set each bit in the range, applying the modulus.
+ could_hit_mapping[(bit >> 3) & array_mask] |= 1 << (bit & 7);
+ }
+ }
+
+ // Zero memory that is below the current stack pointer.
+ const uintptr_t offset =
+ (sp_offset + sizeof(uintptr_t) - 1) & ~(sizeof(uintptr_t) - 1);
+ if (offset) {
+ my_memset(stack_copy, 0, offset);
+ }
+
+ // Apply sanitization to each complete pointer-aligned word in the
+ // stack.
+ uint8_t* sp;
+ for (sp = stack_copy + offset;
+ sp <= stack_copy + stack_len - sizeof(uintptr_t);
+ sp += sizeof(uintptr_t)) {
+ uintptr_t addr;
+ my_memcpy(&addr, sp, sizeof(uintptr_t));
+ if (static_cast<intptr_t>(addr) <= small_int_magnitude &&
+ static_cast<intptr_t>(addr) >= -small_int_magnitude) {
+ continue;
+ }
+ if (stack_mapping && MappingContainsAddress(*stack_mapping, addr)) {
+ continue;
+ }
+ if (last_hit_mapping && MappingContainsAddress(*last_hit_mapping, addr)) {
+ continue;
+ }
+ uintptr_t test = addr >> shift;
+ if (could_hit_mapping[(test >> 3) & array_mask] & (1 << (test & 7)) &&
+ (hit_mapping = FindMappingNoBias(addr)) != nullptr &&
+ hit_mapping->exec) {
+ last_hit_mapping = hit_mapping;
+ continue;
+ }
+ my_memcpy(sp, &defaced, sizeof(uintptr_t));
+ }
+ // Zero any partial word at the top of the stack, if alignment is
+ // such that that is required.
+ if (sp < stack_copy + stack_len) {
+ my_memset(sp, 0, stack_copy + stack_len - sp);
+ }
+}
+
+bool LinuxDumper::StackHasPointerToMapping(const uint8_t* stack_copy,
+ size_t stack_len,
+ uintptr_t sp_offset,
+ const MappingInfo& mapping) {
+ // Loop over all stack words that would have been on the stack in
+ // the target process (i.e. are word aligned, and at addresses >=
+ // the stack pointer). Regardless of the alignment of |stack_copy|,
+ // the memory starting at |stack_copy| + |offset| represents an
+ // aligned word in the target process.
+ const uintptr_t low_addr = mapping.system_mapping_info.start_addr;
+ const uintptr_t high_addr = mapping.system_mapping_info.end_addr;
+ const uintptr_t offset =
+ (sp_offset + sizeof(uintptr_t) - 1) & ~(sizeof(uintptr_t) - 1);
+
+ for (const uint8_t* sp = stack_copy + offset;
+ sp <= stack_copy + stack_len - sizeof(uintptr_t);
+ sp += sizeof(uintptr_t)) {
+ uintptr_t addr;
+ my_memcpy(&addr, sp, sizeof(uintptr_t));
+ if (low_addr <= addr && addr <= high_addr)
+ return true;
+ }
+ return false;
+}
+
+// Find the mapping which the given memory address falls in.
+const MappingInfo* LinuxDumper::FindMapping(const void* address) const {
+ const uintptr_t addr = (uintptr_t) address;
+
+ for (size_t i = 0; i < mappings_.size(); ++i) {
+ const uintptr_t start = static_cast<uintptr_t>(mappings_[i]->start_addr);
+ if (addr >= start && addr - start < mappings_[i]->size)
+ return mappings_[i];
+ }
+
+ return NULL;
+}
+
+// Find the mapping which the given memory address falls in. Uses the
+// unadjusted mapping address range from the kernel, rather than the
+// biased range.
+const MappingInfo* LinuxDumper::FindMappingNoBias(uintptr_t address) const {
+ for (size_t i = 0; i < mappings_.size(); ++i) {
+ if (address >= mappings_[i]->system_mapping_info.start_addr &&
+ address < mappings_[i]->system_mapping_info.end_addr) {
+ return mappings_[i];
+ }
+ }
+ return NULL;
+}
+
+bool LinuxDumper::HandleDeletedFileInMapping(char* path) const {
+ static const size_t kDeletedSuffixLen = sizeof(kDeletedSuffix) - 1;
+
+ // Check for ' (deleted)' in |path|.
+ // |path| has to be at least as long as "/x (deleted)".
+ const size_t path_len = my_strlen(path);
+ if (path_len < kDeletedSuffixLen + 2)
+ return false;
+ if (my_strncmp(path + path_len - kDeletedSuffixLen, kDeletedSuffix,
+ kDeletedSuffixLen) != 0) {
+ return false;
+ }
+
+ // Check |path| against the /proc/pid/exe 'symlink'.
+ char exe_link[NAME_MAX];
+ if (!BuildProcPath(exe_link, pid_, "exe"))
+ return false;
+ MappingInfo new_mapping = {0};
+ if (!SafeReadLink(exe_link, new_mapping.name))
+ return false;
+ char new_path[PATH_MAX];
+ if (!GetMappingAbsolutePath(new_mapping, new_path))
+ return false;
+ if (my_strcmp(path, new_path) != 0)
+ return false;
+
+ // Check to see if someone actually named their executable 'foo (deleted)'.
+ struct kernel_stat exe_stat;
+ struct kernel_stat new_path_stat;
+ if (sys_stat(exe_link, &exe_stat) == 0 &&
+ sys_stat(new_path, &new_path_stat) == 0 &&
+ exe_stat.st_dev == new_path_stat.st_dev &&
+ exe_stat.st_ino == new_path_stat.st_ino) {
+ return false;
+ }
+
+ my_memcpy(path, exe_link, NAME_MAX);
+ return true;
+}
+
+} // namespace google_breakpad
diff --git a/toolkit/crashreporter/breakpad-client/linux/minidump_writer/linux_dumper.h b/toolkit/crashreporter/breakpad-client/linux/minidump_writer/linux_dumper.h
new file mode 100644
index 0000000000..7155524ffc
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/linux/minidump_writer/linux_dumper.h
@@ -0,0 +1,333 @@
+// 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.
+
+// linux_dumper.h: Define the google_breakpad::LinuxDumper class, which
+// is a base class for extracting information of a crashed process. It
+// was originally a complete implementation using the ptrace API, but
+// has been refactored to allow derived implementations supporting both
+// ptrace and core dump. A portion of the original implementation is now
+// in google_breakpad::LinuxPtraceDumper (see linux_ptrace_dumper.h for
+// details).
+
+#ifndef CLIENT_LINUX_MINIDUMP_WRITER_LINUX_DUMPER_H_
+#define CLIENT_LINUX_MINIDUMP_WRITER_LINUX_DUMPER_H_
+
+#include <assert.h>
+#include <elf.h>
+#if defined(__ANDROID__)
+#include <link.h>
+#endif
+#include <linux/limits.h>
+#include <stdint.h>
+#include <sys/types.h>
+#include <sys/user.h>
+
+#include <vector>
+
+#include "linux/dump_writer_common/mapping_info.h"
+#include "linux/dump_writer_common/thread_info.h"
+#include "common/linux/file_id.h"
+#include "common/memory_allocator.h"
+#include "google_breakpad/common/minidump_format.h"
+
+namespace google_breakpad {
+
+// Typedef for our parsing of the auxv variables in /proc/pid/auxv.
+#if defined(__i386) || defined(__ARM_EABI__) || \
+ (defined(__mips__) && _MIPS_SIM == _ABIO32)
+typedef Elf32_auxv_t elf_aux_entry;
+#elif defined(__x86_64) || defined(__aarch64__) || \
+ (defined(__mips__) && _MIPS_SIM != _ABIO32)
+typedef Elf64_auxv_t elf_aux_entry;
+#endif
+
+typedef __typeof__(((elf_aux_entry*) 0)->a_un.a_val) elf_aux_val_t;
+
+// When we find the VDSO mapping in the process's address space, this
+// is the name we use for it when writing it to the minidump.
+// This should always be less than NAME_MAX!
+const char kLinuxGateLibraryName[] = "linux-gate.so";
+
+class LinuxDumper {
+ public:
+ // The |root_prefix| is prepended to mapping paths before opening them, which
+ // is useful if the crash originates from a chroot.
+ explicit LinuxDumper(pid_t pid, const char* root_prefix = "");
+
+ virtual ~LinuxDumper();
+
+ // Parse the data for |threads| and |mappings|.
+ virtual bool Init();
+
+ // Take any actions that could not be taken in Init(). LateInit() is
+ // called after all other caller's initialization is complete, and in
+ // particular after it has called ThreadsSuspend(), so that ptrace is
+ // available.
+ virtual bool LateInit();
+
+ // Return true if the dumper performs a post-mortem dump.
+ virtual bool IsPostMortem() const = 0;
+
+ // Suspend/resume all threads in the given process.
+ virtual bool ThreadsSuspend() = 0;
+ virtual bool ThreadsResume() = 0;
+
+ // Read information about the |index|-th thread of |threads_|.
+ // Returns true on success. One must have called |ThreadsSuspend| first.
+ virtual bool GetThreadInfoByIndex(size_t index, ThreadInfo* info) = 0;
+
+ // Read the name ofthe |index|-th thread of |threads_|.
+ // Returns true on success. One must have called |ThreadsSuspend| first.
+ virtual bool GetThreadNameByIndex(size_t index, char* name, size_t size) = 0;
+
+ size_t GetMainThreadIndex() const {
+ for (size_t i = 0; i < threads_.size(); ++i) {
+ if (threads_[i] == pid_) return i;
+ }
+ return -1u;
+ }
+
+ // These are only valid after a call to |Init|.
+ const wasteful_vector<pid_t> &threads() { return threads_; }
+ const wasteful_vector<MappingInfo*> &mappings() { return mappings_; }
+ const MappingInfo* FindMapping(const void* address) const;
+ // Find the mapping which the given memory address falls in. Unlike
+ // FindMapping, this method uses the unadjusted mapping address
+ // ranges from the kernel, rather than the ranges that have had the
+ // load bias applied.
+ const MappingInfo* FindMappingNoBias(uintptr_t address) const;
+ const wasteful_vector<elf_aux_val_t>& auxv() { return auxv_; }
+
+ // Find a block of memory to take as the stack given the top of stack pointer.
+ // stack: (output) the lowest address in the memory area
+ // stack_len: (output) the length of the memory area
+ // stack_top: the current top of the stack
+ bool GetStackInfo(const void** stack, size_t* stack_len, uintptr_t stack_top);
+
+ // Sanitize a copy of the stack by overwriting words that are not
+ // pointers with a sentinel (0x0defaced).
+ // stack_copy: a copy of the stack to sanitize. |stack_copy| might
+ // not be word aligned, but it represents word aligned
+ // data copied from another location.
+ // stack_len: the length of the allocation pointed to by |stack_copy|.
+ // stack_pointer: the address of the stack pointer (used to locate
+ // the stack mapping, as an optimization).
+ // sp_offset: the offset relative to stack_copy that reflects the
+ // current value of the stack pointer.
+ void SanitizeStackCopy(uint8_t* stack_copy, size_t stack_len,
+ uintptr_t stack_pointer, uintptr_t sp_offset);
+
+ // Test whether |stack_copy| contains a pointer-aligned word that
+ // could be an address within a given mapping.
+ // stack_copy: a copy of the stack to check. |stack_copy| might
+ // not be word aligned, but it represents word aligned
+ // data copied from another location.
+ // stack_len: the length of the allocation pointed to by |stack_copy|.
+ // sp_offset: the offset relative to stack_copy that reflects the
+ // current value of the stack pointer.
+ // mapping: the mapping against which to test stack words.
+ bool StackHasPointerToMapping(const uint8_t* stack_copy, size_t stack_len,
+ uintptr_t sp_offset,
+ const MappingInfo& mapping);
+
+ PageAllocator* allocator() { return &allocator_; }
+
+ // Copy content of |length| bytes from a given process |child|,
+ // starting from |src|, into |dest|. Returns true on success.
+ virtual bool CopyFromProcess(void* dest, pid_t child, const void* src,
+ size_t length) = 0;
+
+ // Builds a proc path for a certain pid for a node (/proc/<pid>/<node>).
+ // |path| is a character array of at least NAME_MAX bytes to return the
+ // result.|node| is the final node without any slashes. Returns true on
+ // success.
+ virtual bool BuildProcPath(char* path, pid_t pid, const char* node) const = 0;
+
+ // Generate a File ID from the .text section of a mapped entry.
+ // If not a member, mapping_id is ignored. This method can also manipulate the
+ // |mapping|.name to truncate "(deleted)" from the file name if necessary.
+ bool ElfFileIdentifierForMapping(const MappingInfo& mapping,
+ bool member,
+ unsigned int mapping_id,
+ wasteful_vector<uint8_t>& identifier);
+
+ void SetCrashInfoFromSigInfo(const siginfo_t& siginfo);
+
+ uintptr_t crash_address() const { return crash_address_; }
+ void set_crash_address(uintptr_t crash_address) {
+ crash_address_ = crash_address;
+ }
+
+ int crash_signal() const { return crash_signal_; }
+ void set_crash_signal(int crash_signal) { crash_signal_ = crash_signal; }
+ const char* GetCrashSignalString() const;
+
+ void set_crash_signal_code(int code) { crash_signal_code_ = code; }
+ int crash_signal_code() const { return crash_signal_code_; }
+
+ void set_crash_exception_info(const std::vector<uint64_t>& exception_info) {
+ assert(exception_info.size() <= MD_EXCEPTION_MAXIMUM_PARAMETERS);
+ crash_exception_info_ = exception_info;
+ }
+ const std::vector<uint64_t>& crash_exception_info() const {
+ return crash_exception_info_;
+ }
+
+ pid_t pid() const { return pid_; }
+ pid_t crash_thread() const { return crash_thread_; }
+ void set_crash_thread(pid_t crash_thread) { crash_thread_ = crash_thread; }
+
+ // Concatenates the |root_prefix_| and |mapping| path. Writes into |path| and
+ // returns true unless the string is too long.
+ bool GetMappingAbsolutePath(const MappingInfo& mapping,
+ char path[PATH_MAX]) const;
+
+ // Extracts the effective path and file name of from |mapping|. In most cases
+ // the effective name/path are just the mapping's path and basename. In some
+ // other cases, however, a library can be mapped from an archive (e.g., when
+ // loading .so libs from an apk on Android) and this method is able to
+ // reconstruct the original file name.
+ void GetMappingEffectiveNameAndPath(const MappingInfo& mapping,
+ char* file_path,
+ size_t file_path_size,
+ char* file_name,
+ size_t file_name_size);
+
+ protected:
+ bool ReadAuxv();
+
+ virtual bool EnumerateMappings();
+
+ virtual bool EnumerateThreads() = 0;
+
+ // For the case where a running program has been deleted, it'll show up in
+ // /proc/pid/maps as "/path/to/program (deleted)". If this is the case, then
+ // see if '/path/to/program (deleted)' matches /proc/pid/exe and return
+ // /proc/pid/exe in |path| so ELF identifier generation works correctly. This
+ // also checks to see if '/path/to/program (deleted)' exists, so it does not
+ // get fooled by a poorly named binary.
+ // For programs that don't end with ' (deleted)', this is a no-op.
+ // This assumes |path| is a buffer with length NAME_MAX.
+ // Returns true if |path| is modified.
+ bool HandleDeletedFileInMapping(char* path) const;
+
+ // ID of the crashed process.
+ const pid_t pid_;
+
+ // Path of the root directory to which mapping paths are relative.
+ const char* const root_prefix_;
+
+ // Virtual address at which the process crashed.
+ uintptr_t crash_address_;
+
+ // Signal that terminated the crashed process.
+ int crash_signal_;
+
+ // The code associated with |crash_signal_|.
+ int crash_signal_code_;
+
+ // The additional fields associated with |crash_signal_|.
+ std::vector<uint64_t> crash_exception_info_;
+
+ // ID of the crashed thread.
+ pid_t crash_thread_;
+
+ mutable PageAllocator allocator_;
+
+ // IDs of all the threads.
+ wasteful_vector<pid_t> threads_;
+
+ // Info from /proc/<pid>/maps.
+ wasteful_vector<MappingInfo*> mappings_;
+
+ // Info from /proc/<pid>/auxv
+ wasteful_vector<elf_aux_val_t> auxv_;
+
+private:
+ bool IsIPCSharedMemorySegment(const char* name);
+
+#if defined(__ANDROID__)
+ // Android M and later support packed ELF relocations in shared libraries.
+ // Packing relocations changes the vaddr of the LOAD segments, such that
+ // the effective load bias is no longer the same as the start address of
+ // the memory mapping containing the executable parts of the library. The
+ // packing is applied to the stripped library run on the target, but not to
+ // any other library, and in particular not to the library used to generate
+ // breakpad symbols. As a result, we need to adjust the |start_addr| for
+ // any mapping that results from a shared library that contains Android
+ // packed relocations, so that it properly represents the effective library
+ // load bias. The following functions support this adjustment.
+
+ // Check that a given mapping at |start_addr| is for an ELF shared library.
+ // If it is, place the ELF header in |ehdr| and return true.
+ // The first LOAD segment in an ELF shared library has offset zero, so the
+ // ELF file header is at the start of this map entry, and in already mapped
+ // memory.
+ bool GetLoadedElfHeader(uintptr_t start_addr, ElfW(Ehdr)* ehdr);
+
+ // For the ELF file mapped at |start_addr|, iterate ELF program headers to
+ // find the min vaddr of all program header LOAD segments, the vaddr for
+ // the DYNAMIC segment, and a count of DYNAMIC entries. Return values in
+ // |min_vaddr_ptr|, |dyn_vaddr_ptr|, and |dyn_count_ptr|.
+ // The program header table is also in already mapped memory.
+ void ParseLoadedElfProgramHeaders(ElfW(Ehdr)* ehdr,
+ uintptr_t start_addr,
+ uintptr_t* min_vaddr_ptr,
+ uintptr_t* dyn_vaddr_ptr,
+ size_t* dyn_count_ptr);
+
+ // Search the DYNAMIC tags for the ELF file with the given |load_bias|, and
+ // return true if the tags indicate that the file contains Android packed
+ // relocations. Dynamic tags are found at |dyn_vaddr| past the |load_bias|.
+ bool HasAndroidPackedRelocations(uintptr_t load_bias,
+ uintptr_t dyn_vaddr,
+ size_t dyn_count);
+
+ // If the ELF file mapped at |start_addr| contained Android packed
+ // relocations, return the load bias that the system linker (or Chromium
+ // crazy linker) will have used. If the file did not contain Android
+ // packed relocations, returns |start_addr|, indicating that no adjustment
+ // is necessary.
+ // The effective load bias is |start_addr| adjusted downwards by the
+ // min vaddr in the library LOAD segments.
+ uintptr_t GetEffectiveLoadBias(ElfW(Ehdr)* ehdr, uintptr_t start_addr);
+
+ // Called from LateInit(). Iterates |mappings_| and rewrites the |start_addr|
+ // field of any that represent ELF shared libraries with Android packed
+ // relocations, so that |start_addr| is the load bias that the system linker
+ // (or Chromium crazy linker) used. This value matches the addresses produced
+ // when the non-relocation-packed library is used for breakpad symbol
+ // generation.
+ void LatePostprocessMappings();
+#endif // __ANDROID__
+};
+
+} // namespace google_breakpad
+
+#endif // CLIENT_LINUX_HANDLER_LINUX_DUMPER_H_
diff --git a/toolkit/crashreporter/breakpad-client/linux/minidump_writer/linux_dumper_unittest_helper.cc b/toolkit/crashreporter/breakpad-client/linux/minidump_writer/linux_dumper_unittest_helper.cc
new file mode 100644
index 0000000000..3ad48e5015
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/linux/minidump_writer/linux_dumper_unittest_helper.cc
@@ -0,0 +1,95 @@
+// 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.
+//
+// Helper program for the linux_dumper class, which creates a bunch of
+// threads. The first word of each thread's stack is set to the thread
+// id.
+
+#include <pthread.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/syscall.h>
+#include <unistd.h>
+
+#include "common/scoped_ptr.h"
+#include "third_party/lss/linux_syscall_support.h"
+
+#if defined(__ARM_EABI__)
+#define TID_PTR_REGISTER "r3"
+#elif defined(__aarch64__)
+#define TID_PTR_REGISTER "x3"
+#elif defined(__i386)
+#define TID_PTR_REGISTER "ecx"
+#elif defined(__x86_64)
+#define TID_PTR_REGISTER "rcx"
+#elif defined(__mips__)
+#define TID_PTR_REGISTER "$1"
+#else
+#error This test has not been ported to this platform.
+#endif
+
+void *thread_function(void *data) {
+ int pipefd = *static_cast<int *>(data);
+ volatile pid_t* thread_id = new pid_t;
+ *thread_id = syscall(__NR_gettid);
+ // Signal parent that a thread has started.
+ uint8_t byte = 1;
+ if (write(pipefd, &byte, sizeof(byte)) != sizeof(byte)) {
+ perror("ERROR: parent notification failed");
+ return NULL;
+ }
+ register volatile pid_t *thread_id_ptr asm(TID_PTR_REGISTER) = thread_id;
+ while (true)
+ asm volatile ("" : : "r" (thread_id_ptr));
+ return NULL;
+}
+
+int main(int argc, char *argv[]) {
+ if (argc < 3) {
+ fprintf(stderr,
+ "usage: linux_dumper_unittest_helper <pipe fd> <# of threads>\n");
+ return 1;
+ }
+ int pipefd = atoi(argv[1]);
+ int num_threads = atoi(argv[2]);
+ if (num_threads < 1) {
+ fprintf(stderr, "ERROR: number of threads is 0");
+ return 1;
+ }
+ google_breakpad::scoped_array<pthread_t> threads(new pthread_t[num_threads]);
+ pthread_attr_t thread_attributes;
+ pthread_attr_init(&thread_attributes);
+ pthread_attr_setdetachstate(&thread_attributes, PTHREAD_CREATE_DETACHED);
+ for (int i = 1; i < num_threads; i++) {
+ pthread_create(&threads[i], &thread_attributes, &thread_function, &pipefd);
+ }
+ thread_function(&pipefd);
+ return 0;
+}
diff --git a/toolkit/crashreporter/breakpad-client/linux/minidump_writer/linux_ptrace_dumper.cc b/toolkit/crashreporter/breakpad-client/linux/minidump_writer/linux_ptrace_dumper.cc
new file mode 100644
index 0000000000..6ed70eeb61
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/linux/minidump_writer/linux_ptrace_dumper.cc
@@ -0,0 +1,403 @@
+// 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.
+
+// linux_ptrace_dumper.cc: Implement google_breakpad::LinuxPtraceDumper.
+// See linux_ptrace_dumper.h for detals.
+// This class was originally splitted from google_breakpad::LinuxDumper.
+
+// This code deals with the mechanics of getting information about a crashed
+// process. Since this code may run in a compromised address space, the same
+// rules apply as detailed at the top of minidump_writer.h: no libc calls and
+// use the alternative allocator.
+
+#include "linux/minidump_writer/linux_ptrace_dumper.h"
+
+#include <asm/ptrace.h>
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ptrace.h>
+#include <sys/uio.h>
+#include <sys/wait.h>
+
+#if defined(__i386)
+#include <cpuid.h>
+#endif
+
+#include "linux/minidump_writer/directory_reader.h"
+#include "linux/minidump_writer/line_reader.h"
+#include "common/linux/linux_libc_support.h"
+#include "third_party/lss/linux_syscall_support.h"
+
+// Suspends a thread by attaching to it.
+static bool SuspendThread(pid_t pid) {
+ // This may fail if the thread has just died or debugged.
+ errno = 0;
+ if (sys_ptrace(PTRACE_ATTACH, pid, NULL, NULL) != 0 &&
+ errno != 0) {
+ return false;
+ }
+ while (sys_waitpid(pid, NULL, __WALL) < 0) {
+ if (errno != EINTR) {
+ sys_ptrace(PTRACE_DETACH, pid, NULL, NULL);
+ return false;
+ }
+ }
+#if defined(__i386) || defined(__x86_64)
+ // On x86, the stack pointer is NULL or -1, when executing trusted code in
+ // the seccomp sandbox. Not only does this cause difficulties down the line
+ // when trying to dump the thread's stack, it also results in the minidumps
+ // containing information about the trusted threads. This information is
+ // generally completely meaningless and just pollutes the minidumps.
+ // We thus test the stack pointer and exclude any threads that are part of
+ // the seccomp sandbox's trusted code.
+ user_regs_struct regs;
+ if (sys_ptrace(PTRACE_GETREGS, pid, NULL, &regs) == -1 ||
+#if defined(__i386)
+ !regs.esp
+#elif defined(__x86_64)
+ !regs.rsp
+#endif
+ ) {
+ sys_ptrace(PTRACE_DETACH, pid, NULL, NULL);
+ return false;
+ }
+#endif
+ return true;
+}
+
+// Resumes a thread by detaching from it.
+static bool ResumeThread(pid_t pid) {
+ return sys_ptrace(PTRACE_DETACH, pid, NULL, NULL) >= 0;
+}
+
+namespace google_breakpad {
+
+LinuxPtraceDumper::LinuxPtraceDumper(pid_t pid)
+ : LinuxDumper(pid),
+ threads_suspended_(false) {
+}
+
+bool LinuxPtraceDumper::BuildProcPath(char* path, pid_t pid,
+ const char* node) const {
+ if (!path || !node || pid <= 0)
+ return false;
+
+ size_t node_len = my_strlen(node);
+ if (node_len == 0)
+ return false;
+
+ const unsigned pid_len = my_uint_len(pid);
+ const size_t total_length = 6 + pid_len + 1 + node_len;
+ if (total_length >= NAME_MAX)
+ return false;
+
+ my_memcpy(path, "/proc/", 6);
+ my_uitos(path + 6, pid, pid_len);
+ path[6 + pid_len] = '/';
+ my_memcpy(path + 6 + pid_len + 1, node, node_len);
+ path[total_length] = '\0';
+ return true;
+}
+
+bool LinuxPtraceDumper::CopyFromProcess(void* dest, pid_t child,
+ const void* src, size_t length) {
+ unsigned long tmp = 55;
+ size_t done = 0;
+ static const size_t word_size = sizeof(tmp);
+ uint8_t* const local = (uint8_t*) dest;
+ uint8_t* const remote = (uint8_t*) src;
+
+ while (done < length) {
+ const size_t l = (length - done > word_size) ? word_size : (length - done);
+ if (sys_ptrace(PTRACE_PEEKDATA, child, remote + done, &tmp) == -1) {
+ tmp = 0;
+ }
+ my_memcpy(local + done, &tmp, l);
+ done += l;
+ }
+ return true;
+}
+
+bool LinuxPtraceDumper::ReadRegisterSet(ThreadInfo* info, pid_t tid)
+{
+#ifdef PTRACE_GETREGSET
+ struct iovec io;
+ info->GetGeneralPurposeRegisters(&io.iov_base, &io.iov_len);
+ if (sys_ptrace(PTRACE_GETREGSET, tid, (void*)NT_PRSTATUS, (void*)&io) == -1) {
+ return false;
+ }
+
+ info->GetFloatingPointRegisters(&io.iov_base, &io.iov_len);
+ if (sys_ptrace(PTRACE_GETREGSET, tid, (void*)NT_FPREGSET, (void*)&io) == -1) {
+ return false;
+ }
+ return true;
+#else
+ return false;
+#endif
+}
+
+bool LinuxPtraceDumper::ReadRegisters(ThreadInfo* info, pid_t tid) {
+#ifdef PTRACE_GETREGS
+ void* gp_addr;
+ info->GetGeneralPurposeRegisters(&gp_addr, NULL);
+ if (sys_ptrace(PTRACE_GETREGS, tid, NULL, gp_addr) == -1) {
+ return false;
+ }
+
+#if !(defined(__ANDROID__) && defined(__ARM_EABI__))
+ // When running an arm build on an arm64 device, attempting to get the
+ // floating point registers fails. On Android, the floating point registers
+ // aren't written to the cpu context anyway, so just don't get them here.
+ // See http://crbug.com/508324
+ void* fp_addr;
+ info->GetFloatingPointRegisters(&fp_addr, NULL);
+ if (sys_ptrace(PTRACE_GETFPREGS, tid, NULL, fp_addr) == -1) {
+ return false;
+ }
+#endif // !(defined(__ANDROID__) && defined(__ARM_EABI__))
+ return true;
+#else // PTRACE_GETREGS
+ return false;
+#endif
+}
+
+// Read thread info from /proc/$pid/status.
+// Fill out the |tgid|, |ppid| and |pid| members of |info|. If unavailable,
+// these members are set to -1. Returns true iff all three members are
+// available.
+bool LinuxPtraceDumper::GetThreadInfoByIndex(size_t index, ThreadInfo* info) {
+ if (index >= threads_.size())
+ return false;
+
+ pid_t tid = threads_[index];
+
+ assert(info != NULL);
+ char status_path[NAME_MAX];
+ if (!BuildProcPath(status_path, tid, "status"))
+ return false;
+
+ const int fd = sys_open(status_path, O_RDONLY, 0);
+ if (fd < 0)
+ return false;
+
+ LineReader* const line_reader = new(allocator_) LineReader(fd);
+ const char* line;
+ unsigned line_len;
+
+ info->ppid = info->tgid = -1;
+
+ while (line_reader->GetNextLine(&line, &line_len)) {
+ if (my_strncmp("Tgid:\t", line, 6) == 0) {
+ my_strtoui(&info->tgid, line + 6);
+ } else if (my_strncmp("PPid:\t", line, 6) == 0) {
+ my_strtoui(&info->ppid, line + 6);
+ }
+
+ line_reader->PopLine(line_len);
+ }
+ sys_close(fd);
+
+ if (info->ppid == -1 || info->tgid == -1)
+ return false;
+
+ if (!ReadRegisterSet(info, tid)) {
+ if (!ReadRegisters(info, tid)) {
+ return false;
+ }
+ }
+
+#if defined(__i386)
+#if !defined(bit_FXSAVE) // e.g. Clang
+#define bit_FXSAVE bit_FXSR
+#endif
+ // Detect if the CPU supports the FXSAVE/FXRSTOR instructions
+ int eax, ebx, ecx, edx;
+ __cpuid(1, eax, ebx, ecx, edx);
+ if (edx & bit_FXSAVE) {
+ if (sys_ptrace(PTRACE_GETFPXREGS, tid, NULL, &info->fpxregs) == -1) {
+ return false;
+ }
+ } else {
+ memset(&info->fpxregs, 0, sizeof(info->fpxregs));
+ }
+#endif // defined(__i386)
+
+#if defined(__i386) || defined(__x86_64)
+ for (unsigned i = 0; i < ThreadInfo::kNumDebugRegisters; ++i) {
+ if (sys_ptrace(
+ PTRACE_PEEKUSER, tid,
+ reinterpret_cast<void*> (offsetof(struct user,
+ u_debugreg[0]) + i *
+ sizeof(debugreg_t)),
+ &info->dregs[i]) == -1) {
+ return false;
+ }
+ }
+#endif
+
+#if defined(__mips__)
+ sys_ptrace(PTRACE_PEEKUSER, tid,
+ reinterpret_cast<void*>(PC), &info->mcontext.pc);
+ sys_ptrace(PTRACE_PEEKUSER, tid,
+ reinterpret_cast<void*>(DSP_BASE), &info->mcontext.hi1);
+ sys_ptrace(PTRACE_PEEKUSER, tid,
+ reinterpret_cast<void*>(DSP_BASE + 1), &info->mcontext.lo1);
+ sys_ptrace(PTRACE_PEEKUSER, tid,
+ reinterpret_cast<void*>(DSP_BASE + 2), &info->mcontext.hi2);
+ sys_ptrace(PTRACE_PEEKUSER, tid,
+ reinterpret_cast<void*>(DSP_BASE + 3), &info->mcontext.lo2);
+ sys_ptrace(PTRACE_PEEKUSER, tid,
+ reinterpret_cast<void*>(DSP_BASE + 4), &info->mcontext.hi3);
+ sys_ptrace(PTRACE_PEEKUSER, tid,
+ reinterpret_cast<void*>(DSP_BASE + 5), &info->mcontext.lo3);
+ sys_ptrace(PTRACE_PEEKUSER, tid,
+ reinterpret_cast<void*>(DSP_CONTROL), &info->mcontext.dsp);
+#endif
+
+ const uint8_t* stack_pointer;
+#if defined(__i386)
+ my_memcpy(&stack_pointer, &info->regs.esp, sizeof(info->regs.esp));
+#elif defined(__x86_64)
+ my_memcpy(&stack_pointer, &info->regs.rsp, sizeof(info->regs.rsp));
+#elif defined(__ARM_EABI__)
+ my_memcpy(&stack_pointer, &info->regs.ARM_sp, sizeof(info->regs.ARM_sp));
+#elif defined(__aarch64__)
+ my_memcpy(&stack_pointer, &info->regs.sp, sizeof(info->regs.sp));
+#elif defined(__mips__)
+ stack_pointer =
+ reinterpret_cast<uint8_t*>(info->mcontext.gregs[MD_CONTEXT_MIPS_REG_SP]);
+#else
+#error "This code hasn't been ported to your platform yet."
+#endif
+ info->stack_pointer = reinterpret_cast<uintptr_t>(stack_pointer);
+
+ return true;
+}
+
+bool LinuxPtraceDumper::GetThreadNameByIndex(size_t index, char* name,
+ size_t size) {
+ if (index >= threads_.size())
+ return false;
+
+ pid_t tid = threads_[index];
+
+ assert(name != NULL);
+ char path[NAME_MAX];
+
+ // Read the thread name (aka comm entry in /proc)
+ if (!BuildProcPath(path, tid, "comm"))
+ return false;
+
+ const int fd = sys_open(path, O_RDONLY, 0);
+ if (fd < 0)
+ return false;
+
+ const int len = sys_read(fd, name, size);
+ if (len > 0)
+ name[len - 1] = '\0'; // Get rid of the newline
+
+ sys_close(fd);
+
+ return len > 0;
+}
+
+bool LinuxPtraceDumper::IsPostMortem() const {
+ return false;
+}
+
+bool LinuxPtraceDumper::ThreadsSuspend() {
+ if (threads_suspended_)
+ return true;
+ for (size_t i = 0; i < threads_.size(); ++i) {
+ if (!SuspendThread(threads_[i])) {
+ // If the thread either disappeared before we could attach to it, or if
+ // it was part of the seccomp sandbox's trusted code, it is OK to
+ // silently drop it from the minidump.
+ if (i < threads_.size() - 1) {
+ my_memmove(&threads_[i], &threads_[i + 1],
+ (threads_.size() - i - 1) * sizeof(threads_[i]));
+ }
+ threads_.resize(threads_.size() - 1);
+ --i;
+ }
+ }
+ threads_suspended_ = true;
+ return !threads_.empty();
+}
+
+bool LinuxPtraceDumper::ThreadsResume() {
+ if (!threads_suspended_)
+ return false;
+ bool good = true;
+ for (size_t i = 0; i < threads_.size(); ++i)
+ good &= ResumeThread(threads_[i]);
+ threads_suspended_ = false;
+ return good;
+}
+
+// Parse /proc/$pid/task to list all the threads of the process identified by
+// pid.
+bool LinuxPtraceDumper::EnumerateThreads() {
+ char task_path[NAME_MAX];
+ if (!BuildProcPath(task_path, pid_, "task"))
+ return false;
+
+ const int fd = sys_open(task_path, O_RDONLY | O_DIRECTORY, 0);
+ if (fd < 0)
+ return false;
+ DirectoryReader* dir_reader = new(allocator_) DirectoryReader(fd);
+
+ // The directory may contain duplicate entries which we filter by assuming
+ // that they are consecutive.
+ int last_tid = -1;
+ const char* dent_name;
+ while (dir_reader->GetNextEntry(&dent_name)) {
+ if (my_strcmp(dent_name, ".") &&
+ my_strcmp(dent_name, "..")) {
+ int tid = 0;
+ if (my_strtoui(&tid, dent_name) &&
+ last_tid != tid) {
+ last_tid = tid;
+ threads_.push_back(tid);
+ }
+ }
+ dir_reader->PopEntry();
+ }
+
+ sys_close(fd);
+ return true;
+}
+
+} // namespace google_breakpad
diff --git a/toolkit/crashreporter/breakpad-client/linux/minidump_writer/linux_ptrace_dumper.h b/toolkit/crashreporter/breakpad-client/linux/minidump_writer/linux_ptrace_dumper.h
new file mode 100644
index 0000000000..576098c349
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/linux/minidump_writer/linux_ptrace_dumper.h
@@ -0,0 +1,106 @@
+// 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.
+
+// linux_ptrace_dumper.h: Define the google_breakpad::LinuxPtraceDumper
+// class, which is derived from google_breakpad::LinuxDumper to extract
+// information from a crashed process via ptrace.
+// This class was originally splitted from google_breakpad::LinuxDumper.
+
+#ifndef CLIENT_LINUX_MINIDUMP_WRITER_LINUX_PTRACE_DUMPER_H_
+#define CLIENT_LINUX_MINIDUMP_WRITER_LINUX_PTRACE_DUMPER_H_
+
+#include "linux/minidump_writer/linux_dumper.h"
+
+namespace google_breakpad {
+
+class LinuxPtraceDumper : public LinuxDumper {
+ public:
+ // Constructs a dumper for extracting information of a given process
+ // with a process ID of |pid|.
+ explicit LinuxPtraceDumper(pid_t pid);
+
+ // Implements LinuxDumper::BuildProcPath().
+ // Builds a proc path for a certain pid for a node (/proc/<pid>/<node>).
+ // |path| is a character array of at least NAME_MAX bytes to return the
+ // result. |node| is the final node without any slashes. Returns true on
+ // success.
+ virtual bool BuildProcPath(char* path, pid_t pid, const char* node) const;
+
+ // Implements LinuxDumper::CopyFromProcess().
+ // Copies content of |length| bytes from a given process |child|,
+ // starting from |src|, into |dest|. This method uses ptrace to extract
+ // the content from the target process. Always returns true.
+ virtual bool CopyFromProcess(void* dest, pid_t child, const void* src,
+ size_t length);
+
+ // Implements LinuxDumper::GetThreadInfoByIndex().
+ // Reads information about the |index|-th thread of |threads_|.
+ // Returns true on success. One must have called |ThreadsSuspend| first.
+ virtual bool GetThreadInfoByIndex(size_t index, ThreadInfo* info);
+
+ // Implements LinuxDumper::GetThreadNameByIndex().
+ // Reads the name of the |index|-th thread of |threads_|.
+ // Returns true on success. One must have called |ThreadsSuspend| first.
+ virtual bool GetThreadNameByIndex(size_t index, char* name, size_t size);
+
+ // Implements LinuxDumper::IsPostMortem().
+ // Always returns false to indicate this dumper performs a dump of
+ // a crashed process via ptrace.
+ virtual bool IsPostMortem() const;
+
+ // Implements LinuxDumper::ThreadsSuspend().
+ // Suspends all threads in the given process. Returns true on success.
+ virtual bool ThreadsSuspend();
+
+ // Implements LinuxDumper::ThreadsResume().
+ // Resumes all threads in the given process. Returns true on success.
+ virtual bool ThreadsResume();
+
+ protected:
+ // Implements LinuxDumper::EnumerateThreads().
+ // Enumerates all threads of the given process into |threads_|.
+ virtual bool EnumerateThreads();
+
+ private:
+ // Set to true if all threads of the crashed process are suspended.
+ bool threads_suspended_;
+
+ // Read the tracee's registers on kernel with PTRACE_GETREGSET support.
+ // Returns false if PTRACE_GETREGSET is not defined.
+ // Returns true on success.
+ bool ReadRegisterSet(ThreadInfo* info, pid_t tid);
+
+ // Read the tracee's registers on kernel with PTRACE_GETREGS support.
+ // Returns true on success.
+ bool ReadRegisters(ThreadInfo* info, pid_t tid);
+};
+
+} // namespace google_breakpad
+
+#endif // CLIENT_LINUX_HANDLER_LINUX_PTRACE_DUMPER_H_
diff --git a/toolkit/crashreporter/breakpad-client/linux/minidump_writer/linux_ptrace_dumper_unittest.cc b/toolkit/crashreporter/breakpad-client/linux/minidump_writer/linux_ptrace_dumper_unittest.cc
new file mode 100644
index 0000000000..79d26a1e31
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/linux/minidump_writer/linux_ptrace_dumper_unittest.cc
@@ -0,0 +1,580 @@
+// 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.
+
+// linux_ptrace_dumper_unittest.cc:
+// Unit tests for google_breakpad::LinuxPtraceDumper.
+//
+// This file was renamed from linux_dumper_unittest.cc and modified due
+// to LinuxDumper being splitted into two classes.
+
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <poll.h>
+#include <unistd.h>
+#include <signal.h>
+#include <stdint.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <sys/prctl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <string>
+
+#include "breakpad_googletest_includes.h"
+#include "linux/minidump_writer/linux_ptrace_dumper.h"
+#include "linux/minidump_writer/minidump_writer_unittest_utils.h"
+#include "common/linux/eintr_wrapper.h"
+#include "common/linux/file_id.h"
+#include "common/linux/ignore_ret.h"
+#include "common/linux/safe_readlink.h"
+#include "common/memory_allocator.h"
+#include "common/using_std_string.h"
+
+#ifndef PR_SET_PTRACER
+#define PR_SET_PTRACER 0x59616d61
+#endif
+
+using namespace google_breakpad;
+
+namespace {
+
+pid_t SetupChildProcess(int number_of_threads) {
+ char kNumberOfThreadsArgument[2];
+ sprintf(kNumberOfThreadsArgument, "%d", number_of_threads);
+
+ int fds[2];
+ EXPECT_NE(-1, pipe(fds));
+
+ pid_t child_pid = fork();
+ if (child_pid == 0) {
+ // In child process.
+ close(fds[0]);
+
+ string helper_path(GetHelperBinary());
+ if (helper_path.empty()) {
+ fprintf(stderr, "Couldn't find helper binary\n");
+ _exit(1);
+ }
+
+ // Pass the pipe fd and the number of threads as arguments.
+ char pipe_fd_string[8];
+ sprintf(pipe_fd_string, "%d", fds[1]);
+ execl(helper_path.c_str(),
+ "linux_dumper_unittest_helper",
+ pipe_fd_string,
+ kNumberOfThreadsArgument,
+ NULL);
+ // Kill if we get here.
+ printf("Errno from exec: %d", errno);
+ std::string err_str = "Exec of " + helper_path + " failed";
+ perror(err_str.c_str());
+ _exit(1);
+ }
+ close(fds[1]);
+
+ // Wait for all child threads to indicate that they have started
+ for (int threads = 0; threads < number_of_threads; threads++) {
+ struct pollfd pfd;
+ memset(&pfd, 0, sizeof(pfd));
+ pfd.fd = fds[0];
+ pfd.events = POLLIN | POLLERR;
+
+ const int r = HANDLE_EINTR(poll(&pfd, 1, 1000));
+ EXPECT_EQ(1, r);
+ EXPECT_TRUE(pfd.revents & POLLIN);
+ uint8_t junk;
+ EXPECT_EQ(read(fds[0], &junk, sizeof(junk)),
+ static_cast<ssize_t>(sizeof(junk)));
+ }
+ close(fds[0]);
+
+ // There is a race here because we may stop a child thread before
+ // it is actually running the busy loop. Empirically this sleep
+ // is sufficient to avoid the race.
+ usleep(100000);
+ return child_pid;
+}
+
+typedef wasteful_vector<uint8_t> id_vector;
+typedef testing::Test LinuxPtraceDumperTest;
+
+/* Fixture for running tests in a child process. */
+class LinuxPtraceDumperChildTest : public testing::Test {
+ protected:
+ virtual void SetUp() {
+ child_pid_ = fork();
+#ifndef __ANDROID__
+ prctl(PR_SET_PTRACER, child_pid_);
+#endif
+ }
+
+ /* Gtest is calling TestBody from this class, which sets up a child
+ * process in which the RealTestBody virtual member is called.
+ * As such, TestBody is not supposed to be overridden in derived classes.
+ */
+ virtual void TestBody() /* final */ {
+ if (child_pid_ == 0) {
+ // child process
+ RealTestBody();
+ _exit(HasFatalFailure() ? kFatalFailure :
+ (HasNonfatalFailure() ? kNonFatalFailure : 0));
+ }
+
+ ASSERT_TRUE(child_pid_ > 0);
+ int status;
+ waitpid(child_pid_, &status, 0);
+ if (WEXITSTATUS(status) == kFatalFailure) {
+ GTEST_FATAL_FAILURE_("Test failed in child process");
+ } else if (WEXITSTATUS(status) == kNonFatalFailure) {
+ GTEST_NONFATAL_FAILURE_("Test failed in child process");
+ }
+ }
+
+ /* Gtest defines TestBody functions through its macros, but classes
+ * derived from this one need to define RealTestBody instead.
+ * This is achieved by defining a TestBody macro further below.
+ */
+ virtual void RealTestBody() = 0;
+
+ id_vector make_vector() {
+ return id_vector(&allocator, kDefaultBuildIdSize);
+ }
+
+ private:
+ static const int kFatalFailure = 1;
+ static const int kNonFatalFailure = 2;
+
+ pid_t child_pid_;
+ PageAllocator allocator;
+};
+
+} // namespace
+
+/* Replace TestBody declarations within TEST*() with RealTestBody
+ * declarations */
+#define TestBody RealTestBody
+
+TEST_F(LinuxPtraceDumperChildTest, Setup) {
+ LinuxPtraceDumper dumper(getppid());
+}
+
+TEST_F(LinuxPtraceDumperChildTest, FindMappings) {
+ LinuxPtraceDumper dumper(getppid());
+ ASSERT_TRUE(dumper.Init());
+
+ ASSERT_TRUE(dumper.FindMapping(reinterpret_cast<void*>(getpid)));
+ ASSERT_TRUE(dumper.FindMapping(reinterpret_cast<void*>(printf)));
+ ASSERT_FALSE(dumper.FindMapping(NULL));
+}
+
+TEST_F(LinuxPtraceDumperChildTest, ThreadList) {
+ LinuxPtraceDumper dumper(getppid());
+ ASSERT_TRUE(dumper.Init());
+
+ ASSERT_GE(dumper.threads().size(), (size_t)1);
+ bool found = false;
+ for (size_t i = 0; i < dumper.threads().size(); ++i) {
+ if (dumper.threads()[i] == getppid()) {
+ ASSERT_FALSE(found);
+ found = true;
+ }
+ }
+ ASSERT_TRUE(found);
+}
+
+// Helper stack class to close a file descriptor and unmap
+// a mmap'ed mapping.
+class StackHelper {
+ public:
+ StackHelper()
+ : fd_(-1), mapping_(NULL), size_(0) {}
+ ~StackHelper() {
+ if (size_)
+ munmap(mapping_, size_);
+ if (fd_ >= 0)
+ close(fd_);
+ }
+ void Init(int fd, char* mapping, size_t size) {
+ fd_ = fd;
+ mapping_ = mapping;
+ size_ = size;
+ }
+
+ char* mapping() const { return mapping_; }
+ size_t size() const { return size_; }
+
+ private:
+ int fd_;
+ char* mapping_;
+ size_t size_;
+};
+
+class LinuxPtraceDumperMappingsTest : public LinuxPtraceDumperChildTest {
+ protected:
+ virtual void SetUp();
+
+ string helper_path_;
+ size_t page_size_;
+ StackHelper helper_;
+};
+
+void LinuxPtraceDumperMappingsTest::SetUp() {
+ helper_path_ = GetHelperBinary();
+ if (helper_path_.empty()) {
+ FAIL() << "Couldn't find helper binary";
+ _exit(1);
+ }
+
+ // mmap two segments out of the helper binary, one
+ // enclosed in the other, but with different protections.
+ page_size_ = sysconf(_SC_PAGESIZE);
+ const size_t kMappingSize = 3 * page_size_;
+ int fd = open(helper_path_.c_str(), O_RDONLY);
+ ASSERT_NE(-1, fd) << "Failed to open file: " << helper_path_
+ << ", Error: " << strerror(errno);
+ char* mapping =
+ reinterpret_cast<char*>(mmap(NULL,
+ kMappingSize,
+ PROT_READ,
+ MAP_SHARED,
+ fd,
+ 0));
+ ASSERT_TRUE(mapping);
+
+ // Ensure that things get cleaned up.
+ helper_.Init(fd, mapping, kMappingSize);
+
+ // Carve a page out of the first mapping with different permissions.
+ char* inside_mapping = reinterpret_cast<char*>(
+ mmap(mapping + 2 * page_size_,
+ page_size_,
+ PROT_NONE,
+ MAP_SHARED | MAP_FIXED,
+ fd,
+ // Map a different offset just to
+ // better test real-world conditions.
+ page_size_));
+ ASSERT_TRUE(inside_mapping);
+
+ LinuxPtraceDumperChildTest::SetUp();
+}
+
+TEST_F(LinuxPtraceDumperMappingsTest, MergedMappings) {
+ // Now check that LinuxPtraceDumper interpreted the mappings properly.
+ LinuxPtraceDumper dumper(getppid());
+ ASSERT_TRUE(dumper.Init());
+ int mapping_count = 0;
+ for (unsigned i = 0; i < dumper.mappings().size(); ++i) {
+ const MappingInfo& mapping = *dumper.mappings()[i];
+ if (strcmp(mapping.name, this->helper_path_.c_str()) == 0) {
+ // This mapping should encompass the entire original mapped
+ // range.
+ EXPECT_EQ(reinterpret_cast<uintptr_t>(this->helper_.mapping()),
+ mapping.start_addr);
+ EXPECT_EQ(this->helper_.size(), mapping.size);
+ EXPECT_EQ(0U, mapping.offset);
+ mapping_count++;
+ }
+ }
+ EXPECT_EQ(1, mapping_count);
+}
+
+TEST_F(LinuxPtraceDumperChildTest, BuildProcPath) {
+ const pid_t pid = getppid();
+ LinuxPtraceDumper dumper(pid);
+
+ char maps_path[NAME_MAX] = "";
+ char maps_path_expected[NAME_MAX];
+ snprintf(maps_path_expected, sizeof(maps_path_expected),
+ "/proc/%d/maps", pid);
+ EXPECT_TRUE(dumper.BuildProcPath(maps_path, pid, "maps"));
+ EXPECT_STREQ(maps_path_expected, maps_path);
+
+ EXPECT_FALSE(dumper.BuildProcPath(NULL, pid, "maps"));
+ EXPECT_FALSE(dumper.BuildProcPath(maps_path, 0, "maps"));
+ EXPECT_FALSE(dumper.BuildProcPath(maps_path, pid, ""));
+ EXPECT_FALSE(dumper.BuildProcPath(maps_path, pid, NULL));
+
+ char long_node[NAME_MAX];
+ size_t long_node_len = NAME_MAX - strlen("/proc/123") - 1;
+ memset(long_node, 'a', long_node_len);
+ long_node[long_node_len] = '\0';
+ EXPECT_FALSE(dumper.BuildProcPath(maps_path, 123, long_node));
+}
+
+#if !defined(__ARM_EABI__) && !defined(__mips__)
+// Ensure that the linux-gate VDSO is included in the mapping list.
+TEST_F(LinuxPtraceDumperChildTest, MappingsIncludeLinuxGate) {
+ LinuxPtraceDumper dumper(getppid());
+ ASSERT_TRUE(dumper.Init());
+
+ void* linux_gate_loc =
+ reinterpret_cast<void *>(dumper.auxv()[AT_SYSINFO_EHDR]);
+ ASSERT_TRUE(linux_gate_loc);
+ bool found_linux_gate = false;
+
+ const wasteful_vector<MappingInfo*> mappings = dumper.mappings();
+ const MappingInfo* mapping;
+ for (unsigned i = 0; i < mappings.size(); ++i) {
+ mapping = mappings[i];
+ if (!strcmp(mapping->name, kLinuxGateLibraryName)) {
+ found_linux_gate = true;
+ break;
+ }
+ }
+ EXPECT_TRUE(found_linux_gate);
+ EXPECT_EQ(linux_gate_loc, reinterpret_cast<void*>(mapping->start_addr));
+ EXPECT_EQ(0, memcmp(linux_gate_loc, ELFMAG, SELFMAG));
+}
+
+// Ensure that the linux-gate VDSO can generate a non-zeroed File ID.
+TEST_F(LinuxPtraceDumperChildTest, LinuxGateMappingID) {
+ LinuxPtraceDumper dumper(getppid());
+ ASSERT_TRUE(dumper.Init());
+
+ bool found_linux_gate = false;
+ const wasteful_vector<MappingInfo*> mappings = dumper.mappings();
+ unsigned index = 0;
+ for (unsigned i = 0; i < mappings.size(); ++i) {
+ if (!strcmp(mappings[i]->name, kLinuxGateLibraryName)) {
+ found_linux_gate = true;
+ index = i;
+ break;
+ }
+ }
+ ASSERT_TRUE(found_linux_gate);
+
+ // Need to suspend the child so ptrace actually works.
+ ASSERT_TRUE(dumper.ThreadsSuspend());
+ id_vector identifier(make_vector());
+ ASSERT_TRUE(dumper.ElfFileIdentifierForMapping(*mappings[index],
+ true,
+ index,
+ identifier));
+
+ id_vector empty_identifier(make_vector());
+ empty_identifier.resize(kDefaultBuildIdSize, 0);
+ EXPECT_NE(empty_identifier, identifier);
+ EXPECT_TRUE(dumper.ThreadsResume());
+}
+#endif
+
+TEST_F(LinuxPtraceDumperChildTest, FileIDsMatch) {
+ // Calculate the File ID of our binary using both
+ // FileID::ElfFileIdentifier and LinuxDumper::ElfFileIdentifierForMapping
+ // and ensure that we get the same result from both.
+ char exe_name[PATH_MAX];
+ ASSERT_TRUE(SafeReadLink("/proc/self/exe", exe_name));
+
+ LinuxPtraceDumper dumper(getppid());
+ ASSERT_TRUE(dumper.Init());
+ const wasteful_vector<MappingInfo*> mappings = dumper.mappings();
+ bool found_exe = false;
+ unsigned i;
+ for (i = 0; i < mappings.size(); ++i) {
+ const MappingInfo* mapping = mappings[i];
+ if (!strcmp(mapping->name, exe_name)) {
+ found_exe = true;
+ break;
+ }
+ }
+ ASSERT_TRUE(found_exe);
+
+ id_vector identifier1(make_vector());
+ id_vector identifier2(make_vector());
+ EXPECT_TRUE(dumper.ElfFileIdentifierForMapping(*mappings[i], true, i,
+ identifier1));
+ FileID fileid(exe_name);
+ EXPECT_TRUE(fileid.ElfFileIdentifier(identifier2));
+
+ string identifier_string1 =
+ FileID::ConvertIdentifierToUUIDString(identifier1);
+ string identifier_string2 =
+ FileID::ConvertIdentifierToUUIDString(identifier2);
+ EXPECT_EQ(identifier_string1, identifier_string2);
+}
+
+/* Get back to normal behavior of TEST*() macros wrt TestBody. */
+#undef TestBody
+
+TEST(LinuxPtraceDumperTest, VerifyStackReadWithMultipleThreads) {
+ static const size_t kNumberOfThreadsInHelperProgram = 5;
+
+ pid_t child_pid = SetupChildProcess(kNumberOfThreadsInHelperProgram);
+ ASSERT_NE(child_pid, -1);
+
+ // Children are ready now.
+ LinuxPtraceDumper dumper(child_pid);
+ ASSERT_TRUE(dumper.Init());
+#if defined(THREAD_SANITIZER)
+ EXPECT_GE(dumper.threads().size(), (size_t)kNumberOfThreadsInHelperProgram);
+#else
+ EXPECT_EQ(dumper.threads().size(), (size_t)kNumberOfThreadsInHelperProgram);
+#endif
+ EXPECT_TRUE(dumper.ThreadsSuspend());
+
+ ThreadInfo one_thread;
+ size_t matching_threads = 0;
+ for (size_t i = 0; i < dumper.threads().size(); ++i) {
+ EXPECT_TRUE(dumper.GetThreadInfoByIndex(i, &one_thread));
+ const void* stack;
+ size_t stack_len;
+ EXPECT_TRUE(dumper.GetStackInfo(&stack, &stack_len,
+ one_thread.stack_pointer));
+ // In the helper program, we stored a pointer to the thread id in a
+ // specific register. Check that we can recover its value.
+#if defined(__ARM_EABI__)
+ pid_t* process_tid_location = (pid_t*)(one_thread.regs.uregs[3]);
+#elif defined(__aarch64__)
+ pid_t* process_tid_location = (pid_t*)(one_thread.regs.regs[3]);
+#elif defined(__i386)
+ pid_t* process_tid_location = (pid_t*)(one_thread.regs.ecx);
+#elif defined(__x86_64)
+ pid_t* process_tid_location = (pid_t*)(one_thread.regs.rcx);
+#elif defined(__mips__)
+ pid_t* process_tid_location =
+ reinterpret_cast<pid_t*>(one_thread.mcontext.gregs[1]);
+#else
+#error This test has not been ported to this platform.
+#endif
+ pid_t one_thread_id;
+ dumper.CopyFromProcess(&one_thread_id,
+ dumper.threads()[i],
+ process_tid_location,
+ 4);
+ matching_threads += (dumper.threads()[i] == one_thread_id) ? 1 : 0;
+ }
+ EXPECT_EQ(matching_threads, kNumberOfThreadsInHelperProgram);
+ EXPECT_TRUE(dumper.ThreadsResume());
+ kill(child_pid, SIGKILL);
+
+ // Reap child
+ int status;
+ ASSERT_NE(-1, HANDLE_EINTR(waitpid(child_pid, &status, 0)));
+ ASSERT_TRUE(WIFSIGNALED(status));
+ ASSERT_EQ(SIGKILL, WTERMSIG(status));
+}
+
+TEST_F(LinuxPtraceDumperTest, SanitizeStackCopy) {
+ static const size_t kNumberOfThreadsInHelperProgram = 1;
+
+ pid_t child_pid = SetupChildProcess(kNumberOfThreadsInHelperProgram);
+ ASSERT_NE(child_pid, -1);
+
+ LinuxPtraceDumper dumper(child_pid);
+ ASSERT_TRUE(dumper.Init());
+ EXPECT_TRUE(dumper.ThreadsSuspend());
+
+ ThreadInfo thread_info;
+ EXPECT_TRUE(dumper.GetThreadInfoByIndex(0, &thread_info));
+
+ const uintptr_t defaced =
+#if defined(__LP64__)
+ 0x0defaced0defaced;
+#else
+ 0x0defaced;
+#endif
+
+ uintptr_t simulated_stack[2];
+
+ // Pointers into the stack shouldn't be sanitized.
+ memset(simulated_stack, 0xff, sizeof(simulated_stack));
+ simulated_stack[1] = thread_info.stack_pointer;
+ dumper.SanitizeStackCopy(reinterpret_cast<uint8_t*>(&simulated_stack),
+ sizeof(simulated_stack), thread_info.stack_pointer,
+ sizeof(uintptr_t));
+ ASSERT_NE(simulated_stack[1], defaced);
+
+ // Memory prior to the stack pointer should be cleared.
+ ASSERT_EQ(simulated_stack[0], 0u);
+
+ // Small integers should not be sanitized.
+ for (int i = -4096; i <= 4096; ++i) {
+ memset(simulated_stack, 0, sizeof(simulated_stack));
+ simulated_stack[0] = static_cast<uintptr_t>(i);
+ dumper.SanitizeStackCopy(reinterpret_cast<uint8_t*>(&simulated_stack),
+ sizeof(simulated_stack), thread_info.stack_pointer,
+ 0u);
+ ASSERT_NE(simulated_stack[0], defaced);
+ }
+
+ // The instruction pointer definitely should point into an executable mapping.
+ const MappingInfo* mapping_info = dumper.FindMappingNoBias(
+ reinterpret_cast<uintptr_t>(thread_info.GetInstructionPointer()));
+ ASSERT_NE(mapping_info, nullptr);
+ ASSERT_TRUE(mapping_info->exec);
+
+ // Pointers to code shouldn't be sanitized.
+ memset(simulated_stack, 0, sizeof(simulated_stack));
+ simulated_stack[1] = thread_info.GetInstructionPointer();
+ dumper.SanitizeStackCopy(reinterpret_cast<uint8_t*>(&simulated_stack),
+ sizeof(simulated_stack), thread_info.stack_pointer,
+ 0u);
+ ASSERT_NE(simulated_stack[0], defaced);
+
+ // String fragments should be sanitized.
+ memcpy(simulated_stack, "abcdefghijklmnop", sizeof(simulated_stack));
+ dumper.SanitizeStackCopy(reinterpret_cast<uint8_t*>(&simulated_stack),
+ sizeof(simulated_stack), thread_info.stack_pointer,
+ 0u);
+ ASSERT_EQ(simulated_stack[0], defaced);
+ ASSERT_EQ(simulated_stack[1], defaced);
+
+ // Heap pointers should be sanititzed.
+#if defined(__ARM_EABI__)
+ uintptr_t heap_addr = thread_info.regs.uregs[3];
+#elif defined(__aarch64__)
+ uintptr_t heap_addr = thread_info.regs.regs[3];
+#elif defined(__i386)
+ uintptr_t heap_addr = thread_info.regs.ecx;
+#elif defined(__x86_64)
+ uintptr_t heap_addr = thread_info.regs.rcx;
+#elif defined(__mips__)
+ uintptr_t heap_addr = thread_info.mcontext.gregs[1];
+#else
+#error This test has not been ported to this platform.
+#endif
+ memset(simulated_stack, 0, sizeof(simulated_stack));
+ simulated_stack[0] = heap_addr;
+ dumper.SanitizeStackCopy(reinterpret_cast<uint8_t*>(&simulated_stack),
+ sizeof(simulated_stack), thread_info.stack_pointer,
+ 0u);
+ ASSERT_EQ(simulated_stack[0], defaced);
+
+ EXPECT_TRUE(dumper.ThreadsResume());
+ kill(child_pid, SIGKILL);
+
+ // Reap child.
+ int status;
+ ASSERT_NE(-1, HANDLE_EINTR(waitpid(child_pid, &status, 0)));
+ ASSERT_TRUE(WIFSIGNALED(status));
+ ASSERT_EQ(SIGKILL, WTERMSIG(status));
+}
diff --git a/toolkit/crashreporter/breakpad-client/linux/minidump_writer/minidump_writer.cc b/toolkit/crashreporter/breakpad-client/linux/minidump_writer/minidump_writer.cc
new file mode 100644
index 0000000000..03066e9110
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/linux/minidump_writer/minidump_writer.cc
@@ -0,0 +1,1562 @@
+// 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 code writes out minidump files:
+// http://msdn.microsoft.com/en-us/library/ms680378(VS.85,loband).aspx
+//
+// Minidumps are a Microsoft format which Breakpad uses for recording crash
+// dumps. This code has to run in a compromised environment (the address space
+// may have received SIGSEGV), thus the following rules apply:
+// * You may not enter the dynamic linker. This means that we cannot call
+// any symbols in a shared library (inc libc). Because of this we replace
+// libc functions in linux_libc_support.h.
+// * You may not call syscalls via the libc wrappers. This rule is a subset
+// of the first rule but it bears repeating. We have direct wrappers
+// around the system calls in linux_syscall_support.h.
+// * You may not malloc. There's an alternative allocator in memory.h and
+// a canonical instance in the LinuxDumper object. We use the placement
+// new form to allocate objects and we don't delete them.
+
+#include "linux/handler/minidump_descriptor.h"
+#include "linux/minidump_writer/minidump_writer.h"
+#include "minidump_file_writer-inl.h"
+
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <link.h>
+#include <stdio.h>
+#if defined(__ANDROID__)
+#include <sys/system_properties.h>
+#endif
+#include <sys/types.h>
+#include <sys/ucontext.h>
+#include <sys/user.h>
+#include <sys/utsname.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <algorithm>
+
+#include "linux/dump_writer_common/thread_info.h"
+#include "linux/dump_writer_common/ucontext_reader.h"
+#include "linux/handler/exception_handler.h"
+#include "linux/minidump_writer/cpu_set.h"
+#include "linux/minidump_writer/line_reader.h"
+#include "linux/minidump_writer/linux_dumper.h"
+#include "linux/minidump_writer/linux_ptrace_dumper.h"
+#include "linux/minidump_writer/proc_cpuinfo_reader.h"
+#include "minidump_file_writer.h"
+#include "common/linux/file_id.h"
+#include "common/linux/linux_libc_support.h"
+#include "common/minidump_type_helper.h"
+#include "google_breakpad/common/minidump_format.h"
+#include "third_party/lss/linux_syscall_support.h"
+
+namespace {
+
+using google_breakpad::AppMemoryList;
+using google_breakpad::auto_wasteful_vector;
+using google_breakpad::ExceptionHandler;
+using google_breakpad::CpuSet;
+using google_breakpad::kDefaultBuildIdSize;
+using google_breakpad::LineReader;
+using google_breakpad::LinuxDumper;
+using google_breakpad::LinuxPtraceDumper;
+using google_breakpad::MDTypeHelper;
+using google_breakpad::MappingEntry;
+using google_breakpad::MappingInfo;
+using google_breakpad::MappingList;
+using google_breakpad::MinidumpFileWriter;
+using google_breakpad::PageAllocator;
+using google_breakpad::ProcCpuInfoReader;
+using google_breakpad::RawContextCPU;
+using google_breakpad::ThreadInfo;
+using google_breakpad::TypedMDRVA;
+using google_breakpad::UContextReader;
+using google_breakpad::UntypedMDRVA;
+using google_breakpad::wasteful_vector;
+
+typedef MDTypeHelper<sizeof(void*)>::MDRawDebug MDRawDebug;
+typedef MDTypeHelper<sizeof(void*)>::MDRawLinkMap MDRawLinkMap;
+
+class MinidumpWriter {
+ public:
+ // The following kLimit* constants are for when minidump_size_limit_ is set
+ // and the minidump size might exceed it.
+ //
+ // Estimate for how big each thread's stack will be (in bytes).
+ static const unsigned kLimitAverageThreadStackLength = 8 * 1024;
+ // Number of threads whose stack size we don't want to limit. These base
+ // threads will simply be the first N threads returned by the dumper (although
+ // the crashing thread will never be limited). Threads beyond this count are
+ // the extra threads.
+ static const unsigned kLimitBaseThreadCount = 20;
+ // Maximum stack size to dump for any extra thread (in bytes).
+ static const unsigned kLimitMaxExtraThreadStackLen = 2 * 1024;
+ // Make sure this number of additional bytes can fit in the minidump
+ // (exclude the stack data).
+ static const unsigned kLimitMinidumpFudgeFactor = 64 * 1024;
+
+ MinidumpWriter(const char* minidump_path,
+ int minidump_fd,
+ const ExceptionHandler::CrashContext* context,
+ const MappingList& mappings,
+ const AppMemoryList& appmem,
+ bool skip_stacks_if_mapping_unreferenced,
+ uintptr_t principal_mapping_address,
+ bool sanitize_stacks,
+ LinuxDumper* dumper)
+ : fd_(minidump_fd),
+ path_(minidump_path),
+ ucontext_(context ? &context->context : NULL),
+#if !defined(__ARM_EABI__) && !defined(__mips__)
+ float_state_(context ? &context->float_state : NULL),
+#endif
+ dumper_(dumper),
+ minidump_size_limit_(-1),
+ memory_blocks_(dumper_->allocator()),
+ mapping_list_(mappings),
+ app_memory_list_(appmem),
+ skip_stacks_if_mapping_unreferenced_(
+ skip_stacks_if_mapping_unreferenced),
+ principal_mapping_address_(principal_mapping_address),
+ principal_mapping_(nullptr),
+ sanitize_stacks_(sanitize_stacks) {
+ // Assert there should be either a valid fd or a valid path, not both.
+ assert(fd_ != -1 || minidump_path);
+ assert(fd_ == -1 || !minidump_path);
+ }
+
+ bool Init() {
+ if (!dumper_->Init())
+ return false;
+
+ if (!dumper_->ThreadsSuspend() || !dumper_->LateInit())
+ return false;
+
+ if (skip_stacks_if_mapping_unreferenced_) {
+ principal_mapping_ =
+ dumper_->FindMappingNoBias(principal_mapping_address_);
+ if (!CrashingThreadReferencesPrincipalMapping())
+ return false;
+ }
+
+ if (fd_ != -1)
+ minidump_writer_.SetFile(fd_);
+ else if (!minidump_writer_.Open(path_))
+ return false;
+
+ return true;
+ }
+
+ ~MinidumpWriter() {
+ // Don't close the file descriptor when it's been provided explicitly.
+ // Callers might still need to use it.
+ if (fd_ == -1)
+ minidump_writer_.Close();
+ dumper_->ThreadsResume();
+ }
+
+ bool CrashingThreadReferencesPrincipalMapping() {
+ if (!ucontext_ || !principal_mapping_)
+ return false;
+
+ const uintptr_t low_addr =
+ principal_mapping_->system_mapping_info.start_addr;
+ const uintptr_t high_addr =
+ principal_mapping_->system_mapping_info.end_addr;
+
+ const uintptr_t stack_pointer = UContextReader::GetStackPointer(ucontext_);
+ const uintptr_t pc = UContextReader::GetInstructionPointer(ucontext_);
+
+ if (pc >= low_addr && pc < high_addr)
+ return true;
+
+ uint8_t* stack_copy;
+ const void* stack;
+ size_t stack_len;
+
+ if (!dumper_->GetStackInfo(&stack, &stack_len, stack_pointer))
+ return false;
+
+ stack_copy = reinterpret_cast<uint8_t*>(Alloc(stack_len));
+ dumper_->CopyFromProcess(stack_copy, GetCrashThread(), stack, stack_len);
+
+ uintptr_t stack_pointer_offset =
+ stack_pointer - reinterpret_cast<uintptr_t>(stack);
+
+ return dumper_->StackHasPointerToMapping(
+ stack_copy, stack_len, stack_pointer_offset, *principal_mapping_);
+ }
+
+ bool Dump() {
+ // A minidump file contains a number of tagged streams. This is the number
+ // of stream which we write.
+ unsigned kNumWriters = 14;
+
+ TypedMDRVA<MDRawDirectory> dir(&minidump_writer_);
+ {
+ // Ensure the header gets flushed, as that happens in the destructor.
+ // If we crash somewhere below, we should have a mostly-intact dump
+ TypedMDRVA<MDRawHeader> header(&minidump_writer_);
+ if (!header.Allocate())
+ return false;
+
+ if (!dir.AllocateArray(kNumWriters))
+ return false;
+
+ my_memset(header.get(), 0, sizeof(MDRawHeader));
+
+ header.get()->signature = MD_HEADER_SIGNATURE;
+ header.get()->version = MD_HEADER_VERSION;
+ header.get()->time_date_stamp = time(NULL);
+ header.get()->stream_count = kNumWriters;
+ header.get()->stream_directory_rva = dir.position();
+ }
+
+ unsigned dir_index = 0;
+ MDRawDirectory dirent;
+
+ if (!WriteThreadListStream(&dirent))
+ return false;
+ dir.CopyIndex(dir_index++, &dirent);
+
+ if (!WriteThreadNamesStream(&dirent))
+ return false;
+ dir.CopyIndex(dir_index++, &dirent);
+
+ if (!WriteMappings(&dirent))
+ return false;
+ dir.CopyIndex(dir_index++, &dirent);
+
+ if (!WriteAppMemory())
+ return false;
+
+ if (!WriteMemoryListStream(&dirent))
+ return false;
+ dir.CopyIndex(dir_index++, &dirent);
+
+ if (!WriteExceptionStream(&dirent))
+ return false;
+ dir.CopyIndex(dir_index++, &dirent);
+
+ if (!WriteSystemInfoStream(&dirent))
+ return false;
+ dir.CopyIndex(dir_index++, &dirent);
+
+ dirent.stream_type = MD_LINUX_CPU_INFO;
+ if (!WriteFile(&dirent.location, "/proc/cpuinfo"))
+ NullifyDirectoryEntry(&dirent);
+ dir.CopyIndex(dir_index++, &dirent);
+
+ dirent.stream_type = MD_LINUX_PROC_STATUS;
+ if (!WriteProcFile(&dirent.location, GetCrashThread(), "status"))
+ NullifyDirectoryEntry(&dirent);
+ dir.CopyIndex(dir_index++, &dirent);
+
+ dirent.stream_type = MD_LINUX_LSB_RELEASE;
+ if (!WriteFile(&dirent.location, "/etc/lsb-release") &&
+ !WriteFile(&dirent.location, "/etc/os-release")) {
+ NullifyDirectoryEntry(&dirent);
+ }
+ dir.CopyIndex(dir_index++, &dirent);
+
+ dirent.stream_type = MD_LINUX_CMD_LINE;
+ if (!WriteProcFile(&dirent.location, GetCrashThread(), "cmdline"))
+ NullifyDirectoryEntry(&dirent);
+ dir.CopyIndex(dir_index++, &dirent);
+
+ dirent.stream_type = MD_LINUX_ENVIRON;
+ if (!WriteProcFile(&dirent.location, GetCrashThread(), "environ"))
+ NullifyDirectoryEntry(&dirent);
+ dir.CopyIndex(dir_index++, &dirent);
+
+ dirent.stream_type = MD_LINUX_AUXV;
+ if (!WriteProcFile(&dirent.location, GetCrashThread(), "auxv"))
+ NullifyDirectoryEntry(&dirent);
+ dir.CopyIndex(dir_index++, &dirent);
+
+ dirent.stream_type = MD_LINUX_MAPS;
+ if (!WriteProcFile(&dirent.location, GetCrashThread(), "maps"))
+ NullifyDirectoryEntry(&dirent);
+ dir.CopyIndex(dir_index++, &dirent);
+
+ dirent.stream_type = MD_LINUX_DSO_DEBUG;
+ if (!WriteDSODebugStream(&dirent))
+ NullifyDirectoryEntry(&dirent);
+ dir.CopyIndex(dir_index++, &dirent);
+
+ // If you add more directory entries, don't forget to update kNumWriters,
+ // above.
+
+ dumper_->ThreadsResume();
+ return true;
+ }
+
+ bool FillThreadStack(MDRawThread* thread, uintptr_t stack_pointer,
+ uintptr_t pc, int max_stack_len, uint8_t** stack_copy) {
+ *stack_copy = NULL;
+ const void* stack;
+ size_t stack_len;
+
+ thread->stack.start_of_memory_range = stack_pointer;
+ thread->stack.memory.data_size = 0;
+ thread->stack.memory.rva = minidump_writer_.position();
+
+ if (dumper_->GetStackInfo(&stack, &stack_len, stack_pointer)) {
+ if (max_stack_len >= 0 &&
+ stack_len > static_cast<unsigned int>(max_stack_len)) {
+ stack_len = max_stack_len;
+ // Skip empty chunks of length max_stack_len.
+ uintptr_t int_stack = reinterpret_cast<uintptr_t>(stack);
+ if (max_stack_len > 0) {
+ while (int_stack + max_stack_len < stack_pointer) {
+ int_stack += max_stack_len;
+ }
+ }
+ stack = reinterpret_cast<const void*>(int_stack);
+ }
+ *stack_copy = reinterpret_cast<uint8_t*>(Alloc(stack_len));
+ dumper_->CopyFromProcess(*stack_copy, thread->thread_id, stack,
+ stack_len);
+
+ uintptr_t stack_pointer_offset =
+ stack_pointer - reinterpret_cast<uintptr_t>(stack);
+ if (skip_stacks_if_mapping_unreferenced_) {
+ if (!principal_mapping_) {
+ return true;
+ }
+ uintptr_t low_addr = principal_mapping_->system_mapping_info.start_addr;
+ uintptr_t high_addr = principal_mapping_->system_mapping_info.end_addr;
+ if ((pc < low_addr || pc > high_addr) &&
+ !dumper_->StackHasPointerToMapping(*stack_copy, stack_len,
+ stack_pointer_offset,
+ *principal_mapping_)) {
+ return true;
+ }
+ }
+
+ if (sanitize_stacks_) {
+ dumper_->SanitizeStackCopy(*stack_copy, stack_len, stack_pointer,
+ stack_pointer_offset);
+ }
+
+ UntypedMDRVA memory(&minidump_writer_);
+ if (!memory.Allocate(stack_len))
+ return false;
+ memory.Copy(*stack_copy, stack_len);
+ thread->stack.start_of_memory_range = reinterpret_cast<uintptr_t>(stack);
+ thread->stack.memory = memory.location();
+ memory_blocks_.push_back(thread->stack);
+ }
+ return true;
+ }
+
+ // Write information about the threads.
+ bool WriteThreadListStream(MDRawDirectory* dirent) {
+ const unsigned num_threads = dumper_->threads().size();
+
+ TypedMDRVA<uint32_t> list(&minidump_writer_);
+ if (!list.AllocateObjectAndArray(num_threads, sizeof(MDRawThread)))
+ return false;
+
+ dirent->stream_type = MD_THREAD_LIST_STREAM;
+ dirent->location = list.location();
+
+ *list.get() = num_threads;
+
+ // If there's a minidump size limit, check if it might be exceeded. Since
+ // most of the space is filled with stack data, just check against that.
+ // If this expects to exceed the limit, set extra_thread_stack_len such
+ // that any thread beyond the first kLimitBaseThreadCount threads will
+ // have only kLimitMaxExtraThreadStackLen bytes dumped.
+ int extra_thread_stack_len = -1; // default to no maximum
+ if (minidump_size_limit_ >= 0) {
+ const unsigned estimated_total_stack_size = num_threads *
+ kLimitAverageThreadStackLength;
+ const off_t estimated_minidump_size = minidump_writer_.position() +
+ estimated_total_stack_size + kLimitMinidumpFudgeFactor;
+ if (estimated_minidump_size > minidump_size_limit_)
+ extra_thread_stack_len = kLimitMaxExtraThreadStackLen;
+ }
+
+ for (unsigned i = 0; i < num_threads; ++i) {
+ MDRawThread thread;
+ my_memset(&thread, 0, sizeof(thread));
+ thread.thread_id = dumper_->threads()[i];
+
+ // We have a different source of information for the crashing thread. If
+ // we used the actual state of the thread we would find it running in the
+ // signal handler with the alternative stack, which would be deeply
+ // unhelpful.
+ if (static_cast<pid_t>(thread.thread_id) == GetCrashThread() &&
+ ucontext_ &&
+ !dumper_->IsPostMortem()) {
+ uint8_t* stack_copy;
+ const uintptr_t stack_ptr = UContextReader::GetStackPointer(ucontext_);
+ if (!FillThreadStack(&thread, stack_ptr,
+ UContextReader::GetInstructionPointer(ucontext_),
+ -1, &stack_copy))
+ return false;
+
+ // Copy 256 bytes around crashing instruction pointer to minidump.
+ const size_t kIPMemorySize = 256;
+ uint64_t ip = UContextReader::GetInstructionPointer(ucontext_);
+ // Bound it to the upper and lower bounds of the memory map
+ // it's contained within. If it's not in mapped memory,
+ // don't bother trying to write it.
+ bool ip_is_mapped = false;
+ MDMemoryDescriptor ip_memory_d;
+ for (unsigned j = 0; j < dumper_->mappings().size(); ++j) {
+ const MappingInfo& mapping = *dumper_->mappings()[j];
+ if (ip >= mapping.start_addr &&
+ ip < mapping.start_addr + mapping.size) {
+ ip_is_mapped = true;
+ // Try to get 128 bytes before and after the IP, but
+ // settle for whatever's available.
+ ip_memory_d.start_of_memory_range =
+ std::max(mapping.start_addr,
+ uintptr_t(ip - (kIPMemorySize / 2)));
+ uintptr_t end_of_range =
+ std::min(uintptr_t(ip + (kIPMemorySize / 2)),
+ uintptr_t(mapping.start_addr + mapping.size));
+ ip_memory_d.memory.data_size =
+ end_of_range - ip_memory_d.start_of_memory_range;
+ break;
+ }
+ }
+
+ if (ip_is_mapped) {
+ UntypedMDRVA ip_memory(&minidump_writer_);
+ if (!ip_memory.Allocate(ip_memory_d.memory.data_size))
+ return false;
+ uint8_t* memory_copy =
+ reinterpret_cast<uint8_t*>(Alloc(ip_memory_d.memory.data_size));
+ dumper_->CopyFromProcess(
+ memory_copy,
+ thread.thread_id,
+ reinterpret_cast<void*>(ip_memory_d.start_of_memory_range),
+ ip_memory_d.memory.data_size);
+ ip_memory.Copy(memory_copy, ip_memory_d.memory.data_size);
+ ip_memory_d.memory = ip_memory.location();
+ memory_blocks_.push_back(ip_memory_d);
+ }
+
+ TypedMDRVA<RawContextCPU> cpu(&minidump_writer_);
+ if (!cpu.Allocate())
+ return false;
+ my_memset(cpu.get(), 0, sizeof(RawContextCPU));
+#if !defined(__ARM_EABI__) && !defined(__mips__)
+ UContextReader::FillCPUContext(cpu.get(), ucontext_, float_state_);
+#else
+ UContextReader::FillCPUContext(cpu.get(), ucontext_);
+#endif
+ thread.thread_context = cpu.location();
+ crashing_thread_context_ = cpu.location();
+ } else {
+ ThreadInfo info;
+ if (!dumper_->GetThreadInfoByIndex(i, &info))
+ return false;
+
+ uint8_t* stack_copy;
+ int max_stack_len = -1; // default to no maximum for this thread
+ if (minidump_size_limit_ >= 0 && i >= kLimitBaseThreadCount)
+ max_stack_len = extra_thread_stack_len;
+ if (!FillThreadStack(&thread, info.stack_pointer,
+ info.GetInstructionPointer(), max_stack_len,
+ &stack_copy))
+ return false;
+
+ TypedMDRVA<RawContextCPU> cpu(&minidump_writer_);
+ if (!cpu.Allocate())
+ return false;
+ my_memset(cpu.get(), 0, sizeof(RawContextCPU));
+ info.FillCPUContext(cpu.get());
+ thread.thread_context = cpu.location();
+ if (dumper_->threads()[i] == GetCrashThread()) {
+ crashing_thread_context_ = cpu.location();
+ if (!dumper_->IsPostMortem()) {
+ // This is the crashing thread of a live process, but
+ // no context was provided, so set the crash address
+ // while the instruction pointer is already here.
+ dumper_->set_crash_address(info.GetInstructionPointer());
+ }
+ }
+ }
+
+ list.CopyIndexAfterObject(i, &thread, sizeof(thread));
+ }
+
+ return true;
+ }
+
+ bool WriteThreadName(pid_t tid, char* name, MDRawThreadName *thread_name) {
+ MDLocationDescriptor string_location;
+
+ if (!minidump_writer_.WriteString(name, 0, &string_location))
+ return false;
+
+ thread_name->thread_id = tid;
+ thread_name->rva_of_thread_name = string_location.rva;
+ return true;
+ }
+
+ // Write the threads' names.
+ bool WriteThreadNamesStream(MDRawDirectory* thread_names_stream) {
+ TypedMDRVA<MDRawThreadNamesList> list(&minidump_writer_);
+ const unsigned num_threads = dumper_->threads().size();
+
+ if (!list.AllocateObjectAndArray(num_threads, sizeof(MDRawThreadName))) {
+ return false;
+ }
+
+ thread_names_stream->stream_type = MD_THREAD_NAMES_STREAM;
+ thread_names_stream->location = list.location();
+ list.get()->number_of_thread_names = num_threads;
+
+ MDRawThreadName thread_name;
+ int thread_idx = 0;
+
+ for (unsigned int i = 0; i < num_threads; ++i) {
+ const pid_t tid = dumper_->threads()[i];
+ // This is a constant from the Linux kernel, documented in man 5 proc.
+ // The comm entries in /proc are no longer than this.
+ static const size_t TASK_COMM_LEN = 16;
+ char name[TASK_COMM_LEN];
+ memset(&thread_name, 0, sizeof(MDRawThreadName));
+
+ if (dumper_->GetThreadNameByIndex(i, name, sizeof(name))) {
+ if (WriteThreadName(tid, name, &thread_name)) {
+ list.CopyIndexAfterObject(thread_idx++, &thread_name,
+ sizeof(MDRawThreadName));
+ }
+ }
+ }
+
+ return true;
+ }
+
+ // Write application-provided memory regions.
+ bool WriteAppMemory() {
+ for (AppMemoryList::const_iterator iter = app_memory_list_.begin();
+ iter != app_memory_list_.end();
+ ++iter) {
+ uint8_t* data_copy =
+ reinterpret_cast<uint8_t*>(dumper_->allocator()->Alloc(iter->length));
+ dumper_->CopyFromProcess(data_copy, GetCrashThread(), iter->ptr,
+ iter->length);
+
+ UntypedMDRVA memory(&minidump_writer_);
+ if (!memory.Allocate(iter->length)) {
+ return false;
+ }
+ memory.Copy(data_copy, iter->length);
+ MDMemoryDescriptor desc;
+ desc.start_of_memory_range = reinterpret_cast<uintptr_t>(iter->ptr);
+ desc.memory = memory.location();
+ memory_blocks_.push_back(desc);
+ }
+
+ return true;
+ }
+
+ static bool ShouldIncludeMapping(const MappingInfo& mapping) {
+ if (mapping.name[0] == 0 || // only want modules with filenames.
+ // Only want to include one mapping per shared lib.
+ // Avoid filtering executable mappings.
+ (mapping.offset != 0 && !mapping.exec) ||
+ mapping.size < 4096) { // too small to get a signature for.
+ return false;
+ }
+
+ return true;
+ }
+
+ // If there is caller-provided information about this mapping
+ // in the mapping_list_ list, return true. Otherwise, return false.
+ bool HaveMappingInfo(const MappingInfo& mapping) {
+ for (MappingList::const_iterator iter = mapping_list_.begin();
+ iter != mapping_list_.end();
+ ++iter) {
+ // Ignore any mappings that are wholly contained within
+ // mappings in the mapping_info_ list.
+ if (mapping.start_addr >= iter->first.start_addr &&
+ (mapping.start_addr + mapping.size) <=
+ (iter->first.start_addr + iter->first.size)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ // Write information about the mappings in effect. Because we are using the
+ // minidump format, the information about the mappings is pretty limited.
+ // Because of this, we also include the full, unparsed, /proc/$x/maps file in
+ // another stream in the file.
+ bool WriteMappings(MDRawDirectory* dirent) {
+ const unsigned num_mappings = dumper_->mappings().size();
+ unsigned num_output_mappings = mapping_list_.size();
+
+ for (unsigned i = 0; i < dumper_->mappings().size(); ++i) {
+ const MappingInfo& mapping = *dumper_->mappings()[i];
+ if (ShouldIncludeMapping(mapping) && !HaveMappingInfo(mapping))
+ num_output_mappings++;
+ }
+
+ TypedMDRVA<uint32_t> list(&minidump_writer_);
+ if (num_output_mappings) {
+ if (!list.AllocateObjectAndArray(num_output_mappings, MD_MODULE_SIZE))
+ return false;
+ } else {
+ // Still create the module list stream, although it will have zero
+ // modules.
+ if (!list.Allocate())
+ return false;
+ }
+
+ dirent->stream_type = MD_MODULE_LIST_STREAM;
+ dirent->location = list.location();
+ *list.get() = num_output_mappings;
+
+ // First write all the mappings from the dumper
+ unsigned int j = 0;
+ for (unsigned i = 0; i < num_mappings; ++i) {
+ const MappingInfo& mapping = *dumper_->mappings()[i];
+ if (!ShouldIncludeMapping(mapping) || HaveMappingInfo(mapping))
+ continue;
+
+ MDRawModule mod;
+ if (!FillRawModule(mapping, true, i, &mod, NULL))
+ return false;
+ list.CopyIndexAfterObject(j++, &mod, MD_MODULE_SIZE);
+ }
+ // Next write all the mappings provided by the caller
+ for (MappingList::const_iterator iter = mapping_list_.begin();
+ iter != mapping_list_.end();
+ ++iter) {
+ MDRawModule mod;
+ if (!FillRawModule(iter->first, false, 0, &mod, &iter->second)) {
+ return false;
+ }
+ list.CopyIndexAfterObject(j++, &mod, MD_MODULE_SIZE);
+ }
+
+ return true;
+ }
+
+ // Fill the MDRawModule |mod| with information about the provided
+ // |mapping|. If |identifier| is non-NULL, use it instead of calculating
+ // a file ID from the mapping.
+ bool FillRawModule(const MappingInfo& mapping,
+ bool member,
+ unsigned int mapping_id,
+ MDRawModule* mod,
+ const std::vector<uint8_t>* identifier) {
+ my_memset(mod, 0, MD_MODULE_SIZE);
+
+ mod->base_of_image = mapping.start_addr;
+ mod->size_of_image = mapping.size;
+
+ auto_wasteful_vector<uint8_t, kDefaultBuildIdSize> identifier_bytes(
+ dumper_->allocator());
+
+ if (identifier) {
+ // GUID was provided by caller.
+ identifier_bytes.insert(identifier_bytes.end(),
+ identifier->begin(),
+ identifier->end());
+ } else {
+ // Note: ElfFileIdentifierForMapping() can manipulate the |mapping.name|.
+ if (!dumper_->ElfFileIdentifierForMapping(mapping,
+ member,
+ mapping_id,
+ identifier_bytes)) {
+ identifier_bytes.clear();
+ }
+ }
+
+ if (!identifier_bytes.empty()) {
+ UntypedMDRVA cv(&minidump_writer_);
+ if (!cv.Allocate(MDCVInfoELF_minsize + identifier_bytes.size()))
+ return false;
+
+ const uint32_t cv_signature = MD_CVINFOELF_SIGNATURE;
+ cv.Copy(&cv_signature, sizeof(cv_signature));
+ cv.Copy(cv.position() + sizeof(cv_signature), &identifier_bytes[0],
+ identifier_bytes.size());
+
+ mod->cv_record = cv.location();
+ }
+
+ char file_name[NAME_MAX];
+ char file_path[NAME_MAX];
+ dumper_->GetMappingEffectiveNameAndPath(
+ mapping, file_path, sizeof(file_path), file_name, sizeof(file_name));
+
+ MDLocationDescriptor ld;
+ if (!minidump_writer_.WriteString(file_path, my_strlen(file_path), &ld))
+ return false;
+ mod->module_name_rva = ld.rva;
+ return true;
+ }
+
+ bool WriteMemoryListStream(MDRawDirectory* dirent) {
+ TypedMDRVA<uint32_t> list(&minidump_writer_);
+ if (!memory_blocks_.empty()) {
+ if (!list.AllocateObjectAndArray(memory_blocks_.size(),
+ sizeof(MDMemoryDescriptor)))
+ return false;
+ } else {
+ // Still create the memory list stream, although it will have zero
+ // memory blocks.
+ if (!list.Allocate())
+ return false;
+ }
+
+ dirent->stream_type = MD_MEMORY_LIST_STREAM;
+ dirent->location = list.location();
+
+ *list.get() = memory_blocks_.size();
+
+ for (size_t i = 0; i < memory_blocks_.size(); ++i) {
+ list.CopyIndexAfterObject(i, &memory_blocks_[i],
+ sizeof(MDMemoryDescriptor));
+ }
+ return true;
+ }
+
+ bool WriteExceptionStream(MDRawDirectory* dirent) {
+ TypedMDRVA<MDRawExceptionStream> exc(&minidump_writer_);
+ if (!exc.Allocate())
+ return false;
+
+ MDRawExceptionStream* stream = exc.get();
+ my_memset(stream, 0, sizeof(MDRawExceptionStream));
+
+ dirent->stream_type = MD_EXCEPTION_STREAM;
+ dirent->location = exc.location();
+
+ stream->thread_id = GetCrashThread();
+ stream->exception_record.exception_code = dumper_->crash_signal();
+ stream->exception_record.exception_flags = dumper_->crash_signal_code();
+ stream->exception_record.exception_address = dumper_->crash_address();
+ const std::vector<uint64_t> crash_exception_info =
+ dumper_->crash_exception_info();
+ stream->exception_record.number_parameters = crash_exception_info.size();
+ memcpy(stream->exception_record.exception_information,
+ crash_exception_info.data(),
+ sizeof(uint64_t) * crash_exception_info.size());
+ stream->thread_context = crashing_thread_context_;
+
+ return true;
+ }
+
+ bool WriteSystemInfoStream(MDRawDirectory* dirent) {
+ TypedMDRVA<MDRawSystemInfo> si(&minidump_writer_);
+ if (!si.Allocate())
+ return false;
+ my_memset(si.get(), 0, sizeof(MDRawSystemInfo));
+
+ dirent->stream_type = MD_SYSTEM_INFO_STREAM;
+ dirent->location = si.location();
+
+ WriteCPUInformation(si.get());
+ WriteOSInformation(si.get());
+
+ return true;
+ }
+
+ bool WriteDSODebugStream(MDRawDirectory* dirent) {
+ ElfW(Phdr)* phdr = reinterpret_cast<ElfW(Phdr) *>(dumper_->auxv()[AT_PHDR]);
+ char* base;
+ int phnum = dumper_->auxv()[AT_PHNUM];
+ if (!phnum || !phdr)
+ return false;
+
+ // Assume the program base is at the beginning of the same page as the PHDR
+ base = reinterpret_cast<char *>(reinterpret_cast<uintptr_t>(phdr) & ~0xfff);
+
+ // Search for the program PT_DYNAMIC segment
+ ElfW(Addr) dyn_addr = 0;
+ for (; phnum >= 0; phnum--, phdr++) {
+ ElfW(Phdr) ph;
+ if (!dumper_->CopyFromProcess(&ph, dumper_->pid(), phdr, sizeof(ph)))
+ return false;
+
+ // Adjust base address with the virtual address of the PT_LOAD segment
+ // corresponding to offset 0
+ if (ph.p_type == PT_LOAD && ph.p_offset == 0) {
+ base -= ph.p_vaddr;
+ }
+ if (ph.p_type == PT_DYNAMIC) {
+ dyn_addr = ph.p_vaddr;
+ }
+ }
+ if (!dyn_addr)
+ return false;
+
+ ElfW(Dyn) *dynamic = reinterpret_cast<ElfW(Dyn) *>(dyn_addr + base);
+
+ // The dynamic linker makes information available that helps gdb find all
+ // DSOs loaded into the program. If this information is indeed available,
+ // dump it to a MD_LINUX_DSO_DEBUG stream.
+ struct r_debug* r_debug = NULL;
+ uint32_t dynamic_length = 0;
+
+ for (int i = 0; ; ++i) {
+ ElfW(Dyn) dyn;
+ dynamic_length += sizeof(dyn);
+ if (!dumper_->CopyFromProcess(&dyn, dumper_->pid(), dynamic + i, sizeof(dyn))) {
+ return false;
+ }
+
+#ifdef __mips__
+ const int32_t debug_tag = DT_MIPS_RLD_MAP;
+#else
+ const int32_t debug_tag = DT_DEBUG;
+#endif
+ if (dyn.d_tag == debug_tag) {
+ r_debug = reinterpret_cast<struct r_debug*>(dyn.d_un.d_ptr);
+ continue;
+ } else if (dyn.d_tag == DT_NULL) {
+ break;
+ }
+ }
+
+ // The "r_map" field of that r_debug struct contains a linked list of all
+ // loaded DSOs.
+ // Our list of DSOs potentially is different from the ones in the crashing
+ // process. So, we have to be careful to never dereference pointers
+ // directly. Instead, we use CopyFromProcess() everywhere.
+ // See <link.h> for a more detailed discussion of the how the dynamic
+ // loader communicates with debuggers.
+
+ // Count the number of loaded DSOs
+ int dso_count = 0;
+ struct r_debug debug_entry;
+ if (!dumper_->CopyFromProcess(&debug_entry, dumper_->pid(), r_debug,
+ sizeof(debug_entry))) {
+ return false;
+ }
+ for (struct link_map* ptr = debug_entry.r_map; ptr; ) {
+ struct link_map map;
+ if (!dumper_->CopyFromProcess(&map, dumper_->pid(), ptr, sizeof(map)))
+ return false;
+
+ ptr = map.l_next;
+ dso_count++;
+ }
+
+ MDRVA linkmap_rva = MinidumpFileWriter::kInvalidMDRVA;
+ if (dso_count > 0) {
+ // If we have at least one DSO, create an array of MDRawLinkMap
+ // entries in the minidump file.
+ TypedMDRVA<MDRawLinkMap> linkmap(&minidump_writer_);
+ if (!linkmap.AllocateArray(dso_count))
+ return false;
+ linkmap_rva = linkmap.location().rva;
+ int idx = 0;
+
+ // Iterate over DSOs and write their information to mini dump
+ for (struct link_map* ptr = debug_entry.r_map; ptr; ) {
+ struct link_map map;
+ if (!dumper_->CopyFromProcess(&map, dumper_->pid(), ptr, sizeof(map)))
+ return false;
+
+ ptr = map.l_next;
+ char filename[257] = { 0 };
+ if (map.l_name) {
+ dumper_->CopyFromProcess(filename, dumper_->pid(), map.l_name,
+ sizeof(filename) - 1);
+ }
+ MDLocationDescriptor location;
+ if (!minidump_writer_.WriteString(filename, 0, &location))
+ return false;
+ MDRawLinkMap entry;
+ entry.name = location.rva;
+ entry.addr = map.l_addr;
+ entry.ld = reinterpret_cast<uintptr_t>(map.l_ld);
+ linkmap.CopyIndex(idx++, &entry);
+ }
+ }
+
+ // Write MD_LINUX_DSO_DEBUG record
+ TypedMDRVA<MDRawDebug> debug(&minidump_writer_);
+ if (!debug.AllocateObjectAndArray(1, dynamic_length))
+ return false;
+ my_memset(debug.get(), 0, sizeof(MDRawDebug));
+ dirent->stream_type = MD_LINUX_DSO_DEBUG;
+ dirent->location = debug.location();
+
+ debug.get()->version = debug_entry.r_version;
+ debug.get()->map = linkmap_rva;
+ debug.get()->dso_count = dso_count;
+ debug.get()->brk = debug_entry.r_brk;
+ debug.get()->ldbase = debug_entry.r_ldbase;
+ debug.get()->dynamic = reinterpret_cast<uintptr_t>(dynamic);
+
+ wasteful_vector<char> dso_debug_data(dumper_->allocator(), dynamic_length);
+ // The passed-in size to the constructor (above) is only a hint.
+ // Must call .resize() to do actual initialization of the elements.
+ dso_debug_data.resize(dynamic_length);
+ dumper_->CopyFromProcess(&dso_debug_data[0], dumper_->pid(), dynamic,
+ dynamic_length);
+ debug.CopyIndexAfterObject(0, &dso_debug_data[0], dynamic_length);
+
+ return true;
+ }
+
+ void set_minidump_size_limit(off_t limit) { minidump_size_limit_ = limit; }
+
+ private:
+ void* Alloc(unsigned bytes) {
+ return dumper_->allocator()->Alloc(bytes);
+ }
+
+ pid_t GetCrashThread() const {
+ return dumper_->crash_thread();
+ }
+
+ void NullifyDirectoryEntry(MDRawDirectory* dirent) {
+ dirent->stream_type = 0;
+ dirent->location.data_size = 0;
+ dirent->location.rva = 0;
+ }
+
+#if defined(__i386__) || defined(__x86_64__) || defined(__mips__)
+ bool WriteCPUInformation(MDRawSystemInfo* sys_info) {
+ char vendor_id[sizeof(sys_info->cpu.x86_cpu_info.vendor_id) + 1] = {0};
+ static const char vendor_id_name[] = "vendor_id";
+
+ struct CpuInfoEntry {
+ const char* info_name;
+ int value;
+ bool found;
+ } cpu_info_table[] = {
+ { "processor", -1, false },
+#if defined(__i386__) || defined(__x86_64__)
+ { "model", 0, false },
+ { "stepping", 0, false },
+ { "cpu family", 0, false },
+#endif
+ };
+
+ // processor_architecture should always be set, do this first
+ sys_info->processor_architecture =
+#if defined(__mips__)
+# if _MIPS_SIM == _ABIO32
+ MD_CPU_ARCHITECTURE_MIPS;
+# elif _MIPS_SIM == _ABI64
+ MD_CPU_ARCHITECTURE_MIPS64;
+# else
+# error "This mips ABI is currently not supported (n32)"
+#endif
+#elif defined(__i386__)
+ MD_CPU_ARCHITECTURE_X86;
+#else
+ MD_CPU_ARCHITECTURE_AMD64;
+#endif
+
+ const int fd = sys_open("/proc/cpuinfo", O_RDONLY, 0);
+ if (fd < 0)
+ return false;
+
+ {
+ PageAllocator allocator;
+ ProcCpuInfoReader* const reader = new(allocator) ProcCpuInfoReader(fd);
+ const char* field;
+ while (reader->GetNextField(&field)) {
+ bool is_first_entry = true;
+ for (CpuInfoEntry& entry : cpu_info_table) {
+ if (!is_first_entry && entry.found) {
+ // except for the 'processor' field, ignore repeated values.
+ continue;
+ }
+ is_first_entry = false;
+ if (!my_strcmp(field, entry.info_name)) {
+ size_t value_len;
+ const char* value = reader->GetValueAndLen(&value_len);
+ if (value_len == 0)
+ continue;
+
+ uintptr_t val;
+ if (my_read_decimal_ptr(&val, value) == value)
+ continue;
+
+ entry.value = static_cast<int>(val);
+ entry.found = true;
+ }
+ }
+
+ // special case for vendor_id
+ if (!my_strcmp(field, vendor_id_name)) {
+ size_t value_len;
+ const char* value = reader->GetValueAndLen(&value_len);
+ if (value_len > 0)
+ my_strlcpy(vendor_id, value, sizeof(vendor_id));
+ }
+ }
+ sys_close(fd);
+ }
+
+ // make sure we got everything we wanted
+ for (const CpuInfoEntry& entry : cpu_info_table) {
+ if (!entry.found) {
+ return false;
+ }
+ }
+ // cpu_info_table[0] holds the last cpu id listed in /proc/cpuinfo,
+ // assuming this is the highest id, change it to the number of CPUs
+ // by adding one.
+ cpu_info_table[0].value++;
+
+ sys_info->number_of_processors = cpu_info_table[0].value;
+#if defined(__i386__) || defined(__x86_64__)
+ sys_info->processor_level = cpu_info_table[3].value;
+ sys_info->processor_revision = cpu_info_table[1].value << 8 |
+ cpu_info_table[2].value;
+#endif
+
+ if (vendor_id[0] != '\0') {
+ my_memcpy(sys_info->cpu.x86_cpu_info.vendor_id, vendor_id,
+ sizeof(sys_info->cpu.x86_cpu_info.vendor_id));
+ }
+ return true;
+ }
+#elif defined(__arm__) || defined(__aarch64__)
+ bool WriteCPUInformation(MDRawSystemInfo* sys_info) {
+ // The CPUID value is broken up in several entries in /proc/cpuinfo.
+ // This table is used to rebuild it from the entries.
+ const struct CpuIdEntry {
+ const char* field;
+ char format;
+ char bit_lshift;
+ char bit_length;
+ } cpu_id_entries[] = {
+ { "CPU implementer", 'x', 24, 8 },
+ { "CPU variant", 'x', 20, 4 },
+ { "CPU part", 'x', 4, 12 },
+ { "CPU revision", 'd', 0, 4 },
+ };
+
+ // The ELF hwcaps are listed in the "Features" entry as textual tags.
+ // This table is used to rebuild them.
+ const struct CpuFeaturesEntry {
+ const char* tag;
+ uint32_t hwcaps;
+ } cpu_features_entries[] = {
+#if defined(__arm__)
+ { "swp", MD_CPU_ARM_ELF_HWCAP_SWP },
+ { "half", MD_CPU_ARM_ELF_HWCAP_HALF },
+ { "thumb", MD_CPU_ARM_ELF_HWCAP_THUMB },
+ { "26bit", MD_CPU_ARM_ELF_HWCAP_26BIT },
+ { "fastmult", MD_CPU_ARM_ELF_HWCAP_FAST_MULT },
+ { "fpa", MD_CPU_ARM_ELF_HWCAP_FPA },
+ { "vfp", MD_CPU_ARM_ELF_HWCAP_VFP },
+ { "edsp", MD_CPU_ARM_ELF_HWCAP_EDSP },
+ { "java", MD_CPU_ARM_ELF_HWCAP_JAVA },
+ { "iwmmxt", MD_CPU_ARM_ELF_HWCAP_IWMMXT },
+ { "crunch", MD_CPU_ARM_ELF_HWCAP_CRUNCH },
+ { "thumbee", MD_CPU_ARM_ELF_HWCAP_THUMBEE },
+ { "neon", MD_CPU_ARM_ELF_HWCAP_NEON },
+ { "vfpv3", MD_CPU_ARM_ELF_HWCAP_VFPv3 },
+ { "vfpv3d16", MD_CPU_ARM_ELF_HWCAP_VFPv3D16 },
+ { "tls", MD_CPU_ARM_ELF_HWCAP_TLS },
+ { "vfpv4", MD_CPU_ARM_ELF_HWCAP_VFPv4 },
+ { "idiva", MD_CPU_ARM_ELF_HWCAP_IDIVA },
+ { "idivt", MD_CPU_ARM_ELF_HWCAP_IDIVT },
+ { "idiv", MD_CPU_ARM_ELF_HWCAP_IDIVA | MD_CPU_ARM_ELF_HWCAP_IDIVT },
+#elif defined(__aarch64__)
+ // No hwcaps on aarch64.
+#endif
+ };
+
+ // processor_architecture should always be set, do this first
+ sys_info->processor_architecture =
+#if defined(__aarch64__)
+ MD_CPU_ARCHITECTURE_ARM64_OLD;
+#else
+ MD_CPU_ARCHITECTURE_ARM;
+#endif
+
+ // /proc/cpuinfo is not readable under various sandboxed environments
+ // (e.g. Android services with the android:isolatedProcess attribute)
+ // prepare for this by setting default values now, which will be
+ // returned when this happens.
+ //
+ // Note: Bogus values are used to distinguish between failures (to
+ // read /sys and /proc files) and really badly configured kernels.
+ sys_info->number_of_processors = 0;
+ sys_info->processor_level = 1U; // There is no ARMv1
+ sys_info->processor_revision = 42;
+ sys_info->cpu.arm_cpu_info.cpuid = 0;
+ sys_info->cpu.arm_cpu_info.elf_hwcaps = 0;
+
+ // Counting the number of CPUs involves parsing two sysfs files,
+ // because the content of /proc/cpuinfo will only mirror the number
+ // of 'online' cores, and thus will vary with time.
+ // See http://www.kernel.org/doc/Documentation/cputopology.txt
+ {
+ CpuSet cpus_present;
+ CpuSet cpus_possible;
+
+ int fd = sys_open("/sys/devices/system/cpu/present", O_RDONLY, 0);
+ if (fd >= 0) {
+ cpus_present.ParseSysFile(fd);
+ sys_close(fd);
+
+ fd = sys_open("/sys/devices/system/cpu/possible", O_RDONLY, 0);
+ if (fd >= 0) {
+ cpus_possible.ParseSysFile(fd);
+ sys_close(fd);
+
+ cpus_present.IntersectWith(cpus_possible);
+ int cpu_count = cpus_present.GetCount();
+ if (cpu_count > 255)
+ cpu_count = 255;
+ sys_info->number_of_processors = static_cast<uint8_t>(cpu_count);
+ }
+ }
+ }
+
+ // Parse /proc/cpuinfo to reconstruct the CPUID value, as well
+ // as the ELF hwcaps field. For the latter, it would be easier to
+ // read /proc/self/auxv but unfortunately, this file is not always
+ // readable from regular Android applications on later versions
+ // (>= 4.1) of the Android platform.
+ const int fd = sys_open("/proc/cpuinfo", O_RDONLY, 0);
+ if (fd < 0) {
+ // Do not return false here to allow the minidump generation
+ // to happen properly.
+ return true;
+ }
+
+ {
+ PageAllocator allocator;
+ ProcCpuInfoReader* const reader =
+ new(allocator) ProcCpuInfoReader(fd);
+ const char* field;
+ while (reader->GetNextField(&field)) {
+ for (const CpuIdEntry& entry : cpu_id_entries) {
+ if (my_strcmp(entry.field, field) != 0)
+ continue;
+ uintptr_t result = 0;
+ const char* value = reader->GetValue();
+ const char* p = value;
+ if (value[0] == '0' && value[1] == 'x') {
+ p = my_read_hex_ptr(&result, value+2);
+ } else if (entry.format == 'x') {
+ p = my_read_hex_ptr(&result, value);
+ } else {
+ p = my_read_decimal_ptr(&result, value);
+ }
+ if (p == value)
+ continue;
+
+ result &= (1U << entry.bit_length)-1;
+ result <<= entry.bit_lshift;
+ sys_info->cpu.arm_cpu_info.cpuid |=
+ static_cast<uint32_t>(result);
+ }
+#if defined(__arm__)
+ // Get the architecture version from the "Processor" field.
+ // Note that it is also available in the "CPU architecture" field,
+ // however, some existing kernels are misconfigured and will report
+ // invalid values here (e.g. 6, while the CPU is ARMv7-A based).
+ // The "Processor" field doesn't have this issue.
+ if (!my_strcmp(field, "Processor")) {
+ size_t value_len;
+ const char* value = reader->GetValueAndLen(&value_len);
+ // Expected format: <text> (v<level><endian>)
+ // Where <text> is some text like "ARMv7 Processor rev 2"
+ // and <level> is a decimal corresponding to the ARM
+ // architecture number. <endian> is either 'l' or 'b'
+ // and corresponds to the endianess, it is ignored here.
+ while (value_len > 0 && my_isspace(value[value_len-1]))
+ value_len--;
+
+ size_t nn = value_len;
+ while (nn > 0 && value[nn-1] != '(')
+ nn--;
+ if (nn > 0 && value[nn] == 'v') {
+ uintptr_t arch_level = 5;
+ my_read_decimal_ptr(&arch_level, value + nn + 1);
+ sys_info->processor_level = static_cast<uint16_t>(arch_level);
+ }
+ }
+#elif defined(__aarch64__)
+ // The aarch64 architecture does not provide the architecture level
+ // in the Processor field, so we instead check the "CPU architecture"
+ // field.
+ if (!my_strcmp(field, "CPU architecture")) {
+ uintptr_t arch_level = 0;
+ const char* value = reader->GetValue();
+ const char* p = value;
+ p = my_read_decimal_ptr(&arch_level, value);
+ if (p == value)
+ continue;
+ sys_info->processor_level = static_cast<uint16_t>(arch_level);
+ }
+#endif
+ // Rebuild the ELF hwcaps from the 'Features' field.
+ if (!my_strcmp(field, "Features")) {
+ size_t value_len;
+ const char* value = reader->GetValueAndLen(&value_len);
+
+ // Parse each space-separated tag.
+ while (value_len > 0) {
+ const char* tag = value;
+ size_t tag_len = value_len;
+ const char* p = my_strchr(tag, ' ');
+ if (p) {
+ tag_len = static_cast<size_t>(p - tag);
+ value += tag_len + 1;
+ value_len -= tag_len + 1;
+ } else {
+ tag_len = strlen(tag);
+ value_len = 0;
+ }
+ for (const CpuFeaturesEntry& entry : cpu_features_entries) {
+ if (tag_len == strlen(entry.tag) &&
+ !memcmp(tag, entry.tag, tag_len)) {
+ sys_info->cpu.arm_cpu_info.elf_hwcaps |= entry.hwcaps;
+ break;
+ }
+ }
+ }
+ }
+ }
+ sys_close(fd);
+ }
+
+ return true;
+ }
+#else
+# error "Unsupported CPU"
+#endif
+
+ bool WriteFile(MDLocationDescriptor* result, const char* filename) {
+ const int fd = sys_open(filename, O_RDONLY, 0);
+ if (fd < 0)
+ return false;
+
+ // We can't stat the files because several of the files that we want to
+ // read are kernel seqfiles, which always have a length of zero. So we have
+ // to read as much as we can into a buffer.
+ static const unsigned kBufSize = 1024 - 2*sizeof(void*);
+ struct Buffers {
+ Buffers* next;
+ size_t len;
+ uint8_t data[kBufSize];
+ } *buffers = reinterpret_cast<Buffers*>(Alloc(sizeof(Buffers)));
+ buffers->next = NULL;
+ buffers->len = 0;
+
+ size_t total = 0;
+ for (Buffers* bufptr = buffers;;) {
+ ssize_t r;
+ do {
+ r = sys_read(fd, &bufptr->data[bufptr->len], kBufSize - bufptr->len);
+ } while (r == -1 && errno == EINTR);
+
+ if (r < 1)
+ break;
+
+ total += r;
+ bufptr->len += r;
+ if (bufptr->len == kBufSize) {
+ bufptr->next = reinterpret_cast<Buffers*>(Alloc(sizeof(Buffers)));
+ bufptr = bufptr->next;
+ bufptr->next = NULL;
+ bufptr->len = 0;
+ }
+ }
+ sys_close(fd);
+
+ if (!total)
+ return false;
+
+ UntypedMDRVA memory(&minidump_writer_);
+ if (!memory.Allocate(total))
+ return false;
+ for (MDRVA pos = memory.position(); buffers; buffers = buffers->next) {
+ // Check for special case of a zero-length buffer. This should only
+ // occur if a file's size happens to be a multiple of the buffer's
+ // size, in which case the final sys_read() will have resulted in
+ // zero bytes being read after the final buffer was just allocated.
+ if (buffers->len == 0) {
+ // This can only occur with final buffer.
+ assert(buffers->next == NULL);
+ continue;
+ }
+ memory.Copy(pos, &buffers->data, buffers->len);
+ pos += buffers->len;
+ }
+ *result = memory.location();
+ return true;
+ }
+
+ bool WriteOSInformation(MDRawSystemInfo* sys_info) {
+#if defined(__ANDROID__)
+ sys_info->platform_id = MD_OS_ANDROID;
+#else
+ sys_info->platform_id = MD_OS_LINUX;
+#endif
+
+ struct utsname uts;
+ if (uname(&uts))
+ return false;
+
+ static const size_t buf_len = 512;
+ char buf[buf_len] = {0};
+ size_t space_left = buf_len - 1;
+ const char* info_table[] = {
+ uts.sysname,
+ uts.release,
+ uts.version,
+ uts.machine,
+ NULL
+ };
+ bool first_item = true;
+ for (const char** cur_info = info_table; *cur_info; cur_info++) {
+ static const char separator[] = " ";
+ size_t separator_len = sizeof(separator) - 1;
+ size_t info_len = my_strlen(*cur_info);
+ if (info_len == 0)
+ continue;
+
+ if (space_left < info_len + (first_item ? 0 : separator_len))
+ break;
+
+ if (!first_item) {
+ my_strlcat(buf, separator, sizeof(buf));
+ space_left -= separator_len;
+ }
+
+ first_item = false;
+ my_strlcat(buf, *cur_info, sizeof(buf));
+ space_left -= info_len;
+ }
+
+ MDLocationDescriptor location;
+ if (!minidump_writer_.WriteString(buf, 0, &location))
+ return false;
+ sys_info->csd_version_rva = location.rva;
+
+ return true;
+ }
+
+ bool WriteProcFile(MDLocationDescriptor* result, pid_t pid,
+ const char* filename) {
+ char buf[NAME_MAX];
+ if (!dumper_->BuildProcPath(buf, pid, filename))
+ return false;
+ return WriteFile(result, buf);
+ }
+
+ // Only one of the 2 member variables below should be set to a valid value.
+ const int fd_; // File descriptor where the minidum should be written.
+ const char* path_; // Path to the file where the minidum should be written.
+
+ const ucontext_t* const ucontext_; // also from the signal handler
+#if !defined(__ARM_EABI__) && !defined(__mips__)
+ const google_breakpad::fpstate_t* const float_state_; // ditto
+#endif
+ LinuxDumper* dumper_;
+ MinidumpFileWriter minidump_writer_;
+ off_t minidump_size_limit_;
+ MDLocationDescriptor crashing_thread_context_;
+ // Blocks of memory written to the dump. These are all currently
+ // written while writing the thread list stream, but saved here
+ // so a memory list stream can be written afterwards.
+ wasteful_vector<MDMemoryDescriptor> memory_blocks_;
+ // Additional information about some mappings provided by the caller.
+ const MappingList& mapping_list_;
+ // Additional memory regions to be included in the dump,
+ // provided by the caller.
+ const AppMemoryList& app_memory_list_;
+ // If set, skip recording any threads that do not reference the
+ // mapping containing principal_mapping_address_.
+ bool skip_stacks_if_mapping_unreferenced_;
+ uintptr_t principal_mapping_address_;
+ const MappingInfo* principal_mapping_;
+ // If true, apply stack sanitization to stored stack data.
+ bool sanitize_stacks_;
+};
+
+
+bool WriteMinidumpImpl(const char* minidump_path,
+ int minidump_fd,
+ off_t minidump_size_limit,
+ pid_t crashing_process,
+ const void* blob, size_t blob_size,
+ const MappingList& mappings,
+ const AppMemoryList& appmem,
+ bool skip_stacks_if_mapping_unreferenced,
+ uintptr_t principal_mapping_address,
+ bool sanitize_stacks) {
+ LinuxPtraceDumper dumper(crashing_process);
+ const ExceptionHandler::CrashContext* context = NULL;
+ if (blob) {
+ if (blob_size != sizeof(ExceptionHandler::CrashContext))
+ return false;
+ context = reinterpret_cast<const ExceptionHandler::CrashContext*>(blob);
+ dumper.SetCrashInfoFromSigInfo(context->siginfo);
+ dumper.set_crash_thread(context->tid);
+ }
+ MinidumpWriter writer(minidump_path, minidump_fd, context, mappings,
+ appmem, skip_stacks_if_mapping_unreferenced,
+ principal_mapping_address, sanitize_stacks, &dumper);
+ // Set desired limit for file size of minidump (-1 means no limit).
+ writer.set_minidump_size_limit(minidump_size_limit);
+ if (!writer.Init())
+ return false;
+ return writer.Dump();
+}
+
+} // namespace
+
+namespace google_breakpad {
+
+bool WriteMinidump(const char* minidump_path, pid_t crashing_process,
+ const void* blob, size_t blob_size,
+ bool skip_stacks_if_mapping_unreferenced,
+ uintptr_t principal_mapping_address,
+ bool sanitize_stacks) {
+ return WriteMinidumpImpl(minidump_path, -1, -1,
+ crashing_process, blob, blob_size,
+ MappingList(), AppMemoryList(),
+ skip_stacks_if_mapping_unreferenced,
+ principal_mapping_address,
+ sanitize_stacks);
+}
+
+bool WriteMinidump(int minidump_fd, pid_t crashing_process,
+ const void* blob, size_t blob_size,
+ bool skip_stacks_if_mapping_unreferenced,
+ uintptr_t principal_mapping_address,
+ bool sanitize_stacks) {
+ return WriteMinidumpImpl(NULL, minidump_fd, -1,
+ crashing_process, blob, blob_size,
+ MappingList(), AppMemoryList(),
+ skip_stacks_if_mapping_unreferenced,
+ principal_mapping_address,
+ sanitize_stacks);
+}
+
+bool WriteMinidump(const char* minidump_path, pid_t process,
+ pid_t process_blamed_thread) {
+ LinuxPtraceDumper dumper(process);
+ // MinidumpWriter will set crash address
+ dumper.set_crash_signal(MD_EXCEPTION_CODE_LIN_DUMP_REQUESTED);
+ dumper.set_crash_thread(process_blamed_thread);
+ MappingList mapping_list;
+ AppMemoryList app_memory_list;
+ MinidumpWriter writer(minidump_path, -1, NULL, mapping_list,
+ app_memory_list, false, 0, false, &dumper);
+ if (!writer.Init())
+ return false;
+ return writer.Dump();
+}
+
+bool WriteMinidump(const char* minidump_path, pid_t crashing_process,
+ const void* blob, size_t blob_size,
+ const MappingList& mappings,
+ const AppMemoryList& appmem,
+ bool skip_stacks_if_mapping_unreferenced,
+ uintptr_t principal_mapping_address,
+ bool sanitize_stacks) {
+ return WriteMinidumpImpl(minidump_path, -1, -1, crashing_process,
+ blob, blob_size,
+ mappings, appmem,
+ skip_stacks_if_mapping_unreferenced,
+ principal_mapping_address,
+ sanitize_stacks);
+}
+
+bool WriteMinidump(int minidump_fd, pid_t crashing_process,
+ const void* blob, size_t blob_size,
+ const MappingList& mappings,
+ const AppMemoryList& appmem,
+ bool skip_stacks_if_mapping_unreferenced,
+ uintptr_t principal_mapping_address,
+ bool sanitize_stacks) {
+ return WriteMinidumpImpl(NULL, minidump_fd, -1, crashing_process,
+ blob, blob_size,
+ mappings, appmem,
+ skip_stacks_if_mapping_unreferenced,
+ principal_mapping_address,
+ sanitize_stacks);
+}
+
+bool WriteMinidump(const char* minidump_path, off_t minidump_size_limit,
+ pid_t crashing_process,
+ const void* blob, size_t blob_size,
+ const MappingList& mappings,
+ const AppMemoryList& appmem,
+ bool skip_stacks_if_mapping_unreferenced,
+ uintptr_t principal_mapping_address,
+ bool sanitize_stacks) {
+ return WriteMinidumpImpl(minidump_path, -1, minidump_size_limit,
+ crashing_process, blob, blob_size,
+ mappings, appmem,
+ skip_stacks_if_mapping_unreferenced,
+ principal_mapping_address,
+ sanitize_stacks);
+}
+
+bool WriteMinidump(int minidump_fd, off_t minidump_size_limit,
+ pid_t crashing_process,
+ const void* blob, size_t blob_size,
+ const MappingList& mappings,
+ const AppMemoryList& appmem,
+ bool skip_stacks_if_mapping_unreferenced,
+ uintptr_t principal_mapping_address,
+ bool sanitize_stacks) {
+ return WriteMinidumpImpl(NULL, minidump_fd, minidump_size_limit,
+ crashing_process, blob, blob_size,
+ mappings, appmem,
+ skip_stacks_if_mapping_unreferenced,
+ principal_mapping_address,
+ sanitize_stacks);
+}
+
+bool WriteMinidump(const char* filename,
+ const MappingList& mappings,
+ const AppMemoryList& appmem,
+ LinuxDumper* dumper) {
+ MinidumpWriter writer(filename, -1, NULL, mappings, appmem,
+ false, 0, false, dumper);
+ if (!writer.Init())
+ return false;
+ return writer.Dump();
+}
+
+} // namespace google_breakpad
diff --git a/toolkit/crashreporter/breakpad-client/linux/minidump_writer/minidump_writer.h b/toolkit/crashreporter/breakpad-client/linux/minidump_writer/minidump_writer.h
new file mode 100644
index 0000000000..1d02ec8d7d
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/linux/minidump_writer/minidump_writer.h
@@ -0,0 +1,143 @@
+// 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 CLIENT_LINUX_MINIDUMP_WRITER_MINIDUMP_WRITER_H_
+#define CLIENT_LINUX_MINIDUMP_WRITER_MINIDUMP_WRITER_H_
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <sys/ucontext.h>
+#include <unistd.h>
+
+#include <list>
+#include <type_traits>
+#include <utility>
+
+#include "linux/minidump_writer/linux_dumper.h"
+#include "google_breakpad/common/minidump_format.h"
+
+namespace google_breakpad {
+
+class ExceptionHandler;
+
+#if defined(__aarch64__)
+typedef struct fpsimd_context fpstate_t;
+#elif !defined(__ARM_EABI__) && !defined(__mips__)
+typedef std::remove_pointer<fpregset_t>::type fpstate_t;
+#endif
+
+// These entries store a list of memory regions that the client wants included
+// in the minidump.
+struct AppMemory {
+ void* ptr;
+ size_t length;
+
+ bool operator==(const struct AppMemory& other) const {
+ return ptr == other.ptr;
+ }
+
+ bool operator==(const void* other) const {
+ return ptr == other;
+ }
+};
+typedef std::list<AppMemory> AppMemoryList;
+
+// Writes a minidump to the filesystem. These functions do not malloc nor use
+// libc functions which may. Thus, it can be used in contexts where the state
+// of the heap may be corrupt.
+// minidump_path: the path to the file to write to. This is opened O_EXCL and
+// fails open fails.
+// crashing_process: the pid of the crashing process. This must be trusted.
+// blob: a blob of data from the crashing process. See exception_handler.h
+// blob_size: the length of |blob|, in bytes
+//
+// Returns true iff successful.
+bool WriteMinidump(const char* minidump_path, pid_t crashing_process,
+ const void* blob, size_t blob_size,
+ bool skip_stacks_if_mapping_unreferenced = false,
+ uintptr_t principal_mapping_address = 0,
+ bool sanitize_stacks = false);
+// Same as above but takes an open file descriptor instead of a path.
+bool WriteMinidump(int minidump_fd, pid_t crashing_process,
+ const void* blob, size_t blob_size,
+ bool skip_stacks_if_mapping_unreferenced = false,
+ uintptr_t principal_mapping_address = 0,
+ bool sanitize_stacks = false);
+
+// Alternate form of WriteMinidump() that works with processes that
+// are not expected to have crashed. If |process_blamed_thread| is
+// meaningful, it will be the one from which a crash signature is
+// extracted. It is not expected that this function will be called
+// from a compromised context, but it is safe to do so.
+bool WriteMinidump(const char* minidump_path, pid_t process,
+ pid_t process_blamed_thread);
+
+// These overloads also allow passing a list of known mappings and
+// a list of additional memory regions to be included in the minidump.
+bool WriteMinidump(const char* minidump_path, pid_t crashing_process,
+ const void* blob, size_t blob_size,
+ const MappingList& mappings,
+ const AppMemoryList& appdata,
+ bool skip_stacks_if_mapping_unreferenced = false,
+ uintptr_t principal_mapping_address = 0,
+ bool sanitize_stacks = false);
+bool WriteMinidump(int minidump_fd, pid_t crashing_process,
+ const void* blob, size_t blob_size,
+ const MappingList& mappings,
+ const AppMemoryList& appdata,
+ bool skip_stacks_if_mapping_unreferenced = false,
+ uintptr_t principal_mapping_address = 0,
+ bool sanitize_stacks = false);
+
+// These overloads also allow passing a file size limit for the minidump.
+bool WriteMinidump(const char* minidump_path, off_t minidump_size_limit,
+ pid_t crashing_process,
+ const void* blob, size_t blob_size,
+ const MappingList& mappings,
+ const AppMemoryList& appdata,
+ bool skip_stacks_if_mapping_unreferenced = false,
+ uintptr_t principal_mapping_address = 0,
+ bool sanitize_stacks = false);
+bool WriteMinidump(int minidump_fd, off_t minidump_size_limit,
+ pid_t crashing_process,
+ const void* blob, size_t blob_size,
+ const MappingList& mappings,
+ const AppMemoryList& appdata,
+ bool skip_stacks_if_mapping_unreferenced = false,
+ uintptr_t principal_mapping_address = 0,
+ bool sanitize_stacks = false);
+
+bool WriteMinidump(const char* filename,
+ const MappingList& mappings,
+ const AppMemoryList& appdata,
+ LinuxDumper* dumper);
+
+} // namespace google_breakpad
+
+#endif // CLIENT_LINUX_MINIDUMP_WRITER_MINIDUMP_WRITER_H_
diff --git a/toolkit/crashreporter/breakpad-client/linux/minidump_writer/minidump_writer_unittest.cc b/toolkit/crashreporter/breakpad-client/linux/minidump_writer/minidump_writer_unittest.cc
new file mode 100644
index 0000000000..4e49a4e577
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/linux/minidump_writer/minidump_writer_unittest.cc
@@ -0,0 +1,934 @@
+// 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.
+
+#include <fcntl.h>
+#include <poll.h>
+#include <sys/stat.h>
+#include <sys/syscall.h>
+#include <sys/types.h>
+#include <ucontext.h>
+#include <unistd.h>
+
+#include <string>
+
+#include "breakpad_googletest_includes.h"
+#include "linux/handler/exception_handler.h"
+#include "linux/minidump_writer/linux_dumper.h"
+#include "linux/minidump_writer/minidump_writer.h"
+#include "linux/minidump_writer/minidump_writer_unittest_utils.h"
+#include "common/linux/breakpad_getcontext.h"
+#include "common/linux/eintr_wrapper.h"
+#include "common/linux/file_id.h"
+#include "common/linux/ignore_ret.h"
+#include "common/linux/safe_readlink.h"
+#include "common/scoped_ptr.h"
+#include "common/tests/auto_tempdir.h"
+#include "common/tests/file_utils.h"
+#include "common/using_std_string.h"
+#include "google_breakpad/processor/minidump.h"
+
+using namespace google_breakpad;
+
+namespace {
+
+typedef testing::Test MinidumpWriterTest;
+
+const char kMDWriterUnitTestFileName[] = "/minidump-writer-unittest";
+
+TEST(MinidumpWriterTest, SetupWithPath) {
+ int fds[2];
+ ASSERT_NE(-1, pipe(fds));
+
+ const pid_t child = fork();
+ if (child == 0) {
+ close(fds[1]);
+ char b;
+ IGNORE_RET(HANDLE_EINTR(read(fds[0], &b, sizeof(b))));
+ close(fds[0]);
+ syscall(__NR_exit_group);
+ }
+ close(fds[0]);
+
+ ExceptionHandler::CrashContext context;
+ memset(&context, 0, sizeof(context));
+
+ AutoTempDir temp_dir;
+ string templ = temp_dir.path() + kMDWriterUnitTestFileName;
+ // Set a non-zero tid to avoid tripping asserts.
+ context.tid = child;
+ ASSERT_TRUE(WriteMinidump(templ.c_str(), child, &context, sizeof(context)));
+ struct stat st;
+ ASSERT_EQ(0, stat(templ.c_str(), &st));
+ ASSERT_GT(st.st_size, 0);
+
+ close(fds[1]);
+ IGNORE_EINTR(waitpid(child, nullptr, 0));
+}
+
+TEST(MinidumpWriterTest, SetupWithFD) {
+ int fds[2];
+ ASSERT_NE(-1, pipe(fds));
+
+ const pid_t child = fork();
+ if (child == 0) {
+ close(fds[1]);
+ char b;
+ HANDLE_EINTR(read(fds[0], &b, sizeof(b)));
+ close(fds[0]);
+ syscall(__NR_exit_group);
+ }
+ close(fds[0]);
+
+ ExceptionHandler::CrashContext context;
+ memset(&context, 0, sizeof(context));
+
+ AutoTempDir temp_dir;
+ string templ = temp_dir.path() + kMDWriterUnitTestFileName;
+ int fd = open(templ.c_str(), O_CREAT | O_WRONLY, S_IRWXU);
+ // Set a non-zero tid to avoid tripping asserts.
+ context.tid = child;
+ ASSERT_TRUE(WriteMinidump(fd, child, &context, sizeof(context)));
+ struct stat st;
+ ASSERT_EQ(0, stat(templ.c_str(), &st));
+ ASSERT_GT(st.st_size, 0);
+
+ close(fds[1]);
+ IGNORE_EINTR(waitpid(child, nullptr, 0));
+}
+
+// Test that mapping info can be specified when writing a minidump,
+// and that it ends up in the module list of the minidump.
+TEST(MinidumpWriterTest, MappingInfo) {
+ int fds[2];
+ ASSERT_NE(-1, pipe(fds));
+
+ // These are defined here so the parent can use them to check the
+ // data from the minidump afterwards.
+ const uint32_t memory_size = sysconf(_SC_PAGESIZE);
+ const char* kMemoryName = "a fake module";
+ const uint8_t kModuleGUID[sizeof(MDGUID)] = {
+ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+ 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF
+ };
+ const string module_identifier = "33221100554477668899AABBCCDDEEFF0";
+
+ // Get some memory.
+ char* memory =
+ reinterpret_cast<char*>(mmap(NULL,
+ memory_size,
+ PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANON,
+ -1,
+ 0));
+ const uintptr_t kMemoryAddress = reinterpret_cast<uintptr_t>(memory);
+ ASSERT_TRUE(memory);
+
+ const pid_t child = fork();
+ if (child == 0) {
+ close(fds[1]);
+ char b;
+ IGNORE_RET(HANDLE_EINTR(read(fds[0], &b, sizeof(b))));
+ close(fds[0]);
+ syscall(__NR_exit_group);
+ }
+ close(fds[0]);
+
+ ExceptionHandler::CrashContext context;
+ memset(&context, 0, sizeof(context));
+ ASSERT_EQ(0, getcontext(&context.context));
+ context.tid = child;
+
+ AutoTempDir temp_dir;
+ string templ = temp_dir.path() + kMDWriterUnitTestFileName;
+
+ // Add information about the mapped memory.
+ MappingInfo info;
+ info.start_addr = kMemoryAddress;
+ info.size = memory_size;
+ info.offset = 0;
+ info.exec = false;
+ strcpy(info.name, kMemoryName);
+
+ MappingList mappings;
+ AppMemoryList memory_list;
+ MappingEntry mapping;
+ mapping.first = info;
+ mapping.second.assign(std::begin(kModuleGUID), std::end(kModuleGUID));
+ mappings.push_back(mapping);
+ ASSERT_TRUE(WriteMinidump(templ.c_str(), child, &context, sizeof(context),
+ mappings, memory_list, false, 0, false));
+
+ // Read the minidump. Load the module list, and ensure that
+ // the mmap'ed |memory| is listed with the given module name
+ // and debug ID.
+ Minidump minidump(templ);
+ ASSERT_TRUE(minidump.Read());
+
+ MinidumpModuleList* module_list = minidump.GetModuleList();
+ ASSERT_TRUE(module_list);
+ const MinidumpModule* module =
+ module_list->GetModuleForAddress(kMemoryAddress);
+ ASSERT_TRUE(module);
+
+ EXPECT_EQ(kMemoryAddress, module->base_address());
+ EXPECT_EQ(memory_size, module->size());
+ EXPECT_EQ(kMemoryName, module->code_file());
+ EXPECT_EQ(module_identifier, module->debug_identifier());
+
+ uint32_t len;
+ // These streams are expected to be there
+ EXPECT_TRUE(minidump.SeekToStreamType(MD_THREAD_LIST_STREAM, &len));
+ EXPECT_TRUE(minidump.SeekToStreamType(MD_MEMORY_LIST_STREAM, &len));
+ EXPECT_TRUE(minidump.SeekToStreamType(MD_EXCEPTION_STREAM, &len));
+ EXPECT_TRUE(minidump.SeekToStreamType(MD_SYSTEM_INFO_STREAM, &len));
+ EXPECT_TRUE(minidump.SeekToStreamType(MD_LINUX_CPU_INFO, &len));
+ EXPECT_TRUE(minidump.SeekToStreamType(MD_LINUX_PROC_STATUS, &len));
+ EXPECT_TRUE(minidump.SeekToStreamType(MD_LINUX_CMD_LINE, &len));
+ EXPECT_TRUE(minidump.SeekToStreamType(MD_LINUX_ENVIRON, &len));
+ EXPECT_TRUE(minidump.SeekToStreamType(MD_LINUX_AUXV, &len));
+ EXPECT_TRUE(minidump.SeekToStreamType(MD_LINUX_MAPS, &len));
+ EXPECT_TRUE(minidump.SeekToStreamType(MD_LINUX_DSO_DEBUG, &len));
+
+ close(fds[1]);
+ IGNORE_EINTR(waitpid(child, nullptr, 0));
+}
+
+// Test that minidumping is skipped while writing minidumps if principal mapping
+// is not referenced.
+TEST(MinidumpWriterTest, MinidumpSkippedIfRequested) {
+ int fds[2];
+ ASSERT_NE(-1, pipe(fds));
+
+ const pid_t child = fork();
+ if (child == 0) {
+ close(fds[1]);
+ char b;
+ IGNORE_RET(HANDLE_EINTR(read(fds[0], &b, sizeof(b))));
+ close(fds[0]);
+ syscall(__NR_exit_group);
+ }
+ close(fds[0]);
+
+ ExceptionHandler::CrashContext context;
+ memset(&context, 0, sizeof(context));
+ ASSERT_EQ(0, getcontext(&context.context));
+ context.tid = child;
+
+ AutoTempDir temp_dir;
+ string templ = temp_dir.path() + kMDWriterUnitTestFileName;
+
+ // pass an invalid principal mapping address, which will force
+ // WriteMinidump to not write a minidump.
+ ASSERT_FALSE(WriteMinidump(templ.c_str(), child, &context, sizeof(context),
+ true, static_cast<uintptr_t>(0x0102030405060708ull),
+ false));
+ close(fds[1]);
+ IGNORE_EINTR(waitpid(child, nullptr, 0));
+}
+
+// Test that minidumping is skipped while writing minidumps if principal mapping
+// is not referenced.
+TEST(MinidumpWriterTest, MinidumpStacksSkippedIfRequested) {
+ int fds[2];
+ ASSERT_NE(-1, pipe(fds));
+
+ const pid_t child = fork();
+ if (child == 0) {
+ close(fds[1]);
+
+ // Create a thread that does not return, and only references libc (not the
+ // current executable). This thread should not be captured in the minidump.
+ pthread_t thread;
+ pthread_attr_t thread_attributes;
+ pthread_attr_init(&thread_attributes);
+ pthread_attr_setdetachstate(&thread_attributes, PTHREAD_CREATE_DETACHED);
+ sigset_t sigset;
+ sigemptyset(&sigset);
+ pthread_create(&thread, &thread_attributes,
+ reinterpret_cast<void* (*)(void*)>(&sigsuspend), &sigset);
+
+ char b;
+ IGNORE_RET(HANDLE_EINTR(read(fds[0], &b, sizeof(b))));
+ close(fds[0]);
+ syscall(__NR_exit_group);
+ }
+ close(fds[0]);
+
+ ExceptionHandler::CrashContext context;
+ memset(&context, 0, sizeof(context));
+ ASSERT_EQ(0, getcontext(&context.context));
+ context.tid = child;
+
+ AutoTempDir temp_dir;
+ string templ = temp_dir.path() + kMDWriterUnitTestFileName;
+
+ // Pass an invalid principal mapping address, which will force
+ // WriteMinidump to not dump any thread stacks.
+ ASSERT_TRUE(WriteMinidump(
+ templ.c_str(), child, &context, sizeof(context), true,
+ reinterpret_cast<uintptr_t>(google_breakpad::WriteFile), false));
+
+ // Read the minidump. And ensure that thread memory was dumped only for the
+ // main thread.
+ Minidump minidump(templ);
+ ASSERT_TRUE(minidump.Read());
+
+ MinidumpThreadList *threads = minidump.GetThreadList();
+ int threads_with_stacks = 0;
+ for (unsigned int i = 0; i < threads->thread_count(); ++i) {
+ MinidumpThread *thread = threads->GetThreadAtIndex(i);
+ if (thread->GetMemory()) {
+ ++threads_with_stacks;
+ }
+ }
+#if defined(THREAD_SANITIZER) || defined(ADDRESS_SANITIZER)
+ ASSERT_GE(threads_with_stacks, 1);
+#else
+ ASSERT_EQ(threads_with_stacks, 1);
+#endif
+ close(fds[1]);
+ IGNORE_EINTR(waitpid(child, nullptr, 0));
+}
+
+// Test that stacks can be sanitized while writing minidumps.
+TEST(MinidumpWriterTest, StacksAreSanitizedIfRequested) {
+ int fds[2];
+ ASSERT_NE(-1, pipe(fds));
+
+ const pid_t child = fork();
+ if (child == 0) {
+ close(fds[1]);
+ char b;
+ IGNORE_RET(HANDLE_EINTR(read(fds[0], &b, sizeof(b))));
+ close(fds[0]);
+ syscall(__NR_exit_group);
+ }
+ close(fds[0]);
+
+ ExceptionHandler::CrashContext context;
+ memset(&context, 0, sizeof(context));
+ ASSERT_EQ(0, getcontext(&context.context));
+ context.tid = child;
+
+ AutoTempDir temp_dir;
+ string templ = temp_dir.path() + kMDWriterUnitTestFileName;
+ // pass an invalid principal mapping address, which will force
+ // WriteMinidump to not dump any thread stacks.
+ ASSERT_TRUE(WriteMinidump(templ.c_str(), child, &context, sizeof(context),
+ false, 0, true));
+
+ // Read the minidump. And ensure that thread memory contains a defaced value.
+ Minidump minidump(templ);
+ ASSERT_TRUE(minidump.Read());
+
+ const uintptr_t defaced =
+#if defined(__LP64__)
+ 0x0defaced0defaced;
+#else
+ 0x0defaced;
+#endif
+ MinidumpThreadList *threads = minidump.GetThreadList();
+ for (unsigned int i = 0; i < threads->thread_count(); ++i) {
+ MinidumpThread *thread = threads->GetThreadAtIndex(i);
+ MinidumpMemoryRegion *mem = thread->GetMemory();
+ ASSERT_TRUE(mem != nullptr);
+ uint32_t sz = mem->GetSize();
+ const uint8_t *data = mem->GetMemory();
+ ASSERT_TRUE(memmem(data, sz, &defaced, sizeof(defaced)) != nullptr);
+ }
+ close(fds[1]);
+ IGNORE_EINTR(waitpid(child, nullptr, 0));
+}
+
+// Test that a binary with a longer-than-usual build id note
+// makes its way all the way through to the minidump unscathed.
+// The linux_client_unittest is linked with an explicit --build-id
+// in Makefile.am.
+TEST(MinidumpWriterTest, BuildIDLong) {
+ int fds[2];
+ ASSERT_NE(-1, pipe(fds));
+
+ const pid_t child = fork();
+ if (child == 0) {
+ close(fds[1]);
+ char b;
+ IGNORE_RET(HANDLE_EINTR(read(fds[0], &b, sizeof(b))));
+ close(fds[0]);
+ syscall(__NR_exit_group);
+ }
+ close(fds[0]);
+
+ ExceptionHandler::CrashContext context;
+ memset(&context, 0, sizeof(context));
+ ASSERT_EQ(0, getcontext(&context.context));
+ context.tid = child;
+
+ AutoTempDir temp_dir;
+ const string dump_path = temp_dir.path() + kMDWriterUnitTestFileName;
+
+ EXPECT_TRUE(WriteMinidump(dump_path.c_str(),
+ child, &context, sizeof(context)));
+ close(fds[1]);
+
+ // Read the minidump. Load the module list, and ensure that
+ // the main module has the correct debug id and code id.
+ Minidump minidump(dump_path);
+ ASSERT_TRUE(minidump.Read());
+
+ MinidumpModuleList* module_list = minidump.GetModuleList();
+ ASSERT_TRUE(module_list);
+ const MinidumpModule* module = module_list->GetMainModule();
+ ASSERT_TRUE(module);
+ const string module_identifier = "030201000504070608090A0B0C0D0E0F0";
+ // This is passed explicitly to the linker in Makefile.am
+ const string build_id =
+ "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f";
+ EXPECT_EQ(module_identifier, module->debug_identifier());
+ EXPECT_EQ(build_id, module->code_identifier());
+
+ IGNORE_EINTR(waitpid(child, nullptr, 0));
+}
+
+// Test that mapping info can be specified, and that it overrides
+// existing mappings that are wholly contained within the specified
+// range.
+TEST(MinidumpWriterTest, MappingInfoContained) {
+ int fds[2];
+ ASSERT_NE(-1, pipe(fds));
+
+ // These are defined here so the parent can use them to check the
+ // data from the minidump afterwards.
+ const int32_t memory_size = sysconf(_SC_PAGESIZE);
+ const char* kMemoryName = "a fake module";
+ const uint8_t kModuleGUID[sizeof(MDGUID)] = {
+ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+ 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF
+ };
+ const string module_identifier = "33221100554477668899AABBCCDDEEFF0";
+
+ // mmap a file
+ AutoTempDir temp_dir;
+ string tempfile = temp_dir.path() + "/minidump-writer-unittest-temp";
+ int fd = open(tempfile.c_str(), O_RDWR | O_CREAT, 0);
+ ASSERT_NE(-1, fd);
+ unlink(tempfile.c_str());
+ // fill with zeros
+ google_breakpad::scoped_array<char> buffer(new char[memory_size]);
+ memset(buffer.get(), 0, memory_size);
+ ASSERT_EQ(memory_size, write(fd, buffer.get(), memory_size));
+ lseek(fd, 0, SEEK_SET);
+
+ char* memory =
+ reinterpret_cast<char*>(mmap(NULL,
+ memory_size,
+ PROT_READ | PROT_WRITE,
+ MAP_PRIVATE,
+ fd,
+ 0));
+ const uintptr_t kMemoryAddress = reinterpret_cast<uintptr_t>(memory);
+ ASSERT_TRUE(memory);
+ close(fd);
+
+ const pid_t child = fork();
+ if (child == 0) {
+ close(fds[1]);
+ char b;
+ IGNORE_RET(HANDLE_EINTR(read(fds[0], &b, sizeof(b))));
+ close(fds[0]);
+ syscall(__NR_exit_group);
+ }
+ close(fds[0]);
+
+ ExceptionHandler::CrashContext context;
+ memset(&context, 0, sizeof(context));
+ context.tid = 1;
+
+ string dumpfile = temp_dir.path() + kMDWriterUnitTestFileName;
+
+ // Add information about the mapped memory. Report it as being larger than
+ // it actually is.
+ MappingInfo info;
+ info.start_addr = kMemoryAddress - memory_size;
+ info.size = memory_size * 3;
+ info.offset = 0;
+ info.exec = false;
+ strcpy(info.name, kMemoryName);
+
+ MappingList mappings;
+ AppMemoryList memory_list;
+ MappingEntry mapping;
+ mapping.first = info;
+ mapping.second.assign(std::begin(kModuleGUID), std::end(kModuleGUID));
+ mappings.push_back(mapping);
+ ASSERT_TRUE(WriteMinidump(dumpfile.c_str(), child, &context, sizeof(context),
+ mappings, memory_list));
+
+ // Read the minidump. Load the module list, and ensure that
+ // the mmap'ed |memory| is listed with the given module name
+ // and debug ID.
+ Minidump minidump(dumpfile);
+ ASSERT_TRUE(minidump.Read());
+
+ MinidumpModuleList* module_list = minidump.GetModuleList();
+ ASSERT_TRUE(module_list);
+ const MinidumpModule* module =
+ module_list->GetModuleForAddress(kMemoryAddress);
+ ASSERT_TRUE(module);
+
+ EXPECT_EQ(info.start_addr, module->base_address());
+ EXPECT_EQ(info.size, module->size());
+ EXPECT_EQ(kMemoryName, module->code_file());
+ EXPECT_EQ(module_identifier, module->debug_identifier());
+
+ close(fds[1]);
+ IGNORE_EINTR(waitpid(child, nullptr, 0));
+}
+
+TEST(MinidumpWriterTest, DeletedBinary) {
+ const string kNumberOfThreadsArgument = "1";
+ const string helper_path(GetHelperBinary());
+ if (helper_path.empty()) {
+ FAIL() << "Couldn't find helper binary";
+ exit(1);
+ }
+
+ // Copy binary to a temp file.
+ AutoTempDir temp_dir;
+ string binpath = temp_dir.path() + "/linux-dumper-unittest-helper";
+ ASSERT_TRUE(CopyFile(helper_path.c_str(), binpath.c_str()))
+ << "Failed to copy " << helper_path << " to " << binpath;
+ ASSERT_EQ(0, chmod(binpath.c_str(), 0755));
+
+ int fds[2];
+ ASSERT_NE(-1, pipe(fds));
+
+ pid_t child_pid = fork();
+ if (child_pid == 0) {
+ // In child process.
+ close(fds[0]);
+
+ // Pass the pipe fd and the number of threads as arguments.
+ char pipe_fd_string[8];
+ sprintf(pipe_fd_string, "%d", fds[1]);
+ execl(binpath.c_str(),
+ binpath.c_str(),
+ pipe_fd_string,
+ kNumberOfThreadsArgument.c_str(),
+ NULL);
+ }
+ close(fds[1]);
+ // Wait for the child process to signal that it's ready.
+ struct pollfd pfd;
+ memset(&pfd, 0, sizeof(pfd));
+ pfd.fd = fds[0];
+ pfd.events = POLLIN | POLLERR;
+
+ const int r = HANDLE_EINTR(poll(&pfd, 1, 1000));
+ ASSERT_EQ(1, r);
+ ASSERT_TRUE(pfd.revents & POLLIN);
+ uint8_t junk;
+ const int nr = HANDLE_EINTR(read(fds[0], &junk, sizeof(junk)));
+ ASSERT_EQ(static_cast<ssize_t>(sizeof(junk)), nr);
+ close(fds[0]);
+
+ // Child is ready now.
+ // Unlink the test binary.
+ unlink(binpath.c_str());
+
+ ExceptionHandler::CrashContext context;
+ memset(&context, 0, sizeof(context));
+
+ string templ = temp_dir.path() + kMDWriterUnitTestFileName;
+ // Set a non-zero tid to avoid tripping asserts.
+ context.tid = child_pid;
+ ASSERT_TRUE(WriteMinidump(templ.c_str(), child_pid, &context,
+ sizeof(context)));
+ kill(child_pid, SIGKILL);
+
+ struct stat st;
+ ASSERT_EQ(0, stat(templ.c_str(), &st));
+ ASSERT_GT(st.st_size, 0);
+
+ Minidump minidump(templ);
+ ASSERT_TRUE(minidump.Read());
+
+ // Check that the main module filename is correct.
+ MinidumpModuleList* module_list = minidump.GetModuleList();
+ ASSERT_TRUE(module_list);
+ const MinidumpModule* module = module_list->GetMainModule();
+ EXPECT_STREQ(binpath.c_str(), module->code_file().c_str());
+ // Check that the file ID is correct.
+ FileID fileid(helper_path.c_str());
+ PageAllocator allocator;
+ wasteful_vector<uint8_t> identifier(&allocator, kDefaultBuildIdSize);
+ EXPECT_TRUE(fileid.ElfFileIdentifier(identifier));
+ string identifier_string = FileID::ConvertIdentifierToUUIDString(identifier);
+ string module_identifier(identifier_string);
+ // Strip out dashes
+ size_t pos;
+ while ((pos = module_identifier.find('-')) != string::npos) {
+ module_identifier.erase(pos, 1);
+ }
+ // And append a zero, because module IDs include an "age" field
+ // which is always zero on Linux.
+ module_identifier += "0";
+ EXPECT_EQ(module_identifier, module->debug_identifier());
+
+ IGNORE_EINTR(waitpid(child_pid, nullptr, 0));
+}
+
+// Test that an additional memory region can be added to the minidump.
+TEST(MinidumpWriterTest, AdditionalMemory) {
+ int fds[2];
+ ASSERT_NE(-1, pipe(fds));
+
+ // These are defined here so the parent can use them to check the
+ // data from the minidump afterwards.
+ const uint32_t kMemorySize = sysconf(_SC_PAGESIZE);
+
+ // Get some heap memory.
+ uint8_t* memory = new uint8_t[kMemorySize];
+ const uintptr_t kMemoryAddress = reinterpret_cast<uintptr_t>(memory);
+ ASSERT_TRUE(memory);
+
+ // Stick some data into the memory so the contents can be verified.
+ for (uint32_t i = 0; i < kMemorySize; ++i) {
+ memory[i] = i % 255;
+ }
+
+ const pid_t child = fork();
+ if (child == 0) {
+ close(fds[1]);
+ char b;
+ HANDLE_EINTR(read(fds[0], &b, sizeof(b)));
+ close(fds[0]);
+ syscall(__NR_exit_group);
+ }
+ close(fds[0]);
+
+ ExceptionHandler::CrashContext context;
+
+ // This needs a valid context for minidump writing to work, but getting
+ // a useful one from the child is too much work, so just use one from
+ // the parent since the child is just a forked copy anyway.
+ ASSERT_EQ(0, getcontext(&context.context));
+ context.tid = child;
+
+ AutoTempDir temp_dir;
+ string templ = temp_dir.path() + kMDWriterUnitTestFileName;
+ unlink(templ.c_str());
+
+ MappingList mappings;
+ AppMemoryList memory_list;
+
+ // Add the memory region to the list of memory to be included.
+ AppMemory app_memory;
+ app_memory.ptr = memory;
+ app_memory.length = kMemorySize;
+ memory_list.push_back(app_memory);
+ ASSERT_TRUE(WriteMinidump(templ.c_str(), child, &context, sizeof(context),
+ mappings, memory_list));
+
+ // Read the minidump. Ensure that the memory region is present
+ Minidump minidump(templ);
+ ASSERT_TRUE(minidump.Read());
+
+ MinidumpMemoryList* dump_memory_list = minidump.GetMemoryList();
+ ASSERT_TRUE(dump_memory_list);
+ const MinidumpMemoryRegion* region =
+ dump_memory_list->GetMemoryRegionForAddress(kMemoryAddress);
+ ASSERT_TRUE(region);
+
+ EXPECT_EQ(kMemoryAddress, region->GetBase());
+ EXPECT_EQ(kMemorySize, region->GetSize());
+
+ // Verify memory contents.
+ EXPECT_EQ(0, memcmp(region->GetMemory(), memory, kMemorySize));
+
+ delete[] memory;
+ close(fds[1]);
+ IGNORE_EINTR(waitpid(child, nullptr, 0));
+}
+
+// Test that an invalid thread stack pointer still results in a minidump.
+TEST(MinidumpWriterTest, InvalidStackPointer) {
+ int fds[2];
+ ASSERT_NE(-1, pipe(fds));
+
+ const pid_t child = fork();
+ if (child == 0) {
+ close(fds[1]);
+ char b;
+ HANDLE_EINTR(read(fds[0], &b, sizeof(b)));
+ close(fds[0]);
+ syscall(__NR_exit_group);
+ }
+ close(fds[0]);
+
+ ExceptionHandler::CrashContext context;
+
+ // This needs a valid context for minidump writing to work, but getting
+ // a useful one from the child is too much work, so just use one from
+ // the parent since the child is just a forked copy anyway.
+ ASSERT_EQ(0, getcontext(&context.context));
+ context.tid = child;
+
+ // Fake the child's stack pointer for its crashing thread. NOTE: This must
+ // be an invalid memory address for the child process (stack or otherwise).
+ // Try 1MB below the current stack.
+ uintptr_t invalid_stack_pointer =
+ reinterpret_cast<uintptr_t>(&context) - 1024*1024;
+#if defined(__i386)
+ context.context.uc_mcontext.gregs[REG_ESP] = invalid_stack_pointer;
+#elif defined(__x86_64)
+ context.context.uc_mcontext.gregs[REG_RSP] = invalid_stack_pointer;
+#elif defined(__ARM_EABI__)
+ context.context.uc_mcontext.arm_sp = invalid_stack_pointer;
+#elif defined(__aarch64__)
+ context.context.uc_mcontext.sp = invalid_stack_pointer;
+#elif defined(__mips__)
+ context.context.uc_mcontext.gregs[MD_CONTEXT_MIPS_REG_SP] =
+ invalid_stack_pointer;
+#else
+# error "This code has not been ported to your platform yet."
+#endif
+
+ AutoTempDir temp_dir;
+ string templ = temp_dir.path() + kMDWriterUnitTestFileName;
+ // NOTE: In previous versions of Breakpad, WriteMinidump() would fail if
+ // presented with an invalid stack pointer.
+ ASSERT_TRUE(WriteMinidump(templ.c_str(), child, &context, sizeof(context)));
+
+ // Read the minidump. Ensure that the memory region is present
+ Minidump minidump(templ);
+ ASSERT_TRUE(minidump.Read());
+
+ // TODO(ted.mielczarek,mkrebs): Enable this part of the test once
+ // https://breakpad.appspot.com/413002/ is committed.
+#if 0
+ // Make sure there's a thread without a stack. NOTE: It's okay if
+ // GetThreadList() shows the error: "ERROR: MinidumpThread has a memory
+ // region problem".
+ MinidumpThreadList* dump_thread_list = minidump.GetThreadList();
+ ASSERT_TRUE(dump_thread_list);
+ bool found_empty_stack = false;
+ for (int i = 0; i < dump_thread_list->thread_count(); i++) {
+ MinidumpThread* thread = dump_thread_list->GetThreadAtIndex(i);
+ ASSERT_TRUE(thread->thread() != NULL);
+ // When the stack size is zero bytes, GetMemory() returns NULL.
+ if (thread->GetMemory() == NULL) {
+ found_empty_stack = true;
+ break;
+ }
+ }
+ // NOTE: If you fail this, first make sure that "invalid_stack_pointer"
+ // above is indeed set to an invalid address.
+ ASSERT_TRUE(found_empty_stack);
+#endif
+
+ close(fds[1]);
+ IGNORE_EINTR(waitpid(child, nullptr, 0));
+}
+
+// Test that limiting the size of the minidump works.
+TEST(MinidumpWriterTest, MinidumpSizeLimit) {
+ static const int kNumberOfThreadsInHelperProgram = 40;
+
+ char number_of_threads_arg[3];
+ sprintf(number_of_threads_arg, "%d", kNumberOfThreadsInHelperProgram);
+
+ string helper_path(GetHelperBinary());
+ if (helper_path.empty()) {
+ FAIL() << "Couldn't find helper binary";
+ exit(1);
+ }
+
+ int fds[2];
+ ASSERT_NE(-1, pipe(fds));
+
+ pid_t child_pid = fork();
+ if (child_pid == 0) {
+ // In child process.
+ close(fds[0]);
+
+ // Pass the pipe fd and the number of threads as arguments.
+ char pipe_fd_string[8];
+ sprintf(pipe_fd_string, "%d", fds[1]);
+ execl(helper_path.c_str(),
+ helper_path.c_str(),
+ pipe_fd_string,
+ number_of_threads_arg,
+ NULL);
+ }
+ close(fds[1]);
+
+ // Wait for all child threads to indicate that they have started
+ for (int threads = 0; threads < kNumberOfThreadsInHelperProgram; threads++) {
+ struct pollfd pfd;
+ memset(&pfd, 0, sizeof(pfd));
+ pfd.fd = fds[0];
+ pfd.events = POLLIN | POLLERR;
+
+ const int r = HANDLE_EINTR(poll(&pfd, 1, 1000));
+ ASSERT_EQ(1, r);
+ ASSERT_TRUE(pfd.revents & POLLIN);
+ uint8_t junk;
+ ASSERT_EQ(read(fds[0], &junk, sizeof(junk)),
+ static_cast<ssize_t>(sizeof(junk)));
+ }
+ close(fds[0]);
+
+ // There is a race here because we may stop a child thread before
+ // it is actually running the busy loop. Empirically this sleep
+ // is sufficient to avoid the race.
+ usleep(100000);
+
+ // Child and its threads are ready now.
+
+
+ off_t normal_file_size;
+ int total_normal_stack_size = 0;
+ AutoTempDir temp_dir;
+
+ // First, write a minidump with no size limit.
+ {
+ string normal_dump = temp_dir.path() +
+ "/minidump-writer-unittest.dmp";
+ ASSERT_TRUE(WriteMinidump(normal_dump.c_str(), -1,
+ child_pid, NULL, 0,
+ MappingList(), AppMemoryList()));
+ struct stat st;
+ ASSERT_EQ(0, stat(normal_dump.c_str(), &st));
+ ASSERT_GT(st.st_size, 0);
+ normal_file_size = st.st_size;
+
+ Minidump minidump(normal_dump);
+ ASSERT_TRUE(minidump.Read());
+ MinidumpThreadList* dump_thread_list = minidump.GetThreadList();
+ ASSERT_TRUE(dump_thread_list);
+ for (unsigned int i = 0; i < dump_thread_list->thread_count(); i++) {
+ MinidumpThread* thread = dump_thread_list->GetThreadAtIndex(i);
+ ASSERT_TRUE(thread->thread() != NULL);
+ // When the stack size is zero bytes, GetMemory() returns NULL.
+ MinidumpMemoryRegion* memory = thread->GetMemory();
+ ASSERT_TRUE(memory != NULL);
+ total_normal_stack_size += memory->GetSize();
+ }
+ }
+
+ // Second, write a minidump with a size limit big enough to not trigger
+ // anything.
+ {
+ // Set size limit arbitrarily 1MB larger than the normal file size -- such
+ // that the limiting code will not kick in.
+ const off_t minidump_size_limit = normal_file_size + 1024*1024;
+
+ string same_dump = temp_dir.path() +
+ "/minidump-writer-unittest-same.dmp";
+ ASSERT_TRUE(WriteMinidump(same_dump.c_str(), minidump_size_limit,
+ child_pid, NULL, 0,
+ MappingList(), AppMemoryList()));
+ struct stat st;
+ ASSERT_EQ(0, stat(same_dump.c_str(), &st));
+ // Make sure limiting wasn't actually triggered. NOTE: If you fail this,
+ // first make sure that "minidump_size_limit" above is indeed set to a
+ // large enough value -- the limit-checking code in minidump_writer.cc
+ // does just a rough estimate.
+ ASSERT_EQ(normal_file_size, st.st_size);
+ }
+
+ // Third, write a minidump with a size limit small enough to be triggered.
+ {
+ // Set size limit to some arbitrary amount, such that the limiting code
+ // will kick in. The equation used to set this value was determined by
+ // simply reversing the size-limit logic a little bit in order to pick a
+ // size we know will trigger it. The definition of
+ // kLimitAverageThreadStackLength here was copied from class
+ // MinidumpWriter in minidump_writer.cc.
+ static const unsigned kLimitAverageThreadStackLength = 8 * 1024;
+ off_t minidump_size_limit = kNumberOfThreadsInHelperProgram *
+ kLimitAverageThreadStackLength;
+ // If, in reality, each of the threads' stack is *smaller* than
+ // kLimitAverageThreadStackLength, the normal file size could very well be
+ // smaller than the arbitrary limit that was just set. In that case,
+ // either of these numbers should trigger the size-limiting code, but we
+ // might as well pick the smallest.
+ if (normal_file_size < minidump_size_limit)
+ minidump_size_limit = normal_file_size;
+
+ string limit_dump = temp_dir.path() +
+ "/minidump-writer-unittest-limit.dmp";
+ ASSERT_TRUE(WriteMinidump(limit_dump.c_str(), minidump_size_limit,
+ child_pid, NULL, 0,
+ MappingList(), AppMemoryList()));
+ struct stat st;
+ ASSERT_EQ(0, stat(limit_dump.c_str(), &st));
+ ASSERT_GT(st.st_size, 0);
+ // Make sure the file size is at least smaller than the original. If this
+ // fails because it's the same size, then the size-limit logic didn't kick
+ // in like it was supposed to.
+ EXPECT_LT(st.st_size, normal_file_size);
+
+ Minidump minidump(limit_dump);
+ ASSERT_TRUE(minidump.Read());
+ MinidumpThreadList* dump_thread_list = minidump.GetThreadList();
+ ASSERT_TRUE(dump_thread_list);
+ int total_limit_stack_size = 0;
+ for (unsigned int i = 0; i < dump_thread_list->thread_count(); i++) {
+ MinidumpThread* thread = dump_thread_list->GetThreadAtIndex(i);
+ ASSERT_TRUE(thread->thread() != NULL);
+ // When the stack size is zero bytes, GetMemory() returns NULL.
+ MinidumpMemoryRegion* memory = thread->GetMemory();
+ ASSERT_TRUE(memory != NULL);
+ total_limit_stack_size += memory->GetSize();
+ }
+
+ // Make sure stack size shrunk by at least 1KB per extra thread. The
+ // definition of kLimitBaseThreadCount here was copied from class
+ // MinidumpWriter in minidump_writer.cc.
+ // Note: The 1KB is arbitrary, and assumes that the thread stacks are big
+ // enough to shrink by that much. For example, if each thread stack was
+ // originally only 2KB, the current size-limit logic wouldn't actually
+ // shrink them because that's the size to which it tries to shrink. If
+ // you fail this part of the test due to something like that, the test
+ // logic should probably be improved to account for your situation.
+ const unsigned kLimitBaseThreadCount = 20;
+ const unsigned kMinPerExtraThreadStackReduction = 1024;
+ const int min_expected_reduction = (kNumberOfThreadsInHelperProgram -
+ kLimitBaseThreadCount) * kMinPerExtraThreadStackReduction;
+ EXPECT_LT(total_limit_stack_size,
+ total_normal_stack_size - min_expected_reduction);
+ }
+
+ // Kill the helper program.
+ kill(child_pid, SIGKILL);
+ IGNORE_EINTR(waitpid(child_pid, nullptr, 0));
+}
+
+} // namespace
diff --git a/toolkit/crashreporter/breakpad-client/linux/minidump_writer/minidump_writer_unittest_utils.cc b/toolkit/crashreporter/breakpad-client/linux/minidump_writer/minidump_writer_unittest_utils.cc
new file mode 100644
index 0000000000..3e27be73cc
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/linux/minidump_writer/minidump_writer_unittest_utils.cc
@@ -0,0 +1,66 @@
+// 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.
+
+// minidump_writer_unittest_utils.cc:
+// Shared routines used by unittests under linux/minidump_writer.
+
+#include <limits.h>
+#include <stdlib.h>
+
+#include "linux/minidump_writer/minidump_writer_unittest_utils.h"
+#include "common/linux/safe_readlink.h"
+#include "common/using_std_string.h"
+
+namespace google_breakpad {
+
+string GetHelperBinary() {
+ string helper_path;
+ char *bindir = getenv("bindir");
+ if (bindir) {
+ helper_path = string(bindir) + "/";
+ } else {
+ // Locate helper binary next to the current binary.
+ char self_path[PATH_MAX];
+ if (!SafeReadLink("/proc/self/exe", self_path)) {
+ return "";
+ }
+ helper_path = string(self_path);
+ size_t pos = helper_path.rfind('/');
+ if (pos == string::npos) {
+ return "";
+ }
+ helper_path.erase(pos + 1);
+ }
+
+ helper_path += "linux_dumper_unittest_helper";
+
+ return helper_path;
+}
+
+} // namespace google_breakpad
diff --git a/toolkit/crashreporter/breakpad-client/linux/minidump_writer/minidump_writer_unittest_utils.h b/toolkit/crashreporter/breakpad-client/linux/minidump_writer/minidump_writer_unittest_utils.h
new file mode 100644
index 0000000000..bc7b7c83f4
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/linux/minidump_writer/minidump_writer_unittest_utils.h
@@ -0,0 +1,49 @@
+// 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.
+
+// minidump_writer_unittest_utils.h:
+// Shared routines used by unittests under linux/minidump_writer.
+
+#ifndef CLIENT_LINUX_MINIDUMP_WRITER_MINIDUMP_WRITER_UNITTEST_UTILS_H_
+#define CLIENT_LINUX_MINIDUMP_WRITER_MINIDUMP_WRITER_UNITTEST_UTILS_H_
+
+#include <string>
+
+#include "common/using_std_string.h"
+
+namespace google_breakpad {
+
+// Returns the full path to linux_dumper_unittest_helper. The full path is
+// discovered either by using the environment variable "bindir" or by using
+// the location of the main module of the currently running process.
+string GetHelperBinary();
+
+} // namespace google_breakpad
+
+#endif // CLIENT_LINUX_MINIDUMP_WRITER_MINIDUMP_WRITER_UNITTEST_UTILS_H_
diff --git a/toolkit/crashreporter/breakpad-client/linux/minidump_writer/proc_cpuinfo_reader.h b/toolkit/crashreporter/breakpad-client/linux/minidump_writer/proc_cpuinfo_reader.h
new file mode 100644
index 0000000000..94a637fc15
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/linux/minidump_writer/proc_cpuinfo_reader.h
@@ -0,0 +1,130 @@
+// 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 CLIENT_LINUX_MINIDUMP_WRITER_PROC_CPUINFO_READER_H_
+#define CLIENT_LINUX_MINIDUMP_WRITER_PROC_CPUINFO_READER_H_
+
+#include <stdint.h>
+#include <assert.h>
+#include <string.h>
+
+#include "linux/minidump_writer/line_reader.h"
+#include "common/linux/linux_libc_support.h"
+#include "third_party/lss/linux_syscall_support.h"
+
+namespace google_breakpad {
+
+// A class for reading /proc/cpuinfo without using fopen/fgets or other
+// functions which may allocate memory.
+class ProcCpuInfoReader {
+public:
+ ProcCpuInfoReader(int fd)
+ : line_reader_(fd), pop_count_(-1) {
+ }
+
+ // Return the next field name, or NULL in case of EOF.
+ // field: (output) Pointer to zero-terminated field name.
+ // Returns true on success, or false on EOF or error (line too long).
+ bool GetNextField(const char** field) {
+ for (;;) {
+ const char* line;
+ unsigned line_len;
+
+ // Try to read next line.
+ if (pop_count_ >= 0) {
+ line_reader_.PopLine(pop_count_);
+ pop_count_ = -1;
+ }
+
+ if (!line_reader_.GetNextLine(&line, &line_len))
+ return false;
+
+ pop_count_ = static_cast<int>(line_len);
+
+ const char* line_end = line + line_len;
+
+ // Expected format: <field-name> <space>+ ':' <space> <value>
+ // Note that:
+ // - empty lines happen.
+ // - <field-name> can contain spaces.
+ // - some fields have an empty <value>
+ char* sep = static_cast<char*>(my_memchr(line, ':', line_len));
+ if (sep == NULL)
+ continue;
+
+ // Record the value. Skip leading space after the column to get
+ // its start.
+ const char* val = sep+1;
+ while (val < line_end && my_isspace(*val))
+ val++;
+
+ value_ = val;
+ value_len_ = static_cast<size_t>(line_end - val);
+
+ // Remove trailing spaces before the column to properly 0-terminate
+ // the field name.
+ while (sep > line && my_isspace(sep[-1]))
+ sep--;
+
+ if (sep == line)
+ continue;
+
+ // zero-terminate field name.
+ *sep = '\0';
+
+ *field = line;
+ return true;
+ }
+ }
+
+ // Return the field value. This must be called after a succesful
+ // call to GetNextField().
+ const char* GetValue() {
+ assert(value_);
+ return value_;
+ }
+
+ // Same as GetValue(), but also returns the length in characters of
+ // the value.
+ const char* GetValueAndLen(size_t* length) {
+ assert(value_);
+ *length = value_len_;
+ return value_;
+ }
+
+private:
+ LineReader line_reader_;
+ int pop_count_;
+ const char* value_;
+ size_t value_len_;
+};
+
+} // namespace google_breakpad
+
+#endif // CLIENT_LINUX_MINIDUMP_WRITER_PROC_CPUINFO_READER_H_
diff --git a/toolkit/crashreporter/breakpad-client/linux/minidump_writer/proc_cpuinfo_reader_unittest.cc b/toolkit/crashreporter/breakpad-client/linux/minidump_writer/proc_cpuinfo_reader_unittest.cc
new file mode 100644
index 0000000000..26fe9e3a38
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/linux/minidump_writer/proc_cpuinfo_reader_unittest.cc
@@ -0,0 +1,199 @@
+// 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.
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+
+#include "linux/minidump_writer/proc_cpuinfo_reader.h"
+#include "breakpad_googletest_includes.h"
+#include "common/linux/tests/auto_testfile.h"
+
+using namespace google_breakpad;
+
+#if !defined(__ANDROID__)
+#define TEMPDIR "/tmp"
+#else
+#define TEMPDIR "/data/local/tmp"
+#endif
+
+
+namespace {
+
+typedef testing::Test ProcCpuInfoReaderTest;
+
+class ScopedTestFile : public AutoTestFile {
+public:
+ explicit ScopedTestFile(const char* text)
+ : AutoTestFile("proc_cpuinfo_reader", text) {
+ }
+};
+
+}
+
+TEST(ProcCpuInfoReaderTest, EmptyFile) {
+ ScopedTestFile file("");
+ ASSERT_TRUE(file.IsOk());
+ ProcCpuInfoReader reader(file.GetFd());
+
+ const char *field;
+ ASSERT_FALSE(reader.GetNextField(&field));
+}
+
+TEST(ProcCpuInfoReaderTest, OneLineTerminated) {
+ ScopedTestFile file("foo : bar\n");
+ ASSERT_TRUE(file.IsOk());
+ ProcCpuInfoReader reader(file.GetFd());
+
+ const char *field;
+ ASSERT_TRUE(reader.GetNextField(&field));
+ ASSERT_STREQ("foo", field);
+ ASSERT_STREQ("bar", reader.GetValue());
+
+ ASSERT_FALSE(reader.GetNextField(&field));
+}
+
+TEST(ProcCpuInfoReaderTest, OneLine) {
+ ScopedTestFile file("foo : bar");
+ ASSERT_TRUE(file.IsOk());
+ ProcCpuInfoReader reader(file.GetFd());
+
+ const char *field;
+ size_t value_len;
+ ASSERT_TRUE(reader.GetNextField(&field));
+ ASSERT_STREQ("foo", field);
+ ASSERT_STREQ("bar", reader.GetValueAndLen(&value_len));
+ ASSERT_EQ(3U, value_len);
+
+ ASSERT_FALSE(reader.GetNextField(&field));
+}
+
+TEST(ProcCpuInfoReaderTest, TwoLinesTerminated) {
+ ScopedTestFile file("foo : bar\nzoo : tut\n");
+ ASSERT_TRUE(file.IsOk());
+ ProcCpuInfoReader reader(file.GetFd());
+
+ const char* field;
+ ASSERT_TRUE(reader.GetNextField(&field));
+ ASSERT_STREQ("foo", field);
+ ASSERT_STREQ("bar", reader.GetValue());
+
+ ASSERT_TRUE(reader.GetNextField(&field));
+ ASSERT_STREQ("zoo", field);
+ ASSERT_STREQ("tut", reader.GetValue());
+
+ ASSERT_FALSE(reader.GetNextField(&field));
+}
+
+TEST(ProcCpuInfoReaderTest, SkipMalformedLine) {
+ ScopedTestFile file("this line should have a column\nfoo : bar\n");
+ ASSERT_TRUE(file.IsOk());
+ ProcCpuInfoReader reader(file.GetFd());
+
+ const char* field;
+ ASSERT_TRUE(reader.GetNextField(&field));
+ ASSERT_STREQ("foo", field);
+ ASSERT_STREQ("bar", reader.GetValue());
+
+ ASSERT_FALSE(reader.GetNextField(&field));
+}
+
+TEST(ProcCpuInfoReaderTest, SkipOneEmptyLine) {
+ ScopedTestFile file("\n\nfoo : bar\n");
+ ASSERT_TRUE(file.IsOk());
+ ProcCpuInfoReader reader(file.GetFd());
+
+ const char* field;
+ ASSERT_TRUE(reader.GetNextField(&field));
+ ASSERT_STREQ("foo", field);
+ ASSERT_STREQ("bar", reader.GetValue());
+
+ ASSERT_FALSE(reader.GetNextField(&field));
+}
+
+TEST(ProcCpuInfoReaderTest, SkipEmptyField) {
+ ScopedTestFile file(" : bar\nzoo : tut\n");
+ ASSERT_TRUE(file.IsOk());
+ ProcCpuInfoReader reader(file.GetFd());
+
+ const char* field;
+ ASSERT_TRUE(reader.GetNextField(&field));
+ ASSERT_STREQ("zoo", field);
+ ASSERT_STREQ("tut", reader.GetValue());
+
+ ASSERT_FALSE(reader.GetNextField(&field));
+}
+
+TEST(ProcCpuInfoReaderTest, SkipTwoEmptyLines) {
+ ScopedTestFile file("foo : bar\n\n\nfoo : bar\n");
+ ASSERT_TRUE(file.IsOk());
+ ProcCpuInfoReader reader(file.GetFd());
+
+ const char* field;
+ ASSERT_TRUE(reader.GetNextField(&field));
+ ASSERT_STREQ("foo", field);
+ ASSERT_STREQ("bar", reader.GetValue());
+
+ ASSERT_TRUE(reader.GetNextField(&field));
+ ASSERT_STREQ("foo", field);
+ ASSERT_STREQ("bar", reader.GetValue());
+
+ ASSERT_FALSE(reader.GetNextField(&field));
+}
+
+TEST(ProcCpuInfoReaderTest, FieldWithSpaces) {
+ ScopedTestFile file("foo bar : zoo\n");
+ ASSERT_TRUE(file.IsOk());
+ ProcCpuInfoReader reader(file.GetFd());
+
+ const char* field;
+ ASSERT_TRUE(reader.GetNextField(&field));
+ ASSERT_STREQ("foo bar", field);
+ ASSERT_STREQ("zoo", reader.GetValue());
+
+ ASSERT_FALSE(reader.GetNextField(&field));
+}
+
+TEST(ProcCpuInfoReaderTest, EmptyValue) {
+ ScopedTestFile file("foo :\n");
+ ASSERT_TRUE(file.IsOk());
+ ProcCpuInfoReader reader(file.GetFd());
+
+ const char* field;
+ ASSERT_TRUE(reader.GetNextField(&field));
+ ASSERT_STREQ("foo", field);
+ size_t value_len;
+ ASSERT_STREQ("", reader.GetValueAndLen(&value_len));
+ ASSERT_EQ(0U, value_len);
+
+ ASSERT_FALSE(reader.GetNextField(&field));
+}
diff --git a/toolkit/crashreporter/breakpad-client/linux/moz.build b/toolkit/crashreporter/breakpad-client/linux/moz.build
new file mode 100644
index 0000000000..ac4fb1e230
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/linux/moz.build
@@ -0,0 +1,47 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+UNIFIED_SOURCES += [
+ 'crash_generation/crash_generation_client.cc',
+ 'crash_generation/crash_generation_server.cc',
+ 'dump_writer_common/thread_info.cc',
+ 'dump_writer_common/ucontext_reader.cc',
+ 'handler/exception_handler.cc',
+ 'handler/guid_generator.cc',
+ 'handler/minidump_descriptor.cc',
+ 'log/log.cc',
+ 'microdump_writer/microdump_writer.cc',
+ 'minidump_writer/linux_dumper.cc',
+ 'minidump_writer/linux_ptrace_dumper.cc',
+]
+
+if CONFIG["CC_TYPE"] == "gcc":
+ # Workaround for an ICE in the hazard detection GCC plug-in, see
+ # https://bugzilla.mozilla.org/show_bug.cgi?id=1756505#c7
+ SOURCES += ['minidump_writer/minidump_writer.cc']
+else:
+ UNIFIED_SOURCES += ['minidump_writer/minidump_writer.cc']
+
+# On Linux we override the guid_creator.h header and use our own instead
+if CONFIG['OS_TARGET'] == 'Linux' or CONFIG['OS_TARGET'] == 'Android':
+ DEFINES['COMMON_LINUX_GUID_CREATOR_H__'] = 1
+
+if CONFIG['OS_TARGET'] == 'Android':
+ DEFINES['ANDROID_NDK_MAJOR_VERSION'] = CONFIG['ANDROID_NDK_MAJOR_VERSION']
+ DEFINES['ANDROID_NDK_MINOR_VERSION'] = CONFIG['ANDROID_NDK_MINOR_VERSION']
+ LOCAL_INCLUDES += [
+ '/toolkit/crashreporter/google-breakpad/src/common/android/include',
+ ]
+
+FINAL_LIBRARY = 'breakpad_client'
+
+include('/toolkit/crashreporter/crashreporter.mozbuild')
+
+if CONFIG['MOZ_PHC']:
+ DEFINES['MOZ_PHC'] = True
+
+if CONFIG['CC_TYPE'] in ('clang', 'gcc'):
+ CXXFLAGS += ['-Wno-error=stack-protector']
diff --git a/toolkit/crashreporter/breakpad-client/mac/crash_generation/client_info.h b/toolkit/crashreporter/breakpad-client/mac/crash_generation/client_info.h
new file mode 100644
index 0000000000..a3a95dcace
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/mac/crash_generation/client_info.h
@@ -0,0 +1,47 @@
+// Copyright (c) 2010 Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef CLIENT_MAC_CRASH_GENERATION_CLIENT_INFO_H_
+#define CLIENT_MAC_CRASH_GENERATION_CLIENT_INFO_H_
+
+namespace google_breakpad {
+
+class ClientInfo {
+ public:
+ explicit ClientInfo(pid_t pid) : pid_(pid) {}
+
+ pid_t pid() const { return pid_; }
+
+ private:
+ pid_t pid_;
+};
+
+} // namespace google_breakpad
+
+#endif // CLIENT_MAC_CRASH_GENERATION_CLIENT_INFO_H_
diff --git a/toolkit/crashreporter/breakpad-client/mac/crash_generation/crash_generation_client.cc b/toolkit/crashreporter/breakpad-client/mac/crash_generation/crash_generation_client.cc
new file mode 100644
index 0000000000..bdbf43aaca
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/mac/crash_generation/crash_generation_client.cc
@@ -0,0 +1,74 @@
+// Copyright (c) 2010 Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "mac/crash_generation/crash_generation_client.h"
+
+#include "mac/crash_generation/crash_generation_server.h"
+#include "common/mac/MachIPC.h"
+
+namespace google_breakpad {
+
+bool CrashGenerationClient::RequestDumpForException(
+ int exception_type,
+ int exception_code,
+ int64_t exception_subcode,
+ mach_port_t crashing_thread,
+ mach_port_t crashing_task) {
+ // The server will send a message to this port indicating that it
+ // has finished its work.
+ ReceivePort acknowledge_port;
+
+ MachSendMessage message(kDumpRequestMessage);
+ message.AddDescriptor(crashing_task); // crashing task
+ message.AddDescriptor(crashing_thread); // crashing thread
+ message.AddDescriptor(MACH_PORT_NULL); // handler thread
+ message.AddDescriptor(acknowledge_port.GetPort()); // message receive port
+
+ ExceptionInfo info;
+ info.exception_type = exception_type;
+ info.exception_code = exception_code;
+ info.exception_subcode = exception_subcode;
+ info.child_pid = getpid();
+
+ message.SetData(&info, sizeof(info));
+
+ kern_return_t result = sender_.SendMessage(message, MACH_MSG_TIMEOUT_NONE);
+ if (result != KERN_SUCCESS)
+ return false;
+
+ // Give the server slightly longer to reply since it has to
+ // inspect this task and write the minidump.
+ MachReceiveMessage acknowledge_message;
+ result = acknowledge_port.WaitForMessage(&acknowledge_message,
+ MACH_MSG_TIMEOUT_NONE);
+
+ return result == KERN_SUCCESS;
+}
+
+} // namespace google_breakpad
diff --git a/toolkit/crashreporter/breakpad-client/mac/crash_generation/crash_generation_client.h b/toolkit/crashreporter/breakpad-client/mac/crash_generation/crash_generation_client.h
new file mode 100644
index 0000000000..9bcd79af7f
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/mac/crash_generation/crash_generation_client.h
@@ -0,0 +1,66 @@
+// Copyright (c) 2010 Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_BREAKPAD_CLIENT_MAC_CRASH_GENERATION_CRASH_GENERATION_CLIENT_H_
+#define GOOGLE_BREAKPAD_CLIENT_MAC_CRASH_GENERATION_CRASH_GENERATION_CLIENT_H_
+
+#include "common/mac/MachIPC.h"
+
+namespace google_breakpad {
+
+class CrashGenerationClient {
+ public:
+ explicit CrashGenerationClient(const char* mach_port_name)
+ : sender_(mach_port_name) {
+ }
+
+ // Request the crash server to generate a dump.
+ //
+ // Return true if the dump was successful; false otherwise.
+ bool RequestDumpForException(int exception_type,
+ int exception_code,
+ int64_t exception_subcode,
+ mach_port_t crashing_thread,
+ mach_port_t crashing_task);
+
+ bool RequestDump() {
+ return RequestDumpForException(0, 0, 0, MACH_PORT_NULL, mach_task_self());
+ }
+
+ private:
+ MachPortSender sender_;
+
+ // Prevent copy construction and assignment.
+ CrashGenerationClient(const CrashGenerationClient&);
+ CrashGenerationClient& operator=(const CrashGenerationClient&);
+};
+
+} // namespace google_breakpad
+
+#endif // GOOGLE_BREAKPAD_CLIENT_MAC_CRASH_GENERATION_CRASH_GENERATION_CLIENT_H_
diff --git a/toolkit/crashreporter/breakpad-client/mac/crash_generation/crash_generation_server.cc b/toolkit/crashreporter/breakpad-client/mac/crash_generation/crash_generation_server.cc
new file mode 100644
index 0000000000..b7b9b5881e
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/mac/crash_generation/crash_generation_server.cc
@@ -0,0 +1,164 @@
+// Copyright (c) 2010 Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "mac/crash_generation/crash_generation_server.h"
+
+#include <pthread.h>
+
+#include "mac/crash_generation/client_info.h"
+#include "mac/handler/minidump_generator.h"
+#include "common/mac/scoped_task_suspend-inl.h"
+
+namespace google_breakpad {
+
+CrashGenerationServer::CrashGenerationServer(
+ const char *mach_port_name,
+ FilterCallback filter,
+ void *filter_context,
+ OnClientDumpRequestCallback dump_callback,
+ void *dump_context,
+ OnClientExitingCallback exit_callback,
+ void *exit_context,
+ bool generate_dumps,
+ const std::string &dump_path)
+ : filter_(filter),
+ filter_context_(filter_context),
+ dump_callback_(dump_callback),
+ dump_context_(dump_context),
+ exit_callback_(exit_callback),
+ exit_context_(exit_context),
+ generate_dumps_(generate_dumps),
+ dump_dir_(dump_path.empty() ? "/tmp" : dump_path),
+ started_(false),
+ receive_port_(mach_port_name),
+ mach_port_name_(mach_port_name) {
+}
+
+CrashGenerationServer::~CrashGenerationServer() {
+ if (started_)
+ Stop();
+}
+
+bool CrashGenerationServer::Start() {
+ int thread_create_result = pthread_create(&server_thread_, NULL,
+ &WaitForMessages, this);
+ started_ = thread_create_result == 0;
+ return started_;
+}
+
+bool CrashGenerationServer::Stop() {
+ if (!started_)
+ return false;
+
+ // Send a quit message to the background thread, and then join it.
+ MachPortSender sender(mach_port_name_.c_str());
+ MachSendMessage quit_message(kQuitMessage);
+ const mach_msg_timeout_t kSendTimeoutMs = 2 * 1000;
+ kern_return_t result = sender.SendMessage(quit_message, kSendTimeoutMs);
+ if (result == KERN_SUCCESS) {
+ int thread_join_result = pthread_join(server_thread_, NULL);
+ started_ = thread_join_result != 0;
+ }
+
+ return !started_;
+}
+
+// static
+void *CrashGenerationServer::WaitForMessages(void *server) {
+ pthread_setname_np("Breakpad CrashGenerationServer");
+
+ CrashGenerationServer *self =
+ reinterpret_cast<CrashGenerationServer*>(server);
+ while (self->WaitForOneMessage()) {}
+ return NULL;
+}
+
+bool CrashGenerationServer::WaitForOneMessage() {
+ MachReceiveMessage message;
+ kern_return_t result = receive_port_.WaitForMessage(&message,
+ MACH_MSG_TIMEOUT_NONE);
+ if (result == KERN_SUCCESS) {
+ switch (message.GetMessageID()) {
+ case kDumpRequestMessage: {
+ ExceptionInfo &info = (ExceptionInfo &)*message.GetData();
+
+ mach_port_t remote_task = message.GetTranslatedPort(0);
+ mach_port_t crashing_thread = message.GetTranslatedPort(1);
+ mach_port_t handler_thread = message.GetTranslatedPort(2);
+ mach_port_t ack_port = message.GetTranslatedPort(3);
+ ClientInfo client(info.child_pid);
+
+ bool result;
+ std::string dump_path;
+ if (generate_dumps_ && (!filter_ || filter_(filter_context_))) {
+ ScopedTaskSuspend suspend(remote_task);
+
+ MinidumpGenerator generator(remote_task, handler_thread);
+ dump_path = generator.UniqueNameInDirectory(dump_dir_, NULL);
+
+ if (info.exception_type && info.exception_code) {
+ generator.SetExceptionInformation(info.exception_type,
+ info.exception_code,
+ info.exception_subcode,
+ crashing_thread);
+ }
+ result = generator.Write(dump_path.c_str());
+ } else {
+ result = true;
+ }
+
+ if (result && dump_callback_) {
+ dump_callback_(dump_context_, client, dump_path);
+ }
+
+ // TODO(ted): support a way for the client to send additional data,
+ // perhaps with a callback so users of the server can read the data
+ // themselves?
+
+ if (ack_port != MACH_PORT_DEAD && ack_port != MACH_PORT_NULL) {
+ MachPortSender sender(ack_port);
+ MachSendMessage ack_message(kAcknowledgementMessage);
+ sender.SendMessage(ack_message, MACH_MSG_TIMEOUT_NONE);
+ }
+
+ if (result && exit_callback_) {
+ exit_callback_(exit_context_, client);
+ }
+ break;
+ }
+ case kQuitMessage:
+ return false;
+ }
+ } else { // result != KERN_SUCCESS
+ return false;
+ }
+ return true;
+}
+
+} // namespace google_breakpad
diff --git a/toolkit/crashreporter/breakpad-client/mac/crash_generation/crash_generation_server.h b/toolkit/crashreporter/breakpad-client/mac/crash_generation/crash_generation_server.h
new file mode 100644
index 0000000000..d0b39f3acf
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/mac/crash_generation/crash_generation_server.h
@@ -0,0 +1,151 @@
+// Copyright (c) 2010 Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_BREAKPAD_CLIENT_MAC_CRASH_GENERATION_CRASH_GENERATION_SERVER_H_
+#define GOOGLE_BREAKPAD_CLIENT_MAC_CRASH_GENERATION_CRASH_GENERATION_SERVER_H_
+
+#include <stdint.h>
+
+#include <string>
+
+#include "common/mac/MachIPC.h"
+
+namespace google_breakpad {
+
+class ClientInfo;
+
+// Messages the server can read via its mach port
+enum {
+ kDumpRequestMessage = 1,
+ kAcknowledgementMessage = 2,
+ kQuitMessage = 3
+};
+
+// Exception details sent by the client when requesting a dump.
+struct ExceptionInfo {
+ int32_t exception_type;
+ int32_t exception_code;
+ int64_t exception_subcode;
+ int32_t child_pid;
+};
+
+class CrashGenerationServer {
+ public:
+ // WARNING: callbacks may be invoked on a different thread
+ // than that which creates the CrashGenerationServer. They must
+ // be thread safe.
+ typedef void (*OnClientDumpRequestCallback)(void *context,
+ const ClientInfo &client_info,
+ const std::string &file_path);
+
+ typedef void (*OnClientExitingCallback)(void *context,
+ const ClientInfo &client_info);
+ // If a FilterCallback returns false, the dump will not be written.
+ typedef bool (*FilterCallback)(void *context);
+
+ // Create an instance with the given parameters.
+ //
+ // mach_port_name: Named server port to listen on.
+ // filter: Callback for a client to cancel writing a dump.
+ // filter_context: Context for the filter callback.
+ // dump_callback: Callback for a client crash dump request.
+ // dump_context: Context for client crash dump request callback.
+ // exit_callback: Callback for client process exit.
+ // exit_context: Context for client exit callback.
+ // generate_dumps: Whether to automatically generate dumps.
+ // Client code of this class might want to generate dumps explicitly
+ // in the crash dump request callback. In that case, false can be
+ // passed for this parameter.
+ // dump_path: Path for generating dumps; required only if true is
+ // passed for generateDumps parameter; NULL can be passed otherwise.
+ CrashGenerationServer(const char *mach_port_name,
+ FilterCallback filter,
+ void *filter_context,
+ OnClientDumpRequestCallback dump_callback,
+ void *dump_context,
+ OnClientExitingCallback exit_callback,
+ void *exit_context,
+ bool generate_dumps,
+ const std::string &dump_path);
+
+ ~CrashGenerationServer();
+
+ // Perform initialization steps needed to start listening to clients.
+ //
+ // Return true if initialization is successful; false otherwise.
+ bool Start();
+
+ // Stop the server.
+ bool Stop();
+
+ private:
+ // Return a unique filename at which a minidump can be written.
+ bool MakeMinidumpFilename(std::string &outFilename);
+
+ // Loop reading client messages and responding to them until
+ // a quit message is received.
+ static void *WaitForMessages(void *server);
+
+ // Wait for a single client message and respond to it. Returns false
+ // if a quit message was received or if an error occurred.
+ bool WaitForOneMessage();
+
+ FilterCallback filter_;
+ void *filter_context_;
+
+ OnClientDumpRequestCallback dump_callback_;
+ void *dump_context_;
+
+ OnClientExitingCallback exit_callback_;
+ void *exit_context_;
+
+ bool generate_dumps_;
+
+ std::string dump_dir_;
+
+ bool started_;
+
+ // The mach port that receives requests to dump from child processes.
+ ReceivePort receive_port_;
+
+ // The name of the mach port. Stored so the Stop method can message
+ // the background thread to shut it down.
+ std::string mach_port_name_;
+
+ // The thread that waits on the receive port.
+ pthread_t server_thread_;
+
+ // Disable copy constructor and operator=.
+ CrashGenerationServer(const CrashGenerationServer&);
+ CrashGenerationServer& operator=(const CrashGenerationServer&);
+};
+
+} // namespace google_breakpad
+
+#endif // GOOGLE_BREAKPAD_CLIENT_MAC_CRASH_GENERATION_CRASH_GENERATION_SERVER_H_
diff --git a/toolkit/crashreporter/breakpad-client/mac/crash_generation/moz.build b/toolkit/crashreporter/breakpad-client/mac/crash_generation/moz.build
new file mode 100644
index 0000000000..731670a4f1
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/mac/crash_generation/moz.build
@@ -0,0 +1,18 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+UNIFIED_SOURCES += [
+ 'crash_generation_client.cc',
+ 'crash_generation_server.cc',
+]
+
+FINAL_LIBRARY = 'breakpad_client'
+
+LOCAL_INCLUDES += [
+ '/ipc/chromium/src',
+ '/toolkit/crashreporter/breakpad-client',
+ '/toolkit/crashreporter/google-breakpad/src',
+]
diff --git a/toolkit/crashreporter/breakpad-client/mac/handler/breakpad_nlist_64.cc b/toolkit/crashreporter/breakpad-client/mac/handler/breakpad_nlist_64.cc
new file mode 100644
index 0000000000..3492b823da
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/mac/handler/breakpad_nlist_64.cc
@@ -0,0 +1,402 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+
+/*
+ * This file was copied from libc/gen/nlist.c from Darwin's source code
+ * The version of nlist used as a base is from 10.5.2, libc-498
+ * http://www.opensource.apple.com/darwinsource/10.5.2/Libc-498/gen/nlist.c
+ *
+ * The full tarball is at:
+ * http://www.opensource.apple.com/darwinsource/tarballs/apsl/Libc-498.tar.gz
+ *
+ * I've modified it to be compatible with 64-bit images.
+*/
+
+#include "breakpad_nlist_64.h"
+
+#include <CoreFoundation/CoreFoundation.h>
+#include <fcntl.h>
+#include <mach-o/nlist.h>
+#include <mach-o/loader.h>
+#include <mach-o/fat.h>
+#include <mach/mach.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/uio.h>
+#include <TargetConditionals.h>
+#include <unistd.h>
+
+/* Stuff lifted from <a.out.h> and <sys/exec.h> since they are gone */
+/*
+ * Header prepended to each a.out file.
+ */
+struct exec {
+ unsigned short a_machtype; /* machine type */
+ unsigned short a_magic; /* magic number */
+ unsigned long a_text; /* size of text segment */
+ unsigned long a_data; /* size of initialized data */
+ unsigned long a_bss; /* size of uninitialized data */
+ unsigned long a_syms; /* size of symbol table */
+ unsigned long a_entry; /* entry point */
+ unsigned long a_trsize; /* size of text relocation */
+ unsigned long a_drsize; /* size of data relocation */
+};
+
+#define OMAGIC 0407 /* old impure format */
+#define NMAGIC 0410 /* read-only text */
+#define ZMAGIC 0413 /* demand load format */
+
+#define N_BADMAG(x) \
+ (((x).a_magic)!=OMAGIC && ((x).a_magic)!=NMAGIC && ((x).a_magic)!=ZMAGIC)
+#define N_TXTOFF(x) \
+ ((x).a_magic==ZMAGIC ? 0 : sizeof (struct exec))
+#define N_SYMOFF(x) \
+ (N_TXTOFF(x) + (x).a_text+(x).a_data + (x).a_trsize+(x).a_drsize)
+
+// Traits structs for specializing function templates to handle
+// 32-bit/64-bit Mach-O files.
+template<typename T>
+struct MachBits {};
+
+typedef struct nlist nlist32;
+typedef struct nlist_64 nlist64;
+
+template<>
+struct MachBits<nlist32> {
+ typedef mach_header mach_header_type;
+ typedef uint32_t word_type;
+ static const uint32_t magic = MH_MAGIC;
+};
+
+template<>
+struct MachBits<nlist64> {
+ typedef mach_header_64 mach_header_type;
+ typedef uint64_t word_type;
+ static const uint32_t magic = MH_MAGIC_64;
+};
+
+template<typename nlist_type>
+int
+__breakpad_fdnlist(int fd, nlist_type *list, const char **symbolNames,
+ cpu_type_t cpu_type);
+
+/*
+ * nlist - retreive attributes from name list (string table version)
+ */
+
+template <typename nlist_type>
+int breakpad_nlist_common(const char *name,
+ nlist_type *list,
+ const char **symbolNames,
+ cpu_type_t cpu_type) {
+ int fd = open(name, O_RDONLY, 0);
+ if (fd < 0)
+ return -1;
+ int n = __breakpad_fdnlist(fd, list, symbolNames, cpu_type);
+ close(fd);
+ return n;
+}
+
+int breakpad_nlist(const char *name,
+ struct nlist *list,
+ const char **symbolNames,
+ cpu_type_t cpu_type) {
+ return breakpad_nlist_common(name, list, symbolNames, cpu_type);
+}
+
+int breakpad_nlist(const char *name,
+ struct nlist_64 *list,
+ const char **symbolNames,
+ cpu_type_t cpu_type) {
+ return breakpad_nlist_common(name, list, symbolNames, cpu_type);
+}
+
+/* Note: __fdnlist() is called from kvm_nlist in libkvm's kvm.c */
+
+template<typename nlist_type>
+int __breakpad_fdnlist(int fd, nlist_type *list, const char **symbolNames,
+ cpu_type_t cpu_type) {
+ typedef typename MachBits<nlist_type>::mach_header_type mach_header_type;
+ typedef typename MachBits<nlist_type>::word_type word_type;
+
+ const uint32_t magic = MachBits<nlist_type>::magic;
+
+ int maxlen = 500;
+ int nreq = 0;
+ for (nlist_type* q = list;
+ symbolNames[q-list] && symbolNames[q-list][0];
+ q++, nreq++) {
+
+ q->n_type = 0;
+ q->n_value = 0;
+ q->n_desc = 0;
+ q->n_sect = 0;
+ q->n_un.n_strx = 0;
+ }
+
+ struct exec buf;
+ if (read(fd, (char *)&buf, sizeof(buf)) != sizeof(buf) ||
+ (N_BADMAG(buf) && *((uint32_t *)&buf) != magic &&
+ CFSwapInt32BigToHost(*((uint32_t *)&buf)) != FAT_MAGIC &&
+ /* The following is the big-endian ppc64 check */
+ (*((uint32_t*)&buf)) != FAT_MAGIC)) {
+ return -1;
+ }
+
+ /* Deal with fat file if necessary */
+ unsigned arch_offset = 0;
+ if (CFSwapInt32BigToHost(*((uint32_t *)&buf)) == FAT_MAGIC ||
+ /* The following is the big-endian ppc64 check */
+ *((unsigned int *)&buf) == FAT_MAGIC) {
+ /* Read in the fat header */
+ struct fat_header fh;
+ if (lseek(fd, 0, SEEK_SET) == -1) {
+ return -1;
+ }
+ if (read(fd, (char *)&fh, sizeof(fh)) != sizeof(fh)) {
+ return -1;
+ }
+
+ /* Convert fat_narchs to host byte order */
+ fh.nfat_arch = CFSwapInt32BigToHost(fh.nfat_arch);
+
+ /* Read in the fat archs */
+ struct fat_arch *fat_archs =
+ (struct fat_arch *)malloc(fh.nfat_arch * sizeof(struct fat_arch));
+ if (fat_archs == NULL) {
+ return -1;
+ }
+ if (read(fd, (char *)fat_archs,
+ sizeof(struct fat_arch) * fh.nfat_arch) !=
+ (ssize_t)(sizeof(struct fat_arch) * fh.nfat_arch)) {
+ free(fat_archs);
+ return -1;
+ }
+
+ /*
+ * Convert archs to host byte ordering (a constraint of
+ * cpusubtype_getbestarch()
+ */
+ for (unsigned i = 0; i < fh.nfat_arch; i++) {
+ fat_archs[i].cputype =
+ CFSwapInt32BigToHost(fat_archs[i].cputype);
+ fat_archs[i].cpusubtype =
+ CFSwapInt32BigToHost(fat_archs[i].cpusubtype);
+ fat_archs[i].offset =
+ CFSwapInt32BigToHost(fat_archs[i].offset);
+ fat_archs[i].size =
+ CFSwapInt32BigToHost(fat_archs[i].size);
+ fat_archs[i].align =
+ CFSwapInt32BigToHost(fat_archs[i].align);
+ }
+
+ struct fat_arch *fap = NULL;
+ for (unsigned i = 0; i < fh.nfat_arch; i++) {
+ if (fat_archs[i].cputype == cpu_type) {
+ fap = &fat_archs[i];
+ break;
+ }
+ }
+
+ if (!fap) {
+ free(fat_archs);
+ return -1;
+ }
+ arch_offset = fap->offset;
+ free(fat_archs);
+
+ /* Read in the beginning of the architecture-specific file */
+ if (lseek(fd, arch_offset, SEEK_SET) == -1) {
+ return -1;
+ }
+ if (read(fd, (char *)&buf, sizeof(buf)) != sizeof(buf)) {
+ return -1;
+ }
+ }
+
+ off_t sa; /* symbol address */
+ off_t ss; /* start of strings */
+ register_t n;
+ if (*((unsigned int *)&buf) == magic) {
+ if (lseek(fd, arch_offset, SEEK_SET) == -1) {
+ return -1;
+ }
+ mach_header_type mh;
+ if (read(fd, (char *)&mh, sizeof(mh)) != sizeof(mh)) {
+ return -1;
+ }
+
+ struct load_command *load_commands =
+ (struct load_command *)malloc(mh.sizeofcmds);
+ if (load_commands == NULL) {
+ return -1;
+ }
+ if (read(fd, (char *)load_commands, mh.sizeofcmds) !=
+ (ssize_t)mh.sizeofcmds) {
+ free(load_commands);
+ return -1;
+ }
+ struct symtab_command *stp = NULL;
+ struct load_command *lcp = load_commands;
+ // iterate through all load commands, looking for
+ // LC_SYMTAB load command
+ for (uint32_t i = 0; i < mh.ncmds; i++) {
+ if (lcp->cmdsize % sizeof(word_type) != 0 ||
+ lcp->cmdsize <= 0 ||
+ (char *)lcp + lcp->cmdsize >
+ (char *)load_commands + mh.sizeofcmds) {
+ free(load_commands);
+ return -1;
+ }
+ if (lcp->cmd == LC_SYMTAB) {
+ if (lcp->cmdsize !=
+ sizeof(struct symtab_command)) {
+ free(load_commands);
+ return -1;
+ }
+ stp = (struct symtab_command *)lcp;
+ break;
+ }
+ lcp = (struct load_command *)
+ ((char *)lcp + lcp->cmdsize);
+ }
+ if (stp == NULL) {
+ free(load_commands);
+ return -1;
+ }
+ // sa points to the beginning of the symbol table
+ sa = stp->symoff + arch_offset;
+ // ss points to the beginning of the string table
+ ss = stp->stroff + arch_offset;
+ // n is the number of bytes in the symbol table
+ // each symbol table entry is an nlist structure
+ n = stp->nsyms * sizeof(nlist_type);
+ free(load_commands);
+ } else {
+ sa = N_SYMOFF(buf) + arch_offset;
+ ss = sa + buf.a_syms + arch_offset;
+ n = buf.a_syms;
+ }
+
+ if (lseek(fd, sa, SEEK_SET) == -1) {
+ return -1;
+ }
+
+ // the algorithm here is to read the nlist entries in m-sized
+ // chunks into q. q is then iterated over. for each entry in q,
+ // use the string table index(q->n_un.n_strx) to read the symbol
+ // name, then scan the nlist entries passed in by the user(via p),
+ // and look for a match
+ while (n) {
+ nlist_type space[BUFSIZ/sizeof (nlist_type)];
+ register_t m = sizeof (space);
+
+ if (n < m)
+ m = n;
+ if (read(fd, (char *)space, m) != m)
+ break;
+ n -= m;
+ off_t savpos = lseek(fd, 0, SEEK_CUR);
+ if (savpos == -1) {
+ return -1;
+ }
+ for (nlist_type* q = space; (m -= sizeof(nlist_type)) >= 0; q++) {
+ char nambuf[BUFSIZ];
+
+ if (q->n_un.n_strx == 0 || q->n_type & N_STAB)
+ continue;
+
+ // seek to the location in the binary where the symbol
+ // name is stored & read it into memory
+ if (lseek(fd, ss+q->n_un.n_strx, SEEK_SET) == -1) {
+ return -1;
+ }
+ if (read(fd, nambuf, maxlen+1) == -1) {
+ return -1;
+ }
+ const char *s2 = nambuf;
+ for (nlist_type *p = list;
+ symbolNames[p-list] && symbolNames[p-list][0];
+ p++) {
+ // get the symbol name the user has passed in that
+ // corresponds to the nlist entry that we're looking at
+ const char *s1 = symbolNames[p - list];
+ while (*s1) {
+ if (*s1++ != *s2++)
+ goto cont;
+ }
+ if (*s2)
+ goto cont;
+
+ p->n_value = q->n_value;
+ p->n_type = q->n_type;
+ p->n_desc = q->n_desc;
+ p->n_sect = q->n_sect;
+ p->n_un.n_strx = q->n_un.n_strx;
+ if (--nreq == 0)
+ return nreq;
+
+ break;
+ cont: ;
+ }
+ }
+ if (lseek(fd, savpos, SEEK_SET) == -1) {
+ return -1;
+ }
+ }
+ return nreq;
+}
diff --git a/toolkit/crashreporter/breakpad-client/mac/handler/breakpad_nlist_64.h b/toolkit/crashreporter/breakpad-client/mac/handler/breakpad_nlist_64.h
new file mode 100644
index 0000000000..e8e2e0834e
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/mac/handler/breakpad_nlist_64.h
@@ -0,0 +1,48 @@
+// Copyright (c) 2008, Google Inc.
+// All rights reserved
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// breakpad_nlist.h
+//
+// This file is meant to provide a header for clients of the modified
+// nlist function implemented to work on 64-bit.
+
+#ifndef CLIENT_MAC_HANDLER_BREAKPAD_NLIST_H__
+#define CLIENT_MAC_HANDLER_BREAKPAD_NLIST_H__
+
+#include <mach/machine.h>
+
+int breakpad_nlist(const char *name,
+ struct nlist *list,
+ const char **symbolNames,
+ cpu_type_t cpu_type);
+int breakpad_nlist(const char *name,
+ struct nlist_64 *list,
+ const char **symbolNames,
+ cpu_type_t cpu_type);
+
+#endif /* CLIENT_MAC_HANDLER_BREAKPAD_NLIST_H__ */
diff --git a/toolkit/crashreporter/breakpad-client/mac/handler/dynamic_images.cc b/toolkit/crashreporter/breakpad-client/mac/handler/dynamic_images.cc
new file mode 100644
index 0000000000..855580a071
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/mac/handler/dynamic_images.cc
@@ -0,0 +1,625 @@
+// Copyright (c) 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "mac/handler/dynamic_images.h"
+
+extern "C" { // needed to compile on Leopard
+ #include <mach-o/nlist.h>
+ #include <stdlib.h>
+ #include <stdio.h>
+}
+
+#include <assert.h>
+#include <AvailabilityMacros.h>
+#include <dlfcn.h>
+#include <mach/task_info.h>
+#include <sys/sysctl.h>
+#include <TargetConditionals.h>
+#include <unistd.h>
+
+#include <algorithm>
+#include <string>
+#include <vector>
+
+#include "breakpad_nlist_64.h"
+
+#if !TARGET_OS_IPHONE
+#include <CoreServices/CoreServices.h>
+#endif // !TARGET_OS_IPHONE
+
+namespace google_breakpad {
+
+using std::string;
+using std::vector;
+
+//==============================================================================
+// Returns the size of the memory region containing |address| and the
+// number of bytes from |address| to the end of the region.
+// We potentially, will extend the size of the original
+// region by the size of the following region if it's contiguous with the
+// first in order to handle cases when we're reading strings and they
+// straddle two vm regions.
+//
+static mach_vm_size_t GetMemoryRegionSize(task_port_t target_task,
+ const uint64_t address,
+ mach_vm_size_t *size_to_end) {
+ mach_vm_address_t region_base = (mach_vm_address_t)address;
+ mach_vm_size_t region_size;
+ natural_t nesting_level = 0;
+ vm_region_submap_info_64 submap_info;
+ mach_msg_type_number_t info_count = VM_REGION_SUBMAP_INFO_COUNT_64;
+
+ // Get information about the vm region containing |address|
+ vm_region_recurse_info_t region_info;
+ region_info = reinterpret_cast<vm_region_recurse_info_t>(&submap_info);
+
+ kern_return_t result =
+ mach_vm_region_recurse(target_task,
+ &region_base,
+ &region_size,
+ &nesting_level,
+ region_info,
+ &info_count);
+
+ if (result == KERN_SUCCESS) {
+ // Get distance from |address| to the end of this region
+ *size_to_end = region_base + region_size -(mach_vm_address_t)address;
+
+ // If we want to handle strings as long as 4096 characters we may need
+ // to check if there's a vm region immediately following the first one.
+ // If so, we need to extend |*size_to_end| to go all the way to the end
+ // of the second region.
+ if (*size_to_end < 4096) {
+ // Second region starts where the first one ends
+ mach_vm_address_t region_base2 =
+ (mach_vm_address_t)(region_base + region_size);
+ mach_vm_size_t region_size2;
+
+ // Get information about the following vm region
+ result =
+ mach_vm_region_recurse(target_task,
+ &region_base2,
+ &region_size2,
+ &nesting_level,
+ region_info,
+ &info_count);
+
+ // Extend region_size to go all the way to the end of the 2nd region
+ if (result == KERN_SUCCESS
+ && region_base2 == region_base + region_size) {
+ region_size += region_size2;
+ }
+ }
+
+ *size_to_end = region_base + region_size -(mach_vm_address_t)address;
+ } else {
+ region_size = 0;
+ *size_to_end = 0;
+ }
+
+ return region_size;
+}
+
+#define kMaxStringLength 8192
+//==============================================================================
+// Reads a NULL-terminated string from another task.
+//
+// Warning! This will not read any strings longer than kMaxStringLength-1
+//
+string ReadTaskString(task_port_t target_task,
+ const uint64_t address) {
+ // The problem is we don't know how much to read until we know how long
+ // the string is. And we don't know how long the string is, until we've read
+ // the memory! So, we'll try to read kMaxStringLength bytes
+ // (or as many bytes as we can until we reach the end of the vm region).
+ mach_vm_size_t size_to_end;
+ GetMemoryRegionSize(target_task, address, &size_to_end);
+
+ if (size_to_end > 0) {
+ mach_vm_size_t size_to_read =
+ size_to_end > kMaxStringLength ? kMaxStringLength : size_to_end;
+
+ vector<uint8_t> bytes;
+ if (ReadTaskMemory(target_task, address, (size_t)size_to_read, bytes) !=
+ KERN_SUCCESS)
+ return string();
+
+ return string(reinterpret_cast<const char*>(&bytes[0]));
+ }
+
+ return string();
+}
+
+//==============================================================================
+// Reads an address range from another task. The bytes read will be returned
+// in bytes, which will be resized as necessary.
+kern_return_t ReadTaskMemory(task_port_t target_task,
+ const uint64_t address,
+ size_t length,
+ vector<uint8_t> &bytes) {
+ int systemPageSize = getpagesize();
+
+ // use the negative of the page size for the mask to find the page address
+ mach_vm_address_t page_address = address & (-systemPageSize);
+
+ mach_vm_address_t last_page_address =
+ (address + length + (systemPageSize - 1)) & (-systemPageSize);
+
+ mach_vm_size_t page_size = last_page_address - page_address;
+ uint8_t* local_start;
+ uint32_t local_length;
+
+ kern_return_t r = mach_vm_read(target_task,
+ page_address,
+ page_size,
+ reinterpret_cast<vm_offset_t*>(&local_start),
+ &local_length);
+
+ if (r != KERN_SUCCESS)
+ return r;
+
+ bytes.resize(length);
+ memcpy(&bytes[0],
+ &local_start[(mach_vm_address_t)address - page_address],
+ length);
+ mach_vm_deallocate(mach_task_self(), (uintptr_t)local_start, local_length);
+ return KERN_SUCCESS;
+}
+
+#pragma mark -
+
+//==============================================================================
+// Traits structs for specializing function templates to handle
+// 32-bit/64-bit Mach-O files.
+struct MachO32 {
+ typedef mach_header mach_header_type;
+ typedef segment_command mach_segment_command_type;
+ typedef dyld_image_info32 dyld_image_info;
+ typedef dyld_all_image_infos32 dyld_all_image_infos;
+ typedef section mach_section_type;
+ typedef struct nlist nlist_type;
+ static const uint32_t magic = MH_MAGIC;
+ static const uint32_t segment_load_command = LC_SEGMENT;
+};
+
+struct MachO64 {
+ typedef mach_header_64 mach_header_type;
+ typedef segment_command_64 mach_segment_command_type;
+ typedef dyld_image_info64 dyld_image_info;
+ typedef dyld_all_image_infos64 dyld_all_image_infos;
+ typedef section_64 mach_section_type;
+ typedef struct nlist_64 nlist_type;
+ static const uint32_t magic = MH_MAGIC_64;
+ static const uint32_t segment_load_command = LC_SEGMENT_64;
+};
+
+template<typename MachBits>
+bool FindTextSection(DynamicImage& image) {
+ typedef typename MachBits::mach_header_type mach_header_type;
+ typedef typename MachBits::mach_segment_command_type
+ mach_segment_command_type;
+ typedef typename MachBits::mach_section_type mach_section_type;
+
+ const mach_header_type* header =
+ reinterpret_cast<const mach_header_type*>(&image.header_[0]);
+
+ if(header->magic != MachBits::magic) {
+ return false;
+ }
+
+ bool is_in_shared_cache = ((header->flags & MH_SHAREDCACHE) != 0);
+ if (is_in_shared_cache) {
+ image.slide_ = image.shared_cache_slide_;
+ }
+
+ const struct load_command *cmd =
+ reinterpret_cast<const struct load_command *>(header + 1);
+
+ bool retval = false;
+
+ uint32_t num_data_sections = 0;
+ const mach_section_type *data_sections = NULL;
+ uint32_t num_data_dirty_sections = 0;
+ const mach_section_type *data_dirty_sections = NULL;
+ bool found_text_section = false;
+ bool found_dylib_id_command = false;
+ for (unsigned int i = 0; cmd && (i < header->ncmds); ++i) {
+ if (!data_sections) {
+ if (cmd->cmd == MachBits::segment_load_command) {
+ const mach_segment_command_type *seg =
+ reinterpret_cast<const mach_segment_command_type *>(cmd);
+
+ if (!strcmp(seg->segname, "__DATA")) {
+ num_data_sections = seg->nsects;
+ data_sections = reinterpret_cast<const mach_section_type *>(seg + 1);
+ }
+ }
+ }
+
+ if (!data_dirty_sections) {
+ if (cmd->cmd == MachBits::segment_load_command) {
+ const mach_segment_command_type *seg =
+ reinterpret_cast<const mach_segment_command_type *>(cmd);
+
+ if (!strcmp(seg->segname, "__DATA_DIRTY")) {
+ num_data_dirty_sections = seg->nsects;
+ data_dirty_sections =
+ reinterpret_cast<const mach_section_type *>(seg + 1);
+ }
+ }
+ }
+
+ if (!found_text_section) {
+ if (cmd->cmd == MachBits::segment_load_command) {
+ const mach_segment_command_type *seg =
+ reinterpret_cast<const mach_segment_command_type *>(cmd);
+
+ if (!is_in_shared_cache) {
+ if (seg->fileoff == 0 && seg->filesize != 0) {
+ image.slide_ =
+ (uintptr_t)image.GetLoadAddress() - (uintptr_t)seg->vmaddr;
+ }
+ }
+
+ if (!strcmp(seg->segname, "__TEXT")) {
+ image.vmaddr_ = static_cast<mach_vm_address_t>(seg->vmaddr);
+ image.vmsize_ = static_cast<mach_vm_size_t>(seg->vmsize);
+ found_text_section = true;
+ }
+ }
+ }
+
+ if (!found_dylib_id_command) {
+ if (cmd->cmd == LC_ID_DYLIB) {
+ const struct dylib_command *dc =
+ reinterpret_cast<const struct dylib_command *>(cmd);
+
+ image.version_ = dc->dylib.current_version;
+ found_dylib_id_command = true;
+ }
+ }
+
+ if (found_dylib_id_command && found_text_section &&
+ data_sections && data_dirty_sections) {
+ break;
+ }
+
+ cmd = reinterpret_cast<const struct load_command *>
+ (reinterpret_cast<const char *>(cmd) + cmd->cmdsize);
+ }
+
+ if (found_dylib_id_command && found_text_section) {
+ retval = true;
+ }
+
+ // The __DYLD,__crash_info section may not be accessible in child process
+ // modules that aren't dyld or in the dyld shared cache.
+ if (image.GetIsDyld() || is_in_shared_cache) {
+ for (unsigned int i = 0; i < num_data_sections; ++i) {
+ if (!strcmp(data_sections[i].sectname, "__crash_info")) {
+ ReadTaskMemory(image.task_,
+ data_sections[i].addr + image.slide_,
+ data_sections[i].size,
+ image.crash_info_);
+ return retval;
+ }
+ }
+ // __crash_info might be in the __DATA_DIRTY segment.
+ for (unsigned int i = 0; i < num_data_dirty_sections; ++i) {
+ if (!strcmp(data_dirty_sections[i].sectname, "__crash_info")) {
+ ReadTaskMemory(image.task_,
+ data_dirty_sections[i].addr + image.slide_,
+ data_dirty_sections[i].size,
+ image.crash_info_);
+ return retval;
+ }
+ }
+ }
+
+ return retval;
+}
+
+//==============================================================================
+// Initializes vmaddr_, vmsize_, and slide_
+void DynamicImage::CalculateMemoryAndVersionInfo() {
+ // unless we can process the header, ensure that calls to
+ // IsValid() will return false
+ vmaddr_ = 0;
+ vmsize_ = 0;
+ slide_ = 0;
+ version_ = 0;
+
+ // The function template above does all the real work.
+ if (Is64Bit())
+ FindTextSection<MachO64>(*this);
+ else
+ FindTextSection<MachO32>(*this);
+}
+
+//==============================================================================
+// The helper function template abstracts the 32/64-bit differences.
+template<typename MachBits>
+uint32_t GetFileTypeFromHeader(DynamicImage& image) {
+ typedef typename MachBits::mach_header_type mach_header_type;
+
+ const mach_header_type* header =
+ reinterpret_cast<const mach_header_type*>(&image.header_[0]);
+ return header->filetype;
+}
+
+uint32_t DynamicImage::GetFileType() {
+ if (Is64Bit())
+ return GetFileTypeFromHeader<MachO64>(*this);
+
+ return GetFileTypeFromHeader<MachO32>(*this);
+}
+
+#pragma mark -
+
+//==============================================================================
+// Loads information about dynamically loaded code in the given task.
+DynamicImages::DynamicImages(mach_port_t task)
+ : task_(task),
+ cpu_type_(DetermineTaskCPUType(task)),
+ image_list_() {
+ ReadImageInfoForTask();
+}
+
+template<typename MachBits>
+static uint64_t LookupSymbol(const char* symbol_name,
+ const char* filename,
+ cpu_type_t cpu_type) {
+ typedef typename MachBits::nlist_type nlist_type;
+
+ nlist_type symbol_info[8] = {};
+ const char *symbolNames[2] = { symbol_name, "\0" };
+ nlist_type &list = symbol_info[0];
+ int invalidEntriesCount = breakpad_nlist(filename,
+ &list,
+ symbolNames,
+ cpu_type);
+
+ if(invalidEntriesCount != 0) {
+ return 0;
+ }
+
+ assert(list.n_value);
+ return list.n_value;
+}
+
+uint64_t DynamicImages::GetDyldAllImageInfosPointer() {
+ task_dyld_info_data_t task_dyld_info;
+ mach_msg_type_number_t count = TASK_DYLD_INFO_COUNT;
+ if (task_info(task_, TASK_DYLD_INFO, (task_info_t)&task_dyld_info,
+ &count) != KERN_SUCCESS) {
+ return 0;
+ }
+
+ return (uint64_t)task_dyld_info.all_image_info_addr;
+}
+
+//==============================================================================
+// This code was written using dyld_debug.c (from Darwin) as a guide.
+
+template<typename MachBits>
+void ReadOneImageInfo(DynamicImages& images, uint64_t image_address,
+ uint64_t file_path_address, uint64_t file_mod_date,
+ uint64_t shared_cache_slide, bool is_dyld) {
+ typedef typename MachBits::mach_header_type mach_header_type;
+
+ // First read just the mach_header from the image in the task.
+ vector<uint8_t> mach_header_bytes;
+ if (ReadTaskMemory(images.task_,
+ image_address,
+ sizeof(mach_header_type),
+ mach_header_bytes) != KERN_SUCCESS) {
+ return; // bail on this dynamic image
+ }
+
+ mach_header_type *header =
+ reinterpret_cast<mach_header_type*>(&mach_header_bytes[0]);
+ if (header->magic != MachBits::magic) {
+ return;
+ }
+
+ cpu_subtype_t cpusubtype = (header->cpusubtype & ~CPU_SUBTYPE_MASK);
+
+ // Now determine the total amount necessary to read the header
+ // plus all of the load commands.
+ size_t header_size = sizeof(mach_header_type) + header->sizeofcmds;
+
+ if (ReadTaskMemory(images.task_,
+ image_address,
+ header_size,
+ mach_header_bytes) != KERN_SUCCESS) {
+ return;
+ }
+
+ // Read the file name from the task's memory space.
+ string file_path;
+ if (file_path_address) {
+ // Although we're reading kMaxStringLength bytes, it's copied in the
+ // the DynamicImage constructor below with the correct string length,
+ // so it's not really wasting memory.
+ file_path = ReadTaskString(images.task_, file_path_address);
+ }
+
+ // Create an object representing this image and add it to our list.
+ DynamicImage *new_image;
+ new_image = new DynamicImage(&mach_header_bytes[0],
+ header_size,
+ image_address,
+ file_path,
+ static_cast<uintptr_t>(file_mod_date),
+ images.task_,
+ images.cpu_type_,
+ cpusubtype,
+ shared_cache_slide,
+ is_dyld);
+
+ if (new_image->IsValid()) {
+ images.image_list_.push_back(DynamicImageRef(new_image));
+ } else {
+ delete new_image;
+ }
+}
+
+template<typename MachBits>
+void ReadImageInfo(DynamicImages& images,
+ uint64_t image_list_address) {
+ typedef typename MachBits::dyld_image_info dyld_image_info;
+ typedef typename MachBits::dyld_all_image_infos dyld_all_image_infos;
+
+ // Read the structure inside of dyld that contains information about
+ // loaded images. We're reading from the desired task's address space.
+
+ // Here we make the assumption that dyld loaded at the same address in
+ // the crashed process vs. this one. This is an assumption made in
+ // "dyld_debug.c" and is said to be nearly always valid.
+ vector<uint8_t> dyld_all_info_bytes;
+ if (ReadTaskMemory(images.task_,
+ image_list_address,
+ sizeof(dyld_all_image_infos),
+ dyld_all_info_bytes) != KERN_SUCCESS) {
+ return;
+ }
+
+ dyld_all_image_infos *dyldInfo =
+ reinterpret_cast<dyld_all_image_infos*>(&dyld_all_info_bytes[0]);
+
+ // number of loaded images
+ int count = dyldInfo->infoArrayCount;
+
+ // Read an array of dyld_image_info structures each containing
+ // information about a loaded image.
+ vector<uint8_t> dyld_info_array_bytes;
+ if (ReadTaskMemory(images.task_,
+ dyldInfo->infoArray,
+ count * sizeof(dyld_image_info),
+ dyld_info_array_bytes) != KERN_SUCCESS) {
+ return;
+ }
+
+ dyld_image_info *infoArray =
+ reinterpret_cast<dyld_image_info*>(&dyld_info_array_bytes[0]);
+ // Add room for dyld at the end
+ images.image_list_.reserve(count + 1);
+
+ for (int i = 0; i < count; ++i) {
+ dyld_image_info &info = infoArray[i];
+ ReadOneImageInfo<MachBits>(images, info.load_address_,
+ info.file_path_, info.file_mod_date_,
+ dyldInfo->sharedCacheSlide,
+ /* is_dyld */ false);
+ }
+
+ // Add an image for dyld itself. It doesn't appear in the standard list of
+ // modules.
+ uint64_t dyld_address = (uint64_t) dyldInfo->dyldImageLoadAddress;
+ if (dyld_address) {
+ ReadOneImageInfo<MachBits>(images, dyld_address,
+ (uint64_t) dyldInfo->dyldPath,
+ /* file_mod_date */ 0,
+ dyldInfo->sharedCacheSlide,
+ /* is_dyld */ true);
+ }
+
+ // sorts based on loading address
+ sort(images.image_list_.begin(), images.image_list_.end());
+ // remove duplicates - this happens in certain strange cases
+ // You can see it in DashboardClient when Google Gadgets plugin
+ // is installed. Apple's crash reporter log and gdb "info shared"
+ // both show the same library multiple times at the same address
+
+ vector<DynamicImageRef>::iterator it = unique(images.image_list_.begin(),
+ images.image_list_.end());
+ images.image_list_.erase(it, images.image_list_.end());
+}
+
+void DynamicImages::ReadImageInfoForTask() {
+ uint64_t imageList = GetDyldAllImageInfosPointer();
+
+ if (imageList) {
+ if (Is64Bit())
+ ReadImageInfo<MachO64>(*this, imageList);
+ else
+ ReadImageInfo<MachO32>(*this, imageList);
+ }
+}
+
+//==============================================================================
+DynamicImage *DynamicImages::GetExecutableImage() {
+ int executable_index = GetExecutableImageIndex();
+
+ if (executable_index >= 0) {
+ return GetImage(executable_index);
+ }
+
+ return NULL;
+}
+
+//==============================================================================
+// returns -1 if failure to find executable
+int DynamicImages::GetExecutableImageIndex() {
+ int image_count = GetImageCount();
+
+ for (int i = 0; i < image_count; ++i) {
+ DynamicImage *image = GetImage(i);
+ if (image->GetFileType() == MH_EXECUTE) {
+ return i;
+ }
+ }
+
+ return -1;
+}
+
+//==============================================================================
+// static
+cpu_type_t DynamicImages::DetermineTaskCPUType(task_t task) {
+ if (task == mach_task_self())
+ return GetNativeCPUType();
+
+ int mib[CTL_MAXNAME];
+ size_t mibLen = CTL_MAXNAME;
+ int err = sysctlnametomib("sysctl.proc_cputype", mib, &mibLen);
+ if (err == 0) {
+ assert(mibLen < CTL_MAXNAME);
+ pid_for_task(task, &mib[mibLen]);
+ mibLen += 1;
+
+ cpu_type_t cpu_type;
+ size_t cpuTypeSize = sizeof(cpu_type);
+ sysctl(mib, static_cast<u_int>(mibLen), &cpu_type, &cpuTypeSize, 0, 0);
+ return cpu_type;
+ }
+
+ return GetNativeCPUType();
+}
+
+} // namespace google_breakpad
diff --git a/toolkit/crashreporter/breakpad-client/mac/handler/dynamic_images.h b/toolkit/crashreporter/breakpad-client/mac/handler/dynamic_images.h
new file mode 100644
index 0000000000..e225c00b88
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/mac/handler/dynamic_images.h
@@ -0,0 +1,386 @@
+// Copyright (c) 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// dynamic_images.h
+//
+// Implements most of the function of the dyld API, but allowing an
+// arbitrary task to be introspected, unlike the dyld API which
+// only allows operation on the current task. The current implementation
+// is limited to use by 32-bit tasks.
+
+#ifndef CLIENT_MAC_HANDLER_DYNAMIC_IMAGES_H__
+#define CLIENT_MAC_HANDLER_DYNAMIC_IMAGES_H__
+
+#include <mach/mach.h>
+#include <mach-o/dyld.h>
+#include <mach-o/loader.h>
+#include <sys/types.h>
+
+#include <string>
+#include <vector>
+
+#include "mach_vm_compat.h"
+
+namespace google_breakpad {
+
+using std::string;
+using std::vector;
+
+//==============================================================================
+// The memory layout of this struct matches the dyld_image_info struct
+// defined in "dyld_gdb.h" in the darwin source.
+typedef struct dyld_image_info32 {
+ uint32_t load_address_; // struct mach_header*
+ uint32_t file_path_; // char*
+ uint32_t file_mod_date_;
+} dyld_image_info32;
+
+typedef struct dyld_image_info64 {
+ uint64_t load_address_; // struct mach_header*
+ uint64_t file_path_; // char*
+ uint64_t file_mod_date_;
+} dyld_image_info64;
+
+//==============================================================================
+// This is as defined in "dyld_gdb.h" in the darwin source.
+// _dyld_all_image_infos (in dyld) is a structure of this type
+// which will be used to determine which dynamic code has been loaded.
+typedef struct dyld_all_image_infos32 {
+ uint32_t version; // == 1 in Mac OS X 10.4
+ uint32_t infoArrayCount;
+ uint32_t infoArray; // const struct dyld_image_info*
+ uint32_t notification;
+ bool processDetachedFromSharedRegion;
+ // Only in version 2 (Mac OS X 10.6, iPhoneOS 2.0) and later
+ const struct mach_header* dyldImageLoadAddress;
+ uint32_t padding[14];
+ // Only in version 12 (Mac OS X 10.7, iOS 4.3) and later
+ uint32_t sharedCacheSlide;
+ uint32_t padding1[6];
+ // Only in version 15 (macOS 10.12, iOS 10.0) and later
+ const char* dyldPath;
+} dyld_all_image_infos32;
+
+typedef struct dyld_all_image_infos64 {
+ uint32_t version; // == 1 in Mac OS X 10.4
+ uint32_t infoArrayCount;
+ uint64_t infoArray; // const struct dyld_image_info*
+ uint64_t notification;
+ bool processDetachedFromSharedRegion;
+ // Only in version 2 (Mac OS X 10.6, iPhoneOS 2.0) and later
+ const struct mach_header_64* dyldImageLoadAddress;
+ uint64_t padding[14];
+ // Only in version 12 (Mac OS X 10.7, iOS 4.3) and later
+ uint64_t sharedCacheSlide;
+ uint64_t padding1[4];
+ // Only in version 15 (macOS 10.12, iOS 10.0) and later
+ const char* dyldPath;
+} dyld_all_image_infos64;
+
+// some typedefs to isolate 64/32 bit differences
+#ifdef __LP64__
+typedef mach_header_64 breakpad_mach_header;
+typedef segment_command_64 breakpad_mach_segment_command;
+#else
+typedef mach_header breakpad_mach_header;
+typedef segment_command breakpad_mach_segment_command;
+#endif
+
+// Bit in mach_header.flags that indicates whether or not the image is in the
+// dyld shared cache. The dyld shared cache is a single image into which
+// commonly used system dylibs and frameworks are incorporated. dyld maps it
+// into every process at load time. The component images all have the same
+// slide.
+#define MH_SHAREDCACHE 0x80000000
+
+// Helper functions to deal with 32-bit/64-bit Mach-O differences.
+class DynamicImage;
+template<typename MachBits>
+bool FindTextSection(DynamicImage& image);
+
+template<typename MachBits>
+uint32_t GetFileTypeFromHeader(DynamicImage& image);
+
+//==============================================================================
+// Represents a single dynamically loaded mach-o image
+class DynamicImage {
+ public:
+ DynamicImage(uint8_t *header, // data is copied
+ size_t header_size, // includes load commands
+ uint64_t load_address,
+ string file_path,
+ uintptr_t image_mod_date,
+ mach_port_t task,
+ cpu_type_t cpu_type,
+ cpu_subtype_t cpu_subtype,
+ ptrdiff_t shared_cache_slide,
+ bool is_dyld)
+ : header_(header, header + header_size),
+ header_size_(header_size),
+ load_address_(load_address),
+ vmaddr_(0),
+ vmsize_(0),
+ slide_(0),
+ crash_info_(),
+ version_(0),
+ file_path_(file_path),
+ file_mod_date_(image_mod_date),
+ is_dyld_(is_dyld),
+ task_(task),
+ cpu_type_(cpu_type),
+ cpu_subtype_(cpu_subtype),
+ shared_cache_slide_(shared_cache_slide) {
+ CalculateMemoryAndVersionInfo();
+ }
+
+ // Size of mach_header plus load commands
+ size_t GetHeaderSize() const {return header_.size();}
+
+ // Full path to mach-o binary
+ string GetFilePath() {return file_path_;}
+
+ uint64_t GetModDate() const {return file_mod_date_;}
+
+ // Actual address where the image was loaded
+ uint64_t GetLoadAddress() const {return load_address_;}
+
+ // Address where the image should be loaded
+ mach_vm_address_t GetVMAddr() const {return vmaddr_;}
+
+ bool GetInDyldSharedCache()
+ {return (shared_cache_slide_ && (slide_ == shared_cache_slide_));}
+
+ bool GetIsDyld() {return is_dyld_;}
+
+ // Difference between GetLoadAddress() and GetVMAddr()
+ ptrdiff_t GetVMAddrSlide() const {return slide_;}
+
+ // Size of the image
+ mach_vm_size_t GetVMSize() const {return vmsize_;}
+
+ // Returns the address of the locally cached __DATA,__crash_info section.
+ // The vector will be empty if the image doesn't have a __crash_info
+ // section. But even if the vector isn't empty, its contents may be "empty"
+ // of useful data (see definition of crashreporter_annotations_t in
+ // mach_vm_compat.h).
+ mach_vm_address_t GetCrashInfo() const {
+ return reinterpret_cast<mach_vm_address_t>(&crash_info_[0]);
+ }
+
+ // Size of the locally cached __DATA,__crash_info section. This will be zero
+ // if the vector is empty. But even if it's non-zero, the __crash_info
+ // section of which it's a copy may be empty of useful data.
+ size_t GetCrashInfoSize() const {return crash_info_.size();}
+
+ // Task owning this loaded image
+ mach_port_t GetTask() {return task_;}
+
+ // CPU type of the task and the image
+ cpu_type_t GetCPUType() {return cpu_type_;}
+
+ // CPU subtype of the image
+ cpu_type_t GetCPUSubtype() {return cpu_subtype_;}
+
+ // filetype from the Mach-O header.
+ uint32_t GetFileType();
+
+ // Return true if the task is a 64-bit architecture.
+ bool Is64Bit() { return (GetCPUType() & CPU_ARCH_ABI64) == CPU_ARCH_ABI64; }
+
+ uint32_t GetVersion() {return version_;}
+ // For sorting
+ bool operator<(const DynamicImage &inInfo) {
+ return GetLoadAddress() < inInfo.GetLoadAddress();
+ }
+
+ // Sanity checking
+ bool IsValid() {return GetVMSize() != 0;}
+
+ private:
+ DynamicImage(const DynamicImage &);
+ DynamicImage &operator=(const DynamicImage &);
+
+ friend class DynamicImages;
+ template<typename MachBits>
+ friend bool FindTextSection(DynamicImage& image);
+ template<typename MachBits>
+ friend uint32_t GetFileTypeFromHeader(DynamicImage& image);
+
+ // Initializes vmaddr_, vmsize_, and slide_
+ void CalculateMemoryAndVersionInfo();
+
+ const vector<uint8_t> header_; // our local copy of the header
+ size_t header_size_; // mach_header plus load commands
+ uint64_t load_address_; // base address image is mapped into
+ mach_vm_address_t vmaddr_;
+ mach_vm_size_t vmsize_;
+ ptrdiff_t slide_;
+ vector<uint8_t> crash_info_;
+ uint32_t version_; // Dylib version
+ string file_path_; // path dyld used to load the image
+ uintptr_t file_mod_date_; // time_t of image file
+ bool is_dyld_; // Is image file dyld itself?
+
+ mach_port_t task_;
+ cpu_type_t cpu_type_; // CPU type of task_ and image
+ cpu_subtype_t cpu_subtype_; // CPU subtype of image
+ ptrdiff_t shared_cache_slide_; // Task's shared cache slide
+};
+
+//==============================================================================
+// DynamicImageRef is just a simple wrapper for a pointer to
+// DynamicImage. The reason we use it instead of a simple typedef is so
+// that we can use stl::sort() on a vector of DynamicImageRefs
+// and simple class pointers can't implement operator<().
+//
+class DynamicImageRef {
+ public:
+ explicit DynamicImageRef(DynamicImage *inP) : p(inP) {}
+ // The copy constructor is required by STL
+ DynamicImageRef(const DynamicImageRef &inRef) : p(inRef.p) {}
+
+ bool operator<(const DynamicImageRef &inRef) const {
+ return (*const_cast<DynamicImageRef*>(this)->p)
+ < (*const_cast<DynamicImageRef&>(inRef).p);
+ }
+
+ bool operator==(const DynamicImageRef &inInfo) const {
+ return (*const_cast<DynamicImageRef*>(this)->p).GetLoadAddress() ==
+ (*const_cast<DynamicImageRef&>(inInfo)).GetLoadAddress();
+ }
+
+ // Be just like DynamicImage*
+ DynamicImage *operator->() {return p;}
+ operator DynamicImage*() {return p;}
+
+ private:
+ DynamicImage *p;
+};
+
+// Helper function to deal with 32-bit/64-bit Mach-O differences.
+class DynamicImages;
+template<typename MachBits>
+void ReadOneImageInfo(DynamicImages& images, uint64_t image_address,
+ uint64_t file_path_address, uint64_t file_mod_date,
+ uint64_t shared_cache_slide, bool is_dyld);
+template<typename MachBits>
+void ReadImageInfo(DynamicImages& images, uint64_t image_list_address);
+
+//==============================================================================
+// An object of type DynamicImages may be created to allow introspection of
+// an arbitrary task's dynamically loaded mach-o binaries. This makes the
+// assumption that the current task has send rights to the target task.
+class DynamicImages {
+ public:
+ explicit DynamicImages(mach_port_t task);
+
+ ~DynamicImages() {
+ for (int i = 0; i < GetImageCount(); ++i) {
+ delete image_list_[i];
+ }
+ }
+
+ // Returns the number of dynamically loaded mach-o images.
+ int GetImageCount() const {return static_cast<int>(image_list_.size());}
+
+ // Returns an individual image.
+ DynamicImage *GetImage(int i) {
+ if (i < (int)image_list_.size()) {
+ return image_list_[i];
+ }
+ return NULL;
+ }
+
+ // Returns the image corresponding to the main executable.
+ DynamicImage *GetExecutableImage();
+ int GetExecutableImageIndex();
+
+ // Returns the task which we're looking at.
+ mach_port_t GetTask() const {return task_;}
+
+ // CPU type of the task
+ cpu_type_t GetCPUType() {return cpu_type_;}
+
+ // Return true if the task is a 64-bit architecture.
+ bool Is64Bit() { return (GetCPUType() & CPU_ARCH_ABI64) == CPU_ARCH_ABI64; }
+
+ // Determine the CPU type of the task being dumped.
+ static cpu_type_t DetermineTaskCPUType(task_t task);
+
+ // Get the native CPU type of this task.
+ static cpu_type_t GetNativeCPUType() {
+#if defined(__i386__)
+ return CPU_TYPE_I386;
+#elif defined(__x86_64__)
+ return CPU_TYPE_X86_64;
+#elif defined(__ppc__)
+ return CPU_TYPE_POWERPC;
+#elif defined(__ppc64__)
+ return CPU_TYPE_POWERPC64;
+#elif defined(__arm__)
+ return CPU_TYPE_ARM;
+#elif defined(__aarch64__)
+ return CPU_TYPE_ARM64;
+#else
+#error "GetNativeCPUType not implemented for this architecture"
+#endif
+ }
+
+ private:
+ template<typename MachBits>
+ friend void ReadOneImageInfo(DynamicImages& images, uint64_t image_address,
+ uint64_t file_path_address, uint64_t file_mod_date,
+ uint64_t shared_cache_slide, bool is_dyld);
+ template<typename MachBits>
+ friend void ReadImageInfo(DynamicImages& images, uint64_t image_list_address);
+
+ bool IsOurTask() {return task_ == mach_task_self();}
+
+ // Initialization
+ void ReadImageInfoForTask();
+ uint64_t GetDyldAllImageInfosPointer();
+
+ mach_port_t task_;
+ cpu_type_t cpu_type_; // CPU type of task_
+ vector<DynamicImageRef> image_list_;
+};
+
+// Fill bytes with the contents of memory at a particular
+// location in another task.
+kern_return_t ReadTaskMemory(task_port_t target_task,
+ const uint64_t address,
+ size_t length,
+ vector<uint8_t> &bytes);
+
+std::string ReadTaskString(task_port_t target_task,
+ const uint64_t address);
+
+} // namespace google_breakpad
+
+#endif // CLIENT_MAC_HANDLER_DYNAMIC_IMAGES_H__
diff --git a/toolkit/crashreporter/breakpad-client/mac/handler/exception_handler.cc b/toolkit/crashreporter/breakpad-client/mac/handler/exception_handler.cc
new file mode 100644
index 0000000000..c39d66ba41
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/mac/handler/exception_handler.cc
@@ -0,0 +1,990 @@
+// Copyright (c) 2006, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <mach/exc.h>
+#include <mach/mig.h>
+#include <pthread.h>
+#include <signal.h>
+#include <TargetConditionals.h>
+
+#include <map>
+
+#include "mac/handler/exception_handler.h"
+#include "mac/handler/minidump_generator.h"
+#include "common/mac/macho_utilities.h"
+#include "common/mac/scoped_task_suspend-inl.h"
+#include "google_breakpad/common/minidump_exception_mac.h"
+#include "mozilla/Assertions.h"
+
+#ifdef MOZ_PHC
+#include "replace_malloc_bridge.h"
+#endif
+
+#ifndef __EXCEPTIONS
+// This file uses C++ try/catch (but shouldn't). Duplicate the macros from
+// <c++/4.2.1/exception_defines.h> allowing this file to work properly with
+// exceptions disabled even when other C++ libraries are used. #undef the try
+// and catch macros first in case libstdc++ is in use and has already provided
+// its own definitions.
+#undef try
+#define try if (true)
+#undef catch
+#define catch(X) if (false)
+#endif // __EXCEPTIONS
+
+#ifndef USE_PROTECTED_ALLOCATIONS
+#if TARGET_OS_IPHONE
+#define USE_PROTECTED_ALLOCATIONS 1
+#else
+#define USE_PROTECTED_ALLOCATIONS 0
+#endif
+#endif
+
+// If USE_PROTECTED_ALLOCATIONS is activated then the
+// gBreakpadAllocator needs to be setup in other code
+// ahead of time. Please see ProtectedMemoryAllocator.h
+// for more details.
+#if USE_PROTECTED_ALLOCATIONS
+ #include "protected_memory_allocator.h"
+ extern ProtectedMemoryAllocator *gBreakpadAllocator;
+#endif
+
+namespace google_breakpad {
+
+static union {
+#if USE_PROTECTED_ALLOCATIONS
+#if defined PAGE_MAX_SIZE
+ char protected_buffer[PAGE_MAX_SIZE] __attribute__((aligned(PAGE_MAX_SIZE)));
+#else
+ char protected_buffer[PAGE_SIZE] __attribute__((aligned(PAGE_SIZE)));
+#endif // defined PAGE_MAX_SIZE
+#endif // USE_PROTECTED_ALLOCATIONS
+ google_breakpad::ExceptionHandler *handler;
+} gProtectedData;
+
+using std::map;
+
+// These structures and techniques are illustrated in
+// Mac OS X Internals, Amit Singh, ch 9.7
+#pragma pack(push, 4)
+struct ExceptionMessage {
+ mach_msg_header_t header;
+ mach_msg_body_t body;
+ mach_msg_port_descriptor_t thread;
+ mach_msg_port_descriptor_t task;
+ NDR_record_t ndr;
+ exception_type_t exception;
+ mach_msg_type_number_t code_count;
+ mach_exception_data_type_t code[EXCEPTION_CODE_MAX];
+ char padding[512];
+};
+#pragma pack(pop)
+
+struct ExceptionParameters {
+ ExceptionParameters() : count(0) {}
+ mach_msg_type_number_t count;
+ exception_mask_t masks[EXC_TYPES_COUNT];
+ mach_port_t ports[EXC_TYPES_COUNT];
+ exception_behavior_t behaviors[EXC_TYPES_COUNT];
+ thread_state_flavor_t flavors[EXC_TYPES_COUNT];
+};
+
+#pragma pack(push, 4)
+struct ExceptionReplyMessage {
+ mach_msg_header_t header;
+ NDR_record_t ndr;
+ kern_return_t return_code;
+};
+#pragma pack(pop)
+
+// Only catch these three exceptions. The other ones are nebulously defined
+// and may result in treating a non-fatal exception as fatal.
+exception_mask_t s_exception_mask = EXC_MASK_BAD_ACCESS |
+EXC_MASK_BAD_INSTRUCTION | EXC_MASK_ARITHMETIC | EXC_MASK_BREAKPOINT |
+EXC_MASK_CRASH | EXC_MASK_RESOURCE | EXC_MASK_GUARD;
+
+kern_return_t ForwardException(mach_port_t task,
+ mach_port_t failed_thread,
+ exception_type_t exception,
+ mach_exception_data_t code,
+ mach_msg_type_number_t code_count);
+
+// The contents of mach_exc_server() and mach_exception_raise() are derived
+// from /usr/include/mach/mach_exc.defs, as follows:
+//
+// 1) Run 'mig mach_exc.defs' which creates the following files:
+// mach_exc.h
+// mach_excServer.c
+// mach_excUser.c
+// 2) The relevant code for mach_exc_server() comes from the following methods
+// in mach_excServer.c:
+// mach_exc_server()
+// _Xmach_exception_raise()
+// 3) The relevant code for mach_exception_raise() comes from the following
+// method in mach_excUser.c:
+// mach_exception_raise()
+boolean_t mach_exc_server(mach_msg_header_t* InHeadP,
+ mach_msg_header_t* OutHeadP)
+{
+ OutHeadP->msgh_bits =
+ MACH_MSGH_BITS(MACH_MSGH_BITS_REMOTE(InHeadP->msgh_bits), 0);
+ OutHeadP->msgh_remote_port = InHeadP->msgh_remote_port;
+ /* Minimal size: mach_exception_raise() will update it if different */
+ OutHeadP->msgh_size = (mach_msg_size_t)sizeof(mig_reply_error_t);
+ OutHeadP->msgh_local_port = MACH_PORT_NULL;
+ OutHeadP->msgh_id = InHeadP->msgh_id + 100;
+ OutHeadP->msgh_reserved = 0;
+
+ if (InHeadP->msgh_id != 2405) {
+ ((mig_reply_error_t*)OutHeadP)->NDR = NDR_record;
+ ((mig_reply_error_t*)OutHeadP)->RetCode = MIG_BAD_ID;
+ return FALSE;
+ }
+
+#pragma pack(push, 4)
+ typedef struct {
+ mach_msg_header_t Head;
+ /* start of the kernel processed data */
+ mach_msg_body_t msgh_body;
+ mach_msg_port_descriptor_t thread;
+ mach_msg_port_descriptor_t task;
+ /* end of the kernel processed data */
+ NDR_record_t NDR;
+ exception_type_t exception;
+ mach_msg_type_number_t codeCnt;
+ int64_t code[2];
+ mach_msg_trailer_t trailer;
+ } Request;
+
+ typedef struct {
+ mach_msg_header_t Head;
+ NDR_record_t NDR;
+ kern_return_t RetCode;
+ } Reply;
+#pragma pack(pop)
+
+ Request* In0P = (Request*)InHeadP;
+ Reply* OutP = (Reply*)OutHeadP;
+
+ if (In0P->task.name != mach_task_self()) {
+ // This exception was not meant for us, we avoid forwarding it (because it
+ // could cause a loop in the exception handler) and simply ignore it
+ // instead.
+ return TRUE;
+ }
+
+ OutP->RetCode = ForwardException(In0P->task.name,
+ In0P->thread.name,
+ In0P->exception,
+ In0P->code,
+ In0P->codeCnt);
+ OutP->NDR = NDR_record;
+ return TRUE;
+}
+
+kern_return_t mach_exception_raise(mach_port_t exception_port,
+ mach_port_t thread,
+ mach_port_t task,
+ exception_type_t exception,
+ mach_exception_data_t code,
+ mach_msg_type_number_t codeCnt)
+{
+#pragma pack(push, 4)
+ typedef struct {
+ mach_msg_header_t Head;
+ /* start of the kernel processed data */
+ mach_msg_body_t msgh_body;
+ mach_msg_port_descriptor_t thread;
+ mach_msg_port_descriptor_t task;
+ /* end of the kernel processed data */
+ NDR_record_t NDR;
+ exception_type_t exception;
+ mach_msg_type_number_t codeCnt;
+ int64_t code[2];
+ } Request;
+
+ typedef struct {
+ mach_msg_header_t Head;
+ NDR_record_t NDR;
+ kern_return_t RetCode;
+ mach_msg_trailer_t trailer;
+ } Reply;
+#pragma pack(pop)
+
+ Request In;
+ Request *InP = &In;
+
+ mach_msg_return_t msg_result;
+ unsigned int msgh_size;
+
+ InP->msgh_body.msgh_descriptor_count = 2;
+ InP->thread.name = thread;
+ InP->thread.disposition = 19;
+ InP->thread.type = MACH_MSG_PORT_DESCRIPTOR;
+ InP->task.name = task;
+ InP->task.disposition = 19;
+ InP->task.type = MACH_MSG_PORT_DESCRIPTOR;
+
+ InP->NDR = NDR_record;
+
+ InP->exception = exception;
+
+ if (codeCnt > 2) {
+ { return MIG_ARRAY_TOO_LARGE; }
+ }
+ (void)memcpy((char *) InP->code, (const char *) code, 8 * codeCnt);
+
+ InP->codeCnt = codeCnt;
+
+ msgh_size = (mach_msg_size_t)(sizeof(Request) - 16) + ((8 * codeCnt));
+ InP->Head.msgh_bits = MACH_MSGH_BITS_COMPLEX |
+ MACH_MSGH_BITS(19, MACH_MSG_TYPE_MAKE_SEND_ONCE);
+ /* msgh_size passed as argument */
+ InP->Head.msgh_remote_port = exception_port;
+ InP->Head.msgh_local_port = mig_get_reply_port();
+ InP->Head.msgh_id = 2405;
+ InP->Head.msgh_reserved = 0;
+
+ msg_result = mach_msg(&InP->Head,
+ MACH_SEND_MSG|MACH_RCV_MSG|MACH_MSG_OPTION_NONE,
+ msgh_size,
+ (mach_msg_size_t)sizeof(Reply),
+ InP->Head.msgh_local_port,
+ MACH_MSG_TIMEOUT_NONE,
+ MACH_PORT_NULL);
+
+ if (msg_result != MACH_MSG_SUCCESS) {
+ fprintf(stderr, "** mach_msg() error forwarding exception!!\n");
+ return msg_result;
+ }
+
+ return KERN_SUCCESS;
+}
+
+ExceptionHandler::ExceptionHandler(const string &dump_path,
+ FilterCallback filter,
+ MinidumpCallback callback,
+ void* callback_context,
+ bool install_handler,
+ const char* port_name)
+ : dump_path_(),
+ filter_(filter),
+ callback_(callback),
+ callback_context_(callback_context),
+ directCallback_(NULL),
+ handler_thread_(NULL),
+ handler_port_(MACH_PORT_NULL),
+ previous_(NULL),
+ installed_exception_handler_(false),
+ is_in_teardown_(false),
+ last_minidump_write_result_(false),
+ use_minidump_write_mutex_(false) {
+ // This will update to the ID and C-string pointers
+ set_dump_path(dump_path);
+ MinidumpGenerator::GatherSystemInformation();
+#if !TARGET_OS_IPHONE
+ if (port_name)
+ crash_generation_client_.reset(new CrashGenerationClient(port_name));
+#endif
+ Setup(install_handler);
+}
+
+// special constructor if we want to bypass minidump writing and
+// simply get a callback with the exception information
+ExceptionHandler::ExceptionHandler(DirectCallback callback,
+ void* callback_context,
+ bool install_handler)
+ : dump_path_(),
+ filter_(NULL),
+ callback_(NULL),
+ callback_context_(callback_context),
+ directCallback_(callback),
+ handler_thread_(NULL),
+ handler_port_(MACH_PORT_NULL),
+ previous_(NULL),
+ installed_exception_handler_(false),
+ is_in_teardown_(false),
+ last_minidump_write_result_(false),
+ use_minidump_write_mutex_(false) {
+ MinidumpGenerator::GatherSystemInformation();
+ Setup(install_handler);
+}
+
+ExceptionHandler::~ExceptionHandler() {
+ Teardown();
+}
+
+bool ExceptionHandler::WriteMinidump(bool write_exception_stream) {
+ // If we're currently writing, just return
+ if (use_minidump_write_mutex_)
+ return false;
+
+ use_minidump_write_mutex_ = true;
+ last_minidump_write_result_ = false;
+
+ // Lock the mutex. Since we just created it, this will return immediately.
+ if (pthread_mutex_lock(&minidump_write_mutex_) == 0) {
+ // Send an empty message to the handle port so that a minidump will
+ // be written
+ bool result = SendMessageToHandlerThread(write_exception_stream ?
+ kWriteDumpWithExceptionMessage :
+ kWriteDumpMessage);
+ if (!result) {
+ pthread_mutex_unlock(&minidump_write_mutex_);
+ return false;
+ }
+
+ // Wait for the minidump writer to complete its writing. It will unlock
+ // the mutex when completed
+ pthread_mutex_lock(&minidump_write_mutex_);
+ }
+
+ use_minidump_write_mutex_ = false;
+ UpdateNextID();
+ return last_minidump_write_result_;
+}
+
+// static
+bool ExceptionHandler::WriteMinidump(const string &dump_path,
+ bool write_exception_stream,
+ MinidumpCallback callback,
+ void* callback_context) {
+ ExceptionHandler handler(dump_path, NULL, callback, callback_context, false,
+ NULL);
+ return handler.WriteMinidump(write_exception_stream);
+}
+
+// static
+bool ExceptionHandler::WriteMinidumpForChild(mach_port_t child,
+ mach_port_t child_blamed_thread,
+ const string &dump_path,
+ MinidumpCallback callback,
+ void* callback_context) {
+ ScopedTaskSuspend suspend(child);
+
+ MinidumpGenerator generator(child, MACH_PORT_NULL);
+ string dump_id;
+ string dump_filename = generator.UniqueNameInDirectory(dump_path, &dump_id);
+
+ generator.SetExceptionInformation(EXC_BREAKPOINT,
+#if defined(__i386__) || defined(__x86_64__)
+ EXC_I386_BPT,
+#elif defined(__ppc__) || defined(__ppc64__)
+ EXC_PPC_BREAKPOINT,
+#elif defined(__arm__) || defined(__aarch64__)
+ EXC_ARM_BREAKPOINT,
+#else
+#error architecture not supported
+#endif
+ 0,
+ child_blamed_thread);
+ bool result = generator.Write(dump_filename.c_str());
+
+ if (callback) {
+ return callback(dump_path.c_str(), dump_id.c_str(),
+ callback_context, nullptr, result);
+ }
+ return result;
+}
+
+#ifdef MOZ_PHC
+static void GetPHCAddrInfo(int exception_type, int64_t exception_subcode,
+ mozilla::phc::AddrInfo* addr_info) {
+ // Is this a crash involving a PHC allocation?
+ if (exception_type == EXC_BAD_ACCESS) {
+ // `exception_subcode` is only non-zero when it's a bad access, in which
+ // case it holds the address of the bad access.
+ char* addr = reinterpret_cast<char*>(exception_subcode);
+ ReplaceMalloc::IsPHCAllocation(addr, addr_info);
+ }
+}
+#endif
+
+bool ExceptionHandler::WriteMinidumpWithException(
+ int exception_type,
+ int64_t exception_code,
+ int64_t exception_subcode,
+ breakpad_ucontext_t* task_context,
+ mach_port_t thread_name,
+ mach_port_t task_name,
+ bool exit_after_write,
+ bool report_current_thread) {
+ bool result = false;
+
+#if TARGET_OS_IPHONE
+ // _exit() should never be called on iOS.
+ exit_after_write = false;
+#endif
+
+ mozilla::phc::AddrInfo addr_info;
+#ifdef MOZ_PHC
+ GetPHCAddrInfo(exception_type, exception_subcode, &addr_info);
+#endif
+
+ if (directCallback_) {
+ if (directCallback_(callback_context_,
+ exception_type,
+ exception_code,
+ exception_subcode,
+ thread_name) ) {
+ if (exit_after_write)
+ _exit(exception_type);
+ }
+#if !TARGET_OS_IPHONE
+ } else if (IsOutOfProcess()) {
+ if (exception_type && exception_code) {
+ // If this is a real exception, give the filter (if any) a chance to
+ // decide if this should be sent.
+ if (filter_ && !filter_(callback_context_))
+ return false;
+ result = crash_generation_client_->RequestDumpForException(
+ exception_type,
+ exception_code,
+ exception_subcode,
+ thread_name,
+ task_name);
+
+ if (callback_) {
+ result = callback_(dump_path_c_, next_minidump_id_c_, callback_context_,
+ &addr_info, result);
+ }
+
+ if (result && exit_after_write) {
+ _exit(exception_type);
+ }
+ }
+#endif
+ } else {
+ string minidump_id;
+
+ // Putting the MinidumpGenerator in its own context will ensure that the
+ // destructor is executed, closing the newly created minidump file.
+ if (!dump_path_.empty()) {
+ MinidumpGenerator md(mach_task_self(),
+ report_current_thread ? MACH_PORT_NULL :
+ mach_thread_self());
+ md.SetTaskContext(task_context);
+ if (exception_type && exception_code) {
+ // If this is a real exception, give the filter (if any) a chance to
+ // decide if this should be sent.
+ if (filter_ && !filter_(callback_context_))
+ return false;
+
+ md.SetExceptionInformation(exception_type, exception_code,
+ exception_subcode, thread_name);
+ }
+
+ result = md.Write(next_minidump_path_c_);
+ }
+
+ // Call user specified callback (if any)
+ if (callback_) {
+ result = callback_(dump_path_c_, next_minidump_id_c_, callback_context_,
+ &addr_info, result);
+ // If the user callback returned true and we're handling an exception
+ // (rather than just writing out the file), then we should exit without
+ // forwarding the exception to the next handler.
+ if (result) {
+ if (exit_after_write)
+ _exit(exception_type);
+ }
+ }
+ }
+
+ return result;
+}
+
+kern_return_t ForwardException(mach_port_t task, mach_port_t failed_thread,
+ exception_type_t exception,
+ mach_exception_data_t code,
+ mach_msg_type_number_t code_count) {
+ // At this time, we should have called Uninstall() on the exception handler
+ // so that the current exception ports are the ones that we should be
+ // forwarding to.
+ ExceptionParameters current;
+
+ current.count = EXC_TYPES_COUNT;
+ mach_port_t current_task = mach_task_self();
+ task_get_exception_ports(current_task,
+ s_exception_mask,
+ current.masks,
+ &current.count,
+ current.ports,
+ current.behaviors,
+ current.flavors);
+
+ // Find the first exception handler that matches the exception
+ unsigned int found;
+ for (found = 0; found < current.count; ++found) {
+ if (current.masks[found] & (1 << exception)) {
+ break;
+ }
+ }
+
+ // Nothing to forward
+ if (found == current.count) {
+ fprintf(stderr, "** No previous ports for forwarding!! \n");
+ _exit(KERN_FAILURE);
+ }
+
+ mach_port_t target_port = current.ports[found];
+ exception_behavior_t target_behavior = current.behaviors[found];
+
+ kern_return_t result;
+ switch (target_behavior & ~MACH_EXCEPTION_CODES) {
+ case EXCEPTION_DEFAULT:
+ result = mach_exception_raise(target_port, failed_thread, task, exception,
+ code, code_count);
+ break;
+ default:
+ fprintf(stderr, "** Unknown exception behavior: %d\n", target_behavior);
+ result = KERN_FAILURE;
+ break;
+ }
+
+ return result;
+}
+
+// static
+void* ExceptionHandler::WaitForMessage(void* exception_handler_class) {
+ pthread_setname_np("Breakpad ExceptionHandler");
+
+ ExceptionHandler* self =
+ reinterpret_cast<ExceptionHandler*>(exception_handler_class);
+ ExceptionMessage receive;
+
+ // Wait for the exception info
+ while (1) {
+ receive.header.msgh_local_port = self->handler_port_;
+ receive.header.msgh_size = static_cast<mach_msg_size_t>(sizeof(receive));
+ kern_return_t result = mach_msg(&(receive.header),
+ MACH_RCV_MSG | MACH_RCV_LARGE, 0,
+ receive.header.msgh_size,
+ self->handler_port_,
+ MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
+
+
+ if (result == KERN_SUCCESS) {
+ // Uninstall our handler so that we don't get in a loop if the process of
+ // writing out a minidump causes an exception. However, if the exception
+ // was caused by a fork'd process, don't uninstall things
+
+ // If the actual exception code is zero, then we're calling this handler
+ // in a way that indicates that we want to either exit this thread or
+ // generate a minidump
+ //
+ // While reporting, all threads (except this one) must be suspended
+ // to avoid misleading stacks. If appropriate they will be resumed
+ // afterwards.
+ if (!receive.exception) {
+ // Don't touch self, since this message could have been sent
+ // from its destructor.
+ if (receive.header.msgh_id == kShutdownMessage)
+ return NULL;
+
+ self->SuspendThreads();
+
+#if USE_PROTECTED_ALLOCATIONS
+ if (gBreakpadAllocator)
+ gBreakpadAllocator->Unprotect();
+#endif
+
+ mach_port_t thread = MACH_PORT_NULL;
+ int exception_type = 0;
+ int64_t exception_code = 0;
+ if (receive.header.msgh_id == kWriteDumpWithExceptionMessage) {
+ thread = receive.thread.name;
+ exception_type = EXC_BREAKPOINT;
+#if defined(__i386__) || defined(__x86_64__)
+ exception_code = EXC_I386_BPT;
+#elif defined(__ppc__) || defined(__ppc64__)
+ exception_code = EXC_PPC_BREAKPOINT;
+#elif defined(__arm__) || defined(__aarch64__)
+ exception_code = EXC_ARM_BREAKPOINT;
+#else
+#error architecture not supported
+#endif
+ }
+
+ // Write out the dump and save the result for later retrieval
+ self->last_minidump_write_result_ =
+ self->WriteMinidumpWithException(exception_type, exception_code,
+ 0, NULL, thread, mach_task_self(),
+ false, false);
+
+#if USE_PROTECTED_ALLOCATIONS
+ if (gBreakpadAllocator)
+ gBreakpadAllocator->Protect();
+#endif
+
+ self->ResumeThreads();
+
+ if (self->use_minidump_write_mutex_)
+ pthread_mutex_unlock(&self->minidump_write_mutex_);
+ } else {
+ bool crash_reported = false;
+
+ // When forking a child process with the exception handler installed,
+ // if the child crashes, it will send the exception back to the parent
+ // process. The check for task == self_task() ensures that only
+ // exceptions that occur in the parent process are caught and
+ // processed.
+ if (receive.task.name == mach_task_self()) {
+ self->SuspendThreads();
+
+#if USE_PROTECTED_ALLOCATIONS
+ if (gBreakpadAllocator)
+ gBreakpadAllocator->Unprotect();
+#endif
+
+ mach_exception_data_type_t subcode = 0;
+ if (receive.code_count > 1) {
+ switch (receive.exception) {
+ case EXC_BAD_ACCESS:
+ case EXC_CRASH:
+ case EXC_RESOURCE:
+ case EXC_GUARD:
+ subcode = receive.code[1];
+ break;
+ default:
+ subcode = 0;
+ }
+ }
+
+ // Generate the minidump with the exception data.
+ crash_reported =
+ self->WriteMinidumpWithException(receive.exception, receive.code[0],
+ subcode, NULL, receive.thread.name,
+ mach_task_self(), true, false);
+
+#if USE_PROTECTED_ALLOCATIONS
+ // This may have become protected again within
+ // WriteMinidumpWithException, but it needs to be unprotected for
+ // UninstallHandler.
+ if (gBreakpadAllocator)
+ gBreakpadAllocator->Unprotect();
+#endif
+
+ self->UninstallHandler(true);
+
+#if USE_PROTECTED_ALLOCATIONS
+ if (gBreakpadAllocator)
+ gBreakpadAllocator->Protect();
+#endif
+ }
+
+ ExceptionReplyMessage reply;
+ if (!mach_exc_server(&receive.header, &reply.header)) {
+ MOZ_CRASH_UNSAFE_PRINTF("Mach message id: %d crash reported = %d",
+ receive.header.msgh_id, crash_reported);
+ }
+
+ // Send a reply and exit
+ mach_msg(&(reply.header), MACH_SEND_MSG,
+ reply.header.msgh_size, 0, MACH_PORT_NULL,
+ MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
+ }
+ }
+ }
+
+ return NULL;
+}
+
+// static
+void ExceptionHandler::SignalHandler(int sig, siginfo_t* info, void* uc) {
+#if USE_PROTECTED_ALLOCATIONS
+ if (gBreakpadAllocator)
+ gBreakpadAllocator->Unprotect();
+#endif
+ gProtectedData.handler->WriteMinidumpWithException(
+ EXC_SOFTWARE,
+ MD_EXCEPTION_CODE_MAC_ABORT,
+ 0,
+ static_cast<breakpad_ucontext_t*>(uc),
+ mach_thread_self(),
+ mach_task_self(),
+ true,
+ true);
+#if USE_PROTECTED_ALLOCATIONS
+ if (gBreakpadAllocator)
+ gBreakpadAllocator->Protect();
+#endif
+}
+
+// static
+bool ExceptionHandler::WriteForwardedExceptionMinidump(int exception_type,
+ int64_t exception_code,
+ int64_t exception_subcode,
+ mach_port_t thread,
+ mach_port_t task)
+{
+ if (!gProtectedData.handler) {
+ return false;
+ }
+ return gProtectedData.handler->WriteMinidumpWithException(exception_type, exception_code,
+ exception_subcode, NULL, thread, task,
+ /* exit_after_write = */ false,
+ /* report_current_thread = */ true);
+}
+
+bool ExceptionHandler::InstallHandler() {
+ // If a handler is already installed, something is really wrong.
+ if (gProtectedData.handler != NULL) {
+ return false;
+ }
+
+ struct sigaction sa;
+ memset(&sa, 0, sizeof(sa));
+ sigemptyset(&sa.sa_mask);
+ sigaddset(&sa.sa_mask, SIGABRT);
+ sa.sa_sigaction = ExceptionHandler::SignalHandler;
+ sa.sa_flags = SA_SIGINFO;
+
+ scoped_ptr<struct sigaction> old(new struct sigaction);
+ if (sigaction(SIGABRT, &sa, old.get()) == -1) {
+ return false;
+ }
+ old_handler_.swap(old);
+ gProtectedData.handler = this;
+#if USE_PROTECTED_ALLOCATIONS
+ assert(((size_t)(gProtectedData.protected_buffer) & PAGE_MASK) == 0);
+ mprotect(gProtectedData.protected_buffer, PAGE_SIZE, PROT_READ);
+#endif
+
+ try {
+#if USE_PROTECTED_ALLOCATIONS
+ previous_ = new (gBreakpadAllocator->Allocate(sizeof(ExceptionParameters)) )
+ ExceptionParameters();
+#else
+ previous_ = new ExceptionParameters();
+#endif
+ }
+ catch (std::bad_alloc) {
+ return false;
+ }
+
+ // Save the current exception ports so that we can forward to them
+ previous_->count = EXC_TYPES_COUNT;
+ mach_port_t current_task = mach_task_self();
+ kern_return_t result = task_get_exception_ports(current_task,
+ s_exception_mask,
+ previous_->masks,
+ &previous_->count,
+ previous_->ports,
+ previous_->behaviors,
+ previous_->flavors);
+
+ // Setup the exception ports on this task. Such documentation as exists for
+ // task_set_exception_port() and friends can be found in the source code for
+ // xnu. Apple's implementation is available at https://opensource.apple.com/.
+ if (result == KERN_SUCCESS)
+ result = task_set_exception_ports(current_task, s_exception_mask,
+ handler_port_,
+ EXCEPTION_DEFAULT | MACH_EXCEPTION_CODES,
+ THREAD_STATE_NONE);
+
+ installed_exception_handler_ = (result == KERN_SUCCESS);
+
+ return installed_exception_handler_;
+}
+
+bool ExceptionHandler::UninstallHandler(bool in_exception) {
+ kern_return_t result = KERN_SUCCESS;
+
+ if (old_handler_.get()) {
+ sigaction(SIGABRT, old_handler_.get(), NULL);
+#if USE_PROTECTED_ALLOCATIONS
+ mprotect(gProtectedData.protected_buffer, PAGE_SIZE,
+ PROT_READ | PROT_WRITE);
+#endif
+ // If we're handling an exception, leak the sigaction struct
+ // because it is unsafe to delete objects while in exception
+ // handling context.
+ if (in_exception) {
+ old_handler_.release();
+ } else {
+ old_handler_.reset();
+ }
+ gProtectedData.handler = NULL;
+ }
+
+ if (installed_exception_handler_) {
+ mach_port_t current_task = mach_task_self();
+
+ // Restore the previous ports
+ for (unsigned int i = 0; i < previous_->count; ++i) {
+ result = task_set_exception_ports(current_task, previous_->masks[i],
+ previous_->ports[i],
+ previous_->behaviors[i],
+ previous_->flavors[i]);
+ if (result != KERN_SUCCESS)
+ return false;
+ }
+
+ // this delete should NOT happen if an exception just occurred!
+ if (!in_exception) {
+#if USE_PROTECTED_ALLOCATIONS
+ previous_->~ExceptionParameters();
+#else
+ delete previous_;
+#endif
+ }
+
+ previous_ = NULL;
+ installed_exception_handler_ = false;
+ }
+
+ return result == KERN_SUCCESS;
+}
+
+bool ExceptionHandler::Setup(bool install_handler) {
+ if (pthread_mutex_init(&minidump_write_mutex_, NULL))
+ return false;
+
+ // Create a receive right
+ mach_port_t current_task = mach_task_self();
+ kern_return_t result = mach_port_allocate(current_task,
+ MACH_PORT_RIGHT_RECEIVE,
+ &handler_port_);
+ // Add send right
+ if (result == KERN_SUCCESS)
+ result = mach_port_insert_right(current_task, handler_port_, handler_port_,
+ MACH_MSG_TYPE_MAKE_SEND);
+
+ if (install_handler && result == KERN_SUCCESS)
+ if (!InstallHandler())
+ return false;
+
+ if (result == KERN_SUCCESS) {
+ // Install the handler in its own thread, detached as we won't be joining.
+ pthread_attr_t attr;
+ pthread_attr_init(&attr);
+ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+ int thread_create_result = pthread_create(&handler_thread_, &attr,
+ &WaitForMessage, this);
+ pthread_attr_destroy(&attr);
+ result = thread_create_result ? KERN_FAILURE : KERN_SUCCESS;
+ }
+
+ return result == KERN_SUCCESS;
+}
+
+bool ExceptionHandler::Teardown() {
+ kern_return_t result = KERN_SUCCESS;
+ is_in_teardown_ = true;
+
+ if (!UninstallHandler(false))
+ return false;
+
+ // Send an empty message so that the handler_thread exits
+ if (SendMessageToHandlerThread(kShutdownMessage)) {
+ mach_port_t current_task = mach_task_self();
+ result = mach_port_deallocate(current_task, handler_port_);
+ if (result != KERN_SUCCESS)
+ return false;
+ } else {
+ return false;
+ }
+
+ handler_thread_ = NULL;
+ handler_port_ = MACH_PORT_NULL;
+ pthread_mutex_destroy(&minidump_write_mutex_);
+
+ return result == KERN_SUCCESS;
+}
+
+bool ExceptionHandler::SendMessageToHandlerThread(
+ HandlerThreadMessage message_id) {
+ ExceptionMessage msg;
+ memset(&msg, 0, sizeof(msg));
+ msg.header.msgh_id = message_id;
+ if (message_id == kWriteDumpMessage ||
+ message_id == kWriteDumpWithExceptionMessage) {
+ // Include this thread's port.
+ msg.thread.name = mach_thread_self();
+ msg.thread.disposition = MACH_MSG_TYPE_PORT_SEND;
+ msg.thread.type = MACH_MSG_PORT_DESCRIPTOR;
+ }
+ msg.header.msgh_size = sizeof(msg) - sizeof(msg.padding);
+ msg.header.msgh_remote_port = handler_port_;
+ msg.header.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND,
+ MACH_MSG_TYPE_MAKE_SEND_ONCE);
+ kern_return_t result = mach_msg(&(msg.header),
+ MACH_SEND_MSG | MACH_SEND_TIMEOUT,
+ msg.header.msgh_size, 0, 0,
+ MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
+
+ return result == KERN_SUCCESS;
+}
+
+void ExceptionHandler::UpdateNextID() {
+ next_minidump_path_ =
+ (MinidumpGenerator::UniqueNameInDirectory(dump_path_, &next_minidump_id_));
+
+ next_minidump_path_c_ = next_minidump_path_.c_str();
+ next_minidump_id_c_ = next_minidump_id_.c_str();
+}
+
+bool ExceptionHandler::SuspendThreads() {
+ thread_act_port_array_t threads_for_task;
+ mach_msg_type_number_t thread_count;
+
+ if (task_threads(mach_task_self(), &threads_for_task, &thread_count))
+ return false;
+
+ // suspend all of the threads except for this one
+ for (unsigned int i = 0; i < thread_count; ++i) {
+ if (threads_for_task[i] != mach_thread_self()) {
+ if (thread_suspend(threads_for_task[i]))
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool ExceptionHandler::ResumeThreads() {
+ thread_act_port_array_t threads_for_task;
+ mach_msg_type_number_t thread_count;
+
+ if (task_threads(mach_task_self(), &threads_for_task, &thread_count))
+ return false;
+
+ // resume all of the threads except for this one
+ for (unsigned int i = 0; i < thread_count; ++i) {
+ if (threads_for_task[i] != mach_thread_self()) {
+ if (thread_resume(threads_for_task[i]))
+ return false;
+ }
+ }
+
+ return true;
+}
+
+} // namespace google_breakpad
diff --git a/toolkit/crashreporter/breakpad-client/mac/handler/exception_handler.h b/toolkit/crashreporter/breakpad-client/mac/handler/exception_handler.h
new file mode 100644
index 0000000000..24728a8c7c
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/mac/handler/exception_handler.h
@@ -0,0 +1,297 @@
+// Copyright (c) 2006, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// exception_handler.h: MacOS exception handler
+// This class can install a Mach exception port handler to trap most common
+// programming errors. If an exception occurs, a minidump file will be
+// generated which contains detailed information about the process and the
+// exception.
+
+#ifndef CLIENT_MAC_HANDLER_EXCEPTION_HANDLER_H__
+#define CLIENT_MAC_HANDLER_EXCEPTION_HANDLER_H__
+
+#include <mach/mach.h>
+#include <TargetConditionals.h>
+
+#include <string>
+
+#include "mac/handler/ucontext_compat.h"
+#include "common/scoped_ptr.h"
+
+#if !TARGET_OS_IPHONE
+#include "mac/crash_generation/crash_generation_client.h"
+#endif
+
+#ifdef MOZ_PHC
+#include "PHC.h"
+#else
+namespace mozilla { namespace phc { class AddrInfo {}; } }
+#endif
+
+namespace google_breakpad {
+
+using std::string;
+
+struct ExceptionParameters;
+
+enum HandlerThreadMessage {
+ // Message ID telling the handler thread to write a dump.
+ kWriteDumpMessage = 0,
+ // Message ID telling the handler thread to write a dump and include
+ // an exception stream.
+ kWriteDumpWithExceptionMessage = 1,
+ // Message ID telling the handler thread to quit.
+ kShutdownMessage = 2
+};
+
+class ExceptionHandler {
+ public:
+ // A callback function to run before Breakpad performs any substantial
+ // processing of an exception. A FilterCallback is called before writing
+ // a minidump. context is the parameter supplied by the user as
+ // callback_context when the handler was created.
+ //
+ // If a FilterCallback returns true, Breakpad will continue processing,
+ // attempting to write a minidump. If a FilterCallback returns false, Breakpad
+ // will immediately report the exception as unhandled without writing a
+ // minidump, allowing another handler the opportunity to handle it.
+ typedef bool (*FilterCallback)(void *context);
+
+ // A callback function to run after the minidump has been written.
+ // |minidump_id| is a unique id for the dump, so the minidump
+ // file is <dump_dir>/<minidump_id>.dmp.
+ // |context| is the value passed into the constructor.
+ // |succeeded| indicates whether a minidump file was successfully written.
+ // Return true if the exception was fully handled and breakpad should exit.
+ // Return false to allow any other exception handlers to process the
+ // exception.
+ typedef bool (*MinidumpCallback)(const char *dump_dir,
+ const char *minidump_id,
+ void *context,
+ const mozilla::phc::AddrInfo* addr_info,
+ bool succeeded);
+
+ // A callback function which will be called directly if an exception occurs.
+ // This bypasses the minidump file writing and simply gives the client
+ // the exception information.
+ typedef bool (*DirectCallback)( void *context,
+ int exception_type,
+ int exception_code,
+ int64_t exception_subcode,
+ mach_port_t thread_name);
+
+ // Creates a new ExceptionHandler instance to handle writing minidumps.
+ // Minidump files will be written to dump_path, and the optional callback
+ // is called after writing the dump file, as described above.
+ // If install_handler is true, then a minidump will be written whenever
+ // an unhandled exception occurs. If it is false, minidumps will only
+ // be written when WriteMinidump is called.
+ // If port_name is non-NULL, attempt to perform out-of-process dump generation
+ // If port_name is NULL, in-process dump generation will be used.
+ ExceptionHandler(const string &dump_path,
+ FilterCallback filter, MinidumpCallback callback,
+ void *callback_context, bool install_handler,
+ const char *port_name);
+
+ // A special constructor if we want to bypass minidump writing and
+ // simply get a callback with the exception information.
+ ExceptionHandler(DirectCallback callback,
+ void *callback_context,
+ bool install_handler);
+
+ ~ExceptionHandler();
+
+ // Get and set the minidump path.
+ string dump_path() const { return dump_path_; }
+ void set_dump_path(const string &dump_path) {
+ dump_path_ = dump_path;
+ dump_path_c_ = dump_path_.c_str();
+ UpdateNextID(); // Necessary to put dump_path_ in next_minidump_path_.
+ }
+
+ // Writes a minidump immediately. This can be used to capture the
+ // execution state independently of a crash. Returns true on success.
+ bool WriteMinidump() {
+ return WriteMinidump(false);
+ }
+
+ bool WriteMinidump(bool write_exception_stream);
+
+ // Convenience form of WriteMinidump which does not require an
+ // ExceptionHandler instance.
+ static bool WriteMinidump(const string &dump_path, MinidumpCallback callback,
+ void *callback_context) {
+ return WriteMinidump(dump_path, false, callback, callback_context);
+ }
+
+ static bool WriteMinidump(const string &dump_path,
+ bool write_exception_stream,
+ MinidumpCallback callback,
+ void *callback_context);
+
+ // Write a minidump of child immediately. This can be used to capture
+ // the execution state of a child process independently of a crash.
+ static bool WriteMinidumpForChild(mach_port_t child,
+ mach_port_t child_blamed_thread,
+ const std::string &dump_path,
+ MinidumpCallback callback,
+ void *callback_context);
+
+ // Write a minidump for an exception that was received by another handler.
+ static bool WriteForwardedExceptionMinidump(int exception_type,
+ int64_t exception_code,
+ int64_t exception_subcode,
+ mach_port_t thread,
+ mach_port_t task);
+
+ // Returns whether out-of-process dump generation is used or not.
+ bool IsOutOfProcess() const {
+#if TARGET_OS_IPHONE
+ return false;
+#else
+ return crash_generation_client_.get() != NULL;
+#endif
+ }
+
+ private:
+ // Install the mach exception handler
+ bool InstallHandler();
+
+ // Uninstall the mach exception handler (if any)
+ bool UninstallHandler(bool in_exception);
+
+ // Setup the handler thread, and if |install_handler| is true, install the
+ // mach exception port handler
+ bool Setup(bool install_handler);
+
+ // Uninstall the mach exception handler (if any) and terminate the helper
+ // thread
+ bool Teardown();
+
+ // Send a mach message to the exception handler. Return true on
+ // success, false otherwise.
+ bool SendMessageToHandlerThread(HandlerThreadMessage message_id);
+
+ // All minidump writing goes through this one routine.
+ // |task_context| can be NULL. If not, it will be used to retrieve the
+ // context of the current thread, instead of using |thread_get_state|.
+ bool WriteMinidumpWithException(int exception_type,
+ int64_t exception_code,
+ int64_t exception_subcode,
+ breakpad_ucontext_t *task_context,
+ mach_port_t thread_name,
+ mach_port_t task_name,
+ bool exit_after_write,
+ bool report_current_thread);
+
+ // When installed, this static function will be call from a newly created
+ // pthread with |this| as the argument
+ static void *WaitForMessage(void *exception_handler_class);
+
+ // Signal handler for SIGABRT.
+ static void SignalHandler(int sig, siginfo_t* info, void* uc);
+
+ // disallow copy ctor and operator=
+ explicit ExceptionHandler(const ExceptionHandler &);
+ void operator=(const ExceptionHandler &);
+
+ // Generates a new ID and stores it in next_minidump_id_, and stores the
+ // path of the next minidump to be written in next_minidump_path_.
+ void UpdateNextID();
+
+ // These functions will suspend/resume all threads except for the
+ // reporting thread
+ bool SuspendThreads();
+ bool ResumeThreads();
+
+ // The destination directory for the minidump
+ string dump_path_;
+
+ // The basename of the next minidump w/o extension
+ string next_minidump_id_;
+
+ // The full path to the next minidump to be written, including extension
+ string next_minidump_path_;
+
+ // Pointers to the UTF-8 versions of above
+ const char *dump_path_c_;
+ const char *next_minidump_id_c_;
+ const char *next_minidump_path_c_;
+
+ // The callback function and pointer to be passed back after the minidump
+ // has been written
+ FilterCallback filter_;
+ MinidumpCallback callback_;
+ void *callback_context_;
+
+ // The callback function to be passed back when we don't want a minidump
+ // file to be written
+ DirectCallback directCallback_;
+
+ // The thread that is created for the handler
+ pthread_t handler_thread_;
+
+ // The port that is waiting on an exception message to be sent, if the
+ // handler is installed
+ mach_port_t handler_port_;
+
+ // These variables save the previous exception handler's data so that it
+ // can be re-installed when this handler is uninstalled
+ ExceptionParameters *previous_;
+
+ // True, if we've installed the exception handler
+ bool installed_exception_handler_;
+
+ // True, if we're in the process of uninstalling the exception handler and
+ // the thread.
+ bool is_in_teardown_;
+
+ // Save the last result of the last minidump
+ bool last_minidump_write_result_;
+
+ // A mutex for use when writing out a minidump that was requested on a
+ // thread other than the exception handler.
+ pthread_mutex_t minidump_write_mutex_;
+
+ // True, if we're using the mutext to indicate when mindump writing occurs
+ bool use_minidump_write_mutex_;
+
+ // Old signal handler for SIGABRT. Used to be able to restore it when
+ // uninstalling.
+ scoped_ptr<struct sigaction> old_handler_;
+
+#if !TARGET_OS_IPHONE
+ // Client for out-of-process dump generation.
+ scoped_ptr<CrashGenerationClient> crash_generation_client_;
+#endif
+};
+
+} // namespace google_breakpad
+
+#endif // CLIENT_MAC_HANDLER_EXCEPTION_HANDLER_H__
diff --git a/toolkit/crashreporter/breakpad-client/mac/handler/mach_vm_compat.h b/toolkit/crashreporter/breakpad-client/mac/handler/mach_vm_compat.h
new file mode 100644
index 0000000000..aef3ad82f5
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/mac/handler/mach_vm_compat.h
@@ -0,0 +1,88 @@
+// Copyright (c) 2011, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef CLIENT_MAC_GENERATOR_MACH_VM_COMPAT_H_
+#define CLIENT_MAC_GENERATOR_MACH_VM_COMPAT_H_
+
+#include <TargetConditionals.h>
+
+// On iOS 5 and higher, mach/mach_vm.h is not supported. Use the corresponding
+// vm_map functions instead.
+#if TARGET_OS_IPHONE
+#include <mach/vm_map.h>
+#define mach_vm_address_t vm_address_t
+#define mach_vm_deallocate vm_deallocate
+#define mach_vm_read vm_read
+#define mach_vm_region_recurse vm_region_recurse_64
+#define mach_vm_size_t vm_size_t
+#else
+#include <mach/mach_vm.h>
+#endif // TARGET_OS_IPHONE
+
+// This is the current (as of macOS 11.2.3) raw format of the data in the
+// __crash_info section of the __DATA segment. It must be read from memory
+// (__crash_info sections in file system modules are always empty of useful
+// data). The data (and that of its strings) may be readable from an out-of-
+// process image, but generally only if the module is in the dyld shared
+// cache. A __crash_info section is considered "empty of useful data" if all
+// of its fields besides 'version' are zero. The __crash_info section is only
+// present on macOS. Apple may add new fields to this structure in the future,
+// as they added 'abort_cause' when 'version' changed from '4' to '5'.
+// Breakpad should take this into account, and provide a way for new fields to
+// be added to future versions of MDRawMacCrashInfoRecord without breaking
+// older code.
+typedef struct { // Non-raw format
+ uint64_t version; // unsigned long
+ uint64_t message; // char *
+ uint64_t signature_string; // char *
+ uint64_t backtrace; // char *
+ uint64_t message2; // char *
+ // We can't use uint64_t for 'thread' in non-raw structures: Though uint64_t
+ // is the same size on all platforms, it's "unsigned long" on some platforms
+ // (like Android and Linux) and "unsigned long long" on others (like macOS
+ // and Windows).
+ uint64_t thread; // uint64_t, but we use unsigned long long
+ uint64_t dialog_mode; // unsigned int
+ // There's a string in the OSAnalytics private framework ("Abort Cause %lld")
+ // which hints that this field's non-raw format is long long.
+ uint64_t abort_cause; // long long, only present when
+ // 'version' > 4
+} crashreporter_annotations_t;
+
+// Defines for calls to getsectdatafromheader_64() or getsectdatafromheader().
+// __LP64__ is true on both amd64 and arm64 (Apple Silicon) hardware.
+#ifdef __LP64__
+ #define getsectdatafromheader_func getsectdatafromheader_64
+ typedef uint64_t getsectdata_size_type;
+#else
+ #define getsectdatafromheader_func getsectdatafromheader
+ typedef uint32_t getsectdata_size_type;
+#endif
+
+#endif // CLIENT_MAC_GENERATOR_MACH_VM_COMPAT_H_
diff --git a/toolkit/crashreporter/breakpad-client/mac/handler/minidump_generator.cc b/toolkit/crashreporter/breakpad-client/mac/handler/minidump_generator.cc
new file mode 100644
index 0000000000..e13e4509b0
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/mac/handler/minidump_generator.cc
@@ -0,0 +1,2135 @@
+// Copyright (c) 2006, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <algorithm>
+#include <cstdio>
+
+#include <mach/host_info.h>
+#include <mach/machine.h>
+#include <mach/vm_statistics.h>
+#include <mach-o/dyld.h>
+#include <mach-o/loader.h>
+#include <mach-o/getsect.h>
+#include <sys/sysctl.h>
+#include <sys/resource.h>
+
+#include <CoreFoundation/CoreFoundation.h>
+
+#include "mac/handler/minidump_generator.h"
+
+#if defined(HAS_ARM_SUPPORT) || defined(HAS_ARM64_SUPPORT)
+#include <mach/arm/thread_status.h>
+#endif
+#ifdef HAS_PPC_SUPPORT
+#include <mach/ppc/thread_status.h>
+#endif
+#ifdef HAS_X86_SUPPORT
+#include <mach/i386/thread_status.h>
+#endif
+
+#include "minidump_file_writer-inl.h"
+#include "common/mac/file_id.h"
+#include "common/mac/macho_id.h"
+#include "common/mac/string_utilities.h"
+
+using MacStringUtils::ConvertToString;
+using MacStringUtils::IntegerValueAtIndex;
+
+namespace google_breakpad {
+
+#if defined(__LP64__) && __LP64__
+#define LC_SEGMENT_ARCH LC_SEGMENT_64
+#define MH_MAGIC_ARCH MH_MAGIC_64
+#else
+#define LC_SEGMENT_ARCH LC_SEGMENT
+#define MH_MAGIC_ARCH MH_MAGIC
+#endif
+
+// constructor when generating from within the crashed process
+MinidumpGenerator::MinidumpGenerator()
+ : writer_(),
+ exception_type_(0),
+ exception_code_(0),
+ exception_subcode_(0),
+ exception_thread_(0),
+ crashing_task_(mach_task_self()),
+ handler_thread_(mach_thread_self()),
+ cpu_type_(DynamicImages::GetNativeCPUType()),
+ dyldImageLoadAddress_(NULL),
+ dyldSlide_(0),
+ dyldPath_(),
+ task_context_(NULL),
+ dynamic_images_(NULL),
+ memory_blocks_(&allocator_) {
+ GatherSystemInformation();
+ GatherCurrentProcessDyldInformation();
+}
+
+// constructor when generating from a different process than the
+// crashed process
+MinidumpGenerator::MinidumpGenerator(mach_port_t crashing_task,
+ mach_port_t handler_thread)
+ : writer_(),
+ exception_type_(0),
+ exception_code_(0),
+ exception_subcode_(0),
+ exception_thread_(0),
+ crashing_task_(crashing_task),
+ handler_thread_(handler_thread),
+ cpu_type_(DynamicImages::GetNativeCPUType()),
+ dyldImageLoadAddress_(NULL),
+ dyldSlide_(0),
+ dyldPath_(),
+ task_context_(NULL),
+ dynamic_images_(NULL),
+ memory_blocks_(&allocator_) {
+ if (crashing_task != mach_task_self()) {
+ dynamic_images_ = new DynamicImages(crashing_task_);
+ cpu_type_ = dynamic_images_->GetCPUType();
+ } else {
+ dynamic_images_ = NULL;
+ cpu_type_ = DynamicImages::GetNativeCPUType();
+ }
+
+ GatherSystemInformation();
+ // This constructor is used when creating a crash server, but the crash
+ // server may also be the crashing process.
+ GatherCurrentProcessDyldInformation();
+}
+
+MinidumpGenerator::~MinidumpGenerator() {
+ delete dynamic_images_;
+}
+
+char MinidumpGenerator::build_string_[16];
+int MinidumpGenerator::os_major_version_ = 0;
+int MinidumpGenerator::os_minor_version_ = 0;
+int MinidumpGenerator::os_build_number_ = 0;
+
+// static
+void MinidumpGenerator::GatherSystemInformation() {
+ // If this is non-zero, then we've already gathered the information
+ if (os_major_version_)
+ return;
+
+ // This code extracts the version and build information from the OS
+ CFStringRef vers_path =
+ CFSTR("/System/Library/CoreServices/SystemVersion.plist");
+ CFURLRef sys_vers =
+ CFURLCreateWithFileSystemPath(NULL,
+ vers_path,
+ kCFURLPOSIXPathStyle,
+ false);
+ CFReadStreamRef read_stream = CFReadStreamCreateWithFile(NULL, sys_vers);
+ CFRelease(sys_vers);
+ if (!read_stream) {
+ return;
+ }
+ if (!CFReadStreamOpen(read_stream)) {
+ CFRelease(read_stream);
+ return;
+ }
+ CFMutableDataRef data = NULL;
+ while (true) {
+ // Actual data file tests: Mac at 480 bytes and iOS at 413 bytes.
+ const CFIndex kMaxBufferLength = 1024;
+ UInt8 data_bytes[kMaxBufferLength];
+ CFIndex num_bytes_read =
+ CFReadStreamRead(read_stream, data_bytes, kMaxBufferLength);
+ if (num_bytes_read < 0) {
+ if (data) {
+ CFRelease(data);
+ data = NULL;
+ }
+ break;
+ } else if (num_bytes_read == 0) {
+ break;
+ } else if (!data) {
+ data = CFDataCreateMutable(NULL, 0);
+ }
+ CFDataAppendBytes(data, data_bytes, num_bytes_read);
+ }
+ CFReadStreamClose(read_stream);
+ CFRelease(read_stream);
+ if (!data) {
+ return;
+ }
+ CFDictionaryRef list =
+ static_cast<CFDictionaryRef>(CFPropertyListCreateWithData(
+ NULL, data, kCFPropertyListImmutable, NULL, NULL));
+ CFRelease(data);
+ if (!list) {
+ return;
+ }
+ CFStringRef build_version = static_cast<CFStringRef>
+ (CFDictionaryGetValue(list, CFSTR("ProductBuildVersion")));
+ CFStringRef product_version = static_cast<CFStringRef>
+ (CFDictionaryGetValue(list, CFSTR("ProductVersion")));
+ string build_str = ConvertToString(build_version);
+ string product_str = ConvertToString(product_version);
+
+ CFRelease(list);
+
+ strlcpy(build_string_, build_str.c_str(), sizeof(build_string_));
+
+ // Parse the string that looks like "10.4.8"
+ os_major_version_ = IntegerValueAtIndex(product_str, 0);
+ os_minor_version_ = IntegerValueAtIndex(product_str, 1);
+ os_build_number_ = IntegerValueAtIndex(product_str, 2);
+}
+
+// static
+uint64_t
+MinidumpGenerator::GetCurrentProcessModuleSlide(breakpad_mach_header* mh,
+ uint64_t shared_cache_slide) {
+ if (!mh || (mh->magic != MH_MAGIC_ARCH)) {
+ return 0;
+ }
+
+ if ((mh->flags & MH_SHAREDCACHE) != 0) {
+ return shared_cache_slide;
+ }
+
+ uint64_t slide = 0;
+
+ uint32_t num_commands = mh->ncmds;
+ breakpad_mach_segment_command* cmd = (breakpad_mach_segment_command*)
+ ((uintptr_t)mh + sizeof(breakpad_mach_header));
+ for (uint32_t i = 0; i < num_commands; ++i) {
+ if (cmd->cmd != LC_SEGMENT_ARCH) {
+ break;
+ }
+ if (!cmd->fileoff && cmd->filesize) {
+ slide = (uintptr_t)mh - cmd->vmaddr;
+ break;
+ }
+ cmd = (breakpad_mach_segment_command*) ((uintptr_t)cmd + cmd->cmdsize);
+ }
+
+ return slide;
+}
+
+void MinidumpGenerator::GatherCurrentProcessDyldInformation() {
+ task_dyld_info_data_t task_dyld_info;
+ mach_msg_type_number_t count = TASK_DYLD_INFO_COUNT;
+ if (task_info(mach_task_self(), TASK_DYLD_INFO,
+ (task_info_t)&task_dyld_info, &count) != KERN_SUCCESS) {
+ return;
+ }
+
+ dyld_all_image_infos_self* aii = (dyld_all_image_infos_self*)
+ task_dyld_info.all_image_info_addr;
+ breakpad_mach_header* mh = (breakpad_mach_header*) aii->dyldImageLoadAddress;
+ if (!mh || (mh->magic != MH_MAGIC_ARCH)) {
+ return;
+ }
+ dyldImageLoadAddress_ = mh;
+ dyldPath_ = string(aii->dyldPath);
+ dyldSlide_ = GetCurrentProcessModuleSlide(mh, aii->sharedCacheSlide);
+}
+
+void MinidumpGenerator::SetTaskContext(breakpad_ucontext_t *task_context) {
+ task_context_ = task_context;
+}
+
+string MinidumpGenerator::UniqueNameInDirectory(const string &dir,
+ string *unique_name) {
+ CFUUIDRef uuid = CFUUIDCreate(NULL);
+ CFStringRef uuid_cfstr = CFUUIDCreateString(NULL, uuid);
+ CFRelease(uuid);
+ string file_name(ConvertToString(uuid_cfstr));
+ CFRelease(uuid_cfstr);
+ string path(dir);
+
+ // Ensure that the directory (if non-empty) has a trailing slash so that
+ // we can append the file name and have a valid pathname.
+ if (!dir.empty()) {
+ if (dir.at(dir.size() - 1) != '/')
+ path.append(1, '/');
+ }
+
+ path.append(file_name);
+ path.append(".dmp");
+
+ if (unique_name)
+ *unique_name = file_name;
+
+ return path;
+}
+
+bool MinidumpGenerator::Write(const char *path) {
+ WriteStreamFN writers[] = {
+ &MinidumpGenerator::WriteThreadListStream,
+ &MinidumpGenerator::WriteMemoryListStream,
+ &MinidumpGenerator::WriteSystemInfoStream,
+ &MinidumpGenerator::WriteModuleListStream,
+ &MinidumpGenerator::WriteMiscInfoStream,
+ &MinidumpGenerator::WriteBreakpadInfoStream,
+ &MinidumpGenerator::WriteCrashInfoStream,
+ &MinidumpGenerator::WriteBootargsStream,
+ &MinidumpGenerator::WriteThreadNamesStream,
+ // Exception stream needs to be the last entry in this array as it may
+ // be omitted in the case where the minidump is written without an
+ // exception.
+ &MinidumpGenerator::WriteExceptionStream,
+ };
+ bool result = false;
+
+ // If opening was successful, create the header, directory, and call each
+ // writer. The destructor for the TypedMDRVAs will cause the data to be
+ // flushed. The destructor for the MinidumpFileWriter will close the file.
+ if (writer_.Open(path)) {
+ TypedMDRVA<MDRawHeader> header(&writer_);
+ TypedMDRVA<MDRawDirectory> dir(&writer_);
+
+ if (!header.Allocate())
+ return false;
+
+ int writer_count = static_cast<int>(sizeof(writers) / sizeof(writers[0]));
+
+ // If we don't have exception information, don't write out the
+ // exception stream
+ if (!exception_thread_ && !exception_type_)
+ --writer_count;
+
+ // Add space for all writers
+ if (!dir.AllocateArray(writer_count))
+ return false;
+
+ MDRawHeader *header_ptr = header.get();
+ header_ptr->signature = MD_HEADER_SIGNATURE;
+ header_ptr->version = MD_HEADER_VERSION;
+ time(reinterpret_cast<time_t *>(&(header_ptr->time_date_stamp)));
+ header_ptr->stream_count = writer_count;
+ header_ptr->stream_directory_rva = dir.position();
+
+ MDRawDirectory local_dir;
+ result = true;
+ for (int i = 0; (result) && (i < writer_count); ++i) {
+ result = (this->*writers[i])(&local_dir);
+
+ if (result)
+ dir.CopyIndex(i, &local_dir);
+ }
+ }
+ return result;
+}
+
+size_t MinidumpGenerator::CalculateStackSize(mach_vm_address_t start_addr) {
+ mach_vm_address_t stack_region_base = start_addr;
+ mach_vm_size_t stack_region_size;
+ natural_t nesting_level = 0;
+ vm_region_submap_info_64 submap_info;
+ mach_msg_type_number_t info_count = VM_REGION_SUBMAP_INFO_COUNT_64;
+
+ vm_region_recurse_info_t region_info;
+ region_info = reinterpret_cast<vm_region_recurse_info_t>(&submap_info);
+
+ if (start_addr == 0) {
+ return 0;
+ }
+
+ kern_return_t result =
+ mach_vm_region_recurse(crashing_task_, &stack_region_base,
+ &stack_region_size, &nesting_level,
+ region_info, &info_count);
+
+ if (result != KERN_SUCCESS || start_addr < stack_region_base) {
+ // Failure or stack corruption, since mach_vm_region had to go
+ // higher in the process address space to find a valid region.
+ return 0;
+ }
+
+ unsigned int tag = submap_info.user_tag;
+
+ // If the user tag is VM_MEMORY_STACK, look for more readable regions with
+ // the same tag placed immediately above the computed stack region. Under
+ // some circumstances, the stack for thread 0 winds up broken up into
+ // multiple distinct abutting regions. This can happen for several reasons,
+ // including user code that calls setrlimit(RLIMIT_STACK, ...) or changes
+ // the access on stack pages by calling mprotect.
+ if (tag == VM_MEMORY_STACK) {
+ while (true) {
+ mach_vm_address_t next_region_base = stack_region_base +
+ stack_region_size;
+ mach_vm_address_t proposed_next_region_base = next_region_base;
+ mach_vm_size_t next_region_size;
+ nesting_level = 0;
+ info_count = VM_REGION_SUBMAP_INFO_COUNT_64;
+ result = mach_vm_region_recurse(crashing_task_, &next_region_base,
+ &next_region_size, &nesting_level,
+ region_info, &info_count);
+ if (result != KERN_SUCCESS ||
+ next_region_base != proposed_next_region_base ||
+ submap_info.user_tag != tag ||
+ (submap_info.protection & VM_PROT_READ) == 0) {
+ break;
+ }
+
+ stack_region_size += next_region_size;
+ }
+ }
+
+ return stack_region_base + stack_region_size - start_addr;
+}
+
+bool MinidumpGenerator::WriteStackFromStartAddress(
+ mach_vm_address_t start_addr,
+ MDMemoryDescriptor *stack_location) {
+ UntypedMDRVA memory(&writer_);
+
+ bool result = false;
+ size_t size = CalculateStackSize(start_addr);
+
+ if (size == 0) {
+ // In some situations the stack address for the thread can come back 0.
+ // In these cases we skip over the threads in question and stuff the
+ // stack with a clearly borked value.
+ start_addr = 0xDEADBEEF;
+ size = 16;
+ if (!memory.Allocate(size))
+ return false;
+
+ unsigned long long dummy_stack[2]; // Fill dummy stack with 16 bytes of
+ // junk.
+ dummy_stack[0] = 0xDEADBEEF;
+ dummy_stack[1] = 0xDEADBEEF;
+
+ result = memory.Copy(dummy_stack, size);
+ } else {
+
+ if (!memory.Allocate(size))
+ return false;
+
+ if (dynamic_images_) {
+ vector<uint8_t> stack_memory;
+ if (ReadTaskMemory(crashing_task_,
+ start_addr,
+ size,
+ stack_memory) != KERN_SUCCESS) {
+ return false;
+ }
+
+ result = memory.Copy(&stack_memory[0], size);
+ } else {
+ result = memory.Copy(reinterpret_cast<const void *>(start_addr), size);
+ }
+ }
+
+ stack_location->start_of_memory_range = start_addr;
+ stack_location->memory = memory.location();
+
+ return result;
+}
+
+bool MinidumpGenerator::WriteStack(breakpad_thread_state_data_t state,
+ MDMemoryDescriptor *stack_location) {
+ switch (cpu_type_) {
+#ifdef HAS_ARM_SUPPORT
+ case CPU_TYPE_ARM:
+ return WriteStackARM(state, stack_location);
+#endif
+#ifdef HAS_ARM64_SUPPORT
+ case CPU_TYPE_ARM64:
+ return WriteStackARM64(state, stack_location);
+#endif
+#ifdef HAS_PPC_SUPPORT
+ case CPU_TYPE_POWERPC:
+ return WriteStackPPC(state, stack_location);
+ case CPU_TYPE_POWERPC64:
+ return WriteStackPPC64(state, stack_location);
+#endif
+#ifdef HAS_X86_SUPPORT
+ case CPU_TYPE_I386:
+ return WriteStackX86(state, stack_location);
+ case CPU_TYPE_X86_64:
+ return WriteStackX86_64(state, stack_location);
+#endif
+ default:
+ return false;
+ }
+}
+
+bool MinidumpGenerator::WriteContext(breakpad_thread_state_data_t state,
+ MDLocationDescriptor *register_location) {
+ switch (cpu_type_) {
+#ifdef HAS_ARM_SUPPORT
+ case CPU_TYPE_ARM:
+ return WriteContextARM(state, register_location);
+#endif
+#ifdef HAS_ARM64_SUPPORT
+ case CPU_TYPE_ARM64:
+ return WriteContextARM64(state, register_location);
+#endif
+#ifdef HAS_PPC_SUPPORT
+ case CPU_TYPE_POWERPC:
+ return WriteContextPPC(state, register_location);
+ case CPU_TYPE_POWERPC64:
+ return WriteContextPPC64(state, register_location);
+#endif
+#ifdef HAS_X86_SUPPORT
+ case CPU_TYPE_I386:
+ return WriteContextX86(state, register_location);
+ case CPU_TYPE_X86_64:
+ return WriteContextX86_64(state, register_location);
+#endif
+ default:
+ return false;
+ }
+}
+
+uint64_t MinidumpGenerator::CurrentPCForStack(
+ breakpad_thread_state_data_t state) {
+ switch (cpu_type_) {
+#ifdef HAS_ARM_SUPPORT
+ case CPU_TYPE_ARM:
+ return CurrentPCForStackARM(state);
+#endif
+#ifdef HAS_ARM64_SUPPORT
+ case CPU_TYPE_ARM64:
+ return CurrentPCForStackARM64(state);
+#endif
+#ifdef HAS_PPC_SUPPORT
+ case CPU_TYPE_POWERPC:
+ return CurrentPCForStackPPC(state);
+ case CPU_TYPE_POWERPC64:
+ return CurrentPCForStackPPC64(state);
+#endif
+#ifdef HAS_X86_SUPPORT
+ case CPU_TYPE_I386:
+ return CurrentPCForStackX86(state);
+ case CPU_TYPE_X86_64:
+ return CurrentPCForStackX86_64(state);
+#endif
+ default:
+ assert(0 && "Unknown CPU type!");
+ return 0;
+ }
+}
+
+#ifdef HAS_ARM_SUPPORT
+bool MinidumpGenerator::WriteStackARM(breakpad_thread_state_data_t state,
+ MDMemoryDescriptor *stack_location) {
+ arm_thread_state_t *machine_state =
+ reinterpret_cast<arm_thread_state_t *>(state);
+ mach_vm_address_t start_addr = REGISTER_FROM_THREADSTATE(machine_state, sp);
+ return WriteStackFromStartAddress(start_addr, stack_location);
+}
+
+uint64_t
+MinidumpGenerator::CurrentPCForStackARM(breakpad_thread_state_data_t state) {
+ arm_thread_state_t *machine_state =
+ reinterpret_cast<arm_thread_state_t *>(state);
+
+ return REGISTER_FROM_THREADSTATE(machine_state, pc);
+}
+
+bool MinidumpGenerator::WriteContextARM(breakpad_thread_state_data_t state,
+ MDLocationDescriptor *register_location)
+{
+ TypedMDRVA<MDRawContextARM> context(&writer_);
+ arm_thread_state_t *machine_state =
+ reinterpret_cast<arm_thread_state_t *>(state);
+
+ if (!context.Allocate())
+ return false;
+
+ *register_location = context.location();
+ MDRawContextARM *context_ptr = context.get();
+ context_ptr->context_flags = MD_CONTEXT_ARM_FULL;
+
+#define AddGPR(a) context_ptr->iregs[a] = REGISTER_FROM_THREADSTATE(machine_state, r[a])
+
+ context_ptr->iregs[13] = REGISTER_FROM_THREADSTATE(machine_state, sp);
+ context_ptr->iregs[14] = REGISTER_FROM_THREADSTATE(machine_state, lr);
+ context_ptr->iregs[15] = REGISTER_FROM_THREADSTATE(machine_state, pc);
+ context_ptr->cpsr = REGISTER_FROM_THREADSTATE(machine_state, cpsr);
+
+ AddGPR(0);
+ AddGPR(1);
+ AddGPR(2);
+ AddGPR(3);
+ AddGPR(4);
+ AddGPR(5);
+ AddGPR(6);
+ AddGPR(7);
+ AddGPR(8);
+ AddGPR(9);
+ AddGPR(10);
+ AddGPR(11);
+ AddGPR(12);
+#undef AddGPR
+
+ return true;
+}
+#endif
+
+#ifdef HAS_ARM64_SUPPORT
+bool MinidumpGenerator::WriteStackARM64(breakpad_thread_state_data_t state,
+ MDMemoryDescriptor *stack_location) {
+ arm_thread_state64_t *machine_state =
+ reinterpret_cast<arm_thread_state64_t *>(state);
+ mach_vm_address_t start_addr = REGISTER_FROM_THREADSTATE(machine_state, sp);
+ return WriteStackFromStartAddress(start_addr, stack_location);
+}
+
+uint64_t
+MinidumpGenerator::CurrentPCForStackARM64(breakpad_thread_state_data_t state) {
+ arm_thread_state64_t *machine_state =
+ reinterpret_cast<arm_thread_state64_t *>(state);
+
+ return REGISTER_FROM_THREADSTATE(machine_state, pc);
+}
+
+bool
+MinidumpGenerator::WriteContextARM64(breakpad_thread_state_data_t state,
+ MDLocationDescriptor *register_location)
+{
+ TypedMDRVA<MDRawContextARM64_Old> context(&writer_);
+ arm_thread_state64_t *machine_state =
+ reinterpret_cast<arm_thread_state64_t *>(state);
+
+ if (!context.Allocate())
+ return false;
+
+ *register_location = context.location();
+ MDRawContextARM64_Old *context_ptr = context.get();
+ context_ptr->context_flags = MD_CONTEXT_ARM64_FULL_OLD;
+
+#define AddGPR(a) \
+ context_ptr->iregs[a] = ARRAY_REGISTER_FROM_THREADSTATE(machine_state, x, a)
+
+ context_ptr->iregs[29] = REGISTER_FROM_THREADSTATE(machine_state, fp);
+ context_ptr->iregs[30] = REGISTER_FROM_THREADSTATE(machine_state, lr);
+ context_ptr->iregs[31] = REGISTER_FROM_THREADSTATE(machine_state, sp);
+ context_ptr->iregs[32] = REGISTER_FROM_THREADSTATE(machine_state, pc);
+ context_ptr->cpsr = REGISTER_FROM_THREADSTATE(machine_state, cpsr);
+
+ AddGPR(0);
+ AddGPR(1);
+ AddGPR(2);
+ AddGPR(3);
+ AddGPR(4);
+ AddGPR(5);
+ AddGPR(6);
+ AddGPR(7);
+ AddGPR(8);
+ AddGPR(9);
+ AddGPR(10);
+ AddGPR(11);
+ AddGPR(12);
+ AddGPR(13);
+ AddGPR(14);
+ AddGPR(15);
+ AddGPR(16);
+ AddGPR(17);
+ AddGPR(18);
+ AddGPR(19);
+ AddGPR(20);
+ AddGPR(21);
+ AddGPR(22);
+ AddGPR(23);
+ AddGPR(24);
+ AddGPR(25);
+ AddGPR(26);
+ AddGPR(27);
+ AddGPR(28);
+#undef AddGPR
+
+ return true;
+}
+#endif
+
+#ifdef HAS_PCC_SUPPORT
+bool MinidumpGenerator::WriteStackPPC(breakpad_thread_state_data_t state,
+ MDMemoryDescriptor *stack_location) {
+ ppc_thread_state_t *machine_state =
+ reinterpret_cast<ppc_thread_state_t *>(state);
+ mach_vm_address_t start_addr = REGISTER_FROM_THREADSTATE(machine_state, r1);
+ return WriteStackFromStartAddress(start_addr, stack_location);
+}
+
+bool MinidumpGenerator::WriteStackPPC64(breakpad_thread_state_data_t state,
+ MDMemoryDescriptor *stack_location) {
+ ppc_thread_state64_t *machine_state =
+ reinterpret_cast<ppc_thread_state64_t *>(state);
+ mach_vm_address_t start_addr = REGISTER_FROM_THREADSTATE(machine_state, r1);
+ return WriteStackFromStartAddress(start_addr, stack_location);
+}
+
+uint64_t
+MinidumpGenerator::CurrentPCForStackPPC(breakpad_thread_state_data_t state) {
+ ppc_thread_state_t *machine_state =
+ reinterpret_cast<ppc_thread_state_t *>(state);
+
+ return REGISTER_FROM_THREADSTATE(machine_state, srr0);
+}
+
+uint64_t
+MinidumpGenerator::CurrentPCForStackPPC64(breakpad_thread_state_data_t state) {
+ ppc_thread_state64_t *machine_state =
+ reinterpret_cast<ppc_thread_state64_t *>(state);
+
+ return REGISTER_FROM_THREADSTATE(machine_state, srr0);
+}
+
+bool MinidumpGenerator::WriteContextPPC(breakpad_thread_state_data_t state,
+ MDLocationDescriptor *register_location)
+{
+ TypedMDRVA<MDRawContextPPC> context(&writer_);
+ ppc_thread_state_t *machine_state =
+ reinterpret_cast<ppc_thread_state_t *>(state);
+
+ if (!context.Allocate())
+ return false;
+
+ *register_location = context.location();
+ MDRawContextPPC *context_ptr = context.get();
+ context_ptr->context_flags = MD_CONTEXT_PPC_BASE;
+
+#define AddReg(a) context_ptr->a = static_cast<__typeof__(context_ptr->a)>( \
+ REGISTER_FROM_THREADSTATE(machine_state, a))
+#define AddGPR(a) context_ptr->gpr[a] = \
+ static_cast<__typeof__(context_ptr->a)>( \
+ REGISTER_FROM_THREADSTATE(machine_state, r ## a)
+
+ AddReg(srr0);
+ AddReg(cr);
+ AddReg(xer);
+ AddReg(ctr);
+ AddReg(lr);
+ AddReg(vrsave);
+
+ AddGPR(0);
+ AddGPR(1);
+ AddGPR(2);
+ AddGPR(3);
+ AddGPR(4);
+ AddGPR(5);
+ AddGPR(6);
+ AddGPR(7);
+ AddGPR(8);
+ AddGPR(9);
+ AddGPR(10);
+ AddGPR(11);
+ AddGPR(12);
+ AddGPR(13);
+ AddGPR(14);
+ AddGPR(15);
+ AddGPR(16);
+ AddGPR(17);
+ AddGPR(18);
+ AddGPR(19);
+ AddGPR(20);
+ AddGPR(21);
+ AddGPR(22);
+ AddGPR(23);
+ AddGPR(24);
+ AddGPR(25);
+ AddGPR(26);
+ AddGPR(27);
+ AddGPR(28);
+ AddGPR(29);
+ AddGPR(30);
+ AddGPR(31);
+ AddReg(mq);
+#undef AddReg
+#undef AddGPR
+
+ return true;
+}
+
+bool MinidumpGenerator::WriteContextPPC64(
+ breakpad_thread_state_data_t state,
+ MDLocationDescriptor *register_location) {
+ TypedMDRVA<MDRawContextPPC64> context(&writer_);
+ ppc_thread_state64_t *machine_state =
+ reinterpret_cast<ppc_thread_state64_t *>(state);
+
+ if (!context.Allocate())
+ return false;
+
+ *register_location = context.location();
+ MDRawContextPPC64 *context_ptr = context.get();
+ context_ptr->context_flags = MD_CONTEXT_PPC_BASE;
+
+#define AddReg(a) context_ptr->a = static_cast<__typeof__(context_ptr->a)>( \
+ REGISTER_FROM_THREADSTATE(machine_state, a))
+#define AddGPR(a) context_ptr->gpr[a] = \
+ static_cast<__typeof__(context_ptr->a)>( \
+ REGISTER_FROM_THREADSTATE(machine_state, r ## a)
+
+ AddReg(srr0);
+ AddReg(cr);
+ AddReg(xer);
+ AddReg(ctr);
+ AddReg(lr);
+ AddReg(vrsave);
+
+ AddGPR(0);
+ AddGPR(1);
+ AddGPR(2);
+ AddGPR(3);
+ AddGPR(4);
+ AddGPR(5);
+ AddGPR(6);
+ AddGPR(7);
+ AddGPR(8);
+ AddGPR(9);
+ AddGPR(10);
+ AddGPR(11);
+ AddGPR(12);
+ AddGPR(13);
+ AddGPR(14);
+ AddGPR(15);
+ AddGPR(16);
+ AddGPR(17);
+ AddGPR(18);
+ AddGPR(19);
+ AddGPR(20);
+ AddGPR(21);
+ AddGPR(22);
+ AddGPR(23);
+ AddGPR(24);
+ AddGPR(25);
+ AddGPR(26);
+ AddGPR(27);
+ AddGPR(28);
+ AddGPR(29);
+ AddGPR(30);
+ AddGPR(31);
+#undef AddReg
+#undef AddGPR
+
+ return true;
+}
+
+#endif
+
+#ifdef HAS_X86_SUPPORT
+bool MinidumpGenerator::WriteStackX86(breakpad_thread_state_data_t state,
+ MDMemoryDescriptor *stack_location) {
+ i386_thread_state_t *machine_state =
+ reinterpret_cast<i386_thread_state_t *>(state);
+
+ mach_vm_address_t start_addr = REGISTER_FROM_THREADSTATE(machine_state, esp);
+ return WriteStackFromStartAddress(start_addr, stack_location);
+}
+
+bool MinidumpGenerator::WriteStackX86_64(breakpad_thread_state_data_t state,
+ MDMemoryDescriptor *stack_location) {
+ x86_thread_state64_t *machine_state =
+ reinterpret_cast<x86_thread_state64_t *>(state);
+
+ mach_vm_address_t start_addr = static_cast<mach_vm_address_t>(
+ REGISTER_FROM_THREADSTATE(machine_state, rsp));
+ return WriteStackFromStartAddress(start_addr, stack_location);
+}
+
+uint64_t
+MinidumpGenerator::CurrentPCForStackX86(breakpad_thread_state_data_t state) {
+ i386_thread_state_t *machine_state =
+ reinterpret_cast<i386_thread_state_t *>(state);
+
+ return REGISTER_FROM_THREADSTATE(machine_state, eip);
+}
+
+uint64_t
+MinidumpGenerator::CurrentPCForStackX86_64(breakpad_thread_state_data_t state) {
+ x86_thread_state64_t *machine_state =
+ reinterpret_cast<x86_thread_state64_t *>(state);
+
+ return REGISTER_FROM_THREADSTATE(machine_state, rip);
+}
+
+bool MinidumpGenerator::WriteContextX86(breakpad_thread_state_data_t state,
+ MDLocationDescriptor *register_location)
+{
+ TypedMDRVA<MDRawContextX86> context(&writer_);
+ i386_thread_state_t *machine_state =
+ reinterpret_cast<i386_thread_state_t *>(state);
+
+ if (!context.Allocate())
+ return false;
+
+ *register_location = context.location();
+ MDRawContextX86 *context_ptr = context.get();
+
+#define AddReg(a) context_ptr->a = static_cast<__typeof__(context_ptr->a)>( \
+ REGISTER_FROM_THREADSTATE(machine_state, a))
+
+ context_ptr->context_flags = MD_CONTEXT_X86;
+ AddReg(eax);
+ AddReg(ebx);
+ AddReg(ecx);
+ AddReg(edx);
+ AddReg(esi);
+ AddReg(edi);
+ AddReg(ebp);
+ AddReg(esp);
+
+ AddReg(cs);
+ AddReg(ds);
+ AddReg(ss);
+ AddReg(es);
+ AddReg(fs);
+ AddReg(gs);
+ AddReg(eflags);
+
+ AddReg(eip);
+#undef AddReg
+
+ return true;
+}
+
+bool MinidumpGenerator::WriteContextX86_64(
+ breakpad_thread_state_data_t state,
+ MDLocationDescriptor *register_location) {
+ TypedMDRVA<MDRawContextAMD64> context(&writer_);
+ x86_thread_state64_t *machine_state =
+ reinterpret_cast<x86_thread_state64_t *>(state);
+
+ if (!context.Allocate())
+ return false;
+
+ *register_location = context.location();
+ MDRawContextAMD64 *context_ptr = context.get();
+
+#define AddReg(a) context_ptr->a = static_cast<__typeof__(context_ptr->a)>( \
+ REGISTER_FROM_THREADSTATE(machine_state, a))
+
+ context_ptr->context_flags = MD_CONTEXT_AMD64;
+ AddReg(rax);
+ AddReg(rbx);
+ AddReg(rcx);
+ AddReg(rdx);
+ AddReg(rdi);
+ AddReg(rsi);
+ AddReg(rbp);
+ AddReg(rsp);
+ AddReg(r8);
+ AddReg(r9);
+ AddReg(r10);
+ AddReg(r11);
+ AddReg(r12);
+ AddReg(r13);
+ AddReg(r14);
+ AddReg(r15);
+ AddReg(rip);
+ // according to AMD's software developer guide, bits above 18 are
+ // not used in the flags register. Since the minidump format
+ // specifies 32 bits for the flags register, we can truncate safely
+ // with no loss.
+ context_ptr->eflags = static_cast<uint32_t>(REGISTER_FROM_THREADSTATE(machine_state, rflags));
+ AddReg(cs);
+ AddReg(fs);
+ AddReg(gs);
+#undef AddReg
+
+ return true;
+}
+#endif
+
+bool MinidumpGenerator::GetThreadState(thread_act_t target_thread,
+ thread_state_t state,
+ mach_msg_type_number_t *count) {
+ if (task_context_ && target_thread == mach_thread_self()) {
+ switch (cpu_type_) {
+#ifdef HAS_ARM_SUPPORT
+ case CPU_TYPE_ARM:
+ size_t final_size =
+ std::min(static_cast<size_t>(*count), sizeof(arm_thread_state_t));
+ memcpy(state, &task_context_->breakpad_uc_mcontext->__ss, final_size);
+ *count = static_cast<mach_msg_type_number_t>(final_size);
+ return true;
+#endif
+#ifdef HAS_ARM64_SUPPORT
+ case CPU_TYPE_ARM64: {
+ size_t final_size =
+ std::min(static_cast<size_t>(*count), sizeof(arm_thread_state64_t));
+ memcpy(state, &task_context_->breakpad_uc_mcontext->__ss, final_size);
+ *count = static_cast<mach_msg_type_number_t>(final_size);
+ return true;
+ }
+#endif
+#ifdef HAS_X86_SUPPORT
+ case CPU_TYPE_I386:
+ case CPU_TYPE_X86_64: {
+ size_t state_size = cpu_type_ == CPU_TYPE_I386 ?
+ sizeof(i386_thread_state_t) : sizeof(x86_thread_state64_t);
+ size_t final_size =
+ std::min(static_cast<size_t>(*count), state_size);
+ memcpy(state, &task_context_->breakpad_uc_mcontext->__ss, final_size);
+ *count = static_cast<mach_msg_type_number_t>(final_size);
+ return true;
+ }
+#endif
+ }
+ }
+
+ thread_state_flavor_t flavor;
+ switch (cpu_type_) {
+#ifdef HAS_ARM_SUPPORT
+ case CPU_TYPE_ARM:
+ flavor = ARM_THREAD_STATE;
+ break;
+#endif
+#ifdef HAS_ARM64_SUPPORT
+ case CPU_TYPE_ARM64:
+ flavor = ARM_THREAD_STATE64;
+ break;
+#endif
+#ifdef HAS_PPC_SUPPORT
+ case CPU_TYPE_POWERPC:
+ flavor = PPC_THREAD_STATE;
+ break;
+ case CPU_TYPE_POWERPC64:
+ flavor = PPC_THREAD_STATE64;
+ break;
+#endif
+#ifdef HAS_X86_SUPPORT
+ case CPU_TYPE_I386:
+ flavor = i386_THREAD_STATE;
+ break;
+ case CPU_TYPE_X86_64:
+ flavor = x86_THREAD_STATE64;
+ break;
+#endif
+ default:
+ return false;
+ }
+ return thread_get_state(target_thread, flavor,
+ state, count) == KERN_SUCCESS;
+}
+
+bool MinidumpGenerator::WriteThreadStream(mach_port_t thread_id,
+ MDRawThread *thread) {
+ breakpad_thread_state_data_t state;
+ mach_msg_type_number_t state_count
+ = static_cast<mach_msg_type_number_t>(sizeof(state));
+
+ if (GetThreadState(thread_id, state, &state_count)) {
+ if (!WriteStack(state, &thread->stack))
+ return false;
+
+ memory_blocks_.push_back(thread->stack);
+
+ if (!WriteContext(state, &thread->thread_context))
+ return false;
+
+ thread->thread_id = thread_id;
+ } else {
+ return false;
+ }
+
+ return true;
+}
+
+bool MinidumpGenerator::WriteThreadListStream(
+ MDRawDirectory *thread_list_stream) {
+ TypedMDRVA<MDRawThreadList> list(&writer_);
+ thread_act_port_array_t threads_for_task;
+ mach_msg_type_number_t thread_count;
+ int non_generator_thread_count;
+
+ if (task_threads(crashing_task_, &threads_for_task, &thread_count))
+ return false;
+
+ // Don't include the generator thread
+ if (handler_thread_ != MACH_PORT_NULL)
+ non_generator_thread_count = thread_count - 1;
+ else
+ non_generator_thread_count = thread_count;
+ if (!list.AllocateObjectAndArray(non_generator_thread_count,
+ sizeof(MDRawThread)))
+ return false;
+
+ thread_list_stream->stream_type = MD_THREAD_LIST_STREAM;
+ thread_list_stream->location = list.location();
+
+ list.get()->number_of_threads = non_generator_thread_count;
+
+ MDRawThread thread;
+ int thread_idx = 0;
+
+ for (unsigned int i = 0; i < thread_count; ++i) {
+ memset(&thread, 0, sizeof(MDRawThread));
+
+ if (threads_for_task[i] != handler_thread_) {
+ if (!WriteThreadStream(threads_for_task[i], &thread))
+ return false;
+
+ list.CopyIndexAfterObject(thread_idx++, &thread, sizeof(MDRawThread));
+ }
+ }
+
+ return true;
+}
+
+bool MinidumpGenerator::WriteMemoryListStream(
+ MDRawDirectory *memory_list_stream) {
+ TypedMDRVA<MDRawMemoryList> list(&writer_);
+
+ // If the dump has an exception, include some memory around the
+ // instruction pointer.
+ const size_t kIPMemorySize = 256; // bytes
+ bool have_ip_memory = false;
+ MDMemoryDescriptor ip_memory_d;
+ if (exception_thread_ && exception_type_) {
+ breakpad_thread_state_data_t state;
+ mach_msg_type_number_t stateCount
+ = static_cast<mach_msg_type_number_t>(sizeof(state));
+
+ if (GetThreadState(exception_thread_, state, &stateCount)) {
+ uint64_t ip = CurrentPCForStack(state);
+ // Bound it to the upper and lower bounds of the region
+ // it's contained within. If it's not in a known memory region,
+ // don't bother trying to write it.
+ mach_vm_address_t addr = static_cast<vm_address_t>(ip);
+ mach_vm_size_t size;
+ natural_t nesting_level = 0;
+ vm_region_submap_info_64 info;
+ mach_msg_type_number_t info_count = VM_REGION_SUBMAP_INFO_COUNT_64;
+ vm_region_recurse_info_t recurse_info;
+ recurse_info = reinterpret_cast<vm_region_recurse_info_t>(&info);
+
+ kern_return_t ret =
+ mach_vm_region_recurse(crashing_task_,
+ &addr,
+ &size,
+ &nesting_level,
+ recurse_info,
+ &info_count);
+ if (ret == KERN_SUCCESS && ip >= addr && ip < (addr + size)) {
+ // Try to get 128 bytes before and after the IP, but
+ // settle for whatever's available.
+ ip_memory_d.start_of_memory_range =
+ std::max(uintptr_t(addr),
+ uintptr_t(ip - (kIPMemorySize / 2)));
+ uintptr_t end_of_range =
+ std::min(uintptr_t(ip + (kIPMemorySize / 2)),
+ uintptr_t(addr + size));
+ uintptr_t range_diff = end_of_range -
+ static_cast<uintptr_t>(ip_memory_d.start_of_memory_range);
+ ip_memory_d.memory.data_size = static_cast<uint32_t>(range_diff);
+ have_ip_memory = true;
+ // This needs to get appended to the list even though
+ // the memory bytes aren't filled in yet so the entire
+ // list can be written first. The memory bytes will get filled
+ // in after the memory list is written.
+ memory_blocks_.push_back(ip_memory_d);
+ }
+ }
+ }
+
+ // Now fill in the memory list and write it.
+ size_t memory_count = memory_blocks_.size();
+ if (!list.AllocateObjectAndArray(memory_count,
+ sizeof(MDMemoryDescriptor)))
+ return false;
+
+ memory_list_stream->stream_type = MD_MEMORY_LIST_STREAM;
+ memory_list_stream->location = list.location();
+
+ list.get()->number_of_memory_ranges = static_cast<uint32_t>(memory_count);
+
+ unsigned int i;
+ for (i = 0; i < memory_count; ++i) {
+ list.CopyIndexAfterObject(i, &memory_blocks_[i],
+ sizeof(MDMemoryDescriptor));
+ }
+
+ if (have_ip_memory) {
+ // Now read the memory around the instruction pointer.
+ UntypedMDRVA ip_memory(&writer_);
+ if (!ip_memory.Allocate(ip_memory_d.memory.data_size))
+ return false;
+
+ if (dynamic_images_) {
+ // Out-of-process.
+ vector<uint8_t> memory;
+ if (ReadTaskMemory(crashing_task_,
+ ip_memory_d.start_of_memory_range,
+ ip_memory_d.memory.data_size,
+ memory) != KERN_SUCCESS) {
+ return false;
+ }
+
+ ip_memory.Copy(&memory[0], ip_memory_d.memory.data_size);
+ } else {
+ // In-process, just copy from local memory.
+ ip_memory.Copy(
+ reinterpret_cast<const void *>(ip_memory_d.start_of_memory_range),
+ ip_memory_d.memory.data_size);
+ }
+
+ ip_memory_d.memory = ip_memory.location();
+ // Write this again now that the data location is filled in.
+ list.CopyIndexAfterObject(i - 1, &ip_memory_d,
+ sizeof(MDMemoryDescriptor));
+ }
+
+ return true;
+}
+
+bool
+MinidumpGenerator::WriteExceptionStream(MDRawDirectory *exception_stream) {
+ TypedMDRVA<MDRawExceptionStream> exception(&writer_);
+
+ if (!exception.Allocate())
+ return false;
+
+ exception_stream->stream_type = MD_EXCEPTION_STREAM;
+ exception_stream->location = exception.location();
+ MDRawExceptionStream *exception_ptr = exception.get();
+ exception_ptr->thread_id = exception_thread_;
+
+ uint64_t u_exception_code = exception_code_;
+ if (exception_type_ == EXC_CRASH) {
+ if (!IsValidExcCrash(exception_code_)) {
+ return false;
+ }
+
+ [[maybe_unused]] int signal_number;
+ RecoverExceptionDataFromExcCrash(u_exception_code, signal_number);
+ }
+
+ // This naming is confusing, but it is the proper translation from
+ // mach naming to minidump naming.
+ exception_ptr->exception_record.exception_code = exception_type_;
+
+ uint32_t exception_flags = 0;
+ if (exception_type_ == EXC_RESOURCE || exception_type_ == EXC_GUARD) {
+ // For EXC_RESOURCE and EXC_GUARD crashes Crashpad records the uppermost
+ // 32 bits of the exception code in the exception flags, let's do the same
+ // here.
+ exception_flags = u_exception_code >> 32;
+ } else {
+ exception_flags = exception_code_;
+ }
+
+ exception_ptr->exception_record.exception_flags = exception_flags;
+
+ breakpad_thread_state_data_t state;
+ mach_msg_type_number_t state_count
+ = static_cast<mach_msg_type_number_t>(sizeof(state));
+
+ if (!GetThreadState(exception_thread_, state, &state_count))
+ return false;
+
+ if (!WriteContext(state, &exception_ptr->thread_context))
+ return false;
+
+ if (exception_type_ == EXC_BAD_ACCESS)
+ exception_ptr->exception_record.exception_address = exception_subcode_;
+ else
+ exception_ptr->exception_record.exception_address = CurrentPCForStack(state);
+
+ // Crashpad stores the exception type and the optional exception codes in
+ // the exception information field, so we do the same here.
+ exception_ptr->exception_record.number_parameters =
+ (exception_subcode_ != 0) ? 3 : 2;
+ exception_ptr->exception_record.exception_information[0] = exception_type_;
+ exception_ptr->exception_record.exception_information[1] = exception_code_;
+ exception_ptr->exception_record.exception_information[2] = exception_subcode_;
+
+ return true;
+}
+
+bool MinidumpGenerator::WriteSystemInfoStream(
+ MDRawDirectory *system_info_stream) {
+ TypedMDRVA<MDRawSystemInfo> info(&writer_);
+
+ if (!info.Allocate())
+ return false;
+
+ system_info_stream->stream_type = MD_SYSTEM_INFO_STREAM;
+ system_info_stream->location = info.location();
+
+ // CPU Information
+ uint32_t number_of_processors;
+ size_t len = sizeof(number_of_processors);
+ sysctlbyname("hw.ncpu", &number_of_processors, &len, NULL, 0);
+ MDRawSystemInfo *info_ptr = info.get();
+
+ switch (cpu_type_) {
+#ifdef HAS_ARM_SUPPORT
+ case CPU_TYPE_ARM:
+ info_ptr->processor_architecture = MD_CPU_ARCHITECTURE_ARM;
+ break;
+#endif
+#ifdef HAS_ARM64_SUPPORT
+ case CPU_TYPE_ARM64:
+ info_ptr->processor_architecture = MD_CPU_ARCHITECTURE_ARM64_OLD;
+ break;
+#endif
+#ifdef HAS_PPC_SUPPORT
+ case CPU_TYPE_POWERPC:
+ case CPU_TYPE_POWERPC64:
+ info_ptr->processor_architecture = MD_CPU_ARCHITECTURE_PPC;
+ break;
+#endif
+#ifdef HAS_X86_SUPPORT
+ case CPU_TYPE_I386:
+ case CPU_TYPE_X86_64:
+ if (cpu_type_ == CPU_TYPE_I386)
+ info_ptr->processor_architecture = MD_CPU_ARCHITECTURE_X86;
+ else
+ info_ptr->processor_architecture = MD_CPU_ARCHITECTURE_AMD64;
+#ifdef __i386__
+ // ebx is used for PIC code, so we need
+ // to preserve it.
+#define cpuid(op,eax,ebx,ecx,edx) \
+ asm ("pushl %%ebx \n\t" \
+ "cpuid \n\t" \
+ "movl %%ebx,%1 \n\t" \
+ "popl %%ebx" \
+ : "=a" (eax), \
+ "=g" (ebx), \
+ "=c" (ecx), \
+ "=d" (edx) \
+ : "0" (op))
+#elif defined(__x86_64__)
+
+#define cpuid(op,eax,ebx,ecx,edx) \
+ asm ("cpuid \n\t" \
+ : "=a" (eax), \
+ "=b" (ebx), \
+ "=c" (ecx), \
+ "=d" (edx) \
+ : "0" (op))
+#endif
+
+#if defined(__i386__) || defined(__x86_64__)
+ int unused, unused2;
+ // get vendor id
+ cpuid(0, unused, info_ptr->cpu.x86_cpu_info.vendor_id[0],
+ info_ptr->cpu.x86_cpu_info.vendor_id[2],
+ info_ptr->cpu.x86_cpu_info.vendor_id[1]);
+ // get version and feature info
+ cpuid(1, info_ptr->cpu.x86_cpu_info.version_information, unused, unused2,
+ info_ptr->cpu.x86_cpu_info.feature_information);
+
+ // family
+ info_ptr->processor_level =
+ (info_ptr->cpu.x86_cpu_info.version_information & 0xF00) >> 8;
+ // 0xMMSS (Model, Stepping)
+ info_ptr->processor_revision = static_cast<uint16_t>(
+ (info_ptr->cpu.x86_cpu_info.version_information & 0xF) |
+ ((info_ptr->cpu.x86_cpu_info.version_information & 0xF0) << 4));
+
+ // decode extended model info
+ if (info_ptr->processor_level == 0xF ||
+ info_ptr->processor_level == 0x6) {
+ info_ptr->processor_revision |=
+ ((info_ptr->cpu.x86_cpu_info.version_information & 0xF0000) >> 4);
+ }
+
+ // decode extended family info
+ if (info_ptr->processor_level == 0xF) {
+ info_ptr->processor_level +=
+ ((info_ptr->cpu.x86_cpu_info.version_information & 0xFF00000) >> 20);
+ }
+
+#endif // __i386__ || __x86_64_
+ break;
+#endif // HAS_X86_SUPPORT
+ default:
+ info_ptr->processor_architecture = MD_CPU_ARCHITECTURE_UNKNOWN;
+ break;
+ }
+
+ info_ptr->number_of_processors = static_cast<uint8_t>(number_of_processors);
+#if TARGET_OS_IPHONE
+ info_ptr->platform_id = MD_OS_IOS;
+#else
+ info_ptr->platform_id = MD_OS_MAC_OS_X;
+#endif // TARGET_OS_IPHONE
+
+ MDLocationDescriptor build_string_loc;
+
+ if (!writer_.WriteString(build_string_, 0,
+ &build_string_loc))
+ return false;
+
+ info_ptr->csd_version_rva = build_string_loc.rva;
+ info_ptr->major_version = os_major_version_;
+ info_ptr->minor_version = os_minor_version_;
+ info_ptr->build_number = os_build_number_;
+
+ return true;
+}
+
+// If index == INT_MAX, we're being asked to write dyld in the crashed process.
+bool MinidumpGenerator::WriteModuleStream(unsigned int index,
+ MDRawModule *module) {
+ if (dynamic_images_) {
+ // we're in a different process than the crashed process
+ DynamicImage *image = dynamic_images_->GetImage(index);
+
+ if (!image)
+ return false;
+
+ memset(module, 0, sizeof(MDRawModule));
+
+ MDLocationDescriptor string_location;
+
+ string name = image->GetFilePath();
+ if (!writer_.WriteString(name.c_str(), 0, &string_location))
+ return false;
+
+ module->base_of_image = image->GetVMAddr() + image->GetVMAddrSlide();
+ module->size_of_image = static_cast<uint32_t>(image->GetVMSize());
+ module->module_name_rva = string_location.rva;
+
+ // We'll skip the executable module, because they don't have
+ // LC_ID_DYLIB load commands, and the crash processing server gets
+ // version information from the Plist file, anyway.
+ if (index != static_cast<uint32_t>(FindExecutableModule())) {
+ module->version_info.signature = MD_VSFIXEDFILEINFO_SIGNATURE;
+ module->version_info.struct_version |= MD_VSFIXEDFILEINFO_VERSION;
+ // Convert MAC dylib version format, which is a 32 bit number, to the
+ // format used by minidump. The mac format is <16 bits>.<8 bits>.<8 bits>
+ // so it fits nicely into the windows version with some massaging
+ // The mapping is:
+ // 1) upper 16 bits of MAC version go to lower 16 bits of product HI
+ // 2) Next most significant 8 bits go to upper 16 bits of product LO
+ // 3) Least significant 8 bits go to lower 16 bits of product LO
+ uint32_t modVersion = image->GetVersion();
+ module->version_info.file_version_hi = 0;
+ module->version_info.file_version_hi = modVersion >> 16;
+ module->version_info.file_version_lo |= (modVersion & 0xff00) << 8;
+ module->version_info.file_version_lo |= (modVersion & 0xff);
+ }
+
+ if (!WriteCVRecord(module, image->GetCPUType(), image->GetCPUSubtype(),
+ name.c_str(), /* in_memory */ false, /* out_of_process */ true,
+ image->GetIsDyld() || image->GetInDyldSharedCache())) {
+ return false;
+ }
+ } else {
+ // Getting module info in the crashed process
+ const breakpad_mach_header *header;
+ if (index == INT_MAX) {
+ header = dyldImageLoadAddress_;
+ } else {
+ header = (breakpad_mach_header*)_dyld_get_image_header(index);
+ }
+ if (!header)
+ return false;
+
+#ifdef __LP64__
+ assert(header->magic == MH_MAGIC_64);
+
+ if(header->magic != MH_MAGIC_64)
+ return false;
+#else
+ assert(header->magic == MH_MAGIC);
+
+ if(header->magic != MH_MAGIC)
+ return false;
+#endif
+
+ int cpu_type = header->cputype;
+ int cpu_subtype = (header->cpusubtype & ~CPU_SUBTYPE_MASK);
+ bool dyld_or_in_dyld_shared_cache;
+ unsigned long slide;
+ const char* name;
+ if (index == INT_MAX) {
+ dyld_or_in_dyld_shared_cache = true;
+ slide = dyldSlide_;
+ name = dyldPath_.c_str();
+ } else {
+ dyld_or_in_dyld_shared_cache =
+ ((header->flags & MH_SHAREDCACHE) != 0);
+ slide = _dyld_get_image_vmaddr_slide(index);
+ name = _dyld_get_image_name(index);
+ }
+ const struct load_command *cmd =
+ reinterpret_cast<const struct load_command *>(header + 1);
+
+ memset(module, 0, sizeof(MDRawModule));
+
+ for (unsigned int i = 0; cmd && (i < header->ncmds); i++) {
+ if (cmd->cmd == LC_SEGMENT_ARCH) {
+
+ const breakpad_mach_segment_command *seg =
+ reinterpret_cast<const breakpad_mach_segment_command *>(cmd);
+
+ if (!strcmp(seg->segname, "__TEXT")) {
+ MDLocationDescriptor string_location;
+
+ if (!writer_.WriteString(name, 0, &string_location))
+ return false;
+
+ module->base_of_image = seg->vmaddr + slide;
+ module->size_of_image = static_cast<uint32_t>(seg->vmsize);
+ module->module_name_rva = string_location.rva;
+
+ bool in_memory = false;
+#if TARGET_OS_IPHONE
+ in_memory = true;
+#endif
+ if (!WriteCVRecord(module, cpu_type, cpu_subtype, name, in_memory,
+ /* out_of_process */ false,
+ dyld_or_in_dyld_shared_cache)) {
+ return false;
+ }
+
+ return true;
+ }
+ }
+
+ cmd = reinterpret_cast<struct load_command*>((char *)cmd + cmd->cmdsize);
+ }
+ }
+
+ return true;
+}
+
+int MinidumpGenerator::FindExecutableModule() {
+ if (dynamic_images_) {
+ int index = dynamic_images_->GetExecutableImageIndex();
+
+ if (index >= 0) {
+ return index;
+ }
+ } else {
+ int image_count = _dyld_image_count();
+ const struct mach_header *header;
+
+ for (int index = 0; index < image_count; ++index) {
+ header = _dyld_get_image_header(index);
+
+ if (header->filetype == MH_EXECUTE)
+ return index;
+ }
+ }
+
+ // failed - just use the first image
+ return 0;
+}
+
+bool MinidumpGenerator::IsValidExcCrash(uint64_t exception_code) {
+ switch ((exception_code >> 20) & 0xf) {
+ case EXC_CRASH: // EXC_CRASH cannot wrap EXC_CRASH
+ case EXC_RESOURCE: // EXC_RESOURCE would lose data if wrapped
+ case EXC_GUARD: // EXC_GUARD would lose data if wrapped
+ case EXC_CORPSE_NOTIFY: // EXC_CRASH cannot wrap EXC_CORPSE_NOTIFY
+ return false;
+ default:
+ return true;
+ }
+}
+
+void MinidumpGenerator::RecoverExceptionDataFromExcCrash(
+ uint64_t exception_code, int& signal_number)
+{
+ exception_type_ = (exception_code >> 20) & 0xf;
+ exception_code_ = exception_code & 0xfffff;
+ signal_number = (exception_code >> 24) & 0xff;
+}
+
+bool MinidumpGenerator::WriteCVRecord(MDRawModule *module, int cpu_type, int cpu_subtype,
+ const char *module_path, bool in_memory,
+ bool out_of_process, bool dyld_or_in_dyld_shared_cache) {
+ TypedMDRVA<MDCVInfoPDB70> cv(&writer_);
+
+ // Only return the last path component of the full module path
+ const char *module_name = strrchr(module_path, '/');
+
+ // Increment past the slash
+ if (module_name)
+ ++module_name;
+ else
+ module_name = "<Unknown>";
+
+ size_t module_name_length = strlen(module_name);
+
+ if (!cv.AllocateObjectAndArray(module_name_length + 1, sizeof(uint8_t)))
+ return false;
+
+ if (!cv.CopyIndexAfterObject(0, module_name, module_name_length))
+ return false;
+
+ module->cv_record = cv.location();
+ MDCVInfoPDB70 *cv_ptr = cv.get();
+ cv_ptr->cv_signature = MD_CVINFOPDB70_SIGNATURE;
+ cv_ptr->age = 0;
+
+ // Get the module identifier
+ unsigned char identifier[16];
+ bool result = false;
+ bool in_memory_changed = false;
+ // As of macOS 11, most system libraries no longer have separate copies in
+ // the macOS file system. They only exist all lumped together in the "dyld
+ // shared cache", which gets loaded into each process on startup. If one of
+ // our system libraries isn't in the file system, we can only get a UUID
+ // (aka a debug id) for it by looking at a copy of the module loaded into
+ // the crashing process. Setting 'in_memory' to 'true' makes this happen.
+ //
+ // We should be reluctant to change the value of 'in_memory' from 'false' to
+ // 'true'. But we'll sometimes need to do that to work around the problem
+ // discussed above. In any case we only do it if all else has failed. This
+ // resolves https://bugzilla.mozilla.org/show_bug.cgi?id=1662862.
+ //
+ // We're always called in the main process. But the crashing process might
+ // be either the same process or a different one (a child process). If it's
+ // a child process, the modules we'll be looking at are in that process's
+ // memory space, to which we generally don't have access. But because dyld
+ // and the dyld shared cache are loaded into all processes, we do have
+ // access (in child processes) to dyld and modules in the dyld shared cache.
+ // So it's fine to look at these modules. But we must prevent ourselves from
+ // trying to access other child process modules. This resolves
+ // https://bugzilla.mozilla.org/show_bug.cgi?id=1676102.
+ while (true) {
+ if (in_memory) {
+ if (out_of_process && !dyld_or_in_dyld_shared_cache) {
+ break;
+ }
+ MacFileUtilities::MachoID macho(module_path,
+ reinterpret_cast<void *>(module->base_of_image),
+ static_cast<size_t>(module->size_of_image));
+ result = macho.UUIDCommand(cpu_type, cpu_subtype, identifier);
+ if (!result)
+ result = macho.MD5(cpu_type, cpu_subtype, identifier);
+ if (result || in_memory_changed)
+ break;
+ }
+
+ if (!result) {
+ FileID file_id(module_path);
+ result = file_id.MachoIdentifier(cpu_type, cpu_subtype,
+ identifier);
+ }
+ if (result)
+ break;
+
+ if (!in_memory) {
+ in_memory = true;
+ in_memory_changed = true;
+ } else
+ break;
+ }
+
+ if (result) {
+ cv_ptr->signature.data1 =
+ static_cast<uint32_t>(identifier[0]) << 24 |
+ static_cast<uint32_t>(identifier[1]) << 16 |
+ static_cast<uint32_t>(identifier[2]) << 8 |
+ static_cast<uint32_t>(identifier[3]);
+ cv_ptr->signature.data2 =
+ static_cast<uint16_t>(identifier[4] << 8) | identifier[5];
+ cv_ptr->signature.data3 =
+ static_cast<uint16_t>(identifier[6] << 8) | identifier[7];
+ cv_ptr->signature.data4[0] = identifier[8];
+ cv_ptr->signature.data4[1] = identifier[9];
+ cv_ptr->signature.data4[2] = identifier[10];
+ cv_ptr->signature.data4[3] = identifier[11];
+ cv_ptr->signature.data4[4] = identifier[12];
+ cv_ptr->signature.data4[5] = identifier[13];
+ cv_ptr->signature.data4[6] = identifier[14];
+ cv_ptr->signature.data4[7] = identifier[15];
+ }
+
+ return true;
+}
+
+bool MinidumpGenerator::WriteModuleListStream(
+ MDRawDirectory *module_list_stream) {
+ TypedMDRVA<MDRawModuleList> list(&writer_);
+
+ uint32_t image_count = dynamic_images_ ?
+ dynamic_images_->GetImageCount() :
+ _dyld_image_count();
+
+ // module_count is one higher when we're in the crashed process, to make
+ // room for dyld, which isn't in the standard list of modules. If
+ // dynamic_images_ exists (and we're in a different process than the
+ // crashed process), we've already added dyld to it.
+ uint32_t module_count = dynamic_images_ ? image_count : image_count + 1;
+
+ if (!list.AllocateObjectAndArray(module_count, MD_MODULE_SIZE))
+ return false;
+
+ module_list_stream->stream_type = MD_MODULE_LIST_STREAM;
+ module_list_stream->location = list.location();
+ list.get()->number_of_modules = static_cast<uint32_t>(module_count);
+
+ // Write out the executable module as the first one
+ MDRawModule module;
+ uint32_t executableIndex = FindExecutableModule();
+
+ if (!WriteModuleStream(static_cast<unsigned>(executableIndex), &module)) {
+ return false;
+ }
+
+ list.CopyIndexAfterObject(0, &module, MD_MODULE_SIZE);
+ int destinationIndex = 1; // Write all other modules after this one
+
+ if (!dynamic_images_) {
+ // If we're in the crashed process we need to write dyld explicitly,
+ // since it's not included in the standard list. index == INT_MAX signals
+ // our intentions to WriteModuleStream().
+ if (!WriteModuleStream(INT_MAX, &module)) {
+ return false;
+ }
+
+ list.CopyIndexAfterObject(destinationIndex++, &module, MD_MODULE_SIZE);
+ }
+
+ for (uint32_t i = 0; i < image_count; ++i) {
+ if (i != executableIndex) {
+ if (!WriteModuleStream(static_cast<unsigned>(i), &module)) {
+ return false;
+ }
+
+ list.CopyIndexAfterObject(destinationIndex++, &module, MD_MODULE_SIZE);
+ }
+ }
+
+ return true;
+}
+
+bool MinidumpGenerator::WriteMiscInfoStream(MDRawDirectory *misc_info_stream) {
+ TypedMDRVA<MDRawMiscInfo> info(&writer_);
+
+ if (!info.Allocate())
+ return false;
+
+ misc_info_stream->stream_type = MD_MISC_INFO_STREAM;
+ misc_info_stream->location = info.location();
+
+ MDRawMiscInfo *info_ptr = info.get();
+ info_ptr->size_of_info = static_cast<uint32_t>(sizeof(MDRawMiscInfo));
+ info_ptr->flags1 = MD_MISCINFO_FLAGS1_PROCESS_ID |
+ MD_MISCINFO_FLAGS1_PROCESS_TIMES |
+ MD_MISCINFO_FLAGS1_PROCESSOR_POWER_INFO;
+
+ // Process ID
+ info_ptr->process_id = getpid();
+
+ // Times
+ struct rusage usage;
+ if (getrusage(RUSAGE_SELF, &usage) != -1) {
+ // Omit the fractional time since the MDRawMiscInfo only wants seconds
+ info_ptr->process_user_time =
+ static_cast<uint32_t>(usage.ru_utime.tv_sec);
+ info_ptr->process_kernel_time =
+ static_cast<uint32_t>(usage.ru_stime.tv_sec);
+ }
+ int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PID,
+ static_cast<int>(info_ptr->process_id) };
+ uint mibsize = static_cast<uint>(sizeof(mib) / sizeof(mib[0]));
+ struct kinfo_proc proc;
+ size_t size = sizeof(proc);
+ if (sysctl(mib, mibsize, &proc, &size, NULL, 0) == 0) {
+ info_ptr->process_create_time =
+ static_cast<uint32_t>(proc.kp_proc.p_starttime.tv_sec);
+ }
+
+ // Speed
+ uint64_t speed;
+ const uint64_t kOneMillion = 1000 * 1000;
+ size = sizeof(speed);
+ sysctlbyname("hw.cpufrequency_max", &speed, &size, NULL, 0);
+ info_ptr->processor_max_mhz = static_cast<uint32_t>(speed / kOneMillion);
+ info_ptr->processor_mhz_limit = static_cast<uint32_t>(speed / kOneMillion);
+ size = sizeof(speed);
+ sysctlbyname("hw.cpufrequency", &speed, &size, NULL, 0);
+ info_ptr->processor_current_mhz = static_cast<uint32_t>(speed / kOneMillion);
+
+ return true;
+}
+
+bool MinidumpGenerator::WriteBreakpadInfoStream(
+ MDRawDirectory *breakpad_info_stream) {
+ TypedMDRVA<MDRawBreakpadInfo> info(&writer_);
+
+ if (!info.Allocate())
+ return false;
+
+ breakpad_info_stream->stream_type = MD_BREAKPAD_INFO_STREAM;
+ breakpad_info_stream->location = info.location();
+ MDRawBreakpadInfo *info_ptr = info.get();
+
+ if (exception_thread_ && exception_type_) {
+ info_ptr->validity = MD_BREAKPAD_INFO_VALID_DUMP_THREAD_ID |
+ MD_BREAKPAD_INFO_VALID_REQUESTING_THREAD_ID;
+ info_ptr->dump_thread_id = handler_thread_;
+ info_ptr->requesting_thread_id = exception_thread_;
+ } else {
+ info_ptr->validity = MD_BREAKPAD_INFO_VALID_DUMP_THREAD_ID;
+ info_ptr->dump_thread_id = handler_thread_;
+ info_ptr->requesting_thread_id = 0;
+ }
+
+ return true;
+}
+
+bool MinidumpGenerator::WriteCrashInfoRecord(MDLocationDescriptor *location,
+ const char *module_path,
+ const char *crash_info,
+ unsigned long crash_info_size,
+ bool out_of_process,
+ bool dyld_or_in_dyld_shared_cache) {
+ TypedMDRVA<MDRawMacCrashInfoRecord> info(&writer_);
+
+ // Only write crash info records for modules that actually have
+ // __DATA,__crash_info sections.
+ if (!crash_info || !crash_info_size) {
+ return false;
+ }
+ // We generally don't have access to modules in another process's memory
+ // space if the module isn't dyld and isn't in the dyld shared cache.
+ if (out_of_process && !dyld_or_in_dyld_shared_cache) {
+ return false;
+ }
+
+ // If 'crash_info_size' is larger than we expect, 'crash_info' probably
+ // contains fields we don't recognize (added by Apple since we last updated
+ // this code). In that case only copy the fields we do recognize. If it's
+ // smaller than we expect, we're probably running on an older version of
+ // macOS, whose __crash_info sections don't contain all the fields we
+ // recognize. In that case make sure the "missing" fields are zeroed in
+ // 'raw_crash_info'.
+ crashreporter_annotations_t raw_crash_info;
+ bzero(&raw_crash_info, sizeof(raw_crash_info));
+ if (crash_info_size > sizeof(raw_crash_info)) {
+ crash_info_size = sizeof(raw_crash_info);
+ }
+ memcpy(&raw_crash_info, crash_info, crash_info_size);
+
+ // Don't write crash info records that are empty of useful data (see
+ // definition of crashreporter_annotations_t in mach_vm_compat.h).
+ bool is_empty = true;
+ if (raw_crash_info.message ||
+ raw_crash_info.signature_string ||
+ raw_crash_info.backtrace ||
+ raw_crash_info.message2 ||
+ raw_crash_info.thread ||
+ raw_crash_info.dialog_mode ||
+ ((raw_crash_info.version > 4) && raw_crash_info.abort_cause)) {
+ is_empty = false;
+ }
+ if (is_empty) {
+ return false;
+ }
+
+ string message;
+ string signature_string;
+ string backtrace;
+ string message2;
+
+ const char *message_ptr = NULL;
+ const char *signature_string_ptr = NULL;
+ const char *backtrace_ptr = NULL;
+ const char *message2_ptr = NULL;
+
+ if (out_of_process) {
+ if (raw_crash_info.message) {
+ message = ReadTaskString(crashing_task_, raw_crash_info.message);
+ message_ptr = message.c_str();
+ }
+ if (raw_crash_info.signature_string) {
+ signature_string =
+ ReadTaskString(crashing_task_, raw_crash_info.signature_string);
+ signature_string_ptr = signature_string.c_str();
+ }
+ if (raw_crash_info.backtrace) {
+ backtrace = ReadTaskString(crashing_task_, raw_crash_info.backtrace);
+ backtrace_ptr = backtrace.c_str();
+ }
+ if (raw_crash_info.message2) {
+ message2 = ReadTaskString(crashing_task_, raw_crash_info.message2);
+ message2_ptr = message2.c_str();
+ }
+ } else {
+ message_ptr = reinterpret_cast<const char *>(raw_crash_info.message);
+ signature_string_ptr =
+ reinterpret_cast<const char *>(raw_crash_info.signature_string);
+ backtrace_ptr = reinterpret_cast<const char *>(raw_crash_info.backtrace);
+ message2_ptr = reinterpret_cast<const char *>(raw_crash_info.message2);
+ }
+
+ const char* data_strings[] = { module_path, message_ptr,
+ signature_string_ptr, backtrace_ptr,
+ message2_ptr };
+
+ // Compute the total size of the strings we'll be copying to
+ // (MDRawMacCrashInfoRecord).data, including their terminal nulls.
+ size_t data_size = 0;
+ for (auto src : data_strings) {
+ if (!src) {
+ src = "";
+ }
+ // Always include the terminal null, even for an empty string.
+ size_t copy_length = strlen(src) + 1;
+ // A "string" that's too large is a sign of data corruption.
+ if (copy_length > MACCRASHINFO_STRING_MAXSIZE) {
+ return false;
+ }
+ data_size += copy_length;
+ }
+
+ if (!info.AllocateObjectAndArray(data_size, sizeof(uint8_t)))
+ return false;
+
+ // Now copy 'module_path' and the __crash_info strings in order to
+ // (MDRawMacCrashInfoRecord).data, including their terminal nulls.
+ size_t offset = 0;
+ for (auto src : data_strings) {
+ if (!src) {
+ src = "";
+ }
+ // Always include the terminal null, even for an empty string.
+ size_t copy_length = strlen(src) + 1;
+ // We can't use CopyIndexAfterObject() here. Calling that method multiple
+ // times only works for objects in an array (which are all the same size).
+ if (!info.Copy(info.position() + sizeof(MDRawMacCrashInfoRecord) + offset,
+ src, copy_length)) {
+ return false;
+ }
+ offset += copy_length;
+ }
+
+ *location = info.location();
+ MDRawMacCrashInfoRecord *info_ptr = info.get();
+ info_ptr->stream_type = MOZ_MACOS_CRASH_INFO_STREAM;
+ info_ptr->version = raw_crash_info.version;
+ info_ptr->thread = raw_crash_info.thread;
+ info_ptr->dialog_mode = raw_crash_info.dialog_mode;
+ info_ptr->abort_cause = raw_crash_info.abort_cause;
+
+ return true;
+}
+
+bool MinidumpGenerator::WriteCrashInfoStream(
+ MDRawDirectory *crash_info_stream) {
+ TypedMDRVA<MDRawMacCrashInfo> list(&writer_);
+
+ if (!list.Allocate())
+ return false;
+
+ crash_info_stream->stream_type = MOZ_MACOS_CRASH_INFO_STREAM;
+ crash_info_stream->location = list.location();
+
+ MDRawMacCrashInfo *list_ptr = list.get();
+ bzero(list_ptr, sizeof(MDRawMacCrashInfo));
+ list_ptr->stream_type = MOZ_MACOS_CRASH_INFO_STREAM;
+ list_ptr->record_start_size = sizeof(MDRawMacCrashInfoRecord);
+
+ uint32_t image_count = dynamic_images_ ?
+ dynamic_images_->GetImageCount() :
+ // Leave room for dyld, which isn't among the images
+ // counted by _dyld_image_count().
+ _dyld_image_count() + 1;
+ uint32_t crash_info_count = 0;
+ for (uint32_t i = 0; (i < image_count) &&
+ (crash_info_count < MAC_CRASH_INFOS_MAX); ++i) {
+ if (dynamic_images_) {
+ // We're in a different process than the crashed process
+ DynamicImage *image = dynamic_images_->GetImage(i);
+ if (!image) {
+ continue;
+ }
+
+ MDLocationDescriptor location;
+ string module_path = image->GetFilePath();
+ // WriteCrashInfoRecord() fails if a module doesn't contain a
+ // __DATA,__crash_info section, or if it's empty of useful data.
+ if (WriteCrashInfoRecord(&location,
+ module_path.c_str(),
+ reinterpret_cast<const char *>
+ (image->GetCrashInfo()),
+ image->GetCrashInfoSize(),
+ /* out_of_process */ true,
+ image->GetInDyldSharedCache() ||
+ image->GetIsDyld())) {
+ list_ptr->records[crash_info_count] = location;
+ ++crash_info_count;
+ }
+ } else {
+ // Getting crash info in the crashed process
+ const breakpad_mach_header *header;
+ // dyld isn't in our list of images, so tack it onto the end.
+ if (i == image_count - 1) {
+ header = dyldImageLoadAddress_;
+ } else {
+ header = (breakpad_mach_header*) _dyld_get_image_header(i);
+ }
+ if (!header || (header->magic != MH_MAGIC_ARCH)) {
+ continue;
+ }
+
+ unsigned long slide;
+ const char *module_path;
+ bool dyld_or_in_dyld_shared_cache;
+ if (i == image_count - 1) {
+ slide = dyldSlide_;
+ module_path = dyldPath_.c_str();
+ dyld_or_in_dyld_shared_cache = true;
+ } else {
+ slide = _dyld_get_image_vmaddr_slide(i);
+ module_path = _dyld_get_image_name(i);
+ dyld_or_in_dyld_shared_cache =
+ ((header->flags & MH_SHAREDCACHE) != 0);
+ }
+
+ getsectdata_size_type crash_info_size = 0;
+ const char *crash_info =
+ getsectdatafromheader_func(header, "__DATA", "__crash_info",
+ &crash_info_size);
+ // __crash_info might be in the __DATA_DIRTY segment.
+ if (!crash_info) {
+ crash_info =
+ getsectdatafromheader_func(header, "__DATA_DIRTY", "__crash_info",
+ &crash_info_size);
+ }
+ if (crash_info) {
+ crash_info += slide;
+ }
+ MDLocationDescriptor location;
+ // WriteCrashInfoRecord() fails if a module doesn't contain a
+ // __DATA,__crash_info section, or if it's empty of useful data.
+ if (WriteCrashInfoRecord(&location, module_path, crash_info,
+ crash_info_size, /* out_of_process */ false,
+ dyld_or_in_dyld_shared_cache)) {
+ list_ptr->records[crash_info_count] = location;
+ ++crash_info_count;
+ }
+ }
+ }
+
+ list_ptr->record_count = crash_info_count;
+
+ return true;
+}
+
+bool MinidumpGenerator::WriteBootargsStream(
+ MDRawDirectory *bootargs_stream) {
+ TypedMDRVA<MDRawMacBootargs> info(&writer_);
+ if (!info.Allocate())
+ return false;
+
+ bootargs_stream->stream_type = MOZ_MACOS_BOOTARGS_STREAM;
+ bootargs_stream->location = info.location();
+
+ // We need to write *something* to the stream -- otherwise it will get
+ // corrupted. So if we fail to get kern.bootargs, or if it's empty, write
+ // an empty string -- a single terminal null.
+ size_t size = 0; // Includes terminal null
+ int rv = sysctlbyname("kern.bootargs", NULL, &size, NULL, 0);
+ if ((rv != 0) || (size == 0))
+ size = 1;
+ vector<uint8_t> bootargs(size);
+ bootargs[0] = 0;
+ if (rv == 0)
+ sysctlbyname("kern.bootargs", &bootargs[0], &size, NULL, 0);
+
+ MDLocationDescriptor bootargs_location;
+ const char *bootargs_ptr = reinterpret_cast<const char *>(&bootargs[0]);
+ if (!writer_.WriteString(bootargs_ptr, 0, &bootargs_location))
+ return false;
+
+ MDRawMacBootargs *info_ptr = info.get();
+ info_ptr->stream_type = MOZ_MACOS_BOOTARGS_STREAM;
+ info_ptr->bootargs = bootargs_location.rva;
+
+ return true;
+}
+
+bool MinidumpGenerator::WriteThreadName(
+ mach_port_t thread_id,
+ MDRawThreadName *thread_name) {
+ MDLocationDescriptor string_location;
+
+ thread_extended_info_data_t thread_extended_info;
+ mach_msg_type_number_t thread_extended_info_count =
+ THREAD_EXTENDED_INFO_COUNT;
+ kern_return_t res = thread_info(thread_id, THREAD_EXTENDED_INFO,
+ (thread_info_t)&thread_extended_info,
+ &thread_extended_info_count);
+
+ if (res != KERN_SUCCESS)
+ return false;
+
+ if (!writer_.WriteString(thread_extended_info.pth_name, 0, &string_location))
+ return false;
+
+ thread_name->thread_id = thread_id;
+ thread_name->rva_of_thread_name = string_location.rva;
+ return true;
+}
+
+bool MinidumpGenerator::WriteThreadNamesStream(
+ MDRawDirectory *thread_names_stream) {
+ TypedMDRVA<MDRawThreadNamesList> list(&writer_);
+ thread_act_port_array_t threads_for_task;
+ mach_msg_type_number_t thread_count;
+
+ if (task_threads(crashing_task_, &threads_for_task, &thread_count))
+ return false;
+
+ int non_generator_thread_count;
+
+ // Don't include the generator thread
+ if (handler_thread_ != MACH_PORT_NULL)
+ non_generator_thread_count = thread_count - 1;
+ else
+ non_generator_thread_count = thread_count;
+
+ if (!list.AllocateObjectAndArray(non_generator_thread_count,
+ sizeof(MDRawThreadName))) {
+ return false;
+ }
+
+ thread_names_stream->stream_type = MD_THREAD_NAMES_STREAM;
+ thread_names_stream->location = list.location();
+
+ list.get()->number_of_thread_names = non_generator_thread_count;
+
+ MDRawThreadName thread_name;
+ int thread_idx = 0;
+
+ for (unsigned int i = 0; i < thread_count; ++i) {
+ memset(&thread_name, 0, sizeof(MDRawThreadName));
+
+ if (threads_for_task[i] != handler_thread_) {
+ if (WriteThreadName(threads_for_task[i], &thread_name)) {
+ list.CopyIndexAfterObject(thread_idx++, &thread_name,
+ sizeof(MDRawThreadName));
+ }
+ }
+ }
+
+ return true;
+}
+
+} // namespace google_breakpad
diff --git a/toolkit/crashreporter/breakpad-client/mac/handler/minidump_generator.h b/toolkit/crashreporter/breakpad-client/mac/handler/minidump_generator.h
new file mode 100644
index 0000000000..aba067cc04
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/mac/handler/minidump_generator.h
@@ -0,0 +1,290 @@
+// Copyright (c) 2006, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// minidump_generator.h: Create a minidump of the current MacOS process.
+
+#ifndef CLIENT_MAC_GENERATOR_MINIDUMP_GENERATOR_H__
+#define CLIENT_MAC_GENERATOR_MINIDUMP_GENERATOR_H__
+
+#include <mach/mach.h>
+#include <TargetConditionals.h>
+
+#include <string>
+
+#include "mac/handler/ucontext_compat.h"
+#include "minidump_file_writer.h"
+#include "common/memory_allocator.h"
+#include "common/mac/macho_utilities.h"
+#include "google_breakpad/common/minidump_format.h"
+
+#include "dynamic_images.h"
+#include "mach_vm_compat.h"
+
+#if defined(__arm__)
+#define HAS_ARM_SUPPORT
+#elif defined(__aarch64__)
+#define HAS_ARM64_SUPPORT
+#elif defined(__i386__) || defined(__x86_64__)
+ #define HAS_X86_SUPPORT
+#endif
+
+namespace google_breakpad {
+
+using std::string;
+
+// Use the REGISTER_FROM_THREADSTATE to access a register name from the
+// breakpad_thread_state_t structure.
+#if __DARWIN_OPAQUE_ARM_THREAD_STATE64
+#define ARRAY_REGISTER_FROM_THREADSTATE(a, b, i) ((a)->__##b[i])
+#define GET_REGISTER_FROM_THREADSTATE_fp(a) \
+ (reinterpret_cast<uintptr_t>((a)->__opaque_fp))
+#define GET_REGISTER_FROM_THREADSTATE_lr(a) \
+ (reinterpret_cast<uintptr_t>((a)->__opaque_lr))
+#define GET_REGISTER_FROM_THREADSTATE_sp(a) \
+ (reinterpret_cast<uintptr_t>((a)->__opaque_sp))
+#define GET_REGISTER_FROM_THREADSTATE_pc(a) \
+ (reinterpret_cast<uintptr_t>((a)->__opaque_pc))
+#define GET_REGISTER_FROM_THREADSTATE_cpsr(a) ((a)->__cpsr)
+#define GET_REGISTER_FROM_THREADSTATE_flags(a) ((a)->__opaque_flags)
+#define REGISTER_FROM_THREADSTATE(a, b) (GET_REGISTER_FROM_THREADSTATE_##b(a))
+#elif __DARWIN_UNIX03 || TARGET_CPU_X86_64 || TARGET_CPU_PPC64 || TARGET_CPU_ARM
+// In The 10.5 SDK Headers Apple prepended __ to the variable names in the
+// i386_thread_state_t structure. There's no good way to tell what version of
+// the SDK we're compiling against so we just toggle on the same preprocessor
+// symbol Apple's headers use.
+#define REGISTER_FROM_THREADSTATE(a, b) ((a)->__ ## b)
+#define ARRAY_REGISTER_FROM_THREADSTATE(a, b, i) \
+ REGISTER_FROM_THREADSTATE(a, b[i])
+#else
+#define REGISTER_FROM_THREADSTATE(a, b) (a->b)
+#define ARRAY_REGISTER_FROM_THREADSTATE(a, b, i) \
+ REGISTER_FROM_THREADSTATE(a, b[i])
+#endif
+
+// These typedefs only apply to the current process, whether or not it's the
+// one that crashed.
+#ifdef __LP64__
+typedef dyld_all_image_infos64 dyld_all_image_infos_self;
+#else
+typedef dyld_all_image_infos32 dyld_all_image_infos_self;
+#endif
+
+// Creates a minidump file of the current process. If there is exception data,
+// use SetExceptionInformation() to add this to the minidump. The minidump
+// file is generated by the Write() function.
+// Usage:
+// MinidumpGenerator minidump();
+// minidump.Write("/tmp/minidump");
+//
+class MinidumpGenerator {
+ public:
+ MinidumpGenerator();
+ MinidumpGenerator(mach_port_t crashing_task, mach_port_t handler_thread);
+
+ virtual ~MinidumpGenerator();
+
+ // Return <dir>/<unique_name>.dmp
+ // Sets |unique_name| (if requested) to the unique name for the minidump
+ static string UniqueNameInDirectory(const string &dir, string *unique_name);
+
+ // Write out the minidump into |path|
+ // All of the components of |path| must exist and be writable
+ // Return true if successful, false otherwise
+ bool Write(const char *path);
+
+ // Specify some exception information, if applicable
+ void SetExceptionInformation(int type, int64_t code, int64_t subcode,
+ mach_port_t thread_name) {
+ exception_type_ = type;
+ exception_code_ = code;
+ exception_subcode_ = subcode;
+ exception_thread_ = thread_name;
+ }
+
+ // Specify the task context. If |task_context| is not NULL, it will be used
+ // to retrieve the context of the current thread, instead of using
+ // |thread_get_state|.
+ void SetTaskContext(breakpad_ucontext_t *task_context);
+
+ // Gather system information. This should be call at least once before using
+ // the MinidumpGenerator class.
+ static void GatherSystemInformation();
+
+ // Get the slide for a module in the current process.
+ static uint64_t GetCurrentProcessModuleSlide(breakpad_mach_header* mh,
+ uint64_t shared_cache_slide);
+
+ // Gather information about the dyld module in the current process. This
+ // information is only relevant if the current process is also the crashing
+ // process.
+ void GatherCurrentProcessDyldInformation();
+
+ protected:
+ // Overridable Stream writers
+ virtual bool WriteExceptionStream(MDRawDirectory *exception_stream);
+
+ // Overridable Helper
+ virtual bool WriteThreadStream(mach_port_t thread_id, MDRawThread *thread);
+
+ private:
+ typedef bool (MinidumpGenerator::*WriteStreamFN)(MDRawDirectory *);
+
+ // Stream writers
+ bool WriteThreadListStream(MDRawDirectory *thread_list_stream);
+ bool WriteMemoryListStream(MDRawDirectory *memory_list_stream);
+ bool WriteSystemInfoStream(MDRawDirectory *system_info_stream);
+ bool WriteModuleListStream(MDRawDirectory *module_list_stream);
+ bool WriteMiscInfoStream(MDRawDirectory *misc_info_stream);
+ bool WriteBreakpadInfoStream(MDRawDirectory *breakpad_info_stream);
+ bool WriteCrashInfoStream(MDRawDirectory *crash_info_stream);
+ bool WriteBootargsStream(MDRawDirectory *bootargs_stream);
+ bool WriteThreadNamesStream(MDRawDirectory *thread_names_stream);
+
+ // Helpers
+ uint64_t CurrentPCForStack(breakpad_thread_state_data_t state);
+ bool GetThreadState(thread_act_t target_thread, thread_state_t state,
+ mach_msg_type_number_t *count);
+ bool WriteStackFromStartAddress(mach_vm_address_t start_addr,
+ MDMemoryDescriptor *stack_location);
+ bool WriteStack(breakpad_thread_state_data_t state,
+ MDMemoryDescriptor *stack_location);
+ bool WriteContext(breakpad_thread_state_data_t state,
+ MDLocationDescriptor *register_location);
+ bool WriteCVRecord(MDRawModule *module, int cpu_type, int cpu_subtype,
+ const char *module_path, bool in_memory,
+ bool out_of_process, bool dyld_or_in_dyld_shared_cache);
+ bool WriteModuleStream(unsigned int index, MDRawModule *module);
+ bool WriteCrashInfoRecord(MDLocationDescriptor *location,
+ const char *module_path,
+ const char *crash_info,
+ unsigned long crash_info_size,
+ bool out_of_process,
+ bool dyld_or_in_dyld_shared_cache);
+ bool WriteThreadName(mach_port_t thread_id,
+ MDRawThreadName *thread_name);
+ size_t CalculateStackSize(mach_vm_address_t start_addr);
+ int FindExecutableModule();
+ bool IsValidExcCrash(uint64_t exception_code);
+ void RecoverExceptionDataFromExcCrash(uint64_t exception_code,
+ int& signal_number);
+
+ // Per-CPU implementations of these methods
+#ifdef HAS_ARM_SUPPORT
+ bool WriteStackARM(breakpad_thread_state_data_t state,
+ MDMemoryDescriptor *stack_location);
+ bool WriteContextARM(breakpad_thread_state_data_t state,
+ MDLocationDescriptor *register_location);
+ uint64_t CurrentPCForStackARM(breakpad_thread_state_data_t state);
+#endif
+#ifdef HAS_ARM64_SUPPORT
+ bool WriteStackARM64(breakpad_thread_state_data_t state,
+ MDMemoryDescriptor *stack_location);
+ bool WriteContextARM64(breakpad_thread_state_data_t state,
+ MDLocationDescriptor *register_location);
+ uint64_t CurrentPCForStackARM64(breakpad_thread_state_data_t state);
+#endif
+#ifdef HAS_PPC_SUPPORT
+ bool WriteStackPPC(breakpad_thread_state_data_t state,
+ MDMemoryDescriptor *stack_location);
+ bool WriteContextPPC(breakpad_thread_state_data_t state,
+ MDLocationDescriptor *register_location);
+ uint64_t CurrentPCForStackPPC(breakpad_thread_state_data_t state);
+ bool WriteStackPPC64(breakpad_thread_state_data_t state,
+ MDMemoryDescriptor *stack_location);
+ bool WriteContextPPC64(breakpad_thread_state_data_t state,
+ MDLocationDescriptor *register_location);
+ uint64_t CurrentPCForStackPPC64(breakpad_thread_state_data_t state);
+#endif
+#ifdef HAS_X86_SUPPORT
+ bool WriteStackX86(breakpad_thread_state_data_t state,
+ MDMemoryDescriptor *stack_location);
+ bool WriteContextX86(breakpad_thread_state_data_t state,
+ MDLocationDescriptor *register_location);
+ uint64_t CurrentPCForStackX86(breakpad_thread_state_data_t state);
+ bool WriteStackX86_64(breakpad_thread_state_data_t state,
+ MDMemoryDescriptor *stack_location);
+ bool WriteContextX86_64(breakpad_thread_state_data_t state,
+ MDLocationDescriptor *register_location);
+ uint64_t CurrentPCForStackX86_64(breakpad_thread_state_data_t state);
+#endif
+
+ // disallow copy ctor and operator=
+ explicit MinidumpGenerator(const MinidumpGenerator &);
+ void operator=(const MinidumpGenerator &);
+
+ protected:
+ // Use this writer to put the data to disk
+ MinidumpFileWriter writer_;
+
+ private:
+ // Exception information
+ int exception_type_;
+ int64_t exception_code_;
+ int64_t exception_subcode_;
+ mach_port_t exception_thread_;
+ mach_port_t crashing_task_;
+ mach_port_t handler_thread_;
+
+ // CPU type of the task being dumped.
+ cpu_type_t cpu_type_;
+
+ // System information
+ static char build_string_[16];
+ static int os_major_version_;
+ static int os_minor_version_;
+ static int os_build_number_;
+
+ // Current process dyld information. It only applies to the crashed process
+ // if the current process is the one that crashed. It doesn't apply to the
+ // crashed process if the current process is the crash server and some other
+ // process has crashed.
+ breakpad_mach_header* dyldImageLoadAddress_;
+ ptrdiff_t dyldSlide_;
+ string dyldPath_;
+
+ // Context of the task to dump.
+ breakpad_ucontext_t *task_context_;
+
+ // Information about dynamically loaded code
+ DynamicImages *dynamic_images_;
+
+ // PageAllocator makes it possible to allocate memory
+ // directly from the system, even while handling an exception.
+ mutable PageAllocator allocator_;
+
+ protected:
+ // Blocks of memory written to the dump. These are all currently
+ // written while writing the thread list stream, but saved here
+ // so a memory list stream can be written afterwards.
+ wasteful_vector<MDMemoryDescriptor> memory_blocks_;
+};
+
+} // namespace google_breakpad
+
+#endif // CLIENT_MAC_GENERATOR_MINIDUMP_GENERATOR_H__
diff --git a/toolkit/crashreporter/breakpad-client/mac/handler/minidump_test.xcodeproj/project.pbxproj b/toolkit/crashreporter/breakpad-client/mac/handler/minidump_test.xcodeproj/project.pbxproj
new file mode 100644
index 0000000000..1924ac4d58
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/mac/handler/minidump_test.xcodeproj/project.pbxproj
@@ -0,0 +1,843 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 46;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ 8BFC813F11FF9A58002CB4DC /* libcrypto.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 8BFC813E11FF9A58002CB4DC /* libcrypto.dylib */; };
+ 8BFC814411FF9A9C002CB4DC /* libcrypto.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 8BFC813E11FF9A58002CB4DC /* libcrypto.dylib */; };
+ 8BFC814511FF9A9D002CB4DC /* libcrypto.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 8BFC813E11FF9A58002CB4DC /* libcrypto.dylib */; };
+ 8BFC814811FF9B13002CB4DC /* libcrypto.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 8BFC813E11FF9A58002CB4DC /* libcrypto.dylib */; };
+ 8BFC814911FF9B13002CB4DC /* libcrypto.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 8BFC813E11FF9A58002CB4DC /* libcrypto.dylib */; };
+ 8BFC814A11FF9B13002CB4DC /* libcrypto.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 8BFC813E11FF9A58002CB4DC /* libcrypto.dylib */; };
+ 8BFC814B11FF9B3F002CB4DC /* SenTestingKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F9721FA10E8B0E2300D7E813 /* SenTestingKit.framework */; };
+ 8BFC814C11FF9B3F002CB4DC /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F9721F6B0E8B0D7000D7E813 /* Cocoa.framework */; };
+ 8BFC81A211FF9C2E002CB4DC /* CPlusTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8BFC819211FF9C23002CB4DC /* CPlusTest.framework */; };
+ 8BFC81A311FF9C2F002CB4DC /* CPlusTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8BFC819211FF9C23002CB4DC /* CPlusTest.framework */; };
+ 8BFC81AD11FF9C8A002CB4DC /* breakpad_nlist_64.cc in Sources */ = {isa = PBXBuildFile; fileRef = F98208A10DB32CAE0017AECA /* breakpad_nlist_64.cc */; };
+ 8BFC81AE11FF9C8C002CB4DC /* breakpad_nlist_64.cc in Sources */ = {isa = PBXBuildFile; fileRef = F98208A10DB32CAE0017AECA /* breakpad_nlist_64.cc */; };
+ 8BFC81AF11FF9C8C002CB4DC /* breakpad_nlist_64.cc in Sources */ = {isa = PBXBuildFile; fileRef = F98208A10DB32CAE0017AECA /* breakpad_nlist_64.cc */; };
+ 8BFC81B011FF9C8D002CB4DC /* breakpad_nlist_64.cc in Sources */ = {isa = PBXBuildFile; fileRef = F98208A10DB32CAE0017AECA /* breakpad_nlist_64.cc */; };
+ 9B35FF5A0B267D5F008DE8C7 /* convert_UTF.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9B35FF560B267D5F008DE8C7 /* convert_UTF.cc */; };
+ 9B35FF5B0B267D5F008DE8C7 /* string_conversion.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9B35FF580B267D5F008DE8C7 /* string_conversion.cc */; };
+ 9B37CEEC0AF98ECD00FA4BD4 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9B37CEEB0AF98ECD00FA4BD4 /* CoreFoundation.framework */; };
+ 9B7CA7700B12873A00CD3A1D /* minidump_file_writer-inl.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 9BE3C01E0B0CE329009892DF /* minidump_file_writer-inl.h */; };
+ 9B7CA8540B12989000CD3A1D /* minidump_file_writer_unittest.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9B7CA8530B12989000CD3A1D /* minidump_file_writer_unittest.cc */; };
+ 9B7CA8550B1298A100CD3A1D /* minidump_file_writer.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9BD82C230B01344C0055103E /* minidump_file_writer.cc */; };
+ 9BC1D2940B336F2300F2A2B4 /* convert_UTF.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9B35FF560B267D5F008DE8C7 /* convert_UTF.cc */; };
+ 9BC1D2950B336F2500F2A2B4 /* string_conversion.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9B35FF580B267D5F008DE8C7 /* string_conversion.cc */; };
+ 9BD82AC10B0029DF0055103E /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9B37CEEB0AF98ECD00FA4BD4 /* CoreFoundation.framework */; };
+ 9BD82BFF0B01333D0055103E /* exception_handler_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9BD82BFD0B01333D0055103E /* exception_handler_test.cc */; };
+ 9BD82C020B01333D0055103E /* minidump_generator_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9BD82BFE0B01333D0055103E /* minidump_generator_test.cc */; };
+ 9BD82C0D0B0133520055103E /* exception_handler.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9BD82C090B0133520055103E /* exception_handler.cc */; };
+ 9BD82C0E0B0133520055103E /* minidump_generator.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9BD82C0B0B0133520055103E /* minidump_generator.cc */; };
+ 9BD82C0F0B0133520055103E /* exception_handler.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9BD82C090B0133520055103E /* exception_handler.cc */; };
+ 9BD82C100B0133520055103E /* exception_handler.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 9BD82C0A0B0133520055103E /* exception_handler.h */; };
+ 9BD82C110B0133520055103E /* minidump_generator.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9BD82C0B0B0133520055103E /* minidump_generator.cc */; };
+ 9BD82C120B0133520055103E /* minidump_generator.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 9BD82C0C0B0133520055103E /* minidump_generator.h */; };
+ 9BD82C250B01344C0055103E /* minidump_file_writer.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9BD82C230B01344C0055103E /* minidump_file_writer.cc */; };
+ 9BD82C260B01344C0055103E /* minidump_file_writer.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9BD82C230B01344C0055103E /* minidump_file_writer.cc */; };
+ 9BD82C270B01344C0055103E /* minidump_file_writer.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 9BD82C240B01344C0055103E /* minidump_file_writer.h */; };
+ 9BD82C2D0B01345E0055103E /* string_utilities.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9BD82C2B0B01345E0055103E /* string_utilities.cc */; };
+ 9BD82C2E0B01345E0055103E /* string_utilities.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9BD82C2B0B01345E0055103E /* string_utilities.cc */; };
+ 9BD82C2F0B01345E0055103E /* string_utilities.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 9BD82C2C0B01345E0055103E /* string_utilities.h */; };
+ D2F651000BEF947200920385 /* file_id.cc in Sources */ = {isa = PBXBuildFile; fileRef = D2F650FA0BEF947200920385 /* file_id.cc */; };
+ D2F651010BEF947200920385 /* file_id.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D2F650FB0BEF947200920385 /* file_id.h */; };
+ D2F651020BEF947200920385 /* macho_id.cc in Sources */ = {isa = PBXBuildFile; fileRef = D2F650FC0BEF947200920385 /* macho_id.cc */; };
+ D2F651030BEF947200920385 /* macho_id.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D2F650FD0BEF947200920385 /* macho_id.h */; };
+ D2F651040BEF947200920385 /* macho_utilities.cc in Sources */ = {isa = PBXBuildFile; fileRef = D2F650FE0BEF947200920385 /* macho_utilities.cc */; };
+ D2F651050BEF947200920385 /* macho_utilities.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D2F650FF0BEF947200920385 /* macho_utilities.h */; };
+ D2F651090BEF949A00920385 /* dynamic_images.cc in Sources */ = {isa = PBXBuildFile; fileRef = D2F651070BEF949A00920385 /* dynamic_images.cc */; };
+ D2F6510A0BEF949A00920385 /* dynamic_images.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D2F651080BEF949A00920385 /* dynamic_images.h */; };
+ D2F6510E0BEF94EB00920385 /* macho_walker.cc in Sources */ = {isa = PBXBuildFile; fileRef = D2F6510C0BEF94EB00920385 /* macho_walker.cc */; };
+ D2F6510F0BEF94EB00920385 /* macho_walker.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D2F6510D0BEF94EB00920385 /* macho_walker.h */; };
+ D2F651110BEF951700920385 /* string_conversion.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9B35FF580B267D5F008DE8C7 /* string_conversion.cc */; };
+ D2F651130BEF951C00920385 /* string_conversion.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 9B35FF590B267D5F008DE8C7 /* string_conversion.h */; };
+ D2F651150BEF953000920385 /* convert_UTF.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9B35FF560B267D5F008DE8C7 /* convert_UTF.cc */; };
+ D2F651160BEF953100920385 /* convert_UTF.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 9B35FF570B267D5F008DE8C7 /* convert_UTF.h */; };
+ D2F6511B0BEF970E00920385 /* dynamic_images.cc in Sources */ = {isa = PBXBuildFile; fileRef = D2F651070BEF949A00920385 /* dynamic_images.cc */; };
+ D2F6511D0BEF973500920385 /* file_id.cc in Sources */ = {isa = PBXBuildFile; fileRef = D2F650FA0BEF947200920385 /* file_id.cc */; };
+ D2F6511E0BEF973600920385 /* macho_id.cc in Sources */ = {isa = PBXBuildFile; fileRef = D2F650FC0BEF947200920385 /* macho_id.cc */; };
+ D2F6511F0BEF973900920385 /* macho_utilities.cc in Sources */ = {isa = PBXBuildFile; fileRef = D2F650FE0BEF947200920385 /* macho_utilities.cc */; };
+ D2F651210BEF975400920385 /* macho_walker.cc in Sources */ = {isa = PBXBuildFile; fileRef = D2F6510C0BEF94EB00920385 /* macho_walker.cc */; };
+ F93A887D0E8B4C8C0026AF89 /* macho_walker.cc in Sources */ = {isa = PBXBuildFile; fileRef = D2F6510C0BEF94EB00920385 /* macho_walker.cc */; };
+ F93A887E0E8B4C8C0026AF89 /* macho_id.cc in Sources */ = {isa = PBXBuildFile; fileRef = D2F650FC0BEF947200920385 /* macho_id.cc */; };
+ F93A887F0E8B4C8C0026AF89 /* macho_utilities.cc in Sources */ = {isa = PBXBuildFile; fileRef = D2F650FE0BEF947200920385 /* macho_utilities.cc */; };
+ F93A88800E8B4C8C0026AF89 /* file_id.cc in Sources */ = {isa = PBXBuildFile; fileRef = D2F650FA0BEF947200920385 /* file_id.cc */; };
+ F93A88860E8B4C9A0026AF89 /* dwarftests.mm in Sources */ = {isa = PBXBuildFile; fileRef = F9721F310E8B07E800D7E813 /* dwarftests.mm */; };
+ F93A88870E8B4C9A0026AF89 /* dump_syms.cc in Sources */ = {isa = PBXBuildFile; fileRef = F9721F390E8B0D0D00D7E813 /* dump_syms.cc */; };
+ F93A88880E8B4C9A0026AF89 /* bytereader.cc in Sources */ = {isa = PBXBuildFile; fileRef = F9721F760E8B0DC700D7E813 /* bytereader.cc */; };
+ F93A88890E8B4C9A0026AF89 /* dwarf2reader.cc in Sources */ = {isa = PBXBuildFile; fileRef = F9721F770E8B0DC700D7E813 /* dwarf2reader.cc */; };
+ F93A888A0E8B4C9A0026AF89 /* functioninfo.cc in Sources */ = {isa = PBXBuildFile; fileRef = F9721F780E8B0DC700D7E813 /* functioninfo.cc */; };
+ F93A888B0E8B4C9A0026AF89 /* md5.cc in Sources */ = {isa = PBXBuildFile; fileRef = F9721FA80E8B0E4800D7E813 /* md5.cc */; };
+ F9721F6C0E8B0D7000D7E813 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F9721F6B0E8B0D7000D7E813 /* Cocoa.framework */; };
+ F9721FA20E8B0E2300D7E813 /* SenTestingKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F9721FA10E8B0E2300D7E813 /* SenTestingKit.framework */; };
+ F982089C0DB3280D0017AECA /* breakpad_nlist_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = F982089B0DB3280D0017AECA /* breakpad_nlist_test.cc */; };
+ F98208A30DB32CAE0017AECA /* breakpad_nlist_64.cc in Sources */ = {isa = PBXBuildFile; fileRef = F98208A10DB32CAE0017AECA /* breakpad_nlist_64.cc */; };
+ F9AE5B390DBFDBDB00505983 /* dynamic_images.cc in Sources */ = {isa = PBXBuildFile; fileRef = D2F651070BEF949A00920385 /* dynamic_images.cc */; };
+ F9AE5B3A0DBFDBDB00505983 /* DynamicImagesTests.cc in Sources */ = {isa = PBXBuildFile; fileRef = F9C5A4210DB82DD800209C76 /* DynamicImagesTests.cc */; };
+ F9B34E870DBC1E1600306484 /* dynamic_images.cc in Sources */ = {isa = PBXBuildFile; fileRef = D2F651070BEF949A00920385 /* dynamic_images.cc */; };
+ F9C5A4220DB82DD800209C76 /* DynamicImagesTests.cc in Sources */ = {isa = PBXBuildFile; fileRef = F9C5A4210DB82DD800209C76 /* DynamicImagesTests.cc */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXCopyFilesBuildPhase section */
+ 8DD76F690486A84900D96B5E /* CopyFiles */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 8;
+ dstPath = /usr/share/man/man1/;
+ dstSubfolderSpec = 0;
+ files = (
+ 9BD82C100B0133520055103E /* exception_handler.h in CopyFiles */,
+ 9BD82C120B0133520055103E /* minidump_generator.h in CopyFiles */,
+ 9BD82C270B01344C0055103E /* minidump_file_writer.h in CopyFiles */,
+ 9BD82C2F0B01345E0055103E /* string_utilities.h in CopyFiles */,
+ 9B7CA7700B12873A00CD3A1D /* minidump_file_writer-inl.h in CopyFiles */,
+ D2F651010BEF947200920385 /* file_id.h in CopyFiles */,
+ D2F651030BEF947200920385 /* macho_id.h in CopyFiles */,
+ D2F651050BEF947200920385 /* macho_utilities.h in CopyFiles */,
+ D2F6510A0BEF949A00920385 /* dynamic_images.h in CopyFiles */,
+ D2F6510F0BEF94EB00920385 /* macho_walker.h in CopyFiles */,
+ D2F651130BEF951C00920385 /* string_conversion.h in CopyFiles */,
+ D2F651160BEF953100920385 /* convert_UTF.h in CopyFiles */,
+ );
+ runOnlyForDeploymentPostprocessing = 1;
+ };
+/* End PBXCopyFilesBuildPhase section */
+
+/* Begin PBXFileReference section */
+ 8BFC812011FF99D5002CB4DC /* Breakpad.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Breakpad.xcconfig; path = ../../../common/mac/Breakpad.xcconfig; sourceTree = SOURCE_ROOT; };
+ 8BFC812111FF99D5002CB4DC /* BreakpadDebug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = BreakpadDebug.xcconfig; path = ../../../common/mac/BreakpadDebug.xcconfig; sourceTree = SOURCE_ROOT; };
+ 8BFC812211FF99D5002CB4DC /* BreakpadRelease.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = BreakpadRelease.xcconfig; path = ../../../common/mac/BreakpadRelease.xcconfig; sourceTree = SOURCE_ROOT; };
+ 8BFC813E11FF9A58002CB4DC /* libcrypto.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libcrypto.dylib; path = usr/lib/libcrypto.dylib; sourceTree = SDKROOT; };
+ 8BFC815411FF9B7F002CB4DC /* Carbon.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Carbon.framework; path = System/Library/Frameworks/Carbon.framework; sourceTree = SDKROOT; };
+ 8BFC819211FF9C23002CB4DC /* CPlusTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CPlusTest.framework; path = Library/Frameworks/CPlusTest.framework; sourceTree = DEVELOPER_DIR; };
+ 8DD76F6C0486A84900D96B5E /* generator_test */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = generator_test; sourceTree = BUILT_PRODUCTS_DIR; };
+ 9B35FF560B267D5F008DE8C7 /* convert_UTF.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = convert_UTF.cc; path = ../../../common/convert_UTF.cc; sourceTree = SOURCE_ROOT; };
+ 9B35FF570B267D5F008DE8C7 /* convert_UTF.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = convert_UTF.h; path = ../../../common/convert_UTF.h; sourceTree = SOURCE_ROOT; };
+ 9B35FF580B267D5F008DE8C7 /* string_conversion.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = string_conversion.cc; path = ../../../common/string_conversion.cc; sourceTree = SOURCE_ROOT; };
+ 9B35FF590B267D5F008DE8C7 /* string_conversion.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = string_conversion.h; path = ../../../common/string_conversion.h; sourceTree = SOURCE_ROOT; };
+ 9B37CEEB0AF98ECD00FA4BD4 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = System/Library/Frameworks/CoreFoundation.framework; sourceTree = SDKROOT; };
+ 9B7CA84E0B1297F200CD3A1D /* unit_test */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = unit_test; sourceTree = BUILT_PRODUCTS_DIR; };
+ 9B7CA8530B12989000CD3A1D /* minidump_file_writer_unittest.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = minidump_file_writer_unittest.cc; path = ../../minidump_file_writer_unittest.cc; sourceTree = "<group>"; };
+ 9BD82A9B0B00267E0055103E /* handler_test */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = handler_test; sourceTree = BUILT_PRODUCTS_DIR; };
+ 9BD82BFD0B01333D0055103E /* exception_handler_test.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = exception_handler_test.cc; sourceTree = SOURCE_ROOT; };
+ 9BD82BFE0B01333D0055103E /* minidump_generator_test.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = minidump_generator_test.cc; sourceTree = SOURCE_ROOT; };
+ 9BD82C090B0133520055103E /* exception_handler.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = exception_handler.cc; sourceTree = SOURCE_ROOT; };
+ 9BD82C0A0B0133520055103E /* exception_handler.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = exception_handler.h; sourceTree = SOURCE_ROOT; };
+ 9BD82C0B0B0133520055103E /* minidump_generator.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = minidump_generator.cc; sourceTree = SOURCE_ROOT; };
+ 9BD82C0C0B0133520055103E /* minidump_generator.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = minidump_generator.h; sourceTree = SOURCE_ROOT; };
+ 9BD82C230B01344C0055103E /* minidump_file_writer.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = minidump_file_writer.cc; path = ../../minidump_file_writer.cc; sourceTree = SOURCE_ROOT; };
+ 9BD82C240B01344C0055103E /* minidump_file_writer.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = minidump_file_writer.h; path = ../../minidump_file_writer.h; sourceTree = SOURCE_ROOT; };
+ 9BD82C2B0B01345E0055103E /* string_utilities.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = string_utilities.cc; path = ../../../common/mac/string_utilities.cc; sourceTree = SOURCE_ROOT; };
+ 9BD82C2C0B01345E0055103E /* string_utilities.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = string_utilities.h; path = ../../../common/mac/string_utilities.h; sourceTree = SOURCE_ROOT; };
+ 9BE3C01E0B0CE329009892DF /* minidump_file_writer-inl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "minidump_file_writer-inl.h"; path = "../../minidump_file_writer-inl.h"; sourceTree = SOURCE_ROOT; };
+ D2F650FA0BEF947200920385 /* file_id.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = file_id.cc; path = ../../../common/mac/file_id.cc; sourceTree = SOURCE_ROOT; };
+ D2F650FB0BEF947200920385 /* file_id.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = file_id.h; path = ../../../common/mac/file_id.h; sourceTree = SOURCE_ROOT; };
+ D2F650FC0BEF947200920385 /* macho_id.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = macho_id.cc; path = ../../../common/mac/macho_id.cc; sourceTree = SOURCE_ROOT; };
+ D2F650FD0BEF947200920385 /* macho_id.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = macho_id.h; path = ../../../common/mac/macho_id.h; sourceTree = SOURCE_ROOT; };
+ D2F650FE0BEF947200920385 /* macho_utilities.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = macho_utilities.cc; path = ../../../common/mac/macho_utilities.cc; sourceTree = SOURCE_ROOT; };
+ D2F650FF0BEF947200920385 /* macho_utilities.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = macho_utilities.h; path = ../../../common/mac/macho_utilities.h; sourceTree = SOURCE_ROOT; };
+ D2F651070BEF949A00920385 /* dynamic_images.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = dynamic_images.cc; sourceTree = "<group>"; };
+ D2F651080BEF949A00920385 /* dynamic_images.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = dynamic_images.h; sourceTree = "<group>"; };
+ D2F6510C0BEF94EB00920385 /* macho_walker.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = macho_walker.cc; path = ../../../common/mac/macho_walker.cc; sourceTree = SOURCE_ROOT; };
+ D2F6510D0BEF94EB00920385 /* macho_walker.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = macho_walker.h; path = ../../../common/mac/macho_walker.h; sourceTree = SOURCE_ROOT; };
+ F917C4F70E03265A00F86017 /* breakpad_exc_server.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = breakpad_exc_server.c; sourceTree = "<group>"; };
+ F917C4F80E03265A00F86017 /* breakpad_exc_server.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = breakpad_exc_server.h; sourceTree = "<group>"; };
+ F93A88750E8B4C700026AF89 /* octestcases.octest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = octestcases.octest; sourceTree = BUILT_PRODUCTS_DIR; };
+ F93A88760E8B4C700026AF89 /* obj-cTestCases-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "obj-cTestCases-Info.plist"; sourceTree = "<group>"; };
+ F9721F300E8B07E800D7E813 /* dwarftests.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dwarftests.h; sourceTree = "<group>"; };
+ F9721F310E8B07E800D7E813 /* dwarftests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = dwarftests.mm; sourceTree = "<group>"; };
+ F9721F380E8B0CFC00D7E813 /* dump_syms.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dump_syms.h; path = ../../../common/mac/dump_syms.h; sourceTree = SOURCE_ROOT; };
+ F9721F390E8B0D0D00D7E813 /* dump_syms.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = dump_syms.cc; path = ../../../common/mac/dump_syms.cc; sourceTree = SOURCE_ROOT; };
+ F9721F6B0E8B0D7000D7E813 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
+ F9721F760E8B0DC700D7E813 /* bytereader.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = bytereader.cc; path = ../../../common/dwarf/bytereader.cc; sourceTree = SOURCE_ROOT; };
+ F9721F770E8B0DC700D7E813 /* dwarf2reader.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = dwarf2reader.cc; path = ../../../common/dwarf/dwarf2reader.cc; sourceTree = SOURCE_ROOT; };
+ F9721F780E8B0DC700D7E813 /* functioninfo.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = functioninfo.cc; path = ../../../common/dwarf/functioninfo.cc; sourceTree = SOURCE_ROOT; };
+ F9721FA10E8B0E2300D7E813 /* SenTestingKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SenTestingKit.framework; path = Library/Frameworks/SenTestingKit.framework; sourceTree = DEVELOPER_DIR; };
+ F9721FA80E8B0E4800D7E813 /* md5.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = md5.cc; path = ../../../common/md5.cc; sourceTree = SOURCE_ROOT; };
+ F982089A0DB3280D0017AECA /* breakpad_nlist_test.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = breakpad_nlist_test.h; sourceTree = "<group>"; };
+ F982089B0DB3280D0017AECA /* breakpad_nlist_test.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = breakpad_nlist_test.cc; sourceTree = "<group>"; };
+ F98208A10DB32CAE0017AECA /* breakpad_nlist_64.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = breakpad_nlist_64.cc; sourceTree = "<group>"; };
+ F98208A20DB32CAE0017AECA /* breakpad_nlist_64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = breakpad_nlist_64.h; sourceTree = "<group>"; };
+ F9AE19B50DB040E300C98454 /* minidump_tests32-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "minidump_tests32-Info.plist"; sourceTree = "<group>"; };
+ F9AE19C30DB04A9500C98454 /* minidump_tests64.cptest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = minidump_tests64.cptest; sourceTree = BUILT_PRODUCTS_DIR; };
+ F9AE5B330DBFDBA300505983 /* minidump_tests32.cptest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = minidump_tests32.cptest; sourceTree = BUILT_PRODUCTS_DIR; };
+ F9AE5B340DBFDBA300505983 /* minidump_tests64-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "minidump_tests64-Info.plist"; sourceTree = "<group>"; };
+ F9C5A4200DB82DD800209C76 /* DynamicImagesTests.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DynamicImagesTests.h; sourceTree = "<group>"; };
+ F9C5A4210DB82DD800209C76 /* DynamicImagesTests.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DynamicImagesTests.cc; sourceTree = "<group>"; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ 8DD76F660486A84900D96B5E /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 9B37CEEC0AF98ECD00FA4BD4 /* CoreFoundation.framework in Frameworks */,
+ 8BFC813F11FF9A58002CB4DC /* libcrypto.dylib in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 9B7CA84C0B1297F200CD3A1D /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 8BFC814511FF9A9D002CB4DC /* libcrypto.dylib in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 9BD82A990B00267E0055103E /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 9BD82AC10B0029DF0055103E /* CoreFoundation.framework in Frameworks */,
+ 8BFC814411FF9A9C002CB4DC /* libcrypto.dylib in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ F93A88720E8B4C700026AF89 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 8BFC814A11FF9B13002CB4DC /* libcrypto.dylib in Frameworks */,
+ 8BFC814B11FF9B3F002CB4DC /* SenTestingKit.framework in Frameworks */,
+ 8BFC814C11FF9B3F002CB4DC /* Cocoa.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ F9AE19C00DB04A9500C98454 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 8BFC814811FF9B13002CB4DC /* libcrypto.dylib in Frameworks */,
+ 8BFC81A211FF9C2E002CB4DC /* CPlusTest.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ F9AE5B300DBFDBA300505983 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ F9721F6C0E8B0D7000D7E813 /* Cocoa.framework in Frameworks */,
+ F9721FA20E8B0E2300D7E813 /* SenTestingKit.framework in Frameworks */,
+ 8BFC814911FF9B13002CB4DC /* libcrypto.dylib in Frameworks */,
+ 8BFC81A311FF9C2F002CB4DC /* CPlusTest.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 08FB7794FE84155DC02AAC07 /* MinidumpWriter */ = {
+ isa = PBXGroup;
+ children = (
+ 8BFC812011FF99D5002CB4DC /* Breakpad.xcconfig */,
+ 8BFC812111FF99D5002CB4DC /* BreakpadDebug.xcconfig */,
+ 8BFC812211FF99D5002CB4DC /* BreakpadRelease.xcconfig */,
+ F9721FA80E8B0E4800D7E813 /* md5.cc */,
+ F9721F760E8B0DC700D7E813 /* bytereader.cc */,
+ F9721F770E8B0DC700D7E813 /* dwarf2reader.cc */,
+ F9721F780E8B0DC700D7E813 /* functioninfo.cc */,
+ F9721F390E8B0D0D00D7E813 /* dump_syms.cc */,
+ F9721F380E8B0CFC00D7E813 /* dump_syms.h */,
+ F917C4F70E03265A00F86017 /* breakpad_exc_server.c */,
+ F917C4F80E03265A00F86017 /* breakpad_exc_server.h */,
+ F98208A10DB32CAE0017AECA /* breakpad_nlist_64.cc */,
+ F98208A20DB32CAE0017AECA /* breakpad_nlist_64.h */,
+ D2F6510C0BEF94EB00920385 /* macho_walker.cc */,
+ D2F6510D0BEF94EB00920385 /* macho_walker.h */,
+ D2F651070BEF949A00920385 /* dynamic_images.cc */,
+ D2F651080BEF949A00920385 /* dynamic_images.h */,
+ D2F650FA0BEF947200920385 /* file_id.cc */,
+ D2F650FB0BEF947200920385 /* file_id.h */,
+ D2F650FC0BEF947200920385 /* macho_id.cc */,
+ D2F650FD0BEF947200920385 /* macho_id.h */,
+ D2F650FE0BEF947200920385 /* macho_utilities.cc */,
+ D2F650FF0BEF947200920385 /* macho_utilities.h */,
+ F9C5A41F0DB82DB000209C76 /* testcases */,
+ 9BD82C040B0133420055103E /* Breakpad */,
+ 08FB7795FE84155DC02AAC07 /* Source */,
+ 9B37CEEA0AF98EB600FA4BD4 /* Frameworks */,
+ 1AB674ADFE9D54B511CA2CBB /* Products */,
+ F9AE19B50DB040E300C98454 /* minidump_tests32-Info.plist */,
+ F9AE5B340DBFDBA300505983 /* minidump_tests64-Info.plist */,
+ F93A88760E8B4C700026AF89 /* obj-cTestCases-Info.plist */,
+ );
+ name = MinidumpWriter;
+ sourceTree = "<group>";
+ };
+ 08FB7795FE84155DC02AAC07 /* Source */ = {
+ isa = PBXGroup;
+ children = (
+ 9BD82BFD0B01333D0055103E /* exception_handler_test.cc */,
+ 9BD82BFE0B01333D0055103E /* minidump_generator_test.cc */,
+ 9B7CA8530B12989000CD3A1D /* minidump_file_writer_unittest.cc */,
+ );
+ name = Source;
+ sourceTree = "<group>";
+ };
+ 1AB674ADFE9D54B511CA2CBB /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 8DD76F6C0486A84900D96B5E /* generator_test */,
+ 9BD82A9B0B00267E0055103E /* handler_test */,
+ 9B7CA84E0B1297F200CD3A1D /* unit_test */,
+ F9AE19C30DB04A9500C98454 /* minidump_tests64.cptest */,
+ F9AE5B330DBFDBA300505983 /* minidump_tests32.cptest */,
+ F93A88750E8B4C700026AF89 /* octestcases.octest */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+ 9B37CEEA0AF98EB600FA4BD4 /* Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ 8BFC813E11FF9A58002CB4DC /* libcrypto.dylib */,
+ 8BFC815411FF9B7F002CB4DC /* Carbon.framework */,
+ F9721FA10E8B0E2300D7E813 /* SenTestingKit.framework */,
+ F9721F6B0E8B0D7000D7E813 /* Cocoa.framework */,
+ 9B37CEEB0AF98ECD00FA4BD4 /* CoreFoundation.framework */,
+ 8BFC819211FF9C23002CB4DC /* CPlusTest.framework */,
+ );
+ name = Frameworks;
+ sourceTree = "<group>";
+ };
+ 9BD82C040B0133420055103E /* Breakpad */ = {
+ isa = PBXGroup;
+ children = (
+ 9B35FF560B267D5F008DE8C7 /* convert_UTF.cc */,
+ 9B35FF570B267D5F008DE8C7 /* convert_UTF.h */,
+ 9B35FF580B267D5F008DE8C7 /* string_conversion.cc */,
+ 9B35FF590B267D5F008DE8C7 /* string_conversion.h */,
+ 9BD82C090B0133520055103E /* exception_handler.cc */,
+ 9BD82C0A0B0133520055103E /* exception_handler.h */,
+ 9BD82C0B0B0133520055103E /* minidump_generator.cc */,
+ 9BD82C0C0B0133520055103E /* minidump_generator.h */,
+ 9BD82C230B01344C0055103E /* minidump_file_writer.cc */,
+ 9BE3C01E0B0CE329009892DF /* minidump_file_writer-inl.h */,
+ 9BD82C240B01344C0055103E /* minidump_file_writer.h */,
+ 9BD82C2B0B01345E0055103E /* string_utilities.cc */,
+ 9BD82C2C0B01345E0055103E /* string_utilities.h */,
+ );
+ name = Breakpad;
+ sourceTree = "<group>";
+ };
+ F9C5A41F0DB82DB000209C76 /* testcases */ = {
+ isa = PBXGroup;
+ children = (
+ F982089A0DB3280D0017AECA /* breakpad_nlist_test.h */,
+ F982089B0DB3280D0017AECA /* breakpad_nlist_test.cc */,
+ F9C5A4200DB82DD800209C76 /* DynamicImagesTests.h */,
+ F9C5A4210DB82DD800209C76 /* DynamicImagesTests.cc */,
+ F9721F300E8B07E800D7E813 /* dwarftests.h */,
+ F9721F310E8B07E800D7E813 /* dwarftests.mm */,
+ );
+ path = testcases;
+ sourceTree = "<group>";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+ 8DD76F620486A84900D96B5E /* generator_test */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 1DEB923108733DC60010E9CD /* Build configuration list for PBXNativeTarget "generator_test" */;
+ buildPhases = (
+ 8DD76F640486A84900D96B5E /* Sources */,
+ 8DD76F660486A84900D96B5E /* Frameworks */,
+ 8DD76F690486A84900D96B5E /* CopyFiles */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = generator_test;
+ productInstallPath = "$(HOME)/bin";
+ productName = MinidumpWriter;
+ productReference = 8DD76F6C0486A84900D96B5E /* generator_test */;
+ productType = "com.apple.product-type.tool";
+ };
+ 9B7CA84D0B1297F200CD3A1D /* unit_test */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 9B7CA8500B12984300CD3A1D /* Build configuration list for PBXNativeTarget "unit_test" */;
+ buildPhases = (
+ 9B7CA84B0B1297F200CD3A1D /* Sources */,
+ 9B7CA84C0B1297F200CD3A1D /* Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = unit_test;
+ productName = "filewriter unit test";
+ productReference = 9B7CA84E0B1297F200CD3A1D /* unit_test */;
+ productType = "com.apple.product-type.tool";
+ };
+ 9BD82A9A0B00267E0055103E /* handler_test */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 9BD82AA60B0026BF0055103E /* Build configuration list for PBXNativeTarget "handler_test" */;
+ buildPhases = (
+ 9BD82A980B00267E0055103E /* Sources */,
+ 9BD82A990B00267E0055103E /* Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = handler_test;
+ productName = ExceptionTester;
+ productReference = 9BD82A9B0B00267E0055103E /* handler_test */;
+ productType = "com.apple.product-type.tool";
+ };
+ F93A88740E8B4C700026AF89 /* obj-c_TestCases */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = F93A88790E8B4C700026AF89 /* Build configuration list for PBXNativeTarget "obj-c_TestCases" */;
+ buildPhases = (
+ F93A88700E8B4C700026AF89 /* Resources */,
+ F93A88710E8B4C700026AF89 /* Sources */,
+ F93A88720E8B4C700026AF89 /* Frameworks */,
+ F93A88730E8B4C700026AF89 /* ShellScript */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = "obj-c_TestCases";
+ productName = octestcases;
+ productReference = F93A88750E8B4C700026AF89 /* octestcases.octest */;
+ productType = "com.apple.product-type.bundle";
+ };
+ F9AE19C20DB04A9500C98454 /* minidump_tests64 */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = F9AE19C70DB04AA200C98454 /* Build configuration list for PBXNativeTarget "minidump_tests64" */;
+ buildPhases = (
+ F9AE19BE0DB04A9500C98454 /* Resources */,
+ F9AE19BF0DB04A9500C98454 /* Sources */,
+ F9AE19C00DB04A9500C98454 /* Frameworks */,
+ F9AE19C10DB04A9500C98454 /* ShellScript */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = minidump_tests64;
+ productName = minidump_tests;
+ productReference = F9AE19C30DB04A9500C98454 /* minidump_tests64.cptest */;
+ productType = "com.apple.product-type.bundle";
+ };
+ F9AE5B320DBFDBA300505983 /* minidump_tests32 */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = F9AE5B380DBFDBA300505983 /* Build configuration list for PBXNativeTarget "minidump_tests32" */;
+ buildPhases = (
+ F9AE5B2E0DBFDBA300505983 /* Resources */,
+ F9AE5B2F0DBFDBA300505983 /* Sources */,
+ F9AE5B300DBFDBA300505983 /* Frameworks */,
+ F9AE5B310DBFDBA300505983 /* ShellScript */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = minidump_tests32;
+ productName = Untitled;
+ productReference = F9AE5B330DBFDBA300505983 /* minidump_tests32.cptest */;
+ productType = "com.apple.product-type.bundle";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 08FB7793FE84155DC02AAC07 /* Project object */ = {
+ isa = PBXProject;
+ buildConfigurationList = 1DEB923508733DC60010E9CD /* Build configuration list for PBXProject "minidump_test" */;
+ compatibilityVersion = "Xcode 3.2";
+ developmentRegion = English;
+ hasScannedForEncodings = 1;
+ knownRegions = (
+ English,
+ Japanese,
+ French,
+ German,
+ );
+ mainGroup = 08FB7794FE84155DC02AAC07 /* MinidumpWriter */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ 8DD76F620486A84900D96B5E /* generator_test */,
+ 9BD82A9A0B00267E0055103E /* handler_test */,
+ 9B7CA84D0B1297F200CD3A1D /* unit_test */,
+ F9AE19C20DB04A9500C98454 /* minidump_tests64 */,
+ F9AE5B320DBFDBA300505983 /* minidump_tests32 */,
+ F93A88740E8B4C700026AF89 /* obj-c_TestCases */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+ F93A88700E8B4C700026AF89 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ F9AE19BE0DB04A9500C98454 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ F9AE5B2E0DBFDBA300505983 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXShellScriptBuildPhase section */
+ F93A88730E8B4C700026AF89 /* ShellScript */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputPaths = (
+ );
+ outputPaths = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "# Run the unit tests in this test bundle.\n\"${SYSTEM_DEVELOPER_DIR}/Tools/RunUnitTests\"\n";
+ };
+ F9AE19C10DB04A9500C98454 /* ShellScript */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputPaths = (
+ );
+ outputPaths = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "# Run the unit tests in this test bundle.\n\"${SYSTEM_DEVELOPER_DIR}/Tools/RunUnitTests\"\n# Run gcov on the framework getting tested\nif [ \"${CONFIGURATION}\" = 'Coverage' ];\nthen\n FRAMEWORK_NAME=minidump_tests64\n FRAMEWORK_OBJ_DIR=${OBJROOT}/${PROJECT_NAME}.build/${CONFIGURATION}/${FRAMEWORK_NAME}.build/Objects-normal/${NATIVE_ARCH_ACTUAL}\n mkdir -p coverage\n pushd coverage\n echo find ${OBJROOT} -name *.gcda -exec gcov -o ${FRAMEWORK_OBJ_DIR} {} \\;\n find ${OBJROOT} -name *.gcda -exec gcov -o ${FRAMEWORK_OBJ_DIR} {} \\;\n popd\nfi ";
+ };
+ F9AE5B310DBFDBA300505983 /* ShellScript */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputPaths = (
+ );
+ outputPaths = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "# Run the unit tests in this test bundle.\n\"${SYSTEM_DEVELOPER_DIR}/Tools/RunUnitTests\"\n\n";
+ };
+/* End PBXShellScriptBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ 8DD76F640486A84900D96B5E /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 9BD82C020B01333D0055103E /* minidump_generator_test.cc in Sources */,
+ 9BD82C0F0B0133520055103E /* exception_handler.cc in Sources */,
+ 9BD82C110B0133520055103E /* minidump_generator.cc in Sources */,
+ 9BD82C260B01344C0055103E /* minidump_file_writer.cc in Sources */,
+ 9BD82C2E0B01345E0055103E /* string_utilities.cc in Sources */,
+ D2F651000BEF947200920385 /* file_id.cc in Sources */,
+ D2F651020BEF947200920385 /* macho_id.cc in Sources */,
+ D2F651040BEF947200920385 /* macho_utilities.cc in Sources */,
+ D2F651090BEF949A00920385 /* dynamic_images.cc in Sources */,
+ D2F6510E0BEF94EB00920385 /* macho_walker.cc in Sources */,
+ D2F651110BEF951700920385 /* string_conversion.cc in Sources */,
+ D2F651150BEF953000920385 /* convert_UTF.cc in Sources */,
+ 8BFC81B011FF9C8D002CB4DC /* breakpad_nlist_64.cc in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 9B7CA84B0B1297F200CD3A1D /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 9B7CA8540B12989000CD3A1D /* minidump_file_writer_unittest.cc in Sources */,
+ 9B7CA8550B1298A100CD3A1D /* minidump_file_writer.cc in Sources */,
+ 9BC1D2940B336F2300F2A2B4 /* convert_UTF.cc in Sources */,
+ 9BC1D2950B336F2500F2A2B4 /* string_conversion.cc in Sources */,
+ 8BFC81AE11FF9C8C002CB4DC /* breakpad_nlist_64.cc in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 9BD82A980B00267E0055103E /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 9BD82BFF0B01333D0055103E /* exception_handler_test.cc in Sources */,
+ 9BD82C0D0B0133520055103E /* exception_handler.cc in Sources */,
+ 9BD82C0E0B0133520055103E /* minidump_generator.cc in Sources */,
+ 9BD82C250B01344C0055103E /* minidump_file_writer.cc in Sources */,
+ 9BD82C2D0B01345E0055103E /* string_utilities.cc in Sources */,
+ 9B35FF5A0B267D5F008DE8C7 /* convert_UTF.cc in Sources */,
+ 9B35FF5B0B267D5F008DE8C7 /* string_conversion.cc in Sources */,
+ D2F6511B0BEF970E00920385 /* dynamic_images.cc in Sources */,
+ D2F6511D0BEF973500920385 /* file_id.cc in Sources */,
+ D2F6511E0BEF973600920385 /* macho_id.cc in Sources */,
+ D2F6511F0BEF973900920385 /* macho_utilities.cc in Sources */,
+ D2F651210BEF975400920385 /* macho_walker.cc in Sources */,
+ 8BFC81AF11FF9C8C002CB4DC /* breakpad_nlist_64.cc in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ F93A88710E8B4C700026AF89 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ F93A88860E8B4C9A0026AF89 /* dwarftests.mm in Sources */,
+ F93A88870E8B4C9A0026AF89 /* dump_syms.cc in Sources */,
+ F93A88880E8B4C9A0026AF89 /* bytereader.cc in Sources */,
+ F93A88890E8B4C9A0026AF89 /* dwarf2reader.cc in Sources */,
+ F93A888A0E8B4C9A0026AF89 /* functioninfo.cc in Sources */,
+ F93A888B0E8B4C9A0026AF89 /* md5.cc in Sources */,
+ F93A887D0E8B4C8C0026AF89 /* macho_walker.cc in Sources */,
+ F93A887E0E8B4C8C0026AF89 /* macho_id.cc in Sources */,
+ F93A887F0E8B4C8C0026AF89 /* macho_utilities.cc in Sources */,
+ F93A88800E8B4C8C0026AF89 /* file_id.cc in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ F9AE19BF0DB04A9500C98454 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ F9B34E870DBC1E1600306484 /* dynamic_images.cc in Sources */,
+ F982089C0DB3280D0017AECA /* breakpad_nlist_test.cc in Sources */,
+ F98208A30DB32CAE0017AECA /* breakpad_nlist_64.cc in Sources */,
+ F9C5A4220DB82DD800209C76 /* DynamicImagesTests.cc in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ F9AE5B2F0DBFDBA300505983 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ F9AE5B390DBFDBDB00505983 /* dynamic_images.cc in Sources */,
+ F9AE5B3A0DBFDBDB00505983 /* DynamicImagesTests.cc in Sources */,
+ 8BFC81AD11FF9C8A002CB4DC /* breakpad_nlist_64.cc in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin XCBuildConfiguration section */
+ 1DEB923208733DC60010E9CD /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CLANG_CXX_LANGUAGE_STANDARD = "c++17";
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "\"$(DEVELOPER_FRAMEWORKS_DIR)\"",
+ );
+ PRODUCT_NAME = generator_test;
+ USER_HEADER_SEARCH_PATHS = "../../../** $(inherited)";
+ };
+ name = Debug;
+ };
+ 1DEB923308733DC60010E9CD /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CLANG_CXX_LANGUAGE_STANDARD = "c++17";
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "\"$(DEVELOPER_FRAMEWORKS_DIR)\"",
+ );
+ PRODUCT_NAME = generator_test;
+ USER_HEADER_SEARCH_PATHS = "../../../** $(inherited)";
+ };
+ name = Release;
+ };
+ 1DEB923608733DC60010E9CD /* Debug */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 8BFC812111FF99D5002CB4DC /* BreakpadDebug.xcconfig */;
+ buildSettings = {
+ };
+ name = Debug;
+ };
+ 1DEB923708733DC60010E9CD /* Release */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 8BFC812211FF99D5002CB4DC /* BreakpadRelease.xcconfig */;
+ buildSettings = {
+ };
+ name = Release;
+ };
+ 9B7CA8510B12984300CD3A1D /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = unit_test;
+ USER_HEADER_SEARCH_PATHS = "../../../** $(inherited)";
+ };
+ name = Debug;
+ };
+ 9B7CA8520B12984300CD3A1D /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = unit_test;
+ USER_HEADER_SEARCH_PATHS = "../../../** $(inherited)";
+ };
+ name = Release;
+ };
+ 9BD82AA70B0026BF0055103E /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = handler_test;
+ USER_HEADER_SEARCH_PATHS = "../../.. $(inherited)";
+ };
+ name = Debug;
+ };
+ 9BD82AA80B0026BF0055103E /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = handler_test;
+ USER_HEADER_SEARCH_PATHS = "../../.. $(inherited)";
+ };
+ name = Release;
+ };
+ F93A88770E8B4C700026AF89 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ FRAMEWORK_SEARCH_PATHS = "$(DEVELOPER_LIBRARY_DIR)/Frameworks";
+ INFOPLIST_FILE = "obj-cTestCases-Info.plist";
+ PRODUCT_NAME = octestcases;
+ USER_HEADER_SEARCH_PATHS = "../../../..//**";
+ WRAPPER_EXTENSION = octest;
+ };
+ name = Debug;
+ };
+ F93A88780E8B4C700026AF89 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ FRAMEWORK_SEARCH_PATHS = "$(DEVELOPER_LIBRARY_DIR)/Frameworks";
+ INFOPLIST_FILE = "obj-cTestCases-Info.plist";
+ PRODUCT_NAME = octestcases;
+ USER_HEADER_SEARCH_PATHS = "../../../..//**";
+ WRAPPER_EXTENSION = octest;
+ };
+ name = Release;
+ };
+ F9AE19C40DB04A9500C98454 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ FRAMEWORK_SEARCH_PATHS = "$(DEVELOPER_LIBRARY_DIR)/Frameworks";
+ INFOPLIST_FILE = "minidump_tests64-Info.plist";
+ PRODUCT_NAME = minidump_tests64;
+ USER_HEADER_SEARCH_PATHS = "../../../**";
+ WRAPPER_EXTENSION = cptest;
+ };
+ name = Debug;
+ };
+ F9AE19C50DB04A9500C98454 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ FRAMEWORK_SEARCH_PATHS = "$(DEVELOPER_LIBRARY_DIR)/Frameworks";
+ INFOPLIST_FILE = "minidump_tests64-Info.plist";
+ PRODUCT_NAME = minidump_tests64;
+ USER_HEADER_SEARCH_PATHS = "../../../**";
+ WRAPPER_EXTENSION = cptest;
+ };
+ name = Release;
+ };
+ F9AE5B350DBFDBA300505983 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ FRAMEWORK_SEARCH_PATHS = "$(DEVELOPER_LIBRARY_DIR)/Frameworks";
+ INFOPLIST_FILE = "minidump_tests32-Info.plist";
+ PRODUCT_NAME = minidump_tests32;
+ USER_HEADER_SEARCH_PATHS = "../../../**";
+ WRAPPER_EXTENSION = cptest;
+ };
+ name = Debug;
+ };
+ F9AE5B370DBFDBA300505983 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ FRAMEWORK_SEARCH_PATHS = "$(DEVELOPER_LIBRARY_DIR)/Frameworks";
+ INFOPLIST_FILE = "minidump_tests32-Info.plist";
+ PRODUCT_NAME = minidump_tests32;
+ USER_HEADER_SEARCH_PATHS = "../../../**";
+ WRAPPER_EXTENSION = cptest;
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ 1DEB923108733DC60010E9CD /* Build configuration list for PBXNativeTarget "generator_test" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 1DEB923208733DC60010E9CD /* Debug */,
+ 1DEB923308733DC60010E9CD /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 1DEB923508733DC60010E9CD /* Build configuration list for PBXProject "minidump_test" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 1DEB923608733DC60010E9CD /* Debug */,
+ 1DEB923708733DC60010E9CD /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 9B7CA8500B12984300CD3A1D /* Build configuration list for PBXNativeTarget "unit_test" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 9B7CA8510B12984300CD3A1D /* Debug */,
+ 9B7CA8520B12984300CD3A1D /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 9BD82AA60B0026BF0055103E /* Build configuration list for PBXNativeTarget "handler_test" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 9BD82AA70B0026BF0055103E /* Debug */,
+ 9BD82AA80B0026BF0055103E /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ F93A88790E8B4C700026AF89 /* Build configuration list for PBXNativeTarget "obj-c_TestCases" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ F93A88770E8B4C700026AF89 /* Debug */,
+ F93A88780E8B4C700026AF89 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ F9AE19C70DB04AA200C98454 /* Build configuration list for PBXNativeTarget "minidump_tests64" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ F9AE19C40DB04A9500C98454 /* Debug */,
+ F9AE19C50DB04A9500C98454 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ F9AE5B380DBFDBA300505983 /* Build configuration list for PBXNativeTarget "minidump_tests32" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ F9AE5B350DBFDBA300505983 /* Debug */,
+ F9AE5B370DBFDBA300505983 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = 08FB7793FE84155DC02AAC07 /* Project object */;
+}
diff --git a/toolkit/crashreporter/breakpad-client/mac/handler/moz.build b/toolkit/crashreporter/breakpad-client/mac/handler/moz.build
new file mode 100644
index 0000000000..7d123a2ef1
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/mac/handler/moz.build
@@ -0,0 +1,22 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+UNIFIED_SOURCES += [
+ 'breakpad_nlist_64.cc',
+ 'dynamic_images.cc',
+ 'exception_handler.cc',
+ 'minidump_generator.cc',
+]
+
+FINAL_LIBRARY = 'breakpad_client'
+
+LOCAL_INCLUDES += [
+ '/toolkit/crashreporter/breakpad-client',
+ '/toolkit/crashreporter/google-breakpad/src',
+]
+
+if CONFIG['MOZ_PHC']:
+ DEFINES['MOZ_PHC'] = True
diff --git a/toolkit/crashreporter/breakpad-client/mac/handler/protected_memory_allocator.cc b/toolkit/crashreporter/breakpad-client/mac/handler/protected_memory_allocator.cc
new file mode 100644
index 0000000000..6142ad124a
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/mac/handler/protected_memory_allocator.cc
@@ -0,0 +1,92 @@
+// Copyright (c) 2006, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// ProtectedMemoryAllocator
+//
+// See the header file for documentation
+
+#include "protected_memory_allocator.h"
+#include <assert.h>
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ProtectedMemoryAllocator::ProtectedMemoryAllocator(vm_size_t pool_size)
+ : pool_size_(pool_size),
+ next_alloc_offset_(0),
+ valid_(false) {
+
+ kern_return_t result = vm_allocate(mach_task_self(),
+ &base_address_,
+ pool_size,
+ TRUE
+ );
+
+ valid_ = (result == KERN_SUCCESS);
+ assert(valid_);
+}
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ProtectedMemoryAllocator::~ProtectedMemoryAllocator() {
+ vm_deallocate(mach_task_self(),
+ base_address_,
+ pool_size_
+ );
+}
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+char *ProtectedMemoryAllocator::Allocate(vm_size_t bytes) {
+ if (valid_ && next_alloc_offset_ + bytes <= pool_size_) {
+ char *p = (char*)base_address_ + next_alloc_offset_;
+ next_alloc_offset_ += bytes;
+ return p;
+ }
+
+ return NULL; // ran out of memory in our allocation block
+}
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+kern_return_t ProtectedMemoryAllocator::Protect() {
+ kern_return_t result = vm_protect(mach_task_self(),
+ base_address_,
+ pool_size_,
+ FALSE,
+ VM_PROT_READ);
+
+ return result;
+}
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+kern_return_t ProtectedMemoryAllocator::Unprotect() {
+ kern_return_t result = vm_protect(mach_task_self(),
+ base_address_,
+ pool_size_,
+ FALSE,
+ VM_PROT_READ | VM_PROT_WRITE);
+
+ return result;
+}
diff --git a/toolkit/crashreporter/breakpad-client/mac/handler/protected_memory_allocator.h b/toolkit/crashreporter/breakpad-client/mac/handler/protected_memory_allocator.h
new file mode 100644
index 0000000000..64ac23c00b
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/mac/handler/protected_memory_allocator.h
@@ -0,0 +1,85 @@
+// Copyright (c) 2006, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// ProtectedMemoryAllocator
+//
+// A very simple allocator class which allows allocation, but not deallocation.
+// The allocations can be made read-only with the Protect() method.
+// This class is NOT useful as a general-purpose memory allocation system,
+// since it does not allow deallocation. It is useful to use for a group
+// of allocations which are created in the same time-frame and destroyed
+// in the same time-frame. It is useful for making allocations of memory
+// which will not need to change often once initialized. This memory can then
+// be protected from memory smashers by calling the Protect() method.
+
+#ifndef PROTECTED_MEMORY_ALLOCATOR_H__
+#define PROTECTED_MEMORY_ALLOCATOR_H__
+
+#include <mach/mach.h>
+
+//
+class ProtectedMemoryAllocator {
+ public:
+ ProtectedMemoryAllocator(vm_size_t pool_size);
+ ~ProtectedMemoryAllocator();
+
+ // Returns a pointer to an allocation of size n within the pool.
+ // Fails by returning NULL is no more space is available.
+ // Please note that the pointers returned from this method should not
+ // be freed in any way (for example by calling free() on them ).
+ char * Allocate(vm_size_t n);
+
+ // Returns the base address of the allocation pool.
+ char * GetBaseAddress() { return (char*)base_address_; }
+
+ // Returns the size of the allocation pool, including allocated
+ // plus free space.
+ vm_size_t GetTotalSize() { return pool_size_; }
+
+ // Returns the number of bytes already allocated in the pool.
+ vm_size_t GetAllocatedSize() { return next_alloc_offset_; }
+
+ // Returns the number of bytes available for allocation.
+ vm_size_t GetFreeSize() { return pool_size_ - next_alloc_offset_; }
+
+ // Makes the entire allocation pool read-only including, of course,
+ // all allocations made from the pool.
+ kern_return_t Protect();
+
+ // Makes the entire allocation pool read/write.
+ kern_return_t Unprotect();
+
+ private:
+ vm_size_t pool_size_;
+ vm_address_t base_address_;
+ vm_size_t next_alloc_offset_;
+ bool valid_;
+};
+
+#endif // PROTECTED_MEMORY_ALLOCATOR_H__
diff --git a/toolkit/crashreporter/breakpad-client/mac/handler/testcases/DynamicImagesTests.cc b/toolkit/crashreporter/breakpad-client/mac/handler/testcases/DynamicImagesTests.cc
new file mode 100644
index 0000000000..42344ec5d3
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/mac/handler/testcases/DynamicImagesTests.cc
@@ -0,0 +1,79 @@
+// Copyright (c) 2008, Google Inc.
+// All rights reserved
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+//
+// DynamicImagesTests.cpp
+// minidump_test
+//
+// Created by Neal Sidhwaney on 4/17/08.
+// Copyright 2008 Google Inc. All rights reserved.
+//
+
+#include "mac/handler/testcases/DynamicImagesTests.h"
+#include "mac/handler/dynamic_images.h"
+
+DynamicImagesTests test2(TEST_INVOCATION(DynamicImagesTests,
+ ReadTaskMemoryTest));
+DynamicImagesTests test3(TEST_INVOCATION(DynamicImagesTests,
+ ReadLibrariesFromLocalTaskTest));
+
+DynamicImagesTests::DynamicImagesTests(TestInvocation *invocation)
+ : TestCase(invocation) {
+}
+
+DynamicImagesTests::~DynamicImagesTests() {
+}
+
+void DynamicImagesTests::ReadTaskMemoryTest() {
+ kern_return_t kr;
+
+ // pick test2 as a symbol we know to be valid to read
+ // anything will work, really
+ void *addr = reinterpret_cast<void*>(&test2);
+ std::vector<uint8_t> buf(getpagesize());
+
+ fprintf(stderr, "reading 0x%p\n", addr);
+ kr = google_breakpad::ReadTaskMemory(mach_task_self(),
+ (uint64_t)addr,
+ getpagesize(),
+ buf);
+
+ CPTAssert(kr == KERN_SUCCESS);
+
+ CPTAssert(0 == memcmp(&buf[0], (const void*)addr, getpagesize()));
+}
+
+void DynamicImagesTests::ReadLibrariesFromLocalTaskTest() {
+
+ mach_port_t me = mach_task_self();
+ google_breakpad::DynamicImages *d = new google_breakpad::DynamicImages(me);
+
+ fprintf(stderr,"Local task image count: %d\n", d->GetImageCount());
+
+ CPTAssert(d->GetImageCount() > 0);
+}
diff --git a/toolkit/crashreporter/breakpad-client/mac/handler/testcases/DynamicImagesTests.h b/toolkit/crashreporter/breakpad-client/mac/handler/testcases/DynamicImagesTests.h
new file mode 100644
index 0000000000..e1e79993bb
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/mac/handler/testcases/DynamicImagesTests.h
@@ -0,0 +1,52 @@
+// Copyright (c) 2008, Google Inc.
+// All rights reserved
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+//
+// DynamicImagesTests.h
+// minidump_test
+//
+// Created by Neal Sidhwaney on 4/17/08.
+// Copyright 2008 Google Inc. All rights reserved.
+//
+//
+
+#ifndef _CLIENT_MAC_HANDLER_TESTCASES_DYNAMICIMAGESTESTS_H__
+#define _CLIENT_MAC_HANDLER_TESTCASES_DYNAMICIMAGESTESTS_H__
+
+#include <CPlusTest/CPlusTest.h>
+
+class DynamicImagesTests : public TestCase {
+ public:
+ explicit DynamicImagesTests(TestInvocation* invocation);
+ virtual ~DynamicImagesTests();
+
+ void ReadTaskMemoryTest();
+ void ReadLibrariesFromLocalTaskTest();
+};
+
+#endif /* _CLIENT_MAC_HANDLER_TESTCASES_DYNAMICIMAGESTESTS_H__ */
diff --git a/toolkit/crashreporter/breakpad-client/mac/handler/testcases/breakpad_nlist_test.cc b/toolkit/crashreporter/breakpad-client/mac/handler/testcases/breakpad_nlist_test.cc
new file mode 100644
index 0000000000..ee3248116d
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/mac/handler/testcases/breakpad_nlist_test.cc
@@ -0,0 +1,106 @@
+// Copyright (c) 2008, Google Inc.
+// All rights reserved
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+//
+// breakpad_nlist_test.cc
+// minidump_test
+//
+// Created by Neal Sidhwaney on 4/13/08.
+// Copyright 2008 Google Inc. All rights reserved.
+//
+
+#include "mac/handler/testcases/breakpad_nlist_test.h"
+#include <mach-o/nlist.h>
+#include "mac/handler/breakpad_nlist_64.h"
+
+BreakpadNlistTest test1(TEST_INVOCATION(BreakpadNlistTest, CompareToNM));
+
+BreakpadNlistTest::BreakpadNlistTest(TestInvocation *invocation)
+ : TestCase(invocation) {
+}
+
+
+BreakpadNlistTest::~BreakpadNlistTest() {
+}
+
+void BreakpadNlistTest::CompareToNM() {
+#if TARGET_CPU_X86_64
+ system("/usr/bin/nm -arch x86_64 /usr/lib/dyld > /tmp/dyld-namelist.txt");
+#elif TARGET_CPU_PPC64
+ system("/usr/bin/nm -arch ppc64 /usr/lib/dyld > /tmp/dyld-namelist.txt");
+#endif
+
+ FILE *fd = fopen("/tmp/dyld-namelist.txt", "rt");
+
+ char oneNMAddr[30];
+ char symbolType;
+ char symbolName[500];
+ while (!feof(fd)) {
+ fscanf(fd, "%s %c %s", oneNMAddr, &symbolType, symbolName);
+ breakpad_nlist symbolList[2];
+ breakpad_nlist &list = symbolList[0];
+
+ memset(symbolList, 0, sizeof(breakpad_nlist)*2);
+ const char *symbolNames[2];
+ symbolNames[0] = (const char*)symbolName;
+ symbolNames[1] = "\0";
+ breakpad_nlist_64("/usr/lib/dyld", &list, symbolNames);
+ uint64_t nmAddr = strtol(oneNMAddr, NULL, 16);
+ if (!IsSymbolMoreThanOnceInDyld(symbolName)) {
+ CPTAssert(nmAddr == symbolList[0].n_value);
+ }
+ }
+
+ fclose(fd);
+}
+
+bool BreakpadNlistTest::IsSymbolMoreThanOnceInDyld(const char *symbolName) {
+ // These are the symbols that occur more than once when nm dumps
+ // the symbol table of /usr/lib/dyld. Our nlist program returns
+ // the first address because it's doing a search so we need to exclude
+ // these from causing the test to fail
+ const char *multipleSymbols[] = {
+ "__Z41__static_initialization_and_destruction_0ii",
+ "___tcf_0",
+ "___tcf_1",
+ "_read_encoded_value_with_base",
+ "_read_sleb128",
+ "_read_uleb128",
+ "\0"};
+
+ bool found = false;
+
+ for (int i = 0; multipleSymbols[i][0]; i++) {
+ if (!strcmp(multipleSymbols[i], symbolName)) {
+ found = true;
+ break;
+ }
+ }
+
+ return found;
+}
diff --git a/toolkit/crashreporter/breakpad-client/mac/handler/testcases/breakpad_nlist_test.h b/toolkit/crashreporter/breakpad-client/mac/handler/testcases/breakpad_nlist_test.h
new file mode 100644
index 0000000000..e93657cc90
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/mac/handler/testcases/breakpad_nlist_test.h
@@ -0,0 +1,62 @@
+// Copyright (c) 2008, Google Inc.
+// All rights reserved
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+//
+// breakpad_nlist_test.h
+// minidump_test
+//
+// Created by Neal Sidhwaney on 4/13/08.
+// Copyright 2008 Google Inc. All rights reserved.
+//
+//
+
+#ifndef CLIENT_MAC_HANDLER_TESTCASES_BREAKPAD_NLIST_TEST_H__
+#define CLIENT_MAC_HANDLER_TESTCASES_BREAKPAD_NLIST_TEST_H__
+
+#include <CPlusTest/CPlusTest.h>
+
+class BreakpadNlistTest : public TestCase {
+ private:
+
+ // nm dumps multiple addresses for the same symbol in
+ // /usr/lib/dyld. So we track those so we don't report failures
+ // in mismatches between what our nlist returns and what nm has
+ // for the duplicate symbols.
+ bool IsSymbolMoreThanOnceInDyld(const char *symbolName);
+
+ public:
+ explicit BreakpadNlistTest(TestInvocation* invocation);
+ virtual ~BreakpadNlistTest();
+
+
+ /* This test case runs nm on /usr/lib/dyld and then compares the
+ output of every symbol to what our nlist implementation returns */
+ void CompareToNM();
+};
+
+#endif /* CLIENT_MAC_HANDLER_TESTCASES_BREAKPAD_NLIST_TEST_H__*/
diff --git a/toolkit/crashreporter/breakpad-client/mac/handler/testcases/dwarftests.h b/toolkit/crashreporter/breakpad-client/mac/handler/testcases/dwarftests.h
new file mode 100644
index 0000000000..21ff7a44f0
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/mac/handler/testcases/dwarftests.h
@@ -0,0 +1,46 @@
+// Copyright (c) 2008, Google Inc.
+// All rights reserved
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+//
+// dwarftests.h
+// minidump_test
+//
+// Created by Neal Sidhwaney on 9/24/08.
+// Copyright 2008 Google Inc. All rights reserved.
+//
+
+#import <SenTestingKit/SenTestingKit.h>
+
+
+@interface dwarftests : SenTestCase {
+
+}
+
+- (void) testDWARFSymbolFileGeneration;
+
+@end
diff --git a/toolkit/crashreporter/breakpad-client/mac/handler/testcases/dwarftests.mm b/toolkit/crashreporter/breakpad-client/mac/handler/testcases/dwarftests.mm
new file mode 100644
index 0000000000..40c69aff25
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/mac/handler/testcases/dwarftests.mm
@@ -0,0 +1,60 @@
+// Copyright (c) 2008, Google Inc.
+// All rights reserved
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+//
+// dwarftests.m
+// minidump_test
+//
+// Created by Neal Sidhwaney on 9/24/08.
+// Copyright 2008 Google Inc. All rights reserved.
+//
+
+#import "dwarftests.h"
+#import "dump_syms.h"
+
+@implementation dwarftests
+- (void) testDWARFSymbolFileGeneration {
+ NSString *inputBreakpadSymbolFile = @"testcases/testdata/dump_syms_i386_breakpad.sym";
+ NSString *outputBreakpadSymbolFile = @"/tmp/dump_syms_i386.breakpad";
+
+ DumpSymbols *dump = [[DumpSymbols alloc] initWithContentsOfFile:@"testcases/testdata/dump_syms_dwarf_data"];
+
+ STAssertNotNil(dump, @"DumpSymbols is nil");
+ [dump setArchitecture:@"i386"];
+ [dump writeSymbolFile:outputBreakpadSymbolFile];
+
+ NSData *d = [[NSData alloc] initWithContentsOfFile:inputBreakpadSymbolFile];
+ STAssertNotNil(d, @"Input breakpad symbol file not found");
+
+ NSData *d1 = [[NSData alloc] initWithContentsOfFile:outputBreakpadSymbolFile];
+ STAssertNotNil(d1, @"Output breakpad symbol file not found");
+
+ STAssertTrue([d isEqualToData:d1],
+ @"Symbol files were not equal!",nil);
+}
+@end
diff --git a/toolkit/crashreporter/breakpad-client/mac/handler/testcases/testdata/dump_syms_dwarf_data b/toolkit/crashreporter/breakpad-client/mac/handler/testcases/testdata/dump_syms_dwarf_data
new file mode 100644
index 0000000000..5be17aeedc
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/mac/handler/testcases/testdata/dump_syms_dwarf_data
Binary files differ
diff --git a/toolkit/crashreporter/breakpad-client/mac/handler/testcases/testdata/dump_syms_i386_breakpad.sym b/toolkit/crashreporter/breakpad-client/mac/handler/testcases/testdata/dump_syms_i386_breakpad.sym
new file mode 100644
index 0000000000..bca43c1037
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/mac/handler/testcases/testdata/dump_syms_i386_breakpad.sym
@@ -0,0 +1,5300 @@
+MODULE mac x86 94BF873C47A73BC07125291390B4C5F10 dump_syms_dwarf_data
+FILE 1 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/libkern/i386/OSByteOrder.h
+FILE 2 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/architecture/byte_order.h
+FILE 3 /g/code/breakpad-staging/src/tools/mac/dump_syms/../../../common/mac/dump_syms.mm
+FILE 4 /Developer/SDKs/MacOSX10.4u.sdk/System/Library/Frameworks/Foundation.framework/Headers/NSRange.h
+FILE 5 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/new
+FILE 6 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/ext/hash_fun.h
+FILE 7 ../../../common/mac/dwarf/dwarf2reader.h
+FILE 8 ../../../common/mac/file_id.h
+FILE 9 ../../../common/mac/dwarf/functioninfo.h
+FILE 10 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/stl_tree.h
+FILE 11 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/stl_iterator.h
+FILE 12 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/ext/hashtable.h
+FILE 13 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/stl_pair.h
+FILE 14 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/ext/new_allocator.h
+FILE 15 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/allocator.h
+FILE 16 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/stl_vector.h
+FILE 17 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/stl_iterator_base_types.h
+FILE 18 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/stl_iterator_base_funcs.h
+FILE 19 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/stl_algo.h
+FILE 20 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/stl_map.h
+FILE 21 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/stl_construct.h
+FILE 22 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/stl_function.h
+FILE 23 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/ext/hash_map
+FILE 24 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/basic_string.h
+FILE 25 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/stl_algobase.h
+FILE 26 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/stl_list.h
+FILE 27 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/list.tcc
+FILE 28 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/stl_uninitialized.h
+FILE 29 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/vector.tcc
+FILE 30 /g/code/breakpad-staging/src/tools/mac/dump_syms/../../../common/mac/dwarf/functioninfo.cc
+FILE 31 ../../../common/mac/dwarf/dwarf2reader.h
+FILE 32 ../../../common/mac/dwarf/functioninfo.h
+FILE 33 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/stl_pair.h
+FILE 34 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/ext/hashtable.h
+FILE 35 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/memory
+FILE 36 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/ext/new_allocator.h
+FILE 37 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/basic_string.h
+FILE 38 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/stl_iterator.h
+FILE 39 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/stl_vector.h
+FILE 40 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/stl_tree.h
+FILE 41 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/stl_function.h
+FILE 42 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/ext/hash_map
+FILE 43 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/stl_construct.h
+FILE 44 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/stl_algobase.h
+FILE 45 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/stl_map.h
+FILE 46 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/stl_uninitialized.h
+FILE 47 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/vector.tcc
+FILE 48 /g/code/breakpad-staging/src/tools/mac/dump_syms/dump_syms_tool.mm
+FILE 49 /g/code/breakpad-staging/src/tools/mac/dump_syms/../../../common/mac/file_id.cc
+FILE 50 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/architecture/byte_order.h
+FILE 51 /g/code/breakpad-staging/src/tools/mac/dump_syms/../../../common/mac/macho_id.cc
+FILE 52 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/libkern/i386/OSByteOrder.h
+FILE 53 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/architecture/byte_order.h
+FILE 54 /g/code/breakpad-staging/src/tools/mac/dump_syms/../../../common/mac/macho_walker.cc
+FILE 55 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/libkern/i386/OSByteOrder.h
+FILE 56 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/architecture/byte_order.h
+FILE 57 /g/code/breakpad-staging/src/tools/mac/dump_syms/../../../common/mac/macho_utilities.cc
+FILE 58 /g/code/breakpad-staging/src/tools/mac/dump_syms/../../../common/mac/dwarf/bytereader.cc
+FILE 59 ../../../common/mac/dwarf/bytereader-inl.h
+FILE 60 /g/code/breakpad-staging/src/tools/mac/dump_syms/../../../common/mac/dwarf/dwarf2reader.cc
+FILE 61 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/stl_algobase.h
+FILE 62 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/stl_deque.h
+FILE 63 ../../../common/mac/dwarf/bytereader.h
+FILE 64 ../../../common/mac/dwarf/bytereader-inl.h
+FILE 65 ../../../common/mac/dwarf/line_state_machine.h
+FILE 66 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/stl_list.h
+FILE 67 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/memory
+FILE 68 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/ext/new_allocator.h
+FILE 69 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/allocator.h
+FILE 70 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/stl_pair.h
+FILE 71 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/stl_vector.h
+FILE 72 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/stl_iterator.h
+FILE 73 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/stl_construct.h
+FILE 74 ../../../common/mac/dwarf/dwarf2reader.h
+FILE 75 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/stl_stack.h
+FILE 76 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/deque.tcc
+FILE 77 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/list.tcc
+FILE 78 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/vector.tcc
+FILE 79 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/stl_uninitialized.h
+FILE 80 /var/tmp/gcc/gcc-5484~1/src/gcc/libgcc2.c
+FUNC 162a 28 0 _OSSwapInt16
+162a 10 44 55
+163a 16 46 55
+1650 2 47 55
+FUNC 1652 1c 0 _OSSwapInt32
+1652 f 53 55
+1661 8 55 55
+1669 3 56 55
+166c 2 57 55
+FUNC 166e 2b 0 _OSSwapInt64
+166e 12 64 55
+1680 11 69 55
+1691 6 70 55
+1697 2 71 55
+1699 1 71 55
+FUNC 169a 1e 0 NXSwapShort
+169a 10 43 56
+16aa c 45 56
+16b6 2 46 56
+FUNC 16b8 19 0 NXSwapInt
+16b8 f 52 56
+16c7 8 54 56
+16cf 2 55 56
+16d1 1 55 56
+FUNC 16d2 19 0 NXSwapLong
+16d2 f 61 56
+16e1 8 63 56
+16e9 2 64 56
+16eb 1 64 56
+FUNC 16ec 1f 0 NXSwapLongLong
+16ec 12 70 56
+16fe b 72 56
+1709 2 73 56
+170b 1 73 56
+FUNC 170c 181 0 -[DumpSymbols convertCPlusPlusSymbols:]
+170c 14 128 3
+1720 54 130 3
+1774 f 132 3
+1783 7 133 3
+178a 1a 136 3
+17a4 5 138 3
+17a9 1a 139 3
+17c3 23 140 3
+17e6 7 141 3
+17ed 44 142 3
+1831 1e 145 3
+184f 29 138 3
+1878 b 148 3
+1883 3 150 3
+1886 7 151 3
+188d 1 151 3
+FUNC 188e 323 0 -[DumpSymbols convertSymbols]
+188e 14 154 3
+18a2 1f 155 3
+18c1 3e 156 3
+18ff 2b 160 3
+192a c 162 3
+1936 43 164 3
+1979 2a 165 3
+19a3 20 168 3
+19c3 d 169 3
+19d0 1e 171 3
+19ee 11 162 3
+19ff 7 181 3
+1a06 6 182 3
+1a0c 5 184 3
+1a11 15 185 3
+1a26 6 18 4
+1a2c 6 19 4
+1a32 6 20 4
+1a38 6 185 3
+1a3e 28 186 3
+1a66 21 187 3
+1a87 1a 188 3
+1aa1 a 190 3
+1aab c 194 3
+1ab7 43 198 3
+1afa 21 199 3
+1b1b 20 202 3
+1b3b 2e 203 3
+1b69 1e 194 3
+1b87 c 184 3
+1b93 17 207 3
+1baa 7 208 3
+1bb1 1 208 3
+FUNC 1bb2 4a2 0 -[DumpSymbols addFunction:line:address:section:]
+1bb2 21 211 3
+1bd3 2f 212 3
+1c02 e 214 3
+1c10 4 219 3
+1c14 2a 221 3
+1c3e 22 223 3
+1c60 6 224 3
+1c66 2a 225 3
+1c90 4 226 3
+1c94 2e 230 3
+1cc2 2e 233 3
+1cf0 2e 236 3
+1d1e a 239 3
+1d28 2b 253 3
+1d53 e 254 3
+1d61 3c 255 3
+1d9d 22 32 4
+1dbf 3 256 3
+1dc2 6 259 3
+1dc8 a 260 3
+1dd2 3c 261 3
+1e0e 25 262 3
+1e33 2a 263 3
+1e5d 22 265 3
+1e7f 26 270 3
+1ea5 6 272 3
+1eab 37 273 3
+1ee2 2a 274 3
+1f0c 17 275 3
+1f23 43 278 3
+1f66 2e 279 3
+1f94 23 282 3
+1fb7 43 285 3
+1ffa 52 287 3
+204c 8 289 3
+FUNC 2054 5a4 0 -[DumpSymbols processSymbolItem:stringTable:]
+2054 18 292 3
+206c 8 293 3
+2074 4 294 3
+2078 16 297 3
+208e c 298 3
+209a f 300 3
+20a9 b 301 3
+20b4 16 303 3
+20ca 4d 309 3
+2117 38 311 3
+214f 30 315 3
+217f 60 317 3
+21df d 322 3
+21ec 2b 325 3
+2217 3a 327 3
+2251 f 332 3
+2260 2d 333 3
+228d 1a 334 3
+22a7 32 335 3
+22d9 20 342 3
+22f9 c 343 3
+2305 24 348 3
+2329 a 349 3
+2333 3c 350 3
+236f 2a 352 3
+2399 1c 353 3
+23b5 9 354 3
+23be f 356 3
+23cd 2d 357 3
+23fa 2f 358 3
+2429 20 360 3
+2449 c 361 3
+2455 7 363 3
+245c 21 365 3
+247d 4a 368 3
+24c7 9 370 3
+24d0 1a 371 3
+24ea 4b 372 3
+2535 4 373 3
+2539 5 371 3
+253e 29 374 3
+2567 2d 376 3
+2594 4b 378 3
+25df 4 379 3
+25e3 a 382 3
+25ed b 383 3
+FUNC 25f8 c9 0 -[DumpSymbols loadSymbolInfo:offset:]
+25f8 13 391 3
+260b 2b 392 3
+2636 2a 393 3
+2660 2d 395 3
+268d 2e 398 3
+26bb 6 399 3
+26c1 1 399 3
+FUNC 26c2 2be 0 -[DumpSymbols loadSTABSSymbolInfo:offset:]
+26c2 16 537 3
+26d8 9 538 3
+26e1 10 539 3
+26f1 2e 540 3
+271f 9 542 3
+2728 22 543 3
+274a 4 544 3
+274e a 546 3
+2758 3c 547 3
+2794 c 549 3
+27a0 e 550 3
+27ae 6 551 3
+27b4 25 552 3
+27d9 25 553 3
+27fe 25 554 3
+2823 c 555 3
+282f c 556 3
+283b c 559 3
+2847 23 562 3
+286a a 563 3
+2874 a 564 3
+287e 2e 565 3
+28ac 39 566 3
+28e5 2e 570 3
+2913 4 571 3
+2917 17 559 3
+292e 25 575 3
+2953 9 576 3
+295c 17 549 3
+2973 4 579 3
+2977 9 580 3
+FUNC 2980 28a 0 -[DumpSymbols loadSymbolInfo64:offset:]
+2980 16 583 3
+2996 9 585 3
+299f 10 586 3
+29af 2e 587 3
+29dd 9 589 3
+29e6 22 590 3
+2a08 4 591 3
+2a0c c 593 3
+2a18 e 594 3
+2a26 6 595 3
+2a2c 25 596 3
+2a51 25 597 3
+2a76 25 598 3
+2a9b 9 599 3
+2aa4 c 600 3
+2ab0 c 603 3
+2abc 17 604 3
+2ad3 23 609 3
+2af6 a 610 3
+2b00 a 611 3
+2b0a 2e 612 3
+2b38 37 613 3
+2b6f 2e 615 3
+2b9d 4 616 3
+2ba1 17 603 3
+2bb8 25 620 3
+2bdd 9 621 3
+2be6 17 593 3
+2bfd 4 624 3
+2c01 9 625 3
+FUNC 2c0a 199 0 -[DumpSymbols loadSymbolInfoForArchitecture]
+2c0a 13 628 3
+2c1d 41 630 3
+2c5e 2b 631 3
+2c89 1a 632 3
+2ca3 40 634 3
+2ce3 40 635 3
+2d23 5f 637 3
+2d82 17 639 3
+2d99 4 640 3
+2d9d 6 641 3
+2da3 1 641 3
+FUNC 2da4 3e5 0 -[DumpSymbols loadHeader:offset:]
+2da4 18 728 3
+2dbc 9 729 3
+2dc5 10 730 3
+2dd5 2e 731 3
+2e03 9 733 3
+2e0c 2b 734 3
+2e37 1e 736 3
+2e55 c 738 3
+2e61 e 739 3
+2e6f 6 740 3
+2e75 50 742 3
+2ec5 2e 743 3
+2ef3 2e 744 3
+2f21 2e 745 3
+2f4f 20 746 3
+2f6f 1b7 755 3
+3126 9 757 3
+312f 25 761 3
+3154 9 762 3
+315d 17 738 3
+3174 a 765 3
+317e b 766 3
+3189 1 766 3
+FUNC 318a 41d 0 -[DumpSymbols loadHeader64:offset:]
+318a 18 769 3
+31a2 9 771 3
+31ab 10 772 3
+31bb 2e 773 3
+31e9 9 775 3
+31f2 c 777 3
+31fe 2b 778 3
+3229 e 779 3
+3237 6 780 3
+323d 50 781 3
+328d 49 782 3
+32d6 49 783 3
+331f 2e 784 3
+334d 9 785 3
+3356 29 786 3
+337f 1c5 794 3
+3544 9 795 3
+354d 25 799 3
+3572 9 800 3
+357b 17 777 3
+3592 a 803 3
+359c b 804 3
+35a7 1 804 3
+FUNC 35a8 52a 0 -[DumpSymbols loadModuleInfo]
+35a8 14 807 3
+35bc e 808 3
+35ca 41 810 3
+360b 1a 811 3
+3625 6 812 3
+362b 6 814 3
+3631 17 815 3
+3648 c 816 3
+3654 29 820 3
+367d 29 821 3
+36a6 29 822 3
+36cf 35 824 3
+3704 12 826 3
+3716 17 827 3
+372d c 828 3
+3739 3c 832 3
+3775 a 834 3
+377f 9 836 3
+3788 25 837 3
+37ad c 839 3
+37b9 54 840 3
+380d 57 841 3
+3864 57 842 3
+38bb 57 843 3
+3912 57 844 3
+3969 1c 846 3
+3985 4b 847 3
+39d0 49 849 3
+3a19 13 839 3
+3a2c 6 851 3
+3a32 3c 852 3
+3a6e 3a 854 3
+3aa8 17 857 3
+3abf c 858 3
+3acb 7 859 3
+FUNC 3ad2 b6 0 WriteFormat
+3ad2 10 862 3
+3ae2 6 867 3
+3ae8 24 868 3
+3b0c 27 869 3
+3b33 40 870 3
+3b73 c 873 3
+3b7f 9 874 3
+FUNC 3b88 35 0 -[DumpSymbols availableArchitectures]
+3b88 13 1140 3
+3b9b 1c 1141 3
+3bb7 6 1142 3
+3bbd 1 1142 3
+FUNC 3bbe 1b4 0 -[DumpSymbols setArchitecture:]
+3bbe 13 1158 3
+3bd1 1a 1159 3
+3beb 4 1160 3
+3bef 2a 1162 3
+3c19 9 1163 3
+3c22 2a 1165 3
+3c4c 9 1166 3
+3c55 9 1167 3
+3c5e 2a 1169 3
+3c88 6 1170 3
+3c8e 2a 1172 3
+3cb8 6 1173 3
+3cbe 2a 1175 3
+3ce8 4 1176 3
+3cec 6 1179 3
+3cf2 2c 1180 3
+3d1e 9 1181 3
+3d27 1c 1183 3
+3d43 1f 1184 3
+3d62 a 1187 3
+3d6c 6 1188 3
+FUNC 3d72 14 0 -[DumpSymbols architecture]
+3d72 c 1191 3
+3d7e 6 1192 3
+3d84 2 1193 3
+FUNC 3d86 e7 0 -[DumpSymbols writeSymbolFile:]
+3d86 13 1196 3
+3d99 1a 1197 3
+3db3 48 1200 3
+3dfb 9 1201 3
+3e04 1e 1203 3
+3e22 6 1205 3
+3e28 9 1206 3
+3e31 21 1208 3
+3e52 b 1210 3
+3e5d a 1212 3
+3e67 6 1213 3
+3e6d 1 1213 3
+FUNC 3e6e 65 0 -[MachSection initWithMachSection:andNumber:]
+3e6e 13 1219 3
+3e81 37 1220 3
+3eb8 9 1221 3
+3ec1 9 1222 3
+3eca 3 1225 3
+3ecd 6 1226 3
+3ed3 1 1226 3
+FUNC 3ed4 14 0 -[MachSection sectionPointer]
+3ed4 c 1228 3
+3ee0 6 1229 3
+3ee6 2 1230 3
+FUNC 3ee8 14 0 -[MachSection sectionNumber]
+3ee8 c 1232 3
+3ef4 6 1233 3
+3efa 2 1234 3
+FUNC 3efc 17c 0 -[DumpSymbols processDWARFSourceFileInfo:]
+3efc 14 459 3
+3f10 a 460 3
+3f1a 3c 461 3
+3f56 20 463 3
+3f76 5 464 3
+3f7b 3a 465 3
+3fb5 1d 466 3
+3fd2 3a 467 3
+400c 2a 468 3
+4036 3b 464 3
+4071 7 471 3
+FUNC 4078 1d7 0 DumpFunctionMap(std::map<unsigned long long, dwarf2reader::FunctionInfo*, std::less<unsigned long long>, std::allocator<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> > >)
+4078 15 82 3
+408d 13 83 3
+40a0 1e 85 3
+40be 42 89 3
+4100 20 90 3
+4120 2b 91 3
+414b 1a 92 3
+4165 23 93 3
+4188 46 96 3
+41ce 46 99 3
+4214 33 83 3
+4247 8 102 3
+424f 1 102 3
+FUNC 4250 3ef 0 -[DumpSymbols processDWARFFunctionInfo:]
+4250 15 473 3
+4265 25 474 3
+428a 1e 476 3
+42a8 a 480 3
+42b2 3c 481 3
+42ee 3d 483 3
+432b 23 485 3
+434e 26 487 3
+4374 6 489 3
+437a 37 490 3
+43b1 2a 491 3
+43db 17 492 3
+43f2 30 496 3
+4422 3d 497 3
+445f 2e 498 3
+448d 30 502 3
+44bd 64 504 3
+4521 34 507 3
+4555 9d 509 3
+45f2 45 474 3
+4637 8 513 3
+463f 1 513 3
+FUNC 4640 1f5 0 -[DumpSymbols processDWARFLineNumberInfo:]
+4640 15 515 3
+4655 25 516 3
+467a 39 520 3
+46b3 26 521 3
+46d9 6 523 3
+46df 37 524 3
+4716 2a 525 3
+4740 17 526 3
+4757 30 529 3
+4787 61 531 3
+47e8 45 516 3
+482d 8 534 3
+4835 1 534 3
+FUNC 4836 10f 0 -[DumpSymbols dealloc]
+4836 13 1145 3
+4849 1c 1146 3
+4865 1c 1147 3
+4881 1c 1148 3
+489d 1c 1149 3
+48b9 1c 1150 3
+48d5 1c 1151 3
+48f1 25 1152 3
+4916 29 1154 3
+493f 6 1155 3
+4945 1 1155 3
+FUNC 4946 512 0 -[DumpSymbols loadDWARFSymbolInfo:offset:]
+4946 17 402 3
+495d 9 405 3
+4966 10 406 3
+4976 2b 408 3
+49a1 38 409 3
+49d9 3a 410 3
+4a13 2e 411 3
+4a41 31 416 3
+4a72 e 418 3
+4a80 24 420 3
+4aa4 5 422 3
+4aa9 b 424 3
+4ab4 b 425 3
+4abf e 426 3
+4acd 2b 427 3
+4af8 2b 428 3
+4b23 2c 431 3
+4b4f 52 439 3
+4ba1 34 444 3
+4bd5 1a 446 3
+4bef 21 451 3
+4c10 1e 452 3
+4c2e 21 453 3
+4c4f 40 422 3
+4c8f 6 453 3
+4c95 170 422 3
+4e05 43 456 3
+4e48 10 457 3
+FUNC 4e58 4fd 0 -[DumpSymbols generateSectionDictionary:]
+4e58 18 663 3
+4e70 10 665 3
+4e80 2e 666 3
+4eae 9 668 3
+4eb7 2b 669 3
+4ee2 7 670 3
+4ee9 2e 672 3
+4f17 d 676 3
+4f24 32 678 3
+4f56 29 680 3
+4f7f a 684 3
+4f89 3c 685 3
+4fc5 31 688 3
+4ff6 5d 689 3
+5053 26 692 3
+5079 21 694 3
+509a c 698 3
+50a6 e 699 3
+50b4 6 700 3
+50ba 9 701 3
+50c3 2e 702 3
+50f1 c 704 3
+50fd 3c 706 3
+5139 66 709 3
+519f 1c 712 3
+51bb fb 714 3
+52b6 6 717 3
+52bc 5 718 3
+52c1 19 704 3
+52da 25 714 3
+52ff 2e 722 3
+532d 9 723 3
+5336 17 698 3
+534d 8 725 3
+5355 1 725 3
+FUNC 5356 24a 0 -[DumpSymbols getSectionMapForArchitecture:]
+5356 14 643 3
+536a 43 645 3
+53ad 1a 648 3
+53c7 1c 645 3
+53e3 18 648 3
+53fb 40 650 3
+543b 20 651 3
+545b 17 652 3
+5472 16 651 3
+5488 cb 652 3
+5553 11 654 3
+5564 32 657 3
+5596 a 658 3
+FUNC 55a0 3fe 0 -[DumpSymbols initWithContentsOfFile:]
+55a0 14 1056 3
+55b4 3b 1057 3
+55ef 44 1059 3
+5633 17 1060 3
+564a c 1061 3
+5656 1f 1064 3
+5675 2b 1067 3
+56a0 a 1069 3
+56aa 35 1083 3
+56df 2 1087 3
+56e1 1a 1088 3
+56fb 3d 1087 3
+5738 33 1092 3
+576b 6 1094 3
+5771 e 1095 3
+577f 17 1096 3
+5796 c 1097 3
+57a2 1c 1101 3
+57be 1f 1103 3
+57dd 18 1104 3
+57f5 23 1107 3
+5818 25 1109 3
+583d 1c 1107 3
+5859 17 1110 3
+5870 c 1111 3
+587c 2a 1115 3
+58a6 8 1116 3
+58ae a 1118 3
+58b8 9 1119 3
+58c1 d 1122 3
+58ce 29 1124 3
+58f7 20 1126 3
+5917 20 1128 3
+5937 57 1132 3
+598e 9 1136 3
+5997 7 1137 3
+FUNC 599e d74 0 -[DumpSymbols outputSymbolFile:]
+599e 18 877 3
+59b6 2e 879 3
+59e4 30 880 3
+5a14 5d 882 3
+5a71 30 883 3
+5aa1 5d 885 3
+5afe 2e 888 3
+5b2c 38 891 3
+5b64 46 892 3
+5baa 26 893 3
+5bd0 20 895 3
+5bf0 20 904 3
+5c10 30 898 3
+5c40 f 899 3
+5c4f 1e 904 3
+5c6d 17 907 3
+5c84 17 908 3
+5c9b 44 911 3
+5cdf 44 914 3
+5d23 a 917 3
+5d2d 36 921 3
+5d63 30 923 3
+5d93 9 18 4
+5d9c 9 19 4
+5da5 c 20 4
+5db1 56 923 3
+5e07 74 925 3
+5e7b f 927 3
+5e8a 44 932 3
+5ece 20 933 3
+5eee c 934 3
+5efa 4e 935 3
+5f48 41 936 3
+5f89 f 937 3
+5f98 14 934 3
+5fac 7 941 3
+5fb3 14 942 3
+5fc7 14 943 3
+5fdb 1d 946 3
+5ff8 c 948 3
+6004 24 949 3
+6028 29 950 3
+6051 9 953 3
+605a 28 954 3
+6082 2e 955 3
+60b0 1e 957 3
+60ce 7 959 3
+60d5 26 962 3
+60fb 2a 963 3
+6125 2a 964 3
+614f 6 966 3
+6155 2a 967 3
+617f e 971 3
+618d 43 972 3
+61d0 4c 974 3
+621c 8 975 3
+6224 2e 979 3
+6252 2e 982 3
+6280 2e 985 3
+62ae 2e 988 3
+62dc 2e 991 3
+630a 2e 994 3
+6338 2e 997 3
+6366 2e 1000 3
+6394 54 1004 3
+63e8 c 1005 3
+63f4 e 1007 3
+6402 27 1008 3
+6429 8 1009 3
+6431 34 1010 3
+6465 24 1012 3
+6489 2 1013 3
+648b 2a 1017 3
+64b5 a 1019 3
+64bf 14 1020 3
+64d3 1d 1021 3
+64f0 a 1025 3
+64fa 32 1026 3
+652c 33 1028 3
+655f c 1029 3
+656b 55 1034 3
+65c0 f 1036 3
+65cf 16 1040 3
+65e5 61 1041 3
+6646 f 1043 3
+6655 47 1046 3
+669c c 1048 3
+66a8 11 948 3
+66b9 4e 1052 3
+6707 b 1053 3
+FUNC 6712 11 0 operator new(unsigned long, void*)
+6712 c 94 5
+671e 5 94 5
+6723 1 94 5
+FUNC 6724 e 0 operator delete(void*, void*)
+6724 c 98 5
+6730 2 98 5
+673e 7 76 6
+6745 2 77 6
+6747 1a 78 6
+6761 d 77 6
+676e 3 79 6
+6771 2 80 6
+6773 1 80 6
+6780 d 95 6
+678d 1 95 6
+678e 13 127 74
+67a1 2a 127 74
+67cb 1 127 74
+67cc 13 127 74
+67df 2a 127 74
+6809 1 127 74
+680a 13 127 74
+681d 2a 127 74
+6847 1 127 74
+FUNC 6848 e 0 dwarf2reader::LineInfoHandler::DefineDir(std::string const&, unsigned int)
+6848 c 131 7
+6854 2 131 74
+FUNC 6856 26 0 dwarf2reader::LineInfoHandler::DefineFile(std::string const&, int, unsigned int, unsigned long long, unsigned long long)
+6856 24 142 7
+687a 2 142 74
+FUNC 687c 1a 0 dwarf2reader::LineInfoHandler::AddLine(unsigned long long, unsigned int, unsigned int, unsigned int)
+687c 18 150 7
+6894 2 150 74
+6896 12 299 74
+68a8 12 299 74
+68ba 13 301 74
+68cd 2a 301 74
+68f7 1 301 74
+68f8 13 301 74
+690b 2a 301 74
+6935 1 301 74
+6936 13 301 74
+6949 2a 301 74
+6973 1 301 74
+FUNC 6974 44 0 dwarf2reader::Dwarf2Handler::StartCompilationUnit(unsigned long long, unsigned char, unsigned char, unsigned long long, unsigned char)
+6974 39 308 7
+69ad b 308 74
+FUNC 69b8 1f 0 dwarf2reader::Dwarf2Handler::StartDIE(unsigned long long, dwarf2reader::DwarfTag, std::list<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm>, std::allocator<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> > > const&)
+69b8 18 314 7
+69d0 7 314 74
+69d7 1 314 74
+FUNC 69d8 26 0 dwarf2reader::Dwarf2Handler::ProcessAttributeUnsigned(unsigned long long, dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm, unsigned long long)
+69d8 24 323 7
+69fc 2 323 74
+FUNC 69fe 26 0 dwarf2reader::Dwarf2Handler::ProcessAttributeSigned(unsigned long long, dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm, long long)
+69fe 24 332 7
+6a22 2 332 74
+FUNC 6a24 26 0 dwarf2reader::Dwarf2Handler::ProcessAttributeBuffer(unsigned long long, dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm, char const*, unsigned long long)
+6a24 24 345 7
+6a48 2 345 74
+FUNC 6a4a 1a 0 dwarf2reader::Dwarf2Handler::ProcessAttributeString(unsigned long long, dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm, std::string const&)
+6a4a 18 354 7
+6a62 2 354 74
+FUNC 6a64 1a 0 dwarf2reader::Dwarf2Handler::EndDIE(unsigned long long)
+6a64 18 360 7
+6a7c 2 360 74
+6a7e c 44 8
+6a8a 2 44 8
+6a8c 13 55 32
+6a9f 35 55 32
+6ad4 13 91 32
+6ae7 73 96 32
+6b5a 13 98 32
+6b6d 35 98 32
+6bae 1a 75 3
+6bc8 2 76 3
+FUNC 6bca 20 0 std::_Rb_tree_const_iterator<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> >::operator!=(std::_Rb_tree_const_iterator<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> > const&) const
+6bca c 287 10
+6bd6 14 288 40
+FUNC 6bea 16 0 std::_Rb_tree_const_iterator<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> >::operator->() const
+6bea c 249 10
+6bf6 a 250 40
+6c0c 7 614 72
+6c13 1 614 72
+6c14 c 241 40
+6c20 c 242 40
+FUNC 6c2c 16 0 std::_Rb_tree_const_iterator<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> >::operator*() const
+6c2c c 245 11
+6c38 a 246 40
+6c42 c 241 40
+6c4e c 242 40
+FUNC 6c5a 20 0 std::_Rb_tree_const_iterator<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > >::operator!=(std::_Rb_tree_const_iterator<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > > const&) const
+6c5a c 287 11
+6c66 14 288 40
+FUNC 6c7a 16 0 std::_Rb_tree_const_iterator<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > >::operator->() const
+6c7a c 249 11
+6c86 a 250 40
+6c90 c 185 34
+6c9c 18 186 34
+6cc0 14 204 34
+6cd4 c 69 70
+6ce0 d 69 70
+6ced 1 69 70
+6cee c 89 70
+6cfa 20 90 70
+6d1a c 69 70
+6d26 d 69 70
+6d33 1 69 70
+6d34 c 69 70
+6d40 d 69 70
+6d4d 1 69 70
+FUNC 6d4e 25 0 std::_Rb_tree_const_iterator<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> >::operator++()
+6d4e c 253 13
+6d5a 14 255 40
+6d6e 5 256 40
+6d73 1 256 40
+FUNC 6d74 25 0 std::_Rb_tree_const_iterator<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > >::operator++()
+6d74 c 253 13
+6d80 14 255 40
+6d94 5 256 40
+6d99 1 256 40
+FUNC 6d9a 14 0 std::_Rb_tree<unsigned long long, std::pair<unsigned long long const, dwarf2reader::FunctionInfo*>, std::_Select1st<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> >, std::less<unsigned long long>, std::allocator<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> > >::_M_begin()
+6d9a c 461 13
+6da6 8 462 40
+FUNC 6dae 14 0 std::_Rb_tree<unsigned long long, std::pair<unsigned long long const, std::pair<std::string, unsigned int> >, std::_Select1st<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > >, std::less<unsigned long long>, std::allocator<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > > >::_M_begin()
+6dae c 461 13
+6dba 8 462 40
+6dc2 c 65 68
+6dce 2 65 68
+6dd0 c 72 68
+6ddc 2 72 68
+6dde c 97 69
+6dea d 97 69
+6df7 1 97 69
+6df8 c 105 69
+6e04 d 105 69
+6e11 1 105 69
+6e12 c 105 69
+6e1e d 105 69
+6e2b 1 105 69
+6e2c c 67 68
+6e38 2 67 68
+6e3a c 99 69
+6e46 14 100 69
+6e5a c 99 69
+6e66 14 100 69
+FUNC 6e7a 2b 0 std::_Vector_base<dwarf2reader::SourceFileInfo, std::allocator<dwarf2reader::SourceFileInfo> >::get_allocator() const
+6e7a 10 93 16
+6e8a 1b 94 71
+6ea5 1 94 71
+6ea6 c 65 68
+6eb2 2 65 68
+6eb4 c 72 68
+6ec0 2 72 68
+6ec2 c 97 69
+6ece d 97 69
+6edb 1 97 69
+6edc c 105 69
+6ee8 d 105 69
+6ef5 1 105 69
+6ef6 c 105 69
+6f02 d 105 69
+6f0f 1 105 69
+6f10 c 67 68
+6f1c 2 67 68
+6f1e c 99 69
+6f2a 14 100 69
+6f3e c 99 69
+6f4a 14 100 69
+FUNC 6f5e 2b 0 std::_Vector_base<std::string, std::allocator<std::string> >::get_allocator() const
+6f5e 10 93 16
+6f6e 1b 94 71
+6f89 1 94 71
+6f8a c 603 72
+6f96 c 603 72
+FUNC 6fa2 23 0 std::vector<dwarf2reader::SourceFileInfo, std::allocator<dwarf2reader::SourceFileInfo> >::begin()
+6fa2 c 333 16
+6fae 17 334 71
+6fc5 1 334 71
+FUNC 6fc6 26 0 std::vector<dwarf2reader::SourceFileInfo, std::allocator<dwarf2reader::SourceFileInfo> >::end()
+6fc6 c 351 16
+6fd2 1a 352 71
+6ff8 5 666 72
+6ffd 1 666 72
+6ffe c 608 72
+700a 14 609 72
+702a 5 666 72
+702f 1 666 72
+FUNC 7030 35 0 bool __gnu_cxx::operator!=<dwarf2reader::SourceFileInfo const*, dwarf2reader::SourceFileInfo*, std::vector<dwarf2reader::SourceFileInfo, std::allocator<dwarf2reader::SourceFileInfo> > >(__gnu_cxx::__normal_iterator<dwarf2reader::SourceFileInfo const*, std::vector<dwarf2reader::SourceFileInfo, std::allocator<dwarf2reader::SourceFileInfo> > > const&, __gnu_cxx::__normal_iterator<dwarf2reader::SourceFileInfo*, std::vector<dwarf2reader::SourceFileInfo, std::allocator<dwarf2reader::SourceFileInfo> > > const&)
+7030 d 693 16
+703d 28 694 72
+7065 1 694 72
+7066 c 603 72
+7072 c 603 72
+708a 27 629 72
+70b1 1 629 72
+70b2 c 84 70
+70be 1f 85 70
+70dd 1 85 70
+FUNC 70de 32 0 std::pair<std::string, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> std::make_pair<std::string, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*>(std::string, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*)
+70de 10 144 16
+70ee 22 145 70
+711c a 190 34
+7132 d 194 34
+713f 1 194 34
+7140 c 84 70
+714c 17 85 70
+7163 1 85 70
+FUNC 7164 2d 0 std::pair<char const*, unsigned long> std::make_pair<char const*, unsigned long>(char const*, unsigned long)
+7164 c 144 16
+7170 21 145 70
+7191 1 145 70
+7192 c 84 70
+719e 1d 85 70
+71bb 1 85 70
+FUNC 71bc 30 0 std::pair<char*, std::pair<char const*, unsigned long> > std::make_pair<char*, std::pair<char const*, unsigned long> >(char*, std::pair<char const*, unsigned long>)
+71bc 10 144 16
+71cc 20 145 70
+71ec c 89 70
+71f8 20 90 70
+7218 d 89 70
+7225 70 90 70
+7295 1 90 70
+FUNC 7296 12 0 std::iterator_traits<unsigned long const*>::iterator_category std::__iterator_category<unsigned long const*>(unsigned long const* const&)
+7296 c 164 17
+72a2 6 165 17
+FUNC 72a8 1d 0 std::iterator_traits<unsigned long const*>::difference_type std::__distance<unsigned long const*>(unsigned long const*, unsigned long const*, std::random_access_iterator_tag)
+72a8 c 92 18
+72b4 11 97 18
+72c5 1 97 18
+FUNC 72c6 33 0 std::iterator_traits<unsigned long const*>::difference_type std::distance<unsigned long const*>(unsigned long const*, unsigned long const*)
+72c6 c 114 18
+72d2 27 118 18
+72f9 1 118 18
+FUNC 72fa 20 0 void std::__advance<unsigned long const*, int>(unsigned long const*&, int, std::random_access_iterator_tag)
+72fa c 150 18
+7306 14 155 18
+FUNC 731a 33 0 void std::advance<unsigned long const*, int>(unsigned long const*&, int)
+731a c 172 18
+7326 27 175 18
+734d 1 175 18
+FUNC 734e 7a 0 unsigned long const* std::lower_bound<unsigned long const*, unsigned long>(unsigned long const*, unsigned long const*, unsigned long const&)
+734e c 2625 19
+735a 15 2642 19
+736f 2 2646 19
+7371 8 2648 19
+7379 6 2649 19
+737f 12 2650 19
+7391 e 2651 19
+739f 6 2653 19
+73a5 4 2654 19
+73a9 e 2655 19
+73b7 6 2658 19
+73bd 6 2646 19
+73c3 5 2660 19
+73db b 227 34
+73e6 e 228 34
+73f4 1c 229 34
+7410 20 230 34
+7430 6 231 34
+7436 c 72 68
+7442 2 72 68
+7444 c 105 69
+7450 d 105 69
+745d 1 105 69
+745e c 105 69
+746a d 105 69
+7477 1 105 69
+7478 c 80 71
+7484 d 80 71
+7491 1 80 71
+7492 c 67 68
+749e 2 67 68
+74a0 c 99 69
+74ac 14 100 69
+FUNC 74c0 2b 0 std::_Vector_base<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> >::get_allocator() const
+74c0 10 93 19
+74d0 1b 94 71
+74eb 1 94 71
+74ec c 238 40
+74f8 a 239 40
+FUNC 7502 26 0 std::_Rb_tree<unsigned long long, std::pair<unsigned long long const, dwarf2reader::FunctionInfo*>, std::_Select1st<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> >, std::less<unsigned long long>, std::allocator<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> > >::begin() const
+7502 c 585 19
+750e 1a 588 40
+FUNC 7528 19 0 std::map<unsigned long long, dwarf2reader::FunctionInfo*, std::less<unsigned long long>, std::allocator<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> > >::begin() const
+7528 c 243 20
+7534 d 244 45
+7541 1 244 45
+FUNC 7542 26 0 std::_Rb_tree<unsigned long long, std::pair<unsigned long long const, dwarf2reader::FunctionInfo*>, std::_Select1st<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> >, std::less<unsigned long long>, std::allocator<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> > >::end() const
+7542 c 596 20
+754e 1a 597 40
+FUNC 7568 19 0 std::map<unsigned long long, dwarf2reader::FunctionInfo*, std::less<unsigned long long>, std::allocator<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> > >::end() const
+7568 c 260 20
+7574 d 261 45
+7581 1 261 45
+7582 c 65 68
+758e 2 65 68
+7590 c 72 68
+759c 2 72 68
+759e c 97 69
+75aa d 97 69
+75b7 1 97 69
+75b8 c 105 69
+75c4 d 105 69
+75d1 1 105 69
+75d2 c 72 68
+75de 2 72 68
+75e0 c 105 69
+75ec d 105 69
+75f9 1 105 69
+75fa c 397 40
+7606 d 397 40
+7613 1 397 40
+7614 c 105 69
+7620 d 105 69
+762d 1 105 69
+FUNC 762e 14 0 std::_Rb_tree<unsigned long long, std::pair<unsigned long long const, dwarf2reader::FunctionInfo*>, std::_Select1st<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> >, std::less<unsigned long long>, std::allocator<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> > >::_S_right(std::_Rb_tree_node_base*)
+762e c 496 20
+763a 8 497 40
+FUNC 7642 14 0 std::_Rb_tree<unsigned long long, std::pair<unsigned long long const, dwarf2reader::FunctionInfo*>, std::_Select1st<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> >, std::less<unsigned long long>, std::allocator<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> > >::_S_left(std::_Rb_tree_node_base*)
+7642 c 488 20
+764e 8 489 40
+7656 c 65 68
+7662 2 65 68
+7664 c 72 68
+7670 2 72 68
+7672 c 97 69
+767e d 97 69
+768b 1 97 69
+768c c 105 69
+7698 d 105 69
+76a5 1 105 69
+76a6 c 72 68
+76b2 2 72 68
+76b4 c 105 69
+76c0 d 105 69
+76cd 1 105 69
+76ce c 397 40
+76da d 397 40
+76e7 1 397 40
+76e8 c 105 69
+76f4 d 105 69
+7701 1 105 69
+FUNC 7702 14 0 std::_Rb_tree<unsigned long long, std::pair<unsigned long long const, std::pair<std::string, unsigned int> >, std::_Select1st<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > >, std::less<unsigned long long>, std::allocator<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > > >::_S_right(std::_Rb_tree_node_base*)
+7702 c 496 20
+770e 8 497 40
+FUNC 7716 14 0 std::_Rb_tree<unsigned long long, std::pair<unsigned long long const, std::pair<std::string, unsigned int> >, std::_Select1st<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > >, std::less<unsigned long long>, std::allocator<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > > >::_S_left(std::_Rb_tree_node_base*)
+7716 c 488 20
+7722 8 489 40
+772a c 84 71
+7736 2f 85 71
+7765 2 86 71
+7767 1 86 71
+7768 c 80 71
+7774 d 80 71
+7781 1 80 71
+7782 c 96 71
+778e 12 97 71
+77a0 2 98 71
+77a2 c 84 71
+77ae 2f 85 71
+77dd 2 86 71
+77df 1 86 71
+77e0 c 80 71
+77ec d 80 71
+77f9 1 80 71
+77fa c 96 71
+7806 12 97 71
+7818 2 98 71
+7826 d 107 68
+7833 1 107 68
+FUNC 7834 2e 0 void std::_Destroy<std::string*, std::allocator<std::string> >(std::string*, std::string*, std::allocator<std::string>)
+7834 c 171 21
+7840 2 173 73
+7842 12 174 73
+7854 c 173 73
+7860 2 174 73
+7862 c 167 40
+786e a 168 40
+FUNC 7878 26 0 std::_Rb_tree<unsigned long long, std::pair<unsigned long long const, dwarf2reader::FunctionInfo*>, std::_Select1st<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> >, std::less<unsigned long long>, std::allocator<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> > >::begin()
+7878 c 581 21
+7884 1a 582 40
+FUNC 789e 19 0 std::map<unsigned long long, dwarf2reader::FunctionInfo*, std::less<unsigned long long>, std::allocator<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> > >::begin()
+789e c 234 21
+78aa d 235 45
+78b7 1 235 45
+FUNC 78b8 26 0 std::_Rb_tree<unsigned long long, std::pair<unsigned long long const, dwarf2reader::FunctionInfo*>, std::_Select1st<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> >, std::less<unsigned long long>, std::allocator<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> > >::end()
+78b8 c 592 21
+78c4 1a 593 40
+FUNC 78de 19 0 std::map<unsigned long long, dwarf2reader::FunctionInfo*, std::less<unsigned long long>, std::allocator<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> > >::end()
+78de c 251 21
+78ea d 252 45
+78f7 1 252 45
+78f8 c 167 40
+7904 a 168 40
+FUNC 790e 26 0 std::_Rb_tree<unsigned long long, std::pair<unsigned long long const, std::pair<std::string, unsigned int> >, std::_Select1st<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > >, std::less<unsigned long long>, std::allocator<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > > >::begin()
+790e c 581 21
+791a 1a 582 40
+FUNC 7934 19 0 std::map<unsigned long long, std::pair<std::string, unsigned int>, std::less<unsigned long long>, std::allocator<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > > >::begin()
+7934 c 234 21
+7940 d 235 45
+794d 1 235 45
+FUNC 794e 26 0 std::_Rb_tree<unsigned long long, std::pair<unsigned long long const, std::pair<std::string, unsigned int> >, std::_Select1st<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > >, std::less<unsigned long long>, std::allocator<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > > >::end()
+794e c 592 21
+795a 1a 593 40
+FUNC 7974 19 0 std::map<unsigned long long, std::pair<std::string, unsigned int>, std::less<unsigned long long>, std::allocator<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > > >::end()
+7974 c 251 21
+7980 d 252 45
+798d 1 252 45
+FUNC 798e 11 0 std::_Select1st<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >::operator()(std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*>&) const
+798e c 546 22
+799a 5 547 41
+799f 1 547 41
+79a0 c 128 34
+79ac 13 129 34
+79bf 1 129 34
+79cc 22 396 34
+79fa d 199 42
+7a07 1 199 42
+7a08 c 65 68
+7a14 2 65 68
+7a16 c 72 68
+7a22 2 72 68
+7a24 c 97 69
+7a30 d 97 69
+7a3d 1 97 69
+7a3e c 105 69
+7a4a d 105 69
+7a57 1 105 69
+7a58 c 65 68
+7a64 2 65 68
+7a66 c 72 68
+7a72 2 72 68
+7a74 c 105 69
+7a80 d 105 69
+7a8d 1 105 69
+7a8e c 97 69
+7a9a d 97 69
+7aa7 1 97 69
+7aa8 c 72 68
+7ab4 2 72 68
+7ab6 c 105 69
+7ac2 d 105 69
+7acf 1 105 69
+7adc d 94 68
+7ae9 1 94 68
+FUNC 7aea 2f 0 std::_Vector_base<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> >::_M_deallocate(dwarf2reader::CompilationUnit::Abbrev*, unsigned long)
+7aea c 120 23
+7af6 6 122 71
+7afc 1d 123 71
+7b19 1 123 71
+7b1a c 108 71
+7b26 43 109 71
+7b69 1 109 71
+7b6a c 65 68
+7b76 2 65 68
+7b78 c 103 69
+7b84 d 103 69
+7b91 1 103 69
+7b92 c 65 68
+7b9e 2 65 68
+7ba0 c 103 69
+7bac d 103 69
+7bb9 1 103 69
+7bc6 d 94 68
+7bd3 1 94 68
+FUNC 7bd4 2f 0 std::_Vector_base<dwarf2reader::SourceFileInfo, std::allocator<dwarf2reader::SourceFileInfo> >::_M_deallocate(dwarf2reader::SourceFileInfo*, unsigned long)
+7bd4 c 120 23
+7be0 6 122 71
+7be6 1d 123 71
+7c03 1 123 71
+7c04 c 108 71
+7c10 43 109 71
+7c53 1 109 71
+7c54 c 188 71
+7c60 12 189 71
+7c72 2 190 71
+7c74 c 35 32
+7c80 d 35 32
+7c8d 1 35 32
+7c9a d 107 68
+7ca7 1 107 68
+FUNC 7ca8 2e 0 void std::_Destroy<dwarf2reader::SourceFileInfo*, std::allocator<dwarf2reader::SourceFileInfo> >(dwarf2reader::SourceFileInfo*, dwarf2reader::SourceFileInfo*, std::allocator<dwarf2reader::SourceFileInfo>)
+7ca8 c 171 23
+7cb4 2 173 73
+7cb6 12 174 73
+7cc8 c 173 73
+7cd4 2 174 73
+7cd6 d 272 71
+7ce3 8c 273 71
+7d6f 1 273 71
+7d7c d 94 68
+7d89 1 94 68
+FUNC 7d8a 2f 0 std::_Vector_base<std::string, std::allocator<std::string> >::_M_deallocate(std::string*, unsigned long)
+7d8a c 120 23
+7d96 6 122 71
+7d9c 1d 123 71
+7db9 1 123 71
+7dba c 108 71
+7dc6 3d 109 71
+7e03 1 109 71
+7e04 c 188 71
+7e10 12 189 71
+7e22 2 190 71
+7e24 d 272 71
+7e31 8c 273 71
+7ebd 1 273 71
+7eca 2b 596 34
+7ef5 1 596 34
+7f02 7 614 72
+7f09 1 614 72
+7f0a c 65 68
+7f16 2 65 68
+7f18 c 72 68
+7f24 2 72 68
+7f26 c 103 69
+7f32 d 103 69
+7f3f 1 103 69
+7f40 c 105 69
+7f4c d 105 69
+7f59 1 105 69
+7f5a c 65 68
+7f66 2 65 68
+7f68 c 72 68
+7f74 2 72 68
+7f76 c 103 69
+7f82 d 103 69
+7f8f 1 103 69
+7f90 c 105 69
+7f9c d 105 69
+7fa9 1 105 69
+7faa c 105 69
+7fb6 d 105 69
+7fc3 1 105 69
+7fd0 d 575 34
+7fdd 1 575 34
+7fea d 575 34
+7ff7 1 575 34
+FUNC 7ff8 11 0 std::_Select1st<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >::operator()(std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> const&) const
+7ff8 c 550 23
+8004 5 551 41
+8009 1 551 41
+8016 2f 600 34
+8045 1 600 34
+8046 c 84 70
+8052 1e 85 70
+FUNC 8070 11 0 std::_Select1st<std::pair<std::string const, std::pair<char const*, unsigned long long> > >::operator()(std::pair<std::string const, std::pair<char const*, unsigned long long> >&) const
+8070 c 546 23
+807c 5 547 41
+8081 1 547 41
+FUNC 8082 11 0 std::_Select1st<std::pair<std::string const, std::pair<char const*, unsigned long long> > >::operator()(std::pair<std::string const, std::pair<char const*, unsigned long long> > const&) const
+8082 c 550 23
+808e 5 551 41
+8093 1 551 41
+8094 c 128 34
+80a0 13 129 34
+80b3 1 129 34
+80b4 c 84 70
+80c0 1e 85 70
+80de c 65 68
+80ea 2 65 68
+80ec c 103 69
+80f8 d 103 69
+8105 1 103 69
+8106 c 65 68
+8112 2 65 68
+8114 c 72 68
+8120 2 72 68
+8122 c 105 69
+812e d 105 69
+813b 1 105 69
+813c c 103 69
+8148 d 103 69
+8155 1 103 69
+8156 c 105 69
+8162 d 105 69
+816f 1 105 69
+8170 c 80 71
+817c d 80 71
+8189 1 80 71
+818a c 67 68
+8196 2 67 68
+8198 c 99 69
+81a4 14 100 69
+FUNC 81b8 2b 0 std::_Vector_base<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*> >::get_allocator() const
+81b8 10 93 23
+81c8 1b 94 71
+81e3 1 94 71
+81e4 c 99 69
+81f0 14 100 69
+8210 2 107 68
+FUNC 8212 2e 0 void std::_Destroy<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >**, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*> >(__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >**, __gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >**, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*>)
+8212 c 171 23
+821e 2 173 73
+8220 12 174 73
+8232 c 173 73
+823e 2 174 73
+824c d 107 68
+8259 1 107 68
+825a c 67 68
+8266 2 67 68
+8268 c 99 69
+8274 14 100 69
+8288 c 403 40
+8294 1c 404 40
+82b0 a 406 40
+82ba a 407 40
+82c4 c 408 40
+82d0 e 409 40
+82de c 553 40
+82ea 36 554 40
+8320 2 555 40
+8322 c 103 69
+832e d 103 69
+833b 1 103 69
+FUNC 833c 2b 0 std::_Rb_tree<unsigned long long, std::pair<unsigned long long const, dwarf2reader::FunctionInfo*>, std::_Select1st<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> >, std::less<unsigned long long>, std::allocator<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> > >::get_allocator() const
+833c 10 350 23
+834c 1b 351 40
+8367 1 351 40
+8368 c 69 70
+8374 2 69 70
+8382 d 107 68
+838f 1 107 68
+839c d 94 68
+83a9 1 94 68
+FUNC 83aa 2a 0 std::_Rb_tree<unsigned long long, std::pair<unsigned long long const, dwarf2reader::FunctionInfo*>, std::_Select1st<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> >, std::less<unsigned long long>, std::allocator<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> > >::_M_put_node(std::_Rb_tree_node<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> >*)
+83aa c 359 23
+83b6 1e 360 40
+FUNC 83d4 59 0 std::_Rb_tree<unsigned long long, std::pair<unsigned long long const, dwarf2reader::FunctionInfo*>, std::_Select1st<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> >, std::less<unsigned long long>, std::allocator<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> > >::destroy_node(std::_Rb_tree_node<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> >*)
+83d4 d 387 23
+83e1 35 389 40
+8416 17 390 40
+842d 1 390 40
+FUNC 842e 56 0 std::_Rb_tree<unsigned long long, std::pair<unsigned long long const, dwarf2reader::FunctionInfo*>, std::_Select1st<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> >, std::less<unsigned long long>, std::allocator<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> > >::_M_erase(std::_Rb_tree_node<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> >*)
+842e c 1051 23
+843a 2 1054 40
+843c 1a 1056 40
+8456 e 1057 40
+8464 12 1058 40
+8476 6 1059 40
+847c 6 1054 40
+8482 2 1059 40
+8484 d 569 40
+8491 58 570 40
+84e9 1 570 40
+84ea c 147 45
+84f6 31 148 45
+8527 1 148 45
+8528 c 92 45
+8534 d 92 45
+8541 1 92 45
+8542 c 67 68
+854e 2 67 68
+8550 c 99 69
+855c 14 100 69
+8570 c 403 40
+857c 1c 404 40
+8598 a 406 40
+85a2 a 407 40
+85ac c 408 40
+85b8 e 409 40
+85c6 c 553 40
+85d2 36 554 40
+8608 2 555 40
+860a c 103 69
+8616 d 103 69
+8623 1 103 69
+FUNC 8624 2b 0 std::_Rb_tree<unsigned long long, std::pair<unsigned long long const, std::pair<std::string, unsigned int> >, std::_Select1st<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > >, std::less<unsigned long long>, std::allocator<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > > >::get_allocator() const
+8624 10 350 23
+8634 1b 351 40
+864f 1 351 40
+8650 c 69 70
+865c d 69 70
+8669 1 69 70
+866a c 69 70
+8676 30 69 70
+86b2 d 107 68
+86bf 1 107 68
+86cc d 94 68
+86d9 1 94 68
+FUNC 86da 2a 0 std::_Rb_tree<unsigned long long, std::pair<unsigned long long const, std::pair<std::string, unsigned int> >, std::_Select1st<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > >, std::less<unsigned long long>, std::allocator<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > > >::_M_put_node(std::_Rb_tree_node<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > >*)
+86da c 359 23
+86e6 1e 360 40
+FUNC 8704 59 0 std::_Rb_tree<unsigned long long, std::pair<unsigned long long const, std::pair<std::string, unsigned int> >, std::_Select1st<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > >, std::less<unsigned long long>, std::allocator<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > > >::destroy_node(std::_Rb_tree_node<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > >*)
+8704 d 387 23
+8711 35 389 40
+8746 17 390 40
+875d 1 390 40
+FUNC 875e 56 0 std::_Rb_tree<unsigned long long, std::pair<unsigned long long const, std::pair<std::string, unsigned int> >, std::_Select1st<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > >, std::less<unsigned long long>, std::allocator<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > > >::_M_erase(std::_Rb_tree_node<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > >*)
+875e c 1051 23
+876a 2 1054 40
+876c 1a 1056 40
+8786 e 1057 40
+8794 12 1058 40
+87a6 6 1059 40
+87ac 6 1054 40
+87b2 2 1059 40
+87b4 d 569 40
+87c1 58 570 40
+8819 1 570 40
+881a c 147 45
+8826 31 148 45
+8857 1 148 45
+8858 c 92 45
+8864 d 92 45
+8871 1 92 45
+8872 c 603 72
+887e c 603 72
+FUNC 888a 23 0 std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*> >::begin()
+888a c 333 23
+8896 17 334 71
+88ad 1 334 71
+88ba 2a 654 72
+FUNC 88e4 42 0 std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*> >::operator[](unsigned long)
+88e4 c 494 23
+88f0 36 495 71
+FUNC 8926 26 0 std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*> >::end()
+8926 c 351 23
+8932 1a 352 71
+FUNC 894c 28 0 bool std::operator==<char, std::char_traits<char>, std::allocator<char> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)
+894c c 2115 24
+8958 1c 2116 37
+FUNC 8974 23 0 std::equal_to<std::string>::operator()(std::string const&, std::string const&) const
+8974 c 199 24
+8980 17 200 41
+8997 1 200 41
+8998 c 80 71
+89a4 d 80 71
+89b1 1 80 71
+89b2 c 67 68
+89be 2 67 68
+89c0 c 99 69
+89cc 14 100 69
+FUNC 89e0 2b 0 std::_Vector_base<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*> >::get_allocator() const
+89e0 10 93 24
+89f0 1b 94 71
+8a0b 1 94 71
+8a0c c 99 69
+8a18 14 100 69
+8a2c c 84 71
+8a38 2f 85 71
+8a67 2 86 71
+8a69 1 86 71
+8a6a c 96 71
+8a76 12 97 71
+8a88 2 98 71
+8a96 2 107 68
+FUNC 8a98 2e 0 void std::_Destroy<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >**, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*> >(__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >**, __gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >**, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*>)
+8a98 c 171 24
+8aa4 2 173 73
+8aa6 12 174 73
+8ab8 c 173 73
+8ac4 2 174 73
+FUNC 8ac6 13 0 std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*> >::max_size() const
+8ac6 c 407 24
+8ad2 7 408 71
+8ad9 1 408 71
+8ada c 603 72
+8ae6 c 603 72
+FUNC 8af2 26 0 std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*> >::end()
+8af2 c 351 24
+8afe 1a 352 71
+FUNC 8b18 23 0 std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*> >::begin()
+8b18 c 333 24
+8b24 17 334 71
+8b3b 1 334 71
+8b48 2a 654 72
+8b7e 7 614 72
+8b85 1 614 72
+FUNC 8b86 42 0 std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*> >::operator[](unsigned long)
+8b86 c 494 24
+8b92 36 495 71
+8bd4 d 107 68
+8be1 1 107 68
+FUNC 8be2 28 0 void std::swap<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >**>(__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >**&, __gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >**&)
+8be2 c 92 25
+8bee 8 97 61
+8bf6 a 98 61
+8c00 a 99 61
+FUNC 8c0a 50 0 std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*> >::swap(std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*> >&)
+8c0a c 733 25
+8c16 12 735 71
+8c28 18 736 71
+8c40 1a 737 71
+8c66 2b 596 34
+8c91 1 596 34
+8c9e 2f 600 34
+8ccd 1 600 34
+FUNC 8cce 28 0 void std::swap<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >**>(__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >**&, __gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >**&)
+8cce c 92 25
+8cda 8 97 61
+8ce2 a 98 61
+8cec a 99 61
+FUNC 8cf6 50 0 std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*> >::swap(std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*> >&)
+8cf6 c 733 25
+8d02 12 735 71
+8d14 18 736 71
+8d2c 1a 737 71
+8d46 c 84 71
+8d52 2f 85 71
+8d81 2 86 71
+8d83 1 86 71
+8d84 c 96 71
+8d90 12 97 71
+8da2 2 98 71
+FUNC 8da4 13 0 std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*> >::max_size() const
+8da4 c 407 25
+8db0 7 408 71
+8db7 1 408 71
+8dc4 d 94 68
+8dd1 1 94 68
+FUNC 8dd2 2f 0 std::_Vector_base<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*> >::_M_deallocate(__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >**, unsigned long)
+8dd2 c 120 25
+8dde 6 122 71
+8de4 1d 123 71
+8e01 1 123 71
+8e02 c 108 71
+8e0e 3d 109 71
+8e4b 1 109 71
+8e4c c 272 71
+8e58 4b 273 71
+8ea3 1 273 71
+8ea4 c 188 71
+8eb0 12 189 71
+8ec2 2 190 71
+8ec4 c 603 72
+8ed0 c 603 72
+FUNC 8edc 2b 0 std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*> >::begin() const
+8edc c 342 25
+8ee8 1f 343 71
+8f07 1 343 71
+FUNC 8f08 2c 0 std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*> >::end() const
+8f08 c 360 25
+8f14 20 361 71
+8f40 5 666 72
+8f45 1 666 72
+8f53 2b 759 72
+FUNC 8f7e 3c 0 std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*> >::size() const
+8f7e c 402 25
+8f8a 30 403 71
+8fc6 26 588 34
+8ff8 15 511 34
+900d 79 513 34
+9086 21 517 34
+90a7 1 517 34
+90b4 14 225 42
+90d4 26 592 34
+FUNC 90fa 49 0 std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*> >::capacity() const
+90fa c 449 25
+9106 3d 451 71
+9143 1 451 71
+9144 c 103 69
+9150 d 103 69
+915d 1 103 69
+916e 1b 286 34
+9189 1 286 34
+9196 d 94 68
+91a3 1 94 68
+91b0 1e 301 34
+91db 56 622 34
+9231 17 623 34
+9254 9 1080 34
+925d 1a 1082 34
+9277 2 1083 34
+9279 8 1085 34
+9281 12 1086 34
+9293 6 1087 34
+9299 6 1083 34
+929f 1b 1089 34
+92ba 1d 1080 34
+92d7 c 1091 34
+92e3 1 1091 34
+92e4 d 360 34
+92f1 77 361 34
+9368 c 93 42
+9374 d 93 42
+9381 1 93 42
+9382 c 72 68
+938e 2 72 68
+9390 c 105 69
+939c d 105 69
+93a9 1 105 69
+93aa c 301 66
+93b6 d 301 66
+93c3 1 301 66
+93d0 d 94 68
+93dd 1 94 68
+FUNC 93de 2f 0 std::_Vector_base<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*> >::_M_deallocate(__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >**, unsigned long)
+93de c 120 26
+93ea 6 122 71
+93f0 1d 123 71
+940d 1 123 71
+940e c 108 71
+941a 3d 109 71
+9457 1 109 71
+9458 c 188 71
+9464 12 189 71
+9476 2 190 71
+9478 c 272 71
+9484 4b 273 71
+94cf 1 273 71
+94d0 c 603 72
+94dc c 603 72
+FUNC 94e8 2b 0 std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*> >::begin() const
+94e8 c 342 26
+94f4 1f 343 71
+9513 1 343 71
+FUNC 9514 2c 0 std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*> >::end() const
+9514 c 360 26
+9520 20 361 71
+954c 2d 662 72
+9579 1 662 72
+FUNC 957a 2d 0 unsigned long const& std::max<unsigned long>(unsigned long const&, unsigned long const&)
+957a c 206 26
+9586 e 211 61
+9594 8 212 61
+959c b 213 61
+95a7 1 213 61
+95b4 19 650 72
+95cd 1 650 72
+95da 5 666 72
+95df 1 666 72
+95ed 2b 759 72
+9624 5 666 72
+9629 1 666 72
+9637 2b 759 72
+FUNC 9662 49 0 std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*> >::capacity() const
+9662 c 449 26
+966e 3d 451 71
+96ab 1 451 71
+FUNC 96ac 3c 0 std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*> >::size() const
+96ac c 402 26
+96b8 30 403 71
+96f4 26 588 34
+9726 26 592 34
+974c c 103 69
+9758 d 103 69
+9765 1 103 69
+9776 1b 286 34
+9791 1 286 34
+979e d 94 68
+97ab 1 94 68
+97b8 1e 301 34
+97e3 56 622 34
+9839 17 623 34
+985c 9 1080 34
+9865 1a 1082 34
+987f 2 1083 34
+9881 8 1085 34
+9889 12 1086 34
+989b 6 1087 34
+98a1 6 1083 34
+98a7 1b 1089 34
+98c2 1d 1080 34
+98df c 1091 34
+98eb 1 1091 34
+98ec d 360 34
+98f9 77 361 34
+9970 c 69 70
+997c 20 69 70
+99a9 5c 104 68
+9a05 1 104 68
+9a06 c 69 70
+9a12 2c 69 70
+9a4b 5c 104 68
+9aa7 1 104 68
+9ab4 2d 662 72
+9ae1 1 662 72
+9aee 19 650 72
+9b07 1 650 72
+9b14 5 666 72
+9b19 1 666 72
+9b27 2b 759 72
+9b52 c 72 68
+9b5e 2 72 68
+9b60 c 105 69
+9b6c d 105 69
+9b79 1 105 69
+9b7a c 69 70
+9b86 2 69 70
+9b94 d 107 68
+9ba1 1 107 68
+9bae d 94 68
+9bbb 1 94 68
+FUNC 9bbc 2a 0 std::_List_base<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm>, std::allocator<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> > >::_M_put_node(std::_List_node<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> >*)
+9bbc c 315 26
+9bc8 1e 316 66
+FUNC 9be6 35 0 bool __gnu_cxx::operator!=<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >**, std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*> > >(__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >**, std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*> > > const&, __gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >**, std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*> > > const&)
+9be6 d 699 26
+9bf3 28 700 72
+9c1b 1 700 72
+9c28 d 623 72
+9c35 5 624 72
+FUNC 9c3a 4b 0 void std::__fill<true>::fill<__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >**, std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*> > >, __gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*>(__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >**, std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*> > >, __gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >**, std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*> > >, __gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >* const&)
+9c3a c 539 61
+9c46 8 541 61
+9c4e 2 542 61
+9c50 12 543 61
+9c62 21 542 61
+9c83 2 543 61
+9c85 1 543 61
+FUNC 9c86 2b 0 void std::fill<__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >**, std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*> > >, __gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*>(__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >**, std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*> > >, __gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >**, std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*> > >, __gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >* const&)
+9c86 c 560 26
+9c92 4 567 61
+9c96 1b 568 61
+9cb1 1 568 61
+FUNC 9cb2 4b 0 void std::_Destroy<__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >**, std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*> > >, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*> >(__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >**, std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*> > >, __gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >**, std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*> > >, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*>)
+9cb2 c 171 26
+9cbe 2 173 73
+9cc0 1a 174 73
+9cda 21 173 73
+9cfb 2 174 73
+9cfd 1 174 73
+9d0a 7 98 68
+9d11 1 98 68
+9d1e 1d 85 68
+9d3b 5 86 68
+9d40 16 88 68
+9d62 1d 297 34
+9d7f 1 297 34
+9d8d e 605 34
+9d9b 9 606 34
+9da4 3c 609 34
+9de0 b 610 34
+9deb 11 609 34
+9dfc b 612 34
+9e07 12 614 34
+9e19 b 615 34
+9e24 13 612 34
+9e37 8 615 34
+9e3f 1 615 34
+9e4d 15 751 34
+9e62 1a 752 34
+9e7c b 754 34
+9e87 49 755 34
+9ed0 3b 756 34
+9f0b 12 754 34
+9f1d 15 758 34
+9f32 8 759 34
+9f3a 1c 760 34
+9f56 f 761 34
+9f65 41 762 34
+9fb2 7 98 68
+9fb9 1 98 68
+9fc6 1d 85 68
+9fe3 5 86 68
+9fe8 17 88 68
+9fff 1 88 68
+a00c 1d 297 34
+a029 1 297 34
+a037 e 605 34
+a045 9 606 34
+a04e 3c 609 34
+a08a b 610 34
+a095 11 609 34
+a0a6 b 612 34
+a0b1 12 614 34
+a0c3 b 615 34
+a0ce 13 612 34
+a0e1 8 615 34
+a0e9 1 615 34
+a0f7 15 751 34
+a10c 1a 752 34
+a126 b 754 34
+a131 49 755 34
+a17a 3b 756 34
+a1b5 12 754 34
+a1c7 15 758 34
+a1dc 8 759 34
+a1e4 1c 760 34
+a200 f 761 34
+a20f 41 762 34
+FUNC a250 35 0 bool __gnu_cxx::operator!=<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >**, std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*> > >(__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >**, std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*> > > const&, __gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >**, std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*> > > const&)
+a250 d 699 26
+a25d 28 700 72
+a285 1 700 72
+a292 d 623 72
+a29f 5 624 72
+FUNC a2a4 4b 0 void std::__fill<true>::fill<__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >**, std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*> > >, __gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*>(__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >**, std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*> > >, __gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >**, std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*> > >, __gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >* const&)
+a2a4 c 539 61
+a2b0 8 541 61
+a2b8 2 542 61
+a2ba 12 543 61
+a2cc 21 542 61
+a2ed 2 543 61
+a2ef 1 543 61
+FUNC a2f0 2b 0 void std::fill<__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >**, std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*> > >, __gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*>(__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >**, std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*> > >, __gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >**, std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*> > >, __gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >* const&)
+a2f0 c 560 26
+a2fc 4 567 61
+a300 1b 568 61
+a31b 1 568 61
+FUNC a31c 4b 0 void std::_Destroy<__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >**, std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*> > >, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*> >(__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >**, std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*> > >, __gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >**, std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*> > >, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*>)
+a31c c 171 26
+a328 2 173 73
+a32a 1a 174 73
+a344 21 173 73
+a365 2 174 73
+a367 1 174 73
+a368 c 65 68
+a374 2 65 68
+a376 c 103 69
+a382 d 103 69
+a38f 1 103 69
+FUNC a390 2b 0 std::_List_base<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm>, std::allocator<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> > >::get_allocator() const
+a390 10 322 26
+a3a0 1b 324 66
+a3bb 1 324 66
+FUNC a3bc 7b 0 std::_List_base<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm>, std::allocator<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> > >::_M_clear()
+a3bc d 69 27
+a3c9 8 72 77
+a3d1 2 73 77
+a3d3 6 75 77
+a3d9 8 76 77
+a3e1 35 77 77
+a416 12 78 77
+a428 a 73 77
+a432 5 78 77
+a437 1 78 77
+a438 c 331 66
+a444 18 332 66
+a45c c 392 66
+a468 d 392 66
+a475 1 392 66
+a476 c 211 74
+a482 10 211 74
+a49e d 107 68
+a4ab 1 107 68
+FUNC a4ac 2e 0 void std::_Destroy<dwarf2reader::CompilationUnit::Abbrev*, std::allocator<dwarf2reader::CompilationUnit::Abbrev> >(dwarf2reader::CompilationUnit::Abbrev*, dwarf2reader::CompilationUnit::Abbrev*, std::allocator<dwarf2reader::CompilationUnit::Abbrev>)
+a4ac c 171 27
+a4b8 2 173 73
+a4ba 12 174 73
+a4cc c 173 73
+a4d8 2 174 73
+a4da c 272 71
+a4e6 4b 273 71
+a531 1 273 71
+a532 13 196 74
+a545 10 196 74
+a555 2f 197 74
+a584 1a 198 74
+a59e 13 196 74
+a5b1 10 196 74
+a5c1 2f 197 74
+a5f0 1a 198 74
+a616 7 98 68
+a61d 1 98 68
+a62a 1d 85 68
+a647 5 86 68
+a64c 10 88 68
+FUNC a65c 2a 0 std::_Vector_base<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*> >::_M_allocate(unsigned long)
+a65c c 116 27
+a668 1e 117 71
+a686 d 100 71
+a693 12 101 71
+a6a5 19 103 71
+a6be b 104 71
+a6c9 3a 105 71
+a703 1 105 71
+a710 7 98 68
+a717 1 98 68
+a724 1d 85 68
+a741 5 86 68
+a746 10 88 68
+FUNC a756 2a 0 std::_Vector_base<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*> >::_M_allocate(unsigned long)
+a756 c 116 27
+a762 1e 117 71
+a780 d 100 71
+a78d 12 101 71
+a79f 19 103 71
+a7b8 b 104 71
+a7c3 3a 105 71
+a7fd 1 105 71
+a80b 12 424 61
+a81d 2e 425 61
+a84b 13 426 61
+a86a 4 440 61
+a86e 1b 443 61
+a889 1 443 61
+a898 56 482 61
+a8fa 4 514 61
+a8fe 4 515 61
+a902 1b 517 61
+a91d 1 517 61
+a92a 8 616 61
+a932 2 617 61
+a934 8 618 61
+a93c f 617 61
+a94b 5 619 61
+a95c 4 641 61
+a960 1b 642 61
+a97b 1 642 61
+FUNC a97c 27 0 void std::__uninitialized_fill_n_aux<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >**, unsigned long, __gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*>(__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >**, unsigned long, __gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >* const&, __true_type)
+a97c c 182 28
+a988 1b 183 79
+a9a3 1 183 79
+FUNC a9a4 2f 0 void std::uninitialized_fill_n<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >**, unsigned long, __gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*>(__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >**, unsigned long, __gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >* const&)
+a9a4 c 214 28
+a9b0 23 218 79
+a9d3 1 218 79
+FUNC a9d4 27 0 void std::__uninitialized_fill_n_a<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >**, unsigned long, __gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*, __gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*>(__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >**, unsigned long, __gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >* const&, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*>)
+a9d4 c 308 28
+a9e0 1b 310 79
+a9fb 1 310 79
+a9fc c 200 71
+aa08 19 201 71
+aa21 42 203 71
+aa63 15 205 71
+aa85 11 992 34
+aa96 c 993 34
+aaa2 15 995 34
+aab7 c 996 34
+aac3 4a 998 34
+ab0d f 1001 34
+ab1c 1c 998 34
+ab38 1a 1003 34
+ab52 5 1004 34
+ab57 1f 1007 34
+ab76 1c 1008 34
+ab92 19 1009 34
+abab 19 1010 34
+abc4 1a 1011 34
+abde a 1004 34
+abe8 11 1001 34
+abf9 15 1014 34
+ac0e 13 1028 34
+ac21 b 1016 34
+ac2c 9 1018 34
+ac35 19 1023 34
+ac4e 23 1024 34
+ac71 19 1025 34
+ac8a 1d 1021 34
+aca7 1a 1018 34
+acc1 b 1028 34
+accc b 1016 34
+acd7 1e 1028 34
+acf5 1 1028 34
+ad06 16 438 34
+ad1c 37 439 34
+ad53 1 439 34
+ad64 37 212 42
+ad9b 1 212 42
+ada8 8 616 61
+adb0 2 617 61
+adb2 8 618 61
+adba f 617 61
+adc9 5 619 61
+adda 4 641 61
+adde 1b 642 61
+adf9 1 642 61
+FUNC adfa 27 0 void std::__uninitialized_fill_n_aux<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >**, unsigned long, __gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*>(__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >**, unsigned long, __gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >* const&, __true_type)
+adfa c 182 28
+ae06 1b 183 79
+ae21 1 183 79
+FUNC ae22 2f 0 void std::uninitialized_fill_n<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >**, unsigned long, __gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*>(__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >**, unsigned long, __gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >* const&)
+ae22 c 214 28
+ae2e 23 218 79
+ae51 1 218 79
+FUNC ae52 27 0 void std::__uninitialized_fill_n_a<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >**, unsigned long, __gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*, __gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*>(__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >**, unsigned long, __gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >* const&, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*>)
+ae52 c 308 28
+ae5e 1b 310 79
+ae79 1 310 79
+ae7a c 200 71
+ae86 19 201 71
+ae9f 42 203 71
+aee1 15 205 71
+af03 11 992 34
+af14 c 993 34
+af20 15 995 34
+af35 c 996 34
+af41 4a 998 34
+af8b f 1001 34
+af9a 1c 998 34
+afb6 1a 1003 34
+afd0 5 1004 34
+afd5 1f 1007 34
+aff4 1c 1008 34
+b010 19 1009 34
+b029 19 1010 34
+b042 1a 1011 34
+b05c a 1004 34
+b066 11 1001 34
+b077 15 1014 34
+b08c 13 1028 34
+b09f b 1016 34
+b0aa 9 1018 34
+b0b3 19 1023 34
+b0cc 23 1024 34
+b0ef 19 1025 34
+b108 1d 1021 34
+b125 1a 1018 34
+b13f b 1028 34
+b14a b 1016 34
+b155 1e 1028 34
+b173 1 1028 34
+b184 16 438 34
+b19a 37 439 34
+b1d1 1 439 34
+b1e2 37 212 42
+b219 1 212 42
+b227 12 424 61
+b239 2e 425 61
+b267 13 426 61
+b286 4 440 61
+b28a 1b 443 61
+b2a5 1 443 61
+b2b4 56 482 61
+b316 4 514 61
+b31a 4 515 61
+b31e 1b 517 61
+b339 1 517 61
+b346 8 616 61
+b34e 2 617 61
+b350 12 618 61
+b362 16 617 61
+b378 5 619 61
+b37d 1 619 61
+b38a 4 641 61
+b38e 1b 642 61
+b3a9 1 642 61
+FUNC b3aa 27 0 void std::__uninitialized_fill_n_aux<__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >**, std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*> > >, unsigned long, __gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*>(__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >**, std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*> > >, unsigned long, __gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >* const&, __true_type)
+b3aa c 182 28
+b3b6 1b 183 79
+b3d1 1 183 79
+FUNC b3d2 2f 0 void std::uninitialized_fill_n<__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >**, std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*> > >, unsigned long, __gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*>(__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >**, std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*> > >, unsigned long, __gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >* const&)
+b3d2 c 214 28
+b3de 23 218 79
+b401 1 218 79
+FUNC b402 27 0 void std::__uninitialized_fill_n_a<__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >**, std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*> > >, unsigned long, __gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*, __gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*>(__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >**, std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*> > >, unsigned long, __gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >* const&, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*>)
+b402 c 308 28
+b40e 1b 310 79
+b429 1 310 79
+b436 8 616 61
+b43e 2 617 61
+b440 12 618 61
+b452 16 617 61
+b468 5 619 61
+b46d 1 619 61
+b47a 4 641 61
+b47e 1b 642 61
+b499 1 642 61
+FUNC b49a 27 0 void std::__uninitialized_fill_n_aux<__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >**, std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*> > >, unsigned long, __gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*>(__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >**, std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*> > >, unsigned long, __gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >* const&, __true_type)
+b49a c 182 28
+b4a6 1b 183 79
+b4c1 1 183 79
+FUNC b4c2 2f 0 void std::uninitialized_fill_n<__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >**, std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*> > >, unsigned long, __gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*>(__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >**, std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*> > >, unsigned long, __gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >* const&)
+b4c2 c 214 28
+b4ce 23 218 79
+b4f1 1 218 79
+FUNC b4f2 27 0 void std::__uninitialized_fill_n_a<__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >**, std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*> > >, unsigned long, __gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*, __gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*>(__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >**, std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*> > >, unsigned long, __gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >* const&, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*>)
+b4f2 c 308 28
+b4fe 1b 310 79
+b519 1 310 79
+b526 22 300 61
+b548 11 301 61
+b559 1 301 61
+b566 4 315 61
+b56a 1b 317 61
+b585 1 317 61
+b592 1b 326 61
+b5ad 1 326 61
+b5ba 4 384 61
+b5be 4 385 61
+b5c2 1b 387 61
+b5dd 1 387 61
+b5ea 1b 74 79
+b605 1 74 79
+b612 23 113 79
+b635 1 113 79
+b642 1b 254 79
+b65d 1 254 79
+b66a 15 763 71
+b67f 40 766 71
+b6bf 3 768 71
+b6c2 2 773 71
+FUNC b6c4 124 0 std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*> >::reserve(unsigned long)
+b6c4 13 69 29
+b6d7 15 71 78
+b6ec e 72 78
+b6fa 19 73 78
+b713 e 75 78
+b721 28 78 78
+b749 3e 79 78
+b787 30 81 78
+b7b7 8 84 78
+b7bf 11 85 78
+b7d0 18 86 78
+b7f5 33 335 61
+b834 4 384 61
+b838 4 385 61
+b83c 1b 387 61
+b857 1 387 61
+b864 1b 74 79
+b87f 1 74 79
+b88c 23 113 79
+b8af 1 113 79
+b8bc 1b 254 79
+b8d7 1 254 79
+b8e6 56 354 61
+b948 4 384 61
+b94c 4 385 61
+b950 1b 387 61
+b96b 1 387 61
+b978 1b 74 79
+b993 1 74 79
+b9a0 23 113 79
+b9c3 1 113 79
+b9d0 1b 254 79
+b9eb 1 254 79
+FUNC b9ec 46e 0 std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*> >::_M_fill_insert(__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >**, std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*> > >, unsigned long, __gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >* const&)
+b9ec 14 311 29
+ba00 b 313 78
+ba0b 24 315 78
+ba2f 8 318 78
+ba37 23 319 78
+ba5a 15 320 78
+ba6f c 321 78
+ba7b 51 323 78
+bacc 14 327 78
+bae0 30 328 78
+bb10 35 330 78
+bb45 48 334 78
+bb8d 17 338 78
+bba4 43 339 78
+bbe7 14 342 78
+bbfb 1e 343 78
+bc19 e 348 78
+bc27 1e 349 78
+bc45 e 350 78
+bc53 1d 353 78
+bc70 8 354 78
+bc78 e 355 78
+bc86 27 357 78
+bcad 6 358 78
+bcb3 4d 361 78
+bd00 40 365 78
+bd40 18 367 78
+bd58 4d 368 78
+bda5 3e 379 78
+bde3 30 381 78
+be13 12 384 78
+be25 13 385 78
+be38 22 386 78
+FUNC be5a 2e 0 std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*> >::insert(__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >**, std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*> > >, unsigned long, __gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >* const&)
+be5a c 657 29
+be66 22 658 71
+be94 15 580 34
+bea9 15 581 34
+bebe 37 582 34
+bef5 c 583 34
+bf01 1 583 34
+bf02 d 335 34
+bf0f 4e 337 34
+bf5d 4d 338 34
+bfaa d 134 42
+bfb7 65 135 42
+c028 22 300 61
+c04a 11 301 61
+c05b 1 301 61
+c068 4 315 61
+c06c 1b 317 61
+c087 1 317 61
+c094 1b 326 61
+c0af 1 326 61
+c0bc 4 384 61
+c0c0 4 385 61
+c0c4 1b 387 61
+c0df 1 387 61
+c0ec 1b 74 79
+c107 1 74 79
+c114 23 113 79
+c137 1 113 79
+c144 1b 254 79
+c15f 1 254 79
+c16c 15 763 71
+c181 40 766 71
+c1c1 3 768 71
+c1c4 2 773 71
+FUNC c1c6 124 0 std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*> >::reserve(unsigned long)
+c1c6 13 69 29
+c1d9 15 71 78
+c1ee e 72 78
+c1fc 19 73 78
+c215 e 75 78
+c223 28 78 78
+c24b 3e 79 78
+c289 30 81 78
+c2b9 8 84 78
+c2c1 11 85 78
+c2d2 18 86 78
+c2f7 33 335 61
+c336 4 384 61
+c33a 4 385 61
+c33e 1b 387 61
+c359 1 387 61
+c366 1b 74 79
+c381 1 74 79
+c38e 23 113 79
+c3b1 1 113 79
+c3be 1b 254 79
+c3d9 1 254 79
+c3e8 56 354 61
+c44a 4 384 61
+c44e 4 385 61
+c452 1b 387 61
+c46d 1 387 61
+c47a 1b 74 79
+c495 1 74 79
+c4a2 23 113 79
+c4c5 1 113 79
+c4d2 1b 254 79
+c4ed 1 254 79
+FUNC c4ee 46e 0 std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*> >::_M_fill_insert(__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >**, std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*> > >, unsigned long, __gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >* const&)
+c4ee 14 311 29
+c502 b 313 78
+c50d 24 315 78
+c531 8 318 78
+c539 23 319 78
+c55c 15 320 78
+c571 c 321 78
+c57d 51 323 78
+c5ce 14 327 78
+c5e2 30 328 78
+c612 35 330 78
+c647 48 334 78
+c68f 17 338 78
+c6a6 43 339 78
+c6e9 14 342 78
+c6fd 1e 343 78
+c71b e 348 78
+c729 1e 349 78
+c747 e 350 78
+c755 1d 353 78
+c772 8 354 78
+c77a e 355 78
+c788 27 357 78
+c7af 6 358 78
+c7b5 4d 361 78
+c802 40 365 78
+c842 18 367 78
+c85a 4d 368 78
+c8a7 3e 379 78
+c8e5 30 381 78
+c915 12 384 78
+c927 13 385 78
+c93a 22 386 78
+FUNC c95c 2e 0 std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*> >::insert(__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >**, std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >*> > >, unsigned long, __gnu_cxx::_Hashtable_node<std::pair<std::string const, __gnu_cxx::hash_map<std::string, std::pair<char const*, unsigned long long>, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<char const*, unsigned long long> > >*> >* const&)
+c95c c 657 29
+c968 22 658 71
+c996 15 580 34
+c9ab 15 581 34
+c9c0 37 582 34
+c9f7 c 583 34
+ca03 1 583 34
+ca04 d 335 34
+ca11 4e 337 34
+ca5f 4d 338 34
+caac d 134 42
+cab9 65 135 42
+FUNC cb1e 44 0 dwarf2reader::CUFunctionInfoHandler::StartCompilationUnit(unsigned long long, unsigned char, unsigned char, unsigned long long, unsigned char)
+cb1e 39 135 42
+cb57 5 102 30
+cb5c 6 103 30
+FUNC cb62 41 0 dwarf2reader::CUFunctionInfoHandler::ProcessAttributeString(unsigned long long, dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm, std::string const&)
+cb62 18 136 30
+cb7a 10 137 30
+cb8a 17 138 30
+cba1 2 139 30
+cba3 1 139 30
+FUNC cba4 2a5 0 dwarf2reader::CUFunctionInfoHandler::ProcessAttributeUnsigned(unsigned long long, dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm, unsigned long long)
+cba4 2d 144 30
+cbd1 a 145 30
+cbdb 58 146 30
+cc33 35 147 30
+cc68 32 146 30
+cc9a 2a 147 30
+ccc4 82 152 30
+cd46 18 153 30
+cd5e 1c 152 30
+cd7a 2f 153 30
+cda9 e 154 30
+cdb7 28 155 30
+cddf 12 157 30
+cdf1 2 158 30
+cdf3 12 160 30
+ce05 2 161 30
+ce07 c 163 30
+ce13 2 164 30
+ce15 2c 166 30
+ce41 8 172 30
+ce49 1 172 30
+FUNC ce4a 19c 0 dwarf2reader::CULineInfoHandler::AddLine(unsigned long long, unsigned int, unsigned int, unsigned int)
+ce4a 20 84 30
+ce6a 1c 85 30
+ce86 9c 87 30
+cf22 4f 89 30
+cf71 19 87 30
+cf8a 25 90 30
+cfaf 30 93 30
+cfdf 7 95 30
+FUNC cfe6 9f 0 dwarf2reader::CUFunctionInfoHandler::EndDIE(unsigned long long)
+cfe6 19 174 30
+cfff 1c 175 30
+d01b 65 177 30
+d080 5 178 30
+d085 1 178 30
+FUNC d086 164 0 dwarf2reader::CUFunctionInfoHandler::StartDIE(unsigned long long, dwarf2reader::DwarfTag, std::list<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm>, std::allocator<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> > > const&)
+d086 20 111 30
+d0a6 1c 112 30
+d0c2 c 126 30
+d0ce 23 115 30
+d0f1 26 116 30
+d117 1a 117 30
+d131 d 118 30
+d13e 1b 119 30
+d159 5f 120 30
+d1b8 c 124 30
+d1c4 1c 115 30
+d1e0 3 126 30
+d1e3 7 129 30
+FUNC d1ea 73 0 dwarf2reader::CULineInfoHandler::DefineDir(std::string const&, unsigned int)
+d1ea 13 52 30
+d1fd 45 54 30
+d242 15 55 30
+d257 6 56 30
+d25d 1 56 30
+FUNC d25e 23b 0 dwarf2reader::CULineInfoHandler::DefineFile(std::string const&, int, unsigned int, unsigned long long, unsigned long long)
+d25e 2c 60 30
+d28a 45 62 30
+d2cf 2f 65 30
+d2fe 24 66 30
+d322 b 68 30
+d32d e 69 30
+d33b 19 71 30
+d354 17 72 30
+d36b 93 74 30
+d3fe 64 77 30
+d462 30 79 30
+d492 7 81 30
+d499 1 81 30
+d49a 14 38 30
+d4ae 36 40 30
+d4e4 41 43 30
+d525 41 44 30
+d566 67 45 30
+d5cd 10 46 30
+d5dd 13 45 30
+d5f0 15 47 30
+d605 e 48 30
+d613 3d 49 30
+d650 20 50 30
+d670 14 38 30
+d684 36 40 30
+d6ba 41 43 30
+d6fb 41 44 30
+d73c 67 45 30
+d7a3 10 46 30
+d7b3 13 45 30
+d7c6 15 47 30
+d7db e 48 30
+d7e9 3d 49 30
+d826 20 50 30
+d846 12 125 74
+d858 12 125 74
+d86a 13 55 32
+d87d 35 55 32
+d8b2 13 98 32
+d8c5 35 98 32
+d8fa c 35 32
+d906 d 35 32
+d913 1 35 32
+d914 d 22 32
+d921 40 22 32
+d961 1 22 32
+d962 c 89 70
+d96e 1e 90 70
+d998 14 208 34
+d9ac c 190 67
+d9b8 a 190 67
+d9c2 c 259 67
+d9ce 21 259 67
+d9ef 1 259 67
+FUNC d9f0 13 0 std::auto_ptr<dwarf2reader::LineInfo>::operator->() const
+d9f0 c 283 35
+d9fc 7 286 67
+da03 1 286 67
+da11 5c 104 68
+da6d 1 104 68
+FUNC da6e 28 0 bool std::operator==<char, std::char_traits<char>, std::allocator<char> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, char const*)
+da6e c 2139 37
+da7a 1c 2140 37
+FUNC da96 5d 0 std::basic_string<char, std::char_traits<char>, std::allocator<char> > std::operator+<char, std::char_traits<char>, std::allocator<char> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, char const*)
+da96 d 2081 37
+daa3 12 2083 37
+dab5 1a 2084 37
+dacf 24 2085 37
+daf3 1 2085 37
+FUNC daf4 5d 0 std::basic_string<char, std::char_traits<char>, std::allocator<char> > std::operator+<char, std::char_traits<char>, std::allocator<char> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)
+daf4 d 2044 37
+db01 12 2046 37
+db13 1a 2047 37
+db2d 24 2048 37
+db51 1 2048 37
+db52 c 84 70
+db5e 17 85 70
+db75 1 85 70
+FUNC db76 2d 0 std::pair<char const*, unsigned int> std::make_pair<char const*, unsigned int>(char const*, unsigned int)
+db76 c 144 37
+db82 21 145 70
+dba3 1 145 70
+dba4 c 84 70
+dbb0 23 85 70
+dbd3 1 85 70
+FUNC dbd4 3c 0 std::pair<unsigned long long, std::pair<char const*, unsigned int> > std::make_pair<unsigned long long, std::pair<char const*, unsigned int> >(unsigned long long, std::pair<char const*, unsigned int>)
+dbd4 1c 144 37
+dbf0 20 145 70
+dc10 d 89 70
+dc1d 64 90 70
+dc81 1 90 70
+dc82 c 89 70
+dc8e 2a 90 70
+dcb8 c 84 70
+dcc4 1d 85 70
+dce1 1 85 70
+FUNC dce2 3c 0 std::pair<unsigned long long, dwarf2reader::FunctionInfo*> std::make_pair<unsigned long long, dwarf2reader::FunctionInfo*>(unsigned long long, dwarf2reader::FunctionInfo*)
+dce2 1c 144 37
+dcfe 20 145 70
+dd2a a 190 34
+dd40 d 194 34
+dd4d 1 194 34
+dd4e c 603 72
+dd5a c 603 72
+FUNC dd66 2b 0 std::vector<std::string, std::allocator<std::string> >::begin() const
+dd66 c 342 39
+dd72 1f 343 71
+dd91 1 343 71
+FUNC dd92 2c 0 std::vector<std::string, std::allocator<std::string> >::end() const
+dd92 c 360 39
+dd9e 20 361 71
+ddca 5 666 72
+ddcf 1 666 72
+dddd 2b 759 72
+FUNC de08 3c 0 std::vector<std::string, std::allocator<std::string> >::size() const
+de08 c 402 39
+de14 30 403 71
+FUNC de44 2b 0 std::vector<dwarf2reader::SourceFileInfo, std::allocator<dwarf2reader::SourceFileInfo> >::begin() const
+de44 c 342 39
+de50 1f 343 71
+de6f 1 343 71
+FUNC de70 2c 0 std::vector<dwarf2reader::SourceFileInfo, std::allocator<dwarf2reader::SourceFileInfo> >::end() const
+de70 c 360 39
+de7c 20 361 71
+dea9 31 759 72
+FUNC deda 3c 0 std::vector<dwarf2reader::SourceFileInfo, std::allocator<dwarf2reader::SourceFileInfo> >::size() const
+deda c 402 39
+dee6 30 403 71
+df16 c 603 72
+df22 c 603 72
+FUNC df2e 26 0 std::vector<std::string, std::allocator<std::string> >::end()
+df2e c 351 39
+df3a 1a 352 71
+df60 7 614 72
+df67 1 614 72
+FUNC df68 13 0 std::vector<std::string, std::allocator<std::string> >::max_size() const
+df68 c 407 39
+df74 7 408 71
+df7b 1 408 71
+df88 5 666 72
+df8d 1 666 72
+df9a d 623 72
+dfa7 5 624 72
+FUNC dfac 23 0 std::vector<std::string, std::allocator<std::string> >::begin()
+dfac c 333 39
+dfb8 17 334 71
+dfcf 1 334 71
+dfd0 c 35 32
+dfdc 26 35 32
+e00f 5c 104 68
+e06b 1 104 68
+e078 7 614 72
+e07f 1 614 72
+FUNC e080 35 0 dwarf2reader::SourceFileInfo::operator=(dwarf2reader::SourceFileInfo const&)
+e080 c 35 39
+e08c 29 35 32
+e0b5 1 35 32
+FUNC e0b6 13 0 std::vector<dwarf2reader::SourceFileInfo, std::allocator<dwarf2reader::SourceFileInfo> >::max_size() const
+e0b6 c 407 39
+e0c2 7 408 71
+e0c9 1 408 71
+e0d6 d 623 72
+e0e3 5 624 72
+FUNC e0e8 3c 0 std::vector<dwarf2reader::SourceFileInfo, std::allocator<dwarf2reader::SourceFileInfo> >::_M_range_check(unsigned long) const
+e0e8 13 515 39
+e0fb 15 517 71
+e110 14 518 71
+FUNC e124 3c 0 std::vector<std::string, std::allocator<std::string> >::_M_range_check(unsigned long) const
+e124 13 515 39
+e137 15 517 71
+e14c 14 518 71
+e16c 2a 654 72
+FUNC e196 42 0 std::vector<std::string, std::allocator<std::string> >::operator[](unsigned long)
+e196 c 494 39
+e1a2 36 495 71
+FUNC e1d8 32 0 std::vector<std::string, std::allocator<std::string> >::at(unsigned long)
+e1d8 c 534 39
+e1e4 12 536 71
+e1f6 14 537 71
+e216 32 654 72
+FUNC e248 42 0 std::vector<dwarf2reader::SourceFileInfo, std::allocator<dwarf2reader::SourceFileInfo> >::operator[](unsigned long)
+e248 c 494 39
+e254 36 495 71
+FUNC e28a 32 0 std::vector<dwarf2reader::SourceFileInfo, std::allocator<dwarf2reader::SourceFileInfo> >::at(unsigned long)
+e28a c 534 39
+e296 12 536 71
+e2a8 14 537 71
+FUNC e2bc 14 0 std::_Rb_tree<unsigned long long, std::pair<unsigned long long const, std::pair<std::string, unsigned int> >, std::_Select1st<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > >, std::less<unsigned long long>, std::allocator<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > > >::_M_end()
+e2bc c 472 40
+e2c8 8 473 40
+FUNC e2d0 11 0 std::_Select1st<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > >::operator()(std::pair<unsigned long long const, std::pair<std::string, unsigned int> > const&) const
+e2d0 c 550 41
+e2dc 5 551 41
+e2e1 1 551 41
+FUNC e2e2 53 0 std::less<unsigned long long>::operator()(unsigned long long const&, unsigned long long const&) const
+e2e2 c 226 41
+e2ee 47 227 41
+e335 1 227 41
+FUNC e336 20 0 std::_Rb_tree_iterator<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > >::operator==(std::_Rb_tree_iterator<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > > const&) const
+e336 c 209 41
+e342 14 210 40
+e356 c 84 70
+e362 18 85 70
+FUNC e37a 14 0 std::_Rb_tree<unsigned long long, std::pair<unsigned long long const, dwarf2reader::FunctionInfo*>, std::_Select1st<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> >, std::less<unsigned long long>, std::allocator<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> > >::_M_end()
+e37a c 472 41
+e386 8 473 40
+FUNC e38e 11 0 std::_Select1st<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> >::operator()(std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> const&) const
+e38e c 550 41
+e39a 5 551 41
+e39f 1 551 41
+FUNC e3a0 20 0 std::_Rb_tree_iterator<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> >::operator==(std::_Rb_tree_iterator<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> > const&) const
+e3a0 c 209 41
+e3ac 14 210 40
+e3c0 c 84 70
+e3cc 18 85 70
+e3e4 c 180 34
+e3f0 13 181 34
+e403 1 181 34
+e410 22 409 34
+e43e d 207 42
+e44b 1 207 42
+FUNC e44c 35 0 bool __gnu_cxx::operator!=<std::string*, std::vector<std::string, std::allocator<std::string> > >(__gnu_cxx::__normal_iterator<std::string*, std::vector<std::string, std::allocator<std::string> > > const&, __gnu_cxx::__normal_iterator<std::string*, std::vector<std::string, std::allocator<std::string> > > const&)
+e44c d 699 42
+e459 28 700 72
+e481 1 700 72
+FUNC e482 4b 0 void std::_Destroy<__gnu_cxx::__normal_iterator<std::string*, std::vector<std::string, std::allocator<std::string> > >, std::allocator<std::string> >(__gnu_cxx::__normal_iterator<std::string*, std::vector<std::string, std::allocator<std::string> > >, __gnu_cxx::__normal_iterator<std::string*, std::vector<std::string, std::allocator<std::string> > >, std::allocator<std::string>)
+e482 c 171 43
+e48e 2 173 73
+e490 1a 174 73
+e4aa 21 173 73
+e4cb 2 174 73
+e4cd 1 174 73
+FUNC e4ce 35 0 bool __gnu_cxx::operator!=<dwarf2reader::SourceFileInfo*, std::vector<dwarf2reader::SourceFileInfo, std::allocator<dwarf2reader::SourceFileInfo> > >(__gnu_cxx::__normal_iterator<dwarf2reader::SourceFileInfo*, std::vector<dwarf2reader::SourceFileInfo, std::allocator<dwarf2reader::SourceFileInfo> > > const&, __gnu_cxx::__normal_iterator<dwarf2reader::SourceFileInfo*, std::vector<dwarf2reader::SourceFileInfo, std::allocator<dwarf2reader::SourceFileInfo> > > const&)
+e4ce d 699 43
+e4db 28 700 72
+e503 1 700 72
+FUNC e504 4b 0 void std::_Destroy<__gnu_cxx::__normal_iterator<dwarf2reader::SourceFileInfo*, std::vector<dwarf2reader::SourceFileInfo, std::allocator<dwarf2reader::SourceFileInfo> > >, std::allocator<dwarf2reader::SourceFileInfo> >(__gnu_cxx::__normal_iterator<dwarf2reader::SourceFileInfo*, std::vector<dwarf2reader::SourceFileInfo, std::allocator<dwarf2reader::SourceFileInfo> > >, __gnu_cxx::__normal_iterator<dwarf2reader::SourceFileInfo*, std::vector<dwarf2reader::SourceFileInfo, std::allocator<dwarf2reader::SourceFileInfo> > >, std::allocator<dwarf2reader::SourceFileInfo>)
+e504 c 171 43
+e510 2 173 73
+e512 1a 174 73
+e52c 21 173 73
+e54d 2 174 73
+e54f 1 174 73
+FUNC e550 14 0 std::_Rb_tree<unsigned long long, std::pair<unsigned long long const, std::pair<std::string, unsigned int> >, std::_Select1st<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > >, std::less<unsigned long long>, std::allocator<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > > >::_S_value(std::_Rb_tree_node<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > > const*)
+e550 c 480 43
+e55c 8 481 40
+FUNC e564 28 0 std::_Rb_tree<unsigned long long, std::pair<unsigned long long const, std::pair<std::string, unsigned int> >, std::_Select1st<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > >, std::less<unsigned long long>, std::allocator<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > > >::_S_key(std::_Rb_tree_node<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > > const*)
+e564 c 484 43
+e570 1c 485 40
+FUNC e58c 25 0 std::_Rb_tree_iterator<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> >::operator--()
+e58c c 194 43
+e598 14 196 40
+e5ac 5 197 40
+e5b1 1 197 40
+FUNC e5b2 25 0 std::_Rb_tree_iterator<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > >::operator--()
+e5b2 c 194 43
+e5be 14 196 40
+e5d2 5 197 40
+e5d7 1 197 40
+FUNC e5d8 14 0 std::_Rb_tree<unsigned long long, std::pair<unsigned long long const, std::pair<std::string, unsigned int> >, std::_Select1st<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > >, std::less<unsigned long long>, std::allocator<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > > >::_S_value(std::_Rb_tree_node_base const*)
+e5d8 c 504 43
+e5e4 8 505 40
+FUNC e5ec 28 0 std::_Rb_tree<unsigned long long, std::pair<unsigned long long const, std::pair<std::string, unsigned int> >, std::_Select1st<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > >, std::less<unsigned long long>, std::allocator<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > > >::_S_key(std::_Rb_tree_node_base const*)
+e5ec c 508 43
+e5f8 1c 509 40
+FUNC e614 14 0 std::_Rb_tree<unsigned long long, std::pair<unsigned long long const, dwarf2reader::FunctionInfo*>, std::_Select1st<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> >, std::less<unsigned long long>, std::allocator<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> > >::_S_value(std::_Rb_tree_node<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> > const*)
+e614 c 480 43
+e620 8 481 40
+FUNC e628 28 0 std::_Rb_tree<unsigned long long, std::pair<unsigned long long const, dwarf2reader::FunctionInfo*>, std::_Select1st<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> >, std::less<unsigned long long>, std::allocator<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> > >::_S_key(std::_Rb_tree_node<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> > const*)
+e628 c 484 43
+e634 1c 485 40
+FUNC e650 14 0 std::_Rb_tree<unsigned long long, std::pair<unsigned long long const, dwarf2reader::FunctionInfo*>, std::_Select1st<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> >, std::less<unsigned long long>, std::allocator<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> > >::_S_value(std::_Rb_tree_node_base const*)
+e650 c 504 43
+e65c 8 505 40
+FUNC e664 28 0 std::_Rb_tree<unsigned long long, std::pair<unsigned long long const, dwarf2reader::FunctionInfo*>, std::_Select1st<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> >, std::less<unsigned long long>, std::allocator<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> > >::_S_key(std::_Rb_tree_node_base const*)
+e664 c 508 43
+e670 1c 509 40
+e698 7 614 72
+e69f 1 614 72
+e6ac 7 98 68
+e6b3 1 98 68
+e6c0 1d 85 68
+e6dd 5 86 68
+e6e2 10 88 68
+FUNC e6f2 2a 0 std::_Vector_base<std::string, std::allocator<std::string> >::_M_allocate(unsigned long)
+e6f2 c 116 43
+e6fe 1e 117 71
+e728 7 98 68
+e72f 1 98 68
+e73c 1d 85 68
+e759 5 86 68
+e75e 16 88 68
+FUNC e774 2a 0 std::_Vector_base<dwarf2reader::SourceFileInfo, std::allocator<dwarf2reader::SourceFileInfo> >::_M_allocate(unsigned long)
+e774 c 116 43
+e780 1e 117 71
+e7aa 3a 104 68
+e7f0 2a 654 72
+FUNC e81a 42 0 std::vector<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*, std::allocator<__gnu_cxx::_Hashtable_node<std::pair<std::string const, std::pair<char const*, unsigned long long> > >*> >::operator[](unsigned long) const
+e81a c 509 43
+e826 36 510 71
+FUNC e85c 4e 0 std::string* std::__copy_backward<false, std::random_access_iterator_tag>::copy_b<std::string*, std::string*>(std::string*, std::string*, std::string*)
+e85c c 408 61
+e868 14 411 61
+e87c 1e 412 61
+e89a b 411 61
+e8a5 5 413 61
+FUNC e8aa 2b 0 std::string* std::__copy_backward_aux<std::string*, std::string*>(std::string*, std::string*, std::string*)
+e8aa c 432 44
+e8b6 4 440 61
+e8ba 1b 443 61
+e8d5 1 443 61
+e8e4 56 482 61
+e946 4 514 61
+e94a 4 515 61
+e94e 1b 517 61
+e969 1 517 61
+FUNC e96a 69 0 void std::_Construct<std::string, std::string>(std::string*, std::string const&)
+e96a d 77 44
+e977 5c 81 73
+e9d3 1 81 73
+FUNC e9d4 54 0 dwarf2reader::SourceFileInfo* std::__copy_backward<false, std::random_access_iterator_tag>::copy_b<dwarf2reader::SourceFileInfo*, dwarf2reader::SourceFileInfo*>(dwarf2reader::SourceFileInfo*, dwarf2reader::SourceFileInfo*, dwarf2reader::SourceFileInfo*)
+e9d4 c 408 61
+e9e0 1a 411 61
+e9fa 1e 412 61
+ea18 b 411 61
+ea23 5 413 61
+FUNC ea28 2b 0 dwarf2reader::SourceFileInfo* std::__copy_backward_aux<dwarf2reader::SourceFileInfo*, dwarf2reader::SourceFileInfo*>(dwarf2reader::SourceFileInfo*, dwarf2reader::SourceFileInfo*, dwarf2reader::SourceFileInfo*)
+ea28 c 432 44
+ea34 4 440 61
+ea38 1b 443 61
+ea53 1 443 61
+ea62 56 482 61
+eac4 4 514 61
+eac8 4 515 61
+eacc 1b 517 61
+eae7 1 517 61
+FUNC eae8 69 0 void std::_Construct<dwarf2reader::SourceFileInfo, dwarf2reader::SourceFileInfo>(dwarf2reader::SourceFileInfo*, dwarf2reader::SourceFileInfo const&)
+eae8 d 77 44
+eaf5 5c 81 73
+eb51 1 81 73
+eb52 c 69 70
+eb5e 20 69 70
+eb7e c 69 70
+eb8a 2a 69 70
+ebc1 5c 104 68
+ec1d 1 104 68
+ec2a 15 523 34
+ec3f 79 525 34
+ecb8 21 529 34
+ecd9 1 529 34
+ece6 14 229 42
+ed06 7 98 68
+ed0d 1 98 68
+ed1a 1d 85 68
+ed37 5 86 68
+ed3c 10 88 68
+FUNC ed4c 29 0 std::_Rb_tree<unsigned long long, std::pair<unsigned long long const, std::pair<std::string, unsigned int> >, std::_Select1st<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > >, std::less<unsigned long long>, std::allocator<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > > >::_M_get_node()
+ed4c c 355 44
+ed58 1d 356 40
+ed75 1 356 40
+FUNC ed76 b6 0 std::_Rb_tree<unsigned long long, std::pair<unsigned long long const, std::pair<std::string, unsigned int> >, std::_Select1st<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > >, std::less<unsigned long long>, std::allocator<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > > >::_M_create_node(std::pair<unsigned long long const, std::pair<std::string, unsigned int> > const&)
+ed76 d 363 44
+ed83 e 365 40
+ed91 3c 367 40
+edcd b 373 40
+edd8 11 367 40
+ede9 b 368 40
+edf4 12 370 40
+ee06 b 371 40
+ee11 13 368 40
+ee24 8 373 40
+FUNC ee2c cd 0 std::_Rb_tree<unsigned long long, std::pair<unsigned long long const, std::pair<std::string, unsigned int> >, std::_Select1st<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > >, std::less<unsigned long long>, std::allocator<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > > >::_M_insert(std::_Rb_tree_node_base*, std::_Rb_tree_node_base*, std::pair<unsigned long long const, std::pair<std::string, unsigned int> > const&)
+ee2c d 787 44
+ee39 15 789 40
+ee4e 5d 792 40
+eeab 24 796 40
+eecf f 798 40
+eede 1b 799 40
+eef9 1 799 40
+FUNC eefa 1ef 0 std::_Rb_tree<unsigned long long, std::pair<unsigned long long const, std::pair<std::string, unsigned int> >, std::_Select1st<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > >, std::less<unsigned long long>, std::allocator<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > > >::insert_unique(std::pair<unsigned long long const, std::pair<std::string, unsigned int> > const&)
+eefa d 869 44
+ef07 e 871 40
+ef15 e 872 40
+ef23 4 873 40
+ef27 2 874 40
+ef29 6 876 40
+ef2f 35 877 40
+ef64 2a 878 40
+ef8e 6 874 40
+ef94 12 880 40
+efa6 a 881 40
+efb0 24 882 40
+efd4 51 883 40
+f025 b 885 40
+f030 36 886 40
+f066 4e 887 40
+f0b4 35 888 40
+f0e9 1 888 40
+FUNC f0ea 20 0 std::map<unsigned long long, std::pair<std::string, unsigned int>, std::less<unsigned long long>, std::allocator<std::pair<unsigned long long const, std::pair<std::string, unsigned int> > > >::insert(std::pair<unsigned long long const, std::pair<std::string, unsigned int> > const&)
+f0ea c 359 45
+f0f6 14 360 45
+f116 7 98 68
+f11d 1 98 68
+f12a 1d 85 68
+f147 5 86 68
+f14c 1d 88 68
+f169 1 88 68
+FUNC f16a 29 0 std::_Rb_tree<unsigned long long, std::pair<unsigned long long const, dwarf2reader::FunctionInfo*>, std::_Select1st<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> >, std::less<unsigned long long>, std::allocator<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> > >::_M_get_node()
+f16a c 355 45
+f176 1d 356 40
+f193 1 356 40
+FUNC f194 5f 0 std::_Rb_tree<unsigned long long, std::pair<unsigned long long const, dwarf2reader::FunctionInfo*>, std::_Select1st<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> >, std::less<unsigned long long>, std::allocator<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> > >::_M_create_node(std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> const&)
+f194 d 363 45
+f1a1 e 365 40
+f1af 3c 367 40
+f1eb 8 373 40
+f1f3 1 373 40
+FUNC f1f4 cd 0 std::_Rb_tree<unsigned long long, std::pair<unsigned long long const, dwarf2reader::FunctionInfo*>, std::_Select1st<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> >, std::less<unsigned long long>, std::allocator<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> > >::_M_insert(std::_Rb_tree_node_base*, std::_Rb_tree_node_base*, std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> const&)
+f1f4 d 787 45
+f201 15 789 40
+f216 5d 792 40
+f273 24 796 40
+f297 f 798 40
+f2a6 1b 799 40
+f2c1 1 799 40
+FUNC f2c2 1ef 0 std::_Rb_tree<unsigned long long, std::pair<unsigned long long const, dwarf2reader::FunctionInfo*>, std::_Select1st<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> >, std::less<unsigned long long>, std::allocator<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> > >::insert_unique(std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> const&)
+f2c2 d 869 45
+f2cf e 871 40
+f2dd e 872 40
+f2eb 4 873 40
+f2ef 2 874 40
+f2f1 6 876 40
+f2f7 35 877 40
+f32c 2a 878 40
+f356 6 874 40
+f35c 12 880 40
+f36e a 881 40
+f378 24 882 40
+f39c 51 883 40
+f3ed b 885 40
+f3f8 36 886 40
+f42e 4e 887 40
+f47c 35 888 40
+f4b1 1 888 40
+FUNC f4b2 20 0 std::map<unsigned long long, dwarf2reader::FunctionInfo*, std::less<unsigned long long>, std::allocator<std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> > >::insert(std::pair<unsigned long long const, dwarf2reader::FunctionInfo*> const&)
+f4b2 c 359 45
+f4be 14 360 45
+FUNC f4d2 19 0 void std::_Destroy<std::string>(std::string*)
+f4d2 c 106 45
+f4de d 107 73
+f4eb 1 107 73
+FUNC f4ec 44 0 void std::__destroy_aux<__gnu_cxx::__normal_iterator<std::string*, std::vector<std::string, std::allocator<std::string> > > >(__gnu_cxx::__normal_iterator<std::string*, std::vector<std::string, std::allocator<std::string> > >, __gnu_cxx::__normal_iterator<std::string*, std::vector<std::string, std::allocator<std::string> > >, __false_type)
+f4ec c 119 45
+f4f8 2 121 73
+f4fa 13 122 73
+f50d 21 121 73
+f52e 2 122 73
+FUNC f530 28 0 void std::_Destroy<__gnu_cxx::__normal_iterator<std::string*, std::vector<std::string, std::allocator<std::string> > > >(__gnu_cxx::__normal_iterator<std::string*, std::vector<std::string, std::allocator<std::string> > >, __gnu_cxx::__normal_iterator<std::string*, std::vector<std::string, std::allocator<std::string> > >)
+f530 c 148 45
+f53c 1c 155 73
+f565 6 82 79
+f56b 2 85 79
+f56d 24 86 79
+f591 2c 85 79
+f5bd b 87 79
+f5c8 b 89 79
+f5d3 12 91 79
+f5e5 b 92 79
+f5f0 13 89 79
+f603 9 92 79
+f618 23 113 79
+f63b 1 113 79
+f648 1b 254 79
+f663 1 254 79
+FUNC f664 430 0 std::vector<std::string, std::allocator<std::string> >::_M_insert_aux(__gnu_cxx::__normal_iterator<std::string*, std::vector<std::string, std::allocator<std::string> > >, std::string const&)
+f664 14 249 47
+f678 14 251 78
+f68c 22 253 78
+f6ae f 255 78
+f6bd 12 256 78
+f6cf 55 257 78
+f724 4b 260 78
+f76f e 264 78
+f77d 15 265 78
+f792 e 266 78
+f7a0 1d 271 78
+f7bd 8 272 78
+f7c5 e 273 78
+f7d3 27 275 78
+f7fa 6 276 78
+f800 55 279 78
+f855 25 284 78
+f87a b 285 78
+f885 4f 286 78
+f8d4 3 284 78
+f8d7 13 279 78
+f8ea e 286 78
+f8f8 4d 298 78
+f945 30 299 78
+f975 12 302 78
+f987 13 303 78
+f99a 23 304 78
+f9bd 3 298 78
+f9c0 13 286 78
+f9d3 b 292 78
+f9de 39 294 78
+fa17 23 295 78
+fa3a 8 296 78
+fa42 16 294 78
+fa58 3 296 78
+fa5b 19 292 78
+fa74 19 298 78
+fa8d 7 304 78
+FUNC fa94 70 0 std::vector<std::string, std::allocator<std::string> >::push_back(std::string const&)
+fa94 c 602 47
+faa0 10 604 71
+fab0 1e 606 71
+face 11 607 71
+fadf 25 610 71
+FUNC fb04 19 0 void std::_Destroy<dwarf2reader::SourceFileInfo>(dwarf2reader::SourceFileInfo*)
+fb04 c 106 47
+fb10 d 107 73
+fb1d 1 107 73
+FUNC fb1e 44 0 void std::__destroy_aux<__gnu_cxx::__normal_iterator<dwarf2reader::SourceFileInfo*, std::vector<dwarf2reader::SourceFileInfo, std::allocator<dwarf2reader::SourceFileInfo> > > >(__gnu_cxx::__normal_iterator<dwarf2reader::SourceFileInfo*, std::vector<dwarf2reader::SourceFileInfo, std::allocator<dwarf2reader::SourceFileInfo> > >, __gnu_cxx::__normal_iterator<dwarf2reader::SourceFileInfo*, std::vector<dwarf2reader::SourceFileInfo, std::allocator<dwarf2reader::SourceFileInfo> > >, __false_type)
+fb1e c 119 47
+fb2a 2 121 73
+fb2c 13 122 73
+fb3f 21 121 73
+fb60 2 122 73
+FUNC fb62 28 0 void std::_Destroy<__gnu_cxx::__normal_iterator<dwarf2reader::SourceFileInfo*, std::vector<dwarf2reader::SourceFileInfo, std::allocator<dwarf2reader::SourceFileInfo> > > >(__gnu_cxx::__normal_iterator<dwarf2reader::SourceFileInfo*, std::vector<dwarf2reader::SourceFileInfo, std::allocator<dwarf2reader::SourceFileInfo> > >, __gnu_cxx::__normal_iterator<dwarf2reader::SourceFileInfo*, std::vector<dwarf2reader::SourceFileInfo, std::allocator<dwarf2reader::SourceFileInfo> > >)
+fb62 c 148 47
+fb6e 1c 155 73
+fb97 6 82 79
+fb9d 2 85 79
+fb9f 24 86 79
+fbc3 2c 85 79
+fbef b 87 79
+fbfa b 89 79
+fc05 12 91 79
+fc17 b 92 79
+fc22 13 89 79
+fc35 9 92 79
+fc4a 23 113 79
+fc6d 1 113 79
+fc7a 1b 254 79
+fc95 1 254 79
+FUNC fc96 43d 0 std::vector<dwarf2reader::SourceFileInfo, std::allocator<dwarf2reader::SourceFileInfo> >::_M_insert_aux(__gnu_cxx::__normal_iterator<dwarf2reader::SourceFileInfo*, std::vector<dwarf2reader::SourceFileInfo, std::allocator<dwarf2reader::SourceFileInfo> > >, dwarf2reader::SourceFileInfo const&)
+fc96 14 249 47
+fcaa 14 251 78
+fcbe 22 253 78
+fce0 f 255 78
+fcef 12 256 78
+fd01 55 257 78
+fd56 4b 260 78
+fda1 e 264 78
+fdaf 15 265 78
+fdc4 e 266 78
+fdd2 1d 271 78
+fdef 8 272 78
+fdf7 e 273 78
+fe05 27 275 78
+fe2c 6 276 78
+fe32 55 279 78
+fe87 25 284 78
+feac b 285 78
+feb7 4f 286 78
+ff06 3 284 78
+ff09 13 279 78
+ff1c e 286 78
+ff2a 4d 298 78
+ff77 36 299 78
+ffad 12 302 78
+ffbf 13 303 78
+ffd2 2a 304 78
+fffc 3 298 78
+ffff 13 286 78
+10012 b 292 78
+1001d 39 294 78
+10056 23 295 78
+10079 8 296 78
+10081 16 294 78
+10097 3 296 78
+1009a 19 292 78
+100b3 19 298 78
+100cc 7 304 78
+100d3 1 304 78
+FUNC 100d4 70 0 std::vector<dwarf2reader::SourceFileInfo, std::allocator<dwarf2reader::SourceFileInfo> >::push_back(dwarf2reader::SourceFileInfo const&)
+100d4 c 602 47
+100e0 10 604 71
+100f0 1e 606 71
+1010e 11 607 71
+1011f 25 610 71
+FUNC 10144 16c 0 Start
+10144 17 610 71
+1015b 40 49 48
+1019b 6 51 48
+101a1 3f 53 48
+101e0 7 54 48
+101e7 5 55 48
+101ec 2a 58 48
+10216 61 61 48
+10277 7 62 48
+1027e 2 63 48
+10280 29 66 48
+102a9 7 67 48
+FUNC 102b0 108 0 Usage
+102b0 19 70 48
+102c9 30 71 48
+102f9 29 73 48
+10322 30 74 48
+10352 30 75 48
+10382 30 76 48
+103b2 6 77 48
+FUNC 103b8 3af 0 SetupOptions
+103b8 21 80 48
+103d9 8 82 48
+103e1 6 85 48
+103e7 10 86 48
+103f7 2e 88 48
+10425 2f 94 48
+10454 2a 91 48
+1047e 23 95 48
+104a1 3e 97 48
+104df 11 98 48
+104f0 7c 99 48
+1056c c 100 48
+10578 5 99 48
+1057d 3e 101 48
+105bb 11 102 48
+105cc 3e 103 48
+1060a 11 104 48
+1061b 37 106 48
+10652 b 107 48
+1065d c 108 48
+10669 b 113 48
+10674 c 114 48
+10680 14 119 48
+10694 30 120 48
+106c4 b 121 48
+106cf c 122 48
+106db 81 127 48
+1075c b 128 48
+10767 1 128 48
+FUNC 10768 a7 0 main
+10768 13 131 48
+1077b 37 132 48
+107b2 1e 135 48
+107d0 e 136 48
+107de 8 137 48
+107e6 17 139 48
+107fd c 141 48
+10809 6 142 48
+1080f 1 142 48
+10810 c 47 49
+1081c 1a 48 49
+10836 2 49 49
+10838 c 47 49
+10844 1a 48 49
+1085e 2 49 49
+FUNC 10860 cb 0 google_breakpad::FileID::FileIdentifier(unsigned char*)
+10860 f 51 49
+1086f 16 52 49
+10885 6 53 49
+1088b f 54 49
+1089a b 57 49
+108a5 7 62 49
+108ac 2 63 49
+108ae 1c 64 49
+108ca 32 63 49
+108fc b 67 49
+10907 12 68 49
+10919 10 70 49
+10929 2 71 49
+1092b 1 71 49
+FUNC 1092c f2 0 google_breakpad::FileID::MachoIdentifier(int, unsigned char*)
+1092c 10 73 49
+1093c 15 74 49
+10951 20 76 49
+10971 f 77 49
+10980 20 79 49
+109a0 c 80 49
+109ac 69 82 49
+10a15 9 83 49
+FUNC 10a1e fb 0 google_breakpad::FileID::ConvertIdentifierToString(unsigned char const*, char*, int)
+10a1e c 87 49
+10a2a 7 88 49
+10a31 c 89 49
+10a3d 15 90 49
+10a52 12 91 49
+10a64 18 93 49
+10a7c e 94 49
+10a8a 2b 96 49
+10ab5 2b 97 49
+10ae0 17 89 49
+10af7 20 101 49
+10b17 2 102 49
+10b19 1 102 49
+FUNC 10b1a 13 0 NXHostByteOrder
+10b1a c 144 56
+10b26 5 147 56
+10b2b 2 153 56
+10b2d 1 153 56
+10b2e c 56 51
+10b3a 1a 57 51
+10b54 1e 58 51
+10b72 2 59 51
+10b74 c 56 51
+10b80 1a 57 51
+10b9a 1e 58 51
+10bb8 2 59 51
+10bba c 61 51
+10bc6 e 62 51
+10bd4 11 63 51
+10be5 2 64 51
+10be7 1 64 51
+10be8 c 61 51
+10bf4 e 62 51
+10c02 11 63 51
+10c13 2 64 51
+10c15 1 64 51
+FUNC 10c16 477 0 MacFileUtilities::MachoID::UpdateCRC(unsigned char*, unsigned long)
+10c16 c 74 51
+10c22 11 82 51
+10c33 14 83 51
+10c47 5 86 51
+10c4c 9 87 51
+10c55 7 88 51
+10c5c 18b 90 51
+10de7 6 91 51
+10ded 14 89 51
+10e01 23 93 51
+10e24 23 94 51
+10e47 d 86 51
+10e54 f 98 51
+10e63 6 100 51
+10e69 18b 101 51
+10ff4 6 102 51
+10ffa c 99 51
+11006 13 105 51
+11019 8 106 51
+11021 10 104 51
+11031 23 108 51
+11054 23 109 51
+11077 14 110 51
+1108b 2 112 51
+1108d 1 112 51
+FUNC 1108e 2c 0 MacFileUtilities::MachoID::UpdateMD5(unsigned char*, unsigned long)
+1108e c 114 51
+1109a 1e 115 51
+110b8 2 116 51
+FUNC 110ba 2c 0 MacFileUtilities::MachoID::UpdateSHA1(unsigned char*, unsigned long)
+110ba c 118 51
+110c6 1e 119 51
+110e4 2 120 51
+FUNC 110e6 121 0 MacFileUtilities::MachoID::Update(MacFileUtilities::MachoWalker*, unsigned long, unsigned long)
+110e6 f 122 51
+110f5 1b 123 51
+11110 e 129 51
+1111e 5 130 51
+11123 9 131 51
+1112c 7 132 51
+11133 a 133 51
+1113d 6 135 51
+11143 7 136 51
+1114a 35 139 51
+1117f 6c 142 51
+111eb 10 143 51
+111fb a 130 51
+11205 2 145 51
+11207 1 145 51
+FUNC 11208 cf 0 MacFileUtilities::MachoID::UUIDCommand(int, unsigned char*)
+11208 14 147 51
+1121c 25 149 51
+11241 7 151 51
+11248 19 152 51
+11261 9 153 51
+1126a 8 157 51
+11272 1f 158 51
+11291 9 159 51
+1129a 36 162 51
+112d0 7 163 51
+112d7 1 163 51
+FUNC 112d8 224 0 MacFileUtilities::MachoID::IDCommand(int, unsigned char*)
+112d8 15 165 51
+112ed 25 167 51
+11312 7 169 51
+11319 19 170 51
+11332 c 171 51
+1133e c 175 51
+1134a 6 180 51
+11350 7 181 51
+11357 9 182 51
+11360 9 183 51
+11369 28 185 51
+11391 33 186 51
+113c4 1e 185 51
+113e2 10 189 51
+113f2 10 190 51
+11402 10 191 51
+11412 d 192 51
+1141f 10 193 51
+1142f 10 194 51
+1143f 10 195 51
+1144f d 196 51
+1145c 17 197 51
+11473 17 198 51
+1148a 17 199 51
+114a1 14 200 51
+114b5 9 202 51
+114be 36 205 51
+114f4 8 206 51
+FUNC 114fc d1 0 MacFileUtilities::MachoID::Adler32(int)
+114fc 14 208 51
+11510 25 209 51
+11535 27 210 51
+1155c d 211 51
+11569 19 213 51
+11582 9 214 51
+1158b 3b 216 51
+115c6 7 217 51
+115cd 1 217 51
+FUNC 115ce f8 0 MacFileUtilities::MachoID::MD5(int, unsigned char*)
+115ce 14 219 51
+115e2 25 220 51
+11607 27 221 51
+1162e 19 223 51
+11647 19 224 51
+11660 9 225 51
+11669 17 227 51
+11680 9 228 51
+11689 36 231 51
+116bf 7 232 51
+FUNC 116c6 f8 0 MacFileUtilities::MachoID::SHA1(int, unsigned char*)
+116c6 14 234 51
+116da 25 235 51
+116ff 27 236 51
+11726 19 238 51
+1173f 19 239 51
+11758 9 240 51
+11761 17 242 51
+11778 9 243 51
+11781 36 246 51
+117b7 7 247 51
+FUNC 117be 378 0 MacFileUtilities::MachoID::WalkerCB(MacFileUtilities::MachoWalker*, load_command*, long long, bool, void*)
+117be 2b 251 51
+117e9 6 252 51
+117ef e 254 51
+117fd 38 257 51
+11835 f 258 51
+11844 9 260 51
+1184d 17 261 51
+11864 20 266 51
+11884 f 267 51
+11893 d 271 51
+118a0 c 273 51
+118ac 38 274 51
+118e4 f 275 51
+118f3 9 277 51
+118fc 1f 278 51
+1191b 14 282 51
+1192f 2b 283 51
+1195a d 285 51
+11967 19 273 51
+11980 e 287 51
+1198e 38 290 51
+119c6 f 291 51
+119d5 9 293 51
+119de 17 294 51
+119f5 20 299 51
+11a15 f 300 51
+11a24 d 304 51
+11a31 c 306 51
+11a3d 38 307 51
+11a75 f 308 51
+11a84 9 310 51
+11a8d 1f 311 51
+11aac 1a 315 51
+11ac6 39 316 51
+11aff d 318 51
+11b0c 11 306 51
+11b1d 10 323 51
+11b2d 9 324 51
+FUNC 11b36 95 0 MacFileUtilities::MachoID::UUIDWalkerCB(MacFileUtilities::MachoWalker*, load_command*, long long, bool, void*)
+11b36 1e 328 51
+11b54 a 329 51
+11b5e 6 331 51
+11b64 2f 333 51
+11b93 9 335 51
+11b9c 6 337 51
+11ba2 14 338 51
+11bb6 9 340 51
+11bbf a 344 51
+11bc9 2 345 51
+11bcb 1 345 51
+FUNC 11bcc 95 0 MacFileUtilities::MachoID::IDWalkerCB(MacFileUtilities::MachoWalker*, load_command*, long long, bool, void*)
+11bcc 1e 349 51
+11bea a 350 51
+11bf4 6 351 51
+11bfa 2f 353 51
+11c29 9 354 51
+11c32 6 356 51
+11c38 14 357 51
+11c4c 9 359 51
+11c55 a 363 51
+11c5f 2 364 51
+11c61 1 364 51
+FUNC 11c62 1c 0 _OSSwapInt32
+11c62 f 53 55
+11c71 8 55 55
+11c79 3 56 55
+11c7c 2 57 55
+FUNC 11c7e 19 0 NXSwapInt
+11c7e f 52 56
+11c8d 8 54 56
+11c95 2 55 56
+11c97 1 55 56
+FUNC 11c98 13 0 NXHostByteOrder
+11c98 c 144 56
+11ca4 5 147 56
+11ca9 2 153 56
+11cab 1 153 56
+11cac c 52 54
+11cb8 12 54 54
+11cca 1a 55 54
+11ce4 2 56 54
+11ce6 c 52 54
+11cf2 12 54 54
+11d04 1a 55 54
+11d1e 2 56 54
+11d20 c 58 54
+11d2c a 59 54
+11d36 d 60 54
+11d43 2 61 54
+11d45 1 61 54
+11d46 c 58 54
+11d52 a 59 54
+11d5c d 60 54
+11d69 2 61 54
+11d6b 1 61 54
+FUNC 11d6c 37 0 MacFileUtilities::MachoWalker::ValidateCPUType(int)
+11d6c c 63 54
+11d78 6 66 54
+11d7e 8 67 54
+11d86 6 68 54
+11d8c b 69 54
+11d97 7 74 54
+11d9e 3 80 54
+11da1 2 81 54
+11da3 1 81 54
+FUNC 11da4 50 0 MacFileUtilities::MachoWalker::ReadBytes(void*, unsigned long, long long)
+11da4 18 96 54
+11dbc 36 97 54
+11df2 2 98 54
+FUNC 11df4 73 0 MacFileUtilities::MachoWalker::CurrentHeader(mach_header_64*, long long*)
+11df4 c 100 54
+11e00 a 101 54
+11e0a 37 102 54
+11e41 11 103 54
+11e52 9 104 54
+11e5b a 107 54
+11e65 2 108 54
+11e67 1 108 54
+FUNC 11e68 2a6 0 MacFileUtilities::MachoWalker::FindHeader(int, long long&)
+11e68 c 110 54
+11e74 15 111 54
+11e89 31 114 54
+11eba c 115 54
+11ec6 10 117 54
+11ed6 4 120 54
+11eda 14 121 54
+11eee 4 122 54
+11ef2 11 129 54
+11f03 28 124 54
+11f2b c 126 54
+11f37 31 133 54
+11f68 c 134 54
+11f74 14 136 54
+11f88 b 137 54
+11f93 8 139 54
+11f9b c 140 54
+11fa7 10 142 54
+11fb7 c 143 54
+11fc3 10 146 54
+11fd3 31 148 54
+12004 c 149 54
+12010 f 151 54
+1201f 14 152 54
+12033 16 154 54
+12049 c 158 54
+12055 31 159 54
+12086 9 160 54
+1208f f 162 54
+1209e 1c 163 54
+120ba 8 165 54
+120c2 10 166 54
+120d2 9 167 54
+120db 16 170 54
+120f1 11 158 54
+12102 a 174 54
+1210c 2 175 54
+FUNC 1210e 109 0 MacFileUtilities::MachoWalker::WalkHeaderCore(long long, unsigned int, bool)
+1210e 1e 224 54
+1212c c 225 54
+12138 2f 227 54
+12167 c 228 54
+12173 6 230 54
+12179 14 231 54
+1218d 5b 234 54
+121e8 12 237 54
+121fa 11 225 54
+1220b a 240 54
+12215 2 241 54
+12217 1 241 54
+FUNC 12218 10e 0 MacFileUtilities::MachoWalker::WalkHeader64AtOffset(long long)
+12218 18 203 54
+12230 2f 205 54
+1225f c 206 54
+1226b e 208 54
+12279 6 209 54
+1227f 14 210 54
+12293 9 212 54
+1229c a 213 54
+122a6 f 214 54
+122b5 15 215 54
+122ca 2b 216 54
+122f5 a 217 54
+122ff a 218 54
+12309 11 219 54
+1231a a 220 54
+12324 2 221 54
+FUNC 12326 143 0 MacFileUtilities::MachoWalker::WalkHeaderAtOffset(long long)
+12326 18 177 54
+1233e 2f 179 54
+1236d c 180 54
+12379 e 182 54
+12387 6 183 54
+1238d 14 184 54
+123a1 2e 189 54
+123cf 7 190 54
+123d6 9 192 54
+123df a 193 54
+123e9 f 194 54
+123f8 15 195 54
+1240d 2b 196 54
+12438 a 197 54
+12442 a 198 54
+1244c 11 199 54
+1245d a 200 54
+12467 2 201 54
+12469 1 201 54
+FUNC 1246a 99 0 MacFileUtilities::MachoWalker::WalkHeader(int)
+1246a c 83 54
+12476 15 84 54
+1248b 1d 86 54
+124a8 d 87 54
+124b5 21 88 54
+124d6 21 90 54
+124f7 a 93 54
+12501 2 94 54
+12503 1 94 54
+FUNC 12504 1c 0 _OSSwapInt32
+12504 f 53 55
+12513 8 55 55
+1251b 3 56 55
+1251e 2 57 55
+FUNC 12520 2b 0 _OSSwapInt64
+12520 12 64 55
+12532 11 69 55
+12543 6 70 55
+12549 2 71 55
+1254b 1 71 55
+FUNC 1254c 19 0 NXSwapLong
+1254c f 61 56
+1255b 8 63 56
+12563 2 64 56
+12565 1 64 56
+FUNC 12566 1f 0 NXSwapLongLong
+12566 12 70 56
+12578 b 72 56
+12583 2 73 56
+12585 1 73 56
+FUNC 12586 32 0 breakpad_swap_uuid_command(breakpad_uuid_command*, NXByteOrder)
+12586 c 37 57
+12592 11 39 57
+125a3 13 40 57
+125b6 2 41 57
+FUNC 125b8 da 0 breakpad_swap_segment_command_64(segment_command_64*, NXByteOrder)
+125b8 c 44 57
+125c4 11 46 57
+125d5 13 47 57
+125e8 17 49 57
+125ff 17 50 57
+12616 17 51 57
+1262d 17 52 57
+12644 13 54 57
+12657 13 55 57
+1266a 13 56 57
+1267d 13 57 57
+12690 2 58 57
+FUNC 12692 a4 0 breakpad_swap_mach_header_64(mach_header_64*, NXByteOrder)
+12692 c 61 57
+1269e 11 63 57
+126af 13 64 57
+126c2 13 65 57
+126d5 13 66 57
+126e8 13 67 57
+126fb 13 68 57
+1270e 13 69 57
+12721 13 70 57
+12734 2 71 57
+FUNC 12736 1d1 0 breakpad_swap_section_64(section_64*, unsigned int, NXByteOrder)
+12736 d 75 57
+12743 c 77 57
+1274f 33 78 57
+12782 33 79 57
+127b5 2d 81 57
+127e2 2d 82 57
+1280f 2d 83 57
+1283c 2d 84 57
+12869 2d 85 57
+12896 2d 86 57
+128c3 2d 87 57
+128f0 11 77 57
+12901 6 89 57
+12907 1 89 57
+12908 12 9 58
+1291a 4f 11 58
+12969 2 12 58
+1296b 1 12 58
+1296c 12 9 58
+1297e 4f 11 58
+129cd 2 12 58
+129cf 1 12 58
+129d0 13 14 58
+129e3 2a 14 58
+12a0d 1 14 58
+12a0e 13 14 58
+12a21 2a 14 58
+12a4b 1 14 58
+12a4c 13 14 58
+12a5f 2a 14 58
+12a89 1 14 58
+FUNC 12a8a bb 0 dwarf2reader::ByteReader::SetOffsetSize(unsigned char)
+12a8a 19 16 58
+12aa3 a 17 58
+12aad 48 18 58
+12af5 6 19 58
+12afb 23 20 58
+12b1e 21 22 58
+12b3f 6 24 58
+12b45 1 24 58
+FUNC 12b46 bb 0 dwarf2reader::ByteReader::SetAddressSize(unsigned char)
+12b46 19 26 58
+12b5f a 27 58
+12b69 48 28 58
+12bb1 6 29 58
+12bb7 23 30 58
+12bda 21 32 58
+12bfb 6 34 58
+12c01 1 34 58
+FUNC 12c02 a2 0 dwarf2reader::ByteReader::ReadFourBytes(char const*) const
+12c02 c 24 59
+12c0e c 25 64
+12c1a d 26 64
+12c27 f 27 64
+12c36 f 28 64
+12c45 b 29 64
+12c50 27 30 64
+12c77 2b 32 64
+12ca2 2 34 64
+FUNC 12ca4 40e 0 dwarf2reader::ByteReader::ReadEightBytes(char const*) const
+12ca4 11 36 59
+12cb5 1a 37 64
+12ccf 1b 38 64
+12cea 1d 39 64
+12d07 1d 40 64
+12d24 1d 41 64
+12d41 1d 42 64
+12d5e 1d 43 64
+12d7b 1d 44 64
+12d98 f 45 64
+12da7 18f 47 64
+12f36 172 50 64
+130a8 a 52 64
+130b2 2 52 64
+FUNC 130b4 a6 0 ReadInitialLength
+130b4 15 29 60
+130c9 18 30 60
+130e1 6 31 60
+130e7 d 35 60
+130f4 13 36 60
+13107 9 37 60
+13110 1a 38 60
+1312a 13 40 60
+1313d 9 41 60
+13146 12 43 60
+13158 2 44 60
+1315a 1f 47 60
+13179 65 50 60
+131de 1f 47 60
+131fd 65 50 60
+FUNC 13262 393 0 dwarf2reader::CompilationUnit::SkipAttribute(char const*, dwarf2reader::DwarfForm)
+13262 14 133 60
+13276 82 136 60
+132f8 1f 139 60
+13317 a 140 60
+13321 21 141 60
+13342 c 147 60
+1334e e 151 60
+1335c e 155 60
+1336a e 159 60
+13378 27 162 60
+1339f 1c 166 60
+133bb 10 167 60
+133cb 1c 171 60
+133e7 10 172 60
+133f7 1e 175 60
+13415 56 180 60
+1346b d 181 60
+13478 1e 182 60
+13496 11 183 60
+134a7 1e 184 60
+134c5 24 189 60
+134e9 26 192 60
+1350f 23 195 60
+13532 22 198 60
+13554 15 199 60
+13569 1b 203 60
+13584 30 206 60
+135b4 30 208 60
+135e4 a 209 60
+135ee 7 210 60
+135f5 1 210 60
+FUNC 135f6 29b 0 dwarf2reader::CompilationUnit::ReadHeader()
+135f6 14 217 60
+1360a 9 218 60
+13613 4e 221 60
+13661 17 223 60
+13678 a 224 60
+13682 f 225 60
+13691 4e 227 60
+136df 1e 228 60
+136fd 6 229 60
+13703 5e 231 60
+13761 1e 232 60
+1377f 18 233 60
+13797 4c 235 60
+137e3 1d 236 60
+13800 1c 237 60
+1381c 5 238 60
+13821 9 240 60
+1382a 60 245 60
+1388a 7 247 60
+13891 1 247 60
+FUNC 13892 a57 0 dwarf2reader::CompilationUnit::ProcessAttribute(unsigned long long, char const*, dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm)
+13892 24 299 60
+138b6 8a 302 60
+13940 1f 307 60
+1395f a 308 60
+13969 36 309 60
+1399f 5b 316 60
+139fa c 317 60
+13a06 5b 322 60
+13a61 e 323 60
+13a6f 55 328 60
+13ac4 e 329 60
+13ad2 55 334 60
+13b27 e 335 60
+13b35 6 338 60
+13b3b 9a 340 60
+13bd5 33 341 60
+13c08 25 340 60
+13c2d 5c 348 60
+13c89 10 349 60
+13c99 5c 354 60
+13cf5 10 355 60
+13d05 55 359 60
+13d5a 1e 360 60
+13d78 56 365 60
+13dce d 366 60
+13ddb 55 368 60
+13e30 1e 369 60
+13e4e 11 370 60
+13e5f 55 372 60
+13eb4 1e 373 60
+13ed2 29 378 60
+13efb 4a 380 60
+13f45 f 381 60
+13f54 29 385 60
+13f7d 4c 387 60
+13fc9 11 388 60
+13fda 1b 392 60
+13ff5 4c 394 60
+14041 11 395 60
+14052 22 399 60
+14074 4e 401 60
+140c2 15 402 60
+140d7 3c 406 60
+14113 1b 408 60
+1412e 54 409 60
+14182 f 411 60
+14191 9a 413 60
+1422b 24 414 60
+1424f 25 413 60
+14274 30 418 60
+142a4 30 420 60
+142d4 a 421 60
+142de b 422 60
+142e9 1 422 60
+142ea 1f 489 60
+14309 3a 491 60
+14343 a 492 60
+1434d 6 493 60
+14353 1 493 60
+14354 1f 489 60
+14373 3a 491 60
+143ad a 492 60
+143b7 6 493 60
+143bd 1 493 60
+FUNC 143be b5 0 dwarf2reader::CompilationUnit::ProcessDIE(unsigned long long, char const*, dwarf2reader::CompilationUnit::Abbrev const&)
+143be 19 426 60
+143d7 13 427 60
+143ea 46 430 60
+14430 3a 427 60
+1446a 3 432 60
+1446d 6 433 60
+14473 1 433 60
+FUNC 14474 85 0 dwarf2reader::CompilationUnit::SkipDIE(char const*, dwarf2reader::CompilationUnit::Abbrev const&)
+14474 c 122 60
+14480 13 123 60
+14493 27 126 60
+144ba 3a 123 60
+144f4 3 128 60
+144f7 2 129 60
+144f9 1 129 60
+FUNC 144fa be4 0 dwarf2reader::LineInfo::ProcessOneOpcode(dwarf2reader::ByteReader*, dwarf2reader::LineInfoHandler*, dwarf2reader::LineInfoHeader const&, char const*, dwarf2reader::LineStateMachine*, unsigned long*, unsigned long, bool*)
+144fa 18 593 60
+14512 a 594 60
+1451c 18 596 60
+14534 8 597 60
+1453c 5 598 60
+14541 19 602 60
+1455a f 603 60
+14569 50 605 60
+145b9 46 607 60
+145ff e0 610 60
+146df 6 612 60
+146e5 22 615 60
+14707 22 616 60
+14729 7 617 60
+14730 b 618 60
+1473b f 619 60
+1474a 5a 623 60
+147a4 7 625 60
+147ab b 626 60
+147b6 f 627 60
+147c5 28 631 60
+147ed e 632 60
+147fb 144 635 60
+1493f 6 637 60
+14945 9e 640 60
+149e3 5 642 60
+149e8 22 644 60
+14a0a e 645 60
+14a18 1c 646 60
+14a34 2b 652 60
+14a5f b 653 60
+14a6a 22 658 60
+14a8c e 659 60
+14a9a 8 660 60
+14aa2 5 662 60
+14aa7 22 664 60
+14ac9 e 665 60
+14ad7 9 666 60
+14ae0 5 668 60
+14ae5 12 670 60
+14af7 5 672 60
+14afc 7 674 60
+14b03 5 676 60
+14b08 16 678 60
+14b1e 9 679 60
+14b27 d9 682 60
+14c00 6 684 60
+14c06 1f 687 60
+14c25 5 689 60
+14c2a 40 693 60
+14c6a d6 696 60
+14d40 6 698 60
+14d46 1c 701 60
+14d62 5 703 60
+14d67 1f 706 60
+14d86 d 707 60
+14d93 13 708 60
+14da6 26 710 60
+14dcc 5 711 60
+14dd1 50 713 60
+14e21 7 715 60
+14e28 b 716 60
+14e33 f 717 60
+14e42 18 725 60
+14e5a f 726 60
+14e69 5 728 60
+14e6e 6 730 60
+14e74 28 732 60
+14e9c d 733 60
+14ea9 22 735 60
+14ecb e 736 60
+14ed9 22 739 60
+14efb e 740 60
+14f09 22 743 60
+14f2b e 744 60
+14f39 a 746 60
+14f43 fd 748 60
+15040 a 758 60
+1504a 9 759 60
+15053 1c 761 60
+1506f d 762 60
+1507c e 763 60
+1508a 2e 759 60
+150b8 b 769 60
+150c3 10 770 60
+150d3 b 771 60
+FUNC 150de 14b 0 dwarf2reader::LineInfo::ReadLines()
+150de e 773 60
+150ec 9 778 60
+150f5 17 782 60
+1510c 8 783 60
+15114 6 785 60
+1511a 9 787 60
+15123 5 788 60
+15128 19 789 60
+15141 5 790 60
+15146 4a 793 60
+15190 6 794 60
+15196 4a 796 60
+151e0 a 797 60
+151ea f 790 60
+151f9 15 788 60
+1520e 14 801 60
+15222 7 802 60
+15229 1 802 60
+FUNC 1522a 4fd 0 dwarf2reader::CompilationUnit::ReadAbbrevs()
+1522a 18 60 60
+15242 e 61 60
+15250 58 65 60
+152a8 38 66 60
+152e0 44 65 60
+15324 2a 66 60
+1534e 45 68 60
+15393 16 69 60
+153a9 1d 75 60
+153c6 6 76 60
+153cc 40 77 60
+1540c b 80 60
+15417 1f 82 60
+15436 e 84 60
+15444 6 77 60
+1544a 1f 68 60
+15469 a 84 60
+15473 1d 79 60
+15490 6 86 60
+15496 a 87 60
+154a0 3d 89 60
+154dd 1f 90 60
+154fc a 91 60
+15506 6 92 60
+1550c 3d 94 60
+15549 1d 95 60
+15566 5 96 60
+1556b 3d 98 60
+155a8 1f 101 60
+155c7 a 102 60
+155d1 3d 104 60
+1560e 1f 105 60
+1562d a 106 60
+15637 c 107 60
+15643 6 111 60
+15649 6 112 60
+1564f 32 113 60
+15681 47 115 60
+156c8 30 116 60
+156f8 24 79 60
+1571c b 118 60
+15727 1 118 60
+FUNC 15728 5dc 0 dwarf2reader::LineInfo::ReadHeader()
+15728 18 503 60
+15740 9 504 60
+15749 17 508 60
+15760 a 510 60
+1576a f 511 60
+15779 60 512 60
+157d9 44 516 60
+1581d 1e 518 60
+1583b 6 519 60
+15841 1e 521 60
+1585f 18 522 60
+15877 1d 524 60
+15894 5 525 60
+15899 20 527 60
+158b9 5 528 60
+158be c 530 60
+158ca 5 531 60
+158cf 1d 533 60
+158ec 5 534 60
+158f1 1d 536 60
+1590e 5 537 60
+15913 45 539 60
+15958 1f 540 60
+15977 19 541 60
+15990 15 542 60
+159a5 1f 539 60
+159c4 30 543 60
+159f4 5 544 60
+159f9 14 542 60
+15a0d e 548 60
+15a1b 7 549 60
+15a22 5 550 60
+15a27 6 551 60
+15a2d 8b 552 60
+15ab8 28 553 60
+15ae0 5 554 60
+15ae5 16 550 60
+15afb 25 552 60
+15b20 5 557 60
+15b25 e 560 60
+15b33 7 561 60
+15b3a 5 563 60
+15b3f 6 564 60
+15b45 28 565 60
+15b6d 22 567 60
+15b8f a 568 60
+15b99 22 570 60
+15bbb a 571 60
+15bc5 22 573 60
+15be7 a 574 60
+15bf1 ba 576 60
+15cab 5 577 60
+15cb0 16 563 60
+15cc6 25 576 60
+15ceb 5 580 60
+15cf0 9 582 60
+15cf9 b 583 60
+FUNC 15d04 3d 0 dwarf2reader::LineInfo::Start()
+15d04 c 495 60
+15d10 b 496 60
+15d1b b 497 60
+15d26 19 498 60
+15d3f 2 499 60
+15d41 1 499 60
+FUNC 15d42 304 0 dwarf2reader::CompilationUnit::ProcessDIEs()
+15d42 11 435 60
+15d53 9 436 60
+15d5c 9 441 60
+15d65 17 445 60
+15d7c 8 446 60
+15d84 6 448 60
+15d8a 6c 453 60
+15df6 8 455 60
+15dfe 16 453 60
+15e14 3 455 60
+15e17 2f 453 60
+15e46 29 458 60
+15e6f 22 460 60
+15e91 a 462 60
+15e9b a 465 60
+15ea5 1e 466 60
+15ec3 13 467 60
+15ed6 2b 468 60
+15f01 18 472 60
+15f19 9 473 60
+15f22 42 474 60
+15f64 1e 475 60
+15f82 2a 477 60
+15fac b 480 60
+15fb7 1e 481 60
+15fd5 26 483 60
+15ffb 1d 455 60
+16018 24 485 60
+1603c a 486 60
+FUNC 16046 35f 0 dwarf2reader::CompilationUnit::Start()
+16046 18 249 60
+1605e 58 251 60
+160b6 35 252 60
+160eb 32 251 60
+1611d 2a 252 60
+16147 20 255 60
+16167 37 256 60
+1619e b 259 60
+161a9 f 264 60
+161b8 17 265 60
+161cf c 266 60
+161db a 268 60
+161e5 95 271 60
+1627a 11 276 60
+1628b b 279 60
+16296 58 282 60
+162ee 2f 283 60
+1631d 32 282 60
+1634f 14 284 60
+16363 1a 285 60
+1637d b 289 60
+16388 12 291 60
+1639a b 292 60
+163a5 1 292 60
+FUNC 163a6 3a 0 std::fill(unsigned char*, unsigned char*, unsigned char const&)
+163a6 c 573 61
+163b2 9 576 61
+163bb 23 577 61
+163de 2 578 61
+FUNC 163e0 33 0 std::__deque_buf_size(unsigned long)
+163e0 c 83 62
+163ec 27 84 62
+16413 1 84 62
+FUNC 16414 18 0 dwarf2reader::ByteReader::OffsetSize() const
+16414 c 38 63
+16420 c 38 63
+FUNC 1642c 18 0 dwarf2reader::ByteReader::AddressSize() const
+1642c c 41 63
+16438 c 41 63
+FUNC 16444 17 0 dwarf2reader::ByteReader::ReadOneByte(char const*) const
+16444 c 10 64
+16450 9 11 64
+16459 2 12 64
+1645b 1 12 64
+FUNC 1645c 63 0 dwarf2reader::ByteReader::ReadTwoBytes(char const*) const
+1645c c 14 64
+16468 d 15 64
+16475 e 16 64
+16483 b 17 64
+1648e 17 18 64
+164a5 18 20 64
+164bd 2 22 64
+164bf 1 22 64
+FUNC 164c0 98 0 dwarf2reader::ByteReader::ReadUnsignedLEB128(char const*, unsigned long*) const
+164c0 e 59 64
+164ce e 60 64
+164dc 7 61 64
+164e3 7 62 64
+164ea e 66 64
+164f8 5 67 64
+164fd 38 69 64
+16535 6 71 64
+1653b 8 65 64
+16543 8 75 64
+1654b 6 77 64
+16551 7 78 64
+FUNC 16558 ee 0 dwarf2reader::ByteReader::ReadSignedLEB128(char const*, unsigned long*) const
+16558 e 84 64
+16566 e 85 64
+16574 7 86 64
+1657b 7 87 64
+16582 e 91 64
+16590 5 92 64
+16595 44 93 64
+165d9 6 94 64
+165df 8 90 64
+165e7 14 97 64
+165fb 36 98 64
+16631 8 99 64
+16639 6 100 64
+1663f 7 101 64
+FUNC 16646 a2 0 dwarf2reader::ByteReader::ReadOffset(char const*) const
+16646 13 103 64
+16659 3f 104 64
+16698 4a 105 64
+166e2 6 106 64
+FUNC 166e8 a2 0 dwarf2reader::ByteReader::ReadAddress(char const*) const
+166e8 13 108 64
+166fb 3f 109 64
+1673a 4a 110 64
+16784 6 111 64
+FUNC 1678a 61 0 dwarf2reader::LineStateMachine::Reset(bool)
+1678a 12 12 65
+1679c 9 13 65
+167a5 11 14 65
+167b6 11 15 65
+167c7 a 16 65
+167d1 a 17 65
+167db 7 18 65
+167e2 7 19 65
+167e9 2 20 65
+167eb 1 20 65
+FUNC 167ec 20 0 std::_List_const_iterator<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> >::operator!=(std::_List_const_iterator<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> > const&) const
+167ec c 253 66
+167f8 14 254 66
+FUNC 1680c 25 0 std::_List_const_iterator<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> >::operator++(int)
+1680c c 226 66
+16818 8 228 66
+16820 c 229 66
+1682c 5 230 66
+16831 1 230 66
+FUNC 16832 16 0 std::_List_const_iterator<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> >::operator->() const
+16832 c 215 66
+1683e a 216 66
+16848 c 190 67
+16854 a 190 67
+FUNC 1685e 13 0 std::auto_ptr<std::stack<unsigned long long, std::deque<unsigned long long, std::allocator<unsigned long long> > > >::operator->() const
+1685e c 283 67
+1686a 7 286 67
+16871 1 286 67
+16872 c 65 68
+1687e 2 65 68
+16880 c 97 69
+1688c d 97 69
+16899 1 97 69
+1689a c 99 69
+168a6 14 100 69
+168ba c 97 69
+168c6 d 97 69
+168d3 1 97 69
+168d4 c 84 70
+168e0 17 85 70
+168f7 1 85 70
+FUNC 168f8 2d 0 std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> std::make_pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm>(dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm)
+168f8 c 144 70
+16904 21 145 70
+16925 1 145 70
+16926 c 202 66
+16932 a 203 66
+FUNC 1693c 25 0 std::list<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm>, std::allocator<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> > >::begin() const
+1693c c 588 70
+16948 19 589 66
+16961 1 589 66
+FUNC 16962 23 0 std::list<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm>, std::allocator<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> > >::end() const
+16962 c 605 70
+1696e 17 606 66
+16985 1 606 66
+16986 c 65 68
+16992 2 65 68
+16994 c 72 68
+169a0 2 72 68
+169a2 c 97 69
+169ae d 97 69
+169bb 1 97 69
+169bc c 105 69
+169c8 d 105 69
+169d5 1 105 69
+169d6 c 105 69
+169e2 d 105 69
+169ef 1 105 69
+169f0 c 67 68
+169fc 2 67 68
+169fe c 99 69
+16a0a 14 100 69
+16a1e c 99 69
+16a2a 14 100 69
+16a3e c 129 62
+16a4a 30 131 62
+16a7a c 65 68
+16a86 2 65 68
+16a88 c 72 68
+16a94 2 72 68
+16a96 c 97 69
+16aa2 d 97 69
+16aaf 1 97 69
+16ab0 c 105 69
+16abc d 105 69
+16ac9 1 105 69
+16aca c 105 69
+16ad6 d 105 69
+16ae3 1 105 69
+16ae4 c 67 68
+16af0 2 67 68
+16af2 c 99 69
+16afe 14 100 69
+16b12 c 99 69
+16b1e 14 100 69
+FUNC 16b32 2b 0 std::_Vector_base<unsigned char, std::allocator<unsigned char> >::get_allocator() const
+16b32 10 93 71
+16b42 1b 94 71
+16b5d 1 94 71
+16b6a 7 614 72
+16b71 1 614 72
+16b72 c 80 71
+16b7e d 80 71
+16b8b 1 80 71
+16b98 2 107 68
+FUNC 16b9a 2d 0 void std::_Destroy<unsigned char*, std::allocator<unsigned char> >(unsigned char*, unsigned char*, std::allocator<unsigned char>)
+16b9a c 171 73
+16ba6 2 173 73
+16ba8 12 174 73
+16bba b 173 73
+16bc5 2 174 73
+16bc7 1 174 73
+16bc8 c 84 71
+16bd4 2f 85 71
+16c03 2 86 71
+16c05 1 86 71
+16c06 c 96 71
+16c12 12 97 71
+16c24 2 98 71
+FUNC 16c26 1f 0 std::_List_base<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm>, std::allocator<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> > >::_M_init()
+16c26 c 338 73
+16c32 8 340 66
+16c3a b 341 66
+16c45 1 341 66
+16c46 c 105 69
+16c52 d 105 69
+16c5f 1 105 69
+16c60 c 125 66
+16c6c a 126 66
+FUNC 16c76 25 0 std::list<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm>, std::allocator<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> > >::begin()
+16c76 c 579 73
+16c82 19 580 66
+16c9b 1 580 66
+FUNC 16c9c 23 0 std::list<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm>, std::allocator<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> > >::end()
+16c9c c 597 73
+16ca8 17 597 66
+16cbf 1 597 66
+16cc0 c 603 72
+16ccc c 603 72
+FUNC 16cd8 2b 0 std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> >::begin() const
+16cd8 c 342 73
+16ce4 1f 343 71
+16d03 1 343 71
+FUNC 16d04 2c 0 std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> >::end() const
+16d04 c 360 73
+16d10 20 361 71
+16d3c 5 666 72
+16d41 1 666 72
+16d4f 31 759 72
+FUNC 16d80 3c 0 std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> >::size() const
+16d80 c 402 73
+16d8c 30 403 71
+16dbc c 603 72
+16dc8 c 603 72
+FUNC 16dd4 23 0 std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> >::begin()
+16dd4 c 333 73
+16de0 17 334 71
+16df7 1 334 71
+16e04 33 654 72
+16e37 1 654 72
+FUNC 16e38 26 0 std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> >::end()
+16e38 c 351 73
+16e44 1a 352 71
+16e6a 7 614 72
+16e71 1 614 72
+FUNC 16e72 42 0 std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> >::operator[](unsigned long)
+16e72 c 494 73
+16e7e 36 495 71
+FUNC 16eb4 13 0 std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> >::max_size() const
+16eb4 c 407 73
+16ec0 7 408 71
+16ec7 1 408 71
+16ed4 5 666 72
+16ed9 1 666 72
+16ee6 d 623 72
+16ef3 5 624 72
+16ef8 c 382 62
+16f04 d 382 62
+16f11 1 382 62
+FUNC 16f12 2b 0 std::_Deque_base<unsigned long long, std::allocator<unsigned long long> >::get_allocator() const
+16f12 10 360 73
+16f22 1b 361 62
+16f3d 1 361 62
+FUNC 16f3e 2d 0 std::deque<unsigned long long, std::allocator<unsigned long long> >::get_allocator() const
+16f3e 10 764 73
+16f4e 1d 765 62
+16f6b 1 765 62
+FUNC 16f6c 13 0 std::_Deque_iterator<unsigned long long, unsigned long long&, unsigned long long*>::operator*() const
+16f6c c 134 73
+16f78 7 135 62
+16f7f 1 135 62
+16f8c 2 107 68
+16f8e c 129 62
+16f9a 30 131 62
+FUNC 16fca 2c 0 std::deque<unsigned long long, std::allocator<unsigned long long> >::end() const
+16fca 10 799 73
+16fda 1c 800 62
+FUNC 16ff6 2c 0 std::deque<unsigned long long, std::allocator<unsigned long long> >::begin() const
+16ff6 10 781 73
+17006 1c 782 62
+FUNC 17022 2e 0 std::deque<unsigned long long, std::allocator<unsigned long long> >::end()
+17022 10 790 73
+17032 1e 791 62
+FUNC 17050 3c 0 std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> >::_M_range_check(unsigned long) const
+17050 13 515 73
+17063 15 517 71
+17078 14 518 71
+FUNC 1708c 32 0 std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> >::at(unsigned long)
+1708c c 534 73
+17098 12 536 71
+170aa 14 537 71
+170ca 2e 104 68
+170f8 c 84 71
+17104 2f 85 71
+17133 2 86 71
+17135 1 86 71
+17136 c 96 71
+17142 12 97 71
+17154 2 98 71
+17156 c 603 72
+17162 c 603 72
+FUNC 1716e 23 0 std::vector<unsigned char, std::allocator<unsigned char> >::begin()
+1716e c 333 73
+1717a 17 334 71
+17191 1 334 71
+1719e 27 654 72
+171c5 1 654 72
+FUNC 171c6 42 0 std::vector<unsigned char, std::allocator<unsigned char> >::operator[](unsigned long)
+171c6 c 494 73
+171d2 36 495 71
+FUNC 17208 26 0 std::vector<unsigned char, std::allocator<unsigned char> >::end()
+17208 c 351 73
+17214 1a 352 71
+1723a d 94 68
+17247 1 94 68
+FUNC 17248 2f 0 std::_Vector_base<unsigned char, std::allocator<unsigned char> >::_M_deallocate(unsigned char*, unsigned long)
+17248 c 120 73
+17254 6 122 71
+1725a 1d 123 71
+17277 1 123 71
+17278 c 108 71
+17284 3a 109 71
+172be c 188 71
+172ca 12 189 71
+172dc 2 190 71
+172de c 272 71
+172ea 4b 273 71
+17335 1 273 71
+17336 13 62 74
+17349 10 62 74
+17359 a 63 74
+17363 25 64 74
+17388 1a 66 74
+173a2 13 62 74
+173b5 10 62 74
+173c5 a 63 74
+173cf 25 64 74
+173f4 1a 66 74
+1740e c 188 71
+1741a 12 189 71
+1742c 2 190 71
+1743b 31 759 72
+1746c c 65 68
+17478 2 65 68
+1747a c 103 69
+17486 d 103 69
+17493 1 103 69
+FUNC 17494 2d 0 std::list<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm>, std::allocator<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> > >::get_allocator() const
+17494 10 570 74
+174a4 1d 571 66
+174c1 1 571 66
+174ce 2e 104 68
+FUNC 174fc 20 0 std::_List_iterator<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> >::operator!=(std::_List_iterator<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> > const&) const
+174fc c 172 74
+17508 14 173 66
+FUNC 1751c 1d 0 std::_List_const_iterator<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> >::operator++()
+1751c c 219 74
+17528 c 221 66
+17534 5 222 66
+17539 1 222 66
+FUNC 1753a 1d 0 std::_List_iterator<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> >::operator++()
+1753a c 138 74
+17546 c 140 66
+17552 5 141 66
+17557 1 141 66
+FUNC 17558 16 0 std::_List_const_iterator<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> >::operator*() const
+17558 c 211 74
+17564 a 212 66
+FUNC 1756e 16 0 std::_List_iterator<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> >::operator*() const
+1756e c 130 74
+1757a a 131 66
+FUNC 17584 20 0 std::_List_const_iterator<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> >::operator==(std::_List_const_iterator<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> > const&) const
+17584 c 249 74
+17590 14 250 66
+FUNC 175a4 35 0 bool __gnu_cxx::operator!=<dwarf2reader::CompilationUnit::Abbrev*, std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> > >(__gnu_cxx::__normal_iterator<dwarf2reader::CompilationUnit::Abbrev*, std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> > > const&, __gnu_cxx::__normal_iterator<dwarf2reader::CompilationUnit::Abbrev*, std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> > > const&)
+175a4 d 699 74
+175b1 28 700 72
+175d9 1 700 72
+FUNC 175da 4b 0 void std::_Destroy<__gnu_cxx::__normal_iterator<dwarf2reader::CompilationUnit::Abbrev*, std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> > >, std::allocator<dwarf2reader::CompilationUnit::Abbrev> >(__gnu_cxx::__normal_iterator<dwarf2reader::CompilationUnit::Abbrev*, std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> > >, __gnu_cxx::__normal_iterator<dwarf2reader::CompilationUnit::Abbrev*, std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> > >, std::allocator<dwarf2reader::CompilationUnit::Abbrev>)
+175da c 171 74
+175e6 2 173 73
+175e8 1a 174 73
+17602 21 173 73
+17623 2 174 73
+17625 1 174 73
+17626 c 127 62
+17632 29 127 62
+1765b 1 127 62
+1765c c 388 62
+17668 41 389 62
+176a9 2 390 62
+176ab 1 390 62
+176b8 d 94 68
+176c5 1 94 68
+FUNC 176c6 20 0 bool std::operator==<unsigned long long, unsigned long long&, unsigned long long*>(std::_Deque_iterator<unsigned long long, unsigned long long&, unsigned long long*> const&, std::_Deque_iterator<unsigned long long, unsigned long long&, unsigned long long*> const&)
+176c6 c 243 74
+176d2 14 244 62
+FUNC 176e6 26 0 bool std::operator!=<unsigned long long, unsigned long long&, unsigned long long*>(std::_Deque_iterator<unsigned long long, unsigned long long&, unsigned long long*> const&, std::_Deque_iterator<unsigned long long, unsigned long long&, unsigned long long*> const&)
+176e6 c 256 74
+176f2 1a 257 62
+FUNC 1770c 1a 0 std::_Deque_iterator<unsigned long long, unsigned long long&, unsigned long long*>::_S_buffer_size()
+1770c c 106 74
+17718 e 107 62
+FUNC 17726 3e 0 std::_Deque_iterator<unsigned long long, unsigned long long&, unsigned long long*>::_M_set_node(unsigned long long**)
+17726 d 229 74
+17733 9 231 62
+1773c b 232 62
+17747 1d 233 62
+FUNC 17764 50 0 std::_Deque_iterator<unsigned long long, unsigned long long&, unsigned long long*>::operator++()
+17764 c 142 74
+17770 d 144 62
+1777d f 145 62
+1778c 18 147 62
+177a4 b 148 62
+177af 5 150 62
+FUNC 177b4 4b 0 void std::_Destroy<std::_Deque_iterator<unsigned long long, unsigned long long&, unsigned long long*>, std::allocator<unsigned long long> >(std::_Deque_iterator<unsigned long long, unsigned long long&, unsigned long long*>, std::_Deque_iterator<unsigned long long, unsigned long long&, unsigned long long*>, std::allocator<unsigned long long>)
+177b4 c 171 74
+177c0 2 173 73
+177c2 1a 174 73
+177dc 21 173 73
+177fd 2 174 73
+177ff 1 174 73
+FUNC 17800 50 0 std::_Deque_iterator<unsigned long long, unsigned long long&, unsigned long long*>::operator--()
+17800 c 162 74
+1780c f 164 62
+1781b 18 166 62
+17833 b 167 62
+1783e d 169 62
+1784b 5 170 62
+FUNC 17850 39 0 std::deque<unsigned long long, std::allocator<unsigned long long> >::back()
+17850 c 988 74
+1785c 15 990 62
+17871 b 991 62
+1787c d 992 62
+17889 1 992 62
+FUNC 1788a 19 0 std::stack<unsigned long long, std::deque<unsigned long long, std::allocator<unsigned long long> > >::top()
+1788a c 163 75
+17896 d 166 75
+178a3 1 166 75
+FUNC 178a4 66 0 std::_Deque_iterator<unsigned long long, unsigned long long&, unsigned long long*>::difference_type std::operator-<unsigned long long, unsigned long long&, unsigned long long*, unsigned long long&, unsigned long long*>(std::_Deque_iterator<unsigned long long, unsigned long long&, unsigned long long*> const&, std::_Deque_iterator<unsigned long long, unsigned long long&, unsigned long long*> const&)
+178a4 d 328 75
+178b1 59 333 62
+FUNC 1790a 26 0 std::deque<unsigned long long, std::allocator<unsigned long long> >::size() const
+1790a c 840 75
+17916 1a 841 62
+1793c 36 662 72
+1797e 23 650 72
+179a1 1 650 72
+179a2 c 67 68
+179ae 2 67 68
+179b0 c 99 69
+179bc 14 100 69
+179d0 c 303 66
+179dc 12 304 66
+179ee 2 305 66
+179f0 c 326 66
+179fc 2f 327 66
+17a2b d 328 66
+17a38 c 457 66
+17a44 14 458 66
+17a58 c 211 74
+17a64 2d 211 74
+17a91 1 211 74
+17a9e 7 98 68
+17aa5 1 98 68
+17ab2 1d 85 68
+17acf 5 86 68
+17ad4 17 88 68
+17aeb 1 88 68
+FUNC 17aec 2a 0 std::_Vector_base<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> >::_M_allocate(unsigned long)
+17aec c 116 75
+17af8 1e 117 71
+17b22 d 94 68
+17b2f 1 94 68
+FUNC 17b30 34 0 std::_Deque_base<unsigned long long, std::allocator<unsigned long long> >::_M_deallocate_node(unsigned long long*)
+17b30 c 402 75
+17b3c 28 403 62
+FUNC 17b64 38 0 std::_Deque_base<unsigned long long, std::allocator<unsigned long long> >::_M_destroy_nodes(unsigned long long**, unsigned long long**)
+17b64 c 504 75
+17b70 8 506 62
+17b78 14 507 62
+17b8c e 506 62
+17b9a 2 507 62
+FUNC 17b9c 62 0 std::deque<unsigned long long, std::allocator<unsigned long long> >::_M_pop_back_aux()
+17b9c c 391 76
+17ba8 15 393 76
+17bbd 1b 394 76
+17bd8 f 395 76
+17be7 17 396 76
+FUNC 17bfe 4f 0 std::deque<unsigned long long, std::allocator<unsigned long long> >::pop_back()
+17bfe c 1081 76
+17c0a 10 1083 62
+17c1a f 1086 62
+17c29 17 1087 62
+17c40 d 1090 62
+17c4d 1 1090 62
+FUNC 17c4e 19 0 std::stack<unsigned long long, std::deque<unsigned long long, std::allocator<unsigned long long> > >::pop()
+17c4e c 205 76
+17c5a d 208 75
+17c67 1 208 75
+17c68 c 72 68
+17c74 2 72 68
+17c76 c 105 69
+17c82 d 105 69
+17c8f 1 105 69
+17c90 c 603 72
+17c9c c 603 72
+FUNC 17ca8 2b 0 std::vector<unsigned char, std::allocator<unsigned char> >::begin() const
+17ca8 c 342 76
+17cb4 1f 343 71
+17cd3 1 343 71
+FUNC 17cd4 2c 0 std::vector<unsigned char, std::allocator<unsigned char> >::end() const
+17cd4 c 360 76
+17ce0 20 361 71
+17d0c 5 666 72
+17d11 1 666 72
+17d1f 28 759 72
+17d47 1 759 72
+FUNC 17d48 3c 0 std::vector<unsigned char, std::allocator<unsigned char> >::size() const
+17d48 c 402 76
+17d54 30 403 71
+17d90 d 623 72
+17d9d 5 624 72
+17dae 5 666 72
+17db3 1 666 72
+FUNC 17db4 35 0 bool __gnu_cxx::operator!=<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >(__gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > > const&, __gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > > const&)
+17db4 d 699 76
+17dc1 28 700 72
+17de9 1 700 72
+FUNC 17dea 4b 0 void std::_Destroy<__gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >, std::allocator<unsigned char> >(__gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >, __gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >, std::allocator<unsigned char>)
+17dea c 171 76
+17df6 2 173 73
+17df8 1a 174 73
+17e12 21 173 73
+17e33 2 174 73
+17e35 1 174 73
+17e43 28 759 72
+17e6b 1 759 72
+17e78 2a 662 72
+FUNC 17ea2 13 0 std::vector<unsigned char, std::allocator<unsigned char> >::max_size() const
+17ea2 c 407 76
+17eae 7 408 71
+17eb5 1 408 71
+17ec2 16 650 72
+17ee4 7 98 68
+17eeb 1 98 68
+17ef8 1d 85 68
+17f15 5 86 68
+17f1a 10 88 68
+FUNC 17f2a 29 0 std::_List_base<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm>, std::allocator<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> > >::_M_get_node()
+17f2a c 311 76
+17f36 1d 312 66
+17f53 1 312 66
+FUNC 17f54 5f 0 std::list<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm>, std::allocator<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> > >::_M_create_node(std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> const&)
+17f54 d 435 76
+17f61 e 437 66
+17f6f 3c 440 66
+17fab 8 447 66
+17fb3 1 447 66
+FUNC 17fb4 35 0 std::list<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm>, std::allocator<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> > >::_M_insert(std::_List_iterator<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> >, std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> const&)
+17fb4 c 1149 76
+17fc0 15 1151 66
+17fd5 14 1152 66
+17fe9 1 1152 66
+FUNC 17fea 52 0 void std::list<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm>, std::allocator<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> > >::_M_insert_dispatch<std::_List_const_iterator<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> > >(std::_List_iterator<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> >, std::_List_const_iterator<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> >, std::_List_const_iterator<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> >, __false_type)
+17fea c 1126 66
+17ff6 2 1128 66
+17ff8 21 1129 66
+18019 21 1128 66
+1803a 2 1129 66
+FUNC 1803c 36 0 void std::list<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm>, std::allocator<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> > >::insert<std::_List_const_iterator<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> > >(std::_List_iterator<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> >, std::_List_const_iterator<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> >, std::_List_const_iterator<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> >)
+1803c c 838 66
+18048 2a 842 66
+18072 e 491 66
+18080 32 492 66
+180b2 64 493 66
+18116 c 211 74
+18122 3d 211 74
+1815f 1 211 74
+1816d 5c 104 68
+181c9 1 104 68
+FUNC 181ca 31 0 std::list<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm>, std::allocator<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> > >::push_back(std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> const&)
+181ca c 772 76
+181d6 25 773 66
+181fb 1 773 66
+FUNC 181fc 69 0 void std::_Construct<dwarf2reader::CompilationUnit::Abbrev, dwarf2reader::CompilationUnit::Abbrev>(dwarf2reader::CompilationUnit::Abbrev*, dwarf2reader::CompilationUnit::Abbrev const&)
+181fc d 77 76
+18209 5c 81 73
+18265 1 81 73
+18272 7 98 68
+18279 1 98 68
+18286 1d 85 68
+182a3 5 86 68
+182a8 10 88 68
+182b8 c 65 68
+182c4 2 65 68
+182c6 c 103 69
+182d2 d 103 69
+182df 1 103 69
+FUNC 182e0 4d 0 std::_Deque_base<unsigned long long, std::allocator<unsigned long long> >::_M_get_map_allocator() const
+182e0 11 394 76
+182f1 3c 395 62
+1832d 1 395 62
+FUNC 1832e 75 0 std::_Deque_base<unsigned long long, std::allocator<unsigned long long> >::_M_allocate_map(unsigned long)
+1832e d 406 76
+1833b 68 407 62
+183a3 1 407 62
+FUNC 183a4 47 0 std::_Deque_base<unsigned long long, std::allocator<unsigned long long> >::_M_deallocate_map(unsigned long long**, unsigned long)
+183a4 c 410 76
+183b0 3b 411 62
+183eb 1 411 62
+183ec c 424 62
+183f8 9 426 62
+18401 22 428 62
+18423 2b 430 62
+1844e c 714 62
+1845a 70 715 62
+184ca c 111 75
+184d6 d 111 75
+184e3 1 111 75
+184e4 c 259 67
+184f0 26 259 67
+18522 7 98 68
+18529 1 98 68
+18536 1d 85 68
+18553 5 86 68
+18558 10 88 68
+FUNC 18568 33 0 std::_Deque_base<unsigned long long, std::allocator<unsigned long long> >::_M_allocate_node()
+18568 c 398 76
+18574 27 399 62
+1859b 1 399 62
+FUNC 1859c 82 0 std::_Deque_base<unsigned long long, std::allocator<unsigned long long> >::_M_create_nodes(unsigned long long**, unsigned long long**)
+1859c d 486 76
+185a9 8 491 62
+185b1 12 492 62
+185c3 13 491 62
+185d6 b 494 62
+185e1 19 496 62
+185fa b 497 62
+18605 13 494 62
+18618 6 497 62
+FUNC 1861e 17b 0 std::_Deque_base<unsigned long long, std::allocator<unsigned long long> >::_M_initialize_map(unsigned long)
+1861e d 447 76
+1862b 1e 450 62
+18649 2a 452 62
+18673 1c 454 62
+1868f 19 462 62
+186a8 c 463 62
+186b4 1e 466 62
+186d2 b 467 62
+186dd 1e 469 62
+186fb 9 470 62
+18704 a 471 62
+1870e b 472 62
+18719 13 467 62
+1872c 15 475 62
+18741 18 476 62
+18759 c 477 62
+18765 34 478 62
+18799 1 478 62
+1879a d 366 62
+187a7 12 367 62
+187b9 39 368 62
+187f2 c 645 62
+187fe 1c 646 62
+FUNC 1881a 4d 0 void std::__fill<true>::fill<__gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >, unsigned char>(__gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >, __gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >, unsigned char const&)
+1881a c 539 61
+18826 9 541 61
+1882f 2 542 61
+18831 13 543 61
+18844 21 542 61
+18865 2 543 61
+18867 1 543 61
+FUNC 18868 2b 0 void std::fill<__gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >, unsigned char>(__gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >, __gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >, unsigned char const&)
+18868 c 560 76
+18874 4 567 61
+18878 1b 568 61
+18893 1 568 61
+FUNC 18894 6a 0 std::list<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm>, std::allocator<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> > >::_M_erase(std::_List_iterator<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> >)
+18894 d 1157 76
+188a1 b 1159 66
+188ac 6 1160 66
+188b2 35 1161 66
+188e7 17 1162 66
+FUNC 188fe 37 0 std::list<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm>, std::allocator<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> > >::erase(std::_List_iterator<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> >)
+188fe c 95 77
+1890a 14 97 77
+1891e 12 98 77
+18930 5 99 77
+18935 1 99 77
+FUNC 18936 3e 0 std::list<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm>, std::allocator<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> > >::erase(std::_List_iterator<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> >, std::_List_iterator<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> >)
+18936 c 883 77
+18942 2 885 66
+18944 15 886 66
+18959 16 885 66
+1896f 5 887 66
+FUNC 18974 129 0 std::list<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm>, std::allocator<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> > >::operator=(std::list<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm>, std::allocator<std::pair<dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm> > > const&)
+18974 e 120 77
+18982 c 122 77
+1898e e 124 77
+1899c e 125 77
+189aa e 126 77
+189b8 e 127 77
+189c6 2 128 77
+189c8 20 130 77
+189e8 5a 128 77
+18a42 16 131 77
+18a58 1b 132 77
+18a73 20 134 77
+18a93 a 136 77
+18a9d 1 136 77
+FUNC 18a9e 4c 0 dwarf2reader::CompilationUnit::Abbrev::operator=(dwarf2reader::CompilationUnit::Abbrev const&)
+18a9e c 211 77
+18aaa 40 211 74
+FUNC 18aea 52 0 dwarf2reader::CompilationUnit::Abbrev* std::__copy<false, std::random_access_iterator_tag>::copy<dwarf2reader::CompilationUnit::Abbrev*, dwarf2reader::CompilationUnit::Abbrev*>(dwarf2reader::CompilationUnit::Abbrev*, dwarf2reader::CompilationUnit::Abbrev*, dwarf2reader::CompilationUnit::Abbrev*)
+18aea c 280 61
+18af6 1a 283 61
+18b10 12 285 61
+18b22 4 286 61
+18b26 6 287 61
+18b2c b 283 61
+18b37 5 289 61
+FUNC 18b3c 2b 0 dwarf2reader::CompilationUnit::Abbrev* std::__copy_aux<dwarf2reader::CompilationUnit::Abbrev*, dwarf2reader::CompilationUnit::Abbrev*>(dwarf2reader::CompilationUnit::Abbrev*, dwarf2reader::CompilationUnit::Abbrev*, dwarf2reader::CompilationUnit::Abbrev*)
+18b3c c 307 77
+18b48 4 315 61
+18b4c 1b 317 61
+18b67 1 317 61
+18b76 56 354 61
+18bd8 4 384 61
+18bdc 4 385 61
+18be0 1b 387 61
+18bfb 1 387 61
+FUNC 18bfc ac 0 std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> >::erase(__gnu_cxx::__normal_iterator<dwarf2reader::CompilationUnit::Abbrev*, std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> > >, __gnu_cxx::__normal_iterator<dwarf2reader::CompilationUnit::Abbrev*, std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> > >)
+18bfc d 122 78
+18c09 26 124 78
+18c2f 43 125 78
+18c72 2e 126 78
+18ca0 8 127 78
+FUNC 18ca8 54 0 dwarf2reader::CompilationUnit::Abbrev* std::__copy_backward<false, std::random_access_iterator_tag>::copy_b<dwarf2reader::CompilationUnit::Abbrev*, dwarf2reader::CompilationUnit::Abbrev*>(dwarf2reader::CompilationUnit::Abbrev*, dwarf2reader::CompilationUnit::Abbrev*, dwarf2reader::CompilationUnit::Abbrev*)
+18ca8 c 408 61
+18cb4 1a 411 61
+18cce 1e 412 61
+18cec b 411 61
+18cf7 5 413 61
+FUNC 18cfc 2b 0 dwarf2reader::CompilationUnit::Abbrev* std::__copy_backward_aux<dwarf2reader::CompilationUnit::Abbrev*, dwarf2reader::CompilationUnit::Abbrev*>(dwarf2reader::CompilationUnit::Abbrev*, dwarf2reader::CompilationUnit::Abbrev*, dwarf2reader::CompilationUnit::Abbrev*)
+18cfc c 432 78
+18d08 4 440 61
+18d0c 1b 443 61
+18d27 1 443 61
+18d36 56 482 61
+18d98 4 514 61
+18d9c 4 515 61
+18da0 1b 517 61
+18dbb 1 517 61
+FUNC 18dbc 4d 0 void std::__fill<false>::fill<__gnu_cxx::__normal_iterator<dwarf2reader::CompilationUnit::Abbrev*, std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> > >, dwarf2reader::CompilationUnit::Abbrev>(__gnu_cxx::__normal_iterator<dwarf2reader::CompilationUnit::Abbrev*, std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> > >, __gnu_cxx::__normal_iterator<dwarf2reader::CompilationUnit::Abbrev*, std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> > >, dwarf2reader::CompilationUnit::Abbrev const&)
+18dbc c 526 61
+18dc8 2 528 61
+18dca 1c 529 61
+18de6 21 528 61
+18e07 2 529 61
+18e09 1 529 61
+FUNC 18e0a 2b 0 void std::fill<__gnu_cxx::__normal_iterator<dwarf2reader::CompilationUnit::Abbrev*, std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> > >, dwarf2reader::CompilationUnit::Abbrev>(__gnu_cxx::__normal_iterator<dwarf2reader::CompilationUnit::Abbrev*, std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> > >, __gnu_cxx::__normal_iterator<dwarf2reader::CompilationUnit::Abbrev*, std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> > >, dwarf2reader::CompilationUnit::Abbrev const&)
+18e0a c 560 78
+18e16 4 567 61
+18e1a 1b 568 61
+18e35 1 568 61
+FUNC 18e36 3f 0 unsigned char* std::__copy<true, std::random_access_iterator_tag>::copy<unsigned char>(unsigned char const*, unsigned char const*, unsigned char*)
+18e36 c 298 61
+18e42 22 300 61
+18e64 11 301 61
+18e75 1 301 61
+FUNC 18e76 2b 0 unsigned char* std::__copy_aux<unsigned char*, unsigned char*>(unsigned char*, unsigned char*, unsigned char*)
+18e76 c 307 78
+18e82 4 315 61
+18e86 1b 317 61
+18ea1 1 317 61
+18eb0 56 354 61
+18f12 4 384 61
+18f16 4 385 61
+18f1a 1b 387 61
+18f35 1 387 61
+FUNC 18f36 a0 0 std::vector<unsigned char, std::allocator<unsigned char> >::erase(__gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >, __gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >)
+18f36 d 122 78
+18f43 26 124 78
+18f69 43 125 78
+18fac 22 126 78
+18fce 8 127 78
+18fe2 7 98 68
+18fe9 1 98 68
+18ff6 1d 85 68
+19013 5 86 68
+19018 d 88 68
+19025 1 88 68
+FUNC 19026 2a 0 std::_Vector_base<unsigned char, std::allocator<unsigned char> >::_M_allocate(unsigned long)
+19026 c 116 78
+19032 1e 117 71
+1905c 1b 74 79
+19077 1 74 79
+19084 23 113 79
+190a7 1 113 79
+190b4 1b 254 79
+190cf 1 254 79
+FUNC 190d0 19 0 void std::_Destroy<dwarf2reader::CompilationUnit::Abbrev>(dwarf2reader::CompilationUnit::Abbrev*)
+190d0 c 106 79
+190dc d 107 73
+190e9 1 107 73
+FUNC 190ea 44 0 void std::__destroy_aux<__gnu_cxx::__normal_iterator<dwarf2reader::CompilationUnit::Abbrev*, std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> > > >(__gnu_cxx::__normal_iterator<dwarf2reader::CompilationUnit::Abbrev*, std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> > >, __gnu_cxx::__normal_iterator<dwarf2reader::CompilationUnit::Abbrev*, std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> > >, __false_type)
+190ea c 119 79
+190f6 2 121 73
+190f8 13 122 73
+1910b 21 121 73
+1912c 2 122 73
+FUNC 1912e 28 0 void std::_Destroy<__gnu_cxx::__normal_iterator<dwarf2reader::CompilationUnit::Abbrev*, std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> > > >(__gnu_cxx::__normal_iterator<dwarf2reader::CompilationUnit::Abbrev*, std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> > >, __gnu_cxx::__normal_iterator<dwarf2reader::CompilationUnit::Abbrev*, std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> > >)
+1912e c 148 79
+1913a 1c 155 73
+FUNC 19156 8d 0 void std::__uninitialized_fill_n_aux<__gnu_cxx::__normal_iterator<dwarf2reader::CompilationUnit::Abbrev*, std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> > >, unsigned long, dwarf2reader::CompilationUnit::Abbrev>(__gnu_cxx::__normal_iterator<dwarf2reader::CompilationUnit::Abbrev*, std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> > >, unsigned long, dwarf2reader::CompilationUnit::Abbrev const&, __false_type)
+19156 d 188 79
+19163 6 190 79
+19169 2 193 79
+1916b 1c 194 79
+19187 1b 193 79
+191a2 b 196 79
+191ad 12 198 79
+191bf b 199 79
+191ca 13 196 79
+191dd 6 199 79
+191e3 1 199 79
+FUNC 191e4 2f 0 void std::uninitialized_fill_n<__gnu_cxx::__normal_iterator<dwarf2reader::CompilationUnit::Abbrev*, std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> > >, unsigned long, dwarf2reader::CompilationUnit::Abbrev>(__gnu_cxx::__normal_iterator<dwarf2reader::CompilationUnit::Abbrev*, std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> > >, unsigned long, dwarf2reader::CompilationUnit::Abbrev const&)
+191e4 c 214 79
+191f0 23 218 79
+19213 1 218 79
+FUNC 19214 27 0 void std::__uninitialized_fill_n_a<__gnu_cxx::__normal_iterator<dwarf2reader::CompilationUnit::Abbrev*, std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> > >, unsigned long, dwarf2reader::CompilationUnit::Abbrev, dwarf2reader::CompilationUnit::Abbrev>(__gnu_cxx::__normal_iterator<dwarf2reader::CompilationUnit::Abbrev*, std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> > >, unsigned long, dwarf2reader::CompilationUnit::Abbrev const&, std::allocator<dwarf2reader::CompilationUnit::Abbrev>)
+19214 c 308 79
+19220 1b 310 79
+1923b 1 310 79
+19249 6 82 79
+1924f 2 85 79
+19251 24 86 79
+19275 2c 85 79
+192a1 b 87 79
+192ac b 89 79
+192b7 12 91 79
+192c9 b 92 79
+192d4 13 89 79
+192e7 9 92 79
+192fc 23 113 79
+1931f 1 113 79
+1932c 1b 254 79
+19347 1 254 79
+FUNC 19348 409 0 std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> >::_M_insert_aux(__gnu_cxx::__normal_iterator<dwarf2reader::CompilationUnit::Abbrev*, std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> > >, dwarf2reader::CompilationUnit::Abbrev const&)
+19348 14 249 79
+1935c 14 251 78
+19370 22 253 78
+19392 f 255 78
+193a1 12 256 78
+193b3 55 257 78
+19408 4b 260 78
+19453 e 264 78
+19461 15 265 78
+19476 e 266 78
+19484 1d 271 78
+194a1 8 272 78
+194a9 e 273 78
+194b7 27 275 78
+194de 6 276 78
+194e4 55 279 78
+19539 25 284 78
+1955e b 285 78
+19569 4f 286 78
+195b8 3 284 78
+195bb 13 279 78
+195ce e 286 78
+195dc 4d 298 78
+19629 36 299 78
+1965f 12 302 78
+19671 13 303 78
+19684 2e 304 78
+196b2 13 286 78
+196c5 b 292 78
+196d0 39 294 78
+19709 23 295 78
+1972c b 296 78
+19737 13 292 78
+1974a 7 304 78
+19751 1 304 78
+FUNC 19752 70 0 std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> >::push_back(dwarf2reader::CompilationUnit::Abbrev const&)
+19752 c 602 79
+1975e 10 604 71
+1976e 1e 606 71
+1978c 11 607 71
+1979d 25 610 71
+FUNC 197c2 50 0 unsigned char* std::__copy_backward<true, std::random_access_iterator_tag>::copy_b<unsigned char>(unsigned char const*, unsigned char const*, unsigned char*)
+197c2 d 422 61
+197cf f 424 61
+197de 24 425 61
+19802 10 426 61
+FUNC 19812 2b 0 unsigned char* std::__copy_backward_aux<unsigned char*, unsigned char*>(unsigned char*, unsigned char*, unsigned char*)
+19812 c 432 79
+1981e 4 440 61
+19822 1b 443 61
+1983d 1 443 61
+1984c 56 482 61
+198ae 4 514 61
+198b2 4 515 61
+198b6 1b 517 61
+198d1 1 517 61
+FUNC 198d2 32 0 unsigned char* std::fill_n<unsigned long>(unsigned char*, unsigned long, unsigned char const&)
+198d2 c 647 79
+198de 1e 649 61
+198fc 8 650 61
+FUNC 19904 27 0 void std::__uninitialized_fill_n_aux<unsigned char*, unsigned long, unsigned char>(unsigned char*, unsigned long, unsigned char const&, __true_type)
+19904 c 182 79
+19910 1b 183 79
+1992b 1 183 79
+FUNC 1992c 2f 0 void std::uninitialized_fill_n<unsigned char*, unsigned long, unsigned char>(unsigned char*, unsigned long, unsigned char const&)
+1992c c 214 79
+19938 23 218 79
+1995b 1 218 79
+FUNC 1995c 27 0 void std::__uninitialized_fill_n_a<unsigned char*, unsigned long, unsigned char, unsigned char>(unsigned char*, unsigned long, unsigned char const&, std::allocator<unsigned char>)
+1995c c 308 79
+19968 1b 310 79
+19983 1 310 79
+FUNC 19984 27 0 void std::__destroy_aux<dwarf2reader::CompilationUnit::Abbrev*>(dwarf2reader::CompilationUnit::Abbrev*, dwarf2reader::CompilationUnit::Abbrev*, __false_type)
+19984 c 119 79
+19990 2 121 73
+19992 b 122 73
+1999d c 121 73
+199a9 2 122 73
+199ab 1 122 73
+FUNC 199ac 28 0 void std::_Destroy<dwarf2reader::CompilationUnit::Abbrev*>(dwarf2reader::CompilationUnit::Abbrev*, dwarf2reader::CompilationUnit::Abbrev*)
+199ac c 148 79
+199b8 1c 155 73
+FUNC 199d4 88 0 dwarf2reader::CompilationUnit::Abbrev* std::__uninitialized_copy_aux<dwarf2reader::CompilationUnit::Abbrev*, dwarf2reader::CompilationUnit::Abbrev*>(dwarf2reader::CompilationUnit::Abbrev*, dwarf2reader::CompilationUnit::Abbrev*, dwarf2reader::CompilationUnit::Abbrev*, __false_type)
+199d4 d 80 79
+199e1 6 82 79
+199e7 2 85 79
+199e9 12 86 79
+199fb 12 85 79
+19a0d b 87 79
+19a18 b 89 79
+19a23 12 91 79
+19a35 b 92 79
+19a40 13 89 79
+19a53 9 92 79
+FUNC 19a5c 2f 0 dwarf2reader::CompilationUnit::Abbrev* std::uninitialized_copy<dwarf2reader::CompilationUnit::Abbrev*, dwarf2reader::CompilationUnit::Abbrev*>(dwarf2reader::CompilationUnit::Abbrev*, dwarf2reader::CompilationUnit::Abbrev*, dwarf2reader::CompilationUnit::Abbrev*)
+19a5c c 108 79
+19a68 23 113 79
+19a8b 1 113 79
+FUNC 19a8c 27 0 dwarf2reader::CompilationUnit::Abbrev* std::__uninitialized_copy_a<dwarf2reader::CompilationUnit::Abbrev*, dwarf2reader::CompilationUnit::Abbrev*, dwarf2reader::CompilationUnit::Abbrev>(dwarf2reader::CompilationUnit::Abbrev*, dwarf2reader::CompilationUnit::Abbrev*, dwarf2reader::CompilationUnit::Abbrev*, std::allocator<dwarf2reader::CompilationUnit::Abbrev>)
+19a8c c 252 79
+19a98 1b 254 79
+19ab3 1 254 79
+FUNC 19ab4 7e 0 void std::__uninitialized_fill_n_aux<dwarf2reader::CompilationUnit::Abbrev*, unsigned long, dwarf2reader::CompilationUnit::Abbrev>(dwarf2reader::CompilationUnit::Abbrev*, unsigned long, dwarf2reader::CompilationUnit::Abbrev const&, __false_type)
+19ab4 d 188 79
+19ac1 6 190 79
+19ac7 2 193 79
+19ac9 12 194 79
+19adb 16 193 79
+19af1 b 196 79
+19afc 12 198 79
+19b0e b 199 79
+19b19 13 196 79
+19b2c 6 199 79
+FUNC 19b32 2f 0 void std::uninitialized_fill_n<dwarf2reader::CompilationUnit::Abbrev*, unsigned long, dwarf2reader::CompilationUnit::Abbrev>(dwarf2reader::CompilationUnit::Abbrev*, unsigned long, dwarf2reader::CompilationUnit::Abbrev const&)
+19b32 c 214 79
+19b3e 23 218 79
+19b61 1 218 79
+FUNC 19b62 27 0 void std::__uninitialized_fill_n_a<dwarf2reader::CompilationUnit::Abbrev*, unsigned long, dwarf2reader::CompilationUnit::Abbrev, dwarf2reader::CompilationUnit::Abbrev>(dwarf2reader::CompilationUnit::Abbrev*, unsigned long, dwarf2reader::CompilationUnit::Abbrev const&, std::allocator<dwarf2reader::CompilationUnit::Abbrev>)
+19b62 c 308 79
+19b6e 1b 310 79
+19b89 1 310 79
+FUNC 19b8a a5 0 dwarf2reader::CompilationUnit::Abbrev* std::__uninitialized_copy_aux<__gnu_cxx::__normal_iterator<dwarf2reader::CompilationUnit::Abbrev*, std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> > >, dwarf2reader::CompilationUnit::Abbrev*>(__gnu_cxx::__normal_iterator<dwarf2reader::CompilationUnit::Abbrev*, std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> > >, __gnu_cxx::__normal_iterator<dwarf2reader::CompilationUnit::Abbrev*, std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> > >, dwarf2reader::CompilationUnit::Abbrev*, __false_type)
+19b8a d 80 79
+19b97 6 82 79
+19b9d 2 85 79
+19b9f 1a 86 79
+19bb9 27 85 79
+19be0 b 87 79
+19beb b 89 79
+19bf6 12 91 79
+19c08 b 92 79
+19c13 13 89 79
+19c26 9 92 79
+19c2f 1 92 79
+FUNC 19c30 2f 0 dwarf2reader::CompilationUnit::Abbrev* std::uninitialized_copy<__gnu_cxx::__normal_iterator<dwarf2reader::CompilationUnit::Abbrev*, std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> > >, dwarf2reader::CompilationUnit::Abbrev*>(__gnu_cxx::__normal_iterator<dwarf2reader::CompilationUnit::Abbrev*, std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> > >, __gnu_cxx::__normal_iterator<dwarf2reader::CompilationUnit::Abbrev*, std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> > >, dwarf2reader::CompilationUnit::Abbrev*)
+19c30 c 108 79
+19c3c 23 113 79
+19c5f 1 113 79
+FUNC 19c60 27 0 dwarf2reader::CompilationUnit::Abbrev* std::__uninitialized_copy_a<__gnu_cxx::__normal_iterator<dwarf2reader::CompilationUnit::Abbrev*, std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> > >, dwarf2reader::CompilationUnit::Abbrev*, dwarf2reader::CompilationUnit::Abbrev>(__gnu_cxx::__normal_iterator<dwarf2reader::CompilationUnit::Abbrev*, std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> > >, __gnu_cxx::__normal_iterator<dwarf2reader::CompilationUnit::Abbrev*, std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> > >, dwarf2reader::CompilationUnit::Abbrev*, std::allocator<dwarf2reader::CompilationUnit::Abbrev>)
+19c60 c 252 79
+19c6c 1b 254 79
+19c87 1 254 79
+FUNC 19c88 5f8 0 std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> >::_M_fill_insert(__gnu_cxx::__normal_iterator<dwarf2reader::CompilationUnit::Abbrev*, std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> > >, unsigned long, dwarf2reader::CompilationUnit::Abbrev const&)
+19c88 15 311 79
+19c9d b 313 78
+19ca8 2a 315 78
+19cd2 12 318 78
+19ce4 23 319 78
+19d07 15 320 78
+19d1c c 321 78
+19d28 5a 323 78
+19d82 1c 327 78
+19d9e 35 328 78
+19dd3 16 323 78
+19de9 30 330 78
+19e19 10 343 78
+19e29 48 334 78
+19e71 21 338 78
+19e92 3d 339 78
+19ecf 13 334 78
+19ee2 b 339 78
+19eed 1c 342 78
+19f09 1e 343 78
+19f27 13 339 78
+19f3a 24 343 78
+19f5e e 348 78
+19f6c 1e 349 78
+19f8a e 350 78
+19f98 1d 353 78
+19fb5 8 354 78
+19fbd e 355 78
+19fcb 27 357 78
+19ff2 6 358 78
+19ff8 4d 361 78
+1a045 40 365 78
+1a085 18 367 78
+1a09d 44 368 78
+1a0e1 3 365 78
+1a0e4 19 361 78
+1a0fd 13 365 78
+1a110 e 368 78
+1a11e 3e 379 78
+1a15c 36 381 78
+1a192 12 384 78
+1a1a4 13 385 78
+1a1b7 2e 386 78
+1a1e5 e 368 78
+1a1f3 b 372 78
+1a1fe 39 374 78
+1a237 23 376 78
+1a25a b 377 78
+1a265 13 372 78
+1a278 8 386 78
+FUNC 1a280 2e 0 std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> >::insert(__gnu_cxx::__normal_iterator<dwarf2reader::CompilationUnit::Abbrev*, std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> > >, unsigned long, dwarf2reader::CompilationUnit::Abbrev const&)
+1a280 c 657 79
+1a28c 22 658 71
+FUNC 1a2ae ab 0 std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> >::resize(unsigned long, dwarf2reader::CompilationUnit::Abbrev const&)
+1a2ae d 422 79
+1a2bb 15 424 71
+1a2d0 48 425 71
+1a318 41 427 71
+1a359 1 427 71
+FUNC 1a35a 63 0 std::vector<dwarf2reader::CompilationUnit::Abbrev, std::allocator<dwarf2reader::CompilationUnit::Abbrev> >::resize(unsigned long)
+1a35a d 441 79
+1a367 56 442 71
+1a3bd 1 442 71
+FUNC 1a3be 13 0 std::_Deque_iterator<unsigned long long, unsigned long long const&, unsigned long long const*>::operator*() const
+1a3be c 134 79
+1a3ca 7 135 62
+1a3d1 1 135 62
+FUNC 1a3d2 3f 0 unsigned long long** std::__copy<true, std::random_access_iterator_tag>::copy<unsigned long long*>(unsigned long long* const*, unsigned long long* const*, unsigned long long**)
+1a3d2 c 298 61
+1a3de 22 300 61
+1a400 11 301 61
+1a411 1 301 61
+FUNC 1a412 2b 0 unsigned long long** std::__copy_aux<unsigned long long**, unsigned long long**>(unsigned long long**, unsigned long long**, unsigned long long**)
+1a412 c 307 79
+1a41e 4 315 61
+1a422 1b 317 61
+1a43d 1 317 61
+FUNC 1a43e 27 0 unsigned long long** std::__copy_normal<false, false>::copy_n<unsigned long long**, unsigned long long**>(unsigned long long**, unsigned long long**, unsigned long long**)
+1a43e c 325 61
+1a44a 1b 326 61
+1a465 1 326 61
+FUNC 1a466 2f 0 unsigned long long** std::copy<unsigned long long**, unsigned long long**>(unsigned long long**, unsigned long long**, unsigned long long**)
+1a466 c 376 79
+1a472 4 384 61
+1a476 4 385 61
+1a47a 1b 387 61
+1a495 1 387 61
+FUNC 1a496 60 0 unsigned long long** std::__copy_backward<true, std::random_access_iterator_tag>::copy_b<unsigned long long*>(unsigned long long* const*, unsigned long long* const*, unsigned long long**)
+1a496 d 422 61
+1a4a3 12 424 61
+1a4b5 2e 425 61
+1a4e3 13 426 61
+FUNC 1a4f6 2b 0 unsigned long long** std::__copy_backward_aux<unsigned long long**, unsigned long long**>(unsigned long long**, unsigned long long**, unsigned long long**)
+1a4f6 c 432 79
+1a502 4 440 61
+1a506 1b 443 61
+1a521 1 443 61
+FUNC 1a522 27 0 unsigned long long** std::__copy_backward_normal<false, false>::copy_b_n<unsigned long long**, unsigned long long**>(unsigned long long**, unsigned long long**, unsigned long long**)
+1a522 c 451 61
+1a52e 1b 452 61
+1a549 1 452 61
+FUNC 1a54a 2f 0 unsigned long long** std::copy_backward<unsigned long long**, unsigned long long**>(unsigned long long**, unsigned long long**, unsigned long long**)
+1a54a c 504 79
+1a556 4 514 61
+1a55a 4 515 61
+1a55e 1b 517 61
+1a579 1 517 61
+FUNC 1a57a 1df 0 std::deque<unsigned long long, std::allocator<unsigned long long> >::_M_reallocate_map(unsigned long, bool)
+1a57a 13 723 79
+1a58d 1b 726 76
+1a5a8 9 727 76
+1a5b1 13 730 76
+1a5c4 39 732 76
+1a5fd b 735 76
+1a608 27 736 76
+1a62f 2f 740 76
+1a65e 26 748 76
+1a684 15 750 76
+1a699 36 751 76
+1a6cf 22 753 76
+1a6f1 1e 756 76
+1a70f 8 758 76
+1a717 9 759 76
+1a720 15 762 76
+1a735 24 763 76
+1a759 1 763 76
+FUNC 1a75a 59 0 std::deque<unsigned long long, std::allocator<unsigned long long> >::_M_reserve_map_at_back(unsigned long)
+1a75a e 1443 79
+1a768 2a 1445 62
+1a792 21 1447 62
+1a7b3 1 1447 62
+FUNC 1a7b4 8c 0 std::deque<unsigned long long, std::allocator<unsigned long long> >::_M_push_back_aux(unsigned long long const&)
+1a7b4 c 345 79
+1a7c0 e 347 76
+1a7ce 13 348 76
+1a7e1 18 349 76
+1a7f9 1e 352 76
+1a817 1b 353 76
+1a832 c 355 76
+1a83e 2 360 76
+FUNC 1a840 62 0 std::deque<unsigned long long, std::allocator<unsigned long long> >::push_back(unsigned long long const&)
+1a840 c 1039 79
+1a84c 13 1041 62
+1a85f 1e 1044 62
+1a87d 11 1045 62
+1a88e 14 1048 62
+FUNC 1a8a2 20 0 std::stack<unsigned long long, std::deque<unsigned long long, std::allocator<unsigned long long> > >::push(unsigned long long const&)
+1a8a2 c 190 79
+1a8ae 14 191 75
+FUNC 1a8c2 27 0 unsigned char* std::__copy_normal<false, false>::copy_n<unsigned char*, unsigned char*>(unsigned char*, unsigned char*, unsigned char*)
+1a8c2 c 325 61
+1a8ce 1b 326 61
+1a8e9 1 326 61
+FUNC 1a8ea 2f 0 unsigned char* std::copy<unsigned char*, unsigned char*>(unsigned char*, unsigned char*, unsigned char*)
+1a8ea c 376 79
+1a8f6 4 384 61
+1a8fa 4 385 61
+1a8fe 1b 387 61
+1a919 1 387 61
+FUNC 1a91a 27 0 unsigned char* std::__uninitialized_copy_aux<unsigned char*, unsigned char*>(unsigned char*, unsigned char*, unsigned char*, __true_type)
+1a91a c 73 79
+1a926 1b 74 79
+1a941 1 74 79
+FUNC 1a942 2f 0 unsigned char* std::uninitialized_copy<unsigned char*, unsigned char*>(unsigned char*, unsigned char*, unsigned char*)
+1a942 c 108 79
+1a94e 23 113 79
+1a971 1 113 79
+FUNC 1a972 27 0 unsigned char* std::__uninitialized_copy_a<unsigned char*, unsigned char*, unsigned char>(unsigned char*, unsigned char*, unsigned char*, std::allocator<unsigned char>)
+1a972 c 252 79
+1a97e 1b 254 79
+1a999 1 254 79
+FUNC 1a99a 40 0 unsigned char* std::__copy_normal<true, false>::copy_n<__gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >, unsigned char*>(__gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >, __gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >, unsigned char*)
+1a99a d 334 61
+1a9a7 33 335 61
+FUNC 1a9da 2f 0 unsigned char* std::copy<__gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >, unsigned char*>(__gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >, __gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >, unsigned char*)
+1a9da c 376 79
+1a9e6 4 384 61
+1a9ea 4 385 61
+1a9ee 1b 387 61
+1aa09 1 387 61
+FUNC 1aa0a 27 0 unsigned char* std::__uninitialized_copy_aux<__gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >, unsigned char*>(__gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >, __gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >, unsigned char*, __true_type)
+1aa0a c 73 79
+1aa16 1b 74 79
+1aa31 1 74 79
+FUNC 1aa32 2f 0 unsigned char* std::uninitialized_copy<__gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >, unsigned char*>(__gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >, __gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >, unsigned char*)
+1aa32 c 108 79
+1aa3e 23 113 79
+1aa61 1 113 79
+FUNC 1aa62 27 0 unsigned char* std::__uninitialized_copy_a<__gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >, unsigned char*, unsigned char>(__gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >, __gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >, unsigned char*, std::allocator<unsigned char>)
+1aa62 c 252 79
+1aa6e 1b 254 79
+1aa89 1 254 79
+1aa96 9 616 61
+1aa9f 2 617 61
+1aaa1 13 618 61
+1aab4 16 617 61
+1aaca 5 619 61
+1aacf 1 619 61
+1aadc 4 641 61
+1aae0 1b 642 61
+1aafb 1 642 61
+FUNC 1aafc 27 0 void std::__uninitialized_fill_n_aux<__gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >, unsigned long, unsigned char>(__gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >, unsigned long, unsigned char const&, __true_type)
+1aafc c 182 79
+1ab08 1b 183 79
+1ab23 1 183 79
+FUNC 1ab24 2f 0 void std::uninitialized_fill_n<__gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >, unsigned long, unsigned char>(__gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >, unsigned long, unsigned char const&)
+1ab24 c 214 79
+1ab30 23 218 79
+1ab53 1 218 79
+FUNC 1ab54 27 0 void std::__uninitialized_fill_n_a<__gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >, unsigned long, unsigned char, unsigned char>(__gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >, unsigned long, unsigned char const&, std::allocator<unsigned char>)
+1ab54 c 308 79
+1ab60 1b 310 79
+1ab7b 1 310 79
+FUNC 1ab7c 45a 0 std::vector<unsigned char, std::allocator<unsigned char> >::_M_fill_insert(__gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >, unsigned long, unsigned char const&)
+1ab7c 14 311 79
+1ab90 b 313 78
+1ab9b 21 315 78
+1abbc 9 318 78
+1abc5 23 319 78
+1abe8 15 320 78
+1abfd c 321 78
+1ac09 4e 323 78
+1ac57 11 327 78
+1ac68 30 328 78
+1ac98 35 330 78
+1accd 48 334 78
+1ad15 14 338 78
+1ad29 43 339 78
+1ad6c 11 342 78
+1ad7d 1e 343 78
+1ad9b e 348 78
+1ada9 1e 349 78
+1adc7 e 350 78
+1add5 1d 353 78
+1adf2 8 354 78
+1adfa e 355 78
+1ae08 27 357 78
+1ae2f 6 358 78
+1ae35 4d 361 78
+1ae82 40 365 78
+1aec2 18 367 78
+1aeda 4d 368 78
+1af27 3e 379 78
+1af65 2d 381 78
+1af92 12 384 78
+1afa4 13 385 78
+1afb7 1f 386 78
+FUNC 1afd6 2e 0 std::vector<unsigned char, std::allocator<unsigned char> >::insert(__gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >, unsigned long, unsigned char const&)
+1afd6 c 657 79
+1afe2 22 658 71
+FUNC 1b004 ab 0 std::vector<unsigned char, std::allocator<unsigned char> >::resize(unsigned long, unsigned char const&)
+1b004 d 422 79
+1b011 15 424 71
+1b026 48 425 71
+1b06e 41 427 71
+1b0af 1 427 71
+FUNC 1b0b0 2b 0 std::vector<unsigned char, std::allocator<unsigned char> >::resize(unsigned long)
+1b0b0 c 441 79
+1b0bc 1f 442 71
+1b0db 1 442 71
+FUNC 1b0dc 1a 0 std::_Deque_iterator<unsigned long long, unsigned long long const&, unsigned long long const*>::_S_buffer_size()
+1b0dc c 106 79
+1b0e8 e 107 62
+FUNC 1b0f6 66 0 std::_Deque_iterator<unsigned long long, unsigned long long const&, unsigned long long const*>::difference_type std::operator-<unsigned long long, unsigned long long const&, unsigned long long const*, unsigned long long const&, unsigned long long const*>(std::_Deque_iterator<unsigned long long, unsigned long long const&, unsigned long long const*> const&, std::_Deque_iterator<unsigned long long, unsigned long long const&, unsigned long long const*> const&)
+1b0f6 d 328 79
+1b103 59 333 62
+FUNC 1b15c 3e 0 std::_Deque_iterator<unsigned long long, unsigned long long const&, unsigned long long const*>::_M_set_node(unsigned long long**)
+1b15c d 229 79
+1b169 9 231 62
+1b172 b 232 62
+1b17d 1d 233 62
+FUNC 1b19a 50 0 std::_Deque_iterator<unsigned long long, unsigned long long const&, unsigned long long const*>::operator++()
+1b19a c 142 79
+1b1a6 d 144 62
+1b1b3 f 145 62
+1b1c2 18 147 62
+1b1da b 148 62
+1b1e5 5 150 62
+FUNC 1b1ea 84 0 std::_Deque_iterator<unsigned long long, unsigned long long&, unsigned long long*> std::__copy<false, std::random_access_iterator_tag>::copy<std::_Deque_iterator<unsigned long long, unsigned long long const&, unsigned long long const*>, std::_Deque_iterator<unsigned long long, unsigned long long&, unsigned long long*> >(std::_Deque_iterator<unsigned long long, unsigned long long const&, unsigned long long const*>, std::_Deque_iterator<unsigned long long, unsigned long long const&, unsigned long long const*>, std::_Deque_iterator<unsigned long long, unsigned long long&, unsigned long long*>)
+1b1ea e 280 61
+1b1f8 17 283 61
+1b20f 20 285 61
+1b22f b 286 61
+1b23a b 287 61
+1b245 b 283 61
+1b250 1e 289 61
+FUNC 1b26e 7e 0 std::_Deque_iterator<unsigned long long, unsigned long long&, unsigned long long*> std::__copy_aux<std::_Deque_iterator<unsigned long long, unsigned long long const&, unsigned long long const*>, std::_Deque_iterator<unsigned long long, unsigned long long&, unsigned long long*> >(std::_Deque_iterator<unsigned long long, unsigned long long const&, unsigned long long const*>, std::_Deque_iterator<unsigned long long, unsigned long long const&, unsigned long long const*>, std::_Deque_iterator<unsigned long long, unsigned long long&, unsigned long long*>)
+1b26e 11 307 79
+1b27f 4 315 61
+1b283 69 317 61
+FUNC 1b2ec 7a 0 std::_Deque_iterator<unsigned long long, unsigned long long&, unsigned long long*> std::__copy_normal<false, false>::copy_n<std::_Deque_iterator<unsigned long long, unsigned long long const&, unsigned long long const*>, std::_Deque_iterator<unsigned long long, unsigned long long&, unsigned long long*> >(std::_Deque_iterator<unsigned long long, unsigned long long const&, unsigned long long const*>, std::_Deque_iterator<unsigned long long, unsigned long long const&, unsigned long long const*>, std::_Deque_iterator<unsigned long long, unsigned long long&, unsigned long long*>)
+1b2ec 11 325 61
+1b2fd 69 326 61
+FUNC 1b366 82 0 std::_Deque_iterator<unsigned long long, unsigned long long&, unsigned long long*> std::copy<std::_Deque_iterator<unsigned long long, unsigned long long const&, unsigned long long const*>, std::_Deque_iterator<unsigned long long, unsigned long long&, unsigned long long*> >(std::_Deque_iterator<unsigned long long, unsigned long long const&, unsigned long long const*>, std::_Deque_iterator<unsigned long long, unsigned long long const&, unsigned long long const*>, std::_Deque_iterator<unsigned long long, unsigned long long&, unsigned long long*>)
+1b366 11 376 79
+1b377 4 384 61
+1b37b 4 385 61
+1b37f 69 387 61
+FUNC 1b3e8 7a 0 std::_Deque_iterator<unsigned long long, unsigned long long&, unsigned long long*> std::__uninitialized_copy_aux<std::_Deque_iterator<unsigned long long, unsigned long long const&, unsigned long long const*>, std::_Deque_iterator<unsigned long long, unsigned long long&, unsigned long long*> >(std::_Deque_iterator<unsigned long long, unsigned long long const&, unsigned long long const*>, std::_Deque_iterator<unsigned long long, unsigned long long const&, unsigned long long const*>, std::_Deque_iterator<unsigned long long, unsigned long long&, unsigned long long*>, __true_type)
+1b3e8 11 73 79
+1b3f9 69 74 79
+FUNC 1b462 82 0 std::_Deque_iterator<unsigned long long, unsigned long long&, unsigned long long*> std::uninitialized_copy<std::_Deque_iterator<unsigned long long, unsigned long long const&, unsigned long long const*>, std::_Deque_iterator<unsigned long long, unsigned long long&, unsigned long long*> >(std::_Deque_iterator<unsigned long long, unsigned long long const&, unsigned long long const*>, std::_Deque_iterator<unsigned long long, unsigned long long const&, unsigned long long const*>, std::_Deque_iterator<unsigned long long, unsigned long long&, unsigned long long*>)
+1b462 11 108 79
+1b473 71 113 79
+FUNC 1b4e4 7a 0 std::_Deque_iterator<unsigned long long, unsigned long long&, unsigned long long*> std::__uninitialized_copy_a<std::_Deque_iterator<unsigned long long, unsigned long long const&, unsigned long long const*>, std::_Deque_iterator<unsigned long long, unsigned long long&, unsigned long long*>, unsigned long long>(std::_Deque_iterator<unsigned long long, unsigned long long const&, unsigned long long const*>, std::_Deque_iterator<unsigned long long, unsigned long long const&, unsigned long long const*>, std::_Deque_iterator<unsigned long long, unsigned long long&, unsigned long long*>, std::allocator<unsigned long long>)
+1b4e4 11 252 79
+1b4f5 69 254 79
+1b55e 10 679 62
+1b56e 64 680 62
+1b5d2 e8 681 62
+1b6ba c 143 75
+1b6c6 14 144 75
+1b6da 6 144 75
+FUNC 1b6e0 4d 0 __eprintf
+1b6e0 6 1826 80
+1b6e6 3 1832 80
+1b6e9 c 1826 80
+1b6f5 29 1832 80
+1b71e a 1837 80
+1b728 5 1838 80
+1b72d e8d3 1838 80
diff --git a/toolkit/crashreporter/breakpad-client/mac/handler/ucontext_compat.h b/toolkit/crashreporter/breakpad-client/mac/handler/ucontext_compat.h
new file mode 100644
index 0000000000..1e4b752e51
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/mac/handler/ucontext_compat.h
@@ -0,0 +1,47 @@
+// Copyright 2013 Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef CLIENT_MAC_HANDLER_UCONTEXT_COMPAT_H_
+#define CLIENT_MAC_HANDLER_UCONTEXT_COMPAT_H_
+
+#include <sys/ucontext.h>
+
+// The purpose of this file is to work around the fact that ucontext_t's
+// uc_mcontext member is an mcontext_t rather than an mcontext64_t on ARM64.
+#if defined(__aarch64__)
+// <sys/ucontext.h> doesn't include the below file.
+#include <sys/_types/_ucontext64.h>
+typedef ucontext64_t breakpad_ucontext_t;
+#define breakpad_uc_mcontext uc_mcontext64
+#else
+typedef ucontext_t breakpad_ucontext_t;
+#define breakpad_uc_mcontext uc_mcontext
+#endif // defined(__aarch64__)
+
+#endif // CLIENT_MAC_HANDLER_UCONTEXT_COMPAT_H_
diff --git a/toolkit/crashreporter/breakpad-client/mac/tests/BreakpadFramework_Test.mm b/toolkit/crashreporter/breakpad-client/mac/tests/BreakpadFramework_Test.mm
new file mode 100644
index 0000000000..2ea103c694
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/mac/tests/BreakpadFramework_Test.mm
@@ -0,0 +1,217 @@
+// Copyright (c) 2009, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// BreakpadFramework_Test.mm
+// Test case file for Breakpad.h/mm.
+//
+
+#import "GTMSenTestCase.h"
+#import "Breakpad.h"
+
+#include <mach/mach.h>
+
+@interface BreakpadFramework_Test : GTMTestCase {
+ @private
+ int last_exception_code_;
+ int last_exception_type_;
+ mach_port_t last_exception_thread_;
+ // We're not using Obj-C BOOL because we need to interop with
+ // Breakpad's callback.
+ bool shouldHandleException_;
+}
+
+// This method is used by a callback used by test cases to determine
+// whether to return true or false to Breakpad when handling an
+// exception.
+- (bool)shouldHandleException;
+// This method returns a minimal dictionary that has what
+// Breakpad needs to initialize.
+- (NSMutableDictionary *)breakpadInitializationDictionary;
+// This method is used by the exception handling callback
+// to communicate to test cases the properites of the last
+// exception.
+- (void)setLastExceptionType:(int)type andCode:(int)code
+ andThread:(mach_port_t)thread;
+@end
+
+// Callback for Breakpad exceptions
+bool myBreakpadCallback(int exception_type,
+ int exception_code,
+ mach_port_t crashing_thread,
+ void *context);
+
+bool myBreakpadCallback(int exception_type,
+ int exception_code,
+ mach_port_t crashing_thread,
+ void *context) {
+ BreakpadFramework_Test *testCaseClass =
+ (BreakpadFramework_Test *)context;
+ [testCaseClass setLastExceptionType:exception_type
+ andCode:exception_code
+ andThread:crashing_thread];
+ bool shouldHandleException =
+ [testCaseClass shouldHandleException];
+ NSLog(@"Callback returning %d", shouldHandleException);
+ return shouldHandleException;
+}
+const int kNoLastExceptionCode = -1;
+const int kNoLastExceptionType = -1;
+const mach_port_t kNoLastExceptionThread = MACH_PORT_NULL;
+
+@implementation BreakpadFramework_Test
+- (void) initializeExceptionStateVariables {
+ last_exception_code_ = kNoLastExceptionCode;
+ last_exception_type_ = kNoLastExceptionType;
+ last_exception_thread_ = kNoLastExceptionThread;
+}
+
+- (NSMutableDictionary *)breakpadInitializationDictionary {
+ NSMutableDictionary *breakpadParams =
+ [NSMutableDictionary dictionaryWithCapacity:3];
+
+ [breakpadParams setObject:@"UnitTests" forKey:@BREAKPAD_PRODUCT];
+ [breakpadParams setObject:@"1.0" forKey:@BREAKPAD_VERSION];
+ [breakpadParams setObject:@"http://staging" forKey:@BREAKPAD_URL];
+ return breakpadParams;
+}
+
+- (bool)shouldHandleException {
+ return shouldHandleException_;
+}
+
+- (void)setLastExceptionType:(int)type
+ andCode:(int)code
+ andThread:(mach_port_t)thread {
+ last_exception_type_ = type;
+ last_exception_code_ = code;
+ last_exception_thread_ = thread;
+}
+
+// Test that the parameters mark required actually enable Breakpad to
+// be initialized.
+- (void)testBreakpadInstantiationWithRequiredParameters {
+ BreakpadRef b = BreakpadCreate([self breakpadInitializationDictionary]);
+ STAssertNotNULL(b, @"BreakpadCreate failed with required parameters");
+ BreakpadRelease(b);
+}
+
+// Test that Breakpad fails to initialize cleanly when required
+// parameters are not present.
+- (void)testBreakpadInstantiationWithoutRequiredParameters {
+ NSMutableDictionary *breakpadDictionary =
+ [self breakpadInitializationDictionary];
+
+ // Skip setting version, so that BreakpadCreate fails.
+ [breakpadDictionary removeObjectForKey:@BREAKPAD_VERSION];
+ BreakpadRef b = BreakpadCreate(breakpadDictionary);
+ STAssertNULL(b, @"BreakpadCreate did not fail when missing a required"
+ " parameter!");
+
+ breakpadDictionary = [self breakpadInitializationDictionary];
+ // Now test with no product
+ [breakpadDictionary removeObjectForKey:@BREAKPAD_PRODUCT];
+ b = BreakpadCreate(breakpadDictionary);
+ STAssertNULL(b, @"BreakpadCreate did not fail when missing a required"
+ " parameter!");
+
+ breakpadDictionary = [self breakpadInitializationDictionary];
+ // Now test with no URL
+ [breakpadDictionary removeObjectForKey:@BREAKPAD_URL];
+ b = BreakpadCreate(breakpadDictionary);
+ STAssertNULL(b, @"BreakpadCreate did not fail when missing a required"
+ " parameter!");
+ BreakpadRelease(b);
+}
+
+// Test to ensure that when we call BreakpadAddUploadParameter,
+// it's added to the dictionary correctly(this test depends on
+// some internal details of Breakpad, namely, the special prefix
+// that it uses to figure out which key/value pairs to upload).
+- (void)testAddingBreakpadServerVariable {
+ NSMutableDictionary *breakpadDictionary =
+ [self breakpadInitializationDictionary];
+
+ BreakpadRef b = BreakpadCreate(breakpadDictionary);
+ STAssertNotNULL(b, @"BreakpadCreate failed with valid dictionary!");
+
+ BreakpadAddUploadParameter(b,
+ @"key",
+ @"value");
+
+ // Test that it did not add the key/value directly, e.g. without
+ // prepending the key with the prefix.
+ STAssertNil(BreakpadKeyValue(b, @"key"),
+ @"AddUploadParameter added key directly to dictionary"
+ " instead of prepending it!");
+
+ NSString *prependedKeyname =
+ [@BREAKPAD_SERVER_PARAMETER_PREFIX stringByAppendingString:@"key"];
+
+ STAssertEqualStrings(BreakpadKeyValue(b, prependedKeyname),
+ @"value",
+ @"Calling BreakpadAddUploadParameter did not prepend "
+ "key name");
+ BreakpadRelease(b);
+}
+
+// Test that when we do on-demand minidump generation,
+// the exception code/type/thread are set properly.
+- (void)testFilterCallbackReturnsFalse {
+ NSMutableDictionary *breakpadDictionary =
+ [self breakpadInitializationDictionary];
+
+ BreakpadRef b = BreakpadCreate(breakpadDictionary);
+ STAssertNotNULL(b, @"BreakpadCreate failed with valid dictionary!");
+ BreakpadSetFilterCallback(b, &myBreakpadCallback, self);
+
+ // This causes the callback to return false, meaning
+ // Breakpad won't take the exception
+ shouldHandleException_ = false;
+
+ [self initializeExceptionStateVariables];
+ STAssertEquals(last_exception_type_, kNoLastExceptionType,
+ @"Last exception type not initialized correctly.");
+ STAssertEquals(last_exception_code_, kNoLastExceptionCode,
+ @"Last exception code not initialized correctly.");
+ STAssertEquals(last_exception_thread_, kNoLastExceptionThread,
+ @"Last exception thread is not initialized correctly.");
+
+ // Cause Breakpad's exception handler to be invoked.
+ BreakpadGenerateAndSendReport(b);
+
+ STAssertEquals(last_exception_type_, 0,
+ @"Last exception type is not 0 for on demand");
+ STAssertEquals(last_exception_code_, 0,
+ @"Last exception code is not 0 for on demand");
+ STAssertEquals(last_exception_thread_, mach_thread_self(),
+ @"Last exception thread is not mach_thread_self() "
+ "for on demand");
+}
+
+@end
diff --git a/toolkit/crashreporter/breakpad-client/mac/tests/crash_generation_server_test.cc b/toolkit/crashreporter/breakpad-client/mac/tests/crash_generation_server_test.cc
new file mode 100644
index 0000000000..0164f4a298
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/mac/tests/crash_generation_server_test.cc
@@ -0,0 +1,398 @@
+// Copyright (c) 2010, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// crash_generation_server_test.cc
+// Unit tests for CrashGenerationServer
+
+#include <dirent.h>
+#include <glob.h>
+#include <stdint.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include <string>
+
+#include "breakpad_googletest_includes.h"
+#include "client/mac/crash_generation/client_info.h"
+#include "client/mac/crash_generation/crash_generation_client.h"
+#include "client/mac/crash_generation/crash_generation_server.h"
+#include "client/mac/handler/exception_handler.h"
+#include "client/mac/tests/spawn_child_process.h"
+#include "common/tests/auto_tempdir.h"
+#include "google_breakpad/processor/minidump.h"
+
+namespace google_breakpad {
+// This acts as the log sink for INFO logging from the processor
+// logging code. The logging output confuses XCode and makes it think
+// there are unit test failures. testlogging.h handles the overriding.
+std::ostringstream info_log;
+}
+
+namespace {
+using std::string;
+using google_breakpad::AutoTempDir;
+using google_breakpad::ClientInfo;
+using google_breakpad::CrashGenerationClient;
+using google_breakpad::CrashGenerationServer;
+using google_breakpad::ExceptionHandler;
+using google_breakpad::Minidump;
+using google_breakpad::MinidumpContext;
+using google_breakpad::MinidumpException;
+using google_breakpad::MinidumpModule;
+using google_breakpad::MinidumpModuleList;
+using google_breakpad::MinidumpSystemInfo;
+using google_breakpad::MinidumpThread;
+using google_breakpad::MinidumpThreadList;
+using testing::Test;
+using namespace google_breakpad_test;
+
+class CrashGenerationServerTest : public Test {
+public:
+ // The port name to receive messages on
+ char mach_port_name[128];
+ // Filename of the last dump that was generated
+ string last_dump_name;
+ // PID of the child process
+ pid_t child_pid;
+ // A temp dir
+ AutoTempDir temp_dir;
+ // Counter just to ensure that we don't hit the same port again
+ static int i;
+ bool filter_callback_called;
+
+ void SetUp() {
+ sprintf(mach_port_name,
+ "com.google.breakpad.ServerTest.%d.%d", getpid(),
+ CrashGenerationServerTest::i++);
+ child_pid = (pid_t)-1;
+ filter_callback_called = false;
+ }
+};
+int CrashGenerationServerTest::i = 0;
+
+// Test that starting and stopping a server works
+TEST_F(CrashGenerationServerTest, testStartStopServer) {
+ CrashGenerationServer server(mach_port_name,
+ NULL, // filter callback
+ NULL, // filter context
+ NULL, // dump callback
+ NULL, // dump context
+ NULL, // exit callback
+ NULL, // exit context
+ false, // generate dumps
+ ""); // dump path
+ ASSERT_TRUE(server.Start());
+ ASSERT_TRUE(server.Stop());
+}
+
+// Test that requesting a dump via CrashGenerationClient works
+// Test without actually dumping
+TEST_F(CrashGenerationServerTest, testRequestDumpNoDump) {
+ CrashGenerationServer server(mach_port_name,
+ NULL, // filter callback
+ NULL, // filter context
+ NULL, // dump callback
+ NULL, // dump context
+ NULL, // exit callback
+ NULL, // exit context
+ false, // don't generate dumps
+ temp_dir.path()); // dump path
+ ASSERT_TRUE(server.Start());
+
+ pid_t pid = fork();
+ ASSERT_NE(-1, pid);
+ if (pid == 0) {
+ CrashGenerationClient client(mach_port_name);
+ bool result = client.RequestDump();
+ exit(result ? 0 : 1);
+ }
+
+ int ret;
+ ASSERT_EQ(pid, waitpid(pid, &ret, 0));
+ EXPECT_TRUE(WIFEXITED(ret));
+ EXPECT_EQ(0, WEXITSTATUS(ret));
+ EXPECT_TRUE(server.Stop());
+ // check that no minidump was written
+ string pattern = temp_dir.path() + "/*";
+ glob_t dirContents;
+ ret = glob(pattern.c_str(), GLOB_NOSORT, NULL, &dirContents);
+ EXPECT_EQ(GLOB_NOMATCH, ret);
+ if (ret != GLOB_NOMATCH)
+ globfree(&dirContents);
+}
+
+void dumpCallback(void *context, const ClientInfo &client_info,
+ const std::string &file_path) {
+ if (context) {
+ CrashGenerationServerTest* self =
+ reinterpret_cast<CrashGenerationServerTest*>(context);
+ if (!file_path.empty())
+ self->last_dump_name = file_path;
+ self->child_pid = client_info.pid();
+ }
+}
+
+void *RequestDump(void *context) {
+ CrashGenerationClient client((const char*)context);
+ bool result = client.RequestDump();
+ return (void*)(result ? 0 : 1);
+}
+
+// Test that actually writing a minidump works
+TEST_F(CrashGenerationServerTest, testRequestDump) {
+ CrashGenerationServer server(mach_port_name,
+ NULL, // filter callback
+ NULL, // filter context
+ dumpCallback, // dump callback
+ this, // dump context
+ NULL, // exit callback
+ NULL, // exit context
+ true, // generate dumps
+ temp_dir.path()); // dump path
+ ASSERT_TRUE(server.Start());
+
+ pid_t pid = fork();
+ ASSERT_NE(-1, pid);
+ if (pid == 0) {
+ // Have to spawn off a separate thread to request the dump,
+ // because MinidumpGenerator assumes the handler thread is not
+ // the only thread
+ pthread_t thread;
+ if (pthread_create(&thread, NULL, RequestDump, (void*)mach_port_name) != 0)
+ exit(1);
+ void* result;
+ pthread_join(thread, &result);
+ exit(reinterpret_cast<intptr_t>(result));
+ }
+
+ int ret;
+ ASSERT_EQ(pid, waitpid(pid, &ret, 0));
+ EXPECT_TRUE(WIFEXITED(ret));
+ EXPECT_EQ(0, WEXITSTATUS(ret));
+ EXPECT_TRUE(server.Stop());
+ // check that minidump was written
+ ASSERT_FALSE(last_dump_name.empty());
+ struct stat st;
+ EXPECT_EQ(0, stat(last_dump_name.c_str(), &st));
+ EXPECT_LT(0, st.st_size);
+ // check client's PID
+ ASSERT_EQ(pid, child_pid);
+}
+
+static void Crasher() {
+ int *a = (int*)0x42;
+
+ fprintf(stdout, "Going to crash...\n");
+ fprintf(stdout, "A = %d", *a);
+}
+
+// Test that crashing a child process with an OOP ExceptionHandler installed
+// results in a minidump being written by the CrashGenerationServer in
+// the parent.
+TEST_F(CrashGenerationServerTest, testChildProcessCrash) {
+ CrashGenerationServer server(mach_port_name,
+ NULL, // filter callback
+ NULL, // filter context
+ dumpCallback, // dump callback
+ this, // dump context
+ NULL, // exit callback
+ NULL, // exit context
+ true, // generate dumps
+ temp_dir.path()); // dump path
+ ASSERT_TRUE(server.Start());
+
+ pid_t pid = fork();
+ ASSERT_NE(-1, pid);
+ if (pid == 0) {
+ // Instantiate an OOP exception handler.
+ ExceptionHandler eh("", NULL, NULL, NULL, true, mach_port_name);
+ Crasher();
+ // not reached
+ exit(0);
+ }
+
+ int ret;
+ ASSERT_EQ(pid, waitpid(pid, &ret, 0));
+ EXPECT_FALSE(WIFEXITED(ret));
+ EXPECT_TRUE(server.Stop());
+ // check that minidump was written
+ ASSERT_FALSE(last_dump_name.empty());
+ struct stat st;
+ EXPECT_EQ(0, stat(last_dump_name.c_str(), &st));
+ EXPECT_LT(0, st.st_size);
+
+ // Read the minidump, sanity check some data.
+ Minidump minidump(last_dump_name.c_str());
+ ASSERT_TRUE(minidump.Read());
+
+ MinidumpSystemInfo* system_info = minidump.GetSystemInfo();
+ ASSERT_TRUE(system_info);
+ const MDRawSystemInfo* raw_info = system_info->system_info();
+ ASSERT_TRUE(raw_info);
+ EXPECT_EQ(kNativeArchitecture, raw_info->processor_architecture);
+
+ MinidumpThreadList* thread_list = minidump.GetThreadList();
+ ASSERT_TRUE(thread_list);
+ ASSERT_EQ((unsigned int)1, thread_list->thread_count());
+
+ MinidumpThread* main_thread = thread_list->GetThreadAtIndex(0);
+ ASSERT_TRUE(main_thread);
+ MinidumpContext* context = main_thread->GetContext();
+ ASSERT_TRUE(context);
+ EXPECT_EQ(kNativeContext, context->GetContextCPU());
+
+ MinidumpModuleList* module_list = minidump.GetModuleList();
+ ASSERT_TRUE(module_list);
+ const MinidumpModule* main_module = module_list->GetMainModule();
+ ASSERT_TRUE(main_module);
+ EXPECT_EQ(GetExecutablePath(), main_module->code_file());
+}
+
+#if (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6) && \
+ (defined(__x86_64__) || defined(__i386__))
+// Test that crashing a child process of a different architecture
+// produces a valid minidump.
+TEST_F(CrashGenerationServerTest, testChildProcessCrashCrossArchitecture) {
+ CrashGenerationServer server(mach_port_name,
+ NULL, // filter callback
+ NULL, // filter context
+ dumpCallback, // dump callback
+ this, // dump context
+ NULL, // exit callback
+ NULL, // exit context
+ true, // generate dumps
+ temp_dir.path()); // dump path
+ ASSERT_TRUE(server.Start());
+
+ // Spawn a child process
+ string helper_path = GetHelperPath();
+ const char* argv[] = {
+ helper_path.c_str(),
+ "crash",
+ mach_port_name,
+ NULL
+ };
+ pid_t pid = spawn_child_process(argv);
+ ASSERT_NE(-1, pid);
+
+ int ret;
+ ASSERT_EQ(pid, waitpid(pid, &ret, 0));
+ EXPECT_FALSE(WIFEXITED(ret));
+ EXPECT_TRUE(server.Stop());
+ // check that minidump was written
+ ASSERT_FALSE(last_dump_name.empty());
+ struct stat st;
+ EXPECT_EQ(0, stat(last_dump_name.c_str(), &st));
+ EXPECT_LT(0, st.st_size);
+
+const MDCPUArchitecture kExpectedArchitecture =
+#if defined(__x86_64__)
+ MD_CPU_ARCHITECTURE_X86
+#elif defined(__i386__)
+ MD_CPU_ARCHITECTURE_AMD64
+#endif
+ ;
+const uint32_t kExpectedContext =
+#if defined(__i386__)
+ MD_CONTEXT_AMD64
+#elif defined(__x86_64__)
+ MD_CONTEXT_X86
+#endif
+ ;
+
+ // Read the minidump, sanity check some data.
+ Minidump minidump(last_dump_name.c_str());
+ ASSERT_TRUE(minidump.Read());
+
+ MinidumpSystemInfo* system_info = minidump.GetSystemInfo();
+ ASSERT_TRUE(system_info);
+ const MDRawSystemInfo* raw_info = system_info->system_info();
+ ASSERT_TRUE(raw_info);
+ EXPECT_EQ(kExpectedArchitecture, raw_info->processor_architecture);
+
+ MinidumpThreadList* thread_list = minidump.GetThreadList();
+ ASSERT_TRUE(thread_list);
+ ASSERT_EQ((unsigned int)1, thread_list->thread_count());
+
+ MinidumpThread* main_thread = thread_list->GetThreadAtIndex(0);
+ ASSERT_TRUE(main_thread);
+ MinidumpContext* context = main_thread->GetContext();
+ ASSERT_TRUE(context);
+ EXPECT_EQ(kExpectedContext, context->GetContextCPU());
+
+ MinidumpModuleList* module_list = minidump.GetModuleList();
+ ASSERT_TRUE(module_list);
+ const MinidumpModule* main_module = module_list->GetMainModule();
+ ASSERT_TRUE(main_module);
+ EXPECT_EQ(helper_path, main_module->code_file());
+}
+#endif
+
+bool filter_callback(void* context) {
+ CrashGenerationServerTest* self =
+ reinterpret_cast<CrashGenerationServerTest*>(context);
+ self->filter_callback_called = true;
+ // veto dump generation
+ return false;
+}
+
+// Test that a filter callback can veto minidump writing.
+TEST_F(CrashGenerationServerTest, testFilter) {
+ CrashGenerationServer server(mach_port_name,
+ filter_callback, // filter callback
+ this, // filter context
+ dumpCallback, // dump callback
+ this, // dump context
+ NULL, // exit callback
+ NULL, // exit context
+ true, // generate dumps
+ temp_dir.path()); // dump path
+ ASSERT_TRUE(server.Start());
+
+ pid_t pid = fork();
+ ASSERT_NE(-1, pid);
+ if (pid == 0) {
+ // Instantiate an OOP exception handler.
+ ExceptionHandler eh("", NULL, NULL, NULL, true, mach_port_name);
+ Crasher();
+ // not reached
+ exit(0);
+ }
+
+ int ret;
+ ASSERT_EQ(pid, waitpid(pid, &ret, 0));
+ EXPECT_FALSE(WIFEXITED(ret));
+ EXPECT_TRUE(server.Stop());
+
+ // check that no minidump was written
+ EXPECT_TRUE(last_dump_name.empty());
+ EXPECT_TRUE(filter_callback_called);
+}
+
+} // namespace
diff --git a/toolkit/crashreporter/breakpad-client/mac/tests/exception_handler_test.cc b/toolkit/crashreporter/breakpad-client/mac/tests/exception_handler_test.cc
new file mode 100644
index 0000000000..d5b505a1e1
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/mac/tests/exception_handler_test.cc
@@ -0,0 +1,714 @@
+// Copyright (c) 2010, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// exception_handler_test.cc: Unit tests for google_breakpad::ExceptionHandler
+
+#include <pthread.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include "breakpad_googletest_includes.h"
+#include "client/mac/handler/exception_handler.h"
+#include "common/linux/ignore_ret.h"
+#include "common/mac/MachIPC.h"
+#include "common/tests/auto_tempdir.h"
+#include "google_breakpad/processor/minidump.h"
+
+namespace google_breakpad {
+// This acts as the log sink for INFO logging from the processor
+// logging code. The logging output confuses XCode and makes it think
+// there are unit test failures. testlogging.h handles the overriding.
+std::ostringstream info_log;
+}
+
+namespace {
+using std::string;
+using google_breakpad::AutoTempDir;
+using google_breakpad::ExceptionHandler;
+using google_breakpad::MachPortSender;
+using google_breakpad::MachReceiveMessage;
+using google_breakpad::MachSendMessage;
+using google_breakpad::Minidump;
+using google_breakpad::MinidumpContext;
+using google_breakpad::MinidumpException;
+using google_breakpad::MinidumpMemoryList;
+using google_breakpad::MinidumpMemoryRegion;
+using google_breakpad::ReceivePort;
+using testing::Test;
+
+class ExceptionHandlerTest : public Test {
+ public:
+ void InProcessCrash(bool aborting);
+ AutoTempDir tempDir;
+ string lastDumpName;
+};
+
+static void Crasher() {
+ int *a = (int*)0x42;
+
+ fprintf(stdout, "Going to crash...\n");
+ fprintf(stdout, "A = %d", *a);
+}
+
+static void AbortCrasher() {
+ fprintf(stdout, "Going to crash...\n");
+ abort();
+}
+
+static void SoonToCrash(void(*crasher)()) {
+ crasher();
+}
+
+static bool MDCallback(const char *dump_dir, const char *file_name,
+ void *context, bool success) {
+ string path(dump_dir);
+ path.append("/");
+ path.append(file_name);
+ path.append(".dmp");
+
+ int fd = *reinterpret_cast<int*>(context);
+ IGNORE_RET(write(fd, path.c_str(), path.length() + 1));
+ close(fd);
+ exit(0);
+ // not reached
+ return true;
+}
+
+void ExceptionHandlerTest::InProcessCrash(bool aborting) {
+ // Give the child process a pipe to report back on.
+ int fds[2];
+ ASSERT_EQ(0, pipe(fds));
+ // Fork off a child process so it can crash.
+ pid_t pid = fork();
+ if (pid == 0) {
+ // In the child process.
+ close(fds[0]);
+ ExceptionHandler eh(tempDir.path(), NULL, MDCallback, &fds[1], true, NULL);
+ // crash
+ SoonToCrash(aborting ? &AbortCrasher : &Crasher);
+ // not reached
+ exit(1);
+ }
+ // In the parent process.
+ ASSERT_NE(-1, pid);
+ // Wait for the background process to return the minidump file.
+ close(fds[1]);
+ char minidump_file[PATH_MAX];
+ ssize_t nbytes = read(fds[0], minidump_file, sizeof(minidump_file));
+ ASSERT_NE(0, nbytes);
+
+ Minidump minidump(minidump_file);
+ ASSERT_TRUE(minidump.Read());
+
+ MinidumpException* exception = minidump.GetException();
+ ASSERT_TRUE(exception);
+
+ const MDRawExceptionStream* raw_exception = exception->exception();
+ ASSERT_TRUE(raw_exception);
+
+ if (aborting) {
+ EXPECT_EQ(MD_EXCEPTION_MAC_SOFTWARE,
+ raw_exception->exception_record.exception_code);
+ EXPECT_EQ(MD_EXCEPTION_CODE_MAC_ABORT,
+ raw_exception->exception_record.exception_flags);
+ } else {
+ EXPECT_EQ(MD_EXCEPTION_MAC_BAD_ACCESS,
+ raw_exception->exception_record.exception_code);
+#if defined(__x86_64__)
+ EXPECT_EQ(MD_EXCEPTION_CODE_MAC_INVALID_ADDRESS,
+ raw_exception->exception_record.exception_flags);
+#elif defined(__i386__)
+ EXPECT_EQ(MD_EXCEPTION_CODE_MAC_PROTECTION_FAILURE,
+ raw_exception->exception_record.exception_flags);
+#endif
+ }
+
+ const MinidumpContext* context = exception->GetContext();
+ ASSERT_TRUE(context);
+
+ uint64_t instruction_pointer;
+ ASSERT_TRUE(context->GetInstructionPointer(&instruction_pointer));
+
+ // Ideally would like to sanity check that abort() is on the stack
+ // but that's hard.
+ MinidumpMemoryList* memory_list = minidump.GetMemoryList();
+ ASSERT_TRUE(memory_list);
+ MinidumpMemoryRegion* region =
+ memory_list->GetMemoryRegionForAddress(instruction_pointer);
+ EXPECT_TRUE(region);
+
+ // Child process should have exited with a zero status.
+ int ret;
+ ASSERT_EQ(pid, waitpid(pid, &ret, 0));
+ EXPECT_NE(0, WIFEXITED(ret));
+ EXPECT_EQ(0, WEXITSTATUS(ret));
+}
+
+TEST_F(ExceptionHandlerTest, InProcess) {
+ InProcessCrash(false);
+}
+
+TEST_F(ExceptionHandlerTest, InProcessAbort) {
+ InProcessCrash(true);
+}
+
+static bool DumpNameMDCallback(const char *dump_dir, const char *file_name,
+ void *context, bool success) {
+ ExceptionHandlerTest *self = reinterpret_cast<ExceptionHandlerTest*>(context);
+ if (dump_dir && file_name) {
+ self->lastDumpName = dump_dir;
+ self->lastDumpName += "/";
+ self->lastDumpName += file_name;
+ self->lastDumpName += ".dmp";
+ }
+ return true;
+}
+
+TEST_F(ExceptionHandlerTest, WriteMinidump) {
+ ExceptionHandler eh(tempDir.path(), NULL, DumpNameMDCallback, this, true,
+ NULL);
+ ASSERT_TRUE(eh.WriteMinidump());
+
+ // Ensure that minidump file exists and is > 0 bytes.
+ ASSERT_FALSE(lastDumpName.empty());
+ struct stat st;
+ ASSERT_EQ(0, stat(lastDumpName.c_str(), &st));
+ ASSERT_LT(0, st.st_size);
+
+ // The minidump should not contain an exception stream.
+ Minidump minidump(lastDumpName);
+ ASSERT_TRUE(minidump.Read());
+
+ MinidumpException* exception = minidump.GetException();
+ EXPECT_FALSE(exception);
+}
+
+TEST_F(ExceptionHandlerTest, WriteMinidumpWithException) {
+ ExceptionHandler eh(tempDir.path(), NULL, DumpNameMDCallback, this, true,
+ NULL);
+ ASSERT_TRUE(eh.WriteMinidump(true));
+
+ // Ensure that minidump file exists and is > 0 bytes.
+ ASSERT_FALSE(lastDumpName.empty());
+ struct stat st;
+ ASSERT_EQ(0, stat(lastDumpName.c_str(), &st));
+ ASSERT_LT(0, st.st_size);
+
+ // The minidump should contain an exception stream.
+ Minidump minidump(lastDumpName);
+ ASSERT_TRUE(minidump.Read());
+
+ MinidumpException* exception = minidump.GetException();
+ ASSERT_TRUE(exception);
+ const MDRawExceptionStream* raw_exception = exception->exception();
+ ASSERT_TRUE(raw_exception);
+
+ EXPECT_EQ(MD_EXCEPTION_MAC_BREAKPOINT,
+ raw_exception->exception_record.exception_code);
+}
+
+TEST_F(ExceptionHandlerTest, DumpChildProcess) {
+ const int kTimeoutMs = 2000;
+ // Create a mach port to receive the child task on.
+ char machPortName[128];
+ sprintf(machPortName, "ExceptionHandlerTest.%d", getpid());
+ ReceivePort parent_recv_port(machPortName);
+
+ // Give the child process a pipe to block on.
+ int fds[2];
+ ASSERT_EQ(0, pipe(fds));
+
+ // Fork off a child process to dump.
+ pid_t pid = fork();
+ if (pid == 0) {
+ // In the child process
+ close(fds[1]);
+
+ // Send parent process the task and thread ports.
+ MachSendMessage child_message(0);
+ child_message.AddDescriptor(mach_task_self());
+ child_message.AddDescriptor(mach_thread_self());
+
+ MachPortSender child_sender(machPortName);
+ if (child_sender.SendMessage(child_message, kTimeoutMs) != KERN_SUCCESS)
+ exit(1);
+
+ // Wait for the parent process.
+ uint8_t data;
+ read(fds[0], &data, 1);
+ exit(0);
+ }
+ // In the parent process.
+ ASSERT_NE(-1, pid);
+ close(fds[0]);
+
+ // Read the child's task and thread ports.
+ MachReceiveMessage child_message;
+ ASSERT_EQ(KERN_SUCCESS,
+ parent_recv_port.WaitForMessage(&child_message, kTimeoutMs));
+ mach_port_t child_task = child_message.GetTranslatedPort(0);
+ mach_port_t child_thread = child_message.GetTranslatedPort(1);
+ ASSERT_NE((mach_port_t)MACH_PORT_NULL, child_task);
+ ASSERT_NE((mach_port_t)MACH_PORT_NULL, child_thread);
+
+ // Write a minidump of the child process.
+ bool result = ExceptionHandler::WriteMinidumpForChild(child_task,
+ child_thread,
+ tempDir.path(),
+ DumpNameMDCallback,
+ this);
+ ASSERT_EQ(true, result);
+
+ // Ensure that minidump file exists and is > 0 bytes.
+ ASSERT_FALSE(lastDumpName.empty());
+ struct stat st;
+ ASSERT_EQ(0, stat(lastDumpName.c_str(), &st));
+ ASSERT_LT(0, st.st_size);
+
+ // Unblock child process
+ uint8_t data = 1;
+ IGNORE_RET(write(fds[1], &data, 1));
+
+ // Child process should have exited with a zero status.
+ int ret;
+ ASSERT_EQ(pid, waitpid(pid, &ret, 0));
+ EXPECT_NE(0, WIFEXITED(ret));
+ EXPECT_EQ(0, WEXITSTATUS(ret));
+}
+
+// Test that memory around the instruction pointer is written
+// to the dump as a MinidumpMemoryRegion.
+TEST_F(ExceptionHandlerTest, InstructionPointerMemory) {
+ // Give the child process a pipe to report back on.
+ int fds[2];
+ ASSERT_EQ(0, pipe(fds));
+
+ // These are defined here so the parent can use them to check the
+ // data from the minidump afterwards.
+ const uint32_t kMemorySize = 256; // bytes
+ const int kOffset = kMemorySize / 2;
+ // This crashes with SIGILL on x86/x86-64/arm.
+ const unsigned char instructions[] = { 0xff, 0xff, 0xff, 0xff };
+
+ pid_t pid = fork();
+ if (pid == 0) {
+ close(fds[0]);
+ ExceptionHandler eh(tempDir.path(), NULL, MDCallback, &fds[1], true, NULL);
+ // Get some executable memory.
+ char* memory =
+ reinterpret_cast<char*>(mmap(NULL,
+ kMemorySize,
+ PROT_READ | PROT_WRITE | PROT_EXEC,
+ MAP_PRIVATE | MAP_ANON,
+ -1,
+ 0));
+ if (!memory)
+ exit(0);
+
+ // Write some instructions that will crash. Put them in the middle
+ // of the block of memory, because the minidump should contain 128
+ // bytes on either side of the instruction pointer.
+ memcpy(memory + kOffset, instructions, sizeof(instructions));
+
+ // Now execute the instructions, which should crash.
+ typedef void (*void_function)(void);
+ void_function memory_function =
+ reinterpret_cast<void_function>(memory + kOffset);
+ memory_function();
+ // not reached
+ exit(1);
+ }
+ // In the parent process.
+ ASSERT_NE(-1, pid);
+ close(fds[1]);
+
+ // Wait for the background process to return the minidump file.
+ close(fds[1]);
+ char minidump_file[PATH_MAX];
+ ssize_t nbytes = read(fds[0], minidump_file, sizeof(minidump_file));
+ ASSERT_NE(0, nbytes);
+ // Ensure that minidump file exists and is > 0 bytes.
+ struct stat st;
+ ASSERT_EQ(0, stat(minidump_file, &st));
+ ASSERT_LT(0, st.st_size);
+
+ // Child process should have exited with a zero status.
+ int ret;
+ ASSERT_EQ(pid, waitpid(pid, &ret, 0));
+ EXPECT_NE(0, WIFEXITED(ret));
+ EXPECT_EQ(0, WEXITSTATUS(ret));
+
+ // Read the minidump. Locate the exception record and the
+ // memory list, and then ensure that there is a memory region
+ // in the memory list that covers the instruction pointer from
+ // the exception record.
+ Minidump minidump(minidump_file);
+ ASSERT_TRUE(minidump.Read());
+
+ MinidumpException* exception = minidump.GetException();
+ MinidumpMemoryList* memory_list = minidump.GetMemoryList();
+ ASSERT_TRUE(exception);
+ ASSERT_TRUE(memory_list);
+ ASSERT_NE((unsigned int)0, memory_list->region_count());
+
+ MinidumpContext* context = exception->GetContext();
+ ASSERT_TRUE(context);
+
+ uint64_t instruction_pointer;
+ ASSERT_TRUE(context->GetInstructionPointer(&instruction_pointer));
+
+ MinidumpMemoryRegion* region =
+ memory_list->GetMemoryRegionForAddress(instruction_pointer);
+ EXPECT_TRUE(region);
+
+ EXPECT_EQ(kMemorySize, region->GetSize());
+ const uint8_t* bytes = region->GetMemory();
+ ASSERT_TRUE(bytes);
+
+ uint8_t prefix_bytes[kOffset];
+ uint8_t suffix_bytes[kMemorySize - kOffset - sizeof(instructions)];
+ memset(prefix_bytes, 0, sizeof(prefix_bytes));
+ memset(suffix_bytes, 0, sizeof(suffix_bytes));
+ EXPECT_TRUE(memcmp(bytes, prefix_bytes, sizeof(prefix_bytes)) == 0);
+ EXPECT_TRUE(memcmp(bytes + kOffset, instructions, sizeof(instructions)) == 0);
+ EXPECT_TRUE(memcmp(bytes + kOffset + sizeof(instructions),
+ suffix_bytes, sizeof(suffix_bytes)) == 0);
+}
+
+// Test that the memory region around the instruction pointer is
+// bounded correctly on the low end.
+TEST_F(ExceptionHandlerTest, InstructionPointerMemoryMinBound) {
+ // Give the child process a pipe to report back on.
+ int fds[2];
+ ASSERT_EQ(0, pipe(fds));
+
+ // These are defined here so the parent can use them to check the
+ // data from the minidump afterwards.
+ const uint32_t kMemorySize = 256; // bytes
+ const int kOffset = 0;
+ // This crashes with SIGILL on x86/x86-64/arm.
+ const unsigned char instructions[] = { 0xff, 0xff, 0xff, 0xff };
+
+ pid_t pid = fork();
+ if (pid == 0) {
+ close(fds[0]);
+ ExceptionHandler eh(tempDir.path(), NULL, MDCallback, &fds[1], true, NULL);
+ // Get some executable memory.
+ char* memory =
+ reinterpret_cast<char*>(mmap(NULL,
+ kMemorySize,
+ PROT_READ | PROT_WRITE | PROT_EXEC,
+ MAP_PRIVATE | MAP_ANON,
+ -1,
+ 0));
+ if (!memory)
+ exit(0);
+
+ // Write some instructions that will crash. Put them at the start
+ // of the block of memory, to ensure that the memory bounding
+ // works properly.
+ memcpy(memory + kOffset, instructions, sizeof(instructions));
+
+ // Now execute the instructions, which should crash.
+ typedef void (*void_function)(void);
+ void_function memory_function =
+ reinterpret_cast<void_function>(memory + kOffset);
+ memory_function();
+ // not reached
+ exit(1);
+ }
+ // In the parent process.
+ ASSERT_NE(-1, pid);
+ close(fds[1]);
+
+ // Wait for the background process to return the minidump file.
+ close(fds[1]);
+ char minidump_file[PATH_MAX];
+ ssize_t nbytes = read(fds[0], minidump_file, sizeof(minidump_file));
+ ASSERT_NE(0, nbytes);
+ // Ensure that minidump file exists and is > 0 bytes.
+ struct stat st;
+ ASSERT_EQ(0, stat(minidump_file, &st));
+ ASSERT_LT(0, st.st_size);
+
+ // Child process should have exited with a zero status.
+ int ret;
+ ASSERT_EQ(pid, waitpid(pid, &ret, 0));
+ EXPECT_NE(0, WIFEXITED(ret));
+ EXPECT_EQ(0, WEXITSTATUS(ret));
+
+ // Read the minidump. Locate the exception record and the
+ // memory list, and then ensure that there is a memory region
+ // in the memory list that covers the instruction pointer from
+ // the exception record.
+ Minidump minidump(minidump_file);
+ ASSERT_TRUE(minidump.Read());
+
+ MinidumpException* exception = minidump.GetException();
+ MinidumpMemoryList* memory_list = minidump.GetMemoryList();
+ ASSERT_TRUE(exception);
+ ASSERT_TRUE(memory_list);
+ ASSERT_NE((unsigned int)0, memory_list->region_count());
+
+ MinidumpContext* context = exception->GetContext();
+ ASSERT_TRUE(context);
+
+ uint64_t instruction_pointer;
+ ASSERT_TRUE(context->GetInstructionPointer(&instruction_pointer));
+
+ MinidumpMemoryRegion* region =
+ memory_list->GetMemoryRegionForAddress(instruction_pointer);
+ EXPECT_TRUE(region);
+
+ EXPECT_EQ(kMemorySize / 2, region->GetSize());
+ const uint8_t* bytes = region->GetMemory();
+ ASSERT_TRUE(bytes);
+
+ uint8_t suffix_bytes[kMemorySize / 2 - sizeof(instructions)];
+ memset(suffix_bytes, 0, sizeof(suffix_bytes));
+ EXPECT_TRUE(memcmp(bytes + kOffset, instructions, sizeof(instructions)) == 0);
+ EXPECT_TRUE(memcmp(bytes + kOffset + sizeof(instructions),
+ suffix_bytes, sizeof(suffix_bytes)) == 0);
+}
+
+// Test that the memory region around the instruction pointer is
+// bounded correctly on the high end.
+TEST_F(ExceptionHandlerTest, InstructionPointerMemoryMaxBound) {
+ // Give the child process a pipe to report back on.
+ int fds[2];
+ ASSERT_EQ(0, pipe(fds));
+
+ // These are defined here so the parent can use them to check the
+ // data from the minidump afterwards.
+ // Use 4k here because the OS will hand out a single page even
+ // if a smaller size is requested, and this test wants to
+ // test the upper bound of the memory range.
+ const uint32_t kMemorySize = 4096; // bytes
+ // This crashes with SIGILL on x86/x86-64/arm.
+ const unsigned char instructions[] = { 0xff, 0xff, 0xff, 0xff };
+ const int kOffset = kMemorySize - sizeof(instructions);
+
+ pid_t pid = fork();
+ if (pid == 0) {
+ close(fds[0]);
+ ExceptionHandler eh(tempDir.path(), NULL, MDCallback, &fds[1], true, NULL);
+ // Get some executable memory.
+ char* memory =
+ reinterpret_cast<char*>(mmap(NULL,
+ kMemorySize,
+ PROT_READ | PROT_WRITE | PROT_EXEC,
+ MAP_PRIVATE | MAP_ANON,
+ -1,
+ 0));
+ if (!memory)
+ exit(0);
+
+ // Write some instructions that will crash. Put them at the start
+ // of the block of memory, to ensure that the memory bounding
+ // works properly.
+ memcpy(memory + kOffset, instructions, sizeof(instructions));
+
+ // Now execute the instructions, which should crash.
+ typedef void (*void_function)(void);
+ void_function memory_function =
+ reinterpret_cast<void_function>(memory + kOffset);
+ memory_function();
+ // not reached
+ exit(1);
+ }
+ // In the parent process.
+ ASSERT_NE(-1, pid);
+ close(fds[1]);
+
+ // Wait for the background process to return the minidump file.
+ close(fds[1]);
+ char minidump_file[PATH_MAX];
+ ssize_t nbytes = read(fds[0], minidump_file, sizeof(minidump_file));
+ ASSERT_NE(0, nbytes);
+ // Ensure that minidump file exists and is > 0 bytes.
+ struct stat st;
+ ASSERT_EQ(0, stat(minidump_file, &st));
+ ASSERT_LT(0, st.st_size);
+
+ // Child process should have exited with a zero status.
+ int ret;
+ ASSERT_EQ(pid, waitpid(pid, &ret, 0));
+ EXPECT_NE(0, WIFEXITED(ret));
+ EXPECT_EQ(0, WEXITSTATUS(ret));
+
+ // Read the minidump. Locate the exception record and the
+ // memory list, and then ensure that there is a memory region
+ // in the memory list that covers the instruction pointer from
+ // the exception record.
+ Minidump minidump(minidump_file);
+ ASSERT_TRUE(minidump.Read());
+
+ MinidumpException* exception = minidump.GetException();
+ MinidumpMemoryList* memory_list = minidump.GetMemoryList();
+ ASSERT_TRUE(exception);
+ ASSERT_TRUE(memory_list);
+ ASSERT_NE((unsigned int)0, memory_list->region_count());
+
+ MinidumpContext* context = exception->GetContext();
+ ASSERT_TRUE(context);
+
+ uint64_t instruction_pointer;
+ ASSERT_TRUE(context->GetInstructionPointer(&instruction_pointer));
+
+ MinidumpMemoryRegion* region =
+ memory_list->GetMemoryRegionForAddress(instruction_pointer);
+ EXPECT_TRUE(region);
+
+ const size_t kPrefixSize = 128; // bytes
+ EXPECT_EQ(kPrefixSize + sizeof(instructions), region->GetSize());
+ const uint8_t* bytes = region->GetMemory();
+ ASSERT_TRUE(bytes);
+
+ uint8_t prefix_bytes[kPrefixSize];
+ memset(prefix_bytes, 0, sizeof(prefix_bytes));
+ EXPECT_TRUE(memcmp(bytes, prefix_bytes, sizeof(prefix_bytes)) == 0);
+ EXPECT_TRUE(memcmp(bytes + kPrefixSize,
+ instructions, sizeof(instructions)) == 0);
+}
+
+// Ensure that an extra memory block doesn't get added when the
+// instruction pointer is not in mapped memory.
+TEST_F(ExceptionHandlerTest, InstructionPointerMemoryNullPointer) {
+ // Give the child process a pipe to report back on.
+ int fds[2];
+ ASSERT_EQ(0, pipe(fds));
+
+ pid_t pid = fork();
+ if (pid == 0) {
+ close(fds[0]);
+ ExceptionHandler eh(tempDir.path(), NULL, MDCallback, &fds[1], true, NULL);
+ // Try calling a NULL pointer.
+ typedef void (*void_function)(void);
+ // Volatile markings are needed to keep Clang from generating invalid
+ // opcodes. See http://crbug.com/498354 for details.
+ volatile void_function memory_function =
+ reinterpret_cast<void_function>(NULL);
+ memory_function();
+ // not reached
+ exit(1);
+ }
+ // In the parent process.
+ ASSERT_NE(-1, pid);
+ close(fds[1]);
+
+ // Wait for the background process to return the minidump file.
+ close(fds[1]);
+ char minidump_file[PATH_MAX];
+ ssize_t nbytes = read(fds[0], minidump_file, sizeof(minidump_file));
+ ASSERT_NE(0, nbytes);
+ // Ensure that minidump file exists and is > 0 bytes.
+ struct stat st;
+ ASSERT_EQ(0, stat(minidump_file, &st));
+ ASSERT_LT(0, st.st_size);
+
+ // Child process should have exited with a zero status.
+ int ret;
+ ASSERT_EQ(pid, waitpid(pid, &ret, 0));
+ EXPECT_NE(0, WIFEXITED(ret));
+ EXPECT_EQ(0, WEXITSTATUS(ret));
+
+ // Read the minidump. Locate the exception record and the
+ // memory list, and then ensure that there is only one memory region
+ // in the memory list (the thread memory from the single thread).
+ Minidump minidump(minidump_file);
+ ASSERT_TRUE(minidump.Read());
+
+ MinidumpException* exception = minidump.GetException();
+ MinidumpMemoryList* memory_list = minidump.GetMemoryList();
+ ASSERT_TRUE(exception);
+ ASSERT_TRUE(memory_list);
+ ASSERT_EQ((unsigned int)1, memory_list->region_count());
+}
+
+static void *Junk(void *) {
+ sleep(1000000);
+ return NULL;
+}
+
+// Test that the memory list gets written correctly when multiple
+// threads are running.
+TEST_F(ExceptionHandlerTest, MemoryListMultipleThreads) {
+ // Give the child process a pipe to report back on.
+ int fds[2];
+ ASSERT_EQ(0, pipe(fds));
+
+ pid_t pid = fork();
+ if (pid == 0) {
+ close(fds[0]);
+ ExceptionHandler eh(tempDir.path(), NULL, MDCallback, &fds[1], true, NULL);
+
+ // Run an extra thread so >2 memory regions will be written.
+ pthread_t junk_thread;
+ if (pthread_create(&junk_thread, NULL, Junk, NULL) == 0)
+ pthread_detach(junk_thread);
+
+ // Just crash.
+ Crasher();
+
+ // not reached
+ exit(1);
+ }
+ // In the parent process.
+ ASSERT_NE(-1, pid);
+ close(fds[1]);
+
+ // Wait for the background process to return the minidump file.
+ close(fds[1]);
+ char minidump_file[PATH_MAX];
+ ssize_t nbytes = read(fds[0], minidump_file, sizeof(minidump_file));
+ ASSERT_NE(0, nbytes);
+ // Ensure that minidump file exists and is > 0 bytes.
+ struct stat st;
+ ASSERT_EQ(0, stat(minidump_file, &st));
+ ASSERT_LT(0, st.st_size);
+
+ // Child process should have exited with a zero status.
+ int ret;
+ ASSERT_EQ(pid, waitpid(pid, &ret, 0));
+ EXPECT_NE(0, WIFEXITED(ret));
+ EXPECT_EQ(0, WEXITSTATUS(ret));
+
+ // Read the minidump, and verify that the memory list can be read.
+ Minidump minidump(minidump_file);
+ ASSERT_TRUE(minidump.Read());
+
+ MinidumpMemoryList* memory_list = minidump.GetMemoryList();
+ ASSERT_TRUE(memory_list);
+ // Verify that there are three memory regions:
+ // one per thread, and one for the instruction pointer memory.
+ ASSERT_EQ((unsigned int)3, memory_list->region_count());
+}
+
+}
diff --git a/toolkit/crashreporter/breakpad-client/mac/tests/minidump_generator_test.cc b/toolkit/crashreporter/breakpad-client/mac/tests/minidump_generator_test.cc
new file mode 100644
index 0000000000..b1fa5d02a1
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/mac/tests/minidump_generator_test.cc
@@ -0,0 +1,320 @@
+// Copyright (c) 2010, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// minidump_generator_test.cc: Unit tests for google_breakpad::MinidumpGenerator
+
+#include <AvailabilityMacros.h>
+#ifndef MAC_OS_X_VERSION_10_6
+#define MAC_OS_X_VERSION_10_6 1060
+#endif
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <string>
+#include <vector>
+
+#include "breakpad_googletest_includes.h"
+#include "client/mac/handler/minidump_generator.h"
+#include "client/mac/tests/spawn_child_process.h"
+#include "common/linux/ignore_ret.h"
+#include "common/mac/MachIPC.h"
+#include "common/tests/auto_tempdir.h"
+#include "google_breakpad/processor/minidump.h"
+
+namespace google_breakpad {
+// This acts as the log sink for INFO logging from the processor
+// logging code. The logging output confuses XCode and makes it think
+// there are unit test failures. testlogging.h handles the overriding.
+std::ostringstream info_log;
+}
+
+namespace {
+using std::string;
+using std::vector;
+using google_breakpad::AutoTempDir;
+using google_breakpad::MinidumpGenerator;
+using google_breakpad::MachPortSender;
+using google_breakpad::MachReceiveMessage;
+using google_breakpad::MachSendMessage;
+using google_breakpad::Minidump;
+using google_breakpad::MinidumpContext;
+using google_breakpad::MinidumpException;
+using google_breakpad::MinidumpModule;
+using google_breakpad::MinidumpModuleList;
+using google_breakpad::MinidumpSystemInfo;
+using google_breakpad::MinidumpThread;
+using google_breakpad::MinidumpThreadList;
+using google_breakpad::ReceivePort;
+using testing::Test;
+using namespace google_breakpad_test;
+
+class MinidumpGeneratorTest : public Test {
+ public:
+ AutoTempDir tempDir;
+};
+
+static void *Junk(void* data) {
+ bool* wait = reinterpret_cast<bool*>(data);
+ while (!*wait) {
+ usleep(10000);
+ }
+ return NULL;
+}
+
+TEST_F(MinidumpGeneratorTest, InProcess) {
+ MinidumpGenerator generator;
+ string dump_filename =
+ MinidumpGenerator::UniqueNameInDirectory(tempDir.path(), NULL);
+
+ // Run an extra thread since MinidumpGenerator assumes there
+ // are 2 or more threads.
+ pthread_t junk_thread;
+ bool quit = false;
+ ASSERT_EQ(0, pthread_create(&junk_thread, NULL, Junk, &quit));
+
+ ASSERT_TRUE(generator.Write(dump_filename.c_str()));
+ // Ensure that minidump file exists and is > 0 bytes.
+ struct stat st;
+ ASSERT_EQ(0, stat(dump_filename.c_str(), &st));
+ ASSERT_LT(0, st.st_size);
+
+ // join the background thread
+ quit = true;
+ pthread_join(junk_thread, NULL);
+
+ // Read the minidump, sanity check some data.
+ Minidump minidump(dump_filename.c_str());
+ ASSERT_TRUE(minidump.Read());
+
+ MinidumpSystemInfo* system_info = minidump.GetSystemInfo();
+ ASSERT_TRUE(system_info);
+ const MDRawSystemInfo* raw_info = system_info->system_info();
+ ASSERT_TRUE(raw_info);
+ EXPECT_EQ(kNativeArchitecture, raw_info->processor_architecture);
+
+ MinidumpThreadList* thread_list = minidump.GetThreadList();
+ ASSERT_TRUE(thread_list);
+ ASSERT_EQ((unsigned int)1, thread_list->thread_count());
+
+ MinidumpThread* main_thread = thread_list->GetThreadAtIndex(0);
+ ASSERT_TRUE(main_thread);
+ MinidumpContext* context = main_thread->GetContext();
+ ASSERT_TRUE(context);
+ EXPECT_EQ(kNativeContext, context->GetContextCPU());
+
+ MinidumpModuleList* module_list = minidump.GetModuleList();
+ ASSERT_TRUE(module_list);
+ const MinidumpModule* main_module = module_list->GetMainModule();
+ ASSERT_TRUE(main_module);
+ EXPECT_EQ(GetExecutablePath(), main_module->code_file());
+}
+
+TEST_F(MinidumpGeneratorTest, OutOfProcess) {
+ const int kTimeoutMs = 2000;
+ // Create a mach port to receive the child task on.
+ char machPortName[128];
+ sprintf(machPortName, "MinidumpGeneratorTest.OutOfProcess.%d", getpid());
+ ReceivePort parent_recv_port(machPortName);
+
+ // Give the child process a pipe to block on.
+ int fds[2];
+ ASSERT_EQ(0, pipe(fds));
+
+ // Fork off a child process to dump.
+ pid_t pid = fork();
+ if (pid == 0) {
+ // In the child process
+ close(fds[1]);
+
+ // Send parent process the task port.
+ MachSendMessage child_message(0);
+ child_message.AddDescriptor(mach_task_self());
+
+ MachPortSender child_sender(machPortName);
+ if (child_sender.SendMessage(child_message, kTimeoutMs) != KERN_SUCCESS) {
+ fprintf(stderr, "Error sending message from child process!\n");
+ exit(1);
+ }
+
+ // Wait for the parent process.
+ uint8_t data;
+ read(fds[0], &data, 1);
+ exit(0);
+ }
+ // In the parent process.
+ ASSERT_NE(-1, pid);
+ close(fds[0]);
+
+ // Read the child's task port.
+ MachReceiveMessage child_message;
+ ASSERT_EQ(KERN_SUCCESS,
+ parent_recv_port.WaitForMessage(&child_message, kTimeoutMs));
+ mach_port_t child_task = child_message.GetTranslatedPort(0);
+ ASSERT_NE((mach_port_t)MACH_PORT_NULL, child_task);
+
+ // Write a minidump of the child process.
+ MinidumpGenerator generator(child_task, MACH_PORT_NULL);
+ string dump_filename =
+ MinidumpGenerator::UniqueNameInDirectory(tempDir.path(), NULL);
+ ASSERT_TRUE(generator.Write(dump_filename.c_str()));
+
+ // Ensure that minidump file exists and is > 0 bytes.
+ struct stat st;
+ ASSERT_EQ(0, stat(dump_filename.c_str(), &st));
+ ASSERT_LT(0, st.st_size);
+
+ // Unblock child process
+ uint8_t data = 1;
+ IGNORE_RET(write(fds[1], &data, 1));
+
+ // Child process should have exited with a zero status.
+ int ret;
+ ASSERT_EQ(pid, waitpid(pid, &ret, 0));
+ EXPECT_NE(0, WIFEXITED(ret));
+ EXPECT_EQ(0, WEXITSTATUS(ret));
+
+ // Read the minidump, sanity check some data.
+ Minidump minidump(dump_filename.c_str());
+ ASSERT_TRUE(minidump.Read());
+
+ MinidumpSystemInfo* system_info = minidump.GetSystemInfo();
+ ASSERT_TRUE(system_info);
+ const MDRawSystemInfo* raw_info = system_info->system_info();
+ ASSERT_TRUE(raw_info);
+ EXPECT_EQ(kNativeArchitecture, raw_info->processor_architecture);
+
+ MinidumpThreadList* thread_list = minidump.GetThreadList();
+ ASSERT_TRUE(thread_list);
+ ASSERT_EQ((unsigned int)1, thread_list->thread_count());
+
+ MinidumpThread* main_thread = thread_list->GetThreadAtIndex(0);
+ ASSERT_TRUE(main_thread);
+ MinidumpContext* context = main_thread->GetContext();
+ ASSERT_TRUE(context);
+ EXPECT_EQ(kNativeContext, context->GetContextCPU());
+
+ MinidumpModuleList* module_list = minidump.GetModuleList();
+ ASSERT_TRUE(module_list);
+ const MinidumpModule* main_module = module_list->GetMainModule();
+ ASSERT_TRUE(main_module);
+ EXPECT_EQ(GetExecutablePath(), main_module->code_file());
+}
+
+// This test fails on 10.5, but I don't have easy access to a 10.5 machine,
+// so it's simpler to just limit it to 10.6 for now.
+#if (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6) && \
+ (defined(__x86_64__) || defined(__i386__))
+
+TEST_F(MinidumpGeneratorTest, CrossArchitectureDump) {
+ const int kTimeoutMs = 5000;
+ // Create a mach port to receive the child task on.
+ char machPortName[128];
+ sprintf(machPortName,
+ "MinidumpGeneratorTest.CrossArchitectureDump.%d", getpid());
+
+ ReceivePort parent_recv_port(machPortName);
+
+ // Spawn a child process to dump.
+ string helper_path = GetHelperPath();
+ const char* argv[] = {
+ helper_path.c_str(),
+ machPortName,
+ NULL
+ };
+ pid_t pid = spawn_child_process(argv);
+ ASSERT_NE(-1, pid);
+
+ // Read the child's task port.
+ MachReceiveMessage child_message;
+ ASSERT_EQ(KERN_SUCCESS,
+ parent_recv_port.WaitForMessage(&child_message, kTimeoutMs));
+ mach_port_t child_task = child_message.GetTranslatedPort(0);
+ ASSERT_NE((mach_port_t)MACH_PORT_NULL, child_task);
+
+ // Write a minidump of the child process.
+ MinidumpGenerator generator(child_task, MACH_PORT_NULL);
+ string dump_filename =
+ MinidumpGenerator::UniqueNameInDirectory(tempDir.path(), NULL);
+ ASSERT_TRUE(generator.Write(dump_filename.c_str()));
+
+ // Ensure that minidump file exists and is > 0 bytes.
+ struct stat st;
+ ASSERT_EQ(0, stat(dump_filename.c_str(), &st));
+ ASSERT_LT(0, st.st_size);
+
+ // Kill child process.
+ kill(pid, SIGKILL);
+
+ int ret;
+ ASSERT_EQ(pid, waitpid(pid, &ret, 0));
+
+const MDCPUArchitecture kExpectedArchitecture =
+#if defined(__x86_64__)
+ MD_CPU_ARCHITECTURE_X86
+#elif defined(__i386__)
+ MD_CPU_ARCHITECTURE_AMD64
+#endif
+ ;
+const uint32_t kExpectedContext =
+#if defined(__i386__)
+ MD_CONTEXT_AMD64
+#elif defined(__x86_64__)
+ MD_CONTEXT_X86
+#endif
+ ;
+
+ // Read the minidump, sanity check some data.
+ Minidump minidump(dump_filename.c_str());
+ ASSERT_TRUE(minidump.Read());
+
+ MinidumpSystemInfo* system_info = minidump.GetSystemInfo();
+ ASSERT_TRUE(system_info);
+ const MDRawSystemInfo* raw_info = system_info->system_info();
+ ASSERT_TRUE(raw_info);
+ EXPECT_EQ(kExpectedArchitecture, raw_info->processor_architecture);
+
+ MinidumpThreadList* thread_list = minidump.GetThreadList();
+ ASSERT_TRUE(thread_list);
+ ASSERT_EQ((unsigned int)1, thread_list->thread_count());
+
+ MinidumpThread* main_thread = thread_list->GetThreadAtIndex(0);
+ ASSERT_TRUE(main_thread);
+ MinidumpContext* context = main_thread->GetContext();
+ ASSERT_TRUE(context);
+ EXPECT_EQ(kExpectedContext, context->GetContextCPU());
+
+ MinidumpModuleList* module_list = minidump.GetModuleList();
+ ASSERT_TRUE(module_list);
+ const MinidumpModule* main_module = module_list->GetMainModule();
+ ASSERT_TRUE(main_module);
+ EXPECT_EQ(helper_path, main_module->code_file());
+}
+#endif // 10.6 && (x86-64 || i386)
+
+}
diff --git a/toolkit/crashreporter/breakpad-client/mac/tests/minidump_generator_test_helper.cc b/toolkit/crashreporter/breakpad-client/mac/tests/minidump_generator_test_helper.cc
new file mode 100644
index 0000000000..4e8ce3cf00
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/mac/tests/minidump_generator_test_helper.cc
@@ -0,0 +1,74 @@
+// Copyright (c) 2010, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// minidump_generator_test_helper.cc: A helper program that
+// minidump_generator_test.cc can launch to test certain things
+// that require a separate executable.
+
+#include <unistd.h>
+
+#include "client/mac/handler/exception_handler.h"
+#include "common/mac/MachIPC.h"
+
+using google_breakpad::MachPortSender;
+using google_breakpad::MachReceiveMessage;
+using google_breakpad::MachSendMessage;
+using google_breakpad::ReceivePort;
+
+int main(int argc, char** argv) {
+ if (argc < 2)
+ return 1;
+
+ if (strcmp(argv[1], "crash") != 0) {
+ const int kTimeoutMs = 2000;
+ // Send parent process the task and thread ports.
+ MachSendMessage child_message(0);
+ child_message.AddDescriptor(mach_task_self());
+ child_message.AddDescriptor(mach_thread_self());
+
+ MachPortSender child_sender(argv[1]);
+ if (child_sender.SendMessage(child_message, kTimeoutMs) != KERN_SUCCESS) {
+ fprintf(stderr, "Error sending message from child process!\n");
+ exit(1);
+ }
+
+ // Loop forever.
+ while (true) {
+ sleep(100);
+ }
+ } else if (argc == 3 && strcmp(argv[1], "crash") == 0) {
+ // Instantiate an OOP exception handler
+ google_breakpad::ExceptionHandler eh("", NULL, NULL, NULL, true, argv[2]);
+ // and crash.
+ int *a = (int*)0x42;
+ *a = 1;
+ }
+
+ return 0;
+}
diff --git a/toolkit/crashreporter/breakpad-client/mac/tests/spawn_child_process.h b/toolkit/crashreporter/breakpad-client/mac/tests/spawn_child_process.h
new file mode 100644
index 0000000000..1b82c56278
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/mac/tests/spawn_child_process.h
@@ -0,0 +1,149 @@
+// Copyright (c) 2010, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Utility functions for spawning a helper process using a different
+// CPU architecture.
+
+#ifndef GOOGLE_BREAKPAD_CLIENT_MAC_TESTS_SPAWN_CHILD_PROCESS
+#define GOOGLE_BREAKPAD_CLIENT_MAC_TESTS_SPAWN_CHILD_PROCESS
+
+#include <AvailabilityMacros.h>
+#ifndef MAC_OS_X_VERSION_10_6
+#define MAC_OS_X_VERSION_10_6 1060
+#endif
+#include <crt_externs.h>
+#include <mach-o/dyld.h>
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6
+#include <spawn.h>
+#endif
+
+#include <string>
+#include <vector>
+
+#include "google_breakpad/common/minidump_format.h"
+
+namespace google_breakpad_test {
+
+using std::string;
+using std::vector;
+
+const MDCPUArchitecture kNativeArchitecture =
+#if defined(__i386__)
+ MD_CPU_ARCHITECTURE_X86
+#elif defined(__x86_64__)
+ MD_CPU_ARCHITECTURE_AMD64
+#elif defined(__ppc__) || defined(__ppc64__)
+ MD_CPU_ARCHITECTURE_PPC
+#else
+#error "This file has not been ported to this CPU architecture."
+#endif
+ ;
+
+const uint32_t kNativeContext =
+#if defined(__i386__)
+ MD_CONTEXT_X86
+#elif defined(__x86_64__)
+ MD_CONTEXT_AMD64
+#elif defined(__ppc__) || defined(__ppc64__)
+ MD_CONTEXT_PPC
+#else
+#error "This file has not been ported to this CPU architecture."
+#endif
+ ;
+
+string GetExecutablePath() {
+ char self_path[PATH_MAX];
+ uint32_t size = sizeof(self_path);
+ if (_NSGetExecutablePath(self_path, &size) != 0)
+ return "";
+ return self_path;
+}
+
+string GetHelperPath() {
+ string helper_path(GetExecutablePath());
+ size_t pos = helper_path.rfind('/');
+ if (pos == string::npos)
+ return "";
+
+ helper_path.erase(pos + 1);
+ helper_path += "minidump_generator_test_helper";
+ return helper_path;
+}
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6
+
+pid_t spawn_child_process(const char** argv) {
+ posix_spawnattr_t spawnattr;
+ if (posix_spawnattr_init(&spawnattr) != 0)
+ return (pid_t)-1;
+
+ cpu_type_t pref_cpu_types[2] = {
+#if defined(__x86_64__)
+ CPU_TYPE_X86,
+#elif defined(__i386__)
+ CPU_TYPE_X86_64,
+#endif
+ CPU_TYPE_ANY
+ };
+
+ // Set spawn attributes.
+ size_t attr_count = sizeof(pref_cpu_types) / sizeof(pref_cpu_types[0]);
+ size_t attr_ocount = 0;
+ if (posix_spawnattr_setbinpref_np(&spawnattr,
+ attr_count,
+ pref_cpu_types,
+ &attr_ocount) != 0 ||
+ attr_ocount != attr_count) {
+ posix_spawnattr_destroy(&spawnattr);
+ return (pid_t)-1;
+ }
+
+ // Create an argv array.
+ vector<char*> argv_v;
+ while (*argv) {
+ argv_v.push_back(strdup(*argv));
+ argv++;
+ }
+ argv_v.push_back(NULL);
+ pid_t new_pid = 0;
+ int result = posix_spawnp(&new_pid, argv_v[0], NULL, &spawnattr,
+ &argv_v[0], *_NSGetEnviron());
+ posix_spawnattr_destroy(&spawnattr);
+
+ for (unsigned i = 0; i < argv_v.size(); i++) {
+ free(argv_v[i]);
+ }
+
+ return result == 0 ? new_pid : -1;
+}
+#endif
+
+} // namespace google_breakpad_test
+
+#endif // GOOGLE_BREAKPAD_CLIENT_MAC_TESTS_SPAWN_CHILD_PROCESS
diff --git a/toolkit/crashreporter/breakpad-client/mac/tests/testlogging.h b/toolkit/crashreporter/breakpad-client/mac/tests/testlogging.h
new file mode 100644
index 0000000000..c6b6be699b
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/mac/tests/testlogging.h
@@ -0,0 +1,9 @@
+// This file exists to override the processor logging for unit tests,
+// since it confuses XCode into thinking unit tests have failed.
+#include <sstream>
+
+namespace google_breakpad {
+extern std::ostringstream info_log;
+}
+
+#define BPLOG_INFO_STREAM google_breakpad::info_log
diff --git a/toolkit/crashreporter/breakpad-client/minidump_file_writer-inl.h b/toolkit/crashreporter/breakpad-client/minidump_file_writer-inl.h
new file mode 100644
index 0000000000..bf63135b85
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/minidump_file_writer-inl.h
@@ -0,0 +1,97 @@
+// Copyright (c) 2006, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// minidump_file_writer-inl.h: Minidump file writer implementation.
+//
+// See minidump_file_writer.h for documentation.
+
+#ifndef CLIENT_MINIDUMP_FILE_WRITER_INL_H__
+#define CLIENT_MINIDUMP_FILE_WRITER_INL_H__
+
+#include <assert.h>
+
+#include "minidump_file_writer.h"
+#include "google_breakpad/common/minidump_size.h"
+
+namespace google_breakpad {
+
+template<typename MDType>
+inline bool TypedMDRVA<MDType>::Allocate() {
+ allocation_state_ = SINGLE_OBJECT;
+ return UntypedMDRVA::Allocate(minidump_size<MDType>::size());
+}
+
+template<typename MDType>
+inline bool TypedMDRVA<MDType>::Allocate(size_t additional) {
+ allocation_state_ = SINGLE_OBJECT;
+ return UntypedMDRVA::Allocate(minidump_size<MDType>::size() + additional);
+}
+
+template<typename MDType>
+inline bool TypedMDRVA<MDType>::AllocateArray(size_t count) {
+ assert(count);
+ allocation_state_ = ARRAY;
+ return UntypedMDRVA::Allocate(minidump_size<MDType>::size() * count);
+}
+
+template<typename MDType>
+inline bool TypedMDRVA<MDType>::AllocateObjectAndArray(size_t count,
+ size_t length) {
+ assert(count && length);
+ allocation_state_ = SINGLE_OBJECT_WITH_ARRAY;
+ return UntypedMDRVA::Allocate(minidump_size<MDType>::size() + count * length);
+}
+
+template<typename MDType>
+inline bool TypedMDRVA<MDType>::CopyIndex(unsigned int index, MDType *item) {
+ assert(allocation_state_ == ARRAY);
+ return writer_->Copy(
+ static_cast<MDRVA>(position_ + index * minidump_size<MDType>::size()),
+ item, minidump_size<MDType>::size());
+}
+
+template<typename MDType>
+inline bool TypedMDRVA<MDType>::CopyIndexAfterObject(unsigned int index,
+ const void *src,
+ size_t length) {
+ assert(allocation_state_ == SINGLE_OBJECT_WITH_ARRAY);
+ return writer_->Copy(
+ static_cast<MDRVA>(position_ + minidump_size<MDType>::size()
+ + index * length),
+ src, length);
+}
+
+template<typename MDType>
+inline bool TypedMDRVA<MDType>::Flush() {
+ return writer_->Copy(position_, &data_, minidump_size<MDType>::size());
+}
+
+} // namespace google_breakpad
+
+#endif // CLIENT_MINIDUMP_FILE_WRITER_INL_H__
diff --git a/toolkit/crashreporter/breakpad-client/minidump_file_writer.cc b/toolkit/crashreporter/breakpad-client/minidump_file_writer.cc
new file mode 100644
index 0000000000..ed9e957d39
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/minidump_file_writer.cc
@@ -0,0 +1,402 @@
+// Copyright (c) 2006, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// minidump_file_writer.cc: Minidump file writer implementation.
+//
+// See minidump_file_writer.h for documentation.
+
+#include <fcntl.h>
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "minidump_file_writer-inl.h"
+#include "common/linux/linux_libc_support.h"
+#include "common/string_conversion.h"
+#if defined(__linux__) && __linux__
+#include "third_party/lss/linux_syscall_support.h"
+#endif
+
+#if defined(__ANDROID__)
+#include <errno.h>
+
+namespace {
+
+bool g_need_ftruncate_workaround = false;
+bool g_checked_need_ftruncate_workaround = false;
+
+void CheckNeedsFTruncateWorkAround(int file) {
+ if (g_checked_need_ftruncate_workaround) {
+ return;
+ }
+ g_checked_need_ftruncate_workaround = true;
+
+ // Attempt an idempotent truncate that chops off nothing and see if we
+ // run into any sort of errors.
+ off_t offset = sys_lseek(file, 0, SEEK_END);
+ if (offset == -1) {
+ // lseek failed. Don't apply work around. It's unlikely that we can write
+ // to a minidump with either method.
+ return;
+ }
+
+ int result = ftruncate(file, offset);
+ if (result == -1 && errno == EACCES) {
+ // It very likely that we are running into the kernel bug in M devices.
+ // We are going to deploy the workaround for writing minidump files
+ // without uses of ftruncate(). This workaround should be fine even
+ // for kernels without the bug.
+ // See http://crbug.com/542840 for more details.
+ g_need_ftruncate_workaround = true;
+ }
+}
+
+bool NeedsFTruncateWorkAround() {
+ return g_need_ftruncate_workaround;
+}
+
+} // namespace
+#endif // defined(__ANDROID__)
+
+namespace google_breakpad {
+
+const MDRVA MinidumpFileWriter::kInvalidMDRVA = static_cast<MDRVA>(-1);
+
+MinidumpFileWriter::MinidumpFileWriter()
+ : file_(-1),
+ close_file_when_destroyed_(true),
+ position_(0),
+ size_(0) {
+}
+
+MinidumpFileWriter::~MinidumpFileWriter() {
+ if (close_file_when_destroyed_)
+ Close();
+}
+
+bool MinidumpFileWriter::Open(const char *path) {
+ assert(file_ == -1);
+#if defined(__linux__) && __linux__
+ file_ = sys_open(path, O_WRONLY | O_CREAT | O_EXCL, 0600);
+#else
+ file_ = open(path, O_WRONLY | O_CREAT | O_EXCL, 0600);
+#endif
+
+ return file_ != -1;
+}
+
+void MinidumpFileWriter::SetFile(const int file) {
+ assert(file_ == -1);
+ file_ = file;
+ close_file_when_destroyed_ = false;
+#if defined(__ANDROID__)
+ CheckNeedsFTruncateWorkAround(file);
+#endif
+}
+
+bool MinidumpFileWriter::Close() {
+ bool result = true;
+
+ if (file_ != -1) {
+#if defined(__ANDROID__)
+ if (!NeedsFTruncateWorkAround() && ftruncate(file_, position_)) {
+ return false;
+ }
+#else
+ if (ftruncate(file_, position_)) {
+ return false;
+ }
+#endif
+#if defined(__linux__) && __linux__
+ result = (sys_close(file_) == 0);
+#else
+ result = (close(file_) == 0);
+#endif
+ file_ = -1;
+ }
+
+ return result;
+}
+
+bool MinidumpFileWriter::CopyStringToMDString(const wchar_t *str,
+ unsigned int length,
+ TypedMDRVA<MDString> *mdstring) {
+ bool result = true;
+ if (sizeof(wchar_t) == sizeof(uint16_t)) {
+ // Shortcut if wchar_t is the same size as MDString's buffer
+ result = mdstring->Copy(str, mdstring->get()->length);
+ } else {
+ uint16_t out[2];
+ int out_idx = 0;
+
+ // Copy the string character by character
+ while (length && result) {
+ UTF32ToUTF16Char(*str, out);
+ if (!out[0])
+ return false;
+
+ // Process one character at a time
+ --length;
+ ++str;
+
+ // Append the one or two UTF-16 characters. The first one will be non-
+ // zero, but the second one may be zero, depending on the conversion from
+ // UTF-32.
+ int out_count = out[1] ? 2 : 1;
+ size_t out_size = sizeof(uint16_t) * out_count;
+ result = mdstring->CopyIndexAfterObject(out_idx, out, out_size);
+ out_idx += out_count;
+ }
+ }
+ return result;
+}
+
+bool MinidumpFileWriter::CopyStringToMDString(const char *str,
+ unsigned int length,
+ TypedMDRVA<MDString> *mdstring) {
+ bool result = true;
+ uint16_t out[2];
+ int out_idx = 0;
+
+ // Copy the string character by character
+ while (length && result) {
+ int conversion_count = UTF8ToUTF16Char(str, length, out);
+ if (!conversion_count)
+ return false;
+
+ // Move the pointer along based on the nubmer of converted characters
+ length -= conversion_count;
+ str += conversion_count;
+
+ // Append the one or two UTF-16 characters
+ int out_count = out[1] ? 2 : 1;
+ size_t out_size = sizeof(uint16_t) * out_count;
+ result = mdstring->CopyIndexAfterObject(out_idx, out, out_size);
+ out_idx += out_count;
+ }
+ return result;
+}
+
+unsigned int MinidumpFileWriter::CalculateNumOfU16s(const wchar_t *str, unsigned int length) {
+ if (sizeof(wchar_t) == sizeof(uint16_t)) {
+ // Shortcut if wchar_t is the same size as MDString's buffer
+ return length;
+ } else {
+ uint16_t out[2];
+ unsigned int num_of_u16s = 0;
+
+ // Copy the string character by character
+ while (length) {
+ UTF32ToUTF16Char(*str, out);
+ if (!out[0])
+ return false;
+
+ // Process one character at a time
+ --length;
+ ++str;
+
+ // Count the number of UTF-16 characters needed for every wchar_t
+ // and add it to the total.
+ int out_count = out[1] ? 2 : 1;
+ num_of_u16s += out_count;
+ }
+
+ return num_of_u16s;
+ }
+}
+
+unsigned int MinidumpFileWriter::CalculateNumOfU16s(const char *str, unsigned int length) {
+ uint16_t out[2];
+ unsigned int num_of_u16s = 0;
+
+ while (length) {
+ int conversion_count = UTF8ToUTF16Char(str, length, out);
+ if (!conversion_count) {
+ break;
+ }
+ // Move the pointer along based on the number of converted characters
+ length -= conversion_count;
+ str += conversion_count;
+
+ // Add one or two to the total
+ int out_count = out[1] ? 2 : 1;
+ num_of_u16s += out_count;
+ }
+
+ return num_of_u16s;
+}
+
+
+template <typename CharType>
+bool MinidumpFileWriter::WriteStringCore(const CharType *str,
+ unsigned int length,
+ MDLocationDescriptor *location) {
+ assert(str);
+ assert(location);
+ // Calculate the mdstring length by either limiting to |length| as passed in
+ // or by finding the location of the NULL character.
+ unsigned int mdstring_length = 0;
+ if (!length)
+ length = INT_MAX;
+ for (; mdstring_length < length && str[mdstring_length]; ++mdstring_length)
+ ;
+
+ unsigned int num_of_u16s = MinidumpFileWriter::CalculateNumOfU16s(str, mdstring_length);
+
+ // Allocate the string buffer
+ TypedMDRVA<MDString> mdstring(this);
+ if (!mdstring.AllocateObjectAndArray(num_of_u16s + 1, sizeof(uint16_t)))
+ return false;
+
+ // Set length excluding the NULL and copy the string
+ mdstring.get()->length =
+ static_cast<uint32_t>(num_of_u16s * sizeof(uint16_t));
+ bool result = CopyStringToMDString(str, mdstring_length, &mdstring);
+
+ // NULL terminate
+ if (result) {
+ uint16_t ch = 0;
+ result = mdstring.CopyIndexAfterObject(num_of_u16s, &ch, sizeof(ch));
+
+ if (result)
+ *location = mdstring.location();
+ }
+
+ return result;
+}
+
+bool MinidumpFileWriter::WriteString(const wchar_t *str, unsigned int length,
+ MDLocationDescriptor *location) {
+ return WriteStringCore(str, length, location);
+}
+
+bool MinidumpFileWriter::WriteString(const char *str, unsigned int length,
+ MDLocationDescriptor *location) {
+ return WriteStringCore(str, length, location);
+}
+
+bool MinidumpFileWriter::WriteMemory(const void *src, size_t size,
+ MDMemoryDescriptor *output) {
+ assert(src);
+ assert(output);
+ UntypedMDRVA mem(this);
+
+ if (!mem.Allocate(size))
+ return false;
+ if (!mem.Copy(src, mem.size()))
+ return false;
+
+ output->start_of_memory_range = reinterpret_cast<uint64_t>(src);
+ output->memory = mem.location();
+
+ return true;
+}
+
+MDRVA MinidumpFileWriter::Allocate(size_t size) {
+ assert(size);
+ assert(file_ != -1);
+#if defined(__ANDROID__)
+ if (NeedsFTruncateWorkAround()) {
+ // If ftruncate() is not available. We simply increase the size beyond the
+ // current file size. sys_write() will expand the file when data is written
+ // to it. Because we did not over allocate to fit memory pages, we also
+ // do not need to ftruncate() the file once we are done.
+ size_ += size;
+
+ // We don't need to seek since the file is unchanged.
+ MDRVA current_position = position_;
+ position_ += static_cast<MDRVA>(size);
+ return current_position;
+ }
+#endif
+ size_t aligned_size = (size + 7) & ~7; // 64-bit alignment
+
+ if (position_ + aligned_size > size_) {
+ size_t growth = aligned_size;
+ size_t minimal_growth = getpagesize();
+
+ // Ensure that the file grows by at least the size of a memory page
+ if (growth < minimal_growth)
+ growth = minimal_growth;
+
+ size_t new_size = size_ + growth;
+ if (ftruncate(file_, new_size) != 0)
+ return kInvalidMDRVA;
+
+ size_ = new_size;
+ }
+
+ MDRVA current_position = position_;
+ position_ += static_cast<MDRVA>(aligned_size);
+
+ return current_position;
+}
+
+bool MinidumpFileWriter::Copy(MDRVA position, const void *src, ssize_t size) {
+ assert(src);
+ assert(size);
+ assert(file_ != -1);
+
+ // Ensure that the data will fit in the allocated space
+ if (static_cast<size_t>(size + position) > size_)
+ return false;
+
+ // Seek and write the data
+#if defined(__linux__) && __linux__
+ if (sys_lseek(file_, position, SEEK_SET) == static_cast<off_t>(position)) {
+ if (sys_write(file_, src, size) == size) {
+ return true;
+ }
+ }
+#else
+ if (lseek(file_, position, SEEK_SET) == static_cast<off_t>(position)) {
+ if (write(file_, src, size) == size) {
+ return true;
+ }
+ }
+#endif
+ return false;
+}
+
+bool UntypedMDRVA::Allocate(size_t size) {
+ assert(size_ == 0);
+ size_ = size;
+ position_ = writer_->Allocate(size_);
+ return position_ != MinidumpFileWriter::kInvalidMDRVA;
+}
+
+bool UntypedMDRVA::Copy(MDRVA pos, const void *src, size_t size) {
+ assert(src);
+ assert(size);
+ assert(pos + size <= position_ + size_);
+ return writer_->Copy(pos, src, size);
+}
+
+} // namespace google_breakpad
diff --git a/toolkit/crashreporter/breakpad-client/minidump_file_writer.h b/toolkit/crashreporter/breakpad-client/minidump_file_writer.h
new file mode 100644
index 0000000000..4d41581027
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/minidump_file_writer.h
@@ -0,0 +1,281 @@
+// Copyright (c) 2006, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// minidump_file_writer.h: Implements file-based minidump generation. It's
+// intended to be used with the Google Breakpad open source crash handling
+// project.
+
+#ifndef CLIENT_MINIDUMP_FILE_WRITER_H__
+#define CLIENT_MINIDUMP_FILE_WRITER_H__
+
+#include <string>
+
+#include "google_breakpad/common/minidump_format.h"
+
+namespace google_breakpad {
+
+class UntypedMDRVA;
+template<typename MDType> class TypedMDRVA;
+
+// The user of this class can Open() a file and add minidump streams, data, and
+// strings using the definitions in minidump_format.h. Since this class is
+// expected to be used in a situation where the current process may be
+// damaged, it will not allocate heap memory.
+// Sample usage:
+// MinidumpFileWriter writer;
+// writer.Open("/tmp/minidump.dmp");
+// TypedMDRVA<MDRawHeader> header(&writer_);
+// header.Allocate();
+// header->get()->signature = MD_HEADER_SIGNATURE;
+// :
+// writer.Close();
+//
+// An alternative is to use SetFile and provide a file descriptor:
+// MinidumpFileWriter writer;
+// writer.SetFile(minidump_fd);
+// TypedMDRVA<MDRawHeader> header(&writer_);
+// header.Allocate();
+// header->get()->signature = MD_HEADER_SIGNATURE;
+// :
+// writer.Close();
+
+class MinidumpFileWriter {
+public:
+ // Invalid MDRVA (Minidump Relative Virtual Address)
+ // returned on failed allocation
+ static const MDRVA kInvalidMDRVA;
+
+ MinidumpFileWriter();
+ ~MinidumpFileWriter();
+
+ // Open |path| as the destination of the minidump data. If |path| already
+ // exists, then Open() will fail.
+ // Return true on success, or false on failure.
+ bool Open(const char *path);
+
+ // Sets the file descriptor |file| as the destination of the minidump data.
+ // Can be used as an alternative to Open() when a file descriptor is
+ // available.
+ // Note that |fd| is not closed when the instance of MinidumpFileWriter is
+ // destroyed.
+ void SetFile(const int file);
+
+ // Close the current file (that was either created when Open was called, or
+ // specified with SetFile).
+ // Return true on success, or false on failure.
+ bool Close();
+
+ // Copy the contents of |str| to a MDString and write it to the file.
+ // |str| is expected to be either UTF-16 or UTF-32 depending on the size
+ // of wchar_t.
+ // Maximum |length| of characters to copy from |str|, or specify 0 to use the
+ // entire NULL terminated string. Copying will stop at the first NULL.
+ // |location| the allocated location
+ // Return true on success, or false on failure
+ bool WriteString(const wchar_t *str, unsigned int length,
+ MDLocationDescriptor *location);
+
+ // Same as above, except with |str| as a UTF-8 string
+ bool WriteString(const char *str, unsigned int length,
+ MDLocationDescriptor *location);
+
+ // Write |size| bytes starting at |src| into the current position.
+ // Return true on success and set |output| to position, or false on failure
+ bool WriteMemory(const void *src, size_t size, MDMemoryDescriptor *output);
+
+ // Copies |size| bytes from |src| to |position|
+ // Return true on success, or false on failure
+ bool Copy(MDRVA position, const void *src, ssize_t size);
+
+ // Return the current position for writing to the minidump
+ inline MDRVA position() const { return position_; }
+
+ private:
+ friend class UntypedMDRVA;
+
+ // Allocates an area of |size| bytes.
+ // Returns the position of the allocation, or kInvalidMDRVA if it was
+ // unable to allocate the bytes.
+ MDRVA Allocate(size_t size);
+
+ // The file descriptor for the output file.
+ int file_;
+
+ // Whether |file_| should be closed when the instance is destroyed.
+ bool close_file_when_destroyed_;
+
+ // Current position in buffer
+ MDRVA position_;
+
+ // Current allocated size
+ size_t size_;
+
+ // Copy |length| characters from |str| to |mdstring|. These are distinct
+ // because the underlying MDString is a UTF-16 based string. The wchar_t
+ // variant may need to create a MDString that has more characters than the
+ // source |str|, whereas the UTF-8 variant may coalesce characters to form
+ // a single UTF-16 character.
+ bool CopyStringToMDString(const wchar_t *str, unsigned int length,
+ TypedMDRVA<MDString> *mdstring);
+ bool CopyStringToMDString(const char *str, unsigned int length,
+ TypedMDRVA<MDString> *mdstring);
+
+ // The common templated code for writing a string
+ template <typename CharType>
+ bool WriteStringCore(const CharType *str, unsigned int length,
+ MDLocationDescriptor *location);
+
+
+ // Calculate the number of uint16_t values required to store a wchar_t string
+ // when its converted to UTF-16.
+ static unsigned int CalculateNumOfU16s(const wchar_t *str, unsigned int length);
+
+ // Calculate the number of uint16_t values required to store a UTF-8 string
+ // when its converted to UTF-16.
+ static unsigned int CalculateNumOfU16s(const char *str, unsigned int length);
+};
+
+// Represents an untyped allocated chunk
+class UntypedMDRVA {
+ public:
+ explicit UntypedMDRVA(MinidumpFileWriter *writer)
+ : writer_(writer),
+ position_(writer->position()),
+ size_(0) {}
+
+ // Allocates |size| bytes. Must not call more than once.
+ // Return true on success, or false on failure
+ bool Allocate(size_t size);
+
+ // Returns the current position or kInvalidMDRVA if allocation failed
+ inline MDRVA position() const { return position_; }
+
+ // Number of bytes allocated
+ inline size_t size() const { return size_; }
+
+ // Return size and position
+ inline MDLocationDescriptor location() const {
+ MDLocationDescriptor location = { static_cast<uint32_t>(size_),
+ position_ };
+ return location;
+ }
+
+ // Copy |size| bytes starting at |src| into the minidump at |position|
+ // Return true on success, or false on failure
+ bool Copy(MDRVA position, const void *src, size_t size);
+
+ // Copy |size| bytes from |src| to the current position
+ inline bool Copy(const void *src, size_t size) {
+ return Copy(position_, src, size);
+ }
+
+ protected:
+ // Writer we associate with
+ MinidumpFileWriter *writer_;
+
+ // Position of the start of the data
+ MDRVA position_;
+
+ // Allocated size
+ size_t size_;
+};
+
+// Represents a Minidump object chunk. Additional memory can be allocated at
+// the end of the object as a:
+// - single allocation
+// - Array of MDType objects
+// - A MDType object followed by an array
+template<typename MDType>
+class TypedMDRVA : public UntypedMDRVA {
+ public:
+ // Constructs an unallocated MDRVA
+ explicit TypedMDRVA(MinidumpFileWriter *writer)
+ : UntypedMDRVA(writer),
+ data_(),
+ allocation_state_(UNALLOCATED) {}
+
+ inline ~TypedMDRVA() {
+ // Ensure that the data_ object is written out
+ if (allocation_state_ != ARRAY)
+ Flush();
+ }
+
+ // Address of object data_ of MDType. This is not declared const as the
+ // typical usage will be to access the underlying |data_| object as to
+ // alter its contents.
+ MDType *get() { return &data_; }
+
+ // Allocates minidump_size<MDType>::size() bytes.
+ // Must not call more than once.
+ // Return true on success, or false on failure
+ bool Allocate();
+
+ // Allocates minidump_size<MDType>::size() + |additional| bytes.
+ // Must not call more than once.
+ // Return true on success, or false on failure
+ bool Allocate(size_t additional);
+
+ // Allocate an array of |count| elements of MDType.
+ // Must not call more than once.
+ // Return true on success, or false on failure
+ bool AllocateArray(size_t count);
+
+ // Allocate an array of |count| elements of |size| after object of MDType
+ // Must not call more than once.
+ // Return true on success, or false on failure
+ bool AllocateObjectAndArray(size_t count, size_t size);
+
+ // Copy |item| to |index|
+ // Must have been allocated using AllocateArray().
+ // Return true on success, or false on failure
+ bool CopyIndex(unsigned int index, MDType *item);
+
+ // Copy |size| bytes starting at |str| to |index|
+ // Must have been allocated using AllocateObjectAndArray().
+ // Return true on success, or false on failure
+ bool CopyIndexAfterObject(unsigned int index, const void *src, size_t size);
+
+ // Write data_
+ bool Flush();
+
+ private:
+ enum AllocationState {
+ UNALLOCATED = 0,
+ SINGLE_OBJECT,
+ ARRAY,
+ SINGLE_OBJECT_WITH_ARRAY
+ };
+
+ MDType data_;
+ AllocationState allocation_state_;
+};
+
+} // namespace google_breakpad
+
+#endif // CLIENT_MINIDUMP_FILE_WRITER_H__
diff --git a/toolkit/crashreporter/breakpad-client/minidump_file_writer_unittest.cc b/toolkit/crashreporter/breakpad-client/minidump_file_writer_unittest.cc
new file mode 100644
index 0000000000..256e337127
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/minidump_file_writer_unittest.cc
@@ -0,0 +1,179 @@
+// 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.
+
+// Author: waylonis@google.com (Dan Waylonis)
+
+/*
+ g++ -I../ ../common/convert_UTF.cc \
+ ../common/string_conversion.cc \
+ minidump_file_writer.cc \
+ minidump_file_writer_unittest.cc \
+ -o minidump_file_writer_unittest
+ */
+
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "minidump_file_writer-inl.h"
+
+using google_breakpad::MinidumpFileWriter;
+
+#define ASSERT_TRUE(cond) \
+if (!(cond)) { \
+ fprintf(stderr, "FAILED: %s at %s:%d\n", #cond, __FILE__, __LINE__); \
+ return false; \
+}
+
+#define ASSERT_EQ(e1, e2) ASSERT_TRUE((e1) == (e2))
+#define ASSERT_NE(e1, e2) ASSERT_TRUE((e1) != (e2))
+
+struct StringStructure {
+ unsigned long integer_value;
+ MDLocationDescriptor first_string;
+ MDLocationDescriptor second_string;
+};
+
+struct ArrayStructure {
+ unsigned char char_value;
+ unsigned short short_value;
+ unsigned long long_value;
+};
+
+typedef struct {
+ unsigned long count;
+ ArrayStructure array[0];
+} ObjectAndArrayStructure;
+
+static bool WriteFile(const char *path) {
+ MinidumpFileWriter writer;
+ if (writer.Open(path)) {
+ // Test a single structure
+ google_breakpad::TypedMDRVA<StringStructure> strings(&writer);
+ ASSERT_TRUE(strings.Allocate());
+ strings.get()->integer_value = 0xBEEF;
+ const char *first = "First String";
+ ASSERT_TRUE(writer.WriteString(first, 0, &strings.get()->first_string));
+ const wchar_t *second = L"Second String";
+ ASSERT_TRUE(writer.WriteString(second, 0, &strings.get()->second_string));
+
+ // Test an array structure
+ google_breakpad::TypedMDRVA<ArrayStructure> array(&writer);
+ unsigned int count = 10;
+ ASSERT_TRUE(array.AllocateArray(count));
+ for (unsigned char i = 0; i < count; ++i) {
+ ArrayStructure local;
+ local.char_value = i;
+ local.short_value = i + 1;
+ local.long_value = i + 2;
+ ASSERT_TRUE(array.CopyIndex(i, &local));
+ }
+
+ // Test an object followed by an array
+ google_breakpad::TypedMDRVA<ObjectAndArrayStructure> obj_array(&writer);
+ ASSERT_TRUE(obj_array.AllocateObjectAndArray(count,
+ sizeof(ArrayStructure)));
+ obj_array.get()->count = count;
+ for (unsigned char i = 0; i < count; ++i) {
+ ArrayStructure local;
+ local.char_value = i;
+ local.short_value = i + 1;
+ local.long_value = i + 2;
+ ASSERT_TRUE(obj_array.CopyIndexAfterObject(i, &local, sizeof(local)));
+ }
+ }
+
+ return writer.Close();
+}
+
+static bool CompareFile(const char *path) {
+ unsigned long expected[] = {
+#if defined(__BIG_ENDIAN__)
+ 0x0000beef, 0x0000001e, 0x00000018, 0x00000020, 0x00000038, 0x00000000,
+ 0x00000018, 0x00460069, 0x00720073, 0x00740020, 0x00530074, 0x00720069,
+ 0x006e0067, 0x00000000, 0x0000001a, 0x00530065, 0x0063006f, 0x006e0064,
+ 0x00200053, 0x00740072, 0x0069006e, 0x00670000, 0x00000001, 0x00000002,
+ 0x01000002, 0x00000003, 0x02000003, 0x00000004, 0x03000004, 0x00000005,
+ 0x04000005, 0x00000006, 0x05000006, 0x00000007, 0x06000007, 0x00000008,
+ 0x07000008, 0x00000009, 0x08000009, 0x0000000a, 0x0900000a, 0x0000000b,
+ 0x0000000a, 0x00000001, 0x00000002, 0x01000002, 0x00000003, 0x02000003,
+ 0x00000004, 0x03000004, 0x00000005, 0x04000005, 0x00000006, 0x05000006,
+ 0x00000007, 0x06000007, 0x00000008, 0x07000008, 0x00000009, 0x08000009,
+ 0x0000000a, 0x0900000a, 0x0000000b, 0x00000000
+#else
+ 0x0000beef, 0x0000001e, 0x00000018, 0x00000020,
+ 0x00000038, 0x00000000, 0x00000018, 0x00690046,
+ 0x00730072, 0x00200074, 0x00740053, 0x00690072,
+ 0x0067006e, 0x00000000, 0x0000001a, 0x00650053,
+ 0x006f0063, 0x0064006e, 0x00530020, 0x00720074,
+ 0x006e0069, 0x00000067, 0x00011e00, 0x00000002,
+ 0x00021e01, 0x00000003, 0x00031e02, 0x00000004,
+ 0x00041e03, 0x00000005, 0x00051e04, 0x00000006,
+ 0x00061e05, 0x00000007, 0x00071e06, 0x00000008,
+ 0x00081e07, 0x00000009, 0x00091e08, 0x0000000a,
+ 0x000a1e09, 0x0000000b, 0x0000000a, 0x00011c00,
+ 0x00000002, 0x00021c01, 0x00000003, 0x00031c02,
+ 0x00000004, 0x00041c03, 0x00000005, 0x00051c04,
+ 0x00000006, 0x00061c05, 0x00000007, 0x00071c06,
+ 0x00000008, 0x00081c07, 0x00000009, 0x00091c08,
+ 0x0000000a, 0x000a1c09, 0x0000000b, 0x00000000,
+#endif
+ };
+ size_t expected_byte_count = sizeof(expected);
+ int fd = open(path, O_RDONLY, 0600);
+ void *buffer = malloc(expected_byte_count);
+ ASSERT_NE(fd, -1);
+ ASSERT_TRUE(buffer);
+ ASSERT_EQ(read(fd, buffer, expected_byte_count),
+ static_cast<ssize_t>(expected_byte_count));
+
+ char *b1, *b2;
+ b1 = reinterpret_cast<char*>(buffer);
+ b2 = reinterpret_cast<char*>(expected);
+ while (*b1 == *b2) {
+ b1++;
+ b2++;
+ }
+
+ printf("%p\n", reinterpret_cast<void*>(b1 - (char*)buffer));
+
+ ASSERT_EQ(memcmp(buffer, expected, expected_byte_count), 0);
+ return true;
+}
+
+static bool RunTests() {
+ const char *path = "/tmp/minidump_file_writer_unittest.dmp";
+ ASSERT_TRUE(WriteFile(path));
+ ASSERT_TRUE(CompareFile(path));
+ unlink(path);
+ return true;
+}
+
+extern "C" int main(int argc, const char *argv[]) {
+ return RunTests() ? 0 : 1;
+}
diff --git a/toolkit/crashreporter/breakpad-client/moz.build b/toolkit/crashreporter/breakpad-client/moz.build
new file mode 100644
index 0000000000..9ee42e4136
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/moz.build
@@ -0,0 +1,33 @@
+# -*- 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/.
+
+SOURCES += [
+ 'minidump_file_writer.cc',
+]
+
+Library('breakpad_client')
+
+USE_LIBS += [
+ 'breakpad_common_s',
+]
+
+if CONFIG['OS_ARCH'] == 'Darwin':
+ USE_LIBS += [
+ 'breakpad_mac_common_s',
+ ]
+elif CONFIG['OS_ARCH'] == 'Linux':
+ USE_LIBS += [
+ 'breakpad_linux_common_s',
+ ]
+
+FINAL_LIBRARY = 'xul'
+
+LOCAL_INCLUDES += [
+ '/toolkit/crashreporter/google-breakpad/src',
+]
+
+if CONFIG['CC_TYPE'] in ('clang', 'gcc'):
+ CXXFLAGS += ['-Wno-error=stack-protector']
diff --git a/toolkit/crashreporter/breakpad-client/windows/common/auto_critical_section.h b/toolkit/crashreporter/breakpad-client/windows/common/auto_critical_section.h
new file mode 100644
index 0000000000..3fd4b9b7e6
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/windows/common/auto_critical_section.h
@@ -0,0 +1,81 @@
+// 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.
+
+#ifndef CLIENT_WINDOWS_COMMON_AUTO_CRITICAL_SECTION_H__
+#define CLIENT_WINDOWS_COMMON_AUTO_CRITICAL_SECTION_H__
+
+#include <windows.h>
+
+namespace google_breakpad {
+
+// Automatically enters the critical section in the constructor and leaves
+// the critical section in the destructor.
+class AutoCriticalSection {
+ public:
+ // Creates a new instance with the given critical section object
+ // and enters the critical section immediately.
+ explicit AutoCriticalSection(CRITICAL_SECTION* cs) : cs_(cs), taken_(false) {
+ assert(cs_);
+ Acquire();
+ }
+
+ // Destructor: leaves the critical section.
+ ~AutoCriticalSection() {
+ if (taken_) {
+ Release();
+ }
+ }
+
+ // Enters the critical section. Recursive Acquire() calls are not allowed.
+ void Acquire() {
+ assert(!taken_);
+ EnterCriticalSection(cs_);
+ taken_ = true;
+ }
+
+ // Leaves the critical section. The caller should not call Release() unless
+ // the critical seciton has been entered already.
+ void Release() {
+ assert(taken_);
+ taken_ = false;
+ LeaveCriticalSection(cs_);
+ }
+
+ private:
+ // Disable copy ctor and operator=.
+ AutoCriticalSection(const AutoCriticalSection&);
+ AutoCriticalSection& operator=(const AutoCriticalSection&);
+
+ CRITICAL_SECTION* cs_;
+ bool taken_;
+};
+
+} // namespace google_breakpad
+
+#endif // CLIENT_WINDOWS_COMMON_AUTO_CRITICAL_SECTION_H__
diff --git a/toolkit/crashreporter/breakpad-client/windows/common/ipc_protocol.h b/toolkit/crashreporter/breakpad-client/windows/common/ipc_protocol.h
new file mode 100644
index 0000000000..c74868198c
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/windows/common/ipc_protocol.h
@@ -0,0 +1,181 @@
+// 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.
+
+#ifndef CLIENT_WINDOWS_COMMON_IPC_PROTOCOL_H__
+#define CLIENT_WINDOWS_COMMON_IPC_PROTOCOL_H__
+
+#include <windows.h>
+#include <dbghelp.h>
+#include <string>
+#include <utility>
+#include "common/windows/string_utils-inl.h"
+#include "google_breakpad/common/minidump_format.h"
+
+namespace google_breakpad {
+
+// Name/value pair for custom client information.
+struct CustomInfoEntry {
+ // Maximum length for name and value for client custom info.
+ static const int kNameMaxLength = 64;
+ static const int kValueMaxLength = 64;
+
+ CustomInfoEntry() {
+ // Putting name and value in initializer list makes VC++ show warning 4351.
+ set_name(NULL);
+ set_value(NULL);
+ }
+
+ CustomInfoEntry(const wchar_t* name_arg, const wchar_t* value_arg) {
+ set_name(name_arg);
+ set_value(value_arg);
+ }
+
+ void set_name(const wchar_t* name_arg) {
+ if (!name_arg) {
+ name[0] = L'\0';
+ return;
+ }
+ WindowsStringUtils::safe_wcscpy(name, kNameMaxLength, name_arg);
+ }
+
+ void set_value(const wchar_t* value_arg) {
+ if (!value_arg) {
+ value[0] = L'\0';
+ return;
+ }
+
+ WindowsStringUtils::safe_wcscpy(value, kValueMaxLength, value_arg);
+ }
+
+ void set(const wchar_t* name_arg, const wchar_t* value_arg) {
+ set_name(name_arg);
+ set_value(value_arg);
+ }
+
+ wchar_t name[kNameMaxLength];
+ wchar_t value[kValueMaxLength];
+};
+
+// Constants for the protocol between client and the server.
+
+// Tags sent with each message indicating the purpose of
+// the message.
+enum MessageTag {
+ MESSAGE_TAG_NONE = 0,
+ MESSAGE_TAG_REGISTRATION_REQUEST = 1,
+ MESSAGE_TAG_REGISTRATION_RESPONSE = 2,
+ MESSAGE_TAG_REGISTRATION_ACK = 3,
+ MESSAGE_TAG_UPLOAD_REQUEST = 4
+};
+
+struct CustomClientInfo {
+ const CustomInfoEntry* entries;
+ size_t count;
+};
+
+// Message structure for IPC between crash client and crash server.
+struct ProtocolMessage {
+ ProtocolMessage()
+ : tag(MESSAGE_TAG_NONE),
+ id(0),
+ dump_type(MiniDumpNormal),
+ thread_id(0),
+ exception_pointers(NULL),
+ assert_info(NULL),
+ custom_client_info(),
+ dump_request_handle(NULL),
+ dump_generated_handle(NULL),
+ server_alive_handle(NULL) {
+ }
+
+ // Creates an instance with the given parameters.
+ ProtocolMessage(MessageTag arg_tag,
+ DWORD arg_id,
+ MINIDUMP_TYPE arg_dump_type,
+ DWORD* arg_thread_id,
+ EXCEPTION_POINTERS** arg_exception_pointers,
+ MDRawAssertionInfo* arg_assert_info,
+ const CustomClientInfo& custom_info,
+ HANDLE arg_dump_request_handle,
+ HANDLE arg_dump_generated_handle,
+ HANDLE arg_server_alive)
+ : tag(arg_tag),
+ id(arg_id),
+ dump_type(arg_dump_type),
+ thread_id(arg_thread_id),
+ exception_pointers(arg_exception_pointers),
+ assert_info(arg_assert_info),
+ custom_client_info(custom_info),
+ dump_request_handle(arg_dump_request_handle),
+ dump_generated_handle(arg_dump_generated_handle),
+ server_alive_handle(arg_server_alive) {
+ }
+
+ // Tag in the message.
+ MessageTag tag;
+
+ // The id for this message. This may be either a process id or a crash id
+ // depending on the type of message.
+ DWORD id;
+
+ // Dump type requested.
+ MINIDUMP_TYPE dump_type;
+
+ // Client thread id pointer.
+ DWORD* thread_id;
+
+ // Exception information.
+ EXCEPTION_POINTERS** exception_pointers;
+
+ // Assert information in case of an invalid parameter or
+ // pure call failure.
+ MDRawAssertionInfo* assert_info;
+
+ // Custom client information.
+ CustomClientInfo custom_client_info;
+
+ // Handle to signal the crash event.
+ HANDLE dump_request_handle;
+
+ // Handle to check if server is done generating crash.
+ HANDLE dump_generated_handle;
+
+ // Handle to a mutex that becomes signaled (WAIT_ABANDONED)
+ // if server process goes down.
+ HANDLE server_alive_handle;
+
+ private:
+ // Disable copy ctor and operator=.
+ ProtocolMessage(const ProtocolMessage& msg);
+ ProtocolMessage& operator=(const ProtocolMessage& msg);
+};
+
+} // namespace google_breakpad
+
+#endif // CLIENT_WINDOWS_COMMON_IPC_PROTOCOL_H__
diff --git a/toolkit/crashreporter/breakpad-client/windows/common/minidump_callback.cc b/toolkit/crashreporter/breakpad-client/windows/common/minidump_callback.cc
new file mode 100644
index 0000000000..54d8e25274
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/windows/common/minidump_callback.cc
@@ -0,0 +1,319 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* 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 "minidump_callback.h"
+
+#include <winternl.h>
+
+#include <algorithm>
+#include <cassert>
+
+namespace google_breakpad {
+
+static const DWORD sHeapRegionSize= 1024;
+static DWORD sPageSize = 0;
+
+using NtQueryInformationThreadFunc = decltype(::NtQueryInformationThread);
+static NtQueryInformationThreadFunc* sNtQueryInformationThread = nullptr;
+
+
+namespace {
+enum {
+ ThreadBasicInformation,
+};
+
+struct CLIENT_ID {
+ PVOID UniqueProcess;
+ PVOID UniqueThread;
+};
+
+struct THREAD_BASIC_INFORMATION {
+ NTSTATUS ExitStatus;
+ PVOID TebBaseAddress;
+ CLIENT_ID ClientId;
+ KAFFINITY AffMask;
+ DWORD Priority;
+ DWORD BasePriority;
+};
+}
+
+void InitAppMemoryInternal()
+{
+ if (!sPageSize) {
+ SYSTEM_INFO systemInfo;
+ GetSystemInfo(&systemInfo);
+ sPageSize = systemInfo.dwPageSize;
+ }
+
+ if (!sNtQueryInformationThread) {
+ sNtQueryInformationThread = (NtQueryInformationThreadFunc*)
+ (::GetProcAddress(::GetModuleHandleW(L"ntdll.dll"),
+ "NtQueryInformationThread"));
+ }
+}
+
+bool GetAppMemoryFromRegister(HANDLE aProcess,
+ const NT_TIB* aTib,
+ RegisterValueType aRegister,
+ AppMemory* aResult)
+{
+ static_assert(sizeof(RegisterValueType) == sizeof(void*),
+ "Size mismatch between DWORD/DWORD64 and void*");
+
+ if (!sPageSize) {
+ // GetSystemInfo() should not fail, but bail out just in case it fails.
+ return false;
+ }
+
+ RegisterValueType addr = aRegister;
+ addr &= ~(static_cast<RegisterValueType>(sPageSize) - 1);
+
+ if (aTib) {
+ if (aRegister >= (RegisterValueType)aTib->StackLimit &&
+ aRegister <= (RegisterValueType)aTib->StackBase) {
+ // aRegister points to the stack.
+ return false;
+ }
+ }
+
+ MEMORY_BASIC_INFORMATION memInfo;
+ memset(&memInfo, 0, sizeof(memInfo));
+ SIZE_T rv = ::VirtualQueryEx(aProcess,
+ reinterpret_cast<void*>(addr),
+ &memInfo,
+ sizeof(memInfo));
+ if (!rv) {
+ // VirtualQuery fails: aAddr is not on heap.
+ return false;
+ }
+
+ // Check protection and type of the memory region. Include the region if it's
+ // 1. read-write: heap, or
+ // 2. read-executable and private: likely to be JIT code.
+ if (memInfo.Protect != PAGE_READWRITE &&
+ memInfo.Protect != PAGE_EXECUTE_READ) {
+ return false;
+ }
+
+ // Try to include a region of size sHeapRegionSize around aRegister, bounded
+ // by the [BaseAddress, BaseAddress + RegionSize].
+ RegisterValueType lower =
+ std::max(aRegister - sHeapRegionSize / 2,
+ reinterpret_cast<RegisterValueType>(memInfo.BaseAddress));
+
+ RegisterValueType upper =
+ std::min(lower + sHeapRegionSize,
+ reinterpret_cast<RegisterValueType>(memInfo.BaseAddress) +
+ memInfo.RegionSize);
+
+ aResult->ptr = lower;
+ aResult->length = upper - lower;
+
+ return true;
+}
+
+static AppMemoryList::iterator
+FindNextPreallocated(AppMemoryList& aList, AppMemoryList::iterator aBegin) {
+ auto it = aBegin;
+ for (auto it = aBegin; it != aList.end(); it++) {
+ if (it->preallocated) {
+ return it;
+ }
+ }
+
+ assert(it == aList.end());
+ return it;
+}
+
+static bool
+GetThreadTib(HANDLE aProcess, DWORD aThreadId, NT_TIB* aTib) {
+ HANDLE threadHandle = ::OpenThread(THREAD_QUERY_INFORMATION,
+ FALSE,
+ aThreadId);
+ if (!threadHandle) {
+ return false;
+ }
+
+ if (!sNtQueryInformationThread) {
+ return false;
+ }
+
+ THREAD_BASIC_INFORMATION threadInfo;
+ auto status = (*sNtQueryInformationThread)(threadHandle,
+ (THREADINFOCLASS)ThreadBasicInformation,
+ &threadInfo,
+ sizeof(threadInfo),
+ NULL);
+ if (!NT_SUCCESS(status)) {
+ return false;
+ }
+
+ auto readSuccess = ::ReadProcessMemory(aProcess,
+ threadInfo.TebBaseAddress,
+ aTib,
+ sizeof(*aTib),
+ NULL);
+ if (!readSuccess) {
+ return false;
+ }
+
+ ::CloseHandle(threadHandle);
+ return true;
+}
+
+void IncludeAppMemoryFromExceptionContext(HANDLE aProcess,
+ DWORD aThreadId,
+ AppMemoryList& aList,
+ PCONTEXT aExceptionContext,
+ bool aInstructionPointerOnly) {
+ RegisterValueType heapAddrCandidates[kExceptionAppMemoryRegions];
+ size_t numElements = 0;
+
+ NT_TIB tib;
+ memset(&tib, 0, sizeof(tib));
+ if (!GetThreadTib(aProcess, aThreadId, &tib)) {
+ // Fail to query thread stack range: only safe to include the region around
+ // the instruction pointer.
+ aInstructionPointerOnly = true;
+ }
+
+ // Add registers that might have a heap address to heapAddrCandidates.
+ // Note that older versions of DbgHelp.dll don't correctly put the memory
+ // around the faulting instruction pointer into the minidump. Include Rip/Eip
+ // unconditionally ensures it gets included.
+#if defined(_M_IX86)
+ if (!aInstructionPointerOnly) {
+ heapAddrCandidates[numElements++] = aExceptionContext->Eax;
+ heapAddrCandidates[numElements++] = aExceptionContext->Ebx;
+ heapAddrCandidates[numElements++] = aExceptionContext->Ecx;
+ heapAddrCandidates[numElements++] = aExceptionContext->Edx;
+ heapAddrCandidates[numElements++] = aExceptionContext->Esi;
+ heapAddrCandidates[numElements++] = aExceptionContext->Edi;
+ }
+ heapAddrCandidates[numElements++] = aExceptionContext->Eip;
+#elif defined(_M_AMD64)
+ if (!aInstructionPointerOnly) {
+ heapAddrCandidates[numElements++] = aExceptionContext->Rax;
+ heapAddrCandidates[numElements++] = aExceptionContext->Rbx;
+ heapAddrCandidates[numElements++] = aExceptionContext->Rcx;
+ heapAddrCandidates[numElements++] = aExceptionContext->Rdx;
+ heapAddrCandidates[numElements++] = aExceptionContext->Rsi;
+ heapAddrCandidates[numElements++] = aExceptionContext->Rdi;
+ heapAddrCandidates[numElements++] = aExceptionContext->R8;
+ heapAddrCandidates[numElements++] = aExceptionContext->R9;
+ heapAddrCandidates[numElements++] = aExceptionContext->R10;
+ heapAddrCandidates[numElements++] = aExceptionContext->R11;
+ heapAddrCandidates[numElements++] = aExceptionContext->R12;
+ heapAddrCandidates[numElements++] = aExceptionContext->R13;
+ heapAddrCandidates[numElements++] = aExceptionContext->R14;
+ heapAddrCandidates[numElements++] = aExceptionContext->R15;
+ }
+ heapAddrCandidates[numElements++] = aExceptionContext->Rip;
+#elif defined(_M_ARM64)
+ if (!aInstructionPointerOnly) {
+ for (auto reg : aExceptionContext->X) {
+ heapAddrCandidates[numElements++] = reg;
+ }
+ heapAddrCandidates[numElements++] = aExceptionContext->Sp;
+ }
+ heapAddrCandidates[numElements++] = aExceptionContext->Pc;
+#endif
+
+ // Inplace sort the candidates for excluding or merging memory regions.
+ auto begin = &heapAddrCandidates[0], end = &heapAddrCandidates[numElements];
+ std::make_heap(begin, end);
+ std::sort_heap(begin, end);
+
+ auto appMemory = FindNextPreallocated(aList, aList.begin());
+ for (size_t i = 0; i < numElements; i++) {
+ if (appMemory == aList.end()) {
+ break;
+ }
+
+ AppMemory tmp{};
+ if (!GetAppMemoryFromRegister(aProcess,
+ aInstructionPointerOnly ? nullptr : &tib,
+ heapAddrCandidates[i],
+ &tmp)) {
+ continue;
+ }
+
+ if (!(tmp.ptr && tmp.length)) {
+ // Something unexpected happens. Skip this candidate.
+ continue;
+ }
+
+ if (!appMemory->ptr) {
+ *appMemory = tmp;
+ continue;
+ }
+
+ if (appMemory->ptr + appMemory->length > tmp.ptr) {
+ // The beginning of the next region fall within the range of the previous
+ // region: merge into one. Note that we don't merge adjacent regions like
+ // [0, 99] and [100, 199] in case we cross the border of memory allocation
+ // regions.
+ appMemory->length = tmp.ptr + tmp.length - appMemory->ptr;
+ continue;
+ }
+
+ appMemory = FindNextPreallocated(aList, ++appMemory);
+ if (appMemory == aList.end()) {
+ break;
+ }
+
+ *appMemory = tmp;
+ }
+}
+
+BOOL CALLBACK MinidumpWriteDumpCallback(
+ PVOID context,
+ const PMINIDUMP_CALLBACK_INPUT callback_input,
+ PMINIDUMP_CALLBACK_OUTPUT callback_output) {
+ switch (callback_input->CallbackType) {
+ case MemoryCallback: {
+ MinidumpCallbackContext* callback_context =
+ reinterpret_cast<MinidumpCallbackContext*>(context);
+
+ // Skip unused preallocated AppMemory elements.
+ while (callback_context->iter != callback_context->end &&
+ callback_context->iter->preallocated &&
+ !callback_context->iter->ptr) {
+ callback_context->iter++;
+ }
+
+ if (callback_context->iter == callback_context->end)
+ return FALSE;
+
+ // Include the specified memory region.
+ callback_output->MemoryBase = callback_context->iter->ptr;
+ callback_output->MemorySize = callback_context->iter->length;
+ callback_context->iter++;
+ return TRUE;
+ }
+
+ // Include all modules.
+ case IncludeModuleCallback:
+ case ModuleCallback:
+ return TRUE;
+
+ // Include all threads.
+ case IncludeThreadCallback:
+ case ThreadCallback:
+ return TRUE;
+
+ // Stop receiving cancel callbacks.
+ case CancelCallback:
+ callback_output->CheckCancel = FALSE;
+ callback_output->Cancel = FALSE;
+ return TRUE;
+ }
+ // Ignore other callback types.
+ return FALSE;
+}
+
+} // namespace google_breakpad
+
diff --git a/toolkit/crashreporter/breakpad-client/windows/common/minidump_callback.h b/toolkit/crashreporter/breakpad-client/windows/common/minidump_callback.h
new file mode 100644
index 0000000000..1306235cfd
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/windows/common/minidump_callback.h
@@ -0,0 +1,78 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* 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/. */
+
+#ifndef MINIDUMP_CALLBACK_H__
+#define MINIDUMP_CALLBACK_H__
+
+#include <windows.h>
+#include <dbghelp.h>
+
+#include <list>
+
+namespace google_breakpad {
+
+// These entries store a list of memory regions that the client wants included
+// in the minidump.
+struct AppMemory {
+ ULONG64 ptr;
+ ULONG length;
+ bool preallocated;
+
+ bool operator==(const struct AppMemory& other) const {
+ return ptr == other.ptr;
+ }
+
+ bool operator==(const void* other) const {
+ return ptr == reinterpret_cast<ULONG64>(other);
+ }
+
+ AppMemory()
+ : ptr(0)
+ , length(0)
+ , preallocated(false)
+ {}
+
+ AppMemory& operator=(const AppMemory& other) = default;
+};
+typedef std::list<AppMemory> AppMemoryList;
+
+// This is passed as the context to the MinidumpWriteDump callback.
+typedef struct {
+ AppMemoryList::const_iterator iter;
+ AppMemoryList::const_iterator end;
+} MinidumpCallbackContext;
+
+static const size_t kExceptionAppMemoryRegions = 33;
+
+#if defined(_M_IX86)
+using RegisterValueType = DWORD;
+#elif defined(_M_AMD64) || defined(_M_ARM64)
+using RegisterValueType = DWORD64;
+#else
+#error Unsupported platform
+#endif
+
+void IncludeAppMemoryFromExceptionContext(HANDLE aProcess,
+ DWORD aThreadId,
+ AppMemoryList& aList,
+ PCONTEXT aExceptionContext,
+ bool aInsttructionPointerOnly);
+
+// This function is used as a callback when calling MinidumpWriteDump,
+// in order to add additional memory regions to the dump.
+BOOL CALLBACK MinidumpWriteDumpCallback(
+ PVOID context,
+ const PMINIDUMP_CALLBACK_INPUT callback_input,
+ PMINIDUMP_CALLBACK_OUTPUT callback_output);
+
+// Called during startup to initialize system information used by
+// IncludeAppMemoryFromExceptionContext().
+void InitAppMemoryInternal();
+
+} // namespace google_breakpad
+
+#endif
+
diff --git a/toolkit/crashreporter/breakpad-client/windows/common/objs.mozbuild b/toolkit/crashreporter/breakpad-client/windows/common/objs.mozbuild
new file mode 100644
index 0000000000..ddc1d58d56
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/windows/common/objs.mozbuild
@@ -0,0 +1,14 @@
+# -*- 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_client_common = [
+ 'minidump_callback.cc',
+]
+
+subdir = 'toolkit/crashreporter/breakpad-client/windows/common'
+objs_client_common = [
+ '/%s/%s' % (subdir, s) for s in lobjs_client_common
+]
diff --git a/toolkit/crashreporter/breakpad-client/windows/crash_generation/ReadMe.txt b/toolkit/crashreporter/breakpad-client/windows/crash_generation/ReadMe.txt
new file mode 100644
index 0000000000..b54d0e11b7
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/windows/crash_generation/ReadMe.txt
@@ -0,0 +1,58 @@
+=========================================================================
+ State machine transitions for the Crash Generation Server
+=========================================================================
+
+=========================================================================
+ |
+ STATE | ACTIONS
+ |
+=========================================================================
+ ERROR | Clean up resources used to serve clients.
+ | Always remain in ERROR state.
+-------------------------------------------------------------------------
+ INITIAL | Connect to the pipe asynchronously.
+ | If connection is successfully queued up asynchronously,
+ | go into CONNECTING state.
+ | If connection is done synchronously, go into CONNECTED
+ | state.
+ | For any unexpected problems, go into ERROR state.
+-------------------------------------------------------------------------
+ CONNECTING | Get the result of async connection request.
+ | If I/O is still incomplete, remain in the CONNECTING
+ | state.
+ | If connection is complete, go into CONNECTED state.
+ | For any unexpected problems, go into DISCONNECTING state.
+-------------------------------------------------------------------------
+ CONNECTED | Read from the pipe asynchronously.
+ | If read request is successfully queued up asynchronously,
+ | go into READING state.
+ | For any unexpected problems, go into DISCONNECTING state.
+-------------------------------------------------------------------------
+ READING | Get the result of async read request.
+ | If read is done, go into READ_DONE state.
+ | For any unexpected problems, go into DISCONNECTING state.
+-------------------------------------------------------------------------
+ READ_DONE | Register the client, prepare the reply and write the
+ | reply to the pipe asynchronously.
+ | If write request is successfully queued up asynchronously,
+ | go into WRITING state.
+ | For any unexpected problems, go into DISCONNECTING state.
+-------------------------------------------------------------------------
+ WRITING | Get the result of the async write request.
+ | If write is done, go into WRITE_DONE state.
+ | For any unexpected problems, go into DISCONNECTING state.
+-------------------------------------------------------------------------
+ WRITE_DONE | Read from the pipe asynchronously (for an ACK).
+ | If read request is successfully queued up asynchonously,
+ | go into READING_ACK state.
+ | For any unexpected problems, go into DISCONNECTING state.
+-------------------------------------------------------------------------
+ READING_ACK | Get the result of the async read request.
+ | If read is done, perform action for successful client
+ | connection.
+ | Go into DISCONNECTING state.
+-------------------------------------------------------------------------
+ DISCONNECTING | Disconnect from the pipe, reset the event and go into
+ | INITIAL state and signal the event again. If anything
+ | fails, go into ERROR state.
+=========================================================================
diff --git a/toolkit/crashreporter/breakpad-client/windows/crash_generation/client_info.cc b/toolkit/crashreporter/breakpad-client/windows/crash_generation/client_info.cc
new file mode 100644
index 0000000000..5e443241c1
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/windows/crash_generation/client_info.cc
@@ -0,0 +1,258 @@
+// 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 <cassert>
+
+#include "windows/crash_generation/client_info.h"
+#include "windows/common/ipc_protocol.h"
+
+static const wchar_t kCustomInfoProcessUptimeName[] = L"ptime";
+static const size_t kMaxCustomInfoEntries = 4096;
+
+namespace google_breakpad {
+
+ClientInfo::ClientInfo(CrashGenerationServer* crash_server,
+ DWORD pid,
+ MINIDUMP_TYPE dump_type,
+ DWORD* thread_id,
+ EXCEPTION_POINTERS** ex_info,
+ MDRawAssertionInfo* assert_info,
+ const CustomClientInfo& custom_client_info)
+ : crash_server_(crash_server),
+ pid_(pid),
+ dump_type_(dump_type),
+ ex_info_(ex_info),
+ assert_info_(assert_info),
+ custom_client_info_(custom_client_info),
+ thread_id_(thread_id),
+ process_handle_(NULL),
+ dump_requested_handle_(NULL),
+ dump_generated_handle_(NULL),
+ dump_request_wait_handle_(NULL),
+ process_exit_wait_handle_(NULL),
+ crash_id_(NULL) {
+ GetSystemTimeAsFileTime(&start_time_);
+}
+
+bool ClientInfo::Initialize() {
+ process_handle_ = OpenProcess(GENERIC_ALL, FALSE, pid_);
+ if (!process_handle_) {
+ return false;
+ }
+
+ // The crash_id will be the low order word of the process creation time.
+ FILETIME creation_time, exit_time, kernel_time, user_time;
+ if (GetProcessTimes(process_handle_, &creation_time, &exit_time,
+ &kernel_time, &user_time)) {
+ start_time_ = creation_time;
+ }
+ crash_id_ = start_time_.dwLowDateTime;
+
+ dump_requested_handle_ = CreateEvent(NULL, // Security attributes.
+ TRUE, // Manual reset.
+ FALSE, // Initial state.
+ NULL); // Name.
+ if (!dump_requested_handle_) {
+ return false;
+ }
+
+ dump_generated_handle_ = CreateEvent(NULL, // Security attributes.
+ TRUE, // Manual reset.
+ FALSE, // Initial state.
+ NULL); // Name.
+ return dump_generated_handle_ != NULL;
+}
+
+void ClientInfo::UnregisterDumpRequestWaitAndBlockUntilNoPending() {
+ if (dump_request_wait_handle_) {
+ // Wait for callbacks that might already be running to finish.
+ UnregisterWaitEx(dump_request_wait_handle_, INVALID_HANDLE_VALUE);
+ dump_request_wait_handle_ = NULL;
+ }
+}
+
+void ClientInfo::UnregisterProcessExitWait(bool block_until_no_pending) {
+ if (process_exit_wait_handle_) {
+ if (block_until_no_pending) {
+ // Wait for the callback that might already be running to finish.
+ UnregisterWaitEx(process_exit_wait_handle_, INVALID_HANDLE_VALUE);
+ } else {
+ UnregisterWait(process_exit_wait_handle_);
+ }
+ process_exit_wait_handle_ = NULL;
+ }
+}
+
+ClientInfo::~ClientInfo() {
+ // Waiting for the callback to finish here is safe because ClientInfo's are
+ // never destroyed from the dump request handling callback.
+ UnregisterDumpRequestWaitAndBlockUntilNoPending();
+
+ // This is a little tricky because ClientInfo's may be destroyed by the same
+ // callback (OnClientEnd) and waiting for it to finish will cause a deadlock.
+ // Regardless of this complication, wait for any running callbacks to finish
+ // so that the common case is properly handled. In order to avoid deadlocks,
+ // the OnClientEnd callback must call UnregisterProcessExitWait(false)
+ // before deleting the ClientInfo.
+ UnregisterProcessExitWait(true);
+
+ if (process_handle_) {
+ CloseHandle(process_handle_);
+ }
+
+ if (dump_requested_handle_) {
+ CloseHandle(dump_requested_handle_);
+ }
+
+ if (dump_generated_handle_) {
+ CloseHandle(dump_generated_handle_);
+ }
+}
+
+bool ClientInfo::GetClientExceptionInfo(EXCEPTION_POINTERS** ex_info_ptr) const {
+ SIZE_T bytes_count = 0;
+
+ static_assert(sizeof(*ex_info_ptr) == sizeof(void*),
+ "Expected to read sizeof(void*) bytes.");
+ if (!ReadProcessMemory(process_handle_,
+ ex_info_,
+ ex_info_ptr,
+ sizeof(*ex_info_ptr),
+ &bytes_count)) {
+ return false;
+ }
+
+ return bytes_count == sizeof(*ex_info_ptr);
+}
+
+bool ClientInfo::PopulateClientExceptionContext(EXCEPTION_POINTERS* ex_info_ptr,
+ CONTEXT* out_context) const {
+ SIZE_T bytes_count = 0;
+
+ EXCEPTION_POINTERS ex_info;
+ if (!ReadProcessMemory(process_handle_,
+ ex_info_ptr,
+ &ex_info,
+ sizeof(ex_info),
+ &bytes_count)) {
+ return false;
+ }
+
+ if (bytes_count != sizeof(ex_info)) {
+ return false;
+ }
+
+ static_assert(sizeof(*out_context) == sizeof(CONTEXT),
+ "Expected to read sizeof(CONTEXT) bytes.");
+ if (!ReadProcessMemory(process_handle_,
+ ex_info.ContextRecord,
+ out_context,
+ sizeof(*out_context),
+ &bytes_count)) {
+ return false;
+ }
+
+ return bytes_count == sizeof(*out_context);
+}
+
+bool ClientInfo::GetClientThreadId(DWORD* thread_id) const {
+ SIZE_T bytes_count = 0;
+ if (!ReadProcessMemory(process_handle_,
+ thread_id_,
+ thread_id,
+ sizeof(*thread_id),
+ &bytes_count)) {
+ return false;
+ }
+
+ return bytes_count == sizeof(*thread_id);
+}
+
+void ClientInfo::SetProcessUptime() {
+ FILETIME now = {0};
+ GetSystemTimeAsFileTime(&now);
+
+ ULARGE_INTEGER time_start;
+ time_start.HighPart = start_time_.dwHighDateTime;
+ time_start.LowPart = start_time_.dwLowDateTime;
+
+ ULARGE_INTEGER time_now;
+ time_now.HighPart = now.dwHighDateTime;
+ time_now.LowPart = now.dwLowDateTime;
+
+ // Calculate the delay and convert it from 100-nanoseconds to milliseconds.
+ __int64 delay = (time_now.QuadPart - time_start.QuadPart) / 10 / 1000;
+
+ // Convert it to a string.
+ wchar_t* value = custom_info_entries_.get()[custom_client_info_.count].value;
+ _i64tow_s(delay, value, CustomInfoEntry::kValueMaxLength, 10);
+}
+
+bool ClientInfo::PopulateCustomInfo() {
+ if (custom_client_info_.count > kMaxCustomInfoEntries)
+ return false;
+
+ SIZE_T bytes_count = 0;
+ SIZE_T read_count = sizeof(CustomInfoEntry) * custom_client_info_.count;
+
+ // If the scoped array for custom info already has an array, it will be
+ // the same size as what we need. This is because the number of custom info
+ // entries is always the same. So allocate memory only if scoped array has
+ // a NULL pointer.
+ if (!custom_info_entries_.get()) {
+ // Allocate an extra entry for reporting uptime for the client process.
+ custom_info_entries_.reset(
+ new CustomInfoEntry[custom_client_info_.count + 1]);
+ // Use the last element in the array for uptime.
+ custom_info_entries_.get()[custom_client_info_.count].set_name(
+ kCustomInfoProcessUptimeName);
+ }
+
+ if (!ReadProcessMemory(process_handle_,
+ custom_client_info_.entries,
+ custom_info_entries_.get(),
+ read_count,
+ &bytes_count)) {
+ return false;
+ }
+
+ SetProcessUptime();
+ return (bytes_count == read_count);
+}
+
+CustomClientInfo ClientInfo::GetCustomInfo() const {
+ CustomClientInfo custom_info;
+ custom_info.entries = custom_info_entries_.get();
+ // Add 1 to the count from the client process to account for extra entry for
+ // process uptime.
+ custom_info.count = custom_client_info_.count + 1;
+ return custom_info;
+}
+
+} // namespace google_breakpad
diff --git a/toolkit/crashreporter/breakpad-client/windows/crash_generation/client_info.h b/toolkit/crashreporter/breakpad-client/windows/crash_generation/client_info.h
new file mode 100644
index 0000000000..506099dcdc
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/windows/crash_generation/client_info.h
@@ -0,0 +1,182 @@
+// 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.
+
+#ifndef CLIENT_WINDOWS_CRASH_GENERATION_CLIENT_INFO_H__
+#define CLIENT_WINDOWS_CRASH_GENERATION_CLIENT_INFO_H__
+
+#include <windows.h>
+#include <dbghelp.h>
+#include "windows/common/ipc_protocol.h"
+#include "common/scoped_ptr.h"
+#include "google_breakpad/common/minidump_format.h"
+
+namespace google_breakpad {
+
+class CrashGenerationServer;
+
+// Abstraction for a crash client process.
+class ClientInfo {
+ public:
+ // Creates an instance with the given values. Gets the process
+ // handle for the given process id and creates necessary event
+ // objects.
+ ClientInfo(CrashGenerationServer* crash_server,
+ DWORD pid,
+ MINIDUMP_TYPE dump_type,
+ DWORD* thread_id,
+ EXCEPTION_POINTERS** ex_info,
+ MDRawAssertionInfo* assert_info,
+ const CustomClientInfo& custom_client_info);
+
+ ~ClientInfo();
+
+ CrashGenerationServer* crash_server() const { return crash_server_; }
+ DWORD pid() const { return pid_; }
+ MINIDUMP_TYPE dump_type() const { return dump_type_; }
+ EXCEPTION_POINTERS** ex_info() const { return ex_info_; }
+ MDRawAssertionInfo* assert_info() const { return assert_info_; }
+ DWORD* thread_id() const { return thread_id_; }
+ HANDLE process_handle() const { return process_handle_; }
+ HANDLE dump_requested_handle() const { return dump_requested_handle_; }
+ HANDLE dump_generated_handle() const { return dump_generated_handle_; }
+ DWORD crash_id() const { return crash_id_; }
+ const CustomClientInfo& custom_client_info() const {
+ return custom_client_info_;
+ }
+
+ void set_dump_request_wait_handle(HANDLE value) {
+ dump_request_wait_handle_ = value;
+ }
+
+ void set_process_exit_wait_handle(HANDLE value) {
+ process_exit_wait_handle_ = value;
+ }
+
+ // Unregister the dump request wait operation and wait for all callbacks
+ // that might already be running to complete before returning.
+ void UnregisterDumpRequestWaitAndBlockUntilNoPending();
+
+ // Unregister the process exit wait operation. If block_until_no_pending is
+ // true, wait for all callbacks that might already be running to complete
+ // before returning.
+ void UnregisterProcessExitWait(bool block_until_no_pending);
+
+ bool Initialize();
+ bool GetClientExceptionInfo(EXCEPTION_POINTERS** ex_info_ptr) const;
+
+ // Reads the content of exception CONTEXT from the client process.
+ bool PopulateClientExceptionContext(EXCEPTION_POINTERS* ex_info,
+ CONTEXT* out_context) const;
+
+ bool GetClientThreadId(DWORD* thread_id) const;
+
+ // Reads the custom information from the client process address space.
+ bool PopulateCustomInfo();
+
+ // Returns the client custom information.
+ CustomClientInfo GetCustomInfo() const;
+
+ private:
+ // Calcualtes the uptime for the client process, converts it to a string and
+ // stores it in the last entry of client custom info.
+ void SetProcessUptime();
+
+ // Crash generation server.
+ CrashGenerationServer* crash_server_;
+
+ // Client process ID.
+ DWORD pid_;
+
+ // Dump type requested by the client.
+ MINIDUMP_TYPE dump_type_;
+
+ // Address of an EXCEPTION_POINTERS* variable in the client
+ // process address space that will point to an instance of
+ // EXCEPTION_POINTERS containing information about crash.
+ //
+ // WARNING: Do not dereference these pointers as they are pointers
+ // in the address space of another process.
+ EXCEPTION_POINTERS** ex_info_;
+
+ // Address of an instance of MDRawAssertionInfo in the client
+ // process address space that will contain information about
+ // non-exception related crashes like invalid parameter assertion
+ // failures and pure calls.
+ //
+ // WARNING: Do not dereference these pointers as they are pointers
+ // in the address space of another process.
+ MDRawAssertionInfo* assert_info_;
+
+ // Custom information about the client.
+ CustomClientInfo custom_client_info_;
+
+ // Contains the custom client info entries read from the client process
+ // memory. This will be populated only if the method GetClientCustomInfo
+ // is called.
+ scoped_array<CustomInfoEntry> custom_info_entries_;
+
+ // Address of a variable in the client process address space that
+ // will contain the thread id of the crashing client thread.
+ //
+ // WARNING: Do not dereference these pointers as they are pointers
+ // in the address space of another process.
+ DWORD* thread_id_;
+
+ // Client process handle.
+ HANDLE process_handle_;
+
+ // Dump request event handle.
+ HANDLE dump_requested_handle_;
+
+ // Dump generated event handle.
+ HANDLE dump_generated_handle_;
+
+ // Wait handle for dump request event.
+ HANDLE dump_request_wait_handle_;
+
+ // Wait handle for process exit event.
+ HANDLE process_exit_wait_handle_;
+
+ // Time when the client process started. It is used to determine the uptime
+ // for the client process when it signals a crash.
+ FILETIME start_time_;
+
+ // The crash id which can be used to request an upload. This will be the
+ // value of the low order dword of the process creation time for the process
+ // being dumped.
+ DWORD crash_id_;
+
+ // Disallow copy ctor and operator=.
+ ClientInfo(const ClientInfo& client_info);
+ ClientInfo& operator=(const ClientInfo& client_info);
+};
+
+} // namespace google_breakpad
+
+#endif // CLIENT_WINDOWS_CRASH_GENERATION_CLIENT_INFO_H__
diff --git a/toolkit/crashreporter/breakpad-client/windows/crash_generation/crash_generation_client.cc b/toolkit/crashreporter/breakpad-client/windows/crash_generation/crash_generation_client.cc
new file mode 100644
index 0000000000..0e524e7854
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/windows/crash_generation/crash_generation_client.cc
@@ -0,0 +1,406 @@
+// 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 "windows/crash_generation/crash_generation_client.h"
+#include <cassert>
+#include <utility>
+#include "windows/common/ipc_protocol.h"
+
+namespace google_breakpad {
+
+const int kPipeBusyWaitTimeoutMs = 2000;
+
+#ifdef _DEBUG
+const DWORD kWaitForServerTimeoutMs = INFINITE;
+#else
+const DWORD kWaitForServerTimeoutMs = 15000;
+#endif
+
+const int kPipeConnectMaxAttempts = 6;
+
+const DWORD kPipeDesiredAccess = FILE_READ_DATA |
+ FILE_WRITE_DATA |
+ FILE_WRITE_ATTRIBUTES;
+
+const DWORD kPipeFlagsAndAttributes = SECURITY_IDENTIFICATION |
+ SECURITY_SQOS_PRESENT;
+
+const DWORD kPipeMode = PIPE_READMODE_MESSAGE;
+
+const size_t kWaitEventCount = 2;
+
+// This function is orphan for production code. It can be used
+// for debugging to help repro some scenarios like the client
+// is slow in writing to the pipe after connecting, the client
+// is slow in reading from the pipe after writing, etc. The parameter
+// overlapped below is not used and it is present to match the signature
+// of this function to TransactNamedPipe Win32 API. Uncomment if needed
+// for debugging.
+/**
+static bool TransactNamedPipeDebugHelper(HANDLE pipe,
+ const void* in_buffer,
+ DWORD in_size,
+ void* out_buffer,
+ DWORD out_size,
+ DWORD* bytes_count,
+ LPOVERLAPPED) {
+ // Uncomment the next sleep to create a gap before writing
+ // to pipe.
+ // Sleep(5000);
+
+ if (!WriteFile(pipe,
+ in_buffer,
+ in_size,
+ bytes_count,
+ NULL)) {
+ return false;
+ }
+
+ // Uncomment the next sleep to create a gap between write
+ // and read.
+ // Sleep(5000);
+
+ return ReadFile(pipe, out_buffer, out_size, bytes_count, NULL) != FALSE;
+}
+**/
+
+CrashGenerationClient::CrashGenerationClient(
+ const wchar_t* pipe_name,
+ MINIDUMP_TYPE dump_type,
+ const CustomClientInfo* custom_info)
+ : pipe_name_(pipe_name),
+ pipe_handle_(NULL),
+ custom_info_(),
+ dump_type_(dump_type),
+ crash_event_(NULL),
+ crash_generated_(NULL),
+ server_alive_(NULL),
+ server_process_id_(0),
+ thread_id_(0),
+ exception_pointers_(NULL) {
+ memset(&assert_info_, 0, sizeof(assert_info_));
+ if (custom_info) {
+ custom_info_ = *custom_info;
+ }
+}
+
+CrashGenerationClient::CrashGenerationClient(
+ HANDLE pipe_handle,
+ MINIDUMP_TYPE dump_type,
+ const CustomClientInfo* custom_info)
+ : pipe_name_(),
+ pipe_handle_(pipe_handle),
+ custom_info_(),
+ dump_type_(dump_type),
+ crash_event_(NULL),
+ crash_generated_(NULL),
+ server_alive_(NULL),
+ server_process_id_(0),
+ thread_id_(0),
+ exception_pointers_(NULL) {
+ memset(&assert_info_, 0, sizeof(assert_info_));
+ if (custom_info) {
+ custom_info_ = *custom_info;
+ }
+}
+
+CrashGenerationClient::~CrashGenerationClient() {
+ if (crash_event_) {
+ CloseHandle(crash_event_);
+ }
+
+ if (crash_generated_) {
+ CloseHandle(crash_generated_);
+ }
+
+ if (server_alive_) {
+ CloseHandle(server_alive_);
+ }
+}
+
+// Performs the registration step with the server process.
+// The registration step involves communicating with the server
+// via a named pipe. The client sends the following pieces of
+// data to the server:
+//
+// * Message tag indicating the client is requesting registration.
+// * Process id of the client process.
+// * Address of a DWORD variable in the client address space
+// that will contain the thread id of the client thread that
+// caused the crash.
+// * Address of a EXCEPTION_POINTERS* variable in the client
+// address space that will point to an instance of EXCEPTION_POINTERS
+// when the crash happens.
+// * Address of an instance of MDRawAssertionInfo that will contain
+// relevant information in case of non-exception crashes like assertion
+// failures and pure calls.
+//
+// In return the client expects the following information from the server:
+//
+// * Message tag indicating successful registration.
+// * Server process id.
+// * Handle to an object that client can signal to request dump
+// generation from the server.
+// * Handle to an object that client can wait on after requesting
+// dump generation for the server to finish dump generation.
+// * Handle to a mutex object that client can wait on to make sure
+// server is still alive.
+//
+// If any step of the expected behavior mentioned above fails, the
+// registration step is not considered successful and hence out-of-process
+// dump generation service is not available.
+//
+// Returns true if the registration is successful; false otherwise.
+bool CrashGenerationClient::Register() {
+ if (IsRegistered()) {
+ return true;
+ }
+
+ HANDLE pipe = ConnectToServer();
+ if (!pipe) {
+ return false;
+ }
+
+ bool success = RegisterClient(pipe);
+ CloseHandle(pipe);
+ return success;
+}
+
+bool CrashGenerationClient::RequestUpload(DWORD crash_id) {
+ HANDLE pipe = ConnectToServer();
+ if (!pipe) {
+ return false;
+ }
+
+ CustomClientInfo custom_info = {NULL, 0};
+ ProtocolMessage msg(MESSAGE_TAG_UPLOAD_REQUEST, crash_id,
+ static_cast<MINIDUMP_TYPE>(NULL), NULL, NULL, NULL,
+ custom_info, NULL, NULL, NULL);
+ DWORD bytes_count = 0;
+ bool success = WriteFile(pipe, &msg, sizeof(msg), &bytes_count, NULL) != 0;
+
+ CloseHandle(pipe);
+ return success;
+}
+
+HANDLE CrashGenerationClient::ConnectToServer() {
+ HANDLE pipe = ConnectToPipe(pipe_name_.c_str(),
+ kPipeDesiredAccess,
+ kPipeFlagsAndAttributes);
+ if (!pipe) {
+ return NULL;
+ }
+
+ DWORD mode = kPipeMode;
+ if (!SetNamedPipeHandleState(pipe, &mode, NULL, NULL)) {
+ CloseHandle(pipe);
+ pipe = NULL;
+ }
+
+ return pipe;
+}
+
+bool CrashGenerationClient::RegisterClient(HANDLE pipe) {
+ ProtocolMessage msg(MESSAGE_TAG_REGISTRATION_REQUEST,
+ GetCurrentProcessId(),
+ dump_type_,
+ &thread_id_,
+ &exception_pointers_,
+ &assert_info_,
+ custom_info_,
+ NULL,
+ NULL,
+ NULL);
+ ProtocolMessage reply;
+ DWORD bytes_count = 0;
+ // The call to TransactNamedPipe below can be changed to a call
+ // to TransactNamedPipeDebugHelper to help repro some scenarios.
+ // For details see comments for TransactNamedPipeDebugHelper.
+ if (!TransactNamedPipe(pipe,
+ &msg,
+ sizeof(msg),
+ &reply,
+ sizeof(ProtocolMessage),
+ &bytes_count,
+ NULL)) {
+ return false;
+ }
+
+ if (!ValidateResponse(reply)) {
+ return false;
+ }
+
+ ProtocolMessage ack_msg;
+ ack_msg.tag = MESSAGE_TAG_REGISTRATION_ACK;
+
+ if (!WriteFile(pipe, &ack_msg, sizeof(ack_msg), &bytes_count, NULL)) {
+ return false;
+ }
+ crash_event_ = reply.dump_request_handle;
+ crash_generated_ = reply.dump_generated_handle;
+ server_alive_ = reply.server_alive_handle;
+ server_process_id_ = reply.id;
+
+ return true;
+}
+
+HANDLE CrashGenerationClient::ConnectToPipe(const wchar_t* pipe_name,
+ DWORD pipe_access,
+ DWORD flags_attrs) {
+ if (pipe_handle_) {
+ HANDLE t = pipe_handle_;
+ pipe_handle_ = NULL;
+ return t;
+ }
+
+ for (int i = 0; i < kPipeConnectMaxAttempts; ++i) {
+ HANDLE pipe = CreateFile(pipe_name,
+ pipe_access,
+ 0,
+ NULL,
+ OPEN_EXISTING,
+ flags_attrs,
+ NULL);
+ if (pipe != INVALID_HANDLE_VALUE) {
+ return pipe;
+ }
+
+ // Cannot continue retrying if error is something other than
+ // ERROR_PIPE_BUSY.
+ if (GetLastError() != ERROR_PIPE_BUSY) {
+ break;
+ }
+
+ // Cannot continue retrying if wait on pipe fails.
+ if (!WaitNamedPipe(pipe_name, kPipeBusyWaitTimeoutMs)) {
+ break;
+ }
+ }
+
+ fprintf(stderr, "ConnectToPipe() failure: GetLastError()=%08lx\n", GetLastError());
+ return NULL;
+}
+
+bool CrashGenerationClient::ValidateResponse(
+ const ProtocolMessage& msg) const {
+ return (msg.tag == MESSAGE_TAG_REGISTRATION_RESPONSE) &&
+ (msg.id != 0) &&
+ (msg.dump_request_handle != NULL) &&
+ (msg.dump_generated_handle != NULL) &&
+ (msg.server_alive_handle != NULL);
+}
+
+bool CrashGenerationClient::IsRegistered() const {
+ return crash_event_ != NULL;
+}
+
+bool CrashGenerationClient::RequestDump(EXCEPTION_POINTERS* ex_info,
+ MDRawAssertionInfo* assert_info) {
+ if (!IsRegistered()) {
+ return false;
+ }
+
+ exception_pointers_ = ex_info;
+ thread_id_ = GetCurrentThreadId();
+
+ if (assert_info) {
+ memcpy(&assert_info_, assert_info, sizeof(assert_info_));
+ } else {
+ memset(&assert_info_, 0, sizeof(assert_info_));
+ }
+
+ return SignalCrashEventAndWait();
+}
+
+bool CrashGenerationClient::RequestDump(EXCEPTION_POINTERS* ex_info) {
+ return RequestDump(ex_info, NULL);
+}
+
+bool CrashGenerationClient::RequestDump(MDRawAssertionInfo* assert_info) {
+ return RequestDump(NULL, assert_info);
+}
+
+bool CrashGenerationClient::SignalCrashEventAndWait() {
+ assert(crash_event_);
+ assert(crash_generated_);
+ assert(server_alive_);
+
+ // Reset the dump generated event before signaling the crash
+ // event so that the server can set the dump generated event
+ // once it is done generating the event.
+ if (!ResetEvent(crash_generated_)) {
+ return false;
+ }
+
+ if (!SetEvent(crash_event_)) {
+ return false;
+ }
+
+ HANDLE wait_handles[kWaitEventCount] = {crash_generated_, server_alive_};
+
+ DWORD result = WaitForMultipleObjects(kWaitEventCount,
+ wait_handles,
+ FALSE,
+ kWaitForServerTimeoutMs);
+
+ // Crash dump was successfully generated only if the server
+ // signaled the crash generated event.
+ return result == WAIT_OBJECT_0;
+}
+
+HANDLE CrashGenerationClient::DuplicatePipeToClientProcess(const wchar_t* pipe_name,
+ HANDLE hProcess) {
+ for (int i = 0; i < kPipeConnectMaxAttempts; ++i) {
+ HANDLE local_pipe = CreateFile(pipe_name, kPipeDesiredAccess,
+ 0, NULL, OPEN_EXISTING,
+ kPipeFlagsAndAttributes, NULL);
+ if (local_pipe != INVALID_HANDLE_VALUE) {
+ HANDLE remotePipe = INVALID_HANDLE_VALUE;
+ if (DuplicateHandle(GetCurrentProcess(), local_pipe,
+ hProcess, &remotePipe, 0, FALSE,
+ DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS)) {
+ return remotePipe;
+ } else {
+ return INVALID_HANDLE_VALUE;
+ }
+ }
+
+ // Cannot continue retrying if the error wasn't a busy pipe.
+ if (GetLastError() != ERROR_PIPE_BUSY) {
+ return INVALID_HANDLE_VALUE;
+ }
+
+ if (!WaitNamedPipe(pipe_name, kPipeBusyWaitTimeoutMs)) {
+ return INVALID_HANDLE_VALUE;
+ }
+ }
+ return INVALID_HANDLE_VALUE;
+}
+
+} // namespace google_breakpad
diff --git a/toolkit/crashreporter/breakpad-client/windows/crash_generation/crash_generation_client.h b/toolkit/crashreporter/breakpad-client/windows/crash_generation/crash_generation_client.h
new file mode 100644
index 0000000000..0bfcdb3731
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/windows/crash_generation/crash_generation_client.h
@@ -0,0 +1,182 @@
+// 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.
+
+#ifndef CLIENT_WINDOWS_CRASH_GENERATION_CRASH_GENERATION_CLIENT_H_
+#define CLIENT_WINDOWS_CRASH_GENERATION_CRASH_GENERATION_CLIENT_H_
+
+#include <windows.h>
+#include <dbghelp.h>
+#include <string>
+#include <utility>
+#include "windows/common/ipc_protocol.h"
+#include "common/scoped_ptr.h"
+
+namespace google_breakpad {
+
+struct CustomClientInfo;
+
+// Abstraction of client-side implementation of out of process
+// crash generation.
+//
+// The process that desires to have out-of-process crash dump
+// generation service can use this class in the following way:
+//
+// * Create an instance.
+// * Call Register method so that the client tries to register
+// with the server process and check the return value. If
+// registration is not successful, out-of-process crash dump
+// generation will not be available
+// * Request dump generation by calling either of the two
+// overloaded RequestDump methods - one in case of exceptions
+// and the other in case of assertion failures
+//
+// Note that it is the responsibility of the client code of
+// this class to set the unhandled exception filter with the
+// system by calling the SetUnhandledExceptionFilter function
+// and the client code should explicitly request dump generation.
+class CrashGenerationClient {
+ public:
+ CrashGenerationClient(const wchar_t* pipe_name,
+ MINIDUMP_TYPE dump_type,
+ const CustomClientInfo* custom_info);
+
+ CrashGenerationClient(HANDLE pipe_handle,
+ MINIDUMP_TYPE dump_type,
+ const CustomClientInfo* custom_info);
+
+ ~CrashGenerationClient();
+
+ // Registers the client process with the crash server.
+ //
+ // Returns true if the registration is successful; false otherwise.
+ bool Register();
+
+ // Requests the crash server to upload a previous dump with the
+ // given crash id.
+ bool RequestUpload(DWORD crash_id);
+
+ bool RequestDump(EXCEPTION_POINTERS* ex_info,
+ MDRawAssertionInfo* assert_info);
+
+ // Requests the crash server to generate a dump with the given
+ // exception information.
+ //
+ // Returns true if the dump was successful; false otherwise. Note that
+ // if the registration step was not performed or it was not successful,
+ // false will be returned.
+ bool RequestDump(EXCEPTION_POINTERS* ex_info);
+
+ // Requests the crash server to generate a dump with the given
+ // assertion information.
+ //
+ // Returns true if the dump was successful; false otherwise. Note that
+ // if the registration step was not performed or it was not successful,
+ // false will be returned.
+ bool RequestDump(MDRawAssertionInfo* assert_info);
+
+ // If the crash generation client is running in a sandbox that prevents it
+ // from opening the named pipe directly, the server process may open the
+ // handle and duplicate it into the client process with this helper method.
+ // Returns INVALID_HANDLE_VALUE on failure. The process must have been opened
+ // with the PROCESS_DUP_HANDLE access right.
+ static HANDLE DuplicatePipeToClientProcess(const wchar_t* pipe_name,
+ HANDLE hProcess);
+
+ private:
+ // Connects to the appropriate pipe and sets the pipe handle state.
+ //
+ // Returns the pipe handle if everything goes well; otherwise Returns NULL.
+ HANDLE ConnectToServer();
+
+ // Performs a handshake with the server over the given pipe which should be
+ // already connected to the server.
+ //
+ // Returns true if handshake with the server was successful; false otherwise.
+ bool RegisterClient(HANDLE pipe);
+
+ // Validates the given server response.
+ bool ValidateResponse(const ProtocolMessage& msg) const;
+
+ // Returns true if the registration step succeeded; false otherwise.
+ bool IsRegistered() const;
+
+ // Connects to the given named pipe with given parameters.
+ //
+ // Returns true if the connection is successful; false otherwise.
+ HANDLE ConnectToPipe(const wchar_t* pipe_name,
+ DWORD pipe_access,
+ DWORD flags_attrs);
+
+ // Signals the crash event and wait for the server to generate crash.
+ bool SignalCrashEventAndWait();
+
+ // Pipe name to use to talk to server.
+ std::wstring pipe_name_;
+
+ // Pipe handle duplicated from server process. Only valid before
+ // Register is called.
+ HANDLE pipe_handle_;
+
+ // Custom client information
+ CustomClientInfo custom_info_;
+
+ // Type of dump to generate.
+ MINIDUMP_TYPE dump_type_;
+
+ // Event to signal in case of a crash.
+ HANDLE crash_event_;
+
+ // Handle to wait on after signaling a crash for the server
+ // to finish generating crash dump.
+ HANDLE crash_generated_;
+
+ // Handle to a mutex that will become signaled with WAIT_ABANDONED
+ // if the server process goes down.
+ HANDLE server_alive_;
+
+ // Server process id.
+ DWORD server_process_id_;
+
+ // Id of the thread that caused the crash.
+ DWORD thread_id_;
+
+ // Exception pointers for an exception crash.
+ EXCEPTION_POINTERS* exception_pointers_;
+
+ // Assertion info for an invalid parameter or pure call crash.
+ MDRawAssertionInfo assert_info_;
+
+ // Disable copy ctor and operator=.
+ CrashGenerationClient(const CrashGenerationClient& crash_client);
+ CrashGenerationClient& operator=(const CrashGenerationClient& crash_client);
+};
+
+} // namespace google_breakpad
+
+#endif // CLIENT_WINDOWS_CRASH_GENERATION_CRASH_GENERATION_CLIENT_H_
diff --git a/toolkit/crashreporter/breakpad-client/windows/crash_generation/crash_generation_server.cc b/toolkit/crashreporter/breakpad-client/windows/crash_generation/crash_generation_server.cc
new file mode 100644
index 0000000000..dfa6d5161f
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/windows/crash_generation/crash_generation_server.cc
@@ -0,0 +1,996 @@
+// 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 "windows/crash_generation/crash_generation_server.h"
+#include <windows.h>
+#include <cassert>
+#include <list>
+#include "windows/common/auto_critical_section.h"
+#include "common/scoped_ptr.h"
+
+#include "windows/crash_generation/client_info.h"
+
+namespace google_breakpad {
+
+// Output buffer size.
+static const size_t kOutBufferSize = 64;
+
+// Input buffer size.
+static const size_t kInBufferSize = 64;
+
+// Access flags for the client on the dump request event.
+static const DWORD kDumpRequestEventAccess = EVENT_MODIFY_STATE;
+
+// Access flags for the client on the dump generated event.
+static const DWORD kDumpGeneratedEventAccess = EVENT_MODIFY_STATE |
+ SYNCHRONIZE;
+
+// Access flags for the client on the mutex.
+static const DWORD kMutexAccess = SYNCHRONIZE;
+
+// Attribute flags for the pipe.
+static const DWORD kPipeAttr = FILE_FLAG_FIRST_PIPE_INSTANCE |
+ PIPE_ACCESS_DUPLEX |
+ FILE_FLAG_OVERLAPPED;
+
+// Mode for the pipe.
+static const DWORD kPipeMode = PIPE_TYPE_MESSAGE |
+ PIPE_READMODE_MESSAGE |
+ PIPE_WAIT;
+
+// For pipe I/O, execute the callback in the wait thread itself,
+// since the callback does very little work. The callback executes
+// the code for one of the states of the server state machine and
+// the code for all of the states perform async I/O and hence
+// finish very quickly.
+static const ULONG kPipeIOThreadFlags = WT_EXECUTEINWAITTHREAD;
+
+// Dump request threads will, most likely, generate dumps. That may
+// take some time to finish, so specify WT_EXECUTELONGFUNCTION flag.
+static const ULONG kDumpRequestThreadFlags = WT_EXECUTEINWAITTHREAD |
+ WT_EXECUTELONGFUNCTION;
+
+static bool IsClientRequestValid(const ProtocolMessage& msg) {
+ return msg.tag == MESSAGE_TAG_UPLOAD_REQUEST ||
+ (msg.tag == MESSAGE_TAG_REGISTRATION_REQUEST &&
+ msg.id != 0 &&
+ msg.thread_id != NULL &&
+ msg.exception_pointers != NULL &&
+ msg.assert_info != NULL);
+}
+
+#ifndef NDEBUG
+static bool CheckForIOIncomplete(bool success) {
+ // We should never get an I/O incomplete since we should not execute this
+ // unless the operation has finished and the overlapped event is signaled. If
+ // we do get INCOMPLETE, we have a bug in our code.
+ return success ? false : (GetLastError() == ERROR_IO_INCOMPLETE);
+}
+#endif
+
+CrashGenerationServer::CrashGenerationServer(
+ const std::wstring& pipe_name,
+ SECURITY_ATTRIBUTES* pipe_sec_attrs,
+ OnClientConnectedCallback connect_callback,
+ void* connect_context,
+ OnClientDumpRequestCallback dump_callback,
+ void* dump_context,
+ OnClientDumpWrittenCallback written_callback,
+ OnClientExitedCallback exit_callback,
+ void* exit_context,
+ OnClientUploadRequestCallback upload_request_callback,
+ void* upload_context,
+ bool generate_dumps,
+ const std::wstring* dump_path)
+ : pipe_name_(pipe_name),
+ pipe_sec_attrs_(pipe_sec_attrs),
+ pipe_(NULL),
+ pipe_wait_handle_(NULL),
+ server_alive_handle_(NULL),
+ connect_callback_(connect_callback),
+ connect_context_(connect_context),
+ dump_callback_(dump_callback),
+ dump_context_(dump_context),
+ written_callback_(written_callback),
+ exit_callback_(exit_callback),
+ exit_context_(exit_context),
+ upload_request_callback_(upload_request_callback),
+ upload_context_(upload_context),
+ generate_dumps_(generate_dumps),
+ pre_fetch_custom_info_(true),
+ dump_path_(dump_path ? *dump_path : L""),
+ server_state_(IPC_SERVER_STATE_UNINITIALIZED),
+ shutting_down_(false),
+ overlapped_(),
+ client_info_(NULL),
+ include_context_heap_(false) {
+ InitializeCriticalSection(&sync_);
+}
+
+// This should never be called from the OnPipeConnected callback.
+// Otherwise the UnregisterWaitEx call below will cause a deadlock.
+CrashGenerationServer::~CrashGenerationServer() {
+ // New scope to release the lock automatically.
+ {
+ // Make sure no clients are added or removed beyond this point.
+ // Before adding or removing any clients, the critical section
+ // must be entered and the shutting_down_ flag checked. The
+ // critical section is then exited only after the clients_ list
+ // modifications are done and the list is in a consistent state.
+ AutoCriticalSection lock(&sync_);
+
+ // Indicate to existing threads that server is shutting down.
+ shutting_down_ = true;
+ }
+ // No one will modify the clients_ list beyond this point -
+ // not even from another thread.
+
+ // Even if there are no current worker threads running, it is possible that
+ // an I/O request is pending on the pipe right now but not yet done.
+ // In fact, it's very likely this is the case unless we are in an ERROR
+ // state. If we don't wait for the pending I/O to be done, then when the I/O
+ // completes, it may write to invalid memory. AppVerifier will flag this
+ // problem too. So we disconnect from the pipe and then wait for the server
+ // to get into error state so that the pending I/O will fail and get
+ // cleared.
+ DisconnectNamedPipe(pipe_);
+ int num_tries = 100;
+ while (num_tries-- && server_state_ != IPC_SERVER_STATE_ERROR) {
+ Sleep(10);
+ }
+
+ // Unregister wait on the pipe.
+ if (pipe_wait_handle_) {
+ // Wait for already executing callbacks to finish.
+ UnregisterWaitEx(pipe_wait_handle_, INVALID_HANDLE_VALUE);
+ }
+
+ // Close the pipe to avoid further client connections.
+ if (pipe_) {
+ CloseHandle(pipe_);
+ }
+
+ // Request all ClientInfo objects to unregister all waits.
+ // No need to enter the critical section because no one is allowed to modify
+ // the clients_ list once the shutting_down_ flag is set.
+ std::list<ClientInfo*>::iterator iter;
+ for (iter = clients_.begin(); iter != clients_.end(); ++iter) {
+ ClientInfo* client_info = *iter;
+ // Unregister waits. Wait for already executing callbacks to finish.
+ // Unregister the client process exit wait first and only then unregister
+ // the dump request wait. The reason is that the OnClientExit callback
+ // also unregisters the dump request wait and such a race (doing the same
+ // unregistration from two threads) is undesirable.
+ client_info->UnregisterProcessExitWait(true);
+ client_info->UnregisterDumpRequestWaitAndBlockUntilNoPending();
+
+ // Destroying the ClientInfo here is safe because all wait operations for
+ // this ClientInfo were unregistered and no pending or running callbacks
+ // for this ClientInfo can possible exist (block_until_no_pending option
+ // was used).
+ delete client_info;
+ }
+
+ if (server_alive_handle_) {
+ // Release the mutex before closing the handle so that clients requesting
+ // dumps wait for a long time for the server to generate a dump.
+ ReleaseMutex(server_alive_handle_);
+ CloseHandle(server_alive_handle_);
+ }
+
+ if (overlapped_.hEvent) {
+ CloseHandle(overlapped_.hEvent);
+ }
+
+ DeleteCriticalSection(&sync_);
+}
+
+bool CrashGenerationServer::Start() {
+ if (server_state_ != IPC_SERVER_STATE_UNINITIALIZED) {
+ return false;
+ }
+
+ server_state_ = IPC_SERVER_STATE_INITIAL;
+
+ server_alive_handle_ = CreateMutex(NULL, TRUE, NULL);
+ if (!server_alive_handle_) {
+ return false;
+ }
+
+ // Event to signal the client connection and pipe reads and writes.
+ overlapped_.hEvent = CreateEvent(NULL, // Security descriptor.
+ TRUE, // Manual reset.
+ FALSE, // Initially nonsignaled.
+ NULL); // Name.
+ if (!overlapped_.hEvent) {
+ return false;
+ }
+
+ // Register a callback with the thread pool for the client connection.
+ if (!RegisterWaitForSingleObject(&pipe_wait_handle_,
+ overlapped_.hEvent,
+ OnPipeConnected,
+ this,
+ INFINITE,
+ kPipeIOThreadFlags)) {
+ return false;
+ }
+
+ pipe_ = CreateNamedPipe(pipe_name_.c_str(),
+ kPipeAttr,
+ kPipeMode,
+ 1,
+ kOutBufferSize,
+ kInBufferSize,
+ 0,
+ pipe_sec_attrs_);
+ if (pipe_ == INVALID_HANDLE_VALUE) {
+ return false;
+ }
+
+ // Kick-start the state machine. This will initiate an asynchronous wait
+ // for client connections.
+ if (!SetEvent(overlapped_.hEvent)) {
+ server_state_ = IPC_SERVER_STATE_ERROR;
+ return false;
+ }
+
+ // If we are in error state, it's because we failed to start listening.
+ return true;
+}
+
+// If the server thread serving clients ever gets into the
+// ERROR state, reset the event, close the pipe and remain
+// in the error state forever. Error state means something
+// that we didn't account for has happened, and it's dangerous
+// to do anything unknowingly.
+void CrashGenerationServer::HandleErrorState() {
+ assert(server_state_ == IPC_SERVER_STATE_ERROR);
+
+ // If the server is shutting down anyway, don't clean up
+ // here since shut down process will clean up.
+ if (shutting_down_) {
+ return;
+ }
+
+ if (pipe_wait_handle_) {
+ UnregisterWait(pipe_wait_handle_);
+ pipe_wait_handle_ = NULL;
+ }
+
+ if (pipe_) {
+ CloseHandle(pipe_);
+ pipe_ = NULL;
+ }
+
+ if (overlapped_.hEvent) {
+ CloseHandle(overlapped_.hEvent);
+ overlapped_.hEvent = NULL;
+ }
+}
+
+// When the server thread serving clients is in the INITIAL state,
+// try to connect to the pipe asynchronously. If the connection
+// finishes synchronously, directly go into the CONNECTED state;
+// otherwise go into the CONNECTING state. For any problems, go
+// into the ERROR state.
+void CrashGenerationServer::HandleInitialState() {
+ assert(server_state_ == IPC_SERVER_STATE_INITIAL);
+
+ if (!ResetEvent(overlapped_.hEvent)) {
+ EnterErrorState();
+ return;
+ }
+
+ bool success = ConnectNamedPipe(pipe_, &overlapped_) != FALSE;
+ DWORD error_code = success ? ERROR_SUCCESS : GetLastError();
+
+ // From MSDN, it is not clear that when ConnectNamedPipe is used
+ // in an overlapped mode, will it ever return non-zero value, and
+ // if so, in what cases.
+ assert(!success);
+
+ switch (error_code) {
+ case ERROR_IO_PENDING:
+ EnterStateWhenSignaled(IPC_SERVER_STATE_CONNECTING);
+ break;
+
+ case ERROR_PIPE_CONNECTED:
+ EnterStateImmediately(IPC_SERVER_STATE_CONNECTED);
+ break;
+
+ default:
+ EnterErrorState();
+ break;
+ }
+}
+
+// When the server thread serving the clients is in the CONNECTING state,
+// try to get the result of the asynchronous connection request using
+// the OVERLAPPED object. If the result indicates the connection is done,
+// go into the CONNECTED state. If the result indicates I/O is still
+// INCOMPLETE, remain in the CONNECTING state. For any problems,
+// go into the DISCONNECTING state.
+void CrashGenerationServer::HandleConnectingState() {
+ assert(server_state_ == IPC_SERVER_STATE_CONNECTING);
+
+ DWORD bytes_count = 0;
+ bool success = GetOverlappedResult(pipe_,
+ &overlapped_,
+ &bytes_count,
+ FALSE) != FALSE;
+ DWORD error_code = success ? ERROR_SUCCESS : GetLastError();
+
+ if (success) {
+ EnterStateImmediately(IPC_SERVER_STATE_CONNECTED);
+ } else if (error_code != ERROR_IO_INCOMPLETE) {
+ EnterStateImmediately(IPC_SERVER_STATE_DISCONNECTING);
+ } else {
+ // remain in CONNECTING state
+ }
+}
+
+// When the server thread serving the clients is in the CONNECTED state,
+// try to issue an asynchronous read from the pipe. If read completes
+// synchronously or if I/O is pending then go into the READING state.
+// For any problems, go into the DISCONNECTING state.
+void CrashGenerationServer::HandleConnectedState() {
+ assert(server_state_ == IPC_SERVER_STATE_CONNECTED);
+
+ DWORD bytes_count = 0;
+ memset(&msg_, 0, sizeof(msg_));
+ bool success = ReadFile(pipe_,
+ &msg_,
+ sizeof(msg_),
+ &bytes_count,
+ &overlapped_) != FALSE;
+ DWORD error_code = success ? ERROR_SUCCESS : GetLastError();
+
+ // Note that the asynchronous read issued above can finish before the
+ // code below executes. But, it is okay to change state after issuing
+ // the asynchronous read. This is because even if the asynchronous read
+ // is done, the callback for it would not be executed until the current
+ // thread finishes its execution.
+ if (success || error_code == ERROR_IO_PENDING) {
+ EnterStateWhenSignaled(IPC_SERVER_STATE_READING);
+ } else {
+ EnterStateImmediately(IPC_SERVER_STATE_DISCONNECTING);
+ }
+}
+
+// When the server thread serving the clients is in the READING state,
+// try to get the result of the async read. If async read is done,
+// go into the READ_DONE state. For any problems, go into the
+// DISCONNECTING state.
+void CrashGenerationServer::HandleReadingState() {
+ assert(server_state_ == IPC_SERVER_STATE_READING);
+
+ DWORD bytes_count = 0;
+ bool success = GetOverlappedResult(pipe_,
+ &overlapped_,
+ &bytes_count,
+ FALSE) != FALSE;
+ if (success && bytes_count == sizeof(ProtocolMessage)) {
+ EnterStateImmediately(IPC_SERVER_STATE_READ_DONE);
+ return;
+ }
+
+ assert(!CheckForIOIncomplete(success));
+ EnterStateImmediately(IPC_SERVER_STATE_DISCONNECTING);
+}
+
+// When the server thread serving the client is in the READ_DONE state,
+// validate the client's request message, register the client by
+// creating appropriate objects and prepare the response. Then try to
+// write the response to the pipe asynchronously. If that succeeds,
+// go into the WRITING state. For any problems, go into the DISCONNECTING
+// state.
+void CrashGenerationServer::HandleReadDoneState() {
+ assert(server_state_ == IPC_SERVER_STATE_READ_DONE);
+
+ if (!IsClientRequestValid(msg_)) {
+ EnterStateImmediately(IPC_SERVER_STATE_DISCONNECTING);
+ return;
+ }
+
+ if (msg_.tag == MESSAGE_TAG_UPLOAD_REQUEST) {
+ if (upload_request_callback_)
+ upload_request_callback_(upload_context_, msg_.id);
+ EnterStateImmediately(IPC_SERVER_STATE_DISCONNECTING);
+ return;
+ }
+
+ scoped_ptr<ClientInfo> client_info(
+ new ClientInfo(this,
+ msg_.id,
+ msg_.dump_type,
+ msg_.thread_id,
+ msg_.exception_pointers,
+ msg_.assert_info,
+ msg_.custom_client_info));
+
+ if (!client_info->Initialize()) {
+ EnterStateImmediately(IPC_SERVER_STATE_DISCONNECTING);
+ return;
+ }
+
+ // Issues an asynchronous WriteFile call if successful.
+ // Iff successful, assigns ownership of the client_info pointer to the server
+ // instance, in which case we must be sure not to free it in this function.
+ if (!RespondToClient(client_info.get())) {
+ EnterStateImmediately(IPC_SERVER_STATE_DISCONNECTING);
+ return;
+ }
+
+ // This is only valid as long as it can be found in the clients_ list
+ client_info_ = client_info.release();
+
+ // Note that the asynchronous write issued by RespondToClient function
+ // can finish before the code below executes. But it is okay to change
+ // state after issuing the asynchronous write. This is because even if
+ // the asynchronous write is done, the callback for it would not be
+ // executed until the current thread finishes its execution.
+ EnterStateWhenSignaled(IPC_SERVER_STATE_WRITING);
+}
+
+// When the server thread serving the clients is in the WRITING state,
+// try to get the result of the async write. If the async write is done,
+// go into the WRITE_DONE state. For any problems, go into the
+// DISONNECTING state.
+void CrashGenerationServer::HandleWritingState() {
+ assert(server_state_ == IPC_SERVER_STATE_WRITING);
+
+ DWORD bytes_count = 0;
+ bool success = GetOverlappedResult(pipe_,
+ &overlapped_,
+ &bytes_count,
+ FALSE) != FALSE;
+ if (success) {
+ EnterStateImmediately(IPC_SERVER_STATE_WRITE_DONE);
+ return;
+ }
+
+ assert(!CheckForIOIncomplete(success));
+ EnterStateImmediately(IPC_SERVER_STATE_DISCONNECTING);
+}
+
+// When the server thread serving the clients is in the WRITE_DONE state,
+// try to issue an async read on the pipe. If the read completes synchronously
+// or if I/O is still pending then go into the READING_ACK state. For any
+// issues, go into the DISCONNECTING state.
+void CrashGenerationServer::HandleWriteDoneState() {
+ assert(server_state_ == IPC_SERVER_STATE_WRITE_DONE);
+
+ DWORD bytes_count = 0;
+ bool success = ReadFile(pipe_,
+ &msg_,
+ sizeof(msg_),
+ &bytes_count,
+ &overlapped_) != FALSE;
+ DWORD error_code = success ? ERROR_SUCCESS : GetLastError();
+
+ if (success) {
+ EnterStateImmediately(IPC_SERVER_STATE_READING_ACK);
+ } else if (error_code == ERROR_IO_PENDING) {
+ EnterStateWhenSignaled(IPC_SERVER_STATE_READING_ACK);
+ } else {
+ EnterStateImmediately(IPC_SERVER_STATE_DISCONNECTING);
+ }
+}
+
+// When the server thread serving the clients is in the READING_ACK state,
+// try to get result of async read. Go into the DISCONNECTING state.
+void CrashGenerationServer::HandleReadingAckState() {
+ assert(server_state_ == IPC_SERVER_STATE_READING_ACK);
+
+ DWORD bytes_count = 0;
+ bool success = GetOverlappedResult(pipe_,
+ &overlapped_,
+ &bytes_count,
+ FALSE) != FALSE;
+ if (success) {
+ // The connection handshake with the client is now complete; perform
+ // the callback.
+ if (connect_callback_) {
+ // Note that there is only a single copy of the ClientInfo of the
+ // currently connected client. However it is being referenced from
+ // two different places:
+ // - the client_info_ member
+ // - the clients_ list
+ // The lifetime of this ClientInfo depends on the lifetime of the
+ // client process - basically it can go away at any time.
+ // However, as long as it is referenced by the clients_ list it
+ // is guaranteed to be valid. Enter the critical section and check
+ // to see whether the client_info_ can be found in the list.
+ // If found, execute the callback and only then leave the critical
+ // section.
+ AutoCriticalSection lock(&sync_);
+
+ bool client_is_still_alive = false;
+ std::list<ClientInfo*>::iterator iter;
+ for (iter = clients_.begin(); iter != clients_.end(); ++iter) {
+ if (client_info_ == *iter) {
+ client_is_still_alive = true;
+ break;
+ }
+ }
+
+ if (client_is_still_alive) {
+ connect_callback_(connect_context_, client_info_);
+ }
+ }
+ } else {
+ assert(!CheckForIOIncomplete(success));
+ }
+
+ EnterStateImmediately(IPC_SERVER_STATE_DISCONNECTING);
+}
+
+// When the server thread serving the client is in the DISCONNECTING state,
+// disconnect from the pipe and reset the event. If anything fails, go into
+// the ERROR state. If it goes well, go into the INITIAL state and set the
+// event to start all over again.
+void CrashGenerationServer::HandleDisconnectingState() {
+ assert(server_state_ == IPC_SERVER_STATE_DISCONNECTING);
+
+ // Done serving the client.
+ client_info_ = NULL;
+
+ overlapped_.Internal = NULL;
+ overlapped_.InternalHigh = NULL;
+ overlapped_.Offset = 0;
+ overlapped_.OffsetHigh = 0;
+ overlapped_.Pointer = NULL;
+
+ if (!ResetEvent(overlapped_.hEvent)) {
+ EnterErrorState();
+ return;
+ }
+
+ if (!DisconnectNamedPipe(pipe_)) {
+ EnterErrorState();
+ return;
+ }
+
+ // If the server is shutting down do not connect to the
+ // next client.
+ if (shutting_down_) {
+ return;
+ }
+
+ EnterStateImmediately(IPC_SERVER_STATE_INITIAL);
+}
+
+void CrashGenerationServer::EnterErrorState() {
+ SetEvent(overlapped_.hEvent);
+ server_state_ = IPC_SERVER_STATE_ERROR;
+}
+
+void CrashGenerationServer::EnterStateWhenSignaled(IPCServerState state) {
+ server_state_ = state;
+}
+
+void CrashGenerationServer::EnterStateImmediately(IPCServerState state) {
+ server_state_ = state;
+
+ if (!SetEvent(overlapped_.hEvent)) {
+ server_state_ = IPC_SERVER_STATE_ERROR;
+ }
+}
+
+bool CrashGenerationServer::PrepareReply(const ClientInfo& client_info,
+ ProtocolMessage* reply) const {
+ reply->tag = MESSAGE_TAG_REGISTRATION_RESPONSE;
+ reply->id = GetCurrentProcessId();
+
+ if (CreateClientHandles(client_info, reply)) {
+ return true;
+ }
+
+ // Closing of remote handles (belonging to a different process) can
+ // only be done through DuplicateHandle.
+ if (reply->dump_request_handle) {
+ DuplicateHandle(client_info.process_handle(), // hSourceProcessHandle
+ reply->dump_request_handle, // hSourceHandle
+ NULL, // hTargetProcessHandle
+ 0, // lpTargetHandle
+ 0, // dwDesiredAccess
+ FALSE, // bInheritHandle
+ DUPLICATE_CLOSE_SOURCE); // dwOptions
+ reply->dump_request_handle = NULL;
+ }
+
+ if (reply->dump_generated_handle) {
+ DuplicateHandle(client_info.process_handle(), // hSourceProcessHandle
+ reply->dump_generated_handle, // hSourceHandle
+ NULL, // hTargetProcessHandle
+ 0, // lpTargetHandle
+ 0, // dwDesiredAccess
+ FALSE, // bInheritHandle
+ DUPLICATE_CLOSE_SOURCE); // dwOptions
+ reply->dump_generated_handle = NULL;
+ }
+
+ if (reply->server_alive_handle) {
+ DuplicateHandle(client_info.process_handle(), // hSourceProcessHandle
+ reply->server_alive_handle, // hSourceHandle
+ NULL, // hTargetProcessHandle
+ 0, // lpTargetHandle
+ 0, // dwDesiredAccess
+ FALSE, // bInheritHandle
+ DUPLICATE_CLOSE_SOURCE); // dwOptions
+ reply->server_alive_handle = NULL;
+ }
+
+ return false;
+}
+
+bool CrashGenerationServer::CreateClientHandles(const ClientInfo& client_info,
+ ProtocolMessage* reply) const {
+ HANDLE current_process = GetCurrentProcess();
+ if (!DuplicateHandle(current_process,
+ client_info.dump_requested_handle(),
+ client_info.process_handle(),
+ &reply->dump_request_handle,
+ kDumpRequestEventAccess,
+ FALSE,
+ 0)) {
+ return false;
+ }
+
+ if (!DuplicateHandle(current_process,
+ client_info.dump_generated_handle(),
+ client_info.process_handle(),
+ &reply->dump_generated_handle,
+ kDumpGeneratedEventAccess,
+ FALSE,
+ 0)) {
+ return false;
+ }
+
+ if (!DuplicateHandle(current_process,
+ server_alive_handle_,
+ client_info.process_handle(),
+ &reply->server_alive_handle,
+ kMutexAccess,
+ FALSE,
+ 0)) {
+ return false;
+ }
+
+ return true;
+}
+
+bool CrashGenerationServer::RespondToClient(ClientInfo* client_info) {
+ ProtocolMessage reply;
+ if (!PrepareReply(*client_info, &reply)) {
+ return false;
+ }
+
+ DWORD bytes_count = 0;
+ bool success = WriteFile(pipe_,
+ &reply,
+ sizeof(reply),
+ &bytes_count,
+ &overlapped_) != FALSE;
+ DWORD error_code = success ? ERROR_SUCCESS : GetLastError();
+
+ if (!success && error_code != ERROR_IO_PENDING) {
+ return false;
+ }
+
+ // Takes over ownership of client_info. We MUST return true if AddClient
+ // succeeds.
+ return AddClient(client_info);
+}
+
+// The server thread servicing the clients runs this method. The method
+// implements the state machine described in ReadMe.txt along with the
+// helper methods HandleXXXState.
+void CrashGenerationServer::HandleConnectionRequest() {
+ // If the server is shutting down, get into ERROR state, reset the event so
+ // more workers don't run and return immediately.
+ if (shutting_down_) {
+ server_state_ = IPC_SERVER_STATE_ERROR;
+ ResetEvent(overlapped_.hEvent);
+ return;
+ }
+
+ switch (server_state_) {
+ case IPC_SERVER_STATE_ERROR:
+ HandleErrorState();
+ break;
+
+ case IPC_SERVER_STATE_INITIAL:
+ HandleInitialState();
+ break;
+
+ case IPC_SERVER_STATE_CONNECTING:
+ HandleConnectingState();
+ break;
+
+ case IPC_SERVER_STATE_CONNECTED:
+ HandleConnectedState();
+ break;
+
+ case IPC_SERVER_STATE_READING:
+ HandleReadingState();
+ break;
+
+ case IPC_SERVER_STATE_READ_DONE:
+ HandleReadDoneState();
+ break;
+
+ case IPC_SERVER_STATE_WRITING:
+ HandleWritingState();
+ break;
+
+ case IPC_SERVER_STATE_WRITE_DONE:
+ HandleWriteDoneState();
+ break;
+
+ case IPC_SERVER_STATE_READING_ACK:
+ HandleReadingAckState();
+ break;
+
+ case IPC_SERVER_STATE_DISCONNECTING:
+ HandleDisconnectingState();
+ break;
+
+ default:
+ assert(false);
+ // This indicates that we added one more state without
+ // adding handling code.
+ server_state_ = IPC_SERVER_STATE_ERROR;
+ break;
+ }
+}
+
+bool CrashGenerationServer::AddClient(ClientInfo* client_info) {
+ HANDLE request_wait_handle = NULL;
+ if (!RegisterWaitForSingleObject(&request_wait_handle,
+ client_info->dump_requested_handle(),
+ OnDumpRequest,
+ client_info,
+ INFINITE,
+ kDumpRequestThreadFlags)) {
+ return false;
+ }
+
+ client_info->set_dump_request_wait_handle(request_wait_handle);
+
+ // New scope to hold the lock for the shortest time.
+ {
+ AutoCriticalSection lock(&sync_);
+
+ // OnClientEnd will be called when the client process terminates.
+ HANDLE process_wait_handle = NULL;
+ if (!RegisterWaitForSingleObject(&process_wait_handle,
+ client_info->process_handle(),
+ OnClientEnd,
+ client_info,
+ INFINITE,
+ WT_EXECUTEONLYONCE)) {
+ return false;
+ }
+
+ client_info->set_process_exit_wait_handle(process_wait_handle);
+
+ if (shutting_down_) {
+ // If server is shutting down, don't add new clients
+ return false;
+ }
+ clients_.push_back(client_info);
+ }
+
+ return true;
+}
+
+// static
+void CALLBACK CrashGenerationServer::OnPipeConnected(void* context, BOOLEAN) {
+ assert(context);
+
+ CrashGenerationServer* obj =
+ reinterpret_cast<CrashGenerationServer*>(context);
+ obj->HandleConnectionRequest();
+}
+
+// static
+void CALLBACK CrashGenerationServer::OnDumpRequest(void* context, BOOLEAN) {
+ assert(context);
+ ClientInfo* client_info = reinterpret_cast<ClientInfo*>(context);
+
+ CrashGenerationServer* crash_server = client_info->crash_server();
+ assert(crash_server);
+ if (crash_server->pre_fetch_custom_info_) {
+ client_info->PopulateCustomInfo();
+ }
+ crash_server->HandleDumpRequest(*client_info);
+
+ ResetEvent(client_info->dump_requested_handle());
+}
+
+// static
+void CALLBACK CrashGenerationServer::OnClientEnd(void* context, BOOLEAN) {
+ assert(context);
+ ClientInfo* client_info = reinterpret_cast<ClientInfo*>(context);
+
+ CrashGenerationServer* crash_server = client_info->crash_server();
+ assert(crash_server);
+
+ crash_server->HandleClientProcessExit(client_info);
+}
+
+void CrashGenerationServer::HandleClientProcessExit(ClientInfo* client_info) {
+ assert(client_info);
+
+ // Must unregister the dump request wait operation and wait for any
+ // dump requests that might be pending to finish before proceeding
+ // with the client_info cleanup.
+ client_info->UnregisterDumpRequestWaitAndBlockUntilNoPending();
+
+ if (exit_callback_) {
+ exit_callback_(exit_context_, *client_info);
+ }
+
+ // Start a new scope to release lock automatically.
+ {
+ AutoCriticalSection lock(&sync_);
+ if (shutting_down_) {
+ // The crash generation server is shutting down and as part of the
+ // shutdown process it will delete all clients from the clients_ list.
+ return;
+ }
+ clients_.remove(client_info);
+ }
+
+ AutoCriticalSection lock(&sync_);
+
+ // Explicitly unregister the process exit wait using the non-blocking method.
+ // Otherwise, the destructor will attempt to unregister it using the blocking
+ // method which will lead to a deadlock because it is being called from the
+ // callback of the same wait operation
+ client_info->UnregisterProcessExitWait(false);
+
+ delete client_info;
+}
+
+void CrashGenerationServer::HandleDumpRequest(const ClientInfo& client_info) {
+ bool execute_callback = true;
+ // Generate the dump only if it's explicitly requested by the
+ // server application; otherwise the server might want to generate
+ // dump in the callback.
+ std::wstring dump_path;
+ if (generate_dumps_) {
+ if (!GenerateDump(client_info, &dump_path)) {
+ // client proccess terminated or some other error
+ execute_callback = false;
+ }
+ }
+
+ if (dump_callback_ && execute_callback) {
+ dump_callback_(dump_context_, client_info, dump_path);
+ }
+
+ SetEvent(client_info.dump_generated_handle());
+
+ if (written_callback_ && execute_callback) {
+ written_callback_(dump_context_, client_info);
+ }
+}
+
+void CrashGenerationServer::set_include_context_heap(bool enabled) {
+ include_context_heap_ = enabled;
+}
+
+bool CrashGenerationServer::GenerateDump(const ClientInfo& client,
+ std::wstring* dump_path) {
+ assert(client.pid() != 0);
+ assert(client.process_handle());
+
+ DWORD client_thread_id = 0;
+ if (!client.GetClientThreadId(&client_thread_id)) {
+ return false;
+ }
+
+ // We have to get the address of EXCEPTION_INFORMATION from
+ // the client process address space.
+ EXCEPTION_POINTERS* client_ex_info = NULL;
+
+ // Only needs to read the value of a remote pointer in client_ex_info.
+ if (!client.GetClientExceptionInfo(&client_ex_info)) {
+ return false;
+ }
+
+ if (include_context_heap_) {
+ CONTEXT context_content;
+
+ // Needs to read the content of CONTEXT from the client.
+ if (!client.PopulateClientExceptionContext(client_ex_info,
+ &context_content)) {
+ include_context_heap_ = false;
+ }
+
+ // Allocate AppMemory instances for exception context.
+ for (size_t i = 0; i < kExceptionAppMemoryRegions; i++) {
+ AppMemory app_memory;
+ app_memory.ptr = reinterpret_cast<ULONG64>(nullptr);
+ app_memory.length = 0;
+ app_memory.preallocated = true;
+ app_memory_info_.push_back(app_memory);
+ }
+
+ IncludeAppMemoryFromExceptionContext(client.process_handle(),
+ client_thread_id,
+ app_memory_info_,
+ &context_content,
+ !include_context_heap_);
+ }
+
+ MinidumpGenerator dump_generator(dump_path_,
+ client.process_handle(),
+ client.pid(),
+ client_thread_id,
+ GetCurrentThreadId(),
+ client_ex_info,
+ client.assert_info(),
+ client.dump_type(),
+ true);
+
+ MinidumpCallbackContext callback_context;
+ MINIDUMP_CALLBACK_INFORMATION callback;
+ if (include_context_heap_) {
+ // Set memory callback to include heap regions.
+ callback_context.iter = app_memory_info_.cbegin();
+ callback_context.end = app_memory_info_.cend();
+
+ callback.CallbackRoutine = MinidumpWriteDumpCallback;
+ callback.CallbackParam = &callback_context;
+
+ dump_generator.SetCallback(&callback);
+ }
+
+ if (!dump_generator.GenerateDumpFile(dump_path)) {
+ return false;
+ }
+
+ // If the client requests a full memory dump, we will write a normal mini
+ // dump and a full memory dump. Both dump files use the same uuid as file
+ // name prefix.
+ if (client.dump_type() & MiniDumpWithFullMemory) {
+ std::wstring full_dump_path;
+ if (!dump_generator.GenerateFullDumpFile(&full_dump_path)) {
+ return false;
+ }
+ }
+
+ return dump_generator.WriteMinidump();
+}
+
+} // namespace google_breakpad
diff --git a/toolkit/crashreporter/breakpad-client/windows/crash_generation/crash_generation_server.h b/toolkit/crashreporter/breakpad-client/windows/crash_generation/crash_generation_server.h
new file mode 100644
index 0000000000..cc1912cf3c
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/windows/crash_generation/crash_generation_server.h
@@ -0,0 +1,318 @@
+// 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.
+
+#ifndef CLIENT_WINDOWS_CRASH_GENERATION_CRASH_GENERATION_SERVER_H__
+#define CLIENT_WINDOWS_CRASH_GENERATION_CRASH_GENERATION_SERVER_H__
+
+#include <list>
+#include <string>
+#include "windows/common/minidump_callback.h"
+#include "windows/common/ipc_protocol.h"
+#include "windows/crash_generation/minidump_generator.h"
+#include "common/scoped_ptr.h"
+
+namespace google_breakpad {
+class ClientInfo;
+
+// Abstraction for server side implementation of out-of-process crash
+// generation protocol for Windows platform only. It generates Windows
+// minidump files for client processes that request dump generation. When
+// the server is requested to start listening for clients (by calling the
+// Start method), it creates a named pipe and waits for the clients to
+// register. In response, it hands them event handles that the client can
+// signal to request dump generation. When the clients request dump
+// generation in this way, the server generates Windows minidump files.
+class CrashGenerationServer {
+ public:
+ typedef void (*OnClientConnectedCallback)(void* context,
+ const ClientInfo* client_info);
+
+ typedef void (*OnClientDumpRequestCallback)(void* context,
+ const ClientInfo& client_info,
+ const std::wstring& file_path);
+
+ typedef void (*OnClientDumpWrittenCallback)(void* context,
+ const ClientInfo& client_info);
+
+ typedef void (*OnClientExitedCallback)(void* context,
+ const ClientInfo& client_info);
+
+ typedef void (*OnClientUploadRequestCallback)(void* context,
+ const DWORD crash_id);
+
+ // Creates an instance with the given parameters.
+ //
+ // Parameter pipe_name: Name of the Windows named pipe
+ // Parameter pipe_sec_attrs Security attributes to set on the pipe. Pass
+ // NULL to use default security on the pipe. By default, the pipe created
+ // allows Local System, Administrators and the Creator full control and
+ // the Everyone group read access on the pipe.
+ // Parameter connect_callback: Callback for a new client connection.
+ // Parameter connect_context: Context for client connection callback.
+ // Parameter dump_callback: Callback for a client crash dump request.
+ // Parameter dump_context: Context for client crash dump request callback.
+ // Parameter written_callback: Callback called after a crash dump was written.
+ // Parameter exit_callback: Callback for client process exit.
+ // Parameter exit_context: Context for client exit callback.
+ // Parameter generate_dumps: Whether to automatically generate dumps.
+ // Client code of this class might want to generate dumps explicitly in the
+ // crash dump request callback. In that case, false can be passed for this
+ // parameter.
+ // Parameter dump_path: Path for generating dumps; required only if true is
+ // passed for generateDumps parameter; NULL can be passed otherwise.
+ CrashGenerationServer(const std::wstring& pipe_name,
+ SECURITY_ATTRIBUTES* pipe_sec_attrs,
+ OnClientConnectedCallback connect_callback,
+ void* connect_context,
+ OnClientDumpRequestCallback dump_callback,
+ void* dump_context,
+ OnClientDumpWrittenCallback written_callback,
+ OnClientExitedCallback exit_callback,
+ void* exit_context,
+ OnClientUploadRequestCallback upload_request_callback,
+ void* upload_context,
+ bool generate_dumps,
+ const std::wstring* dump_path);
+
+ ~CrashGenerationServer();
+
+ // Performs initialization steps needed to start listening to clients. Upon
+ // successful return clients may connect to this server's pipe.
+ //
+ // Returns true if initialization is successful; false otherwise.
+ bool Start();
+
+ void pre_fetch_custom_info(bool do_pre_fetch) {
+ pre_fetch_custom_info_ = do_pre_fetch;
+ }
+
+ // Calling set_include_context_heap(true) causes heap regions to be included
+ // in the minidump when a crash happens. The heap regions are from the
+ // register values of the client crashing context.
+ void set_include_context_heap(bool enabled);
+
+ private:
+ // Various states the client can be in during the handshake with
+ // the server.
+ enum IPCServerState {
+ // Server starts in this state.
+ IPC_SERVER_STATE_UNINITIALIZED,
+
+ // Server is in error state and it cannot serve any clients.
+ IPC_SERVER_STATE_ERROR,
+
+ // Server starts in this state.
+ IPC_SERVER_STATE_INITIAL,
+
+ // Server has issued an async connect to the pipe and it is waiting
+ // for the connection to be established.
+ IPC_SERVER_STATE_CONNECTING,
+
+ // Server is connected successfully.
+ IPC_SERVER_STATE_CONNECTED,
+
+ // Server has issued an async read from the pipe and it is waiting for
+ // the read to finish.
+ IPC_SERVER_STATE_READING,
+
+ // Server is done reading from the pipe.
+ IPC_SERVER_STATE_READ_DONE,
+
+ // Server has issued an async write to the pipe and it is waiting for
+ // the write to finish.
+ IPC_SERVER_STATE_WRITING,
+
+ // Server is done writing to the pipe.
+ IPC_SERVER_STATE_WRITE_DONE,
+
+ // Server has issued an async read from the pipe for an ack and it
+ // is waiting for the read to finish.
+ IPC_SERVER_STATE_READING_ACK,
+
+ // Server is done writing to the pipe and it is now ready to disconnect
+ // and reconnect.
+ IPC_SERVER_STATE_DISCONNECTING
+ };
+
+ //
+ // Helper methods to handle various server IPC states.
+ //
+ void HandleErrorState();
+ void HandleInitialState();
+ void HandleConnectingState();
+ void HandleConnectedState();
+ void HandleReadingState();
+ void HandleReadDoneState();
+ void HandleWritingState();
+ void HandleWriteDoneState();
+ void HandleReadingAckState();
+ void HandleDisconnectingState();
+
+ // Prepares reply for a client from the given parameters.
+ bool PrepareReply(const ClientInfo& client_info,
+ ProtocolMessage* reply) const;
+
+ // Duplicates various handles in the ClientInfo object for the client
+ // process and stores them in the given ProtocolMessage instance. If
+ // creating any handle fails, ProtocolMessage will contain the handles
+ // already created successfully, which should be closed by the caller.
+ bool CreateClientHandles(const ClientInfo& client_info,
+ ProtocolMessage* reply) const;
+
+ // Response to the given client. Return true if all steps of
+ // responding to the client succeed, false otherwise.
+ bool RespondToClient(ClientInfo* client_info);
+
+ // Handles a connection request from the client.
+ void HandleConnectionRequest();
+
+ // Handles a dump request from the client.
+ void HandleDumpRequest(const ClientInfo& client_info);
+
+ // Callback for pipe connected event.
+ static void CALLBACK OnPipeConnected(void* context, BOOLEAN timer_or_wait);
+
+ // Callback for a dump request.
+ static void CALLBACK OnDumpRequest(void* context, BOOLEAN timer_or_wait);
+
+ // Callback for client process exit event.
+ static void CALLBACK OnClientEnd(void* context, BOOLEAN timer_or_wait);
+
+ // Handles client process exit.
+ void HandleClientProcessExit(ClientInfo* client_info);
+
+ // Adds the given client to the list of registered clients.
+ bool AddClient(ClientInfo* client_info);
+
+ // Generates dump for the given client.
+ bool GenerateDump(const ClientInfo& client, std::wstring* dump_path);
+
+ // Puts the server in a permanent error state and sets a signal such that
+ // the state will be immediately entered after the current state transition
+ // is complete.
+ void EnterErrorState();
+
+ // Puts the server in the specified state and sets a signal such that the
+ // state is immediately entered after the current state transition is
+ // complete.
+ void EnterStateImmediately(IPCServerState state);
+
+ // Puts the server in the specified state. No signal will be set, so the state
+ // transition will only occur when signaled manually or by completion of an
+ // asynchronous IO operation.
+ void EnterStateWhenSignaled(IPCServerState state);
+
+ // Sync object for thread-safe access to the shared list of clients.
+ CRITICAL_SECTION sync_;
+
+ // List of clients.
+ std::list<ClientInfo*> clients_;
+
+ // Pipe name.
+ std::wstring pipe_name_;
+
+ // Pipe security attributes
+ SECURITY_ATTRIBUTES* pipe_sec_attrs_;
+
+ // Handle to the pipe used for handshake with clients.
+ HANDLE pipe_;
+
+ // Pipe wait handle.
+ HANDLE pipe_wait_handle_;
+
+ // Handle to server-alive mutex.
+ HANDLE server_alive_handle_;
+
+ // Callback for a successful client connection.
+ OnClientConnectedCallback connect_callback_;
+
+ // Context for client connected callback.
+ void* connect_context_;
+
+ // Callback for a client dump request.
+ OnClientDumpRequestCallback dump_callback_;
+
+ // Context for client dump request callback.
+ void* dump_context_;
+
+ // Callback for a client dump written.
+ OnClientDumpWrittenCallback written_callback_;
+
+ // Callback for client process exit.
+ OnClientExitedCallback exit_callback_;
+
+ // Context for client process exit callback.
+ void* exit_context_;
+
+ // Callback for upload request.
+ OnClientUploadRequestCallback upload_request_callback_;
+
+ // Context for upload request callback.
+ void* upload_context_;
+
+ // Whether to generate dumps.
+ bool generate_dumps_;
+
+ // Wether to populate custom information up-front.
+ bool pre_fetch_custom_info_;
+
+ // The dump path for the server.
+ const std::wstring dump_path_;
+
+ // State of the server in performing the IPC with the client.
+ // Note that since we restrict the pipe to one instance, we
+ // only need to keep one state of the server. Otherwise, server
+ // would have one state per client it is talking to.
+ IPCServerState server_state_;
+
+ // Whether the server is shutting down.
+ bool shutting_down_;
+
+ // Overlapped instance for async I/O on the pipe.
+ OVERLAPPED overlapped_;
+
+ // Message object used in IPC with the client.
+ ProtocolMessage msg_;
+
+ // Client Info for the client that's connecting to the server.
+ ClientInfo* client_info_;
+
+ // Whether to include heap regions of the crashing context.
+ bool include_context_heap_;
+
+ AppMemoryList app_memory_info_;
+
+ // Disable copy ctor and operator=.
+ CrashGenerationServer(const CrashGenerationServer& crash_server);
+ CrashGenerationServer& operator=(const CrashGenerationServer& crash_server);
+};
+
+} // namespace google_breakpad
+
+#endif // CLIENT_WINDOWS_CRASH_GENERATION_CRASH_GENERATION_SERVER_H__
diff --git a/toolkit/crashreporter/breakpad-client/windows/crash_generation/minidump_generator.cc b/toolkit/crashreporter/breakpad-client/windows/crash_generation/minidump_generator.cc
new file mode 100644
index 0000000000..0e0643c5a1
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/windows/crash_generation/minidump_generator.cc
@@ -0,0 +1,581 @@
+// 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 "windows/crash_generation/minidump_generator.h"
+
+#include <assert.h>
+#include <avrfsdk.h>
+
+#include <algorithm>
+#include <iterator>
+#include <list>
+#include <vector>
+
+#include "windows/common/auto_critical_section.h"
+#include "common/scoped_ptr.h"
+#include "common/windows/guid_string.h"
+
+using std::wstring;
+
+namespace {
+
+// A helper class used to collect handle operations data. Unlike
+// |MiniDumpWithHandleData| it records the operations for a single handle value
+// only, making it possible to include this information to a minidump.
+class HandleTraceData {
+ public:
+ HandleTraceData();
+ ~HandleTraceData();
+
+ // Collects the handle operations data and formats a user stream to be added
+ // to the minidump.
+ bool CollectHandleData(HANDLE process_handle,
+ EXCEPTION_POINTERS* exception_pointers);
+
+ // Fills the user dump entry with a pointer to the collected handle operations
+ // data. Returns |true| if the entry was initialized successfully, or |false|
+ // if no trace data is available.
+ bool GetUserStream(MINIDUMP_USER_STREAM* user_stream);
+
+ private:
+ // Reads the exception code from the client process's address space.
+ // This routine assumes that the client process's pointer width matches ours.
+ static bool ReadExceptionCode(HANDLE process_handle,
+ EXCEPTION_POINTERS* exception_pointers,
+ DWORD* exception_code);
+
+ // Stores handle operations retrieved by VerifierEnumerateResource().
+ static ULONG CALLBACK RecordHandleOperations(void* resource_description,
+ void* enumeration_context,
+ ULONG* enumeration_level);
+
+ // Function pointer type for VerifierEnumerateResource, which is looked up
+ // dynamically.
+ typedef BOOL (WINAPI* VerifierEnumerateResourceType)(
+ HANDLE Process,
+ ULONG Flags,
+ ULONG ResourceType,
+ AVRF_RESOURCE_ENUMERATE_CALLBACK ResourceCallback,
+ PVOID EnumerationContext);
+
+ // Handle to dynamically loaded verifier.dll.
+ HMODULE verifier_module_;
+
+ // Pointer to the VerifierEnumerateResource function.
+ VerifierEnumerateResourceType enumerate_resource_;
+
+ // Handle value to look for.
+ ULONG64 handle_;
+
+ // List of handle operations for |handle_|.
+ std::list<AVRF_HANDLE_OPERATION> operations_;
+
+ // Minidump stream data.
+ std::vector<char> stream_;
+};
+
+HandleTraceData::HandleTraceData()
+ : verifier_module_(NULL),
+ enumerate_resource_(NULL),
+ handle_(NULL) {
+}
+
+HandleTraceData::~HandleTraceData() {
+ if (verifier_module_) {
+ FreeLibrary(verifier_module_);
+ }
+}
+
+bool HandleTraceData::CollectHandleData(
+ HANDLE process_handle,
+ EXCEPTION_POINTERS* exception_pointers) {
+ DWORD exception_code;
+ if (!ReadExceptionCode(process_handle, exception_pointers, &exception_code)) {
+ return false;
+ }
+
+ // Verify whether the execption is STATUS_INVALID_HANDLE. Do not record any
+ // handle information if it is a different exception to keep the minidump
+ // small.
+ if (exception_code != STATUS_INVALID_HANDLE) {
+ return true;
+ }
+
+ // Load verifier!VerifierEnumerateResource() dynamically.
+ verifier_module_ = LoadLibrary(TEXT("verifier.dll"));
+ if (!verifier_module_) {
+ return false;
+ }
+
+ enumerate_resource_ = reinterpret_cast<VerifierEnumerateResourceType>(
+ GetProcAddress(verifier_module_, "VerifierEnumerateResource"));
+ if (!enumerate_resource_) {
+ return false;
+ }
+
+ // STATUS_INVALID_HANDLE does not provide the offending handle value in
+ // the exception parameters so we have to guess. At the moment we scan
+ // the handle operations trace looking for the last invalid handle operation
+ // and record only the operations for that handle value.
+ if (enumerate_resource_(process_handle,
+ 0,
+ AvrfResourceHandleTrace,
+ &RecordHandleOperations,
+ this) != ERROR_SUCCESS) {
+ // The handle tracing must have not been enabled.
+ return true;
+ }
+
+ // Now that |handle_| is initialized, purge all irrelevant operations.
+ std::list<AVRF_HANDLE_OPERATION>::iterator i = operations_.begin();
+ std::list<AVRF_HANDLE_OPERATION>::iterator i_end = operations_.end();
+ while (i != i_end) {
+ if (i->Handle == handle_) {
+ ++i;
+ } else {
+ i = operations_.erase(i);
+ }
+ }
+
+ // Convert the list of recorded operations to a minidump stream.
+ stream_.resize(sizeof(MINIDUMP_HANDLE_OPERATION_LIST) +
+ sizeof(AVRF_HANDLE_OPERATION) * operations_.size());
+
+ MINIDUMP_HANDLE_OPERATION_LIST* stream_data =
+ reinterpret_cast<MINIDUMP_HANDLE_OPERATION_LIST*>(
+ &stream_.front());
+ stream_data->SizeOfHeader = sizeof(MINIDUMP_HANDLE_OPERATION_LIST);
+ stream_data->SizeOfEntry = sizeof(AVRF_HANDLE_OPERATION);
+ stream_data->NumberOfEntries = static_cast<ULONG32>(operations_.size());
+ stream_data->Reserved = 0;
+ std::copy(operations_.begin(),
+ operations_.end(),
+#if defined(_MSC_VER) && !defined(_LIBCPP_STD_VER)
+ stdext::checked_array_iterator<AVRF_HANDLE_OPERATION*>(
+ reinterpret_cast<AVRF_HANDLE_OPERATION*>(stream_data + 1),
+ operations_.size())
+#else
+ reinterpret_cast<AVRF_HANDLE_OPERATION*>(stream_data + 1)
+#endif
+ );
+
+ return true;
+}
+
+bool HandleTraceData::GetUserStream(MINIDUMP_USER_STREAM* user_stream) {
+ if (stream_.empty()) {
+ return false;
+ } else {
+ user_stream->Type = HandleOperationListStream;
+ user_stream->BufferSize = static_cast<ULONG>(stream_.size());
+ user_stream->Buffer = &stream_.front();
+ return true;
+ }
+}
+
+bool HandleTraceData::ReadExceptionCode(
+ HANDLE process_handle,
+ EXCEPTION_POINTERS* exception_pointers,
+ DWORD* exception_code) {
+ EXCEPTION_POINTERS pointers;
+ if (!ReadProcessMemory(process_handle,
+ exception_pointers,
+ &pointers,
+ sizeof(pointers),
+ NULL)) {
+ return false;
+ }
+
+ if (!ReadProcessMemory(process_handle,
+ pointers.ExceptionRecord,
+ exception_code,
+ sizeof(*exception_code),
+ NULL)) {
+ return false;
+ }
+
+ return true;
+}
+
+ULONG CALLBACK HandleTraceData::RecordHandleOperations(
+ void* resource_description,
+ void* enumeration_context,
+ ULONG* enumeration_level) {
+ AVRF_HANDLE_OPERATION* description =
+ reinterpret_cast<AVRF_HANDLE_OPERATION*>(resource_description);
+ HandleTraceData* self =
+ reinterpret_cast<HandleTraceData*>(enumeration_context);
+
+ // Remember the last invalid handle operation.
+ if (description->OperationType == OperationDbBADREF) {
+ self->handle_ = description->Handle;
+ }
+
+ // Record all handle operations.
+ self->operations_.push_back(*description);
+
+ *enumeration_level = HeapEnumerationEverything;
+ return ERROR_SUCCESS;
+}
+
+} // namespace
+
+namespace google_breakpad {
+
+MinidumpGenerator::MinidumpGenerator(
+ const std::wstring& dump_path,
+ const HANDLE process_handle,
+ const DWORD process_id,
+ const DWORD thread_id,
+ const DWORD requesting_thread_id,
+ EXCEPTION_POINTERS* exception_pointers,
+ MDRawAssertionInfo* assert_info,
+ const MINIDUMP_TYPE dump_type,
+ const bool is_client_pointers)
+ : dbghelp_module_(NULL),
+ write_dump_(NULL),
+ rpcrt4_module_(NULL),
+ create_uuid_(NULL),
+ process_handle_(process_handle),
+ process_id_(process_id),
+ thread_id_(thread_id),
+ requesting_thread_id_(requesting_thread_id),
+ exception_pointers_(exception_pointers),
+ assert_info_(assert_info),
+ dump_type_(dump_type),
+ is_client_pointers_(is_client_pointers),
+ dump_path_(dump_path),
+ uuid_generated_(false),
+ dump_file_(INVALID_HANDLE_VALUE),
+ full_dump_file_(INVALID_HANDLE_VALUE),
+ dump_file_is_internal_(false),
+ full_dump_file_is_internal_(false),
+ additional_streams_(NULL),
+ callback_info_(NULL) {
+ uuid_ = {0};
+ InitializeCriticalSection(&module_load_sync_);
+ InitializeCriticalSection(&get_proc_address_sync_);
+}
+
+MinidumpGenerator::~MinidumpGenerator() {
+ if (dump_file_is_internal_ && dump_file_ != INVALID_HANDLE_VALUE) {
+ CloseHandle(dump_file_);
+ }
+
+ if (full_dump_file_is_internal_ && full_dump_file_ != INVALID_HANDLE_VALUE) {
+ CloseHandle(full_dump_file_);
+ }
+
+ if (dbghelp_module_) {
+ FreeLibrary(dbghelp_module_);
+ }
+
+ if (rpcrt4_module_) {
+ FreeLibrary(rpcrt4_module_);
+ }
+
+ DeleteCriticalSection(&get_proc_address_sync_);
+ DeleteCriticalSection(&module_load_sync_);
+}
+
+bool MinidumpGenerator::WriteMinidump() {
+ bool full_memory_dump = (dump_type_ & MiniDumpWithFullMemory) != 0;
+ if (dump_file_ == INVALID_HANDLE_VALUE ||
+ (full_memory_dump && full_dump_file_ == INVALID_HANDLE_VALUE)) {
+ return false;
+ }
+
+ MiniDumpWriteDumpType write_dump = GetWriteDump();
+ if (!write_dump) {
+ return false;
+ }
+
+ MINIDUMP_EXCEPTION_INFORMATION dump_exception_info;
+
+ // Setup the exception information object only if it's a dump
+ // due to an exception.
+ if (exception_pointers_) {
+ dump_exception_info.ThreadId = thread_id_;
+ dump_exception_info.ExceptionPointers = exception_pointers_;
+ dump_exception_info.ClientPointers = is_client_pointers_;
+ }
+
+ // Add an MDRawBreakpadInfo stream to the minidump, to provide additional
+ // information about the exception handler to the Breakpad processor.
+ // The information will help the processor determine which threads are
+ // relevant. The Breakpad processor does not require this information but
+ // can function better with Breakpad-generated dumps when it is present.
+ // The native debugger is not harmed by the presence of this information.
+ MDRawBreakpadInfo breakpad_info = {0};
+ if (!is_client_pointers_) {
+ // Set the dump thread id and requesting thread id only in case of
+ // in-process dump generation.
+ breakpad_info.validity = MD_BREAKPAD_INFO_VALID_DUMP_THREAD_ID |
+ MD_BREAKPAD_INFO_VALID_REQUESTING_THREAD_ID;
+ breakpad_info.dump_thread_id = thread_id_;
+ breakpad_info.requesting_thread_id = requesting_thread_id_;
+ }
+
+ int additional_streams_count = additional_streams_ ?
+ additional_streams_->UserStreamCount : 0;
+ scoped_array<MINIDUMP_USER_STREAM> user_stream_array(
+ new MINIDUMP_USER_STREAM[3 + additional_streams_count]);
+ user_stream_array[0].Type = MD_BREAKPAD_INFO_STREAM;
+ user_stream_array[0].BufferSize = sizeof(breakpad_info);
+ user_stream_array[0].Buffer = &breakpad_info;
+
+ MINIDUMP_USER_STREAM_INFORMATION user_streams;
+ user_streams.UserStreamCount = 1;
+ user_streams.UserStreamArray = user_stream_array.get();
+
+ MDRawAssertionInfo* actual_assert_info = assert_info_;
+ MDRawAssertionInfo client_assert_info = {{0}};
+
+ if (assert_info_) {
+ // If the assertion info object lives in the client process,
+ // read the memory of the client process.
+ if (is_client_pointers_) {
+ SIZE_T bytes_read = 0;
+ if (!ReadProcessMemory(process_handle_,
+ assert_info_,
+ &client_assert_info,
+ sizeof(client_assert_info),
+ &bytes_read)) {
+ if (dump_file_is_internal_)
+ CloseHandle(dump_file_);
+ if (full_dump_file_is_internal_ &&
+ full_dump_file_ != INVALID_HANDLE_VALUE)
+ CloseHandle(full_dump_file_);
+ return false;
+ }
+
+ if (bytes_read != sizeof(client_assert_info)) {
+ if (dump_file_is_internal_)
+ CloseHandle(dump_file_);
+ if (full_dump_file_is_internal_ &&
+ full_dump_file_ != INVALID_HANDLE_VALUE)
+ CloseHandle(full_dump_file_);
+ return false;
+ }
+
+ actual_assert_info = &client_assert_info;
+ }
+
+ user_stream_array[1].Type = MD_ASSERTION_INFO_STREAM;
+ user_stream_array[1].BufferSize = sizeof(MDRawAssertionInfo);
+ user_stream_array[1].Buffer = actual_assert_info;
+ ++user_streams.UserStreamCount;
+ }
+
+ if (additional_streams_) {
+ for (size_t i = 0;
+ i < additional_streams_->UserStreamCount;
+ i++, user_streams.UserStreamCount++) {
+ user_stream_array[user_streams.UserStreamCount].Type =
+ additional_streams_->UserStreamArray[i].Type;
+ user_stream_array[user_streams.UserStreamCount].BufferSize =
+ additional_streams_->UserStreamArray[i].BufferSize;
+ user_stream_array[user_streams.UserStreamCount].Buffer =
+ additional_streams_->UserStreamArray[i].Buffer;
+ }
+ }
+
+ // If the process is terminated by STATUS_INVALID_HANDLE exception store
+ // the trace of operations for the offending handle value. Do nothing special
+ // if the client already requested the handle trace to be stored in the dump.
+ HandleTraceData handle_trace_data;
+ if (exception_pointers_ && (dump_type_ & MiniDumpWithHandleData) == 0) {
+ if (!handle_trace_data.CollectHandleData(process_handle_,
+ exception_pointers_)) {
+ if (dump_file_is_internal_)
+ CloseHandle(dump_file_);
+ if (full_dump_file_is_internal_ &&
+ full_dump_file_ != INVALID_HANDLE_VALUE)
+ CloseHandle(full_dump_file_);
+ return false;
+ }
+ }
+
+ bool result_full_memory = true;
+ if (full_memory_dump) {
+ result_full_memory = write_dump(
+ process_handle_,
+ process_id_,
+ full_dump_file_,
+ static_cast<MINIDUMP_TYPE>((dump_type_ & (~MiniDumpNormal))
+ | MiniDumpWithHandleData),
+ exception_pointers_ ? &dump_exception_info : NULL,
+ &user_streams,
+ NULL) != FALSE;
+ }
+
+ // Add handle operations trace stream to the minidump if it was collected.
+ if (handle_trace_data.GetUserStream(
+ &user_stream_array[user_streams.UserStreamCount])) {
+ ++user_streams.UserStreamCount;
+ }
+
+ bool result_minidump = write_dump(
+ process_handle_,
+ process_id_,
+ dump_file_,
+ static_cast<MINIDUMP_TYPE>((dump_type_ & (~MiniDumpWithFullMemory))
+ | MiniDumpNormal),
+ exception_pointers_ ? &dump_exception_info : NULL,
+ &user_streams,
+ callback_info_) != FALSE;
+
+ return result_minidump && result_full_memory;
+}
+
+bool MinidumpGenerator::GenerateDumpFile(wstring* dump_path) {
+ // The dump file was already set by handle or this function was previously
+ // called.
+ if (dump_file_ != INVALID_HANDLE_VALUE) {
+ return false;
+ }
+
+ wstring dump_file_path;
+ if (!GenerateDumpFilePath(&dump_file_path)) {
+ return false;
+ }
+
+ dump_file_ = CreateFile(dump_file_path.c_str(),
+ GENERIC_WRITE,
+ 0,
+ NULL,
+ CREATE_NEW,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+ if (dump_file_ == INVALID_HANDLE_VALUE) {
+ return false;
+ }
+
+ dump_file_is_internal_ = true;
+ *dump_path = dump_file_path;
+ return true;
+}
+
+bool MinidumpGenerator::GenerateFullDumpFile(wstring* full_dump_path) {
+ // A full minidump was not requested.
+ if ((dump_type_ & MiniDumpWithFullMemory) == 0) {
+ return false;
+ }
+
+ // The dump file was already set by handle or this function was previously
+ // called.
+ if (full_dump_file_ != INVALID_HANDLE_VALUE) {
+ return false;
+ }
+
+ wstring full_dump_file_path;
+ if (!GenerateDumpFilePath(&full_dump_file_path)) {
+ return false;
+ }
+ full_dump_file_path.resize(full_dump_file_path.size() - 4); // strip .dmp
+ full_dump_file_path.append(TEXT("-full.dmp"));
+
+ full_dump_file_ = CreateFile(full_dump_file_path.c_str(),
+ GENERIC_WRITE,
+ 0,
+ NULL,
+ CREATE_NEW,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+ if (full_dump_file_ == INVALID_HANDLE_VALUE) {
+ return false;
+ }
+
+ full_dump_file_is_internal_ = true;
+ *full_dump_path = full_dump_file_path;
+ return true;
+}
+
+HMODULE MinidumpGenerator::GetDbghelpModule() {
+ AutoCriticalSection lock(&module_load_sync_);
+ if (!dbghelp_module_) {
+ dbghelp_module_ = LoadLibrary(TEXT("dbghelp.dll"));
+ }
+
+ return dbghelp_module_;
+}
+
+MinidumpGenerator::MiniDumpWriteDumpType MinidumpGenerator::GetWriteDump() {
+ AutoCriticalSection lock(&get_proc_address_sync_);
+ if (!write_dump_) {
+ HMODULE module = GetDbghelpModule();
+ if (module) {
+ FARPROC proc = GetProcAddress(module, "MiniDumpWriteDump");
+ write_dump_ = reinterpret_cast<MiniDumpWriteDumpType>(proc);
+ }
+ }
+
+ return write_dump_;
+}
+
+HMODULE MinidumpGenerator::GetRpcrt4Module() {
+ AutoCriticalSection lock(&module_load_sync_);
+ if (!rpcrt4_module_) {
+ rpcrt4_module_ = LoadLibrary(TEXT("rpcrt4.dll"));
+ }
+
+ return rpcrt4_module_;
+}
+
+MinidumpGenerator::UuidCreateType MinidumpGenerator::GetCreateUuid() {
+ AutoCriticalSection lock(&module_load_sync_);
+ if (!create_uuid_) {
+ HMODULE module = GetRpcrt4Module();
+ if (module) {
+ FARPROC proc = GetProcAddress(module, "UuidCreate");
+ create_uuid_ = reinterpret_cast<UuidCreateType>(proc);
+ }
+ }
+
+ return create_uuid_;
+}
+
+bool MinidumpGenerator::GenerateDumpFilePath(wstring* file_path) {
+ if (!uuid_generated_) {
+ UuidCreateType create_uuid = GetCreateUuid();
+ if (!create_uuid) {
+ return false;
+ }
+
+ create_uuid(&uuid_);
+ uuid_generated_ = true;
+ }
+
+ wstring id_str = GUIDString::GUIDToWString(&uuid_);
+
+ *file_path = dump_path_ + TEXT("\\") + id_str + TEXT(".dmp");
+ return true;
+}
+
+} // namespace google_breakpad
diff --git a/toolkit/crashreporter/breakpad-client/windows/crash_generation/minidump_generator.h b/toolkit/crashreporter/breakpad-client/windows/crash_generation/minidump_generator.h
new file mode 100644
index 0000000000..a707c0bb1d
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/windows/crash_generation/minidump_generator.h
@@ -0,0 +1,203 @@
+// 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.
+
+#ifndef CLIENT_WINDOWS_CRASH_GENERATION_MINIDUMP_GENERATOR_H_
+#define CLIENT_WINDOWS_CRASH_GENERATION_MINIDUMP_GENERATOR_H_
+
+#include <windows.h>
+#include <dbghelp.h>
+#include <rpc.h>
+#include <list>
+#include <string>
+#include "google_breakpad/common/minidump_format.h"
+
+namespace google_breakpad {
+
+// Abstraction for various objects and operations needed to generate
+// minidump on Windows. This abstraction is useful to hide all the gory
+// details for minidump generation and provide a clean interface to
+// the clients to generate minidumps.
+class MinidumpGenerator {
+ public:
+ // Creates an instance with the given parameters.
+ // is_client_pointers specifies whether the exception_pointers and
+ // assert_info point into the process that is being dumped.
+ // Before calling WriteMinidump on the returned instance a dump file muct be
+ // specified by a call to either SetDumpFile() or GenerateDumpFile().
+ // If a full dump file will be requested via a subsequent call to either
+ // SetFullDumpFile or GenerateFullDumpFile() dump_type must include
+ // MiniDumpWithFullMemory.
+ MinidumpGenerator(const std::wstring& dump_path,
+ const HANDLE process_handle,
+ const DWORD process_id,
+ const DWORD thread_id,
+ const DWORD requesting_thread_id,
+ EXCEPTION_POINTERS* exception_pointers,
+ MDRawAssertionInfo* assert_info,
+ const MINIDUMP_TYPE dump_type,
+ const bool is_client_pointers);
+
+ ~MinidumpGenerator();
+
+ void SetDumpFile(const HANDLE dump_file) { dump_file_ = dump_file; }
+ void SetFullDumpFile(const HANDLE full_dump_file) {
+ full_dump_file_ = full_dump_file;
+ }
+
+ // Generate the name for the dump file that will be written to once
+ // WriteMinidump() is called. Can only be called once and cannot be called
+ // if the dump file is set via SetDumpFile().
+ bool GenerateDumpFile(std::wstring* dump_path);
+
+ // Generate the name for the full dump file that will be written to once
+ // WriteMinidump() is called. Cannot be called unless the minidump type
+ // includes MiniDumpWithFullMemory. Can only be called once and cannot be
+ // called if the dump file is set via SetFullDumpFile().
+ bool GenerateFullDumpFile(std::wstring* full_dump_path);
+
+ void SetAdditionalStreams(
+ MINIDUMP_USER_STREAM_INFORMATION* additional_streams) {
+ additional_streams_ = additional_streams;
+ }
+
+ void SetCallback(MINIDUMP_CALLBACK_INFORMATION* callback_info) {
+ callback_info_ = callback_info;
+ }
+
+ // Writes the minidump with the given parameters. Stores the
+ // dump file path in the dump_path parameter if dump generation
+ // succeeds.
+ bool WriteMinidump();
+
+ private:
+ // Function pointer type for MiniDumpWriteDump, which is looked up
+ // dynamically.
+ typedef BOOL (WINAPI* MiniDumpWriteDumpType)(
+ HANDLE hProcess,
+ DWORD ProcessId,
+ HANDLE hFile,
+ MINIDUMP_TYPE DumpType,
+ CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
+ CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
+ CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam);
+
+ // Function pointer type for UuidCreate, which is looked up dynamically.
+ typedef RPC_STATUS (RPC_ENTRY* UuidCreateType)(UUID* Uuid);
+
+ // Loads the appropriate DLL lazily in a thread safe way.
+ HMODULE GetDbghelpModule();
+
+ // Loads the appropriate DLL and gets a pointer to the MiniDumpWriteDump
+ // function lazily and in a thread-safe manner.
+ MiniDumpWriteDumpType GetWriteDump();
+
+ // Loads the appropriate DLL lazily in a thread safe way.
+ HMODULE GetRpcrt4Module();
+
+ // Loads the appropriate DLL and gets a pointer to the UuidCreate
+ // function lazily and in a thread-safe manner.
+ UuidCreateType GetCreateUuid();
+
+ // Returns the path for the file to write dump to.
+ bool GenerateDumpFilePath(std::wstring* file_path);
+
+ // Handle to dynamically loaded DbgHelp.dll.
+ HMODULE dbghelp_module_;
+
+ // Pointer to the MiniDumpWriteDump function.
+ MiniDumpWriteDumpType write_dump_;
+
+ // Handle to dynamically loaded rpcrt4.dll.
+ HMODULE rpcrt4_module_;
+
+ // Pointer to the UuidCreate function.
+ UuidCreateType create_uuid_;
+
+ // Handle for the process to dump.
+ HANDLE process_handle_;
+
+ // Process ID for the process to dump.
+ DWORD process_id_;
+
+ // The crashing thread ID.
+ DWORD thread_id_;
+
+ // The thread ID which is requesting the dump.
+ DWORD requesting_thread_id_;
+
+ // Pointer to the exception information for the crash. This may point to an
+ // address in the crashing process so it should not be dereferenced.
+ EXCEPTION_POINTERS* exception_pointers_;
+
+ // Assertion info for the report.
+ MDRawAssertionInfo* assert_info_;
+
+ // Type of minidump to generate.
+ MINIDUMP_TYPE dump_type_;
+
+ // Specifies whether the exception_pointers_ reference memory in the crashing
+ // process.
+ bool is_client_pointers_;
+
+ // Folder path to store dump files.
+ std::wstring dump_path_;
+
+ // UUID used to make dump file names.
+ UUID uuid_;
+ bool uuid_generated_;
+
+ // The file where the dump will be written.
+ HANDLE dump_file_;
+
+ // The file where the full dump will be written.
+ HANDLE full_dump_file_;
+
+ // Tracks whether the dump file handle is managed externally.
+ bool dump_file_is_internal_;
+
+ // Tracks whether the full dump file handle is managed externally.
+ bool full_dump_file_is_internal_;
+
+ // Additional streams to be written to the dump.
+ MINIDUMP_USER_STREAM_INFORMATION* additional_streams_;
+
+ // The user defined callback for the various stages of the dump process.
+ MINIDUMP_CALLBACK_INFORMATION* callback_info_;
+
+ // Critical section to sychronize action of loading modules dynamically.
+ CRITICAL_SECTION module_load_sync_;
+
+ // Critical section to synchronize action of dynamically getting function
+ // addresses from modules.
+ CRITICAL_SECTION get_proc_address_sync_;
+};
+
+} // namespace google_breakpad
+
+#endif // CLIENT_WINDOWS_CRASH_GENERATION_MINIDUMP_GENERATOR_H_
diff --git a/toolkit/crashreporter/breakpad-client/windows/crash_generation/objs.mozbuild b/toolkit/crashreporter/breakpad-client/windows/crash_generation/objs.mozbuild
new file mode 100644
index 0000000000..c964936f1d
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/windows/crash_generation/objs.mozbuild
@@ -0,0 +1,17 @@
+# -*- 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_crash_generation = [
+ 'client_info.cc',
+ 'crash_generation_client.cc',
+ 'crash_generation_server.cc',
+ 'minidump_generator.cc',
+]
+
+subdir = 'toolkit/crashreporter/breakpad-client/windows/crash_generation'
+objs_crash_generation = [
+ '/%s/%s' % (subdir, s) for s in lobjs_crash_generation
+]
diff --git a/toolkit/crashreporter/breakpad-client/windows/handler/exception_handler.cc b/toolkit/crashreporter/breakpad-client/windows/handler/exception_handler.cc
new file mode 100644
index 0000000000..281593e4b4
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/windows/handler/exception_handler.cc
@@ -0,0 +1,1121 @@
+// 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 <objbase.h>
+
+#include <algorithm>
+#include <cassert>
+#include <cstdio>
+
+#include "common/windows/string_utils-inl.h"
+
+#include "windows/common/ipc_protocol.h"
+#include "windows/handler/exception_handler.h"
+#include "common/windows/guid_string.h"
+
+#ifdef MOZ_PHC
+#include "replace_malloc_bridge.h"
+#endif
+
+namespace google_breakpad {
+
+// This define is new to Windows 10.
+#ifndef DBG_PRINTEXCEPTION_WIDE_C
+#define DBG_PRINTEXCEPTION_WIDE_C ((DWORD)0x4001000A)
+#endif
+
+vector<ExceptionHandler*>* ExceptionHandler::handler_stack_ = NULL;
+LONG ExceptionHandler::handler_stack_index_ = 0;
+CRITICAL_SECTION ExceptionHandler::handler_stack_critical_section_;
+volatile LONG ExceptionHandler::instance_count_ = 0;
+
+ExceptionHandler::ExceptionHandler(const wstring& dump_path,
+ FilterCallback filter,
+ MinidumpCallback callback,
+ void* callback_context,
+ int handler_types,
+ MINIDUMP_TYPE dump_type,
+ const wchar_t* pipe_name,
+ const CustomClientInfo* custom_info) {
+ Initialize(dump_path,
+ filter,
+ callback,
+ callback_context,
+ handler_types,
+ dump_type,
+ pipe_name,
+ NULL, // pipe_handle
+ NULL, // crash_generation_client
+ custom_info);
+}
+
+ExceptionHandler::ExceptionHandler(const wstring& dump_path,
+ FilterCallback filter,
+ MinidumpCallback callback,
+ void* callback_context,
+ int handler_types,
+ MINIDUMP_TYPE dump_type,
+ HANDLE pipe_handle,
+ const CustomClientInfo* custom_info) {
+ Initialize(dump_path,
+ filter,
+ callback,
+ callback_context,
+ handler_types,
+ dump_type,
+ NULL, // pipe_name
+ pipe_handle,
+ NULL, // crash_generation_client
+ custom_info);
+}
+
+ExceptionHandler::ExceptionHandler(
+ const wstring& dump_path,
+ FilterCallback filter,
+ MinidumpCallback callback,
+ void* callback_context,
+ int handler_types,
+ CrashGenerationClient* crash_generation_client) {
+ // The dump_type, pipe_name and custom_info that are passed in to Initialize()
+ // are not used. The ones set in crash_generation_client are used instead.
+ Initialize(dump_path,
+ filter,
+ callback,
+ callback_context,
+ handler_types,
+ MiniDumpNormal, // dump_type - not used
+ NULL, // pipe_name - not used
+ NULL, // pipe_handle
+ crash_generation_client,
+ NULL); // custom_info - not used
+}
+
+ExceptionHandler::ExceptionHandler(const wstring &dump_path,
+ FilterCallback filter,
+ MinidumpCallback callback,
+ void* callback_context,
+ int handler_types) {
+ Initialize(dump_path,
+ filter,
+ callback,
+ callback_context,
+ handler_types,
+ MiniDumpNormal,
+ NULL, // pipe_name
+ NULL, // pipe_handle
+ NULL, // crash_generation_client
+ NULL); // custom_info
+}
+
+void ExceptionHandler::Initialize(
+ const wstring& dump_path,
+ FilterCallback filter,
+ MinidumpCallback callback,
+ void* callback_context,
+ int handler_types,
+ MINIDUMP_TYPE dump_type,
+ const wchar_t* pipe_name,
+ HANDLE pipe_handle,
+ CrashGenerationClient* crash_generation_client,
+ const CustomClientInfo* custom_info) {
+ LONG instance_count = InterlockedIncrement(&instance_count_);
+ filter_ = filter;
+ callback_ = callback;
+ callback_context_ = callback_context;
+ dump_path_c_ = NULL;
+ next_minidump_id_c_ = NULL;
+ next_minidump_path_c_ = NULL;
+ dbghelp_module_ = NULL;
+ minidump_write_dump_ = NULL;
+ dump_type_ = dump_type;
+ rpcrt4_module_ = NULL;
+ uuid_create_ = NULL;
+ handler_types_ = handler_types;
+ previous_filter_ = NULL;
+#if _MSC_VER >= 1400 // MSVC 2005/8
+ previous_iph_ = NULL;
+#endif // _MSC_VER >= 1400
+ previous_pch_ = NULL;
+ heap_corruption_veh_ = NULL;
+ handler_thread_ = NULL;
+ is_shutdown_ = false;
+ handler_start_semaphore_ = NULL;
+ handler_finish_semaphore_ = NULL;
+ requesting_thread_id_ = 0;
+ exception_info_ = NULL;
+ assertion_ = NULL;
+ handler_return_value_ = MinidumpResult::Failure;
+ handle_debug_exceptions_ = false;
+ consume_invalid_handle_exceptions_ = false;
+
+ // Attempt to use out-of-process if user has specified a pipe or a
+ // crash generation client.
+ scoped_ptr<CrashGenerationClient> client;
+ if (crash_generation_client) {
+ client.reset(crash_generation_client);
+ } else if (pipe_name) {
+ client.reset(
+ new CrashGenerationClient(pipe_name, dump_type_, custom_info));
+ } else if (pipe_handle) {
+ client.reset(
+ new CrashGenerationClient(pipe_handle, dump_type_, custom_info));
+ }
+
+ if (client.get() != NULL) {
+ // If successful in registering with the monitoring process,
+ // there is no need to setup in-process crash generation.
+ if (client->Register()) {
+ crash_generation_client_.reset(client.release());
+ }
+ }
+
+ if (!IsOutOfProcess()) {
+ // Either client did not ask for out-of-process crash generation
+ // or registration with the server process failed. In either case,
+ // setup to do in-process crash generation.
+
+ // Set synchronization primitives and the handler thread. Each
+ // ExceptionHandler object gets its own handler thread because that's the
+ // only way to reliably guarantee sufficient stack space in an exception,
+ // and it allows an easy way to get a snapshot of the requesting thread's
+ // context outside of an exception.
+ InitializeCriticalSection(&handler_critical_section_);
+ handler_start_semaphore_ = CreateSemaphore(NULL, 0, 1, NULL);
+ assert(handler_start_semaphore_ != NULL);
+
+ handler_finish_semaphore_ = CreateSemaphore(NULL, 0, 1, NULL);
+ assert(handler_finish_semaphore_ != NULL);
+
+ // Don't attempt to create the thread if we could not create the semaphores.
+ if (handler_finish_semaphore_ != NULL && handler_start_semaphore_ != NULL) {
+ DWORD thread_id;
+ const int kExceptionHandlerThreadInitialStackSize = 64 * 1024;
+ handler_thread_ = CreateThread(NULL, // lpThreadAttributes
+ kExceptionHandlerThreadInitialStackSize,
+ ExceptionHandlerThreadMain,
+ this, // lpParameter
+ 0, // dwCreationFlags
+ &thread_id);
+ assert(handler_thread_ != NULL);
+ }
+
+ dbghelp_module_ = LoadLibrary(L"dbghelp.dll");
+ if (dbghelp_module_) {
+ minidump_write_dump_ = reinterpret_cast<MiniDumpWriteDump_type>(
+ GetProcAddress(dbghelp_module_, "MiniDumpWriteDump"));
+ }
+
+ // Load this library dynamically to not affect existing projects. Most
+ // projects don't link against this directly, it's usually dynamically
+ // loaded by dependent code.
+ rpcrt4_module_ = LoadLibrary(L"rpcrt4.dll");
+ if (rpcrt4_module_) {
+ uuid_create_ = reinterpret_cast<UuidCreate_type>(
+ GetProcAddress(rpcrt4_module_, "UuidCreate"));
+ }
+
+ // set_dump_path calls UpdateNextID. This sets up all of the path and id
+ // strings, and their equivalent c_str pointers.
+ set_dump_path(dump_path);
+ }
+
+ // Reserve one element for the instruction memory
+ AppMemory instruction_memory;
+ instruction_memory.ptr = NULL;
+ instruction_memory.length = 0;
+ instruction_memory.preallocated = true;
+ app_memory_info_.push_back(instruction_memory);
+
+ // There is a race condition here. If the first instance has not yet
+ // initialized the critical section, the second (and later) instances may
+ // try to use uninitialized critical section object. The feature of multiple
+ // instances in one module is not used much, so leave it as is for now.
+ // One way to solve this in the current design (that is, keeping the static
+ // handler stack) is to use spin locks with volatile bools to synchronize
+ // the handler stack. This works only if the compiler guarantees to generate
+ // cache coherent code for volatile.
+ // TODO(munjal): Fix this in a better way by changing the design if possible.
+
+ // Lazy initialization of the handler_stack_critical_section_
+ if (instance_count == 1) {
+ InitializeCriticalSection(&handler_stack_critical_section_);
+ }
+
+ if (handler_types != HANDLER_NONE) {
+ EnterCriticalSection(&handler_stack_critical_section_);
+
+ // The first time an ExceptionHandler that installs a handler is
+ // created, set up the handler stack.
+ if (!handler_stack_) {
+ handler_stack_ = new vector<ExceptionHandler*>();
+ }
+ handler_stack_->push_back(this);
+
+ if (handler_types & HANDLER_EXCEPTION)
+ previous_filter_ = SetUnhandledExceptionFilter(HandleException);
+
+#if _MSC_VER >= 1400 // MSVC 2005/8
+ if (handler_types & HANDLER_INVALID_PARAMETER)
+ previous_iph_ = _set_invalid_parameter_handler(HandleInvalidParameter);
+#endif // _MSC_VER >= 1400
+
+ if (handler_types & HANDLER_PURECALL)
+ previous_pch_ = _set_purecall_handler(HandlePureVirtualCall);
+
+ if (handler_types & HANDLER_HEAP_CORRUPTION) {
+ // Under ASan we need to let the ASan runtime's ShadowExceptionHandler stay
+ // in the first handler position.
+#ifdef MOZ_ASAN
+ const bool first = false;
+#else
+ const bool first = true;
+#endif // MOZ_ASAN
+ heap_corruption_veh_ =
+ AddVectoredExceptionHandler(first, HandleHeapCorruption);
+ }
+
+ LeaveCriticalSection(&handler_stack_critical_section_);
+ }
+
+ include_context_heap_ = false;
+}
+
+ExceptionHandler::~ExceptionHandler() {
+ if (handler_types_ != HANDLER_NONE) {
+ EnterCriticalSection(&handler_stack_critical_section_);
+
+ if (handler_types_ & HANDLER_EXCEPTION)
+ SetUnhandledExceptionFilter(previous_filter_);
+
+#if _MSC_VER >= 1400 // MSVC 2005/8
+ if (handler_types_ & HANDLER_INVALID_PARAMETER)
+ _set_invalid_parameter_handler(previous_iph_);
+#endif // _MSC_VER >= 1400
+
+ if (handler_types_ & HANDLER_PURECALL)
+ _set_purecall_handler(previous_pch_);
+
+ if (handler_types_ & HANDLER_HEAP_CORRUPTION)
+ RemoveVectoredExceptionHandler(heap_corruption_veh_);
+
+ if (handler_stack_->back() == this) {
+ handler_stack_->pop_back();
+ } else {
+ // TODO(mmentovai): use advapi32!ReportEvent to log the warning to the
+ // system's application event log.
+ fprintf(stderr, "warning: removing Breakpad handler out of order\n");
+ vector<ExceptionHandler*>::iterator iterator = handler_stack_->begin();
+ while (iterator != handler_stack_->end()) {
+ if (*iterator == this) {
+ iterator = handler_stack_->erase(iterator);
+ } else {
+ ++iterator;
+ }
+ }
+ }
+
+ if (handler_stack_->empty()) {
+ // When destroying the last ExceptionHandler that installed a handler,
+ // clean up the handler stack.
+ delete handler_stack_;
+ handler_stack_ = NULL;
+ }
+
+ LeaveCriticalSection(&handler_stack_critical_section_);
+ }
+
+ // Some of the objects were only initialized if out of process
+ // registration was not done.
+ if (!IsOutOfProcess()) {
+#ifdef BREAKPAD_NO_TERMINATE_THREAD
+ // Clean up the handler thread and synchronization primitives. The handler
+ // thread is either waiting on the semaphore to handle a crash or it is
+ // handling a crash. Coming out of the wait is fast but wait more in the
+ // eventuality a crash is handled. This compilation option results in a
+ // deadlock if the exception handler is destroyed while executing code
+ // inside DllMain.
+ is_shutdown_ = true;
+ ReleaseSemaphore(handler_start_semaphore_, 1, NULL);
+ const int kWaitForHandlerThreadMs = 60000;
+ WaitForSingleObject(handler_thread_, kWaitForHandlerThreadMs);
+#else
+ TerminateThread(handler_thread_, 1);
+#endif // BREAKPAD_NO_TERMINATE_THREAD
+
+ CloseHandle(handler_thread_);
+ handler_thread_ = NULL;
+ DeleteCriticalSection(&handler_critical_section_);
+ CloseHandle(handler_start_semaphore_);
+ CloseHandle(handler_finish_semaphore_);
+ }
+
+ // There is a race condition in the code below: if this instance is
+ // deleting the static critical section and a new instance of the class
+ // is created, then there is a possibility that the critical section be
+ // initialized while the same critical section is being deleted. Given the
+ // usage pattern for the code, this race condition is unlikely to hit, but it
+ // is a race condition nonetheless.
+ if (InterlockedDecrement(&instance_count_) == 0) {
+ DeleteCriticalSection(&handler_stack_critical_section_);
+ }
+
+ // The exception handler is not set anymore and the handler thread which
+ // could call MiniDumpWriteDump() has been shut down; it is now safe to
+ // unload these modules.
+ if (dbghelp_module_) {
+ FreeLibrary(dbghelp_module_);
+ }
+
+ if (rpcrt4_module_) {
+ FreeLibrary(rpcrt4_module_);
+ }
+}
+
+bool ExceptionHandler::RequestUpload(DWORD crash_id) {
+ return crash_generation_client_->RequestUpload(crash_id);
+}
+
+// The SetThreadDescription API was brought in version 1607 of Windows 10.
+typedef HRESULT(WINAPI* SetThreadDescriptionPtr)(HANDLE hThread,
+ PCWSTR lpThreadDescription);
+
+// static
+DWORD ExceptionHandler::ExceptionHandlerThreadMain(void* lpParameter) {
+ HMODULE handle = ::GetModuleHandle(L"Kernel32.dll");
+ if (handle) {
+ if (FARPROC address = ::GetProcAddress(handle, "SetThreadDescription")) {
+ auto SetThreadDescriptionFunc =
+ reinterpret_cast<SetThreadDescriptionPtr>(address);
+ SetThreadDescriptionFunc(::GetCurrentThread(),
+ L"Breakpad ExceptionHandler");
+ }
+ }
+
+ ExceptionHandler* self = reinterpret_cast<ExceptionHandler *>(lpParameter);
+ assert(self);
+ assert(self->handler_start_semaphore_ != NULL);
+ assert(self->handler_finish_semaphore_ != NULL);
+
+ for (;;) {
+ if (WaitForSingleObject(self->handler_start_semaphore_, INFINITE) ==
+ WAIT_OBJECT_0) {
+ // Perform the requested action.
+ if (self->is_shutdown_) {
+ // The instance of the exception handler is being destroyed.
+ break;
+ } else {
+ self->handler_return_value_ =
+ self->WriteMinidumpWithException(self->requesting_thread_id_,
+ self->exception_info_,
+ self->assertion_);
+ }
+
+ // Allow the requesting thread to proceed.
+ ReleaseSemaphore(self->handler_finish_semaphore_, 1, NULL);
+ }
+ }
+
+ // This statement is not reached when the thread is unconditionally
+ // terminated by the ExceptionHandler destructor.
+ return 0;
+}
+
+// HandleException and HandleInvalidParameter must create an
+// AutoExceptionHandler object to maintain static state and to determine which
+// ExceptionHandler instance to use. The constructor locates the correct
+// instance, and makes it available through get_handler(). The destructor
+// restores the state in effect prior to allocating the AutoExceptionHandler.
+class AutoExceptionHandler {
+ public:
+ AutoExceptionHandler() {
+ // Increment handler_stack_index_ so that if another Breakpad handler is
+ // registered using this same HandleException function, and it needs to be
+ // called while this handler is running (either because this handler
+ // declines to handle the exception, or an exception occurs during
+ // handling), HandleException will find the appropriate ExceptionHandler
+ // object in handler_stack_ to deliver the exception to.
+ //
+ // Because handler_stack_ is addressed in reverse (as |size - index|),
+ // preincrementing handler_stack_index_ avoids needing to subtract 1 from
+ // the argument to |at|.
+ //
+ // The index is maintained instead of popping elements off of the handler
+ // stack and pushing them at the end of this method. This avoids ruining
+ // the order of elements in the stack in the event that some other thread
+ // decides to manipulate the handler stack (such as creating a new
+ // ExceptionHandler object) while an exception is being handled.
+ EnterCriticalSection(&ExceptionHandler::handler_stack_critical_section_);
+ handler_ = ExceptionHandler::handler_stack_->at(
+ ExceptionHandler::handler_stack_->size() -
+ ++ExceptionHandler::handler_stack_index_);
+
+ // In case another exception occurs while this handler is doing its thing,
+ // it should be delivered to the previous filter.
+ SetUnhandledExceptionFilter(handler_->previous_filter_);
+#if _MSC_VER >= 1400 // MSVC 2005/8
+ _set_invalid_parameter_handler(handler_->previous_iph_);
+#endif // _MSC_VER >= 1400
+ _set_purecall_handler(handler_->previous_pch_);
+ }
+
+ ~AutoExceptionHandler() {
+ // Put things back the way they were before entering this handler.
+ SetUnhandledExceptionFilter(ExceptionHandler::HandleException);
+#if _MSC_VER >= 1400 // MSVC 2005/8
+ _set_invalid_parameter_handler(ExceptionHandler::HandleInvalidParameter);
+#endif // _MSC_VER >= 1400
+ _set_purecall_handler(ExceptionHandler::HandlePureVirtualCall);
+
+ --ExceptionHandler::handler_stack_index_;
+ LeaveCriticalSection(&ExceptionHandler::handler_stack_critical_section_);
+ }
+
+ ExceptionHandler* get_handler() const { return handler_; }
+
+ private:
+ ExceptionHandler* handler_;
+};
+
+// static
+LONG ExceptionHandler::HandleException(EXCEPTION_POINTERS* exinfo) {
+ AutoExceptionHandler auto_exception_handler;
+ ExceptionHandler* current_handler = auto_exception_handler.get_handler();
+
+ // Ignore EXCEPTION_BREAKPOINT and EXCEPTION_SINGLE_STEP exceptions. This
+ // logic will short-circuit before calling WriteMinidumpOnHandlerThread,
+ // allowing something else to handle the breakpoint without incurring the
+ // overhead transitioning to and from the handler thread. This behavior
+ // can be overridden by calling ExceptionHandler::set_handle_debug_exceptions.
+ DWORD code = exinfo->ExceptionRecord->ExceptionCode;
+ LONG action;
+ bool is_debug_exception = (code == EXCEPTION_BREAKPOINT) ||
+ (code == EXCEPTION_SINGLE_STEP) ||
+ (code == DBG_PRINTEXCEPTION_C) ||
+ (code == DBG_PRINTEXCEPTION_WIDE_C);
+
+ if (code == EXCEPTION_INVALID_HANDLE &&
+ current_handler->consume_invalid_handle_exceptions_) {
+ return EXCEPTION_CONTINUE_EXECUTION;
+ }
+
+ MinidumpResult result = MinidumpResult::Failure;
+
+ if (!is_debug_exception ||
+ current_handler->get_handle_debug_exceptions()) {
+ // If out-of-proc crash handler client is available, we have to use that
+ // to generate dump and we cannot fall back on in-proc dump generation
+ // because we never prepared for an in-proc dump generation
+
+ // In case of out-of-process dump generation, directly call
+ // WriteMinidumpWithException since there is no separate thread running.
+ if (current_handler->IsOutOfProcess()) {
+ result = current_handler->WriteMinidumpWithException(
+ GetCurrentThreadId(),
+ exinfo,
+ NULL);
+ } else {
+ result = current_handler->WriteMinidumpOnHandlerThread(exinfo, NULL)
+ ? MinidumpResult::Success : MinidumpResult::Failure;
+ }
+ }
+
+ // The handler fully handled the exception. Returning
+ // EXCEPTION_EXECUTE_HANDLER indicates this to the system, and usually
+ // results in the application being terminated.
+ //
+ // Note: If the application was launched from within the Cygwin
+ // environment, returning EXCEPTION_EXECUTE_HANDLER seems to cause the
+ // application to be restarted.
+ if ((result == MinidumpResult::Success) ||
+ (result == MinidumpResult::Ignored)) {
+ action = EXCEPTION_EXECUTE_HANDLER;
+ } else {
+ // There was an exception, it was a breakpoint or something else ignored
+ // above, or it was passed to the handler, which decided not to handle it.
+ // This could be because the filter callback didn't want it, because
+ // minidump writing failed for some reason, or because the post-minidump
+ // callback function indicated failure. Give the previous handler a
+ // chance to do something with the exception. If there is no previous
+ // handler, return EXCEPTION_CONTINUE_SEARCH, which will allow a debugger
+ // or native "crashed" dialog to handle the exception.
+ if (current_handler->previous_filter_) {
+ action = current_handler->previous_filter_(exinfo);
+ } else {
+ action = EXCEPTION_CONTINUE_SEARCH;
+ }
+ }
+
+ return action;
+}
+
+#if _MSC_VER >= 1400 // MSVC 2005/8
+// static
+void ExceptionHandler::HandleInvalidParameter(const wchar_t* expression,
+ const wchar_t* function,
+ const wchar_t* file,
+ unsigned int line,
+ uintptr_t reserved) {
+ // This is an invalid parameter, not an exception. It's safe to play with
+ // sprintf here.
+ AutoExceptionHandler auto_exception_handler;
+ ExceptionHandler* current_handler = auto_exception_handler.get_handler();
+
+ MDRawAssertionInfo assertion;
+ memset(&assertion, 0, sizeof(assertion));
+ _snwprintf_s(reinterpret_cast<wchar_t*>(assertion.expression),
+ sizeof(assertion.expression) / sizeof(assertion.expression[0]),
+ _TRUNCATE, L"%s", expression);
+ _snwprintf_s(reinterpret_cast<wchar_t*>(assertion.function),
+ sizeof(assertion.function) / sizeof(assertion.function[0]),
+ _TRUNCATE, L"%s", function);
+ _snwprintf_s(reinterpret_cast<wchar_t*>(assertion.file),
+ sizeof(assertion.file) / sizeof(assertion.file[0]),
+ _TRUNCATE, L"%s", file);
+ assertion.line = line;
+ assertion.type = MD_ASSERTION_INFO_TYPE_INVALID_PARAMETER;
+
+ // Make up an exception record for the current thread and CPU context
+ // to make it possible for the crash processor to classify these
+ // as do regular crashes, and to make it humane for developers to
+ // analyze them.
+ EXCEPTION_RECORD exception_record = {};
+ CONTEXT exception_context = {};
+ EXCEPTION_POINTERS exception_ptrs = { &exception_record, &exception_context };
+
+ ::RtlCaptureContext(&exception_context);
+
+ exception_record.ExceptionCode = STATUS_INVALID_PARAMETER;
+
+ // We store pointers to the the expression and function strings,
+ // and the line as exception parameters to make them easy to
+ // access by the developer on the far side.
+ exception_record.NumberParameters = 3;
+ exception_record.ExceptionInformation[0] =
+ reinterpret_cast<ULONG_PTR>(&assertion.expression);
+ exception_record.ExceptionInformation[1] =
+ reinterpret_cast<ULONG_PTR>(&assertion.file);
+ exception_record.ExceptionInformation[2] = assertion.line;
+
+ bool success = false;
+ // In case of out-of-process dump generation, directly call
+ // WriteMinidumpWithException since there is no separate thread running.
+ if (current_handler->IsOutOfProcess()) {
+ success = current_handler->WriteMinidumpWithException(
+ GetCurrentThreadId(),
+ &exception_ptrs,
+ &assertion) == MinidumpResult::Success;
+ } else {
+ success = current_handler->WriteMinidumpOnHandlerThread(&exception_ptrs,
+ &assertion);
+ }
+
+ if (!success) {
+ if (current_handler->previous_iph_) {
+ // The handler didn't fully handle the exception. Give it to the
+ // previous invalid parameter handler.
+ current_handler->previous_iph_(expression,
+ function,
+ file,
+ line,
+ reserved);
+ } else {
+ // If there's no previous handler, pass the exception back in to the
+ // invalid parameter handler's core. That's the routine that called this
+ // function, but now, since this function is no longer registered (and in
+ // fact, no function at all is registered), this will result in the
+ // default code path being taken: _CRT_DEBUGGER_HOOK and _invoke_watson.
+ // Use _invalid_parameter where it exists (in _DEBUG builds) as it passes
+ // more information through. In non-debug builds, it is not available,
+ // so fall back to using _invalid_parameter_noinfo. See invarg.c in the
+ // CRT source.
+#ifdef _DEBUG
+ _invalid_parameter(expression, function, file, line, reserved);
+#else // _DEBUG
+ _invalid_parameter_noinfo();
+#endif // _DEBUG
+ }
+ }
+
+ // The handler either took care of the invalid parameter problem itself,
+ // or passed it on to another handler. "Swallow" it by exiting, paralleling
+ // the behavior of "swallowing" exceptions.
+ exit(0);
+}
+#endif // _MSC_VER >= 1400
+
+// static
+void ExceptionHandler::HandlePureVirtualCall() {
+ // This is an pure virtual function call, not an exception. It's safe to
+ // play with sprintf here.
+ AutoExceptionHandler auto_exception_handler;
+ ExceptionHandler* current_handler = auto_exception_handler.get_handler();
+
+ MDRawAssertionInfo assertion;
+ memset(&assertion, 0, sizeof(assertion));
+ assertion.type = MD_ASSERTION_INFO_TYPE_PURE_VIRTUAL_CALL;
+
+ // Make up an exception record for the current thread and CPU context
+ // to make it possible for the crash processor to classify these
+ // as do regular crashes, and to make it humane for developers to
+ // analyze them.
+ EXCEPTION_RECORD exception_record = {};
+ CONTEXT exception_context = {};
+ EXCEPTION_POINTERS exception_ptrs = { &exception_record, &exception_context };
+
+ ::RtlCaptureContext(&exception_context);
+
+ exception_record.ExceptionCode = STATUS_NONCONTINUABLE_EXCEPTION;
+
+ // We store pointers to the the expression and function strings,
+ // and the line as exception parameters to make them easy to
+ // access by the developer on the far side.
+ exception_record.NumberParameters = 3;
+ exception_record.ExceptionInformation[0] =
+ reinterpret_cast<ULONG_PTR>(&assertion.expression);
+ exception_record.ExceptionInformation[1] =
+ reinterpret_cast<ULONG_PTR>(&assertion.file);
+ exception_record.ExceptionInformation[2] = assertion.line;
+
+ bool success = false;
+ // In case of out-of-process dump generation, directly call
+ // WriteMinidumpWithException since there is no separate thread running.
+
+ if (current_handler->IsOutOfProcess()) {
+ success = current_handler->WriteMinidumpWithException(
+ GetCurrentThreadId(),
+ &exception_ptrs,
+ &assertion) == MinidumpResult::Success;
+ } else {
+ success = current_handler->WriteMinidumpOnHandlerThread(&exception_ptrs,
+ &assertion);
+ }
+
+ if (!success) {
+ if (current_handler->previous_pch_) {
+ // The handler didn't fully handle the exception. Give it to the
+ // previous purecall handler.
+ current_handler->previous_pch_();
+ } else {
+ // If there's no previous handler, return and let _purecall handle it.
+ // This will just put up an assertion dialog.
+ return;
+ }
+ }
+
+ // The handler either took care of the invalid parameter problem itself,
+ // or passed it on to another handler. "Swallow" it by exiting, paralleling
+ // the behavior of "swallowing" exceptions.
+ exit(0);
+}
+
+// static
+LONG ExceptionHandler::HandleHeapCorruption(EXCEPTION_POINTERS* exinfo) {
+ if (exinfo->ExceptionRecord->ExceptionCode != STATUS_HEAP_CORRUPTION) {
+ return EXCEPTION_CONTINUE_SEARCH;
+ }
+
+ AutoExceptionHandler auto_exception_handler;
+ ExceptionHandler* current_handler = auto_exception_handler.get_handler();
+
+ bool result = false;
+
+ // In case of out-of-process dump generation, directly call
+ // WriteMinidumpWithException since there is no separate thread running.
+ if (current_handler->IsOutOfProcess()) {
+ result = current_handler->WriteMinidumpWithException(
+ GetCurrentThreadId(), exinfo, NULL) == MinidumpResult::Success;
+ } else {
+ result = current_handler->WriteMinidumpOnHandlerThread(exinfo, NULL);
+ }
+
+ return result ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH;
+}
+
+bool ExceptionHandler::WriteMinidumpOnHandlerThread(
+ EXCEPTION_POINTERS* exinfo, MDRawAssertionInfo* assertion) {
+ EnterCriticalSection(&handler_critical_section_);
+
+ // There isn't much we can do if the handler thread
+ // was not successfully created.
+ if (handler_thread_ == NULL) {
+ LeaveCriticalSection(&handler_critical_section_);
+ return false;
+ }
+
+ // The handler thread should only be created when the semaphores are valid.
+ assert(handler_start_semaphore_ != NULL);
+ assert(handler_finish_semaphore_ != NULL);
+
+ // Set up data to be passed in to the handler thread.
+ requesting_thread_id_ = GetCurrentThreadId();
+ exception_info_ = exinfo;
+ assertion_ = assertion;
+
+ // This causes the handler thread to call WriteMinidumpWithException.
+ ReleaseSemaphore(handler_start_semaphore_, 1, NULL);
+
+ // Wait until WriteMinidumpWithException is done and collect its return value.
+ WaitForSingleObject(handler_finish_semaphore_, INFINITE);
+ bool status = (handler_return_value_ == MinidumpResult::Success);
+
+ // Clean up.
+ requesting_thread_id_ = 0;
+ exception_info_ = NULL;
+ assertion_ = NULL;
+
+ LeaveCriticalSection(&handler_critical_section_);
+
+ return status;
+}
+
+bool ExceptionHandler::WriteMinidump() {
+ // Make up an exception record for the current thread and CPU context
+ // to make it possible for the crash processor to classify these
+ // as do regular crashes, and to make it humane for developers to
+ // analyze them.
+ EXCEPTION_RECORD exception_record = {};
+ CONTEXT exception_context = {};
+ EXCEPTION_POINTERS exception_ptrs = { &exception_record, &exception_context };
+
+ ::RtlCaptureContext(&exception_context);
+ exception_record.ExceptionCode = STATUS_NONCONTINUABLE_EXCEPTION;
+
+ return WriteMinidumpForException(&exception_ptrs);
+}
+
+bool ExceptionHandler::WriteMinidumpForException(EXCEPTION_POINTERS* exinfo) {
+ // In case of out-of-process dump generation, directly call
+ // WriteMinidumpWithException since there is no separate thread running.
+ if (IsOutOfProcess()) {
+ return WriteMinidumpWithException(GetCurrentThreadId(),
+ exinfo,
+ NULL) == MinidumpResult::Success;
+ }
+
+ bool success = WriteMinidumpOnHandlerThread(exinfo, NULL);
+ UpdateNextID();
+ return success;
+}
+
+// static
+bool ExceptionHandler::WriteMinidump(const wstring &dump_path,
+ MinidumpCallback callback,
+ void* callback_context,
+ MINIDUMP_TYPE dump_type) {
+ ExceptionHandler handler(dump_path, NULL, callback, callback_context,
+ HANDLER_NONE, dump_type, (HANDLE)NULL, NULL);
+ return handler.WriteMinidump();
+}
+
+// static
+bool ExceptionHandler::WriteMinidumpForChild(HANDLE child,
+ DWORD child_blamed_thread,
+ const wstring& dump_path,
+ MinidumpCallback callback,
+ void* callback_context,
+ MINIDUMP_TYPE dump_type) {
+ EXCEPTION_RECORD ex;
+ CONTEXT ctx;
+ EXCEPTION_POINTERS exinfo = { NULL, NULL };
+ // As documented on MSDN, on failure SuspendThread returns (DWORD) -1
+ const DWORD kFailedToSuspendThread = static_cast<DWORD>(-1);
+ DWORD last_suspend_count = kFailedToSuspendThread;
+ HANDLE child_thread_handle = OpenThread(THREAD_GET_CONTEXT |
+ THREAD_QUERY_INFORMATION |
+ THREAD_SUSPEND_RESUME,
+ FALSE,
+ child_blamed_thread);
+ // This thread may have died already, so not opening the handle is a
+ // non-fatal error.
+ if (child_thread_handle != NULL) {
+ last_suspend_count = SuspendThread(child_thread_handle);
+ if (last_suspend_count != kFailedToSuspendThread) {
+ ctx.ContextFlags = CONTEXT_ALL;
+ if (GetThreadContext(child_thread_handle, &ctx)) {
+ memset(&ex, 0, sizeof(ex));
+ ex.ExceptionCode = EXCEPTION_BREAKPOINT;
+#if defined(_M_IX86)
+ ex.ExceptionAddress = reinterpret_cast<PVOID>(ctx.Eip);
+#elif defined(_M_X64)
+ ex.ExceptionAddress = reinterpret_cast<PVOID>(ctx.Rip);
+#endif
+ exinfo.ExceptionRecord = &ex;
+ exinfo.ContextRecord = &ctx;
+ }
+ }
+ }
+
+ ExceptionHandler handler(dump_path, NULL, callback, callback_context,
+ HANDLER_NONE, dump_type, (HANDLE)NULL, NULL);
+ bool success = handler.WriteMinidumpWithExceptionForProcess(
+ child_blamed_thread,
+ exinfo.ExceptionRecord ? &exinfo : NULL,
+ NULL, child, false);
+
+ if (last_suspend_count != kFailedToSuspendThread) {
+ ResumeThread(child_thread_handle);
+ }
+
+ CloseHandle(child_thread_handle);
+
+ if (callback) {
+ // nullptr here for phc::AddrInfo* is ok because this is not a crash.
+ success = callback(handler.dump_path_c_, handler.next_minidump_id_c_,
+ callback_context, NULL, NULL, nullptr, success);
+ }
+
+ return success;
+}
+
+#ifdef MOZ_PHC
+static void GetPHCAddrInfo(EXCEPTION_POINTERS* exinfo,
+ mozilla::phc::AddrInfo* addr_info) {
+ // Is this a crash involving a PHC allocation?
+ PEXCEPTION_RECORD rec = exinfo->ExceptionRecord;
+ if (rec->ExceptionCode == EXCEPTION_ACCESS_VIOLATION) {
+ // rec->ExceptionInformation[0] contains a value indicating what type of
+ // operation it what, and rec->ExceptionInformation[1] contains the
+ // virtual address of the inaccessible data.
+ char* crashAddr = reinterpret_cast<char*>(rec->ExceptionInformation[1]);
+ ReplaceMalloc::IsPHCAllocation(crashAddr, addr_info);
+ }
+}
+#endif
+
+ExceptionHandler::MinidumpResult ExceptionHandler::WriteMinidumpWithException(
+ DWORD requesting_thread_id,
+ EXCEPTION_POINTERS* exinfo,
+ MDRawAssertionInfo* assertion) {
+ mozilla::phc::AddrInfo addr_info;
+#ifdef MOZ_PHC
+ GetPHCAddrInfo(exinfo, &addr_info);
+#endif
+
+ // Give user code a chance to approve or prevent writing a minidump. If the
+ // filter returns Failure or Ignored , don't handle the exception and return
+ // the result for further handling downstream. If this method was called as a
+ // result of an exception, returning Failure will cause HandleException to
+ // call any previous handler or return EXCEPTION_CONTINUE_SEARCH on the
+ // exception thread, allowing it to appear as though this handler were not
+ // present at all.
+ if (filter_) {
+ switch (filter_(callback_context_, exinfo, assertion)) {
+ case FilterResult::HandleException: break;
+ case FilterResult::AbortWithoutMinidump: return MinidumpResult::Ignored;
+ case FilterResult::ContinueSearch: return MinidumpResult::Failure;
+ }
+ }
+
+ bool success = false;
+ if (IsOutOfProcess()) {
+ success = crash_generation_client_->RequestDump(exinfo, assertion);
+ } else {
+ success = WriteMinidumpWithExceptionForProcess(requesting_thread_id,
+ exinfo,
+ assertion,
+ GetCurrentProcess(),
+ true);
+ }
+
+ if (callback_) {
+ // TODO(munjal): In case of out-of-process dump generation, both
+ // dump_path_c_ and next_minidump_id_ will be NULL. For out-of-process
+ // scenario, the server process ends up creating the dump path and dump
+ // id so they are not known to the client.
+ success = callback_(dump_path_c_, next_minidump_id_c_, callback_context_,
+ exinfo, assertion, &addr_info, success);
+ }
+
+ return success ? MinidumpResult::Success : MinidumpResult::Failure;
+}
+
+// static
+bool ExceptionHandler::WriteMinidumpWithExceptionForProcess(
+ DWORD requesting_thread_id,
+ EXCEPTION_POINTERS* exinfo,
+ MDRawAssertionInfo* assertion,
+ HANDLE process,
+ bool write_requester_stream) {
+ bool success = false;
+ if (minidump_write_dump_) {
+ HANDLE dump_file = CreateFile(next_minidump_path_c_,
+ GENERIC_WRITE,
+ 0, // no sharing
+ NULL,
+ CREATE_NEW, // fail if exists
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+ if (dump_file != INVALID_HANDLE_VALUE) {
+ MINIDUMP_EXCEPTION_INFORMATION except_info;
+ except_info.ThreadId = requesting_thread_id;
+ except_info.ExceptionPointers = exinfo;
+ except_info.ClientPointers = FALSE;
+
+ // Leave room in user_stream_array for possible breakpad and
+ // assertion info streams.
+ MINIDUMP_USER_STREAM user_stream_array[2];
+ MINIDUMP_USER_STREAM_INFORMATION user_streams;
+ user_streams.UserStreamCount = 0;
+ user_streams.UserStreamArray = user_stream_array;
+
+ if (write_requester_stream) {
+ // Add an MDRawBreakpadInfo stream to the minidump, to provide
+ // additional information about the exception handler to the Breakpad
+ // processor. The information will help the processor determine which
+ // threads are relevant. The Breakpad processor does not require this
+ // information but can function better with Breakpad-generated dumps
+ // when it is present. The native debugger is not harmed by the
+ // presence of this information.
+ MDRawBreakpadInfo breakpad_info;
+ breakpad_info.validity = MD_BREAKPAD_INFO_VALID_DUMP_THREAD_ID |
+ MD_BREAKPAD_INFO_VALID_REQUESTING_THREAD_ID;
+ breakpad_info.dump_thread_id = GetCurrentThreadId();
+ breakpad_info.requesting_thread_id = requesting_thread_id;
+
+ int index = user_streams.UserStreamCount;
+ user_stream_array[index].Type = MD_BREAKPAD_INFO_STREAM;
+ user_stream_array[index].BufferSize = sizeof(breakpad_info);
+ user_stream_array[index].Buffer = &breakpad_info;
+ ++user_streams.UserStreamCount;
+ }
+
+ if (assertion) {
+ int index = user_streams.UserStreamCount;
+ user_stream_array[index].Type = MD_ASSERTION_INFO_STREAM;
+ user_stream_array[index].BufferSize = sizeof(MDRawAssertionInfo);
+ user_stream_array[index].Buffer = assertion;
+ ++user_streams.UserStreamCount;
+ }
+
+ MinidumpCallbackContext context;
+ context.iter = app_memory_info_.begin();
+ context.end = app_memory_info_.end();
+
+ if (exinfo) {
+ IncludeAppMemoryFromExceptionContext(process,
+ requesting_thread_id,
+ app_memory_info_,
+ exinfo->ContextRecord,
+ !include_context_heap_);
+ }
+
+ // Skip the reserved element if there was no instruction memory
+ if (context.iter->ptr == 0) {
+ context.iter++;
+ }
+
+ MINIDUMP_CALLBACK_INFORMATION callback;
+ callback.CallbackRoutine = MinidumpWriteDumpCallback;
+ callback.CallbackParam = reinterpret_cast<void*>(&context);
+
+ // The explicit comparison to TRUE avoids a warning (C4800).
+ success = (minidump_write_dump_(process,
+ GetProcessId(process),
+ dump_file,
+ dump_type_,
+ exinfo ? &except_info : NULL,
+ &user_streams,
+ &callback) == TRUE);
+
+ CloseHandle(dump_file);
+ }
+ }
+
+ return success;
+}
+
+void ExceptionHandler::UpdateNextID() {
+ assert(uuid_create_);
+ UUID id = {0};
+ if (uuid_create_) {
+ uuid_create_(&id);
+ }
+ next_minidump_id_ = GUIDString::GUIDToWString(&id);
+ next_minidump_id_c_ = next_minidump_id_.c_str();
+
+ wchar_t minidump_path[MAX_PATH];
+ swprintf(minidump_path, MAX_PATH, L"%s\\%s.dmp",
+ dump_path_c_, next_minidump_id_c_);
+
+ // remove when VC++7.1 is no longer supported
+ minidump_path[MAX_PATH - 1] = L'\0';
+
+ next_minidump_path_ = minidump_path;
+ next_minidump_path_c_ = next_minidump_path_.c_str();
+}
+
+void ExceptionHandler::RegisterAppMemory(void* ptr, size_t length) {
+ AppMemoryList::iterator iter =
+ std::find(app_memory_info_.begin(), app_memory_info_.end(), ptr);
+ if (iter != app_memory_info_.end()) {
+ // Don't allow registering the same pointer twice.
+ return;
+ }
+
+ AppMemory app_memory;
+ app_memory.ptr = reinterpret_cast<ULONG64>(ptr);
+ app_memory.length = static_cast<ULONG>(length);
+ app_memory.preallocated = false;
+ app_memory_info_.push_back(app_memory);
+}
+
+void ExceptionHandler::UnregisterAppMemory(void* ptr) {
+ AppMemoryList::iterator iter =
+ std::find(app_memory_info_.begin(), app_memory_info_.end(), ptr);
+ if (iter != app_memory_info_.end()) {
+ app_memory_info_.erase(iter);
+ }
+}
+
+void ExceptionHandler::set_include_context_heap(bool enabled) {
+ if (enabled && !include_context_heap_) {
+ // Initialize system info used in including context heap regions.
+ InitAppMemoryInternal();
+
+ // Preallocate AppMemory instances for exception context if necessary.
+ auto predicate = [] (const AppMemory& appMemory) -> bool {
+ return appMemory.preallocated;
+ };
+
+ int preallocatedCount =
+ std::count_if(app_memory_info_.begin(), app_memory_info_.end(), predicate);
+
+ for (size_t i = 0; i < kExceptionAppMemoryRegions - preallocatedCount; i++) {
+ AppMemory app_memory;
+ app_memory.ptr = reinterpret_cast<ULONG64>(nullptr);
+ app_memory.length = 0;
+ app_memory.preallocated = true;
+ app_memory_info_.push_back(app_memory);
+ }
+ }
+
+ include_context_heap_ = enabled;
+}
+
+} // namespace google_breakpad
diff --git a/toolkit/crashreporter/breakpad-client/windows/handler/exception_handler.h b/toolkit/crashreporter/breakpad-client/windows/handler/exception_handler.h
new file mode 100644
index 0000000000..18c8f5821a
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/windows/handler/exception_handler.h
@@ -0,0 +1,547 @@
+// 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.
+
+// ExceptionHandler can write a minidump file when an exception occurs,
+// or when WriteMinidump() is called explicitly by your program.
+//
+// To have the exception handler write minidumps when an uncaught exception
+// (crash) occurs, you should create an instance early in the execution
+// of your program, and keep it around for the entire time you want to
+// have crash handling active (typically, until shutdown).
+//
+// If you want to write minidumps without installing the exception handler,
+// you can create an ExceptionHandler with install_handler set to false,
+// then call WriteMinidump. You can also use this technique if you want to
+// use different minidump callbacks for different call sites.
+//
+// In either case, a callback function is called when a minidump is written,
+// which receives the unqiue id of the minidump. The caller can use this
+// id to collect and write additional application state, and to launch an
+// external crash-reporting application.
+//
+// It is important that creation and destruction of ExceptionHandler objects
+// be nested cleanly, when using install_handler = true.
+// Avoid the following pattern:
+// ExceptionHandler *e = new ExceptionHandler(...);
+// ExceptionHandler *f = new ExceptionHandler(...);
+// delete e;
+// This will put the exception filter stack into an inconsistent state.
+
+#ifndef CLIENT_WINDOWS_HANDLER_EXCEPTION_HANDLER_H__
+#define CLIENT_WINDOWS_HANDLER_EXCEPTION_HANDLER_H__
+
+#include <stdlib.h>
+#include <windows.h>
+#include <dbghelp.h>
+#include <rpc.h>
+
+#pragma warning(push)
+// Disable exception handler warnings.
+#pragma warning(disable:4530)
+
+#include <list>
+#include <string>
+#include <vector>
+
+#include "windows/common/minidump_callback.h"
+#include "windows/common/ipc_protocol.h"
+#include "windows/crash_generation/crash_generation_client.h"
+#include "common/scoped_ptr.h"
+#include "google_breakpad/common/minidump_format.h"
+
+#ifdef MOZ_PHC
+#include "PHC.h"
+#else
+namespace mozilla { namespace phc { class AddrInfo {}; } }
+#endif
+
+namespace google_breakpad {
+
+using std::vector;
+using std::wstring;
+
+class ExceptionHandler {
+ public:
+ // The result value for the filter callback, see below.
+ enum class FilterResult {
+ HandleException,
+ AbortWithoutMinidump,
+ ContinueSearch
+ };
+
+ // A callback function to run before Breakpad performs any substantial
+ // processing of an exception. A FilterCallback is called before writing
+ // a minidump. context is the parameter supplied by the user as
+ // callback_context when the handler was created. exinfo points to the
+ // exception record, if any; assertion points to assertion information,
+ // if any.
+ //
+ // If a FilterCallback returns HandleException, Breakpad will attempt to
+ // write a minidump. If a FilterCallback returns ContinueSearch Breakpad
+ // will immediately report the exception as unhandled without writing a
+ // minidump, allowing another handler the opportunity to handle it.
+ // If a FilterCallback returns AbortWithoutMinidump, Breakpad will report the
+ // exception as handled but will not write a minidump, letting the process
+ // terminate itself instead.
+ typedef FilterResult (*FilterCallback)(void* context,
+ EXCEPTION_POINTERS* exinfo,
+ MDRawAssertionInfo* assertion);
+
+ // A callback function to run after the minidump has been written.
+ // minidump_id is a unique id for the dump, so the minidump
+ // file is <dump_path>\<minidump_id>.dmp. context is the parameter supplied
+ // by the user as callback_context when the handler was created. exinfo
+ // points to the exception record, or NULL if no exception occurred.
+ // succeeded indicates whether a minidump file was successfully written.
+ // assertion points to information about an assertion if the handler was
+ // invoked by an assertion.
+ //
+ // If an exception occurred and the callback returns true, Breakpad will treat
+ // the exception as fully-handled, suppressing any other handlers from being
+ // notified of the exception. If the callback returns false, Breakpad will
+ // treat the exception as unhandled, and allow another handler to handle it.
+ // If there are no other handlers, Breakpad will report the exception to the
+ // system as unhandled, allowing a debugger or native crash dialog the
+ // opportunity to handle the exception. Most callback implementations
+ // should normally return the value of |succeeded|, or when they wish to
+ // not report an exception of handled, false. Callbacks will rarely want to
+ // return true directly (unless |succeeded| is true).
+ //
+ // For out-of-process dump generation, dump path and minidump ID will always
+ // be NULL. In case of out-of-process dump generation, the dump path and
+ // minidump id are controlled by the server process and are not communicated
+ // back to the crashing process.
+ typedef bool (*MinidumpCallback)(const wchar_t* dump_path,
+ const wchar_t* minidump_id,
+ void* context,
+ EXCEPTION_POINTERS* exinfo,
+ MDRawAssertionInfo* assertion,
+ const mozilla::phc::AddrInfo* addr_info,
+ bool succeeded);
+
+ // HandlerType specifies which types of handlers should be installed, if
+ // any. Use HANDLER_NONE for an ExceptionHandler that remains idle,
+ // without catching any failures on its own. This type of handler may
+ // still be triggered by calling WriteMinidump. Otherwise, use a
+ // combination of the other HANDLER_ values, or HANDLER_ALL to install
+ // all handlers.
+ enum HandlerType {
+ HANDLER_NONE = 0,
+ HANDLER_EXCEPTION = 1 << 0, // SetUnhandledExceptionFilter
+ HANDLER_INVALID_PARAMETER = 1 << 1, // _set_invalid_parameter_handler
+ HANDLER_PURECALL = 1 << 2, // _set_purecall_handler
+ HANDLER_HEAP_CORRUPTION = 1 << 4, // AddVectoredExceptionHandler
+ HANDLER_ALL = HANDLER_EXCEPTION | HANDLER_INVALID_PARAMETER |
+ HANDLER_PURECALL | HANDLER_HEAP_CORRUPTION
+ };
+
+ // Creates a new ExceptionHandler instance to handle writing minidumps.
+ // Before writing a minidump, the optional filter callback will be called.
+ // Its return value determines whether or not Breakpad should write a
+ // minidump. Minidump files will be written to dump_path, and the optional
+ // callback is called after writing the dump file, as described above.
+ // handler_types specifies the types of handlers that should be installed.
+ ExceptionHandler(const wstring& dump_path,
+ FilterCallback filter,
+ MinidumpCallback callback,
+ void* callback_context,
+ int handler_types);
+
+ // Creates a new ExceptionHandler instance that can attempt to perform
+ // out-of-process dump generation if pipe_name is not NULL. If pipe_name is
+ // NULL, or if out-of-process dump generation registration step fails,
+ // in-process dump generation will be used. This also allows specifying
+ // the dump type to generate.
+ ExceptionHandler(const wstring& dump_path,
+ FilterCallback filter,
+ MinidumpCallback callback,
+ void* callback_context,
+ int handler_types,
+ MINIDUMP_TYPE dump_type,
+ const wchar_t* pipe_name,
+ const CustomClientInfo* custom_info);
+
+ // As above, creates a new ExceptionHandler instance to perform
+ // out-of-process dump generation if the given pipe_handle is not NULL.
+ ExceptionHandler(const wstring& dump_path,
+ FilterCallback filter,
+ MinidumpCallback callback,
+ void* callback_context,
+ int handler_types,
+ MINIDUMP_TYPE dump_type,
+ HANDLE pipe_handle,
+ const CustomClientInfo* custom_info);
+
+ // ExceptionHandler that ENSURES out-of-process dump generation. Expects a
+ // crash generation client that is already registered with a crash generation
+ // server. Takes ownership of the passed-in crash_generation_client.
+ //
+ // Usage example:
+ // crash_generation_client = new CrashGenerationClient(..);
+ // if (crash_generation_client->Register()) {
+ // // Registration with the crash generation server succeeded.
+ // // Out-of-process dump generation is guaranteed.
+ // g_handler = new ExceptionHandler(.., crash_generation_client, ..);
+ // return true;
+ // }
+ ExceptionHandler(const wstring& dump_path,
+ FilterCallback filter,
+ MinidumpCallback callback,
+ void* callback_context,
+ int handler_types,
+ CrashGenerationClient* crash_generation_client);
+
+ ~ExceptionHandler();
+
+ // Get and set the minidump path.
+ wstring dump_path() const { return dump_path_; }
+ void set_dump_path(const wstring &dump_path) {
+ dump_path_ = dump_path;
+ dump_path_c_ = dump_path_.c_str();
+ UpdateNextID(); // Necessary to put dump_path_ in next_minidump_path_.
+ }
+
+ // Requests that a previously reported crash be uploaded.
+ bool RequestUpload(DWORD crash_id);
+
+ // Writes a minidump immediately. This can be used to capture the
+ // execution state independently of a crash. Returns true on success.
+ bool WriteMinidump();
+
+ // Writes a minidump immediately, with the user-supplied exception
+ // information.
+ bool WriteMinidumpForException(EXCEPTION_POINTERS* exinfo);
+
+ // Convenience form of WriteMinidump which does not require an
+ // ExceptionHandler instance.
+ static bool WriteMinidump(const wstring &dump_path,
+ MinidumpCallback callback, void* callback_context,
+ MINIDUMP_TYPE dump_type = MiniDumpNormal);
+
+ // Write a minidump of |child| immediately. This can be used to
+ // capture the execution state of |child| independently of a crash.
+ // Pass a meaningful |child_blamed_thread| to make that thread in
+ // the child process the one from which a crash signature is
+ // extracted.
+ static bool WriteMinidumpForChild(HANDLE child,
+ DWORD child_blamed_thread,
+ const wstring& dump_path,
+ MinidumpCallback callback,
+ void* callback_context,
+ MINIDUMP_TYPE dump_type = MiniDumpNormal);
+
+ // Get the thread ID of the thread requesting the dump (either the exception
+ // thread or any other thread that called WriteMinidump directly). This
+ // may be useful if you want to include additional thread state in your
+ // dumps.
+ DWORD get_requesting_thread_id() const { return requesting_thread_id_; }
+
+ // Controls behavior of EXCEPTION_BREAKPOINT and EXCEPTION_SINGLE_STEP.
+ bool get_handle_debug_exceptions() const { return handle_debug_exceptions_; }
+ void set_handle_debug_exceptions(bool handle_debug_exceptions) {
+ handle_debug_exceptions_ = handle_debug_exceptions;
+ }
+
+ // Controls behavior of EXCEPTION_INVALID_HANDLE.
+ bool get_consume_invalid_handle_exceptions() const {
+ return consume_invalid_handle_exceptions_;
+ }
+ void set_consume_invalid_handle_exceptions(
+ bool consume_invalid_handle_exceptions) {
+ consume_invalid_handle_exceptions_ = consume_invalid_handle_exceptions;
+ }
+
+ // Returns whether out-of-process dump generation is used or not.
+ bool IsOutOfProcess() const { return crash_generation_client_.get() != NULL; }
+
+ // Calling RegisterAppMemory(p, len) causes len bytes starting
+ // at address p to be copied to the minidump when a crash happens.
+ void RegisterAppMemory(void* ptr, size_t length);
+ void UnregisterAppMemory(void* ptr);
+
+ // Calling set_include_context_heap(true) causes heap regions to be included
+ // in the minidump when a crash happens. The heap regions are from the
+ // register values of the crashing context.
+ void set_include_context_heap(bool enabled);
+
+ private:
+ friend class AutoExceptionHandler;
+
+ // Initializes the instance with given values.
+ void Initialize(const wstring& dump_path,
+ FilterCallback filter,
+ MinidumpCallback callback,
+ void* callback_context,
+ int handler_types,
+ MINIDUMP_TYPE dump_type,
+ const wchar_t* pipe_name,
+ HANDLE pipe_handle,
+ CrashGenerationClient* crash_generation_client,
+ const CustomClientInfo* custom_info);
+
+ // Function pointer type for MiniDumpWriteDump, which is looked up
+ // dynamically.
+ typedef BOOL (WINAPI *MiniDumpWriteDump_type)(
+ HANDLE hProcess,
+ DWORD dwPid,
+ HANDLE hFile,
+ MINIDUMP_TYPE DumpType,
+ CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
+ CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
+ CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam);
+
+ // Function pointer type for UuidCreate, which is looked up dynamically.
+ typedef RPC_STATUS (RPC_ENTRY *UuidCreate_type)(UUID* Uuid);
+
+ // Runs the main loop for the exception handler thread.
+ static DWORD WINAPI ExceptionHandlerThreadMain(void* lpParameter);
+
+ // Called on the exception thread when an unhandled exception occurs.
+ // Signals the exception handler thread to handle the exception.
+ static LONG WINAPI HandleException(EXCEPTION_POINTERS* exinfo);
+
+#if _MSC_VER >= 1400 // MSVC 2005/8
+ // This function will be called by some CRT functions when they detect
+ // that they were passed an invalid parameter. Note that in _DEBUG builds,
+ // the CRT may display an assertion dialog before calling this function,
+ // and the function will not be called unless the assertion dialog is
+ // dismissed by clicking "Ignore."
+ static void HandleInvalidParameter(const wchar_t* expression,
+ const wchar_t* function,
+ const wchar_t* file,
+ unsigned int line,
+ uintptr_t reserved);
+#endif // _MSC_VER >= 1400
+
+ // This function will be called by the CRT when a pure virtual
+ // function is called.
+ static void HandlePureVirtualCall();
+
+ // This function will be called by the vectored exception handler and will
+ // generate a minidump only for exceptions of type STATUS_HEAP_CORRUPTION.
+ static LONG WINAPI HandleHeapCorruption(EXCEPTION_POINTERS* exinfo);
+
+ // This is called on the exception thread or on another thread that
+ // the user wishes to produce a dump from. It calls
+ // WriteMinidumpWithException on the handler thread, avoiding stack
+ // overflows and inconsistent dumps due to writing the dump from
+ // the exception thread. If the dump is requested as a result of an
+ // exception, exinfo contains exception information, otherwise, it
+ // is NULL. If the dump is requested as a result of an assertion
+ // (such as an invalid parameter being passed to a CRT function),
+ // assertion contains data about the assertion, otherwise, it is NULL.
+ bool WriteMinidumpOnHandlerThread(EXCEPTION_POINTERS* exinfo,
+ MDRawAssertionInfo* assertion);
+
+ // The return value for WriteMinidumpWithException(), see below.
+ enum class MinidumpResult {
+ Success,
+ Failure,
+ Ignored
+ };
+
+ // This function is called on the handler thread. It calls into
+ // WriteMinidumpWithExceptionForProcess() with a handle to the
+ // current process. requesting_thread_id is the ID of the thread
+ // that requested the dump. If the dump is requested as a result of
+ // an exception, exinfo contains exception information, otherwise,
+ // it is NULL. It will return Success in case the minidump has been written
+ // successfully, Failure if we couldn't write out the minidump because of an
+ // error and Ignored if we didn't even try to write the minidump because the
+ // filter callback indicated that we should ignore this exception and abort.
+ // The latter condition is only relevent for a top-level exception handler,
+ // other callers should equate it to a failure.
+ MinidumpResult WriteMinidumpWithException(DWORD requesting_thread_id,
+ EXCEPTION_POINTERS* exinfo,
+ MDRawAssertionInfo* assertion);
+
+ // This function does the actual writing of a minidump. It is
+ // called on the handler thread. requesting_thread_id is the ID of
+ // the thread that requested the dump, if that information is
+ // meaningful. If the dump is requested as a result of an
+ // exception, exinfo contains exception information, otherwise, it
+ // is NULL. process is the one that will be dumped. If
+ // requesting_thread_id is meaningful and should be added to the
+ // minidump, write_requester_stream is |true|.
+ bool WriteMinidumpWithExceptionForProcess(DWORD requesting_thread_id,
+ EXCEPTION_POINTERS* exinfo,
+ MDRawAssertionInfo* assertion,
+ HANDLE process,
+ bool write_requester_stream);
+
+ // Generates a new ID and stores it in next_minidump_id_, and stores the
+ // path of the next minidump to be written in next_minidump_path_.
+ void UpdateNextID();
+
+ FilterCallback filter_;
+ MinidumpCallback callback_;
+ void* callback_context_;
+
+ scoped_ptr<CrashGenerationClient> crash_generation_client_;
+
+ // The directory in which a minidump will be written, set by the dump_path
+ // argument to the constructor, or set_dump_path.
+ wstring dump_path_;
+
+ // The basename of the next minidump to be written, without the extension.
+ wstring next_minidump_id_;
+
+ // The full pathname of the next minidump to be written, including the file
+ // extension.
+ wstring next_minidump_path_;
+
+ // Pointers to C-string representations of the above. These are set when
+ // the above wstring versions are set in order to avoid calling c_str during
+ // an exception, as c_str may attempt to allocate heap memory. These
+ // pointers are not owned by the ExceptionHandler object, but their lifetimes
+ // should be equivalent to the lifetimes of the associated wstring, provided
+ // that the wstrings are not altered.
+ const wchar_t* dump_path_c_;
+ const wchar_t* next_minidump_id_c_;
+ const wchar_t* next_minidump_path_c_;
+
+ HMODULE dbghelp_module_;
+ MiniDumpWriteDump_type minidump_write_dump_;
+ MINIDUMP_TYPE dump_type_;
+
+ HMODULE rpcrt4_module_;
+ UuidCreate_type uuid_create_;
+
+ // Tracks the handler types that were installed according to the
+ // handler_types constructor argument.
+ int handler_types_;
+
+ // When installed_handler_ is true, previous_filter_ is the unhandled
+ // exception filter that was set prior to installing ExceptionHandler as
+ // the unhandled exception filter and pointing it to |this|. NULL indicates
+ // that there is no previous unhandled exception filter.
+ LPTOP_LEVEL_EXCEPTION_FILTER previous_filter_;
+
+#if _MSC_VER >= 1400 // MSVC 2005/8
+ // Beginning in VC 8, the CRT provides an invalid parameter handler that will
+ // be called when some CRT functions are passed invalid parameters. In
+ // earlier CRTs, the same conditions would cause unexpected behavior or
+ // crashes.
+ _invalid_parameter_handler previous_iph_;
+#endif // _MSC_VER >= 1400
+
+ // The CRT allows you to override the default handler for pure
+ // virtual function calls.
+ _purecall_handler previous_pch_;
+
+ // Vectored exception handler used for catching STATUS_HEAP_CORRUPTION
+ // exceptions
+ PVOID heap_corruption_veh_;
+
+ // The exception handler thread.
+ HANDLE handler_thread_;
+
+ // True if the exception handler is being destroyed.
+ // Starting with MSVC 2005, Visual C has stronger guarantees on volatile vars.
+ // It has release semantics on write and acquire semantics on reads.
+ // See the msdn documentation.
+ volatile bool is_shutdown_;
+
+ // The critical section enforcing the requirement that only one exception be
+ // handled by a handler at a time.
+ CRITICAL_SECTION handler_critical_section_;
+
+ // Semaphores used to move exception handling between the exception thread
+ // and the handler thread. handler_start_semaphore_ is signalled by the
+ // exception thread to wake up the handler thread when an exception occurs.
+ // handler_finish_semaphore_ is signalled by the handler thread to wake up
+ // the exception thread when handling is complete.
+ HANDLE handler_start_semaphore_;
+ HANDLE handler_finish_semaphore_;
+
+ // The next 2 fields contain data passed from the requesting thread to
+ // the handler thread.
+
+ // The thread ID of the thread requesting the dump (either the exception
+ // thread or any other thread that called WriteMinidump directly).
+ DWORD requesting_thread_id_;
+
+ // The exception info passed to the exception handler on the exception
+ // thread, if an exception occurred. NULL for user-requested dumps.
+ EXCEPTION_POINTERS* exception_info_;
+
+ // If the handler is invoked due to an assertion, this will contain a
+ // pointer to the assertion information. It is NULL at other times.
+ MDRawAssertionInfo* assertion_;
+
+ // The return value of the handler, passed from the handler thread back to
+ // the requesting thread.
+ MinidumpResult handler_return_value_;
+
+ // If true, the handler will intercept EXCEPTION_BREAKPOINT and
+ // EXCEPTION_SINGLE_STEP exceptions. Leave this false (the default)
+ // to not interfere with debuggers.
+ bool handle_debug_exceptions_;
+
+ // If true, the handler will consume any EXCEPTION_INVALID_HANDLE exceptions.
+ // Leave this false (the default) to handle these exceptions as normal.
+ bool consume_invalid_handle_exceptions_;
+
+ // Callers can request additional memory regions to be included in
+ // the dump.
+ AppMemoryList app_memory_info_;
+
+ // A stack of ExceptionHandler objects that have installed unhandled
+ // exception filters. This vector is used by HandleException to determine
+ // which ExceptionHandler object to route an exception to. When an
+ // ExceptionHandler is created with install_handler true, it will append
+ // itself to this list.
+ static vector<ExceptionHandler*>* handler_stack_;
+
+ // The index of the ExceptionHandler in handler_stack_ that will handle the
+ // next exception. Note that 0 means the last entry in handler_stack_, 1
+ // means the next-to-last entry, and so on. This is used by HandleException
+ // to support multiple stacked Breakpad handlers.
+ static LONG handler_stack_index_;
+
+ // handler_stack_critical_section_ guards operations on handler_stack_ and
+ // handler_stack_index_. The critical section is initialized by the
+ // first instance of the class and destroyed by the last instance of it.
+ static CRITICAL_SECTION handler_stack_critical_section_;
+
+ // The number of instances of this class.
+ static volatile LONG instance_count_;
+
+ bool include_context_heap_;
+
+ // disallow copy ctor and operator=
+ explicit ExceptionHandler(const ExceptionHandler &);
+ void operator=(const ExceptionHandler &);
+};
+
+} // namespace google_breakpad
+
+#pragma warning(pop)
+
+#endif // CLIENT_WINDOWS_HANDLER_EXCEPTION_HANDLER_H__
diff --git a/toolkit/crashreporter/breakpad-client/windows/handler/objs.mozbuild b/toolkit/crashreporter/breakpad-client/windows/handler/objs.mozbuild
new file mode 100644
index 0000000000..22dc0d27dd
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/windows/handler/objs.mozbuild
@@ -0,0 +1,17 @@
+# -*- 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_handler = [
+ 'exception_handler.cc',
+]
+
+subdir = 'toolkit/crashreporter/breakpad-client/windows/handler'
+objs_handler = [
+ '/%s/%s' % (subdir, s) for s in lobjs_handler
+]
+
+if CONFIG['MOZ_PHC']:
+ DEFINES['MOZ_PHC'] = True
diff --git a/toolkit/crashreporter/breakpad-client/windows/sender/crash_report_sender.cc b/toolkit/crashreporter/breakpad-client/windows/sender/crash_report_sender.cc
new file mode 100644
index 0000000000..bf8ea5ea7a
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/windows/sender/crash_report_sender.cc
@@ -0,0 +1,140 @@
+// 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.
+
+// Disable exception handler warnings.
+#pragma warning(disable : 4530)
+
+#include <errno.h>
+
+#include "windows/sender/crash_report_sender.h"
+#include "common/windows/http_upload.h"
+
+#if _MSC_VER < 1400 // MSVC 2005/8
+// Older MSVC doesn't have fscanf_s, but they are compatible as long as
+// we don't use the string conversions (%s/%c/%S/%C).
+# define fscanf_s fscanf
+#endif
+
+namespace google_breakpad {
+
+static const char kCheckpointSignature[] = "GBP1\n";
+
+CrashReportSender::CrashReportSender(const wstring& checkpoint_file)
+ : checkpoint_file_(checkpoint_file),
+ max_reports_per_day_(-1),
+ last_sent_date_(-1),
+ reports_sent_(0) {
+ FILE* fd;
+ if (OpenCheckpointFile(L"r", &fd) == 0) {
+ ReadCheckpoint(fd);
+ fclose(fd);
+ }
+}
+
+ReportResult CrashReportSender::SendCrashReport(
+ const wstring& url, const string& parameters,
+ const map<wstring, wstring>& files, wstring* report_code) {
+ int today = GetCurrentDate();
+ if (today == last_sent_date_ && max_reports_per_day_ != -1 &&
+ reports_sent_ >= max_reports_per_day_) {
+ return RESULT_THROTTLED;
+ }
+
+ int http_response = 0;
+ bool result = HTTPUpload::SendMultipartPostRequest(
+ url, parameters, files, NULL, report_code,
+ &http_response);
+
+ if (result) {
+ ReportSent(today);
+ return RESULT_SUCCEEDED;
+ } else if (http_response >= 400 && http_response < 500) {
+ return RESULT_REJECTED;
+ } else {
+ return RESULT_FAILED;
+ }
+}
+
+void CrashReportSender::ReadCheckpoint(FILE* fd) {
+ char buf[128];
+ if (!fgets(buf, sizeof(buf), fd) || strcmp(buf, kCheckpointSignature) != 0) {
+ return;
+ }
+
+ if (fscanf_s(fd, "%d\n", &last_sent_date_) != 1) {
+ last_sent_date_ = -1;
+ return;
+ }
+ if (fscanf_s(fd, "%d\n", &reports_sent_) != 1) {
+ reports_sent_ = 0;
+ return;
+ }
+}
+
+void CrashReportSender::ReportSent(int today) {
+ // Update the report stats
+ if (today != last_sent_date_) {
+ last_sent_date_ = today;
+ reports_sent_ = 0;
+ }
+ ++reports_sent_;
+
+ // Update the checkpoint file
+ FILE* fd;
+ if (OpenCheckpointFile(L"w", &fd) == 0) {
+ fputs(kCheckpointSignature, fd);
+ fprintf(fd, "%d\n", last_sent_date_);
+ fprintf(fd, "%d\n", reports_sent_);
+ fclose(fd);
+ }
+}
+
+int CrashReportSender::GetCurrentDate() const {
+ SYSTEMTIME system_time;
+ GetSystemTime(&system_time);
+ return (system_time.wYear * 10000) + (system_time.wMonth * 100) +
+ system_time.wDay;
+}
+
+int CrashReportSender::OpenCheckpointFile(const wchar_t* mode, FILE** fd) {
+ if (checkpoint_file_.empty()) {
+ return ENOENT;
+ }
+#if _MSC_VER >= 1400 // MSVC 2005/8
+ return _wfopen_s(fd, checkpoint_file_.c_str(), mode);
+#else
+ *fd = _wfopen(checkpoint_file_.c_str(), mode);
+ if (*fd == NULL) {
+ return errno;
+ }
+ return 0;
+#endif
+}
+
+} // namespace google_breakpad
diff --git a/toolkit/crashreporter/breakpad-client/windows/sender/crash_report_sender.h b/toolkit/crashreporter/breakpad-client/windows/sender/crash_report_sender.h
new file mode 100644
index 0000000000..02b5f4fe49
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/windows/sender/crash_report_sender.h
@@ -0,0 +1,122 @@
+// 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 CLIENT_WINDOWS_SENDER_CRASH_REPORT_SENDER_H__
+#define CLIENT_WINDOWS_SENDER_CRASH_REPORT_SENDER_H__
+
+// CrashReportSender is a "static" class which provides an API to upload
+// crash reports via HTTP(S). A crash report is formatted as a multipart POST
+// request, which contains a set of caller-supplied string key/value pairs,
+// and a minidump file to upload.
+//
+// To use this library in your project, you will need to link against
+// wininet.lib.
+
+#pragma warning(push)
+// Disable exception handler warnings.
+#pragma warning(disable : 4530)
+
+#include <map>
+#include <string>
+
+namespace google_breakpad {
+
+using std::map;
+using std::string;
+using std::wstring;
+
+typedef enum {
+ RESULT_FAILED = 0, // Failed to communicate with the server; try later.
+ RESULT_REJECTED, // Successfully sent the crash report, but the
+ // server rejected it; don't resend this report.
+ RESULT_SUCCEEDED, // The server accepted the crash report.
+ RESULT_THROTTLED // No attempt was made to send the crash report, because
+ // we exceeded the maximum reports per day.
+} ReportResult;
+
+class CrashReportSender {
+ public:
+ // Initializes a CrashReportSender instance.
+ // If checkpoint_file is non-empty, breakpad will persist crash report
+ // state to this file. A checkpoint file is required for
+ // set_max_reports_per_day() to function properly.
+ explicit CrashReportSender(const wstring& checkpoint_file);
+ ~CrashReportSender() {}
+
+ // Sets the maximum number of crash reports that will be sent in a 24-hour
+ // period. This uses the state persisted to the checkpoint file.
+ // The default value of -1 means that there is no limit on reports sent.
+ void set_max_reports_per_day(int reports) { max_reports_per_day_ = reports; }
+
+ int max_reports_per_day() const { return max_reports_per_day_; }
+
+ // Sends the specified files, along with the map of
+ // name value pairs, as a multipart POST request to the given URL.
+ // Parameters are specified as a JSON-encoded string in |parameters|.
+ // Only HTTP(S) URLs are currently supported. The return value indicates
+ // the result of the operation (see above for possible results).
+ // If report_code is non-NULL and the report is sent successfully (that is,
+ // the return value is RESULT_SUCCEEDED), a code uniquely identifying the
+ // report will be returned in report_code.
+ // (Otherwise, report_code will be unchanged.)
+ ReportResult SendCrashReport(const wstring& url, const string& parameters,
+ const map<wstring, wstring>& files,
+ wstring* report_code);
+
+ private:
+ // Reads persistent state from a checkpoint file.
+ void ReadCheckpoint(FILE* fd);
+
+ // Called when a new report has been sent, to update the checkpoint state.
+ void ReportSent(int today);
+
+ // Returns today's date (UTC) formatted as YYYYMMDD.
+ int GetCurrentDate() const;
+
+ // Opens the checkpoint file with the specified mode.
+ // Returns zero on success, or an error code on failure.
+ int OpenCheckpointFile(const wchar_t* mode, FILE** fd);
+
+ wstring checkpoint_file_;
+ int max_reports_per_day_;
+ // The last date on which we sent a report, expressed as YYYYMMDD.
+ int last_sent_date_;
+ // Number of reports sent on last_sent_date_
+ int reports_sent_;
+
+ // Disallow copy constructor and operator=
+ explicit CrashReportSender(const CrashReportSender&);
+ void operator=(const CrashReportSender&);
+};
+
+} // namespace google_breakpad
+
+#pragma warning(pop)
+
+#endif // CLIENT_WINDOWS_SENDER_CRASH_REPORT_SENDER_H__
diff --git a/toolkit/crashreporter/breakpad-client/windows/sender/objs.mozbuild b/toolkit/crashreporter/breakpad-client/windows/sender/objs.mozbuild
new file mode 100644
index 0000000000..3084bb92e6
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/windows/sender/objs.mozbuild
@@ -0,0 +1,14 @@
+# -*- 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_sender = [
+ 'crash_report_sender.cc',
+]
+
+subdir = 'toolkit/crashreporter/breakpad-client/windows/sender'
+objs_sender = [
+ '/%s/%s' % (subdir, s) for s in lobjs_sender
+]
diff --git a/toolkit/crashreporter/breakpad-client/windows/unittests/crash_generation_server_test.cc b/toolkit/crashreporter/breakpad-client/windows/unittests/crash_generation_server_test.cc
new file mode 100644
index 0000000000..09f2dd200d
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/windows/unittests/crash_generation_server_test.cc
@@ -0,0 +1,303 @@
+// Copyright 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_googletest_includes.h"
+#include "client/windows/crash_generation/crash_generation_server.h"
+#include "client/windows/common/ipc_protocol.h"
+
+using testing::_;
+
+namespace {
+
+const wchar_t kPipeName[] =
+ L"\\\\.\\pipe\\CrashGenerationServerTest\\TestCaseServer";
+
+const DWORD kPipeDesiredAccess = FILE_READ_DATA |
+ FILE_WRITE_DATA |
+ FILE_WRITE_ATTRIBUTES;
+
+const DWORD kPipeFlagsAndAttributes = SECURITY_IDENTIFICATION |
+ SECURITY_SQOS_PRESENT;
+
+const DWORD kPipeMode = PIPE_READMODE_MESSAGE;
+
+#define arraysize(f) (sizeof(f) / sizeof(*f))
+const google_breakpad::CustomInfoEntry kCustomInfoEntries[] = {
+ google_breakpad::CustomInfoEntry(L"prod", L"CrashGenerationServerTest"),
+ google_breakpad::CustomInfoEntry(L"ver", L"1.0"),
+};
+
+class CrashGenerationServerTest : public ::testing::Test {
+ public:
+ CrashGenerationServerTest()
+ : crash_generation_server_(kPipeName,
+ NULL,
+ CallOnClientConnected, &mock_callbacks_,
+ CallOnClientDumpRequested, &mock_callbacks_,
+ CallOnClientExited, &mock_callbacks_,
+ CallOnClientUploadRequested, &mock_callbacks_,
+ false,
+ NULL),
+ thread_id_(0),
+ exception_pointers_(NULL) {
+ memset(&assert_info_, 0, sizeof(assert_info_));
+ }
+
+ protected:
+ class MockCrashGenerationServerCallbacks {
+ public:
+ MOCK_METHOD1(OnClientConnected,
+ void(const google_breakpad::ClientInfo* client_info));
+ MOCK_METHOD2(OnClientDumpRequested,
+ void(const google_breakpad::ClientInfo* client_info,
+ const std::wstring* file_path));
+ MOCK_METHOD1(OnClientExited,
+ void(const google_breakpad::ClientInfo* client_info));
+ MOCK_METHOD1(OnClientUploadRequested,
+ void(const DWORD crash_id));
+ };
+
+ enum ClientFault {
+ NO_FAULT,
+ CLOSE_AFTER_CONNECT,
+ SEND_INVALID_REGISTRATION,
+ TRUNCATE_REGISTRATION,
+ CLOSE_AFTER_REGISTRATION,
+ RESPONSE_BUFFER_TOO_SMALL,
+ CLOSE_AFTER_RESPONSE,
+ SEND_INVALID_ACK
+ };
+
+ void SetUp() {
+ ASSERT_TRUE(crash_generation_server_.Start());
+ }
+
+ void FaultyClient(ClientFault fault_type) {
+ HANDLE pipe = CreateFile(kPipeName,
+ kPipeDesiredAccess,
+ 0,
+ NULL,
+ OPEN_EXISTING,
+ kPipeFlagsAndAttributes,
+ NULL);
+
+ if (pipe == INVALID_HANDLE_VALUE) {
+ ASSERT_EQ(ERROR_PIPE_BUSY, GetLastError());
+
+ // Cannot continue retrying if wait on pipe fails.
+ ASSERT_TRUE(WaitNamedPipe(kPipeName, 500));
+
+ pipe = CreateFile(kPipeName,
+ kPipeDesiredAccess,
+ 0,
+ NULL,
+ OPEN_EXISTING,
+ kPipeFlagsAndAttributes,
+ NULL);
+ }
+
+ ASSERT_NE(pipe, INVALID_HANDLE_VALUE);
+
+ DWORD mode = kPipeMode;
+ ASSERT_TRUE(SetNamedPipeHandleState(pipe, &mode, NULL, NULL));
+
+ DoFaultyClient(fault_type, pipe);
+
+ CloseHandle(pipe);
+ }
+
+ void DoTestFault(ClientFault fault) {
+ EXPECT_CALL(mock_callbacks_, OnClientConnected(_)).Times(0);
+ ASSERT_NO_FATAL_FAILURE(FaultyClient(fault));
+ ASSERT_NO_FATAL_FAILURE(FaultyClient(fault));
+ ASSERT_NO_FATAL_FAILURE(FaultyClient(fault));
+
+ EXPECT_CALL(mock_callbacks_, OnClientConnected(_));
+
+ ASSERT_NO_FATAL_FAILURE(FaultyClient(NO_FAULT));
+
+ // Slight hack. The OnClientConnected is only invoked after the ack is
+ // received by the server. At that point, the FaultyClient call has already
+ // returned. The best way to wait until the server is done handling that is
+ // to send one more ping, whose processing will be blocked by delivery of
+ // the OnClientConnected message.
+ ASSERT_NO_FATAL_FAILURE(FaultyClient(CLOSE_AFTER_CONNECT));
+ }
+
+ MockCrashGenerationServerCallbacks mock_callbacks_;
+
+ private:
+ // Depends on the caller to successfully open the pipe before invocation and
+ // to close it immediately afterwards.
+ void DoFaultyClient(ClientFault fault_type, HANDLE pipe) {
+ if (fault_type == CLOSE_AFTER_CONNECT) {
+ return;
+ }
+
+ google_breakpad::CustomClientInfo custom_info = {kCustomInfoEntries,
+ arraysize(kCustomInfoEntries)};
+
+ google_breakpad::ProtocolMessage msg(
+ fault_type == SEND_INVALID_REGISTRATION ?
+ google_breakpad::MESSAGE_TAG_NONE :
+ google_breakpad::MESSAGE_TAG_REGISTRATION_REQUEST,
+ GetCurrentProcessId(),
+ MiniDumpNormal,
+ &thread_id_,
+ &exception_pointers_,
+ &assert_info_,
+ custom_info,
+ NULL,
+ NULL,
+ NULL);
+
+ DWORD bytes_count = 0;
+
+ ASSERT_TRUE(WriteFile(pipe,
+ &msg,
+ fault_type == TRUNCATE_REGISTRATION ?
+ sizeof(msg) / 2 : sizeof(msg),
+ &bytes_count,
+ NULL));
+
+ if (fault_type == CLOSE_AFTER_REGISTRATION) {
+ return;
+ }
+
+ google_breakpad::ProtocolMessage reply;
+
+ if (!ReadFile(pipe,
+ &reply,
+ fault_type == RESPONSE_BUFFER_TOO_SMALL ?
+ sizeof(google_breakpad::ProtocolMessage) / 2 :
+ sizeof(google_breakpad::ProtocolMessage),
+ &bytes_count,
+ NULL)) {
+ switch (fault_type) {
+ case TRUNCATE_REGISTRATION:
+ case RESPONSE_BUFFER_TOO_SMALL:
+ case SEND_INVALID_REGISTRATION:
+ return;
+
+ default:
+ FAIL() << "Unexpectedly failed to register.";
+ }
+ }
+
+ if (fault_type == CLOSE_AFTER_RESPONSE) {
+ return;
+ }
+
+ google_breakpad::ProtocolMessage ack_msg;
+ ack_msg.tag = google_breakpad::MESSAGE_TAG_REGISTRATION_ACK;
+
+ ASSERT_TRUE(WriteFile(pipe,
+ &ack_msg,
+ SEND_INVALID_ACK ?
+ sizeof(ack_msg) : sizeof(ack_msg) / 2,
+ &bytes_count,
+ NULL));
+
+ return;
+ }
+
+ static void CallOnClientConnected(
+ void* context, const google_breakpad::ClientInfo* client_info) {
+ static_cast<MockCrashGenerationServerCallbacks*>(context)->
+ OnClientConnected(client_info);
+ }
+
+ static void CallOnClientDumpRequested(
+ void* context,
+ const google_breakpad::ClientInfo* client_info,
+ const std::wstring* file_path) {
+ static_cast<MockCrashGenerationServerCallbacks*>(context)->
+ OnClientDumpRequested(client_info, file_path);
+ }
+
+ static void CallOnClientExited(
+ void* context, const google_breakpad::ClientInfo* client_info) {
+ static_cast<MockCrashGenerationServerCallbacks*>(context)->
+ OnClientExited(client_info);
+ }
+
+ static void CallOnClientUploadRequested(void* context, const DWORD crash_id) {
+ static_cast<MockCrashGenerationServerCallbacks*>(context)->
+ OnClientUploadRequested(crash_id);
+ }
+
+ DWORD thread_id_;
+ EXCEPTION_POINTERS* exception_pointers_;
+ MDRawAssertionInfo assert_info_;
+
+ google_breakpad::CrashGenerationServer crash_generation_server_;
+};
+
+TEST_F(CrashGenerationServerTest, PingServerTest) {
+ DoTestFault(CLOSE_AFTER_CONNECT);
+}
+
+TEST_F(CrashGenerationServerTest, InvalidRegistration) {
+ DoTestFault(SEND_INVALID_REGISTRATION);
+}
+
+TEST_F(CrashGenerationServerTest, TruncateRegistration) {
+ DoTestFault(TRUNCATE_REGISTRATION);
+}
+
+TEST_F(CrashGenerationServerTest, CloseAfterRegistration) {
+ DoTestFault(CLOSE_AFTER_REGISTRATION);
+}
+
+TEST_F(CrashGenerationServerTest, ResponseBufferTooSmall) {
+ DoTestFault(RESPONSE_BUFFER_TOO_SMALL);
+}
+
+TEST_F(CrashGenerationServerTest, CloseAfterResponse) {
+ DoTestFault(CLOSE_AFTER_RESPONSE);
+}
+
+// It turns out that, as long as you send one byte, the ACK is accepted and
+// registration succeeds.
+TEST_F(CrashGenerationServerTest, SendInvalidAck) {
+ EXPECT_CALL(mock_callbacks_, OnClientConnected(_));
+ ASSERT_NO_FATAL_FAILURE(FaultyClient(SEND_INVALID_ACK));
+
+ // See DoTestFault for an explanation of this line
+ ASSERT_NO_FATAL_FAILURE(FaultyClient(CLOSE_AFTER_CONNECT));
+
+ EXPECT_CALL(mock_callbacks_, OnClientConnected(_));
+ ASSERT_NO_FATAL_FAILURE(FaultyClient(NO_FAULT));
+
+ // See DoTestFault for an explanation of this line
+ ASSERT_NO_FATAL_FAILURE(FaultyClient(CLOSE_AFTER_CONNECT));
+}
+
+} // anonymous namespace
diff --git a/toolkit/crashreporter/breakpad-client/windows/unittests/dump_analysis.cc b/toolkit/crashreporter/breakpad-client/windows/unittests/dump_analysis.cc
new file mode 100644
index 0000000000..53d4ddbde9
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/windows/unittests/dump_analysis.cc
@@ -0,0 +1,184 @@
+// 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 <windows.h>
+#include <objbase.h>
+#include <dbghelp.h>
+
+#include "breakpad_googletest_includes.h"
+#include "client/windows/unittests/dump_analysis.h" // NOLINT
+
+DumpAnalysis::~DumpAnalysis() {
+ if (dump_file_view_ != NULL) {
+ EXPECT_TRUE(::UnmapViewOfFile(dump_file_view_));
+ ::CloseHandle(dump_file_mapping_);
+ dump_file_mapping_ = NULL;
+ }
+
+ if (dump_file_handle_ != NULL) {
+ ::CloseHandle(dump_file_handle_);
+ dump_file_handle_ = NULL;
+ }
+}
+
+void DumpAnalysis::EnsureDumpMapped() {
+ if (dump_file_view_ == NULL) {
+ dump_file_handle_ = ::CreateFile(dump_file_.c_str(),
+ GENERIC_READ,
+ 0,
+ NULL,
+ OPEN_EXISTING,
+ 0,
+ NULL);
+ ASSERT_TRUE(dump_file_handle_ != NULL);
+ ASSERT_TRUE(dump_file_mapping_ == NULL);
+
+ dump_file_mapping_ = ::CreateFileMapping(dump_file_handle_,
+ NULL,
+ PAGE_READONLY,
+ 0,
+ 0,
+ NULL);
+ ASSERT_TRUE(dump_file_mapping_ != NULL);
+
+ dump_file_view_ = ::MapViewOfFile(dump_file_mapping_,
+ FILE_MAP_READ,
+ 0,
+ 0,
+ 0);
+ ASSERT_TRUE(dump_file_view_ != NULL);
+ }
+}
+
+bool DumpAnalysis::HasTebs() const {
+ MINIDUMP_THREAD_LIST* thread_list = NULL;
+ size_t thread_list_size = GetStream(ThreadListStream, &thread_list);
+
+ if (thread_list_size > 0 && thread_list != NULL) {
+ for (ULONG i = 0; i < thread_list->NumberOfThreads; ++i) {
+ if (!HasMemory(thread_list->Threads[i].Teb))
+ return false;
+ }
+
+ return true;
+ }
+
+ // No thread list, no TEB info.
+ return false;
+}
+
+bool DumpAnalysis::HasPeb() const {
+ MINIDUMP_THREAD_LIST* thread_list = NULL;
+ size_t thread_list_size = GetStream(ThreadListStream, &thread_list);
+
+ if (thread_list_size > 0 && thread_list != NULL &&
+ thread_list->NumberOfThreads > 0) {
+ FakeTEB* teb = NULL;
+ if (!HasMemory(thread_list->Threads[0].Teb, &teb))
+ return false;
+
+ return HasMemory(teb->peb);
+ }
+
+ return false;
+}
+
+bool DumpAnalysis::HasStream(ULONG stream_number) const {
+ void* stream = NULL;
+ size_t stream_size = GetStreamImpl(stream_number, &stream);
+ return stream_size > 0 && stream != NULL;
+}
+
+size_t DumpAnalysis::GetStreamImpl(ULONG stream_number, void** stream) const {
+ MINIDUMP_DIRECTORY* directory = NULL;
+ ULONG memory_list_size = 0;
+ BOOL ret = ::MiniDumpReadDumpStream(dump_file_view_,
+ stream_number,
+ &directory,
+ stream,
+ &memory_list_size);
+
+ return ret ? memory_list_size : 0;
+}
+
+bool DumpAnalysis::HasMemoryImpl(const void *addr_in, size_t structuresize,
+ void **structure) const {
+ uintptr_t address = reinterpret_cast<uintptr_t>(addr_in);
+ MINIDUMP_MEMORY_LIST* memory_list = NULL;
+ size_t memory_list_size = GetStream(MemoryListStream, &memory_list);
+ if (memory_list_size > 0 && memory_list != NULL) {
+ for (ULONG i = 0; i < memory_list->NumberOfMemoryRanges; ++i) {
+ MINIDUMP_MEMORY_DESCRIPTOR& descr = memory_list->MemoryRanges[i];
+ const uintptr_t range_start =
+ static_cast<uintptr_t>(descr.StartOfMemoryRange);
+ uintptr_t range_end = range_start + descr.Memory.DataSize;
+
+ if (address >= range_start &&
+ address + structuresize < range_end) {
+ // The start address falls in the range, and the end address is
+ // in bounds, return a pointer to the structure if requested.
+ if (structure != NULL)
+ *structure = RVA_TO_ADDR(dump_file_view_, descr.Memory.Rva);
+
+ return true;
+ }
+ }
+ }
+
+ // We didn't find the range in a MINIDUMP_MEMORY_LIST, so maybe this
+ // is a full dump using MINIDUMP_MEMORY64_LIST with all the memory at the
+ // end of the dump file.
+ MINIDUMP_MEMORY64_LIST* memory64_list = NULL;
+ memory_list_size = GetStream(Memory64ListStream, &memory64_list);
+ if (memory_list_size > 0 && memory64_list != NULL) {
+ // Keep track of where the current descriptor maps to.
+ RVA64 curr_rva = memory64_list->BaseRva;
+ for (ULONG i = 0; i < memory64_list->NumberOfMemoryRanges; ++i) {
+ MINIDUMP_MEMORY_DESCRIPTOR64& descr = memory64_list->MemoryRanges[i];
+ uintptr_t range_start =
+ static_cast<uintptr_t>(descr.StartOfMemoryRange);
+ uintptr_t range_end = range_start + static_cast<size_t>(descr.DataSize);
+
+ if (address >= range_start &&
+ address + structuresize < range_end) {
+ // The start address falls in the range, and the end address is
+ // in bounds, return a pointer to the structure if requested.
+ if (structure != NULL)
+ *structure = RVA_TO_ADDR(dump_file_view_, curr_rva);
+
+ return true;
+ }
+
+ // Advance the current RVA.
+ curr_rva += descr.DataSize;
+ }
+ }
+
+ return false;
+}
diff --git a/toolkit/crashreporter/breakpad-client/windows/unittests/dump_analysis.h b/toolkit/crashreporter/breakpad-client/windows/unittests/dump_analysis.h
new file mode 100644
index 0000000000..6cef48d814
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/windows/unittests/dump_analysis.h
@@ -0,0 +1,102 @@
+// Copyright (c) 2010, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef CLIENT_WINDOWS_UNITTESTS_DUMP_ANALYSIS_H_
+#define CLIENT_WINDOWS_UNITTESTS_DUMP_ANALYSIS_H_
+
+#include "client/windows/crash_generation/minidump_generator.h"
+
+// Convenience to get to the PEB pointer in a TEB.
+struct FakeTEB {
+ char dummy[0x30];
+ void* peb;
+};
+
+class DumpAnalysis {
+ public:
+ explicit DumpAnalysis(const std::wstring& file_path)
+ : dump_file_(file_path), dump_file_view_(NULL), dump_file_mapping_(NULL),
+ dump_file_handle_(NULL) {
+ EnsureDumpMapped();
+ }
+ ~DumpAnalysis();
+
+ bool HasStream(ULONG stream_number) const;
+
+ // This is template to keep type safety in the front, but we end up casting
+ // to void** inside the implementation to pass the pointer to Win32. So
+ // casting here is considered safe.
+ template <class StreamType>
+ size_t GetStream(ULONG stream_number, StreamType** stream) const {
+ return GetStreamImpl(stream_number, reinterpret_cast<void**>(stream));
+ }
+
+ bool HasTebs() const;
+ bool HasPeb() const;
+ bool HasMemory(ULONG64 address) const {
+ return HasMemory<BYTE>(address, NULL);
+ }
+
+ bool HasMemory(const void* address) const {
+ return HasMemory<BYTE>(address, NULL);
+ }
+
+ template <class StructureType>
+ bool HasMemory(ULONG64 address, StructureType** structure = NULL) const {
+ // We can't cope with 64 bit addresses for now.
+ if (address > 0xFFFFFFFFUL)
+ return false;
+
+ return HasMemory(reinterpret_cast<void*>(address), structure);
+ }
+
+ template <class StructureType>
+ bool HasMemory(const void* addr_in, StructureType** structure = NULL) const {
+ return HasMemoryImpl(addr_in, sizeof(StructureType),
+ reinterpret_cast<void**>(structure));
+ }
+
+ protected:
+ void EnsureDumpMapped();
+
+ HANDLE dump_file_mapping_;
+ HANDLE dump_file_handle_;
+ void* dump_file_view_;
+ std::wstring dump_file_;
+
+ private:
+ // This is the implementation of GetStream<>.
+ size_t GetStreamImpl(ULONG stream_number, void** stream) const;
+
+ // This is the implementation of HasMemory<>.
+ bool HasMemoryImpl(const void* addr_in, size_t pointersize,
+ void** structure) const;
+};
+
+#endif // CLIENT_WINDOWS_UNITTESTS_DUMP_ANALYSIS_H_
diff --git a/toolkit/crashreporter/breakpad-client/windows/unittests/exception_handler_death_test.cc b/toolkit/crashreporter/breakpad-client/windows/unittests/exception_handler_death_test.cc
new file mode 100644
index 0000000000..5ef9e64d1d
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/windows/unittests/exception_handler_death_test.cc
@@ -0,0 +1,587 @@
+// Copyright 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 <windows.h>
+#include <dbghelp.h>
+#include <strsafe.h>
+#include <objbase.h>
+#include <shellapi.h>
+
+#include <string>
+
+#include "breakpad_googletest_includes.h"
+#include "client/windows/crash_generation/crash_generation_server.h"
+#include "client/windows/handler/exception_handler.h"
+#include "client/windows/unittests/exception_handler_test.h"
+#include "common/windows/string_utils-inl.h"
+#include "google_breakpad/processor/minidump.h"
+
+namespace {
+
+using std::wstring;
+using namespace google_breakpad;
+
+const wchar_t kPipeName[] = L"\\\\.\\pipe\\BreakpadCrashTest\\TestCaseServer";
+const char kSuccessIndicator[] = "success";
+const char kFailureIndicator[] = "failure";
+
+// Utility function to test for a path's existence.
+BOOL DoesPathExist(const TCHAR *path_name);
+
+enum OutOfProcGuarantee {
+ OUT_OF_PROC_GUARANTEED,
+ OUT_OF_PROC_BEST_EFFORT,
+};
+
+class ExceptionHandlerDeathTest : public ::testing::Test {
+ protected:
+ // Member variable for each test that they can use
+ // for temporary storage.
+ TCHAR temp_path_[MAX_PATH];
+ // Actually constructs a temp path name.
+ virtual void SetUp();
+ // A helper method that tests can use to crash.
+ void DoCrashAccessViolation(const OutOfProcGuarantee out_of_proc_guarantee);
+ void DoCrashPureVirtualCall();
+};
+
+void ExceptionHandlerDeathTest::SetUp() {
+ const ::testing::TestInfo* const test_info =
+ ::testing::UnitTest::GetInstance()->current_test_info();
+ TCHAR temp_path[MAX_PATH] = { '\0' };
+ TCHAR test_name_wide[MAX_PATH] = { '\0' };
+ // We want the temporary directory to be what the OS returns
+ // to us, + the test case name.
+ GetTempPath(MAX_PATH, temp_path);
+ // The test case name is exposed as a c-style string,
+ // convert it to a wchar_t string.
+ int dwRet = MultiByteToWideChar(CP_ACP, 0, test_info->name(),
+ static_cast<int>(strlen(test_info->name())),
+ test_name_wide,
+ MAX_PATH);
+ if (!dwRet) {
+ assert(false);
+ }
+ StringCchPrintfW(temp_path_, MAX_PATH, L"%s%s", temp_path, test_name_wide);
+ CreateDirectory(temp_path_, NULL);
+}
+
+BOOL DoesPathExist(const TCHAR *path_name) {
+ DWORD flags = GetFileAttributes(path_name);
+ if (flags == INVALID_FILE_ATTRIBUTES) {
+ return FALSE;
+ }
+ return TRUE;
+}
+
+bool MinidumpWrittenCallback(const wchar_t* dump_path,
+ const wchar_t* minidump_id,
+ void* context,
+ EXCEPTION_POINTERS* exinfo,
+ MDRawAssertionInfo* assertion,
+ bool succeeded) {
+ if (succeeded && DoesPathExist(dump_path)) {
+ fprintf(stderr, kSuccessIndicator);
+ } else {
+ fprintf(stderr, kFailureIndicator);
+ }
+ // If we don't flush, the output doesn't get sent before
+ // this process dies.
+ fflush(stderr);
+ return succeeded;
+}
+
+TEST_F(ExceptionHandlerDeathTest, InProcTest) {
+ // For the in-proc test, we just need to instantiate an exception
+ // handler in in-proc mode, and crash. Since the entire test is
+ // reexecuted in the child process, we don't have to worry about
+ // the semantics of the exception handler being inherited/not
+ // inherited across CreateProcess().
+ ASSERT_TRUE(DoesPathExist(temp_path_));
+ scoped_ptr<google_breakpad::ExceptionHandler> exc(
+ new google_breakpad::ExceptionHandler(
+ temp_path_,
+ NULL,
+ &MinidumpWrittenCallback,
+ NULL,
+ google_breakpad::ExceptionHandler::HANDLER_ALL));
+
+ // Disable GTest SEH handler
+ testing::DisableExceptionHandlerInScope disable_exception_handler;
+
+ int *i = NULL;
+ ASSERT_DEATH((*i)++, kSuccessIndicator);
+}
+
+static bool gDumpCallbackCalled = false;
+
+void clientDumpCallback(void *dump_context,
+ const google_breakpad::ClientInfo *client_info,
+ const std::wstring *dump_path) {
+ gDumpCallbackCalled = true;
+}
+
+void ExceptionHandlerDeathTest::DoCrashAccessViolation(
+ const OutOfProcGuarantee out_of_proc_guarantee) {
+ scoped_ptr<google_breakpad::ExceptionHandler> exc;
+
+ if (out_of_proc_guarantee == OUT_OF_PROC_GUARANTEED) {
+ google_breakpad::CrashGenerationClient *client =
+ new google_breakpad::CrashGenerationClient(kPipeName,
+ MiniDumpNormal,
+ NULL); // custom_info
+ ASSERT_TRUE(client->Register());
+ exc.reset(new google_breakpad::ExceptionHandler(
+ temp_path_,
+ NULL, // filter
+ NULL, // callback
+ NULL, // callback_context
+ google_breakpad::ExceptionHandler::HANDLER_ALL,
+ client));
+ } else {
+ ASSERT_TRUE(out_of_proc_guarantee == OUT_OF_PROC_BEST_EFFORT);
+ exc.reset(new google_breakpad::ExceptionHandler(
+ temp_path_,
+ NULL, // filter
+ NULL, // callback
+ NULL, // callback_context
+ google_breakpad::ExceptionHandler::HANDLER_ALL,
+ MiniDumpNormal,
+ kPipeName,
+ NULL)); // custom_info
+ }
+
+ // Disable GTest SEH handler
+ testing::DisableExceptionHandlerInScope disable_exception_handler;
+
+ // Although this is executing in the child process of the death test,
+ // if it's not true we'll still get an error rather than the crash
+ // being expected.
+ ASSERT_TRUE(exc->IsOutOfProcess());
+ int *i = NULL;
+ printf("%d\n", (*i)++);
+}
+
+TEST_F(ExceptionHandlerDeathTest, OutOfProcTest) {
+ // We can take advantage of a detail of google test here to save some
+ // complexity in testing: when you do a death test, it actually forks.
+ // So we can make the main test harness the crash generation server,
+ // and call ASSERT_DEATH on a NULL dereference, it to expecting test
+ // the out of process scenario, since it's happening in a different
+ // process! This is different from the above because, above, we pass
+ // a NULL pipe name, and we also don't start a crash generation server.
+
+ ASSERT_TRUE(DoesPathExist(temp_path_));
+ std::wstring dump_path(temp_path_);
+ google_breakpad::CrashGenerationServer server(
+ kPipeName, NULL, NULL, NULL, &clientDumpCallback, NULL, NULL, NULL, NULL,
+ NULL, true, &dump_path);
+
+ // This HAS to be EXPECT_, because when this test case is executed in the
+ // child process, the server registration will fail due to the named pipe
+ // being the same.
+ EXPECT_TRUE(server.Start());
+ gDumpCallbackCalled = false;
+ ASSERT_DEATH(this->DoCrashAccessViolation(OUT_OF_PROC_BEST_EFFORT), "");
+ EXPECT_TRUE(gDumpCallbackCalled);
+}
+
+TEST_F(ExceptionHandlerDeathTest, OutOfProcGuaranteedTest) {
+ // This is similar to the previous test (OutOfProcTest). The only difference
+ // is that in this test, the crash generation client is created and registered
+ // with the crash generation server outside of the ExceptionHandler
+ // constructor which allows breakpad users to opt out of the default
+ // in-process dump generation when the registration with the crash generation
+ // server fails.
+
+ ASSERT_TRUE(DoesPathExist(temp_path_));
+ std::wstring dump_path(temp_path_);
+ google_breakpad::CrashGenerationServer server(
+ kPipeName, NULL, NULL, NULL, &clientDumpCallback, NULL, NULL, NULL, NULL,
+ NULL, true, &dump_path);
+
+ // This HAS to be EXPECT_, because when this test case is executed in the
+ // child process, the server registration will fail due to the named pipe
+ // being the same.
+ EXPECT_TRUE(server.Start());
+ gDumpCallbackCalled = false;
+ ASSERT_DEATH(this->DoCrashAccessViolation(OUT_OF_PROC_GUARANTEED), "");
+ EXPECT_TRUE(gDumpCallbackCalled);
+}
+
+TEST_F(ExceptionHandlerDeathTest, InvalidParameterTest) {
+ using google_breakpad::ExceptionHandler;
+
+ ASSERT_TRUE(DoesPathExist(temp_path_));
+ ExceptionHandler handler(temp_path_, NULL, NULL, NULL,
+ ExceptionHandler::HANDLER_INVALID_PARAMETER);
+
+ // Disable the message box for assertions
+ _CrtSetReportMode(_CRT_ASSERT, 0);
+
+ // Call with a bad argument. The invalid parameter will be swallowed
+ // and a dump will be generated, the process will exit(0).
+ ASSERT_EXIT(printf(NULL), ::testing::ExitedWithCode(0), "");
+}
+
+
+struct PureVirtualCallBase {
+ PureVirtualCallBase() {
+ // We have to reinterpret so the linker doesn't get confused because the
+ // method isn't defined.
+ reinterpret_cast<PureVirtualCallBase*>(this)->PureFunction();
+ }
+ virtual ~PureVirtualCallBase() {}
+ virtual void PureFunction() const = 0;
+};
+struct PureVirtualCall : public PureVirtualCallBase {
+ PureVirtualCall() { PureFunction(); }
+ virtual void PureFunction() const {}
+};
+
+void ExceptionHandlerDeathTest::DoCrashPureVirtualCall() {
+ PureVirtualCall instance;
+}
+
+TEST_F(ExceptionHandlerDeathTest, PureVirtualCallTest) {
+ using google_breakpad::ExceptionHandler;
+
+ ASSERT_TRUE(DoesPathExist(temp_path_));
+ ExceptionHandler handler(temp_path_, NULL, NULL, NULL,
+ ExceptionHandler::HANDLER_PURECALL);
+
+ // Disable the message box for assertions
+ _CrtSetReportMode(_CRT_ASSERT, 0);
+
+ // Calls a pure virtual function.
+ EXPECT_EXIT(DoCrashPureVirtualCall(), ::testing::ExitedWithCode(0), "");
+}
+
+wstring find_minidump_in_directory(const wstring &directory) {
+ wstring search_path = directory + L"\\*";
+ WIN32_FIND_DATA find_data;
+ HANDLE find_handle = FindFirstFileW(search_path.c_str(), &find_data);
+ if (find_handle == INVALID_HANDLE_VALUE)
+ return wstring();
+
+ wstring filename;
+ do {
+ const wchar_t extension[] = L".dmp";
+ const size_t extension_length = sizeof(extension) / sizeof(extension[0]) - 1;
+ const size_t filename_length = wcslen(find_data.cFileName);
+ if (filename_length > extension_length &&
+ wcsncmp(extension,
+ find_data.cFileName + filename_length - extension_length,
+ extension_length) == 0) {
+ filename = directory + L"\\" + find_data.cFileName;
+ break;
+ }
+ } while (FindNextFile(find_handle, &find_data));
+ FindClose(find_handle);
+ return filename;
+}
+
+#ifndef ADDRESS_SANITIZER
+
+TEST_F(ExceptionHandlerDeathTest, InstructionPointerMemory) {
+ ASSERT_TRUE(DoesPathExist(temp_path_));
+ scoped_ptr<google_breakpad::ExceptionHandler> exc(
+ new google_breakpad::ExceptionHandler(
+ temp_path_,
+ NULL,
+ NULL,
+ NULL,
+ google_breakpad::ExceptionHandler::HANDLER_ALL));
+
+ // Disable GTest SEH handler
+ testing::DisableExceptionHandlerInScope disable_exception_handler;
+
+ // Get some executable memory.
+ const uint32_t kMemorySize = 256; // bytes
+ const int kOffset = kMemorySize / 2;
+ // This crashes with SIGILL on x86/x86-64/arm.
+ const unsigned char instructions[] = { 0xff, 0xff, 0xff, 0xff };
+ char* memory = reinterpret_cast<char*>(VirtualAlloc(NULL,
+ kMemorySize,
+ MEM_COMMIT | MEM_RESERVE,
+ PAGE_EXECUTE_READWRITE));
+ ASSERT_TRUE(memory);
+
+ // Write some instructions that will crash. Put them
+ // in the middle of the block of memory, because the
+ // minidump should contain 128 bytes on either side of the
+ // instruction pointer.
+ memcpy(memory + kOffset, instructions, sizeof(instructions));
+
+ // Now execute the instructions, which should crash.
+ typedef void (*void_function)(void);
+ void_function memory_function =
+ reinterpret_cast<void_function>(memory + kOffset);
+ ASSERT_DEATH(memory_function(), "");
+
+ // free the memory.
+ VirtualFree(memory, 0, MEM_RELEASE);
+
+ // Verify that the resulting minidump contains the memory around the IP
+ wstring minidump_filename_wide = find_minidump_in_directory(temp_path_);
+ ASSERT_FALSE(minidump_filename_wide.empty());
+ string minidump_filename;
+ ASSERT_TRUE(WindowsStringUtils::safe_wcstombs(minidump_filename_wide,
+ &minidump_filename));
+
+ // Read the minidump. Locate the exception record and the
+ // memory list, and then ensure that there is a memory region
+ // in the memory list that covers at least 128 bytes on either
+ // side of the instruction pointer from the exception record.
+ {
+ Minidump minidump(minidump_filename);
+ ASSERT_TRUE(minidump.Read());
+
+ MinidumpException* exception = minidump.GetException();
+ MinidumpMemoryList* memory_list = minidump.GetMemoryList();
+ ASSERT_TRUE(exception);
+ ASSERT_TRUE(memory_list);
+ ASSERT_LT((unsigned)0, memory_list->region_count());
+
+ MinidumpContext* context = exception->GetContext();
+ ASSERT_TRUE(context);
+
+ uint64_t instruction_pointer;
+ ASSERT_TRUE(context->GetInstructionPointer(&instruction_pointer));
+
+ MinidumpMemoryRegion* region =
+ memory_list->GetMemoryRegionForAddress(instruction_pointer);
+ ASSERT_TRUE(region);
+
+ EXPECT_LE(kMemorySize, region->GetSize());
+ const uint8_t* bytes = region->GetMemory();
+ ASSERT_TRUE(bytes);
+
+ uint64_t ip_offset = instruction_pointer - region->GetBase();
+ EXPECT_GE(region->GetSize() - kOffset, ip_offset);
+ EXPECT_LE(kOffset, ip_offset);
+
+ uint8_t prefix_bytes[kOffset];
+ uint8_t suffix_bytes[kMemorySize - kOffset - sizeof(instructions)];
+ memset(prefix_bytes, 0, sizeof(prefix_bytes));
+ memset(suffix_bytes, 0, sizeof(suffix_bytes));
+ EXPECT_EQ(0, memcmp(bytes + ip_offset - kOffset, prefix_bytes,
+ sizeof(prefix_bytes)));
+ EXPECT_EQ(0, memcmp(bytes + ip_offset, instructions, sizeof(instructions)));
+ EXPECT_EQ(0, memcmp(bytes + ip_offset + sizeof(instructions), suffix_bytes,
+ sizeof(suffix_bytes)));
+ }
+
+ DeleteFileW(minidump_filename_wide.c_str());
+}
+
+TEST_F(ExceptionHandlerDeathTest, InstructionPointerMemoryMinBound) {
+ ASSERT_TRUE(DoesPathExist(temp_path_));
+ scoped_ptr<google_breakpad::ExceptionHandler> exc(
+ new google_breakpad::ExceptionHandler(
+ temp_path_,
+ NULL,
+ NULL,
+ NULL,
+ google_breakpad::ExceptionHandler::HANDLER_ALL));
+
+ // Disable GTest SEH handler
+ testing::DisableExceptionHandlerInScope disable_exception_handler;
+
+ SYSTEM_INFO sSysInfo; // Useful information about the system
+ GetSystemInfo(&sSysInfo); // Initialize the structure.
+
+ const uint32_t kMemorySize = 256; // bytes
+ const DWORD kPageSize = sSysInfo.dwPageSize;
+ const int kOffset = 0;
+ // This crashes with SIGILL on x86/x86-64/arm.
+ const unsigned char instructions[] = { 0xff, 0xff, 0xff, 0xff };
+ // Get some executable memory. Specifically, reserve two pages,
+ // but only commit the second.
+ char* all_memory = reinterpret_cast<char*>(VirtualAlloc(NULL,
+ kPageSize * 2,
+ MEM_RESERVE,
+ PAGE_NOACCESS));
+ ASSERT_TRUE(all_memory);
+ char* memory = all_memory + kPageSize;
+ ASSERT_TRUE(VirtualAlloc(memory, kPageSize,
+ MEM_COMMIT, PAGE_EXECUTE_READWRITE));
+
+ // Write some instructions that will crash. Put them
+ // in the middle of the block of memory, because the
+ // minidump should contain 128 bytes on either side of the
+ // instruction pointer.
+ memcpy(memory + kOffset, instructions, sizeof(instructions));
+
+ // Now execute the instructions, which should crash.
+ typedef void (*void_function)(void);
+ void_function memory_function =
+ reinterpret_cast<void_function>(memory + kOffset);
+ ASSERT_DEATH(memory_function(), "");
+
+ // free the memory.
+ VirtualFree(memory, 0, MEM_RELEASE);
+
+ // Verify that the resulting minidump contains the memory around the IP
+ wstring minidump_filename_wide = find_minidump_in_directory(temp_path_);
+ ASSERT_FALSE(minidump_filename_wide.empty());
+ string minidump_filename;
+ ASSERT_TRUE(WindowsStringUtils::safe_wcstombs(minidump_filename_wide,
+ &minidump_filename));
+
+ // Read the minidump. Locate the exception record and the
+ // memory list, and then ensure that there is a memory region
+ // in the memory list that covers the instruction pointer from
+ // the exception record.
+ {
+ Minidump minidump(minidump_filename);
+ ASSERT_TRUE(minidump.Read());
+
+ MinidumpException* exception = minidump.GetException();
+ MinidumpMemoryList* memory_list = minidump.GetMemoryList();
+ ASSERT_TRUE(exception);
+ ASSERT_TRUE(memory_list);
+ ASSERT_LT((unsigned)0, memory_list->region_count());
+
+ MinidumpContext* context = exception->GetContext();
+ ASSERT_TRUE(context);
+
+ uint64_t instruction_pointer;
+ ASSERT_TRUE(context->GetInstructionPointer(&instruction_pointer));
+
+ MinidumpMemoryRegion* region =
+ memory_list->GetMemoryRegionForAddress(instruction_pointer);
+ ASSERT_TRUE(region);
+
+ EXPECT_EQ(kMemorySize / 2, region->GetSize());
+ const uint8_t* bytes = region->GetMemory();
+ ASSERT_TRUE(bytes);
+
+ uint8_t suffix_bytes[kMemorySize / 2 - sizeof(instructions)];
+ memset(suffix_bytes, 0, sizeof(suffix_bytes));
+ EXPECT_TRUE(memcmp(bytes + kOffset,
+ instructions, sizeof(instructions)) == 0);
+ EXPECT_TRUE(memcmp(bytes + kOffset + sizeof(instructions),
+ suffix_bytes, sizeof(suffix_bytes)) == 0);
+ }
+
+ DeleteFileW(minidump_filename_wide.c_str());
+}
+
+TEST_F(ExceptionHandlerDeathTest, InstructionPointerMemoryMaxBound) {
+ ASSERT_TRUE(DoesPathExist(temp_path_));
+ scoped_ptr<google_breakpad::ExceptionHandler> exc(
+ new google_breakpad::ExceptionHandler(
+ temp_path_,
+ NULL,
+ NULL,
+ NULL,
+ google_breakpad::ExceptionHandler::HANDLER_ALL));
+
+ // Disable GTest SEH handler
+ testing::DisableExceptionHandlerInScope disable_exception_handler;
+
+ SYSTEM_INFO sSysInfo; // Useful information about the system
+ GetSystemInfo(&sSysInfo); // Initialize the structure.
+
+ const DWORD kPageSize = sSysInfo.dwPageSize;
+ // This crashes with SIGILL on x86/x86-64/arm.
+ const unsigned char instructions[] = { 0xff, 0xff, 0xff, 0xff };
+ const int kOffset = kPageSize - sizeof(instructions);
+ // Get some executable memory. Specifically, reserve two pages,
+ // but only commit the first.
+ char* memory = reinterpret_cast<char*>(VirtualAlloc(NULL,
+ kPageSize * 2,
+ MEM_RESERVE,
+ PAGE_NOACCESS));
+ ASSERT_TRUE(memory);
+ ASSERT_TRUE(VirtualAlloc(memory, kPageSize,
+ MEM_COMMIT, PAGE_EXECUTE_READWRITE));
+
+ // Write some instructions that will crash.
+ memcpy(memory + kOffset, instructions, sizeof(instructions));
+
+ // Now execute the instructions, which should crash.
+ typedef void (*void_function)(void);
+ void_function memory_function =
+ reinterpret_cast<void_function>(memory + kOffset);
+ ASSERT_DEATH(memory_function(), "");
+
+ // free the memory.
+ VirtualFree(memory, 0, MEM_RELEASE);
+
+ // Verify that the resulting minidump contains the memory around the IP
+ wstring minidump_filename_wide = find_minidump_in_directory(temp_path_);
+ ASSERT_FALSE(minidump_filename_wide.empty());
+ string minidump_filename;
+ ASSERT_TRUE(WindowsStringUtils::safe_wcstombs(minidump_filename_wide,
+ &minidump_filename));
+
+ // Read the minidump. Locate the exception record and the
+ // memory list, and then ensure that there is a memory region
+ // in the memory list that covers the instruction pointer from
+ // the exception record.
+ {
+ Minidump minidump(minidump_filename);
+ ASSERT_TRUE(minidump.Read());
+
+ MinidumpException* exception = minidump.GetException();
+ MinidumpMemoryList* memory_list = minidump.GetMemoryList();
+ ASSERT_TRUE(exception);
+ ASSERT_TRUE(memory_list);
+ ASSERT_LT((unsigned)0, memory_list->region_count());
+
+ MinidumpContext* context = exception->GetContext();
+ ASSERT_TRUE(context);
+
+ uint64_t instruction_pointer;
+ ASSERT_TRUE(context->GetInstructionPointer(&instruction_pointer));
+
+ MinidumpMemoryRegion* region =
+ memory_list->GetMemoryRegionForAddress(instruction_pointer);
+ ASSERT_TRUE(region);
+
+ const size_t kPrefixSize = 128; // bytes
+ EXPECT_EQ(kPrefixSize + sizeof(instructions), region->GetSize());
+ const uint8_t* bytes = region->GetMemory();
+ ASSERT_TRUE(bytes);
+
+ uint8_t prefix_bytes[kPrefixSize];
+ memset(prefix_bytes, 0, sizeof(prefix_bytes));
+ EXPECT_EQ(0, memcmp(bytes, prefix_bytes, sizeof(prefix_bytes)));
+ EXPECT_EQ(0, memcmp(bytes + kPrefixSize,
+ instructions, sizeof(instructions)));
+ }
+
+ DeleteFileW(minidump_filename_wide.c_str());
+}
+
+#endif // !ADDRESS_SANITIZER
+
+} // namespace
diff --git a/toolkit/crashreporter/breakpad-client/windows/unittests/exception_handler_nesting_test.cc b/toolkit/crashreporter/breakpad-client/windows/unittests/exception_handler_nesting_test.cc
new file mode 100644
index 0000000000..3ae1d7cd05
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/windows/unittests/exception_handler_nesting_test.cc
@@ -0,0 +1,327 @@
+// Copyright 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 <windows.h>
+
+#include <string>
+
+#include "breakpad_googletest_includes.h"
+#include "client/windows/handler/exception_handler.h"
+#include "client/windows/unittests/exception_handler_test.h"
+
+namespace {
+
+const char kFoo[] = "foo";
+const char kBar[] = "bar";
+
+const char kStartOfLine[] = "^";
+const char kEndOfLine[] = "$";
+
+const char kFilterReturnsTrue[] = "filter_returns_true";
+const char kFilterReturnsFalse[] = "filter_returns_false";
+
+const char kCallbackReturnsTrue[] = "callback_returns_true";
+const char kCallbackReturnsFalse[] = "callback_returns_false";
+
+bool DoesPathExist(const wchar_t *path_name) {
+ DWORD flags = GetFileAttributes(path_name);
+ if (flags == INVALID_FILE_ATTRIBUTES) {
+ return false;
+ }
+ return true;
+}
+
+// A callback function to run before Breakpad performs any substantial
+// processing of an exception. A FilterCallback is called before writing
+// a minidump. context is the parameter supplied by the user as
+// callback_context when the handler was created. exinfo points to the
+// exception record, if any; assertion points to assertion information,
+// if any.
+//
+// If a FilterCallback returns true, Breakpad will continue processing,
+// attempting to write a minidump. If a FilterCallback returns false,
+// Breakpad will immediately report the exception as unhandled without
+// writing a minidump, allowing another handler the opportunity to handle it.
+template <bool filter_return_value>
+bool CrashHandlerFilter(void* context,
+ EXCEPTION_POINTERS* exinfo,
+ MDRawAssertionInfo* assertion) {
+ if (filter_return_value) {
+ fprintf(stderr, kFilterReturnsTrue);
+ } else {
+ fprintf(stderr, kFilterReturnsFalse);
+ }
+ fflush(stderr);
+
+ return filter_return_value;
+}
+
+// A callback function to run after the minidump has been written.
+// minidump_id is a unique id for the dump, so the minidump
+// file is <dump_path>\<minidump_id>.dmp. context is the parameter supplied
+// by the user as callback_context when the handler was created. exinfo
+// points to the exception record, or NULL if no exception occurred.
+// succeeded indicates whether a minidump file was successfully written.
+// assertion points to information about an assertion if the handler was
+// invoked by an assertion.
+//
+// If an exception occurred and the callback returns true, Breakpad will treat
+// the exception as fully-handled, suppressing any other handlers from being
+// notified of the exception. If the callback returns false, Breakpad will
+// treat the exception as unhandled, and allow another handler to handle it.
+// If there are no other handlers, Breakpad will report the exception to the
+// system as unhandled, allowing a debugger or native crash dialog the
+// opportunity to handle the exception. Most callback implementations
+// should normally return the value of |succeeded|, or when they wish to
+// not report an exception of handled, false. Callbacks will rarely want to
+// return true directly (unless |succeeded| is true).
+//
+// For out-of-process dump generation, dump path and minidump ID will always
+// be NULL. In case of out-of-process dump generation, the dump path and
+// minidump id are controlled by the server process and are not communicated
+// back to the crashing process.
+template <bool callback_return_value>
+bool MinidumpWrittenCallback(const wchar_t* dump_path,
+ const wchar_t* minidump_id,
+ void* context,
+ EXCEPTION_POINTERS* exinfo,
+ MDRawAssertionInfo* assertion,
+ bool succeeded) {
+ bool rv = false;
+ if (callback_return_value &&
+ succeeded &&
+ DoesPathExist(dump_path)) {
+ rv = true;
+ fprintf(stderr, kCallbackReturnsTrue);
+ } else {
+ fprintf(stderr, kCallbackReturnsFalse);
+ }
+ fflush(stderr);
+
+ return rv;
+}
+
+
+void DoCrash(const char *message) {
+ if (message) {
+ fprintf(stderr, "%s", message);
+ fflush(stderr);
+ }
+ int *i = NULL;
+ (*i)++;
+
+ ASSERT_TRUE(false);
+}
+
+void InstallExceptionHandlerAndCrash(bool install_filter,
+ bool filter_return_value,
+ bool install_callback,
+ bool callback_return_value) {
+ wchar_t temp_path[MAX_PATH] = { '\0' };
+ GetTempPath(MAX_PATH, temp_path);
+
+ ASSERT_TRUE(DoesPathExist(temp_path));
+ google_breakpad::ExceptionHandler exc(
+ temp_path,
+ install_filter ?
+ (filter_return_value ?
+ &CrashHandlerFilter<true> :
+ &CrashHandlerFilter<false>) :
+ NULL,
+ install_callback ?
+ (callback_return_value ?
+ &MinidumpWrittenCallback<true> :
+ &MinidumpWrittenCallback<false>) :
+ NULL,
+ NULL, // callback_context
+ google_breakpad::ExceptionHandler::HANDLER_EXCEPTION);
+
+ // Disable GTest SEH handler
+ testing::DisableExceptionHandlerInScope disable_exception_handler;
+
+ DoCrash(NULL);
+}
+
+TEST(AssertDeathSanity, Simple) {
+ ASSERT_DEATH(DoCrash(NULL), "");
+}
+
+TEST(AssertDeathSanity, Regex) {
+ ASSERT_DEATH(DoCrash(kFoo),
+ std::string(kStartOfLine) +
+ std::string(kFoo) +
+ std::string(kEndOfLine));
+
+ ASSERT_DEATH(DoCrash(kBar),
+ std::string(kStartOfLine) +
+ std::string(kBar) +
+ std::string(kEndOfLine));
+}
+
+TEST(ExceptionHandlerCallbacks, FilterTrue_No_Callback) {
+ ASSERT_DEATH(
+ InstallExceptionHandlerAndCrash(true, // install_filter
+ true, // filter_return_value
+ false, // install_callback
+ false), // callback_return_value
+ std::string(kStartOfLine) +
+ std::string(kFilterReturnsTrue) +
+ std::string(kEndOfLine));
+}
+
+TEST(ExceptionHandlerCallbacks, FilterTrue_Callback) {
+ ASSERT_DEATH(
+ InstallExceptionHandlerAndCrash(true, // install_filter
+ true, // filter_return_value
+ true, // install_callback
+ false), // callback_return_value
+ std::string(kStartOfLine) +
+ std::string(kFilterReturnsTrue) +
+ std::string(kCallbackReturnsFalse) +
+ std::string(kEndOfLine));
+}
+
+TEST(ExceptionHandlerCallbacks, FilterFalse_No_Callback) {
+ ASSERT_DEATH(
+ InstallExceptionHandlerAndCrash(true, // install_filter
+ false, // filter_return_value
+ false, // install_callback
+ false), // callback_return_value
+ std::string(kStartOfLine) +
+ std::string(kFilterReturnsFalse) +
+ std::string(kEndOfLine));
+}
+
+// Callback shouldn't be executed when filter returns false
+TEST(ExceptionHandlerCallbacks, FilterFalse_Callback) {
+ ASSERT_DEATH(
+ InstallExceptionHandlerAndCrash(true, // install_filter
+ false, // filter_return_value
+ true, // install_callback
+ false), // callback_return_value
+ std::string(kStartOfLine) +
+ std::string(kFilterReturnsFalse) +
+ std::string(kEndOfLine));
+}
+
+TEST(ExceptionHandlerCallbacks, No_Filter_No_Callback) {
+ ASSERT_DEATH(
+ InstallExceptionHandlerAndCrash(false, // install_filter
+ true, // filter_return_value
+ false, // install_callback
+ false), // callback_return_value
+ std::string(kStartOfLine) +
+ std::string(kEndOfLine));
+}
+
+TEST(ExceptionHandlerCallbacks, No_Filter_Callback) {
+ ASSERT_DEATH(
+ InstallExceptionHandlerAndCrash(false, // install_filter
+ true, // filter_return_value
+ true, // install_callback
+ false), // callback_return_value
+ std::string(kStartOfLine) +
+ std::string(kCallbackReturnsFalse) +
+ std::string(kEndOfLine));
+}
+
+
+TEST(ExceptionHandlerNesting, Skip_From_Inner_Filter) {
+ wchar_t temp_path[MAX_PATH] = { '\0' };
+ GetTempPath(MAX_PATH, temp_path);
+
+ ASSERT_TRUE(DoesPathExist(temp_path));
+ google_breakpad::ExceptionHandler exc(
+ temp_path,
+ &CrashHandlerFilter<true>,
+ &MinidumpWrittenCallback<false>,
+ NULL, // callback_context
+ google_breakpad::ExceptionHandler::HANDLER_EXCEPTION);
+
+ ASSERT_DEATH(
+ InstallExceptionHandlerAndCrash(true, // install_filter
+ false, // filter_return_value
+ true, // install_callback
+ true), // callback_return_value
+ std::string(kStartOfLine) +
+ std::string(kFilterReturnsFalse) + // inner filter
+ std::string(kFilterReturnsTrue) + // outer filter
+ std::string(kCallbackReturnsFalse) + // outer callback
+ std::string(kEndOfLine));
+}
+
+TEST(ExceptionHandlerNesting, Skip_From_Inner_Callback) {
+ wchar_t temp_path[MAX_PATH] = { '\0' };
+ GetTempPath(MAX_PATH, temp_path);
+
+ ASSERT_TRUE(DoesPathExist(temp_path));
+ google_breakpad::ExceptionHandler exc(
+ temp_path,
+ &CrashHandlerFilter<true>,
+ &MinidumpWrittenCallback<false>,
+ NULL, // callback_context
+ google_breakpad::ExceptionHandler::HANDLER_EXCEPTION);
+
+ ASSERT_DEATH(
+ InstallExceptionHandlerAndCrash(true, // install_filter
+ true, // filter_return_value
+ true, // install_callback
+ false), // callback_return_value
+ std::string(kStartOfLine) +
+ std::string(kFilterReturnsTrue) + // inner filter
+ std::string(kCallbackReturnsFalse) + // inner callback
+ std::string(kFilterReturnsTrue) + // outer filter
+ std::string(kCallbackReturnsFalse) + // outer callback
+ std::string(kEndOfLine));
+}
+
+TEST(ExceptionHandlerNesting, Handled_By_Inner_Handler) {
+ wchar_t temp_path[MAX_PATH] = { '\0' };
+ GetTempPath(MAX_PATH, temp_path);
+
+ ASSERT_TRUE(DoesPathExist(temp_path));
+ google_breakpad::ExceptionHandler exc(
+ temp_path,
+ &CrashHandlerFilter<true>,
+ &MinidumpWrittenCallback<true>,
+ NULL, // callback_context
+ google_breakpad::ExceptionHandler::HANDLER_EXCEPTION);
+
+ ASSERT_DEATH(
+ InstallExceptionHandlerAndCrash(true, // install_filter
+ true, // filter_return_value
+ true, // install_callback
+ true), // callback_return_value
+ std::string(kStartOfLine) +
+ std::string(kFilterReturnsTrue) + // inner filter
+ std::string(kCallbackReturnsTrue) + // inner callback
+ std::string(kEndOfLine));
+}
+
+} // namespace
diff --git a/toolkit/crashreporter/breakpad-client/windows/unittests/exception_handler_test.cc b/toolkit/crashreporter/breakpad-client/windows/unittests/exception_handler_test.cc
new file mode 100644
index 0000000000..a4ce12a8aa
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/windows/unittests/exception_handler_test.cc
@@ -0,0 +1,503 @@
+// Copyright 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 "client/windows/unittests/exception_handler_test.h"
+
+#include <windows.h>
+#include <dbghelp.h>
+#include <strsafe.h>
+#include <objbase.h>
+#include <shellapi.h>
+
+#include <string>
+
+#include "breakpad_googletest_includes.h"
+#include "client/windows/crash_generation/crash_generation_server.h"
+#include "client/windows/handler/exception_handler.h"
+#include "client/windows/unittests/dump_analysis.h" // NOLINT
+#include "common/windows/string_utils-inl.h"
+#include "google_breakpad/processor/minidump.h"
+
+namespace testing {
+
+DisableExceptionHandlerInScope::DisableExceptionHandlerInScope() {
+ catch_exceptions_ = GTEST_FLAG(catch_exceptions);
+ GTEST_FLAG(catch_exceptions) = false;
+}
+
+DisableExceptionHandlerInScope::~DisableExceptionHandlerInScope() {
+ GTEST_FLAG(catch_exceptions) = catch_exceptions_;
+}
+
+} // namespace testing
+
+namespace {
+
+using std::wstring;
+using namespace google_breakpad;
+
+const wchar_t kPipeName[] = L"\\\\.\\pipe\\BreakpadCrashTest\\TestCaseServer";
+const char kSuccessIndicator[] = "success";
+const char kFailureIndicator[] = "failure";
+
+const MINIDUMP_TYPE kFullDumpType = static_cast<MINIDUMP_TYPE>(
+ MiniDumpWithFullMemory | // Full memory from process.
+ MiniDumpWithProcessThreadData | // Get PEB and TEB.
+ MiniDumpWithHandleData); // Get all handle information.
+
+class ExceptionHandlerTest : public ::testing::Test {
+ protected:
+ // Member variable for each test that they can use
+ // for temporary storage.
+ TCHAR temp_path_[MAX_PATH];
+
+ // Actually constructs a temp path name.
+ virtual void SetUp();
+
+ // Deletes temporary files.
+ virtual void TearDown();
+
+ void DoCrashInvalidParameter();
+ void DoCrashPureVirtualCall();
+
+ // Utility function to test for a path's existence.
+ static BOOL DoesPathExist(const TCHAR *path_name);
+
+ // Client callback.
+ static void ClientDumpCallback(
+ void *dump_context,
+ const google_breakpad::ClientInfo *client_info,
+ const std::wstring *dump_path);
+
+ static bool DumpCallback(const wchar_t* dump_path,
+ const wchar_t* minidump_id,
+ void* context,
+ EXCEPTION_POINTERS* exinfo,
+ MDRawAssertionInfo* assertion,
+ bool succeeded);
+
+ static std::wstring dump_file;
+ static std::wstring full_dump_file;
+};
+
+std::wstring ExceptionHandlerTest::dump_file;
+std::wstring ExceptionHandlerTest::full_dump_file;
+
+void ExceptionHandlerTest::SetUp() {
+ const ::testing::TestInfo* const test_info =
+ ::testing::UnitTest::GetInstance()->current_test_info();
+ TCHAR temp_path[MAX_PATH] = { '\0' };
+ TCHAR test_name_wide[MAX_PATH] = { '\0' };
+ // We want the temporary directory to be what the OS returns
+ // to us, + the test case name.
+ GetTempPath(MAX_PATH, temp_path);
+ // THe test case name is exposed to use as a c-style string,
+ // But we might be working in UNICODE here on Windows.
+ int dwRet = MultiByteToWideChar(CP_ACP, 0, test_info->name(),
+ static_cast<int>(strlen(test_info->name())),
+ test_name_wide,
+ MAX_PATH);
+ if (!dwRet) {
+ assert(false);
+ }
+ StringCchPrintfW(temp_path_, MAX_PATH, L"%s%s", temp_path, test_name_wide);
+ CreateDirectory(temp_path_, NULL);
+}
+
+void ExceptionHandlerTest::TearDown() {
+ if (!dump_file.empty()) {
+ ::DeleteFile(dump_file.c_str());
+ dump_file = L"";
+ }
+ if (!full_dump_file.empty()) {
+ ::DeleteFile(full_dump_file.c_str());
+ full_dump_file = L"";
+ }
+}
+
+BOOL ExceptionHandlerTest::DoesPathExist(const TCHAR *path_name) {
+ DWORD flags = GetFileAttributes(path_name);
+ if (flags == INVALID_FILE_ATTRIBUTES) {
+ return FALSE;
+ }
+ return TRUE;
+}
+
+// static
+void ExceptionHandlerTest::ClientDumpCallback(
+ void *dump_context,
+ const google_breakpad::ClientInfo *client_info,
+ const wstring *dump_path) {
+ dump_file = *dump_path;
+ // Create the full dump file name from the dump path.
+ full_dump_file = dump_file.substr(0, dump_file.length() - 4) + L"-full.dmp";
+}
+
+// static
+bool ExceptionHandlerTest::DumpCallback(const wchar_t* dump_path,
+ const wchar_t* minidump_id,
+ void* context,
+ EXCEPTION_POINTERS* exinfo,
+ MDRawAssertionInfo* assertion,
+ bool succeeded) {
+ dump_file = dump_path;
+ dump_file += L"\\";
+ dump_file += minidump_id;
+ dump_file += L".dmp";
+ return succeeded;
+}
+
+void ExceptionHandlerTest::DoCrashInvalidParameter() {
+ google_breakpad::ExceptionHandler *exc =
+ new google_breakpad::ExceptionHandler(
+ temp_path_, NULL, NULL, NULL,
+ google_breakpad::ExceptionHandler::HANDLER_INVALID_PARAMETER,
+ kFullDumpType, kPipeName, NULL);
+
+ // Disable the message box for assertions
+ _CrtSetReportMode(_CRT_ASSERT, 0);
+
+ // Although this is executing in the child process of the death test,
+ // if it's not true we'll still get an error rather than the crash
+ // being expected.
+ ASSERT_TRUE(exc->IsOutOfProcess());
+ printf(NULL);
+}
+
+
+struct PureVirtualCallBase {
+ PureVirtualCallBase() {
+ // We have to reinterpret so the linker doesn't get confused because the
+ // method isn't defined.
+ reinterpret_cast<PureVirtualCallBase*>(this)->PureFunction();
+ }
+ virtual ~PureVirtualCallBase() {}
+ virtual void PureFunction() const = 0;
+};
+struct PureVirtualCall : public PureVirtualCallBase {
+ PureVirtualCall() { PureFunction(); }
+ virtual void PureFunction() const {}
+};
+
+void ExceptionHandlerTest::DoCrashPureVirtualCall() {
+ google_breakpad::ExceptionHandler *exc =
+ new google_breakpad::ExceptionHandler(
+ temp_path_, NULL, NULL, NULL,
+ google_breakpad::ExceptionHandler::HANDLER_PURECALL,
+ kFullDumpType, kPipeName, NULL);
+
+ // Disable the message box for assertions
+ _CrtSetReportMode(_CRT_ASSERT, 0);
+
+ // Although this is executing in the child process of the death test,
+ // if it's not true we'll still get an error rather than the crash
+ // being expected.
+ ASSERT_TRUE(exc->IsOutOfProcess());
+
+ // Create a new frame to ensure PureVirtualCall is not optimized to some
+ // other line in this function.
+ {
+ PureVirtualCall instance;
+ }
+}
+
+// This test validates that the minidump is written correctly.
+TEST_F(ExceptionHandlerTest, InvalidParameterMiniDumpTest) {
+ ASSERT_TRUE(DoesPathExist(temp_path_));
+
+ // Call with a bad argument
+ ASSERT_TRUE(DoesPathExist(temp_path_));
+ wstring dump_path(temp_path_);
+ google_breakpad::CrashGenerationServer server(
+ kPipeName, NULL, NULL, NULL, ClientDumpCallback, NULL, NULL, NULL, NULL,
+ NULL, true, &dump_path);
+
+ ASSERT_TRUE(dump_file.empty() && full_dump_file.empty());
+
+ // This HAS to be EXPECT_, because when this test case is executed in the
+ // child process, the server registration will fail due to the named pipe
+ // being the same.
+ EXPECT_TRUE(server.Start());
+ EXPECT_EXIT(DoCrashInvalidParameter(), ::testing::ExitedWithCode(0), "");
+ ASSERT_TRUE(!dump_file.empty() && !full_dump_file.empty());
+ ASSERT_TRUE(DoesPathExist(dump_file.c_str()));
+ ASSERT_TRUE(DoesPathExist(full_dump_file.c_str()));
+
+ // Verify the dump for infos.
+ DumpAnalysis mini(dump_file);
+ DumpAnalysis full(full_dump_file);
+
+ // The dump should have all of these streams.
+ EXPECT_TRUE(mini.HasStream(ThreadListStream));
+ EXPECT_TRUE(full.HasStream(ThreadListStream));
+ EXPECT_TRUE(mini.HasStream(ModuleListStream));
+ EXPECT_TRUE(full.HasStream(ModuleListStream));
+ EXPECT_TRUE(mini.HasStream(ExceptionStream));
+ EXPECT_TRUE(full.HasStream(ExceptionStream));
+ EXPECT_TRUE(mini.HasStream(SystemInfoStream));
+ EXPECT_TRUE(full.HasStream(SystemInfoStream));
+ EXPECT_TRUE(mini.HasStream(MiscInfoStream));
+ EXPECT_TRUE(full.HasStream(MiscInfoStream));
+ EXPECT_TRUE(mini.HasStream(HandleDataStream));
+ EXPECT_TRUE(full.HasStream(HandleDataStream));
+
+ // We expect PEB and TEBs in this dump.
+ EXPECT_TRUE(mini.HasTebs() || full.HasTebs());
+ EXPECT_TRUE(mini.HasPeb() || full.HasPeb());
+
+ // Minidump should have a memory listing, but no 64-bit memory.
+ EXPECT_TRUE(mini.HasStream(MemoryListStream));
+ EXPECT_FALSE(mini.HasStream(Memory64ListStream));
+
+ EXPECT_FALSE(full.HasStream(MemoryListStream));
+ EXPECT_TRUE(full.HasStream(Memory64ListStream));
+
+ // This is the only place we don't use OR because we want both not
+ // to have the streams.
+ EXPECT_FALSE(mini.HasStream(ThreadExListStream));
+ EXPECT_FALSE(full.HasStream(ThreadExListStream));
+ EXPECT_FALSE(mini.HasStream(CommentStreamA));
+ EXPECT_FALSE(full.HasStream(CommentStreamA));
+ EXPECT_FALSE(mini.HasStream(CommentStreamW));
+ EXPECT_FALSE(full.HasStream(CommentStreamW));
+ EXPECT_FALSE(mini.HasStream(FunctionTableStream));
+ EXPECT_FALSE(full.HasStream(FunctionTableStream));
+ EXPECT_FALSE(mini.HasStream(MemoryInfoListStream));
+ EXPECT_FALSE(full.HasStream(MemoryInfoListStream));
+ EXPECT_FALSE(mini.HasStream(ThreadInfoListStream));
+ EXPECT_FALSE(full.HasStream(ThreadInfoListStream));
+ EXPECT_FALSE(mini.HasStream(HandleOperationListStream));
+ EXPECT_FALSE(full.HasStream(HandleOperationListStream));
+ EXPECT_FALSE(mini.HasStream(TokenStream));
+ EXPECT_FALSE(full.HasStream(TokenStream));
+}
+
+
+// This test validates that the minidump is written correctly.
+TEST_F(ExceptionHandlerTest, PureVirtualCallMiniDumpTest) {
+ ASSERT_TRUE(DoesPathExist(temp_path_));
+
+ // Call with a bad argument
+ ASSERT_TRUE(DoesPathExist(temp_path_));
+ wstring dump_path(temp_path_);
+ google_breakpad::CrashGenerationServer server(
+ kPipeName, NULL, NULL, NULL, ClientDumpCallback, NULL, NULL, NULL, NULL,
+ NULL, true, &dump_path);
+
+ ASSERT_TRUE(dump_file.empty() && full_dump_file.empty());
+
+ // This HAS to be EXPECT_, because when this test case is executed in the
+ // child process, the server registration will fail due to the named pipe
+ // being the same.
+ EXPECT_TRUE(server.Start());
+ EXPECT_EXIT(DoCrashPureVirtualCall(), ::testing::ExitedWithCode(0), "");
+ ASSERT_TRUE(!dump_file.empty() && !full_dump_file.empty());
+ ASSERT_TRUE(DoesPathExist(dump_file.c_str()));
+ ASSERT_TRUE(DoesPathExist(full_dump_file.c_str()));
+
+ // Verify the dump for infos.
+ DumpAnalysis mini(dump_file);
+ DumpAnalysis full(full_dump_file);
+
+ // The dump should have all of these streams.
+ EXPECT_TRUE(mini.HasStream(ThreadListStream));
+ EXPECT_TRUE(full.HasStream(ThreadListStream));
+ EXPECT_TRUE(mini.HasStream(ModuleListStream));
+ EXPECT_TRUE(full.HasStream(ModuleListStream));
+ EXPECT_TRUE(mini.HasStream(ExceptionStream));
+ EXPECT_TRUE(full.HasStream(ExceptionStream));
+ EXPECT_TRUE(mini.HasStream(SystemInfoStream));
+ EXPECT_TRUE(full.HasStream(SystemInfoStream));
+ EXPECT_TRUE(mini.HasStream(MiscInfoStream));
+ EXPECT_TRUE(full.HasStream(MiscInfoStream));
+ EXPECT_TRUE(mini.HasStream(HandleDataStream));
+ EXPECT_TRUE(full.HasStream(HandleDataStream));
+
+ // We expect PEB and TEBs in this dump.
+ EXPECT_TRUE(mini.HasTebs() || full.HasTebs());
+ EXPECT_TRUE(mini.HasPeb() || full.HasPeb());
+
+ // Minidump should have a memory listing, but no 64-bit memory.
+ EXPECT_TRUE(mini.HasStream(MemoryListStream));
+ EXPECT_FALSE(mini.HasStream(Memory64ListStream));
+
+ EXPECT_FALSE(full.HasStream(MemoryListStream));
+ EXPECT_TRUE(full.HasStream(Memory64ListStream));
+
+ // This is the only place we don't use OR because we want both not
+ // to have the streams.
+ EXPECT_FALSE(mini.HasStream(ThreadExListStream));
+ EXPECT_FALSE(full.HasStream(ThreadExListStream));
+ EXPECT_FALSE(mini.HasStream(CommentStreamA));
+ EXPECT_FALSE(full.HasStream(CommentStreamA));
+ EXPECT_FALSE(mini.HasStream(CommentStreamW));
+ EXPECT_FALSE(full.HasStream(CommentStreamW));
+ EXPECT_FALSE(mini.HasStream(FunctionTableStream));
+ EXPECT_FALSE(full.HasStream(FunctionTableStream));
+ EXPECT_FALSE(mini.HasStream(MemoryInfoListStream));
+ EXPECT_FALSE(full.HasStream(MemoryInfoListStream));
+ EXPECT_FALSE(mini.HasStream(ThreadInfoListStream));
+ EXPECT_FALSE(full.HasStream(ThreadInfoListStream));
+ EXPECT_FALSE(mini.HasStream(HandleOperationListStream));
+ EXPECT_FALSE(full.HasStream(HandleOperationListStream));
+ EXPECT_FALSE(mini.HasStream(TokenStream));
+ EXPECT_FALSE(full.HasStream(TokenStream));
+}
+
+// Test that writing a minidump produces a valid minidump containing
+// some expected structures.
+TEST_F(ExceptionHandlerTest, WriteMinidumpTest) {
+ ExceptionHandler handler(temp_path_,
+ NULL,
+ DumpCallback,
+ NULL,
+ ExceptionHandler::HANDLER_ALL);
+
+ // Disable GTest SEH handler
+ testing::DisableExceptionHandlerInScope disable_exception_handler;
+
+ ASSERT_TRUE(handler.WriteMinidump());
+ ASSERT_FALSE(dump_file.empty());
+
+ string minidump_filename;
+ ASSERT_TRUE(WindowsStringUtils::safe_wcstombs(dump_file,
+ &minidump_filename));
+
+ // Read the minidump and verify some info.
+ Minidump minidump(minidump_filename);
+ ASSERT_TRUE(minidump.Read());
+ // TODO(ted): more comprehensive tests...
+}
+
+// Test that an additional memory region can be included in the minidump.
+TEST_F(ExceptionHandlerTest, AdditionalMemory) {
+ SYSTEM_INFO si;
+ GetSystemInfo(&si);
+ const uint32_t kMemorySize = si.dwPageSize;
+
+ // Get some heap memory.
+ uint8_t* memory = new uint8_t[kMemorySize];
+ const uintptr_t kMemoryAddress = reinterpret_cast<uintptr_t>(memory);
+ ASSERT_TRUE(memory);
+
+ // Stick some data into the memory so the contents can be verified.
+ for (uint32_t i = 0; i < kMemorySize; ++i) {
+ memory[i] = i % 255;
+ }
+
+ ExceptionHandler handler(temp_path_,
+ NULL,
+ DumpCallback,
+ NULL,
+ ExceptionHandler::HANDLER_ALL);
+
+ // Disable GTest SEH handler
+ testing::DisableExceptionHandlerInScope disable_exception_handler;
+
+ // Add the memory region to the list of memory to be included.
+ handler.RegisterAppMemory(memory, kMemorySize);
+ ASSERT_TRUE(handler.WriteMinidump());
+ ASSERT_FALSE(dump_file.empty());
+
+ string minidump_filename;
+ ASSERT_TRUE(WindowsStringUtils::safe_wcstombs(dump_file,
+ &minidump_filename));
+
+ // Read the minidump. Ensure that the memory region is present
+ Minidump minidump(minidump_filename);
+ ASSERT_TRUE(minidump.Read());
+
+ MinidumpMemoryList* dump_memory_list = minidump.GetMemoryList();
+ ASSERT_TRUE(dump_memory_list);
+ const MinidumpMemoryRegion* region =
+ dump_memory_list->GetMemoryRegionForAddress(kMemoryAddress);
+ ASSERT_TRUE(region);
+
+ EXPECT_EQ(kMemoryAddress, region->GetBase());
+ EXPECT_EQ(kMemorySize, region->GetSize());
+
+ // Verify memory contents.
+ EXPECT_EQ(0, memcmp(region->GetMemory(), memory, kMemorySize));
+
+ delete[] memory;
+}
+
+// Test that a memory region that was previously registered
+// can be unregistered.
+TEST_F(ExceptionHandlerTest, AdditionalMemoryRemove) {
+ SYSTEM_INFO si;
+ GetSystemInfo(&si);
+ const uint32_t kMemorySize = si.dwPageSize;
+
+ // Get some heap memory.
+ uint8_t* memory = new uint8_t[kMemorySize];
+ const uintptr_t kMemoryAddress = reinterpret_cast<uintptr_t>(memory);
+ ASSERT_TRUE(memory);
+
+ // Stick some data into the memory so the contents can be verified.
+ for (uint32_t i = 0; i < kMemorySize; ++i) {
+ memory[i] = i % 255;
+ }
+
+ ExceptionHandler handler(temp_path_,
+ NULL,
+ DumpCallback,
+ NULL,
+ ExceptionHandler::HANDLER_ALL);
+
+ // Disable GTest SEH handler
+ testing::DisableExceptionHandlerInScope disable_exception_handler;
+
+ // Add the memory region to the list of memory to be included.
+ handler.RegisterAppMemory(memory, kMemorySize);
+
+ // ...and then remove it
+ handler.UnregisterAppMemory(memory);
+
+ ASSERT_TRUE(handler.WriteMinidump());
+ ASSERT_FALSE(dump_file.empty());
+
+ string minidump_filename;
+ ASSERT_TRUE(WindowsStringUtils::safe_wcstombs(dump_file,
+ &minidump_filename));
+
+ // Read the minidump. Ensure that the memory region is not present.
+ Minidump minidump(minidump_filename);
+ ASSERT_TRUE(minidump.Read());
+
+ MinidumpMemoryList* dump_memory_list = minidump.GetMemoryList();
+ ASSERT_TRUE(dump_memory_list);
+ const MinidumpMemoryRegion* region =
+ dump_memory_list->GetMemoryRegionForAddress(kMemoryAddress);
+ EXPECT_FALSE(region);
+
+ delete[] memory;
+}
+
+} // namespace
diff --git a/toolkit/crashreporter/breakpad-client/windows/unittests/exception_handler_test.h b/toolkit/crashreporter/breakpad-client/windows/unittests/exception_handler_test.h
new file mode 100644
index 0000000000..ef973e5392
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/windows/unittests/exception_handler_test.h
@@ -0,0 +1,61 @@
+// Copyright 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 CLIENT_WINDOWS_UNITTESTS_EXCEPTION_HANDLER_TEST_H_
+#define CLIENT_WINDOWS_UNITTESTS_EXCEPTION_HANDLER_TEST_H_
+
+namespace testing {
+
+// By default, GTest (on Windows) installs a SEH filter (and a handler) before
+// starting to run all the tests in order to avoid test interruptions is some
+// of the tests are crashing. Unfortunately, this functionality prevents the
+// execution to reach the UnhandledExceptionFilter installed by Google-Breakpad
+// ExceptionHandler so in order to test the Google-Breakpad exception handling
+// code the exception handling done by GTest must be disabled.
+// Usage:
+//
+// google_breakpad::ExceptionHandler exc(...);
+//
+// // Disable GTest SEH handler
+// testing::DisableExceptionHandlerInScope disable_exception_handler;
+// ...
+// ASSERT_DEATH( ... some crash ...);
+//
+class DisableExceptionHandlerInScope {
+ public:
+ DisableExceptionHandlerInScope();
+ ~DisableExceptionHandlerInScope();
+
+ private:
+ bool catch_exceptions_;
+};
+
+} // namespace testing
+
+#endif // CLIENT_WINDOWS_UNITTESTS_EXCEPTION_HANDLER_TEST_H_
diff --git a/toolkit/crashreporter/breakpad-client/windows/unittests/minidump_test.cc b/toolkit/crashreporter/breakpad-client/windows/unittests/minidump_test.cc
new file mode 100644
index 0000000000..82641125c1
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-client/windows/unittests/minidump_test.cc
@@ -0,0 +1,332 @@
+// 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 <windows.h>
+#include <objbase.h>
+#include <dbghelp.h>
+
+#include "breakpad_googletest_includes.h"
+#include "client/windows/crash_generation/minidump_generator.h"
+#include "client/windows/unittests/dump_analysis.h" // NOLINT
+
+namespace {
+
+// Minidump with stacks, PEB, TEB, and unloaded module list.
+const MINIDUMP_TYPE kSmallDumpType = static_cast<MINIDUMP_TYPE>(
+ MiniDumpWithProcessThreadData | // Get PEB and TEB.
+ MiniDumpWithUnloadedModules); // Get unloaded modules when available.
+
+// Minidump with all of the above, plus memory referenced from stack.
+const MINIDUMP_TYPE kLargerDumpType = static_cast<MINIDUMP_TYPE>(
+ MiniDumpWithProcessThreadData | // Get PEB and TEB.
+ MiniDumpWithUnloadedModules | // Get unloaded modules when available.
+ MiniDumpWithIndirectlyReferencedMemory); // Get memory referenced by stack.
+
+// Large dump with all process memory.
+const MINIDUMP_TYPE kFullDumpType = static_cast<MINIDUMP_TYPE>(
+ MiniDumpWithFullMemory | // Full memory from process.
+ MiniDumpWithProcessThreadData | // Get PEB and TEB.
+ MiniDumpWithHandleData | // Get all handle information.
+ MiniDumpWithUnloadedModules); // Get unloaded modules when available.
+
+class MinidumpTest: public testing::Test {
+ public:
+ MinidumpTest() {
+ wchar_t temp_dir_path[ MAX_PATH ] = {0};
+ ::GetTempPath(MAX_PATH, temp_dir_path);
+ dump_path_ = temp_dir_path;
+ }
+
+ virtual void SetUp() {
+ // Make sure URLMon isn't loaded into our process.
+ ASSERT_EQ(NULL, ::GetModuleHandle(L"urlmon.dll"));
+
+ // Then load and unload it to ensure we have something to
+ // stock the unloaded module list with.
+ HMODULE urlmon = ::LoadLibrary(L"urlmon.dll");
+ ASSERT_TRUE(urlmon != NULL);
+ ASSERT_TRUE(::FreeLibrary(urlmon));
+ }
+
+ virtual void TearDown() {
+ if (!dump_file_.empty()) {
+ ::DeleteFile(dump_file_.c_str());
+ dump_file_ = L"";
+ }
+ if (!full_dump_file_.empty()) {
+ ::DeleteFile(full_dump_file_.c_str());
+ full_dump_file_ = L"";
+ }
+ }
+
+ bool WriteDump(ULONG flags) {
+ using google_breakpad::MinidumpGenerator;
+
+ // Fake exception is access violation on write to this.
+ EXCEPTION_RECORD ex_record = {
+ STATUS_ACCESS_VIOLATION, // ExceptionCode
+ 0, // ExceptionFlags
+ NULL, // ExceptionRecord;
+ reinterpret_cast<void*>(static_cast<uintptr_t>(0xCAFEBABE)), // ExceptionAddress;
+ 2, // NumberParameters;
+ { EXCEPTION_WRITE_FAULT, reinterpret_cast<ULONG_PTR>(this) }
+ };
+ CONTEXT ctx_record = {};
+ EXCEPTION_POINTERS ex_ptrs = {
+ &ex_record,
+ &ctx_record,
+ };
+
+ MinidumpGenerator generator(dump_path_,
+ ::GetCurrentProcess(),
+ ::GetCurrentProcessId(),
+ ::GetCurrentThreadId(),
+ ::GetCurrentThreadId(),
+ &ex_ptrs,
+ NULL,
+ static_cast<MINIDUMP_TYPE>(flags),
+ TRUE);
+ generator.GenerateDumpFile(&dump_file_);
+ generator.GenerateFullDumpFile(&full_dump_file_);
+ // And write a dump
+ bool result = generator.WriteMinidump();
+ return result == TRUE;
+ }
+
+ protected:
+ std::wstring dump_file_;
+ std::wstring full_dump_file_;
+
+ std::wstring dump_path_;
+};
+
+// We need to be able to get file information from Windows
+bool HasFileInfo(const std::wstring& file_path) {
+ DWORD dummy;
+ const wchar_t* path = file_path.c_str();
+ DWORD length = ::GetFileVersionInfoSize(path, &dummy);
+ if (length == 0)
+ return NULL;
+
+ void* data = calloc(length, 1);
+ if (!data)
+ return false;
+
+ if (!::GetFileVersionInfo(path, dummy, length, data)) {
+ free(data);
+ return false;
+ }
+
+ void* translate = NULL;
+ UINT page_count;
+ BOOL query_result = VerQueryValue(
+ data,
+ L"\\VarFileInfo\\Translation",
+ static_cast<void**>(&translate),
+ &page_count);
+
+ free(data);
+ if (query_result && translate) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+TEST_F(MinidumpTest, Version) {
+ // Loads DbgHelp.dll in process
+ ImagehlpApiVersion();
+
+ HMODULE dbg_help = ::GetModuleHandle(L"dbghelp.dll");
+ ASSERT_TRUE(dbg_help != NULL);
+
+ wchar_t dbg_help_file[1024] = {};
+ ASSERT_TRUE(::GetModuleFileName(dbg_help,
+ dbg_help_file,
+ sizeof(dbg_help_file) /
+ sizeof(*dbg_help_file)));
+ ASSERT_TRUE(HasFileInfo(std::wstring(dbg_help_file)) != NULL);
+
+// LOG(INFO) << "DbgHelp.dll version: " << file_info->file_version();
+}
+
+TEST_F(MinidumpTest, Normal) {
+ EXPECT_TRUE(WriteDump(MiniDumpNormal));
+ DumpAnalysis mini(dump_file_);
+
+ // We expect threads, modules and some memory.
+ EXPECT_TRUE(mini.HasStream(ThreadListStream));
+ EXPECT_TRUE(mini.HasStream(ModuleListStream));
+ EXPECT_TRUE(mini.HasStream(MemoryListStream));
+ EXPECT_TRUE(mini.HasStream(ExceptionStream));
+ EXPECT_TRUE(mini.HasStream(SystemInfoStream));
+ EXPECT_TRUE(mini.HasStream(MiscInfoStream));
+
+ EXPECT_FALSE(mini.HasStream(ThreadExListStream));
+ EXPECT_FALSE(mini.HasStream(Memory64ListStream));
+ EXPECT_FALSE(mini.HasStream(CommentStreamA));
+ EXPECT_FALSE(mini.HasStream(CommentStreamW));
+ EXPECT_FALSE(mini.HasStream(HandleDataStream));
+ EXPECT_FALSE(mini.HasStream(FunctionTableStream));
+ EXPECT_FALSE(mini.HasStream(UnloadedModuleListStream));
+ EXPECT_FALSE(mini.HasStream(MemoryInfoListStream));
+ EXPECT_FALSE(mini.HasStream(ThreadInfoListStream));
+ EXPECT_FALSE(mini.HasStream(HandleOperationListStream));
+ EXPECT_FALSE(mini.HasStream(TokenStream));
+
+ // We expect no PEB nor TEBs in this dump.
+ EXPECT_FALSE(mini.HasTebs());
+ EXPECT_FALSE(mini.HasPeb());
+
+ // We expect no off-stack memory in this dump.
+ EXPECT_FALSE(mini.HasMemory(this));
+}
+
+TEST_F(MinidumpTest, SmallDump) {
+ ASSERT_TRUE(WriteDump(kSmallDumpType));
+ DumpAnalysis mini(dump_file_);
+
+ EXPECT_TRUE(mini.HasStream(ThreadListStream));
+ EXPECT_TRUE(mini.HasStream(ModuleListStream));
+ EXPECT_TRUE(mini.HasStream(MemoryListStream));
+ EXPECT_TRUE(mini.HasStream(ExceptionStream));
+ EXPECT_TRUE(mini.HasStream(SystemInfoStream));
+ EXPECT_TRUE(mini.HasStream(UnloadedModuleListStream));
+ EXPECT_TRUE(mini.HasStream(MiscInfoStream));
+
+ // We expect PEB and TEBs in this dump.
+ EXPECT_TRUE(mini.HasTebs());
+ EXPECT_TRUE(mini.HasPeb());
+
+ EXPECT_FALSE(mini.HasStream(ThreadExListStream));
+ EXPECT_FALSE(mini.HasStream(Memory64ListStream));
+ EXPECT_FALSE(mini.HasStream(CommentStreamA));
+ EXPECT_FALSE(mini.HasStream(CommentStreamW));
+ EXPECT_FALSE(mini.HasStream(HandleDataStream));
+ EXPECT_FALSE(mini.HasStream(FunctionTableStream));
+ EXPECT_FALSE(mini.HasStream(MemoryInfoListStream));
+ EXPECT_FALSE(mini.HasStream(ThreadInfoListStream));
+ EXPECT_FALSE(mini.HasStream(HandleOperationListStream));
+ EXPECT_FALSE(mini.HasStream(TokenStream));
+
+ // We expect no off-stack memory in this dump.
+ EXPECT_FALSE(mini.HasMemory(this));
+}
+
+TEST_F(MinidumpTest, LargerDump) {
+ ASSERT_TRUE(WriteDump(kLargerDumpType));
+ DumpAnalysis mini(dump_file_);
+
+ // The dump should have all of these streams.
+ EXPECT_TRUE(mini.HasStream(ThreadListStream));
+ EXPECT_TRUE(mini.HasStream(ModuleListStream));
+ EXPECT_TRUE(mini.HasStream(MemoryListStream));
+ EXPECT_TRUE(mini.HasStream(ExceptionStream));
+ EXPECT_TRUE(mini.HasStream(SystemInfoStream));
+ EXPECT_TRUE(mini.HasStream(UnloadedModuleListStream));
+ EXPECT_TRUE(mini.HasStream(MiscInfoStream));
+
+ // We expect memory referenced by stack in this dump.
+ EXPECT_TRUE(mini.HasMemory(this));
+
+ // We expect PEB and TEBs in this dump.
+ EXPECT_TRUE(mini.HasTebs());
+ EXPECT_TRUE(mini.HasPeb());
+
+ EXPECT_FALSE(mini.HasStream(ThreadExListStream));
+ EXPECT_FALSE(mini.HasStream(Memory64ListStream));
+ EXPECT_FALSE(mini.HasStream(CommentStreamA));
+ EXPECT_FALSE(mini.HasStream(CommentStreamW));
+ EXPECT_FALSE(mini.HasStream(HandleDataStream));
+ EXPECT_FALSE(mini.HasStream(FunctionTableStream));
+ EXPECT_FALSE(mini.HasStream(MemoryInfoListStream));
+ EXPECT_FALSE(mini.HasStream(ThreadInfoListStream));
+ EXPECT_FALSE(mini.HasStream(HandleOperationListStream));
+ EXPECT_FALSE(mini.HasStream(TokenStream));
+}
+
+TEST_F(MinidumpTest, FullDump) {
+ ASSERT_TRUE(WriteDump(kFullDumpType));
+ ASSERT_TRUE(dump_file_ != L"");
+ ASSERT_TRUE(full_dump_file_ != L"");
+ DumpAnalysis mini(dump_file_);
+ DumpAnalysis full(full_dump_file_);
+
+ // Either dumps can contain part of the information.
+
+ // The dump should have all of these streams.
+ EXPECT_TRUE(mini.HasStream(ThreadListStream));
+ EXPECT_TRUE(full.HasStream(ThreadListStream));
+ EXPECT_TRUE(mini.HasStream(ModuleListStream));
+ EXPECT_TRUE(full.HasStream(ModuleListStream));
+ EXPECT_TRUE(mini.HasStream(ExceptionStream));
+ EXPECT_TRUE(full.HasStream(ExceptionStream));
+ EXPECT_TRUE(mini.HasStream(SystemInfoStream));
+ EXPECT_TRUE(full.HasStream(SystemInfoStream));
+ EXPECT_TRUE(mini.HasStream(UnloadedModuleListStream));
+ EXPECT_TRUE(full.HasStream(UnloadedModuleListStream));
+ EXPECT_TRUE(mini.HasStream(MiscInfoStream));
+ EXPECT_TRUE(full.HasStream(MiscInfoStream));
+ EXPECT_TRUE(mini.HasStream(HandleDataStream));
+ EXPECT_TRUE(full.HasStream(HandleDataStream));
+
+ // We expect memory referenced by stack in this dump.
+ EXPECT_FALSE(mini.HasMemory(this));
+ EXPECT_TRUE(full.HasMemory(this));
+
+ // We expect PEB and TEBs in this dump.
+ EXPECT_TRUE(mini.HasTebs() || full.HasTebs());
+ EXPECT_TRUE(mini.HasPeb() || full.HasPeb());
+
+ EXPECT_TRUE(mini.HasStream(MemoryListStream));
+ EXPECT_TRUE(full.HasStream(Memory64ListStream));
+ EXPECT_FALSE(mini.HasStream(Memory64ListStream));
+ EXPECT_FALSE(full.HasStream(MemoryListStream));
+
+ // This is the only place we don't use OR because we want both not
+ // to have the streams.
+ EXPECT_FALSE(mini.HasStream(ThreadExListStream));
+ EXPECT_FALSE(full.HasStream(ThreadExListStream));
+ EXPECT_FALSE(mini.HasStream(CommentStreamA));
+ EXPECT_FALSE(full.HasStream(CommentStreamA));
+ EXPECT_FALSE(mini.HasStream(CommentStreamW));
+ EXPECT_FALSE(full.HasStream(CommentStreamW));
+ EXPECT_FALSE(mini.HasStream(FunctionTableStream));
+ EXPECT_FALSE(full.HasStream(FunctionTableStream));
+ EXPECT_FALSE(mini.HasStream(MemoryInfoListStream));
+ EXPECT_FALSE(full.HasStream(MemoryInfoListStream));
+ EXPECT_FALSE(mini.HasStream(ThreadInfoListStream));
+ EXPECT_FALSE(full.HasStream(ThreadInfoListStream));
+ EXPECT_FALSE(mini.HasStream(HandleOperationListStream));
+ EXPECT_FALSE(full.HasStream(HandleOperationListStream));
+ EXPECT_FALSE(mini.HasStream(TokenStream));
+ EXPECT_FALSE(full.HasStream(TokenStream));
+}
+
+} // namespace
diff --git a/toolkit/crashreporter/breakpad-patches/00-arm-exidx-rollup.patch b/toolkit/crashreporter/breakpad-patches/00-arm-exidx-rollup.patch
new file mode 100644
index 0000000000..33ae81f3df
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-patches/00-arm-exidx-rollup.patch
@@ -0,0 +1,1352 @@
+diff --git a/Makefile.am b/Makefile.am
+index 9a25d9d4..07206601 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -571,6 +571,8 @@ src_tools_linux_core2md_core2md_LDADD = \
+ src/client/linux/libbreakpad_client.a
+
+ src_tools_linux_dump_syms_dump_syms_SOURCES = \
++ src/common/arm_ex_reader.cc \
++ src/common/arm_ex_to_module.cc \
+ src/common/dwarf_cfi_to_module.cc \
+ src/common/dwarf_cu_to_module.cc \
+ src/common/dwarf_line_to_module.cc \
+@@ -660,6 +662,8 @@ src_tools_mac_dump_syms_dump_syms_mac_LDADD= \
+ $(RUST_DEMANGLE_LIBS)
+
+ src_common_dumper_unittest_SOURCES = \
++ src/common/arm_ex_reader.cc \
++ src/common/arm_ex_to_module.cc \
+ src/common/byte_cursor_unittest.cc \
+ src/common/convert_UTF.cc \
+ src/common/dwarf_cfi_to_module.cc \
+@@ -1348,6 +1352,10 @@ EXTRA_DIST = \
+ src/client/windows/sender/crash_report_sender.cc \
+ src/client/windows/sender/crash_report_sender.h \
+ src/client/windows/sender/crash_report_sender.gyp \
++ src/common/arm_ex_reader.cc \
++ src/common/arm_ex_reader.h \
++ src/common/arm_ex_to_module.cc \
++ src/common/arm_ex_to_module.h \
+ src/common/dwarf/dwarf2diehandler.h \
+ src/common/dwarf/dwarf2enums.h \
+ src/common/dwarf/line_state_machine.h \
+diff --git a/src/common/arm_ex_reader.cc b/src/common/arm_ex_reader.cc
+new file mode 100644
+index 00000000..2d1ed983
+--- /dev/null
++++ b/src/common/arm_ex_reader.cc
+@@ -0,0 +1,487 @@
++
++/* 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/src/common/arm_ex_reader.h b/src/common/arm_ex_reader.h
+new file mode 100644
+index 00000000..9b54e8a0
+--- /dev/null
++++ b/src/common/arm_ex_reader.h
+@@ -0,0 +1,114 @@
++/* 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/src/common/arm_ex_to_module.cc b/src/common/arm_ex_to_module.cc
+new file mode 100644
+index 00000000..c326744f
+--- /dev/null
++++ b/src/common/arm_ex_to_module.cc
+@@ -0,0 +1,209 @@
++
++/* 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/src/common/arm_ex_to_module.h b/src/common/arm_ex_to_module.h
+new file mode 100644
+index 00000000..f413a16a
+--- /dev/null
++++ b/src/common/arm_ex_to_module.h
+@@ -0,0 +1,119 @@
++/* 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/src/common/linux/dump_symbols.cc b/src/common/linux/dump_symbols.cc
+index 0eea2b54..e398f7b3 100644
+--- a/src/common/linux/dump_symbols.cc
++++ b/src/common/linux/dump_symbols.cc
+@@ -54,6 +54,7 @@
+ #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"
+@@ -76,6 +77,11 @@
+ #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 {
+
+@@ -429,6 +435,52 @@ bool LoadDwarfCFI(const string& dwarf_filename,
+ 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);
+@@ -846,6 +898,29 @@ bool LoadSymbols(const string& obj_file,
+ }
+ }
+
++ // 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",
+diff --git a/src/common/module.cc b/src/common/module.cc
+index aff22127..a3544029 100644
+--- a/src/common/module.cc
++++ b/src/common/module.cc
+@@ -64,7 +64,7 @@ Module::~Module() {
+ it != functions_.end(); ++it) {
+ delete *it;
+ }
+- for (vector<StackFrameEntry *>::iterator it = stack_frame_entries_.begin();
++ for (StackFrameEntrySet::iterator it = stack_frame_entries_.begin();
+ it != stack_frame_entries_.end(); ++it) {
+ delete *it;
+ }
+@@ -130,12 +130,18 @@ void Module::AddFunctions(vector<Function *>::iterator begin,
+ AddFunction(*it);
+ }
+
+-void Module::AddStackFrameEntry(StackFrameEntry *stack_frame_entry) {
++void Module::AddStackFrameEntry(StackFrameEntry* stack_frame_entry) {
+ if (!AddressIsInModule(stack_frame_entry->address)) {
+ return;
+ }
+
+- stack_frame_entries_.push_back(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) {
+@@ -199,8 +205,25 @@ void Module::GetFiles(vector<File *> *vec) {
+ vec->push_back(it->second);
+ }
+
+-void Module::GetStackFrameEntries(vector<StackFrameEntry *> *vec) const {
+- *vec = stack_frame_entries_;
++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() {
+@@ -331,7 +354,7 @@ bool Module::Write(std::ostream &stream, SymbolData symbol_data) {
+
+ if (symbol_data != NO_CFI) {
+ // Write out 'STACK CFI INIT' and 'STACK CFI' records.
+- vector<StackFrameEntry *>::const_iterator frame_it;
++ StackFrameEntrySet::const_iterator frame_it;
+ for (frame_it = stack_frame_entries_.begin();
+ frame_it != stack_frame_entries_.end(); ++frame_it) {
+ StackFrameEntry *entry = *frame_it;
+diff --git a/src/common/module.h b/src/common/module.h
+index 7309cedd..37758605 100644
+--- a/src/common/module.h
++++ b/src/common/module.h
+@@ -185,6 +185,13 @@ class Module {
+ }
+ };
+
++ 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,
+@@ -273,6 +280,10 @@ class Module {
+ // 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
+@@ -342,6 +353,9 @@ class Module {
+ // 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.
+@@ -350,7 +364,7 @@ class Module {
+
+ // The module owns all the call frame info entries that have been
+ // added to it.
+- vector<StackFrameEntry *> stack_frame_entries_;
++ 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.
+diff --git a/src/common/module_unittest.cc b/src/common/module_unittest.cc
+index 37fee5dd..b855f186 100644
+--- a/src/common/module_unittest.cc
++++ b/src/common/module_unittest.cc
+@@ -344,11 +344,6 @@ TEST(Construct, AddFrames) {
+ 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 ddb5f41285aa7757 1486493370dc5073 \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 5e8d0db0a7075c6c 1c7edb12a7aea229"
+ " .cfa: Whose woods are these\n"
+ "STACK CFI 36682fad3763ffff"
+@@ -356,7 +351,12 @@ TEST(Construct, AddFrames) {
+ " stromboli: his house is in\n"
+ "STACK CFI 47ceb0f63c269d7f"
+ " calzone: the village though"
+- " cannoli: he will not see me stopping here\n",
++ " 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.
+@@ -364,10 +364,18 @@ TEST(Construct, AddFrames) {
+ m.GetStackFrameEntries(&entries);
+ ASSERT_EQ(3U, entries.size());
+ // Check first entry.
+- EXPECT_EQ(0xddb5f41285aa7757ULL, entries[0]->address);
+- EXPECT_EQ(0x1486493370dc5073ULL, entries[0]->size);
+- ASSERT_EQ(0U, entries[0]->initial_rules.size());
+- ASSERT_EQ(0U, entries[0]->rule_changes.size());
++ 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);
+@@ -379,18 +387,10 @@ TEST(Construct, AddFrames) {
+ EXPECT_THAT(entries[1]->initial_rules, ContainerEq(entry2_initial));
+ ASSERT_EQ(0U, entries[1]->rule_changes.size());
+ // Check third entry.
+- EXPECT_EQ(0x5e8d0db0a7075c6cULL, entries[2]->address);
+- EXPECT_EQ(0x1c7edb12a7aea229ULL, entries[2]->size);
+- Module::RuleMap entry3_initial;
+- entry3_initial[".cfa"] = "Whose woods are these";
+- EXPECT_THAT(entries[2]->initial_rules, ContainerEq(entry3_initial));
+- Module::RuleChangeMap entry3_changes;
+- entry3_changes[0x36682fad3763ffffULL][".cfa"] = "I think I know";
+- entry3_changes[0x36682fad3763ffffULL]["stromboli"] = "his house is in";
+- entry3_changes[0x47ceb0f63c269d7fULL]["calzone"] = "the village though";
+- entry3_changes[0x47ceb0f63c269d7fULL]["cannoli"] =
+- "he will not see me stopping here";
+- EXPECT_THAT(entries[2]->rule_changes, ContainerEq(entry3_changes));
++ 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) {
+@@ -612,5 +612,63 @@ TEST(Write, OutOfRangeAddresses) {
+ EXPECT_STREQ("MODULE os-name architecture id-string name with spaces\n"
+ "STACK CFI INIT 2000 100 \n",
+ s.str().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/breakpad-patches/02-define-print-mach-result.patch b/toolkit/crashreporter/breakpad-patches/02-define-print-mach-result.patch
new file mode 100644
index 0000000000..933659120d
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-patches/02-define-print-mach-result.patch
@@ -0,0 +1,24 @@
+diff --git a/src/common/mac/MachIPC.h b/src/common/mac/MachIPC.h
+--- a/src/common/mac/MachIPC.h
++++ b/src/common/mac/MachIPC.h
+@@ -90,18 +90,20 @@
+ //
+ // char messageString[] = "Hello server!\n";
+ // message.SetData(messageString, strlen(messageString)+1);
+ //
+ // kern_return_t result = sender.SendMessage(message, 1000); // timeout 1000ms
+ //
+
+ namespace google_breakpad {
++#ifndef PRINT_MACH_RESULT
+ #define PRINT_MACH_RESULT(result_, message_) \
+ printf(message_" %s (%d)\n", mach_error_string(result_), result_ );
++#endif
+
+ //==============================================================================
+ // 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,
diff --git a/toolkit/crashreporter/breakpad-patches/03-strstr-libc-replacement.patch b/toolkit/crashreporter/breakpad-patches/03-strstr-libc-replacement.patch
new file mode 100644
index 0000000000..17006a91d9
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-patches/03-strstr-libc-replacement.patch
@@ -0,0 +1,54 @@
+diff --git a/src/common/linux/linux_libc_support.cc b/src/common/linux/linux_libc_support.cc
+--- a/src/common/linux/linux_libc_support.cc
++++ b/src/common/linux/linux_libc_support.cc
+@@ -133,16 +133,27 @@ const char* my_strrchr(const char* hayst
+ while (*haystack) {
+ if (*haystack == needle)
+ ret = haystack;
+ haystack++;
+ }
+ return ret;
+ }
+
++const char* my_strstr(const char* haystack, const char* needle) {
++ while (*haystack != 0) {
++ if((*haystack == *needle) &&
++ (my_strncmp(haystack, needle, my_strlen(needle)) == 0)) {
++ return haystack;
++ }
++ haystack++;
++ }
++ return nullptr;
++}
++
+ 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;
+diff --git a/src/common/linux/linux_libc_support.h b/src/common/linux/linux_libc_support.h
+--- a/src/common/linux/linux_libc_support.h
++++ b/src/common/linux/linux_libc_support.h
+@@ -62,16 +62,18 @@ extern unsigned my_uint_len(uintmax_t i)
+ // 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);
+
++extern const char *my_strstr(const char *haystack, const 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);
+
+
diff --git a/toolkit/crashreporter/breakpad-patches/04-update-headers.patch b/toolkit/crashreporter/breakpad-patches/04-update-headers.patch
new file mode 100644
index 0000000000..4baa27be90
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-patches/04-update-headers.patch
@@ -0,0 +1,6039 @@
+diff --git a/src/third_party/curl/COPYING b/src/third_party/curl/COPYING
+--- a/src/third_party/curl/COPYING
++++ b/src/third_party/curl/COPYING
+@@ -1,11 +1,12 @@
+ COPYRIGHT AND PERMISSION NOTICE
+
+-Copyright (c) 1996 - 2011, Daniel Stenberg, <daniel@haxx.se>.
++Copyright (c) 1996 - 2019, Daniel Stenberg, <daniel@haxx.se>, and many
++contributors, see the THANKS file.
+
+ All rights reserved.
+
+ Permission to use, copy, modify, and distribute this software for any purpose
+ with or without fee is hereby granted, provided that the above copyright
+ notice and this permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+@@ -14,9 +15,8 @@ FITNESS FOR A PARTICULAR PURPOSE AND NON
+ 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.
+
+ 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 this Software without prior written authorization of the copyright holder.
+-
+diff --git a/src/third_party/curl/curl.h b/src/third_party/curl/curl.h
+--- a/src/third_party/curl/curl.h
++++ b/src/third_party/curl/curl.h
+@@ -2,234 +2,402 @@
+ #define __CURL_CURL_H
+ /***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+- * Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
++ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+- * are also available at http://curl.haxx.se/docs/copyright.html.
++ * are also available at https://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+- * $Id: curl.h,v 1.396 2009-10-16 13:30:31 yangtse Exp $
+ ***************************************************************************/
+
+ /*
+ * If you have libcurl problems, all docs and details are found here:
+- * http://curl.haxx.se/libcurl/
++ * https://curl.haxx.se/libcurl/
+ *
+ * curl-library mailing list subscription and unsubscription web interface:
+- * http://cool.haxx.se/mailman/listinfo/curl-library/
++ * https://cool.haxx.se/mailman/listinfo/curl-library/
+ */
+
+-/*
+- * Leading 'curl' path on the 'curlbuild.h' include statement is
+- * required to properly allow building outside of the source tree,
+- * due to the fact that in this case 'curlbuild.h' is generated in
+- * a subdirectory of the build tree while 'curl.h actually remains
+- * in a subdirectory of the source tree.
+- */
+-
+-#include "third_party/curl/curlver.h" /* libcurl version defines */
+-#include "third_party/curl/curlbuild.h" /* libcurl build definitions */
+-#include "third_party/curl/curlrules.h" /* libcurl rules enforcement */
++#ifdef CURL_NO_OLDIES
++#define CURL_STRICTER
++#endif
++
++#include "curlver.h" /* libcurl version defines */
++#include "system.h" /* determine things run-time */
+
+ /*
+ * Define WIN32 when build target is Win32 API
+ */
+
+ #if (defined(_WIN32) || defined(__WIN32__)) && \
+ !defined(WIN32) && !defined(__SYMBIAN32__)
+ #define WIN32
+ #endif
+
+ #include <stdio.h>
+ #include <limits.h>
+
++#if defined(__FreeBSD__) && (__FreeBSD__ >= 2)
++/* Needed for __FreeBSD_version symbol definition */
++#include <osreldate.h>
++#endif
++
+ /* The include stuff here below is mainly for time_t! */
+ #include <sys/types.h>
+ #include <time.h>
+
+-#if defined(WIN32) && !defined(_WIN32_WCE) && !defined(__GNUC__) && \
+- !defined(__CYGWIN__) || defined(__MINGW32__)
+-#if !(defined(_WINSOCKAPI_) || defined(_WINSOCK_H))
++#if defined(WIN32) && !defined(_WIN32_WCE) && !defined(__CYGWIN__)
++#if !(defined(_WINSOCKAPI_) || defined(_WINSOCK_H) || \
++ defined(__LWIP_OPT_H__) || defined(LWIP_HDR_OPT_H))
+ /* The check above prevents the winsock2 inclusion if winsock.h already was
+ included, since they can't co-exist without problems */
+ #include <winsock2.h>
+ #include <ws2tcpip.h>
+ #endif
+-#else
++#endif
+
+ /* HP-UX systems version 9, 10 and 11 lack sys/select.h and so does oldish
+- libc5-based Linux systems. Only include it on system that are known to
++ libc5-based Linux systems. Only include it on systems that are known to
+ require it! */
+ #if defined(_AIX) || defined(__NOVELL_LIBC__) || defined(__NetBSD__) || \
+ defined(__minix) || defined(__SYMBIAN32__) || defined(__INTEGRITY) || \
+- defined(__ANDROID__)
++ defined(ANDROID) || defined(__ANDROID__) || defined(__OpenBSD__) || \
++ defined(__CYGWIN__) || \
++ (defined(__FreeBSD_version) && (__FreeBSD_version < 800000))
+ #include <sys/select.h>
+ #endif
+
+-#ifndef _WIN32_WCE
++#if !defined(WIN32) && !defined(_WIN32_WCE)
+ #include <sys/socket.h>
+ #endif
++
+ #if !defined(WIN32) && !defined(__WATCOMC__) && !defined(__VXWORKS__)
+ #include <sys/time.h>
+ #endif
+-#include <sys/types.h>
+-#endif
+
+ #ifdef __BEOS__
+ #include <support/SupportDefs.h>
+ #endif
+
++/* Compatibility for non-Clang compilers */
++#ifndef __has_declspec_attribute
++# define __has_declspec_attribute(x) 0
++#endif
++
+ #ifdef __cplusplus
+ extern "C" {
+ #endif
+
++#if defined(BUILDING_LIBCURL) || defined(CURL_STRICTER)
++typedef struct Curl_easy CURL;
++typedef struct Curl_share CURLSH;
++#else
+ typedef void CURL;
++typedef void CURLSH;
++#endif
+
+ /*
+- * Decorate exportable functions for Win32 and Symbian OS DLL linking.
+- * This avoids using a .def file for building libcurl.dll.
++ * libcurl external API function linkage decorations.
+ */
+-#if (defined(WIN32) || defined(_WIN32) || defined(__SYMBIAN32__)) && \
+- !defined(CURL_STATICLIB)
+-#if defined(BUILDING_LIBCURL)
+-#define CURL_EXTERN __declspec(dllexport)
+-#else
+-#define CURL_EXTERN __declspec(dllimport)
+-#endif
++
++#ifdef CURL_STATICLIB
++# define CURL_EXTERN
++#elif defined(WIN32) || defined(_WIN32) || defined(__SYMBIAN32__) || \
++ (__has_declspec_attribute(dllexport) && \
++ __has_declspec_attribute(dllimport))
++# if defined(BUILDING_LIBCURL)
++# define CURL_EXTERN __declspec(dllexport)
++# else
++# define CURL_EXTERN __declspec(dllimport)
++# endif
++#elif defined(BUILDING_LIBCURL) && defined(CURL_HIDDEN_SYMBOLS)
++# define CURL_EXTERN CURL_EXTERN_SYMBOL
+ #else
+-
+-#ifdef CURL_HIDDEN_SYMBOLS
+-/*
+- * This definition is used to make external definitions visible in the
+- * shared library when symbols are hidden by default. It makes no
+- * difference when compiling applications whether this is set or not,
+- * only when compiling the library.
+- */
+-#define CURL_EXTERN CURL_EXTERN_SYMBOL
+-#else
+-#define CURL_EXTERN
+-#endif
++# define CURL_EXTERN
+ #endif
+
+ #ifndef curl_socket_typedef
+ /* socket typedef */
+-#ifdef WIN32
++#if defined(WIN32) && !defined(__LWIP_OPT_H__) && !defined(LWIP_HDR_OPT_H)
+ typedef SOCKET curl_socket_t;
+ #define CURL_SOCKET_BAD INVALID_SOCKET
+ #else
+ typedef int curl_socket_t;
+ #define CURL_SOCKET_BAD -1
+ #endif
+ #define curl_socket_typedef
+ #endif /* curl_socket_typedef */
+
++/* enum for the different supported SSL backends */
++typedef enum {
++ CURLSSLBACKEND_NONE = 0,
++ CURLSSLBACKEND_OPENSSL = 1,
++ CURLSSLBACKEND_GNUTLS = 2,
++ CURLSSLBACKEND_NSS = 3,
++ CURLSSLBACKEND_OBSOLETE4 = 4, /* Was QSOSSL. */
++ CURLSSLBACKEND_GSKIT = 5,
++ CURLSSLBACKEND_POLARSSL = 6,
++ CURLSSLBACKEND_WOLFSSL = 7,
++ CURLSSLBACKEND_SCHANNEL = 8,
++ CURLSSLBACKEND_SECURETRANSPORT = 9,
++ CURLSSLBACKEND_AXTLS = 10, /* never used since 7.63.0 */
++ CURLSSLBACKEND_MBEDTLS = 11,
++ CURLSSLBACKEND_MESALINK = 12
++} curl_sslbackend;
++
++/* aliases for library clones and renames */
++#define CURLSSLBACKEND_LIBRESSL CURLSSLBACKEND_OPENSSL
++#define CURLSSLBACKEND_BORINGSSL CURLSSLBACKEND_OPENSSL
++
++/* deprecated names: */
++#define CURLSSLBACKEND_CYASSL CURLSSLBACKEND_WOLFSSL
++#define CURLSSLBACKEND_DARWINSSL CURLSSLBACKEND_SECURETRANSPORT
++
+ struct curl_httppost {
+ struct curl_httppost *next; /* next entry in the list */
+ char *name; /* pointer to allocated name */
+ long namelength; /* length of name length */
+ char *contents; /* pointer to allocated data contents */
+- long contentslength; /* length of contents field */
++ long contentslength; /* length of contents field, see also
++ CURL_HTTPPOST_LARGE */
+ char *buffer; /* pointer to allocated buffer contents */
+ long bufferlength; /* length of buffer field */
+ char *contenttype; /* Content-Type */
+- struct curl_slist* contentheader; /* list of extra headers for this form */
++ struct curl_slist *contentheader; /* list of extra headers for this form */
+ struct curl_httppost *more; /* if one field name has more than one
+ file, this link should link to following
+ files */
+ long flags; /* as defined below */
+-#define HTTPPOST_FILENAME (1<<0) /* specified content is a file name */
+-#define HTTPPOST_READFILE (1<<1) /* specified content is a file name */
+-#define HTTPPOST_PTRNAME (1<<2) /* name is only stored pointer
+- do not free in formfree */
+-#define HTTPPOST_PTRCONTENTS (1<<3) /* contents is only stored pointer
+- do not free in formfree */
+-#define HTTPPOST_BUFFER (1<<4) /* upload file from buffer */
+-#define HTTPPOST_PTRBUFFER (1<<5) /* upload file from pointer contents */
+-#define HTTPPOST_CALLBACK (1<<6) /* upload file contents by using the
+- regular read callback to get the data
+- and pass the given pointer as custom
+- pointer */
++
++/* specified content is a file name */
++#define CURL_HTTPPOST_FILENAME (1<<0)
++/* specified content is a file name */
++#define CURL_HTTPPOST_READFILE (1<<1)
++/* name is only stored pointer do not free in formfree */
++#define CURL_HTTPPOST_PTRNAME (1<<2)
++/* contents is only stored pointer do not free in formfree */
++#define CURL_HTTPPOST_PTRCONTENTS (1<<3)
++/* upload file from buffer */
++#define CURL_HTTPPOST_BUFFER (1<<4)
++/* upload file from pointer contents */
++#define CURL_HTTPPOST_PTRBUFFER (1<<5)
++/* upload file contents by using the regular read callback to get the data and
++ pass the given pointer as custom pointer */
++#define CURL_HTTPPOST_CALLBACK (1<<6)
++/* use size in 'contentlen', added in 7.46.0 */
++#define CURL_HTTPPOST_LARGE (1<<7)
+
+ char *showfilename; /* The file name to show. If not set, the
+ actual file name will be used (if this
+ is a file part) */
+ void *userp; /* custom pointer used for
+ HTTPPOST_CALLBACK posts */
++ curl_off_t contentlen; /* alternative length of contents
++ field. Used if CURL_HTTPPOST_LARGE is
++ set. Added in 7.46.0 */
+ };
+
++/* This is the CURLOPT_PROGRESSFUNCTION callback proto. It is now considered
++ deprecated but was the only choice up until 7.31.0 */
+ typedef int (*curl_progress_callback)(void *clientp,
+ double dltotal,
+ double dlnow,
+ double ultotal,
+ double ulnow);
+
++/* This is the CURLOPT_XFERINFOFUNCTION callback proto. It was introduced in
++ 7.32.0, it avoids floating point and provides more detailed information. */
++typedef int (*curl_xferinfo_callback)(void *clientp,
++ curl_off_t dltotal,
++ curl_off_t dlnow,
++ curl_off_t ultotal,
++ curl_off_t ulnow);
++
++#ifndef CURL_MAX_READ_SIZE
++ /* The maximum receive buffer size configurable via CURLOPT_BUFFERSIZE. */
++#define CURL_MAX_READ_SIZE 524288
++#endif
++
+ #ifndef CURL_MAX_WRITE_SIZE
+ /* Tests have proven that 20K is a very bad buffer size for uploads on
+ Windows, while 16K for some odd reason performed a lot better.
+ We do the ifndef check to allow this value to easier be changed at build
+- time for those who feel adventurous. */
++ time for those who feel adventurous. The practical minimum is about
++ 400 bytes since libcurl uses a buffer of this size as a scratch area
++ (unrelated to network send operations). */
+ #define CURL_MAX_WRITE_SIZE 16384
+ #endif
+
+ #ifndef CURL_MAX_HTTP_HEADER
+ /* The only reason to have a max limit for this is to avoid the risk of a bad
+ server feeding libcurl with a never-ending header that will cause reallocs
+ infinitely */
+ #define CURL_MAX_HTTP_HEADER (100*1024)
+ #endif
+
+-
+ /* This is a magic return code for the write callback that, when returned,
+ will signal libcurl to pause receiving on the current transfer. */
+ #define CURL_WRITEFUNC_PAUSE 0x10000001
++
+ typedef size_t (*curl_write_callback)(char *buffer,
+ size_t size,
+ size_t nitems,
+ void *outstream);
+
++/* This callback will be called when a new resolver request is made */
++typedef int (*curl_resolver_start_callback)(void *resolver_state,
++ void *reserved, void *userdata);
++
++/* enumeration of file types */
++typedef enum {
++ CURLFILETYPE_FILE = 0,
++ CURLFILETYPE_DIRECTORY,
++ CURLFILETYPE_SYMLINK,
++ CURLFILETYPE_DEVICE_BLOCK,
++ CURLFILETYPE_DEVICE_CHAR,
++ CURLFILETYPE_NAMEDPIPE,
++ CURLFILETYPE_SOCKET,
++ CURLFILETYPE_DOOR, /* is possible only on Sun Solaris now */
++
++ CURLFILETYPE_UNKNOWN /* should never occur */
++} curlfiletype;
++
++#define CURLFINFOFLAG_KNOWN_FILENAME (1<<0)
++#define CURLFINFOFLAG_KNOWN_FILETYPE (1<<1)
++#define CURLFINFOFLAG_KNOWN_TIME (1<<2)
++#define CURLFINFOFLAG_KNOWN_PERM (1<<3)
++#define CURLFINFOFLAG_KNOWN_UID (1<<4)
++#define CURLFINFOFLAG_KNOWN_GID (1<<5)
++#define CURLFINFOFLAG_KNOWN_SIZE (1<<6)
++#define CURLFINFOFLAG_KNOWN_HLINKCOUNT (1<<7)
++
++/* Content of this structure depends on information which is known and is
++ achievable (e.g. by FTP LIST parsing). Please see the url_easy_setopt(3) man
++ page for callbacks returning this structure -- some fields are mandatory,
++ some others are optional. The FLAG field has special meaning. */
++struct curl_fileinfo {
++ char *filename;
++ curlfiletype filetype;
++ time_t time;
++ unsigned int perm;
++ int uid;
++ int gid;
++ curl_off_t size;
++ long int hardlinks;
++
++ struct {
++ /* If some of these fields is not NULL, it is a pointer to b_data. */
++ char *time;
++ char *perm;
++ char *user;
++ char *group;
++ char *target; /* pointer to the target filename of a symlink */
++ } strings;
++
++ unsigned int flags;
++
++ /* used internally */
++ char *b_data;
++ size_t b_size;
++ size_t b_used;
++};
++
++/* return codes for CURLOPT_CHUNK_BGN_FUNCTION */
++#define CURL_CHUNK_BGN_FUNC_OK 0
++#define CURL_CHUNK_BGN_FUNC_FAIL 1 /* tell the lib to end the task */
++#define CURL_CHUNK_BGN_FUNC_SKIP 2 /* skip this chunk over */
++
++/* if splitting of data transfer is enabled, this callback is called before
++ download of an individual chunk started. Note that parameter "remains" works
++ only for FTP wildcard downloading (for now), otherwise is not used */
++typedef long (*curl_chunk_bgn_callback)(const void *transfer_info,
++ void *ptr,
++ int remains);
++
++/* return codes for CURLOPT_CHUNK_END_FUNCTION */
++#define CURL_CHUNK_END_FUNC_OK 0
++#define CURL_CHUNK_END_FUNC_FAIL 1 /* tell the lib to end the task */
++
++/* If splitting of data transfer is enabled this callback is called after
++ download of an individual chunk finished.
++ Note! After this callback was set then it have to be called FOR ALL chunks.
++ Even if downloading of this chunk was skipped in CHUNK_BGN_FUNC.
++ This is the reason why we don't need "transfer_info" parameter in this
++ callback and we are not interested in "remains" parameter too. */
++typedef long (*curl_chunk_end_callback)(void *ptr);
++
++/* return codes for FNMATCHFUNCTION */
++#define CURL_FNMATCHFUNC_MATCH 0 /* string corresponds to the pattern */
++#define CURL_FNMATCHFUNC_NOMATCH 1 /* pattern doesn't match the string */
++#define CURL_FNMATCHFUNC_FAIL 2 /* an error occurred */
++
++/* callback type for wildcard downloading pattern matching. If the
++ string matches the pattern, return CURL_FNMATCHFUNC_MATCH value, etc. */
++typedef int (*curl_fnmatch_callback)(void *ptr,
++ const char *pattern,
++ const char *string);
++
+ /* These are the return codes for the seek callbacks */
+ #define CURL_SEEKFUNC_OK 0
+ #define CURL_SEEKFUNC_FAIL 1 /* fail the entire transfer */
+ #define CURL_SEEKFUNC_CANTSEEK 2 /* tell libcurl seeking can't be done, so
+ libcurl might try other means instead */
+ typedef int (*curl_seek_callback)(void *instream,
+ curl_off_t offset,
+ int origin); /* 'whence' */
+
+ /* This is a return code for the read callback that, when returned, will
+ signal libcurl to immediately abort the current transfer. */
+ #define CURL_READFUNC_ABORT 0x10000000
+ /* This is a return code for the read callback that, when returned, will
+ signal libcurl to pause sending data on the current transfer. */
+ #define CURL_READFUNC_PAUSE 0x10000001
+
++/* Return code for when the trailing headers' callback has terminated
++ without any errors*/
++#define CURL_TRAILERFUNC_OK 0
++/* Return code for when was an error in the trailing header's list and we
++ want to abort the request */
++#define CURL_TRAILERFUNC_ABORT 1
++
+ typedef size_t (*curl_read_callback)(char *buffer,
+ size_t size,
+ size_t nitems,
+ void *instream);
+
+-typedef enum {
+- CURLSOCKTYPE_IPCXN, /* socket created for a specific IP connection */
+- CURLSOCKTYPE_LAST /* never use */
++typedef int (*curl_trailer_callback)(struct curl_slist **list,
++ void *userdata);
++
++typedef enum {
++ CURLSOCKTYPE_IPCXN, /* socket created for a specific IP connection */
++ CURLSOCKTYPE_ACCEPT, /* socket created by accept() call */
++ CURLSOCKTYPE_LAST /* never use */
+ } curlsocktype;
+
++/* The return code from the sockopt_callback can signal information back
++ to libcurl: */
++#define CURL_SOCKOPT_OK 0
++#define CURL_SOCKOPT_ERROR 1 /* causes libcurl to abort and return
++ CURLE_ABORTED_BY_CALLBACK */
++#define CURL_SOCKOPT_ALREADY_CONNECTED 2
++
+ typedef int (*curl_sockopt_callback)(void *clientp,
+ curl_socket_t curlfd,
+ curlsocktype purpose);
+
+ struct curl_sockaddr {
+ int family;
+ int socktype;
+ int protocol;
+@@ -239,53 +407,52 @@ struct curl_sockaddr {
+ struct sockaddr addr;
+ };
+
+ typedef curl_socket_t
+ (*curl_opensocket_callback)(void *clientp,
+ curlsocktype purpose,
+ struct curl_sockaddr *address);
+
+-#ifndef CURL_NO_OLDIES
+- /* not used since 7.10.8, will be removed in a future release */
+-typedef int (*curl_passwd_callback)(void *clientp,
+- const char *prompt,
+- char *buffer,
+- int buflen);
+-#endif
++typedef int
++(*curl_closesocket_callback)(void *clientp, curl_socket_t item);
+
+ typedef enum {
+ CURLIOE_OK, /* I/O operation successful */
+ CURLIOE_UNKNOWNCMD, /* command was unknown to callback */
+ CURLIOE_FAILRESTART, /* failed to restart the read */
+ CURLIOE_LAST /* never use */
+ } curlioerr;
+
+-typedef enum {
++typedef enum {
+ CURLIOCMD_NOP, /* no operation */
+ CURLIOCMD_RESTARTREAD, /* restart the read stream from start */
+ CURLIOCMD_LAST /* never use */
+ } curliocmd;
+
+ typedef curlioerr (*curl_ioctl_callback)(CURL *handle,
+ int cmd,
+ void *clientp);
+
++#ifndef CURL_DID_MEMORY_FUNC_TYPEDEFS
+ /*
+ * The following typedef's are signatures of malloc, free, realloc, strdup and
+ * calloc respectively. Function pointers of these types can be passed to the
+ * curl_global_init_mem() function to set user defined memory management
+ * callback routines.
+ */
+ typedef void *(*curl_malloc_callback)(size_t size);
+ typedef void (*curl_free_callback)(void *ptr);
+ typedef void *(*curl_realloc_callback)(void *ptr, size_t size);
+ typedef char *(*curl_strdup_callback)(const char *str);
+ typedef void *(*curl_calloc_callback)(size_t nmemb, size_t size);
+
++#define CURL_DID_MEMORY_FUNC_TYPEDEFS
++#endif
++
+ /* the kind of data that is passed to information_callback*/
+ typedef enum {
+ CURLINFO_TEXT = 0,
+ CURLINFO_HEADER_IN, /* 1 */
+ CURLINFO_HEADER_OUT, /* 2 */
+ CURLINFO_DATA_IN, /* 3 */
+ CURLINFO_DATA_OUT, /* 4 */
+ CURLINFO_SSL_DATA_IN, /* 5 */
+@@ -307,31 +474,37 @@ typedef int (*curl_debug_callback)
+ codes must remain the same!
+ */
+
+ typedef enum {
+ CURLE_OK = 0,
+ CURLE_UNSUPPORTED_PROTOCOL, /* 1 */
+ CURLE_FAILED_INIT, /* 2 */
+ CURLE_URL_MALFORMAT, /* 3 */
+- CURLE_OBSOLETE4, /* 4 - NOT USED */
++ CURLE_NOT_BUILT_IN, /* 4 - [was obsoleted in August 2007 for
++ 7.17.0, reused in April 2011 for 7.21.5] */
+ CURLE_COULDNT_RESOLVE_PROXY, /* 5 */
+ CURLE_COULDNT_RESOLVE_HOST, /* 6 */
+ CURLE_COULDNT_CONNECT, /* 7 */
+- CURLE_FTP_WEIRD_SERVER_REPLY, /* 8 */
++ CURLE_WEIRD_SERVER_REPLY, /* 8 */
+ CURLE_REMOTE_ACCESS_DENIED, /* 9 a service was denied by the server
+ due to lack of access - when login fails
+ this is not returned. */
+- CURLE_OBSOLETE10, /* 10 - NOT USED */
++ CURLE_FTP_ACCEPT_FAILED, /* 10 - [was obsoleted in April 2006 for
++ 7.15.4, reused in Dec 2011 for 7.24.0]*/
+ CURLE_FTP_WEIRD_PASS_REPLY, /* 11 */
+- CURLE_OBSOLETE12, /* 12 - NOT USED */
++ CURLE_FTP_ACCEPT_TIMEOUT, /* 12 - timeout occurred accepting server
++ [was obsoleted in August 2007 for 7.17.0,
++ reused in Dec 2011 for 7.24.0]*/
+ CURLE_FTP_WEIRD_PASV_REPLY, /* 13 */
+ CURLE_FTP_WEIRD_227_FORMAT, /* 14 */
+ CURLE_FTP_CANT_GET_HOST, /* 15 */
+- CURLE_OBSOLETE16, /* 16 - NOT USED */
++ CURLE_HTTP2, /* 16 - A problem in the http2 framing layer.
++ [was obsoleted in August 2007 for 7.17.0,
++ reused in July 2014 for 7.38.0] */
+ CURLE_FTP_COULDNT_SET_TYPE, /* 17 */
+ CURLE_PARTIAL_FILE, /* 18 */
+ CURLE_FTP_COULDNT_RETR_FILE, /* 19 */
+ CURLE_OBSOLETE20, /* 20 - NOT USED */
+ CURLE_QUOTE_ERROR, /* 21 - quote command failure */
+ CURLE_HTTP_RETURNED_ERROR, /* 22 */
+ CURLE_WRITE_ERROR, /* 23 */
+ CURLE_OBSOLETE24, /* 24 - NOT USED */
+@@ -350,39 +523,39 @@ typedef enum {
+ CURLE_RANGE_ERROR, /* 33 - RANGE "command" didn't work */
+ CURLE_HTTP_POST_ERROR, /* 34 */
+ CURLE_SSL_CONNECT_ERROR, /* 35 - wrong when connecting with SSL */
+ CURLE_BAD_DOWNLOAD_RESUME, /* 36 - couldn't resume download */
+ CURLE_FILE_COULDNT_READ_FILE, /* 37 */
+ CURLE_LDAP_CANNOT_BIND, /* 38 */
+ CURLE_LDAP_SEARCH_FAILED, /* 39 */
+ CURLE_OBSOLETE40, /* 40 - NOT USED */
+- CURLE_FUNCTION_NOT_FOUND, /* 41 */
++ CURLE_FUNCTION_NOT_FOUND, /* 41 - NOT USED starting with 7.53.0 */
+ CURLE_ABORTED_BY_CALLBACK, /* 42 */
+ CURLE_BAD_FUNCTION_ARGUMENT, /* 43 */
+ CURLE_OBSOLETE44, /* 44 - NOT USED */
+ CURLE_INTERFACE_FAILED, /* 45 - CURLOPT_INTERFACE failed */
+ CURLE_OBSOLETE46, /* 46 - NOT USED */
+- CURLE_TOO_MANY_REDIRECTS , /* 47 - catch endless re-direct loops */
+- CURLE_UNKNOWN_TELNET_OPTION, /* 48 - User specified an unknown option */
+- CURLE_TELNET_OPTION_SYNTAX , /* 49 - Malformed telnet option */
++ CURLE_TOO_MANY_REDIRECTS, /* 47 - catch endless re-direct loops */
++ CURLE_UNKNOWN_OPTION, /* 48 - User specified an unknown option */
++ CURLE_TELNET_OPTION_SYNTAX, /* 49 - Malformed telnet option */
+ CURLE_OBSOLETE50, /* 50 - NOT USED */
+- CURLE_PEER_FAILED_VERIFICATION, /* 51 - peer's certificate or fingerprint
+- wasn't verified fine */
++ CURLE_OBSOLETE51, /* 51 - NOT USED */
+ CURLE_GOT_NOTHING, /* 52 - when this is a specific error */
+ CURLE_SSL_ENGINE_NOTFOUND, /* 53 - SSL crypto engine not found */
+ CURLE_SSL_ENGINE_SETFAILED, /* 54 - can not set SSL crypto engine as
+ default */
+ CURLE_SEND_ERROR, /* 55 - failed sending network data */
+ CURLE_RECV_ERROR, /* 56 - failure in receiving network data */
+ CURLE_OBSOLETE57, /* 57 - NOT IN USE */
+ CURLE_SSL_CERTPROBLEM, /* 58 - problem with the local certificate */
+ CURLE_SSL_CIPHER, /* 59 - couldn't use specified cipher */
+- CURLE_SSL_CACERT, /* 60 - problem with the CA cert (path?) */
+- CURLE_BAD_CONTENT_ENCODING, /* 61 - Unrecognized transfer encoding */
++ CURLE_PEER_FAILED_VERIFICATION, /* 60 - peer's certificate or fingerprint
++ wasn't verified fine */
++ CURLE_BAD_CONTENT_ENCODING, /* 61 - Unrecognized/bad encoding */
+ CURLE_LDAP_INVALID_URL, /* 62 - Invalid LDAP URL */
+ CURLE_FILESIZE_EXCEEDED, /* 63 - Maximum file size exceeded */
+ CURLE_USE_SSL_FAILED, /* 64 - Requested FTP SSL level failed */
+ CURLE_SEND_FAIL_REWIND, /* 65 - Sending the data requires a rewind
+ that failed */
+ CURLE_SSL_ENGINE_INITFAILED, /* 66 - failed to initialise ENGINE */
+ CURLE_LOGIN_DENIED, /* 67 - user, password or similar was not
+ accepted and we failed to login */
+@@ -410,43 +583,72 @@ typedef enum {
+ connection */
+ CURLE_AGAIN, /* 81 - socket is not ready for send/recv,
+ wait till it's ready and try again (Added
+ in 7.18.2) */
+ CURLE_SSL_CRL_BADFILE, /* 82 - could not load CRL file, missing or
+ wrong format (Added in 7.19.0) */
+ CURLE_SSL_ISSUER_ERROR, /* 83 - Issuer check failed. (Added in
+ 7.19.0) */
++ CURLE_FTP_PRET_FAILED, /* 84 - a PRET command failed */
++ CURLE_RTSP_CSEQ_ERROR, /* 85 - mismatch of RTSP CSeq numbers */
++ CURLE_RTSP_SESSION_ERROR, /* 86 - mismatch of RTSP Session Ids */
++ CURLE_FTP_BAD_FILE_LIST, /* 87 - unable to parse FTP file list */
++ CURLE_CHUNK_FAILED, /* 88 - chunk callback reported error */
++ CURLE_NO_CONNECTION_AVAILABLE, /* 89 - No connection available, the
++ session will be queued */
++ CURLE_SSL_PINNEDPUBKEYNOTMATCH, /* 90 - specified pinned public key did not
++ match */
++ CURLE_SSL_INVALIDCERTSTATUS, /* 91 - invalid certificate status */
++ CURLE_HTTP2_STREAM, /* 92 - stream error in HTTP/2 framing layer
++ */
++ CURLE_RECURSIVE_API_CALL, /* 93 - an api function was called from
++ inside a callback */
+ CURL_LAST /* never use! */
+ } CURLcode;
+
+ #ifndef CURL_NO_OLDIES /* define this to test if your app builds with all
+ the obsolete stuff removed! */
+
+-/* Backwards compatibility with older names */
++/* Previously obsolete error code re-used in 7.38.0 */
++#define CURLE_OBSOLETE16 CURLE_HTTP2
++
++/* Previously obsolete error codes re-used in 7.24.0 */
++#define CURLE_OBSOLETE10 CURLE_FTP_ACCEPT_FAILED
++#define CURLE_OBSOLETE12 CURLE_FTP_ACCEPT_TIMEOUT
++
++/* compatibility with older names */
++#define CURLOPT_ENCODING CURLOPT_ACCEPT_ENCODING
++#define CURLE_FTP_WEIRD_SERVER_REPLY CURLE_WEIRD_SERVER_REPLY
++
++/* The following were added in 7.62.0 */
++#define CURLE_SSL_CACERT CURLE_PEER_FAILED_VERIFICATION
++
++/* The following were added in 7.21.5, April 2011 */
++#define CURLE_UNKNOWN_TELNET_OPTION CURLE_UNKNOWN_OPTION
+
+ /* The following were added in 7.17.1 */
+ /* These are scheduled to disappear by 2009 */
+ #define CURLE_SSL_PEER_CERTIFICATE CURLE_PEER_FAILED_VERIFICATION
+
+ /* The following were added in 7.17.0 */
+ /* These are scheduled to disappear by 2009 */
+-#define CURLE_OBSOLETE CURLE_OBSOLETE50 /* noone should be using this! */
++#define CURLE_OBSOLETE CURLE_OBSOLETE50 /* no one should be using this! */
+ #define CURLE_BAD_PASSWORD_ENTERED CURLE_OBSOLETE46
+ #define CURLE_BAD_CALLING_ORDER CURLE_OBSOLETE44
+ #define CURLE_FTP_USER_PASSWORD_INCORRECT CURLE_OBSOLETE10
+ #define CURLE_FTP_CANT_RECONNECT CURLE_OBSOLETE16
+ #define CURLE_FTP_COULDNT_GET_SIZE CURLE_OBSOLETE32
+ #define CURLE_FTP_COULDNT_SET_ASCII CURLE_OBSOLETE29
+ #define CURLE_FTP_WEIRD_USER_REPLY CURLE_OBSOLETE12
+ #define CURLE_FTP_WRITE_ERROR CURLE_OBSOLETE20
+ #define CURLE_LIBRARY_NOT_FOUND CURLE_OBSOLETE40
+ #define CURLE_MALFORMAT_USER CURLE_OBSOLETE24
+ #define CURLE_SHARE_IN_USE CURLE_OBSOLETE57
+-#define CURLE_URL_MALFORMAT_USER CURLE_OBSOLETE4
++#define CURLE_URL_MALFORMAT_USER CURLE_NOT_BUILT_IN
+
+ #define CURLE_FTP_ACCESS_DENIED CURLE_REMOTE_ACCESS_DENIED
+ #define CURLE_FTP_COULDNT_SET_BINARY CURLE_FTP_COULDNT_SET_TYPE
+ #define CURLE_FTP_QUOTE_ERROR CURLE_QUOTE_ERROR
+ #define CURLE_TFTP_DISKFULL CURLE_REMOTE_DISK_FULL
+ #define CURLE_TFTP_EXISTS CURLE_REMOTE_FILE_EXISTS
+ #define CURLE_HTTP_RANGE_ERROR CURLE_RANGE_ERROR
+ #define CURLE_FTP_SSL_FAILED CURLE_USE_SSL_FAILED
+@@ -462,69 +664,115 @@ typedef enum {
+ #define CURLE_FTP_PARTIAL_FILE CURLE_PARTIAL_FILE
+ #define CURLE_FTP_BAD_DOWNLOAD_RESUME CURLE_BAD_DOWNLOAD_RESUME
+
+ /* This was the error code 50 in 7.7.3 and a few earlier versions, this
+ is no longer used by libcurl but is instead #defined here only to not
+ make programs break */
+ #define CURLE_ALREADY_COMPLETE 99999
+
++/* Provide defines for really old option names */
++#define CURLOPT_FILE CURLOPT_WRITEDATA /* name changed in 7.9.7 */
++#define CURLOPT_INFILE CURLOPT_READDATA /* name changed in 7.9.7 */
++#define CURLOPT_WRITEHEADER CURLOPT_HEADERDATA
++
++/* Since long deprecated options with no code in the lib that does anything
++ with them. */
++#define CURLOPT_WRITEINFO CURLOPT_OBSOLETE40
++#define CURLOPT_CLOSEPOLICY CURLOPT_OBSOLETE72
++
+ #endif /*!CURL_NO_OLDIES*/
+
+ /* This prototype applies to all conversion callbacks */
+ typedef CURLcode (*curl_conv_callback)(char *buffer, size_t length);
+
+ typedef CURLcode (*curl_ssl_ctx_callback)(CURL *curl, /* easy handle */
+ void *ssl_ctx, /* actually an
+ OpenSSL SSL_CTX */
+ void *userptr);
+
+ typedef enum {
+ CURLPROXY_HTTP = 0, /* added in 7.10, new in 7.19.4 default is to use
+ CONNECT HTTP/1.1 */
+ CURLPROXY_HTTP_1_0 = 1, /* added in 7.19.4, force to use CONNECT
+ HTTP/1.0 */
++ CURLPROXY_HTTPS = 2, /* added in 7.52.0 */
+ CURLPROXY_SOCKS4 = 4, /* support added in 7.15.2, enum existed already
+ in 7.10 */
+ CURLPROXY_SOCKS5 = 5, /* added in 7.10 */
+ CURLPROXY_SOCKS4A = 6, /* added in 7.18.0 */
+ CURLPROXY_SOCKS5_HOSTNAME = 7 /* Use the SOCKS5 protocol but pass along the
+ host name rather than the IP address. added
+ in 7.18.0 */
+ } curl_proxytype; /* this enum was added in 7.10 */
+
+-#define CURLAUTH_NONE 0 /* nothing */
+-#define CURLAUTH_BASIC (1<<0) /* Basic (default) */
+-#define CURLAUTH_DIGEST (1<<1) /* Digest */
+-#define CURLAUTH_GSSNEGOTIATE (1<<2) /* GSS-Negotiate */
+-#define CURLAUTH_NTLM (1<<3) /* NTLM */
+-#define CURLAUTH_DIGEST_IE (1<<4) /* Digest with IE flavour */
+-#define CURLAUTH_ANY (~CURLAUTH_DIGEST_IE) /* all fine types set */
+-#define CURLAUTH_ANYSAFE (~(CURLAUTH_BASIC|CURLAUTH_DIGEST_IE))
++/*
++ * Bitmasks for CURLOPT_HTTPAUTH and CURLOPT_PROXYAUTH options:
++ *
++ * CURLAUTH_NONE - No HTTP authentication
++ * CURLAUTH_BASIC - HTTP Basic authentication (default)
++ * CURLAUTH_DIGEST - HTTP Digest authentication
++ * CURLAUTH_NEGOTIATE - HTTP Negotiate (SPNEGO) authentication
++ * CURLAUTH_GSSNEGOTIATE - Alias for CURLAUTH_NEGOTIATE (deprecated)
++ * CURLAUTH_NTLM - HTTP NTLM authentication
++ * CURLAUTH_DIGEST_IE - HTTP Digest authentication with IE flavour
++ * CURLAUTH_NTLM_WB - HTTP NTLM authentication delegated to winbind helper
++ * CURLAUTH_BEARER - HTTP Bearer token authentication
++ * CURLAUTH_ONLY - Use together with a single other type to force no
++ * authentication or just that single type
++ * CURLAUTH_ANY - All fine types set
++ * CURLAUTH_ANYSAFE - All fine types except Basic
++ */
++
++#define CURLAUTH_NONE ((unsigned long)0)
++#define CURLAUTH_BASIC (((unsigned long)1)<<0)
++#define CURLAUTH_DIGEST (((unsigned long)1)<<1)
++#define CURLAUTH_NEGOTIATE (((unsigned long)1)<<2)
++/* Deprecated since the advent of CURLAUTH_NEGOTIATE */
++#define CURLAUTH_GSSNEGOTIATE CURLAUTH_NEGOTIATE
++/* Used for CURLOPT_SOCKS5_AUTH to stay terminologically correct */
++#define CURLAUTH_GSSAPI CURLAUTH_NEGOTIATE
++#define CURLAUTH_NTLM (((unsigned long)1)<<3)
++#define CURLAUTH_DIGEST_IE (((unsigned long)1)<<4)
++#define CURLAUTH_NTLM_WB (((unsigned long)1)<<5)
++#define CURLAUTH_BEARER (((unsigned long)1)<<6)
++#define CURLAUTH_ONLY (((unsigned long)1)<<31)
++#define CURLAUTH_ANY (~CURLAUTH_DIGEST_IE)
++#define CURLAUTH_ANYSAFE (~(CURLAUTH_BASIC|CURLAUTH_DIGEST_IE))
+
+ #define CURLSSH_AUTH_ANY ~0 /* all types supported by the server */
+ #define CURLSSH_AUTH_NONE 0 /* none allowed, silly but complete */
+ #define CURLSSH_AUTH_PUBLICKEY (1<<0) /* public/private key files */
+ #define CURLSSH_AUTH_PASSWORD (1<<1) /* password */
+ #define CURLSSH_AUTH_HOST (1<<2) /* host key files */
+ #define CURLSSH_AUTH_KEYBOARD (1<<3) /* keyboard interactive */
++#define CURLSSH_AUTH_AGENT (1<<4) /* agent (ssh-agent, pageant...) */
++#define CURLSSH_AUTH_GSSAPI (1<<5) /* gssapi (kerberos, ...) */
+ #define CURLSSH_AUTH_DEFAULT CURLSSH_AUTH_ANY
+
++#define CURLGSSAPI_DELEGATION_NONE 0 /* no delegation (default) */
++#define CURLGSSAPI_DELEGATION_POLICY_FLAG (1<<0) /* if permitted by policy */
++#define CURLGSSAPI_DELEGATION_FLAG (1<<1) /* delegate always */
++
+ #define CURL_ERROR_SIZE 256
+
++enum curl_khtype {
++ CURLKHTYPE_UNKNOWN,
++ CURLKHTYPE_RSA1,
++ CURLKHTYPE_RSA,
++ CURLKHTYPE_DSS,
++ CURLKHTYPE_ECDSA,
++ CURLKHTYPE_ED25519
++};
++
+ struct curl_khkey {
+ const char *key; /* points to a zero-terminated string encoded with base64
+ if len is zero, otherwise to the "raw" data */
+ size_t len;
+- enum type {
+- CURLKHTYPE_UNKNOWN,
+- CURLKHTYPE_RSA1,
+- CURLKHTYPE_RSA,
+- CURLKHTYPE_DSS
+- } keytype;
++ enum curl_khtype keytype;
+ };
+
+ /* this is the set of return values expected from the curl_sshkeycallback
+ callback */
+ enum curl_khstat {
+ CURLKHSTAT_FINE_ADD_TO_FILE,
+ CURLKHSTAT_FINE,
+ CURLKHSTAT_REJECT, /* reject the connection, return an error */
+@@ -553,16 +801,37 @@ typedef int
+ typedef enum {
+ CURLUSESSL_NONE, /* do not attempt to use SSL */
+ CURLUSESSL_TRY, /* try using SSL, proceed anyway otherwise */
+ CURLUSESSL_CONTROL, /* SSL for the control connection or fail */
+ CURLUSESSL_ALL, /* SSL for all communication or fail */
+ CURLUSESSL_LAST /* not an option, never use */
+ } curl_usessl;
+
++/* Definition of bits for the CURLOPT_SSL_OPTIONS argument: */
++
++/* - ALLOW_BEAST tells libcurl to allow the BEAST SSL vulnerability in the
++ name of improving interoperability with older servers. Some SSL libraries
++ have introduced work-arounds for this flaw but those work-arounds sometimes
++ make the SSL communication fail. To regain functionality with those broken
++ servers, a user can this way allow the vulnerability back. */
++#define CURLSSLOPT_ALLOW_BEAST (1<<0)
++
++/* - NO_REVOKE tells libcurl to disable certificate revocation checks for those
++ SSL backends where such behavior is present. */
++#define CURLSSLOPT_NO_REVOKE (1<<1)
++
++/* The default connection attempt delay in milliseconds for happy eyeballs.
++ CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS.3 and happy-eyeballs-timeout-ms.d document
++ this value, keep them in sync. */
++#define CURL_HET_DEFAULT 200L
++
++/* The default connection upkeep interval in milliseconds. */
++#define CURL_UPKEEP_INTERVAL_DEFAULT 60000L
++
+ #ifndef CURL_NO_OLDIES /* define this to test if your app builds with all
+ the obsolete stuff removed! */
+
+ /* Backwards compatibility with older names */
+ /* These are scheduled to disappear by 2009 */
+
+ #define CURLFTPSSL_NONE CURLUSESSL_NONE
+ #define CURLFTPSSL_TRY CURLUSESSL_TRY
+@@ -603,91 +872,124 @@ typedef enum {
+ typedef enum {
+ CURLFTPMETHOD_DEFAULT, /* let libcurl pick */
+ CURLFTPMETHOD_MULTICWD, /* single CWD operation for each path part */
+ CURLFTPMETHOD_NOCWD, /* no CWD at all */
+ CURLFTPMETHOD_SINGLECWD, /* one CWD to full dir, then work on file */
+ CURLFTPMETHOD_LAST /* not an option, never use */
+ } curl_ftpmethod;
+
++/* bitmask defines for CURLOPT_HEADEROPT */
++#define CURLHEADER_UNIFIED 0
++#define CURLHEADER_SEPARATE (1<<0)
++
++/* CURLALTSVC_* are bits for the CURLOPT_ALTSVC_CTRL option */
++#define CURLALTSVC_IMMEDIATELY (1<<0)
++#define CURLALTSVC_ALTUSED (1<<1)
++#define CURLALTSVC_READONLYFILE (1<<2)
++#define CURLALTSVC_H1 (1<<3)
++#define CURLALTSVC_H2 (1<<4)
++#define CURLALTSVC_H3 (1<<5)
++
+ /* CURLPROTO_ defines are for the CURLOPT_*PROTOCOLS options */
+ #define CURLPROTO_HTTP (1<<0)
+ #define CURLPROTO_HTTPS (1<<1)
+ #define CURLPROTO_FTP (1<<2)
+ #define CURLPROTO_FTPS (1<<3)
+ #define CURLPROTO_SCP (1<<4)
+ #define CURLPROTO_SFTP (1<<5)
+ #define CURLPROTO_TELNET (1<<6)
+ #define CURLPROTO_LDAP (1<<7)
+ #define CURLPROTO_LDAPS (1<<8)
+ #define CURLPROTO_DICT (1<<9)
+ #define CURLPROTO_FILE (1<<10)
+ #define CURLPROTO_TFTP (1<<11)
++#define CURLPROTO_IMAP (1<<12)
++#define CURLPROTO_IMAPS (1<<13)
++#define CURLPROTO_POP3 (1<<14)
++#define CURLPROTO_POP3S (1<<15)
++#define CURLPROTO_SMTP (1<<16)
++#define CURLPROTO_SMTPS (1<<17)
++#define CURLPROTO_RTSP (1<<18)
++#define CURLPROTO_RTMP (1<<19)
++#define CURLPROTO_RTMPT (1<<20)
++#define CURLPROTO_RTMPE (1<<21)
++#define CURLPROTO_RTMPTE (1<<22)
++#define CURLPROTO_RTMPS (1<<23)
++#define CURLPROTO_RTMPTS (1<<24)
++#define CURLPROTO_GOPHER (1<<25)
++#define CURLPROTO_SMB (1<<26)
++#define CURLPROTO_SMBS (1<<27)
+ #define CURLPROTO_ALL (~0) /* enable everything */
+
+ /* long may be 32 or 64 bits, but we should never depend on anything else
+ but 32 */
+ #define CURLOPTTYPE_LONG 0
+ #define CURLOPTTYPE_OBJECTPOINT 10000
++#define CURLOPTTYPE_STRINGPOINT 10000
+ #define CURLOPTTYPE_FUNCTIONPOINT 20000
+ #define CURLOPTTYPE_OFF_T 30000
+
++/* *STRINGPOINT is an alias for OBJECTPOINT to allow tools to extract the
++ string options from the header file */
++
+ /* name is uppercase CURLOPT_<name>,
+ type is one of the defined CURLOPTTYPE_<type>
+ number is unique identifier */
+ #ifdef CINIT
+ #undef CINIT
+ #endif
+
+ #ifdef CURL_ISOCPP
+-#define CINIT(name,type,number) CURLOPT_ ## name = CURLOPTTYPE_ ## type + number
++#define CINIT(na,t,nu) CURLOPT_ ## na = CURLOPTTYPE_ ## t + nu
+ #else
+ /* The macro "##" is ISO C, we assume pre-ISO C doesn't support it. */
+ #define LONG CURLOPTTYPE_LONG
+ #define OBJECTPOINT CURLOPTTYPE_OBJECTPOINT
++#define STRINGPOINT CURLOPTTYPE_OBJECTPOINT
+ #define FUNCTIONPOINT CURLOPTTYPE_FUNCTIONPOINT
+ #define OFF_T CURLOPTTYPE_OFF_T
+ #define CINIT(name,type,number) CURLOPT_/**/name = type + number
+ #endif
+
+ /*
+ * This macro-mania below setups the CURLOPT_[what] enum, to be used with
+ * curl_easy_setopt(). The first argument in the CINIT() macro is the [what]
+ * word.
+ */
+
+ typedef enum {
+ /* This is the FILE * or void * the regular output should be written to. */
+- CINIT(FILE, OBJECTPOINT, 1),
++ CINIT(WRITEDATA, OBJECTPOINT, 1),
+
+ /* The full URL to get/put */
+- CINIT(URL, OBJECTPOINT, 2),
++ CINIT(URL, STRINGPOINT, 2),
+
+ /* Port number to connect to, if other than default. */
+ CINIT(PORT, LONG, 3),
+
+ /* Name of proxy to use. */
+- CINIT(PROXY, OBJECTPOINT, 4),
+-
+- /* "name:password" to use when fetching. */
+- CINIT(USERPWD, OBJECTPOINT, 5),
+-
+- /* "name:password" to use with proxy. */
+- CINIT(PROXYUSERPWD, OBJECTPOINT, 6),
++ CINIT(PROXY, STRINGPOINT, 4),
++
++ /* "user:password;options" to use when fetching. */
++ CINIT(USERPWD, STRINGPOINT, 5),
++
++ /* "user:password" to use with proxy. */
++ CINIT(PROXYUSERPWD, STRINGPOINT, 6),
+
+ /* Range to get, specified as an ASCII string. */
+- CINIT(RANGE, OBJECTPOINT, 7),
++ CINIT(RANGE, STRINGPOINT, 7),
+
+ /* not used */
+
+ /* Specified file stream to upload from (use as input): */
+- CINIT(INFILE, OBJECTPOINT, 9),
++ CINIT(READDATA, OBJECTPOINT, 9),
+
+ /* Buffer to receive error messages in, must be at least CURL_ERROR_SIZE
+- * bytes big. If this is not used, error messages go to stderr instead: */
++ * bytes big. */
+ CINIT(ERRORBUFFER, OBJECTPOINT, 10),
+
+ /* Function that will be called to store the output (instead of fwrite). The
+ * parameters will use fwrite() syntax, make sure to follow them. */
+ CINIT(WRITEFUNCTION, FUNCTIONPOINT, 11),
+
+ /* Function that will be called to read the input (instead of fread). The
+ * parameters will use fread() syntax, make sure to follow them. */
+@@ -706,24 +1008,24 @@ typedef enum {
+ * sizes to handle larger files. See below for INFILESIZE_LARGE.
+ */
+ CINIT(INFILESIZE, LONG, 14),
+
+ /* POST static input fields. */
+ CINIT(POSTFIELDS, OBJECTPOINT, 15),
+
+ /* Set the referrer page (needed by some CGIs) */
+- CINIT(REFERER, OBJECTPOINT, 16),
++ CINIT(REFERER, STRINGPOINT, 16),
+
+ /* Set the FTP PORT string (interface name, named or numerical IP address)
+ Use i.e '-' to use default address. */
+- CINIT(FTPPORT, OBJECTPOINT, 17),
++ CINIT(FTPPORT, STRINGPOINT, 17),
+
+ /* Set the User-Agent string (examined by some CGIs) */
+- CINIT(USERAGENT, OBJECTPOINT, 18),
++ CINIT(USERAGENT, STRINGPOINT, 18),
+
+ /* If the download receives less than "low speed limit" bytes/second
+ * during "low speed time" seconds, the operations is aborted.
+ * You could i.e if you have a pretty high speed connection, abort if
+ * it is less than 2000 bytes/sec during 20 seconds.
+ */
+
+ /* Set the "low speed limit" */
+@@ -736,43 +1038,44 @@ typedef enum {
+ *
+ * Note there is also a _LARGE version of this key which uses
+ * off_t types, allowing for large file offsets on platforms which
+ * use larger-than-32-bit off_t's. Look below for RESUME_FROM_LARGE.
+ */
+ CINIT(RESUME_FROM, LONG, 21),
+
+ /* Set cookie in request: */
+- CINIT(COOKIE, OBJECTPOINT, 22),
+-
+- /* This points to a linked list of headers, struct curl_slist kind */
++ CINIT(COOKIE, STRINGPOINT, 22),
++
++ /* This points to a linked list of headers, struct curl_slist kind. This
++ list is also used for RTSP (in spite of its name) */
+ CINIT(HTTPHEADER, OBJECTPOINT, 23),
+
+ /* This points to a linked list of post entries, struct curl_httppost */
+ CINIT(HTTPPOST, OBJECTPOINT, 24),
+
+ /* name of the file keeping your private SSL-certificate */
+- CINIT(SSLCERT, OBJECTPOINT, 25),
++ CINIT(SSLCERT, STRINGPOINT, 25),
+
+ /* password for the SSL or SSH private key */
+- CINIT(KEYPASSWD, OBJECTPOINT, 26),
++ CINIT(KEYPASSWD, STRINGPOINT, 26),
+
+ /* send TYPE parameter? */
+ CINIT(CRLF, LONG, 27),
+
+ /* send linked-list of QUOTE commands */
+ CINIT(QUOTE, OBJECTPOINT, 28),
+
+ /* send FILE * or void * to store headers to, if you use a callback it
+ is simply passed to the callback unmodified */
+- CINIT(WRITEHEADER, OBJECTPOINT, 29),
++ CINIT(HEADERDATA, OBJECTPOINT, 29),
+
+ /* point to a file to read the initial cookies from, also enables
+ "cookie awareness" */
+- CINIT(COOKIEFILE, OBJECTPOINT, 31),
++ CINIT(COOKIEFILE, STRINGPOINT, 31),
+
+ /* What version to specifically try to use.
+ See CURL_SSLVERSION defines below. */
+ CINIT(SSLVERSION, LONG, 32),
+
+ /* What kind of HTTP time condition to use, see defines */
+ CINIT(TIMECONDITION, LONG, 33),
+
+@@ -781,87 +1084,88 @@ typedef enum {
+ CINIT(TIMEVALUE, LONG, 34),
+
+ /* 35 = OBSOLETE */
+
+ /* Custom request, for customizing the get command like
+ HTTP: DELETE, TRACE and others
+ FTP: to use a different list command
+ */
+- CINIT(CUSTOMREQUEST, OBJECTPOINT, 36),
+-
+- /* HTTP request, for odd commands like DELETE, TRACE and others */
++ CINIT(CUSTOMREQUEST, STRINGPOINT, 36),
++
++ /* FILE handle to use instead of stderr */
+ CINIT(STDERR, OBJECTPOINT, 37),
+
+ /* 38 is not used */
+
+ /* send linked-list of post-transfer QUOTE commands */
+ CINIT(POSTQUOTE, OBJECTPOINT, 39),
+
+- /* Pass a pointer to string of the output using full variable-replacement
+- as described elsewhere. */
+- CINIT(WRITEINFO, OBJECTPOINT, 40),
++ CINIT(OBSOLETE40, OBJECTPOINT, 40), /* OBSOLETE, do not use! */
+
+ CINIT(VERBOSE, LONG, 41), /* talk a lot */
+ CINIT(HEADER, LONG, 42), /* throw the header out too */
+ CINIT(NOPROGRESS, LONG, 43), /* shut off the progress meter */
+ CINIT(NOBODY, LONG, 44), /* use HEAD to get http document */
+- CINIT(FAILONERROR, LONG, 45), /* no output on http error codes >= 300 */
++ CINIT(FAILONERROR, LONG, 45), /* no output on http error codes >= 400 */
+ CINIT(UPLOAD, LONG, 46), /* this is an upload */
+ CINIT(POST, LONG, 47), /* HTTP POST method */
+- CINIT(DIRLISTONLY, LONG, 48), /* return bare names when listing directories */
++ CINIT(DIRLISTONLY, LONG, 48), /* bare names when listing directories */
+
+ CINIT(APPEND, LONG, 50), /* Append instead of overwrite on upload! */
+
+ /* Specify whether to read the user+password from the .netrc or the URL.
+ * This must be one of the CURL_NETRC_* enums below. */
+ CINIT(NETRC, LONG, 51),
+
+ CINIT(FOLLOWLOCATION, LONG, 52), /* use Location: Luke! */
+
+ CINIT(TRANSFERTEXT, LONG, 53), /* transfer data in text/ASCII format */
+ CINIT(PUT, LONG, 54), /* HTTP PUT */
+
+ /* 55 = OBSOLETE */
+
+- /* Function that will be called instead of the internal progress display
++ /* DEPRECATED
++ * Function that will be called instead of the internal progress display
+ * function. This function should be defined as the curl_progress_callback
+ * prototype defines. */
+ CINIT(PROGRESSFUNCTION, FUNCTIONPOINT, 56),
+
+- /* Data passed to the progress callback */
++ /* Data passed to the CURLOPT_PROGRESSFUNCTION and CURLOPT_XFERINFOFUNCTION
++ callbacks */
+ CINIT(PROGRESSDATA, OBJECTPOINT, 57),
++#define CURLOPT_XFERINFODATA CURLOPT_PROGRESSDATA
+
+ /* We want the referrer field set automatically when following locations */
+ CINIT(AUTOREFERER, LONG, 58),
+
+ /* Port of the proxy, can be set in the proxy string as well with:
+ "[host]:[port]" */
+ CINIT(PROXYPORT, LONG, 59),
+
+ /* size of the POST input data, if strlen() is not good to use */
+ CINIT(POSTFIELDSIZE, LONG, 60),
+
+ /* tunnel non-http operations through a HTTP proxy */
+ CINIT(HTTPPROXYTUNNEL, LONG, 61),
+
+ /* Set the interface string to use as outgoing network interface */
+- CINIT(INTERFACE, OBJECTPOINT, 62),
++ CINIT(INTERFACE, STRINGPOINT, 62),
+
+ /* Set the krb4/5 security level, this also enables krb4/5 awareness. This
+ * is a string, 'clear', 'safe', 'confidential' or 'private'. If the string
+ * is set but doesn't match one of these, 'private' will be used. */
+- CINIT(KRBLEVEL, OBJECTPOINT, 63),
++ CINIT(KRBLEVEL, STRINGPOINT, 63),
+
+ /* Set if we should verify the peer in ssl handshake, set 1 to verify. */
+ CINIT(SSL_VERIFYPEER, LONG, 64),
+
+ /* The CApath or CAfile used to validate the peer certificate
+ this option is used only if SSL_VERIFYPEER is true */
+- CINIT(CAINFO, OBJECTPOINT, 65),
++ CINIT(CAINFO, STRINGPOINT, 65),
+
+ /* 66 = OBSOLETE */
+ /* 67 = OBSOLETE */
+
+ /* Maximum number of http redirects to follow */
+ CINIT(MAXREDIRS, LONG, 68),
+
+ /* Pass a long set to 1 to get the date of the requested document (if
+@@ -869,42 +1173,39 @@ typedef enum {
+ CINIT(FILETIME, LONG, 69),
+
+ /* This points to a linked list of telnet options */
+ CINIT(TELNETOPTIONS, OBJECTPOINT, 70),
+
+ /* Max amount of cached alive connections */
+ CINIT(MAXCONNECTS, LONG, 71),
+
+- /* What policy to use when closing connections when the cache is filled
+- up */
+- CINIT(CLOSEPOLICY, LONG, 72),
++ CINIT(OBSOLETE72, LONG, 72), /* OBSOLETE, do not use! */
+
+ /* 73 = OBSOLETE */
+
+ /* Set to explicitly use a new connection for the upcoming transfer.
+ Do not use this unless you're absolutely sure of this, as it makes the
+ operation slower and is less friendly for the network. */
+ CINIT(FRESH_CONNECT, LONG, 74),
+
+ /* Set to explicitly forbid the upcoming transfer's connection to be re-used
+ when done. Do not use this unless you're absolutely sure of this, as it
+ makes the operation slower and is less friendly for the network. */
+ CINIT(FORBID_REUSE, LONG, 75),
+
+ /* Set to a file name that contains random data for libcurl to use to
+ seed the random engine when doing SSL connects. */
+- CINIT(RANDOM_FILE, OBJECTPOINT, 76),
++ CINIT(RANDOM_FILE, STRINGPOINT, 76),
+
+ /* Set to the Entropy Gathering Daemon socket pathname */
+- CINIT(EGDSOCKET, OBJECTPOINT, 77),
+-
+- /* Time-out connect operations after this amount of seconds, if connects
+- are OK within this time, then fine... This only aborts the connect
+- phase. [Only works on unix-style/SIGALRM operating systems] */
++ CINIT(EGDSOCKET, STRINGPOINT, 77),
++
++ /* Time-out connect operations after this amount of seconds, if connects are
++ OK within this time, then fine... This only aborts the connect phase. */
+ CINIT(CONNECTTIMEOUT, LONG, 78),
+
+ /* Function that will be called to store headers (instead of fwrite). The
+ * parameters will use fwrite() syntax, make sure to follow them. */
+ CINIT(HEADERFUNCTION, FUNCTIONPOINT, 79),
+
+ /* Set this to force the HTTP request to get back to GET. Only really usable
+ if POST, PUT or a custom request have been used first.
+@@ -913,49 +1214,49 @@ typedef enum {
+
+ /* Set if we should verify the Common name from the peer certificate in ssl
+ * handshake, set 1 to check existence, 2 to ensure that it matches the
+ * provided hostname. */
+ CINIT(SSL_VERIFYHOST, LONG, 81),
+
+ /* Specify which file name to write all known cookies in after completed
+ operation. Set file name to "-" (dash) to make it go to stdout. */
+- CINIT(COOKIEJAR, OBJECTPOINT, 82),
++ CINIT(COOKIEJAR, STRINGPOINT, 82),
+
+ /* Specify which SSL ciphers to use */
+- CINIT(SSL_CIPHER_LIST, OBJECTPOINT, 83),
++ CINIT(SSL_CIPHER_LIST, STRINGPOINT, 83),
+
+ /* Specify which HTTP version to use! This must be set to one of the
+ CURL_HTTP_VERSION* enums set below. */
+ CINIT(HTTP_VERSION, LONG, 84),
+
+ /* Specifically switch on or off the FTP engine's use of the EPSV command. By
+ default, that one will always be attempted before the more traditional
+ PASV command. */
+ CINIT(FTP_USE_EPSV, LONG, 85),
+
+ /* type of the file keeping your SSL-certificate ("DER", "PEM", "ENG") */
+- CINIT(SSLCERTTYPE, OBJECTPOINT, 86),
++ CINIT(SSLCERTTYPE, STRINGPOINT, 86),
+
+ /* name of the file keeping your private SSL-key */
+- CINIT(SSLKEY, OBJECTPOINT, 87),
++ CINIT(SSLKEY, STRINGPOINT, 87),
+
+ /* type of the file keeping your private SSL-key ("DER", "PEM", "ENG") */
+- CINIT(SSLKEYTYPE, OBJECTPOINT, 88),
++ CINIT(SSLKEYTYPE, STRINGPOINT, 88),
+
+ /* crypto engine for the SSL-sub system */
+- CINIT(SSLENGINE, OBJECTPOINT, 89),
++ CINIT(SSLENGINE, STRINGPOINT, 89),
+
+ /* set the crypto engine for the SSL-sub system as default
+ the param has no meaning...
+ */
+ CINIT(SSLENGINE_DEFAULT, LONG, 90),
+
+ /* Non-zero value means to use the global dns cache */
+- CINIT(DNS_USE_GLOBAL_CACHE, LONG, 91), /* To become OBSOLETE soon */
++ CINIT(DNS_USE_GLOBAL_CACHE, LONG, 91), /* DEPRECATED, do not use! */
+
+ /* DNS cache timeout */
+ CINIT(DNS_CACHE_TIMEOUT, LONG, 92),
+
+ /* send linked-list of pre-transfer QUOTE commands */
+ CINIT(PREQUOTE, OBJECTPOINT, 93),
+
+ /* set the debug function */
+@@ -964,50 +1265,52 @@ typedef enum {
+ /* set the data for the debug function */
+ CINIT(DEBUGDATA, OBJECTPOINT, 95),
+
+ /* mark this as start of a cookie session */
+ CINIT(COOKIESESSION, LONG, 96),
+
+ /* The CApath directory used to validate the peer certificate
+ this option is used only if SSL_VERIFYPEER is true */
+- CINIT(CAPATH, OBJECTPOINT, 97),
++ CINIT(CAPATH, STRINGPOINT, 97),
+
+ /* Instruct libcurl to use a smaller receive buffer */
+ CINIT(BUFFERSIZE, LONG, 98),
+
+ /* Instruct libcurl to not use any signal/alarm handlers, even when using
+ timeouts. This option is useful for multi-threaded applications.
+ See libcurl-the-guide for more background information. */
+ CINIT(NOSIGNAL, LONG, 99),
+
+ /* Provide a CURLShare for mutexing non-ts data */
+ CINIT(SHARE, OBJECTPOINT, 100),
+
+ /* indicates type of proxy. accepted values are CURLPROXY_HTTP (default),
+- CURLPROXY_SOCKS4, CURLPROXY_SOCKS4A and CURLPROXY_SOCKS5. */
++ CURLPROXY_HTTPS, CURLPROXY_SOCKS4, CURLPROXY_SOCKS4A and
++ CURLPROXY_SOCKS5. */
+ CINIT(PROXYTYPE, LONG, 101),
+
+ /* Set the Accept-Encoding string. Use this to tell a server you would like
+- the response to be compressed. */
+- CINIT(ENCODING, OBJECTPOINT, 102),
++ the response to be compressed. Before 7.21.6, this was known as
++ CURLOPT_ENCODING */
++ CINIT(ACCEPT_ENCODING, STRINGPOINT, 102),
+
+ /* Set pointer to private data */
+ CINIT(PRIVATE, OBJECTPOINT, 103),
+
+ /* Set aliases for HTTP 200 in the HTTP Response header */
+ CINIT(HTTP200ALIASES, OBJECTPOINT, 104),
+
+ /* Continue to send authentication (user+password) when following locations,
+ even when hostname changed. This can potentially send off the name
+ and password to whatever host the server decides. */
+ CINIT(UNRESTRICTED_AUTH, LONG, 105),
+
+- /* Specifically switch on or off the FTP engine's use of the EPRT command ( it
+- also disables the LPRT attempt). By default, those ones will always be
++ /* Specifically switch on or off the FTP engine's use of the EPRT command (
++ it also disables the LPRT attempt). By default, those ones will always be
+ attempted before the good old traditional PORT command. */
+ CINIT(FTP_USE_EPRT, LONG, 106),
+
+ /* Set this to a bitmask value to enable the particular authentications
+ methods you like. Use this in combination with CURLOPT_USERPWD.
+ Note that setting multiple bits may cause extra network round-trips. */
+ CINIT(HTTPAUTH, LONG, 107),
+
+@@ -1031,16 +1334,17 @@ typedef enum {
+ Note that setting multiple bits may cause extra network round-trips. */
+ CINIT(PROXYAUTH, LONG, 111),
+
+ /* FTP option that changes the timeout, in seconds, associated with
+ getting a response. This is different from transfer timeout time and
+ essentially places a demand on the FTP server to acknowledge commands
+ in a timely manner. */
+ CINIT(FTP_RESPONSE_TIMEOUT, LONG, 112),
++#define CURLOPT_SERVER_RESPONSE_TIMEOUT CURLOPT_FTP_RESPONSE_TIMEOUT
+
+ /* Set this option to one of the CURL_IPRESOLVE_* defines (see below) to
+ tell libcurl to resolve names to those IP versions only. This only has
+ affect on systems with support for more than one, i.e IPv4 _and_ IPv6. */
+ CINIT(IPRESOLVE, LONG, 113),
+
+ /* Set this option to limit the size of a file that will be downloaded from
+ an HTTP or FTP server.
+@@ -1063,22 +1367,22 @@ typedef enum {
+ * an HTTP or FTP server. See MAXFILESIZE above for the LONG version.
+ */
+ CINIT(MAXFILESIZE_LARGE, OFF_T, 117),
+
+ /* Set this option to the file name of your .netrc file you want libcurl
+ to parse (using the CURLOPT_NETRC option). If not set, libcurl will do
+ a poor attempt to find the user's home directory and check for a .netrc
+ file in there. */
+- CINIT(NETRC_FILE, OBJECTPOINT, 118),
++ CINIT(NETRC_FILE, STRINGPOINT, 118),
+
+ /* Enable SSL/TLS for FTP, pick one of:
+- CURLFTPSSL_TRY - try using SSL, proceed anyway otherwise
+- CURLFTPSSL_CONTROL - SSL for the control connection or fail
+- CURLFTPSSL_ALL - SSL for all communication or fail
++ CURLUSESSL_TRY - try using SSL, proceed anyway otherwise
++ CURLUSESSL_CONTROL - SSL for the control connection or fail
++ CURLUSESSL_ALL - SSL for all communication or fail
+ */
+ CINIT(USE_SSL, LONG, 119),
+
+ /* The _LARGE version of the standard POSTFIELDSIZE option */
+ CINIT(POSTFIELDSIZE_LARGE, OFF_T, 120),
+
+ /* Enable/disable the TCP Nagle algorithm */
+ CINIT(TCP_NODELAY, LONG, 121),
+@@ -1106,20 +1410,20 @@ typedef enum {
+ CINIT(IOCTLFUNCTION, FUNCTIONPOINT, 130),
+ CINIT(IOCTLDATA, OBJECTPOINT, 131),
+
+ /* 132 OBSOLETE. Gone in 7.16.0 */
+ /* 133 OBSOLETE. Gone in 7.16.0 */
+
+ /* zero terminated string for pass on to the FTP server when asked for
+ "account" info */
+- CINIT(FTP_ACCOUNT, OBJECTPOINT, 134),
+-
+- /* feed cookies into cookie engine */
+- CINIT(COOKIELIST, OBJECTPOINT, 135),
++ CINIT(FTP_ACCOUNT, STRINGPOINT, 134),
++
++ /* feed cookie into cookie engine */
++ CINIT(COOKIELIST, STRINGPOINT, 135),
+
+ /* ignore Content-Length */
+ CINIT(IGNORE_CONTENT_LENGTH, LONG, 136),
+
+ /* Set to non-zero to skip the IP address received in a 227 PASV FTP server
+ response. Typically used for FTP-SSL purposes but is not restricted to
+ that. libcurl will then instead use the same IP address it used for the
+ control connection. */
+@@ -1155,32 +1459,32 @@ typedef enum {
+ CINIT(CONV_FROM_UTF8_FUNCTION, FUNCTIONPOINT, 144),
+
+ /* if the connection proceeds too quickly then need to slow it down */
+ /* limit-rate: maximum number of bytes per second to send or receive */
+ CINIT(MAX_SEND_SPEED_LARGE, OFF_T, 145),
+ CINIT(MAX_RECV_SPEED_LARGE, OFF_T, 146),
+
+ /* Pointer to command string to send if USER/PASS fails. */
+- CINIT(FTP_ALTERNATIVE_TO_USER, OBJECTPOINT, 147),
++ CINIT(FTP_ALTERNATIVE_TO_USER, STRINGPOINT, 147),
+
+ /* callback function for setting socket options */
+ CINIT(SOCKOPTFUNCTION, FUNCTIONPOINT, 148),
+ CINIT(SOCKOPTDATA, OBJECTPOINT, 149),
+
+ /* set to 0 to disable session ID re-use for this transfer, default is
+ enabled (== 1) */
+ CINIT(SSL_SESSIONID_CACHE, LONG, 150),
+
+ /* allowed SSH authentication methods */
+ CINIT(SSH_AUTH_TYPES, LONG, 151),
+
+ /* Used by scp/sftp to do public/private key authentication */
+- CINIT(SSH_PUBLIC_KEYFILE, OBJECTPOINT, 152),
+- CINIT(SSH_PRIVATE_KEYFILE, OBJECTPOINT, 153),
++ CINIT(SSH_PUBLIC_KEYFILE, STRINGPOINT, 152),
++ CINIT(SSH_PRIVATE_KEYFILE, STRINGPOINT, 153),
+
+ /* Send CCC (Clear Command Channel) after authentication */
+ CINIT(FTP_SSL_CCC, LONG, 154),
+
+ /* Same as TIMEOUT and CONNECTTIMEOUT, but with ms resolution */
+ CINIT(TIMEOUT_MS, LONG, 155),
+ CINIT(CONNECTTIMEOUT_MS, LONG, 156),
+
+@@ -1194,17 +1498,17 @@ typedef enum {
+ CINIT(NEW_FILE_PERMS, LONG, 159),
+ CINIT(NEW_DIRECTORY_PERMS, LONG, 160),
+
+ /* Set the behaviour of POST when redirecting. Values must be set to one
+ of CURL_REDIR* defines below. This used to be called CURLOPT_POST301 */
+ CINIT(POSTREDIR, LONG, 161),
+
+ /* used by scp/sftp to verify the host's public key */
+- CINIT(SSH_HOST_PUBLIC_KEY_MD5, OBJECTPOINT, 162),
++ CINIT(SSH_HOST_PUBLIC_KEY_MD5, STRINGPOINT, 162),
+
+ /* Callback function for opening socket (instead of socket(2)). Optionally,
+ callback is able change the address or refuse to connect returning
+ CURL_SOCKET_BAD. The callback should have type
+ curl_opensocket_callback */
+ CINIT(OPENSOCKETFUNCTION, FUNCTIONPOINT, 163),
+ CINIT(OPENSOCKETDATA, OBJECTPOINT, 164),
+
+@@ -1214,51 +1518,50 @@ typedef enum {
+ /* set transfer mode (;type=<a|i>) when doing FTP via an HTTP proxy */
+ CINIT(PROXY_TRANSFER_MODE, LONG, 166),
+
+ /* Callback function for seeking in the input stream */
+ CINIT(SEEKFUNCTION, FUNCTIONPOINT, 167),
+ CINIT(SEEKDATA, OBJECTPOINT, 168),
+
+ /* CRL file */
+- CINIT(CRLFILE, OBJECTPOINT, 169),
++ CINIT(CRLFILE, STRINGPOINT, 169),
+
+ /* Issuer certificate */
+- CINIT(ISSUERCERT, OBJECTPOINT, 170),
++ CINIT(ISSUERCERT, STRINGPOINT, 170),
+
+ /* (IPv6) Address scope */
+ CINIT(ADDRESS_SCOPE, LONG, 171),
+
+ /* Collect certificate chain info and allow it to get retrievable with
+- CURLINFO_CERTINFO after the transfer is complete. (Unfortunately) only
+- working with OpenSSL-powered builds. */
++ CURLINFO_CERTINFO after the transfer is complete. */
+ CINIT(CERTINFO, LONG, 172),
+
+ /* "name" and "pwd" to use when fetching. */
+- CINIT(USERNAME, OBJECTPOINT, 173),
+- CINIT(PASSWORD, OBJECTPOINT, 174),
++ CINIT(USERNAME, STRINGPOINT, 173),
++ CINIT(PASSWORD, STRINGPOINT, 174),
+
+ /* "name" and "pwd" to use with Proxy when fetching. */
+- CINIT(PROXYUSERNAME, OBJECTPOINT, 175),
+- CINIT(PROXYPASSWORD, OBJECTPOINT, 176),
++ CINIT(PROXYUSERNAME, STRINGPOINT, 175),
++ CINIT(PROXYPASSWORD, STRINGPOINT, 176),
+
+ /* Comma separated list of hostnames defining no-proxy zones. These should
+ match both hostnames directly, and hostnames within a domain. For
+ example, local.com will match local.com and www.local.com, but NOT
+ notlocal.com or www.notlocal.com. For compatibility with other
+ implementations of this, .local.com will be considered to be the same as
+ local.com. A single * is the only valid wildcard, and effectively
+ disables the use of proxy. */
+- CINIT(NOPROXY, OBJECTPOINT, 177),
++ CINIT(NOPROXY, STRINGPOINT, 177),
+
+ /* block size for TFTP transfers */
+ CINIT(TFTP_BLKSIZE, LONG, 178),
+
+ /* Socks Service */
+- CINIT(SOCKS5_GSSAPI_SERVICE, OBJECTPOINT, 179),
++ CINIT(SOCKS5_GSSAPI_SERVICE, STRINGPOINT, 179), /* DEPRECATED, do not use! */
+
+ /* Socks Service */
+ CINIT(SOCKS5_GSSAPI_NEC, LONG, 180),
+
+ /* set the bitmask for the protocols that are allowed to be used for the
+ transfer, which thus helps the app which takes URLs from users or other
+ external inputs and want to restrict what protocol(s) to deal
+ with. Defaults to CURLPROTO_ALL. */
+@@ -1266,25 +1569,360 @@ typedef enum {
+
+ /* set the bitmask for the protocols that libcurl is allowed to follow to,
+ as a subset of the CURLOPT_PROTOCOLS ones. That means the protocol needs
+ to be set in both bitmasks to be allowed to get redirected to. Defaults
+ to all protocols except FILE and SCP. */
+ CINIT(REDIR_PROTOCOLS, LONG, 182),
+
+ /* set the SSH knownhost file name to use */
+- CINIT(SSH_KNOWNHOSTS, OBJECTPOINT, 183),
++ CINIT(SSH_KNOWNHOSTS, STRINGPOINT, 183),
+
+ /* set the SSH host key callback, must point to a curl_sshkeycallback
+ function */
+ CINIT(SSH_KEYFUNCTION, FUNCTIONPOINT, 184),
+
+ /* set the SSH host key callback custom pointer */
+ CINIT(SSH_KEYDATA, OBJECTPOINT, 185),
+
++ /* set the SMTP mail originator */
++ CINIT(MAIL_FROM, STRINGPOINT, 186),
++
++ /* set the list of SMTP mail receiver(s) */
++ CINIT(MAIL_RCPT, OBJECTPOINT, 187),
++
++ /* FTP: send PRET before PASV */
++ CINIT(FTP_USE_PRET, LONG, 188),
++
++ /* RTSP request method (OPTIONS, SETUP, PLAY, etc...) */
++ CINIT(RTSP_REQUEST, LONG, 189),
++
++ /* The RTSP session identifier */
++ CINIT(RTSP_SESSION_ID, STRINGPOINT, 190),
++
++ /* The RTSP stream URI */
++ CINIT(RTSP_STREAM_URI, STRINGPOINT, 191),
++
++ /* The Transport: header to use in RTSP requests */
++ CINIT(RTSP_TRANSPORT, STRINGPOINT, 192),
++
++ /* Manually initialize the client RTSP CSeq for this handle */
++ CINIT(RTSP_CLIENT_CSEQ, LONG, 193),
++
++ /* Manually initialize the server RTSP CSeq for this handle */
++ CINIT(RTSP_SERVER_CSEQ, LONG, 194),
++
++ /* The stream to pass to INTERLEAVEFUNCTION. */
++ CINIT(INTERLEAVEDATA, OBJECTPOINT, 195),
++
++ /* Let the application define a custom write method for RTP data */
++ CINIT(INTERLEAVEFUNCTION, FUNCTIONPOINT, 196),
++
++ /* Turn on wildcard matching */
++ CINIT(WILDCARDMATCH, LONG, 197),
++
++ /* Directory matching callback called before downloading of an
++ individual file (chunk) started */
++ CINIT(CHUNK_BGN_FUNCTION, FUNCTIONPOINT, 198),
++
++ /* Directory matching callback called after the file (chunk)
++ was downloaded, or skipped */
++ CINIT(CHUNK_END_FUNCTION, FUNCTIONPOINT, 199),
++
++ /* Change match (fnmatch-like) callback for wildcard matching */
++ CINIT(FNMATCH_FUNCTION, FUNCTIONPOINT, 200),
++
++ /* Let the application define custom chunk data pointer */
++ CINIT(CHUNK_DATA, OBJECTPOINT, 201),
++
++ /* FNMATCH_FUNCTION user pointer */
++ CINIT(FNMATCH_DATA, OBJECTPOINT, 202),
++
++ /* send linked-list of name:port:address sets */
++ CINIT(RESOLVE, OBJECTPOINT, 203),
++
++ /* Set a username for authenticated TLS */
++ CINIT(TLSAUTH_USERNAME, STRINGPOINT, 204),
++
++ /* Set a password for authenticated TLS */
++ CINIT(TLSAUTH_PASSWORD, STRINGPOINT, 205),
++
++ /* Set authentication type for authenticated TLS */
++ CINIT(TLSAUTH_TYPE, STRINGPOINT, 206),
++
++ /* Set to 1 to enable the "TE:" header in HTTP requests to ask for
++ compressed transfer-encoded responses. Set to 0 to disable the use of TE:
++ in outgoing requests. The current default is 0, but it might change in a
++ future libcurl release.
++
++ libcurl will ask for the compressed methods it knows of, and if that
++ isn't any, it will not ask for transfer-encoding at all even if this
++ option is set to 1.
++
++ */
++ CINIT(TRANSFER_ENCODING, LONG, 207),
++
++ /* Callback function for closing socket (instead of close(2)). The callback
++ should have type curl_closesocket_callback */
++ CINIT(CLOSESOCKETFUNCTION, FUNCTIONPOINT, 208),
++ CINIT(CLOSESOCKETDATA, OBJECTPOINT, 209),
++
++ /* allow GSSAPI credential delegation */
++ CINIT(GSSAPI_DELEGATION, LONG, 210),
++
++ /* Set the name servers to use for DNS resolution */
++ CINIT(DNS_SERVERS, STRINGPOINT, 211),
++
++ /* Time-out accept operations (currently for FTP only) after this amount
++ of milliseconds. */
++ CINIT(ACCEPTTIMEOUT_MS, LONG, 212),
++
++ /* Set TCP keepalive */
++ CINIT(TCP_KEEPALIVE, LONG, 213),
++
++ /* non-universal keepalive knobs (Linux, AIX, HP-UX, more) */
++ CINIT(TCP_KEEPIDLE, LONG, 214),
++ CINIT(TCP_KEEPINTVL, LONG, 215),
++
++ /* Enable/disable specific SSL features with a bitmask, see CURLSSLOPT_* */
++ CINIT(SSL_OPTIONS, LONG, 216),
++
++ /* Set the SMTP auth originator */
++ CINIT(MAIL_AUTH, STRINGPOINT, 217),
++
++ /* Enable/disable SASL initial response */
++ CINIT(SASL_IR, LONG, 218),
++
++ /* Function that will be called instead of the internal progress display
++ * function. This function should be defined as the curl_xferinfo_callback
++ * prototype defines. (Deprecates CURLOPT_PROGRESSFUNCTION) */
++ CINIT(XFERINFOFUNCTION, FUNCTIONPOINT, 219),
++
++ /* The XOAUTH2 bearer token */
++ CINIT(XOAUTH2_BEARER, STRINGPOINT, 220),
++
++ /* Set the interface string to use as outgoing network
++ * interface for DNS requests.
++ * Only supported by the c-ares DNS backend */
++ CINIT(DNS_INTERFACE, STRINGPOINT, 221),
++
++ /* Set the local IPv4 address to use for outgoing DNS requests.
++ * Only supported by the c-ares DNS backend */
++ CINIT(DNS_LOCAL_IP4, STRINGPOINT, 222),
++
++ /* Set the local IPv6 address to use for outgoing DNS requests.
++ * Only supported by the c-ares DNS backend */
++ CINIT(DNS_LOCAL_IP6, STRINGPOINT, 223),
++
++ /* Set authentication options directly */
++ CINIT(LOGIN_OPTIONS, STRINGPOINT, 224),
++
++ /* Enable/disable TLS NPN extension (http2 over ssl might fail without) */
++ CINIT(SSL_ENABLE_NPN, LONG, 225),
++
++ /* Enable/disable TLS ALPN extension (http2 over ssl might fail without) */
++ CINIT(SSL_ENABLE_ALPN, LONG, 226),
++
++ /* Time to wait for a response to a HTTP request containing an
++ * Expect: 100-continue header before sending the data anyway. */
++ CINIT(EXPECT_100_TIMEOUT_MS, LONG, 227),
++
++ /* This points to a linked list of headers used for proxy requests only,
++ struct curl_slist kind */
++ CINIT(PROXYHEADER, OBJECTPOINT, 228),
++
++ /* Pass in a bitmask of "header options" */
++ CINIT(HEADEROPT, LONG, 229),
++
++ /* The public key in DER form used to validate the peer public key
++ this option is used only if SSL_VERIFYPEER is true */
++ CINIT(PINNEDPUBLICKEY, STRINGPOINT, 230),
++
++ /* Path to Unix domain socket */
++ CINIT(UNIX_SOCKET_PATH, STRINGPOINT, 231),
++
++ /* Set if we should verify the certificate status. */
++ CINIT(SSL_VERIFYSTATUS, LONG, 232),
++
++ /* Set if we should enable TLS false start. */
++ CINIT(SSL_FALSESTART, LONG, 233),
++
++ /* Do not squash dot-dot sequences */
++ CINIT(PATH_AS_IS, LONG, 234),
++
++ /* Proxy Service Name */
++ CINIT(PROXY_SERVICE_NAME, STRINGPOINT, 235),
++
++ /* Service Name */
++ CINIT(SERVICE_NAME, STRINGPOINT, 236),
++
++ /* Wait/don't wait for pipe/mutex to clarify */
++ CINIT(PIPEWAIT, LONG, 237),
++
++ /* Set the protocol used when curl is given a URL without a protocol */
++ CINIT(DEFAULT_PROTOCOL, STRINGPOINT, 238),
++
++ /* Set stream weight, 1 - 256 (default is 16) */
++ CINIT(STREAM_WEIGHT, LONG, 239),
++
++ /* Set stream dependency on another CURL handle */
++ CINIT(STREAM_DEPENDS, OBJECTPOINT, 240),
++
++ /* Set E-xclusive stream dependency on another CURL handle */
++ CINIT(STREAM_DEPENDS_E, OBJECTPOINT, 241),
++
++ /* Do not send any tftp option requests to the server */
++ CINIT(TFTP_NO_OPTIONS, LONG, 242),
++
++ /* Linked-list of host:port:connect-to-host:connect-to-port,
++ overrides the URL's host:port (only for the network layer) */
++ CINIT(CONNECT_TO, OBJECTPOINT, 243),
++
++ /* Set TCP Fast Open */
++ CINIT(TCP_FASTOPEN, LONG, 244),
++
++ /* Continue to send data if the server responds early with an
++ * HTTP status code >= 300 */
++ CINIT(KEEP_SENDING_ON_ERROR, LONG, 245),
++
++ /* The CApath or CAfile used to validate the proxy certificate
++ this option is used only if PROXY_SSL_VERIFYPEER is true */
++ CINIT(PROXY_CAINFO, STRINGPOINT, 246),
++
++ /* The CApath directory used to validate the proxy certificate
++ this option is used only if PROXY_SSL_VERIFYPEER is true */
++ CINIT(PROXY_CAPATH, STRINGPOINT, 247),
++
++ /* Set if we should verify the proxy in ssl handshake,
++ set 1 to verify. */
++ CINIT(PROXY_SSL_VERIFYPEER, LONG, 248),
++
++ /* Set if we should verify the Common name from the proxy certificate in ssl
++ * handshake, set 1 to check existence, 2 to ensure that it matches
++ * the provided hostname. */
++ CINIT(PROXY_SSL_VERIFYHOST, LONG, 249),
++
++ /* What version to specifically try to use for proxy.
++ See CURL_SSLVERSION defines below. */
++ CINIT(PROXY_SSLVERSION, LONG, 250),
++
++ /* Set a username for authenticated TLS for proxy */
++ CINIT(PROXY_TLSAUTH_USERNAME, STRINGPOINT, 251),
++
++ /* Set a password for authenticated TLS for proxy */
++ CINIT(PROXY_TLSAUTH_PASSWORD, STRINGPOINT, 252),
++
++ /* Set authentication type for authenticated TLS for proxy */
++ CINIT(PROXY_TLSAUTH_TYPE, STRINGPOINT, 253),
++
++ /* name of the file keeping your private SSL-certificate for proxy */
++ CINIT(PROXY_SSLCERT, STRINGPOINT, 254),
++
++ /* type of the file keeping your SSL-certificate ("DER", "PEM", "ENG") for
++ proxy */
++ CINIT(PROXY_SSLCERTTYPE, STRINGPOINT, 255),
++
++ /* name of the file keeping your private SSL-key for proxy */
++ CINIT(PROXY_SSLKEY, STRINGPOINT, 256),
++
++ /* type of the file keeping your private SSL-key ("DER", "PEM", "ENG") for
++ proxy */
++ CINIT(PROXY_SSLKEYTYPE, STRINGPOINT, 257),
++
++ /* password for the SSL private key for proxy */
++ CINIT(PROXY_KEYPASSWD, STRINGPOINT, 258),
++
++ /* Specify which SSL ciphers to use for proxy */
++ CINIT(PROXY_SSL_CIPHER_LIST, STRINGPOINT, 259),
++
++ /* CRL file for proxy */
++ CINIT(PROXY_CRLFILE, STRINGPOINT, 260),
++
++ /* Enable/disable specific SSL features with a bitmask for proxy, see
++ CURLSSLOPT_* */
++ CINIT(PROXY_SSL_OPTIONS, LONG, 261),
++
++ /* Name of pre proxy to use. */
++ CINIT(PRE_PROXY, STRINGPOINT, 262),
++
++ /* The public key in DER form used to validate the proxy public key
++ this option is used only if PROXY_SSL_VERIFYPEER is true */
++ CINIT(PROXY_PINNEDPUBLICKEY, STRINGPOINT, 263),
++
++ /* Path to an abstract Unix domain socket */
++ CINIT(ABSTRACT_UNIX_SOCKET, STRINGPOINT, 264),
++
++ /* Suppress proxy CONNECT response headers from user callbacks */
++ CINIT(SUPPRESS_CONNECT_HEADERS, LONG, 265),
++
++ /* The request target, instead of extracted from the URL */
++ CINIT(REQUEST_TARGET, STRINGPOINT, 266),
++
++ /* bitmask of allowed auth methods for connections to SOCKS5 proxies */
++ CINIT(SOCKS5_AUTH, LONG, 267),
++
++ /* Enable/disable SSH compression */
++ CINIT(SSH_COMPRESSION, LONG, 268),
++
++ /* Post MIME data. */
++ CINIT(MIMEPOST, OBJECTPOINT, 269),
++
++ /* Time to use with the CURLOPT_TIMECONDITION. Specified in number of
++ seconds since 1 Jan 1970. */
++ CINIT(TIMEVALUE_LARGE, OFF_T, 270),
++
++ /* Head start in milliseconds to give happy eyeballs. */
++ CINIT(HAPPY_EYEBALLS_TIMEOUT_MS, LONG, 271),
++
++ /* Function that will be called before a resolver request is made */
++ CINIT(RESOLVER_START_FUNCTION, FUNCTIONPOINT, 272),
++
++ /* User data to pass to the resolver start callback. */
++ CINIT(RESOLVER_START_DATA, OBJECTPOINT, 273),
++
++ /* send HAProxy PROXY protocol header? */
++ CINIT(HAPROXYPROTOCOL, LONG, 274),
++
++ /* shuffle addresses before use when DNS returns multiple */
++ CINIT(DNS_SHUFFLE_ADDRESSES, LONG, 275),
++
++ /* Specify which TLS 1.3 ciphers suites to use */
++ CINIT(TLS13_CIPHERS, STRINGPOINT, 276),
++ CINIT(PROXY_TLS13_CIPHERS, STRINGPOINT, 277),
++
++ /* Disallow specifying username/login in URL. */
++ CINIT(DISALLOW_USERNAME_IN_URL, LONG, 278),
++
++ /* DNS-over-HTTPS URL */
++ CINIT(DOH_URL, STRINGPOINT, 279),
++
++ /* Preferred buffer size to use for uploads */
++ CINIT(UPLOAD_BUFFERSIZE, LONG, 280),
++
++ /* Time in ms between connection upkeep calls for long-lived connections. */
++ CINIT(UPKEEP_INTERVAL_MS, LONG, 281),
++
++ /* Specify URL using CURL URL API. */
++ CINIT(CURLU, OBJECTPOINT, 282),
++
++ /* add trailing data just after no more data is available */
++ CINIT(TRAILERFUNCTION, FUNCTIONPOINT, 283),
++
++ /* pointer to be passed to HTTP_TRAILER_FUNCTION */
++ CINIT(TRAILERDATA, OBJECTPOINT, 284),
++
++ /* set this to 1L to allow HTTP/0.9 responses or 0L to disallow */
++ CINIT(HTTP09_ALLOWED, LONG, 285),
++
++ /* alt-svc control bitmask */
++ CINIT(ALTSVC_CTRL, LONG, 286),
++
++ /* alt-svc cache file name to possibly read from/write to */
++ CINIT(ALTSVC, STRINGPOINT, 287),
++
+ CURLOPT_LASTENTRY /* the last unused */
+ } CURLoption;
+
+ #ifndef CURL_NO_OLDIES /* define this to test if your app builds with all
+ the obsolete stuff removed! */
+
+ /* Backwards compatibility with older names */
+ /* These are scheduled to disappear by 2011 */
+@@ -1311,81 +1949,260 @@ typedef enum {
+ #endif
+
+
+ /* Below here follows defines for the CURLOPT_IPRESOLVE option. If a host
+ name resolves addresses using more than one IP protocol version, this
+ option might be handy to force libcurl to use a specific IP version. */
+ #define CURL_IPRESOLVE_WHATEVER 0 /* default, resolves addresses to all IP
+ versions that your system allows */
+-#define CURL_IPRESOLVE_V4 1 /* resolve to ipv4 addresses */
+-#define CURL_IPRESOLVE_V6 2 /* resolve to ipv6 addresses */
++#define CURL_IPRESOLVE_V4 1 /* resolve to IPv4 addresses */
++#define CURL_IPRESOLVE_V6 2 /* resolve to IPv6 addresses */
+
+ /* three convenient "aliases" that follow the name scheme better */
+-#define CURLOPT_WRITEDATA CURLOPT_FILE
+-#define CURLOPT_READDATA CURLOPT_INFILE
+-#define CURLOPT_HEADERDATA CURLOPT_WRITEHEADER
++#define CURLOPT_RTSPHEADER CURLOPT_HTTPHEADER
+
+ /* These enums are for use with the CURLOPT_HTTP_VERSION option. */
+ enum {
+ CURL_HTTP_VERSION_NONE, /* setting this means we don't care, and that we'd
+ like the library to choose the best possible
+ for us! */
+ CURL_HTTP_VERSION_1_0, /* please use HTTP 1.0 in the request */
+ CURL_HTTP_VERSION_1_1, /* please use HTTP 1.1 in the request */
++ CURL_HTTP_VERSION_2_0, /* please use HTTP 2 in the request */
++ CURL_HTTP_VERSION_2TLS, /* use version 2 for HTTPS, version 1.1 for HTTP */
++ CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE, /* please use HTTP 2 without HTTP/1.1
++ Upgrade */
+
+ CURL_HTTP_VERSION_LAST /* *ILLEGAL* http version */
+ };
+
++/* Convenience definition simple because the name of the version is HTTP/2 and
++ not 2.0. The 2_0 version of the enum name was set while the version was
++ still planned to be 2.0 and we stick to it for compatibility. */
++#define CURL_HTTP_VERSION_2 CURL_HTTP_VERSION_2_0
++
++/*
++ * Public API enums for RTSP requests
++ */
++enum {
++ CURL_RTSPREQ_NONE, /* first in list */
++ CURL_RTSPREQ_OPTIONS,
++ CURL_RTSPREQ_DESCRIBE,
++ CURL_RTSPREQ_ANNOUNCE,
++ CURL_RTSPREQ_SETUP,
++ CURL_RTSPREQ_PLAY,
++ CURL_RTSPREQ_PAUSE,
++ CURL_RTSPREQ_TEARDOWN,
++ CURL_RTSPREQ_GET_PARAMETER,
++ CURL_RTSPREQ_SET_PARAMETER,
++ CURL_RTSPREQ_RECORD,
++ CURL_RTSPREQ_RECEIVE,
++ CURL_RTSPREQ_LAST /* last in list */
++};
++
+ /* These enums are for use with the CURLOPT_NETRC option. */
+ enum CURL_NETRC_OPTION {
+ CURL_NETRC_IGNORED, /* The .netrc will never be read.
+ * This is the default. */
+ CURL_NETRC_OPTIONAL, /* A user:password in the URL will be preferred
+ * to one in the .netrc. */
+ CURL_NETRC_REQUIRED, /* A user:password in the URL will be ignored.
+ * Unless one is set programmatically, the .netrc
+ * will be queried. */
+ CURL_NETRC_LAST
+ };
+
+ enum {
+ CURL_SSLVERSION_DEFAULT,
+- CURL_SSLVERSION_TLSv1,
++ CURL_SSLVERSION_TLSv1, /* TLS 1.x */
+ CURL_SSLVERSION_SSLv2,
+ CURL_SSLVERSION_SSLv3,
++ CURL_SSLVERSION_TLSv1_0,
++ CURL_SSLVERSION_TLSv1_1,
++ CURL_SSLVERSION_TLSv1_2,
++ CURL_SSLVERSION_TLSv1_3,
+
+ CURL_SSLVERSION_LAST /* never use, keep last */
+ };
+
++enum {
++ CURL_SSLVERSION_MAX_NONE = 0,
++ CURL_SSLVERSION_MAX_DEFAULT = (CURL_SSLVERSION_TLSv1 << 16),
++ CURL_SSLVERSION_MAX_TLSv1_0 = (CURL_SSLVERSION_TLSv1_0 << 16),
++ CURL_SSLVERSION_MAX_TLSv1_1 = (CURL_SSLVERSION_TLSv1_1 << 16),
++ CURL_SSLVERSION_MAX_TLSv1_2 = (CURL_SSLVERSION_TLSv1_2 << 16),
++ CURL_SSLVERSION_MAX_TLSv1_3 = (CURL_SSLVERSION_TLSv1_3 << 16),
++
++ /* never use, keep last */
++ CURL_SSLVERSION_MAX_LAST = (CURL_SSLVERSION_LAST << 16)
++};
++
++enum CURL_TLSAUTH {
++ CURL_TLSAUTH_NONE,
++ CURL_TLSAUTH_SRP,
++ CURL_TLSAUTH_LAST /* never use, keep last */
++};
++
+ /* symbols to use with CURLOPT_POSTREDIR.
+- CURL_REDIR_POST_301 and CURL_REDIR_POST_302 can be bitwise ORed so that
+- CURL_REDIR_POST_301 | CURL_REDIR_POST_302 == CURL_REDIR_POST_ALL */
++ CURL_REDIR_POST_301, CURL_REDIR_POST_302 and CURL_REDIR_POST_303
++ can be bitwise ORed so that CURL_REDIR_POST_301 | CURL_REDIR_POST_302
++ | CURL_REDIR_POST_303 == CURL_REDIR_POST_ALL */
+
+ #define CURL_REDIR_GET_ALL 0
+ #define CURL_REDIR_POST_301 1
+ #define CURL_REDIR_POST_302 2
+-#define CURL_REDIR_POST_ALL (CURL_REDIR_POST_301|CURL_REDIR_POST_302)
++#define CURL_REDIR_POST_303 4
++#define CURL_REDIR_POST_ALL \
++ (CURL_REDIR_POST_301|CURL_REDIR_POST_302|CURL_REDIR_POST_303)
+
+ typedef enum {
+ CURL_TIMECOND_NONE,
+
+ CURL_TIMECOND_IFMODSINCE,
+ CURL_TIMECOND_IFUNMODSINCE,
+ CURL_TIMECOND_LASTMOD,
+
+ CURL_TIMECOND_LAST
+ } curl_TimeCond;
+
++/* Special size_t value signaling a zero-terminated string. */
++#define CURL_ZERO_TERMINATED ((size_t) -1)
+
+ /* curl_strequal() and curl_strnequal() are subject for removal in a future
+- libcurl, see lib/README.curlx for details */
+-CURL_EXTERN int (curl_strequal)(const char *s1, const char *s2);
+-CURL_EXTERN int (curl_strnequal)(const char *s1, const char *s2, size_t n);
+-
++ release */
++CURL_EXTERN int curl_strequal(const char *s1, const char *s2);
++CURL_EXTERN int curl_strnequal(const char *s1, const char *s2, size_t n);
++
++/* Mime/form handling support. */
++typedef struct curl_mime_s curl_mime; /* Mime context. */
++typedef struct curl_mimepart_s curl_mimepart; /* Mime part context. */
++
++/*
++ * NAME curl_mime_init()
++ *
++ * DESCRIPTION
++ *
++ * Create a mime context and return its handle. The easy parameter is the
++ * target handle.
++ */
++CURL_EXTERN curl_mime *curl_mime_init(CURL *easy);
++
++/*
++ * NAME curl_mime_free()
++ *
++ * DESCRIPTION
++ *
++ * release a mime handle and its substructures.
++ */
++CURL_EXTERN void curl_mime_free(curl_mime *mime);
++
++/*
++ * NAME curl_mime_addpart()
++ *
++ * DESCRIPTION
++ *
++ * Append a new empty part to the given mime context and return a handle to
++ * the created part.
++ */
++CURL_EXTERN curl_mimepart *curl_mime_addpart(curl_mime *mime);
++
++/*
++ * NAME curl_mime_name()
++ *
++ * DESCRIPTION
++ *
++ * Set mime/form part name.
++ */
++CURL_EXTERN CURLcode curl_mime_name(curl_mimepart *part, const char *name);
++
++/*
++ * NAME curl_mime_filename()
++ *
++ * DESCRIPTION
++ *
++ * Set mime part remote file name.
++ */
++CURL_EXTERN CURLcode curl_mime_filename(curl_mimepart *part,
++ const char *filename);
++
++/*
++ * NAME curl_mime_type()
++ *
++ * DESCRIPTION
++ *
++ * Set mime part type.
++ */
++CURL_EXTERN CURLcode curl_mime_type(curl_mimepart *part, const char *mimetype);
++
++/*
++ * NAME curl_mime_encoder()
++ *
++ * DESCRIPTION
++ *
++ * Set mime data transfer encoder.
++ */
++CURL_EXTERN CURLcode curl_mime_encoder(curl_mimepart *part,
++ const char *encoding);
++
++/*
++ * NAME curl_mime_data()
++ *
++ * DESCRIPTION
++ *
++ * Set mime part data source from memory data,
++ */
++CURL_EXTERN CURLcode curl_mime_data(curl_mimepart *part,
++ const char *data, size_t datasize);
++
++/*
++ * NAME curl_mime_filedata()
++ *
++ * DESCRIPTION
++ *
++ * Set mime part data source from named file.
++ */
++CURL_EXTERN CURLcode curl_mime_filedata(curl_mimepart *part,
++ const char *filename);
++
++/*
++ * NAME curl_mime_data_cb()
++ *
++ * DESCRIPTION
++ *
++ * Set mime part data source from callback function.
++ */
++CURL_EXTERN CURLcode curl_mime_data_cb(curl_mimepart *part,
++ curl_off_t datasize,
++ curl_read_callback readfunc,
++ curl_seek_callback seekfunc,
++ curl_free_callback freefunc,
++ void *arg);
++
++/*
++ * NAME curl_mime_subparts()
++ *
++ * DESCRIPTION
++ *
++ * Set mime part data source from subparts.
++ */
++CURL_EXTERN CURLcode curl_mime_subparts(curl_mimepart *part,
++ curl_mime *subparts);
++/*
++ * NAME curl_mime_headers()
++ *
++ * DESCRIPTION
++ *
++ * Set mime part headers.
++ */
++CURL_EXTERN CURLcode curl_mime_headers(curl_mimepart *part,
++ struct curl_slist *headers,
++ int take_ownership);
++
++/* Old form API. */
+ /* name is uppercase CURLFORM_<name> */
+ #ifdef CFINIT
+ #undef CFINIT
+ #endif
+
+ #ifdef CURL_ISOCPP
+ #define CFINIT(name) CURLFORM_ ## name
+ #else
+@@ -1414,16 +2231,17 @@ typedef enum {
+
+ CFINIT(CONTENTTYPE),
+ CFINIT(CONTENTHEADER),
+ CFINIT(FILENAME),
+ CFINIT(END),
+ CFINIT(OBSOLETE2),
+
+ CFINIT(STREAM),
++ CFINIT(CONTENTLEN), /* added in 7.46.0, provide a curl_off_t length */
+
+ CURLFORM_LASTENTRY /* the last unused */
+ } CURLformoption;
+
+ #undef CFINIT /* done */
+
+ /* structure to be used as parameter for CURLFORM_ARRAY */
+ struct curl_forms {
+@@ -1477,17 +2295,18 @@ CURL_EXTERN CURLFORMcode curl_formadd(st
+ /*
+ * callback function for curl_formget()
+ * The void *arg pointer will be the one passed as second argument to
+ * curl_formget().
+ * The character buffer passed to it must not be freed.
+ * Should return the buffer length passed to it as the argument "len" on
+ * success.
+ */
+-typedef size_t (*curl_formget_callback)(void *arg, const char *buf, size_t len);
++typedef size_t (*curl_formget_callback)(void *arg, const char *buf,
++ size_t len);
+
+ /*
+ * NAME curl_formget()
+ *
+ * DESCRIPTION
+ *
+ * Serialize a curl_httppost struct built with curl_formadd().
+ * Accepts a void pointer as second argument which will be passed to
+@@ -1616,16 +2435,57 @@ CURL_EXTERN void curl_global_cleanup(voi
+
+ /* linked-list structure for the CURLOPT_QUOTE option (and other) */
+ struct curl_slist {
+ char *data;
+ struct curl_slist *next;
+ };
+
+ /*
++ * NAME curl_global_sslset()
++ *
++ * DESCRIPTION
++ *
++ * When built with multiple SSL backends, curl_global_sslset() allows to
++ * choose one. This function can only be called once, and it must be called
++ * *before* curl_global_init().
++ *
++ * The backend can be identified by the id (e.g. CURLSSLBACKEND_OPENSSL). The
++ * backend can also be specified via the name parameter (passing -1 as id).
++ * If both id and name are specified, the name will be ignored. If neither id
++ * nor name are specified, the function will fail with
++ * CURLSSLSET_UNKNOWN_BACKEND and set the "avail" pointer to the
++ * NULL-terminated list of available backends.
++ *
++ * Upon success, the function returns CURLSSLSET_OK.
++ *
++ * If the specified SSL backend is not available, the function returns
++ * CURLSSLSET_UNKNOWN_BACKEND and sets the "avail" pointer to a NULL-terminated
++ * list of available SSL backends.
++ *
++ * The SSL backend can be set only once. If it has already been set, a
++ * subsequent attempt to change it will result in a CURLSSLSET_TOO_LATE.
++ */
++
++typedef struct {
++ curl_sslbackend id;
++ const char *name;
++} curl_ssl_backend;
++
++typedef enum {
++ CURLSSLSET_OK = 0,
++ CURLSSLSET_UNKNOWN_BACKEND,
++ CURLSSLSET_TOO_LATE,
++ CURLSSLSET_NO_BACKENDS /* libcurl was built without any SSL support */
++} CURLsslset;
++
++CURL_EXTERN CURLsslset curl_global_sslset(curl_sslbackend id, const char *name,
++ const curl_ssl_backend ***avail);
++
++/*
+ * NAME curl_slist_append()
+ *
+ * DESCRIPTION
+ *
+ * Appends a string to a linked list. If no list exists, it will be created
+ * first. Returns the new list, after appending.
+ */
+ CURL_EXTERN struct curl_slist *curl_slist_append(struct curl_slist *,
+@@ -1655,41 +2515,59 @@ CURL_EXTERN time_t curl_getdate(const ch
+ for with CURLOPT_CERTINFO / CURLINFO_CERTINFO */
+ struct curl_certinfo {
+ int num_of_certs; /* number of certificates with information */
+ struct curl_slist **certinfo; /* for each index in this array, there's a
+ linked list with textual information in the
+ format "name: value" */
+ };
+
++/* Information about the SSL library used and the respective internal SSL
++ handle, which can be used to obtain further information regarding the
++ connection. Asked for with CURLINFO_TLS_SSL_PTR or CURLINFO_TLS_SESSION. */
++struct curl_tlssessioninfo {
++ curl_sslbackend backend;
++ void *internals;
++};
++
+ #define CURLINFO_STRING 0x100000
+ #define CURLINFO_LONG 0x200000
+ #define CURLINFO_DOUBLE 0x300000
+ #define CURLINFO_SLIST 0x400000
++#define CURLINFO_PTR 0x400000 /* same as SLIST */
++#define CURLINFO_SOCKET 0x500000
++#define CURLINFO_OFF_T 0x600000
+ #define CURLINFO_MASK 0x0fffff
+ #define CURLINFO_TYPEMASK 0xf00000
+
+ typedef enum {
+ CURLINFO_NONE, /* first, never use this */
+ CURLINFO_EFFECTIVE_URL = CURLINFO_STRING + 1,
+ CURLINFO_RESPONSE_CODE = CURLINFO_LONG + 2,
+ CURLINFO_TOTAL_TIME = CURLINFO_DOUBLE + 3,
+ CURLINFO_NAMELOOKUP_TIME = CURLINFO_DOUBLE + 4,
+ CURLINFO_CONNECT_TIME = CURLINFO_DOUBLE + 5,
+ CURLINFO_PRETRANSFER_TIME = CURLINFO_DOUBLE + 6,
+ CURLINFO_SIZE_UPLOAD = CURLINFO_DOUBLE + 7,
++ CURLINFO_SIZE_UPLOAD_T = CURLINFO_OFF_T + 7,
+ CURLINFO_SIZE_DOWNLOAD = CURLINFO_DOUBLE + 8,
++ CURLINFO_SIZE_DOWNLOAD_T = CURLINFO_OFF_T + 8,
+ CURLINFO_SPEED_DOWNLOAD = CURLINFO_DOUBLE + 9,
++ CURLINFO_SPEED_DOWNLOAD_T = CURLINFO_OFF_T + 9,
+ CURLINFO_SPEED_UPLOAD = CURLINFO_DOUBLE + 10,
++ CURLINFO_SPEED_UPLOAD_T = CURLINFO_OFF_T + 10,
+ CURLINFO_HEADER_SIZE = CURLINFO_LONG + 11,
+ CURLINFO_REQUEST_SIZE = CURLINFO_LONG + 12,
+ CURLINFO_SSL_VERIFYRESULT = CURLINFO_LONG + 13,
+ CURLINFO_FILETIME = CURLINFO_LONG + 14,
++ CURLINFO_FILETIME_T = CURLINFO_OFF_T + 14,
+ CURLINFO_CONTENT_LENGTH_DOWNLOAD = CURLINFO_DOUBLE + 15,
++ CURLINFO_CONTENT_LENGTH_DOWNLOAD_T = CURLINFO_OFF_T + 15,
+ CURLINFO_CONTENT_LENGTH_UPLOAD = CURLINFO_DOUBLE + 16,
++ CURLINFO_CONTENT_LENGTH_UPLOAD_T = CURLINFO_OFF_T + 16,
+ CURLINFO_STARTTRANSFER_TIME = CURLINFO_DOUBLE + 17,
+ CURLINFO_CONTENT_TYPE = CURLINFO_STRING + 18,
+ CURLINFO_REDIRECT_TIME = CURLINFO_DOUBLE + 19,
+ CURLINFO_REDIRECT_COUNT = CURLINFO_LONG + 20,
+ CURLINFO_PRIVATE = CURLINFO_STRING + 21,
+ CURLINFO_HTTP_CONNECTCODE = CURLINFO_LONG + 22,
+ CURLINFO_HTTPAUTH_AVAIL = CURLINFO_LONG + 23,
+ CURLINFO_PROXYAUTH_AVAIL = CURLINFO_LONG + 24,
+@@ -1697,21 +2575,45 @@ typedef enum {
+ CURLINFO_NUM_CONNECTS = CURLINFO_LONG + 26,
+ CURLINFO_SSL_ENGINES = CURLINFO_SLIST + 27,
+ CURLINFO_COOKIELIST = CURLINFO_SLIST + 28,
+ CURLINFO_LASTSOCKET = CURLINFO_LONG + 29,
+ CURLINFO_FTP_ENTRY_PATH = CURLINFO_STRING + 30,
+ CURLINFO_REDIRECT_URL = CURLINFO_STRING + 31,
+ CURLINFO_PRIMARY_IP = CURLINFO_STRING + 32,
+ CURLINFO_APPCONNECT_TIME = CURLINFO_DOUBLE + 33,
+- CURLINFO_CERTINFO = CURLINFO_SLIST + 34,
++ CURLINFO_CERTINFO = CURLINFO_PTR + 34,
+ CURLINFO_CONDITION_UNMET = CURLINFO_LONG + 35,
++ CURLINFO_RTSP_SESSION_ID = CURLINFO_STRING + 36,
++ CURLINFO_RTSP_CLIENT_CSEQ = CURLINFO_LONG + 37,
++ CURLINFO_RTSP_SERVER_CSEQ = CURLINFO_LONG + 38,
++ CURLINFO_RTSP_CSEQ_RECV = CURLINFO_LONG + 39,
++ CURLINFO_PRIMARY_PORT = CURLINFO_LONG + 40,
++ CURLINFO_LOCAL_IP = CURLINFO_STRING + 41,
++ CURLINFO_LOCAL_PORT = CURLINFO_LONG + 42,
++ CURLINFO_TLS_SESSION = CURLINFO_PTR + 43,
++ CURLINFO_ACTIVESOCKET = CURLINFO_SOCKET + 44,
++ CURLINFO_TLS_SSL_PTR = CURLINFO_PTR + 45,
++ CURLINFO_HTTP_VERSION = CURLINFO_LONG + 46,
++ CURLINFO_PROXY_SSL_VERIFYRESULT = CURLINFO_LONG + 47,
++ CURLINFO_PROTOCOL = CURLINFO_LONG + 48,
++ CURLINFO_SCHEME = CURLINFO_STRING + 49,
+ /* Fill in new entries below here! */
+
+- CURLINFO_LASTONE = 35
++ /* Preferably these would be defined conditionally based on the
++ sizeof curl_off_t being 64-bits */
++ CURLINFO_TOTAL_TIME_T = CURLINFO_OFF_T + 50,
++ CURLINFO_NAMELOOKUP_TIME_T = CURLINFO_OFF_T + 51,
++ CURLINFO_CONNECT_TIME_T = CURLINFO_OFF_T + 52,
++ CURLINFO_PRETRANSFER_TIME_T = CURLINFO_OFF_T + 53,
++ CURLINFO_STARTTRANSFER_TIME_T = CURLINFO_OFF_T + 54,
++ CURLINFO_REDIRECT_TIME_T = CURLINFO_OFF_T + 55,
++ CURLINFO_APPCONNECT_TIME_T = CURLINFO_OFF_T + 56,
++
++ CURLINFO_LASTONE = 56
+ } CURLINFO;
+
+ /* CURLINFO_RESPONSE_CODE is the new name for the option previously known as
+ CURLINFO_HTTP_CODE */
+ #define CURLINFO_HTTP_CODE CURLINFO_RESPONSE_CODE
+
+ typedef enum {
+ CURLCLOSEPOLICY_NONE, /* first, never use this */
+@@ -1720,21 +2622,22 @@ typedef enum {
+ CURLCLOSEPOLICY_LEAST_RECENTLY_USED,
+ CURLCLOSEPOLICY_LEAST_TRAFFIC,
+ CURLCLOSEPOLICY_SLOWEST,
+ CURLCLOSEPOLICY_CALLBACK,
+
+ CURLCLOSEPOLICY_LAST /* last, never use this */
+ } curl_closepolicy;
+
+-#define CURL_GLOBAL_SSL (1<<0)
++#define CURL_GLOBAL_SSL (1<<0) /* no purpose since since 7.57.0 */
+ #define CURL_GLOBAL_WIN32 (1<<1)
+ #define CURL_GLOBAL_ALL (CURL_GLOBAL_SSL|CURL_GLOBAL_WIN32)
+ #define CURL_GLOBAL_NOTHING 0
+ #define CURL_GLOBAL_DEFAULT CURL_GLOBAL_ALL
++#define CURL_GLOBAL_ACK_EINTR (1<<2)
+
+
+ /*****************************************************************************
+ * Setup defines, protos etc for the sharing stuff.
+ */
+
+ /* Different data locks for a single share */
+ typedef enum {
+@@ -1743,16 +2646,17 @@ typedef enum {
+ * the locking is just made to change the internal state of the share
+ * itself.
+ */
+ CURL_LOCK_DATA_SHARE,
+ CURL_LOCK_DATA_COOKIE,
+ CURL_LOCK_DATA_DNS,
+ CURL_LOCK_DATA_SSL_SESSION,
+ CURL_LOCK_DATA_CONNECT,
++ CURL_LOCK_DATA_PSL,
+ CURL_LOCK_DATA_LAST
+ } curl_lock_data;
+
+ /* Different lock access types */
+ typedef enum {
+ CURL_LOCK_ACCESS_NONE = 0, /* unspecified action */
+ CURL_LOCK_ACCESS_SHARED = 1, /* for read perhaps */
+ CURL_LOCK_ACCESS_SINGLE = 2, /* for write perhaps */
+@@ -1762,25 +2666,25 @@ typedef enum {
+ typedef void (*curl_lock_function)(CURL *handle,
+ curl_lock_data data,
+ curl_lock_access locktype,
+ void *userptr);
+ typedef void (*curl_unlock_function)(CURL *handle,
+ curl_lock_data data,
+ void *userptr);
+
+-typedef void CURLSH;
+
+ typedef enum {
+ CURLSHE_OK, /* all is fine */
+ CURLSHE_BAD_OPTION, /* 1 */
+ CURLSHE_IN_USE, /* 2 */
+ CURLSHE_INVALID, /* 3 */
+- CURLSHE_NOMEM, /* out of memory */
+- CURLSHE_LAST /* never use */
++ CURLSHE_NOMEM, /* 4 out of memory */
++ CURLSHE_NOT_BUILT_IN, /* 5 feature not present in lib */
++ CURLSHE_LAST /* never use */
+ } CURLSHcode;
+
+ typedef enum {
+ CURLSHOPT_NONE, /* don't use */
+ CURLSHOPT_SHARE, /* specify a data type to share */
+ CURLSHOPT_UNSHARE, /* specify which data type to stop sharing */
+ CURLSHOPT_LOCKFUNC, /* pass in a 'curl_lock_function' pointer */
+ CURLSHOPT_UNLOCKFUNC, /* pass in a 'curl_unlock_function' pointer */
+@@ -1797,25 +2701,26 @@ CURL_EXTERN CURLSHcode curl_share_cleanu
+ * Structures for querying information about the curl library at runtime.
+ */
+
+ typedef enum {
+ CURLVERSION_FIRST,
+ CURLVERSION_SECOND,
+ CURLVERSION_THIRD,
+ CURLVERSION_FOURTH,
++ CURLVERSION_FIFTH,
+ CURLVERSION_LAST /* never actually use this */
+ } CURLversion;
+
+ /* The 'CURLVERSION_NOW' is the symbolic name meant to be used by
+ basically all programs ever that want to get version information. It is
+ meant to be a built-in version number for what kind of struct the caller
+ expects. If the struct ever changes, we redefine the NOW to another enum
+ from above. */
+-#define CURLVERSION_NOW CURLVERSION_FOURTH
++#define CURLVERSION_NOW CURLVERSION_FIFTH
+
+ typedef struct {
+ CURLversion age; /* age of the returned struct */
+ const char *version; /* LIBCURL_VERSION */
+ unsigned int version_num; /* LIBCURL_VERSION_NUM */
+ const char *host; /* OS/host/cpu/machine when configured */
+ int features; /* bitmask, see defines below */
+ const char *ssl_version; /* human readable string */
+@@ -1833,34 +2738,56 @@ typedef struct {
+
+ /* These field were added in CURLVERSION_FOURTH */
+
+ /* Same as '_libiconv_version' if built with HAVE_ICONV */
+ int iconv_ver_num;
+
+ const char *libssh_version; /* human readable string */
+
++ /* These fields were added in CURLVERSION_FIFTH */
++
++ unsigned int brotli_ver_num; /* Numeric Brotli version
++ (MAJOR << 24) | (MINOR << 12) | PATCH */
++ const char *brotli_version; /* human readable string. */
++
+ } curl_version_info_data;
+
+-#define CURL_VERSION_IPV6 (1<<0) /* IPv6-enabled */
+-#define CURL_VERSION_KERBEROS4 (1<<1) /* kerberos auth is supported */
+-#define CURL_VERSION_SSL (1<<2) /* SSL options are present */
+-#define CURL_VERSION_LIBZ (1<<3) /* libz features are present */
+-#define CURL_VERSION_NTLM (1<<4) /* NTLM auth is supported */
+-#define CURL_VERSION_GSSNEGOTIATE (1<<5) /* Negotiate auth support */
+-#define CURL_VERSION_DEBUG (1<<6) /* built with debug capabilities */
+-#define CURL_VERSION_ASYNCHDNS (1<<7) /* asynchronous dns resolves */
+-#define CURL_VERSION_SPNEGO (1<<8) /* SPNEGO auth */
+-#define CURL_VERSION_LARGEFILE (1<<9) /* supports files bigger than 2GB */
+-#define CURL_VERSION_IDN (1<<10) /* International Domain Names support */
+-#define CURL_VERSION_SSPI (1<<11) /* SSPI is supported */
+-#define CURL_VERSION_CONV (1<<12) /* character conversions supported */
+-#define CURL_VERSION_CURLDEBUG (1<<13) /* debug memory tracking supported */
+-
+-/*
++#define CURL_VERSION_IPV6 (1<<0) /* IPv6-enabled */
++#define CURL_VERSION_KERBEROS4 (1<<1) /* Kerberos V4 auth is supported
++ (deprecated) */
++#define CURL_VERSION_SSL (1<<2) /* SSL options are present */
++#define CURL_VERSION_LIBZ (1<<3) /* libz features are present */
++#define CURL_VERSION_NTLM (1<<4) /* NTLM auth is supported */
++#define CURL_VERSION_GSSNEGOTIATE (1<<5) /* Negotiate auth is supported
++ (deprecated) */
++#define CURL_VERSION_DEBUG (1<<6) /* Built with debug capabilities */
++#define CURL_VERSION_ASYNCHDNS (1<<7) /* Asynchronous DNS resolves */
++#define CURL_VERSION_SPNEGO (1<<8) /* SPNEGO auth is supported */
++#define CURL_VERSION_LARGEFILE (1<<9) /* Supports files larger than 2GB */
++#define CURL_VERSION_IDN (1<<10) /* Internationized Domain Names are
++ supported */
++#define CURL_VERSION_SSPI (1<<11) /* Built against Windows SSPI */
++#define CURL_VERSION_CONV (1<<12) /* Character conversions supported */
++#define CURL_VERSION_CURLDEBUG (1<<13) /* Debug memory tracking supported */
++#define CURL_VERSION_TLSAUTH_SRP (1<<14) /* TLS-SRP auth is supported */
++#define CURL_VERSION_NTLM_WB (1<<15) /* NTLM delegation to winbind helper
++ is supported */
++#define CURL_VERSION_HTTP2 (1<<16) /* HTTP2 support built-in */
++#define CURL_VERSION_GSSAPI (1<<17) /* Built against a GSS-API library */
++#define CURL_VERSION_KERBEROS5 (1<<18) /* Kerberos V5 auth is supported */
++#define CURL_VERSION_UNIX_SOCKETS (1<<19) /* Unix domain sockets support */
++#define CURL_VERSION_PSL (1<<20) /* Mozilla's Public Suffix List, used
++ for cookie domain verification */
++#define CURL_VERSION_HTTPS_PROXY (1<<21) /* HTTPS-proxy support built-in */
++#define CURL_VERSION_MULTI_SSL (1<<22) /* Multiple SSL backends available */
++#define CURL_VERSION_BROTLI (1<<23) /* Brotli features are present. */
++#define CURL_VERSION_ALTSVC (1<<24) /* Alt-Svc handling built-in */
++
++ /*
+ * NAME curl_version_info()
+ *
+ * DESCRIPTION
+ *
+ * This function returns a pointer to a static copy of the version info
+ * struct. See above.
+ */
+ CURL_EXTERN curl_version_info_data *curl_version_info(CURLversion);
+@@ -1910,16 +2837,17 @@ CURL_EXTERN CURLcode curl_easy_pause(CUR
+ #ifdef __cplusplus
+ }
+ #endif
+
+ /* unfortunately, the easy.h and multi.h include files need options and info
+ stuff before they can be included! */
+ #include "easy.h" /* nothing in curl is fun without the easy stuff */
+ #include "multi.h"
++#include "urlapi.h"
+
+ /* the typechecker doesn't work in C++ (yet) */
+ #if defined(__GNUC__) && defined(__GNUC_MINOR__) && \
+ ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)) && \
+ !defined(__cplusplus) && !defined(CURL_DISABLE_TYPECHECK)
+ #include "typecheck-gcc.h"
+ #else
+ #if defined(__STDC__) && (__STDC__ >= 1)
+diff --git a/src/third_party/curl/curlbuild.h b/src/third_party/curl/curlbuild.h
+deleted file mode 100644
+--- a/src/third_party/curl/curlbuild.h
++++ /dev/null
+@@ -1,203 +0,0 @@
+-/* include/curl/curlbuild.h. Generated from curlbuild.h.in by configure. */
+-#ifndef __CURL_CURLBUILD_H
+-#define __CURL_CURLBUILD_H
+-/***************************************************************************
+- * _ _ ____ _
+- * Project ___| | | | _ \| |
+- * / __| | | | |_) | |
+- * | (__| |_| | _ <| |___
+- * \___|\___/|_| \_\_____|
+- *
+- * Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
+- *
+- * This software is licensed as described in the file COPYING, which
+- * you should have received as part of this distribution. The terms
+- * are also available at http://curl.haxx.se/docs/copyright.html.
+- *
+- * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+- * copies of the Software, and permit persons to whom the Software is
+- * furnished to do so, under the terms of the COPYING file.
+- *
+- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+- * KIND, either express or implied.
+- *
+- * $Id: curlbuild.h.in,v 1.8 2009-04-29 15:15:38 yangtse Exp $
+- ***************************************************************************/
+-
+-/* ================================================================ */
+-/* NOTES FOR CONFIGURE CAPABLE SYSTEMS */
+-/* ================================================================ */
+-
+-/*
+- * NOTE 1:
+- * -------
+- *
+- * Nothing in this file is intended to be modified or adjusted by the
+- * curl library user nor by the curl library builder.
+- *
+- * If you think that something actually needs to be changed, adjusted
+- * or fixed in this file, then, report it on the libcurl development
+- * mailing list: http://cool.haxx.se/mailman/listinfo/curl-library/
+- *
+- * This header file shall only export symbols which are 'curl' or 'CURL'
+- * prefixed, otherwise public name space would be polluted.
+- *
+- * NOTE 2:
+- * -------
+- *
+- * Right now you might be staring at file include/curl/curlbuild.h.in or
+- * at file include/curl/curlbuild.h, this is due to the following reason:
+- *
+- * On systems capable of running the configure script, the configure process
+- * will overwrite the distributed include/curl/curlbuild.h file with one that
+- * is suitable and specific to the library being configured and built, which
+- * is generated from the include/curl/curlbuild.h.in template file.
+- *
+- */
+-
+-/* ================================================================ */
+-/* DEFINITION OF THESE SYMBOLS SHALL NOT TAKE PLACE ANYWHERE ELSE */
+-/* ================================================================ */
+-
+-#ifdef CURL_SIZEOF_LONG
+-# error "CURL_SIZEOF_LONG shall not be defined except in curlbuild.h"
+- Error Compilation_aborted_CURL_SIZEOF_LONG_already_defined
+-#endif
+-
+-#ifdef CURL_TYPEOF_CURL_SOCKLEN_T
+-# error "CURL_TYPEOF_CURL_SOCKLEN_T shall not be defined except in curlbuild.h"
+- Error Compilation_aborted_CURL_TYPEOF_CURL_SOCKLEN_T_already_defined
+-#endif
+-
+-#ifdef CURL_SIZEOF_CURL_SOCKLEN_T
+-# error "CURL_SIZEOF_CURL_SOCKLEN_T shall not be defined except in curlbuild.h"
+- Error Compilation_aborted_CURL_SIZEOF_CURL_SOCKLEN_T_already_defined
+-#endif
+-
+-#ifdef CURL_TYPEOF_CURL_OFF_T
+-# error "CURL_TYPEOF_CURL_OFF_T shall not be defined except in curlbuild.h"
+- Error Compilation_aborted_CURL_TYPEOF_CURL_OFF_T_already_defined
+-#endif
+-
+-#ifdef CURL_FORMAT_CURL_OFF_T
+-# error "CURL_FORMAT_CURL_OFF_T shall not be defined except in curlbuild.h"
+- Error Compilation_aborted_CURL_FORMAT_CURL_OFF_T_already_defined
+-#endif
+-
+-#ifdef CURL_FORMAT_CURL_OFF_TU
+-# error "CURL_FORMAT_CURL_OFF_TU shall not be defined except in curlbuild.h"
+- Error Compilation_aborted_CURL_FORMAT_CURL_OFF_TU_already_defined
+-#endif
+-
+-#ifdef CURL_FORMAT_OFF_T
+-# error "CURL_FORMAT_OFF_T shall not be defined except in curlbuild.h"
+- Error Compilation_aborted_CURL_FORMAT_OFF_T_already_defined
+-#endif
+-
+-#ifdef CURL_SIZEOF_CURL_OFF_T
+-# error "CURL_SIZEOF_CURL_OFF_T shall not be defined except in curlbuild.h"
+- Error Compilation_aborted_CURL_SIZEOF_CURL_OFF_T_already_defined
+-#endif
+-
+-#ifdef CURL_SUFFIX_CURL_OFF_T
+-# error "CURL_SUFFIX_CURL_OFF_T shall not be defined except in curlbuild.h"
+- Error Compilation_aborted_CURL_SUFFIX_CURL_OFF_T_already_defined
+-#endif
+-
+-#ifdef CURL_SUFFIX_CURL_OFF_TU
+-# error "CURL_SUFFIX_CURL_OFF_TU shall not be defined except in curlbuild.h"
+- Error Compilation_aborted_CURL_SUFFIX_CURL_OFF_TU_already_defined
+-#endif
+-
+-/* ================================================================ */
+-/* EXTERNAL INTERFACE SETTINGS FOR CONFIGURE CAPABLE SYSTEMS ONLY */
+-/* ================================================================ */
+-
+-/* Configure process defines this to 1 when it finds out that system */
+-/* header file ws2tcpip.h must be included by the external interface. */
+-/* #undef CURL_PULL_WS2TCPIP_H */
+-#ifdef CURL_PULL_WS2TCPIP_H
+-# ifndef WIN32_LEAN_AND_MEAN
+-# define WIN32_LEAN_AND_MEAN
+-# endif
+-# include <windows.h>
+-# include <winsock2.h>
+-# include <ws2tcpip.h>
+-#endif
+-
+-/* Configure process defines this to 1 when it finds out that system */
+-/* header file sys/types.h must be included by the external interface. */
+-#define CURL_PULL_SYS_TYPES_H 1
+-#ifdef CURL_PULL_SYS_TYPES_H
+-# include <sys/types.h>
+-#endif
+-
+-/* Configure process defines this to 1 when it finds out that system */
+-/* header file stdint.h must be included by the external interface. */
+-/* #undef CURL_PULL_STDINT_H */
+-#ifdef CURL_PULL_STDINT_H
+-# include <stdint.h>
+-#endif
+-
+-/* Configure process defines this to 1 when it finds out that system */
+-/* header file inttypes.h must be included by the external interface. */
+-/* #undef CURL_PULL_INTTYPES_H */
+-#ifdef CURL_PULL_INTTYPES_H
+-# include <inttypes.h>
+-#endif
+-
+-/* Configure process defines this to 1 when it finds out that system */
+-/* header file sys/socket.h must be included by the external interface. */
+-#define CURL_PULL_SYS_SOCKET_H 1
+-#ifdef CURL_PULL_SYS_SOCKET_H
+-# include <sys/socket.h>
+-#endif
+-
+-/* The size of `long', as computed by sizeof. */
+-#if defined(_M_X64) || (defined(__x86_64__) && !defined(__ILP32__)) || \
+- defined(__aarch64__) || (defined(__mips__) && _MIPS_SIM == _ABI64) || \
+- defined(__powerpc64__) || defined(__s390x__) || defined(__LP64__)
+-#define CURL_SIZEOF_LONG 8
+-#else
+-#define CURL_SIZEOF_LONG 4
+-#endif
+-
+-/* Integral data type used for curl_socklen_t. */
+-#define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
+-
+-/* The size of `curl_socklen_t', as computed by sizeof. */
+-#define CURL_SIZEOF_CURL_SOCKLEN_T 4
+-
+-/* Data type definition of curl_socklen_t. */
+-typedef CURL_TYPEOF_CURL_SOCKLEN_T curl_socklen_t;
+-
+-/* Signed integral data type used for curl_off_t. */
+-#if defined(_M_X64) || (defined(__x86_64__) && !defined(__ILP32__)) || \
+- defined(__aarch64__)
+-#define CURL_TYPEOF_CURL_OFF_T long
+-#else
+-#define CURL_TYPEOF_CURL_OFF_T int64_t
+-#endif
+-
+-/* Data type definition of curl_off_t. */
+-typedef CURL_TYPEOF_CURL_OFF_T curl_off_t;
+-
+-/* curl_off_t formatting string directive without "%" conversion specifier. */
+-#define CURL_FORMAT_CURL_OFF_T "ld"
+-
+-/* unsigned curl_off_t formatting string without "%" conversion specifier. */
+-#define CURL_FORMAT_CURL_OFF_TU "lu"
+-
+-/* curl_off_t formatting string directive with "%" conversion specifier. */
+-#define CURL_FORMAT_OFF_T "%ld"
+-
+-/* The size of `curl_off_t', as computed by sizeof. */
+-#define CURL_SIZEOF_CURL_OFF_T 8
+-
+-/* curl_off_t constant suffix. */
+-#define CURL_SUFFIX_CURL_OFF_T L
+-
+-/* unsigned curl_off_t constant suffix. */
+-#define CURL_SUFFIX_CURL_OFF_TU UL
+-
+-#endif /* __CURL_CURLBUILD_H */
+diff --git a/src/third_party/curl/curlrules.h b/src/third_party/curl/curlrules.h
+deleted file mode 100644
+--- a/src/third_party/curl/curlrules.h
++++ /dev/null
+@@ -1,249 +0,0 @@
+-#ifndef __CURL_CURLRULES_H
+-#define __CURL_CURLRULES_H
+-/***************************************************************************
+- * _ _ ____ _
+- * Project ___| | | | _ \| |
+- * / __| | | | |_) | |
+- * | (__| |_| | _ <| |___
+- * \___|\___/|_| \_\_____|
+- *
+- * Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
+- *
+- * This software is licensed as described in the file COPYING, which
+- * you should have received as part of this distribution. The terms
+- * are also available at http://curl.haxx.se/docs/copyright.html.
+- *
+- * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+- * copies of the Software, and permit persons to whom the Software is
+- * furnished to do so, under the terms of the COPYING file.
+- *
+- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+- * KIND, either express or implied.
+- *
+- * $Id: curlrules.h,v 1.7 2009-10-27 16:56:20 yangtse Exp $
+- ***************************************************************************/
+-
+-/* ================================================================ */
+-/* COMPILE TIME SANITY CHECKS */
+-/* ================================================================ */
+-
+-/*
+- * NOTE 1:
+- * -------
+- *
+- * All checks done in this file are intentionally placed in a public
+- * header file which is pulled by curl/curl.h when an application is
+- * being built using an already built libcurl library. Additionally
+- * this file is also included and used when building the library.
+- *
+- * If compilation fails on this file it is certainly sure that the
+- * problem is elsewhere. It could be a problem in the curlbuild.h
+- * header file, or simply that you are using different compilation
+- * settings than those used to build the library.
+- *
+- * Nothing in this file is intended to be modified or adjusted by the
+- * curl library user nor by the curl library builder.
+- *
+- * Do not deactivate any check, these are done to make sure that the
+- * library is properly built and used.
+- *
+- * You can find further help on the libcurl development mailing list:
+- * http://cool.haxx.se/mailman/listinfo/curl-library/
+- *
+- * NOTE 2
+- * ------
+- *
+- * Some of the following compile time checks are based on the fact
+- * that the dimension of a constant array can not be a negative one.
+- * In this way if the compile time verification fails, the compilation
+- * will fail issuing an error. The error description wording is compiler
+- * dependent but it will be quite similar to one of the following:
+- *
+- * "negative subscript or subscript is too large"
+- * "array must have at least one element"
+- * "-1 is an illegal array size"
+- * "size of array is negative"
+- *
+- * If you are building an application which tries to use an already
+- * built libcurl library and you are getting this kind of errors on
+- * this file, it is a clear indication that there is a mismatch between
+- * how the library was built and how you are trying to use it for your
+- * application. Your already compiled or binary library provider is the
+- * only one who can give you the details you need to properly use it.
+- */
+-
+-/*
+- * Verify that some macros are actually defined.
+- */
+-
+-#ifndef CURL_SIZEOF_LONG
+-# error "CURL_SIZEOF_LONG definition is missing!"
+- Error Compilation_aborted_CURL_SIZEOF_LONG_is_missing
+-#endif
+-
+-#ifndef CURL_TYPEOF_CURL_SOCKLEN_T
+-# error "CURL_TYPEOF_CURL_SOCKLEN_T definition is missing!"
+- Error Compilation_aborted_CURL_TYPEOF_CURL_SOCKLEN_T_is_missing
+-#endif
+-
+-#ifndef CURL_SIZEOF_CURL_SOCKLEN_T
+-# error "CURL_SIZEOF_CURL_SOCKLEN_T definition is missing!"
+- Error Compilation_aborted_CURL_SIZEOF_CURL_SOCKLEN_T_is_missing
+-#endif
+-
+-#ifndef CURL_TYPEOF_CURL_OFF_T
+-# error "CURL_TYPEOF_CURL_OFF_T definition is missing!"
+- Error Compilation_aborted_CURL_TYPEOF_CURL_OFF_T_is_missing
+-#endif
+-
+-#ifndef CURL_FORMAT_CURL_OFF_T
+-# error "CURL_FORMAT_CURL_OFF_T definition is missing!"
+- Error Compilation_aborted_CURL_FORMAT_CURL_OFF_T_is_missing
+-#endif
+-
+-#ifndef CURL_FORMAT_CURL_OFF_TU
+-# error "CURL_FORMAT_CURL_OFF_TU definition is missing!"
+- Error Compilation_aborted_CURL_FORMAT_CURL_OFF_TU_is_missing
+-#endif
+-
+-#ifndef CURL_FORMAT_OFF_T
+-# error "CURL_FORMAT_OFF_T definition is missing!"
+- Error Compilation_aborted_CURL_FORMAT_OFF_T_is_missing
+-#endif
+-
+-#ifndef CURL_SIZEOF_CURL_OFF_T
+-# error "CURL_SIZEOF_CURL_OFF_T definition is missing!"
+- Error Compilation_aborted_CURL_SIZEOF_CURL_OFF_T_is_missing
+-#endif
+-
+-#ifndef CURL_SUFFIX_CURL_OFF_T
+-# error "CURL_SUFFIX_CURL_OFF_T definition is missing!"
+- Error Compilation_aborted_CURL_SUFFIX_CURL_OFF_T_is_missing
+-#endif
+-
+-#ifndef CURL_SUFFIX_CURL_OFF_TU
+-# error "CURL_SUFFIX_CURL_OFF_TU definition is missing!"
+- Error Compilation_aborted_CURL_SUFFIX_CURL_OFF_TU_is_missing
+-#endif
+-
+-/*
+- * Macros private to this header file.
+- */
+-
+-#define CurlchkszEQ(t, s) sizeof(t) == s ? 1 : -1
+-
+-#define CurlchkszGE(t1, t2) sizeof(t1) >= sizeof(t2) ? 1 : -1
+-
+-/*
+- * Verify that the size previously defined and expected for long
+- * is the same as the one reported by sizeof() at compile time.
+- */
+-
+-typedef char
+- __curl_rule_01__
+- [CurlchkszEQ(long, CURL_SIZEOF_LONG)];
+-
+-/*
+- * Verify that the size previously defined and expected for
+- * curl_off_t is actually the the same as the one reported
+- * by sizeof() at compile time.
+- */
+-
+-typedef char
+- __curl_rule_02__
+- [CurlchkszEQ(curl_off_t, CURL_SIZEOF_CURL_OFF_T)];
+-
+-/*
+- * Verify at compile time that the size of curl_off_t as reported
+- * by sizeof() is greater or equal than the one reported for long
+- * for the current compilation.
+- */
+-
+-typedef char
+- __curl_rule_03__
+- [CurlchkszGE(curl_off_t, long)];
+-
+-/*
+- * Verify that the size previously defined and expected for
+- * curl_socklen_t is actually the the same as the one reported
+- * by sizeof() at compile time.
+- */
+-
+-typedef char
+- __curl_rule_04__
+- [CurlchkszEQ(curl_socklen_t, CURL_SIZEOF_CURL_SOCKLEN_T)];
+-
+-/*
+- * Verify at compile time that the size of curl_socklen_t as reported
+- * by sizeof() is greater or equal than the one reported for int for
+- * the current compilation.
+- */
+-
+-typedef char
+- __curl_rule_05__
+- [CurlchkszGE(curl_socklen_t, int)];
+-
+-/* ================================================================ */
+-/* EXTERNALLY AND INTERNALLY VISIBLE DEFINITIONS */
+-/* ================================================================ */
+-
+-/*
+- * CURL_ISOCPP and CURL_OFF_T_C definitions are done here in order to allow
+- * these to be visible and exported by the external libcurl interface API,
+- * while also making them visible to the library internals, simply including
+- * setup.h, without actually needing to include curl.h internally.
+- * If some day this section would grow big enough, all this should be moved
+- * to its own header file.
+- */
+-
+-/*
+- * Figure out if we can use the ## preprocessor operator, which is supported
+- * by ISO/ANSI C and C++. Some compilers support it without setting __STDC__
+- * or __cplusplus so we need to carefully check for them too.
+- */
+-
+-#if defined(__STDC__) || defined(_MSC_VER) || defined(__cplusplus) || \
+- defined(__HP_aCC) || defined(__BORLANDC__) || defined(__LCC__) || \
+- defined(__POCC__) || defined(__SALFORDC__) || defined(__HIGHC__) || \
+- defined(__ILEC400__)
+- /* This compiler is believed to have an ISO compatible preprocessor */
+-#define CURL_ISOCPP
+-#else
+- /* This compiler is believed NOT to have an ISO compatible preprocessor */
+-#undef CURL_ISOCPP
+-#endif
+-
+-/*
+- * Macros for minimum-width signed and unsigned curl_off_t integer constants.
+- */
+-
+-#ifdef CURL_ISOCPP
+-# define __CURL_OFF_T_C_HELPER2(Val,Suffix) Val ## Suffix
+-#else
+-# define __CURL_OFF_T_C_HELPER2(Val,Suffix) Val/**/Suffix
+-#endif
+-#define __CURL_OFF_T_C_HELPER1(Val,Suffix) __CURL_OFF_T_C_HELPER2(Val,Suffix)
+-#define CURL_OFF_T_C(Val) __CURL_OFF_T_C_HELPER1(Val,CURL_SUFFIX_CURL_OFF_T)
+-#define CURL_OFF_TU_C(Val) __CURL_OFF_T_C_HELPER1(Val,CURL_SUFFIX_CURL_OFF_TU)
+-
+-/*
+- * Get rid of macros private to this header file.
+- */
+-
+-#undef CurlchkszEQ
+-#undef CurlchkszGE
+-
+-/*
+- * Get rid of macros not intended to exist beyond this point.
+- */
+-
+-#undef CURL_PULL_WS2TCPIP_H
+-#undef CURL_PULL_SYS_TYPES_H
+-#undef CURL_PULL_SYS_SOCKET_H
+-#undef CURL_PULL_STDINT_H
+-#undef CURL_PULL_INTTYPES_H
+-
+-#undef CURL_TYPEOF_CURL_SOCKLEN_T
+-#undef CURL_TYPEOF_CURL_OFF_T
+-
+-#endif /* __CURL_CURLRULES_H */
+diff --git a/src/third_party/curl/curlver.h b/src/third_party/curl/curlver.h
+--- a/src/third_party/curl/curlver.h
++++ b/src/third_party/curl/curlver.h
+@@ -2,69 +2,76 @@
+ #define __CURL_CURLVER_H
+ /***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+- * Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
++ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+- * are also available at http://curl.haxx.se/docs/copyright.html.
++ * are also available at https://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+- * $Id: curlver.h,v 1.48 2009-08-12 11:24:52 bagder Exp $
+ ***************************************************************************/
+
+ /* This header file contains nothing but libcurl version info, generated by
+ a script at release-time. This was made its own header file in 7.11.2 */
+
+ /* This is the global package copyright */
+-#define LIBCURL_COPYRIGHT "1996 - 2009 Daniel Stenberg, <daniel@haxx.se>."
++#define LIBCURL_COPYRIGHT "1996 - 2019 Daniel Stenberg, <daniel@haxx.se>."
+
+ /* This is the version number of the libcurl package from which this header
+ file origins: */
+-#define LIBCURL_VERSION "7.19.7"
++#define LIBCURL_VERSION "7.64.1-DEV"
+
+ /* The numeric version number is also available "in parts" by using these
+ defines: */
+ #define LIBCURL_VERSION_MAJOR 7
+-#define LIBCURL_VERSION_MINOR 19
+-#define LIBCURL_VERSION_PATCH 7
++#define LIBCURL_VERSION_MINOR 64
++#define LIBCURL_VERSION_PATCH 1
+
+ /* This is the numeric version of the libcurl version number, meant for easier
+ parsing and comparions by programs. The LIBCURL_VERSION_NUM define will
+ always follow this syntax:
+
+ 0xXXYYZZ
+
+ Where XX, YY and ZZ are the main version, release and patch numbers in
+ hexadecimal (using 8 bits each). All three numbers are always represented
+ using two digits. 1.2 would appear as "0x010200" while version 9.11.7
+ appears as "0x090b07".
+
+ This 6-digit (24 bits) hexadecimal number does not show pre-release number,
+ and it is always a greater number in a more recent release. It makes
+ comparisons with greater than and less than work.
++
++ Note: This define is the full hex number and _does not_ use the
++ CURL_VERSION_BITS() macro since curl's own configure script greps for it
++ and needs it to contain the full number.
+ */
+-#define LIBCURL_VERSION_NUM 0x071307
++#define LIBCURL_VERSION_NUM 0x074001
+
+ /*
+ * This is the date and time when the full source package was created. The
+- * timestamp is not stored in CVS, as the timestamp is properly set in the
++ * timestamp is not stored in git, as the timestamp is properly set in the
+ * tarballs by the maketgz script.
+ *
+- * The format of the date should follow this template:
++ * The format of the date follows this template:
+ *
+- * "Mon Feb 12 11:35:33 UTC 2007"
++ * "2007-11-23"
+ */
+-#define LIBCURL_TIMESTAMP "Wed Nov 4 12:34:59 UTC 2009"
++#define LIBCURL_TIMESTAMP "[unreleased]"
++
++#define CURL_VERSION_BITS(x,y,z) ((x)<<16|(y)<<8|z)
++#define CURL_AT_LEAST_VERSION(x,y,z) \
++ (LIBCURL_VERSION_NUM >= CURL_VERSION_BITS(x, y, z))
+
+ #endif /* __CURL_CURLVER_H */
+diff --git a/src/third_party/curl/easy.h b/src/third_party/curl/easy.h
+--- a/src/third_party/curl/easy.h
++++ b/src/third_party/curl/easy.h
+@@ -2,30 +2,29 @@
+ #define __CURL_EASY_H
+ /***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+- * Copyright (C) 1998 - 2008, Daniel Stenberg, <daniel@haxx.se>, et al.
++ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+- * are also available at http://curl.haxx.se/docs/copyright.html.
++ * are also available at https://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+- * $Id: easy.h,v 1.14 2008-05-12 21:43:28 bagder Exp $
+ ***************************************************************************/
+ #ifdef __cplusplus
+ extern "C" {
+ #endif
+
+ CURL_EXTERN CURL *curl_easy_init(void);
+ CURL_EXTERN CURLcode curl_easy_setopt(CURL *curl, CURLoption option, ...);
+ CURL_EXTERN CURLcode curl_easy_perform(CURL *curl);
+@@ -49,22 +48,22 @@ CURL_EXTERN CURLcode curl_easy_getinfo(C
+
+ /*
+ * NAME curl_easy_duphandle()
+ *
+ * DESCRIPTION
+ *
+ * Creates a new curl session handle with the same options set for the handle
+ * passed in. Duplicating a handle could only be a matter of cloning data and
+- * options, internal state info and things like persistant connections cannot
+- * be transfered. It is useful in multithreaded applications when you can run
++ * options, internal state info and things like persistent connections cannot
++ * be transferred. It is useful in multithreaded applications when you can run
+ * curl_easy_duphandle() for each new thread to avoid a series of identical
+ * curl_easy_setopt() invokes in every thread.
+ */
+-CURL_EXTERN CURL* curl_easy_duphandle(CURL *curl);
++CURL_EXTERN CURL *curl_easy_duphandle(CURL *curl);
+
+ /*
+ * NAME curl_easy_reset()
+ *
+ * DESCRIPTION
+ *
+ * Re-initializes a CURL handle to the default values. This puts back the
+ * handle to the same state as it was in when it was just created.
+@@ -91,13 +90,23 @@ CURL_EXTERN CURLcode curl_easy_recv(CURL
+ * DESCRIPTION
+ *
+ * Sends data over the connected socket. Use after successful
+ * curl_easy_perform() with CURLOPT_CONNECT_ONLY option.
+ */
+ CURL_EXTERN CURLcode curl_easy_send(CURL *curl, const void *buffer,
+ size_t buflen, size_t *n);
+
++
++/*
++ * NAME curl_easy_upkeep()
++ *
++ * DESCRIPTION
++ *
++ * Performs connection upkeep for the given session handle.
++ */
++CURL_EXTERN CURLcode curl_easy_upkeep(CURL *curl);
++
+ #ifdef __cplusplus
+ }
+ #endif
+
+ #endif
+diff --git a/src/third_party/curl/mprintf.h b/src/third_party/curl/mprintf.h
+deleted file mode 100644
+--- a/src/third_party/curl/mprintf.h
++++ /dev/null
+@@ -1,82 +0,0 @@
+-#ifndef __CURL_MPRINTF_H
+-#define __CURL_MPRINTF_H
+-/***************************************************************************
+- * _ _ ____ _
+- * Project ___| | | | _ \| |
+- * / __| | | | |_) | |
+- * | (__| |_| | _ <| |___
+- * \___|\___/|_| \_\_____|
+- *
+- * Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
+- *
+- * This software is licensed as described in the file COPYING, which
+- * you should have received as part of this distribution. The terms
+- * are also available at http://curl.haxx.se/docs/copyright.html.
+- *
+- * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+- * copies of the Software, and permit persons to whom the Software is
+- * furnished to do so, under the terms of the COPYING file.
+- *
+- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+- * KIND, either express or implied.
+- *
+- * $Id: mprintf.h,v 1.16 2008-05-20 10:21:50 patrickm Exp $
+- ***************************************************************************/
+-
+-#include <stdarg.h>
+-#include <stdio.h> /* needed for FILE */
+-
+-#include "curl.h"
+-
+-#ifdef __cplusplus
+-extern "C" {
+-#endif
+-
+-CURL_EXTERN int curl_mprintf(const char *format, ...);
+-CURL_EXTERN int curl_mfprintf(FILE *fd, const char *format, ...);
+-CURL_EXTERN int curl_msprintf(char *buffer, const char *format, ...);
+-CURL_EXTERN int curl_msnprintf(char *buffer, size_t maxlength,
+- const char *format, ...);
+-CURL_EXTERN int curl_mvprintf(const char *format, va_list args);
+-CURL_EXTERN int curl_mvfprintf(FILE *fd, const char *format, va_list args);
+-CURL_EXTERN int curl_mvsprintf(char *buffer, const char *format, va_list args);
+-CURL_EXTERN int curl_mvsnprintf(char *buffer, size_t maxlength,
+- const char *format, va_list args);
+-CURL_EXTERN char *curl_maprintf(const char *format, ...);
+-CURL_EXTERN char *curl_mvaprintf(const char *format, va_list args);
+-
+-#ifdef _MPRINTF_REPLACE
+-# undef printf
+-# undef fprintf
+-# undef sprintf
+-# undef vsprintf
+-# undef snprintf
+-# undef vprintf
+-# undef vfprintf
+-# undef vsnprintf
+-# undef aprintf
+-# undef vaprintf
+-# define printf curl_mprintf
+-# define fprintf curl_mfprintf
+-#ifdef CURLDEBUG
+-/* When built with CURLDEBUG we define away the sprintf() functions since we
+- don't want internal code to be using them */
+-# define sprintf sprintf_was_used
+-# define vsprintf vsprintf_was_used
+-#else
+-# define sprintf curl_msprintf
+-# define vsprintf curl_mvsprintf
+-#endif
+-# define snprintf curl_msnprintf
+-# define vprintf curl_mvprintf
+-# define vfprintf curl_mvfprintf
+-# define vsnprintf curl_mvsnprintf
+-# define aprintf curl_maprintf
+-# define vaprintf curl_mvaprintf
+-#endif
+-
+-#ifdef __cplusplus
+-}
+-#endif
+-
+-#endif /* __CURL_MPRINTF_H */
+diff --git a/src/third_party/curl/multi.h b/src/third_party/curl/multi.h
+--- a/src/third_party/curl/multi.h
++++ b/src/third_party/curl/multi.h
+@@ -2,30 +2,29 @@
+ #define __CURL_MULTI_H
+ /***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+- * Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
++ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+- * are also available at http://curl.haxx.se/docs/copyright.html.
++ * are also available at https://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+- * $Id: multi.h,v 1.45 2008-05-20 10:21:50 patrickm Exp $
+ ***************************************************************************/
+ /*
+ This is an "external" header file. Don't give away any internals here!
+
+ GOALS
+
+ o Enable a "pull" interface. The application that uses libcurl decides where
+ and when to ask libcurl to get/send data.
+@@ -48,36 +47,49 @@
+ * but with this warning attached.
+ */
+ #include "curl.h"
+
+ #ifdef __cplusplus
+ extern "C" {
+ #endif
+
++#if defined(BUILDING_LIBCURL) || defined(CURL_STRICTER)
++typedef struct Curl_multi CURLM;
++#else
+ typedef void CURLM;
++#endif
+
+ typedef enum {
+ CURLM_CALL_MULTI_PERFORM = -1, /* please call curl_multi_perform() or
+ curl_multi_socket*() soon */
+ CURLM_OK,
+ CURLM_BAD_HANDLE, /* the passed-in handle is not a valid CURLM handle */
+ CURLM_BAD_EASY_HANDLE, /* an easy handle was not good/valid */
+ CURLM_OUT_OF_MEMORY, /* if you ever get this, you're in deep sh*t */
+ CURLM_INTERNAL_ERROR, /* this is a libcurl bug */
+ CURLM_BAD_SOCKET, /* the passed in socket argument did not match */
+ CURLM_UNKNOWN_OPTION, /* curl_multi_setopt() with unsupported option */
++ CURLM_ADDED_ALREADY, /* an easy handle already added to a multi handle was
++ attempted to get added - again */
++ CURLM_RECURSIVE_API_CALL, /* an api function was called from inside a
++ callback */
+ CURLM_LAST
+ } CURLMcode;
+
+ /* just to make code nicer when using curl_multi_socket() you can now check
+ for CURLM_CALL_MULTI_SOCKET too in the same style it works for
+ curl_multi_perform() and CURLM_CALL_MULTI_PERFORM */
+ #define CURLM_CALL_MULTI_SOCKET CURLM_CALL_MULTI_PERFORM
+
++/* bitmask bits for CURLMOPT_PIPELINING */
++#define CURLPIPE_NOTHING 0L
++#define CURLPIPE_HTTP1 1L
++#define CURLPIPE_MULTIPLEX 2L
++
+ typedef enum {
+ CURLMSG_NONE, /* first, not used */
+ CURLMSG_DONE, /* This easy handle has completed. 'result' contains
+ the CURLcode of the transfer */
+ CURLMSG_LAST /* last, not used */
+ } CURLMSG;
+
+ struct CURLMsg {
+@@ -85,16 +97,29 @@ struct CURLMsg {
+ CURL *easy_handle; /* the handle it concerns */
+ union {
+ void *whatever; /* message-specific data */
+ CURLcode result; /* return code for transfer */
+ } data;
+ };
+ typedef struct CURLMsg CURLMsg;
+
++/* Based on poll(2) structure and values.
++ * We don't use pollfd and POLL* constants explicitly
++ * to cover platforms without poll(). */
++#define CURL_WAIT_POLLIN 0x0001
++#define CURL_WAIT_POLLPRI 0x0002
++#define CURL_WAIT_POLLOUT 0x0004
++
++struct curl_waitfd {
++ curl_socket_t fd;
++ short events;
++ short revents; /* not supported yet */
++};
++
+ /*
+ * Name: curl_multi_init()
+ *
+ * Desc: inititalize multi-style curl usage
+ *
+ * Returns: a new CURLM handle to use in all 'curl_multi' functions.
+ */
+ CURL_EXTERN CURLM *curl_multi_init(void);
+@@ -129,31 +154,45 @@ CURL_EXTERN CURLMcode curl_multi_remove_
+ * Returns: CURLMcode type, general multi error code.
+ */
+ CURL_EXTERN CURLMcode curl_multi_fdset(CURLM *multi_handle,
+ fd_set *read_fd_set,
+ fd_set *write_fd_set,
+ fd_set *exc_fd_set,
+ int *max_fd);
+
++/*
++ * Name: curl_multi_wait()
++ *
++ * Desc: Poll on all fds within a CURLM set as well as any
++ * additional fds passed to the function.
++ *
++ * Returns: CURLMcode type, general multi error code.
++ */
++CURL_EXTERN CURLMcode curl_multi_wait(CURLM *multi_handle,
++ struct curl_waitfd extra_fds[],
++ unsigned int extra_nfds,
++ int timeout_ms,
++ int *ret);
++
+ /*
+ * Name: curl_multi_perform()
+ *
+ * Desc: When the app thinks there's data available for curl it calls this
+ * function to read/write whatever there is right now. This returns
+ * as soon as the reads and writes are done. This function does not
+ * require that there actually is data available for reading or that
+ * data can be written, it can be called just in case. It returns
+ * the number of handles that still transfer data in the second
+ * argument's integer-pointer.
+ *
+ * Returns: CURLMcode type, general multi error code. *NOTE* that this only
+ * returns errors etc regarding the whole multi stack. There might
+- * still have occurred problems on invidual transfers even when this
+- * returns OK.
++ * still have occurred problems on individual transfers even when
++ * this returns OK.
+ */
+ CURL_EXTERN CURLMcode curl_multi_perform(CURLM *multi_handle,
+ int *running_handles);
+
+ /*
+ * Name: curl_multi_cleanup()
+ *
+ * Desc: Cleans up and removes a whole multi stack. It does not free or
+@@ -176,17 +215,17 @@ CURL_EXTERN CURLMcode curl_multi_cleanup
+ * Repeated calls to this function will return a new struct each
+ * time, until a special "end of msgs" struct is returned as a signal
+ * that there is no more to get at this point.
+ *
+ * The data the returned pointer points to will not survive calling
+ * curl_multi_cleanup().
+ *
+ * The 'CURLMsg' struct is meant to be very simple and only contain
+- * very basic informations. If more involved information is wanted,
++ * very basic information. If more involved information is wanted,
+ * we will provide the particular "transfer handle" in that struct
+ * and that should/could/would be used in subsequent
+ * curl_easy_getinfo() calls (or similar). The point being that we
+ * must never expose complex structs to applications, as then we'll
+ * undoubtably get backwards compatibility problems in the future.
+ *
+ * Returns: A pointer to a filled-in struct, or NULL if it failed or ran out
+ * of structs. It also writes the number of messages left in the
+@@ -307,16 +346,47 @@ typedef enum {
+ CINIT(TIMERFUNCTION, FUNCTIONPOINT, 4),
+
+ /* This is the argument passed to the timer callback */
+ CINIT(TIMERDATA, OBJECTPOINT, 5),
+
+ /* maximum number of entries in the connection cache */
+ CINIT(MAXCONNECTS, LONG, 6),
+
++ /* maximum number of (pipelining) connections to one host */
++ CINIT(MAX_HOST_CONNECTIONS, LONG, 7),
++
++ /* maximum number of requests in a pipeline */
++ CINIT(MAX_PIPELINE_LENGTH, LONG, 8),
++
++ /* a connection with a content-length longer than this
++ will not be considered for pipelining */
++ CINIT(CONTENT_LENGTH_PENALTY_SIZE, OFF_T, 9),
++
++ /* a connection with a chunk length longer than this
++ will not be considered for pipelining */
++ CINIT(CHUNK_LENGTH_PENALTY_SIZE, OFF_T, 10),
++
++ /* a list of site names(+port) that are blacklisted from
++ pipelining */
++ CINIT(PIPELINING_SITE_BL, OBJECTPOINT, 11),
++
++ /* a list of server types that are blacklisted from
++ pipelining */
++ CINIT(PIPELINING_SERVER_BL, OBJECTPOINT, 12),
++
++ /* maximum number of open connections in total */
++ CINIT(MAX_TOTAL_CONNECTIONS, LONG, 13),
++
++ /* This is the server push callback function pointer */
++ CINIT(PUSHFUNCTION, FUNCTIONPOINT, 14),
++
++ /* This is the argument passed to the server push callback */
++ CINIT(PUSHDATA, OBJECTPOINT, 15),
++
+ CURLMOPT_LASTENTRY /* the last unused */
+ } CURLMoption;
+
+
+ /*
+ * Name: curl_multi_setopt()
+ *
+ * Desc: Sets options for the multi handle.
+@@ -334,13 +404,38 @@ CURL_EXTERN CURLMcode curl_multi_setopt(
+ * given socket and a private pointer of the application. This is
+ * (only) useful for curl_multi_socket uses.
+ *
+ * Returns: CURLM error code.
+ */
+ CURL_EXTERN CURLMcode curl_multi_assign(CURLM *multi_handle,
+ curl_socket_t sockfd, void *sockp);
+
++
++/*
++ * Name: curl_push_callback
++ *
++ * Desc: This callback gets called when a new stream is being pushed by the
++ * server. It approves or denies the new stream.
++ *
++ * Returns: CURL_PUSH_OK or CURL_PUSH_DENY.
++ */
++#define CURL_PUSH_OK 0
++#define CURL_PUSH_DENY 1
++
++struct curl_pushheaders; /* forward declaration only */
++
++CURL_EXTERN char *curl_pushheader_bynum(struct curl_pushheaders *h,
++ size_t num);
++CURL_EXTERN char *curl_pushheader_byname(struct curl_pushheaders *h,
++ const char *name);
++
++typedef int (*curl_push_callback)(CURL *parent,
++ CURL *easy,
++ size_t num_headers,
++ struct curl_pushheaders *headers,
++ void *userp);
++
+ #ifdef __cplusplus
+ } /* end of extern "C" */
+ #endif
+
+ #endif
+diff --git a/src/third_party/curl/stdcheaders.h b/src/third_party/curl/stdcheaders.h
+deleted file mode 100644
+--- a/src/third_party/curl/stdcheaders.h
++++ /dev/null
+@@ -1,34 +0,0 @@
+-#ifndef __STDC_HEADERS_H
+-#define __STDC_HEADERS_H
+-/***************************************************************************
+- * _ _ ____ _
+- * Project ___| | | | _ \| |
+- * / __| | | | |_) | |
+- * | (__| |_| | _ <| |___
+- * \___|\___/|_| \_\_____|
+- *
+- * Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
+- *
+- * This software is licensed as described in the file COPYING, which
+- * you should have received as part of this distribution. The terms
+- * are also available at http://curl.haxx.se/docs/copyright.html.
+- *
+- * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+- * copies of the Software, and permit persons to whom the Software is
+- * furnished to do so, under the terms of the COPYING file.
+- *
+- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+- * KIND, either express or implied.
+- *
+- * $Id: stdcheaders.h,v 1.9 2009-05-18 12:25:45 yangtse Exp $
+- ***************************************************************************/
+-
+-#include <sys/types.h>
+-
+-size_t fread (void *, size_t, size_t, FILE *);
+-size_t fwrite (const void *, size_t, size_t, FILE *);
+-
+-int strcasecmp(const char *, const char *);
+-int strncasecmp(const char *, const char *, size_t);
+-
+-#endif
+diff --git a/src/third_party/curl/system.h b/src/third_party/curl/system.h
+new file mode 100644
+--- /dev/null
++++ b/src/third_party/curl/system.h
+@@ -0,0 +1,493 @@
++#ifndef __CURL_SYSTEM_H
++#define __CURL_SYSTEM_H
++/***************************************************************************
++ * _ _ ____ _
++ * Project ___| | | | _ \| |
++ * / __| | | | |_) | |
++ * | (__| |_| | _ <| |___
++ * \___|\___/|_| \_\_____|
++ *
++ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
++ *
++ * This software is licensed as described in the file COPYING, which
++ * you should have received as part of this distribution. The terms
++ * are also available at https://curl.haxx.se/docs/copyright.html.
++ *
++ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
++ * copies of the Software, and permit persons to whom the Software is
++ * furnished to do so, under the terms of the COPYING file.
++ *
++ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
++ * KIND, either express or implied.
++ *
++ ***************************************************************************/
++
++/*
++ * Try to keep one section per platform, compiler and architecture, otherwise,
++ * if an existing section is reused for a different one and later on the
++ * original is adjusted, probably the piggybacking one can be adversely
++ * changed.
++ *
++ * In order to differentiate between platforms/compilers/architectures use
++ * only compiler built in predefined preprocessor symbols.
++ *
++ * curl_off_t
++ * ----------
++ *
++ * For any given platform/compiler curl_off_t must be typedef'ed to a 64-bit
++ * wide signed integral data type. The width of this data type must remain
++ * constant and independent of any possible large file support settings.
++ *
++ * As an exception to the above, curl_off_t shall be typedef'ed to a 32-bit
++ * wide signed integral data type if there is no 64-bit type.
++ *
++ * As a general rule, curl_off_t shall not be mapped to off_t. This rule shall
++ * only be violated if off_t is the only 64-bit data type available and the
++ * size of off_t is independent of large file support settings. Keep your
++ * build on the safe side avoiding an off_t gating. If you have a 64-bit
++ * off_t then take for sure that another 64-bit data type exists, dig deeper
++ * and you will find it.
++ *
++ */
++
++#if defined(__DJGPP__) || defined(__GO32__)
++# if defined(__DJGPP__) && (__DJGPP__ > 1)
++# define CURL_TYPEOF_CURL_OFF_T long long
++# define CURL_FORMAT_CURL_OFF_T "lld"
++# define CURL_FORMAT_CURL_OFF_TU "llu"
++# define CURL_SUFFIX_CURL_OFF_T LL
++# define CURL_SUFFIX_CURL_OFF_TU ULL
++# else
++# define CURL_TYPEOF_CURL_OFF_T long
++# define CURL_FORMAT_CURL_OFF_T "ld"
++# define CURL_FORMAT_CURL_OFF_TU "lu"
++# define CURL_SUFFIX_CURL_OFF_T L
++# define CURL_SUFFIX_CURL_OFF_TU UL
++# endif
++# define CURL_TYPEOF_CURL_SOCKLEN_T int
++
++#elif defined(__SALFORDC__)
++# define CURL_TYPEOF_CURL_OFF_T long
++# define CURL_FORMAT_CURL_OFF_T "ld"
++# define CURL_FORMAT_CURL_OFF_TU "lu"
++# define CURL_SUFFIX_CURL_OFF_T L
++# define CURL_SUFFIX_CURL_OFF_TU UL
++# define CURL_TYPEOF_CURL_SOCKLEN_T int
++
++#elif defined(__BORLANDC__)
++# if (__BORLANDC__ < 0x520)
++# define CURL_TYPEOF_CURL_OFF_T long
++# define CURL_FORMAT_CURL_OFF_T "ld"
++# define CURL_FORMAT_CURL_OFF_TU "lu"
++# define CURL_SUFFIX_CURL_OFF_T L
++# define CURL_SUFFIX_CURL_OFF_TU UL
++# else
++# define CURL_TYPEOF_CURL_OFF_T __int64
++# define CURL_FORMAT_CURL_OFF_T "I64d"
++# define CURL_FORMAT_CURL_OFF_TU "I64u"
++# define CURL_SUFFIX_CURL_OFF_T i64
++# define CURL_SUFFIX_CURL_OFF_TU ui64
++# endif
++# define CURL_TYPEOF_CURL_SOCKLEN_T int
++
++#elif defined(__TURBOC__)
++# define CURL_TYPEOF_CURL_OFF_T long
++# define CURL_FORMAT_CURL_OFF_T "ld"
++# define CURL_FORMAT_CURL_OFF_TU "lu"
++# define CURL_SUFFIX_CURL_OFF_T L
++# define CURL_SUFFIX_CURL_OFF_TU UL
++# define CURL_TYPEOF_CURL_SOCKLEN_T int
++
++#elif defined(__WATCOMC__)
++# if defined(__386__)
++# define CURL_TYPEOF_CURL_OFF_T __int64
++# define CURL_FORMAT_CURL_OFF_T "I64d"
++# define CURL_FORMAT_CURL_OFF_TU "I64u"
++# define CURL_SUFFIX_CURL_OFF_T i64
++# define CURL_SUFFIX_CURL_OFF_TU ui64
++# else
++# define CURL_TYPEOF_CURL_OFF_T long
++# define CURL_FORMAT_CURL_OFF_T "ld"
++# define CURL_FORMAT_CURL_OFF_TU "lu"
++# define CURL_SUFFIX_CURL_OFF_T L
++# define CURL_SUFFIX_CURL_OFF_TU UL
++# endif
++# define CURL_TYPEOF_CURL_SOCKLEN_T int
++
++#elif defined(__POCC__)
++# if (__POCC__ < 280)
++# define CURL_TYPEOF_CURL_OFF_T long
++# define CURL_FORMAT_CURL_OFF_T "ld"
++# define CURL_FORMAT_CURL_OFF_TU "lu"
++# define CURL_SUFFIX_CURL_OFF_T L
++# define CURL_SUFFIX_CURL_OFF_TU UL
++# elif defined(_MSC_VER)
++# define CURL_TYPEOF_CURL_OFF_T __int64
++# define CURL_FORMAT_CURL_OFF_T "I64d"
++# define CURL_FORMAT_CURL_OFF_TU "I64u"
++# define CURL_SUFFIX_CURL_OFF_T i64
++# define CURL_SUFFIX_CURL_OFF_TU ui64
++# else
++# define CURL_TYPEOF_CURL_OFF_T long long
++# define CURL_FORMAT_CURL_OFF_T "lld"
++# define CURL_FORMAT_CURL_OFF_TU "llu"
++# define CURL_SUFFIX_CURL_OFF_T LL
++# define CURL_SUFFIX_CURL_OFF_TU ULL
++# endif
++# define CURL_TYPEOF_CURL_SOCKLEN_T int
++
++#elif defined(__LCC__)
++# define CURL_TYPEOF_CURL_OFF_T long
++# define CURL_FORMAT_CURL_OFF_T "ld"
++# define CURL_FORMAT_CURL_OFF_TU "lu"
++# define CURL_SUFFIX_CURL_OFF_T L
++# define CURL_SUFFIX_CURL_OFF_TU UL
++# define CURL_TYPEOF_CURL_SOCKLEN_T int
++
++#elif defined(__SYMBIAN32__)
++# if defined(__EABI__) /* Treat all ARM compilers equally */
++# define CURL_TYPEOF_CURL_OFF_T long long
++# define CURL_FORMAT_CURL_OFF_T "lld"
++# define CURL_FORMAT_CURL_OFF_TU "llu"
++# define CURL_SUFFIX_CURL_OFF_T LL
++# define CURL_SUFFIX_CURL_OFF_TU ULL
++# elif defined(__CW32__)
++# pragma longlong on
++# define CURL_TYPEOF_CURL_OFF_T long long
++# define CURL_FORMAT_CURL_OFF_T "lld"
++# define CURL_FORMAT_CURL_OFF_TU "llu"
++# define CURL_SUFFIX_CURL_OFF_T LL
++# define CURL_SUFFIX_CURL_OFF_TU ULL
++# elif defined(__VC32__)
++# define CURL_TYPEOF_CURL_OFF_T __int64
++# define CURL_FORMAT_CURL_OFF_T "lld"
++# define CURL_FORMAT_CURL_OFF_TU "llu"
++# define CURL_SUFFIX_CURL_OFF_T LL
++# define CURL_SUFFIX_CURL_OFF_TU ULL
++# endif
++# define CURL_TYPEOF_CURL_SOCKLEN_T unsigned int
++
++#elif defined(__MWERKS__)
++# define CURL_TYPEOF_CURL_OFF_T long long
++# define CURL_FORMAT_CURL_OFF_T "lld"
++# define CURL_FORMAT_CURL_OFF_TU "llu"
++# define CURL_SUFFIX_CURL_OFF_T LL
++# define CURL_SUFFIX_CURL_OFF_TU ULL
++# define CURL_TYPEOF_CURL_SOCKLEN_T int
++
++#elif defined(_WIN32_WCE)
++# define CURL_TYPEOF_CURL_OFF_T __int64
++# define CURL_FORMAT_CURL_OFF_T "I64d"
++# define CURL_FORMAT_CURL_OFF_TU "I64u"
++# define CURL_SUFFIX_CURL_OFF_T i64
++# define CURL_SUFFIX_CURL_OFF_TU ui64
++# define CURL_TYPEOF_CURL_SOCKLEN_T int
++
++#elif defined(__MINGW32__)
++# define CURL_TYPEOF_CURL_OFF_T long long
++# define CURL_FORMAT_CURL_OFF_T "I64d"
++# define CURL_FORMAT_CURL_OFF_TU "I64u"
++# define CURL_SUFFIX_CURL_OFF_T LL
++# define CURL_SUFFIX_CURL_OFF_TU ULL
++# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
++# define CURL_PULL_SYS_TYPES_H 1
++# define CURL_PULL_WS2TCPIP_H 1
++
++#elif defined(__VMS)
++# if defined(__VAX)
++# define CURL_TYPEOF_CURL_OFF_T long
++# define CURL_FORMAT_CURL_OFF_T "ld"
++# define CURL_FORMAT_CURL_OFF_TU "lu"
++# define CURL_SUFFIX_CURL_OFF_T L
++# define CURL_SUFFIX_CURL_OFF_TU UL
++# else
++# define CURL_TYPEOF_CURL_OFF_T long long
++# define CURL_FORMAT_CURL_OFF_T "lld"
++# define CURL_FORMAT_CURL_OFF_TU "llu"
++# define CURL_SUFFIX_CURL_OFF_T LL
++# define CURL_SUFFIX_CURL_OFF_TU ULL
++# endif
++# define CURL_TYPEOF_CURL_SOCKLEN_T unsigned int
++
++#elif defined(__OS400__)
++# if defined(__ILEC400__)
++# define CURL_TYPEOF_CURL_OFF_T long long
++# define CURL_FORMAT_CURL_OFF_T "lld"
++# define CURL_FORMAT_CURL_OFF_TU "llu"
++# define CURL_SUFFIX_CURL_OFF_T LL
++# define CURL_SUFFIX_CURL_OFF_TU ULL
++# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
++# define CURL_PULL_SYS_TYPES_H 1
++# define CURL_PULL_SYS_SOCKET_H 1
++# endif
++
++#elif defined(__MVS__)
++# if defined(__IBMC__) || defined(__IBMCPP__)
++# if defined(_ILP32)
++# elif defined(_LP64)
++# endif
++# if defined(_LONG_LONG)
++# define CURL_TYPEOF_CURL_OFF_T long long
++# define CURL_FORMAT_CURL_OFF_T "lld"
++# define CURL_FORMAT_CURL_OFF_TU "llu"
++# define CURL_SUFFIX_CURL_OFF_T LL
++# define CURL_SUFFIX_CURL_OFF_TU ULL
++# elif defined(_LP64)
++# define CURL_TYPEOF_CURL_OFF_T long
++# define CURL_FORMAT_CURL_OFF_T "ld"
++# define CURL_FORMAT_CURL_OFF_TU "lu"
++# define CURL_SUFFIX_CURL_OFF_T L
++# define CURL_SUFFIX_CURL_OFF_TU UL
++# else
++# define CURL_TYPEOF_CURL_OFF_T long
++# define CURL_FORMAT_CURL_OFF_T "ld"
++# define CURL_FORMAT_CURL_OFF_TU "lu"
++# define CURL_SUFFIX_CURL_OFF_T L
++# define CURL_SUFFIX_CURL_OFF_TU UL
++# endif
++# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
++# define CURL_PULL_SYS_TYPES_H 1
++# define CURL_PULL_SYS_SOCKET_H 1
++# endif
++
++#elif defined(__370__)
++# if defined(__IBMC__) || defined(__IBMCPP__)
++# if defined(_ILP32)
++# elif defined(_LP64)
++# endif
++# if defined(_LONG_LONG)
++# define CURL_TYPEOF_CURL_OFF_T long long
++# define CURL_FORMAT_CURL_OFF_T "lld"
++# define CURL_FORMAT_CURL_OFF_TU "llu"
++# define CURL_SUFFIX_CURL_OFF_T LL
++# define CURL_SUFFIX_CURL_OFF_TU ULL
++# elif defined(_LP64)
++# define CURL_TYPEOF_CURL_OFF_T long
++# define CURL_FORMAT_CURL_OFF_T "ld"
++# define CURL_FORMAT_CURL_OFF_TU "lu"
++# define CURL_SUFFIX_CURL_OFF_T L
++# define CURL_SUFFIX_CURL_OFF_TU UL
++# else
++# define CURL_TYPEOF_CURL_OFF_T long
++# define CURL_FORMAT_CURL_OFF_T "ld"
++# define CURL_FORMAT_CURL_OFF_TU "lu"
++# define CURL_SUFFIX_CURL_OFF_T L
++# define CURL_SUFFIX_CURL_OFF_TU UL
++# endif
++# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
++# define CURL_PULL_SYS_TYPES_H 1
++# define CURL_PULL_SYS_SOCKET_H 1
++# endif
++
++#elif defined(TPF)
++# define CURL_TYPEOF_CURL_OFF_T long
++# define CURL_FORMAT_CURL_OFF_T "ld"
++# define CURL_FORMAT_CURL_OFF_TU "lu"
++# define CURL_SUFFIX_CURL_OFF_T L
++# define CURL_SUFFIX_CURL_OFF_TU UL
++# define CURL_TYPEOF_CURL_SOCKLEN_T int
++
++#elif defined(__TINYC__) /* also known as tcc */
++
++# define CURL_TYPEOF_CURL_OFF_T long long
++# define CURL_FORMAT_CURL_OFF_T "lld"
++# define CURL_FORMAT_CURL_OFF_TU "llu"
++# define CURL_SUFFIX_CURL_OFF_T LL
++# define CURL_SUFFIX_CURL_OFF_TU ULL
++# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
++# define CURL_PULL_SYS_TYPES_H 1
++# define CURL_PULL_SYS_SOCKET_H 1
++
++#elif defined(__SUNPRO_C) || defined(__SUNPRO_CC) /* Oracle Solaris Studio */
++# if !defined(__LP64) && (defined(__ILP32) || \
++ defined(__i386) || \
++ defined(__sparcv8) || \
++ defined(__sparcv8plus))
++# define CURL_TYPEOF_CURL_OFF_T long long
++# define CURL_FORMAT_CURL_OFF_T "lld"
++# define CURL_FORMAT_CURL_OFF_TU "llu"
++# define CURL_SUFFIX_CURL_OFF_T LL
++# define CURL_SUFFIX_CURL_OFF_TU ULL
++# elif defined(__LP64) || \
++ defined(__amd64) || defined(__sparcv9)
++# define CURL_TYPEOF_CURL_OFF_T long
++# define CURL_FORMAT_CURL_OFF_T "ld"
++# define CURL_FORMAT_CURL_OFF_TU "lu"
++# define CURL_SUFFIX_CURL_OFF_T L
++# define CURL_SUFFIX_CURL_OFF_TU UL
++# endif
++# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
++# define CURL_PULL_SYS_TYPES_H 1
++# define CURL_PULL_SYS_SOCKET_H 1
++
++#elif defined(__xlc__) /* IBM xlc compiler */
++# if !defined(_LP64)
++# define CURL_TYPEOF_CURL_OFF_T long long
++# define CURL_FORMAT_CURL_OFF_T "lld"
++# define CURL_FORMAT_CURL_OFF_TU "llu"
++# define CURL_SUFFIX_CURL_OFF_T LL
++# define CURL_SUFFIX_CURL_OFF_TU ULL
++# else
++# define CURL_TYPEOF_CURL_OFF_T long
++# define CURL_FORMAT_CURL_OFF_T "ld"
++# define CURL_FORMAT_CURL_OFF_TU "lu"
++# define CURL_SUFFIX_CURL_OFF_T L
++# define CURL_SUFFIX_CURL_OFF_TU UL
++# endif
++# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
++# define CURL_PULL_SYS_TYPES_H 1
++# define CURL_PULL_SYS_SOCKET_H 1
++
++/* ===================================== */
++/* KEEP MSVC THE PENULTIMATE ENTRY */
++/* ===================================== */
++
++#elif defined(_MSC_VER)
++# if (_MSC_VER >= 900) && (_INTEGRAL_MAX_BITS >= 64)
++# define CURL_TYPEOF_CURL_OFF_T __int64
++# define CURL_FORMAT_CURL_OFF_T "I64d"
++# define CURL_FORMAT_CURL_OFF_TU "I64u"
++# define CURL_SUFFIX_CURL_OFF_T i64
++# define CURL_SUFFIX_CURL_OFF_TU ui64
++# else
++# define CURL_TYPEOF_CURL_OFF_T long
++# define CURL_FORMAT_CURL_OFF_T "ld"
++# define CURL_FORMAT_CURL_OFF_TU "lu"
++# define CURL_SUFFIX_CURL_OFF_T L
++# define CURL_SUFFIX_CURL_OFF_TU UL
++# endif
++# define CURL_TYPEOF_CURL_SOCKLEN_T int
++
++/* ===================================== */
++/* KEEP GENERIC GCC THE LAST ENTRY */
++/* ===================================== */
++
++#elif defined(__GNUC__) && !defined(_SCO_DS)
++# if !defined(__LP64__) && \
++ (defined(__ILP32__) || defined(__i386__) || defined(__hppa__) || \
++ defined(__ppc__) || defined(__powerpc__) || defined(__arm__) || \
++ defined(__sparc__) || defined(__mips__) || defined(__sh__) || \
++ defined(__XTENSA__) || \
++ (defined(__SIZEOF_LONG__) && __SIZEOF_LONG__ == 4) || \
++ (defined(__LONG_MAX__) && __LONG_MAX__ == 2147483647L))
++# define CURL_TYPEOF_CURL_OFF_T long long
++# define CURL_FORMAT_CURL_OFF_T "lld"
++# define CURL_FORMAT_CURL_OFF_TU "llu"
++# define CURL_SUFFIX_CURL_OFF_T LL
++# define CURL_SUFFIX_CURL_OFF_TU ULL
++# elif defined(__LP64__) || \
++ defined(__x86_64__) || defined(__ppc64__) || defined(__sparc64__) || \
++ (defined(__SIZEOF_LONG__) && __SIZEOF_LONG__ == 8) || \
++ (defined(__LONG_MAX__) && __LONG_MAX__ == 9223372036854775807L)
++# define CURL_TYPEOF_CURL_OFF_T long
++# define CURL_FORMAT_CURL_OFF_T "ld"
++# define CURL_FORMAT_CURL_OFF_TU "lu"
++# define CURL_SUFFIX_CURL_OFF_T L
++# define CURL_SUFFIX_CURL_OFF_TU UL
++# endif
++# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
++# define CURL_PULL_SYS_TYPES_H 1
++# define CURL_PULL_SYS_SOCKET_H 1
++
++#else
++/* generic "safe guess" on old 32 bit style */
++# define CURL_TYPEOF_CURL_OFF_T long
++# define CURL_FORMAT_CURL_OFF_T "ld"
++# define CURL_FORMAT_CURL_OFF_TU "lu"
++# define CURL_SUFFIX_CURL_OFF_T L
++# define CURL_SUFFIX_CURL_OFF_TU UL
++# define CURL_TYPEOF_CURL_SOCKLEN_T int
++#endif
++
++#ifdef _AIX
++/* AIX needs <sys/poll.h> */
++#define CURL_PULL_SYS_POLL_H
++#endif
++
++
++/* CURL_PULL_WS2TCPIP_H is defined above when inclusion of header file */
++/* ws2tcpip.h is required here to properly make type definitions below. */
++#ifdef CURL_PULL_WS2TCPIP_H
++# include <winsock2.h>
++# include <windows.h>
++# include <ws2tcpip.h>
++#endif
++
++/* CURL_PULL_SYS_TYPES_H is defined above when inclusion of header file */
++/* sys/types.h is required here to properly make type definitions below. */
++#ifdef CURL_PULL_SYS_TYPES_H
++# include <sys/types.h>
++#endif
++
++/* CURL_PULL_SYS_SOCKET_H is defined above when inclusion of header file */
++/* sys/socket.h is required here to properly make type definitions below. */
++#ifdef CURL_PULL_SYS_SOCKET_H
++# include <sys/socket.h>
++#endif
++
++/* CURL_PULL_SYS_POLL_H is defined above when inclusion of header file */
++/* sys/poll.h is required here to properly make type definitions below. */
++#ifdef CURL_PULL_SYS_POLL_H
++# include <sys/poll.h>
++#endif
++
++/* Data type definition of curl_socklen_t. */
++#ifdef CURL_TYPEOF_CURL_SOCKLEN_T
++ typedef CURL_TYPEOF_CURL_SOCKLEN_T curl_socklen_t;
++#endif
++
++/* Data type definition of curl_off_t. */
++
++#ifdef CURL_TYPEOF_CURL_OFF_T
++ typedef CURL_TYPEOF_CURL_OFF_T curl_off_t;
++#endif
++
++/*
++ * CURL_ISOCPP and CURL_OFF_T_C definitions are done here in order to allow
++ * these to be visible and exported by the external libcurl interface API,
++ * while also making them visible to the library internals, simply including
++ * curl_setup.h, without actually needing to include curl.h internally.
++ * If some day this section would grow big enough, all this should be moved
++ * to its own header file.
++ */
++
++/*
++ * Figure out if we can use the ## preprocessor operator, which is supported
++ * by ISO/ANSI C and C++. Some compilers support it without setting __STDC__
++ * or __cplusplus so we need to carefully check for them too.
++ */
++
++#if defined(__STDC__) || defined(_MSC_VER) || defined(__cplusplus) || \
++ defined(__HP_aCC) || defined(__BORLANDC__) || defined(__LCC__) || \
++ defined(__POCC__) || defined(__SALFORDC__) || defined(__HIGHC__) || \
++ defined(__ILEC400__)
++ /* This compiler is believed to have an ISO compatible preprocessor */
++#define CURL_ISOCPP
++#else
++ /* This compiler is believed NOT to have an ISO compatible preprocessor */
++#undef CURL_ISOCPP
++#endif
++
++/*
++ * Macros for minimum-width signed and unsigned curl_off_t integer constants.
++ */
++
++#if defined(__BORLANDC__) && (__BORLANDC__ == 0x0551)
++# define __CURL_OFF_T_C_HLPR2(x) x
++# define __CURL_OFF_T_C_HLPR1(x) __CURL_OFF_T_C_HLPR2(x)
++# define CURL_OFF_T_C(Val) __CURL_OFF_T_C_HLPR1(Val) ## \
++ __CURL_OFF_T_C_HLPR1(CURL_SUFFIX_CURL_OFF_T)
++# define CURL_OFF_TU_C(Val) __CURL_OFF_T_C_HLPR1(Val) ## \
++ __CURL_OFF_T_C_HLPR1(CURL_SUFFIX_CURL_OFF_TU)
++#else
++# ifdef CURL_ISOCPP
++# define __CURL_OFF_T_C_HLPR2(Val,Suffix) Val ## Suffix
++# else
++# define __CURL_OFF_T_C_HLPR2(Val,Suffix) Val/**/Suffix
++# endif
++# define __CURL_OFF_T_C_HLPR1(Val,Suffix) __CURL_OFF_T_C_HLPR2(Val,Suffix)
++# define CURL_OFF_T_C(Val) __CURL_OFF_T_C_HLPR1(Val,CURL_SUFFIX_CURL_OFF_T)
++# define CURL_OFF_TU_C(Val) __CURL_OFF_T_C_HLPR1(Val,CURL_SUFFIX_CURL_OFF_TU)
++#endif
++
++#endif /* __CURL_SYSTEM_H */
+diff --git a/src/third_party/curl/typecheck-gcc.h b/src/third_party/curl/typecheck-gcc.h
+--- a/src/third_party/curl/typecheck-gcc.h
++++ b/src/third_party/curl/typecheck-gcc.h
+@@ -2,111 +2,151 @@
+ #define __CURL_TYPECHECK_GCC_H
+ /***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+- * Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
++ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+- * are also available at http://curl.haxx.se/docs/copyright.html.
++ * are also available at https://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+- * $Id: typecheck-gcc.h,v 1.9 2009-01-25 23:26:31 bagder Exp $
+ ***************************************************************************/
+
+ /* wraps curl_easy_setopt() with typechecking */
+
+ /* To add a new kind of warning, add an
+- * if(_curl_is_sometype_option(_curl_opt) && ! _curl_is_sometype(value))
+- * _curl_easy_setopt_err_sometype();
++ * if(_curl_is_sometype_option(_curl_opt))
++ * if(!_curl_is_sometype(value))
++ * _curl_easy_setopt_err_sometype();
+ * block and define _curl_is_sometype_option, _curl_is_sometype and
+ * _curl_easy_setopt_err_sometype below
+ *
++ * NOTE: We use two nested 'if' statements here instead of the && operator, in
++ * order to work around gcc bug #32061. It affects only gcc 4.3.x/4.4.x
++ * when compiling with -Wlogical-op.
++ *
+ * To add an option that uses the same type as an existing option, you'll just
+ * need to extend the appropriate _curl_*_option macro
+ */
+ #define curl_easy_setopt(handle, option, value) \
+ __extension__ ({ \
+- __typeof__ (option) _curl_opt = option; \
+- if (__builtin_constant_p(_curl_opt)) { \
+- if (_curl_is_long_option(_curl_opt) && !_curl_is_long(value)) \
+- _curl_easy_setopt_err_long(); \
+- if (_curl_is_off_t_option(_curl_opt) && !_curl_is_off_t(value)) \
+- _curl_easy_setopt_err_curl_off_t(); \
+- if (_curl_is_string_option(_curl_opt) && !_curl_is_string(value)) \
+- _curl_easy_setopt_err_string(); \
+- if (_curl_is_write_cb_option(_curl_opt) && !_curl_is_write_cb(value)) \
+- _curl_easy_setopt_err_write_callback(); \
+- if ((_curl_opt) == CURLOPT_READFUNCTION && !_curl_is_read_cb(value)) \
+- _curl_easy_setopt_err_read_cb(); \
+- if ((_curl_opt) == CURLOPT_IOCTLFUNCTION && !_curl_is_ioctl_cb(value)) \
+- _curl_easy_setopt_err_ioctl_cb(); \
+- if ((_curl_opt) == CURLOPT_SOCKOPTFUNCTION && !_curl_is_sockopt_cb(value))\
+- _curl_easy_setopt_err_sockopt_cb(); \
+- if ((_curl_opt) == CURLOPT_OPENSOCKETFUNCTION && \
+- !_curl_is_opensocket_cb(value)) \
+- _curl_easy_setopt_err_opensocket_cb(); \
+- if ((_curl_opt) == CURLOPT_PROGRESSFUNCTION && \
+- !_curl_is_progress_cb(value)) \
+- _curl_easy_setopt_err_progress_cb(); \
+- if ((_curl_opt) == CURLOPT_DEBUGFUNCTION && !_curl_is_debug_cb(value)) \
+- _curl_easy_setopt_err_debug_cb(); \
+- if ((_curl_opt) == CURLOPT_SSL_CTX_FUNCTION && \
+- !_curl_is_ssl_ctx_cb(value)) \
+- _curl_easy_setopt_err_ssl_ctx_cb(); \
+- if (_curl_is_conv_cb_option(_curl_opt) && !_curl_is_conv_cb(value)) \
+- _curl_easy_setopt_err_conv_cb(); \
+- if ((_curl_opt) == CURLOPT_SEEKFUNCTION && !_curl_is_seek_cb(value)) \
+- _curl_easy_setopt_err_seek_cb(); \
+- if (_curl_is_cb_data_option(_curl_opt) && !_curl_is_cb_data(value)) \
+- _curl_easy_setopt_err_cb_data(); \
+- if ((_curl_opt) == CURLOPT_ERRORBUFFER && !_curl_is_error_buffer(value)) \
+- _curl_easy_setopt_err_error_buffer(); \
+- if ((_curl_opt) == CURLOPT_STDERR && !_curl_is_FILE(value)) \
+- _curl_easy_setopt_err_FILE(); \
+- if (_curl_is_postfields_option(_curl_opt) && !_curl_is_postfields(value)) \
+- _curl_easy_setopt_err_postfields(); \
+- if ((_curl_opt) == CURLOPT_HTTPPOST && \
+- !_curl_is_arr((value), struct curl_httppost)) \
+- _curl_easy_setopt_err_curl_httpost(); \
+- if (_curl_is_slist_option(_curl_opt) && \
+- !_curl_is_arr((value), struct curl_slist)) \
+- _curl_easy_setopt_err_curl_slist(); \
+- if ((_curl_opt) == CURLOPT_SHARE && !_curl_is_ptr((value), CURLSH)) \
+- _curl_easy_setopt_err_CURLSH(); \
++ __typeof__(option) _curl_opt = option; \
++ if(__builtin_constant_p(_curl_opt)) { \
++ if(_curl_is_long_option(_curl_opt)) \
++ if(!_curl_is_long(value)) \
++ _curl_easy_setopt_err_long(); \
++ if(_curl_is_off_t_option(_curl_opt)) \
++ if(!_curl_is_off_t(value)) \
++ _curl_easy_setopt_err_curl_off_t(); \
++ if(_curl_is_string_option(_curl_opt)) \
++ if(!_curl_is_string(value)) \
++ _curl_easy_setopt_err_string(); \
++ if(_curl_is_write_cb_option(_curl_opt)) \
++ if(!_curl_is_write_cb(value)) \
++ _curl_easy_setopt_err_write_callback(); \
++ if((_curl_opt) == CURLOPT_RESOLVER_START_FUNCTION) \
++ if(!_curl_is_resolver_start_callback(value)) \
++ _curl_easy_setopt_err_resolver_start_callback(); \
++ if((_curl_opt) == CURLOPT_READFUNCTION) \
++ if(!_curl_is_read_cb(value)) \
++ _curl_easy_setopt_err_read_cb(); \
++ if((_curl_opt) == CURLOPT_IOCTLFUNCTION) \
++ if(!_curl_is_ioctl_cb(value)) \
++ _curl_easy_setopt_err_ioctl_cb(); \
++ if((_curl_opt) == CURLOPT_SOCKOPTFUNCTION) \
++ if(!_curl_is_sockopt_cb(value)) \
++ _curl_easy_setopt_err_sockopt_cb(); \
++ if((_curl_opt) == CURLOPT_OPENSOCKETFUNCTION) \
++ if(!_curl_is_opensocket_cb(value)) \
++ _curl_easy_setopt_err_opensocket_cb(); \
++ if((_curl_opt) == CURLOPT_PROGRESSFUNCTION) \
++ if(!_curl_is_progress_cb(value)) \
++ _curl_easy_setopt_err_progress_cb(); \
++ if((_curl_opt) == CURLOPT_DEBUGFUNCTION) \
++ if(!_curl_is_debug_cb(value)) \
++ _curl_easy_setopt_err_debug_cb(); \
++ if((_curl_opt) == CURLOPT_SSL_CTX_FUNCTION) \
++ if(!_curl_is_ssl_ctx_cb(value)) \
++ _curl_easy_setopt_err_ssl_ctx_cb(); \
++ if(_curl_is_conv_cb_option(_curl_opt)) \
++ if(!_curl_is_conv_cb(value)) \
++ _curl_easy_setopt_err_conv_cb(); \
++ if((_curl_opt) == CURLOPT_SEEKFUNCTION) \
++ if(!_curl_is_seek_cb(value)) \
++ _curl_easy_setopt_err_seek_cb(); \
++ if(_curl_is_cb_data_option(_curl_opt)) \
++ if(!_curl_is_cb_data(value)) \
++ _curl_easy_setopt_err_cb_data(); \
++ if((_curl_opt) == CURLOPT_ERRORBUFFER) \
++ if(!_curl_is_error_buffer(value)) \
++ _curl_easy_setopt_err_error_buffer(); \
++ if((_curl_opt) == CURLOPT_STDERR) \
++ if(!_curl_is_FILE(value)) \
++ _curl_easy_setopt_err_FILE(); \
++ if(_curl_is_postfields_option(_curl_opt)) \
++ if(!_curl_is_postfields(value)) \
++ _curl_easy_setopt_err_postfields(); \
++ if((_curl_opt) == CURLOPT_HTTPPOST) \
++ if(!_curl_is_arr((value), struct curl_httppost)) \
++ _curl_easy_setopt_err_curl_httpost(); \
++ if((_curl_opt) == CURLOPT_MIMEPOST) \
++ if(!_curl_is_ptr((value), curl_mime)) \
++ _curl_easy_setopt_err_curl_mimepost(); \
++ if(_curl_is_slist_option(_curl_opt)) \
++ if(!_curl_is_arr((value), struct curl_slist)) \
++ _curl_easy_setopt_err_curl_slist(); \
++ if((_curl_opt) == CURLOPT_SHARE) \
++ if(!_curl_is_ptr((value), CURLSH)) \
++ _curl_easy_setopt_err_CURLSH(); \
+ } \
+ curl_easy_setopt(handle, _curl_opt, value); \
+ })
+
+ /* wraps curl_easy_getinfo() with typechecking */
+ /* FIXME: don't allow const pointers */
+ #define curl_easy_getinfo(handle, info, arg) \
+ __extension__ ({ \
+- __typeof__ (info) _curl_info = info; \
+- if (__builtin_constant_p(_curl_info)) { \
+- if (_curl_is_string_info(_curl_info) && !_curl_is_arr((arg), char *)) \
+- _curl_easy_getinfo_err_string(); \
+- if (_curl_is_long_info(_curl_info) && !_curl_is_arr((arg), long)) \
+- _curl_easy_getinfo_err_long(); \
+- if (_curl_is_double_info(_curl_info) && !_curl_is_arr((arg), double)) \
+- _curl_easy_getinfo_err_double(); \
+- if (_curl_is_slist_info(_curl_info) && \
+- !_curl_is_arr((arg), struct curl_slist *)) \
+- _curl_easy_getinfo_err_curl_slist(); \
++ __typeof__(info) _curl_info = info; \
++ if(__builtin_constant_p(_curl_info)) { \
++ if(_curl_is_string_info(_curl_info)) \
++ if(!_curl_is_arr((arg), char *)) \
++ _curl_easy_getinfo_err_string(); \
++ if(_curl_is_long_info(_curl_info)) \
++ if(!_curl_is_arr((arg), long)) \
++ _curl_easy_getinfo_err_long(); \
++ if(_curl_is_double_info(_curl_info)) \
++ if(!_curl_is_arr((arg), double)) \
++ _curl_easy_getinfo_err_double(); \
++ if(_curl_is_slist_info(_curl_info)) \
++ if(!_curl_is_arr((arg), struct curl_slist *)) \
++ _curl_easy_getinfo_err_curl_slist(); \
++ if(_curl_is_tlssessioninfo_info(_curl_info)) \
++ if(!_curl_is_arr((arg), struct curl_tlssessioninfo *)) \
++ _curl_easy_getinfo_err_curl_tlssesssioninfo(); \
++ if(_curl_is_certinfo_info(_curl_info)) \
++ if(!_curl_is_arr((arg), struct curl_certinfo *)) \
++ _curl_easy_getinfo_err_curl_certinfo(); \
++ if(_curl_is_socket_info(_curl_info)) \
++ if(!_curl_is_arr((arg), curl_socket_t)) \
++ _curl_easy_getinfo_err_curl_socket(); \
++ if(_curl_is_off_t_info(_curl_info)) \
++ if(!_curl_is_arr((arg), curl_off_t)) \
++ _curl_easy_getinfo_err_curl_off_t(); \
+ } \
+ curl_easy_getinfo(handle, _curl_info, arg); \
+ })
+
+ /* TODO: typechecking for curl_share_setopt() and curl_multi_setopt(),
+ * for now just make sure that the functions are called with three
+ * arguments
+ */
+@@ -114,70 +154,93 @@
+ #define curl_multi_setopt(handle,opt,param) curl_multi_setopt(handle,opt,param)
+
+
+ /* the actual warnings, triggered by calling the _curl_easy_setopt_err*
+ * functions */
+
+ /* To define a new warning, use _CURL_WARNING(identifier, "message") */
+ #define _CURL_WARNING(id, message) \
+- static void __attribute__((warning(message))) __attribute__((unused)) \
+- __attribute__((noinline)) id(void) { __asm__(""); }
++ static void __attribute__((__warning__(message))) \
++ __attribute__((__unused__)) __attribute__((__noinline__)) \
++ id(void) { __asm__(""); }
+
+ _CURL_WARNING(_curl_easy_setopt_err_long,
+ "curl_easy_setopt expects a long argument for this option")
+ _CURL_WARNING(_curl_easy_setopt_err_curl_off_t,
+ "curl_easy_setopt expects a curl_off_t argument for this option")
+ _CURL_WARNING(_curl_easy_setopt_err_string,
+- "curl_easy_setopt expects a string (char* or char[]) argument for this option"
++ "curl_easy_setopt expects a "
++ "string ('char *' or char[]) argument for this option"
+ )
+ _CURL_WARNING(_curl_easy_setopt_err_write_callback,
+ "curl_easy_setopt expects a curl_write_callback argument for this option")
++_CURL_WARNING(_curl_easy_setopt_err_resolver_start_callback,
++ "curl_easy_setopt expects a "
++ "curl_resolver_start_callback argument for this option"
++ )
+ _CURL_WARNING(_curl_easy_setopt_err_read_cb,
+ "curl_easy_setopt expects a curl_read_callback argument for this option")
+ _CURL_WARNING(_curl_easy_setopt_err_ioctl_cb,
+ "curl_easy_setopt expects a curl_ioctl_callback argument for this option")
+ _CURL_WARNING(_curl_easy_setopt_err_sockopt_cb,
+ "curl_easy_setopt expects a curl_sockopt_callback argument for this option")
+ _CURL_WARNING(_curl_easy_setopt_err_opensocket_cb,
+- "curl_easy_setopt expects a curl_opensocket_callback argument for this option"
++ "curl_easy_setopt expects a "
++ "curl_opensocket_callback argument for this option"
+ )
+ _CURL_WARNING(_curl_easy_setopt_err_progress_cb,
+ "curl_easy_setopt expects a curl_progress_callback argument for this option")
+ _CURL_WARNING(_curl_easy_setopt_err_debug_cb,
+ "curl_easy_setopt expects a curl_debug_callback argument for this option")
+ _CURL_WARNING(_curl_easy_setopt_err_ssl_ctx_cb,
+ "curl_easy_setopt expects a curl_ssl_ctx_callback argument for this option")
+ _CURL_WARNING(_curl_easy_setopt_err_conv_cb,
+ "curl_easy_setopt expects a curl_conv_callback argument for this option")
+ _CURL_WARNING(_curl_easy_setopt_err_seek_cb,
+ "curl_easy_setopt expects a curl_seek_callback argument for this option")
+ _CURL_WARNING(_curl_easy_setopt_err_cb_data,
+- "curl_easy_setopt expects a private data pointer as argument for this option")
++ "curl_easy_setopt expects a "
++ "private data pointer as argument for this option")
+ _CURL_WARNING(_curl_easy_setopt_err_error_buffer,
+- "curl_easy_setopt expects a char buffer of CURL_ERROR_SIZE as argument for this option")
++ "curl_easy_setopt expects a "
++ "char buffer of CURL_ERROR_SIZE as argument for this option")
+ _CURL_WARNING(_curl_easy_setopt_err_FILE,
+- "curl_easy_setopt expects a FILE* argument for this option")
++ "curl_easy_setopt expects a 'FILE *' argument for this option")
+ _CURL_WARNING(_curl_easy_setopt_err_postfields,
+- "curl_easy_setopt expects a void* or char* argument for this option")
++ "curl_easy_setopt expects a 'void *' or 'char *' argument for this option")
+ _CURL_WARNING(_curl_easy_setopt_err_curl_httpost,
+- "curl_easy_setopt expects a struct curl_httppost* argument for this option")
++ "curl_easy_setopt expects a 'struct curl_httppost *' "
++ "argument for this option")
++_CURL_WARNING(_curl_easy_setopt_err_curl_mimepost,
++ "curl_easy_setopt expects a 'curl_mime *' "
++ "argument for this option")
+ _CURL_WARNING(_curl_easy_setopt_err_curl_slist,
+- "curl_easy_setopt expects a struct curl_slist* argument for this option")
++ "curl_easy_setopt expects a 'struct curl_slist *' argument for this option")
+ _CURL_WARNING(_curl_easy_setopt_err_CURLSH,
+ "curl_easy_setopt expects a CURLSH* argument for this option")
+
+ _CURL_WARNING(_curl_easy_getinfo_err_string,
+- "curl_easy_getinfo expects a pointer to char * for this info")
++ "curl_easy_getinfo expects a pointer to 'char *' for this info")
+ _CURL_WARNING(_curl_easy_getinfo_err_long,
+ "curl_easy_getinfo expects a pointer to long for this info")
+ _CURL_WARNING(_curl_easy_getinfo_err_double,
+ "curl_easy_getinfo expects a pointer to double for this info")
+ _CURL_WARNING(_curl_easy_getinfo_err_curl_slist,
+- "curl_easy_getinfo expects a pointer to struct curl_slist * for this info")
++ "curl_easy_getinfo expects a pointer to 'struct curl_slist *' for this info")
++_CURL_WARNING(_curl_easy_getinfo_err_curl_tlssesssioninfo,
++ "curl_easy_getinfo expects a pointer to "
++ "'struct curl_tlssessioninfo *' for this info")
++_CURL_WARNING(_curl_easy_getinfo_err_curl_certinfo,
++ "curl_easy_getinfo expects a pointer to "
++ "'struct curl_certinfo *' for this info")
++_CURL_WARNING(_curl_easy_getinfo_err_curl_socket,
++ "curl_easy_getinfo expects a pointer to curl_socket_t for this info")
++_CURL_WARNING(_curl_easy_getinfo_err_curl_off_t,
++ "curl_easy_getinfo expects a pointer to curl_off_t for this info")
+
+ /* groups of curl_easy_setops options that take the same type of argument */
+
+ /* To add a new option to one of the groups, just add
+ * (option) == CURLOPT_SOMETHING
+ * to the or-expression. If the option takes a long or curl_off_t, you don't
+ * have to do anything
+ */
+@@ -186,97 +249,145 @@
+ #define _curl_is_long_option(option) \
+ (0 < (option) && (option) < CURLOPTTYPE_OBJECTPOINT)
+
+ #define _curl_is_off_t_option(option) \
+ ((option) > CURLOPTTYPE_OFF_T)
+
+ /* evaluates to true if option takes a char* argument */
+ #define _curl_is_string_option(option) \
+- ((option) == CURLOPT_URL || \
+- (option) == CURLOPT_PROXY || \
+- (option) == CURLOPT_INTERFACE || \
+- (option) == CURLOPT_NETRC_FILE || \
+- (option) == CURLOPT_USERPWD || \
+- (option) == CURLOPT_USERNAME || \
+- (option) == CURLOPT_PASSWORD || \
+- (option) == CURLOPT_PROXYUSERPWD || \
+- (option) == CURLOPT_PROXYUSERNAME || \
+- (option) == CURLOPT_PROXYPASSWORD || \
+- (option) == CURLOPT_NOPROXY || \
+- (option) == CURLOPT_ENCODING || \
+- (option) == CURLOPT_REFERER || \
+- (option) == CURLOPT_USERAGENT || \
++ ((option) == CURLOPT_ABSTRACT_UNIX_SOCKET || \
++ (option) == CURLOPT_ACCEPT_ENCODING || \
++ (option) == CURLOPT_ALTSVC || \
++ (option) == CURLOPT_CAINFO || \
++ (option) == CURLOPT_CAPATH || \
+ (option) == CURLOPT_COOKIE || \
+ (option) == CURLOPT_COOKIEFILE || \
+ (option) == CURLOPT_COOKIEJAR || \
+ (option) == CURLOPT_COOKIELIST || \
++ (option) == CURLOPT_CRLFILE || \
++ (option) == CURLOPT_CUSTOMREQUEST || \
++ (option) == CURLOPT_DEFAULT_PROTOCOL || \
++ (option) == CURLOPT_DNS_INTERFACE || \
++ (option) == CURLOPT_DNS_LOCAL_IP4 || \
++ (option) == CURLOPT_DNS_LOCAL_IP6 || \
++ (option) == CURLOPT_DNS_SERVERS || \
++ (option) == CURLOPT_DOH_URL || \
++ (option) == CURLOPT_EGDSOCKET || \
+ (option) == CURLOPT_FTPPORT || \
+- (option) == CURLOPT_FTP_ALTERNATIVE_TO_USER || \
+ (option) == CURLOPT_FTP_ACCOUNT || \
++ (option) == CURLOPT_FTP_ALTERNATIVE_TO_USER || \
++ (option) == CURLOPT_INTERFACE || \
++ (option) == CURLOPT_ISSUERCERT || \
++ (option) == CURLOPT_KEYPASSWD || \
++ (option) == CURLOPT_KRBLEVEL || \
++ (option) == CURLOPT_LOGIN_OPTIONS || \
++ (option) == CURLOPT_MAIL_AUTH || \
++ (option) == CURLOPT_MAIL_FROM || \
++ (option) == CURLOPT_NETRC_FILE || \
++ (option) == CURLOPT_NOPROXY || \
++ (option) == CURLOPT_PASSWORD || \
++ (option) == CURLOPT_PINNEDPUBLICKEY || \
++ (option) == CURLOPT_PRE_PROXY || \
++ (option) == CURLOPT_PROXY || \
++ (option) == CURLOPT_PROXYPASSWORD || \
++ (option) == CURLOPT_PROXYUSERNAME || \
++ (option) == CURLOPT_PROXYUSERPWD || \
++ (option) == CURLOPT_PROXY_CAINFO || \
++ (option) == CURLOPT_PROXY_CAPATH || \
++ (option) == CURLOPT_PROXY_CRLFILE || \
++ (option) == CURLOPT_PROXY_KEYPASSWD || \
++ (option) == CURLOPT_PROXY_PINNEDPUBLICKEY || \
++ (option) == CURLOPT_PROXY_SERVICE_NAME || \
++ (option) == CURLOPT_PROXY_SSLCERT || \
++ (option) == CURLOPT_PROXY_SSLCERTTYPE || \
++ (option) == CURLOPT_PROXY_SSLKEY || \
++ (option) == CURLOPT_PROXY_SSLKEYTYPE || \
++ (option) == CURLOPT_PROXY_SSL_CIPHER_LIST || \
++ (option) == CURLOPT_PROXY_TLSAUTH_PASSWORD || \
++ (option) == CURLOPT_PROXY_TLSAUTH_USERNAME || \
++ (option) == CURLOPT_PROXY_TLSAUTH_TYPE || \
++ (option) == CURLOPT_RANDOM_FILE || \
+ (option) == CURLOPT_RANGE || \
+- (option) == CURLOPT_CUSTOMREQUEST || \
++ (option) == CURLOPT_REFERER || \
++ (option) == CURLOPT_RTSP_SESSION_ID || \
++ (option) == CURLOPT_RTSP_STREAM_URI || \
++ (option) == CURLOPT_RTSP_TRANSPORT || \
++ (option) == CURLOPT_SERVICE_NAME || \
++ (option) == CURLOPT_SOCKS5_GSSAPI_SERVICE || \
++ (option) == CURLOPT_SSH_HOST_PUBLIC_KEY_MD5 || \
++ (option) == CURLOPT_SSH_KNOWNHOSTS || \
++ (option) == CURLOPT_SSH_PRIVATE_KEYFILE || \
++ (option) == CURLOPT_SSH_PUBLIC_KEYFILE || \
+ (option) == CURLOPT_SSLCERT || \
+ (option) == CURLOPT_SSLCERTTYPE || \
++ (option) == CURLOPT_SSLENGINE || \
+ (option) == CURLOPT_SSLKEY || \
+ (option) == CURLOPT_SSLKEYTYPE || \
+- (option) == CURLOPT_KEYPASSWD || \
+- (option) == CURLOPT_SSLENGINE || \
+- (option) == CURLOPT_CAINFO || \
+- (option) == CURLOPT_CAPATH || \
+- (option) == CURLOPT_RANDOM_FILE || \
+- (option) == CURLOPT_EGDSOCKET || \
+ (option) == CURLOPT_SSL_CIPHER_LIST || \
+- (option) == CURLOPT_KRBLEVEL || \
+- (option) == CURLOPT_SSH_HOST_PUBLIC_KEY_MD5 || \
+- (option) == CURLOPT_SSH_PUBLIC_KEYFILE || \
+- (option) == CURLOPT_SSH_PRIVATE_KEYFILE || \
+- (option) == CURLOPT_CRLFILE || \
+- (option) == CURLOPT_ISSUERCERT || \
++ (option) == CURLOPT_TLSAUTH_PASSWORD || \
++ (option) == CURLOPT_TLSAUTH_TYPE || \
++ (option) == CURLOPT_TLSAUTH_USERNAME || \
++ (option) == CURLOPT_UNIX_SOCKET_PATH || \
++ (option) == CURLOPT_URL || \
++ (option) == CURLOPT_USERAGENT || \
++ (option) == CURLOPT_USERNAME || \
++ (option) == CURLOPT_USERPWD || \
++ (option) == CURLOPT_XOAUTH2_BEARER || \
+ 0)
+
+ /* evaluates to true if option takes a curl_write_callback argument */
+ #define _curl_is_write_cb_option(option) \
+ ((option) == CURLOPT_HEADERFUNCTION || \
+ (option) == CURLOPT_WRITEFUNCTION)
+
+ /* evaluates to true if option takes a curl_conv_callback argument */
+ #define _curl_is_conv_cb_option(option) \
+ ((option) == CURLOPT_CONV_TO_NETWORK_FUNCTION || \
+ (option) == CURLOPT_CONV_FROM_NETWORK_FUNCTION || \
+ (option) == CURLOPT_CONV_FROM_UTF8_FUNCTION)
+
+ /* evaluates to true if option takes a data argument to pass to a callback */
+ #define _curl_is_cb_data_option(option) \
+- ((option) == CURLOPT_WRITEDATA || \
+- (option) == CURLOPT_READDATA || \
++ ((option) == CURLOPT_CHUNK_DATA || \
++ (option) == CURLOPT_CLOSESOCKETDATA || \
++ (option) == CURLOPT_DEBUGDATA || \
++ (option) == CURLOPT_FNMATCH_DATA || \
++ (option) == CURLOPT_HEADERDATA || \
++ (option) == CURLOPT_INTERLEAVEDATA || \
+ (option) == CURLOPT_IOCTLDATA || \
+- (option) == CURLOPT_SOCKOPTDATA || \
+ (option) == CURLOPT_OPENSOCKETDATA || \
++ (option) == CURLOPT_PRIVATE || \
+ (option) == CURLOPT_PROGRESSDATA || \
+- (option) == CURLOPT_WRITEHEADER || \
+- (option) == CURLOPT_DEBUGDATA || \
++ (option) == CURLOPT_READDATA || \
++ (option) == CURLOPT_SEEKDATA || \
++ (option) == CURLOPT_SOCKOPTDATA || \
++ (option) == CURLOPT_SSH_KEYDATA || \
+ (option) == CURLOPT_SSL_CTX_DATA || \
+- (option) == CURLOPT_SEEKDATA || \
+- (option) == CURLOPT_PRIVATE || \
++ (option) == CURLOPT_WRITEDATA || \
++ (option) == CURLOPT_RESOLVER_START_DATA || \
++ (option) == CURLOPT_CURLU || \
+ 0)
+
+ /* evaluates to true if option takes a POST data argument (void* or char*) */
+ #define _curl_is_postfields_option(option) \
+ ((option) == CURLOPT_POSTFIELDS || \
+ (option) == CURLOPT_COPYPOSTFIELDS || \
+ 0)
+
+ /* evaluates to true if option takes a struct curl_slist * argument */
+ #define _curl_is_slist_option(option) \
+- ((option) == CURLOPT_HTTPHEADER || \
+- (option) == CURLOPT_HTTP200ALIASES || \
+- (option) == CURLOPT_QUOTE || \
++ ((option) == CURLOPT_HTTP200ALIASES || \
++ (option) == CURLOPT_HTTPHEADER || \
++ (option) == CURLOPT_MAIL_RCPT || \
+ (option) == CURLOPT_POSTQUOTE || \
+ (option) == CURLOPT_PREQUOTE || \
++ (option) == CURLOPT_PROXYHEADER || \
++ (option) == CURLOPT_QUOTE || \
++ (option) == CURLOPT_RESOLVE || \
+ (option) == CURLOPT_TELNETOPTIONS || \
+ 0)
+
+ /* groups of curl_easy_getinfo infos that take the same type of argument */
+
+ /* evaluates to true if info expects a pointer to char * argument */
+ #define _curl_is_string_info(info) \
+ (CURLINFO_STRING < (info) && (info) < CURLINFO_LONG)
+@@ -285,34 +396,49 @@
+ #define _curl_is_long_info(info) \
+ (CURLINFO_LONG < (info) && (info) < CURLINFO_DOUBLE)
+
+ /* evaluates to true if info expects a pointer to double argument */
+ #define _curl_is_double_info(info) \
+ (CURLINFO_DOUBLE < (info) && (info) < CURLINFO_SLIST)
+
+ /* true if info expects a pointer to struct curl_slist * argument */
+-#define _curl_is_slist_info(info) \
+- (CURLINFO_SLIST < (info))
++#define _curl_is_slist_info(info) \
++ (((info) == CURLINFO_SSL_ENGINES) || ((info) == CURLINFO_COOKIELIST))
++
++/* true if info expects a pointer to struct curl_tlssessioninfo * argument */
++#define _curl_is_tlssessioninfo_info(info) \
++ (((info) == CURLINFO_TLS_SSL_PTR) || ((info) == CURLINFO_TLS_SESSION))
++
++/* true if info expects a pointer to struct curl_certinfo * argument */
++#define _curl_is_certinfo_info(info) ((info) == CURLINFO_CERTINFO)
++
++/* true if info expects a pointer to struct curl_socket_t argument */
++#define _curl_is_socket_info(info) \
++ (CURLINFO_SOCKET < (info) && (info) < CURLINFO_OFF_T)
++
++/* true if info expects a pointer to curl_off_t argument */
++#define _curl_is_off_t_info(info) \
++ (CURLINFO_OFF_T < (info))
+
+
+ /* typecheck helpers -- check whether given expression has requested type*/
+
+ /* For pointers, you can use the _curl_is_ptr/_curl_is_arr macros,
+ * otherwise define a new macro. Search for __builtin_types_compatible_p
+ * in the GCC manual.
+ * NOTE: these macros MUST NOT EVALUATE their arguments! The argument is
+ * the actual expression passed to the curl_easy_setopt macro. This
+ * means that you can only apply the sizeof and __typeof__ operators, no
+ * == or whatsoever.
+ */
+
+-/* XXX: should evaluate to true iff expr is a pointer */
++/* XXX: should evaluate to true if expr is a pointer */
+ #define _curl_is_any_ptr(expr) \
+- (sizeof(expr) == sizeof(void*))
++ (sizeof(expr) == sizeof(void *))
+
+ /* evaluates to true if expr is NULL */
+ /* XXX: must not evaluate expr, so this check is not accurate */
+ #define _curl_is_NULL(expr) \
+ (__builtin_types_compatible_p(__typeof__(expr), __typeof__(NULL)))
+
+ /* evaluates to true if expr is type*, const type* or NULL */
+ #define _curl_is_ptr(expr, type) \
+@@ -350,202 +476,225 @@
+
+ /* evaluates to true if expr is of type curl_off_t */
+ #define _curl_is_off_t(expr) \
+ (__builtin_types_compatible_p(__typeof__(expr), curl_off_t))
+
+ /* evaluates to true if expr is abuffer suitable for CURLOPT_ERRORBUFFER */
+ /* XXX: also check size of an char[] array? */
+ #define _curl_is_error_buffer(expr) \
+- (__builtin_types_compatible_p(__typeof__(expr), char *) || \
++ (_curl_is_NULL(expr) || \
++ __builtin_types_compatible_p(__typeof__(expr), char *) || \
+ __builtin_types_compatible_p(__typeof__(expr), char[]))
+
+ /* evaluates to true if expr is of type (const) void* or (const) FILE* */
+ #if 0
+ #define _curl_is_cb_data(expr) \
+ (_curl_is_ptr((expr), void) || \
+ _curl_is_ptr((expr), FILE))
+ #else /* be less strict */
+ #define _curl_is_cb_data(expr) \
+ _curl_is_any_ptr(expr)
+ #endif
+
+ /* evaluates to true if expr is of type FILE* */
+-#define _curl_is_FILE(expr) \
+- (__builtin_types_compatible_p(__typeof__(expr), FILE *))
++#define _curl_is_FILE(expr) \
++ (_curl_is_NULL(expr) || \
++ (__builtin_types_compatible_p(__typeof__(expr), FILE *)))
+
+ /* evaluates to true if expr can be passed as POST data (void* or char*) */
+ #define _curl_is_postfields(expr) \
+ (_curl_is_ptr((expr), void) || \
+- _curl_is_arr((expr), char))
++ _curl_is_arr((expr), char) || \
++ _curl_is_arr((expr), unsigned char))
+
+ /* FIXME: the whole callback checking is messy...
+ * The idea is to tolerate char vs. void and const vs. not const
+ * pointers in arguments at least
+ */
+ /* helper: __builtin_types_compatible_p distinguishes between functions and
+ * function pointers, hide it */
+ #define _curl_callback_compatible(func, type) \
+ (__builtin_types_compatible_p(__typeof__(func), type) || \
+- __builtin_types_compatible_p(__typeof__(func), type*))
++ __builtin_types_compatible_p(__typeof__(func) *, type))
++
++/* evaluates to true if expr is of type curl_resolver_start_callback */
++#define _curl_is_resolver_start_callback(expr) \
++ (_curl_is_NULL(expr) || \
++ _curl_callback_compatible((expr), curl_resolver_start_callback))
+
+ /* evaluates to true if expr is of type curl_read_callback or "similar" */
+ #define _curl_is_read_cb(expr) \
+ (_curl_is_NULL(expr) || \
+- __builtin_types_compatible_p(__typeof__(expr), __typeof__(fread)) || \
+- __builtin_types_compatible_p(__typeof__(expr), curl_read_callback) || \
++ _curl_callback_compatible((expr), __typeof__(fread) *) || \
++ _curl_callback_compatible((expr), curl_read_callback) || \
+ _curl_callback_compatible((expr), _curl_read_callback1) || \
+ _curl_callback_compatible((expr), _curl_read_callback2) || \
+ _curl_callback_compatible((expr), _curl_read_callback3) || \
+ _curl_callback_compatible((expr), _curl_read_callback4) || \
+ _curl_callback_compatible((expr), _curl_read_callback5) || \
+ _curl_callback_compatible((expr), _curl_read_callback6))
+-typedef size_t (_curl_read_callback1)(char *, size_t, size_t, void*);
+-typedef size_t (_curl_read_callback2)(char *, size_t, size_t, const void*);
+-typedef size_t (_curl_read_callback3)(char *, size_t, size_t, FILE*);
+-typedef size_t (_curl_read_callback4)(void *, size_t, size_t, void*);
+-typedef size_t (_curl_read_callback5)(void *, size_t, size_t, const void*);
+-typedef size_t (_curl_read_callback6)(void *, size_t, size_t, FILE*);
++typedef size_t (*_curl_read_callback1)(char *, size_t, size_t, void *);
++typedef size_t (*_curl_read_callback2)(char *, size_t, size_t, const void *);
++typedef size_t (*_curl_read_callback3)(char *, size_t, size_t, FILE *);
++typedef size_t (*_curl_read_callback4)(void *, size_t, size_t, void *);
++typedef size_t (*_curl_read_callback5)(void *, size_t, size_t, const void *);
++typedef size_t (*_curl_read_callback6)(void *, size_t, size_t, FILE *);
+
+ /* evaluates to true if expr is of type curl_write_callback or "similar" */
+ #define _curl_is_write_cb(expr) \
+ (_curl_is_read_cb(expr) || \
+- __builtin_types_compatible_p(__typeof__(expr), __typeof__(fwrite)) || \
+- __builtin_types_compatible_p(__typeof__(expr), curl_write_callback) || \
++ _curl_callback_compatible((expr), __typeof__(fwrite) *) || \
++ _curl_callback_compatible((expr), curl_write_callback) || \
+ _curl_callback_compatible((expr), _curl_write_callback1) || \
+ _curl_callback_compatible((expr), _curl_write_callback2) || \
+ _curl_callback_compatible((expr), _curl_write_callback3) || \
+ _curl_callback_compatible((expr), _curl_write_callback4) || \
+ _curl_callback_compatible((expr), _curl_write_callback5) || \
+ _curl_callback_compatible((expr), _curl_write_callback6))
+-typedef size_t (_curl_write_callback1)(const char *, size_t, size_t, void*);
+-typedef size_t (_curl_write_callback2)(const char *, size_t, size_t,
+- const void*);
+-typedef size_t (_curl_write_callback3)(const char *, size_t, size_t, FILE*);
+-typedef size_t (_curl_write_callback4)(const void *, size_t, size_t, void*);
+-typedef size_t (_curl_write_callback5)(const void *, size_t, size_t,
+- const void*);
+-typedef size_t (_curl_write_callback6)(const void *, size_t, size_t, FILE*);
++typedef size_t (*_curl_write_callback1)(const char *, size_t, size_t, void *);
++typedef size_t (*_curl_write_callback2)(const char *, size_t, size_t,
++ const void *);
++typedef size_t (*_curl_write_callback3)(const char *, size_t, size_t, FILE *);
++typedef size_t (*_curl_write_callback4)(const void *, size_t, size_t, void *);
++typedef size_t (*_curl_write_callback5)(const void *, size_t, size_t,
++ const void *);
++typedef size_t (*_curl_write_callback6)(const void *, size_t, size_t, FILE *);
+
+ /* evaluates to true if expr is of type curl_ioctl_callback or "similar" */
+ #define _curl_is_ioctl_cb(expr) \
+ (_curl_is_NULL(expr) || \
+- __builtin_types_compatible_p(__typeof__(expr), curl_ioctl_callback) || \
++ _curl_callback_compatible((expr), curl_ioctl_callback) || \
+ _curl_callback_compatible((expr), _curl_ioctl_callback1) || \
+ _curl_callback_compatible((expr), _curl_ioctl_callback2) || \
+ _curl_callback_compatible((expr), _curl_ioctl_callback3) || \
+ _curl_callback_compatible((expr), _curl_ioctl_callback4))
+-typedef curlioerr (_curl_ioctl_callback1)(CURL *, int, void*);
+-typedef curlioerr (_curl_ioctl_callback2)(CURL *, int, const void*);
+-typedef curlioerr (_curl_ioctl_callback3)(CURL *, curliocmd, void*);
+-typedef curlioerr (_curl_ioctl_callback4)(CURL *, curliocmd, const void*);
++typedef curlioerr (*_curl_ioctl_callback1)(CURL *, int, void *);
++typedef curlioerr (*_curl_ioctl_callback2)(CURL *, int, const void *);
++typedef curlioerr (*_curl_ioctl_callback3)(CURL *, curliocmd, void *);
++typedef curlioerr (*_curl_ioctl_callback4)(CURL *, curliocmd, const void *);
+
+ /* evaluates to true if expr is of type curl_sockopt_callback or "similar" */
+ #define _curl_is_sockopt_cb(expr) \
+ (_curl_is_NULL(expr) || \
+- __builtin_types_compatible_p(__typeof__(expr), curl_sockopt_callback) || \
++ _curl_callback_compatible((expr), curl_sockopt_callback) || \
+ _curl_callback_compatible((expr), _curl_sockopt_callback1) || \
+ _curl_callback_compatible((expr), _curl_sockopt_callback2))
+-typedef int (_curl_sockopt_callback1)(void *, curl_socket_t, curlsocktype);
+-typedef int (_curl_sockopt_callback2)(const void *, curl_socket_t,
++typedef int (*_curl_sockopt_callback1)(void *, curl_socket_t, curlsocktype);
++typedef int (*_curl_sockopt_callback2)(const void *, curl_socket_t,
+ curlsocktype);
+
+-/* evaluates to true if expr is of type curl_opensocket_callback or "similar" */
++/* evaluates to true if expr is of type curl_opensocket_callback or
++ "similar" */
+ #define _curl_is_opensocket_cb(expr) \
+ (_curl_is_NULL(expr) || \
+- __builtin_types_compatible_p(__typeof__(expr), curl_opensocket_callback) ||\
++ _curl_callback_compatible((expr), curl_opensocket_callback) || \
+ _curl_callback_compatible((expr), _curl_opensocket_callback1) || \
+ _curl_callback_compatible((expr), _curl_opensocket_callback2) || \
+ _curl_callback_compatible((expr), _curl_opensocket_callback3) || \
+ _curl_callback_compatible((expr), _curl_opensocket_callback4))
+-typedef curl_socket_t (_curl_opensocket_callback1)
++typedef curl_socket_t (*_curl_opensocket_callback1)
+ (void *, curlsocktype, struct curl_sockaddr *);
+-typedef curl_socket_t (_curl_opensocket_callback2)
++typedef curl_socket_t (*_curl_opensocket_callback2)
+ (void *, curlsocktype, const struct curl_sockaddr *);
+-typedef curl_socket_t (_curl_opensocket_callback3)
++typedef curl_socket_t (*_curl_opensocket_callback3)
+ (const void *, curlsocktype, struct curl_sockaddr *);
+-typedef curl_socket_t (_curl_opensocket_callback4)
++typedef curl_socket_t (*_curl_opensocket_callback4)
+ (const void *, curlsocktype, const struct curl_sockaddr *);
+
+ /* evaluates to true if expr is of type curl_progress_callback or "similar" */
+ #define _curl_is_progress_cb(expr) \
+ (_curl_is_NULL(expr) || \
+- __builtin_types_compatible_p(__typeof__(expr), curl_progress_callback) || \
++ _curl_callback_compatible((expr), curl_progress_callback) || \
+ _curl_callback_compatible((expr), _curl_progress_callback1) || \
+ _curl_callback_compatible((expr), _curl_progress_callback2))
+-typedef int (_curl_progress_callback1)(void *,
++typedef int (*_curl_progress_callback1)(void *,
+ double, double, double, double);
+-typedef int (_curl_progress_callback2)(const void *,
++typedef int (*_curl_progress_callback2)(const void *,
+ double, double, double, double);
+
+ /* evaluates to true if expr is of type curl_debug_callback or "similar" */
+ #define _curl_is_debug_cb(expr) \
+ (_curl_is_NULL(expr) || \
+- __builtin_types_compatible_p(__typeof__(expr), curl_debug_callback) || \
++ _curl_callback_compatible((expr), curl_debug_callback) || \
+ _curl_callback_compatible((expr), _curl_debug_callback1) || \
+ _curl_callback_compatible((expr), _curl_debug_callback2) || \
+ _curl_callback_compatible((expr), _curl_debug_callback3) || \
+- _curl_callback_compatible((expr), _curl_debug_callback4))
+-typedef int (_curl_debug_callback1) (CURL *,
++ _curl_callback_compatible((expr), _curl_debug_callback4) || \
++ _curl_callback_compatible((expr), _curl_debug_callback5) || \
++ _curl_callback_compatible((expr), _curl_debug_callback6) || \
++ _curl_callback_compatible((expr), _curl_debug_callback7) || \
++ _curl_callback_compatible((expr), _curl_debug_callback8))
++typedef int (*_curl_debug_callback1) (CURL *,
+ curl_infotype, char *, size_t, void *);
+-typedef int (_curl_debug_callback2) (CURL *,
++typedef int (*_curl_debug_callback2) (CURL *,
+ curl_infotype, char *, size_t, const void *);
+-typedef int (_curl_debug_callback3) (CURL *,
++typedef int (*_curl_debug_callback3) (CURL *,
+ curl_infotype, const char *, size_t, void *);
+-typedef int (_curl_debug_callback4) (CURL *,
++typedef int (*_curl_debug_callback4) (CURL *,
+ curl_infotype, const char *, size_t, const void *);
++typedef int (*_curl_debug_callback5) (CURL *,
++ curl_infotype, unsigned char *, size_t, void *);
++typedef int (*_curl_debug_callback6) (CURL *,
++ curl_infotype, unsigned char *, size_t, const void *);
++typedef int (*_curl_debug_callback7) (CURL *,
++ curl_infotype, const unsigned char *, size_t, void *);
++typedef int (*_curl_debug_callback8) (CURL *,
++ curl_infotype, const unsigned char *, size_t, const void *);
+
+ /* evaluates to true if expr is of type curl_ssl_ctx_callback or "similar" */
+ /* this is getting even messier... */
+ #define _curl_is_ssl_ctx_cb(expr) \
+ (_curl_is_NULL(expr) || \
+- __builtin_types_compatible_p(__typeof__(expr), curl_ssl_ctx_callback) || \
++ _curl_callback_compatible((expr), curl_ssl_ctx_callback) || \
+ _curl_callback_compatible((expr), _curl_ssl_ctx_callback1) || \
+ _curl_callback_compatible((expr), _curl_ssl_ctx_callback2) || \
+ _curl_callback_compatible((expr), _curl_ssl_ctx_callback3) || \
+ _curl_callback_compatible((expr), _curl_ssl_ctx_callback4) || \
+ _curl_callback_compatible((expr), _curl_ssl_ctx_callback5) || \
+ _curl_callback_compatible((expr), _curl_ssl_ctx_callback6) || \
+ _curl_callback_compatible((expr), _curl_ssl_ctx_callback7) || \
+ _curl_callback_compatible((expr), _curl_ssl_ctx_callback8))
+-typedef CURLcode (_curl_ssl_ctx_callback1)(CURL *, void *, void *);
+-typedef CURLcode (_curl_ssl_ctx_callback2)(CURL *, void *, const void *);
+-typedef CURLcode (_curl_ssl_ctx_callback3)(CURL *, const void *, void *);
+-typedef CURLcode (_curl_ssl_ctx_callback4)(CURL *, const void *, const void *);
++typedef CURLcode (*_curl_ssl_ctx_callback1)(CURL *, void *, void *);
++typedef CURLcode (*_curl_ssl_ctx_callback2)(CURL *, void *, const void *);
++typedef CURLcode (*_curl_ssl_ctx_callback3)(CURL *, const void *, void *);
++typedef CURLcode (*_curl_ssl_ctx_callback4)(CURL *, const void *,
++ const void *);
+ #ifdef HEADER_SSL_H
+ /* hack: if we included OpenSSL's ssl.h, we know about SSL_CTX
+ * this will of course break if we're included before OpenSSL headers...
+ */
+-typedef CURLcode (_curl_ssl_ctx_callback5)(CURL *, SSL_CTX, void *);
+-typedef CURLcode (_curl_ssl_ctx_callback6)(CURL *, SSL_CTX, const void *);
+-typedef CURLcode (_curl_ssl_ctx_callback7)(CURL *, const SSL_CTX, void *);
+-typedef CURLcode (_curl_ssl_ctx_callback8)(CURL *, const SSL_CTX, const void *);
++typedef CURLcode (*_curl_ssl_ctx_callback5)(CURL *, SSL_CTX, void *);
++typedef CURLcode (*_curl_ssl_ctx_callback6)(CURL *, SSL_CTX, const void *);
++typedef CURLcode (*_curl_ssl_ctx_callback7)(CURL *, const SSL_CTX, void *);
++typedef CURLcode (*_curl_ssl_ctx_callback8)(CURL *, const SSL_CTX,
++ const void *);
+ #else
+ typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback5;
+ typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback6;
+ typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback7;
+ typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback8;
+ #endif
+
+ /* evaluates to true if expr is of type curl_conv_callback or "similar" */
+ #define _curl_is_conv_cb(expr) \
+ (_curl_is_NULL(expr) || \
+- __builtin_types_compatible_p(__typeof__(expr), curl_conv_callback) || \
++ _curl_callback_compatible((expr), curl_conv_callback) || \
+ _curl_callback_compatible((expr), _curl_conv_callback1) || \
+ _curl_callback_compatible((expr), _curl_conv_callback2) || \
+ _curl_callback_compatible((expr), _curl_conv_callback3) || \
+ _curl_callback_compatible((expr), _curl_conv_callback4))
+ typedef CURLcode (*_curl_conv_callback1)(char *, size_t length);
+ typedef CURLcode (*_curl_conv_callback2)(const char *, size_t length);
+ typedef CURLcode (*_curl_conv_callback3)(void *, size_t length);
+ typedef CURLcode (*_curl_conv_callback4)(const void *, size_t length);
+
+ /* evaluates to true if expr is of type curl_seek_callback or "similar" */
+ #define _curl_is_seek_cb(expr) \
+ (_curl_is_NULL(expr) || \
+- __builtin_types_compatible_p(__typeof__(expr), curl_seek_callback) || \
++ _curl_callback_compatible((expr), curl_seek_callback) || \
+ _curl_callback_compatible((expr), _curl_seek_callback1) || \
+ _curl_callback_compatible((expr), _curl_seek_callback2))
+ typedef CURLcode (*_curl_seek_callback1)(void *, curl_off_t, int);
+ typedef CURLcode (*_curl_seek_callback2)(const void *, curl_off_t, int);
+
+
+ #endif /* __CURL_TYPECHECK_GCC_H */
+diff --git a/src/third_party/curl/types.h b/src/third_party/curl/types.h
+deleted file mode 100644
+--- a/src/third_party/curl/types.h
++++ /dev/null
+@@ -1,1 +0,0 @@
+-/* not used */
+diff --git a/src/third_party/curl/urlapi.h b/src/third_party/curl/urlapi.h
+new file mode 100644
+--- /dev/null
++++ b/src/third_party/curl/urlapi.h
+@@ -0,0 +1,122 @@
++#ifndef __CURL_URLAPI_H
++#define __CURL_URLAPI_H
++/***************************************************************************
++ * _ _ ____ _
++ * Project ___| | | | _ \| |
++ * / __| | | | |_) | |
++ * | (__| |_| | _ <| |___
++ * \___|\___/|_| \_\_____|
++ *
++ * Copyright (C) 2018 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
++ *
++ * This software is licensed as described in the file COPYING, which
++ * you should have received as part of this distribution. The terms
++ * are also available at https://curl.haxx.se/docs/copyright.html.
++ *
++ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
++ * copies of the Software, and permit persons to whom the Software is
++ * furnished to do so, under the terms of the COPYING file.
++ *
++ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
++ * KIND, either express or implied.
++ *
++ ***************************************************************************/
++
++#include "curl.h"
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++/* the error codes for the URL API */
++typedef enum {
++ CURLUE_OK,
++ CURLUE_BAD_HANDLE, /* 1 */
++ CURLUE_BAD_PARTPOINTER, /* 2 */
++ CURLUE_MALFORMED_INPUT, /* 3 */
++ CURLUE_BAD_PORT_NUMBER, /* 4 */
++ CURLUE_UNSUPPORTED_SCHEME, /* 5 */
++ CURLUE_URLDECODE, /* 6 */
++ CURLUE_OUT_OF_MEMORY, /* 7 */
++ CURLUE_USER_NOT_ALLOWED, /* 8 */
++ CURLUE_UNKNOWN_PART, /* 9 */
++ CURLUE_NO_SCHEME, /* 10 */
++ CURLUE_NO_USER, /* 11 */
++ CURLUE_NO_PASSWORD, /* 12 */
++ CURLUE_NO_OPTIONS, /* 13 */
++ CURLUE_NO_HOST, /* 14 */
++ CURLUE_NO_PORT, /* 15 */
++ CURLUE_NO_QUERY, /* 16 */
++ CURLUE_NO_FRAGMENT /* 17 */
++} CURLUcode;
++
++typedef enum {
++ CURLUPART_URL,
++ CURLUPART_SCHEME,
++ CURLUPART_USER,
++ CURLUPART_PASSWORD,
++ CURLUPART_OPTIONS,
++ CURLUPART_HOST,
++ CURLUPART_PORT,
++ CURLUPART_PATH,
++ CURLUPART_QUERY,
++ CURLUPART_FRAGMENT
++} CURLUPart;
++
++#define CURLU_DEFAULT_PORT (1<<0) /* return default port number */
++#define CURLU_NO_DEFAULT_PORT (1<<1) /* act as if no port number was set,
++ if the port number matches the
++ default for the scheme */
++#define CURLU_DEFAULT_SCHEME (1<<2) /* return default scheme if
++ missing */
++#define CURLU_NON_SUPPORT_SCHEME (1<<3) /* allow non-supported scheme */
++#define CURLU_PATH_AS_IS (1<<4) /* leave dot sequences */
++#define CURLU_DISALLOW_USER (1<<5) /* no user+password allowed */
++#define CURLU_URLDECODE (1<<6) /* URL decode on get */
++#define CURLU_URLENCODE (1<<7) /* URL encode on set */
++#define CURLU_APPENDQUERY (1<<8) /* append a form style part */
++#define CURLU_GUESS_SCHEME (1<<9) /* legacy curl-style guessing */
++
++typedef struct Curl_URL CURLU;
++
++/*
++ * curl_url() creates a new CURLU handle and returns a pointer to it.
++ * Must be freed with curl_url_cleanup().
++ */
++CURL_EXTERN CURLU *curl_url(void);
++
++/*
++ * curl_url_cleanup() frees the CURLU handle and related resources used for
++ * the URL parsing. It will not free strings previously returned with the URL
++ * API.
++ */
++CURL_EXTERN void curl_url_cleanup(CURLU *handle);
++
++/*
++ * curl_url_dup() duplicates a CURLU handle and returns a new copy. The new
++ * handle must also be freed with curl_url_cleanup().
++ */
++CURL_EXTERN CURLU *curl_url_dup(CURLU *in);
++
++/*
++ * curl_url_get() extracts a specific part of the URL from a CURLU
++ * handle. Returns error code. The returned pointer MUST be freed with
++ * curl_free() afterwards.
++ */
++CURL_EXTERN CURLUcode curl_url_get(CURLU *handle, CURLUPart what,
++ char **part, unsigned int flags);
++
++/*
++ * curl_url_set() sets a specific part of the URL in a CURLU handle. Returns
++ * error code. The passed in string will be copied. Passing a NULL instead of
++ * a part string, clears that part.
++ */
++CURL_EXTERN CURLUcode curl_url_set(CURLU *handle, CURLUPart what,
++ const char *part, unsigned int flags);
++
++
++#ifdef __cplusplus
++} /* end of extern "C" */
++#endif
++
++#endif
+diff --git a/src/third_party/musl/include/elf.h b/src/third_party/musl/include/elf.h
+--- a/src/third_party/musl/include/elf.h
++++ b/src/third_party/musl/include/elf.h
+@@ -205,23 +205,123 @@ typedef struct {
+ #define EM_D10V 85
+ #define EM_D30V 86
+ #define EM_V850 87
+ #define EM_M32R 88
+ #define EM_MN10300 89
+ #define EM_MN10200 90
+ #define EM_PJ 91
+ #define EM_OR1K 92
++#define EM_OPENRISC 92
+ #define EM_ARC_A5 93
++#define EM_ARC_COMPACT 93
+ #define EM_XTENSA 94
++#define EM_VIDEOCORE 95
++#define EM_TMM_GPP 96
++#define EM_NS32K 97
++#define EM_TPC 98
++#define EM_SNP1K 99
++#define EM_ST200 100
++#define EM_IP2K 101
++#define EM_MAX 102
++#define EM_CR 103
++#define EM_F2MC16 104
++#define EM_MSP430 105
++#define EM_BLACKFIN 106
++#define EM_SE_C33 107
++#define EM_SEP 108
++#define EM_ARCA 109
++#define EM_UNICORE 110
++#define EM_EXCESS 111
++#define EM_DXP 112
++#define EM_ALTERA_NIOS2 113
++#define EM_CRX 114
++#define EM_XGATE 115
++#define EM_C166 116
++#define EM_M16C 117
++#define EM_DSPIC30F 118
++#define EM_CE 119
++#define EM_M32C 120
++#define EM_TSK3000 131
++#define EM_RS08 132
++#define EM_SHARC 133
++#define EM_ECOG2 134
++#define EM_SCORE7 135
++#define EM_DSP24 136
++#define EM_VIDEOCORE3 137
++#define EM_LATTICEMICO32 138
++#define EM_SE_C17 139
++#define EM_TI_C6000 140
++#define EM_TI_C2000 141
++#define EM_TI_C5500 142
++#define EM_TI_ARP32 143
++#define EM_TI_PRU 144
++#define EM_MMDSP_PLUS 160
++#define EM_CYPRESS_M8C 161
++#define EM_R32C 162
++#define EM_TRIMEDIA 163
++#define EM_QDSP6 164
++#define EM_8051 165
++#define EM_STXP7X 166
++#define EM_NDS32 167
++#define EM_ECOG1X 168
++#define EM_MAXQ30 169
++#define EM_XIMO16 170
++#define EM_MANIK 171
++#define EM_CRAYNV2 172
++#define EM_RX 173
++#define EM_METAG 174
++#define EM_MCST_ELBRUS 175
++#define EM_ECOG16 176
++#define EM_CR16 177
++#define EM_ETPU 178
++#define EM_SLE9X 179
++#define EM_L10M 180
++#define EM_K10M 181
+ #define EM_AARCH64 183
++#define EM_AVR32 185
++#define EM_STM8 186
++#define EM_TILE64 187
+ #define EM_TILEPRO 188
+ #define EM_MICROBLAZE 189
++#define EM_CUDA 190
+ #define EM_TILEGX 191
+-#define EM_NUM 192
++#define EM_CLOUDSHIELD 192
++#define EM_COREA_1ST 193
++#define EM_COREA_2ND 194
++#define EM_ARC_COMPACT2 195
++#define EM_OPEN8 196
++#define EM_RL78 197
++#define EM_VIDEOCORE5 198
++#define EM_78KOR 199
++#define EM_56800EX 200
++#define EM_BA1 201
++#define EM_BA2 202
++#define EM_XCORE 203
++#define EM_MCHP_PIC 204
++#define EM_KM32 210
++#define EM_KMX32 211
++#define EM_EMX16 212
++#define EM_EMX8 213
++#define EM_KVARC 214
++#define EM_CDP 215
++#define EM_COGE 216
++#define EM_COOL 217
++#define EM_NORC 218
++#define EM_CSR_KALIMBA 219
++#define EM_Z80 220
++#define EM_VISIUM 221
++#define EM_FT32 222
++#define EM_MOXIE 223
++#define EM_AMDGPU 224
++#define EM_RISCV 243
++#define EM_BPF 247
++#define EM_CSKY 252
++#define EM_NUM 253
++
+ #define EM_ALPHA 0x9026
+
+ #define EV_NONE 0
+ #define EV_CURRENT 1
+ #define EV_NUM 2
+
+ typedef struct {
+ Elf32_Word sh_name;
+@@ -311,21 +411,42 @@ typedef struct {
+ #define SHF_MERGE (1 << 4)
+ #define SHF_STRINGS (1 << 5)
+ #define SHF_INFO_LINK (1 << 6)
+ #define SHF_LINK_ORDER (1 << 7)
+ #define SHF_OS_NONCONFORMING (1 << 8)
+
+ #define SHF_GROUP (1 << 9)
+ #define SHF_TLS (1 << 10)
++#define SHF_COMPRESSED (1 << 11)
+ #define SHF_MASKOS 0x0ff00000
+ #define SHF_MASKPROC 0xf0000000
+ #define SHF_ORDERED (1 << 30)
+ #define SHF_EXCLUDE (1U << 31)
+
++typedef struct {
++ Elf32_Word ch_type;
++ Elf32_Word ch_size;
++ Elf32_Word ch_addralign;
++} Elf32_Chdr;
++
++typedef struct {
++ Elf64_Word ch_type;
++ Elf64_Word ch_reserved;
++ Elf64_Xword ch_size;
++ Elf64_Xword ch_addralign;
++} Elf64_Chdr;
++
++#define ELFCOMPRESS_ZLIB 1
++#define ELFCOMPRESS_LOOS 0x60000000
++#define ELFCOMPRESS_HIOS 0x6fffffff
++#define ELFCOMPRESS_LOPROC 0x70000000
++#define ELFCOMPRESS_HIPROC 0x7fffffff
++
++
+ #define GRP_COMDAT 0x1
+
+ typedef struct {
+ Elf32_Word st_name;
+ Elf32_Addr st_value;
+ Elf32_Word st_size;
+ unsigned char st_info;
+ unsigned char st_other;
+@@ -404,18 +525,17 @@ typedef struct {
+ #define STV_DEFAULT 0
+ #define STV_INTERNAL 1
+ #define STV_HIDDEN 2
+ #define STV_PROTECTED 3
+
+
+
+
+-typedef struct
+-{
++typedef struct {
+ Elf32_Addr r_offset;
+ Elf32_Word r_info;
+ } Elf32_Rel;
+
+ typedef struct {
+ Elf64_Addr r_offset;
+ Elf64_Xword r_info;
+ } Elf64_Rel;
+@@ -499,16 +619,17 @@ typedef struct {
+ #define PF_W (1 << 1)
+ #define PF_R (1 << 2)
+ #define PF_MASKOS 0x0ff00000
+ #define PF_MASKPROC 0xf0000000
+
+
+
+ #define NT_PRSTATUS 1
++#define NT_PRFPREG 2
+ #define NT_FPREGSET 2
+ #define NT_PRPSINFO 3
+ #define NT_PRXREG 4
+ #define NT_TASKSTRUCT 4
+ #define NT_PLATFORM 5
+ #define NT_AUXV 6
+ #define NT_GWINDOWS 7
+ #define NT_ASRS 8
+@@ -520,35 +641,61 @@ typedef struct {
+ #define NT_LWPSINFO 17
+ #define NT_PRFPXREG 20
+ #define NT_SIGINFO 0x53494749
+ #define NT_FILE 0x46494c45
+ #define NT_PRXFPREG 0x46e62b7f
+ #define NT_PPC_VMX 0x100
+ #define NT_PPC_SPE 0x101
+ #define NT_PPC_VSX 0x102
++#define NT_PPC_TAR 0x103
++#define NT_PPC_PPR 0x104
++#define NT_PPC_DSCR 0x105
++#define NT_PPC_EBB 0x106
++#define NT_PPC_PMU 0x107
++#define NT_PPC_TM_CGPR 0x108
++#define NT_PPC_TM_CFPR 0x109
++#define NT_PPC_TM_CVMX 0x10a
++#define NT_PPC_TM_CVSX 0x10b
++#define NT_PPC_TM_SPR 0x10c
++#define NT_PPC_TM_CTAR 0x10d
++#define NT_PPC_TM_CPPR 0x10e
++#define NT_PPC_TM_CDSCR 0x10f
+ #define NT_386_TLS 0x200
+ #define NT_386_IOPERM 0x201
+ #define NT_X86_XSTATE 0x202
+ #define NT_S390_HIGH_GPRS 0x300
+ #define NT_S390_TIMER 0x301
+ #define NT_S390_TODCMP 0x302
+ #define NT_S390_TODPREG 0x303
+ #define NT_S390_CTRS 0x304
+ #define NT_S390_PREFIX 0x305
+ #define NT_S390_LAST_BREAK 0x306
+ #define NT_S390_SYSTEM_CALL 0x307
+ #define NT_S390_TDB 0x308
++#define NT_S390_VXRS_LOW 0x309
++#define NT_S390_VXRS_HIGH 0x30a
++#define NT_S390_GS_CB 0x30b
++#define NT_S390_GS_BC 0x30c
++#define NT_S390_RI_CB 0x30d
+ #define NT_ARM_VFP 0x400
+ #define NT_ARM_TLS 0x401
+ #define NT_ARM_HW_BREAK 0x402
+ #define NT_ARM_HW_WATCH 0x403
++#define NT_ARM_SYSTEM_CALL 0x404
++#define NT_ARM_SVE 0x405
++#define NT_ARM_PAC_MASK 0x406
+ #define NT_METAG_CBUF 0x500
+ #define NT_METAG_RPIPE 0x501
+ #define NT_METAG_TLS 0x502
++#define NT_ARC_V2 0x600
++#define NT_VMCOREDD 0x700
++#define NT_MIPS_DSP 0x800
++#define NT_MIPS_FP_MODE 0x801
++#define NT_MIPS_MSA 0x802
+ #define NT_VERSION 1
+
+
+
+
+ typedef struct {
+ Elf32_Sword d_tag;
+ union {
+@@ -596,17 +743,18 @@ typedef struct {
+ #define DT_FINI_ARRAY 26
+ #define DT_INIT_ARRAYSZ 27
+ #define DT_FINI_ARRAYSZ 28
+ #define DT_RUNPATH 29
+ #define DT_FLAGS 30
+ #define DT_ENCODING 32
+ #define DT_PREINIT_ARRAY 32
+ #define DT_PREINIT_ARRAYSZ 33
+-#define DT_NUM 34
++#define DT_SYMTAB_SHNDX 34
++#define DT_NUM 35
+ #define DT_LOOS 0x6000000d
+ #define DT_HIOS 0x6ffff000
+ #define DT_LOPROC 0x70000000
+ #define DT_HIPROC 0x7fffffff
+ #define DT_PROCNUM DT_MIPS_NUM
+
+ #define DT_VALRNGLO 0x6ffffd00
+ #define DT_GNU_PRELINKED 0x6ffffdf5
+@@ -696,16 +844,18 @@ typedef struct {
+ #define DF_1_IGNMULDEF 0x00040000
+ #define DF_1_NOKSYMS 0x00080000
+ #define DF_1_NOHDR 0x00100000
+ #define DF_1_EDITED 0x00200000
+ #define DF_1_NORELOC 0x00400000
+ #define DF_1_SYMINTPOSE 0x00800000
+ #define DF_1_GLOBAUDIT 0x01000000
+ #define DF_1_SINGLETON 0x02000000
++#define DF_1_STUB 0x04000000
++#define DF_1_PIE 0x08000000
+
+ #define DTF_1_PARINIT 0x00000001
+ #define DTF_1_CONFEXP 0x00000002
+
+
+ #define DF_P1_LAZYLOAD 0x00000001
+ #define DF_P1_GROUPPERM 0x00000002
+
+@@ -877,17 +1027,26 @@ typedef struct {
+
+
+
+ #define AT_L1I_CACHESHAPE 34
+ #define AT_L1D_CACHESHAPE 35
+ #define AT_L2_CACHESHAPE 36
+ #define AT_L3_CACHESHAPE 37
+
+-
++#define AT_L1I_CACHESIZE 40
++#define AT_L1I_CACHEGEOMETRY 41
++#define AT_L1D_CACHESIZE 42
++#define AT_L1D_CACHEGEOMETRY 43
++#define AT_L2_CACHESIZE 44
++#define AT_L2_CACHEGEOMETRY 45
++#define AT_L3_CACHESIZE 46
++#define AT_L3_CACHEGEOMETRY 47
++
++#define AT_MINSIGSTKSZ 51
+
+
+ typedef struct {
+ Elf32_Word n_namesz;
+ Elf32_Word n_descsz;
+ Elf32_Word n_type;
+ } Elf32_Nhdr;
+
+@@ -972,17 +1131,35 @@ typedef struct {
+ #define R_68K_PLT8 15
+ #define R_68K_PLT32O 16
+ #define R_68K_PLT16O 17
+ #define R_68K_PLT8O 18
+ #define R_68K_COPY 19
+ #define R_68K_GLOB_DAT 20
+ #define R_68K_JMP_SLOT 21
+ #define R_68K_RELATIVE 22
+-#define R_68K_NUM 23
++#define R_68K_TLS_GD32 25
++#define R_68K_TLS_GD16 26
++#define R_68K_TLS_GD8 27
++#define R_68K_TLS_LDM32 28
++#define R_68K_TLS_LDM16 29
++#define R_68K_TLS_LDM8 30
++#define R_68K_TLS_LDO32 31
++#define R_68K_TLS_LDO16 32
++#define R_68K_TLS_LDO8 33
++#define R_68K_TLS_IE32 34
++#define R_68K_TLS_IE16 35
++#define R_68K_TLS_IE8 36
++#define R_68K_TLS_LE32 37
++#define R_68K_TLS_LE16 38
++#define R_68K_TLS_LE8 39
++#define R_68K_TLS_DTPMOD32 40
++#define R_68K_TLS_DTPREL32 41
++#define R_68K_TLS_TPREL32 42
++#define R_68K_NUM 43
+
+ #define R_386_NONE 0
+ #define R_386_32 1
+ #define R_386_PC32 2
+ #define R_386_GOT32 3
+ #define R_386_PLT32 4
+ #define R_386_COPY 5
+ #define R_386_GLOB_DAT 6
+@@ -1015,17 +1192,18 @@ typedef struct {
+ #define R_386_TLS_DTPMOD32 35
+ #define R_386_TLS_DTPOFF32 36
+ #define R_386_TLS_TPOFF32 37
+ #define R_386_SIZE32 38
+ #define R_386_TLS_GOTDESC 39
+ #define R_386_TLS_DESC_CALL 40
+ #define R_386_TLS_DESC 41
+ #define R_386_IRELATIVE 42
+-#define R_386_NUM 43
++#define R_386_GOT32X 43
++#define R_386_NUM 44
+
+
+
+
+
+ #define STT_SPARC_REGISTER 13
+
+
+@@ -1148,16 +1326,17 @@ typedef struct {
+
+ #define EF_MIPS_NOREORDER 1
+ #define EF_MIPS_PIC 2
+ #define EF_MIPS_CPIC 4
+ #define EF_MIPS_XGOT 8
+ #define EF_MIPS_64BIT_WHIRL 16
+ #define EF_MIPS_ABI2 32
+ #define EF_MIPS_ABI_ON32 64
++#define EF_MIPS_FP64 512
+ #define EF_MIPS_NAN2008 1024
+ #define EF_MIPS_ARCH 0xf0000000
+
+
+
+ #define EF_MIPS_ARCH_1 0x00000000
+ #define EF_MIPS_ARCH_2 0x10000000
+ #define EF_MIPS_ARCH_3 0x20000000
+@@ -1392,16 +1571,17 @@ typedef struct {
+
+ #define R_MIPS_NUM 128
+
+
+
+ #define PT_MIPS_REGINFO 0x70000000
+ #define PT_MIPS_RTPROC 0x70000001
+ #define PT_MIPS_OPTIONS 0x70000002
++#define PT_MIPS_ABIFLAGS 0x70000003
+
+
+
+ #define PF_MIPS_LOCAL 0x10000000
+
+
+
+ #define DT_MIPS_RLD_VERSION 0x70000001
+@@ -1455,17 +1635,18 @@ typedef struct {
+
+ #define DT_MIPS_COMPACT_SIZE 0x7000002f
+ #define DT_MIPS_GP_VALUE 0x70000030
+ #define DT_MIPS_AUX_DYNAMIC 0x70000031
+
+ #define DT_MIPS_PLTGOT 0x70000032
+
+ #define DT_MIPS_RWPLT 0x70000034
+-#define DT_MIPS_NUM 0x35
++#define DT_MIPS_RLD_MAP_REL 0x70000035
++#define DT_MIPS_NUM 0x36
+
+
+
+ #define RHF_NONE 0
+ #define RHF_QUICKSTART (1 << 0)
+ #define RHF_NOTPOT (1 << 1)
+ #define RHF_NO_LIBRARY_REPLACEMENT (1 << 2)
+ #define RHF_NO_MOVE (1 << 3)
+@@ -1478,27 +1659,25 @@ typedef struct {
+ #define RHF_REQUICKSTART (1 << 10)
+ #define RHF_REQUICKSTARTED (1 << 11)
+ #define RHF_CORD (1 << 12)
+ #define RHF_NO_UNRES_UNDEF (1 << 13)
+ #define RHF_RLD_ORDER_SAFE (1 << 14)
+
+
+
+-typedef struct
+-{
++typedef struct {
+ Elf32_Word l_name;
+ Elf32_Word l_time_stamp;
+ Elf32_Word l_checksum;
+ Elf32_Word l_version;
+ Elf32_Word l_flags;
+ } Elf32_Lib;
+
+-typedef struct
+-{
++typedef struct {
+ Elf64_Word l_name;
+ Elf64_Word l_time_stamp;
+ Elf64_Word l_checksum;
+ Elf64_Word l_version;
+ Elf64_Word l_flags;
+ } Elf64_Lib;
+
+
+@@ -1511,17 +1690,83 @@ typedef struct
+ #define LL_EXPORTS (1 << 3)
+ #define LL_DELAY_LOAD (1 << 4)
+ #define LL_DELTA (1 << 5)
+
+
+
+ typedef Elf32_Addr Elf32_Conflict;
+
+-
++typedef struct {
++ Elf32_Half version;
++ unsigned char isa_level;
++ unsigned char isa_rev;
++ unsigned char gpr_size;
++ unsigned char cpr1_size;
++ unsigned char cpr2_size;
++ unsigned char fp_abi;
++ Elf32_Word isa_ext;
++ Elf32_Word ases;
++ Elf32_Word flags1;
++ Elf32_Word flags2;
++} Elf_MIPS_ABIFlags_v0;
++
++#define MIPS_AFL_REG_NONE 0x00
++#define MIPS_AFL_REG_32 0x01
++#define MIPS_AFL_REG_64 0x02
++#define MIPS_AFL_REG_128 0x03
++
++#define MIPS_AFL_ASE_DSP 0x00000001
++#define MIPS_AFL_ASE_DSPR2 0x00000002
++#define MIPS_AFL_ASE_EVA 0x00000004
++#define MIPS_AFL_ASE_MCU 0x00000008
++#define MIPS_AFL_ASE_MDMX 0x00000010
++#define MIPS_AFL_ASE_MIPS3D 0x00000020
++#define MIPS_AFL_ASE_MT 0x00000040
++#define MIPS_AFL_ASE_SMARTMIPS 0x00000080
++#define MIPS_AFL_ASE_VIRT 0x00000100
++#define MIPS_AFL_ASE_MSA 0x00000200
++#define MIPS_AFL_ASE_MIPS16 0x00000400
++#define MIPS_AFL_ASE_MICROMIPS 0x00000800
++#define MIPS_AFL_ASE_XPA 0x00001000
++#define MIPS_AFL_ASE_MASK 0x00001fff
++
++#define MIPS_AFL_EXT_XLR 1
++#define MIPS_AFL_EXT_OCTEON2 2
++#define MIPS_AFL_EXT_OCTEONP 3
++#define MIPS_AFL_EXT_LOONGSON_3A 4
++#define MIPS_AFL_EXT_OCTEON 5
++#define MIPS_AFL_EXT_5900 6
++#define MIPS_AFL_EXT_4650 7
++#define MIPS_AFL_EXT_4010 8
++#define MIPS_AFL_EXT_4100 9
++#define MIPS_AFL_EXT_3900 10
++#define MIPS_AFL_EXT_10000 11
++#define MIPS_AFL_EXT_SB1 12
++#define MIPS_AFL_EXT_4111 13
++#define MIPS_AFL_EXT_4120 14
++#define MIPS_AFL_EXT_5400 15
++#define MIPS_AFL_EXT_5500 16
++#define MIPS_AFL_EXT_LOONGSON_2E 17
++#define MIPS_AFL_EXT_LOONGSON_2F 18
++
++#define MIPS_AFL_FLAGS1_ODDSPREG 1
++
++enum
++{
++ Val_GNU_MIPS_ABI_FP_ANY = 0,
++ Val_GNU_MIPS_ABI_FP_DOUBLE = 1,
++ Val_GNU_MIPS_ABI_FP_SINGLE = 2,
++ Val_GNU_MIPS_ABI_FP_SOFT = 3,
++ Val_GNU_MIPS_ABI_FP_OLD_64 = 4,
++ Val_GNU_MIPS_ABI_FP_XX = 5,
++ Val_GNU_MIPS_ABI_FP_64 = 6,
++ Val_GNU_MIPS_ABI_FP_64A = 7,
++ Val_GNU_MIPS_ABI_FP_MAX = 7
++};
+
+
+
+
+ #define EF_PARISC_TRAPNIL 0x00010000
+ #define EF_PARISC_EXT 0x00020000
+ #define EF_PARISC_LSB 0x00040000
+ #define EF_PARISC_WIDE 0x00080000
+@@ -1852,17 +2097,18 @@ typedef Elf32_Addr Elf32_Conflict;
+ #define R_PPC_GOT_TPREL16 87
+ #define R_PPC_GOT_TPREL16_LO 88
+ #define R_PPC_GOT_TPREL16_HI 89
+ #define R_PPC_GOT_TPREL16_HA 90
+ #define R_PPC_GOT_DTPREL16 91
+ #define R_PPC_GOT_DTPREL16_LO 92
+ #define R_PPC_GOT_DTPREL16_HI 93
+ #define R_PPC_GOT_DTPREL16_HA 94
+-
++#define R_PPC_TLSGD 95
++#define R_PPC_TLSLD 96
+
+
+ #define R_PPC_EMB_NADDR32 101
+ #define R_PPC_EMB_NADDR16 102
+ #define R_PPC_EMB_NADDR16_LO 103
+ #define R_PPC_EMB_NADDR16_HI 104
+ #define R_PPC_EMB_NADDR16_HA 105
+ #define R_PPC_EMB_SDAI16 106
+@@ -1895,17 +2141,20 @@ typedef Elf32_Addr Elf32_Conflict;
+ #define R_PPC_REL16_HA 252
+
+
+
+ #define R_PPC_TOC16 255
+
+
+ #define DT_PPC_GOT (DT_LOPROC + 0)
+-#define DT_PPC_NUM 1
++#define DT_PPC_OPT (DT_LOPROC + 1)
++#define DT_PPC_NUM 2
++
++#define PPC_OPT_TLS 1
+
+
+ #define R_PPC64_NONE R_PPC_NONE
+ #define R_PPC64_ADDR32 R_PPC_ADDR32
+ #define R_PPC64_ADDR24 R_PPC_ADDR24
+ #define R_PPC64_ADDR16 R_PPC_ADDR16
+ #define R_PPC64_ADDR16_LO R_PPC_ADDR16_LO
+ #define R_PPC64_ADDR16_HI R_PPC_ADDR16_HI
+@@ -2008,33 +2257,49 @@ typedef Elf32_Addr Elf32_Conflict;
+ #define R_PPC64_TPREL16_HIGHEST 99
+ #define R_PPC64_TPREL16_HIGHESTA 100
+ #define R_PPC64_DTPREL16_DS 101
+ #define R_PPC64_DTPREL16_LO_DS 102
+ #define R_PPC64_DTPREL16_HIGHER 103
+ #define R_PPC64_DTPREL16_HIGHERA 104
+ #define R_PPC64_DTPREL16_HIGHEST 105
+ #define R_PPC64_DTPREL16_HIGHESTA 106
++#define R_PPC64_TLSGD 107
++#define R_PPC64_TLSLD 108
++#define R_PPC64_TOCSAVE 109
++#define R_PPC64_ADDR16_HIGH 110
++#define R_PPC64_ADDR16_HIGHA 111
++#define R_PPC64_TPREL16_HIGH 112
++#define R_PPC64_TPREL16_HIGHA 113
++#define R_PPC64_DTPREL16_HIGH 114
++#define R_PPC64_DTPREL16_HIGHA 115
+
+
+ #define R_PPC64_JMP_IREL 247
+ #define R_PPC64_IRELATIVE 248
+ #define R_PPC64_REL16 249
+ #define R_PPC64_REL16_LO 250
+ #define R_PPC64_REL16_HI 251
+ #define R_PPC64_REL16_HA 252
+
++#define EF_PPC64_ABI 3
+
+ #define DT_PPC64_GLINK (DT_LOPROC + 0)
+ #define DT_PPC64_OPD (DT_LOPROC + 1)
+ #define DT_PPC64_OPDSZ (DT_LOPROC + 2)
+-#define DT_PPC64_NUM 3
+-
+-
+-
++#define DT_PPC64_OPT (DT_LOPROC + 3)
++#define DT_PPC64_NUM 4
++
++#define PPC64_OPT_TLS 1
++#define PPC64_OPT_MULTI_TOC 2
++#define PPC64_OPT_LOCALENTRY 4
++
++#define STO_PPC64_LOCAL_BIT 5
++#define STO_PPC64_LOCAL_MASK 0xe0
++#define PPC64_LOCAL_ENTRY_OFFSET(x) (1 << (((x)&0xe0)>>5) & 0xfc)
+
+
+ #define EF_ARM_RELEXEC 0x01
+ #define EF_ARM_HASENTRY 0x02
+ #define EF_ARM_INTERWORK 0x04
+ #define EF_ARM_APCS_26 0x08
+ #define EF_ARM_APCS_FLOAT 0x10
+ #define EF_ARM_PIC 0x20
+@@ -2084,18 +2349,27 @@ typedef Elf32_Addr Elf32_Conflict;
+
+ #define PT_ARM_EXIDX (PT_LOPROC + 1)
+
+
+ #define SHT_ARM_EXIDX (SHT_LOPROC + 1)
+ #define SHT_ARM_PREEMPTMAP (SHT_LOPROC + 2)
+ #define SHT_ARM_ATTRIBUTES (SHT_LOPROC + 3)
+
+-
+ #define R_AARCH64_NONE 0
++#define R_AARCH64_P32_ABS32 1
++#define R_AARCH64_P32_COPY 180
++#define R_AARCH64_P32_GLOB_DAT 181
++#define R_AARCH64_P32_JUMP_SLOT 182
++#define R_AARCH64_P32_RELATIVE 183
++#define R_AARCH64_P32_TLS_DTPMOD 184
++#define R_AARCH64_P32_TLS_DTPREL 185
++#define R_AARCH64_P32_TLS_TPREL 186
++#define R_AARCH64_P32_TLSDESC 187
++#define R_AARCH64_P32_IRELATIVE 188
+ #define R_AARCH64_ABS64 257
+ #define R_AARCH64_ABS32 258
+ #define R_AARCH64_ABS16 259
+ #define R_AARCH64_PREL64 260
+ #define R_AARCH64_PREL32 261
+ #define R_AARCH64_PREL16 262
+ #define R_AARCH64_MOVW_UABS_G0 263
+ #define R_AARCH64_MOVW_UABS_G0_NC 264
+@@ -2203,18 +2477,21 @@ typedef Elf32_Addr Elf32_Conflict;
+ #define R_AARCH64_TLSLE_LDST128_TPREL_LO12 570
+ #define R_AARCH64_TLSLE_LDST128_TPREL_LO12_NC 571
+ #define R_AARCH64_TLSLD_LDST128_DTPREL_LO12 572
+ #define R_AARCH64_TLSLD_LDST128_DTPREL_LO12_NC 573
+ #define R_AARCH64_COPY 1024
+ #define R_AARCH64_GLOB_DAT 1025
+ #define R_AARCH64_JUMP_SLOT 1026
+ #define R_AARCH64_RELATIVE 1027
++#define R_AARCH64_TLS_DTPMOD 1028
+ #define R_AARCH64_TLS_DTPMOD64 1028
++#define R_AARCH64_TLS_DTPREL 1029
+ #define R_AARCH64_TLS_DTPREL64 1029
++#define R_AARCH64_TLS_TPREL 1030
+ #define R_AARCH64_TLS_TPREL64 1030
+ #define R_AARCH64_TLSDESC 1031
+
+
+ #define R_ARM_NONE 0
+ #define R_ARM_PC24 1
+ #define R_ARM_ABS32 2
+ #define R_ARM_REL32 3
+@@ -2342,16 +2619,71 @@ typedef Elf32_Addr Elf32_Conflict;
+ #define R_ARM_RREL32 252
+ #define R_ARM_RABS22 253
+ #define R_ARM_RPC24 254
+ #define R_ARM_RBASE 255
+
+ #define R_ARM_NUM 256
+
+
++#define R_CKCORE_NONE 0
++#define R_CKCORE_ADDR32 1
++#define R_CKCORE_PCRELIMM8BY4 2
++#define R_CKCORE_PCRELIMM11BY2 3
++#define R_CKCORE_PCREL32 5
++#define R_CKCORE_PCRELJSR_IMM11BY2 6
++#define R_CKCORE_RELATIVE 9
++#define R_CKCORE_COPY 10
++#define R_CKCORE_GLOB_DAT 11
++#define R_CKCORE_JUMP_SLOT 12
++#define R_CKCORE_GOTOFF 13
++#define R_CKCORE_GOTPC 14
++#define R_CKCORE_GOT32 15
++#define R_CKCORE_PLT32 16
++#define R_CKCORE_ADDRGOT 17
++#define R_CKCORE_ADDRPLT 18
++#define R_CKCORE_PCREL_IMM26BY2 19
++#define R_CKCORE_PCREL_IMM16BY2 20
++#define R_CKCORE_PCREL_IMM16BY4 21
++#define R_CKCORE_PCREL_IMM10BY2 22
++#define R_CKCORE_PCREL_IMM10BY4 23
++#define R_CKCORE_ADDR_HI16 24
++#define R_CKCORE_ADDR_LO16 25
++#define R_CKCORE_GOTPC_HI16 26
++#define R_CKCORE_GOTPC_LO16 27
++#define R_CKCORE_GOTOFF_HI16 28
++#define R_CKCORE_GOTOFF_LO16 29
++#define R_CKCORE_GOT12 30
++#define R_CKCORE_GOT_HI16 31
++#define R_CKCORE_GOT_LO16 32
++#define R_CKCORE_PLT12 33
++#define R_CKCORE_PLT_HI16 34
++#define R_CKCORE_PLT_LO16 35
++#define R_CKCORE_ADDRGOT_HI16 36
++#define R_CKCORE_ADDRGOT_LO16 37
++#define R_CKCORE_ADDRPLT_HI16 38
++#define R_CKCORE_ADDRPLT_LO16 39
++#define R_CKCORE_PCREL_JSR_IMM26BY2 40
++#define R_CKCORE_TOFFSET_LO16 41
++#define R_CKCORE_DOFFSET_LO16 42
++#define R_CKCORE_PCREL_IMM18BY2 43
++#define R_CKCORE_DOFFSET_IMM18 44
++#define R_CKCORE_DOFFSET_IMM18BY2 45
++#define R_CKCORE_DOFFSET_IMM18BY4 46
++#define R_CKCORE_GOT_IMM18BY4 48
++#define R_CKCORE_PLT_IMM18BY4 49
++#define R_CKCORE_PCREL_IMM7BY4 50
++#define R_CKCORE_TLS_LE32 51
++#define R_CKCORE_TLS_IE32 52
++#define R_CKCORE_TLS_GD32 53
++#define R_CKCORE_TLS_LDM32 54
++#define R_CKCORE_TLS_LDO32 55
++#define R_CKCORE_TLS_DTPMOD32 56
++#define R_CKCORE_TLS_DTPOFF32 57
++#define R_CKCORE_TLS_TPOFF32 58
+
+
+ #define EF_IA_64_MASKOS 0x0000000f
+ #define EF_IA_64_ABI64 0x00000010
+ #define EF_IA_64_ARCH 0xff000000
+
+
+ #define PT_IA_64_ARCHEXT (PT_LOPROC + 0)
+@@ -2454,17 +2786,38 @@ typedef Elf32_Addr Elf32_Conflict;
+ #define R_IA64_DTPREL64I 0xb3
+ #define R_IA64_DTPREL32MSB 0xb4
+ #define R_IA64_DTPREL32LSB 0xb5
+ #define R_IA64_DTPREL64MSB 0xb6
+ #define R_IA64_DTPREL64LSB 0xb7
+ #define R_IA64_LTOFF_DTPREL22 0xba
+
+
+-
++#define EF_SH_MACH_MASK 0x1f
++#define EF_SH_UNKNOWN 0x0
++#define EF_SH1 0x1
++#define EF_SH2 0x2
++#define EF_SH3 0x3
++#define EF_SH_DSP 0x4
++#define EF_SH3_DSP 0x5
++#define EF_SH4AL_DSP 0x6
++#define EF_SH3E 0x8
++#define EF_SH4 0x9
++#define EF_SH2E 0xb
++#define EF_SH4A 0xc
++#define EF_SH2A 0xd
++#define EF_SH4_NOFPU 0x10
++#define EF_SH4A_NOFPU 0x11
++#define EF_SH4_NOMMU_NOFPU 0x12
++#define EF_SH2A_NOFPU 0x13
++#define EF_SH3_NOMMU 0x14
++#define EF_SH2A_SH4_NOFPU 0x15
++#define EF_SH2A_SH3_NOFPU 0x16
++#define EF_SH2A_SH4 0x17
++#define EF_SH2A_SH3E 0x18
+
+ #define R_SH_NONE 0
+ #define R_SH_DIR32 1
+ #define R_SH_REL32 2
+ #define R_SH_DIR8WPN 3
+ #define R_SH_IND12W 4
+ #define R_SH_DIR8WPL 5
+ #define R_SH_DIR8WPZ 6
+@@ -2660,17 +3013,19 @@ typedef Elf32_Addr Elf32_Conflict;
+ #define R_X86_64_SIZE64 33
+
+ #define R_X86_64_GOTPC32_TLSDESC 34
+ #define R_X86_64_TLSDESC_CALL 35
+
+ #define R_X86_64_TLSDESC 36
+ #define R_X86_64_IRELATIVE 37
+ #define R_X86_64_RELATIVE64 38
+-#define R_X86_64_NUM 39
++#define R_X86_64_GOTPCRELX 41
++#define R_X86_64_REX_GOTPCRELX 42
++#define R_X86_64_NUM 43
+
+
+
+ #define R_MN10300_NONE 0
+ #define R_MN10300_32 1
+ #define R_MN10300_16 2
+ #define R_MN10300_8 3
+ #define R_MN10300_PCREL32 4
+@@ -2778,16 +3133,65 @@ typedef Elf32_Addr Elf32_Conflict;
+ #define R_MICROBLAZE_TLSGD 23
+ #define R_MICROBLAZE_TLSLD 24
+ #define R_MICROBLAZE_TLSDTPMOD32 25
+ #define R_MICROBLAZE_TLSDTPREL32 26
+ #define R_MICROBLAZE_TLSDTPREL64 27
+ #define R_MICROBLAZE_TLSGOTTPREL32 28
+ #define R_MICROBLAZE_TLSTPREL32 29
+
++#define DT_NIOS2_GP 0x70000002
++
++#define R_NIOS2_NONE 0
++#define R_NIOS2_S16 1
++#define R_NIOS2_U16 2
++#define R_NIOS2_PCREL16 3
++#define R_NIOS2_CALL26 4
++#define R_NIOS2_IMM5 5
++#define R_NIOS2_CACHE_OPX 6
++#define R_NIOS2_IMM6 7
++#define R_NIOS2_IMM8 8
++#define R_NIOS2_HI16 9
++#define R_NIOS2_LO16 10
++#define R_NIOS2_HIADJ16 11
++#define R_NIOS2_BFD_RELOC_32 12
++#define R_NIOS2_BFD_RELOC_16 13
++#define R_NIOS2_BFD_RELOC_8 14
++#define R_NIOS2_GPREL 15
++#define R_NIOS2_GNU_VTINHERIT 16
++#define R_NIOS2_GNU_VTENTRY 17
++#define R_NIOS2_UJMP 18
++#define R_NIOS2_CJMP 19
++#define R_NIOS2_CALLR 20
++#define R_NIOS2_ALIGN 21
++#define R_NIOS2_GOT16 22
++#define R_NIOS2_CALL16 23
++#define R_NIOS2_GOTOFF_LO 24
++#define R_NIOS2_GOTOFF_HA 25
++#define R_NIOS2_PCREL_LO 26
++#define R_NIOS2_PCREL_HA 27
++#define R_NIOS2_TLS_GD16 28
++#define R_NIOS2_TLS_LDM16 29
++#define R_NIOS2_TLS_LDO16 30
++#define R_NIOS2_TLS_IE16 31
++#define R_NIOS2_TLS_LE16 32
++#define R_NIOS2_TLS_DTPMOD 33
++#define R_NIOS2_TLS_DTPREL 34
++#define R_NIOS2_TLS_TPREL 35
++#define R_NIOS2_COPY 36
++#define R_NIOS2_GLOB_DAT 37
++#define R_NIOS2_JUMP_SLOT 38
++#define R_NIOS2_RELATIVE 39
++#define R_NIOS2_GOTOFF 40
++#define R_NIOS2_CALL26_NOAT 41
++#define R_NIOS2_GOT_LO 42
++#define R_NIOS2_GOT_HA 43
++#define R_NIOS2_CALL_LO 44
++#define R_NIOS2_CALL_HA 45
++
+ #define R_OR1K_NONE 0
+ #define R_OR1K_32 1
+ #define R_OR1K_16 2
+ #define R_OR1K_8 3
+ #define R_OR1K_LO_16_IN_INSN 4
+ #define R_OR1K_HI_16_IN_INSN 5
+ #define R_OR1K_INSN_REL_26 6
+ #define R_OR1K_GNU_VTENTRY 7
+@@ -2814,14 +3218,17 @@ typedef Elf32_Addr Elf32_Conflict;
+ #define R_OR1K_TLS_IE_HI16 28
+ #define R_OR1K_TLS_IE_LO16 29
+ #define R_OR1K_TLS_LE_HI16 30
+ #define R_OR1K_TLS_LE_LO16 31
+ #define R_OR1K_TLS_TPOFF 32
+ #define R_OR1K_TLS_DTPOFF 33
+ #define R_OR1K_TLS_DTPMOD 34
+
++#define R_BPF_NONE 0
++#define R_BPF_MAP_FD 1
++
+ #ifdef __cplusplus
+ }
+ #endif
+
+
+ #endif
+
diff --git a/toolkit/crashreporter/breakpad-patches/09-json-upload.patch b/toolkit/crashreporter/breakpad-patches/09-json-upload.patch
new file mode 100644
index 0000000000..8ad73bc681
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-patches/09-json-upload.patch
@@ -0,0 +1,333 @@
+diff --git a/src/common/linux/http_upload.cc b/src/common/linux/http_upload.cc
+index 702526af..0a1019dd 100644
+--- a/src/common/linux/http_upload.cc
++++ b/src/common/linux/http_upload.cc
+@@ -55,7 +55,7 @@ static const char kUserAgent[] = "Breakpad/1.0 (Linux)";
+
+ // static
+ bool HTTPUpload::SendRequest(const string &url,
+- const map<string, string> &parameters,
++ const string &parameters,
+ const map<string, string> &files,
+ const string &proxy,
+ const string &proxy_user_pwd,
+@@ -66,9 +66,6 @@ bool HTTPUpload::SendRequest(const string &url,
+ 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);
+@@ -133,14 +130,14 @@ bool HTTPUpload::SendRequest(const string &url,
+ // 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);
++ (*curl_formadd)(&formpost, &lastptr, CURLFORM_COPYNAME, "extra",
++ CURLFORM_BUFFER, "extra.json", CURLFORM_BUFFERPTR,
++ parameters.c_str(), CURLFORM_BUFFERLENGTH,
++ parameters.length(), CURLFORM_CONTENTTYPE, "application/json",
++ CURLFORM_END);
+
+ // Add form files.
++ map<string, string>::const_iterator iter = files.begin();
+ for (iter = files.begin(); iter != files.end(); ++iter) {
+ (*curl_formadd)(&formpost, &lastptr,
+ CURLFORM_COPYNAME, iter->first.c_str(),
+@@ -210,21 +207,4 @@ bool HTTPUpload::CheckCurlLib(void* curl_lib) {
+ 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/src/common/linux/http_upload.h b/src/common/linux/http_upload.h
+index bc1d5d57..95dedebc 100644
+--- a/src/common/linux/http_upload.h
++++ b/src/common/linux/http_upload.h
+@@ -29,7 +29,7 @@
+
+ // 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.
++// parameters encoded in a JSON string, and a file to upload.
+
+ #ifndef COMMON_LINUX_HTTP_UPLOAD_H__
+ #define COMMON_LINUX_HTTP_UPLOAD_H__
+@@ -49,8 +49,7 @@ class HTTPUpload {
+ // 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.
++ // Parameters are specified as a JSON-encoded string in |parameters|.
+ // 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.
+@@ -59,7 +58,7 @@ class HTTPUpload {
+ // 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 string &parameters,
+ const map<string, string> &files,
+ const string &proxy,
+ const string &proxy_user_pwd,
+@@ -69,11 +68,6 @@ class HTTPUpload {
+ 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);
+
+diff --git a/src/common/mac/HTTPMultipartUpload.h b/src/common/mac/HTTPMultipartUpload.h
+index 42e8fed3..0cea733e 100644
+--- a/src/common/mac/HTTPMultipartUpload.h
++++ b/src/common/mac/HTTPMultipartUpload.h
+@@ -37,7 +37,7 @@
+ @interface HTTPMultipartUpload : NSObject {
+ @protected
+ NSURL *url_; // The destination URL (STRONG)
+- NSDictionary *parameters_; // The key/value pairs for sending data (STRONG)
++ NSMutableString *parameters_; // The JSON payload 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)
+@@ -47,8 +47,8 @@
+
+ - (NSURL *)URL;
+
+-- (void)setParameters:(NSDictionary *)parameters;
+-- (NSDictionary *)parameters;
++- (void)setParameters:(NSMutableString *)parameters;
++- (NSMutableString *)parameters;
+
+ - (void)addFileAtPath:(NSString *)path name:(NSString *)name;
+ - (void)addFileContents:(NSData *)data name:(NSString *)name;
+diff --git a/src/common/mac/HTTPMultipartUpload.m b/src/common/mac/HTTPMultipartUpload.m
+index a3677f25..d2480493 100644
+--- a/src/common/mac/HTTPMultipartUpload.m
++++ b/src/common/mac/HTTPMultipartUpload.m
+@@ -93,7 +93,7 @@ static NSData *SendSynchronousNSURLRequest(NSURLRequest *req,
+ - (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 *)formDataForJSON:(NSString *)json;
+ - (NSData *)formDataForFileContents:(NSData *)contents name:(NSString *)name;
+ - (NSData *)formDataForFile:(NSString *)file name:(NSString *)name;
+ @end
+@@ -110,13 +110,16 @@ static NSData *SendSynchronousNSURLRequest(NSURLRequest *req,
+ }
+
+ //=============================================================================
+-- (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];
++- (NSData *)formDataForJSON:(NSString *)json {
++ NSMutableData *data = [NSMutableData data];
++ NSString *fmt = @"--%@\r\nContent-Disposition: form-data; name=\"extra\"; "
++ "filename=\"extra.json\"\r\nContent-Type: application/json\r\n\r\n";
++ NSString *form = [NSString stringWithFormat:fmt, boundary_];
++
++ [data appendData:[form dataUsingEncoding:NSUTF8StringEncoding]];
++ [data appendData:[json dataUsingEncoding:NSUTF8StringEncoding]];
+
+- return [form dataUsingEncoding:NSUTF8StringEncoding];
++ return data;
+ }
+
+ //=============================================================================
+@@ -171,15 +174,15 @@ static NSData *SendSynchronousNSURLRequest(NSURLRequest *req,
+ }
+
+ //=============================================================================
+-- (void)setParameters:(NSDictionary *)parameters {
++- (void)setParameters:(NSMutableString *)parameters {
+ if (parameters != parameters_) {
+ [parameters_ release];
+- parameters_ = [parameters copy];
++ parameters_ = [parameters mutableCopy];
+ }
+ }
+
+ //=============================================================================
+-- (NSDictionary *)parameters {
++- (NSMutableString *)parameters {
+ return parameters_;
+ }
+
+@@ -210,16 +213,8 @@ static NSData *SendSynchronousNSURLRequest(NSURLRequest *req,
+ [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 JSON parameters to the message
++ [postBody appendData:[self formDataForJSON:parameters_]];
+
+ // Add any files to the message
+ NSArray *fileNames = [files_ allKeys];
+diff --git a/src/common/windows/http_upload.cc b/src/common/windows/http_upload.cc
+index b0cc9078..5df17e1a 100644
+--- a/src/common/windows/http_upload.cc
++++ b/src/common/windows/http_upload.cc
+@@ -141,23 +141,6 @@ namespace {
+ return rv;
+ }
+
+- bool 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;
+- }
+-
+ // Converts a UTF16 string to UTF8.
+ string WideToUTF8(const wstring &wide) {
+ return WideToMBCP(wide, CP_UTF8);
+@@ -390,7 +373,7 @@ namespace {
+ return true;
+ }
+
+- bool GenerateRequestBody(const map<wstring, wstring> &parameters,
++ bool GenerateRequestBody(const string &parameters,
+ const map<wstring, wstring> &files,
+ const wstring &boundary,
+ string *request_body) {
+@@ -401,14 +384,19 @@ namespace {
+
+ 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");
++ // Append the extra data as a single JSON form entry
++ request_body->append("--" + boundary_str + "\r\n");
++ request_body->append(
++ "Content-Disposition: form-data; "
++ "name=\"extra\"; "
++ "filename=\"extra.json\"\r\n");
++ request_body->append("Content-Type: application/json\r\n");
++ request_body->append("\r\n");
++
++ if (!parameters.empty()) {
++ request_body->append(parameters);
+ }
++ request_body->append("\r\n");
+
+ // Now append each upload file as a binary (octet-stream) part
+ for (map<wstring, wstring>::const_iterator pos = files.begin();
+@@ -463,16 +451,11 @@ namespace google_breakpad {
+
+ bool HTTPUpload::SendMultipartPostRequest(
+ const wstring& url,
+- const map<wstring, wstring>& parameters,
++ const string& parameters,
+ const map<wstring, wstring>& files,
+ int* timeout_ms,
+ wstring* response_body,
+ int* response_code) {
+- // TODO(bryner): support non-ASCII parameter names
+- if (!CheckParameters(parameters)) {
+- return false;
+- }
+-
+ wstring boundary = GenerateMultipartBoundary();
+ wstring content_type_header = GenerateMultipartPostRequestHeader(boundary);
+
+diff --git a/src/common/windows/http_upload.h b/src/common/windows/http_upload.h
+index 57e526e3..1e47f582 100644
+--- a/src/common/windows/http_upload.h
++++ b/src/common/windows/http_upload.h
+@@ -29,7 +29,7 @@
+
+ // 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.
++// parameters encoded in a JSON string, and a file to upload.
+
+ #ifndef COMMON_WINDOWS_HTTP_UPLOAD_H_
+ #define COMMON_WINDOWS_HTTP_UPLOAD_H_
+@@ -45,9 +45,9 @@
+
+ namespace google_breakpad {
+
++using std::map;
+ using std::string;
+ using std::wstring;
+-using std::map;
+
+ class HTTPUpload {
+ public:
+@@ -81,8 +81,7 @@ class HTTPUpload {
+ // 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.
++ // Parameters are specified as a JSON-encoded string in |parameters|.
+ // 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.
+@@ -90,7 +89,7 @@ class HTTPUpload {
+ // received (or 0 if the request failed before getting an HTTP response).
+ static bool SendMultipartPostRequest(
+ const wstring& url,
+- const map<wstring, wstring>& parameters,
++ const string& parameters,
+ const map<wstring, wstring>& files,
+ int *timeout_ms,
+ wstring *response_body,
diff --git a/toolkit/crashreporter/breakpad-patches/10-macho-cpu-subtype.patch b/toolkit/crashreporter/breakpad-patches/10-macho-cpu-subtype.patch
new file mode 100644
index 0000000000..be743f9fe7
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-patches/10-macho-cpu-subtype.patch
@@ -0,0 +1,47 @@
+changeset: 571402:0c63dcd7a1c6
+user: Steven Michaud <smichaud@pobox.com>
+date: Tue Nov 19 21:42:37 2019 +0000
+summary: Bug 1371390 - Pay attention to macho images' cpusubtype when creating minidumps (revised). r=gsvelto
+
+diff --git a/src/common/mac/macho_walker.cc b/src/common/mac/macho_walker.cc
+--- a/src/common/mac/macho_walker.cc
++++ b/src/common/mac/macho_walker.cc
+@@ -151,16 +151,18 @@ bool MachoWalker::FindHeader(cpu_type_t
+ // 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);
+
++ header.cpusubtype &= ~CPU_SUBTYPE_MASK;
++
+ if (cpu_type != header.cputype ||
+ (cpu_subtype != CPU_SUBTYPE_MULTIPLE &&
+ cpu_subtype != header.cpusubtype)) {
+ return false;
+ }
+
+ offset = 0;
+ return true;
+@@ -180,16 +182,18 @@ bool MachoWalker::FindHeader(cpu_type_t
+ 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);
+
++ arch.cpusubtype &= ~CPU_SUBTYPE_MASK;
++
+ if (arch.cputype == cpu_type &&
+ (cpu_subtype == CPU_SUBTYPE_MULTIPLE ||
+ arch.cpusubtype == cpu_subtype)) {
+ offset = arch.offset;
+ return true;
+ }
+
+ offset += sizeof(arch);
+
diff --git a/toolkit/crashreporter/breakpad-patches/12-macho-cpu-subtype-fix.patch b/toolkit/crashreporter/breakpad-patches/12-macho-cpu-subtype-fix.patch
new file mode 100644
index 0000000000..6fad2d4d58
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-patches/12-macho-cpu-subtype-fix.patch
@@ -0,0 +1,22 @@
+commit 65b01bb302ba1eb7b0240753c22dce39c5ed836b
+Author: Nathan Froyd <froydnj@mozilla.com>
+Date: Tue Jul 14 16:50:20 2020 -0400
+
+ mask off cpusubtype bits before determining Mach-O identifiers; r=gsvelto
+
+ If we don't do this, we run into problems when walking over the Mach-O load
+ commands, where we *do* mask off cpusubtype bits.
+
+diff --git a/src/common/mac/dump_syms.cc b/src/common/mac/dump_syms.cc
+index 4ad0e2b..1c9a067 100644
+--- a/src/common/mac/dump_syms.cc
++++ b/src/common/mac/dump_syms.cc
+@@ -286,7 +286,7 @@ 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;
++ cpu_subtype_t cpu_subtype = selected_object_file_->cpusubtype & ~CPU_SUBTYPE_MASK;
+ 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());
diff --git a/toolkit/crashreporter/breakpad-patches/13-improve-arm64-stack-walking.patch b/toolkit/crashreporter/breakpad-patches/13-improve-arm64-stack-walking.patch
new file mode 100644
index 0000000000..b9c6f82799
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-patches/13-improve-arm64-stack-walking.patch
@@ -0,0 +1,79 @@
+diff --git a/src/processor/stackwalker_arm64.cc b/src/processor/stackwalker_arm64.cc
+--- a/src/processor/stackwalker_arm64.cc
++++ b/src/processor/stackwalker_arm64.cc
+@@ -282,16 +282,27 @@ void StackwalkerARM64::CorrectRegLRByFra
+ << std::hex << (last_last_fp + 8);
+ return;
+ }
+ last_lr = PtrauthStrip(last_lr);
+
+ last_frame->context.iregs[MD_CONTEXT_ARM64_REG_LR] = last_lr;
+ }
+
++bool StackwalkerARM64::ValidInstructionPointerInFrame(const StackFrameARM64& frame) {
++ const uint64_t ip = frame.context.iregs[MD_CONTEXT_ARM64_REG_PC];
++
++ if ((ip < 0x1000) || (ip > 0x000fffffffffffff)) {
++ // The IP points into the first page or above the user space threshold
++ return false;
++ }
++
++ return true;
++}
++
+ StackFrame* StackwalkerARM64::GetCallerFrame(const CallStack* stack,
+ bool stack_scan_allowed) {
+ if (!memory_ || !stack) {
+ BPLOG(ERROR) << "Can't get caller frame without memory or stack";
+ return NULL;
+ }
+
+ const vector<StackFrame*> &frames = *stack->frames();
+@@ -300,21 +311,22 @@ StackFrame* StackwalkerARM64::GetCallerF
+
+ // See if there is DWARF call frame information covering this address.
+ scoped_ptr<CFIFrameInfo> cfi_frame_info(
+ frame_symbolizer_->FindCFIFrameInfo(last_frame));
+ if (cfi_frame_info.get())
+ frame.reset(GetCallerByCFIFrameInfo(frames, cfi_frame_info.get()));
+
+ // If CFI failed, or there wasn't CFI available, fall back to frame pointer.
+- if (!frame.get())
++ if (!frame.get() || !ValidInstructionPointerInFrame(*frame))
+ frame.reset(GetCallerByFramePointer(frames));
+
+ // If everything failed, fall back to stack scanning.
+- if (stack_scan_allowed && !frame.get())
++ if (stack_scan_allowed &&
++ (!frame.get() || !ValidInstructionPointerInFrame(*frame)))
+ frame.reset(GetCallerByStackScan(frames));
+
+ // If nothing worked, tell the caller.
+ if (!frame.get())
+ return NULL;
+
+ // Should we terminate the stack walk? (end-of-stack or broken invariant)
+ if (TerminateWalk(frame->context.iregs[MD_CONTEXT_ARM64_REG_PC],
+diff --git a/src/processor/stackwalker_arm64.h b/src/processor/stackwalker_arm64.h
+--- a/src/processor/stackwalker_arm64.h
++++ b/src/processor/stackwalker_arm64.h
+@@ -92,16 +92,19 @@ class StackwalkerARM64 : public Stackwal
+
+ // GetCallerByFramePointer() depends on the previous frame having recovered
+ // x30($LR) which may not have been done when using CFI.
+ // This function recovers $LR in the previous frame by using the frame-pointer
+ // two frames back to read it from the stack.
+ void CorrectRegLRByFramePointer(const vector<StackFrame*>& frames,
+ StackFrameARM64* last_frame);
+
++ // Return true if the instruction pointer points into the first 4KiB of memory
++ bool ValidInstructionPointerInFrame(const StackFrameARM64& frame);
++
+ // Stores the CPU context corresponding to the youngest stack frame, to
+ // be returned by GetContextFrame.
+ const MDRawContextARM64* context_;
+
+ // Validity mask for youngest stack frame. This is always
+ // CONTEXT_VALID_ALL in real use; it is only changeable for the sake of
+ // unit tests.
+ uint64_t context_frame_validity_;
diff --git a/toolkit/crashreporter/breakpad-patches/14-handle-non-fixed-size-amd64-and-x86-contexts.patch b/toolkit/crashreporter/breakpad-patches/14-handle-non-fixed-size-amd64-and-x86-contexts.patch
new file mode 100644
index 0000000000..b9544281c2
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-patches/14-handle-non-fixed-size-amd64-and-x86-contexts.patch
@@ -0,0 +1,344 @@
+diff --git a/src/processor/minidump.cc b/src/processor/minidump.cc
+index 1f479558..aa63fe47 100644
+--- a/src/processor/minidump.cc
++++ b/src/processor/minidump.cc
+@@ -444,140 +444,30 @@ MinidumpContext::MinidumpContext(Minidump* minidump)
+
+ MinidumpContext::~MinidumpContext() {
+ }
+
+ bool MinidumpContext::Read(uint32_t expected_size) {
+ valid_ = false;
+
+ // Certain raw context types are currently assumed to have unique sizes.
+- if (!IsContextSizeUnique(sizeof(MDRawContextAMD64))) {
+- BPLOG(ERROR) << "sizeof(MDRawContextAMD64) cannot match the size of any "
+- << "other raw context";
+- return false;
+- }
+ if (!IsContextSizeUnique(sizeof(MDRawContextPPC64))) {
+ BPLOG(ERROR) << "sizeof(MDRawContextPPC64) cannot match the size of any "
+ << "other raw context";
+ return false;
+ }
+ if (!IsContextSizeUnique(sizeof(MDRawContextARM64_Old))) {
+ BPLOG(ERROR) << "sizeof(MDRawContextARM64_Old) cannot match the size of any "
+ << "other raw context";
+ return false;
+ }
+
+ FreeContext();
+
+- // First, figure out what type of CPU this context structure is for.
+- // For some reason, the AMD64 Context doesn't have context_flags
+- // at the beginning of the structure, so special case it here.
+- if (expected_size == sizeof(MDRawContextAMD64)) {
+- BPLOG(INFO) << "MinidumpContext: looks like AMD64 context";
+-
+- scoped_ptr<MDRawContextAMD64> context_amd64(new MDRawContextAMD64());
+- if (!minidump_->ReadBytes(context_amd64.get(),
+- sizeof(MDRawContextAMD64))) {
+- BPLOG(ERROR) << "MinidumpContext could not read amd64 context";
+- return false;
+- }
+-
+- if (minidump_->swap())
+- Swap(&context_amd64->context_flags);
+-
+- uint32_t cpu_type = context_amd64->context_flags & MD_CONTEXT_CPU_MASK;
+- if (cpu_type == 0) {
+- if (minidump_->GetContextCPUFlagsFromSystemInfo(&cpu_type)) {
+- context_amd64->context_flags |= cpu_type;
+- } else {
+- BPLOG(ERROR) << "Failed to preserve the current stream position";
+- return false;
+- }
+- }
+-
+- if (cpu_type != MD_CONTEXT_AMD64) {
+- // TODO: Fall through to switch below.
+- // https://bugs.chromium.org/p/google-breakpad/issues/detail?id=550
+- BPLOG(ERROR) << "MinidumpContext not actually amd64 context";
+- return false;
+- }
+-
+- // Do this after reading the entire MDRawContext structure because
+- // GetSystemInfo may seek minidump to a new position.
+- if (!CheckAgainstSystemInfo(cpu_type)) {
+- BPLOG(ERROR) << "MinidumpContext amd64 does not match system info";
+- return false;
+- }
+-
+- // Normalize the 128-bit types in the dump.
+- // Since this is AMD64, by definition, the values are little-endian.
+- for (unsigned int vr_index = 0;
+- vr_index < MD_CONTEXT_AMD64_VR_COUNT;
+- ++vr_index)
+- Normalize128(&context_amd64->vector_register[vr_index], false);
+-
+- if (minidump_->swap()) {
+- Swap(&context_amd64->p1_home);
+- Swap(&context_amd64->p2_home);
+- Swap(&context_amd64->p3_home);
+- Swap(&context_amd64->p4_home);
+- Swap(&context_amd64->p5_home);
+- Swap(&context_amd64->p6_home);
+- // context_flags is already swapped
+- Swap(&context_amd64->mx_csr);
+- Swap(&context_amd64->cs);
+- Swap(&context_amd64->ds);
+- Swap(&context_amd64->es);
+- Swap(&context_amd64->fs);
+- Swap(&context_amd64->ss);
+- Swap(&context_amd64->eflags);
+- Swap(&context_amd64->dr0);
+- Swap(&context_amd64->dr1);
+- Swap(&context_amd64->dr2);
+- Swap(&context_amd64->dr3);
+- Swap(&context_amd64->dr6);
+- Swap(&context_amd64->dr7);
+- Swap(&context_amd64->rax);
+- Swap(&context_amd64->rcx);
+- Swap(&context_amd64->rdx);
+- Swap(&context_amd64->rbx);
+- Swap(&context_amd64->rsp);
+- Swap(&context_amd64->rbp);
+- Swap(&context_amd64->rsi);
+- Swap(&context_amd64->rdi);
+- Swap(&context_amd64->r8);
+- Swap(&context_amd64->r9);
+- Swap(&context_amd64->r10);
+- Swap(&context_amd64->r11);
+- Swap(&context_amd64->r12);
+- Swap(&context_amd64->r13);
+- Swap(&context_amd64->r14);
+- Swap(&context_amd64->r15);
+- Swap(&context_amd64->rip);
+- // FIXME: I'm not sure what actually determines
+- // which member of the union {flt_save, sse_registers}
+- // is valid. We're not currently using either,
+- // but it would be good to have them swapped properly.
+-
+- for (unsigned int vr_index = 0;
+- vr_index < MD_CONTEXT_AMD64_VR_COUNT;
+- ++vr_index)
+- Swap(&context_amd64->vector_register[vr_index]);
+- Swap(&context_amd64->vector_control);
+- Swap(&context_amd64->debug_control);
+- Swap(&context_amd64->last_branch_to_rip);
+- Swap(&context_amd64->last_branch_from_rip);
+- Swap(&context_amd64->last_exception_to_rip);
+- Swap(&context_amd64->last_exception_from_rip);
+- }
+-
+- SetContextFlags(context_amd64->context_flags);
+-
+- SetContextAMD64(context_amd64.release());
+- } else if (expected_size == sizeof(MDRawContextPPC64)) {
++ if (expected_size == sizeof(MDRawContextPPC64)) {
+ // |context_flags| of MDRawContextPPC64 is 64 bits, but other MDRawContext
+ // in the else case have 32 bits |context_flags|, so special case it here.
+ uint64_t context_flags;
+ if (!minidump_->ReadBytes(&context_flags, sizeof(context_flags))) {
+ BPLOG(ERROR) << "MinidumpContext could not read context flags";
+ return false;
+ }
+ if (minidump_->swap())
+@@ -739,56 +629,152 @@ bool MinidumpContext::Read(uint32_t expected_size) {
+ }
+ }
+
+ scoped_ptr<MDRawContextARM64> new_context(new MDRawContextARM64());
+ ConvertOldARM64Context(*context_arm64.get(), new_context.get());
+ SetContextFlags(new_context->context_flags);
+ SetContextARM64(new_context.release());
+ } else {
+- uint32_t context_flags;
+- if (!minidump_->ReadBytes(&context_flags, sizeof(context_flags))) {
+- BPLOG(ERROR) << "MinidumpContext could not read context flags";
++ uint32_t cpu_type = 0;
++ if (!minidump_->GetContextCPUFlagsFromSystemInfo(&cpu_type)) {
++ BPLOG(ERROR) << "Failed to preserve the current stream position";
+ return false;
+ }
+- if (minidump_->swap())
+- Swap(&context_flags);
+
+- uint32_t cpu_type = context_flags & MD_CONTEXT_CPU_MASK;
+- if (cpu_type == 0) {
+- // Unfortunately the flag for MD_CONTEXT_ARM that was taken
+- // from a Windows CE SDK header conflicts in practice with
+- // the CONTEXT_XSTATE flag. MD_CONTEXT_ARM has been renumbered,
+- // but handle dumps with the legacy value gracefully here.
+- if (context_flags & MD_CONTEXT_ARM_OLD) {
+- context_flags |= MD_CONTEXT_ARM;
+- context_flags &= ~MD_CONTEXT_ARM_OLD;
+- cpu_type = MD_CONTEXT_ARM;
++ uint32_t context_flags = 0;
++ if ((cpu_type == 0) || cpu_type != MD_CONTEXT_AMD64) {
++ if (!minidump_->ReadBytes(&context_flags, sizeof(context_flags))) {
++ BPLOG(ERROR) << "MinidumpContext could not read context flags";
++ return false;
+ }
+- }
+
+- if (cpu_type == 0) {
+- if (minidump_->GetContextCPUFlagsFromSystemInfo(&cpu_type)) {
+- context_flags |= cpu_type;
++ if (minidump_->swap())
++ Swap(&context_flags);
++
++ if ((context_flags & MD_CONTEXT_CPU_MASK) == 0) {
++ // Unfortunately the flag for MD_CONTEXT_ARM that was taken
++ // from a Windows CE SDK header conflicts in practice with
++ // the CONTEXT_XSTATE flag. MD_CONTEXT_ARM has been renumbered,
++ // but handle dumps with the legacy value gracefully here.
++ if (context_flags & MD_CONTEXT_ARM_OLD) {
++ context_flags |= MD_CONTEXT_ARM;
++ context_flags &= ~MD_CONTEXT_ARM_OLD;
++ cpu_type = MD_CONTEXT_ARM;
++ } else {
++ context_flags |= cpu_type;
++ }
+ } else {
+- BPLOG(ERROR) << "Failed to preserve the current stream position";
+- return false;
++ cpu_type = context_flags & MD_CONTEXT_CPU_MASK;
+ }
+ }
+
+ // Allocate the context structure for the correct CPU and fill it. The
+ // casts are slightly unorthodox, but it seems better to do that than to
+ // maintain a separate pointer for each type of CPU context structure
+ // when only one of them will be used.
+ switch (cpu_type) {
++ case MD_CONTEXT_AMD64: {
++ if (expected_size != sizeof(MDRawContextAMD64)) {
++ BPLOG(INFO) << "MinidumpContext AMD64 size mismatch, " <<
++ expected_size << " != " << sizeof(MDRawContextAMD64);
++ }
++ BPLOG(INFO) << "MinidumpContext: looks like AMD64 context";
++
++ scoped_ptr<MDRawContextAMD64> context_amd64(new MDRawContextAMD64());
++ if (!minidump_->ReadBytes(context_amd64.get(),
++ sizeof(MDRawContextAMD64))) {
++ BPLOG(ERROR) << "MinidumpContext could not read amd64 context";
++ return false;
++ }
++
++ if (minidump_->swap())
++ Swap(&context_amd64->context_flags);
++
++ // Update context_flags since we haven't done it yet
++ context_flags = context_amd64->context_flags;
++
++ if (cpu_type != (context_flags & MD_CONTEXT_CPU_MASK)) {
++ BPLOG(ERROR) << "MinidumpContext amd64 does not match system info";
++ return false;
++ }
++
++ // Normalize the 128-bit types in the dump.
++ // Since this is AMD64, by definition, the values are little-endian.
++ for (unsigned int vr_index = 0;
++ vr_index < MD_CONTEXT_AMD64_VR_COUNT;
++ ++vr_index)
++ Normalize128(&context_amd64->vector_register[vr_index], false);
++
++ if (minidump_->swap()) {
++ Swap(&context_amd64->p1_home);
++ Swap(&context_amd64->p2_home);
++ Swap(&context_amd64->p3_home);
++ Swap(&context_amd64->p4_home);
++ Swap(&context_amd64->p5_home);
++ Swap(&context_amd64->p6_home);
++ // context_flags is already swapped
++ Swap(&context_amd64->mx_csr);
++ Swap(&context_amd64->cs);
++ Swap(&context_amd64->ds);
++ Swap(&context_amd64->es);
++ Swap(&context_amd64->fs);
++ Swap(&context_amd64->ss);
++ Swap(&context_amd64->eflags);
++ Swap(&context_amd64->dr0);
++ Swap(&context_amd64->dr1);
++ Swap(&context_amd64->dr2);
++ Swap(&context_amd64->dr3);
++ Swap(&context_amd64->dr6);
++ Swap(&context_amd64->dr7);
++ Swap(&context_amd64->rax);
++ Swap(&context_amd64->rcx);
++ Swap(&context_amd64->rdx);
++ Swap(&context_amd64->rbx);
++ Swap(&context_amd64->rsp);
++ Swap(&context_amd64->rbp);
++ Swap(&context_amd64->rsi);
++ Swap(&context_amd64->rdi);
++ Swap(&context_amd64->r8);
++ Swap(&context_amd64->r9);
++ Swap(&context_amd64->r10);
++ Swap(&context_amd64->r11);
++ Swap(&context_amd64->r12);
++ Swap(&context_amd64->r13);
++ Swap(&context_amd64->r14);
++ Swap(&context_amd64->r15);
++ Swap(&context_amd64->rip);
++ // FIXME: I'm not sure what actually determines
++ // which member of the union {flt_save, sse_registers}
++ // is valid. We're not currently using either,
++ // but it would be good to have them swapped properly.
++
++ for (unsigned int vr_index = 0;
++ vr_index < MD_CONTEXT_AMD64_VR_COUNT;
++ ++vr_index)
++ Swap(&context_amd64->vector_register[vr_index]);
++ Swap(&context_amd64->vector_control);
++ Swap(&context_amd64->debug_control);
++ Swap(&context_amd64->last_branch_to_rip);
++ Swap(&context_amd64->last_branch_from_rip);
++ Swap(&context_amd64->last_exception_to_rip);
++ Swap(&context_amd64->last_exception_from_rip);
++ }
++
++ SetContextFlags(context_amd64->context_flags);
++
++ SetContextAMD64(context_amd64.release());
++ minidump_->SeekSet(
++ (minidump_->Tell() - sizeof(MDRawContextAMD64)) + expected_size);
++ break;
++ }
+ case MD_CONTEXT_X86: {
+ if (expected_size != sizeof(MDRawContextX86)) {
+- BPLOG(ERROR) << "MinidumpContext x86 size mismatch, " <<
++ BPLOG(INFO) << "MinidumpContext x86 size mismatch, " <<
+ expected_size << " != " << sizeof(MDRawContextX86);
+- return false;
+ }
+
+ scoped_ptr<MDRawContextX86> context_x86(new MDRawContextX86());
+
+ // Set the context_flags member, which has already been read, and
+ // read the rest of the structure beginning with the first member
+ // after context_flags.
+ context_x86->context_flags = context_flags;
+@@ -843,16 +829,18 @@ bool MinidumpContext::Read(uint32_t expected_size) {
+ Swap(&context_x86->eflags);
+ Swap(&context_x86->esp);
+ Swap(&context_x86->ss);
+ // context_x86->extended_registers[] contains 8-bit quantities and
+ // does not need to be swapped.
+ }
+
+ SetContextX86(context_x86.release());
++ minidump_->SeekSet(
++ (minidump_->Tell() - sizeof(MDRawContextX86)) + expected_size);
+
+ break;
+ }
+
+ case MD_CONTEXT_PPC: {
+ if (expected_size != sizeof(MDRawContextPPC)) {
+ BPLOG(ERROR) << "MinidumpContext ppc size mismatch, " <<
+ expected_size << " != " << sizeof(MDRawContextPPC);
+--
+2.26.2
+
diff --git a/toolkit/crashreporter/breakpad-patches/15-freebsd-profiler-support.patch b/toolkit/crashreporter/breakpad-patches/15-freebsd-profiler-support.patch
new file mode 100644
index 0000000000..812d554865
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-patches/15-freebsd-profiler-support.patch
@@ -0,0 +1,107 @@
+changeset: 599606:74707e8ecf38
+user: Greg V <greg@unrelenting.technology>
+date: Wed May 06 17:44:19 2020 +0000
+summary: Bug 1634205 - Support Gecko Profiler and Base Profiler on FreeBSD r=mstange
+
+diff --git a/src/common/dwarf/elf_reader.cc b/src/common/dwarf/elf_reader.cc
+--- a/src/common/dwarf/elf_reader.cc
++++ b/src/common/dwarf/elf_reader.cc
+@@ -52,17 +52,17 @@
+
+ // 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__
++#if __APPLE__ || __FreeBSD__
+ #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__
+diff --git a/src/common/linux/elfutils.cc b/src/common/linux/elfutils.cc
+--- a/src/common/linux/elfutils.cc
++++ b/src/common/linux/elfutils.cc
+@@ -30,16 +30,20 @@
+ #include "common/linux/elfutils.h"
+
+ #include <assert.h>
+ #include <string.h>
+
+ #include "common/linux/linux_libc_support.h"
+ #include "common/linux/elfutils-inl.h"
+
++#if defined(__FreeBSD__)
++# define ElfW(type) Elf_##type
++#endif
++
+ namespace google_breakpad {
+
+ namespace {
+
+ template<typename ElfClass>
+ void FindElfClassSection(const char *elf_base,
+ const char *section_name,
+ typename ElfClass::Word section_type,
+diff --git a/src/common/memory_allocator.h b/src/common/memory_allocator.h
+--- a/src/common/memory_allocator.h
++++ b/src/common/memory_allocator.h
+@@ -37,17 +37,17 @@
+
+ #include <memory>
+ #include <vector>
+
+ #if defined(MEMORY_SANITIZER)
+ #include <sanitizer/msan_interface.h>
+ #endif
+
+-#ifdef __APPLE__
++#if defined(__APPLE__) || defined(__FreeBSD__)
+ #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 {
+diff --git a/src/third_party/lss/linux_syscall_support.h b/src/third_party/lss/linux_syscall_support.h
+--- a/src/third_party/lss/linux_syscall_support.h
++++ b/src/third_party/lss/linux_syscall_support.h
+@@ -4527,10 +4527,27 @@ struct kernel_statfs {
+ #pragma pop_macro("pread64")
+ #pragma pop_macro("pwrite64")
+ #pragma pop_macro("getdents64")
+
+ #if defined(__cplusplus) && !defined(SYS_CPLUSPLUS)
+ }
+ #endif
+
+-#endif
+-#endif
++#elif defined(__FreeBSD__)
++
++#include <unistd.h>
++#include <sys/stat.h>
++
++#define sys_readlink readlink
++
++#define sys_open open
++#define sys_close close
++#define sys_fstat fstat
++#define sys_fstat64 fstat
++#define kernel_stat stat
++#define kernel_stat64 stat
++#define sys_mmap mmap
++#define sys_munmap munmap
++
++#endif
++
++#endif
+
diff --git a/toolkit/crashreporter/breakpad-patches/16-get-last-error.patch b/toolkit/crashreporter/breakpad-patches/16-get-last-error.patch
new file mode 100644
index 0000000000..96bebbe503
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-patches/16-get-last-error.patch
@@ -0,0 +1,181 @@
+diff --git a/src/google_breakpad/processor/call_stack.h b/src/google_breakpad/processor/call_stack.h
+--- a/src/google_breakpad/processor/call_stack.h
++++ b/src/google_breakpad/processor/call_stack.h
+@@ -62,26 +62,30 @@ class CallStack {
+
+ // Resets the CallStack to its initial empty state
+ void Clear();
+
+ const vector<StackFrame*>* frames() const { return &frames_; }
+
+ // Set the TID associated with this call stack.
+ void set_tid(uint32_t tid) { tid_ = tid; }
++ void set_last_error(uint32_t last_error) { last_error_ = last_error; }
+
+ uint32_t tid() const { return tid_; }
++ uint32_t last_error() const { return last_error_; }
+
+ private:
+ // Stackwalker is responsible for building the frames_ vector.
+ friend class Stackwalker;
+
+ // Storage for pushed frames.
+ vector<StackFrame*> frames_;
+
+ // The TID associated with this call stack. Default to 0 if it's not
+ // available.
+ uint32_t tid_;
++ // The last error the OS set for this thread (win32's GetLastError())
++ uint32_t last_error_;
+ };
+
+ } // namespace google_breakpad
+
+ #endif // GOOGLE_BREAKPAD_PROCSSOR_CALL_STACK_H__
+diff --git a/src/google_breakpad/processor/minidump.h b/src/google_breakpad/processor/minidump.h
+--- a/src/google_breakpad/processor/minidump.h
++++ b/src/google_breakpad/processor/minidump.h
+@@ -279,16 +279,26 @@ class MinidumpMemoryRegion : public Mini
+ class MinidumpThread : public MinidumpObject {
+ public:
+ virtual ~MinidumpThread();
+
+ const MDRawThread* thread() const { return valid_ ? &thread_ : NULL; }
+ // GetMemory may return NULL even if the MinidumpThread is valid,
+ // if the thread memory cannot be read.
+ virtual MinidumpMemoryRegion* GetMemory();
++ // Corresponds to win32's GetLastError function, which records the last
++ // error value set by the OS for this thread. A more useful error message
++ // can be produced by passing this value to FormatMessage:
++ //
++ // https://docs.microsoft.com/windows/win32/debug/retrieving-the-last-error-code
++ //
++ // The value may also be looked up in Microsoft's System Error Codes listing:
++ //
++ // https://docs.microsoft.com/windows/win32/debug/system-error-codes
++ virtual uint32_t GetLastError();
+ // GetContext may return NULL even if the MinidumpThread is valid.
+ virtual MinidumpContext* GetContext();
+
+ // The thread ID is used to determine if a thread is the exception thread,
+ // so a special getter is provided to retrieve this data from the
+ // MDRawThread structure. Returns false if the thread ID cannot be
+ // determined.
+ virtual bool GetThreadID(uint32_t *thread_id) const;
+diff --git a/src/processor/call_stack.cc b/src/processor/call_stack.cc
+--- a/src/processor/call_stack.cc
++++ b/src/processor/call_stack.cc
+@@ -44,11 +44,12 @@ CallStack::~CallStack() {
+
+ void CallStack::Clear() {
+ for (vector<StackFrame *>::const_iterator iterator = frames_.begin();
+ iterator != frames_.end();
+ ++iterator) {
+ delete *iterator;
+ }
+ tid_ = 0;
++ last_error_ = 0;
+ }
+
+ } // namespace google_breakpad
+diff --git a/src/processor/minidump.cc b/src/processor/minidump.cc
+--- a/src/processor/minidump.cc
++++ b/src/processor/minidump.cc
+@@ -1567,16 +1567,76 @@ MinidumpMemoryRegion* MinidumpThread::Ge
+ if (!valid_) {
+ BPLOG(ERROR) << "Invalid MinidumpThread for GetMemory";
+ return NULL;
+ }
+
+ return memory_;
+ }
+
++uint32_t MinidumpThread::GetLastError() {
++ if (!valid_) {
++ BPLOG(ERROR) << "Cannot retrieve GetLastError() from an invalid thread";
++ return 0;
++ }
++
++ if (!thread_.teb) {
++ BPLOG(ERROR) << "Cannot retrieve GetLastError() without a valid TEB pointer";
++ return 0;
++ }
++
++ auto memory = minidump_->GetMemoryList();
++ if (!memory) {
++ BPLOG(ERROR) << "Cannot retrieve GetLastError() without a valid memory list";
++ return 0;
++ }
++
++ auto context = GetContext();
++ if (!context) {
++ BPLOG(ERROR) << "Cannot retrieve GetLastError()'s without a valid context";
++ return 0;
++ }
++
++ uint64_t pointer_width = 0;
++ switch (context_->GetContextCPU()) {
++ case MD_CONTEXT_X86:
++ pointer_width = 4;
++ break;
++ case MD_CONTEXT_AMD64:
++ case MD_CONTEXT_ARM64:
++ pointer_width = 8;
++ break;
++ default:
++ BPLOG(ERROR) << "GetLastError() isn't implemented for this CPU type yet";
++ return 0;
++ }
++
++ auto region = memory->GetMemoryRegionForAddress(thread_.teb);
++ if (!region) {
++ BPLOG(ERROR) << "GetLastError()'s memory isn't mapped in this minidump";
++ return 0;
++ }
++
++ // The TEB is opaque but we know the value we want lives at this offset
++ // from reverse engineering.
++ uint64_t offset = pointer_width * 13;
++ uint32_t error = 0;
++ if (!region->GetMemoryAtAddress(thread_.teb + offset, &error)) {
++ BPLOG(ERROR) << "GetLastError()'s memory isn't mapped in this minidump";
++ return 0;
++ }
++
++ if (minidump_->swap()) {
++ Swap(&error);
++ }
++
++ return error;
++}
++
++
+
+ MinidumpContext* MinidumpThread::GetContext() {
+ if (!valid_) {
+ BPLOG(ERROR) << "Invalid MinidumpThread for GetContext";
+ return NULL;
+ }
+
+ if (!context_) {
+diff --git a/src/processor/minidump_processor.cc b/src/processor/minidump_processor.cc
+--- a/src/processor/minidump_processor.cc
++++ b/src/processor/minidump_processor.cc
+@@ -301,16 +301,17 @@ ProcessResult MinidumpProcessor::Process
+ }
+ } else {
+ // Threads with missing CPU contexts will hit this, but
+ // don't abort processing the rest of the dump just for
+ // one bad thread.
+ BPLOG(ERROR) << "No stackwalker for " << thread_string;
+ }
+ stack->set_tid(thread_id);
++ stack->set_last_error(thread->GetLastError());
+ process_state->threads_.push_back(stack.release());
+ process_state->thread_memory_regions_.push_back(thread_memory);
+ }
+
+ if (interrupted) {
+ BPLOG(INFO) << "Processing interrupted for " << dump->path();
+ return PROCESS_SYMBOL_SUPPLIER_INTERRUPTED;
+ }
diff --git a/toolkit/crashreporter/breakpad-patches/17-unloaded-modules.patch b/toolkit/crashreporter/breakpad-patches/17-unloaded-modules.patch
new file mode 100644
index 0000000000..c413e4eff4
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-patches/17-unloaded-modules.patch
@@ -0,0 +1,251 @@
+changeset: 649910:59994b59eb51
+tag: tip
+parent: 649905:058997a8167d
+user: Gabriele Svelto <gsvelto@mozilla.com>
+date: Wed Mar 31 16:25:34 2021 +0200
+summary: Bug 1702043 - Print out the list of unloaded modules when processing a minidump
+
+diff --git a/src/google_breakpad/processor/minidump.h b/src/google_breakpad/processor/minidump.h
+--- a/src/google_breakpad/processor/minidump.h
++++ b/src/google_breakpad/processor/minidump.h
+@@ -792,16 +792,19 @@ class MinidumpUnloadedModule : public Mi
+ string debug_file() const override;
+ string debug_identifier() const override;
+ string version() const override;
+ CodeModule* Copy() const override;
+ bool is_unloaded() const override { return true; }
+ uint64_t shrink_down_delta() const override;
+ void SetShrinkDownDelta(uint64_t shrink_down_delta) override;
+
++ // Print a human-readable representation of the object to stdout.
++ void Print();
++
+ protected:
+ explicit MinidumpUnloadedModule(Minidump* minidump);
+
+ private:
+ // These objects are managed by MinidumpUnloadedModuleList
+ friend class MinidumpUnloadedModuleList;
+
+ // This works like MinidumpStream::Read, but is driven by
+@@ -850,16 +853,19 @@ class MinidumpUnloadedModuleList : publi
+ const MinidumpUnloadedModule* GetMainModule() const override;
+ const MinidumpUnloadedModule*
+ GetModuleAtSequence(unsigned int sequence) const override;
+ const MinidumpUnloadedModule*
+ GetModuleAtIndex(unsigned int index) const override;
+ const CodeModules* Copy() const override;
+ vector<linked_ptr<const CodeModule>> GetShrunkRangeModules() const override;
+
++ // Print a human-readable representation of the object to stdout.
++ void Print();
++
+ protected:
+ explicit MinidumpUnloadedModuleList(Minidump* minidump_);
+
+ private:
+ friend class Minidump;
+
+ typedef vector<MinidumpUnloadedModule> MinidumpUnloadedModules;
+
+diff --git a/src/processor/minidump.cc b/src/processor/minidump.cc
+--- a/src/processor/minidump.cc
++++ b/src/processor/minidump.cc
+@@ -3727,16 +3727,46 @@ MinidumpUnloadedModule::MinidumpUnloaded
+ name_(NULL) {
+
+ }
+
+ MinidumpUnloadedModule::~MinidumpUnloadedModule() {
+ delete name_;
+ }
+
++void MinidumpUnloadedModule::Print() {
++ if (!valid_) {
++ BPLOG(ERROR) << "MinidumpUnloadedModule cannot print invalid data";
++ return;
++ }
++
++ printf("MDRawUnloadedModule\n");
++ printf(" base_of_image = 0x%" PRIx64 "\n",
++ unloaded_module_.base_of_image);
++ printf(" size_of_image = 0x%x\n",
++ unloaded_module_.size_of_image);
++ printf(" checksum = 0x%x\n",
++ unloaded_module_.checksum);
++ printf(" time_date_stamp = 0x%x %s\n",
++ unloaded_module_.time_date_stamp,
++ TimeTToUTCString(unloaded_module_.time_date_stamp).c_str());
++ printf(" module_name_rva = 0x%x\n",
++ unloaded_module_.module_name_rva);
++
++ printf(" (code_file) = \"%s\"\n", code_file().c_str());
++ printf(" (code_identifier) = \"%s\"\n",
++ code_identifier().c_str());
++
++ printf(" (debug_file) = \"%s\"\n", debug_file().c_str());
++ printf(" (debug_identifier) = \"%s\"\n",
++ debug_identifier().c_str());
++ printf(" (version) = \"%s\"\n", version().c_str());
++ printf("\n");
++}
++
+ string MinidumpUnloadedModule::code_file() const {
+ if (!valid_) {
+ BPLOG(ERROR) << "Invalid MinidumpUnloadedModule for code_file";
+ return "";
+ }
+
+ return *name_;
+ }
+@@ -3911,16 +3941,34 @@ MinidumpUnloadedModuleList::MinidumpUnlo
+ range_map_->SetMergeStrategy(MergeRangeStrategy::kTruncateLower);
+ }
+
+ MinidumpUnloadedModuleList::~MinidumpUnloadedModuleList() {
+ delete range_map_;
+ delete unloaded_modules_;
+ }
+
++void MinidumpUnloadedModuleList::Print() {
++ if (!valid_) {
++ BPLOG(ERROR) << "MinidumpUnloadedModuleList cannot print invalid data";
++ return;
++ }
++
++ printf("MinidumpUnloadedModuleList\n");
++ printf(" module_count = %d\n", module_count_);
++ printf("\n");
++
++ for (unsigned int module_index = 0;
++ module_index < module_count_;
++ ++module_index) {
++ printf("module[%d]\n", module_index);
++
++ (*unloaded_modules_)[module_index].Print();
++ }
++}
+
+ bool MinidumpUnloadedModuleList::Read(uint32_t expected_size) {
+ range_map_->Clear();
+ delete unloaded_modules_;
+ unloaded_modules_ = NULL;
+ module_count_ = 0;
+
+ valid_ = false;
+diff --git a/src/processor/minidump_dump.cc b/src/processor/minidump_dump.cc
+--- a/src/processor/minidump_dump.cc
++++ b/src/processor/minidump_dump.cc
+@@ -40,16 +40,17 @@
+ #include "google_breakpad/processor/minidump.h"
+ #include "processor/logging.h"
+
+ namespace {
+
+ using google_breakpad::Minidump;
+ using google_breakpad::MinidumpThreadList;
+ using google_breakpad::MinidumpModuleList;
++using google_breakpad::MinidumpUnloadedModuleList;
+ using google_breakpad::MinidumpMemoryInfoList;
+ using google_breakpad::MinidumpMemoryList;
+ using google_breakpad::MinidumpException;
+ using google_breakpad::MinidumpAssertion;
+ using google_breakpad::MinidumpSystemInfo;
+ using google_breakpad::MinidumpMiscInfo;
+ using google_breakpad::MinidumpBreakpadInfo;
+ using google_breakpad::MinidumpCrashpadInfo;
+@@ -127,16 +128,25 @@ static bool PrintMinidumpDump(const Opti
+ MinidumpModuleList *module_list = minidump.GetModuleList();
+ if (!module_list) {
+ ++errors;
+ BPLOG(ERROR) << "minidump.GetModuleList() failed";
+ } else {
+ module_list->Print();
+ }
+
++ MinidumpUnloadedModuleList::set_max_modules(UINT32_MAX);
++ MinidumpUnloadedModuleList *unloaded_module_list = minidump.GetUnloadedModuleList();
++ if (!unloaded_module_list) {
++ ++errors;
++ BPLOG(ERROR) << "minidump.GetUnloadedModuleList() failed";
++ } else {
++ unloaded_module_list->Print();
++ }
++
+ MinidumpMemoryList *memory_list = minidump.GetMemoryList();
+ if (!memory_list) {
+ ++errors;
+ BPLOG(ERROR) << "minidump.GetMemoryList() failed";
+ } else {
+ memory_list->Print();
+ }
+
+diff --git a/src/processor/stackwalk_common.cc b/src/processor/stackwalk_common.cc
+--- a/src/processor/stackwalk_common.cc
++++ b/src/processor/stackwalk_common.cc
+@@ -777,16 +777,46 @@ static void PrintModulesMachineReadable(
+ StripSeparator(module->debug_identifier()).c_str(),
+ kOutputSeparator, base_address,
+ kOutputSeparator, base_address + module->size() - 1,
+ kOutputSeparator,
+ main_module != NULL && base_address == main_address ? 1 : 0);
+ }
+ }
+
++// PrintUnloadedModulesMachineReadable outputs a list of loaded modules,
++// one per line, in the following machine-readable pipe-delimited
++// text format:
++// UnloadedModule|{Module Filename}|{Base Address}|{Max Address}|{Main}
++static void PrintUnloadedModulesMachineReadable(const CodeModules* modules) {
++ if (!modules)
++ return;
++
++ uint64_t main_address = 0;
++ const CodeModule* main_module = modules->GetMainModule();
++ if (main_module) {
++ main_address = main_module->base_address();
++ }
++
++ unsigned int module_count = modules->module_count();
++ for (unsigned int module_sequence = 0;
++ module_sequence < module_count;
++ ++module_sequence) {
++ const CodeModule* module = modules->GetModuleAtSequence(module_sequence);
++ uint64_t base_address = module->base_address();
++ printf("UnloadedModule%c%s%c0x%08" PRIx64 "%c0x%08" PRIx64 "%c%d\n",
++ kOutputSeparator,
++ StripSeparator(PathnameStripper::File(module->code_file())).c_str(),
++ kOutputSeparator, base_address,
++ kOutputSeparator, base_address + module->size() - 1,
++ kOutputSeparator,
++ main_module != NULL && base_address == main_address ? 1 : 0);
++ }
++}
++
+ } // namespace
+
+ void PrintProcessState(const ProcessState& process_state,
+ bool output_stack_contents,
+ SourceLineResolverInterface* resolver) {
+ // Print OS and CPU information.
+ string cpu = process_state.system_info()->cpu;
+ string cpu_info = process_state.system_info()->cpu_info;
+@@ -921,16 +951,17 @@ void PrintProcessStateMachineReadable(co
+
+ if (requesting_thread != -1) {
+ printf("%d\n", requesting_thread);
+ } else {
+ printf("\n");
+ }
+
+ PrintModulesMachineReadable(process_state.modules());
++ PrintUnloadedModulesMachineReadable(process_state.unloaded_modules());
+
+ // blank line to indicate start of threads
+ printf("\n");
+
+ // If the thread that requested the dump is known, print it first.
+ if (requesting_thread != -1) {
+ PrintStackMachineReadable(requesting_thread,
+ process_state.threads()->at(requesting_thread));
+
diff --git a/toolkit/crashreporter/breakpad-patches/18-fastfail-codes.patch b/toolkit/crashreporter/breakpad-patches/18-fastfail-codes.patch
new file mode 100644
index 0000000000..543f320c46
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-patches/18-fastfail-codes.patch
@@ -0,0 +1,359 @@
+changeset: 651272:ff2582aceafe
+parent: 651260:b740f950e497
+user: Gabriele Svelto <gsvelto@mozilla.com>
+date: Thu Apr 08 12:01:43 2021 +0200
+summary: fastfail
+
+diff --git a/src/google_breakpad/common/minidump_exception_win32.h b/src/google_breakpad/common/minidump_exception_win32.h
+--- a/src/google_breakpad/common/minidump_exception_win32.h
++++ b/src/google_breakpad/common/minidump_exception_win32.h
+@@ -2261,9 +2261,84 @@ typedef enum {
+ // These constants are defined in the MSDN documentation of
+ // the EXCEPTION_RECORD structure.
+ typedef enum {
+ MD_IN_PAGE_ERROR_WIN_READ = 0,
+ MD_IN_PAGE_ERROR_WIN_WRITE = 1,
+ MD_IN_PAGE_ERROR_WIN_EXEC = 8
+ } MDInPageErrorTypeWin;
+
++/* For (MDException).exception_information[0], when (MDException).exception_code
++ * is MD_EXCEPTION_CODE_WIN_STACK_BUFFER_OVERRUN. This describes the underlying
++ * reason for the crash. These values come from winnt.h.
++ *
++ * The content of this enum was created from winnt.h in the 10 SDK
++ * (version 10.0.19041.0) with
++ *
++ * egrep '#define FAST_FAIL_[A-Z_0-9]+\s+[0-9]' winnt.h
++ * | tr -d '\r'
++ * | sed -r 's@#define FAST_FAIL_([A-Z_0-9]+)\s+([0-9]+).*@\2 \1@'
++ * | sed -r 's@([0-9]+) ([A-Z_0-9]+)@ MD_FAST_FAIL_WIN_\2 = \1,@' */
++typedef enum {
++ MD_FAST_FAIL_WIN_LEGACY_GS_VIOLATION = 0,
++ MD_FAST_FAIL_WIN_VTGUARD_CHECK_FAILURE = 1,
++ MD_FAST_FAIL_WIN_STACK_COOKIE_CHECK_FAILURE = 2,
++ MD_FAST_FAIL_WIN_CORRUPT_LIST_ENTRY = 3,
++ MD_FAST_FAIL_WIN_INCORRECT_STACK = 4,
++ MD_FAST_FAIL_WIN_INVALID_ARG = 5,
++ MD_FAST_FAIL_WIN_GS_COOKIE_INIT = 6,
++ MD_FAST_FAIL_WIN_FATAL_APP_EXIT = 7,
++ MD_FAST_FAIL_WIN_RANGE_CHECK_FAILURE = 8,
++ MD_FAST_FAIL_WIN_UNSAFE_REGISTRY_ACCESS = 9,
++ MD_FAST_FAIL_WIN_GUARD_ICALL_CHECK_FAILURE = 10,
++ MD_FAST_FAIL_WIN_GUARD_WRITE_CHECK_FAILURE = 11,
++ MD_FAST_FAIL_WIN_INVALID_FIBER_SWITCH = 12,
++ MD_FAST_FAIL_WIN_INVALID_SET_OF_CONTEXT = 13,
++ MD_FAST_FAIL_WIN_INVALID_REFERENCE_COUNT = 14,
++ MD_FAST_FAIL_WIN_INVALID_JUMP_BUFFER = 18,
++ MD_FAST_FAIL_WIN_MRDATA_MODIFIED = 19,
++ MD_FAST_FAIL_WIN_CERTIFICATION_FAILURE = 20,
++ MD_FAST_FAIL_WIN_INVALID_EXCEPTION_CHAIN = 21,
++ MD_FAST_FAIL_WIN_CRYPTO_LIBRARY = 22,
++ MD_FAST_FAIL_WIN_INVALID_CALL_IN_DLL_CALLOUT = 23,
++ MD_FAST_FAIL_WIN_INVALID_IMAGE_BASE = 24,
++ MD_FAST_FAIL_WIN_DLOAD_PROTECTION_FAILURE = 25,
++ MD_FAST_FAIL_WIN_UNSAFE_EXTENSION_CALL = 26,
++ MD_FAST_FAIL_WIN_DEPRECATED_SERVICE_INVOKED = 27,
++ MD_FAST_FAIL_WIN_INVALID_BUFFER_ACCESS = 28,
++ MD_FAST_FAIL_WIN_INVALID_BALANCED_TREE = 29,
++ MD_FAST_FAIL_WIN_INVALID_NEXT_THREAD = 30,
++ MD_FAST_FAIL_WIN_GUARD_ICALL_CHECK_SUPPRESSED = 31,
++ MD_FAST_FAIL_WIN_APCS_DISABLED = 32,
++ MD_FAST_FAIL_WIN_INVALID_IDLE_STATE = 33,
++ MD_FAST_FAIL_WIN_MRDATA_PROTECTION_FAILURE = 34,
++ MD_FAST_FAIL_WIN_UNEXPECTED_HEAP_EXCEPTION = 35,
++ MD_FAST_FAIL_WIN_INVALID_LOCK_STATE = 36,
++ MD_FAST_FAIL_WIN_GUARD_JUMPTABLE = 37,
++ MD_FAST_FAIL_WIN_INVALID_LONGJUMP_TARGET = 38,
++ MD_FAST_FAIL_WIN_INVALID_DISPATCH_CONTEXT = 39,
++ MD_FAST_FAIL_WIN_INVALID_THREAD = 40,
++ MD_FAST_FAIL_WIN_INVALID_SYSCALL_NUMBER = 41,
++ MD_FAST_FAIL_WIN_INVALID_FILE_OPERATION = 42,
++ MD_FAST_FAIL_WIN_LPAC_ACCESS_DENIED = 43,
++ MD_FAST_FAIL_WIN_GUARD_SS_FAILURE = 44,
++ MD_FAST_FAIL_WIN_LOADER_CONTINUITY_FAILURE = 45,
++ MD_FAST_FAIL_WIN_GUARD_EXPORT_SUPPRESSION_FAILURE = 46,
++ MD_FAST_FAIL_WIN_INVALID_CONTROL_STACK = 47,
++ MD_FAST_FAIL_WIN_SET_CONTEXT_DENIED = 48,
++ MD_FAST_FAIL_WIN_INVALID_IAT = 49,
++ MD_FAST_FAIL_WIN_HEAP_METADATA_CORRUPTION = 50,
++ MD_FAST_FAIL_WIN_PAYLOAD_RESTRICTION_VIOLATION = 51,
++ MD_FAST_FAIL_WIN_LOW_LABEL_ACCESS_DENIED = 52,
++ MD_FAST_FAIL_WIN_ENCLAVE_CALL_FAILURE = 53,
++ MD_FAST_FAIL_WIN_UNHANDLED_LSS_EXCEPTON = 54,
++ MD_FAST_FAIL_WIN_ADMINLESS_ACCESS_DENIED = 55,
++ MD_FAST_FAIL_WIN_UNEXPECTED_CALL = 56,
++ MD_FAST_FAIL_WIN_CONTROL_INVALID_RETURN_ADDRESS = 57,
++ MD_FAST_FAIL_WIN_UNEXPECTED_HOST_BEHAVIOR = 58,
++ MD_FAST_FAIL_WIN_FLAGS_CORRUPTION = 59,
++ MD_FAST_FAIL_WIN_VEH_CORRUPTION = 60,
++ MD_FAST_FAIL_WIN_ETW_CORRUPTION = 61,
++ MD_FAST_FAIL_WIN_RIO_ABORT = 62,
++ MD_FAST_FAIL_WIN_INVALID_PFN = 63,
++} MDFastFailWin;
++
+ #endif /* GOOGLE_BREAKPAD_COMMON_MINIDUMP_EXCEPTION_WIN32_H__ */
+diff --git a/src/processor/minidump_processor.cc b/src/processor/minidump_processor.cc
+--- a/src/processor/minidump_processor.cc
++++ b/src/processor/minidump_processor.cc
+@@ -1288,16 +1288,24 @@ string MinidumpProcessor::GetCrashReason
+ case MD_EXCEPTION_CODE_WIN_BAD_FUNCTION_TABLE:
+ reason = "EXCEPTION_BAD_FUNCTION_TABLE";
+ break;
+ case MD_EXCEPTION_CODE_WIN_POSSIBLE_DEADLOCK:
+ reason = "EXCEPTION_POSSIBLE_DEADLOCK";
+ break;
+ case MD_EXCEPTION_CODE_WIN_STACK_BUFFER_OVERRUN:
+ reason = "EXCEPTION_STACK_BUFFER_OVERRUN";
++ if (raw_exception->exception_record.number_parameters > 0) {
++ uint32_t fast_fail_code =
++ static_cast<uint32_t>
++ (raw_exception->exception_record.exception_information[0]);
++ reason.append(" / ");
++ reason.append(FastFailToString(fast_fail_code));
++ }
++
+ break;
+ case MD_EXCEPTION_CODE_WIN_HEAP_CORRUPTION:
+ reason = "EXCEPTION_HEAP_CORRUPTION";
+ break;
+ case MD_EXCEPTION_OUT_OF_MEMORY:
+ reason = "Out of Memory";
+ break;
+ case MD_EXCEPTION_CODE_WIN_UNHANDLED_CPP_EXCEPTION:
+diff --git a/src/processor/symbolic_constants_win.cc b/src/processor/symbolic_constants_win.cc
+--- a/src/processor/symbolic_constants_win.cc
++++ b/src/processor/symbolic_constants_win.cc
+@@ -6409,9 +6409,214 @@ string NTStatusToString(uint32_t ntstatu
+ snprintf(reason_string, sizeof(reason_string), "0x%08x", ntstatus);
+ reason = reason_string;
+ break;
+ }
+ }
+ return reason;
+ }
+
++string FastFailToString(uint32_t fast_fail_code) {
++ string code_string;
++ // The content of this switch was created from winnt.h in the 10 SDK
++ // (version 10.0.19041.0) with
++ //
++ // egrep '#define FAST_FAIL_[A-Z_0-9]+\s+[0-9]' winnt.h
++ // | tr -d '\r'
++ // | sed -r 's@#define FAST_FAIL_([A-Z_0-9]+)\s+([0-9]+).*@\2 \1@'
++ // | sed -r 's@([0-9]+) ([A-Z_0-9]+)@ case MD_FAST_FAIL_WIN_\2:\n code_string = "FAST_FAIL_\2";\n break;@'
++ //
++ // and then the default case added.
++ switch (fast_fail_code) {
++ case MD_FAST_FAIL_WIN_LEGACY_GS_VIOLATION:
++ code_string = "FAST_FAIL_LEGACY_GS_VIOLATION";
++ break;
++ case MD_FAST_FAIL_WIN_VTGUARD_CHECK_FAILURE:
++ code_string = "FAST_FAIL_VTGUARD_CHECK_FAILURE";
++ break;
++ case MD_FAST_FAIL_WIN_STACK_COOKIE_CHECK_FAILURE:
++ code_string = "FAST_FAIL_STACK_COOKIE_CHECK_FAILURE";
++ break;
++ case MD_FAST_FAIL_WIN_CORRUPT_LIST_ENTRY:
++ code_string = "FAST_FAIL_CORRUPT_LIST_ENTRY";
++ break;
++ case MD_FAST_FAIL_WIN_INCORRECT_STACK:
++ code_string = "FAST_FAIL_INCORRECT_STACK";
++ break;
++ case MD_FAST_FAIL_WIN_INVALID_ARG:
++ code_string = "FAST_FAIL_INVALID_ARG";
++ break;
++ case MD_FAST_FAIL_WIN_GS_COOKIE_INIT:
++ code_string = "FAST_FAIL_GS_COOKIE_INIT";
++ break;
++ case MD_FAST_FAIL_WIN_FATAL_APP_EXIT:
++ code_string = "FAST_FAIL_FATAL_APP_EXIT";
++ break;
++ case MD_FAST_FAIL_WIN_RANGE_CHECK_FAILURE:
++ code_string = "FAST_FAIL_RANGE_CHECK_FAILURE";
++ break;
++ case MD_FAST_FAIL_WIN_UNSAFE_REGISTRY_ACCESS:
++ code_string = "FAST_FAIL_UNSAFE_REGISTRY_ACCESS";
++ break;
++ case MD_FAST_FAIL_WIN_GUARD_ICALL_CHECK_FAILURE:
++ code_string = "FAST_FAIL_GUARD_ICALL_CHECK_FAILURE";
++ break;
++ case MD_FAST_FAIL_WIN_GUARD_WRITE_CHECK_FAILURE:
++ code_string = "FAST_FAIL_GUARD_WRITE_CHECK_FAILURE";
++ break;
++ case MD_FAST_FAIL_WIN_INVALID_FIBER_SWITCH:
++ code_string = "FAST_FAIL_INVALID_FIBER_SWITCH";
++ break;
++ case MD_FAST_FAIL_WIN_INVALID_SET_OF_CONTEXT:
++ code_string = "FAST_FAIL_INVALID_SET_OF_CONTEXT";
++ break;
++ case MD_FAST_FAIL_WIN_INVALID_REFERENCE_COUNT:
++ code_string = "FAST_FAIL_INVALID_REFERENCE_COUNT";
++ break;
++ case MD_FAST_FAIL_WIN_INVALID_JUMP_BUFFER:
++ code_string = "FAST_FAIL_INVALID_JUMP_BUFFER";
++ break;
++ case MD_FAST_FAIL_WIN_MRDATA_MODIFIED:
++ code_string = "FAST_FAIL_MRDATA_MODIFIED";
++ break;
++ case MD_FAST_FAIL_WIN_CERTIFICATION_FAILURE:
++ code_string = "FAST_FAIL_CERTIFICATION_FAILURE";
++ break;
++ case MD_FAST_FAIL_WIN_INVALID_EXCEPTION_CHAIN:
++ code_string = "FAST_FAIL_INVALID_EXCEPTION_CHAIN";
++ break;
++ case MD_FAST_FAIL_WIN_CRYPTO_LIBRARY:
++ code_string = "FAST_FAIL_CRYPTO_LIBRARY";
++ break;
++ case MD_FAST_FAIL_WIN_INVALID_CALL_IN_DLL_CALLOUT:
++ code_string = "FAST_FAIL_INVALID_CALL_IN_DLL_CALLOUT";
++ break;
++ case MD_FAST_FAIL_WIN_INVALID_IMAGE_BASE:
++ code_string = "FAST_FAIL_INVALID_IMAGE_BASE";
++ break;
++ case MD_FAST_FAIL_WIN_DLOAD_PROTECTION_FAILURE:
++ code_string = "FAST_FAIL_DLOAD_PROTECTION_FAILURE";
++ break;
++ case MD_FAST_FAIL_WIN_UNSAFE_EXTENSION_CALL:
++ code_string = "FAST_FAIL_UNSAFE_EXTENSION_CALL";
++ break;
++ case MD_FAST_FAIL_WIN_DEPRECATED_SERVICE_INVOKED:
++ code_string = "FAST_FAIL_DEPRECATED_SERVICE_INVOKED";
++ break;
++ case MD_FAST_FAIL_WIN_INVALID_BUFFER_ACCESS:
++ code_string = "FAST_FAIL_INVALID_BUFFER_ACCESS";
++ break;
++ case MD_FAST_FAIL_WIN_INVALID_BALANCED_TREE:
++ code_string = "FAST_FAIL_INVALID_BALANCED_TREE";
++ break;
++ case MD_FAST_FAIL_WIN_INVALID_NEXT_THREAD:
++ code_string = "FAST_FAIL_INVALID_NEXT_THREAD";
++ break;
++ case MD_FAST_FAIL_WIN_GUARD_ICALL_CHECK_SUPPRESSED:
++ code_string = "FAST_FAIL_GUARD_ICALL_CHECK_SUPPRESSED";
++ break;
++ case MD_FAST_FAIL_WIN_APCS_DISABLED:
++ code_string = "FAST_FAIL_APCS_DISABLED";
++ break;
++ case MD_FAST_FAIL_WIN_INVALID_IDLE_STATE:
++ code_string = "FAST_FAIL_INVALID_IDLE_STATE";
++ break;
++ case MD_FAST_FAIL_WIN_MRDATA_PROTECTION_FAILURE:
++ code_string = "FAST_FAIL_MRDATA_PROTECTION_FAILURE";
++ break;
++ case MD_FAST_FAIL_WIN_UNEXPECTED_HEAP_EXCEPTION:
++ code_string = "FAST_FAIL_UNEXPECTED_HEAP_EXCEPTION";
++ break;
++ case MD_FAST_FAIL_WIN_INVALID_LOCK_STATE:
++ code_string = "FAST_FAIL_INVALID_LOCK_STATE";
++ break;
++ case MD_FAST_FAIL_WIN_GUARD_JUMPTABLE:
++ code_string = "FAST_FAIL_GUARD_JUMPTABLE";
++ break;
++ case MD_FAST_FAIL_WIN_INVALID_LONGJUMP_TARGET:
++ code_string = "FAST_FAIL_INVALID_LONGJUMP_TARGET";
++ break;
++ case MD_FAST_FAIL_WIN_INVALID_DISPATCH_CONTEXT:
++ code_string = "FAST_FAIL_INVALID_DISPATCH_CONTEXT";
++ break;
++ case MD_FAST_FAIL_WIN_INVALID_THREAD:
++ code_string = "FAST_FAIL_INVALID_THREAD";
++ break;
++ case MD_FAST_FAIL_WIN_INVALID_SYSCALL_NUMBER:
++ code_string = "FAST_FAIL_INVALID_SYSCALL_NUMBER";
++ break;
++ case MD_FAST_FAIL_WIN_INVALID_FILE_OPERATION:
++ code_string = "FAST_FAIL_INVALID_FILE_OPERATION";
++ break;
++ case MD_FAST_FAIL_WIN_LPAC_ACCESS_DENIED:
++ code_string = "FAST_FAIL_LPAC_ACCESS_DENIED";
++ break;
++ case MD_FAST_FAIL_WIN_GUARD_SS_FAILURE:
++ code_string = "FAST_FAIL_GUARD_SS_FAILURE";
++ break;
++ case MD_FAST_FAIL_WIN_LOADER_CONTINUITY_FAILURE:
++ code_string = "FAST_FAIL_LOADER_CONTINUITY_FAILURE";
++ break;
++ case MD_FAST_FAIL_WIN_GUARD_EXPORT_SUPPRESSION_FAILURE:
++ code_string = "FAST_FAIL_GUARD_EXPORT_SUPPRESSION_FAILURE";
++ break;
++ case MD_FAST_FAIL_WIN_INVALID_CONTROL_STACK:
++ code_string = "FAST_FAIL_INVALID_CONTROL_STACK";
++ break;
++ case MD_FAST_FAIL_WIN_SET_CONTEXT_DENIED:
++ code_string = "FAST_FAIL_SET_CONTEXT_DENIED";
++ break;
++ case MD_FAST_FAIL_WIN_INVALID_IAT:
++ code_string = "FAST_FAIL_INVALID_IAT";
++ break;
++ case MD_FAST_FAIL_WIN_HEAP_METADATA_CORRUPTION:
++ code_string = "FAST_FAIL_HEAP_METADATA_CORRUPTION";
++ break;
++ case MD_FAST_FAIL_WIN_PAYLOAD_RESTRICTION_VIOLATION:
++ code_string = "FAST_FAIL_PAYLOAD_RESTRICTION_VIOLATION";
++ break;
++ case MD_FAST_FAIL_WIN_LOW_LABEL_ACCESS_DENIED:
++ code_string = "FAST_FAIL_LOW_LABEL_ACCESS_DENIED";
++ break;
++ case MD_FAST_FAIL_WIN_ENCLAVE_CALL_FAILURE:
++ code_string = "FAST_FAIL_ENCLAVE_CALL_FAILURE";
++ break;
++ case MD_FAST_FAIL_WIN_UNHANDLED_LSS_EXCEPTON:
++ code_string = "FAST_FAIL_UNHANDLED_LSS_EXCEPTON";
++ break;
++ case MD_FAST_FAIL_WIN_ADMINLESS_ACCESS_DENIED:
++ code_string = "FAST_FAIL_ADMINLESS_ACCESS_DENIED";
++ break;
++ case MD_FAST_FAIL_WIN_UNEXPECTED_CALL:
++ code_string = "FAST_FAIL_UNEXPECTED_CALL";
++ break;
++ case MD_FAST_FAIL_WIN_CONTROL_INVALID_RETURN_ADDRESS:
++ code_string = "FAST_FAIL_CONTROL_INVALID_RETURN_ADDRESS";
++ break;
++ case MD_FAST_FAIL_WIN_UNEXPECTED_HOST_BEHAVIOR:
++ code_string = "FAST_FAIL_UNEXPECTED_HOST_BEHAVIOR";
++ break;
++ case MD_FAST_FAIL_WIN_FLAGS_CORRUPTION:
++ code_string = "FAST_FAIL_FLAGS_CORRUPTION";
++ break;
++ case MD_FAST_FAIL_WIN_VEH_CORRUPTION:
++ code_string = "FAST_FAIL_VEH_CORRUPTION";
++ break;
++ case MD_FAST_FAIL_WIN_ETW_CORRUPTION:
++ code_string = "FAST_FAIL_ETW_CORRUPTION";
++ break;
++ case MD_FAST_FAIL_WIN_RIO_ABORT:
++ code_string = "FAST_FAIL_RIO_ABORT";
++ break;
++ case MD_FAST_FAIL_WIN_INVALID_PFN:
++ code_string = "FAST_FAIL_INVALID_PFN";
++ break;
++ default: {
++ char buffer[11];
++ snprintf(buffer, sizeof(buffer), "%u", fast_fail_code);
++ code_string = buffer;
++ break;
++ }
++ }
++ return code_string;
++}
++
+ } // namespace google_breakpad
+diff --git a/src/processor/symbolic_constants_win.h b/src/processor/symbolic_constants_win.h
+--- a/src/processor/symbolic_constants_win.h
++++ b/src/processor/symbolic_constants_win.h
+@@ -41,11 +41,14 @@
+ #include "common/using_std_string.h"
+ #include "google_breakpad/common/breakpad_types.h"
+
+ namespace google_breakpad {
+
+ /* Converts a NTSTATUS code to a reason string. */
+ string NTStatusToString(uint32_t ntstatus);
+
++/* Converts a FAST_FAIL code to a reason string. */
++string FastFailToString(uint32_t fast_fail_code);
++
+ } // namespace google_breakpad
+
+ #endif // GOOGLE_BREAKPAD_PROCESSOR_SYMBOLIC_CONSTANTS_WIN_H_
+
diff --git a/toolkit/crashreporter/breakpad-patches/19-updated-ntstatus.patch b/toolkit/crashreporter/breakpad-patches/19-updated-ntstatus.patch
new file mode 100644
index 0000000000..13c6597435
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-patches/19-updated-ntstatus.patch
@@ -0,0 +1,3500 @@
+changeset: 651287:a6a1b6cc572e
+tag: tip
+parent: 651282:232ec0fbbaaa
+user: Gabriele Svelto <gsvelto@mozilla.com>
+date: Thu Apr 08 11:13:10 2021 +0200
+summary: Updated ntstatus.h definitions in Breakpad
+
+diff --git a/src/google_breakpad/common/minidump_exception_win32.h b/src/google_breakpad/common/minidump_exception_win32.h
+--- a/src/google_breakpad/common/minidump_exception_win32.h
++++ b/src/google_breakpad/common/minidump_exception_win32.h
+@@ -39,22 +39,18 @@
+ #ifndef GOOGLE_BREAKPAD_COMMON_MINIDUMP_EXCEPTION_WIN32_H__
+ #define GOOGLE_BREAKPAD_COMMON_MINIDUMP_EXCEPTION_WIN32_H__
+
+ #include <stddef.h>
+
+ #include "google_breakpad/common/breakpad_types.h"
+
+
+-/* For (MDException).exception_code. These values come from WinBase.h
+- * and WinNT.h (names beginning with EXCEPTION_ are in WinBase.h,
+- * they are STATUS_ in WinNT.h). */
++/* For (MDException).exception_code. These values come from WinBase.h */
+ typedef enum {
+- MD_EXCEPTION_CODE_WIN_CONTROL_C = 0x40010005,
+- /* DBG_CONTROL_C */
+ MD_EXCEPTION_CODE_WIN_GUARD_PAGE_VIOLATION = 0x80000001,
+ /* EXCEPTION_GUARD_PAGE */
+ MD_EXCEPTION_CODE_WIN_DATATYPE_MISALIGNMENT = 0x80000002,
+ /* EXCEPTION_DATATYPE_MISALIGNMENT */
+ MD_EXCEPTION_CODE_WIN_BREAKPOINT = 0x80000003,
+ /* EXCEPTION_BREAKPOINT */
+ MD_EXCEPTION_CODE_WIN_SINGLE_STEP = 0x80000004,
+ /* EXCEPTION_SINGLE_STEP */
+@@ -93,51 +89,291 @@ typedef enum {
+ MD_EXCEPTION_CODE_WIN_PRIVILEGED_INSTRUCTION = 0xc0000096,
+ /* EXCEPTION_PRIV_INSTRUCTION */
+ MD_EXCEPTION_CODE_WIN_STACK_OVERFLOW = 0xc00000fd,
+ /* EXCEPTION_STACK_OVERFLOW */
+ MD_EXCEPTION_CODE_WIN_BAD_FUNCTION_TABLE = 0xc00000ff,
+ /* EXCEPTION_BAD_FUNCTION_TABLE */
+ MD_EXCEPTION_CODE_WIN_POSSIBLE_DEADLOCK = 0xc0000194,
+ /* EXCEPTION_POSSIBLE_DEADLOCK */
+- MD_EXCEPTION_CODE_WIN_STACK_BUFFER_OVERRUN = 0xc0000409,
+- /* STATUS_STACK_BUFFER_OVERRUN */
+- MD_EXCEPTION_CODE_WIN_HEAP_CORRUPTION = 0xc0000374,
+- /* STATUS_HEAP_CORRUPTION */
+ MD_EXCEPTION_OUT_OF_MEMORY = 0xe0000008,
+ /* Exception thrown by Chromium allocators to indicate OOM.
+ See base/process/memory.h in Chromium for rationale. */
+ MD_EXCEPTION_CODE_WIN_UNHANDLED_CPP_EXCEPTION = 0xe06d7363,
+ /* Per http://support.microsoft.com/kb/185294,
+ generated by Visual C++ compiler */
+ MD_EXCEPTION_CODE_WIN_SIMULATED = 0x0517a7ed
+ /* Fake exception code used by Crashpad's
+ CrashpadClient::DumpWithoutCrash. */
+ } MDExceptionCodeWin;
+
+
+ /* For (MDException).exception_information[2], when (MDException).exception_code
+ * is MD_EXCEPTION_CODE_WIN_IN_PAGE_ERROR. This describes the underlying reason
+ * for the error. These values come from ntstatus.h.
+ *
+- * The content of this enum was created from ntstatus.h in the 8.1 SDK with
++ * The content of this enum was created from ntstatus.h in the 10 SDK
++ * (version 10.0.19041.0) with
+ *
+- * egrep '#define [A-Z_0-9]+\s+\(\(NTSTATUS\)0xC[0-9A-F]+L\)' ntstatus.h
++ * egrep '#define [A-Z_0-9]+\s+\(\(NTSTATUS\)0x[048C][0-9A-F]+L\)' ntstatus.h
+ * | tr -d '\r'
+- * | sed -r 's@#define ([A-Z_0-9]+)\s+\(\(NTSTATUS\)(0xC[0-9A-F]+)L\).*@\2 \1@'
++ * | sed -r 's@#define ([A-Z_0-9]+)\s+\(\(NTSTATUS\)(0x[048C][0-9A-F]+)L\).*@\2 \1@'
+ * | sort
+- * | sed -r 's@(0xC[0-9A-F]+) ([A-Z_0-9]+)@ MD_NTSTATUS_WIN_\2 = \1,@'
++ * | sed -r 's@(0x[048C][0-9A-F]+) ([A-Z_0-9]+)@ MD_NTSTATUS_WIN_\2 = \1,@'
+ *
+ * With easy copy to clipboard with
+ * | xclip -selection c # on linux
+ * | clip # on windows
+- * | pbcopy # on mac
+- *
+- * and then the last comma manually removed. */
++ * | pbcopy # on mac */
+ typedef enum {
++ MD_NTSTATUS_WIN_STATUS_SUCCESS = 0x00000000,
++ MD_NTSTATUS_WIN_STATUS_WAIT_0 = 0x00000000,
++ MD_NTSTATUS_WIN_STATUS_WAIT_1 = 0x00000001,
++ MD_NTSTATUS_WIN_STATUS_WAIT_2 = 0x00000002,
++ MD_NTSTATUS_WIN_STATUS_WAIT_3 = 0x00000003,
++ MD_NTSTATUS_WIN_STATUS_WAIT_63 = 0x0000003F,
++ MD_NTSTATUS_WIN_STATUS_ABANDONED = 0x00000080,
++ MD_NTSTATUS_WIN_STATUS_ABANDONED_WAIT_0 = 0x00000080,
++ MD_NTSTATUS_WIN_STATUS_ABANDONED_WAIT_63 = 0x000000BF,
++ MD_NTSTATUS_WIN_STATUS_USER_APC = 0x000000C0,
++ MD_NTSTATUS_WIN_STATUS_ALREADY_COMPLETE = 0x000000FF,
++ MD_NTSTATUS_WIN_STATUS_KERNEL_APC = 0x00000100,
++ MD_NTSTATUS_WIN_STATUS_ALERTED = 0x00000101,
++ MD_NTSTATUS_WIN_STATUS_TIMEOUT = 0x00000102,
++ MD_NTSTATUS_WIN_STATUS_PENDING = 0x00000103,
++ MD_NTSTATUS_WIN_STATUS_REPARSE = 0x00000104,
++ MD_NTSTATUS_WIN_STATUS_MORE_ENTRIES = 0x00000105,
++ MD_NTSTATUS_WIN_STATUS_NOT_ALL_ASSIGNED = 0x00000106,
++ MD_NTSTATUS_WIN_STATUS_SOME_NOT_MAPPED = 0x00000107,
++ MD_NTSTATUS_WIN_STATUS_OPLOCK_BREAK_IN_PROGRESS = 0x00000108,
++ MD_NTSTATUS_WIN_STATUS_VOLUME_MOUNTED = 0x00000109,
++ MD_NTSTATUS_WIN_STATUS_RXACT_COMMITTED = 0x0000010A,
++ MD_NTSTATUS_WIN_STATUS_NOTIFY_CLEANUP = 0x0000010B,
++ MD_NTSTATUS_WIN_STATUS_NOTIFY_ENUM_DIR = 0x0000010C,
++ MD_NTSTATUS_WIN_STATUS_NO_QUOTAS_FOR_ACCOUNT = 0x0000010D,
++ MD_NTSTATUS_WIN_STATUS_PRIMARY_TRANSPORT_CONNECT_FAILED = 0x0000010E,
++ MD_NTSTATUS_WIN_STATUS_PAGE_FAULT_TRANSITION = 0x00000110,
++ MD_NTSTATUS_WIN_STATUS_PAGE_FAULT_DEMAND_ZERO = 0x00000111,
++ MD_NTSTATUS_WIN_STATUS_PAGE_FAULT_COPY_ON_WRITE = 0x00000112,
++ MD_NTSTATUS_WIN_STATUS_PAGE_FAULT_GUARD_PAGE = 0x00000113,
++ MD_NTSTATUS_WIN_STATUS_PAGE_FAULT_PAGING_FILE = 0x00000114,
++ MD_NTSTATUS_WIN_STATUS_CACHE_PAGE_LOCKED = 0x00000115,
++ MD_NTSTATUS_WIN_STATUS_CRASH_DUMP = 0x00000116,
++ MD_NTSTATUS_WIN_STATUS_BUFFER_ALL_ZEROS = 0x00000117,
++ MD_NTSTATUS_WIN_STATUS_REPARSE_OBJECT = 0x00000118,
++ MD_NTSTATUS_WIN_STATUS_RESOURCE_REQUIREMENTS_CHANGED = 0x00000119,
++ MD_NTSTATUS_WIN_STATUS_TRANSLATION_COMPLETE = 0x00000120,
++ MD_NTSTATUS_WIN_STATUS_DS_MEMBERSHIP_EVALUATED_LOCALLY = 0x00000121,
++ MD_NTSTATUS_WIN_STATUS_NOTHING_TO_TERMINATE = 0x00000122,
++ MD_NTSTATUS_WIN_STATUS_PROCESS_NOT_IN_JOB = 0x00000123,
++ MD_NTSTATUS_WIN_STATUS_PROCESS_IN_JOB = 0x00000124,
++ MD_NTSTATUS_WIN_STATUS_VOLSNAP_HIBERNATE_READY = 0x00000125,
++ MD_NTSTATUS_WIN_STATUS_FSFILTER_OP_COMPLETED_SUCCESSFULLY = 0x00000126,
++ MD_NTSTATUS_WIN_STATUS_INTERRUPT_VECTOR_ALREADY_CONNECTED = 0x00000127,
++ MD_NTSTATUS_WIN_STATUS_INTERRUPT_STILL_CONNECTED = 0x00000128,
++ MD_NTSTATUS_WIN_STATUS_PROCESS_CLONED = 0x00000129,
++ MD_NTSTATUS_WIN_STATUS_FILE_LOCKED_WITH_ONLY_READERS = 0x0000012A,
++ MD_NTSTATUS_WIN_STATUS_FILE_LOCKED_WITH_WRITERS = 0x0000012B,
++ MD_NTSTATUS_WIN_STATUS_VALID_IMAGE_HASH = 0x0000012C,
++ MD_NTSTATUS_WIN_STATUS_VALID_CATALOG_HASH = 0x0000012D,
++ MD_NTSTATUS_WIN_STATUS_VALID_STRONG_CODE_HASH = 0x0000012E,
++ MD_NTSTATUS_WIN_STATUS_GHOSTED = 0x0000012F,
++ MD_NTSTATUS_WIN_STATUS_DATA_OVERWRITTEN = 0x00000130,
++ MD_NTSTATUS_WIN_STATUS_RESOURCEMANAGER_READ_ONLY = 0x00000202,
++ MD_NTSTATUS_WIN_STATUS_RING_PREVIOUSLY_EMPTY = 0x00000210,
++ MD_NTSTATUS_WIN_STATUS_RING_PREVIOUSLY_FULL = 0x00000211,
++ MD_NTSTATUS_WIN_STATUS_RING_PREVIOUSLY_ABOVE_QUOTA = 0x00000212,
++ MD_NTSTATUS_WIN_STATUS_RING_NEWLY_EMPTY = 0x00000213,
++ MD_NTSTATUS_WIN_STATUS_RING_SIGNAL_OPPOSITE_ENDPOINT = 0x00000214,
++ MD_NTSTATUS_WIN_STATUS_OPLOCK_SWITCHED_TO_NEW_HANDLE = 0x00000215,
++ MD_NTSTATUS_WIN_STATUS_OPLOCK_HANDLE_CLOSED = 0x00000216,
++ MD_NTSTATUS_WIN_STATUS_WAIT_FOR_OPLOCK = 0x00000367,
++ MD_NTSTATUS_WIN_STATUS_REPARSE_GLOBAL = 0x00000368,
++ MD_NTSTATUS_WIN_DBG_EXCEPTION_HANDLED = 0x00010001,
++ MD_NTSTATUS_WIN_DBG_CONTINUE = 0x00010002,
++ MD_NTSTATUS_WIN_STATUS_FLT_IO_COMPLETE = 0x001C0001,
++ MD_NTSTATUS_WIN_STATUS_RTPM_CONTEXT_CONTINUE = 0x00293000,
++ MD_NTSTATUS_WIN_STATUS_RTPM_CONTEXT_COMPLETE = 0x00293001,
++ MD_NTSTATUS_WIN_STATUS_HV_PENDING_PAGE_REQUESTS = 0x00350059,
++ MD_NTSTATUS_WIN_STATUS_SPACES_REPAIRED = 0x00E70000,
++ MD_NTSTATUS_WIN_STATUS_SPACES_PAUSE = 0x00E70001,
++ MD_NTSTATUS_WIN_STATUS_SPACES_COMPLETE = 0x00E70002,
++ MD_NTSTATUS_WIN_STATUS_SPACES_REDIRECT = 0x00E70003,
++ MD_NTSTATUS_WIN_STATUS_OBJECT_NAME_EXISTS = 0x40000000,
++ MD_NTSTATUS_WIN_STATUS_THREAD_WAS_SUSPENDED = 0x40000001,
++ MD_NTSTATUS_WIN_STATUS_WORKING_SET_LIMIT_RANGE = 0x40000002,
++ MD_NTSTATUS_WIN_STATUS_IMAGE_NOT_AT_BASE = 0x40000003,
++ MD_NTSTATUS_WIN_STATUS_RXACT_STATE_CREATED = 0x40000004,
++ MD_NTSTATUS_WIN_STATUS_SEGMENT_NOTIFICATION = 0x40000005,
++ MD_NTSTATUS_WIN_STATUS_LOCAL_USER_SESSION_KEY = 0x40000006,
++ MD_NTSTATUS_WIN_STATUS_BAD_CURRENT_DIRECTORY = 0x40000007,
++ MD_NTSTATUS_WIN_STATUS_SERIAL_MORE_WRITES = 0x40000008,
++ MD_NTSTATUS_WIN_STATUS_REGISTRY_RECOVERED = 0x40000009,
++ MD_NTSTATUS_WIN_STATUS_FT_READ_RECOVERY_FROM_BACKUP = 0x4000000A,
++ MD_NTSTATUS_WIN_STATUS_FT_WRITE_RECOVERY = 0x4000000B,
++ MD_NTSTATUS_WIN_STATUS_SERIAL_COUNTER_TIMEOUT = 0x4000000C,
++ MD_NTSTATUS_WIN_STATUS_NULL_LM_PASSWORD = 0x4000000D,
++ MD_NTSTATUS_WIN_STATUS_IMAGE_MACHINE_TYPE_MISMATCH = 0x4000000E,
++ MD_NTSTATUS_WIN_STATUS_RECEIVE_PARTIAL = 0x4000000F,
++ MD_NTSTATUS_WIN_STATUS_RECEIVE_EXPEDITED = 0x40000010,
++ MD_NTSTATUS_WIN_STATUS_RECEIVE_PARTIAL_EXPEDITED = 0x40000011,
++ MD_NTSTATUS_WIN_STATUS_EVENT_DONE = 0x40000012,
++ MD_NTSTATUS_WIN_STATUS_EVENT_PENDING = 0x40000013,
++ MD_NTSTATUS_WIN_STATUS_CHECKING_FILE_SYSTEM = 0x40000014,
++ MD_NTSTATUS_WIN_STATUS_FATAL_APP_EXIT = 0x40000015,
++ MD_NTSTATUS_WIN_STATUS_PREDEFINED_HANDLE = 0x40000016,
++ MD_NTSTATUS_WIN_STATUS_WAS_UNLOCKED = 0x40000017,
++ MD_NTSTATUS_WIN_STATUS_SERVICE_NOTIFICATION = 0x40000018,
++ MD_NTSTATUS_WIN_STATUS_WAS_LOCKED = 0x40000019,
++ MD_NTSTATUS_WIN_STATUS_LOG_HARD_ERROR = 0x4000001A,
++ MD_NTSTATUS_WIN_STATUS_ALREADY_WIN32 = 0x4000001B,
++ MD_NTSTATUS_WIN_STATUS_WX86_UNSIMULATE = 0x4000001C,
++ MD_NTSTATUS_WIN_STATUS_WX86_CONTINUE = 0x4000001D,
++ MD_NTSTATUS_WIN_STATUS_WX86_SINGLE_STEP = 0x4000001E,
++ MD_NTSTATUS_WIN_STATUS_WX86_BREAKPOINT = 0x4000001F,
++ MD_NTSTATUS_WIN_STATUS_WX86_EXCEPTION_CONTINUE = 0x40000020,
++ MD_NTSTATUS_WIN_STATUS_WX86_EXCEPTION_LASTCHANCE = 0x40000021,
++ MD_NTSTATUS_WIN_STATUS_WX86_EXCEPTION_CHAIN = 0x40000022,
++ MD_NTSTATUS_WIN_STATUS_IMAGE_MACHINE_TYPE_MISMATCH_EXE = 0x40000023,
++ MD_NTSTATUS_WIN_STATUS_NO_YIELD_PERFORMED = 0x40000024,
++ MD_NTSTATUS_WIN_STATUS_TIMER_RESUME_IGNORED = 0x40000025,
++ MD_NTSTATUS_WIN_STATUS_ARBITRATION_UNHANDLED = 0x40000026,
++ MD_NTSTATUS_WIN_STATUS_CARDBUS_NOT_SUPPORTED = 0x40000027,
++ MD_NTSTATUS_WIN_STATUS_WX86_CREATEWX86TIB = 0x40000028,
++ MD_NTSTATUS_WIN_STATUS_MP_PROCESSOR_MISMATCH = 0x40000029,
++ MD_NTSTATUS_WIN_STATUS_HIBERNATED = 0x4000002A,
++ MD_NTSTATUS_WIN_STATUS_RESUME_HIBERNATION = 0x4000002B,
++ MD_NTSTATUS_WIN_STATUS_FIRMWARE_UPDATED = 0x4000002C,
++ MD_NTSTATUS_WIN_STATUS_DRIVERS_LEAKING_LOCKED_PAGES = 0x4000002D,
++ MD_NTSTATUS_WIN_STATUS_MESSAGE_RETRIEVED = 0x4000002E,
++ MD_NTSTATUS_WIN_STATUS_SYSTEM_POWERSTATE_TRANSITION = 0x4000002F,
++ MD_NTSTATUS_WIN_STATUS_ALPC_CHECK_COMPLETION_LIST = 0x40000030,
++ MD_NTSTATUS_WIN_STATUS_SYSTEM_POWERSTATE_COMPLEX_TRANSITION = 0x40000031,
++ MD_NTSTATUS_WIN_STATUS_ACCESS_AUDIT_BY_POLICY = 0x40000032,
++ MD_NTSTATUS_WIN_STATUS_ABANDON_HIBERFILE = 0x40000033,
++ MD_NTSTATUS_WIN_STATUS_BIZRULES_NOT_ENABLED = 0x40000034,
++ MD_NTSTATUS_WIN_STATUS_FT_READ_FROM_COPY = 0x40000035,
++ MD_NTSTATUS_WIN_STATUS_IMAGE_AT_DIFFERENT_BASE = 0x40000036,
++ MD_NTSTATUS_WIN_STATUS_PATCH_DEFERRED = 0x40000037,
++ MD_NTSTATUS_WIN_STATUS_WAKE_SYSTEM = 0x40000294,
++ MD_NTSTATUS_WIN_STATUS_DS_SHUTTING_DOWN = 0x40000370,
++ MD_NTSTATUS_WIN_STATUS_DISK_REPAIR_REDIRECTED = 0x40000807,
++ MD_NTSTATUS_WIN_STATUS_SERVICES_FAILED_AUTOSTART = 0x4000A144,
++ MD_NTSTATUS_WIN_DBG_REPLY_LATER = 0x40010001,
++ MD_NTSTATUS_WIN_DBG_UNABLE_TO_PROVIDE_HANDLE = 0x40010002,
++ MD_NTSTATUS_WIN_DBG_TERMINATE_THREAD = 0x40010003,
++ MD_NTSTATUS_WIN_DBG_TERMINATE_PROCESS = 0x40010004,
++ MD_NTSTATUS_WIN_DBG_CONTROL_C = 0x40010005,
++ MD_NTSTATUS_WIN_DBG_PRINTEXCEPTION_C = 0x40010006,
++ MD_NTSTATUS_WIN_DBG_RIPEXCEPTION = 0x40010007,
++ MD_NTSTATUS_WIN_DBG_CONTROL_BREAK = 0x40010008,
++ MD_NTSTATUS_WIN_DBG_COMMAND_EXCEPTION = 0x40010009,
++ MD_NTSTATUS_WIN_DBG_PRINTEXCEPTION_WIDE_C = 0x4001000A,
++ MD_NTSTATUS_WIN_RPC_NT_UUID_LOCAL_ONLY = 0x40020056,
++ MD_NTSTATUS_WIN_RPC_NT_SEND_INCOMPLETE = 0x400200AF,
++ MD_NTSTATUS_WIN_STATUS_CTX_CDM_CONNECT = 0x400A0004,
++ MD_NTSTATUS_WIN_STATUS_CTX_CDM_DISCONNECT = 0x400A0005,
++ MD_NTSTATUS_WIN_STATUS_SXS_RELEASE_ACTIVATION_CONTEXT = 0x4015000D,
++ MD_NTSTATUS_WIN_STATUS_HEURISTIC_DAMAGE_POSSIBLE = 0x40190001,
++ MD_NTSTATUS_WIN_STATUS_RECOVERY_NOT_NEEDED = 0x40190034,
++ MD_NTSTATUS_WIN_STATUS_RM_ALREADY_STARTED = 0x40190035,
++ MD_NTSTATUS_WIN_STATUS_LOG_NO_RESTART = 0x401A000C,
++ MD_NTSTATUS_WIN_STATUS_VIDEO_DRIVER_DEBUG_REPORT_REQUEST = 0x401B00EC,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_PARTIAL_DATA_POPULATED = 0x401E000A,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_SKIP_ALLOCATION_PREPARATION = 0x401E0201,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_MODE_NOT_PINNED = 0x401E0307,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_NO_PREFERRED_MODE = 0x401E031E,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_DATASET_IS_EMPTY = 0x401E034B,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_NO_MORE_ELEMENTS_IN_DATASET = 0x401E034C,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_PATH_CONTENT_GEOMETRY_TRANSFORMATION_NOT_PINNED = 0x401E0351,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_UNKNOWN_CHILD_STATUS = 0x401E042F,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_LEADLINK_START_DEFERRED = 0x401E0437,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_POLLING_TOO_FREQUENTLY = 0x401E0439,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_START_DEFERRED = 0x401E043A,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_DEPENDABLE_CHILD_STATUS = 0x401E043C,
++ MD_NTSTATUS_WIN_STATUS_NDIS_INDICATION_REQUIRED = 0x40230001,
++ MD_NTSTATUS_WIN_STATUS_PCP_UNSUPPORTED_PSS_SALT = 0x40292023,
++ MD_NTSTATUS_WIN_STATUS_GUARD_PAGE_VIOLATION = 0x80000001,
++ MD_NTSTATUS_WIN_STATUS_DATATYPE_MISALIGNMENT = 0x80000002,
++ MD_NTSTATUS_WIN_STATUS_BREAKPOINT = 0x80000003,
++ MD_NTSTATUS_WIN_STATUS_SINGLE_STEP = 0x80000004,
++ MD_NTSTATUS_WIN_STATUS_BUFFER_OVERFLOW = 0x80000005,
++ MD_NTSTATUS_WIN_STATUS_NO_MORE_FILES = 0x80000006,
++ MD_NTSTATUS_WIN_STATUS_WAKE_SYSTEM_DEBUGGER = 0x80000007,
++ MD_NTSTATUS_WIN_STATUS_HANDLES_CLOSED = 0x8000000A,
++ MD_NTSTATUS_WIN_STATUS_NO_INHERITANCE = 0x8000000B,
++ MD_NTSTATUS_WIN_STATUS_GUID_SUBSTITUTION_MADE = 0x8000000C,
++ MD_NTSTATUS_WIN_STATUS_PARTIAL_COPY = 0x8000000D,
++ MD_NTSTATUS_WIN_STATUS_DEVICE_PAPER_EMPTY = 0x8000000E,
++ MD_NTSTATUS_WIN_STATUS_DEVICE_POWERED_OFF = 0x8000000F,
++ MD_NTSTATUS_WIN_STATUS_DEVICE_OFF_LINE = 0x80000010,
++ MD_NTSTATUS_WIN_STATUS_DEVICE_BUSY = 0x80000011,
++ MD_NTSTATUS_WIN_STATUS_NO_MORE_EAS = 0x80000012,
++ MD_NTSTATUS_WIN_STATUS_INVALID_EA_NAME = 0x80000013,
++ MD_NTSTATUS_WIN_STATUS_EA_LIST_INCONSISTENT = 0x80000014,
++ MD_NTSTATUS_WIN_STATUS_INVALID_EA_FLAG = 0x80000015,
++ MD_NTSTATUS_WIN_STATUS_VERIFY_REQUIRED = 0x80000016,
++ MD_NTSTATUS_WIN_STATUS_EXTRANEOUS_INFORMATION = 0x80000017,
++ MD_NTSTATUS_WIN_STATUS_RXACT_COMMIT_NECESSARY = 0x80000018,
++ MD_NTSTATUS_WIN_STATUS_NO_MORE_ENTRIES = 0x8000001A,
++ MD_NTSTATUS_WIN_STATUS_FILEMARK_DETECTED = 0x8000001B,
++ MD_NTSTATUS_WIN_STATUS_MEDIA_CHANGED = 0x8000001C,
++ MD_NTSTATUS_WIN_STATUS_BUS_RESET = 0x8000001D,
++ MD_NTSTATUS_WIN_STATUS_END_OF_MEDIA = 0x8000001E,
++ MD_NTSTATUS_WIN_STATUS_BEGINNING_OF_MEDIA = 0x8000001F,
++ MD_NTSTATUS_WIN_STATUS_MEDIA_CHECK = 0x80000020,
++ MD_NTSTATUS_WIN_STATUS_SETMARK_DETECTED = 0x80000021,
++ MD_NTSTATUS_WIN_STATUS_NO_DATA_DETECTED = 0x80000022,
++ MD_NTSTATUS_WIN_STATUS_REDIRECTOR_HAS_OPEN_HANDLES = 0x80000023,
++ MD_NTSTATUS_WIN_STATUS_SERVER_HAS_OPEN_HANDLES = 0x80000024,
++ MD_NTSTATUS_WIN_STATUS_ALREADY_DISCONNECTED = 0x80000025,
++ MD_NTSTATUS_WIN_STATUS_LONGJUMP = 0x80000026,
++ MD_NTSTATUS_WIN_STATUS_CLEANER_CARTRIDGE_INSTALLED = 0x80000027,
++ MD_NTSTATUS_WIN_STATUS_PLUGPLAY_QUERY_VETOED = 0x80000028,
++ MD_NTSTATUS_WIN_STATUS_UNWIND_CONSOLIDATE = 0x80000029,
++ MD_NTSTATUS_WIN_STATUS_REGISTRY_HIVE_RECOVERED = 0x8000002A,
++ MD_NTSTATUS_WIN_STATUS_DLL_MIGHT_BE_INSECURE = 0x8000002B,
++ MD_NTSTATUS_WIN_STATUS_DLL_MIGHT_BE_INCOMPATIBLE = 0x8000002C,
++ MD_NTSTATUS_WIN_STATUS_STOPPED_ON_SYMLINK = 0x8000002D,
++ MD_NTSTATUS_WIN_STATUS_CANNOT_GRANT_REQUESTED_OPLOCK = 0x8000002E,
++ MD_NTSTATUS_WIN_STATUS_NO_ACE_CONDITION = 0x8000002F,
++ MD_NTSTATUS_WIN_STATUS_DEVICE_SUPPORT_IN_PROGRESS = 0x80000030,
++ MD_NTSTATUS_WIN_STATUS_DEVICE_POWER_CYCLE_REQUIRED = 0x80000031,
++ MD_NTSTATUS_WIN_STATUS_NO_WORK_DONE = 0x80000032,
++ MD_NTSTATUS_WIN_STATUS_RETURN_ADDRESS_HIJACK_ATTEMPT = 0x80000033,
++ MD_NTSTATUS_WIN_STATUS_DEVICE_REQUIRES_CLEANING = 0x80000288,
++ MD_NTSTATUS_WIN_STATUS_DEVICE_DOOR_OPEN = 0x80000289,
++ MD_NTSTATUS_WIN_STATUS_DATA_LOST_REPAIR = 0x80000803,
++ MD_NTSTATUS_WIN_STATUS_GPIO_INTERRUPT_ALREADY_UNMASKED = 0x8000A127,
++ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_PROPERTY_BLOB_CHECKSUM_MISMATCH = 0x8000CF00,
++ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_PROPERTY_BLOB_TOO_LARGE = 0x8000CF04,
++ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_TOO_MANY_PROPERTY_BLOBS = 0x8000CF05,
++ MD_NTSTATUS_WIN_DBG_EXCEPTION_NOT_HANDLED = 0x80010001,
++ MD_NTSTATUS_WIN_STATUS_CLUSTER_NODE_ALREADY_UP = 0x80130001,
++ MD_NTSTATUS_WIN_STATUS_CLUSTER_NODE_ALREADY_DOWN = 0x80130002,
++ MD_NTSTATUS_WIN_STATUS_CLUSTER_NETWORK_ALREADY_ONLINE = 0x80130003,
++ MD_NTSTATUS_WIN_STATUS_CLUSTER_NETWORK_ALREADY_OFFLINE = 0x80130004,
++ MD_NTSTATUS_WIN_STATUS_CLUSTER_NODE_ALREADY_MEMBER = 0x80130005,
++ MD_NTSTATUS_WIN_STATUS_COULD_NOT_RESIZE_LOG = 0x80190009,
++ MD_NTSTATUS_WIN_STATUS_NO_TXF_METADATA = 0x80190029,
++ MD_NTSTATUS_WIN_STATUS_CANT_RECOVER_WITH_HANDLE_OPEN = 0x80190031,
++ MD_NTSTATUS_WIN_STATUS_TXF_METADATA_ALREADY_PRESENT = 0x80190041,
++ MD_NTSTATUS_WIN_STATUS_TRANSACTION_SCOPE_CALLBACKS_NOT_SET = 0x80190042,
++ MD_NTSTATUS_WIN_STATUS_VIDEO_HUNG_DISPLAY_DRIVER_THREAD_RECOVERED = 0x801B00EB,
++ MD_NTSTATUS_WIN_STATUS_FLT_BUFFER_TOO_SMALL = 0x801C0001,
++ MD_NTSTATUS_WIN_STATUS_FVE_PARTIAL_METADATA = 0x80210001,
++ MD_NTSTATUS_WIN_STATUS_FVE_TRANSIENT_STATE = 0x80210002,
++ MD_NTSTATUS_WIN_STATUS_VID_REMOTE_NODE_PARENT_GPA_PAGES_USED = 0x80370001,
++ MD_NTSTATUS_WIN_STATUS_VOLMGR_INCOMPLETE_REGENERATION = 0x80380001,
++ MD_NTSTATUS_WIN_STATUS_VOLMGR_INCOMPLETE_DISK_MIGRATION = 0x80380002,
++ MD_NTSTATUS_WIN_STATUS_BCD_NOT_ALL_ENTRIES_IMPORTED = 0x80390001,
++ MD_NTSTATUS_WIN_STATUS_BCD_NOT_ALL_ENTRIES_SYNCHRONIZED = 0x80390003,
++ MD_NTSTATUS_WIN_STATUS_QUERY_STORAGE_ERROR = 0x803A0001,
++ MD_NTSTATUS_WIN_STATUS_GDI_HANDLE_LEAK = 0x803F0001,
++ MD_NTSTATUS_WIN_STATUS_SECUREBOOT_NOT_ENABLED = 0x80430006,
+ MD_NTSTATUS_WIN_STATUS_UNSUCCESSFUL = 0xC0000001,
+ MD_NTSTATUS_WIN_STATUS_NOT_IMPLEMENTED = 0xC0000002,
+ MD_NTSTATUS_WIN_STATUS_INVALID_INFO_CLASS = 0xC0000003,
+ MD_NTSTATUS_WIN_STATUS_INFO_LENGTH_MISMATCH = 0xC0000004,
+ MD_NTSTATUS_WIN_STATUS_ACCESS_VIOLATION = 0xC0000005,
+ MD_NTSTATUS_WIN_STATUS_IN_PAGE_ERROR = 0xC0000006,
+ MD_NTSTATUS_WIN_STATUS_PAGEFILE_QUOTA = 0xC0000007,
+ MD_NTSTATUS_WIN_STATUS_INVALID_HANDLE = 0xC0000008,
+@@ -181,16 +417,17 @@ typedef enum {
+ MD_NTSTATUS_WIN_STATUS_INVALID_PORT_ATTRIBUTES = 0xC000002E,
+ MD_NTSTATUS_WIN_STATUS_PORT_MESSAGE_TOO_LONG = 0xC000002F,
+ MD_NTSTATUS_WIN_STATUS_INVALID_PARAMETER_MIX = 0xC0000030,
+ MD_NTSTATUS_WIN_STATUS_INVALID_QUOTA_LOWER = 0xC0000031,
+ MD_NTSTATUS_WIN_STATUS_DISK_CORRUPT_ERROR = 0xC0000032,
+ MD_NTSTATUS_WIN_STATUS_OBJECT_NAME_INVALID = 0xC0000033,
+ MD_NTSTATUS_WIN_STATUS_OBJECT_NAME_NOT_FOUND = 0xC0000034,
+ MD_NTSTATUS_WIN_STATUS_OBJECT_NAME_COLLISION = 0xC0000035,
++ MD_NTSTATUS_WIN_STATUS_PORT_DO_NOT_DISTURB = 0xC0000036,
+ MD_NTSTATUS_WIN_STATUS_PORT_DISCONNECTED = 0xC0000037,
+ MD_NTSTATUS_WIN_STATUS_DEVICE_ALREADY_ATTACHED = 0xC0000038,
+ MD_NTSTATUS_WIN_STATUS_OBJECT_PATH_INVALID = 0xC0000039,
+ MD_NTSTATUS_WIN_STATUS_OBJECT_PATH_NOT_FOUND = 0xC000003A,
+ MD_NTSTATUS_WIN_STATUS_OBJECT_PATH_SYNTAX_BAD = 0xC000003B,
+ MD_NTSTATUS_WIN_STATUS_DATA_OVERRUN = 0xC000003C,
+ MD_NTSTATUS_WIN_STATUS_DATA_LATE_ERROR = 0xC000003D,
+ MD_NTSTATUS_WIN_STATUS_DATA_ERROR = 0xC000003E,
+@@ -549,16 +786,24 @@ typedef enum {
+ MD_NTSTATUS_WIN_STATUS_IMAGE_SUBSYSTEM_NOT_PRESENT = 0xC00001A3,
+ MD_NTSTATUS_WIN_STATUS_NOTIFICATION_GUID_ALREADY_DEFINED = 0xC00001A4,
+ MD_NTSTATUS_WIN_STATUS_INVALID_EXCEPTION_HANDLER = 0xC00001A5,
+ MD_NTSTATUS_WIN_STATUS_DUPLICATE_PRIVILEGES = 0xC00001A6,
+ MD_NTSTATUS_WIN_STATUS_NOT_ALLOWED_ON_SYSTEM_FILE = 0xC00001A7,
+ MD_NTSTATUS_WIN_STATUS_REPAIR_NEEDED = 0xC00001A8,
+ MD_NTSTATUS_WIN_STATUS_QUOTA_NOT_ENABLED = 0xC00001A9,
+ MD_NTSTATUS_WIN_STATUS_NO_APPLICATION_PACKAGE = 0xC00001AA,
++ MD_NTSTATUS_WIN_STATUS_FILE_METADATA_OPTIMIZATION_IN_PROGRESS = 0xC00001AB,
++ MD_NTSTATUS_WIN_STATUS_NOT_SAME_OBJECT = 0xC00001AC,
++ MD_NTSTATUS_WIN_STATUS_FATAL_MEMORY_EXHAUSTION = 0xC00001AD,
++ MD_NTSTATUS_WIN_STATUS_ERROR_PROCESS_NOT_IN_JOB = 0xC00001AE,
++ MD_NTSTATUS_WIN_STATUS_CPU_SET_INVALID = 0xC00001AF,
++ MD_NTSTATUS_WIN_STATUS_IO_DEVICE_INVALID_DATA = 0xC00001B0,
++ MD_NTSTATUS_WIN_STATUS_IO_UNALIGNED_WRITE = 0xC00001B1,
++ MD_NTSTATUS_WIN_STATUS_CONTROL_STACK_VIOLATION = 0xC00001B2,
+ MD_NTSTATUS_WIN_STATUS_NETWORK_OPEN_RESTRICTION = 0xC0000201,
+ MD_NTSTATUS_WIN_STATUS_NO_USER_SESSION_KEY = 0xC0000202,
+ MD_NTSTATUS_WIN_STATUS_USER_SESSION_DELETED = 0xC0000203,
+ MD_NTSTATUS_WIN_STATUS_RESOURCE_LANG_NOT_FOUND = 0xC0000204,
+ MD_NTSTATUS_WIN_STATUS_INSUFF_SERVER_RESOURCES = 0xC0000205,
+ MD_NTSTATUS_WIN_STATUS_INVALID_BUFFER_SIZE = 0xC0000206,
+ MD_NTSTATUS_WIN_STATUS_INVALID_ADDRESS_COMPONENT = 0xC0000207,
+ MD_NTSTATUS_WIN_STATUS_INVALID_ADDRESS_WILDCARD = 0xC0000208,
+@@ -664,16 +909,17 @@ typedef enum {
+ MD_NTSTATUS_WIN_STATUS_NO_MORE_MATCHES = 0xC0000273,
+ MD_NTSTATUS_WIN_STATUS_NOT_A_REPARSE_POINT = 0xC0000275,
+ MD_NTSTATUS_WIN_STATUS_IO_REPARSE_TAG_INVALID = 0xC0000276,
+ MD_NTSTATUS_WIN_STATUS_IO_REPARSE_TAG_MISMATCH = 0xC0000277,
+ MD_NTSTATUS_WIN_STATUS_IO_REPARSE_DATA_INVALID = 0xC0000278,
+ MD_NTSTATUS_WIN_STATUS_IO_REPARSE_TAG_NOT_HANDLED = 0xC0000279,
+ MD_NTSTATUS_WIN_STATUS_PWD_TOO_LONG = 0xC000027A,
+ MD_NTSTATUS_WIN_STATUS_STOWED_EXCEPTION = 0xC000027B,
++ MD_NTSTATUS_WIN_STATUS_CONTEXT_STOWED_EXCEPTION = 0xC000027C,
+ MD_NTSTATUS_WIN_STATUS_REPARSE_POINT_NOT_RESOLVED = 0xC0000280,
+ MD_NTSTATUS_WIN_STATUS_DIRECTORY_IS_A_REPARSE_POINT = 0xC0000281,
+ MD_NTSTATUS_WIN_STATUS_RANGE_LIST_CONFLICT = 0xC0000282,
+ MD_NTSTATUS_WIN_STATUS_SOURCE_ELEMENT_EMPTY = 0xC0000283,
+ MD_NTSTATUS_WIN_STATUS_DESTINATION_ELEMENT_FULL = 0xC0000284,
+ MD_NTSTATUS_WIN_STATUS_ILLEGAL_ELEMENT_ADDRESS = 0xC0000285,
+ MD_NTSTATUS_WIN_STATUS_MAGAZINE_NOT_PRESENT = 0xC0000286,
+ MD_NTSTATUS_WIN_STATUS_REINITIALIZATION_NEEDED = 0xC0000287,
+@@ -796,16 +1042,17 @@ typedef enum {
+ MD_NTSTATUS_WIN_STATUS_COPY_PROTECTION_FAILURE = 0xC0000305,
+ MD_NTSTATUS_WIN_STATUS_CSS_AUTHENTICATION_FAILURE = 0xC0000306,
+ MD_NTSTATUS_WIN_STATUS_CSS_KEY_NOT_PRESENT = 0xC0000307,
+ MD_NTSTATUS_WIN_STATUS_CSS_KEY_NOT_ESTABLISHED = 0xC0000308,
+ MD_NTSTATUS_WIN_STATUS_CSS_SCRAMBLED_SECTOR = 0xC0000309,
+ MD_NTSTATUS_WIN_STATUS_CSS_REGION_MISMATCH = 0xC000030A,
+ MD_NTSTATUS_WIN_STATUS_CSS_RESETS_EXHAUSTED = 0xC000030B,
+ MD_NTSTATUS_WIN_STATUS_PASSWORD_CHANGE_REQUIRED = 0xC000030C,
++ MD_NTSTATUS_WIN_STATUS_LOST_MODE_LOGON_RESTRICTION = 0xC000030D,
+ MD_NTSTATUS_WIN_STATUS_PKINIT_FAILURE = 0xC0000320,
+ MD_NTSTATUS_WIN_STATUS_SMARTCARD_SUBSYSTEM_FAILURE = 0xC0000321,
+ MD_NTSTATUS_WIN_STATUS_NO_KERB_KEY = 0xC0000322,
+ MD_NTSTATUS_WIN_STATUS_HOST_DOWN = 0xC0000350,
+ MD_NTSTATUS_WIN_STATUS_UNSUPPORTED_PREAUTH = 0xC0000351,
+ MD_NTSTATUS_WIN_STATUS_EFS_ALG_BLOB_TOO_BIG = 0xC0000352,
+ MD_NTSTATUS_WIN_STATUS_PORT_NOT_SET = 0xC0000353,
+ MD_NTSTATUS_WIN_STATUS_DEBUGGER_INACTIVE = 0xC0000354,
+@@ -928,16 +1175,17 @@ typedef enum {
+ MD_NTSTATUS_WIN_STATUS_FILE_NOT_AVAILABLE = 0xC0000467,
+ MD_NTSTATUS_WIN_STATUS_DEVICE_INSUFFICIENT_RESOURCES = 0xC0000468,
+ MD_NTSTATUS_WIN_STATUS_PACKAGE_UPDATING = 0xC0000469,
+ MD_NTSTATUS_WIN_STATUS_NOT_READ_FROM_COPY = 0xC000046A,
+ MD_NTSTATUS_WIN_STATUS_FT_WRITE_FAILURE = 0xC000046B,
+ MD_NTSTATUS_WIN_STATUS_FT_DI_SCAN_REQUIRED = 0xC000046C,
+ MD_NTSTATUS_WIN_STATUS_OBJECT_NOT_EXTERNALLY_BACKED = 0xC000046D,
+ MD_NTSTATUS_WIN_STATUS_EXTERNAL_BACKING_PROVIDER_UNKNOWN = 0xC000046E,
++ MD_NTSTATUS_WIN_STATUS_COMPRESSION_NOT_BENEFICIAL = 0xC000046F,
+ MD_NTSTATUS_WIN_STATUS_DATA_CHECKSUM_ERROR = 0xC0000470,
+ MD_NTSTATUS_WIN_STATUS_INTERMIXED_KERNEL_EA_OPERATION = 0xC0000471,
+ MD_NTSTATUS_WIN_STATUS_TRIM_READ_ZERO_NOT_SUPPORTED = 0xC0000472,
+ MD_NTSTATUS_WIN_STATUS_TOO_MANY_SEGMENT_DESCRIPTORS = 0xC0000473,
+ MD_NTSTATUS_WIN_STATUS_INVALID_OFFSET_ALIGNMENT = 0xC0000474,
+ MD_NTSTATUS_WIN_STATUS_INVALID_FIELD_IN_PARAMETER_LIST = 0xC0000475,
+ MD_NTSTATUS_WIN_STATUS_OPERATION_IN_PROGRESS = 0xC0000476,
+ MD_NTSTATUS_WIN_STATUS_INVALID_INITIATOR_TARGET_PATH = 0xC0000477,
+@@ -948,26 +1196,101 @@ typedef enum {
+ MD_NTSTATUS_WIN_STATUS_DIRECTORY_NOT_SUPPORTED = 0xC000047C,
+ MD_NTSTATUS_WIN_STATUS_IO_OPERATION_TIMEOUT = 0xC000047D,
+ MD_NTSTATUS_WIN_STATUS_SYSTEM_NEEDS_REMEDIATION = 0xC000047E,
+ MD_NTSTATUS_WIN_STATUS_APPX_INTEGRITY_FAILURE_CLR_NGEN = 0xC000047F,
+ MD_NTSTATUS_WIN_STATUS_SHARE_UNAVAILABLE = 0xC0000480,
+ MD_NTSTATUS_WIN_STATUS_APISET_NOT_HOSTED = 0xC0000481,
+ MD_NTSTATUS_WIN_STATUS_APISET_NOT_PRESENT = 0xC0000482,
+ MD_NTSTATUS_WIN_STATUS_DEVICE_HARDWARE_ERROR = 0xC0000483,
++ MD_NTSTATUS_WIN_STATUS_FIRMWARE_SLOT_INVALID = 0xC0000484,
++ MD_NTSTATUS_WIN_STATUS_FIRMWARE_IMAGE_INVALID = 0xC0000485,
++ MD_NTSTATUS_WIN_STATUS_STORAGE_TOPOLOGY_ID_MISMATCH = 0xC0000486,
++ MD_NTSTATUS_WIN_STATUS_WIM_NOT_BOOTABLE = 0xC0000487,
++ MD_NTSTATUS_WIN_STATUS_BLOCKED_BY_PARENTAL_CONTROLS = 0xC0000488,
++ MD_NTSTATUS_WIN_STATUS_NEEDS_REGISTRATION = 0xC0000489,
++ MD_NTSTATUS_WIN_STATUS_QUOTA_ACTIVITY = 0xC000048A,
++ MD_NTSTATUS_WIN_STATUS_CALLBACK_INVOKE_INLINE = 0xC000048B,
++ MD_NTSTATUS_WIN_STATUS_BLOCK_TOO_MANY_REFERENCES = 0xC000048C,
++ MD_NTSTATUS_WIN_STATUS_MARKED_TO_DISALLOW_WRITES = 0xC000048D,
++ MD_NTSTATUS_WIN_STATUS_NETWORK_ACCESS_DENIED_EDP = 0xC000048E,
++ MD_NTSTATUS_WIN_STATUS_ENCLAVE_FAILURE = 0xC000048F,
++ MD_NTSTATUS_WIN_STATUS_PNP_NO_COMPAT_DRIVERS = 0xC0000490,
++ MD_NTSTATUS_WIN_STATUS_PNP_DRIVER_PACKAGE_NOT_FOUND = 0xC0000491,
++ MD_NTSTATUS_WIN_STATUS_PNP_DRIVER_CONFIGURATION_NOT_FOUND = 0xC0000492,
++ MD_NTSTATUS_WIN_STATUS_PNP_DRIVER_CONFIGURATION_INCOMPLETE = 0xC0000493,
++ MD_NTSTATUS_WIN_STATUS_PNP_FUNCTION_DRIVER_REQUIRED = 0xC0000494,
++ MD_NTSTATUS_WIN_STATUS_PNP_DEVICE_CONFIGURATION_PENDING = 0xC0000495,
++ MD_NTSTATUS_WIN_STATUS_DEVICE_HINT_NAME_BUFFER_TOO_SMALL = 0xC0000496,
++ MD_NTSTATUS_WIN_STATUS_PACKAGE_NOT_AVAILABLE = 0xC0000497,
++ MD_NTSTATUS_WIN_STATUS_DEVICE_IN_MAINTENANCE = 0xC0000499,
++ MD_NTSTATUS_WIN_STATUS_NOT_SUPPORTED_ON_DAX = 0xC000049A,
++ MD_NTSTATUS_WIN_STATUS_FREE_SPACE_TOO_FRAGMENTED = 0xC000049B,
++ MD_NTSTATUS_WIN_STATUS_DAX_MAPPING_EXISTS = 0xC000049C,
++ MD_NTSTATUS_WIN_STATUS_CHILD_PROCESS_BLOCKED = 0xC000049D,
++ MD_NTSTATUS_WIN_STATUS_STORAGE_LOST_DATA_PERSISTENCE = 0xC000049E,
++ MD_NTSTATUS_WIN_STATUS_VRF_CFG_AND_IO_ENABLED = 0xC000049F,
++ MD_NTSTATUS_WIN_STATUS_PARTITION_TERMINATING = 0xC00004A0,
++ MD_NTSTATUS_WIN_STATUS_EXTERNAL_SYSKEY_NOT_SUPPORTED = 0xC00004A1,
++ MD_NTSTATUS_WIN_STATUS_ENCLAVE_VIOLATION = 0xC00004A2,
++ MD_NTSTATUS_WIN_STATUS_FILE_PROTECTED_UNDER_DPL = 0xC00004A3,
++ MD_NTSTATUS_WIN_STATUS_VOLUME_NOT_CLUSTER_ALIGNED = 0xC00004A4,
++ MD_NTSTATUS_WIN_STATUS_NO_PHYSICALLY_ALIGNED_FREE_SPACE_FOUND = 0xC00004A5,
++ MD_NTSTATUS_WIN_STATUS_APPX_FILE_NOT_ENCRYPTED = 0xC00004A6,
++ MD_NTSTATUS_WIN_STATUS_RWRAW_ENCRYPTED_FILE_NOT_ENCRYPTED = 0xC00004A7,
++ MD_NTSTATUS_WIN_STATUS_RWRAW_ENCRYPTED_INVALID_EDATAINFO_FILEOFFSET = 0xC00004A8,
++ MD_NTSTATUS_WIN_STATUS_RWRAW_ENCRYPTED_INVALID_EDATAINFO_FILERANGE = 0xC00004A9,
++ MD_NTSTATUS_WIN_STATUS_RWRAW_ENCRYPTED_INVALID_EDATAINFO_PARAMETER = 0xC00004AA,
++ MD_NTSTATUS_WIN_STATUS_FT_READ_FAILURE = 0xC00004AB,
++ MD_NTSTATUS_WIN_STATUS_PATCH_CONFLICT = 0xC00004AC,
++ MD_NTSTATUS_WIN_STATUS_STORAGE_RESERVE_ID_INVALID = 0xC00004AD,
++ MD_NTSTATUS_WIN_STATUS_STORAGE_RESERVE_DOES_NOT_EXIST = 0xC00004AE,
++ MD_NTSTATUS_WIN_STATUS_STORAGE_RESERVE_ALREADY_EXISTS = 0xC00004AF,
++ MD_NTSTATUS_WIN_STATUS_STORAGE_RESERVE_NOT_EMPTY = 0xC00004B0,
++ MD_NTSTATUS_WIN_STATUS_NOT_A_DAX_VOLUME = 0xC00004B1,
++ MD_NTSTATUS_WIN_STATUS_NOT_DAX_MAPPABLE = 0xC00004B2,
++ MD_NTSTATUS_WIN_STATUS_CASE_DIFFERING_NAMES_IN_DIR = 0xC00004B3,
++ MD_NTSTATUS_WIN_STATUS_FILE_NOT_SUPPORTED = 0xC00004B4,
++ MD_NTSTATUS_WIN_STATUS_NOT_SUPPORTED_WITH_BTT = 0xC00004B5,
++ MD_NTSTATUS_WIN_STATUS_ENCRYPTION_DISABLED = 0xC00004B6,
++ MD_NTSTATUS_WIN_STATUS_ENCRYPTING_METADATA_DISALLOWED = 0xC00004B7,
++ MD_NTSTATUS_WIN_STATUS_CANT_CLEAR_ENCRYPTION_FLAG = 0xC00004B8,
++ MD_NTSTATUS_WIN_STATUS_UNSATISFIED_DEPENDENCIES = 0xC00004B9,
++ MD_NTSTATUS_WIN_STATUS_CASE_SENSITIVE_PATH = 0xC00004BA,
++ MD_NTSTATUS_WIN_STATUS_HAS_SYSTEM_CRITICAL_FILES = 0xC00004BD,
+ MD_NTSTATUS_WIN_STATUS_INVALID_TASK_NAME = 0xC0000500,
+ MD_NTSTATUS_WIN_STATUS_INVALID_TASK_INDEX = 0xC0000501,
+ MD_NTSTATUS_WIN_STATUS_THREAD_ALREADY_IN_TASK = 0xC0000502,
+ MD_NTSTATUS_WIN_STATUS_CALLBACK_BYPASS = 0xC0000503,
+ MD_NTSTATUS_WIN_STATUS_UNDEFINED_SCOPE = 0xC0000504,
+ MD_NTSTATUS_WIN_STATUS_INVALID_CAP = 0xC0000505,
+ MD_NTSTATUS_WIN_STATUS_NOT_GUI_PROCESS = 0xC0000506,
++ MD_NTSTATUS_WIN_STATUS_DEVICE_HUNG = 0xC0000507,
++ MD_NTSTATUS_WIN_STATUS_CONTAINER_ASSIGNED = 0xC0000508,
++ MD_NTSTATUS_WIN_STATUS_JOB_NO_CONTAINER = 0xC0000509,
++ MD_NTSTATUS_WIN_STATUS_DEVICE_UNRESPONSIVE = 0xC000050A,
++ MD_NTSTATUS_WIN_STATUS_REPARSE_POINT_ENCOUNTERED = 0xC000050B,
++ MD_NTSTATUS_WIN_STATUS_ATTRIBUTE_NOT_PRESENT = 0xC000050C,
++ MD_NTSTATUS_WIN_STATUS_NOT_A_TIERED_VOLUME = 0xC000050D,
++ MD_NTSTATUS_WIN_STATUS_ALREADY_HAS_STREAM_ID = 0xC000050E,
++ MD_NTSTATUS_WIN_STATUS_JOB_NOT_EMPTY = 0xC000050F,
++ MD_NTSTATUS_WIN_STATUS_ALREADY_INITIALIZED = 0xC0000510,
++ MD_NTSTATUS_WIN_STATUS_ENCLAVE_NOT_TERMINATED = 0xC0000511,
++ MD_NTSTATUS_WIN_STATUS_ENCLAVE_IS_TERMINATING = 0xC0000512,
++ MD_NTSTATUS_WIN_STATUS_SMB1_NOT_AVAILABLE = 0xC0000513,
++ MD_NTSTATUS_WIN_STATUS_SMR_GARBAGE_COLLECTION_REQUIRED = 0xC0000514,
++ MD_NTSTATUS_WIN_STATUS_INTERRUPTED = 0xC0000515,
++ MD_NTSTATUS_WIN_STATUS_THREAD_NOT_RUNNING = 0xC0000516,
+ MD_NTSTATUS_WIN_STATUS_FAIL_FAST_EXCEPTION = 0xC0000602,
+ MD_NTSTATUS_WIN_STATUS_IMAGE_CERT_REVOKED = 0xC0000603,
+ MD_NTSTATUS_WIN_STATUS_DYNAMIC_CODE_BLOCKED = 0xC0000604,
++ MD_NTSTATUS_WIN_STATUS_IMAGE_CERT_EXPIRED = 0xC0000605,
++ MD_NTSTATUS_WIN_STATUS_STRICT_CFG_VIOLATION = 0xC0000606,
++ MD_NTSTATUS_WIN_STATUS_SET_CONTEXT_DENIED = 0xC000060A,
++ MD_NTSTATUS_WIN_STATUS_CROSS_PARTITION_VIOLATION = 0xC000060B,
+ MD_NTSTATUS_WIN_STATUS_PORT_CLOSED = 0xC0000700,
+ MD_NTSTATUS_WIN_STATUS_MESSAGE_LOST = 0xC0000701,
+ MD_NTSTATUS_WIN_STATUS_INVALID_MESSAGE = 0xC0000702,
+ MD_NTSTATUS_WIN_STATUS_REQUEST_CANCELED = 0xC0000703,
+ MD_NTSTATUS_WIN_STATUS_RECURSIVE_DISPATCH = 0xC0000704,
+ MD_NTSTATUS_WIN_STATUS_LPC_RECEIVE_BUFFER_EXPECTED = 0xC0000705,
+ MD_NTSTATUS_WIN_STATUS_LPC_INVALID_CONNECTION_USAGE = 0xC0000706,
+ MD_NTSTATUS_WIN_STATUS_LPC_REQUESTS_NOT_ALLOWED = 0xC0000707,
+@@ -992,16 +1315,21 @@ typedef enum {
+ MD_NTSTATUS_WIN_STATUS_PORT_ALREADY_HAS_COMPLETION_LIST = 0xC000071A,
+ MD_NTSTATUS_WIN_STATUS_CALLBACK_RETURNED_THREAD_PRIORITY = 0xC000071B,
+ MD_NTSTATUS_WIN_STATUS_INVALID_THREAD = 0xC000071C,
+ MD_NTSTATUS_WIN_STATUS_CALLBACK_RETURNED_TRANSACTION = 0xC000071D,
+ MD_NTSTATUS_WIN_STATUS_CALLBACK_RETURNED_LDR_LOCK = 0xC000071E,
+ MD_NTSTATUS_WIN_STATUS_CALLBACK_RETURNED_LANG = 0xC000071F,
+ MD_NTSTATUS_WIN_STATUS_CALLBACK_RETURNED_PRI_BACK = 0xC0000720,
+ MD_NTSTATUS_WIN_STATUS_CALLBACK_RETURNED_THREAD_AFFINITY = 0xC0000721,
++ MD_NTSTATUS_WIN_STATUS_LPC_HANDLE_COUNT_EXCEEDED = 0xC0000722,
++ MD_NTSTATUS_WIN_STATUS_EXECUTABLE_MEMORY_WRITE = 0xC0000723,
++ MD_NTSTATUS_WIN_STATUS_KERNEL_EXECUTABLE_MEMORY_WRITE = 0xC0000724,
++ MD_NTSTATUS_WIN_STATUS_ATTACHED_EXECUTABLE_MEMORY_WRITE = 0xC0000725,
++ MD_NTSTATUS_WIN_STATUS_TRIGGERED_EXECUTABLE_MEMORY_WRITE = 0xC0000726,
+ MD_NTSTATUS_WIN_STATUS_DISK_REPAIR_DISABLED = 0xC0000800,
+ MD_NTSTATUS_WIN_STATUS_DS_DOMAIN_RENAME_IN_PROGRESS = 0xC0000801,
+ MD_NTSTATUS_WIN_STATUS_DISK_QUOTA_EXCEEDED = 0xC0000802,
+ MD_NTSTATUS_WIN_STATUS_CONTENT_BLOCKED = 0xC0000804,
+ MD_NTSTATUS_WIN_STATUS_BAD_CLUSTERS = 0xC0000805,
+ MD_NTSTATUS_WIN_STATUS_VOLUME_DIRTY = 0xC0000806,
+ MD_NTSTATUS_WIN_STATUS_DISK_REPAIR_UNSUCCESSFUL = 0xC0000808,
+ MD_NTSTATUS_WIN_STATUS_CORRUPT_LOG_OVERFULL = 0xC0000809,
+@@ -1028,16 +1356,19 @@ typedef enum {
+ MD_NTSTATUS_WIN_STATUS_FILE_HANDLE_REVOKED = 0xC0000910,
+ MD_NTSTATUS_WIN_STATUS_WOW_ASSERTION = 0xC0009898,
+ MD_NTSTATUS_WIN_STATUS_INVALID_SIGNATURE = 0xC000A000,
+ MD_NTSTATUS_WIN_STATUS_HMAC_NOT_SUPPORTED = 0xC000A001,
+ MD_NTSTATUS_WIN_STATUS_AUTH_TAG_MISMATCH = 0xC000A002,
+ MD_NTSTATUS_WIN_STATUS_INVALID_STATE_TRANSITION = 0xC000A003,
+ MD_NTSTATUS_WIN_STATUS_INVALID_KERNEL_INFO_VERSION = 0xC000A004,
+ MD_NTSTATUS_WIN_STATUS_INVALID_PEP_INFO_VERSION = 0xC000A005,
++ MD_NTSTATUS_WIN_STATUS_HANDLE_REVOKED = 0xC000A006,
++ MD_NTSTATUS_WIN_STATUS_EOF_ON_GHOSTED_RANGE = 0xC000A007,
++ MD_NTSTATUS_WIN_STATUS_CC_NEEDS_CALLBACK_SECTION_DRAIN = 0xC000A008,
+ MD_NTSTATUS_WIN_STATUS_IPSEC_QUEUE_OVERFLOW = 0xC000A010,
+ MD_NTSTATUS_WIN_STATUS_ND_QUEUE_OVERFLOW = 0xC000A011,
+ MD_NTSTATUS_WIN_STATUS_HOPLIMIT_EXCEEDED = 0xC000A012,
+ MD_NTSTATUS_WIN_STATUS_PROTOCOL_NOT_SUPPORTED = 0xC000A013,
+ MD_NTSTATUS_WIN_STATUS_FASTPATH_REJECTED = 0xC000A014,
+ MD_NTSTATUS_WIN_STATUS_LOST_WRITEBEHIND_DATA_NETWORK_DISCONNECTED = 0xC000A080,
+ MD_NTSTATUS_WIN_STATUS_LOST_WRITEBEHIND_DATA_NETWORK_SERVER_ERROR = 0xC000A081,
+ MD_NTSTATUS_WIN_STATUS_LOST_WRITEBEHIND_DATA_LOCAL_DISK_ERROR = 0xC000A082,
+@@ -1059,25 +1390,72 @@ typedef enum {
+ MD_NTSTATUS_WIN_STATUS_CANNOT_SWITCH_RUNLEVEL = 0xC000A141,
+ MD_NTSTATUS_WIN_STATUS_INVALID_RUNLEVEL_SETTING = 0xC000A142,
+ MD_NTSTATUS_WIN_STATUS_RUNLEVEL_SWITCH_TIMEOUT = 0xC000A143,
+ MD_NTSTATUS_WIN_STATUS_RUNLEVEL_SWITCH_AGENT_TIMEOUT = 0xC000A145,
+ MD_NTSTATUS_WIN_STATUS_RUNLEVEL_SWITCH_IN_PROGRESS = 0xC000A146,
+ MD_NTSTATUS_WIN_STATUS_NOT_APPCONTAINER = 0xC000A200,
+ MD_NTSTATUS_WIN_STATUS_NOT_SUPPORTED_IN_APPCONTAINER = 0xC000A201,
+ MD_NTSTATUS_WIN_STATUS_INVALID_PACKAGE_SID_LENGTH = 0xC000A202,
++ MD_NTSTATUS_WIN_STATUS_LPAC_ACCESS_DENIED = 0xC000A203,
++ MD_NTSTATUS_WIN_STATUS_ADMINLESS_ACCESS_DENIED = 0xC000A204,
+ MD_NTSTATUS_WIN_STATUS_APP_DATA_NOT_FOUND = 0xC000A281,
+ MD_NTSTATUS_WIN_STATUS_APP_DATA_EXPIRED = 0xC000A282,
+ MD_NTSTATUS_WIN_STATUS_APP_DATA_CORRUPT = 0xC000A283,
+ MD_NTSTATUS_WIN_STATUS_APP_DATA_LIMIT_EXCEEDED = 0xC000A284,
+ MD_NTSTATUS_WIN_STATUS_APP_DATA_REBOOT_REQUIRED = 0xC000A285,
+ MD_NTSTATUS_WIN_STATUS_OFFLOAD_READ_FLT_NOT_SUPPORTED = 0xC000A2A1,
+ MD_NTSTATUS_WIN_STATUS_OFFLOAD_WRITE_FLT_NOT_SUPPORTED = 0xC000A2A2,
+ MD_NTSTATUS_WIN_STATUS_OFFLOAD_READ_FILE_NOT_SUPPORTED = 0xC000A2A3,
+ MD_NTSTATUS_WIN_STATUS_OFFLOAD_WRITE_FILE_NOT_SUPPORTED = 0xC000A2A4,
++ MD_NTSTATUS_WIN_STATUS_WOF_WIM_HEADER_CORRUPT = 0xC000A2A5,
++ MD_NTSTATUS_WIN_STATUS_WOF_WIM_RESOURCE_TABLE_CORRUPT = 0xC000A2A6,
++ MD_NTSTATUS_WIN_STATUS_WOF_FILE_RESOURCE_TABLE_CORRUPT = 0xC000A2A7,
++ MD_NTSTATUS_WIN_STATUS_CIMFS_IMAGE_CORRUPT = 0xC000C001,
++ MD_NTSTATUS_WIN_STATUS_FILE_SYSTEM_VIRTUALIZATION_UNAVAILABLE = 0xC000CE01,
++ MD_NTSTATUS_WIN_STATUS_FILE_SYSTEM_VIRTUALIZATION_METADATA_CORRUPT = 0xC000CE02,
++ MD_NTSTATUS_WIN_STATUS_FILE_SYSTEM_VIRTUALIZATION_BUSY = 0xC000CE03,
++ MD_NTSTATUS_WIN_STATUS_FILE_SYSTEM_VIRTUALIZATION_PROVIDER_UNKNOWN = 0xC000CE04,
++ MD_NTSTATUS_WIN_STATUS_FILE_SYSTEM_VIRTUALIZATION_INVALID_OPERATION = 0xC000CE05,
++ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_SYNC_ROOT_METADATA_CORRUPT = 0xC000CF00,
++ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_PROVIDER_NOT_RUNNING = 0xC000CF01,
++ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_METADATA_CORRUPT = 0xC000CF02,
++ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_METADATA_TOO_LARGE = 0xC000CF03,
++ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_PROPERTY_VERSION_NOT_SUPPORTED = 0xC000CF06,
++ MD_NTSTATUS_WIN_STATUS_NOT_A_CLOUD_FILE = 0xC000CF07,
++ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_NOT_IN_SYNC = 0xC000CF08,
++ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_ALREADY_CONNECTED = 0xC000CF09,
++ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_NOT_SUPPORTED = 0xC000CF0A,
++ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_INVALID_REQUEST = 0xC000CF0B,
++ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_READ_ONLY_VOLUME = 0xC000CF0C,
++ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_CONNECTED_PROVIDER_ONLY = 0xC000CF0D,
++ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_VALIDATION_FAILED = 0xC000CF0E,
++ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_AUTHENTICATION_FAILED = 0xC000CF0F,
++ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_INSUFFICIENT_RESOURCES = 0xC000CF10,
++ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_NETWORK_UNAVAILABLE = 0xC000CF11,
++ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_UNSUCCESSFUL = 0xC000CF12,
++ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_NOT_UNDER_SYNC_ROOT = 0xC000CF13,
++ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_IN_USE = 0xC000CF14,
++ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_PINNED = 0xC000CF15,
++ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_REQUEST_ABORTED = 0xC000CF16,
++ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_PROPERTY_CORRUPT = 0xC000CF17,
++ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_ACCESS_DENIED = 0xC000CF18,
++ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_INCOMPATIBLE_HARDLINKS = 0xC000CF19,
++ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_PROPERTY_LOCK_CONFLICT = 0xC000CF1A,
++ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_REQUEST_CANCELED = 0xC000CF1B,
++ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_PROVIDER_TERMINATED = 0xC000CF1D,
++ MD_NTSTATUS_WIN_STATUS_NOT_A_CLOUD_SYNC_ROOT = 0xC000CF1E,
++ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_REQUEST_TIMEOUT = 0xC000CF1F,
++ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_DEHYDRATION_DISALLOWED = 0xC000CF20,
++ MD_NTSTATUS_WIN_STATUS_FILE_SNAP_IN_PROGRESS = 0xC000F500,
++ MD_NTSTATUS_WIN_STATUS_FILE_SNAP_USER_SECTION_NOT_SUPPORTED = 0xC000F501,
++ MD_NTSTATUS_WIN_STATUS_FILE_SNAP_MODIFY_NOT_SUPPORTED = 0xC000F502,
++ MD_NTSTATUS_WIN_STATUS_FILE_SNAP_IO_NOT_COORDINATED = 0xC000F503,
++ MD_NTSTATUS_WIN_STATUS_FILE_SNAP_UNEXPECTED_ERROR = 0xC000F504,
++ MD_NTSTATUS_WIN_STATUS_FILE_SNAP_INVALID_PARAMETER = 0xC000F505,
+ MD_NTSTATUS_WIN_DBG_NO_STATE_CHANGE = 0xC0010001,
+ MD_NTSTATUS_WIN_DBG_APP_NOT_IDLE = 0xC0010002,
+ MD_NTSTATUS_WIN_RPC_NT_INVALID_STRING_BINDING = 0xC0020001,
+ MD_NTSTATUS_WIN_RPC_NT_WRONG_KIND_OF_BINDING = 0xC0020002,
+ MD_NTSTATUS_WIN_RPC_NT_INVALID_BINDING = 0xC0020003,
+ MD_NTSTATUS_WIN_RPC_NT_PROTSEQ_NOT_SUPPORTED = 0xC0020004,
+ MD_NTSTATUS_WIN_RPC_NT_INVALID_RPC_PROTSEQ = 0xC0020005,
+ MD_NTSTATUS_WIN_RPC_NT_INVALID_STRING_UUID = 0xC0020006,
+@@ -1263,16 +1641,21 @@ typedef enum {
+ MD_NTSTATUS_WIN_STATUS_CLUSTER_CSV_VOLUME_NOT_LOCAL = 0xC0130019,
+ MD_NTSTATUS_WIN_STATUS_CLUSTER_CSV_READ_OPLOCK_BREAK_IN_PROGRESS = 0xC0130020,
+ MD_NTSTATUS_WIN_STATUS_CLUSTER_CSV_AUTO_PAUSE_ERROR = 0xC0130021,
+ MD_NTSTATUS_WIN_STATUS_CLUSTER_CSV_REDIRECTED = 0xC0130022,
+ MD_NTSTATUS_WIN_STATUS_CLUSTER_CSV_NOT_REDIRECTED = 0xC0130023,
+ MD_NTSTATUS_WIN_STATUS_CLUSTER_CSV_VOLUME_DRAINING = 0xC0130024,
+ MD_NTSTATUS_WIN_STATUS_CLUSTER_CSV_SNAPSHOT_CREATION_IN_PROGRESS = 0xC0130025,
+ MD_NTSTATUS_WIN_STATUS_CLUSTER_CSV_VOLUME_DRAINING_SUCCEEDED_DOWNLEVEL = 0xC0130026,
++ MD_NTSTATUS_WIN_STATUS_CLUSTER_CSV_NO_SNAPSHOTS = 0xC0130027,
++ MD_NTSTATUS_WIN_STATUS_CSV_IO_PAUSE_TIMEOUT = 0xC0130028,
++ MD_NTSTATUS_WIN_STATUS_CLUSTER_CSV_INVALID_HANDLE = 0xC0130029,
++ MD_NTSTATUS_WIN_STATUS_CLUSTER_CSV_SUPPORTED_ONLY_ON_COORDINATOR = 0xC0130030,
++ MD_NTSTATUS_WIN_STATUS_CLUSTER_CAM_TICKET_REPLAY_DETECTED = 0xC0130031,
+ MD_NTSTATUS_WIN_STATUS_ACPI_INVALID_OPCODE = 0xC0140001,
+ MD_NTSTATUS_WIN_STATUS_ACPI_STACK_OVERFLOW = 0xC0140002,
+ MD_NTSTATUS_WIN_STATUS_ACPI_ASSERT_FAILED = 0xC0140003,
+ MD_NTSTATUS_WIN_STATUS_ACPI_INVALID_INDEX = 0xC0140004,
+ MD_NTSTATUS_WIN_STATUS_ACPI_INVALID_ARGUMENT = 0xC0140005,
+ MD_NTSTATUS_WIN_STATUS_ACPI_FATAL = 0xC0140006,
+ MD_NTSTATUS_WIN_STATUS_ACPI_INVALID_SUPERNAME = 0xC0140007,
+ MD_NTSTATUS_WIN_STATUS_ACPI_INVALID_ARGTYPE = 0xC0140008,
+@@ -1504,16 +1887,21 @@ typedef enum {
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_PRESENT_OCCLUDED = 0xC01E0006,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_PRESENT_DENIED = 0xC01E0007,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_CANNOTCOLORCONVERT = 0xC01E0008,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_DRIVER_MISMATCH = 0xC01E0009,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_PRESENT_REDIRECTION_DISABLED = 0xC01E000B,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_PRESENT_UNOCCLUDED = 0xC01E000C,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_WINDOWDC_NOT_AVAILABLE = 0xC01E000D,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_WINDOWLESS_PRESENT_DISABLED = 0xC01E000E,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_PRESENT_INVALID_WINDOW = 0xC01E000F,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_PRESENT_BUFFER_NOT_BOUND = 0xC01E0010,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_VAIL_STATE_CHANGED = 0xC01E0011,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INDIRECT_DISPLAY_ABANDON_SWAPCHAIN = 0xC01E0012,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INDIRECT_DISPLAY_DEVICE_STOPPED = 0xC01E0013,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_NO_VIDEO_MEMORY = 0xC01E0100,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_CANT_LOCK_MEMORY = 0xC01E0101,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_ALLOCATION_BUSY = 0xC01E0102,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_TOO_MANY_REFERENCES = 0xC01E0103,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_TRY_AGAIN_LATER = 0xC01E0104,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_TRY_AGAIN_NOW = 0xC01E0105,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_ALLOCATION_INVALID = 0xC01E0106,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_UNSWIZZLING_APERTURE_UNAVAILABLE = 0xC01E0107,
+@@ -1725,16 +2113,17 @@ typedef enum {
+ MD_NTSTATUS_WIN_STATUS_FVE_EDRIVE_DRY_RUN_FAILED = 0xC0210038,
+ MD_NTSTATUS_WIN_STATUS_FVE_SECUREBOOT_DISABLED = 0xC0210039,
+ MD_NTSTATUS_WIN_STATUS_FVE_SECUREBOOT_CONFIG_CHANGE = 0xC021003A,
+ MD_NTSTATUS_WIN_STATUS_FVE_DEVICE_LOCKEDOUT = 0xC021003B,
+ MD_NTSTATUS_WIN_STATUS_FVE_VOLUME_EXTEND_PREVENTS_EOW_DECRYPT = 0xC021003C,
+ MD_NTSTATUS_WIN_STATUS_FVE_NOT_DE_VOLUME = 0xC021003D,
+ MD_NTSTATUS_WIN_STATUS_FVE_PROTECTION_DISABLED = 0xC021003E,
+ MD_NTSTATUS_WIN_STATUS_FVE_PROTECTION_CANNOT_BE_DISABLED = 0xC021003F,
++ MD_NTSTATUS_WIN_STATUS_FVE_OSV_KSR_NOT_ALLOWED = 0xC0210040,
+ MD_NTSTATUS_WIN_STATUS_FWP_CALLOUT_NOT_FOUND = 0xC0220001,
+ MD_NTSTATUS_WIN_STATUS_FWP_CONDITION_NOT_FOUND = 0xC0220002,
+ MD_NTSTATUS_WIN_STATUS_FWP_FILTER_NOT_FOUND = 0xC0220003,
+ MD_NTSTATUS_WIN_STATUS_FWP_LAYER_NOT_FOUND = 0xC0220004,
+ MD_NTSTATUS_WIN_STATUS_FWP_PROVIDER_NOT_FOUND = 0xC0220005,
+ MD_NTSTATUS_WIN_STATUS_FWP_PROVIDER_CONTEXT_NOT_FOUND = 0xC0220006,
+ MD_NTSTATUS_WIN_STATUS_FWP_SUBLAYER_NOT_FOUND = 0xC0220007,
+ MD_NTSTATUS_WIN_STATUS_FWP_NOT_FOUND = 0xC0220008,
+@@ -1832,25 +2221,32 @@ typedef enum {
+ MD_NTSTATUS_WIN_STATUS_NDIS_INVALID_ADDRESS = 0xC0230022,
+ MD_NTSTATUS_WIN_STATUS_NDIS_PAUSED = 0xC023002A,
+ MD_NTSTATUS_WIN_STATUS_NDIS_INTERFACE_NOT_FOUND = 0xC023002B,
+ MD_NTSTATUS_WIN_STATUS_NDIS_UNSUPPORTED_REVISION = 0xC023002C,
+ MD_NTSTATUS_WIN_STATUS_NDIS_INVALID_PORT = 0xC023002D,
+ MD_NTSTATUS_WIN_STATUS_NDIS_INVALID_PORT_STATE = 0xC023002E,
+ MD_NTSTATUS_WIN_STATUS_NDIS_LOW_POWER_STATE = 0xC023002F,
+ MD_NTSTATUS_WIN_STATUS_NDIS_REINIT_REQUIRED = 0xC0230030,
++ MD_NTSTATUS_WIN_STATUS_NDIS_NO_QUEUES = 0xC0230031,
+ MD_NTSTATUS_WIN_STATUS_NDIS_NOT_SUPPORTED = 0xC02300BB,
+ MD_NTSTATUS_WIN_STATUS_NDIS_OFFLOAD_POLICY = 0xC023100F,
+ MD_NTSTATUS_WIN_STATUS_NDIS_OFFLOAD_CONNECTION_REJECTED = 0xC0231012,
+ MD_NTSTATUS_WIN_STATUS_NDIS_OFFLOAD_PATH_REJECTED = 0xC0231013,
+ MD_NTSTATUS_WIN_STATUS_NDIS_DOT11_AUTO_CONFIG_ENABLED = 0xC0232000,
+ MD_NTSTATUS_WIN_STATUS_NDIS_DOT11_MEDIA_IN_USE = 0xC0232001,
+ MD_NTSTATUS_WIN_STATUS_NDIS_DOT11_POWER_STATE_INVALID = 0xC0232002,
+ MD_NTSTATUS_WIN_STATUS_NDIS_PM_WOL_PATTERN_LIST_FULL = 0xC0232003,
+ MD_NTSTATUS_WIN_STATUS_NDIS_PM_PROTOCOL_OFFLOAD_LIST_FULL = 0xC0232004,
++ MD_NTSTATUS_WIN_STATUS_NDIS_DOT11_AP_CHANNEL_CURRENTLY_NOT_AVAILABLE = 0xC0232005,
++ MD_NTSTATUS_WIN_STATUS_NDIS_DOT11_AP_BAND_CURRENTLY_NOT_AVAILABLE = 0xC0232006,
++ MD_NTSTATUS_WIN_STATUS_NDIS_DOT11_AP_CHANNEL_NOT_ALLOWED = 0xC0232007,
++ MD_NTSTATUS_WIN_STATUS_NDIS_DOT11_AP_BAND_NOT_ALLOWED = 0xC0232008,
++ MD_NTSTATUS_WIN_STATUS_QUIC_HANDSHAKE_FAILURE = 0xC0240000,
++ MD_NTSTATUS_WIN_STATUS_QUIC_VER_NEG_FAILURE = 0xC0240001,
+ MD_NTSTATUS_WIN_STATUS_TPM_ERROR_MASK = 0xC0290000,
+ MD_NTSTATUS_WIN_STATUS_TPM_AUTHFAIL = 0xC0290001,
+ MD_NTSTATUS_WIN_STATUS_TPM_BADINDEX = 0xC0290002,
+ MD_NTSTATUS_WIN_STATUS_TPM_BAD_PARAMETER = 0xC0290003,
+ MD_NTSTATUS_WIN_STATUS_TPM_AUDITFAILURE = 0xC0290004,
+ MD_NTSTATUS_WIN_STATUS_TPM_CLEAR_DISABLED = 0xC0290005,
+ MD_NTSTATUS_WIN_STATUS_TPM_DEACTIVATED = 0xC0290006,
+ MD_NTSTATUS_WIN_STATUS_TPM_DISABLED = 0xC0290007,
+@@ -1940,16 +2336,84 @@ typedef enum {
+ MD_NTSTATUS_WIN_STATUS_TPM_TOOMANYCONTEXTS = 0xC029005B,
+ MD_NTSTATUS_WIN_STATUS_TPM_MA_TICKET_SIGNATURE = 0xC029005C,
+ MD_NTSTATUS_WIN_STATUS_TPM_MA_DESTINATION = 0xC029005D,
+ MD_NTSTATUS_WIN_STATUS_TPM_MA_SOURCE = 0xC029005E,
+ MD_NTSTATUS_WIN_STATUS_TPM_MA_AUTHORITY = 0xC029005F,
+ MD_NTSTATUS_WIN_STATUS_TPM_PERMANENTEK = 0xC0290061,
+ MD_NTSTATUS_WIN_STATUS_TPM_BAD_SIGNATURE = 0xC0290062,
+ MD_NTSTATUS_WIN_STATUS_TPM_NOCONTEXTSPACE = 0xC0290063,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_ASYMMETRIC = 0xC0290081,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_ATTRIBUTES = 0xC0290082,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_HASH = 0xC0290083,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_VALUE = 0xC0290084,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_HIERARCHY = 0xC0290085,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_KEY_SIZE = 0xC0290087,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_MGF = 0xC0290088,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_MODE = 0xC0290089,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_TYPE = 0xC029008A,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_HANDLE = 0xC029008B,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_KDF = 0xC029008C,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_RANGE = 0xC029008D,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_AUTH_FAIL = 0xC029008E,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_NONCE = 0xC029008F,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_PP = 0xC0290090,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_SCHEME = 0xC0290092,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_SIZE = 0xC0290095,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_SYMMETRIC = 0xC0290096,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_TAG = 0xC0290097,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_SELECTOR = 0xC0290098,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_INSUFFICIENT = 0xC029009A,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_SIGNATURE = 0xC029009B,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_KEY = 0xC029009C,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_POLICY_FAIL = 0xC029009D,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_INTEGRITY = 0xC029009F,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_TICKET = 0xC02900A0,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_RESERVED_BITS = 0xC02900A1,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_BAD_AUTH = 0xC02900A2,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_EXPIRED = 0xC02900A3,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_POLICY_CC = 0xC02900A4,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_BINDING = 0xC02900A5,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_CURVE = 0xC02900A6,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_ECC_POINT = 0xC02900A7,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_INITIALIZE = 0xC0290100,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_FAILURE = 0xC0290101,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_SEQUENCE = 0xC0290103,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_PRIVATE = 0xC029010B,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_HMAC = 0xC0290119,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_DISABLED = 0xC0290120,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_EXCLUSIVE = 0xC0290121,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_ECC_CURVE = 0xC0290123,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_AUTH_TYPE = 0xC0290124,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_AUTH_MISSING = 0xC0290125,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_POLICY = 0xC0290126,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_PCR = 0xC0290127,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_PCR_CHANGED = 0xC0290128,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_UPGRADE = 0xC029012D,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_TOO_MANY_CONTEXTS = 0xC029012E,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_AUTH_UNAVAILABLE = 0xC029012F,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_REBOOT = 0xC0290130,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_UNBALANCED = 0xC0290131,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_COMMAND_SIZE = 0xC0290142,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_COMMAND_CODE = 0xC0290143,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_AUTHSIZE = 0xC0290144,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_AUTH_CONTEXT = 0xC0290145,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_NV_RANGE = 0xC0290146,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_NV_SIZE = 0xC0290147,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_NV_LOCKED = 0xC0290148,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_NV_AUTHORIZATION = 0xC0290149,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_NV_UNINITIALIZED = 0xC029014A,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_NV_SPACE = 0xC029014B,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_NV_DEFINED = 0xC029014C,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_BAD_CONTEXT = 0xC0290150,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_CPHASH = 0xC0290151,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_PARENT = 0xC0290152,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_NEEDS_TEST = 0xC0290153,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_NO_RESULT = 0xC0290154,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_SENSITIVE = 0xC0290155,
+ MD_NTSTATUS_WIN_STATUS_TPM_COMMAND_BLOCKED = 0xC0290400,
+ MD_NTSTATUS_WIN_STATUS_TPM_INVALID_HANDLE = 0xC0290401,
+ MD_NTSTATUS_WIN_STATUS_TPM_DUPLICATE_VHANDLE = 0xC0290402,
+ MD_NTSTATUS_WIN_STATUS_TPM_EMBEDDED_COMMAND_BLOCKED = 0xC0290403,
+ MD_NTSTATUS_WIN_STATUS_TPM_EMBEDDED_COMMAND_UNSUPPORTED = 0xC0290404,
+ MD_NTSTATUS_WIN_STATUS_TPM_RETRY = 0xC0290800,
+ MD_NTSTATUS_WIN_STATUS_TPM_NEEDS_SELFTEST = 0xC0290801,
+ MD_NTSTATUS_WIN_STATUS_TPM_DOING_SELFTEST = 0xC0290802,
+@@ -1969,16 +2433,42 @@ typedef enum {
+ MD_NTSTATUS_WIN_STATUS_PCP_BUFFER_TOO_SMALL = 0xC0292006,
+ MD_NTSTATUS_WIN_STATUS_PCP_INTERNAL_ERROR = 0xC0292007,
+ MD_NTSTATUS_WIN_STATUS_PCP_AUTHENTICATION_FAILED = 0xC0292008,
+ MD_NTSTATUS_WIN_STATUS_PCP_AUTHENTICATION_IGNORED = 0xC0292009,
+ MD_NTSTATUS_WIN_STATUS_PCP_POLICY_NOT_FOUND = 0xC029200A,
+ MD_NTSTATUS_WIN_STATUS_PCP_PROFILE_NOT_FOUND = 0xC029200B,
+ MD_NTSTATUS_WIN_STATUS_PCP_VALIDATION_FAILED = 0xC029200C,
+ MD_NTSTATUS_WIN_STATUS_PCP_DEVICE_NOT_FOUND = 0xC029200D,
++ MD_NTSTATUS_WIN_STATUS_PCP_WRONG_PARENT = 0xC029200E,
++ MD_NTSTATUS_WIN_STATUS_PCP_KEY_NOT_LOADED = 0xC029200F,
++ MD_NTSTATUS_WIN_STATUS_PCP_NO_KEY_CERTIFICATION = 0xC0292010,
++ MD_NTSTATUS_WIN_STATUS_PCP_KEY_NOT_FINALIZED = 0xC0292011,
++ MD_NTSTATUS_WIN_STATUS_PCP_ATTESTATION_CHALLENGE_NOT_SET = 0xC0292012,
++ MD_NTSTATUS_WIN_STATUS_PCP_NOT_PCR_BOUND = 0xC0292013,
++ MD_NTSTATUS_WIN_STATUS_PCP_KEY_ALREADY_FINALIZED = 0xC0292014,
++ MD_NTSTATUS_WIN_STATUS_PCP_KEY_USAGE_POLICY_NOT_SUPPORTED = 0xC0292015,
++ MD_NTSTATUS_WIN_STATUS_PCP_KEY_USAGE_POLICY_INVALID = 0xC0292016,
++ MD_NTSTATUS_WIN_STATUS_PCP_SOFT_KEY_ERROR = 0xC0292017,
++ MD_NTSTATUS_WIN_STATUS_PCP_KEY_NOT_AUTHENTICATED = 0xC0292018,
++ MD_NTSTATUS_WIN_STATUS_PCP_KEY_NOT_AIK = 0xC0292019,
++ MD_NTSTATUS_WIN_STATUS_PCP_KEY_NOT_SIGNING_KEY = 0xC029201A,
++ MD_NTSTATUS_WIN_STATUS_PCP_LOCKED_OUT = 0xC029201B,
++ MD_NTSTATUS_WIN_STATUS_PCP_CLAIM_TYPE_NOT_SUPPORTED = 0xC029201C,
++ MD_NTSTATUS_WIN_STATUS_PCP_TPM_VERSION_NOT_SUPPORTED = 0xC029201D,
++ MD_NTSTATUS_WIN_STATUS_PCP_BUFFER_LENGTH_MISMATCH = 0xC029201E,
++ MD_NTSTATUS_WIN_STATUS_PCP_IFX_RSA_KEY_CREATION_BLOCKED = 0xC029201F,
++ MD_NTSTATUS_WIN_STATUS_PCP_TICKET_MISSING = 0xC0292020,
++ MD_NTSTATUS_WIN_STATUS_PCP_RAW_POLICY_NOT_SUPPORTED = 0xC0292021,
++ MD_NTSTATUS_WIN_STATUS_PCP_KEY_HANDLE_INVALIDATED = 0xC0292022,
++ MD_NTSTATUS_WIN_STATUS_RTPM_NO_RESULT = 0xC0293002,
++ MD_NTSTATUS_WIN_STATUS_RTPM_PCR_READ_INCOMPLETE = 0xC0293003,
++ MD_NTSTATUS_WIN_STATUS_RTPM_INVALID_CONTEXT = 0xC0293004,
++ MD_NTSTATUS_WIN_STATUS_RTPM_UNSUPPORTED_CMD = 0xC0293005,
++ MD_NTSTATUS_WIN_STATUS_TPM_ZERO_EXHAUST_ENABLED = 0xC0294000,
+ MD_NTSTATUS_WIN_STATUS_HV_INVALID_HYPERCALL_CODE = 0xC0350002,
+ MD_NTSTATUS_WIN_STATUS_HV_INVALID_HYPERCALL_INPUT = 0xC0350003,
+ MD_NTSTATUS_WIN_STATUS_HV_INVALID_ALIGNMENT = 0xC0350004,
+ MD_NTSTATUS_WIN_STATUS_HV_INVALID_PARAMETER = 0xC0350005,
+ MD_NTSTATUS_WIN_STATUS_HV_ACCESS_DENIED = 0xC0350006,
+ MD_NTSTATUS_WIN_STATUS_HV_INVALID_PARTITION_STATE = 0xC0350007,
+ MD_NTSTATUS_WIN_STATUS_HV_OPERATION_DENIED = 0xC0350008,
+ MD_NTSTATUS_WIN_STATUS_HV_UNKNOWN_PROPERTY = 0xC0350009,
+@@ -1986,28 +2476,46 @@ typedef enum {
+ MD_NTSTATUS_WIN_STATUS_HV_INSUFFICIENT_MEMORY = 0xC035000B,
+ MD_NTSTATUS_WIN_STATUS_HV_PARTITION_TOO_DEEP = 0xC035000C,
+ MD_NTSTATUS_WIN_STATUS_HV_INVALID_PARTITION_ID = 0xC035000D,
+ MD_NTSTATUS_WIN_STATUS_HV_INVALID_VP_INDEX = 0xC035000E,
+ MD_NTSTATUS_WIN_STATUS_HV_INVALID_PORT_ID = 0xC0350011,
+ MD_NTSTATUS_WIN_STATUS_HV_INVALID_CONNECTION_ID = 0xC0350012,
+ MD_NTSTATUS_WIN_STATUS_HV_INSUFFICIENT_BUFFERS = 0xC0350013,
+ MD_NTSTATUS_WIN_STATUS_HV_NOT_ACKNOWLEDGED = 0xC0350014,
++ MD_NTSTATUS_WIN_STATUS_HV_INVALID_VP_STATE = 0xC0350015,
+ MD_NTSTATUS_WIN_STATUS_HV_ACKNOWLEDGED = 0xC0350016,
+ MD_NTSTATUS_WIN_STATUS_HV_INVALID_SAVE_RESTORE_STATE = 0xC0350017,
+ MD_NTSTATUS_WIN_STATUS_HV_INVALID_SYNIC_STATE = 0xC0350018,
+ MD_NTSTATUS_WIN_STATUS_HV_OBJECT_IN_USE = 0xC0350019,
+ MD_NTSTATUS_WIN_STATUS_HV_INVALID_PROXIMITY_DOMAIN_INFO = 0xC035001A,
+ MD_NTSTATUS_WIN_STATUS_HV_NO_DATA = 0xC035001B,
+ MD_NTSTATUS_WIN_STATUS_HV_INACTIVE = 0xC035001C,
+ MD_NTSTATUS_WIN_STATUS_HV_NO_RESOURCES = 0xC035001D,
+ MD_NTSTATUS_WIN_STATUS_HV_FEATURE_UNAVAILABLE = 0xC035001E,
+ MD_NTSTATUS_WIN_STATUS_HV_INSUFFICIENT_BUFFER = 0xC0350033,
+ MD_NTSTATUS_WIN_STATUS_HV_INSUFFICIENT_DEVICE_DOMAINS = 0xC0350038,
++ MD_NTSTATUS_WIN_STATUS_HV_CPUID_FEATURE_VALIDATION_ERROR = 0xC035003C,
++ MD_NTSTATUS_WIN_STATUS_HV_CPUID_XSAVE_FEATURE_VALIDATION_ERROR = 0xC035003D,
++ MD_NTSTATUS_WIN_STATUS_HV_PROCESSOR_STARTUP_TIMEOUT = 0xC035003E,
++ MD_NTSTATUS_WIN_STATUS_HV_SMX_ENABLED = 0xC035003F,
+ MD_NTSTATUS_WIN_STATUS_HV_INVALID_LP_INDEX = 0xC0350041,
++ MD_NTSTATUS_WIN_STATUS_HV_INVALID_REGISTER_VALUE = 0xC0350050,
++ MD_NTSTATUS_WIN_STATUS_HV_INVALID_VTL_STATE = 0xC0350051,
++ MD_NTSTATUS_WIN_STATUS_HV_NX_NOT_DETECTED = 0xC0350055,
++ MD_NTSTATUS_WIN_STATUS_HV_INVALID_DEVICE_ID = 0xC0350057,
++ MD_NTSTATUS_WIN_STATUS_HV_INVALID_DEVICE_STATE = 0xC0350058,
++ MD_NTSTATUS_WIN_STATUS_HV_PAGE_REQUEST_INVALID = 0xC0350060,
++ MD_NTSTATUS_WIN_STATUS_HV_INVALID_CPU_GROUP_ID = 0xC035006F,
++ MD_NTSTATUS_WIN_STATUS_HV_INVALID_CPU_GROUP_STATE = 0xC0350070,
++ MD_NTSTATUS_WIN_STATUS_HV_OPERATION_FAILED = 0xC0350071,
++ MD_NTSTATUS_WIN_STATUS_HV_NOT_ALLOWED_WITH_NESTED_VIRT_ACTIVE = 0xC0350072,
++ MD_NTSTATUS_WIN_STATUS_HV_INSUFFICIENT_ROOT_MEMORY = 0xC0350073,
++ MD_NTSTATUS_WIN_STATUS_HV_EVENT_BUFFER_ALREADY_FREED = 0xC0350074,
++ MD_NTSTATUS_WIN_STATUS_HV_INSUFFICIENT_CONTIGUOUS_MEMORY = 0xC0350075,
+ MD_NTSTATUS_WIN_STATUS_HV_NOT_PRESENT = 0xC0351000,
+ MD_NTSTATUS_WIN_STATUS_IPSEC_BAD_SPI = 0xC0360001,
+ MD_NTSTATUS_WIN_STATUS_IPSEC_SA_LIFETIME_EXPIRED = 0xC0360002,
+ MD_NTSTATUS_WIN_STATUS_IPSEC_WRONG_SA = 0xC0360003,
+ MD_NTSTATUS_WIN_STATUS_IPSEC_REPLAY_CHECK_FAILED = 0xC0360004,
+ MD_NTSTATUS_WIN_STATUS_IPSEC_INVALID_PACKET = 0xC0360005,
+ MD_NTSTATUS_WIN_STATUS_IPSEC_INTEGRITY_CHECK_FAILED = 0xC0360006,
+ MD_NTSTATUS_WIN_STATUS_IPSEC_CLEAR_TEXT_DROP = 0xC0360007,
+@@ -2056,16 +2564,17 @@ typedef enum {
+ MD_NTSTATUS_WIN_STATUS_VID_INVALID_CHILD_GPA_PAGE_SET = 0xC0370022,
+ MD_NTSTATUS_WIN_STATUS_VID_RESERVE_PAGE_SET_IS_BEING_USED = 0xC0370023,
+ MD_NTSTATUS_WIN_STATUS_VID_RESERVE_PAGE_SET_TOO_SMALL = 0xC0370024,
+ MD_NTSTATUS_WIN_STATUS_VID_MBP_ALREADY_LOCKED_USING_RESERVED_PAGE = 0xC0370025,
+ MD_NTSTATUS_WIN_STATUS_VID_MBP_COUNT_EXCEEDED_LIMIT = 0xC0370026,
+ MD_NTSTATUS_WIN_STATUS_VID_SAVED_STATE_CORRUPT = 0xC0370027,
+ MD_NTSTATUS_WIN_STATUS_VID_SAVED_STATE_UNRECOGNIZED_ITEM = 0xC0370028,
+ MD_NTSTATUS_WIN_STATUS_VID_SAVED_STATE_INCOMPATIBLE = 0xC0370029,
++ MD_NTSTATUS_WIN_STATUS_VID_VTL_ACCESS_DENIED = 0xC037002A,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_DATABASE_FULL = 0xC0380001,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_CONFIGURATION_CORRUPTED = 0xC0380002,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_CONFIGURATION_NOT_IN_SYNC = 0xC0380003,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_PACK_CONFIG_UPDATE_FAILED = 0xC0380004,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_CONTAINS_NON_SIMPLE_VOLUME = 0xC0380005,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_DUPLICATE = 0xC0380006,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_DYNAMIC = 0xC0380007,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_ID_INVALID = 0xC0380008,
+@@ -2186,25 +2695,32 @@ typedef enum {
+ MD_NTSTATUS_WIN_STATUS_VIRTDISK_DISK_ALREADY_OWNED = 0xC03A001E,
+ MD_NTSTATUS_WIN_STATUS_VIRTDISK_DISK_ONLINE_AND_WRITABLE = 0xC03A001F,
+ MD_NTSTATUS_WIN_STATUS_CTLOG_TRACKING_NOT_INITIALIZED = 0xC03A0020,
+ MD_NTSTATUS_WIN_STATUS_CTLOG_LOGFILE_SIZE_EXCEEDED_MAXSIZE = 0xC03A0021,
+ MD_NTSTATUS_WIN_STATUS_CTLOG_VHD_CHANGED_OFFLINE = 0xC03A0022,
+ MD_NTSTATUS_WIN_STATUS_CTLOG_INVALID_TRACKING_STATE = 0xC03A0023,
+ MD_NTSTATUS_WIN_STATUS_CTLOG_INCONSISTENT_TRACKING_FILE = 0xC03A0024,
+ MD_NTSTATUS_WIN_STATUS_VHD_METADATA_FULL = 0xC03A0028,
++ MD_NTSTATUS_WIN_STATUS_VHD_INVALID_CHANGE_TRACKING_ID = 0xC03A0029,
++ MD_NTSTATUS_WIN_STATUS_VHD_CHANGE_TRACKING_DISABLED = 0xC03A002A,
++ MD_NTSTATUS_WIN_STATUS_VHD_MISSING_CHANGE_TRACKING_INFORMATION = 0xC03A0030,
++ MD_NTSTATUS_WIN_STATUS_VHD_RESIZE_WOULD_TRUNCATE_DATA = 0xC03A0031,
++ MD_NTSTATUS_WIN_STATUS_VHD_COULD_NOT_COMPUTE_MINIMUM_VIRTUAL_SIZE = 0xC03A0032,
++ MD_NTSTATUS_WIN_STATUS_VHD_ALREADY_AT_OR_BELOW_MINIMUM_VIRTUAL_SIZE = 0xC03A0033,
+ MD_NTSTATUS_WIN_STATUS_RKF_KEY_NOT_FOUND = 0xC0400001,
+ MD_NTSTATUS_WIN_STATUS_RKF_DUPLICATE_KEY = 0xC0400002,
+ MD_NTSTATUS_WIN_STATUS_RKF_BLOB_FULL = 0xC0400003,
+ MD_NTSTATUS_WIN_STATUS_RKF_STORE_FULL = 0xC0400004,
+ MD_NTSTATUS_WIN_STATUS_RKF_FILE_BLOCKED = 0xC0400005,
+ MD_NTSTATUS_WIN_STATUS_RKF_ACTIVE_KEY = 0xC0400006,
+ MD_NTSTATUS_WIN_STATUS_RDBSS_RESTART_OPERATION = 0xC0410001,
+ MD_NTSTATUS_WIN_STATUS_RDBSS_CONTINUE_OPERATION = 0xC0410002,
+ MD_NTSTATUS_WIN_STATUS_RDBSS_POST_OPERATION = 0xC0410003,
++ MD_NTSTATUS_WIN_STATUS_RDBSS_RETRY_LOOKUP = 0xC0410004,
+ MD_NTSTATUS_WIN_STATUS_BTH_ATT_INVALID_HANDLE = 0xC0420001,
+ MD_NTSTATUS_WIN_STATUS_BTH_ATT_READ_NOT_PERMITTED = 0xC0420002,
+ MD_NTSTATUS_WIN_STATUS_BTH_ATT_WRITE_NOT_PERMITTED = 0xC0420003,
+ MD_NTSTATUS_WIN_STATUS_BTH_ATT_INVALID_PDU = 0xC0420004,
+ MD_NTSTATUS_WIN_STATUS_BTH_ATT_INSUFFICIENT_AUTHENTICATION = 0xC0420005,
+ MD_NTSTATUS_WIN_STATUS_BTH_ATT_REQUEST_NOT_SUPPORTED = 0xC0420006,
+ MD_NTSTATUS_WIN_STATUS_BTH_ATT_INVALID_OFFSET = 0xC0420007,
+ MD_NTSTATUS_WIN_STATUS_BTH_ATT_INSUFFICIENT_AUTHORIZATION = 0xC0420008,
+@@ -2219,40 +2735,113 @@ typedef enum {
+ MD_NTSTATUS_WIN_STATUS_BTH_ATT_INSUFFICIENT_RESOURCES = 0xC0420011,
+ MD_NTSTATUS_WIN_STATUS_BTH_ATT_UNKNOWN_ERROR = 0xC0421000,
+ MD_NTSTATUS_WIN_STATUS_SECUREBOOT_ROLLBACK_DETECTED = 0xC0430001,
+ MD_NTSTATUS_WIN_STATUS_SECUREBOOT_POLICY_VIOLATION = 0xC0430002,
+ MD_NTSTATUS_WIN_STATUS_SECUREBOOT_INVALID_POLICY = 0xC0430003,
+ MD_NTSTATUS_WIN_STATUS_SECUREBOOT_POLICY_PUBLISHER_NOT_FOUND = 0xC0430004,
+ MD_NTSTATUS_WIN_STATUS_SECUREBOOT_POLICY_NOT_SIGNED = 0xC0430005,
+ MD_NTSTATUS_WIN_STATUS_SECUREBOOT_FILE_REPLACED = 0xC0430007,
++ MD_NTSTATUS_WIN_STATUS_SECUREBOOT_POLICY_NOT_AUTHORIZED = 0xC0430008,
++ MD_NTSTATUS_WIN_STATUS_SECUREBOOT_POLICY_UNKNOWN = 0xC0430009,
++ MD_NTSTATUS_WIN_STATUS_SECUREBOOT_POLICY_MISSING_ANTIROLLBACKVERSION = 0xC043000A,
++ MD_NTSTATUS_WIN_STATUS_SECUREBOOT_PLATFORM_ID_MISMATCH = 0xC043000B,
++ MD_NTSTATUS_WIN_STATUS_SECUREBOOT_POLICY_ROLLBACK_DETECTED = 0xC043000C,
++ MD_NTSTATUS_WIN_STATUS_SECUREBOOT_POLICY_UPGRADE_MISMATCH = 0xC043000D,
++ MD_NTSTATUS_WIN_STATUS_SECUREBOOT_REQUIRED_POLICY_FILE_MISSING = 0xC043000E,
++ MD_NTSTATUS_WIN_STATUS_SECUREBOOT_NOT_BASE_POLICY = 0xC043000F,
++ MD_NTSTATUS_WIN_STATUS_SECUREBOOT_NOT_SUPPLEMENTAL_POLICY = 0xC0430010,
+ MD_NTSTATUS_WIN_STATUS_AUDIO_ENGINE_NODE_NOT_FOUND = 0xC0440001,
+ MD_NTSTATUS_WIN_STATUS_HDAUDIO_EMPTY_CONNECTION_LIST = 0xC0440002,
+ MD_NTSTATUS_WIN_STATUS_HDAUDIO_CONNECTION_LIST_NOT_SUPPORTED = 0xC0440003,
+ MD_NTSTATUS_WIN_STATUS_HDAUDIO_NO_LOGICAL_DEVICES_CREATED = 0xC0440004,
+ MD_NTSTATUS_WIN_STATUS_HDAUDIO_NULL_LINKED_LIST_ENTRY = 0xC0440005,
++ MD_NTSTATUS_WIN_STATUS_VSM_NOT_INITIALIZED = 0xC0450000,
++ MD_NTSTATUS_WIN_STATUS_VSM_DMA_PROTECTION_NOT_IN_USE = 0xC0450001,
+ MD_NTSTATUS_WIN_STATUS_VOLSNAP_BOOTFILE_NOT_VALID = 0xC0500003,
++ MD_NTSTATUS_WIN_STATUS_VOLSNAP_ACTIVATION_TIMEOUT = 0xC0500004,
+ MD_NTSTATUS_WIN_STATUS_IO_PREEMPTED = 0xC0510001,
+ MD_NTSTATUS_WIN_STATUS_SVHDX_ERROR_STORED = 0xC05C0000,
+ MD_NTSTATUS_WIN_STATUS_SVHDX_ERROR_NOT_AVAILABLE = 0xC05CFF00,
+ MD_NTSTATUS_WIN_STATUS_SVHDX_UNIT_ATTENTION_AVAILABLE = 0xC05CFF01,
+ MD_NTSTATUS_WIN_STATUS_SVHDX_UNIT_ATTENTION_CAPACITY_DATA_CHANGED = 0xC05CFF02,
+ MD_NTSTATUS_WIN_STATUS_SVHDX_UNIT_ATTENTION_RESERVATIONS_PREEMPTED = 0xC05CFF03,
+ MD_NTSTATUS_WIN_STATUS_SVHDX_UNIT_ATTENTION_RESERVATIONS_RELEASED = 0xC05CFF04,
+ MD_NTSTATUS_WIN_STATUS_SVHDX_UNIT_ATTENTION_REGISTRATIONS_PREEMPTED = 0xC05CFF05,
+ MD_NTSTATUS_WIN_STATUS_SVHDX_UNIT_ATTENTION_OPERATING_DEFINITION_CHANGED = 0xC05CFF06,
+ MD_NTSTATUS_WIN_STATUS_SVHDX_RESERVATION_CONFLICT = 0xC05CFF07,
+ MD_NTSTATUS_WIN_STATUS_SVHDX_WRONG_FILE_TYPE = 0xC05CFF08,
+ MD_NTSTATUS_WIN_STATUS_SVHDX_VERSION_MISMATCH = 0xC05CFF09,
+ MD_NTSTATUS_WIN_STATUS_VHD_SHARED = 0xC05CFF0A,
++ MD_NTSTATUS_WIN_STATUS_SVHDX_NO_INITIATOR = 0xC05CFF0B,
++ MD_NTSTATUS_WIN_STATUS_VHDSET_BACKING_STORAGE_NOT_FOUND = 0xC05CFF0C,
++ MD_NTSTATUS_WIN_STATUS_SMB_NO_PREAUTH_INTEGRITY_HASH_OVERLAP = 0xC05D0000,
++ MD_NTSTATUS_WIN_STATUS_SMB_BAD_CLUSTER_DIALECT = 0xC05D0001,
++ MD_NTSTATUS_WIN_STATUS_SMB_GUEST_LOGON_BLOCKED = 0xC05D0002,
++ MD_NTSTATUS_WIN_STATUS_SPACES_FAULT_DOMAIN_TYPE_INVALID = 0xC0E70001,
+ MD_NTSTATUS_WIN_STATUS_SPACES_RESILIENCY_TYPE_INVALID = 0xC0E70003,
+ MD_NTSTATUS_WIN_STATUS_SPACES_DRIVE_SECTOR_SIZE_INVALID = 0xC0E70004,
++ MD_NTSTATUS_WIN_STATUS_SPACES_DRIVE_REDUNDANCY_INVALID = 0xC0E70006,
++ MD_NTSTATUS_WIN_STATUS_SPACES_NUMBER_OF_DATA_COPIES_INVALID = 0xC0E70007,
+ MD_NTSTATUS_WIN_STATUS_SPACES_INTERLEAVE_LENGTH_INVALID = 0xC0E70009,
+ MD_NTSTATUS_WIN_STATUS_SPACES_NUMBER_OF_COLUMNS_INVALID = 0xC0E7000A,
+- MD_NTSTATUS_WIN_STATUS_SPACES_NOT_ENOUGH_DRIVES = 0xC0E7000B
++ MD_NTSTATUS_WIN_STATUS_SPACES_NOT_ENOUGH_DRIVES = 0xC0E7000B,
++ MD_NTSTATUS_WIN_STATUS_SPACES_EXTENDED_ERROR = 0xC0E7000C,
++ MD_NTSTATUS_WIN_STATUS_SPACES_PROVISIONING_TYPE_INVALID = 0xC0E7000D,
++ MD_NTSTATUS_WIN_STATUS_SPACES_ALLOCATION_SIZE_INVALID = 0xC0E7000E,
++ MD_NTSTATUS_WIN_STATUS_SPACES_ENCLOSURE_AWARE_INVALID = 0xC0E7000F,
++ MD_NTSTATUS_WIN_STATUS_SPACES_WRITE_CACHE_SIZE_INVALID = 0xC0E70010,
++ MD_NTSTATUS_WIN_STATUS_SPACES_NUMBER_OF_GROUPS_INVALID = 0xC0E70011,
++ MD_NTSTATUS_WIN_STATUS_SPACES_DRIVE_OPERATIONAL_STATE_INVALID = 0xC0E70012,
++ MD_NTSTATUS_WIN_STATUS_SPACES_UPDATE_COLUMN_STATE = 0xC0E70013,
++ MD_NTSTATUS_WIN_STATUS_SPACES_MAP_REQUIRED = 0xC0E70014,
++ MD_NTSTATUS_WIN_STATUS_SPACES_UNSUPPORTED_VERSION = 0xC0E70015,
++ MD_NTSTATUS_WIN_STATUS_SPACES_CORRUPT_METADATA = 0xC0E70016,
++ MD_NTSTATUS_WIN_STATUS_SPACES_DRT_FULL = 0xC0E70017,
++ MD_NTSTATUS_WIN_STATUS_SPACES_INCONSISTENCY = 0xC0E70018,
++ MD_NTSTATUS_WIN_STATUS_SPACES_LOG_NOT_READY = 0xC0E70019,
++ MD_NTSTATUS_WIN_STATUS_SPACES_NO_REDUNDANCY = 0xC0E7001A,
++ MD_NTSTATUS_WIN_STATUS_SPACES_DRIVE_NOT_READY = 0xC0E7001B,
++ MD_NTSTATUS_WIN_STATUS_SPACES_DRIVE_SPLIT = 0xC0E7001C,
++ MD_NTSTATUS_WIN_STATUS_SPACES_DRIVE_LOST_DATA = 0xC0E7001D,
++ MD_NTSTATUS_WIN_STATUS_SPACES_ENTRY_INCOMPLETE = 0xC0E7001E,
++ MD_NTSTATUS_WIN_STATUS_SPACES_ENTRY_INVALID = 0xC0E7001F,
++ MD_NTSTATUS_WIN_STATUS_SPACES_MARK_DIRTY = 0xC0E70020,
++ MD_NTSTATUS_WIN_STATUS_SECCORE_INVALID_COMMAND = 0xC0E80000,
++ MD_NTSTATUS_WIN_STATUS_SYSTEM_INTEGRITY_ROLLBACK_DETECTED = 0xC0E90001,
++ MD_NTSTATUS_WIN_STATUS_SYSTEM_INTEGRITY_POLICY_VIOLATION = 0xC0E90002,
++ MD_NTSTATUS_WIN_STATUS_SYSTEM_INTEGRITY_INVALID_POLICY = 0xC0E90003,
++ MD_NTSTATUS_WIN_STATUS_SYSTEM_INTEGRITY_POLICY_NOT_SIGNED = 0xC0E90004,
++ MD_NTSTATUS_WIN_STATUS_SYSTEM_INTEGRITY_TOO_MANY_POLICIES = 0xC0E90005,
++ MD_NTSTATUS_WIN_STATUS_SYSTEM_INTEGRITY_SUPPLEMENTAL_POLICY_NOT_AUTHORIZED = 0xC0E90006,
++ MD_NTSTATUS_WIN_STATUS_NO_APPLICABLE_APP_LICENSES_FOUND = 0xC0EA0001,
++ MD_NTSTATUS_WIN_STATUS_CLIP_LICENSE_NOT_FOUND = 0xC0EA0002,
++ MD_NTSTATUS_WIN_STATUS_CLIP_DEVICE_LICENSE_MISSING = 0xC0EA0003,
++ MD_NTSTATUS_WIN_STATUS_CLIP_LICENSE_INVALID_SIGNATURE = 0xC0EA0004,
++ MD_NTSTATUS_WIN_STATUS_CLIP_KEYHOLDER_LICENSE_MISSING_OR_INVALID = 0xC0EA0005,
++ MD_NTSTATUS_WIN_STATUS_CLIP_LICENSE_EXPIRED = 0xC0EA0006,
++ MD_NTSTATUS_WIN_STATUS_CLIP_LICENSE_SIGNED_BY_UNKNOWN_SOURCE = 0xC0EA0007,
++ MD_NTSTATUS_WIN_STATUS_CLIP_LICENSE_NOT_SIGNED = 0xC0EA0008,
++ MD_NTSTATUS_WIN_STATUS_CLIP_LICENSE_HARDWARE_ID_OUT_OF_TOLERANCE = 0xC0EA0009,
++ MD_NTSTATUS_WIN_STATUS_CLIP_LICENSE_DEVICE_ID_MISMATCH = 0xC0EA000A,
++ MD_NTSTATUS_WIN_STATUS_PLATFORM_MANIFEST_NOT_AUTHORIZED = 0xC0EB0001,
++ MD_NTSTATUS_WIN_STATUS_PLATFORM_MANIFEST_INVALID = 0xC0EB0002,
++ MD_NTSTATUS_WIN_STATUS_PLATFORM_MANIFEST_FILE_NOT_AUTHORIZED = 0xC0EB0003,
++ MD_NTSTATUS_WIN_STATUS_PLATFORM_MANIFEST_CATALOG_NOT_AUTHORIZED = 0xC0EB0004,
++ MD_NTSTATUS_WIN_STATUS_PLATFORM_MANIFEST_BINARY_ID_NOT_FOUND = 0xC0EB0005,
++ MD_NTSTATUS_WIN_STATUS_PLATFORM_MANIFEST_NOT_ACTIVE = 0xC0EB0006,
++ MD_NTSTATUS_WIN_STATUS_PLATFORM_MANIFEST_NOT_SIGNED = 0xC0EB0007,
++ MD_NTSTATUS_WIN_STATUS_APPEXEC_CONDITION_NOT_SATISFIED = 0xC0EC0000,
++ MD_NTSTATUS_WIN_STATUS_APPEXEC_HANDLE_INVALIDATED = 0xC0EC0001,
++ MD_NTSTATUS_WIN_STATUS_APPEXEC_INVALID_HOST_GENERATION = 0xC0EC0002,
++ MD_NTSTATUS_WIN_STATUS_APPEXEC_UNEXPECTED_PROCESS_REGISTRATION = 0xC0EC0003,
++ MD_NTSTATUS_WIN_STATUS_APPEXEC_INVALID_HOST_STATE = 0xC0EC0004,
++ MD_NTSTATUS_WIN_STATUS_APPEXEC_NO_DONOR = 0xC0EC0005,
++ MD_NTSTATUS_WIN_STATUS_APPEXEC_HOST_ID_MISMATCH = 0xC0EC0006,
++ MD_NTSTATUS_WIN_STATUS_APPEXEC_UNKNOWN_USER = 0xC0EC0007,
+ } MDNTStatusCodeWin;
+
+ // These constants are defined in the MSDN documentation of
+ // the EXCEPTION_RECORD structure.
+ typedef enum {
+ MD_ACCESS_VIOLATION_WIN_READ = 0,
+ MD_ACCESS_VIOLATION_WIN_WRITE = 1,
+ MD_ACCESS_VIOLATION_WIN_EXEC = 8
+diff --git a/src/processor/exploitability_win.cc b/src/processor/exploitability_win.cc
+--- a/src/processor/exploitability_win.cc
++++ b/src/processor/exploitability_win.cc
+@@ -147,18 +147,18 @@ ExploitabilityRating ExploitabilityWin::
+ break;
+
+ // These represent bugs in exception handlers.
+ case MD_EXCEPTION_CODE_WIN_INVALID_DISPOSITION:
+ case MD_EXCEPTION_CODE_WIN_NONCONTINUABLE_EXCEPTION:
+ exploitability_weight += kSmallBump;
+ break;
+
+- case MD_EXCEPTION_CODE_WIN_HEAP_CORRUPTION:
+- case MD_EXCEPTION_CODE_WIN_STACK_BUFFER_OVERRUN:
++ case MD_NTSTATUS_WIN_STATUS_HEAP_CORRUPTION:
++ case MD_NTSTATUS_WIN_STATUS_STACK_BUFFER_OVERRUN:
+ exploitability_weight += kHugeBump;
+ break;
+
+ case MD_EXCEPTION_CODE_WIN_GUARD_PAGE_VIOLATION:
+ exploitability_weight += kLargeBump;
+ break;
+
+ case MD_EXCEPTION_CODE_WIN_ACCESS_VIOLATION:
+diff --git a/src/processor/minidump_processor.cc b/src/processor/minidump_processor.cc
+--- a/src/processor/minidump_processor.cc
++++ b/src/processor/minidump_processor.cc
+@@ -1138,19 +1138,16 @@ string MinidumpProcessor::GetCrashReason
+ break;
+ }
+ break;
+ }
+
+ case MD_OS_WIN32_NT:
+ case MD_OS_WIN32_WINDOWS: {
+ switch (exception_code) {
+- case MD_EXCEPTION_CODE_WIN_CONTROL_C:
+- reason = "DBG_CONTROL_C";
+- break;
+ case MD_EXCEPTION_CODE_WIN_GUARD_PAGE_VIOLATION:
+ reason = "EXCEPTION_GUARD_PAGE";
+ break;
+ case MD_EXCEPTION_CODE_WIN_DATATYPE_MISALIGNMENT:
+ reason = "EXCEPTION_DATATYPE_MISALIGNMENT";
+ break;
+ case MD_EXCEPTION_CODE_WIN_BREAKPOINT:
+ reason = "EXCEPTION_BREAKPOINT";
+@@ -1245,17 +1242,17 @@ string MinidumpProcessor::GetCrashReason
+ break;
+ case MD_EXCEPTION_CODE_WIN_NONCONTINUABLE_EXCEPTION:
+ reason = "EXCEPTION_NONCONTINUABLE_EXCEPTION";
+ break;
+ case MD_EXCEPTION_CODE_WIN_INVALID_DISPOSITION:
+ reason = "EXCEPTION_INVALID_DISPOSITION";
+ break;
+ case MD_EXCEPTION_CODE_WIN_ARRAY_BOUNDS_EXCEEDED:
+- reason = "EXCEPTION_BOUNDS_EXCEEDED";
++ reason = "EXCEPTION_ARRAY_BOUNDS_EXCEEDED";
+ break;
+ case MD_EXCEPTION_CODE_WIN_FLOAT_DENORMAL_OPERAND:
+ reason = "EXCEPTION_FLT_DENORMAL_OPERAND";
+ break;
+ case MD_EXCEPTION_CODE_WIN_FLOAT_DIVIDE_BY_ZERO:
+ reason = "EXCEPTION_FLT_DIVIDE_BY_ZERO";
+ break;
+ case MD_EXCEPTION_CODE_WIN_FLOAT_INEXACT_RESULT:
+@@ -1286,41 +1283,41 @@ string MinidumpProcessor::GetCrashReason
+ reason = "EXCEPTION_STACK_OVERFLOW";
+ break;
+ case MD_EXCEPTION_CODE_WIN_BAD_FUNCTION_TABLE:
+ reason = "EXCEPTION_BAD_FUNCTION_TABLE";
+ break;
+ case MD_EXCEPTION_CODE_WIN_POSSIBLE_DEADLOCK:
+ reason = "EXCEPTION_POSSIBLE_DEADLOCK";
+ break;
+- case MD_EXCEPTION_CODE_WIN_STACK_BUFFER_OVERRUN:
+- reason = "EXCEPTION_STACK_BUFFER_OVERRUN";
++ case MD_NTSTATUS_WIN_STATUS_STACK_BUFFER_OVERRUN:
++ reason = "STATUS_STACK_BUFFER_OVERRUN";
+ if (raw_exception->exception_record.number_parameters > 0) {
+ uint32_t fast_fail_code =
+ static_cast<uint32_t>
+ (raw_exception->exception_record.exception_information[0]);
+ reason.append(" / ");
+ reason.append(FastFailToString(fast_fail_code));
+ }
+
+ break;
+- case MD_EXCEPTION_CODE_WIN_HEAP_CORRUPTION:
+- reason = "EXCEPTION_HEAP_CORRUPTION";
+- break;
+ case MD_EXCEPTION_OUT_OF_MEMORY:
+ reason = "Out of Memory";
+ break;
+ case MD_EXCEPTION_CODE_WIN_UNHANDLED_CPP_EXCEPTION:
+ reason = "Unhandled C++ Exception";
+ break;
+ case MD_EXCEPTION_CODE_WIN_SIMULATED:
+ reason = "Simulated Exception";
+ break;
+ default:
+- BPLOG(INFO) << "Unknown exception reason " << reason;
++ reason = NTStatusToString(exception_code);
++ if (reason.substr(0, 2) == "0x") {
++ BPLOG(INFO) << "Unknown exception reason " << reason;
++ }
+ break;
+ }
+ break;
+ }
+
+ case MD_OS_ANDROID:
+ case MD_OS_LINUX: {
+ switch (exception_code) {
+diff --git a/src/processor/symbolic_constants_win.cc b/src/processor/symbolic_constants_win.cc
+--- a/src/processor/symbolic_constants_win.cc
++++ b/src/processor/symbolic_constants_win.cc
+@@ -39,31 +39,761 @@
+ #include "google_breakpad/common/breakpad_types.h"
+ #include "google_breakpad/common/minidump_exception_win32.h"
+ #include "processor/symbolic_constants_win.h"
+
+ namespace google_breakpad {
+
+ string NTStatusToString(uint32_t ntstatus) {
+ string reason;
+- // The content of this switch was created from ntstatus.h in the 8.1 SDK with
++ // The content of this switch was created from ntstatus.h in the 10 SDK
++ // (version 10.0.19041.0) with
+ //
+- // egrep '#define [A-Z_0-9]+\s+\(\(NTSTATUS\)0xC[0-9A-F]+L\)' ntstatus.h
++ // egrep '#define [A-Z_0-9]+\s+\(\(NTSTATUS\)0x[048C][0-9A-F]+L\)' ntstatus.h
+ // | tr -d '\r'
+- // | sed -r 's@#define ([A-Z_0-9]+)\s+\(\(NTSTATUS\)(0xC[0-9A-F]+)L\).*@\2 \1@'
++ // | sed -r 's@#define ([A-Z_0-9]+)\s+\(\(NTSTATUS\)(0x[048C][0-9A-F]+)L\).*@\2 \1@'
+ // | sort
+- // | sed -r 's@(0xC[0-9A-F]+) ([A-Z_0-9]+)@ case MD_NTSTATUS_WIN_\2:\n reason = "\2";\n break;@'
++ // | sed -r 's@(0x[048C][0-9A-F]+) ([A-Z_0-9]+)@ case MD_NTSTATUS_WIN_\2:\n reason = "\2";\n break;@'
+ //
+ // With easy copy to clipboard with
+ // | xclip -selection c # on linux
+ // | clip # on windows
+ // | pbcopy # on mac
+ //
+ // and then the default case added.
+ switch (ntstatus) {
++ case MD_NTSTATUS_WIN_STATUS_SUCCESS:
++ reason = "STATUS_SUCCESS";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_WAIT_1:
++ reason = "STATUS_WAIT_1";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_WAIT_2:
++ reason = "STATUS_WAIT_2";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_WAIT_3:
++ reason = "STATUS_WAIT_3";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_WAIT_63:
++ reason = "STATUS_WAIT_63";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_ABANDONED:
++ reason = "STATUS_ABANDONED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_ABANDONED_WAIT_63:
++ reason = "STATUS_ABANDONED_WAIT_63";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_USER_APC:
++ reason = "STATUS_USER_APC";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_ALREADY_COMPLETE:
++ reason = "STATUS_ALREADY_COMPLETE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_KERNEL_APC:
++ reason = "STATUS_KERNEL_APC";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_ALERTED:
++ reason = "STATUS_ALERTED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_TIMEOUT:
++ reason = "STATUS_TIMEOUT";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_PENDING:
++ reason = "STATUS_PENDING";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_REPARSE:
++ reason = "STATUS_REPARSE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_MORE_ENTRIES:
++ reason = "STATUS_MORE_ENTRIES";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_NOT_ALL_ASSIGNED:
++ reason = "STATUS_NOT_ALL_ASSIGNED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_SOME_NOT_MAPPED:
++ reason = "STATUS_SOME_NOT_MAPPED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_OPLOCK_BREAK_IN_PROGRESS:
++ reason = "STATUS_OPLOCK_BREAK_IN_PROGRESS";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_VOLUME_MOUNTED:
++ reason = "STATUS_VOLUME_MOUNTED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_RXACT_COMMITTED:
++ reason = "STATUS_RXACT_COMMITTED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_NOTIFY_CLEANUP:
++ reason = "STATUS_NOTIFY_CLEANUP";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_NOTIFY_ENUM_DIR:
++ reason = "STATUS_NOTIFY_ENUM_DIR";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_NO_QUOTAS_FOR_ACCOUNT:
++ reason = "STATUS_NO_QUOTAS_FOR_ACCOUNT";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_PRIMARY_TRANSPORT_CONNECT_FAILED:
++ reason = "STATUS_PRIMARY_TRANSPORT_CONNECT_FAILED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_PAGE_FAULT_TRANSITION:
++ reason = "STATUS_PAGE_FAULT_TRANSITION";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_PAGE_FAULT_DEMAND_ZERO:
++ reason = "STATUS_PAGE_FAULT_DEMAND_ZERO";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_PAGE_FAULT_COPY_ON_WRITE:
++ reason = "STATUS_PAGE_FAULT_COPY_ON_WRITE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_PAGE_FAULT_GUARD_PAGE:
++ reason = "STATUS_PAGE_FAULT_GUARD_PAGE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_PAGE_FAULT_PAGING_FILE:
++ reason = "STATUS_PAGE_FAULT_PAGING_FILE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_CACHE_PAGE_LOCKED:
++ reason = "STATUS_CACHE_PAGE_LOCKED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_CRASH_DUMP:
++ reason = "STATUS_CRASH_DUMP";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_BUFFER_ALL_ZEROS:
++ reason = "STATUS_BUFFER_ALL_ZEROS";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_REPARSE_OBJECT:
++ reason = "STATUS_REPARSE_OBJECT";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_RESOURCE_REQUIREMENTS_CHANGED:
++ reason = "STATUS_RESOURCE_REQUIREMENTS_CHANGED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_TRANSLATION_COMPLETE:
++ reason = "STATUS_TRANSLATION_COMPLETE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_DS_MEMBERSHIP_EVALUATED_LOCALLY:
++ reason = "STATUS_DS_MEMBERSHIP_EVALUATED_LOCALLY";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_NOTHING_TO_TERMINATE:
++ reason = "STATUS_NOTHING_TO_TERMINATE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_PROCESS_NOT_IN_JOB:
++ reason = "STATUS_PROCESS_NOT_IN_JOB";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_PROCESS_IN_JOB:
++ reason = "STATUS_PROCESS_IN_JOB";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_VOLSNAP_HIBERNATE_READY:
++ reason = "STATUS_VOLSNAP_HIBERNATE_READY";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_FSFILTER_OP_COMPLETED_SUCCESSFULLY:
++ reason = "STATUS_FSFILTER_OP_COMPLETED_SUCCESSFULLY";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_INTERRUPT_VECTOR_ALREADY_CONNECTED:
++ reason = "STATUS_INTERRUPT_VECTOR_ALREADY_CONNECTED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_INTERRUPT_STILL_CONNECTED:
++ reason = "STATUS_INTERRUPT_STILL_CONNECTED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_PROCESS_CLONED:
++ reason = "STATUS_PROCESS_CLONED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_FILE_LOCKED_WITH_ONLY_READERS:
++ reason = "STATUS_FILE_LOCKED_WITH_ONLY_READERS";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_FILE_LOCKED_WITH_WRITERS:
++ reason = "STATUS_FILE_LOCKED_WITH_WRITERS";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_VALID_IMAGE_HASH:
++ reason = "STATUS_VALID_IMAGE_HASH";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_VALID_CATALOG_HASH:
++ reason = "STATUS_VALID_CATALOG_HASH";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_VALID_STRONG_CODE_HASH:
++ reason = "STATUS_VALID_STRONG_CODE_HASH";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_GHOSTED:
++ reason = "STATUS_GHOSTED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_DATA_OVERWRITTEN:
++ reason = "STATUS_DATA_OVERWRITTEN";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_RESOURCEMANAGER_READ_ONLY:
++ reason = "STATUS_RESOURCEMANAGER_READ_ONLY";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_RING_PREVIOUSLY_EMPTY:
++ reason = "STATUS_RING_PREVIOUSLY_EMPTY";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_RING_PREVIOUSLY_FULL:
++ reason = "STATUS_RING_PREVIOUSLY_FULL";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_RING_PREVIOUSLY_ABOVE_QUOTA:
++ reason = "STATUS_RING_PREVIOUSLY_ABOVE_QUOTA";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_RING_NEWLY_EMPTY:
++ reason = "STATUS_RING_NEWLY_EMPTY";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_RING_SIGNAL_OPPOSITE_ENDPOINT:
++ reason = "STATUS_RING_SIGNAL_OPPOSITE_ENDPOINT";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_OPLOCK_SWITCHED_TO_NEW_HANDLE:
++ reason = "STATUS_OPLOCK_SWITCHED_TO_NEW_HANDLE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_OPLOCK_HANDLE_CLOSED:
++ reason = "STATUS_OPLOCK_HANDLE_CLOSED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_WAIT_FOR_OPLOCK:
++ reason = "STATUS_WAIT_FOR_OPLOCK";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_REPARSE_GLOBAL:
++ reason = "STATUS_REPARSE_GLOBAL";
++ break;
++ case MD_NTSTATUS_WIN_DBG_EXCEPTION_HANDLED:
++ reason = "DBG_EXCEPTION_HANDLED";
++ break;
++ case MD_NTSTATUS_WIN_DBG_CONTINUE:
++ reason = "DBG_CONTINUE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_FLT_IO_COMPLETE:
++ reason = "STATUS_FLT_IO_COMPLETE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_RTPM_CONTEXT_CONTINUE:
++ reason = "STATUS_RTPM_CONTEXT_CONTINUE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_RTPM_CONTEXT_COMPLETE:
++ reason = "STATUS_RTPM_CONTEXT_COMPLETE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_HV_PENDING_PAGE_REQUESTS:
++ reason = "STATUS_HV_PENDING_PAGE_REQUESTS";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_SPACES_REPAIRED:
++ reason = "STATUS_SPACES_REPAIRED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_SPACES_PAUSE:
++ reason = "STATUS_SPACES_PAUSE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_SPACES_COMPLETE:
++ reason = "STATUS_SPACES_COMPLETE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_SPACES_REDIRECT:
++ reason = "STATUS_SPACES_REDIRECT";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_OBJECT_NAME_EXISTS:
++ reason = "STATUS_OBJECT_NAME_EXISTS";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_THREAD_WAS_SUSPENDED:
++ reason = "STATUS_THREAD_WAS_SUSPENDED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_WORKING_SET_LIMIT_RANGE:
++ reason = "STATUS_WORKING_SET_LIMIT_RANGE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_IMAGE_NOT_AT_BASE:
++ reason = "STATUS_IMAGE_NOT_AT_BASE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_RXACT_STATE_CREATED:
++ reason = "STATUS_RXACT_STATE_CREATED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_SEGMENT_NOTIFICATION:
++ reason = "STATUS_SEGMENT_NOTIFICATION";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_LOCAL_USER_SESSION_KEY:
++ reason = "STATUS_LOCAL_USER_SESSION_KEY";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_BAD_CURRENT_DIRECTORY:
++ reason = "STATUS_BAD_CURRENT_DIRECTORY";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_SERIAL_MORE_WRITES:
++ reason = "STATUS_SERIAL_MORE_WRITES";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_REGISTRY_RECOVERED:
++ reason = "STATUS_REGISTRY_RECOVERED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_FT_READ_RECOVERY_FROM_BACKUP:
++ reason = "STATUS_FT_READ_RECOVERY_FROM_BACKUP";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_FT_WRITE_RECOVERY:
++ reason = "STATUS_FT_WRITE_RECOVERY";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_SERIAL_COUNTER_TIMEOUT:
++ reason = "STATUS_SERIAL_COUNTER_TIMEOUT";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_NULL_LM_PASSWORD:
++ reason = "STATUS_NULL_LM_PASSWORD";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_IMAGE_MACHINE_TYPE_MISMATCH:
++ reason = "STATUS_IMAGE_MACHINE_TYPE_MISMATCH";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_RECEIVE_PARTIAL:
++ reason = "STATUS_RECEIVE_PARTIAL";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_RECEIVE_EXPEDITED:
++ reason = "STATUS_RECEIVE_EXPEDITED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_RECEIVE_PARTIAL_EXPEDITED:
++ reason = "STATUS_RECEIVE_PARTIAL_EXPEDITED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_EVENT_DONE:
++ reason = "STATUS_EVENT_DONE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_EVENT_PENDING:
++ reason = "STATUS_EVENT_PENDING";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_CHECKING_FILE_SYSTEM:
++ reason = "STATUS_CHECKING_FILE_SYSTEM";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_FATAL_APP_EXIT:
++ reason = "STATUS_FATAL_APP_EXIT";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_PREDEFINED_HANDLE:
++ reason = "STATUS_PREDEFINED_HANDLE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_WAS_UNLOCKED:
++ reason = "STATUS_WAS_UNLOCKED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_SERVICE_NOTIFICATION:
++ reason = "STATUS_SERVICE_NOTIFICATION";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_WAS_LOCKED:
++ reason = "STATUS_WAS_LOCKED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_LOG_HARD_ERROR:
++ reason = "STATUS_LOG_HARD_ERROR";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_ALREADY_WIN32:
++ reason = "STATUS_ALREADY_WIN32";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_WX86_UNSIMULATE:
++ reason = "STATUS_WX86_UNSIMULATE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_WX86_CONTINUE:
++ reason = "STATUS_WX86_CONTINUE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_WX86_SINGLE_STEP:
++ reason = "STATUS_WX86_SINGLE_STEP";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_WX86_BREAKPOINT:
++ reason = "STATUS_WX86_BREAKPOINT";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_WX86_EXCEPTION_CONTINUE:
++ reason = "STATUS_WX86_EXCEPTION_CONTINUE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_WX86_EXCEPTION_LASTCHANCE:
++ reason = "STATUS_WX86_EXCEPTION_LASTCHANCE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_WX86_EXCEPTION_CHAIN:
++ reason = "STATUS_WX86_EXCEPTION_CHAIN";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_IMAGE_MACHINE_TYPE_MISMATCH_EXE:
++ reason = "STATUS_IMAGE_MACHINE_TYPE_MISMATCH_EXE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_NO_YIELD_PERFORMED:
++ reason = "STATUS_NO_YIELD_PERFORMED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_TIMER_RESUME_IGNORED:
++ reason = "STATUS_TIMER_RESUME_IGNORED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_ARBITRATION_UNHANDLED:
++ reason = "STATUS_ARBITRATION_UNHANDLED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_CARDBUS_NOT_SUPPORTED:
++ reason = "STATUS_CARDBUS_NOT_SUPPORTED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_WX86_CREATEWX86TIB:
++ reason = "STATUS_WX86_CREATEWX86TIB";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_MP_PROCESSOR_MISMATCH:
++ reason = "STATUS_MP_PROCESSOR_MISMATCH";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_HIBERNATED:
++ reason = "STATUS_HIBERNATED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_RESUME_HIBERNATION:
++ reason = "STATUS_RESUME_HIBERNATION";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_FIRMWARE_UPDATED:
++ reason = "STATUS_FIRMWARE_UPDATED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_DRIVERS_LEAKING_LOCKED_PAGES:
++ reason = "STATUS_DRIVERS_LEAKING_LOCKED_PAGES";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_MESSAGE_RETRIEVED:
++ reason = "STATUS_MESSAGE_RETRIEVED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_SYSTEM_POWERSTATE_TRANSITION:
++ reason = "STATUS_SYSTEM_POWERSTATE_TRANSITION";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_ALPC_CHECK_COMPLETION_LIST:
++ reason = "STATUS_ALPC_CHECK_COMPLETION_LIST";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_SYSTEM_POWERSTATE_COMPLEX_TRANSITION:
++ reason = "STATUS_SYSTEM_POWERSTATE_COMPLEX_TRANSITION";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_ACCESS_AUDIT_BY_POLICY:
++ reason = "STATUS_ACCESS_AUDIT_BY_POLICY";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_ABANDON_HIBERFILE:
++ reason = "STATUS_ABANDON_HIBERFILE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_BIZRULES_NOT_ENABLED:
++ reason = "STATUS_BIZRULES_NOT_ENABLED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_FT_READ_FROM_COPY:
++ reason = "STATUS_FT_READ_FROM_COPY";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_IMAGE_AT_DIFFERENT_BASE:
++ reason = "STATUS_IMAGE_AT_DIFFERENT_BASE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_PATCH_DEFERRED:
++ reason = "STATUS_PATCH_DEFERRED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_WAKE_SYSTEM:
++ reason = "STATUS_WAKE_SYSTEM";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_DS_SHUTTING_DOWN:
++ reason = "STATUS_DS_SHUTTING_DOWN";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_DISK_REPAIR_REDIRECTED:
++ reason = "STATUS_DISK_REPAIR_REDIRECTED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_SERVICES_FAILED_AUTOSTART:
++ reason = "STATUS_SERVICES_FAILED_AUTOSTART";
++ break;
++ case MD_NTSTATUS_WIN_DBG_REPLY_LATER:
++ reason = "DBG_REPLY_LATER";
++ break;
++ case MD_NTSTATUS_WIN_DBG_UNABLE_TO_PROVIDE_HANDLE:
++ reason = "DBG_UNABLE_TO_PROVIDE_HANDLE";
++ break;
++ case MD_NTSTATUS_WIN_DBG_TERMINATE_THREAD:
++ reason = "DBG_TERMINATE_THREAD";
++ break;
++ case MD_NTSTATUS_WIN_DBG_TERMINATE_PROCESS:
++ reason = "DBG_TERMINATE_PROCESS";
++ break;
++ case MD_NTSTATUS_WIN_DBG_CONTROL_C:
++ reason = "DBG_CONTROL_C";
++ break;
++ case MD_NTSTATUS_WIN_DBG_PRINTEXCEPTION_C:
++ reason = "DBG_PRINTEXCEPTION_C";
++ break;
++ case MD_NTSTATUS_WIN_DBG_RIPEXCEPTION:
++ reason = "DBG_RIPEXCEPTION";
++ break;
++ case MD_NTSTATUS_WIN_DBG_CONTROL_BREAK:
++ reason = "DBG_CONTROL_BREAK";
++ break;
++ case MD_NTSTATUS_WIN_DBG_COMMAND_EXCEPTION:
++ reason = "DBG_COMMAND_EXCEPTION";
++ break;
++ case MD_NTSTATUS_WIN_DBG_PRINTEXCEPTION_WIDE_C:
++ reason = "DBG_PRINTEXCEPTION_WIDE_C";
++ break;
++ case MD_NTSTATUS_WIN_RPC_NT_UUID_LOCAL_ONLY:
++ reason = "RPC_NT_UUID_LOCAL_ONLY";
++ break;
++ case MD_NTSTATUS_WIN_RPC_NT_SEND_INCOMPLETE:
++ reason = "RPC_NT_SEND_INCOMPLETE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_CTX_CDM_CONNECT:
++ reason = "STATUS_CTX_CDM_CONNECT";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_CTX_CDM_DISCONNECT:
++ reason = "STATUS_CTX_CDM_DISCONNECT";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_SXS_RELEASE_ACTIVATION_CONTEXT:
++ reason = "STATUS_SXS_RELEASE_ACTIVATION_CONTEXT";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_HEURISTIC_DAMAGE_POSSIBLE:
++ reason = "STATUS_HEURISTIC_DAMAGE_POSSIBLE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_RECOVERY_NOT_NEEDED:
++ reason = "STATUS_RECOVERY_NOT_NEEDED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_RM_ALREADY_STARTED:
++ reason = "STATUS_RM_ALREADY_STARTED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_LOG_NO_RESTART:
++ reason = "STATUS_LOG_NO_RESTART";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_VIDEO_DRIVER_DEBUG_REPORT_REQUEST:
++ reason = "STATUS_VIDEO_DRIVER_DEBUG_REPORT_REQUEST";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_GRAPHICS_PARTIAL_DATA_POPULATED:
++ reason = "STATUS_GRAPHICS_PARTIAL_DATA_POPULATED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_GRAPHICS_SKIP_ALLOCATION_PREPARATION:
++ reason = "STATUS_GRAPHICS_SKIP_ALLOCATION_PREPARATION";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_GRAPHICS_MODE_NOT_PINNED:
++ reason = "STATUS_GRAPHICS_MODE_NOT_PINNED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_GRAPHICS_NO_PREFERRED_MODE:
++ reason = "STATUS_GRAPHICS_NO_PREFERRED_MODE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_GRAPHICS_DATASET_IS_EMPTY:
++ reason = "STATUS_GRAPHICS_DATASET_IS_EMPTY";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_GRAPHICS_NO_MORE_ELEMENTS_IN_DATASET:
++ reason = "STATUS_GRAPHICS_NO_MORE_ELEMENTS_IN_DATASET";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_GRAPHICS_PATH_CONTENT_GEOMETRY_TRANSFORMATION_NOT_PINNED:
++ reason = "STATUS_GRAPHICS_PATH_CONTENT_GEOMETRY_TRANSFORMATION_NOT_PINNED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_GRAPHICS_UNKNOWN_CHILD_STATUS:
++ reason = "STATUS_GRAPHICS_UNKNOWN_CHILD_STATUS";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_GRAPHICS_LEADLINK_START_DEFERRED:
++ reason = "STATUS_GRAPHICS_LEADLINK_START_DEFERRED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_GRAPHICS_POLLING_TOO_FREQUENTLY:
++ reason = "STATUS_GRAPHICS_POLLING_TOO_FREQUENTLY";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_GRAPHICS_START_DEFERRED:
++ reason = "STATUS_GRAPHICS_START_DEFERRED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_GRAPHICS_DEPENDABLE_CHILD_STATUS:
++ reason = "STATUS_GRAPHICS_DEPENDABLE_CHILD_STATUS";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_NDIS_INDICATION_REQUIRED:
++ reason = "STATUS_NDIS_INDICATION_REQUIRED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_PCP_UNSUPPORTED_PSS_SALT:
++ reason = "STATUS_PCP_UNSUPPORTED_PSS_SALT";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_GUARD_PAGE_VIOLATION:
++ reason = "STATUS_GUARD_PAGE_VIOLATION";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_DATATYPE_MISALIGNMENT:
++ reason = "STATUS_DATATYPE_MISALIGNMENT";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_BREAKPOINT:
++ reason = "STATUS_BREAKPOINT";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_SINGLE_STEP:
++ reason = "STATUS_SINGLE_STEP";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_BUFFER_OVERFLOW:
++ reason = "STATUS_BUFFER_OVERFLOW";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_NO_MORE_FILES:
++ reason = "STATUS_NO_MORE_FILES";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_WAKE_SYSTEM_DEBUGGER:
++ reason = "STATUS_WAKE_SYSTEM_DEBUGGER";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_HANDLES_CLOSED:
++ reason = "STATUS_HANDLES_CLOSED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_NO_INHERITANCE:
++ reason = "STATUS_NO_INHERITANCE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_GUID_SUBSTITUTION_MADE:
++ reason = "STATUS_GUID_SUBSTITUTION_MADE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_PARTIAL_COPY:
++ reason = "STATUS_PARTIAL_COPY";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_DEVICE_PAPER_EMPTY:
++ reason = "STATUS_DEVICE_PAPER_EMPTY";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_DEVICE_POWERED_OFF:
++ reason = "STATUS_DEVICE_POWERED_OFF";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_DEVICE_OFF_LINE:
++ reason = "STATUS_DEVICE_OFF_LINE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_DEVICE_BUSY:
++ reason = "STATUS_DEVICE_BUSY";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_NO_MORE_EAS:
++ reason = "STATUS_NO_MORE_EAS";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_INVALID_EA_NAME:
++ reason = "STATUS_INVALID_EA_NAME";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_EA_LIST_INCONSISTENT:
++ reason = "STATUS_EA_LIST_INCONSISTENT";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_INVALID_EA_FLAG:
++ reason = "STATUS_INVALID_EA_FLAG";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_VERIFY_REQUIRED:
++ reason = "STATUS_VERIFY_REQUIRED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_EXTRANEOUS_INFORMATION:
++ reason = "STATUS_EXTRANEOUS_INFORMATION";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_RXACT_COMMIT_NECESSARY:
++ reason = "STATUS_RXACT_COMMIT_NECESSARY";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_NO_MORE_ENTRIES:
++ reason = "STATUS_NO_MORE_ENTRIES";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_FILEMARK_DETECTED:
++ reason = "STATUS_FILEMARK_DETECTED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_MEDIA_CHANGED:
++ reason = "STATUS_MEDIA_CHANGED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_BUS_RESET:
++ reason = "STATUS_BUS_RESET";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_END_OF_MEDIA:
++ reason = "STATUS_END_OF_MEDIA";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_BEGINNING_OF_MEDIA:
++ reason = "STATUS_BEGINNING_OF_MEDIA";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_MEDIA_CHECK:
++ reason = "STATUS_MEDIA_CHECK";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_SETMARK_DETECTED:
++ reason = "STATUS_SETMARK_DETECTED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_NO_DATA_DETECTED:
++ reason = "STATUS_NO_DATA_DETECTED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_REDIRECTOR_HAS_OPEN_HANDLES:
++ reason = "STATUS_REDIRECTOR_HAS_OPEN_HANDLES";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_SERVER_HAS_OPEN_HANDLES:
++ reason = "STATUS_SERVER_HAS_OPEN_HANDLES";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_ALREADY_DISCONNECTED:
++ reason = "STATUS_ALREADY_DISCONNECTED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_LONGJUMP:
++ reason = "STATUS_LONGJUMP";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_CLEANER_CARTRIDGE_INSTALLED:
++ reason = "STATUS_CLEANER_CARTRIDGE_INSTALLED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_PLUGPLAY_QUERY_VETOED:
++ reason = "STATUS_PLUGPLAY_QUERY_VETOED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_UNWIND_CONSOLIDATE:
++ reason = "STATUS_UNWIND_CONSOLIDATE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_REGISTRY_HIVE_RECOVERED:
++ reason = "STATUS_REGISTRY_HIVE_RECOVERED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_DLL_MIGHT_BE_INSECURE:
++ reason = "STATUS_DLL_MIGHT_BE_INSECURE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_DLL_MIGHT_BE_INCOMPATIBLE:
++ reason = "STATUS_DLL_MIGHT_BE_INCOMPATIBLE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_STOPPED_ON_SYMLINK:
++ reason = "STATUS_STOPPED_ON_SYMLINK";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_CANNOT_GRANT_REQUESTED_OPLOCK:
++ reason = "STATUS_CANNOT_GRANT_REQUESTED_OPLOCK";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_NO_ACE_CONDITION:
++ reason = "STATUS_NO_ACE_CONDITION";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_DEVICE_SUPPORT_IN_PROGRESS:
++ reason = "STATUS_DEVICE_SUPPORT_IN_PROGRESS";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_DEVICE_POWER_CYCLE_REQUIRED:
++ reason = "STATUS_DEVICE_POWER_CYCLE_REQUIRED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_NO_WORK_DONE:
++ reason = "STATUS_NO_WORK_DONE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_RETURN_ADDRESS_HIJACK_ATTEMPT:
++ reason = "STATUS_RETURN_ADDRESS_HIJACK_ATTEMPT";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_DEVICE_REQUIRES_CLEANING:
++ reason = "STATUS_DEVICE_REQUIRES_CLEANING";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_DEVICE_DOOR_OPEN:
++ reason = "STATUS_DEVICE_DOOR_OPEN";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_DATA_LOST_REPAIR:
++ reason = "STATUS_DATA_LOST_REPAIR";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_GPIO_INTERRUPT_ALREADY_UNMASKED:
++ reason = "STATUS_GPIO_INTERRUPT_ALREADY_UNMASKED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_PROPERTY_BLOB_CHECKSUM_MISMATCH:
++ reason = "STATUS_CLOUD_FILE_PROPERTY_BLOB_CHECKSUM_MISMATCH";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_PROPERTY_BLOB_TOO_LARGE:
++ reason = "STATUS_CLOUD_FILE_PROPERTY_BLOB_TOO_LARGE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_TOO_MANY_PROPERTY_BLOBS:
++ reason = "STATUS_CLOUD_FILE_TOO_MANY_PROPERTY_BLOBS";
++ break;
++ case MD_NTSTATUS_WIN_DBG_EXCEPTION_NOT_HANDLED:
++ reason = "DBG_EXCEPTION_NOT_HANDLED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_CLUSTER_NODE_ALREADY_UP:
++ reason = "STATUS_CLUSTER_NODE_ALREADY_UP";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_CLUSTER_NODE_ALREADY_DOWN:
++ reason = "STATUS_CLUSTER_NODE_ALREADY_DOWN";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_CLUSTER_NETWORK_ALREADY_ONLINE:
++ reason = "STATUS_CLUSTER_NETWORK_ALREADY_ONLINE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_CLUSTER_NETWORK_ALREADY_OFFLINE:
++ reason = "STATUS_CLUSTER_NETWORK_ALREADY_OFFLINE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_CLUSTER_NODE_ALREADY_MEMBER:
++ reason = "STATUS_CLUSTER_NODE_ALREADY_MEMBER";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_COULD_NOT_RESIZE_LOG:
++ reason = "STATUS_COULD_NOT_RESIZE_LOG";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_NO_TXF_METADATA:
++ reason = "STATUS_NO_TXF_METADATA";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_CANT_RECOVER_WITH_HANDLE_OPEN:
++ reason = "STATUS_CANT_RECOVER_WITH_HANDLE_OPEN";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_TXF_METADATA_ALREADY_PRESENT:
++ reason = "STATUS_TXF_METADATA_ALREADY_PRESENT";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_TRANSACTION_SCOPE_CALLBACKS_NOT_SET:
++ reason = "STATUS_TRANSACTION_SCOPE_CALLBACKS_NOT_SET";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_VIDEO_HUNG_DISPLAY_DRIVER_THREAD_RECOVERED:
++ reason = "STATUS_VIDEO_HUNG_DISPLAY_DRIVER_THREAD_RECOVERED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_FLT_BUFFER_TOO_SMALL:
++ reason = "STATUS_FLT_BUFFER_TOO_SMALL";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_FVE_PARTIAL_METADATA:
++ reason = "STATUS_FVE_PARTIAL_METADATA";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_FVE_TRANSIENT_STATE:
++ reason = "STATUS_FVE_TRANSIENT_STATE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_VID_REMOTE_NODE_PARENT_GPA_PAGES_USED:
++ reason = "STATUS_VID_REMOTE_NODE_PARENT_GPA_PAGES_USED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_VOLMGR_INCOMPLETE_REGENERATION:
++ reason = "STATUS_VOLMGR_INCOMPLETE_REGENERATION";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_VOLMGR_INCOMPLETE_DISK_MIGRATION:
++ reason = "STATUS_VOLMGR_INCOMPLETE_DISK_MIGRATION";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_BCD_NOT_ALL_ENTRIES_IMPORTED:
++ reason = "STATUS_BCD_NOT_ALL_ENTRIES_IMPORTED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_BCD_NOT_ALL_ENTRIES_SYNCHRONIZED:
++ reason = "STATUS_BCD_NOT_ALL_ENTRIES_SYNCHRONIZED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_QUERY_STORAGE_ERROR:
++ reason = "STATUS_QUERY_STORAGE_ERROR";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_GDI_HANDLE_LEAK:
++ reason = "STATUS_GDI_HANDLE_LEAK";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_SECUREBOOT_NOT_ENABLED:
++ reason = "STATUS_SECUREBOOT_NOT_ENABLED";
++ break;
+ case MD_NTSTATUS_WIN_STATUS_UNSUCCESSFUL:
+ reason = "STATUS_UNSUCCESSFUL";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_NOT_IMPLEMENTED:
+ reason = "STATUS_NOT_IMPLEMENTED";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_INVALID_INFO_CLASS:
+ reason = "STATUS_INVALID_INFO_CLASS";
+@@ -213,16 +943,19 @@ string NTStatusToString(uint32_t ntstatu
+ reason = "STATUS_OBJECT_NAME_INVALID";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_OBJECT_NAME_NOT_FOUND:
+ reason = "STATUS_OBJECT_NAME_NOT_FOUND";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_OBJECT_NAME_COLLISION:
+ reason = "STATUS_OBJECT_NAME_COLLISION";
+ break;
++ case MD_NTSTATUS_WIN_STATUS_PORT_DO_NOT_DISTURB:
++ reason = "STATUS_PORT_DO_NOT_DISTURB";
++ break;
+ case MD_NTSTATUS_WIN_STATUS_PORT_DISCONNECTED:
+ reason = "STATUS_PORT_DISCONNECTED";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_DEVICE_ALREADY_ATTACHED:
+ reason = "STATUS_DEVICE_ALREADY_ATTACHED";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_OBJECT_PATH_INVALID:
+ reason = "STATUS_OBJECT_PATH_INVALID";
+@@ -1317,16 +2050,40 @@ string NTStatusToString(uint32_t ntstatu
+ reason = "STATUS_REPAIR_NEEDED";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_QUOTA_NOT_ENABLED:
+ reason = "STATUS_QUOTA_NOT_ENABLED";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_NO_APPLICATION_PACKAGE:
+ reason = "STATUS_NO_APPLICATION_PACKAGE";
+ break;
++ case MD_NTSTATUS_WIN_STATUS_FILE_METADATA_OPTIMIZATION_IN_PROGRESS:
++ reason = "STATUS_FILE_METADATA_OPTIMIZATION_IN_PROGRESS";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_NOT_SAME_OBJECT:
++ reason = "STATUS_NOT_SAME_OBJECT";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_FATAL_MEMORY_EXHAUSTION:
++ reason = "STATUS_FATAL_MEMORY_EXHAUSTION";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_ERROR_PROCESS_NOT_IN_JOB:
++ reason = "STATUS_ERROR_PROCESS_NOT_IN_JOB";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_CPU_SET_INVALID:
++ reason = "STATUS_CPU_SET_INVALID";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_IO_DEVICE_INVALID_DATA:
++ reason = "STATUS_IO_DEVICE_INVALID_DATA";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_IO_UNALIGNED_WRITE:
++ reason = "STATUS_IO_UNALIGNED_WRITE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_CONTROL_STACK_VIOLATION:
++ reason = "STATUS_CONTROL_STACK_VIOLATION";
++ break;
+ case MD_NTSTATUS_WIN_STATUS_NETWORK_OPEN_RESTRICTION:
+ reason = "STATUS_NETWORK_OPEN_RESTRICTION";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_NO_USER_SESSION_KEY:
+ reason = "STATUS_NO_USER_SESSION_KEY";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_USER_SESSION_DELETED:
+ reason = "STATUS_USER_SESSION_DELETED";
+@@ -1662,16 +2419,19 @@ string NTStatusToString(uint32_t ntstatu
+ reason = "STATUS_IO_REPARSE_TAG_NOT_HANDLED";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_PWD_TOO_LONG:
+ reason = "STATUS_PWD_TOO_LONG";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_STOWED_EXCEPTION:
+ reason = "STATUS_STOWED_EXCEPTION";
+ break;
++ case MD_NTSTATUS_WIN_STATUS_CONTEXT_STOWED_EXCEPTION:
++ reason = "STATUS_CONTEXT_STOWED_EXCEPTION";
++ break;
+ case MD_NTSTATUS_WIN_STATUS_REPARSE_POINT_NOT_RESOLVED:
+ reason = "STATUS_REPARSE_POINT_NOT_RESOLVED";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_DIRECTORY_IS_A_REPARSE_POINT:
+ reason = "STATUS_DIRECTORY_IS_A_REPARSE_POINT";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_RANGE_LIST_CONFLICT:
+ reason = "STATUS_RANGE_LIST_CONFLICT";
+@@ -2058,16 +2818,19 @@ string NTStatusToString(uint32_t ntstatu
+ reason = "STATUS_CSS_REGION_MISMATCH";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_CSS_RESETS_EXHAUSTED:
+ reason = "STATUS_CSS_RESETS_EXHAUSTED";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_PASSWORD_CHANGE_REQUIRED:
+ reason = "STATUS_PASSWORD_CHANGE_REQUIRED";
+ break;
++ case MD_NTSTATUS_WIN_STATUS_LOST_MODE_LOGON_RESTRICTION:
++ reason = "STATUS_LOST_MODE_LOGON_RESTRICTION";
++ break;
+ case MD_NTSTATUS_WIN_STATUS_PKINIT_FAILURE:
+ reason = "STATUS_PKINIT_FAILURE";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_SMARTCARD_SUBSYSTEM_FAILURE:
+ reason = "STATUS_SMARTCARD_SUBSYSTEM_FAILURE";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_NO_KERB_KEY:
+ reason = "STATUS_NO_KERB_KEY";
+@@ -2454,16 +3217,19 @@ string NTStatusToString(uint32_t ntstatu
+ reason = "STATUS_FT_DI_SCAN_REQUIRED";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_OBJECT_NOT_EXTERNALLY_BACKED:
+ reason = "STATUS_OBJECT_NOT_EXTERNALLY_BACKED";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_EXTERNAL_BACKING_PROVIDER_UNKNOWN:
+ reason = "STATUS_EXTERNAL_BACKING_PROVIDER_UNKNOWN";
+ break;
++ case MD_NTSTATUS_WIN_STATUS_COMPRESSION_NOT_BENEFICIAL:
++ reason = "STATUS_COMPRESSION_NOT_BENEFICIAL";
++ break;
+ case MD_NTSTATUS_WIN_STATUS_DATA_CHECKSUM_ERROR:
+ reason = "STATUS_DATA_CHECKSUM_ERROR";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_INTERMIXED_KERNEL_EA_OPERATION:
+ reason = "STATUS_INTERMIXED_KERNEL_EA_OPERATION";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_TRIM_READ_ZERO_NOT_SUPPORTED:
+ reason = "STATUS_TRIM_READ_ZERO_NOT_SUPPORTED";
+@@ -2514,16 +3280,181 @@ string NTStatusToString(uint32_t ntstatu
+ reason = "STATUS_APISET_NOT_HOSTED";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_APISET_NOT_PRESENT:
+ reason = "STATUS_APISET_NOT_PRESENT";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_DEVICE_HARDWARE_ERROR:
+ reason = "STATUS_DEVICE_HARDWARE_ERROR";
+ break;
++ case MD_NTSTATUS_WIN_STATUS_FIRMWARE_SLOT_INVALID:
++ reason = "STATUS_FIRMWARE_SLOT_INVALID";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_FIRMWARE_IMAGE_INVALID:
++ reason = "STATUS_FIRMWARE_IMAGE_INVALID";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_STORAGE_TOPOLOGY_ID_MISMATCH:
++ reason = "STATUS_STORAGE_TOPOLOGY_ID_MISMATCH";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_WIM_NOT_BOOTABLE:
++ reason = "STATUS_WIM_NOT_BOOTABLE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_BLOCKED_BY_PARENTAL_CONTROLS:
++ reason = "STATUS_BLOCKED_BY_PARENTAL_CONTROLS";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_NEEDS_REGISTRATION:
++ reason = "STATUS_NEEDS_REGISTRATION";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_QUOTA_ACTIVITY:
++ reason = "STATUS_QUOTA_ACTIVITY";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_CALLBACK_INVOKE_INLINE:
++ reason = "STATUS_CALLBACK_INVOKE_INLINE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_BLOCK_TOO_MANY_REFERENCES:
++ reason = "STATUS_BLOCK_TOO_MANY_REFERENCES";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_MARKED_TO_DISALLOW_WRITES:
++ reason = "STATUS_MARKED_TO_DISALLOW_WRITES";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_NETWORK_ACCESS_DENIED_EDP:
++ reason = "STATUS_NETWORK_ACCESS_DENIED_EDP";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_ENCLAVE_FAILURE:
++ reason = "STATUS_ENCLAVE_FAILURE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_PNP_NO_COMPAT_DRIVERS:
++ reason = "STATUS_PNP_NO_COMPAT_DRIVERS";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_PNP_DRIVER_PACKAGE_NOT_FOUND:
++ reason = "STATUS_PNP_DRIVER_PACKAGE_NOT_FOUND";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_PNP_DRIVER_CONFIGURATION_NOT_FOUND:
++ reason = "STATUS_PNP_DRIVER_CONFIGURATION_NOT_FOUND";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_PNP_DRIVER_CONFIGURATION_INCOMPLETE:
++ reason = "STATUS_PNP_DRIVER_CONFIGURATION_INCOMPLETE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_PNP_FUNCTION_DRIVER_REQUIRED:
++ reason = "STATUS_PNP_FUNCTION_DRIVER_REQUIRED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_PNP_DEVICE_CONFIGURATION_PENDING:
++ reason = "STATUS_PNP_DEVICE_CONFIGURATION_PENDING";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_DEVICE_HINT_NAME_BUFFER_TOO_SMALL:
++ reason = "STATUS_DEVICE_HINT_NAME_BUFFER_TOO_SMALL";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_PACKAGE_NOT_AVAILABLE:
++ reason = "STATUS_PACKAGE_NOT_AVAILABLE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_DEVICE_IN_MAINTENANCE:
++ reason = "STATUS_DEVICE_IN_MAINTENANCE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_NOT_SUPPORTED_ON_DAX:
++ reason = "STATUS_NOT_SUPPORTED_ON_DAX";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_FREE_SPACE_TOO_FRAGMENTED:
++ reason = "STATUS_FREE_SPACE_TOO_FRAGMENTED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_DAX_MAPPING_EXISTS:
++ reason = "STATUS_DAX_MAPPING_EXISTS";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_CHILD_PROCESS_BLOCKED:
++ reason = "STATUS_CHILD_PROCESS_BLOCKED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_STORAGE_LOST_DATA_PERSISTENCE:
++ reason = "STATUS_STORAGE_LOST_DATA_PERSISTENCE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_VRF_CFG_AND_IO_ENABLED:
++ reason = "STATUS_VRF_CFG_AND_IO_ENABLED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_PARTITION_TERMINATING:
++ reason = "STATUS_PARTITION_TERMINATING";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_EXTERNAL_SYSKEY_NOT_SUPPORTED:
++ reason = "STATUS_EXTERNAL_SYSKEY_NOT_SUPPORTED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_ENCLAVE_VIOLATION:
++ reason = "STATUS_ENCLAVE_VIOLATION";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_FILE_PROTECTED_UNDER_DPL:
++ reason = "STATUS_FILE_PROTECTED_UNDER_DPL";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_VOLUME_NOT_CLUSTER_ALIGNED:
++ reason = "STATUS_VOLUME_NOT_CLUSTER_ALIGNED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_NO_PHYSICALLY_ALIGNED_FREE_SPACE_FOUND:
++ reason = "STATUS_NO_PHYSICALLY_ALIGNED_FREE_SPACE_FOUND";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_APPX_FILE_NOT_ENCRYPTED:
++ reason = "STATUS_APPX_FILE_NOT_ENCRYPTED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_RWRAW_ENCRYPTED_FILE_NOT_ENCRYPTED:
++ reason = "STATUS_RWRAW_ENCRYPTED_FILE_NOT_ENCRYPTED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_RWRAW_ENCRYPTED_INVALID_EDATAINFO_FILEOFFSET:
++ reason = "STATUS_RWRAW_ENCRYPTED_INVALID_EDATAINFO_FILEOFFSET";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_RWRAW_ENCRYPTED_INVALID_EDATAINFO_FILERANGE:
++ reason = "STATUS_RWRAW_ENCRYPTED_INVALID_EDATAINFO_FILERANGE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_RWRAW_ENCRYPTED_INVALID_EDATAINFO_PARAMETER:
++ reason = "STATUS_RWRAW_ENCRYPTED_INVALID_EDATAINFO_PARAMETER";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_FT_READ_FAILURE:
++ reason = "STATUS_FT_READ_FAILURE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_PATCH_CONFLICT:
++ reason = "STATUS_PATCH_CONFLICT";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_STORAGE_RESERVE_ID_INVALID:
++ reason = "STATUS_STORAGE_RESERVE_ID_INVALID";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_STORAGE_RESERVE_DOES_NOT_EXIST:
++ reason = "STATUS_STORAGE_RESERVE_DOES_NOT_EXIST";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_STORAGE_RESERVE_ALREADY_EXISTS:
++ reason = "STATUS_STORAGE_RESERVE_ALREADY_EXISTS";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_STORAGE_RESERVE_NOT_EMPTY:
++ reason = "STATUS_STORAGE_RESERVE_NOT_EMPTY";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_NOT_A_DAX_VOLUME:
++ reason = "STATUS_NOT_A_DAX_VOLUME";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_NOT_DAX_MAPPABLE:
++ reason = "STATUS_NOT_DAX_MAPPABLE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_CASE_DIFFERING_NAMES_IN_DIR:
++ reason = "STATUS_CASE_DIFFERING_NAMES_IN_DIR";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_FILE_NOT_SUPPORTED:
++ reason = "STATUS_FILE_NOT_SUPPORTED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_NOT_SUPPORTED_WITH_BTT:
++ reason = "STATUS_NOT_SUPPORTED_WITH_BTT";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_ENCRYPTION_DISABLED:
++ reason = "STATUS_ENCRYPTION_DISABLED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_ENCRYPTING_METADATA_DISALLOWED:
++ reason = "STATUS_ENCRYPTING_METADATA_DISALLOWED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_CANT_CLEAR_ENCRYPTION_FLAG:
++ reason = "STATUS_CANT_CLEAR_ENCRYPTION_FLAG";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_UNSATISFIED_DEPENDENCIES:
++ reason = "STATUS_UNSATISFIED_DEPENDENCIES";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_CASE_SENSITIVE_PATH:
++ reason = "STATUS_CASE_SENSITIVE_PATH";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_HAS_SYSTEM_CRITICAL_FILES:
++ reason = "STATUS_HAS_SYSTEM_CRITICAL_FILES";
++ break;
+ case MD_NTSTATUS_WIN_STATUS_INVALID_TASK_NAME:
+ reason = "STATUS_INVALID_TASK_NAME";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_INVALID_TASK_INDEX:
+ reason = "STATUS_INVALID_TASK_INDEX";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_THREAD_ALREADY_IN_TASK:
+ reason = "STATUS_THREAD_ALREADY_IN_TASK";
+@@ -2535,25 +3466,85 @@ string NTStatusToString(uint32_t ntstatu
+ reason = "STATUS_UNDEFINED_SCOPE";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_INVALID_CAP:
+ reason = "STATUS_INVALID_CAP";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_NOT_GUI_PROCESS:
+ reason = "STATUS_NOT_GUI_PROCESS";
+ break;
++ case MD_NTSTATUS_WIN_STATUS_DEVICE_HUNG:
++ reason = "STATUS_DEVICE_HUNG";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_CONTAINER_ASSIGNED:
++ reason = "STATUS_CONTAINER_ASSIGNED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_JOB_NO_CONTAINER:
++ reason = "STATUS_JOB_NO_CONTAINER";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_DEVICE_UNRESPONSIVE:
++ reason = "STATUS_DEVICE_UNRESPONSIVE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_REPARSE_POINT_ENCOUNTERED:
++ reason = "STATUS_REPARSE_POINT_ENCOUNTERED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_ATTRIBUTE_NOT_PRESENT:
++ reason = "STATUS_ATTRIBUTE_NOT_PRESENT";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_NOT_A_TIERED_VOLUME:
++ reason = "STATUS_NOT_A_TIERED_VOLUME";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_ALREADY_HAS_STREAM_ID:
++ reason = "STATUS_ALREADY_HAS_STREAM_ID";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_JOB_NOT_EMPTY:
++ reason = "STATUS_JOB_NOT_EMPTY";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_ALREADY_INITIALIZED:
++ reason = "STATUS_ALREADY_INITIALIZED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_ENCLAVE_NOT_TERMINATED:
++ reason = "STATUS_ENCLAVE_NOT_TERMINATED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_ENCLAVE_IS_TERMINATING:
++ reason = "STATUS_ENCLAVE_IS_TERMINATING";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_SMB1_NOT_AVAILABLE:
++ reason = "STATUS_SMB1_NOT_AVAILABLE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_SMR_GARBAGE_COLLECTION_REQUIRED:
++ reason = "STATUS_SMR_GARBAGE_COLLECTION_REQUIRED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_INTERRUPTED:
++ reason = "STATUS_INTERRUPTED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_THREAD_NOT_RUNNING:
++ reason = "STATUS_THREAD_NOT_RUNNING";
++ break;
+ case MD_NTSTATUS_WIN_STATUS_FAIL_FAST_EXCEPTION:
+ reason = "STATUS_FAIL_FAST_EXCEPTION";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_IMAGE_CERT_REVOKED:
+ reason = "STATUS_IMAGE_CERT_REVOKED";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_DYNAMIC_CODE_BLOCKED:
+ reason = "STATUS_DYNAMIC_CODE_BLOCKED";
+ break;
++ case MD_NTSTATUS_WIN_STATUS_IMAGE_CERT_EXPIRED:
++ reason = "STATUS_IMAGE_CERT_EXPIRED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_STRICT_CFG_VIOLATION:
++ reason = "STATUS_STRICT_CFG_VIOLATION";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_SET_CONTEXT_DENIED:
++ reason = "STATUS_SET_CONTEXT_DENIED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_CROSS_PARTITION_VIOLATION:
++ reason = "STATUS_CROSS_PARTITION_VIOLATION";
++ break;
+ case MD_NTSTATUS_WIN_STATUS_PORT_CLOSED:
+ reason = "STATUS_PORT_CLOSED";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_MESSAGE_LOST:
+ reason = "STATUS_MESSAGE_LOST";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_INVALID_MESSAGE:
+ reason = "STATUS_INVALID_MESSAGE";
+@@ -2646,16 +3637,31 @@ string NTStatusToString(uint32_t ntstatu
+ reason = "STATUS_CALLBACK_RETURNED_LANG";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_CALLBACK_RETURNED_PRI_BACK:
+ reason = "STATUS_CALLBACK_RETURNED_PRI_BACK";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_CALLBACK_RETURNED_THREAD_AFFINITY:
+ reason = "STATUS_CALLBACK_RETURNED_THREAD_AFFINITY";
+ break;
++ case MD_NTSTATUS_WIN_STATUS_LPC_HANDLE_COUNT_EXCEEDED:
++ reason = "STATUS_LPC_HANDLE_COUNT_EXCEEDED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_EXECUTABLE_MEMORY_WRITE:
++ reason = "STATUS_EXECUTABLE_MEMORY_WRITE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_KERNEL_EXECUTABLE_MEMORY_WRITE:
++ reason = "STATUS_KERNEL_EXECUTABLE_MEMORY_WRITE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_ATTACHED_EXECUTABLE_MEMORY_WRITE:
++ reason = "STATUS_ATTACHED_EXECUTABLE_MEMORY_WRITE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_TRIGGERED_EXECUTABLE_MEMORY_WRITE:
++ reason = "STATUS_TRIGGERED_EXECUTABLE_MEMORY_WRITE";
++ break;
+ case MD_NTSTATUS_WIN_STATUS_DISK_REPAIR_DISABLED:
+ reason = "STATUS_DISK_REPAIR_DISABLED";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_DS_DOMAIN_RENAME_IN_PROGRESS:
+ reason = "STATUS_DS_DOMAIN_RENAME_IN_PROGRESS";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_DISK_QUOTA_EXCEEDED:
+ reason = "STATUS_DISK_QUOTA_EXCEEDED";
+@@ -2754,16 +3760,25 @@ string NTStatusToString(uint32_t ntstatu
+ reason = "STATUS_INVALID_STATE_TRANSITION";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_INVALID_KERNEL_INFO_VERSION:
+ reason = "STATUS_INVALID_KERNEL_INFO_VERSION";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_INVALID_PEP_INFO_VERSION:
+ reason = "STATUS_INVALID_PEP_INFO_VERSION";
+ break;
++ case MD_NTSTATUS_WIN_STATUS_HANDLE_REVOKED:
++ reason = "STATUS_HANDLE_REVOKED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_EOF_ON_GHOSTED_RANGE:
++ reason = "STATUS_EOF_ON_GHOSTED_RANGE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_CC_NEEDS_CALLBACK_SECTION_DRAIN:
++ reason = "STATUS_CC_NEEDS_CALLBACK_SECTION_DRAIN";
++ break;
+ case MD_NTSTATUS_WIN_STATUS_IPSEC_QUEUE_OVERFLOW:
+ reason = "STATUS_IPSEC_QUEUE_OVERFLOW";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_ND_QUEUE_OVERFLOW:
+ reason = "STATUS_ND_QUEUE_OVERFLOW";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_HOPLIMIT_EXCEEDED:
+ reason = "STATUS_HOPLIMIT_EXCEEDED";
+@@ -2847,16 +3862,22 @@ string NTStatusToString(uint32_t ntstatu
+ reason = "STATUS_NOT_APPCONTAINER";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_NOT_SUPPORTED_IN_APPCONTAINER:
+ reason = "STATUS_NOT_SUPPORTED_IN_APPCONTAINER";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_INVALID_PACKAGE_SID_LENGTH:
+ reason = "STATUS_INVALID_PACKAGE_SID_LENGTH";
+ break;
++ case MD_NTSTATUS_WIN_STATUS_LPAC_ACCESS_DENIED:
++ reason = "STATUS_LPAC_ACCESS_DENIED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_ADMINLESS_ACCESS_DENIED:
++ reason = "STATUS_ADMINLESS_ACCESS_DENIED";
++ break;
+ case MD_NTSTATUS_WIN_STATUS_APP_DATA_NOT_FOUND:
+ reason = "STATUS_APP_DATA_NOT_FOUND";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_APP_DATA_EXPIRED:
+ reason = "STATUS_APP_DATA_EXPIRED";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_APP_DATA_CORRUPT:
+ reason = "STATUS_APP_DATA_CORRUPT";
+@@ -2874,16 +3895,151 @@ string NTStatusToString(uint32_t ntstatu
+ reason = "STATUS_OFFLOAD_WRITE_FLT_NOT_SUPPORTED";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_OFFLOAD_READ_FILE_NOT_SUPPORTED:
+ reason = "STATUS_OFFLOAD_READ_FILE_NOT_SUPPORTED";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_OFFLOAD_WRITE_FILE_NOT_SUPPORTED:
+ reason = "STATUS_OFFLOAD_WRITE_FILE_NOT_SUPPORTED";
+ break;
++ case MD_NTSTATUS_WIN_STATUS_WOF_WIM_HEADER_CORRUPT:
++ reason = "STATUS_WOF_WIM_HEADER_CORRUPT";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_WOF_WIM_RESOURCE_TABLE_CORRUPT:
++ reason = "STATUS_WOF_WIM_RESOURCE_TABLE_CORRUPT";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_WOF_FILE_RESOURCE_TABLE_CORRUPT:
++ reason = "STATUS_WOF_FILE_RESOURCE_TABLE_CORRUPT";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_CIMFS_IMAGE_CORRUPT:
++ reason = "STATUS_CIMFS_IMAGE_CORRUPT";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_FILE_SYSTEM_VIRTUALIZATION_UNAVAILABLE:
++ reason = "STATUS_FILE_SYSTEM_VIRTUALIZATION_UNAVAILABLE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_FILE_SYSTEM_VIRTUALIZATION_METADATA_CORRUPT:
++ reason = "STATUS_FILE_SYSTEM_VIRTUALIZATION_METADATA_CORRUPT";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_FILE_SYSTEM_VIRTUALIZATION_BUSY:
++ reason = "STATUS_FILE_SYSTEM_VIRTUALIZATION_BUSY";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_FILE_SYSTEM_VIRTUALIZATION_PROVIDER_UNKNOWN:
++ reason = "STATUS_FILE_SYSTEM_VIRTUALIZATION_PROVIDER_UNKNOWN";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_FILE_SYSTEM_VIRTUALIZATION_INVALID_OPERATION:
++ reason = "STATUS_FILE_SYSTEM_VIRTUALIZATION_INVALID_OPERATION";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_SYNC_ROOT_METADATA_CORRUPT:
++ reason = "STATUS_CLOUD_FILE_SYNC_ROOT_METADATA_CORRUPT";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_PROVIDER_NOT_RUNNING:
++ reason = "STATUS_CLOUD_FILE_PROVIDER_NOT_RUNNING";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_METADATA_CORRUPT:
++ reason = "STATUS_CLOUD_FILE_METADATA_CORRUPT";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_METADATA_TOO_LARGE:
++ reason = "STATUS_CLOUD_FILE_METADATA_TOO_LARGE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_PROPERTY_VERSION_NOT_SUPPORTED:
++ reason = "STATUS_CLOUD_FILE_PROPERTY_VERSION_NOT_SUPPORTED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_NOT_A_CLOUD_FILE:
++ reason = "STATUS_NOT_A_CLOUD_FILE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_NOT_IN_SYNC:
++ reason = "STATUS_CLOUD_FILE_NOT_IN_SYNC";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_ALREADY_CONNECTED:
++ reason = "STATUS_CLOUD_FILE_ALREADY_CONNECTED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_NOT_SUPPORTED:
++ reason = "STATUS_CLOUD_FILE_NOT_SUPPORTED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_INVALID_REQUEST:
++ reason = "STATUS_CLOUD_FILE_INVALID_REQUEST";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_READ_ONLY_VOLUME:
++ reason = "STATUS_CLOUD_FILE_READ_ONLY_VOLUME";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_CONNECTED_PROVIDER_ONLY:
++ reason = "STATUS_CLOUD_FILE_CONNECTED_PROVIDER_ONLY";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_VALIDATION_FAILED:
++ reason = "STATUS_CLOUD_FILE_VALIDATION_FAILED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_AUTHENTICATION_FAILED:
++ reason = "STATUS_CLOUD_FILE_AUTHENTICATION_FAILED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_INSUFFICIENT_RESOURCES:
++ reason = "STATUS_CLOUD_FILE_INSUFFICIENT_RESOURCES";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_NETWORK_UNAVAILABLE:
++ reason = "STATUS_CLOUD_FILE_NETWORK_UNAVAILABLE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_UNSUCCESSFUL:
++ reason = "STATUS_CLOUD_FILE_UNSUCCESSFUL";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_NOT_UNDER_SYNC_ROOT:
++ reason = "STATUS_CLOUD_FILE_NOT_UNDER_SYNC_ROOT";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_IN_USE:
++ reason = "STATUS_CLOUD_FILE_IN_USE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_PINNED:
++ reason = "STATUS_CLOUD_FILE_PINNED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_REQUEST_ABORTED:
++ reason = "STATUS_CLOUD_FILE_REQUEST_ABORTED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_PROPERTY_CORRUPT:
++ reason = "STATUS_CLOUD_FILE_PROPERTY_CORRUPT";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_ACCESS_DENIED:
++ reason = "STATUS_CLOUD_FILE_ACCESS_DENIED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_INCOMPATIBLE_HARDLINKS:
++ reason = "STATUS_CLOUD_FILE_INCOMPATIBLE_HARDLINKS";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_PROPERTY_LOCK_CONFLICT:
++ reason = "STATUS_CLOUD_FILE_PROPERTY_LOCK_CONFLICT";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_REQUEST_CANCELED:
++ reason = "STATUS_CLOUD_FILE_REQUEST_CANCELED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_PROVIDER_TERMINATED:
++ reason = "STATUS_CLOUD_FILE_PROVIDER_TERMINATED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_NOT_A_CLOUD_SYNC_ROOT:
++ reason = "STATUS_NOT_A_CLOUD_SYNC_ROOT";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_REQUEST_TIMEOUT:
++ reason = "STATUS_CLOUD_FILE_REQUEST_TIMEOUT";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_DEHYDRATION_DISALLOWED:
++ reason = "STATUS_CLOUD_FILE_DEHYDRATION_DISALLOWED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_FILE_SNAP_IN_PROGRESS:
++ reason = "STATUS_FILE_SNAP_IN_PROGRESS";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_FILE_SNAP_USER_SECTION_NOT_SUPPORTED:
++ reason = "STATUS_FILE_SNAP_USER_SECTION_NOT_SUPPORTED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_FILE_SNAP_MODIFY_NOT_SUPPORTED:
++ reason = "STATUS_FILE_SNAP_MODIFY_NOT_SUPPORTED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_FILE_SNAP_IO_NOT_COORDINATED:
++ reason = "STATUS_FILE_SNAP_IO_NOT_COORDINATED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_FILE_SNAP_UNEXPECTED_ERROR:
++ reason = "STATUS_FILE_SNAP_UNEXPECTED_ERROR";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_FILE_SNAP_INVALID_PARAMETER:
++ reason = "STATUS_FILE_SNAP_INVALID_PARAMETER";
++ break;
+ case MD_NTSTATUS_WIN_DBG_NO_STATE_CHANGE:
+ reason = "DBG_NO_STATE_CHANGE";
+ break;
+ case MD_NTSTATUS_WIN_DBG_APP_NOT_IDLE:
+ reason = "DBG_APP_NOT_IDLE";
+ break;
+ case MD_NTSTATUS_WIN_RPC_NT_INVALID_STRING_BINDING:
+ reason = "RPC_NT_INVALID_STRING_BINDING";
+@@ -3459,16 +4615,31 @@ string NTStatusToString(uint32_t ntstatu
+ reason = "STATUS_CLUSTER_CSV_VOLUME_DRAINING";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_CLUSTER_CSV_SNAPSHOT_CREATION_IN_PROGRESS:
+ reason = "STATUS_CLUSTER_CSV_SNAPSHOT_CREATION_IN_PROGRESS";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_CLUSTER_CSV_VOLUME_DRAINING_SUCCEEDED_DOWNLEVEL:
+ reason = "STATUS_CLUSTER_CSV_VOLUME_DRAINING_SUCCEEDED_DOWNLEVEL";
+ break;
++ case MD_NTSTATUS_WIN_STATUS_CLUSTER_CSV_NO_SNAPSHOTS:
++ reason = "STATUS_CLUSTER_CSV_NO_SNAPSHOTS";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_CSV_IO_PAUSE_TIMEOUT:
++ reason = "STATUS_CSV_IO_PAUSE_TIMEOUT";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_CLUSTER_CSV_INVALID_HANDLE:
++ reason = "STATUS_CLUSTER_CSV_INVALID_HANDLE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_CLUSTER_CSV_SUPPORTED_ONLY_ON_COORDINATOR:
++ reason = "STATUS_CLUSTER_CSV_SUPPORTED_ONLY_ON_COORDINATOR";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_CLUSTER_CAM_TICKET_REPLAY_DETECTED:
++ reason = "STATUS_CLUSTER_CAM_TICKET_REPLAY_DETECTED";
++ break;
+ case MD_NTSTATUS_WIN_STATUS_ACPI_INVALID_OPCODE:
+ reason = "STATUS_ACPI_INVALID_OPCODE";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_ACPI_STACK_OVERFLOW:
+ reason = "STATUS_ACPI_STACK_OVERFLOW";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_ACPI_ASSERT_FAILED:
+ reason = "STATUS_ACPI_ASSERT_FAILED";
+@@ -4182,16 +5353,31 @@ string NTStatusToString(uint32_t ntstatu
+ reason = "STATUS_GRAPHICS_PRESENT_UNOCCLUDED";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_GRAPHICS_WINDOWDC_NOT_AVAILABLE:
+ reason = "STATUS_GRAPHICS_WINDOWDC_NOT_AVAILABLE";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_GRAPHICS_WINDOWLESS_PRESENT_DISABLED:
+ reason = "STATUS_GRAPHICS_WINDOWLESS_PRESENT_DISABLED";
+ break;
++ case MD_NTSTATUS_WIN_STATUS_GRAPHICS_PRESENT_INVALID_WINDOW:
++ reason = "STATUS_GRAPHICS_PRESENT_INVALID_WINDOW";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_GRAPHICS_PRESENT_BUFFER_NOT_BOUND:
++ reason = "STATUS_GRAPHICS_PRESENT_BUFFER_NOT_BOUND";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_GRAPHICS_VAIL_STATE_CHANGED:
++ reason = "STATUS_GRAPHICS_VAIL_STATE_CHANGED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INDIRECT_DISPLAY_ABANDON_SWAPCHAIN:
++ reason = "STATUS_GRAPHICS_INDIRECT_DISPLAY_ABANDON_SWAPCHAIN";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INDIRECT_DISPLAY_DEVICE_STOPPED:
++ reason = "STATUS_GRAPHICS_INDIRECT_DISPLAY_DEVICE_STOPPED";
++ break;
+ case MD_NTSTATUS_WIN_STATUS_GRAPHICS_NO_VIDEO_MEMORY:
+ reason = "STATUS_GRAPHICS_NO_VIDEO_MEMORY";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_GRAPHICS_CANT_LOCK_MEMORY:
+ reason = "STATUS_GRAPHICS_CANT_LOCK_MEMORY";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_GRAPHICS_ALLOCATION_BUSY:
+ reason = "STATUS_GRAPHICS_ALLOCATION_BUSY";
+@@ -4845,16 +6031,19 @@ string NTStatusToString(uint32_t ntstatu
+ reason = "STATUS_FVE_NOT_DE_VOLUME";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_FVE_PROTECTION_DISABLED:
+ reason = "STATUS_FVE_PROTECTION_DISABLED";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_FVE_PROTECTION_CANNOT_BE_DISABLED:
+ reason = "STATUS_FVE_PROTECTION_CANNOT_BE_DISABLED";
+ break;
++ case MD_NTSTATUS_WIN_STATUS_FVE_OSV_KSR_NOT_ALLOWED:
++ reason = "STATUS_FVE_OSV_KSR_NOT_ALLOWED";
++ break;
+ case MD_NTSTATUS_WIN_STATUS_FWP_CALLOUT_NOT_FOUND:
+ reason = "STATUS_FWP_CALLOUT_NOT_FOUND";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_FWP_CONDITION_NOT_FOUND:
+ reason = "STATUS_FWP_CONDITION_NOT_FOUND";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_FWP_FILTER_NOT_FOUND:
+ reason = "STATUS_FWP_FILTER_NOT_FOUND";
+@@ -5166,16 +6355,19 @@ string NTStatusToString(uint32_t ntstatu
+ reason = "STATUS_NDIS_INVALID_PORT_STATE";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_NDIS_LOW_POWER_STATE:
+ reason = "STATUS_NDIS_LOW_POWER_STATE";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_NDIS_REINIT_REQUIRED:
+ reason = "STATUS_NDIS_REINIT_REQUIRED";
+ break;
++ case MD_NTSTATUS_WIN_STATUS_NDIS_NO_QUEUES:
++ reason = "STATUS_NDIS_NO_QUEUES";
++ break;
+ case MD_NTSTATUS_WIN_STATUS_NDIS_NOT_SUPPORTED:
+ reason = "STATUS_NDIS_NOT_SUPPORTED";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_NDIS_OFFLOAD_POLICY:
+ reason = "STATUS_NDIS_OFFLOAD_POLICY";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_NDIS_OFFLOAD_CONNECTION_REJECTED:
+ reason = "STATUS_NDIS_OFFLOAD_CONNECTION_REJECTED";
+@@ -5193,16 +6385,34 @@ string NTStatusToString(uint32_t ntstatu
+ reason = "STATUS_NDIS_DOT11_POWER_STATE_INVALID";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_NDIS_PM_WOL_PATTERN_LIST_FULL:
+ reason = "STATUS_NDIS_PM_WOL_PATTERN_LIST_FULL";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_NDIS_PM_PROTOCOL_OFFLOAD_LIST_FULL:
+ reason = "STATUS_NDIS_PM_PROTOCOL_OFFLOAD_LIST_FULL";
+ break;
++ case MD_NTSTATUS_WIN_STATUS_NDIS_DOT11_AP_CHANNEL_CURRENTLY_NOT_AVAILABLE:
++ reason = "STATUS_NDIS_DOT11_AP_CHANNEL_CURRENTLY_NOT_AVAILABLE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_NDIS_DOT11_AP_BAND_CURRENTLY_NOT_AVAILABLE:
++ reason = "STATUS_NDIS_DOT11_AP_BAND_CURRENTLY_NOT_AVAILABLE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_NDIS_DOT11_AP_CHANNEL_NOT_ALLOWED:
++ reason = "STATUS_NDIS_DOT11_AP_CHANNEL_NOT_ALLOWED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_NDIS_DOT11_AP_BAND_NOT_ALLOWED:
++ reason = "STATUS_NDIS_DOT11_AP_BAND_NOT_ALLOWED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_QUIC_HANDSHAKE_FAILURE:
++ reason = "STATUS_QUIC_HANDSHAKE_FAILURE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_QUIC_VER_NEG_FAILURE:
++ reason = "STATUS_QUIC_VER_NEG_FAILURE";
++ break;
+ case MD_NTSTATUS_WIN_STATUS_TPM_ERROR_MASK:
+ reason = "STATUS_TPM_ERROR_MASK";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_TPM_AUTHFAIL:
+ reason = "STATUS_TPM_AUTHFAIL";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_TPM_BADINDEX:
+ reason = "STATUS_TPM_BADINDEX";
+@@ -5490,16 +6700,220 @@ string NTStatusToString(uint32_t ntstatu
+ reason = "STATUS_TPM_PERMANENTEK";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_TPM_BAD_SIGNATURE:
+ reason = "STATUS_TPM_BAD_SIGNATURE";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_TPM_NOCONTEXTSPACE:
+ reason = "STATUS_TPM_NOCONTEXTSPACE";
+ break;
++ case MD_NTSTATUS_WIN_STATUS_TPM_20_E_ASYMMETRIC:
++ reason = "STATUS_TPM_20_E_ASYMMETRIC";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_TPM_20_E_ATTRIBUTES:
++ reason = "STATUS_TPM_20_E_ATTRIBUTES";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_TPM_20_E_HASH:
++ reason = "STATUS_TPM_20_E_HASH";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_TPM_20_E_VALUE:
++ reason = "STATUS_TPM_20_E_VALUE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_TPM_20_E_HIERARCHY:
++ reason = "STATUS_TPM_20_E_HIERARCHY";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_TPM_20_E_KEY_SIZE:
++ reason = "STATUS_TPM_20_E_KEY_SIZE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_TPM_20_E_MGF:
++ reason = "STATUS_TPM_20_E_MGF";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_TPM_20_E_MODE:
++ reason = "STATUS_TPM_20_E_MODE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_TPM_20_E_TYPE:
++ reason = "STATUS_TPM_20_E_TYPE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_TPM_20_E_HANDLE:
++ reason = "STATUS_TPM_20_E_HANDLE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_TPM_20_E_KDF:
++ reason = "STATUS_TPM_20_E_KDF";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_TPM_20_E_RANGE:
++ reason = "STATUS_TPM_20_E_RANGE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_TPM_20_E_AUTH_FAIL:
++ reason = "STATUS_TPM_20_E_AUTH_FAIL";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_TPM_20_E_NONCE:
++ reason = "STATUS_TPM_20_E_NONCE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_TPM_20_E_PP:
++ reason = "STATUS_TPM_20_E_PP";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_TPM_20_E_SCHEME:
++ reason = "STATUS_TPM_20_E_SCHEME";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_TPM_20_E_SIZE:
++ reason = "STATUS_TPM_20_E_SIZE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_TPM_20_E_SYMMETRIC:
++ reason = "STATUS_TPM_20_E_SYMMETRIC";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_TPM_20_E_TAG:
++ reason = "STATUS_TPM_20_E_TAG";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_TPM_20_E_SELECTOR:
++ reason = "STATUS_TPM_20_E_SELECTOR";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_TPM_20_E_INSUFFICIENT:
++ reason = "STATUS_TPM_20_E_INSUFFICIENT";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_TPM_20_E_SIGNATURE:
++ reason = "STATUS_TPM_20_E_SIGNATURE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_TPM_20_E_KEY:
++ reason = "STATUS_TPM_20_E_KEY";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_TPM_20_E_POLICY_FAIL:
++ reason = "STATUS_TPM_20_E_POLICY_FAIL";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_TPM_20_E_INTEGRITY:
++ reason = "STATUS_TPM_20_E_INTEGRITY";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_TPM_20_E_TICKET:
++ reason = "STATUS_TPM_20_E_TICKET";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_TPM_20_E_RESERVED_BITS:
++ reason = "STATUS_TPM_20_E_RESERVED_BITS";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_TPM_20_E_BAD_AUTH:
++ reason = "STATUS_TPM_20_E_BAD_AUTH";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_TPM_20_E_EXPIRED:
++ reason = "STATUS_TPM_20_E_EXPIRED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_TPM_20_E_POLICY_CC:
++ reason = "STATUS_TPM_20_E_POLICY_CC";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_TPM_20_E_BINDING:
++ reason = "STATUS_TPM_20_E_BINDING";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_TPM_20_E_CURVE:
++ reason = "STATUS_TPM_20_E_CURVE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_TPM_20_E_ECC_POINT:
++ reason = "STATUS_TPM_20_E_ECC_POINT";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_TPM_20_E_INITIALIZE:
++ reason = "STATUS_TPM_20_E_INITIALIZE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_TPM_20_E_FAILURE:
++ reason = "STATUS_TPM_20_E_FAILURE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_TPM_20_E_SEQUENCE:
++ reason = "STATUS_TPM_20_E_SEQUENCE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_TPM_20_E_PRIVATE:
++ reason = "STATUS_TPM_20_E_PRIVATE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_TPM_20_E_HMAC:
++ reason = "STATUS_TPM_20_E_HMAC";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_TPM_20_E_DISABLED:
++ reason = "STATUS_TPM_20_E_DISABLED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_TPM_20_E_EXCLUSIVE:
++ reason = "STATUS_TPM_20_E_EXCLUSIVE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_TPM_20_E_ECC_CURVE:
++ reason = "STATUS_TPM_20_E_ECC_CURVE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_TPM_20_E_AUTH_TYPE:
++ reason = "STATUS_TPM_20_E_AUTH_TYPE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_TPM_20_E_AUTH_MISSING:
++ reason = "STATUS_TPM_20_E_AUTH_MISSING";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_TPM_20_E_POLICY:
++ reason = "STATUS_TPM_20_E_POLICY";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_TPM_20_E_PCR:
++ reason = "STATUS_TPM_20_E_PCR";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_TPM_20_E_PCR_CHANGED:
++ reason = "STATUS_TPM_20_E_PCR_CHANGED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_TPM_20_E_UPGRADE:
++ reason = "STATUS_TPM_20_E_UPGRADE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_TPM_20_E_TOO_MANY_CONTEXTS:
++ reason = "STATUS_TPM_20_E_TOO_MANY_CONTEXTS";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_TPM_20_E_AUTH_UNAVAILABLE:
++ reason = "STATUS_TPM_20_E_AUTH_UNAVAILABLE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_TPM_20_E_REBOOT:
++ reason = "STATUS_TPM_20_E_REBOOT";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_TPM_20_E_UNBALANCED:
++ reason = "STATUS_TPM_20_E_UNBALANCED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_TPM_20_E_COMMAND_SIZE:
++ reason = "STATUS_TPM_20_E_COMMAND_SIZE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_TPM_20_E_COMMAND_CODE:
++ reason = "STATUS_TPM_20_E_COMMAND_CODE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_TPM_20_E_AUTHSIZE:
++ reason = "STATUS_TPM_20_E_AUTHSIZE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_TPM_20_E_AUTH_CONTEXT:
++ reason = "STATUS_TPM_20_E_AUTH_CONTEXT";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_TPM_20_E_NV_RANGE:
++ reason = "STATUS_TPM_20_E_NV_RANGE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_TPM_20_E_NV_SIZE:
++ reason = "STATUS_TPM_20_E_NV_SIZE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_TPM_20_E_NV_LOCKED:
++ reason = "STATUS_TPM_20_E_NV_LOCKED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_TPM_20_E_NV_AUTHORIZATION:
++ reason = "STATUS_TPM_20_E_NV_AUTHORIZATION";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_TPM_20_E_NV_UNINITIALIZED:
++ reason = "STATUS_TPM_20_E_NV_UNINITIALIZED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_TPM_20_E_NV_SPACE:
++ reason = "STATUS_TPM_20_E_NV_SPACE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_TPM_20_E_NV_DEFINED:
++ reason = "STATUS_TPM_20_E_NV_DEFINED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_TPM_20_E_BAD_CONTEXT:
++ reason = "STATUS_TPM_20_E_BAD_CONTEXT";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_TPM_20_E_CPHASH:
++ reason = "STATUS_TPM_20_E_CPHASH";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_TPM_20_E_PARENT:
++ reason = "STATUS_TPM_20_E_PARENT";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_TPM_20_E_NEEDS_TEST:
++ reason = "STATUS_TPM_20_E_NEEDS_TEST";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_TPM_20_E_NO_RESULT:
++ reason = "STATUS_TPM_20_E_NO_RESULT";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_TPM_20_E_SENSITIVE:
++ reason = "STATUS_TPM_20_E_SENSITIVE";
++ break;
+ case MD_NTSTATUS_WIN_STATUS_TPM_COMMAND_BLOCKED:
+ reason = "STATUS_TPM_COMMAND_BLOCKED";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_TPM_INVALID_HANDLE:
+ reason = "STATUS_TPM_INVALID_HANDLE";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_TPM_DUPLICATE_VHANDLE:
+ reason = "STATUS_TPM_DUPLICATE_VHANDLE";
+@@ -5577,16 +6991,94 @@ string NTStatusToString(uint32_t ntstatu
+ reason = "STATUS_PCP_PROFILE_NOT_FOUND";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_PCP_VALIDATION_FAILED:
+ reason = "STATUS_PCP_VALIDATION_FAILED";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_PCP_DEVICE_NOT_FOUND:
+ reason = "STATUS_PCP_DEVICE_NOT_FOUND";
+ break;
++ case MD_NTSTATUS_WIN_STATUS_PCP_WRONG_PARENT:
++ reason = "STATUS_PCP_WRONG_PARENT";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_PCP_KEY_NOT_LOADED:
++ reason = "STATUS_PCP_KEY_NOT_LOADED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_PCP_NO_KEY_CERTIFICATION:
++ reason = "STATUS_PCP_NO_KEY_CERTIFICATION";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_PCP_KEY_NOT_FINALIZED:
++ reason = "STATUS_PCP_KEY_NOT_FINALIZED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_PCP_ATTESTATION_CHALLENGE_NOT_SET:
++ reason = "STATUS_PCP_ATTESTATION_CHALLENGE_NOT_SET";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_PCP_NOT_PCR_BOUND:
++ reason = "STATUS_PCP_NOT_PCR_BOUND";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_PCP_KEY_ALREADY_FINALIZED:
++ reason = "STATUS_PCP_KEY_ALREADY_FINALIZED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_PCP_KEY_USAGE_POLICY_NOT_SUPPORTED:
++ reason = "STATUS_PCP_KEY_USAGE_POLICY_NOT_SUPPORTED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_PCP_KEY_USAGE_POLICY_INVALID:
++ reason = "STATUS_PCP_KEY_USAGE_POLICY_INVALID";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_PCP_SOFT_KEY_ERROR:
++ reason = "STATUS_PCP_SOFT_KEY_ERROR";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_PCP_KEY_NOT_AUTHENTICATED:
++ reason = "STATUS_PCP_KEY_NOT_AUTHENTICATED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_PCP_KEY_NOT_AIK:
++ reason = "STATUS_PCP_KEY_NOT_AIK";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_PCP_KEY_NOT_SIGNING_KEY:
++ reason = "STATUS_PCP_KEY_NOT_SIGNING_KEY";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_PCP_LOCKED_OUT:
++ reason = "STATUS_PCP_LOCKED_OUT";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_PCP_CLAIM_TYPE_NOT_SUPPORTED:
++ reason = "STATUS_PCP_CLAIM_TYPE_NOT_SUPPORTED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_PCP_TPM_VERSION_NOT_SUPPORTED:
++ reason = "STATUS_PCP_TPM_VERSION_NOT_SUPPORTED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_PCP_BUFFER_LENGTH_MISMATCH:
++ reason = "STATUS_PCP_BUFFER_LENGTH_MISMATCH";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_PCP_IFX_RSA_KEY_CREATION_BLOCKED:
++ reason = "STATUS_PCP_IFX_RSA_KEY_CREATION_BLOCKED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_PCP_TICKET_MISSING:
++ reason = "STATUS_PCP_TICKET_MISSING";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_PCP_RAW_POLICY_NOT_SUPPORTED:
++ reason = "STATUS_PCP_RAW_POLICY_NOT_SUPPORTED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_PCP_KEY_HANDLE_INVALIDATED:
++ reason = "STATUS_PCP_KEY_HANDLE_INVALIDATED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_RTPM_NO_RESULT:
++ reason = "STATUS_RTPM_NO_RESULT";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_RTPM_PCR_READ_INCOMPLETE:
++ reason = "STATUS_RTPM_PCR_READ_INCOMPLETE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_RTPM_INVALID_CONTEXT:
++ reason = "STATUS_RTPM_INVALID_CONTEXT";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_RTPM_UNSUPPORTED_CMD:
++ reason = "STATUS_RTPM_UNSUPPORTED_CMD";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_TPM_ZERO_EXHAUST_ENABLED:
++ reason = "STATUS_TPM_ZERO_EXHAUST_ENABLED";
++ break;
+ case MD_NTSTATUS_WIN_STATUS_HV_INVALID_HYPERCALL_CODE:
+ reason = "STATUS_HV_INVALID_HYPERCALL_CODE";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_HV_INVALID_HYPERCALL_INPUT:
+ reason = "STATUS_HV_INVALID_HYPERCALL_INPUT";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_HV_INVALID_ALIGNMENT:
+ reason = "STATUS_HV_INVALID_ALIGNMENT";
+@@ -5628,16 +7120,19 @@ string NTStatusToString(uint32_t ntstatu
+ reason = "STATUS_HV_INVALID_CONNECTION_ID";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_HV_INSUFFICIENT_BUFFERS:
+ reason = "STATUS_HV_INSUFFICIENT_BUFFERS";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_HV_NOT_ACKNOWLEDGED:
+ reason = "STATUS_HV_NOT_ACKNOWLEDGED";
+ break;
++ case MD_NTSTATUS_WIN_STATUS_HV_INVALID_VP_STATE:
++ reason = "STATUS_HV_INVALID_VP_STATE";
++ break;
+ case MD_NTSTATUS_WIN_STATUS_HV_ACKNOWLEDGED:
+ reason = "STATUS_HV_ACKNOWLEDGED";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_HV_INVALID_SAVE_RESTORE_STATE:
+ reason = "STATUS_HV_INVALID_SAVE_RESTORE_STATE";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_HV_INVALID_SYNIC_STATE:
+ reason = "STATUS_HV_INVALID_SYNIC_STATE";
+@@ -5661,19 +7156,70 @@ string NTStatusToString(uint32_t ntstatu
+ reason = "STATUS_HV_FEATURE_UNAVAILABLE";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_HV_INSUFFICIENT_BUFFER:
+ reason = "STATUS_HV_INSUFFICIENT_BUFFER";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_HV_INSUFFICIENT_DEVICE_DOMAINS:
+ reason = "STATUS_HV_INSUFFICIENT_DEVICE_DOMAINS";
+ break;
++ case MD_NTSTATUS_WIN_STATUS_HV_CPUID_FEATURE_VALIDATION_ERROR:
++ reason = "STATUS_HV_CPUID_FEATURE_VALIDATION_ERROR";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_HV_CPUID_XSAVE_FEATURE_VALIDATION_ERROR:
++ reason = "STATUS_HV_CPUID_XSAVE_FEATURE_VALIDATION_ERROR";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_HV_PROCESSOR_STARTUP_TIMEOUT:
++ reason = "STATUS_HV_PROCESSOR_STARTUP_TIMEOUT";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_HV_SMX_ENABLED:
++ reason = "STATUS_HV_SMX_ENABLED";
++ break;
+ case MD_NTSTATUS_WIN_STATUS_HV_INVALID_LP_INDEX:
+ reason = "STATUS_HV_INVALID_LP_INDEX";
+ break;
++ case MD_NTSTATUS_WIN_STATUS_HV_INVALID_REGISTER_VALUE:
++ reason = "STATUS_HV_INVALID_REGISTER_VALUE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_HV_INVALID_VTL_STATE:
++ reason = "STATUS_HV_INVALID_VTL_STATE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_HV_NX_NOT_DETECTED:
++ reason = "STATUS_HV_NX_NOT_DETECTED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_HV_INVALID_DEVICE_ID:
++ reason = "STATUS_HV_INVALID_DEVICE_ID";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_HV_INVALID_DEVICE_STATE:
++ reason = "STATUS_HV_INVALID_DEVICE_STATE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_HV_PAGE_REQUEST_INVALID:
++ reason = "STATUS_HV_PAGE_REQUEST_INVALID";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_HV_INVALID_CPU_GROUP_ID:
++ reason = "STATUS_HV_INVALID_CPU_GROUP_ID";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_HV_INVALID_CPU_GROUP_STATE:
++ reason = "STATUS_HV_INVALID_CPU_GROUP_STATE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_HV_OPERATION_FAILED:
++ reason = "STATUS_HV_OPERATION_FAILED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_HV_NOT_ALLOWED_WITH_NESTED_VIRT_ACTIVE:
++ reason = "STATUS_HV_NOT_ALLOWED_WITH_NESTED_VIRT_ACTIVE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_HV_INSUFFICIENT_ROOT_MEMORY:
++ reason = "STATUS_HV_INSUFFICIENT_ROOT_MEMORY";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_HV_EVENT_BUFFER_ALREADY_FREED:
++ reason = "STATUS_HV_EVENT_BUFFER_ALREADY_FREED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_HV_INSUFFICIENT_CONTIGUOUS_MEMORY:
++ reason = "STATUS_HV_INSUFFICIENT_CONTIGUOUS_MEMORY";
++ break;
+ case MD_NTSTATUS_WIN_STATUS_HV_NOT_PRESENT:
+ reason = "STATUS_HV_NOT_PRESENT";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_IPSEC_BAD_SPI:
+ reason = "STATUS_IPSEC_BAD_SPI";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_IPSEC_SA_LIFETIME_EXPIRED:
+ reason = "STATUS_IPSEC_SA_LIFETIME_EXPIRED";
+@@ -5838,16 +7384,19 @@ string NTStatusToString(uint32_t ntstatu
+ reason = "STATUS_VID_SAVED_STATE_CORRUPT";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_VID_SAVED_STATE_UNRECOGNIZED_ITEM:
+ reason = "STATUS_VID_SAVED_STATE_UNRECOGNIZED_ITEM";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_VID_SAVED_STATE_INCOMPATIBLE:
+ reason = "STATUS_VID_SAVED_STATE_INCOMPATIBLE";
+ break;
++ case MD_NTSTATUS_WIN_STATUS_VID_VTL_ACCESS_DENIED:
++ reason = "STATUS_VID_VTL_ACCESS_DENIED";
++ break;
+ case MD_NTSTATUS_WIN_STATUS_VOLMGR_DATABASE_FULL:
+ reason = "STATUS_VOLMGR_DATABASE_FULL";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_CONFIGURATION_CORRUPTED:
+ reason = "STATUS_VOLMGR_DISK_CONFIGURATION_CORRUPTED";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_CONFIGURATION_NOT_IN_SYNC:
+ reason = "STATUS_VOLMGR_DISK_CONFIGURATION_NOT_IN_SYNC";
+@@ -6228,16 +7777,34 @@ string NTStatusToString(uint32_t ntstatu
+ reason = "STATUS_CTLOG_INVALID_TRACKING_STATE";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_CTLOG_INCONSISTENT_TRACKING_FILE:
+ reason = "STATUS_CTLOG_INCONSISTENT_TRACKING_FILE";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_VHD_METADATA_FULL:
+ reason = "STATUS_VHD_METADATA_FULL";
+ break;
++ case MD_NTSTATUS_WIN_STATUS_VHD_INVALID_CHANGE_TRACKING_ID:
++ reason = "STATUS_VHD_INVALID_CHANGE_TRACKING_ID";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_VHD_CHANGE_TRACKING_DISABLED:
++ reason = "STATUS_VHD_CHANGE_TRACKING_DISABLED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_VHD_MISSING_CHANGE_TRACKING_INFORMATION:
++ reason = "STATUS_VHD_MISSING_CHANGE_TRACKING_INFORMATION";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_VHD_RESIZE_WOULD_TRUNCATE_DATA:
++ reason = "STATUS_VHD_RESIZE_WOULD_TRUNCATE_DATA";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_VHD_COULD_NOT_COMPUTE_MINIMUM_VIRTUAL_SIZE:
++ reason = "STATUS_VHD_COULD_NOT_COMPUTE_MINIMUM_VIRTUAL_SIZE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_VHD_ALREADY_AT_OR_BELOW_MINIMUM_VIRTUAL_SIZE:
++ reason = "STATUS_VHD_ALREADY_AT_OR_BELOW_MINIMUM_VIRTUAL_SIZE";
++ break;
+ case MD_NTSTATUS_WIN_STATUS_RKF_KEY_NOT_FOUND:
+ reason = "STATUS_RKF_KEY_NOT_FOUND";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_RKF_DUPLICATE_KEY:
+ reason = "STATUS_RKF_DUPLICATE_KEY";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_RKF_BLOB_FULL:
+ reason = "STATUS_RKF_BLOB_FULL";
+@@ -6255,16 +7822,19 @@ string NTStatusToString(uint32_t ntstatu
+ reason = "STATUS_RDBSS_RESTART_OPERATION";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_RDBSS_CONTINUE_OPERATION:
+ reason = "STATUS_RDBSS_CONTINUE_OPERATION";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_RDBSS_POST_OPERATION:
+ reason = "STATUS_RDBSS_POST_OPERATION";
+ break;
++ case MD_NTSTATUS_WIN_STATUS_RDBSS_RETRY_LOOKUP:
++ reason = "STATUS_RDBSS_RETRY_LOOKUP";
++ break;
+ case MD_NTSTATUS_WIN_STATUS_BTH_ATT_INVALID_HANDLE:
+ reason = "STATUS_BTH_ATT_INVALID_HANDLE";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_BTH_ATT_READ_NOT_PERMITTED:
+ reason = "STATUS_BTH_ATT_READ_NOT_PERMITTED";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_BTH_ATT_WRITE_NOT_PERMITTED:
+ reason = "STATUS_BTH_ATT_WRITE_NOT_PERMITTED";
+@@ -6327,34 +7897,70 @@ string NTStatusToString(uint32_t ntstatu
+ reason = "STATUS_SECUREBOOT_POLICY_PUBLISHER_NOT_FOUND";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_SECUREBOOT_POLICY_NOT_SIGNED:
+ reason = "STATUS_SECUREBOOT_POLICY_NOT_SIGNED";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_SECUREBOOT_FILE_REPLACED:
+ reason = "STATUS_SECUREBOOT_FILE_REPLACED";
+ break;
++ case MD_NTSTATUS_WIN_STATUS_SECUREBOOT_POLICY_NOT_AUTHORIZED:
++ reason = "STATUS_SECUREBOOT_POLICY_NOT_AUTHORIZED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_SECUREBOOT_POLICY_UNKNOWN:
++ reason = "STATUS_SECUREBOOT_POLICY_UNKNOWN";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_SECUREBOOT_POLICY_MISSING_ANTIROLLBACKVERSION:
++ reason = "STATUS_SECUREBOOT_POLICY_MISSING_ANTIROLLBACKVERSION";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_SECUREBOOT_PLATFORM_ID_MISMATCH:
++ reason = "STATUS_SECUREBOOT_PLATFORM_ID_MISMATCH";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_SECUREBOOT_POLICY_ROLLBACK_DETECTED:
++ reason = "STATUS_SECUREBOOT_POLICY_ROLLBACK_DETECTED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_SECUREBOOT_POLICY_UPGRADE_MISMATCH:
++ reason = "STATUS_SECUREBOOT_POLICY_UPGRADE_MISMATCH";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_SECUREBOOT_REQUIRED_POLICY_FILE_MISSING:
++ reason = "STATUS_SECUREBOOT_REQUIRED_POLICY_FILE_MISSING";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_SECUREBOOT_NOT_BASE_POLICY:
++ reason = "STATUS_SECUREBOOT_NOT_BASE_POLICY";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_SECUREBOOT_NOT_SUPPLEMENTAL_POLICY:
++ reason = "STATUS_SECUREBOOT_NOT_SUPPLEMENTAL_POLICY";
++ break;
+ case MD_NTSTATUS_WIN_STATUS_AUDIO_ENGINE_NODE_NOT_FOUND:
+ reason = "STATUS_AUDIO_ENGINE_NODE_NOT_FOUND";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_HDAUDIO_EMPTY_CONNECTION_LIST:
+ reason = "STATUS_HDAUDIO_EMPTY_CONNECTION_LIST";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_HDAUDIO_CONNECTION_LIST_NOT_SUPPORTED:
+ reason = "STATUS_HDAUDIO_CONNECTION_LIST_NOT_SUPPORTED";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_HDAUDIO_NO_LOGICAL_DEVICES_CREATED:
+ reason = "STATUS_HDAUDIO_NO_LOGICAL_DEVICES_CREATED";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_HDAUDIO_NULL_LINKED_LIST_ENTRY:
+ reason = "STATUS_HDAUDIO_NULL_LINKED_LIST_ENTRY";
+ break;
++ case MD_NTSTATUS_WIN_STATUS_VSM_NOT_INITIALIZED:
++ reason = "STATUS_VSM_NOT_INITIALIZED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_VSM_DMA_PROTECTION_NOT_IN_USE:
++ reason = "STATUS_VSM_DMA_PROTECTION_NOT_IN_USE";
++ break;
+ case MD_NTSTATUS_WIN_STATUS_VOLSNAP_BOOTFILE_NOT_VALID:
+ reason = "STATUS_VOLSNAP_BOOTFILE_NOT_VALID";
+ break;
++ case MD_NTSTATUS_WIN_STATUS_VOLSNAP_ACTIVATION_TIMEOUT:
++ reason = "STATUS_VOLSNAP_ACTIVATION_TIMEOUT";
++ break;
+ case MD_NTSTATUS_WIN_STATUS_IO_PREEMPTED:
+ reason = "STATUS_IO_PREEMPTED";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_SVHDX_ERROR_STORED:
+ reason = "STATUS_SVHDX_ERROR_STORED";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_SVHDX_ERROR_NOT_AVAILABLE:
+ reason = "STATUS_SVHDX_ERROR_NOT_AVAILABLE";
+@@ -6384,31 +7990,214 @@ string NTStatusToString(uint32_t ntstatu
+ reason = "STATUS_SVHDX_WRONG_FILE_TYPE";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_SVHDX_VERSION_MISMATCH:
+ reason = "STATUS_SVHDX_VERSION_MISMATCH";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_VHD_SHARED:
+ reason = "STATUS_VHD_SHARED";
+ break;
++ case MD_NTSTATUS_WIN_STATUS_SVHDX_NO_INITIATOR:
++ reason = "STATUS_SVHDX_NO_INITIATOR";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_VHDSET_BACKING_STORAGE_NOT_FOUND:
++ reason = "STATUS_VHDSET_BACKING_STORAGE_NOT_FOUND";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_SMB_NO_PREAUTH_INTEGRITY_HASH_OVERLAP:
++ reason = "STATUS_SMB_NO_PREAUTH_INTEGRITY_HASH_OVERLAP";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_SMB_BAD_CLUSTER_DIALECT:
++ reason = "STATUS_SMB_BAD_CLUSTER_DIALECT";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_SMB_GUEST_LOGON_BLOCKED:
++ reason = "STATUS_SMB_GUEST_LOGON_BLOCKED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_SPACES_FAULT_DOMAIN_TYPE_INVALID:
++ reason = "STATUS_SPACES_FAULT_DOMAIN_TYPE_INVALID";
++ break;
+ case MD_NTSTATUS_WIN_STATUS_SPACES_RESILIENCY_TYPE_INVALID:
+ reason = "STATUS_SPACES_RESILIENCY_TYPE_INVALID";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_SPACES_DRIVE_SECTOR_SIZE_INVALID:
+ reason = "STATUS_SPACES_DRIVE_SECTOR_SIZE_INVALID";
+ break;
++ case MD_NTSTATUS_WIN_STATUS_SPACES_DRIVE_REDUNDANCY_INVALID:
++ reason = "STATUS_SPACES_DRIVE_REDUNDANCY_INVALID";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_SPACES_NUMBER_OF_DATA_COPIES_INVALID:
++ reason = "STATUS_SPACES_NUMBER_OF_DATA_COPIES_INVALID";
++ break;
+ case MD_NTSTATUS_WIN_STATUS_SPACES_INTERLEAVE_LENGTH_INVALID:
+ reason = "STATUS_SPACES_INTERLEAVE_LENGTH_INVALID";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_SPACES_NUMBER_OF_COLUMNS_INVALID:
+ reason = "STATUS_SPACES_NUMBER_OF_COLUMNS_INVALID";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_SPACES_NOT_ENOUGH_DRIVES:
+ reason = "STATUS_SPACES_NOT_ENOUGH_DRIVES";
+ break;
++ case MD_NTSTATUS_WIN_STATUS_SPACES_EXTENDED_ERROR:
++ reason = "STATUS_SPACES_EXTENDED_ERROR";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_SPACES_PROVISIONING_TYPE_INVALID:
++ reason = "STATUS_SPACES_PROVISIONING_TYPE_INVALID";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_SPACES_ALLOCATION_SIZE_INVALID:
++ reason = "STATUS_SPACES_ALLOCATION_SIZE_INVALID";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_SPACES_ENCLOSURE_AWARE_INVALID:
++ reason = "STATUS_SPACES_ENCLOSURE_AWARE_INVALID";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_SPACES_WRITE_CACHE_SIZE_INVALID:
++ reason = "STATUS_SPACES_WRITE_CACHE_SIZE_INVALID";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_SPACES_NUMBER_OF_GROUPS_INVALID:
++ reason = "STATUS_SPACES_NUMBER_OF_GROUPS_INVALID";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_SPACES_DRIVE_OPERATIONAL_STATE_INVALID:
++ reason = "STATUS_SPACES_DRIVE_OPERATIONAL_STATE_INVALID";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_SPACES_UPDATE_COLUMN_STATE:
++ reason = "STATUS_SPACES_UPDATE_COLUMN_STATE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_SPACES_MAP_REQUIRED:
++ reason = "STATUS_SPACES_MAP_REQUIRED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_SPACES_UNSUPPORTED_VERSION:
++ reason = "STATUS_SPACES_UNSUPPORTED_VERSION";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_SPACES_CORRUPT_METADATA:
++ reason = "STATUS_SPACES_CORRUPT_METADATA";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_SPACES_DRT_FULL:
++ reason = "STATUS_SPACES_DRT_FULL";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_SPACES_INCONSISTENCY:
++ reason = "STATUS_SPACES_INCONSISTENCY";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_SPACES_LOG_NOT_READY:
++ reason = "STATUS_SPACES_LOG_NOT_READY";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_SPACES_NO_REDUNDANCY:
++ reason = "STATUS_SPACES_NO_REDUNDANCY";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_SPACES_DRIVE_NOT_READY:
++ reason = "STATUS_SPACES_DRIVE_NOT_READY";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_SPACES_DRIVE_SPLIT:
++ reason = "STATUS_SPACES_DRIVE_SPLIT";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_SPACES_DRIVE_LOST_DATA:
++ reason = "STATUS_SPACES_DRIVE_LOST_DATA";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_SPACES_ENTRY_INCOMPLETE:
++ reason = "STATUS_SPACES_ENTRY_INCOMPLETE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_SPACES_ENTRY_INVALID:
++ reason = "STATUS_SPACES_ENTRY_INVALID";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_SPACES_MARK_DIRTY:
++ reason = "STATUS_SPACES_MARK_DIRTY";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_SECCORE_INVALID_COMMAND:
++ reason = "STATUS_SECCORE_INVALID_COMMAND";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_SYSTEM_INTEGRITY_ROLLBACK_DETECTED:
++ reason = "STATUS_SYSTEM_INTEGRITY_ROLLBACK_DETECTED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_SYSTEM_INTEGRITY_POLICY_VIOLATION:
++ reason = "STATUS_SYSTEM_INTEGRITY_POLICY_VIOLATION";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_SYSTEM_INTEGRITY_INVALID_POLICY:
++ reason = "STATUS_SYSTEM_INTEGRITY_INVALID_POLICY";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_SYSTEM_INTEGRITY_POLICY_NOT_SIGNED:
++ reason = "STATUS_SYSTEM_INTEGRITY_POLICY_NOT_SIGNED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_SYSTEM_INTEGRITY_TOO_MANY_POLICIES:
++ reason = "STATUS_SYSTEM_INTEGRITY_TOO_MANY_POLICIES";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_SYSTEM_INTEGRITY_SUPPLEMENTAL_POLICY_NOT_AUTHORIZED:
++ reason = "STATUS_SYSTEM_INTEGRITY_SUPPLEMENTAL_POLICY_NOT_AUTHORIZED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_NO_APPLICABLE_APP_LICENSES_FOUND:
++ reason = "STATUS_NO_APPLICABLE_APP_LICENSES_FOUND";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_CLIP_LICENSE_NOT_FOUND:
++ reason = "STATUS_CLIP_LICENSE_NOT_FOUND";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_CLIP_DEVICE_LICENSE_MISSING:
++ reason = "STATUS_CLIP_DEVICE_LICENSE_MISSING";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_CLIP_LICENSE_INVALID_SIGNATURE:
++ reason = "STATUS_CLIP_LICENSE_INVALID_SIGNATURE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_CLIP_KEYHOLDER_LICENSE_MISSING_OR_INVALID:
++ reason = "STATUS_CLIP_KEYHOLDER_LICENSE_MISSING_OR_INVALID";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_CLIP_LICENSE_EXPIRED:
++ reason = "STATUS_CLIP_LICENSE_EXPIRED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_CLIP_LICENSE_SIGNED_BY_UNKNOWN_SOURCE:
++ reason = "STATUS_CLIP_LICENSE_SIGNED_BY_UNKNOWN_SOURCE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_CLIP_LICENSE_NOT_SIGNED:
++ reason = "STATUS_CLIP_LICENSE_NOT_SIGNED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_CLIP_LICENSE_HARDWARE_ID_OUT_OF_TOLERANCE:
++ reason = "STATUS_CLIP_LICENSE_HARDWARE_ID_OUT_OF_TOLERANCE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_CLIP_LICENSE_DEVICE_ID_MISMATCH:
++ reason = "STATUS_CLIP_LICENSE_DEVICE_ID_MISMATCH";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_PLATFORM_MANIFEST_NOT_AUTHORIZED:
++ reason = "STATUS_PLATFORM_MANIFEST_NOT_AUTHORIZED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_PLATFORM_MANIFEST_INVALID:
++ reason = "STATUS_PLATFORM_MANIFEST_INVALID";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_PLATFORM_MANIFEST_FILE_NOT_AUTHORIZED:
++ reason = "STATUS_PLATFORM_MANIFEST_FILE_NOT_AUTHORIZED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_PLATFORM_MANIFEST_CATALOG_NOT_AUTHORIZED:
++ reason = "STATUS_PLATFORM_MANIFEST_CATALOG_NOT_AUTHORIZED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_PLATFORM_MANIFEST_BINARY_ID_NOT_FOUND:
++ reason = "STATUS_PLATFORM_MANIFEST_BINARY_ID_NOT_FOUND";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_PLATFORM_MANIFEST_NOT_ACTIVE:
++ reason = "STATUS_PLATFORM_MANIFEST_NOT_ACTIVE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_PLATFORM_MANIFEST_NOT_SIGNED:
++ reason = "STATUS_PLATFORM_MANIFEST_NOT_SIGNED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_APPEXEC_CONDITION_NOT_SATISFIED:
++ reason = "STATUS_APPEXEC_CONDITION_NOT_SATISFIED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_APPEXEC_HANDLE_INVALIDATED:
++ reason = "STATUS_APPEXEC_HANDLE_INVALIDATED";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_APPEXEC_INVALID_HOST_GENERATION:
++ reason = "STATUS_APPEXEC_INVALID_HOST_GENERATION";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_APPEXEC_UNEXPECTED_PROCESS_REGISTRATION:
++ reason = "STATUS_APPEXEC_UNEXPECTED_PROCESS_REGISTRATION";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_APPEXEC_INVALID_HOST_STATE:
++ reason = "STATUS_APPEXEC_INVALID_HOST_STATE";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_APPEXEC_NO_DONOR:
++ reason = "STATUS_APPEXEC_NO_DONOR";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_APPEXEC_HOST_ID_MISMATCH:
++ reason = "STATUS_APPEXEC_HOST_ID_MISMATCH";
++ break;
++ case MD_NTSTATUS_WIN_STATUS_APPEXEC_UNKNOWN_USER:
++ reason = "STATUS_APPEXEC_UNKNOWN_USER";
++ break;
+ default: {
+ char reason_string[11];
+ snprintf(reason_string, sizeof(reason_string), "0x%08x", ntstatus);
+ reason = reason_string;
+ break;
+ }
+ }
+ return reason;
+
diff --git a/toolkit/crashreporter/breakpad-patches/20-mac-crash-info.patch b/toolkit/crashreporter/breakpad-patches/20-mac-crash-info.patch
new file mode 100644
index 0000000000..be971133a1
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-patches/20-mac-crash-info.patch
@@ -0,0 +1,516 @@
+# HG changeset patch
+# User Steven Michaud <smichaud@pobox.com>
+# Date 1619800781 18000
+# Fri Apr 30 11:39:41 2021 -0500
+# Node ID 9f89eb3d68316e8c3a469d1c058ad40c1807d7bc
+# Parent 0db412525773fff333e8d338551021e083c25619
+Bug 1577886 - Add support to for macOS __crash_info data to Breakpad. r=gsvelto
+Differential Revision: https://phabricator.services.mozilla.com/D112871
+
+diff --git a/src/google_breakpad/common/minidump_format.h b/src/google_breakpad/common/minidump_format.h
+--- a/src/google_breakpad/common/minidump_format.h
++++ b/src/google_breakpad/common/minidump_format.h
+@@ -351,6 +351,10 @@ typedef enum {
+ /* Crashpad extension types. 0x4350 = "CP"
+ * See Crashpad's minidump/minidump_extensions.h. */
+ MD_CRASHPAD_INFO_STREAM = 0x43500001, /* MDRawCrashpadInfo */
++
++ /* Data from the __DATA,__crash_info section of every module which contains
++ * one that has useful data. Only available on macOS. 0x4D7A = "Mz". */
++ MOZ_MACOS_CRASH_INFO_STREAM = 0x4d7a0001,
+ } MDStreamType; /* MINIDUMP_STREAM_TYPE */
+
+
+@@ -1094,6 +1098,52 @@ typedef struct {
+ MDLocationDescriptor module_list; /* MDRawModuleCrashpadInfoList */
+ } MDRawCrashpadInfo;
+
++/* macOS __DATA,__crash_info data */
++
++typedef struct {
++ uint64_t stream_type; /* MOZ_MACOS_CRASH_INFO_STREAM */
++ uint64_t version;
++ uint64_t thread;
++ uint64_t dialog_mode;
++ uint64_t abort_cause; /* Only valid when 'version' > 4 */
++ /* If/when Apple adds more fields to crashreporter_annotations_t, add
++ * numerical fields here and change (MDRawMacCrashInfo).record_start_size
++ * accordingly. Make them all uint64_t, to keep this structure the same size
++ * on all platforms. 'data' should always be the last field. Add new string
++ * fields to the end of 'data'. */
++ /* 'data' currently contains five null-terminated uint8_t arrays, each
++ * possibly empty (containing only a single terminal null), stored one after
++ * the other:
++ * module_path;
++ * message;
++ * signature_string;
++ * backtrace;
++ * message2; */
++ uint8_t data[0];
++} MDRawMacCrashInfoRecord;
++
++/* This is the maximum supported size for each string in
++ * (MDRawMacCrashInfoRecord).data. If we encounter a string in the
++ * __crash_info section which seems larger than this, that's a sign of data
++ * corruption. */
++#define MACCRASHINFO_STRING_MAXSIZE 8192
++
++/* In principle there should only be one or two non-empty __DATA,__crash_info
++ * sections per process. But the __crash_info section is almost entirely
++ * undocumented, so just in case we set a large maximum. */
++#define MAC_CRASH_INFOS_MAX 20
++
++typedef struct {
++ uint32_t stream_type; /* MOZ_MACOS_CRASH_INFO_STREAM */
++ uint32_t record_count;
++ /* The size of the "fixed-size" part of MDRawMacCrashInfoRecord, before the
++ * 'data' field. This will always be 'sizeof(MDRawMacCrashInfoRecord)'. But
++ * that value may change if more numerical fields are added to
++ * MDRawMacCrashInfoRecord in the future. */
++ uint32_t record_start_size;
++ MDLocationDescriptor records[MAC_CRASH_INFOS_MAX];
++} MDRawMacCrashInfo;
++
+ #if defined(_MSC_VER)
+ #pragma warning(pop)
+ #endif /* _MSC_VER */
+diff --git a/src/google_breakpad/processor/minidump.h b/src/google_breakpad/processor/minidump.h
+--- a/src/google_breakpad/processor/minidump.h
++++ b/src/google_breakpad/processor/minidump.h
+@@ -1151,6 +1151,57 @@ class MinidumpCrashpadInfo : public Mini
+ std::map<std::string, std::string> simple_annotations_;
+ };
+
++// MinidumpMacCrashInfo wraps MDRawMacCrashInfo. It's an optional stream
++// in a minidump that records information from the __DATA,__crash_info
++// section of every module in the crashing process that contains one, and
++// which isn't empty of useful information. Only present on macOS.
++
++// Friendly wrapper for the information in MDRawMacCrashInfoRecord.
++typedef struct crash_info_record {
++ string module_path;
++ unsigned long version;
++ string message;
++ string signature_string;
++ string backtrace;
++ string message2;
++ unsigned long long thread;
++ unsigned int dialog_mode;
++ long long abort_cause; // Only valid when 'version' > 4
++ crash_info_record()
++ : version(0), thread(0), dialog_mode(0), abort_cause(0)
++ {}
++} crash_info_record_t;
++
++class MinidumpMacCrashInfo : public MinidumpStream {
++ public:
++ // A human-readable representation of the data from the __DATA,__crash_info
++ // sections in all of the crashing process's modules that have one, if
++ // it's not empty of useful data. Suitable for use by "minidump_stackwalk".
++ string description() const { return description_; }
++ // A "machine-readable" copy of the same information, suitable for use by
++ // "minidump_stalkwalk -m".
++ vector<crash_info_record_t> const records() {
++ return records_;
++ }
++
++ // Print a human-readable representation of the object to stdout.
++ void Print();
++
++ private:
++ friend class Minidump;
++
++ static const uint32_t kStreamType = MOZ_MACOS_CRASH_INFO_STREAM;
++
++ explicit MinidumpMacCrashInfo(Minidump* minidump_);
++
++ bool ReadCrashInfoRecord(MDLocationDescriptor location,
++ uint32_t record_start_size);
++ bool Read(uint32_t expected_size);
++
++ string description_;
++ vector<crash_info_record_t> records_;
++};
++
+
+ // Minidump is the user's interface to a minidump file. It wraps MDRawHeader
+ // and provides access to the minidump's top-level stream directory.
+@@ -1214,6 +1265,7 @@ class Minidump {
+ virtual MinidumpBreakpadInfo* GetBreakpadInfo();
+ virtual MinidumpMemoryInfoList* GetMemoryInfoList();
+ MinidumpCrashpadInfo* GetCrashpadInfo();
++ MinidumpMacCrashInfo* GetMacCrashInfo();
+
+ // The next method also calls GetStream, but is exclusive for Linux dumps.
+ virtual MinidumpLinuxMapsList *GetLinuxMapsList();
+diff --git a/src/google_breakpad/processor/process_state.h b/src/google_breakpad/processor/process_state.h
+--- a/src/google_breakpad/processor/process_state.h
++++ b/src/google_breakpad/processor/process_state.h
+@@ -112,6 +112,14 @@ class ProcessState {
+ return &thread_memory_regions_;
+ }
+ const SystemInfo* system_info() const { return &system_info_; }
++ string mac_crash_info() const { return mac_crash_info_; }
++ size_t mac_crash_info_records_count() const {
++ return mac_crash_info_records_.size();
++ }
++ const crash_info_record_t* mac_crash_info_records() const {
++ return reinterpret_cast<const crash_info_record_t*>(
++ &mac_crash_info_records_[0]);
++ }
+ const CodeModules* modules() const { return modules_; }
+ const CodeModules* unloaded_modules() const { return unloaded_modules_; }
+ const vector<linked_ptr<const CodeModule> >* shrunk_range_modules() const {
+@@ -179,6 +187,10 @@ class ProcessState {
+ // OS and CPU information.
+ SystemInfo system_info_;
+
++ // Information from __DATA,__crash_info sections. Only present on macOS.
++ string mac_crash_info_;
++ vector<crash_info_record_t> mac_crash_info_records_;
++
+ // The modules that were loaded into the process represented by the
+ // ProcessState.
+ const CodeModules *modules_;
+diff --git a/src/processor/minidump.cc b/src/processor/minidump.cc
+--- a/src/processor/minidump.cc
++++ b/src/processor/minidump.cc
+@@ -5116,6 +5116,230 @@ void MinidumpCrashpadInfo::Print() {
+ printf("\n");
+ }
+
++//
++// MinidumpMacCrashInfo
++//
++
++MinidumpMacCrashInfo::MinidumpMacCrashInfo(Minidump* minidump)
++ : MinidumpStream(minidump),
++ description_(),
++ records_() {
++}
++
++bool MinidumpMacCrashInfo::ReadCrashInfoRecord(MDLocationDescriptor location,
++ uint32_t record_start_size) {
++ if (!minidump_->SeekSet(location.rva)) {
++ BPLOG(ERROR) << "ReadCrashInfoRecord could not seek to record";
++ return false;
++ }
++
++ // We may be reading a minidump 1) created by (newer) code that defines more
++ // fields than we do in the fixed-size part of MDRawMacCrashInfoRecord
++ // (before 'data'), or 2) created by (older) code that defines fewer fields.
++ // In the first case we read in the newer fields but ignore them. In the
++ // second case we read in only the older fields, and leave the newer fields
++ // (in 'raw_record_start') set to zero.
++ uint32_t raw_record_size = sizeof(MDRawMacCrashInfoRecord);
++ if (record_start_size > raw_record_size) {
++ raw_record_size = record_start_size;
++ }
++ scoped_ptr< vector<uint8_t> > raw_record(
++ new vector<uint8_t>(raw_record_size));
++ if (!minidump_->ReadBytes(&(*raw_record)[0], record_start_size)) {
++ BPLOG(ERROR) << "ReadCrashInfoRecord could not read " <<
++ record_start_size << " bytes of record";
++ return false;
++ }
++ MDRawMacCrashInfoRecord* raw_record_start =
++ (MDRawMacCrashInfoRecord*) &(*raw_record)[0];
++
++ if (minidump_->swap()) {
++ Swap(&raw_record_start->stream_type);
++ Swap(&raw_record_start->version);
++ Swap(&raw_record_start->thread);
++ Swap(&raw_record_start->dialog_mode);
++ Swap(&raw_record_start->abort_cause);
++ }
++
++ if (raw_record_start->stream_type != MOZ_MACOS_CRASH_INFO_STREAM) {
++ BPLOG(ERROR) << "ReadCrashInfoRecord stream type mismatch, " <<
++ raw_record_start->stream_type << " != " <<
++ MOZ_MACOS_CRASH_INFO_STREAM;
++ return false;
++ }
++
++ uint32_t string_data_size = location.data_size - record_start_size;
++ scoped_ptr< vector<uint8_t> > data(new vector<uint8_t>(string_data_size));
++ if (!minidump_->ReadBytes(&(*data)[0], string_data_size)) {
++ BPLOG(ERROR) << "ReadCrashInfoRecord could not read " <<
++ string_data_size << " bytes of record data";
++ return false;
++ }
++
++ crash_info_record_t record;
++
++ record.version = (unsigned long) raw_record_start->version;
++ record.thread = (unsigned long long) raw_record_start->thread;
++ record.dialog_mode = (unsigned int) raw_record_start->dialog_mode;
++ record.abort_cause = (long long) raw_record_start->abort_cause;
++
++ // Once again, we may be reading a minidump created by newer code that
++ // stores more strings than we expect in (MDRawMacCrashInfoRecord).data,
++ // or one created by older code that contains fewer strings than we
++ // expect. In the first case we ignore the "extra" strings. To deal with
++ // the second case we bail when 'offset >= string_data_size'.
++ const char* string_data = (const char*) &(*data)[0];
++ size_t offset = 0;
++ for (int i = 1; i <= 5; ++i) {
++ switch (i) {
++ case 1:
++ record.module_path.append(string_data);
++ break;
++ case 2:
++ record.message.append(string_data);
++ break;
++ case 3:
++ record.signature_string.append(string_data);
++ break;
++ case 4:
++ record.backtrace.append(string_data);
++ break;
++ case 5:
++ record.message2.append(string_data);
++ break;
++ }
++ size_t char_array_size = strlen(string_data) + 1;
++ offset += char_array_size;
++ if (offset >= string_data_size) {
++ break;
++ }
++ string_data += char_array_size;
++ }
++
++ records_.push_back(record);
++
++ description_.append(" Module \"");
++ description_.append(record.module_path);
++ description_.append("\":\n");
++
++ int num_fields = 6;
++ if (record.version > 4) {
++ num_fields = 7;
++ }
++ for (int i = 1; i <= num_fields; ++i) {
++ switch (i) {
++ case 1:
++ if (!record.message.empty()) {
++ description_.append(" message: \"");
++ description_.append(record.message);
++ description_.append("\"\n");
++ }
++ break;
++ case 2:
++ if (!record.signature_string.empty()) {
++ description_.append(" signature_string: \"");
++ description_.append(record.signature_string);
++ description_.append("\"\n");
++ }
++ break;
++ case 3:
++ if (!record.backtrace.empty()) {
++ description_.append(" backtrace: \"");
++ description_.append(record.backtrace);
++ description_.append("\"\n");
++ }
++ break;
++ case 4:
++ if (!record.message2.empty()) {
++ description_.append(" message2: \"");
++ description_.append(record.message2);
++ description_.append("\"\n");
++ }
++ break;
++ case 5:
++ if (record.thread) {
++ char thread[128];
++ snprintf(thread, sizeof(thread), " thread: 0x%llx\n",
++ record.thread);
++ description_.append(thread);
++ }
++ break;
++ case 6:
++ if (record.dialog_mode) {
++ char dialog_mode[128];
++ snprintf(dialog_mode, sizeof(dialog_mode), " dialog_mode: 0x%x\n",
++ record.dialog_mode);
++ description_.append(dialog_mode);
++ }
++ break;
++ case 7:
++ if (record.abort_cause) {
++ char abort_cause[128];
++ snprintf(abort_cause, sizeof(abort_cause), " abort_cause: %lld\n",
++ record.abort_cause);
++ description_.append(abort_cause);
++ }
++ break;
++ default:
++ break;
++ }
++ }
++
++ return true;
++}
++
++bool MinidumpMacCrashInfo::Read(uint32_t expected_size) {
++ description_.clear();
++ records_.clear();
++ valid_ = false;
++
++ MDRawMacCrashInfo crash_info;
++ if (expected_size != sizeof(crash_info)) {
++ BPLOG(ERROR) << "MinidumpMacCrashInfo size mismatch, " <<
++ expected_size << " != " << sizeof(crash_info);
++ return false;
++ }
++ if (!minidump_->ReadBytes(&crash_info, sizeof(crash_info))) {
++ BPLOG(ERROR) << "MinidumpMacCrashInfo could not read " <<
++ sizeof(crash_info) << " bytes";
++ return false;
++ }
++ if (minidump_->swap()) {
++ Swap(&crash_info.stream_type);
++ Swap(&crash_info.record_count);
++ Swap(&crash_info.record_start_size);
++ for (uint32_t i = 0; i < crash_info.record_count; ++i) {
++ Swap(&crash_info.records[i].data_size);
++ Swap(&crash_info.records[i].rva);
++ }
++ }
++ if (crash_info.stream_type != MOZ_MACOS_CRASH_INFO_STREAM) {
++ BPLOG(ERROR) << "MinidumpMacCrashInfo stream type mismatch, " <<
++ crash_info.stream_type << " != " <<
++ MOZ_MACOS_CRASH_INFO_STREAM;
++ return false;
++ }
++
++ for (uint32_t i = 0; i < crash_info.record_count; ++i) {
++ if (!ReadCrashInfoRecord(crash_info.records[i],
++ crash_info.record_start_size)) {
++ return false;
++ }
++ }
++
++ valid_ = true;
++ return true;
++}
++
++void MinidumpMacCrashInfo::Print() {
++ if (!valid_) {
++ BPLOG(ERROR) << "MinidumpMacCrashInfo cannot print invalid data";
++ return;
++ }
++
++ printf("MinidumpMacCrashInfo:\n\n");
++ printf("%s", description_.c_str());
++}
+
+ //
+ // Minidump
+@@ -5378,7 +5602,8 @@ bool Minidump::Read() {
+ case MD_SYSTEM_INFO_STREAM:
+ case MD_MISC_INFO_STREAM:
+ case MD_BREAKPAD_INFO_STREAM:
+- case MD_CRASHPAD_INFO_STREAM: {
++ case MD_CRASHPAD_INFO_STREAM:
++ case MOZ_MACOS_CRASH_INFO_STREAM: {
+ if (stream_map_->find(stream_type) != stream_map_->end()) {
+ // Another stream with this type was already found. A minidump
+ // file should contain at most one of each of these stream types.
+@@ -5499,6 +5724,11 @@ MinidumpCrashpadInfo* Minidump::GetCrash
+ return GetStream(&crashpad_info);
+ }
+
++MinidumpMacCrashInfo* Minidump::GetMacCrashInfo() {
++ MinidumpMacCrashInfo* mac_crash_info;
++ return GetStream(&mac_crash_info);
++}
++
+ static const char* get_stream_name(uint32_t stream_type) {
+ switch (stream_type) {
+ case MD_UNUSED_STREAM:
+@@ -5571,6 +5801,8 @@ static const char* get_stream_name(uint3
+ return "MD_LINUX_DSO_DEBUG";
+ case MD_CRASHPAD_INFO_STREAM:
+ return "MD_CRASHPAD_INFO_STREAM";
++ case MOZ_MACOS_CRASH_INFO_STREAM:
++ return "MOZ_MACOS_CRASH_INFO_STREAM";
+ default:
+ return "unknown";
+ }
+diff --git a/src/processor/minidump_processor.cc b/src/processor/minidump_processor.cc
+--- a/src/processor/minidump_processor.cc
++++ b/src/processor/minidump_processor.cc
+@@ -137,6 +137,12 @@ ProcessResult MinidumpProcessor::Process
+ }
+ }
+
++ MinidumpMacCrashInfo *crash_info = dump->GetMacCrashInfo();
++ if (crash_info) {
++ process_state->mac_crash_info_ = crash_info->description();
++ process_state->mac_crash_info_records_ = crash_info->records();
++ }
++
+ // This will just return an empty string if it doesn't exist.
+ process_state->assertion_ = GetAssertion(dump);
+
+diff --git a/src/processor/stackwalk_common.cc b/src/processor/stackwalk_common.cc
+--- a/src/processor/stackwalk_common.cc
++++ b/src/processor/stackwalk_common.cc
+@@ -872,6 +872,12 @@ void PrintProcessState(const ProcessStat
+ printf("Process uptime: not available\n");
+ }
+
++ if (!process_state.mac_crash_info().empty()) {
++ printf("\n");
++ printf("Application-specific information:\n");
++ printf("%s", process_state.mac_crash_info().c_str());
++ }
++
+ // If the thread that requested the dump is known, print it first.
+ int requesting_thread = process_state.requesting_thread();
+ if (requesting_thread != -1) {
+@@ -955,6 +961,44 @@ void PrintProcessStateMachineReadable(co
+ printf("\n");
+ }
+
++ const crash_info_record_t* crash_info_records =
++ process_state.mac_crash_info_records();
++ size_t num_records =
++ process_state.mac_crash_info_records_count();
++ for (size_t i = 0; i < num_records; ++i) {
++ char thread_str[32];
++ if (crash_info_records[i].thread) {
++ snprintf(thread_str, sizeof(thread_str), "0x%llx",
++ crash_info_records[i].thread);
++ } else {
++ strncpy(thread_str, "0", sizeof(thread_str));
++ }
++ char dialog_mode_str[32];
++ if (crash_info_records[i].dialog_mode) {
++ snprintf(dialog_mode_str, sizeof(dialog_mode_str), "0x%x",
++ crash_info_records[i].dialog_mode);
++ } else {
++ strncpy(dialog_mode_str, "0", sizeof(dialog_mode_str));
++ }
++ char abort_cause_str[32];
++ if (crash_info_records[i].abort_cause) {
++ snprintf(abort_cause_str, sizeof(abort_cause_str), "%lld",
++ crash_info_records[i].abort_cause);
++ } else {
++ strncpy(abort_cause_str, "0", sizeof(abort_cause_str));
++ }
++ printf("MacCrashInfo%c%s%c%lu%c%s%c%s%c%s%c%s%c%s%c%s%c%s\n",
++ kOutputSeparator, crash_info_records[i].module_path.c_str(),
++ kOutputSeparator, crash_info_records[i].version,
++ kOutputSeparator, crash_info_records[i].message.c_str(),
++ kOutputSeparator, crash_info_records[i].signature_string.c_str(),
++ kOutputSeparator, crash_info_records[i].backtrace.c_str(),
++ kOutputSeparator, crash_info_records[i].message2.c_str(),
++ kOutputSeparator, thread_str,
++ kOutputSeparator, dialog_mode_str,
++ kOutputSeparator, abort_cause_str);
++ }
++
+ PrintModulesMachineReadable(process_state.modules());
+ PrintUnloadedModulesMachineReadable(process_state.unloaded_modules());
+
diff --git a/toolkit/crashreporter/breakpad-patches/21-thread-names.patch b/toolkit/crashreporter/breakpad-patches/21-thread-names.patch
new file mode 100644
index 0000000000..ea4dd67cd1
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-patches/21-thread-names.patch
@@ -0,0 +1,661 @@
+diff --git a/src/google_breakpad/common/minidump_format.h b/src/google_breakpad/common/minidump_format.h
+--- a/src/google_breakpad/common/minidump_format.h
++++ b/src/google_breakpad/common/minidump_format.h
+@@ -227,17 +227,18 @@ typedef struct {
+
+ /*
+ * DbgHelp.h
+ */
+
+
+ /* An MDRVA is an offset into the minidump file. The beginning of the
+ * MDRawHeader is at offset 0. */
+-typedef uint32_t MDRVA; /* RVA */
++typedef uint32_t MDRVA; /* RVA */
++typedef uint64_t MDRVA64; /* RVA64 */
+
+ typedef struct {
+ uint32_t data_size;
+ MDRVA rva;
+ } MDLocationDescriptor; /* MINIDUMP_LOCATION_DESCRIPTOR */
+
+
+ typedef struct {
+@@ -327,16 +328,18 @@ typedef enum {
+ MD_MISC_INFO_STREAM = 15, /* MDRawMiscInfo */
+ MD_MEMORY_INFO_LIST_STREAM = 16, /* MDRawMemoryInfoList */
+ MD_THREAD_INFO_LIST_STREAM = 17,
+ MD_HANDLE_OPERATION_LIST_STREAM = 18,
+ MD_TOKEN_STREAM = 19,
+ MD_JAVASCRIPT_DATA_STREAM = 20,
+ MD_SYSTEM_MEMORY_INFO_STREAM = 21,
+ MD_PROCESS_VM_COUNTERS_STREAM = 22,
++ MD_IPT_TRACE_STREAM = 23,
++ MD_THREAD_NAMES_STREAM = 24,
+ MD_LAST_RESERVED_STREAM = 0x0000ffff,
+
+ /* Breakpad extension types. 0x4767 = "Gg" */
+ MD_BREAKPAD_INFO_STREAM = 0x47670001, /* MDRawBreakpadInfo */
+ MD_ASSERTION_INFO_STREAM = 0x47670002, /* MDRawAssertionInfo */
+ /* These are additional minidump stream values which are specific to
+ * the linux breakpad implementation. */
+ MD_LINUX_CPU_INFO = 0x47670003, /* /proc/cpuinfo */
+@@ -1117,16 +1120,26 @@ typedef struct {
+ * module_path;
+ * message;
+ * signature_string;
+ * backtrace;
+ * message2; */
+ uint8_t data[0];
+ } MDRawMacCrashInfoRecord;
+
++typedef struct __attribute__((packed,aligned(4))) {
++ uint32_t thread_id;
++ MDRVA64 rva_of_thread_name;
++} MDRawThreadName;
++
++typedef struct {
++ uint32_t number_of_thread_names;
++ MDRawThreadName thread_names[0];
++} MDRawThreadNamesList;
++
+ /* This is the maximum supported size for each string in
+ * (MDRawMacCrashInfoRecord).data. If we encounter a string in the
+ * __crash_info section which seems larger than this, that's a sign of data
+ * corruption. */
+ #define MACCRASHINFO_STRING_MAXSIZE 8192
+
+ /* In principle there should only be one or two non-empty __DATA,__crash_info
+ * sections per process. But the __crash_info section is almost entirely
+diff --git a/src/google_breakpad/processor/call_stack.h b/src/google_breakpad/processor/call_stack.h
+--- a/src/google_breakpad/processor/call_stack.h
++++ b/src/google_breakpad/processor/call_stack.h
+@@ -41,21 +41,23 @@
+ // beginning with the innermost callee frame.
+ //
+ // Author: Mark Mentovai
+
+ #ifndef GOOGLE_BREAKPAD_PROCESSOR_CALL_STACK_H__
+ #define GOOGLE_BREAKPAD_PROCESSOR_CALL_STACK_H__
+
+ #include <cstdint>
++#include <string>
+ #include <vector>
+
+ namespace google_breakpad {
+
+ using std::vector;
++using std::string;
+
+ struct StackFrame;
+ template<typename T> class linked_ptr;
+
+ class CallStack {
+ public:
+ CallStack() { Clear(); }
+ ~CallStack();
+@@ -63,29 +65,33 @@ class CallStack {
+ // Resets the CallStack to its initial empty state
+ void Clear();
+
+ const vector<StackFrame*>* frames() const { return &frames_; }
+
+ // Set the TID associated with this call stack.
+ void set_tid(uint32_t tid) { tid_ = tid; }
+ void set_last_error(uint32_t last_error) { last_error_ = last_error; }
++ void set_name(const string& name) { name_ = name; }
+
+ uint32_t tid() const { return tid_; }
+ uint32_t last_error() const { return last_error_; }
++ const string name() const { return name_; }
+
+ private:
+ // Stackwalker is responsible for building the frames_ vector.
+ friend class Stackwalker;
+
+ // Storage for pushed frames.
+ vector<StackFrame*> frames_;
+
+ // The TID associated with this call stack. Default to 0 if it's not
+ // available.
+ uint32_t tid_;
+ // The last error the OS set for this thread (win32's GetLastError())
+ uint32_t last_error_;
++ // The name of this thread, empty if it's not available
++ string name_;
+ };
+
+ } // namespace google_breakpad
+
+ #endif // GOOGLE_BREAKPAD_PROCSSOR_CALL_STACK_H__
+diff --git a/src/google_breakpad/processor/minidump.h b/src/google_breakpad/processor/minidump.h
+--- a/src/google_breakpad/processor/minidump.h
++++ b/src/google_breakpad/processor/minidump.h
+@@ -1197,16 +1197,96 @@ class MinidumpMacCrashInfo : public Mini
+ bool ReadCrashInfoRecord(MDLocationDescriptor location,
+ uint32_t record_start_size);
+ bool Read(uint32_t expected_size);
+
+ string description_;
+ vector<crash_info_record_t> records_;
+ };
+
++// MinidumpThreadName wraps MDRawThreadName
++class MinidumpThreadName : public MinidumpObject {
++ public:
++ ~MinidumpThreadName() override;
++
++ const MDRawThreadName* thread_name() const {
++ if (valid_) {
++ return &thread_name_;
++ }
++
++ return NULL;
++ }
++
++ uint32_t thread_id() const {
++ if (valid_) {
++ return thread_name_.thread_id;
++ }
++
++ return 0;
++ }
++
++ string name() const;
++
++ // Print a human-readable representation of the object to stdout.
++ void Print();
++
++ protected:
++ explicit MinidumpThreadName(Minidump* minidump);
++
++ private:
++ // These objects are managed by MinidumpThreadNameList
++ friend class MinidumpThreadNamesList;
++
++ // This works like MinidumpStream::Read, but is driven by
++ // MinidumpThreadNameList.
++ bool Read(uint32_t expected_size);
++
++ // Reads the thread name. This is done separately from Read to
++ // allow contiguous reading of thread names by MinidumpThreadNameList.
++ bool ReadAuxiliaryData();
++
++ bool valid_;
++ MDRawThreadName thread_name_;
++ const string* name_;
++};
++
++
++// MinidumpThreadNamesList contains all the names for threads in a process
++// in the form of MinidumpThreadNames.
++class MinidumpThreadNamesList : public MinidumpStream {
++ public:
++ ~MinidumpThreadNamesList() override;
++
++ unsigned int name_count() const {
++ return valid_ ? name_count_ : 0;
++ }
++
++ const string GetNameForThreadId(uint32_t thread_id) const;
++
++ // Print a human-readable representation of the object to stdout.
++ void Print();
++
++ protected:
++ explicit MinidumpThreadNamesList(Minidump* minidump_);
++
++ private:
++ friend class Minidump;
++
++ typedef vector<MinidumpThreadName> MinidumpThreadNames;
++
++ static const uint32_t kStreamType = MD_THREAD_NAMES_STREAM;
++
++ bool Read(uint32_t expected_size_) override;
++
++ MinidumpThreadNames* thread_names_;
++ uint32_t name_count_;
++ bool valid_;
++
++ DISALLOW_COPY_AND_ASSIGN(MinidumpThreadNamesList);
++};
+
+ // Minidump is the user's interface to a minidump file. It wraps MDRawHeader
+ // and provides access to the minidump's top-level stream directory.
+ class Minidump {
+ public:
+ // path is the pathname of a file containing the minidump.
+ explicit Minidump(const string& path,
+ bool hexdump=false,
+@@ -1261,16 +1343,17 @@ class Minidump {
+ virtual MinidumpAssertion* GetAssertion();
+ virtual MinidumpSystemInfo* GetSystemInfo();
+ virtual MinidumpUnloadedModuleList* GetUnloadedModuleList();
+ virtual MinidumpMiscInfo* GetMiscInfo();
+ virtual MinidumpBreakpadInfo* GetBreakpadInfo();
+ virtual MinidumpMemoryInfoList* GetMemoryInfoList();
+ MinidumpCrashpadInfo* GetCrashpadInfo();
+ MinidumpMacCrashInfo* GetMacCrashInfo();
++ MinidumpThreadNamesList* GetThreadNamesList();
+
+ // The next method also calls GetStream, but is exclusive for Linux dumps.
+ virtual MinidumpLinuxMapsList *GetLinuxMapsList();
+
+ // The next set of methods are provided for users who wish to access
+ // data in minidump files directly, while leveraging the rest of
+ // this class and related classes to handle the basic minidump
+ // structure and known stream types.
+diff --git a/src/processor/call_stack.cc b/src/processor/call_stack.cc
+--- a/src/processor/call_stack.cc
++++ b/src/processor/call_stack.cc
+@@ -45,11 +45,12 @@ CallStack::~CallStack() {
+ void CallStack::Clear() {
+ for (vector<StackFrame *>::const_iterator iterator = frames_.begin();
+ iterator != frames_.end();
+ ++iterator) {
+ delete *iterator;
+ }
+ tid_ = 0;
+ last_error_ = 0;
++ name_ = "";
+ }
+
+ } // namespace google_breakpad
+diff --git a/src/processor/minidump.cc b/src/processor/minidump.cc
+--- a/src/processor/minidump.cc
++++ b/src/processor/minidump.cc
+@@ -5724,16 +5724,226 @@ MinidumpCrashpadInfo* Minidump::GetCrash
+ return GetStream(&crashpad_info);
+ }
+
+ MinidumpMacCrashInfo* Minidump::GetMacCrashInfo() {
+ MinidumpMacCrashInfo* mac_crash_info;
+ return GetStream(&mac_crash_info);
+ }
+
++MinidumpThreadNamesList* Minidump::GetThreadNamesList() {
++ MinidumpThreadNamesList* thread_names_list;
++ return GetStream(&thread_names_list);
++}
++
++//
++// MinidumpThreadName
++//
++
++
++MinidumpThreadName::MinidumpThreadName(Minidump* minidump)
++ : MinidumpObject(minidump),
++ valid_(false),
++ thread_name_(),
++ name_(NULL) {
++
++}
++
++MinidumpThreadName::~MinidumpThreadName() {
++ ;
++}
++
++void MinidumpThreadName::Print() {
++ if (!valid_) {
++ BPLOG(ERROR) << "MinidumpThreadName cannot print invalid data";
++ return;
++ }
++
++ printf("MDRawThreadName\n");
++ printf(" thread_id = 0x%x\n",
++ thread_name_.thread_id);
++ printf(" rva_of_thread_name = 0x%" PRIx64 "\n",
++ thread_name_.rva_of_thread_name);
++
++ printf(" (name) = \"%s\"\n", name().c_str());
++ printf("\n");
++}
++
++string MinidumpThreadName::name() const {
++ if (!valid_) {
++ BPLOG(ERROR) << "Invalid MinidumpThreadName for name";
++ return "";
++ }
++
++ return *name_;
++}
++
++bool MinidumpThreadName::Read(uint32_t expected_size) {
++
++ delete name_;
++
++ if (expected_size < sizeof(thread_name_)) {
++ BPLOG(ERROR) << "MinidumpThreadName expected size is less than size "
++ << "of struct " << expected_size << " < "
++ << sizeof(thread_name_);
++ return false;
++ }
++
++ if (!minidump_->ReadBytes(&thread_name_, sizeof(thread_name_))) {
++ BPLOG(ERROR) << "MinidumpThreadName cannot read name";
++ return false;
++ }
++
++ if (expected_size > sizeof(thread_name_)) {
++ uint32_t thread_name_bytes_remaining = expected_size - sizeof(thread_name_);
++ off_t pos = minidump_->Tell();
++ if (!minidump_->SeekSet(pos + thread_name_bytes_remaining)) {
++ BPLOG(ERROR) << "MinidumpThreadName unable to seek to end of name";
++ return false;
++ }
++ }
++
++ if (minidump_->swap()) {
++ Swap(&thread_name_.thread_id);
++ uint64_t rva_of_thread_name;
++ memcpy(&rva_of_thread_name, &thread_name_.rva_of_thread_name, sizeof(uint64_t));
++ Swap(&rva_of_thread_name);
++ memcpy(&thread_name_.rva_of_thread_name, &rva_of_thread_name, sizeof(uint64_t));
++ }
++
++ return true;
++}
++
++bool MinidumpThreadName::ReadAuxiliaryData() {
++ // Each thread must have a name string.
++ name_ = minidump_->ReadString(thread_name_.rva_of_thread_name);
++ if (!name_) {
++ BPLOG(ERROR) << "MinidumpThreadName could not read name";
++ valid_ = false;
++ return false;
++ }
++
++ // At this point, we have enough info for the name to be valid.
++ valid_ = true;
++ return true;
++}
++
++//
++// MinidumpThreadNamesList
++//
++
++
++MinidumpThreadNamesList::MinidumpThreadNamesList(Minidump* minidump)
++ : MinidumpStream(minidump),
++ thread_names_(NULL),
++ name_count_(0),
++ valid_(false) {
++ ;
++}
++
++MinidumpThreadNamesList::~MinidumpThreadNamesList() {
++ delete thread_names_;
++}
++
++const string MinidumpThreadNamesList::GetNameForThreadId(uint32_t thread_id) const {
++ if (valid_) {
++ for (unsigned int name_index = 0;
++ name_index < name_count_;
++ ++name_index) {
++ const MinidumpThreadName& thread_name = (*thread_names_)[name_index];
++ if (thread_name.thread_id() == thread_id) {
++ return thread_name.name();
++ }
++ }
++ }
++
++ return "";
++}
++
++void MinidumpThreadNamesList::Print() {
++ if (!valid_) {
++ BPLOG(ERROR) << "MinidumpThreadNamesList cannot print invalid data";
++ return;
++ }
++
++ printf("MinidumpThreadNamesList\n");
++ printf(" name_count = %d\n", name_count_);
++ printf("\n");
++
++ for (unsigned int name_index = 0;
++ name_index < name_count_;
++ ++name_index) {
++ printf("thread_name[%d]\n", name_index);
++
++ (*thread_names_)[name_index].Print();
++ }
++}
++
++bool MinidumpThreadNamesList::Read(uint32_t expected_size) {
++ delete thread_names_;
++ thread_names_ = NULL;
++ name_count_ = 0;
++
++ valid_ = false;
++
++ uint32_t number_of_thread_names;
++ if (!minidump_->ReadBytes(&number_of_thread_names, sizeof(number_of_thread_names))) {
++ BPLOG(ERROR) << "MinidumpThreadNamesList could not read the number of thread names";
++ return false;
++ }
++
++ if (minidump_->swap()) {
++ Swap(&number_of_thread_names);
++ }
++
++ if (expected_size !=
++ sizeof(number_of_thread_names) + (sizeof(MDRawThreadName) * number_of_thread_names)) {
++ BPLOG(ERROR) << "MinidumpThreadNamesList expected_size mismatch " <<
++ expected_size << " != " << sizeof(number_of_thread_names) << " + (" <<
++ sizeof(MDRawThreadName) << " * " << number_of_thread_names << ")";
++ return false;
++ }
++
++ if (number_of_thread_names != 0) {
++ scoped_ptr<MinidumpThreadNames> thread_names(
++ new MinidumpThreadNames(number_of_thread_names,
++ MinidumpThreadName(minidump_)));
++
++ for (unsigned int name_index = 0;
++ name_index < number_of_thread_names;
++ ++name_index) {
++ MinidumpThreadName* thread_name = &(*thread_names)[name_index];
++
++ if (!thread_name->Read(sizeof(MDRawThreadName))) {
++ BPLOG(ERROR) << "MinidumpThreadNamesList could not read name " <<
++ name_index << "/" << number_of_thread_names;
++ return false;
++ }
++ }
++
++ for (unsigned int name_index = 0;
++ name_index < number_of_thread_names;
++ ++name_index) {
++ MinidumpThreadName* thread_name = &(*thread_names)[name_index];
++
++ if (!thread_name->ReadAuxiliaryData()) {
++ BPLOG(ERROR) << "MinidumpThreadNamesList could not read required "
++ "auxiliary data for thread name " <<
++ name_index << "/" << number_of_thread_names;
++ return false;
++ }
++ }
++ thread_names_ = thread_names.release();
++ }
++
++ name_count_ = number_of_thread_names;
++ valid_ = true;
++ return true;
++}
++
+ static const char* get_stream_name(uint32_t stream_type) {
+ switch (stream_type) {
+ case MD_UNUSED_STREAM:
+ return "MD_UNUSED_STREAM";
+ case MD_RESERVED_STREAM_0:
+ return "MD_RESERVED_STREAM_0";
+ case MD_RESERVED_STREAM_1:
+ return "MD_RESERVED_STREAM_1";
+@@ -5772,16 +5982,20 @@ static const char* get_stream_name(uint3
+ case MD_TOKEN_STREAM:
+ return "MD_TOKEN_STREAM";
+ case MD_JAVASCRIPT_DATA_STREAM:
+ return "MD_JAVASCRIPT_DATA_STREAM";
+ case MD_SYSTEM_MEMORY_INFO_STREAM:
+ return "MD_SYSTEM_MEMORY_INFO_STREAM";
+ case MD_PROCESS_VM_COUNTERS_STREAM:
+ return "MD_PROCESS_VM_COUNTERS_STREAM";
++ case MD_IPT_TRACE_STREAM:
++ return "MD_IPT_TRACE_STREAM";
++ case MD_THREAD_NAMES_STREAM:
++ return "MD_THREAD_NAMES_STREAM";
+ case MD_LAST_RESERVED_STREAM:
+ return "MD_LAST_RESERVED_STREAM";
+ case MD_BREAKPAD_INFO_STREAM:
+ return "MD_BREAKPAD_INFO_STREAM";
+ case MD_ASSERTION_INFO_STREAM:
+ return "MD_ASSERTION_INFO_STREAM";
+ case MD_LINUX_CPU_INFO:
+ return "MD_LINUX_CPU_INFO";
+diff --git a/src/processor/minidump_dump.cc b/src/processor/minidump_dump.cc
+--- a/src/processor/minidump_dump.cc
++++ b/src/processor/minidump_dump.cc
+@@ -49,16 +49,17 @@ using google_breakpad::MinidumpUnloadedM
+ using google_breakpad::MinidumpMemoryInfoList;
+ using google_breakpad::MinidumpMemoryList;
+ using google_breakpad::MinidumpException;
+ using google_breakpad::MinidumpAssertion;
+ using google_breakpad::MinidumpSystemInfo;
+ using google_breakpad::MinidumpMiscInfo;
+ using google_breakpad::MinidumpBreakpadInfo;
+ using google_breakpad::MinidumpCrashpadInfo;
++using google_breakpad::MinidumpThreadNamesList;
+
+ struct Options {
+ Options()
+ : minidumpPath(), hexdump(false), hexdump_width(16) {}
+
+ string minidumpPath;
+ bool hexdump;
+ unsigned int hexdump_width;
+@@ -197,16 +198,21 @@ static bool PrintMinidumpDump(const Opti
+ }
+
+ MinidumpCrashpadInfo *crashpad_info = minidump.GetCrashpadInfo();
+ if (crashpad_info) {
+ // Crashpad info is optional, so don't treat absence as an error.
+ crashpad_info->Print();
+ }
+
++ MinidumpThreadNamesList *thread_names_list = minidump.GetThreadNamesList();
++ if (thread_names_list) {
++ thread_names_list->Print();
++ }
++
+ DumpRawStream(&minidump,
+ MD_LINUX_CMD_LINE,
+ "MD_LINUX_CMD_LINE",
+ &errors);
+ DumpRawStream(&minidump,
+ MD_LINUX_ENVIRON,
+ "MD_LINUX_ENVIRON",
+ &errors);
+diff --git a/src/processor/minidump_processor.cc b/src/processor/minidump_processor.cc
+--- a/src/processor/minidump_processor.cc
++++ b/src/processor/minidump_processor.cc
+@@ -173,16 +173,22 @@ ProcessResult MinidumpProcessor::Process
+ }
+
+ MinidumpMemoryList *memory_list = dump->GetMemoryList();
+ if (memory_list) {
+ BPLOG(INFO) << "Found " << memory_list->region_count()
+ << " memory regions.";
+ }
+
++ MinidumpThreadNamesList* thread_names_list = dump->GetThreadNamesList();
++ if (thread_names_list) {
++ BPLOG(INFO) << "Found " << thread_names_list->name_count()
++ << " thread names.";
++ }
++
+ MinidumpThreadList *threads = dump->GetThreadList();
+ if (!threads) {
+ BPLOG(ERROR) << "Minidump " << dump->path() << " has no thread list";
+ return PROCESS_ERROR_NO_THREAD_LIST;
+ }
+
+ BPLOG(INFO) << "Minidump " << dump->path() << " has " <<
+ (has_cpu_info ? "" : "no ") << "CPU info, " <<
+@@ -308,16 +314,19 @@ ProcessResult MinidumpProcessor::Process
+ } else {
+ // Threads with missing CPU contexts will hit this, but
+ // don't abort processing the rest of the dump just for
+ // one bad thread.
+ BPLOG(ERROR) << "No stackwalker for " << thread_string;
+ }
+ stack->set_tid(thread_id);
+ stack->set_last_error(thread->GetLastError());
++ if (thread_names_list) {
++ stack->set_name(thread_names_list->GetNameForThreadId(thread_id));
++ }
+ process_state->threads_.push_back(stack.release());
+ process_state->thread_memory_regions_.push_back(thread_memory);
+ }
+
+ if (interrupted) {
+ BPLOG(INFO) << "Processing interrupted for " << dump->path();
+ return PROCESS_SYMBOL_SUPPLIER_INTERRUPTED;
+ }
+diff --git a/src/processor/stackwalk_common.cc b/src/processor/stackwalk_common.cc
+--- a/src/processor/stackwalk_common.cc
++++ b/src/processor/stackwalk_common.cc
+@@ -876,35 +876,45 @@ void PrintProcessState(const ProcessStat
+ printf("\n");
+ printf("Application-specific information:\n");
+ printf("%s", process_state.mac_crash_info().c_str());
+ }
+
+ // If the thread that requested the dump is known, print it first.
+ int requesting_thread = process_state.requesting_thread();
+ if (requesting_thread != -1) {
+- printf("\n");
+- printf("Thread %d (%s)\n",
+- requesting_thread,
+- process_state.crashed() ? "crashed" :
+- "requested dump, did not crash");
+- PrintStack(process_state.threads()->at(requesting_thread), cpu,
++ const CallStack* requesting_thread_callstack =
++ process_state.threads()->at(requesting_thread);
++ printf("\n"
++ "Thread %d (%s)",
++ requesting_thread,
++ process_state.crashed() ? "crashed" :
++ "requested dump, did not crash");
++ if (!requesting_thread_callstack->name().empty()) {
++ printf(" - %s", requesting_thread_callstack->name().c_str());
++ }
++ PrintStack(requesting_thread_callstack, cpu,
+ output_stack_contents,
+ process_state.thread_memory_regions()->at(requesting_thread),
+ process_state.modules(), resolver);
+ }
+
+ // Print all of the threads in the dump.
+ int thread_count = process_state.threads()->size();
+ for (int thread_index = 0; thread_index < thread_count; ++thread_index) {
+ if (thread_index != requesting_thread) {
+ // Don't print the crash thread again, it was already printed.
++ const CallStack* callstack = process_state.threads()->at(thread_index);
++ printf("\n"
++ "Thread %d", thread_index);
++ if (!callstack->name().empty()) {
++ printf(" - %s", callstack->name().c_str());
++ }
+ printf("\n");
+- printf("Thread %d\n", thread_index);
+- PrintStack(process_state.threads()->at(thread_index), cpu,
++ PrintStack(callstack, cpu,
+ output_stack_contents,
+ process_state.thread_memory_regions()->at(thread_index),
+ process_state.modules(), resolver);
+ }
+ }
+
+ PrintModules(process_state.modules(),
+ process_state.modules_without_symbols(),
diff --git a/toolkit/crashreporter/breakpad-patches/22-winerror-codes.patch b/toolkit/crashreporter/breakpad-patches/22-winerror-codes.patch
new file mode 100644
index 0000000000..f0845366dc
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-patches/22-winerror-codes.patch
@@ -0,0 +1,22069 @@
+diff --git a/src/google_breakpad/common/minidump_exception_win32.h b/src/google_breakpad/common/minidump_exception_win32.h
+--- a/src/google_breakpad/common/minidump_exception_win32.h
++++ b/src/google_breakpad/common/minidump_exception_win32.h
+@@ -2925,9 +2925,2651 @@ typedef enum {
+ MD_FAST_FAIL_WIN_UNEXPECTED_HOST_BEHAVIOR = 58,
+ MD_FAST_FAIL_WIN_FLAGS_CORRUPTION = 59,
+ MD_FAST_FAIL_WIN_VEH_CORRUPTION = 60,
+ MD_FAST_FAIL_WIN_ETW_CORRUPTION = 61,
+ MD_FAST_FAIL_WIN_RIO_ABORT = 62,
+ MD_FAST_FAIL_WIN_INVALID_PFN = 63,
+ } MDFastFailWin;
+
++/* For various (MDException).exception_information entries. This describes the
++* underlying reason for the crash. These values come from winerror.h.
++ *
++ * The content of this enum was created from winnt.h in the 10 SDK
++ * (version 10.0.19041.0) with
++ *
++ * egrep -o '#define ERROR_[A-Z_0-9]+\s+[0-9]+L' winerror.h
++ * | tr -d '\r'
++ * | sed -r 's@#define ERROR_([A-Z_0-9]+)\s+([0-9]+)L@\2 \1@'
++ * | sort -n
++ * | sed -r 's@([0-9]+) ([A-Z_0-9]+)@ MD_ERROR_WIN_\2 = \1,@' */
++typedef enum {
++ MD_ERROR_WIN_SUCCESS = 0,
++ MD_ERROR_WIN_INVALID_FUNCTION = 1,
++ MD_ERROR_WIN_FILE_NOT_FOUND = 2,
++ MD_ERROR_WIN_PATH_NOT_FOUND = 3,
++ MD_ERROR_WIN_TOO_MANY_OPEN_FILES = 4,
++ MD_ERROR_WIN_ACCESS_DENIED = 5,
++ MD_ERROR_WIN_INVALID_HANDLE = 6,
++ MD_ERROR_WIN_ARENA_TRASHED = 7,
++ MD_ERROR_WIN_NOT_ENOUGH_MEMORY = 8,
++ MD_ERROR_WIN_INVALID_BLOCK = 9,
++ MD_ERROR_WIN_BAD_ENVIRONMENT = 10,
++ MD_ERROR_WIN_BAD_FORMAT = 11,
++ MD_ERROR_WIN_INVALID_ACCESS = 12,
++ MD_ERROR_WIN_INVALID_DATA = 13,
++ MD_ERROR_WIN_OUTOFMEMORY = 14,
++ MD_ERROR_WIN_INVALID_DRIVE = 15,
++ MD_ERROR_WIN_CURRENT_DIRECTORY = 16,
++ MD_ERROR_WIN_NOT_SAME_DEVICE = 17,
++ MD_ERROR_WIN_NO_MORE_FILES = 18,
++ MD_ERROR_WIN_WRITE_PROTECT = 19,
++ MD_ERROR_WIN_BAD_UNIT = 20,
++ MD_ERROR_WIN_NOT_READY = 21,
++ MD_ERROR_WIN_BAD_COMMAND = 22,
++ MD_ERROR_WIN_CRC = 23,
++ MD_ERROR_WIN_BAD_LENGTH = 24,
++ MD_ERROR_WIN_SEEK = 25,
++ MD_ERROR_WIN_NOT_DOS_DISK = 26,
++ MD_ERROR_WIN_SECTOR_NOT_FOUND = 27,
++ MD_ERROR_WIN_OUT_OF_PAPER = 28,
++ MD_ERROR_WIN_WRITE_FAULT = 29,
++ MD_ERROR_WIN_READ_FAULT = 30,
++ MD_ERROR_WIN_GEN_FAILURE = 31,
++ MD_ERROR_WIN_SHARING_VIOLATION = 32,
++ MD_ERROR_WIN_LOCK_VIOLATION = 33,
++ MD_ERROR_WIN_WRONG_DISK = 34,
++ MD_ERROR_WIN_SHARING_BUFFER_EXCEEDED = 36,
++ MD_ERROR_WIN_HANDLE_EOF = 38,
++ MD_ERROR_WIN_HANDLE_DISK_FULL = 39,
++ MD_ERROR_WIN_NOT_SUPPORTED = 50,
++ MD_ERROR_WIN_REM_NOT_LIST = 51,
++ MD_ERROR_WIN_DUP_NAME = 52,
++ MD_ERROR_WIN_BAD_NETPATH = 53,
++ MD_ERROR_WIN_NETWORK_BUSY = 54,
++ MD_ERROR_WIN_DEV_NOT_EXIST = 55,
++ MD_ERROR_WIN_TOO_MANY_CMDS = 56,
++ MD_ERROR_WIN_ADAP_HDW_ERR = 57,
++ MD_ERROR_WIN_BAD_NET_RESP = 58,
++ MD_ERROR_WIN_UNEXP_NET_ERR = 59,
++ MD_ERROR_WIN_BAD_REM_ADAP = 60,
++ MD_ERROR_WIN_PRINTQ_FULL = 61,
++ MD_ERROR_WIN_NO_SPOOL_SPACE = 62,
++ MD_ERROR_WIN_PRINT_CANCELLED = 63,
++ MD_ERROR_WIN_NETNAME_DELETED = 64,
++ MD_ERROR_WIN_NETWORK_ACCESS_DENIED = 65,
++ MD_ERROR_WIN_BAD_DEV_TYPE = 66,
++ MD_ERROR_WIN_BAD_NET_NAME = 67,
++ MD_ERROR_WIN_TOO_MANY_NAMES = 68,
++ MD_ERROR_WIN_TOO_MANY_SESS = 69,
++ MD_ERROR_WIN_SHARING_PAUSED = 70,
++ MD_ERROR_WIN_REQ_NOT_ACCEP = 71,
++ MD_ERROR_WIN_REDIR_PAUSED = 72,
++ MD_ERROR_WIN_FILE_EXISTS = 80,
++ MD_ERROR_WIN_CANNOT_MAKE = 82,
++ MD_ERROR_WIN_FAIL_I24 = 83,
++ MD_ERROR_WIN_OUT_OF_STRUCTURES = 84,
++ MD_ERROR_WIN_ALREADY_ASSIGNED = 85,
++ MD_ERROR_WIN_INVALID_PASSWORD = 86,
++ MD_ERROR_WIN_INVALID_PARAMETER = 87,
++ MD_ERROR_WIN_NET_WRITE_FAULT = 88,
++ MD_ERROR_WIN_NO_PROC_SLOTS = 89,
++ MD_ERROR_WIN_TOO_MANY_SEMAPHORES = 100,
++ MD_ERROR_WIN_EXCL_SEM_ALREADY_OWNED = 101,
++ MD_ERROR_WIN_SEM_IS_SET = 102,
++ MD_ERROR_WIN_TOO_MANY_SEM_REQUESTS = 103,
++ MD_ERROR_WIN_INVALID_AT_INTERRUPT_TIME = 104,
++ MD_ERROR_WIN_SEM_OWNER_DIED = 105,
++ MD_ERROR_WIN_SEM_USER_LIMIT = 106,
++ MD_ERROR_WIN_DISK_CHANGE = 107,
++ MD_ERROR_WIN_DRIVE_LOCKED = 108,
++ MD_ERROR_WIN_BROKEN_PIPE = 109,
++ MD_ERROR_WIN_OPEN_FAILED = 110,
++ MD_ERROR_WIN_BUFFER_OVERFLOW = 111,
++ MD_ERROR_WIN_DISK_FULL = 112,
++ MD_ERROR_WIN_NO_MORE_SEARCH_HANDLES = 113,
++ MD_ERROR_WIN_INVALID_TARGET_HANDLE = 114,
++ MD_ERROR_WIN_INVALID_CATEGORY = 117,
++ MD_ERROR_WIN_INVALID_VERIFY_SWITCH = 118,
++ MD_ERROR_WIN_BAD_DRIVER_LEVEL = 119,
++ MD_ERROR_WIN_CALL_NOT_IMPLEMENTED = 120,
++ MD_ERROR_WIN_SEM_TIMEOUT = 121,
++ MD_ERROR_WIN_INSUFFICIENT_BUFFER = 122,
++ MD_ERROR_WIN_INVALID_NAME = 123,
++ MD_ERROR_WIN_INVALID_LEVEL = 124,
++ MD_ERROR_WIN_NO_VOLUME_LABEL = 125,
++ MD_ERROR_WIN_MOD_NOT_FOUND = 126,
++ MD_ERROR_WIN_PROC_NOT_FOUND = 127,
++ MD_ERROR_WIN_WAIT_NO_CHILDREN = 128,
++ MD_ERROR_WIN_CHILD_NOT_COMPLETE = 129,
++ MD_ERROR_WIN_DIRECT_ACCESS_HANDLE = 130,
++ MD_ERROR_WIN_NEGATIVE_SEEK = 131,
++ MD_ERROR_WIN_SEEK_ON_DEVICE = 132,
++ MD_ERROR_WIN_IS_JOIN_TARGET = 133,
++ MD_ERROR_WIN_IS_JOINED = 134,
++ MD_ERROR_WIN_IS_SUBSTED = 135,
++ MD_ERROR_WIN_NOT_JOINED = 136,
++ MD_ERROR_WIN_NOT_SUBSTED = 137,
++ MD_ERROR_WIN_JOIN_TO_JOIN = 138,
++ MD_ERROR_WIN_SUBST_TO_SUBST = 139,
++ MD_ERROR_WIN_JOIN_TO_SUBST = 140,
++ MD_ERROR_WIN_SUBST_TO_JOIN = 141,
++ MD_ERROR_WIN_BUSY_DRIVE = 142,
++ MD_ERROR_WIN_SAME_DRIVE = 143,
++ MD_ERROR_WIN_DIR_NOT_ROOT = 144,
++ MD_ERROR_WIN_DIR_NOT_EMPTY = 145,
++ MD_ERROR_WIN_IS_SUBST_PATH = 146,
++ MD_ERROR_WIN_IS_JOIN_PATH = 147,
++ MD_ERROR_WIN_PATH_BUSY = 148,
++ MD_ERROR_WIN_IS_SUBST_TARGET = 149,
++ MD_ERROR_WIN_SYSTEM_TRACE = 150,
++ MD_ERROR_WIN_INVALID_EVENT_COUNT = 151,
++ MD_ERROR_WIN_TOO_MANY_MUXWAITERS = 152,
++ MD_ERROR_WIN_INVALID_LIST_FORMAT = 153,
++ MD_ERROR_WIN_LABEL_TOO_LONG = 154,
++ MD_ERROR_WIN_TOO_MANY_TCBS = 155,
++ MD_ERROR_WIN_SIGNAL_REFUSED = 156,
++ MD_ERROR_WIN_DISCARDED = 157,
++ MD_ERROR_WIN_NOT_LOCKED = 158,
++ MD_ERROR_WIN_BAD_THREADID_ADDR = 159,
++ MD_ERROR_WIN_BAD_ARGUMENTS = 160,
++ MD_ERROR_WIN_BAD_PATHNAME = 161,
++ MD_ERROR_WIN_SIGNAL_PENDING = 162,
++ MD_ERROR_WIN_MAX_THRDS_REACHED = 164,
++ MD_ERROR_WIN_LOCK_FAILED = 167,
++ MD_ERROR_WIN_BUSY = 170,
++ MD_ERROR_WIN_DEVICE_SUPPORT_IN_PROGRESS = 171,
++ MD_ERROR_WIN_CANCEL_VIOLATION = 173,
++ MD_ERROR_WIN_ATOMIC_LOCKS_NOT_SUPPORTED = 174,
++ MD_ERROR_WIN_INVALID_SEGMENT_NUMBER = 180,
++ MD_ERROR_WIN_INVALID_ORDINAL = 182,
++ MD_ERROR_WIN_ALREADY_EXISTS = 183,
++ MD_ERROR_WIN_INVALID_FLAG_NUMBER = 186,
++ MD_ERROR_WIN_SEM_NOT_FOUND = 187,
++ MD_ERROR_WIN_INVALID_STARTING_CODESEG = 188,
++ MD_ERROR_WIN_INVALID_STACKSEG = 189,
++ MD_ERROR_WIN_INVALID_MODULETYPE = 190,
++ MD_ERROR_WIN_INVALID_EXE_SIGNATURE = 191,
++ MD_ERROR_WIN_EXE_MARKED_INVALID = 192,
++ MD_ERROR_WIN_BAD_EXE_FORMAT = 193,
++ MD_ERROR_WIN_INVALID_MINALLOCSIZE = 195,
++ MD_ERROR_WIN_DYNLINK_FROM_INVALID_RING = 196,
++ MD_ERROR_WIN_IOPL_NOT_ENABLED = 197,
++ MD_ERROR_WIN_INVALID_SEGDPL = 198,
++ MD_ERROR_WIN_RING2SEG_MUST_BE_MOVABLE = 200,
++ MD_ERROR_WIN_RELOC_CHAIN_XEEDS_SEGLIM = 201,
++ MD_ERROR_WIN_INFLOOP_IN_RELOC_CHAIN = 202,
++ MD_ERROR_WIN_ENVVAR_NOT_FOUND = 203,
++ MD_ERROR_WIN_NO_SIGNAL_SENT = 205,
++ MD_ERROR_WIN_FILENAME_EXCED_RANGE = 206,
++ MD_ERROR_WIN_RING2_STACK_IN_USE = 207,
++ MD_ERROR_WIN_META_EXPANSION_TOO_LONG = 208,
++ MD_ERROR_WIN_INVALID_SIGNAL_NUMBER = 209,
++ MD_ERROR_WIN_THREAD_1_INACTIVE = 210,
++ MD_ERROR_WIN_LOCKED = 212,
++ MD_ERROR_WIN_TOO_MANY_MODULES = 214,
++ MD_ERROR_WIN_NESTING_NOT_ALLOWED = 215,
++ MD_ERROR_WIN_EXE_MACHINE_TYPE_MISMATCH = 216,
++ MD_ERROR_WIN_EXE_CANNOT_MODIFY_SIGNED_BINARY = 217,
++ MD_ERROR_WIN_EXE_CANNOT_MODIFY_STRONG_SIGNED_BINARY = 218,
++ MD_ERROR_WIN_FILE_CHECKED_OUT = 220,
++ MD_ERROR_WIN_CHECKOUT_REQUIRED = 221,
++ MD_ERROR_WIN_BAD_FILE_TYPE = 222,
++ MD_ERROR_WIN_FILE_TOO_LARGE = 223,
++ MD_ERROR_WIN_FORMS_AUTH_REQUIRED = 224,
++ MD_ERROR_WIN_VIRUS_INFECTED = 225,
++ MD_ERROR_WIN_VIRUS_DELETED = 226,
++ MD_ERROR_WIN_PIPE_LOCAL = 229,
++ MD_ERROR_WIN_BAD_PIPE = 230,
++ MD_ERROR_WIN_PIPE_BUSY = 231,
++ MD_ERROR_WIN_NO_DATA = 232,
++ MD_ERROR_WIN_PIPE_NOT_CONNECTED = 233,
++ MD_ERROR_WIN_MORE_DATA = 234,
++ MD_ERROR_WIN_NO_WORK_DONE = 235,
++ MD_ERROR_WIN_VC_DISCONNECTED = 240,
++ MD_ERROR_WIN_INVALID_EA_NAME = 254,
++ MD_ERROR_WIN_EA_LIST_INCONSISTENT = 255,
++ MD_ERROR_WIN_NO_MORE_ITEMS = 259,
++ MD_ERROR_WIN_CANNOT_COPY = 266,
++ MD_ERROR_WIN_DIRECTORY = 267,
++ MD_ERROR_WIN_EAS_DIDNT_FIT = 275,
++ MD_ERROR_WIN_EA_FILE_CORRUPT = 276,
++ MD_ERROR_WIN_EA_TABLE_FULL = 277,
++ MD_ERROR_WIN_INVALID_EA_HANDLE = 278,
++ MD_ERROR_WIN_EAS_NOT_SUPPORTED = 282,
++ MD_ERROR_WIN_NOT_OWNER = 288,
++ MD_ERROR_WIN_TOO_MANY_POSTS = 298,
++ MD_ERROR_WIN_PARTIAL_COPY = 299,
++ MD_ERROR_WIN_OPLOCK_NOT_GRANTED = 300,
++ MD_ERROR_WIN_INVALID_OPLOCK_PROTOCOL = 301,
++ MD_ERROR_WIN_DISK_TOO_FRAGMENTED = 302,
++ MD_ERROR_WIN_DELETE_PENDING = 303,
++ MD_ERROR_WIN_INCOMPATIBLE_WITH_GLOBAL_SHORT_NAME_REGISTRY_SETTING = 304,
++ MD_ERROR_WIN_SHORT_NAMES_NOT_ENABLED_ON_VOLUME = 305,
++ MD_ERROR_WIN_SECURITY_STREAM_IS_INCONSISTENT = 306,
++ MD_ERROR_WIN_INVALID_LOCK_RANGE = 307,
++ MD_ERROR_WIN_IMAGE_SUBSYSTEM_NOT_PRESENT = 308,
++ MD_ERROR_WIN_NOTIFICATION_GUID_ALREADY_DEFINED = 309,
++ MD_ERROR_WIN_INVALID_EXCEPTION_HANDLER = 310,
++ MD_ERROR_WIN_DUPLICATE_PRIVILEGES = 311,
++ MD_ERROR_WIN_NO_RANGES_PROCESSED = 312,
++ MD_ERROR_WIN_NOT_ALLOWED_ON_SYSTEM_FILE = 313,
++ MD_ERROR_WIN_DISK_RESOURCES_EXHAUSTED = 314,
++ MD_ERROR_WIN_INVALID_TOKEN = 315,
++ MD_ERROR_WIN_DEVICE_FEATURE_NOT_SUPPORTED = 316,
++ MD_ERROR_WIN_MR_MID_NOT_FOUND = 317,
++ MD_ERROR_WIN_SCOPE_NOT_FOUND = 318,
++ MD_ERROR_WIN_UNDEFINED_SCOPE = 319,
++ MD_ERROR_WIN_INVALID_CAP = 320,
++ MD_ERROR_WIN_DEVICE_UNREACHABLE = 321,
++ MD_ERROR_WIN_DEVICE_NO_RESOURCES = 322,
++ MD_ERROR_WIN_DATA_CHECKSUM_ERROR = 323,
++ MD_ERROR_WIN_INTERMIXED_KERNEL_EA_OPERATION = 324,
++ MD_ERROR_WIN_FILE_LEVEL_TRIM_NOT_SUPPORTED = 326,
++ MD_ERROR_WIN_OFFSET_ALIGNMENT_VIOLATION = 327,
++ MD_ERROR_WIN_INVALID_FIELD_IN_PARAMETER_LIST = 328,
++ MD_ERROR_WIN_OPERATION_IN_PROGRESS = 329,
++ MD_ERROR_WIN_BAD_DEVICE_PATH = 330,
++ MD_ERROR_WIN_TOO_MANY_DESCRIPTORS = 331,
++ MD_ERROR_WIN_SCRUB_DATA_DISABLED = 332,
++ MD_ERROR_WIN_NOT_REDUNDANT_STORAGE = 333,
++ MD_ERROR_WIN_RESIDENT_FILE_NOT_SUPPORTED = 334,
++ MD_ERROR_WIN_COMPRESSED_FILE_NOT_SUPPORTED = 335,
++ MD_ERROR_WIN_DIRECTORY_NOT_SUPPORTED = 336,
++ MD_ERROR_WIN_NOT_READ_FROM_COPY = 337,
++ MD_ERROR_WIN_FT_WRITE_FAILURE = 338,
++ MD_ERROR_WIN_FT_DI_SCAN_REQUIRED = 339,
++ MD_ERROR_WIN_INVALID_KERNEL_INFO_VERSION = 340,
++ MD_ERROR_WIN_INVALID_PEP_INFO_VERSION = 341,
++ MD_ERROR_WIN_OBJECT_NOT_EXTERNALLY_BACKED = 342,
++ MD_ERROR_WIN_EXTERNAL_BACKING_PROVIDER_UNKNOWN = 343,
++ MD_ERROR_WIN_COMPRESSION_NOT_BENEFICIAL = 344,
++ MD_ERROR_WIN_STORAGE_TOPOLOGY_ID_MISMATCH = 345,
++ MD_ERROR_WIN_BLOCKED_BY_PARENTAL_CONTROLS = 346,
++ MD_ERROR_WIN_BLOCK_TOO_MANY_REFERENCES = 347,
++ MD_ERROR_WIN_MARKED_TO_DISALLOW_WRITES = 348,
++ MD_ERROR_WIN_ENCLAVE_FAILURE = 349,
++ MD_ERROR_WIN_FAIL_NOACTION_REBOOT = 350,
++ MD_ERROR_WIN_FAIL_SHUTDOWN = 351,
++ MD_ERROR_WIN_FAIL_RESTART = 352,
++ MD_ERROR_WIN_MAX_SESSIONS_REACHED = 353,
++ MD_ERROR_WIN_NETWORK_ACCESS_DENIED_EDP = 354,
++ MD_ERROR_WIN_DEVICE_HINT_NAME_BUFFER_TOO_SMALL = 355,
++ MD_ERROR_WIN_EDP_POLICY_DENIES_OPERATION = 356,
++ MD_ERROR_WIN_EDP_DPL_POLICY_CANT_BE_SATISFIED = 357,
++ MD_ERROR_WIN_CLOUD_FILE_SYNC_ROOT_METADATA_CORRUPT = 358,
++ MD_ERROR_WIN_DEVICE_IN_MAINTENANCE = 359,
++ MD_ERROR_WIN_NOT_SUPPORTED_ON_DAX = 360,
++ MD_ERROR_WIN_DAX_MAPPING_EXISTS = 361,
++ MD_ERROR_WIN_CLOUD_FILE_PROVIDER_NOT_RUNNING = 362,
++ MD_ERROR_WIN_CLOUD_FILE_METADATA_CORRUPT = 363,
++ MD_ERROR_WIN_CLOUD_FILE_METADATA_TOO_LARGE = 364,
++ MD_ERROR_WIN_CLOUD_FILE_PROPERTY_BLOB_TOO_LARGE = 365,
++ MD_ERROR_WIN_CLOUD_FILE_PROPERTY_BLOB_CHECKSUM_MISMATCH = 366,
++ MD_ERROR_WIN_CHILD_PROCESS_BLOCKED = 367,
++ MD_ERROR_WIN_STORAGE_LOST_DATA_PERSISTENCE = 368,
++ MD_ERROR_WIN_FILE_SYSTEM_VIRTUALIZATION_UNAVAILABLE = 369,
++ MD_ERROR_WIN_FILE_SYSTEM_VIRTUALIZATION_METADATA_CORRUPT = 370,
++ MD_ERROR_WIN_FILE_SYSTEM_VIRTUALIZATION_BUSY = 371,
++ MD_ERROR_WIN_FILE_SYSTEM_VIRTUALIZATION_PROVIDER_UNKNOWN = 372,
++ MD_ERROR_WIN_GDI_HANDLE_LEAK = 373,
++ MD_ERROR_WIN_CLOUD_FILE_TOO_MANY_PROPERTY_BLOBS = 374,
++ MD_ERROR_WIN_CLOUD_FILE_PROPERTY_VERSION_NOT_SUPPORTED = 375,
++ MD_ERROR_WIN_NOT_A_CLOUD_FILE = 376,
++ MD_ERROR_WIN_CLOUD_FILE_NOT_IN_SYNC = 377,
++ MD_ERROR_WIN_CLOUD_FILE_ALREADY_CONNECTED = 378,
++ MD_ERROR_WIN_CLOUD_FILE_NOT_SUPPORTED = 379,
++ MD_ERROR_WIN_CLOUD_FILE_INVALID_REQUEST = 380,
++ MD_ERROR_WIN_CLOUD_FILE_READ_ONLY_VOLUME = 381,
++ MD_ERROR_WIN_CLOUD_FILE_CONNECTED_PROVIDER_ONLY = 382,
++ MD_ERROR_WIN_CLOUD_FILE_VALIDATION_FAILED = 383,
++ MD_ERROR_WIN_SMB1_NOT_AVAILABLE = 384,
++ MD_ERROR_WIN_FILE_SYSTEM_VIRTUALIZATION_INVALID_OPERATION = 385,
++ MD_ERROR_WIN_CLOUD_FILE_AUTHENTICATION_FAILED = 386,
++ MD_ERROR_WIN_CLOUD_FILE_INSUFFICIENT_RESOURCES = 387,
++ MD_ERROR_WIN_CLOUD_FILE_NETWORK_UNAVAILABLE = 388,
++ MD_ERROR_WIN_CLOUD_FILE_UNSUCCESSFUL = 389,
++ MD_ERROR_WIN_CLOUD_FILE_NOT_UNDER_SYNC_ROOT = 390,
++ MD_ERROR_WIN_CLOUD_FILE_IN_USE = 391,
++ MD_ERROR_WIN_CLOUD_FILE_PINNED = 392,
++ MD_ERROR_WIN_CLOUD_FILE_REQUEST_ABORTED = 393,
++ MD_ERROR_WIN_CLOUD_FILE_PROPERTY_CORRUPT = 394,
++ MD_ERROR_WIN_CLOUD_FILE_ACCESS_DENIED = 395,
++ MD_ERROR_WIN_CLOUD_FILE_INCOMPATIBLE_HARDLINKS = 396,
++ MD_ERROR_WIN_CLOUD_FILE_PROPERTY_LOCK_CONFLICT = 397,
++ MD_ERROR_WIN_CLOUD_FILE_REQUEST_CANCELED = 398,
++ MD_ERROR_WIN_EXTERNAL_SYSKEY_NOT_SUPPORTED = 399,
++ MD_ERROR_WIN_THREAD_MODE_ALREADY_BACKGROUND = 400,
++ MD_ERROR_WIN_THREAD_MODE_NOT_BACKGROUND = 401,
++ MD_ERROR_WIN_PROCESS_MODE_ALREADY_BACKGROUND = 402,
++ MD_ERROR_WIN_PROCESS_MODE_NOT_BACKGROUND = 403,
++ MD_ERROR_WIN_CLOUD_FILE_PROVIDER_TERMINATED = 404,
++ MD_ERROR_WIN_NOT_A_CLOUD_SYNC_ROOT = 405,
++ MD_ERROR_WIN_FILE_PROTECTED_UNDER_DPL = 406,
++ MD_ERROR_WIN_VOLUME_NOT_CLUSTER_ALIGNED = 407,
++ MD_ERROR_WIN_NO_PHYSICALLY_ALIGNED_FREE_SPACE_FOUND = 408,
++ MD_ERROR_WIN_APPX_FILE_NOT_ENCRYPTED = 409,
++ MD_ERROR_WIN_RWRAW_ENCRYPTED_FILE_NOT_ENCRYPTED = 410,
++ MD_ERROR_WIN_RWRAW_ENCRYPTED_INVALID_EDATAINFO_FILEOFFSET = 411,
++ MD_ERROR_WIN_RWRAW_ENCRYPTED_INVALID_EDATAINFO_FILERANGE = 412,
++ MD_ERROR_WIN_RWRAW_ENCRYPTED_INVALID_EDATAINFO_PARAMETER = 413,
++ MD_ERROR_WIN_LINUX_SUBSYSTEM_NOT_PRESENT = 414,
++ MD_ERROR_WIN_FT_READ_FAILURE = 415,
++ MD_ERROR_WIN_STORAGE_RESERVE_ID_INVALID = 416,
++ MD_ERROR_WIN_STORAGE_RESERVE_DOES_NOT_EXIST = 417,
++ MD_ERROR_WIN_STORAGE_RESERVE_ALREADY_EXISTS = 418,
++ MD_ERROR_WIN_STORAGE_RESERVE_NOT_EMPTY = 419,
++ MD_ERROR_WIN_NOT_A_DAX_VOLUME = 420,
++ MD_ERROR_WIN_NOT_DAX_MAPPABLE = 421,
++ MD_ERROR_WIN_TIME_SENSITIVE_THREAD = 422,
++ MD_ERROR_WIN_DPL_NOT_SUPPORTED_FOR_USER = 423,
++ MD_ERROR_WIN_CASE_DIFFERING_NAMES_IN_DIR = 424,
++ MD_ERROR_WIN_FILE_NOT_SUPPORTED = 425,
++ MD_ERROR_WIN_CLOUD_FILE_REQUEST_TIMEOUT = 426,
++ MD_ERROR_WIN_NO_TASK_QUEUE = 427,
++ MD_ERROR_WIN_SRC_SRV_DLL_LOAD_FAILED = 428,
++ MD_ERROR_WIN_NOT_SUPPORTED_WITH_BTT = 429,
++ MD_ERROR_WIN_ENCRYPTION_DISABLED = 430,
++ MD_ERROR_WIN_ENCRYPTING_METADATA_DISALLOWED = 431,
++ MD_ERROR_WIN_CANT_CLEAR_ENCRYPTION_FLAG = 432,
++ MD_ERROR_WIN_NO_SUCH_DEVICE = 433,
++ MD_ERROR_WIN_CLOUD_FILE_DEHYDRATION_DISALLOWED = 434,
++ MD_ERROR_WIN_FILE_SNAP_IN_PROGRESS = 435,
++ MD_ERROR_WIN_FILE_SNAP_USER_SECTION_NOT_SUPPORTED = 436,
++ MD_ERROR_WIN_FILE_SNAP_MODIFY_NOT_SUPPORTED = 437,
++ MD_ERROR_WIN_FILE_SNAP_IO_NOT_COORDINATED = 438,
++ MD_ERROR_WIN_FILE_SNAP_UNEXPECTED_ERROR = 439,
++ MD_ERROR_WIN_FILE_SNAP_INVALID_PARAMETER = 440,
++ MD_ERROR_WIN_UNSATISFIED_DEPENDENCIES = 441,
++ MD_ERROR_WIN_CASE_SENSITIVE_PATH = 442,
++ MD_ERROR_WIN_UNEXPECTED_NTCACHEMANAGER_ERROR = 443,
++ MD_ERROR_WIN_LINUX_SUBSYSTEM_UPDATE_REQUIRED = 444,
++ MD_ERROR_WIN_DLP_POLICY_WARNS_AGAINST_OPERATION = 445,
++ MD_ERROR_WIN_DLP_POLICY_DENIES_OPERATION = 446,
++ MD_ERROR_WIN_DLP_POLICY_SILENTLY_FAIL = 449,
++ MD_ERROR_WIN_CAPAUTHZ_NOT_DEVUNLOCKED = 450,
++ MD_ERROR_WIN_CAPAUTHZ_CHANGE_TYPE = 451,
++ MD_ERROR_WIN_CAPAUTHZ_NOT_PROVISIONED = 452,
++ MD_ERROR_WIN_CAPAUTHZ_NOT_AUTHORIZED = 453,
++ MD_ERROR_WIN_CAPAUTHZ_NO_POLICY = 454,
++ MD_ERROR_WIN_CAPAUTHZ_DB_CORRUPTED = 455,
++ MD_ERROR_WIN_CAPAUTHZ_SCCD_INVALID_CATALOG = 456,
++ MD_ERROR_WIN_CAPAUTHZ_SCCD_NO_AUTH_ENTITY = 457,
++ MD_ERROR_WIN_CAPAUTHZ_SCCD_PARSE_ERROR = 458,
++ MD_ERROR_WIN_CAPAUTHZ_SCCD_DEV_MODE_REQUIRED = 459,
++ MD_ERROR_WIN_CAPAUTHZ_SCCD_NO_CAPABILITY_MATCH = 460,
++ MD_ERROR_WIN_CIMFS_IMAGE_CORRUPT = 470,
++ MD_ERROR_WIN_PNP_QUERY_REMOVE_DEVICE_TIMEOUT = 480,
++ MD_ERROR_WIN_PNP_QUERY_REMOVE_RELATED_DEVICE_TIMEOUT = 481,
++ MD_ERROR_WIN_PNP_QUERY_REMOVE_UNRELATED_DEVICE_TIMEOUT = 482,
++ MD_ERROR_WIN_DEVICE_HARDWARE_ERROR = 483,
++ MD_ERROR_WIN_INVALID_ADDRESS = 487,
++ MD_ERROR_WIN_HAS_SYSTEM_CRITICAL_FILES = 488,
++ MD_ERROR_WIN_USER_PROFILE_LOAD = 500,
++ MD_ERROR_WIN_ARITHMETIC_OVERFLOW = 534,
++ MD_ERROR_WIN_PIPE_CONNECTED = 535,
++ MD_ERROR_WIN_PIPE_LISTENING = 536,
++ MD_ERROR_WIN_VERIFIER_STOP = 537,
++ MD_ERROR_WIN_ABIOS_ERROR = 538,
++ MD_ERROR_WIN_WX86_WARNING = 539,
++ MD_ERROR_WIN_WX86_ERROR = 540,
++ MD_ERROR_WIN_TIMER_NOT_CANCELED = 541,
++ MD_ERROR_WIN_UNWIND = 542,
++ MD_ERROR_WIN_BAD_STACK = 543,
++ MD_ERROR_WIN_INVALID_UNWIND_TARGET = 544,
++ MD_ERROR_WIN_INVALID_PORT_ATTRIBUTES = 545,
++ MD_ERROR_WIN_PORT_MESSAGE_TOO_LONG = 546,
++ MD_ERROR_WIN_INVALID_QUOTA_LOWER = 547,
++ MD_ERROR_WIN_DEVICE_ALREADY_ATTACHED = 548,
++ MD_ERROR_WIN_INSTRUCTION_MISALIGNMENT = 549,
++ MD_ERROR_WIN_PROFILING_NOT_STARTED = 550,
++ MD_ERROR_WIN_PROFILING_NOT_STOPPED = 551,
++ MD_ERROR_WIN_COULD_NOT_INTERPRET = 552,
++ MD_ERROR_WIN_PROFILING_AT_LIMIT = 553,
++ MD_ERROR_WIN_CANT_WAIT = 554,
++ MD_ERROR_WIN_CANT_TERMINATE_SELF = 555,
++ MD_ERROR_WIN_UNEXPECTED_MM_CREATE_ERR = 556,
++ MD_ERROR_WIN_UNEXPECTED_MM_MAP_ERROR = 557,
++ MD_ERROR_WIN_UNEXPECTED_MM_EXTEND_ERR = 558,
++ MD_ERROR_WIN_BAD_FUNCTION_TABLE = 559,
++ MD_ERROR_WIN_NO_GUID_TRANSLATION = 560,
++ MD_ERROR_WIN_INVALID_LDT_SIZE = 561,
++ MD_ERROR_WIN_INVALID_LDT_OFFSET = 563,
++ MD_ERROR_WIN_INVALID_LDT_DESCRIPTOR = 564,
++ MD_ERROR_WIN_TOO_MANY_THREADS = 565,
++ MD_ERROR_WIN_THREAD_NOT_IN_PROCESS = 566,
++ MD_ERROR_WIN_PAGEFILE_QUOTA_EXCEEDED = 567,
++ MD_ERROR_WIN_LOGON_SERVER_CONFLICT = 568,
++ MD_ERROR_WIN_SYNCHRONIZATION_REQUIRED = 569,
++ MD_ERROR_WIN_NET_OPEN_FAILED = 570,
++ MD_ERROR_WIN_IO_PRIVILEGE_FAILED = 571,
++ MD_ERROR_WIN_CONTROL_C_EXIT = 572,
++ MD_ERROR_WIN_MISSING_SYSTEMFILE = 573,
++ MD_ERROR_WIN_UNHANDLED_EXCEPTION = 574,
++ MD_ERROR_WIN_APP_INIT_FAILURE = 575,
++ MD_ERROR_WIN_PAGEFILE_CREATE_FAILED = 576,
++ MD_ERROR_WIN_INVALID_IMAGE_HASH = 577,
++ MD_ERROR_WIN_NO_PAGEFILE = 578,
++ MD_ERROR_WIN_ILLEGAL_FLOAT_CONTEXT = 579,
++ MD_ERROR_WIN_NO_EVENT_PAIR = 580,
++ MD_ERROR_WIN_DOMAIN_CTRLR_CONFIG_ERROR = 581,
++ MD_ERROR_WIN_ILLEGAL_CHARACTER = 582,
++ MD_ERROR_WIN_UNDEFINED_CHARACTER = 583,
++ MD_ERROR_WIN_FLOPPY_VOLUME = 584,
++ MD_ERROR_WIN_BIOS_FAILED_TO_CONNECT_INTERRUPT = 585,
++ MD_ERROR_WIN_BACKUP_CONTROLLER = 586,
++ MD_ERROR_WIN_MUTANT_LIMIT_EXCEEDED = 587,
++ MD_ERROR_WIN_FS_DRIVER_REQUIRED = 588,
++ MD_ERROR_WIN_CANNOT_LOAD_REGISTRY_FILE = 589,
++ MD_ERROR_WIN_DEBUG_ATTACH_FAILED = 590,
++ MD_ERROR_WIN_SYSTEM_PROCESS_TERMINATED = 591,
++ MD_ERROR_WIN_DATA_NOT_ACCEPTED = 592,
++ MD_ERROR_WIN_VDM_HARD_ERROR = 593,
++ MD_ERROR_WIN_DRIVER_CANCEL_TIMEOUT = 594,
++ MD_ERROR_WIN_REPLY_MESSAGE_MISMATCH = 595,
++ MD_ERROR_WIN_LOST_WRITEBEHIND_DATA = 596,
++ MD_ERROR_WIN_CLIENT_SERVER_PARAMETERS_INVALID = 597,
++ MD_ERROR_WIN_NOT_TINY_STREAM = 598,
++ MD_ERROR_WIN_STACK_OVERFLOW_READ = 599,
++ MD_ERROR_WIN_CONVERT_TO_LARGE = 600,
++ MD_ERROR_WIN_FOUND_OUT_OF_SCOPE = 601,
++ MD_ERROR_WIN_ALLOCATE_BUCKET = 602,
++ MD_ERROR_WIN_MARSHALL_OVERFLOW = 603,
++ MD_ERROR_WIN_INVALID_VARIANT = 604,
++ MD_ERROR_WIN_BAD_COMPRESSION_BUFFER = 605,
++ MD_ERROR_WIN_AUDIT_FAILED = 606,
++ MD_ERROR_WIN_TIMER_RESOLUTION_NOT_SET = 607,
++ MD_ERROR_WIN_INSUFFICIENT_LOGON_INFO = 608,
++ MD_ERROR_WIN_BAD_DLL_ENTRYPOINT = 609,
++ MD_ERROR_WIN_BAD_SERVICE_ENTRYPOINT = 610,
++ MD_ERROR_WIN_IP_ADDRESS_CONFLICT1 = 611,
++ MD_ERROR_WIN_IP_ADDRESS_CONFLICT2 = 612,
++ MD_ERROR_WIN_REGISTRY_QUOTA_LIMIT = 613,
++ MD_ERROR_WIN_NO_CALLBACK_ACTIVE = 614,
++ MD_ERROR_WIN_PWD_TOO_SHORT = 615,
++ MD_ERROR_WIN_PWD_TOO_RECENT = 616,
++ MD_ERROR_WIN_PWD_HISTORY_CONFLICT = 617,
++ MD_ERROR_WIN_UNSUPPORTED_COMPRESSION = 618,
++ MD_ERROR_WIN_INVALID_HW_PROFILE = 619,
++ MD_ERROR_WIN_INVALID_PLUGPLAY_DEVICE_PATH = 620,
++ MD_ERROR_WIN_QUOTA_LIST_INCONSISTENT = 621,
++ MD_ERROR_WIN_EVALUATION_EXPIRATION = 622,
++ MD_ERROR_WIN_ILLEGAL_DLL_RELOCATION = 623,
++ MD_ERROR_WIN_DLL_INIT_FAILED_LOGOFF = 624,
++ MD_ERROR_WIN_VALIDATE_CONTINUE = 625,
++ MD_ERROR_WIN_NO_MORE_MATCHES = 626,
++ MD_ERROR_WIN_RANGE_LIST_CONFLICT = 627,
++ MD_ERROR_WIN_SERVER_SID_MISMATCH = 628,
++ MD_ERROR_WIN_CANT_ENABLE_DENY_ONLY = 629,
++ MD_ERROR_WIN_FLOAT_MULTIPLE_FAULTS = 630,
++ MD_ERROR_WIN_FLOAT_MULTIPLE_TRAPS = 631,
++ MD_ERROR_WIN_NOINTERFACE = 632,
++ MD_ERROR_WIN_DRIVER_FAILED_SLEEP = 633,
++ MD_ERROR_WIN_CORRUPT_SYSTEM_FILE = 634,
++ MD_ERROR_WIN_COMMITMENT_MINIMUM = 635,
++ MD_ERROR_WIN_PNP_RESTART_ENUMERATION = 636,
++ MD_ERROR_WIN_SYSTEM_IMAGE_BAD_SIGNATURE = 637,
++ MD_ERROR_WIN_PNP_REBOOT_REQUIRED = 638,
++ MD_ERROR_WIN_INSUFFICIENT_POWER = 639,
++ MD_ERROR_WIN_MULTIPLE_FAULT_VIOLATION = 640,
++ MD_ERROR_WIN_SYSTEM_SHUTDOWN = 641,
++ MD_ERROR_WIN_PORT_NOT_SET = 642,
++ MD_ERROR_WIN_DS_VERSION_CHECK_FAILURE = 643,
++ MD_ERROR_WIN_RANGE_NOT_FOUND = 644,
++ MD_ERROR_WIN_NOT_SAFE_MODE_DRIVER = 646,
++ MD_ERROR_WIN_FAILED_DRIVER_ENTRY = 647,
++ MD_ERROR_WIN_DEVICE_ENUMERATION_ERROR = 648,
++ MD_ERROR_WIN_MOUNT_POINT_NOT_RESOLVED = 649,
++ MD_ERROR_WIN_INVALID_DEVICE_OBJECT_PARAMETER = 650,
++ MD_ERROR_WIN_MCA_OCCURED = 651,
++ MD_ERROR_WIN_DRIVER_DATABASE_ERROR = 652,
++ MD_ERROR_WIN_SYSTEM_HIVE_TOO_LARGE = 653,
++ MD_ERROR_WIN_DRIVER_FAILED_PRIOR_UNLOAD = 654,
++ MD_ERROR_WIN_VOLSNAP_PREPARE_HIBERNATE = 655,
++ MD_ERROR_WIN_HIBERNATION_FAILURE = 656,
++ MD_ERROR_WIN_PWD_TOO_LONG = 657,
++ MD_ERROR_WIN_FILE_SYSTEM_LIMITATION = 665,
++ MD_ERROR_WIN_ASSERTION_FAILURE = 668,
++ MD_ERROR_WIN_ACPI_ERROR = 669,
++ MD_ERROR_WIN_WOW_ASSERTION = 670,
++ MD_ERROR_WIN_PNP_BAD_MPS_TABLE = 671,
++ MD_ERROR_WIN_PNP_TRANSLATION_FAILED = 672,
++ MD_ERROR_WIN_PNP_IRQ_TRANSLATION_FAILED = 673,
++ MD_ERROR_WIN_PNP_INVALID_ID = 674,
++ MD_ERROR_WIN_WAKE_SYSTEM_DEBUGGER = 675,
++ MD_ERROR_WIN_HANDLES_CLOSED = 676,
++ MD_ERROR_WIN_EXTRANEOUS_INFORMATION = 677,
++ MD_ERROR_WIN_RXACT_COMMIT_NECESSARY = 678,
++ MD_ERROR_WIN_MEDIA_CHECK = 679,
++ MD_ERROR_WIN_GUID_SUBSTITUTION_MADE = 680,
++ MD_ERROR_WIN_STOPPED_ON_SYMLINK = 681,
++ MD_ERROR_WIN_LONGJUMP = 682,
++ MD_ERROR_WIN_PLUGPLAY_QUERY_VETOED = 683,
++ MD_ERROR_WIN_UNWIND_CONSOLIDATE = 684,
++ MD_ERROR_WIN_REGISTRY_HIVE_RECOVERED = 685,
++ MD_ERROR_WIN_DLL_MIGHT_BE_INSECURE = 686,
++ MD_ERROR_WIN_DLL_MIGHT_BE_INCOMPATIBLE = 687,
++ MD_ERROR_WIN_DBG_EXCEPTION_NOT_HANDLED = 688,
++ MD_ERROR_WIN_DBG_REPLY_LATER = 689,
++ MD_ERROR_WIN_DBG_UNABLE_TO_PROVIDE_HANDLE = 690,
++ MD_ERROR_WIN_DBG_TERMINATE_THREAD = 691,
++ MD_ERROR_WIN_DBG_TERMINATE_PROCESS = 692,
++ MD_ERROR_WIN_DBG_CONTROL_C = 693,
++ MD_ERROR_WIN_DBG_PRINTEXCEPTION_C = 694,
++ MD_ERROR_WIN_DBG_RIPEXCEPTION = 695,
++ MD_ERROR_WIN_DBG_CONTROL_BREAK = 696,
++ MD_ERROR_WIN_DBG_COMMAND_EXCEPTION = 697,
++ MD_ERROR_WIN_OBJECT_NAME_EXISTS = 698,
++ MD_ERROR_WIN_THREAD_WAS_SUSPENDED = 699,
++ MD_ERROR_WIN_IMAGE_NOT_AT_BASE = 700,
++ MD_ERROR_WIN_RXACT_STATE_CREATED = 701,
++ MD_ERROR_WIN_SEGMENT_NOTIFICATION = 702,
++ MD_ERROR_WIN_BAD_CURRENT_DIRECTORY = 703,
++ MD_ERROR_WIN_FT_READ_RECOVERY_FROM_BACKUP = 704,
++ MD_ERROR_WIN_FT_WRITE_RECOVERY = 705,
++ MD_ERROR_WIN_IMAGE_MACHINE_TYPE_MISMATCH = 706,
++ MD_ERROR_WIN_RECEIVE_PARTIAL = 707,
++ MD_ERROR_WIN_RECEIVE_EXPEDITED = 708,
++ MD_ERROR_WIN_RECEIVE_PARTIAL_EXPEDITED = 709,
++ MD_ERROR_WIN_EVENT_DONE = 710,
++ MD_ERROR_WIN_EVENT_PENDING = 711,
++ MD_ERROR_WIN_CHECKING_FILE_SYSTEM = 712,
++ MD_ERROR_WIN_FATAL_APP_EXIT = 713,
++ MD_ERROR_WIN_PREDEFINED_HANDLE = 714,
++ MD_ERROR_WIN_WAS_UNLOCKED = 715,
++ MD_ERROR_WIN_SERVICE_NOTIFICATION = 716,
++ MD_ERROR_WIN_WAS_LOCKED = 717,
++ MD_ERROR_WIN_LOG_HARD_ERROR = 718,
++ MD_ERROR_WIN_ALREADY_WIN32 = 719,
++ MD_ERROR_WIN_IMAGE_MACHINE_TYPE_MISMATCH_EXE = 720,
++ MD_ERROR_WIN_NO_YIELD_PERFORMED = 721,
++ MD_ERROR_WIN_TIMER_RESUME_IGNORED = 722,
++ MD_ERROR_WIN_ARBITRATION_UNHANDLED = 723,
++ MD_ERROR_WIN_CARDBUS_NOT_SUPPORTED = 724,
++ MD_ERROR_WIN_MP_PROCESSOR_MISMATCH = 725,
++ MD_ERROR_WIN_HIBERNATED = 726,
++ MD_ERROR_WIN_RESUME_HIBERNATION = 727,
++ MD_ERROR_WIN_FIRMWARE_UPDATED = 728,
++ MD_ERROR_WIN_DRIVERS_LEAKING_LOCKED_PAGES = 729,
++ MD_ERROR_WIN_WAKE_SYSTEM = 730,
++ MD_ERROR_WIN_WAIT_1 = 731,
++ MD_ERROR_WIN_WAIT_2 = 732,
++ MD_ERROR_WIN_WAIT_3 = 733,
++ MD_ERROR_WIN_WAIT_63 = 734,
++ MD_ERROR_WIN_ABANDONED_WAIT_0 = 735,
++ MD_ERROR_WIN_ABANDONED_WAIT_63 = 736,
++ MD_ERROR_WIN_USER_APC = 737,
++ MD_ERROR_WIN_KERNEL_APC = 738,
++ MD_ERROR_WIN_ALERTED = 739,
++ MD_ERROR_WIN_ELEVATION_REQUIRED = 740,
++ MD_ERROR_WIN_REPARSE = 741,
++ MD_ERROR_WIN_OPLOCK_BREAK_IN_PROGRESS = 742,
++ MD_ERROR_WIN_VOLUME_MOUNTED = 743,
++ MD_ERROR_WIN_RXACT_COMMITTED = 744,
++ MD_ERROR_WIN_NOTIFY_CLEANUP = 745,
++ MD_ERROR_WIN_PRIMARY_TRANSPORT_CONNECT_FAILED = 746,
++ MD_ERROR_WIN_PAGE_FAULT_TRANSITION = 747,
++ MD_ERROR_WIN_PAGE_FAULT_DEMAND_ZERO = 748,
++ MD_ERROR_WIN_PAGE_FAULT_COPY_ON_WRITE = 749,
++ MD_ERROR_WIN_PAGE_FAULT_GUARD_PAGE = 750,
++ MD_ERROR_WIN_PAGE_FAULT_PAGING_FILE = 751,
++ MD_ERROR_WIN_CACHE_PAGE_LOCKED = 752,
++ MD_ERROR_WIN_CRASH_DUMP = 753,
++ MD_ERROR_WIN_BUFFER_ALL_ZEROS = 754,
++ MD_ERROR_WIN_REPARSE_OBJECT = 755,
++ MD_ERROR_WIN_RESOURCE_REQUIREMENTS_CHANGED = 756,
++ MD_ERROR_WIN_TRANSLATION_COMPLETE = 757,
++ MD_ERROR_WIN_NOTHING_TO_TERMINATE = 758,
++ MD_ERROR_WIN_PROCESS_NOT_IN_JOB = 759,
++ MD_ERROR_WIN_PROCESS_IN_JOB = 760,
++ MD_ERROR_WIN_VOLSNAP_HIBERNATE_READY = 761,
++ MD_ERROR_WIN_FSFILTER_OP_COMPLETED_SUCCESSFULLY = 762,
++ MD_ERROR_WIN_INTERRUPT_VECTOR_ALREADY_CONNECTED = 763,
++ MD_ERROR_WIN_INTERRUPT_STILL_CONNECTED = 764,
++ MD_ERROR_WIN_WAIT_FOR_OPLOCK = 765,
++ MD_ERROR_WIN_DBG_EXCEPTION_HANDLED = 766,
++ MD_ERROR_WIN_DBG_CONTINUE = 767,
++ MD_ERROR_WIN_CALLBACK_POP_STACK = 768,
++ MD_ERROR_WIN_COMPRESSION_DISABLED = 769,
++ MD_ERROR_WIN_CANTFETCHBACKWARDS = 770,
++ MD_ERROR_WIN_CANTSCROLLBACKWARDS = 771,
++ MD_ERROR_WIN_ROWSNOTRELEASED = 772,
++ MD_ERROR_WIN_BAD_ACCESSOR_FLAGS = 773,
++ MD_ERROR_WIN_ERRORS_ENCOUNTERED = 774,
++ MD_ERROR_WIN_NOT_CAPABLE = 775,
++ MD_ERROR_WIN_REQUEST_OUT_OF_SEQUENCE = 776,
++ MD_ERROR_WIN_VERSION_PARSE_ERROR = 777,
++ MD_ERROR_WIN_BADSTARTPOSITION = 778,
++ MD_ERROR_WIN_MEMORY_HARDWARE = 779,
++ MD_ERROR_WIN_DISK_REPAIR_DISABLED = 780,
++ MD_ERROR_WIN_INSUFFICIENT_RESOURCE_FOR_SPECIFIED_SHARED_SECTION_SIZE = 781,
++ MD_ERROR_WIN_SYSTEM_POWERSTATE_TRANSITION = 782,
++ MD_ERROR_WIN_SYSTEM_POWERSTATE_COMPLEX_TRANSITION = 783,
++ MD_ERROR_WIN_MCA_EXCEPTION = 784,
++ MD_ERROR_WIN_ACCESS_AUDIT_BY_POLICY = 785,
++ MD_ERROR_WIN_ACCESS_DISABLED_NO_SAFER_UI_BY_POLICY = 786,
++ MD_ERROR_WIN_ABANDON_HIBERFILE = 787,
++ MD_ERROR_WIN_LOST_WRITEBEHIND_DATA_NETWORK_DISCONNECTED = 788,
++ MD_ERROR_WIN_LOST_WRITEBEHIND_DATA_NETWORK_SERVER_ERROR = 789,
++ MD_ERROR_WIN_LOST_WRITEBEHIND_DATA_LOCAL_DISK_ERROR = 790,
++ MD_ERROR_WIN_BAD_MCFG_TABLE = 791,
++ MD_ERROR_WIN_DISK_REPAIR_REDIRECTED = 792,
++ MD_ERROR_WIN_DISK_REPAIR_UNSUCCESSFUL = 793,
++ MD_ERROR_WIN_CORRUPT_LOG_OVERFULL = 794,
++ MD_ERROR_WIN_CORRUPT_LOG_CORRUPTED = 795,
++ MD_ERROR_WIN_CORRUPT_LOG_UNAVAILABLE = 796,
++ MD_ERROR_WIN_CORRUPT_LOG_DELETED_FULL = 797,
++ MD_ERROR_WIN_CORRUPT_LOG_CLEARED = 798,
++ MD_ERROR_WIN_ORPHAN_NAME_EXHAUSTED = 799,
++ MD_ERROR_WIN_OPLOCK_SWITCHED_TO_NEW_HANDLE = 800,
++ MD_ERROR_WIN_CANNOT_GRANT_REQUESTED_OPLOCK = 801,
++ MD_ERROR_WIN_CANNOT_BREAK_OPLOCK = 802,
++ MD_ERROR_WIN_OPLOCK_HANDLE_CLOSED = 803,
++ MD_ERROR_WIN_NO_ACE_CONDITION = 804,
++ MD_ERROR_WIN_INVALID_ACE_CONDITION = 805,
++ MD_ERROR_WIN_FILE_HANDLE_REVOKED = 806,
++ MD_ERROR_WIN_IMAGE_AT_DIFFERENT_BASE = 807,
++ MD_ERROR_WIN_ENCRYPTED_IO_NOT_POSSIBLE = 808,
++ MD_ERROR_WIN_FILE_METADATA_OPTIMIZATION_IN_PROGRESS = 809,
++ MD_ERROR_WIN_QUOTA_ACTIVITY = 810,
++ MD_ERROR_WIN_HANDLE_REVOKED = 811,
++ MD_ERROR_WIN_CALLBACK_INVOKE_INLINE = 812,
++ MD_ERROR_WIN_CPU_SET_INVALID = 813,
++ MD_ERROR_WIN_ENCLAVE_NOT_TERMINATED = 814,
++ MD_ERROR_WIN_ENCLAVE_VIOLATION = 815,
++ MD_ERROR_WIN_EA_ACCESS_DENIED = 994,
++ MD_ERROR_WIN_OPERATION_ABORTED = 995,
++ MD_ERROR_WIN_IO_INCOMPLETE = 996,
++ MD_ERROR_WIN_IO_PENDING = 997,
++ MD_ERROR_WIN_NOACCESS = 998,
++ MD_ERROR_WIN_SWAPERROR = 999,
++ MD_ERROR_WIN_STACK_OVERFLOW = 1001,
++ MD_ERROR_WIN_INVALID_MESSAGE = 1002,
++ MD_ERROR_WIN_CAN_NOT_COMPLETE = 1003,
++ MD_ERROR_WIN_INVALID_FLAGS = 1004,
++ MD_ERROR_WIN_UNRECOGNIZED_VOLUME = 1005,
++ MD_ERROR_WIN_FILE_INVALID = 1006,
++ MD_ERROR_WIN_FULLSCREEN_MODE = 1007,
++ MD_ERROR_WIN_NO_TOKEN = 1008,
++ MD_ERROR_WIN_BADDB = 1009,
++ MD_ERROR_WIN_BADKEY = 1010,
++ MD_ERROR_WIN_CANTOPEN = 1011,
++ MD_ERROR_WIN_CANTREAD = 1012,
++ MD_ERROR_WIN_CANTWRITE = 1013,
++ MD_ERROR_WIN_REGISTRY_RECOVERED = 1014,
++ MD_ERROR_WIN_REGISTRY_CORRUPT = 1015,
++ MD_ERROR_WIN_REGISTRY_IO_FAILED = 1016,
++ MD_ERROR_WIN_NOT_REGISTRY_FILE = 1017,
++ MD_ERROR_WIN_KEY_DELETED = 1018,
++ MD_ERROR_WIN_NO_LOG_SPACE = 1019,
++ MD_ERROR_WIN_KEY_HAS_CHILDREN = 1020,
++ MD_ERROR_WIN_CHILD_MUST_BE_VOLATILE = 1021,
++ MD_ERROR_WIN_NOTIFY_ENUM_DIR = 1022,
++ MD_ERROR_WIN_DEPENDENT_SERVICES_RUNNING = 1051,
++ MD_ERROR_WIN_INVALID_SERVICE_CONTROL = 1052,
++ MD_ERROR_WIN_SERVICE_REQUEST_TIMEOUT = 1053,
++ MD_ERROR_WIN_SERVICE_NO_THREAD = 1054,
++ MD_ERROR_WIN_SERVICE_DATABASE_LOCKED = 1055,
++ MD_ERROR_WIN_SERVICE_ALREADY_RUNNING = 1056,
++ MD_ERROR_WIN_INVALID_SERVICE_ACCOUNT = 1057,
++ MD_ERROR_WIN_SERVICE_DISABLED = 1058,
++ MD_ERROR_WIN_CIRCULAR_DEPENDENCY = 1059,
++ MD_ERROR_WIN_SERVICE_DOES_NOT_EXIST = 1060,
++ MD_ERROR_WIN_SERVICE_CANNOT_ACCEPT_CTRL = 1061,
++ MD_ERROR_WIN_SERVICE_NOT_ACTIVE = 1062,
++ MD_ERROR_WIN_FAILED_SERVICE_CONTROLLER_CONNECT = 1063,
++ MD_ERROR_WIN_EXCEPTION_IN_SERVICE = 1064,
++ MD_ERROR_WIN_DATABASE_DOES_NOT_EXIST = 1065,
++ MD_ERROR_WIN_SERVICE_SPECIFIC_ERROR = 1066,
++ MD_ERROR_WIN_PROCESS_ABORTED = 1067,
++ MD_ERROR_WIN_SERVICE_DEPENDENCY_FAIL = 1068,
++ MD_ERROR_WIN_SERVICE_LOGON_FAILED = 1069,
++ MD_ERROR_WIN_SERVICE_START_HANG = 1070,
++ MD_ERROR_WIN_INVALID_SERVICE_LOCK = 1071,
++ MD_ERROR_WIN_SERVICE_MARKED_FOR_DELETE = 1072,
++ MD_ERROR_WIN_SERVICE_EXISTS = 1073,
++ MD_ERROR_WIN_ALREADY_RUNNING_LKG = 1074,
++ MD_ERROR_WIN_SERVICE_DEPENDENCY_DELETED = 1075,
++ MD_ERROR_WIN_BOOT_ALREADY_ACCEPTED = 1076,
++ MD_ERROR_WIN_SERVICE_NEVER_STARTED = 1077,
++ MD_ERROR_WIN_DUPLICATE_SERVICE_NAME = 1078,
++ MD_ERROR_WIN_DIFFERENT_SERVICE_ACCOUNT = 1079,
++ MD_ERROR_WIN_CANNOT_DETECT_DRIVER_FAILURE = 1080,
++ MD_ERROR_WIN_CANNOT_DETECT_PROCESS_ABORT = 1081,
++ MD_ERROR_WIN_NO_RECOVERY_PROGRAM = 1082,
++ MD_ERROR_WIN_SERVICE_NOT_IN_EXE = 1083,
++ MD_ERROR_WIN_NOT_SAFEBOOT_SERVICE = 1084,
++ MD_ERROR_WIN_END_OF_MEDIA = 1100,
++ MD_ERROR_WIN_FILEMARK_DETECTED = 1101,
++ MD_ERROR_WIN_BEGINNING_OF_MEDIA = 1102,
++ MD_ERROR_WIN_SETMARK_DETECTED = 1103,
++ MD_ERROR_WIN_NO_DATA_DETECTED = 1104,
++ MD_ERROR_WIN_PARTITION_FAILURE = 1105,
++ MD_ERROR_WIN_INVALID_BLOCK_LENGTH = 1106,
++ MD_ERROR_WIN_DEVICE_NOT_PARTITIONED = 1107,
++ MD_ERROR_WIN_UNABLE_TO_LOCK_MEDIA = 1108,
++ MD_ERROR_WIN_UNABLE_TO_UNLOAD_MEDIA = 1109,
++ MD_ERROR_WIN_MEDIA_CHANGED = 1110,
++ MD_ERROR_WIN_BUS_RESET = 1111,
++ MD_ERROR_WIN_NO_MEDIA_IN_DRIVE = 1112,
++ MD_ERROR_WIN_NO_UNICODE_TRANSLATION = 1113,
++ MD_ERROR_WIN_DLL_INIT_FAILED = 1114,
++ MD_ERROR_WIN_SHUTDOWN_IN_PROGRESS = 1115,
++ MD_ERROR_WIN_NO_SHUTDOWN_IN_PROGRESS = 1116,
++ MD_ERROR_WIN_IO_DEVICE = 1117,
++ MD_ERROR_WIN_SERIAL_NO_DEVICE = 1118,
++ MD_ERROR_WIN_IRQ_BUSY = 1119,
++ MD_ERROR_WIN_MORE_WRITES = 1120,
++ MD_ERROR_WIN_COUNTER_TIMEOUT = 1121,
++ MD_ERROR_WIN_FLOPPY_ID_MARK_NOT_FOUND = 1122,
++ MD_ERROR_WIN_FLOPPY_WRONG_CYLINDER = 1123,
++ MD_ERROR_WIN_FLOPPY_UNKNOWN_ERROR = 1124,
++ MD_ERROR_WIN_FLOPPY_BAD_REGISTERS = 1125,
++ MD_ERROR_WIN_DISK_RECALIBRATE_FAILED = 1126,
++ MD_ERROR_WIN_DISK_OPERATION_FAILED = 1127,
++ MD_ERROR_WIN_DISK_RESET_FAILED = 1128,
++ MD_ERROR_WIN_EOM_OVERFLOW = 1129,
++ MD_ERROR_WIN_NOT_ENOUGH_SERVER_MEMORY = 1130,
++ MD_ERROR_WIN_POSSIBLE_DEADLOCK = 1131,
++ MD_ERROR_WIN_MAPPED_ALIGNMENT = 1132,
++ MD_ERROR_WIN_SET_POWER_STATE_VETOED = 1140,
++ MD_ERROR_WIN_SET_POWER_STATE_FAILED = 1141,
++ MD_ERROR_WIN_TOO_MANY_LINKS = 1142,
++ MD_ERROR_WIN_OLD_WIN_VERSION = 1150,
++ MD_ERROR_WIN_APP_WRONG_OS = 1151,
++ MD_ERROR_WIN_SINGLE_INSTANCE_APP = 1152,
++ MD_ERROR_WIN_RMODE_APP = 1153,
++ MD_ERROR_WIN_INVALID_DLL = 1154,
++ MD_ERROR_WIN_NO_ASSOCIATION = 1155,
++ MD_ERROR_WIN_DDE_FAIL = 1156,
++ MD_ERROR_WIN_DLL_NOT_FOUND = 1157,
++ MD_ERROR_WIN_NO_MORE_USER_HANDLES = 1158,
++ MD_ERROR_WIN_MESSAGE_SYNC_ONLY = 1159,
++ MD_ERROR_WIN_SOURCE_ELEMENT_EMPTY = 1160,
++ MD_ERROR_WIN_DESTINATION_ELEMENT_FULL = 1161,
++ MD_ERROR_WIN_ILLEGAL_ELEMENT_ADDRESS = 1162,
++ MD_ERROR_WIN_MAGAZINE_NOT_PRESENT = 1163,
++ MD_ERROR_WIN_DEVICE_REINITIALIZATION_NEEDED = 1164,
++ MD_ERROR_WIN_DEVICE_REQUIRES_CLEANING = 1165,
++ MD_ERROR_WIN_DEVICE_DOOR_OPEN = 1166,
++ MD_ERROR_WIN_DEVICE_NOT_CONNECTED = 1167,
++ MD_ERROR_WIN_NOT_FOUND = 1168,
++ MD_ERROR_WIN_NO_MATCH = 1169,
++ MD_ERROR_WIN_SET_NOT_FOUND = 1170,
++ MD_ERROR_WIN_POINT_NOT_FOUND = 1171,
++ MD_ERROR_WIN_NO_TRACKING_SERVICE = 1172,
++ MD_ERROR_WIN_NO_VOLUME_ID = 1173,
++ MD_ERROR_WIN_UNABLE_TO_REMOVE_REPLACED = 1175,
++ MD_ERROR_WIN_UNABLE_TO_MOVE_REPLACEMENT = 1176,
++ MD_ERROR_WIN_UNABLE_TO_MOVE_REPLACEMENT_2 = 1177,
++ MD_ERROR_WIN_JOURNAL_DELETE_IN_PROGRESS = 1178,
++ MD_ERROR_WIN_JOURNAL_NOT_ACTIVE = 1179,
++ MD_ERROR_WIN_POTENTIAL_FILE_FOUND = 1180,
++ MD_ERROR_WIN_JOURNAL_ENTRY_DELETED = 1181,
++ MD_ERROR_WIN_VRF_CFG_AND_IO_ENABLED = 1183,
++ MD_ERROR_WIN_PARTITION_TERMINATING = 1184,
++ MD_ERROR_WIN_SHUTDOWN_IS_SCHEDULED = 1190,
++ MD_ERROR_WIN_SHUTDOWN_USERS_LOGGED_ON = 1191,
++ MD_ERROR_WIN_BAD_DEVICE = 1200,
++ MD_ERROR_WIN_CONNECTION_UNAVAIL = 1201,
++ MD_ERROR_WIN_DEVICE_ALREADY_REMEMBERED = 1202,
++ MD_ERROR_WIN_NO_NET_OR_BAD_PATH = 1203,
++ MD_ERROR_WIN_BAD_PROVIDER = 1204,
++ MD_ERROR_WIN_CANNOT_OPEN_PROFILE = 1205,
++ MD_ERROR_WIN_BAD_PROFILE = 1206,
++ MD_ERROR_WIN_NOT_CONTAINER = 1207,
++ MD_ERROR_WIN_EXTENDED_ERROR = 1208,
++ MD_ERROR_WIN_INVALID_GROUPNAME = 1209,
++ MD_ERROR_WIN_INVALID_COMPUTERNAME = 1210,
++ MD_ERROR_WIN_INVALID_EVENTNAME = 1211,
++ MD_ERROR_WIN_INVALID_DOMAINNAME = 1212,
++ MD_ERROR_WIN_INVALID_SERVICENAME = 1213,
++ MD_ERROR_WIN_INVALID_NETNAME = 1214,
++ MD_ERROR_WIN_INVALID_SHARENAME = 1215,
++ MD_ERROR_WIN_INVALID_PASSWORDNAME = 1216,
++ MD_ERROR_WIN_INVALID_MESSAGENAME = 1217,
++ MD_ERROR_WIN_INVALID_MESSAGEDEST = 1218,
++ MD_ERROR_WIN_SESSION_CREDENTIAL_CONFLICT = 1219,
++ MD_ERROR_WIN_REMOTE_SESSION_LIMIT_EXCEEDED = 1220,
++ MD_ERROR_WIN_DUP_DOMAINNAME = 1221,
++ MD_ERROR_WIN_NO_NETWORK = 1222,
++ MD_ERROR_WIN_CANCELLED = 1223,
++ MD_ERROR_WIN_USER_MAPPED_FILE = 1224,
++ MD_ERROR_WIN_CONNECTION_REFUSED = 1225,
++ MD_ERROR_WIN_GRACEFUL_DISCONNECT = 1226,
++ MD_ERROR_WIN_ADDRESS_ALREADY_ASSOCIATED = 1227,
++ MD_ERROR_WIN_ADDRESS_NOT_ASSOCIATED = 1228,
++ MD_ERROR_WIN_CONNECTION_INVALID = 1229,
++ MD_ERROR_WIN_CONNECTION_ACTIVE = 1230,
++ MD_ERROR_WIN_NETWORK_UNREACHABLE = 1231,
++ MD_ERROR_WIN_HOST_UNREACHABLE = 1232,
++ MD_ERROR_WIN_PROTOCOL_UNREACHABLE = 1233,
++ MD_ERROR_WIN_PORT_UNREACHABLE = 1234,
++ MD_ERROR_WIN_REQUEST_ABORTED = 1235,
++ MD_ERROR_WIN_CONNECTION_ABORTED = 1236,
++ MD_ERROR_WIN_RETRY = 1237,
++ MD_ERROR_WIN_CONNECTION_COUNT_LIMIT = 1238,
++ MD_ERROR_WIN_LOGIN_TIME_RESTRICTION = 1239,
++ MD_ERROR_WIN_LOGIN_WKSTA_RESTRICTION = 1240,
++ MD_ERROR_WIN_INCORRECT_ADDRESS = 1241,
++ MD_ERROR_WIN_ALREADY_REGISTERED = 1242,
++ MD_ERROR_WIN_SERVICE_NOT_FOUND = 1243,
++ MD_ERROR_WIN_NOT_AUTHENTICATED = 1244,
++ MD_ERROR_WIN_NOT_LOGGED_ON = 1245,
++ MD_ERROR_WIN_CONTINUE = 1246,
++ MD_ERROR_WIN_ALREADY_INITIALIZED = 1247,
++ MD_ERROR_WIN_NO_MORE_DEVICES = 1248,
++ MD_ERROR_WIN_NO_SUCH_SITE = 1249,
++ MD_ERROR_WIN_DOMAIN_CONTROLLER_EXISTS = 1250,
++ MD_ERROR_WIN_ONLY_IF_CONNECTED = 1251,
++ MD_ERROR_WIN_OVERRIDE_NOCHANGES = 1252,
++ MD_ERROR_WIN_BAD_USER_PROFILE = 1253,
++ MD_ERROR_WIN_NOT_SUPPORTED_ON_SBS = 1254,
++ MD_ERROR_WIN_SERVER_SHUTDOWN_IN_PROGRESS = 1255,
++ MD_ERROR_WIN_HOST_DOWN = 1256,
++ MD_ERROR_WIN_NON_ACCOUNT_SID = 1257,
++ MD_ERROR_WIN_NON_DOMAIN_SID = 1258,
++ MD_ERROR_WIN_APPHELP_BLOCK = 1259,
++ MD_ERROR_WIN_ACCESS_DISABLED_BY_POLICY = 1260,
++ MD_ERROR_WIN_REG_NAT_CONSUMPTION = 1261,
++ MD_ERROR_WIN_CSCSHARE_OFFLINE = 1262,
++ MD_ERROR_WIN_PKINIT_FAILURE = 1263,
++ MD_ERROR_WIN_SMARTCARD_SUBSYSTEM_FAILURE = 1264,
++ MD_ERROR_WIN_DOWNGRADE_DETECTED = 1265,
++ MD_ERROR_WIN_MACHINE_LOCKED = 1271,
++ MD_ERROR_WIN_SMB_GUEST_LOGON_BLOCKED = 1272,
++ MD_ERROR_WIN_CALLBACK_SUPPLIED_INVALID_DATA = 1273,
++ MD_ERROR_WIN_SYNC_FOREGROUND_REFRESH_REQUIRED = 1274,
++ MD_ERROR_WIN_DRIVER_BLOCKED = 1275,
++ MD_ERROR_WIN_INVALID_IMPORT_OF_NON_DLL = 1276,
++ MD_ERROR_WIN_ACCESS_DISABLED_WEBBLADE = 1277,
++ MD_ERROR_WIN_ACCESS_DISABLED_WEBBLADE_TAMPER = 1278,
++ MD_ERROR_WIN_RECOVERY_FAILURE = 1279,
++ MD_ERROR_WIN_ALREADY_FIBER = 1280,
++ MD_ERROR_WIN_ALREADY_THREAD = 1281,
++ MD_ERROR_WIN_STACK_BUFFER_OVERRUN = 1282,
++ MD_ERROR_WIN_PARAMETER_QUOTA_EXCEEDED = 1283,
++ MD_ERROR_WIN_DEBUGGER_INACTIVE = 1284,
++ MD_ERROR_WIN_DELAY_LOAD_FAILED = 1285,
++ MD_ERROR_WIN_VDM_DISALLOWED = 1286,
++ MD_ERROR_WIN_UNIDENTIFIED_ERROR = 1287,
++ MD_ERROR_WIN_INVALID_CRUNTIME_PARAMETER = 1288,
++ MD_ERROR_WIN_BEYOND_VDL = 1289,
++ MD_ERROR_WIN_INCOMPATIBLE_SERVICE_SID_TYPE = 1290,
++ MD_ERROR_WIN_DRIVER_PROCESS_TERMINATED = 1291,
++ MD_ERROR_WIN_IMPLEMENTATION_LIMIT = 1292,
++ MD_ERROR_WIN_PROCESS_IS_PROTECTED = 1293,
++ MD_ERROR_WIN_SERVICE_NOTIFY_CLIENT_LAGGING = 1294,
++ MD_ERROR_WIN_DISK_QUOTA_EXCEEDED = 1295,
++ MD_ERROR_WIN_CONTENT_BLOCKED = 1296,
++ MD_ERROR_WIN_INCOMPATIBLE_SERVICE_PRIVILEGE = 1297,
++ MD_ERROR_WIN_APP_HANG = 1298,
++ MD_ERROR_WIN_INVALID_LABEL = 1299,
++ MD_ERROR_WIN_NOT_ALL_ASSIGNED = 1300,
++ MD_ERROR_WIN_SOME_NOT_MAPPED = 1301,
++ MD_ERROR_WIN_NO_QUOTAS_FOR_ACCOUNT = 1302,
++ MD_ERROR_WIN_LOCAL_USER_SESSION_KEY = 1303,
++ MD_ERROR_WIN_NULL_LM_PASSWORD = 1304,
++ MD_ERROR_WIN_UNKNOWN_REVISION = 1305,
++ MD_ERROR_WIN_REVISION_MISMATCH = 1306,
++ MD_ERROR_WIN_INVALID_OWNER = 1307,
++ MD_ERROR_WIN_INVALID_PRIMARY_GROUP = 1308,
++ MD_ERROR_WIN_NO_IMPERSONATION_TOKEN = 1309,
++ MD_ERROR_WIN_CANT_DISABLE_MANDATORY = 1310,
++ MD_ERROR_WIN_NO_LOGON_SERVERS = 1311,
++ MD_ERROR_WIN_NO_SUCH_LOGON_SESSION = 1312,
++ MD_ERROR_WIN_NO_SUCH_PRIVILEGE = 1313,
++ MD_ERROR_WIN_PRIVILEGE_NOT_HELD = 1314,
++ MD_ERROR_WIN_INVALID_ACCOUNT_NAME = 1315,
++ MD_ERROR_WIN_USER_EXISTS = 1316,
++ MD_ERROR_WIN_NO_SUCH_USER = 1317,
++ MD_ERROR_WIN_GROUP_EXISTS = 1318,
++ MD_ERROR_WIN_NO_SUCH_GROUP = 1319,
++ MD_ERROR_WIN_MEMBER_IN_GROUP = 1320,
++ MD_ERROR_WIN_MEMBER_NOT_IN_GROUP = 1321,
++ MD_ERROR_WIN_LAST_ADMIN = 1322,
++ MD_ERROR_WIN_WRONG_PASSWORD = 1323,
++ MD_ERROR_WIN_ILL_FORMED_PASSWORD = 1324,
++ MD_ERROR_WIN_PASSWORD_RESTRICTION = 1325,
++ MD_ERROR_WIN_LOGON_FAILURE = 1326,
++ MD_ERROR_WIN_ACCOUNT_RESTRICTION = 1327,
++ MD_ERROR_WIN_INVALID_LOGON_HOURS = 1328,
++ MD_ERROR_WIN_INVALID_WORKSTATION = 1329,
++ MD_ERROR_WIN_PASSWORD_EXPIRED = 1330,
++ MD_ERROR_WIN_ACCOUNT_DISABLED = 1331,
++ MD_ERROR_WIN_NONE_MAPPED = 1332,
++ MD_ERROR_WIN_TOO_MANY_LUIDS_REQUESTED = 1333,
++ MD_ERROR_WIN_LUIDS_EXHAUSTED = 1334,
++ MD_ERROR_WIN_INVALID_SUB_AUTHORITY = 1335,
++ MD_ERROR_WIN_INVALID_ACL = 1336,
++ MD_ERROR_WIN_INVALID_SID = 1337,
++ MD_ERROR_WIN_INVALID_SECURITY_DESCR = 1338,
++ MD_ERROR_WIN_BAD_INHERITANCE_ACL = 1340,
++ MD_ERROR_WIN_SERVER_DISABLED = 1341,
++ MD_ERROR_WIN_SERVER_NOT_DISABLED = 1342,
++ MD_ERROR_WIN_INVALID_ID_AUTHORITY = 1343,
++ MD_ERROR_WIN_ALLOTTED_SPACE_EXCEEDED = 1344,
++ MD_ERROR_WIN_INVALID_GROUP_ATTRIBUTES = 1345,
++ MD_ERROR_WIN_BAD_IMPERSONATION_LEVEL = 1346,
++ MD_ERROR_WIN_CANT_OPEN_ANONYMOUS = 1347,
++ MD_ERROR_WIN_BAD_VALIDATION_CLASS = 1348,
++ MD_ERROR_WIN_BAD_TOKEN_TYPE = 1349,
++ MD_ERROR_WIN_NO_SECURITY_ON_OBJECT = 1350,
++ MD_ERROR_WIN_CANT_ACCESS_DOMAIN_INFO = 1351,
++ MD_ERROR_WIN_INVALID_SERVER_STATE = 1352,
++ MD_ERROR_WIN_INVALID_DOMAIN_STATE = 1353,
++ MD_ERROR_WIN_INVALID_DOMAIN_ROLE = 1354,
++ MD_ERROR_WIN_NO_SUCH_DOMAIN = 1355,
++ MD_ERROR_WIN_DOMAIN_EXISTS = 1356,
++ MD_ERROR_WIN_DOMAIN_LIMIT_EXCEEDED = 1357,
++ MD_ERROR_WIN_INTERNAL_DB_CORRUPTION = 1358,
++ MD_ERROR_WIN_INTERNAL_ERROR = 1359,
++ MD_ERROR_WIN_GENERIC_NOT_MAPPED = 1360,
++ MD_ERROR_WIN_BAD_DESCRIPTOR_FORMAT = 1361,
++ MD_ERROR_WIN_NOT_LOGON_PROCESS = 1362,
++ MD_ERROR_WIN_LOGON_SESSION_EXISTS = 1363,
++ MD_ERROR_WIN_NO_SUCH_PACKAGE = 1364,
++ MD_ERROR_WIN_BAD_LOGON_SESSION_STATE = 1365,
++ MD_ERROR_WIN_LOGON_SESSION_COLLISION = 1366,
++ MD_ERROR_WIN_INVALID_LOGON_TYPE = 1367,
++ MD_ERROR_WIN_CANNOT_IMPERSONATE = 1368,
++ MD_ERROR_WIN_RXACT_INVALID_STATE = 1369,
++ MD_ERROR_WIN_RXACT_COMMIT_FAILURE = 1370,
++ MD_ERROR_WIN_SPECIAL_ACCOUNT = 1371,
++ MD_ERROR_WIN_SPECIAL_GROUP = 1372,
++ MD_ERROR_WIN_SPECIAL_USER = 1373,
++ MD_ERROR_WIN_MEMBERS_PRIMARY_GROUP = 1374,
++ MD_ERROR_WIN_TOKEN_ALREADY_IN_USE = 1375,
++ MD_ERROR_WIN_NO_SUCH_ALIAS = 1376,
++ MD_ERROR_WIN_MEMBER_NOT_IN_ALIAS = 1377,
++ MD_ERROR_WIN_MEMBER_IN_ALIAS = 1378,
++ MD_ERROR_WIN_ALIAS_EXISTS = 1379,
++ MD_ERROR_WIN_LOGON_NOT_GRANTED = 1380,
++ MD_ERROR_WIN_TOO_MANY_SECRETS = 1381,
++ MD_ERROR_WIN_SECRET_TOO_LONG = 1382,
++ MD_ERROR_WIN_INTERNAL_DB_ERROR = 1383,
++ MD_ERROR_WIN_TOO_MANY_CONTEXT_IDS = 1384,
++ MD_ERROR_WIN_LOGON_TYPE_NOT_GRANTED = 1385,
++ MD_ERROR_WIN_NT_CROSS_ENCRYPTION_REQUIRED = 1386,
++ MD_ERROR_WIN_NO_SUCH_MEMBER = 1387,
++ MD_ERROR_WIN_INVALID_MEMBER = 1388,
++ MD_ERROR_WIN_TOO_MANY_SIDS = 1389,
++ MD_ERROR_WIN_LM_CROSS_ENCRYPTION_REQUIRED = 1390,
++ MD_ERROR_WIN_NO_INHERITANCE = 1391,
++ MD_ERROR_WIN_FILE_CORRUPT = 1392,
++ MD_ERROR_WIN_DISK_CORRUPT = 1393,
++ MD_ERROR_WIN_NO_USER_SESSION_KEY = 1394,
++ MD_ERROR_WIN_LICENSE_QUOTA_EXCEEDED = 1395,
++ MD_ERROR_WIN_WRONG_TARGET_NAME = 1396,
++ MD_ERROR_WIN_MUTUAL_AUTH_FAILED = 1397,
++ MD_ERROR_WIN_TIME_SKEW = 1398,
++ MD_ERROR_WIN_CURRENT_DOMAIN_NOT_ALLOWED = 1399,
++ MD_ERROR_WIN_INVALID_WINDOW_HANDLE = 1400,
++ MD_ERROR_WIN_INVALID_MENU_HANDLE = 1401,
++ MD_ERROR_WIN_INVALID_CURSOR_HANDLE = 1402,
++ MD_ERROR_WIN_INVALID_ACCEL_HANDLE = 1403,
++ MD_ERROR_WIN_INVALID_HOOK_HANDLE = 1404,
++ MD_ERROR_WIN_INVALID_DWP_HANDLE = 1405,
++ MD_ERROR_WIN_TLW_WITH_WSCHILD = 1406,
++ MD_ERROR_WIN_CANNOT_FIND_WND_CLASS = 1407,
++ MD_ERROR_WIN_WINDOW_OF_OTHER_THREAD = 1408,
++ MD_ERROR_WIN_HOTKEY_ALREADY_REGISTERED = 1409,
++ MD_ERROR_WIN_CLASS_ALREADY_EXISTS = 1410,
++ MD_ERROR_WIN_CLASS_DOES_NOT_EXIST = 1411,
++ MD_ERROR_WIN_CLASS_HAS_WINDOWS = 1412,
++ MD_ERROR_WIN_INVALID_INDEX = 1413,
++ MD_ERROR_WIN_INVALID_ICON_HANDLE = 1414,
++ MD_ERROR_WIN_PRIVATE_DIALOG_INDEX = 1415,
++ MD_ERROR_WIN_LISTBOX_ID_NOT_FOUND = 1416,
++ MD_ERROR_WIN_NO_WILDCARD_CHARACTERS = 1417,
++ MD_ERROR_WIN_CLIPBOARD_NOT_OPEN = 1418,
++ MD_ERROR_WIN_HOTKEY_NOT_REGISTERED = 1419,
++ MD_ERROR_WIN_WINDOW_NOT_DIALOG = 1420,
++ MD_ERROR_WIN_CONTROL_ID_NOT_FOUND = 1421,
++ MD_ERROR_WIN_INVALID_COMBOBOX_MESSAGE = 1422,
++ MD_ERROR_WIN_WINDOW_NOT_COMBOBOX = 1423,
++ MD_ERROR_WIN_INVALID_EDIT_HEIGHT = 1424,
++ MD_ERROR_WIN_DC_NOT_FOUND = 1425,
++ MD_ERROR_WIN_INVALID_HOOK_FILTER = 1426,
++ MD_ERROR_WIN_INVALID_FILTER_PROC = 1427,
++ MD_ERROR_WIN_HOOK_NEEDS_HMOD = 1428,
++ MD_ERROR_WIN_GLOBAL_ONLY_HOOK = 1429,
++ MD_ERROR_WIN_JOURNAL_HOOK_SET = 1430,
++ MD_ERROR_WIN_HOOK_NOT_INSTALLED = 1431,
++ MD_ERROR_WIN_INVALID_LB_MESSAGE = 1432,
++ MD_ERROR_WIN_SETCOUNT_ON_BAD_LB = 1433,
++ MD_ERROR_WIN_LB_WITHOUT_TABSTOPS = 1434,
++ MD_ERROR_WIN_DESTROY_OBJECT_OF_OTHER_THREAD = 1435,
++ MD_ERROR_WIN_CHILD_WINDOW_MENU = 1436,
++ MD_ERROR_WIN_NO_SYSTEM_MENU = 1437,
++ MD_ERROR_WIN_INVALID_MSGBOX_STYLE = 1438,
++ MD_ERROR_WIN_INVALID_SPI_VALUE = 1439,
++ MD_ERROR_WIN_SCREEN_ALREADY_LOCKED = 1440,
++ MD_ERROR_WIN_HWNDS_HAVE_DIFF_PARENT = 1441,
++ MD_ERROR_WIN_NOT_CHILD_WINDOW = 1442,
++ MD_ERROR_WIN_INVALID_GW_COMMAND = 1443,
++ MD_ERROR_WIN_INVALID_THREAD_ID = 1444,
++ MD_ERROR_WIN_NON_MDICHILD_WINDOW = 1445,
++ MD_ERROR_WIN_POPUP_ALREADY_ACTIVE = 1446,
++ MD_ERROR_WIN_NO_SCROLLBARS = 1447,
++ MD_ERROR_WIN_INVALID_SCROLLBAR_RANGE = 1448,
++ MD_ERROR_WIN_INVALID_SHOWWIN_COMMAND = 1449,
++ MD_ERROR_WIN_NO_SYSTEM_RESOURCES = 1450,
++ MD_ERROR_WIN_NONPAGED_SYSTEM_RESOURCES = 1451,
++ MD_ERROR_WIN_PAGED_SYSTEM_RESOURCES = 1452,
++ MD_ERROR_WIN_WORKING_SET_QUOTA = 1453,
++ MD_ERROR_WIN_PAGEFILE_QUOTA = 1454,
++ MD_ERROR_WIN_COMMITMENT_LIMIT = 1455,
++ MD_ERROR_WIN_MENU_ITEM_NOT_FOUND = 1456,
++ MD_ERROR_WIN_INVALID_KEYBOARD_HANDLE = 1457,
++ MD_ERROR_WIN_HOOK_TYPE_NOT_ALLOWED = 1458,
++ MD_ERROR_WIN_REQUIRES_INTERACTIVE_WINDOWSTATION = 1459,
++ MD_ERROR_WIN_TIMEOUT = 1460,
++ MD_ERROR_WIN_INVALID_MONITOR_HANDLE = 1461,
++ MD_ERROR_WIN_INCORRECT_SIZE = 1462,
++ MD_ERROR_WIN_SYMLINK_CLASS_DISABLED = 1463,
++ MD_ERROR_WIN_SYMLINK_NOT_SUPPORTED = 1464,
++ MD_ERROR_WIN_XML_PARSE_ERROR = 1465,
++ MD_ERROR_WIN_XMLDSIG_ERROR = 1466,
++ MD_ERROR_WIN_RESTART_APPLICATION = 1467,
++ MD_ERROR_WIN_WRONG_COMPARTMENT = 1468,
++ MD_ERROR_WIN_AUTHIP_FAILURE = 1469,
++ MD_ERROR_WIN_NO_NVRAM_RESOURCES = 1470,
++ MD_ERROR_WIN_NOT_GUI_PROCESS = 1471,
++ MD_ERROR_WIN_EVENTLOG_FILE_CORRUPT = 1500,
++ MD_ERROR_WIN_EVENTLOG_CANT_START = 1501,
++ MD_ERROR_WIN_LOG_FILE_FULL = 1502,
++ MD_ERROR_WIN_EVENTLOG_FILE_CHANGED = 1503,
++ MD_ERROR_WIN_CONTAINER_ASSIGNED = 1504,
++ MD_ERROR_WIN_JOB_NO_CONTAINER = 1505,
++ MD_ERROR_WIN_INVALID_TASK_NAME = 1550,
++ MD_ERROR_WIN_INVALID_TASK_INDEX = 1551,
++ MD_ERROR_WIN_THREAD_ALREADY_IN_TASK = 1552,
++ MD_ERROR_WIN_INSTALL_SERVICE_FAILURE = 1601,
++ MD_ERROR_WIN_INSTALL_USEREXIT = 1602,
++ MD_ERROR_WIN_INSTALL_FAILURE = 1603,
++ MD_ERROR_WIN_INSTALL_SUSPEND = 1604,
++ MD_ERROR_WIN_UNKNOWN_PRODUCT = 1605,
++ MD_ERROR_WIN_UNKNOWN_FEATURE = 1606,
++ MD_ERROR_WIN_UNKNOWN_COMPONENT = 1607,
++ MD_ERROR_WIN_UNKNOWN_PROPERTY = 1608,
++ MD_ERROR_WIN_INVALID_HANDLE_STATE = 1609,
++ MD_ERROR_WIN_BAD_CONFIGURATION = 1610,
++ MD_ERROR_WIN_INDEX_ABSENT = 1611,
++ MD_ERROR_WIN_INSTALL_SOURCE_ABSENT = 1612,
++ MD_ERROR_WIN_INSTALL_PACKAGE_VERSION = 1613,
++ MD_ERROR_WIN_PRODUCT_UNINSTALLED = 1614,
++ MD_ERROR_WIN_BAD_QUERY_SYNTAX = 1615,
++ MD_ERROR_WIN_INVALID_FIELD = 1616,
++ MD_ERROR_WIN_DEVICE_REMOVED = 1617,
++ MD_ERROR_WIN_INSTALL_ALREADY_RUNNING = 1618,
++ MD_ERROR_WIN_INSTALL_PACKAGE_OPEN_FAILED = 1619,
++ MD_ERROR_WIN_INSTALL_PACKAGE_INVALID = 1620,
++ MD_ERROR_WIN_INSTALL_UI_FAILURE = 1621,
++ MD_ERROR_WIN_INSTALL_LOG_FAILURE = 1622,
++ MD_ERROR_WIN_INSTALL_LANGUAGE_UNSUPPORTED = 1623,
++ MD_ERROR_WIN_INSTALL_TRANSFORM_FAILURE = 1624,
++ MD_ERROR_WIN_INSTALL_PACKAGE_REJECTED = 1625,
++ MD_ERROR_WIN_FUNCTION_NOT_CALLED = 1626,
++ MD_ERROR_WIN_FUNCTION_FAILED = 1627,
++ MD_ERROR_WIN_INVALID_TABLE = 1628,
++ MD_ERROR_WIN_DATATYPE_MISMATCH = 1629,
++ MD_ERROR_WIN_UNSUPPORTED_TYPE = 1630,
++ MD_ERROR_WIN_CREATE_FAILED = 1631,
++ MD_ERROR_WIN_INSTALL_TEMP_UNWRITABLE = 1632,
++ MD_ERROR_WIN_INSTALL_PLATFORM_UNSUPPORTED = 1633,
++ MD_ERROR_WIN_INSTALL_NOTUSED = 1634,
++ MD_ERROR_WIN_PATCH_PACKAGE_OPEN_FAILED = 1635,
++ MD_ERROR_WIN_PATCH_PACKAGE_INVALID = 1636,
++ MD_ERROR_WIN_PATCH_PACKAGE_UNSUPPORTED = 1637,
++ MD_ERROR_WIN_PRODUCT_VERSION = 1638,
++ MD_ERROR_WIN_INVALID_COMMAND_LINE = 1639,
++ MD_ERROR_WIN_INSTALL_REMOTE_DISALLOWED = 1640,
++ MD_ERROR_WIN_SUCCESS_REBOOT_INITIATED = 1641,
++ MD_ERROR_WIN_PATCH_TARGET_NOT_FOUND = 1642,
++ MD_ERROR_WIN_PATCH_PACKAGE_REJECTED = 1643,
++ MD_ERROR_WIN_INSTALL_TRANSFORM_REJECTED = 1644,
++ MD_ERROR_WIN_INSTALL_REMOTE_PROHIBITED = 1645,
++ MD_ERROR_WIN_PATCH_REMOVAL_UNSUPPORTED = 1646,
++ MD_ERROR_WIN_UNKNOWN_PATCH = 1647,
++ MD_ERROR_WIN_PATCH_NO_SEQUENCE = 1648,
++ MD_ERROR_WIN_PATCH_REMOVAL_DISALLOWED = 1649,
++ MD_ERROR_WIN_INVALID_PATCH_XML = 1650,
++ MD_ERROR_WIN_PATCH_MANAGED_ADVERTISED_PRODUCT = 1651,
++ MD_ERROR_WIN_INSTALL_SERVICE_SAFEBOOT = 1652,
++ MD_ERROR_WIN_FAIL_FAST_EXCEPTION = 1653,
++ MD_ERROR_WIN_INSTALL_REJECTED = 1654,
++ MD_ERROR_WIN_DYNAMIC_CODE_BLOCKED = 1655,
++ MD_ERROR_WIN_NOT_SAME_OBJECT = 1656,
++ MD_ERROR_WIN_STRICT_CFG_VIOLATION = 1657,
++ MD_ERROR_WIN_SET_CONTEXT_DENIED = 1660,
++ MD_ERROR_WIN_CROSS_PARTITION_VIOLATION = 1661,
++ MD_ERROR_WIN_RETURN_ADDRESS_HIJACK_ATTEMPT = 1662,
++ MD_ERROR_WIN_INVALID_USER_BUFFER = 1784,
++ MD_ERROR_WIN_UNRECOGNIZED_MEDIA = 1785,
++ MD_ERROR_WIN_NO_TRUST_LSA_SECRET = 1786,
++ MD_ERROR_WIN_NO_TRUST_SAM_ACCOUNT = 1787,
++ MD_ERROR_WIN_TRUSTED_DOMAIN_FAILURE = 1788,
++ MD_ERROR_WIN_TRUSTED_RELATIONSHIP_FAILURE = 1789,
++ MD_ERROR_WIN_TRUST_FAILURE = 1790,
++ MD_ERROR_WIN_NETLOGON_NOT_STARTED = 1792,
++ MD_ERROR_WIN_ACCOUNT_EXPIRED = 1793,
++ MD_ERROR_WIN_REDIRECTOR_HAS_OPEN_HANDLES = 1794,
++ MD_ERROR_WIN_PRINTER_DRIVER_ALREADY_INSTALLED = 1795,
++ MD_ERROR_WIN_UNKNOWN_PORT = 1796,
++ MD_ERROR_WIN_UNKNOWN_PRINTER_DRIVER = 1797,
++ MD_ERROR_WIN_UNKNOWN_PRINTPROCESSOR = 1798,
++ MD_ERROR_WIN_INVALID_SEPARATOR_FILE = 1799,
++ MD_ERROR_WIN_INVALID_PRIORITY = 1800,
++ MD_ERROR_WIN_INVALID_PRINTER_NAME = 1801,
++ MD_ERROR_WIN_PRINTER_ALREADY_EXISTS = 1802,
++ MD_ERROR_WIN_INVALID_PRINTER_COMMAND = 1803,
++ MD_ERROR_WIN_INVALID_DATATYPE = 1804,
++ MD_ERROR_WIN_INVALID_ENVIRONMENT = 1805,
++ MD_ERROR_WIN_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT = 1807,
++ MD_ERROR_WIN_NOLOGON_WORKSTATION_TRUST_ACCOUNT = 1808,
++ MD_ERROR_WIN_NOLOGON_SERVER_TRUST_ACCOUNT = 1809,
++ MD_ERROR_WIN_DOMAIN_TRUST_INCONSISTENT = 1810,
++ MD_ERROR_WIN_SERVER_HAS_OPEN_HANDLES = 1811,
++ MD_ERROR_WIN_RESOURCE_DATA_NOT_FOUND = 1812,
++ MD_ERROR_WIN_RESOURCE_TYPE_NOT_FOUND = 1813,
++ MD_ERROR_WIN_RESOURCE_NAME_NOT_FOUND = 1814,
++ MD_ERROR_WIN_RESOURCE_LANG_NOT_FOUND = 1815,
++ MD_ERROR_WIN_NOT_ENOUGH_QUOTA = 1816,
++ MD_ERROR_WIN_INVALID_TIME = 1901,
++ MD_ERROR_WIN_INVALID_FORM_NAME = 1902,
++ MD_ERROR_WIN_INVALID_FORM_SIZE = 1903,
++ MD_ERROR_WIN_ALREADY_WAITING = 1904,
++ MD_ERROR_WIN_PRINTER_DELETED = 1905,
++ MD_ERROR_WIN_INVALID_PRINTER_STATE = 1906,
++ MD_ERROR_WIN_PASSWORD_MUST_CHANGE = 1907,
++ MD_ERROR_WIN_DOMAIN_CONTROLLER_NOT_FOUND = 1908,
++ MD_ERROR_WIN_ACCOUNT_LOCKED_OUT = 1909,
++ MD_ERROR_WIN_NO_SITENAME = 1919,
++ MD_ERROR_WIN_CANT_ACCESS_FILE = 1920,
++ MD_ERROR_WIN_CANT_RESOLVE_FILENAME = 1921,
++ MD_ERROR_WIN_KM_DRIVER_BLOCKED = 1930,
++ MD_ERROR_WIN_CONTEXT_EXPIRED = 1931,
++ MD_ERROR_WIN_PER_USER_TRUST_QUOTA_EXCEEDED = 1932,
++ MD_ERROR_WIN_ALL_USER_TRUST_QUOTA_EXCEEDED = 1933,
++ MD_ERROR_WIN_USER_DELETE_TRUST_QUOTA_EXCEEDED = 1934,
++ MD_ERROR_WIN_AUTHENTICATION_FIREWALL_FAILED = 1935,
++ MD_ERROR_WIN_REMOTE_PRINT_CONNECTIONS_BLOCKED = 1936,
++ MD_ERROR_WIN_NTLM_BLOCKED = 1937,
++ MD_ERROR_WIN_PASSWORD_CHANGE_REQUIRED = 1938,
++ MD_ERROR_WIN_LOST_MODE_LOGON_RESTRICTION = 1939,
++ MD_ERROR_WIN_INVALID_PIXEL_FORMAT = 2000,
++ MD_ERROR_WIN_BAD_DRIVER = 2001,
++ MD_ERROR_WIN_INVALID_WINDOW_STYLE = 2002,
++ MD_ERROR_WIN_METAFILE_NOT_SUPPORTED = 2003,
++ MD_ERROR_WIN_TRANSFORM_NOT_SUPPORTED = 2004,
++ MD_ERROR_WIN_CLIPPING_NOT_SUPPORTED = 2005,
++ MD_ERROR_WIN_INVALID_CMM = 2010,
++ MD_ERROR_WIN_INVALID_PROFILE = 2011,
++ MD_ERROR_WIN_TAG_NOT_FOUND = 2012,
++ MD_ERROR_WIN_TAG_NOT_PRESENT = 2013,
++ MD_ERROR_WIN_DUPLICATE_TAG = 2014,
++ MD_ERROR_WIN_PROFILE_NOT_ASSOCIATED_WITH_DEVICE = 2015,
++ MD_ERROR_WIN_PROFILE_NOT_FOUND = 2016,
++ MD_ERROR_WIN_INVALID_COLORSPACE = 2017,
++ MD_ERROR_WIN_ICM_NOT_ENABLED = 2018,
++ MD_ERROR_WIN_DELETING_ICM_XFORM = 2019,
++ MD_ERROR_WIN_INVALID_TRANSFORM = 2020,
++ MD_ERROR_WIN_COLORSPACE_MISMATCH = 2021,
++ MD_ERROR_WIN_INVALID_COLORINDEX = 2022,
++ MD_ERROR_WIN_PROFILE_DOES_NOT_MATCH_DEVICE = 2023,
++ MD_ERROR_WIN_CONNECTED_OTHER_PASSWORD = 2108,
++ MD_ERROR_WIN_CONNECTED_OTHER_PASSWORD_DEFAULT = 2109,
++ MD_ERROR_WIN_BAD_USERNAME = 2202,
++ MD_ERROR_WIN_NOT_CONNECTED = 2250,
++ MD_ERROR_WIN_OPEN_FILES = 2401,
++ MD_ERROR_WIN_ACTIVE_CONNECTIONS = 2402,
++ MD_ERROR_WIN_DEVICE_IN_USE = 2404,
++ MD_ERROR_WIN_UNKNOWN_PRINT_MONITOR = 3000,
++ MD_ERROR_WIN_PRINTER_DRIVER_IN_USE = 3001,
++ MD_ERROR_WIN_SPOOL_FILE_NOT_FOUND = 3002,
++ MD_ERROR_WIN_SPL_NO_STARTDOC = 3003,
++ MD_ERROR_WIN_SPL_NO_ADDJOB = 3004,
++ MD_ERROR_WIN_PRINT_PROCESSOR_ALREADY_INSTALLED = 3005,
++ MD_ERROR_WIN_PRINT_MONITOR_ALREADY_INSTALLED = 3006,
++ MD_ERROR_WIN_INVALID_PRINT_MONITOR = 3007,
++ MD_ERROR_WIN_PRINT_MONITOR_IN_USE = 3008,
++ MD_ERROR_WIN_PRINTER_HAS_JOBS_QUEUED = 3009,
++ MD_ERROR_WIN_SUCCESS_REBOOT_REQUIRED = 3010,
++ MD_ERROR_WIN_SUCCESS_RESTART_REQUIRED = 3011,
++ MD_ERROR_WIN_PRINTER_NOT_FOUND = 3012,
++ MD_ERROR_WIN_PRINTER_DRIVER_WARNED = 3013,
++ MD_ERROR_WIN_PRINTER_DRIVER_BLOCKED = 3014,
++ MD_ERROR_WIN_PRINTER_DRIVER_PACKAGE_IN_USE = 3015,
++ MD_ERROR_WIN_CORE_DRIVER_PACKAGE_NOT_FOUND = 3016,
++ MD_ERROR_WIN_FAIL_REBOOT_REQUIRED = 3017,
++ MD_ERROR_WIN_FAIL_REBOOT_INITIATED = 3018,
++ MD_ERROR_WIN_PRINTER_DRIVER_DOWNLOAD_NEEDED = 3019,
++ MD_ERROR_WIN_PRINT_JOB_RESTART_REQUIRED = 3020,
++ MD_ERROR_WIN_INVALID_PRINTER_DRIVER_MANIFEST = 3021,
++ MD_ERROR_WIN_PRINTER_NOT_SHAREABLE = 3022,
++ MD_ERROR_WIN_REQUEST_PAUSED = 3050,
++ MD_ERROR_WIN_APPEXEC_CONDITION_NOT_SATISFIED = 3060,
++ MD_ERROR_WIN_APPEXEC_HANDLE_INVALIDATED = 3061,
++ MD_ERROR_WIN_APPEXEC_INVALID_HOST_GENERATION = 3062,
++ MD_ERROR_WIN_APPEXEC_UNEXPECTED_PROCESS_REGISTRATION = 3063,
++ MD_ERROR_WIN_APPEXEC_INVALID_HOST_STATE = 3064,
++ MD_ERROR_WIN_APPEXEC_NO_DONOR = 3065,
++ MD_ERROR_WIN_APPEXEC_HOST_ID_MISMATCH = 3066,
++ MD_ERROR_WIN_APPEXEC_UNKNOWN_USER = 3067,
++ MD_ERROR_WIN_IO_REISSUE_AS_CACHED = 3950,
++ MD_ERROR_WIN_WINS_INTERNAL = 4000,
++ MD_ERROR_WIN_CAN_NOT_DEL_LOCAL_WINS = 4001,
++ MD_ERROR_WIN_STATIC_INIT = 4002,
++ MD_ERROR_WIN_INC_BACKUP = 4003,
++ MD_ERROR_WIN_FULL_BACKUP = 4004,
++ MD_ERROR_WIN_REC_NON_EXISTENT = 4005,
++ MD_ERROR_WIN_RPL_NOT_ALLOWED = 4006,
++ MD_ERROR_WIN_DHCP_ADDRESS_CONFLICT = 4100,
++ MD_ERROR_WIN_WMI_GUID_NOT_FOUND = 4200,
++ MD_ERROR_WIN_WMI_INSTANCE_NOT_FOUND = 4201,
++ MD_ERROR_WIN_WMI_ITEMID_NOT_FOUND = 4202,
++ MD_ERROR_WIN_WMI_TRY_AGAIN = 4203,
++ MD_ERROR_WIN_WMI_DP_NOT_FOUND = 4204,
++ MD_ERROR_WIN_WMI_UNRESOLVED_INSTANCE_REF = 4205,
++ MD_ERROR_WIN_WMI_ALREADY_ENABLED = 4206,
++ MD_ERROR_WIN_WMI_GUID_DISCONNECTED = 4207,
++ MD_ERROR_WIN_WMI_SERVER_UNAVAILABLE = 4208,
++ MD_ERROR_WIN_WMI_DP_FAILED = 4209,
++ MD_ERROR_WIN_WMI_INVALID_MOF = 4210,
++ MD_ERROR_WIN_WMI_INVALID_REGINFO = 4211,
++ MD_ERROR_WIN_WMI_ALREADY_DISABLED = 4212,
++ MD_ERROR_WIN_WMI_READ_ONLY = 4213,
++ MD_ERROR_WIN_WMI_SET_FAILURE = 4214,
++ MD_ERROR_WIN_NOT_APPCONTAINER = 4250,
++ MD_ERROR_WIN_APPCONTAINER_REQUIRED = 4251,
++ MD_ERROR_WIN_NOT_SUPPORTED_IN_APPCONTAINER = 4252,
++ MD_ERROR_WIN_INVALID_PACKAGE_SID_LENGTH = 4253,
++ MD_ERROR_WIN_INVALID_MEDIA = 4300,
++ MD_ERROR_WIN_INVALID_LIBRARY = 4301,
++ MD_ERROR_WIN_INVALID_MEDIA_POOL = 4302,
++ MD_ERROR_WIN_DRIVE_MEDIA_MISMATCH = 4303,
++ MD_ERROR_WIN_MEDIA_OFFLINE = 4304,
++ MD_ERROR_WIN_LIBRARY_OFFLINE = 4305,
++ MD_ERROR_WIN_EMPTY = 4306,
++ MD_ERROR_WIN_NOT_EMPTY = 4307,
++ MD_ERROR_WIN_MEDIA_UNAVAILABLE = 4308,
++ MD_ERROR_WIN_RESOURCE_DISABLED = 4309,
++ MD_ERROR_WIN_INVALID_CLEANER = 4310,
++ MD_ERROR_WIN_UNABLE_TO_CLEAN = 4311,
++ MD_ERROR_WIN_OBJECT_NOT_FOUND = 4312,
++ MD_ERROR_WIN_DATABASE_FAILURE = 4313,
++ MD_ERROR_WIN_DATABASE_FULL = 4314,
++ MD_ERROR_WIN_MEDIA_INCOMPATIBLE = 4315,
++ MD_ERROR_WIN_RESOURCE_NOT_PRESENT = 4316,
++ MD_ERROR_WIN_INVALID_OPERATION = 4317,
++ MD_ERROR_WIN_MEDIA_NOT_AVAILABLE = 4318,
++ MD_ERROR_WIN_DEVICE_NOT_AVAILABLE = 4319,
++ MD_ERROR_WIN_REQUEST_REFUSED = 4320,
++ MD_ERROR_WIN_INVALID_DRIVE_OBJECT = 4321,
++ MD_ERROR_WIN_LIBRARY_FULL = 4322,
++ MD_ERROR_WIN_MEDIUM_NOT_ACCESSIBLE = 4323,
++ MD_ERROR_WIN_UNABLE_TO_LOAD_MEDIUM = 4324,
++ MD_ERROR_WIN_UNABLE_TO_INVENTORY_DRIVE = 4325,
++ MD_ERROR_WIN_UNABLE_TO_INVENTORY_SLOT = 4326,
++ MD_ERROR_WIN_UNABLE_TO_INVENTORY_TRANSPORT = 4327,
++ MD_ERROR_WIN_TRANSPORT_FULL = 4328,
++ MD_ERROR_WIN_CONTROLLING_IEPORT = 4329,
++ MD_ERROR_WIN_UNABLE_TO_EJECT_MOUNTED_MEDIA = 4330,
++ MD_ERROR_WIN_CLEANER_SLOT_SET = 4331,
++ MD_ERROR_WIN_CLEANER_SLOT_NOT_SET = 4332,
++ MD_ERROR_WIN_CLEANER_CARTRIDGE_SPENT = 4333,
++ MD_ERROR_WIN_UNEXPECTED_OMID = 4334,
++ MD_ERROR_WIN_CANT_DELETE_LAST_ITEM = 4335,
++ MD_ERROR_WIN_MESSAGE_EXCEEDS_MAX_SIZE = 4336,
++ MD_ERROR_WIN_VOLUME_CONTAINS_SYS_FILES = 4337,
++ MD_ERROR_WIN_INDIGENOUS_TYPE = 4338,
++ MD_ERROR_WIN_NO_SUPPORTING_DRIVES = 4339,
++ MD_ERROR_WIN_CLEANER_CARTRIDGE_INSTALLED = 4340,
++ MD_ERROR_WIN_IEPORT_FULL = 4341,
++ MD_ERROR_WIN_FILE_OFFLINE = 4350,
++ MD_ERROR_WIN_REMOTE_STORAGE_NOT_ACTIVE = 4351,
++ MD_ERROR_WIN_REMOTE_STORAGE_MEDIA_ERROR = 4352,
++ MD_ERROR_WIN_NOT_A_REPARSE_POINT = 4390,
++ MD_ERROR_WIN_REPARSE_ATTRIBUTE_CONFLICT = 4391,
++ MD_ERROR_WIN_INVALID_REPARSE_DATA = 4392,
++ MD_ERROR_WIN_REPARSE_TAG_INVALID = 4393,
++ MD_ERROR_WIN_REPARSE_TAG_MISMATCH = 4394,
++ MD_ERROR_WIN_REPARSE_POINT_ENCOUNTERED = 4395,
++ MD_ERROR_WIN_APP_DATA_NOT_FOUND = 4400,
++ MD_ERROR_WIN_APP_DATA_EXPIRED = 4401,
++ MD_ERROR_WIN_APP_DATA_CORRUPT = 4402,
++ MD_ERROR_WIN_APP_DATA_LIMIT_EXCEEDED = 4403,
++ MD_ERROR_WIN_APP_DATA_REBOOT_REQUIRED = 4404,
++ MD_ERROR_WIN_SECUREBOOT_ROLLBACK_DETECTED = 4420,
++ MD_ERROR_WIN_SECUREBOOT_POLICY_VIOLATION = 4421,
++ MD_ERROR_WIN_SECUREBOOT_INVALID_POLICY = 4422,
++ MD_ERROR_WIN_SECUREBOOT_POLICY_PUBLISHER_NOT_FOUND = 4423,
++ MD_ERROR_WIN_SECUREBOOT_POLICY_NOT_SIGNED = 4424,
++ MD_ERROR_WIN_SECUREBOOT_NOT_ENABLED = 4425,
++ MD_ERROR_WIN_SECUREBOOT_FILE_REPLACED = 4426,
++ MD_ERROR_WIN_SECUREBOOT_POLICY_NOT_AUTHORIZED = 4427,
++ MD_ERROR_WIN_SECUREBOOT_POLICY_UNKNOWN = 4428,
++ MD_ERROR_WIN_SECUREBOOT_POLICY_MISSING_ANTIROLLBACKVERSION = 4429,
++ MD_ERROR_WIN_SECUREBOOT_PLATFORM_ID_MISMATCH = 4430,
++ MD_ERROR_WIN_SECUREBOOT_POLICY_ROLLBACK_DETECTED = 4431,
++ MD_ERROR_WIN_SECUREBOOT_POLICY_UPGRADE_MISMATCH = 4432,
++ MD_ERROR_WIN_SECUREBOOT_REQUIRED_POLICY_FILE_MISSING = 4433,
++ MD_ERROR_WIN_SECUREBOOT_NOT_BASE_POLICY = 4434,
++ MD_ERROR_WIN_SECUREBOOT_NOT_SUPPLEMENTAL_POLICY = 4435,
++ MD_ERROR_WIN_OFFLOAD_READ_FLT_NOT_SUPPORTED = 4440,
++ MD_ERROR_WIN_OFFLOAD_WRITE_FLT_NOT_SUPPORTED = 4441,
++ MD_ERROR_WIN_OFFLOAD_READ_FILE_NOT_SUPPORTED = 4442,
++ MD_ERROR_WIN_OFFLOAD_WRITE_FILE_NOT_SUPPORTED = 4443,
++ MD_ERROR_WIN_ALREADY_HAS_STREAM_ID = 4444,
++ MD_ERROR_WIN_SMR_GARBAGE_COLLECTION_REQUIRED = 4445,
++ MD_ERROR_WIN_WOF_WIM_HEADER_CORRUPT = 4446,
++ MD_ERROR_WIN_WOF_WIM_RESOURCE_TABLE_CORRUPT = 4447,
++ MD_ERROR_WIN_WOF_FILE_RESOURCE_TABLE_CORRUPT = 4448,
++ MD_ERROR_WIN_VOLUME_NOT_SIS_ENABLED = 4500,
++ MD_ERROR_WIN_SYSTEM_INTEGRITY_ROLLBACK_DETECTED = 4550,
++ MD_ERROR_WIN_SYSTEM_INTEGRITY_POLICY_VIOLATION = 4551,
++ MD_ERROR_WIN_SYSTEM_INTEGRITY_INVALID_POLICY = 4552,
++ MD_ERROR_WIN_SYSTEM_INTEGRITY_POLICY_NOT_SIGNED = 4553,
++ MD_ERROR_WIN_SYSTEM_INTEGRITY_TOO_MANY_POLICIES = 4554,
++ MD_ERROR_WIN_SYSTEM_INTEGRITY_SUPPLEMENTAL_POLICY_NOT_AUTHORIZED = 4555,
++ MD_ERROR_WIN_VSM_NOT_INITIALIZED = 4560,
++ MD_ERROR_WIN_VSM_DMA_PROTECTION_NOT_IN_USE = 4561,
++ MD_ERROR_WIN_PLATFORM_MANIFEST_NOT_AUTHORIZED = 4570,
++ MD_ERROR_WIN_PLATFORM_MANIFEST_INVALID = 4571,
++ MD_ERROR_WIN_PLATFORM_MANIFEST_FILE_NOT_AUTHORIZED = 4572,
++ MD_ERROR_WIN_PLATFORM_MANIFEST_CATALOG_NOT_AUTHORIZED = 4573,
++ MD_ERROR_WIN_PLATFORM_MANIFEST_BINARY_ID_NOT_FOUND = 4574,
++ MD_ERROR_WIN_PLATFORM_MANIFEST_NOT_ACTIVE = 4575,
++ MD_ERROR_WIN_PLATFORM_MANIFEST_NOT_SIGNED = 4576,
++ MD_ERROR_WIN_DEPENDENT_RESOURCE_EXISTS = 5001,
++ MD_ERROR_WIN_DEPENDENCY_NOT_FOUND = 5002,
++ MD_ERROR_WIN_DEPENDENCY_ALREADY_EXISTS = 5003,
++ MD_ERROR_WIN_RESOURCE_NOT_ONLINE = 5004,
++ MD_ERROR_WIN_HOST_NODE_NOT_AVAILABLE = 5005,
++ MD_ERROR_WIN_RESOURCE_NOT_AVAILABLE = 5006,
++ MD_ERROR_WIN_RESOURCE_NOT_FOUND = 5007,
++ MD_ERROR_WIN_SHUTDOWN_CLUSTER = 5008,
++ MD_ERROR_WIN_CANT_EVICT_ACTIVE_NODE = 5009,
++ MD_ERROR_WIN_OBJECT_ALREADY_EXISTS = 5010,
++ MD_ERROR_WIN_OBJECT_IN_LIST = 5011,
++ MD_ERROR_WIN_GROUP_NOT_AVAILABLE = 5012,
++ MD_ERROR_WIN_GROUP_NOT_FOUND = 5013,
++ MD_ERROR_WIN_GROUP_NOT_ONLINE = 5014,
++ MD_ERROR_WIN_HOST_NODE_NOT_RESOURCE_OWNER = 5015,
++ MD_ERROR_WIN_HOST_NODE_NOT_GROUP_OWNER = 5016,
++ MD_ERROR_WIN_RESMON_CREATE_FAILED = 5017,
++ MD_ERROR_WIN_RESMON_ONLINE_FAILED = 5018,
++ MD_ERROR_WIN_RESOURCE_ONLINE = 5019,
++ MD_ERROR_WIN_QUORUM_RESOURCE = 5020,
++ MD_ERROR_WIN_NOT_QUORUM_CAPABLE = 5021,
++ MD_ERROR_WIN_CLUSTER_SHUTTING_DOWN = 5022,
++ MD_ERROR_WIN_INVALID_STATE = 5023,
++ MD_ERROR_WIN_RESOURCE_PROPERTIES_STORED = 5024,
++ MD_ERROR_WIN_NOT_QUORUM_CLASS = 5025,
++ MD_ERROR_WIN_CORE_RESOURCE = 5026,
++ MD_ERROR_WIN_QUORUM_RESOURCE_ONLINE_FAILED = 5027,
++ MD_ERROR_WIN_QUORUMLOG_OPEN_FAILED = 5028,
++ MD_ERROR_WIN_CLUSTERLOG_CORRUPT = 5029,
++ MD_ERROR_WIN_CLUSTERLOG_RECORD_EXCEEDS_MAXSIZE = 5030,
++ MD_ERROR_WIN_CLUSTERLOG_EXCEEDS_MAXSIZE = 5031,
++ MD_ERROR_WIN_CLUSTERLOG_CHKPOINT_NOT_FOUND = 5032,
++ MD_ERROR_WIN_CLUSTERLOG_NOT_ENOUGH_SPACE = 5033,
++ MD_ERROR_WIN_QUORUM_OWNER_ALIVE = 5034,
++ MD_ERROR_WIN_NETWORK_NOT_AVAILABLE = 5035,
++ MD_ERROR_WIN_NODE_NOT_AVAILABLE = 5036,
++ MD_ERROR_WIN_ALL_NODES_NOT_AVAILABLE = 5037,
++ MD_ERROR_WIN_RESOURCE_FAILED = 5038,
++ MD_ERROR_WIN_CLUSTER_INVALID_NODE = 5039,
++ MD_ERROR_WIN_CLUSTER_NODE_EXISTS = 5040,
++ MD_ERROR_WIN_CLUSTER_JOIN_IN_PROGRESS = 5041,
++ MD_ERROR_WIN_CLUSTER_NODE_NOT_FOUND = 5042,
++ MD_ERROR_WIN_CLUSTER_LOCAL_NODE_NOT_FOUND = 5043,
++ MD_ERROR_WIN_CLUSTER_NETWORK_EXISTS = 5044,
++ MD_ERROR_WIN_CLUSTER_NETWORK_NOT_FOUND = 5045,
++ MD_ERROR_WIN_CLUSTER_NETINTERFACE_EXISTS = 5046,
++ MD_ERROR_WIN_CLUSTER_NETINTERFACE_NOT_FOUND = 5047,
++ MD_ERROR_WIN_CLUSTER_INVALID_REQUEST = 5048,
++ MD_ERROR_WIN_CLUSTER_INVALID_NETWORK_PROVIDER = 5049,
++ MD_ERROR_WIN_CLUSTER_NODE_DOWN = 5050,
++ MD_ERROR_WIN_CLUSTER_NODE_UNREACHABLE = 5051,
++ MD_ERROR_WIN_CLUSTER_NODE_NOT_MEMBER = 5052,
++ MD_ERROR_WIN_CLUSTER_JOIN_NOT_IN_PROGRESS = 5053,
++ MD_ERROR_WIN_CLUSTER_INVALID_NETWORK = 5054,
++ MD_ERROR_WIN_CLUSTER_NODE_UP = 5056,
++ MD_ERROR_WIN_CLUSTER_IPADDR_IN_USE = 5057,
++ MD_ERROR_WIN_CLUSTER_NODE_NOT_PAUSED = 5058,
++ MD_ERROR_WIN_CLUSTER_NO_SECURITY_CONTEXT = 5059,
++ MD_ERROR_WIN_CLUSTER_NETWORK_NOT_INTERNAL = 5060,
++ MD_ERROR_WIN_CLUSTER_NODE_ALREADY_UP = 5061,
++ MD_ERROR_WIN_CLUSTER_NODE_ALREADY_DOWN = 5062,
++ MD_ERROR_WIN_CLUSTER_NETWORK_ALREADY_ONLINE = 5063,
++ MD_ERROR_WIN_CLUSTER_NETWORK_ALREADY_OFFLINE = 5064,
++ MD_ERROR_WIN_CLUSTER_NODE_ALREADY_MEMBER = 5065,
++ MD_ERROR_WIN_CLUSTER_LAST_INTERNAL_NETWORK = 5066,
++ MD_ERROR_WIN_CLUSTER_NETWORK_HAS_DEPENDENTS = 5067,
++ MD_ERROR_WIN_INVALID_OPERATION_ON_QUORUM = 5068,
++ MD_ERROR_WIN_DEPENDENCY_NOT_ALLOWED = 5069,
++ MD_ERROR_WIN_CLUSTER_NODE_PAUSED = 5070,
++ MD_ERROR_WIN_NODE_CANT_HOST_RESOURCE = 5071,
++ MD_ERROR_WIN_CLUSTER_NODE_NOT_READY = 5072,
++ MD_ERROR_WIN_CLUSTER_NODE_SHUTTING_DOWN = 5073,
++ MD_ERROR_WIN_CLUSTER_JOIN_ABORTED = 5074,
++ MD_ERROR_WIN_CLUSTER_INCOMPATIBLE_VERSIONS = 5075,
++ MD_ERROR_WIN_CLUSTER_MAXNUM_OF_RESOURCES_EXCEEDED = 5076,
++ MD_ERROR_WIN_CLUSTER_SYSTEM_CONFIG_CHANGED = 5077,
++ MD_ERROR_WIN_CLUSTER_RESOURCE_TYPE_NOT_FOUND = 5078,
++ MD_ERROR_WIN_CLUSTER_RESTYPE_NOT_SUPPORTED = 5079,
++ MD_ERROR_WIN_CLUSTER_RESNAME_NOT_FOUND = 5080,
++ MD_ERROR_WIN_CLUSTER_NO_RPC_PACKAGES_REGISTERED = 5081,
++ MD_ERROR_WIN_CLUSTER_OWNER_NOT_IN_PREFLIST = 5082,
++ MD_ERROR_WIN_CLUSTER_DATABASE_SEQMISMATCH = 5083,
++ MD_ERROR_WIN_RESMON_INVALID_STATE = 5084,
++ MD_ERROR_WIN_CLUSTER_GUM_NOT_LOCKER = 5085,
++ MD_ERROR_WIN_QUORUM_DISK_NOT_FOUND = 5086,
++ MD_ERROR_WIN_DATABASE_BACKUP_CORRUPT = 5087,
++ MD_ERROR_WIN_CLUSTER_NODE_ALREADY_HAS_DFS_ROOT = 5088,
++ MD_ERROR_WIN_RESOURCE_PROPERTY_UNCHANGEABLE = 5089,
++ MD_ERROR_WIN_NO_ADMIN_ACCESS_POINT = 5090,
++ MD_ERROR_WIN_CLUSTER_MEMBERSHIP_INVALID_STATE = 5890,
++ MD_ERROR_WIN_CLUSTER_QUORUMLOG_NOT_FOUND = 5891,
++ MD_ERROR_WIN_CLUSTER_MEMBERSHIP_HALT = 5892,
++ MD_ERROR_WIN_CLUSTER_INSTANCE_ID_MISMATCH = 5893,
++ MD_ERROR_WIN_CLUSTER_NETWORK_NOT_FOUND_FOR_IP = 5894,
++ MD_ERROR_WIN_CLUSTER_PROPERTY_DATA_TYPE_MISMATCH = 5895,
++ MD_ERROR_WIN_CLUSTER_EVICT_WITHOUT_CLEANUP = 5896,
++ MD_ERROR_WIN_CLUSTER_PARAMETER_MISMATCH = 5897,
++ MD_ERROR_WIN_NODE_CANNOT_BE_CLUSTERED = 5898,
++ MD_ERROR_WIN_CLUSTER_WRONG_OS_VERSION = 5899,
++ MD_ERROR_WIN_CLUSTER_CANT_CREATE_DUP_CLUSTER_NAME = 5900,
++ MD_ERROR_WIN_CLUSCFG_ALREADY_COMMITTED = 5901,
++ MD_ERROR_WIN_CLUSCFG_ROLLBACK_FAILED = 5902,
++ MD_ERROR_WIN_CLUSCFG_SYSTEM_DISK_DRIVE_LETTER_CONFLICT = 5903,
++ MD_ERROR_WIN_CLUSTER_OLD_VERSION = 5904,
++ MD_ERROR_WIN_CLUSTER_MISMATCHED_COMPUTER_ACCT_NAME = 5905,
++ MD_ERROR_WIN_CLUSTER_NO_NET_ADAPTERS = 5906,
++ MD_ERROR_WIN_CLUSTER_POISONED = 5907,
++ MD_ERROR_WIN_CLUSTER_GROUP_MOVING = 5908,
++ MD_ERROR_WIN_CLUSTER_RESOURCE_TYPE_BUSY = 5909,
++ MD_ERROR_WIN_RESOURCE_CALL_TIMED_OUT = 5910,
++ MD_ERROR_WIN_INVALID_CLUSTER_IPV6_ADDRESS = 5911,
++ MD_ERROR_WIN_CLUSTER_INTERNAL_INVALID_FUNCTION = 5912,
++ MD_ERROR_WIN_CLUSTER_PARAMETER_OUT_OF_BOUNDS = 5913,
++ MD_ERROR_WIN_CLUSTER_PARTIAL_SEND = 5914,
++ MD_ERROR_WIN_CLUSTER_REGISTRY_INVALID_FUNCTION = 5915,
++ MD_ERROR_WIN_CLUSTER_INVALID_STRING_TERMINATION = 5916,
++ MD_ERROR_WIN_CLUSTER_INVALID_STRING_FORMAT = 5917,
++ MD_ERROR_WIN_CLUSTER_DATABASE_TRANSACTION_IN_PROGRESS = 5918,
++ MD_ERROR_WIN_CLUSTER_DATABASE_TRANSACTION_NOT_IN_PROGRESS = 5919,
++ MD_ERROR_WIN_CLUSTER_NULL_DATA = 5920,
++ MD_ERROR_WIN_CLUSTER_PARTIAL_READ = 5921,
++ MD_ERROR_WIN_CLUSTER_PARTIAL_WRITE = 5922,
++ MD_ERROR_WIN_CLUSTER_CANT_DESERIALIZE_DATA = 5923,
++ MD_ERROR_WIN_DEPENDENT_RESOURCE_PROPERTY_CONFLICT = 5924,
++ MD_ERROR_WIN_CLUSTER_NO_QUORUM = 5925,
++ MD_ERROR_WIN_CLUSTER_INVALID_IPV6_NETWORK = 5926,
++ MD_ERROR_WIN_CLUSTER_INVALID_IPV6_TUNNEL_NETWORK = 5927,
++ MD_ERROR_WIN_QUORUM_NOT_ALLOWED_IN_THIS_GROUP = 5928,
++ MD_ERROR_WIN_DEPENDENCY_TREE_TOO_COMPLEX = 5929,
++ MD_ERROR_WIN_EXCEPTION_IN_RESOURCE_CALL = 5930,
++ MD_ERROR_WIN_CLUSTER_RHS_FAILED_INITIALIZATION = 5931,
++ MD_ERROR_WIN_CLUSTER_NOT_INSTALLED = 5932,
++ MD_ERROR_WIN_CLUSTER_RESOURCES_MUST_BE_ONLINE_ON_THE_SAME_NODE = 5933,
++ MD_ERROR_WIN_CLUSTER_MAX_NODES_IN_CLUSTER = 5934,
++ MD_ERROR_WIN_CLUSTER_TOO_MANY_NODES = 5935,
++ MD_ERROR_WIN_CLUSTER_OBJECT_ALREADY_USED = 5936,
++ MD_ERROR_WIN_NONCORE_GROUPS_FOUND = 5937,
++ MD_ERROR_WIN_FILE_SHARE_RESOURCE_CONFLICT = 5938,
++ MD_ERROR_WIN_CLUSTER_EVICT_INVALID_REQUEST = 5939,
++ MD_ERROR_WIN_CLUSTER_SINGLETON_RESOURCE = 5940,
++ MD_ERROR_WIN_CLUSTER_GROUP_SINGLETON_RESOURCE = 5941,
++ MD_ERROR_WIN_CLUSTER_RESOURCE_PROVIDER_FAILED = 5942,
++ MD_ERROR_WIN_CLUSTER_RESOURCE_CONFIGURATION_ERROR = 5943,
++ MD_ERROR_WIN_CLUSTER_GROUP_BUSY = 5944,
++ MD_ERROR_WIN_CLUSTER_NOT_SHARED_VOLUME = 5945,
++ MD_ERROR_WIN_CLUSTER_INVALID_SECURITY_DESCRIPTOR = 5946,
++ MD_ERROR_WIN_CLUSTER_SHARED_VOLUMES_IN_USE = 5947,
++ MD_ERROR_WIN_CLUSTER_USE_SHARED_VOLUMES_API = 5948,
++ MD_ERROR_WIN_CLUSTER_BACKUP_IN_PROGRESS = 5949,
++ MD_ERROR_WIN_NON_CSV_PATH = 5950,
++ MD_ERROR_WIN_CSV_VOLUME_NOT_LOCAL = 5951,
++ MD_ERROR_WIN_CLUSTER_WATCHDOG_TERMINATING = 5952,
++ MD_ERROR_WIN_CLUSTER_RESOURCE_VETOED_MOVE_INCOMPATIBLE_NODES = 5953,
++ MD_ERROR_WIN_CLUSTER_INVALID_NODE_WEIGHT = 5954,
++ MD_ERROR_WIN_CLUSTER_RESOURCE_VETOED_CALL = 5955,
++ MD_ERROR_WIN_RESMON_SYSTEM_RESOURCES_LACKING = 5956,
++ MD_ERROR_WIN_CLUSTER_RESOURCE_VETOED_MOVE_NOT_ENOUGH_RESOURCES_ON_DESTINATION = 5957,
++ MD_ERROR_WIN_CLUSTER_RESOURCE_VETOED_MOVE_NOT_ENOUGH_RESOURCES_ON_SOURCE = 5958,
++ MD_ERROR_WIN_CLUSTER_GROUP_QUEUED = 5959,
++ MD_ERROR_WIN_CLUSTER_RESOURCE_LOCKED_STATUS = 5960,
++ MD_ERROR_WIN_CLUSTER_SHARED_VOLUME_FAILOVER_NOT_ALLOWED = 5961,
++ MD_ERROR_WIN_CLUSTER_NODE_DRAIN_IN_PROGRESS = 5962,
++ MD_ERROR_WIN_CLUSTER_DISK_NOT_CONNECTED = 5963,
++ MD_ERROR_WIN_DISK_NOT_CSV_CAPABLE = 5964,
++ MD_ERROR_WIN_RESOURCE_NOT_IN_AVAILABLE_STORAGE = 5965,
++ MD_ERROR_WIN_CLUSTER_SHARED_VOLUME_REDIRECTED = 5966,
++ MD_ERROR_WIN_CLUSTER_SHARED_VOLUME_NOT_REDIRECTED = 5967,
++ MD_ERROR_WIN_CLUSTER_CANNOT_RETURN_PROPERTIES = 5968,
++ MD_ERROR_WIN_CLUSTER_RESOURCE_CONTAINS_UNSUPPORTED_DIFF_AREA_FOR_SHARED_VOLUMES = 5969,
++ MD_ERROR_WIN_CLUSTER_RESOURCE_IS_IN_MAINTENANCE_MODE = 5970,
++ MD_ERROR_WIN_CLUSTER_AFFINITY_CONFLICT = 5971,
++ MD_ERROR_WIN_CLUSTER_RESOURCE_IS_REPLICA_VIRTUAL_MACHINE = 5972,
++ MD_ERROR_WIN_CLUSTER_UPGRADE_INCOMPATIBLE_VERSIONS = 5973,
++ MD_ERROR_WIN_CLUSTER_UPGRADE_FIX_QUORUM_NOT_SUPPORTED = 5974,
++ MD_ERROR_WIN_CLUSTER_UPGRADE_RESTART_REQUIRED = 5975,
++ MD_ERROR_WIN_CLUSTER_UPGRADE_IN_PROGRESS = 5976,
++ MD_ERROR_WIN_CLUSTER_UPGRADE_INCOMPLETE = 5977,
++ MD_ERROR_WIN_CLUSTER_NODE_IN_GRACE_PERIOD = 5978,
++ MD_ERROR_WIN_CLUSTER_CSV_IO_PAUSE_TIMEOUT = 5979,
++ MD_ERROR_WIN_NODE_NOT_ACTIVE_CLUSTER_MEMBER = 5980,
++ MD_ERROR_WIN_CLUSTER_RESOURCE_NOT_MONITORED = 5981,
++ MD_ERROR_WIN_CLUSTER_RESOURCE_DOES_NOT_SUPPORT_UNMONITORED = 5982,
++ MD_ERROR_WIN_CLUSTER_RESOURCE_IS_REPLICATED = 5983,
++ MD_ERROR_WIN_CLUSTER_NODE_ISOLATED = 5984,
++ MD_ERROR_WIN_CLUSTER_NODE_QUARANTINED = 5985,
++ MD_ERROR_WIN_CLUSTER_DATABASE_UPDATE_CONDITION_FAILED = 5986,
++ MD_ERROR_WIN_CLUSTER_SPACE_DEGRADED = 5987,
++ MD_ERROR_WIN_CLUSTER_TOKEN_DELEGATION_NOT_SUPPORTED = 5988,
++ MD_ERROR_WIN_CLUSTER_CSV_INVALID_HANDLE = 5989,
++ MD_ERROR_WIN_CLUSTER_CSV_SUPPORTED_ONLY_ON_COORDINATOR = 5990,
++ MD_ERROR_WIN_GROUPSET_NOT_AVAILABLE = 5991,
++ MD_ERROR_WIN_GROUPSET_NOT_FOUND = 5992,
++ MD_ERROR_WIN_GROUPSET_CANT_PROVIDE = 5993,
++ MD_ERROR_WIN_CLUSTER_FAULT_DOMAIN_PARENT_NOT_FOUND = 5994,
++ MD_ERROR_WIN_CLUSTER_FAULT_DOMAIN_INVALID_HIERARCHY = 5995,
++ MD_ERROR_WIN_CLUSTER_FAULT_DOMAIN_FAILED_S2D_VALIDATION = 5996,
++ MD_ERROR_WIN_CLUSTER_FAULT_DOMAIN_S2D_CONNECTIVITY_LOSS = 5997,
++ MD_ERROR_WIN_CLUSTER_INVALID_INFRASTRUCTURE_FILESERVER_NAME = 5998,
++ MD_ERROR_WIN_CLUSTERSET_MANAGEMENT_CLUSTER_UNREACHABLE = 5999,
++ MD_ERROR_WIN_ENCRYPTION_FAILED = 6000,
++ MD_ERROR_WIN_DECRYPTION_FAILED = 6001,
++ MD_ERROR_WIN_FILE_ENCRYPTED = 6002,
++ MD_ERROR_WIN_NO_RECOVERY_POLICY = 6003,
++ MD_ERROR_WIN_NO_EFS = 6004,
++ MD_ERROR_WIN_WRONG_EFS = 6005,
++ MD_ERROR_WIN_NO_USER_KEYS = 6006,
++ MD_ERROR_WIN_FILE_NOT_ENCRYPTED = 6007,
++ MD_ERROR_WIN_NOT_EXPORT_FORMAT = 6008,
++ MD_ERROR_WIN_FILE_READ_ONLY = 6009,
++ MD_ERROR_WIN_DIR_EFS_DISALLOWED = 6010,
++ MD_ERROR_WIN_EFS_SERVER_NOT_TRUSTED = 6011,
++ MD_ERROR_WIN_BAD_RECOVERY_POLICY = 6012,
++ MD_ERROR_WIN_EFS_ALG_BLOB_TOO_BIG = 6013,
++ MD_ERROR_WIN_VOLUME_NOT_SUPPORT_EFS = 6014,
++ MD_ERROR_WIN_EFS_DISABLED = 6015,
++ MD_ERROR_WIN_EFS_VERSION_NOT_SUPPORT = 6016,
++ MD_ERROR_WIN_CS_ENCRYPTION_INVALID_SERVER_RESPONSE = 6017,
++ MD_ERROR_WIN_CS_ENCRYPTION_UNSUPPORTED_SERVER = 6018,
++ MD_ERROR_WIN_CS_ENCRYPTION_EXISTING_ENCRYPTED_FILE = 6019,
++ MD_ERROR_WIN_CS_ENCRYPTION_NEW_ENCRYPTED_FILE = 6020,
++ MD_ERROR_WIN_CS_ENCRYPTION_FILE_NOT_CSE = 6021,
++ MD_ERROR_WIN_ENCRYPTION_POLICY_DENIES_OPERATION = 6022,
++ MD_ERROR_WIN_WIP_ENCRYPTION_FAILED = 6023,
++ MD_ERROR_WIN_NO_BROWSER_SERVERS_FOUND = 6118,
++ MD_ERROR_WIN_CLUSTER_OBJECT_IS_CLUSTER_SET_VM = 6250,
++ MD_ERROR_WIN_LOG_SECTOR_INVALID = 6600,
++ MD_ERROR_WIN_LOG_SECTOR_PARITY_INVALID = 6601,
++ MD_ERROR_WIN_LOG_SECTOR_REMAPPED = 6602,
++ MD_ERROR_WIN_LOG_BLOCK_INCOMPLETE = 6603,
++ MD_ERROR_WIN_LOG_INVALID_RANGE = 6604,
++ MD_ERROR_WIN_LOG_BLOCKS_EXHAUSTED = 6605,
++ MD_ERROR_WIN_LOG_READ_CONTEXT_INVALID = 6606,
++ MD_ERROR_WIN_LOG_RESTART_INVALID = 6607,
++ MD_ERROR_WIN_LOG_BLOCK_VERSION = 6608,
++ MD_ERROR_WIN_LOG_BLOCK_INVALID = 6609,
++ MD_ERROR_WIN_LOG_READ_MODE_INVALID = 6610,
++ MD_ERROR_WIN_LOG_NO_RESTART = 6611,
++ MD_ERROR_WIN_LOG_METADATA_CORRUPT = 6612,
++ MD_ERROR_WIN_LOG_METADATA_INVALID = 6613,
++ MD_ERROR_WIN_LOG_METADATA_INCONSISTENT = 6614,
++ MD_ERROR_WIN_LOG_RESERVATION_INVALID = 6615,
++ MD_ERROR_WIN_LOG_CANT_DELETE = 6616,
++ MD_ERROR_WIN_LOG_CONTAINER_LIMIT_EXCEEDED = 6617,
++ MD_ERROR_WIN_LOG_START_OF_LOG = 6618,
++ MD_ERROR_WIN_LOG_POLICY_ALREADY_INSTALLED = 6619,
++ MD_ERROR_WIN_LOG_POLICY_NOT_INSTALLED = 6620,
++ MD_ERROR_WIN_LOG_POLICY_INVALID = 6621,
++ MD_ERROR_WIN_LOG_POLICY_CONFLICT = 6622,
++ MD_ERROR_WIN_LOG_PINNED_ARCHIVE_TAIL = 6623,
++ MD_ERROR_WIN_LOG_RECORD_NONEXISTENT = 6624,
++ MD_ERROR_WIN_LOG_RECORDS_RESERVED_INVALID = 6625,
++ MD_ERROR_WIN_LOG_SPACE_RESERVED_INVALID = 6626,
++ MD_ERROR_WIN_LOG_TAIL_INVALID = 6627,
++ MD_ERROR_WIN_LOG_FULL = 6628,
++ MD_ERROR_WIN_COULD_NOT_RESIZE_LOG = 6629,
++ MD_ERROR_WIN_LOG_MULTIPLEXED = 6630,
++ MD_ERROR_WIN_LOG_DEDICATED = 6631,
++ MD_ERROR_WIN_LOG_ARCHIVE_NOT_IN_PROGRESS = 6632,
++ MD_ERROR_WIN_LOG_ARCHIVE_IN_PROGRESS = 6633,
++ MD_ERROR_WIN_LOG_EPHEMERAL = 6634,
++ MD_ERROR_WIN_LOG_NOT_ENOUGH_CONTAINERS = 6635,
++ MD_ERROR_WIN_LOG_CLIENT_ALREADY_REGISTERED = 6636,
++ MD_ERROR_WIN_LOG_CLIENT_NOT_REGISTERED = 6637,
++ MD_ERROR_WIN_LOG_FULL_HANDLER_IN_PROGRESS = 6638,
++ MD_ERROR_WIN_LOG_CONTAINER_READ_FAILED = 6639,
++ MD_ERROR_WIN_LOG_CONTAINER_WRITE_FAILED = 6640,
++ MD_ERROR_WIN_LOG_CONTAINER_OPEN_FAILED = 6641,
++ MD_ERROR_WIN_LOG_CONTAINER_STATE_INVALID = 6642,
++ MD_ERROR_WIN_LOG_STATE_INVALID = 6643,
++ MD_ERROR_WIN_LOG_PINNED = 6644,
++ MD_ERROR_WIN_LOG_METADATA_FLUSH_FAILED = 6645,
++ MD_ERROR_WIN_LOG_INCONSISTENT_SECURITY = 6646,
++ MD_ERROR_WIN_LOG_APPENDED_FLUSH_FAILED = 6647,
++ MD_ERROR_WIN_LOG_PINNED_RESERVATION = 6648,
++ MD_ERROR_WIN_INVALID_TRANSACTION = 6700,
++ MD_ERROR_WIN_TRANSACTION_NOT_ACTIVE = 6701,
++ MD_ERROR_WIN_TRANSACTION_REQUEST_NOT_VALID = 6702,
++ MD_ERROR_WIN_TRANSACTION_NOT_REQUESTED = 6703,
++ MD_ERROR_WIN_TRANSACTION_ALREADY_ABORTED = 6704,
++ MD_ERROR_WIN_TRANSACTION_ALREADY_COMMITTED = 6705,
++ MD_ERROR_WIN_TM_INITIALIZATION_FAILED = 6706,
++ MD_ERROR_WIN_RESOURCEMANAGER_READ_ONLY = 6707,
++ MD_ERROR_WIN_TRANSACTION_NOT_JOINED = 6708,
++ MD_ERROR_WIN_TRANSACTION_SUPERIOR_EXISTS = 6709,
++ MD_ERROR_WIN_CRM_PROTOCOL_ALREADY_EXISTS = 6710,
++ MD_ERROR_WIN_TRANSACTION_PROPAGATION_FAILED = 6711,
++ MD_ERROR_WIN_CRM_PROTOCOL_NOT_FOUND = 6712,
++ MD_ERROR_WIN_TRANSACTION_INVALID_MARSHALL_BUFFER = 6713,
++ MD_ERROR_WIN_CURRENT_TRANSACTION_NOT_VALID = 6714,
++ MD_ERROR_WIN_TRANSACTION_NOT_FOUND = 6715,
++ MD_ERROR_WIN_RESOURCEMANAGER_NOT_FOUND = 6716,
++ MD_ERROR_WIN_ENLISTMENT_NOT_FOUND = 6717,
++ MD_ERROR_WIN_TRANSACTIONMANAGER_NOT_FOUND = 6718,
++ MD_ERROR_WIN_TRANSACTIONMANAGER_NOT_ONLINE = 6719,
++ MD_ERROR_WIN_TRANSACTIONMANAGER_RECOVERY_NAME_COLLISION = 6720,
++ MD_ERROR_WIN_TRANSACTION_NOT_ROOT = 6721,
++ MD_ERROR_WIN_TRANSACTION_OBJECT_EXPIRED = 6722,
++ MD_ERROR_WIN_TRANSACTION_RESPONSE_NOT_ENLISTED = 6723,
++ MD_ERROR_WIN_TRANSACTION_RECORD_TOO_LONG = 6724,
++ MD_ERROR_WIN_IMPLICIT_TRANSACTION_NOT_SUPPORTED = 6725,
++ MD_ERROR_WIN_TRANSACTION_INTEGRITY_VIOLATED = 6726,
++ MD_ERROR_WIN_TRANSACTIONMANAGER_IDENTITY_MISMATCH = 6727,
++ MD_ERROR_WIN_RM_CANNOT_BE_FROZEN_FOR_SNAPSHOT = 6728,
++ MD_ERROR_WIN_TRANSACTION_MUST_WRITETHROUGH = 6729,
++ MD_ERROR_WIN_TRANSACTION_NO_SUPERIOR = 6730,
++ MD_ERROR_WIN_HEURISTIC_DAMAGE_POSSIBLE = 6731,
++ MD_ERROR_WIN_TRANSACTIONAL_CONFLICT = 6800,
++ MD_ERROR_WIN_RM_NOT_ACTIVE = 6801,
++ MD_ERROR_WIN_RM_METADATA_CORRUPT = 6802,
++ MD_ERROR_WIN_DIRECTORY_NOT_RM = 6803,
++ MD_ERROR_WIN_TRANSACTIONS_UNSUPPORTED_REMOTE = 6805,
++ MD_ERROR_WIN_LOG_RESIZE_INVALID_SIZE = 6806,
++ MD_ERROR_WIN_OBJECT_NO_LONGER_EXISTS = 6807,
++ MD_ERROR_WIN_STREAM_MINIVERSION_NOT_FOUND = 6808,
++ MD_ERROR_WIN_STREAM_MINIVERSION_NOT_VALID = 6809,
++ MD_ERROR_WIN_MINIVERSION_INACCESSIBLE_FROM_SPECIFIED_TRANSACTION = 6810,
++ MD_ERROR_WIN_CANT_OPEN_MINIVERSION_WITH_MODIFY_INTENT = 6811,
++ MD_ERROR_WIN_CANT_CREATE_MORE_STREAM_MINIVERSIONS = 6812,
++ MD_ERROR_WIN_REMOTE_FILE_VERSION_MISMATCH = 6814,
++ MD_ERROR_WIN_HANDLE_NO_LONGER_VALID = 6815,
++ MD_ERROR_WIN_NO_TXF_METADATA = 6816,
++ MD_ERROR_WIN_LOG_CORRUPTION_DETECTED = 6817,
++ MD_ERROR_WIN_CANT_RECOVER_WITH_HANDLE_OPEN = 6818,
++ MD_ERROR_WIN_RM_DISCONNECTED = 6819,
++ MD_ERROR_WIN_ENLISTMENT_NOT_SUPERIOR = 6820,
++ MD_ERROR_WIN_RECOVERY_NOT_NEEDED = 6821,
++ MD_ERROR_WIN_RM_ALREADY_STARTED = 6822,
++ MD_ERROR_WIN_FILE_IDENTITY_NOT_PERSISTENT = 6823,
++ MD_ERROR_WIN_CANT_BREAK_TRANSACTIONAL_DEPENDENCY = 6824,
++ MD_ERROR_WIN_CANT_CROSS_RM_BOUNDARY = 6825,
++ MD_ERROR_WIN_TXF_DIR_NOT_EMPTY = 6826,
++ MD_ERROR_WIN_INDOUBT_TRANSACTIONS_EXIST = 6827,
++ MD_ERROR_WIN_TM_VOLATILE = 6828,
++ MD_ERROR_WIN_ROLLBACK_TIMER_EXPIRED = 6829,
++ MD_ERROR_WIN_TXF_ATTRIBUTE_CORRUPT = 6830,
++ MD_ERROR_WIN_EFS_NOT_ALLOWED_IN_TRANSACTION = 6831,
++ MD_ERROR_WIN_TRANSACTIONAL_OPEN_NOT_ALLOWED = 6832,
++ MD_ERROR_WIN_LOG_GROWTH_FAILED = 6833,
++ MD_ERROR_WIN_TRANSACTED_MAPPING_UNSUPPORTED_REMOTE = 6834,
++ MD_ERROR_WIN_TXF_METADATA_ALREADY_PRESENT = 6835,
++ MD_ERROR_WIN_TRANSACTION_SCOPE_CALLBACKS_NOT_SET = 6836,
++ MD_ERROR_WIN_TRANSACTION_REQUIRED_PROMOTION = 6837,
++ MD_ERROR_WIN_CANNOT_EXECUTE_FILE_IN_TRANSACTION = 6838,
++ MD_ERROR_WIN_TRANSACTIONS_NOT_FROZEN = 6839,
++ MD_ERROR_WIN_TRANSACTION_FREEZE_IN_PROGRESS = 6840,
++ MD_ERROR_WIN_NOT_SNAPSHOT_VOLUME = 6841,
++ MD_ERROR_WIN_NO_SAVEPOINT_WITH_OPEN_FILES = 6842,
++ MD_ERROR_WIN_DATA_LOST_REPAIR = 6843,
++ MD_ERROR_WIN_SPARSE_NOT_ALLOWED_IN_TRANSACTION = 6844,
++ MD_ERROR_WIN_TM_IDENTITY_MISMATCH = 6845,
++ MD_ERROR_WIN_FLOATED_SECTION = 6846,
++ MD_ERROR_WIN_CANNOT_ACCEPT_TRANSACTED_WORK = 6847,
++ MD_ERROR_WIN_CANNOT_ABORT_TRANSACTIONS = 6848,
++ MD_ERROR_WIN_BAD_CLUSTERS = 6849,
++ MD_ERROR_WIN_COMPRESSION_NOT_ALLOWED_IN_TRANSACTION = 6850,
++ MD_ERROR_WIN_VOLUME_DIRTY = 6851,
++ MD_ERROR_WIN_NO_LINK_TRACKING_IN_TRANSACTION = 6852,
++ MD_ERROR_WIN_OPERATION_NOT_SUPPORTED_IN_TRANSACTION = 6853,
++ MD_ERROR_WIN_EXPIRED_HANDLE = 6854,
++ MD_ERROR_WIN_TRANSACTION_NOT_ENLISTED = 6855,
++ MD_ERROR_WIN_CTX_WINSTATION_NAME_INVALID = 7001,
++ MD_ERROR_WIN_CTX_INVALID_PD = 7002,
++ MD_ERROR_WIN_CTX_PD_NOT_FOUND = 7003,
++ MD_ERROR_WIN_CTX_WD_NOT_FOUND = 7004,
++ MD_ERROR_WIN_CTX_CANNOT_MAKE_EVENTLOG_ENTRY = 7005,
++ MD_ERROR_WIN_CTX_SERVICE_NAME_COLLISION = 7006,
++ MD_ERROR_WIN_CTX_CLOSE_PENDING = 7007,
++ MD_ERROR_WIN_CTX_NO_OUTBUF = 7008,
++ MD_ERROR_WIN_CTX_MODEM_INF_NOT_FOUND = 7009,
++ MD_ERROR_WIN_CTX_INVALID_MODEMNAME = 7010,
++ MD_ERROR_WIN_CTX_MODEM_RESPONSE_ERROR = 7011,
++ MD_ERROR_WIN_CTX_MODEM_RESPONSE_TIMEOUT = 7012,
++ MD_ERROR_WIN_CTX_MODEM_RESPONSE_NO_CARRIER = 7013,
++ MD_ERROR_WIN_CTX_MODEM_RESPONSE_NO_DIALTONE = 7014,
++ MD_ERROR_WIN_CTX_MODEM_RESPONSE_BUSY = 7015,
++ MD_ERROR_WIN_CTX_MODEM_RESPONSE_VOICE = 7016,
++ MD_ERROR_WIN_CTX_TD_ERROR = 7017,
++ MD_ERROR_WIN_CTX_WINSTATION_NOT_FOUND = 7022,
++ MD_ERROR_WIN_CTX_WINSTATION_ALREADY_EXISTS = 7023,
++ MD_ERROR_WIN_CTX_WINSTATION_BUSY = 7024,
++ MD_ERROR_WIN_CTX_BAD_VIDEO_MODE = 7025,
++ MD_ERROR_WIN_CTX_GRAPHICS_INVALID = 7035,
++ MD_ERROR_WIN_CTX_LOGON_DISABLED = 7037,
++ MD_ERROR_WIN_CTX_NOT_CONSOLE = 7038,
++ MD_ERROR_WIN_CTX_CLIENT_QUERY_TIMEOUT = 7040,
++ MD_ERROR_WIN_CTX_CONSOLE_DISCONNECT = 7041,
++ MD_ERROR_WIN_CTX_CONSOLE_CONNECT = 7042,
++ MD_ERROR_WIN_CTX_SHADOW_DENIED = 7044,
++ MD_ERROR_WIN_CTX_WINSTATION_ACCESS_DENIED = 7045,
++ MD_ERROR_WIN_CTX_INVALID_WD = 7049,
++ MD_ERROR_WIN_CTX_SHADOW_INVALID = 7050,
++ MD_ERROR_WIN_CTX_SHADOW_DISABLED = 7051,
++ MD_ERROR_WIN_CTX_CLIENT_LICENSE_IN_USE = 7052,
++ MD_ERROR_WIN_CTX_CLIENT_LICENSE_NOT_SET = 7053,
++ MD_ERROR_WIN_CTX_LICENSE_NOT_AVAILABLE = 7054,
++ MD_ERROR_WIN_CTX_LICENSE_CLIENT_INVALID = 7055,
++ MD_ERROR_WIN_CTX_LICENSE_EXPIRED = 7056,
++ MD_ERROR_WIN_CTX_SHADOW_NOT_RUNNING = 7057,
++ MD_ERROR_WIN_CTX_SHADOW_ENDED_BY_MODE_CHANGE = 7058,
++ MD_ERROR_WIN_ACTIVATION_COUNT_EXCEEDED = 7059,
++ MD_ERROR_WIN_CTX_WINSTATIONS_DISABLED = 7060,
++ MD_ERROR_WIN_CTX_ENCRYPTION_LEVEL_REQUIRED = 7061,
++ MD_ERROR_WIN_CTX_SESSION_IN_USE = 7062,
++ MD_ERROR_WIN_CTX_NO_FORCE_LOGOFF = 7063,
++ MD_ERROR_WIN_CTX_ACCOUNT_RESTRICTION = 7064,
++ MD_ERROR_WIN_RDP_PROTOCOL_ERROR = 7065,
++ MD_ERROR_WIN_CTX_CDM_CONNECT = 7066,
++ MD_ERROR_WIN_CTX_CDM_DISCONNECT = 7067,
++ MD_ERROR_WIN_CTX_SECURITY_LAYER_ERROR = 7068,
++ MD_ERROR_WIN_TS_INCOMPATIBLE_SESSIONS = 7069,
++ MD_ERROR_WIN_TS_VIDEO_SUBSYSTEM_ERROR = 7070,
++ MD_ERROR_WIN_DS_NOT_INSTALLED = 8200,
++ MD_ERROR_WIN_DS_MEMBERSHIP_EVALUATED_LOCALLY = 8201,
++ MD_ERROR_WIN_DS_NO_ATTRIBUTE_OR_VALUE = 8202,
++ MD_ERROR_WIN_DS_INVALID_ATTRIBUTE_SYNTAX = 8203,
++ MD_ERROR_WIN_DS_ATTRIBUTE_TYPE_UNDEFINED = 8204,
++ MD_ERROR_WIN_DS_ATTRIBUTE_OR_VALUE_EXISTS = 8205,
++ MD_ERROR_WIN_DS_BUSY = 8206,
++ MD_ERROR_WIN_DS_UNAVAILABLE = 8207,
++ MD_ERROR_WIN_DS_NO_RIDS_ALLOCATED = 8208,
++ MD_ERROR_WIN_DS_NO_MORE_RIDS = 8209,
++ MD_ERROR_WIN_DS_INCORRECT_ROLE_OWNER = 8210,
++ MD_ERROR_WIN_DS_RIDMGR_INIT_ERROR = 8211,
++ MD_ERROR_WIN_DS_OBJ_CLASS_VIOLATION = 8212,
++ MD_ERROR_WIN_DS_CANT_ON_NON_LEAF = 8213,
++ MD_ERROR_WIN_DS_CANT_ON_RDN = 8214,
++ MD_ERROR_WIN_DS_CANT_MOD_OBJ_CLASS = 8215,
++ MD_ERROR_WIN_DS_CROSS_DOM_MOVE_ERROR = 8216,
++ MD_ERROR_WIN_DS_GC_NOT_AVAILABLE = 8217,
++ MD_ERROR_WIN_SHARED_POLICY = 8218,
++ MD_ERROR_WIN_POLICY_OBJECT_NOT_FOUND = 8219,
++ MD_ERROR_WIN_POLICY_ONLY_IN_DS = 8220,
++ MD_ERROR_WIN_PROMOTION_ACTIVE = 8221,
++ MD_ERROR_WIN_NO_PROMOTION_ACTIVE = 8222,
++ MD_ERROR_WIN_DS_OPERATIONS_ERROR = 8224,
++ MD_ERROR_WIN_DS_PROTOCOL_ERROR = 8225,
++ MD_ERROR_WIN_DS_TIMELIMIT_EXCEEDED = 8226,
++ MD_ERROR_WIN_DS_SIZELIMIT_EXCEEDED = 8227,
++ MD_ERROR_WIN_DS_ADMIN_LIMIT_EXCEEDED = 8228,
++ MD_ERROR_WIN_DS_COMPARE_FALSE = 8229,
++ MD_ERROR_WIN_DS_COMPARE_TRUE = 8230,
++ MD_ERROR_WIN_DS_AUTH_METHOD_NOT_SUPPORTED = 8231,
++ MD_ERROR_WIN_DS_STRONG_AUTH_REQUIRED = 8232,
++ MD_ERROR_WIN_DS_INAPPROPRIATE_AUTH = 8233,
++ MD_ERROR_WIN_DS_AUTH_UNKNOWN = 8234,
++ MD_ERROR_WIN_DS_REFERRAL = 8235,
++ MD_ERROR_WIN_DS_UNAVAILABLE_CRIT_EXTENSION = 8236,
++ MD_ERROR_WIN_DS_CONFIDENTIALITY_REQUIRED = 8237,
++ MD_ERROR_WIN_DS_INAPPROPRIATE_MATCHING = 8238,
++ MD_ERROR_WIN_DS_CONSTRAINT_VIOLATION = 8239,
++ MD_ERROR_WIN_DS_NO_SUCH_OBJECT = 8240,
++ MD_ERROR_WIN_DS_ALIAS_PROBLEM = 8241,
++ MD_ERROR_WIN_DS_INVALID_DN_SYNTAX = 8242,
++ MD_ERROR_WIN_DS_IS_LEAF = 8243,
++ MD_ERROR_WIN_DS_ALIAS_DEREF_PROBLEM = 8244,
++ MD_ERROR_WIN_DS_UNWILLING_TO_PERFORM = 8245,
++ MD_ERROR_WIN_DS_LOOP_DETECT = 8246,
++ MD_ERROR_WIN_DS_NAMING_VIOLATION = 8247,
++ MD_ERROR_WIN_DS_OBJECT_RESULTS_TOO_LARGE = 8248,
++ MD_ERROR_WIN_DS_AFFECTS_MULTIPLE_DSAS = 8249,
++ MD_ERROR_WIN_DS_SERVER_DOWN = 8250,
++ MD_ERROR_WIN_DS_LOCAL_ERROR = 8251,
++ MD_ERROR_WIN_DS_ENCODING_ERROR = 8252,
++ MD_ERROR_WIN_DS_DECODING_ERROR = 8253,
++ MD_ERROR_WIN_DS_FILTER_UNKNOWN = 8254,
++ MD_ERROR_WIN_DS_PARAM_ERROR = 8255,
++ MD_ERROR_WIN_DS_NOT_SUPPORTED = 8256,
++ MD_ERROR_WIN_DS_NO_RESULTS_RETURNED = 8257,
++ MD_ERROR_WIN_DS_CONTROL_NOT_FOUND = 8258,
++ MD_ERROR_WIN_DS_CLIENT_LOOP = 8259,
++ MD_ERROR_WIN_DS_REFERRAL_LIMIT_EXCEEDED = 8260,
++ MD_ERROR_WIN_DS_SORT_CONTROL_MISSING = 8261,
++ MD_ERROR_WIN_DS_OFFSET_RANGE_ERROR = 8262,
++ MD_ERROR_WIN_DS_RIDMGR_DISABLED = 8263,
++ MD_ERROR_WIN_DS_ROOT_MUST_BE_NC = 8301,
++ MD_ERROR_WIN_DS_ADD_REPLICA_INHIBITED = 8302,
++ MD_ERROR_WIN_DS_ATT_NOT_DEF_IN_SCHEMA = 8303,
++ MD_ERROR_WIN_DS_MAX_OBJ_SIZE_EXCEEDED = 8304,
++ MD_ERROR_WIN_DS_OBJ_STRING_NAME_EXISTS = 8305,
++ MD_ERROR_WIN_DS_NO_RDN_DEFINED_IN_SCHEMA = 8306,
++ MD_ERROR_WIN_DS_RDN_DOESNT_MATCH_SCHEMA = 8307,
++ MD_ERROR_WIN_DS_NO_REQUESTED_ATTS_FOUND = 8308,
++ MD_ERROR_WIN_DS_USER_BUFFER_TO_SMALL = 8309,
++ MD_ERROR_WIN_DS_ATT_IS_NOT_ON_OBJ = 8310,
++ MD_ERROR_WIN_DS_ILLEGAL_MOD_OPERATION = 8311,
++ MD_ERROR_WIN_DS_OBJ_TOO_LARGE = 8312,
++ MD_ERROR_WIN_DS_BAD_INSTANCE_TYPE = 8313,
++ MD_ERROR_WIN_DS_MASTERDSA_REQUIRED = 8314,
++ MD_ERROR_WIN_DS_OBJECT_CLASS_REQUIRED = 8315,
++ MD_ERROR_WIN_DS_MISSING_REQUIRED_ATT = 8316,
++ MD_ERROR_WIN_DS_ATT_NOT_DEF_FOR_CLASS = 8317,
++ MD_ERROR_WIN_DS_ATT_ALREADY_EXISTS = 8318,
++ MD_ERROR_WIN_DS_CANT_ADD_ATT_VALUES = 8320,
++ MD_ERROR_WIN_DS_SINGLE_VALUE_CONSTRAINT = 8321,
++ MD_ERROR_WIN_DS_RANGE_CONSTRAINT = 8322,
++ MD_ERROR_WIN_DS_ATT_VAL_ALREADY_EXISTS = 8323,
++ MD_ERROR_WIN_DS_CANT_REM_MISSING_ATT = 8324,
++ MD_ERROR_WIN_DS_CANT_REM_MISSING_ATT_VAL = 8325,
++ MD_ERROR_WIN_DS_ROOT_CANT_BE_SUBREF = 8326,
++ MD_ERROR_WIN_DS_NO_CHAINING = 8327,
++ MD_ERROR_WIN_DS_NO_CHAINED_EVAL = 8328,
++ MD_ERROR_WIN_DS_NO_PARENT_OBJECT = 8329,
++ MD_ERROR_WIN_DS_PARENT_IS_AN_ALIAS = 8330,
++ MD_ERROR_WIN_DS_CANT_MIX_MASTER_AND_REPS = 8331,
++ MD_ERROR_WIN_DS_CHILDREN_EXIST = 8332,
++ MD_ERROR_WIN_DS_OBJ_NOT_FOUND = 8333,
++ MD_ERROR_WIN_DS_ALIASED_OBJ_MISSING = 8334,
++ MD_ERROR_WIN_DS_BAD_NAME_SYNTAX = 8335,
++ MD_ERROR_WIN_DS_ALIAS_POINTS_TO_ALIAS = 8336,
++ MD_ERROR_WIN_DS_CANT_DEREF_ALIAS = 8337,
++ MD_ERROR_WIN_DS_OUT_OF_SCOPE = 8338,
++ MD_ERROR_WIN_DS_OBJECT_BEING_REMOVED = 8339,
++ MD_ERROR_WIN_DS_CANT_DELETE_DSA_OBJ = 8340,
++ MD_ERROR_WIN_DS_GENERIC_ERROR = 8341,
++ MD_ERROR_WIN_DS_DSA_MUST_BE_INT_MASTER = 8342,
++ MD_ERROR_WIN_DS_CLASS_NOT_DSA = 8343,
++ MD_ERROR_WIN_DS_INSUFF_ACCESS_RIGHTS = 8344,
++ MD_ERROR_WIN_DS_ILLEGAL_SUPERIOR = 8345,
++ MD_ERROR_WIN_DS_ATTRIBUTE_OWNED_BY_SAM = 8346,
++ MD_ERROR_WIN_DS_NAME_TOO_MANY_PARTS = 8347,
++ MD_ERROR_WIN_DS_NAME_TOO_LONG = 8348,
++ MD_ERROR_WIN_DS_NAME_VALUE_TOO_LONG = 8349,
++ MD_ERROR_WIN_DS_NAME_UNPARSEABLE = 8350,
++ MD_ERROR_WIN_DS_NAME_TYPE_UNKNOWN = 8351,
++ MD_ERROR_WIN_DS_NOT_AN_OBJECT = 8352,
++ MD_ERROR_WIN_DS_SEC_DESC_TOO_SHORT = 8353,
++ MD_ERROR_WIN_DS_SEC_DESC_INVALID = 8354,
++ MD_ERROR_WIN_DS_NO_DELETED_NAME = 8355,
++ MD_ERROR_WIN_DS_SUBREF_MUST_HAVE_PARENT = 8356,
++ MD_ERROR_WIN_DS_NCNAME_MUST_BE_NC = 8357,
++ MD_ERROR_WIN_DS_CANT_ADD_SYSTEM_ONLY = 8358,
++ MD_ERROR_WIN_DS_CLASS_MUST_BE_CONCRETE = 8359,
++ MD_ERROR_WIN_DS_INVALID_DMD = 8360,
++ MD_ERROR_WIN_DS_OBJ_GUID_EXISTS = 8361,
++ MD_ERROR_WIN_DS_NOT_ON_BACKLINK = 8362,
++ MD_ERROR_WIN_DS_NO_CROSSREF_FOR_NC = 8363,
++ MD_ERROR_WIN_DS_SHUTTING_DOWN = 8364,
++ MD_ERROR_WIN_DS_UNKNOWN_OPERATION = 8365,
++ MD_ERROR_WIN_DS_INVALID_ROLE_OWNER = 8366,
++ MD_ERROR_WIN_DS_COULDNT_CONTACT_FSMO = 8367,
++ MD_ERROR_WIN_DS_CROSS_NC_DN_RENAME = 8368,
++ MD_ERROR_WIN_DS_CANT_MOD_SYSTEM_ONLY = 8369,
++ MD_ERROR_WIN_DS_REPLICATOR_ONLY = 8370,
++ MD_ERROR_WIN_DS_OBJ_CLASS_NOT_DEFINED = 8371,
++ MD_ERROR_WIN_DS_OBJ_CLASS_NOT_SUBCLASS = 8372,
++ MD_ERROR_WIN_DS_NAME_REFERENCE_INVALID = 8373,
++ MD_ERROR_WIN_DS_CROSS_REF_EXISTS = 8374,
++ MD_ERROR_WIN_DS_CANT_DEL_MASTER_CROSSREF = 8375,
++ MD_ERROR_WIN_DS_SUBTREE_NOTIFY_NOT_NC_HEAD = 8376,
++ MD_ERROR_WIN_DS_NOTIFY_FILTER_TOO_COMPLEX = 8377,
++ MD_ERROR_WIN_DS_DUP_RDN = 8378,
++ MD_ERROR_WIN_DS_DUP_OID = 8379,
++ MD_ERROR_WIN_DS_DUP_MAPI_ID = 8380,
++ MD_ERROR_WIN_DS_DUP_SCHEMA_ID_GUID = 8381,
++ MD_ERROR_WIN_DS_DUP_LDAP_DISPLAY_NAME = 8382,
++ MD_ERROR_WIN_DS_SEMANTIC_ATT_TEST = 8383,
++ MD_ERROR_WIN_DS_SYNTAX_MISMATCH = 8384,
++ MD_ERROR_WIN_DS_EXISTS_IN_MUST_HAVE = 8385,
++ MD_ERROR_WIN_DS_EXISTS_IN_MAY_HAVE = 8386,
++ MD_ERROR_WIN_DS_NONEXISTENT_MAY_HAVE = 8387,
++ MD_ERROR_WIN_DS_NONEXISTENT_MUST_HAVE = 8388,
++ MD_ERROR_WIN_DS_AUX_CLS_TEST_FAIL = 8389,
++ MD_ERROR_WIN_DS_NONEXISTENT_POSS_SUP = 8390,
++ MD_ERROR_WIN_DS_SUB_CLS_TEST_FAIL = 8391,
++ MD_ERROR_WIN_DS_BAD_RDN_ATT_ID_SYNTAX = 8392,
++ MD_ERROR_WIN_DS_EXISTS_IN_AUX_CLS = 8393,
++ MD_ERROR_WIN_DS_EXISTS_IN_SUB_CLS = 8394,
++ MD_ERROR_WIN_DS_EXISTS_IN_POSS_SUP = 8395,
++ MD_ERROR_WIN_DS_RECALCSCHEMA_FAILED = 8396,
++ MD_ERROR_WIN_DS_TREE_DELETE_NOT_FINISHED = 8397,
++ MD_ERROR_WIN_DS_CANT_DELETE = 8398,
++ MD_ERROR_WIN_DS_ATT_SCHEMA_REQ_ID = 8399,
++ MD_ERROR_WIN_DS_BAD_ATT_SCHEMA_SYNTAX = 8400,
++ MD_ERROR_WIN_DS_CANT_CACHE_ATT = 8401,
++ MD_ERROR_WIN_DS_CANT_CACHE_CLASS = 8402,
++ MD_ERROR_WIN_DS_CANT_REMOVE_ATT_CACHE = 8403,
++ MD_ERROR_WIN_DS_CANT_REMOVE_CLASS_CACHE = 8404,
++ MD_ERROR_WIN_DS_CANT_RETRIEVE_DN = 8405,
++ MD_ERROR_WIN_DS_MISSING_SUPREF = 8406,
++ MD_ERROR_WIN_DS_CANT_RETRIEVE_INSTANCE = 8407,
++ MD_ERROR_WIN_DS_CODE_INCONSISTENCY = 8408,
++ MD_ERROR_WIN_DS_DATABASE_ERROR = 8409,
++ MD_ERROR_WIN_DS_GOVERNSID_MISSING = 8410,
++ MD_ERROR_WIN_DS_MISSING_EXPECTED_ATT = 8411,
++ MD_ERROR_WIN_DS_NCNAME_MISSING_CR_REF = 8412,
++ MD_ERROR_WIN_DS_SECURITY_CHECKING_ERROR = 8413,
++ MD_ERROR_WIN_DS_SCHEMA_NOT_LOADED = 8414,
++ MD_ERROR_WIN_DS_SCHEMA_ALLOC_FAILED = 8415,
++ MD_ERROR_WIN_DS_ATT_SCHEMA_REQ_SYNTAX = 8416,
++ MD_ERROR_WIN_DS_GCVERIFY_ERROR = 8417,
++ MD_ERROR_WIN_DS_DRA_SCHEMA_MISMATCH = 8418,
++ MD_ERROR_WIN_DS_CANT_FIND_DSA_OBJ = 8419,
++ MD_ERROR_WIN_DS_CANT_FIND_EXPECTED_NC = 8420,
++ MD_ERROR_WIN_DS_CANT_FIND_NC_IN_CACHE = 8421,
++ MD_ERROR_WIN_DS_CANT_RETRIEVE_CHILD = 8422,
++ MD_ERROR_WIN_DS_SECURITY_ILLEGAL_MODIFY = 8423,
++ MD_ERROR_WIN_DS_CANT_REPLACE_HIDDEN_REC = 8424,
++ MD_ERROR_WIN_DS_BAD_HIERARCHY_FILE = 8425,
++ MD_ERROR_WIN_DS_BUILD_HIERARCHY_TABLE_FAILED = 8426,
++ MD_ERROR_WIN_DS_CONFIG_PARAM_MISSING = 8427,
++ MD_ERROR_WIN_DS_COUNTING_AB_INDICES_FAILED = 8428,
++ MD_ERROR_WIN_DS_HIERARCHY_TABLE_MALLOC_FAILED = 8429,
++ MD_ERROR_WIN_DS_INTERNAL_FAILURE = 8430,
++ MD_ERROR_WIN_DS_UNKNOWN_ERROR = 8431,
++ MD_ERROR_WIN_DS_ROOT_REQUIRES_CLASS_TOP = 8432,
++ MD_ERROR_WIN_DS_REFUSING_FSMO_ROLES = 8433,
++ MD_ERROR_WIN_DS_MISSING_FSMO_SETTINGS = 8434,
++ MD_ERROR_WIN_DS_UNABLE_TO_SURRENDER_ROLES = 8435,
++ MD_ERROR_WIN_DS_DRA_GENERIC = 8436,
++ MD_ERROR_WIN_DS_DRA_INVALID_PARAMETER = 8437,
++ MD_ERROR_WIN_DS_DRA_BUSY = 8438,
++ MD_ERROR_WIN_DS_DRA_BAD_DN = 8439,
++ MD_ERROR_WIN_DS_DRA_BAD_NC = 8440,
++ MD_ERROR_WIN_DS_DRA_DN_EXISTS = 8441,
++ MD_ERROR_WIN_DS_DRA_INTERNAL_ERROR = 8442,
++ MD_ERROR_WIN_DS_DRA_INCONSISTENT_DIT = 8443,
++ MD_ERROR_WIN_DS_DRA_CONNECTION_FAILED = 8444,
++ MD_ERROR_WIN_DS_DRA_BAD_INSTANCE_TYPE = 8445,
++ MD_ERROR_WIN_DS_DRA_OUT_OF_MEM = 8446,
++ MD_ERROR_WIN_DS_DRA_MAIL_PROBLEM = 8447,
++ MD_ERROR_WIN_DS_DRA_REF_ALREADY_EXISTS = 8448,
++ MD_ERROR_WIN_DS_DRA_REF_NOT_FOUND = 8449,
++ MD_ERROR_WIN_DS_DRA_OBJ_IS_REP_SOURCE = 8450,
++ MD_ERROR_WIN_DS_DRA_DB_ERROR = 8451,
++ MD_ERROR_WIN_DS_DRA_NO_REPLICA = 8452,
++ MD_ERROR_WIN_DS_DRA_ACCESS_DENIED = 8453,
++ MD_ERROR_WIN_DS_DRA_NOT_SUPPORTED = 8454,
++ MD_ERROR_WIN_DS_DRA_RPC_CANCELLED = 8455,
++ MD_ERROR_WIN_DS_DRA_SOURCE_DISABLED = 8456,
++ MD_ERROR_WIN_DS_DRA_SINK_DISABLED = 8457,
++ MD_ERROR_WIN_DS_DRA_NAME_COLLISION = 8458,
++ MD_ERROR_WIN_DS_DRA_SOURCE_REINSTALLED = 8459,
++ MD_ERROR_WIN_DS_DRA_MISSING_PARENT = 8460,
++ MD_ERROR_WIN_DS_DRA_PREEMPTED = 8461,
++ MD_ERROR_WIN_DS_DRA_ABANDON_SYNC = 8462,
++ MD_ERROR_WIN_DS_DRA_SHUTDOWN = 8463,
++ MD_ERROR_WIN_DS_DRA_INCOMPATIBLE_PARTIAL_SET = 8464,
++ MD_ERROR_WIN_DS_DRA_SOURCE_IS_PARTIAL_REPLICA = 8465,
++ MD_ERROR_WIN_DS_DRA_EXTN_CONNECTION_FAILED = 8466,
++ MD_ERROR_WIN_DS_INSTALL_SCHEMA_MISMATCH = 8467,
++ MD_ERROR_WIN_DS_DUP_LINK_ID = 8468,
++ MD_ERROR_WIN_DS_NAME_ERROR_RESOLVING = 8469,
++ MD_ERROR_WIN_DS_NAME_ERROR_NOT_FOUND = 8470,
++ MD_ERROR_WIN_DS_NAME_ERROR_NOT_UNIQUE = 8471,
++ MD_ERROR_WIN_DS_NAME_ERROR_NO_MAPPING = 8472,
++ MD_ERROR_WIN_DS_NAME_ERROR_DOMAIN_ONLY = 8473,
++ MD_ERROR_WIN_DS_NAME_ERROR_NO_SYNTACTICAL_MAPPING = 8474,
++ MD_ERROR_WIN_DS_CONSTRUCTED_ATT_MOD = 8475,
++ MD_ERROR_WIN_DS_WRONG_OM_OBJ_CLASS = 8476,
++ MD_ERROR_WIN_DS_DRA_REPL_PENDING = 8477,
++ MD_ERROR_WIN_DS_DS_REQUIRED = 8478,
++ MD_ERROR_WIN_DS_INVALID_LDAP_DISPLAY_NAME = 8479,
++ MD_ERROR_WIN_DS_NON_BASE_SEARCH = 8480,
++ MD_ERROR_WIN_DS_CANT_RETRIEVE_ATTS = 8481,
++ MD_ERROR_WIN_DS_BACKLINK_WITHOUT_LINK = 8482,
++ MD_ERROR_WIN_DS_EPOCH_MISMATCH = 8483,
++ MD_ERROR_WIN_DS_SRC_NAME_MISMATCH = 8484,
++ MD_ERROR_WIN_DS_SRC_AND_DST_NC_IDENTICAL = 8485,
++ MD_ERROR_WIN_DS_DST_NC_MISMATCH = 8486,
++ MD_ERROR_WIN_DS_NOT_AUTHORITIVE_FOR_DST_NC = 8487,
++ MD_ERROR_WIN_DS_SRC_GUID_MISMATCH = 8488,
++ MD_ERROR_WIN_DS_CANT_MOVE_DELETED_OBJECT = 8489,
++ MD_ERROR_WIN_DS_PDC_OPERATION_IN_PROGRESS = 8490,
++ MD_ERROR_WIN_DS_CROSS_DOMAIN_CLEANUP_REQD = 8491,
++ MD_ERROR_WIN_DS_ILLEGAL_XDOM_MOVE_OPERATION = 8492,
++ MD_ERROR_WIN_DS_CANT_WITH_ACCT_GROUP_MEMBERSHPS = 8493,
++ MD_ERROR_WIN_DS_NC_MUST_HAVE_NC_PARENT = 8494,
++ MD_ERROR_WIN_DS_CR_IMPOSSIBLE_TO_VALIDATE = 8495,
++ MD_ERROR_WIN_DS_DST_DOMAIN_NOT_NATIVE = 8496,
++ MD_ERROR_WIN_DS_MISSING_INFRASTRUCTURE_CONTAINER = 8497,
++ MD_ERROR_WIN_DS_CANT_MOVE_ACCOUNT_GROUP = 8498,
++ MD_ERROR_WIN_DS_CANT_MOVE_RESOURCE_GROUP = 8499,
++ MD_ERROR_WIN_DS_INVALID_SEARCH_FLAG = 8500,
++ MD_ERROR_WIN_DS_NO_TREE_DELETE_ABOVE_NC = 8501,
++ MD_ERROR_WIN_DS_COULDNT_LOCK_TREE_FOR_DELETE = 8502,
++ MD_ERROR_WIN_DS_COULDNT_IDENTIFY_OBJECTS_FOR_TREE_DELETE = 8503,
++ MD_ERROR_WIN_DS_SAM_INIT_FAILURE = 8504,
++ MD_ERROR_WIN_DS_SENSITIVE_GROUP_VIOLATION = 8505,
++ MD_ERROR_WIN_DS_CANT_MOD_PRIMARYGROUPID = 8506,
++ MD_ERROR_WIN_DS_ILLEGAL_BASE_SCHEMA_MOD = 8507,
++ MD_ERROR_WIN_DS_NONSAFE_SCHEMA_CHANGE = 8508,
++ MD_ERROR_WIN_DS_SCHEMA_UPDATE_DISALLOWED = 8509,
++ MD_ERROR_WIN_DS_CANT_CREATE_UNDER_SCHEMA = 8510,
++ MD_ERROR_WIN_DS_INSTALL_NO_SRC_SCH_VERSION = 8511,
++ MD_ERROR_WIN_DS_INSTALL_NO_SCH_VERSION_IN_INIFILE = 8512,
++ MD_ERROR_WIN_DS_INVALID_GROUP_TYPE = 8513,
++ MD_ERROR_WIN_DS_NO_NEST_GLOBALGROUP_IN_MIXEDDOMAIN = 8514,
++ MD_ERROR_WIN_DS_NO_NEST_LOCALGROUP_IN_MIXEDDOMAIN = 8515,
++ MD_ERROR_WIN_DS_GLOBAL_CANT_HAVE_LOCAL_MEMBER = 8516,
++ MD_ERROR_WIN_DS_GLOBAL_CANT_HAVE_UNIVERSAL_MEMBER = 8517,
++ MD_ERROR_WIN_DS_UNIVERSAL_CANT_HAVE_LOCAL_MEMBER = 8518,
++ MD_ERROR_WIN_DS_GLOBAL_CANT_HAVE_CROSSDOMAIN_MEMBER = 8519,
++ MD_ERROR_WIN_DS_LOCAL_CANT_HAVE_CROSSDOMAIN_LOCAL_MEMBER = 8520,
++ MD_ERROR_WIN_DS_HAVE_PRIMARY_MEMBERS = 8521,
++ MD_ERROR_WIN_DS_STRING_SD_CONVERSION_FAILED = 8522,
++ MD_ERROR_WIN_DS_NAMING_MASTER_GC = 8523,
++ MD_ERROR_WIN_DS_DNS_LOOKUP_FAILURE = 8524,
++ MD_ERROR_WIN_DS_COULDNT_UPDATE_SPNS = 8525,
++ MD_ERROR_WIN_DS_CANT_RETRIEVE_SD = 8526,
++ MD_ERROR_WIN_DS_KEY_NOT_UNIQUE = 8527,
++ MD_ERROR_WIN_DS_WRONG_LINKED_ATT_SYNTAX = 8528,
++ MD_ERROR_WIN_DS_SAM_NEED_BOOTKEY_PASSWORD = 8529,
++ MD_ERROR_WIN_DS_SAM_NEED_BOOTKEY_FLOPPY = 8530,
++ MD_ERROR_WIN_DS_CANT_START = 8531,
++ MD_ERROR_WIN_DS_INIT_FAILURE = 8532,
++ MD_ERROR_WIN_DS_NO_PKT_PRIVACY_ON_CONNECTION = 8533,
++ MD_ERROR_WIN_DS_SOURCE_DOMAIN_IN_FOREST = 8534,
++ MD_ERROR_WIN_DS_DESTINATION_DOMAIN_NOT_IN_FOREST = 8535,
++ MD_ERROR_WIN_DS_DESTINATION_AUDITING_NOT_ENABLED = 8536,
++ MD_ERROR_WIN_DS_CANT_FIND_DC_FOR_SRC_DOMAIN = 8537,
++ MD_ERROR_WIN_DS_SRC_OBJ_NOT_GROUP_OR_USER = 8538,
++ MD_ERROR_WIN_DS_SRC_SID_EXISTS_IN_FOREST = 8539,
++ MD_ERROR_WIN_DS_SRC_AND_DST_OBJECT_CLASS_MISMATCH = 8540,
++ MD_ERROR_WIN_SAM_INIT_FAILURE = 8541,
++ MD_ERROR_WIN_DS_DRA_SCHEMA_INFO_SHIP = 8542,
++ MD_ERROR_WIN_DS_DRA_SCHEMA_CONFLICT = 8543,
++ MD_ERROR_WIN_DS_DRA_EARLIER_SCHEMA_CONFLICT = 8544,
++ MD_ERROR_WIN_DS_DRA_OBJ_NC_MISMATCH = 8545,
++ MD_ERROR_WIN_DS_NC_STILL_HAS_DSAS = 8546,
++ MD_ERROR_WIN_DS_GC_REQUIRED = 8547,
++ MD_ERROR_WIN_DS_LOCAL_MEMBER_OF_LOCAL_ONLY = 8548,
++ MD_ERROR_WIN_DS_NO_FPO_IN_UNIVERSAL_GROUPS = 8549,
++ MD_ERROR_WIN_DS_CANT_ADD_TO_GC = 8550,
++ MD_ERROR_WIN_DS_NO_CHECKPOINT_WITH_PDC = 8551,
++ MD_ERROR_WIN_DS_SOURCE_AUDITING_NOT_ENABLED = 8552,
++ MD_ERROR_WIN_DS_CANT_CREATE_IN_NONDOMAIN_NC = 8553,
++ MD_ERROR_WIN_DS_INVALID_NAME_FOR_SPN = 8554,
++ MD_ERROR_WIN_DS_FILTER_USES_CONTRUCTED_ATTRS = 8555,
++ MD_ERROR_WIN_DS_UNICODEPWD_NOT_IN_QUOTES = 8556,
++ MD_ERROR_WIN_DS_MACHINE_ACCOUNT_QUOTA_EXCEEDED = 8557,
++ MD_ERROR_WIN_DS_MUST_BE_RUN_ON_DST_DC = 8558,
++ MD_ERROR_WIN_DS_SRC_DC_MUST_BE_SP4_OR_GREATER = 8559,
++ MD_ERROR_WIN_DS_CANT_TREE_DELETE_CRITICAL_OBJ = 8560,
++ MD_ERROR_WIN_DS_INIT_FAILURE_CONSOLE = 8561,
++ MD_ERROR_WIN_DS_SAM_INIT_FAILURE_CONSOLE = 8562,
++ MD_ERROR_WIN_DS_FOREST_VERSION_TOO_HIGH = 8563,
++ MD_ERROR_WIN_DS_DOMAIN_VERSION_TOO_HIGH = 8564,
++ MD_ERROR_WIN_DS_FOREST_VERSION_TOO_LOW = 8565,
++ MD_ERROR_WIN_DS_DOMAIN_VERSION_TOO_LOW = 8566,
++ MD_ERROR_WIN_DS_INCOMPATIBLE_VERSION = 8567,
++ MD_ERROR_WIN_DS_LOW_DSA_VERSION = 8568,
++ MD_ERROR_WIN_DS_NO_BEHAVIOR_VERSION_IN_MIXEDDOMAIN = 8569,
++ MD_ERROR_WIN_DS_NOT_SUPPORTED_SORT_ORDER = 8570,
++ MD_ERROR_WIN_DS_NAME_NOT_UNIQUE = 8571,
++ MD_ERROR_WIN_DS_MACHINE_ACCOUNT_CREATED_PRENT4 = 8572,
++ MD_ERROR_WIN_DS_OUT_OF_VERSION_STORE = 8573,
++ MD_ERROR_WIN_DS_INCOMPATIBLE_CONTROLS_USED = 8574,
++ MD_ERROR_WIN_DS_NO_REF_DOMAIN = 8575,
++ MD_ERROR_WIN_DS_RESERVED_LINK_ID = 8576,
++ MD_ERROR_WIN_DS_LINK_ID_NOT_AVAILABLE = 8577,
++ MD_ERROR_WIN_DS_AG_CANT_HAVE_UNIVERSAL_MEMBER = 8578,
++ MD_ERROR_WIN_DS_MODIFYDN_DISALLOWED_BY_INSTANCE_TYPE = 8579,
++ MD_ERROR_WIN_DS_NO_OBJECT_MOVE_IN_SCHEMA_NC = 8580,
++ MD_ERROR_WIN_DS_MODIFYDN_DISALLOWED_BY_FLAG = 8581,
++ MD_ERROR_WIN_DS_MODIFYDN_WRONG_GRANDPARENT = 8582,
++ MD_ERROR_WIN_DS_NAME_ERROR_TRUST_REFERRAL = 8583,
++ MD_ERROR_WIN_NOT_SUPPORTED_ON_STANDARD_SERVER = 8584,
++ MD_ERROR_WIN_DS_CANT_ACCESS_REMOTE_PART_OF_AD = 8585,
++ MD_ERROR_WIN_DS_CR_IMPOSSIBLE_TO_VALIDATE_V2 = 8586,
++ MD_ERROR_WIN_DS_THREAD_LIMIT_EXCEEDED = 8587,
++ MD_ERROR_WIN_DS_NOT_CLOSEST = 8588,
++ MD_ERROR_WIN_DS_CANT_DERIVE_SPN_WITHOUT_SERVER_REF = 8589,
++ MD_ERROR_WIN_DS_SINGLE_USER_MODE_FAILED = 8590,
++ MD_ERROR_WIN_DS_NTDSCRIPT_SYNTAX_ERROR = 8591,
++ MD_ERROR_WIN_DS_NTDSCRIPT_PROCESS_ERROR = 8592,
++ MD_ERROR_WIN_DS_DIFFERENT_REPL_EPOCHS = 8593,
++ MD_ERROR_WIN_DS_DRS_EXTENSIONS_CHANGED = 8594,
++ MD_ERROR_WIN_DS_REPLICA_SET_CHANGE_NOT_ALLOWED_ON_DISABLED_CR = 8595,
++ MD_ERROR_WIN_DS_NO_MSDS_INTID = 8596,
++ MD_ERROR_WIN_DS_DUP_MSDS_INTID = 8597,
++ MD_ERROR_WIN_DS_EXISTS_IN_RDNATTID = 8598,
++ MD_ERROR_WIN_DS_AUTHORIZATION_FAILED = 8599,
++ MD_ERROR_WIN_DS_INVALID_SCRIPT = 8600,
++ MD_ERROR_WIN_DS_REMOTE_CROSSREF_OP_FAILED = 8601,
++ MD_ERROR_WIN_DS_CROSS_REF_BUSY = 8602,
++ MD_ERROR_WIN_DS_CANT_DERIVE_SPN_FOR_DELETED_DOMAIN = 8603,
++ MD_ERROR_WIN_DS_CANT_DEMOTE_WITH_WRITEABLE_NC = 8604,
++ MD_ERROR_WIN_DS_DUPLICATE_ID_FOUND = 8605,
++ MD_ERROR_WIN_DS_INSUFFICIENT_ATTR_TO_CREATE_OBJECT = 8606,
++ MD_ERROR_WIN_DS_GROUP_CONVERSION_ERROR = 8607,
++ MD_ERROR_WIN_DS_CANT_MOVE_APP_BASIC_GROUP = 8608,
++ MD_ERROR_WIN_DS_CANT_MOVE_APP_QUERY_GROUP = 8609,
++ MD_ERROR_WIN_DS_ROLE_NOT_VERIFIED = 8610,
++ MD_ERROR_WIN_DS_WKO_CONTAINER_CANNOT_BE_SPECIAL = 8611,
++ MD_ERROR_WIN_DS_DOMAIN_RENAME_IN_PROGRESS = 8612,
++ MD_ERROR_WIN_DS_EXISTING_AD_CHILD_NC = 8613,
++ MD_ERROR_WIN_DS_REPL_LIFETIME_EXCEEDED = 8614,
++ MD_ERROR_WIN_DS_DISALLOWED_IN_SYSTEM_CONTAINER = 8615,
++ MD_ERROR_WIN_DS_LDAP_SEND_QUEUE_FULL = 8616,
++ MD_ERROR_WIN_DS_DRA_OUT_SCHEDULE_WINDOW = 8617,
++ MD_ERROR_WIN_DS_POLICY_NOT_KNOWN = 8618,
++ MD_ERROR_WIN_NO_SITE_SETTINGS_OBJECT = 8619,
++ MD_ERROR_WIN_NO_SECRETS = 8620,
++ MD_ERROR_WIN_NO_WRITABLE_DC_FOUND = 8621,
++ MD_ERROR_WIN_DS_NO_SERVER_OBJECT = 8622,
++ MD_ERROR_WIN_DS_NO_NTDSA_OBJECT = 8623,
++ MD_ERROR_WIN_DS_NON_ASQ_SEARCH = 8624,
++ MD_ERROR_WIN_DS_AUDIT_FAILURE = 8625,
++ MD_ERROR_WIN_DS_INVALID_SEARCH_FLAG_SUBTREE = 8626,
++ MD_ERROR_WIN_DS_INVALID_SEARCH_FLAG_TUPLE = 8627,
++ MD_ERROR_WIN_DS_HIERARCHY_TABLE_TOO_DEEP = 8628,
++ MD_ERROR_WIN_DS_DRA_CORRUPT_UTD_VECTOR = 8629,
++ MD_ERROR_WIN_DS_DRA_SECRETS_DENIED = 8630,
++ MD_ERROR_WIN_DS_RESERVED_MAPI_ID = 8631,
++ MD_ERROR_WIN_DS_MAPI_ID_NOT_AVAILABLE = 8632,
++ MD_ERROR_WIN_DS_DRA_MISSING_KRBTGT_SECRET = 8633,
++ MD_ERROR_WIN_DS_DOMAIN_NAME_EXISTS_IN_FOREST = 8634,
++ MD_ERROR_WIN_DS_FLAT_NAME_EXISTS_IN_FOREST = 8635,
++ MD_ERROR_WIN_INVALID_USER_PRINCIPAL_NAME = 8636,
++ MD_ERROR_WIN_DS_OID_MAPPED_GROUP_CANT_HAVE_MEMBERS = 8637,
++ MD_ERROR_WIN_DS_OID_NOT_FOUND = 8638,
++ MD_ERROR_WIN_DS_DRA_RECYCLED_TARGET = 8639,
++ MD_ERROR_WIN_DS_DISALLOWED_NC_REDIRECT = 8640,
++ MD_ERROR_WIN_DS_HIGH_ADLDS_FFL = 8641,
++ MD_ERROR_WIN_DS_HIGH_DSA_VERSION = 8642,
++ MD_ERROR_WIN_DS_LOW_ADLDS_FFL = 8643,
++ MD_ERROR_WIN_DOMAIN_SID_SAME_AS_LOCAL_WORKSTATION = 8644,
++ MD_ERROR_WIN_DS_UNDELETE_SAM_VALIDATION_FAILED = 8645,
++ MD_ERROR_WIN_INCORRECT_ACCOUNT_TYPE = 8646,
++ MD_ERROR_WIN_DS_SPN_VALUE_NOT_UNIQUE_IN_FOREST = 8647,
++ MD_ERROR_WIN_DS_UPN_VALUE_NOT_UNIQUE_IN_FOREST = 8648,
++ MD_ERROR_WIN_DS_MISSING_FOREST_TRUST = 8649,
++ MD_ERROR_WIN_DS_VALUE_KEY_NOT_UNIQUE = 8650,
++ MD_ERROR_WIN_IPSEC_QM_POLICY_EXISTS = 13000,
++ MD_ERROR_WIN_IPSEC_QM_POLICY_NOT_FOUND = 13001,
++ MD_ERROR_WIN_IPSEC_QM_POLICY_IN_USE = 13002,
++ MD_ERROR_WIN_IPSEC_MM_POLICY_EXISTS = 13003,
++ MD_ERROR_WIN_IPSEC_MM_POLICY_NOT_FOUND = 13004,
++ MD_ERROR_WIN_IPSEC_MM_POLICY_IN_USE = 13005,
++ MD_ERROR_WIN_IPSEC_MM_FILTER_EXISTS = 13006,
++ MD_ERROR_WIN_IPSEC_MM_FILTER_NOT_FOUND = 13007,
++ MD_ERROR_WIN_IPSEC_TRANSPORT_FILTER_EXISTS = 13008,
++ MD_ERROR_WIN_IPSEC_TRANSPORT_FILTER_NOT_FOUND = 13009,
++ MD_ERROR_WIN_IPSEC_MM_AUTH_EXISTS = 13010,
++ MD_ERROR_WIN_IPSEC_MM_AUTH_NOT_FOUND = 13011,
++ MD_ERROR_WIN_IPSEC_MM_AUTH_IN_USE = 13012,
++ MD_ERROR_WIN_IPSEC_DEFAULT_MM_POLICY_NOT_FOUND = 13013,
++ MD_ERROR_WIN_IPSEC_DEFAULT_MM_AUTH_NOT_FOUND = 13014,
++ MD_ERROR_WIN_IPSEC_DEFAULT_QM_POLICY_NOT_FOUND = 13015,
++ MD_ERROR_WIN_IPSEC_TUNNEL_FILTER_EXISTS = 13016,
++ MD_ERROR_WIN_IPSEC_TUNNEL_FILTER_NOT_FOUND = 13017,
++ MD_ERROR_WIN_IPSEC_MM_FILTER_PENDING_DELETION = 13018,
++ MD_ERROR_WIN_IPSEC_TRANSPORT_FILTER_PENDING_DELETION = 13019,
++ MD_ERROR_WIN_IPSEC_TUNNEL_FILTER_PENDING_DELETION = 13020,
++ MD_ERROR_WIN_IPSEC_MM_POLICY_PENDING_DELETION = 13021,
++ MD_ERROR_WIN_IPSEC_MM_AUTH_PENDING_DELETION = 13022,
++ MD_ERROR_WIN_IPSEC_QM_POLICY_PENDING_DELETION = 13023,
++ MD_ERROR_WIN_IPSEC_IKE_NEG_STATUS_BEGIN = 13800,
++ MD_ERROR_WIN_IPSEC_IKE_AUTH_FAIL = 13801,
++ MD_ERROR_WIN_IPSEC_IKE_ATTRIB_FAIL = 13802,
++ MD_ERROR_WIN_IPSEC_IKE_NEGOTIATION_PENDING = 13803,
++ MD_ERROR_WIN_IPSEC_IKE_GENERAL_PROCESSING_ERROR = 13804,
++ MD_ERROR_WIN_IPSEC_IKE_TIMED_OUT = 13805,
++ MD_ERROR_WIN_IPSEC_IKE_NO_CERT = 13806,
++ MD_ERROR_WIN_IPSEC_IKE_SA_DELETED = 13807,
++ MD_ERROR_WIN_IPSEC_IKE_SA_REAPED = 13808,
++ MD_ERROR_WIN_IPSEC_IKE_MM_ACQUIRE_DROP = 13809,
++ MD_ERROR_WIN_IPSEC_IKE_QM_ACQUIRE_DROP = 13810,
++ MD_ERROR_WIN_IPSEC_IKE_QUEUE_DROP_MM = 13811,
++ MD_ERROR_WIN_IPSEC_IKE_QUEUE_DROP_NO_MM = 13812,
++ MD_ERROR_WIN_IPSEC_IKE_DROP_NO_RESPONSE = 13813,
++ MD_ERROR_WIN_IPSEC_IKE_MM_DELAY_DROP = 13814,
++ MD_ERROR_WIN_IPSEC_IKE_QM_DELAY_DROP = 13815,
++ MD_ERROR_WIN_IPSEC_IKE_ERROR = 13816,
++ MD_ERROR_WIN_IPSEC_IKE_CRL_FAILED = 13817,
++ MD_ERROR_WIN_IPSEC_IKE_INVALID_KEY_USAGE = 13818,
++ MD_ERROR_WIN_IPSEC_IKE_INVALID_CERT_TYPE = 13819,
++ MD_ERROR_WIN_IPSEC_IKE_NO_PRIVATE_KEY = 13820,
++ MD_ERROR_WIN_IPSEC_IKE_SIMULTANEOUS_REKEY = 13821,
++ MD_ERROR_WIN_IPSEC_IKE_DH_FAIL = 13822,
++ MD_ERROR_WIN_IPSEC_IKE_CRITICAL_PAYLOAD_NOT_RECOGNIZED = 13823,
++ MD_ERROR_WIN_IPSEC_IKE_INVALID_HEADER = 13824,
++ MD_ERROR_WIN_IPSEC_IKE_NO_POLICY = 13825,
++ MD_ERROR_WIN_IPSEC_IKE_INVALID_SIGNATURE = 13826,
++ MD_ERROR_WIN_IPSEC_IKE_KERBEROS_ERROR = 13827,
++ MD_ERROR_WIN_IPSEC_IKE_NO_PUBLIC_KEY = 13828,
++ MD_ERROR_WIN_IPSEC_IKE_PROCESS_ERR = 13829,
++ MD_ERROR_WIN_IPSEC_IKE_PROCESS_ERR_SA = 13830,
++ MD_ERROR_WIN_IPSEC_IKE_PROCESS_ERR_PROP = 13831,
++ MD_ERROR_WIN_IPSEC_IKE_PROCESS_ERR_TRANS = 13832,
++ MD_ERROR_WIN_IPSEC_IKE_PROCESS_ERR_KE = 13833,
++ MD_ERROR_WIN_IPSEC_IKE_PROCESS_ERR_ID = 13834,
++ MD_ERROR_WIN_IPSEC_IKE_PROCESS_ERR_CERT = 13835,
++ MD_ERROR_WIN_IPSEC_IKE_PROCESS_ERR_CERT_REQ = 13836,
++ MD_ERROR_WIN_IPSEC_IKE_PROCESS_ERR_HASH = 13837,
++ MD_ERROR_WIN_IPSEC_IKE_PROCESS_ERR_SIG = 13838,
++ MD_ERROR_WIN_IPSEC_IKE_PROCESS_ERR_NONCE = 13839,
++ MD_ERROR_WIN_IPSEC_IKE_PROCESS_ERR_NOTIFY = 13840,
++ MD_ERROR_WIN_IPSEC_IKE_PROCESS_ERR_DELETE = 13841,
++ MD_ERROR_WIN_IPSEC_IKE_PROCESS_ERR_VENDOR = 13842,
++ MD_ERROR_WIN_IPSEC_IKE_INVALID_PAYLOAD = 13843,
++ MD_ERROR_WIN_IPSEC_IKE_LOAD_SOFT_SA = 13844,
++ MD_ERROR_WIN_IPSEC_IKE_SOFT_SA_TORN_DOWN = 13845,
++ MD_ERROR_WIN_IPSEC_IKE_INVALID_COOKIE = 13846,
++ MD_ERROR_WIN_IPSEC_IKE_NO_PEER_CERT = 13847,
++ MD_ERROR_WIN_IPSEC_IKE_PEER_CRL_FAILED = 13848,
++ MD_ERROR_WIN_IPSEC_IKE_POLICY_CHANGE = 13849,
++ MD_ERROR_WIN_IPSEC_IKE_NO_MM_POLICY = 13850,
++ MD_ERROR_WIN_IPSEC_IKE_NOTCBPRIV = 13851,
++ MD_ERROR_WIN_IPSEC_IKE_SECLOADFAIL = 13852,
++ MD_ERROR_WIN_IPSEC_IKE_FAILSSPINIT = 13853,
++ MD_ERROR_WIN_IPSEC_IKE_FAILQUERYSSP = 13854,
++ MD_ERROR_WIN_IPSEC_IKE_SRVACQFAIL = 13855,
++ MD_ERROR_WIN_IPSEC_IKE_SRVQUERYCRED = 13856,
++ MD_ERROR_WIN_IPSEC_IKE_GETSPIFAIL = 13857,
++ MD_ERROR_WIN_IPSEC_IKE_INVALID_FILTER = 13858,
++ MD_ERROR_WIN_IPSEC_IKE_OUT_OF_MEMORY = 13859,
++ MD_ERROR_WIN_IPSEC_IKE_ADD_UPDATE_KEY_FAILED = 13860,
++ MD_ERROR_WIN_IPSEC_IKE_INVALID_POLICY = 13861,
++ MD_ERROR_WIN_IPSEC_IKE_UNKNOWN_DOI = 13862,
++ MD_ERROR_WIN_IPSEC_IKE_INVALID_SITUATION = 13863,
++ MD_ERROR_WIN_IPSEC_IKE_DH_FAILURE = 13864,
++ MD_ERROR_WIN_IPSEC_IKE_INVALID_GROUP = 13865,
++ MD_ERROR_WIN_IPSEC_IKE_ENCRYPT = 13866,
++ MD_ERROR_WIN_IPSEC_IKE_DECRYPT = 13867,
++ MD_ERROR_WIN_IPSEC_IKE_POLICY_MATCH = 13868,
++ MD_ERROR_WIN_IPSEC_IKE_UNSUPPORTED_ID = 13869,
++ MD_ERROR_WIN_IPSEC_IKE_INVALID_HASH = 13870,
++ MD_ERROR_WIN_IPSEC_IKE_INVALID_HASH_ALG = 13871,
++ MD_ERROR_WIN_IPSEC_IKE_INVALID_HASH_SIZE = 13872,
++ MD_ERROR_WIN_IPSEC_IKE_INVALID_ENCRYPT_ALG = 13873,
++ MD_ERROR_WIN_IPSEC_IKE_INVALID_AUTH_ALG = 13874,
++ MD_ERROR_WIN_IPSEC_IKE_INVALID_SIG = 13875,
++ MD_ERROR_WIN_IPSEC_IKE_LOAD_FAILED = 13876,
++ MD_ERROR_WIN_IPSEC_IKE_RPC_DELETE = 13877,
++ MD_ERROR_WIN_IPSEC_IKE_BENIGN_REINIT = 13878,
++ MD_ERROR_WIN_IPSEC_IKE_INVALID_RESPONDER_LIFETIME_NOTIFY = 13879,
++ MD_ERROR_WIN_IPSEC_IKE_INVALID_MAJOR_VERSION = 13880,
++ MD_ERROR_WIN_IPSEC_IKE_INVALID_CERT_KEYLEN = 13881,
++ MD_ERROR_WIN_IPSEC_IKE_MM_LIMIT = 13882,
++ MD_ERROR_WIN_IPSEC_IKE_NEGOTIATION_DISABLED = 13883,
++ MD_ERROR_WIN_IPSEC_IKE_QM_LIMIT = 13884,
++ MD_ERROR_WIN_IPSEC_IKE_MM_EXPIRED = 13885,
++ MD_ERROR_WIN_IPSEC_IKE_PEER_MM_ASSUMED_INVALID = 13886,
++ MD_ERROR_WIN_IPSEC_IKE_CERT_CHAIN_POLICY_MISMATCH = 13887,
++ MD_ERROR_WIN_IPSEC_IKE_UNEXPECTED_MESSAGE_ID = 13888,
++ MD_ERROR_WIN_IPSEC_IKE_INVALID_AUTH_PAYLOAD = 13889,
++ MD_ERROR_WIN_IPSEC_IKE_DOS_COOKIE_SENT = 13890,
++ MD_ERROR_WIN_IPSEC_IKE_SHUTTING_DOWN = 13891,
++ MD_ERROR_WIN_IPSEC_IKE_CGA_AUTH_FAILED = 13892,
++ MD_ERROR_WIN_IPSEC_IKE_PROCESS_ERR_NATOA = 13893,
++ MD_ERROR_WIN_IPSEC_IKE_INVALID_MM_FOR_QM = 13894,
++ MD_ERROR_WIN_IPSEC_IKE_QM_EXPIRED = 13895,
++ MD_ERROR_WIN_IPSEC_IKE_TOO_MANY_FILTERS = 13896,
++ MD_ERROR_WIN_IPSEC_IKE_NEG_STATUS_END = 13897,
++ MD_ERROR_WIN_IPSEC_IKE_KILL_DUMMY_NAP_TUNNEL = 13898,
++ MD_ERROR_WIN_IPSEC_IKE_INNER_IP_ASSIGNMENT_FAILURE = 13899,
++ MD_ERROR_WIN_IPSEC_IKE_REQUIRE_CP_PAYLOAD_MISSING = 13900,
++ MD_ERROR_WIN_IPSEC_KEY_MODULE_IMPERSONATION_NEGOTIATION_PENDING = 13901,
++ MD_ERROR_WIN_IPSEC_IKE_COEXISTENCE_SUPPRESS = 13902,
++ MD_ERROR_WIN_IPSEC_IKE_RATELIMIT_DROP = 13903,
++ MD_ERROR_WIN_IPSEC_IKE_PEER_DOESNT_SUPPORT_MOBIKE = 13904,
++ MD_ERROR_WIN_IPSEC_IKE_AUTHORIZATION_FAILURE = 13905,
++ MD_ERROR_WIN_IPSEC_IKE_STRONG_CRED_AUTHORIZATION_FAILURE = 13906,
++ MD_ERROR_WIN_IPSEC_IKE_AUTHORIZATION_FAILURE_WITH_OPTIONAL_RETRY = 13907,
++ MD_ERROR_WIN_IPSEC_IKE_STRONG_CRED_AUTHORIZATION_AND_CERTMAP_FAILURE = 13908,
++ MD_ERROR_WIN_IPSEC_IKE_NEG_STATUS_EXTENDED_END = 13909,
++ MD_ERROR_WIN_IPSEC_BAD_SPI = 13910,
++ MD_ERROR_WIN_IPSEC_SA_LIFETIME_EXPIRED = 13911,
++ MD_ERROR_WIN_IPSEC_WRONG_SA = 13912,
++ MD_ERROR_WIN_IPSEC_REPLAY_CHECK_FAILED = 13913,
++ MD_ERROR_WIN_IPSEC_INVALID_PACKET = 13914,
++ MD_ERROR_WIN_IPSEC_INTEGRITY_CHECK_FAILED = 13915,
++ MD_ERROR_WIN_IPSEC_CLEAR_TEXT_DROP = 13916,
++ MD_ERROR_WIN_IPSEC_AUTH_FIREWALL_DROP = 13917,
++ MD_ERROR_WIN_IPSEC_THROTTLE_DROP = 13918,
++ MD_ERROR_WIN_IPSEC_DOSP_BLOCK = 13925,
++ MD_ERROR_WIN_IPSEC_DOSP_RECEIVED_MULTICAST = 13926,
++ MD_ERROR_WIN_IPSEC_DOSP_INVALID_PACKET = 13927,
++ MD_ERROR_WIN_IPSEC_DOSP_STATE_LOOKUP_FAILED = 13928,
++ MD_ERROR_WIN_IPSEC_DOSP_MAX_ENTRIES = 13929,
++ MD_ERROR_WIN_IPSEC_DOSP_KEYMOD_NOT_ALLOWED = 13930,
++ MD_ERROR_WIN_IPSEC_DOSP_NOT_INSTALLED = 13931,
++ MD_ERROR_WIN_IPSEC_DOSP_MAX_PER_IP_RATELIMIT_QUEUES = 13932,
++ MD_ERROR_WIN_SXS_SECTION_NOT_FOUND = 14000,
++ MD_ERROR_WIN_SXS_CANT_GEN_ACTCTX = 14001,
++ MD_ERROR_WIN_SXS_INVALID_ACTCTXDATA_FORMAT = 14002,
++ MD_ERROR_WIN_SXS_ASSEMBLY_NOT_FOUND = 14003,
++ MD_ERROR_WIN_SXS_MANIFEST_FORMAT_ERROR = 14004,
++ MD_ERROR_WIN_SXS_MANIFEST_PARSE_ERROR = 14005,
++ MD_ERROR_WIN_SXS_ACTIVATION_CONTEXT_DISABLED = 14006,
++ MD_ERROR_WIN_SXS_KEY_NOT_FOUND = 14007,
++ MD_ERROR_WIN_SXS_VERSION_CONFLICT = 14008,
++ MD_ERROR_WIN_SXS_WRONG_SECTION_TYPE = 14009,
++ MD_ERROR_WIN_SXS_THREAD_QUERIES_DISABLED = 14010,
++ MD_ERROR_WIN_SXS_PROCESS_DEFAULT_ALREADY_SET = 14011,
++ MD_ERROR_WIN_SXS_UNKNOWN_ENCODING_GROUP = 14012,
++ MD_ERROR_WIN_SXS_UNKNOWN_ENCODING = 14013,
++ MD_ERROR_WIN_SXS_INVALID_XML_NAMESPACE_URI = 14014,
++ MD_ERROR_WIN_SXS_ROOT_MANIFEST_DEPENDENCY_NOT_INSTALLED = 14015,
++ MD_ERROR_WIN_SXS_LEAF_MANIFEST_DEPENDENCY_NOT_INSTALLED = 14016,
++ MD_ERROR_WIN_SXS_INVALID_ASSEMBLY_IDENTITY_ATTRIBUTE = 14017,
++ MD_ERROR_WIN_SXS_MANIFEST_MISSING_REQUIRED_DEFAULT_NAMESPACE = 14018,
++ MD_ERROR_WIN_SXS_MANIFEST_INVALID_REQUIRED_DEFAULT_NAMESPACE = 14019,
++ MD_ERROR_WIN_SXS_PRIVATE_MANIFEST_CROSS_PATH_WITH_REPARSE_POINT = 14020,
++ MD_ERROR_WIN_SXS_DUPLICATE_DLL_NAME = 14021,
++ MD_ERROR_WIN_SXS_DUPLICATE_WINDOWCLASS_NAME = 14022,
++ MD_ERROR_WIN_SXS_DUPLICATE_CLSID = 14023,
++ MD_ERROR_WIN_SXS_DUPLICATE_IID = 14024,
++ MD_ERROR_WIN_SXS_DUPLICATE_TLBID = 14025,
++ MD_ERROR_WIN_SXS_DUPLICATE_PROGID = 14026,
++ MD_ERROR_WIN_SXS_DUPLICATE_ASSEMBLY_NAME = 14027,
++ MD_ERROR_WIN_SXS_FILE_HASH_MISMATCH = 14028,
++ MD_ERROR_WIN_SXS_POLICY_PARSE_ERROR = 14029,
++ MD_ERROR_WIN_SXS_XML_E_MISSINGQUOTE = 14030,
++ MD_ERROR_WIN_SXS_XML_E_COMMENTSYNTAX = 14031,
++ MD_ERROR_WIN_SXS_XML_E_BADSTARTNAMECHAR = 14032,
++ MD_ERROR_WIN_SXS_XML_E_BADNAMECHAR = 14033,
++ MD_ERROR_WIN_SXS_XML_E_BADCHARINSTRING = 14034,
++ MD_ERROR_WIN_SXS_XML_E_XMLDECLSYNTAX = 14035,
++ MD_ERROR_WIN_SXS_XML_E_BADCHARDATA = 14036,
++ MD_ERROR_WIN_SXS_XML_E_MISSINGWHITESPACE = 14037,
++ MD_ERROR_WIN_SXS_XML_E_EXPECTINGTAGEND = 14038,
++ MD_ERROR_WIN_SXS_XML_E_MISSINGSEMICOLON = 14039,
++ MD_ERROR_WIN_SXS_XML_E_UNBALANCEDPAREN = 14040,
++ MD_ERROR_WIN_SXS_XML_E_INTERNALERROR = 14041,
++ MD_ERROR_WIN_SXS_XML_E_UNEXPECTED_WHITESPACE = 14042,
++ MD_ERROR_WIN_SXS_XML_E_INCOMPLETE_ENCODING = 14043,
++ MD_ERROR_WIN_SXS_XML_E_MISSING_PAREN = 14044,
++ MD_ERROR_WIN_SXS_XML_E_EXPECTINGCLOSEQUOTE = 14045,
++ MD_ERROR_WIN_SXS_XML_E_MULTIPLE_COLONS = 14046,
++ MD_ERROR_WIN_SXS_XML_E_INVALID_DECIMAL = 14047,
++ MD_ERROR_WIN_SXS_XML_E_INVALID_HEXIDECIMAL = 14048,
++ MD_ERROR_WIN_SXS_XML_E_INVALID_UNICODE = 14049,
++ MD_ERROR_WIN_SXS_XML_E_WHITESPACEORQUESTIONMARK = 14050,
++ MD_ERROR_WIN_SXS_XML_E_UNEXPECTEDENDTAG = 14051,
++ MD_ERROR_WIN_SXS_XML_E_UNCLOSEDTAG = 14052,
++ MD_ERROR_WIN_SXS_XML_E_DUPLICATEATTRIBUTE = 14053,
++ MD_ERROR_WIN_SXS_XML_E_MULTIPLEROOTS = 14054,
++ MD_ERROR_WIN_SXS_XML_E_INVALIDATROOTLEVEL = 14055,
++ MD_ERROR_WIN_SXS_XML_E_BADXMLDECL = 14056,
++ MD_ERROR_WIN_SXS_XML_E_MISSINGROOT = 14057,
++ MD_ERROR_WIN_SXS_XML_E_UNEXPECTEDEOF = 14058,
++ MD_ERROR_WIN_SXS_XML_E_BADPEREFINSUBSET = 14059,
++ MD_ERROR_WIN_SXS_XML_E_UNCLOSEDSTARTTAG = 14060,
++ MD_ERROR_WIN_SXS_XML_E_UNCLOSEDENDTAG = 14061,
++ MD_ERROR_WIN_SXS_XML_E_UNCLOSEDSTRING = 14062,
++ MD_ERROR_WIN_SXS_XML_E_UNCLOSEDCOMMENT = 14063,
++ MD_ERROR_WIN_SXS_XML_E_UNCLOSEDDECL = 14064,
++ MD_ERROR_WIN_SXS_XML_E_UNCLOSEDCDATA = 14065,
++ MD_ERROR_WIN_SXS_XML_E_RESERVEDNAMESPACE = 14066,
++ MD_ERROR_WIN_SXS_XML_E_INVALIDENCODING = 14067,
++ MD_ERROR_WIN_SXS_XML_E_INVALIDSWITCH = 14068,
++ MD_ERROR_WIN_SXS_XML_E_BADXMLCASE = 14069,
++ MD_ERROR_WIN_SXS_XML_E_INVALID_STANDALONE = 14070,
++ MD_ERROR_WIN_SXS_XML_E_UNEXPECTED_STANDALONE = 14071,
++ MD_ERROR_WIN_SXS_XML_E_INVALID_VERSION = 14072,
++ MD_ERROR_WIN_SXS_XML_E_MISSINGEQUALS = 14073,
++ MD_ERROR_WIN_SXS_PROTECTION_RECOVERY_FAILED = 14074,
++ MD_ERROR_WIN_SXS_PROTECTION_PUBLIC_KEY_TOO_SHORT = 14075,
++ MD_ERROR_WIN_SXS_PROTECTION_CATALOG_NOT_VALID = 14076,
++ MD_ERROR_WIN_SXS_UNTRANSLATABLE_HRESULT = 14077,
++ MD_ERROR_WIN_SXS_PROTECTION_CATALOG_FILE_MISSING = 14078,
++ MD_ERROR_WIN_SXS_MISSING_ASSEMBLY_IDENTITY_ATTRIBUTE = 14079,
++ MD_ERROR_WIN_SXS_INVALID_ASSEMBLY_IDENTITY_ATTRIBUTE_NAME = 14080,
++ MD_ERROR_WIN_SXS_ASSEMBLY_MISSING = 14081,
++ MD_ERROR_WIN_SXS_CORRUPT_ACTIVATION_STACK = 14082,
++ MD_ERROR_WIN_SXS_CORRUPTION = 14083,
++ MD_ERROR_WIN_SXS_EARLY_DEACTIVATION = 14084,
++ MD_ERROR_WIN_SXS_INVALID_DEACTIVATION = 14085,
++ MD_ERROR_WIN_SXS_MULTIPLE_DEACTIVATION = 14086,
++ MD_ERROR_WIN_SXS_PROCESS_TERMINATION_REQUESTED = 14087,
++ MD_ERROR_WIN_SXS_RELEASE_ACTIVATION_CONTEXT = 14088,
++ MD_ERROR_WIN_SXS_SYSTEM_DEFAULT_ACTIVATION_CONTEXT_EMPTY = 14089,
++ MD_ERROR_WIN_SXS_INVALID_IDENTITY_ATTRIBUTE_VALUE = 14090,
++ MD_ERROR_WIN_SXS_INVALID_IDENTITY_ATTRIBUTE_NAME = 14091,
++ MD_ERROR_WIN_SXS_IDENTITY_DUPLICATE_ATTRIBUTE = 14092,
++ MD_ERROR_WIN_SXS_IDENTITY_PARSE_ERROR = 14093,
++ MD_ERROR_WIN_MALFORMED_SUBSTITUTION_STRING = 14094,
++ MD_ERROR_WIN_SXS_INCORRECT_PUBLIC_KEY_TOKEN = 14095,
++ MD_ERROR_WIN_UNMAPPED_SUBSTITUTION_STRING = 14096,
++ MD_ERROR_WIN_SXS_ASSEMBLY_NOT_LOCKED = 14097,
++ MD_ERROR_WIN_SXS_COMPONENT_STORE_CORRUPT = 14098,
++ MD_ERROR_WIN_ADVANCED_INSTALLER_FAILED = 14099,
++ MD_ERROR_WIN_XML_ENCODING_MISMATCH = 14100,
++ MD_ERROR_WIN_SXS_MANIFEST_IDENTITY_SAME_BUT_CONTENTS_DIFFERENT = 14101,
++ MD_ERROR_WIN_SXS_IDENTITIES_DIFFERENT = 14102,
++ MD_ERROR_WIN_SXS_ASSEMBLY_IS_NOT_A_DEPLOYMENT = 14103,
++ MD_ERROR_WIN_SXS_FILE_NOT_PART_OF_ASSEMBLY = 14104,
++ MD_ERROR_WIN_SXS_MANIFEST_TOO_BIG = 14105,
++ MD_ERROR_WIN_SXS_SETTING_NOT_REGISTERED = 14106,
++ MD_ERROR_WIN_SXS_TRANSACTION_CLOSURE_INCOMPLETE = 14107,
++ MD_ERROR_WIN_SMI_PRIMITIVE_INSTALLER_FAILED = 14108,
++ MD_ERROR_WIN_GENERIC_COMMAND_FAILED = 14109,
++ MD_ERROR_WIN_SXS_FILE_HASH_MISSING = 14110,
++ MD_ERROR_WIN_SXS_DUPLICATE_ACTIVATABLE_CLASS = 14111,
++ MD_ERROR_WIN_EVT_INVALID_CHANNEL_PATH = 15000,
++ MD_ERROR_WIN_EVT_INVALID_QUERY = 15001,
++ MD_ERROR_WIN_EVT_PUBLISHER_METADATA_NOT_FOUND = 15002,
++ MD_ERROR_WIN_EVT_EVENT_TEMPLATE_NOT_FOUND = 15003,
++ MD_ERROR_WIN_EVT_INVALID_PUBLISHER_NAME = 15004,
++ MD_ERROR_WIN_EVT_INVALID_EVENT_DATA = 15005,
++ MD_ERROR_WIN_EVT_CHANNEL_NOT_FOUND = 15007,
++ MD_ERROR_WIN_EVT_MALFORMED_XML_TEXT = 15008,
++ MD_ERROR_WIN_EVT_SUBSCRIPTION_TO_DIRECT_CHANNEL = 15009,
++ MD_ERROR_WIN_EVT_CONFIGURATION_ERROR = 15010,
++ MD_ERROR_WIN_EVT_QUERY_RESULT_STALE = 15011,
++ MD_ERROR_WIN_EVT_QUERY_RESULT_INVALID_POSITION = 15012,
++ MD_ERROR_WIN_EVT_NON_VALIDATING_MSXML = 15013,
++ MD_ERROR_WIN_EVT_FILTER_ALREADYSCOPED = 15014,
++ MD_ERROR_WIN_EVT_FILTER_NOTELTSET = 15015,
++ MD_ERROR_WIN_EVT_FILTER_INVARG = 15016,
++ MD_ERROR_WIN_EVT_FILTER_INVTEST = 15017,
++ MD_ERROR_WIN_EVT_FILTER_INVTYPE = 15018,
++ MD_ERROR_WIN_EVT_FILTER_PARSEERR = 15019,
++ MD_ERROR_WIN_EVT_FILTER_UNSUPPORTEDOP = 15020,
++ MD_ERROR_WIN_EVT_FILTER_UNEXPECTEDTOKEN = 15021,
++ MD_ERROR_WIN_EVT_INVALID_OPERATION_OVER_ENABLED_DIRECT_CHANNEL = 15022,
++ MD_ERROR_WIN_EVT_INVALID_CHANNEL_PROPERTY_VALUE = 15023,
++ MD_ERROR_WIN_EVT_INVALID_PUBLISHER_PROPERTY_VALUE = 15024,
++ MD_ERROR_WIN_EVT_CHANNEL_CANNOT_ACTIVATE = 15025,
++ MD_ERROR_WIN_EVT_FILTER_TOO_COMPLEX = 15026,
++ MD_ERROR_WIN_EVT_MESSAGE_NOT_FOUND = 15027,
++ MD_ERROR_WIN_EVT_MESSAGE_ID_NOT_FOUND = 15028,
++ MD_ERROR_WIN_EVT_UNRESOLVED_VALUE_INSERT = 15029,
++ MD_ERROR_WIN_EVT_UNRESOLVED_PARAMETER_INSERT = 15030,
++ MD_ERROR_WIN_EVT_MAX_INSERTS_REACHED = 15031,
++ MD_ERROR_WIN_EVT_EVENT_DEFINITION_NOT_FOUND = 15032,
++ MD_ERROR_WIN_EVT_MESSAGE_LOCALE_NOT_FOUND = 15033,
++ MD_ERROR_WIN_EVT_VERSION_TOO_OLD = 15034,
++ MD_ERROR_WIN_EVT_VERSION_TOO_NEW = 15035,
++ MD_ERROR_WIN_EVT_CANNOT_OPEN_CHANNEL_OF_QUERY = 15036,
++ MD_ERROR_WIN_EVT_PUBLISHER_DISABLED = 15037,
++ MD_ERROR_WIN_EVT_FILTER_OUT_OF_RANGE = 15038,
++ MD_ERROR_WIN_EC_SUBSCRIPTION_CANNOT_ACTIVATE = 15080,
++ MD_ERROR_WIN_EC_LOG_DISABLED = 15081,
++ MD_ERROR_WIN_EC_CIRCULAR_FORWARDING = 15082,
++ MD_ERROR_WIN_EC_CREDSTORE_FULL = 15083,
++ MD_ERROR_WIN_EC_CRED_NOT_FOUND = 15084,
++ MD_ERROR_WIN_EC_NO_ACTIVE_CHANNEL = 15085,
++ MD_ERROR_WIN_MUI_FILE_NOT_FOUND = 15100,
++ MD_ERROR_WIN_MUI_INVALID_FILE = 15101,
++ MD_ERROR_WIN_MUI_INVALID_RC_CONFIG = 15102,
++ MD_ERROR_WIN_MUI_INVALID_LOCALE_NAME = 15103,
++ MD_ERROR_WIN_MUI_INVALID_ULTIMATEFALLBACK_NAME = 15104,
++ MD_ERROR_WIN_MUI_FILE_NOT_LOADED = 15105,
++ MD_ERROR_WIN_RESOURCE_ENUM_USER_STOP = 15106,
++ MD_ERROR_WIN_MUI_INTLSETTINGS_UILANG_NOT_INSTALLED = 15107,
++ MD_ERROR_WIN_MUI_INTLSETTINGS_INVALID_LOCALE_NAME = 15108,
++ MD_ERROR_WIN_MRM_RUNTIME_NO_DEFAULT_OR_NEUTRAL_RESOURCE = 15110,
++ MD_ERROR_WIN_MRM_INVALID_PRICONFIG = 15111,
++ MD_ERROR_WIN_MRM_INVALID_FILE_TYPE = 15112,
++ MD_ERROR_WIN_MRM_UNKNOWN_QUALIFIER = 15113,
++ MD_ERROR_WIN_MRM_INVALID_QUALIFIER_VALUE = 15114,
++ MD_ERROR_WIN_MRM_NO_CANDIDATE = 15115,
++ MD_ERROR_WIN_MRM_NO_MATCH_OR_DEFAULT_CANDIDATE = 15116,
++ MD_ERROR_WIN_MRM_RESOURCE_TYPE_MISMATCH = 15117,
++ MD_ERROR_WIN_MRM_DUPLICATE_MAP_NAME = 15118,
++ MD_ERROR_WIN_MRM_DUPLICATE_ENTRY = 15119,
++ MD_ERROR_WIN_MRM_INVALID_RESOURCE_IDENTIFIER = 15120,
++ MD_ERROR_WIN_MRM_FILEPATH_TOO_LONG = 15121,
++ MD_ERROR_WIN_MRM_UNSUPPORTED_DIRECTORY_TYPE = 15122,
++ MD_ERROR_WIN_MRM_INVALID_PRI_FILE = 15126,
++ MD_ERROR_WIN_MRM_NAMED_RESOURCE_NOT_FOUND = 15127,
++ MD_ERROR_WIN_MRM_MAP_NOT_FOUND = 15135,
++ MD_ERROR_WIN_MRM_UNSUPPORTED_PROFILE_TYPE = 15136,
++ MD_ERROR_WIN_MRM_INVALID_QUALIFIER_OPERATOR = 15137,
++ MD_ERROR_WIN_MRM_INDETERMINATE_QUALIFIER_VALUE = 15138,
++ MD_ERROR_WIN_MRM_AUTOMERGE_ENABLED = 15139,
++ MD_ERROR_WIN_MRM_TOO_MANY_RESOURCES = 15140,
++ MD_ERROR_WIN_MRM_UNSUPPORTED_FILE_TYPE_FOR_MERGE = 15141,
++ MD_ERROR_WIN_MRM_UNSUPPORTED_FILE_TYPE_FOR_LOAD_UNLOAD_PRI_FILE = 15142,
++ MD_ERROR_WIN_MRM_NO_CURRENT_VIEW_ON_THREAD = 15143,
++ MD_ERROR_WIN_DIFFERENT_PROFILE_RESOURCE_MANAGER_EXIST = 15144,
++ MD_ERROR_WIN_OPERATION_NOT_ALLOWED_FROM_SYSTEM_COMPONENT = 15145,
++ MD_ERROR_WIN_MRM_DIRECT_REF_TO_NON_DEFAULT_RESOURCE = 15146,
++ MD_ERROR_WIN_MRM_GENERATION_COUNT_MISMATCH = 15147,
++ MD_ERROR_WIN_PRI_MERGE_VERSION_MISMATCH = 15148,
++ MD_ERROR_WIN_PRI_MERGE_MISSING_SCHEMA = 15149,
++ MD_ERROR_WIN_PRI_MERGE_LOAD_FILE_FAILED = 15150,
++ MD_ERROR_WIN_PRI_MERGE_ADD_FILE_FAILED = 15151,
++ MD_ERROR_WIN_PRI_MERGE_WRITE_FILE_FAILED = 15152,
++ MD_ERROR_WIN_PRI_MERGE_MULTIPLE_PACKAGE_FAMILIES_NOT_ALLOWED = 15153,
++ MD_ERROR_WIN_PRI_MERGE_MULTIPLE_MAIN_PACKAGES_NOT_ALLOWED = 15154,
++ MD_ERROR_WIN_PRI_MERGE_BUNDLE_PACKAGES_NOT_ALLOWED = 15155,
++ MD_ERROR_WIN_PRI_MERGE_MAIN_PACKAGE_REQUIRED = 15156,
++ MD_ERROR_WIN_PRI_MERGE_RESOURCE_PACKAGE_REQUIRED = 15157,
++ MD_ERROR_WIN_PRI_MERGE_INVALID_FILE_NAME = 15158,
++ MD_ERROR_WIN_MRM_PACKAGE_NOT_FOUND = 15159,
++ MD_ERROR_WIN_MRM_MISSING_DEFAULT_LANGUAGE = 15160,
++ MD_ERROR_WIN_MCA_INVALID_CAPABILITIES_STRING = 15200,
++ MD_ERROR_WIN_MCA_INVALID_VCP_VERSION = 15201,
++ MD_ERROR_WIN_MCA_MONITOR_VIOLATES_MCCS_SPECIFICATION = 15202,
++ MD_ERROR_WIN_MCA_MCCS_VERSION_MISMATCH = 15203,
++ MD_ERROR_WIN_MCA_UNSUPPORTED_MCCS_VERSION = 15204,
++ MD_ERROR_WIN_MCA_INTERNAL_ERROR = 15205,
++ MD_ERROR_WIN_MCA_INVALID_TECHNOLOGY_TYPE_RETURNED = 15206,
++ MD_ERROR_WIN_MCA_UNSUPPORTED_COLOR_TEMPERATURE = 15207,
++ MD_ERROR_WIN_AMBIGUOUS_SYSTEM_DEVICE = 15250,
++ MD_ERROR_WIN_SYSTEM_DEVICE_NOT_FOUND = 15299,
++ MD_ERROR_WIN_HASH_NOT_SUPPORTED = 15300,
++ MD_ERROR_WIN_HASH_NOT_PRESENT = 15301,
++ MD_ERROR_WIN_SECONDARY_IC_PROVIDER_NOT_REGISTERED = 15321,
++ MD_ERROR_WIN_GPIO_CLIENT_INFORMATION_INVALID = 15322,
++ MD_ERROR_WIN_GPIO_VERSION_NOT_SUPPORTED = 15323,
++ MD_ERROR_WIN_GPIO_INVALID_REGISTRATION_PACKET = 15324,
++ MD_ERROR_WIN_GPIO_OPERATION_DENIED = 15325,
++ MD_ERROR_WIN_GPIO_INCOMPATIBLE_CONNECT_MODE = 15326,
++ MD_ERROR_WIN_GPIO_INTERRUPT_ALREADY_UNMASKED = 15327,
++ MD_ERROR_WIN_CANNOT_SWITCH_RUNLEVEL = 15400,
++ MD_ERROR_WIN_INVALID_RUNLEVEL_SETTING = 15401,
++ MD_ERROR_WIN_RUNLEVEL_SWITCH_TIMEOUT = 15402,
++ MD_ERROR_WIN_RUNLEVEL_SWITCH_AGENT_TIMEOUT = 15403,
++ MD_ERROR_WIN_RUNLEVEL_SWITCH_IN_PROGRESS = 15404,
++ MD_ERROR_WIN_SERVICES_FAILED_AUTOSTART = 15405,
++ MD_ERROR_WIN_COM_TASK_STOP_PENDING = 15501,
++ MD_ERROR_WIN_INSTALL_OPEN_PACKAGE_FAILED = 15600,
++ MD_ERROR_WIN_INSTALL_PACKAGE_NOT_FOUND = 15601,
++ MD_ERROR_WIN_INSTALL_INVALID_PACKAGE = 15602,
++ MD_ERROR_WIN_INSTALL_RESOLVE_DEPENDENCY_FAILED = 15603,
++ MD_ERROR_WIN_INSTALL_OUT_OF_DISK_SPACE = 15604,
++ MD_ERROR_WIN_INSTALL_NETWORK_FAILURE = 15605,
++ MD_ERROR_WIN_INSTALL_REGISTRATION_FAILURE = 15606,
++ MD_ERROR_WIN_INSTALL_DEREGISTRATION_FAILURE = 15607,
++ MD_ERROR_WIN_INSTALL_CANCEL = 15608,
++ MD_ERROR_WIN_INSTALL_FAILED = 15609,
++ MD_ERROR_WIN_REMOVE_FAILED = 15610,
++ MD_ERROR_WIN_PACKAGE_ALREADY_EXISTS = 15611,
++ MD_ERROR_WIN_NEEDS_REMEDIATION = 15612,
++ MD_ERROR_WIN_INSTALL_PREREQUISITE_FAILED = 15613,
++ MD_ERROR_WIN_PACKAGE_REPOSITORY_CORRUPTED = 15614,
++ MD_ERROR_WIN_INSTALL_POLICY_FAILURE = 15615,
++ MD_ERROR_WIN_PACKAGE_UPDATING = 15616,
++ MD_ERROR_WIN_DEPLOYMENT_BLOCKED_BY_POLICY = 15617,
++ MD_ERROR_WIN_PACKAGES_IN_USE = 15618,
++ MD_ERROR_WIN_RECOVERY_FILE_CORRUPT = 15619,
++ MD_ERROR_WIN_INVALID_STAGED_SIGNATURE = 15620,
++ MD_ERROR_WIN_DELETING_EXISTING_APPLICATIONDATA_STORE_FAILED = 15621,
++ MD_ERROR_WIN_INSTALL_PACKAGE_DOWNGRADE = 15622,
++ MD_ERROR_WIN_SYSTEM_NEEDS_REMEDIATION = 15623,
++ MD_ERROR_WIN_APPX_INTEGRITY_FAILURE_CLR_NGEN = 15624,
++ MD_ERROR_WIN_RESILIENCY_FILE_CORRUPT = 15625,
++ MD_ERROR_WIN_INSTALL_FIREWALL_SERVICE_NOT_RUNNING = 15626,
++ MD_ERROR_WIN_PACKAGE_MOVE_FAILED = 15627,
++ MD_ERROR_WIN_INSTALL_VOLUME_NOT_EMPTY = 15628,
++ MD_ERROR_WIN_INSTALL_VOLUME_OFFLINE = 15629,
++ MD_ERROR_WIN_INSTALL_VOLUME_CORRUPT = 15630,
++ MD_ERROR_WIN_NEEDS_REGISTRATION = 15631,
++ MD_ERROR_WIN_INSTALL_WRONG_PROCESSOR_ARCHITECTURE = 15632,
++ MD_ERROR_WIN_DEV_SIDELOAD_LIMIT_EXCEEDED = 15633,
++ MD_ERROR_WIN_INSTALL_OPTIONAL_PACKAGE_REQUIRES_MAIN_PACKAGE = 15634,
++ MD_ERROR_WIN_PACKAGE_NOT_SUPPORTED_ON_FILESYSTEM = 15635,
++ MD_ERROR_WIN_PACKAGE_MOVE_BLOCKED_BY_STREAMING = 15636,
++ MD_ERROR_WIN_INSTALL_OPTIONAL_PACKAGE_APPLICATIONID_NOT_UNIQUE = 15637,
++ MD_ERROR_WIN_PACKAGE_STAGING_ONHOLD = 15638,
++ MD_ERROR_WIN_INSTALL_INVALID_RELATED_SET_UPDATE = 15639,
++ MD_ERROR_WIN_INSTALL_OPTIONAL_PACKAGE_REQUIRES_MAIN_PACKAGE_FULLTRUST_CAPABILITY = 15640,
++ MD_ERROR_WIN_DEPLOYMENT_BLOCKED_BY_USER_LOG_OFF = 15641,
++ MD_ERROR_WIN_PROVISION_OPTIONAL_PACKAGE_REQUIRES_MAIN_PACKAGE_PROVISIONED = 15642,
++ MD_ERROR_WIN_PACKAGES_REPUTATION_CHECK_FAILED = 15643,
++ MD_ERROR_WIN_PACKAGES_REPUTATION_CHECK_TIMEDOUT = 15644,
++ MD_ERROR_WIN_DEPLOYMENT_OPTION_NOT_SUPPORTED = 15645,
++ MD_ERROR_WIN_APPINSTALLER_ACTIVATION_BLOCKED = 15646,
++ MD_ERROR_WIN_REGISTRATION_FROM_REMOTE_DRIVE_NOT_SUPPORTED = 15647,
++ MD_ERROR_WIN_APPX_RAW_DATA_WRITE_FAILED = 15648,
++ MD_ERROR_WIN_DEPLOYMENT_BLOCKED_BY_VOLUME_POLICY_PACKAGE = 15649,
++ MD_ERROR_WIN_DEPLOYMENT_BLOCKED_BY_VOLUME_POLICY_MACHINE = 15650,
++ MD_ERROR_WIN_DEPLOYMENT_BLOCKED_BY_PROFILE_POLICY = 15651,
++ MD_ERROR_WIN_DEPLOYMENT_FAILED_CONFLICTING_MUTABLE_PACKAGE_DIRECTORY = 15652,
++ MD_ERROR_WIN_SINGLETON_RESOURCE_INSTALLED_IN_ACTIVE_USER = 15653,
++ MD_ERROR_WIN_DIFFERENT_VERSION_OF_PACKAGED_SERVICE_INSTALLED = 15654,
++ MD_ERROR_WIN_SERVICE_EXISTS_AS_NON_PACKAGED_SERVICE = 15655,
++ MD_ERROR_WIN_PACKAGED_SERVICE_REQUIRES_ADMIN_PRIVILEGES = 15656,
++ MD_ERROR_WIN_REDIRECTION_TO_DEFAULT_ACCOUNT_NOT_ALLOWED = 15657,
++ MD_ERROR_WIN_PACKAGE_LACKS_CAPABILITY_TO_DEPLOY_ON_HOST = 15658,
++ MD_ERROR_WIN_UNSIGNED_PACKAGE_INVALID_CONTENT = 15659,
++ MD_ERROR_WIN_UNSIGNED_PACKAGE_INVALID_PUBLISHER_NAMESPACE = 15660,
++ MD_ERROR_WIN_SIGNED_PACKAGE_INVALID_PUBLISHER_NAMESPACE = 15661,
++ MD_ERROR_WIN_PACKAGE_EXTERNAL_LOCATION_NOT_ALLOWED = 15662,
++ MD_ERROR_WIN_INSTALL_FULLTRUST_HOSTRUNTIME_REQUIRES_MAIN_PACKAGE_FULLTRUST_CAPABILITY = 15663,
++ MD_ERROR_WIN_STATE_LOAD_STORE_FAILED = 15800,
++ MD_ERROR_WIN_STATE_GET_VERSION_FAILED = 15801,
++ MD_ERROR_WIN_STATE_SET_VERSION_FAILED = 15802,
++ MD_ERROR_WIN_STATE_STRUCTURED_RESET_FAILED = 15803,
++ MD_ERROR_WIN_STATE_OPEN_CONTAINER_FAILED = 15804,
++ MD_ERROR_WIN_STATE_CREATE_CONTAINER_FAILED = 15805,
++ MD_ERROR_WIN_STATE_DELETE_CONTAINER_FAILED = 15806,
++ MD_ERROR_WIN_STATE_READ_SETTING_FAILED = 15807,
++ MD_ERROR_WIN_STATE_WRITE_SETTING_FAILED = 15808,
++ MD_ERROR_WIN_STATE_DELETE_SETTING_FAILED = 15809,
++ MD_ERROR_WIN_STATE_QUERY_SETTING_FAILED = 15810,
++ MD_ERROR_WIN_STATE_READ_COMPOSITE_SETTING_FAILED = 15811,
++ MD_ERROR_WIN_STATE_WRITE_COMPOSITE_SETTING_FAILED = 15812,
++ MD_ERROR_WIN_STATE_ENUMERATE_CONTAINER_FAILED = 15813,
++ MD_ERROR_WIN_STATE_ENUMERATE_SETTINGS_FAILED = 15814,
++ MD_ERROR_WIN_STATE_COMPOSITE_SETTING_VALUE_SIZE_LIMIT_EXCEEDED = 15815,
++ MD_ERROR_WIN_STATE_SETTING_VALUE_SIZE_LIMIT_EXCEEDED = 15816,
++ MD_ERROR_WIN_STATE_SETTING_NAME_SIZE_LIMIT_EXCEEDED = 15817,
++ MD_ERROR_WIN_STATE_CONTAINER_NAME_SIZE_LIMIT_EXCEEDED = 15818,
++ MD_ERROR_WIN_API_UNAVAILABLE = 15841,
++} MDErrorWin;
++
+ #endif /* GOOGLE_BREAKPAD_COMMON_MINIDUMP_EXCEPTION_WIN32_H__ */
+diff --git a/src/processor/minidump_processor.cc b/src/processor/minidump_processor.cc
+--- a/src/processor/minidump_processor.cc
++++ b/src/processor/minidump_processor.cc
+@@ -1241,17 +1241,23 @@ string MinidumpProcessor::GetCrashReason
+ *address =
+ raw_exception->exception_record.exception_information[1];
+ }
+ if (raw_exception->exception_record.number_parameters >= 3) {
+ uint32_t ntstatus =
+ static_cast<uint32_t>
+ (raw_exception->exception_record.exception_information[2]);
+ reason.append(" / ");
+- reason.append(NTStatusToString(ntstatus));
++ const char* ntstatus_str = NTStatusToString(ntstatus);
++ if (ntstatus_str) {
++ reason.append(ntstatus_str);
++ } else {
++ snprintf(reason_string, sizeof(reason_string), "%#010x", ntstatus);
++ reason.append(reason_string);
++ }
+ }
+ break;
+ case MD_EXCEPTION_CODE_WIN_INVALID_HANDLE:
+ reason = "EXCEPTION_INVALID_HANDLE";
+ break;
+ case MD_EXCEPTION_CODE_WIN_ILLEGAL_INSTRUCTION:
+ reason = "EXCEPTION_ILLEGAL_INSTRUCTION";
+ break;
+@@ -1304,34 +1310,47 @@ string MinidumpProcessor::GetCrashReason
+ reason = "EXCEPTION_POSSIBLE_DEADLOCK";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_STACK_BUFFER_OVERRUN:
+ reason = "STATUS_STACK_BUFFER_OVERRUN";
+ if (raw_exception->exception_record.number_parameters > 0) {
+ uint32_t fast_fail_code =
+ static_cast<uint32_t>
+ (raw_exception->exception_record.exception_information[0]);
++ char fast_fail_buff[13] = {};
++ const char* fast_fail_string = FastFailToString(fast_fail_code);
++ if (!fast_fail_string) {
++ snprintf(fast_fail_buff, sizeof(fast_fail_buff), "%#010x",
++ fast_fail_code);
++ fast_fail_string = fast_fail_buff;
++ }
++
+ reason.append(" / ");
+- reason.append(FastFailToString(fast_fail_code));
++ reason.append(fast_fail_string);
+ }
+
+ break;
+ case MD_EXCEPTION_OUT_OF_MEMORY:
+ reason = "Out of Memory";
+ break;
+ case MD_EXCEPTION_CODE_WIN_UNHANDLED_CPP_EXCEPTION:
+ reason = "Unhandled C++ Exception";
+ break;
+ case MD_EXCEPTION_CODE_WIN_SIMULATED:
+ reason = "Simulated Exception";
+ break;
+ default:
+- reason = NTStatusToString(exception_code);
+- if (reason.substr(0, 2) == "0x") {
+- BPLOG(INFO) << "Unknown exception reason " << reason;
++ fprintf(stderr, "exception_code = %u\n", exception_code);
++ const char* exception_str = NTStatusToString(exception_code);
++ fprintf(stderr, "exception_str = %s\n", exception_str);
++ if (exception_str == nullptr) {
++ exception_str = WinErrorToString(exception_code);
++ }
++ if (exception_str != nullptr) {
++ reason = exception_str;
+ }
+ break;
+ }
+ break;
+ }
+
+ case MD_OS_ANDROID:
+ case MD_OS_LINUX: {
+diff --git a/src/processor/symbolic_constants_win.cc b/src/processor/symbolic_constants_win.cc
+--- a/src/processor/symbolic_constants_win.cc
++++ b/src/processor/symbolic_constants_win.cc
+@@ -28,8384 +28,10931 @@
+ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ // ntstatus_reason_win.h: Windows NTSTATUS code to string.
+ //
+ // Provides a means to convert NTSTATUS codes to strings.
+ //
+ // Author: Ben Wagner
+
++#include <algorithm>
+ #include <string>
+
+ #include "common/stdio_wrapper.h"
+ #include "google_breakpad/common/breakpad_types.h"
+ #include "google_breakpad/common/minidump_exception_win32.h"
+ #include "processor/symbolic_constants_win.h"
+
+ namespace google_breakpad {
+
+-string NTStatusToString(uint32_t ntstatus) {
+- string reason;
+- // The content of this switch was created from ntstatus.h in the 10 SDK
+- // (version 10.0.19041.0) with
+- //
+- // egrep '#define [A-Z_0-9]+\s+\(\(NTSTATUS\)0x[048C][0-9A-F]+L\)' ntstatus.h
+- // | tr -d '\r'
+- // | sed -r 's@#define ([A-Z_0-9]+)\s+\(\(NTSTATUS\)(0x[048C][0-9A-F]+)L\).*@\2 \1@'
+- // | sort
+- // | sed -r 's@(0x[048C][0-9A-F]+) ([A-Z_0-9]+)@ case MD_NTSTATUS_WIN_\2:\n reason = "\2";\n break;@'
+- //
+- // With easy copy to clipboard with
+- // | xclip -selection c # on linux
+- // | clip # on windows
+- // | pbcopy # on mac
+- //
+- // and then the default case added.
+- switch (ntstatus) {
+- case MD_NTSTATUS_WIN_STATUS_SUCCESS:
+- reason = "STATUS_SUCCESS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_WAIT_1:
+- reason = "STATUS_WAIT_1";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_WAIT_2:
+- reason = "STATUS_WAIT_2";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_WAIT_3:
+- reason = "STATUS_WAIT_3";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_WAIT_63:
+- reason = "STATUS_WAIT_63";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ABANDONED:
+- reason = "STATUS_ABANDONED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ABANDONED_WAIT_63:
+- reason = "STATUS_ABANDONED_WAIT_63";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_USER_APC:
+- reason = "STATUS_USER_APC";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ALREADY_COMPLETE:
+- reason = "STATUS_ALREADY_COMPLETE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_KERNEL_APC:
+- reason = "STATUS_KERNEL_APC";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ALERTED:
+- reason = "STATUS_ALERTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TIMEOUT:
+- reason = "STATUS_TIMEOUT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PENDING:
+- reason = "STATUS_PENDING";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_REPARSE:
+- reason = "STATUS_REPARSE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_MORE_ENTRIES:
+- reason = "STATUS_MORE_ENTRIES";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NOT_ALL_ASSIGNED:
+- reason = "STATUS_NOT_ALL_ASSIGNED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SOME_NOT_MAPPED:
+- reason = "STATUS_SOME_NOT_MAPPED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_OPLOCK_BREAK_IN_PROGRESS:
+- reason = "STATUS_OPLOCK_BREAK_IN_PROGRESS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLUME_MOUNTED:
+- reason = "STATUS_VOLUME_MOUNTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_RXACT_COMMITTED:
+- reason = "STATUS_RXACT_COMMITTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NOTIFY_CLEANUP:
+- reason = "STATUS_NOTIFY_CLEANUP";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NOTIFY_ENUM_DIR:
+- reason = "STATUS_NOTIFY_ENUM_DIR";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NO_QUOTAS_FOR_ACCOUNT:
+- reason = "STATUS_NO_QUOTAS_FOR_ACCOUNT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PRIMARY_TRANSPORT_CONNECT_FAILED:
+- reason = "STATUS_PRIMARY_TRANSPORT_CONNECT_FAILED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PAGE_FAULT_TRANSITION:
+- reason = "STATUS_PAGE_FAULT_TRANSITION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PAGE_FAULT_DEMAND_ZERO:
+- reason = "STATUS_PAGE_FAULT_DEMAND_ZERO";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PAGE_FAULT_COPY_ON_WRITE:
+- reason = "STATUS_PAGE_FAULT_COPY_ON_WRITE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PAGE_FAULT_GUARD_PAGE:
+- reason = "STATUS_PAGE_FAULT_GUARD_PAGE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PAGE_FAULT_PAGING_FILE:
+- reason = "STATUS_PAGE_FAULT_PAGING_FILE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CACHE_PAGE_LOCKED:
+- reason = "STATUS_CACHE_PAGE_LOCKED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CRASH_DUMP:
+- reason = "STATUS_CRASH_DUMP";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_BUFFER_ALL_ZEROS:
+- reason = "STATUS_BUFFER_ALL_ZEROS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_REPARSE_OBJECT:
+- reason = "STATUS_REPARSE_OBJECT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_RESOURCE_REQUIREMENTS_CHANGED:
+- reason = "STATUS_RESOURCE_REQUIREMENTS_CHANGED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TRANSLATION_COMPLETE:
+- reason = "STATUS_TRANSLATION_COMPLETE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DS_MEMBERSHIP_EVALUATED_LOCALLY:
+- reason = "STATUS_DS_MEMBERSHIP_EVALUATED_LOCALLY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NOTHING_TO_TERMINATE:
+- reason = "STATUS_NOTHING_TO_TERMINATE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PROCESS_NOT_IN_JOB:
+- reason = "STATUS_PROCESS_NOT_IN_JOB";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PROCESS_IN_JOB:
+- reason = "STATUS_PROCESS_IN_JOB";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLSNAP_HIBERNATE_READY:
+- reason = "STATUS_VOLSNAP_HIBERNATE_READY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FSFILTER_OP_COMPLETED_SUCCESSFULLY:
+- reason = "STATUS_FSFILTER_OP_COMPLETED_SUCCESSFULLY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INTERRUPT_VECTOR_ALREADY_CONNECTED:
+- reason = "STATUS_INTERRUPT_VECTOR_ALREADY_CONNECTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INTERRUPT_STILL_CONNECTED:
+- reason = "STATUS_INTERRUPT_STILL_CONNECTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PROCESS_CLONED:
+- reason = "STATUS_PROCESS_CLONED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FILE_LOCKED_WITH_ONLY_READERS:
+- reason = "STATUS_FILE_LOCKED_WITH_ONLY_READERS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FILE_LOCKED_WITH_WRITERS:
+- reason = "STATUS_FILE_LOCKED_WITH_WRITERS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VALID_IMAGE_HASH:
+- reason = "STATUS_VALID_IMAGE_HASH";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VALID_CATALOG_HASH:
+- reason = "STATUS_VALID_CATALOG_HASH";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VALID_STRONG_CODE_HASH:
+- reason = "STATUS_VALID_STRONG_CODE_HASH";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GHOSTED:
+- reason = "STATUS_GHOSTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DATA_OVERWRITTEN:
+- reason = "STATUS_DATA_OVERWRITTEN";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_RESOURCEMANAGER_READ_ONLY:
+- reason = "STATUS_RESOURCEMANAGER_READ_ONLY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_RING_PREVIOUSLY_EMPTY:
+- reason = "STATUS_RING_PREVIOUSLY_EMPTY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_RING_PREVIOUSLY_FULL:
+- reason = "STATUS_RING_PREVIOUSLY_FULL";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_RING_PREVIOUSLY_ABOVE_QUOTA:
+- reason = "STATUS_RING_PREVIOUSLY_ABOVE_QUOTA";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_RING_NEWLY_EMPTY:
+- reason = "STATUS_RING_NEWLY_EMPTY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_RING_SIGNAL_OPPOSITE_ENDPOINT:
+- reason = "STATUS_RING_SIGNAL_OPPOSITE_ENDPOINT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_OPLOCK_SWITCHED_TO_NEW_HANDLE:
+- reason = "STATUS_OPLOCK_SWITCHED_TO_NEW_HANDLE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_OPLOCK_HANDLE_CLOSED:
+- reason = "STATUS_OPLOCK_HANDLE_CLOSED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_WAIT_FOR_OPLOCK:
+- reason = "STATUS_WAIT_FOR_OPLOCK";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_REPARSE_GLOBAL:
+- reason = "STATUS_REPARSE_GLOBAL";
+- break;
+- case MD_NTSTATUS_WIN_DBG_EXCEPTION_HANDLED:
+- reason = "DBG_EXCEPTION_HANDLED";
+- break;
+- case MD_NTSTATUS_WIN_DBG_CONTINUE:
+- reason = "DBG_CONTINUE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FLT_IO_COMPLETE:
+- reason = "STATUS_FLT_IO_COMPLETE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_RTPM_CONTEXT_CONTINUE:
+- reason = "STATUS_RTPM_CONTEXT_CONTINUE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_RTPM_CONTEXT_COMPLETE:
+- reason = "STATUS_RTPM_CONTEXT_COMPLETE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_HV_PENDING_PAGE_REQUESTS:
+- reason = "STATUS_HV_PENDING_PAGE_REQUESTS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SPACES_REPAIRED:
+- reason = "STATUS_SPACES_REPAIRED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SPACES_PAUSE:
+- reason = "STATUS_SPACES_PAUSE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SPACES_COMPLETE:
+- reason = "STATUS_SPACES_COMPLETE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SPACES_REDIRECT:
+- reason = "STATUS_SPACES_REDIRECT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_OBJECT_NAME_EXISTS:
+- reason = "STATUS_OBJECT_NAME_EXISTS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_THREAD_WAS_SUSPENDED:
+- reason = "STATUS_THREAD_WAS_SUSPENDED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_WORKING_SET_LIMIT_RANGE:
+- reason = "STATUS_WORKING_SET_LIMIT_RANGE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_IMAGE_NOT_AT_BASE:
+- reason = "STATUS_IMAGE_NOT_AT_BASE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_RXACT_STATE_CREATED:
+- reason = "STATUS_RXACT_STATE_CREATED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SEGMENT_NOTIFICATION:
+- reason = "STATUS_SEGMENT_NOTIFICATION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_LOCAL_USER_SESSION_KEY:
+- reason = "STATUS_LOCAL_USER_SESSION_KEY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_BAD_CURRENT_DIRECTORY:
+- reason = "STATUS_BAD_CURRENT_DIRECTORY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SERIAL_MORE_WRITES:
+- reason = "STATUS_SERIAL_MORE_WRITES";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_REGISTRY_RECOVERED:
+- reason = "STATUS_REGISTRY_RECOVERED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FT_READ_RECOVERY_FROM_BACKUP:
+- reason = "STATUS_FT_READ_RECOVERY_FROM_BACKUP";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FT_WRITE_RECOVERY:
+- reason = "STATUS_FT_WRITE_RECOVERY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SERIAL_COUNTER_TIMEOUT:
+- reason = "STATUS_SERIAL_COUNTER_TIMEOUT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NULL_LM_PASSWORD:
+- reason = "STATUS_NULL_LM_PASSWORD";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_IMAGE_MACHINE_TYPE_MISMATCH:
+- reason = "STATUS_IMAGE_MACHINE_TYPE_MISMATCH";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_RECEIVE_PARTIAL:
+- reason = "STATUS_RECEIVE_PARTIAL";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_RECEIVE_EXPEDITED:
+- reason = "STATUS_RECEIVE_EXPEDITED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_RECEIVE_PARTIAL_EXPEDITED:
+- reason = "STATUS_RECEIVE_PARTIAL_EXPEDITED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_EVENT_DONE:
+- reason = "STATUS_EVENT_DONE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_EVENT_PENDING:
+- reason = "STATUS_EVENT_PENDING";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CHECKING_FILE_SYSTEM:
+- reason = "STATUS_CHECKING_FILE_SYSTEM";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FATAL_APP_EXIT:
+- reason = "STATUS_FATAL_APP_EXIT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PREDEFINED_HANDLE:
+- reason = "STATUS_PREDEFINED_HANDLE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_WAS_UNLOCKED:
+- reason = "STATUS_WAS_UNLOCKED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SERVICE_NOTIFICATION:
+- reason = "STATUS_SERVICE_NOTIFICATION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_WAS_LOCKED:
+- reason = "STATUS_WAS_LOCKED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_LOG_HARD_ERROR:
+- reason = "STATUS_LOG_HARD_ERROR";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ALREADY_WIN32:
+- reason = "STATUS_ALREADY_WIN32";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_WX86_UNSIMULATE:
+- reason = "STATUS_WX86_UNSIMULATE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_WX86_CONTINUE:
+- reason = "STATUS_WX86_CONTINUE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_WX86_SINGLE_STEP:
+- reason = "STATUS_WX86_SINGLE_STEP";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_WX86_BREAKPOINT:
+- reason = "STATUS_WX86_BREAKPOINT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_WX86_EXCEPTION_CONTINUE:
+- reason = "STATUS_WX86_EXCEPTION_CONTINUE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_WX86_EXCEPTION_LASTCHANCE:
+- reason = "STATUS_WX86_EXCEPTION_LASTCHANCE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_WX86_EXCEPTION_CHAIN:
+- reason = "STATUS_WX86_EXCEPTION_CHAIN";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_IMAGE_MACHINE_TYPE_MISMATCH_EXE:
+- reason = "STATUS_IMAGE_MACHINE_TYPE_MISMATCH_EXE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NO_YIELD_PERFORMED:
+- reason = "STATUS_NO_YIELD_PERFORMED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TIMER_RESUME_IGNORED:
+- reason = "STATUS_TIMER_RESUME_IGNORED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ARBITRATION_UNHANDLED:
+- reason = "STATUS_ARBITRATION_UNHANDLED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CARDBUS_NOT_SUPPORTED:
+- reason = "STATUS_CARDBUS_NOT_SUPPORTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_WX86_CREATEWX86TIB:
+- reason = "STATUS_WX86_CREATEWX86TIB";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_MP_PROCESSOR_MISMATCH:
+- reason = "STATUS_MP_PROCESSOR_MISMATCH";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_HIBERNATED:
+- reason = "STATUS_HIBERNATED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_RESUME_HIBERNATION:
+- reason = "STATUS_RESUME_HIBERNATION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FIRMWARE_UPDATED:
+- reason = "STATUS_FIRMWARE_UPDATED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DRIVERS_LEAKING_LOCKED_PAGES:
+- reason = "STATUS_DRIVERS_LEAKING_LOCKED_PAGES";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_MESSAGE_RETRIEVED:
+- reason = "STATUS_MESSAGE_RETRIEVED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SYSTEM_POWERSTATE_TRANSITION:
+- reason = "STATUS_SYSTEM_POWERSTATE_TRANSITION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ALPC_CHECK_COMPLETION_LIST:
+- reason = "STATUS_ALPC_CHECK_COMPLETION_LIST";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SYSTEM_POWERSTATE_COMPLEX_TRANSITION:
+- reason = "STATUS_SYSTEM_POWERSTATE_COMPLEX_TRANSITION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ACCESS_AUDIT_BY_POLICY:
+- reason = "STATUS_ACCESS_AUDIT_BY_POLICY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ABANDON_HIBERFILE:
+- reason = "STATUS_ABANDON_HIBERFILE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_BIZRULES_NOT_ENABLED:
+- reason = "STATUS_BIZRULES_NOT_ENABLED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FT_READ_FROM_COPY:
+- reason = "STATUS_FT_READ_FROM_COPY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_IMAGE_AT_DIFFERENT_BASE:
+- reason = "STATUS_IMAGE_AT_DIFFERENT_BASE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PATCH_DEFERRED:
+- reason = "STATUS_PATCH_DEFERRED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_WAKE_SYSTEM:
+- reason = "STATUS_WAKE_SYSTEM";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DS_SHUTTING_DOWN:
+- reason = "STATUS_DS_SHUTTING_DOWN";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DISK_REPAIR_REDIRECTED:
+- reason = "STATUS_DISK_REPAIR_REDIRECTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SERVICES_FAILED_AUTOSTART:
+- reason = "STATUS_SERVICES_FAILED_AUTOSTART";
+- break;
+- case MD_NTSTATUS_WIN_DBG_REPLY_LATER:
+- reason = "DBG_REPLY_LATER";
+- break;
+- case MD_NTSTATUS_WIN_DBG_UNABLE_TO_PROVIDE_HANDLE:
+- reason = "DBG_UNABLE_TO_PROVIDE_HANDLE";
+- break;
+- case MD_NTSTATUS_WIN_DBG_TERMINATE_THREAD:
+- reason = "DBG_TERMINATE_THREAD";
+- break;
+- case MD_NTSTATUS_WIN_DBG_TERMINATE_PROCESS:
+- reason = "DBG_TERMINATE_PROCESS";
+- break;
+- case MD_NTSTATUS_WIN_DBG_CONTROL_C:
+- reason = "DBG_CONTROL_C";
+- break;
+- case MD_NTSTATUS_WIN_DBG_PRINTEXCEPTION_C:
+- reason = "DBG_PRINTEXCEPTION_C";
+- break;
+- case MD_NTSTATUS_WIN_DBG_RIPEXCEPTION:
+- reason = "DBG_RIPEXCEPTION";
+- break;
+- case MD_NTSTATUS_WIN_DBG_CONTROL_BREAK:
+- reason = "DBG_CONTROL_BREAK";
+- break;
+- case MD_NTSTATUS_WIN_DBG_COMMAND_EXCEPTION:
+- reason = "DBG_COMMAND_EXCEPTION";
+- break;
+- case MD_NTSTATUS_WIN_DBG_PRINTEXCEPTION_WIDE_C:
+- reason = "DBG_PRINTEXCEPTION_WIDE_C";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_UUID_LOCAL_ONLY:
+- reason = "RPC_NT_UUID_LOCAL_ONLY";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_SEND_INCOMPLETE:
+- reason = "RPC_NT_SEND_INCOMPLETE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CTX_CDM_CONNECT:
+- reason = "STATUS_CTX_CDM_CONNECT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CTX_CDM_DISCONNECT:
+- reason = "STATUS_CTX_CDM_DISCONNECT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SXS_RELEASE_ACTIVATION_CONTEXT:
+- reason = "STATUS_SXS_RELEASE_ACTIVATION_CONTEXT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_HEURISTIC_DAMAGE_POSSIBLE:
+- reason = "STATUS_HEURISTIC_DAMAGE_POSSIBLE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_RECOVERY_NOT_NEEDED:
+- reason = "STATUS_RECOVERY_NOT_NEEDED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_RM_ALREADY_STARTED:
+- reason = "STATUS_RM_ALREADY_STARTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_LOG_NO_RESTART:
+- reason = "STATUS_LOG_NO_RESTART";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VIDEO_DRIVER_DEBUG_REPORT_REQUEST:
+- reason = "STATUS_VIDEO_DRIVER_DEBUG_REPORT_REQUEST";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_PARTIAL_DATA_POPULATED:
+- reason = "STATUS_GRAPHICS_PARTIAL_DATA_POPULATED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_SKIP_ALLOCATION_PREPARATION:
+- reason = "STATUS_GRAPHICS_SKIP_ALLOCATION_PREPARATION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_MODE_NOT_PINNED:
+- reason = "STATUS_GRAPHICS_MODE_NOT_PINNED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_NO_PREFERRED_MODE:
+- reason = "STATUS_GRAPHICS_NO_PREFERRED_MODE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_DATASET_IS_EMPTY:
+- reason = "STATUS_GRAPHICS_DATASET_IS_EMPTY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_NO_MORE_ELEMENTS_IN_DATASET:
+- reason = "STATUS_GRAPHICS_NO_MORE_ELEMENTS_IN_DATASET";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_PATH_CONTENT_GEOMETRY_TRANSFORMATION_NOT_PINNED:
+- reason = "STATUS_GRAPHICS_PATH_CONTENT_GEOMETRY_TRANSFORMATION_NOT_PINNED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_UNKNOWN_CHILD_STATUS:
+- reason = "STATUS_GRAPHICS_UNKNOWN_CHILD_STATUS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_LEADLINK_START_DEFERRED:
+- reason = "STATUS_GRAPHICS_LEADLINK_START_DEFERRED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_POLLING_TOO_FREQUENTLY:
+- reason = "STATUS_GRAPHICS_POLLING_TOO_FREQUENTLY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_START_DEFERRED:
+- reason = "STATUS_GRAPHICS_START_DEFERRED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_DEPENDABLE_CHILD_STATUS:
+- reason = "STATUS_GRAPHICS_DEPENDABLE_CHILD_STATUS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NDIS_INDICATION_REQUIRED:
+- reason = "STATUS_NDIS_INDICATION_REQUIRED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PCP_UNSUPPORTED_PSS_SALT:
+- reason = "STATUS_PCP_UNSUPPORTED_PSS_SALT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GUARD_PAGE_VIOLATION:
+- reason = "STATUS_GUARD_PAGE_VIOLATION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DATATYPE_MISALIGNMENT:
+- reason = "STATUS_DATATYPE_MISALIGNMENT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_BREAKPOINT:
+- reason = "STATUS_BREAKPOINT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SINGLE_STEP:
+- reason = "STATUS_SINGLE_STEP";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_BUFFER_OVERFLOW:
+- reason = "STATUS_BUFFER_OVERFLOW";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NO_MORE_FILES:
+- reason = "STATUS_NO_MORE_FILES";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_WAKE_SYSTEM_DEBUGGER:
+- reason = "STATUS_WAKE_SYSTEM_DEBUGGER";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_HANDLES_CLOSED:
+- reason = "STATUS_HANDLES_CLOSED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NO_INHERITANCE:
+- reason = "STATUS_NO_INHERITANCE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GUID_SUBSTITUTION_MADE:
+- reason = "STATUS_GUID_SUBSTITUTION_MADE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PARTIAL_COPY:
+- reason = "STATUS_PARTIAL_COPY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DEVICE_PAPER_EMPTY:
+- reason = "STATUS_DEVICE_PAPER_EMPTY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DEVICE_POWERED_OFF:
+- reason = "STATUS_DEVICE_POWERED_OFF";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DEVICE_OFF_LINE:
+- reason = "STATUS_DEVICE_OFF_LINE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DEVICE_BUSY:
+- reason = "STATUS_DEVICE_BUSY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NO_MORE_EAS:
+- reason = "STATUS_NO_MORE_EAS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_EA_NAME:
+- reason = "STATUS_INVALID_EA_NAME";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_EA_LIST_INCONSISTENT:
+- reason = "STATUS_EA_LIST_INCONSISTENT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_EA_FLAG:
+- reason = "STATUS_INVALID_EA_FLAG";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VERIFY_REQUIRED:
+- reason = "STATUS_VERIFY_REQUIRED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_EXTRANEOUS_INFORMATION:
+- reason = "STATUS_EXTRANEOUS_INFORMATION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_RXACT_COMMIT_NECESSARY:
+- reason = "STATUS_RXACT_COMMIT_NECESSARY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NO_MORE_ENTRIES:
+- reason = "STATUS_NO_MORE_ENTRIES";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FILEMARK_DETECTED:
+- reason = "STATUS_FILEMARK_DETECTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_MEDIA_CHANGED:
+- reason = "STATUS_MEDIA_CHANGED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_BUS_RESET:
+- reason = "STATUS_BUS_RESET";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_END_OF_MEDIA:
+- reason = "STATUS_END_OF_MEDIA";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_BEGINNING_OF_MEDIA:
+- reason = "STATUS_BEGINNING_OF_MEDIA";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_MEDIA_CHECK:
+- reason = "STATUS_MEDIA_CHECK";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SETMARK_DETECTED:
+- reason = "STATUS_SETMARK_DETECTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NO_DATA_DETECTED:
+- reason = "STATUS_NO_DATA_DETECTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_REDIRECTOR_HAS_OPEN_HANDLES:
+- reason = "STATUS_REDIRECTOR_HAS_OPEN_HANDLES";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SERVER_HAS_OPEN_HANDLES:
+- reason = "STATUS_SERVER_HAS_OPEN_HANDLES";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ALREADY_DISCONNECTED:
+- reason = "STATUS_ALREADY_DISCONNECTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_LONGJUMP:
+- reason = "STATUS_LONGJUMP";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CLEANER_CARTRIDGE_INSTALLED:
+- reason = "STATUS_CLEANER_CARTRIDGE_INSTALLED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PLUGPLAY_QUERY_VETOED:
+- reason = "STATUS_PLUGPLAY_QUERY_VETOED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_UNWIND_CONSOLIDATE:
+- reason = "STATUS_UNWIND_CONSOLIDATE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_REGISTRY_HIVE_RECOVERED:
+- reason = "STATUS_REGISTRY_HIVE_RECOVERED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DLL_MIGHT_BE_INSECURE:
+- reason = "STATUS_DLL_MIGHT_BE_INSECURE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DLL_MIGHT_BE_INCOMPATIBLE:
+- reason = "STATUS_DLL_MIGHT_BE_INCOMPATIBLE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_STOPPED_ON_SYMLINK:
+- reason = "STATUS_STOPPED_ON_SYMLINK";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CANNOT_GRANT_REQUESTED_OPLOCK:
+- reason = "STATUS_CANNOT_GRANT_REQUESTED_OPLOCK";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NO_ACE_CONDITION:
+- reason = "STATUS_NO_ACE_CONDITION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DEVICE_SUPPORT_IN_PROGRESS:
+- reason = "STATUS_DEVICE_SUPPORT_IN_PROGRESS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DEVICE_POWER_CYCLE_REQUIRED:
+- reason = "STATUS_DEVICE_POWER_CYCLE_REQUIRED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NO_WORK_DONE:
+- reason = "STATUS_NO_WORK_DONE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_RETURN_ADDRESS_HIJACK_ATTEMPT:
+- reason = "STATUS_RETURN_ADDRESS_HIJACK_ATTEMPT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DEVICE_REQUIRES_CLEANING:
+- reason = "STATUS_DEVICE_REQUIRES_CLEANING";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DEVICE_DOOR_OPEN:
+- reason = "STATUS_DEVICE_DOOR_OPEN";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DATA_LOST_REPAIR:
+- reason = "STATUS_DATA_LOST_REPAIR";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GPIO_INTERRUPT_ALREADY_UNMASKED:
+- reason = "STATUS_GPIO_INTERRUPT_ALREADY_UNMASKED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_PROPERTY_BLOB_CHECKSUM_MISMATCH:
+- reason = "STATUS_CLOUD_FILE_PROPERTY_BLOB_CHECKSUM_MISMATCH";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_PROPERTY_BLOB_TOO_LARGE:
+- reason = "STATUS_CLOUD_FILE_PROPERTY_BLOB_TOO_LARGE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_TOO_MANY_PROPERTY_BLOBS:
+- reason = "STATUS_CLOUD_FILE_TOO_MANY_PROPERTY_BLOBS";
+- break;
+- case MD_NTSTATUS_WIN_DBG_EXCEPTION_NOT_HANDLED:
+- reason = "DBG_EXCEPTION_NOT_HANDLED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CLUSTER_NODE_ALREADY_UP:
+- reason = "STATUS_CLUSTER_NODE_ALREADY_UP";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CLUSTER_NODE_ALREADY_DOWN:
+- reason = "STATUS_CLUSTER_NODE_ALREADY_DOWN";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CLUSTER_NETWORK_ALREADY_ONLINE:
+- reason = "STATUS_CLUSTER_NETWORK_ALREADY_ONLINE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CLUSTER_NETWORK_ALREADY_OFFLINE:
+- reason = "STATUS_CLUSTER_NETWORK_ALREADY_OFFLINE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CLUSTER_NODE_ALREADY_MEMBER:
+- reason = "STATUS_CLUSTER_NODE_ALREADY_MEMBER";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_COULD_NOT_RESIZE_LOG:
+- reason = "STATUS_COULD_NOT_RESIZE_LOG";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NO_TXF_METADATA:
+- reason = "STATUS_NO_TXF_METADATA";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CANT_RECOVER_WITH_HANDLE_OPEN:
+- reason = "STATUS_CANT_RECOVER_WITH_HANDLE_OPEN";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TXF_METADATA_ALREADY_PRESENT:
+- reason = "STATUS_TXF_METADATA_ALREADY_PRESENT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TRANSACTION_SCOPE_CALLBACKS_NOT_SET:
+- reason = "STATUS_TRANSACTION_SCOPE_CALLBACKS_NOT_SET";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VIDEO_HUNG_DISPLAY_DRIVER_THREAD_RECOVERED:
+- reason = "STATUS_VIDEO_HUNG_DISPLAY_DRIVER_THREAD_RECOVERED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FLT_BUFFER_TOO_SMALL:
+- reason = "STATUS_FLT_BUFFER_TOO_SMALL";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FVE_PARTIAL_METADATA:
+- reason = "STATUS_FVE_PARTIAL_METADATA";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FVE_TRANSIENT_STATE:
+- reason = "STATUS_FVE_TRANSIENT_STATE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VID_REMOTE_NODE_PARENT_GPA_PAGES_USED:
+- reason = "STATUS_VID_REMOTE_NODE_PARENT_GPA_PAGES_USED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLMGR_INCOMPLETE_REGENERATION:
+- reason = "STATUS_VOLMGR_INCOMPLETE_REGENERATION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLMGR_INCOMPLETE_DISK_MIGRATION:
+- reason = "STATUS_VOLMGR_INCOMPLETE_DISK_MIGRATION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_BCD_NOT_ALL_ENTRIES_IMPORTED:
+- reason = "STATUS_BCD_NOT_ALL_ENTRIES_IMPORTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_BCD_NOT_ALL_ENTRIES_SYNCHRONIZED:
+- reason = "STATUS_BCD_NOT_ALL_ENTRIES_SYNCHRONIZED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_QUERY_STORAGE_ERROR:
+- reason = "STATUS_QUERY_STORAGE_ERROR";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GDI_HANDLE_LEAK:
+- reason = "STATUS_GDI_HANDLE_LEAK";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SECUREBOOT_NOT_ENABLED:
+- reason = "STATUS_SECUREBOOT_NOT_ENABLED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_UNSUCCESSFUL:
+- reason = "STATUS_UNSUCCESSFUL";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NOT_IMPLEMENTED:
+- reason = "STATUS_NOT_IMPLEMENTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_INFO_CLASS:
+- reason = "STATUS_INVALID_INFO_CLASS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INFO_LENGTH_MISMATCH:
+- reason = "STATUS_INFO_LENGTH_MISMATCH";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ACCESS_VIOLATION:
+- reason = "STATUS_ACCESS_VIOLATION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_IN_PAGE_ERROR:
+- reason = "STATUS_IN_PAGE_ERROR";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PAGEFILE_QUOTA:
+- reason = "STATUS_PAGEFILE_QUOTA";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_HANDLE:
+- reason = "STATUS_INVALID_HANDLE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_BAD_INITIAL_STACK:
+- reason = "STATUS_BAD_INITIAL_STACK";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_BAD_INITIAL_PC:
+- reason = "STATUS_BAD_INITIAL_PC";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_CID:
+- reason = "STATUS_INVALID_CID";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TIMER_NOT_CANCELED:
+- reason = "STATUS_TIMER_NOT_CANCELED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_PARAMETER:
+- reason = "STATUS_INVALID_PARAMETER";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NO_SUCH_DEVICE:
+- reason = "STATUS_NO_SUCH_DEVICE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NO_SUCH_FILE:
+- reason = "STATUS_NO_SUCH_FILE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_DEVICE_REQUEST:
+- reason = "STATUS_INVALID_DEVICE_REQUEST";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_END_OF_FILE:
+- reason = "STATUS_END_OF_FILE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_WRONG_VOLUME:
+- reason = "STATUS_WRONG_VOLUME";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NO_MEDIA_IN_DEVICE:
+- reason = "STATUS_NO_MEDIA_IN_DEVICE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_UNRECOGNIZED_MEDIA:
+- reason = "STATUS_UNRECOGNIZED_MEDIA";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NONEXISTENT_SECTOR:
+- reason = "STATUS_NONEXISTENT_SECTOR";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_MORE_PROCESSING_REQUIRED:
+- reason = "STATUS_MORE_PROCESSING_REQUIRED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NO_MEMORY:
+- reason = "STATUS_NO_MEMORY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CONFLICTING_ADDRESSES:
+- reason = "STATUS_CONFLICTING_ADDRESSES";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NOT_MAPPED_VIEW:
+- reason = "STATUS_NOT_MAPPED_VIEW";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_UNABLE_TO_FREE_VM:
+- reason = "STATUS_UNABLE_TO_FREE_VM";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_UNABLE_TO_DELETE_SECTION:
+- reason = "STATUS_UNABLE_TO_DELETE_SECTION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_SYSTEM_SERVICE:
+- reason = "STATUS_INVALID_SYSTEM_SERVICE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ILLEGAL_INSTRUCTION:
+- reason = "STATUS_ILLEGAL_INSTRUCTION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_LOCK_SEQUENCE:
+- reason = "STATUS_INVALID_LOCK_SEQUENCE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_VIEW_SIZE:
+- reason = "STATUS_INVALID_VIEW_SIZE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_FILE_FOR_SECTION:
+- reason = "STATUS_INVALID_FILE_FOR_SECTION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ALREADY_COMMITTED:
+- reason = "STATUS_ALREADY_COMMITTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ACCESS_DENIED:
+- reason = "STATUS_ACCESS_DENIED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_BUFFER_TOO_SMALL:
+- reason = "STATUS_BUFFER_TOO_SMALL";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_OBJECT_TYPE_MISMATCH:
+- reason = "STATUS_OBJECT_TYPE_MISMATCH";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NONCONTINUABLE_EXCEPTION:
+- reason = "STATUS_NONCONTINUABLE_EXCEPTION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_DISPOSITION:
+- reason = "STATUS_INVALID_DISPOSITION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_UNWIND:
+- reason = "STATUS_UNWIND";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_BAD_STACK:
+- reason = "STATUS_BAD_STACK";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_UNWIND_TARGET:
+- reason = "STATUS_INVALID_UNWIND_TARGET";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NOT_LOCKED:
+- reason = "STATUS_NOT_LOCKED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PARITY_ERROR:
+- reason = "STATUS_PARITY_ERROR";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_UNABLE_TO_DECOMMIT_VM:
+- reason = "STATUS_UNABLE_TO_DECOMMIT_VM";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NOT_COMMITTED:
+- reason = "STATUS_NOT_COMMITTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_PORT_ATTRIBUTES:
+- reason = "STATUS_INVALID_PORT_ATTRIBUTES";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PORT_MESSAGE_TOO_LONG:
+- reason = "STATUS_PORT_MESSAGE_TOO_LONG";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_PARAMETER_MIX:
+- reason = "STATUS_INVALID_PARAMETER_MIX";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_QUOTA_LOWER:
+- reason = "STATUS_INVALID_QUOTA_LOWER";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DISK_CORRUPT_ERROR:
+- reason = "STATUS_DISK_CORRUPT_ERROR";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_OBJECT_NAME_INVALID:
+- reason = "STATUS_OBJECT_NAME_INVALID";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_OBJECT_NAME_NOT_FOUND:
+- reason = "STATUS_OBJECT_NAME_NOT_FOUND";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_OBJECT_NAME_COLLISION:
+- reason = "STATUS_OBJECT_NAME_COLLISION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PORT_DO_NOT_DISTURB:
+- reason = "STATUS_PORT_DO_NOT_DISTURB";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PORT_DISCONNECTED:
+- reason = "STATUS_PORT_DISCONNECTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DEVICE_ALREADY_ATTACHED:
+- reason = "STATUS_DEVICE_ALREADY_ATTACHED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_OBJECT_PATH_INVALID:
+- reason = "STATUS_OBJECT_PATH_INVALID";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_OBJECT_PATH_NOT_FOUND:
+- reason = "STATUS_OBJECT_PATH_NOT_FOUND";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_OBJECT_PATH_SYNTAX_BAD:
+- reason = "STATUS_OBJECT_PATH_SYNTAX_BAD";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DATA_OVERRUN:
+- reason = "STATUS_DATA_OVERRUN";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DATA_LATE_ERROR:
+- reason = "STATUS_DATA_LATE_ERROR";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DATA_ERROR:
+- reason = "STATUS_DATA_ERROR";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CRC_ERROR:
+- reason = "STATUS_CRC_ERROR";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SECTION_TOO_BIG:
+- reason = "STATUS_SECTION_TOO_BIG";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PORT_CONNECTION_REFUSED:
+- reason = "STATUS_PORT_CONNECTION_REFUSED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_PORT_HANDLE:
+- reason = "STATUS_INVALID_PORT_HANDLE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SHARING_VIOLATION:
+- reason = "STATUS_SHARING_VIOLATION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_QUOTA_EXCEEDED:
+- reason = "STATUS_QUOTA_EXCEEDED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_PAGE_PROTECTION:
+- reason = "STATUS_INVALID_PAGE_PROTECTION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_MUTANT_NOT_OWNED:
+- reason = "STATUS_MUTANT_NOT_OWNED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SEMAPHORE_LIMIT_EXCEEDED:
+- reason = "STATUS_SEMAPHORE_LIMIT_EXCEEDED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PORT_ALREADY_SET:
+- reason = "STATUS_PORT_ALREADY_SET";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SECTION_NOT_IMAGE:
+- reason = "STATUS_SECTION_NOT_IMAGE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SUSPEND_COUNT_EXCEEDED:
+- reason = "STATUS_SUSPEND_COUNT_EXCEEDED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_THREAD_IS_TERMINATING:
+- reason = "STATUS_THREAD_IS_TERMINATING";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_BAD_WORKING_SET_LIMIT:
+- reason = "STATUS_BAD_WORKING_SET_LIMIT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INCOMPATIBLE_FILE_MAP:
+- reason = "STATUS_INCOMPATIBLE_FILE_MAP";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SECTION_PROTECTION:
+- reason = "STATUS_SECTION_PROTECTION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_EAS_NOT_SUPPORTED:
+- reason = "STATUS_EAS_NOT_SUPPORTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_EA_TOO_LARGE:
+- reason = "STATUS_EA_TOO_LARGE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NONEXISTENT_EA_ENTRY:
+- reason = "STATUS_NONEXISTENT_EA_ENTRY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NO_EAS_ON_FILE:
+- reason = "STATUS_NO_EAS_ON_FILE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_EA_CORRUPT_ERROR:
+- reason = "STATUS_EA_CORRUPT_ERROR";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FILE_LOCK_CONFLICT:
+- reason = "STATUS_FILE_LOCK_CONFLICT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_LOCK_NOT_GRANTED:
+- reason = "STATUS_LOCK_NOT_GRANTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DELETE_PENDING:
+- reason = "STATUS_DELETE_PENDING";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CTL_FILE_NOT_SUPPORTED:
+- reason = "STATUS_CTL_FILE_NOT_SUPPORTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_UNKNOWN_REVISION:
+- reason = "STATUS_UNKNOWN_REVISION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_REVISION_MISMATCH:
+- reason = "STATUS_REVISION_MISMATCH";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_OWNER:
+- reason = "STATUS_INVALID_OWNER";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_PRIMARY_GROUP:
+- reason = "STATUS_INVALID_PRIMARY_GROUP";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NO_IMPERSONATION_TOKEN:
+- reason = "STATUS_NO_IMPERSONATION_TOKEN";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CANT_DISABLE_MANDATORY:
+- reason = "STATUS_CANT_DISABLE_MANDATORY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NO_LOGON_SERVERS:
+- reason = "STATUS_NO_LOGON_SERVERS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NO_SUCH_LOGON_SESSION:
+- reason = "STATUS_NO_SUCH_LOGON_SESSION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NO_SUCH_PRIVILEGE:
+- reason = "STATUS_NO_SUCH_PRIVILEGE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PRIVILEGE_NOT_HELD:
+- reason = "STATUS_PRIVILEGE_NOT_HELD";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_ACCOUNT_NAME:
+- reason = "STATUS_INVALID_ACCOUNT_NAME";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_USER_EXISTS:
+- reason = "STATUS_USER_EXISTS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NO_SUCH_USER:
+- reason = "STATUS_NO_SUCH_USER";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GROUP_EXISTS:
+- reason = "STATUS_GROUP_EXISTS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NO_SUCH_GROUP:
+- reason = "STATUS_NO_SUCH_GROUP";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_MEMBER_IN_GROUP:
+- reason = "STATUS_MEMBER_IN_GROUP";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_MEMBER_NOT_IN_GROUP:
+- reason = "STATUS_MEMBER_NOT_IN_GROUP";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_LAST_ADMIN:
+- reason = "STATUS_LAST_ADMIN";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_WRONG_PASSWORD:
+- reason = "STATUS_WRONG_PASSWORD";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ILL_FORMED_PASSWORD:
+- reason = "STATUS_ILL_FORMED_PASSWORD";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PASSWORD_RESTRICTION:
+- reason = "STATUS_PASSWORD_RESTRICTION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_LOGON_FAILURE:
+- reason = "STATUS_LOGON_FAILURE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ACCOUNT_RESTRICTION:
+- reason = "STATUS_ACCOUNT_RESTRICTION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_LOGON_HOURS:
+- reason = "STATUS_INVALID_LOGON_HOURS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_WORKSTATION:
+- reason = "STATUS_INVALID_WORKSTATION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PASSWORD_EXPIRED:
+- reason = "STATUS_PASSWORD_EXPIRED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ACCOUNT_DISABLED:
+- reason = "STATUS_ACCOUNT_DISABLED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NONE_MAPPED:
+- reason = "STATUS_NONE_MAPPED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TOO_MANY_LUIDS_REQUESTED:
+- reason = "STATUS_TOO_MANY_LUIDS_REQUESTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_LUIDS_EXHAUSTED:
+- reason = "STATUS_LUIDS_EXHAUSTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_SUB_AUTHORITY:
+- reason = "STATUS_INVALID_SUB_AUTHORITY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_ACL:
+- reason = "STATUS_INVALID_ACL";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_SID:
+- reason = "STATUS_INVALID_SID";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_SECURITY_DESCR:
+- reason = "STATUS_INVALID_SECURITY_DESCR";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PROCEDURE_NOT_FOUND:
+- reason = "STATUS_PROCEDURE_NOT_FOUND";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_IMAGE_FORMAT:
+- reason = "STATUS_INVALID_IMAGE_FORMAT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NO_TOKEN:
+- reason = "STATUS_NO_TOKEN";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_BAD_INHERITANCE_ACL:
+- reason = "STATUS_BAD_INHERITANCE_ACL";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_RANGE_NOT_LOCKED:
+- reason = "STATUS_RANGE_NOT_LOCKED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DISK_FULL:
+- reason = "STATUS_DISK_FULL";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SERVER_DISABLED:
+- reason = "STATUS_SERVER_DISABLED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SERVER_NOT_DISABLED:
+- reason = "STATUS_SERVER_NOT_DISABLED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TOO_MANY_GUIDS_REQUESTED:
+- reason = "STATUS_TOO_MANY_GUIDS_REQUESTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GUIDS_EXHAUSTED:
+- reason = "STATUS_GUIDS_EXHAUSTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_ID_AUTHORITY:
+- reason = "STATUS_INVALID_ID_AUTHORITY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_AGENTS_EXHAUSTED:
+- reason = "STATUS_AGENTS_EXHAUSTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_VOLUME_LABEL:
+- reason = "STATUS_INVALID_VOLUME_LABEL";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SECTION_NOT_EXTENDED:
+- reason = "STATUS_SECTION_NOT_EXTENDED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NOT_MAPPED_DATA:
+- reason = "STATUS_NOT_MAPPED_DATA";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_RESOURCE_DATA_NOT_FOUND:
+- reason = "STATUS_RESOURCE_DATA_NOT_FOUND";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_RESOURCE_TYPE_NOT_FOUND:
+- reason = "STATUS_RESOURCE_TYPE_NOT_FOUND";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_RESOURCE_NAME_NOT_FOUND:
+- reason = "STATUS_RESOURCE_NAME_NOT_FOUND";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ARRAY_BOUNDS_EXCEEDED:
+- reason = "STATUS_ARRAY_BOUNDS_EXCEEDED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FLOAT_DENORMAL_OPERAND:
+- reason = "STATUS_FLOAT_DENORMAL_OPERAND";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FLOAT_DIVIDE_BY_ZERO:
+- reason = "STATUS_FLOAT_DIVIDE_BY_ZERO";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FLOAT_INEXACT_RESULT:
+- reason = "STATUS_FLOAT_INEXACT_RESULT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FLOAT_INVALID_OPERATION:
+- reason = "STATUS_FLOAT_INVALID_OPERATION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FLOAT_OVERFLOW:
+- reason = "STATUS_FLOAT_OVERFLOW";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FLOAT_STACK_CHECK:
+- reason = "STATUS_FLOAT_STACK_CHECK";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FLOAT_UNDERFLOW:
+- reason = "STATUS_FLOAT_UNDERFLOW";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INTEGER_DIVIDE_BY_ZERO:
+- reason = "STATUS_INTEGER_DIVIDE_BY_ZERO";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INTEGER_OVERFLOW:
+- reason = "STATUS_INTEGER_OVERFLOW";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PRIVILEGED_INSTRUCTION:
+- reason = "STATUS_PRIVILEGED_INSTRUCTION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TOO_MANY_PAGING_FILES:
+- reason = "STATUS_TOO_MANY_PAGING_FILES";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FILE_INVALID:
+- reason = "STATUS_FILE_INVALID";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ALLOTTED_SPACE_EXCEEDED:
+- reason = "STATUS_ALLOTTED_SPACE_EXCEEDED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INSUFFICIENT_RESOURCES:
+- reason = "STATUS_INSUFFICIENT_RESOURCES";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DFS_EXIT_PATH_FOUND:
+- reason = "STATUS_DFS_EXIT_PATH_FOUND";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DEVICE_DATA_ERROR:
+- reason = "STATUS_DEVICE_DATA_ERROR";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DEVICE_NOT_CONNECTED:
+- reason = "STATUS_DEVICE_NOT_CONNECTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DEVICE_POWER_FAILURE:
+- reason = "STATUS_DEVICE_POWER_FAILURE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FREE_VM_NOT_AT_BASE:
+- reason = "STATUS_FREE_VM_NOT_AT_BASE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_MEMORY_NOT_ALLOCATED:
+- reason = "STATUS_MEMORY_NOT_ALLOCATED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_WORKING_SET_QUOTA:
+- reason = "STATUS_WORKING_SET_QUOTA";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_MEDIA_WRITE_PROTECTED:
+- reason = "STATUS_MEDIA_WRITE_PROTECTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DEVICE_NOT_READY:
+- reason = "STATUS_DEVICE_NOT_READY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_GROUP_ATTRIBUTES:
+- reason = "STATUS_INVALID_GROUP_ATTRIBUTES";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_BAD_IMPERSONATION_LEVEL:
+- reason = "STATUS_BAD_IMPERSONATION_LEVEL";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CANT_OPEN_ANONYMOUS:
+- reason = "STATUS_CANT_OPEN_ANONYMOUS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_BAD_VALIDATION_CLASS:
+- reason = "STATUS_BAD_VALIDATION_CLASS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_BAD_TOKEN_TYPE:
+- reason = "STATUS_BAD_TOKEN_TYPE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_BAD_MASTER_BOOT_RECORD:
+- reason = "STATUS_BAD_MASTER_BOOT_RECORD";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INSTRUCTION_MISALIGNMENT:
+- reason = "STATUS_INSTRUCTION_MISALIGNMENT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INSTANCE_NOT_AVAILABLE:
+- reason = "STATUS_INSTANCE_NOT_AVAILABLE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PIPE_NOT_AVAILABLE:
+- reason = "STATUS_PIPE_NOT_AVAILABLE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_PIPE_STATE:
+- reason = "STATUS_INVALID_PIPE_STATE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PIPE_BUSY:
+- reason = "STATUS_PIPE_BUSY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ILLEGAL_FUNCTION:
+- reason = "STATUS_ILLEGAL_FUNCTION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PIPE_DISCONNECTED:
+- reason = "STATUS_PIPE_DISCONNECTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PIPE_CLOSING:
+- reason = "STATUS_PIPE_CLOSING";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PIPE_CONNECTED:
+- reason = "STATUS_PIPE_CONNECTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PIPE_LISTENING:
+- reason = "STATUS_PIPE_LISTENING";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_READ_MODE:
+- reason = "STATUS_INVALID_READ_MODE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_IO_TIMEOUT:
+- reason = "STATUS_IO_TIMEOUT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FILE_FORCED_CLOSED:
+- reason = "STATUS_FILE_FORCED_CLOSED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PROFILING_NOT_STARTED:
+- reason = "STATUS_PROFILING_NOT_STARTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PROFILING_NOT_STOPPED:
+- reason = "STATUS_PROFILING_NOT_STOPPED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_COULD_NOT_INTERPRET:
+- reason = "STATUS_COULD_NOT_INTERPRET";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FILE_IS_A_DIRECTORY:
+- reason = "STATUS_FILE_IS_A_DIRECTORY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NOT_SUPPORTED:
+- reason = "STATUS_NOT_SUPPORTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_REMOTE_NOT_LISTENING:
+- reason = "STATUS_REMOTE_NOT_LISTENING";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DUPLICATE_NAME:
+- reason = "STATUS_DUPLICATE_NAME";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_BAD_NETWORK_PATH:
+- reason = "STATUS_BAD_NETWORK_PATH";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NETWORK_BUSY:
+- reason = "STATUS_NETWORK_BUSY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DEVICE_DOES_NOT_EXIST:
+- reason = "STATUS_DEVICE_DOES_NOT_EXIST";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TOO_MANY_COMMANDS:
+- reason = "STATUS_TOO_MANY_COMMANDS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ADAPTER_HARDWARE_ERROR:
+- reason = "STATUS_ADAPTER_HARDWARE_ERROR";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_NETWORK_RESPONSE:
+- reason = "STATUS_INVALID_NETWORK_RESPONSE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_UNEXPECTED_NETWORK_ERROR:
+- reason = "STATUS_UNEXPECTED_NETWORK_ERROR";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_BAD_REMOTE_ADAPTER:
+- reason = "STATUS_BAD_REMOTE_ADAPTER";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PRINT_QUEUE_FULL:
+- reason = "STATUS_PRINT_QUEUE_FULL";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NO_SPOOL_SPACE:
+- reason = "STATUS_NO_SPOOL_SPACE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PRINT_CANCELLED:
+- reason = "STATUS_PRINT_CANCELLED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NETWORK_NAME_DELETED:
+- reason = "STATUS_NETWORK_NAME_DELETED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NETWORK_ACCESS_DENIED:
+- reason = "STATUS_NETWORK_ACCESS_DENIED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_BAD_DEVICE_TYPE:
+- reason = "STATUS_BAD_DEVICE_TYPE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_BAD_NETWORK_NAME:
+- reason = "STATUS_BAD_NETWORK_NAME";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TOO_MANY_NAMES:
+- reason = "STATUS_TOO_MANY_NAMES";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TOO_MANY_SESSIONS:
+- reason = "STATUS_TOO_MANY_SESSIONS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SHARING_PAUSED:
+- reason = "STATUS_SHARING_PAUSED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_REQUEST_NOT_ACCEPTED:
+- reason = "STATUS_REQUEST_NOT_ACCEPTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_REDIRECTOR_PAUSED:
+- reason = "STATUS_REDIRECTOR_PAUSED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NET_WRITE_FAULT:
+- reason = "STATUS_NET_WRITE_FAULT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PROFILING_AT_LIMIT:
+- reason = "STATUS_PROFILING_AT_LIMIT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NOT_SAME_DEVICE:
+- reason = "STATUS_NOT_SAME_DEVICE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FILE_RENAMED:
+- reason = "STATUS_FILE_RENAMED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VIRTUAL_CIRCUIT_CLOSED:
+- reason = "STATUS_VIRTUAL_CIRCUIT_CLOSED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NO_SECURITY_ON_OBJECT:
+- reason = "STATUS_NO_SECURITY_ON_OBJECT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CANT_WAIT:
+- reason = "STATUS_CANT_WAIT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PIPE_EMPTY:
+- reason = "STATUS_PIPE_EMPTY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CANT_ACCESS_DOMAIN_INFO:
+- reason = "STATUS_CANT_ACCESS_DOMAIN_INFO";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CANT_TERMINATE_SELF:
+- reason = "STATUS_CANT_TERMINATE_SELF";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_SERVER_STATE:
+- reason = "STATUS_INVALID_SERVER_STATE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_DOMAIN_STATE:
+- reason = "STATUS_INVALID_DOMAIN_STATE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_DOMAIN_ROLE:
+- reason = "STATUS_INVALID_DOMAIN_ROLE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NO_SUCH_DOMAIN:
+- reason = "STATUS_NO_SUCH_DOMAIN";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DOMAIN_EXISTS:
+- reason = "STATUS_DOMAIN_EXISTS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DOMAIN_LIMIT_EXCEEDED:
+- reason = "STATUS_DOMAIN_LIMIT_EXCEEDED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_OPLOCK_NOT_GRANTED:
+- reason = "STATUS_OPLOCK_NOT_GRANTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_OPLOCK_PROTOCOL:
+- reason = "STATUS_INVALID_OPLOCK_PROTOCOL";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INTERNAL_DB_CORRUPTION:
+- reason = "STATUS_INTERNAL_DB_CORRUPTION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INTERNAL_ERROR:
+- reason = "STATUS_INTERNAL_ERROR";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GENERIC_NOT_MAPPED:
+- reason = "STATUS_GENERIC_NOT_MAPPED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_BAD_DESCRIPTOR_FORMAT:
+- reason = "STATUS_BAD_DESCRIPTOR_FORMAT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_USER_BUFFER:
+- reason = "STATUS_INVALID_USER_BUFFER";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_UNEXPECTED_IO_ERROR:
+- reason = "STATUS_UNEXPECTED_IO_ERROR";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_UNEXPECTED_MM_CREATE_ERR:
+- reason = "STATUS_UNEXPECTED_MM_CREATE_ERR";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_UNEXPECTED_MM_MAP_ERROR:
+- reason = "STATUS_UNEXPECTED_MM_MAP_ERROR";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_UNEXPECTED_MM_EXTEND_ERR:
+- reason = "STATUS_UNEXPECTED_MM_EXTEND_ERR";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NOT_LOGON_PROCESS:
+- reason = "STATUS_NOT_LOGON_PROCESS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_LOGON_SESSION_EXISTS:
+- reason = "STATUS_LOGON_SESSION_EXISTS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_PARAMETER_1:
+- reason = "STATUS_INVALID_PARAMETER_1";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_PARAMETER_2:
+- reason = "STATUS_INVALID_PARAMETER_2";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_PARAMETER_3:
+- reason = "STATUS_INVALID_PARAMETER_3";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_PARAMETER_4:
+- reason = "STATUS_INVALID_PARAMETER_4";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_PARAMETER_5:
+- reason = "STATUS_INVALID_PARAMETER_5";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_PARAMETER_6:
+- reason = "STATUS_INVALID_PARAMETER_6";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_PARAMETER_7:
+- reason = "STATUS_INVALID_PARAMETER_7";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_PARAMETER_8:
+- reason = "STATUS_INVALID_PARAMETER_8";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_PARAMETER_9:
+- reason = "STATUS_INVALID_PARAMETER_9";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_PARAMETER_10:
+- reason = "STATUS_INVALID_PARAMETER_10";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_PARAMETER_11:
+- reason = "STATUS_INVALID_PARAMETER_11";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_PARAMETER_12:
+- reason = "STATUS_INVALID_PARAMETER_12";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_REDIRECTOR_NOT_STARTED:
+- reason = "STATUS_REDIRECTOR_NOT_STARTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_REDIRECTOR_STARTED:
+- reason = "STATUS_REDIRECTOR_STARTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_STACK_OVERFLOW:
+- reason = "STATUS_STACK_OVERFLOW";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NO_SUCH_PACKAGE:
+- reason = "STATUS_NO_SUCH_PACKAGE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_BAD_FUNCTION_TABLE:
+- reason = "STATUS_BAD_FUNCTION_TABLE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VARIABLE_NOT_FOUND:
+- reason = "STATUS_VARIABLE_NOT_FOUND";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DIRECTORY_NOT_EMPTY:
+- reason = "STATUS_DIRECTORY_NOT_EMPTY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FILE_CORRUPT_ERROR:
+- reason = "STATUS_FILE_CORRUPT_ERROR";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NOT_A_DIRECTORY:
+- reason = "STATUS_NOT_A_DIRECTORY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_BAD_LOGON_SESSION_STATE:
+- reason = "STATUS_BAD_LOGON_SESSION_STATE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_LOGON_SESSION_COLLISION:
+- reason = "STATUS_LOGON_SESSION_COLLISION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NAME_TOO_LONG:
+- reason = "STATUS_NAME_TOO_LONG";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FILES_OPEN:
+- reason = "STATUS_FILES_OPEN";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CONNECTION_IN_USE:
+- reason = "STATUS_CONNECTION_IN_USE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_MESSAGE_NOT_FOUND:
+- reason = "STATUS_MESSAGE_NOT_FOUND";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PROCESS_IS_TERMINATING:
+- reason = "STATUS_PROCESS_IS_TERMINATING";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_LOGON_TYPE:
+- reason = "STATUS_INVALID_LOGON_TYPE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NO_GUID_TRANSLATION:
+- reason = "STATUS_NO_GUID_TRANSLATION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CANNOT_IMPERSONATE:
+- reason = "STATUS_CANNOT_IMPERSONATE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_IMAGE_ALREADY_LOADED:
+- reason = "STATUS_IMAGE_ALREADY_LOADED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ABIOS_NOT_PRESENT:
+- reason = "STATUS_ABIOS_NOT_PRESENT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ABIOS_LID_NOT_EXIST:
+- reason = "STATUS_ABIOS_LID_NOT_EXIST";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ABIOS_LID_ALREADY_OWNED:
+- reason = "STATUS_ABIOS_LID_ALREADY_OWNED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ABIOS_NOT_LID_OWNER:
+- reason = "STATUS_ABIOS_NOT_LID_OWNER";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ABIOS_INVALID_COMMAND:
+- reason = "STATUS_ABIOS_INVALID_COMMAND";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ABIOS_INVALID_LID:
+- reason = "STATUS_ABIOS_INVALID_LID";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ABIOS_SELECTOR_NOT_AVAILABLE:
+- reason = "STATUS_ABIOS_SELECTOR_NOT_AVAILABLE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ABIOS_INVALID_SELECTOR:
+- reason = "STATUS_ABIOS_INVALID_SELECTOR";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NO_LDT:
+- reason = "STATUS_NO_LDT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_LDT_SIZE:
+- reason = "STATUS_INVALID_LDT_SIZE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_LDT_OFFSET:
+- reason = "STATUS_INVALID_LDT_OFFSET";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_LDT_DESCRIPTOR:
+- reason = "STATUS_INVALID_LDT_DESCRIPTOR";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_IMAGE_NE_FORMAT:
+- reason = "STATUS_INVALID_IMAGE_NE_FORMAT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_RXACT_INVALID_STATE:
+- reason = "STATUS_RXACT_INVALID_STATE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_RXACT_COMMIT_FAILURE:
+- reason = "STATUS_RXACT_COMMIT_FAILURE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_MAPPED_FILE_SIZE_ZERO:
+- reason = "STATUS_MAPPED_FILE_SIZE_ZERO";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TOO_MANY_OPENED_FILES:
+- reason = "STATUS_TOO_MANY_OPENED_FILES";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CANCELLED:
+- reason = "STATUS_CANCELLED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CANNOT_DELETE:
+- reason = "STATUS_CANNOT_DELETE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_COMPUTER_NAME:
+- reason = "STATUS_INVALID_COMPUTER_NAME";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FILE_DELETED:
+- reason = "STATUS_FILE_DELETED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SPECIAL_ACCOUNT:
+- reason = "STATUS_SPECIAL_ACCOUNT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SPECIAL_GROUP:
+- reason = "STATUS_SPECIAL_GROUP";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SPECIAL_USER:
+- reason = "STATUS_SPECIAL_USER";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_MEMBERS_PRIMARY_GROUP:
+- reason = "STATUS_MEMBERS_PRIMARY_GROUP";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FILE_CLOSED:
+- reason = "STATUS_FILE_CLOSED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TOO_MANY_THREADS:
+- reason = "STATUS_TOO_MANY_THREADS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_THREAD_NOT_IN_PROCESS:
+- reason = "STATUS_THREAD_NOT_IN_PROCESS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TOKEN_ALREADY_IN_USE:
+- reason = "STATUS_TOKEN_ALREADY_IN_USE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PAGEFILE_QUOTA_EXCEEDED:
+- reason = "STATUS_PAGEFILE_QUOTA_EXCEEDED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_COMMITMENT_LIMIT:
+- reason = "STATUS_COMMITMENT_LIMIT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_IMAGE_LE_FORMAT:
+- reason = "STATUS_INVALID_IMAGE_LE_FORMAT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_IMAGE_NOT_MZ:
+- reason = "STATUS_INVALID_IMAGE_NOT_MZ";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_IMAGE_PROTECT:
+- reason = "STATUS_INVALID_IMAGE_PROTECT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_IMAGE_WIN_16:
+- reason = "STATUS_INVALID_IMAGE_WIN_16";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_LOGON_SERVER_CONFLICT:
+- reason = "STATUS_LOGON_SERVER_CONFLICT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TIME_DIFFERENCE_AT_DC:
+- reason = "STATUS_TIME_DIFFERENCE_AT_DC";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SYNCHRONIZATION_REQUIRED:
+- reason = "STATUS_SYNCHRONIZATION_REQUIRED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DLL_NOT_FOUND:
+- reason = "STATUS_DLL_NOT_FOUND";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_OPEN_FAILED:
+- reason = "STATUS_OPEN_FAILED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_IO_PRIVILEGE_FAILED:
+- reason = "STATUS_IO_PRIVILEGE_FAILED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ORDINAL_NOT_FOUND:
+- reason = "STATUS_ORDINAL_NOT_FOUND";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ENTRYPOINT_NOT_FOUND:
+- reason = "STATUS_ENTRYPOINT_NOT_FOUND";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CONTROL_C_EXIT:
+- reason = "STATUS_CONTROL_C_EXIT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_LOCAL_DISCONNECT:
+- reason = "STATUS_LOCAL_DISCONNECT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_REMOTE_DISCONNECT:
+- reason = "STATUS_REMOTE_DISCONNECT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_REMOTE_RESOURCES:
+- reason = "STATUS_REMOTE_RESOURCES";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_LINK_FAILED:
+- reason = "STATUS_LINK_FAILED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_LINK_TIMEOUT:
+- reason = "STATUS_LINK_TIMEOUT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_CONNECTION:
+- reason = "STATUS_INVALID_CONNECTION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_ADDRESS:
+- reason = "STATUS_INVALID_ADDRESS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DLL_INIT_FAILED:
+- reason = "STATUS_DLL_INIT_FAILED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_MISSING_SYSTEMFILE:
+- reason = "STATUS_MISSING_SYSTEMFILE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_UNHANDLED_EXCEPTION:
+- reason = "STATUS_UNHANDLED_EXCEPTION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_APP_INIT_FAILURE:
+- reason = "STATUS_APP_INIT_FAILURE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PAGEFILE_CREATE_FAILED:
+- reason = "STATUS_PAGEFILE_CREATE_FAILED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NO_PAGEFILE:
+- reason = "STATUS_NO_PAGEFILE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_LEVEL:
+- reason = "STATUS_INVALID_LEVEL";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_WRONG_PASSWORD_CORE:
+- reason = "STATUS_WRONG_PASSWORD_CORE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ILLEGAL_FLOAT_CONTEXT:
+- reason = "STATUS_ILLEGAL_FLOAT_CONTEXT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PIPE_BROKEN:
+- reason = "STATUS_PIPE_BROKEN";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_REGISTRY_CORRUPT:
+- reason = "STATUS_REGISTRY_CORRUPT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_REGISTRY_IO_FAILED:
+- reason = "STATUS_REGISTRY_IO_FAILED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NO_EVENT_PAIR:
+- reason = "STATUS_NO_EVENT_PAIR";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_UNRECOGNIZED_VOLUME:
+- reason = "STATUS_UNRECOGNIZED_VOLUME";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SERIAL_NO_DEVICE_INITED:
+- reason = "STATUS_SERIAL_NO_DEVICE_INITED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NO_SUCH_ALIAS:
+- reason = "STATUS_NO_SUCH_ALIAS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_MEMBER_NOT_IN_ALIAS:
+- reason = "STATUS_MEMBER_NOT_IN_ALIAS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_MEMBER_IN_ALIAS:
+- reason = "STATUS_MEMBER_IN_ALIAS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ALIAS_EXISTS:
+- reason = "STATUS_ALIAS_EXISTS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_LOGON_NOT_GRANTED:
+- reason = "STATUS_LOGON_NOT_GRANTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TOO_MANY_SECRETS:
+- reason = "STATUS_TOO_MANY_SECRETS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SECRET_TOO_LONG:
+- reason = "STATUS_SECRET_TOO_LONG";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INTERNAL_DB_ERROR:
+- reason = "STATUS_INTERNAL_DB_ERROR";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FULLSCREEN_MODE:
+- reason = "STATUS_FULLSCREEN_MODE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TOO_MANY_CONTEXT_IDS:
+- reason = "STATUS_TOO_MANY_CONTEXT_IDS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_LOGON_TYPE_NOT_GRANTED:
+- reason = "STATUS_LOGON_TYPE_NOT_GRANTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NOT_REGISTRY_FILE:
+- reason = "STATUS_NOT_REGISTRY_FILE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NT_CROSS_ENCRYPTION_REQUIRED:
+- reason = "STATUS_NT_CROSS_ENCRYPTION_REQUIRED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DOMAIN_CTRLR_CONFIG_ERROR:
+- reason = "STATUS_DOMAIN_CTRLR_CONFIG_ERROR";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FT_MISSING_MEMBER:
+- reason = "STATUS_FT_MISSING_MEMBER";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ILL_FORMED_SERVICE_ENTRY:
+- reason = "STATUS_ILL_FORMED_SERVICE_ENTRY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ILLEGAL_CHARACTER:
+- reason = "STATUS_ILLEGAL_CHARACTER";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_UNMAPPABLE_CHARACTER:
+- reason = "STATUS_UNMAPPABLE_CHARACTER";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_UNDEFINED_CHARACTER:
+- reason = "STATUS_UNDEFINED_CHARACTER";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FLOPPY_VOLUME:
+- reason = "STATUS_FLOPPY_VOLUME";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FLOPPY_ID_MARK_NOT_FOUND:
+- reason = "STATUS_FLOPPY_ID_MARK_NOT_FOUND";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FLOPPY_WRONG_CYLINDER:
+- reason = "STATUS_FLOPPY_WRONG_CYLINDER";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FLOPPY_UNKNOWN_ERROR:
+- reason = "STATUS_FLOPPY_UNKNOWN_ERROR";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FLOPPY_BAD_REGISTERS:
+- reason = "STATUS_FLOPPY_BAD_REGISTERS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DISK_RECALIBRATE_FAILED:
+- reason = "STATUS_DISK_RECALIBRATE_FAILED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DISK_OPERATION_FAILED:
+- reason = "STATUS_DISK_OPERATION_FAILED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DISK_RESET_FAILED:
+- reason = "STATUS_DISK_RESET_FAILED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SHARED_IRQ_BUSY:
+- reason = "STATUS_SHARED_IRQ_BUSY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FT_ORPHANING:
+- reason = "STATUS_FT_ORPHANING";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_BIOS_FAILED_TO_CONNECT_INTERRUPT:
+- reason = "STATUS_BIOS_FAILED_TO_CONNECT_INTERRUPT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PARTITION_FAILURE:
+- reason = "STATUS_PARTITION_FAILURE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_BLOCK_LENGTH:
+- reason = "STATUS_INVALID_BLOCK_LENGTH";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DEVICE_NOT_PARTITIONED:
+- reason = "STATUS_DEVICE_NOT_PARTITIONED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_UNABLE_TO_LOCK_MEDIA:
+- reason = "STATUS_UNABLE_TO_LOCK_MEDIA";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_UNABLE_TO_UNLOAD_MEDIA:
+- reason = "STATUS_UNABLE_TO_UNLOAD_MEDIA";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_EOM_OVERFLOW:
+- reason = "STATUS_EOM_OVERFLOW";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NO_MEDIA:
+- reason = "STATUS_NO_MEDIA";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NO_SUCH_MEMBER:
+- reason = "STATUS_NO_SUCH_MEMBER";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_MEMBER:
+- reason = "STATUS_INVALID_MEMBER";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_KEY_DELETED:
+- reason = "STATUS_KEY_DELETED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NO_LOG_SPACE:
+- reason = "STATUS_NO_LOG_SPACE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TOO_MANY_SIDS:
+- reason = "STATUS_TOO_MANY_SIDS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_LM_CROSS_ENCRYPTION_REQUIRED:
+- reason = "STATUS_LM_CROSS_ENCRYPTION_REQUIRED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_KEY_HAS_CHILDREN:
+- reason = "STATUS_KEY_HAS_CHILDREN";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CHILD_MUST_BE_VOLATILE:
+- reason = "STATUS_CHILD_MUST_BE_VOLATILE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DEVICE_CONFIGURATION_ERROR:
+- reason = "STATUS_DEVICE_CONFIGURATION_ERROR";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DRIVER_INTERNAL_ERROR:
+- reason = "STATUS_DRIVER_INTERNAL_ERROR";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_DEVICE_STATE:
+- reason = "STATUS_INVALID_DEVICE_STATE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_IO_DEVICE_ERROR:
+- reason = "STATUS_IO_DEVICE_ERROR";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DEVICE_PROTOCOL_ERROR:
+- reason = "STATUS_DEVICE_PROTOCOL_ERROR";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_BACKUP_CONTROLLER:
+- reason = "STATUS_BACKUP_CONTROLLER";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_LOG_FILE_FULL:
+- reason = "STATUS_LOG_FILE_FULL";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TOO_LATE:
+- reason = "STATUS_TOO_LATE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NO_TRUST_LSA_SECRET:
+- reason = "STATUS_NO_TRUST_LSA_SECRET";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NO_TRUST_SAM_ACCOUNT:
+- reason = "STATUS_NO_TRUST_SAM_ACCOUNT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TRUSTED_DOMAIN_FAILURE:
+- reason = "STATUS_TRUSTED_DOMAIN_FAILURE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TRUSTED_RELATIONSHIP_FAILURE:
+- reason = "STATUS_TRUSTED_RELATIONSHIP_FAILURE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_EVENTLOG_FILE_CORRUPT:
+- reason = "STATUS_EVENTLOG_FILE_CORRUPT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_EVENTLOG_CANT_START:
+- reason = "STATUS_EVENTLOG_CANT_START";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TRUST_FAILURE:
+- reason = "STATUS_TRUST_FAILURE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_MUTANT_LIMIT_EXCEEDED:
+- reason = "STATUS_MUTANT_LIMIT_EXCEEDED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NETLOGON_NOT_STARTED:
+- reason = "STATUS_NETLOGON_NOT_STARTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ACCOUNT_EXPIRED:
+- reason = "STATUS_ACCOUNT_EXPIRED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_POSSIBLE_DEADLOCK:
+- reason = "STATUS_POSSIBLE_DEADLOCK";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NETWORK_CREDENTIAL_CONFLICT:
+- reason = "STATUS_NETWORK_CREDENTIAL_CONFLICT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_REMOTE_SESSION_LIMIT:
+- reason = "STATUS_REMOTE_SESSION_LIMIT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_EVENTLOG_FILE_CHANGED:
+- reason = "STATUS_EVENTLOG_FILE_CHANGED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT:
+- reason = "STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT:
+- reason = "STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT:
+- reason = "STATUS_NOLOGON_SERVER_TRUST_ACCOUNT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DOMAIN_TRUST_INCONSISTENT:
+- reason = "STATUS_DOMAIN_TRUST_INCONSISTENT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FS_DRIVER_REQUIRED:
+- reason = "STATUS_FS_DRIVER_REQUIRED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_IMAGE_ALREADY_LOADED_AS_DLL:
+- reason = "STATUS_IMAGE_ALREADY_LOADED_AS_DLL";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INCOMPATIBLE_WITH_GLOBAL_SHORT_NAME_REGISTRY_SETTING:
+- reason = "STATUS_INCOMPATIBLE_WITH_GLOBAL_SHORT_NAME_REGISTRY_SETTING";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SHORT_NAMES_NOT_ENABLED_ON_VOLUME:
+- reason = "STATUS_SHORT_NAMES_NOT_ENABLED_ON_VOLUME";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SECURITY_STREAM_IS_INCONSISTENT:
+- reason = "STATUS_SECURITY_STREAM_IS_INCONSISTENT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_LOCK_RANGE:
+- reason = "STATUS_INVALID_LOCK_RANGE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_ACE_CONDITION:
+- reason = "STATUS_INVALID_ACE_CONDITION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_IMAGE_SUBSYSTEM_NOT_PRESENT:
+- reason = "STATUS_IMAGE_SUBSYSTEM_NOT_PRESENT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NOTIFICATION_GUID_ALREADY_DEFINED:
+- reason = "STATUS_NOTIFICATION_GUID_ALREADY_DEFINED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_EXCEPTION_HANDLER:
+- reason = "STATUS_INVALID_EXCEPTION_HANDLER";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DUPLICATE_PRIVILEGES:
+- reason = "STATUS_DUPLICATE_PRIVILEGES";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NOT_ALLOWED_ON_SYSTEM_FILE:
+- reason = "STATUS_NOT_ALLOWED_ON_SYSTEM_FILE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_REPAIR_NEEDED:
+- reason = "STATUS_REPAIR_NEEDED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_QUOTA_NOT_ENABLED:
+- reason = "STATUS_QUOTA_NOT_ENABLED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NO_APPLICATION_PACKAGE:
+- reason = "STATUS_NO_APPLICATION_PACKAGE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FILE_METADATA_OPTIMIZATION_IN_PROGRESS:
+- reason = "STATUS_FILE_METADATA_OPTIMIZATION_IN_PROGRESS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NOT_SAME_OBJECT:
+- reason = "STATUS_NOT_SAME_OBJECT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FATAL_MEMORY_EXHAUSTION:
+- reason = "STATUS_FATAL_MEMORY_EXHAUSTION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ERROR_PROCESS_NOT_IN_JOB:
+- reason = "STATUS_ERROR_PROCESS_NOT_IN_JOB";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CPU_SET_INVALID:
+- reason = "STATUS_CPU_SET_INVALID";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_IO_DEVICE_INVALID_DATA:
+- reason = "STATUS_IO_DEVICE_INVALID_DATA";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_IO_UNALIGNED_WRITE:
+- reason = "STATUS_IO_UNALIGNED_WRITE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CONTROL_STACK_VIOLATION:
+- reason = "STATUS_CONTROL_STACK_VIOLATION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NETWORK_OPEN_RESTRICTION:
+- reason = "STATUS_NETWORK_OPEN_RESTRICTION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NO_USER_SESSION_KEY:
+- reason = "STATUS_NO_USER_SESSION_KEY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_USER_SESSION_DELETED:
+- reason = "STATUS_USER_SESSION_DELETED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_RESOURCE_LANG_NOT_FOUND:
+- reason = "STATUS_RESOURCE_LANG_NOT_FOUND";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INSUFF_SERVER_RESOURCES:
+- reason = "STATUS_INSUFF_SERVER_RESOURCES";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_BUFFER_SIZE:
+- reason = "STATUS_INVALID_BUFFER_SIZE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_ADDRESS_COMPONENT:
+- reason = "STATUS_INVALID_ADDRESS_COMPONENT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_ADDRESS_WILDCARD:
+- reason = "STATUS_INVALID_ADDRESS_WILDCARD";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TOO_MANY_ADDRESSES:
+- reason = "STATUS_TOO_MANY_ADDRESSES";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ADDRESS_ALREADY_EXISTS:
+- reason = "STATUS_ADDRESS_ALREADY_EXISTS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ADDRESS_CLOSED:
+- reason = "STATUS_ADDRESS_CLOSED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CONNECTION_DISCONNECTED:
+- reason = "STATUS_CONNECTION_DISCONNECTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CONNECTION_RESET:
+- reason = "STATUS_CONNECTION_RESET";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TOO_MANY_NODES:
+- reason = "STATUS_TOO_MANY_NODES";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TRANSACTION_ABORTED:
+- reason = "STATUS_TRANSACTION_ABORTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TRANSACTION_TIMED_OUT:
+- reason = "STATUS_TRANSACTION_TIMED_OUT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TRANSACTION_NO_RELEASE:
+- reason = "STATUS_TRANSACTION_NO_RELEASE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TRANSACTION_NO_MATCH:
+- reason = "STATUS_TRANSACTION_NO_MATCH";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TRANSACTION_RESPONDED:
+- reason = "STATUS_TRANSACTION_RESPONDED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TRANSACTION_INVALID_ID:
+- reason = "STATUS_TRANSACTION_INVALID_ID";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TRANSACTION_INVALID_TYPE:
+- reason = "STATUS_TRANSACTION_INVALID_TYPE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NOT_SERVER_SESSION:
+- reason = "STATUS_NOT_SERVER_SESSION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NOT_CLIENT_SESSION:
+- reason = "STATUS_NOT_CLIENT_SESSION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CANNOT_LOAD_REGISTRY_FILE:
+- reason = "STATUS_CANNOT_LOAD_REGISTRY_FILE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DEBUG_ATTACH_FAILED:
+- reason = "STATUS_DEBUG_ATTACH_FAILED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SYSTEM_PROCESS_TERMINATED:
+- reason = "STATUS_SYSTEM_PROCESS_TERMINATED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DATA_NOT_ACCEPTED:
+- reason = "STATUS_DATA_NOT_ACCEPTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NO_BROWSER_SERVERS_FOUND:
+- reason = "STATUS_NO_BROWSER_SERVERS_FOUND";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VDM_HARD_ERROR:
+- reason = "STATUS_VDM_HARD_ERROR";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DRIVER_CANCEL_TIMEOUT:
+- reason = "STATUS_DRIVER_CANCEL_TIMEOUT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_REPLY_MESSAGE_MISMATCH:
+- reason = "STATUS_REPLY_MESSAGE_MISMATCH";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_MAPPED_ALIGNMENT:
+- reason = "STATUS_MAPPED_ALIGNMENT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_IMAGE_CHECKSUM_MISMATCH:
+- reason = "STATUS_IMAGE_CHECKSUM_MISMATCH";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_LOST_WRITEBEHIND_DATA:
+- reason = "STATUS_LOST_WRITEBEHIND_DATA";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CLIENT_SERVER_PARAMETERS_INVALID:
+- reason = "STATUS_CLIENT_SERVER_PARAMETERS_INVALID";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PASSWORD_MUST_CHANGE:
+- reason = "STATUS_PASSWORD_MUST_CHANGE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NOT_FOUND:
+- reason = "STATUS_NOT_FOUND";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NOT_TINY_STREAM:
+- reason = "STATUS_NOT_TINY_STREAM";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_RECOVERY_FAILURE:
+- reason = "STATUS_RECOVERY_FAILURE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_STACK_OVERFLOW_READ:
+- reason = "STATUS_STACK_OVERFLOW_READ";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FAIL_CHECK:
+- reason = "STATUS_FAIL_CHECK";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DUPLICATE_OBJECTID:
+- reason = "STATUS_DUPLICATE_OBJECTID";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_OBJECTID_EXISTS:
+- reason = "STATUS_OBJECTID_EXISTS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CONVERT_TO_LARGE:
+- reason = "STATUS_CONVERT_TO_LARGE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_RETRY:
+- reason = "STATUS_RETRY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FOUND_OUT_OF_SCOPE:
+- reason = "STATUS_FOUND_OUT_OF_SCOPE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ALLOCATE_BUCKET:
+- reason = "STATUS_ALLOCATE_BUCKET";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PROPSET_NOT_FOUND:
+- reason = "STATUS_PROPSET_NOT_FOUND";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_MARSHALL_OVERFLOW:
+- reason = "STATUS_MARSHALL_OVERFLOW";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_VARIANT:
+- reason = "STATUS_INVALID_VARIANT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DOMAIN_CONTROLLER_NOT_FOUND:
+- reason = "STATUS_DOMAIN_CONTROLLER_NOT_FOUND";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ACCOUNT_LOCKED_OUT:
+- reason = "STATUS_ACCOUNT_LOCKED_OUT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_HANDLE_NOT_CLOSABLE:
+- reason = "STATUS_HANDLE_NOT_CLOSABLE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CONNECTION_REFUSED:
+- reason = "STATUS_CONNECTION_REFUSED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRACEFUL_DISCONNECT:
+- reason = "STATUS_GRACEFUL_DISCONNECT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ADDRESS_ALREADY_ASSOCIATED:
+- reason = "STATUS_ADDRESS_ALREADY_ASSOCIATED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ADDRESS_NOT_ASSOCIATED:
+- reason = "STATUS_ADDRESS_NOT_ASSOCIATED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CONNECTION_INVALID:
+- reason = "STATUS_CONNECTION_INVALID";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CONNECTION_ACTIVE:
+- reason = "STATUS_CONNECTION_ACTIVE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NETWORK_UNREACHABLE:
+- reason = "STATUS_NETWORK_UNREACHABLE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_HOST_UNREACHABLE:
+- reason = "STATUS_HOST_UNREACHABLE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PROTOCOL_UNREACHABLE:
+- reason = "STATUS_PROTOCOL_UNREACHABLE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PORT_UNREACHABLE:
+- reason = "STATUS_PORT_UNREACHABLE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_REQUEST_ABORTED:
+- reason = "STATUS_REQUEST_ABORTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CONNECTION_ABORTED:
+- reason = "STATUS_CONNECTION_ABORTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_BAD_COMPRESSION_BUFFER:
+- reason = "STATUS_BAD_COMPRESSION_BUFFER";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_USER_MAPPED_FILE:
+- reason = "STATUS_USER_MAPPED_FILE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_AUDIT_FAILED:
+- reason = "STATUS_AUDIT_FAILED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TIMER_RESOLUTION_NOT_SET:
+- reason = "STATUS_TIMER_RESOLUTION_NOT_SET";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CONNECTION_COUNT_LIMIT:
+- reason = "STATUS_CONNECTION_COUNT_LIMIT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_LOGIN_TIME_RESTRICTION:
+- reason = "STATUS_LOGIN_TIME_RESTRICTION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_LOGIN_WKSTA_RESTRICTION:
+- reason = "STATUS_LOGIN_WKSTA_RESTRICTION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_IMAGE_MP_UP_MISMATCH:
+- reason = "STATUS_IMAGE_MP_UP_MISMATCH";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INSUFFICIENT_LOGON_INFO:
+- reason = "STATUS_INSUFFICIENT_LOGON_INFO";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_BAD_DLL_ENTRYPOINT:
+- reason = "STATUS_BAD_DLL_ENTRYPOINT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_BAD_SERVICE_ENTRYPOINT:
+- reason = "STATUS_BAD_SERVICE_ENTRYPOINT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_LPC_REPLY_LOST:
+- reason = "STATUS_LPC_REPLY_LOST";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_IP_ADDRESS_CONFLICT1:
+- reason = "STATUS_IP_ADDRESS_CONFLICT1";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_IP_ADDRESS_CONFLICT2:
+- reason = "STATUS_IP_ADDRESS_CONFLICT2";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_REGISTRY_QUOTA_LIMIT:
+- reason = "STATUS_REGISTRY_QUOTA_LIMIT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PATH_NOT_COVERED:
+- reason = "STATUS_PATH_NOT_COVERED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NO_CALLBACK_ACTIVE:
+- reason = "STATUS_NO_CALLBACK_ACTIVE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_LICENSE_QUOTA_EXCEEDED:
+- reason = "STATUS_LICENSE_QUOTA_EXCEEDED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PWD_TOO_SHORT:
+- reason = "STATUS_PWD_TOO_SHORT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PWD_TOO_RECENT:
+- reason = "STATUS_PWD_TOO_RECENT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PWD_HISTORY_CONFLICT:
+- reason = "STATUS_PWD_HISTORY_CONFLICT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PLUGPLAY_NO_DEVICE:
+- reason = "STATUS_PLUGPLAY_NO_DEVICE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_UNSUPPORTED_COMPRESSION:
+- reason = "STATUS_UNSUPPORTED_COMPRESSION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_HW_PROFILE:
+- reason = "STATUS_INVALID_HW_PROFILE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_PLUGPLAY_DEVICE_PATH:
+- reason = "STATUS_INVALID_PLUGPLAY_DEVICE_PATH";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DRIVER_ORDINAL_NOT_FOUND:
+- reason = "STATUS_DRIVER_ORDINAL_NOT_FOUND";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DRIVER_ENTRYPOINT_NOT_FOUND:
+- reason = "STATUS_DRIVER_ENTRYPOINT_NOT_FOUND";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_RESOURCE_NOT_OWNED:
+- reason = "STATUS_RESOURCE_NOT_OWNED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TOO_MANY_LINKS:
+- reason = "STATUS_TOO_MANY_LINKS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_QUOTA_LIST_INCONSISTENT:
+- reason = "STATUS_QUOTA_LIST_INCONSISTENT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FILE_IS_OFFLINE:
+- reason = "STATUS_FILE_IS_OFFLINE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_EVALUATION_EXPIRATION:
+- reason = "STATUS_EVALUATION_EXPIRATION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ILLEGAL_DLL_RELOCATION:
+- reason = "STATUS_ILLEGAL_DLL_RELOCATION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_LICENSE_VIOLATION:
+- reason = "STATUS_LICENSE_VIOLATION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DLL_INIT_FAILED_LOGOFF:
+- reason = "STATUS_DLL_INIT_FAILED_LOGOFF";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DRIVER_UNABLE_TO_LOAD:
+- reason = "STATUS_DRIVER_UNABLE_TO_LOAD";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DFS_UNAVAILABLE:
+- reason = "STATUS_DFS_UNAVAILABLE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLUME_DISMOUNTED:
+- reason = "STATUS_VOLUME_DISMOUNTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_WX86_INTERNAL_ERROR:
+- reason = "STATUS_WX86_INTERNAL_ERROR";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_WX86_FLOAT_STACK_CHECK:
+- reason = "STATUS_WX86_FLOAT_STACK_CHECK";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VALIDATE_CONTINUE:
+- reason = "STATUS_VALIDATE_CONTINUE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NO_MATCH:
+- reason = "STATUS_NO_MATCH";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NO_MORE_MATCHES:
+- reason = "STATUS_NO_MORE_MATCHES";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NOT_A_REPARSE_POINT:
+- reason = "STATUS_NOT_A_REPARSE_POINT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_IO_REPARSE_TAG_INVALID:
+- reason = "STATUS_IO_REPARSE_TAG_INVALID";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_IO_REPARSE_TAG_MISMATCH:
+- reason = "STATUS_IO_REPARSE_TAG_MISMATCH";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_IO_REPARSE_DATA_INVALID:
+- reason = "STATUS_IO_REPARSE_DATA_INVALID";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_IO_REPARSE_TAG_NOT_HANDLED:
+- reason = "STATUS_IO_REPARSE_TAG_NOT_HANDLED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PWD_TOO_LONG:
+- reason = "STATUS_PWD_TOO_LONG";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_STOWED_EXCEPTION:
+- reason = "STATUS_STOWED_EXCEPTION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CONTEXT_STOWED_EXCEPTION:
+- reason = "STATUS_CONTEXT_STOWED_EXCEPTION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_REPARSE_POINT_NOT_RESOLVED:
+- reason = "STATUS_REPARSE_POINT_NOT_RESOLVED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DIRECTORY_IS_A_REPARSE_POINT:
+- reason = "STATUS_DIRECTORY_IS_A_REPARSE_POINT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_RANGE_LIST_CONFLICT:
+- reason = "STATUS_RANGE_LIST_CONFLICT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SOURCE_ELEMENT_EMPTY:
+- reason = "STATUS_SOURCE_ELEMENT_EMPTY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DESTINATION_ELEMENT_FULL:
+- reason = "STATUS_DESTINATION_ELEMENT_FULL";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ILLEGAL_ELEMENT_ADDRESS:
+- reason = "STATUS_ILLEGAL_ELEMENT_ADDRESS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_MAGAZINE_NOT_PRESENT:
+- reason = "STATUS_MAGAZINE_NOT_PRESENT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_REINITIALIZATION_NEEDED:
+- reason = "STATUS_REINITIALIZATION_NEEDED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ENCRYPTION_FAILED:
+- reason = "STATUS_ENCRYPTION_FAILED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DECRYPTION_FAILED:
+- reason = "STATUS_DECRYPTION_FAILED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_RANGE_NOT_FOUND:
+- reason = "STATUS_RANGE_NOT_FOUND";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NO_RECOVERY_POLICY:
+- reason = "STATUS_NO_RECOVERY_POLICY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NO_EFS:
+- reason = "STATUS_NO_EFS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_WRONG_EFS:
+- reason = "STATUS_WRONG_EFS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NO_USER_KEYS:
+- reason = "STATUS_NO_USER_KEYS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FILE_NOT_ENCRYPTED:
+- reason = "STATUS_FILE_NOT_ENCRYPTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NOT_EXPORT_FORMAT:
+- reason = "STATUS_NOT_EXPORT_FORMAT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FILE_ENCRYPTED:
+- reason = "STATUS_FILE_ENCRYPTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_WMI_GUID_NOT_FOUND:
+- reason = "STATUS_WMI_GUID_NOT_FOUND";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_WMI_INSTANCE_NOT_FOUND:
+- reason = "STATUS_WMI_INSTANCE_NOT_FOUND";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_WMI_ITEMID_NOT_FOUND:
+- reason = "STATUS_WMI_ITEMID_NOT_FOUND";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_WMI_TRY_AGAIN:
+- reason = "STATUS_WMI_TRY_AGAIN";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SHARED_POLICY:
+- reason = "STATUS_SHARED_POLICY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_POLICY_OBJECT_NOT_FOUND:
+- reason = "STATUS_POLICY_OBJECT_NOT_FOUND";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_POLICY_ONLY_IN_DS:
+- reason = "STATUS_POLICY_ONLY_IN_DS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLUME_NOT_UPGRADED:
+- reason = "STATUS_VOLUME_NOT_UPGRADED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_REMOTE_STORAGE_NOT_ACTIVE:
+- reason = "STATUS_REMOTE_STORAGE_NOT_ACTIVE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_REMOTE_STORAGE_MEDIA_ERROR:
+- reason = "STATUS_REMOTE_STORAGE_MEDIA_ERROR";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NO_TRACKING_SERVICE:
+- reason = "STATUS_NO_TRACKING_SERVICE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SERVER_SID_MISMATCH:
+- reason = "STATUS_SERVER_SID_MISMATCH";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DS_NO_ATTRIBUTE_OR_VALUE:
+- reason = "STATUS_DS_NO_ATTRIBUTE_OR_VALUE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DS_INVALID_ATTRIBUTE_SYNTAX:
+- reason = "STATUS_DS_INVALID_ATTRIBUTE_SYNTAX";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DS_ATTRIBUTE_TYPE_UNDEFINED:
+- reason = "STATUS_DS_ATTRIBUTE_TYPE_UNDEFINED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DS_ATTRIBUTE_OR_VALUE_EXISTS:
+- reason = "STATUS_DS_ATTRIBUTE_OR_VALUE_EXISTS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DS_BUSY:
+- reason = "STATUS_DS_BUSY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DS_UNAVAILABLE:
+- reason = "STATUS_DS_UNAVAILABLE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DS_NO_RIDS_ALLOCATED:
+- reason = "STATUS_DS_NO_RIDS_ALLOCATED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DS_NO_MORE_RIDS:
+- reason = "STATUS_DS_NO_MORE_RIDS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DS_INCORRECT_ROLE_OWNER:
+- reason = "STATUS_DS_INCORRECT_ROLE_OWNER";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DS_RIDMGR_INIT_ERROR:
+- reason = "STATUS_DS_RIDMGR_INIT_ERROR";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DS_OBJ_CLASS_VIOLATION:
+- reason = "STATUS_DS_OBJ_CLASS_VIOLATION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DS_CANT_ON_NON_LEAF:
+- reason = "STATUS_DS_CANT_ON_NON_LEAF";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DS_CANT_ON_RDN:
+- reason = "STATUS_DS_CANT_ON_RDN";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DS_CANT_MOD_OBJ_CLASS:
+- reason = "STATUS_DS_CANT_MOD_OBJ_CLASS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DS_CROSS_DOM_MOVE_FAILED:
+- reason = "STATUS_DS_CROSS_DOM_MOVE_FAILED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DS_GC_NOT_AVAILABLE:
+- reason = "STATUS_DS_GC_NOT_AVAILABLE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DIRECTORY_SERVICE_REQUIRED:
+- reason = "STATUS_DIRECTORY_SERVICE_REQUIRED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_REPARSE_ATTRIBUTE_CONFLICT:
+- reason = "STATUS_REPARSE_ATTRIBUTE_CONFLICT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CANT_ENABLE_DENY_ONLY:
+- reason = "STATUS_CANT_ENABLE_DENY_ONLY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FLOAT_MULTIPLE_FAULTS:
+- reason = "STATUS_FLOAT_MULTIPLE_FAULTS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FLOAT_MULTIPLE_TRAPS:
+- reason = "STATUS_FLOAT_MULTIPLE_TRAPS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DEVICE_REMOVED:
+- reason = "STATUS_DEVICE_REMOVED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_JOURNAL_DELETE_IN_PROGRESS:
+- reason = "STATUS_JOURNAL_DELETE_IN_PROGRESS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_JOURNAL_NOT_ACTIVE:
+- reason = "STATUS_JOURNAL_NOT_ACTIVE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NOINTERFACE:
+- reason = "STATUS_NOINTERFACE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DS_RIDMGR_DISABLED:
+- reason = "STATUS_DS_RIDMGR_DISABLED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DS_ADMIN_LIMIT_EXCEEDED:
+- reason = "STATUS_DS_ADMIN_LIMIT_EXCEEDED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DRIVER_FAILED_SLEEP:
+- reason = "STATUS_DRIVER_FAILED_SLEEP";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_MUTUAL_AUTHENTICATION_FAILED:
+- reason = "STATUS_MUTUAL_AUTHENTICATION_FAILED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CORRUPT_SYSTEM_FILE:
+- reason = "STATUS_CORRUPT_SYSTEM_FILE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DATATYPE_MISALIGNMENT_ERROR:
+- reason = "STATUS_DATATYPE_MISALIGNMENT_ERROR";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_WMI_READ_ONLY:
+- reason = "STATUS_WMI_READ_ONLY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_WMI_SET_FAILURE:
+- reason = "STATUS_WMI_SET_FAILURE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_COMMITMENT_MINIMUM:
+- reason = "STATUS_COMMITMENT_MINIMUM";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_REG_NAT_CONSUMPTION:
+- reason = "STATUS_REG_NAT_CONSUMPTION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TRANSPORT_FULL:
+- reason = "STATUS_TRANSPORT_FULL";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DS_SAM_INIT_FAILURE:
+- reason = "STATUS_DS_SAM_INIT_FAILURE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ONLY_IF_CONNECTED:
+- reason = "STATUS_ONLY_IF_CONNECTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DS_SENSITIVE_GROUP_VIOLATION:
+- reason = "STATUS_DS_SENSITIVE_GROUP_VIOLATION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PNP_RESTART_ENUMERATION:
+- reason = "STATUS_PNP_RESTART_ENUMERATION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_JOURNAL_ENTRY_DELETED:
+- reason = "STATUS_JOURNAL_ENTRY_DELETED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DS_CANT_MOD_PRIMARYGROUPID:
+- reason = "STATUS_DS_CANT_MOD_PRIMARYGROUPID";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SYSTEM_IMAGE_BAD_SIGNATURE:
+- reason = "STATUS_SYSTEM_IMAGE_BAD_SIGNATURE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PNP_REBOOT_REQUIRED:
+- reason = "STATUS_PNP_REBOOT_REQUIRED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_POWER_STATE_INVALID:
+- reason = "STATUS_POWER_STATE_INVALID";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DS_INVALID_GROUP_TYPE:
+- reason = "STATUS_DS_INVALID_GROUP_TYPE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DS_NO_NEST_GLOBALGROUP_IN_MIXEDDOMAIN:
+- reason = "STATUS_DS_NO_NEST_GLOBALGROUP_IN_MIXEDDOMAIN";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DS_NO_NEST_LOCALGROUP_IN_MIXEDDOMAIN:
+- reason = "STATUS_DS_NO_NEST_LOCALGROUP_IN_MIXEDDOMAIN";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DS_GLOBAL_CANT_HAVE_LOCAL_MEMBER:
+- reason = "STATUS_DS_GLOBAL_CANT_HAVE_LOCAL_MEMBER";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DS_GLOBAL_CANT_HAVE_UNIVERSAL_MEMBER:
+- reason = "STATUS_DS_GLOBAL_CANT_HAVE_UNIVERSAL_MEMBER";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DS_UNIVERSAL_CANT_HAVE_LOCAL_MEMBER:
+- reason = "STATUS_DS_UNIVERSAL_CANT_HAVE_LOCAL_MEMBER";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DS_GLOBAL_CANT_HAVE_CROSSDOMAIN_MEMBER:
+- reason = "STATUS_DS_GLOBAL_CANT_HAVE_CROSSDOMAIN_MEMBER";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DS_LOCAL_CANT_HAVE_CROSSDOMAIN_LOCAL_MEMBER:
+- reason = "STATUS_DS_LOCAL_CANT_HAVE_CROSSDOMAIN_LOCAL_MEMBER";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DS_HAVE_PRIMARY_MEMBERS:
+- reason = "STATUS_DS_HAVE_PRIMARY_MEMBERS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_WMI_NOT_SUPPORTED:
+- reason = "STATUS_WMI_NOT_SUPPORTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INSUFFICIENT_POWER:
+- reason = "STATUS_INSUFFICIENT_POWER";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SAM_NEED_BOOTKEY_PASSWORD:
+- reason = "STATUS_SAM_NEED_BOOTKEY_PASSWORD";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SAM_NEED_BOOTKEY_FLOPPY:
+- reason = "STATUS_SAM_NEED_BOOTKEY_FLOPPY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DS_CANT_START:
+- reason = "STATUS_DS_CANT_START";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DS_INIT_FAILURE:
+- reason = "STATUS_DS_INIT_FAILURE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SAM_INIT_FAILURE:
+- reason = "STATUS_SAM_INIT_FAILURE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DS_GC_REQUIRED:
+- reason = "STATUS_DS_GC_REQUIRED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DS_LOCAL_MEMBER_OF_LOCAL_ONLY:
+- reason = "STATUS_DS_LOCAL_MEMBER_OF_LOCAL_ONLY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DS_NO_FPO_IN_UNIVERSAL_GROUPS:
+- reason = "STATUS_DS_NO_FPO_IN_UNIVERSAL_GROUPS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DS_MACHINE_ACCOUNT_QUOTA_EXCEEDED:
+- reason = "STATUS_DS_MACHINE_ACCOUNT_QUOTA_EXCEEDED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_MULTIPLE_FAULT_VIOLATION:
+- reason = "STATUS_MULTIPLE_FAULT_VIOLATION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CURRENT_DOMAIN_NOT_ALLOWED:
+- reason = "STATUS_CURRENT_DOMAIN_NOT_ALLOWED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CANNOT_MAKE:
+- reason = "STATUS_CANNOT_MAKE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SYSTEM_SHUTDOWN:
+- reason = "STATUS_SYSTEM_SHUTDOWN";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DS_INIT_FAILURE_CONSOLE:
+- reason = "STATUS_DS_INIT_FAILURE_CONSOLE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DS_SAM_INIT_FAILURE_CONSOLE:
+- reason = "STATUS_DS_SAM_INIT_FAILURE_CONSOLE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_UNFINISHED_CONTEXT_DELETED:
+- reason = "STATUS_UNFINISHED_CONTEXT_DELETED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NO_TGT_REPLY:
+- reason = "STATUS_NO_TGT_REPLY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_OBJECTID_NOT_FOUND:
+- reason = "STATUS_OBJECTID_NOT_FOUND";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NO_IP_ADDRESSES:
+- reason = "STATUS_NO_IP_ADDRESSES";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_WRONG_CREDENTIAL_HANDLE:
+- reason = "STATUS_WRONG_CREDENTIAL_HANDLE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CRYPTO_SYSTEM_INVALID:
+- reason = "STATUS_CRYPTO_SYSTEM_INVALID";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_MAX_REFERRALS_EXCEEDED:
+- reason = "STATUS_MAX_REFERRALS_EXCEEDED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_MUST_BE_KDC:
+- reason = "STATUS_MUST_BE_KDC";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_STRONG_CRYPTO_NOT_SUPPORTED:
+- reason = "STATUS_STRONG_CRYPTO_NOT_SUPPORTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TOO_MANY_PRINCIPALS:
+- reason = "STATUS_TOO_MANY_PRINCIPALS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NO_PA_DATA:
+- reason = "STATUS_NO_PA_DATA";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PKINIT_NAME_MISMATCH:
+- reason = "STATUS_PKINIT_NAME_MISMATCH";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SMARTCARD_LOGON_REQUIRED:
+- reason = "STATUS_SMARTCARD_LOGON_REQUIRED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_KDC_INVALID_REQUEST:
+- reason = "STATUS_KDC_INVALID_REQUEST";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_KDC_UNABLE_TO_REFER:
+- reason = "STATUS_KDC_UNABLE_TO_REFER";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_KDC_UNKNOWN_ETYPE:
+- reason = "STATUS_KDC_UNKNOWN_ETYPE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SHUTDOWN_IN_PROGRESS:
+- reason = "STATUS_SHUTDOWN_IN_PROGRESS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SERVER_SHUTDOWN_IN_PROGRESS:
+- reason = "STATUS_SERVER_SHUTDOWN_IN_PROGRESS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NOT_SUPPORTED_ON_SBS:
+- reason = "STATUS_NOT_SUPPORTED_ON_SBS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_WMI_GUID_DISCONNECTED:
+- reason = "STATUS_WMI_GUID_DISCONNECTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_WMI_ALREADY_DISABLED:
+- reason = "STATUS_WMI_ALREADY_DISABLED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_WMI_ALREADY_ENABLED:
+- reason = "STATUS_WMI_ALREADY_ENABLED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_MFT_TOO_FRAGMENTED:
+- reason = "STATUS_MFT_TOO_FRAGMENTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_COPY_PROTECTION_FAILURE:
+- reason = "STATUS_COPY_PROTECTION_FAILURE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CSS_AUTHENTICATION_FAILURE:
+- reason = "STATUS_CSS_AUTHENTICATION_FAILURE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CSS_KEY_NOT_PRESENT:
+- reason = "STATUS_CSS_KEY_NOT_PRESENT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CSS_KEY_NOT_ESTABLISHED:
+- reason = "STATUS_CSS_KEY_NOT_ESTABLISHED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CSS_SCRAMBLED_SECTOR:
+- reason = "STATUS_CSS_SCRAMBLED_SECTOR";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CSS_REGION_MISMATCH:
+- reason = "STATUS_CSS_REGION_MISMATCH";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CSS_RESETS_EXHAUSTED:
+- reason = "STATUS_CSS_RESETS_EXHAUSTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PASSWORD_CHANGE_REQUIRED:
+- reason = "STATUS_PASSWORD_CHANGE_REQUIRED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_LOST_MODE_LOGON_RESTRICTION:
+- reason = "STATUS_LOST_MODE_LOGON_RESTRICTION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PKINIT_FAILURE:
+- reason = "STATUS_PKINIT_FAILURE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SMARTCARD_SUBSYSTEM_FAILURE:
+- reason = "STATUS_SMARTCARD_SUBSYSTEM_FAILURE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NO_KERB_KEY:
+- reason = "STATUS_NO_KERB_KEY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_HOST_DOWN:
+- reason = "STATUS_HOST_DOWN";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_UNSUPPORTED_PREAUTH:
+- reason = "STATUS_UNSUPPORTED_PREAUTH";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_EFS_ALG_BLOB_TOO_BIG:
+- reason = "STATUS_EFS_ALG_BLOB_TOO_BIG";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PORT_NOT_SET:
+- reason = "STATUS_PORT_NOT_SET";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DEBUGGER_INACTIVE:
+- reason = "STATUS_DEBUGGER_INACTIVE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DS_VERSION_CHECK_FAILURE:
+- reason = "STATUS_DS_VERSION_CHECK_FAILURE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_AUDITING_DISABLED:
+- reason = "STATUS_AUDITING_DISABLED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PRENT4_MACHINE_ACCOUNT:
+- reason = "STATUS_PRENT4_MACHINE_ACCOUNT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DS_AG_CANT_HAVE_UNIVERSAL_MEMBER:
+- reason = "STATUS_DS_AG_CANT_HAVE_UNIVERSAL_MEMBER";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_IMAGE_WIN_32:
+- reason = "STATUS_INVALID_IMAGE_WIN_32";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_IMAGE_WIN_64:
+- reason = "STATUS_INVALID_IMAGE_WIN_64";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_BAD_BINDINGS:
+- reason = "STATUS_BAD_BINDINGS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NETWORK_SESSION_EXPIRED:
+- reason = "STATUS_NETWORK_SESSION_EXPIRED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_APPHELP_BLOCK:
+- reason = "STATUS_APPHELP_BLOCK";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ALL_SIDS_FILTERED:
+- reason = "STATUS_ALL_SIDS_FILTERED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NOT_SAFE_MODE_DRIVER:
+- reason = "STATUS_NOT_SAFE_MODE_DRIVER";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ACCESS_DISABLED_BY_POLICY_DEFAULT:
+- reason = "STATUS_ACCESS_DISABLED_BY_POLICY_DEFAULT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ACCESS_DISABLED_BY_POLICY_PATH:
+- reason = "STATUS_ACCESS_DISABLED_BY_POLICY_PATH";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ACCESS_DISABLED_BY_POLICY_PUBLISHER:
+- reason = "STATUS_ACCESS_DISABLED_BY_POLICY_PUBLISHER";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER:
+- reason = "STATUS_ACCESS_DISABLED_BY_POLICY_OTHER";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FAILED_DRIVER_ENTRY:
+- reason = "STATUS_FAILED_DRIVER_ENTRY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DEVICE_ENUMERATION_ERROR:
+- reason = "STATUS_DEVICE_ENUMERATION_ERROR";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_MOUNT_POINT_NOT_RESOLVED:
+- reason = "STATUS_MOUNT_POINT_NOT_RESOLVED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_DEVICE_OBJECT_PARAMETER:
+- reason = "STATUS_INVALID_DEVICE_OBJECT_PARAMETER";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_MCA_OCCURED:
+- reason = "STATUS_MCA_OCCURED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DRIVER_BLOCKED_CRITICAL:
+- reason = "STATUS_DRIVER_BLOCKED_CRITICAL";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DRIVER_BLOCKED:
+- reason = "STATUS_DRIVER_BLOCKED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DRIVER_DATABASE_ERROR:
+- reason = "STATUS_DRIVER_DATABASE_ERROR";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SYSTEM_HIVE_TOO_LARGE:
+- reason = "STATUS_SYSTEM_HIVE_TOO_LARGE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_IMPORT_OF_NON_DLL:
+- reason = "STATUS_INVALID_IMPORT_OF_NON_DLL";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NO_SECRETS:
+- reason = "STATUS_NO_SECRETS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ACCESS_DISABLED_NO_SAFER_UI_BY_POLICY:
+- reason = "STATUS_ACCESS_DISABLED_NO_SAFER_UI_BY_POLICY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FAILED_STACK_SWITCH:
+- reason = "STATUS_FAILED_STACK_SWITCH";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_HEAP_CORRUPTION:
+- reason = "STATUS_HEAP_CORRUPTION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SMARTCARD_WRONG_PIN:
+- reason = "STATUS_SMARTCARD_WRONG_PIN";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SMARTCARD_CARD_BLOCKED:
+- reason = "STATUS_SMARTCARD_CARD_BLOCKED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SMARTCARD_CARD_NOT_AUTHENTICATED:
+- reason = "STATUS_SMARTCARD_CARD_NOT_AUTHENTICATED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SMARTCARD_NO_CARD:
+- reason = "STATUS_SMARTCARD_NO_CARD";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SMARTCARD_NO_KEY_CONTAINER:
+- reason = "STATUS_SMARTCARD_NO_KEY_CONTAINER";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SMARTCARD_NO_CERTIFICATE:
+- reason = "STATUS_SMARTCARD_NO_CERTIFICATE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SMARTCARD_NO_KEYSET:
+- reason = "STATUS_SMARTCARD_NO_KEYSET";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SMARTCARD_IO_ERROR:
+- reason = "STATUS_SMARTCARD_IO_ERROR";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DOWNGRADE_DETECTED:
+- reason = "STATUS_DOWNGRADE_DETECTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SMARTCARD_CERT_REVOKED:
+- reason = "STATUS_SMARTCARD_CERT_REVOKED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ISSUING_CA_UNTRUSTED:
+- reason = "STATUS_ISSUING_CA_UNTRUSTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_REVOCATION_OFFLINE_C:
+- reason = "STATUS_REVOCATION_OFFLINE_C";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PKINIT_CLIENT_FAILURE:
+- reason = "STATUS_PKINIT_CLIENT_FAILURE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SMARTCARD_CERT_EXPIRED:
+- reason = "STATUS_SMARTCARD_CERT_EXPIRED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DRIVER_FAILED_PRIOR_UNLOAD:
+- reason = "STATUS_DRIVER_FAILED_PRIOR_UNLOAD";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SMARTCARD_SILENT_CONTEXT:
+- reason = "STATUS_SMARTCARD_SILENT_CONTEXT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PER_USER_TRUST_QUOTA_EXCEEDED:
+- reason = "STATUS_PER_USER_TRUST_QUOTA_EXCEEDED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ALL_USER_TRUST_QUOTA_EXCEEDED:
+- reason = "STATUS_ALL_USER_TRUST_QUOTA_EXCEEDED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_USER_DELETE_TRUST_QUOTA_EXCEEDED:
+- reason = "STATUS_USER_DELETE_TRUST_QUOTA_EXCEEDED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DS_NAME_NOT_UNIQUE:
+- reason = "STATUS_DS_NAME_NOT_UNIQUE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DS_DUPLICATE_ID_FOUND:
+- reason = "STATUS_DS_DUPLICATE_ID_FOUND";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DS_GROUP_CONVERSION_ERROR:
+- reason = "STATUS_DS_GROUP_CONVERSION_ERROR";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLSNAP_PREPARE_HIBERNATE:
+- reason = "STATUS_VOLSNAP_PREPARE_HIBERNATE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_USER2USER_REQUIRED:
+- reason = "STATUS_USER2USER_REQUIRED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_STACK_BUFFER_OVERRUN:
+- reason = "STATUS_STACK_BUFFER_OVERRUN";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NO_S4U_PROT_SUPPORT:
+- reason = "STATUS_NO_S4U_PROT_SUPPORT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CROSSREALM_DELEGATION_FAILURE:
+- reason = "STATUS_CROSSREALM_DELEGATION_FAILURE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_REVOCATION_OFFLINE_KDC:
+- reason = "STATUS_REVOCATION_OFFLINE_KDC";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ISSUING_CA_UNTRUSTED_KDC:
+- reason = "STATUS_ISSUING_CA_UNTRUSTED_KDC";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_KDC_CERT_EXPIRED:
+- reason = "STATUS_KDC_CERT_EXPIRED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_KDC_CERT_REVOKED:
+- reason = "STATUS_KDC_CERT_REVOKED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PARAMETER_QUOTA_EXCEEDED:
+- reason = "STATUS_PARAMETER_QUOTA_EXCEEDED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_HIBERNATION_FAILURE:
+- reason = "STATUS_HIBERNATION_FAILURE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DELAY_LOAD_FAILED:
+- reason = "STATUS_DELAY_LOAD_FAILED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_AUTHENTICATION_FIREWALL_FAILED:
+- reason = "STATUS_AUTHENTICATION_FIREWALL_FAILED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VDM_DISALLOWED:
+- reason = "STATUS_VDM_DISALLOWED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_HUNG_DISPLAY_DRIVER_THREAD:
+- reason = "STATUS_HUNG_DISPLAY_DRIVER_THREAD";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INSUFFICIENT_RESOURCE_FOR_SPECIFIED_SHARED_SECTION_SIZE:
+- reason = "STATUS_INSUFFICIENT_RESOURCE_FOR_SPECIFIED_SHARED_SECTION_SIZE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_CRUNTIME_PARAMETER:
+- reason = "STATUS_INVALID_CRUNTIME_PARAMETER";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NTLM_BLOCKED:
+- reason = "STATUS_NTLM_BLOCKED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DS_SRC_SID_EXISTS_IN_FOREST:
+- reason = "STATUS_DS_SRC_SID_EXISTS_IN_FOREST";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DS_DOMAIN_NAME_EXISTS_IN_FOREST:
+- reason = "STATUS_DS_DOMAIN_NAME_EXISTS_IN_FOREST";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DS_FLAT_NAME_EXISTS_IN_FOREST:
+- reason = "STATUS_DS_FLAT_NAME_EXISTS_IN_FOREST";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_USER_PRINCIPAL_NAME:
+- reason = "STATUS_INVALID_USER_PRINCIPAL_NAME";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FATAL_USER_CALLBACK_EXCEPTION:
+- reason = "STATUS_FATAL_USER_CALLBACK_EXCEPTION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ASSERTION_FAILURE:
+- reason = "STATUS_ASSERTION_FAILURE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VERIFIER_STOP:
+- reason = "STATUS_VERIFIER_STOP";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CALLBACK_POP_STACK:
+- reason = "STATUS_CALLBACK_POP_STACK";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INCOMPATIBLE_DRIVER_BLOCKED:
+- reason = "STATUS_INCOMPATIBLE_DRIVER_BLOCKED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_HIVE_UNLOADED:
+- reason = "STATUS_HIVE_UNLOADED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_COMPRESSION_DISABLED:
+- reason = "STATUS_COMPRESSION_DISABLED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FILE_SYSTEM_LIMITATION:
+- reason = "STATUS_FILE_SYSTEM_LIMITATION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_IMAGE_HASH:
+- reason = "STATUS_INVALID_IMAGE_HASH";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NOT_CAPABLE:
+- reason = "STATUS_NOT_CAPABLE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_REQUEST_OUT_OF_SEQUENCE:
+- reason = "STATUS_REQUEST_OUT_OF_SEQUENCE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_IMPLEMENTATION_LIMIT:
+- reason = "STATUS_IMPLEMENTATION_LIMIT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ELEVATION_REQUIRED:
+- reason = "STATUS_ELEVATION_REQUIRED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NO_SECURITY_CONTEXT:
+- reason = "STATUS_NO_SECURITY_CONTEXT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PKU2U_CERT_FAILURE:
+- reason = "STATUS_PKU2U_CERT_FAILURE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_BEYOND_VDL:
+- reason = "STATUS_BEYOND_VDL";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ENCOUNTERED_WRITE_IN_PROGRESS:
+- reason = "STATUS_ENCOUNTERED_WRITE_IN_PROGRESS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PTE_CHANGED:
+- reason = "STATUS_PTE_CHANGED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PURGE_FAILED:
+- reason = "STATUS_PURGE_FAILED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CRED_REQUIRES_CONFIRMATION:
+- reason = "STATUS_CRED_REQUIRES_CONFIRMATION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CS_ENCRYPTION_INVALID_SERVER_RESPONSE:
+- reason = "STATUS_CS_ENCRYPTION_INVALID_SERVER_RESPONSE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CS_ENCRYPTION_UNSUPPORTED_SERVER:
+- reason = "STATUS_CS_ENCRYPTION_UNSUPPORTED_SERVER";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CS_ENCRYPTION_EXISTING_ENCRYPTED_FILE:
+- reason = "STATUS_CS_ENCRYPTION_EXISTING_ENCRYPTED_FILE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CS_ENCRYPTION_NEW_ENCRYPTED_FILE:
+- reason = "STATUS_CS_ENCRYPTION_NEW_ENCRYPTED_FILE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CS_ENCRYPTION_FILE_NOT_CSE:
+- reason = "STATUS_CS_ENCRYPTION_FILE_NOT_CSE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_LABEL:
+- reason = "STATUS_INVALID_LABEL";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DRIVER_PROCESS_TERMINATED:
+- reason = "STATUS_DRIVER_PROCESS_TERMINATED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_AMBIGUOUS_SYSTEM_DEVICE:
+- reason = "STATUS_AMBIGUOUS_SYSTEM_DEVICE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SYSTEM_DEVICE_NOT_FOUND:
+- reason = "STATUS_SYSTEM_DEVICE_NOT_FOUND";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_RESTART_BOOT_APPLICATION:
+- reason = "STATUS_RESTART_BOOT_APPLICATION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INSUFFICIENT_NVRAM_RESOURCES:
+- reason = "STATUS_INSUFFICIENT_NVRAM_RESOURCES";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_SESSION:
+- reason = "STATUS_INVALID_SESSION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_THREAD_ALREADY_IN_SESSION:
+- reason = "STATUS_THREAD_ALREADY_IN_SESSION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_THREAD_NOT_IN_SESSION:
+- reason = "STATUS_THREAD_NOT_IN_SESSION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_WEIGHT:
+- reason = "STATUS_INVALID_WEIGHT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_REQUEST_PAUSED:
+- reason = "STATUS_REQUEST_PAUSED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NO_RANGES_PROCESSED:
+- reason = "STATUS_NO_RANGES_PROCESSED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DISK_RESOURCES_EXHAUSTED:
+- reason = "STATUS_DISK_RESOURCES_EXHAUSTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NEEDS_REMEDIATION:
+- reason = "STATUS_NEEDS_REMEDIATION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DEVICE_FEATURE_NOT_SUPPORTED:
+- reason = "STATUS_DEVICE_FEATURE_NOT_SUPPORTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DEVICE_UNREACHABLE:
+- reason = "STATUS_DEVICE_UNREACHABLE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_TOKEN:
+- reason = "STATUS_INVALID_TOKEN";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SERVER_UNAVAILABLE:
+- reason = "STATUS_SERVER_UNAVAILABLE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FILE_NOT_AVAILABLE:
+- reason = "STATUS_FILE_NOT_AVAILABLE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DEVICE_INSUFFICIENT_RESOURCES:
+- reason = "STATUS_DEVICE_INSUFFICIENT_RESOURCES";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PACKAGE_UPDATING:
+- reason = "STATUS_PACKAGE_UPDATING";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NOT_READ_FROM_COPY:
+- reason = "STATUS_NOT_READ_FROM_COPY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FT_WRITE_FAILURE:
+- reason = "STATUS_FT_WRITE_FAILURE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FT_DI_SCAN_REQUIRED:
+- reason = "STATUS_FT_DI_SCAN_REQUIRED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_OBJECT_NOT_EXTERNALLY_BACKED:
+- reason = "STATUS_OBJECT_NOT_EXTERNALLY_BACKED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_EXTERNAL_BACKING_PROVIDER_UNKNOWN:
+- reason = "STATUS_EXTERNAL_BACKING_PROVIDER_UNKNOWN";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_COMPRESSION_NOT_BENEFICIAL:
+- reason = "STATUS_COMPRESSION_NOT_BENEFICIAL";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DATA_CHECKSUM_ERROR:
+- reason = "STATUS_DATA_CHECKSUM_ERROR";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INTERMIXED_KERNEL_EA_OPERATION:
+- reason = "STATUS_INTERMIXED_KERNEL_EA_OPERATION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TRIM_READ_ZERO_NOT_SUPPORTED:
+- reason = "STATUS_TRIM_READ_ZERO_NOT_SUPPORTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TOO_MANY_SEGMENT_DESCRIPTORS:
+- reason = "STATUS_TOO_MANY_SEGMENT_DESCRIPTORS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_OFFSET_ALIGNMENT:
+- reason = "STATUS_INVALID_OFFSET_ALIGNMENT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_FIELD_IN_PARAMETER_LIST:
+- reason = "STATUS_INVALID_FIELD_IN_PARAMETER_LIST";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_OPERATION_IN_PROGRESS:
+- reason = "STATUS_OPERATION_IN_PROGRESS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_INITIATOR_TARGET_PATH:
+- reason = "STATUS_INVALID_INITIATOR_TARGET_PATH";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SCRUB_DATA_DISABLED:
+- reason = "STATUS_SCRUB_DATA_DISABLED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NOT_REDUNDANT_STORAGE:
+- reason = "STATUS_NOT_REDUNDANT_STORAGE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_RESIDENT_FILE_NOT_SUPPORTED:
+- reason = "STATUS_RESIDENT_FILE_NOT_SUPPORTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_COMPRESSED_FILE_NOT_SUPPORTED:
+- reason = "STATUS_COMPRESSED_FILE_NOT_SUPPORTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DIRECTORY_NOT_SUPPORTED:
+- reason = "STATUS_DIRECTORY_NOT_SUPPORTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_IO_OPERATION_TIMEOUT:
+- reason = "STATUS_IO_OPERATION_TIMEOUT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SYSTEM_NEEDS_REMEDIATION:
+- reason = "STATUS_SYSTEM_NEEDS_REMEDIATION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_APPX_INTEGRITY_FAILURE_CLR_NGEN:
+- reason = "STATUS_APPX_INTEGRITY_FAILURE_CLR_NGEN";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SHARE_UNAVAILABLE:
+- reason = "STATUS_SHARE_UNAVAILABLE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_APISET_NOT_HOSTED:
+- reason = "STATUS_APISET_NOT_HOSTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_APISET_NOT_PRESENT:
+- reason = "STATUS_APISET_NOT_PRESENT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DEVICE_HARDWARE_ERROR:
+- reason = "STATUS_DEVICE_HARDWARE_ERROR";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FIRMWARE_SLOT_INVALID:
+- reason = "STATUS_FIRMWARE_SLOT_INVALID";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FIRMWARE_IMAGE_INVALID:
+- reason = "STATUS_FIRMWARE_IMAGE_INVALID";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_STORAGE_TOPOLOGY_ID_MISMATCH:
+- reason = "STATUS_STORAGE_TOPOLOGY_ID_MISMATCH";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_WIM_NOT_BOOTABLE:
+- reason = "STATUS_WIM_NOT_BOOTABLE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_BLOCKED_BY_PARENTAL_CONTROLS:
+- reason = "STATUS_BLOCKED_BY_PARENTAL_CONTROLS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NEEDS_REGISTRATION:
+- reason = "STATUS_NEEDS_REGISTRATION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_QUOTA_ACTIVITY:
+- reason = "STATUS_QUOTA_ACTIVITY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CALLBACK_INVOKE_INLINE:
+- reason = "STATUS_CALLBACK_INVOKE_INLINE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_BLOCK_TOO_MANY_REFERENCES:
+- reason = "STATUS_BLOCK_TOO_MANY_REFERENCES";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_MARKED_TO_DISALLOW_WRITES:
+- reason = "STATUS_MARKED_TO_DISALLOW_WRITES";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NETWORK_ACCESS_DENIED_EDP:
+- reason = "STATUS_NETWORK_ACCESS_DENIED_EDP";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ENCLAVE_FAILURE:
+- reason = "STATUS_ENCLAVE_FAILURE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PNP_NO_COMPAT_DRIVERS:
+- reason = "STATUS_PNP_NO_COMPAT_DRIVERS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PNP_DRIVER_PACKAGE_NOT_FOUND:
+- reason = "STATUS_PNP_DRIVER_PACKAGE_NOT_FOUND";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PNP_DRIVER_CONFIGURATION_NOT_FOUND:
+- reason = "STATUS_PNP_DRIVER_CONFIGURATION_NOT_FOUND";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PNP_DRIVER_CONFIGURATION_INCOMPLETE:
+- reason = "STATUS_PNP_DRIVER_CONFIGURATION_INCOMPLETE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PNP_FUNCTION_DRIVER_REQUIRED:
+- reason = "STATUS_PNP_FUNCTION_DRIVER_REQUIRED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PNP_DEVICE_CONFIGURATION_PENDING:
+- reason = "STATUS_PNP_DEVICE_CONFIGURATION_PENDING";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DEVICE_HINT_NAME_BUFFER_TOO_SMALL:
+- reason = "STATUS_DEVICE_HINT_NAME_BUFFER_TOO_SMALL";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PACKAGE_NOT_AVAILABLE:
+- reason = "STATUS_PACKAGE_NOT_AVAILABLE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DEVICE_IN_MAINTENANCE:
+- reason = "STATUS_DEVICE_IN_MAINTENANCE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NOT_SUPPORTED_ON_DAX:
+- reason = "STATUS_NOT_SUPPORTED_ON_DAX";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FREE_SPACE_TOO_FRAGMENTED:
+- reason = "STATUS_FREE_SPACE_TOO_FRAGMENTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DAX_MAPPING_EXISTS:
+- reason = "STATUS_DAX_MAPPING_EXISTS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CHILD_PROCESS_BLOCKED:
+- reason = "STATUS_CHILD_PROCESS_BLOCKED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_STORAGE_LOST_DATA_PERSISTENCE:
+- reason = "STATUS_STORAGE_LOST_DATA_PERSISTENCE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VRF_CFG_AND_IO_ENABLED:
+- reason = "STATUS_VRF_CFG_AND_IO_ENABLED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PARTITION_TERMINATING:
+- reason = "STATUS_PARTITION_TERMINATING";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_EXTERNAL_SYSKEY_NOT_SUPPORTED:
+- reason = "STATUS_EXTERNAL_SYSKEY_NOT_SUPPORTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ENCLAVE_VIOLATION:
+- reason = "STATUS_ENCLAVE_VIOLATION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FILE_PROTECTED_UNDER_DPL:
+- reason = "STATUS_FILE_PROTECTED_UNDER_DPL";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLUME_NOT_CLUSTER_ALIGNED:
+- reason = "STATUS_VOLUME_NOT_CLUSTER_ALIGNED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NO_PHYSICALLY_ALIGNED_FREE_SPACE_FOUND:
+- reason = "STATUS_NO_PHYSICALLY_ALIGNED_FREE_SPACE_FOUND";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_APPX_FILE_NOT_ENCRYPTED:
+- reason = "STATUS_APPX_FILE_NOT_ENCRYPTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_RWRAW_ENCRYPTED_FILE_NOT_ENCRYPTED:
+- reason = "STATUS_RWRAW_ENCRYPTED_FILE_NOT_ENCRYPTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_RWRAW_ENCRYPTED_INVALID_EDATAINFO_FILEOFFSET:
+- reason = "STATUS_RWRAW_ENCRYPTED_INVALID_EDATAINFO_FILEOFFSET";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_RWRAW_ENCRYPTED_INVALID_EDATAINFO_FILERANGE:
+- reason = "STATUS_RWRAW_ENCRYPTED_INVALID_EDATAINFO_FILERANGE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_RWRAW_ENCRYPTED_INVALID_EDATAINFO_PARAMETER:
+- reason = "STATUS_RWRAW_ENCRYPTED_INVALID_EDATAINFO_PARAMETER";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FT_READ_FAILURE:
+- reason = "STATUS_FT_READ_FAILURE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PATCH_CONFLICT:
+- reason = "STATUS_PATCH_CONFLICT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_STORAGE_RESERVE_ID_INVALID:
+- reason = "STATUS_STORAGE_RESERVE_ID_INVALID";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_STORAGE_RESERVE_DOES_NOT_EXIST:
+- reason = "STATUS_STORAGE_RESERVE_DOES_NOT_EXIST";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_STORAGE_RESERVE_ALREADY_EXISTS:
+- reason = "STATUS_STORAGE_RESERVE_ALREADY_EXISTS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_STORAGE_RESERVE_NOT_EMPTY:
+- reason = "STATUS_STORAGE_RESERVE_NOT_EMPTY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NOT_A_DAX_VOLUME:
+- reason = "STATUS_NOT_A_DAX_VOLUME";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NOT_DAX_MAPPABLE:
+- reason = "STATUS_NOT_DAX_MAPPABLE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CASE_DIFFERING_NAMES_IN_DIR:
+- reason = "STATUS_CASE_DIFFERING_NAMES_IN_DIR";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FILE_NOT_SUPPORTED:
+- reason = "STATUS_FILE_NOT_SUPPORTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NOT_SUPPORTED_WITH_BTT:
+- reason = "STATUS_NOT_SUPPORTED_WITH_BTT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ENCRYPTION_DISABLED:
+- reason = "STATUS_ENCRYPTION_DISABLED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ENCRYPTING_METADATA_DISALLOWED:
+- reason = "STATUS_ENCRYPTING_METADATA_DISALLOWED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CANT_CLEAR_ENCRYPTION_FLAG:
+- reason = "STATUS_CANT_CLEAR_ENCRYPTION_FLAG";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_UNSATISFIED_DEPENDENCIES:
+- reason = "STATUS_UNSATISFIED_DEPENDENCIES";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CASE_SENSITIVE_PATH:
+- reason = "STATUS_CASE_SENSITIVE_PATH";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_HAS_SYSTEM_CRITICAL_FILES:
+- reason = "STATUS_HAS_SYSTEM_CRITICAL_FILES";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_TASK_NAME:
+- reason = "STATUS_INVALID_TASK_NAME";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_TASK_INDEX:
+- reason = "STATUS_INVALID_TASK_INDEX";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_THREAD_ALREADY_IN_TASK:
+- reason = "STATUS_THREAD_ALREADY_IN_TASK";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CALLBACK_BYPASS:
+- reason = "STATUS_CALLBACK_BYPASS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_UNDEFINED_SCOPE:
+- reason = "STATUS_UNDEFINED_SCOPE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_CAP:
+- reason = "STATUS_INVALID_CAP";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NOT_GUI_PROCESS:
+- reason = "STATUS_NOT_GUI_PROCESS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DEVICE_HUNG:
+- reason = "STATUS_DEVICE_HUNG";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CONTAINER_ASSIGNED:
+- reason = "STATUS_CONTAINER_ASSIGNED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_JOB_NO_CONTAINER:
+- reason = "STATUS_JOB_NO_CONTAINER";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DEVICE_UNRESPONSIVE:
+- reason = "STATUS_DEVICE_UNRESPONSIVE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_REPARSE_POINT_ENCOUNTERED:
+- reason = "STATUS_REPARSE_POINT_ENCOUNTERED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ATTRIBUTE_NOT_PRESENT:
+- reason = "STATUS_ATTRIBUTE_NOT_PRESENT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NOT_A_TIERED_VOLUME:
+- reason = "STATUS_NOT_A_TIERED_VOLUME";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ALREADY_HAS_STREAM_ID:
+- reason = "STATUS_ALREADY_HAS_STREAM_ID";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_JOB_NOT_EMPTY:
+- reason = "STATUS_JOB_NOT_EMPTY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ALREADY_INITIALIZED:
+- reason = "STATUS_ALREADY_INITIALIZED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ENCLAVE_NOT_TERMINATED:
+- reason = "STATUS_ENCLAVE_NOT_TERMINATED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ENCLAVE_IS_TERMINATING:
+- reason = "STATUS_ENCLAVE_IS_TERMINATING";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SMB1_NOT_AVAILABLE:
+- reason = "STATUS_SMB1_NOT_AVAILABLE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SMR_GARBAGE_COLLECTION_REQUIRED:
+- reason = "STATUS_SMR_GARBAGE_COLLECTION_REQUIRED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INTERRUPTED:
+- reason = "STATUS_INTERRUPTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_THREAD_NOT_RUNNING:
+- reason = "STATUS_THREAD_NOT_RUNNING";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FAIL_FAST_EXCEPTION:
+- reason = "STATUS_FAIL_FAST_EXCEPTION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_IMAGE_CERT_REVOKED:
+- reason = "STATUS_IMAGE_CERT_REVOKED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DYNAMIC_CODE_BLOCKED:
+- reason = "STATUS_DYNAMIC_CODE_BLOCKED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_IMAGE_CERT_EXPIRED:
+- reason = "STATUS_IMAGE_CERT_EXPIRED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_STRICT_CFG_VIOLATION:
+- reason = "STATUS_STRICT_CFG_VIOLATION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SET_CONTEXT_DENIED:
+- reason = "STATUS_SET_CONTEXT_DENIED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CROSS_PARTITION_VIOLATION:
+- reason = "STATUS_CROSS_PARTITION_VIOLATION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PORT_CLOSED:
+- reason = "STATUS_PORT_CLOSED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_MESSAGE_LOST:
+- reason = "STATUS_MESSAGE_LOST";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_MESSAGE:
+- reason = "STATUS_INVALID_MESSAGE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_REQUEST_CANCELED:
+- reason = "STATUS_REQUEST_CANCELED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_RECURSIVE_DISPATCH:
+- reason = "STATUS_RECURSIVE_DISPATCH";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_LPC_RECEIVE_BUFFER_EXPECTED:
+- reason = "STATUS_LPC_RECEIVE_BUFFER_EXPECTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_LPC_INVALID_CONNECTION_USAGE:
+- reason = "STATUS_LPC_INVALID_CONNECTION_USAGE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_LPC_REQUESTS_NOT_ALLOWED:
+- reason = "STATUS_LPC_REQUESTS_NOT_ALLOWED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_RESOURCE_IN_USE:
+- reason = "STATUS_RESOURCE_IN_USE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_HARDWARE_MEMORY_ERROR:
+- reason = "STATUS_HARDWARE_MEMORY_ERROR";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_THREADPOOL_HANDLE_EXCEPTION:
+- reason = "STATUS_THREADPOOL_HANDLE_EXCEPTION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_THREADPOOL_SET_EVENT_ON_COMPLETION_FAILED:
+- reason = "STATUS_THREADPOOL_SET_EVENT_ON_COMPLETION_FAILED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_THREADPOOL_RELEASE_SEMAPHORE_ON_COMPLETION_FAILED:
+- reason = "STATUS_THREADPOOL_RELEASE_SEMAPHORE_ON_COMPLETION_FAILED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_THREADPOOL_RELEASE_MUTEX_ON_COMPLETION_FAILED:
+- reason = "STATUS_THREADPOOL_RELEASE_MUTEX_ON_COMPLETION_FAILED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_THREADPOOL_FREE_LIBRARY_ON_COMPLETION_FAILED:
+- reason = "STATUS_THREADPOOL_FREE_LIBRARY_ON_COMPLETION_FAILED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_THREADPOOL_RELEASED_DURING_OPERATION:
+- reason = "STATUS_THREADPOOL_RELEASED_DURING_OPERATION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CALLBACK_RETURNED_WHILE_IMPERSONATING:
+- reason = "STATUS_CALLBACK_RETURNED_WHILE_IMPERSONATING";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_APC_RETURNED_WHILE_IMPERSONATING:
+- reason = "STATUS_APC_RETURNED_WHILE_IMPERSONATING";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PROCESS_IS_PROTECTED:
+- reason = "STATUS_PROCESS_IS_PROTECTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_MCA_EXCEPTION:
+- reason = "STATUS_MCA_EXCEPTION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CERTIFICATE_MAPPING_NOT_UNIQUE:
+- reason = "STATUS_CERTIFICATE_MAPPING_NOT_UNIQUE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SYMLINK_CLASS_DISABLED:
+- reason = "STATUS_SYMLINK_CLASS_DISABLED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_IDN_NORMALIZATION:
+- reason = "STATUS_INVALID_IDN_NORMALIZATION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NO_UNICODE_TRANSLATION:
+- reason = "STATUS_NO_UNICODE_TRANSLATION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ALREADY_REGISTERED:
+- reason = "STATUS_ALREADY_REGISTERED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CONTEXT_MISMATCH:
+- reason = "STATUS_CONTEXT_MISMATCH";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PORT_ALREADY_HAS_COMPLETION_LIST:
+- reason = "STATUS_PORT_ALREADY_HAS_COMPLETION_LIST";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CALLBACK_RETURNED_THREAD_PRIORITY:
+- reason = "STATUS_CALLBACK_RETURNED_THREAD_PRIORITY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_THREAD:
+- reason = "STATUS_INVALID_THREAD";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CALLBACK_RETURNED_TRANSACTION:
+- reason = "STATUS_CALLBACK_RETURNED_TRANSACTION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CALLBACK_RETURNED_LDR_LOCK:
+- reason = "STATUS_CALLBACK_RETURNED_LDR_LOCK";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CALLBACK_RETURNED_LANG:
+- reason = "STATUS_CALLBACK_RETURNED_LANG";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CALLBACK_RETURNED_PRI_BACK:
+- reason = "STATUS_CALLBACK_RETURNED_PRI_BACK";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CALLBACK_RETURNED_THREAD_AFFINITY:
+- reason = "STATUS_CALLBACK_RETURNED_THREAD_AFFINITY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_LPC_HANDLE_COUNT_EXCEEDED:
+- reason = "STATUS_LPC_HANDLE_COUNT_EXCEEDED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_EXECUTABLE_MEMORY_WRITE:
+- reason = "STATUS_EXECUTABLE_MEMORY_WRITE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_KERNEL_EXECUTABLE_MEMORY_WRITE:
+- reason = "STATUS_KERNEL_EXECUTABLE_MEMORY_WRITE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ATTACHED_EXECUTABLE_MEMORY_WRITE:
+- reason = "STATUS_ATTACHED_EXECUTABLE_MEMORY_WRITE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TRIGGERED_EXECUTABLE_MEMORY_WRITE:
+- reason = "STATUS_TRIGGERED_EXECUTABLE_MEMORY_WRITE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DISK_REPAIR_DISABLED:
+- reason = "STATUS_DISK_REPAIR_DISABLED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DS_DOMAIN_RENAME_IN_PROGRESS:
+- reason = "STATUS_DS_DOMAIN_RENAME_IN_PROGRESS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DISK_QUOTA_EXCEEDED:
+- reason = "STATUS_DISK_QUOTA_EXCEEDED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CONTENT_BLOCKED:
+- reason = "STATUS_CONTENT_BLOCKED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_BAD_CLUSTERS:
+- reason = "STATUS_BAD_CLUSTERS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLUME_DIRTY:
+- reason = "STATUS_VOLUME_DIRTY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DISK_REPAIR_UNSUCCESSFUL:
+- reason = "STATUS_DISK_REPAIR_UNSUCCESSFUL";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CORRUPT_LOG_OVERFULL:
+- reason = "STATUS_CORRUPT_LOG_OVERFULL";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CORRUPT_LOG_CORRUPTED:
+- reason = "STATUS_CORRUPT_LOG_CORRUPTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CORRUPT_LOG_UNAVAILABLE:
+- reason = "STATUS_CORRUPT_LOG_UNAVAILABLE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CORRUPT_LOG_DELETED_FULL:
+- reason = "STATUS_CORRUPT_LOG_DELETED_FULL";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CORRUPT_LOG_CLEARED:
+- reason = "STATUS_CORRUPT_LOG_CLEARED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ORPHAN_NAME_EXHAUSTED:
+- reason = "STATUS_ORPHAN_NAME_EXHAUSTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PROACTIVE_SCAN_IN_PROGRESS:
+- reason = "STATUS_PROACTIVE_SCAN_IN_PROGRESS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ENCRYPTED_IO_NOT_POSSIBLE:
+- reason = "STATUS_ENCRYPTED_IO_NOT_POSSIBLE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CORRUPT_LOG_UPLEVEL_RECORDS:
+- reason = "STATUS_CORRUPT_LOG_UPLEVEL_RECORDS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FILE_CHECKED_OUT:
+- reason = "STATUS_FILE_CHECKED_OUT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CHECKOUT_REQUIRED:
+- reason = "STATUS_CHECKOUT_REQUIRED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_BAD_FILE_TYPE:
+- reason = "STATUS_BAD_FILE_TYPE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FILE_TOO_LARGE:
+- reason = "STATUS_FILE_TOO_LARGE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FORMS_AUTH_REQUIRED:
+- reason = "STATUS_FORMS_AUTH_REQUIRED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VIRUS_INFECTED:
+- reason = "STATUS_VIRUS_INFECTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VIRUS_DELETED:
+- reason = "STATUS_VIRUS_DELETED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_BAD_MCFG_TABLE:
+- reason = "STATUS_BAD_MCFG_TABLE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CANNOT_BREAK_OPLOCK:
+- reason = "STATUS_CANNOT_BREAK_OPLOCK";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_BAD_KEY:
+- reason = "STATUS_BAD_KEY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_BAD_DATA:
+- reason = "STATUS_BAD_DATA";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NO_KEY:
+- reason = "STATUS_NO_KEY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FILE_HANDLE_REVOKED:
+- reason = "STATUS_FILE_HANDLE_REVOKED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_WOW_ASSERTION:
+- reason = "STATUS_WOW_ASSERTION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_SIGNATURE:
+- reason = "STATUS_INVALID_SIGNATURE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_HMAC_NOT_SUPPORTED:
+- reason = "STATUS_HMAC_NOT_SUPPORTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_AUTH_TAG_MISMATCH:
+- reason = "STATUS_AUTH_TAG_MISMATCH";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_STATE_TRANSITION:
+- reason = "STATUS_INVALID_STATE_TRANSITION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_KERNEL_INFO_VERSION:
+- reason = "STATUS_INVALID_KERNEL_INFO_VERSION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_PEP_INFO_VERSION:
+- reason = "STATUS_INVALID_PEP_INFO_VERSION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_HANDLE_REVOKED:
+- reason = "STATUS_HANDLE_REVOKED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_EOF_ON_GHOSTED_RANGE:
+- reason = "STATUS_EOF_ON_GHOSTED_RANGE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CC_NEEDS_CALLBACK_SECTION_DRAIN:
+- reason = "STATUS_CC_NEEDS_CALLBACK_SECTION_DRAIN";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_IPSEC_QUEUE_OVERFLOW:
+- reason = "STATUS_IPSEC_QUEUE_OVERFLOW";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ND_QUEUE_OVERFLOW:
+- reason = "STATUS_ND_QUEUE_OVERFLOW";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_HOPLIMIT_EXCEEDED:
+- reason = "STATUS_HOPLIMIT_EXCEEDED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PROTOCOL_NOT_SUPPORTED:
+- reason = "STATUS_PROTOCOL_NOT_SUPPORTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FASTPATH_REJECTED:
+- reason = "STATUS_FASTPATH_REJECTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_LOST_WRITEBEHIND_DATA_NETWORK_DISCONNECTED:
+- reason = "STATUS_LOST_WRITEBEHIND_DATA_NETWORK_DISCONNECTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_LOST_WRITEBEHIND_DATA_NETWORK_SERVER_ERROR:
+- reason = "STATUS_LOST_WRITEBEHIND_DATA_NETWORK_SERVER_ERROR";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_LOST_WRITEBEHIND_DATA_LOCAL_DISK_ERROR:
+- reason = "STATUS_LOST_WRITEBEHIND_DATA_LOCAL_DISK_ERROR";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_XML_PARSE_ERROR:
+- reason = "STATUS_XML_PARSE_ERROR";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_XMLDSIG_ERROR:
+- reason = "STATUS_XMLDSIG_ERROR";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_WRONG_COMPARTMENT:
+- reason = "STATUS_WRONG_COMPARTMENT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_AUTHIP_FAILURE:
+- reason = "STATUS_AUTHIP_FAILURE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DS_OID_MAPPED_GROUP_CANT_HAVE_MEMBERS:
+- reason = "STATUS_DS_OID_MAPPED_GROUP_CANT_HAVE_MEMBERS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DS_OID_NOT_FOUND:
+- reason = "STATUS_DS_OID_NOT_FOUND";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INCORRECT_ACCOUNT_TYPE:
+- reason = "STATUS_INCORRECT_ACCOUNT_TYPE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_HASH_NOT_SUPPORTED:
+- reason = "STATUS_HASH_NOT_SUPPORTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_HASH_NOT_PRESENT:
+- reason = "STATUS_HASH_NOT_PRESENT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SECONDARY_IC_PROVIDER_NOT_REGISTERED:
+- reason = "STATUS_SECONDARY_IC_PROVIDER_NOT_REGISTERED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GPIO_CLIENT_INFORMATION_INVALID:
+- reason = "STATUS_GPIO_CLIENT_INFORMATION_INVALID";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GPIO_VERSION_NOT_SUPPORTED:
+- reason = "STATUS_GPIO_VERSION_NOT_SUPPORTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GPIO_INVALID_REGISTRATION_PACKET:
+- reason = "STATUS_GPIO_INVALID_REGISTRATION_PACKET";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GPIO_OPERATION_DENIED:
+- reason = "STATUS_GPIO_OPERATION_DENIED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GPIO_INCOMPATIBLE_CONNECT_MODE:
+- reason = "STATUS_GPIO_INCOMPATIBLE_CONNECT_MODE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CANNOT_SWITCH_RUNLEVEL:
+- reason = "STATUS_CANNOT_SWITCH_RUNLEVEL";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_RUNLEVEL_SETTING:
+- reason = "STATUS_INVALID_RUNLEVEL_SETTING";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_RUNLEVEL_SWITCH_TIMEOUT:
+- reason = "STATUS_RUNLEVEL_SWITCH_TIMEOUT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_RUNLEVEL_SWITCH_AGENT_TIMEOUT:
+- reason = "STATUS_RUNLEVEL_SWITCH_AGENT_TIMEOUT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_RUNLEVEL_SWITCH_IN_PROGRESS:
+- reason = "STATUS_RUNLEVEL_SWITCH_IN_PROGRESS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NOT_APPCONTAINER:
+- reason = "STATUS_NOT_APPCONTAINER";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NOT_SUPPORTED_IN_APPCONTAINER:
+- reason = "STATUS_NOT_SUPPORTED_IN_APPCONTAINER";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_PACKAGE_SID_LENGTH:
+- reason = "STATUS_INVALID_PACKAGE_SID_LENGTH";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_LPAC_ACCESS_DENIED:
+- reason = "STATUS_LPAC_ACCESS_DENIED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ADMINLESS_ACCESS_DENIED:
+- reason = "STATUS_ADMINLESS_ACCESS_DENIED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_APP_DATA_NOT_FOUND:
+- reason = "STATUS_APP_DATA_NOT_FOUND";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_APP_DATA_EXPIRED:
+- reason = "STATUS_APP_DATA_EXPIRED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_APP_DATA_CORRUPT:
+- reason = "STATUS_APP_DATA_CORRUPT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_APP_DATA_LIMIT_EXCEEDED:
+- reason = "STATUS_APP_DATA_LIMIT_EXCEEDED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_APP_DATA_REBOOT_REQUIRED:
+- reason = "STATUS_APP_DATA_REBOOT_REQUIRED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_OFFLOAD_READ_FLT_NOT_SUPPORTED:
+- reason = "STATUS_OFFLOAD_READ_FLT_NOT_SUPPORTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_OFFLOAD_WRITE_FLT_NOT_SUPPORTED:
+- reason = "STATUS_OFFLOAD_WRITE_FLT_NOT_SUPPORTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_OFFLOAD_READ_FILE_NOT_SUPPORTED:
+- reason = "STATUS_OFFLOAD_READ_FILE_NOT_SUPPORTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_OFFLOAD_WRITE_FILE_NOT_SUPPORTED:
+- reason = "STATUS_OFFLOAD_WRITE_FILE_NOT_SUPPORTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_WOF_WIM_HEADER_CORRUPT:
+- reason = "STATUS_WOF_WIM_HEADER_CORRUPT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_WOF_WIM_RESOURCE_TABLE_CORRUPT:
+- reason = "STATUS_WOF_WIM_RESOURCE_TABLE_CORRUPT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_WOF_FILE_RESOURCE_TABLE_CORRUPT:
+- reason = "STATUS_WOF_FILE_RESOURCE_TABLE_CORRUPT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CIMFS_IMAGE_CORRUPT:
+- reason = "STATUS_CIMFS_IMAGE_CORRUPT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FILE_SYSTEM_VIRTUALIZATION_UNAVAILABLE:
+- reason = "STATUS_FILE_SYSTEM_VIRTUALIZATION_UNAVAILABLE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FILE_SYSTEM_VIRTUALIZATION_METADATA_CORRUPT:
+- reason = "STATUS_FILE_SYSTEM_VIRTUALIZATION_METADATA_CORRUPT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FILE_SYSTEM_VIRTUALIZATION_BUSY:
+- reason = "STATUS_FILE_SYSTEM_VIRTUALIZATION_BUSY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FILE_SYSTEM_VIRTUALIZATION_PROVIDER_UNKNOWN:
+- reason = "STATUS_FILE_SYSTEM_VIRTUALIZATION_PROVIDER_UNKNOWN";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FILE_SYSTEM_VIRTUALIZATION_INVALID_OPERATION:
+- reason = "STATUS_FILE_SYSTEM_VIRTUALIZATION_INVALID_OPERATION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_SYNC_ROOT_METADATA_CORRUPT:
+- reason = "STATUS_CLOUD_FILE_SYNC_ROOT_METADATA_CORRUPT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_PROVIDER_NOT_RUNNING:
+- reason = "STATUS_CLOUD_FILE_PROVIDER_NOT_RUNNING";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_METADATA_CORRUPT:
+- reason = "STATUS_CLOUD_FILE_METADATA_CORRUPT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_METADATA_TOO_LARGE:
+- reason = "STATUS_CLOUD_FILE_METADATA_TOO_LARGE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_PROPERTY_VERSION_NOT_SUPPORTED:
+- reason = "STATUS_CLOUD_FILE_PROPERTY_VERSION_NOT_SUPPORTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NOT_A_CLOUD_FILE:
+- reason = "STATUS_NOT_A_CLOUD_FILE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_NOT_IN_SYNC:
+- reason = "STATUS_CLOUD_FILE_NOT_IN_SYNC";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_ALREADY_CONNECTED:
+- reason = "STATUS_CLOUD_FILE_ALREADY_CONNECTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_NOT_SUPPORTED:
+- reason = "STATUS_CLOUD_FILE_NOT_SUPPORTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_INVALID_REQUEST:
+- reason = "STATUS_CLOUD_FILE_INVALID_REQUEST";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_READ_ONLY_VOLUME:
+- reason = "STATUS_CLOUD_FILE_READ_ONLY_VOLUME";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_CONNECTED_PROVIDER_ONLY:
+- reason = "STATUS_CLOUD_FILE_CONNECTED_PROVIDER_ONLY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_VALIDATION_FAILED:
+- reason = "STATUS_CLOUD_FILE_VALIDATION_FAILED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_AUTHENTICATION_FAILED:
+- reason = "STATUS_CLOUD_FILE_AUTHENTICATION_FAILED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_INSUFFICIENT_RESOURCES:
+- reason = "STATUS_CLOUD_FILE_INSUFFICIENT_RESOURCES";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_NETWORK_UNAVAILABLE:
+- reason = "STATUS_CLOUD_FILE_NETWORK_UNAVAILABLE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_UNSUCCESSFUL:
+- reason = "STATUS_CLOUD_FILE_UNSUCCESSFUL";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_NOT_UNDER_SYNC_ROOT:
+- reason = "STATUS_CLOUD_FILE_NOT_UNDER_SYNC_ROOT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_IN_USE:
+- reason = "STATUS_CLOUD_FILE_IN_USE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_PINNED:
+- reason = "STATUS_CLOUD_FILE_PINNED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_REQUEST_ABORTED:
+- reason = "STATUS_CLOUD_FILE_REQUEST_ABORTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_PROPERTY_CORRUPT:
+- reason = "STATUS_CLOUD_FILE_PROPERTY_CORRUPT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_ACCESS_DENIED:
+- reason = "STATUS_CLOUD_FILE_ACCESS_DENIED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_INCOMPATIBLE_HARDLINKS:
+- reason = "STATUS_CLOUD_FILE_INCOMPATIBLE_HARDLINKS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_PROPERTY_LOCK_CONFLICT:
+- reason = "STATUS_CLOUD_FILE_PROPERTY_LOCK_CONFLICT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_REQUEST_CANCELED:
+- reason = "STATUS_CLOUD_FILE_REQUEST_CANCELED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_PROVIDER_TERMINATED:
+- reason = "STATUS_CLOUD_FILE_PROVIDER_TERMINATED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NOT_A_CLOUD_SYNC_ROOT:
+- reason = "STATUS_NOT_A_CLOUD_SYNC_ROOT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_REQUEST_TIMEOUT:
+- reason = "STATUS_CLOUD_FILE_REQUEST_TIMEOUT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_DEHYDRATION_DISALLOWED:
+- reason = "STATUS_CLOUD_FILE_DEHYDRATION_DISALLOWED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FILE_SNAP_IN_PROGRESS:
+- reason = "STATUS_FILE_SNAP_IN_PROGRESS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FILE_SNAP_USER_SECTION_NOT_SUPPORTED:
+- reason = "STATUS_FILE_SNAP_USER_SECTION_NOT_SUPPORTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FILE_SNAP_MODIFY_NOT_SUPPORTED:
+- reason = "STATUS_FILE_SNAP_MODIFY_NOT_SUPPORTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FILE_SNAP_IO_NOT_COORDINATED:
+- reason = "STATUS_FILE_SNAP_IO_NOT_COORDINATED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FILE_SNAP_UNEXPECTED_ERROR:
+- reason = "STATUS_FILE_SNAP_UNEXPECTED_ERROR";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FILE_SNAP_INVALID_PARAMETER:
+- reason = "STATUS_FILE_SNAP_INVALID_PARAMETER";
+- break;
+- case MD_NTSTATUS_WIN_DBG_NO_STATE_CHANGE:
+- reason = "DBG_NO_STATE_CHANGE";
+- break;
+- case MD_NTSTATUS_WIN_DBG_APP_NOT_IDLE:
+- reason = "DBG_APP_NOT_IDLE";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_INVALID_STRING_BINDING:
+- reason = "RPC_NT_INVALID_STRING_BINDING";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_WRONG_KIND_OF_BINDING:
+- reason = "RPC_NT_WRONG_KIND_OF_BINDING";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_INVALID_BINDING:
+- reason = "RPC_NT_INVALID_BINDING";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_PROTSEQ_NOT_SUPPORTED:
+- reason = "RPC_NT_PROTSEQ_NOT_SUPPORTED";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_INVALID_RPC_PROTSEQ:
+- reason = "RPC_NT_INVALID_RPC_PROTSEQ";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_INVALID_STRING_UUID:
+- reason = "RPC_NT_INVALID_STRING_UUID";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_INVALID_ENDPOINT_FORMAT:
+- reason = "RPC_NT_INVALID_ENDPOINT_FORMAT";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_INVALID_NET_ADDR:
+- reason = "RPC_NT_INVALID_NET_ADDR";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_NO_ENDPOINT_FOUND:
+- reason = "RPC_NT_NO_ENDPOINT_FOUND";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_INVALID_TIMEOUT:
+- reason = "RPC_NT_INVALID_TIMEOUT";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_OBJECT_NOT_FOUND:
+- reason = "RPC_NT_OBJECT_NOT_FOUND";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_ALREADY_REGISTERED:
+- reason = "RPC_NT_ALREADY_REGISTERED";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_TYPE_ALREADY_REGISTERED:
+- reason = "RPC_NT_TYPE_ALREADY_REGISTERED";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_ALREADY_LISTENING:
+- reason = "RPC_NT_ALREADY_LISTENING";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_NO_PROTSEQS_REGISTERED:
+- reason = "RPC_NT_NO_PROTSEQS_REGISTERED";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_NOT_LISTENING:
+- reason = "RPC_NT_NOT_LISTENING";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_UNKNOWN_MGR_TYPE:
+- reason = "RPC_NT_UNKNOWN_MGR_TYPE";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_UNKNOWN_IF:
+- reason = "RPC_NT_UNKNOWN_IF";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_NO_BINDINGS:
+- reason = "RPC_NT_NO_BINDINGS";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_NO_PROTSEQS:
+- reason = "RPC_NT_NO_PROTSEQS";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_CANT_CREATE_ENDPOINT:
+- reason = "RPC_NT_CANT_CREATE_ENDPOINT";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_OUT_OF_RESOURCES:
+- reason = "RPC_NT_OUT_OF_RESOURCES";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_SERVER_UNAVAILABLE:
+- reason = "RPC_NT_SERVER_UNAVAILABLE";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_SERVER_TOO_BUSY:
+- reason = "RPC_NT_SERVER_TOO_BUSY";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_INVALID_NETWORK_OPTIONS:
+- reason = "RPC_NT_INVALID_NETWORK_OPTIONS";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_NO_CALL_ACTIVE:
+- reason = "RPC_NT_NO_CALL_ACTIVE";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_CALL_FAILED:
+- reason = "RPC_NT_CALL_FAILED";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_CALL_FAILED_DNE:
+- reason = "RPC_NT_CALL_FAILED_DNE";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_PROTOCOL_ERROR:
+- reason = "RPC_NT_PROTOCOL_ERROR";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_UNSUPPORTED_TRANS_SYN:
+- reason = "RPC_NT_UNSUPPORTED_TRANS_SYN";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_UNSUPPORTED_TYPE:
+- reason = "RPC_NT_UNSUPPORTED_TYPE";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_INVALID_TAG:
+- reason = "RPC_NT_INVALID_TAG";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_INVALID_BOUND:
+- reason = "RPC_NT_INVALID_BOUND";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_NO_ENTRY_NAME:
+- reason = "RPC_NT_NO_ENTRY_NAME";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_INVALID_NAME_SYNTAX:
+- reason = "RPC_NT_INVALID_NAME_SYNTAX";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_UNSUPPORTED_NAME_SYNTAX:
+- reason = "RPC_NT_UNSUPPORTED_NAME_SYNTAX";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_UUID_NO_ADDRESS:
+- reason = "RPC_NT_UUID_NO_ADDRESS";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_DUPLICATE_ENDPOINT:
+- reason = "RPC_NT_DUPLICATE_ENDPOINT";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_UNKNOWN_AUTHN_TYPE:
+- reason = "RPC_NT_UNKNOWN_AUTHN_TYPE";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_MAX_CALLS_TOO_SMALL:
+- reason = "RPC_NT_MAX_CALLS_TOO_SMALL";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_STRING_TOO_LONG:
+- reason = "RPC_NT_STRING_TOO_LONG";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_PROTSEQ_NOT_FOUND:
+- reason = "RPC_NT_PROTSEQ_NOT_FOUND";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_PROCNUM_OUT_OF_RANGE:
+- reason = "RPC_NT_PROCNUM_OUT_OF_RANGE";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_BINDING_HAS_NO_AUTH:
+- reason = "RPC_NT_BINDING_HAS_NO_AUTH";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_UNKNOWN_AUTHN_SERVICE:
+- reason = "RPC_NT_UNKNOWN_AUTHN_SERVICE";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_UNKNOWN_AUTHN_LEVEL:
+- reason = "RPC_NT_UNKNOWN_AUTHN_LEVEL";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_INVALID_AUTH_IDENTITY:
+- reason = "RPC_NT_INVALID_AUTH_IDENTITY";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_UNKNOWN_AUTHZ_SERVICE:
+- reason = "RPC_NT_UNKNOWN_AUTHZ_SERVICE";
+- break;
+- case MD_NTSTATUS_WIN_EPT_NT_INVALID_ENTRY:
+- reason = "EPT_NT_INVALID_ENTRY";
+- break;
+- case MD_NTSTATUS_WIN_EPT_NT_CANT_PERFORM_OP:
+- reason = "EPT_NT_CANT_PERFORM_OP";
+- break;
+- case MD_NTSTATUS_WIN_EPT_NT_NOT_REGISTERED:
+- reason = "EPT_NT_NOT_REGISTERED";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_NOTHING_TO_EXPORT:
+- reason = "RPC_NT_NOTHING_TO_EXPORT";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_INCOMPLETE_NAME:
+- reason = "RPC_NT_INCOMPLETE_NAME";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_INVALID_VERS_OPTION:
+- reason = "RPC_NT_INVALID_VERS_OPTION";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_NO_MORE_MEMBERS:
+- reason = "RPC_NT_NO_MORE_MEMBERS";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_NOT_ALL_OBJS_UNEXPORTED:
+- reason = "RPC_NT_NOT_ALL_OBJS_UNEXPORTED";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_INTERFACE_NOT_FOUND:
+- reason = "RPC_NT_INTERFACE_NOT_FOUND";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_ENTRY_ALREADY_EXISTS:
+- reason = "RPC_NT_ENTRY_ALREADY_EXISTS";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_ENTRY_NOT_FOUND:
+- reason = "RPC_NT_ENTRY_NOT_FOUND";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_NAME_SERVICE_UNAVAILABLE:
+- reason = "RPC_NT_NAME_SERVICE_UNAVAILABLE";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_INVALID_NAF_ID:
+- reason = "RPC_NT_INVALID_NAF_ID";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_CANNOT_SUPPORT:
+- reason = "RPC_NT_CANNOT_SUPPORT";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_NO_CONTEXT_AVAILABLE:
+- reason = "RPC_NT_NO_CONTEXT_AVAILABLE";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_INTERNAL_ERROR:
+- reason = "RPC_NT_INTERNAL_ERROR";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_ZERO_DIVIDE:
+- reason = "RPC_NT_ZERO_DIVIDE";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_ADDRESS_ERROR:
+- reason = "RPC_NT_ADDRESS_ERROR";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_FP_DIV_ZERO:
+- reason = "RPC_NT_FP_DIV_ZERO";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_FP_UNDERFLOW:
+- reason = "RPC_NT_FP_UNDERFLOW";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_FP_OVERFLOW:
+- reason = "RPC_NT_FP_OVERFLOW";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_CALL_IN_PROGRESS:
+- reason = "RPC_NT_CALL_IN_PROGRESS";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_NO_MORE_BINDINGS:
+- reason = "RPC_NT_NO_MORE_BINDINGS";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_GROUP_MEMBER_NOT_FOUND:
+- reason = "RPC_NT_GROUP_MEMBER_NOT_FOUND";
+- break;
+- case MD_NTSTATUS_WIN_EPT_NT_CANT_CREATE:
+- reason = "EPT_NT_CANT_CREATE";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_INVALID_OBJECT:
+- reason = "RPC_NT_INVALID_OBJECT";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_NO_INTERFACES:
+- reason = "RPC_NT_NO_INTERFACES";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_CALL_CANCELLED:
+- reason = "RPC_NT_CALL_CANCELLED";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_BINDING_INCOMPLETE:
+- reason = "RPC_NT_BINDING_INCOMPLETE";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_COMM_FAILURE:
+- reason = "RPC_NT_COMM_FAILURE";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_UNSUPPORTED_AUTHN_LEVEL:
+- reason = "RPC_NT_UNSUPPORTED_AUTHN_LEVEL";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_NO_PRINC_NAME:
+- reason = "RPC_NT_NO_PRINC_NAME";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_NOT_RPC_ERROR:
+- reason = "RPC_NT_NOT_RPC_ERROR";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_SEC_PKG_ERROR:
+- reason = "RPC_NT_SEC_PKG_ERROR";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_NOT_CANCELLED:
+- reason = "RPC_NT_NOT_CANCELLED";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_INVALID_ASYNC_HANDLE:
+- reason = "RPC_NT_INVALID_ASYNC_HANDLE";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_INVALID_ASYNC_CALL:
+- reason = "RPC_NT_INVALID_ASYNC_CALL";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_PROXY_ACCESS_DENIED:
+- reason = "RPC_NT_PROXY_ACCESS_DENIED";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_COOKIE_AUTH_FAILED:
+- reason = "RPC_NT_COOKIE_AUTH_FAILED";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_NO_MORE_ENTRIES:
+- reason = "RPC_NT_NO_MORE_ENTRIES";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_SS_CHAR_TRANS_OPEN_FAIL:
+- reason = "RPC_NT_SS_CHAR_TRANS_OPEN_FAIL";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_SS_CHAR_TRANS_SHORT_FILE:
+- reason = "RPC_NT_SS_CHAR_TRANS_SHORT_FILE";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_SS_IN_NULL_CONTEXT:
+- reason = "RPC_NT_SS_IN_NULL_CONTEXT";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_SS_CONTEXT_MISMATCH:
+- reason = "RPC_NT_SS_CONTEXT_MISMATCH";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_SS_CONTEXT_DAMAGED:
+- reason = "RPC_NT_SS_CONTEXT_DAMAGED";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_SS_HANDLES_MISMATCH:
+- reason = "RPC_NT_SS_HANDLES_MISMATCH";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_SS_CANNOT_GET_CALL_HANDLE:
+- reason = "RPC_NT_SS_CANNOT_GET_CALL_HANDLE";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_NULL_REF_POINTER:
+- reason = "RPC_NT_NULL_REF_POINTER";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_ENUM_VALUE_OUT_OF_RANGE:
+- reason = "RPC_NT_ENUM_VALUE_OUT_OF_RANGE";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_BYTE_COUNT_TOO_SMALL:
+- reason = "RPC_NT_BYTE_COUNT_TOO_SMALL";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_BAD_STUB_DATA:
+- reason = "RPC_NT_BAD_STUB_DATA";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_INVALID_ES_ACTION:
+- reason = "RPC_NT_INVALID_ES_ACTION";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_WRONG_ES_VERSION:
+- reason = "RPC_NT_WRONG_ES_VERSION";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_WRONG_STUB_VERSION:
+- reason = "RPC_NT_WRONG_STUB_VERSION";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_INVALID_PIPE_OBJECT:
+- reason = "RPC_NT_INVALID_PIPE_OBJECT";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_INVALID_PIPE_OPERATION:
+- reason = "RPC_NT_INVALID_PIPE_OPERATION";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_WRONG_PIPE_VERSION:
+- reason = "RPC_NT_WRONG_PIPE_VERSION";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_PIPE_CLOSED:
+- reason = "RPC_NT_PIPE_CLOSED";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_PIPE_DISCIPLINE_ERROR:
+- reason = "RPC_NT_PIPE_DISCIPLINE_ERROR";
+- break;
+- case MD_NTSTATUS_WIN_RPC_NT_PIPE_EMPTY:
+- reason = "RPC_NT_PIPE_EMPTY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PNP_BAD_MPS_TABLE:
+- reason = "STATUS_PNP_BAD_MPS_TABLE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PNP_TRANSLATION_FAILED:
+- reason = "STATUS_PNP_TRANSLATION_FAILED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PNP_IRQ_TRANSLATION_FAILED:
+- reason = "STATUS_PNP_IRQ_TRANSLATION_FAILED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PNP_INVALID_ID:
+- reason = "STATUS_PNP_INVALID_ID";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_IO_REISSUE_AS_CACHED:
+- reason = "STATUS_IO_REISSUE_AS_CACHED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CTX_WINSTATION_NAME_INVALID:
+- reason = "STATUS_CTX_WINSTATION_NAME_INVALID";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CTX_INVALID_PD:
+- reason = "STATUS_CTX_INVALID_PD";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CTX_PD_NOT_FOUND:
+- reason = "STATUS_CTX_PD_NOT_FOUND";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CTX_CLOSE_PENDING:
+- reason = "STATUS_CTX_CLOSE_PENDING";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CTX_NO_OUTBUF:
+- reason = "STATUS_CTX_NO_OUTBUF";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CTX_MODEM_INF_NOT_FOUND:
+- reason = "STATUS_CTX_MODEM_INF_NOT_FOUND";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CTX_INVALID_MODEMNAME:
+- reason = "STATUS_CTX_INVALID_MODEMNAME";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CTX_RESPONSE_ERROR:
+- reason = "STATUS_CTX_RESPONSE_ERROR";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CTX_MODEM_RESPONSE_TIMEOUT:
+- reason = "STATUS_CTX_MODEM_RESPONSE_TIMEOUT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CTX_MODEM_RESPONSE_NO_CARRIER:
+- reason = "STATUS_CTX_MODEM_RESPONSE_NO_CARRIER";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CTX_MODEM_RESPONSE_NO_DIALTONE:
+- reason = "STATUS_CTX_MODEM_RESPONSE_NO_DIALTONE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CTX_MODEM_RESPONSE_BUSY:
+- reason = "STATUS_CTX_MODEM_RESPONSE_BUSY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CTX_MODEM_RESPONSE_VOICE:
+- reason = "STATUS_CTX_MODEM_RESPONSE_VOICE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CTX_TD_ERROR:
+- reason = "STATUS_CTX_TD_ERROR";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CTX_LICENSE_CLIENT_INVALID:
+- reason = "STATUS_CTX_LICENSE_CLIENT_INVALID";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CTX_LICENSE_NOT_AVAILABLE:
+- reason = "STATUS_CTX_LICENSE_NOT_AVAILABLE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CTX_LICENSE_EXPIRED:
+- reason = "STATUS_CTX_LICENSE_EXPIRED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CTX_WINSTATION_NOT_FOUND:
+- reason = "STATUS_CTX_WINSTATION_NOT_FOUND";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CTX_WINSTATION_NAME_COLLISION:
+- reason = "STATUS_CTX_WINSTATION_NAME_COLLISION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CTX_WINSTATION_BUSY:
+- reason = "STATUS_CTX_WINSTATION_BUSY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CTX_BAD_VIDEO_MODE:
+- reason = "STATUS_CTX_BAD_VIDEO_MODE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CTX_GRAPHICS_INVALID:
+- reason = "STATUS_CTX_GRAPHICS_INVALID";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CTX_NOT_CONSOLE:
+- reason = "STATUS_CTX_NOT_CONSOLE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CTX_CLIENT_QUERY_TIMEOUT:
+- reason = "STATUS_CTX_CLIENT_QUERY_TIMEOUT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CTX_CONSOLE_DISCONNECT:
+- reason = "STATUS_CTX_CONSOLE_DISCONNECT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CTX_CONSOLE_CONNECT:
+- reason = "STATUS_CTX_CONSOLE_CONNECT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CTX_SHADOW_DENIED:
+- reason = "STATUS_CTX_SHADOW_DENIED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CTX_WINSTATION_ACCESS_DENIED:
+- reason = "STATUS_CTX_WINSTATION_ACCESS_DENIED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CTX_INVALID_WD:
+- reason = "STATUS_CTX_INVALID_WD";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CTX_WD_NOT_FOUND:
+- reason = "STATUS_CTX_WD_NOT_FOUND";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CTX_SHADOW_INVALID:
+- reason = "STATUS_CTX_SHADOW_INVALID";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CTX_SHADOW_DISABLED:
+- reason = "STATUS_CTX_SHADOW_DISABLED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_RDP_PROTOCOL_ERROR:
+- reason = "STATUS_RDP_PROTOCOL_ERROR";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CTX_CLIENT_LICENSE_NOT_SET:
+- reason = "STATUS_CTX_CLIENT_LICENSE_NOT_SET";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CTX_CLIENT_LICENSE_IN_USE:
+- reason = "STATUS_CTX_CLIENT_LICENSE_IN_USE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CTX_SHADOW_ENDED_BY_MODE_CHANGE:
+- reason = "STATUS_CTX_SHADOW_ENDED_BY_MODE_CHANGE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CTX_SHADOW_NOT_RUNNING:
+- reason = "STATUS_CTX_SHADOW_NOT_RUNNING";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CTX_LOGON_DISABLED:
+- reason = "STATUS_CTX_LOGON_DISABLED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CTX_SECURITY_LAYER_ERROR:
+- reason = "STATUS_CTX_SECURITY_LAYER_ERROR";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TS_INCOMPATIBLE_SESSIONS:
+- reason = "STATUS_TS_INCOMPATIBLE_SESSIONS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TS_VIDEO_SUBSYSTEM_ERROR:
+- reason = "STATUS_TS_VIDEO_SUBSYSTEM_ERROR";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_MUI_FILE_NOT_FOUND:
+- reason = "STATUS_MUI_FILE_NOT_FOUND";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_MUI_INVALID_FILE:
+- reason = "STATUS_MUI_INVALID_FILE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_MUI_INVALID_RC_CONFIG:
+- reason = "STATUS_MUI_INVALID_RC_CONFIG";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_MUI_INVALID_LOCALE_NAME:
+- reason = "STATUS_MUI_INVALID_LOCALE_NAME";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_MUI_INVALID_ULTIMATEFALLBACK_NAME:
+- reason = "STATUS_MUI_INVALID_ULTIMATEFALLBACK_NAME";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_MUI_FILE_NOT_LOADED:
+- reason = "STATUS_MUI_FILE_NOT_LOADED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_RESOURCE_ENUM_USER_STOP:
+- reason = "STATUS_RESOURCE_ENUM_USER_STOP";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CLUSTER_INVALID_NODE:
+- reason = "STATUS_CLUSTER_INVALID_NODE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CLUSTER_NODE_EXISTS:
+- reason = "STATUS_CLUSTER_NODE_EXISTS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CLUSTER_JOIN_IN_PROGRESS:
+- reason = "STATUS_CLUSTER_JOIN_IN_PROGRESS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CLUSTER_NODE_NOT_FOUND:
+- reason = "STATUS_CLUSTER_NODE_NOT_FOUND";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CLUSTER_LOCAL_NODE_NOT_FOUND:
+- reason = "STATUS_CLUSTER_LOCAL_NODE_NOT_FOUND";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CLUSTER_NETWORK_EXISTS:
+- reason = "STATUS_CLUSTER_NETWORK_EXISTS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CLUSTER_NETWORK_NOT_FOUND:
+- reason = "STATUS_CLUSTER_NETWORK_NOT_FOUND";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CLUSTER_NETINTERFACE_EXISTS:
+- reason = "STATUS_CLUSTER_NETINTERFACE_EXISTS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CLUSTER_NETINTERFACE_NOT_FOUND:
+- reason = "STATUS_CLUSTER_NETINTERFACE_NOT_FOUND";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CLUSTER_INVALID_REQUEST:
+- reason = "STATUS_CLUSTER_INVALID_REQUEST";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CLUSTER_INVALID_NETWORK_PROVIDER:
+- reason = "STATUS_CLUSTER_INVALID_NETWORK_PROVIDER";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CLUSTER_NODE_DOWN:
+- reason = "STATUS_CLUSTER_NODE_DOWN";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CLUSTER_NODE_UNREACHABLE:
+- reason = "STATUS_CLUSTER_NODE_UNREACHABLE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CLUSTER_NODE_NOT_MEMBER:
+- reason = "STATUS_CLUSTER_NODE_NOT_MEMBER";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CLUSTER_JOIN_NOT_IN_PROGRESS:
+- reason = "STATUS_CLUSTER_JOIN_NOT_IN_PROGRESS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CLUSTER_INVALID_NETWORK:
+- reason = "STATUS_CLUSTER_INVALID_NETWORK";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CLUSTER_NO_NET_ADAPTERS:
+- reason = "STATUS_CLUSTER_NO_NET_ADAPTERS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CLUSTER_NODE_UP:
+- reason = "STATUS_CLUSTER_NODE_UP";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CLUSTER_NODE_PAUSED:
+- reason = "STATUS_CLUSTER_NODE_PAUSED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CLUSTER_NODE_NOT_PAUSED:
+- reason = "STATUS_CLUSTER_NODE_NOT_PAUSED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CLUSTER_NO_SECURITY_CONTEXT:
+- reason = "STATUS_CLUSTER_NO_SECURITY_CONTEXT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CLUSTER_NETWORK_NOT_INTERNAL:
+- reason = "STATUS_CLUSTER_NETWORK_NOT_INTERNAL";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CLUSTER_POISONED:
+- reason = "STATUS_CLUSTER_POISONED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CLUSTER_NON_CSV_PATH:
+- reason = "STATUS_CLUSTER_NON_CSV_PATH";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CLUSTER_CSV_VOLUME_NOT_LOCAL:
+- reason = "STATUS_CLUSTER_CSV_VOLUME_NOT_LOCAL";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CLUSTER_CSV_READ_OPLOCK_BREAK_IN_PROGRESS:
+- reason = "STATUS_CLUSTER_CSV_READ_OPLOCK_BREAK_IN_PROGRESS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CLUSTER_CSV_AUTO_PAUSE_ERROR:
+- reason = "STATUS_CLUSTER_CSV_AUTO_PAUSE_ERROR";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CLUSTER_CSV_REDIRECTED:
+- reason = "STATUS_CLUSTER_CSV_REDIRECTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CLUSTER_CSV_NOT_REDIRECTED:
+- reason = "STATUS_CLUSTER_CSV_NOT_REDIRECTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CLUSTER_CSV_VOLUME_DRAINING:
+- reason = "STATUS_CLUSTER_CSV_VOLUME_DRAINING";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CLUSTER_CSV_SNAPSHOT_CREATION_IN_PROGRESS:
+- reason = "STATUS_CLUSTER_CSV_SNAPSHOT_CREATION_IN_PROGRESS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CLUSTER_CSV_VOLUME_DRAINING_SUCCEEDED_DOWNLEVEL:
+- reason = "STATUS_CLUSTER_CSV_VOLUME_DRAINING_SUCCEEDED_DOWNLEVEL";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CLUSTER_CSV_NO_SNAPSHOTS:
+- reason = "STATUS_CLUSTER_CSV_NO_SNAPSHOTS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CSV_IO_PAUSE_TIMEOUT:
+- reason = "STATUS_CSV_IO_PAUSE_TIMEOUT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CLUSTER_CSV_INVALID_HANDLE:
+- reason = "STATUS_CLUSTER_CSV_INVALID_HANDLE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CLUSTER_CSV_SUPPORTED_ONLY_ON_COORDINATOR:
+- reason = "STATUS_CLUSTER_CSV_SUPPORTED_ONLY_ON_COORDINATOR";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CLUSTER_CAM_TICKET_REPLAY_DETECTED:
+- reason = "STATUS_CLUSTER_CAM_TICKET_REPLAY_DETECTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ACPI_INVALID_OPCODE:
+- reason = "STATUS_ACPI_INVALID_OPCODE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ACPI_STACK_OVERFLOW:
+- reason = "STATUS_ACPI_STACK_OVERFLOW";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ACPI_ASSERT_FAILED:
+- reason = "STATUS_ACPI_ASSERT_FAILED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ACPI_INVALID_INDEX:
+- reason = "STATUS_ACPI_INVALID_INDEX";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ACPI_INVALID_ARGUMENT:
+- reason = "STATUS_ACPI_INVALID_ARGUMENT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ACPI_FATAL:
+- reason = "STATUS_ACPI_FATAL";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ACPI_INVALID_SUPERNAME:
+- reason = "STATUS_ACPI_INVALID_SUPERNAME";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ACPI_INVALID_ARGTYPE:
+- reason = "STATUS_ACPI_INVALID_ARGTYPE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ACPI_INVALID_OBJTYPE:
+- reason = "STATUS_ACPI_INVALID_OBJTYPE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ACPI_INVALID_TARGETTYPE:
+- reason = "STATUS_ACPI_INVALID_TARGETTYPE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ACPI_INCORRECT_ARGUMENT_COUNT:
+- reason = "STATUS_ACPI_INCORRECT_ARGUMENT_COUNT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ACPI_ADDRESS_NOT_MAPPED:
+- reason = "STATUS_ACPI_ADDRESS_NOT_MAPPED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ACPI_INVALID_EVENTTYPE:
+- reason = "STATUS_ACPI_INVALID_EVENTTYPE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ACPI_HANDLER_COLLISION:
+- reason = "STATUS_ACPI_HANDLER_COLLISION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ACPI_INVALID_DATA:
+- reason = "STATUS_ACPI_INVALID_DATA";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ACPI_INVALID_REGION:
+- reason = "STATUS_ACPI_INVALID_REGION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ACPI_INVALID_ACCESS_SIZE:
+- reason = "STATUS_ACPI_INVALID_ACCESS_SIZE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ACPI_ACQUIRE_GLOBAL_LOCK:
+- reason = "STATUS_ACPI_ACQUIRE_GLOBAL_LOCK";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ACPI_ALREADY_INITIALIZED:
+- reason = "STATUS_ACPI_ALREADY_INITIALIZED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ACPI_NOT_INITIALIZED:
+- reason = "STATUS_ACPI_NOT_INITIALIZED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ACPI_INVALID_MUTEX_LEVEL:
+- reason = "STATUS_ACPI_INVALID_MUTEX_LEVEL";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ACPI_MUTEX_NOT_OWNED:
+- reason = "STATUS_ACPI_MUTEX_NOT_OWNED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ACPI_MUTEX_NOT_OWNER:
+- reason = "STATUS_ACPI_MUTEX_NOT_OWNER";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ACPI_RS_ACCESS:
+- reason = "STATUS_ACPI_RS_ACCESS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ACPI_INVALID_TABLE:
+- reason = "STATUS_ACPI_INVALID_TABLE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ACPI_REG_HANDLER_FAILED:
+- reason = "STATUS_ACPI_REG_HANDLER_FAILED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ACPI_POWER_REQUEST_FAILED:
+- reason = "STATUS_ACPI_POWER_REQUEST_FAILED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SXS_SECTION_NOT_FOUND:
+- reason = "STATUS_SXS_SECTION_NOT_FOUND";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SXS_CANT_GEN_ACTCTX:
+- reason = "STATUS_SXS_CANT_GEN_ACTCTX";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SXS_INVALID_ACTCTXDATA_FORMAT:
+- reason = "STATUS_SXS_INVALID_ACTCTXDATA_FORMAT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SXS_ASSEMBLY_NOT_FOUND:
+- reason = "STATUS_SXS_ASSEMBLY_NOT_FOUND";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SXS_MANIFEST_FORMAT_ERROR:
+- reason = "STATUS_SXS_MANIFEST_FORMAT_ERROR";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SXS_MANIFEST_PARSE_ERROR:
+- reason = "STATUS_SXS_MANIFEST_PARSE_ERROR";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SXS_ACTIVATION_CONTEXT_DISABLED:
+- reason = "STATUS_SXS_ACTIVATION_CONTEXT_DISABLED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SXS_KEY_NOT_FOUND:
+- reason = "STATUS_SXS_KEY_NOT_FOUND";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SXS_VERSION_CONFLICT:
+- reason = "STATUS_SXS_VERSION_CONFLICT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SXS_WRONG_SECTION_TYPE:
+- reason = "STATUS_SXS_WRONG_SECTION_TYPE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SXS_THREAD_QUERIES_DISABLED:
+- reason = "STATUS_SXS_THREAD_QUERIES_DISABLED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SXS_ASSEMBLY_MISSING:
+- reason = "STATUS_SXS_ASSEMBLY_MISSING";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SXS_PROCESS_DEFAULT_ALREADY_SET:
+- reason = "STATUS_SXS_PROCESS_DEFAULT_ALREADY_SET";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SXS_EARLY_DEACTIVATION:
+- reason = "STATUS_SXS_EARLY_DEACTIVATION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SXS_INVALID_DEACTIVATION:
+- reason = "STATUS_SXS_INVALID_DEACTIVATION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SXS_MULTIPLE_DEACTIVATION:
+- reason = "STATUS_SXS_MULTIPLE_DEACTIVATION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SXS_SYSTEM_DEFAULT_ACTIVATION_CONTEXT_EMPTY:
+- reason = "STATUS_SXS_SYSTEM_DEFAULT_ACTIVATION_CONTEXT_EMPTY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SXS_PROCESS_TERMINATION_REQUESTED:
+- reason = "STATUS_SXS_PROCESS_TERMINATION_REQUESTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SXS_CORRUPT_ACTIVATION_STACK:
+- reason = "STATUS_SXS_CORRUPT_ACTIVATION_STACK";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SXS_CORRUPTION:
+- reason = "STATUS_SXS_CORRUPTION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SXS_INVALID_IDENTITY_ATTRIBUTE_VALUE:
+- reason = "STATUS_SXS_INVALID_IDENTITY_ATTRIBUTE_VALUE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SXS_INVALID_IDENTITY_ATTRIBUTE_NAME:
+- reason = "STATUS_SXS_INVALID_IDENTITY_ATTRIBUTE_NAME";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SXS_IDENTITY_DUPLICATE_ATTRIBUTE:
+- reason = "STATUS_SXS_IDENTITY_DUPLICATE_ATTRIBUTE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SXS_IDENTITY_PARSE_ERROR:
+- reason = "STATUS_SXS_IDENTITY_PARSE_ERROR";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SXS_COMPONENT_STORE_CORRUPT:
+- reason = "STATUS_SXS_COMPONENT_STORE_CORRUPT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SXS_FILE_HASH_MISMATCH:
+- reason = "STATUS_SXS_FILE_HASH_MISMATCH";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SXS_MANIFEST_IDENTITY_SAME_BUT_CONTENTS_DIFFERENT:
+- reason = "STATUS_SXS_MANIFEST_IDENTITY_SAME_BUT_CONTENTS_DIFFERENT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SXS_IDENTITIES_DIFFERENT:
+- reason = "STATUS_SXS_IDENTITIES_DIFFERENT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SXS_ASSEMBLY_IS_NOT_A_DEPLOYMENT:
+- reason = "STATUS_SXS_ASSEMBLY_IS_NOT_A_DEPLOYMENT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SXS_FILE_NOT_PART_OF_ASSEMBLY:
+- reason = "STATUS_SXS_FILE_NOT_PART_OF_ASSEMBLY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ADVANCED_INSTALLER_FAILED:
+- reason = "STATUS_ADVANCED_INSTALLER_FAILED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_XML_ENCODING_MISMATCH:
+- reason = "STATUS_XML_ENCODING_MISMATCH";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SXS_MANIFEST_TOO_BIG:
+- reason = "STATUS_SXS_MANIFEST_TOO_BIG";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SXS_SETTING_NOT_REGISTERED:
+- reason = "STATUS_SXS_SETTING_NOT_REGISTERED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SXS_TRANSACTION_CLOSURE_INCOMPLETE:
+- reason = "STATUS_SXS_TRANSACTION_CLOSURE_INCOMPLETE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SMI_PRIMITIVE_INSTALLER_FAILED:
+- reason = "STATUS_SMI_PRIMITIVE_INSTALLER_FAILED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GENERIC_COMMAND_FAILED:
+- reason = "STATUS_GENERIC_COMMAND_FAILED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SXS_FILE_HASH_MISSING:
+- reason = "STATUS_SXS_FILE_HASH_MISSING";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TRANSACTIONAL_CONFLICT:
+- reason = "STATUS_TRANSACTIONAL_CONFLICT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INVALID_TRANSACTION:
+- reason = "STATUS_INVALID_TRANSACTION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TRANSACTION_NOT_ACTIVE:
+- reason = "STATUS_TRANSACTION_NOT_ACTIVE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TM_INITIALIZATION_FAILED:
+- reason = "STATUS_TM_INITIALIZATION_FAILED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_RM_NOT_ACTIVE:
+- reason = "STATUS_RM_NOT_ACTIVE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_RM_METADATA_CORRUPT:
+- reason = "STATUS_RM_METADATA_CORRUPT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TRANSACTION_NOT_JOINED:
+- reason = "STATUS_TRANSACTION_NOT_JOINED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_DIRECTORY_NOT_RM:
+- reason = "STATUS_DIRECTORY_NOT_RM";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TRANSACTIONS_UNSUPPORTED_REMOTE:
+- reason = "STATUS_TRANSACTIONS_UNSUPPORTED_REMOTE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_LOG_RESIZE_INVALID_SIZE:
+- reason = "STATUS_LOG_RESIZE_INVALID_SIZE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_REMOTE_FILE_VERSION_MISMATCH:
+- reason = "STATUS_REMOTE_FILE_VERSION_MISMATCH";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CRM_PROTOCOL_ALREADY_EXISTS:
+- reason = "STATUS_CRM_PROTOCOL_ALREADY_EXISTS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TRANSACTION_PROPAGATION_FAILED:
+- reason = "STATUS_TRANSACTION_PROPAGATION_FAILED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CRM_PROTOCOL_NOT_FOUND:
+- reason = "STATUS_CRM_PROTOCOL_NOT_FOUND";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TRANSACTION_SUPERIOR_EXISTS:
+- reason = "STATUS_TRANSACTION_SUPERIOR_EXISTS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TRANSACTION_REQUEST_NOT_VALID:
+- reason = "STATUS_TRANSACTION_REQUEST_NOT_VALID";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TRANSACTION_NOT_REQUESTED:
+- reason = "STATUS_TRANSACTION_NOT_REQUESTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TRANSACTION_ALREADY_ABORTED:
+- reason = "STATUS_TRANSACTION_ALREADY_ABORTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TRANSACTION_ALREADY_COMMITTED:
+- reason = "STATUS_TRANSACTION_ALREADY_COMMITTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TRANSACTION_INVALID_MARSHALL_BUFFER:
+- reason = "STATUS_TRANSACTION_INVALID_MARSHALL_BUFFER";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CURRENT_TRANSACTION_NOT_VALID:
+- reason = "STATUS_CURRENT_TRANSACTION_NOT_VALID";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_LOG_GROWTH_FAILED:
+- reason = "STATUS_LOG_GROWTH_FAILED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_OBJECT_NO_LONGER_EXISTS:
+- reason = "STATUS_OBJECT_NO_LONGER_EXISTS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_STREAM_MINIVERSION_NOT_FOUND:
+- reason = "STATUS_STREAM_MINIVERSION_NOT_FOUND";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_STREAM_MINIVERSION_NOT_VALID:
+- reason = "STATUS_STREAM_MINIVERSION_NOT_VALID";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_MINIVERSION_INACCESSIBLE_FROM_SPECIFIED_TRANSACTION:
+- reason = "STATUS_MINIVERSION_INACCESSIBLE_FROM_SPECIFIED_TRANSACTION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CANT_OPEN_MINIVERSION_WITH_MODIFY_INTENT:
+- reason = "STATUS_CANT_OPEN_MINIVERSION_WITH_MODIFY_INTENT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CANT_CREATE_MORE_STREAM_MINIVERSIONS:
+- reason = "STATUS_CANT_CREATE_MORE_STREAM_MINIVERSIONS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_HANDLE_NO_LONGER_VALID:
+- reason = "STATUS_HANDLE_NO_LONGER_VALID";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_LOG_CORRUPTION_DETECTED:
+- reason = "STATUS_LOG_CORRUPTION_DETECTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_RM_DISCONNECTED:
+- reason = "STATUS_RM_DISCONNECTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ENLISTMENT_NOT_SUPERIOR:
+- reason = "STATUS_ENLISTMENT_NOT_SUPERIOR";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FILE_IDENTITY_NOT_PERSISTENT:
+- reason = "STATUS_FILE_IDENTITY_NOT_PERSISTENT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CANT_BREAK_TRANSACTIONAL_DEPENDENCY:
+- reason = "STATUS_CANT_BREAK_TRANSACTIONAL_DEPENDENCY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CANT_CROSS_RM_BOUNDARY:
+- reason = "STATUS_CANT_CROSS_RM_BOUNDARY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TXF_DIR_NOT_EMPTY:
+- reason = "STATUS_TXF_DIR_NOT_EMPTY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_INDOUBT_TRANSACTIONS_EXIST:
+- reason = "STATUS_INDOUBT_TRANSACTIONS_EXIST";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TM_VOLATILE:
+- reason = "STATUS_TM_VOLATILE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ROLLBACK_TIMER_EXPIRED:
+- reason = "STATUS_ROLLBACK_TIMER_EXPIRED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TXF_ATTRIBUTE_CORRUPT:
+- reason = "STATUS_TXF_ATTRIBUTE_CORRUPT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_EFS_NOT_ALLOWED_IN_TRANSACTION:
+- reason = "STATUS_EFS_NOT_ALLOWED_IN_TRANSACTION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TRANSACTIONAL_OPEN_NOT_ALLOWED:
+- reason = "STATUS_TRANSACTIONAL_OPEN_NOT_ALLOWED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TRANSACTED_MAPPING_UNSUPPORTED_REMOTE:
+- reason = "STATUS_TRANSACTED_MAPPING_UNSUPPORTED_REMOTE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TRANSACTION_REQUIRED_PROMOTION:
+- reason = "STATUS_TRANSACTION_REQUIRED_PROMOTION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CANNOT_EXECUTE_FILE_IN_TRANSACTION:
+- reason = "STATUS_CANNOT_EXECUTE_FILE_IN_TRANSACTION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TRANSACTIONS_NOT_FROZEN:
+- reason = "STATUS_TRANSACTIONS_NOT_FROZEN";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TRANSACTION_FREEZE_IN_PROGRESS:
+- reason = "STATUS_TRANSACTION_FREEZE_IN_PROGRESS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NOT_SNAPSHOT_VOLUME:
+- reason = "STATUS_NOT_SNAPSHOT_VOLUME";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NO_SAVEPOINT_WITH_OPEN_FILES:
+- reason = "STATUS_NO_SAVEPOINT_WITH_OPEN_FILES";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SPARSE_NOT_ALLOWED_IN_TRANSACTION:
+- reason = "STATUS_SPARSE_NOT_ALLOWED_IN_TRANSACTION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TM_IDENTITY_MISMATCH:
+- reason = "STATUS_TM_IDENTITY_MISMATCH";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FLOATED_SECTION:
+- reason = "STATUS_FLOATED_SECTION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CANNOT_ACCEPT_TRANSACTED_WORK:
+- reason = "STATUS_CANNOT_ACCEPT_TRANSACTED_WORK";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CANNOT_ABORT_TRANSACTIONS:
+- reason = "STATUS_CANNOT_ABORT_TRANSACTIONS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TRANSACTION_NOT_FOUND:
+- reason = "STATUS_TRANSACTION_NOT_FOUND";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_RESOURCEMANAGER_NOT_FOUND:
+- reason = "STATUS_RESOURCEMANAGER_NOT_FOUND";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_ENLISTMENT_NOT_FOUND:
+- reason = "STATUS_ENLISTMENT_NOT_FOUND";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TRANSACTIONMANAGER_NOT_FOUND:
+- reason = "STATUS_TRANSACTIONMANAGER_NOT_FOUND";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TRANSACTIONMANAGER_NOT_ONLINE:
+- reason = "STATUS_TRANSACTIONMANAGER_NOT_ONLINE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TRANSACTIONMANAGER_RECOVERY_NAME_COLLISION:
+- reason = "STATUS_TRANSACTIONMANAGER_RECOVERY_NAME_COLLISION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TRANSACTION_NOT_ROOT:
+- reason = "STATUS_TRANSACTION_NOT_ROOT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TRANSACTION_OBJECT_EXPIRED:
+- reason = "STATUS_TRANSACTION_OBJECT_EXPIRED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_COMPRESSION_NOT_ALLOWED_IN_TRANSACTION:
+- reason = "STATUS_COMPRESSION_NOT_ALLOWED_IN_TRANSACTION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TRANSACTION_RESPONSE_NOT_ENLISTED:
+- reason = "STATUS_TRANSACTION_RESPONSE_NOT_ENLISTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TRANSACTION_RECORD_TOO_LONG:
+- reason = "STATUS_TRANSACTION_RECORD_TOO_LONG";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NO_LINK_TRACKING_IN_TRANSACTION:
+- reason = "STATUS_NO_LINK_TRACKING_IN_TRANSACTION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_OPERATION_NOT_SUPPORTED_IN_TRANSACTION:
+- reason = "STATUS_OPERATION_NOT_SUPPORTED_IN_TRANSACTION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TRANSACTION_INTEGRITY_VIOLATED:
+- reason = "STATUS_TRANSACTION_INTEGRITY_VIOLATED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TRANSACTIONMANAGER_IDENTITY_MISMATCH:
+- reason = "STATUS_TRANSACTIONMANAGER_IDENTITY_MISMATCH";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_RM_CANNOT_BE_FROZEN_FOR_SNAPSHOT:
+- reason = "STATUS_RM_CANNOT_BE_FROZEN_FOR_SNAPSHOT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TRANSACTION_MUST_WRITETHROUGH:
+- reason = "STATUS_TRANSACTION_MUST_WRITETHROUGH";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TRANSACTION_NO_SUPERIOR:
+- reason = "STATUS_TRANSACTION_NO_SUPERIOR";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_EXPIRED_HANDLE:
+- reason = "STATUS_EXPIRED_HANDLE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TRANSACTION_NOT_ENLISTED:
+- reason = "STATUS_TRANSACTION_NOT_ENLISTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_LOG_SECTOR_INVALID:
+- reason = "STATUS_LOG_SECTOR_INVALID";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_LOG_SECTOR_PARITY_INVALID:
+- reason = "STATUS_LOG_SECTOR_PARITY_INVALID";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_LOG_SECTOR_REMAPPED:
+- reason = "STATUS_LOG_SECTOR_REMAPPED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_LOG_BLOCK_INCOMPLETE:
+- reason = "STATUS_LOG_BLOCK_INCOMPLETE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_LOG_INVALID_RANGE:
+- reason = "STATUS_LOG_INVALID_RANGE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_LOG_BLOCKS_EXHAUSTED:
+- reason = "STATUS_LOG_BLOCKS_EXHAUSTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_LOG_READ_CONTEXT_INVALID:
+- reason = "STATUS_LOG_READ_CONTEXT_INVALID";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_LOG_RESTART_INVALID:
+- reason = "STATUS_LOG_RESTART_INVALID";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_LOG_BLOCK_VERSION:
+- reason = "STATUS_LOG_BLOCK_VERSION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_LOG_BLOCK_INVALID:
+- reason = "STATUS_LOG_BLOCK_INVALID";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_LOG_READ_MODE_INVALID:
+- reason = "STATUS_LOG_READ_MODE_INVALID";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_LOG_METADATA_CORRUPT:
+- reason = "STATUS_LOG_METADATA_CORRUPT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_LOG_METADATA_INVALID:
+- reason = "STATUS_LOG_METADATA_INVALID";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_LOG_METADATA_INCONSISTENT:
+- reason = "STATUS_LOG_METADATA_INCONSISTENT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_LOG_RESERVATION_INVALID:
+- reason = "STATUS_LOG_RESERVATION_INVALID";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_LOG_CANT_DELETE:
+- reason = "STATUS_LOG_CANT_DELETE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_LOG_CONTAINER_LIMIT_EXCEEDED:
+- reason = "STATUS_LOG_CONTAINER_LIMIT_EXCEEDED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_LOG_START_OF_LOG:
+- reason = "STATUS_LOG_START_OF_LOG";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_LOG_POLICY_ALREADY_INSTALLED:
+- reason = "STATUS_LOG_POLICY_ALREADY_INSTALLED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_LOG_POLICY_NOT_INSTALLED:
+- reason = "STATUS_LOG_POLICY_NOT_INSTALLED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_LOG_POLICY_INVALID:
+- reason = "STATUS_LOG_POLICY_INVALID";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_LOG_POLICY_CONFLICT:
+- reason = "STATUS_LOG_POLICY_CONFLICT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_LOG_PINNED_ARCHIVE_TAIL:
+- reason = "STATUS_LOG_PINNED_ARCHIVE_TAIL";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_LOG_RECORD_NONEXISTENT:
+- reason = "STATUS_LOG_RECORD_NONEXISTENT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_LOG_RECORDS_RESERVED_INVALID:
+- reason = "STATUS_LOG_RECORDS_RESERVED_INVALID";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_LOG_SPACE_RESERVED_INVALID:
+- reason = "STATUS_LOG_SPACE_RESERVED_INVALID";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_LOG_TAIL_INVALID:
+- reason = "STATUS_LOG_TAIL_INVALID";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_LOG_FULL:
+- reason = "STATUS_LOG_FULL";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_LOG_MULTIPLEXED:
+- reason = "STATUS_LOG_MULTIPLEXED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_LOG_DEDICATED:
+- reason = "STATUS_LOG_DEDICATED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_LOG_ARCHIVE_NOT_IN_PROGRESS:
+- reason = "STATUS_LOG_ARCHIVE_NOT_IN_PROGRESS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_LOG_ARCHIVE_IN_PROGRESS:
+- reason = "STATUS_LOG_ARCHIVE_IN_PROGRESS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_LOG_EPHEMERAL:
+- reason = "STATUS_LOG_EPHEMERAL";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_LOG_NOT_ENOUGH_CONTAINERS:
+- reason = "STATUS_LOG_NOT_ENOUGH_CONTAINERS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_LOG_CLIENT_ALREADY_REGISTERED:
+- reason = "STATUS_LOG_CLIENT_ALREADY_REGISTERED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_LOG_CLIENT_NOT_REGISTERED:
+- reason = "STATUS_LOG_CLIENT_NOT_REGISTERED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_LOG_FULL_HANDLER_IN_PROGRESS:
+- reason = "STATUS_LOG_FULL_HANDLER_IN_PROGRESS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_LOG_CONTAINER_READ_FAILED:
+- reason = "STATUS_LOG_CONTAINER_READ_FAILED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_LOG_CONTAINER_WRITE_FAILED:
+- reason = "STATUS_LOG_CONTAINER_WRITE_FAILED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_LOG_CONTAINER_OPEN_FAILED:
+- reason = "STATUS_LOG_CONTAINER_OPEN_FAILED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_LOG_CONTAINER_STATE_INVALID:
+- reason = "STATUS_LOG_CONTAINER_STATE_INVALID";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_LOG_STATE_INVALID:
+- reason = "STATUS_LOG_STATE_INVALID";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_LOG_PINNED:
+- reason = "STATUS_LOG_PINNED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_LOG_METADATA_FLUSH_FAILED:
+- reason = "STATUS_LOG_METADATA_FLUSH_FAILED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_LOG_INCONSISTENT_SECURITY:
+- reason = "STATUS_LOG_INCONSISTENT_SECURITY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_LOG_APPENDED_FLUSH_FAILED:
+- reason = "STATUS_LOG_APPENDED_FLUSH_FAILED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_LOG_PINNED_RESERVATION:
+- reason = "STATUS_LOG_PINNED_RESERVATION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VIDEO_HUNG_DISPLAY_DRIVER_THREAD:
+- reason = "STATUS_VIDEO_HUNG_DISPLAY_DRIVER_THREAD";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FLT_NO_HANDLER_DEFINED:
+- reason = "STATUS_FLT_NO_HANDLER_DEFINED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FLT_CONTEXT_ALREADY_DEFINED:
+- reason = "STATUS_FLT_CONTEXT_ALREADY_DEFINED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FLT_INVALID_ASYNCHRONOUS_REQUEST:
+- reason = "STATUS_FLT_INVALID_ASYNCHRONOUS_REQUEST";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FLT_DISALLOW_FAST_IO:
+- reason = "STATUS_FLT_DISALLOW_FAST_IO";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FLT_INVALID_NAME_REQUEST:
+- reason = "STATUS_FLT_INVALID_NAME_REQUEST";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FLT_NOT_SAFE_TO_POST_OPERATION:
+- reason = "STATUS_FLT_NOT_SAFE_TO_POST_OPERATION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FLT_NOT_INITIALIZED:
+- reason = "STATUS_FLT_NOT_INITIALIZED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FLT_FILTER_NOT_READY:
+- reason = "STATUS_FLT_FILTER_NOT_READY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FLT_POST_OPERATION_CLEANUP:
+- reason = "STATUS_FLT_POST_OPERATION_CLEANUP";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FLT_INTERNAL_ERROR:
+- reason = "STATUS_FLT_INTERNAL_ERROR";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FLT_DELETING_OBJECT:
+- reason = "STATUS_FLT_DELETING_OBJECT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FLT_MUST_BE_NONPAGED_POOL:
+- reason = "STATUS_FLT_MUST_BE_NONPAGED_POOL";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FLT_DUPLICATE_ENTRY:
+- reason = "STATUS_FLT_DUPLICATE_ENTRY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FLT_CBDQ_DISABLED:
+- reason = "STATUS_FLT_CBDQ_DISABLED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FLT_DO_NOT_ATTACH:
+- reason = "STATUS_FLT_DO_NOT_ATTACH";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FLT_DO_NOT_DETACH:
+- reason = "STATUS_FLT_DO_NOT_DETACH";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FLT_INSTANCE_ALTITUDE_COLLISION:
+- reason = "STATUS_FLT_INSTANCE_ALTITUDE_COLLISION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FLT_INSTANCE_NAME_COLLISION:
+- reason = "STATUS_FLT_INSTANCE_NAME_COLLISION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FLT_FILTER_NOT_FOUND:
+- reason = "STATUS_FLT_FILTER_NOT_FOUND";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FLT_VOLUME_NOT_FOUND:
+- reason = "STATUS_FLT_VOLUME_NOT_FOUND";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FLT_INSTANCE_NOT_FOUND:
+- reason = "STATUS_FLT_INSTANCE_NOT_FOUND";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FLT_CONTEXT_ALLOCATION_NOT_FOUND:
+- reason = "STATUS_FLT_CONTEXT_ALLOCATION_NOT_FOUND";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FLT_INVALID_CONTEXT_REGISTRATION:
+- reason = "STATUS_FLT_INVALID_CONTEXT_REGISTRATION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FLT_NAME_CACHE_MISS:
+- reason = "STATUS_FLT_NAME_CACHE_MISS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FLT_NO_DEVICE_OBJECT:
+- reason = "STATUS_FLT_NO_DEVICE_OBJECT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FLT_VOLUME_ALREADY_MOUNTED:
+- reason = "STATUS_FLT_VOLUME_ALREADY_MOUNTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FLT_ALREADY_ENLISTED:
+- reason = "STATUS_FLT_ALREADY_ENLISTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FLT_CONTEXT_ALREADY_LINKED:
+- reason = "STATUS_FLT_CONTEXT_ALREADY_LINKED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FLT_NO_WAITER_FOR_REPLY:
+- reason = "STATUS_FLT_NO_WAITER_FOR_REPLY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FLT_REGISTRATION_BUSY:
+- reason = "STATUS_FLT_REGISTRATION_BUSY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_MONITOR_NO_DESCRIPTOR:
+- reason = "STATUS_MONITOR_NO_DESCRIPTOR";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_MONITOR_UNKNOWN_DESCRIPTOR_FORMAT:
+- reason = "STATUS_MONITOR_UNKNOWN_DESCRIPTOR_FORMAT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_MONITOR_INVALID_DESCRIPTOR_CHECKSUM:
+- reason = "STATUS_MONITOR_INVALID_DESCRIPTOR_CHECKSUM";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_MONITOR_INVALID_STANDARD_TIMING_BLOCK:
+- reason = "STATUS_MONITOR_INVALID_STANDARD_TIMING_BLOCK";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_MONITOR_WMI_DATABLOCK_REGISTRATION_FAILED:
+- reason = "STATUS_MONITOR_WMI_DATABLOCK_REGISTRATION_FAILED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_MONITOR_INVALID_SERIAL_NUMBER_MONDSC_BLOCK:
+- reason = "STATUS_MONITOR_INVALID_SERIAL_NUMBER_MONDSC_BLOCK";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_MONITOR_INVALID_USER_FRIENDLY_MONDSC_BLOCK:
+- reason = "STATUS_MONITOR_INVALID_USER_FRIENDLY_MONDSC_BLOCK";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_MONITOR_NO_MORE_DESCRIPTOR_DATA:
+- reason = "STATUS_MONITOR_NO_MORE_DESCRIPTOR_DATA";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_MONITOR_INVALID_DETAILED_TIMING_BLOCK:
+- reason = "STATUS_MONITOR_INVALID_DETAILED_TIMING_BLOCK";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_MONITOR_INVALID_MANUFACTURE_DATE:
+- reason = "STATUS_MONITOR_INVALID_MANUFACTURE_DATE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_NOT_EXCLUSIVE_MODE_OWNER:
+- reason = "STATUS_GRAPHICS_NOT_EXCLUSIVE_MODE_OWNER";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER:
+- reason = "STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_DISPLAY_ADAPTER:
+- reason = "STATUS_GRAPHICS_INVALID_DISPLAY_ADAPTER";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_ADAPTER_WAS_RESET:
+- reason = "STATUS_GRAPHICS_ADAPTER_WAS_RESET";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_DRIVER_MODEL:
+- reason = "STATUS_GRAPHICS_INVALID_DRIVER_MODEL";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_PRESENT_MODE_CHANGED:
+- reason = "STATUS_GRAPHICS_PRESENT_MODE_CHANGED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_PRESENT_OCCLUDED:
+- reason = "STATUS_GRAPHICS_PRESENT_OCCLUDED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_PRESENT_DENIED:
+- reason = "STATUS_GRAPHICS_PRESENT_DENIED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_CANNOTCOLORCONVERT:
+- reason = "STATUS_GRAPHICS_CANNOTCOLORCONVERT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_DRIVER_MISMATCH:
+- reason = "STATUS_GRAPHICS_DRIVER_MISMATCH";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_PRESENT_REDIRECTION_DISABLED:
+- reason = "STATUS_GRAPHICS_PRESENT_REDIRECTION_DISABLED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_PRESENT_UNOCCLUDED:
+- reason = "STATUS_GRAPHICS_PRESENT_UNOCCLUDED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_WINDOWDC_NOT_AVAILABLE:
+- reason = "STATUS_GRAPHICS_WINDOWDC_NOT_AVAILABLE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_WINDOWLESS_PRESENT_DISABLED:
+- reason = "STATUS_GRAPHICS_WINDOWLESS_PRESENT_DISABLED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_PRESENT_INVALID_WINDOW:
+- reason = "STATUS_GRAPHICS_PRESENT_INVALID_WINDOW";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_PRESENT_BUFFER_NOT_BOUND:
+- reason = "STATUS_GRAPHICS_PRESENT_BUFFER_NOT_BOUND";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_VAIL_STATE_CHANGED:
+- reason = "STATUS_GRAPHICS_VAIL_STATE_CHANGED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INDIRECT_DISPLAY_ABANDON_SWAPCHAIN:
+- reason = "STATUS_GRAPHICS_INDIRECT_DISPLAY_ABANDON_SWAPCHAIN";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INDIRECT_DISPLAY_DEVICE_STOPPED:
+- reason = "STATUS_GRAPHICS_INDIRECT_DISPLAY_DEVICE_STOPPED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_NO_VIDEO_MEMORY:
+- reason = "STATUS_GRAPHICS_NO_VIDEO_MEMORY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_CANT_LOCK_MEMORY:
+- reason = "STATUS_GRAPHICS_CANT_LOCK_MEMORY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_ALLOCATION_BUSY:
+- reason = "STATUS_GRAPHICS_ALLOCATION_BUSY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_TOO_MANY_REFERENCES:
+- reason = "STATUS_GRAPHICS_TOO_MANY_REFERENCES";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_TRY_AGAIN_LATER:
+- reason = "STATUS_GRAPHICS_TRY_AGAIN_LATER";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_TRY_AGAIN_NOW:
+- reason = "STATUS_GRAPHICS_TRY_AGAIN_NOW";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_ALLOCATION_INVALID:
+- reason = "STATUS_GRAPHICS_ALLOCATION_INVALID";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_UNSWIZZLING_APERTURE_UNAVAILABLE:
+- reason = "STATUS_GRAPHICS_UNSWIZZLING_APERTURE_UNAVAILABLE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_UNSWIZZLING_APERTURE_UNSUPPORTED:
+- reason = "STATUS_GRAPHICS_UNSWIZZLING_APERTURE_UNSUPPORTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_CANT_EVICT_PINNED_ALLOCATION:
+- reason = "STATUS_GRAPHICS_CANT_EVICT_PINNED_ALLOCATION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_ALLOCATION_USAGE:
+- reason = "STATUS_GRAPHICS_INVALID_ALLOCATION_USAGE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_CANT_RENDER_LOCKED_ALLOCATION:
+- reason = "STATUS_GRAPHICS_CANT_RENDER_LOCKED_ALLOCATION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_ALLOCATION_CLOSED:
+- reason = "STATUS_GRAPHICS_ALLOCATION_CLOSED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_ALLOCATION_INSTANCE:
+- reason = "STATUS_GRAPHICS_INVALID_ALLOCATION_INSTANCE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_ALLOCATION_HANDLE:
+- reason = "STATUS_GRAPHICS_INVALID_ALLOCATION_HANDLE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_WRONG_ALLOCATION_DEVICE:
+- reason = "STATUS_GRAPHICS_WRONG_ALLOCATION_DEVICE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_ALLOCATION_CONTENT_LOST:
+- reason = "STATUS_GRAPHICS_ALLOCATION_CONTENT_LOST";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_GPU_EXCEPTION_ON_DEVICE:
+- reason = "STATUS_GRAPHICS_GPU_EXCEPTION_ON_DEVICE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_VIDPN_TOPOLOGY:
+- reason = "STATUS_GRAPHICS_INVALID_VIDPN_TOPOLOGY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_VIDPN_TOPOLOGY_NOT_SUPPORTED:
+- reason = "STATUS_GRAPHICS_VIDPN_TOPOLOGY_NOT_SUPPORTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_VIDPN_TOPOLOGY_CURRENTLY_NOT_SUPPORTED:
+- reason = "STATUS_GRAPHICS_VIDPN_TOPOLOGY_CURRENTLY_NOT_SUPPORTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_VIDPN:
+- reason = "STATUS_GRAPHICS_INVALID_VIDPN";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_SOURCE:
+- reason = "STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_SOURCE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_TARGET:
+- reason = "STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_TARGET";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_VIDPN_MODALITY_NOT_SUPPORTED:
+- reason = "STATUS_GRAPHICS_VIDPN_MODALITY_NOT_SUPPORTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_VIDPN_SOURCEMODESET:
+- reason = "STATUS_GRAPHICS_INVALID_VIDPN_SOURCEMODESET";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_VIDPN_TARGETMODESET:
+- reason = "STATUS_GRAPHICS_INVALID_VIDPN_TARGETMODESET";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_FREQUENCY:
+- reason = "STATUS_GRAPHICS_INVALID_FREQUENCY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_ACTIVE_REGION:
+- reason = "STATUS_GRAPHICS_INVALID_ACTIVE_REGION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_TOTAL_REGION:
+- reason = "STATUS_GRAPHICS_INVALID_TOTAL_REGION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_SOURCE_MODE:
+- reason = "STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_SOURCE_MODE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_TARGET_MODE:
+- reason = "STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_TARGET_MODE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_PINNED_MODE_MUST_REMAIN_IN_SET:
+- reason = "STATUS_GRAPHICS_PINNED_MODE_MUST_REMAIN_IN_SET";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_PATH_ALREADY_IN_TOPOLOGY:
+- reason = "STATUS_GRAPHICS_PATH_ALREADY_IN_TOPOLOGY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_MODE_ALREADY_IN_MODESET:
+- reason = "STATUS_GRAPHICS_MODE_ALREADY_IN_MODESET";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_VIDEOPRESENTSOURCESET:
+- reason = "STATUS_GRAPHICS_INVALID_VIDEOPRESENTSOURCESET";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_VIDEOPRESENTTARGETSET:
+- reason = "STATUS_GRAPHICS_INVALID_VIDEOPRESENTTARGETSET";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_SOURCE_ALREADY_IN_SET:
+- reason = "STATUS_GRAPHICS_SOURCE_ALREADY_IN_SET";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_TARGET_ALREADY_IN_SET:
+- reason = "STATUS_GRAPHICS_TARGET_ALREADY_IN_SET";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_VIDPN_PRESENT_PATH:
+- reason = "STATUS_GRAPHICS_INVALID_VIDPN_PRESENT_PATH";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_NO_RECOMMENDED_VIDPN_TOPOLOGY:
+- reason = "STATUS_GRAPHICS_NO_RECOMMENDED_VIDPN_TOPOLOGY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_MONITOR_FREQUENCYRANGESET:
+- reason = "STATUS_GRAPHICS_INVALID_MONITOR_FREQUENCYRANGESET";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_MONITOR_FREQUENCYRANGE:
+- reason = "STATUS_GRAPHICS_INVALID_MONITOR_FREQUENCYRANGE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_FREQUENCYRANGE_NOT_IN_SET:
+- reason = "STATUS_GRAPHICS_FREQUENCYRANGE_NOT_IN_SET";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_FREQUENCYRANGE_ALREADY_IN_SET:
+- reason = "STATUS_GRAPHICS_FREQUENCYRANGE_ALREADY_IN_SET";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_STALE_MODESET:
+- reason = "STATUS_GRAPHICS_STALE_MODESET";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_MONITOR_SOURCEMODESET:
+- reason = "STATUS_GRAPHICS_INVALID_MONITOR_SOURCEMODESET";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_MONITOR_SOURCE_MODE:
+- reason = "STATUS_GRAPHICS_INVALID_MONITOR_SOURCE_MODE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_NO_RECOMMENDED_FUNCTIONAL_VIDPN:
+- reason = "STATUS_GRAPHICS_NO_RECOMMENDED_FUNCTIONAL_VIDPN";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_MODE_ID_MUST_BE_UNIQUE:
+- reason = "STATUS_GRAPHICS_MODE_ID_MUST_BE_UNIQUE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_EMPTY_ADAPTER_MONITOR_MODE_SUPPORT_INTERSECTION:
+- reason = "STATUS_GRAPHICS_EMPTY_ADAPTER_MONITOR_MODE_SUPPORT_INTERSECTION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_VIDEO_PRESENT_TARGETS_LESS_THAN_SOURCES:
+- reason = "STATUS_GRAPHICS_VIDEO_PRESENT_TARGETS_LESS_THAN_SOURCES";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_PATH_NOT_IN_TOPOLOGY:
+- reason = "STATUS_GRAPHICS_PATH_NOT_IN_TOPOLOGY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_ADAPTER_MUST_HAVE_AT_LEAST_ONE_SOURCE:
+- reason = "STATUS_GRAPHICS_ADAPTER_MUST_HAVE_AT_LEAST_ONE_SOURCE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_ADAPTER_MUST_HAVE_AT_LEAST_ONE_TARGET:
+- reason = "STATUS_GRAPHICS_ADAPTER_MUST_HAVE_AT_LEAST_ONE_TARGET";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_MONITORDESCRIPTORSET:
+- reason = "STATUS_GRAPHICS_INVALID_MONITORDESCRIPTORSET";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_MONITORDESCRIPTOR:
+- reason = "STATUS_GRAPHICS_INVALID_MONITORDESCRIPTOR";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_MONITORDESCRIPTOR_NOT_IN_SET:
+- reason = "STATUS_GRAPHICS_MONITORDESCRIPTOR_NOT_IN_SET";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_MONITORDESCRIPTOR_ALREADY_IN_SET:
+- reason = "STATUS_GRAPHICS_MONITORDESCRIPTOR_ALREADY_IN_SET";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_MONITORDESCRIPTOR_ID_MUST_BE_UNIQUE:
+- reason = "STATUS_GRAPHICS_MONITORDESCRIPTOR_ID_MUST_BE_UNIQUE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_VIDPN_TARGET_SUBSET_TYPE:
+- reason = "STATUS_GRAPHICS_INVALID_VIDPN_TARGET_SUBSET_TYPE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_RESOURCES_NOT_RELATED:
+- reason = "STATUS_GRAPHICS_RESOURCES_NOT_RELATED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_SOURCE_ID_MUST_BE_UNIQUE:
+- reason = "STATUS_GRAPHICS_SOURCE_ID_MUST_BE_UNIQUE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_TARGET_ID_MUST_BE_UNIQUE:
+- reason = "STATUS_GRAPHICS_TARGET_ID_MUST_BE_UNIQUE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_NO_AVAILABLE_VIDPN_TARGET:
+- reason = "STATUS_GRAPHICS_NO_AVAILABLE_VIDPN_TARGET";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_MONITOR_COULD_NOT_BE_ASSOCIATED_WITH_ADAPTER:
+- reason = "STATUS_GRAPHICS_MONITOR_COULD_NOT_BE_ASSOCIATED_WITH_ADAPTER";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_NO_VIDPNMGR:
+- reason = "STATUS_GRAPHICS_NO_VIDPNMGR";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_NO_ACTIVE_VIDPN:
+- reason = "STATUS_GRAPHICS_NO_ACTIVE_VIDPN";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_STALE_VIDPN_TOPOLOGY:
+- reason = "STATUS_GRAPHICS_STALE_VIDPN_TOPOLOGY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_MONITOR_NOT_CONNECTED:
+- reason = "STATUS_GRAPHICS_MONITOR_NOT_CONNECTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_SOURCE_NOT_IN_TOPOLOGY:
+- reason = "STATUS_GRAPHICS_SOURCE_NOT_IN_TOPOLOGY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_PRIMARYSURFACE_SIZE:
+- reason = "STATUS_GRAPHICS_INVALID_PRIMARYSURFACE_SIZE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_VISIBLEREGION_SIZE:
+- reason = "STATUS_GRAPHICS_INVALID_VISIBLEREGION_SIZE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_STRIDE:
+- reason = "STATUS_GRAPHICS_INVALID_STRIDE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_PIXELFORMAT:
+- reason = "STATUS_GRAPHICS_INVALID_PIXELFORMAT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_COLORBASIS:
+- reason = "STATUS_GRAPHICS_INVALID_COLORBASIS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_PIXELVALUEACCESSMODE:
+- reason = "STATUS_GRAPHICS_INVALID_PIXELVALUEACCESSMODE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_TARGET_NOT_IN_TOPOLOGY:
+- reason = "STATUS_GRAPHICS_TARGET_NOT_IN_TOPOLOGY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_NO_DISPLAY_MODE_MANAGEMENT_SUPPORT:
+- reason = "STATUS_GRAPHICS_NO_DISPLAY_MODE_MANAGEMENT_SUPPORT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE:
+- reason = "STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_CANT_ACCESS_ACTIVE_VIDPN:
+- reason = "STATUS_GRAPHICS_CANT_ACCESS_ACTIVE_VIDPN";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_PATH_IMPORTANCE_ORDINAL:
+- reason = "STATUS_GRAPHICS_INVALID_PATH_IMPORTANCE_ORDINAL";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_PATH_CONTENT_GEOMETRY_TRANSFORMATION:
+- reason = "STATUS_GRAPHICS_INVALID_PATH_CONTENT_GEOMETRY_TRANSFORMATION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_PATH_CONTENT_GEOMETRY_TRANSFORMATION_NOT_SUPPORTED:
+- reason = "STATUS_GRAPHICS_PATH_CONTENT_GEOMETRY_TRANSFORMATION_NOT_SUPPORTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_GAMMA_RAMP:
+- reason = "STATUS_GRAPHICS_INVALID_GAMMA_RAMP";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_GAMMA_RAMP_NOT_SUPPORTED:
+- reason = "STATUS_GRAPHICS_GAMMA_RAMP_NOT_SUPPORTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_MULTISAMPLING_NOT_SUPPORTED:
+- reason = "STATUS_GRAPHICS_MULTISAMPLING_NOT_SUPPORTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_MODE_NOT_IN_MODESET:
+- reason = "STATUS_GRAPHICS_MODE_NOT_IN_MODESET";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_VIDPN_TOPOLOGY_RECOMMENDATION_REASON:
+- reason = "STATUS_GRAPHICS_INVALID_VIDPN_TOPOLOGY_RECOMMENDATION_REASON";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_PATH_CONTENT_TYPE:
+- reason = "STATUS_GRAPHICS_INVALID_PATH_CONTENT_TYPE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_COPYPROTECTION_TYPE:
+- reason = "STATUS_GRAPHICS_INVALID_COPYPROTECTION_TYPE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_UNASSIGNED_MODESET_ALREADY_EXISTS:
+- reason = "STATUS_GRAPHICS_UNASSIGNED_MODESET_ALREADY_EXISTS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_SCANLINE_ORDERING:
+- reason = "STATUS_GRAPHICS_INVALID_SCANLINE_ORDERING";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_TOPOLOGY_CHANGES_NOT_ALLOWED:
+- reason = "STATUS_GRAPHICS_TOPOLOGY_CHANGES_NOT_ALLOWED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_NO_AVAILABLE_IMPORTANCE_ORDINALS:
+- reason = "STATUS_GRAPHICS_NO_AVAILABLE_IMPORTANCE_ORDINALS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INCOMPATIBLE_PRIVATE_FORMAT:
+- reason = "STATUS_GRAPHICS_INCOMPATIBLE_PRIVATE_FORMAT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_MODE_PRUNING_ALGORITHM:
+- reason = "STATUS_GRAPHICS_INVALID_MODE_PRUNING_ALGORITHM";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_MONITOR_CAPABILITY_ORIGIN:
+- reason = "STATUS_GRAPHICS_INVALID_MONITOR_CAPABILITY_ORIGIN";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_MONITOR_FREQUENCYRANGE_CONSTRAINT:
+- reason = "STATUS_GRAPHICS_INVALID_MONITOR_FREQUENCYRANGE_CONSTRAINT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_MAX_NUM_PATHS_REACHED:
+- reason = "STATUS_GRAPHICS_MAX_NUM_PATHS_REACHED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_CANCEL_VIDPN_TOPOLOGY_AUGMENTATION:
+- reason = "STATUS_GRAPHICS_CANCEL_VIDPN_TOPOLOGY_AUGMENTATION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_CLIENT_TYPE:
+- reason = "STATUS_GRAPHICS_INVALID_CLIENT_TYPE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_CLIENTVIDPN_NOT_SET:
+- reason = "STATUS_GRAPHICS_CLIENTVIDPN_NOT_SET";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_SPECIFIED_CHILD_ALREADY_CONNECTED:
+- reason = "STATUS_GRAPHICS_SPECIFIED_CHILD_ALREADY_CONNECTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_CHILD_DESCRIPTOR_NOT_SUPPORTED:
+- reason = "STATUS_GRAPHICS_CHILD_DESCRIPTOR_NOT_SUPPORTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_NOT_A_LINKED_ADAPTER:
+- reason = "STATUS_GRAPHICS_NOT_A_LINKED_ADAPTER";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_LEADLINK_NOT_ENUMERATED:
+- reason = "STATUS_GRAPHICS_LEADLINK_NOT_ENUMERATED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_CHAINLINKS_NOT_ENUMERATED:
+- reason = "STATUS_GRAPHICS_CHAINLINKS_NOT_ENUMERATED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_ADAPTER_CHAIN_NOT_READY:
+- reason = "STATUS_GRAPHICS_ADAPTER_CHAIN_NOT_READY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_CHAINLINKS_NOT_STARTED:
+- reason = "STATUS_GRAPHICS_CHAINLINKS_NOT_STARTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_CHAINLINKS_NOT_POWERED_ON:
+- reason = "STATUS_GRAPHICS_CHAINLINKS_NOT_POWERED_ON";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INCONSISTENT_DEVICE_LINK_STATE:
+- reason = "STATUS_GRAPHICS_INCONSISTENT_DEVICE_LINK_STATE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_NOT_POST_DEVICE_DRIVER:
+- reason = "STATUS_GRAPHICS_NOT_POST_DEVICE_DRIVER";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_ADAPTER_ACCESS_NOT_EXCLUDED:
+- reason = "STATUS_GRAPHICS_ADAPTER_ACCESS_NOT_EXCLUDED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_NOT_SUPPORTED:
+- reason = "STATUS_GRAPHICS_OPM_NOT_SUPPORTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_COPP_NOT_SUPPORTED:
+- reason = "STATUS_GRAPHICS_COPP_NOT_SUPPORTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_UAB_NOT_SUPPORTED:
+- reason = "STATUS_GRAPHICS_UAB_NOT_SUPPORTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_INVALID_ENCRYPTED_PARAMETERS:
+- reason = "STATUS_GRAPHICS_OPM_INVALID_ENCRYPTED_PARAMETERS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_NO_PROTECTED_OUTPUTS_EXIST:
+- reason = "STATUS_GRAPHICS_OPM_NO_PROTECTED_OUTPUTS_EXIST";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_INTERNAL_ERROR:
+- reason = "STATUS_GRAPHICS_OPM_INTERNAL_ERROR";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_INVALID_HANDLE:
+- reason = "STATUS_GRAPHICS_OPM_INVALID_HANDLE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_PVP_INVALID_CERTIFICATE_LENGTH:
+- reason = "STATUS_GRAPHICS_PVP_INVALID_CERTIFICATE_LENGTH";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_SPANNING_MODE_ENABLED:
+- reason = "STATUS_GRAPHICS_OPM_SPANNING_MODE_ENABLED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_THEATER_MODE_ENABLED:
+- reason = "STATUS_GRAPHICS_OPM_THEATER_MODE_ENABLED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_PVP_HFS_FAILED:
+- reason = "STATUS_GRAPHICS_PVP_HFS_FAILED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_INVALID_SRM:
+- reason = "STATUS_GRAPHICS_OPM_INVALID_SRM";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_OUTPUT_DOES_NOT_SUPPORT_HDCP:
+- reason = "STATUS_GRAPHICS_OPM_OUTPUT_DOES_NOT_SUPPORT_HDCP";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_OUTPUT_DOES_NOT_SUPPORT_ACP:
+- reason = "STATUS_GRAPHICS_OPM_OUTPUT_DOES_NOT_SUPPORT_ACP";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_OUTPUT_DOES_NOT_SUPPORT_CGMSA:
+- reason = "STATUS_GRAPHICS_OPM_OUTPUT_DOES_NOT_SUPPORT_CGMSA";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_HDCP_SRM_NEVER_SET:
+- reason = "STATUS_GRAPHICS_OPM_HDCP_SRM_NEVER_SET";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_RESOLUTION_TOO_HIGH:
+- reason = "STATUS_GRAPHICS_OPM_RESOLUTION_TOO_HIGH";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_ALL_HDCP_HARDWARE_ALREADY_IN_USE:
+- reason = "STATUS_GRAPHICS_OPM_ALL_HDCP_HARDWARE_ALREADY_IN_USE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_PROTECTED_OUTPUT_NO_LONGER_EXISTS:
+- reason = "STATUS_GRAPHICS_OPM_PROTECTED_OUTPUT_NO_LONGER_EXISTS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_PROTECTED_OUTPUT_DOES_NOT_HAVE_COPP_SEMANTICS:
+- reason = "STATUS_GRAPHICS_OPM_PROTECTED_OUTPUT_DOES_NOT_HAVE_COPP_SEMANTICS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_INVALID_INFORMATION_REQUEST:
+- reason = "STATUS_GRAPHICS_OPM_INVALID_INFORMATION_REQUEST";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_DRIVER_INTERNAL_ERROR:
+- reason = "STATUS_GRAPHICS_OPM_DRIVER_INTERNAL_ERROR";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_PROTECTED_OUTPUT_DOES_NOT_HAVE_OPM_SEMANTICS:
+- reason = "STATUS_GRAPHICS_OPM_PROTECTED_OUTPUT_DOES_NOT_HAVE_OPM_SEMANTICS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_SIGNALING_NOT_SUPPORTED:
+- reason = "STATUS_GRAPHICS_OPM_SIGNALING_NOT_SUPPORTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_INVALID_CONFIGURATION_REQUEST:
+- reason = "STATUS_GRAPHICS_OPM_INVALID_CONFIGURATION_REQUEST";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_I2C_NOT_SUPPORTED:
+- reason = "STATUS_GRAPHICS_I2C_NOT_SUPPORTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_I2C_DEVICE_DOES_NOT_EXIST:
+- reason = "STATUS_GRAPHICS_I2C_DEVICE_DOES_NOT_EXIST";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_I2C_ERROR_TRANSMITTING_DATA:
+- reason = "STATUS_GRAPHICS_I2C_ERROR_TRANSMITTING_DATA";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_I2C_ERROR_RECEIVING_DATA:
+- reason = "STATUS_GRAPHICS_I2C_ERROR_RECEIVING_DATA";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_DDCCI_VCP_NOT_SUPPORTED:
+- reason = "STATUS_GRAPHICS_DDCCI_VCP_NOT_SUPPORTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_DDCCI_INVALID_DATA:
+- reason = "STATUS_GRAPHICS_DDCCI_INVALID_DATA";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_DDCCI_MONITOR_RETURNED_INVALID_TIMING_STATUS_BYTE:
+- reason = "STATUS_GRAPHICS_DDCCI_MONITOR_RETURNED_INVALID_TIMING_STATUS_BYTE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_DDCCI_INVALID_CAPABILITIES_STRING:
+- reason = "STATUS_GRAPHICS_DDCCI_INVALID_CAPABILITIES_STRING";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_MCA_INTERNAL_ERROR:
+- reason = "STATUS_GRAPHICS_MCA_INTERNAL_ERROR";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_DDCCI_INVALID_MESSAGE_COMMAND:
+- reason = "STATUS_GRAPHICS_DDCCI_INVALID_MESSAGE_COMMAND";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_DDCCI_INVALID_MESSAGE_LENGTH:
+- reason = "STATUS_GRAPHICS_DDCCI_INVALID_MESSAGE_LENGTH";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_DDCCI_INVALID_MESSAGE_CHECKSUM:
+- reason = "STATUS_GRAPHICS_DDCCI_INVALID_MESSAGE_CHECKSUM";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_PHYSICAL_MONITOR_HANDLE:
+- reason = "STATUS_GRAPHICS_INVALID_PHYSICAL_MONITOR_HANDLE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_MONITOR_NO_LONGER_EXISTS:
+- reason = "STATUS_GRAPHICS_MONITOR_NO_LONGER_EXISTS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_ONLY_CONSOLE_SESSION_SUPPORTED:
+- reason = "STATUS_GRAPHICS_ONLY_CONSOLE_SESSION_SUPPORTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_NO_DISPLAY_DEVICE_CORRESPONDS_TO_NAME:
+- reason = "STATUS_GRAPHICS_NO_DISPLAY_DEVICE_CORRESPONDS_TO_NAME";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_DISPLAY_DEVICE_NOT_ATTACHED_TO_DESKTOP:
+- reason = "STATUS_GRAPHICS_DISPLAY_DEVICE_NOT_ATTACHED_TO_DESKTOP";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_MIRRORING_DEVICES_NOT_SUPPORTED:
+- reason = "STATUS_GRAPHICS_MIRRORING_DEVICES_NOT_SUPPORTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_POINTER:
+- reason = "STATUS_GRAPHICS_INVALID_POINTER";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_NO_MONITORS_CORRESPOND_TO_DISPLAY_DEVICE:
+- reason = "STATUS_GRAPHICS_NO_MONITORS_CORRESPOND_TO_DISPLAY_DEVICE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_PARAMETER_ARRAY_TOO_SMALL:
+- reason = "STATUS_GRAPHICS_PARAMETER_ARRAY_TOO_SMALL";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INTERNAL_ERROR:
+- reason = "STATUS_GRAPHICS_INTERNAL_ERROR";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_GRAPHICS_SESSION_TYPE_CHANGE_IN_PROGRESS:
+- reason = "STATUS_GRAPHICS_SESSION_TYPE_CHANGE_IN_PROGRESS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FVE_LOCKED_VOLUME:
+- reason = "STATUS_FVE_LOCKED_VOLUME";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FVE_NOT_ENCRYPTED:
+- reason = "STATUS_FVE_NOT_ENCRYPTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FVE_BAD_INFORMATION:
+- reason = "STATUS_FVE_BAD_INFORMATION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FVE_TOO_SMALL:
+- reason = "STATUS_FVE_TOO_SMALL";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FVE_FAILED_WRONG_FS:
+- reason = "STATUS_FVE_FAILED_WRONG_FS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FVE_BAD_PARTITION_SIZE:
+- reason = "STATUS_FVE_BAD_PARTITION_SIZE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FVE_FS_NOT_EXTENDED:
+- reason = "STATUS_FVE_FS_NOT_EXTENDED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FVE_FS_MOUNTED:
+- reason = "STATUS_FVE_FS_MOUNTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FVE_NO_LICENSE:
+- reason = "STATUS_FVE_NO_LICENSE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FVE_ACTION_NOT_ALLOWED:
+- reason = "STATUS_FVE_ACTION_NOT_ALLOWED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FVE_BAD_DATA:
+- reason = "STATUS_FVE_BAD_DATA";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FVE_VOLUME_NOT_BOUND:
+- reason = "STATUS_FVE_VOLUME_NOT_BOUND";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FVE_NOT_DATA_VOLUME:
+- reason = "STATUS_FVE_NOT_DATA_VOLUME";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FVE_CONV_READ_ERROR:
+- reason = "STATUS_FVE_CONV_READ_ERROR";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FVE_CONV_WRITE_ERROR:
+- reason = "STATUS_FVE_CONV_WRITE_ERROR";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FVE_OVERLAPPED_UPDATE:
+- reason = "STATUS_FVE_OVERLAPPED_UPDATE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FVE_FAILED_SECTOR_SIZE:
+- reason = "STATUS_FVE_FAILED_SECTOR_SIZE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FVE_FAILED_AUTHENTICATION:
+- reason = "STATUS_FVE_FAILED_AUTHENTICATION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FVE_NOT_OS_VOLUME:
+- reason = "STATUS_FVE_NOT_OS_VOLUME";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FVE_KEYFILE_NOT_FOUND:
+- reason = "STATUS_FVE_KEYFILE_NOT_FOUND";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FVE_KEYFILE_INVALID:
+- reason = "STATUS_FVE_KEYFILE_INVALID";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FVE_KEYFILE_NO_VMK:
+- reason = "STATUS_FVE_KEYFILE_NO_VMK";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FVE_TPM_DISABLED:
+- reason = "STATUS_FVE_TPM_DISABLED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FVE_TPM_SRK_AUTH_NOT_ZERO:
+- reason = "STATUS_FVE_TPM_SRK_AUTH_NOT_ZERO";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FVE_TPM_INVALID_PCR:
+- reason = "STATUS_FVE_TPM_INVALID_PCR";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FVE_TPM_NO_VMK:
+- reason = "STATUS_FVE_TPM_NO_VMK";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FVE_PIN_INVALID:
+- reason = "STATUS_FVE_PIN_INVALID";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FVE_AUTH_INVALID_APPLICATION:
+- reason = "STATUS_FVE_AUTH_INVALID_APPLICATION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FVE_AUTH_INVALID_CONFIG:
+- reason = "STATUS_FVE_AUTH_INVALID_CONFIG";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FVE_DEBUGGER_ENABLED:
+- reason = "STATUS_FVE_DEBUGGER_ENABLED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FVE_DRY_RUN_FAILED:
+- reason = "STATUS_FVE_DRY_RUN_FAILED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FVE_BAD_METADATA_POINTER:
+- reason = "STATUS_FVE_BAD_METADATA_POINTER";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FVE_OLD_METADATA_COPY:
+- reason = "STATUS_FVE_OLD_METADATA_COPY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FVE_REBOOT_REQUIRED:
+- reason = "STATUS_FVE_REBOOT_REQUIRED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FVE_RAW_ACCESS:
+- reason = "STATUS_FVE_RAW_ACCESS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FVE_RAW_BLOCKED:
+- reason = "STATUS_FVE_RAW_BLOCKED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FVE_NO_AUTOUNLOCK_MASTER_KEY:
+- reason = "STATUS_FVE_NO_AUTOUNLOCK_MASTER_KEY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FVE_MOR_FAILED:
+- reason = "STATUS_FVE_MOR_FAILED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FVE_NO_FEATURE_LICENSE:
+- reason = "STATUS_FVE_NO_FEATURE_LICENSE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FVE_POLICY_USER_DISABLE_RDV_NOT_ALLOWED:
+- reason = "STATUS_FVE_POLICY_USER_DISABLE_RDV_NOT_ALLOWED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FVE_CONV_RECOVERY_FAILED:
+- reason = "STATUS_FVE_CONV_RECOVERY_FAILED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FVE_VIRTUALIZED_SPACE_TOO_BIG:
+- reason = "STATUS_FVE_VIRTUALIZED_SPACE_TOO_BIG";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FVE_INVALID_DATUM_TYPE:
+- reason = "STATUS_FVE_INVALID_DATUM_TYPE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FVE_VOLUME_TOO_SMALL:
+- reason = "STATUS_FVE_VOLUME_TOO_SMALL";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FVE_ENH_PIN_INVALID:
+- reason = "STATUS_FVE_ENH_PIN_INVALID";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FVE_FULL_ENCRYPTION_NOT_ALLOWED_ON_TP_STORAGE:
+- reason = "STATUS_FVE_FULL_ENCRYPTION_NOT_ALLOWED_ON_TP_STORAGE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FVE_WIPE_NOT_ALLOWED_ON_TP_STORAGE:
+- reason = "STATUS_FVE_WIPE_NOT_ALLOWED_ON_TP_STORAGE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FVE_NOT_ALLOWED_ON_CSV_STACK:
+- reason = "STATUS_FVE_NOT_ALLOWED_ON_CSV_STACK";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FVE_NOT_ALLOWED_ON_CLUSTER:
+- reason = "STATUS_FVE_NOT_ALLOWED_ON_CLUSTER";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FVE_NOT_ALLOWED_TO_UPGRADE_WHILE_CONVERTING:
+- reason = "STATUS_FVE_NOT_ALLOWED_TO_UPGRADE_WHILE_CONVERTING";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FVE_WIPE_CANCEL_NOT_APPLICABLE:
+- reason = "STATUS_FVE_WIPE_CANCEL_NOT_APPLICABLE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FVE_EDRIVE_DRY_RUN_FAILED:
+- reason = "STATUS_FVE_EDRIVE_DRY_RUN_FAILED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FVE_SECUREBOOT_DISABLED:
+- reason = "STATUS_FVE_SECUREBOOT_DISABLED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FVE_SECUREBOOT_CONFIG_CHANGE:
+- reason = "STATUS_FVE_SECUREBOOT_CONFIG_CHANGE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FVE_DEVICE_LOCKEDOUT:
+- reason = "STATUS_FVE_DEVICE_LOCKEDOUT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FVE_VOLUME_EXTEND_PREVENTS_EOW_DECRYPT:
+- reason = "STATUS_FVE_VOLUME_EXTEND_PREVENTS_EOW_DECRYPT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FVE_NOT_DE_VOLUME:
+- reason = "STATUS_FVE_NOT_DE_VOLUME";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FVE_PROTECTION_DISABLED:
+- reason = "STATUS_FVE_PROTECTION_DISABLED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FVE_PROTECTION_CANNOT_BE_DISABLED:
+- reason = "STATUS_FVE_PROTECTION_CANNOT_BE_DISABLED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FVE_OSV_KSR_NOT_ALLOWED:
+- reason = "STATUS_FVE_OSV_KSR_NOT_ALLOWED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FWP_CALLOUT_NOT_FOUND:
+- reason = "STATUS_FWP_CALLOUT_NOT_FOUND";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FWP_CONDITION_NOT_FOUND:
+- reason = "STATUS_FWP_CONDITION_NOT_FOUND";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FWP_FILTER_NOT_FOUND:
+- reason = "STATUS_FWP_FILTER_NOT_FOUND";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FWP_LAYER_NOT_FOUND:
+- reason = "STATUS_FWP_LAYER_NOT_FOUND";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FWP_PROVIDER_NOT_FOUND:
+- reason = "STATUS_FWP_PROVIDER_NOT_FOUND";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FWP_PROVIDER_CONTEXT_NOT_FOUND:
+- reason = "STATUS_FWP_PROVIDER_CONTEXT_NOT_FOUND";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FWP_SUBLAYER_NOT_FOUND:
+- reason = "STATUS_FWP_SUBLAYER_NOT_FOUND";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FWP_NOT_FOUND:
+- reason = "STATUS_FWP_NOT_FOUND";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FWP_ALREADY_EXISTS:
+- reason = "STATUS_FWP_ALREADY_EXISTS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FWP_IN_USE:
+- reason = "STATUS_FWP_IN_USE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FWP_DYNAMIC_SESSION_IN_PROGRESS:
+- reason = "STATUS_FWP_DYNAMIC_SESSION_IN_PROGRESS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FWP_WRONG_SESSION:
+- reason = "STATUS_FWP_WRONG_SESSION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FWP_NO_TXN_IN_PROGRESS:
+- reason = "STATUS_FWP_NO_TXN_IN_PROGRESS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FWP_TXN_IN_PROGRESS:
+- reason = "STATUS_FWP_TXN_IN_PROGRESS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FWP_TXN_ABORTED:
+- reason = "STATUS_FWP_TXN_ABORTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FWP_SESSION_ABORTED:
+- reason = "STATUS_FWP_SESSION_ABORTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FWP_INCOMPATIBLE_TXN:
+- reason = "STATUS_FWP_INCOMPATIBLE_TXN";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FWP_TIMEOUT:
+- reason = "STATUS_FWP_TIMEOUT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FWP_NET_EVENTS_DISABLED:
+- reason = "STATUS_FWP_NET_EVENTS_DISABLED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FWP_INCOMPATIBLE_LAYER:
+- reason = "STATUS_FWP_INCOMPATIBLE_LAYER";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FWP_KM_CLIENTS_ONLY:
+- reason = "STATUS_FWP_KM_CLIENTS_ONLY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FWP_LIFETIME_MISMATCH:
+- reason = "STATUS_FWP_LIFETIME_MISMATCH";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FWP_BUILTIN_OBJECT:
+- reason = "STATUS_FWP_BUILTIN_OBJECT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FWP_TOO_MANY_CALLOUTS:
+- reason = "STATUS_FWP_TOO_MANY_CALLOUTS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FWP_NOTIFICATION_DROPPED:
+- reason = "STATUS_FWP_NOTIFICATION_DROPPED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FWP_TRAFFIC_MISMATCH:
+- reason = "STATUS_FWP_TRAFFIC_MISMATCH";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FWP_INCOMPATIBLE_SA_STATE:
+- reason = "STATUS_FWP_INCOMPATIBLE_SA_STATE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FWP_NULL_POINTER:
+- reason = "STATUS_FWP_NULL_POINTER";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FWP_INVALID_ENUMERATOR:
+- reason = "STATUS_FWP_INVALID_ENUMERATOR";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FWP_INVALID_FLAGS:
+- reason = "STATUS_FWP_INVALID_FLAGS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FWP_INVALID_NET_MASK:
+- reason = "STATUS_FWP_INVALID_NET_MASK";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FWP_INVALID_RANGE:
+- reason = "STATUS_FWP_INVALID_RANGE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FWP_INVALID_INTERVAL:
+- reason = "STATUS_FWP_INVALID_INTERVAL";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FWP_ZERO_LENGTH_ARRAY:
+- reason = "STATUS_FWP_ZERO_LENGTH_ARRAY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FWP_NULL_DISPLAY_NAME:
+- reason = "STATUS_FWP_NULL_DISPLAY_NAME";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FWP_INVALID_ACTION_TYPE:
+- reason = "STATUS_FWP_INVALID_ACTION_TYPE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FWP_INVALID_WEIGHT:
+- reason = "STATUS_FWP_INVALID_WEIGHT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FWP_MATCH_TYPE_MISMATCH:
+- reason = "STATUS_FWP_MATCH_TYPE_MISMATCH";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FWP_TYPE_MISMATCH:
+- reason = "STATUS_FWP_TYPE_MISMATCH";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FWP_OUT_OF_BOUNDS:
+- reason = "STATUS_FWP_OUT_OF_BOUNDS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FWP_RESERVED:
+- reason = "STATUS_FWP_RESERVED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FWP_DUPLICATE_CONDITION:
+- reason = "STATUS_FWP_DUPLICATE_CONDITION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FWP_DUPLICATE_KEYMOD:
+- reason = "STATUS_FWP_DUPLICATE_KEYMOD";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FWP_ACTION_INCOMPATIBLE_WITH_LAYER:
+- reason = "STATUS_FWP_ACTION_INCOMPATIBLE_WITH_LAYER";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FWP_ACTION_INCOMPATIBLE_WITH_SUBLAYER:
+- reason = "STATUS_FWP_ACTION_INCOMPATIBLE_WITH_SUBLAYER";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FWP_CONTEXT_INCOMPATIBLE_WITH_LAYER:
+- reason = "STATUS_FWP_CONTEXT_INCOMPATIBLE_WITH_LAYER";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FWP_CONTEXT_INCOMPATIBLE_WITH_CALLOUT:
+- reason = "STATUS_FWP_CONTEXT_INCOMPATIBLE_WITH_CALLOUT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FWP_INCOMPATIBLE_AUTH_METHOD:
+- reason = "STATUS_FWP_INCOMPATIBLE_AUTH_METHOD";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FWP_INCOMPATIBLE_DH_GROUP:
+- reason = "STATUS_FWP_INCOMPATIBLE_DH_GROUP";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FWP_EM_NOT_SUPPORTED:
+- reason = "STATUS_FWP_EM_NOT_SUPPORTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FWP_NEVER_MATCH:
+- reason = "STATUS_FWP_NEVER_MATCH";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FWP_PROVIDER_CONTEXT_MISMATCH:
+- reason = "STATUS_FWP_PROVIDER_CONTEXT_MISMATCH";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FWP_INVALID_PARAMETER:
+- reason = "STATUS_FWP_INVALID_PARAMETER";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FWP_TOO_MANY_SUBLAYERS:
+- reason = "STATUS_FWP_TOO_MANY_SUBLAYERS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FWP_CALLOUT_NOTIFICATION_FAILED:
+- reason = "STATUS_FWP_CALLOUT_NOTIFICATION_FAILED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FWP_INVALID_AUTH_TRANSFORM:
+- reason = "STATUS_FWP_INVALID_AUTH_TRANSFORM";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FWP_INVALID_CIPHER_TRANSFORM:
+- reason = "STATUS_FWP_INVALID_CIPHER_TRANSFORM";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FWP_INCOMPATIBLE_CIPHER_TRANSFORM:
+- reason = "STATUS_FWP_INCOMPATIBLE_CIPHER_TRANSFORM";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FWP_INVALID_TRANSFORM_COMBINATION:
+- reason = "STATUS_FWP_INVALID_TRANSFORM_COMBINATION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FWP_DUPLICATE_AUTH_METHOD:
+- reason = "STATUS_FWP_DUPLICATE_AUTH_METHOD";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FWP_INVALID_TUNNEL_ENDPOINT:
+- reason = "STATUS_FWP_INVALID_TUNNEL_ENDPOINT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FWP_L2_DRIVER_NOT_READY:
+- reason = "STATUS_FWP_L2_DRIVER_NOT_READY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FWP_KEY_DICTATOR_ALREADY_REGISTERED:
+- reason = "STATUS_FWP_KEY_DICTATOR_ALREADY_REGISTERED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FWP_KEY_DICTATION_INVALID_KEYING_MATERIAL:
+- reason = "STATUS_FWP_KEY_DICTATION_INVALID_KEYING_MATERIAL";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FWP_CONNECTIONS_DISABLED:
+- reason = "STATUS_FWP_CONNECTIONS_DISABLED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FWP_INVALID_DNS_NAME:
+- reason = "STATUS_FWP_INVALID_DNS_NAME";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FWP_STILL_ON:
+- reason = "STATUS_FWP_STILL_ON";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FWP_IKEEXT_NOT_RUNNING:
+- reason = "STATUS_FWP_IKEEXT_NOT_RUNNING";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FWP_TCPIP_NOT_READY:
+- reason = "STATUS_FWP_TCPIP_NOT_READY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FWP_INJECT_HANDLE_CLOSING:
+- reason = "STATUS_FWP_INJECT_HANDLE_CLOSING";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FWP_INJECT_HANDLE_STALE:
+- reason = "STATUS_FWP_INJECT_HANDLE_STALE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FWP_CANNOT_PEND:
+- reason = "STATUS_FWP_CANNOT_PEND";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_FWP_DROP_NOICMP:
+- reason = "STATUS_FWP_DROP_NOICMP";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NDIS_CLOSING:
+- reason = "STATUS_NDIS_CLOSING";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NDIS_BAD_VERSION:
+- reason = "STATUS_NDIS_BAD_VERSION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NDIS_BAD_CHARACTERISTICS:
+- reason = "STATUS_NDIS_BAD_CHARACTERISTICS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NDIS_ADAPTER_NOT_FOUND:
+- reason = "STATUS_NDIS_ADAPTER_NOT_FOUND";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NDIS_OPEN_FAILED:
+- reason = "STATUS_NDIS_OPEN_FAILED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NDIS_DEVICE_FAILED:
+- reason = "STATUS_NDIS_DEVICE_FAILED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NDIS_MULTICAST_FULL:
+- reason = "STATUS_NDIS_MULTICAST_FULL";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NDIS_MULTICAST_EXISTS:
+- reason = "STATUS_NDIS_MULTICAST_EXISTS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NDIS_MULTICAST_NOT_FOUND:
+- reason = "STATUS_NDIS_MULTICAST_NOT_FOUND";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NDIS_REQUEST_ABORTED:
+- reason = "STATUS_NDIS_REQUEST_ABORTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NDIS_RESET_IN_PROGRESS:
+- reason = "STATUS_NDIS_RESET_IN_PROGRESS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NDIS_INVALID_PACKET:
+- reason = "STATUS_NDIS_INVALID_PACKET";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NDIS_INVALID_DEVICE_REQUEST:
+- reason = "STATUS_NDIS_INVALID_DEVICE_REQUEST";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NDIS_ADAPTER_NOT_READY:
+- reason = "STATUS_NDIS_ADAPTER_NOT_READY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NDIS_INVALID_LENGTH:
+- reason = "STATUS_NDIS_INVALID_LENGTH";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NDIS_INVALID_DATA:
+- reason = "STATUS_NDIS_INVALID_DATA";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NDIS_BUFFER_TOO_SHORT:
+- reason = "STATUS_NDIS_BUFFER_TOO_SHORT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NDIS_INVALID_OID:
+- reason = "STATUS_NDIS_INVALID_OID";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NDIS_ADAPTER_REMOVED:
+- reason = "STATUS_NDIS_ADAPTER_REMOVED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NDIS_UNSUPPORTED_MEDIA:
+- reason = "STATUS_NDIS_UNSUPPORTED_MEDIA";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NDIS_GROUP_ADDRESS_IN_USE:
+- reason = "STATUS_NDIS_GROUP_ADDRESS_IN_USE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NDIS_FILE_NOT_FOUND:
+- reason = "STATUS_NDIS_FILE_NOT_FOUND";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NDIS_ERROR_READING_FILE:
+- reason = "STATUS_NDIS_ERROR_READING_FILE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NDIS_ALREADY_MAPPED:
+- reason = "STATUS_NDIS_ALREADY_MAPPED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NDIS_RESOURCE_CONFLICT:
+- reason = "STATUS_NDIS_RESOURCE_CONFLICT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NDIS_MEDIA_DISCONNECTED:
+- reason = "STATUS_NDIS_MEDIA_DISCONNECTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NDIS_INVALID_ADDRESS:
+- reason = "STATUS_NDIS_INVALID_ADDRESS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NDIS_PAUSED:
+- reason = "STATUS_NDIS_PAUSED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NDIS_INTERFACE_NOT_FOUND:
+- reason = "STATUS_NDIS_INTERFACE_NOT_FOUND";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NDIS_UNSUPPORTED_REVISION:
+- reason = "STATUS_NDIS_UNSUPPORTED_REVISION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NDIS_INVALID_PORT:
+- reason = "STATUS_NDIS_INVALID_PORT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NDIS_INVALID_PORT_STATE:
+- reason = "STATUS_NDIS_INVALID_PORT_STATE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NDIS_LOW_POWER_STATE:
+- reason = "STATUS_NDIS_LOW_POWER_STATE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NDIS_REINIT_REQUIRED:
+- reason = "STATUS_NDIS_REINIT_REQUIRED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NDIS_NO_QUEUES:
+- reason = "STATUS_NDIS_NO_QUEUES";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NDIS_NOT_SUPPORTED:
+- reason = "STATUS_NDIS_NOT_SUPPORTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NDIS_OFFLOAD_POLICY:
+- reason = "STATUS_NDIS_OFFLOAD_POLICY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NDIS_OFFLOAD_CONNECTION_REJECTED:
+- reason = "STATUS_NDIS_OFFLOAD_CONNECTION_REJECTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NDIS_OFFLOAD_PATH_REJECTED:
+- reason = "STATUS_NDIS_OFFLOAD_PATH_REJECTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NDIS_DOT11_AUTO_CONFIG_ENABLED:
+- reason = "STATUS_NDIS_DOT11_AUTO_CONFIG_ENABLED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NDIS_DOT11_MEDIA_IN_USE:
+- reason = "STATUS_NDIS_DOT11_MEDIA_IN_USE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NDIS_DOT11_POWER_STATE_INVALID:
+- reason = "STATUS_NDIS_DOT11_POWER_STATE_INVALID";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NDIS_PM_WOL_PATTERN_LIST_FULL:
+- reason = "STATUS_NDIS_PM_WOL_PATTERN_LIST_FULL";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NDIS_PM_PROTOCOL_OFFLOAD_LIST_FULL:
+- reason = "STATUS_NDIS_PM_PROTOCOL_OFFLOAD_LIST_FULL";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NDIS_DOT11_AP_CHANNEL_CURRENTLY_NOT_AVAILABLE:
+- reason = "STATUS_NDIS_DOT11_AP_CHANNEL_CURRENTLY_NOT_AVAILABLE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NDIS_DOT11_AP_BAND_CURRENTLY_NOT_AVAILABLE:
+- reason = "STATUS_NDIS_DOT11_AP_BAND_CURRENTLY_NOT_AVAILABLE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NDIS_DOT11_AP_CHANNEL_NOT_ALLOWED:
+- reason = "STATUS_NDIS_DOT11_AP_CHANNEL_NOT_ALLOWED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NDIS_DOT11_AP_BAND_NOT_ALLOWED:
+- reason = "STATUS_NDIS_DOT11_AP_BAND_NOT_ALLOWED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_QUIC_HANDSHAKE_FAILURE:
+- reason = "STATUS_QUIC_HANDSHAKE_FAILURE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_QUIC_VER_NEG_FAILURE:
+- reason = "STATUS_QUIC_VER_NEG_FAILURE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_ERROR_MASK:
+- reason = "STATUS_TPM_ERROR_MASK";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_AUTHFAIL:
+- reason = "STATUS_TPM_AUTHFAIL";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_BADINDEX:
+- reason = "STATUS_TPM_BADINDEX";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_BAD_PARAMETER:
+- reason = "STATUS_TPM_BAD_PARAMETER";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_AUDITFAILURE:
+- reason = "STATUS_TPM_AUDITFAILURE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_CLEAR_DISABLED:
+- reason = "STATUS_TPM_CLEAR_DISABLED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_DEACTIVATED:
+- reason = "STATUS_TPM_DEACTIVATED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_DISABLED:
+- reason = "STATUS_TPM_DISABLED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_DISABLED_CMD:
+- reason = "STATUS_TPM_DISABLED_CMD";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_FAIL:
+- reason = "STATUS_TPM_FAIL";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_BAD_ORDINAL:
+- reason = "STATUS_TPM_BAD_ORDINAL";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_INSTALL_DISABLED:
+- reason = "STATUS_TPM_INSTALL_DISABLED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_INVALID_KEYHANDLE:
+- reason = "STATUS_TPM_INVALID_KEYHANDLE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_KEYNOTFOUND:
+- reason = "STATUS_TPM_KEYNOTFOUND";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_INAPPROPRIATE_ENC:
+- reason = "STATUS_TPM_INAPPROPRIATE_ENC";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_MIGRATEFAIL:
+- reason = "STATUS_TPM_MIGRATEFAIL";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_INVALID_PCR_INFO:
+- reason = "STATUS_TPM_INVALID_PCR_INFO";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_NOSPACE:
+- reason = "STATUS_TPM_NOSPACE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_NOSRK:
+- reason = "STATUS_TPM_NOSRK";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_NOTSEALED_BLOB:
+- reason = "STATUS_TPM_NOTSEALED_BLOB";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_OWNER_SET:
+- reason = "STATUS_TPM_OWNER_SET";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_RESOURCES:
+- reason = "STATUS_TPM_RESOURCES";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_SHORTRANDOM:
+- reason = "STATUS_TPM_SHORTRANDOM";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_SIZE:
+- reason = "STATUS_TPM_SIZE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_WRONGPCRVAL:
+- reason = "STATUS_TPM_WRONGPCRVAL";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_BAD_PARAM_SIZE:
+- reason = "STATUS_TPM_BAD_PARAM_SIZE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_SHA_THREAD:
+- reason = "STATUS_TPM_SHA_THREAD";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_SHA_ERROR:
+- reason = "STATUS_TPM_SHA_ERROR";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_FAILEDSELFTEST:
+- reason = "STATUS_TPM_FAILEDSELFTEST";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_AUTH2FAIL:
+- reason = "STATUS_TPM_AUTH2FAIL";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_BADTAG:
+- reason = "STATUS_TPM_BADTAG";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_IOERROR:
+- reason = "STATUS_TPM_IOERROR";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_ENCRYPT_ERROR:
+- reason = "STATUS_TPM_ENCRYPT_ERROR";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_DECRYPT_ERROR:
+- reason = "STATUS_TPM_DECRYPT_ERROR";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_INVALID_AUTHHANDLE:
+- reason = "STATUS_TPM_INVALID_AUTHHANDLE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_NO_ENDORSEMENT:
+- reason = "STATUS_TPM_NO_ENDORSEMENT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_INVALID_KEYUSAGE:
+- reason = "STATUS_TPM_INVALID_KEYUSAGE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_WRONG_ENTITYTYPE:
+- reason = "STATUS_TPM_WRONG_ENTITYTYPE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_INVALID_POSTINIT:
+- reason = "STATUS_TPM_INVALID_POSTINIT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_INAPPROPRIATE_SIG:
+- reason = "STATUS_TPM_INAPPROPRIATE_SIG";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_BAD_KEY_PROPERTY:
+- reason = "STATUS_TPM_BAD_KEY_PROPERTY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_BAD_MIGRATION:
+- reason = "STATUS_TPM_BAD_MIGRATION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_BAD_SCHEME:
+- reason = "STATUS_TPM_BAD_SCHEME";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_BAD_DATASIZE:
+- reason = "STATUS_TPM_BAD_DATASIZE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_BAD_MODE:
+- reason = "STATUS_TPM_BAD_MODE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_BAD_PRESENCE:
+- reason = "STATUS_TPM_BAD_PRESENCE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_BAD_VERSION:
+- reason = "STATUS_TPM_BAD_VERSION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_NO_WRAP_TRANSPORT:
+- reason = "STATUS_TPM_NO_WRAP_TRANSPORT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_AUDITFAIL_UNSUCCESSFUL:
+- reason = "STATUS_TPM_AUDITFAIL_UNSUCCESSFUL";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_AUDITFAIL_SUCCESSFUL:
+- reason = "STATUS_TPM_AUDITFAIL_SUCCESSFUL";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_NOTRESETABLE:
+- reason = "STATUS_TPM_NOTRESETABLE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_NOTLOCAL:
+- reason = "STATUS_TPM_NOTLOCAL";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_BAD_TYPE:
+- reason = "STATUS_TPM_BAD_TYPE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_INVALID_RESOURCE:
+- reason = "STATUS_TPM_INVALID_RESOURCE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_NOTFIPS:
+- reason = "STATUS_TPM_NOTFIPS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_INVALID_FAMILY:
+- reason = "STATUS_TPM_INVALID_FAMILY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_NO_NV_PERMISSION:
+- reason = "STATUS_TPM_NO_NV_PERMISSION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_REQUIRES_SIGN:
+- reason = "STATUS_TPM_REQUIRES_SIGN";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_KEY_NOTSUPPORTED:
+- reason = "STATUS_TPM_KEY_NOTSUPPORTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_AUTH_CONFLICT:
+- reason = "STATUS_TPM_AUTH_CONFLICT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_AREA_LOCKED:
+- reason = "STATUS_TPM_AREA_LOCKED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_BAD_LOCALITY:
+- reason = "STATUS_TPM_BAD_LOCALITY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_READ_ONLY:
+- reason = "STATUS_TPM_READ_ONLY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_PER_NOWRITE:
+- reason = "STATUS_TPM_PER_NOWRITE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_FAMILYCOUNT:
+- reason = "STATUS_TPM_FAMILYCOUNT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_WRITE_LOCKED:
+- reason = "STATUS_TPM_WRITE_LOCKED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_BAD_ATTRIBUTES:
+- reason = "STATUS_TPM_BAD_ATTRIBUTES";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_INVALID_STRUCTURE:
+- reason = "STATUS_TPM_INVALID_STRUCTURE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_KEY_OWNER_CONTROL:
+- reason = "STATUS_TPM_KEY_OWNER_CONTROL";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_BAD_COUNTER:
+- reason = "STATUS_TPM_BAD_COUNTER";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_NOT_FULLWRITE:
+- reason = "STATUS_TPM_NOT_FULLWRITE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_CONTEXT_GAP:
+- reason = "STATUS_TPM_CONTEXT_GAP";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_MAXNVWRITES:
+- reason = "STATUS_TPM_MAXNVWRITES";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_NOOPERATOR:
+- reason = "STATUS_TPM_NOOPERATOR";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_RESOURCEMISSING:
+- reason = "STATUS_TPM_RESOURCEMISSING";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_DELEGATE_LOCK:
+- reason = "STATUS_TPM_DELEGATE_LOCK";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_DELEGATE_FAMILY:
+- reason = "STATUS_TPM_DELEGATE_FAMILY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_DELEGATE_ADMIN:
+- reason = "STATUS_TPM_DELEGATE_ADMIN";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_TRANSPORT_NOTEXCLUSIVE:
+- reason = "STATUS_TPM_TRANSPORT_NOTEXCLUSIVE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_OWNER_CONTROL:
+- reason = "STATUS_TPM_OWNER_CONTROL";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_DAA_RESOURCES:
+- reason = "STATUS_TPM_DAA_RESOURCES";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_DAA_INPUT_DATA0:
+- reason = "STATUS_TPM_DAA_INPUT_DATA0";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_DAA_INPUT_DATA1:
+- reason = "STATUS_TPM_DAA_INPUT_DATA1";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_DAA_ISSUER_SETTINGS:
+- reason = "STATUS_TPM_DAA_ISSUER_SETTINGS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_DAA_TPM_SETTINGS:
+- reason = "STATUS_TPM_DAA_TPM_SETTINGS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_DAA_STAGE:
+- reason = "STATUS_TPM_DAA_STAGE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_DAA_ISSUER_VALIDITY:
+- reason = "STATUS_TPM_DAA_ISSUER_VALIDITY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_DAA_WRONG_W:
+- reason = "STATUS_TPM_DAA_WRONG_W";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_BAD_HANDLE:
+- reason = "STATUS_TPM_BAD_HANDLE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_BAD_DELEGATE:
+- reason = "STATUS_TPM_BAD_DELEGATE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_BADCONTEXT:
+- reason = "STATUS_TPM_BADCONTEXT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_TOOMANYCONTEXTS:
+- reason = "STATUS_TPM_TOOMANYCONTEXTS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_MA_TICKET_SIGNATURE:
+- reason = "STATUS_TPM_MA_TICKET_SIGNATURE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_MA_DESTINATION:
+- reason = "STATUS_TPM_MA_DESTINATION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_MA_SOURCE:
+- reason = "STATUS_TPM_MA_SOURCE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_MA_AUTHORITY:
+- reason = "STATUS_TPM_MA_AUTHORITY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_PERMANENTEK:
+- reason = "STATUS_TPM_PERMANENTEK";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_BAD_SIGNATURE:
+- reason = "STATUS_TPM_BAD_SIGNATURE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_NOCONTEXTSPACE:
+- reason = "STATUS_TPM_NOCONTEXTSPACE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_20_E_ASYMMETRIC:
+- reason = "STATUS_TPM_20_E_ASYMMETRIC";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_20_E_ATTRIBUTES:
+- reason = "STATUS_TPM_20_E_ATTRIBUTES";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_20_E_HASH:
+- reason = "STATUS_TPM_20_E_HASH";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_20_E_VALUE:
+- reason = "STATUS_TPM_20_E_VALUE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_20_E_HIERARCHY:
+- reason = "STATUS_TPM_20_E_HIERARCHY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_20_E_KEY_SIZE:
+- reason = "STATUS_TPM_20_E_KEY_SIZE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_20_E_MGF:
+- reason = "STATUS_TPM_20_E_MGF";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_20_E_MODE:
+- reason = "STATUS_TPM_20_E_MODE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_20_E_TYPE:
+- reason = "STATUS_TPM_20_E_TYPE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_20_E_HANDLE:
+- reason = "STATUS_TPM_20_E_HANDLE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_20_E_KDF:
+- reason = "STATUS_TPM_20_E_KDF";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_20_E_RANGE:
+- reason = "STATUS_TPM_20_E_RANGE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_20_E_AUTH_FAIL:
+- reason = "STATUS_TPM_20_E_AUTH_FAIL";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_20_E_NONCE:
+- reason = "STATUS_TPM_20_E_NONCE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_20_E_PP:
+- reason = "STATUS_TPM_20_E_PP";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_20_E_SCHEME:
+- reason = "STATUS_TPM_20_E_SCHEME";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_20_E_SIZE:
+- reason = "STATUS_TPM_20_E_SIZE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_20_E_SYMMETRIC:
+- reason = "STATUS_TPM_20_E_SYMMETRIC";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_20_E_TAG:
+- reason = "STATUS_TPM_20_E_TAG";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_20_E_SELECTOR:
+- reason = "STATUS_TPM_20_E_SELECTOR";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_20_E_INSUFFICIENT:
+- reason = "STATUS_TPM_20_E_INSUFFICIENT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_20_E_SIGNATURE:
+- reason = "STATUS_TPM_20_E_SIGNATURE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_20_E_KEY:
+- reason = "STATUS_TPM_20_E_KEY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_20_E_POLICY_FAIL:
+- reason = "STATUS_TPM_20_E_POLICY_FAIL";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_20_E_INTEGRITY:
+- reason = "STATUS_TPM_20_E_INTEGRITY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_20_E_TICKET:
+- reason = "STATUS_TPM_20_E_TICKET";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_20_E_RESERVED_BITS:
+- reason = "STATUS_TPM_20_E_RESERVED_BITS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_20_E_BAD_AUTH:
+- reason = "STATUS_TPM_20_E_BAD_AUTH";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_20_E_EXPIRED:
+- reason = "STATUS_TPM_20_E_EXPIRED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_20_E_POLICY_CC:
+- reason = "STATUS_TPM_20_E_POLICY_CC";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_20_E_BINDING:
+- reason = "STATUS_TPM_20_E_BINDING";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_20_E_CURVE:
+- reason = "STATUS_TPM_20_E_CURVE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_20_E_ECC_POINT:
+- reason = "STATUS_TPM_20_E_ECC_POINT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_20_E_INITIALIZE:
+- reason = "STATUS_TPM_20_E_INITIALIZE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_20_E_FAILURE:
+- reason = "STATUS_TPM_20_E_FAILURE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_20_E_SEQUENCE:
+- reason = "STATUS_TPM_20_E_SEQUENCE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_20_E_PRIVATE:
+- reason = "STATUS_TPM_20_E_PRIVATE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_20_E_HMAC:
+- reason = "STATUS_TPM_20_E_HMAC";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_20_E_DISABLED:
+- reason = "STATUS_TPM_20_E_DISABLED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_20_E_EXCLUSIVE:
+- reason = "STATUS_TPM_20_E_EXCLUSIVE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_20_E_ECC_CURVE:
+- reason = "STATUS_TPM_20_E_ECC_CURVE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_20_E_AUTH_TYPE:
+- reason = "STATUS_TPM_20_E_AUTH_TYPE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_20_E_AUTH_MISSING:
+- reason = "STATUS_TPM_20_E_AUTH_MISSING";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_20_E_POLICY:
+- reason = "STATUS_TPM_20_E_POLICY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_20_E_PCR:
+- reason = "STATUS_TPM_20_E_PCR";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_20_E_PCR_CHANGED:
+- reason = "STATUS_TPM_20_E_PCR_CHANGED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_20_E_UPGRADE:
+- reason = "STATUS_TPM_20_E_UPGRADE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_20_E_TOO_MANY_CONTEXTS:
+- reason = "STATUS_TPM_20_E_TOO_MANY_CONTEXTS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_20_E_AUTH_UNAVAILABLE:
+- reason = "STATUS_TPM_20_E_AUTH_UNAVAILABLE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_20_E_REBOOT:
+- reason = "STATUS_TPM_20_E_REBOOT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_20_E_UNBALANCED:
+- reason = "STATUS_TPM_20_E_UNBALANCED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_20_E_COMMAND_SIZE:
+- reason = "STATUS_TPM_20_E_COMMAND_SIZE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_20_E_COMMAND_CODE:
+- reason = "STATUS_TPM_20_E_COMMAND_CODE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_20_E_AUTHSIZE:
+- reason = "STATUS_TPM_20_E_AUTHSIZE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_20_E_AUTH_CONTEXT:
+- reason = "STATUS_TPM_20_E_AUTH_CONTEXT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_20_E_NV_RANGE:
+- reason = "STATUS_TPM_20_E_NV_RANGE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_20_E_NV_SIZE:
+- reason = "STATUS_TPM_20_E_NV_SIZE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_20_E_NV_LOCKED:
+- reason = "STATUS_TPM_20_E_NV_LOCKED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_20_E_NV_AUTHORIZATION:
+- reason = "STATUS_TPM_20_E_NV_AUTHORIZATION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_20_E_NV_UNINITIALIZED:
+- reason = "STATUS_TPM_20_E_NV_UNINITIALIZED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_20_E_NV_SPACE:
+- reason = "STATUS_TPM_20_E_NV_SPACE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_20_E_NV_DEFINED:
+- reason = "STATUS_TPM_20_E_NV_DEFINED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_20_E_BAD_CONTEXT:
+- reason = "STATUS_TPM_20_E_BAD_CONTEXT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_20_E_CPHASH:
+- reason = "STATUS_TPM_20_E_CPHASH";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_20_E_PARENT:
+- reason = "STATUS_TPM_20_E_PARENT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_20_E_NEEDS_TEST:
+- reason = "STATUS_TPM_20_E_NEEDS_TEST";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_20_E_NO_RESULT:
+- reason = "STATUS_TPM_20_E_NO_RESULT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_20_E_SENSITIVE:
+- reason = "STATUS_TPM_20_E_SENSITIVE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_COMMAND_BLOCKED:
+- reason = "STATUS_TPM_COMMAND_BLOCKED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_INVALID_HANDLE:
+- reason = "STATUS_TPM_INVALID_HANDLE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_DUPLICATE_VHANDLE:
+- reason = "STATUS_TPM_DUPLICATE_VHANDLE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_EMBEDDED_COMMAND_BLOCKED:
+- reason = "STATUS_TPM_EMBEDDED_COMMAND_BLOCKED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_EMBEDDED_COMMAND_UNSUPPORTED:
+- reason = "STATUS_TPM_EMBEDDED_COMMAND_UNSUPPORTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_RETRY:
+- reason = "STATUS_TPM_RETRY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_NEEDS_SELFTEST:
+- reason = "STATUS_TPM_NEEDS_SELFTEST";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_DOING_SELFTEST:
+- reason = "STATUS_TPM_DOING_SELFTEST";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_DEFEND_LOCK_RUNNING:
+- reason = "STATUS_TPM_DEFEND_LOCK_RUNNING";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_COMMAND_CANCELED:
+- reason = "STATUS_TPM_COMMAND_CANCELED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_TOO_MANY_CONTEXTS:
+- reason = "STATUS_TPM_TOO_MANY_CONTEXTS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_NOT_FOUND:
+- reason = "STATUS_TPM_NOT_FOUND";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_ACCESS_DENIED:
+- reason = "STATUS_TPM_ACCESS_DENIED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_INSUFFICIENT_BUFFER:
+- reason = "STATUS_TPM_INSUFFICIENT_BUFFER";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_PPI_FUNCTION_UNSUPPORTED:
+- reason = "STATUS_TPM_PPI_FUNCTION_UNSUPPORTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PCP_ERROR_MASK:
+- reason = "STATUS_PCP_ERROR_MASK";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PCP_DEVICE_NOT_READY:
+- reason = "STATUS_PCP_DEVICE_NOT_READY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PCP_INVALID_HANDLE:
+- reason = "STATUS_PCP_INVALID_HANDLE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PCP_INVALID_PARAMETER:
+- reason = "STATUS_PCP_INVALID_PARAMETER";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PCP_FLAG_NOT_SUPPORTED:
+- reason = "STATUS_PCP_FLAG_NOT_SUPPORTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PCP_NOT_SUPPORTED:
+- reason = "STATUS_PCP_NOT_SUPPORTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PCP_BUFFER_TOO_SMALL:
+- reason = "STATUS_PCP_BUFFER_TOO_SMALL";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PCP_INTERNAL_ERROR:
+- reason = "STATUS_PCP_INTERNAL_ERROR";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PCP_AUTHENTICATION_FAILED:
+- reason = "STATUS_PCP_AUTHENTICATION_FAILED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PCP_AUTHENTICATION_IGNORED:
+- reason = "STATUS_PCP_AUTHENTICATION_IGNORED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PCP_POLICY_NOT_FOUND:
+- reason = "STATUS_PCP_POLICY_NOT_FOUND";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PCP_PROFILE_NOT_FOUND:
+- reason = "STATUS_PCP_PROFILE_NOT_FOUND";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PCP_VALIDATION_FAILED:
+- reason = "STATUS_PCP_VALIDATION_FAILED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PCP_DEVICE_NOT_FOUND:
+- reason = "STATUS_PCP_DEVICE_NOT_FOUND";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PCP_WRONG_PARENT:
+- reason = "STATUS_PCP_WRONG_PARENT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PCP_KEY_NOT_LOADED:
+- reason = "STATUS_PCP_KEY_NOT_LOADED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PCP_NO_KEY_CERTIFICATION:
+- reason = "STATUS_PCP_NO_KEY_CERTIFICATION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PCP_KEY_NOT_FINALIZED:
+- reason = "STATUS_PCP_KEY_NOT_FINALIZED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PCP_ATTESTATION_CHALLENGE_NOT_SET:
+- reason = "STATUS_PCP_ATTESTATION_CHALLENGE_NOT_SET";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PCP_NOT_PCR_BOUND:
+- reason = "STATUS_PCP_NOT_PCR_BOUND";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PCP_KEY_ALREADY_FINALIZED:
+- reason = "STATUS_PCP_KEY_ALREADY_FINALIZED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PCP_KEY_USAGE_POLICY_NOT_SUPPORTED:
+- reason = "STATUS_PCP_KEY_USAGE_POLICY_NOT_SUPPORTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PCP_KEY_USAGE_POLICY_INVALID:
+- reason = "STATUS_PCP_KEY_USAGE_POLICY_INVALID";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PCP_SOFT_KEY_ERROR:
+- reason = "STATUS_PCP_SOFT_KEY_ERROR";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PCP_KEY_NOT_AUTHENTICATED:
+- reason = "STATUS_PCP_KEY_NOT_AUTHENTICATED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PCP_KEY_NOT_AIK:
+- reason = "STATUS_PCP_KEY_NOT_AIK";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PCP_KEY_NOT_SIGNING_KEY:
+- reason = "STATUS_PCP_KEY_NOT_SIGNING_KEY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PCP_LOCKED_OUT:
+- reason = "STATUS_PCP_LOCKED_OUT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PCP_CLAIM_TYPE_NOT_SUPPORTED:
+- reason = "STATUS_PCP_CLAIM_TYPE_NOT_SUPPORTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PCP_TPM_VERSION_NOT_SUPPORTED:
+- reason = "STATUS_PCP_TPM_VERSION_NOT_SUPPORTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PCP_BUFFER_LENGTH_MISMATCH:
+- reason = "STATUS_PCP_BUFFER_LENGTH_MISMATCH";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PCP_IFX_RSA_KEY_CREATION_BLOCKED:
+- reason = "STATUS_PCP_IFX_RSA_KEY_CREATION_BLOCKED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PCP_TICKET_MISSING:
+- reason = "STATUS_PCP_TICKET_MISSING";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PCP_RAW_POLICY_NOT_SUPPORTED:
+- reason = "STATUS_PCP_RAW_POLICY_NOT_SUPPORTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PCP_KEY_HANDLE_INVALIDATED:
+- reason = "STATUS_PCP_KEY_HANDLE_INVALIDATED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_RTPM_NO_RESULT:
+- reason = "STATUS_RTPM_NO_RESULT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_RTPM_PCR_READ_INCOMPLETE:
+- reason = "STATUS_RTPM_PCR_READ_INCOMPLETE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_RTPM_INVALID_CONTEXT:
+- reason = "STATUS_RTPM_INVALID_CONTEXT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_RTPM_UNSUPPORTED_CMD:
+- reason = "STATUS_RTPM_UNSUPPORTED_CMD";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_TPM_ZERO_EXHAUST_ENABLED:
+- reason = "STATUS_TPM_ZERO_EXHAUST_ENABLED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_HV_INVALID_HYPERCALL_CODE:
+- reason = "STATUS_HV_INVALID_HYPERCALL_CODE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_HV_INVALID_HYPERCALL_INPUT:
+- reason = "STATUS_HV_INVALID_HYPERCALL_INPUT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_HV_INVALID_ALIGNMENT:
+- reason = "STATUS_HV_INVALID_ALIGNMENT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_HV_INVALID_PARAMETER:
+- reason = "STATUS_HV_INVALID_PARAMETER";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_HV_ACCESS_DENIED:
+- reason = "STATUS_HV_ACCESS_DENIED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_HV_INVALID_PARTITION_STATE:
+- reason = "STATUS_HV_INVALID_PARTITION_STATE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_HV_OPERATION_DENIED:
+- reason = "STATUS_HV_OPERATION_DENIED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_HV_UNKNOWN_PROPERTY:
+- reason = "STATUS_HV_UNKNOWN_PROPERTY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_HV_PROPERTY_VALUE_OUT_OF_RANGE:
+- reason = "STATUS_HV_PROPERTY_VALUE_OUT_OF_RANGE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_HV_INSUFFICIENT_MEMORY:
+- reason = "STATUS_HV_INSUFFICIENT_MEMORY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_HV_PARTITION_TOO_DEEP:
+- reason = "STATUS_HV_PARTITION_TOO_DEEP";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_HV_INVALID_PARTITION_ID:
+- reason = "STATUS_HV_INVALID_PARTITION_ID";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_HV_INVALID_VP_INDEX:
+- reason = "STATUS_HV_INVALID_VP_INDEX";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_HV_INVALID_PORT_ID:
+- reason = "STATUS_HV_INVALID_PORT_ID";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_HV_INVALID_CONNECTION_ID:
+- reason = "STATUS_HV_INVALID_CONNECTION_ID";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_HV_INSUFFICIENT_BUFFERS:
+- reason = "STATUS_HV_INSUFFICIENT_BUFFERS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_HV_NOT_ACKNOWLEDGED:
+- reason = "STATUS_HV_NOT_ACKNOWLEDGED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_HV_INVALID_VP_STATE:
+- reason = "STATUS_HV_INVALID_VP_STATE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_HV_ACKNOWLEDGED:
+- reason = "STATUS_HV_ACKNOWLEDGED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_HV_INVALID_SAVE_RESTORE_STATE:
+- reason = "STATUS_HV_INVALID_SAVE_RESTORE_STATE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_HV_INVALID_SYNIC_STATE:
+- reason = "STATUS_HV_INVALID_SYNIC_STATE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_HV_OBJECT_IN_USE:
+- reason = "STATUS_HV_OBJECT_IN_USE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_HV_INVALID_PROXIMITY_DOMAIN_INFO:
+- reason = "STATUS_HV_INVALID_PROXIMITY_DOMAIN_INFO";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_HV_NO_DATA:
+- reason = "STATUS_HV_NO_DATA";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_HV_INACTIVE:
+- reason = "STATUS_HV_INACTIVE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_HV_NO_RESOURCES:
+- reason = "STATUS_HV_NO_RESOURCES";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_HV_FEATURE_UNAVAILABLE:
+- reason = "STATUS_HV_FEATURE_UNAVAILABLE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_HV_INSUFFICIENT_BUFFER:
+- reason = "STATUS_HV_INSUFFICIENT_BUFFER";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_HV_INSUFFICIENT_DEVICE_DOMAINS:
+- reason = "STATUS_HV_INSUFFICIENT_DEVICE_DOMAINS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_HV_CPUID_FEATURE_VALIDATION_ERROR:
+- reason = "STATUS_HV_CPUID_FEATURE_VALIDATION_ERROR";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_HV_CPUID_XSAVE_FEATURE_VALIDATION_ERROR:
+- reason = "STATUS_HV_CPUID_XSAVE_FEATURE_VALIDATION_ERROR";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_HV_PROCESSOR_STARTUP_TIMEOUT:
+- reason = "STATUS_HV_PROCESSOR_STARTUP_TIMEOUT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_HV_SMX_ENABLED:
+- reason = "STATUS_HV_SMX_ENABLED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_HV_INVALID_LP_INDEX:
+- reason = "STATUS_HV_INVALID_LP_INDEX";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_HV_INVALID_REGISTER_VALUE:
+- reason = "STATUS_HV_INVALID_REGISTER_VALUE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_HV_INVALID_VTL_STATE:
+- reason = "STATUS_HV_INVALID_VTL_STATE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_HV_NX_NOT_DETECTED:
+- reason = "STATUS_HV_NX_NOT_DETECTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_HV_INVALID_DEVICE_ID:
+- reason = "STATUS_HV_INVALID_DEVICE_ID";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_HV_INVALID_DEVICE_STATE:
+- reason = "STATUS_HV_INVALID_DEVICE_STATE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_HV_PAGE_REQUEST_INVALID:
+- reason = "STATUS_HV_PAGE_REQUEST_INVALID";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_HV_INVALID_CPU_GROUP_ID:
+- reason = "STATUS_HV_INVALID_CPU_GROUP_ID";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_HV_INVALID_CPU_GROUP_STATE:
+- reason = "STATUS_HV_INVALID_CPU_GROUP_STATE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_HV_OPERATION_FAILED:
+- reason = "STATUS_HV_OPERATION_FAILED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_HV_NOT_ALLOWED_WITH_NESTED_VIRT_ACTIVE:
+- reason = "STATUS_HV_NOT_ALLOWED_WITH_NESTED_VIRT_ACTIVE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_HV_INSUFFICIENT_ROOT_MEMORY:
+- reason = "STATUS_HV_INSUFFICIENT_ROOT_MEMORY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_HV_EVENT_BUFFER_ALREADY_FREED:
+- reason = "STATUS_HV_EVENT_BUFFER_ALREADY_FREED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_HV_INSUFFICIENT_CONTIGUOUS_MEMORY:
+- reason = "STATUS_HV_INSUFFICIENT_CONTIGUOUS_MEMORY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_HV_NOT_PRESENT:
+- reason = "STATUS_HV_NOT_PRESENT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_IPSEC_BAD_SPI:
+- reason = "STATUS_IPSEC_BAD_SPI";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_IPSEC_SA_LIFETIME_EXPIRED:
+- reason = "STATUS_IPSEC_SA_LIFETIME_EXPIRED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_IPSEC_WRONG_SA:
+- reason = "STATUS_IPSEC_WRONG_SA";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_IPSEC_REPLAY_CHECK_FAILED:
+- reason = "STATUS_IPSEC_REPLAY_CHECK_FAILED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_IPSEC_INVALID_PACKET:
+- reason = "STATUS_IPSEC_INVALID_PACKET";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_IPSEC_INTEGRITY_CHECK_FAILED:
+- reason = "STATUS_IPSEC_INTEGRITY_CHECK_FAILED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_IPSEC_CLEAR_TEXT_DROP:
+- reason = "STATUS_IPSEC_CLEAR_TEXT_DROP";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_IPSEC_AUTH_FIREWALL_DROP:
+- reason = "STATUS_IPSEC_AUTH_FIREWALL_DROP";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_IPSEC_THROTTLE_DROP:
+- reason = "STATUS_IPSEC_THROTTLE_DROP";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_IPSEC_DOSP_BLOCK:
+- reason = "STATUS_IPSEC_DOSP_BLOCK";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_IPSEC_DOSP_RECEIVED_MULTICAST:
+- reason = "STATUS_IPSEC_DOSP_RECEIVED_MULTICAST";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_IPSEC_DOSP_INVALID_PACKET:
+- reason = "STATUS_IPSEC_DOSP_INVALID_PACKET";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_IPSEC_DOSP_STATE_LOOKUP_FAILED:
+- reason = "STATUS_IPSEC_DOSP_STATE_LOOKUP_FAILED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_IPSEC_DOSP_MAX_ENTRIES:
+- reason = "STATUS_IPSEC_DOSP_MAX_ENTRIES";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_IPSEC_DOSP_KEYMOD_NOT_ALLOWED:
+- reason = "STATUS_IPSEC_DOSP_KEYMOD_NOT_ALLOWED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_IPSEC_DOSP_MAX_PER_IP_RATELIMIT_QUEUES:
+- reason = "STATUS_IPSEC_DOSP_MAX_PER_IP_RATELIMIT_QUEUES";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VID_DUPLICATE_HANDLER:
+- reason = "STATUS_VID_DUPLICATE_HANDLER";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VID_TOO_MANY_HANDLERS:
+- reason = "STATUS_VID_TOO_MANY_HANDLERS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VID_QUEUE_FULL:
+- reason = "STATUS_VID_QUEUE_FULL";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VID_HANDLER_NOT_PRESENT:
+- reason = "STATUS_VID_HANDLER_NOT_PRESENT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VID_INVALID_OBJECT_NAME:
+- reason = "STATUS_VID_INVALID_OBJECT_NAME";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VID_PARTITION_NAME_TOO_LONG:
+- reason = "STATUS_VID_PARTITION_NAME_TOO_LONG";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VID_MESSAGE_QUEUE_NAME_TOO_LONG:
+- reason = "STATUS_VID_MESSAGE_QUEUE_NAME_TOO_LONG";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VID_PARTITION_ALREADY_EXISTS:
+- reason = "STATUS_VID_PARTITION_ALREADY_EXISTS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VID_PARTITION_DOES_NOT_EXIST:
+- reason = "STATUS_VID_PARTITION_DOES_NOT_EXIST";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VID_PARTITION_NAME_NOT_FOUND:
+- reason = "STATUS_VID_PARTITION_NAME_NOT_FOUND";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VID_MESSAGE_QUEUE_ALREADY_EXISTS:
+- reason = "STATUS_VID_MESSAGE_QUEUE_ALREADY_EXISTS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VID_EXCEEDED_MBP_ENTRY_MAP_LIMIT:
+- reason = "STATUS_VID_EXCEEDED_MBP_ENTRY_MAP_LIMIT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VID_MB_STILL_REFERENCED:
+- reason = "STATUS_VID_MB_STILL_REFERENCED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VID_CHILD_GPA_PAGE_SET_CORRUPTED:
+- reason = "STATUS_VID_CHILD_GPA_PAGE_SET_CORRUPTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VID_INVALID_NUMA_SETTINGS:
+- reason = "STATUS_VID_INVALID_NUMA_SETTINGS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VID_INVALID_NUMA_NODE_INDEX:
+- reason = "STATUS_VID_INVALID_NUMA_NODE_INDEX";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VID_NOTIFICATION_QUEUE_ALREADY_ASSOCIATED:
+- reason = "STATUS_VID_NOTIFICATION_QUEUE_ALREADY_ASSOCIATED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VID_INVALID_MEMORY_BLOCK_HANDLE:
+- reason = "STATUS_VID_INVALID_MEMORY_BLOCK_HANDLE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VID_PAGE_RANGE_OVERFLOW:
+- reason = "STATUS_VID_PAGE_RANGE_OVERFLOW";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VID_INVALID_MESSAGE_QUEUE_HANDLE:
+- reason = "STATUS_VID_INVALID_MESSAGE_QUEUE_HANDLE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VID_INVALID_GPA_RANGE_HANDLE:
+- reason = "STATUS_VID_INVALID_GPA_RANGE_HANDLE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VID_NO_MEMORY_BLOCK_NOTIFICATION_QUEUE:
+- reason = "STATUS_VID_NO_MEMORY_BLOCK_NOTIFICATION_QUEUE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VID_MEMORY_BLOCK_LOCK_COUNT_EXCEEDED:
+- reason = "STATUS_VID_MEMORY_BLOCK_LOCK_COUNT_EXCEEDED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VID_INVALID_PPM_HANDLE:
+- reason = "STATUS_VID_INVALID_PPM_HANDLE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VID_MBPS_ARE_LOCKED:
+- reason = "STATUS_VID_MBPS_ARE_LOCKED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VID_MESSAGE_QUEUE_CLOSED:
+- reason = "STATUS_VID_MESSAGE_QUEUE_CLOSED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VID_VIRTUAL_PROCESSOR_LIMIT_EXCEEDED:
+- reason = "STATUS_VID_VIRTUAL_PROCESSOR_LIMIT_EXCEEDED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VID_STOP_PENDING:
+- reason = "STATUS_VID_STOP_PENDING";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VID_INVALID_PROCESSOR_STATE:
+- reason = "STATUS_VID_INVALID_PROCESSOR_STATE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VID_EXCEEDED_KM_CONTEXT_COUNT_LIMIT:
+- reason = "STATUS_VID_EXCEEDED_KM_CONTEXT_COUNT_LIMIT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VID_KM_INTERFACE_ALREADY_INITIALIZED:
+- reason = "STATUS_VID_KM_INTERFACE_ALREADY_INITIALIZED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VID_MB_PROPERTY_ALREADY_SET_RESET:
+- reason = "STATUS_VID_MB_PROPERTY_ALREADY_SET_RESET";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VID_MMIO_RANGE_DESTROYED:
+- reason = "STATUS_VID_MMIO_RANGE_DESTROYED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VID_INVALID_CHILD_GPA_PAGE_SET:
+- reason = "STATUS_VID_INVALID_CHILD_GPA_PAGE_SET";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VID_RESERVE_PAGE_SET_IS_BEING_USED:
+- reason = "STATUS_VID_RESERVE_PAGE_SET_IS_BEING_USED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VID_RESERVE_PAGE_SET_TOO_SMALL:
+- reason = "STATUS_VID_RESERVE_PAGE_SET_TOO_SMALL";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VID_MBP_ALREADY_LOCKED_USING_RESERVED_PAGE:
+- reason = "STATUS_VID_MBP_ALREADY_LOCKED_USING_RESERVED_PAGE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VID_MBP_COUNT_EXCEEDED_LIMIT:
+- reason = "STATUS_VID_MBP_COUNT_EXCEEDED_LIMIT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VID_SAVED_STATE_CORRUPT:
+- reason = "STATUS_VID_SAVED_STATE_CORRUPT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VID_SAVED_STATE_UNRECOGNIZED_ITEM:
+- reason = "STATUS_VID_SAVED_STATE_UNRECOGNIZED_ITEM";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VID_SAVED_STATE_INCOMPATIBLE:
+- reason = "STATUS_VID_SAVED_STATE_INCOMPATIBLE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VID_VTL_ACCESS_DENIED:
+- reason = "STATUS_VID_VTL_ACCESS_DENIED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLMGR_DATABASE_FULL:
+- reason = "STATUS_VOLMGR_DATABASE_FULL";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_CONFIGURATION_CORRUPTED:
+- reason = "STATUS_VOLMGR_DISK_CONFIGURATION_CORRUPTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_CONFIGURATION_NOT_IN_SYNC:
+- reason = "STATUS_VOLMGR_DISK_CONFIGURATION_NOT_IN_SYNC";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLMGR_PACK_CONFIG_UPDATE_FAILED:
+- reason = "STATUS_VOLMGR_PACK_CONFIG_UPDATE_FAILED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_CONTAINS_NON_SIMPLE_VOLUME:
+- reason = "STATUS_VOLMGR_DISK_CONTAINS_NON_SIMPLE_VOLUME";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_DUPLICATE:
+- reason = "STATUS_VOLMGR_DISK_DUPLICATE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_DYNAMIC:
+- reason = "STATUS_VOLMGR_DISK_DYNAMIC";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_ID_INVALID:
+- reason = "STATUS_VOLMGR_DISK_ID_INVALID";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_INVALID:
+- reason = "STATUS_VOLMGR_DISK_INVALID";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_LAST_VOTER:
+- reason = "STATUS_VOLMGR_DISK_LAST_VOTER";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_LAYOUT_INVALID:
+- reason = "STATUS_VOLMGR_DISK_LAYOUT_INVALID";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_LAYOUT_NON_BASIC_BETWEEN_BASIC_PARTITIONS:
+- reason = "STATUS_VOLMGR_DISK_LAYOUT_NON_BASIC_BETWEEN_BASIC_PARTITIONS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_LAYOUT_NOT_CYLINDER_ALIGNED:
+- reason = "STATUS_VOLMGR_DISK_LAYOUT_NOT_CYLINDER_ALIGNED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_LAYOUT_PARTITIONS_TOO_SMALL:
+- reason = "STATUS_VOLMGR_DISK_LAYOUT_PARTITIONS_TOO_SMALL";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_LAYOUT_PRIMARY_BETWEEN_LOGICAL_PARTITIONS:
+- reason = "STATUS_VOLMGR_DISK_LAYOUT_PRIMARY_BETWEEN_LOGICAL_PARTITIONS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_LAYOUT_TOO_MANY_PARTITIONS:
+- reason = "STATUS_VOLMGR_DISK_LAYOUT_TOO_MANY_PARTITIONS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_MISSING:
+- reason = "STATUS_VOLMGR_DISK_MISSING";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_NOT_EMPTY:
+- reason = "STATUS_VOLMGR_DISK_NOT_EMPTY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_NOT_ENOUGH_SPACE:
+- reason = "STATUS_VOLMGR_DISK_NOT_ENOUGH_SPACE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_REVECTORING_FAILED:
+- reason = "STATUS_VOLMGR_DISK_REVECTORING_FAILED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_SECTOR_SIZE_INVALID:
+- reason = "STATUS_VOLMGR_DISK_SECTOR_SIZE_INVALID";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_SET_NOT_CONTAINED:
+- reason = "STATUS_VOLMGR_DISK_SET_NOT_CONTAINED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_USED_BY_MULTIPLE_MEMBERS:
+- reason = "STATUS_VOLMGR_DISK_USED_BY_MULTIPLE_MEMBERS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_USED_BY_MULTIPLE_PLEXES:
+- reason = "STATUS_VOLMGR_DISK_USED_BY_MULTIPLE_PLEXES";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLMGR_DYNAMIC_DISK_NOT_SUPPORTED:
+- reason = "STATUS_VOLMGR_DYNAMIC_DISK_NOT_SUPPORTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLMGR_EXTENT_ALREADY_USED:
+- reason = "STATUS_VOLMGR_EXTENT_ALREADY_USED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLMGR_EXTENT_NOT_CONTIGUOUS:
+- reason = "STATUS_VOLMGR_EXTENT_NOT_CONTIGUOUS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLMGR_EXTENT_NOT_IN_PUBLIC_REGION:
+- reason = "STATUS_VOLMGR_EXTENT_NOT_IN_PUBLIC_REGION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLMGR_EXTENT_NOT_SECTOR_ALIGNED:
+- reason = "STATUS_VOLMGR_EXTENT_NOT_SECTOR_ALIGNED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLMGR_EXTENT_OVERLAPS_EBR_PARTITION:
+- reason = "STATUS_VOLMGR_EXTENT_OVERLAPS_EBR_PARTITION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLMGR_EXTENT_VOLUME_LENGTHS_DO_NOT_MATCH:
+- reason = "STATUS_VOLMGR_EXTENT_VOLUME_LENGTHS_DO_NOT_MATCH";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLMGR_FAULT_TOLERANT_NOT_SUPPORTED:
+- reason = "STATUS_VOLMGR_FAULT_TOLERANT_NOT_SUPPORTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLMGR_INTERLEAVE_LENGTH_INVALID:
+- reason = "STATUS_VOLMGR_INTERLEAVE_LENGTH_INVALID";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLMGR_MAXIMUM_REGISTERED_USERS:
+- reason = "STATUS_VOLMGR_MAXIMUM_REGISTERED_USERS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLMGR_MEMBER_IN_SYNC:
+- reason = "STATUS_VOLMGR_MEMBER_IN_SYNC";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLMGR_MEMBER_INDEX_DUPLICATE:
+- reason = "STATUS_VOLMGR_MEMBER_INDEX_DUPLICATE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLMGR_MEMBER_INDEX_INVALID:
+- reason = "STATUS_VOLMGR_MEMBER_INDEX_INVALID";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLMGR_MEMBER_MISSING:
+- reason = "STATUS_VOLMGR_MEMBER_MISSING";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLMGR_MEMBER_NOT_DETACHED:
+- reason = "STATUS_VOLMGR_MEMBER_NOT_DETACHED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLMGR_MEMBER_REGENERATING:
+- reason = "STATUS_VOLMGR_MEMBER_REGENERATING";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLMGR_ALL_DISKS_FAILED:
+- reason = "STATUS_VOLMGR_ALL_DISKS_FAILED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLMGR_NO_REGISTERED_USERS:
+- reason = "STATUS_VOLMGR_NO_REGISTERED_USERS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLMGR_NO_SUCH_USER:
+- reason = "STATUS_VOLMGR_NO_SUCH_USER";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLMGR_NOTIFICATION_RESET:
+- reason = "STATUS_VOLMGR_NOTIFICATION_RESET";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLMGR_NUMBER_OF_MEMBERS_INVALID:
+- reason = "STATUS_VOLMGR_NUMBER_OF_MEMBERS_INVALID";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLMGR_NUMBER_OF_PLEXES_INVALID:
+- reason = "STATUS_VOLMGR_NUMBER_OF_PLEXES_INVALID";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLMGR_PACK_DUPLICATE:
+- reason = "STATUS_VOLMGR_PACK_DUPLICATE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLMGR_PACK_ID_INVALID:
+- reason = "STATUS_VOLMGR_PACK_ID_INVALID";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLMGR_PACK_INVALID:
+- reason = "STATUS_VOLMGR_PACK_INVALID";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLMGR_PACK_NAME_INVALID:
+- reason = "STATUS_VOLMGR_PACK_NAME_INVALID";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLMGR_PACK_OFFLINE:
+- reason = "STATUS_VOLMGR_PACK_OFFLINE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLMGR_PACK_HAS_QUORUM:
+- reason = "STATUS_VOLMGR_PACK_HAS_QUORUM";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLMGR_PACK_WITHOUT_QUORUM:
+- reason = "STATUS_VOLMGR_PACK_WITHOUT_QUORUM";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLMGR_PARTITION_STYLE_INVALID:
+- reason = "STATUS_VOLMGR_PARTITION_STYLE_INVALID";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLMGR_PARTITION_UPDATE_FAILED:
+- reason = "STATUS_VOLMGR_PARTITION_UPDATE_FAILED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLMGR_PLEX_IN_SYNC:
+- reason = "STATUS_VOLMGR_PLEX_IN_SYNC";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLMGR_PLEX_INDEX_DUPLICATE:
+- reason = "STATUS_VOLMGR_PLEX_INDEX_DUPLICATE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLMGR_PLEX_INDEX_INVALID:
+- reason = "STATUS_VOLMGR_PLEX_INDEX_INVALID";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLMGR_PLEX_LAST_ACTIVE:
+- reason = "STATUS_VOLMGR_PLEX_LAST_ACTIVE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLMGR_PLEX_MISSING:
+- reason = "STATUS_VOLMGR_PLEX_MISSING";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLMGR_PLEX_REGENERATING:
+- reason = "STATUS_VOLMGR_PLEX_REGENERATING";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLMGR_PLEX_TYPE_INVALID:
+- reason = "STATUS_VOLMGR_PLEX_TYPE_INVALID";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLMGR_PLEX_NOT_RAID5:
+- reason = "STATUS_VOLMGR_PLEX_NOT_RAID5";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLMGR_PLEX_NOT_SIMPLE:
+- reason = "STATUS_VOLMGR_PLEX_NOT_SIMPLE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLMGR_STRUCTURE_SIZE_INVALID:
+- reason = "STATUS_VOLMGR_STRUCTURE_SIZE_INVALID";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLMGR_TOO_MANY_NOTIFICATION_REQUESTS:
+- reason = "STATUS_VOLMGR_TOO_MANY_NOTIFICATION_REQUESTS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLMGR_TRANSACTION_IN_PROGRESS:
+- reason = "STATUS_VOLMGR_TRANSACTION_IN_PROGRESS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLMGR_UNEXPECTED_DISK_LAYOUT_CHANGE:
+- reason = "STATUS_VOLMGR_UNEXPECTED_DISK_LAYOUT_CHANGE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLMGR_VOLUME_CONTAINS_MISSING_DISK:
+- reason = "STATUS_VOLMGR_VOLUME_CONTAINS_MISSING_DISK";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLMGR_VOLUME_ID_INVALID:
+- reason = "STATUS_VOLMGR_VOLUME_ID_INVALID";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLMGR_VOLUME_LENGTH_INVALID:
+- reason = "STATUS_VOLMGR_VOLUME_LENGTH_INVALID";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLMGR_VOLUME_LENGTH_NOT_SECTOR_SIZE_MULTIPLE:
+- reason = "STATUS_VOLMGR_VOLUME_LENGTH_NOT_SECTOR_SIZE_MULTIPLE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLMGR_VOLUME_NOT_MIRRORED:
+- reason = "STATUS_VOLMGR_VOLUME_NOT_MIRRORED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLMGR_VOLUME_NOT_RETAINED:
+- reason = "STATUS_VOLMGR_VOLUME_NOT_RETAINED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLMGR_VOLUME_OFFLINE:
+- reason = "STATUS_VOLMGR_VOLUME_OFFLINE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLMGR_VOLUME_RETAINED:
+- reason = "STATUS_VOLMGR_VOLUME_RETAINED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLMGR_NUMBER_OF_EXTENTS_INVALID:
+- reason = "STATUS_VOLMGR_NUMBER_OF_EXTENTS_INVALID";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLMGR_DIFFERENT_SECTOR_SIZE:
+- reason = "STATUS_VOLMGR_DIFFERENT_SECTOR_SIZE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLMGR_BAD_BOOT_DISK:
+- reason = "STATUS_VOLMGR_BAD_BOOT_DISK";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLMGR_PACK_CONFIG_OFFLINE:
+- reason = "STATUS_VOLMGR_PACK_CONFIG_OFFLINE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLMGR_PACK_CONFIG_ONLINE:
+- reason = "STATUS_VOLMGR_PACK_CONFIG_ONLINE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLMGR_NOT_PRIMARY_PACK:
+- reason = "STATUS_VOLMGR_NOT_PRIMARY_PACK";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLMGR_PACK_LOG_UPDATE_FAILED:
+- reason = "STATUS_VOLMGR_PACK_LOG_UPDATE_FAILED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLMGR_NUMBER_OF_DISKS_IN_PLEX_INVALID:
+- reason = "STATUS_VOLMGR_NUMBER_OF_DISKS_IN_PLEX_INVALID";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLMGR_NUMBER_OF_DISKS_IN_MEMBER_INVALID:
+- reason = "STATUS_VOLMGR_NUMBER_OF_DISKS_IN_MEMBER_INVALID";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLMGR_VOLUME_MIRRORED:
+- reason = "STATUS_VOLMGR_VOLUME_MIRRORED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLMGR_PLEX_NOT_SIMPLE_SPANNED:
+- reason = "STATUS_VOLMGR_PLEX_NOT_SIMPLE_SPANNED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLMGR_NO_VALID_LOG_COPIES:
+- reason = "STATUS_VOLMGR_NO_VALID_LOG_COPIES";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLMGR_PRIMARY_PACK_PRESENT:
+- reason = "STATUS_VOLMGR_PRIMARY_PACK_PRESENT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLMGR_NUMBER_OF_DISKS_INVALID:
+- reason = "STATUS_VOLMGR_NUMBER_OF_DISKS_INVALID";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLMGR_MIRROR_NOT_SUPPORTED:
+- reason = "STATUS_VOLMGR_MIRROR_NOT_SUPPORTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLMGR_RAID5_NOT_SUPPORTED:
+- reason = "STATUS_VOLMGR_RAID5_NOT_SUPPORTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_BCD_TOO_MANY_ELEMENTS:
+- reason = "STATUS_BCD_TOO_MANY_ELEMENTS";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VHD_DRIVE_FOOTER_MISSING:
+- reason = "STATUS_VHD_DRIVE_FOOTER_MISSING";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VHD_DRIVE_FOOTER_CHECKSUM_MISMATCH:
+- reason = "STATUS_VHD_DRIVE_FOOTER_CHECKSUM_MISMATCH";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VHD_DRIVE_FOOTER_CORRUPT:
+- reason = "STATUS_VHD_DRIVE_FOOTER_CORRUPT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VHD_FORMAT_UNKNOWN:
+- reason = "STATUS_VHD_FORMAT_UNKNOWN";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VHD_FORMAT_UNSUPPORTED_VERSION:
+- reason = "STATUS_VHD_FORMAT_UNSUPPORTED_VERSION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VHD_SPARSE_HEADER_CHECKSUM_MISMATCH:
+- reason = "STATUS_VHD_SPARSE_HEADER_CHECKSUM_MISMATCH";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VHD_SPARSE_HEADER_UNSUPPORTED_VERSION:
+- reason = "STATUS_VHD_SPARSE_HEADER_UNSUPPORTED_VERSION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VHD_SPARSE_HEADER_CORRUPT:
+- reason = "STATUS_VHD_SPARSE_HEADER_CORRUPT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VHD_BLOCK_ALLOCATION_FAILURE:
+- reason = "STATUS_VHD_BLOCK_ALLOCATION_FAILURE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VHD_BLOCK_ALLOCATION_TABLE_CORRUPT:
+- reason = "STATUS_VHD_BLOCK_ALLOCATION_TABLE_CORRUPT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VHD_INVALID_BLOCK_SIZE:
+- reason = "STATUS_VHD_INVALID_BLOCK_SIZE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VHD_BITMAP_MISMATCH:
+- reason = "STATUS_VHD_BITMAP_MISMATCH";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VHD_PARENT_VHD_NOT_FOUND:
+- reason = "STATUS_VHD_PARENT_VHD_NOT_FOUND";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VHD_CHILD_PARENT_ID_MISMATCH:
+- reason = "STATUS_VHD_CHILD_PARENT_ID_MISMATCH";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VHD_CHILD_PARENT_TIMESTAMP_MISMATCH:
+- reason = "STATUS_VHD_CHILD_PARENT_TIMESTAMP_MISMATCH";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VHD_METADATA_READ_FAILURE:
+- reason = "STATUS_VHD_METADATA_READ_FAILURE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VHD_METADATA_WRITE_FAILURE:
+- reason = "STATUS_VHD_METADATA_WRITE_FAILURE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VHD_INVALID_SIZE:
+- reason = "STATUS_VHD_INVALID_SIZE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VHD_INVALID_FILE_SIZE:
+- reason = "STATUS_VHD_INVALID_FILE_SIZE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VIRTDISK_PROVIDER_NOT_FOUND:
+- reason = "STATUS_VIRTDISK_PROVIDER_NOT_FOUND";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VIRTDISK_NOT_VIRTUAL_DISK:
+- reason = "STATUS_VIRTDISK_NOT_VIRTUAL_DISK";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VHD_PARENT_VHD_ACCESS_DENIED:
+- reason = "STATUS_VHD_PARENT_VHD_ACCESS_DENIED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VHD_CHILD_PARENT_SIZE_MISMATCH:
+- reason = "STATUS_VHD_CHILD_PARENT_SIZE_MISMATCH";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VHD_DIFFERENCING_CHAIN_CYCLE_DETECTED:
+- reason = "STATUS_VHD_DIFFERENCING_CHAIN_CYCLE_DETECTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VHD_DIFFERENCING_CHAIN_ERROR_IN_PARENT:
+- reason = "STATUS_VHD_DIFFERENCING_CHAIN_ERROR_IN_PARENT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VIRTUAL_DISK_LIMITATION:
+- reason = "STATUS_VIRTUAL_DISK_LIMITATION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VHD_INVALID_TYPE:
+- reason = "STATUS_VHD_INVALID_TYPE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VHD_INVALID_STATE:
+- reason = "STATUS_VHD_INVALID_STATE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VIRTDISK_UNSUPPORTED_DISK_SECTOR_SIZE:
+- reason = "STATUS_VIRTDISK_UNSUPPORTED_DISK_SECTOR_SIZE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VIRTDISK_DISK_ALREADY_OWNED:
+- reason = "STATUS_VIRTDISK_DISK_ALREADY_OWNED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VIRTDISK_DISK_ONLINE_AND_WRITABLE:
+- reason = "STATUS_VIRTDISK_DISK_ONLINE_AND_WRITABLE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CTLOG_TRACKING_NOT_INITIALIZED:
+- reason = "STATUS_CTLOG_TRACKING_NOT_INITIALIZED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CTLOG_LOGFILE_SIZE_EXCEEDED_MAXSIZE:
+- reason = "STATUS_CTLOG_LOGFILE_SIZE_EXCEEDED_MAXSIZE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CTLOG_VHD_CHANGED_OFFLINE:
+- reason = "STATUS_CTLOG_VHD_CHANGED_OFFLINE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CTLOG_INVALID_TRACKING_STATE:
+- reason = "STATUS_CTLOG_INVALID_TRACKING_STATE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CTLOG_INCONSISTENT_TRACKING_FILE:
+- reason = "STATUS_CTLOG_INCONSISTENT_TRACKING_FILE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VHD_METADATA_FULL:
+- reason = "STATUS_VHD_METADATA_FULL";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VHD_INVALID_CHANGE_TRACKING_ID:
+- reason = "STATUS_VHD_INVALID_CHANGE_TRACKING_ID";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VHD_CHANGE_TRACKING_DISABLED:
+- reason = "STATUS_VHD_CHANGE_TRACKING_DISABLED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VHD_MISSING_CHANGE_TRACKING_INFORMATION:
+- reason = "STATUS_VHD_MISSING_CHANGE_TRACKING_INFORMATION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VHD_RESIZE_WOULD_TRUNCATE_DATA:
+- reason = "STATUS_VHD_RESIZE_WOULD_TRUNCATE_DATA";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VHD_COULD_NOT_COMPUTE_MINIMUM_VIRTUAL_SIZE:
+- reason = "STATUS_VHD_COULD_NOT_COMPUTE_MINIMUM_VIRTUAL_SIZE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VHD_ALREADY_AT_OR_BELOW_MINIMUM_VIRTUAL_SIZE:
+- reason = "STATUS_VHD_ALREADY_AT_OR_BELOW_MINIMUM_VIRTUAL_SIZE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_RKF_KEY_NOT_FOUND:
+- reason = "STATUS_RKF_KEY_NOT_FOUND";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_RKF_DUPLICATE_KEY:
+- reason = "STATUS_RKF_DUPLICATE_KEY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_RKF_BLOB_FULL:
+- reason = "STATUS_RKF_BLOB_FULL";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_RKF_STORE_FULL:
+- reason = "STATUS_RKF_STORE_FULL";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_RKF_FILE_BLOCKED:
+- reason = "STATUS_RKF_FILE_BLOCKED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_RKF_ACTIVE_KEY:
+- reason = "STATUS_RKF_ACTIVE_KEY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_RDBSS_RESTART_OPERATION:
+- reason = "STATUS_RDBSS_RESTART_OPERATION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_RDBSS_CONTINUE_OPERATION:
+- reason = "STATUS_RDBSS_CONTINUE_OPERATION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_RDBSS_POST_OPERATION:
+- reason = "STATUS_RDBSS_POST_OPERATION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_RDBSS_RETRY_LOOKUP:
+- reason = "STATUS_RDBSS_RETRY_LOOKUP";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_BTH_ATT_INVALID_HANDLE:
+- reason = "STATUS_BTH_ATT_INVALID_HANDLE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_BTH_ATT_READ_NOT_PERMITTED:
+- reason = "STATUS_BTH_ATT_READ_NOT_PERMITTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_BTH_ATT_WRITE_NOT_PERMITTED:
+- reason = "STATUS_BTH_ATT_WRITE_NOT_PERMITTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_BTH_ATT_INVALID_PDU:
+- reason = "STATUS_BTH_ATT_INVALID_PDU";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_BTH_ATT_INSUFFICIENT_AUTHENTICATION:
+- reason = "STATUS_BTH_ATT_INSUFFICIENT_AUTHENTICATION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_BTH_ATT_REQUEST_NOT_SUPPORTED:
+- reason = "STATUS_BTH_ATT_REQUEST_NOT_SUPPORTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_BTH_ATT_INVALID_OFFSET:
+- reason = "STATUS_BTH_ATT_INVALID_OFFSET";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_BTH_ATT_INSUFFICIENT_AUTHORIZATION:
+- reason = "STATUS_BTH_ATT_INSUFFICIENT_AUTHORIZATION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_BTH_ATT_PREPARE_QUEUE_FULL:
+- reason = "STATUS_BTH_ATT_PREPARE_QUEUE_FULL";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_BTH_ATT_ATTRIBUTE_NOT_FOUND:
+- reason = "STATUS_BTH_ATT_ATTRIBUTE_NOT_FOUND";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_BTH_ATT_ATTRIBUTE_NOT_LONG:
+- reason = "STATUS_BTH_ATT_ATTRIBUTE_NOT_LONG";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_BTH_ATT_INSUFFICIENT_ENCRYPTION_KEY_SIZE:
+- reason = "STATUS_BTH_ATT_INSUFFICIENT_ENCRYPTION_KEY_SIZE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_BTH_ATT_INVALID_ATTRIBUTE_VALUE_LENGTH:
+- reason = "STATUS_BTH_ATT_INVALID_ATTRIBUTE_VALUE_LENGTH";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_BTH_ATT_UNLIKELY:
+- reason = "STATUS_BTH_ATT_UNLIKELY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_BTH_ATT_INSUFFICIENT_ENCRYPTION:
+- reason = "STATUS_BTH_ATT_INSUFFICIENT_ENCRYPTION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_BTH_ATT_UNSUPPORTED_GROUP_TYPE:
+- reason = "STATUS_BTH_ATT_UNSUPPORTED_GROUP_TYPE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_BTH_ATT_INSUFFICIENT_RESOURCES:
+- reason = "STATUS_BTH_ATT_INSUFFICIENT_RESOURCES";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_BTH_ATT_UNKNOWN_ERROR:
+- reason = "STATUS_BTH_ATT_UNKNOWN_ERROR";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SECUREBOOT_ROLLBACK_DETECTED:
+- reason = "STATUS_SECUREBOOT_ROLLBACK_DETECTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SECUREBOOT_POLICY_VIOLATION:
+- reason = "STATUS_SECUREBOOT_POLICY_VIOLATION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SECUREBOOT_INVALID_POLICY:
+- reason = "STATUS_SECUREBOOT_INVALID_POLICY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SECUREBOOT_POLICY_PUBLISHER_NOT_FOUND:
+- reason = "STATUS_SECUREBOOT_POLICY_PUBLISHER_NOT_FOUND";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SECUREBOOT_POLICY_NOT_SIGNED:
+- reason = "STATUS_SECUREBOOT_POLICY_NOT_SIGNED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SECUREBOOT_FILE_REPLACED:
+- reason = "STATUS_SECUREBOOT_FILE_REPLACED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SECUREBOOT_POLICY_NOT_AUTHORIZED:
+- reason = "STATUS_SECUREBOOT_POLICY_NOT_AUTHORIZED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SECUREBOOT_POLICY_UNKNOWN:
+- reason = "STATUS_SECUREBOOT_POLICY_UNKNOWN";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SECUREBOOT_POLICY_MISSING_ANTIROLLBACKVERSION:
+- reason = "STATUS_SECUREBOOT_POLICY_MISSING_ANTIROLLBACKVERSION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SECUREBOOT_PLATFORM_ID_MISMATCH:
+- reason = "STATUS_SECUREBOOT_PLATFORM_ID_MISMATCH";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SECUREBOOT_POLICY_ROLLBACK_DETECTED:
+- reason = "STATUS_SECUREBOOT_POLICY_ROLLBACK_DETECTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SECUREBOOT_POLICY_UPGRADE_MISMATCH:
+- reason = "STATUS_SECUREBOOT_POLICY_UPGRADE_MISMATCH";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SECUREBOOT_REQUIRED_POLICY_FILE_MISSING:
+- reason = "STATUS_SECUREBOOT_REQUIRED_POLICY_FILE_MISSING";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SECUREBOOT_NOT_BASE_POLICY:
+- reason = "STATUS_SECUREBOOT_NOT_BASE_POLICY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SECUREBOOT_NOT_SUPPLEMENTAL_POLICY:
+- reason = "STATUS_SECUREBOOT_NOT_SUPPLEMENTAL_POLICY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_AUDIO_ENGINE_NODE_NOT_FOUND:
+- reason = "STATUS_AUDIO_ENGINE_NODE_NOT_FOUND";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_HDAUDIO_EMPTY_CONNECTION_LIST:
+- reason = "STATUS_HDAUDIO_EMPTY_CONNECTION_LIST";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_HDAUDIO_CONNECTION_LIST_NOT_SUPPORTED:
+- reason = "STATUS_HDAUDIO_CONNECTION_LIST_NOT_SUPPORTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_HDAUDIO_NO_LOGICAL_DEVICES_CREATED:
+- reason = "STATUS_HDAUDIO_NO_LOGICAL_DEVICES_CREATED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_HDAUDIO_NULL_LINKED_LIST_ENTRY:
+- reason = "STATUS_HDAUDIO_NULL_LINKED_LIST_ENTRY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VSM_NOT_INITIALIZED:
+- reason = "STATUS_VSM_NOT_INITIALIZED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VSM_DMA_PROTECTION_NOT_IN_USE:
+- reason = "STATUS_VSM_DMA_PROTECTION_NOT_IN_USE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLSNAP_BOOTFILE_NOT_VALID:
+- reason = "STATUS_VOLSNAP_BOOTFILE_NOT_VALID";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VOLSNAP_ACTIVATION_TIMEOUT:
+- reason = "STATUS_VOLSNAP_ACTIVATION_TIMEOUT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_IO_PREEMPTED:
+- reason = "STATUS_IO_PREEMPTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SVHDX_ERROR_STORED:
+- reason = "STATUS_SVHDX_ERROR_STORED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SVHDX_ERROR_NOT_AVAILABLE:
+- reason = "STATUS_SVHDX_ERROR_NOT_AVAILABLE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SVHDX_UNIT_ATTENTION_AVAILABLE:
+- reason = "STATUS_SVHDX_UNIT_ATTENTION_AVAILABLE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SVHDX_UNIT_ATTENTION_CAPACITY_DATA_CHANGED:
+- reason = "STATUS_SVHDX_UNIT_ATTENTION_CAPACITY_DATA_CHANGED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SVHDX_UNIT_ATTENTION_RESERVATIONS_PREEMPTED:
+- reason = "STATUS_SVHDX_UNIT_ATTENTION_RESERVATIONS_PREEMPTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SVHDX_UNIT_ATTENTION_RESERVATIONS_RELEASED:
+- reason = "STATUS_SVHDX_UNIT_ATTENTION_RESERVATIONS_RELEASED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SVHDX_UNIT_ATTENTION_REGISTRATIONS_PREEMPTED:
+- reason = "STATUS_SVHDX_UNIT_ATTENTION_REGISTRATIONS_PREEMPTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SVHDX_UNIT_ATTENTION_OPERATING_DEFINITION_CHANGED:
+- reason = "STATUS_SVHDX_UNIT_ATTENTION_OPERATING_DEFINITION_CHANGED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SVHDX_RESERVATION_CONFLICT:
+- reason = "STATUS_SVHDX_RESERVATION_CONFLICT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SVHDX_WRONG_FILE_TYPE:
+- reason = "STATUS_SVHDX_WRONG_FILE_TYPE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SVHDX_VERSION_MISMATCH:
+- reason = "STATUS_SVHDX_VERSION_MISMATCH";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VHD_SHARED:
+- reason = "STATUS_VHD_SHARED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SVHDX_NO_INITIATOR:
+- reason = "STATUS_SVHDX_NO_INITIATOR";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_VHDSET_BACKING_STORAGE_NOT_FOUND:
+- reason = "STATUS_VHDSET_BACKING_STORAGE_NOT_FOUND";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SMB_NO_PREAUTH_INTEGRITY_HASH_OVERLAP:
+- reason = "STATUS_SMB_NO_PREAUTH_INTEGRITY_HASH_OVERLAP";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SMB_BAD_CLUSTER_DIALECT:
+- reason = "STATUS_SMB_BAD_CLUSTER_DIALECT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SMB_GUEST_LOGON_BLOCKED:
+- reason = "STATUS_SMB_GUEST_LOGON_BLOCKED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SPACES_FAULT_DOMAIN_TYPE_INVALID:
+- reason = "STATUS_SPACES_FAULT_DOMAIN_TYPE_INVALID";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SPACES_RESILIENCY_TYPE_INVALID:
+- reason = "STATUS_SPACES_RESILIENCY_TYPE_INVALID";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SPACES_DRIVE_SECTOR_SIZE_INVALID:
+- reason = "STATUS_SPACES_DRIVE_SECTOR_SIZE_INVALID";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SPACES_DRIVE_REDUNDANCY_INVALID:
+- reason = "STATUS_SPACES_DRIVE_REDUNDANCY_INVALID";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SPACES_NUMBER_OF_DATA_COPIES_INVALID:
+- reason = "STATUS_SPACES_NUMBER_OF_DATA_COPIES_INVALID";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SPACES_INTERLEAVE_LENGTH_INVALID:
+- reason = "STATUS_SPACES_INTERLEAVE_LENGTH_INVALID";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SPACES_NUMBER_OF_COLUMNS_INVALID:
+- reason = "STATUS_SPACES_NUMBER_OF_COLUMNS_INVALID";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SPACES_NOT_ENOUGH_DRIVES:
+- reason = "STATUS_SPACES_NOT_ENOUGH_DRIVES";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SPACES_EXTENDED_ERROR:
+- reason = "STATUS_SPACES_EXTENDED_ERROR";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SPACES_PROVISIONING_TYPE_INVALID:
+- reason = "STATUS_SPACES_PROVISIONING_TYPE_INVALID";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SPACES_ALLOCATION_SIZE_INVALID:
+- reason = "STATUS_SPACES_ALLOCATION_SIZE_INVALID";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SPACES_ENCLOSURE_AWARE_INVALID:
+- reason = "STATUS_SPACES_ENCLOSURE_AWARE_INVALID";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SPACES_WRITE_CACHE_SIZE_INVALID:
+- reason = "STATUS_SPACES_WRITE_CACHE_SIZE_INVALID";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SPACES_NUMBER_OF_GROUPS_INVALID:
+- reason = "STATUS_SPACES_NUMBER_OF_GROUPS_INVALID";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SPACES_DRIVE_OPERATIONAL_STATE_INVALID:
+- reason = "STATUS_SPACES_DRIVE_OPERATIONAL_STATE_INVALID";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SPACES_UPDATE_COLUMN_STATE:
+- reason = "STATUS_SPACES_UPDATE_COLUMN_STATE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SPACES_MAP_REQUIRED:
+- reason = "STATUS_SPACES_MAP_REQUIRED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SPACES_UNSUPPORTED_VERSION:
+- reason = "STATUS_SPACES_UNSUPPORTED_VERSION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SPACES_CORRUPT_METADATA:
+- reason = "STATUS_SPACES_CORRUPT_METADATA";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SPACES_DRT_FULL:
+- reason = "STATUS_SPACES_DRT_FULL";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SPACES_INCONSISTENCY:
+- reason = "STATUS_SPACES_INCONSISTENCY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SPACES_LOG_NOT_READY:
+- reason = "STATUS_SPACES_LOG_NOT_READY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SPACES_NO_REDUNDANCY:
+- reason = "STATUS_SPACES_NO_REDUNDANCY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SPACES_DRIVE_NOT_READY:
+- reason = "STATUS_SPACES_DRIVE_NOT_READY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SPACES_DRIVE_SPLIT:
+- reason = "STATUS_SPACES_DRIVE_SPLIT";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SPACES_DRIVE_LOST_DATA:
+- reason = "STATUS_SPACES_DRIVE_LOST_DATA";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SPACES_ENTRY_INCOMPLETE:
+- reason = "STATUS_SPACES_ENTRY_INCOMPLETE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SPACES_ENTRY_INVALID:
+- reason = "STATUS_SPACES_ENTRY_INVALID";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SPACES_MARK_DIRTY:
+- reason = "STATUS_SPACES_MARK_DIRTY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SECCORE_INVALID_COMMAND:
+- reason = "STATUS_SECCORE_INVALID_COMMAND";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SYSTEM_INTEGRITY_ROLLBACK_DETECTED:
+- reason = "STATUS_SYSTEM_INTEGRITY_ROLLBACK_DETECTED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SYSTEM_INTEGRITY_POLICY_VIOLATION:
+- reason = "STATUS_SYSTEM_INTEGRITY_POLICY_VIOLATION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SYSTEM_INTEGRITY_INVALID_POLICY:
+- reason = "STATUS_SYSTEM_INTEGRITY_INVALID_POLICY";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SYSTEM_INTEGRITY_POLICY_NOT_SIGNED:
+- reason = "STATUS_SYSTEM_INTEGRITY_POLICY_NOT_SIGNED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SYSTEM_INTEGRITY_TOO_MANY_POLICIES:
+- reason = "STATUS_SYSTEM_INTEGRITY_TOO_MANY_POLICIES";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_SYSTEM_INTEGRITY_SUPPLEMENTAL_POLICY_NOT_AUTHORIZED:
+- reason = "STATUS_SYSTEM_INTEGRITY_SUPPLEMENTAL_POLICY_NOT_AUTHORIZED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_NO_APPLICABLE_APP_LICENSES_FOUND:
+- reason = "STATUS_NO_APPLICABLE_APP_LICENSES_FOUND";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CLIP_LICENSE_NOT_FOUND:
+- reason = "STATUS_CLIP_LICENSE_NOT_FOUND";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CLIP_DEVICE_LICENSE_MISSING:
+- reason = "STATUS_CLIP_DEVICE_LICENSE_MISSING";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CLIP_LICENSE_INVALID_SIGNATURE:
+- reason = "STATUS_CLIP_LICENSE_INVALID_SIGNATURE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CLIP_KEYHOLDER_LICENSE_MISSING_OR_INVALID:
+- reason = "STATUS_CLIP_KEYHOLDER_LICENSE_MISSING_OR_INVALID";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CLIP_LICENSE_EXPIRED:
+- reason = "STATUS_CLIP_LICENSE_EXPIRED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CLIP_LICENSE_SIGNED_BY_UNKNOWN_SOURCE:
+- reason = "STATUS_CLIP_LICENSE_SIGNED_BY_UNKNOWN_SOURCE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CLIP_LICENSE_NOT_SIGNED:
+- reason = "STATUS_CLIP_LICENSE_NOT_SIGNED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CLIP_LICENSE_HARDWARE_ID_OUT_OF_TOLERANCE:
+- reason = "STATUS_CLIP_LICENSE_HARDWARE_ID_OUT_OF_TOLERANCE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_CLIP_LICENSE_DEVICE_ID_MISMATCH:
+- reason = "STATUS_CLIP_LICENSE_DEVICE_ID_MISMATCH";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PLATFORM_MANIFEST_NOT_AUTHORIZED:
+- reason = "STATUS_PLATFORM_MANIFEST_NOT_AUTHORIZED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PLATFORM_MANIFEST_INVALID:
+- reason = "STATUS_PLATFORM_MANIFEST_INVALID";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PLATFORM_MANIFEST_FILE_NOT_AUTHORIZED:
+- reason = "STATUS_PLATFORM_MANIFEST_FILE_NOT_AUTHORIZED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PLATFORM_MANIFEST_CATALOG_NOT_AUTHORIZED:
+- reason = "STATUS_PLATFORM_MANIFEST_CATALOG_NOT_AUTHORIZED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PLATFORM_MANIFEST_BINARY_ID_NOT_FOUND:
+- reason = "STATUS_PLATFORM_MANIFEST_BINARY_ID_NOT_FOUND";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PLATFORM_MANIFEST_NOT_ACTIVE:
+- reason = "STATUS_PLATFORM_MANIFEST_NOT_ACTIVE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_PLATFORM_MANIFEST_NOT_SIGNED:
+- reason = "STATUS_PLATFORM_MANIFEST_NOT_SIGNED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_APPEXEC_CONDITION_NOT_SATISFIED:
+- reason = "STATUS_APPEXEC_CONDITION_NOT_SATISFIED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_APPEXEC_HANDLE_INVALIDATED:
+- reason = "STATUS_APPEXEC_HANDLE_INVALIDATED";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_APPEXEC_INVALID_HOST_GENERATION:
+- reason = "STATUS_APPEXEC_INVALID_HOST_GENERATION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_APPEXEC_UNEXPECTED_PROCESS_REGISTRATION:
+- reason = "STATUS_APPEXEC_UNEXPECTED_PROCESS_REGISTRATION";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_APPEXEC_INVALID_HOST_STATE:
+- reason = "STATUS_APPEXEC_INVALID_HOST_STATE";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_APPEXEC_NO_DONOR:
+- reason = "STATUS_APPEXEC_NO_DONOR";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_APPEXEC_HOST_ID_MISMATCH:
+- reason = "STATUS_APPEXEC_HOST_ID_MISMATCH";
+- break;
+- case MD_NTSTATUS_WIN_STATUS_APPEXEC_UNKNOWN_USER:
+- reason = "STATUS_APPEXEC_UNKNOWN_USER";
+- break;
+- default: {
+- char reason_string[11];
+- snprintf(reason_string, sizeof(reason_string), "0x%08x", ntstatus);
+- reason = reason_string;
+- break;
+- }
++// The content of this array was created from ntstatus.h in the 10 SDK
++// (version 10.0.19041.0) with
++//
++// egrep '#define [A-Z_0-9]+\s+\(\(NTSTATUS\)0x[048C][0-9A-F]+L\)' ntstatus.h
++// | tr -d '\r'
++// | sed -r 's@#define ([A-Z_0-9]+)\s+\(\(NTSTATUS\)(0x[048C][0-9A-F]+)L\).*@\2 \1@'
++// | sort
++// | sed -r 's@(0x[048C][0-9A-F]+) ([A-Z_0-9]+)@ MD_NTSTATUS_WIN_\2,@'
++//
++// With easy copy to clipboard with
++// | xclip -selection c # on linux
++// | clip # on windows
++// | pbcopy # on mac
++static const uint32_t kNTStatusValues[] = {
++ MD_NTSTATUS_WIN_STATUS_SUCCESS,
++ MD_NTSTATUS_WIN_STATUS_WAIT_0,
++ MD_NTSTATUS_WIN_STATUS_WAIT_1,
++ MD_NTSTATUS_WIN_STATUS_WAIT_2,
++ MD_NTSTATUS_WIN_STATUS_WAIT_3,
++ MD_NTSTATUS_WIN_STATUS_WAIT_63,
++ MD_NTSTATUS_WIN_STATUS_ABANDONED,
++ MD_NTSTATUS_WIN_STATUS_ABANDONED_WAIT_0,
++ MD_NTSTATUS_WIN_STATUS_ABANDONED_WAIT_63,
++ MD_NTSTATUS_WIN_STATUS_USER_APC,
++ MD_NTSTATUS_WIN_STATUS_ALREADY_COMPLETE,
++ MD_NTSTATUS_WIN_STATUS_KERNEL_APC,
++ MD_NTSTATUS_WIN_STATUS_ALERTED,
++ MD_NTSTATUS_WIN_STATUS_TIMEOUT,
++ MD_NTSTATUS_WIN_STATUS_PENDING,
++ MD_NTSTATUS_WIN_STATUS_REPARSE,
++ MD_NTSTATUS_WIN_STATUS_MORE_ENTRIES,
++ MD_NTSTATUS_WIN_STATUS_NOT_ALL_ASSIGNED,
++ MD_NTSTATUS_WIN_STATUS_SOME_NOT_MAPPED,
++ MD_NTSTATUS_WIN_STATUS_OPLOCK_BREAK_IN_PROGRESS,
++ MD_NTSTATUS_WIN_STATUS_VOLUME_MOUNTED,
++ MD_NTSTATUS_WIN_STATUS_RXACT_COMMITTED,
++ MD_NTSTATUS_WIN_STATUS_NOTIFY_CLEANUP,
++ MD_NTSTATUS_WIN_STATUS_NOTIFY_ENUM_DIR,
++ MD_NTSTATUS_WIN_STATUS_NO_QUOTAS_FOR_ACCOUNT,
++ MD_NTSTATUS_WIN_STATUS_PRIMARY_TRANSPORT_CONNECT_FAILED,
++ MD_NTSTATUS_WIN_STATUS_PAGE_FAULT_TRANSITION,
++ MD_NTSTATUS_WIN_STATUS_PAGE_FAULT_DEMAND_ZERO,
++ MD_NTSTATUS_WIN_STATUS_PAGE_FAULT_COPY_ON_WRITE,
++ MD_NTSTATUS_WIN_STATUS_PAGE_FAULT_GUARD_PAGE,
++ MD_NTSTATUS_WIN_STATUS_PAGE_FAULT_PAGING_FILE,
++ MD_NTSTATUS_WIN_STATUS_CACHE_PAGE_LOCKED,
++ MD_NTSTATUS_WIN_STATUS_CRASH_DUMP,
++ MD_NTSTATUS_WIN_STATUS_BUFFER_ALL_ZEROS,
++ MD_NTSTATUS_WIN_STATUS_REPARSE_OBJECT,
++ MD_NTSTATUS_WIN_STATUS_RESOURCE_REQUIREMENTS_CHANGED,
++ MD_NTSTATUS_WIN_STATUS_TRANSLATION_COMPLETE,
++ MD_NTSTATUS_WIN_STATUS_DS_MEMBERSHIP_EVALUATED_LOCALLY,
++ MD_NTSTATUS_WIN_STATUS_NOTHING_TO_TERMINATE,
++ MD_NTSTATUS_WIN_STATUS_PROCESS_NOT_IN_JOB,
++ MD_NTSTATUS_WIN_STATUS_PROCESS_IN_JOB,
++ MD_NTSTATUS_WIN_STATUS_VOLSNAP_HIBERNATE_READY,
++ MD_NTSTATUS_WIN_STATUS_FSFILTER_OP_COMPLETED_SUCCESSFULLY,
++ MD_NTSTATUS_WIN_STATUS_INTERRUPT_VECTOR_ALREADY_CONNECTED,
++ MD_NTSTATUS_WIN_STATUS_INTERRUPT_STILL_CONNECTED,
++ MD_NTSTATUS_WIN_STATUS_PROCESS_CLONED,
++ MD_NTSTATUS_WIN_STATUS_FILE_LOCKED_WITH_ONLY_READERS,
++ MD_NTSTATUS_WIN_STATUS_FILE_LOCKED_WITH_WRITERS,
++ MD_NTSTATUS_WIN_STATUS_VALID_IMAGE_HASH,
++ MD_NTSTATUS_WIN_STATUS_VALID_CATALOG_HASH,
++ MD_NTSTATUS_WIN_STATUS_VALID_STRONG_CODE_HASH,
++ MD_NTSTATUS_WIN_STATUS_GHOSTED,
++ MD_NTSTATUS_WIN_STATUS_DATA_OVERWRITTEN,
++ MD_NTSTATUS_WIN_STATUS_RESOURCEMANAGER_READ_ONLY,
++ MD_NTSTATUS_WIN_STATUS_RING_PREVIOUSLY_EMPTY,
++ MD_NTSTATUS_WIN_STATUS_RING_PREVIOUSLY_FULL,
++ MD_NTSTATUS_WIN_STATUS_RING_PREVIOUSLY_ABOVE_QUOTA,
++ MD_NTSTATUS_WIN_STATUS_RING_NEWLY_EMPTY,
++ MD_NTSTATUS_WIN_STATUS_RING_SIGNAL_OPPOSITE_ENDPOINT,
++ MD_NTSTATUS_WIN_STATUS_OPLOCK_SWITCHED_TO_NEW_HANDLE,
++ MD_NTSTATUS_WIN_STATUS_OPLOCK_HANDLE_CLOSED,
++ MD_NTSTATUS_WIN_STATUS_WAIT_FOR_OPLOCK,
++ MD_NTSTATUS_WIN_STATUS_REPARSE_GLOBAL,
++ MD_NTSTATUS_WIN_DBG_EXCEPTION_HANDLED,
++ MD_NTSTATUS_WIN_DBG_CONTINUE,
++ MD_NTSTATUS_WIN_STATUS_FLT_IO_COMPLETE,
++ MD_NTSTATUS_WIN_STATUS_RTPM_CONTEXT_CONTINUE,
++ MD_NTSTATUS_WIN_STATUS_RTPM_CONTEXT_COMPLETE,
++ MD_NTSTATUS_WIN_STATUS_HV_PENDING_PAGE_REQUESTS,
++ MD_NTSTATUS_WIN_STATUS_SPACES_REPAIRED,
++ MD_NTSTATUS_WIN_STATUS_SPACES_PAUSE,
++ MD_NTSTATUS_WIN_STATUS_SPACES_COMPLETE,
++ MD_NTSTATUS_WIN_STATUS_SPACES_REDIRECT,
++ MD_NTSTATUS_WIN_STATUS_OBJECT_NAME_EXISTS,
++ MD_NTSTATUS_WIN_STATUS_THREAD_WAS_SUSPENDED,
++ MD_NTSTATUS_WIN_STATUS_WORKING_SET_LIMIT_RANGE,
++ MD_NTSTATUS_WIN_STATUS_IMAGE_NOT_AT_BASE,
++ MD_NTSTATUS_WIN_STATUS_RXACT_STATE_CREATED,
++ MD_NTSTATUS_WIN_STATUS_SEGMENT_NOTIFICATION,
++ MD_NTSTATUS_WIN_STATUS_LOCAL_USER_SESSION_KEY,
++ MD_NTSTATUS_WIN_STATUS_BAD_CURRENT_DIRECTORY,
++ MD_NTSTATUS_WIN_STATUS_SERIAL_MORE_WRITES,
++ MD_NTSTATUS_WIN_STATUS_REGISTRY_RECOVERED,
++ MD_NTSTATUS_WIN_STATUS_FT_READ_RECOVERY_FROM_BACKUP,
++ MD_NTSTATUS_WIN_STATUS_FT_WRITE_RECOVERY,
++ MD_NTSTATUS_WIN_STATUS_SERIAL_COUNTER_TIMEOUT,
++ MD_NTSTATUS_WIN_STATUS_NULL_LM_PASSWORD,
++ MD_NTSTATUS_WIN_STATUS_IMAGE_MACHINE_TYPE_MISMATCH,
++ MD_NTSTATUS_WIN_STATUS_RECEIVE_PARTIAL,
++ MD_NTSTATUS_WIN_STATUS_RECEIVE_EXPEDITED,
++ MD_NTSTATUS_WIN_STATUS_RECEIVE_PARTIAL_EXPEDITED,
++ MD_NTSTATUS_WIN_STATUS_EVENT_DONE,
++ MD_NTSTATUS_WIN_STATUS_EVENT_PENDING,
++ MD_NTSTATUS_WIN_STATUS_CHECKING_FILE_SYSTEM,
++ MD_NTSTATUS_WIN_STATUS_FATAL_APP_EXIT,
++ MD_NTSTATUS_WIN_STATUS_PREDEFINED_HANDLE,
++ MD_NTSTATUS_WIN_STATUS_WAS_UNLOCKED,
++ MD_NTSTATUS_WIN_STATUS_SERVICE_NOTIFICATION,
++ MD_NTSTATUS_WIN_STATUS_WAS_LOCKED,
++ MD_NTSTATUS_WIN_STATUS_LOG_HARD_ERROR,
++ MD_NTSTATUS_WIN_STATUS_ALREADY_WIN32,
++ MD_NTSTATUS_WIN_STATUS_WX86_UNSIMULATE,
++ MD_NTSTATUS_WIN_STATUS_WX86_CONTINUE,
++ MD_NTSTATUS_WIN_STATUS_WX86_SINGLE_STEP,
++ MD_NTSTATUS_WIN_STATUS_WX86_BREAKPOINT,
++ MD_NTSTATUS_WIN_STATUS_WX86_EXCEPTION_CONTINUE,
++ MD_NTSTATUS_WIN_STATUS_WX86_EXCEPTION_LASTCHANCE,
++ MD_NTSTATUS_WIN_STATUS_WX86_EXCEPTION_CHAIN,
++ MD_NTSTATUS_WIN_STATUS_IMAGE_MACHINE_TYPE_MISMATCH_EXE,
++ MD_NTSTATUS_WIN_STATUS_NO_YIELD_PERFORMED,
++ MD_NTSTATUS_WIN_STATUS_TIMER_RESUME_IGNORED,
++ MD_NTSTATUS_WIN_STATUS_ARBITRATION_UNHANDLED,
++ MD_NTSTATUS_WIN_STATUS_CARDBUS_NOT_SUPPORTED,
++ MD_NTSTATUS_WIN_STATUS_WX86_CREATEWX86TIB,
++ MD_NTSTATUS_WIN_STATUS_MP_PROCESSOR_MISMATCH,
++ MD_NTSTATUS_WIN_STATUS_HIBERNATED,
++ MD_NTSTATUS_WIN_STATUS_RESUME_HIBERNATION,
++ MD_NTSTATUS_WIN_STATUS_FIRMWARE_UPDATED,
++ MD_NTSTATUS_WIN_STATUS_DRIVERS_LEAKING_LOCKED_PAGES,
++ MD_NTSTATUS_WIN_STATUS_MESSAGE_RETRIEVED,
++ MD_NTSTATUS_WIN_STATUS_SYSTEM_POWERSTATE_TRANSITION,
++ MD_NTSTATUS_WIN_STATUS_ALPC_CHECK_COMPLETION_LIST,
++ MD_NTSTATUS_WIN_STATUS_SYSTEM_POWERSTATE_COMPLEX_TRANSITION,
++ MD_NTSTATUS_WIN_STATUS_ACCESS_AUDIT_BY_POLICY,
++ MD_NTSTATUS_WIN_STATUS_ABANDON_HIBERFILE,
++ MD_NTSTATUS_WIN_STATUS_BIZRULES_NOT_ENABLED,
++ MD_NTSTATUS_WIN_STATUS_FT_READ_FROM_COPY,
++ MD_NTSTATUS_WIN_STATUS_IMAGE_AT_DIFFERENT_BASE,
++ MD_NTSTATUS_WIN_STATUS_PATCH_DEFERRED,
++ MD_NTSTATUS_WIN_STATUS_WAKE_SYSTEM,
++ MD_NTSTATUS_WIN_STATUS_DS_SHUTTING_DOWN,
++ MD_NTSTATUS_WIN_STATUS_DISK_REPAIR_REDIRECTED,
++ MD_NTSTATUS_WIN_STATUS_SERVICES_FAILED_AUTOSTART,
++ MD_NTSTATUS_WIN_DBG_REPLY_LATER,
++ MD_NTSTATUS_WIN_DBG_UNABLE_TO_PROVIDE_HANDLE,
++ MD_NTSTATUS_WIN_DBG_TERMINATE_THREAD,
++ MD_NTSTATUS_WIN_DBG_TERMINATE_PROCESS,
++ MD_NTSTATUS_WIN_DBG_CONTROL_C,
++ MD_NTSTATUS_WIN_DBG_PRINTEXCEPTION_C,
++ MD_NTSTATUS_WIN_DBG_RIPEXCEPTION,
++ MD_NTSTATUS_WIN_DBG_CONTROL_BREAK,
++ MD_NTSTATUS_WIN_DBG_COMMAND_EXCEPTION,
++ MD_NTSTATUS_WIN_DBG_PRINTEXCEPTION_WIDE_C,
++ MD_NTSTATUS_WIN_RPC_NT_UUID_LOCAL_ONLY,
++ MD_NTSTATUS_WIN_RPC_NT_SEND_INCOMPLETE,
++ MD_NTSTATUS_WIN_STATUS_CTX_CDM_CONNECT,
++ MD_NTSTATUS_WIN_STATUS_CTX_CDM_DISCONNECT,
++ MD_NTSTATUS_WIN_STATUS_SXS_RELEASE_ACTIVATION_CONTEXT,
++ MD_NTSTATUS_WIN_STATUS_HEURISTIC_DAMAGE_POSSIBLE,
++ MD_NTSTATUS_WIN_STATUS_RECOVERY_NOT_NEEDED,
++ MD_NTSTATUS_WIN_STATUS_RM_ALREADY_STARTED,
++ MD_NTSTATUS_WIN_STATUS_LOG_NO_RESTART,
++ MD_NTSTATUS_WIN_STATUS_VIDEO_DRIVER_DEBUG_REPORT_REQUEST,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_PARTIAL_DATA_POPULATED,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_SKIP_ALLOCATION_PREPARATION,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_MODE_NOT_PINNED,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_NO_PREFERRED_MODE,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_DATASET_IS_EMPTY,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_NO_MORE_ELEMENTS_IN_DATASET,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_PATH_CONTENT_GEOMETRY_TRANSFORMATION_NOT_PINNED,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_UNKNOWN_CHILD_STATUS,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_LEADLINK_START_DEFERRED,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_POLLING_TOO_FREQUENTLY,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_START_DEFERRED,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_DEPENDABLE_CHILD_STATUS,
++ MD_NTSTATUS_WIN_STATUS_NDIS_INDICATION_REQUIRED,
++ MD_NTSTATUS_WIN_STATUS_PCP_UNSUPPORTED_PSS_SALT,
++ MD_NTSTATUS_WIN_STATUS_GUARD_PAGE_VIOLATION,
++ MD_NTSTATUS_WIN_STATUS_DATATYPE_MISALIGNMENT,
++ MD_NTSTATUS_WIN_STATUS_BREAKPOINT,
++ MD_NTSTATUS_WIN_STATUS_SINGLE_STEP,
++ MD_NTSTATUS_WIN_STATUS_BUFFER_OVERFLOW,
++ MD_NTSTATUS_WIN_STATUS_NO_MORE_FILES,
++ MD_NTSTATUS_WIN_STATUS_WAKE_SYSTEM_DEBUGGER,
++ MD_NTSTATUS_WIN_STATUS_HANDLES_CLOSED,
++ MD_NTSTATUS_WIN_STATUS_NO_INHERITANCE,
++ MD_NTSTATUS_WIN_STATUS_GUID_SUBSTITUTION_MADE,
++ MD_NTSTATUS_WIN_STATUS_PARTIAL_COPY,
++ MD_NTSTATUS_WIN_STATUS_DEVICE_PAPER_EMPTY,
++ MD_NTSTATUS_WIN_STATUS_DEVICE_POWERED_OFF,
++ MD_NTSTATUS_WIN_STATUS_DEVICE_OFF_LINE,
++ MD_NTSTATUS_WIN_STATUS_DEVICE_BUSY,
++ MD_NTSTATUS_WIN_STATUS_NO_MORE_EAS,
++ MD_NTSTATUS_WIN_STATUS_INVALID_EA_NAME,
++ MD_NTSTATUS_WIN_STATUS_EA_LIST_INCONSISTENT,
++ MD_NTSTATUS_WIN_STATUS_INVALID_EA_FLAG,
++ MD_NTSTATUS_WIN_STATUS_VERIFY_REQUIRED,
++ MD_NTSTATUS_WIN_STATUS_EXTRANEOUS_INFORMATION,
++ MD_NTSTATUS_WIN_STATUS_RXACT_COMMIT_NECESSARY,
++ MD_NTSTATUS_WIN_STATUS_NO_MORE_ENTRIES,
++ MD_NTSTATUS_WIN_STATUS_FILEMARK_DETECTED,
++ MD_NTSTATUS_WIN_STATUS_MEDIA_CHANGED,
++ MD_NTSTATUS_WIN_STATUS_BUS_RESET,
++ MD_NTSTATUS_WIN_STATUS_END_OF_MEDIA,
++ MD_NTSTATUS_WIN_STATUS_BEGINNING_OF_MEDIA,
++ MD_NTSTATUS_WIN_STATUS_MEDIA_CHECK,
++ MD_NTSTATUS_WIN_STATUS_SETMARK_DETECTED,
++ MD_NTSTATUS_WIN_STATUS_NO_DATA_DETECTED,
++ MD_NTSTATUS_WIN_STATUS_REDIRECTOR_HAS_OPEN_HANDLES,
++ MD_NTSTATUS_WIN_STATUS_SERVER_HAS_OPEN_HANDLES,
++ MD_NTSTATUS_WIN_STATUS_ALREADY_DISCONNECTED,
++ MD_NTSTATUS_WIN_STATUS_LONGJUMP,
++ MD_NTSTATUS_WIN_STATUS_CLEANER_CARTRIDGE_INSTALLED,
++ MD_NTSTATUS_WIN_STATUS_PLUGPLAY_QUERY_VETOED,
++ MD_NTSTATUS_WIN_STATUS_UNWIND_CONSOLIDATE,
++ MD_NTSTATUS_WIN_STATUS_REGISTRY_HIVE_RECOVERED,
++ MD_NTSTATUS_WIN_STATUS_DLL_MIGHT_BE_INSECURE,
++ MD_NTSTATUS_WIN_STATUS_DLL_MIGHT_BE_INCOMPATIBLE,
++ MD_NTSTATUS_WIN_STATUS_STOPPED_ON_SYMLINK,
++ MD_NTSTATUS_WIN_STATUS_CANNOT_GRANT_REQUESTED_OPLOCK,
++ MD_NTSTATUS_WIN_STATUS_NO_ACE_CONDITION,
++ MD_NTSTATUS_WIN_STATUS_DEVICE_SUPPORT_IN_PROGRESS,
++ MD_NTSTATUS_WIN_STATUS_DEVICE_POWER_CYCLE_REQUIRED,
++ MD_NTSTATUS_WIN_STATUS_NO_WORK_DONE,
++ MD_NTSTATUS_WIN_STATUS_RETURN_ADDRESS_HIJACK_ATTEMPT,
++ MD_NTSTATUS_WIN_STATUS_DEVICE_REQUIRES_CLEANING,
++ MD_NTSTATUS_WIN_STATUS_DEVICE_DOOR_OPEN,
++ MD_NTSTATUS_WIN_STATUS_DATA_LOST_REPAIR,
++ MD_NTSTATUS_WIN_STATUS_GPIO_INTERRUPT_ALREADY_UNMASKED,
++ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_PROPERTY_BLOB_CHECKSUM_MISMATCH,
++ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_PROPERTY_BLOB_TOO_LARGE,
++ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_TOO_MANY_PROPERTY_BLOBS,
++ MD_NTSTATUS_WIN_DBG_EXCEPTION_NOT_HANDLED,
++ MD_NTSTATUS_WIN_STATUS_CLUSTER_NODE_ALREADY_UP,
++ MD_NTSTATUS_WIN_STATUS_CLUSTER_NODE_ALREADY_DOWN,
++ MD_NTSTATUS_WIN_STATUS_CLUSTER_NETWORK_ALREADY_ONLINE,
++ MD_NTSTATUS_WIN_STATUS_CLUSTER_NETWORK_ALREADY_OFFLINE,
++ MD_NTSTATUS_WIN_STATUS_CLUSTER_NODE_ALREADY_MEMBER,
++ MD_NTSTATUS_WIN_STATUS_COULD_NOT_RESIZE_LOG,
++ MD_NTSTATUS_WIN_STATUS_NO_TXF_METADATA,
++ MD_NTSTATUS_WIN_STATUS_CANT_RECOVER_WITH_HANDLE_OPEN,
++ MD_NTSTATUS_WIN_STATUS_TXF_METADATA_ALREADY_PRESENT,
++ MD_NTSTATUS_WIN_STATUS_TRANSACTION_SCOPE_CALLBACKS_NOT_SET,
++ MD_NTSTATUS_WIN_STATUS_VIDEO_HUNG_DISPLAY_DRIVER_THREAD_RECOVERED,
++ MD_NTSTATUS_WIN_STATUS_FLT_BUFFER_TOO_SMALL,
++ MD_NTSTATUS_WIN_STATUS_FVE_PARTIAL_METADATA,
++ MD_NTSTATUS_WIN_STATUS_FVE_TRANSIENT_STATE,
++ MD_NTSTATUS_WIN_STATUS_VID_REMOTE_NODE_PARENT_GPA_PAGES_USED,
++ MD_NTSTATUS_WIN_STATUS_VOLMGR_INCOMPLETE_REGENERATION,
++ MD_NTSTATUS_WIN_STATUS_VOLMGR_INCOMPLETE_DISK_MIGRATION,
++ MD_NTSTATUS_WIN_STATUS_BCD_NOT_ALL_ENTRIES_IMPORTED,
++ MD_NTSTATUS_WIN_STATUS_BCD_NOT_ALL_ENTRIES_SYNCHRONIZED,
++ MD_NTSTATUS_WIN_STATUS_QUERY_STORAGE_ERROR,
++ MD_NTSTATUS_WIN_STATUS_GDI_HANDLE_LEAK,
++ MD_NTSTATUS_WIN_STATUS_SECUREBOOT_NOT_ENABLED,
++ MD_NTSTATUS_WIN_STATUS_UNSUCCESSFUL,
++ MD_NTSTATUS_WIN_STATUS_NOT_IMPLEMENTED,
++ MD_NTSTATUS_WIN_STATUS_INVALID_INFO_CLASS,
++ MD_NTSTATUS_WIN_STATUS_INFO_LENGTH_MISMATCH,
++ MD_NTSTATUS_WIN_STATUS_ACCESS_VIOLATION,
++ MD_NTSTATUS_WIN_STATUS_IN_PAGE_ERROR,
++ MD_NTSTATUS_WIN_STATUS_PAGEFILE_QUOTA,
++ MD_NTSTATUS_WIN_STATUS_INVALID_HANDLE,
++ MD_NTSTATUS_WIN_STATUS_BAD_INITIAL_STACK,
++ MD_NTSTATUS_WIN_STATUS_BAD_INITIAL_PC,
++ MD_NTSTATUS_WIN_STATUS_INVALID_CID,
++ MD_NTSTATUS_WIN_STATUS_TIMER_NOT_CANCELED,
++ MD_NTSTATUS_WIN_STATUS_INVALID_PARAMETER,
++ MD_NTSTATUS_WIN_STATUS_NO_SUCH_DEVICE,
++ MD_NTSTATUS_WIN_STATUS_NO_SUCH_FILE,
++ MD_NTSTATUS_WIN_STATUS_INVALID_DEVICE_REQUEST,
++ MD_NTSTATUS_WIN_STATUS_END_OF_FILE,
++ MD_NTSTATUS_WIN_STATUS_WRONG_VOLUME,
++ MD_NTSTATUS_WIN_STATUS_NO_MEDIA_IN_DEVICE,
++ MD_NTSTATUS_WIN_STATUS_UNRECOGNIZED_MEDIA,
++ MD_NTSTATUS_WIN_STATUS_NONEXISTENT_SECTOR,
++ MD_NTSTATUS_WIN_STATUS_MORE_PROCESSING_REQUIRED,
++ MD_NTSTATUS_WIN_STATUS_NO_MEMORY,
++ MD_NTSTATUS_WIN_STATUS_CONFLICTING_ADDRESSES,
++ MD_NTSTATUS_WIN_STATUS_NOT_MAPPED_VIEW,
++ MD_NTSTATUS_WIN_STATUS_UNABLE_TO_FREE_VM,
++ MD_NTSTATUS_WIN_STATUS_UNABLE_TO_DELETE_SECTION,
++ MD_NTSTATUS_WIN_STATUS_INVALID_SYSTEM_SERVICE,
++ MD_NTSTATUS_WIN_STATUS_ILLEGAL_INSTRUCTION,
++ MD_NTSTATUS_WIN_STATUS_INVALID_LOCK_SEQUENCE,
++ MD_NTSTATUS_WIN_STATUS_INVALID_VIEW_SIZE,
++ MD_NTSTATUS_WIN_STATUS_INVALID_FILE_FOR_SECTION,
++ MD_NTSTATUS_WIN_STATUS_ALREADY_COMMITTED,
++ MD_NTSTATUS_WIN_STATUS_ACCESS_DENIED,
++ MD_NTSTATUS_WIN_STATUS_BUFFER_TOO_SMALL,
++ MD_NTSTATUS_WIN_STATUS_OBJECT_TYPE_MISMATCH,
++ MD_NTSTATUS_WIN_STATUS_NONCONTINUABLE_EXCEPTION,
++ MD_NTSTATUS_WIN_STATUS_INVALID_DISPOSITION,
++ MD_NTSTATUS_WIN_STATUS_UNWIND,
++ MD_NTSTATUS_WIN_STATUS_BAD_STACK,
++ MD_NTSTATUS_WIN_STATUS_INVALID_UNWIND_TARGET,
++ MD_NTSTATUS_WIN_STATUS_NOT_LOCKED,
++ MD_NTSTATUS_WIN_STATUS_PARITY_ERROR,
++ MD_NTSTATUS_WIN_STATUS_UNABLE_TO_DECOMMIT_VM,
++ MD_NTSTATUS_WIN_STATUS_NOT_COMMITTED,
++ MD_NTSTATUS_WIN_STATUS_INVALID_PORT_ATTRIBUTES,
++ MD_NTSTATUS_WIN_STATUS_PORT_MESSAGE_TOO_LONG,
++ MD_NTSTATUS_WIN_STATUS_INVALID_PARAMETER_MIX,
++ MD_NTSTATUS_WIN_STATUS_INVALID_QUOTA_LOWER,
++ MD_NTSTATUS_WIN_STATUS_DISK_CORRUPT_ERROR,
++ MD_NTSTATUS_WIN_STATUS_OBJECT_NAME_INVALID,
++ MD_NTSTATUS_WIN_STATUS_OBJECT_NAME_NOT_FOUND,
++ MD_NTSTATUS_WIN_STATUS_OBJECT_NAME_COLLISION,
++ MD_NTSTATUS_WIN_STATUS_PORT_DO_NOT_DISTURB,
++ MD_NTSTATUS_WIN_STATUS_PORT_DISCONNECTED,
++ MD_NTSTATUS_WIN_STATUS_DEVICE_ALREADY_ATTACHED,
++ MD_NTSTATUS_WIN_STATUS_OBJECT_PATH_INVALID,
++ MD_NTSTATUS_WIN_STATUS_OBJECT_PATH_NOT_FOUND,
++ MD_NTSTATUS_WIN_STATUS_OBJECT_PATH_SYNTAX_BAD,
++ MD_NTSTATUS_WIN_STATUS_DATA_OVERRUN,
++ MD_NTSTATUS_WIN_STATUS_DATA_LATE_ERROR,
++ MD_NTSTATUS_WIN_STATUS_DATA_ERROR,
++ MD_NTSTATUS_WIN_STATUS_CRC_ERROR,
++ MD_NTSTATUS_WIN_STATUS_SECTION_TOO_BIG,
++ MD_NTSTATUS_WIN_STATUS_PORT_CONNECTION_REFUSED,
++ MD_NTSTATUS_WIN_STATUS_INVALID_PORT_HANDLE,
++ MD_NTSTATUS_WIN_STATUS_SHARING_VIOLATION,
++ MD_NTSTATUS_WIN_STATUS_QUOTA_EXCEEDED,
++ MD_NTSTATUS_WIN_STATUS_INVALID_PAGE_PROTECTION,
++ MD_NTSTATUS_WIN_STATUS_MUTANT_NOT_OWNED,
++ MD_NTSTATUS_WIN_STATUS_SEMAPHORE_LIMIT_EXCEEDED,
++ MD_NTSTATUS_WIN_STATUS_PORT_ALREADY_SET,
++ MD_NTSTATUS_WIN_STATUS_SECTION_NOT_IMAGE,
++ MD_NTSTATUS_WIN_STATUS_SUSPEND_COUNT_EXCEEDED,
++ MD_NTSTATUS_WIN_STATUS_THREAD_IS_TERMINATING,
++ MD_NTSTATUS_WIN_STATUS_BAD_WORKING_SET_LIMIT,
++ MD_NTSTATUS_WIN_STATUS_INCOMPATIBLE_FILE_MAP,
++ MD_NTSTATUS_WIN_STATUS_SECTION_PROTECTION,
++ MD_NTSTATUS_WIN_STATUS_EAS_NOT_SUPPORTED,
++ MD_NTSTATUS_WIN_STATUS_EA_TOO_LARGE,
++ MD_NTSTATUS_WIN_STATUS_NONEXISTENT_EA_ENTRY,
++ MD_NTSTATUS_WIN_STATUS_NO_EAS_ON_FILE,
++ MD_NTSTATUS_WIN_STATUS_EA_CORRUPT_ERROR,
++ MD_NTSTATUS_WIN_STATUS_FILE_LOCK_CONFLICT,
++ MD_NTSTATUS_WIN_STATUS_LOCK_NOT_GRANTED,
++ MD_NTSTATUS_WIN_STATUS_DELETE_PENDING,
++ MD_NTSTATUS_WIN_STATUS_CTL_FILE_NOT_SUPPORTED,
++ MD_NTSTATUS_WIN_STATUS_UNKNOWN_REVISION,
++ MD_NTSTATUS_WIN_STATUS_REVISION_MISMATCH,
++ MD_NTSTATUS_WIN_STATUS_INVALID_OWNER,
++ MD_NTSTATUS_WIN_STATUS_INVALID_PRIMARY_GROUP,
++ MD_NTSTATUS_WIN_STATUS_NO_IMPERSONATION_TOKEN,
++ MD_NTSTATUS_WIN_STATUS_CANT_DISABLE_MANDATORY,
++ MD_NTSTATUS_WIN_STATUS_NO_LOGON_SERVERS,
++ MD_NTSTATUS_WIN_STATUS_NO_SUCH_LOGON_SESSION,
++ MD_NTSTATUS_WIN_STATUS_NO_SUCH_PRIVILEGE,
++ MD_NTSTATUS_WIN_STATUS_PRIVILEGE_NOT_HELD,
++ MD_NTSTATUS_WIN_STATUS_INVALID_ACCOUNT_NAME,
++ MD_NTSTATUS_WIN_STATUS_USER_EXISTS,
++ MD_NTSTATUS_WIN_STATUS_NO_SUCH_USER,
++ MD_NTSTATUS_WIN_STATUS_GROUP_EXISTS,
++ MD_NTSTATUS_WIN_STATUS_NO_SUCH_GROUP,
++ MD_NTSTATUS_WIN_STATUS_MEMBER_IN_GROUP,
++ MD_NTSTATUS_WIN_STATUS_MEMBER_NOT_IN_GROUP,
++ MD_NTSTATUS_WIN_STATUS_LAST_ADMIN,
++ MD_NTSTATUS_WIN_STATUS_WRONG_PASSWORD,
++ MD_NTSTATUS_WIN_STATUS_ILL_FORMED_PASSWORD,
++ MD_NTSTATUS_WIN_STATUS_PASSWORD_RESTRICTION,
++ MD_NTSTATUS_WIN_STATUS_LOGON_FAILURE,
++ MD_NTSTATUS_WIN_STATUS_ACCOUNT_RESTRICTION,
++ MD_NTSTATUS_WIN_STATUS_INVALID_LOGON_HOURS,
++ MD_NTSTATUS_WIN_STATUS_INVALID_WORKSTATION,
++ MD_NTSTATUS_WIN_STATUS_PASSWORD_EXPIRED,
++ MD_NTSTATUS_WIN_STATUS_ACCOUNT_DISABLED,
++ MD_NTSTATUS_WIN_STATUS_NONE_MAPPED,
++ MD_NTSTATUS_WIN_STATUS_TOO_MANY_LUIDS_REQUESTED,
++ MD_NTSTATUS_WIN_STATUS_LUIDS_EXHAUSTED,
++ MD_NTSTATUS_WIN_STATUS_INVALID_SUB_AUTHORITY,
++ MD_NTSTATUS_WIN_STATUS_INVALID_ACL,
++ MD_NTSTATUS_WIN_STATUS_INVALID_SID,
++ MD_NTSTATUS_WIN_STATUS_INVALID_SECURITY_DESCR,
++ MD_NTSTATUS_WIN_STATUS_PROCEDURE_NOT_FOUND,
++ MD_NTSTATUS_WIN_STATUS_INVALID_IMAGE_FORMAT,
++ MD_NTSTATUS_WIN_STATUS_NO_TOKEN,
++ MD_NTSTATUS_WIN_STATUS_BAD_INHERITANCE_ACL,
++ MD_NTSTATUS_WIN_STATUS_RANGE_NOT_LOCKED,
++ MD_NTSTATUS_WIN_STATUS_DISK_FULL,
++ MD_NTSTATUS_WIN_STATUS_SERVER_DISABLED,
++ MD_NTSTATUS_WIN_STATUS_SERVER_NOT_DISABLED,
++ MD_NTSTATUS_WIN_STATUS_TOO_MANY_GUIDS_REQUESTED,
++ MD_NTSTATUS_WIN_STATUS_GUIDS_EXHAUSTED,
++ MD_NTSTATUS_WIN_STATUS_INVALID_ID_AUTHORITY,
++ MD_NTSTATUS_WIN_STATUS_AGENTS_EXHAUSTED,
++ MD_NTSTATUS_WIN_STATUS_INVALID_VOLUME_LABEL,
++ MD_NTSTATUS_WIN_STATUS_SECTION_NOT_EXTENDED,
++ MD_NTSTATUS_WIN_STATUS_NOT_MAPPED_DATA,
++ MD_NTSTATUS_WIN_STATUS_RESOURCE_DATA_NOT_FOUND,
++ MD_NTSTATUS_WIN_STATUS_RESOURCE_TYPE_NOT_FOUND,
++ MD_NTSTATUS_WIN_STATUS_RESOURCE_NAME_NOT_FOUND,
++ MD_NTSTATUS_WIN_STATUS_ARRAY_BOUNDS_EXCEEDED,
++ MD_NTSTATUS_WIN_STATUS_FLOAT_DENORMAL_OPERAND,
++ MD_NTSTATUS_WIN_STATUS_FLOAT_DIVIDE_BY_ZERO,
++ MD_NTSTATUS_WIN_STATUS_FLOAT_INEXACT_RESULT,
++ MD_NTSTATUS_WIN_STATUS_FLOAT_INVALID_OPERATION,
++ MD_NTSTATUS_WIN_STATUS_FLOAT_OVERFLOW,
++ MD_NTSTATUS_WIN_STATUS_FLOAT_STACK_CHECK,
++ MD_NTSTATUS_WIN_STATUS_FLOAT_UNDERFLOW,
++ MD_NTSTATUS_WIN_STATUS_INTEGER_DIVIDE_BY_ZERO,
++ MD_NTSTATUS_WIN_STATUS_INTEGER_OVERFLOW,
++ MD_NTSTATUS_WIN_STATUS_PRIVILEGED_INSTRUCTION,
++ MD_NTSTATUS_WIN_STATUS_TOO_MANY_PAGING_FILES,
++ MD_NTSTATUS_WIN_STATUS_FILE_INVALID,
++ MD_NTSTATUS_WIN_STATUS_ALLOTTED_SPACE_EXCEEDED,
++ MD_NTSTATUS_WIN_STATUS_INSUFFICIENT_RESOURCES,
++ MD_NTSTATUS_WIN_STATUS_DFS_EXIT_PATH_FOUND,
++ MD_NTSTATUS_WIN_STATUS_DEVICE_DATA_ERROR,
++ MD_NTSTATUS_WIN_STATUS_DEVICE_NOT_CONNECTED,
++ MD_NTSTATUS_WIN_STATUS_DEVICE_POWER_FAILURE,
++ MD_NTSTATUS_WIN_STATUS_FREE_VM_NOT_AT_BASE,
++ MD_NTSTATUS_WIN_STATUS_MEMORY_NOT_ALLOCATED,
++ MD_NTSTATUS_WIN_STATUS_WORKING_SET_QUOTA,
++ MD_NTSTATUS_WIN_STATUS_MEDIA_WRITE_PROTECTED,
++ MD_NTSTATUS_WIN_STATUS_DEVICE_NOT_READY,
++ MD_NTSTATUS_WIN_STATUS_INVALID_GROUP_ATTRIBUTES,
++ MD_NTSTATUS_WIN_STATUS_BAD_IMPERSONATION_LEVEL,
++ MD_NTSTATUS_WIN_STATUS_CANT_OPEN_ANONYMOUS,
++ MD_NTSTATUS_WIN_STATUS_BAD_VALIDATION_CLASS,
++ MD_NTSTATUS_WIN_STATUS_BAD_TOKEN_TYPE,
++ MD_NTSTATUS_WIN_STATUS_BAD_MASTER_BOOT_RECORD,
++ MD_NTSTATUS_WIN_STATUS_INSTRUCTION_MISALIGNMENT,
++ MD_NTSTATUS_WIN_STATUS_INSTANCE_NOT_AVAILABLE,
++ MD_NTSTATUS_WIN_STATUS_PIPE_NOT_AVAILABLE,
++ MD_NTSTATUS_WIN_STATUS_INVALID_PIPE_STATE,
++ MD_NTSTATUS_WIN_STATUS_PIPE_BUSY,
++ MD_NTSTATUS_WIN_STATUS_ILLEGAL_FUNCTION,
++ MD_NTSTATUS_WIN_STATUS_PIPE_DISCONNECTED,
++ MD_NTSTATUS_WIN_STATUS_PIPE_CLOSING,
++ MD_NTSTATUS_WIN_STATUS_PIPE_CONNECTED,
++ MD_NTSTATUS_WIN_STATUS_PIPE_LISTENING,
++ MD_NTSTATUS_WIN_STATUS_INVALID_READ_MODE,
++ MD_NTSTATUS_WIN_STATUS_IO_TIMEOUT,
++ MD_NTSTATUS_WIN_STATUS_FILE_FORCED_CLOSED,
++ MD_NTSTATUS_WIN_STATUS_PROFILING_NOT_STARTED,
++ MD_NTSTATUS_WIN_STATUS_PROFILING_NOT_STOPPED,
++ MD_NTSTATUS_WIN_STATUS_COULD_NOT_INTERPRET,
++ MD_NTSTATUS_WIN_STATUS_FILE_IS_A_DIRECTORY,
++ MD_NTSTATUS_WIN_STATUS_NOT_SUPPORTED,
++ MD_NTSTATUS_WIN_STATUS_REMOTE_NOT_LISTENING,
++ MD_NTSTATUS_WIN_STATUS_DUPLICATE_NAME,
++ MD_NTSTATUS_WIN_STATUS_BAD_NETWORK_PATH,
++ MD_NTSTATUS_WIN_STATUS_NETWORK_BUSY,
++ MD_NTSTATUS_WIN_STATUS_DEVICE_DOES_NOT_EXIST,
++ MD_NTSTATUS_WIN_STATUS_TOO_MANY_COMMANDS,
++ MD_NTSTATUS_WIN_STATUS_ADAPTER_HARDWARE_ERROR,
++ MD_NTSTATUS_WIN_STATUS_INVALID_NETWORK_RESPONSE,
++ MD_NTSTATUS_WIN_STATUS_UNEXPECTED_NETWORK_ERROR,
++ MD_NTSTATUS_WIN_STATUS_BAD_REMOTE_ADAPTER,
++ MD_NTSTATUS_WIN_STATUS_PRINT_QUEUE_FULL,
++ MD_NTSTATUS_WIN_STATUS_NO_SPOOL_SPACE,
++ MD_NTSTATUS_WIN_STATUS_PRINT_CANCELLED,
++ MD_NTSTATUS_WIN_STATUS_NETWORK_NAME_DELETED,
++ MD_NTSTATUS_WIN_STATUS_NETWORK_ACCESS_DENIED,
++ MD_NTSTATUS_WIN_STATUS_BAD_DEVICE_TYPE,
++ MD_NTSTATUS_WIN_STATUS_BAD_NETWORK_NAME,
++ MD_NTSTATUS_WIN_STATUS_TOO_MANY_NAMES,
++ MD_NTSTATUS_WIN_STATUS_TOO_MANY_SESSIONS,
++ MD_NTSTATUS_WIN_STATUS_SHARING_PAUSED,
++ MD_NTSTATUS_WIN_STATUS_REQUEST_NOT_ACCEPTED,
++ MD_NTSTATUS_WIN_STATUS_REDIRECTOR_PAUSED,
++ MD_NTSTATUS_WIN_STATUS_NET_WRITE_FAULT,
++ MD_NTSTATUS_WIN_STATUS_PROFILING_AT_LIMIT,
++ MD_NTSTATUS_WIN_STATUS_NOT_SAME_DEVICE,
++ MD_NTSTATUS_WIN_STATUS_FILE_RENAMED,
++ MD_NTSTATUS_WIN_STATUS_VIRTUAL_CIRCUIT_CLOSED,
++ MD_NTSTATUS_WIN_STATUS_NO_SECURITY_ON_OBJECT,
++ MD_NTSTATUS_WIN_STATUS_CANT_WAIT,
++ MD_NTSTATUS_WIN_STATUS_PIPE_EMPTY,
++ MD_NTSTATUS_WIN_STATUS_CANT_ACCESS_DOMAIN_INFO,
++ MD_NTSTATUS_WIN_STATUS_CANT_TERMINATE_SELF,
++ MD_NTSTATUS_WIN_STATUS_INVALID_SERVER_STATE,
++ MD_NTSTATUS_WIN_STATUS_INVALID_DOMAIN_STATE,
++ MD_NTSTATUS_WIN_STATUS_INVALID_DOMAIN_ROLE,
++ MD_NTSTATUS_WIN_STATUS_NO_SUCH_DOMAIN,
++ MD_NTSTATUS_WIN_STATUS_DOMAIN_EXISTS,
++ MD_NTSTATUS_WIN_STATUS_DOMAIN_LIMIT_EXCEEDED,
++ MD_NTSTATUS_WIN_STATUS_OPLOCK_NOT_GRANTED,
++ MD_NTSTATUS_WIN_STATUS_INVALID_OPLOCK_PROTOCOL,
++ MD_NTSTATUS_WIN_STATUS_INTERNAL_DB_CORRUPTION,
++ MD_NTSTATUS_WIN_STATUS_INTERNAL_ERROR,
++ MD_NTSTATUS_WIN_STATUS_GENERIC_NOT_MAPPED,
++ MD_NTSTATUS_WIN_STATUS_BAD_DESCRIPTOR_FORMAT,
++ MD_NTSTATUS_WIN_STATUS_INVALID_USER_BUFFER,
++ MD_NTSTATUS_WIN_STATUS_UNEXPECTED_IO_ERROR,
++ MD_NTSTATUS_WIN_STATUS_UNEXPECTED_MM_CREATE_ERR,
++ MD_NTSTATUS_WIN_STATUS_UNEXPECTED_MM_MAP_ERROR,
++ MD_NTSTATUS_WIN_STATUS_UNEXPECTED_MM_EXTEND_ERR,
++ MD_NTSTATUS_WIN_STATUS_NOT_LOGON_PROCESS,
++ MD_NTSTATUS_WIN_STATUS_LOGON_SESSION_EXISTS,
++ MD_NTSTATUS_WIN_STATUS_INVALID_PARAMETER_1,
++ MD_NTSTATUS_WIN_STATUS_INVALID_PARAMETER_2,
++ MD_NTSTATUS_WIN_STATUS_INVALID_PARAMETER_3,
++ MD_NTSTATUS_WIN_STATUS_INVALID_PARAMETER_4,
++ MD_NTSTATUS_WIN_STATUS_INVALID_PARAMETER_5,
++ MD_NTSTATUS_WIN_STATUS_INVALID_PARAMETER_6,
++ MD_NTSTATUS_WIN_STATUS_INVALID_PARAMETER_7,
++ MD_NTSTATUS_WIN_STATUS_INVALID_PARAMETER_8,
++ MD_NTSTATUS_WIN_STATUS_INVALID_PARAMETER_9,
++ MD_NTSTATUS_WIN_STATUS_INVALID_PARAMETER_10,
++ MD_NTSTATUS_WIN_STATUS_INVALID_PARAMETER_11,
++ MD_NTSTATUS_WIN_STATUS_INVALID_PARAMETER_12,
++ MD_NTSTATUS_WIN_STATUS_REDIRECTOR_NOT_STARTED,
++ MD_NTSTATUS_WIN_STATUS_REDIRECTOR_STARTED,
++ MD_NTSTATUS_WIN_STATUS_STACK_OVERFLOW,
++ MD_NTSTATUS_WIN_STATUS_NO_SUCH_PACKAGE,
++ MD_NTSTATUS_WIN_STATUS_BAD_FUNCTION_TABLE,
++ MD_NTSTATUS_WIN_STATUS_VARIABLE_NOT_FOUND,
++ MD_NTSTATUS_WIN_STATUS_DIRECTORY_NOT_EMPTY,
++ MD_NTSTATUS_WIN_STATUS_FILE_CORRUPT_ERROR,
++ MD_NTSTATUS_WIN_STATUS_NOT_A_DIRECTORY,
++ MD_NTSTATUS_WIN_STATUS_BAD_LOGON_SESSION_STATE,
++ MD_NTSTATUS_WIN_STATUS_LOGON_SESSION_COLLISION,
++ MD_NTSTATUS_WIN_STATUS_NAME_TOO_LONG,
++ MD_NTSTATUS_WIN_STATUS_FILES_OPEN,
++ MD_NTSTATUS_WIN_STATUS_CONNECTION_IN_USE,
++ MD_NTSTATUS_WIN_STATUS_MESSAGE_NOT_FOUND,
++ MD_NTSTATUS_WIN_STATUS_PROCESS_IS_TERMINATING,
++ MD_NTSTATUS_WIN_STATUS_INVALID_LOGON_TYPE,
++ MD_NTSTATUS_WIN_STATUS_NO_GUID_TRANSLATION,
++ MD_NTSTATUS_WIN_STATUS_CANNOT_IMPERSONATE,
++ MD_NTSTATUS_WIN_STATUS_IMAGE_ALREADY_LOADED,
++ MD_NTSTATUS_WIN_STATUS_ABIOS_NOT_PRESENT,
++ MD_NTSTATUS_WIN_STATUS_ABIOS_LID_NOT_EXIST,
++ MD_NTSTATUS_WIN_STATUS_ABIOS_LID_ALREADY_OWNED,
++ MD_NTSTATUS_WIN_STATUS_ABIOS_NOT_LID_OWNER,
++ MD_NTSTATUS_WIN_STATUS_ABIOS_INVALID_COMMAND,
++ MD_NTSTATUS_WIN_STATUS_ABIOS_INVALID_LID,
++ MD_NTSTATUS_WIN_STATUS_ABIOS_SELECTOR_NOT_AVAILABLE,
++ MD_NTSTATUS_WIN_STATUS_ABIOS_INVALID_SELECTOR,
++ MD_NTSTATUS_WIN_STATUS_NO_LDT,
++ MD_NTSTATUS_WIN_STATUS_INVALID_LDT_SIZE,
++ MD_NTSTATUS_WIN_STATUS_INVALID_LDT_OFFSET,
++ MD_NTSTATUS_WIN_STATUS_INVALID_LDT_DESCRIPTOR,
++ MD_NTSTATUS_WIN_STATUS_INVALID_IMAGE_NE_FORMAT,
++ MD_NTSTATUS_WIN_STATUS_RXACT_INVALID_STATE,
++ MD_NTSTATUS_WIN_STATUS_RXACT_COMMIT_FAILURE,
++ MD_NTSTATUS_WIN_STATUS_MAPPED_FILE_SIZE_ZERO,
++ MD_NTSTATUS_WIN_STATUS_TOO_MANY_OPENED_FILES,
++ MD_NTSTATUS_WIN_STATUS_CANCELLED,
++ MD_NTSTATUS_WIN_STATUS_CANNOT_DELETE,
++ MD_NTSTATUS_WIN_STATUS_INVALID_COMPUTER_NAME,
++ MD_NTSTATUS_WIN_STATUS_FILE_DELETED,
++ MD_NTSTATUS_WIN_STATUS_SPECIAL_ACCOUNT,
++ MD_NTSTATUS_WIN_STATUS_SPECIAL_GROUP,
++ MD_NTSTATUS_WIN_STATUS_SPECIAL_USER,
++ MD_NTSTATUS_WIN_STATUS_MEMBERS_PRIMARY_GROUP,
++ MD_NTSTATUS_WIN_STATUS_FILE_CLOSED,
++ MD_NTSTATUS_WIN_STATUS_TOO_MANY_THREADS,
++ MD_NTSTATUS_WIN_STATUS_THREAD_NOT_IN_PROCESS,
++ MD_NTSTATUS_WIN_STATUS_TOKEN_ALREADY_IN_USE,
++ MD_NTSTATUS_WIN_STATUS_PAGEFILE_QUOTA_EXCEEDED,
++ MD_NTSTATUS_WIN_STATUS_COMMITMENT_LIMIT,
++ MD_NTSTATUS_WIN_STATUS_INVALID_IMAGE_LE_FORMAT,
++ MD_NTSTATUS_WIN_STATUS_INVALID_IMAGE_NOT_MZ,
++ MD_NTSTATUS_WIN_STATUS_INVALID_IMAGE_PROTECT,
++ MD_NTSTATUS_WIN_STATUS_INVALID_IMAGE_WIN_16,
++ MD_NTSTATUS_WIN_STATUS_LOGON_SERVER_CONFLICT,
++ MD_NTSTATUS_WIN_STATUS_TIME_DIFFERENCE_AT_DC,
++ MD_NTSTATUS_WIN_STATUS_SYNCHRONIZATION_REQUIRED,
++ MD_NTSTATUS_WIN_STATUS_DLL_NOT_FOUND,
++ MD_NTSTATUS_WIN_STATUS_OPEN_FAILED,
++ MD_NTSTATUS_WIN_STATUS_IO_PRIVILEGE_FAILED,
++ MD_NTSTATUS_WIN_STATUS_ORDINAL_NOT_FOUND,
++ MD_NTSTATUS_WIN_STATUS_ENTRYPOINT_NOT_FOUND,
++ MD_NTSTATUS_WIN_STATUS_CONTROL_C_EXIT,
++ MD_NTSTATUS_WIN_STATUS_LOCAL_DISCONNECT,
++ MD_NTSTATUS_WIN_STATUS_REMOTE_DISCONNECT,
++ MD_NTSTATUS_WIN_STATUS_REMOTE_RESOURCES,
++ MD_NTSTATUS_WIN_STATUS_LINK_FAILED,
++ MD_NTSTATUS_WIN_STATUS_LINK_TIMEOUT,
++ MD_NTSTATUS_WIN_STATUS_INVALID_CONNECTION,
++ MD_NTSTATUS_WIN_STATUS_INVALID_ADDRESS,
++ MD_NTSTATUS_WIN_STATUS_DLL_INIT_FAILED,
++ MD_NTSTATUS_WIN_STATUS_MISSING_SYSTEMFILE,
++ MD_NTSTATUS_WIN_STATUS_UNHANDLED_EXCEPTION,
++ MD_NTSTATUS_WIN_STATUS_APP_INIT_FAILURE,
++ MD_NTSTATUS_WIN_STATUS_PAGEFILE_CREATE_FAILED,
++ MD_NTSTATUS_WIN_STATUS_NO_PAGEFILE,
++ MD_NTSTATUS_WIN_STATUS_INVALID_LEVEL,
++ MD_NTSTATUS_WIN_STATUS_WRONG_PASSWORD_CORE,
++ MD_NTSTATUS_WIN_STATUS_ILLEGAL_FLOAT_CONTEXT,
++ MD_NTSTATUS_WIN_STATUS_PIPE_BROKEN,
++ MD_NTSTATUS_WIN_STATUS_REGISTRY_CORRUPT,
++ MD_NTSTATUS_WIN_STATUS_REGISTRY_IO_FAILED,
++ MD_NTSTATUS_WIN_STATUS_NO_EVENT_PAIR,
++ MD_NTSTATUS_WIN_STATUS_UNRECOGNIZED_VOLUME,
++ MD_NTSTATUS_WIN_STATUS_SERIAL_NO_DEVICE_INITED,
++ MD_NTSTATUS_WIN_STATUS_NO_SUCH_ALIAS,
++ MD_NTSTATUS_WIN_STATUS_MEMBER_NOT_IN_ALIAS,
++ MD_NTSTATUS_WIN_STATUS_MEMBER_IN_ALIAS,
++ MD_NTSTATUS_WIN_STATUS_ALIAS_EXISTS,
++ MD_NTSTATUS_WIN_STATUS_LOGON_NOT_GRANTED,
++ MD_NTSTATUS_WIN_STATUS_TOO_MANY_SECRETS,
++ MD_NTSTATUS_WIN_STATUS_SECRET_TOO_LONG,
++ MD_NTSTATUS_WIN_STATUS_INTERNAL_DB_ERROR,
++ MD_NTSTATUS_WIN_STATUS_FULLSCREEN_MODE,
++ MD_NTSTATUS_WIN_STATUS_TOO_MANY_CONTEXT_IDS,
++ MD_NTSTATUS_WIN_STATUS_LOGON_TYPE_NOT_GRANTED,
++ MD_NTSTATUS_WIN_STATUS_NOT_REGISTRY_FILE,
++ MD_NTSTATUS_WIN_STATUS_NT_CROSS_ENCRYPTION_REQUIRED,
++ MD_NTSTATUS_WIN_STATUS_DOMAIN_CTRLR_CONFIG_ERROR,
++ MD_NTSTATUS_WIN_STATUS_FT_MISSING_MEMBER,
++ MD_NTSTATUS_WIN_STATUS_ILL_FORMED_SERVICE_ENTRY,
++ MD_NTSTATUS_WIN_STATUS_ILLEGAL_CHARACTER,
++ MD_NTSTATUS_WIN_STATUS_UNMAPPABLE_CHARACTER,
++ MD_NTSTATUS_WIN_STATUS_UNDEFINED_CHARACTER,
++ MD_NTSTATUS_WIN_STATUS_FLOPPY_VOLUME,
++ MD_NTSTATUS_WIN_STATUS_FLOPPY_ID_MARK_NOT_FOUND,
++ MD_NTSTATUS_WIN_STATUS_FLOPPY_WRONG_CYLINDER,
++ MD_NTSTATUS_WIN_STATUS_FLOPPY_UNKNOWN_ERROR,
++ MD_NTSTATUS_WIN_STATUS_FLOPPY_BAD_REGISTERS,
++ MD_NTSTATUS_WIN_STATUS_DISK_RECALIBRATE_FAILED,
++ MD_NTSTATUS_WIN_STATUS_DISK_OPERATION_FAILED,
++ MD_NTSTATUS_WIN_STATUS_DISK_RESET_FAILED,
++ MD_NTSTATUS_WIN_STATUS_SHARED_IRQ_BUSY,
++ MD_NTSTATUS_WIN_STATUS_FT_ORPHANING,
++ MD_NTSTATUS_WIN_STATUS_BIOS_FAILED_TO_CONNECT_INTERRUPT,
++ MD_NTSTATUS_WIN_STATUS_PARTITION_FAILURE,
++ MD_NTSTATUS_WIN_STATUS_INVALID_BLOCK_LENGTH,
++ MD_NTSTATUS_WIN_STATUS_DEVICE_NOT_PARTITIONED,
++ MD_NTSTATUS_WIN_STATUS_UNABLE_TO_LOCK_MEDIA,
++ MD_NTSTATUS_WIN_STATUS_UNABLE_TO_UNLOAD_MEDIA,
++ MD_NTSTATUS_WIN_STATUS_EOM_OVERFLOW,
++ MD_NTSTATUS_WIN_STATUS_NO_MEDIA,
++ MD_NTSTATUS_WIN_STATUS_NO_SUCH_MEMBER,
++ MD_NTSTATUS_WIN_STATUS_INVALID_MEMBER,
++ MD_NTSTATUS_WIN_STATUS_KEY_DELETED,
++ MD_NTSTATUS_WIN_STATUS_NO_LOG_SPACE,
++ MD_NTSTATUS_WIN_STATUS_TOO_MANY_SIDS,
++ MD_NTSTATUS_WIN_STATUS_LM_CROSS_ENCRYPTION_REQUIRED,
++ MD_NTSTATUS_WIN_STATUS_KEY_HAS_CHILDREN,
++ MD_NTSTATUS_WIN_STATUS_CHILD_MUST_BE_VOLATILE,
++ MD_NTSTATUS_WIN_STATUS_DEVICE_CONFIGURATION_ERROR,
++ MD_NTSTATUS_WIN_STATUS_DRIVER_INTERNAL_ERROR,
++ MD_NTSTATUS_WIN_STATUS_INVALID_DEVICE_STATE,
++ MD_NTSTATUS_WIN_STATUS_IO_DEVICE_ERROR,
++ MD_NTSTATUS_WIN_STATUS_DEVICE_PROTOCOL_ERROR,
++ MD_NTSTATUS_WIN_STATUS_BACKUP_CONTROLLER,
++ MD_NTSTATUS_WIN_STATUS_LOG_FILE_FULL,
++ MD_NTSTATUS_WIN_STATUS_TOO_LATE,
++ MD_NTSTATUS_WIN_STATUS_NO_TRUST_LSA_SECRET,
++ MD_NTSTATUS_WIN_STATUS_NO_TRUST_SAM_ACCOUNT,
++ MD_NTSTATUS_WIN_STATUS_TRUSTED_DOMAIN_FAILURE,
++ MD_NTSTATUS_WIN_STATUS_TRUSTED_RELATIONSHIP_FAILURE,
++ MD_NTSTATUS_WIN_STATUS_EVENTLOG_FILE_CORRUPT,
++ MD_NTSTATUS_WIN_STATUS_EVENTLOG_CANT_START,
++ MD_NTSTATUS_WIN_STATUS_TRUST_FAILURE,
++ MD_NTSTATUS_WIN_STATUS_MUTANT_LIMIT_EXCEEDED,
++ MD_NTSTATUS_WIN_STATUS_NETLOGON_NOT_STARTED,
++ MD_NTSTATUS_WIN_STATUS_ACCOUNT_EXPIRED,
++ MD_NTSTATUS_WIN_STATUS_POSSIBLE_DEADLOCK,
++ MD_NTSTATUS_WIN_STATUS_NETWORK_CREDENTIAL_CONFLICT,
++ MD_NTSTATUS_WIN_STATUS_REMOTE_SESSION_LIMIT,
++ MD_NTSTATUS_WIN_STATUS_EVENTLOG_FILE_CHANGED,
++ MD_NTSTATUS_WIN_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT,
++ MD_NTSTATUS_WIN_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT,
++ MD_NTSTATUS_WIN_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT,
++ MD_NTSTATUS_WIN_STATUS_DOMAIN_TRUST_INCONSISTENT,
++ MD_NTSTATUS_WIN_STATUS_FS_DRIVER_REQUIRED,
++ MD_NTSTATUS_WIN_STATUS_IMAGE_ALREADY_LOADED_AS_DLL,
++ MD_NTSTATUS_WIN_STATUS_INCOMPATIBLE_WITH_GLOBAL_SHORT_NAME_REGISTRY_SETTING,
++ MD_NTSTATUS_WIN_STATUS_SHORT_NAMES_NOT_ENABLED_ON_VOLUME,
++ MD_NTSTATUS_WIN_STATUS_SECURITY_STREAM_IS_INCONSISTENT,
++ MD_NTSTATUS_WIN_STATUS_INVALID_LOCK_RANGE,
++ MD_NTSTATUS_WIN_STATUS_INVALID_ACE_CONDITION,
++ MD_NTSTATUS_WIN_STATUS_IMAGE_SUBSYSTEM_NOT_PRESENT,
++ MD_NTSTATUS_WIN_STATUS_NOTIFICATION_GUID_ALREADY_DEFINED,
++ MD_NTSTATUS_WIN_STATUS_INVALID_EXCEPTION_HANDLER,
++ MD_NTSTATUS_WIN_STATUS_DUPLICATE_PRIVILEGES,
++ MD_NTSTATUS_WIN_STATUS_NOT_ALLOWED_ON_SYSTEM_FILE,
++ MD_NTSTATUS_WIN_STATUS_REPAIR_NEEDED,
++ MD_NTSTATUS_WIN_STATUS_QUOTA_NOT_ENABLED,
++ MD_NTSTATUS_WIN_STATUS_NO_APPLICATION_PACKAGE,
++ MD_NTSTATUS_WIN_STATUS_FILE_METADATA_OPTIMIZATION_IN_PROGRESS,
++ MD_NTSTATUS_WIN_STATUS_NOT_SAME_OBJECT,
++ MD_NTSTATUS_WIN_STATUS_FATAL_MEMORY_EXHAUSTION,
++ MD_NTSTATUS_WIN_STATUS_ERROR_PROCESS_NOT_IN_JOB,
++ MD_NTSTATUS_WIN_STATUS_CPU_SET_INVALID,
++ MD_NTSTATUS_WIN_STATUS_IO_DEVICE_INVALID_DATA,
++ MD_NTSTATUS_WIN_STATUS_IO_UNALIGNED_WRITE,
++ MD_NTSTATUS_WIN_STATUS_CONTROL_STACK_VIOLATION,
++ MD_NTSTATUS_WIN_STATUS_NETWORK_OPEN_RESTRICTION,
++ MD_NTSTATUS_WIN_STATUS_NO_USER_SESSION_KEY,
++ MD_NTSTATUS_WIN_STATUS_USER_SESSION_DELETED,
++ MD_NTSTATUS_WIN_STATUS_RESOURCE_LANG_NOT_FOUND,
++ MD_NTSTATUS_WIN_STATUS_INSUFF_SERVER_RESOURCES,
++ MD_NTSTATUS_WIN_STATUS_INVALID_BUFFER_SIZE,
++ MD_NTSTATUS_WIN_STATUS_INVALID_ADDRESS_COMPONENT,
++ MD_NTSTATUS_WIN_STATUS_INVALID_ADDRESS_WILDCARD,
++ MD_NTSTATUS_WIN_STATUS_TOO_MANY_ADDRESSES,
++ MD_NTSTATUS_WIN_STATUS_ADDRESS_ALREADY_EXISTS,
++ MD_NTSTATUS_WIN_STATUS_ADDRESS_CLOSED,
++ MD_NTSTATUS_WIN_STATUS_CONNECTION_DISCONNECTED,
++ MD_NTSTATUS_WIN_STATUS_CONNECTION_RESET,
++ MD_NTSTATUS_WIN_STATUS_TOO_MANY_NODES,
++ MD_NTSTATUS_WIN_STATUS_TRANSACTION_ABORTED,
++ MD_NTSTATUS_WIN_STATUS_TRANSACTION_TIMED_OUT,
++ MD_NTSTATUS_WIN_STATUS_TRANSACTION_NO_RELEASE,
++ MD_NTSTATUS_WIN_STATUS_TRANSACTION_NO_MATCH,
++ MD_NTSTATUS_WIN_STATUS_TRANSACTION_RESPONDED,
++ MD_NTSTATUS_WIN_STATUS_TRANSACTION_INVALID_ID,
++ MD_NTSTATUS_WIN_STATUS_TRANSACTION_INVALID_TYPE,
++ MD_NTSTATUS_WIN_STATUS_NOT_SERVER_SESSION,
++ MD_NTSTATUS_WIN_STATUS_NOT_CLIENT_SESSION,
++ MD_NTSTATUS_WIN_STATUS_CANNOT_LOAD_REGISTRY_FILE,
++ MD_NTSTATUS_WIN_STATUS_DEBUG_ATTACH_FAILED,
++ MD_NTSTATUS_WIN_STATUS_SYSTEM_PROCESS_TERMINATED,
++ MD_NTSTATUS_WIN_STATUS_DATA_NOT_ACCEPTED,
++ MD_NTSTATUS_WIN_STATUS_NO_BROWSER_SERVERS_FOUND,
++ MD_NTSTATUS_WIN_STATUS_VDM_HARD_ERROR,
++ MD_NTSTATUS_WIN_STATUS_DRIVER_CANCEL_TIMEOUT,
++ MD_NTSTATUS_WIN_STATUS_REPLY_MESSAGE_MISMATCH,
++ MD_NTSTATUS_WIN_STATUS_MAPPED_ALIGNMENT,
++ MD_NTSTATUS_WIN_STATUS_IMAGE_CHECKSUM_MISMATCH,
++ MD_NTSTATUS_WIN_STATUS_LOST_WRITEBEHIND_DATA,
++ MD_NTSTATUS_WIN_STATUS_CLIENT_SERVER_PARAMETERS_INVALID,
++ MD_NTSTATUS_WIN_STATUS_PASSWORD_MUST_CHANGE,
++ MD_NTSTATUS_WIN_STATUS_NOT_FOUND,
++ MD_NTSTATUS_WIN_STATUS_NOT_TINY_STREAM,
++ MD_NTSTATUS_WIN_STATUS_RECOVERY_FAILURE,
++ MD_NTSTATUS_WIN_STATUS_STACK_OVERFLOW_READ,
++ MD_NTSTATUS_WIN_STATUS_FAIL_CHECK,
++ MD_NTSTATUS_WIN_STATUS_DUPLICATE_OBJECTID,
++ MD_NTSTATUS_WIN_STATUS_OBJECTID_EXISTS,
++ MD_NTSTATUS_WIN_STATUS_CONVERT_TO_LARGE,
++ MD_NTSTATUS_WIN_STATUS_RETRY,
++ MD_NTSTATUS_WIN_STATUS_FOUND_OUT_OF_SCOPE,
++ MD_NTSTATUS_WIN_STATUS_ALLOCATE_BUCKET,
++ MD_NTSTATUS_WIN_STATUS_PROPSET_NOT_FOUND,
++ MD_NTSTATUS_WIN_STATUS_MARSHALL_OVERFLOW,
++ MD_NTSTATUS_WIN_STATUS_INVALID_VARIANT,
++ MD_NTSTATUS_WIN_STATUS_DOMAIN_CONTROLLER_NOT_FOUND,
++ MD_NTSTATUS_WIN_STATUS_ACCOUNT_LOCKED_OUT,
++ MD_NTSTATUS_WIN_STATUS_HANDLE_NOT_CLOSABLE,
++ MD_NTSTATUS_WIN_STATUS_CONNECTION_REFUSED,
++ MD_NTSTATUS_WIN_STATUS_GRACEFUL_DISCONNECT,
++ MD_NTSTATUS_WIN_STATUS_ADDRESS_ALREADY_ASSOCIATED,
++ MD_NTSTATUS_WIN_STATUS_ADDRESS_NOT_ASSOCIATED,
++ MD_NTSTATUS_WIN_STATUS_CONNECTION_INVALID,
++ MD_NTSTATUS_WIN_STATUS_CONNECTION_ACTIVE,
++ MD_NTSTATUS_WIN_STATUS_NETWORK_UNREACHABLE,
++ MD_NTSTATUS_WIN_STATUS_HOST_UNREACHABLE,
++ MD_NTSTATUS_WIN_STATUS_PROTOCOL_UNREACHABLE,
++ MD_NTSTATUS_WIN_STATUS_PORT_UNREACHABLE,
++ MD_NTSTATUS_WIN_STATUS_REQUEST_ABORTED,
++ MD_NTSTATUS_WIN_STATUS_CONNECTION_ABORTED,
++ MD_NTSTATUS_WIN_STATUS_BAD_COMPRESSION_BUFFER,
++ MD_NTSTATUS_WIN_STATUS_USER_MAPPED_FILE,
++ MD_NTSTATUS_WIN_STATUS_AUDIT_FAILED,
++ MD_NTSTATUS_WIN_STATUS_TIMER_RESOLUTION_NOT_SET,
++ MD_NTSTATUS_WIN_STATUS_CONNECTION_COUNT_LIMIT,
++ MD_NTSTATUS_WIN_STATUS_LOGIN_TIME_RESTRICTION,
++ MD_NTSTATUS_WIN_STATUS_LOGIN_WKSTA_RESTRICTION,
++ MD_NTSTATUS_WIN_STATUS_IMAGE_MP_UP_MISMATCH,
++ MD_NTSTATUS_WIN_STATUS_INSUFFICIENT_LOGON_INFO,
++ MD_NTSTATUS_WIN_STATUS_BAD_DLL_ENTRYPOINT,
++ MD_NTSTATUS_WIN_STATUS_BAD_SERVICE_ENTRYPOINT,
++ MD_NTSTATUS_WIN_STATUS_LPC_REPLY_LOST,
++ MD_NTSTATUS_WIN_STATUS_IP_ADDRESS_CONFLICT1,
++ MD_NTSTATUS_WIN_STATUS_IP_ADDRESS_CONFLICT2,
++ MD_NTSTATUS_WIN_STATUS_REGISTRY_QUOTA_LIMIT,
++ MD_NTSTATUS_WIN_STATUS_PATH_NOT_COVERED,
++ MD_NTSTATUS_WIN_STATUS_NO_CALLBACK_ACTIVE,
++ MD_NTSTATUS_WIN_STATUS_LICENSE_QUOTA_EXCEEDED,
++ MD_NTSTATUS_WIN_STATUS_PWD_TOO_SHORT,
++ MD_NTSTATUS_WIN_STATUS_PWD_TOO_RECENT,
++ MD_NTSTATUS_WIN_STATUS_PWD_HISTORY_CONFLICT,
++ MD_NTSTATUS_WIN_STATUS_PLUGPLAY_NO_DEVICE,
++ MD_NTSTATUS_WIN_STATUS_UNSUPPORTED_COMPRESSION,
++ MD_NTSTATUS_WIN_STATUS_INVALID_HW_PROFILE,
++ MD_NTSTATUS_WIN_STATUS_INVALID_PLUGPLAY_DEVICE_PATH,
++ MD_NTSTATUS_WIN_STATUS_DRIVER_ORDINAL_NOT_FOUND,
++ MD_NTSTATUS_WIN_STATUS_DRIVER_ENTRYPOINT_NOT_FOUND,
++ MD_NTSTATUS_WIN_STATUS_RESOURCE_NOT_OWNED,
++ MD_NTSTATUS_WIN_STATUS_TOO_MANY_LINKS,
++ MD_NTSTATUS_WIN_STATUS_QUOTA_LIST_INCONSISTENT,
++ MD_NTSTATUS_WIN_STATUS_FILE_IS_OFFLINE,
++ MD_NTSTATUS_WIN_STATUS_EVALUATION_EXPIRATION,
++ MD_NTSTATUS_WIN_STATUS_ILLEGAL_DLL_RELOCATION,
++ MD_NTSTATUS_WIN_STATUS_LICENSE_VIOLATION,
++ MD_NTSTATUS_WIN_STATUS_DLL_INIT_FAILED_LOGOFF,
++ MD_NTSTATUS_WIN_STATUS_DRIVER_UNABLE_TO_LOAD,
++ MD_NTSTATUS_WIN_STATUS_DFS_UNAVAILABLE,
++ MD_NTSTATUS_WIN_STATUS_VOLUME_DISMOUNTED,
++ MD_NTSTATUS_WIN_STATUS_WX86_INTERNAL_ERROR,
++ MD_NTSTATUS_WIN_STATUS_WX86_FLOAT_STACK_CHECK,
++ MD_NTSTATUS_WIN_STATUS_VALIDATE_CONTINUE,
++ MD_NTSTATUS_WIN_STATUS_NO_MATCH,
++ MD_NTSTATUS_WIN_STATUS_NO_MORE_MATCHES,
++ MD_NTSTATUS_WIN_STATUS_NOT_A_REPARSE_POINT,
++ MD_NTSTATUS_WIN_STATUS_IO_REPARSE_TAG_INVALID,
++ MD_NTSTATUS_WIN_STATUS_IO_REPARSE_TAG_MISMATCH,
++ MD_NTSTATUS_WIN_STATUS_IO_REPARSE_DATA_INVALID,
++ MD_NTSTATUS_WIN_STATUS_IO_REPARSE_TAG_NOT_HANDLED,
++ MD_NTSTATUS_WIN_STATUS_PWD_TOO_LONG,
++ MD_NTSTATUS_WIN_STATUS_STOWED_EXCEPTION,
++ MD_NTSTATUS_WIN_STATUS_CONTEXT_STOWED_EXCEPTION,
++ MD_NTSTATUS_WIN_STATUS_REPARSE_POINT_NOT_RESOLVED,
++ MD_NTSTATUS_WIN_STATUS_DIRECTORY_IS_A_REPARSE_POINT,
++ MD_NTSTATUS_WIN_STATUS_RANGE_LIST_CONFLICT,
++ MD_NTSTATUS_WIN_STATUS_SOURCE_ELEMENT_EMPTY,
++ MD_NTSTATUS_WIN_STATUS_DESTINATION_ELEMENT_FULL,
++ MD_NTSTATUS_WIN_STATUS_ILLEGAL_ELEMENT_ADDRESS,
++ MD_NTSTATUS_WIN_STATUS_MAGAZINE_NOT_PRESENT,
++ MD_NTSTATUS_WIN_STATUS_REINITIALIZATION_NEEDED,
++ MD_NTSTATUS_WIN_STATUS_ENCRYPTION_FAILED,
++ MD_NTSTATUS_WIN_STATUS_DECRYPTION_FAILED,
++ MD_NTSTATUS_WIN_STATUS_RANGE_NOT_FOUND,
++ MD_NTSTATUS_WIN_STATUS_NO_RECOVERY_POLICY,
++ MD_NTSTATUS_WIN_STATUS_NO_EFS,
++ MD_NTSTATUS_WIN_STATUS_WRONG_EFS,
++ MD_NTSTATUS_WIN_STATUS_NO_USER_KEYS,
++ MD_NTSTATUS_WIN_STATUS_FILE_NOT_ENCRYPTED,
++ MD_NTSTATUS_WIN_STATUS_NOT_EXPORT_FORMAT,
++ MD_NTSTATUS_WIN_STATUS_FILE_ENCRYPTED,
++ MD_NTSTATUS_WIN_STATUS_WMI_GUID_NOT_FOUND,
++ MD_NTSTATUS_WIN_STATUS_WMI_INSTANCE_NOT_FOUND,
++ MD_NTSTATUS_WIN_STATUS_WMI_ITEMID_NOT_FOUND,
++ MD_NTSTATUS_WIN_STATUS_WMI_TRY_AGAIN,
++ MD_NTSTATUS_WIN_STATUS_SHARED_POLICY,
++ MD_NTSTATUS_WIN_STATUS_POLICY_OBJECT_NOT_FOUND,
++ MD_NTSTATUS_WIN_STATUS_POLICY_ONLY_IN_DS,
++ MD_NTSTATUS_WIN_STATUS_VOLUME_NOT_UPGRADED,
++ MD_NTSTATUS_WIN_STATUS_REMOTE_STORAGE_NOT_ACTIVE,
++ MD_NTSTATUS_WIN_STATUS_REMOTE_STORAGE_MEDIA_ERROR,
++ MD_NTSTATUS_WIN_STATUS_NO_TRACKING_SERVICE,
++ MD_NTSTATUS_WIN_STATUS_SERVER_SID_MISMATCH,
++ MD_NTSTATUS_WIN_STATUS_DS_NO_ATTRIBUTE_OR_VALUE,
++ MD_NTSTATUS_WIN_STATUS_DS_INVALID_ATTRIBUTE_SYNTAX,
++ MD_NTSTATUS_WIN_STATUS_DS_ATTRIBUTE_TYPE_UNDEFINED,
++ MD_NTSTATUS_WIN_STATUS_DS_ATTRIBUTE_OR_VALUE_EXISTS,
++ MD_NTSTATUS_WIN_STATUS_DS_BUSY,
++ MD_NTSTATUS_WIN_STATUS_DS_UNAVAILABLE,
++ MD_NTSTATUS_WIN_STATUS_DS_NO_RIDS_ALLOCATED,
++ MD_NTSTATUS_WIN_STATUS_DS_NO_MORE_RIDS,
++ MD_NTSTATUS_WIN_STATUS_DS_INCORRECT_ROLE_OWNER,
++ MD_NTSTATUS_WIN_STATUS_DS_RIDMGR_INIT_ERROR,
++ MD_NTSTATUS_WIN_STATUS_DS_OBJ_CLASS_VIOLATION,
++ MD_NTSTATUS_WIN_STATUS_DS_CANT_ON_NON_LEAF,
++ MD_NTSTATUS_WIN_STATUS_DS_CANT_ON_RDN,
++ MD_NTSTATUS_WIN_STATUS_DS_CANT_MOD_OBJ_CLASS,
++ MD_NTSTATUS_WIN_STATUS_DS_CROSS_DOM_MOVE_FAILED,
++ MD_NTSTATUS_WIN_STATUS_DS_GC_NOT_AVAILABLE,
++ MD_NTSTATUS_WIN_STATUS_DIRECTORY_SERVICE_REQUIRED,
++ MD_NTSTATUS_WIN_STATUS_REPARSE_ATTRIBUTE_CONFLICT,
++ MD_NTSTATUS_WIN_STATUS_CANT_ENABLE_DENY_ONLY,
++ MD_NTSTATUS_WIN_STATUS_FLOAT_MULTIPLE_FAULTS,
++ MD_NTSTATUS_WIN_STATUS_FLOAT_MULTIPLE_TRAPS,
++ MD_NTSTATUS_WIN_STATUS_DEVICE_REMOVED,
++ MD_NTSTATUS_WIN_STATUS_JOURNAL_DELETE_IN_PROGRESS,
++ MD_NTSTATUS_WIN_STATUS_JOURNAL_NOT_ACTIVE,
++ MD_NTSTATUS_WIN_STATUS_NOINTERFACE,
++ MD_NTSTATUS_WIN_STATUS_DS_RIDMGR_DISABLED,
++ MD_NTSTATUS_WIN_STATUS_DS_ADMIN_LIMIT_EXCEEDED,
++ MD_NTSTATUS_WIN_STATUS_DRIVER_FAILED_SLEEP,
++ MD_NTSTATUS_WIN_STATUS_MUTUAL_AUTHENTICATION_FAILED,
++ MD_NTSTATUS_WIN_STATUS_CORRUPT_SYSTEM_FILE,
++ MD_NTSTATUS_WIN_STATUS_DATATYPE_MISALIGNMENT_ERROR,
++ MD_NTSTATUS_WIN_STATUS_WMI_READ_ONLY,
++ MD_NTSTATUS_WIN_STATUS_WMI_SET_FAILURE,
++ MD_NTSTATUS_WIN_STATUS_COMMITMENT_MINIMUM,
++ MD_NTSTATUS_WIN_STATUS_REG_NAT_CONSUMPTION,
++ MD_NTSTATUS_WIN_STATUS_TRANSPORT_FULL,
++ MD_NTSTATUS_WIN_STATUS_DS_SAM_INIT_FAILURE,
++ MD_NTSTATUS_WIN_STATUS_ONLY_IF_CONNECTED,
++ MD_NTSTATUS_WIN_STATUS_DS_SENSITIVE_GROUP_VIOLATION,
++ MD_NTSTATUS_WIN_STATUS_PNP_RESTART_ENUMERATION,
++ MD_NTSTATUS_WIN_STATUS_JOURNAL_ENTRY_DELETED,
++ MD_NTSTATUS_WIN_STATUS_DS_CANT_MOD_PRIMARYGROUPID,
++ MD_NTSTATUS_WIN_STATUS_SYSTEM_IMAGE_BAD_SIGNATURE,
++ MD_NTSTATUS_WIN_STATUS_PNP_REBOOT_REQUIRED,
++ MD_NTSTATUS_WIN_STATUS_POWER_STATE_INVALID,
++ MD_NTSTATUS_WIN_STATUS_DS_INVALID_GROUP_TYPE,
++ MD_NTSTATUS_WIN_STATUS_DS_NO_NEST_GLOBALGROUP_IN_MIXEDDOMAIN,
++ MD_NTSTATUS_WIN_STATUS_DS_NO_NEST_LOCALGROUP_IN_MIXEDDOMAIN,
++ MD_NTSTATUS_WIN_STATUS_DS_GLOBAL_CANT_HAVE_LOCAL_MEMBER,
++ MD_NTSTATUS_WIN_STATUS_DS_GLOBAL_CANT_HAVE_UNIVERSAL_MEMBER,
++ MD_NTSTATUS_WIN_STATUS_DS_UNIVERSAL_CANT_HAVE_LOCAL_MEMBER,
++ MD_NTSTATUS_WIN_STATUS_DS_GLOBAL_CANT_HAVE_CROSSDOMAIN_MEMBER,
++ MD_NTSTATUS_WIN_STATUS_DS_LOCAL_CANT_HAVE_CROSSDOMAIN_LOCAL_MEMBER,
++ MD_NTSTATUS_WIN_STATUS_DS_HAVE_PRIMARY_MEMBERS,
++ MD_NTSTATUS_WIN_STATUS_WMI_NOT_SUPPORTED,
++ MD_NTSTATUS_WIN_STATUS_INSUFFICIENT_POWER,
++ MD_NTSTATUS_WIN_STATUS_SAM_NEED_BOOTKEY_PASSWORD,
++ MD_NTSTATUS_WIN_STATUS_SAM_NEED_BOOTKEY_FLOPPY,
++ MD_NTSTATUS_WIN_STATUS_DS_CANT_START,
++ MD_NTSTATUS_WIN_STATUS_DS_INIT_FAILURE,
++ MD_NTSTATUS_WIN_STATUS_SAM_INIT_FAILURE,
++ MD_NTSTATUS_WIN_STATUS_DS_GC_REQUIRED,
++ MD_NTSTATUS_WIN_STATUS_DS_LOCAL_MEMBER_OF_LOCAL_ONLY,
++ MD_NTSTATUS_WIN_STATUS_DS_NO_FPO_IN_UNIVERSAL_GROUPS,
++ MD_NTSTATUS_WIN_STATUS_DS_MACHINE_ACCOUNT_QUOTA_EXCEEDED,
++ MD_NTSTATUS_WIN_STATUS_MULTIPLE_FAULT_VIOLATION,
++ MD_NTSTATUS_WIN_STATUS_CURRENT_DOMAIN_NOT_ALLOWED,
++ MD_NTSTATUS_WIN_STATUS_CANNOT_MAKE,
++ MD_NTSTATUS_WIN_STATUS_SYSTEM_SHUTDOWN,
++ MD_NTSTATUS_WIN_STATUS_DS_INIT_FAILURE_CONSOLE,
++ MD_NTSTATUS_WIN_STATUS_DS_SAM_INIT_FAILURE_CONSOLE,
++ MD_NTSTATUS_WIN_STATUS_UNFINISHED_CONTEXT_DELETED,
++ MD_NTSTATUS_WIN_STATUS_NO_TGT_REPLY,
++ MD_NTSTATUS_WIN_STATUS_OBJECTID_NOT_FOUND,
++ MD_NTSTATUS_WIN_STATUS_NO_IP_ADDRESSES,
++ MD_NTSTATUS_WIN_STATUS_WRONG_CREDENTIAL_HANDLE,
++ MD_NTSTATUS_WIN_STATUS_CRYPTO_SYSTEM_INVALID,
++ MD_NTSTATUS_WIN_STATUS_MAX_REFERRALS_EXCEEDED,
++ MD_NTSTATUS_WIN_STATUS_MUST_BE_KDC,
++ MD_NTSTATUS_WIN_STATUS_STRONG_CRYPTO_NOT_SUPPORTED,
++ MD_NTSTATUS_WIN_STATUS_TOO_MANY_PRINCIPALS,
++ MD_NTSTATUS_WIN_STATUS_NO_PA_DATA,
++ MD_NTSTATUS_WIN_STATUS_PKINIT_NAME_MISMATCH,
++ MD_NTSTATUS_WIN_STATUS_SMARTCARD_LOGON_REQUIRED,
++ MD_NTSTATUS_WIN_STATUS_KDC_INVALID_REQUEST,
++ MD_NTSTATUS_WIN_STATUS_KDC_UNABLE_TO_REFER,
++ MD_NTSTATUS_WIN_STATUS_KDC_UNKNOWN_ETYPE,
++ MD_NTSTATUS_WIN_STATUS_SHUTDOWN_IN_PROGRESS,
++ MD_NTSTATUS_WIN_STATUS_SERVER_SHUTDOWN_IN_PROGRESS,
++ MD_NTSTATUS_WIN_STATUS_NOT_SUPPORTED_ON_SBS,
++ MD_NTSTATUS_WIN_STATUS_WMI_GUID_DISCONNECTED,
++ MD_NTSTATUS_WIN_STATUS_WMI_ALREADY_DISABLED,
++ MD_NTSTATUS_WIN_STATUS_WMI_ALREADY_ENABLED,
++ MD_NTSTATUS_WIN_STATUS_MFT_TOO_FRAGMENTED,
++ MD_NTSTATUS_WIN_STATUS_COPY_PROTECTION_FAILURE,
++ MD_NTSTATUS_WIN_STATUS_CSS_AUTHENTICATION_FAILURE,
++ MD_NTSTATUS_WIN_STATUS_CSS_KEY_NOT_PRESENT,
++ MD_NTSTATUS_WIN_STATUS_CSS_KEY_NOT_ESTABLISHED,
++ MD_NTSTATUS_WIN_STATUS_CSS_SCRAMBLED_SECTOR,
++ MD_NTSTATUS_WIN_STATUS_CSS_REGION_MISMATCH,
++ MD_NTSTATUS_WIN_STATUS_CSS_RESETS_EXHAUSTED,
++ MD_NTSTATUS_WIN_STATUS_PASSWORD_CHANGE_REQUIRED,
++ MD_NTSTATUS_WIN_STATUS_LOST_MODE_LOGON_RESTRICTION,
++ MD_NTSTATUS_WIN_STATUS_PKINIT_FAILURE,
++ MD_NTSTATUS_WIN_STATUS_SMARTCARD_SUBSYSTEM_FAILURE,
++ MD_NTSTATUS_WIN_STATUS_NO_KERB_KEY,
++ MD_NTSTATUS_WIN_STATUS_HOST_DOWN,
++ MD_NTSTATUS_WIN_STATUS_UNSUPPORTED_PREAUTH,
++ MD_NTSTATUS_WIN_STATUS_EFS_ALG_BLOB_TOO_BIG,
++ MD_NTSTATUS_WIN_STATUS_PORT_NOT_SET,
++ MD_NTSTATUS_WIN_STATUS_DEBUGGER_INACTIVE,
++ MD_NTSTATUS_WIN_STATUS_DS_VERSION_CHECK_FAILURE,
++ MD_NTSTATUS_WIN_STATUS_AUDITING_DISABLED,
++ MD_NTSTATUS_WIN_STATUS_PRENT4_MACHINE_ACCOUNT,
++ MD_NTSTATUS_WIN_STATUS_DS_AG_CANT_HAVE_UNIVERSAL_MEMBER,
++ MD_NTSTATUS_WIN_STATUS_INVALID_IMAGE_WIN_32,
++ MD_NTSTATUS_WIN_STATUS_INVALID_IMAGE_WIN_64,
++ MD_NTSTATUS_WIN_STATUS_BAD_BINDINGS,
++ MD_NTSTATUS_WIN_STATUS_NETWORK_SESSION_EXPIRED,
++ MD_NTSTATUS_WIN_STATUS_APPHELP_BLOCK,
++ MD_NTSTATUS_WIN_STATUS_ALL_SIDS_FILTERED,
++ MD_NTSTATUS_WIN_STATUS_NOT_SAFE_MODE_DRIVER,
++ MD_NTSTATUS_WIN_STATUS_ACCESS_DISABLED_BY_POLICY_DEFAULT,
++ MD_NTSTATUS_WIN_STATUS_ACCESS_DISABLED_BY_POLICY_PATH,
++ MD_NTSTATUS_WIN_STATUS_ACCESS_DISABLED_BY_POLICY_PUBLISHER,
++ MD_NTSTATUS_WIN_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER,
++ MD_NTSTATUS_WIN_STATUS_FAILED_DRIVER_ENTRY,
++ MD_NTSTATUS_WIN_STATUS_DEVICE_ENUMERATION_ERROR,
++ MD_NTSTATUS_WIN_STATUS_MOUNT_POINT_NOT_RESOLVED,
++ MD_NTSTATUS_WIN_STATUS_INVALID_DEVICE_OBJECT_PARAMETER,
++ MD_NTSTATUS_WIN_STATUS_MCA_OCCURED,
++ MD_NTSTATUS_WIN_STATUS_DRIVER_BLOCKED_CRITICAL,
++ MD_NTSTATUS_WIN_STATUS_DRIVER_BLOCKED,
++ MD_NTSTATUS_WIN_STATUS_DRIVER_DATABASE_ERROR,
++ MD_NTSTATUS_WIN_STATUS_SYSTEM_HIVE_TOO_LARGE,
++ MD_NTSTATUS_WIN_STATUS_INVALID_IMPORT_OF_NON_DLL,
++ MD_NTSTATUS_WIN_STATUS_NO_SECRETS,
++ MD_NTSTATUS_WIN_STATUS_ACCESS_DISABLED_NO_SAFER_UI_BY_POLICY,
++ MD_NTSTATUS_WIN_STATUS_FAILED_STACK_SWITCH,
++ MD_NTSTATUS_WIN_STATUS_HEAP_CORRUPTION,
++ MD_NTSTATUS_WIN_STATUS_SMARTCARD_WRONG_PIN,
++ MD_NTSTATUS_WIN_STATUS_SMARTCARD_CARD_BLOCKED,
++ MD_NTSTATUS_WIN_STATUS_SMARTCARD_CARD_NOT_AUTHENTICATED,
++ MD_NTSTATUS_WIN_STATUS_SMARTCARD_NO_CARD,
++ MD_NTSTATUS_WIN_STATUS_SMARTCARD_NO_KEY_CONTAINER,
++ MD_NTSTATUS_WIN_STATUS_SMARTCARD_NO_CERTIFICATE,
++ MD_NTSTATUS_WIN_STATUS_SMARTCARD_NO_KEYSET,
++ MD_NTSTATUS_WIN_STATUS_SMARTCARD_IO_ERROR,
++ MD_NTSTATUS_WIN_STATUS_DOWNGRADE_DETECTED,
++ MD_NTSTATUS_WIN_STATUS_SMARTCARD_CERT_REVOKED,
++ MD_NTSTATUS_WIN_STATUS_ISSUING_CA_UNTRUSTED,
++ MD_NTSTATUS_WIN_STATUS_REVOCATION_OFFLINE_C,
++ MD_NTSTATUS_WIN_STATUS_PKINIT_CLIENT_FAILURE,
++ MD_NTSTATUS_WIN_STATUS_SMARTCARD_CERT_EXPIRED,
++ MD_NTSTATUS_WIN_STATUS_DRIVER_FAILED_PRIOR_UNLOAD,
++ MD_NTSTATUS_WIN_STATUS_SMARTCARD_SILENT_CONTEXT,
++ MD_NTSTATUS_WIN_STATUS_PER_USER_TRUST_QUOTA_EXCEEDED,
++ MD_NTSTATUS_WIN_STATUS_ALL_USER_TRUST_QUOTA_EXCEEDED,
++ MD_NTSTATUS_WIN_STATUS_USER_DELETE_TRUST_QUOTA_EXCEEDED,
++ MD_NTSTATUS_WIN_STATUS_DS_NAME_NOT_UNIQUE,
++ MD_NTSTATUS_WIN_STATUS_DS_DUPLICATE_ID_FOUND,
++ MD_NTSTATUS_WIN_STATUS_DS_GROUP_CONVERSION_ERROR,
++ MD_NTSTATUS_WIN_STATUS_VOLSNAP_PREPARE_HIBERNATE,
++ MD_NTSTATUS_WIN_STATUS_USER2USER_REQUIRED,
++ MD_NTSTATUS_WIN_STATUS_STACK_BUFFER_OVERRUN,
++ MD_NTSTATUS_WIN_STATUS_NO_S4U_PROT_SUPPORT,
++ MD_NTSTATUS_WIN_STATUS_CROSSREALM_DELEGATION_FAILURE,
++ MD_NTSTATUS_WIN_STATUS_REVOCATION_OFFLINE_KDC,
++ MD_NTSTATUS_WIN_STATUS_ISSUING_CA_UNTRUSTED_KDC,
++ MD_NTSTATUS_WIN_STATUS_KDC_CERT_EXPIRED,
++ MD_NTSTATUS_WIN_STATUS_KDC_CERT_REVOKED,
++ MD_NTSTATUS_WIN_STATUS_PARAMETER_QUOTA_EXCEEDED,
++ MD_NTSTATUS_WIN_STATUS_HIBERNATION_FAILURE,
++ MD_NTSTATUS_WIN_STATUS_DELAY_LOAD_FAILED,
++ MD_NTSTATUS_WIN_STATUS_AUTHENTICATION_FIREWALL_FAILED,
++ MD_NTSTATUS_WIN_STATUS_VDM_DISALLOWED,
++ MD_NTSTATUS_WIN_STATUS_HUNG_DISPLAY_DRIVER_THREAD,
++ MD_NTSTATUS_WIN_STATUS_INSUFFICIENT_RESOURCE_FOR_SPECIFIED_SHARED_SECTION_SIZE,
++ MD_NTSTATUS_WIN_STATUS_INVALID_CRUNTIME_PARAMETER,
++ MD_NTSTATUS_WIN_STATUS_NTLM_BLOCKED,
++ MD_NTSTATUS_WIN_STATUS_DS_SRC_SID_EXISTS_IN_FOREST,
++ MD_NTSTATUS_WIN_STATUS_DS_DOMAIN_NAME_EXISTS_IN_FOREST,
++ MD_NTSTATUS_WIN_STATUS_DS_FLAT_NAME_EXISTS_IN_FOREST,
++ MD_NTSTATUS_WIN_STATUS_INVALID_USER_PRINCIPAL_NAME,
++ MD_NTSTATUS_WIN_STATUS_FATAL_USER_CALLBACK_EXCEPTION,
++ MD_NTSTATUS_WIN_STATUS_ASSERTION_FAILURE,
++ MD_NTSTATUS_WIN_STATUS_VERIFIER_STOP,
++ MD_NTSTATUS_WIN_STATUS_CALLBACK_POP_STACK,
++ MD_NTSTATUS_WIN_STATUS_INCOMPATIBLE_DRIVER_BLOCKED,
++ MD_NTSTATUS_WIN_STATUS_HIVE_UNLOADED,
++ MD_NTSTATUS_WIN_STATUS_COMPRESSION_DISABLED,
++ MD_NTSTATUS_WIN_STATUS_FILE_SYSTEM_LIMITATION,
++ MD_NTSTATUS_WIN_STATUS_INVALID_IMAGE_HASH,
++ MD_NTSTATUS_WIN_STATUS_NOT_CAPABLE,
++ MD_NTSTATUS_WIN_STATUS_REQUEST_OUT_OF_SEQUENCE,
++ MD_NTSTATUS_WIN_STATUS_IMPLEMENTATION_LIMIT,
++ MD_NTSTATUS_WIN_STATUS_ELEVATION_REQUIRED,
++ MD_NTSTATUS_WIN_STATUS_NO_SECURITY_CONTEXT,
++ MD_NTSTATUS_WIN_STATUS_PKU2U_CERT_FAILURE,
++ MD_NTSTATUS_WIN_STATUS_BEYOND_VDL,
++ MD_NTSTATUS_WIN_STATUS_ENCOUNTERED_WRITE_IN_PROGRESS,
++ MD_NTSTATUS_WIN_STATUS_PTE_CHANGED,
++ MD_NTSTATUS_WIN_STATUS_PURGE_FAILED,
++ MD_NTSTATUS_WIN_STATUS_CRED_REQUIRES_CONFIRMATION,
++ MD_NTSTATUS_WIN_STATUS_CS_ENCRYPTION_INVALID_SERVER_RESPONSE,
++ MD_NTSTATUS_WIN_STATUS_CS_ENCRYPTION_UNSUPPORTED_SERVER,
++ MD_NTSTATUS_WIN_STATUS_CS_ENCRYPTION_EXISTING_ENCRYPTED_FILE,
++ MD_NTSTATUS_WIN_STATUS_CS_ENCRYPTION_NEW_ENCRYPTED_FILE,
++ MD_NTSTATUS_WIN_STATUS_CS_ENCRYPTION_FILE_NOT_CSE,
++ MD_NTSTATUS_WIN_STATUS_INVALID_LABEL,
++ MD_NTSTATUS_WIN_STATUS_DRIVER_PROCESS_TERMINATED,
++ MD_NTSTATUS_WIN_STATUS_AMBIGUOUS_SYSTEM_DEVICE,
++ MD_NTSTATUS_WIN_STATUS_SYSTEM_DEVICE_NOT_FOUND,
++ MD_NTSTATUS_WIN_STATUS_RESTART_BOOT_APPLICATION,
++ MD_NTSTATUS_WIN_STATUS_INSUFFICIENT_NVRAM_RESOURCES,
++ MD_NTSTATUS_WIN_STATUS_INVALID_SESSION,
++ MD_NTSTATUS_WIN_STATUS_THREAD_ALREADY_IN_SESSION,
++ MD_NTSTATUS_WIN_STATUS_THREAD_NOT_IN_SESSION,
++ MD_NTSTATUS_WIN_STATUS_INVALID_WEIGHT,
++ MD_NTSTATUS_WIN_STATUS_REQUEST_PAUSED,
++ MD_NTSTATUS_WIN_STATUS_NO_RANGES_PROCESSED,
++ MD_NTSTATUS_WIN_STATUS_DISK_RESOURCES_EXHAUSTED,
++ MD_NTSTATUS_WIN_STATUS_NEEDS_REMEDIATION,
++ MD_NTSTATUS_WIN_STATUS_DEVICE_FEATURE_NOT_SUPPORTED,
++ MD_NTSTATUS_WIN_STATUS_DEVICE_UNREACHABLE,
++ MD_NTSTATUS_WIN_STATUS_INVALID_TOKEN,
++ MD_NTSTATUS_WIN_STATUS_SERVER_UNAVAILABLE,
++ MD_NTSTATUS_WIN_STATUS_FILE_NOT_AVAILABLE,
++ MD_NTSTATUS_WIN_STATUS_DEVICE_INSUFFICIENT_RESOURCES,
++ MD_NTSTATUS_WIN_STATUS_PACKAGE_UPDATING,
++ MD_NTSTATUS_WIN_STATUS_NOT_READ_FROM_COPY,
++ MD_NTSTATUS_WIN_STATUS_FT_WRITE_FAILURE,
++ MD_NTSTATUS_WIN_STATUS_FT_DI_SCAN_REQUIRED,
++ MD_NTSTATUS_WIN_STATUS_OBJECT_NOT_EXTERNALLY_BACKED,
++ MD_NTSTATUS_WIN_STATUS_EXTERNAL_BACKING_PROVIDER_UNKNOWN,
++ MD_NTSTATUS_WIN_STATUS_COMPRESSION_NOT_BENEFICIAL,
++ MD_NTSTATUS_WIN_STATUS_DATA_CHECKSUM_ERROR,
++ MD_NTSTATUS_WIN_STATUS_INTERMIXED_KERNEL_EA_OPERATION,
++ MD_NTSTATUS_WIN_STATUS_TRIM_READ_ZERO_NOT_SUPPORTED,
++ MD_NTSTATUS_WIN_STATUS_TOO_MANY_SEGMENT_DESCRIPTORS,
++ MD_NTSTATUS_WIN_STATUS_INVALID_OFFSET_ALIGNMENT,
++ MD_NTSTATUS_WIN_STATUS_INVALID_FIELD_IN_PARAMETER_LIST,
++ MD_NTSTATUS_WIN_STATUS_OPERATION_IN_PROGRESS,
++ MD_NTSTATUS_WIN_STATUS_INVALID_INITIATOR_TARGET_PATH,
++ MD_NTSTATUS_WIN_STATUS_SCRUB_DATA_DISABLED,
++ MD_NTSTATUS_WIN_STATUS_NOT_REDUNDANT_STORAGE,
++ MD_NTSTATUS_WIN_STATUS_RESIDENT_FILE_NOT_SUPPORTED,
++ MD_NTSTATUS_WIN_STATUS_COMPRESSED_FILE_NOT_SUPPORTED,
++ MD_NTSTATUS_WIN_STATUS_DIRECTORY_NOT_SUPPORTED,
++ MD_NTSTATUS_WIN_STATUS_IO_OPERATION_TIMEOUT,
++ MD_NTSTATUS_WIN_STATUS_SYSTEM_NEEDS_REMEDIATION,
++ MD_NTSTATUS_WIN_STATUS_APPX_INTEGRITY_FAILURE_CLR_NGEN,
++ MD_NTSTATUS_WIN_STATUS_SHARE_UNAVAILABLE,
++ MD_NTSTATUS_WIN_STATUS_APISET_NOT_HOSTED,
++ MD_NTSTATUS_WIN_STATUS_APISET_NOT_PRESENT,
++ MD_NTSTATUS_WIN_STATUS_DEVICE_HARDWARE_ERROR,
++ MD_NTSTATUS_WIN_STATUS_FIRMWARE_SLOT_INVALID,
++ MD_NTSTATUS_WIN_STATUS_FIRMWARE_IMAGE_INVALID,
++ MD_NTSTATUS_WIN_STATUS_STORAGE_TOPOLOGY_ID_MISMATCH,
++ MD_NTSTATUS_WIN_STATUS_WIM_NOT_BOOTABLE,
++ MD_NTSTATUS_WIN_STATUS_BLOCKED_BY_PARENTAL_CONTROLS,
++ MD_NTSTATUS_WIN_STATUS_NEEDS_REGISTRATION,
++ MD_NTSTATUS_WIN_STATUS_QUOTA_ACTIVITY,
++ MD_NTSTATUS_WIN_STATUS_CALLBACK_INVOKE_INLINE,
++ MD_NTSTATUS_WIN_STATUS_BLOCK_TOO_MANY_REFERENCES,
++ MD_NTSTATUS_WIN_STATUS_MARKED_TO_DISALLOW_WRITES,
++ MD_NTSTATUS_WIN_STATUS_NETWORK_ACCESS_DENIED_EDP,
++ MD_NTSTATUS_WIN_STATUS_ENCLAVE_FAILURE,
++ MD_NTSTATUS_WIN_STATUS_PNP_NO_COMPAT_DRIVERS,
++ MD_NTSTATUS_WIN_STATUS_PNP_DRIVER_PACKAGE_NOT_FOUND,
++ MD_NTSTATUS_WIN_STATUS_PNP_DRIVER_CONFIGURATION_NOT_FOUND,
++ MD_NTSTATUS_WIN_STATUS_PNP_DRIVER_CONFIGURATION_INCOMPLETE,
++ MD_NTSTATUS_WIN_STATUS_PNP_FUNCTION_DRIVER_REQUIRED,
++ MD_NTSTATUS_WIN_STATUS_PNP_DEVICE_CONFIGURATION_PENDING,
++ MD_NTSTATUS_WIN_STATUS_DEVICE_HINT_NAME_BUFFER_TOO_SMALL,
++ MD_NTSTATUS_WIN_STATUS_PACKAGE_NOT_AVAILABLE,
++ MD_NTSTATUS_WIN_STATUS_DEVICE_IN_MAINTENANCE,
++ MD_NTSTATUS_WIN_STATUS_NOT_SUPPORTED_ON_DAX,
++ MD_NTSTATUS_WIN_STATUS_FREE_SPACE_TOO_FRAGMENTED,
++ MD_NTSTATUS_WIN_STATUS_DAX_MAPPING_EXISTS,
++ MD_NTSTATUS_WIN_STATUS_CHILD_PROCESS_BLOCKED,
++ MD_NTSTATUS_WIN_STATUS_STORAGE_LOST_DATA_PERSISTENCE,
++ MD_NTSTATUS_WIN_STATUS_VRF_CFG_AND_IO_ENABLED,
++ MD_NTSTATUS_WIN_STATUS_PARTITION_TERMINATING,
++ MD_NTSTATUS_WIN_STATUS_EXTERNAL_SYSKEY_NOT_SUPPORTED,
++ MD_NTSTATUS_WIN_STATUS_ENCLAVE_VIOLATION,
++ MD_NTSTATUS_WIN_STATUS_FILE_PROTECTED_UNDER_DPL,
++ MD_NTSTATUS_WIN_STATUS_VOLUME_NOT_CLUSTER_ALIGNED,
++ MD_NTSTATUS_WIN_STATUS_NO_PHYSICALLY_ALIGNED_FREE_SPACE_FOUND,
++ MD_NTSTATUS_WIN_STATUS_APPX_FILE_NOT_ENCRYPTED,
++ MD_NTSTATUS_WIN_STATUS_RWRAW_ENCRYPTED_FILE_NOT_ENCRYPTED,
++ MD_NTSTATUS_WIN_STATUS_RWRAW_ENCRYPTED_INVALID_EDATAINFO_FILEOFFSET,
++ MD_NTSTATUS_WIN_STATUS_RWRAW_ENCRYPTED_INVALID_EDATAINFO_FILERANGE,
++ MD_NTSTATUS_WIN_STATUS_RWRAW_ENCRYPTED_INVALID_EDATAINFO_PARAMETER,
++ MD_NTSTATUS_WIN_STATUS_FT_READ_FAILURE,
++ MD_NTSTATUS_WIN_STATUS_PATCH_CONFLICT,
++ MD_NTSTATUS_WIN_STATUS_STORAGE_RESERVE_ID_INVALID,
++ MD_NTSTATUS_WIN_STATUS_STORAGE_RESERVE_DOES_NOT_EXIST,
++ MD_NTSTATUS_WIN_STATUS_STORAGE_RESERVE_ALREADY_EXISTS,
++ MD_NTSTATUS_WIN_STATUS_STORAGE_RESERVE_NOT_EMPTY,
++ MD_NTSTATUS_WIN_STATUS_NOT_A_DAX_VOLUME,
++ MD_NTSTATUS_WIN_STATUS_NOT_DAX_MAPPABLE,
++ MD_NTSTATUS_WIN_STATUS_CASE_DIFFERING_NAMES_IN_DIR,
++ MD_NTSTATUS_WIN_STATUS_FILE_NOT_SUPPORTED,
++ MD_NTSTATUS_WIN_STATUS_NOT_SUPPORTED_WITH_BTT,
++ MD_NTSTATUS_WIN_STATUS_ENCRYPTION_DISABLED,
++ MD_NTSTATUS_WIN_STATUS_ENCRYPTING_METADATA_DISALLOWED,
++ MD_NTSTATUS_WIN_STATUS_CANT_CLEAR_ENCRYPTION_FLAG,
++ MD_NTSTATUS_WIN_STATUS_UNSATISFIED_DEPENDENCIES,
++ MD_NTSTATUS_WIN_STATUS_CASE_SENSITIVE_PATH,
++ MD_NTSTATUS_WIN_STATUS_HAS_SYSTEM_CRITICAL_FILES,
++ MD_NTSTATUS_WIN_STATUS_INVALID_TASK_NAME,
++ MD_NTSTATUS_WIN_STATUS_INVALID_TASK_INDEX,
++ MD_NTSTATUS_WIN_STATUS_THREAD_ALREADY_IN_TASK,
++ MD_NTSTATUS_WIN_STATUS_CALLBACK_BYPASS,
++ MD_NTSTATUS_WIN_STATUS_UNDEFINED_SCOPE,
++ MD_NTSTATUS_WIN_STATUS_INVALID_CAP,
++ MD_NTSTATUS_WIN_STATUS_NOT_GUI_PROCESS,
++ MD_NTSTATUS_WIN_STATUS_DEVICE_HUNG,
++ MD_NTSTATUS_WIN_STATUS_CONTAINER_ASSIGNED,
++ MD_NTSTATUS_WIN_STATUS_JOB_NO_CONTAINER,
++ MD_NTSTATUS_WIN_STATUS_DEVICE_UNRESPONSIVE,
++ MD_NTSTATUS_WIN_STATUS_REPARSE_POINT_ENCOUNTERED,
++ MD_NTSTATUS_WIN_STATUS_ATTRIBUTE_NOT_PRESENT,
++ MD_NTSTATUS_WIN_STATUS_NOT_A_TIERED_VOLUME,
++ MD_NTSTATUS_WIN_STATUS_ALREADY_HAS_STREAM_ID,
++ MD_NTSTATUS_WIN_STATUS_JOB_NOT_EMPTY,
++ MD_NTSTATUS_WIN_STATUS_ALREADY_INITIALIZED,
++ MD_NTSTATUS_WIN_STATUS_ENCLAVE_NOT_TERMINATED,
++ MD_NTSTATUS_WIN_STATUS_ENCLAVE_IS_TERMINATING,
++ MD_NTSTATUS_WIN_STATUS_SMB1_NOT_AVAILABLE,
++ MD_NTSTATUS_WIN_STATUS_SMR_GARBAGE_COLLECTION_REQUIRED,
++ MD_NTSTATUS_WIN_STATUS_INTERRUPTED,
++ MD_NTSTATUS_WIN_STATUS_THREAD_NOT_RUNNING,
++ MD_NTSTATUS_WIN_STATUS_FAIL_FAST_EXCEPTION,
++ MD_NTSTATUS_WIN_STATUS_IMAGE_CERT_REVOKED,
++ MD_NTSTATUS_WIN_STATUS_DYNAMIC_CODE_BLOCKED,
++ MD_NTSTATUS_WIN_STATUS_IMAGE_CERT_EXPIRED,
++ MD_NTSTATUS_WIN_STATUS_STRICT_CFG_VIOLATION,
++ MD_NTSTATUS_WIN_STATUS_SET_CONTEXT_DENIED,
++ MD_NTSTATUS_WIN_STATUS_CROSS_PARTITION_VIOLATION,
++ MD_NTSTATUS_WIN_STATUS_PORT_CLOSED,
++ MD_NTSTATUS_WIN_STATUS_MESSAGE_LOST,
++ MD_NTSTATUS_WIN_STATUS_INVALID_MESSAGE,
++ MD_NTSTATUS_WIN_STATUS_REQUEST_CANCELED,
++ MD_NTSTATUS_WIN_STATUS_RECURSIVE_DISPATCH,
++ MD_NTSTATUS_WIN_STATUS_LPC_RECEIVE_BUFFER_EXPECTED,
++ MD_NTSTATUS_WIN_STATUS_LPC_INVALID_CONNECTION_USAGE,
++ MD_NTSTATUS_WIN_STATUS_LPC_REQUESTS_NOT_ALLOWED,
++ MD_NTSTATUS_WIN_STATUS_RESOURCE_IN_USE,
++ MD_NTSTATUS_WIN_STATUS_HARDWARE_MEMORY_ERROR,
++ MD_NTSTATUS_WIN_STATUS_THREADPOOL_HANDLE_EXCEPTION,
++ MD_NTSTATUS_WIN_STATUS_THREADPOOL_SET_EVENT_ON_COMPLETION_FAILED,
++ MD_NTSTATUS_WIN_STATUS_THREADPOOL_RELEASE_SEMAPHORE_ON_COMPLETION_FAILED,
++ MD_NTSTATUS_WIN_STATUS_THREADPOOL_RELEASE_MUTEX_ON_COMPLETION_FAILED,
++ MD_NTSTATUS_WIN_STATUS_THREADPOOL_FREE_LIBRARY_ON_COMPLETION_FAILED,
++ MD_NTSTATUS_WIN_STATUS_THREADPOOL_RELEASED_DURING_OPERATION,
++ MD_NTSTATUS_WIN_STATUS_CALLBACK_RETURNED_WHILE_IMPERSONATING,
++ MD_NTSTATUS_WIN_STATUS_APC_RETURNED_WHILE_IMPERSONATING,
++ MD_NTSTATUS_WIN_STATUS_PROCESS_IS_PROTECTED,
++ MD_NTSTATUS_WIN_STATUS_MCA_EXCEPTION,
++ MD_NTSTATUS_WIN_STATUS_CERTIFICATE_MAPPING_NOT_UNIQUE,
++ MD_NTSTATUS_WIN_STATUS_SYMLINK_CLASS_DISABLED,
++ MD_NTSTATUS_WIN_STATUS_INVALID_IDN_NORMALIZATION,
++ MD_NTSTATUS_WIN_STATUS_NO_UNICODE_TRANSLATION,
++ MD_NTSTATUS_WIN_STATUS_ALREADY_REGISTERED,
++ MD_NTSTATUS_WIN_STATUS_CONTEXT_MISMATCH,
++ MD_NTSTATUS_WIN_STATUS_PORT_ALREADY_HAS_COMPLETION_LIST,
++ MD_NTSTATUS_WIN_STATUS_CALLBACK_RETURNED_THREAD_PRIORITY,
++ MD_NTSTATUS_WIN_STATUS_INVALID_THREAD,
++ MD_NTSTATUS_WIN_STATUS_CALLBACK_RETURNED_TRANSACTION,
++ MD_NTSTATUS_WIN_STATUS_CALLBACK_RETURNED_LDR_LOCK,
++ MD_NTSTATUS_WIN_STATUS_CALLBACK_RETURNED_LANG,
++ MD_NTSTATUS_WIN_STATUS_CALLBACK_RETURNED_PRI_BACK,
++ MD_NTSTATUS_WIN_STATUS_CALLBACK_RETURNED_THREAD_AFFINITY,
++ MD_NTSTATUS_WIN_STATUS_LPC_HANDLE_COUNT_EXCEEDED,
++ MD_NTSTATUS_WIN_STATUS_EXECUTABLE_MEMORY_WRITE,
++ MD_NTSTATUS_WIN_STATUS_KERNEL_EXECUTABLE_MEMORY_WRITE,
++ MD_NTSTATUS_WIN_STATUS_ATTACHED_EXECUTABLE_MEMORY_WRITE,
++ MD_NTSTATUS_WIN_STATUS_TRIGGERED_EXECUTABLE_MEMORY_WRITE,
++ MD_NTSTATUS_WIN_STATUS_DISK_REPAIR_DISABLED,
++ MD_NTSTATUS_WIN_STATUS_DS_DOMAIN_RENAME_IN_PROGRESS,
++ MD_NTSTATUS_WIN_STATUS_DISK_QUOTA_EXCEEDED,
++ MD_NTSTATUS_WIN_STATUS_CONTENT_BLOCKED,
++ MD_NTSTATUS_WIN_STATUS_BAD_CLUSTERS,
++ MD_NTSTATUS_WIN_STATUS_VOLUME_DIRTY,
++ MD_NTSTATUS_WIN_STATUS_DISK_REPAIR_UNSUCCESSFUL,
++ MD_NTSTATUS_WIN_STATUS_CORRUPT_LOG_OVERFULL,
++ MD_NTSTATUS_WIN_STATUS_CORRUPT_LOG_CORRUPTED,
++ MD_NTSTATUS_WIN_STATUS_CORRUPT_LOG_UNAVAILABLE,
++ MD_NTSTATUS_WIN_STATUS_CORRUPT_LOG_DELETED_FULL,
++ MD_NTSTATUS_WIN_STATUS_CORRUPT_LOG_CLEARED,
++ MD_NTSTATUS_WIN_STATUS_ORPHAN_NAME_EXHAUSTED,
++ MD_NTSTATUS_WIN_STATUS_PROACTIVE_SCAN_IN_PROGRESS,
++ MD_NTSTATUS_WIN_STATUS_ENCRYPTED_IO_NOT_POSSIBLE,
++ MD_NTSTATUS_WIN_STATUS_CORRUPT_LOG_UPLEVEL_RECORDS,
++ MD_NTSTATUS_WIN_STATUS_FILE_CHECKED_OUT,
++ MD_NTSTATUS_WIN_STATUS_CHECKOUT_REQUIRED,
++ MD_NTSTATUS_WIN_STATUS_BAD_FILE_TYPE,
++ MD_NTSTATUS_WIN_STATUS_FILE_TOO_LARGE,
++ MD_NTSTATUS_WIN_STATUS_FORMS_AUTH_REQUIRED,
++ MD_NTSTATUS_WIN_STATUS_VIRUS_INFECTED,
++ MD_NTSTATUS_WIN_STATUS_VIRUS_DELETED,
++ MD_NTSTATUS_WIN_STATUS_BAD_MCFG_TABLE,
++ MD_NTSTATUS_WIN_STATUS_CANNOT_BREAK_OPLOCK,
++ MD_NTSTATUS_WIN_STATUS_BAD_KEY,
++ MD_NTSTATUS_WIN_STATUS_BAD_DATA,
++ MD_NTSTATUS_WIN_STATUS_NO_KEY,
++ MD_NTSTATUS_WIN_STATUS_FILE_HANDLE_REVOKED,
++ MD_NTSTATUS_WIN_STATUS_WOW_ASSERTION,
++ MD_NTSTATUS_WIN_STATUS_INVALID_SIGNATURE,
++ MD_NTSTATUS_WIN_STATUS_HMAC_NOT_SUPPORTED,
++ MD_NTSTATUS_WIN_STATUS_AUTH_TAG_MISMATCH,
++ MD_NTSTATUS_WIN_STATUS_INVALID_STATE_TRANSITION,
++ MD_NTSTATUS_WIN_STATUS_INVALID_KERNEL_INFO_VERSION,
++ MD_NTSTATUS_WIN_STATUS_INVALID_PEP_INFO_VERSION,
++ MD_NTSTATUS_WIN_STATUS_HANDLE_REVOKED,
++ MD_NTSTATUS_WIN_STATUS_EOF_ON_GHOSTED_RANGE,
++ MD_NTSTATUS_WIN_STATUS_CC_NEEDS_CALLBACK_SECTION_DRAIN,
++ MD_NTSTATUS_WIN_STATUS_IPSEC_QUEUE_OVERFLOW,
++ MD_NTSTATUS_WIN_STATUS_ND_QUEUE_OVERFLOW,
++ MD_NTSTATUS_WIN_STATUS_HOPLIMIT_EXCEEDED,
++ MD_NTSTATUS_WIN_STATUS_PROTOCOL_NOT_SUPPORTED,
++ MD_NTSTATUS_WIN_STATUS_FASTPATH_REJECTED,
++ MD_NTSTATUS_WIN_STATUS_LOST_WRITEBEHIND_DATA_NETWORK_DISCONNECTED,
++ MD_NTSTATUS_WIN_STATUS_LOST_WRITEBEHIND_DATA_NETWORK_SERVER_ERROR,
++ MD_NTSTATUS_WIN_STATUS_LOST_WRITEBEHIND_DATA_LOCAL_DISK_ERROR,
++ MD_NTSTATUS_WIN_STATUS_XML_PARSE_ERROR,
++ MD_NTSTATUS_WIN_STATUS_XMLDSIG_ERROR,
++ MD_NTSTATUS_WIN_STATUS_WRONG_COMPARTMENT,
++ MD_NTSTATUS_WIN_STATUS_AUTHIP_FAILURE,
++ MD_NTSTATUS_WIN_STATUS_DS_OID_MAPPED_GROUP_CANT_HAVE_MEMBERS,
++ MD_NTSTATUS_WIN_STATUS_DS_OID_NOT_FOUND,
++ MD_NTSTATUS_WIN_STATUS_INCORRECT_ACCOUNT_TYPE,
++ MD_NTSTATUS_WIN_STATUS_HASH_NOT_SUPPORTED,
++ MD_NTSTATUS_WIN_STATUS_HASH_NOT_PRESENT,
++ MD_NTSTATUS_WIN_STATUS_SECONDARY_IC_PROVIDER_NOT_REGISTERED,
++ MD_NTSTATUS_WIN_STATUS_GPIO_CLIENT_INFORMATION_INVALID,
++ MD_NTSTATUS_WIN_STATUS_GPIO_VERSION_NOT_SUPPORTED,
++ MD_NTSTATUS_WIN_STATUS_GPIO_INVALID_REGISTRATION_PACKET,
++ MD_NTSTATUS_WIN_STATUS_GPIO_OPERATION_DENIED,
++ MD_NTSTATUS_WIN_STATUS_GPIO_INCOMPATIBLE_CONNECT_MODE,
++ MD_NTSTATUS_WIN_STATUS_CANNOT_SWITCH_RUNLEVEL,
++ MD_NTSTATUS_WIN_STATUS_INVALID_RUNLEVEL_SETTING,
++ MD_NTSTATUS_WIN_STATUS_RUNLEVEL_SWITCH_TIMEOUT,
++ MD_NTSTATUS_WIN_STATUS_RUNLEVEL_SWITCH_AGENT_TIMEOUT,
++ MD_NTSTATUS_WIN_STATUS_RUNLEVEL_SWITCH_IN_PROGRESS,
++ MD_NTSTATUS_WIN_STATUS_NOT_APPCONTAINER,
++ MD_NTSTATUS_WIN_STATUS_NOT_SUPPORTED_IN_APPCONTAINER,
++ MD_NTSTATUS_WIN_STATUS_INVALID_PACKAGE_SID_LENGTH,
++ MD_NTSTATUS_WIN_STATUS_LPAC_ACCESS_DENIED,
++ MD_NTSTATUS_WIN_STATUS_ADMINLESS_ACCESS_DENIED,
++ MD_NTSTATUS_WIN_STATUS_APP_DATA_NOT_FOUND,
++ MD_NTSTATUS_WIN_STATUS_APP_DATA_EXPIRED,
++ MD_NTSTATUS_WIN_STATUS_APP_DATA_CORRUPT,
++ MD_NTSTATUS_WIN_STATUS_APP_DATA_LIMIT_EXCEEDED,
++ MD_NTSTATUS_WIN_STATUS_APP_DATA_REBOOT_REQUIRED,
++ MD_NTSTATUS_WIN_STATUS_OFFLOAD_READ_FLT_NOT_SUPPORTED,
++ MD_NTSTATUS_WIN_STATUS_OFFLOAD_WRITE_FLT_NOT_SUPPORTED,
++ MD_NTSTATUS_WIN_STATUS_OFFLOAD_READ_FILE_NOT_SUPPORTED,
++ MD_NTSTATUS_WIN_STATUS_OFFLOAD_WRITE_FILE_NOT_SUPPORTED,
++ MD_NTSTATUS_WIN_STATUS_WOF_WIM_HEADER_CORRUPT,
++ MD_NTSTATUS_WIN_STATUS_WOF_WIM_RESOURCE_TABLE_CORRUPT,
++ MD_NTSTATUS_WIN_STATUS_WOF_FILE_RESOURCE_TABLE_CORRUPT,
++ MD_NTSTATUS_WIN_STATUS_CIMFS_IMAGE_CORRUPT,
++ MD_NTSTATUS_WIN_STATUS_FILE_SYSTEM_VIRTUALIZATION_UNAVAILABLE,
++ MD_NTSTATUS_WIN_STATUS_FILE_SYSTEM_VIRTUALIZATION_METADATA_CORRUPT,
++ MD_NTSTATUS_WIN_STATUS_FILE_SYSTEM_VIRTUALIZATION_BUSY,
++ MD_NTSTATUS_WIN_STATUS_FILE_SYSTEM_VIRTUALIZATION_PROVIDER_UNKNOWN,
++ MD_NTSTATUS_WIN_STATUS_FILE_SYSTEM_VIRTUALIZATION_INVALID_OPERATION,
++ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_SYNC_ROOT_METADATA_CORRUPT,
++ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_PROVIDER_NOT_RUNNING,
++ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_METADATA_CORRUPT,
++ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_METADATA_TOO_LARGE,
++ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_PROPERTY_VERSION_NOT_SUPPORTED,
++ MD_NTSTATUS_WIN_STATUS_NOT_A_CLOUD_FILE,
++ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_NOT_IN_SYNC,
++ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_ALREADY_CONNECTED,
++ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_NOT_SUPPORTED,
++ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_INVALID_REQUEST,
++ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_READ_ONLY_VOLUME,
++ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_CONNECTED_PROVIDER_ONLY,
++ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_VALIDATION_FAILED,
++ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_AUTHENTICATION_FAILED,
++ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_INSUFFICIENT_RESOURCES,
++ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_NETWORK_UNAVAILABLE,
++ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_UNSUCCESSFUL,
++ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_NOT_UNDER_SYNC_ROOT,
++ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_IN_USE,
++ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_PINNED,
++ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_REQUEST_ABORTED,
++ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_PROPERTY_CORRUPT,
++ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_ACCESS_DENIED,
++ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_INCOMPATIBLE_HARDLINKS,
++ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_PROPERTY_LOCK_CONFLICT,
++ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_REQUEST_CANCELED,
++ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_PROVIDER_TERMINATED,
++ MD_NTSTATUS_WIN_STATUS_NOT_A_CLOUD_SYNC_ROOT,
++ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_REQUEST_TIMEOUT,
++ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_DEHYDRATION_DISALLOWED,
++ MD_NTSTATUS_WIN_STATUS_FILE_SNAP_IN_PROGRESS,
++ MD_NTSTATUS_WIN_STATUS_FILE_SNAP_USER_SECTION_NOT_SUPPORTED,
++ MD_NTSTATUS_WIN_STATUS_FILE_SNAP_MODIFY_NOT_SUPPORTED,
++ MD_NTSTATUS_WIN_STATUS_FILE_SNAP_IO_NOT_COORDINATED,
++ MD_NTSTATUS_WIN_STATUS_FILE_SNAP_UNEXPECTED_ERROR,
++ MD_NTSTATUS_WIN_STATUS_FILE_SNAP_INVALID_PARAMETER,
++ MD_NTSTATUS_WIN_DBG_NO_STATE_CHANGE,
++ MD_NTSTATUS_WIN_DBG_APP_NOT_IDLE,
++ MD_NTSTATUS_WIN_RPC_NT_INVALID_STRING_BINDING,
++ MD_NTSTATUS_WIN_RPC_NT_WRONG_KIND_OF_BINDING,
++ MD_NTSTATUS_WIN_RPC_NT_INVALID_BINDING,
++ MD_NTSTATUS_WIN_RPC_NT_PROTSEQ_NOT_SUPPORTED,
++ MD_NTSTATUS_WIN_RPC_NT_INVALID_RPC_PROTSEQ,
++ MD_NTSTATUS_WIN_RPC_NT_INVALID_STRING_UUID,
++ MD_NTSTATUS_WIN_RPC_NT_INVALID_ENDPOINT_FORMAT,
++ MD_NTSTATUS_WIN_RPC_NT_INVALID_NET_ADDR,
++ MD_NTSTATUS_WIN_RPC_NT_NO_ENDPOINT_FOUND,
++ MD_NTSTATUS_WIN_RPC_NT_INVALID_TIMEOUT,
++ MD_NTSTATUS_WIN_RPC_NT_OBJECT_NOT_FOUND,
++ MD_NTSTATUS_WIN_RPC_NT_ALREADY_REGISTERED,
++ MD_NTSTATUS_WIN_RPC_NT_TYPE_ALREADY_REGISTERED,
++ MD_NTSTATUS_WIN_RPC_NT_ALREADY_LISTENING,
++ MD_NTSTATUS_WIN_RPC_NT_NO_PROTSEQS_REGISTERED,
++ MD_NTSTATUS_WIN_RPC_NT_NOT_LISTENING,
++ MD_NTSTATUS_WIN_RPC_NT_UNKNOWN_MGR_TYPE,
++ MD_NTSTATUS_WIN_RPC_NT_UNKNOWN_IF,
++ MD_NTSTATUS_WIN_RPC_NT_NO_BINDINGS,
++ MD_NTSTATUS_WIN_RPC_NT_NO_PROTSEQS,
++ MD_NTSTATUS_WIN_RPC_NT_CANT_CREATE_ENDPOINT,
++ MD_NTSTATUS_WIN_RPC_NT_OUT_OF_RESOURCES,
++ MD_NTSTATUS_WIN_RPC_NT_SERVER_UNAVAILABLE,
++ MD_NTSTATUS_WIN_RPC_NT_SERVER_TOO_BUSY,
++ MD_NTSTATUS_WIN_RPC_NT_INVALID_NETWORK_OPTIONS,
++ MD_NTSTATUS_WIN_RPC_NT_NO_CALL_ACTIVE,
++ MD_NTSTATUS_WIN_RPC_NT_CALL_FAILED,
++ MD_NTSTATUS_WIN_RPC_NT_CALL_FAILED_DNE,
++ MD_NTSTATUS_WIN_RPC_NT_PROTOCOL_ERROR,
++ MD_NTSTATUS_WIN_RPC_NT_UNSUPPORTED_TRANS_SYN,
++ MD_NTSTATUS_WIN_RPC_NT_UNSUPPORTED_TYPE,
++ MD_NTSTATUS_WIN_RPC_NT_INVALID_TAG,
++ MD_NTSTATUS_WIN_RPC_NT_INVALID_BOUND,
++ MD_NTSTATUS_WIN_RPC_NT_NO_ENTRY_NAME,
++ MD_NTSTATUS_WIN_RPC_NT_INVALID_NAME_SYNTAX,
++ MD_NTSTATUS_WIN_RPC_NT_UNSUPPORTED_NAME_SYNTAX,
++ MD_NTSTATUS_WIN_RPC_NT_UUID_NO_ADDRESS,
++ MD_NTSTATUS_WIN_RPC_NT_DUPLICATE_ENDPOINT,
++ MD_NTSTATUS_WIN_RPC_NT_UNKNOWN_AUTHN_TYPE,
++ MD_NTSTATUS_WIN_RPC_NT_MAX_CALLS_TOO_SMALL,
++ MD_NTSTATUS_WIN_RPC_NT_STRING_TOO_LONG,
++ MD_NTSTATUS_WIN_RPC_NT_PROTSEQ_NOT_FOUND,
++ MD_NTSTATUS_WIN_RPC_NT_PROCNUM_OUT_OF_RANGE,
++ MD_NTSTATUS_WIN_RPC_NT_BINDING_HAS_NO_AUTH,
++ MD_NTSTATUS_WIN_RPC_NT_UNKNOWN_AUTHN_SERVICE,
++ MD_NTSTATUS_WIN_RPC_NT_UNKNOWN_AUTHN_LEVEL,
++ MD_NTSTATUS_WIN_RPC_NT_INVALID_AUTH_IDENTITY,
++ MD_NTSTATUS_WIN_RPC_NT_UNKNOWN_AUTHZ_SERVICE,
++ MD_NTSTATUS_WIN_EPT_NT_INVALID_ENTRY,
++ MD_NTSTATUS_WIN_EPT_NT_CANT_PERFORM_OP,
++ MD_NTSTATUS_WIN_EPT_NT_NOT_REGISTERED,
++ MD_NTSTATUS_WIN_RPC_NT_NOTHING_TO_EXPORT,
++ MD_NTSTATUS_WIN_RPC_NT_INCOMPLETE_NAME,
++ MD_NTSTATUS_WIN_RPC_NT_INVALID_VERS_OPTION,
++ MD_NTSTATUS_WIN_RPC_NT_NO_MORE_MEMBERS,
++ MD_NTSTATUS_WIN_RPC_NT_NOT_ALL_OBJS_UNEXPORTED,
++ MD_NTSTATUS_WIN_RPC_NT_INTERFACE_NOT_FOUND,
++ MD_NTSTATUS_WIN_RPC_NT_ENTRY_ALREADY_EXISTS,
++ MD_NTSTATUS_WIN_RPC_NT_ENTRY_NOT_FOUND,
++ MD_NTSTATUS_WIN_RPC_NT_NAME_SERVICE_UNAVAILABLE,
++ MD_NTSTATUS_WIN_RPC_NT_INVALID_NAF_ID,
++ MD_NTSTATUS_WIN_RPC_NT_CANNOT_SUPPORT,
++ MD_NTSTATUS_WIN_RPC_NT_NO_CONTEXT_AVAILABLE,
++ MD_NTSTATUS_WIN_RPC_NT_INTERNAL_ERROR,
++ MD_NTSTATUS_WIN_RPC_NT_ZERO_DIVIDE,
++ MD_NTSTATUS_WIN_RPC_NT_ADDRESS_ERROR,
++ MD_NTSTATUS_WIN_RPC_NT_FP_DIV_ZERO,
++ MD_NTSTATUS_WIN_RPC_NT_FP_UNDERFLOW,
++ MD_NTSTATUS_WIN_RPC_NT_FP_OVERFLOW,
++ MD_NTSTATUS_WIN_RPC_NT_CALL_IN_PROGRESS,
++ MD_NTSTATUS_WIN_RPC_NT_NO_MORE_BINDINGS,
++ MD_NTSTATUS_WIN_RPC_NT_GROUP_MEMBER_NOT_FOUND,
++ MD_NTSTATUS_WIN_EPT_NT_CANT_CREATE,
++ MD_NTSTATUS_WIN_RPC_NT_INVALID_OBJECT,
++ MD_NTSTATUS_WIN_RPC_NT_NO_INTERFACES,
++ MD_NTSTATUS_WIN_RPC_NT_CALL_CANCELLED,
++ MD_NTSTATUS_WIN_RPC_NT_BINDING_INCOMPLETE,
++ MD_NTSTATUS_WIN_RPC_NT_COMM_FAILURE,
++ MD_NTSTATUS_WIN_RPC_NT_UNSUPPORTED_AUTHN_LEVEL,
++ MD_NTSTATUS_WIN_RPC_NT_NO_PRINC_NAME,
++ MD_NTSTATUS_WIN_RPC_NT_NOT_RPC_ERROR,
++ MD_NTSTATUS_WIN_RPC_NT_SEC_PKG_ERROR,
++ MD_NTSTATUS_WIN_RPC_NT_NOT_CANCELLED,
++ MD_NTSTATUS_WIN_RPC_NT_INVALID_ASYNC_HANDLE,
++ MD_NTSTATUS_WIN_RPC_NT_INVALID_ASYNC_CALL,
++ MD_NTSTATUS_WIN_RPC_NT_PROXY_ACCESS_DENIED,
++ MD_NTSTATUS_WIN_RPC_NT_COOKIE_AUTH_FAILED,
++ MD_NTSTATUS_WIN_RPC_NT_NO_MORE_ENTRIES,
++ MD_NTSTATUS_WIN_RPC_NT_SS_CHAR_TRANS_OPEN_FAIL,
++ MD_NTSTATUS_WIN_RPC_NT_SS_CHAR_TRANS_SHORT_FILE,
++ MD_NTSTATUS_WIN_RPC_NT_SS_IN_NULL_CONTEXT,
++ MD_NTSTATUS_WIN_RPC_NT_SS_CONTEXT_MISMATCH,
++ MD_NTSTATUS_WIN_RPC_NT_SS_CONTEXT_DAMAGED,
++ MD_NTSTATUS_WIN_RPC_NT_SS_HANDLES_MISMATCH,
++ MD_NTSTATUS_WIN_RPC_NT_SS_CANNOT_GET_CALL_HANDLE,
++ MD_NTSTATUS_WIN_RPC_NT_NULL_REF_POINTER,
++ MD_NTSTATUS_WIN_RPC_NT_ENUM_VALUE_OUT_OF_RANGE,
++ MD_NTSTATUS_WIN_RPC_NT_BYTE_COUNT_TOO_SMALL,
++ MD_NTSTATUS_WIN_RPC_NT_BAD_STUB_DATA,
++ MD_NTSTATUS_WIN_RPC_NT_INVALID_ES_ACTION,
++ MD_NTSTATUS_WIN_RPC_NT_WRONG_ES_VERSION,
++ MD_NTSTATUS_WIN_RPC_NT_WRONG_STUB_VERSION,
++ MD_NTSTATUS_WIN_RPC_NT_INVALID_PIPE_OBJECT,
++ MD_NTSTATUS_WIN_RPC_NT_INVALID_PIPE_OPERATION,
++ MD_NTSTATUS_WIN_RPC_NT_WRONG_PIPE_VERSION,
++ MD_NTSTATUS_WIN_RPC_NT_PIPE_CLOSED,
++ MD_NTSTATUS_WIN_RPC_NT_PIPE_DISCIPLINE_ERROR,
++ MD_NTSTATUS_WIN_RPC_NT_PIPE_EMPTY,
++ MD_NTSTATUS_WIN_STATUS_PNP_BAD_MPS_TABLE,
++ MD_NTSTATUS_WIN_STATUS_PNP_TRANSLATION_FAILED,
++ MD_NTSTATUS_WIN_STATUS_PNP_IRQ_TRANSLATION_FAILED,
++ MD_NTSTATUS_WIN_STATUS_PNP_INVALID_ID,
++ MD_NTSTATUS_WIN_STATUS_IO_REISSUE_AS_CACHED,
++ MD_NTSTATUS_WIN_STATUS_CTX_WINSTATION_NAME_INVALID,
++ MD_NTSTATUS_WIN_STATUS_CTX_INVALID_PD,
++ MD_NTSTATUS_WIN_STATUS_CTX_PD_NOT_FOUND,
++ MD_NTSTATUS_WIN_STATUS_CTX_CLOSE_PENDING,
++ MD_NTSTATUS_WIN_STATUS_CTX_NO_OUTBUF,
++ MD_NTSTATUS_WIN_STATUS_CTX_MODEM_INF_NOT_FOUND,
++ MD_NTSTATUS_WIN_STATUS_CTX_INVALID_MODEMNAME,
++ MD_NTSTATUS_WIN_STATUS_CTX_RESPONSE_ERROR,
++ MD_NTSTATUS_WIN_STATUS_CTX_MODEM_RESPONSE_TIMEOUT,
++ MD_NTSTATUS_WIN_STATUS_CTX_MODEM_RESPONSE_NO_CARRIER,
++ MD_NTSTATUS_WIN_STATUS_CTX_MODEM_RESPONSE_NO_DIALTONE,
++ MD_NTSTATUS_WIN_STATUS_CTX_MODEM_RESPONSE_BUSY,
++ MD_NTSTATUS_WIN_STATUS_CTX_MODEM_RESPONSE_VOICE,
++ MD_NTSTATUS_WIN_STATUS_CTX_TD_ERROR,
++ MD_NTSTATUS_WIN_STATUS_CTX_LICENSE_CLIENT_INVALID,
++ MD_NTSTATUS_WIN_STATUS_CTX_LICENSE_NOT_AVAILABLE,
++ MD_NTSTATUS_WIN_STATUS_CTX_LICENSE_EXPIRED,
++ MD_NTSTATUS_WIN_STATUS_CTX_WINSTATION_NOT_FOUND,
++ MD_NTSTATUS_WIN_STATUS_CTX_WINSTATION_NAME_COLLISION,
++ MD_NTSTATUS_WIN_STATUS_CTX_WINSTATION_BUSY,
++ MD_NTSTATUS_WIN_STATUS_CTX_BAD_VIDEO_MODE,
++ MD_NTSTATUS_WIN_STATUS_CTX_GRAPHICS_INVALID,
++ MD_NTSTATUS_WIN_STATUS_CTX_NOT_CONSOLE,
++ MD_NTSTATUS_WIN_STATUS_CTX_CLIENT_QUERY_TIMEOUT,
++ MD_NTSTATUS_WIN_STATUS_CTX_CONSOLE_DISCONNECT,
++ MD_NTSTATUS_WIN_STATUS_CTX_CONSOLE_CONNECT,
++ MD_NTSTATUS_WIN_STATUS_CTX_SHADOW_DENIED,
++ MD_NTSTATUS_WIN_STATUS_CTX_WINSTATION_ACCESS_DENIED,
++ MD_NTSTATUS_WIN_STATUS_CTX_INVALID_WD,
++ MD_NTSTATUS_WIN_STATUS_CTX_WD_NOT_FOUND,
++ MD_NTSTATUS_WIN_STATUS_CTX_SHADOW_INVALID,
++ MD_NTSTATUS_WIN_STATUS_CTX_SHADOW_DISABLED,
++ MD_NTSTATUS_WIN_STATUS_RDP_PROTOCOL_ERROR,
++ MD_NTSTATUS_WIN_STATUS_CTX_CLIENT_LICENSE_NOT_SET,
++ MD_NTSTATUS_WIN_STATUS_CTX_CLIENT_LICENSE_IN_USE,
++ MD_NTSTATUS_WIN_STATUS_CTX_SHADOW_ENDED_BY_MODE_CHANGE,
++ MD_NTSTATUS_WIN_STATUS_CTX_SHADOW_NOT_RUNNING,
++ MD_NTSTATUS_WIN_STATUS_CTX_LOGON_DISABLED,
++ MD_NTSTATUS_WIN_STATUS_CTX_SECURITY_LAYER_ERROR,
++ MD_NTSTATUS_WIN_STATUS_TS_INCOMPATIBLE_SESSIONS,
++ MD_NTSTATUS_WIN_STATUS_TS_VIDEO_SUBSYSTEM_ERROR,
++ MD_NTSTATUS_WIN_STATUS_MUI_FILE_NOT_FOUND,
++ MD_NTSTATUS_WIN_STATUS_MUI_INVALID_FILE,
++ MD_NTSTATUS_WIN_STATUS_MUI_INVALID_RC_CONFIG,
++ MD_NTSTATUS_WIN_STATUS_MUI_INVALID_LOCALE_NAME,
++ MD_NTSTATUS_WIN_STATUS_MUI_INVALID_ULTIMATEFALLBACK_NAME,
++ MD_NTSTATUS_WIN_STATUS_MUI_FILE_NOT_LOADED,
++ MD_NTSTATUS_WIN_STATUS_RESOURCE_ENUM_USER_STOP,
++ MD_NTSTATUS_WIN_STATUS_CLUSTER_INVALID_NODE,
++ MD_NTSTATUS_WIN_STATUS_CLUSTER_NODE_EXISTS,
++ MD_NTSTATUS_WIN_STATUS_CLUSTER_JOIN_IN_PROGRESS,
++ MD_NTSTATUS_WIN_STATUS_CLUSTER_NODE_NOT_FOUND,
++ MD_NTSTATUS_WIN_STATUS_CLUSTER_LOCAL_NODE_NOT_FOUND,
++ MD_NTSTATUS_WIN_STATUS_CLUSTER_NETWORK_EXISTS,
++ MD_NTSTATUS_WIN_STATUS_CLUSTER_NETWORK_NOT_FOUND,
++ MD_NTSTATUS_WIN_STATUS_CLUSTER_NETINTERFACE_EXISTS,
++ MD_NTSTATUS_WIN_STATUS_CLUSTER_NETINTERFACE_NOT_FOUND,
++ MD_NTSTATUS_WIN_STATUS_CLUSTER_INVALID_REQUEST,
++ MD_NTSTATUS_WIN_STATUS_CLUSTER_INVALID_NETWORK_PROVIDER,
++ MD_NTSTATUS_WIN_STATUS_CLUSTER_NODE_DOWN,
++ MD_NTSTATUS_WIN_STATUS_CLUSTER_NODE_UNREACHABLE,
++ MD_NTSTATUS_WIN_STATUS_CLUSTER_NODE_NOT_MEMBER,
++ MD_NTSTATUS_WIN_STATUS_CLUSTER_JOIN_NOT_IN_PROGRESS,
++ MD_NTSTATUS_WIN_STATUS_CLUSTER_INVALID_NETWORK,
++ MD_NTSTATUS_WIN_STATUS_CLUSTER_NO_NET_ADAPTERS,
++ MD_NTSTATUS_WIN_STATUS_CLUSTER_NODE_UP,
++ MD_NTSTATUS_WIN_STATUS_CLUSTER_NODE_PAUSED,
++ MD_NTSTATUS_WIN_STATUS_CLUSTER_NODE_NOT_PAUSED,
++ MD_NTSTATUS_WIN_STATUS_CLUSTER_NO_SECURITY_CONTEXT,
++ MD_NTSTATUS_WIN_STATUS_CLUSTER_NETWORK_NOT_INTERNAL,
++ MD_NTSTATUS_WIN_STATUS_CLUSTER_POISONED,
++ MD_NTSTATUS_WIN_STATUS_CLUSTER_NON_CSV_PATH,
++ MD_NTSTATUS_WIN_STATUS_CLUSTER_CSV_VOLUME_NOT_LOCAL,
++ MD_NTSTATUS_WIN_STATUS_CLUSTER_CSV_READ_OPLOCK_BREAK_IN_PROGRESS,
++ MD_NTSTATUS_WIN_STATUS_CLUSTER_CSV_AUTO_PAUSE_ERROR,
++ MD_NTSTATUS_WIN_STATUS_CLUSTER_CSV_REDIRECTED,
++ MD_NTSTATUS_WIN_STATUS_CLUSTER_CSV_NOT_REDIRECTED,
++ MD_NTSTATUS_WIN_STATUS_CLUSTER_CSV_VOLUME_DRAINING,
++ MD_NTSTATUS_WIN_STATUS_CLUSTER_CSV_SNAPSHOT_CREATION_IN_PROGRESS,
++ MD_NTSTATUS_WIN_STATUS_CLUSTER_CSV_VOLUME_DRAINING_SUCCEEDED_DOWNLEVEL,
++ MD_NTSTATUS_WIN_STATUS_CLUSTER_CSV_NO_SNAPSHOTS,
++ MD_NTSTATUS_WIN_STATUS_CSV_IO_PAUSE_TIMEOUT,
++ MD_NTSTATUS_WIN_STATUS_CLUSTER_CSV_INVALID_HANDLE,
++ MD_NTSTATUS_WIN_STATUS_CLUSTER_CSV_SUPPORTED_ONLY_ON_COORDINATOR,
++ MD_NTSTATUS_WIN_STATUS_CLUSTER_CAM_TICKET_REPLAY_DETECTED,
++ MD_NTSTATUS_WIN_STATUS_ACPI_INVALID_OPCODE,
++ MD_NTSTATUS_WIN_STATUS_ACPI_STACK_OVERFLOW,
++ MD_NTSTATUS_WIN_STATUS_ACPI_ASSERT_FAILED,
++ MD_NTSTATUS_WIN_STATUS_ACPI_INVALID_INDEX,
++ MD_NTSTATUS_WIN_STATUS_ACPI_INVALID_ARGUMENT,
++ MD_NTSTATUS_WIN_STATUS_ACPI_FATAL,
++ MD_NTSTATUS_WIN_STATUS_ACPI_INVALID_SUPERNAME,
++ MD_NTSTATUS_WIN_STATUS_ACPI_INVALID_ARGTYPE,
++ MD_NTSTATUS_WIN_STATUS_ACPI_INVALID_OBJTYPE,
++ MD_NTSTATUS_WIN_STATUS_ACPI_INVALID_TARGETTYPE,
++ MD_NTSTATUS_WIN_STATUS_ACPI_INCORRECT_ARGUMENT_COUNT,
++ MD_NTSTATUS_WIN_STATUS_ACPI_ADDRESS_NOT_MAPPED,
++ MD_NTSTATUS_WIN_STATUS_ACPI_INVALID_EVENTTYPE,
++ MD_NTSTATUS_WIN_STATUS_ACPI_HANDLER_COLLISION,
++ MD_NTSTATUS_WIN_STATUS_ACPI_INVALID_DATA,
++ MD_NTSTATUS_WIN_STATUS_ACPI_INVALID_REGION,
++ MD_NTSTATUS_WIN_STATUS_ACPI_INVALID_ACCESS_SIZE,
++ MD_NTSTATUS_WIN_STATUS_ACPI_ACQUIRE_GLOBAL_LOCK,
++ MD_NTSTATUS_WIN_STATUS_ACPI_ALREADY_INITIALIZED,
++ MD_NTSTATUS_WIN_STATUS_ACPI_NOT_INITIALIZED,
++ MD_NTSTATUS_WIN_STATUS_ACPI_INVALID_MUTEX_LEVEL,
++ MD_NTSTATUS_WIN_STATUS_ACPI_MUTEX_NOT_OWNED,
++ MD_NTSTATUS_WIN_STATUS_ACPI_MUTEX_NOT_OWNER,
++ MD_NTSTATUS_WIN_STATUS_ACPI_RS_ACCESS,
++ MD_NTSTATUS_WIN_STATUS_ACPI_INVALID_TABLE,
++ MD_NTSTATUS_WIN_STATUS_ACPI_REG_HANDLER_FAILED,
++ MD_NTSTATUS_WIN_STATUS_ACPI_POWER_REQUEST_FAILED,
++ MD_NTSTATUS_WIN_STATUS_SXS_SECTION_NOT_FOUND,
++ MD_NTSTATUS_WIN_STATUS_SXS_CANT_GEN_ACTCTX,
++ MD_NTSTATUS_WIN_STATUS_SXS_INVALID_ACTCTXDATA_FORMAT,
++ MD_NTSTATUS_WIN_STATUS_SXS_ASSEMBLY_NOT_FOUND,
++ MD_NTSTATUS_WIN_STATUS_SXS_MANIFEST_FORMAT_ERROR,
++ MD_NTSTATUS_WIN_STATUS_SXS_MANIFEST_PARSE_ERROR,
++ MD_NTSTATUS_WIN_STATUS_SXS_ACTIVATION_CONTEXT_DISABLED,
++ MD_NTSTATUS_WIN_STATUS_SXS_KEY_NOT_FOUND,
++ MD_NTSTATUS_WIN_STATUS_SXS_VERSION_CONFLICT,
++ MD_NTSTATUS_WIN_STATUS_SXS_WRONG_SECTION_TYPE,
++ MD_NTSTATUS_WIN_STATUS_SXS_THREAD_QUERIES_DISABLED,
++ MD_NTSTATUS_WIN_STATUS_SXS_ASSEMBLY_MISSING,
++ MD_NTSTATUS_WIN_STATUS_SXS_PROCESS_DEFAULT_ALREADY_SET,
++ MD_NTSTATUS_WIN_STATUS_SXS_EARLY_DEACTIVATION,
++ MD_NTSTATUS_WIN_STATUS_SXS_INVALID_DEACTIVATION,
++ MD_NTSTATUS_WIN_STATUS_SXS_MULTIPLE_DEACTIVATION,
++ MD_NTSTATUS_WIN_STATUS_SXS_SYSTEM_DEFAULT_ACTIVATION_CONTEXT_EMPTY,
++ MD_NTSTATUS_WIN_STATUS_SXS_PROCESS_TERMINATION_REQUESTED,
++ MD_NTSTATUS_WIN_STATUS_SXS_CORRUPT_ACTIVATION_STACK,
++ MD_NTSTATUS_WIN_STATUS_SXS_CORRUPTION,
++ MD_NTSTATUS_WIN_STATUS_SXS_INVALID_IDENTITY_ATTRIBUTE_VALUE,
++ MD_NTSTATUS_WIN_STATUS_SXS_INVALID_IDENTITY_ATTRIBUTE_NAME,
++ MD_NTSTATUS_WIN_STATUS_SXS_IDENTITY_DUPLICATE_ATTRIBUTE,
++ MD_NTSTATUS_WIN_STATUS_SXS_IDENTITY_PARSE_ERROR,
++ MD_NTSTATUS_WIN_STATUS_SXS_COMPONENT_STORE_CORRUPT,
++ MD_NTSTATUS_WIN_STATUS_SXS_FILE_HASH_MISMATCH,
++ MD_NTSTATUS_WIN_STATUS_SXS_MANIFEST_IDENTITY_SAME_BUT_CONTENTS_DIFFERENT,
++ MD_NTSTATUS_WIN_STATUS_SXS_IDENTITIES_DIFFERENT,
++ MD_NTSTATUS_WIN_STATUS_SXS_ASSEMBLY_IS_NOT_A_DEPLOYMENT,
++ MD_NTSTATUS_WIN_STATUS_SXS_FILE_NOT_PART_OF_ASSEMBLY,
++ MD_NTSTATUS_WIN_STATUS_ADVANCED_INSTALLER_FAILED,
++ MD_NTSTATUS_WIN_STATUS_XML_ENCODING_MISMATCH,
++ MD_NTSTATUS_WIN_STATUS_SXS_MANIFEST_TOO_BIG,
++ MD_NTSTATUS_WIN_STATUS_SXS_SETTING_NOT_REGISTERED,
++ MD_NTSTATUS_WIN_STATUS_SXS_TRANSACTION_CLOSURE_INCOMPLETE,
++ MD_NTSTATUS_WIN_STATUS_SMI_PRIMITIVE_INSTALLER_FAILED,
++ MD_NTSTATUS_WIN_STATUS_GENERIC_COMMAND_FAILED,
++ MD_NTSTATUS_WIN_STATUS_SXS_FILE_HASH_MISSING,
++ MD_NTSTATUS_WIN_STATUS_TRANSACTIONAL_CONFLICT,
++ MD_NTSTATUS_WIN_STATUS_INVALID_TRANSACTION,
++ MD_NTSTATUS_WIN_STATUS_TRANSACTION_NOT_ACTIVE,
++ MD_NTSTATUS_WIN_STATUS_TM_INITIALIZATION_FAILED,
++ MD_NTSTATUS_WIN_STATUS_RM_NOT_ACTIVE,
++ MD_NTSTATUS_WIN_STATUS_RM_METADATA_CORRUPT,
++ MD_NTSTATUS_WIN_STATUS_TRANSACTION_NOT_JOINED,
++ MD_NTSTATUS_WIN_STATUS_DIRECTORY_NOT_RM,
++ MD_NTSTATUS_WIN_STATUS_TRANSACTIONS_UNSUPPORTED_REMOTE,
++ MD_NTSTATUS_WIN_STATUS_LOG_RESIZE_INVALID_SIZE,
++ MD_NTSTATUS_WIN_STATUS_REMOTE_FILE_VERSION_MISMATCH,
++ MD_NTSTATUS_WIN_STATUS_CRM_PROTOCOL_ALREADY_EXISTS,
++ MD_NTSTATUS_WIN_STATUS_TRANSACTION_PROPAGATION_FAILED,
++ MD_NTSTATUS_WIN_STATUS_CRM_PROTOCOL_NOT_FOUND,
++ MD_NTSTATUS_WIN_STATUS_TRANSACTION_SUPERIOR_EXISTS,
++ MD_NTSTATUS_WIN_STATUS_TRANSACTION_REQUEST_NOT_VALID,
++ MD_NTSTATUS_WIN_STATUS_TRANSACTION_NOT_REQUESTED,
++ MD_NTSTATUS_WIN_STATUS_TRANSACTION_ALREADY_ABORTED,
++ MD_NTSTATUS_WIN_STATUS_TRANSACTION_ALREADY_COMMITTED,
++ MD_NTSTATUS_WIN_STATUS_TRANSACTION_INVALID_MARSHALL_BUFFER,
++ MD_NTSTATUS_WIN_STATUS_CURRENT_TRANSACTION_NOT_VALID,
++ MD_NTSTATUS_WIN_STATUS_LOG_GROWTH_FAILED,
++ MD_NTSTATUS_WIN_STATUS_OBJECT_NO_LONGER_EXISTS,
++ MD_NTSTATUS_WIN_STATUS_STREAM_MINIVERSION_NOT_FOUND,
++ MD_NTSTATUS_WIN_STATUS_STREAM_MINIVERSION_NOT_VALID,
++ MD_NTSTATUS_WIN_STATUS_MINIVERSION_INACCESSIBLE_FROM_SPECIFIED_TRANSACTION,
++ MD_NTSTATUS_WIN_STATUS_CANT_OPEN_MINIVERSION_WITH_MODIFY_INTENT,
++ MD_NTSTATUS_WIN_STATUS_CANT_CREATE_MORE_STREAM_MINIVERSIONS,
++ MD_NTSTATUS_WIN_STATUS_HANDLE_NO_LONGER_VALID,
++ MD_NTSTATUS_WIN_STATUS_LOG_CORRUPTION_DETECTED,
++ MD_NTSTATUS_WIN_STATUS_RM_DISCONNECTED,
++ MD_NTSTATUS_WIN_STATUS_ENLISTMENT_NOT_SUPERIOR,
++ MD_NTSTATUS_WIN_STATUS_FILE_IDENTITY_NOT_PERSISTENT,
++ MD_NTSTATUS_WIN_STATUS_CANT_BREAK_TRANSACTIONAL_DEPENDENCY,
++ MD_NTSTATUS_WIN_STATUS_CANT_CROSS_RM_BOUNDARY,
++ MD_NTSTATUS_WIN_STATUS_TXF_DIR_NOT_EMPTY,
++ MD_NTSTATUS_WIN_STATUS_INDOUBT_TRANSACTIONS_EXIST,
++ MD_NTSTATUS_WIN_STATUS_TM_VOLATILE,
++ MD_NTSTATUS_WIN_STATUS_ROLLBACK_TIMER_EXPIRED,
++ MD_NTSTATUS_WIN_STATUS_TXF_ATTRIBUTE_CORRUPT,
++ MD_NTSTATUS_WIN_STATUS_EFS_NOT_ALLOWED_IN_TRANSACTION,
++ MD_NTSTATUS_WIN_STATUS_TRANSACTIONAL_OPEN_NOT_ALLOWED,
++ MD_NTSTATUS_WIN_STATUS_TRANSACTED_MAPPING_UNSUPPORTED_REMOTE,
++ MD_NTSTATUS_WIN_STATUS_TRANSACTION_REQUIRED_PROMOTION,
++ MD_NTSTATUS_WIN_STATUS_CANNOT_EXECUTE_FILE_IN_TRANSACTION,
++ MD_NTSTATUS_WIN_STATUS_TRANSACTIONS_NOT_FROZEN,
++ MD_NTSTATUS_WIN_STATUS_TRANSACTION_FREEZE_IN_PROGRESS,
++ MD_NTSTATUS_WIN_STATUS_NOT_SNAPSHOT_VOLUME,
++ MD_NTSTATUS_WIN_STATUS_NO_SAVEPOINT_WITH_OPEN_FILES,
++ MD_NTSTATUS_WIN_STATUS_SPARSE_NOT_ALLOWED_IN_TRANSACTION,
++ MD_NTSTATUS_WIN_STATUS_TM_IDENTITY_MISMATCH,
++ MD_NTSTATUS_WIN_STATUS_FLOATED_SECTION,
++ MD_NTSTATUS_WIN_STATUS_CANNOT_ACCEPT_TRANSACTED_WORK,
++ MD_NTSTATUS_WIN_STATUS_CANNOT_ABORT_TRANSACTIONS,
++ MD_NTSTATUS_WIN_STATUS_TRANSACTION_NOT_FOUND,
++ MD_NTSTATUS_WIN_STATUS_RESOURCEMANAGER_NOT_FOUND,
++ MD_NTSTATUS_WIN_STATUS_ENLISTMENT_NOT_FOUND,
++ MD_NTSTATUS_WIN_STATUS_TRANSACTIONMANAGER_NOT_FOUND,
++ MD_NTSTATUS_WIN_STATUS_TRANSACTIONMANAGER_NOT_ONLINE,
++ MD_NTSTATUS_WIN_STATUS_TRANSACTIONMANAGER_RECOVERY_NAME_COLLISION,
++ MD_NTSTATUS_WIN_STATUS_TRANSACTION_NOT_ROOT,
++ MD_NTSTATUS_WIN_STATUS_TRANSACTION_OBJECT_EXPIRED,
++ MD_NTSTATUS_WIN_STATUS_COMPRESSION_NOT_ALLOWED_IN_TRANSACTION,
++ MD_NTSTATUS_WIN_STATUS_TRANSACTION_RESPONSE_NOT_ENLISTED,
++ MD_NTSTATUS_WIN_STATUS_TRANSACTION_RECORD_TOO_LONG,
++ MD_NTSTATUS_WIN_STATUS_NO_LINK_TRACKING_IN_TRANSACTION,
++ MD_NTSTATUS_WIN_STATUS_OPERATION_NOT_SUPPORTED_IN_TRANSACTION,
++ MD_NTSTATUS_WIN_STATUS_TRANSACTION_INTEGRITY_VIOLATED,
++ MD_NTSTATUS_WIN_STATUS_TRANSACTIONMANAGER_IDENTITY_MISMATCH,
++ MD_NTSTATUS_WIN_STATUS_RM_CANNOT_BE_FROZEN_FOR_SNAPSHOT,
++ MD_NTSTATUS_WIN_STATUS_TRANSACTION_MUST_WRITETHROUGH,
++ MD_NTSTATUS_WIN_STATUS_TRANSACTION_NO_SUPERIOR,
++ MD_NTSTATUS_WIN_STATUS_EXPIRED_HANDLE,
++ MD_NTSTATUS_WIN_STATUS_TRANSACTION_NOT_ENLISTED,
++ MD_NTSTATUS_WIN_STATUS_LOG_SECTOR_INVALID,
++ MD_NTSTATUS_WIN_STATUS_LOG_SECTOR_PARITY_INVALID,
++ MD_NTSTATUS_WIN_STATUS_LOG_SECTOR_REMAPPED,
++ MD_NTSTATUS_WIN_STATUS_LOG_BLOCK_INCOMPLETE,
++ MD_NTSTATUS_WIN_STATUS_LOG_INVALID_RANGE,
++ MD_NTSTATUS_WIN_STATUS_LOG_BLOCKS_EXHAUSTED,
++ MD_NTSTATUS_WIN_STATUS_LOG_READ_CONTEXT_INVALID,
++ MD_NTSTATUS_WIN_STATUS_LOG_RESTART_INVALID,
++ MD_NTSTATUS_WIN_STATUS_LOG_BLOCK_VERSION,
++ MD_NTSTATUS_WIN_STATUS_LOG_BLOCK_INVALID,
++ MD_NTSTATUS_WIN_STATUS_LOG_READ_MODE_INVALID,
++ MD_NTSTATUS_WIN_STATUS_LOG_METADATA_CORRUPT,
++ MD_NTSTATUS_WIN_STATUS_LOG_METADATA_INVALID,
++ MD_NTSTATUS_WIN_STATUS_LOG_METADATA_INCONSISTENT,
++ MD_NTSTATUS_WIN_STATUS_LOG_RESERVATION_INVALID,
++ MD_NTSTATUS_WIN_STATUS_LOG_CANT_DELETE,
++ MD_NTSTATUS_WIN_STATUS_LOG_CONTAINER_LIMIT_EXCEEDED,
++ MD_NTSTATUS_WIN_STATUS_LOG_START_OF_LOG,
++ MD_NTSTATUS_WIN_STATUS_LOG_POLICY_ALREADY_INSTALLED,
++ MD_NTSTATUS_WIN_STATUS_LOG_POLICY_NOT_INSTALLED,
++ MD_NTSTATUS_WIN_STATUS_LOG_POLICY_INVALID,
++ MD_NTSTATUS_WIN_STATUS_LOG_POLICY_CONFLICT,
++ MD_NTSTATUS_WIN_STATUS_LOG_PINNED_ARCHIVE_TAIL,
++ MD_NTSTATUS_WIN_STATUS_LOG_RECORD_NONEXISTENT,
++ MD_NTSTATUS_WIN_STATUS_LOG_RECORDS_RESERVED_INVALID,
++ MD_NTSTATUS_WIN_STATUS_LOG_SPACE_RESERVED_INVALID,
++ MD_NTSTATUS_WIN_STATUS_LOG_TAIL_INVALID,
++ MD_NTSTATUS_WIN_STATUS_LOG_FULL,
++ MD_NTSTATUS_WIN_STATUS_LOG_MULTIPLEXED,
++ MD_NTSTATUS_WIN_STATUS_LOG_DEDICATED,
++ MD_NTSTATUS_WIN_STATUS_LOG_ARCHIVE_NOT_IN_PROGRESS,
++ MD_NTSTATUS_WIN_STATUS_LOG_ARCHIVE_IN_PROGRESS,
++ MD_NTSTATUS_WIN_STATUS_LOG_EPHEMERAL,
++ MD_NTSTATUS_WIN_STATUS_LOG_NOT_ENOUGH_CONTAINERS,
++ MD_NTSTATUS_WIN_STATUS_LOG_CLIENT_ALREADY_REGISTERED,
++ MD_NTSTATUS_WIN_STATUS_LOG_CLIENT_NOT_REGISTERED,
++ MD_NTSTATUS_WIN_STATUS_LOG_FULL_HANDLER_IN_PROGRESS,
++ MD_NTSTATUS_WIN_STATUS_LOG_CONTAINER_READ_FAILED,
++ MD_NTSTATUS_WIN_STATUS_LOG_CONTAINER_WRITE_FAILED,
++ MD_NTSTATUS_WIN_STATUS_LOG_CONTAINER_OPEN_FAILED,
++ MD_NTSTATUS_WIN_STATUS_LOG_CONTAINER_STATE_INVALID,
++ MD_NTSTATUS_WIN_STATUS_LOG_STATE_INVALID,
++ MD_NTSTATUS_WIN_STATUS_LOG_PINNED,
++ MD_NTSTATUS_WIN_STATUS_LOG_METADATA_FLUSH_FAILED,
++ MD_NTSTATUS_WIN_STATUS_LOG_INCONSISTENT_SECURITY,
++ MD_NTSTATUS_WIN_STATUS_LOG_APPENDED_FLUSH_FAILED,
++ MD_NTSTATUS_WIN_STATUS_LOG_PINNED_RESERVATION,
++ MD_NTSTATUS_WIN_STATUS_VIDEO_HUNG_DISPLAY_DRIVER_THREAD,
++ MD_NTSTATUS_WIN_STATUS_FLT_NO_HANDLER_DEFINED,
++ MD_NTSTATUS_WIN_STATUS_FLT_CONTEXT_ALREADY_DEFINED,
++ MD_NTSTATUS_WIN_STATUS_FLT_INVALID_ASYNCHRONOUS_REQUEST,
++ MD_NTSTATUS_WIN_STATUS_FLT_DISALLOW_FAST_IO,
++ MD_NTSTATUS_WIN_STATUS_FLT_INVALID_NAME_REQUEST,
++ MD_NTSTATUS_WIN_STATUS_FLT_NOT_SAFE_TO_POST_OPERATION,
++ MD_NTSTATUS_WIN_STATUS_FLT_NOT_INITIALIZED,
++ MD_NTSTATUS_WIN_STATUS_FLT_FILTER_NOT_READY,
++ MD_NTSTATUS_WIN_STATUS_FLT_POST_OPERATION_CLEANUP,
++ MD_NTSTATUS_WIN_STATUS_FLT_INTERNAL_ERROR,
++ MD_NTSTATUS_WIN_STATUS_FLT_DELETING_OBJECT,
++ MD_NTSTATUS_WIN_STATUS_FLT_MUST_BE_NONPAGED_POOL,
++ MD_NTSTATUS_WIN_STATUS_FLT_DUPLICATE_ENTRY,
++ MD_NTSTATUS_WIN_STATUS_FLT_CBDQ_DISABLED,
++ MD_NTSTATUS_WIN_STATUS_FLT_DO_NOT_ATTACH,
++ MD_NTSTATUS_WIN_STATUS_FLT_DO_NOT_DETACH,
++ MD_NTSTATUS_WIN_STATUS_FLT_INSTANCE_ALTITUDE_COLLISION,
++ MD_NTSTATUS_WIN_STATUS_FLT_INSTANCE_NAME_COLLISION,
++ MD_NTSTATUS_WIN_STATUS_FLT_FILTER_NOT_FOUND,
++ MD_NTSTATUS_WIN_STATUS_FLT_VOLUME_NOT_FOUND,
++ MD_NTSTATUS_WIN_STATUS_FLT_INSTANCE_NOT_FOUND,
++ MD_NTSTATUS_WIN_STATUS_FLT_CONTEXT_ALLOCATION_NOT_FOUND,
++ MD_NTSTATUS_WIN_STATUS_FLT_INVALID_CONTEXT_REGISTRATION,
++ MD_NTSTATUS_WIN_STATUS_FLT_NAME_CACHE_MISS,
++ MD_NTSTATUS_WIN_STATUS_FLT_NO_DEVICE_OBJECT,
++ MD_NTSTATUS_WIN_STATUS_FLT_VOLUME_ALREADY_MOUNTED,
++ MD_NTSTATUS_WIN_STATUS_FLT_ALREADY_ENLISTED,
++ MD_NTSTATUS_WIN_STATUS_FLT_CONTEXT_ALREADY_LINKED,
++ MD_NTSTATUS_WIN_STATUS_FLT_NO_WAITER_FOR_REPLY,
++ MD_NTSTATUS_WIN_STATUS_FLT_REGISTRATION_BUSY,
++ MD_NTSTATUS_WIN_STATUS_MONITOR_NO_DESCRIPTOR,
++ MD_NTSTATUS_WIN_STATUS_MONITOR_UNKNOWN_DESCRIPTOR_FORMAT,
++ MD_NTSTATUS_WIN_STATUS_MONITOR_INVALID_DESCRIPTOR_CHECKSUM,
++ MD_NTSTATUS_WIN_STATUS_MONITOR_INVALID_STANDARD_TIMING_BLOCK,
++ MD_NTSTATUS_WIN_STATUS_MONITOR_WMI_DATABLOCK_REGISTRATION_FAILED,
++ MD_NTSTATUS_WIN_STATUS_MONITOR_INVALID_SERIAL_NUMBER_MONDSC_BLOCK,
++ MD_NTSTATUS_WIN_STATUS_MONITOR_INVALID_USER_FRIENDLY_MONDSC_BLOCK,
++ MD_NTSTATUS_WIN_STATUS_MONITOR_NO_MORE_DESCRIPTOR_DATA,
++ MD_NTSTATUS_WIN_STATUS_MONITOR_INVALID_DETAILED_TIMING_BLOCK,
++ MD_NTSTATUS_WIN_STATUS_MONITOR_INVALID_MANUFACTURE_DATE,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_NOT_EXCLUSIVE_MODE_OWNER,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_DISPLAY_ADAPTER,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_ADAPTER_WAS_RESET,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_DRIVER_MODEL,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_PRESENT_MODE_CHANGED,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_PRESENT_OCCLUDED,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_PRESENT_DENIED,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_CANNOTCOLORCONVERT,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_DRIVER_MISMATCH,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_PRESENT_REDIRECTION_DISABLED,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_PRESENT_UNOCCLUDED,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_WINDOWDC_NOT_AVAILABLE,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_WINDOWLESS_PRESENT_DISABLED,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_PRESENT_INVALID_WINDOW,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_PRESENT_BUFFER_NOT_BOUND,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_VAIL_STATE_CHANGED,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INDIRECT_DISPLAY_ABANDON_SWAPCHAIN,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INDIRECT_DISPLAY_DEVICE_STOPPED,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_NO_VIDEO_MEMORY,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_CANT_LOCK_MEMORY,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_ALLOCATION_BUSY,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_TOO_MANY_REFERENCES,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_TRY_AGAIN_LATER,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_TRY_AGAIN_NOW,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_ALLOCATION_INVALID,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_UNSWIZZLING_APERTURE_UNAVAILABLE,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_UNSWIZZLING_APERTURE_UNSUPPORTED,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_CANT_EVICT_PINNED_ALLOCATION,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_ALLOCATION_USAGE,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_CANT_RENDER_LOCKED_ALLOCATION,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_ALLOCATION_CLOSED,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_ALLOCATION_INSTANCE,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_ALLOCATION_HANDLE,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_WRONG_ALLOCATION_DEVICE,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_ALLOCATION_CONTENT_LOST,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_GPU_EXCEPTION_ON_DEVICE,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_VIDPN_TOPOLOGY,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_VIDPN_TOPOLOGY_NOT_SUPPORTED,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_VIDPN_TOPOLOGY_CURRENTLY_NOT_SUPPORTED,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_VIDPN,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_SOURCE,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_TARGET,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_VIDPN_MODALITY_NOT_SUPPORTED,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_VIDPN_SOURCEMODESET,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_VIDPN_TARGETMODESET,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_FREQUENCY,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_ACTIVE_REGION,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_TOTAL_REGION,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_SOURCE_MODE,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_TARGET_MODE,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_PINNED_MODE_MUST_REMAIN_IN_SET,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_PATH_ALREADY_IN_TOPOLOGY,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_MODE_ALREADY_IN_MODESET,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_VIDEOPRESENTSOURCESET,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_VIDEOPRESENTTARGETSET,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_SOURCE_ALREADY_IN_SET,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_TARGET_ALREADY_IN_SET,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_VIDPN_PRESENT_PATH,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_NO_RECOMMENDED_VIDPN_TOPOLOGY,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_MONITOR_FREQUENCYRANGESET,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_MONITOR_FREQUENCYRANGE,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_FREQUENCYRANGE_NOT_IN_SET,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_FREQUENCYRANGE_ALREADY_IN_SET,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_STALE_MODESET,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_MONITOR_SOURCEMODESET,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_MONITOR_SOURCE_MODE,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_NO_RECOMMENDED_FUNCTIONAL_VIDPN,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_MODE_ID_MUST_BE_UNIQUE,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_EMPTY_ADAPTER_MONITOR_MODE_SUPPORT_INTERSECTION,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_VIDEO_PRESENT_TARGETS_LESS_THAN_SOURCES,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_PATH_NOT_IN_TOPOLOGY,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_ADAPTER_MUST_HAVE_AT_LEAST_ONE_SOURCE,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_ADAPTER_MUST_HAVE_AT_LEAST_ONE_TARGET,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_MONITORDESCRIPTORSET,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_MONITORDESCRIPTOR,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_MONITORDESCRIPTOR_NOT_IN_SET,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_MONITORDESCRIPTOR_ALREADY_IN_SET,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_MONITORDESCRIPTOR_ID_MUST_BE_UNIQUE,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_VIDPN_TARGET_SUBSET_TYPE,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_RESOURCES_NOT_RELATED,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_SOURCE_ID_MUST_BE_UNIQUE,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_TARGET_ID_MUST_BE_UNIQUE,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_NO_AVAILABLE_VIDPN_TARGET,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_MONITOR_COULD_NOT_BE_ASSOCIATED_WITH_ADAPTER,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_NO_VIDPNMGR,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_NO_ACTIVE_VIDPN,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_STALE_VIDPN_TOPOLOGY,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_MONITOR_NOT_CONNECTED,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_SOURCE_NOT_IN_TOPOLOGY,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_PRIMARYSURFACE_SIZE,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_VISIBLEREGION_SIZE,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_STRIDE,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_PIXELFORMAT,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_COLORBASIS,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_PIXELVALUEACCESSMODE,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_TARGET_NOT_IN_TOPOLOGY,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_NO_DISPLAY_MODE_MANAGEMENT_SUPPORT,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_CANT_ACCESS_ACTIVE_VIDPN,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_PATH_IMPORTANCE_ORDINAL,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_PATH_CONTENT_GEOMETRY_TRANSFORMATION,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_PATH_CONTENT_GEOMETRY_TRANSFORMATION_NOT_SUPPORTED,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_GAMMA_RAMP,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_GAMMA_RAMP_NOT_SUPPORTED,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_MULTISAMPLING_NOT_SUPPORTED,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_MODE_NOT_IN_MODESET,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_VIDPN_TOPOLOGY_RECOMMENDATION_REASON,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_PATH_CONTENT_TYPE,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_COPYPROTECTION_TYPE,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_UNASSIGNED_MODESET_ALREADY_EXISTS,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_SCANLINE_ORDERING,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_TOPOLOGY_CHANGES_NOT_ALLOWED,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_NO_AVAILABLE_IMPORTANCE_ORDINALS,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INCOMPATIBLE_PRIVATE_FORMAT,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_MODE_PRUNING_ALGORITHM,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_MONITOR_CAPABILITY_ORIGIN,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_MONITOR_FREQUENCYRANGE_CONSTRAINT,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_MAX_NUM_PATHS_REACHED,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_CANCEL_VIDPN_TOPOLOGY_AUGMENTATION,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_CLIENT_TYPE,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_CLIENTVIDPN_NOT_SET,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_SPECIFIED_CHILD_ALREADY_CONNECTED,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_CHILD_DESCRIPTOR_NOT_SUPPORTED,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_NOT_A_LINKED_ADAPTER,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_LEADLINK_NOT_ENUMERATED,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_CHAINLINKS_NOT_ENUMERATED,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_ADAPTER_CHAIN_NOT_READY,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_CHAINLINKS_NOT_STARTED,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_CHAINLINKS_NOT_POWERED_ON,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INCONSISTENT_DEVICE_LINK_STATE,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_NOT_POST_DEVICE_DRIVER,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_ADAPTER_ACCESS_NOT_EXCLUDED,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_NOT_SUPPORTED,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_COPP_NOT_SUPPORTED,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_UAB_NOT_SUPPORTED,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_INVALID_ENCRYPTED_PARAMETERS,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_NO_PROTECTED_OUTPUTS_EXIST,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_INTERNAL_ERROR,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_INVALID_HANDLE,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_PVP_INVALID_CERTIFICATE_LENGTH,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_SPANNING_MODE_ENABLED,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_THEATER_MODE_ENABLED,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_PVP_HFS_FAILED,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_INVALID_SRM,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_OUTPUT_DOES_NOT_SUPPORT_HDCP,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_OUTPUT_DOES_NOT_SUPPORT_ACP,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_OUTPUT_DOES_NOT_SUPPORT_CGMSA,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_HDCP_SRM_NEVER_SET,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_RESOLUTION_TOO_HIGH,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_ALL_HDCP_HARDWARE_ALREADY_IN_USE,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_PROTECTED_OUTPUT_NO_LONGER_EXISTS,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_PROTECTED_OUTPUT_DOES_NOT_HAVE_COPP_SEMANTICS,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_INVALID_INFORMATION_REQUEST,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_DRIVER_INTERNAL_ERROR,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_PROTECTED_OUTPUT_DOES_NOT_HAVE_OPM_SEMANTICS,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_SIGNALING_NOT_SUPPORTED,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_INVALID_CONFIGURATION_REQUEST,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_I2C_NOT_SUPPORTED,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_I2C_DEVICE_DOES_NOT_EXIST,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_I2C_ERROR_TRANSMITTING_DATA,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_I2C_ERROR_RECEIVING_DATA,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_DDCCI_VCP_NOT_SUPPORTED,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_DDCCI_INVALID_DATA,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_DDCCI_MONITOR_RETURNED_INVALID_TIMING_STATUS_BYTE,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_DDCCI_INVALID_CAPABILITIES_STRING,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_MCA_INTERNAL_ERROR,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_DDCCI_INVALID_MESSAGE_COMMAND,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_DDCCI_INVALID_MESSAGE_LENGTH,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_DDCCI_INVALID_MESSAGE_CHECKSUM,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_PHYSICAL_MONITOR_HANDLE,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_MONITOR_NO_LONGER_EXISTS,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_ONLY_CONSOLE_SESSION_SUPPORTED,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_NO_DISPLAY_DEVICE_CORRESPONDS_TO_NAME,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_DISPLAY_DEVICE_NOT_ATTACHED_TO_DESKTOP,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_MIRRORING_DEVICES_NOT_SUPPORTED,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_POINTER,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_NO_MONITORS_CORRESPOND_TO_DISPLAY_DEVICE,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_PARAMETER_ARRAY_TOO_SMALL,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INTERNAL_ERROR,
++ MD_NTSTATUS_WIN_STATUS_GRAPHICS_SESSION_TYPE_CHANGE_IN_PROGRESS,
++ MD_NTSTATUS_WIN_STATUS_FVE_LOCKED_VOLUME,
++ MD_NTSTATUS_WIN_STATUS_FVE_NOT_ENCRYPTED,
++ MD_NTSTATUS_WIN_STATUS_FVE_BAD_INFORMATION,
++ MD_NTSTATUS_WIN_STATUS_FVE_TOO_SMALL,
++ MD_NTSTATUS_WIN_STATUS_FVE_FAILED_WRONG_FS,
++ MD_NTSTATUS_WIN_STATUS_FVE_BAD_PARTITION_SIZE,
++ MD_NTSTATUS_WIN_STATUS_FVE_FS_NOT_EXTENDED,
++ MD_NTSTATUS_WIN_STATUS_FVE_FS_MOUNTED,
++ MD_NTSTATUS_WIN_STATUS_FVE_NO_LICENSE,
++ MD_NTSTATUS_WIN_STATUS_FVE_ACTION_NOT_ALLOWED,
++ MD_NTSTATUS_WIN_STATUS_FVE_BAD_DATA,
++ MD_NTSTATUS_WIN_STATUS_FVE_VOLUME_NOT_BOUND,
++ MD_NTSTATUS_WIN_STATUS_FVE_NOT_DATA_VOLUME,
++ MD_NTSTATUS_WIN_STATUS_FVE_CONV_READ_ERROR,
++ MD_NTSTATUS_WIN_STATUS_FVE_CONV_WRITE_ERROR,
++ MD_NTSTATUS_WIN_STATUS_FVE_OVERLAPPED_UPDATE,
++ MD_NTSTATUS_WIN_STATUS_FVE_FAILED_SECTOR_SIZE,
++ MD_NTSTATUS_WIN_STATUS_FVE_FAILED_AUTHENTICATION,
++ MD_NTSTATUS_WIN_STATUS_FVE_NOT_OS_VOLUME,
++ MD_NTSTATUS_WIN_STATUS_FVE_KEYFILE_NOT_FOUND,
++ MD_NTSTATUS_WIN_STATUS_FVE_KEYFILE_INVALID,
++ MD_NTSTATUS_WIN_STATUS_FVE_KEYFILE_NO_VMK,
++ MD_NTSTATUS_WIN_STATUS_FVE_TPM_DISABLED,
++ MD_NTSTATUS_WIN_STATUS_FVE_TPM_SRK_AUTH_NOT_ZERO,
++ MD_NTSTATUS_WIN_STATUS_FVE_TPM_INVALID_PCR,
++ MD_NTSTATUS_WIN_STATUS_FVE_TPM_NO_VMK,
++ MD_NTSTATUS_WIN_STATUS_FVE_PIN_INVALID,
++ MD_NTSTATUS_WIN_STATUS_FVE_AUTH_INVALID_APPLICATION,
++ MD_NTSTATUS_WIN_STATUS_FVE_AUTH_INVALID_CONFIG,
++ MD_NTSTATUS_WIN_STATUS_FVE_DEBUGGER_ENABLED,
++ MD_NTSTATUS_WIN_STATUS_FVE_DRY_RUN_FAILED,
++ MD_NTSTATUS_WIN_STATUS_FVE_BAD_METADATA_POINTER,
++ MD_NTSTATUS_WIN_STATUS_FVE_OLD_METADATA_COPY,
++ MD_NTSTATUS_WIN_STATUS_FVE_REBOOT_REQUIRED,
++ MD_NTSTATUS_WIN_STATUS_FVE_RAW_ACCESS,
++ MD_NTSTATUS_WIN_STATUS_FVE_RAW_BLOCKED,
++ MD_NTSTATUS_WIN_STATUS_FVE_NO_AUTOUNLOCK_MASTER_KEY,
++ MD_NTSTATUS_WIN_STATUS_FVE_MOR_FAILED,
++ MD_NTSTATUS_WIN_STATUS_FVE_NO_FEATURE_LICENSE,
++ MD_NTSTATUS_WIN_STATUS_FVE_POLICY_USER_DISABLE_RDV_NOT_ALLOWED,
++ MD_NTSTATUS_WIN_STATUS_FVE_CONV_RECOVERY_FAILED,
++ MD_NTSTATUS_WIN_STATUS_FVE_VIRTUALIZED_SPACE_TOO_BIG,
++ MD_NTSTATUS_WIN_STATUS_FVE_INVALID_DATUM_TYPE,
++ MD_NTSTATUS_WIN_STATUS_FVE_VOLUME_TOO_SMALL,
++ MD_NTSTATUS_WIN_STATUS_FVE_ENH_PIN_INVALID,
++ MD_NTSTATUS_WIN_STATUS_FVE_FULL_ENCRYPTION_NOT_ALLOWED_ON_TP_STORAGE,
++ MD_NTSTATUS_WIN_STATUS_FVE_WIPE_NOT_ALLOWED_ON_TP_STORAGE,
++ MD_NTSTATUS_WIN_STATUS_FVE_NOT_ALLOWED_ON_CSV_STACK,
++ MD_NTSTATUS_WIN_STATUS_FVE_NOT_ALLOWED_ON_CLUSTER,
++ MD_NTSTATUS_WIN_STATUS_FVE_NOT_ALLOWED_TO_UPGRADE_WHILE_CONVERTING,
++ MD_NTSTATUS_WIN_STATUS_FVE_WIPE_CANCEL_NOT_APPLICABLE,
++ MD_NTSTATUS_WIN_STATUS_FVE_EDRIVE_DRY_RUN_FAILED,
++ MD_NTSTATUS_WIN_STATUS_FVE_SECUREBOOT_DISABLED,
++ MD_NTSTATUS_WIN_STATUS_FVE_SECUREBOOT_CONFIG_CHANGE,
++ MD_NTSTATUS_WIN_STATUS_FVE_DEVICE_LOCKEDOUT,
++ MD_NTSTATUS_WIN_STATUS_FVE_VOLUME_EXTEND_PREVENTS_EOW_DECRYPT,
++ MD_NTSTATUS_WIN_STATUS_FVE_NOT_DE_VOLUME,
++ MD_NTSTATUS_WIN_STATUS_FVE_PROTECTION_DISABLED,
++ MD_NTSTATUS_WIN_STATUS_FVE_PROTECTION_CANNOT_BE_DISABLED,
++ MD_NTSTATUS_WIN_STATUS_FVE_OSV_KSR_NOT_ALLOWED,
++ MD_NTSTATUS_WIN_STATUS_FWP_CALLOUT_NOT_FOUND,
++ MD_NTSTATUS_WIN_STATUS_FWP_CONDITION_NOT_FOUND,
++ MD_NTSTATUS_WIN_STATUS_FWP_FILTER_NOT_FOUND,
++ MD_NTSTATUS_WIN_STATUS_FWP_LAYER_NOT_FOUND,
++ MD_NTSTATUS_WIN_STATUS_FWP_PROVIDER_NOT_FOUND,
++ MD_NTSTATUS_WIN_STATUS_FWP_PROVIDER_CONTEXT_NOT_FOUND,
++ MD_NTSTATUS_WIN_STATUS_FWP_SUBLAYER_NOT_FOUND,
++ MD_NTSTATUS_WIN_STATUS_FWP_NOT_FOUND,
++ MD_NTSTATUS_WIN_STATUS_FWP_ALREADY_EXISTS,
++ MD_NTSTATUS_WIN_STATUS_FWP_IN_USE,
++ MD_NTSTATUS_WIN_STATUS_FWP_DYNAMIC_SESSION_IN_PROGRESS,
++ MD_NTSTATUS_WIN_STATUS_FWP_WRONG_SESSION,
++ MD_NTSTATUS_WIN_STATUS_FWP_NO_TXN_IN_PROGRESS,
++ MD_NTSTATUS_WIN_STATUS_FWP_TXN_IN_PROGRESS,
++ MD_NTSTATUS_WIN_STATUS_FWP_TXN_ABORTED,
++ MD_NTSTATUS_WIN_STATUS_FWP_SESSION_ABORTED,
++ MD_NTSTATUS_WIN_STATUS_FWP_INCOMPATIBLE_TXN,
++ MD_NTSTATUS_WIN_STATUS_FWP_TIMEOUT,
++ MD_NTSTATUS_WIN_STATUS_FWP_NET_EVENTS_DISABLED,
++ MD_NTSTATUS_WIN_STATUS_FWP_INCOMPATIBLE_LAYER,
++ MD_NTSTATUS_WIN_STATUS_FWP_KM_CLIENTS_ONLY,
++ MD_NTSTATUS_WIN_STATUS_FWP_LIFETIME_MISMATCH,
++ MD_NTSTATUS_WIN_STATUS_FWP_BUILTIN_OBJECT,
++ MD_NTSTATUS_WIN_STATUS_FWP_TOO_MANY_CALLOUTS,
++ MD_NTSTATUS_WIN_STATUS_FWP_NOTIFICATION_DROPPED,
++ MD_NTSTATUS_WIN_STATUS_FWP_TRAFFIC_MISMATCH,
++ MD_NTSTATUS_WIN_STATUS_FWP_INCOMPATIBLE_SA_STATE,
++ MD_NTSTATUS_WIN_STATUS_FWP_NULL_POINTER,
++ MD_NTSTATUS_WIN_STATUS_FWP_INVALID_ENUMERATOR,
++ MD_NTSTATUS_WIN_STATUS_FWP_INVALID_FLAGS,
++ MD_NTSTATUS_WIN_STATUS_FWP_INVALID_NET_MASK,
++ MD_NTSTATUS_WIN_STATUS_FWP_INVALID_RANGE,
++ MD_NTSTATUS_WIN_STATUS_FWP_INVALID_INTERVAL,
++ MD_NTSTATUS_WIN_STATUS_FWP_ZERO_LENGTH_ARRAY,
++ MD_NTSTATUS_WIN_STATUS_FWP_NULL_DISPLAY_NAME,
++ MD_NTSTATUS_WIN_STATUS_FWP_INVALID_ACTION_TYPE,
++ MD_NTSTATUS_WIN_STATUS_FWP_INVALID_WEIGHT,
++ MD_NTSTATUS_WIN_STATUS_FWP_MATCH_TYPE_MISMATCH,
++ MD_NTSTATUS_WIN_STATUS_FWP_TYPE_MISMATCH,
++ MD_NTSTATUS_WIN_STATUS_FWP_OUT_OF_BOUNDS,
++ MD_NTSTATUS_WIN_STATUS_FWP_RESERVED,
++ MD_NTSTATUS_WIN_STATUS_FWP_DUPLICATE_CONDITION,
++ MD_NTSTATUS_WIN_STATUS_FWP_DUPLICATE_KEYMOD,
++ MD_NTSTATUS_WIN_STATUS_FWP_ACTION_INCOMPATIBLE_WITH_LAYER,
++ MD_NTSTATUS_WIN_STATUS_FWP_ACTION_INCOMPATIBLE_WITH_SUBLAYER,
++ MD_NTSTATUS_WIN_STATUS_FWP_CONTEXT_INCOMPATIBLE_WITH_LAYER,
++ MD_NTSTATUS_WIN_STATUS_FWP_CONTEXT_INCOMPATIBLE_WITH_CALLOUT,
++ MD_NTSTATUS_WIN_STATUS_FWP_INCOMPATIBLE_AUTH_METHOD,
++ MD_NTSTATUS_WIN_STATUS_FWP_INCOMPATIBLE_DH_GROUP,
++ MD_NTSTATUS_WIN_STATUS_FWP_EM_NOT_SUPPORTED,
++ MD_NTSTATUS_WIN_STATUS_FWP_NEVER_MATCH,
++ MD_NTSTATUS_WIN_STATUS_FWP_PROVIDER_CONTEXT_MISMATCH,
++ MD_NTSTATUS_WIN_STATUS_FWP_INVALID_PARAMETER,
++ MD_NTSTATUS_WIN_STATUS_FWP_TOO_MANY_SUBLAYERS,
++ MD_NTSTATUS_WIN_STATUS_FWP_CALLOUT_NOTIFICATION_FAILED,
++ MD_NTSTATUS_WIN_STATUS_FWP_INVALID_AUTH_TRANSFORM,
++ MD_NTSTATUS_WIN_STATUS_FWP_INVALID_CIPHER_TRANSFORM,
++ MD_NTSTATUS_WIN_STATUS_FWP_INCOMPATIBLE_CIPHER_TRANSFORM,
++ MD_NTSTATUS_WIN_STATUS_FWP_INVALID_TRANSFORM_COMBINATION,
++ MD_NTSTATUS_WIN_STATUS_FWP_DUPLICATE_AUTH_METHOD,
++ MD_NTSTATUS_WIN_STATUS_FWP_INVALID_TUNNEL_ENDPOINT,
++ MD_NTSTATUS_WIN_STATUS_FWP_L2_DRIVER_NOT_READY,
++ MD_NTSTATUS_WIN_STATUS_FWP_KEY_DICTATOR_ALREADY_REGISTERED,
++ MD_NTSTATUS_WIN_STATUS_FWP_KEY_DICTATION_INVALID_KEYING_MATERIAL,
++ MD_NTSTATUS_WIN_STATUS_FWP_CONNECTIONS_DISABLED,
++ MD_NTSTATUS_WIN_STATUS_FWP_INVALID_DNS_NAME,
++ MD_NTSTATUS_WIN_STATUS_FWP_STILL_ON,
++ MD_NTSTATUS_WIN_STATUS_FWP_IKEEXT_NOT_RUNNING,
++ MD_NTSTATUS_WIN_STATUS_FWP_TCPIP_NOT_READY,
++ MD_NTSTATUS_WIN_STATUS_FWP_INJECT_HANDLE_CLOSING,
++ MD_NTSTATUS_WIN_STATUS_FWP_INJECT_HANDLE_STALE,
++ MD_NTSTATUS_WIN_STATUS_FWP_CANNOT_PEND,
++ MD_NTSTATUS_WIN_STATUS_FWP_DROP_NOICMP,
++ MD_NTSTATUS_WIN_STATUS_NDIS_CLOSING,
++ MD_NTSTATUS_WIN_STATUS_NDIS_BAD_VERSION,
++ MD_NTSTATUS_WIN_STATUS_NDIS_BAD_CHARACTERISTICS,
++ MD_NTSTATUS_WIN_STATUS_NDIS_ADAPTER_NOT_FOUND,
++ MD_NTSTATUS_WIN_STATUS_NDIS_OPEN_FAILED,
++ MD_NTSTATUS_WIN_STATUS_NDIS_DEVICE_FAILED,
++ MD_NTSTATUS_WIN_STATUS_NDIS_MULTICAST_FULL,
++ MD_NTSTATUS_WIN_STATUS_NDIS_MULTICAST_EXISTS,
++ MD_NTSTATUS_WIN_STATUS_NDIS_MULTICAST_NOT_FOUND,
++ MD_NTSTATUS_WIN_STATUS_NDIS_REQUEST_ABORTED,
++ MD_NTSTATUS_WIN_STATUS_NDIS_RESET_IN_PROGRESS,
++ MD_NTSTATUS_WIN_STATUS_NDIS_INVALID_PACKET,
++ MD_NTSTATUS_WIN_STATUS_NDIS_INVALID_DEVICE_REQUEST,
++ MD_NTSTATUS_WIN_STATUS_NDIS_ADAPTER_NOT_READY,
++ MD_NTSTATUS_WIN_STATUS_NDIS_INVALID_LENGTH,
++ MD_NTSTATUS_WIN_STATUS_NDIS_INVALID_DATA,
++ MD_NTSTATUS_WIN_STATUS_NDIS_BUFFER_TOO_SHORT,
++ MD_NTSTATUS_WIN_STATUS_NDIS_INVALID_OID,
++ MD_NTSTATUS_WIN_STATUS_NDIS_ADAPTER_REMOVED,
++ MD_NTSTATUS_WIN_STATUS_NDIS_UNSUPPORTED_MEDIA,
++ MD_NTSTATUS_WIN_STATUS_NDIS_GROUP_ADDRESS_IN_USE,
++ MD_NTSTATUS_WIN_STATUS_NDIS_FILE_NOT_FOUND,
++ MD_NTSTATUS_WIN_STATUS_NDIS_ERROR_READING_FILE,
++ MD_NTSTATUS_WIN_STATUS_NDIS_ALREADY_MAPPED,
++ MD_NTSTATUS_WIN_STATUS_NDIS_RESOURCE_CONFLICT,
++ MD_NTSTATUS_WIN_STATUS_NDIS_MEDIA_DISCONNECTED,
++ MD_NTSTATUS_WIN_STATUS_NDIS_INVALID_ADDRESS,
++ MD_NTSTATUS_WIN_STATUS_NDIS_PAUSED,
++ MD_NTSTATUS_WIN_STATUS_NDIS_INTERFACE_NOT_FOUND,
++ MD_NTSTATUS_WIN_STATUS_NDIS_UNSUPPORTED_REVISION,
++ MD_NTSTATUS_WIN_STATUS_NDIS_INVALID_PORT,
++ MD_NTSTATUS_WIN_STATUS_NDIS_INVALID_PORT_STATE,
++ MD_NTSTATUS_WIN_STATUS_NDIS_LOW_POWER_STATE,
++ MD_NTSTATUS_WIN_STATUS_NDIS_REINIT_REQUIRED,
++ MD_NTSTATUS_WIN_STATUS_NDIS_NO_QUEUES,
++ MD_NTSTATUS_WIN_STATUS_NDIS_NOT_SUPPORTED,
++ MD_NTSTATUS_WIN_STATUS_NDIS_OFFLOAD_POLICY,
++ MD_NTSTATUS_WIN_STATUS_NDIS_OFFLOAD_CONNECTION_REJECTED,
++ MD_NTSTATUS_WIN_STATUS_NDIS_OFFLOAD_PATH_REJECTED,
++ MD_NTSTATUS_WIN_STATUS_NDIS_DOT11_AUTO_CONFIG_ENABLED,
++ MD_NTSTATUS_WIN_STATUS_NDIS_DOT11_MEDIA_IN_USE,
++ MD_NTSTATUS_WIN_STATUS_NDIS_DOT11_POWER_STATE_INVALID,
++ MD_NTSTATUS_WIN_STATUS_NDIS_PM_WOL_PATTERN_LIST_FULL,
++ MD_NTSTATUS_WIN_STATUS_NDIS_PM_PROTOCOL_OFFLOAD_LIST_FULL,
++ MD_NTSTATUS_WIN_STATUS_NDIS_DOT11_AP_CHANNEL_CURRENTLY_NOT_AVAILABLE,
++ MD_NTSTATUS_WIN_STATUS_NDIS_DOT11_AP_BAND_CURRENTLY_NOT_AVAILABLE,
++ MD_NTSTATUS_WIN_STATUS_NDIS_DOT11_AP_CHANNEL_NOT_ALLOWED,
++ MD_NTSTATUS_WIN_STATUS_NDIS_DOT11_AP_BAND_NOT_ALLOWED,
++ MD_NTSTATUS_WIN_STATUS_QUIC_HANDSHAKE_FAILURE,
++ MD_NTSTATUS_WIN_STATUS_QUIC_VER_NEG_FAILURE,
++ MD_NTSTATUS_WIN_STATUS_TPM_ERROR_MASK,
++ MD_NTSTATUS_WIN_STATUS_TPM_AUTHFAIL,
++ MD_NTSTATUS_WIN_STATUS_TPM_BADINDEX,
++ MD_NTSTATUS_WIN_STATUS_TPM_BAD_PARAMETER,
++ MD_NTSTATUS_WIN_STATUS_TPM_AUDITFAILURE,
++ MD_NTSTATUS_WIN_STATUS_TPM_CLEAR_DISABLED,
++ MD_NTSTATUS_WIN_STATUS_TPM_DEACTIVATED,
++ MD_NTSTATUS_WIN_STATUS_TPM_DISABLED,
++ MD_NTSTATUS_WIN_STATUS_TPM_DISABLED_CMD,
++ MD_NTSTATUS_WIN_STATUS_TPM_FAIL,
++ MD_NTSTATUS_WIN_STATUS_TPM_BAD_ORDINAL,
++ MD_NTSTATUS_WIN_STATUS_TPM_INSTALL_DISABLED,
++ MD_NTSTATUS_WIN_STATUS_TPM_INVALID_KEYHANDLE,
++ MD_NTSTATUS_WIN_STATUS_TPM_KEYNOTFOUND,
++ MD_NTSTATUS_WIN_STATUS_TPM_INAPPROPRIATE_ENC,
++ MD_NTSTATUS_WIN_STATUS_TPM_MIGRATEFAIL,
++ MD_NTSTATUS_WIN_STATUS_TPM_INVALID_PCR_INFO,
++ MD_NTSTATUS_WIN_STATUS_TPM_NOSPACE,
++ MD_NTSTATUS_WIN_STATUS_TPM_NOSRK,
++ MD_NTSTATUS_WIN_STATUS_TPM_NOTSEALED_BLOB,
++ MD_NTSTATUS_WIN_STATUS_TPM_OWNER_SET,
++ MD_NTSTATUS_WIN_STATUS_TPM_RESOURCES,
++ MD_NTSTATUS_WIN_STATUS_TPM_SHORTRANDOM,
++ MD_NTSTATUS_WIN_STATUS_TPM_SIZE,
++ MD_NTSTATUS_WIN_STATUS_TPM_WRONGPCRVAL,
++ MD_NTSTATUS_WIN_STATUS_TPM_BAD_PARAM_SIZE,
++ MD_NTSTATUS_WIN_STATUS_TPM_SHA_THREAD,
++ MD_NTSTATUS_WIN_STATUS_TPM_SHA_ERROR,
++ MD_NTSTATUS_WIN_STATUS_TPM_FAILEDSELFTEST,
++ MD_NTSTATUS_WIN_STATUS_TPM_AUTH2FAIL,
++ MD_NTSTATUS_WIN_STATUS_TPM_BADTAG,
++ MD_NTSTATUS_WIN_STATUS_TPM_IOERROR,
++ MD_NTSTATUS_WIN_STATUS_TPM_ENCRYPT_ERROR,
++ MD_NTSTATUS_WIN_STATUS_TPM_DECRYPT_ERROR,
++ MD_NTSTATUS_WIN_STATUS_TPM_INVALID_AUTHHANDLE,
++ MD_NTSTATUS_WIN_STATUS_TPM_NO_ENDORSEMENT,
++ MD_NTSTATUS_WIN_STATUS_TPM_INVALID_KEYUSAGE,
++ MD_NTSTATUS_WIN_STATUS_TPM_WRONG_ENTITYTYPE,
++ MD_NTSTATUS_WIN_STATUS_TPM_INVALID_POSTINIT,
++ MD_NTSTATUS_WIN_STATUS_TPM_INAPPROPRIATE_SIG,
++ MD_NTSTATUS_WIN_STATUS_TPM_BAD_KEY_PROPERTY,
++ MD_NTSTATUS_WIN_STATUS_TPM_BAD_MIGRATION,
++ MD_NTSTATUS_WIN_STATUS_TPM_BAD_SCHEME,
++ MD_NTSTATUS_WIN_STATUS_TPM_BAD_DATASIZE,
++ MD_NTSTATUS_WIN_STATUS_TPM_BAD_MODE,
++ MD_NTSTATUS_WIN_STATUS_TPM_BAD_PRESENCE,
++ MD_NTSTATUS_WIN_STATUS_TPM_BAD_VERSION,
++ MD_NTSTATUS_WIN_STATUS_TPM_NO_WRAP_TRANSPORT,
++ MD_NTSTATUS_WIN_STATUS_TPM_AUDITFAIL_UNSUCCESSFUL,
++ MD_NTSTATUS_WIN_STATUS_TPM_AUDITFAIL_SUCCESSFUL,
++ MD_NTSTATUS_WIN_STATUS_TPM_NOTRESETABLE,
++ MD_NTSTATUS_WIN_STATUS_TPM_NOTLOCAL,
++ MD_NTSTATUS_WIN_STATUS_TPM_BAD_TYPE,
++ MD_NTSTATUS_WIN_STATUS_TPM_INVALID_RESOURCE,
++ MD_NTSTATUS_WIN_STATUS_TPM_NOTFIPS,
++ MD_NTSTATUS_WIN_STATUS_TPM_INVALID_FAMILY,
++ MD_NTSTATUS_WIN_STATUS_TPM_NO_NV_PERMISSION,
++ MD_NTSTATUS_WIN_STATUS_TPM_REQUIRES_SIGN,
++ MD_NTSTATUS_WIN_STATUS_TPM_KEY_NOTSUPPORTED,
++ MD_NTSTATUS_WIN_STATUS_TPM_AUTH_CONFLICT,
++ MD_NTSTATUS_WIN_STATUS_TPM_AREA_LOCKED,
++ MD_NTSTATUS_WIN_STATUS_TPM_BAD_LOCALITY,
++ MD_NTSTATUS_WIN_STATUS_TPM_READ_ONLY,
++ MD_NTSTATUS_WIN_STATUS_TPM_PER_NOWRITE,
++ MD_NTSTATUS_WIN_STATUS_TPM_FAMILYCOUNT,
++ MD_NTSTATUS_WIN_STATUS_TPM_WRITE_LOCKED,
++ MD_NTSTATUS_WIN_STATUS_TPM_BAD_ATTRIBUTES,
++ MD_NTSTATUS_WIN_STATUS_TPM_INVALID_STRUCTURE,
++ MD_NTSTATUS_WIN_STATUS_TPM_KEY_OWNER_CONTROL,
++ MD_NTSTATUS_WIN_STATUS_TPM_BAD_COUNTER,
++ MD_NTSTATUS_WIN_STATUS_TPM_NOT_FULLWRITE,
++ MD_NTSTATUS_WIN_STATUS_TPM_CONTEXT_GAP,
++ MD_NTSTATUS_WIN_STATUS_TPM_MAXNVWRITES,
++ MD_NTSTATUS_WIN_STATUS_TPM_NOOPERATOR,
++ MD_NTSTATUS_WIN_STATUS_TPM_RESOURCEMISSING,
++ MD_NTSTATUS_WIN_STATUS_TPM_DELEGATE_LOCK,
++ MD_NTSTATUS_WIN_STATUS_TPM_DELEGATE_FAMILY,
++ MD_NTSTATUS_WIN_STATUS_TPM_DELEGATE_ADMIN,
++ MD_NTSTATUS_WIN_STATUS_TPM_TRANSPORT_NOTEXCLUSIVE,
++ MD_NTSTATUS_WIN_STATUS_TPM_OWNER_CONTROL,
++ MD_NTSTATUS_WIN_STATUS_TPM_DAA_RESOURCES,
++ MD_NTSTATUS_WIN_STATUS_TPM_DAA_INPUT_DATA0,
++ MD_NTSTATUS_WIN_STATUS_TPM_DAA_INPUT_DATA1,
++ MD_NTSTATUS_WIN_STATUS_TPM_DAA_ISSUER_SETTINGS,
++ MD_NTSTATUS_WIN_STATUS_TPM_DAA_TPM_SETTINGS,
++ MD_NTSTATUS_WIN_STATUS_TPM_DAA_STAGE,
++ MD_NTSTATUS_WIN_STATUS_TPM_DAA_ISSUER_VALIDITY,
++ MD_NTSTATUS_WIN_STATUS_TPM_DAA_WRONG_W,
++ MD_NTSTATUS_WIN_STATUS_TPM_BAD_HANDLE,
++ MD_NTSTATUS_WIN_STATUS_TPM_BAD_DELEGATE,
++ MD_NTSTATUS_WIN_STATUS_TPM_BADCONTEXT,
++ MD_NTSTATUS_WIN_STATUS_TPM_TOOMANYCONTEXTS,
++ MD_NTSTATUS_WIN_STATUS_TPM_MA_TICKET_SIGNATURE,
++ MD_NTSTATUS_WIN_STATUS_TPM_MA_DESTINATION,
++ MD_NTSTATUS_WIN_STATUS_TPM_MA_SOURCE,
++ MD_NTSTATUS_WIN_STATUS_TPM_MA_AUTHORITY,
++ MD_NTSTATUS_WIN_STATUS_TPM_PERMANENTEK,
++ MD_NTSTATUS_WIN_STATUS_TPM_BAD_SIGNATURE,
++ MD_NTSTATUS_WIN_STATUS_TPM_NOCONTEXTSPACE,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_ASYMMETRIC,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_ATTRIBUTES,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_HASH,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_VALUE,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_HIERARCHY,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_KEY_SIZE,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_MGF,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_MODE,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_TYPE,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_HANDLE,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_KDF,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_RANGE,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_AUTH_FAIL,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_NONCE,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_PP,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_SCHEME,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_SIZE,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_SYMMETRIC,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_TAG,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_SELECTOR,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_INSUFFICIENT,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_SIGNATURE,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_KEY,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_POLICY_FAIL,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_INTEGRITY,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_TICKET,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_RESERVED_BITS,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_BAD_AUTH,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_EXPIRED,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_POLICY_CC,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_BINDING,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_CURVE,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_ECC_POINT,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_INITIALIZE,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_FAILURE,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_SEQUENCE,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_PRIVATE,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_HMAC,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_DISABLED,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_EXCLUSIVE,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_ECC_CURVE,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_AUTH_TYPE,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_AUTH_MISSING,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_POLICY,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_PCR,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_PCR_CHANGED,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_UPGRADE,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_TOO_MANY_CONTEXTS,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_AUTH_UNAVAILABLE,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_REBOOT,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_UNBALANCED,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_COMMAND_SIZE,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_COMMAND_CODE,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_AUTHSIZE,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_AUTH_CONTEXT,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_NV_RANGE,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_NV_SIZE,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_NV_LOCKED,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_NV_AUTHORIZATION,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_NV_UNINITIALIZED,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_NV_SPACE,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_NV_DEFINED,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_BAD_CONTEXT,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_CPHASH,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_PARENT,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_NEEDS_TEST,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_NO_RESULT,
++ MD_NTSTATUS_WIN_STATUS_TPM_20_E_SENSITIVE,
++ MD_NTSTATUS_WIN_STATUS_TPM_COMMAND_BLOCKED,
++ MD_NTSTATUS_WIN_STATUS_TPM_INVALID_HANDLE,
++ MD_NTSTATUS_WIN_STATUS_TPM_DUPLICATE_VHANDLE,
++ MD_NTSTATUS_WIN_STATUS_TPM_EMBEDDED_COMMAND_BLOCKED,
++ MD_NTSTATUS_WIN_STATUS_TPM_EMBEDDED_COMMAND_UNSUPPORTED,
++ MD_NTSTATUS_WIN_STATUS_TPM_RETRY,
++ MD_NTSTATUS_WIN_STATUS_TPM_NEEDS_SELFTEST,
++ MD_NTSTATUS_WIN_STATUS_TPM_DOING_SELFTEST,
++ MD_NTSTATUS_WIN_STATUS_TPM_DEFEND_LOCK_RUNNING,
++ MD_NTSTATUS_WIN_STATUS_TPM_COMMAND_CANCELED,
++ MD_NTSTATUS_WIN_STATUS_TPM_TOO_MANY_CONTEXTS,
++ MD_NTSTATUS_WIN_STATUS_TPM_NOT_FOUND,
++ MD_NTSTATUS_WIN_STATUS_TPM_ACCESS_DENIED,
++ MD_NTSTATUS_WIN_STATUS_TPM_INSUFFICIENT_BUFFER,
++ MD_NTSTATUS_WIN_STATUS_TPM_PPI_FUNCTION_UNSUPPORTED,
++ MD_NTSTATUS_WIN_STATUS_PCP_ERROR_MASK,
++ MD_NTSTATUS_WIN_STATUS_PCP_DEVICE_NOT_READY,
++ MD_NTSTATUS_WIN_STATUS_PCP_INVALID_HANDLE,
++ MD_NTSTATUS_WIN_STATUS_PCP_INVALID_PARAMETER,
++ MD_NTSTATUS_WIN_STATUS_PCP_FLAG_NOT_SUPPORTED,
++ MD_NTSTATUS_WIN_STATUS_PCP_NOT_SUPPORTED,
++ MD_NTSTATUS_WIN_STATUS_PCP_BUFFER_TOO_SMALL,
++ MD_NTSTATUS_WIN_STATUS_PCP_INTERNAL_ERROR,
++ MD_NTSTATUS_WIN_STATUS_PCP_AUTHENTICATION_FAILED,
++ MD_NTSTATUS_WIN_STATUS_PCP_AUTHENTICATION_IGNORED,
++ MD_NTSTATUS_WIN_STATUS_PCP_POLICY_NOT_FOUND,
++ MD_NTSTATUS_WIN_STATUS_PCP_PROFILE_NOT_FOUND,
++ MD_NTSTATUS_WIN_STATUS_PCP_VALIDATION_FAILED,
++ MD_NTSTATUS_WIN_STATUS_PCP_DEVICE_NOT_FOUND,
++ MD_NTSTATUS_WIN_STATUS_PCP_WRONG_PARENT,
++ MD_NTSTATUS_WIN_STATUS_PCP_KEY_NOT_LOADED,
++ MD_NTSTATUS_WIN_STATUS_PCP_NO_KEY_CERTIFICATION,
++ MD_NTSTATUS_WIN_STATUS_PCP_KEY_NOT_FINALIZED,
++ MD_NTSTATUS_WIN_STATUS_PCP_ATTESTATION_CHALLENGE_NOT_SET,
++ MD_NTSTATUS_WIN_STATUS_PCP_NOT_PCR_BOUND,
++ MD_NTSTATUS_WIN_STATUS_PCP_KEY_ALREADY_FINALIZED,
++ MD_NTSTATUS_WIN_STATUS_PCP_KEY_USAGE_POLICY_NOT_SUPPORTED,
++ MD_NTSTATUS_WIN_STATUS_PCP_KEY_USAGE_POLICY_INVALID,
++ MD_NTSTATUS_WIN_STATUS_PCP_SOFT_KEY_ERROR,
++ MD_NTSTATUS_WIN_STATUS_PCP_KEY_NOT_AUTHENTICATED,
++ MD_NTSTATUS_WIN_STATUS_PCP_KEY_NOT_AIK,
++ MD_NTSTATUS_WIN_STATUS_PCP_KEY_NOT_SIGNING_KEY,
++ MD_NTSTATUS_WIN_STATUS_PCP_LOCKED_OUT,
++ MD_NTSTATUS_WIN_STATUS_PCP_CLAIM_TYPE_NOT_SUPPORTED,
++ MD_NTSTATUS_WIN_STATUS_PCP_TPM_VERSION_NOT_SUPPORTED,
++ MD_NTSTATUS_WIN_STATUS_PCP_BUFFER_LENGTH_MISMATCH,
++ MD_NTSTATUS_WIN_STATUS_PCP_IFX_RSA_KEY_CREATION_BLOCKED,
++ MD_NTSTATUS_WIN_STATUS_PCP_TICKET_MISSING,
++ MD_NTSTATUS_WIN_STATUS_PCP_RAW_POLICY_NOT_SUPPORTED,
++ MD_NTSTATUS_WIN_STATUS_PCP_KEY_HANDLE_INVALIDATED,
++ MD_NTSTATUS_WIN_STATUS_RTPM_NO_RESULT,
++ MD_NTSTATUS_WIN_STATUS_RTPM_PCR_READ_INCOMPLETE,
++ MD_NTSTATUS_WIN_STATUS_RTPM_INVALID_CONTEXT,
++ MD_NTSTATUS_WIN_STATUS_RTPM_UNSUPPORTED_CMD,
++ MD_NTSTATUS_WIN_STATUS_TPM_ZERO_EXHAUST_ENABLED,
++ MD_NTSTATUS_WIN_STATUS_HV_INVALID_HYPERCALL_CODE,
++ MD_NTSTATUS_WIN_STATUS_HV_INVALID_HYPERCALL_INPUT,
++ MD_NTSTATUS_WIN_STATUS_HV_INVALID_ALIGNMENT,
++ MD_NTSTATUS_WIN_STATUS_HV_INVALID_PARAMETER,
++ MD_NTSTATUS_WIN_STATUS_HV_ACCESS_DENIED,
++ MD_NTSTATUS_WIN_STATUS_HV_INVALID_PARTITION_STATE,
++ MD_NTSTATUS_WIN_STATUS_HV_OPERATION_DENIED,
++ MD_NTSTATUS_WIN_STATUS_HV_UNKNOWN_PROPERTY,
++ MD_NTSTATUS_WIN_STATUS_HV_PROPERTY_VALUE_OUT_OF_RANGE,
++ MD_NTSTATUS_WIN_STATUS_HV_INSUFFICIENT_MEMORY,
++ MD_NTSTATUS_WIN_STATUS_HV_PARTITION_TOO_DEEP,
++ MD_NTSTATUS_WIN_STATUS_HV_INVALID_PARTITION_ID,
++ MD_NTSTATUS_WIN_STATUS_HV_INVALID_VP_INDEX,
++ MD_NTSTATUS_WIN_STATUS_HV_INVALID_PORT_ID,
++ MD_NTSTATUS_WIN_STATUS_HV_INVALID_CONNECTION_ID,
++ MD_NTSTATUS_WIN_STATUS_HV_INSUFFICIENT_BUFFERS,
++ MD_NTSTATUS_WIN_STATUS_HV_NOT_ACKNOWLEDGED,
++ MD_NTSTATUS_WIN_STATUS_HV_INVALID_VP_STATE,
++ MD_NTSTATUS_WIN_STATUS_HV_ACKNOWLEDGED,
++ MD_NTSTATUS_WIN_STATUS_HV_INVALID_SAVE_RESTORE_STATE,
++ MD_NTSTATUS_WIN_STATUS_HV_INVALID_SYNIC_STATE,
++ MD_NTSTATUS_WIN_STATUS_HV_OBJECT_IN_USE,
++ MD_NTSTATUS_WIN_STATUS_HV_INVALID_PROXIMITY_DOMAIN_INFO,
++ MD_NTSTATUS_WIN_STATUS_HV_NO_DATA,
++ MD_NTSTATUS_WIN_STATUS_HV_INACTIVE,
++ MD_NTSTATUS_WIN_STATUS_HV_NO_RESOURCES,
++ MD_NTSTATUS_WIN_STATUS_HV_FEATURE_UNAVAILABLE,
++ MD_NTSTATUS_WIN_STATUS_HV_INSUFFICIENT_BUFFER,
++ MD_NTSTATUS_WIN_STATUS_HV_INSUFFICIENT_DEVICE_DOMAINS,
++ MD_NTSTATUS_WIN_STATUS_HV_CPUID_FEATURE_VALIDATION_ERROR,
++ MD_NTSTATUS_WIN_STATUS_HV_CPUID_XSAVE_FEATURE_VALIDATION_ERROR,
++ MD_NTSTATUS_WIN_STATUS_HV_PROCESSOR_STARTUP_TIMEOUT,
++ MD_NTSTATUS_WIN_STATUS_HV_SMX_ENABLED,
++ MD_NTSTATUS_WIN_STATUS_HV_INVALID_LP_INDEX,
++ MD_NTSTATUS_WIN_STATUS_HV_INVALID_REGISTER_VALUE,
++ MD_NTSTATUS_WIN_STATUS_HV_INVALID_VTL_STATE,
++ MD_NTSTATUS_WIN_STATUS_HV_NX_NOT_DETECTED,
++ MD_NTSTATUS_WIN_STATUS_HV_INVALID_DEVICE_ID,
++ MD_NTSTATUS_WIN_STATUS_HV_INVALID_DEVICE_STATE,
++ MD_NTSTATUS_WIN_STATUS_HV_PAGE_REQUEST_INVALID,
++ MD_NTSTATUS_WIN_STATUS_HV_INVALID_CPU_GROUP_ID,
++ MD_NTSTATUS_WIN_STATUS_HV_INVALID_CPU_GROUP_STATE,
++ MD_NTSTATUS_WIN_STATUS_HV_OPERATION_FAILED,
++ MD_NTSTATUS_WIN_STATUS_HV_NOT_ALLOWED_WITH_NESTED_VIRT_ACTIVE,
++ MD_NTSTATUS_WIN_STATUS_HV_INSUFFICIENT_ROOT_MEMORY,
++ MD_NTSTATUS_WIN_STATUS_HV_EVENT_BUFFER_ALREADY_FREED,
++ MD_NTSTATUS_WIN_STATUS_HV_INSUFFICIENT_CONTIGUOUS_MEMORY,
++ MD_NTSTATUS_WIN_STATUS_HV_NOT_PRESENT,
++ MD_NTSTATUS_WIN_STATUS_IPSEC_BAD_SPI,
++ MD_NTSTATUS_WIN_STATUS_IPSEC_SA_LIFETIME_EXPIRED,
++ MD_NTSTATUS_WIN_STATUS_IPSEC_WRONG_SA,
++ MD_NTSTATUS_WIN_STATUS_IPSEC_REPLAY_CHECK_FAILED,
++ MD_NTSTATUS_WIN_STATUS_IPSEC_INVALID_PACKET,
++ MD_NTSTATUS_WIN_STATUS_IPSEC_INTEGRITY_CHECK_FAILED,
++ MD_NTSTATUS_WIN_STATUS_IPSEC_CLEAR_TEXT_DROP,
++ MD_NTSTATUS_WIN_STATUS_IPSEC_AUTH_FIREWALL_DROP,
++ MD_NTSTATUS_WIN_STATUS_IPSEC_THROTTLE_DROP,
++ MD_NTSTATUS_WIN_STATUS_IPSEC_DOSP_BLOCK,
++ MD_NTSTATUS_WIN_STATUS_IPSEC_DOSP_RECEIVED_MULTICAST,
++ MD_NTSTATUS_WIN_STATUS_IPSEC_DOSP_INVALID_PACKET,
++ MD_NTSTATUS_WIN_STATUS_IPSEC_DOSP_STATE_LOOKUP_FAILED,
++ MD_NTSTATUS_WIN_STATUS_IPSEC_DOSP_MAX_ENTRIES,
++ MD_NTSTATUS_WIN_STATUS_IPSEC_DOSP_KEYMOD_NOT_ALLOWED,
++ MD_NTSTATUS_WIN_STATUS_IPSEC_DOSP_MAX_PER_IP_RATELIMIT_QUEUES,
++ MD_NTSTATUS_WIN_STATUS_VID_DUPLICATE_HANDLER,
++ MD_NTSTATUS_WIN_STATUS_VID_TOO_MANY_HANDLERS,
++ MD_NTSTATUS_WIN_STATUS_VID_QUEUE_FULL,
++ MD_NTSTATUS_WIN_STATUS_VID_HANDLER_NOT_PRESENT,
++ MD_NTSTATUS_WIN_STATUS_VID_INVALID_OBJECT_NAME,
++ MD_NTSTATUS_WIN_STATUS_VID_PARTITION_NAME_TOO_LONG,
++ MD_NTSTATUS_WIN_STATUS_VID_MESSAGE_QUEUE_NAME_TOO_LONG,
++ MD_NTSTATUS_WIN_STATUS_VID_PARTITION_ALREADY_EXISTS,
++ MD_NTSTATUS_WIN_STATUS_VID_PARTITION_DOES_NOT_EXIST,
++ MD_NTSTATUS_WIN_STATUS_VID_PARTITION_NAME_NOT_FOUND,
++ MD_NTSTATUS_WIN_STATUS_VID_MESSAGE_QUEUE_ALREADY_EXISTS,
++ MD_NTSTATUS_WIN_STATUS_VID_EXCEEDED_MBP_ENTRY_MAP_LIMIT,
++ MD_NTSTATUS_WIN_STATUS_VID_MB_STILL_REFERENCED,
++ MD_NTSTATUS_WIN_STATUS_VID_CHILD_GPA_PAGE_SET_CORRUPTED,
++ MD_NTSTATUS_WIN_STATUS_VID_INVALID_NUMA_SETTINGS,
++ MD_NTSTATUS_WIN_STATUS_VID_INVALID_NUMA_NODE_INDEX,
++ MD_NTSTATUS_WIN_STATUS_VID_NOTIFICATION_QUEUE_ALREADY_ASSOCIATED,
++ MD_NTSTATUS_WIN_STATUS_VID_INVALID_MEMORY_BLOCK_HANDLE,
++ MD_NTSTATUS_WIN_STATUS_VID_PAGE_RANGE_OVERFLOW,
++ MD_NTSTATUS_WIN_STATUS_VID_INVALID_MESSAGE_QUEUE_HANDLE,
++ MD_NTSTATUS_WIN_STATUS_VID_INVALID_GPA_RANGE_HANDLE,
++ MD_NTSTATUS_WIN_STATUS_VID_NO_MEMORY_BLOCK_NOTIFICATION_QUEUE,
++ MD_NTSTATUS_WIN_STATUS_VID_MEMORY_BLOCK_LOCK_COUNT_EXCEEDED,
++ MD_NTSTATUS_WIN_STATUS_VID_INVALID_PPM_HANDLE,
++ MD_NTSTATUS_WIN_STATUS_VID_MBPS_ARE_LOCKED,
++ MD_NTSTATUS_WIN_STATUS_VID_MESSAGE_QUEUE_CLOSED,
++ MD_NTSTATUS_WIN_STATUS_VID_VIRTUAL_PROCESSOR_LIMIT_EXCEEDED,
++ MD_NTSTATUS_WIN_STATUS_VID_STOP_PENDING,
++ MD_NTSTATUS_WIN_STATUS_VID_INVALID_PROCESSOR_STATE,
++ MD_NTSTATUS_WIN_STATUS_VID_EXCEEDED_KM_CONTEXT_COUNT_LIMIT,
++ MD_NTSTATUS_WIN_STATUS_VID_KM_INTERFACE_ALREADY_INITIALIZED,
++ MD_NTSTATUS_WIN_STATUS_VID_MB_PROPERTY_ALREADY_SET_RESET,
++ MD_NTSTATUS_WIN_STATUS_VID_MMIO_RANGE_DESTROYED,
++ MD_NTSTATUS_WIN_STATUS_VID_INVALID_CHILD_GPA_PAGE_SET,
++ MD_NTSTATUS_WIN_STATUS_VID_RESERVE_PAGE_SET_IS_BEING_USED,
++ MD_NTSTATUS_WIN_STATUS_VID_RESERVE_PAGE_SET_TOO_SMALL,
++ MD_NTSTATUS_WIN_STATUS_VID_MBP_ALREADY_LOCKED_USING_RESERVED_PAGE,
++ MD_NTSTATUS_WIN_STATUS_VID_MBP_COUNT_EXCEEDED_LIMIT,
++ MD_NTSTATUS_WIN_STATUS_VID_SAVED_STATE_CORRUPT,
++ MD_NTSTATUS_WIN_STATUS_VID_SAVED_STATE_UNRECOGNIZED_ITEM,
++ MD_NTSTATUS_WIN_STATUS_VID_SAVED_STATE_INCOMPATIBLE,
++ MD_NTSTATUS_WIN_STATUS_VID_VTL_ACCESS_DENIED,
++ MD_NTSTATUS_WIN_STATUS_VOLMGR_DATABASE_FULL,
++ MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_CONFIGURATION_CORRUPTED,
++ MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_CONFIGURATION_NOT_IN_SYNC,
++ MD_NTSTATUS_WIN_STATUS_VOLMGR_PACK_CONFIG_UPDATE_FAILED,
++ MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_CONTAINS_NON_SIMPLE_VOLUME,
++ MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_DUPLICATE,
++ MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_DYNAMIC,
++ MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_ID_INVALID,
++ MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_INVALID,
++ MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_LAST_VOTER,
++ MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_LAYOUT_INVALID,
++ MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_LAYOUT_NON_BASIC_BETWEEN_BASIC_PARTITIONS,
++ MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_LAYOUT_NOT_CYLINDER_ALIGNED,
++ MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_LAYOUT_PARTITIONS_TOO_SMALL,
++ MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_LAYOUT_PRIMARY_BETWEEN_LOGICAL_PARTITIONS,
++ MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_LAYOUT_TOO_MANY_PARTITIONS,
++ MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_MISSING,
++ MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_NOT_EMPTY,
++ MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_NOT_ENOUGH_SPACE,
++ MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_REVECTORING_FAILED,
++ MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_SECTOR_SIZE_INVALID,
++ MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_SET_NOT_CONTAINED,
++ MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_USED_BY_MULTIPLE_MEMBERS,
++ MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_USED_BY_MULTIPLE_PLEXES,
++ MD_NTSTATUS_WIN_STATUS_VOLMGR_DYNAMIC_DISK_NOT_SUPPORTED,
++ MD_NTSTATUS_WIN_STATUS_VOLMGR_EXTENT_ALREADY_USED,
++ MD_NTSTATUS_WIN_STATUS_VOLMGR_EXTENT_NOT_CONTIGUOUS,
++ MD_NTSTATUS_WIN_STATUS_VOLMGR_EXTENT_NOT_IN_PUBLIC_REGION,
++ MD_NTSTATUS_WIN_STATUS_VOLMGR_EXTENT_NOT_SECTOR_ALIGNED,
++ MD_NTSTATUS_WIN_STATUS_VOLMGR_EXTENT_OVERLAPS_EBR_PARTITION,
++ MD_NTSTATUS_WIN_STATUS_VOLMGR_EXTENT_VOLUME_LENGTHS_DO_NOT_MATCH,
++ MD_NTSTATUS_WIN_STATUS_VOLMGR_FAULT_TOLERANT_NOT_SUPPORTED,
++ MD_NTSTATUS_WIN_STATUS_VOLMGR_INTERLEAVE_LENGTH_INVALID,
++ MD_NTSTATUS_WIN_STATUS_VOLMGR_MAXIMUM_REGISTERED_USERS,
++ MD_NTSTATUS_WIN_STATUS_VOLMGR_MEMBER_IN_SYNC,
++ MD_NTSTATUS_WIN_STATUS_VOLMGR_MEMBER_INDEX_DUPLICATE,
++ MD_NTSTATUS_WIN_STATUS_VOLMGR_MEMBER_INDEX_INVALID,
++ MD_NTSTATUS_WIN_STATUS_VOLMGR_MEMBER_MISSING,
++ MD_NTSTATUS_WIN_STATUS_VOLMGR_MEMBER_NOT_DETACHED,
++ MD_NTSTATUS_WIN_STATUS_VOLMGR_MEMBER_REGENERATING,
++ MD_NTSTATUS_WIN_STATUS_VOLMGR_ALL_DISKS_FAILED,
++ MD_NTSTATUS_WIN_STATUS_VOLMGR_NO_REGISTERED_USERS,
++ MD_NTSTATUS_WIN_STATUS_VOLMGR_NO_SUCH_USER,
++ MD_NTSTATUS_WIN_STATUS_VOLMGR_NOTIFICATION_RESET,
++ MD_NTSTATUS_WIN_STATUS_VOLMGR_NUMBER_OF_MEMBERS_INVALID,
++ MD_NTSTATUS_WIN_STATUS_VOLMGR_NUMBER_OF_PLEXES_INVALID,
++ MD_NTSTATUS_WIN_STATUS_VOLMGR_PACK_DUPLICATE,
++ MD_NTSTATUS_WIN_STATUS_VOLMGR_PACK_ID_INVALID,
++ MD_NTSTATUS_WIN_STATUS_VOLMGR_PACK_INVALID,
++ MD_NTSTATUS_WIN_STATUS_VOLMGR_PACK_NAME_INVALID,
++ MD_NTSTATUS_WIN_STATUS_VOLMGR_PACK_OFFLINE,
++ MD_NTSTATUS_WIN_STATUS_VOLMGR_PACK_HAS_QUORUM,
++ MD_NTSTATUS_WIN_STATUS_VOLMGR_PACK_WITHOUT_QUORUM,
++ MD_NTSTATUS_WIN_STATUS_VOLMGR_PARTITION_STYLE_INVALID,
++ MD_NTSTATUS_WIN_STATUS_VOLMGR_PARTITION_UPDATE_FAILED,
++ MD_NTSTATUS_WIN_STATUS_VOLMGR_PLEX_IN_SYNC,
++ MD_NTSTATUS_WIN_STATUS_VOLMGR_PLEX_INDEX_DUPLICATE,
++ MD_NTSTATUS_WIN_STATUS_VOLMGR_PLEX_INDEX_INVALID,
++ MD_NTSTATUS_WIN_STATUS_VOLMGR_PLEX_LAST_ACTIVE,
++ MD_NTSTATUS_WIN_STATUS_VOLMGR_PLEX_MISSING,
++ MD_NTSTATUS_WIN_STATUS_VOLMGR_PLEX_REGENERATING,
++ MD_NTSTATUS_WIN_STATUS_VOLMGR_PLEX_TYPE_INVALID,
++ MD_NTSTATUS_WIN_STATUS_VOLMGR_PLEX_NOT_RAID5,
++ MD_NTSTATUS_WIN_STATUS_VOLMGR_PLEX_NOT_SIMPLE,
++ MD_NTSTATUS_WIN_STATUS_VOLMGR_STRUCTURE_SIZE_INVALID,
++ MD_NTSTATUS_WIN_STATUS_VOLMGR_TOO_MANY_NOTIFICATION_REQUESTS,
++ MD_NTSTATUS_WIN_STATUS_VOLMGR_TRANSACTION_IN_PROGRESS,
++ MD_NTSTATUS_WIN_STATUS_VOLMGR_UNEXPECTED_DISK_LAYOUT_CHANGE,
++ MD_NTSTATUS_WIN_STATUS_VOLMGR_VOLUME_CONTAINS_MISSING_DISK,
++ MD_NTSTATUS_WIN_STATUS_VOLMGR_VOLUME_ID_INVALID,
++ MD_NTSTATUS_WIN_STATUS_VOLMGR_VOLUME_LENGTH_INVALID,
++ MD_NTSTATUS_WIN_STATUS_VOLMGR_VOLUME_LENGTH_NOT_SECTOR_SIZE_MULTIPLE,
++ MD_NTSTATUS_WIN_STATUS_VOLMGR_VOLUME_NOT_MIRRORED,
++ MD_NTSTATUS_WIN_STATUS_VOLMGR_VOLUME_NOT_RETAINED,
++ MD_NTSTATUS_WIN_STATUS_VOLMGR_VOLUME_OFFLINE,
++ MD_NTSTATUS_WIN_STATUS_VOLMGR_VOLUME_RETAINED,
++ MD_NTSTATUS_WIN_STATUS_VOLMGR_NUMBER_OF_EXTENTS_INVALID,
++ MD_NTSTATUS_WIN_STATUS_VOLMGR_DIFFERENT_SECTOR_SIZE,
++ MD_NTSTATUS_WIN_STATUS_VOLMGR_BAD_BOOT_DISK,
++ MD_NTSTATUS_WIN_STATUS_VOLMGR_PACK_CONFIG_OFFLINE,
++ MD_NTSTATUS_WIN_STATUS_VOLMGR_PACK_CONFIG_ONLINE,
++ MD_NTSTATUS_WIN_STATUS_VOLMGR_NOT_PRIMARY_PACK,
++ MD_NTSTATUS_WIN_STATUS_VOLMGR_PACK_LOG_UPDATE_FAILED,
++ MD_NTSTATUS_WIN_STATUS_VOLMGR_NUMBER_OF_DISKS_IN_PLEX_INVALID,
++ MD_NTSTATUS_WIN_STATUS_VOLMGR_NUMBER_OF_DISKS_IN_MEMBER_INVALID,
++ MD_NTSTATUS_WIN_STATUS_VOLMGR_VOLUME_MIRRORED,
++ MD_NTSTATUS_WIN_STATUS_VOLMGR_PLEX_NOT_SIMPLE_SPANNED,
++ MD_NTSTATUS_WIN_STATUS_VOLMGR_NO_VALID_LOG_COPIES,
++ MD_NTSTATUS_WIN_STATUS_VOLMGR_PRIMARY_PACK_PRESENT,
++ MD_NTSTATUS_WIN_STATUS_VOLMGR_NUMBER_OF_DISKS_INVALID,
++ MD_NTSTATUS_WIN_STATUS_VOLMGR_MIRROR_NOT_SUPPORTED,
++ MD_NTSTATUS_WIN_STATUS_VOLMGR_RAID5_NOT_SUPPORTED,
++ MD_NTSTATUS_WIN_STATUS_BCD_TOO_MANY_ELEMENTS,
++ MD_NTSTATUS_WIN_STATUS_VHD_DRIVE_FOOTER_MISSING,
++ MD_NTSTATUS_WIN_STATUS_VHD_DRIVE_FOOTER_CHECKSUM_MISMATCH,
++ MD_NTSTATUS_WIN_STATUS_VHD_DRIVE_FOOTER_CORRUPT,
++ MD_NTSTATUS_WIN_STATUS_VHD_FORMAT_UNKNOWN,
++ MD_NTSTATUS_WIN_STATUS_VHD_FORMAT_UNSUPPORTED_VERSION,
++ MD_NTSTATUS_WIN_STATUS_VHD_SPARSE_HEADER_CHECKSUM_MISMATCH,
++ MD_NTSTATUS_WIN_STATUS_VHD_SPARSE_HEADER_UNSUPPORTED_VERSION,
++ MD_NTSTATUS_WIN_STATUS_VHD_SPARSE_HEADER_CORRUPT,
++ MD_NTSTATUS_WIN_STATUS_VHD_BLOCK_ALLOCATION_FAILURE,
++ MD_NTSTATUS_WIN_STATUS_VHD_BLOCK_ALLOCATION_TABLE_CORRUPT,
++ MD_NTSTATUS_WIN_STATUS_VHD_INVALID_BLOCK_SIZE,
++ MD_NTSTATUS_WIN_STATUS_VHD_BITMAP_MISMATCH,
++ MD_NTSTATUS_WIN_STATUS_VHD_PARENT_VHD_NOT_FOUND,
++ MD_NTSTATUS_WIN_STATUS_VHD_CHILD_PARENT_ID_MISMATCH,
++ MD_NTSTATUS_WIN_STATUS_VHD_CHILD_PARENT_TIMESTAMP_MISMATCH,
++ MD_NTSTATUS_WIN_STATUS_VHD_METADATA_READ_FAILURE,
++ MD_NTSTATUS_WIN_STATUS_VHD_METADATA_WRITE_FAILURE,
++ MD_NTSTATUS_WIN_STATUS_VHD_INVALID_SIZE,
++ MD_NTSTATUS_WIN_STATUS_VHD_INVALID_FILE_SIZE,
++ MD_NTSTATUS_WIN_STATUS_VIRTDISK_PROVIDER_NOT_FOUND,
++ MD_NTSTATUS_WIN_STATUS_VIRTDISK_NOT_VIRTUAL_DISK,
++ MD_NTSTATUS_WIN_STATUS_VHD_PARENT_VHD_ACCESS_DENIED,
++ MD_NTSTATUS_WIN_STATUS_VHD_CHILD_PARENT_SIZE_MISMATCH,
++ MD_NTSTATUS_WIN_STATUS_VHD_DIFFERENCING_CHAIN_CYCLE_DETECTED,
++ MD_NTSTATUS_WIN_STATUS_VHD_DIFFERENCING_CHAIN_ERROR_IN_PARENT,
++ MD_NTSTATUS_WIN_STATUS_VIRTUAL_DISK_LIMITATION,
++ MD_NTSTATUS_WIN_STATUS_VHD_INVALID_TYPE,
++ MD_NTSTATUS_WIN_STATUS_VHD_INVALID_STATE,
++ MD_NTSTATUS_WIN_STATUS_VIRTDISK_UNSUPPORTED_DISK_SECTOR_SIZE,
++ MD_NTSTATUS_WIN_STATUS_VIRTDISK_DISK_ALREADY_OWNED,
++ MD_NTSTATUS_WIN_STATUS_VIRTDISK_DISK_ONLINE_AND_WRITABLE,
++ MD_NTSTATUS_WIN_STATUS_CTLOG_TRACKING_NOT_INITIALIZED,
++ MD_NTSTATUS_WIN_STATUS_CTLOG_LOGFILE_SIZE_EXCEEDED_MAXSIZE,
++ MD_NTSTATUS_WIN_STATUS_CTLOG_VHD_CHANGED_OFFLINE,
++ MD_NTSTATUS_WIN_STATUS_CTLOG_INVALID_TRACKING_STATE,
++ MD_NTSTATUS_WIN_STATUS_CTLOG_INCONSISTENT_TRACKING_FILE,
++ MD_NTSTATUS_WIN_STATUS_VHD_METADATA_FULL,
++ MD_NTSTATUS_WIN_STATUS_VHD_INVALID_CHANGE_TRACKING_ID,
++ MD_NTSTATUS_WIN_STATUS_VHD_CHANGE_TRACKING_DISABLED,
++ MD_NTSTATUS_WIN_STATUS_VHD_MISSING_CHANGE_TRACKING_INFORMATION,
++ MD_NTSTATUS_WIN_STATUS_VHD_RESIZE_WOULD_TRUNCATE_DATA,
++ MD_NTSTATUS_WIN_STATUS_VHD_COULD_NOT_COMPUTE_MINIMUM_VIRTUAL_SIZE,
++ MD_NTSTATUS_WIN_STATUS_VHD_ALREADY_AT_OR_BELOW_MINIMUM_VIRTUAL_SIZE,
++ MD_NTSTATUS_WIN_STATUS_RKF_KEY_NOT_FOUND,
++ MD_NTSTATUS_WIN_STATUS_RKF_DUPLICATE_KEY,
++ MD_NTSTATUS_WIN_STATUS_RKF_BLOB_FULL,
++ MD_NTSTATUS_WIN_STATUS_RKF_STORE_FULL,
++ MD_NTSTATUS_WIN_STATUS_RKF_FILE_BLOCKED,
++ MD_NTSTATUS_WIN_STATUS_RKF_ACTIVE_KEY,
++ MD_NTSTATUS_WIN_STATUS_RDBSS_RESTART_OPERATION,
++ MD_NTSTATUS_WIN_STATUS_RDBSS_CONTINUE_OPERATION,
++ MD_NTSTATUS_WIN_STATUS_RDBSS_POST_OPERATION,
++ MD_NTSTATUS_WIN_STATUS_RDBSS_RETRY_LOOKUP,
++ MD_NTSTATUS_WIN_STATUS_BTH_ATT_INVALID_HANDLE,
++ MD_NTSTATUS_WIN_STATUS_BTH_ATT_READ_NOT_PERMITTED,
++ MD_NTSTATUS_WIN_STATUS_BTH_ATT_WRITE_NOT_PERMITTED,
++ MD_NTSTATUS_WIN_STATUS_BTH_ATT_INVALID_PDU,
++ MD_NTSTATUS_WIN_STATUS_BTH_ATT_INSUFFICIENT_AUTHENTICATION,
++ MD_NTSTATUS_WIN_STATUS_BTH_ATT_REQUEST_NOT_SUPPORTED,
++ MD_NTSTATUS_WIN_STATUS_BTH_ATT_INVALID_OFFSET,
++ MD_NTSTATUS_WIN_STATUS_BTH_ATT_INSUFFICIENT_AUTHORIZATION,
++ MD_NTSTATUS_WIN_STATUS_BTH_ATT_PREPARE_QUEUE_FULL,
++ MD_NTSTATUS_WIN_STATUS_BTH_ATT_ATTRIBUTE_NOT_FOUND,
++ MD_NTSTATUS_WIN_STATUS_BTH_ATT_ATTRIBUTE_NOT_LONG,
++ MD_NTSTATUS_WIN_STATUS_BTH_ATT_INSUFFICIENT_ENCRYPTION_KEY_SIZE,
++ MD_NTSTATUS_WIN_STATUS_BTH_ATT_INVALID_ATTRIBUTE_VALUE_LENGTH,
++ MD_NTSTATUS_WIN_STATUS_BTH_ATT_UNLIKELY,
++ MD_NTSTATUS_WIN_STATUS_BTH_ATT_INSUFFICIENT_ENCRYPTION,
++ MD_NTSTATUS_WIN_STATUS_BTH_ATT_UNSUPPORTED_GROUP_TYPE,
++ MD_NTSTATUS_WIN_STATUS_BTH_ATT_INSUFFICIENT_RESOURCES,
++ MD_NTSTATUS_WIN_STATUS_BTH_ATT_UNKNOWN_ERROR,
++ MD_NTSTATUS_WIN_STATUS_SECUREBOOT_ROLLBACK_DETECTED,
++ MD_NTSTATUS_WIN_STATUS_SECUREBOOT_POLICY_VIOLATION,
++ MD_NTSTATUS_WIN_STATUS_SECUREBOOT_INVALID_POLICY,
++ MD_NTSTATUS_WIN_STATUS_SECUREBOOT_POLICY_PUBLISHER_NOT_FOUND,
++ MD_NTSTATUS_WIN_STATUS_SECUREBOOT_POLICY_NOT_SIGNED,
++ MD_NTSTATUS_WIN_STATUS_SECUREBOOT_FILE_REPLACED,
++ MD_NTSTATUS_WIN_STATUS_SECUREBOOT_POLICY_NOT_AUTHORIZED,
++ MD_NTSTATUS_WIN_STATUS_SECUREBOOT_POLICY_UNKNOWN,
++ MD_NTSTATUS_WIN_STATUS_SECUREBOOT_POLICY_MISSING_ANTIROLLBACKVERSION,
++ MD_NTSTATUS_WIN_STATUS_SECUREBOOT_PLATFORM_ID_MISMATCH,
++ MD_NTSTATUS_WIN_STATUS_SECUREBOOT_POLICY_ROLLBACK_DETECTED,
++ MD_NTSTATUS_WIN_STATUS_SECUREBOOT_POLICY_UPGRADE_MISMATCH,
++ MD_NTSTATUS_WIN_STATUS_SECUREBOOT_REQUIRED_POLICY_FILE_MISSING,
++ MD_NTSTATUS_WIN_STATUS_SECUREBOOT_NOT_BASE_POLICY,
++ MD_NTSTATUS_WIN_STATUS_SECUREBOOT_NOT_SUPPLEMENTAL_POLICY,
++ MD_NTSTATUS_WIN_STATUS_AUDIO_ENGINE_NODE_NOT_FOUND,
++ MD_NTSTATUS_WIN_STATUS_HDAUDIO_EMPTY_CONNECTION_LIST,
++ MD_NTSTATUS_WIN_STATUS_HDAUDIO_CONNECTION_LIST_NOT_SUPPORTED,
++ MD_NTSTATUS_WIN_STATUS_HDAUDIO_NO_LOGICAL_DEVICES_CREATED,
++ MD_NTSTATUS_WIN_STATUS_HDAUDIO_NULL_LINKED_LIST_ENTRY,
++ MD_NTSTATUS_WIN_STATUS_VSM_NOT_INITIALIZED,
++ MD_NTSTATUS_WIN_STATUS_VSM_DMA_PROTECTION_NOT_IN_USE,
++ MD_NTSTATUS_WIN_STATUS_VOLSNAP_BOOTFILE_NOT_VALID,
++ MD_NTSTATUS_WIN_STATUS_VOLSNAP_ACTIVATION_TIMEOUT,
++ MD_NTSTATUS_WIN_STATUS_IO_PREEMPTED,
++ MD_NTSTATUS_WIN_STATUS_SVHDX_ERROR_STORED,
++ MD_NTSTATUS_WIN_STATUS_SVHDX_ERROR_NOT_AVAILABLE,
++ MD_NTSTATUS_WIN_STATUS_SVHDX_UNIT_ATTENTION_AVAILABLE,
++ MD_NTSTATUS_WIN_STATUS_SVHDX_UNIT_ATTENTION_CAPACITY_DATA_CHANGED,
++ MD_NTSTATUS_WIN_STATUS_SVHDX_UNIT_ATTENTION_RESERVATIONS_PREEMPTED,
++ MD_NTSTATUS_WIN_STATUS_SVHDX_UNIT_ATTENTION_RESERVATIONS_RELEASED,
++ MD_NTSTATUS_WIN_STATUS_SVHDX_UNIT_ATTENTION_REGISTRATIONS_PREEMPTED,
++ MD_NTSTATUS_WIN_STATUS_SVHDX_UNIT_ATTENTION_OPERATING_DEFINITION_CHANGED,
++ MD_NTSTATUS_WIN_STATUS_SVHDX_RESERVATION_CONFLICT,
++ MD_NTSTATUS_WIN_STATUS_SVHDX_WRONG_FILE_TYPE,
++ MD_NTSTATUS_WIN_STATUS_SVHDX_VERSION_MISMATCH,
++ MD_NTSTATUS_WIN_STATUS_VHD_SHARED,
++ MD_NTSTATUS_WIN_STATUS_SVHDX_NO_INITIATOR,
++ MD_NTSTATUS_WIN_STATUS_VHDSET_BACKING_STORAGE_NOT_FOUND,
++ MD_NTSTATUS_WIN_STATUS_SMB_NO_PREAUTH_INTEGRITY_HASH_OVERLAP,
++ MD_NTSTATUS_WIN_STATUS_SMB_BAD_CLUSTER_DIALECT,
++ MD_NTSTATUS_WIN_STATUS_SMB_GUEST_LOGON_BLOCKED,
++ MD_NTSTATUS_WIN_STATUS_SPACES_FAULT_DOMAIN_TYPE_INVALID,
++ MD_NTSTATUS_WIN_STATUS_SPACES_RESILIENCY_TYPE_INVALID,
++ MD_NTSTATUS_WIN_STATUS_SPACES_DRIVE_SECTOR_SIZE_INVALID,
++ MD_NTSTATUS_WIN_STATUS_SPACES_DRIVE_REDUNDANCY_INVALID,
++ MD_NTSTATUS_WIN_STATUS_SPACES_NUMBER_OF_DATA_COPIES_INVALID,
++ MD_NTSTATUS_WIN_STATUS_SPACES_INTERLEAVE_LENGTH_INVALID,
++ MD_NTSTATUS_WIN_STATUS_SPACES_NUMBER_OF_COLUMNS_INVALID,
++ MD_NTSTATUS_WIN_STATUS_SPACES_NOT_ENOUGH_DRIVES,
++ MD_NTSTATUS_WIN_STATUS_SPACES_EXTENDED_ERROR,
++ MD_NTSTATUS_WIN_STATUS_SPACES_PROVISIONING_TYPE_INVALID,
++ MD_NTSTATUS_WIN_STATUS_SPACES_ALLOCATION_SIZE_INVALID,
++ MD_NTSTATUS_WIN_STATUS_SPACES_ENCLOSURE_AWARE_INVALID,
++ MD_NTSTATUS_WIN_STATUS_SPACES_WRITE_CACHE_SIZE_INVALID,
++ MD_NTSTATUS_WIN_STATUS_SPACES_NUMBER_OF_GROUPS_INVALID,
++ MD_NTSTATUS_WIN_STATUS_SPACES_DRIVE_OPERATIONAL_STATE_INVALID,
++ MD_NTSTATUS_WIN_STATUS_SPACES_UPDATE_COLUMN_STATE,
++ MD_NTSTATUS_WIN_STATUS_SPACES_MAP_REQUIRED,
++ MD_NTSTATUS_WIN_STATUS_SPACES_UNSUPPORTED_VERSION,
++ MD_NTSTATUS_WIN_STATUS_SPACES_CORRUPT_METADATA,
++ MD_NTSTATUS_WIN_STATUS_SPACES_DRT_FULL,
++ MD_NTSTATUS_WIN_STATUS_SPACES_INCONSISTENCY,
++ MD_NTSTATUS_WIN_STATUS_SPACES_LOG_NOT_READY,
++ MD_NTSTATUS_WIN_STATUS_SPACES_NO_REDUNDANCY,
++ MD_NTSTATUS_WIN_STATUS_SPACES_DRIVE_NOT_READY,
++ MD_NTSTATUS_WIN_STATUS_SPACES_DRIVE_SPLIT,
++ MD_NTSTATUS_WIN_STATUS_SPACES_DRIVE_LOST_DATA,
++ MD_NTSTATUS_WIN_STATUS_SPACES_ENTRY_INCOMPLETE,
++ MD_NTSTATUS_WIN_STATUS_SPACES_ENTRY_INVALID,
++ MD_NTSTATUS_WIN_STATUS_SPACES_MARK_DIRTY,
++ MD_NTSTATUS_WIN_STATUS_SECCORE_INVALID_COMMAND,
++ MD_NTSTATUS_WIN_STATUS_SYSTEM_INTEGRITY_ROLLBACK_DETECTED,
++ MD_NTSTATUS_WIN_STATUS_SYSTEM_INTEGRITY_POLICY_VIOLATION,
++ MD_NTSTATUS_WIN_STATUS_SYSTEM_INTEGRITY_INVALID_POLICY,
++ MD_NTSTATUS_WIN_STATUS_SYSTEM_INTEGRITY_POLICY_NOT_SIGNED,
++ MD_NTSTATUS_WIN_STATUS_SYSTEM_INTEGRITY_TOO_MANY_POLICIES,
++ MD_NTSTATUS_WIN_STATUS_SYSTEM_INTEGRITY_SUPPLEMENTAL_POLICY_NOT_AUTHORIZED,
++ MD_NTSTATUS_WIN_STATUS_NO_APPLICABLE_APP_LICENSES_FOUND,
++ MD_NTSTATUS_WIN_STATUS_CLIP_LICENSE_NOT_FOUND,
++ MD_NTSTATUS_WIN_STATUS_CLIP_DEVICE_LICENSE_MISSING,
++ MD_NTSTATUS_WIN_STATUS_CLIP_LICENSE_INVALID_SIGNATURE,
++ MD_NTSTATUS_WIN_STATUS_CLIP_KEYHOLDER_LICENSE_MISSING_OR_INVALID,
++ MD_NTSTATUS_WIN_STATUS_CLIP_LICENSE_EXPIRED,
++ MD_NTSTATUS_WIN_STATUS_CLIP_LICENSE_SIGNED_BY_UNKNOWN_SOURCE,
++ MD_NTSTATUS_WIN_STATUS_CLIP_LICENSE_NOT_SIGNED,
++ MD_NTSTATUS_WIN_STATUS_CLIP_LICENSE_HARDWARE_ID_OUT_OF_TOLERANCE,
++ MD_NTSTATUS_WIN_STATUS_CLIP_LICENSE_DEVICE_ID_MISMATCH,
++ MD_NTSTATUS_WIN_STATUS_PLATFORM_MANIFEST_NOT_AUTHORIZED,
++ MD_NTSTATUS_WIN_STATUS_PLATFORM_MANIFEST_INVALID,
++ MD_NTSTATUS_WIN_STATUS_PLATFORM_MANIFEST_FILE_NOT_AUTHORIZED,
++ MD_NTSTATUS_WIN_STATUS_PLATFORM_MANIFEST_CATALOG_NOT_AUTHORIZED,
++ MD_NTSTATUS_WIN_STATUS_PLATFORM_MANIFEST_BINARY_ID_NOT_FOUND,
++ MD_NTSTATUS_WIN_STATUS_PLATFORM_MANIFEST_NOT_ACTIVE,
++ MD_NTSTATUS_WIN_STATUS_PLATFORM_MANIFEST_NOT_SIGNED,
++ MD_NTSTATUS_WIN_STATUS_APPEXEC_CONDITION_NOT_SATISFIED,
++ MD_NTSTATUS_WIN_STATUS_APPEXEC_HANDLE_INVALIDATED,
++ MD_NTSTATUS_WIN_STATUS_APPEXEC_INVALID_HOST_GENERATION,
++ MD_NTSTATUS_WIN_STATUS_APPEXEC_UNEXPECTED_PROCESS_REGISTRATION,
++ MD_NTSTATUS_WIN_STATUS_APPEXEC_INVALID_HOST_STATE,
++ MD_NTSTATUS_WIN_STATUS_APPEXEC_NO_DONOR,
++ MD_NTSTATUS_WIN_STATUS_APPEXEC_HOST_ID_MISMATCH,
++ MD_NTSTATUS_WIN_STATUS_APPEXEC_UNKNOWN_USER,
++};
++
++// The content of this array was created from ntstatus.h in the 10 SDK
++// (version 10.0.19041.0) with
++//
++// egrep '#define [A-Z_0-9]+\s+\(\(NTSTATUS\)0x[048C][0-9A-F]+L\)' ntstatus.h
++// | tr -d '\r'
++// | sed -r 's@#define ([A-Z_0-9]+)\s+\(\(NTSTATUS\)(0x[048C][0-9A-F]+)L\).*@\2 \1@'
++// | sort
++// | sed -r 's@(0x[048C][0-9A-F]+) ([A-Z_0-9]+)@ "\2",@'
++//
++// With easy copy to clipboard with
++// | xclip -selection c # on linux
++// | clip # on windows
++// | pbcopy # on mac
++static const char* kNTStatusStrings[] = {
++ "STATUS_SUCCESS",
++ "STATUS_WAIT_0",
++ "STATUS_WAIT_1",
++ "STATUS_WAIT_2",
++ "STATUS_WAIT_3",
++ "STATUS_WAIT_63",
++ "STATUS_ABANDONED",
++ "STATUS_ABANDONED_WAIT_0",
++ "STATUS_ABANDONED_WAIT_63",
++ "STATUS_USER_APC",
++ "STATUS_ALREADY_COMPLETE",
++ "STATUS_KERNEL_APC",
++ "STATUS_ALERTED",
++ "STATUS_TIMEOUT",
++ "STATUS_PENDING",
++ "STATUS_REPARSE",
++ "STATUS_MORE_ENTRIES",
++ "STATUS_NOT_ALL_ASSIGNED",
++ "STATUS_SOME_NOT_MAPPED",
++ "STATUS_OPLOCK_BREAK_IN_PROGRESS",
++ "STATUS_VOLUME_MOUNTED",
++ "STATUS_RXACT_COMMITTED",
++ "STATUS_NOTIFY_CLEANUP",
++ "STATUS_NOTIFY_ENUM_DIR",
++ "STATUS_NO_QUOTAS_FOR_ACCOUNT",
++ "STATUS_PRIMARY_TRANSPORT_CONNECT_FAILED",
++ "STATUS_PAGE_FAULT_TRANSITION",
++ "STATUS_PAGE_FAULT_DEMAND_ZERO",
++ "STATUS_PAGE_FAULT_COPY_ON_WRITE",
++ "STATUS_PAGE_FAULT_GUARD_PAGE",
++ "STATUS_PAGE_FAULT_PAGING_FILE",
++ "STATUS_CACHE_PAGE_LOCKED",
++ "STATUS_CRASH_DUMP",
++ "STATUS_BUFFER_ALL_ZEROS",
++ "STATUS_REPARSE_OBJECT",
++ "STATUS_RESOURCE_REQUIREMENTS_CHANGED",
++ "STATUS_TRANSLATION_COMPLETE",
++ "STATUS_DS_MEMBERSHIP_EVALUATED_LOCALLY",
++ "STATUS_NOTHING_TO_TERMINATE",
++ "STATUS_PROCESS_NOT_IN_JOB",
++ "STATUS_PROCESS_IN_JOB",
++ "STATUS_VOLSNAP_HIBERNATE_READY",
++ "STATUS_FSFILTER_OP_COMPLETED_SUCCESSFULLY",
++ "STATUS_INTERRUPT_VECTOR_ALREADY_CONNECTED",
++ "STATUS_INTERRUPT_STILL_CONNECTED",
++ "STATUS_PROCESS_CLONED",
++ "STATUS_FILE_LOCKED_WITH_ONLY_READERS",
++ "STATUS_FILE_LOCKED_WITH_WRITERS",
++ "STATUS_VALID_IMAGE_HASH",
++ "STATUS_VALID_CATALOG_HASH",
++ "STATUS_VALID_STRONG_CODE_HASH",
++ "STATUS_GHOSTED",
++ "STATUS_DATA_OVERWRITTEN",
++ "STATUS_RESOURCEMANAGER_READ_ONLY",
++ "STATUS_RING_PREVIOUSLY_EMPTY",
++ "STATUS_RING_PREVIOUSLY_FULL",
++ "STATUS_RING_PREVIOUSLY_ABOVE_QUOTA",
++ "STATUS_RING_NEWLY_EMPTY",
++ "STATUS_RING_SIGNAL_OPPOSITE_ENDPOINT",
++ "STATUS_OPLOCK_SWITCHED_TO_NEW_HANDLE",
++ "STATUS_OPLOCK_HANDLE_CLOSED",
++ "STATUS_WAIT_FOR_OPLOCK",
++ "STATUS_REPARSE_GLOBAL",
++ "DBG_EXCEPTION_HANDLED",
++ "DBG_CONTINUE",
++ "STATUS_FLT_IO_COMPLETE",
++ "STATUS_RTPM_CONTEXT_CONTINUE",
++ "STATUS_RTPM_CONTEXT_COMPLETE",
++ "STATUS_HV_PENDING_PAGE_REQUESTS",
++ "STATUS_SPACES_REPAIRED",
++ "STATUS_SPACES_PAUSE",
++ "STATUS_SPACES_COMPLETE",
++ "STATUS_SPACES_REDIRECT",
++ "STATUS_OBJECT_NAME_EXISTS",
++ "STATUS_THREAD_WAS_SUSPENDED",
++ "STATUS_WORKING_SET_LIMIT_RANGE",
++ "STATUS_IMAGE_NOT_AT_BASE",
++ "STATUS_RXACT_STATE_CREATED",
++ "STATUS_SEGMENT_NOTIFICATION",
++ "STATUS_LOCAL_USER_SESSION_KEY",
++ "STATUS_BAD_CURRENT_DIRECTORY",
++ "STATUS_SERIAL_MORE_WRITES",
++ "STATUS_REGISTRY_RECOVERED",
++ "STATUS_FT_READ_RECOVERY_FROM_BACKUP",
++ "STATUS_FT_WRITE_RECOVERY",
++ "STATUS_SERIAL_COUNTER_TIMEOUT",
++ "STATUS_NULL_LM_PASSWORD",
++ "STATUS_IMAGE_MACHINE_TYPE_MISMATCH",
++ "STATUS_RECEIVE_PARTIAL",
++ "STATUS_RECEIVE_EXPEDITED",
++ "STATUS_RECEIVE_PARTIAL_EXPEDITED",
++ "STATUS_EVENT_DONE",
++ "STATUS_EVENT_PENDING",
++ "STATUS_CHECKING_FILE_SYSTEM",
++ "STATUS_FATAL_APP_EXIT",
++ "STATUS_PREDEFINED_HANDLE",
++ "STATUS_WAS_UNLOCKED",
++ "STATUS_SERVICE_NOTIFICATION",
++ "STATUS_WAS_LOCKED",
++ "STATUS_LOG_HARD_ERROR",
++ "STATUS_ALREADY_WIN32",
++ "STATUS_WX86_UNSIMULATE",
++ "STATUS_WX86_CONTINUE",
++ "STATUS_WX86_SINGLE_STEP",
++ "STATUS_WX86_BREAKPOINT",
++ "STATUS_WX86_EXCEPTION_CONTINUE",
++ "STATUS_WX86_EXCEPTION_LASTCHANCE",
++ "STATUS_WX86_EXCEPTION_CHAIN",
++ "STATUS_IMAGE_MACHINE_TYPE_MISMATCH_EXE",
++ "STATUS_NO_YIELD_PERFORMED",
++ "STATUS_TIMER_RESUME_IGNORED",
++ "STATUS_ARBITRATION_UNHANDLED",
++ "STATUS_CARDBUS_NOT_SUPPORTED",
++ "STATUS_WX86_CREATEWX86TIB",
++ "STATUS_MP_PROCESSOR_MISMATCH",
++ "STATUS_HIBERNATED",
++ "STATUS_RESUME_HIBERNATION",
++ "STATUS_FIRMWARE_UPDATED",
++ "STATUS_DRIVERS_LEAKING_LOCKED_PAGES",
++ "STATUS_MESSAGE_RETRIEVED",
++ "STATUS_SYSTEM_POWERSTATE_TRANSITION",
++ "STATUS_ALPC_CHECK_COMPLETION_LIST",
++ "STATUS_SYSTEM_POWERSTATE_COMPLEX_TRANSITION",
++ "STATUS_ACCESS_AUDIT_BY_POLICY",
++ "STATUS_ABANDON_HIBERFILE",
++ "STATUS_BIZRULES_NOT_ENABLED",
++ "STATUS_FT_READ_FROM_COPY",
++ "STATUS_IMAGE_AT_DIFFERENT_BASE",
++ "STATUS_PATCH_DEFERRED",
++ "STATUS_WAKE_SYSTEM",
++ "STATUS_DS_SHUTTING_DOWN",
++ "STATUS_DISK_REPAIR_REDIRECTED",
++ "STATUS_SERVICES_FAILED_AUTOSTART",
++ "DBG_REPLY_LATER",
++ "DBG_UNABLE_TO_PROVIDE_HANDLE",
++ "DBG_TERMINATE_THREAD",
++ "DBG_TERMINATE_PROCESS",
++ "DBG_CONTROL_C",
++ "DBG_PRINTEXCEPTION_C",
++ "DBG_RIPEXCEPTION",
++ "DBG_CONTROL_BREAK",
++ "DBG_COMMAND_EXCEPTION",
++ "DBG_PRINTEXCEPTION_WIDE_C",
++ "RPC_NT_UUID_LOCAL_ONLY",
++ "RPC_NT_SEND_INCOMPLETE",
++ "STATUS_CTX_CDM_CONNECT",
++ "STATUS_CTX_CDM_DISCONNECT",
++ "STATUS_SXS_RELEASE_ACTIVATION_CONTEXT",
++ "STATUS_HEURISTIC_DAMAGE_POSSIBLE",
++ "STATUS_RECOVERY_NOT_NEEDED",
++ "STATUS_RM_ALREADY_STARTED",
++ "STATUS_LOG_NO_RESTART",
++ "STATUS_VIDEO_DRIVER_DEBUG_REPORT_REQUEST",
++ "STATUS_GRAPHICS_PARTIAL_DATA_POPULATED",
++ "STATUS_GRAPHICS_SKIP_ALLOCATION_PREPARATION",
++ "STATUS_GRAPHICS_MODE_NOT_PINNED",
++ "STATUS_GRAPHICS_NO_PREFERRED_MODE",
++ "STATUS_GRAPHICS_DATASET_IS_EMPTY",
++ "STATUS_GRAPHICS_NO_MORE_ELEMENTS_IN_DATASET",
++ "STATUS_GRAPHICS_PATH_CONTENT_GEOMETRY_TRANSFORMATION_NOT_PINNED",
++ "STATUS_GRAPHICS_UNKNOWN_CHILD_STATUS",
++ "STATUS_GRAPHICS_LEADLINK_START_DEFERRED",
++ "STATUS_GRAPHICS_POLLING_TOO_FREQUENTLY",
++ "STATUS_GRAPHICS_START_DEFERRED",
++ "STATUS_GRAPHICS_DEPENDABLE_CHILD_STATUS",
++ "STATUS_NDIS_INDICATION_REQUIRED",
++ "STATUS_PCP_UNSUPPORTED_PSS_SALT",
++ "STATUS_GUARD_PAGE_VIOLATION",
++ "STATUS_DATATYPE_MISALIGNMENT",
++ "STATUS_BREAKPOINT",
++ "STATUS_SINGLE_STEP",
++ "STATUS_BUFFER_OVERFLOW",
++ "STATUS_NO_MORE_FILES",
++ "STATUS_WAKE_SYSTEM_DEBUGGER",
++ "STATUS_HANDLES_CLOSED",
++ "STATUS_NO_INHERITANCE",
++ "STATUS_GUID_SUBSTITUTION_MADE",
++ "STATUS_PARTIAL_COPY",
++ "STATUS_DEVICE_PAPER_EMPTY",
++ "STATUS_DEVICE_POWERED_OFF",
++ "STATUS_DEVICE_OFF_LINE",
++ "STATUS_DEVICE_BUSY",
++ "STATUS_NO_MORE_EAS",
++ "STATUS_INVALID_EA_NAME",
++ "STATUS_EA_LIST_INCONSISTENT",
++ "STATUS_INVALID_EA_FLAG",
++ "STATUS_VERIFY_REQUIRED",
++ "STATUS_EXTRANEOUS_INFORMATION",
++ "STATUS_RXACT_COMMIT_NECESSARY",
++ "STATUS_NO_MORE_ENTRIES",
++ "STATUS_FILEMARK_DETECTED",
++ "STATUS_MEDIA_CHANGED",
++ "STATUS_BUS_RESET",
++ "STATUS_END_OF_MEDIA",
++ "STATUS_BEGINNING_OF_MEDIA",
++ "STATUS_MEDIA_CHECK",
++ "STATUS_SETMARK_DETECTED",
++ "STATUS_NO_DATA_DETECTED",
++ "STATUS_REDIRECTOR_HAS_OPEN_HANDLES",
++ "STATUS_SERVER_HAS_OPEN_HANDLES",
++ "STATUS_ALREADY_DISCONNECTED",
++ "STATUS_LONGJUMP",
++ "STATUS_CLEANER_CARTRIDGE_INSTALLED",
++ "STATUS_PLUGPLAY_QUERY_VETOED",
++ "STATUS_UNWIND_CONSOLIDATE",
++ "STATUS_REGISTRY_HIVE_RECOVERED",
++ "STATUS_DLL_MIGHT_BE_INSECURE",
++ "STATUS_DLL_MIGHT_BE_INCOMPATIBLE",
++ "STATUS_STOPPED_ON_SYMLINK",
++ "STATUS_CANNOT_GRANT_REQUESTED_OPLOCK",
++ "STATUS_NO_ACE_CONDITION",
++ "STATUS_DEVICE_SUPPORT_IN_PROGRESS",
++ "STATUS_DEVICE_POWER_CYCLE_REQUIRED",
++ "STATUS_NO_WORK_DONE",
++ "STATUS_RETURN_ADDRESS_HIJACK_ATTEMPT",
++ "STATUS_DEVICE_REQUIRES_CLEANING",
++ "STATUS_DEVICE_DOOR_OPEN",
++ "STATUS_DATA_LOST_REPAIR",
++ "STATUS_GPIO_INTERRUPT_ALREADY_UNMASKED",
++ "STATUS_CLOUD_FILE_PROPERTY_BLOB_CHECKSUM_MISMATCH",
++ "STATUS_CLOUD_FILE_PROPERTY_BLOB_TOO_LARGE",
++ "STATUS_CLOUD_FILE_TOO_MANY_PROPERTY_BLOBS",
++ "DBG_EXCEPTION_NOT_HANDLED",
++ "STATUS_CLUSTER_NODE_ALREADY_UP",
++ "STATUS_CLUSTER_NODE_ALREADY_DOWN",
++ "STATUS_CLUSTER_NETWORK_ALREADY_ONLINE",
++ "STATUS_CLUSTER_NETWORK_ALREADY_OFFLINE",
++ "STATUS_CLUSTER_NODE_ALREADY_MEMBER",
++ "STATUS_COULD_NOT_RESIZE_LOG",
++ "STATUS_NO_TXF_METADATA",
++ "STATUS_CANT_RECOVER_WITH_HANDLE_OPEN",
++ "STATUS_TXF_METADATA_ALREADY_PRESENT",
++ "STATUS_TRANSACTION_SCOPE_CALLBACKS_NOT_SET",
++ "STATUS_VIDEO_HUNG_DISPLAY_DRIVER_THREAD_RECOVERED",
++ "STATUS_FLT_BUFFER_TOO_SMALL",
++ "STATUS_FVE_PARTIAL_METADATA",
++ "STATUS_FVE_TRANSIENT_STATE",
++ "STATUS_VID_REMOTE_NODE_PARENT_GPA_PAGES_USED",
++ "STATUS_VOLMGR_INCOMPLETE_REGENERATION",
++ "STATUS_VOLMGR_INCOMPLETE_DISK_MIGRATION",
++ "STATUS_BCD_NOT_ALL_ENTRIES_IMPORTED",
++ "STATUS_BCD_NOT_ALL_ENTRIES_SYNCHRONIZED",
++ "STATUS_QUERY_STORAGE_ERROR",
++ "STATUS_GDI_HANDLE_LEAK",
++ "STATUS_SECUREBOOT_NOT_ENABLED",
++ "STATUS_UNSUCCESSFUL",
++ "STATUS_NOT_IMPLEMENTED",
++ "STATUS_INVALID_INFO_CLASS",
++ "STATUS_INFO_LENGTH_MISMATCH",
++ "STATUS_ACCESS_VIOLATION",
++ "STATUS_IN_PAGE_ERROR",
++ "STATUS_PAGEFILE_QUOTA",
++ "STATUS_INVALID_HANDLE",
++ "STATUS_BAD_INITIAL_STACK",
++ "STATUS_BAD_INITIAL_PC",
++ "STATUS_INVALID_CID",
++ "STATUS_TIMER_NOT_CANCELED",
++ "STATUS_INVALID_PARAMETER",
++ "STATUS_NO_SUCH_DEVICE",
++ "STATUS_NO_SUCH_FILE",
++ "STATUS_INVALID_DEVICE_REQUEST",
++ "STATUS_END_OF_FILE",
++ "STATUS_WRONG_VOLUME",
++ "STATUS_NO_MEDIA_IN_DEVICE",
++ "STATUS_UNRECOGNIZED_MEDIA",
++ "STATUS_NONEXISTENT_SECTOR",
++ "STATUS_MORE_PROCESSING_REQUIRED",
++ "STATUS_NO_MEMORY",
++ "STATUS_CONFLICTING_ADDRESSES",
++ "STATUS_NOT_MAPPED_VIEW",
++ "STATUS_UNABLE_TO_FREE_VM",
++ "STATUS_UNABLE_TO_DELETE_SECTION",
++ "STATUS_INVALID_SYSTEM_SERVICE",
++ "STATUS_ILLEGAL_INSTRUCTION",
++ "STATUS_INVALID_LOCK_SEQUENCE",
++ "STATUS_INVALID_VIEW_SIZE",
++ "STATUS_INVALID_FILE_FOR_SECTION",
++ "STATUS_ALREADY_COMMITTED",
++ "STATUS_ACCESS_DENIED",
++ "STATUS_BUFFER_TOO_SMALL",
++ "STATUS_OBJECT_TYPE_MISMATCH",
++ "STATUS_NONCONTINUABLE_EXCEPTION",
++ "STATUS_INVALID_DISPOSITION",
++ "STATUS_UNWIND",
++ "STATUS_BAD_STACK",
++ "STATUS_INVALID_UNWIND_TARGET",
++ "STATUS_NOT_LOCKED",
++ "STATUS_PARITY_ERROR",
++ "STATUS_UNABLE_TO_DECOMMIT_VM",
++ "STATUS_NOT_COMMITTED",
++ "STATUS_INVALID_PORT_ATTRIBUTES",
++ "STATUS_PORT_MESSAGE_TOO_LONG",
++ "STATUS_INVALID_PARAMETER_MIX",
++ "STATUS_INVALID_QUOTA_LOWER",
++ "STATUS_DISK_CORRUPT_ERROR",
++ "STATUS_OBJECT_NAME_INVALID",
++ "STATUS_OBJECT_NAME_NOT_FOUND",
++ "STATUS_OBJECT_NAME_COLLISION",
++ "STATUS_PORT_DO_NOT_DISTURB",
++ "STATUS_PORT_DISCONNECTED",
++ "STATUS_DEVICE_ALREADY_ATTACHED",
++ "STATUS_OBJECT_PATH_INVALID",
++ "STATUS_OBJECT_PATH_NOT_FOUND",
++ "STATUS_OBJECT_PATH_SYNTAX_BAD",
++ "STATUS_DATA_OVERRUN",
++ "STATUS_DATA_LATE_ERROR",
++ "STATUS_DATA_ERROR",
++ "STATUS_CRC_ERROR",
++ "STATUS_SECTION_TOO_BIG",
++ "STATUS_PORT_CONNECTION_REFUSED",
++ "STATUS_INVALID_PORT_HANDLE",
++ "STATUS_SHARING_VIOLATION",
++ "STATUS_QUOTA_EXCEEDED",
++ "STATUS_INVALID_PAGE_PROTECTION",
++ "STATUS_MUTANT_NOT_OWNED",
++ "STATUS_SEMAPHORE_LIMIT_EXCEEDED",
++ "STATUS_PORT_ALREADY_SET",
++ "STATUS_SECTION_NOT_IMAGE",
++ "STATUS_SUSPEND_COUNT_EXCEEDED",
++ "STATUS_THREAD_IS_TERMINATING",
++ "STATUS_BAD_WORKING_SET_LIMIT",
++ "STATUS_INCOMPATIBLE_FILE_MAP",
++ "STATUS_SECTION_PROTECTION",
++ "STATUS_EAS_NOT_SUPPORTED",
++ "STATUS_EA_TOO_LARGE",
++ "STATUS_NONEXISTENT_EA_ENTRY",
++ "STATUS_NO_EAS_ON_FILE",
++ "STATUS_EA_CORRUPT_ERROR",
++ "STATUS_FILE_LOCK_CONFLICT",
++ "STATUS_LOCK_NOT_GRANTED",
++ "STATUS_DELETE_PENDING",
++ "STATUS_CTL_FILE_NOT_SUPPORTED",
++ "STATUS_UNKNOWN_REVISION",
++ "STATUS_REVISION_MISMATCH",
++ "STATUS_INVALID_OWNER",
++ "STATUS_INVALID_PRIMARY_GROUP",
++ "STATUS_NO_IMPERSONATION_TOKEN",
++ "STATUS_CANT_DISABLE_MANDATORY",
++ "STATUS_NO_LOGON_SERVERS",
++ "STATUS_NO_SUCH_LOGON_SESSION",
++ "STATUS_NO_SUCH_PRIVILEGE",
++ "STATUS_PRIVILEGE_NOT_HELD",
++ "STATUS_INVALID_ACCOUNT_NAME",
++ "STATUS_USER_EXISTS",
++ "STATUS_NO_SUCH_USER",
++ "STATUS_GROUP_EXISTS",
++ "STATUS_NO_SUCH_GROUP",
++ "STATUS_MEMBER_IN_GROUP",
++ "STATUS_MEMBER_NOT_IN_GROUP",
++ "STATUS_LAST_ADMIN",
++ "STATUS_WRONG_PASSWORD",
++ "STATUS_ILL_FORMED_PASSWORD",
++ "STATUS_PASSWORD_RESTRICTION",
++ "STATUS_LOGON_FAILURE",
++ "STATUS_ACCOUNT_RESTRICTION",
++ "STATUS_INVALID_LOGON_HOURS",
++ "STATUS_INVALID_WORKSTATION",
++ "STATUS_PASSWORD_EXPIRED",
++ "STATUS_ACCOUNT_DISABLED",
++ "STATUS_NONE_MAPPED",
++ "STATUS_TOO_MANY_LUIDS_REQUESTED",
++ "STATUS_LUIDS_EXHAUSTED",
++ "STATUS_INVALID_SUB_AUTHORITY",
++ "STATUS_INVALID_ACL",
++ "STATUS_INVALID_SID",
++ "STATUS_INVALID_SECURITY_DESCR",
++ "STATUS_PROCEDURE_NOT_FOUND",
++ "STATUS_INVALID_IMAGE_FORMAT",
++ "STATUS_NO_TOKEN",
++ "STATUS_BAD_INHERITANCE_ACL",
++ "STATUS_RANGE_NOT_LOCKED",
++ "STATUS_DISK_FULL",
++ "STATUS_SERVER_DISABLED",
++ "STATUS_SERVER_NOT_DISABLED",
++ "STATUS_TOO_MANY_GUIDS_REQUESTED",
++ "STATUS_GUIDS_EXHAUSTED",
++ "STATUS_INVALID_ID_AUTHORITY",
++ "STATUS_AGENTS_EXHAUSTED",
++ "STATUS_INVALID_VOLUME_LABEL",
++ "STATUS_SECTION_NOT_EXTENDED",
++ "STATUS_NOT_MAPPED_DATA",
++ "STATUS_RESOURCE_DATA_NOT_FOUND",
++ "STATUS_RESOURCE_TYPE_NOT_FOUND",
++ "STATUS_RESOURCE_NAME_NOT_FOUND",
++ "STATUS_ARRAY_BOUNDS_EXCEEDED",
++ "STATUS_FLOAT_DENORMAL_OPERAND",
++ "STATUS_FLOAT_DIVIDE_BY_ZERO",
++ "STATUS_FLOAT_INEXACT_RESULT",
++ "STATUS_FLOAT_INVALID_OPERATION",
++ "STATUS_FLOAT_OVERFLOW",
++ "STATUS_FLOAT_STACK_CHECK",
++ "STATUS_FLOAT_UNDERFLOW",
++ "STATUS_INTEGER_DIVIDE_BY_ZERO",
++ "STATUS_INTEGER_OVERFLOW",
++ "STATUS_PRIVILEGED_INSTRUCTION",
++ "STATUS_TOO_MANY_PAGING_FILES",
++ "STATUS_FILE_INVALID",
++ "STATUS_ALLOTTED_SPACE_EXCEEDED",
++ "STATUS_INSUFFICIENT_RESOURCES",
++ "STATUS_DFS_EXIT_PATH_FOUND",
++ "STATUS_DEVICE_DATA_ERROR",
++ "STATUS_DEVICE_NOT_CONNECTED",
++ "STATUS_DEVICE_POWER_FAILURE",
++ "STATUS_FREE_VM_NOT_AT_BASE",
++ "STATUS_MEMORY_NOT_ALLOCATED",
++ "STATUS_WORKING_SET_QUOTA",
++ "STATUS_MEDIA_WRITE_PROTECTED",
++ "STATUS_DEVICE_NOT_READY",
++ "STATUS_INVALID_GROUP_ATTRIBUTES",
++ "STATUS_BAD_IMPERSONATION_LEVEL",
++ "STATUS_CANT_OPEN_ANONYMOUS",
++ "STATUS_BAD_VALIDATION_CLASS",
++ "STATUS_BAD_TOKEN_TYPE",
++ "STATUS_BAD_MASTER_BOOT_RECORD",
++ "STATUS_INSTRUCTION_MISALIGNMENT",
++ "STATUS_INSTANCE_NOT_AVAILABLE",
++ "STATUS_PIPE_NOT_AVAILABLE",
++ "STATUS_INVALID_PIPE_STATE",
++ "STATUS_PIPE_BUSY",
++ "STATUS_ILLEGAL_FUNCTION",
++ "STATUS_PIPE_DISCONNECTED",
++ "STATUS_PIPE_CLOSING",
++ "STATUS_PIPE_CONNECTED",
++ "STATUS_PIPE_LISTENING",
++ "STATUS_INVALID_READ_MODE",
++ "STATUS_IO_TIMEOUT",
++ "STATUS_FILE_FORCED_CLOSED",
++ "STATUS_PROFILING_NOT_STARTED",
++ "STATUS_PROFILING_NOT_STOPPED",
++ "STATUS_COULD_NOT_INTERPRET",
++ "STATUS_FILE_IS_A_DIRECTORY",
++ "STATUS_NOT_SUPPORTED",
++ "STATUS_REMOTE_NOT_LISTENING",
++ "STATUS_DUPLICATE_NAME",
++ "STATUS_BAD_NETWORK_PATH",
++ "STATUS_NETWORK_BUSY",
++ "STATUS_DEVICE_DOES_NOT_EXIST",
++ "STATUS_TOO_MANY_COMMANDS",
++ "STATUS_ADAPTER_HARDWARE_ERROR",
++ "STATUS_INVALID_NETWORK_RESPONSE",
++ "STATUS_UNEXPECTED_NETWORK_ERROR",
++ "STATUS_BAD_REMOTE_ADAPTER",
++ "STATUS_PRINT_QUEUE_FULL",
++ "STATUS_NO_SPOOL_SPACE",
++ "STATUS_PRINT_CANCELLED",
++ "STATUS_NETWORK_NAME_DELETED",
++ "STATUS_NETWORK_ACCESS_DENIED",
++ "STATUS_BAD_DEVICE_TYPE",
++ "STATUS_BAD_NETWORK_NAME",
++ "STATUS_TOO_MANY_NAMES",
++ "STATUS_TOO_MANY_SESSIONS",
++ "STATUS_SHARING_PAUSED",
++ "STATUS_REQUEST_NOT_ACCEPTED",
++ "STATUS_REDIRECTOR_PAUSED",
++ "STATUS_NET_WRITE_FAULT",
++ "STATUS_PROFILING_AT_LIMIT",
++ "STATUS_NOT_SAME_DEVICE",
++ "STATUS_FILE_RENAMED",
++ "STATUS_VIRTUAL_CIRCUIT_CLOSED",
++ "STATUS_NO_SECURITY_ON_OBJECT",
++ "STATUS_CANT_WAIT",
++ "STATUS_PIPE_EMPTY",
++ "STATUS_CANT_ACCESS_DOMAIN_INFO",
++ "STATUS_CANT_TERMINATE_SELF",
++ "STATUS_INVALID_SERVER_STATE",
++ "STATUS_INVALID_DOMAIN_STATE",
++ "STATUS_INVALID_DOMAIN_ROLE",
++ "STATUS_NO_SUCH_DOMAIN",
++ "STATUS_DOMAIN_EXISTS",
++ "STATUS_DOMAIN_LIMIT_EXCEEDED",
++ "STATUS_OPLOCK_NOT_GRANTED",
++ "STATUS_INVALID_OPLOCK_PROTOCOL",
++ "STATUS_INTERNAL_DB_CORRUPTION",
++ "STATUS_INTERNAL_ERROR",
++ "STATUS_GENERIC_NOT_MAPPED",
++ "STATUS_BAD_DESCRIPTOR_FORMAT",
++ "STATUS_INVALID_USER_BUFFER",
++ "STATUS_UNEXPECTED_IO_ERROR",
++ "STATUS_UNEXPECTED_MM_CREATE_ERR",
++ "STATUS_UNEXPECTED_MM_MAP_ERROR",
++ "STATUS_UNEXPECTED_MM_EXTEND_ERR",
++ "STATUS_NOT_LOGON_PROCESS",
++ "STATUS_LOGON_SESSION_EXISTS",
++ "STATUS_INVALID_PARAMETER_1",
++ "STATUS_INVALID_PARAMETER_2",
++ "STATUS_INVALID_PARAMETER_3",
++ "STATUS_INVALID_PARAMETER_4",
++ "STATUS_INVALID_PARAMETER_5",
++ "STATUS_INVALID_PARAMETER_6",
++ "STATUS_INVALID_PARAMETER_7",
++ "STATUS_INVALID_PARAMETER_8",
++ "STATUS_INVALID_PARAMETER_9",
++ "STATUS_INVALID_PARAMETER_10",
++ "STATUS_INVALID_PARAMETER_11",
++ "STATUS_INVALID_PARAMETER_12",
++ "STATUS_REDIRECTOR_NOT_STARTED",
++ "STATUS_REDIRECTOR_STARTED",
++ "STATUS_STACK_OVERFLOW",
++ "STATUS_NO_SUCH_PACKAGE",
++ "STATUS_BAD_FUNCTION_TABLE",
++ "STATUS_VARIABLE_NOT_FOUND",
++ "STATUS_DIRECTORY_NOT_EMPTY",
++ "STATUS_FILE_CORRUPT_ERROR",
++ "STATUS_NOT_A_DIRECTORY",
++ "STATUS_BAD_LOGON_SESSION_STATE",
++ "STATUS_LOGON_SESSION_COLLISION",
++ "STATUS_NAME_TOO_LONG",
++ "STATUS_FILES_OPEN",
++ "STATUS_CONNECTION_IN_USE",
++ "STATUS_MESSAGE_NOT_FOUND",
++ "STATUS_PROCESS_IS_TERMINATING",
++ "STATUS_INVALID_LOGON_TYPE",
++ "STATUS_NO_GUID_TRANSLATION",
++ "STATUS_CANNOT_IMPERSONATE",
++ "STATUS_IMAGE_ALREADY_LOADED",
++ "STATUS_ABIOS_NOT_PRESENT",
++ "STATUS_ABIOS_LID_NOT_EXIST",
++ "STATUS_ABIOS_LID_ALREADY_OWNED",
++ "STATUS_ABIOS_NOT_LID_OWNER",
++ "STATUS_ABIOS_INVALID_COMMAND",
++ "STATUS_ABIOS_INVALID_LID",
++ "STATUS_ABIOS_SELECTOR_NOT_AVAILABLE",
++ "STATUS_ABIOS_INVALID_SELECTOR",
++ "STATUS_NO_LDT",
++ "STATUS_INVALID_LDT_SIZE",
++ "STATUS_INVALID_LDT_OFFSET",
++ "STATUS_INVALID_LDT_DESCRIPTOR",
++ "STATUS_INVALID_IMAGE_NE_FORMAT",
++ "STATUS_RXACT_INVALID_STATE",
++ "STATUS_RXACT_COMMIT_FAILURE",
++ "STATUS_MAPPED_FILE_SIZE_ZERO",
++ "STATUS_TOO_MANY_OPENED_FILES",
++ "STATUS_CANCELLED",
++ "STATUS_CANNOT_DELETE",
++ "STATUS_INVALID_COMPUTER_NAME",
++ "STATUS_FILE_DELETED",
++ "STATUS_SPECIAL_ACCOUNT",
++ "STATUS_SPECIAL_GROUP",
++ "STATUS_SPECIAL_USER",
++ "STATUS_MEMBERS_PRIMARY_GROUP",
++ "STATUS_FILE_CLOSED",
++ "STATUS_TOO_MANY_THREADS",
++ "STATUS_THREAD_NOT_IN_PROCESS",
++ "STATUS_TOKEN_ALREADY_IN_USE",
++ "STATUS_PAGEFILE_QUOTA_EXCEEDED",
++ "STATUS_COMMITMENT_LIMIT",
++ "STATUS_INVALID_IMAGE_LE_FORMAT",
++ "STATUS_INVALID_IMAGE_NOT_MZ",
++ "STATUS_INVALID_IMAGE_PROTECT",
++ "STATUS_INVALID_IMAGE_WIN_16",
++ "STATUS_LOGON_SERVER_CONFLICT",
++ "STATUS_TIME_DIFFERENCE_AT_DC",
++ "STATUS_SYNCHRONIZATION_REQUIRED",
++ "STATUS_DLL_NOT_FOUND",
++ "STATUS_OPEN_FAILED",
++ "STATUS_IO_PRIVILEGE_FAILED",
++ "STATUS_ORDINAL_NOT_FOUND",
++ "STATUS_ENTRYPOINT_NOT_FOUND",
++ "STATUS_CONTROL_C_EXIT",
++ "STATUS_LOCAL_DISCONNECT",
++ "STATUS_REMOTE_DISCONNECT",
++ "STATUS_REMOTE_RESOURCES",
++ "STATUS_LINK_FAILED",
++ "STATUS_LINK_TIMEOUT",
++ "STATUS_INVALID_CONNECTION",
++ "STATUS_INVALID_ADDRESS",
++ "STATUS_DLL_INIT_FAILED",
++ "STATUS_MISSING_SYSTEMFILE",
++ "STATUS_UNHANDLED_EXCEPTION",
++ "STATUS_APP_INIT_FAILURE",
++ "STATUS_PAGEFILE_CREATE_FAILED",
++ "STATUS_NO_PAGEFILE",
++ "STATUS_INVALID_LEVEL",
++ "STATUS_WRONG_PASSWORD_CORE",
++ "STATUS_ILLEGAL_FLOAT_CONTEXT",
++ "STATUS_PIPE_BROKEN",
++ "STATUS_REGISTRY_CORRUPT",
++ "STATUS_REGISTRY_IO_FAILED",
++ "STATUS_NO_EVENT_PAIR",
++ "STATUS_UNRECOGNIZED_VOLUME",
++ "STATUS_SERIAL_NO_DEVICE_INITED",
++ "STATUS_NO_SUCH_ALIAS",
++ "STATUS_MEMBER_NOT_IN_ALIAS",
++ "STATUS_MEMBER_IN_ALIAS",
++ "STATUS_ALIAS_EXISTS",
++ "STATUS_LOGON_NOT_GRANTED",
++ "STATUS_TOO_MANY_SECRETS",
++ "STATUS_SECRET_TOO_LONG",
++ "STATUS_INTERNAL_DB_ERROR",
++ "STATUS_FULLSCREEN_MODE",
++ "STATUS_TOO_MANY_CONTEXT_IDS",
++ "STATUS_LOGON_TYPE_NOT_GRANTED",
++ "STATUS_NOT_REGISTRY_FILE",
++ "STATUS_NT_CROSS_ENCRYPTION_REQUIRED",
++ "STATUS_DOMAIN_CTRLR_CONFIG_ERROR",
++ "STATUS_FT_MISSING_MEMBER",
++ "STATUS_ILL_FORMED_SERVICE_ENTRY",
++ "STATUS_ILLEGAL_CHARACTER",
++ "STATUS_UNMAPPABLE_CHARACTER",
++ "STATUS_UNDEFINED_CHARACTER",
++ "STATUS_FLOPPY_VOLUME",
++ "STATUS_FLOPPY_ID_MARK_NOT_FOUND",
++ "STATUS_FLOPPY_WRONG_CYLINDER",
++ "STATUS_FLOPPY_UNKNOWN_ERROR",
++ "STATUS_FLOPPY_BAD_REGISTERS",
++ "STATUS_DISK_RECALIBRATE_FAILED",
++ "STATUS_DISK_OPERATION_FAILED",
++ "STATUS_DISK_RESET_FAILED",
++ "STATUS_SHARED_IRQ_BUSY",
++ "STATUS_FT_ORPHANING",
++ "STATUS_BIOS_FAILED_TO_CONNECT_INTERRUPT",
++ "STATUS_PARTITION_FAILURE",
++ "STATUS_INVALID_BLOCK_LENGTH",
++ "STATUS_DEVICE_NOT_PARTITIONED",
++ "STATUS_UNABLE_TO_LOCK_MEDIA",
++ "STATUS_UNABLE_TO_UNLOAD_MEDIA",
++ "STATUS_EOM_OVERFLOW",
++ "STATUS_NO_MEDIA",
++ "STATUS_NO_SUCH_MEMBER",
++ "STATUS_INVALID_MEMBER",
++ "STATUS_KEY_DELETED",
++ "STATUS_NO_LOG_SPACE",
++ "STATUS_TOO_MANY_SIDS",
++ "STATUS_LM_CROSS_ENCRYPTION_REQUIRED",
++ "STATUS_KEY_HAS_CHILDREN",
++ "STATUS_CHILD_MUST_BE_VOLATILE",
++ "STATUS_DEVICE_CONFIGURATION_ERROR",
++ "STATUS_DRIVER_INTERNAL_ERROR",
++ "STATUS_INVALID_DEVICE_STATE",
++ "STATUS_IO_DEVICE_ERROR",
++ "STATUS_DEVICE_PROTOCOL_ERROR",
++ "STATUS_BACKUP_CONTROLLER",
++ "STATUS_LOG_FILE_FULL",
++ "STATUS_TOO_LATE",
++ "STATUS_NO_TRUST_LSA_SECRET",
++ "STATUS_NO_TRUST_SAM_ACCOUNT",
++ "STATUS_TRUSTED_DOMAIN_FAILURE",
++ "STATUS_TRUSTED_RELATIONSHIP_FAILURE",
++ "STATUS_EVENTLOG_FILE_CORRUPT",
++ "STATUS_EVENTLOG_CANT_START",
++ "STATUS_TRUST_FAILURE",
++ "STATUS_MUTANT_LIMIT_EXCEEDED",
++ "STATUS_NETLOGON_NOT_STARTED",
++ "STATUS_ACCOUNT_EXPIRED",
++ "STATUS_POSSIBLE_DEADLOCK",
++ "STATUS_NETWORK_CREDENTIAL_CONFLICT",
++ "STATUS_REMOTE_SESSION_LIMIT",
++ "STATUS_EVENTLOG_FILE_CHANGED",
++ "STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT",
++ "STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT",
++ "STATUS_NOLOGON_SERVER_TRUST_ACCOUNT",
++ "STATUS_DOMAIN_TRUST_INCONSISTENT",
++ "STATUS_FS_DRIVER_REQUIRED",
++ "STATUS_IMAGE_ALREADY_LOADED_AS_DLL",
++ "STATUS_INCOMPATIBLE_WITH_GLOBAL_SHORT_NAME_REGISTRY_SETTING",
++ "STATUS_SHORT_NAMES_NOT_ENABLED_ON_VOLUME",
++ "STATUS_SECURITY_STREAM_IS_INCONSISTENT",
++ "STATUS_INVALID_LOCK_RANGE",
++ "STATUS_INVALID_ACE_CONDITION",
++ "STATUS_IMAGE_SUBSYSTEM_NOT_PRESENT",
++ "STATUS_NOTIFICATION_GUID_ALREADY_DEFINED",
++ "STATUS_INVALID_EXCEPTION_HANDLER",
++ "STATUS_DUPLICATE_PRIVILEGES",
++ "STATUS_NOT_ALLOWED_ON_SYSTEM_FILE",
++ "STATUS_REPAIR_NEEDED",
++ "STATUS_QUOTA_NOT_ENABLED",
++ "STATUS_NO_APPLICATION_PACKAGE",
++ "STATUS_FILE_METADATA_OPTIMIZATION_IN_PROGRESS",
++ "STATUS_NOT_SAME_OBJECT",
++ "STATUS_FATAL_MEMORY_EXHAUSTION",
++ "STATUS_ERROR_PROCESS_NOT_IN_JOB",
++ "STATUS_CPU_SET_INVALID",
++ "STATUS_IO_DEVICE_INVALID_DATA",
++ "STATUS_IO_UNALIGNED_WRITE",
++ "STATUS_CONTROL_STACK_VIOLATION",
++ "STATUS_NETWORK_OPEN_RESTRICTION",
++ "STATUS_NO_USER_SESSION_KEY",
++ "STATUS_USER_SESSION_DELETED",
++ "STATUS_RESOURCE_LANG_NOT_FOUND",
++ "STATUS_INSUFF_SERVER_RESOURCES",
++ "STATUS_INVALID_BUFFER_SIZE",
++ "STATUS_INVALID_ADDRESS_COMPONENT",
++ "STATUS_INVALID_ADDRESS_WILDCARD",
++ "STATUS_TOO_MANY_ADDRESSES",
++ "STATUS_ADDRESS_ALREADY_EXISTS",
++ "STATUS_ADDRESS_CLOSED",
++ "STATUS_CONNECTION_DISCONNECTED",
++ "STATUS_CONNECTION_RESET",
++ "STATUS_TOO_MANY_NODES",
++ "STATUS_TRANSACTION_ABORTED",
++ "STATUS_TRANSACTION_TIMED_OUT",
++ "STATUS_TRANSACTION_NO_RELEASE",
++ "STATUS_TRANSACTION_NO_MATCH",
++ "STATUS_TRANSACTION_RESPONDED",
++ "STATUS_TRANSACTION_INVALID_ID",
++ "STATUS_TRANSACTION_INVALID_TYPE",
++ "STATUS_NOT_SERVER_SESSION",
++ "STATUS_NOT_CLIENT_SESSION",
++ "STATUS_CANNOT_LOAD_REGISTRY_FILE",
++ "STATUS_DEBUG_ATTACH_FAILED",
++ "STATUS_SYSTEM_PROCESS_TERMINATED",
++ "STATUS_DATA_NOT_ACCEPTED",
++ "STATUS_NO_BROWSER_SERVERS_FOUND",
++ "STATUS_VDM_HARD_ERROR",
++ "STATUS_DRIVER_CANCEL_TIMEOUT",
++ "STATUS_REPLY_MESSAGE_MISMATCH",
++ "STATUS_MAPPED_ALIGNMENT",
++ "STATUS_IMAGE_CHECKSUM_MISMATCH",
++ "STATUS_LOST_WRITEBEHIND_DATA",
++ "STATUS_CLIENT_SERVER_PARAMETERS_INVALID",
++ "STATUS_PASSWORD_MUST_CHANGE",
++ "STATUS_NOT_FOUND",
++ "STATUS_NOT_TINY_STREAM",
++ "STATUS_RECOVERY_FAILURE",
++ "STATUS_STACK_OVERFLOW_READ",
++ "STATUS_FAIL_CHECK",
++ "STATUS_DUPLICATE_OBJECTID",
++ "STATUS_OBJECTID_EXISTS",
++ "STATUS_CONVERT_TO_LARGE",
++ "STATUS_RETRY",
++ "STATUS_FOUND_OUT_OF_SCOPE",
++ "STATUS_ALLOCATE_BUCKET",
++ "STATUS_PROPSET_NOT_FOUND",
++ "STATUS_MARSHALL_OVERFLOW",
++ "STATUS_INVALID_VARIANT",
++ "STATUS_DOMAIN_CONTROLLER_NOT_FOUND",
++ "STATUS_ACCOUNT_LOCKED_OUT",
++ "STATUS_HANDLE_NOT_CLOSABLE",
++ "STATUS_CONNECTION_REFUSED",
++ "STATUS_GRACEFUL_DISCONNECT",
++ "STATUS_ADDRESS_ALREADY_ASSOCIATED",
++ "STATUS_ADDRESS_NOT_ASSOCIATED",
++ "STATUS_CONNECTION_INVALID",
++ "STATUS_CONNECTION_ACTIVE",
++ "STATUS_NETWORK_UNREACHABLE",
++ "STATUS_HOST_UNREACHABLE",
++ "STATUS_PROTOCOL_UNREACHABLE",
++ "STATUS_PORT_UNREACHABLE",
++ "STATUS_REQUEST_ABORTED",
++ "STATUS_CONNECTION_ABORTED",
++ "STATUS_BAD_COMPRESSION_BUFFER",
++ "STATUS_USER_MAPPED_FILE",
++ "STATUS_AUDIT_FAILED",
++ "STATUS_TIMER_RESOLUTION_NOT_SET",
++ "STATUS_CONNECTION_COUNT_LIMIT",
++ "STATUS_LOGIN_TIME_RESTRICTION",
++ "STATUS_LOGIN_WKSTA_RESTRICTION",
++ "STATUS_IMAGE_MP_UP_MISMATCH",
++ "STATUS_INSUFFICIENT_LOGON_INFO",
++ "STATUS_BAD_DLL_ENTRYPOINT",
++ "STATUS_BAD_SERVICE_ENTRYPOINT",
++ "STATUS_LPC_REPLY_LOST",
++ "STATUS_IP_ADDRESS_CONFLICT1",
++ "STATUS_IP_ADDRESS_CONFLICT2",
++ "STATUS_REGISTRY_QUOTA_LIMIT",
++ "STATUS_PATH_NOT_COVERED",
++ "STATUS_NO_CALLBACK_ACTIVE",
++ "STATUS_LICENSE_QUOTA_EXCEEDED",
++ "STATUS_PWD_TOO_SHORT",
++ "STATUS_PWD_TOO_RECENT",
++ "STATUS_PWD_HISTORY_CONFLICT",
++ "STATUS_PLUGPLAY_NO_DEVICE",
++ "STATUS_UNSUPPORTED_COMPRESSION",
++ "STATUS_INVALID_HW_PROFILE",
++ "STATUS_INVALID_PLUGPLAY_DEVICE_PATH",
++ "STATUS_DRIVER_ORDINAL_NOT_FOUND",
++ "STATUS_DRIVER_ENTRYPOINT_NOT_FOUND",
++ "STATUS_RESOURCE_NOT_OWNED",
++ "STATUS_TOO_MANY_LINKS",
++ "STATUS_QUOTA_LIST_INCONSISTENT",
++ "STATUS_FILE_IS_OFFLINE",
++ "STATUS_EVALUATION_EXPIRATION",
++ "STATUS_ILLEGAL_DLL_RELOCATION",
++ "STATUS_LICENSE_VIOLATION",
++ "STATUS_DLL_INIT_FAILED_LOGOFF",
++ "STATUS_DRIVER_UNABLE_TO_LOAD",
++ "STATUS_DFS_UNAVAILABLE",
++ "STATUS_VOLUME_DISMOUNTED",
++ "STATUS_WX86_INTERNAL_ERROR",
++ "STATUS_WX86_FLOAT_STACK_CHECK",
++ "STATUS_VALIDATE_CONTINUE",
++ "STATUS_NO_MATCH",
++ "STATUS_NO_MORE_MATCHES",
++ "STATUS_NOT_A_REPARSE_POINT",
++ "STATUS_IO_REPARSE_TAG_INVALID",
++ "STATUS_IO_REPARSE_TAG_MISMATCH",
++ "STATUS_IO_REPARSE_DATA_INVALID",
++ "STATUS_IO_REPARSE_TAG_NOT_HANDLED",
++ "STATUS_PWD_TOO_LONG",
++ "STATUS_STOWED_EXCEPTION",
++ "STATUS_CONTEXT_STOWED_EXCEPTION",
++ "STATUS_REPARSE_POINT_NOT_RESOLVED",
++ "STATUS_DIRECTORY_IS_A_REPARSE_POINT",
++ "STATUS_RANGE_LIST_CONFLICT",
++ "STATUS_SOURCE_ELEMENT_EMPTY",
++ "STATUS_DESTINATION_ELEMENT_FULL",
++ "STATUS_ILLEGAL_ELEMENT_ADDRESS",
++ "STATUS_MAGAZINE_NOT_PRESENT",
++ "STATUS_REINITIALIZATION_NEEDED",
++ "STATUS_ENCRYPTION_FAILED",
++ "STATUS_DECRYPTION_FAILED",
++ "STATUS_RANGE_NOT_FOUND",
++ "STATUS_NO_RECOVERY_POLICY",
++ "STATUS_NO_EFS",
++ "STATUS_WRONG_EFS",
++ "STATUS_NO_USER_KEYS",
++ "STATUS_FILE_NOT_ENCRYPTED",
++ "STATUS_NOT_EXPORT_FORMAT",
++ "STATUS_FILE_ENCRYPTED",
++ "STATUS_WMI_GUID_NOT_FOUND",
++ "STATUS_WMI_INSTANCE_NOT_FOUND",
++ "STATUS_WMI_ITEMID_NOT_FOUND",
++ "STATUS_WMI_TRY_AGAIN",
++ "STATUS_SHARED_POLICY",
++ "STATUS_POLICY_OBJECT_NOT_FOUND",
++ "STATUS_POLICY_ONLY_IN_DS",
++ "STATUS_VOLUME_NOT_UPGRADED",
++ "STATUS_REMOTE_STORAGE_NOT_ACTIVE",
++ "STATUS_REMOTE_STORAGE_MEDIA_ERROR",
++ "STATUS_NO_TRACKING_SERVICE",
++ "STATUS_SERVER_SID_MISMATCH",
++ "STATUS_DS_NO_ATTRIBUTE_OR_VALUE",
++ "STATUS_DS_INVALID_ATTRIBUTE_SYNTAX",
++ "STATUS_DS_ATTRIBUTE_TYPE_UNDEFINED",
++ "STATUS_DS_ATTRIBUTE_OR_VALUE_EXISTS",
++ "STATUS_DS_BUSY",
++ "STATUS_DS_UNAVAILABLE",
++ "STATUS_DS_NO_RIDS_ALLOCATED",
++ "STATUS_DS_NO_MORE_RIDS",
++ "STATUS_DS_INCORRECT_ROLE_OWNER",
++ "STATUS_DS_RIDMGR_INIT_ERROR",
++ "STATUS_DS_OBJ_CLASS_VIOLATION",
++ "STATUS_DS_CANT_ON_NON_LEAF",
++ "STATUS_DS_CANT_ON_RDN",
++ "STATUS_DS_CANT_MOD_OBJ_CLASS",
++ "STATUS_DS_CROSS_DOM_MOVE_FAILED",
++ "STATUS_DS_GC_NOT_AVAILABLE",
++ "STATUS_DIRECTORY_SERVICE_REQUIRED",
++ "STATUS_REPARSE_ATTRIBUTE_CONFLICT",
++ "STATUS_CANT_ENABLE_DENY_ONLY",
++ "STATUS_FLOAT_MULTIPLE_FAULTS",
++ "STATUS_FLOAT_MULTIPLE_TRAPS",
++ "STATUS_DEVICE_REMOVED",
++ "STATUS_JOURNAL_DELETE_IN_PROGRESS",
++ "STATUS_JOURNAL_NOT_ACTIVE",
++ "STATUS_NOINTERFACE",
++ "STATUS_DS_RIDMGR_DISABLED",
++ "STATUS_DS_ADMIN_LIMIT_EXCEEDED",
++ "STATUS_DRIVER_FAILED_SLEEP",
++ "STATUS_MUTUAL_AUTHENTICATION_FAILED",
++ "STATUS_CORRUPT_SYSTEM_FILE",
++ "STATUS_DATATYPE_MISALIGNMENT_ERROR",
++ "STATUS_WMI_READ_ONLY",
++ "STATUS_WMI_SET_FAILURE",
++ "STATUS_COMMITMENT_MINIMUM",
++ "STATUS_REG_NAT_CONSUMPTION",
++ "STATUS_TRANSPORT_FULL",
++ "STATUS_DS_SAM_INIT_FAILURE",
++ "STATUS_ONLY_IF_CONNECTED",
++ "STATUS_DS_SENSITIVE_GROUP_VIOLATION",
++ "STATUS_PNP_RESTART_ENUMERATION",
++ "STATUS_JOURNAL_ENTRY_DELETED",
++ "STATUS_DS_CANT_MOD_PRIMARYGROUPID",
++ "STATUS_SYSTEM_IMAGE_BAD_SIGNATURE",
++ "STATUS_PNP_REBOOT_REQUIRED",
++ "STATUS_POWER_STATE_INVALID",
++ "STATUS_DS_INVALID_GROUP_TYPE",
++ "STATUS_DS_NO_NEST_GLOBALGROUP_IN_MIXEDDOMAIN",
++ "STATUS_DS_NO_NEST_LOCALGROUP_IN_MIXEDDOMAIN",
++ "STATUS_DS_GLOBAL_CANT_HAVE_LOCAL_MEMBER",
++ "STATUS_DS_GLOBAL_CANT_HAVE_UNIVERSAL_MEMBER",
++ "STATUS_DS_UNIVERSAL_CANT_HAVE_LOCAL_MEMBER",
++ "STATUS_DS_GLOBAL_CANT_HAVE_CROSSDOMAIN_MEMBER",
++ "STATUS_DS_LOCAL_CANT_HAVE_CROSSDOMAIN_LOCAL_MEMBER",
++ "STATUS_DS_HAVE_PRIMARY_MEMBERS",
++ "STATUS_WMI_NOT_SUPPORTED",
++ "STATUS_INSUFFICIENT_POWER",
++ "STATUS_SAM_NEED_BOOTKEY_PASSWORD",
++ "STATUS_SAM_NEED_BOOTKEY_FLOPPY",
++ "STATUS_DS_CANT_START",
++ "STATUS_DS_INIT_FAILURE",
++ "STATUS_SAM_INIT_FAILURE",
++ "STATUS_DS_GC_REQUIRED",
++ "STATUS_DS_LOCAL_MEMBER_OF_LOCAL_ONLY",
++ "STATUS_DS_NO_FPO_IN_UNIVERSAL_GROUPS",
++ "STATUS_DS_MACHINE_ACCOUNT_QUOTA_EXCEEDED",
++ "STATUS_MULTIPLE_FAULT_VIOLATION",
++ "STATUS_CURRENT_DOMAIN_NOT_ALLOWED",
++ "STATUS_CANNOT_MAKE",
++ "STATUS_SYSTEM_SHUTDOWN",
++ "STATUS_DS_INIT_FAILURE_CONSOLE",
++ "STATUS_DS_SAM_INIT_FAILURE_CONSOLE",
++ "STATUS_UNFINISHED_CONTEXT_DELETED",
++ "STATUS_NO_TGT_REPLY",
++ "STATUS_OBJECTID_NOT_FOUND",
++ "STATUS_NO_IP_ADDRESSES",
++ "STATUS_WRONG_CREDENTIAL_HANDLE",
++ "STATUS_CRYPTO_SYSTEM_INVALID",
++ "STATUS_MAX_REFERRALS_EXCEEDED",
++ "STATUS_MUST_BE_KDC",
++ "STATUS_STRONG_CRYPTO_NOT_SUPPORTED",
++ "STATUS_TOO_MANY_PRINCIPALS",
++ "STATUS_NO_PA_DATA",
++ "STATUS_PKINIT_NAME_MISMATCH",
++ "STATUS_SMARTCARD_LOGON_REQUIRED",
++ "STATUS_KDC_INVALID_REQUEST",
++ "STATUS_KDC_UNABLE_TO_REFER",
++ "STATUS_KDC_UNKNOWN_ETYPE",
++ "STATUS_SHUTDOWN_IN_PROGRESS",
++ "STATUS_SERVER_SHUTDOWN_IN_PROGRESS",
++ "STATUS_NOT_SUPPORTED_ON_SBS",
++ "STATUS_WMI_GUID_DISCONNECTED",
++ "STATUS_WMI_ALREADY_DISABLED",
++ "STATUS_WMI_ALREADY_ENABLED",
++ "STATUS_MFT_TOO_FRAGMENTED",
++ "STATUS_COPY_PROTECTION_FAILURE",
++ "STATUS_CSS_AUTHENTICATION_FAILURE",
++ "STATUS_CSS_KEY_NOT_PRESENT",
++ "STATUS_CSS_KEY_NOT_ESTABLISHED",
++ "STATUS_CSS_SCRAMBLED_SECTOR",
++ "STATUS_CSS_REGION_MISMATCH",
++ "STATUS_CSS_RESETS_EXHAUSTED",
++ "STATUS_PASSWORD_CHANGE_REQUIRED",
++ "STATUS_LOST_MODE_LOGON_RESTRICTION",
++ "STATUS_PKINIT_FAILURE",
++ "STATUS_SMARTCARD_SUBSYSTEM_FAILURE",
++ "STATUS_NO_KERB_KEY",
++ "STATUS_HOST_DOWN",
++ "STATUS_UNSUPPORTED_PREAUTH",
++ "STATUS_EFS_ALG_BLOB_TOO_BIG",
++ "STATUS_PORT_NOT_SET",
++ "STATUS_DEBUGGER_INACTIVE",
++ "STATUS_DS_VERSION_CHECK_FAILURE",
++ "STATUS_AUDITING_DISABLED",
++ "STATUS_PRENT4_MACHINE_ACCOUNT",
++ "STATUS_DS_AG_CANT_HAVE_UNIVERSAL_MEMBER",
++ "STATUS_INVALID_IMAGE_WIN_32",
++ "STATUS_INVALID_IMAGE_WIN_64",
++ "STATUS_BAD_BINDINGS",
++ "STATUS_NETWORK_SESSION_EXPIRED",
++ "STATUS_APPHELP_BLOCK",
++ "STATUS_ALL_SIDS_FILTERED",
++ "STATUS_NOT_SAFE_MODE_DRIVER",
++ "STATUS_ACCESS_DISABLED_BY_POLICY_DEFAULT",
++ "STATUS_ACCESS_DISABLED_BY_POLICY_PATH",
++ "STATUS_ACCESS_DISABLED_BY_POLICY_PUBLISHER",
++ "STATUS_ACCESS_DISABLED_BY_POLICY_OTHER",
++ "STATUS_FAILED_DRIVER_ENTRY",
++ "STATUS_DEVICE_ENUMERATION_ERROR",
++ "STATUS_MOUNT_POINT_NOT_RESOLVED",
++ "STATUS_INVALID_DEVICE_OBJECT_PARAMETER",
++ "STATUS_MCA_OCCURED",
++ "STATUS_DRIVER_BLOCKED_CRITICAL",
++ "STATUS_DRIVER_BLOCKED",
++ "STATUS_DRIVER_DATABASE_ERROR",
++ "STATUS_SYSTEM_HIVE_TOO_LARGE",
++ "STATUS_INVALID_IMPORT_OF_NON_DLL",
++ "STATUS_NO_SECRETS",
++ "STATUS_ACCESS_DISABLED_NO_SAFER_UI_BY_POLICY",
++ "STATUS_FAILED_STACK_SWITCH",
++ "STATUS_HEAP_CORRUPTION",
++ "STATUS_SMARTCARD_WRONG_PIN",
++ "STATUS_SMARTCARD_CARD_BLOCKED",
++ "STATUS_SMARTCARD_CARD_NOT_AUTHENTICATED",
++ "STATUS_SMARTCARD_NO_CARD",
++ "STATUS_SMARTCARD_NO_KEY_CONTAINER",
++ "STATUS_SMARTCARD_NO_CERTIFICATE",
++ "STATUS_SMARTCARD_NO_KEYSET",
++ "STATUS_SMARTCARD_IO_ERROR",
++ "STATUS_DOWNGRADE_DETECTED",
++ "STATUS_SMARTCARD_CERT_REVOKED",
++ "STATUS_ISSUING_CA_UNTRUSTED",
++ "STATUS_REVOCATION_OFFLINE_C",
++ "STATUS_PKINIT_CLIENT_FAILURE",
++ "STATUS_SMARTCARD_CERT_EXPIRED",
++ "STATUS_DRIVER_FAILED_PRIOR_UNLOAD",
++ "STATUS_SMARTCARD_SILENT_CONTEXT",
++ "STATUS_PER_USER_TRUST_QUOTA_EXCEEDED",
++ "STATUS_ALL_USER_TRUST_QUOTA_EXCEEDED",
++ "STATUS_USER_DELETE_TRUST_QUOTA_EXCEEDED",
++ "STATUS_DS_NAME_NOT_UNIQUE",
++ "STATUS_DS_DUPLICATE_ID_FOUND",
++ "STATUS_DS_GROUP_CONVERSION_ERROR",
++ "STATUS_VOLSNAP_PREPARE_HIBERNATE",
++ "STATUS_USER2USER_REQUIRED",
++ "STATUS_STACK_BUFFER_OVERRUN",
++ "STATUS_NO_S4U_PROT_SUPPORT",
++ "STATUS_CROSSREALM_DELEGATION_FAILURE",
++ "STATUS_REVOCATION_OFFLINE_KDC",
++ "STATUS_ISSUING_CA_UNTRUSTED_KDC",
++ "STATUS_KDC_CERT_EXPIRED",
++ "STATUS_KDC_CERT_REVOKED",
++ "STATUS_PARAMETER_QUOTA_EXCEEDED",
++ "STATUS_HIBERNATION_FAILURE",
++ "STATUS_DELAY_LOAD_FAILED",
++ "STATUS_AUTHENTICATION_FIREWALL_FAILED",
++ "STATUS_VDM_DISALLOWED",
++ "STATUS_HUNG_DISPLAY_DRIVER_THREAD",
++ "STATUS_INSUFFICIENT_RESOURCE_FOR_SPECIFIED_SHARED_SECTION_SIZE",
++ "STATUS_INVALID_CRUNTIME_PARAMETER",
++ "STATUS_NTLM_BLOCKED",
++ "STATUS_DS_SRC_SID_EXISTS_IN_FOREST",
++ "STATUS_DS_DOMAIN_NAME_EXISTS_IN_FOREST",
++ "STATUS_DS_FLAT_NAME_EXISTS_IN_FOREST",
++ "STATUS_INVALID_USER_PRINCIPAL_NAME",
++ "STATUS_FATAL_USER_CALLBACK_EXCEPTION",
++ "STATUS_ASSERTION_FAILURE",
++ "STATUS_VERIFIER_STOP",
++ "STATUS_CALLBACK_POP_STACK",
++ "STATUS_INCOMPATIBLE_DRIVER_BLOCKED",
++ "STATUS_HIVE_UNLOADED",
++ "STATUS_COMPRESSION_DISABLED",
++ "STATUS_FILE_SYSTEM_LIMITATION",
++ "STATUS_INVALID_IMAGE_HASH",
++ "STATUS_NOT_CAPABLE",
++ "STATUS_REQUEST_OUT_OF_SEQUENCE",
++ "STATUS_IMPLEMENTATION_LIMIT",
++ "STATUS_ELEVATION_REQUIRED",
++ "STATUS_NO_SECURITY_CONTEXT",
++ "STATUS_PKU2U_CERT_FAILURE",
++ "STATUS_BEYOND_VDL",
++ "STATUS_ENCOUNTERED_WRITE_IN_PROGRESS",
++ "STATUS_PTE_CHANGED",
++ "STATUS_PURGE_FAILED",
++ "STATUS_CRED_REQUIRES_CONFIRMATION",
++ "STATUS_CS_ENCRYPTION_INVALID_SERVER_RESPONSE",
++ "STATUS_CS_ENCRYPTION_UNSUPPORTED_SERVER",
++ "STATUS_CS_ENCRYPTION_EXISTING_ENCRYPTED_FILE",
++ "STATUS_CS_ENCRYPTION_NEW_ENCRYPTED_FILE",
++ "STATUS_CS_ENCRYPTION_FILE_NOT_CSE",
++ "STATUS_INVALID_LABEL",
++ "STATUS_DRIVER_PROCESS_TERMINATED",
++ "STATUS_AMBIGUOUS_SYSTEM_DEVICE",
++ "STATUS_SYSTEM_DEVICE_NOT_FOUND",
++ "STATUS_RESTART_BOOT_APPLICATION",
++ "STATUS_INSUFFICIENT_NVRAM_RESOURCES",
++ "STATUS_INVALID_SESSION",
++ "STATUS_THREAD_ALREADY_IN_SESSION",
++ "STATUS_THREAD_NOT_IN_SESSION",
++ "STATUS_INVALID_WEIGHT",
++ "STATUS_REQUEST_PAUSED",
++ "STATUS_NO_RANGES_PROCESSED",
++ "STATUS_DISK_RESOURCES_EXHAUSTED",
++ "STATUS_NEEDS_REMEDIATION",
++ "STATUS_DEVICE_FEATURE_NOT_SUPPORTED",
++ "STATUS_DEVICE_UNREACHABLE",
++ "STATUS_INVALID_TOKEN",
++ "STATUS_SERVER_UNAVAILABLE",
++ "STATUS_FILE_NOT_AVAILABLE",
++ "STATUS_DEVICE_INSUFFICIENT_RESOURCES",
++ "STATUS_PACKAGE_UPDATING",
++ "STATUS_NOT_READ_FROM_COPY",
++ "STATUS_FT_WRITE_FAILURE",
++ "STATUS_FT_DI_SCAN_REQUIRED",
++ "STATUS_OBJECT_NOT_EXTERNALLY_BACKED",
++ "STATUS_EXTERNAL_BACKING_PROVIDER_UNKNOWN",
++ "STATUS_COMPRESSION_NOT_BENEFICIAL",
++ "STATUS_DATA_CHECKSUM_ERROR",
++ "STATUS_INTERMIXED_KERNEL_EA_OPERATION",
++ "STATUS_TRIM_READ_ZERO_NOT_SUPPORTED",
++ "STATUS_TOO_MANY_SEGMENT_DESCRIPTORS",
++ "STATUS_INVALID_OFFSET_ALIGNMENT",
++ "STATUS_INVALID_FIELD_IN_PARAMETER_LIST",
++ "STATUS_OPERATION_IN_PROGRESS",
++ "STATUS_INVALID_INITIATOR_TARGET_PATH",
++ "STATUS_SCRUB_DATA_DISABLED",
++ "STATUS_NOT_REDUNDANT_STORAGE",
++ "STATUS_RESIDENT_FILE_NOT_SUPPORTED",
++ "STATUS_COMPRESSED_FILE_NOT_SUPPORTED",
++ "STATUS_DIRECTORY_NOT_SUPPORTED",
++ "STATUS_IO_OPERATION_TIMEOUT",
++ "STATUS_SYSTEM_NEEDS_REMEDIATION",
++ "STATUS_APPX_INTEGRITY_FAILURE_CLR_NGEN",
++ "STATUS_SHARE_UNAVAILABLE",
++ "STATUS_APISET_NOT_HOSTED",
++ "STATUS_APISET_NOT_PRESENT",
++ "STATUS_DEVICE_HARDWARE_ERROR",
++ "STATUS_FIRMWARE_SLOT_INVALID",
++ "STATUS_FIRMWARE_IMAGE_INVALID",
++ "STATUS_STORAGE_TOPOLOGY_ID_MISMATCH",
++ "STATUS_WIM_NOT_BOOTABLE",
++ "STATUS_BLOCKED_BY_PARENTAL_CONTROLS",
++ "STATUS_NEEDS_REGISTRATION",
++ "STATUS_QUOTA_ACTIVITY",
++ "STATUS_CALLBACK_INVOKE_INLINE",
++ "STATUS_BLOCK_TOO_MANY_REFERENCES",
++ "STATUS_MARKED_TO_DISALLOW_WRITES",
++ "STATUS_NETWORK_ACCESS_DENIED_EDP",
++ "STATUS_ENCLAVE_FAILURE",
++ "STATUS_PNP_NO_COMPAT_DRIVERS",
++ "STATUS_PNP_DRIVER_PACKAGE_NOT_FOUND",
++ "STATUS_PNP_DRIVER_CONFIGURATION_NOT_FOUND",
++ "STATUS_PNP_DRIVER_CONFIGURATION_INCOMPLETE",
++ "STATUS_PNP_FUNCTION_DRIVER_REQUIRED",
++ "STATUS_PNP_DEVICE_CONFIGURATION_PENDING",
++ "STATUS_DEVICE_HINT_NAME_BUFFER_TOO_SMALL",
++ "STATUS_PACKAGE_NOT_AVAILABLE",
++ "STATUS_DEVICE_IN_MAINTENANCE",
++ "STATUS_NOT_SUPPORTED_ON_DAX",
++ "STATUS_FREE_SPACE_TOO_FRAGMENTED",
++ "STATUS_DAX_MAPPING_EXISTS",
++ "STATUS_CHILD_PROCESS_BLOCKED",
++ "STATUS_STORAGE_LOST_DATA_PERSISTENCE",
++ "STATUS_VRF_CFG_AND_IO_ENABLED",
++ "STATUS_PARTITION_TERMINATING",
++ "STATUS_EXTERNAL_SYSKEY_NOT_SUPPORTED",
++ "STATUS_ENCLAVE_VIOLATION",
++ "STATUS_FILE_PROTECTED_UNDER_DPL",
++ "STATUS_VOLUME_NOT_CLUSTER_ALIGNED",
++ "STATUS_NO_PHYSICALLY_ALIGNED_FREE_SPACE_FOUND",
++ "STATUS_APPX_FILE_NOT_ENCRYPTED",
++ "STATUS_RWRAW_ENCRYPTED_FILE_NOT_ENCRYPTED",
++ "STATUS_RWRAW_ENCRYPTED_INVALID_EDATAINFO_FILEOFFSET",
++ "STATUS_RWRAW_ENCRYPTED_INVALID_EDATAINFO_FILERANGE",
++ "STATUS_RWRAW_ENCRYPTED_INVALID_EDATAINFO_PARAMETER",
++ "STATUS_FT_READ_FAILURE",
++ "STATUS_PATCH_CONFLICT",
++ "STATUS_STORAGE_RESERVE_ID_INVALID",
++ "STATUS_STORAGE_RESERVE_DOES_NOT_EXIST",
++ "STATUS_STORAGE_RESERVE_ALREADY_EXISTS",
++ "STATUS_STORAGE_RESERVE_NOT_EMPTY",
++ "STATUS_NOT_A_DAX_VOLUME",
++ "STATUS_NOT_DAX_MAPPABLE",
++ "STATUS_CASE_DIFFERING_NAMES_IN_DIR",
++ "STATUS_FILE_NOT_SUPPORTED",
++ "STATUS_NOT_SUPPORTED_WITH_BTT",
++ "STATUS_ENCRYPTION_DISABLED",
++ "STATUS_ENCRYPTING_METADATA_DISALLOWED",
++ "STATUS_CANT_CLEAR_ENCRYPTION_FLAG",
++ "STATUS_UNSATISFIED_DEPENDENCIES",
++ "STATUS_CASE_SENSITIVE_PATH",
++ "STATUS_HAS_SYSTEM_CRITICAL_FILES",
++ "STATUS_INVALID_TASK_NAME",
++ "STATUS_INVALID_TASK_INDEX",
++ "STATUS_THREAD_ALREADY_IN_TASK",
++ "STATUS_CALLBACK_BYPASS",
++ "STATUS_UNDEFINED_SCOPE",
++ "STATUS_INVALID_CAP",
++ "STATUS_NOT_GUI_PROCESS",
++ "STATUS_DEVICE_HUNG",
++ "STATUS_CONTAINER_ASSIGNED",
++ "STATUS_JOB_NO_CONTAINER",
++ "STATUS_DEVICE_UNRESPONSIVE",
++ "STATUS_REPARSE_POINT_ENCOUNTERED",
++ "STATUS_ATTRIBUTE_NOT_PRESENT",
++ "STATUS_NOT_A_TIERED_VOLUME",
++ "STATUS_ALREADY_HAS_STREAM_ID",
++ "STATUS_JOB_NOT_EMPTY",
++ "STATUS_ALREADY_INITIALIZED",
++ "STATUS_ENCLAVE_NOT_TERMINATED",
++ "STATUS_ENCLAVE_IS_TERMINATING",
++ "STATUS_SMB1_NOT_AVAILABLE",
++ "STATUS_SMR_GARBAGE_COLLECTION_REQUIRED",
++ "STATUS_INTERRUPTED",
++ "STATUS_THREAD_NOT_RUNNING",
++ "STATUS_FAIL_FAST_EXCEPTION",
++ "STATUS_IMAGE_CERT_REVOKED",
++ "STATUS_DYNAMIC_CODE_BLOCKED",
++ "STATUS_IMAGE_CERT_EXPIRED",
++ "STATUS_STRICT_CFG_VIOLATION",
++ "STATUS_SET_CONTEXT_DENIED",
++ "STATUS_CROSS_PARTITION_VIOLATION",
++ "STATUS_PORT_CLOSED",
++ "STATUS_MESSAGE_LOST",
++ "STATUS_INVALID_MESSAGE",
++ "STATUS_REQUEST_CANCELED",
++ "STATUS_RECURSIVE_DISPATCH",
++ "STATUS_LPC_RECEIVE_BUFFER_EXPECTED",
++ "STATUS_LPC_INVALID_CONNECTION_USAGE",
++ "STATUS_LPC_REQUESTS_NOT_ALLOWED",
++ "STATUS_RESOURCE_IN_USE",
++ "STATUS_HARDWARE_MEMORY_ERROR",
++ "STATUS_THREADPOOL_HANDLE_EXCEPTION",
++ "STATUS_THREADPOOL_SET_EVENT_ON_COMPLETION_FAILED",
++ "STATUS_THREADPOOL_RELEASE_SEMAPHORE_ON_COMPLETION_FAILED",
++ "STATUS_THREADPOOL_RELEASE_MUTEX_ON_COMPLETION_FAILED",
++ "STATUS_THREADPOOL_FREE_LIBRARY_ON_COMPLETION_FAILED",
++ "STATUS_THREADPOOL_RELEASED_DURING_OPERATION",
++ "STATUS_CALLBACK_RETURNED_WHILE_IMPERSONATING",
++ "STATUS_APC_RETURNED_WHILE_IMPERSONATING",
++ "STATUS_PROCESS_IS_PROTECTED",
++ "STATUS_MCA_EXCEPTION",
++ "STATUS_CERTIFICATE_MAPPING_NOT_UNIQUE",
++ "STATUS_SYMLINK_CLASS_DISABLED",
++ "STATUS_INVALID_IDN_NORMALIZATION",
++ "STATUS_NO_UNICODE_TRANSLATION",
++ "STATUS_ALREADY_REGISTERED",
++ "STATUS_CONTEXT_MISMATCH",
++ "STATUS_PORT_ALREADY_HAS_COMPLETION_LIST",
++ "STATUS_CALLBACK_RETURNED_THREAD_PRIORITY",
++ "STATUS_INVALID_THREAD",
++ "STATUS_CALLBACK_RETURNED_TRANSACTION",
++ "STATUS_CALLBACK_RETURNED_LDR_LOCK",
++ "STATUS_CALLBACK_RETURNED_LANG",
++ "STATUS_CALLBACK_RETURNED_PRI_BACK",
++ "STATUS_CALLBACK_RETURNED_THREAD_AFFINITY",
++ "STATUS_LPC_HANDLE_COUNT_EXCEEDED",
++ "STATUS_EXECUTABLE_MEMORY_WRITE",
++ "STATUS_KERNEL_EXECUTABLE_MEMORY_WRITE",
++ "STATUS_ATTACHED_EXECUTABLE_MEMORY_WRITE",
++ "STATUS_TRIGGERED_EXECUTABLE_MEMORY_WRITE",
++ "STATUS_DISK_REPAIR_DISABLED",
++ "STATUS_DS_DOMAIN_RENAME_IN_PROGRESS",
++ "STATUS_DISK_QUOTA_EXCEEDED",
++ "STATUS_CONTENT_BLOCKED",
++ "STATUS_BAD_CLUSTERS",
++ "STATUS_VOLUME_DIRTY",
++ "STATUS_DISK_REPAIR_UNSUCCESSFUL",
++ "STATUS_CORRUPT_LOG_OVERFULL",
++ "STATUS_CORRUPT_LOG_CORRUPTED",
++ "STATUS_CORRUPT_LOG_UNAVAILABLE",
++ "STATUS_CORRUPT_LOG_DELETED_FULL",
++ "STATUS_CORRUPT_LOG_CLEARED",
++ "STATUS_ORPHAN_NAME_EXHAUSTED",
++ "STATUS_PROACTIVE_SCAN_IN_PROGRESS",
++ "STATUS_ENCRYPTED_IO_NOT_POSSIBLE",
++ "STATUS_CORRUPT_LOG_UPLEVEL_RECORDS",
++ "STATUS_FILE_CHECKED_OUT",
++ "STATUS_CHECKOUT_REQUIRED",
++ "STATUS_BAD_FILE_TYPE",
++ "STATUS_FILE_TOO_LARGE",
++ "STATUS_FORMS_AUTH_REQUIRED",
++ "STATUS_VIRUS_INFECTED",
++ "STATUS_VIRUS_DELETED",
++ "STATUS_BAD_MCFG_TABLE",
++ "STATUS_CANNOT_BREAK_OPLOCK",
++ "STATUS_BAD_KEY",
++ "STATUS_BAD_DATA",
++ "STATUS_NO_KEY",
++ "STATUS_FILE_HANDLE_REVOKED",
++ "STATUS_WOW_ASSERTION",
++ "STATUS_INVALID_SIGNATURE",
++ "STATUS_HMAC_NOT_SUPPORTED",
++ "STATUS_AUTH_TAG_MISMATCH",
++ "STATUS_INVALID_STATE_TRANSITION",
++ "STATUS_INVALID_KERNEL_INFO_VERSION",
++ "STATUS_INVALID_PEP_INFO_VERSION",
++ "STATUS_HANDLE_REVOKED",
++ "STATUS_EOF_ON_GHOSTED_RANGE",
++ "STATUS_CC_NEEDS_CALLBACK_SECTION_DRAIN",
++ "STATUS_IPSEC_QUEUE_OVERFLOW",
++ "STATUS_ND_QUEUE_OVERFLOW",
++ "STATUS_HOPLIMIT_EXCEEDED",
++ "STATUS_PROTOCOL_NOT_SUPPORTED",
++ "STATUS_FASTPATH_REJECTED",
++ "STATUS_LOST_WRITEBEHIND_DATA_NETWORK_DISCONNECTED",
++ "STATUS_LOST_WRITEBEHIND_DATA_NETWORK_SERVER_ERROR",
++ "STATUS_LOST_WRITEBEHIND_DATA_LOCAL_DISK_ERROR",
++ "STATUS_XML_PARSE_ERROR",
++ "STATUS_XMLDSIG_ERROR",
++ "STATUS_WRONG_COMPARTMENT",
++ "STATUS_AUTHIP_FAILURE",
++ "STATUS_DS_OID_MAPPED_GROUP_CANT_HAVE_MEMBERS",
++ "STATUS_DS_OID_NOT_FOUND",
++ "STATUS_INCORRECT_ACCOUNT_TYPE",
++ "STATUS_HASH_NOT_SUPPORTED",
++ "STATUS_HASH_NOT_PRESENT",
++ "STATUS_SECONDARY_IC_PROVIDER_NOT_REGISTERED",
++ "STATUS_GPIO_CLIENT_INFORMATION_INVALID",
++ "STATUS_GPIO_VERSION_NOT_SUPPORTED",
++ "STATUS_GPIO_INVALID_REGISTRATION_PACKET",
++ "STATUS_GPIO_OPERATION_DENIED",
++ "STATUS_GPIO_INCOMPATIBLE_CONNECT_MODE",
++ "STATUS_CANNOT_SWITCH_RUNLEVEL",
++ "STATUS_INVALID_RUNLEVEL_SETTING",
++ "STATUS_RUNLEVEL_SWITCH_TIMEOUT",
++ "STATUS_RUNLEVEL_SWITCH_AGENT_TIMEOUT",
++ "STATUS_RUNLEVEL_SWITCH_IN_PROGRESS",
++ "STATUS_NOT_APPCONTAINER",
++ "STATUS_NOT_SUPPORTED_IN_APPCONTAINER",
++ "STATUS_INVALID_PACKAGE_SID_LENGTH",
++ "STATUS_LPAC_ACCESS_DENIED",
++ "STATUS_ADMINLESS_ACCESS_DENIED",
++ "STATUS_APP_DATA_NOT_FOUND",
++ "STATUS_APP_DATA_EXPIRED",
++ "STATUS_APP_DATA_CORRUPT",
++ "STATUS_APP_DATA_LIMIT_EXCEEDED",
++ "STATUS_APP_DATA_REBOOT_REQUIRED",
++ "STATUS_OFFLOAD_READ_FLT_NOT_SUPPORTED",
++ "STATUS_OFFLOAD_WRITE_FLT_NOT_SUPPORTED",
++ "STATUS_OFFLOAD_READ_FILE_NOT_SUPPORTED",
++ "STATUS_OFFLOAD_WRITE_FILE_NOT_SUPPORTED",
++ "STATUS_WOF_WIM_HEADER_CORRUPT",
++ "STATUS_WOF_WIM_RESOURCE_TABLE_CORRUPT",
++ "STATUS_WOF_FILE_RESOURCE_TABLE_CORRUPT",
++ "STATUS_CIMFS_IMAGE_CORRUPT",
++ "STATUS_FILE_SYSTEM_VIRTUALIZATION_UNAVAILABLE",
++ "STATUS_FILE_SYSTEM_VIRTUALIZATION_METADATA_CORRUPT",
++ "STATUS_FILE_SYSTEM_VIRTUALIZATION_BUSY",
++ "STATUS_FILE_SYSTEM_VIRTUALIZATION_PROVIDER_UNKNOWN",
++ "STATUS_FILE_SYSTEM_VIRTUALIZATION_INVALID_OPERATION",
++ "STATUS_CLOUD_FILE_SYNC_ROOT_METADATA_CORRUPT",
++ "STATUS_CLOUD_FILE_PROVIDER_NOT_RUNNING",
++ "STATUS_CLOUD_FILE_METADATA_CORRUPT",
++ "STATUS_CLOUD_FILE_METADATA_TOO_LARGE",
++ "STATUS_CLOUD_FILE_PROPERTY_VERSION_NOT_SUPPORTED",
++ "STATUS_NOT_A_CLOUD_FILE",
++ "STATUS_CLOUD_FILE_NOT_IN_SYNC",
++ "STATUS_CLOUD_FILE_ALREADY_CONNECTED",
++ "STATUS_CLOUD_FILE_NOT_SUPPORTED",
++ "STATUS_CLOUD_FILE_INVALID_REQUEST",
++ "STATUS_CLOUD_FILE_READ_ONLY_VOLUME",
++ "STATUS_CLOUD_FILE_CONNECTED_PROVIDER_ONLY",
++ "STATUS_CLOUD_FILE_VALIDATION_FAILED",
++ "STATUS_CLOUD_FILE_AUTHENTICATION_FAILED",
++ "STATUS_CLOUD_FILE_INSUFFICIENT_RESOURCES",
++ "STATUS_CLOUD_FILE_NETWORK_UNAVAILABLE",
++ "STATUS_CLOUD_FILE_UNSUCCESSFUL",
++ "STATUS_CLOUD_FILE_NOT_UNDER_SYNC_ROOT",
++ "STATUS_CLOUD_FILE_IN_USE",
++ "STATUS_CLOUD_FILE_PINNED",
++ "STATUS_CLOUD_FILE_REQUEST_ABORTED",
++ "STATUS_CLOUD_FILE_PROPERTY_CORRUPT",
++ "STATUS_CLOUD_FILE_ACCESS_DENIED",
++ "STATUS_CLOUD_FILE_INCOMPATIBLE_HARDLINKS",
++ "STATUS_CLOUD_FILE_PROPERTY_LOCK_CONFLICT",
++ "STATUS_CLOUD_FILE_REQUEST_CANCELED",
++ "STATUS_CLOUD_FILE_PROVIDER_TERMINATED",
++ "STATUS_NOT_A_CLOUD_SYNC_ROOT",
++ "STATUS_CLOUD_FILE_REQUEST_TIMEOUT",
++ "STATUS_CLOUD_FILE_DEHYDRATION_DISALLOWED",
++ "STATUS_FILE_SNAP_IN_PROGRESS",
++ "STATUS_FILE_SNAP_USER_SECTION_NOT_SUPPORTED",
++ "STATUS_FILE_SNAP_MODIFY_NOT_SUPPORTED",
++ "STATUS_FILE_SNAP_IO_NOT_COORDINATED",
++ "STATUS_FILE_SNAP_UNEXPECTED_ERROR",
++ "STATUS_FILE_SNAP_INVALID_PARAMETER",
++ "DBG_NO_STATE_CHANGE",
++ "DBG_APP_NOT_IDLE",
++ "RPC_NT_INVALID_STRING_BINDING",
++ "RPC_NT_WRONG_KIND_OF_BINDING",
++ "RPC_NT_INVALID_BINDING",
++ "RPC_NT_PROTSEQ_NOT_SUPPORTED",
++ "RPC_NT_INVALID_RPC_PROTSEQ",
++ "RPC_NT_INVALID_STRING_UUID",
++ "RPC_NT_INVALID_ENDPOINT_FORMAT",
++ "RPC_NT_INVALID_NET_ADDR",
++ "RPC_NT_NO_ENDPOINT_FOUND",
++ "RPC_NT_INVALID_TIMEOUT",
++ "RPC_NT_OBJECT_NOT_FOUND",
++ "RPC_NT_ALREADY_REGISTERED",
++ "RPC_NT_TYPE_ALREADY_REGISTERED",
++ "RPC_NT_ALREADY_LISTENING",
++ "RPC_NT_NO_PROTSEQS_REGISTERED",
++ "RPC_NT_NOT_LISTENING",
++ "RPC_NT_UNKNOWN_MGR_TYPE",
++ "RPC_NT_UNKNOWN_IF",
++ "RPC_NT_NO_BINDINGS",
++ "RPC_NT_NO_PROTSEQS",
++ "RPC_NT_CANT_CREATE_ENDPOINT",
++ "RPC_NT_OUT_OF_RESOURCES",
++ "RPC_NT_SERVER_UNAVAILABLE",
++ "RPC_NT_SERVER_TOO_BUSY",
++ "RPC_NT_INVALID_NETWORK_OPTIONS",
++ "RPC_NT_NO_CALL_ACTIVE",
++ "RPC_NT_CALL_FAILED",
++ "RPC_NT_CALL_FAILED_DNE",
++ "RPC_NT_PROTOCOL_ERROR",
++ "RPC_NT_UNSUPPORTED_TRANS_SYN",
++ "RPC_NT_UNSUPPORTED_TYPE",
++ "RPC_NT_INVALID_TAG",
++ "RPC_NT_INVALID_BOUND",
++ "RPC_NT_NO_ENTRY_NAME",
++ "RPC_NT_INVALID_NAME_SYNTAX",
++ "RPC_NT_UNSUPPORTED_NAME_SYNTAX",
++ "RPC_NT_UUID_NO_ADDRESS",
++ "RPC_NT_DUPLICATE_ENDPOINT",
++ "RPC_NT_UNKNOWN_AUTHN_TYPE",
++ "RPC_NT_MAX_CALLS_TOO_SMALL",
++ "RPC_NT_STRING_TOO_LONG",
++ "RPC_NT_PROTSEQ_NOT_FOUND",
++ "RPC_NT_PROCNUM_OUT_OF_RANGE",
++ "RPC_NT_BINDING_HAS_NO_AUTH",
++ "RPC_NT_UNKNOWN_AUTHN_SERVICE",
++ "RPC_NT_UNKNOWN_AUTHN_LEVEL",
++ "RPC_NT_INVALID_AUTH_IDENTITY",
++ "RPC_NT_UNKNOWN_AUTHZ_SERVICE",
++ "EPT_NT_INVALID_ENTRY",
++ "EPT_NT_CANT_PERFORM_OP",
++ "EPT_NT_NOT_REGISTERED",
++ "RPC_NT_NOTHING_TO_EXPORT",
++ "RPC_NT_INCOMPLETE_NAME",
++ "RPC_NT_INVALID_VERS_OPTION",
++ "RPC_NT_NO_MORE_MEMBERS",
++ "RPC_NT_NOT_ALL_OBJS_UNEXPORTED",
++ "RPC_NT_INTERFACE_NOT_FOUND",
++ "RPC_NT_ENTRY_ALREADY_EXISTS",
++ "RPC_NT_ENTRY_NOT_FOUND",
++ "RPC_NT_NAME_SERVICE_UNAVAILABLE",
++ "RPC_NT_INVALID_NAF_ID",
++ "RPC_NT_CANNOT_SUPPORT",
++ "RPC_NT_NO_CONTEXT_AVAILABLE",
++ "RPC_NT_INTERNAL_ERROR",
++ "RPC_NT_ZERO_DIVIDE",
++ "RPC_NT_ADDRESS_ERROR",
++ "RPC_NT_FP_DIV_ZERO",
++ "RPC_NT_FP_UNDERFLOW",
++ "RPC_NT_FP_OVERFLOW",
++ "RPC_NT_CALL_IN_PROGRESS",
++ "RPC_NT_NO_MORE_BINDINGS",
++ "RPC_NT_GROUP_MEMBER_NOT_FOUND",
++ "EPT_NT_CANT_CREATE",
++ "RPC_NT_INVALID_OBJECT",
++ "RPC_NT_NO_INTERFACES",
++ "RPC_NT_CALL_CANCELLED",
++ "RPC_NT_BINDING_INCOMPLETE",
++ "RPC_NT_COMM_FAILURE",
++ "RPC_NT_UNSUPPORTED_AUTHN_LEVEL",
++ "RPC_NT_NO_PRINC_NAME",
++ "RPC_NT_NOT_RPC_ERROR",
++ "RPC_NT_SEC_PKG_ERROR",
++ "RPC_NT_NOT_CANCELLED",
++ "RPC_NT_INVALID_ASYNC_HANDLE",
++ "RPC_NT_INVALID_ASYNC_CALL",
++ "RPC_NT_PROXY_ACCESS_DENIED",
++ "RPC_NT_COOKIE_AUTH_FAILED",
++ "RPC_NT_NO_MORE_ENTRIES",
++ "RPC_NT_SS_CHAR_TRANS_OPEN_FAIL",
++ "RPC_NT_SS_CHAR_TRANS_SHORT_FILE",
++ "RPC_NT_SS_IN_NULL_CONTEXT",
++ "RPC_NT_SS_CONTEXT_MISMATCH",
++ "RPC_NT_SS_CONTEXT_DAMAGED",
++ "RPC_NT_SS_HANDLES_MISMATCH",
++ "RPC_NT_SS_CANNOT_GET_CALL_HANDLE",
++ "RPC_NT_NULL_REF_POINTER",
++ "RPC_NT_ENUM_VALUE_OUT_OF_RANGE",
++ "RPC_NT_BYTE_COUNT_TOO_SMALL",
++ "RPC_NT_BAD_STUB_DATA",
++ "RPC_NT_INVALID_ES_ACTION",
++ "RPC_NT_WRONG_ES_VERSION",
++ "RPC_NT_WRONG_STUB_VERSION",
++ "RPC_NT_INVALID_PIPE_OBJECT",
++ "RPC_NT_INVALID_PIPE_OPERATION",
++ "RPC_NT_WRONG_PIPE_VERSION",
++ "RPC_NT_PIPE_CLOSED",
++ "RPC_NT_PIPE_DISCIPLINE_ERROR",
++ "RPC_NT_PIPE_EMPTY",
++ "STATUS_PNP_BAD_MPS_TABLE",
++ "STATUS_PNP_TRANSLATION_FAILED",
++ "STATUS_PNP_IRQ_TRANSLATION_FAILED",
++ "STATUS_PNP_INVALID_ID",
++ "STATUS_IO_REISSUE_AS_CACHED",
++ "STATUS_CTX_WINSTATION_NAME_INVALID",
++ "STATUS_CTX_INVALID_PD",
++ "STATUS_CTX_PD_NOT_FOUND",
++ "STATUS_CTX_CLOSE_PENDING",
++ "STATUS_CTX_NO_OUTBUF",
++ "STATUS_CTX_MODEM_INF_NOT_FOUND",
++ "STATUS_CTX_INVALID_MODEMNAME",
++ "STATUS_CTX_RESPONSE_ERROR",
++ "STATUS_CTX_MODEM_RESPONSE_TIMEOUT",
++ "STATUS_CTX_MODEM_RESPONSE_NO_CARRIER",
++ "STATUS_CTX_MODEM_RESPONSE_NO_DIALTONE",
++ "STATUS_CTX_MODEM_RESPONSE_BUSY",
++ "STATUS_CTX_MODEM_RESPONSE_VOICE",
++ "STATUS_CTX_TD_ERROR",
++ "STATUS_CTX_LICENSE_CLIENT_INVALID",
++ "STATUS_CTX_LICENSE_NOT_AVAILABLE",
++ "STATUS_CTX_LICENSE_EXPIRED",
++ "STATUS_CTX_WINSTATION_NOT_FOUND",
++ "STATUS_CTX_WINSTATION_NAME_COLLISION",
++ "STATUS_CTX_WINSTATION_BUSY",
++ "STATUS_CTX_BAD_VIDEO_MODE",
++ "STATUS_CTX_GRAPHICS_INVALID",
++ "STATUS_CTX_NOT_CONSOLE",
++ "STATUS_CTX_CLIENT_QUERY_TIMEOUT",
++ "STATUS_CTX_CONSOLE_DISCONNECT",
++ "STATUS_CTX_CONSOLE_CONNECT",
++ "STATUS_CTX_SHADOW_DENIED",
++ "STATUS_CTX_WINSTATION_ACCESS_DENIED",
++ "STATUS_CTX_INVALID_WD",
++ "STATUS_CTX_WD_NOT_FOUND",
++ "STATUS_CTX_SHADOW_INVALID",
++ "STATUS_CTX_SHADOW_DISABLED",
++ "STATUS_RDP_PROTOCOL_ERROR",
++ "STATUS_CTX_CLIENT_LICENSE_NOT_SET",
++ "STATUS_CTX_CLIENT_LICENSE_IN_USE",
++ "STATUS_CTX_SHADOW_ENDED_BY_MODE_CHANGE",
++ "STATUS_CTX_SHADOW_NOT_RUNNING",
++ "STATUS_CTX_LOGON_DISABLED",
++ "STATUS_CTX_SECURITY_LAYER_ERROR",
++ "STATUS_TS_INCOMPATIBLE_SESSIONS",
++ "STATUS_TS_VIDEO_SUBSYSTEM_ERROR",
++ "STATUS_MUI_FILE_NOT_FOUND",
++ "STATUS_MUI_INVALID_FILE",
++ "STATUS_MUI_INVALID_RC_CONFIG",
++ "STATUS_MUI_INVALID_LOCALE_NAME",
++ "STATUS_MUI_INVALID_ULTIMATEFALLBACK_NAME",
++ "STATUS_MUI_FILE_NOT_LOADED",
++ "STATUS_RESOURCE_ENUM_USER_STOP",
++ "STATUS_CLUSTER_INVALID_NODE",
++ "STATUS_CLUSTER_NODE_EXISTS",
++ "STATUS_CLUSTER_JOIN_IN_PROGRESS",
++ "STATUS_CLUSTER_NODE_NOT_FOUND",
++ "STATUS_CLUSTER_LOCAL_NODE_NOT_FOUND",
++ "STATUS_CLUSTER_NETWORK_EXISTS",
++ "STATUS_CLUSTER_NETWORK_NOT_FOUND",
++ "STATUS_CLUSTER_NETINTERFACE_EXISTS",
++ "STATUS_CLUSTER_NETINTERFACE_NOT_FOUND",
++ "STATUS_CLUSTER_INVALID_REQUEST",
++ "STATUS_CLUSTER_INVALID_NETWORK_PROVIDER",
++ "STATUS_CLUSTER_NODE_DOWN",
++ "STATUS_CLUSTER_NODE_UNREACHABLE",
++ "STATUS_CLUSTER_NODE_NOT_MEMBER",
++ "STATUS_CLUSTER_JOIN_NOT_IN_PROGRESS",
++ "STATUS_CLUSTER_INVALID_NETWORK",
++ "STATUS_CLUSTER_NO_NET_ADAPTERS",
++ "STATUS_CLUSTER_NODE_UP",
++ "STATUS_CLUSTER_NODE_PAUSED",
++ "STATUS_CLUSTER_NODE_NOT_PAUSED",
++ "STATUS_CLUSTER_NO_SECURITY_CONTEXT",
++ "STATUS_CLUSTER_NETWORK_NOT_INTERNAL",
++ "STATUS_CLUSTER_POISONED",
++ "STATUS_CLUSTER_NON_CSV_PATH",
++ "STATUS_CLUSTER_CSV_VOLUME_NOT_LOCAL",
++ "STATUS_CLUSTER_CSV_READ_OPLOCK_BREAK_IN_PROGRESS",
++ "STATUS_CLUSTER_CSV_AUTO_PAUSE_ERROR",
++ "STATUS_CLUSTER_CSV_REDIRECTED",
++ "STATUS_CLUSTER_CSV_NOT_REDIRECTED",
++ "STATUS_CLUSTER_CSV_VOLUME_DRAINING",
++ "STATUS_CLUSTER_CSV_SNAPSHOT_CREATION_IN_PROGRESS",
++ "STATUS_CLUSTER_CSV_VOLUME_DRAINING_SUCCEEDED_DOWNLEVEL",
++ "STATUS_CLUSTER_CSV_NO_SNAPSHOTS",
++ "STATUS_CSV_IO_PAUSE_TIMEOUT",
++ "STATUS_CLUSTER_CSV_INVALID_HANDLE",
++ "STATUS_CLUSTER_CSV_SUPPORTED_ONLY_ON_COORDINATOR",
++ "STATUS_CLUSTER_CAM_TICKET_REPLAY_DETECTED",
++ "STATUS_ACPI_INVALID_OPCODE",
++ "STATUS_ACPI_STACK_OVERFLOW",
++ "STATUS_ACPI_ASSERT_FAILED",
++ "STATUS_ACPI_INVALID_INDEX",
++ "STATUS_ACPI_INVALID_ARGUMENT",
++ "STATUS_ACPI_FATAL",
++ "STATUS_ACPI_INVALID_SUPERNAME",
++ "STATUS_ACPI_INVALID_ARGTYPE",
++ "STATUS_ACPI_INVALID_OBJTYPE",
++ "STATUS_ACPI_INVALID_TARGETTYPE",
++ "STATUS_ACPI_INCORRECT_ARGUMENT_COUNT",
++ "STATUS_ACPI_ADDRESS_NOT_MAPPED",
++ "STATUS_ACPI_INVALID_EVENTTYPE",
++ "STATUS_ACPI_HANDLER_COLLISION",
++ "STATUS_ACPI_INVALID_DATA",
++ "STATUS_ACPI_INVALID_REGION",
++ "STATUS_ACPI_INVALID_ACCESS_SIZE",
++ "STATUS_ACPI_ACQUIRE_GLOBAL_LOCK",
++ "STATUS_ACPI_ALREADY_INITIALIZED",
++ "STATUS_ACPI_NOT_INITIALIZED",
++ "STATUS_ACPI_INVALID_MUTEX_LEVEL",
++ "STATUS_ACPI_MUTEX_NOT_OWNED",
++ "STATUS_ACPI_MUTEX_NOT_OWNER",
++ "STATUS_ACPI_RS_ACCESS",
++ "STATUS_ACPI_INVALID_TABLE",
++ "STATUS_ACPI_REG_HANDLER_FAILED",
++ "STATUS_ACPI_POWER_REQUEST_FAILED",
++ "STATUS_SXS_SECTION_NOT_FOUND",
++ "STATUS_SXS_CANT_GEN_ACTCTX",
++ "STATUS_SXS_INVALID_ACTCTXDATA_FORMAT",
++ "STATUS_SXS_ASSEMBLY_NOT_FOUND",
++ "STATUS_SXS_MANIFEST_FORMAT_ERROR",
++ "STATUS_SXS_MANIFEST_PARSE_ERROR",
++ "STATUS_SXS_ACTIVATION_CONTEXT_DISABLED",
++ "STATUS_SXS_KEY_NOT_FOUND",
++ "STATUS_SXS_VERSION_CONFLICT",
++ "STATUS_SXS_WRONG_SECTION_TYPE",
++ "STATUS_SXS_THREAD_QUERIES_DISABLED",
++ "STATUS_SXS_ASSEMBLY_MISSING",
++ "STATUS_SXS_PROCESS_DEFAULT_ALREADY_SET",
++ "STATUS_SXS_EARLY_DEACTIVATION",
++ "STATUS_SXS_INVALID_DEACTIVATION",
++ "STATUS_SXS_MULTIPLE_DEACTIVATION",
++ "STATUS_SXS_SYSTEM_DEFAULT_ACTIVATION_CONTEXT_EMPTY",
++ "STATUS_SXS_PROCESS_TERMINATION_REQUESTED",
++ "STATUS_SXS_CORRUPT_ACTIVATION_STACK",
++ "STATUS_SXS_CORRUPTION",
++ "STATUS_SXS_INVALID_IDENTITY_ATTRIBUTE_VALUE",
++ "STATUS_SXS_INVALID_IDENTITY_ATTRIBUTE_NAME",
++ "STATUS_SXS_IDENTITY_DUPLICATE_ATTRIBUTE",
++ "STATUS_SXS_IDENTITY_PARSE_ERROR",
++ "STATUS_SXS_COMPONENT_STORE_CORRUPT",
++ "STATUS_SXS_FILE_HASH_MISMATCH",
++ "STATUS_SXS_MANIFEST_IDENTITY_SAME_BUT_CONTENTS_DIFFERENT",
++ "STATUS_SXS_IDENTITIES_DIFFERENT",
++ "STATUS_SXS_ASSEMBLY_IS_NOT_A_DEPLOYMENT",
++ "STATUS_SXS_FILE_NOT_PART_OF_ASSEMBLY",
++ "STATUS_ADVANCED_INSTALLER_FAILED",
++ "STATUS_XML_ENCODING_MISMATCH",
++ "STATUS_SXS_MANIFEST_TOO_BIG",
++ "STATUS_SXS_SETTING_NOT_REGISTERED",
++ "STATUS_SXS_TRANSACTION_CLOSURE_INCOMPLETE",
++ "STATUS_SMI_PRIMITIVE_INSTALLER_FAILED",
++ "STATUS_GENERIC_COMMAND_FAILED",
++ "STATUS_SXS_FILE_HASH_MISSING",
++ "STATUS_TRANSACTIONAL_CONFLICT",
++ "STATUS_INVALID_TRANSACTION",
++ "STATUS_TRANSACTION_NOT_ACTIVE",
++ "STATUS_TM_INITIALIZATION_FAILED",
++ "STATUS_RM_NOT_ACTIVE",
++ "STATUS_RM_METADATA_CORRUPT",
++ "STATUS_TRANSACTION_NOT_JOINED",
++ "STATUS_DIRECTORY_NOT_RM",
++ "STATUS_TRANSACTIONS_UNSUPPORTED_REMOTE",
++ "STATUS_LOG_RESIZE_INVALID_SIZE",
++ "STATUS_REMOTE_FILE_VERSION_MISMATCH",
++ "STATUS_CRM_PROTOCOL_ALREADY_EXISTS",
++ "STATUS_TRANSACTION_PROPAGATION_FAILED",
++ "STATUS_CRM_PROTOCOL_NOT_FOUND",
++ "STATUS_TRANSACTION_SUPERIOR_EXISTS",
++ "STATUS_TRANSACTION_REQUEST_NOT_VALID",
++ "STATUS_TRANSACTION_NOT_REQUESTED",
++ "STATUS_TRANSACTION_ALREADY_ABORTED",
++ "STATUS_TRANSACTION_ALREADY_COMMITTED",
++ "STATUS_TRANSACTION_INVALID_MARSHALL_BUFFER",
++ "STATUS_CURRENT_TRANSACTION_NOT_VALID",
++ "STATUS_LOG_GROWTH_FAILED",
++ "STATUS_OBJECT_NO_LONGER_EXISTS",
++ "STATUS_STREAM_MINIVERSION_NOT_FOUND",
++ "STATUS_STREAM_MINIVERSION_NOT_VALID",
++ "STATUS_MINIVERSION_INACCESSIBLE_FROM_SPECIFIED_TRANSACTION",
++ "STATUS_CANT_OPEN_MINIVERSION_WITH_MODIFY_INTENT",
++ "STATUS_CANT_CREATE_MORE_STREAM_MINIVERSIONS",
++ "STATUS_HANDLE_NO_LONGER_VALID",
++ "STATUS_LOG_CORRUPTION_DETECTED",
++ "STATUS_RM_DISCONNECTED",
++ "STATUS_ENLISTMENT_NOT_SUPERIOR",
++ "STATUS_FILE_IDENTITY_NOT_PERSISTENT",
++ "STATUS_CANT_BREAK_TRANSACTIONAL_DEPENDENCY",
++ "STATUS_CANT_CROSS_RM_BOUNDARY",
++ "STATUS_TXF_DIR_NOT_EMPTY",
++ "STATUS_INDOUBT_TRANSACTIONS_EXIST",
++ "STATUS_TM_VOLATILE",
++ "STATUS_ROLLBACK_TIMER_EXPIRED",
++ "STATUS_TXF_ATTRIBUTE_CORRUPT",
++ "STATUS_EFS_NOT_ALLOWED_IN_TRANSACTION",
++ "STATUS_TRANSACTIONAL_OPEN_NOT_ALLOWED",
++ "STATUS_TRANSACTED_MAPPING_UNSUPPORTED_REMOTE",
++ "STATUS_TRANSACTION_REQUIRED_PROMOTION",
++ "STATUS_CANNOT_EXECUTE_FILE_IN_TRANSACTION",
++ "STATUS_TRANSACTIONS_NOT_FROZEN",
++ "STATUS_TRANSACTION_FREEZE_IN_PROGRESS",
++ "STATUS_NOT_SNAPSHOT_VOLUME",
++ "STATUS_NO_SAVEPOINT_WITH_OPEN_FILES",
++ "STATUS_SPARSE_NOT_ALLOWED_IN_TRANSACTION",
++ "STATUS_TM_IDENTITY_MISMATCH",
++ "STATUS_FLOATED_SECTION",
++ "STATUS_CANNOT_ACCEPT_TRANSACTED_WORK",
++ "STATUS_CANNOT_ABORT_TRANSACTIONS",
++ "STATUS_TRANSACTION_NOT_FOUND",
++ "STATUS_RESOURCEMANAGER_NOT_FOUND",
++ "STATUS_ENLISTMENT_NOT_FOUND",
++ "STATUS_TRANSACTIONMANAGER_NOT_FOUND",
++ "STATUS_TRANSACTIONMANAGER_NOT_ONLINE",
++ "STATUS_TRANSACTIONMANAGER_RECOVERY_NAME_COLLISION",
++ "STATUS_TRANSACTION_NOT_ROOT",
++ "STATUS_TRANSACTION_OBJECT_EXPIRED",
++ "STATUS_COMPRESSION_NOT_ALLOWED_IN_TRANSACTION",
++ "STATUS_TRANSACTION_RESPONSE_NOT_ENLISTED",
++ "STATUS_TRANSACTION_RECORD_TOO_LONG",
++ "STATUS_NO_LINK_TRACKING_IN_TRANSACTION",
++ "STATUS_OPERATION_NOT_SUPPORTED_IN_TRANSACTION",
++ "STATUS_TRANSACTION_INTEGRITY_VIOLATED",
++ "STATUS_TRANSACTIONMANAGER_IDENTITY_MISMATCH",
++ "STATUS_RM_CANNOT_BE_FROZEN_FOR_SNAPSHOT",
++ "STATUS_TRANSACTION_MUST_WRITETHROUGH",
++ "STATUS_TRANSACTION_NO_SUPERIOR",
++ "STATUS_EXPIRED_HANDLE",
++ "STATUS_TRANSACTION_NOT_ENLISTED",
++ "STATUS_LOG_SECTOR_INVALID",
++ "STATUS_LOG_SECTOR_PARITY_INVALID",
++ "STATUS_LOG_SECTOR_REMAPPED",
++ "STATUS_LOG_BLOCK_INCOMPLETE",
++ "STATUS_LOG_INVALID_RANGE",
++ "STATUS_LOG_BLOCKS_EXHAUSTED",
++ "STATUS_LOG_READ_CONTEXT_INVALID",
++ "STATUS_LOG_RESTART_INVALID",
++ "STATUS_LOG_BLOCK_VERSION",
++ "STATUS_LOG_BLOCK_INVALID",
++ "STATUS_LOG_READ_MODE_INVALID",
++ "STATUS_LOG_METADATA_CORRUPT",
++ "STATUS_LOG_METADATA_INVALID",
++ "STATUS_LOG_METADATA_INCONSISTENT",
++ "STATUS_LOG_RESERVATION_INVALID",
++ "STATUS_LOG_CANT_DELETE",
++ "STATUS_LOG_CONTAINER_LIMIT_EXCEEDED",
++ "STATUS_LOG_START_OF_LOG",
++ "STATUS_LOG_POLICY_ALREADY_INSTALLED",
++ "STATUS_LOG_POLICY_NOT_INSTALLED",
++ "STATUS_LOG_POLICY_INVALID",
++ "STATUS_LOG_POLICY_CONFLICT",
++ "STATUS_LOG_PINNED_ARCHIVE_TAIL",
++ "STATUS_LOG_RECORD_NONEXISTENT",
++ "STATUS_LOG_RECORDS_RESERVED_INVALID",
++ "STATUS_LOG_SPACE_RESERVED_INVALID",
++ "STATUS_LOG_TAIL_INVALID",
++ "STATUS_LOG_FULL",
++ "STATUS_LOG_MULTIPLEXED",
++ "STATUS_LOG_DEDICATED",
++ "STATUS_LOG_ARCHIVE_NOT_IN_PROGRESS",
++ "STATUS_LOG_ARCHIVE_IN_PROGRESS",
++ "STATUS_LOG_EPHEMERAL",
++ "STATUS_LOG_NOT_ENOUGH_CONTAINERS",
++ "STATUS_LOG_CLIENT_ALREADY_REGISTERED",
++ "STATUS_LOG_CLIENT_NOT_REGISTERED",
++ "STATUS_LOG_FULL_HANDLER_IN_PROGRESS",
++ "STATUS_LOG_CONTAINER_READ_FAILED",
++ "STATUS_LOG_CONTAINER_WRITE_FAILED",
++ "STATUS_LOG_CONTAINER_OPEN_FAILED",
++ "STATUS_LOG_CONTAINER_STATE_INVALID",
++ "STATUS_LOG_STATE_INVALID",
++ "STATUS_LOG_PINNED",
++ "STATUS_LOG_METADATA_FLUSH_FAILED",
++ "STATUS_LOG_INCONSISTENT_SECURITY",
++ "STATUS_LOG_APPENDED_FLUSH_FAILED",
++ "STATUS_LOG_PINNED_RESERVATION",
++ "STATUS_VIDEO_HUNG_DISPLAY_DRIVER_THREAD",
++ "STATUS_FLT_NO_HANDLER_DEFINED",
++ "STATUS_FLT_CONTEXT_ALREADY_DEFINED",
++ "STATUS_FLT_INVALID_ASYNCHRONOUS_REQUEST",
++ "STATUS_FLT_DISALLOW_FAST_IO",
++ "STATUS_FLT_INVALID_NAME_REQUEST",
++ "STATUS_FLT_NOT_SAFE_TO_POST_OPERATION",
++ "STATUS_FLT_NOT_INITIALIZED",
++ "STATUS_FLT_FILTER_NOT_READY",
++ "STATUS_FLT_POST_OPERATION_CLEANUP",
++ "STATUS_FLT_INTERNAL_ERROR",
++ "STATUS_FLT_DELETING_OBJECT",
++ "STATUS_FLT_MUST_BE_NONPAGED_POOL",
++ "STATUS_FLT_DUPLICATE_ENTRY",
++ "STATUS_FLT_CBDQ_DISABLED",
++ "STATUS_FLT_DO_NOT_ATTACH",
++ "STATUS_FLT_DO_NOT_DETACH",
++ "STATUS_FLT_INSTANCE_ALTITUDE_COLLISION",
++ "STATUS_FLT_INSTANCE_NAME_COLLISION",
++ "STATUS_FLT_FILTER_NOT_FOUND",
++ "STATUS_FLT_VOLUME_NOT_FOUND",
++ "STATUS_FLT_INSTANCE_NOT_FOUND",
++ "STATUS_FLT_CONTEXT_ALLOCATION_NOT_FOUND",
++ "STATUS_FLT_INVALID_CONTEXT_REGISTRATION",
++ "STATUS_FLT_NAME_CACHE_MISS",
++ "STATUS_FLT_NO_DEVICE_OBJECT",
++ "STATUS_FLT_VOLUME_ALREADY_MOUNTED",
++ "STATUS_FLT_ALREADY_ENLISTED",
++ "STATUS_FLT_CONTEXT_ALREADY_LINKED",
++ "STATUS_FLT_NO_WAITER_FOR_REPLY",
++ "STATUS_FLT_REGISTRATION_BUSY",
++ "STATUS_MONITOR_NO_DESCRIPTOR",
++ "STATUS_MONITOR_UNKNOWN_DESCRIPTOR_FORMAT",
++ "STATUS_MONITOR_INVALID_DESCRIPTOR_CHECKSUM",
++ "STATUS_MONITOR_INVALID_STANDARD_TIMING_BLOCK",
++ "STATUS_MONITOR_WMI_DATABLOCK_REGISTRATION_FAILED",
++ "STATUS_MONITOR_INVALID_SERIAL_NUMBER_MONDSC_BLOCK",
++ "STATUS_MONITOR_INVALID_USER_FRIENDLY_MONDSC_BLOCK",
++ "STATUS_MONITOR_NO_MORE_DESCRIPTOR_DATA",
++ "STATUS_MONITOR_INVALID_DETAILED_TIMING_BLOCK",
++ "STATUS_MONITOR_INVALID_MANUFACTURE_DATE",
++ "STATUS_GRAPHICS_NOT_EXCLUSIVE_MODE_OWNER",
++ "STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER",
++ "STATUS_GRAPHICS_INVALID_DISPLAY_ADAPTER",
++ "STATUS_GRAPHICS_ADAPTER_WAS_RESET",
++ "STATUS_GRAPHICS_INVALID_DRIVER_MODEL",
++ "STATUS_GRAPHICS_PRESENT_MODE_CHANGED",
++ "STATUS_GRAPHICS_PRESENT_OCCLUDED",
++ "STATUS_GRAPHICS_PRESENT_DENIED",
++ "STATUS_GRAPHICS_CANNOTCOLORCONVERT",
++ "STATUS_GRAPHICS_DRIVER_MISMATCH",
++ "STATUS_GRAPHICS_PRESENT_REDIRECTION_DISABLED",
++ "STATUS_GRAPHICS_PRESENT_UNOCCLUDED",
++ "STATUS_GRAPHICS_WINDOWDC_NOT_AVAILABLE",
++ "STATUS_GRAPHICS_WINDOWLESS_PRESENT_DISABLED",
++ "STATUS_GRAPHICS_PRESENT_INVALID_WINDOW",
++ "STATUS_GRAPHICS_PRESENT_BUFFER_NOT_BOUND",
++ "STATUS_GRAPHICS_VAIL_STATE_CHANGED",
++ "STATUS_GRAPHICS_INDIRECT_DISPLAY_ABANDON_SWAPCHAIN",
++ "STATUS_GRAPHICS_INDIRECT_DISPLAY_DEVICE_STOPPED",
++ "STATUS_GRAPHICS_NO_VIDEO_MEMORY",
++ "STATUS_GRAPHICS_CANT_LOCK_MEMORY",
++ "STATUS_GRAPHICS_ALLOCATION_BUSY",
++ "STATUS_GRAPHICS_TOO_MANY_REFERENCES",
++ "STATUS_GRAPHICS_TRY_AGAIN_LATER",
++ "STATUS_GRAPHICS_TRY_AGAIN_NOW",
++ "STATUS_GRAPHICS_ALLOCATION_INVALID",
++ "STATUS_GRAPHICS_UNSWIZZLING_APERTURE_UNAVAILABLE",
++ "STATUS_GRAPHICS_UNSWIZZLING_APERTURE_UNSUPPORTED",
++ "STATUS_GRAPHICS_CANT_EVICT_PINNED_ALLOCATION",
++ "STATUS_GRAPHICS_INVALID_ALLOCATION_USAGE",
++ "STATUS_GRAPHICS_CANT_RENDER_LOCKED_ALLOCATION",
++ "STATUS_GRAPHICS_ALLOCATION_CLOSED",
++ "STATUS_GRAPHICS_INVALID_ALLOCATION_INSTANCE",
++ "STATUS_GRAPHICS_INVALID_ALLOCATION_HANDLE",
++ "STATUS_GRAPHICS_WRONG_ALLOCATION_DEVICE",
++ "STATUS_GRAPHICS_ALLOCATION_CONTENT_LOST",
++ "STATUS_GRAPHICS_GPU_EXCEPTION_ON_DEVICE",
++ "STATUS_GRAPHICS_INVALID_VIDPN_TOPOLOGY",
++ "STATUS_GRAPHICS_VIDPN_TOPOLOGY_NOT_SUPPORTED",
++ "STATUS_GRAPHICS_VIDPN_TOPOLOGY_CURRENTLY_NOT_SUPPORTED",
++ "STATUS_GRAPHICS_INVALID_VIDPN",
++ "STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_SOURCE",
++ "STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_TARGET",
++ "STATUS_GRAPHICS_VIDPN_MODALITY_NOT_SUPPORTED",
++ "STATUS_GRAPHICS_INVALID_VIDPN_SOURCEMODESET",
++ "STATUS_GRAPHICS_INVALID_VIDPN_TARGETMODESET",
++ "STATUS_GRAPHICS_INVALID_FREQUENCY",
++ "STATUS_GRAPHICS_INVALID_ACTIVE_REGION",
++ "STATUS_GRAPHICS_INVALID_TOTAL_REGION",
++ "STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_SOURCE_MODE",
++ "STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_TARGET_MODE",
++ "STATUS_GRAPHICS_PINNED_MODE_MUST_REMAIN_IN_SET",
++ "STATUS_GRAPHICS_PATH_ALREADY_IN_TOPOLOGY",
++ "STATUS_GRAPHICS_MODE_ALREADY_IN_MODESET",
++ "STATUS_GRAPHICS_INVALID_VIDEOPRESENTSOURCESET",
++ "STATUS_GRAPHICS_INVALID_VIDEOPRESENTTARGETSET",
++ "STATUS_GRAPHICS_SOURCE_ALREADY_IN_SET",
++ "STATUS_GRAPHICS_TARGET_ALREADY_IN_SET",
++ "STATUS_GRAPHICS_INVALID_VIDPN_PRESENT_PATH",
++ "STATUS_GRAPHICS_NO_RECOMMENDED_VIDPN_TOPOLOGY",
++ "STATUS_GRAPHICS_INVALID_MONITOR_FREQUENCYRANGESET",
++ "STATUS_GRAPHICS_INVALID_MONITOR_FREQUENCYRANGE",
++ "STATUS_GRAPHICS_FREQUENCYRANGE_NOT_IN_SET",
++ "STATUS_GRAPHICS_FREQUENCYRANGE_ALREADY_IN_SET",
++ "STATUS_GRAPHICS_STALE_MODESET",
++ "STATUS_GRAPHICS_INVALID_MONITOR_SOURCEMODESET",
++ "STATUS_GRAPHICS_INVALID_MONITOR_SOURCE_MODE",
++ "STATUS_GRAPHICS_NO_RECOMMENDED_FUNCTIONAL_VIDPN",
++ "STATUS_GRAPHICS_MODE_ID_MUST_BE_UNIQUE",
++ "STATUS_GRAPHICS_EMPTY_ADAPTER_MONITOR_MODE_SUPPORT_INTERSECTION",
++ "STATUS_GRAPHICS_VIDEO_PRESENT_TARGETS_LESS_THAN_SOURCES",
++ "STATUS_GRAPHICS_PATH_NOT_IN_TOPOLOGY",
++ "STATUS_GRAPHICS_ADAPTER_MUST_HAVE_AT_LEAST_ONE_SOURCE",
++ "STATUS_GRAPHICS_ADAPTER_MUST_HAVE_AT_LEAST_ONE_TARGET",
++ "STATUS_GRAPHICS_INVALID_MONITORDESCRIPTORSET",
++ "STATUS_GRAPHICS_INVALID_MONITORDESCRIPTOR",
++ "STATUS_GRAPHICS_MONITORDESCRIPTOR_NOT_IN_SET",
++ "STATUS_GRAPHICS_MONITORDESCRIPTOR_ALREADY_IN_SET",
++ "STATUS_GRAPHICS_MONITORDESCRIPTOR_ID_MUST_BE_UNIQUE",
++ "STATUS_GRAPHICS_INVALID_VIDPN_TARGET_SUBSET_TYPE",
++ "STATUS_GRAPHICS_RESOURCES_NOT_RELATED",
++ "STATUS_GRAPHICS_SOURCE_ID_MUST_BE_UNIQUE",
++ "STATUS_GRAPHICS_TARGET_ID_MUST_BE_UNIQUE",
++ "STATUS_GRAPHICS_NO_AVAILABLE_VIDPN_TARGET",
++ "STATUS_GRAPHICS_MONITOR_COULD_NOT_BE_ASSOCIATED_WITH_ADAPTER",
++ "STATUS_GRAPHICS_NO_VIDPNMGR",
++ "STATUS_GRAPHICS_NO_ACTIVE_VIDPN",
++ "STATUS_GRAPHICS_STALE_VIDPN_TOPOLOGY",
++ "STATUS_GRAPHICS_MONITOR_NOT_CONNECTED",
++ "STATUS_GRAPHICS_SOURCE_NOT_IN_TOPOLOGY",
++ "STATUS_GRAPHICS_INVALID_PRIMARYSURFACE_SIZE",
++ "STATUS_GRAPHICS_INVALID_VISIBLEREGION_SIZE",
++ "STATUS_GRAPHICS_INVALID_STRIDE",
++ "STATUS_GRAPHICS_INVALID_PIXELFORMAT",
++ "STATUS_GRAPHICS_INVALID_COLORBASIS",
++ "STATUS_GRAPHICS_INVALID_PIXELVALUEACCESSMODE",
++ "STATUS_GRAPHICS_TARGET_NOT_IN_TOPOLOGY",
++ "STATUS_GRAPHICS_NO_DISPLAY_MODE_MANAGEMENT_SUPPORT",
++ "STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE",
++ "STATUS_GRAPHICS_CANT_ACCESS_ACTIVE_VIDPN",
++ "STATUS_GRAPHICS_INVALID_PATH_IMPORTANCE_ORDINAL",
++ "STATUS_GRAPHICS_INVALID_PATH_CONTENT_GEOMETRY_TRANSFORMATION",
++ "STATUS_GRAPHICS_PATH_CONTENT_GEOMETRY_TRANSFORMATION_NOT_SUPPORTED",
++ "STATUS_GRAPHICS_INVALID_GAMMA_RAMP",
++ "STATUS_GRAPHICS_GAMMA_RAMP_NOT_SUPPORTED",
++ "STATUS_GRAPHICS_MULTISAMPLING_NOT_SUPPORTED",
++ "STATUS_GRAPHICS_MODE_NOT_IN_MODESET",
++ "STATUS_GRAPHICS_INVALID_VIDPN_TOPOLOGY_RECOMMENDATION_REASON",
++ "STATUS_GRAPHICS_INVALID_PATH_CONTENT_TYPE",
++ "STATUS_GRAPHICS_INVALID_COPYPROTECTION_TYPE",
++ "STATUS_GRAPHICS_UNASSIGNED_MODESET_ALREADY_EXISTS",
++ "STATUS_GRAPHICS_INVALID_SCANLINE_ORDERING",
++ "STATUS_GRAPHICS_TOPOLOGY_CHANGES_NOT_ALLOWED",
++ "STATUS_GRAPHICS_NO_AVAILABLE_IMPORTANCE_ORDINALS",
++ "STATUS_GRAPHICS_INCOMPATIBLE_PRIVATE_FORMAT",
++ "STATUS_GRAPHICS_INVALID_MODE_PRUNING_ALGORITHM",
++ "STATUS_GRAPHICS_INVALID_MONITOR_CAPABILITY_ORIGIN",
++ "STATUS_GRAPHICS_INVALID_MONITOR_FREQUENCYRANGE_CONSTRAINT",
++ "STATUS_GRAPHICS_MAX_NUM_PATHS_REACHED",
++ "STATUS_GRAPHICS_CANCEL_VIDPN_TOPOLOGY_AUGMENTATION",
++ "STATUS_GRAPHICS_INVALID_CLIENT_TYPE",
++ "STATUS_GRAPHICS_CLIENTVIDPN_NOT_SET",
++ "STATUS_GRAPHICS_SPECIFIED_CHILD_ALREADY_CONNECTED",
++ "STATUS_GRAPHICS_CHILD_DESCRIPTOR_NOT_SUPPORTED",
++ "STATUS_GRAPHICS_NOT_A_LINKED_ADAPTER",
++ "STATUS_GRAPHICS_LEADLINK_NOT_ENUMERATED",
++ "STATUS_GRAPHICS_CHAINLINKS_NOT_ENUMERATED",
++ "STATUS_GRAPHICS_ADAPTER_CHAIN_NOT_READY",
++ "STATUS_GRAPHICS_CHAINLINKS_NOT_STARTED",
++ "STATUS_GRAPHICS_CHAINLINKS_NOT_POWERED_ON",
++ "STATUS_GRAPHICS_INCONSISTENT_DEVICE_LINK_STATE",
++ "STATUS_GRAPHICS_NOT_POST_DEVICE_DRIVER",
++ "STATUS_GRAPHICS_ADAPTER_ACCESS_NOT_EXCLUDED",
++ "STATUS_GRAPHICS_OPM_NOT_SUPPORTED",
++ "STATUS_GRAPHICS_COPP_NOT_SUPPORTED",
++ "STATUS_GRAPHICS_UAB_NOT_SUPPORTED",
++ "STATUS_GRAPHICS_OPM_INVALID_ENCRYPTED_PARAMETERS",
++ "STATUS_GRAPHICS_OPM_NO_PROTECTED_OUTPUTS_EXIST",
++ "STATUS_GRAPHICS_OPM_INTERNAL_ERROR",
++ "STATUS_GRAPHICS_OPM_INVALID_HANDLE",
++ "STATUS_GRAPHICS_PVP_INVALID_CERTIFICATE_LENGTH",
++ "STATUS_GRAPHICS_OPM_SPANNING_MODE_ENABLED",
++ "STATUS_GRAPHICS_OPM_THEATER_MODE_ENABLED",
++ "STATUS_GRAPHICS_PVP_HFS_FAILED",
++ "STATUS_GRAPHICS_OPM_INVALID_SRM",
++ "STATUS_GRAPHICS_OPM_OUTPUT_DOES_NOT_SUPPORT_HDCP",
++ "STATUS_GRAPHICS_OPM_OUTPUT_DOES_NOT_SUPPORT_ACP",
++ "STATUS_GRAPHICS_OPM_OUTPUT_DOES_NOT_SUPPORT_CGMSA",
++ "STATUS_GRAPHICS_OPM_HDCP_SRM_NEVER_SET",
++ "STATUS_GRAPHICS_OPM_RESOLUTION_TOO_HIGH",
++ "STATUS_GRAPHICS_OPM_ALL_HDCP_HARDWARE_ALREADY_IN_USE",
++ "STATUS_GRAPHICS_OPM_PROTECTED_OUTPUT_NO_LONGER_EXISTS",
++ "STATUS_GRAPHICS_OPM_PROTECTED_OUTPUT_DOES_NOT_HAVE_COPP_SEMANTICS",
++ "STATUS_GRAPHICS_OPM_INVALID_INFORMATION_REQUEST",
++ "STATUS_GRAPHICS_OPM_DRIVER_INTERNAL_ERROR",
++ "STATUS_GRAPHICS_OPM_PROTECTED_OUTPUT_DOES_NOT_HAVE_OPM_SEMANTICS",
++ "STATUS_GRAPHICS_OPM_SIGNALING_NOT_SUPPORTED",
++ "STATUS_GRAPHICS_OPM_INVALID_CONFIGURATION_REQUEST",
++ "STATUS_GRAPHICS_I2C_NOT_SUPPORTED",
++ "STATUS_GRAPHICS_I2C_DEVICE_DOES_NOT_EXIST",
++ "STATUS_GRAPHICS_I2C_ERROR_TRANSMITTING_DATA",
++ "STATUS_GRAPHICS_I2C_ERROR_RECEIVING_DATA",
++ "STATUS_GRAPHICS_DDCCI_VCP_NOT_SUPPORTED",
++ "STATUS_GRAPHICS_DDCCI_INVALID_DATA",
++ "STATUS_GRAPHICS_DDCCI_MONITOR_RETURNED_INVALID_TIMING_STATUS_BYTE",
++ "STATUS_GRAPHICS_DDCCI_INVALID_CAPABILITIES_STRING",
++ "STATUS_GRAPHICS_MCA_INTERNAL_ERROR",
++ "STATUS_GRAPHICS_DDCCI_INVALID_MESSAGE_COMMAND",
++ "STATUS_GRAPHICS_DDCCI_INVALID_MESSAGE_LENGTH",
++ "STATUS_GRAPHICS_DDCCI_INVALID_MESSAGE_CHECKSUM",
++ "STATUS_GRAPHICS_INVALID_PHYSICAL_MONITOR_HANDLE",
++ "STATUS_GRAPHICS_MONITOR_NO_LONGER_EXISTS",
++ "STATUS_GRAPHICS_ONLY_CONSOLE_SESSION_SUPPORTED",
++ "STATUS_GRAPHICS_NO_DISPLAY_DEVICE_CORRESPONDS_TO_NAME",
++ "STATUS_GRAPHICS_DISPLAY_DEVICE_NOT_ATTACHED_TO_DESKTOP",
++ "STATUS_GRAPHICS_MIRRORING_DEVICES_NOT_SUPPORTED",
++ "STATUS_GRAPHICS_INVALID_POINTER",
++ "STATUS_GRAPHICS_NO_MONITORS_CORRESPOND_TO_DISPLAY_DEVICE",
++ "STATUS_GRAPHICS_PARAMETER_ARRAY_TOO_SMALL",
++ "STATUS_GRAPHICS_INTERNAL_ERROR",
++ "STATUS_GRAPHICS_SESSION_TYPE_CHANGE_IN_PROGRESS",
++ "STATUS_FVE_LOCKED_VOLUME",
++ "STATUS_FVE_NOT_ENCRYPTED",
++ "STATUS_FVE_BAD_INFORMATION",
++ "STATUS_FVE_TOO_SMALL",
++ "STATUS_FVE_FAILED_WRONG_FS",
++ "STATUS_FVE_BAD_PARTITION_SIZE",
++ "STATUS_FVE_FS_NOT_EXTENDED",
++ "STATUS_FVE_FS_MOUNTED",
++ "STATUS_FVE_NO_LICENSE",
++ "STATUS_FVE_ACTION_NOT_ALLOWED",
++ "STATUS_FVE_BAD_DATA",
++ "STATUS_FVE_VOLUME_NOT_BOUND",
++ "STATUS_FVE_NOT_DATA_VOLUME",
++ "STATUS_FVE_CONV_READ_ERROR",
++ "STATUS_FVE_CONV_WRITE_ERROR",
++ "STATUS_FVE_OVERLAPPED_UPDATE",
++ "STATUS_FVE_FAILED_SECTOR_SIZE",
++ "STATUS_FVE_FAILED_AUTHENTICATION",
++ "STATUS_FVE_NOT_OS_VOLUME",
++ "STATUS_FVE_KEYFILE_NOT_FOUND",
++ "STATUS_FVE_KEYFILE_INVALID",
++ "STATUS_FVE_KEYFILE_NO_VMK",
++ "STATUS_FVE_TPM_DISABLED",
++ "STATUS_FVE_TPM_SRK_AUTH_NOT_ZERO",
++ "STATUS_FVE_TPM_INVALID_PCR",
++ "STATUS_FVE_TPM_NO_VMK",
++ "STATUS_FVE_PIN_INVALID",
++ "STATUS_FVE_AUTH_INVALID_APPLICATION",
++ "STATUS_FVE_AUTH_INVALID_CONFIG",
++ "STATUS_FVE_DEBUGGER_ENABLED",
++ "STATUS_FVE_DRY_RUN_FAILED",
++ "STATUS_FVE_BAD_METADATA_POINTER",
++ "STATUS_FVE_OLD_METADATA_COPY",
++ "STATUS_FVE_REBOOT_REQUIRED",
++ "STATUS_FVE_RAW_ACCESS",
++ "STATUS_FVE_RAW_BLOCKED",
++ "STATUS_FVE_NO_AUTOUNLOCK_MASTER_KEY",
++ "STATUS_FVE_MOR_FAILED",
++ "STATUS_FVE_NO_FEATURE_LICENSE",
++ "STATUS_FVE_POLICY_USER_DISABLE_RDV_NOT_ALLOWED",
++ "STATUS_FVE_CONV_RECOVERY_FAILED",
++ "STATUS_FVE_VIRTUALIZED_SPACE_TOO_BIG",
++ "STATUS_FVE_INVALID_DATUM_TYPE",
++ "STATUS_FVE_VOLUME_TOO_SMALL",
++ "STATUS_FVE_ENH_PIN_INVALID",
++ "STATUS_FVE_FULL_ENCRYPTION_NOT_ALLOWED_ON_TP_STORAGE",
++ "STATUS_FVE_WIPE_NOT_ALLOWED_ON_TP_STORAGE",
++ "STATUS_FVE_NOT_ALLOWED_ON_CSV_STACK",
++ "STATUS_FVE_NOT_ALLOWED_ON_CLUSTER",
++ "STATUS_FVE_NOT_ALLOWED_TO_UPGRADE_WHILE_CONVERTING",
++ "STATUS_FVE_WIPE_CANCEL_NOT_APPLICABLE",
++ "STATUS_FVE_EDRIVE_DRY_RUN_FAILED",
++ "STATUS_FVE_SECUREBOOT_DISABLED",
++ "STATUS_FVE_SECUREBOOT_CONFIG_CHANGE",
++ "STATUS_FVE_DEVICE_LOCKEDOUT",
++ "STATUS_FVE_VOLUME_EXTEND_PREVENTS_EOW_DECRYPT",
++ "STATUS_FVE_NOT_DE_VOLUME",
++ "STATUS_FVE_PROTECTION_DISABLED",
++ "STATUS_FVE_PROTECTION_CANNOT_BE_DISABLED",
++ "STATUS_FVE_OSV_KSR_NOT_ALLOWED",
++ "STATUS_FWP_CALLOUT_NOT_FOUND",
++ "STATUS_FWP_CONDITION_NOT_FOUND",
++ "STATUS_FWP_FILTER_NOT_FOUND",
++ "STATUS_FWP_LAYER_NOT_FOUND",
++ "STATUS_FWP_PROVIDER_NOT_FOUND",
++ "STATUS_FWP_PROVIDER_CONTEXT_NOT_FOUND",
++ "STATUS_FWP_SUBLAYER_NOT_FOUND",
++ "STATUS_FWP_NOT_FOUND",
++ "STATUS_FWP_ALREADY_EXISTS",
++ "STATUS_FWP_IN_USE",
++ "STATUS_FWP_DYNAMIC_SESSION_IN_PROGRESS",
++ "STATUS_FWP_WRONG_SESSION",
++ "STATUS_FWP_NO_TXN_IN_PROGRESS",
++ "STATUS_FWP_TXN_IN_PROGRESS",
++ "STATUS_FWP_TXN_ABORTED",
++ "STATUS_FWP_SESSION_ABORTED",
++ "STATUS_FWP_INCOMPATIBLE_TXN",
++ "STATUS_FWP_TIMEOUT",
++ "STATUS_FWP_NET_EVENTS_DISABLED",
++ "STATUS_FWP_INCOMPATIBLE_LAYER",
++ "STATUS_FWP_KM_CLIENTS_ONLY",
++ "STATUS_FWP_LIFETIME_MISMATCH",
++ "STATUS_FWP_BUILTIN_OBJECT",
++ "STATUS_FWP_TOO_MANY_CALLOUTS",
++ "STATUS_FWP_NOTIFICATION_DROPPED",
++ "STATUS_FWP_TRAFFIC_MISMATCH",
++ "STATUS_FWP_INCOMPATIBLE_SA_STATE",
++ "STATUS_FWP_NULL_POINTER",
++ "STATUS_FWP_INVALID_ENUMERATOR",
++ "STATUS_FWP_INVALID_FLAGS",
++ "STATUS_FWP_INVALID_NET_MASK",
++ "STATUS_FWP_INVALID_RANGE",
++ "STATUS_FWP_INVALID_INTERVAL",
++ "STATUS_FWP_ZERO_LENGTH_ARRAY",
++ "STATUS_FWP_NULL_DISPLAY_NAME",
++ "STATUS_FWP_INVALID_ACTION_TYPE",
++ "STATUS_FWP_INVALID_WEIGHT",
++ "STATUS_FWP_MATCH_TYPE_MISMATCH",
++ "STATUS_FWP_TYPE_MISMATCH",
++ "STATUS_FWP_OUT_OF_BOUNDS",
++ "STATUS_FWP_RESERVED",
++ "STATUS_FWP_DUPLICATE_CONDITION",
++ "STATUS_FWP_DUPLICATE_KEYMOD",
++ "STATUS_FWP_ACTION_INCOMPATIBLE_WITH_LAYER",
++ "STATUS_FWP_ACTION_INCOMPATIBLE_WITH_SUBLAYER",
++ "STATUS_FWP_CONTEXT_INCOMPATIBLE_WITH_LAYER",
++ "STATUS_FWP_CONTEXT_INCOMPATIBLE_WITH_CALLOUT",
++ "STATUS_FWP_INCOMPATIBLE_AUTH_METHOD",
++ "STATUS_FWP_INCOMPATIBLE_DH_GROUP",
++ "STATUS_FWP_EM_NOT_SUPPORTED",
++ "STATUS_FWP_NEVER_MATCH",
++ "STATUS_FWP_PROVIDER_CONTEXT_MISMATCH",
++ "STATUS_FWP_INVALID_PARAMETER",
++ "STATUS_FWP_TOO_MANY_SUBLAYERS",
++ "STATUS_FWP_CALLOUT_NOTIFICATION_FAILED",
++ "STATUS_FWP_INVALID_AUTH_TRANSFORM",
++ "STATUS_FWP_INVALID_CIPHER_TRANSFORM",
++ "STATUS_FWP_INCOMPATIBLE_CIPHER_TRANSFORM",
++ "STATUS_FWP_INVALID_TRANSFORM_COMBINATION",
++ "STATUS_FWP_DUPLICATE_AUTH_METHOD",
++ "STATUS_FWP_INVALID_TUNNEL_ENDPOINT",
++ "STATUS_FWP_L2_DRIVER_NOT_READY",
++ "STATUS_FWP_KEY_DICTATOR_ALREADY_REGISTERED",
++ "STATUS_FWP_KEY_DICTATION_INVALID_KEYING_MATERIAL",
++ "STATUS_FWP_CONNECTIONS_DISABLED",
++ "STATUS_FWP_INVALID_DNS_NAME",
++ "STATUS_FWP_STILL_ON",
++ "STATUS_FWP_IKEEXT_NOT_RUNNING",
++ "STATUS_FWP_TCPIP_NOT_READY",
++ "STATUS_FWP_INJECT_HANDLE_CLOSING",
++ "STATUS_FWP_INJECT_HANDLE_STALE",
++ "STATUS_FWP_CANNOT_PEND",
++ "STATUS_FWP_DROP_NOICMP",
++ "STATUS_NDIS_CLOSING",
++ "STATUS_NDIS_BAD_VERSION",
++ "STATUS_NDIS_BAD_CHARACTERISTICS",
++ "STATUS_NDIS_ADAPTER_NOT_FOUND",
++ "STATUS_NDIS_OPEN_FAILED",
++ "STATUS_NDIS_DEVICE_FAILED",
++ "STATUS_NDIS_MULTICAST_FULL",
++ "STATUS_NDIS_MULTICAST_EXISTS",
++ "STATUS_NDIS_MULTICAST_NOT_FOUND",
++ "STATUS_NDIS_REQUEST_ABORTED",
++ "STATUS_NDIS_RESET_IN_PROGRESS",
++ "STATUS_NDIS_INVALID_PACKET",
++ "STATUS_NDIS_INVALID_DEVICE_REQUEST",
++ "STATUS_NDIS_ADAPTER_NOT_READY",
++ "STATUS_NDIS_INVALID_LENGTH",
++ "STATUS_NDIS_INVALID_DATA",
++ "STATUS_NDIS_BUFFER_TOO_SHORT",
++ "STATUS_NDIS_INVALID_OID",
++ "STATUS_NDIS_ADAPTER_REMOVED",
++ "STATUS_NDIS_UNSUPPORTED_MEDIA",
++ "STATUS_NDIS_GROUP_ADDRESS_IN_USE",
++ "STATUS_NDIS_FILE_NOT_FOUND",
++ "STATUS_NDIS_ERROR_READING_FILE",
++ "STATUS_NDIS_ALREADY_MAPPED",
++ "STATUS_NDIS_RESOURCE_CONFLICT",
++ "STATUS_NDIS_MEDIA_DISCONNECTED",
++ "STATUS_NDIS_INVALID_ADDRESS",
++ "STATUS_NDIS_PAUSED",
++ "STATUS_NDIS_INTERFACE_NOT_FOUND",
++ "STATUS_NDIS_UNSUPPORTED_REVISION",
++ "STATUS_NDIS_INVALID_PORT",
++ "STATUS_NDIS_INVALID_PORT_STATE",
++ "STATUS_NDIS_LOW_POWER_STATE",
++ "STATUS_NDIS_REINIT_REQUIRED",
++ "STATUS_NDIS_NO_QUEUES",
++ "STATUS_NDIS_NOT_SUPPORTED",
++ "STATUS_NDIS_OFFLOAD_POLICY",
++ "STATUS_NDIS_OFFLOAD_CONNECTION_REJECTED",
++ "STATUS_NDIS_OFFLOAD_PATH_REJECTED",
++ "STATUS_NDIS_DOT11_AUTO_CONFIG_ENABLED",
++ "STATUS_NDIS_DOT11_MEDIA_IN_USE",
++ "STATUS_NDIS_DOT11_POWER_STATE_INVALID",
++ "STATUS_NDIS_PM_WOL_PATTERN_LIST_FULL",
++ "STATUS_NDIS_PM_PROTOCOL_OFFLOAD_LIST_FULL",
++ "STATUS_NDIS_DOT11_AP_CHANNEL_CURRENTLY_NOT_AVAILABLE",
++ "STATUS_NDIS_DOT11_AP_BAND_CURRENTLY_NOT_AVAILABLE",
++ "STATUS_NDIS_DOT11_AP_CHANNEL_NOT_ALLOWED",
++ "STATUS_NDIS_DOT11_AP_BAND_NOT_ALLOWED",
++ "STATUS_QUIC_HANDSHAKE_FAILURE",
++ "STATUS_QUIC_VER_NEG_FAILURE",
++ "STATUS_TPM_ERROR_MASK",
++ "STATUS_TPM_AUTHFAIL",
++ "STATUS_TPM_BADINDEX",
++ "STATUS_TPM_BAD_PARAMETER",
++ "STATUS_TPM_AUDITFAILURE",
++ "STATUS_TPM_CLEAR_DISABLED",
++ "STATUS_TPM_DEACTIVATED",
++ "STATUS_TPM_DISABLED",
++ "STATUS_TPM_DISABLED_CMD",
++ "STATUS_TPM_FAIL",
++ "STATUS_TPM_BAD_ORDINAL",
++ "STATUS_TPM_INSTALL_DISABLED",
++ "STATUS_TPM_INVALID_KEYHANDLE",
++ "STATUS_TPM_KEYNOTFOUND",
++ "STATUS_TPM_INAPPROPRIATE_ENC",
++ "STATUS_TPM_MIGRATEFAIL",
++ "STATUS_TPM_INVALID_PCR_INFO",
++ "STATUS_TPM_NOSPACE",
++ "STATUS_TPM_NOSRK",
++ "STATUS_TPM_NOTSEALED_BLOB",
++ "STATUS_TPM_OWNER_SET",
++ "STATUS_TPM_RESOURCES",
++ "STATUS_TPM_SHORTRANDOM",
++ "STATUS_TPM_SIZE",
++ "STATUS_TPM_WRONGPCRVAL",
++ "STATUS_TPM_BAD_PARAM_SIZE",
++ "STATUS_TPM_SHA_THREAD",
++ "STATUS_TPM_SHA_ERROR",
++ "STATUS_TPM_FAILEDSELFTEST",
++ "STATUS_TPM_AUTH2FAIL",
++ "STATUS_TPM_BADTAG",
++ "STATUS_TPM_IOERROR",
++ "STATUS_TPM_ENCRYPT_ERROR",
++ "STATUS_TPM_DECRYPT_ERROR",
++ "STATUS_TPM_INVALID_AUTHHANDLE",
++ "STATUS_TPM_NO_ENDORSEMENT",
++ "STATUS_TPM_INVALID_KEYUSAGE",
++ "STATUS_TPM_WRONG_ENTITYTYPE",
++ "STATUS_TPM_INVALID_POSTINIT",
++ "STATUS_TPM_INAPPROPRIATE_SIG",
++ "STATUS_TPM_BAD_KEY_PROPERTY",
++ "STATUS_TPM_BAD_MIGRATION",
++ "STATUS_TPM_BAD_SCHEME",
++ "STATUS_TPM_BAD_DATASIZE",
++ "STATUS_TPM_BAD_MODE",
++ "STATUS_TPM_BAD_PRESENCE",
++ "STATUS_TPM_BAD_VERSION",
++ "STATUS_TPM_NO_WRAP_TRANSPORT",
++ "STATUS_TPM_AUDITFAIL_UNSUCCESSFUL",
++ "STATUS_TPM_AUDITFAIL_SUCCESSFUL",
++ "STATUS_TPM_NOTRESETABLE",
++ "STATUS_TPM_NOTLOCAL",
++ "STATUS_TPM_BAD_TYPE",
++ "STATUS_TPM_INVALID_RESOURCE",
++ "STATUS_TPM_NOTFIPS",
++ "STATUS_TPM_INVALID_FAMILY",
++ "STATUS_TPM_NO_NV_PERMISSION",
++ "STATUS_TPM_REQUIRES_SIGN",
++ "STATUS_TPM_KEY_NOTSUPPORTED",
++ "STATUS_TPM_AUTH_CONFLICT",
++ "STATUS_TPM_AREA_LOCKED",
++ "STATUS_TPM_BAD_LOCALITY",
++ "STATUS_TPM_READ_ONLY",
++ "STATUS_TPM_PER_NOWRITE",
++ "STATUS_TPM_FAMILYCOUNT",
++ "STATUS_TPM_WRITE_LOCKED",
++ "STATUS_TPM_BAD_ATTRIBUTES",
++ "STATUS_TPM_INVALID_STRUCTURE",
++ "STATUS_TPM_KEY_OWNER_CONTROL",
++ "STATUS_TPM_BAD_COUNTER",
++ "STATUS_TPM_NOT_FULLWRITE",
++ "STATUS_TPM_CONTEXT_GAP",
++ "STATUS_TPM_MAXNVWRITES",
++ "STATUS_TPM_NOOPERATOR",
++ "STATUS_TPM_RESOURCEMISSING",
++ "STATUS_TPM_DELEGATE_LOCK",
++ "STATUS_TPM_DELEGATE_FAMILY",
++ "STATUS_TPM_DELEGATE_ADMIN",
++ "STATUS_TPM_TRANSPORT_NOTEXCLUSIVE",
++ "STATUS_TPM_OWNER_CONTROL",
++ "STATUS_TPM_DAA_RESOURCES",
++ "STATUS_TPM_DAA_INPUT_DATA0",
++ "STATUS_TPM_DAA_INPUT_DATA1",
++ "STATUS_TPM_DAA_ISSUER_SETTINGS",
++ "STATUS_TPM_DAA_TPM_SETTINGS",
++ "STATUS_TPM_DAA_STAGE",
++ "STATUS_TPM_DAA_ISSUER_VALIDITY",
++ "STATUS_TPM_DAA_WRONG_W",
++ "STATUS_TPM_BAD_HANDLE",
++ "STATUS_TPM_BAD_DELEGATE",
++ "STATUS_TPM_BADCONTEXT",
++ "STATUS_TPM_TOOMANYCONTEXTS",
++ "STATUS_TPM_MA_TICKET_SIGNATURE",
++ "STATUS_TPM_MA_DESTINATION",
++ "STATUS_TPM_MA_SOURCE",
++ "STATUS_TPM_MA_AUTHORITY",
++ "STATUS_TPM_PERMANENTEK",
++ "STATUS_TPM_BAD_SIGNATURE",
++ "STATUS_TPM_NOCONTEXTSPACE",
++ "STATUS_TPM_20_E_ASYMMETRIC",
++ "STATUS_TPM_20_E_ATTRIBUTES",
++ "STATUS_TPM_20_E_HASH",
++ "STATUS_TPM_20_E_VALUE",
++ "STATUS_TPM_20_E_HIERARCHY",
++ "STATUS_TPM_20_E_KEY_SIZE",
++ "STATUS_TPM_20_E_MGF",
++ "STATUS_TPM_20_E_MODE",
++ "STATUS_TPM_20_E_TYPE",
++ "STATUS_TPM_20_E_HANDLE",
++ "STATUS_TPM_20_E_KDF",
++ "STATUS_TPM_20_E_RANGE",
++ "STATUS_TPM_20_E_AUTH_FAIL",
++ "STATUS_TPM_20_E_NONCE",
++ "STATUS_TPM_20_E_PP",
++ "STATUS_TPM_20_E_SCHEME",
++ "STATUS_TPM_20_E_SIZE",
++ "STATUS_TPM_20_E_SYMMETRIC",
++ "STATUS_TPM_20_E_TAG",
++ "STATUS_TPM_20_E_SELECTOR",
++ "STATUS_TPM_20_E_INSUFFICIENT",
++ "STATUS_TPM_20_E_SIGNATURE",
++ "STATUS_TPM_20_E_KEY",
++ "STATUS_TPM_20_E_POLICY_FAIL",
++ "STATUS_TPM_20_E_INTEGRITY",
++ "STATUS_TPM_20_E_TICKET",
++ "STATUS_TPM_20_E_RESERVED_BITS",
++ "STATUS_TPM_20_E_BAD_AUTH",
++ "STATUS_TPM_20_E_EXPIRED",
++ "STATUS_TPM_20_E_POLICY_CC",
++ "STATUS_TPM_20_E_BINDING",
++ "STATUS_TPM_20_E_CURVE",
++ "STATUS_TPM_20_E_ECC_POINT",
++ "STATUS_TPM_20_E_INITIALIZE",
++ "STATUS_TPM_20_E_FAILURE",
++ "STATUS_TPM_20_E_SEQUENCE",
++ "STATUS_TPM_20_E_PRIVATE",
++ "STATUS_TPM_20_E_HMAC",
++ "STATUS_TPM_20_E_DISABLED",
++ "STATUS_TPM_20_E_EXCLUSIVE",
++ "STATUS_TPM_20_E_ECC_CURVE",
++ "STATUS_TPM_20_E_AUTH_TYPE",
++ "STATUS_TPM_20_E_AUTH_MISSING",
++ "STATUS_TPM_20_E_POLICY",
++ "STATUS_TPM_20_E_PCR",
++ "STATUS_TPM_20_E_PCR_CHANGED",
++ "STATUS_TPM_20_E_UPGRADE",
++ "STATUS_TPM_20_E_TOO_MANY_CONTEXTS",
++ "STATUS_TPM_20_E_AUTH_UNAVAILABLE",
++ "STATUS_TPM_20_E_REBOOT",
++ "STATUS_TPM_20_E_UNBALANCED",
++ "STATUS_TPM_20_E_COMMAND_SIZE",
++ "STATUS_TPM_20_E_COMMAND_CODE",
++ "STATUS_TPM_20_E_AUTHSIZE",
++ "STATUS_TPM_20_E_AUTH_CONTEXT",
++ "STATUS_TPM_20_E_NV_RANGE",
++ "STATUS_TPM_20_E_NV_SIZE",
++ "STATUS_TPM_20_E_NV_LOCKED",
++ "STATUS_TPM_20_E_NV_AUTHORIZATION",
++ "STATUS_TPM_20_E_NV_UNINITIALIZED",
++ "STATUS_TPM_20_E_NV_SPACE",
++ "STATUS_TPM_20_E_NV_DEFINED",
++ "STATUS_TPM_20_E_BAD_CONTEXT",
++ "STATUS_TPM_20_E_CPHASH",
++ "STATUS_TPM_20_E_PARENT",
++ "STATUS_TPM_20_E_NEEDS_TEST",
++ "STATUS_TPM_20_E_NO_RESULT",
++ "STATUS_TPM_20_E_SENSITIVE",
++ "STATUS_TPM_COMMAND_BLOCKED",
++ "STATUS_TPM_INVALID_HANDLE",
++ "STATUS_TPM_DUPLICATE_VHANDLE",
++ "STATUS_TPM_EMBEDDED_COMMAND_BLOCKED",
++ "STATUS_TPM_EMBEDDED_COMMAND_UNSUPPORTED",
++ "STATUS_TPM_RETRY",
++ "STATUS_TPM_NEEDS_SELFTEST",
++ "STATUS_TPM_DOING_SELFTEST",
++ "STATUS_TPM_DEFEND_LOCK_RUNNING",
++ "STATUS_TPM_COMMAND_CANCELED",
++ "STATUS_TPM_TOO_MANY_CONTEXTS",
++ "STATUS_TPM_NOT_FOUND",
++ "STATUS_TPM_ACCESS_DENIED",
++ "STATUS_TPM_INSUFFICIENT_BUFFER",
++ "STATUS_TPM_PPI_FUNCTION_UNSUPPORTED",
++ "STATUS_PCP_ERROR_MASK",
++ "STATUS_PCP_DEVICE_NOT_READY",
++ "STATUS_PCP_INVALID_HANDLE",
++ "STATUS_PCP_INVALID_PARAMETER",
++ "STATUS_PCP_FLAG_NOT_SUPPORTED",
++ "STATUS_PCP_NOT_SUPPORTED",
++ "STATUS_PCP_BUFFER_TOO_SMALL",
++ "STATUS_PCP_INTERNAL_ERROR",
++ "STATUS_PCP_AUTHENTICATION_FAILED",
++ "STATUS_PCP_AUTHENTICATION_IGNORED",
++ "STATUS_PCP_POLICY_NOT_FOUND",
++ "STATUS_PCP_PROFILE_NOT_FOUND",
++ "STATUS_PCP_VALIDATION_FAILED",
++ "STATUS_PCP_DEVICE_NOT_FOUND",
++ "STATUS_PCP_WRONG_PARENT",
++ "STATUS_PCP_KEY_NOT_LOADED",
++ "STATUS_PCP_NO_KEY_CERTIFICATION",
++ "STATUS_PCP_KEY_NOT_FINALIZED",
++ "STATUS_PCP_ATTESTATION_CHALLENGE_NOT_SET",
++ "STATUS_PCP_NOT_PCR_BOUND",
++ "STATUS_PCP_KEY_ALREADY_FINALIZED",
++ "STATUS_PCP_KEY_USAGE_POLICY_NOT_SUPPORTED",
++ "STATUS_PCP_KEY_USAGE_POLICY_INVALID",
++ "STATUS_PCP_SOFT_KEY_ERROR",
++ "STATUS_PCP_KEY_NOT_AUTHENTICATED",
++ "STATUS_PCP_KEY_NOT_AIK",
++ "STATUS_PCP_KEY_NOT_SIGNING_KEY",
++ "STATUS_PCP_LOCKED_OUT",
++ "STATUS_PCP_CLAIM_TYPE_NOT_SUPPORTED",
++ "STATUS_PCP_TPM_VERSION_NOT_SUPPORTED",
++ "STATUS_PCP_BUFFER_LENGTH_MISMATCH",
++ "STATUS_PCP_IFX_RSA_KEY_CREATION_BLOCKED",
++ "STATUS_PCP_TICKET_MISSING",
++ "STATUS_PCP_RAW_POLICY_NOT_SUPPORTED",
++ "STATUS_PCP_KEY_HANDLE_INVALIDATED",
++ "STATUS_RTPM_NO_RESULT",
++ "STATUS_RTPM_PCR_READ_INCOMPLETE",
++ "STATUS_RTPM_INVALID_CONTEXT",
++ "STATUS_RTPM_UNSUPPORTED_CMD",
++ "STATUS_TPM_ZERO_EXHAUST_ENABLED",
++ "STATUS_HV_INVALID_HYPERCALL_CODE",
++ "STATUS_HV_INVALID_HYPERCALL_INPUT",
++ "STATUS_HV_INVALID_ALIGNMENT",
++ "STATUS_HV_INVALID_PARAMETER",
++ "STATUS_HV_ACCESS_DENIED",
++ "STATUS_HV_INVALID_PARTITION_STATE",
++ "STATUS_HV_OPERATION_DENIED",
++ "STATUS_HV_UNKNOWN_PROPERTY",
++ "STATUS_HV_PROPERTY_VALUE_OUT_OF_RANGE",
++ "STATUS_HV_INSUFFICIENT_MEMORY",
++ "STATUS_HV_PARTITION_TOO_DEEP",
++ "STATUS_HV_INVALID_PARTITION_ID",
++ "STATUS_HV_INVALID_VP_INDEX",
++ "STATUS_HV_INVALID_PORT_ID",
++ "STATUS_HV_INVALID_CONNECTION_ID",
++ "STATUS_HV_INSUFFICIENT_BUFFERS",
++ "STATUS_HV_NOT_ACKNOWLEDGED",
++ "STATUS_HV_INVALID_VP_STATE",
++ "STATUS_HV_ACKNOWLEDGED",
++ "STATUS_HV_INVALID_SAVE_RESTORE_STATE",
++ "STATUS_HV_INVALID_SYNIC_STATE",
++ "STATUS_HV_OBJECT_IN_USE",
++ "STATUS_HV_INVALID_PROXIMITY_DOMAIN_INFO",
++ "STATUS_HV_NO_DATA",
++ "STATUS_HV_INACTIVE",
++ "STATUS_HV_NO_RESOURCES",
++ "STATUS_HV_FEATURE_UNAVAILABLE",
++ "STATUS_HV_INSUFFICIENT_BUFFER",
++ "STATUS_HV_INSUFFICIENT_DEVICE_DOMAINS",
++ "STATUS_HV_CPUID_FEATURE_VALIDATION_ERROR",
++ "STATUS_HV_CPUID_XSAVE_FEATURE_VALIDATION_ERROR",
++ "STATUS_HV_PROCESSOR_STARTUP_TIMEOUT",
++ "STATUS_HV_SMX_ENABLED",
++ "STATUS_HV_INVALID_LP_INDEX",
++ "STATUS_HV_INVALID_REGISTER_VALUE",
++ "STATUS_HV_INVALID_VTL_STATE",
++ "STATUS_HV_NX_NOT_DETECTED",
++ "STATUS_HV_INVALID_DEVICE_ID",
++ "STATUS_HV_INVALID_DEVICE_STATE",
++ "STATUS_HV_PAGE_REQUEST_INVALID",
++ "STATUS_HV_INVALID_CPU_GROUP_ID",
++ "STATUS_HV_INVALID_CPU_GROUP_STATE",
++ "STATUS_HV_OPERATION_FAILED",
++ "STATUS_HV_NOT_ALLOWED_WITH_NESTED_VIRT_ACTIVE",
++ "STATUS_HV_INSUFFICIENT_ROOT_MEMORY",
++ "STATUS_HV_EVENT_BUFFER_ALREADY_FREED",
++ "STATUS_HV_INSUFFICIENT_CONTIGUOUS_MEMORY",
++ "STATUS_HV_NOT_PRESENT",
++ "STATUS_IPSEC_BAD_SPI",
++ "STATUS_IPSEC_SA_LIFETIME_EXPIRED",
++ "STATUS_IPSEC_WRONG_SA",
++ "STATUS_IPSEC_REPLAY_CHECK_FAILED",
++ "STATUS_IPSEC_INVALID_PACKET",
++ "STATUS_IPSEC_INTEGRITY_CHECK_FAILED",
++ "STATUS_IPSEC_CLEAR_TEXT_DROP",
++ "STATUS_IPSEC_AUTH_FIREWALL_DROP",
++ "STATUS_IPSEC_THROTTLE_DROP",
++ "STATUS_IPSEC_DOSP_BLOCK",
++ "STATUS_IPSEC_DOSP_RECEIVED_MULTICAST",
++ "STATUS_IPSEC_DOSP_INVALID_PACKET",
++ "STATUS_IPSEC_DOSP_STATE_LOOKUP_FAILED",
++ "STATUS_IPSEC_DOSP_MAX_ENTRIES",
++ "STATUS_IPSEC_DOSP_KEYMOD_NOT_ALLOWED",
++ "STATUS_IPSEC_DOSP_MAX_PER_IP_RATELIMIT_QUEUES",
++ "STATUS_VID_DUPLICATE_HANDLER",
++ "STATUS_VID_TOO_MANY_HANDLERS",
++ "STATUS_VID_QUEUE_FULL",
++ "STATUS_VID_HANDLER_NOT_PRESENT",
++ "STATUS_VID_INVALID_OBJECT_NAME",
++ "STATUS_VID_PARTITION_NAME_TOO_LONG",
++ "STATUS_VID_MESSAGE_QUEUE_NAME_TOO_LONG",
++ "STATUS_VID_PARTITION_ALREADY_EXISTS",
++ "STATUS_VID_PARTITION_DOES_NOT_EXIST",
++ "STATUS_VID_PARTITION_NAME_NOT_FOUND",
++ "STATUS_VID_MESSAGE_QUEUE_ALREADY_EXISTS",
++ "STATUS_VID_EXCEEDED_MBP_ENTRY_MAP_LIMIT",
++ "STATUS_VID_MB_STILL_REFERENCED",
++ "STATUS_VID_CHILD_GPA_PAGE_SET_CORRUPTED",
++ "STATUS_VID_INVALID_NUMA_SETTINGS",
++ "STATUS_VID_INVALID_NUMA_NODE_INDEX",
++ "STATUS_VID_NOTIFICATION_QUEUE_ALREADY_ASSOCIATED",
++ "STATUS_VID_INVALID_MEMORY_BLOCK_HANDLE",
++ "STATUS_VID_PAGE_RANGE_OVERFLOW",
++ "STATUS_VID_INVALID_MESSAGE_QUEUE_HANDLE",
++ "STATUS_VID_INVALID_GPA_RANGE_HANDLE",
++ "STATUS_VID_NO_MEMORY_BLOCK_NOTIFICATION_QUEUE",
++ "STATUS_VID_MEMORY_BLOCK_LOCK_COUNT_EXCEEDED",
++ "STATUS_VID_INVALID_PPM_HANDLE",
++ "STATUS_VID_MBPS_ARE_LOCKED",
++ "STATUS_VID_MESSAGE_QUEUE_CLOSED",
++ "STATUS_VID_VIRTUAL_PROCESSOR_LIMIT_EXCEEDED",
++ "STATUS_VID_STOP_PENDING",
++ "STATUS_VID_INVALID_PROCESSOR_STATE",
++ "STATUS_VID_EXCEEDED_KM_CONTEXT_COUNT_LIMIT",
++ "STATUS_VID_KM_INTERFACE_ALREADY_INITIALIZED",
++ "STATUS_VID_MB_PROPERTY_ALREADY_SET_RESET",
++ "STATUS_VID_MMIO_RANGE_DESTROYED",
++ "STATUS_VID_INVALID_CHILD_GPA_PAGE_SET",
++ "STATUS_VID_RESERVE_PAGE_SET_IS_BEING_USED",
++ "STATUS_VID_RESERVE_PAGE_SET_TOO_SMALL",
++ "STATUS_VID_MBP_ALREADY_LOCKED_USING_RESERVED_PAGE",
++ "STATUS_VID_MBP_COUNT_EXCEEDED_LIMIT",
++ "STATUS_VID_SAVED_STATE_CORRUPT",
++ "STATUS_VID_SAVED_STATE_UNRECOGNIZED_ITEM",
++ "STATUS_VID_SAVED_STATE_INCOMPATIBLE",
++ "STATUS_VID_VTL_ACCESS_DENIED",
++ "STATUS_VOLMGR_DATABASE_FULL",
++ "STATUS_VOLMGR_DISK_CONFIGURATION_CORRUPTED",
++ "STATUS_VOLMGR_DISK_CONFIGURATION_NOT_IN_SYNC",
++ "STATUS_VOLMGR_PACK_CONFIG_UPDATE_FAILED",
++ "STATUS_VOLMGR_DISK_CONTAINS_NON_SIMPLE_VOLUME",
++ "STATUS_VOLMGR_DISK_DUPLICATE",
++ "STATUS_VOLMGR_DISK_DYNAMIC",
++ "STATUS_VOLMGR_DISK_ID_INVALID",
++ "STATUS_VOLMGR_DISK_INVALID",
++ "STATUS_VOLMGR_DISK_LAST_VOTER",
++ "STATUS_VOLMGR_DISK_LAYOUT_INVALID",
++ "STATUS_VOLMGR_DISK_LAYOUT_NON_BASIC_BETWEEN_BASIC_PARTITIONS",
++ "STATUS_VOLMGR_DISK_LAYOUT_NOT_CYLINDER_ALIGNED",
++ "STATUS_VOLMGR_DISK_LAYOUT_PARTITIONS_TOO_SMALL",
++ "STATUS_VOLMGR_DISK_LAYOUT_PRIMARY_BETWEEN_LOGICAL_PARTITIONS",
++ "STATUS_VOLMGR_DISK_LAYOUT_TOO_MANY_PARTITIONS",
++ "STATUS_VOLMGR_DISK_MISSING",
++ "STATUS_VOLMGR_DISK_NOT_EMPTY",
++ "STATUS_VOLMGR_DISK_NOT_ENOUGH_SPACE",
++ "STATUS_VOLMGR_DISK_REVECTORING_FAILED",
++ "STATUS_VOLMGR_DISK_SECTOR_SIZE_INVALID",
++ "STATUS_VOLMGR_DISK_SET_NOT_CONTAINED",
++ "STATUS_VOLMGR_DISK_USED_BY_MULTIPLE_MEMBERS",
++ "STATUS_VOLMGR_DISK_USED_BY_MULTIPLE_PLEXES",
++ "STATUS_VOLMGR_DYNAMIC_DISK_NOT_SUPPORTED",
++ "STATUS_VOLMGR_EXTENT_ALREADY_USED",
++ "STATUS_VOLMGR_EXTENT_NOT_CONTIGUOUS",
++ "STATUS_VOLMGR_EXTENT_NOT_IN_PUBLIC_REGION",
++ "STATUS_VOLMGR_EXTENT_NOT_SECTOR_ALIGNED",
++ "STATUS_VOLMGR_EXTENT_OVERLAPS_EBR_PARTITION",
++ "STATUS_VOLMGR_EXTENT_VOLUME_LENGTHS_DO_NOT_MATCH",
++ "STATUS_VOLMGR_FAULT_TOLERANT_NOT_SUPPORTED",
++ "STATUS_VOLMGR_INTERLEAVE_LENGTH_INVALID",
++ "STATUS_VOLMGR_MAXIMUM_REGISTERED_USERS",
++ "STATUS_VOLMGR_MEMBER_IN_SYNC",
++ "STATUS_VOLMGR_MEMBER_INDEX_DUPLICATE",
++ "STATUS_VOLMGR_MEMBER_INDEX_INVALID",
++ "STATUS_VOLMGR_MEMBER_MISSING",
++ "STATUS_VOLMGR_MEMBER_NOT_DETACHED",
++ "STATUS_VOLMGR_MEMBER_REGENERATING",
++ "STATUS_VOLMGR_ALL_DISKS_FAILED",
++ "STATUS_VOLMGR_NO_REGISTERED_USERS",
++ "STATUS_VOLMGR_NO_SUCH_USER",
++ "STATUS_VOLMGR_NOTIFICATION_RESET",
++ "STATUS_VOLMGR_NUMBER_OF_MEMBERS_INVALID",
++ "STATUS_VOLMGR_NUMBER_OF_PLEXES_INVALID",
++ "STATUS_VOLMGR_PACK_DUPLICATE",
++ "STATUS_VOLMGR_PACK_ID_INVALID",
++ "STATUS_VOLMGR_PACK_INVALID",
++ "STATUS_VOLMGR_PACK_NAME_INVALID",
++ "STATUS_VOLMGR_PACK_OFFLINE",
++ "STATUS_VOLMGR_PACK_HAS_QUORUM",
++ "STATUS_VOLMGR_PACK_WITHOUT_QUORUM",
++ "STATUS_VOLMGR_PARTITION_STYLE_INVALID",
++ "STATUS_VOLMGR_PARTITION_UPDATE_FAILED",
++ "STATUS_VOLMGR_PLEX_IN_SYNC",
++ "STATUS_VOLMGR_PLEX_INDEX_DUPLICATE",
++ "STATUS_VOLMGR_PLEX_INDEX_INVALID",
++ "STATUS_VOLMGR_PLEX_LAST_ACTIVE",
++ "STATUS_VOLMGR_PLEX_MISSING",
++ "STATUS_VOLMGR_PLEX_REGENERATING",
++ "STATUS_VOLMGR_PLEX_TYPE_INVALID",
++ "STATUS_VOLMGR_PLEX_NOT_RAID5",
++ "STATUS_VOLMGR_PLEX_NOT_SIMPLE",
++ "STATUS_VOLMGR_STRUCTURE_SIZE_INVALID",
++ "STATUS_VOLMGR_TOO_MANY_NOTIFICATION_REQUESTS",
++ "STATUS_VOLMGR_TRANSACTION_IN_PROGRESS",
++ "STATUS_VOLMGR_UNEXPECTED_DISK_LAYOUT_CHANGE",
++ "STATUS_VOLMGR_VOLUME_CONTAINS_MISSING_DISK",
++ "STATUS_VOLMGR_VOLUME_ID_INVALID",
++ "STATUS_VOLMGR_VOLUME_LENGTH_INVALID",
++ "STATUS_VOLMGR_VOLUME_LENGTH_NOT_SECTOR_SIZE_MULTIPLE",
++ "STATUS_VOLMGR_VOLUME_NOT_MIRRORED",
++ "STATUS_VOLMGR_VOLUME_NOT_RETAINED",
++ "STATUS_VOLMGR_VOLUME_OFFLINE",
++ "STATUS_VOLMGR_VOLUME_RETAINED",
++ "STATUS_VOLMGR_NUMBER_OF_EXTENTS_INVALID",
++ "STATUS_VOLMGR_DIFFERENT_SECTOR_SIZE",
++ "STATUS_VOLMGR_BAD_BOOT_DISK",
++ "STATUS_VOLMGR_PACK_CONFIG_OFFLINE",
++ "STATUS_VOLMGR_PACK_CONFIG_ONLINE",
++ "STATUS_VOLMGR_NOT_PRIMARY_PACK",
++ "STATUS_VOLMGR_PACK_LOG_UPDATE_FAILED",
++ "STATUS_VOLMGR_NUMBER_OF_DISKS_IN_PLEX_INVALID",
++ "STATUS_VOLMGR_NUMBER_OF_DISKS_IN_MEMBER_INVALID",
++ "STATUS_VOLMGR_VOLUME_MIRRORED",
++ "STATUS_VOLMGR_PLEX_NOT_SIMPLE_SPANNED",
++ "STATUS_VOLMGR_NO_VALID_LOG_COPIES",
++ "STATUS_VOLMGR_PRIMARY_PACK_PRESENT",
++ "STATUS_VOLMGR_NUMBER_OF_DISKS_INVALID",
++ "STATUS_VOLMGR_MIRROR_NOT_SUPPORTED",
++ "STATUS_VOLMGR_RAID5_NOT_SUPPORTED",
++ "STATUS_BCD_TOO_MANY_ELEMENTS",
++ "STATUS_VHD_DRIVE_FOOTER_MISSING",
++ "STATUS_VHD_DRIVE_FOOTER_CHECKSUM_MISMATCH",
++ "STATUS_VHD_DRIVE_FOOTER_CORRUPT",
++ "STATUS_VHD_FORMAT_UNKNOWN",
++ "STATUS_VHD_FORMAT_UNSUPPORTED_VERSION",
++ "STATUS_VHD_SPARSE_HEADER_CHECKSUM_MISMATCH",
++ "STATUS_VHD_SPARSE_HEADER_UNSUPPORTED_VERSION",
++ "STATUS_VHD_SPARSE_HEADER_CORRUPT",
++ "STATUS_VHD_BLOCK_ALLOCATION_FAILURE",
++ "STATUS_VHD_BLOCK_ALLOCATION_TABLE_CORRUPT",
++ "STATUS_VHD_INVALID_BLOCK_SIZE",
++ "STATUS_VHD_BITMAP_MISMATCH",
++ "STATUS_VHD_PARENT_VHD_NOT_FOUND",
++ "STATUS_VHD_CHILD_PARENT_ID_MISMATCH",
++ "STATUS_VHD_CHILD_PARENT_TIMESTAMP_MISMATCH",
++ "STATUS_VHD_METADATA_READ_FAILURE",
++ "STATUS_VHD_METADATA_WRITE_FAILURE",
++ "STATUS_VHD_INVALID_SIZE",
++ "STATUS_VHD_INVALID_FILE_SIZE",
++ "STATUS_VIRTDISK_PROVIDER_NOT_FOUND",
++ "STATUS_VIRTDISK_NOT_VIRTUAL_DISK",
++ "STATUS_VHD_PARENT_VHD_ACCESS_DENIED",
++ "STATUS_VHD_CHILD_PARENT_SIZE_MISMATCH",
++ "STATUS_VHD_DIFFERENCING_CHAIN_CYCLE_DETECTED",
++ "STATUS_VHD_DIFFERENCING_CHAIN_ERROR_IN_PARENT",
++ "STATUS_VIRTUAL_DISK_LIMITATION",
++ "STATUS_VHD_INVALID_TYPE",
++ "STATUS_VHD_INVALID_STATE",
++ "STATUS_VIRTDISK_UNSUPPORTED_DISK_SECTOR_SIZE",
++ "STATUS_VIRTDISK_DISK_ALREADY_OWNED",
++ "STATUS_VIRTDISK_DISK_ONLINE_AND_WRITABLE",
++ "STATUS_CTLOG_TRACKING_NOT_INITIALIZED",
++ "STATUS_CTLOG_LOGFILE_SIZE_EXCEEDED_MAXSIZE",
++ "STATUS_CTLOG_VHD_CHANGED_OFFLINE",
++ "STATUS_CTLOG_INVALID_TRACKING_STATE",
++ "STATUS_CTLOG_INCONSISTENT_TRACKING_FILE",
++ "STATUS_VHD_METADATA_FULL",
++ "STATUS_VHD_INVALID_CHANGE_TRACKING_ID",
++ "STATUS_VHD_CHANGE_TRACKING_DISABLED",
++ "STATUS_VHD_MISSING_CHANGE_TRACKING_INFORMATION",
++ "STATUS_VHD_RESIZE_WOULD_TRUNCATE_DATA",
++ "STATUS_VHD_COULD_NOT_COMPUTE_MINIMUM_VIRTUAL_SIZE",
++ "STATUS_VHD_ALREADY_AT_OR_BELOW_MINIMUM_VIRTUAL_SIZE",
++ "STATUS_RKF_KEY_NOT_FOUND",
++ "STATUS_RKF_DUPLICATE_KEY",
++ "STATUS_RKF_BLOB_FULL",
++ "STATUS_RKF_STORE_FULL",
++ "STATUS_RKF_FILE_BLOCKED",
++ "STATUS_RKF_ACTIVE_KEY",
++ "STATUS_RDBSS_RESTART_OPERATION",
++ "STATUS_RDBSS_CONTINUE_OPERATION",
++ "STATUS_RDBSS_POST_OPERATION",
++ "STATUS_RDBSS_RETRY_LOOKUP",
++ "STATUS_BTH_ATT_INVALID_HANDLE",
++ "STATUS_BTH_ATT_READ_NOT_PERMITTED",
++ "STATUS_BTH_ATT_WRITE_NOT_PERMITTED",
++ "STATUS_BTH_ATT_INVALID_PDU",
++ "STATUS_BTH_ATT_INSUFFICIENT_AUTHENTICATION",
++ "STATUS_BTH_ATT_REQUEST_NOT_SUPPORTED",
++ "STATUS_BTH_ATT_INVALID_OFFSET",
++ "STATUS_BTH_ATT_INSUFFICIENT_AUTHORIZATION",
++ "STATUS_BTH_ATT_PREPARE_QUEUE_FULL",
++ "STATUS_BTH_ATT_ATTRIBUTE_NOT_FOUND",
++ "STATUS_BTH_ATT_ATTRIBUTE_NOT_LONG",
++ "STATUS_BTH_ATT_INSUFFICIENT_ENCRYPTION_KEY_SIZE",
++ "STATUS_BTH_ATT_INVALID_ATTRIBUTE_VALUE_LENGTH",
++ "STATUS_BTH_ATT_UNLIKELY",
++ "STATUS_BTH_ATT_INSUFFICIENT_ENCRYPTION",
++ "STATUS_BTH_ATT_UNSUPPORTED_GROUP_TYPE",
++ "STATUS_BTH_ATT_INSUFFICIENT_RESOURCES",
++ "STATUS_BTH_ATT_UNKNOWN_ERROR",
++ "STATUS_SECUREBOOT_ROLLBACK_DETECTED",
++ "STATUS_SECUREBOOT_POLICY_VIOLATION",
++ "STATUS_SECUREBOOT_INVALID_POLICY",
++ "STATUS_SECUREBOOT_POLICY_PUBLISHER_NOT_FOUND",
++ "STATUS_SECUREBOOT_POLICY_NOT_SIGNED",
++ "STATUS_SECUREBOOT_FILE_REPLACED",
++ "STATUS_SECUREBOOT_POLICY_NOT_AUTHORIZED",
++ "STATUS_SECUREBOOT_POLICY_UNKNOWN",
++ "STATUS_SECUREBOOT_POLICY_MISSING_ANTIROLLBACKVERSION",
++ "STATUS_SECUREBOOT_PLATFORM_ID_MISMATCH",
++ "STATUS_SECUREBOOT_POLICY_ROLLBACK_DETECTED",
++ "STATUS_SECUREBOOT_POLICY_UPGRADE_MISMATCH",
++ "STATUS_SECUREBOOT_REQUIRED_POLICY_FILE_MISSING",
++ "STATUS_SECUREBOOT_NOT_BASE_POLICY",
++ "STATUS_SECUREBOOT_NOT_SUPPLEMENTAL_POLICY",
++ "STATUS_AUDIO_ENGINE_NODE_NOT_FOUND",
++ "STATUS_HDAUDIO_EMPTY_CONNECTION_LIST",
++ "STATUS_HDAUDIO_CONNECTION_LIST_NOT_SUPPORTED",
++ "STATUS_HDAUDIO_NO_LOGICAL_DEVICES_CREATED",
++ "STATUS_HDAUDIO_NULL_LINKED_LIST_ENTRY",
++ "STATUS_VSM_NOT_INITIALIZED",
++ "STATUS_VSM_DMA_PROTECTION_NOT_IN_USE",
++ "STATUS_VOLSNAP_BOOTFILE_NOT_VALID",
++ "STATUS_VOLSNAP_ACTIVATION_TIMEOUT",
++ "STATUS_IO_PREEMPTED",
++ "STATUS_SVHDX_ERROR_STORED",
++ "STATUS_SVHDX_ERROR_NOT_AVAILABLE",
++ "STATUS_SVHDX_UNIT_ATTENTION_AVAILABLE",
++ "STATUS_SVHDX_UNIT_ATTENTION_CAPACITY_DATA_CHANGED",
++ "STATUS_SVHDX_UNIT_ATTENTION_RESERVATIONS_PREEMPTED",
++ "STATUS_SVHDX_UNIT_ATTENTION_RESERVATIONS_RELEASED",
++ "STATUS_SVHDX_UNIT_ATTENTION_REGISTRATIONS_PREEMPTED",
++ "STATUS_SVHDX_UNIT_ATTENTION_OPERATING_DEFINITION_CHANGED",
++ "STATUS_SVHDX_RESERVATION_CONFLICT",
++ "STATUS_SVHDX_WRONG_FILE_TYPE",
++ "STATUS_SVHDX_VERSION_MISMATCH",
++ "STATUS_VHD_SHARED",
++ "STATUS_SVHDX_NO_INITIATOR",
++ "STATUS_VHDSET_BACKING_STORAGE_NOT_FOUND",
++ "STATUS_SMB_NO_PREAUTH_INTEGRITY_HASH_OVERLAP",
++ "STATUS_SMB_BAD_CLUSTER_DIALECT",
++ "STATUS_SMB_GUEST_LOGON_BLOCKED",
++ "STATUS_SPACES_FAULT_DOMAIN_TYPE_INVALID",
++ "STATUS_SPACES_RESILIENCY_TYPE_INVALID",
++ "STATUS_SPACES_DRIVE_SECTOR_SIZE_INVALID",
++ "STATUS_SPACES_DRIVE_REDUNDANCY_INVALID",
++ "STATUS_SPACES_NUMBER_OF_DATA_COPIES_INVALID",
++ "STATUS_SPACES_INTERLEAVE_LENGTH_INVALID",
++ "STATUS_SPACES_NUMBER_OF_COLUMNS_INVALID",
++ "STATUS_SPACES_NOT_ENOUGH_DRIVES",
++ "STATUS_SPACES_EXTENDED_ERROR",
++ "STATUS_SPACES_PROVISIONING_TYPE_INVALID",
++ "STATUS_SPACES_ALLOCATION_SIZE_INVALID",
++ "STATUS_SPACES_ENCLOSURE_AWARE_INVALID",
++ "STATUS_SPACES_WRITE_CACHE_SIZE_INVALID",
++ "STATUS_SPACES_NUMBER_OF_GROUPS_INVALID",
++ "STATUS_SPACES_DRIVE_OPERATIONAL_STATE_INVALID",
++ "STATUS_SPACES_UPDATE_COLUMN_STATE",
++ "STATUS_SPACES_MAP_REQUIRED",
++ "STATUS_SPACES_UNSUPPORTED_VERSION",
++ "STATUS_SPACES_CORRUPT_METADATA",
++ "STATUS_SPACES_DRT_FULL",
++ "STATUS_SPACES_INCONSISTENCY",
++ "STATUS_SPACES_LOG_NOT_READY",
++ "STATUS_SPACES_NO_REDUNDANCY",
++ "STATUS_SPACES_DRIVE_NOT_READY",
++ "STATUS_SPACES_DRIVE_SPLIT",
++ "STATUS_SPACES_DRIVE_LOST_DATA",
++ "STATUS_SPACES_ENTRY_INCOMPLETE",
++ "STATUS_SPACES_ENTRY_INVALID",
++ "STATUS_SPACES_MARK_DIRTY",
++ "STATUS_SECCORE_INVALID_COMMAND",
++ "STATUS_SYSTEM_INTEGRITY_ROLLBACK_DETECTED",
++ "STATUS_SYSTEM_INTEGRITY_POLICY_VIOLATION",
++ "STATUS_SYSTEM_INTEGRITY_INVALID_POLICY",
++ "STATUS_SYSTEM_INTEGRITY_POLICY_NOT_SIGNED",
++ "STATUS_SYSTEM_INTEGRITY_TOO_MANY_POLICIES",
++ "STATUS_SYSTEM_INTEGRITY_SUPPLEMENTAL_POLICY_NOT_AUTHORIZED",
++ "STATUS_NO_APPLICABLE_APP_LICENSES_FOUND",
++ "STATUS_CLIP_LICENSE_NOT_FOUND",
++ "STATUS_CLIP_DEVICE_LICENSE_MISSING",
++ "STATUS_CLIP_LICENSE_INVALID_SIGNATURE",
++ "STATUS_CLIP_KEYHOLDER_LICENSE_MISSING_OR_INVALID",
++ "STATUS_CLIP_LICENSE_EXPIRED",
++ "STATUS_CLIP_LICENSE_SIGNED_BY_UNKNOWN_SOURCE",
++ "STATUS_CLIP_LICENSE_NOT_SIGNED",
++ "STATUS_CLIP_LICENSE_HARDWARE_ID_OUT_OF_TOLERANCE",
++ "STATUS_CLIP_LICENSE_DEVICE_ID_MISMATCH",
++ "STATUS_PLATFORM_MANIFEST_NOT_AUTHORIZED",
++ "STATUS_PLATFORM_MANIFEST_INVALID",
++ "STATUS_PLATFORM_MANIFEST_FILE_NOT_AUTHORIZED",
++ "STATUS_PLATFORM_MANIFEST_CATALOG_NOT_AUTHORIZED",
++ "STATUS_PLATFORM_MANIFEST_BINARY_ID_NOT_FOUND",
++ "STATUS_PLATFORM_MANIFEST_NOT_ACTIVE",
++ "STATUS_PLATFORM_MANIFEST_NOT_SIGNED",
++ "STATUS_APPEXEC_CONDITION_NOT_SATISFIED",
++ "STATUS_APPEXEC_HANDLE_INVALIDATED",
++ "STATUS_APPEXEC_INVALID_HOST_GENERATION",
++ "STATUS_APPEXEC_UNEXPECTED_PROCESS_REGISTRATION",
++ "STATUS_APPEXEC_INVALID_HOST_STATE",
++ "STATUS_APPEXEC_NO_DONOR",
++ "STATUS_APPEXEC_HOST_ID_MISMATCH",
++ "STATUS_APPEXEC_UNKNOWN_USER",
++};
++
++const char* NTStatusToString(uint32_t ntstatus) {
++ auto itr = std::find(std::begin(kNTStatusValues),
++ std::end(kNTStatusValues),
++ ntstatus);
++ if (itr == std::end(kNTStatusValues)) {
++ return nullptr;
+ }
+- return reason;
++
++ return kNTStatusStrings[itr - std::begin(kNTStatusValues)];
+ }
+
+-string FastFailToString(uint32_t fast_fail_code) {
+- string code_string;
+- // The content of this switch was created from winnt.h in the 10 SDK
+- // (version 10.0.19041.0) with
+- //
+- // egrep '#define FAST_FAIL_[A-Z_0-9]+\s+[0-9]' winnt.h
+- // | tr -d '\r'
+- // | sed -r 's@#define FAST_FAIL_([A-Z_0-9]+)\s+([0-9]+).*@\2 \1@'
+- // | sed -r 's@([0-9]+) ([A-Z_0-9]+)@ case MD_FAST_FAIL_WIN_\2:\n code_string = "FAST_FAIL_\2";\n break;@'
+- //
+- // and then the default case added.
+- switch (fast_fail_code) {
+- case MD_FAST_FAIL_WIN_LEGACY_GS_VIOLATION:
+- code_string = "FAST_FAIL_LEGACY_GS_VIOLATION";
+- break;
+- case MD_FAST_FAIL_WIN_VTGUARD_CHECK_FAILURE:
+- code_string = "FAST_FAIL_VTGUARD_CHECK_FAILURE";
+- break;
+- case MD_FAST_FAIL_WIN_STACK_COOKIE_CHECK_FAILURE:
+- code_string = "FAST_FAIL_STACK_COOKIE_CHECK_FAILURE";
+- break;
+- case MD_FAST_FAIL_WIN_CORRUPT_LIST_ENTRY:
+- code_string = "FAST_FAIL_CORRUPT_LIST_ENTRY";
+- break;
+- case MD_FAST_FAIL_WIN_INCORRECT_STACK:
+- code_string = "FAST_FAIL_INCORRECT_STACK";
+- break;
+- case MD_FAST_FAIL_WIN_INVALID_ARG:
+- code_string = "FAST_FAIL_INVALID_ARG";
+- break;
+- case MD_FAST_FAIL_WIN_GS_COOKIE_INIT:
+- code_string = "FAST_FAIL_GS_COOKIE_INIT";
+- break;
+- case MD_FAST_FAIL_WIN_FATAL_APP_EXIT:
+- code_string = "FAST_FAIL_FATAL_APP_EXIT";
+- break;
+- case MD_FAST_FAIL_WIN_RANGE_CHECK_FAILURE:
+- code_string = "FAST_FAIL_RANGE_CHECK_FAILURE";
+- break;
+- case MD_FAST_FAIL_WIN_UNSAFE_REGISTRY_ACCESS:
+- code_string = "FAST_FAIL_UNSAFE_REGISTRY_ACCESS";
+- break;
+- case MD_FAST_FAIL_WIN_GUARD_ICALL_CHECK_FAILURE:
+- code_string = "FAST_FAIL_GUARD_ICALL_CHECK_FAILURE";
+- break;
+- case MD_FAST_FAIL_WIN_GUARD_WRITE_CHECK_FAILURE:
+- code_string = "FAST_FAIL_GUARD_WRITE_CHECK_FAILURE";
+- break;
+- case MD_FAST_FAIL_WIN_INVALID_FIBER_SWITCH:
+- code_string = "FAST_FAIL_INVALID_FIBER_SWITCH";
+- break;
+- case MD_FAST_FAIL_WIN_INVALID_SET_OF_CONTEXT:
+- code_string = "FAST_FAIL_INVALID_SET_OF_CONTEXT";
+- break;
+- case MD_FAST_FAIL_WIN_INVALID_REFERENCE_COUNT:
+- code_string = "FAST_FAIL_INVALID_REFERENCE_COUNT";
+- break;
+- case MD_FAST_FAIL_WIN_INVALID_JUMP_BUFFER:
+- code_string = "FAST_FAIL_INVALID_JUMP_BUFFER";
+- break;
+- case MD_FAST_FAIL_WIN_MRDATA_MODIFIED:
+- code_string = "FAST_FAIL_MRDATA_MODIFIED";
+- break;
+- case MD_FAST_FAIL_WIN_CERTIFICATION_FAILURE:
+- code_string = "FAST_FAIL_CERTIFICATION_FAILURE";
+- break;
+- case MD_FAST_FAIL_WIN_INVALID_EXCEPTION_CHAIN:
+- code_string = "FAST_FAIL_INVALID_EXCEPTION_CHAIN";
+- break;
+- case MD_FAST_FAIL_WIN_CRYPTO_LIBRARY:
+- code_string = "FAST_FAIL_CRYPTO_LIBRARY";
+- break;
+- case MD_FAST_FAIL_WIN_INVALID_CALL_IN_DLL_CALLOUT:
+- code_string = "FAST_FAIL_INVALID_CALL_IN_DLL_CALLOUT";
+- break;
+- case MD_FAST_FAIL_WIN_INVALID_IMAGE_BASE:
+- code_string = "FAST_FAIL_INVALID_IMAGE_BASE";
+- break;
+- case MD_FAST_FAIL_WIN_DLOAD_PROTECTION_FAILURE:
+- code_string = "FAST_FAIL_DLOAD_PROTECTION_FAILURE";
+- break;
+- case MD_FAST_FAIL_WIN_UNSAFE_EXTENSION_CALL:
+- code_string = "FAST_FAIL_UNSAFE_EXTENSION_CALL";
+- break;
+- case MD_FAST_FAIL_WIN_DEPRECATED_SERVICE_INVOKED:
+- code_string = "FAST_FAIL_DEPRECATED_SERVICE_INVOKED";
+- break;
+- case MD_FAST_FAIL_WIN_INVALID_BUFFER_ACCESS:
+- code_string = "FAST_FAIL_INVALID_BUFFER_ACCESS";
+- break;
+- case MD_FAST_FAIL_WIN_INVALID_BALANCED_TREE:
+- code_string = "FAST_FAIL_INVALID_BALANCED_TREE";
+- break;
+- case MD_FAST_FAIL_WIN_INVALID_NEXT_THREAD:
+- code_string = "FAST_FAIL_INVALID_NEXT_THREAD";
+- break;
+- case MD_FAST_FAIL_WIN_GUARD_ICALL_CHECK_SUPPRESSED:
+- code_string = "FAST_FAIL_GUARD_ICALL_CHECK_SUPPRESSED";
+- break;
+- case MD_FAST_FAIL_WIN_APCS_DISABLED:
+- code_string = "FAST_FAIL_APCS_DISABLED";
+- break;
+- case MD_FAST_FAIL_WIN_INVALID_IDLE_STATE:
+- code_string = "FAST_FAIL_INVALID_IDLE_STATE";
+- break;
+- case MD_FAST_FAIL_WIN_MRDATA_PROTECTION_FAILURE:
+- code_string = "FAST_FAIL_MRDATA_PROTECTION_FAILURE";
+- break;
+- case MD_FAST_FAIL_WIN_UNEXPECTED_HEAP_EXCEPTION:
+- code_string = "FAST_FAIL_UNEXPECTED_HEAP_EXCEPTION";
+- break;
+- case MD_FAST_FAIL_WIN_INVALID_LOCK_STATE:
+- code_string = "FAST_FAIL_INVALID_LOCK_STATE";
+- break;
+- case MD_FAST_FAIL_WIN_GUARD_JUMPTABLE:
+- code_string = "FAST_FAIL_GUARD_JUMPTABLE";
+- break;
+- case MD_FAST_FAIL_WIN_INVALID_LONGJUMP_TARGET:
+- code_string = "FAST_FAIL_INVALID_LONGJUMP_TARGET";
+- break;
+- case MD_FAST_FAIL_WIN_INVALID_DISPATCH_CONTEXT:
+- code_string = "FAST_FAIL_INVALID_DISPATCH_CONTEXT";
+- break;
+- case MD_FAST_FAIL_WIN_INVALID_THREAD:
+- code_string = "FAST_FAIL_INVALID_THREAD";
+- break;
+- case MD_FAST_FAIL_WIN_INVALID_SYSCALL_NUMBER:
+- code_string = "FAST_FAIL_INVALID_SYSCALL_NUMBER";
+- break;
+- case MD_FAST_FAIL_WIN_INVALID_FILE_OPERATION:
+- code_string = "FAST_FAIL_INVALID_FILE_OPERATION";
+- break;
+- case MD_FAST_FAIL_WIN_LPAC_ACCESS_DENIED:
+- code_string = "FAST_FAIL_LPAC_ACCESS_DENIED";
+- break;
+- case MD_FAST_FAIL_WIN_GUARD_SS_FAILURE:
+- code_string = "FAST_FAIL_GUARD_SS_FAILURE";
+- break;
+- case MD_FAST_FAIL_WIN_LOADER_CONTINUITY_FAILURE:
+- code_string = "FAST_FAIL_LOADER_CONTINUITY_FAILURE";
+- break;
+- case MD_FAST_FAIL_WIN_GUARD_EXPORT_SUPPRESSION_FAILURE:
+- code_string = "FAST_FAIL_GUARD_EXPORT_SUPPRESSION_FAILURE";
+- break;
+- case MD_FAST_FAIL_WIN_INVALID_CONTROL_STACK:
+- code_string = "FAST_FAIL_INVALID_CONTROL_STACK";
+- break;
+- case MD_FAST_FAIL_WIN_SET_CONTEXT_DENIED:
+- code_string = "FAST_FAIL_SET_CONTEXT_DENIED";
+- break;
+- case MD_FAST_FAIL_WIN_INVALID_IAT:
+- code_string = "FAST_FAIL_INVALID_IAT";
+- break;
+- case MD_FAST_FAIL_WIN_HEAP_METADATA_CORRUPTION:
+- code_string = "FAST_FAIL_HEAP_METADATA_CORRUPTION";
+- break;
+- case MD_FAST_FAIL_WIN_PAYLOAD_RESTRICTION_VIOLATION:
+- code_string = "FAST_FAIL_PAYLOAD_RESTRICTION_VIOLATION";
+- break;
+- case MD_FAST_FAIL_WIN_LOW_LABEL_ACCESS_DENIED:
+- code_string = "FAST_FAIL_LOW_LABEL_ACCESS_DENIED";
+- break;
+- case MD_FAST_FAIL_WIN_ENCLAVE_CALL_FAILURE:
+- code_string = "FAST_FAIL_ENCLAVE_CALL_FAILURE";
+- break;
+- case MD_FAST_FAIL_WIN_UNHANDLED_LSS_EXCEPTON:
+- code_string = "FAST_FAIL_UNHANDLED_LSS_EXCEPTON";
+- break;
+- case MD_FAST_FAIL_WIN_ADMINLESS_ACCESS_DENIED:
+- code_string = "FAST_FAIL_ADMINLESS_ACCESS_DENIED";
+- break;
+- case MD_FAST_FAIL_WIN_UNEXPECTED_CALL:
+- code_string = "FAST_FAIL_UNEXPECTED_CALL";
+- break;
+- case MD_FAST_FAIL_WIN_CONTROL_INVALID_RETURN_ADDRESS:
+- code_string = "FAST_FAIL_CONTROL_INVALID_RETURN_ADDRESS";
+- break;
+- case MD_FAST_FAIL_WIN_UNEXPECTED_HOST_BEHAVIOR:
+- code_string = "FAST_FAIL_UNEXPECTED_HOST_BEHAVIOR";
+- break;
+- case MD_FAST_FAIL_WIN_FLAGS_CORRUPTION:
+- code_string = "FAST_FAIL_FLAGS_CORRUPTION";
+- break;
+- case MD_FAST_FAIL_WIN_VEH_CORRUPTION:
+- code_string = "FAST_FAIL_VEH_CORRUPTION";
+- break;
+- case MD_FAST_FAIL_WIN_ETW_CORRUPTION:
+- code_string = "FAST_FAIL_ETW_CORRUPTION";
+- break;
+- case MD_FAST_FAIL_WIN_RIO_ABORT:
+- code_string = "FAST_FAIL_RIO_ABORT";
+- break;
+- case MD_FAST_FAIL_WIN_INVALID_PFN:
+- code_string = "FAST_FAIL_INVALID_PFN";
+- break;
+- default: {
+- char buffer[11];
+- snprintf(buffer, sizeof(buffer), "%u", fast_fail_code);
+- code_string = buffer;
+- break;
+- }
++// The content of this array was created from winnt.h in the 10 SDK
++// (version 10.0.19041.0) with the following script:
++//
++// egrep '#define FAST_FAIL_[A-Z_0-9]+\s+[0-9]' winnt.h
++// | tr -d '\r'
++// | sed -r 's@#define FAST_FAIL_([A-Z_0-9]+)\s+([0-9]+).*@\2 \1@'
++// | sed -r 's@([0-9]+) ([A-Z_0-9]+)@ MD_FAST_FAIL_WIN_\2,@'
++// | head -n -1
++static const uint8_t kFastFailValues[] = {
++ MD_FAST_FAIL_WIN_LEGACY_GS_VIOLATION,
++ MD_FAST_FAIL_WIN_VTGUARD_CHECK_FAILURE,
++ MD_FAST_FAIL_WIN_STACK_COOKIE_CHECK_FAILURE,
++ MD_FAST_FAIL_WIN_CORRUPT_LIST_ENTRY,
++ MD_FAST_FAIL_WIN_INCORRECT_STACK,
++ MD_FAST_FAIL_WIN_INVALID_ARG,
++ MD_FAST_FAIL_WIN_GS_COOKIE_INIT,
++ MD_FAST_FAIL_WIN_FATAL_APP_EXIT,
++ MD_FAST_FAIL_WIN_RANGE_CHECK_FAILURE,
++ MD_FAST_FAIL_WIN_UNSAFE_REGISTRY_ACCESS,
++ MD_FAST_FAIL_WIN_GUARD_ICALL_CHECK_FAILURE,
++ MD_FAST_FAIL_WIN_GUARD_WRITE_CHECK_FAILURE,
++ MD_FAST_FAIL_WIN_INVALID_FIBER_SWITCH,
++ MD_FAST_FAIL_WIN_INVALID_SET_OF_CONTEXT,
++ MD_FAST_FAIL_WIN_INVALID_REFERENCE_COUNT,
++ MD_FAST_FAIL_WIN_INVALID_JUMP_BUFFER,
++ MD_FAST_FAIL_WIN_MRDATA_MODIFIED,
++ MD_FAST_FAIL_WIN_CERTIFICATION_FAILURE,
++ MD_FAST_FAIL_WIN_INVALID_EXCEPTION_CHAIN,
++ MD_FAST_FAIL_WIN_CRYPTO_LIBRARY,
++ MD_FAST_FAIL_WIN_INVALID_CALL_IN_DLL_CALLOUT,
++ MD_FAST_FAIL_WIN_INVALID_IMAGE_BASE,
++ MD_FAST_FAIL_WIN_DLOAD_PROTECTION_FAILURE,
++ MD_FAST_FAIL_WIN_UNSAFE_EXTENSION_CALL,
++ MD_FAST_FAIL_WIN_DEPRECATED_SERVICE_INVOKED,
++ MD_FAST_FAIL_WIN_INVALID_BUFFER_ACCESS,
++ MD_FAST_FAIL_WIN_INVALID_BALANCED_TREE,
++ MD_FAST_FAIL_WIN_INVALID_NEXT_THREAD,
++ MD_FAST_FAIL_WIN_GUARD_ICALL_CHECK_SUPPRESSED,
++ MD_FAST_FAIL_WIN_APCS_DISABLED,
++ MD_FAST_FAIL_WIN_INVALID_IDLE_STATE,
++ MD_FAST_FAIL_WIN_MRDATA_PROTECTION_FAILURE,
++ MD_FAST_FAIL_WIN_UNEXPECTED_HEAP_EXCEPTION,
++ MD_FAST_FAIL_WIN_INVALID_LOCK_STATE,
++ MD_FAST_FAIL_WIN_GUARD_JUMPTABLE,
++ MD_FAST_FAIL_WIN_INVALID_LONGJUMP_TARGET,
++ MD_FAST_FAIL_WIN_INVALID_DISPATCH_CONTEXT,
++ MD_FAST_FAIL_WIN_INVALID_THREAD,
++ MD_FAST_FAIL_WIN_INVALID_SYSCALL_NUMBER,
++ MD_FAST_FAIL_WIN_INVALID_FILE_OPERATION,
++ MD_FAST_FAIL_WIN_LPAC_ACCESS_DENIED,
++ MD_FAST_FAIL_WIN_GUARD_SS_FAILURE,
++ MD_FAST_FAIL_WIN_LOADER_CONTINUITY_FAILURE,
++ MD_FAST_FAIL_WIN_GUARD_EXPORT_SUPPRESSION_FAILURE,
++ MD_FAST_FAIL_WIN_INVALID_CONTROL_STACK,
++ MD_FAST_FAIL_WIN_SET_CONTEXT_DENIED,
++ MD_FAST_FAIL_WIN_INVALID_IAT,
++ MD_FAST_FAIL_WIN_HEAP_METADATA_CORRUPTION,
++ MD_FAST_FAIL_WIN_PAYLOAD_RESTRICTION_VIOLATION,
++ MD_FAST_FAIL_WIN_LOW_LABEL_ACCESS_DENIED,
++ MD_FAST_FAIL_WIN_ENCLAVE_CALL_FAILURE,
++ MD_FAST_FAIL_WIN_UNHANDLED_LSS_EXCEPTON,
++ MD_FAST_FAIL_WIN_ADMINLESS_ACCESS_DENIED,
++ MD_FAST_FAIL_WIN_UNEXPECTED_CALL,
++ MD_FAST_FAIL_WIN_CONTROL_INVALID_RETURN_ADDRESS,
++ MD_FAST_FAIL_WIN_UNEXPECTED_HOST_BEHAVIOR,
++ MD_FAST_FAIL_WIN_FLAGS_CORRUPTION,
++ MD_FAST_FAIL_WIN_VEH_CORRUPTION,
++ MD_FAST_FAIL_WIN_ETW_CORRUPTION,
++ MD_FAST_FAIL_WIN_RIO_ABORT,
++ MD_FAST_FAIL_WIN_INVALID_PFN,
++};
++
++// The content of this array was created from winnt.h in the 10 SDK
++// (version 10.0.19041.0) with the following script:
++//
++// egrep '#define FAST_FAIL_[A-Z_0-9]+\s+[0-9]' winnt.h
++// | tr -d '\r'
++// | sed -r 's@#define FAST_FAIL_([A-Z_0-9]+)\s+([0-9]+).*@\2 \1@'
++// | sed -r 's@([0-9]+) ([A-Z_0-9]+)@ "FAST_FAIL_\2",@'
++// | head -n -1
++static const char* kFastFailStrings[] = {
++ "FAST_FAIL_LEGACY_GS_VIOLATION",
++ "FAST_FAIL_VTGUARD_CHECK_FAILURE",
++ "FAST_FAIL_STACK_COOKIE_CHECK_FAILURE",
++ "FAST_FAIL_CORRUPT_LIST_ENTRY",
++ "FAST_FAIL_INCORRECT_STACK",
++ "FAST_FAIL_INVALID_ARG",
++ "FAST_FAIL_GS_COOKIE_INIT",
++ "FAST_FAIL_FATAL_APP_EXIT",
++ "FAST_FAIL_RANGE_CHECK_FAILURE",
++ "FAST_FAIL_UNSAFE_REGISTRY_ACCESS",
++ "FAST_FAIL_GUARD_ICALL_CHECK_FAILURE",
++ "FAST_FAIL_GUARD_WRITE_CHECK_FAILURE",
++ "FAST_FAIL_INVALID_FIBER_SWITCH",
++ "FAST_FAIL_INVALID_SET_OF_CONTEXT",
++ "FAST_FAIL_INVALID_REFERENCE_COUNT",
++ "FAST_FAIL_INVALID_JUMP_BUFFER",
++ "FAST_FAIL_MRDATA_MODIFIED",
++ "FAST_FAIL_CERTIFICATION_FAILURE",
++ "FAST_FAIL_INVALID_EXCEPTION_CHAIN",
++ "FAST_FAIL_CRYPTO_LIBRARY",
++ "FAST_FAIL_INVALID_CALL_IN_DLL_CALLOUT",
++ "FAST_FAIL_INVALID_IMAGE_BASE",
++ "FAST_FAIL_DLOAD_PROTECTION_FAILURE",
++ "FAST_FAIL_UNSAFE_EXTENSION_CALL",
++ "FAST_FAIL_DEPRECATED_SERVICE_INVOKED",
++ "FAST_FAIL_INVALID_BUFFER_ACCESS",
++ "FAST_FAIL_INVALID_BALANCED_TREE",
++ "FAST_FAIL_INVALID_NEXT_THREAD",
++ "FAST_FAIL_GUARD_ICALL_CHECK_SUPPRESSED",
++ "FAST_FAIL_APCS_DISABLED",
++ "FAST_FAIL_INVALID_IDLE_STATE",
++ "FAST_FAIL_MRDATA_PROTECTION_FAILURE",
++ "FAST_FAIL_UNEXPECTED_HEAP_EXCEPTION",
++ "FAST_FAIL_INVALID_LOCK_STATE",
++ "FAST_FAIL_GUARD_JUMPTABLE",
++ "FAST_FAIL_INVALID_LONGJUMP_TARGET",
++ "FAST_FAIL_INVALID_DISPATCH_CONTEXT",
++ "FAST_FAIL_INVALID_THREAD",
++ "FAST_FAIL_INVALID_SYSCALL_NUMBER",
++ "FAST_FAIL_INVALID_FILE_OPERATION",
++ "FAST_FAIL_LPAC_ACCESS_DENIED",
++ "FAST_FAIL_GUARD_SS_FAILURE",
++ "FAST_FAIL_LOADER_CONTINUITY_FAILURE",
++ "FAST_FAIL_GUARD_EXPORT_SUPPRESSION_FAILURE",
++ "FAST_FAIL_INVALID_CONTROL_STACK",
++ "FAST_FAIL_SET_CONTEXT_DENIED",
++ "FAST_FAIL_INVALID_IAT",
++ "FAST_FAIL_HEAP_METADATA_CORRUPTION",
++ "FAST_FAIL_PAYLOAD_RESTRICTION_VIOLATION",
++ "FAST_FAIL_LOW_LABEL_ACCESS_DENIED",
++ "FAST_FAIL_ENCLAVE_CALL_FAILURE",
++ "FAST_FAIL_UNHANDLED_LSS_EXCEPTON",
++ "FAST_FAIL_ADMINLESS_ACCESS_DENIED",
++ "FAST_FAIL_UNEXPECTED_CALL",
++ "FAST_FAIL_CONTROL_INVALID_RETURN_ADDRESS",
++ "FAST_FAIL_UNEXPECTED_HOST_BEHAVIOR",
++ "FAST_FAIL_FLAGS_CORRUPTION",
++ "FAST_FAIL_VEH_CORRUPTION",
++ "FAST_FAIL_ETW_CORRUPTION",
++ "FAST_FAIL_RIO_ABORT",
++ "FAST_FAIL_INVALID_PFN",
++};
++
++const char* FastFailToString(uint32_t fast_fail_code) {
++ auto itr = std::find(std::begin(kFastFailValues),
++ std::end(kFastFailValues),
++ fast_fail_code);
++ if (itr == std::end(kFastFailValues)) {
++ return nullptr;
+ }
+- return code_string;
++
++ return kFastFailStrings[itr - std::begin(kFastFailValues)];
++}
++
++// The content of this array was created from winerror.h in the 10 SDK
++// (version 10.0.19041.0) with the following script:
++//
++// egrep -o '#define ERROR_[A-Z_0-9]+\s+[0-9]+L' winerror.h
++// | tr -d '\r'
++// | sed -r 's@#define ERROR_([A-Z_0-9]+)\s+([0-9]+)L@\2 \1@'
++// | sort -n
++// | sed -r 's@([0-9]+) ([A-Z_0-9]+)@ MD_ERROR_WIN_\2,@'
++static const uint16_t kWinErrorValues[] = {
++ MD_ERROR_WIN_SUCCESS,
++ MD_ERROR_WIN_INVALID_FUNCTION,
++ MD_ERROR_WIN_FILE_NOT_FOUND,
++ MD_ERROR_WIN_PATH_NOT_FOUND,
++ MD_ERROR_WIN_TOO_MANY_OPEN_FILES,
++ MD_ERROR_WIN_ACCESS_DENIED,
++ MD_ERROR_WIN_INVALID_HANDLE,
++ MD_ERROR_WIN_ARENA_TRASHED,
++ MD_ERROR_WIN_NOT_ENOUGH_MEMORY,
++ MD_ERROR_WIN_INVALID_BLOCK,
++ MD_ERROR_WIN_BAD_ENVIRONMENT,
++ MD_ERROR_WIN_BAD_FORMAT,
++ MD_ERROR_WIN_INVALID_ACCESS,
++ MD_ERROR_WIN_INVALID_DATA,
++ MD_ERROR_WIN_OUTOFMEMORY,
++ MD_ERROR_WIN_INVALID_DRIVE,
++ MD_ERROR_WIN_CURRENT_DIRECTORY,
++ MD_ERROR_WIN_NOT_SAME_DEVICE,
++ MD_ERROR_WIN_NO_MORE_FILES,
++ MD_ERROR_WIN_WRITE_PROTECT,
++ MD_ERROR_WIN_BAD_UNIT,
++ MD_ERROR_WIN_NOT_READY,
++ MD_ERROR_WIN_BAD_COMMAND,
++ MD_ERROR_WIN_CRC,
++ MD_ERROR_WIN_BAD_LENGTH,
++ MD_ERROR_WIN_SEEK,
++ MD_ERROR_WIN_NOT_DOS_DISK,
++ MD_ERROR_WIN_SECTOR_NOT_FOUND,
++ MD_ERROR_WIN_OUT_OF_PAPER,
++ MD_ERROR_WIN_WRITE_FAULT,
++ MD_ERROR_WIN_READ_FAULT,
++ MD_ERROR_WIN_GEN_FAILURE,
++ MD_ERROR_WIN_SHARING_VIOLATION,
++ MD_ERROR_WIN_LOCK_VIOLATION,
++ MD_ERROR_WIN_WRONG_DISK,
++ MD_ERROR_WIN_SHARING_BUFFER_EXCEEDED,
++ MD_ERROR_WIN_HANDLE_EOF,
++ MD_ERROR_WIN_HANDLE_DISK_FULL,
++ MD_ERROR_WIN_NOT_SUPPORTED,
++ MD_ERROR_WIN_REM_NOT_LIST,
++ MD_ERROR_WIN_DUP_NAME,
++ MD_ERROR_WIN_BAD_NETPATH,
++ MD_ERROR_WIN_NETWORK_BUSY,
++ MD_ERROR_WIN_DEV_NOT_EXIST,
++ MD_ERROR_WIN_TOO_MANY_CMDS,
++ MD_ERROR_WIN_ADAP_HDW_ERR,
++ MD_ERROR_WIN_BAD_NET_RESP,
++ MD_ERROR_WIN_UNEXP_NET_ERR,
++ MD_ERROR_WIN_BAD_REM_ADAP,
++ MD_ERROR_WIN_PRINTQ_FULL,
++ MD_ERROR_WIN_NO_SPOOL_SPACE,
++ MD_ERROR_WIN_PRINT_CANCELLED,
++ MD_ERROR_WIN_NETNAME_DELETED,
++ MD_ERROR_WIN_NETWORK_ACCESS_DENIED,
++ MD_ERROR_WIN_BAD_DEV_TYPE,
++ MD_ERROR_WIN_BAD_NET_NAME,
++ MD_ERROR_WIN_TOO_MANY_NAMES,
++ MD_ERROR_WIN_TOO_MANY_SESS,
++ MD_ERROR_WIN_SHARING_PAUSED,
++ MD_ERROR_WIN_REQ_NOT_ACCEP,
++ MD_ERROR_WIN_REDIR_PAUSED,
++ MD_ERROR_WIN_FILE_EXISTS,
++ MD_ERROR_WIN_CANNOT_MAKE,
++ MD_ERROR_WIN_FAIL_I24,
++ MD_ERROR_WIN_OUT_OF_STRUCTURES,
++ MD_ERROR_WIN_ALREADY_ASSIGNED,
++ MD_ERROR_WIN_INVALID_PASSWORD,
++ MD_ERROR_WIN_INVALID_PARAMETER,
++ MD_ERROR_WIN_NET_WRITE_FAULT,
++ MD_ERROR_WIN_NO_PROC_SLOTS,
++ MD_ERROR_WIN_TOO_MANY_SEMAPHORES,
++ MD_ERROR_WIN_EXCL_SEM_ALREADY_OWNED,
++ MD_ERROR_WIN_SEM_IS_SET,
++ MD_ERROR_WIN_TOO_MANY_SEM_REQUESTS,
++ MD_ERROR_WIN_INVALID_AT_INTERRUPT_TIME,
++ MD_ERROR_WIN_SEM_OWNER_DIED,
++ MD_ERROR_WIN_SEM_USER_LIMIT,
++ MD_ERROR_WIN_DISK_CHANGE,
++ MD_ERROR_WIN_DRIVE_LOCKED,
++ MD_ERROR_WIN_BROKEN_PIPE,
++ MD_ERROR_WIN_OPEN_FAILED,
++ MD_ERROR_WIN_BUFFER_OVERFLOW,
++ MD_ERROR_WIN_DISK_FULL,
++ MD_ERROR_WIN_NO_MORE_SEARCH_HANDLES,
++ MD_ERROR_WIN_INVALID_TARGET_HANDLE,
++ MD_ERROR_WIN_INVALID_CATEGORY,
++ MD_ERROR_WIN_INVALID_VERIFY_SWITCH,
++ MD_ERROR_WIN_BAD_DRIVER_LEVEL,
++ MD_ERROR_WIN_CALL_NOT_IMPLEMENTED,
++ MD_ERROR_WIN_SEM_TIMEOUT,
++ MD_ERROR_WIN_INSUFFICIENT_BUFFER,
++ MD_ERROR_WIN_INVALID_NAME,
++ MD_ERROR_WIN_INVALID_LEVEL,
++ MD_ERROR_WIN_NO_VOLUME_LABEL,
++ MD_ERROR_WIN_MOD_NOT_FOUND,
++ MD_ERROR_WIN_PROC_NOT_FOUND,
++ MD_ERROR_WIN_WAIT_NO_CHILDREN,
++ MD_ERROR_WIN_CHILD_NOT_COMPLETE,
++ MD_ERROR_WIN_DIRECT_ACCESS_HANDLE,
++ MD_ERROR_WIN_NEGATIVE_SEEK,
++ MD_ERROR_WIN_SEEK_ON_DEVICE,
++ MD_ERROR_WIN_IS_JOIN_TARGET,
++ MD_ERROR_WIN_IS_JOINED,
++ MD_ERROR_WIN_IS_SUBSTED,
++ MD_ERROR_WIN_NOT_JOINED,
++ MD_ERROR_WIN_NOT_SUBSTED,
++ MD_ERROR_WIN_JOIN_TO_JOIN,
++ MD_ERROR_WIN_SUBST_TO_SUBST,
++ MD_ERROR_WIN_JOIN_TO_SUBST,
++ MD_ERROR_WIN_SUBST_TO_JOIN,
++ MD_ERROR_WIN_BUSY_DRIVE,
++ MD_ERROR_WIN_SAME_DRIVE,
++ MD_ERROR_WIN_DIR_NOT_ROOT,
++ MD_ERROR_WIN_DIR_NOT_EMPTY,
++ MD_ERROR_WIN_IS_SUBST_PATH,
++ MD_ERROR_WIN_IS_JOIN_PATH,
++ MD_ERROR_WIN_PATH_BUSY,
++ MD_ERROR_WIN_IS_SUBST_TARGET,
++ MD_ERROR_WIN_SYSTEM_TRACE,
++ MD_ERROR_WIN_INVALID_EVENT_COUNT,
++ MD_ERROR_WIN_TOO_MANY_MUXWAITERS,
++ MD_ERROR_WIN_INVALID_LIST_FORMAT,
++ MD_ERROR_WIN_LABEL_TOO_LONG,
++ MD_ERROR_WIN_TOO_MANY_TCBS,
++ MD_ERROR_WIN_SIGNAL_REFUSED,
++ MD_ERROR_WIN_DISCARDED,
++ MD_ERROR_WIN_NOT_LOCKED,
++ MD_ERROR_WIN_BAD_THREADID_ADDR,
++ MD_ERROR_WIN_BAD_ARGUMENTS,
++ MD_ERROR_WIN_BAD_PATHNAME,
++ MD_ERROR_WIN_SIGNAL_PENDING,
++ MD_ERROR_WIN_MAX_THRDS_REACHED,
++ MD_ERROR_WIN_LOCK_FAILED,
++ MD_ERROR_WIN_BUSY,
++ MD_ERROR_WIN_DEVICE_SUPPORT_IN_PROGRESS,
++ MD_ERROR_WIN_CANCEL_VIOLATION,
++ MD_ERROR_WIN_ATOMIC_LOCKS_NOT_SUPPORTED,
++ MD_ERROR_WIN_INVALID_SEGMENT_NUMBER,
++ MD_ERROR_WIN_INVALID_ORDINAL,
++ MD_ERROR_WIN_ALREADY_EXISTS,
++ MD_ERROR_WIN_INVALID_FLAG_NUMBER,
++ MD_ERROR_WIN_SEM_NOT_FOUND,
++ MD_ERROR_WIN_INVALID_STARTING_CODESEG,
++ MD_ERROR_WIN_INVALID_STACKSEG,
++ MD_ERROR_WIN_INVALID_MODULETYPE,
++ MD_ERROR_WIN_INVALID_EXE_SIGNATURE,
++ MD_ERROR_WIN_EXE_MARKED_INVALID,
++ MD_ERROR_WIN_BAD_EXE_FORMAT,
++ MD_ERROR_WIN_INVALID_MINALLOCSIZE,
++ MD_ERROR_WIN_DYNLINK_FROM_INVALID_RING,
++ MD_ERROR_WIN_IOPL_NOT_ENABLED,
++ MD_ERROR_WIN_INVALID_SEGDPL,
++ MD_ERROR_WIN_RING2SEG_MUST_BE_MOVABLE,
++ MD_ERROR_WIN_RELOC_CHAIN_XEEDS_SEGLIM,
++ MD_ERROR_WIN_INFLOOP_IN_RELOC_CHAIN,
++ MD_ERROR_WIN_ENVVAR_NOT_FOUND,
++ MD_ERROR_WIN_NO_SIGNAL_SENT,
++ MD_ERROR_WIN_FILENAME_EXCED_RANGE,
++ MD_ERROR_WIN_RING2_STACK_IN_USE,
++ MD_ERROR_WIN_META_EXPANSION_TOO_LONG,
++ MD_ERROR_WIN_INVALID_SIGNAL_NUMBER,
++ MD_ERROR_WIN_THREAD_1_INACTIVE,
++ MD_ERROR_WIN_LOCKED,
++ MD_ERROR_WIN_TOO_MANY_MODULES,
++ MD_ERROR_WIN_NESTING_NOT_ALLOWED,
++ MD_ERROR_WIN_EXE_MACHINE_TYPE_MISMATCH,
++ MD_ERROR_WIN_EXE_CANNOT_MODIFY_SIGNED_BINARY,
++ MD_ERROR_WIN_EXE_CANNOT_MODIFY_STRONG_SIGNED_BINARY,
++ MD_ERROR_WIN_FILE_CHECKED_OUT,
++ MD_ERROR_WIN_CHECKOUT_REQUIRED,
++ MD_ERROR_WIN_BAD_FILE_TYPE,
++ MD_ERROR_WIN_FILE_TOO_LARGE,
++ MD_ERROR_WIN_FORMS_AUTH_REQUIRED,
++ MD_ERROR_WIN_VIRUS_INFECTED,
++ MD_ERROR_WIN_VIRUS_DELETED,
++ MD_ERROR_WIN_PIPE_LOCAL,
++ MD_ERROR_WIN_BAD_PIPE,
++ MD_ERROR_WIN_PIPE_BUSY,
++ MD_ERROR_WIN_NO_DATA,
++ MD_ERROR_WIN_PIPE_NOT_CONNECTED,
++ MD_ERROR_WIN_MORE_DATA,
++ MD_ERROR_WIN_NO_WORK_DONE,
++ MD_ERROR_WIN_VC_DISCONNECTED,
++ MD_ERROR_WIN_INVALID_EA_NAME,
++ MD_ERROR_WIN_EA_LIST_INCONSISTENT,
++ MD_ERROR_WIN_NO_MORE_ITEMS,
++ MD_ERROR_WIN_CANNOT_COPY,
++ MD_ERROR_WIN_DIRECTORY,
++ MD_ERROR_WIN_EAS_DIDNT_FIT,
++ MD_ERROR_WIN_EA_FILE_CORRUPT,
++ MD_ERROR_WIN_EA_TABLE_FULL,
++ MD_ERROR_WIN_INVALID_EA_HANDLE,
++ MD_ERROR_WIN_EAS_NOT_SUPPORTED,
++ MD_ERROR_WIN_NOT_OWNER,
++ MD_ERROR_WIN_TOO_MANY_POSTS,
++ MD_ERROR_WIN_PARTIAL_COPY,
++ MD_ERROR_WIN_OPLOCK_NOT_GRANTED,
++ MD_ERROR_WIN_INVALID_OPLOCK_PROTOCOL,
++ MD_ERROR_WIN_DISK_TOO_FRAGMENTED,
++ MD_ERROR_WIN_DELETE_PENDING,
++ MD_ERROR_WIN_INCOMPATIBLE_WITH_GLOBAL_SHORT_NAME_REGISTRY_SETTING,
++ MD_ERROR_WIN_SHORT_NAMES_NOT_ENABLED_ON_VOLUME,
++ MD_ERROR_WIN_SECURITY_STREAM_IS_INCONSISTENT,
++ MD_ERROR_WIN_INVALID_LOCK_RANGE,
++ MD_ERROR_WIN_IMAGE_SUBSYSTEM_NOT_PRESENT,
++ MD_ERROR_WIN_NOTIFICATION_GUID_ALREADY_DEFINED,
++ MD_ERROR_WIN_INVALID_EXCEPTION_HANDLER,
++ MD_ERROR_WIN_DUPLICATE_PRIVILEGES,
++ MD_ERROR_WIN_NO_RANGES_PROCESSED,
++ MD_ERROR_WIN_NOT_ALLOWED_ON_SYSTEM_FILE,
++ MD_ERROR_WIN_DISK_RESOURCES_EXHAUSTED,
++ MD_ERROR_WIN_INVALID_TOKEN,
++ MD_ERROR_WIN_DEVICE_FEATURE_NOT_SUPPORTED,
++ MD_ERROR_WIN_MR_MID_NOT_FOUND,
++ MD_ERROR_WIN_SCOPE_NOT_FOUND,
++ MD_ERROR_WIN_UNDEFINED_SCOPE,
++ MD_ERROR_WIN_INVALID_CAP,
++ MD_ERROR_WIN_DEVICE_UNREACHABLE,
++ MD_ERROR_WIN_DEVICE_NO_RESOURCES,
++ MD_ERROR_WIN_DATA_CHECKSUM_ERROR,
++ MD_ERROR_WIN_INTERMIXED_KERNEL_EA_OPERATION,
++ MD_ERROR_WIN_FILE_LEVEL_TRIM_NOT_SUPPORTED,
++ MD_ERROR_WIN_OFFSET_ALIGNMENT_VIOLATION,
++ MD_ERROR_WIN_INVALID_FIELD_IN_PARAMETER_LIST,
++ MD_ERROR_WIN_OPERATION_IN_PROGRESS,
++ MD_ERROR_WIN_BAD_DEVICE_PATH,
++ MD_ERROR_WIN_TOO_MANY_DESCRIPTORS,
++ MD_ERROR_WIN_SCRUB_DATA_DISABLED,
++ MD_ERROR_WIN_NOT_REDUNDANT_STORAGE,
++ MD_ERROR_WIN_RESIDENT_FILE_NOT_SUPPORTED,
++ MD_ERROR_WIN_COMPRESSED_FILE_NOT_SUPPORTED,
++ MD_ERROR_WIN_DIRECTORY_NOT_SUPPORTED,
++ MD_ERROR_WIN_NOT_READ_FROM_COPY,
++ MD_ERROR_WIN_FT_WRITE_FAILURE,
++ MD_ERROR_WIN_FT_DI_SCAN_REQUIRED,
++ MD_ERROR_WIN_INVALID_KERNEL_INFO_VERSION,
++ MD_ERROR_WIN_INVALID_PEP_INFO_VERSION,
++ MD_ERROR_WIN_OBJECT_NOT_EXTERNALLY_BACKED,
++ MD_ERROR_WIN_EXTERNAL_BACKING_PROVIDER_UNKNOWN,
++ MD_ERROR_WIN_COMPRESSION_NOT_BENEFICIAL,
++ MD_ERROR_WIN_STORAGE_TOPOLOGY_ID_MISMATCH,
++ MD_ERROR_WIN_BLOCKED_BY_PARENTAL_CONTROLS,
++ MD_ERROR_WIN_BLOCK_TOO_MANY_REFERENCES,
++ MD_ERROR_WIN_MARKED_TO_DISALLOW_WRITES,
++ MD_ERROR_WIN_ENCLAVE_FAILURE,
++ MD_ERROR_WIN_FAIL_NOACTION_REBOOT,
++ MD_ERROR_WIN_FAIL_SHUTDOWN,
++ MD_ERROR_WIN_FAIL_RESTART,
++ MD_ERROR_WIN_MAX_SESSIONS_REACHED,
++ MD_ERROR_WIN_NETWORK_ACCESS_DENIED_EDP,
++ MD_ERROR_WIN_DEVICE_HINT_NAME_BUFFER_TOO_SMALL,
++ MD_ERROR_WIN_EDP_POLICY_DENIES_OPERATION,
++ MD_ERROR_WIN_EDP_DPL_POLICY_CANT_BE_SATISFIED,
++ MD_ERROR_WIN_CLOUD_FILE_SYNC_ROOT_METADATA_CORRUPT,
++ MD_ERROR_WIN_DEVICE_IN_MAINTENANCE,
++ MD_ERROR_WIN_NOT_SUPPORTED_ON_DAX,
++ MD_ERROR_WIN_DAX_MAPPING_EXISTS,
++ MD_ERROR_WIN_CLOUD_FILE_PROVIDER_NOT_RUNNING,
++ MD_ERROR_WIN_CLOUD_FILE_METADATA_CORRUPT,
++ MD_ERROR_WIN_CLOUD_FILE_METADATA_TOO_LARGE,
++ MD_ERROR_WIN_CLOUD_FILE_PROPERTY_BLOB_TOO_LARGE,
++ MD_ERROR_WIN_CLOUD_FILE_PROPERTY_BLOB_CHECKSUM_MISMATCH,
++ MD_ERROR_WIN_CHILD_PROCESS_BLOCKED,
++ MD_ERROR_WIN_STORAGE_LOST_DATA_PERSISTENCE,
++ MD_ERROR_WIN_FILE_SYSTEM_VIRTUALIZATION_UNAVAILABLE,
++ MD_ERROR_WIN_FILE_SYSTEM_VIRTUALIZATION_METADATA_CORRUPT,
++ MD_ERROR_WIN_FILE_SYSTEM_VIRTUALIZATION_BUSY,
++ MD_ERROR_WIN_FILE_SYSTEM_VIRTUALIZATION_PROVIDER_UNKNOWN,
++ MD_ERROR_WIN_GDI_HANDLE_LEAK,
++ MD_ERROR_WIN_CLOUD_FILE_TOO_MANY_PROPERTY_BLOBS,
++ MD_ERROR_WIN_CLOUD_FILE_PROPERTY_VERSION_NOT_SUPPORTED,
++ MD_ERROR_WIN_NOT_A_CLOUD_FILE,
++ MD_ERROR_WIN_CLOUD_FILE_NOT_IN_SYNC,
++ MD_ERROR_WIN_CLOUD_FILE_ALREADY_CONNECTED,
++ MD_ERROR_WIN_CLOUD_FILE_NOT_SUPPORTED,
++ MD_ERROR_WIN_CLOUD_FILE_INVALID_REQUEST,
++ MD_ERROR_WIN_CLOUD_FILE_READ_ONLY_VOLUME,
++ MD_ERROR_WIN_CLOUD_FILE_CONNECTED_PROVIDER_ONLY,
++ MD_ERROR_WIN_CLOUD_FILE_VALIDATION_FAILED,
++ MD_ERROR_WIN_SMB1_NOT_AVAILABLE,
++ MD_ERROR_WIN_FILE_SYSTEM_VIRTUALIZATION_INVALID_OPERATION,
++ MD_ERROR_WIN_CLOUD_FILE_AUTHENTICATION_FAILED,
++ MD_ERROR_WIN_CLOUD_FILE_INSUFFICIENT_RESOURCES,
++ MD_ERROR_WIN_CLOUD_FILE_NETWORK_UNAVAILABLE,
++ MD_ERROR_WIN_CLOUD_FILE_UNSUCCESSFUL,
++ MD_ERROR_WIN_CLOUD_FILE_NOT_UNDER_SYNC_ROOT,
++ MD_ERROR_WIN_CLOUD_FILE_IN_USE,
++ MD_ERROR_WIN_CLOUD_FILE_PINNED,
++ MD_ERROR_WIN_CLOUD_FILE_REQUEST_ABORTED,
++ MD_ERROR_WIN_CLOUD_FILE_PROPERTY_CORRUPT,
++ MD_ERROR_WIN_CLOUD_FILE_ACCESS_DENIED,
++ MD_ERROR_WIN_CLOUD_FILE_INCOMPATIBLE_HARDLINKS,
++ MD_ERROR_WIN_CLOUD_FILE_PROPERTY_LOCK_CONFLICT,
++ MD_ERROR_WIN_CLOUD_FILE_REQUEST_CANCELED,
++ MD_ERROR_WIN_EXTERNAL_SYSKEY_NOT_SUPPORTED,
++ MD_ERROR_WIN_THREAD_MODE_ALREADY_BACKGROUND,
++ MD_ERROR_WIN_THREAD_MODE_NOT_BACKGROUND,
++ MD_ERROR_WIN_PROCESS_MODE_ALREADY_BACKGROUND,
++ MD_ERROR_WIN_PROCESS_MODE_NOT_BACKGROUND,
++ MD_ERROR_WIN_CLOUD_FILE_PROVIDER_TERMINATED,
++ MD_ERROR_WIN_NOT_A_CLOUD_SYNC_ROOT,
++ MD_ERROR_WIN_FILE_PROTECTED_UNDER_DPL,
++ MD_ERROR_WIN_VOLUME_NOT_CLUSTER_ALIGNED,
++ MD_ERROR_WIN_NO_PHYSICALLY_ALIGNED_FREE_SPACE_FOUND,
++ MD_ERROR_WIN_APPX_FILE_NOT_ENCRYPTED,
++ MD_ERROR_WIN_RWRAW_ENCRYPTED_FILE_NOT_ENCRYPTED,
++ MD_ERROR_WIN_RWRAW_ENCRYPTED_INVALID_EDATAINFO_FILEOFFSET,
++ MD_ERROR_WIN_RWRAW_ENCRYPTED_INVALID_EDATAINFO_FILERANGE,
++ MD_ERROR_WIN_RWRAW_ENCRYPTED_INVALID_EDATAINFO_PARAMETER,
++ MD_ERROR_WIN_LINUX_SUBSYSTEM_NOT_PRESENT,
++ MD_ERROR_WIN_FT_READ_FAILURE,
++ MD_ERROR_WIN_STORAGE_RESERVE_ID_INVALID,
++ MD_ERROR_WIN_STORAGE_RESERVE_DOES_NOT_EXIST,
++ MD_ERROR_WIN_STORAGE_RESERVE_ALREADY_EXISTS,
++ MD_ERROR_WIN_STORAGE_RESERVE_NOT_EMPTY,
++ MD_ERROR_WIN_NOT_A_DAX_VOLUME,
++ MD_ERROR_WIN_NOT_DAX_MAPPABLE,
++ MD_ERROR_WIN_TIME_SENSITIVE_THREAD,
++ MD_ERROR_WIN_DPL_NOT_SUPPORTED_FOR_USER,
++ MD_ERROR_WIN_CASE_DIFFERING_NAMES_IN_DIR,
++ MD_ERROR_WIN_FILE_NOT_SUPPORTED,
++ MD_ERROR_WIN_CLOUD_FILE_REQUEST_TIMEOUT,
++ MD_ERROR_WIN_NO_TASK_QUEUE,
++ MD_ERROR_WIN_SRC_SRV_DLL_LOAD_FAILED,
++ MD_ERROR_WIN_NOT_SUPPORTED_WITH_BTT,
++ MD_ERROR_WIN_ENCRYPTION_DISABLED,
++ MD_ERROR_WIN_ENCRYPTING_METADATA_DISALLOWED,
++ MD_ERROR_WIN_CANT_CLEAR_ENCRYPTION_FLAG,
++ MD_ERROR_WIN_NO_SUCH_DEVICE,
++ MD_ERROR_WIN_CLOUD_FILE_DEHYDRATION_DISALLOWED,
++ MD_ERROR_WIN_FILE_SNAP_IN_PROGRESS,
++ MD_ERROR_WIN_FILE_SNAP_USER_SECTION_NOT_SUPPORTED,
++ MD_ERROR_WIN_FILE_SNAP_MODIFY_NOT_SUPPORTED,
++ MD_ERROR_WIN_FILE_SNAP_IO_NOT_COORDINATED,
++ MD_ERROR_WIN_FILE_SNAP_UNEXPECTED_ERROR,
++ MD_ERROR_WIN_FILE_SNAP_INVALID_PARAMETER,
++ MD_ERROR_WIN_UNSATISFIED_DEPENDENCIES,
++ MD_ERROR_WIN_CASE_SENSITIVE_PATH,
++ MD_ERROR_WIN_UNEXPECTED_NTCACHEMANAGER_ERROR,
++ MD_ERROR_WIN_LINUX_SUBSYSTEM_UPDATE_REQUIRED,
++ MD_ERROR_WIN_DLP_POLICY_WARNS_AGAINST_OPERATION,
++ MD_ERROR_WIN_DLP_POLICY_DENIES_OPERATION,
++ MD_ERROR_WIN_DLP_POLICY_SILENTLY_FAIL,
++ MD_ERROR_WIN_CAPAUTHZ_NOT_DEVUNLOCKED,
++ MD_ERROR_WIN_CAPAUTHZ_CHANGE_TYPE,
++ MD_ERROR_WIN_CAPAUTHZ_NOT_PROVISIONED,
++ MD_ERROR_WIN_CAPAUTHZ_NOT_AUTHORIZED,
++ MD_ERROR_WIN_CAPAUTHZ_NO_POLICY,
++ MD_ERROR_WIN_CAPAUTHZ_DB_CORRUPTED,
++ MD_ERROR_WIN_CAPAUTHZ_SCCD_INVALID_CATALOG,
++ MD_ERROR_WIN_CAPAUTHZ_SCCD_NO_AUTH_ENTITY,
++ MD_ERROR_WIN_CAPAUTHZ_SCCD_PARSE_ERROR,
++ MD_ERROR_WIN_CAPAUTHZ_SCCD_DEV_MODE_REQUIRED,
++ MD_ERROR_WIN_CAPAUTHZ_SCCD_NO_CAPABILITY_MATCH,
++ MD_ERROR_WIN_CIMFS_IMAGE_CORRUPT,
++ MD_ERROR_WIN_PNP_QUERY_REMOVE_DEVICE_TIMEOUT,
++ MD_ERROR_WIN_PNP_QUERY_REMOVE_RELATED_DEVICE_TIMEOUT,
++ MD_ERROR_WIN_PNP_QUERY_REMOVE_UNRELATED_DEVICE_TIMEOUT,
++ MD_ERROR_WIN_DEVICE_HARDWARE_ERROR,
++ MD_ERROR_WIN_INVALID_ADDRESS,
++ MD_ERROR_WIN_HAS_SYSTEM_CRITICAL_FILES,
++ MD_ERROR_WIN_USER_PROFILE_LOAD,
++ MD_ERROR_WIN_ARITHMETIC_OVERFLOW,
++ MD_ERROR_WIN_PIPE_CONNECTED,
++ MD_ERROR_WIN_PIPE_LISTENING,
++ MD_ERROR_WIN_VERIFIER_STOP,
++ MD_ERROR_WIN_ABIOS_ERROR,
++ MD_ERROR_WIN_WX86_WARNING,
++ MD_ERROR_WIN_WX86_ERROR,
++ MD_ERROR_WIN_TIMER_NOT_CANCELED,
++ MD_ERROR_WIN_UNWIND,
++ MD_ERROR_WIN_BAD_STACK,
++ MD_ERROR_WIN_INVALID_UNWIND_TARGET,
++ MD_ERROR_WIN_INVALID_PORT_ATTRIBUTES,
++ MD_ERROR_WIN_PORT_MESSAGE_TOO_LONG,
++ MD_ERROR_WIN_INVALID_QUOTA_LOWER,
++ MD_ERROR_WIN_DEVICE_ALREADY_ATTACHED,
++ MD_ERROR_WIN_INSTRUCTION_MISALIGNMENT,
++ MD_ERROR_WIN_PROFILING_NOT_STARTED,
++ MD_ERROR_WIN_PROFILING_NOT_STOPPED,
++ MD_ERROR_WIN_COULD_NOT_INTERPRET,
++ MD_ERROR_WIN_PROFILING_AT_LIMIT,
++ MD_ERROR_WIN_CANT_WAIT,
++ MD_ERROR_WIN_CANT_TERMINATE_SELF,
++ MD_ERROR_WIN_UNEXPECTED_MM_CREATE_ERR,
++ MD_ERROR_WIN_UNEXPECTED_MM_MAP_ERROR,
++ MD_ERROR_WIN_UNEXPECTED_MM_EXTEND_ERR,
++ MD_ERROR_WIN_BAD_FUNCTION_TABLE,
++ MD_ERROR_WIN_NO_GUID_TRANSLATION,
++ MD_ERROR_WIN_INVALID_LDT_SIZE,
++ MD_ERROR_WIN_INVALID_LDT_OFFSET,
++ MD_ERROR_WIN_INVALID_LDT_DESCRIPTOR,
++ MD_ERROR_WIN_TOO_MANY_THREADS,
++ MD_ERROR_WIN_THREAD_NOT_IN_PROCESS,
++ MD_ERROR_WIN_PAGEFILE_QUOTA_EXCEEDED,
++ MD_ERROR_WIN_LOGON_SERVER_CONFLICT,
++ MD_ERROR_WIN_SYNCHRONIZATION_REQUIRED,
++ MD_ERROR_WIN_NET_OPEN_FAILED,
++ MD_ERROR_WIN_IO_PRIVILEGE_FAILED,
++ MD_ERROR_WIN_CONTROL_C_EXIT,
++ MD_ERROR_WIN_MISSING_SYSTEMFILE,
++ MD_ERROR_WIN_UNHANDLED_EXCEPTION,
++ MD_ERROR_WIN_APP_INIT_FAILURE,
++ MD_ERROR_WIN_PAGEFILE_CREATE_FAILED,
++ MD_ERROR_WIN_INVALID_IMAGE_HASH,
++ MD_ERROR_WIN_NO_PAGEFILE,
++ MD_ERROR_WIN_ILLEGAL_FLOAT_CONTEXT,
++ MD_ERROR_WIN_NO_EVENT_PAIR,
++ MD_ERROR_WIN_DOMAIN_CTRLR_CONFIG_ERROR,
++ MD_ERROR_WIN_ILLEGAL_CHARACTER,
++ MD_ERROR_WIN_UNDEFINED_CHARACTER,
++ MD_ERROR_WIN_FLOPPY_VOLUME,
++ MD_ERROR_WIN_BIOS_FAILED_TO_CONNECT_INTERRUPT,
++ MD_ERROR_WIN_BACKUP_CONTROLLER,
++ MD_ERROR_WIN_MUTANT_LIMIT_EXCEEDED,
++ MD_ERROR_WIN_FS_DRIVER_REQUIRED,
++ MD_ERROR_WIN_CANNOT_LOAD_REGISTRY_FILE,
++ MD_ERROR_WIN_DEBUG_ATTACH_FAILED,
++ MD_ERROR_WIN_SYSTEM_PROCESS_TERMINATED,
++ MD_ERROR_WIN_DATA_NOT_ACCEPTED,
++ MD_ERROR_WIN_VDM_HARD_ERROR,
++ MD_ERROR_WIN_DRIVER_CANCEL_TIMEOUT,
++ MD_ERROR_WIN_REPLY_MESSAGE_MISMATCH,
++ MD_ERROR_WIN_LOST_WRITEBEHIND_DATA,
++ MD_ERROR_WIN_CLIENT_SERVER_PARAMETERS_INVALID,
++ MD_ERROR_WIN_NOT_TINY_STREAM,
++ MD_ERROR_WIN_STACK_OVERFLOW_READ,
++ MD_ERROR_WIN_CONVERT_TO_LARGE,
++ MD_ERROR_WIN_FOUND_OUT_OF_SCOPE,
++ MD_ERROR_WIN_ALLOCATE_BUCKET,
++ MD_ERROR_WIN_MARSHALL_OVERFLOW,
++ MD_ERROR_WIN_INVALID_VARIANT,
++ MD_ERROR_WIN_BAD_COMPRESSION_BUFFER,
++ MD_ERROR_WIN_AUDIT_FAILED,
++ MD_ERROR_WIN_TIMER_RESOLUTION_NOT_SET,
++ MD_ERROR_WIN_INSUFFICIENT_LOGON_INFO,
++ MD_ERROR_WIN_BAD_DLL_ENTRYPOINT,
++ MD_ERROR_WIN_BAD_SERVICE_ENTRYPOINT,
++ MD_ERROR_WIN_IP_ADDRESS_CONFLICT1,
++ MD_ERROR_WIN_IP_ADDRESS_CONFLICT2,
++ MD_ERROR_WIN_REGISTRY_QUOTA_LIMIT,
++ MD_ERROR_WIN_NO_CALLBACK_ACTIVE,
++ MD_ERROR_WIN_PWD_TOO_SHORT,
++ MD_ERROR_WIN_PWD_TOO_RECENT,
++ MD_ERROR_WIN_PWD_HISTORY_CONFLICT,
++ MD_ERROR_WIN_UNSUPPORTED_COMPRESSION,
++ MD_ERROR_WIN_INVALID_HW_PROFILE,
++ MD_ERROR_WIN_INVALID_PLUGPLAY_DEVICE_PATH,
++ MD_ERROR_WIN_QUOTA_LIST_INCONSISTENT,
++ MD_ERROR_WIN_EVALUATION_EXPIRATION,
++ MD_ERROR_WIN_ILLEGAL_DLL_RELOCATION,
++ MD_ERROR_WIN_DLL_INIT_FAILED_LOGOFF,
++ MD_ERROR_WIN_VALIDATE_CONTINUE,
++ MD_ERROR_WIN_NO_MORE_MATCHES,
++ MD_ERROR_WIN_RANGE_LIST_CONFLICT,
++ MD_ERROR_WIN_SERVER_SID_MISMATCH,
++ MD_ERROR_WIN_CANT_ENABLE_DENY_ONLY,
++ MD_ERROR_WIN_FLOAT_MULTIPLE_FAULTS,
++ MD_ERROR_WIN_FLOAT_MULTIPLE_TRAPS,
++ MD_ERROR_WIN_NOINTERFACE,
++ MD_ERROR_WIN_DRIVER_FAILED_SLEEP,
++ MD_ERROR_WIN_CORRUPT_SYSTEM_FILE,
++ MD_ERROR_WIN_COMMITMENT_MINIMUM,
++ MD_ERROR_WIN_PNP_RESTART_ENUMERATION,
++ MD_ERROR_WIN_SYSTEM_IMAGE_BAD_SIGNATURE,
++ MD_ERROR_WIN_PNP_REBOOT_REQUIRED,
++ MD_ERROR_WIN_INSUFFICIENT_POWER,
++ MD_ERROR_WIN_MULTIPLE_FAULT_VIOLATION,
++ MD_ERROR_WIN_SYSTEM_SHUTDOWN,
++ MD_ERROR_WIN_PORT_NOT_SET,
++ MD_ERROR_WIN_DS_VERSION_CHECK_FAILURE,
++ MD_ERROR_WIN_RANGE_NOT_FOUND,
++ MD_ERROR_WIN_NOT_SAFE_MODE_DRIVER,
++ MD_ERROR_WIN_FAILED_DRIVER_ENTRY,
++ MD_ERROR_WIN_DEVICE_ENUMERATION_ERROR,
++ MD_ERROR_WIN_MOUNT_POINT_NOT_RESOLVED,
++ MD_ERROR_WIN_INVALID_DEVICE_OBJECT_PARAMETER,
++ MD_ERROR_WIN_MCA_OCCURED,
++ MD_ERROR_WIN_DRIVER_DATABASE_ERROR,
++ MD_ERROR_WIN_SYSTEM_HIVE_TOO_LARGE,
++ MD_ERROR_WIN_DRIVER_FAILED_PRIOR_UNLOAD,
++ MD_ERROR_WIN_VOLSNAP_PREPARE_HIBERNATE,
++ MD_ERROR_WIN_HIBERNATION_FAILURE,
++ MD_ERROR_WIN_PWD_TOO_LONG,
++ MD_ERROR_WIN_FILE_SYSTEM_LIMITATION,
++ MD_ERROR_WIN_ASSERTION_FAILURE,
++ MD_ERROR_WIN_ACPI_ERROR,
++ MD_ERROR_WIN_WOW_ASSERTION,
++ MD_ERROR_WIN_PNP_BAD_MPS_TABLE,
++ MD_ERROR_WIN_PNP_TRANSLATION_FAILED,
++ MD_ERROR_WIN_PNP_IRQ_TRANSLATION_FAILED,
++ MD_ERROR_WIN_PNP_INVALID_ID,
++ MD_ERROR_WIN_WAKE_SYSTEM_DEBUGGER,
++ MD_ERROR_WIN_HANDLES_CLOSED,
++ MD_ERROR_WIN_EXTRANEOUS_INFORMATION,
++ MD_ERROR_WIN_RXACT_COMMIT_NECESSARY,
++ MD_ERROR_WIN_MEDIA_CHECK,
++ MD_ERROR_WIN_GUID_SUBSTITUTION_MADE,
++ MD_ERROR_WIN_STOPPED_ON_SYMLINK,
++ MD_ERROR_WIN_LONGJUMP,
++ MD_ERROR_WIN_PLUGPLAY_QUERY_VETOED,
++ MD_ERROR_WIN_UNWIND_CONSOLIDATE,
++ MD_ERROR_WIN_REGISTRY_HIVE_RECOVERED,
++ MD_ERROR_WIN_DLL_MIGHT_BE_INSECURE,
++ MD_ERROR_WIN_DLL_MIGHT_BE_INCOMPATIBLE,
++ MD_ERROR_WIN_DBG_EXCEPTION_NOT_HANDLED,
++ MD_ERROR_WIN_DBG_REPLY_LATER,
++ MD_ERROR_WIN_DBG_UNABLE_TO_PROVIDE_HANDLE,
++ MD_ERROR_WIN_DBG_TERMINATE_THREAD,
++ MD_ERROR_WIN_DBG_TERMINATE_PROCESS,
++ MD_ERROR_WIN_DBG_CONTROL_C,
++ MD_ERROR_WIN_DBG_PRINTEXCEPTION_C,
++ MD_ERROR_WIN_DBG_RIPEXCEPTION,
++ MD_ERROR_WIN_DBG_CONTROL_BREAK,
++ MD_ERROR_WIN_DBG_COMMAND_EXCEPTION,
++ MD_ERROR_WIN_OBJECT_NAME_EXISTS,
++ MD_ERROR_WIN_THREAD_WAS_SUSPENDED,
++ MD_ERROR_WIN_IMAGE_NOT_AT_BASE,
++ MD_ERROR_WIN_RXACT_STATE_CREATED,
++ MD_ERROR_WIN_SEGMENT_NOTIFICATION,
++ MD_ERROR_WIN_BAD_CURRENT_DIRECTORY,
++ MD_ERROR_WIN_FT_READ_RECOVERY_FROM_BACKUP,
++ MD_ERROR_WIN_FT_WRITE_RECOVERY,
++ MD_ERROR_WIN_IMAGE_MACHINE_TYPE_MISMATCH,
++ MD_ERROR_WIN_RECEIVE_PARTIAL,
++ MD_ERROR_WIN_RECEIVE_EXPEDITED,
++ MD_ERROR_WIN_RECEIVE_PARTIAL_EXPEDITED,
++ MD_ERROR_WIN_EVENT_DONE,
++ MD_ERROR_WIN_EVENT_PENDING,
++ MD_ERROR_WIN_CHECKING_FILE_SYSTEM,
++ MD_ERROR_WIN_FATAL_APP_EXIT,
++ MD_ERROR_WIN_PREDEFINED_HANDLE,
++ MD_ERROR_WIN_WAS_UNLOCKED,
++ MD_ERROR_WIN_SERVICE_NOTIFICATION,
++ MD_ERROR_WIN_WAS_LOCKED,
++ MD_ERROR_WIN_LOG_HARD_ERROR,
++ MD_ERROR_WIN_ALREADY_WIN32,
++ MD_ERROR_WIN_IMAGE_MACHINE_TYPE_MISMATCH_EXE,
++ MD_ERROR_WIN_NO_YIELD_PERFORMED,
++ MD_ERROR_WIN_TIMER_RESUME_IGNORED,
++ MD_ERROR_WIN_ARBITRATION_UNHANDLED,
++ MD_ERROR_WIN_CARDBUS_NOT_SUPPORTED,
++ MD_ERROR_WIN_MP_PROCESSOR_MISMATCH,
++ MD_ERROR_WIN_HIBERNATED,
++ MD_ERROR_WIN_RESUME_HIBERNATION,
++ MD_ERROR_WIN_FIRMWARE_UPDATED,
++ MD_ERROR_WIN_DRIVERS_LEAKING_LOCKED_PAGES,
++ MD_ERROR_WIN_WAKE_SYSTEM,
++ MD_ERROR_WIN_WAIT_1,
++ MD_ERROR_WIN_WAIT_2,
++ MD_ERROR_WIN_WAIT_3,
++ MD_ERROR_WIN_WAIT_63,
++ MD_ERROR_WIN_ABANDONED_WAIT_0,
++ MD_ERROR_WIN_ABANDONED_WAIT_63,
++ MD_ERROR_WIN_USER_APC,
++ MD_ERROR_WIN_KERNEL_APC,
++ MD_ERROR_WIN_ALERTED,
++ MD_ERROR_WIN_ELEVATION_REQUIRED,
++ MD_ERROR_WIN_REPARSE,
++ MD_ERROR_WIN_OPLOCK_BREAK_IN_PROGRESS,
++ MD_ERROR_WIN_VOLUME_MOUNTED,
++ MD_ERROR_WIN_RXACT_COMMITTED,
++ MD_ERROR_WIN_NOTIFY_CLEANUP,
++ MD_ERROR_WIN_PRIMARY_TRANSPORT_CONNECT_FAILED,
++ MD_ERROR_WIN_PAGE_FAULT_TRANSITION,
++ MD_ERROR_WIN_PAGE_FAULT_DEMAND_ZERO,
++ MD_ERROR_WIN_PAGE_FAULT_COPY_ON_WRITE,
++ MD_ERROR_WIN_PAGE_FAULT_GUARD_PAGE,
++ MD_ERROR_WIN_PAGE_FAULT_PAGING_FILE,
++ MD_ERROR_WIN_CACHE_PAGE_LOCKED,
++ MD_ERROR_WIN_CRASH_DUMP,
++ MD_ERROR_WIN_BUFFER_ALL_ZEROS,
++ MD_ERROR_WIN_REPARSE_OBJECT,
++ MD_ERROR_WIN_RESOURCE_REQUIREMENTS_CHANGED,
++ MD_ERROR_WIN_TRANSLATION_COMPLETE,
++ MD_ERROR_WIN_NOTHING_TO_TERMINATE,
++ MD_ERROR_WIN_PROCESS_NOT_IN_JOB,
++ MD_ERROR_WIN_PROCESS_IN_JOB,
++ MD_ERROR_WIN_VOLSNAP_HIBERNATE_READY,
++ MD_ERROR_WIN_FSFILTER_OP_COMPLETED_SUCCESSFULLY,
++ MD_ERROR_WIN_INTERRUPT_VECTOR_ALREADY_CONNECTED,
++ MD_ERROR_WIN_INTERRUPT_STILL_CONNECTED,
++ MD_ERROR_WIN_WAIT_FOR_OPLOCK,
++ MD_ERROR_WIN_DBG_EXCEPTION_HANDLED,
++ MD_ERROR_WIN_DBG_CONTINUE,
++ MD_ERROR_WIN_CALLBACK_POP_STACK,
++ MD_ERROR_WIN_COMPRESSION_DISABLED,
++ MD_ERROR_WIN_CANTFETCHBACKWARDS,
++ MD_ERROR_WIN_CANTSCROLLBACKWARDS,
++ MD_ERROR_WIN_ROWSNOTRELEASED,
++ MD_ERROR_WIN_BAD_ACCESSOR_FLAGS,
++ MD_ERROR_WIN_ERRORS_ENCOUNTERED,
++ MD_ERROR_WIN_NOT_CAPABLE,
++ MD_ERROR_WIN_REQUEST_OUT_OF_SEQUENCE,
++ MD_ERROR_WIN_VERSION_PARSE_ERROR,
++ MD_ERROR_WIN_BADSTARTPOSITION,
++ MD_ERROR_WIN_MEMORY_HARDWARE,
++ MD_ERROR_WIN_DISK_REPAIR_DISABLED,
++ MD_ERROR_WIN_INSUFFICIENT_RESOURCE_FOR_SPECIFIED_SHARED_SECTION_SIZE,
++ MD_ERROR_WIN_SYSTEM_POWERSTATE_TRANSITION,
++ MD_ERROR_WIN_SYSTEM_POWERSTATE_COMPLEX_TRANSITION,
++ MD_ERROR_WIN_MCA_EXCEPTION,
++ MD_ERROR_WIN_ACCESS_AUDIT_BY_POLICY,
++ MD_ERROR_WIN_ACCESS_DISABLED_NO_SAFER_UI_BY_POLICY,
++ MD_ERROR_WIN_ABANDON_HIBERFILE,
++ MD_ERROR_WIN_LOST_WRITEBEHIND_DATA_NETWORK_DISCONNECTED,
++ MD_ERROR_WIN_LOST_WRITEBEHIND_DATA_NETWORK_SERVER_ERROR,
++ MD_ERROR_WIN_LOST_WRITEBEHIND_DATA_LOCAL_DISK_ERROR,
++ MD_ERROR_WIN_BAD_MCFG_TABLE,
++ MD_ERROR_WIN_DISK_REPAIR_REDIRECTED,
++ MD_ERROR_WIN_DISK_REPAIR_UNSUCCESSFUL,
++ MD_ERROR_WIN_CORRUPT_LOG_OVERFULL,
++ MD_ERROR_WIN_CORRUPT_LOG_CORRUPTED,
++ MD_ERROR_WIN_CORRUPT_LOG_UNAVAILABLE,
++ MD_ERROR_WIN_CORRUPT_LOG_DELETED_FULL,
++ MD_ERROR_WIN_CORRUPT_LOG_CLEARED,
++ MD_ERROR_WIN_ORPHAN_NAME_EXHAUSTED,
++ MD_ERROR_WIN_OPLOCK_SWITCHED_TO_NEW_HANDLE,
++ MD_ERROR_WIN_CANNOT_GRANT_REQUESTED_OPLOCK,
++ MD_ERROR_WIN_CANNOT_BREAK_OPLOCK,
++ MD_ERROR_WIN_OPLOCK_HANDLE_CLOSED,
++ MD_ERROR_WIN_NO_ACE_CONDITION,
++ MD_ERROR_WIN_INVALID_ACE_CONDITION,
++ MD_ERROR_WIN_FILE_HANDLE_REVOKED,
++ MD_ERROR_WIN_IMAGE_AT_DIFFERENT_BASE,
++ MD_ERROR_WIN_ENCRYPTED_IO_NOT_POSSIBLE,
++ MD_ERROR_WIN_FILE_METADATA_OPTIMIZATION_IN_PROGRESS,
++ MD_ERROR_WIN_QUOTA_ACTIVITY,
++ MD_ERROR_WIN_HANDLE_REVOKED,
++ MD_ERROR_WIN_CALLBACK_INVOKE_INLINE,
++ MD_ERROR_WIN_CPU_SET_INVALID,
++ MD_ERROR_WIN_ENCLAVE_NOT_TERMINATED,
++ MD_ERROR_WIN_ENCLAVE_VIOLATION,
++ MD_ERROR_WIN_EA_ACCESS_DENIED,
++ MD_ERROR_WIN_OPERATION_ABORTED,
++ MD_ERROR_WIN_IO_INCOMPLETE,
++ MD_ERROR_WIN_IO_PENDING,
++ MD_ERROR_WIN_NOACCESS,
++ MD_ERROR_WIN_SWAPERROR,
++ MD_ERROR_WIN_STACK_OVERFLOW,
++ MD_ERROR_WIN_INVALID_MESSAGE,
++ MD_ERROR_WIN_CAN_NOT_COMPLETE,
++ MD_ERROR_WIN_INVALID_FLAGS,
++ MD_ERROR_WIN_UNRECOGNIZED_VOLUME,
++ MD_ERROR_WIN_FILE_INVALID,
++ MD_ERROR_WIN_FULLSCREEN_MODE,
++ MD_ERROR_WIN_NO_TOKEN,
++ MD_ERROR_WIN_BADDB,
++ MD_ERROR_WIN_BADKEY,
++ MD_ERROR_WIN_CANTOPEN,
++ MD_ERROR_WIN_CANTREAD,
++ MD_ERROR_WIN_CANTWRITE,
++ MD_ERROR_WIN_REGISTRY_RECOVERED,
++ MD_ERROR_WIN_REGISTRY_CORRUPT,
++ MD_ERROR_WIN_REGISTRY_IO_FAILED,
++ MD_ERROR_WIN_NOT_REGISTRY_FILE,
++ MD_ERROR_WIN_KEY_DELETED,
++ MD_ERROR_WIN_NO_LOG_SPACE,
++ MD_ERROR_WIN_KEY_HAS_CHILDREN,
++ MD_ERROR_WIN_CHILD_MUST_BE_VOLATILE,
++ MD_ERROR_WIN_NOTIFY_ENUM_DIR,
++ MD_ERROR_WIN_DEPENDENT_SERVICES_RUNNING,
++ MD_ERROR_WIN_INVALID_SERVICE_CONTROL,
++ MD_ERROR_WIN_SERVICE_REQUEST_TIMEOUT,
++ MD_ERROR_WIN_SERVICE_NO_THREAD,
++ MD_ERROR_WIN_SERVICE_DATABASE_LOCKED,
++ MD_ERROR_WIN_SERVICE_ALREADY_RUNNING,
++ MD_ERROR_WIN_INVALID_SERVICE_ACCOUNT,
++ MD_ERROR_WIN_SERVICE_DISABLED,
++ MD_ERROR_WIN_CIRCULAR_DEPENDENCY,
++ MD_ERROR_WIN_SERVICE_DOES_NOT_EXIST,
++ MD_ERROR_WIN_SERVICE_CANNOT_ACCEPT_CTRL,
++ MD_ERROR_WIN_SERVICE_NOT_ACTIVE,
++ MD_ERROR_WIN_FAILED_SERVICE_CONTROLLER_CONNECT,
++ MD_ERROR_WIN_EXCEPTION_IN_SERVICE,
++ MD_ERROR_WIN_DATABASE_DOES_NOT_EXIST,
++ MD_ERROR_WIN_SERVICE_SPECIFIC_ERROR,
++ MD_ERROR_WIN_PROCESS_ABORTED,
++ MD_ERROR_WIN_SERVICE_DEPENDENCY_FAIL,
++ MD_ERROR_WIN_SERVICE_LOGON_FAILED,
++ MD_ERROR_WIN_SERVICE_START_HANG,
++ MD_ERROR_WIN_INVALID_SERVICE_LOCK,
++ MD_ERROR_WIN_SERVICE_MARKED_FOR_DELETE,
++ MD_ERROR_WIN_SERVICE_EXISTS,
++ MD_ERROR_WIN_ALREADY_RUNNING_LKG,
++ MD_ERROR_WIN_SERVICE_DEPENDENCY_DELETED,
++ MD_ERROR_WIN_BOOT_ALREADY_ACCEPTED,
++ MD_ERROR_WIN_SERVICE_NEVER_STARTED,
++ MD_ERROR_WIN_DUPLICATE_SERVICE_NAME,
++ MD_ERROR_WIN_DIFFERENT_SERVICE_ACCOUNT,
++ MD_ERROR_WIN_CANNOT_DETECT_DRIVER_FAILURE,
++ MD_ERROR_WIN_CANNOT_DETECT_PROCESS_ABORT,
++ MD_ERROR_WIN_NO_RECOVERY_PROGRAM,
++ MD_ERROR_WIN_SERVICE_NOT_IN_EXE,
++ MD_ERROR_WIN_NOT_SAFEBOOT_SERVICE,
++ MD_ERROR_WIN_END_OF_MEDIA,
++ MD_ERROR_WIN_FILEMARK_DETECTED,
++ MD_ERROR_WIN_BEGINNING_OF_MEDIA,
++ MD_ERROR_WIN_SETMARK_DETECTED,
++ MD_ERROR_WIN_NO_DATA_DETECTED,
++ MD_ERROR_WIN_PARTITION_FAILURE,
++ MD_ERROR_WIN_INVALID_BLOCK_LENGTH,
++ MD_ERROR_WIN_DEVICE_NOT_PARTITIONED,
++ MD_ERROR_WIN_UNABLE_TO_LOCK_MEDIA,
++ MD_ERROR_WIN_UNABLE_TO_UNLOAD_MEDIA,
++ MD_ERROR_WIN_MEDIA_CHANGED,
++ MD_ERROR_WIN_BUS_RESET,
++ MD_ERROR_WIN_NO_MEDIA_IN_DRIVE,
++ MD_ERROR_WIN_NO_UNICODE_TRANSLATION,
++ MD_ERROR_WIN_DLL_INIT_FAILED,
++ MD_ERROR_WIN_SHUTDOWN_IN_PROGRESS,
++ MD_ERROR_WIN_NO_SHUTDOWN_IN_PROGRESS,
++ MD_ERROR_WIN_IO_DEVICE,
++ MD_ERROR_WIN_SERIAL_NO_DEVICE,
++ MD_ERROR_WIN_IRQ_BUSY,
++ MD_ERROR_WIN_MORE_WRITES,
++ MD_ERROR_WIN_COUNTER_TIMEOUT,
++ MD_ERROR_WIN_FLOPPY_ID_MARK_NOT_FOUND,
++ MD_ERROR_WIN_FLOPPY_WRONG_CYLINDER,
++ MD_ERROR_WIN_FLOPPY_UNKNOWN_ERROR,
++ MD_ERROR_WIN_FLOPPY_BAD_REGISTERS,
++ MD_ERROR_WIN_DISK_RECALIBRATE_FAILED,
++ MD_ERROR_WIN_DISK_OPERATION_FAILED,
++ MD_ERROR_WIN_DISK_RESET_FAILED,
++ MD_ERROR_WIN_EOM_OVERFLOW,
++ MD_ERROR_WIN_NOT_ENOUGH_SERVER_MEMORY,
++ MD_ERROR_WIN_POSSIBLE_DEADLOCK,
++ MD_ERROR_WIN_MAPPED_ALIGNMENT,
++ MD_ERROR_WIN_SET_POWER_STATE_VETOED,
++ MD_ERROR_WIN_SET_POWER_STATE_FAILED,
++ MD_ERROR_WIN_TOO_MANY_LINKS,
++ MD_ERROR_WIN_OLD_WIN_VERSION,
++ MD_ERROR_WIN_APP_WRONG_OS,
++ MD_ERROR_WIN_SINGLE_INSTANCE_APP,
++ MD_ERROR_WIN_RMODE_APP,
++ MD_ERROR_WIN_INVALID_DLL,
++ MD_ERROR_WIN_NO_ASSOCIATION,
++ MD_ERROR_WIN_DDE_FAIL,
++ MD_ERROR_WIN_DLL_NOT_FOUND,
++ MD_ERROR_WIN_NO_MORE_USER_HANDLES,
++ MD_ERROR_WIN_MESSAGE_SYNC_ONLY,
++ MD_ERROR_WIN_SOURCE_ELEMENT_EMPTY,
++ MD_ERROR_WIN_DESTINATION_ELEMENT_FULL,
++ MD_ERROR_WIN_ILLEGAL_ELEMENT_ADDRESS,
++ MD_ERROR_WIN_MAGAZINE_NOT_PRESENT,
++ MD_ERROR_WIN_DEVICE_REINITIALIZATION_NEEDED,
++ MD_ERROR_WIN_DEVICE_REQUIRES_CLEANING,
++ MD_ERROR_WIN_DEVICE_DOOR_OPEN,
++ MD_ERROR_WIN_DEVICE_NOT_CONNECTED,
++ MD_ERROR_WIN_NOT_FOUND,
++ MD_ERROR_WIN_NO_MATCH,
++ MD_ERROR_WIN_SET_NOT_FOUND,
++ MD_ERROR_WIN_POINT_NOT_FOUND,
++ MD_ERROR_WIN_NO_TRACKING_SERVICE,
++ MD_ERROR_WIN_NO_VOLUME_ID,
++ MD_ERROR_WIN_UNABLE_TO_REMOVE_REPLACED,
++ MD_ERROR_WIN_UNABLE_TO_MOVE_REPLACEMENT,
++ MD_ERROR_WIN_UNABLE_TO_MOVE_REPLACEMENT_2,
++ MD_ERROR_WIN_JOURNAL_DELETE_IN_PROGRESS,
++ MD_ERROR_WIN_JOURNAL_NOT_ACTIVE,
++ MD_ERROR_WIN_POTENTIAL_FILE_FOUND,
++ MD_ERROR_WIN_JOURNAL_ENTRY_DELETED,
++ MD_ERROR_WIN_VRF_CFG_AND_IO_ENABLED,
++ MD_ERROR_WIN_PARTITION_TERMINATING,
++ MD_ERROR_WIN_SHUTDOWN_IS_SCHEDULED,
++ MD_ERROR_WIN_SHUTDOWN_USERS_LOGGED_ON,
++ MD_ERROR_WIN_BAD_DEVICE,
++ MD_ERROR_WIN_CONNECTION_UNAVAIL,
++ MD_ERROR_WIN_DEVICE_ALREADY_REMEMBERED,
++ MD_ERROR_WIN_NO_NET_OR_BAD_PATH,
++ MD_ERROR_WIN_BAD_PROVIDER,
++ MD_ERROR_WIN_CANNOT_OPEN_PROFILE,
++ MD_ERROR_WIN_BAD_PROFILE,
++ MD_ERROR_WIN_NOT_CONTAINER,
++ MD_ERROR_WIN_EXTENDED_ERROR,
++ MD_ERROR_WIN_INVALID_GROUPNAME,
++ MD_ERROR_WIN_INVALID_COMPUTERNAME,
++ MD_ERROR_WIN_INVALID_EVENTNAME,
++ MD_ERROR_WIN_INVALID_DOMAINNAME,
++ MD_ERROR_WIN_INVALID_SERVICENAME,
++ MD_ERROR_WIN_INVALID_NETNAME,
++ MD_ERROR_WIN_INVALID_SHARENAME,
++ MD_ERROR_WIN_INVALID_PASSWORDNAME,
++ MD_ERROR_WIN_INVALID_MESSAGENAME,
++ MD_ERROR_WIN_INVALID_MESSAGEDEST,
++ MD_ERROR_WIN_SESSION_CREDENTIAL_CONFLICT,
++ MD_ERROR_WIN_REMOTE_SESSION_LIMIT_EXCEEDED,
++ MD_ERROR_WIN_DUP_DOMAINNAME,
++ MD_ERROR_WIN_NO_NETWORK,
++ MD_ERROR_WIN_CANCELLED,
++ MD_ERROR_WIN_USER_MAPPED_FILE,
++ MD_ERROR_WIN_CONNECTION_REFUSED,
++ MD_ERROR_WIN_GRACEFUL_DISCONNECT,
++ MD_ERROR_WIN_ADDRESS_ALREADY_ASSOCIATED,
++ MD_ERROR_WIN_ADDRESS_NOT_ASSOCIATED,
++ MD_ERROR_WIN_CONNECTION_INVALID,
++ MD_ERROR_WIN_CONNECTION_ACTIVE,
++ MD_ERROR_WIN_NETWORK_UNREACHABLE,
++ MD_ERROR_WIN_HOST_UNREACHABLE,
++ MD_ERROR_WIN_PROTOCOL_UNREACHABLE,
++ MD_ERROR_WIN_PORT_UNREACHABLE,
++ MD_ERROR_WIN_REQUEST_ABORTED,
++ MD_ERROR_WIN_CONNECTION_ABORTED,
++ MD_ERROR_WIN_RETRY,
++ MD_ERROR_WIN_CONNECTION_COUNT_LIMIT,
++ MD_ERROR_WIN_LOGIN_TIME_RESTRICTION,
++ MD_ERROR_WIN_LOGIN_WKSTA_RESTRICTION,
++ MD_ERROR_WIN_INCORRECT_ADDRESS,
++ MD_ERROR_WIN_ALREADY_REGISTERED,
++ MD_ERROR_WIN_SERVICE_NOT_FOUND,
++ MD_ERROR_WIN_NOT_AUTHENTICATED,
++ MD_ERROR_WIN_NOT_LOGGED_ON,
++ MD_ERROR_WIN_CONTINUE,
++ MD_ERROR_WIN_ALREADY_INITIALIZED,
++ MD_ERROR_WIN_NO_MORE_DEVICES,
++ MD_ERROR_WIN_NO_SUCH_SITE,
++ MD_ERROR_WIN_DOMAIN_CONTROLLER_EXISTS,
++ MD_ERROR_WIN_ONLY_IF_CONNECTED,
++ MD_ERROR_WIN_OVERRIDE_NOCHANGES,
++ MD_ERROR_WIN_BAD_USER_PROFILE,
++ MD_ERROR_WIN_NOT_SUPPORTED_ON_SBS,
++ MD_ERROR_WIN_SERVER_SHUTDOWN_IN_PROGRESS,
++ MD_ERROR_WIN_HOST_DOWN,
++ MD_ERROR_WIN_NON_ACCOUNT_SID,
++ MD_ERROR_WIN_NON_DOMAIN_SID,
++ MD_ERROR_WIN_APPHELP_BLOCK,
++ MD_ERROR_WIN_ACCESS_DISABLED_BY_POLICY,
++ MD_ERROR_WIN_REG_NAT_CONSUMPTION,
++ MD_ERROR_WIN_CSCSHARE_OFFLINE,
++ MD_ERROR_WIN_PKINIT_FAILURE,
++ MD_ERROR_WIN_SMARTCARD_SUBSYSTEM_FAILURE,
++ MD_ERROR_WIN_DOWNGRADE_DETECTED,
++ MD_ERROR_WIN_MACHINE_LOCKED,
++ MD_ERROR_WIN_SMB_GUEST_LOGON_BLOCKED,
++ MD_ERROR_WIN_CALLBACK_SUPPLIED_INVALID_DATA,
++ MD_ERROR_WIN_SYNC_FOREGROUND_REFRESH_REQUIRED,
++ MD_ERROR_WIN_DRIVER_BLOCKED,
++ MD_ERROR_WIN_INVALID_IMPORT_OF_NON_DLL,
++ MD_ERROR_WIN_ACCESS_DISABLED_WEBBLADE,
++ MD_ERROR_WIN_ACCESS_DISABLED_WEBBLADE_TAMPER,
++ MD_ERROR_WIN_RECOVERY_FAILURE,
++ MD_ERROR_WIN_ALREADY_FIBER,
++ MD_ERROR_WIN_ALREADY_THREAD,
++ MD_ERROR_WIN_STACK_BUFFER_OVERRUN,
++ MD_ERROR_WIN_PARAMETER_QUOTA_EXCEEDED,
++ MD_ERROR_WIN_DEBUGGER_INACTIVE,
++ MD_ERROR_WIN_DELAY_LOAD_FAILED,
++ MD_ERROR_WIN_VDM_DISALLOWED,
++ MD_ERROR_WIN_UNIDENTIFIED_ERROR,
++ MD_ERROR_WIN_INVALID_CRUNTIME_PARAMETER,
++ MD_ERROR_WIN_BEYOND_VDL,
++ MD_ERROR_WIN_INCOMPATIBLE_SERVICE_SID_TYPE,
++ MD_ERROR_WIN_DRIVER_PROCESS_TERMINATED,
++ MD_ERROR_WIN_IMPLEMENTATION_LIMIT,
++ MD_ERROR_WIN_PROCESS_IS_PROTECTED,
++ MD_ERROR_WIN_SERVICE_NOTIFY_CLIENT_LAGGING,
++ MD_ERROR_WIN_DISK_QUOTA_EXCEEDED,
++ MD_ERROR_WIN_CONTENT_BLOCKED,
++ MD_ERROR_WIN_INCOMPATIBLE_SERVICE_PRIVILEGE,
++ MD_ERROR_WIN_APP_HANG,
++ MD_ERROR_WIN_INVALID_LABEL,
++ MD_ERROR_WIN_NOT_ALL_ASSIGNED,
++ MD_ERROR_WIN_SOME_NOT_MAPPED,
++ MD_ERROR_WIN_NO_QUOTAS_FOR_ACCOUNT,
++ MD_ERROR_WIN_LOCAL_USER_SESSION_KEY,
++ MD_ERROR_WIN_NULL_LM_PASSWORD,
++ MD_ERROR_WIN_UNKNOWN_REVISION,
++ MD_ERROR_WIN_REVISION_MISMATCH,
++ MD_ERROR_WIN_INVALID_OWNER,
++ MD_ERROR_WIN_INVALID_PRIMARY_GROUP,
++ MD_ERROR_WIN_NO_IMPERSONATION_TOKEN,
++ MD_ERROR_WIN_CANT_DISABLE_MANDATORY,
++ MD_ERROR_WIN_NO_LOGON_SERVERS,
++ MD_ERROR_WIN_NO_SUCH_LOGON_SESSION,
++ MD_ERROR_WIN_NO_SUCH_PRIVILEGE,
++ MD_ERROR_WIN_PRIVILEGE_NOT_HELD,
++ MD_ERROR_WIN_INVALID_ACCOUNT_NAME,
++ MD_ERROR_WIN_USER_EXISTS,
++ MD_ERROR_WIN_NO_SUCH_USER,
++ MD_ERROR_WIN_GROUP_EXISTS,
++ MD_ERROR_WIN_NO_SUCH_GROUP,
++ MD_ERROR_WIN_MEMBER_IN_GROUP,
++ MD_ERROR_WIN_MEMBER_NOT_IN_GROUP,
++ MD_ERROR_WIN_LAST_ADMIN,
++ MD_ERROR_WIN_WRONG_PASSWORD,
++ MD_ERROR_WIN_ILL_FORMED_PASSWORD,
++ MD_ERROR_WIN_PASSWORD_RESTRICTION,
++ MD_ERROR_WIN_LOGON_FAILURE,
++ MD_ERROR_WIN_ACCOUNT_RESTRICTION,
++ MD_ERROR_WIN_INVALID_LOGON_HOURS,
++ MD_ERROR_WIN_INVALID_WORKSTATION,
++ MD_ERROR_WIN_PASSWORD_EXPIRED,
++ MD_ERROR_WIN_ACCOUNT_DISABLED,
++ MD_ERROR_WIN_NONE_MAPPED,
++ MD_ERROR_WIN_TOO_MANY_LUIDS_REQUESTED,
++ MD_ERROR_WIN_LUIDS_EXHAUSTED,
++ MD_ERROR_WIN_INVALID_SUB_AUTHORITY,
++ MD_ERROR_WIN_INVALID_ACL,
++ MD_ERROR_WIN_INVALID_SID,
++ MD_ERROR_WIN_INVALID_SECURITY_DESCR,
++ MD_ERROR_WIN_BAD_INHERITANCE_ACL,
++ MD_ERROR_WIN_SERVER_DISABLED,
++ MD_ERROR_WIN_SERVER_NOT_DISABLED,
++ MD_ERROR_WIN_INVALID_ID_AUTHORITY,
++ MD_ERROR_WIN_ALLOTTED_SPACE_EXCEEDED,
++ MD_ERROR_WIN_INVALID_GROUP_ATTRIBUTES,
++ MD_ERROR_WIN_BAD_IMPERSONATION_LEVEL,
++ MD_ERROR_WIN_CANT_OPEN_ANONYMOUS,
++ MD_ERROR_WIN_BAD_VALIDATION_CLASS,
++ MD_ERROR_WIN_BAD_TOKEN_TYPE,
++ MD_ERROR_WIN_NO_SECURITY_ON_OBJECT,
++ MD_ERROR_WIN_CANT_ACCESS_DOMAIN_INFO,
++ MD_ERROR_WIN_INVALID_SERVER_STATE,
++ MD_ERROR_WIN_INVALID_DOMAIN_STATE,
++ MD_ERROR_WIN_INVALID_DOMAIN_ROLE,
++ MD_ERROR_WIN_NO_SUCH_DOMAIN,
++ MD_ERROR_WIN_DOMAIN_EXISTS,
++ MD_ERROR_WIN_DOMAIN_LIMIT_EXCEEDED,
++ MD_ERROR_WIN_INTERNAL_DB_CORRUPTION,
++ MD_ERROR_WIN_INTERNAL_ERROR,
++ MD_ERROR_WIN_GENERIC_NOT_MAPPED,
++ MD_ERROR_WIN_BAD_DESCRIPTOR_FORMAT,
++ MD_ERROR_WIN_NOT_LOGON_PROCESS,
++ MD_ERROR_WIN_LOGON_SESSION_EXISTS,
++ MD_ERROR_WIN_NO_SUCH_PACKAGE,
++ MD_ERROR_WIN_BAD_LOGON_SESSION_STATE,
++ MD_ERROR_WIN_LOGON_SESSION_COLLISION,
++ MD_ERROR_WIN_INVALID_LOGON_TYPE,
++ MD_ERROR_WIN_CANNOT_IMPERSONATE,
++ MD_ERROR_WIN_RXACT_INVALID_STATE,
++ MD_ERROR_WIN_RXACT_COMMIT_FAILURE,
++ MD_ERROR_WIN_SPECIAL_ACCOUNT,
++ MD_ERROR_WIN_SPECIAL_GROUP,
++ MD_ERROR_WIN_SPECIAL_USER,
++ MD_ERROR_WIN_MEMBERS_PRIMARY_GROUP,
++ MD_ERROR_WIN_TOKEN_ALREADY_IN_USE,
++ MD_ERROR_WIN_NO_SUCH_ALIAS,
++ MD_ERROR_WIN_MEMBER_NOT_IN_ALIAS,
++ MD_ERROR_WIN_MEMBER_IN_ALIAS,
++ MD_ERROR_WIN_ALIAS_EXISTS,
++ MD_ERROR_WIN_LOGON_NOT_GRANTED,
++ MD_ERROR_WIN_TOO_MANY_SECRETS,
++ MD_ERROR_WIN_SECRET_TOO_LONG,
++ MD_ERROR_WIN_INTERNAL_DB_ERROR,
++ MD_ERROR_WIN_TOO_MANY_CONTEXT_IDS,
++ MD_ERROR_WIN_LOGON_TYPE_NOT_GRANTED,
++ MD_ERROR_WIN_NT_CROSS_ENCRYPTION_REQUIRED,
++ MD_ERROR_WIN_NO_SUCH_MEMBER,
++ MD_ERROR_WIN_INVALID_MEMBER,
++ MD_ERROR_WIN_TOO_MANY_SIDS,
++ MD_ERROR_WIN_LM_CROSS_ENCRYPTION_REQUIRED,
++ MD_ERROR_WIN_NO_INHERITANCE,
++ MD_ERROR_WIN_FILE_CORRUPT,
++ MD_ERROR_WIN_DISK_CORRUPT,
++ MD_ERROR_WIN_NO_USER_SESSION_KEY,
++ MD_ERROR_WIN_LICENSE_QUOTA_EXCEEDED,
++ MD_ERROR_WIN_WRONG_TARGET_NAME,
++ MD_ERROR_WIN_MUTUAL_AUTH_FAILED,
++ MD_ERROR_WIN_TIME_SKEW,
++ MD_ERROR_WIN_CURRENT_DOMAIN_NOT_ALLOWED,
++ MD_ERROR_WIN_INVALID_WINDOW_HANDLE,
++ MD_ERROR_WIN_INVALID_MENU_HANDLE,
++ MD_ERROR_WIN_INVALID_CURSOR_HANDLE,
++ MD_ERROR_WIN_INVALID_ACCEL_HANDLE,
++ MD_ERROR_WIN_INVALID_HOOK_HANDLE,
++ MD_ERROR_WIN_INVALID_DWP_HANDLE,
++ MD_ERROR_WIN_TLW_WITH_WSCHILD,
++ MD_ERROR_WIN_CANNOT_FIND_WND_CLASS,
++ MD_ERROR_WIN_WINDOW_OF_OTHER_THREAD,
++ MD_ERROR_WIN_HOTKEY_ALREADY_REGISTERED,
++ MD_ERROR_WIN_CLASS_ALREADY_EXISTS,
++ MD_ERROR_WIN_CLASS_DOES_NOT_EXIST,
++ MD_ERROR_WIN_CLASS_HAS_WINDOWS,
++ MD_ERROR_WIN_INVALID_INDEX,
++ MD_ERROR_WIN_INVALID_ICON_HANDLE,
++ MD_ERROR_WIN_PRIVATE_DIALOG_INDEX,
++ MD_ERROR_WIN_LISTBOX_ID_NOT_FOUND,
++ MD_ERROR_WIN_NO_WILDCARD_CHARACTERS,
++ MD_ERROR_WIN_CLIPBOARD_NOT_OPEN,
++ MD_ERROR_WIN_HOTKEY_NOT_REGISTERED,
++ MD_ERROR_WIN_WINDOW_NOT_DIALOG,
++ MD_ERROR_WIN_CONTROL_ID_NOT_FOUND,
++ MD_ERROR_WIN_INVALID_COMBOBOX_MESSAGE,
++ MD_ERROR_WIN_WINDOW_NOT_COMBOBOX,
++ MD_ERROR_WIN_INVALID_EDIT_HEIGHT,
++ MD_ERROR_WIN_DC_NOT_FOUND,
++ MD_ERROR_WIN_INVALID_HOOK_FILTER,
++ MD_ERROR_WIN_INVALID_FILTER_PROC,
++ MD_ERROR_WIN_HOOK_NEEDS_HMOD,
++ MD_ERROR_WIN_GLOBAL_ONLY_HOOK,
++ MD_ERROR_WIN_JOURNAL_HOOK_SET,
++ MD_ERROR_WIN_HOOK_NOT_INSTALLED,
++ MD_ERROR_WIN_INVALID_LB_MESSAGE,
++ MD_ERROR_WIN_SETCOUNT_ON_BAD_LB,
++ MD_ERROR_WIN_LB_WITHOUT_TABSTOPS,
++ MD_ERROR_WIN_DESTROY_OBJECT_OF_OTHER_THREAD,
++ MD_ERROR_WIN_CHILD_WINDOW_MENU,
++ MD_ERROR_WIN_NO_SYSTEM_MENU,
++ MD_ERROR_WIN_INVALID_MSGBOX_STYLE,
++ MD_ERROR_WIN_INVALID_SPI_VALUE,
++ MD_ERROR_WIN_SCREEN_ALREADY_LOCKED,
++ MD_ERROR_WIN_HWNDS_HAVE_DIFF_PARENT,
++ MD_ERROR_WIN_NOT_CHILD_WINDOW,
++ MD_ERROR_WIN_INVALID_GW_COMMAND,
++ MD_ERROR_WIN_INVALID_THREAD_ID,
++ MD_ERROR_WIN_NON_MDICHILD_WINDOW,
++ MD_ERROR_WIN_POPUP_ALREADY_ACTIVE,
++ MD_ERROR_WIN_NO_SCROLLBARS,
++ MD_ERROR_WIN_INVALID_SCROLLBAR_RANGE,
++ MD_ERROR_WIN_INVALID_SHOWWIN_COMMAND,
++ MD_ERROR_WIN_NO_SYSTEM_RESOURCES,
++ MD_ERROR_WIN_NONPAGED_SYSTEM_RESOURCES,
++ MD_ERROR_WIN_PAGED_SYSTEM_RESOURCES,
++ MD_ERROR_WIN_WORKING_SET_QUOTA,
++ MD_ERROR_WIN_PAGEFILE_QUOTA,
++ MD_ERROR_WIN_COMMITMENT_LIMIT,
++ MD_ERROR_WIN_MENU_ITEM_NOT_FOUND,
++ MD_ERROR_WIN_INVALID_KEYBOARD_HANDLE,
++ MD_ERROR_WIN_HOOK_TYPE_NOT_ALLOWED,
++ MD_ERROR_WIN_REQUIRES_INTERACTIVE_WINDOWSTATION,
++ MD_ERROR_WIN_TIMEOUT,
++ MD_ERROR_WIN_INVALID_MONITOR_HANDLE,
++ MD_ERROR_WIN_INCORRECT_SIZE,
++ MD_ERROR_WIN_SYMLINK_CLASS_DISABLED,
++ MD_ERROR_WIN_SYMLINK_NOT_SUPPORTED,
++ MD_ERROR_WIN_XML_PARSE_ERROR,
++ MD_ERROR_WIN_XMLDSIG_ERROR,
++ MD_ERROR_WIN_RESTART_APPLICATION,
++ MD_ERROR_WIN_WRONG_COMPARTMENT,
++ MD_ERROR_WIN_AUTHIP_FAILURE,
++ MD_ERROR_WIN_NO_NVRAM_RESOURCES,
++ MD_ERROR_WIN_NOT_GUI_PROCESS,
++ MD_ERROR_WIN_EVENTLOG_FILE_CORRUPT,
++ MD_ERROR_WIN_EVENTLOG_CANT_START,
++ MD_ERROR_WIN_LOG_FILE_FULL,
++ MD_ERROR_WIN_EVENTLOG_FILE_CHANGED,
++ MD_ERROR_WIN_CONTAINER_ASSIGNED,
++ MD_ERROR_WIN_JOB_NO_CONTAINER,
++ MD_ERROR_WIN_INVALID_TASK_NAME,
++ MD_ERROR_WIN_INVALID_TASK_INDEX,
++ MD_ERROR_WIN_THREAD_ALREADY_IN_TASK,
++ MD_ERROR_WIN_INSTALL_SERVICE_FAILURE,
++ MD_ERROR_WIN_INSTALL_USEREXIT,
++ MD_ERROR_WIN_INSTALL_FAILURE,
++ MD_ERROR_WIN_INSTALL_SUSPEND,
++ MD_ERROR_WIN_UNKNOWN_PRODUCT,
++ MD_ERROR_WIN_UNKNOWN_FEATURE,
++ MD_ERROR_WIN_UNKNOWN_COMPONENT,
++ MD_ERROR_WIN_UNKNOWN_PROPERTY,
++ MD_ERROR_WIN_INVALID_HANDLE_STATE,
++ MD_ERROR_WIN_BAD_CONFIGURATION,
++ MD_ERROR_WIN_INDEX_ABSENT,
++ MD_ERROR_WIN_INSTALL_SOURCE_ABSENT,
++ MD_ERROR_WIN_INSTALL_PACKAGE_VERSION,
++ MD_ERROR_WIN_PRODUCT_UNINSTALLED,
++ MD_ERROR_WIN_BAD_QUERY_SYNTAX,
++ MD_ERROR_WIN_INVALID_FIELD,
++ MD_ERROR_WIN_DEVICE_REMOVED,
++ MD_ERROR_WIN_INSTALL_ALREADY_RUNNING,
++ MD_ERROR_WIN_INSTALL_PACKAGE_OPEN_FAILED,
++ MD_ERROR_WIN_INSTALL_PACKAGE_INVALID,
++ MD_ERROR_WIN_INSTALL_UI_FAILURE,
++ MD_ERROR_WIN_INSTALL_LOG_FAILURE,
++ MD_ERROR_WIN_INSTALL_LANGUAGE_UNSUPPORTED,
++ MD_ERROR_WIN_INSTALL_TRANSFORM_FAILURE,
++ MD_ERROR_WIN_INSTALL_PACKAGE_REJECTED,
++ MD_ERROR_WIN_FUNCTION_NOT_CALLED,
++ MD_ERROR_WIN_FUNCTION_FAILED,
++ MD_ERROR_WIN_INVALID_TABLE,
++ MD_ERROR_WIN_DATATYPE_MISMATCH,
++ MD_ERROR_WIN_UNSUPPORTED_TYPE,
++ MD_ERROR_WIN_CREATE_FAILED,
++ MD_ERROR_WIN_INSTALL_TEMP_UNWRITABLE,
++ MD_ERROR_WIN_INSTALL_PLATFORM_UNSUPPORTED,
++ MD_ERROR_WIN_INSTALL_NOTUSED,
++ MD_ERROR_WIN_PATCH_PACKAGE_OPEN_FAILED,
++ MD_ERROR_WIN_PATCH_PACKAGE_INVALID,
++ MD_ERROR_WIN_PATCH_PACKAGE_UNSUPPORTED,
++ MD_ERROR_WIN_PRODUCT_VERSION,
++ MD_ERROR_WIN_INVALID_COMMAND_LINE,
++ MD_ERROR_WIN_INSTALL_REMOTE_DISALLOWED,
++ MD_ERROR_WIN_SUCCESS_REBOOT_INITIATED,
++ MD_ERROR_WIN_PATCH_TARGET_NOT_FOUND,
++ MD_ERROR_WIN_PATCH_PACKAGE_REJECTED,
++ MD_ERROR_WIN_INSTALL_TRANSFORM_REJECTED,
++ MD_ERROR_WIN_INSTALL_REMOTE_PROHIBITED,
++ MD_ERROR_WIN_PATCH_REMOVAL_UNSUPPORTED,
++ MD_ERROR_WIN_UNKNOWN_PATCH,
++ MD_ERROR_WIN_PATCH_NO_SEQUENCE,
++ MD_ERROR_WIN_PATCH_REMOVAL_DISALLOWED,
++ MD_ERROR_WIN_INVALID_PATCH_XML,
++ MD_ERROR_WIN_PATCH_MANAGED_ADVERTISED_PRODUCT,
++ MD_ERROR_WIN_INSTALL_SERVICE_SAFEBOOT,
++ MD_ERROR_WIN_FAIL_FAST_EXCEPTION,
++ MD_ERROR_WIN_INSTALL_REJECTED,
++ MD_ERROR_WIN_DYNAMIC_CODE_BLOCKED,
++ MD_ERROR_WIN_NOT_SAME_OBJECT,
++ MD_ERROR_WIN_STRICT_CFG_VIOLATION,
++ MD_ERROR_WIN_SET_CONTEXT_DENIED,
++ MD_ERROR_WIN_CROSS_PARTITION_VIOLATION,
++ MD_ERROR_WIN_RETURN_ADDRESS_HIJACK_ATTEMPT,
++ MD_ERROR_WIN_INVALID_USER_BUFFER,
++ MD_ERROR_WIN_UNRECOGNIZED_MEDIA,
++ MD_ERROR_WIN_NO_TRUST_LSA_SECRET,
++ MD_ERROR_WIN_NO_TRUST_SAM_ACCOUNT,
++ MD_ERROR_WIN_TRUSTED_DOMAIN_FAILURE,
++ MD_ERROR_WIN_TRUSTED_RELATIONSHIP_FAILURE,
++ MD_ERROR_WIN_TRUST_FAILURE,
++ MD_ERROR_WIN_NETLOGON_NOT_STARTED,
++ MD_ERROR_WIN_ACCOUNT_EXPIRED,
++ MD_ERROR_WIN_REDIRECTOR_HAS_OPEN_HANDLES,
++ MD_ERROR_WIN_PRINTER_DRIVER_ALREADY_INSTALLED,
++ MD_ERROR_WIN_UNKNOWN_PORT,
++ MD_ERROR_WIN_UNKNOWN_PRINTER_DRIVER,
++ MD_ERROR_WIN_UNKNOWN_PRINTPROCESSOR,
++ MD_ERROR_WIN_INVALID_SEPARATOR_FILE,
++ MD_ERROR_WIN_INVALID_PRIORITY,
++ MD_ERROR_WIN_INVALID_PRINTER_NAME,
++ MD_ERROR_WIN_PRINTER_ALREADY_EXISTS,
++ MD_ERROR_WIN_INVALID_PRINTER_COMMAND,
++ MD_ERROR_WIN_INVALID_DATATYPE,
++ MD_ERROR_WIN_INVALID_ENVIRONMENT,
++ MD_ERROR_WIN_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT,
++ MD_ERROR_WIN_NOLOGON_WORKSTATION_TRUST_ACCOUNT,
++ MD_ERROR_WIN_NOLOGON_SERVER_TRUST_ACCOUNT,
++ MD_ERROR_WIN_DOMAIN_TRUST_INCONSISTENT,
++ MD_ERROR_WIN_SERVER_HAS_OPEN_HANDLES,
++ MD_ERROR_WIN_RESOURCE_DATA_NOT_FOUND,
++ MD_ERROR_WIN_RESOURCE_TYPE_NOT_FOUND,
++ MD_ERROR_WIN_RESOURCE_NAME_NOT_FOUND,
++ MD_ERROR_WIN_RESOURCE_LANG_NOT_FOUND,
++ MD_ERROR_WIN_NOT_ENOUGH_QUOTA,
++ MD_ERROR_WIN_INVALID_TIME,
++ MD_ERROR_WIN_INVALID_FORM_NAME,
++ MD_ERROR_WIN_INVALID_FORM_SIZE,
++ MD_ERROR_WIN_ALREADY_WAITING,
++ MD_ERROR_WIN_PRINTER_DELETED,
++ MD_ERROR_WIN_INVALID_PRINTER_STATE,
++ MD_ERROR_WIN_PASSWORD_MUST_CHANGE,
++ MD_ERROR_WIN_DOMAIN_CONTROLLER_NOT_FOUND,
++ MD_ERROR_WIN_ACCOUNT_LOCKED_OUT,
++ MD_ERROR_WIN_NO_SITENAME,
++ MD_ERROR_WIN_CANT_ACCESS_FILE,
++ MD_ERROR_WIN_CANT_RESOLVE_FILENAME,
++ MD_ERROR_WIN_KM_DRIVER_BLOCKED,
++ MD_ERROR_WIN_CONTEXT_EXPIRED,
++ MD_ERROR_WIN_PER_USER_TRUST_QUOTA_EXCEEDED,
++ MD_ERROR_WIN_ALL_USER_TRUST_QUOTA_EXCEEDED,
++ MD_ERROR_WIN_USER_DELETE_TRUST_QUOTA_EXCEEDED,
++ MD_ERROR_WIN_AUTHENTICATION_FIREWALL_FAILED,
++ MD_ERROR_WIN_REMOTE_PRINT_CONNECTIONS_BLOCKED,
++ MD_ERROR_WIN_NTLM_BLOCKED,
++ MD_ERROR_WIN_PASSWORD_CHANGE_REQUIRED,
++ MD_ERROR_WIN_LOST_MODE_LOGON_RESTRICTION,
++ MD_ERROR_WIN_INVALID_PIXEL_FORMAT,
++ MD_ERROR_WIN_BAD_DRIVER,
++ MD_ERROR_WIN_INVALID_WINDOW_STYLE,
++ MD_ERROR_WIN_METAFILE_NOT_SUPPORTED,
++ MD_ERROR_WIN_TRANSFORM_NOT_SUPPORTED,
++ MD_ERROR_WIN_CLIPPING_NOT_SUPPORTED,
++ MD_ERROR_WIN_INVALID_CMM,
++ MD_ERROR_WIN_INVALID_PROFILE,
++ MD_ERROR_WIN_TAG_NOT_FOUND,
++ MD_ERROR_WIN_TAG_NOT_PRESENT,
++ MD_ERROR_WIN_DUPLICATE_TAG,
++ MD_ERROR_WIN_PROFILE_NOT_ASSOCIATED_WITH_DEVICE,
++ MD_ERROR_WIN_PROFILE_NOT_FOUND,
++ MD_ERROR_WIN_INVALID_COLORSPACE,
++ MD_ERROR_WIN_ICM_NOT_ENABLED,
++ MD_ERROR_WIN_DELETING_ICM_XFORM,
++ MD_ERROR_WIN_INVALID_TRANSFORM,
++ MD_ERROR_WIN_COLORSPACE_MISMATCH,
++ MD_ERROR_WIN_INVALID_COLORINDEX,
++ MD_ERROR_WIN_PROFILE_DOES_NOT_MATCH_DEVICE,
++ MD_ERROR_WIN_CONNECTED_OTHER_PASSWORD,
++ MD_ERROR_WIN_CONNECTED_OTHER_PASSWORD_DEFAULT,
++ MD_ERROR_WIN_BAD_USERNAME,
++ MD_ERROR_WIN_NOT_CONNECTED,
++ MD_ERROR_WIN_OPEN_FILES,
++ MD_ERROR_WIN_ACTIVE_CONNECTIONS,
++ MD_ERROR_WIN_DEVICE_IN_USE,
++ MD_ERROR_WIN_UNKNOWN_PRINT_MONITOR,
++ MD_ERROR_WIN_PRINTER_DRIVER_IN_USE,
++ MD_ERROR_WIN_SPOOL_FILE_NOT_FOUND,
++ MD_ERROR_WIN_SPL_NO_STARTDOC,
++ MD_ERROR_WIN_SPL_NO_ADDJOB,
++ MD_ERROR_WIN_PRINT_PROCESSOR_ALREADY_INSTALLED,
++ MD_ERROR_WIN_PRINT_MONITOR_ALREADY_INSTALLED,
++ MD_ERROR_WIN_INVALID_PRINT_MONITOR,
++ MD_ERROR_WIN_PRINT_MONITOR_IN_USE,
++ MD_ERROR_WIN_PRINTER_HAS_JOBS_QUEUED,
++ MD_ERROR_WIN_SUCCESS_REBOOT_REQUIRED,
++ MD_ERROR_WIN_SUCCESS_RESTART_REQUIRED,
++ MD_ERROR_WIN_PRINTER_NOT_FOUND,
++ MD_ERROR_WIN_PRINTER_DRIVER_WARNED,
++ MD_ERROR_WIN_PRINTER_DRIVER_BLOCKED,
++ MD_ERROR_WIN_PRINTER_DRIVER_PACKAGE_IN_USE,
++ MD_ERROR_WIN_CORE_DRIVER_PACKAGE_NOT_FOUND,
++ MD_ERROR_WIN_FAIL_REBOOT_REQUIRED,
++ MD_ERROR_WIN_FAIL_REBOOT_INITIATED,
++ MD_ERROR_WIN_PRINTER_DRIVER_DOWNLOAD_NEEDED,
++ MD_ERROR_WIN_PRINT_JOB_RESTART_REQUIRED,
++ MD_ERROR_WIN_INVALID_PRINTER_DRIVER_MANIFEST,
++ MD_ERROR_WIN_PRINTER_NOT_SHAREABLE,
++ MD_ERROR_WIN_REQUEST_PAUSED,
++ MD_ERROR_WIN_APPEXEC_CONDITION_NOT_SATISFIED,
++ MD_ERROR_WIN_APPEXEC_HANDLE_INVALIDATED,
++ MD_ERROR_WIN_APPEXEC_INVALID_HOST_GENERATION,
++ MD_ERROR_WIN_APPEXEC_UNEXPECTED_PROCESS_REGISTRATION,
++ MD_ERROR_WIN_APPEXEC_INVALID_HOST_STATE,
++ MD_ERROR_WIN_APPEXEC_NO_DONOR,
++ MD_ERROR_WIN_APPEXEC_HOST_ID_MISMATCH,
++ MD_ERROR_WIN_APPEXEC_UNKNOWN_USER,
++ MD_ERROR_WIN_IO_REISSUE_AS_CACHED,
++ MD_ERROR_WIN_WINS_INTERNAL,
++ MD_ERROR_WIN_CAN_NOT_DEL_LOCAL_WINS,
++ MD_ERROR_WIN_STATIC_INIT,
++ MD_ERROR_WIN_INC_BACKUP,
++ MD_ERROR_WIN_FULL_BACKUP,
++ MD_ERROR_WIN_REC_NON_EXISTENT,
++ MD_ERROR_WIN_RPL_NOT_ALLOWED,
++ MD_ERROR_WIN_DHCP_ADDRESS_CONFLICT,
++ MD_ERROR_WIN_WMI_GUID_NOT_FOUND,
++ MD_ERROR_WIN_WMI_INSTANCE_NOT_FOUND,
++ MD_ERROR_WIN_WMI_ITEMID_NOT_FOUND,
++ MD_ERROR_WIN_WMI_TRY_AGAIN,
++ MD_ERROR_WIN_WMI_DP_NOT_FOUND,
++ MD_ERROR_WIN_WMI_UNRESOLVED_INSTANCE_REF,
++ MD_ERROR_WIN_WMI_ALREADY_ENABLED,
++ MD_ERROR_WIN_WMI_GUID_DISCONNECTED,
++ MD_ERROR_WIN_WMI_SERVER_UNAVAILABLE,
++ MD_ERROR_WIN_WMI_DP_FAILED,
++ MD_ERROR_WIN_WMI_INVALID_MOF,
++ MD_ERROR_WIN_WMI_INVALID_REGINFO,
++ MD_ERROR_WIN_WMI_ALREADY_DISABLED,
++ MD_ERROR_WIN_WMI_READ_ONLY,
++ MD_ERROR_WIN_WMI_SET_FAILURE,
++ MD_ERROR_WIN_NOT_APPCONTAINER,
++ MD_ERROR_WIN_APPCONTAINER_REQUIRED,
++ MD_ERROR_WIN_NOT_SUPPORTED_IN_APPCONTAINER,
++ MD_ERROR_WIN_INVALID_PACKAGE_SID_LENGTH,
++ MD_ERROR_WIN_INVALID_MEDIA,
++ MD_ERROR_WIN_INVALID_LIBRARY,
++ MD_ERROR_WIN_INVALID_MEDIA_POOL,
++ MD_ERROR_WIN_DRIVE_MEDIA_MISMATCH,
++ MD_ERROR_WIN_MEDIA_OFFLINE,
++ MD_ERROR_WIN_LIBRARY_OFFLINE,
++ MD_ERROR_WIN_EMPTY,
++ MD_ERROR_WIN_NOT_EMPTY,
++ MD_ERROR_WIN_MEDIA_UNAVAILABLE,
++ MD_ERROR_WIN_RESOURCE_DISABLED,
++ MD_ERROR_WIN_INVALID_CLEANER,
++ MD_ERROR_WIN_UNABLE_TO_CLEAN,
++ MD_ERROR_WIN_OBJECT_NOT_FOUND,
++ MD_ERROR_WIN_DATABASE_FAILURE,
++ MD_ERROR_WIN_DATABASE_FULL,
++ MD_ERROR_WIN_MEDIA_INCOMPATIBLE,
++ MD_ERROR_WIN_RESOURCE_NOT_PRESENT,
++ MD_ERROR_WIN_INVALID_OPERATION,
++ MD_ERROR_WIN_MEDIA_NOT_AVAILABLE,
++ MD_ERROR_WIN_DEVICE_NOT_AVAILABLE,
++ MD_ERROR_WIN_REQUEST_REFUSED,
++ MD_ERROR_WIN_INVALID_DRIVE_OBJECT,
++ MD_ERROR_WIN_LIBRARY_FULL,
++ MD_ERROR_WIN_MEDIUM_NOT_ACCESSIBLE,
++ MD_ERROR_WIN_UNABLE_TO_LOAD_MEDIUM,
++ MD_ERROR_WIN_UNABLE_TO_INVENTORY_DRIVE,
++ MD_ERROR_WIN_UNABLE_TO_INVENTORY_SLOT,
++ MD_ERROR_WIN_UNABLE_TO_INVENTORY_TRANSPORT,
++ MD_ERROR_WIN_TRANSPORT_FULL,
++ MD_ERROR_WIN_CONTROLLING_IEPORT,
++ MD_ERROR_WIN_UNABLE_TO_EJECT_MOUNTED_MEDIA,
++ MD_ERROR_WIN_CLEANER_SLOT_SET,
++ MD_ERROR_WIN_CLEANER_SLOT_NOT_SET,
++ MD_ERROR_WIN_CLEANER_CARTRIDGE_SPENT,
++ MD_ERROR_WIN_UNEXPECTED_OMID,
++ MD_ERROR_WIN_CANT_DELETE_LAST_ITEM,
++ MD_ERROR_WIN_MESSAGE_EXCEEDS_MAX_SIZE,
++ MD_ERROR_WIN_VOLUME_CONTAINS_SYS_FILES,
++ MD_ERROR_WIN_INDIGENOUS_TYPE,
++ MD_ERROR_WIN_NO_SUPPORTING_DRIVES,
++ MD_ERROR_WIN_CLEANER_CARTRIDGE_INSTALLED,
++ MD_ERROR_WIN_IEPORT_FULL,
++ MD_ERROR_WIN_FILE_OFFLINE,
++ MD_ERROR_WIN_REMOTE_STORAGE_NOT_ACTIVE,
++ MD_ERROR_WIN_REMOTE_STORAGE_MEDIA_ERROR,
++ MD_ERROR_WIN_NOT_A_REPARSE_POINT,
++ MD_ERROR_WIN_REPARSE_ATTRIBUTE_CONFLICT,
++ MD_ERROR_WIN_INVALID_REPARSE_DATA,
++ MD_ERROR_WIN_REPARSE_TAG_INVALID,
++ MD_ERROR_WIN_REPARSE_TAG_MISMATCH,
++ MD_ERROR_WIN_REPARSE_POINT_ENCOUNTERED,
++ MD_ERROR_WIN_APP_DATA_NOT_FOUND,
++ MD_ERROR_WIN_APP_DATA_EXPIRED,
++ MD_ERROR_WIN_APP_DATA_CORRUPT,
++ MD_ERROR_WIN_APP_DATA_LIMIT_EXCEEDED,
++ MD_ERROR_WIN_APP_DATA_REBOOT_REQUIRED,
++ MD_ERROR_WIN_SECUREBOOT_ROLLBACK_DETECTED,
++ MD_ERROR_WIN_SECUREBOOT_POLICY_VIOLATION,
++ MD_ERROR_WIN_SECUREBOOT_INVALID_POLICY,
++ MD_ERROR_WIN_SECUREBOOT_POLICY_PUBLISHER_NOT_FOUND,
++ MD_ERROR_WIN_SECUREBOOT_POLICY_NOT_SIGNED,
++ MD_ERROR_WIN_SECUREBOOT_NOT_ENABLED,
++ MD_ERROR_WIN_SECUREBOOT_FILE_REPLACED,
++ MD_ERROR_WIN_SECUREBOOT_POLICY_NOT_AUTHORIZED,
++ MD_ERROR_WIN_SECUREBOOT_POLICY_UNKNOWN,
++ MD_ERROR_WIN_SECUREBOOT_POLICY_MISSING_ANTIROLLBACKVERSION,
++ MD_ERROR_WIN_SECUREBOOT_PLATFORM_ID_MISMATCH,
++ MD_ERROR_WIN_SECUREBOOT_POLICY_ROLLBACK_DETECTED,
++ MD_ERROR_WIN_SECUREBOOT_POLICY_UPGRADE_MISMATCH,
++ MD_ERROR_WIN_SECUREBOOT_REQUIRED_POLICY_FILE_MISSING,
++ MD_ERROR_WIN_SECUREBOOT_NOT_BASE_POLICY,
++ MD_ERROR_WIN_SECUREBOOT_NOT_SUPPLEMENTAL_POLICY,
++ MD_ERROR_WIN_OFFLOAD_READ_FLT_NOT_SUPPORTED,
++ MD_ERROR_WIN_OFFLOAD_WRITE_FLT_NOT_SUPPORTED,
++ MD_ERROR_WIN_OFFLOAD_READ_FILE_NOT_SUPPORTED,
++ MD_ERROR_WIN_OFFLOAD_WRITE_FILE_NOT_SUPPORTED,
++ MD_ERROR_WIN_ALREADY_HAS_STREAM_ID,
++ MD_ERROR_WIN_SMR_GARBAGE_COLLECTION_REQUIRED,
++ MD_ERROR_WIN_WOF_WIM_HEADER_CORRUPT,
++ MD_ERROR_WIN_WOF_WIM_RESOURCE_TABLE_CORRUPT,
++ MD_ERROR_WIN_WOF_FILE_RESOURCE_TABLE_CORRUPT,
++ MD_ERROR_WIN_VOLUME_NOT_SIS_ENABLED,
++ MD_ERROR_WIN_SYSTEM_INTEGRITY_ROLLBACK_DETECTED,
++ MD_ERROR_WIN_SYSTEM_INTEGRITY_POLICY_VIOLATION,
++ MD_ERROR_WIN_SYSTEM_INTEGRITY_INVALID_POLICY,
++ MD_ERROR_WIN_SYSTEM_INTEGRITY_POLICY_NOT_SIGNED,
++ MD_ERROR_WIN_SYSTEM_INTEGRITY_TOO_MANY_POLICIES,
++ MD_ERROR_WIN_SYSTEM_INTEGRITY_SUPPLEMENTAL_POLICY_NOT_AUTHORIZED,
++ MD_ERROR_WIN_VSM_NOT_INITIALIZED,
++ MD_ERROR_WIN_VSM_DMA_PROTECTION_NOT_IN_USE,
++ MD_ERROR_WIN_PLATFORM_MANIFEST_NOT_AUTHORIZED,
++ MD_ERROR_WIN_PLATFORM_MANIFEST_INVALID,
++ MD_ERROR_WIN_PLATFORM_MANIFEST_FILE_NOT_AUTHORIZED,
++ MD_ERROR_WIN_PLATFORM_MANIFEST_CATALOG_NOT_AUTHORIZED,
++ MD_ERROR_WIN_PLATFORM_MANIFEST_BINARY_ID_NOT_FOUND,
++ MD_ERROR_WIN_PLATFORM_MANIFEST_NOT_ACTIVE,
++ MD_ERROR_WIN_PLATFORM_MANIFEST_NOT_SIGNED,
++ MD_ERROR_WIN_DEPENDENT_RESOURCE_EXISTS,
++ MD_ERROR_WIN_DEPENDENCY_NOT_FOUND,
++ MD_ERROR_WIN_DEPENDENCY_ALREADY_EXISTS,
++ MD_ERROR_WIN_RESOURCE_NOT_ONLINE,
++ MD_ERROR_WIN_HOST_NODE_NOT_AVAILABLE,
++ MD_ERROR_WIN_RESOURCE_NOT_AVAILABLE,
++ MD_ERROR_WIN_RESOURCE_NOT_FOUND,
++ MD_ERROR_WIN_SHUTDOWN_CLUSTER,
++ MD_ERROR_WIN_CANT_EVICT_ACTIVE_NODE,
++ MD_ERROR_WIN_OBJECT_ALREADY_EXISTS,
++ MD_ERROR_WIN_OBJECT_IN_LIST,
++ MD_ERROR_WIN_GROUP_NOT_AVAILABLE,
++ MD_ERROR_WIN_GROUP_NOT_FOUND,
++ MD_ERROR_WIN_GROUP_NOT_ONLINE,
++ MD_ERROR_WIN_HOST_NODE_NOT_RESOURCE_OWNER,
++ MD_ERROR_WIN_HOST_NODE_NOT_GROUP_OWNER,
++ MD_ERROR_WIN_RESMON_CREATE_FAILED,
++ MD_ERROR_WIN_RESMON_ONLINE_FAILED,
++ MD_ERROR_WIN_RESOURCE_ONLINE,
++ MD_ERROR_WIN_QUORUM_RESOURCE,
++ MD_ERROR_WIN_NOT_QUORUM_CAPABLE,
++ MD_ERROR_WIN_CLUSTER_SHUTTING_DOWN,
++ MD_ERROR_WIN_INVALID_STATE,
++ MD_ERROR_WIN_RESOURCE_PROPERTIES_STORED,
++ MD_ERROR_WIN_NOT_QUORUM_CLASS,
++ MD_ERROR_WIN_CORE_RESOURCE,
++ MD_ERROR_WIN_QUORUM_RESOURCE_ONLINE_FAILED,
++ MD_ERROR_WIN_QUORUMLOG_OPEN_FAILED,
++ MD_ERROR_WIN_CLUSTERLOG_CORRUPT,
++ MD_ERROR_WIN_CLUSTERLOG_RECORD_EXCEEDS_MAXSIZE,
++ MD_ERROR_WIN_CLUSTERLOG_EXCEEDS_MAXSIZE,
++ MD_ERROR_WIN_CLUSTERLOG_CHKPOINT_NOT_FOUND,
++ MD_ERROR_WIN_CLUSTERLOG_NOT_ENOUGH_SPACE,
++ MD_ERROR_WIN_QUORUM_OWNER_ALIVE,
++ MD_ERROR_WIN_NETWORK_NOT_AVAILABLE,
++ MD_ERROR_WIN_NODE_NOT_AVAILABLE,
++ MD_ERROR_WIN_ALL_NODES_NOT_AVAILABLE,
++ MD_ERROR_WIN_RESOURCE_FAILED,
++ MD_ERROR_WIN_CLUSTER_INVALID_NODE,
++ MD_ERROR_WIN_CLUSTER_NODE_EXISTS,
++ MD_ERROR_WIN_CLUSTER_JOIN_IN_PROGRESS,
++ MD_ERROR_WIN_CLUSTER_NODE_NOT_FOUND,
++ MD_ERROR_WIN_CLUSTER_LOCAL_NODE_NOT_FOUND,
++ MD_ERROR_WIN_CLUSTER_NETWORK_EXISTS,
++ MD_ERROR_WIN_CLUSTER_NETWORK_NOT_FOUND,
++ MD_ERROR_WIN_CLUSTER_NETINTERFACE_EXISTS,
++ MD_ERROR_WIN_CLUSTER_NETINTERFACE_NOT_FOUND,
++ MD_ERROR_WIN_CLUSTER_INVALID_REQUEST,
++ MD_ERROR_WIN_CLUSTER_INVALID_NETWORK_PROVIDER,
++ MD_ERROR_WIN_CLUSTER_NODE_DOWN,
++ MD_ERROR_WIN_CLUSTER_NODE_UNREACHABLE,
++ MD_ERROR_WIN_CLUSTER_NODE_NOT_MEMBER,
++ MD_ERROR_WIN_CLUSTER_JOIN_NOT_IN_PROGRESS,
++ MD_ERROR_WIN_CLUSTER_INVALID_NETWORK,
++ MD_ERROR_WIN_CLUSTER_NODE_UP,
++ MD_ERROR_WIN_CLUSTER_IPADDR_IN_USE,
++ MD_ERROR_WIN_CLUSTER_NODE_NOT_PAUSED,
++ MD_ERROR_WIN_CLUSTER_NO_SECURITY_CONTEXT,
++ MD_ERROR_WIN_CLUSTER_NETWORK_NOT_INTERNAL,
++ MD_ERROR_WIN_CLUSTER_NODE_ALREADY_UP,
++ MD_ERROR_WIN_CLUSTER_NODE_ALREADY_DOWN,
++ MD_ERROR_WIN_CLUSTER_NETWORK_ALREADY_ONLINE,
++ MD_ERROR_WIN_CLUSTER_NETWORK_ALREADY_OFFLINE,
++ MD_ERROR_WIN_CLUSTER_NODE_ALREADY_MEMBER,
++ MD_ERROR_WIN_CLUSTER_LAST_INTERNAL_NETWORK,
++ MD_ERROR_WIN_CLUSTER_NETWORK_HAS_DEPENDENTS,
++ MD_ERROR_WIN_INVALID_OPERATION_ON_QUORUM,
++ MD_ERROR_WIN_DEPENDENCY_NOT_ALLOWED,
++ MD_ERROR_WIN_CLUSTER_NODE_PAUSED,
++ MD_ERROR_WIN_NODE_CANT_HOST_RESOURCE,
++ MD_ERROR_WIN_CLUSTER_NODE_NOT_READY,
++ MD_ERROR_WIN_CLUSTER_NODE_SHUTTING_DOWN,
++ MD_ERROR_WIN_CLUSTER_JOIN_ABORTED,
++ MD_ERROR_WIN_CLUSTER_INCOMPATIBLE_VERSIONS,
++ MD_ERROR_WIN_CLUSTER_MAXNUM_OF_RESOURCES_EXCEEDED,
++ MD_ERROR_WIN_CLUSTER_SYSTEM_CONFIG_CHANGED,
++ MD_ERROR_WIN_CLUSTER_RESOURCE_TYPE_NOT_FOUND,
++ MD_ERROR_WIN_CLUSTER_RESTYPE_NOT_SUPPORTED,
++ MD_ERROR_WIN_CLUSTER_RESNAME_NOT_FOUND,
++ MD_ERROR_WIN_CLUSTER_NO_RPC_PACKAGES_REGISTERED,
++ MD_ERROR_WIN_CLUSTER_OWNER_NOT_IN_PREFLIST,
++ MD_ERROR_WIN_CLUSTER_DATABASE_SEQMISMATCH,
++ MD_ERROR_WIN_RESMON_INVALID_STATE,
++ MD_ERROR_WIN_CLUSTER_GUM_NOT_LOCKER,
++ MD_ERROR_WIN_QUORUM_DISK_NOT_FOUND,
++ MD_ERROR_WIN_DATABASE_BACKUP_CORRUPT,
++ MD_ERROR_WIN_CLUSTER_NODE_ALREADY_HAS_DFS_ROOT,
++ MD_ERROR_WIN_RESOURCE_PROPERTY_UNCHANGEABLE,
++ MD_ERROR_WIN_NO_ADMIN_ACCESS_POINT,
++ MD_ERROR_WIN_CLUSTER_MEMBERSHIP_INVALID_STATE,
++ MD_ERROR_WIN_CLUSTER_QUORUMLOG_NOT_FOUND,
++ MD_ERROR_WIN_CLUSTER_MEMBERSHIP_HALT,
++ MD_ERROR_WIN_CLUSTER_INSTANCE_ID_MISMATCH,
++ MD_ERROR_WIN_CLUSTER_NETWORK_NOT_FOUND_FOR_IP,
++ MD_ERROR_WIN_CLUSTER_PROPERTY_DATA_TYPE_MISMATCH,
++ MD_ERROR_WIN_CLUSTER_EVICT_WITHOUT_CLEANUP,
++ MD_ERROR_WIN_CLUSTER_PARAMETER_MISMATCH,
++ MD_ERROR_WIN_NODE_CANNOT_BE_CLUSTERED,
++ MD_ERROR_WIN_CLUSTER_WRONG_OS_VERSION,
++ MD_ERROR_WIN_CLUSTER_CANT_CREATE_DUP_CLUSTER_NAME,
++ MD_ERROR_WIN_CLUSCFG_ALREADY_COMMITTED,
++ MD_ERROR_WIN_CLUSCFG_ROLLBACK_FAILED,
++ MD_ERROR_WIN_CLUSCFG_SYSTEM_DISK_DRIVE_LETTER_CONFLICT,
++ MD_ERROR_WIN_CLUSTER_OLD_VERSION,
++ MD_ERROR_WIN_CLUSTER_MISMATCHED_COMPUTER_ACCT_NAME,
++ MD_ERROR_WIN_CLUSTER_NO_NET_ADAPTERS,
++ MD_ERROR_WIN_CLUSTER_POISONED,
++ MD_ERROR_WIN_CLUSTER_GROUP_MOVING,
++ MD_ERROR_WIN_CLUSTER_RESOURCE_TYPE_BUSY,
++ MD_ERROR_WIN_RESOURCE_CALL_TIMED_OUT,
++ MD_ERROR_WIN_INVALID_CLUSTER_IPV6_ADDRESS,
++ MD_ERROR_WIN_CLUSTER_INTERNAL_INVALID_FUNCTION,
++ MD_ERROR_WIN_CLUSTER_PARAMETER_OUT_OF_BOUNDS,
++ MD_ERROR_WIN_CLUSTER_PARTIAL_SEND,
++ MD_ERROR_WIN_CLUSTER_REGISTRY_INVALID_FUNCTION,
++ MD_ERROR_WIN_CLUSTER_INVALID_STRING_TERMINATION,
++ MD_ERROR_WIN_CLUSTER_INVALID_STRING_FORMAT,
++ MD_ERROR_WIN_CLUSTER_DATABASE_TRANSACTION_IN_PROGRESS,
++ MD_ERROR_WIN_CLUSTER_DATABASE_TRANSACTION_NOT_IN_PROGRESS,
++ MD_ERROR_WIN_CLUSTER_NULL_DATA,
++ MD_ERROR_WIN_CLUSTER_PARTIAL_READ,
++ MD_ERROR_WIN_CLUSTER_PARTIAL_WRITE,
++ MD_ERROR_WIN_CLUSTER_CANT_DESERIALIZE_DATA,
++ MD_ERROR_WIN_DEPENDENT_RESOURCE_PROPERTY_CONFLICT,
++ MD_ERROR_WIN_CLUSTER_NO_QUORUM,
++ MD_ERROR_WIN_CLUSTER_INVALID_IPV6_NETWORK,
++ MD_ERROR_WIN_CLUSTER_INVALID_IPV6_TUNNEL_NETWORK,
++ MD_ERROR_WIN_QUORUM_NOT_ALLOWED_IN_THIS_GROUP,
++ MD_ERROR_WIN_DEPENDENCY_TREE_TOO_COMPLEX,
++ MD_ERROR_WIN_EXCEPTION_IN_RESOURCE_CALL,
++ MD_ERROR_WIN_CLUSTER_RHS_FAILED_INITIALIZATION,
++ MD_ERROR_WIN_CLUSTER_NOT_INSTALLED,
++ MD_ERROR_WIN_CLUSTER_RESOURCES_MUST_BE_ONLINE_ON_THE_SAME_NODE,
++ MD_ERROR_WIN_CLUSTER_MAX_NODES_IN_CLUSTER,
++ MD_ERROR_WIN_CLUSTER_TOO_MANY_NODES,
++ MD_ERROR_WIN_CLUSTER_OBJECT_ALREADY_USED,
++ MD_ERROR_WIN_NONCORE_GROUPS_FOUND,
++ MD_ERROR_WIN_FILE_SHARE_RESOURCE_CONFLICT,
++ MD_ERROR_WIN_CLUSTER_EVICT_INVALID_REQUEST,
++ MD_ERROR_WIN_CLUSTER_SINGLETON_RESOURCE,
++ MD_ERROR_WIN_CLUSTER_GROUP_SINGLETON_RESOURCE,
++ MD_ERROR_WIN_CLUSTER_RESOURCE_PROVIDER_FAILED,
++ MD_ERROR_WIN_CLUSTER_RESOURCE_CONFIGURATION_ERROR,
++ MD_ERROR_WIN_CLUSTER_GROUP_BUSY,
++ MD_ERROR_WIN_CLUSTER_NOT_SHARED_VOLUME,
++ MD_ERROR_WIN_CLUSTER_INVALID_SECURITY_DESCRIPTOR,
++ MD_ERROR_WIN_CLUSTER_SHARED_VOLUMES_IN_USE,
++ MD_ERROR_WIN_CLUSTER_USE_SHARED_VOLUMES_API,
++ MD_ERROR_WIN_CLUSTER_BACKUP_IN_PROGRESS,
++ MD_ERROR_WIN_NON_CSV_PATH,
++ MD_ERROR_WIN_CSV_VOLUME_NOT_LOCAL,
++ MD_ERROR_WIN_CLUSTER_WATCHDOG_TERMINATING,
++ MD_ERROR_WIN_CLUSTER_RESOURCE_VETOED_MOVE_INCOMPATIBLE_NODES,
++ MD_ERROR_WIN_CLUSTER_INVALID_NODE_WEIGHT,
++ MD_ERROR_WIN_CLUSTER_RESOURCE_VETOED_CALL,
++ MD_ERROR_WIN_RESMON_SYSTEM_RESOURCES_LACKING,
++ MD_ERROR_WIN_CLUSTER_RESOURCE_VETOED_MOVE_NOT_ENOUGH_RESOURCES_ON_DESTINATION,
++ MD_ERROR_WIN_CLUSTER_RESOURCE_VETOED_MOVE_NOT_ENOUGH_RESOURCES_ON_SOURCE,
++ MD_ERROR_WIN_CLUSTER_GROUP_QUEUED,
++ MD_ERROR_WIN_CLUSTER_RESOURCE_LOCKED_STATUS,
++ MD_ERROR_WIN_CLUSTER_SHARED_VOLUME_FAILOVER_NOT_ALLOWED,
++ MD_ERROR_WIN_CLUSTER_NODE_DRAIN_IN_PROGRESS,
++ MD_ERROR_WIN_CLUSTER_DISK_NOT_CONNECTED,
++ MD_ERROR_WIN_DISK_NOT_CSV_CAPABLE,
++ MD_ERROR_WIN_RESOURCE_NOT_IN_AVAILABLE_STORAGE,
++ MD_ERROR_WIN_CLUSTER_SHARED_VOLUME_REDIRECTED,
++ MD_ERROR_WIN_CLUSTER_SHARED_VOLUME_NOT_REDIRECTED,
++ MD_ERROR_WIN_CLUSTER_CANNOT_RETURN_PROPERTIES,
++ MD_ERROR_WIN_CLUSTER_RESOURCE_CONTAINS_UNSUPPORTED_DIFF_AREA_FOR_SHARED_VOLUMES,
++ MD_ERROR_WIN_CLUSTER_RESOURCE_IS_IN_MAINTENANCE_MODE,
++ MD_ERROR_WIN_CLUSTER_AFFINITY_CONFLICT,
++ MD_ERROR_WIN_CLUSTER_RESOURCE_IS_REPLICA_VIRTUAL_MACHINE,
++ MD_ERROR_WIN_CLUSTER_UPGRADE_INCOMPATIBLE_VERSIONS,
++ MD_ERROR_WIN_CLUSTER_UPGRADE_FIX_QUORUM_NOT_SUPPORTED,
++ MD_ERROR_WIN_CLUSTER_UPGRADE_RESTART_REQUIRED,
++ MD_ERROR_WIN_CLUSTER_UPGRADE_IN_PROGRESS,
++ MD_ERROR_WIN_CLUSTER_UPGRADE_INCOMPLETE,
++ MD_ERROR_WIN_CLUSTER_NODE_IN_GRACE_PERIOD,
++ MD_ERROR_WIN_CLUSTER_CSV_IO_PAUSE_TIMEOUT,
++ MD_ERROR_WIN_NODE_NOT_ACTIVE_CLUSTER_MEMBER,
++ MD_ERROR_WIN_CLUSTER_RESOURCE_NOT_MONITORED,
++ MD_ERROR_WIN_CLUSTER_RESOURCE_DOES_NOT_SUPPORT_UNMONITORED,
++ MD_ERROR_WIN_CLUSTER_RESOURCE_IS_REPLICATED,
++ MD_ERROR_WIN_CLUSTER_NODE_ISOLATED,
++ MD_ERROR_WIN_CLUSTER_NODE_QUARANTINED,
++ MD_ERROR_WIN_CLUSTER_DATABASE_UPDATE_CONDITION_FAILED,
++ MD_ERROR_WIN_CLUSTER_SPACE_DEGRADED,
++ MD_ERROR_WIN_CLUSTER_TOKEN_DELEGATION_NOT_SUPPORTED,
++ MD_ERROR_WIN_CLUSTER_CSV_INVALID_HANDLE,
++ MD_ERROR_WIN_CLUSTER_CSV_SUPPORTED_ONLY_ON_COORDINATOR,
++ MD_ERROR_WIN_GROUPSET_NOT_AVAILABLE,
++ MD_ERROR_WIN_GROUPSET_NOT_FOUND,
++ MD_ERROR_WIN_GROUPSET_CANT_PROVIDE,
++ MD_ERROR_WIN_CLUSTER_FAULT_DOMAIN_PARENT_NOT_FOUND,
++ MD_ERROR_WIN_CLUSTER_FAULT_DOMAIN_INVALID_HIERARCHY,
++ MD_ERROR_WIN_CLUSTER_FAULT_DOMAIN_FAILED_S2D_VALIDATION,
++ MD_ERROR_WIN_CLUSTER_FAULT_DOMAIN_S2D_CONNECTIVITY_LOSS,
++ MD_ERROR_WIN_CLUSTER_INVALID_INFRASTRUCTURE_FILESERVER_NAME,
++ MD_ERROR_WIN_CLUSTERSET_MANAGEMENT_CLUSTER_UNREACHABLE,
++ MD_ERROR_WIN_ENCRYPTION_FAILED,
++ MD_ERROR_WIN_DECRYPTION_FAILED,
++ MD_ERROR_WIN_FILE_ENCRYPTED,
++ MD_ERROR_WIN_NO_RECOVERY_POLICY,
++ MD_ERROR_WIN_NO_EFS,
++ MD_ERROR_WIN_WRONG_EFS,
++ MD_ERROR_WIN_NO_USER_KEYS,
++ MD_ERROR_WIN_FILE_NOT_ENCRYPTED,
++ MD_ERROR_WIN_NOT_EXPORT_FORMAT,
++ MD_ERROR_WIN_FILE_READ_ONLY,
++ MD_ERROR_WIN_DIR_EFS_DISALLOWED,
++ MD_ERROR_WIN_EFS_SERVER_NOT_TRUSTED,
++ MD_ERROR_WIN_BAD_RECOVERY_POLICY,
++ MD_ERROR_WIN_EFS_ALG_BLOB_TOO_BIG,
++ MD_ERROR_WIN_VOLUME_NOT_SUPPORT_EFS,
++ MD_ERROR_WIN_EFS_DISABLED,
++ MD_ERROR_WIN_EFS_VERSION_NOT_SUPPORT,
++ MD_ERROR_WIN_CS_ENCRYPTION_INVALID_SERVER_RESPONSE,
++ MD_ERROR_WIN_CS_ENCRYPTION_UNSUPPORTED_SERVER,
++ MD_ERROR_WIN_CS_ENCRYPTION_EXISTING_ENCRYPTED_FILE,
++ MD_ERROR_WIN_CS_ENCRYPTION_NEW_ENCRYPTED_FILE,
++ MD_ERROR_WIN_CS_ENCRYPTION_FILE_NOT_CSE,
++ MD_ERROR_WIN_ENCRYPTION_POLICY_DENIES_OPERATION,
++ MD_ERROR_WIN_WIP_ENCRYPTION_FAILED,
++ MD_ERROR_WIN_NO_BROWSER_SERVERS_FOUND,
++ MD_ERROR_WIN_CLUSTER_OBJECT_IS_CLUSTER_SET_VM,
++ MD_ERROR_WIN_LOG_SECTOR_INVALID,
++ MD_ERROR_WIN_LOG_SECTOR_PARITY_INVALID,
++ MD_ERROR_WIN_LOG_SECTOR_REMAPPED,
++ MD_ERROR_WIN_LOG_BLOCK_INCOMPLETE,
++ MD_ERROR_WIN_LOG_INVALID_RANGE,
++ MD_ERROR_WIN_LOG_BLOCKS_EXHAUSTED,
++ MD_ERROR_WIN_LOG_READ_CONTEXT_INVALID,
++ MD_ERROR_WIN_LOG_RESTART_INVALID,
++ MD_ERROR_WIN_LOG_BLOCK_VERSION,
++ MD_ERROR_WIN_LOG_BLOCK_INVALID,
++ MD_ERROR_WIN_LOG_READ_MODE_INVALID,
++ MD_ERROR_WIN_LOG_NO_RESTART,
++ MD_ERROR_WIN_LOG_METADATA_CORRUPT,
++ MD_ERROR_WIN_LOG_METADATA_INVALID,
++ MD_ERROR_WIN_LOG_METADATA_INCONSISTENT,
++ MD_ERROR_WIN_LOG_RESERVATION_INVALID,
++ MD_ERROR_WIN_LOG_CANT_DELETE,
++ MD_ERROR_WIN_LOG_CONTAINER_LIMIT_EXCEEDED,
++ MD_ERROR_WIN_LOG_START_OF_LOG,
++ MD_ERROR_WIN_LOG_POLICY_ALREADY_INSTALLED,
++ MD_ERROR_WIN_LOG_POLICY_NOT_INSTALLED,
++ MD_ERROR_WIN_LOG_POLICY_INVALID,
++ MD_ERROR_WIN_LOG_POLICY_CONFLICT,
++ MD_ERROR_WIN_LOG_PINNED_ARCHIVE_TAIL,
++ MD_ERROR_WIN_LOG_RECORD_NONEXISTENT,
++ MD_ERROR_WIN_LOG_RECORDS_RESERVED_INVALID,
++ MD_ERROR_WIN_LOG_SPACE_RESERVED_INVALID,
++ MD_ERROR_WIN_LOG_TAIL_INVALID,
++ MD_ERROR_WIN_LOG_FULL,
++ MD_ERROR_WIN_COULD_NOT_RESIZE_LOG,
++ MD_ERROR_WIN_LOG_MULTIPLEXED,
++ MD_ERROR_WIN_LOG_DEDICATED,
++ MD_ERROR_WIN_LOG_ARCHIVE_NOT_IN_PROGRESS,
++ MD_ERROR_WIN_LOG_ARCHIVE_IN_PROGRESS,
++ MD_ERROR_WIN_LOG_EPHEMERAL,
++ MD_ERROR_WIN_LOG_NOT_ENOUGH_CONTAINERS,
++ MD_ERROR_WIN_LOG_CLIENT_ALREADY_REGISTERED,
++ MD_ERROR_WIN_LOG_CLIENT_NOT_REGISTERED,
++ MD_ERROR_WIN_LOG_FULL_HANDLER_IN_PROGRESS,
++ MD_ERROR_WIN_LOG_CONTAINER_READ_FAILED,
++ MD_ERROR_WIN_LOG_CONTAINER_WRITE_FAILED,
++ MD_ERROR_WIN_LOG_CONTAINER_OPEN_FAILED,
++ MD_ERROR_WIN_LOG_CONTAINER_STATE_INVALID,
++ MD_ERROR_WIN_LOG_STATE_INVALID,
++ MD_ERROR_WIN_LOG_PINNED,
++ MD_ERROR_WIN_LOG_METADATA_FLUSH_FAILED,
++ MD_ERROR_WIN_LOG_INCONSISTENT_SECURITY,
++ MD_ERROR_WIN_LOG_APPENDED_FLUSH_FAILED,
++ MD_ERROR_WIN_LOG_PINNED_RESERVATION,
++ MD_ERROR_WIN_INVALID_TRANSACTION,
++ MD_ERROR_WIN_TRANSACTION_NOT_ACTIVE,
++ MD_ERROR_WIN_TRANSACTION_REQUEST_NOT_VALID,
++ MD_ERROR_WIN_TRANSACTION_NOT_REQUESTED,
++ MD_ERROR_WIN_TRANSACTION_ALREADY_ABORTED,
++ MD_ERROR_WIN_TRANSACTION_ALREADY_COMMITTED,
++ MD_ERROR_WIN_TM_INITIALIZATION_FAILED,
++ MD_ERROR_WIN_RESOURCEMANAGER_READ_ONLY,
++ MD_ERROR_WIN_TRANSACTION_NOT_JOINED,
++ MD_ERROR_WIN_TRANSACTION_SUPERIOR_EXISTS,
++ MD_ERROR_WIN_CRM_PROTOCOL_ALREADY_EXISTS,
++ MD_ERROR_WIN_TRANSACTION_PROPAGATION_FAILED,
++ MD_ERROR_WIN_CRM_PROTOCOL_NOT_FOUND,
++ MD_ERROR_WIN_TRANSACTION_INVALID_MARSHALL_BUFFER,
++ MD_ERROR_WIN_CURRENT_TRANSACTION_NOT_VALID,
++ MD_ERROR_WIN_TRANSACTION_NOT_FOUND,
++ MD_ERROR_WIN_RESOURCEMANAGER_NOT_FOUND,
++ MD_ERROR_WIN_ENLISTMENT_NOT_FOUND,
++ MD_ERROR_WIN_TRANSACTIONMANAGER_NOT_FOUND,
++ MD_ERROR_WIN_TRANSACTIONMANAGER_NOT_ONLINE,
++ MD_ERROR_WIN_TRANSACTIONMANAGER_RECOVERY_NAME_COLLISION,
++ MD_ERROR_WIN_TRANSACTION_NOT_ROOT,
++ MD_ERROR_WIN_TRANSACTION_OBJECT_EXPIRED,
++ MD_ERROR_WIN_TRANSACTION_RESPONSE_NOT_ENLISTED,
++ MD_ERROR_WIN_TRANSACTION_RECORD_TOO_LONG,
++ MD_ERROR_WIN_IMPLICIT_TRANSACTION_NOT_SUPPORTED,
++ MD_ERROR_WIN_TRANSACTION_INTEGRITY_VIOLATED,
++ MD_ERROR_WIN_TRANSACTIONMANAGER_IDENTITY_MISMATCH,
++ MD_ERROR_WIN_RM_CANNOT_BE_FROZEN_FOR_SNAPSHOT,
++ MD_ERROR_WIN_TRANSACTION_MUST_WRITETHROUGH,
++ MD_ERROR_WIN_TRANSACTION_NO_SUPERIOR,
++ MD_ERROR_WIN_HEURISTIC_DAMAGE_POSSIBLE,
++ MD_ERROR_WIN_TRANSACTIONAL_CONFLICT,
++ MD_ERROR_WIN_RM_NOT_ACTIVE,
++ MD_ERROR_WIN_RM_METADATA_CORRUPT,
++ MD_ERROR_WIN_DIRECTORY_NOT_RM,
++ MD_ERROR_WIN_TRANSACTIONS_UNSUPPORTED_REMOTE,
++ MD_ERROR_WIN_LOG_RESIZE_INVALID_SIZE,
++ MD_ERROR_WIN_OBJECT_NO_LONGER_EXISTS,
++ MD_ERROR_WIN_STREAM_MINIVERSION_NOT_FOUND,
++ MD_ERROR_WIN_STREAM_MINIVERSION_NOT_VALID,
++ MD_ERROR_WIN_MINIVERSION_INACCESSIBLE_FROM_SPECIFIED_TRANSACTION,
++ MD_ERROR_WIN_CANT_OPEN_MINIVERSION_WITH_MODIFY_INTENT,
++ MD_ERROR_WIN_CANT_CREATE_MORE_STREAM_MINIVERSIONS,
++ MD_ERROR_WIN_REMOTE_FILE_VERSION_MISMATCH,
++ MD_ERROR_WIN_HANDLE_NO_LONGER_VALID,
++ MD_ERROR_WIN_NO_TXF_METADATA,
++ MD_ERROR_WIN_LOG_CORRUPTION_DETECTED,
++ MD_ERROR_WIN_CANT_RECOVER_WITH_HANDLE_OPEN,
++ MD_ERROR_WIN_RM_DISCONNECTED,
++ MD_ERROR_WIN_ENLISTMENT_NOT_SUPERIOR,
++ MD_ERROR_WIN_RECOVERY_NOT_NEEDED,
++ MD_ERROR_WIN_RM_ALREADY_STARTED,
++ MD_ERROR_WIN_FILE_IDENTITY_NOT_PERSISTENT,
++ MD_ERROR_WIN_CANT_BREAK_TRANSACTIONAL_DEPENDENCY,
++ MD_ERROR_WIN_CANT_CROSS_RM_BOUNDARY,
++ MD_ERROR_WIN_TXF_DIR_NOT_EMPTY,
++ MD_ERROR_WIN_INDOUBT_TRANSACTIONS_EXIST,
++ MD_ERROR_WIN_TM_VOLATILE,
++ MD_ERROR_WIN_ROLLBACK_TIMER_EXPIRED,
++ MD_ERROR_WIN_TXF_ATTRIBUTE_CORRUPT,
++ MD_ERROR_WIN_EFS_NOT_ALLOWED_IN_TRANSACTION,
++ MD_ERROR_WIN_TRANSACTIONAL_OPEN_NOT_ALLOWED,
++ MD_ERROR_WIN_LOG_GROWTH_FAILED,
++ MD_ERROR_WIN_TRANSACTED_MAPPING_UNSUPPORTED_REMOTE,
++ MD_ERROR_WIN_TXF_METADATA_ALREADY_PRESENT,
++ MD_ERROR_WIN_TRANSACTION_SCOPE_CALLBACKS_NOT_SET,
++ MD_ERROR_WIN_TRANSACTION_REQUIRED_PROMOTION,
++ MD_ERROR_WIN_CANNOT_EXECUTE_FILE_IN_TRANSACTION,
++ MD_ERROR_WIN_TRANSACTIONS_NOT_FROZEN,
++ MD_ERROR_WIN_TRANSACTION_FREEZE_IN_PROGRESS,
++ MD_ERROR_WIN_NOT_SNAPSHOT_VOLUME,
++ MD_ERROR_WIN_NO_SAVEPOINT_WITH_OPEN_FILES,
++ MD_ERROR_WIN_DATA_LOST_REPAIR,
++ MD_ERROR_WIN_SPARSE_NOT_ALLOWED_IN_TRANSACTION,
++ MD_ERROR_WIN_TM_IDENTITY_MISMATCH,
++ MD_ERROR_WIN_FLOATED_SECTION,
++ MD_ERROR_WIN_CANNOT_ACCEPT_TRANSACTED_WORK,
++ MD_ERROR_WIN_CANNOT_ABORT_TRANSACTIONS,
++ MD_ERROR_WIN_BAD_CLUSTERS,
++ MD_ERROR_WIN_COMPRESSION_NOT_ALLOWED_IN_TRANSACTION,
++ MD_ERROR_WIN_VOLUME_DIRTY,
++ MD_ERROR_WIN_NO_LINK_TRACKING_IN_TRANSACTION,
++ MD_ERROR_WIN_OPERATION_NOT_SUPPORTED_IN_TRANSACTION,
++ MD_ERROR_WIN_EXPIRED_HANDLE,
++ MD_ERROR_WIN_TRANSACTION_NOT_ENLISTED,
++ MD_ERROR_WIN_CTX_WINSTATION_NAME_INVALID,
++ MD_ERROR_WIN_CTX_INVALID_PD,
++ MD_ERROR_WIN_CTX_PD_NOT_FOUND,
++ MD_ERROR_WIN_CTX_WD_NOT_FOUND,
++ MD_ERROR_WIN_CTX_CANNOT_MAKE_EVENTLOG_ENTRY,
++ MD_ERROR_WIN_CTX_SERVICE_NAME_COLLISION,
++ MD_ERROR_WIN_CTX_CLOSE_PENDING,
++ MD_ERROR_WIN_CTX_NO_OUTBUF,
++ MD_ERROR_WIN_CTX_MODEM_INF_NOT_FOUND,
++ MD_ERROR_WIN_CTX_INVALID_MODEMNAME,
++ MD_ERROR_WIN_CTX_MODEM_RESPONSE_ERROR,
++ MD_ERROR_WIN_CTX_MODEM_RESPONSE_TIMEOUT,
++ MD_ERROR_WIN_CTX_MODEM_RESPONSE_NO_CARRIER,
++ MD_ERROR_WIN_CTX_MODEM_RESPONSE_NO_DIALTONE,
++ MD_ERROR_WIN_CTX_MODEM_RESPONSE_BUSY,
++ MD_ERROR_WIN_CTX_MODEM_RESPONSE_VOICE,
++ MD_ERROR_WIN_CTX_TD_ERROR,
++ MD_ERROR_WIN_CTX_WINSTATION_NOT_FOUND,
++ MD_ERROR_WIN_CTX_WINSTATION_ALREADY_EXISTS,
++ MD_ERROR_WIN_CTX_WINSTATION_BUSY,
++ MD_ERROR_WIN_CTX_BAD_VIDEO_MODE,
++ MD_ERROR_WIN_CTX_GRAPHICS_INVALID,
++ MD_ERROR_WIN_CTX_LOGON_DISABLED,
++ MD_ERROR_WIN_CTX_NOT_CONSOLE,
++ MD_ERROR_WIN_CTX_CLIENT_QUERY_TIMEOUT,
++ MD_ERROR_WIN_CTX_CONSOLE_DISCONNECT,
++ MD_ERROR_WIN_CTX_CONSOLE_CONNECT,
++ MD_ERROR_WIN_CTX_SHADOW_DENIED,
++ MD_ERROR_WIN_CTX_WINSTATION_ACCESS_DENIED,
++ MD_ERROR_WIN_CTX_INVALID_WD,
++ MD_ERROR_WIN_CTX_SHADOW_INVALID,
++ MD_ERROR_WIN_CTX_SHADOW_DISABLED,
++ MD_ERROR_WIN_CTX_CLIENT_LICENSE_IN_USE,
++ MD_ERROR_WIN_CTX_CLIENT_LICENSE_NOT_SET,
++ MD_ERROR_WIN_CTX_LICENSE_NOT_AVAILABLE,
++ MD_ERROR_WIN_CTX_LICENSE_CLIENT_INVALID,
++ MD_ERROR_WIN_CTX_LICENSE_EXPIRED,
++ MD_ERROR_WIN_CTX_SHADOW_NOT_RUNNING,
++ MD_ERROR_WIN_CTX_SHADOW_ENDED_BY_MODE_CHANGE,
++ MD_ERROR_WIN_ACTIVATION_COUNT_EXCEEDED,
++ MD_ERROR_WIN_CTX_WINSTATIONS_DISABLED,
++ MD_ERROR_WIN_CTX_ENCRYPTION_LEVEL_REQUIRED,
++ MD_ERROR_WIN_CTX_SESSION_IN_USE,
++ MD_ERROR_WIN_CTX_NO_FORCE_LOGOFF,
++ MD_ERROR_WIN_CTX_ACCOUNT_RESTRICTION,
++ MD_ERROR_WIN_RDP_PROTOCOL_ERROR,
++ MD_ERROR_WIN_CTX_CDM_CONNECT,
++ MD_ERROR_WIN_CTX_CDM_DISCONNECT,
++ MD_ERROR_WIN_CTX_SECURITY_LAYER_ERROR,
++ MD_ERROR_WIN_TS_INCOMPATIBLE_SESSIONS,
++ MD_ERROR_WIN_TS_VIDEO_SUBSYSTEM_ERROR,
++ MD_ERROR_WIN_DS_NOT_INSTALLED,
++ MD_ERROR_WIN_DS_MEMBERSHIP_EVALUATED_LOCALLY,
++ MD_ERROR_WIN_DS_NO_ATTRIBUTE_OR_VALUE,
++ MD_ERROR_WIN_DS_INVALID_ATTRIBUTE_SYNTAX,
++ MD_ERROR_WIN_DS_ATTRIBUTE_TYPE_UNDEFINED,
++ MD_ERROR_WIN_DS_ATTRIBUTE_OR_VALUE_EXISTS,
++ MD_ERROR_WIN_DS_BUSY,
++ MD_ERROR_WIN_DS_UNAVAILABLE,
++ MD_ERROR_WIN_DS_NO_RIDS_ALLOCATED,
++ MD_ERROR_WIN_DS_NO_MORE_RIDS,
++ MD_ERROR_WIN_DS_INCORRECT_ROLE_OWNER,
++ MD_ERROR_WIN_DS_RIDMGR_INIT_ERROR,
++ MD_ERROR_WIN_DS_OBJ_CLASS_VIOLATION,
++ MD_ERROR_WIN_DS_CANT_ON_NON_LEAF,
++ MD_ERROR_WIN_DS_CANT_ON_RDN,
++ MD_ERROR_WIN_DS_CANT_MOD_OBJ_CLASS,
++ MD_ERROR_WIN_DS_CROSS_DOM_MOVE_ERROR,
++ MD_ERROR_WIN_DS_GC_NOT_AVAILABLE,
++ MD_ERROR_WIN_SHARED_POLICY,
++ MD_ERROR_WIN_POLICY_OBJECT_NOT_FOUND,
++ MD_ERROR_WIN_POLICY_ONLY_IN_DS,
++ MD_ERROR_WIN_PROMOTION_ACTIVE,
++ MD_ERROR_WIN_NO_PROMOTION_ACTIVE,
++ MD_ERROR_WIN_DS_OPERATIONS_ERROR,
++ MD_ERROR_WIN_DS_PROTOCOL_ERROR,
++ MD_ERROR_WIN_DS_TIMELIMIT_EXCEEDED,
++ MD_ERROR_WIN_DS_SIZELIMIT_EXCEEDED,
++ MD_ERROR_WIN_DS_ADMIN_LIMIT_EXCEEDED,
++ MD_ERROR_WIN_DS_COMPARE_FALSE,
++ MD_ERROR_WIN_DS_COMPARE_TRUE,
++ MD_ERROR_WIN_DS_AUTH_METHOD_NOT_SUPPORTED,
++ MD_ERROR_WIN_DS_STRONG_AUTH_REQUIRED,
++ MD_ERROR_WIN_DS_INAPPROPRIATE_AUTH,
++ MD_ERROR_WIN_DS_AUTH_UNKNOWN,
++ MD_ERROR_WIN_DS_REFERRAL,
++ MD_ERROR_WIN_DS_UNAVAILABLE_CRIT_EXTENSION,
++ MD_ERROR_WIN_DS_CONFIDENTIALITY_REQUIRED,
++ MD_ERROR_WIN_DS_INAPPROPRIATE_MATCHING,
++ MD_ERROR_WIN_DS_CONSTRAINT_VIOLATION,
++ MD_ERROR_WIN_DS_NO_SUCH_OBJECT,
++ MD_ERROR_WIN_DS_ALIAS_PROBLEM,
++ MD_ERROR_WIN_DS_INVALID_DN_SYNTAX,
++ MD_ERROR_WIN_DS_IS_LEAF,
++ MD_ERROR_WIN_DS_ALIAS_DEREF_PROBLEM,
++ MD_ERROR_WIN_DS_UNWILLING_TO_PERFORM,
++ MD_ERROR_WIN_DS_LOOP_DETECT,
++ MD_ERROR_WIN_DS_NAMING_VIOLATION,
++ MD_ERROR_WIN_DS_OBJECT_RESULTS_TOO_LARGE,
++ MD_ERROR_WIN_DS_AFFECTS_MULTIPLE_DSAS,
++ MD_ERROR_WIN_DS_SERVER_DOWN,
++ MD_ERROR_WIN_DS_LOCAL_ERROR,
++ MD_ERROR_WIN_DS_ENCODING_ERROR,
++ MD_ERROR_WIN_DS_DECODING_ERROR,
++ MD_ERROR_WIN_DS_FILTER_UNKNOWN,
++ MD_ERROR_WIN_DS_PARAM_ERROR,
++ MD_ERROR_WIN_DS_NOT_SUPPORTED,
++ MD_ERROR_WIN_DS_NO_RESULTS_RETURNED,
++ MD_ERROR_WIN_DS_CONTROL_NOT_FOUND,
++ MD_ERROR_WIN_DS_CLIENT_LOOP,
++ MD_ERROR_WIN_DS_REFERRAL_LIMIT_EXCEEDED,
++ MD_ERROR_WIN_DS_SORT_CONTROL_MISSING,
++ MD_ERROR_WIN_DS_OFFSET_RANGE_ERROR,
++ MD_ERROR_WIN_DS_RIDMGR_DISABLED,
++ MD_ERROR_WIN_DS_ROOT_MUST_BE_NC,
++ MD_ERROR_WIN_DS_ADD_REPLICA_INHIBITED,
++ MD_ERROR_WIN_DS_ATT_NOT_DEF_IN_SCHEMA,
++ MD_ERROR_WIN_DS_MAX_OBJ_SIZE_EXCEEDED,
++ MD_ERROR_WIN_DS_OBJ_STRING_NAME_EXISTS,
++ MD_ERROR_WIN_DS_NO_RDN_DEFINED_IN_SCHEMA,
++ MD_ERROR_WIN_DS_RDN_DOESNT_MATCH_SCHEMA,
++ MD_ERROR_WIN_DS_NO_REQUESTED_ATTS_FOUND,
++ MD_ERROR_WIN_DS_USER_BUFFER_TO_SMALL,
++ MD_ERROR_WIN_DS_ATT_IS_NOT_ON_OBJ,
++ MD_ERROR_WIN_DS_ILLEGAL_MOD_OPERATION,
++ MD_ERROR_WIN_DS_OBJ_TOO_LARGE,
++ MD_ERROR_WIN_DS_BAD_INSTANCE_TYPE,
++ MD_ERROR_WIN_DS_MASTERDSA_REQUIRED,
++ MD_ERROR_WIN_DS_OBJECT_CLASS_REQUIRED,
++ MD_ERROR_WIN_DS_MISSING_REQUIRED_ATT,
++ MD_ERROR_WIN_DS_ATT_NOT_DEF_FOR_CLASS,
++ MD_ERROR_WIN_DS_ATT_ALREADY_EXISTS,
++ MD_ERROR_WIN_DS_CANT_ADD_ATT_VALUES,
++ MD_ERROR_WIN_DS_SINGLE_VALUE_CONSTRAINT,
++ MD_ERROR_WIN_DS_RANGE_CONSTRAINT,
++ MD_ERROR_WIN_DS_ATT_VAL_ALREADY_EXISTS,
++ MD_ERROR_WIN_DS_CANT_REM_MISSING_ATT,
++ MD_ERROR_WIN_DS_CANT_REM_MISSING_ATT_VAL,
++ MD_ERROR_WIN_DS_ROOT_CANT_BE_SUBREF,
++ MD_ERROR_WIN_DS_NO_CHAINING,
++ MD_ERROR_WIN_DS_NO_CHAINED_EVAL,
++ MD_ERROR_WIN_DS_NO_PARENT_OBJECT,
++ MD_ERROR_WIN_DS_PARENT_IS_AN_ALIAS,
++ MD_ERROR_WIN_DS_CANT_MIX_MASTER_AND_REPS,
++ MD_ERROR_WIN_DS_CHILDREN_EXIST,
++ MD_ERROR_WIN_DS_OBJ_NOT_FOUND,
++ MD_ERROR_WIN_DS_ALIASED_OBJ_MISSING,
++ MD_ERROR_WIN_DS_BAD_NAME_SYNTAX,
++ MD_ERROR_WIN_DS_ALIAS_POINTS_TO_ALIAS,
++ MD_ERROR_WIN_DS_CANT_DEREF_ALIAS,
++ MD_ERROR_WIN_DS_OUT_OF_SCOPE,
++ MD_ERROR_WIN_DS_OBJECT_BEING_REMOVED,
++ MD_ERROR_WIN_DS_CANT_DELETE_DSA_OBJ,
++ MD_ERROR_WIN_DS_GENERIC_ERROR,
++ MD_ERROR_WIN_DS_DSA_MUST_BE_INT_MASTER,
++ MD_ERROR_WIN_DS_CLASS_NOT_DSA,
++ MD_ERROR_WIN_DS_INSUFF_ACCESS_RIGHTS,
++ MD_ERROR_WIN_DS_ILLEGAL_SUPERIOR,
++ MD_ERROR_WIN_DS_ATTRIBUTE_OWNED_BY_SAM,
++ MD_ERROR_WIN_DS_NAME_TOO_MANY_PARTS,
++ MD_ERROR_WIN_DS_NAME_TOO_LONG,
++ MD_ERROR_WIN_DS_NAME_VALUE_TOO_LONG,
++ MD_ERROR_WIN_DS_NAME_UNPARSEABLE,
++ MD_ERROR_WIN_DS_NAME_TYPE_UNKNOWN,
++ MD_ERROR_WIN_DS_NOT_AN_OBJECT,
++ MD_ERROR_WIN_DS_SEC_DESC_TOO_SHORT,
++ MD_ERROR_WIN_DS_SEC_DESC_INVALID,
++ MD_ERROR_WIN_DS_NO_DELETED_NAME,
++ MD_ERROR_WIN_DS_SUBREF_MUST_HAVE_PARENT,
++ MD_ERROR_WIN_DS_NCNAME_MUST_BE_NC,
++ MD_ERROR_WIN_DS_CANT_ADD_SYSTEM_ONLY,
++ MD_ERROR_WIN_DS_CLASS_MUST_BE_CONCRETE,
++ MD_ERROR_WIN_DS_INVALID_DMD,
++ MD_ERROR_WIN_DS_OBJ_GUID_EXISTS,
++ MD_ERROR_WIN_DS_NOT_ON_BACKLINK,
++ MD_ERROR_WIN_DS_NO_CROSSREF_FOR_NC,
++ MD_ERROR_WIN_DS_SHUTTING_DOWN,
++ MD_ERROR_WIN_DS_UNKNOWN_OPERATION,
++ MD_ERROR_WIN_DS_INVALID_ROLE_OWNER,
++ MD_ERROR_WIN_DS_COULDNT_CONTACT_FSMO,
++ MD_ERROR_WIN_DS_CROSS_NC_DN_RENAME,
++ MD_ERROR_WIN_DS_CANT_MOD_SYSTEM_ONLY,
++ MD_ERROR_WIN_DS_REPLICATOR_ONLY,
++ MD_ERROR_WIN_DS_OBJ_CLASS_NOT_DEFINED,
++ MD_ERROR_WIN_DS_OBJ_CLASS_NOT_SUBCLASS,
++ MD_ERROR_WIN_DS_NAME_REFERENCE_INVALID,
++ MD_ERROR_WIN_DS_CROSS_REF_EXISTS,
++ MD_ERROR_WIN_DS_CANT_DEL_MASTER_CROSSREF,
++ MD_ERROR_WIN_DS_SUBTREE_NOTIFY_NOT_NC_HEAD,
++ MD_ERROR_WIN_DS_NOTIFY_FILTER_TOO_COMPLEX,
++ MD_ERROR_WIN_DS_DUP_RDN,
++ MD_ERROR_WIN_DS_DUP_OID,
++ MD_ERROR_WIN_DS_DUP_MAPI_ID,
++ MD_ERROR_WIN_DS_DUP_SCHEMA_ID_GUID,
++ MD_ERROR_WIN_DS_DUP_LDAP_DISPLAY_NAME,
++ MD_ERROR_WIN_DS_SEMANTIC_ATT_TEST,
++ MD_ERROR_WIN_DS_SYNTAX_MISMATCH,
++ MD_ERROR_WIN_DS_EXISTS_IN_MUST_HAVE,
++ MD_ERROR_WIN_DS_EXISTS_IN_MAY_HAVE,
++ MD_ERROR_WIN_DS_NONEXISTENT_MAY_HAVE,
++ MD_ERROR_WIN_DS_NONEXISTENT_MUST_HAVE,
++ MD_ERROR_WIN_DS_AUX_CLS_TEST_FAIL,
++ MD_ERROR_WIN_DS_NONEXISTENT_POSS_SUP,
++ MD_ERROR_WIN_DS_SUB_CLS_TEST_FAIL,
++ MD_ERROR_WIN_DS_BAD_RDN_ATT_ID_SYNTAX,
++ MD_ERROR_WIN_DS_EXISTS_IN_AUX_CLS,
++ MD_ERROR_WIN_DS_EXISTS_IN_SUB_CLS,
++ MD_ERROR_WIN_DS_EXISTS_IN_POSS_SUP,
++ MD_ERROR_WIN_DS_RECALCSCHEMA_FAILED,
++ MD_ERROR_WIN_DS_TREE_DELETE_NOT_FINISHED,
++ MD_ERROR_WIN_DS_CANT_DELETE,
++ MD_ERROR_WIN_DS_ATT_SCHEMA_REQ_ID,
++ MD_ERROR_WIN_DS_BAD_ATT_SCHEMA_SYNTAX,
++ MD_ERROR_WIN_DS_CANT_CACHE_ATT,
++ MD_ERROR_WIN_DS_CANT_CACHE_CLASS,
++ MD_ERROR_WIN_DS_CANT_REMOVE_ATT_CACHE,
++ MD_ERROR_WIN_DS_CANT_REMOVE_CLASS_CACHE,
++ MD_ERROR_WIN_DS_CANT_RETRIEVE_DN,
++ MD_ERROR_WIN_DS_MISSING_SUPREF,
++ MD_ERROR_WIN_DS_CANT_RETRIEVE_INSTANCE,
++ MD_ERROR_WIN_DS_CODE_INCONSISTENCY,
++ MD_ERROR_WIN_DS_DATABASE_ERROR,
++ MD_ERROR_WIN_DS_GOVERNSID_MISSING,
++ MD_ERROR_WIN_DS_MISSING_EXPECTED_ATT,
++ MD_ERROR_WIN_DS_NCNAME_MISSING_CR_REF,
++ MD_ERROR_WIN_DS_SECURITY_CHECKING_ERROR,
++ MD_ERROR_WIN_DS_SCHEMA_NOT_LOADED,
++ MD_ERROR_WIN_DS_SCHEMA_ALLOC_FAILED,
++ MD_ERROR_WIN_DS_ATT_SCHEMA_REQ_SYNTAX,
++ MD_ERROR_WIN_DS_GCVERIFY_ERROR,
++ MD_ERROR_WIN_DS_DRA_SCHEMA_MISMATCH,
++ MD_ERROR_WIN_DS_CANT_FIND_DSA_OBJ,
++ MD_ERROR_WIN_DS_CANT_FIND_EXPECTED_NC,
++ MD_ERROR_WIN_DS_CANT_FIND_NC_IN_CACHE,
++ MD_ERROR_WIN_DS_CANT_RETRIEVE_CHILD,
++ MD_ERROR_WIN_DS_SECURITY_ILLEGAL_MODIFY,
++ MD_ERROR_WIN_DS_CANT_REPLACE_HIDDEN_REC,
++ MD_ERROR_WIN_DS_BAD_HIERARCHY_FILE,
++ MD_ERROR_WIN_DS_BUILD_HIERARCHY_TABLE_FAILED,
++ MD_ERROR_WIN_DS_CONFIG_PARAM_MISSING,
++ MD_ERROR_WIN_DS_COUNTING_AB_INDICES_FAILED,
++ MD_ERROR_WIN_DS_HIERARCHY_TABLE_MALLOC_FAILED,
++ MD_ERROR_WIN_DS_INTERNAL_FAILURE,
++ MD_ERROR_WIN_DS_UNKNOWN_ERROR,
++ MD_ERROR_WIN_DS_ROOT_REQUIRES_CLASS_TOP,
++ MD_ERROR_WIN_DS_REFUSING_FSMO_ROLES,
++ MD_ERROR_WIN_DS_MISSING_FSMO_SETTINGS,
++ MD_ERROR_WIN_DS_UNABLE_TO_SURRENDER_ROLES,
++ MD_ERROR_WIN_DS_DRA_GENERIC,
++ MD_ERROR_WIN_DS_DRA_INVALID_PARAMETER,
++ MD_ERROR_WIN_DS_DRA_BUSY,
++ MD_ERROR_WIN_DS_DRA_BAD_DN,
++ MD_ERROR_WIN_DS_DRA_BAD_NC,
++ MD_ERROR_WIN_DS_DRA_DN_EXISTS,
++ MD_ERROR_WIN_DS_DRA_INTERNAL_ERROR,
++ MD_ERROR_WIN_DS_DRA_INCONSISTENT_DIT,
++ MD_ERROR_WIN_DS_DRA_CONNECTION_FAILED,
++ MD_ERROR_WIN_DS_DRA_BAD_INSTANCE_TYPE,
++ MD_ERROR_WIN_DS_DRA_OUT_OF_MEM,
++ MD_ERROR_WIN_DS_DRA_MAIL_PROBLEM,
++ MD_ERROR_WIN_DS_DRA_REF_ALREADY_EXISTS,
++ MD_ERROR_WIN_DS_DRA_REF_NOT_FOUND,
++ MD_ERROR_WIN_DS_DRA_OBJ_IS_REP_SOURCE,
++ MD_ERROR_WIN_DS_DRA_DB_ERROR,
++ MD_ERROR_WIN_DS_DRA_NO_REPLICA,
++ MD_ERROR_WIN_DS_DRA_ACCESS_DENIED,
++ MD_ERROR_WIN_DS_DRA_NOT_SUPPORTED,
++ MD_ERROR_WIN_DS_DRA_RPC_CANCELLED,
++ MD_ERROR_WIN_DS_DRA_SOURCE_DISABLED,
++ MD_ERROR_WIN_DS_DRA_SINK_DISABLED,
++ MD_ERROR_WIN_DS_DRA_NAME_COLLISION,
++ MD_ERROR_WIN_DS_DRA_SOURCE_REINSTALLED,
++ MD_ERROR_WIN_DS_DRA_MISSING_PARENT,
++ MD_ERROR_WIN_DS_DRA_PREEMPTED,
++ MD_ERROR_WIN_DS_DRA_ABANDON_SYNC,
++ MD_ERROR_WIN_DS_DRA_SHUTDOWN,
++ MD_ERROR_WIN_DS_DRA_INCOMPATIBLE_PARTIAL_SET,
++ MD_ERROR_WIN_DS_DRA_SOURCE_IS_PARTIAL_REPLICA,
++ MD_ERROR_WIN_DS_DRA_EXTN_CONNECTION_FAILED,
++ MD_ERROR_WIN_DS_INSTALL_SCHEMA_MISMATCH,
++ MD_ERROR_WIN_DS_DUP_LINK_ID,
++ MD_ERROR_WIN_DS_NAME_ERROR_RESOLVING,
++ MD_ERROR_WIN_DS_NAME_ERROR_NOT_FOUND,
++ MD_ERROR_WIN_DS_NAME_ERROR_NOT_UNIQUE,
++ MD_ERROR_WIN_DS_NAME_ERROR_NO_MAPPING,
++ MD_ERROR_WIN_DS_NAME_ERROR_DOMAIN_ONLY,
++ MD_ERROR_WIN_DS_NAME_ERROR_NO_SYNTACTICAL_MAPPING,
++ MD_ERROR_WIN_DS_CONSTRUCTED_ATT_MOD,
++ MD_ERROR_WIN_DS_WRONG_OM_OBJ_CLASS,
++ MD_ERROR_WIN_DS_DRA_REPL_PENDING,
++ MD_ERROR_WIN_DS_DS_REQUIRED,
++ MD_ERROR_WIN_DS_INVALID_LDAP_DISPLAY_NAME,
++ MD_ERROR_WIN_DS_NON_BASE_SEARCH,
++ MD_ERROR_WIN_DS_CANT_RETRIEVE_ATTS,
++ MD_ERROR_WIN_DS_BACKLINK_WITHOUT_LINK,
++ MD_ERROR_WIN_DS_EPOCH_MISMATCH,
++ MD_ERROR_WIN_DS_SRC_NAME_MISMATCH,
++ MD_ERROR_WIN_DS_SRC_AND_DST_NC_IDENTICAL,
++ MD_ERROR_WIN_DS_DST_NC_MISMATCH,
++ MD_ERROR_WIN_DS_NOT_AUTHORITIVE_FOR_DST_NC,
++ MD_ERROR_WIN_DS_SRC_GUID_MISMATCH,
++ MD_ERROR_WIN_DS_CANT_MOVE_DELETED_OBJECT,
++ MD_ERROR_WIN_DS_PDC_OPERATION_IN_PROGRESS,
++ MD_ERROR_WIN_DS_CROSS_DOMAIN_CLEANUP_REQD,
++ MD_ERROR_WIN_DS_ILLEGAL_XDOM_MOVE_OPERATION,
++ MD_ERROR_WIN_DS_CANT_WITH_ACCT_GROUP_MEMBERSHPS,
++ MD_ERROR_WIN_DS_NC_MUST_HAVE_NC_PARENT,
++ MD_ERROR_WIN_DS_CR_IMPOSSIBLE_TO_VALIDATE,
++ MD_ERROR_WIN_DS_DST_DOMAIN_NOT_NATIVE,
++ MD_ERROR_WIN_DS_MISSING_INFRASTRUCTURE_CONTAINER,
++ MD_ERROR_WIN_DS_CANT_MOVE_ACCOUNT_GROUP,
++ MD_ERROR_WIN_DS_CANT_MOVE_RESOURCE_GROUP,
++ MD_ERROR_WIN_DS_INVALID_SEARCH_FLAG,
++ MD_ERROR_WIN_DS_NO_TREE_DELETE_ABOVE_NC,
++ MD_ERROR_WIN_DS_COULDNT_LOCK_TREE_FOR_DELETE,
++ MD_ERROR_WIN_DS_COULDNT_IDENTIFY_OBJECTS_FOR_TREE_DELETE,
++ MD_ERROR_WIN_DS_SAM_INIT_FAILURE,
++ MD_ERROR_WIN_DS_SENSITIVE_GROUP_VIOLATION,
++ MD_ERROR_WIN_DS_CANT_MOD_PRIMARYGROUPID,
++ MD_ERROR_WIN_DS_ILLEGAL_BASE_SCHEMA_MOD,
++ MD_ERROR_WIN_DS_NONSAFE_SCHEMA_CHANGE,
++ MD_ERROR_WIN_DS_SCHEMA_UPDATE_DISALLOWED,
++ MD_ERROR_WIN_DS_CANT_CREATE_UNDER_SCHEMA,
++ MD_ERROR_WIN_DS_INSTALL_NO_SRC_SCH_VERSION,
++ MD_ERROR_WIN_DS_INSTALL_NO_SCH_VERSION_IN_INIFILE,
++ MD_ERROR_WIN_DS_INVALID_GROUP_TYPE,
++ MD_ERROR_WIN_DS_NO_NEST_GLOBALGROUP_IN_MIXEDDOMAIN,
++ MD_ERROR_WIN_DS_NO_NEST_LOCALGROUP_IN_MIXEDDOMAIN,
++ MD_ERROR_WIN_DS_GLOBAL_CANT_HAVE_LOCAL_MEMBER,
++ MD_ERROR_WIN_DS_GLOBAL_CANT_HAVE_UNIVERSAL_MEMBER,
++ MD_ERROR_WIN_DS_UNIVERSAL_CANT_HAVE_LOCAL_MEMBER,
++ MD_ERROR_WIN_DS_GLOBAL_CANT_HAVE_CROSSDOMAIN_MEMBER,
++ MD_ERROR_WIN_DS_LOCAL_CANT_HAVE_CROSSDOMAIN_LOCAL_MEMBER,
++ MD_ERROR_WIN_DS_HAVE_PRIMARY_MEMBERS,
++ MD_ERROR_WIN_DS_STRING_SD_CONVERSION_FAILED,
++ MD_ERROR_WIN_DS_NAMING_MASTER_GC,
++ MD_ERROR_WIN_DS_DNS_LOOKUP_FAILURE,
++ MD_ERROR_WIN_DS_COULDNT_UPDATE_SPNS,
++ MD_ERROR_WIN_DS_CANT_RETRIEVE_SD,
++ MD_ERROR_WIN_DS_KEY_NOT_UNIQUE,
++ MD_ERROR_WIN_DS_WRONG_LINKED_ATT_SYNTAX,
++ MD_ERROR_WIN_DS_SAM_NEED_BOOTKEY_PASSWORD,
++ MD_ERROR_WIN_DS_SAM_NEED_BOOTKEY_FLOPPY,
++ MD_ERROR_WIN_DS_CANT_START,
++ MD_ERROR_WIN_DS_INIT_FAILURE,
++ MD_ERROR_WIN_DS_NO_PKT_PRIVACY_ON_CONNECTION,
++ MD_ERROR_WIN_DS_SOURCE_DOMAIN_IN_FOREST,
++ MD_ERROR_WIN_DS_DESTINATION_DOMAIN_NOT_IN_FOREST,
++ MD_ERROR_WIN_DS_DESTINATION_AUDITING_NOT_ENABLED,
++ MD_ERROR_WIN_DS_CANT_FIND_DC_FOR_SRC_DOMAIN,
++ MD_ERROR_WIN_DS_SRC_OBJ_NOT_GROUP_OR_USER,
++ MD_ERROR_WIN_DS_SRC_SID_EXISTS_IN_FOREST,
++ MD_ERROR_WIN_DS_SRC_AND_DST_OBJECT_CLASS_MISMATCH,
++ MD_ERROR_WIN_SAM_INIT_FAILURE,
++ MD_ERROR_WIN_DS_DRA_SCHEMA_INFO_SHIP,
++ MD_ERROR_WIN_DS_DRA_SCHEMA_CONFLICT,
++ MD_ERROR_WIN_DS_DRA_EARLIER_SCHEMA_CONFLICT,
++ MD_ERROR_WIN_DS_DRA_OBJ_NC_MISMATCH,
++ MD_ERROR_WIN_DS_NC_STILL_HAS_DSAS,
++ MD_ERROR_WIN_DS_GC_REQUIRED,
++ MD_ERROR_WIN_DS_LOCAL_MEMBER_OF_LOCAL_ONLY,
++ MD_ERROR_WIN_DS_NO_FPO_IN_UNIVERSAL_GROUPS,
++ MD_ERROR_WIN_DS_CANT_ADD_TO_GC,
++ MD_ERROR_WIN_DS_NO_CHECKPOINT_WITH_PDC,
++ MD_ERROR_WIN_DS_SOURCE_AUDITING_NOT_ENABLED,
++ MD_ERROR_WIN_DS_CANT_CREATE_IN_NONDOMAIN_NC,
++ MD_ERROR_WIN_DS_INVALID_NAME_FOR_SPN,
++ MD_ERROR_WIN_DS_FILTER_USES_CONTRUCTED_ATTRS,
++ MD_ERROR_WIN_DS_UNICODEPWD_NOT_IN_QUOTES,
++ MD_ERROR_WIN_DS_MACHINE_ACCOUNT_QUOTA_EXCEEDED,
++ MD_ERROR_WIN_DS_MUST_BE_RUN_ON_DST_DC,
++ MD_ERROR_WIN_DS_SRC_DC_MUST_BE_SP4_OR_GREATER,
++ MD_ERROR_WIN_DS_CANT_TREE_DELETE_CRITICAL_OBJ,
++ MD_ERROR_WIN_DS_INIT_FAILURE_CONSOLE,
++ MD_ERROR_WIN_DS_SAM_INIT_FAILURE_CONSOLE,
++ MD_ERROR_WIN_DS_FOREST_VERSION_TOO_HIGH,
++ MD_ERROR_WIN_DS_DOMAIN_VERSION_TOO_HIGH,
++ MD_ERROR_WIN_DS_FOREST_VERSION_TOO_LOW,
++ MD_ERROR_WIN_DS_DOMAIN_VERSION_TOO_LOW,
++ MD_ERROR_WIN_DS_INCOMPATIBLE_VERSION,
++ MD_ERROR_WIN_DS_LOW_DSA_VERSION,
++ MD_ERROR_WIN_DS_NO_BEHAVIOR_VERSION_IN_MIXEDDOMAIN,
++ MD_ERROR_WIN_DS_NOT_SUPPORTED_SORT_ORDER,
++ MD_ERROR_WIN_DS_NAME_NOT_UNIQUE,
++ MD_ERROR_WIN_DS_MACHINE_ACCOUNT_CREATED_PRENT4,
++ MD_ERROR_WIN_DS_OUT_OF_VERSION_STORE,
++ MD_ERROR_WIN_DS_INCOMPATIBLE_CONTROLS_USED,
++ MD_ERROR_WIN_DS_NO_REF_DOMAIN,
++ MD_ERROR_WIN_DS_RESERVED_LINK_ID,
++ MD_ERROR_WIN_DS_LINK_ID_NOT_AVAILABLE,
++ MD_ERROR_WIN_DS_AG_CANT_HAVE_UNIVERSAL_MEMBER,
++ MD_ERROR_WIN_DS_MODIFYDN_DISALLOWED_BY_INSTANCE_TYPE,
++ MD_ERROR_WIN_DS_NO_OBJECT_MOVE_IN_SCHEMA_NC,
++ MD_ERROR_WIN_DS_MODIFYDN_DISALLOWED_BY_FLAG,
++ MD_ERROR_WIN_DS_MODIFYDN_WRONG_GRANDPARENT,
++ MD_ERROR_WIN_DS_NAME_ERROR_TRUST_REFERRAL,
++ MD_ERROR_WIN_NOT_SUPPORTED_ON_STANDARD_SERVER,
++ MD_ERROR_WIN_DS_CANT_ACCESS_REMOTE_PART_OF_AD,
++ MD_ERROR_WIN_DS_CR_IMPOSSIBLE_TO_VALIDATE_V2,
++ MD_ERROR_WIN_DS_THREAD_LIMIT_EXCEEDED,
++ MD_ERROR_WIN_DS_NOT_CLOSEST,
++ MD_ERROR_WIN_DS_CANT_DERIVE_SPN_WITHOUT_SERVER_REF,
++ MD_ERROR_WIN_DS_SINGLE_USER_MODE_FAILED,
++ MD_ERROR_WIN_DS_NTDSCRIPT_SYNTAX_ERROR,
++ MD_ERROR_WIN_DS_NTDSCRIPT_PROCESS_ERROR,
++ MD_ERROR_WIN_DS_DIFFERENT_REPL_EPOCHS,
++ MD_ERROR_WIN_DS_DRS_EXTENSIONS_CHANGED,
++ MD_ERROR_WIN_DS_REPLICA_SET_CHANGE_NOT_ALLOWED_ON_DISABLED_CR,
++ MD_ERROR_WIN_DS_NO_MSDS_INTID,
++ MD_ERROR_WIN_DS_DUP_MSDS_INTID,
++ MD_ERROR_WIN_DS_EXISTS_IN_RDNATTID,
++ MD_ERROR_WIN_DS_AUTHORIZATION_FAILED,
++ MD_ERROR_WIN_DS_INVALID_SCRIPT,
++ MD_ERROR_WIN_DS_REMOTE_CROSSREF_OP_FAILED,
++ MD_ERROR_WIN_DS_CROSS_REF_BUSY,
++ MD_ERROR_WIN_DS_CANT_DERIVE_SPN_FOR_DELETED_DOMAIN,
++ MD_ERROR_WIN_DS_CANT_DEMOTE_WITH_WRITEABLE_NC,
++ MD_ERROR_WIN_DS_DUPLICATE_ID_FOUND,
++ MD_ERROR_WIN_DS_INSUFFICIENT_ATTR_TO_CREATE_OBJECT,
++ MD_ERROR_WIN_DS_GROUP_CONVERSION_ERROR,
++ MD_ERROR_WIN_DS_CANT_MOVE_APP_BASIC_GROUP,
++ MD_ERROR_WIN_DS_CANT_MOVE_APP_QUERY_GROUP,
++ MD_ERROR_WIN_DS_ROLE_NOT_VERIFIED,
++ MD_ERROR_WIN_DS_WKO_CONTAINER_CANNOT_BE_SPECIAL,
++ MD_ERROR_WIN_DS_DOMAIN_RENAME_IN_PROGRESS,
++ MD_ERROR_WIN_DS_EXISTING_AD_CHILD_NC,
++ MD_ERROR_WIN_DS_REPL_LIFETIME_EXCEEDED,
++ MD_ERROR_WIN_DS_DISALLOWED_IN_SYSTEM_CONTAINER,
++ MD_ERROR_WIN_DS_LDAP_SEND_QUEUE_FULL,
++ MD_ERROR_WIN_DS_DRA_OUT_SCHEDULE_WINDOW,
++ MD_ERROR_WIN_DS_POLICY_NOT_KNOWN,
++ MD_ERROR_WIN_NO_SITE_SETTINGS_OBJECT,
++ MD_ERROR_WIN_NO_SECRETS,
++ MD_ERROR_WIN_NO_WRITABLE_DC_FOUND,
++ MD_ERROR_WIN_DS_NO_SERVER_OBJECT,
++ MD_ERROR_WIN_DS_NO_NTDSA_OBJECT,
++ MD_ERROR_WIN_DS_NON_ASQ_SEARCH,
++ MD_ERROR_WIN_DS_AUDIT_FAILURE,
++ MD_ERROR_WIN_DS_INVALID_SEARCH_FLAG_SUBTREE,
++ MD_ERROR_WIN_DS_INVALID_SEARCH_FLAG_TUPLE,
++ MD_ERROR_WIN_DS_HIERARCHY_TABLE_TOO_DEEP,
++ MD_ERROR_WIN_DS_DRA_CORRUPT_UTD_VECTOR,
++ MD_ERROR_WIN_DS_DRA_SECRETS_DENIED,
++ MD_ERROR_WIN_DS_RESERVED_MAPI_ID,
++ MD_ERROR_WIN_DS_MAPI_ID_NOT_AVAILABLE,
++ MD_ERROR_WIN_DS_DRA_MISSING_KRBTGT_SECRET,
++ MD_ERROR_WIN_DS_DOMAIN_NAME_EXISTS_IN_FOREST,
++ MD_ERROR_WIN_DS_FLAT_NAME_EXISTS_IN_FOREST,
++ MD_ERROR_WIN_INVALID_USER_PRINCIPAL_NAME,
++ MD_ERROR_WIN_DS_OID_MAPPED_GROUP_CANT_HAVE_MEMBERS,
++ MD_ERROR_WIN_DS_OID_NOT_FOUND,
++ MD_ERROR_WIN_DS_DRA_RECYCLED_TARGET,
++ MD_ERROR_WIN_DS_DISALLOWED_NC_REDIRECT,
++ MD_ERROR_WIN_DS_HIGH_ADLDS_FFL,
++ MD_ERROR_WIN_DS_HIGH_DSA_VERSION,
++ MD_ERROR_WIN_DS_LOW_ADLDS_FFL,
++ MD_ERROR_WIN_DOMAIN_SID_SAME_AS_LOCAL_WORKSTATION,
++ MD_ERROR_WIN_DS_UNDELETE_SAM_VALIDATION_FAILED,
++ MD_ERROR_WIN_INCORRECT_ACCOUNT_TYPE,
++ MD_ERROR_WIN_DS_SPN_VALUE_NOT_UNIQUE_IN_FOREST,
++ MD_ERROR_WIN_DS_UPN_VALUE_NOT_UNIQUE_IN_FOREST,
++ MD_ERROR_WIN_DS_MISSING_FOREST_TRUST,
++ MD_ERROR_WIN_DS_VALUE_KEY_NOT_UNIQUE,
++ MD_ERROR_WIN_IPSEC_QM_POLICY_EXISTS,
++ MD_ERROR_WIN_IPSEC_QM_POLICY_NOT_FOUND,
++ MD_ERROR_WIN_IPSEC_QM_POLICY_IN_USE,
++ MD_ERROR_WIN_IPSEC_MM_POLICY_EXISTS,
++ MD_ERROR_WIN_IPSEC_MM_POLICY_NOT_FOUND,
++ MD_ERROR_WIN_IPSEC_MM_POLICY_IN_USE,
++ MD_ERROR_WIN_IPSEC_MM_FILTER_EXISTS,
++ MD_ERROR_WIN_IPSEC_MM_FILTER_NOT_FOUND,
++ MD_ERROR_WIN_IPSEC_TRANSPORT_FILTER_EXISTS,
++ MD_ERROR_WIN_IPSEC_TRANSPORT_FILTER_NOT_FOUND,
++ MD_ERROR_WIN_IPSEC_MM_AUTH_EXISTS,
++ MD_ERROR_WIN_IPSEC_MM_AUTH_NOT_FOUND,
++ MD_ERROR_WIN_IPSEC_MM_AUTH_IN_USE,
++ MD_ERROR_WIN_IPSEC_DEFAULT_MM_POLICY_NOT_FOUND,
++ MD_ERROR_WIN_IPSEC_DEFAULT_MM_AUTH_NOT_FOUND,
++ MD_ERROR_WIN_IPSEC_DEFAULT_QM_POLICY_NOT_FOUND,
++ MD_ERROR_WIN_IPSEC_TUNNEL_FILTER_EXISTS,
++ MD_ERROR_WIN_IPSEC_TUNNEL_FILTER_NOT_FOUND,
++ MD_ERROR_WIN_IPSEC_MM_FILTER_PENDING_DELETION,
++ MD_ERROR_WIN_IPSEC_TRANSPORT_FILTER_PENDING_DELETION,
++ MD_ERROR_WIN_IPSEC_TUNNEL_FILTER_PENDING_DELETION,
++ MD_ERROR_WIN_IPSEC_MM_POLICY_PENDING_DELETION,
++ MD_ERROR_WIN_IPSEC_MM_AUTH_PENDING_DELETION,
++ MD_ERROR_WIN_IPSEC_QM_POLICY_PENDING_DELETION,
++ MD_ERROR_WIN_IPSEC_IKE_NEG_STATUS_BEGIN,
++ MD_ERROR_WIN_IPSEC_IKE_AUTH_FAIL,
++ MD_ERROR_WIN_IPSEC_IKE_ATTRIB_FAIL,
++ MD_ERROR_WIN_IPSEC_IKE_NEGOTIATION_PENDING,
++ MD_ERROR_WIN_IPSEC_IKE_GENERAL_PROCESSING_ERROR,
++ MD_ERROR_WIN_IPSEC_IKE_TIMED_OUT,
++ MD_ERROR_WIN_IPSEC_IKE_NO_CERT,
++ MD_ERROR_WIN_IPSEC_IKE_SA_DELETED,
++ MD_ERROR_WIN_IPSEC_IKE_SA_REAPED,
++ MD_ERROR_WIN_IPSEC_IKE_MM_ACQUIRE_DROP,
++ MD_ERROR_WIN_IPSEC_IKE_QM_ACQUIRE_DROP,
++ MD_ERROR_WIN_IPSEC_IKE_QUEUE_DROP_MM,
++ MD_ERROR_WIN_IPSEC_IKE_QUEUE_DROP_NO_MM,
++ MD_ERROR_WIN_IPSEC_IKE_DROP_NO_RESPONSE,
++ MD_ERROR_WIN_IPSEC_IKE_MM_DELAY_DROP,
++ MD_ERROR_WIN_IPSEC_IKE_QM_DELAY_DROP,
++ MD_ERROR_WIN_IPSEC_IKE_ERROR,
++ MD_ERROR_WIN_IPSEC_IKE_CRL_FAILED,
++ MD_ERROR_WIN_IPSEC_IKE_INVALID_KEY_USAGE,
++ MD_ERROR_WIN_IPSEC_IKE_INVALID_CERT_TYPE,
++ MD_ERROR_WIN_IPSEC_IKE_NO_PRIVATE_KEY,
++ MD_ERROR_WIN_IPSEC_IKE_SIMULTANEOUS_REKEY,
++ MD_ERROR_WIN_IPSEC_IKE_DH_FAIL,
++ MD_ERROR_WIN_IPSEC_IKE_CRITICAL_PAYLOAD_NOT_RECOGNIZED,
++ MD_ERROR_WIN_IPSEC_IKE_INVALID_HEADER,
++ MD_ERROR_WIN_IPSEC_IKE_NO_POLICY,
++ MD_ERROR_WIN_IPSEC_IKE_INVALID_SIGNATURE,
++ MD_ERROR_WIN_IPSEC_IKE_KERBEROS_ERROR,
++ MD_ERROR_WIN_IPSEC_IKE_NO_PUBLIC_KEY,
++ MD_ERROR_WIN_IPSEC_IKE_PROCESS_ERR,
++ MD_ERROR_WIN_IPSEC_IKE_PROCESS_ERR_SA,
++ MD_ERROR_WIN_IPSEC_IKE_PROCESS_ERR_PROP,
++ MD_ERROR_WIN_IPSEC_IKE_PROCESS_ERR_TRANS,
++ MD_ERROR_WIN_IPSEC_IKE_PROCESS_ERR_KE,
++ MD_ERROR_WIN_IPSEC_IKE_PROCESS_ERR_ID,
++ MD_ERROR_WIN_IPSEC_IKE_PROCESS_ERR_CERT,
++ MD_ERROR_WIN_IPSEC_IKE_PROCESS_ERR_CERT_REQ,
++ MD_ERROR_WIN_IPSEC_IKE_PROCESS_ERR_HASH,
++ MD_ERROR_WIN_IPSEC_IKE_PROCESS_ERR_SIG,
++ MD_ERROR_WIN_IPSEC_IKE_PROCESS_ERR_NONCE,
++ MD_ERROR_WIN_IPSEC_IKE_PROCESS_ERR_NOTIFY,
++ MD_ERROR_WIN_IPSEC_IKE_PROCESS_ERR_DELETE,
++ MD_ERROR_WIN_IPSEC_IKE_PROCESS_ERR_VENDOR,
++ MD_ERROR_WIN_IPSEC_IKE_INVALID_PAYLOAD,
++ MD_ERROR_WIN_IPSEC_IKE_LOAD_SOFT_SA,
++ MD_ERROR_WIN_IPSEC_IKE_SOFT_SA_TORN_DOWN,
++ MD_ERROR_WIN_IPSEC_IKE_INVALID_COOKIE,
++ MD_ERROR_WIN_IPSEC_IKE_NO_PEER_CERT,
++ MD_ERROR_WIN_IPSEC_IKE_PEER_CRL_FAILED,
++ MD_ERROR_WIN_IPSEC_IKE_POLICY_CHANGE,
++ MD_ERROR_WIN_IPSEC_IKE_NO_MM_POLICY,
++ MD_ERROR_WIN_IPSEC_IKE_NOTCBPRIV,
++ MD_ERROR_WIN_IPSEC_IKE_SECLOADFAIL,
++ MD_ERROR_WIN_IPSEC_IKE_FAILSSPINIT,
++ MD_ERROR_WIN_IPSEC_IKE_FAILQUERYSSP,
++ MD_ERROR_WIN_IPSEC_IKE_SRVACQFAIL,
++ MD_ERROR_WIN_IPSEC_IKE_SRVQUERYCRED,
++ MD_ERROR_WIN_IPSEC_IKE_GETSPIFAIL,
++ MD_ERROR_WIN_IPSEC_IKE_INVALID_FILTER,
++ MD_ERROR_WIN_IPSEC_IKE_OUT_OF_MEMORY,
++ MD_ERROR_WIN_IPSEC_IKE_ADD_UPDATE_KEY_FAILED,
++ MD_ERROR_WIN_IPSEC_IKE_INVALID_POLICY,
++ MD_ERROR_WIN_IPSEC_IKE_UNKNOWN_DOI,
++ MD_ERROR_WIN_IPSEC_IKE_INVALID_SITUATION,
++ MD_ERROR_WIN_IPSEC_IKE_DH_FAILURE,
++ MD_ERROR_WIN_IPSEC_IKE_INVALID_GROUP,
++ MD_ERROR_WIN_IPSEC_IKE_ENCRYPT,
++ MD_ERROR_WIN_IPSEC_IKE_DECRYPT,
++ MD_ERROR_WIN_IPSEC_IKE_POLICY_MATCH,
++ MD_ERROR_WIN_IPSEC_IKE_UNSUPPORTED_ID,
++ MD_ERROR_WIN_IPSEC_IKE_INVALID_HASH,
++ MD_ERROR_WIN_IPSEC_IKE_INVALID_HASH_ALG,
++ MD_ERROR_WIN_IPSEC_IKE_INVALID_HASH_SIZE,
++ MD_ERROR_WIN_IPSEC_IKE_INVALID_ENCRYPT_ALG,
++ MD_ERROR_WIN_IPSEC_IKE_INVALID_AUTH_ALG,
++ MD_ERROR_WIN_IPSEC_IKE_INVALID_SIG,
++ MD_ERROR_WIN_IPSEC_IKE_LOAD_FAILED,
++ MD_ERROR_WIN_IPSEC_IKE_RPC_DELETE,
++ MD_ERROR_WIN_IPSEC_IKE_BENIGN_REINIT,
++ MD_ERROR_WIN_IPSEC_IKE_INVALID_RESPONDER_LIFETIME_NOTIFY,
++ MD_ERROR_WIN_IPSEC_IKE_INVALID_MAJOR_VERSION,
++ MD_ERROR_WIN_IPSEC_IKE_INVALID_CERT_KEYLEN,
++ MD_ERROR_WIN_IPSEC_IKE_MM_LIMIT,
++ MD_ERROR_WIN_IPSEC_IKE_NEGOTIATION_DISABLED,
++ MD_ERROR_WIN_IPSEC_IKE_QM_LIMIT,
++ MD_ERROR_WIN_IPSEC_IKE_MM_EXPIRED,
++ MD_ERROR_WIN_IPSEC_IKE_PEER_MM_ASSUMED_INVALID,
++ MD_ERROR_WIN_IPSEC_IKE_CERT_CHAIN_POLICY_MISMATCH,
++ MD_ERROR_WIN_IPSEC_IKE_UNEXPECTED_MESSAGE_ID,
++ MD_ERROR_WIN_IPSEC_IKE_INVALID_AUTH_PAYLOAD,
++ MD_ERROR_WIN_IPSEC_IKE_DOS_COOKIE_SENT,
++ MD_ERROR_WIN_IPSEC_IKE_SHUTTING_DOWN,
++ MD_ERROR_WIN_IPSEC_IKE_CGA_AUTH_FAILED,
++ MD_ERROR_WIN_IPSEC_IKE_PROCESS_ERR_NATOA,
++ MD_ERROR_WIN_IPSEC_IKE_INVALID_MM_FOR_QM,
++ MD_ERROR_WIN_IPSEC_IKE_QM_EXPIRED,
++ MD_ERROR_WIN_IPSEC_IKE_TOO_MANY_FILTERS,
++ MD_ERROR_WIN_IPSEC_IKE_NEG_STATUS_END,
++ MD_ERROR_WIN_IPSEC_IKE_KILL_DUMMY_NAP_TUNNEL,
++ MD_ERROR_WIN_IPSEC_IKE_INNER_IP_ASSIGNMENT_FAILURE,
++ MD_ERROR_WIN_IPSEC_IKE_REQUIRE_CP_PAYLOAD_MISSING,
++ MD_ERROR_WIN_IPSEC_KEY_MODULE_IMPERSONATION_NEGOTIATION_PENDING,
++ MD_ERROR_WIN_IPSEC_IKE_COEXISTENCE_SUPPRESS,
++ MD_ERROR_WIN_IPSEC_IKE_RATELIMIT_DROP,
++ MD_ERROR_WIN_IPSEC_IKE_PEER_DOESNT_SUPPORT_MOBIKE,
++ MD_ERROR_WIN_IPSEC_IKE_AUTHORIZATION_FAILURE,
++ MD_ERROR_WIN_IPSEC_IKE_STRONG_CRED_AUTHORIZATION_FAILURE,
++ MD_ERROR_WIN_IPSEC_IKE_AUTHORIZATION_FAILURE_WITH_OPTIONAL_RETRY,
++ MD_ERROR_WIN_IPSEC_IKE_STRONG_CRED_AUTHORIZATION_AND_CERTMAP_FAILURE,
++ MD_ERROR_WIN_IPSEC_IKE_NEG_STATUS_EXTENDED_END,
++ MD_ERROR_WIN_IPSEC_BAD_SPI,
++ MD_ERROR_WIN_IPSEC_SA_LIFETIME_EXPIRED,
++ MD_ERROR_WIN_IPSEC_WRONG_SA,
++ MD_ERROR_WIN_IPSEC_REPLAY_CHECK_FAILED,
++ MD_ERROR_WIN_IPSEC_INVALID_PACKET,
++ MD_ERROR_WIN_IPSEC_INTEGRITY_CHECK_FAILED,
++ MD_ERROR_WIN_IPSEC_CLEAR_TEXT_DROP,
++ MD_ERROR_WIN_IPSEC_AUTH_FIREWALL_DROP,
++ MD_ERROR_WIN_IPSEC_THROTTLE_DROP,
++ MD_ERROR_WIN_IPSEC_DOSP_BLOCK,
++ MD_ERROR_WIN_IPSEC_DOSP_RECEIVED_MULTICAST,
++ MD_ERROR_WIN_IPSEC_DOSP_INVALID_PACKET,
++ MD_ERROR_WIN_IPSEC_DOSP_STATE_LOOKUP_FAILED,
++ MD_ERROR_WIN_IPSEC_DOSP_MAX_ENTRIES,
++ MD_ERROR_WIN_IPSEC_DOSP_KEYMOD_NOT_ALLOWED,
++ MD_ERROR_WIN_IPSEC_DOSP_NOT_INSTALLED,
++ MD_ERROR_WIN_IPSEC_DOSP_MAX_PER_IP_RATELIMIT_QUEUES,
++ MD_ERROR_WIN_SXS_SECTION_NOT_FOUND,
++ MD_ERROR_WIN_SXS_CANT_GEN_ACTCTX,
++ MD_ERROR_WIN_SXS_INVALID_ACTCTXDATA_FORMAT,
++ MD_ERROR_WIN_SXS_ASSEMBLY_NOT_FOUND,
++ MD_ERROR_WIN_SXS_MANIFEST_FORMAT_ERROR,
++ MD_ERROR_WIN_SXS_MANIFEST_PARSE_ERROR,
++ MD_ERROR_WIN_SXS_ACTIVATION_CONTEXT_DISABLED,
++ MD_ERROR_WIN_SXS_KEY_NOT_FOUND,
++ MD_ERROR_WIN_SXS_VERSION_CONFLICT,
++ MD_ERROR_WIN_SXS_WRONG_SECTION_TYPE,
++ MD_ERROR_WIN_SXS_THREAD_QUERIES_DISABLED,
++ MD_ERROR_WIN_SXS_PROCESS_DEFAULT_ALREADY_SET,
++ MD_ERROR_WIN_SXS_UNKNOWN_ENCODING_GROUP,
++ MD_ERROR_WIN_SXS_UNKNOWN_ENCODING,
++ MD_ERROR_WIN_SXS_INVALID_XML_NAMESPACE_URI,
++ MD_ERROR_WIN_SXS_ROOT_MANIFEST_DEPENDENCY_NOT_INSTALLED,
++ MD_ERROR_WIN_SXS_LEAF_MANIFEST_DEPENDENCY_NOT_INSTALLED,
++ MD_ERROR_WIN_SXS_INVALID_ASSEMBLY_IDENTITY_ATTRIBUTE,
++ MD_ERROR_WIN_SXS_MANIFEST_MISSING_REQUIRED_DEFAULT_NAMESPACE,
++ MD_ERROR_WIN_SXS_MANIFEST_INVALID_REQUIRED_DEFAULT_NAMESPACE,
++ MD_ERROR_WIN_SXS_PRIVATE_MANIFEST_CROSS_PATH_WITH_REPARSE_POINT,
++ MD_ERROR_WIN_SXS_DUPLICATE_DLL_NAME,
++ MD_ERROR_WIN_SXS_DUPLICATE_WINDOWCLASS_NAME,
++ MD_ERROR_WIN_SXS_DUPLICATE_CLSID,
++ MD_ERROR_WIN_SXS_DUPLICATE_IID,
++ MD_ERROR_WIN_SXS_DUPLICATE_TLBID,
++ MD_ERROR_WIN_SXS_DUPLICATE_PROGID,
++ MD_ERROR_WIN_SXS_DUPLICATE_ASSEMBLY_NAME,
++ MD_ERROR_WIN_SXS_FILE_HASH_MISMATCH,
++ MD_ERROR_WIN_SXS_POLICY_PARSE_ERROR,
++ MD_ERROR_WIN_SXS_XML_E_MISSINGQUOTE,
++ MD_ERROR_WIN_SXS_XML_E_COMMENTSYNTAX,
++ MD_ERROR_WIN_SXS_XML_E_BADSTARTNAMECHAR,
++ MD_ERROR_WIN_SXS_XML_E_BADNAMECHAR,
++ MD_ERROR_WIN_SXS_XML_E_BADCHARINSTRING,
++ MD_ERROR_WIN_SXS_XML_E_XMLDECLSYNTAX,
++ MD_ERROR_WIN_SXS_XML_E_BADCHARDATA,
++ MD_ERROR_WIN_SXS_XML_E_MISSINGWHITESPACE,
++ MD_ERROR_WIN_SXS_XML_E_EXPECTINGTAGEND,
++ MD_ERROR_WIN_SXS_XML_E_MISSINGSEMICOLON,
++ MD_ERROR_WIN_SXS_XML_E_UNBALANCEDPAREN,
++ MD_ERROR_WIN_SXS_XML_E_INTERNALERROR,
++ MD_ERROR_WIN_SXS_XML_E_UNEXPECTED_WHITESPACE,
++ MD_ERROR_WIN_SXS_XML_E_INCOMPLETE_ENCODING,
++ MD_ERROR_WIN_SXS_XML_E_MISSING_PAREN,
++ MD_ERROR_WIN_SXS_XML_E_EXPECTINGCLOSEQUOTE,
++ MD_ERROR_WIN_SXS_XML_E_MULTIPLE_COLONS,
++ MD_ERROR_WIN_SXS_XML_E_INVALID_DECIMAL,
++ MD_ERROR_WIN_SXS_XML_E_INVALID_HEXIDECIMAL,
++ MD_ERROR_WIN_SXS_XML_E_INVALID_UNICODE,
++ MD_ERROR_WIN_SXS_XML_E_WHITESPACEORQUESTIONMARK,
++ MD_ERROR_WIN_SXS_XML_E_UNEXPECTEDENDTAG,
++ MD_ERROR_WIN_SXS_XML_E_UNCLOSEDTAG,
++ MD_ERROR_WIN_SXS_XML_E_DUPLICATEATTRIBUTE,
++ MD_ERROR_WIN_SXS_XML_E_MULTIPLEROOTS,
++ MD_ERROR_WIN_SXS_XML_E_INVALIDATROOTLEVEL,
++ MD_ERROR_WIN_SXS_XML_E_BADXMLDECL,
++ MD_ERROR_WIN_SXS_XML_E_MISSINGROOT,
++ MD_ERROR_WIN_SXS_XML_E_UNEXPECTEDEOF,
++ MD_ERROR_WIN_SXS_XML_E_BADPEREFINSUBSET,
++ MD_ERROR_WIN_SXS_XML_E_UNCLOSEDSTARTTAG,
++ MD_ERROR_WIN_SXS_XML_E_UNCLOSEDENDTAG,
++ MD_ERROR_WIN_SXS_XML_E_UNCLOSEDSTRING,
++ MD_ERROR_WIN_SXS_XML_E_UNCLOSEDCOMMENT,
++ MD_ERROR_WIN_SXS_XML_E_UNCLOSEDDECL,
++ MD_ERROR_WIN_SXS_XML_E_UNCLOSEDCDATA,
++ MD_ERROR_WIN_SXS_XML_E_RESERVEDNAMESPACE,
++ MD_ERROR_WIN_SXS_XML_E_INVALIDENCODING,
++ MD_ERROR_WIN_SXS_XML_E_INVALIDSWITCH,
++ MD_ERROR_WIN_SXS_XML_E_BADXMLCASE,
++ MD_ERROR_WIN_SXS_XML_E_INVALID_STANDALONE,
++ MD_ERROR_WIN_SXS_XML_E_UNEXPECTED_STANDALONE,
++ MD_ERROR_WIN_SXS_XML_E_INVALID_VERSION,
++ MD_ERROR_WIN_SXS_XML_E_MISSINGEQUALS,
++ MD_ERROR_WIN_SXS_PROTECTION_RECOVERY_FAILED,
++ MD_ERROR_WIN_SXS_PROTECTION_PUBLIC_KEY_TOO_SHORT,
++ MD_ERROR_WIN_SXS_PROTECTION_CATALOG_NOT_VALID,
++ MD_ERROR_WIN_SXS_UNTRANSLATABLE_HRESULT,
++ MD_ERROR_WIN_SXS_PROTECTION_CATALOG_FILE_MISSING,
++ MD_ERROR_WIN_SXS_MISSING_ASSEMBLY_IDENTITY_ATTRIBUTE,
++ MD_ERROR_WIN_SXS_INVALID_ASSEMBLY_IDENTITY_ATTRIBUTE_NAME,
++ MD_ERROR_WIN_SXS_ASSEMBLY_MISSING,
++ MD_ERROR_WIN_SXS_CORRUPT_ACTIVATION_STACK,
++ MD_ERROR_WIN_SXS_CORRUPTION,
++ MD_ERROR_WIN_SXS_EARLY_DEACTIVATION,
++ MD_ERROR_WIN_SXS_INVALID_DEACTIVATION,
++ MD_ERROR_WIN_SXS_MULTIPLE_DEACTIVATION,
++ MD_ERROR_WIN_SXS_PROCESS_TERMINATION_REQUESTED,
++ MD_ERROR_WIN_SXS_RELEASE_ACTIVATION_CONTEXT,
++ MD_ERROR_WIN_SXS_SYSTEM_DEFAULT_ACTIVATION_CONTEXT_EMPTY,
++ MD_ERROR_WIN_SXS_INVALID_IDENTITY_ATTRIBUTE_VALUE,
++ MD_ERROR_WIN_SXS_INVALID_IDENTITY_ATTRIBUTE_NAME,
++ MD_ERROR_WIN_SXS_IDENTITY_DUPLICATE_ATTRIBUTE,
++ MD_ERROR_WIN_SXS_IDENTITY_PARSE_ERROR,
++ MD_ERROR_WIN_MALFORMED_SUBSTITUTION_STRING,
++ MD_ERROR_WIN_SXS_INCORRECT_PUBLIC_KEY_TOKEN,
++ MD_ERROR_WIN_UNMAPPED_SUBSTITUTION_STRING,
++ MD_ERROR_WIN_SXS_ASSEMBLY_NOT_LOCKED,
++ MD_ERROR_WIN_SXS_COMPONENT_STORE_CORRUPT,
++ MD_ERROR_WIN_ADVANCED_INSTALLER_FAILED,
++ MD_ERROR_WIN_XML_ENCODING_MISMATCH,
++ MD_ERROR_WIN_SXS_MANIFEST_IDENTITY_SAME_BUT_CONTENTS_DIFFERENT,
++ MD_ERROR_WIN_SXS_IDENTITIES_DIFFERENT,
++ MD_ERROR_WIN_SXS_ASSEMBLY_IS_NOT_A_DEPLOYMENT,
++ MD_ERROR_WIN_SXS_FILE_NOT_PART_OF_ASSEMBLY,
++ MD_ERROR_WIN_SXS_MANIFEST_TOO_BIG,
++ MD_ERROR_WIN_SXS_SETTING_NOT_REGISTERED,
++ MD_ERROR_WIN_SXS_TRANSACTION_CLOSURE_INCOMPLETE,
++ MD_ERROR_WIN_SMI_PRIMITIVE_INSTALLER_FAILED,
++ MD_ERROR_WIN_GENERIC_COMMAND_FAILED,
++ MD_ERROR_WIN_SXS_FILE_HASH_MISSING,
++ MD_ERROR_WIN_SXS_DUPLICATE_ACTIVATABLE_CLASS,
++ MD_ERROR_WIN_EVT_INVALID_CHANNEL_PATH,
++ MD_ERROR_WIN_EVT_INVALID_QUERY,
++ MD_ERROR_WIN_EVT_PUBLISHER_METADATA_NOT_FOUND,
++ MD_ERROR_WIN_EVT_EVENT_TEMPLATE_NOT_FOUND,
++ MD_ERROR_WIN_EVT_INVALID_PUBLISHER_NAME,
++ MD_ERROR_WIN_EVT_INVALID_EVENT_DATA,
++ MD_ERROR_WIN_EVT_CHANNEL_NOT_FOUND,
++ MD_ERROR_WIN_EVT_MALFORMED_XML_TEXT,
++ MD_ERROR_WIN_EVT_SUBSCRIPTION_TO_DIRECT_CHANNEL,
++ MD_ERROR_WIN_EVT_CONFIGURATION_ERROR,
++ MD_ERROR_WIN_EVT_QUERY_RESULT_STALE,
++ MD_ERROR_WIN_EVT_QUERY_RESULT_INVALID_POSITION,
++ MD_ERROR_WIN_EVT_NON_VALIDATING_MSXML,
++ MD_ERROR_WIN_EVT_FILTER_ALREADYSCOPED,
++ MD_ERROR_WIN_EVT_FILTER_NOTELTSET,
++ MD_ERROR_WIN_EVT_FILTER_INVARG,
++ MD_ERROR_WIN_EVT_FILTER_INVTEST,
++ MD_ERROR_WIN_EVT_FILTER_INVTYPE,
++ MD_ERROR_WIN_EVT_FILTER_PARSEERR,
++ MD_ERROR_WIN_EVT_FILTER_UNSUPPORTEDOP,
++ MD_ERROR_WIN_EVT_FILTER_UNEXPECTEDTOKEN,
++ MD_ERROR_WIN_EVT_INVALID_OPERATION_OVER_ENABLED_DIRECT_CHANNEL,
++ MD_ERROR_WIN_EVT_INVALID_CHANNEL_PROPERTY_VALUE,
++ MD_ERROR_WIN_EVT_INVALID_PUBLISHER_PROPERTY_VALUE,
++ MD_ERROR_WIN_EVT_CHANNEL_CANNOT_ACTIVATE,
++ MD_ERROR_WIN_EVT_FILTER_TOO_COMPLEX,
++ MD_ERROR_WIN_EVT_MESSAGE_NOT_FOUND,
++ MD_ERROR_WIN_EVT_MESSAGE_ID_NOT_FOUND,
++ MD_ERROR_WIN_EVT_UNRESOLVED_VALUE_INSERT,
++ MD_ERROR_WIN_EVT_UNRESOLVED_PARAMETER_INSERT,
++ MD_ERROR_WIN_EVT_MAX_INSERTS_REACHED,
++ MD_ERROR_WIN_EVT_EVENT_DEFINITION_NOT_FOUND,
++ MD_ERROR_WIN_EVT_MESSAGE_LOCALE_NOT_FOUND,
++ MD_ERROR_WIN_EVT_VERSION_TOO_OLD,
++ MD_ERROR_WIN_EVT_VERSION_TOO_NEW,
++ MD_ERROR_WIN_EVT_CANNOT_OPEN_CHANNEL_OF_QUERY,
++ MD_ERROR_WIN_EVT_PUBLISHER_DISABLED,
++ MD_ERROR_WIN_EVT_FILTER_OUT_OF_RANGE,
++ MD_ERROR_WIN_EC_SUBSCRIPTION_CANNOT_ACTIVATE,
++ MD_ERROR_WIN_EC_LOG_DISABLED,
++ MD_ERROR_WIN_EC_CIRCULAR_FORWARDING,
++ MD_ERROR_WIN_EC_CREDSTORE_FULL,
++ MD_ERROR_WIN_EC_CRED_NOT_FOUND,
++ MD_ERROR_WIN_EC_NO_ACTIVE_CHANNEL,
++ MD_ERROR_WIN_MUI_FILE_NOT_FOUND,
++ MD_ERROR_WIN_MUI_INVALID_FILE,
++ MD_ERROR_WIN_MUI_INVALID_RC_CONFIG,
++ MD_ERROR_WIN_MUI_INVALID_LOCALE_NAME,
++ MD_ERROR_WIN_MUI_INVALID_ULTIMATEFALLBACK_NAME,
++ MD_ERROR_WIN_MUI_FILE_NOT_LOADED,
++ MD_ERROR_WIN_RESOURCE_ENUM_USER_STOP,
++ MD_ERROR_WIN_MUI_INTLSETTINGS_UILANG_NOT_INSTALLED,
++ MD_ERROR_WIN_MUI_INTLSETTINGS_INVALID_LOCALE_NAME,
++ MD_ERROR_WIN_MRM_RUNTIME_NO_DEFAULT_OR_NEUTRAL_RESOURCE,
++ MD_ERROR_WIN_MRM_INVALID_PRICONFIG,
++ MD_ERROR_WIN_MRM_INVALID_FILE_TYPE,
++ MD_ERROR_WIN_MRM_UNKNOWN_QUALIFIER,
++ MD_ERROR_WIN_MRM_INVALID_QUALIFIER_VALUE,
++ MD_ERROR_WIN_MRM_NO_CANDIDATE,
++ MD_ERROR_WIN_MRM_NO_MATCH_OR_DEFAULT_CANDIDATE,
++ MD_ERROR_WIN_MRM_RESOURCE_TYPE_MISMATCH,
++ MD_ERROR_WIN_MRM_DUPLICATE_MAP_NAME,
++ MD_ERROR_WIN_MRM_DUPLICATE_ENTRY,
++ MD_ERROR_WIN_MRM_INVALID_RESOURCE_IDENTIFIER,
++ MD_ERROR_WIN_MRM_FILEPATH_TOO_LONG,
++ MD_ERROR_WIN_MRM_UNSUPPORTED_DIRECTORY_TYPE,
++ MD_ERROR_WIN_MRM_INVALID_PRI_FILE,
++ MD_ERROR_WIN_MRM_NAMED_RESOURCE_NOT_FOUND,
++ MD_ERROR_WIN_MRM_MAP_NOT_FOUND,
++ MD_ERROR_WIN_MRM_UNSUPPORTED_PROFILE_TYPE,
++ MD_ERROR_WIN_MRM_INVALID_QUALIFIER_OPERATOR,
++ MD_ERROR_WIN_MRM_INDETERMINATE_QUALIFIER_VALUE,
++ MD_ERROR_WIN_MRM_AUTOMERGE_ENABLED,
++ MD_ERROR_WIN_MRM_TOO_MANY_RESOURCES,
++ MD_ERROR_WIN_MRM_UNSUPPORTED_FILE_TYPE_FOR_MERGE,
++ MD_ERROR_WIN_MRM_UNSUPPORTED_FILE_TYPE_FOR_LOAD_UNLOAD_PRI_FILE,
++ MD_ERROR_WIN_MRM_NO_CURRENT_VIEW_ON_THREAD,
++ MD_ERROR_WIN_DIFFERENT_PROFILE_RESOURCE_MANAGER_EXIST,
++ MD_ERROR_WIN_OPERATION_NOT_ALLOWED_FROM_SYSTEM_COMPONENT,
++ MD_ERROR_WIN_MRM_DIRECT_REF_TO_NON_DEFAULT_RESOURCE,
++ MD_ERROR_WIN_MRM_GENERATION_COUNT_MISMATCH,
++ MD_ERROR_WIN_PRI_MERGE_VERSION_MISMATCH,
++ MD_ERROR_WIN_PRI_MERGE_MISSING_SCHEMA,
++ MD_ERROR_WIN_PRI_MERGE_LOAD_FILE_FAILED,
++ MD_ERROR_WIN_PRI_MERGE_ADD_FILE_FAILED,
++ MD_ERROR_WIN_PRI_MERGE_WRITE_FILE_FAILED,
++ MD_ERROR_WIN_PRI_MERGE_MULTIPLE_PACKAGE_FAMILIES_NOT_ALLOWED,
++ MD_ERROR_WIN_PRI_MERGE_MULTIPLE_MAIN_PACKAGES_NOT_ALLOWED,
++ MD_ERROR_WIN_PRI_MERGE_BUNDLE_PACKAGES_NOT_ALLOWED,
++ MD_ERROR_WIN_PRI_MERGE_MAIN_PACKAGE_REQUIRED,
++ MD_ERROR_WIN_PRI_MERGE_RESOURCE_PACKAGE_REQUIRED,
++ MD_ERROR_WIN_PRI_MERGE_INVALID_FILE_NAME,
++ MD_ERROR_WIN_MRM_PACKAGE_NOT_FOUND,
++ MD_ERROR_WIN_MRM_MISSING_DEFAULT_LANGUAGE,
++ MD_ERROR_WIN_MCA_INVALID_CAPABILITIES_STRING,
++ MD_ERROR_WIN_MCA_INVALID_VCP_VERSION,
++ MD_ERROR_WIN_MCA_MONITOR_VIOLATES_MCCS_SPECIFICATION,
++ MD_ERROR_WIN_MCA_MCCS_VERSION_MISMATCH,
++ MD_ERROR_WIN_MCA_UNSUPPORTED_MCCS_VERSION,
++ MD_ERROR_WIN_MCA_INTERNAL_ERROR,
++ MD_ERROR_WIN_MCA_INVALID_TECHNOLOGY_TYPE_RETURNED,
++ MD_ERROR_WIN_MCA_UNSUPPORTED_COLOR_TEMPERATURE,
++ MD_ERROR_WIN_AMBIGUOUS_SYSTEM_DEVICE,
++ MD_ERROR_WIN_SYSTEM_DEVICE_NOT_FOUND,
++ MD_ERROR_WIN_HASH_NOT_SUPPORTED,
++ MD_ERROR_WIN_HASH_NOT_PRESENT,
++ MD_ERROR_WIN_SECONDARY_IC_PROVIDER_NOT_REGISTERED,
++ MD_ERROR_WIN_GPIO_CLIENT_INFORMATION_INVALID,
++ MD_ERROR_WIN_GPIO_VERSION_NOT_SUPPORTED,
++ MD_ERROR_WIN_GPIO_INVALID_REGISTRATION_PACKET,
++ MD_ERROR_WIN_GPIO_OPERATION_DENIED,
++ MD_ERROR_WIN_GPIO_INCOMPATIBLE_CONNECT_MODE,
++ MD_ERROR_WIN_GPIO_INTERRUPT_ALREADY_UNMASKED,
++ MD_ERROR_WIN_CANNOT_SWITCH_RUNLEVEL,
++ MD_ERROR_WIN_INVALID_RUNLEVEL_SETTING,
++ MD_ERROR_WIN_RUNLEVEL_SWITCH_TIMEOUT,
++ MD_ERROR_WIN_RUNLEVEL_SWITCH_AGENT_TIMEOUT,
++ MD_ERROR_WIN_RUNLEVEL_SWITCH_IN_PROGRESS,
++ MD_ERROR_WIN_SERVICES_FAILED_AUTOSTART,
++ MD_ERROR_WIN_COM_TASK_STOP_PENDING,
++ MD_ERROR_WIN_INSTALL_OPEN_PACKAGE_FAILED,
++ MD_ERROR_WIN_INSTALL_PACKAGE_NOT_FOUND,
++ MD_ERROR_WIN_INSTALL_INVALID_PACKAGE,
++ MD_ERROR_WIN_INSTALL_RESOLVE_DEPENDENCY_FAILED,
++ MD_ERROR_WIN_INSTALL_OUT_OF_DISK_SPACE,
++ MD_ERROR_WIN_INSTALL_NETWORK_FAILURE,
++ MD_ERROR_WIN_INSTALL_REGISTRATION_FAILURE,
++ MD_ERROR_WIN_INSTALL_DEREGISTRATION_FAILURE,
++ MD_ERROR_WIN_INSTALL_CANCEL,
++ MD_ERROR_WIN_INSTALL_FAILED,
++ MD_ERROR_WIN_REMOVE_FAILED,
++ MD_ERROR_WIN_PACKAGE_ALREADY_EXISTS,
++ MD_ERROR_WIN_NEEDS_REMEDIATION,
++ MD_ERROR_WIN_INSTALL_PREREQUISITE_FAILED,
++ MD_ERROR_WIN_PACKAGE_REPOSITORY_CORRUPTED,
++ MD_ERROR_WIN_INSTALL_POLICY_FAILURE,
++ MD_ERROR_WIN_PACKAGE_UPDATING,
++ MD_ERROR_WIN_DEPLOYMENT_BLOCKED_BY_POLICY,
++ MD_ERROR_WIN_PACKAGES_IN_USE,
++ MD_ERROR_WIN_RECOVERY_FILE_CORRUPT,
++ MD_ERROR_WIN_INVALID_STAGED_SIGNATURE,
++ MD_ERROR_WIN_DELETING_EXISTING_APPLICATIONDATA_STORE_FAILED,
++ MD_ERROR_WIN_INSTALL_PACKAGE_DOWNGRADE,
++ MD_ERROR_WIN_SYSTEM_NEEDS_REMEDIATION,
++ MD_ERROR_WIN_APPX_INTEGRITY_FAILURE_CLR_NGEN,
++ MD_ERROR_WIN_RESILIENCY_FILE_CORRUPT,
++ MD_ERROR_WIN_INSTALL_FIREWALL_SERVICE_NOT_RUNNING,
++ MD_ERROR_WIN_PACKAGE_MOVE_FAILED,
++ MD_ERROR_WIN_INSTALL_VOLUME_NOT_EMPTY,
++ MD_ERROR_WIN_INSTALL_VOLUME_OFFLINE,
++ MD_ERROR_WIN_INSTALL_VOLUME_CORRUPT,
++ MD_ERROR_WIN_NEEDS_REGISTRATION,
++ MD_ERROR_WIN_INSTALL_WRONG_PROCESSOR_ARCHITECTURE,
++ MD_ERROR_WIN_DEV_SIDELOAD_LIMIT_EXCEEDED,
++ MD_ERROR_WIN_INSTALL_OPTIONAL_PACKAGE_REQUIRES_MAIN_PACKAGE,
++ MD_ERROR_WIN_PACKAGE_NOT_SUPPORTED_ON_FILESYSTEM,
++ MD_ERROR_WIN_PACKAGE_MOVE_BLOCKED_BY_STREAMING,
++ MD_ERROR_WIN_INSTALL_OPTIONAL_PACKAGE_APPLICATIONID_NOT_UNIQUE,
++ MD_ERROR_WIN_PACKAGE_STAGING_ONHOLD,
++ MD_ERROR_WIN_INSTALL_INVALID_RELATED_SET_UPDATE,
++ MD_ERROR_WIN_INSTALL_OPTIONAL_PACKAGE_REQUIRES_MAIN_PACKAGE_FULLTRUST_CAPABILITY,
++ MD_ERROR_WIN_DEPLOYMENT_BLOCKED_BY_USER_LOG_OFF,
++ MD_ERROR_WIN_PROVISION_OPTIONAL_PACKAGE_REQUIRES_MAIN_PACKAGE_PROVISIONED,
++ MD_ERROR_WIN_PACKAGES_REPUTATION_CHECK_FAILED,
++ MD_ERROR_WIN_PACKAGES_REPUTATION_CHECK_TIMEDOUT,
++ MD_ERROR_WIN_DEPLOYMENT_OPTION_NOT_SUPPORTED,
++ MD_ERROR_WIN_APPINSTALLER_ACTIVATION_BLOCKED,
++ MD_ERROR_WIN_REGISTRATION_FROM_REMOTE_DRIVE_NOT_SUPPORTED,
++ MD_ERROR_WIN_APPX_RAW_DATA_WRITE_FAILED,
++ MD_ERROR_WIN_DEPLOYMENT_BLOCKED_BY_VOLUME_POLICY_PACKAGE,
++ MD_ERROR_WIN_DEPLOYMENT_BLOCKED_BY_VOLUME_POLICY_MACHINE,
++ MD_ERROR_WIN_DEPLOYMENT_BLOCKED_BY_PROFILE_POLICY,
++ MD_ERROR_WIN_DEPLOYMENT_FAILED_CONFLICTING_MUTABLE_PACKAGE_DIRECTORY,
++ MD_ERROR_WIN_SINGLETON_RESOURCE_INSTALLED_IN_ACTIVE_USER,
++ MD_ERROR_WIN_DIFFERENT_VERSION_OF_PACKAGED_SERVICE_INSTALLED,
++ MD_ERROR_WIN_SERVICE_EXISTS_AS_NON_PACKAGED_SERVICE,
++ MD_ERROR_WIN_PACKAGED_SERVICE_REQUIRES_ADMIN_PRIVILEGES,
++ MD_ERROR_WIN_REDIRECTION_TO_DEFAULT_ACCOUNT_NOT_ALLOWED,
++ MD_ERROR_WIN_PACKAGE_LACKS_CAPABILITY_TO_DEPLOY_ON_HOST,
++ MD_ERROR_WIN_UNSIGNED_PACKAGE_INVALID_CONTENT,
++ MD_ERROR_WIN_UNSIGNED_PACKAGE_INVALID_PUBLISHER_NAMESPACE,
++ MD_ERROR_WIN_SIGNED_PACKAGE_INVALID_PUBLISHER_NAMESPACE,
++ MD_ERROR_WIN_PACKAGE_EXTERNAL_LOCATION_NOT_ALLOWED,
++ MD_ERROR_WIN_INSTALL_FULLTRUST_HOSTRUNTIME_REQUIRES_MAIN_PACKAGE_FULLTRUST_CAPABILITY,
++ MD_ERROR_WIN_STATE_LOAD_STORE_FAILED,
++ MD_ERROR_WIN_STATE_GET_VERSION_FAILED,
++ MD_ERROR_WIN_STATE_SET_VERSION_FAILED,
++ MD_ERROR_WIN_STATE_STRUCTURED_RESET_FAILED,
++ MD_ERROR_WIN_STATE_OPEN_CONTAINER_FAILED,
++ MD_ERROR_WIN_STATE_CREATE_CONTAINER_FAILED,
++ MD_ERROR_WIN_STATE_DELETE_CONTAINER_FAILED,
++ MD_ERROR_WIN_STATE_READ_SETTING_FAILED,
++ MD_ERROR_WIN_STATE_WRITE_SETTING_FAILED,
++ MD_ERROR_WIN_STATE_DELETE_SETTING_FAILED,
++ MD_ERROR_WIN_STATE_QUERY_SETTING_FAILED,
++ MD_ERROR_WIN_STATE_READ_COMPOSITE_SETTING_FAILED,
++ MD_ERROR_WIN_STATE_WRITE_COMPOSITE_SETTING_FAILED,
++ MD_ERROR_WIN_STATE_ENUMERATE_CONTAINER_FAILED,
++ MD_ERROR_WIN_STATE_ENUMERATE_SETTINGS_FAILED,
++ MD_ERROR_WIN_STATE_COMPOSITE_SETTING_VALUE_SIZE_LIMIT_EXCEEDED,
++ MD_ERROR_WIN_STATE_SETTING_VALUE_SIZE_LIMIT_EXCEEDED,
++ MD_ERROR_WIN_STATE_SETTING_NAME_SIZE_LIMIT_EXCEEDED,
++ MD_ERROR_WIN_STATE_CONTAINER_NAME_SIZE_LIMIT_EXCEEDED,
++ MD_ERROR_WIN_API_UNAVAILABLE,
++};
++
++// The content of this array was created from winerror.h in the 10 SDK
++// (version 10.0.19041.0) with the following script:
++//
++// egrep -o '#define ERROR_[A-Z_0-9]+\s+[0-9]+L' winerror.h
++// | tr -d '\r'
++// | sed -r 's@#define (ERROR_[A-Z_0-9]+)\s+([0-9]+)L@\2 \1@'
++// | sort -n | sed -r 's@([0-9]+) ([A-Z_0-9]+)@ "\2",@'
++static const char* kWinErrorStrings[] = {
++ "ERROR_SUCCESS",
++ "ERROR_INVALID_FUNCTION",
++ "ERROR_FILE_NOT_FOUND",
++ "ERROR_PATH_NOT_FOUND",
++ "ERROR_TOO_MANY_OPEN_FILES",
++ "ERROR_ACCESS_DENIED",
++ "ERROR_INVALID_HANDLE",
++ "ERROR_ARENA_TRASHED",
++ "ERROR_NOT_ENOUGH_MEMORY",
++ "ERROR_INVALID_BLOCK",
++ "ERROR_BAD_ENVIRONMENT",
++ "ERROR_BAD_FORMAT",
++ "ERROR_INVALID_ACCESS",
++ "ERROR_INVALID_DATA",
++ "ERROR_OUTOFMEMORY",
++ "ERROR_INVALID_DRIVE",
++ "ERROR_CURRENT_DIRECTORY",
++ "ERROR_NOT_SAME_DEVICE",
++ "ERROR_NO_MORE_FILES",
++ "ERROR_WRITE_PROTECT",
++ "ERROR_BAD_UNIT",
++ "ERROR_NOT_READY",
++ "ERROR_BAD_COMMAND",
++ "ERROR_CRC",
++ "ERROR_BAD_LENGTH",
++ "ERROR_SEEK",
++ "ERROR_NOT_DOS_DISK",
++ "ERROR_SECTOR_NOT_FOUND",
++ "ERROR_OUT_OF_PAPER",
++ "ERROR_WRITE_FAULT",
++ "ERROR_READ_FAULT",
++ "ERROR_GEN_FAILURE",
++ "ERROR_SHARING_VIOLATION",
++ "ERROR_LOCK_VIOLATION",
++ "ERROR_WRONG_DISK",
++ "ERROR_SHARING_BUFFER_EXCEEDED",
++ "ERROR_HANDLE_EOF",
++ "ERROR_HANDLE_DISK_FULL",
++ "ERROR_NOT_SUPPORTED",
++ "ERROR_REM_NOT_LIST",
++ "ERROR_DUP_NAME",
++ "ERROR_BAD_NETPATH",
++ "ERROR_NETWORK_BUSY",
++ "ERROR_DEV_NOT_EXIST",
++ "ERROR_TOO_MANY_CMDS",
++ "ERROR_ADAP_HDW_ERR",
++ "ERROR_BAD_NET_RESP",
++ "ERROR_UNEXP_NET_ERR",
++ "ERROR_BAD_REM_ADAP",
++ "ERROR_PRINTQ_FULL",
++ "ERROR_NO_SPOOL_SPACE",
++ "ERROR_PRINT_CANCELLED",
++ "ERROR_NETNAME_DELETED",
++ "ERROR_NETWORK_ACCESS_DENIED",
++ "ERROR_BAD_DEV_TYPE",
++ "ERROR_BAD_NET_NAME",
++ "ERROR_TOO_MANY_NAMES",
++ "ERROR_TOO_MANY_SESS",
++ "ERROR_SHARING_PAUSED",
++ "ERROR_REQ_NOT_ACCEP",
++ "ERROR_REDIR_PAUSED",
++ "ERROR_FILE_EXISTS",
++ "ERROR_CANNOT_MAKE",
++ "ERROR_FAIL_I24",
++ "ERROR_OUT_OF_STRUCTURES",
++ "ERROR_ALREADY_ASSIGNED",
++ "ERROR_INVALID_PASSWORD",
++ "ERROR_INVALID_PARAMETER",
++ "ERROR_NET_WRITE_FAULT",
++ "ERROR_NO_PROC_SLOTS",
++ "ERROR_TOO_MANY_SEMAPHORES",
++ "ERROR_EXCL_SEM_ALREADY_OWNED",
++ "ERROR_SEM_IS_SET",
++ "ERROR_TOO_MANY_SEM_REQUESTS",
++ "ERROR_INVALID_AT_INTERRUPT_TIME",
++ "ERROR_SEM_OWNER_DIED",
++ "ERROR_SEM_USER_LIMIT",
++ "ERROR_DISK_CHANGE",
++ "ERROR_DRIVE_LOCKED",
++ "ERROR_BROKEN_PIPE",
++ "ERROR_OPEN_FAILED",
++ "ERROR_BUFFER_OVERFLOW",
++ "ERROR_DISK_FULL",
++ "ERROR_NO_MORE_SEARCH_HANDLES",
++ "ERROR_INVALID_TARGET_HANDLE",
++ "ERROR_INVALID_CATEGORY",
++ "ERROR_INVALID_VERIFY_SWITCH",
++ "ERROR_BAD_DRIVER_LEVEL",
++ "ERROR_CALL_NOT_IMPLEMENTED",
++ "ERROR_SEM_TIMEOUT",
++ "ERROR_INSUFFICIENT_BUFFER",
++ "ERROR_INVALID_NAME",
++ "ERROR_INVALID_LEVEL",
++ "ERROR_NO_VOLUME_LABEL",
++ "ERROR_MOD_NOT_FOUND",
++ "ERROR_PROC_NOT_FOUND",
++ "ERROR_WAIT_NO_CHILDREN",
++ "ERROR_CHILD_NOT_COMPLETE",
++ "ERROR_DIRECT_ACCESS_HANDLE",
++ "ERROR_NEGATIVE_SEEK",
++ "ERROR_SEEK_ON_DEVICE",
++ "ERROR_IS_JOIN_TARGET",
++ "ERROR_IS_JOINED",
++ "ERROR_IS_SUBSTED",
++ "ERROR_NOT_JOINED",
++ "ERROR_NOT_SUBSTED",
++ "ERROR_JOIN_TO_JOIN",
++ "ERROR_SUBST_TO_SUBST",
++ "ERROR_JOIN_TO_SUBST",
++ "ERROR_SUBST_TO_JOIN",
++ "ERROR_BUSY_DRIVE",
++ "ERROR_SAME_DRIVE",
++ "ERROR_DIR_NOT_ROOT",
++ "ERROR_DIR_NOT_EMPTY",
++ "ERROR_IS_SUBST_PATH",
++ "ERROR_IS_JOIN_PATH",
++ "ERROR_PATH_BUSY",
++ "ERROR_IS_SUBST_TARGET",
++ "ERROR_SYSTEM_TRACE",
++ "ERROR_INVALID_EVENT_COUNT",
++ "ERROR_TOO_MANY_MUXWAITERS",
++ "ERROR_INVALID_LIST_FORMAT",
++ "ERROR_LABEL_TOO_LONG",
++ "ERROR_TOO_MANY_TCBS",
++ "ERROR_SIGNAL_REFUSED",
++ "ERROR_DISCARDED",
++ "ERROR_NOT_LOCKED",
++ "ERROR_BAD_THREADID_ADDR",
++ "ERROR_BAD_ARGUMENTS",
++ "ERROR_BAD_PATHNAME",
++ "ERROR_SIGNAL_PENDING",
++ "ERROR_MAX_THRDS_REACHED",
++ "ERROR_LOCK_FAILED",
++ "ERROR_BUSY",
++ "ERROR_DEVICE_SUPPORT_IN_PROGRESS",
++ "ERROR_CANCEL_VIOLATION",
++ "ERROR_ATOMIC_LOCKS_NOT_SUPPORTED",
++ "ERROR_INVALID_SEGMENT_NUMBER",
++ "ERROR_INVALID_ORDINAL",
++ "ERROR_ALREADY_EXISTS",
++ "ERROR_INVALID_FLAG_NUMBER",
++ "ERROR_SEM_NOT_FOUND",
++ "ERROR_INVALID_STARTING_CODESEG",
++ "ERROR_INVALID_STACKSEG",
++ "ERROR_INVALID_MODULETYPE",
++ "ERROR_INVALID_EXE_SIGNATURE",
++ "ERROR_EXE_MARKED_INVALID",
++ "ERROR_BAD_EXE_FORMAT",
++ "ERROR_INVALID_MINALLOCSIZE",
++ "ERROR_DYNLINK_FROM_INVALID_RING",
++ "ERROR_IOPL_NOT_ENABLED",
++ "ERROR_INVALID_SEGDPL",
++ "ERROR_RING2SEG_MUST_BE_MOVABLE",
++ "ERROR_RELOC_CHAIN_XEEDS_SEGLIM",
++ "ERROR_INFLOOP_IN_RELOC_CHAIN",
++ "ERROR_ENVVAR_NOT_FOUND",
++ "ERROR_NO_SIGNAL_SENT",
++ "ERROR_FILENAME_EXCED_RANGE",
++ "ERROR_RING2_STACK_IN_USE",
++ "ERROR_META_EXPANSION_TOO_LONG",
++ "ERROR_INVALID_SIGNAL_NUMBER",
++ "ERROR_THREAD_1_INACTIVE",
++ "ERROR_LOCKED",
++ "ERROR_TOO_MANY_MODULES",
++ "ERROR_NESTING_NOT_ALLOWED",
++ "ERROR_EXE_MACHINE_TYPE_MISMATCH",
++ "ERROR_EXE_CANNOT_MODIFY_SIGNED_BINARY",
++ "ERROR_EXE_CANNOT_MODIFY_STRONG_SIGNED_BINARY",
++ "ERROR_FILE_CHECKED_OUT",
++ "ERROR_CHECKOUT_REQUIRED",
++ "ERROR_BAD_FILE_TYPE",
++ "ERROR_FILE_TOO_LARGE",
++ "ERROR_FORMS_AUTH_REQUIRED",
++ "ERROR_VIRUS_INFECTED",
++ "ERROR_VIRUS_DELETED",
++ "ERROR_PIPE_LOCAL",
++ "ERROR_BAD_PIPE",
++ "ERROR_PIPE_BUSY",
++ "ERROR_NO_DATA",
++ "ERROR_PIPE_NOT_CONNECTED",
++ "ERROR_MORE_DATA",
++ "ERROR_NO_WORK_DONE",
++ "ERROR_VC_DISCONNECTED",
++ "ERROR_INVALID_EA_NAME",
++ "ERROR_EA_LIST_INCONSISTENT",
++ "ERROR_NO_MORE_ITEMS",
++ "ERROR_CANNOT_COPY",
++ "ERROR_DIRECTORY",
++ "ERROR_EAS_DIDNT_FIT",
++ "ERROR_EA_FILE_CORRUPT",
++ "ERROR_EA_TABLE_FULL",
++ "ERROR_INVALID_EA_HANDLE",
++ "ERROR_EAS_NOT_SUPPORTED",
++ "ERROR_NOT_OWNER",
++ "ERROR_TOO_MANY_POSTS",
++ "ERROR_PARTIAL_COPY",
++ "ERROR_OPLOCK_NOT_GRANTED",
++ "ERROR_INVALID_OPLOCK_PROTOCOL",
++ "ERROR_DISK_TOO_FRAGMENTED",
++ "ERROR_DELETE_PENDING",
++ "ERROR_INCOMPATIBLE_WITH_GLOBAL_SHORT_NAME_REGISTRY_SETTING",
++ "ERROR_SHORT_NAMES_NOT_ENABLED_ON_VOLUME",
++ "ERROR_SECURITY_STREAM_IS_INCONSISTENT",
++ "ERROR_INVALID_LOCK_RANGE",
++ "ERROR_IMAGE_SUBSYSTEM_NOT_PRESENT",
++ "ERROR_NOTIFICATION_GUID_ALREADY_DEFINED",
++ "ERROR_INVALID_EXCEPTION_HANDLER",
++ "ERROR_DUPLICATE_PRIVILEGES",
++ "ERROR_NO_RANGES_PROCESSED",
++ "ERROR_NOT_ALLOWED_ON_SYSTEM_FILE",
++ "ERROR_DISK_RESOURCES_EXHAUSTED",
++ "ERROR_INVALID_TOKEN",
++ "ERROR_DEVICE_FEATURE_NOT_SUPPORTED",
++ "ERROR_MR_MID_NOT_FOUND",
++ "ERROR_SCOPE_NOT_FOUND",
++ "ERROR_UNDEFINED_SCOPE",
++ "ERROR_INVALID_CAP",
++ "ERROR_DEVICE_UNREACHABLE",
++ "ERROR_DEVICE_NO_RESOURCES",
++ "ERROR_DATA_CHECKSUM_ERROR",
++ "ERROR_INTERMIXED_KERNEL_EA_OPERATION",
++ "ERROR_FILE_LEVEL_TRIM_NOT_SUPPORTED",
++ "ERROR_OFFSET_ALIGNMENT_VIOLATION",
++ "ERROR_INVALID_FIELD_IN_PARAMETER_LIST",
++ "ERROR_OPERATION_IN_PROGRESS",
++ "ERROR_BAD_DEVICE_PATH",
++ "ERROR_TOO_MANY_DESCRIPTORS",
++ "ERROR_SCRUB_DATA_DISABLED",
++ "ERROR_NOT_REDUNDANT_STORAGE",
++ "ERROR_RESIDENT_FILE_NOT_SUPPORTED",
++ "ERROR_COMPRESSED_FILE_NOT_SUPPORTED",
++ "ERROR_DIRECTORY_NOT_SUPPORTED",
++ "ERROR_NOT_READ_FROM_COPY",
++ "ERROR_FT_WRITE_FAILURE",
++ "ERROR_FT_DI_SCAN_REQUIRED",
++ "ERROR_INVALID_KERNEL_INFO_VERSION",
++ "ERROR_INVALID_PEP_INFO_VERSION",
++ "ERROR_OBJECT_NOT_EXTERNALLY_BACKED",
++ "ERROR_EXTERNAL_BACKING_PROVIDER_UNKNOWN",
++ "ERROR_COMPRESSION_NOT_BENEFICIAL",
++ "ERROR_STORAGE_TOPOLOGY_ID_MISMATCH",
++ "ERROR_BLOCKED_BY_PARENTAL_CONTROLS",
++ "ERROR_BLOCK_TOO_MANY_REFERENCES",
++ "ERROR_MARKED_TO_DISALLOW_WRITES",
++ "ERROR_ENCLAVE_FAILURE",
++ "ERROR_FAIL_NOACTION_REBOOT",
++ "ERROR_FAIL_SHUTDOWN",
++ "ERROR_FAIL_RESTART",
++ "ERROR_MAX_SESSIONS_REACHED",
++ "ERROR_NETWORK_ACCESS_DENIED_EDP",
++ "ERROR_DEVICE_HINT_NAME_BUFFER_TOO_SMALL",
++ "ERROR_EDP_POLICY_DENIES_OPERATION",
++ "ERROR_EDP_DPL_POLICY_CANT_BE_SATISFIED",
++ "ERROR_CLOUD_FILE_SYNC_ROOT_METADATA_CORRUPT",
++ "ERROR_DEVICE_IN_MAINTENANCE",
++ "ERROR_NOT_SUPPORTED_ON_DAX",
++ "ERROR_DAX_MAPPING_EXISTS",
++ "ERROR_CLOUD_FILE_PROVIDER_NOT_RUNNING",
++ "ERROR_CLOUD_FILE_METADATA_CORRUPT",
++ "ERROR_CLOUD_FILE_METADATA_TOO_LARGE",
++ "ERROR_CLOUD_FILE_PROPERTY_BLOB_TOO_LARGE",
++ "ERROR_CLOUD_FILE_PROPERTY_BLOB_CHECKSUM_MISMATCH",
++ "ERROR_CHILD_PROCESS_BLOCKED",
++ "ERROR_STORAGE_LOST_DATA_PERSISTENCE",
++ "ERROR_FILE_SYSTEM_VIRTUALIZATION_UNAVAILABLE",
++ "ERROR_FILE_SYSTEM_VIRTUALIZATION_METADATA_CORRUPT",
++ "ERROR_FILE_SYSTEM_VIRTUALIZATION_BUSY",
++ "ERROR_FILE_SYSTEM_VIRTUALIZATION_PROVIDER_UNKNOWN",
++ "ERROR_GDI_HANDLE_LEAK",
++ "ERROR_CLOUD_FILE_TOO_MANY_PROPERTY_BLOBS",
++ "ERROR_CLOUD_FILE_PROPERTY_VERSION_NOT_SUPPORTED",
++ "ERROR_NOT_A_CLOUD_FILE",
++ "ERROR_CLOUD_FILE_NOT_IN_SYNC",
++ "ERROR_CLOUD_FILE_ALREADY_CONNECTED",
++ "ERROR_CLOUD_FILE_NOT_SUPPORTED",
++ "ERROR_CLOUD_FILE_INVALID_REQUEST",
++ "ERROR_CLOUD_FILE_READ_ONLY_VOLUME",
++ "ERROR_CLOUD_FILE_CONNECTED_PROVIDER_ONLY",
++ "ERROR_CLOUD_FILE_VALIDATION_FAILED",
++ "ERROR_SMB1_NOT_AVAILABLE",
++ "ERROR_FILE_SYSTEM_VIRTUALIZATION_INVALID_OPERATION",
++ "ERROR_CLOUD_FILE_AUTHENTICATION_FAILED",
++ "ERROR_CLOUD_FILE_INSUFFICIENT_RESOURCES",
++ "ERROR_CLOUD_FILE_NETWORK_UNAVAILABLE",
++ "ERROR_CLOUD_FILE_UNSUCCESSFUL",
++ "ERROR_CLOUD_FILE_NOT_UNDER_SYNC_ROOT",
++ "ERROR_CLOUD_FILE_IN_USE",
++ "ERROR_CLOUD_FILE_PINNED",
++ "ERROR_CLOUD_FILE_REQUEST_ABORTED",
++ "ERROR_CLOUD_FILE_PROPERTY_CORRUPT",
++ "ERROR_CLOUD_FILE_ACCESS_DENIED",
++ "ERROR_CLOUD_FILE_INCOMPATIBLE_HARDLINKS",
++ "ERROR_CLOUD_FILE_PROPERTY_LOCK_CONFLICT",
++ "ERROR_CLOUD_FILE_REQUEST_CANCELED",
++ "ERROR_EXTERNAL_SYSKEY_NOT_SUPPORTED",
++ "ERROR_THREAD_MODE_ALREADY_BACKGROUND",
++ "ERROR_THREAD_MODE_NOT_BACKGROUND",
++ "ERROR_PROCESS_MODE_ALREADY_BACKGROUND",
++ "ERROR_PROCESS_MODE_NOT_BACKGROUND",
++ "ERROR_CLOUD_FILE_PROVIDER_TERMINATED",
++ "ERROR_NOT_A_CLOUD_SYNC_ROOT",
++ "ERROR_FILE_PROTECTED_UNDER_DPL",
++ "ERROR_VOLUME_NOT_CLUSTER_ALIGNED",
++ "ERROR_NO_PHYSICALLY_ALIGNED_FREE_SPACE_FOUND",
++ "ERROR_APPX_FILE_NOT_ENCRYPTED",
++ "ERROR_RWRAW_ENCRYPTED_FILE_NOT_ENCRYPTED",
++ "ERROR_RWRAW_ENCRYPTED_INVALID_EDATAINFO_FILEOFFSET",
++ "ERROR_RWRAW_ENCRYPTED_INVALID_EDATAINFO_FILERANGE",
++ "ERROR_RWRAW_ENCRYPTED_INVALID_EDATAINFO_PARAMETER",
++ "ERROR_LINUX_SUBSYSTEM_NOT_PRESENT",
++ "ERROR_FT_READ_FAILURE",
++ "ERROR_STORAGE_RESERVE_ID_INVALID",
++ "ERROR_STORAGE_RESERVE_DOES_NOT_EXIST",
++ "ERROR_STORAGE_RESERVE_ALREADY_EXISTS",
++ "ERROR_STORAGE_RESERVE_NOT_EMPTY",
++ "ERROR_NOT_A_DAX_VOLUME",
++ "ERROR_NOT_DAX_MAPPABLE",
++ "ERROR_TIME_SENSITIVE_THREAD",
++ "ERROR_DPL_NOT_SUPPORTED_FOR_USER",
++ "ERROR_CASE_DIFFERING_NAMES_IN_DIR",
++ "ERROR_FILE_NOT_SUPPORTED",
++ "ERROR_CLOUD_FILE_REQUEST_TIMEOUT",
++ "ERROR_NO_TASK_QUEUE",
++ "ERROR_SRC_SRV_DLL_LOAD_FAILED",
++ "ERROR_NOT_SUPPORTED_WITH_BTT",
++ "ERROR_ENCRYPTION_DISABLED",
++ "ERROR_ENCRYPTING_METADATA_DISALLOWED",
++ "ERROR_CANT_CLEAR_ENCRYPTION_FLAG",
++ "ERROR_NO_SUCH_DEVICE",
++ "ERROR_CLOUD_FILE_DEHYDRATION_DISALLOWED",
++ "ERROR_FILE_SNAP_IN_PROGRESS",
++ "ERROR_FILE_SNAP_USER_SECTION_NOT_SUPPORTED",
++ "ERROR_FILE_SNAP_MODIFY_NOT_SUPPORTED",
++ "ERROR_FILE_SNAP_IO_NOT_COORDINATED",
++ "ERROR_FILE_SNAP_UNEXPECTED_ERROR",
++ "ERROR_FILE_SNAP_INVALID_PARAMETER",
++ "ERROR_UNSATISFIED_DEPENDENCIES",
++ "ERROR_CASE_SENSITIVE_PATH",
++ "ERROR_UNEXPECTED_NTCACHEMANAGER_ERROR",
++ "ERROR_LINUX_SUBSYSTEM_UPDATE_REQUIRED",
++ "ERROR_DLP_POLICY_WARNS_AGAINST_OPERATION",
++ "ERROR_DLP_POLICY_DENIES_OPERATION",
++ "ERROR_DLP_POLICY_SILENTLY_FAIL",
++ "ERROR_CAPAUTHZ_NOT_DEVUNLOCKED",
++ "ERROR_CAPAUTHZ_CHANGE_TYPE",
++ "ERROR_CAPAUTHZ_NOT_PROVISIONED",
++ "ERROR_CAPAUTHZ_NOT_AUTHORIZED",
++ "ERROR_CAPAUTHZ_NO_POLICY",
++ "ERROR_CAPAUTHZ_DB_CORRUPTED",
++ "ERROR_CAPAUTHZ_SCCD_INVALID_CATALOG",
++ "ERROR_CAPAUTHZ_SCCD_NO_AUTH_ENTITY",
++ "ERROR_CAPAUTHZ_SCCD_PARSE_ERROR",
++ "ERROR_CAPAUTHZ_SCCD_DEV_MODE_REQUIRED",
++ "ERROR_CAPAUTHZ_SCCD_NO_CAPABILITY_MATCH",
++ "ERROR_CIMFS_IMAGE_CORRUPT",
++ "ERROR_PNP_QUERY_REMOVE_DEVICE_TIMEOUT",
++ "ERROR_PNP_QUERY_REMOVE_RELATED_DEVICE_TIMEOUT",
++ "ERROR_PNP_QUERY_REMOVE_UNRELATED_DEVICE_TIMEOUT",
++ "ERROR_DEVICE_HARDWARE_ERROR",
++ "ERROR_INVALID_ADDRESS",
++ "ERROR_HAS_SYSTEM_CRITICAL_FILES",
++ "ERROR_USER_PROFILE_LOAD",
++ "ERROR_ARITHMETIC_OVERFLOW",
++ "ERROR_PIPE_CONNECTED",
++ "ERROR_PIPE_LISTENING",
++ "ERROR_VERIFIER_STOP",
++ "ERROR_ABIOS_ERROR",
++ "ERROR_WX86_WARNING",
++ "ERROR_WX86_ERROR",
++ "ERROR_TIMER_NOT_CANCELED",
++ "ERROR_UNWIND",
++ "ERROR_BAD_STACK",
++ "ERROR_INVALID_UNWIND_TARGET",
++ "ERROR_INVALID_PORT_ATTRIBUTES",
++ "ERROR_PORT_MESSAGE_TOO_LONG",
++ "ERROR_INVALID_QUOTA_LOWER",
++ "ERROR_DEVICE_ALREADY_ATTACHED",
++ "ERROR_INSTRUCTION_MISALIGNMENT",
++ "ERROR_PROFILING_NOT_STARTED",
++ "ERROR_PROFILING_NOT_STOPPED",
++ "ERROR_COULD_NOT_INTERPRET",
++ "ERROR_PROFILING_AT_LIMIT",
++ "ERROR_CANT_WAIT",
++ "ERROR_CANT_TERMINATE_SELF",
++ "ERROR_UNEXPECTED_MM_CREATE_ERR",
++ "ERROR_UNEXPECTED_MM_MAP_ERROR",
++ "ERROR_UNEXPECTED_MM_EXTEND_ERR",
++ "ERROR_BAD_FUNCTION_TABLE",
++ "ERROR_NO_GUID_TRANSLATION",
++ "ERROR_INVALID_LDT_SIZE",
++ "ERROR_INVALID_LDT_OFFSET",
++ "ERROR_INVALID_LDT_DESCRIPTOR",
++ "ERROR_TOO_MANY_THREADS",
++ "ERROR_THREAD_NOT_IN_PROCESS",
++ "ERROR_PAGEFILE_QUOTA_EXCEEDED",
++ "ERROR_LOGON_SERVER_CONFLICT",
++ "ERROR_SYNCHRONIZATION_REQUIRED",
++ "ERROR_NET_OPEN_FAILED",
++ "ERROR_IO_PRIVILEGE_FAILED",
++ "ERROR_CONTROL_C_EXIT",
++ "ERROR_MISSING_SYSTEMFILE",
++ "ERROR_UNHANDLED_EXCEPTION",
++ "ERROR_APP_INIT_FAILURE",
++ "ERROR_PAGEFILE_CREATE_FAILED",
++ "ERROR_INVALID_IMAGE_HASH",
++ "ERROR_NO_PAGEFILE",
++ "ERROR_ILLEGAL_FLOAT_CONTEXT",
++ "ERROR_NO_EVENT_PAIR",
++ "ERROR_DOMAIN_CTRLR_CONFIG_ERROR",
++ "ERROR_ILLEGAL_CHARACTER",
++ "ERROR_UNDEFINED_CHARACTER",
++ "ERROR_FLOPPY_VOLUME",
++ "ERROR_BIOS_FAILED_TO_CONNECT_INTERRUPT",
++ "ERROR_BACKUP_CONTROLLER",
++ "ERROR_MUTANT_LIMIT_EXCEEDED",
++ "ERROR_FS_DRIVER_REQUIRED",
++ "ERROR_CANNOT_LOAD_REGISTRY_FILE",
++ "ERROR_DEBUG_ATTACH_FAILED",
++ "ERROR_SYSTEM_PROCESS_TERMINATED",
++ "ERROR_DATA_NOT_ACCEPTED",
++ "ERROR_VDM_HARD_ERROR",
++ "ERROR_DRIVER_CANCEL_TIMEOUT",
++ "ERROR_REPLY_MESSAGE_MISMATCH",
++ "ERROR_LOST_WRITEBEHIND_DATA",
++ "ERROR_CLIENT_SERVER_PARAMETERS_INVALID",
++ "ERROR_NOT_TINY_STREAM",
++ "ERROR_STACK_OVERFLOW_READ",
++ "ERROR_CONVERT_TO_LARGE",
++ "ERROR_FOUND_OUT_OF_SCOPE",
++ "ERROR_ALLOCATE_BUCKET",
++ "ERROR_MARSHALL_OVERFLOW",
++ "ERROR_INVALID_VARIANT",
++ "ERROR_BAD_COMPRESSION_BUFFER",
++ "ERROR_AUDIT_FAILED",
++ "ERROR_TIMER_RESOLUTION_NOT_SET",
++ "ERROR_INSUFFICIENT_LOGON_INFO",
++ "ERROR_BAD_DLL_ENTRYPOINT",
++ "ERROR_BAD_SERVICE_ENTRYPOINT",
++ "ERROR_IP_ADDRESS_CONFLICT1",
++ "ERROR_IP_ADDRESS_CONFLICT2",
++ "ERROR_REGISTRY_QUOTA_LIMIT",
++ "ERROR_NO_CALLBACK_ACTIVE",
++ "ERROR_PWD_TOO_SHORT",
++ "ERROR_PWD_TOO_RECENT",
++ "ERROR_PWD_HISTORY_CONFLICT",
++ "ERROR_UNSUPPORTED_COMPRESSION",
++ "ERROR_INVALID_HW_PROFILE",
++ "ERROR_INVALID_PLUGPLAY_DEVICE_PATH",
++ "ERROR_QUOTA_LIST_INCONSISTENT",
++ "ERROR_EVALUATION_EXPIRATION",
++ "ERROR_ILLEGAL_DLL_RELOCATION",
++ "ERROR_DLL_INIT_FAILED_LOGOFF",
++ "ERROR_VALIDATE_CONTINUE",
++ "ERROR_NO_MORE_MATCHES",
++ "ERROR_RANGE_LIST_CONFLICT",
++ "ERROR_SERVER_SID_MISMATCH",
++ "ERROR_CANT_ENABLE_DENY_ONLY",
++ "ERROR_FLOAT_MULTIPLE_FAULTS",
++ "ERROR_FLOAT_MULTIPLE_TRAPS",
++ "ERROR_NOINTERFACE",
++ "ERROR_DRIVER_FAILED_SLEEP",
++ "ERROR_CORRUPT_SYSTEM_FILE",
++ "ERROR_COMMITMENT_MINIMUM",
++ "ERROR_PNP_RESTART_ENUMERATION",
++ "ERROR_SYSTEM_IMAGE_BAD_SIGNATURE",
++ "ERROR_PNP_REBOOT_REQUIRED",
++ "ERROR_INSUFFICIENT_POWER",
++ "ERROR_MULTIPLE_FAULT_VIOLATION",
++ "ERROR_SYSTEM_SHUTDOWN",
++ "ERROR_PORT_NOT_SET",
++ "ERROR_DS_VERSION_CHECK_FAILURE",
++ "ERROR_RANGE_NOT_FOUND",
++ "ERROR_NOT_SAFE_MODE_DRIVER",
++ "ERROR_FAILED_DRIVER_ENTRY",
++ "ERROR_DEVICE_ENUMERATION_ERROR",
++ "ERROR_MOUNT_POINT_NOT_RESOLVED",
++ "ERROR_INVALID_DEVICE_OBJECT_PARAMETER",
++ "ERROR_MCA_OCCURED",
++ "ERROR_DRIVER_DATABASE_ERROR",
++ "ERROR_SYSTEM_HIVE_TOO_LARGE",
++ "ERROR_DRIVER_FAILED_PRIOR_UNLOAD",
++ "ERROR_VOLSNAP_PREPARE_HIBERNATE",
++ "ERROR_HIBERNATION_FAILURE",
++ "ERROR_PWD_TOO_LONG",
++ "ERROR_FILE_SYSTEM_LIMITATION",
++ "ERROR_ASSERTION_FAILURE",
++ "ERROR_ACPI_ERROR",
++ "ERROR_WOW_ASSERTION",
++ "ERROR_PNP_BAD_MPS_TABLE",
++ "ERROR_PNP_TRANSLATION_FAILED",
++ "ERROR_PNP_IRQ_TRANSLATION_FAILED",
++ "ERROR_PNP_INVALID_ID",
++ "ERROR_WAKE_SYSTEM_DEBUGGER",
++ "ERROR_HANDLES_CLOSED",
++ "ERROR_EXTRANEOUS_INFORMATION",
++ "ERROR_RXACT_COMMIT_NECESSARY",
++ "ERROR_MEDIA_CHECK",
++ "ERROR_GUID_SUBSTITUTION_MADE",
++ "ERROR_STOPPED_ON_SYMLINK",
++ "ERROR_LONGJUMP",
++ "ERROR_PLUGPLAY_QUERY_VETOED",
++ "ERROR_UNWIND_CONSOLIDATE",
++ "ERROR_REGISTRY_HIVE_RECOVERED",
++ "ERROR_DLL_MIGHT_BE_INSECURE",
++ "ERROR_DLL_MIGHT_BE_INCOMPATIBLE",
++ "ERROR_DBG_EXCEPTION_NOT_HANDLED",
++ "ERROR_DBG_REPLY_LATER",
++ "ERROR_DBG_UNABLE_TO_PROVIDE_HANDLE",
++ "ERROR_DBG_TERMINATE_THREAD",
++ "ERROR_DBG_TERMINATE_PROCESS",
++ "ERROR_DBG_CONTROL_C",
++ "ERROR_DBG_PRINTEXCEPTION_C",
++ "ERROR_DBG_RIPEXCEPTION",
++ "ERROR_DBG_CONTROL_BREAK",
++ "ERROR_DBG_COMMAND_EXCEPTION",
++ "ERROR_OBJECT_NAME_EXISTS",
++ "ERROR_THREAD_WAS_SUSPENDED",
++ "ERROR_IMAGE_NOT_AT_BASE",
++ "ERROR_RXACT_STATE_CREATED",
++ "ERROR_SEGMENT_NOTIFICATION",
++ "ERROR_BAD_CURRENT_DIRECTORY",
++ "ERROR_FT_READ_RECOVERY_FROM_BACKUP",
++ "ERROR_FT_WRITE_RECOVERY",
++ "ERROR_IMAGE_MACHINE_TYPE_MISMATCH",
++ "ERROR_RECEIVE_PARTIAL",
++ "ERROR_RECEIVE_EXPEDITED",
++ "ERROR_RECEIVE_PARTIAL_EXPEDITED",
++ "ERROR_EVENT_DONE",
++ "ERROR_EVENT_PENDING",
++ "ERROR_CHECKING_FILE_SYSTEM",
++ "ERROR_FATAL_APP_EXIT",
++ "ERROR_PREDEFINED_HANDLE",
++ "ERROR_WAS_UNLOCKED",
++ "ERROR_SERVICE_NOTIFICATION",
++ "ERROR_WAS_LOCKED",
++ "ERROR_LOG_HARD_ERROR",
++ "ERROR_ALREADY_WIN32",
++ "ERROR_IMAGE_MACHINE_TYPE_MISMATCH_EXE",
++ "ERROR_NO_YIELD_PERFORMED",
++ "ERROR_TIMER_RESUME_IGNORED",
++ "ERROR_ARBITRATION_UNHANDLED",
++ "ERROR_CARDBUS_NOT_SUPPORTED",
++ "ERROR_MP_PROCESSOR_MISMATCH",
++ "ERROR_HIBERNATED",
++ "ERROR_RESUME_HIBERNATION",
++ "ERROR_FIRMWARE_UPDATED",
++ "ERROR_DRIVERS_LEAKING_LOCKED_PAGES",
++ "ERROR_WAKE_SYSTEM",
++ "ERROR_WAIT_1",
++ "ERROR_WAIT_2",
++ "ERROR_WAIT_3",
++ "ERROR_WAIT_63",
++ "ERROR_ABANDONED_WAIT_0",
++ "ERROR_ABANDONED_WAIT_63",
++ "ERROR_USER_APC",
++ "ERROR_KERNEL_APC",
++ "ERROR_ALERTED",
++ "ERROR_ELEVATION_REQUIRED",
++ "ERROR_REPARSE",
++ "ERROR_OPLOCK_BREAK_IN_PROGRESS",
++ "ERROR_VOLUME_MOUNTED",
++ "ERROR_RXACT_COMMITTED",
++ "ERROR_NOTIFY_CLEANUP",
++ "ERROR_PRIMARY_TRANSPORT_CONNECT_FAILED",
++ "ERROR_PAGE_FAULT_TRANSITION",
++ "ERROR_PAGE_FAULT_DEMAND_ZERO",
++ "ERROR_PAGE_FAULT_COPY_ON_WRITE",
++ "ERROR_PAGE_FAULT_GUARD_PAGE",
++ "ERROR_PAGE_FAULT_PAGING_FILE",
++ "ERROR_CACHE_PAGE_LOCKED",
++ "ERROR_CRASH_DUMP",
++ "ERROR_BUFFER_ALL_ZEROS",
++ "ERROR_REPARSE_OBJECT",
++ "ERROR_RESOURCE_REQUIREMENTS_CHANGED",
++ "ERROR_TRANSLATION_COMPLETE",
++ "ERROR_NOTHING_TO_TERMINATE",
++ "ERROR_PROCESS_NOT_IN_JOB",
++ "ERROR_PROCESS_IN_JOB",
++ "ERROR_VOLSNAP_HIBERNATE_READY",
++ "ERROR_FSFILTER_OP_COMPLETED_SUCCESSFULLY",
++ "ERROR_INTERRUPT_VECTOR_ALREADY_CONNECTED",
++ "ERROR_INTERRUPT_STILL_CONNECTED",
++ "ERROR_WAIT_FOR_OPLOCK",
++ "ERROR_DBG_EXCEPTION_HANDLED",
++ "ERROR_DBG_CONTINUE",
++ "ERROR_CALLBACK_POP_STACK",
++ "ERROR_COMPRESSION_DISABLED",
++ "ERROR_CANTFETCHBACKWARDS",
++ "ERROR_CANTSCROLLBACKWARDS",
++ "ERROR_ROWSNOTRELEASED",
++ "ERROR_BAD_ACCESSOR_FLAGS",
++ "ERROR_ERRORS_ENCOUNTERED",
++ "ERROR_NOT_CAPABLE",
++ "ERROR_REQUEST_OUT_OF_SEQUENCE",
++ "ERROR_VERSION_PARSE_ERROR",
++ "ERROR_BADSTARTPOSITION",
++ "ERROR_MEMORY_HARDWARE",
++ "ERROR_DISK_REPAIR_DISABLED",
++ "ERROR_INSUFFICIENT_RESOURCE_FOR_SPECIFIED_SHARED_SECTION_SIZE",
++ "ERROR_SYSTEM_POWERSTATE_TRANSITION",
++ "ERROR_SYSTEM_POWERSTATE_COMPLEX_TRANSITION",
++ "ERROR_MCA_EXCEPTION",
++ "ERROR_ACCESS_AUDIT_BY_POLICY",
++ "ERROR_ACCESS_DISABLED_NO_SAFER_UI_BY_POLICY",
++ "ERROR_ABANDON_HIBERFILE",
++ "ERROR_LOST_WRITEBEHIND_DATA_NETWORK_DISCONNECTED",
++ "ERROR_LOST_WRITEBEHIND_DATA_NETWORK_SERVER_ERROR",
++ "ERROR_LOST_WRITEBEHIND_DATA_LOCAL_DISK_ERROR",
++ "ERROR_BAD_MCFG_TABLE",
++ "ERROR_DISK_REPAIR_REDIRECTED",
++ "ERROR_DISK_REPAIR_UNSUCCESSFUL",
++ "ERROR_CORRUPT_LOG_OVERFULL",
++ "ERROR_CORRUPT_LOG_CORRUPTED",
++ "ERROR_CORRUPT_LOG_UNAVAILABLE",
++ "ERROR_CORRUPT_LOG_DELETED_FULL",
++ "ERROR_CORRUPT_LOG_CLEARED",
++ "ERROR_ORPHAN_NAME_EXHAUSTED",
++ "ERROR_OPLOCK_SWITCHED_TO_NEW_HANDLE",
++ "ERROR_CANNOT_GRANT_REQUESTED_OPLOCK",
++ "ERROR_CANNOT_BREAK_OPLOCK",
++ "ERROR_OPLOCK_HANDLE_CLOSED",
++ "ERROR_NO_ACE_CONDITION",
++ "ERROR_INVALID_ACE_CONDITION",
++ "ERROR_FILE_HANDLE_REVOKED",
++ "ERROR_IMAGE_AT_DIFFERENT_BASE",
++ "ERROR_ENCRYPTED_IO_NOT_POSSIBLE",
++ "ERROR_FILE_METADATA_OPTIMIZATION_IN_PROGRESS",
++ "ERROR_QUOTA_ACTIVITY",
++ "ERROR_HANDLE_REVOKED",
++ "ERROR_CALLBACK_INVOKE_INLINE",
++ "ERROR_CPU_SET_INVALID",
++ "ERROR_ENCLAVE_NOT_TERMINATED",
++ "ERROR_ENCLAVE_VIOLATION",
++ "ERROR_EA_ACCESS_DENIED",
++ "ERROR_OPERATION_ABORTED",
++ "ERROR_IO_INCOMPLETE",
++ "ERROR_IO_PENDING",
++ "ERROR_NOACCESS",
++ "ERROR_SWAPERROR",
++ "ERROR_STACK_OVERFLOW",
++ "ERROR_INVALID_MESSAGE",
++ "ERROR_CAN_NOT_COMPLETE",
++ "ERROR_INVALID_FLAGS",
++ "ERROR_UNRECOGNIZED_VOLUME",
++ "ERROR_FILE_INVALID",
++ "ERROR_FULLSCREEN_MODE",
++ "ERROR_NO_TOKEN",
++ "ERROR_BADDB",
++ "ERROR_BADKEY",
++ "ERROR_CANTOPEN",
++ "ERROR_CANTREAD",
++ "ERROR_CANTWRITE",
++ "ERROR_REGISTRY_RECOVERED",
++ "ERROR_REGISTRY_CORRUPT",
++ "ERROR_REGISTRY_IO_FAILED",
++ "ERROR_NOT_REGISTRY_FILE",
++ "ERROR_KEY_DELETED",
++ "ERROR_NO_LOG_SPACE",
++ "ERROR_KEY_HAS_CHILDREN",
++ "ERROR_CHILD_MUST_BE_VOLATILE",
++ "ERROR_NOTIFY_ENUM_DIR",
++ "ERROR_DEPENDENT_SERVICES_RUNNING",
++ "ERROR_INVALID_SERVICE_CONTROL",
++ "ERROR_SERVICE_REQUEST_TIMEOUT",
++ "ERROR_SERVICE_NO_THREAD",
++ "ERROR_SERVICE_DATABASE_LOCKED",
++ "ERROR_SERVICE_ALREADY_RUNNING",
++ "ERROR_INVALID_SERVICE_ACCOUNT",
++ "ERROR_SERVICE_DISABLED",
++ "ERROR_CIRCULAR_DEPENDENCY",
++ "ERROR_SERVICE_DOES_NOT_EXIST",
++ "ERROR_SERVICE_CANNOT_ACCEPT_CTRL",
++ "ERROR_SERVICE_NOT_ACTIVE",
++ "ERROR_FAILED_SERVICE_CONTROLLER_CONNECT",
++ "ERROR_EXCEPTION_IN_SERVICE",
++ "ERROR_DATABASE_DOES_NOT_EXIST",
++ "ERROR_SERVICE_SPECIFIC_ERROR",
++ "ERROR_PROCESS_ABORTED",
++ "ERROR_SERVICE_DEPENDENCY_FAIL",
++ "ERROR_SERVICE_LOGON_FAILED",
++ "ERROR_SERVICE_START_HANG",
++ "ERROR_INVALID_SERVICE_LOCK",
++ "ERROR_SERVICE_MARKED_FOR_DELETE",
++ "ERROR_SERVICE_EXISTS",
++ "ERROR_ALREADY_RUNNING_LKG",
++ "ERROR_SERVICE_DEPENDENCY_DELETED",
++ "ERROR_BOOT_ALREADY_ACCEPTED",
++ "ERROR_SERVICE_NEVER_STARTED",
++ "ERROR_DUPLICATE_SERVICE_NAME",
++ "ERROR_DIFFERENT_SERVICE_ACCOUNT",
++ "ERROR_CANNOT_DETECT_DRIVER_FAILURE",
++ "ERROR_CANNOT_DETECT_PROCESS_ABORT",
++ "ERROR_NO_RECOVERY_PROGRAM",
++ "ERROR_SERVICE_NOT_IN_EXE",
++ "ERROR_NOT_SAFEBOOT_SERVICE",
++ "ERROR_END_OF_MEDIA",
++ "ERROR_FILEMARK_DETECTED",
++ "ERROR_BEGINNING_OF_MEDIA",
++ "ERROR_SETMARK_DETECTED",
++ "ERROR_NO_DATA_DETECTED",
++ "ERROR_PARTITION_FAILURE",
++ "ERROR_INVALID_BLOCK_LENGTH",
++ "ERROR_DEVICE_NOT_PARTITIONED",
++ "ERROR_UNABLE_TO_LOCK_MEDIA",
++ "ERROR_UNABLE_TO_UNLOAD_MEDIA",
++ "ERROR_MEDIA_CHANGED",
++ "ERROR_BUS_RESET",
++ "ERROR_NO_MEDIA_IN_DRIVE",
++ "ERROR_NO_UNICODE_TRANSLATION",
++ "ERROR_DLL_INIT_FAILED",
++ "ERROR_SHUTDOWN_IN_PROGRESS",
++ "ERROR_NO_SHUTDOWN_IN_PROGRESS",
++ "ERROR_IO_DEVICE",
++ "ERROR_SERIAL_NO_DEVICE",
++ "ERROR_IRQ_BUSY",
++ "ERROR_MORE_WRITES",
++ "ERROR_COUNTER_TIMEOUT",
++ "ERROR_FLOPPY_ID_MARK_NOT_FOUND",
++ "ERROR_FLOPPY_WRONG_CYLINDER",
++ "ERROR_FLOPPY_UNKNOWN_ERROR",
++ "ERROR_FLOPPY_BAD_REGISTERS",
++ "ERROR_DISK_RECALIBRATE_FAILED",
++ "ERROR_DISK_OPERATION_FAILED",
++ "ERROR_DISK_RESET_FAILED",
++ "ERROR_EOM_OVERFLOW",
++ "ERROR_NOT_ENOUGH_SERVER_MEMORY",
++ "ERROR_POSSIBLE_DEADLOCK",
++ "ERROR_MAPPED_ALIGNMENT",
++ "ERROR_SET_POWER_STATE_VETOED",
++ "ERROR_SET_POWER_STATE_FAILED",
++ "ERROR_TOO_MANY_LINKS",
++ "ERROR_OLD_WIN_VERSION",
++ "ERROR_APP_WRONG_OS",
++ "ERROR_SINGLE_INSTANCE_APP",
++ "ERROR_RMODE_APP",
++ "ERROR_INVALID_DLL",
++ "ERROR_NO_ASSOCIATION",
++ "ERROR_DDE_FAIL",
++ "ERROR_DLL_NOT_FOUND",
++ "ERROR_NO_MORE_USER_HANDLES",
++ "ERROR_MESSAGE_SYNC_ONLY",
++ "ERROR_SOURCE_ELEMENT_EMPTY",
++ "ERROR_DESTINATION_ELEMENT_FULL",
++ "ERROR_ILLEGAL_ELEMENT_ADDRESS",
++ "ERROR_MAGAZINE_NOT_PRESENT",
++ "ERROR_DEVICE_REINITIALIZATION_NEEDED",
++ "ERROR_DEVICE_REQUIRES_CLEANING",
++ "ERROR_DEVICE_DOOR_OPEN",
++ "ERROR_DEVICE_NOT_CONNECTED",
++ "ERROR_NOT_FOUND",
++ "ERROR_NO_MATCH",
++ "ERROR_SET_NOT_FOUND",
++ "ERROR_POINT_NOT_FOUND",
++ "ERROR_NO_TRACKING_SERVICE",
++ "ERROR_NO_VOLUME_ID",
++ "ERROR_UNABLE_TO_REMOVE_REPLACED",
++ "ERROR_UNABLE_TO_MOVE_REPLACEMENT",
++ "ERROR_UNABLE_TO_MOVE_REPLACEMENT_2",
++ "ERROR_JOURNAL_DELETE_IN_PROGRESS",
++ "ERROR_JOURNAL_NOT_ACTIVE",
++ "ERROR_POTENTIAL_FILE_FOUND",
++ "ERROR_JOURNAL_ENTRY_DELETED",
++ "ERROR_VRF_CFG_AND_IO_ENABLED",
++ "ERROR_PARTITION_TERMINATING",
++ "ERROR_SHUTDOWN_IS_SCHEDULED",
++ "ERROR_SHUTDOWN_USERS_LOGGED_ON",
++ "ERROR_BAD_DEVICE",
++ "ERROR_CONNECTION_UNAVAIL",
++ "ERROR_DEVICE_ALREADY_REMEMBERED",
++ "ERROR_NO_NET_OR_BAD_PATH",
++ "ERROR_BAD_PROVIDER",
++ "ERROR_CANNOT_OPEN_PROFILE",
++ "ERROR_BAD_PROFILE",
++ "ERROR_NOT_CONTAINER",
++ "ERROR_EXTENDED_ERROR",
++ "ERROR_INVALID_GROUPNAME",
++ "ERROR_INVALID_COMPUTERNAME",
++ "ERROR_INVALID_EVENTNAME",
++ "ERROR_INVALID_DOMAINNAME",
++ "ERROR_INVALID_SERVICENAME",
++ "ERROR_INVALID_NETNAME",
++ "ERROR_INVALID_SHARENAME",
++ "ERROR_INVALID_PASSWORDNAME",
++ "ERROR_INVALID_MESSAGENAME",
++ "ERROR_INVALID_MESSAGEDEST",
++ "ERROR_SESSION_CREDENTIAL_CONFLICT",
++ "ERROR_REMOTE_SESSION_LIMIT_EXCEEDED",
++ "ERROR_DUP_DOMAINNAME",
++ "ERROR_NO_NETWORK",
++ "ERROR_CANCELLED",
++ "ERROR_USER_MAPPED_FILE",
++ "ERROR_CONNECTION_REFUSED",
++ "ERROR_GRACEFUL_DISCONNECT",
++ "ERROR_ADDRESS_ALREADY_ASSOCIATED",
++ "ERROR_ADDRESS_NOT_ASSOCIATED",
++ "ERROR_CONNECTION_INVALID",
++ "ERROR_CONNECTION_ACTIVE",
++ "ERROR_NETWORK_UNREACHABLE",
++ "ERROR_HOST_UNREACHABLE",
++ "ERROR_PROTOCOL_UNREACHABLE",
++ "ERROR_PORT_UNREACHABLE",
++ "ERROR_REQUEST_ABORTED",
++ "ERROR_CONNECTION_ABORTED",
++ "ERROR_RETRY",
++ "ERROR_CONNECTION_COUNT_LIMIT",
++ "ERROR_LOGIN_TIME_RESTRICTION",
++ "ERROR_LOGIN_WKSTA_RESTRICTION",
++ "ERROR_INCORRECT_ADDRESS",
++ "ERROR_ALREADY_REGISTERED",
++ "ERROR_SERVICE_NOT_FOUND",
++ "ERROR_NOT_AUTHENTICATED",
++ "ERROR_NOT_LOGGED_ON",
++ "ERROR_CONTINUE",
++ "ERROR_ALREADY_INITIALIZED",
++ "ERROR_NO_MORE_DEVICES",
++ "ERROR_NO_SUCH_SITE",
++ "ERROR_DOMAIN_CONTROLLER_EXISTS",
++ "ERROR_ONLY_IF_CONNECTED",
++ "ERROR_OVERRIDE_NOCHANGES",
++ "ERROR_BAD_USER_PROFILE",
++ "ERROR_NOT_SUPPORTED_ON_SBS",
++ "ERROR_SERVER_SHUTDOWN_IN_PROGRESS",
++ "ERROR_HOST_DOWN",
++ "ERROR_NON_ACCOUNT_SID",
++ "ERROR_NON_DOMAIN_SID",
++ "ERROR_APPHELP_BLOCK",
++ "ERROR_ACCESS_DISABLED_BY_POLICY",
++ "ERROR_REG_NAT_CONSUMPTION",
++ "ERROR_CSCSHARE_OFFLINE",
++ "ERROR_PKINIT_FAILURE",
++ "ERROR_SMARTCARD_SUBSYSTEM_FAILURE",
++ "ERROR_DOWNGRADE_DETECTED",
++ "ERROR_MACHINE_LOCKED",
++ "ERROR_SMB_GUEST_LOGON_BLOCKED",
++ "ERROR_CALLBACK_SUPPLIED_INVALID_DATA",
++ "ERROR_SYNC_FOREGROUND_REFRESH_REQUIRED",
++ "ERROR_DRIVER_BLOCKED",
++ "ERROR_INVALID_IMPORT_OF_NON_DLL",
++ "ERROR_ACCESS_DISABLED_WEBBLADE",
++ "ERROR_ACCESS_DISABLED_WEBBLADE_TAMPER",
++ "ERROR_RECOVERY_FAILURE",
++ "ERROR_ALREADY_FIBER",
++ "ERROR_ALREADY_THREAD",
++ "ERROR_STACK_BUFFER_OVERRUN",
++ "ERROR_PARAMETER_QUOTA_EXCEEDED",
++ "ERROR_DEBUGGER_INACTIVE",
++ "ERROR_DELAY_LOAD_FAILED",
++ "ERROR_VDM_DISALLOWED",
++ "ERROR_UNIDENTIFIED_ERROR",
++ "ERROR_INVALID_CRUNTIME_PARAMETER",
++ "ERROR_BEYOND_VDL",
++ "ERROR_INCOMPATIBLE_SERVICE_SID_TYPE",
++ "ERROR_DRIVER_PROCESS_TERMINATED",
++ "ERROR_IMPLEMENTATION_LIMIT",
++ "ERROR_PROCESS_IS_PROTECTED",
++ "ERROR_SERVICE_NOTIFY_CLIENT_LAGGING",
++ "ERROR_DISK_QUOTA_EXCEEDED",
++ "ERROR_CONTENT_BLOCKED",
++ "ERROR_INCOMPATIBLE_SERVICE_PRIVILEGE",
++ "ERROR_APP_HANG",
++ "ERROR_INVALID_LABEL",
++ "ERROR_NOT_ALL_ASSIGNED",
++ "ERROR_SOME_NOT_MAPPED",
++ "ERROR_NO_QUOTAS_FOR_ACCOUNT",
++ "ERROR_LOCAL_USER_SESSION_KEY",
++ "ERROR_NULL_LM_PASSWORD",
++ "ERROR_UNKNOWN_REVISION",
++ "ERROR_REVISION_MISMATCH",
++ "ERROR_INVALID_OWNER",
++ "ERROR_INVALID_PRIMARY_GROUP",
++ "ERROR_NO_IMPERSONATION_TOKEN",
++ "ERROR_CANT_DISABLE_MANDATORY",
++ "ERROR_NO_LOGON_SERVERS",
++ "ERROR_NO_SUCH_LOGON_SESSION",
++ "ERROR_NO_SUCH_PRIVILEGE",
++ "ERROR_PRIVILEGE_NOT_HELD",
++ "ERROR_INVALID_ACCOUNT_NAME",
++ "ERROR_USER_EXISTS",
++ "ERROR_NO_SUCH_USER",
++ "ERROR_GROUP_EXISTS",
++ "ERROR_NO_SUCH_GROUP",
++ "ERROR_MEMBER_IN_GROUP",
++ "ERROR_MEMBER_NOT_IN_GROUP",
++ "ERROR_LAST_ADMIN",
++ "ERROR_WRONG_PASSWORD",
++ "ERROR_ILL_FORMED_PASSWORD",
++ "ERROR_PASSWORD_RESTRICTION",
++ "ERROR_LOGON_FAILURE",
++ "ERROR_ACCOUNT_RESTRICTION",
++ "ERROR_INVALID_LOGON_HOURS",
++ "ERROR_INVALID_WORKSTATION",
++ "ERROR_PASSWORD_EXPIRED",
++ "ERROR_ACCOUNT_DISABLED",
++ "ERROR_NONE_MAPPED",
++ "ERROR_TOO_MANY_LUIDS_REQUESTED",
++ "ERROR_LUIDS_EXHAUSTED",
++ "ERROR_INVALID_SUB_AUTHORITY",
++ "ERROR_INVALID_ACL",
++ "ERROR_INVALID_SID",
++ "ERROR_INVALID_SECURITY_DESCR",
++ "ERROR_BAD_INHERITANCE_ACL",
++ "ERROR_SERVER_DISABLED",
++ "ERROR_SERVER_NOT_DISABLED",
++ "ERROR_INVALID_ID_AUTHORITY",
++ "ERROR_ALLOTTED_SPACE_EXCEEDED",
++ "ERROR_INVALID_GROUP_ATTRIBUTES",
++ "ERROR_BAD_IMPERSONATION_LEVEL",
++ "ERROR_CANT_OPEN_ANONYMOUS",
++ "ERROR_BAD_VALIDATION_CLASS",
++ "ERROR_BAD_TOKEN_TYPE",
++ "ERROR_NO_SECURITY_ON_OBJECT",
++ "ERROR_CANT_ACCESS_DOMAIN_INFO",
++ "ERROR_INVALID_SERVER_STATE",
++ "ERROR_INVALID_DOMAIN_STATE",
++ "ERROR_INVALID_DOMAIN_ROLE",
++ "ERROR_NO_SUCH_DOMAIN",
++ "ERROR_DOMAIN_EXISTS",
++ "ERROR_DOMAIN_LIMIT_EXCEEDED",
++ "ERROR_INTERNAL_DB_CORRUPTION",
++ "ERROR_INTERNAL_ERROR",
++ "ERROR_GENERIC_NOT_MAPPED",
++ "ERROR_BAD_DESCRIPTOR_FORMAT",
++ "ERROR_NOT_LOGON_PROCESS",
++ "ERROR_LOGON_SESSION_EXISTS",
++ "ERROR_NO_SUCH_PACKAGE",
++ "ERROR_BAD_LOGON_SESSION_STATE",
++ "ERROR_LOGON_SESSION_COLLISION",
++ "ERROR_INVALID_LOGON_TYPE",
++ "ERROR_CANNOT_IMPERSONATE",
++ "ERROR_RXACT_INVALID_STATE",
++ "ERROR_RXACT_COMMIT_FAILURE",
++ "ERROR_SPECIAL_ACCOUNT",
++ "ERROR_SPECIAL_GROUP",
++ "ERROR_SPECIAL_USER",
++ "ERROR_MEMBERS_PRIMARY_GROUP",
++ "ERROR_TOKEN_ALREADY_IN_USE",
++ "ERROR_NO_SUCH_ALIAS",
++ "ERROR_MEMBER_NOT_IN_ALIAS",
++ "ERROR_MEMBER_IN_ALIAS",
++ "ERROR_ALIAS_EXISTS",
++ "ERROR_LOGON_NOT_GRANTED",
++ "ERROR_TOO_MANY_SECRETS",
++ "ERROR_SECRET_TOO_LONG",
++ "ERROR_INTERNAL_DB_ERROR",
++ "ERROR_TOO_MANY_CONTEXT_IDS",
++ "ERROR_LOGON_TYPE_NOT_GRANTED",
++ "ERROR_NT_CROSS_ENCRYPTION_REQUIRED",
++ "ERROR_NO_SUCH_MEMBER",
++ "ERROR_INVALID_MEMBER",
++ "ERROR_TOO_MANY_SIDS",
++ "ERROR_LM_CROSS_ENCRYPTION_REQUIRED",
++ "ERROR_NO_INHERITANCE",
++ "ERROR_FILE_CORRUPT",
++ "ERROR_DISK_CORRUPT",
++ "ERROR_NO_USER_SESSION_KEY",
++ "ERROR_LICENSE_QUOTA_EXCEEDED",
++ "ERROR_WRONG_TARGET_NAME",
++ "ERROR_MUTUAL_AUTH_FAILED",
++ "ERROR_TIME_SKEW",
++ "ERROR_CURRENT_DOMAIN_NOT_ALLOWED",
++ "ERROR_INVALID_WINDOW_HANDLE",
++ "ERROR_INVALID_MENU_HANDLE",
++ "ERROR_INVALID_CURSOR_HANDLE",
++ "ERROR_INVALID_ACCEL_HANDLE",
++ "ERROR_INVALID_HOOK_HANDLE",
++ "ERROR_INVALID_DWP_HANDLE",
++ "ERROR_TLW_WITH_WSCHILD",
++ "ERROR_CANNOT_FIND_WND_CLASS",
++ "ERROR_WINDOW_OF_OTHER_THREAD",
++ "ERROR_HOTKEY_ALREADY_REGISTERED",
++ "ERROR_CLASS_ALREADY_EXISTS",
++ "ERROR_CLASS_DOES_NOT_EXIST",
++ "ERROR_CLASS_HAS_WINDOWS",
++ "ERROR_INVALID_INDEX",
++ "ERROR_INVALID_ICON_HANDLE",
++ "ERROR_PRIVATE_DIALOG_INDEX",
++ "ERROR_LISTBOX_ID_NOT_FOUND",
++ "ERROR_NO_WILDCARD_CHARACTERS",
++ "ERROR_CLIPBOARD_NOT_OPEN",
++ "ERROR_HOTKEY_NOT_REGISTERED",
++ "ERROR_WINDOW_NOT_DIALOG",
++ "ERROR_CONTROL_ID_NOT_FOUND",
++ "ERROR_INVALID_COMBOBOX_MESSAGE",
++ "ERROR_WINDOW_NOT_COMBOBOX",
++ "ERROR_INVALID_EDIT_HEIGHT",
++ "ERROR_DC_NOT_FOUND",
++ "ERROR_INVALID_HOOK_FILTER",
++ "ERROR_INVALID_FILTER_PROC",
++ "ERROR_HOOK_NEEDS_HMOD",
++ "ERROR_GLOBAL_ONLY_HOOK",
++ "ERROR_JOURNAL_HOOK_SET",
++ "ERROR_HOOK_NOT_INSTALLED",
++ "ERROR_INVALID_LB_MESSAGE",
++ "ERROR_SETCOUNT_ON_BAD_LB",
++ "ERROR_LB_WITHOUT_TABSTOPS",
++ "ERROR_DESTROY_OBJECT_OF_OTHER_THREAD",
++ "ERROR_CHILD_WINDOW_MENU",
++ "ERROR_NO_SYSTEM_MENU",
++ "ERROR_INVALID_MSGBOX_STYLE",
++ "ERROR_INVALID_SPI_VALUE",
++ "ERROR_SCREEN_ALREADY_LOCKED",
++ "ERROR_HWNDS_HAVE_DIFF_PARENT",
++ "ERROR_NOT_CHILD_WINDOW",
++ "ERROR_INVALID_GW_COMMAND",
++ "ERROR_INVALID_THREAD_ID",
++ "ERROR_NON_MDICHILD_WINDOW",
++ "ERROR_POPUP_ALREADY_ACTIVE",
++ "ERROR_NO_SCROLLBARS",
++ "ERROR_INVALID_SCROLLBAR_RANGE",
++ "ERROR_INVALID_SHOWWIN_COMMAND",
++ "ERROR_NO_SYSTEM_RESOURCES",
++ "ERROR_NONPAGED_SYSTEM_RESOURCES",
++ "ERROR_PAGED_SYSTEM_RESOURCES",
++ "ERROR_WORKING_SET_QUOTA",
++ "ERROR_PAGEFILE_QUOTA",
++ "ERROR_COMMITMENT_LIMIT",
++ "ERROR_MENU_ITEM_NOT_FOUND",
++ "ERROR_INVALID_KEYBOARD_HANDLE",
++ "ERROR_HOOK_TYPE_NOT_ALLOWED",
++ "ERROR_REQUIRES_INTERACTIVE_WINDOWSTATION",
++ "ERROR_TIMEOUT",
++ "ERROR_INVALID_MONITOR_HANDLE",
++ "ERROR_INCORRECT_SIZE",
++ "ERROR_SYMLINK_CLASS_DISABLED",
++ "ERROR_SYMLINK_NOT_SUPPORTED",
++ "ERROR_XML_PARSE_ERROR",
++ "ERROR_XMLDSIG_ERROR",
++ "ERROR_RESTART_APPLICATION",
++ "ERROR_WRONG_COMPARTMENT",
++ "ERROR_AUTHIP_FAILURE",
++ "ERROR_NO_NVRAM_RESOURCES",
++ "ERROR_NOT_GUI_PROCESS",
++ "ERROR_EVENTLOG_FILE_CORRUPT",
++ "ERROR_EVENTLOG_CANT_START",
++ "ERROR_LOG_FILE_FULL",
++ "ERROR_EVENTLOG_FILE_CHANGED",
++ "ERROR_CONTAINER_ASSIGNED",
++ "ERROR_JOB_NO_CONTAINER",
++ "ERROR_INVALID_TASK_NAME",
++ "ERROR_INVALID_TASK_INDEX",
++ "ERROR_THREAD_ALREADY_IN_TASK",
++ "ERROR_INSTALL_SERVICE_FAILURE",
++ "ERROR_INSTALL_USEREXIT",
++ "ERROR_INSTALL_FAILURE",
++ "ERROR_INSTALL_SUSPEND",
++ "ERROR_UNKNOWN_PRODUCT",
++ "ERROR_UNKNOWN_FEATURE",
++ "ERROR_UNKNOWN_COMPONENT",
++ "ERROR_UNKNOWN_PROPERTY",
++ "ERROR_INVALID_HANDLE_STATE",
++ "ERROR_BAD_CONFIGURATION",
++ "ERROR_INDEX_ABSENT",
++ "ERROR_INSTALL_SOURCE_ABSENT",
++ "ERROR_INSTALL_PACKAGE_VERSION",
++ "ERROR_PRODUCT_UNINSTALLED",
++ "ERROR_BAD_QUERY_SYNTAX",
++ "ERROR_INVALID_FIELD",
++ "ERROR_DEVICE_REMOVED",
++ "ERROR_INSTALL_ALREADY_RUNNING",
++ "ERROR_INSTALL_PACKAGE_OPEN_FAILED",
++ "ERROR_INSTALL_PACKAGE_INVALID",
++ "ERROR_INSTALL_UI_FAILURE",
++ "ERROR_INSTALL_LOG_FAILURE",
++ "ERROR_INSTALL_LANGUAGE_UNSUPPORTED",
++ "ERROR_INSTALL_TRANSFORM_FAILURE",
++ "ERROR_INSTALL_PACKAGE_REJECTED",
++ "ERROR_FUNCTION_NOT_CALLED",
++ "ERROR_FUNCTION_FAILED",
++ "ERROR_INVALID_TABLE",
++ "ERROR_DATATYPE_MISMATCH",
++ "ERROR_UNSUPPORTED_TYPE",
++ "ERROR_CREATE_FAILED",
++ "ERROR_INSTALL_TEMP_UNWRITABLE",
++ "ERROR_INSTALL_PLATFORM_UNSUPPORTED",
++ "ERROR_INSTALL_NOTUSED",
++ "ERROR_PATCH_PACKAGE_OPEN_FAILED",
++ "ERROR_PATCH_PACKAGE_INVALID",
++ "ERROR_PATCH_PACKAGE_UNSUPPORTED",
++ "ERROR_PRODUCT_VERSION",
++ "ERROR_INVALID_COMMAND_LINE",
++ "ERROR_INSTALL_REMOTE_DISALLOWED",
++ "ERROR_SUCCESS_REBOOT_INITIATED",
++ "ERROR_PATCH_TARGET_NOT_FOUND",
++ "ERROR_PATCH_PACKAGE_REJECTED",
++ "ERROR_INSTALL_TRANSFORM_REJECTED",
++ "ERROR_INSTALL_REMOTE_PROHIBITED",
++ "ERROR_PATCH_REMOVAL_UNSUPPORTED",
++ "ERROR_UNKNOWN_PATCH",
++ "ERROR_PATCH_NO_SEQUENCE",
++ "ERROR_PATCH_REMOVAL_DISALLOWED",
++ "ERROR_INVALID_PATCH_XML",
++ "ERROR_PATCH_MANAGED_ADVERTISED_PRODUCT",
++ "ERROR_INSTALL_SERVICE_SAFEBOOT",
++ "ERROR_FAIL_FAST_EXCEPTION",
++ "ERROR_INSTALL_REJECTED",
++ "ERROR_DYNAMIC_CODE_BLOCKED",
++ "ERROR_NOT_SAME_OBJECT",
++ "ERROR_STRICT_CFG_VIOLATION",
++ "ERROR_SET_CONTEXT_DENIED",
++ "ERROR_CROSS_PARTITION_VIOLATION",
++ "ERROR_RETURN_ADDRESS_HIJACK_ATTEMPT",
++ "ERROR_INVALID_USER_BUFFER",
++ "ERROR_UNRECOGNIZED_MEDIA",
++ "ERROR_NO_TRUST_LSA_SECRET",
++ "ERROR_NO_TRUST_SAM_ACCOUNT",
++ "ERROR_TRUSTED_DOMAIN_FAILURE",
++ "ERROR_TRUSTED_RELATIONSHIP_FAILURE",
++ "ERROR_TRUST_FAILURE",
++ "ERROR_NETLOGON_NOT_STARTED",
++ "ERROR_ACCOUNT_EXPIRED",
++ "ERROR_REDIRECTOR_HAS_OPEN_HANDLES",
++ "ERROR_PRINTER_DRIVER_ALREADY_INSTALLED",
++ "ERROR_UNKNOWN_PORT",
++ "ERROR_UNKNOWN_PRINTER_DRIVER",
++ "ERROR_UNKNOWN_PRINTPROCESSOR",
++ "ERROR_INVALID_SEPARATOR_FILE",
++ "ERROR_INVALID_PRIORITY",
++ "ERROR_INVALID_PRINTER_NAME",
++ "ERROR_PRINTER_ALREADY_EXISTS",
++ "ERROR_INVALID_PRINTER_COMMAND",
++ "ERROR_INVALID_DATATYPE",
++ "ERROR_INVALID_ENVIRONMENT",
++ "ERROR_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT",
++ "ERROR_NOLOGON_WORKSTATION_TRUST_ACCOUNT",
++ "ERROR_NOLOGON_SERVER_TRUST_ACCOUNT",
++ "ERROR_DOMAIN_TRUST_INCONSISTENT",
++ "ERROR_SERVER_HAS_OPEN_HANDLES",
++ "ERROR_RESOURCE_DATA_NOT_FOUND",
++ "ERROR_RESOURCE_TYPE_NOT_FOUND",
++ "ERROR_RESOURCE_NAME_NOT_FOUND",
++ "ERROR_RESOURCE_LANG_NOT_FOUND",
++ "ERROR_NOT_ENOUGH_QUOTA",
++ "ERROR_INVALID_TIME",
++ "ERROR_INVALID_FORM_NAME",
++ "ERROR_INVALID_FORM_SIZE",
++ "ERROR_ALREADY_WAITING",
++ "ERROR_PRINTER_DELETED",
++ "ERROR_INVALID_PRINTER_STATE",
++ "ERROR_PASSWORD_MUST_CHANGE",
++ "ERROR_DOMAIN_CONTROLLER_NOT_FOUND",
++ "ERROR_ACCOUNT_LOCKED_OUT",
++ "ERROR_NO_SITENAME",
++ "ERROR_CANT_ACCESS_FILE",
++ "ERROR_CANT_RESOLVE_FILENAME",
++ "ERROR_KM_DRIVER_BLOCKED",
++ "ERROR_CONTEXT_EXPIRED",
++ "ERROR_PER_USER_TRUST_QUOTA_EXCEEDED",
++ "ERROR_ALL_USER_TRUST_QUOTA_EXCEEDED",
++ "ERROR_USER_DELETE_TRUST_QUOTA_EXCEEDED",
++ "ERROR_AUTHENTICATION_FIREWALL_FAILED",
++ "ERROR_REMOTE_PRINT_CONNECTIONS_BLOCKED",
++ "ERROR_NTLM_BLOCKED",
++ "ERROR_PASSWORD_CHANGE_REQUIRED",
++ "ERROR_LOST_MODE_LOGON_RESTRICTION",
++ "ERROR_INVALID_PIXEL_FORMAT",
++ "ERROR_BAD_DRIVER",
++ "ERROR_INVALID_WINDOW_STYLE",
++ "ERROR_METAFILE_NOT_SUPPORTED",
++ "ERROR_TRANSFORM_NOT_SUPPORTED",
++ "ERROR_CLIPPING_NOT_SUPPORTED",
++ "ERROR_INVALID_CMM",
++ "ERROR_INVALID_PROFILE",
++ "ERROR_TAG_NOT_FOUND",
++ "ERROR_TAG_NOT_PRESENT",
++ "ERROR_DUPLICATE_TAG",
++ "ERROR_PROFILE_NOT_ASSOCIATED_WITH_DEVICE",
++ "ERROR_PROFILE_NOT_FOUND",
++ "ERROR_INVALID_COLORSPACE",
++ "ERROR_ICM_NOT_ENABLED",
++ "ERROR_DELETING_ICM_XFORM",
++ "ERROR_INVALID_TRANSFORM",
++ "ERROR_COLORSPACE_MISMATCH",
++ "ERROR_INVALID_COLORINDEX",
++ "ERROR_PROFILE_DOES_NOT_MATCH_DEVICE",
++ "ERROR_CONNECTED_OTHER_PASSWORD",
++ "ERROR_CONNECTED_OTHER_PASSWORD_DEFAULT",
++ "ERROR_BAD_USERNAME",
++ "ERROR_NOT_CONNECTED",
++ "ERROR_OPEN_FILES",
++ "ERROR_ACTIVE_CONNECTIONS",
++ "ERROR_DEVICE_IN_USE",
++ "ERROR_UNKNOWN_PRINT_MONITOR",
++ "ERROR_PRINTER_DRIVER_IN_USE",
++ "ERROR_SPOOL_FILE_NOT_FOUND",
++ "ERROR_SPL_NO_STARTDOC",
++ "ERROR_SPL_NO_ADDJOB",
++ "ERROR_PRINT_PROCESSOR_ALREADY_INSTALLED",
++ "ERROR_PRINT_MONITOR_ALREADY_INSTALLED",
++ "ERROR_INVALID_PRINT_MONITOR",
++ "ERROR_PRINT_MONITOR_IN_USE",
++ "ERROR_PRINTER_HAS_JOBS_QUEUED",
++ "ERROR_SUCCESS_REBOOT_REQUIRED",
++ "ERROR_SUCCESS_RESTART_REQUIRED",
++ "ERROR_PRINTER_NOT_FOUND",
++ "ERROR_PRINTER_DRIVER_WARNED",
++ "ERROR_PRINTER_DRIVER_BLOCKED",
++ "ERROR_PRINTER_DRIVER_PACKAGE_IN_USE",
++ "ERROR_CORE_DRIVER_PACKAGE_NOT_FOUND",
++ "ERROR_FAIL_REBOOT_REQUIRED",
++ "ERROR_FAIL_REBOOT_INITIATED",
++ "ERROR_PRINTER_DRIVER_DOWNLOAD_NEEDED",
++ "ERROR_PRINT_JOB_RESTART_REQUIRED",
++ "ERROR_INVALID_PRINTER_DRIVER_MANIFEST",
++ "ERROR_PRINTER_NOT_SHAREABLE",
++ "ERROR_REQUEST_PAUSED",
++ "ERROR_APPEXEC_CONDITION_NOT_SATISFIED",
++ "ERROR_APPEXEC_HANDLE_INVALIDATED",
++ "ERROR_APPEXEC_INVALID_HOST_GENERATION",
++ "ERROR_APPEXEC_UNEXPECTED_PROCESS_REGISTRATION",
++ "ERROR_APPEXEC_INVALID_HOST_STATE",
++ "ERROR_APPEXEC_NO_DONOR",
++ "ERROR_APPEXEC_HOST_ID_MISMATCH",
++ "ERROR_APPEXEC_UNKNOWN_USER",
++ "ERROR_IO_REISSUE_AS_CACHED",
++ "ERROR_WINS_INTERNAL",
++ "ERROR_CAN_NOT_DEL_LOCAL_WINS",
++ "ERROR_STATIC_INIT",
++ "ERROR_INC_BACKUP",
++ "ERROR_FULL_BACKUP",
++ "ERROR_REC_NON_EXISTENT",
++ "ERROR_RPL_NOT_ALLOWED",
++ "ERROR_DHCP_ADDRESS_CONFLICT",
++ "ERROR_WMI_GUID_NOT_FOUND",
++ "ERROR_WMI_INSTANCE_NOT_FOUND",
++ "ERROR_WMI_ITEMID_NOT_FOUND",
++ "ERROR_WMI_TRY_AGAIN",
++ "ERROR_WMI_DP_NOT_FOUND",
++ "ERROR_WMI_UNRESOLVED_INSTANCE_REF",
++ "ERROR_WMI_ALREADY_ENABLED",
++ "ERROR_WMI_GUID_DISCONNECTED",
++ "ERROR_WMI_SERVER_UNAVAILABLE",
++ "ERROR_WMI_DP_FAILED",
++ "ERROR_WMI_INVALID_MOF",
++ "ERROR_WMI_INVALID_REGINFO",
++ "ERROR_WMI_ALREADY_DISABLED",
++ "ERROR_WMI_READ_ONLY",
++ "ERROR_WMI_SET_FAILURE",
++ "ERROR_NOT_APPCONTAINER",
++ "ERROR_APPCONTAINER_REQUIRED",
++ "ERROR_NOT_SUPPORTED_IN_APPCONTAINER",
++ "ERROR_INVALID_PACKAGE_SID_LENGTH",
++ "ERROR_INVALID_MEDIA",
++ "ERROR_INVALID_LIBRARY",
++ "ERROR_INVALID_MEDIA_POOL",
++ "ERROR_DRIVE_MEDIA_MISMATCH",
++ "ERROR_MEDIA_OFFLINE",
++ "ERROR_LIBRARY_OFFLINE",
++ "ERROR_EMPTY",
++ "ERROR_NOT_EMPTY",
++ "ERROR_MEDIA_UNAVAILABLE",
++ "ERROR_RESOURCE_DISABLED",
++ "ERROR_INVALID_CLEANER",
++ "ERROR_UNABLE_TO_CLEAN",
++ "ERROR_OBJECT_NOT_FOUND",
++ "ERROR_DATABASE_FAILURE",
++ "ERROR_DATABASE_FULL",
++ "ERROR_MEDIA_INCOMPATIBLE",
++ "ERROR_RESOURCE_NOT_PRESENT",
++ "ERROR_INVALID_OPERATION",
++ "ERROR_MEDIA_NOT_AVAILABLE",
++ "ERROR_DEVICE_NOT_AVAILABLE",
++ "ERROR_REQUEST_REFUSED",
++ "ERROR_INVALID_DRIVE_OBJECT",
++ "ERROR_LIBRARY_FULL",
++ "ERROR_MEDIUM_NOT_ACCESSIBLE",
++ "ERROR_UNABLE_TO_LOAD_MEDIUM",
++ "ERROR_UNABLE_TO_INVENTORY_DRIVE",
++ "ERROR_UNABLE_TO_INVENTORY_SLOT",
++ "ERROR_UNABLE_TO_INVENTORY_TRANSPORT",
++ "ERROR_TRANSPORT_FULL",
++ "ERROR_CONTROLLING_IEPORT",
++ "ERROR_UNABLE_TO_EJECT_MOUNTED_MEDIA",
++ "ERROR_CLEANER_SLOT_SET",
++ "ERROR_CLEANER_SLOT_NOT_SET",
++ "ERROR_CLEANER_CARTRIDGE_SPENT",
++ "ERROR_UNEXPECTED_OMID",
++ "ERROR_CANT_DELETE_LAST_ITEM",
++ "ERROR_MESSAGE_EXCEEDS_MAX_SIZE",
++ "ERROR_VOLUME_CONTAINS_SYS_FILES",
++ "ERROR_INDIGENOUS_TYPE",
++ "ERROR_NO_SUPPORTING_DRIVES",
++ "ERROR_CLEANER_CARTRIDGE_INSTALLED",
++ "ERROR_IEPORT_FULL",
++ "ERROR_FILE_OFFLINE",
++ "ERROR_REMOTE_STORAGE_NOT_ACTIVE",
++ "ERROR_REMOTE_STORAGE_MEDIA_ERROR",
++ "ERROR_NOT_A_REPARSE_POINT",
++ "ERROR_REPARSE_ATTRIBUTE_CONFLICT",
++ "ERROR_INVALID_REPARSE_DATA",
++ "ERROR_REPARSE_TAG_INVALID",
++ "ERROR_REPARSE_TAG_MISMATCH",
++ "ERROR_REPARSE_POINT_ENCOUNTERED",
++ "ERROR_APP_DATA_NOT_FOUND",
++ "ERROR_APP_DATA_EXPIRED",
++ "ERROR_APP_DATA_CORRUPT",
++ "ERROR_APP_DATA_LIMIT_EXCEEDED",
++ "ERROR_APP_DATA_REBOOT_REQUIRED",
++ "ERROR_SECUREBOOT_ROLLBACK_DETECTED",
++ "ERROR_SECUREBOOT_POLICY_VIOLATION",
++ "ERROR_SECUREBOOT_INVALID_POLICY",
++ "ERROR_SECUREBOOT_POLICY_PUBLISHER_NOT_FOUND",
++ "ERROR_SECUREBOOT_POLICY_NOT_SIGNED",
++ "ERROR_SECUREBOOT_NOT_ENABLED",
++ "ERROR_SECUREBOOT_FILE_REPLACED",
++ "ERROR_SECUREBOOT_POLICY_NOT_AUTHORIZED",
++ "ERROR_SECUREBOOT_POLICY_UNKNOWN",
++ "ERROR_SECUREBOOT_POLICY_MISSING_ANTIROLLBACKVERSION",
++ "ERROR_SECUREBOOT_PLATFORM_ID_MISMATCH",
++ "ERROR_SECUREBOOT_POLICY_ROLLBACK_DETECTED",
++ "ERROR_SECUREBOOT_POLICY_UPGRADE_MISMATCH",
++ "ERROR_SECUREBOOT_REQUIRED_POLICY_FILE_MISSING",
++ "ERROR_SECUREBOOT_NOT_BASE_POLICY",
++ "ERROR_SECUREBOOT_NOT_SUPPLEMENTAL_POLICY",
++ "ERROR_OFFLOAD_READ_FLT_NOT_SUPPORTED",
++ "ERROR_OFFLOAD_WRITE_FLT_NOT_SUPPORTED",
++ "ERROR_OFFLOAD_READ_FILE_NOT_SUPPORTED",
++ "ERROR_OFFLOAD_WRITE_FILE_NOT_SUPPORTED",
++ "ERROR_ALREADY_HAS_STREAM_ID",
++ "ERROR_SMR_GARBAGE_COLLECTION_REQUIRED",
++ "ERROR_WOF_WIM_HEADER_CORRUPT",
++ "ERROR_WOF_WIM_RESOURCE_TABLE_CORRUPT",
++ "ERROR_WOF_FILE_RESOURCE_TABLE_CORRUPT",
++ "ERROR_VOLUME_NOT_SIS_ENABLED",
++ "ERROR_SYSTEM_INTEGRITY_ROLLBACK_DETECTED",
++ "ERROR_SYSTEM_INTEGRITY_POLICY_VIOLATION",
++ "ERROR_SYSTEM_INTEGRITY_INVALID_POLICY",
++ "ERROR_SYSTEM_INTEGRITY_POLICY_NOT_SIGNED",
++ "ERROR_SYSTEM_INTEGRITY_TOO_MANY_POLICIES",
++ "ERROR_SYSTEM_INTEGRITY_SUPPLEMENTAL_POLICY_NOT_AUTHORIZED",
++ "ERROR_VSM_NOT_INITIALIZED",
++ "ERROR_VSM_DMA_PROTECTION_NOT_IN_USE",
++ "ERROR_PLATFORM_MANIFEST_NOT_AUTHORIZED",
++ "ERROR_PLATFORM_MANIFEST_INVALID",
++ "ERROR_PLATFORM_MANIFEST_FILE_NOT_AUTHORIZED",
++ "ERROR_PLATFORM_MANIFEST_CATALOG_NOT_AUTHORIZED",
++ "ERROR_PLATFORM_MANIFEST_BINARY_ID_NOT_FOUND",
++ "ERROR_PLATFORM_MANIFEST_NOT_ACTIVE",
++ "ERROR_PLATFORM_MANIFEST_NOT_SIGNED",
++ "ERROR_DEPENDENT_RESOURCE_EXISTS",
++ "ERROR_DEPENDENCY_NOT_FOUND",
++ "ERROR_DEPENDENCY_ALREADY_EXISTS",
++ "ERROR_RESOURCE_NOT_ONLINE",
++ "ERROR_HOST_NODE_NOT_AVAILABLE",
++ "ERROR_RESOURCE_NOT_AVAILABLE",
++ "ERROR_RESOURCE_NOT_FOUND",
++ "ERROR_SHUTDOWN_CLUSTER",
++ "ERROR_CANT_EVICT_ACTIVE_NODE",
++ "ERROR_OBJECT_ALREADY_EXISTS",
++ "ERROR_OBJECT_IN_LIST",
++ "ERROR_GROUP_NOT_AVAILABLE",
++ "ERROR_GROUP_NOT_FOUND",
++ "ERROR_GROUP_NOT_ONLINE",
++ "ERROR_HOST_NODE_NOT_RESOURCE_OWNER",
++ "ERROR_HOST_NODE_NOT_GROUP_OWNER",
++ "ERROR_RESMON_CREATE_FAILED",
++ "ERROR_RESMON_ONLINE_FAILED",
++ "ERROR_RESOURCE_ONLINE",
++ "ERROR_QUORUM_RESOURCE",
++ "ERROR_NOT_QUORUM_CAPABLE",
++ "ERROR_CLUSTER_SHUTTING_DOWN",
++ "ERROR_INVALID_STATE",
++ "ERROR_RESOURCE_PROPERTIES_STORED",
++ "ERROR_NOT_QUORUM_CLASS",
++ "ERROR_CORE_RESOURCE",
++ "ERROR_QUORUM_RESOURCE_ONLINE_FAILED",
++ "ERROR_QUORUMLOG_OPEN_FAILED",
++ "ERROR_CLUSTERLOG_CORRUPT",
++ "ERROR_CLUSTERLOG_RECORD_EXCEEDS_MAXSIZE",
++ "ERROR_CLUSTERLOG_EXCEEDS_MAXSIZE",
++ "ERROR_CLUSTERLOG_CHKPOINT_NOT_FOUND",
++ "ERROR_CLUSTERLOG_NOT_ENOUGH_SPACE",
++ "ERROR_QUORUM_OWNER_ALIVE",
++ "ERROR_NETWORK_NOT_AVAILABLE",
++ "ERROR_NODE_NOT_AVAILABLE",
++ "ERROR_ALL_NODES_NOT_AVAILABLE",
++ "ERROR_RESOURCE_FAILED",
++ "ERROR_CLUSTER_INVALID_NODE",
++ "ERROR_CLUSTER_NODE_EXISTS",
++ "ERROR_CLUSTER_JOIN_IN_PROGRESS",
++ "ERROR_CLUSTER_NODE_NOT_FOUND",
++ "ERROR_CLUSTER_LOCAL_NODE_NOT_FOUND",
++ "ERROR_CLUSTER_NETWORK_EXISTS",
++ "ERROR_CLUSTER_NETWORK_NOT_FOUND",
++ "ERROR_CLUSTER_NETINTERFACE_EXISTS",
++ "ERROR_CLUSTER_NETINTERFACE_NOT_FOUND",
++ "ERROR_CLUSTER_INVALID_REQUEST",
++ "ERROR_CLUSTER_INVALID_NETWORK_PROVIDER",
++ "ERROR_CLUSTER_NODE_DOWN",
++ "ERROR_CLUSTER_NODE_UNREACHABLE",
++ "ERROR_CLUSTER_NODE_NOT_MEMBER",
++ "ERROR_CLUSTER_JOIN_NOT_IN_PROGRESS",
++ "ERROR_CLUSTER_INVALID_NETWORK",
++ "ERROR_CLUSTER_NODE_UP",
++ "ERROR_CLUSTER_IPADDR_IN_USE",
++ "ERROR_CLUSTER_NODE_NOT_PAUSED",
++ "ERROR_CLUSTER_NO_SECURITY_CONTEXT",
++ "ERROR_CLUSTER_NETWORK_NOT_INTERNAL",
++ "ERROR_CLUSTER_NODE_ALREADY_UP",
++ "ERROR_CLUSTER_NODE_ALREADY_DOWN",
++ "ERROR_CLUSTER_NETWORK_ALREADY_ONLINE",
++ "ERROR_CLUSTER_NETWORK_ALREADY_OFFLINE",
++ "ERROR_CLUSTER_NODE_ALREADY_MEMBER",
++ "ERROR_CLUSTER_LAST_INTERNAL_NETWORK",
++ "ERROR_CLUSTER_NETWORK_HAS_DEPENDENTS",
++ "ERROR_INVALID_OPERATION_ON_QUORUM",
++ "ERROR_DEPENDENCY_NOT_ALLOWED",
++ "ERROR_CLUSTER_NODE_PAUSED",
++ "ERROR_NODE_CANT_HOST_RESOURCE",
++ "ERROR_CLUSTER_NODE_NOT_READY",
++ "ERROR_CLUSTER_NODE_SHUTTING_DOWN",
++ "ERROR_CLUSTER_JOIN_ABORTED",
++ "ERROR_CLUSTER_INCOMPATIBLE_VERSIONS",
++ "ERROR_CLUSTER_MAXNUM_OF_RESOURCES_EXCEEDED",
++ "ERROR_CLUSTER_SYSTEM_CONFIG_CHANGED",
++ "ERROR_CLUSTER_RESOURCE_TYPE_NOT_FOUND",
++ "ERROR_CLUSTER_RESTYPE_NOT_SUPPORTED",
++ "ERROR_CLUSTER_RESNAME_NOT_FOUND",
++ "ERROR_CLUSTER_NO_RPC_PACKAGES_REGISTERED",
++ "ERROR_CLUSTER_OWNER_NOT_IN_PREFLIST",
++ "ERROR_CLUSTER_DATABASE_SEQMISMATCH",
++ "ERROR_RESMON_INVALID_STATE",
++ "ERROR_CLUSTER_GUM_NOT_LOCKER",
++ "ERROR_QUORUM_DISK_NOT_FOUND",
++ "ERROR_DATABASE_BACKUP_CORRUPT",
++ "ERROR_CLUSTER_NODE_ALREADY_HAS_DFS_ROOT",
++ "ERROR_RESOURCE_PROPERTY_UNCHANGEABLE",
++ "ERROR_NO_ADMIN_ACCESS_POINT",
++ "ERROR_CLUSTER_MEMBERSHIP_INVALID_STATE",
++ "ERROR_CLUSTER_QUORUMLOG_NOT_FOUND",
++ "ERROR_CLUSTER_MEMBERSHIP_HALT",
++ "ERROR_CLUSTER_INSTANCE_ID_MISMATCH",
++ "ERROR_CLUSTER_NETWORK_NOT_FOUND_FOR_IP",
++ "ERROR_CLUSTER_PROPERTY_DATA_TYPE_MISMATCH",
++ "ERROR_CLUSTER_EVICT_WITHOUT_CLEANUP",
++ "ERROR_CLUSTER_PARAMETER_MISMATCH",
++ "ERROR_NODE_CANNOT_BE_CLUSTERED",
++ "ERROR_CLUSTER_WRONG_OS_VERSION",
++ "ERROR_CLUSTER_CANT_CREATE_DUP_CLUSTER_NAME",
++ "ERROR_CLUSCFG_ALREADY_COMMITTED",
++ "ERROR_CLUSCFG_ROLLBACK_FAILED",
++ "ERROR_CLUSCFG_SYSTEM_DISK_DRIVE_LETTER_CONFLICT",
++ "ERROR_CLUSTER_OLD_VERSION",
++ "ERROR_CLUSTER_MISMATCHED_COMPUTER_ACCT_NAME",
++ "ERROR_CLUSTER_NO_NET_ADAPTERS",
++ "ERROR_CLUSTER_POISONED",
++ "ERROR_CLUSTER_GROUP_MOVING",
++ "ERROR_CLUSTER_RESOURCE_TYPE_BUSY",
++ "ERROR_RESOURCE_CALL_TIMED_OUT",
++ "ERROR_INVALID_CLUSTER_IPV6_ADDRESS",
++ "ERROR_CLUSTER_INTERNAL_INVALID_FUNCTION",
++ "ERROR_CLUSTER_PARAMETER_OUT_OF_BOUNDS",
++ "ERROR_CLUSTER_PARTIAL_SEND",
++ "ERROR_CLUSTER_REGISTRY_INVALID_FUNCTION",
++ "ERROR_CLUSTER_INVALID_STRING_TERMINATION",
++ "ERROR_CLUSTER_INVALID_STRING_FORMAT",
++ "ERROR_CLUSTER_DATABASE_TRANSACTION_IN_PROGRESS",
++ "ERROR_CLUSTER_DATABASE_TRANSACTION_NOT_IN_PROGRESS",
++ "ERROR_CLUSTER_NULL_DATA",
++ "ERROR_CLUSTER_PARTIAL_READ",
++ "ERROR_CLUSTER_PARTIAL_WRITE",
++ "ERROR_CLUSTER_CANT_DESERIALIZE_DATA",
++ "ERROR_DEPENDENT_RESOURCE_PROPERTY_CONFLICT",
++ "ERROR_CLUSTER_NO_QUORUM",
++ "ERROR_CLUSTER_INVALID_IPV6_NETWORK",
++ "ERROR_CLUSTER_INVALID_IPV6_TUNNEL_NETWORK",
++ "ERROR_QUORUM_NOT_ALLOWED_IN_THIS_GROUP",
++ "ERROR_DEPENDENCY_TREE_TOO_COMPLEX",
++ "ERROR_EXCEPTION_IN_RESOURCE_CALL",
++ "ERROR_CLUSTER_RHS_FAILED_INITIALIZATION",
++ "ERROR_CLUSTER_NOT_INSTALLED",
++ "ERROR_CLUSTER_RESOURCES_MUST_BE_ONLINE_ON_THE_SAME_NODE",
++ "ERROR_CLUSTER_MAX_NODES_IN_CLUSTER",
++ "ERROR_CLUSTER_TOO_MANY_NODES",
++ "ERROR_CLUSTER_OBJECT_ALREADY_USED",
++ "ERROR_NONCORE_GROUPS_FOUND",
++ "ERROR_FILE_SHARE_RESOURCE_CONFLICT",
++ "ERROR_CLUSTER_EVICT_INVALID_REQUEST",
++ "ERROR_CLUSTER_SINGLETON_RESOURCE",
++ "ERROR_CLUSTER_GROUP_SINGLETON_RESOURCE",
++ "ERROR_CLUSTER_RESOURCE_PROVIDER_FAILED",
++ "ERROR_CLUSTER_RESOURCE_CONFIGURATION_ERROR",
++ "ERROR_CLUSTER_GROUP_BUSY",
++ "ERROR_CLUSTER_NOT_SHARED_VOLUME",
++ "ERROR_CLUSTER_INVALID_SECURITY_DESCRIPTOR",
++ "ERROR_CLUSTER_SHARED_VOLUMES_IN_USE",
++ "ERROR_CLUSTER_USE_SHARED_VOLUMES_API",
++ "ERROR_CLUSTER_BACKUP_IN_PROGRESS",
++ "ERROR_NON_CSV_PATH",
++ "ERROR_CSV_VOLUME_NOT_LOCAL",
++ "ERROR_CLUSTER_WATCHDOG_TERMINATING",
++ "ERROR_CLUSTER_RESOURCE_VETOED_MOVE_INCOMPATIBLE_NODES",
++ "ERROR_CLUSTER_INVALID_NODE_WEIGHT",
++ "ERROR_CLUSTER_RESOURCE_VETOED_CALL",
++ "ERROR_RESMON_SYSTEM_RESOURCES_LACKING",
++ "ERROR_CLUSTER_RESOURCE_VETOED_MOVE_NOT_ENOUGH_RESOURCES_ON_DESTINATION",
++ "ERROR_CLUSTER_RESOURCE_VETOED_MOVE_NOT_ENOUGH_RESOURCES_ON_SOURCE",
++ "ERROR_CLUSTER_GROUP_QUEUED",
++ "ERROR_CLUSTER_RESOURCE_LOCKED_STATUS",
++ "ERROR_CLUSTER_SHARED_VOLUME_FAILOVER_NOT_ALLOWED",
++ "ERROR_CLUSTER_NODE_DRAIN_IN_PROGRESS",
++ "ERROR_CLUSTER_DISK_NOT_CONNECTED",
++ "ERROR_DISK_NOT_CSV_CAPABLE",
++ "ERROR_RESOURCE_NOT_IN_AVAILABLE_STORAGE",
++ "ERROR_CLUSTER_SHARED_VOLUME_REDIRECTED",
++ "ERROR_CLUSTER_SHARED_VOLUME_NOT_REDIRECTED",
++ "ERROR_CLUSTER_CANNOT_RETURN_PROPERTIES",
++ "ERROR_CLUSTER_RESOURCE_CONTAINS_UNSUPPORTED_DIFF_AREA_FOR_SHARED_VOLUMES",
++ "ERROR_CLUSTER_RESOURCE_IS_IN_MAINTENANCE_MODE",
++ "ERROR_CLUSTER_AFFINITY_CONFLICT",
++ "ERROR_CLUSTER_RESOURCE_IS_REPLICA_VIRTUAL_MACHINE",
++ "ERROR_CLUSTER_UPGRADE_INCOMPATIBLE_VERSIONS",
++ "ERROR_CLUSTER_UPGRADE_FIX_QUORUM_NOT_SUPPORTED",
++ "ERROR_CLUSTER_UPGRADE_RESTART_REQUIRED",
++ "ERROR_CLUSTER_UPGRADE_IN_PROGRESS",
++ "ERROR_CLUSTER_UPGRADE_INCOMPLETE",
++ "ERROR_CLUSTER_NODE_IN_GRACE_PERIOD",
++ "ERROR_CLUSTER_CSV_IO_PAUSE_TIMEOUT",
++ "ERROR_NODE_NOT_ACTIVE_CLUSTER_MEMBER",
++ "ERROR_CLUSTER_RESOURCE_NOT_MONITORED",
++ "ERROR_CLUSTER_RESOURCE_DOES_NOT_SUPPORT_UNMONITORED",
++ "ERROR_CLUSTER_RESOURCE_IS_REPLICATED",
++ "ERROR_CLUSTER_NODE_ISOLATED",
++ "ERROR_CLUSTER_NODE_QUARANTINED",
++ "ERROR_CLUSTER_DATABASE_UPDATE_CONDITION_FAILED",
++ "ERROR_CLUSTER_SPACE_DEGRADED",
++ "ERROR_CLUSTER_TOKEN_DELEGATION_NOT_SUPPORTED",
++ "ERROR_CLUSTER_CSV_INVALID_HANDLE",
++ "ERROR_CLUSTER_CSV_SUPPORTED_ONLY_ON_COORDINATOR",
++ "ERROR_GROUPSET_NOT_AVAILABLE",
++ "ERROR_GROUPSET_NOT_FOUND",
++ "ERROR_GROUPSET_CANT_PROVIDE",
++ "ERROR_CLUSTER_FAULT_DOMAIN_PARENT_NOT_FOUND",
++ "ERROR_CLUSTER_FAULT_DOMAIN_INVALID_HIERARCHY",
++ "ERROR_CLUSTER_FAULT_DOMAIN_FAILED_S2D_VALIDATION",
++ "ERROR_CLUSTER_FAULT_DOMAIN_S2D_CONNECTIVITY_LOSS",
++ "ERROR_CLUSTER_INVALID_INFRASTRUCTURE_FILESERVER_NAME",
++ "ERROR_CLUSTERSET_MANAGEMENT_CLUSTER_UNREACHABLE",
++ "ERROR_ENCRYPTION_FAILED",
++ "ERROR_DECRYPTION_FAILED",
++ "ERROR_FILE_ENCRYPTED",
++ "ERROR_NO_RECOVERY_POLICY",
++ "ERROR_NO_EFS",
++ "ERROR_WRONG_EFS",
++ "ERROR_NO_USER_KEYS",
++ "ERROR_FILE_NOT_ENCRYPTED",
++ "ERROR_NOT_EXPORT_FORMAT",
++ "ERROR_FILE_READ_ONLY",
++ "ERROR_DIR_EFS_DISALLOWED",
++ "ERROR_EFS_SERVER_NOT_TRUSTED",
++ "ERROR_BAD_RECOVERY_POLICY",
++ "ERROR_EFS_ALG_BLOB_TOO_BIG",
++ "ERROR_VOLUME_NOT_SUPPORT_EFS",
++ "ERROR_EFS_DISABLED",
++ "ERROR_EFS_VERSION_NOT_SUPPORT",
++ "ERROR_CS_ENCRYPTION_INVALID_SERVER_RESPONSE",
++ "ERROR_CS_ENCRYPTION_UNSUPPORTED_SERVER",
++ "ERROR_CS_ENCRYPTION_EXISTING_ENCRYPTED_FILE",
++ "ERROR_CS_ENCRYPTION_NEW_ENCRYPTED_FILE",
++ "ERROR_CS_ENCRYPTION_FILE_NOT_CSE",
++ "ERROR_ENCRYPTION_POLICY_DENIES_OPERATION",
++ "ERROR_WIP_ENCRYPTION_FAILED",
++ "ERROR_NO_BROWSER_SERVERS_FOUND",
++ "ERROR_CLUSTER_OBJECT_IS_CLUSTER_SET_VM",
++ "ERROR_LOG_SECTOR_INVALID",
++ "ERROR_LOG_SECTOR_PARITY_INVALID",
++ "ERROR_LOG_SECTOR_REMAPPED",
++ "ERROR_LOG_BLOCK_INCOMPLETE",
++ "ERROR_LOG_INVALID_RANGE",
++ "ERROR_LOG_BLOCKS_EXHAUSTED",
++ "ERROR_LOG_READ_CONTEXT_INVALID",
++ "ERROR_LOG_RESTART_INVALID",
++ "ERROR_LOG_BLOCK_VERSION",
++ "ERROR_LOG_BLOCK_INVALID",
++ "ERROR_LOG_READ_MODE_INVALID",
++ "ERROR_LOG_NO_RESTART",
++ "ERROR_LOG_METADATA_CORRUPT",
++ "ERROR_LOG_METADATA_INVALID",
++ "ERROR_LOG_METADATA_INCONSISTENT",
++ "ERROR_LOG_RESERVATION_INVALID",
++ "ERROR_LOG_CANT_DELETE",
++ "ERROR_LOG_CONTAINER_LIMIT_EXCEEDED",
++ "ERROR_LOG_START_OF_LOG",
++ "ERROR_LOG_POLICY_ALREADY_INSTALLED",
++ "ERROR_LOG_POLICY_NOT_INSTALLED",
++ "ERROR_LOG_POLICY_INVALID",
++ "ERROR_LOG_POLICY_CONFLICT",
++ "ERROR_LOG_PINNED_ARCHIVE_TAIL",
++ "ERROR_LOG_RECORD_NONEXISTENT",
++ "ERROR_LOG_RECORDS_RESERVED_INVALID",
++ "ERROR_LOG_SPACE_RESERVED_INVALID",
++ "ERROR_LOG_TAIL_INVALID",
++ "ERROR_LOG_FULL",
++ "ERROR_COULD_NOT_RESIZE_LOG",
++ "ERROR_LOG_MULTIPLEXED",
++ "ERROR_LOG_DEDICATED",
++ "ERROR_LOG_ARCHIVE_NOT_IN_PROGRESS",
++ "ERROR_LOG_ARCHIVE_IN_PROGRESS",
++ "ERROR_LOG_EPHEMERAL",
++ "ERROR_LOG_NOT_ENOUGH_CONTAINERS",
++ "ERROR_LOG_CLIENT_ALREADY_REGISTERED",
++ "ERROR_LOG_CLIENT_NOT_REGISTERED",
++ "ERROR_LOG_FULL_HANDLER_IN_PROGRESS",
++ "ERROR_LOG_CONTAINER_READ_FAILED",
++ "ERROR_LOG_CONTAINER_WRITE_FAILED",
++ "ERROR_LOG_CONTAINER_OPEN_FAILED",
++ "ERROR_LOG_CONTAINER_STATE_INVALID",
++ "ERROR_LOG_STATE_INVALID",
++ "ERROR_LOG_PINNED",
++ "ERROR_LOG_METADATA_FLUSH_FAILED",
++ "ERROR_LOG_INCONSISTENT_SECURITY",
++ "ERROR_LOG_APPENDED_FLUSH_FAILED",
++ "ERROR_LOG_PINNED_RESERVATION",
++ "ERROR_INVALID_TRANSACTION",
++ "ERROR_TRANSACTION_NOT_ACTIVE",
++ "ERROR_TRANSACTION_REQUEST_NOT_VALID",
++ "ERROR_TRANSACTION_NOT_REQUESTED",
++ "ERROR_TRANSACTION_ALREADY_ABORTED",
++ "ERROR_TRANSACTION_ALREADY_COMMITTED",
++ "ERROR_TM_INITIALIZATION_FAILED",
++ "ERROR_RESOURCEMANAGER_READ_ONLY",
++ "ERROR_TRANSACTION_NOT_JOINED",
++ "ERROR_TRANSACTION_SUPERIOR_EXISTS",
++ "ERROR_CRM_PROTOCOL_ALREADY_EXISTS",
++ "ERROR_TRANSACTION_PROPAGATION_FAILED",
++ "ERROR_CRM_PROTOCOL_NOT_FOUND",
++ "ERROR_TRANSACTION_INVALID_MARSHALL_BUFFER",
++ "ERROR_CURRENT_TRANSACTION_NOT_VALID",
++ "ERROR_TRANSACTION_NOT_FOUND",
++ "ERROR_RESOURCEMANAGER_NOT_FOUND",
++ "ERROR_ENLISTMENT_NOT_FOUND",
++ "ERROR_TRANSACTIONMANAGER_NOT_FOUND",
++ "ERROR_TRANSACTIONMANAGER_NOT_ONLINE",
++ "ERROR_TRANSACTIONMANAGER_RECOVERY_NAME_COLLISION",
++ "ERROR_TRANSACTION_NOT_ROOT",
++ "ERROR_TRANSACTION_OBJECT_EXPIRED",
++ "ERROR_TRANSACTION_RESPONSE_NOT_ENLISTED",
++ "ERROR_TRANSACTION_RECORD_TOO_LONG",
++ "ERROR_IMPLICIT_TRANSACTION_NOT_SUPPORTED",
++ "ERROR_TRANSACTION_INTEGRITY_VIOLATED",
++ "ERROR_TRANSACTIONMANAGER_IDENTITY_MISMATCH",
++ "ERROR_RM_CANNOT_BE_FROZEN_FOR_SNAPSHOT",
++ "ERROR_TRANSACTION_MUST_WRITETHROUGH",
++ "ERROR_TRANSACTION_NO_SUPERIOR",
++ "ERROR_HEURISTIC_DAMAGE_POSSIBLE",
++ "ERROR_TRANSACTIONAL_CONFLICT",
++ "ERROR_RM_NOT_ACTIVE",
++ "ERROR_RM_METADATA_CORRUPT",
++ "ERROR_DIRECTORY_NOT_RM",
++ "ERROR_TRANSACTIONS_UNSUPPORTED_REMOTE",
++ "ERROR_LOG_RESIZE_INVALID_SIZE",
++ "ERROR_OBJECT_NO_LONGER_EXISTS",
++ "ERROR_STREAM_MINIVERSION_NOT_FOUND",
++ "ERROR_STREAM_MINIVERSION_NOT_VALID",
++ "ERROR_MINIVERSION_INACCESSIBLE_FROM_SPECIFIED_TRANSACTION",
++ "ERROR_CANT_OPEN_MINIVERSION_WITH_MODIFY_INTENT",
++ "ERROR_CANT_CREATE_MORE_STREAM_MINIVERSIONS",
++ "ERROR_REMOTE_FILE_VERSION_MISMATCH",
++ "ERROR_HANDLE_NO_LONGER_VALID",
++ "ERROR_NO_TXF_METADATA",
++ "ERROR_LOG_CORRUPTION_DETECTED",
++ "ERROR_CANT_RECOVER_WITH_HANDLE_OPEN",
++ "ERROR_RM_DISCONNECTED",
++ "ERROR_ENLISTMENT_NOT_SUPERIOR",
++ "ERROR_RECOVERY_NOT_NEEDED",
++ "ERROR_RM_ALREADY_STARTED",
++ "ERROR_FILE_IDENTITY_NOT_PERSISTENT",
++ "ERROR_CANT_BREAK_TRANSACTIONAL_DEPENDENCY",
++ "ERROR_CANT_CROSS_RM_BOUNDARY",
++ "ERROR_TXF_DIR_NOT_EMPTY",
++ "ERROR_INDOUBT_TRANSACTIONS_EXIST",
++ "ERROR_TM_VOLATILE",
++ "ERROR_ROLLBACK_TIMER_EXPIRED",
++ "ERROR_TXF_ATTRIBUTE_CORRUPT",
++ "ERROR_EFS_NOT_ALLOWED_IN_TRANSACTION",
++ "ERROR_TRANSACTIONAL_OPEN_NOT_ALLOWED",
++ "ERROR_LOG_GROWTH_FAILED",
++ "ERROR_TRANSACTED_MAPPING_UNSUPPORTED_REMOTE",
++ "ERROR_TXF_METADATA_ALREADY_PRESENT",
++ "ERROR_TRANSACTION_SCOPE_CALLBACKS_NOT_SET",
++ "ERROR_TRANSACTION_REQUIRED_PROMOTION",
++ "ERROR_CANNOT_EXECUTE_FILE_IN_TRANSACTION",
++ "ERROR_TRANSACTIONS_NOT_FROZEN",
++ "ERROR_TRANSACTION_FREEZE_IN_PROGRESS",
++ "ERROR_NOT_SNAPSHOT_VOLUME",
++ "ERROR_NO_SAVEPOINT_WITH_OPEN_FILES",
++ "ERROR_DATA_LOST_REPAIR",
++ "ERROR_SPARSE_NOT_ALLOWED_IN_TRANSACTION",
++ "ERROR_TM_IDENTITY_MISMATCH",
++ "ERROR_FLOATED_SECTION",
++ "ERROR_CANNOT_ACCEPT_TRANSACTED_WORK",
++ "ERROR_CANNOT_ABORT_TRANSACTIONS",
++ "ERROR_BAD_CLUSTERS",
++ "ERROR_COMPRESSION_NOT_ALLOWED_IN_TRANSACTION",
++ "ERROR_VOLUME_DIRTY",
++ "ERROR_NO_LINK_TRACKING_IN_TRANSACTION",
++ "ERROR_OPERATION_NOT_SUPPORTED_IN_TRANSACTION",
++ "ERROR_EXPIRED_HANDLE",
++ "ERROR_TRANSACTION_NOT_ENLISTED",
++ "ERROR_CTX_WINSTATION_NAME_INVALID",
++ "ERROR_CTX_INVALID_PD",
++ "ERROR_CTX_PD_NOT_FOUND",
++ "ERROR_CTX_WD_NOT_FOUND",
++ "ERROR_CTX_CANNOT_MAKE_EVENTLOG_ENTRY",
++ "ERROR_CTX_SERVICE_NAME_COLLISION",
++ "ERROR_CTX_CLOSE_PENDING",
++ "ERROR_CTX_NO_OUTBUF",
++ "ERROR_CTX_MODEM_INF_NOT_FOUND",
++ "ERROR_CTX_INVALID_MODEMNAME",
++ "ERROR_CTX_MODEM_RESPONSE_ERROR",
++ "ERROR_CTX_MODEM_RESPONSE_TIMEOUT",
++ "ERROR_CTX_MODEM_RESPONSE_NO_CARRIER",
++ "ERROR_CTX_MODEM_RESPONSE_NO_DIALTONE",
++ "ERROR_CTX_MODEM_RESPONSE_BUSY",
++ "ERROR_CTX_MODEM_RESPONSE_VOICE",
++ "ERROR_CTX_TD_ERROR",
++ "ERROR_CTX_WINSTATION_NOT_FOUND",
++ "ERROR_CTX_WINSTATION_ALREADY_EXISTS",
++ "ERROR_CTX_WINSTATION_BUSY",
++ "ERROR_CTX_BAD_VIDEO_MODE",
++ "ERROR_CTX_GRAPHICS_INVALID",
++ "ERROR_CTX_LOGON_DISABLED",
++ "ERROR_CTX_NOT_CONSOLE",
++ "ERROR_CTX_CLIENT_QUERY_TIMEOUT",
++ "ERROR_CTX_CONSOLE_DISCONNECT",
++ "ERROR_CTX_CONSOLE_CONNECT",
++ "ERROR_CTX_SHADOW_DENIED",
++ "ERROR_CTX_WINSTATION_ACCESS_DENIED",
++ "ERROR_CTX_INVALID_WD",
++ "ERROR_CTX_SHADOW_INVALID",
++ "ERROR_CTX_SHADOW_DISABLED",
++ "ERROR_CTX_CLIENT_LICENSE_IN_USE",
++ "ERROR_CTX_CLIENT_LICENSE_NOT_SET",
++ "ERROR_CTX_LICENSE_NOT_AVAILABLE",
++ "ERROR_CTX_LICENSE_CLIENT_INVALID",
++ "ERROR_CTX_LICENSE_EXPIRED",
++ "ERROR_CTX_SHADOW_NOT_RUNNING",
++ "ERROR_CTX_SHADOW_ENDED_BY_MODE_CHANGE",
++ "ERROR_ACTIVATION_COUNT_EXCEEDED",
++ "ERROR_CTX_WINSTATIONS_DISABLED",
++ "ERROR_CTX_ENCRYPTION_LEVEL_REQUIRED",
++ "ERROR_CTX_SESSION_IN_USE",
++ "ERROR_CTX_NO_FORCE_LOGOFF",
++ "ERROR_CTX_ACCOUNT_RESTRICTION",
++ "ERROR_RDP_PROTOCOL_ERROR",
++ "ERROR_CTX_CDM_CONNECT",
++ "ERROR_CTX_CDM_DISCONNECT",
++ "ERROR_CTX_SECURITY_LAYER_ERROR",
++ "ERROR_TS_INCOMPATIBLE_SESSIONS",
++ "ERROR_TS_VIDEO_SUBSYSTEM_ERROR",
++ "ERROR_DS_NOT_INSTALLED",
++ "ERROR_DS_MEMBERSHIP_EVALUATED_LOCALLY",
++ "ERROR_DS_NO_ATTRIBUTE_OR_VALUE",
++ "ERROR_DS_INVALID_ATTRIBUTE_SYNTAX",
++ "ERROR_DS_ATTRIBUTE_TYPE_UNDEFINED",
++ "ERROR_DS_ATTRIBUTE_OR_VALUE_EXISTS",
++ "ERROR_DS_BUSY",
++ "ERROR_DS_UNAVAILABLE",
++ "ERROR_DS_NO_RIDS_ALLOCATED",
++ "ERROR_DS_NO_MORE_RIDS",
++ "ERROR_DS_INCORRECT_ROLE_OWNER",
++ "ERROR_DS_RIDMGR_INIT_ERROR",
++ "ERROR_DS_OBJ_CLASS_VIOLATION",
++ "ERROR_DS_CANT_ON_NON_LEAF",
++ "ERROR_DS_CANT_ON_RDN",
++ "ERROR_DS_CANT_MOD_OBJ_CLASS",
++ "ERROR_DS_CROSS_DOM_MOVE_ERROR",
++ "ERROR_DS_GC_NOT_AVAILABLE",
++ "ERROR_SHARED_POLICY",
++ "ERROR_POLICY_OBJECT_NOT_FOUND",
++ "ERROR_POLICY_ONLY_IN_DS",
++ "ERROR_PROMOTION_ACTIVE",
++ "ERROR_NO_PROMOTION_ACTIVE",
++ "ERROR_DS_OPERATIONS_ERROR",
++ "ERROR_DS_PROTOCOL_ERROR",
++ "ERROR_DS_TIMELIMIT_EXCEEDED",
++ "ERROR_DS_SIZELIMIT_EXCEEDED",
++ "ERROR_DS_ADMIN_LIMIT_EXCEEDED",
++ "ERROR_DS_COMPARE_FALSE",
++ "ERROR_DS_COMPARE_TRUE",
++ "ERROR_DS_AUTH_METHOD_NOT_SUPPORTED",
++ "ERROR_DS_STRONG_AUTH_REQUIRED",
++ "ERROR_DS_INAPPROPRIATE_AUTH",
++ "ERROR_DS_AUTH_UNKNOWN",
++ "ERROR_DS_REFERRAL",
++ "ERROR_DS_UNAVAILABLE_CRIT_EXTENSION",
++ "ERROR_DS_CONFIDENTIALITY_REQUIRED",
++ "ERROR_DS_INAPPROPRIATE_MATCHING",
++ "ERROR_DS_CONSTRAINT_VIOLATION",
++ "ERROR_DS_NO_SUCH_OBJECT",
++ "ERROR_DS_ALIAS_PROBLEM",
++ "ERROR_DS_INVALID_DN_SYNTAX",
++ "ERROR_DS_IS_LEAF",
++ "ERROR_DS_ALIAS_DEREF_PROBLEM",
++ "ERROR_DS_UNWILLING_TO_PERFORM",
++ "ERROR_DS_LOOP_DETECT",
++ "ERROR_DS_NAMING_VIOLATION",
++ "ERROR_DS_OBJECT_RESULTS_TOO_LARGE",
++ "ERROR_DS_AFFECTS_MULTIPLE_DSAS",
++ "ERROR_DS_SERVER_DOWN",
++ "ERROR_DS_LOCAL_ERROR",
++ "ERROR_DS_ENCODING_ERROR",
++ "ERROR_DS_DECODING_ERROR",
++ "ERROR_DS_FILTER_UNKNOWN",
++ "ERROR_DS_PARAM_ERROR",
++ "ERROR_DS_NOT_SUPPORTED",
++ "ERROR_DS_NO_RESULTS_RETURNED",
++ "ERROR_DS_CONTROL_NOT_FOUND",
++ "ERROR_DS_CLIENT_LOOP",
++ "ERROR_DS_REFERRAL_LIMIT_EXCEEDED",
++ "ERROR_DS_SORT_CONTROL_MISSING",
++ "ERROR_DS_OFFSET_RANGE_ERROR",
++ "ERROR_DS_RIDMGR_DISABLED",
++ "ERROR_DS_ROOT_MUST_BE_NC",
++ "ERROR_DS_ADD_REPLICA_INHIBITED",
++ "ERROR_DS_ATT_NOT_DEF_IN_SCHEMA",
++ "ERROR_DS_MAX_OBJ_SIZE_EXCEEDED",
++ "ERROR_DS_OBJ_STRING_NAME_EXISTS",
++ "ERROR_DS_NO_RDN_DEFINED_IN_SCHEMA",
++ "ERROR_DS_RDN_DOESNT_MATCH_SCHEMA",
++ "ERROR_DS_NO_REQUESTED_ATTS_FOUND",
++ "ERROR_DS_USER_BUFFER_TO_SMALL",
++ "ERROR_DS_ATT_IS_NOT_ON_OBJ",
++ "ERROR_DS_ILLEGAL_MOD_OPERATION",
++ "ERROR_DS_OBJ_TOO_LARGE",
++ "ERROR_DS_BAD_INSTANCE_TYPE",
++ "ERROR_DS_MASTERDSA_REQUIRED",
++ "ERROR_DS_OBJECT_CLASS_REQUIRED",
++ "ERROR_DS_MISSING_REQUIRED_ATT",
++ "ERROR_DS_ATT_NOT_DEF_FOR_CLASS",
++ "ERROR_DS_ATT_ALREADY_EXISTS",
++ "ERROR_DS_CANT_ADD_ATT_VALUES",
++ "ERROR_DS_SINGLE_VALUE_CONSTRAINT",
++ "ERROR_DS_RANGE_CONSTRAINT",
++ "ERROR_DS_ATT_VAL_ALREADY_EXISTS",
++ "ERROR_DS_CANT_REM_MISSING_ATT",
++ "ERROR_DS_CANT_REM_MISSING_ATT_VAL",
++ "ERROR_DS_ROOT_CANT_BE_SUBREF",
++ "ERROR_DS_NO_CHAINING",
++ "ERROR_DS_NO_CHAINED_EVAL",
++ "ERROR_DS_NO_PARENT_OBJECT",
++ "ERROR_DS_PARENT_IS_AN_ALIAS",
++ "ERROR_DS_CANT_MIX_MASTER_AND_REPS",
++ "ERROR_DS_CHILDREN_EXIST",
++ "ERROR_DS_OBJ_NOT_FOUND",
++ "ERROR_DS_ALIASED_OBJ_MISSING",
++ "ERROR_DS_BAD_NAME_SYNTAX",
++ "ERROR_DS_ALIAS_POINTS_TO_ALIAS",
++ "ERROR_DS_CANT_DEREF_ALIAS",
++ "ERROR_DS_OUT_OF_SCOPE",
++ "ERROR_DS_OBJECT_BEING_REMOVED",
++ "ERROR_DS_CANT_DELETE_DSA_OBJ",
++ "ERROR_DS_GENERIC_ERROR",
++ "ERROR_DS_DSA_MUST_BE_INT_MASTER",
++ "ERROR_DS_CLASS_NOT_DSA",
++ "ERROR_DS_INSUFF_ACCESS_RIGHTS",
++ "ERROR_DS_ILLEGAL_SUPERIOR",
++ "ERROR_DS_ATTRIBUTE_OWNED_BY_SAM",
++ "ERROR_DS_NAME_TOO_MANY_PARTS",
++ "ERROR_DS_NAME_TOO_LONG",
++ "ERROR_DS_NAME_VALUE_TOO_LONG",
++ "ERROR_DS_NAME_UNPARSEABLE",
++ "ERROR_DS_NAME_TYPE_UNKNOWN",
++ "ERROR_DS_NOT_AN_OBJECT",
++ "ERROR_DS_SEC_DESC_TOO_SHORT",
++ "ERROR_DS_SEC_DESC_INVALID",
++ "ERROR_DS_NO_DELETED_NAME",
++ "ERROR_DS_SUBREF_MUST_HAVE_PARENT",
++ "ERROR_DS_NCNAME_MUST_BE_NC",
++ "ERROR_DS_CANT_ADD_SYSTEM_ONLY",
++ "ERROR_DS_CLASS_MUST_BE_CONCRETE",
++ "ERROR_DS_INVALID_DMD",
++ "ERROR_DS_OBJ_GUID_EXISTS",
++ "ERROR_DS_NOT_ON_BACKLINK",
++ "ERROR_DS_NO_CROSSREF_FOR_NC",
++ "ERROR_DS_SHUTTING_DOWN",
++ "ERROR_DS_UNKNOWN_OPERATION",
++ "ERROR_DS_INVALID_ROLE_OWNER",
++ "ERROR_DS_COULDNT_CONTACT_FSMO",
++ "ERROR_DS_CROSS_NC_DN_RENAME",
++ "ERROR_DS_CANT_MOD_SYSTEM_ONLY",
++ "ERROR_DS_REPLICATOR_ONLY",
++ "ERROR_DS_OBJ_CLASS_NOT_DEFINED",
++ "ERROR_DS_OBJ_CLASS_NOT_SUBCLASS",
++ "ERROR_DS_NAME_REFERENCE_INVALID",
++ "ERROR_DS_CROSS_REF_EXISTS",
++ "ERROR_DS_CANT_DEL_MASTER_CROSSREF",
++ "ERROR_DS_SUBTREE_NOTIFY_NOT_NC_HEAD",
++ "ERROR_DS_NOTIFY_FILTER_TOO_COMPLEX",
++ "ERROR_DS_DUP_RDN",
++ "ERROR_DS_DUP_OID",
++ "ERROR_DS_DUP_MAPI_ID",
++ "ERROR_DS_DUP_SCHEMA_ID_GUID",
++ "ERROR_DS_DUP_LDAP_DISPLAY_NAME",
++ "ERROR_DS_SEMANTIC_ATT_TEST",
++ "ERROR_DS_SYNTAX_MISMATCH",
++ "ERROR_DS_EXISTS_IN_MUST_HAVE",
++ "ERROR_DS_EXISTS_IN_MAY_HAVE",
++ "ERROR_DS_NONEXISTENT_MAY_HAVE",
++ "ERROR_DS_NONEXISTENT_MUST_HAVE",
++ "ERROR_DS_AUX_CLS_TEST_FAIL",
++ "ERROR_DS_NONEXISTENT_POSS_SUP",
++ "ERROR_DS_SUB_CLS_TEST_FAIL",
++ "ERROR_DS_BAD_RDN_ATT_ID_SYNTAX",
++ "ERROR_DS_EXISTS_IN_AUX_CLS",
++ "ERROR_DS_EXISTS_IN_SUB_CLS",
++ "ERROR_DS_EXISTS_IN_POSS_SUP",
++ "ERROR_DS_RECALCSCHEMA_FAILED",
++ "ERROR_DS_TREE_DELETE_NOT_FINISHED",
++ "ERROR_DS_CANT_DELETE",
++ "ERROR_DS_ATT_SCHEMA_REQ_ID",
++ "ERROR_DS_BAD_ATT_SCHEMA_SYNTAX",
++ "ERROR_DS_CANT_CACHE_ATT",
++ "ERROR_DS_CANT_CACHE_CLASS",
++ "ERROR_DS_CANT_REMOVE_ATT_CACHE",
++ "ERROR_DS_CANT_REMOVE_CLASS_CACHE",
++ "ERROR_DS_CANT_RETRIEVE_DN",
++ "ERROR_DS_MISSING_SUPREF",
++ "ERROR_DS_CANT_RETRIEVE_INSTANCE",
++ "ERROR_DS_CODE_INCONSISTENCY",
++ "ERROR_DS_DATABASE_ERROR",
++ "ERROR_DS_GOVERNSID_MISSING",
++ "ERROR_DS_MISSING_EXPECTED_ATT",
++ "ERROR_DS_NCNAME_MISSING_CR_REF",
++ "ERROR_DS_SECURITY_CHECKING_ERROR",
++ "ERROR_DS_SCHEMA_NOT_LOADED",
++ "ERROR_DS_SCHEMA_ALLOC_FAILED",
++ "ERROR_DS_ATT_SCHEMA_REQ_SYNTAX",
++ "ERROR_DS_GCVERIFY_ERROR",
++ "ERROR_DS_DRA_SCHEMA_MISMATCH",
++ "ERROR_DS_CANT_FIND_DSA_OBJ",
++ "ERROR_DS_CANT_FIND_EXPECTED_NC",
++ "ERROR_DS_CANT_FIND_NC_IN_CACHE",
++ "ERROR_DS_CANT_RETRIEVE_CHILD",
++ "ERROR_DS_SECURITY_ILLEGAL_MODIFY",
++ "ERROR_DS_CANT_REPLACE_HIDDEN_REC",
++ "ERROR_DS_BAD_HIERARCHY_FILE",
++ "ERROR_DS_BUILD_HIERARCHY_TABLE_FAILED",
++ "ERROR_DS_CONFIG_PARAM_MISSING",
++ "ERROR_DS_COUNTING_AB_INDICES_FAILED",
++ "ERROR_DS_HIERARCHY_TABLE_MALLOC_FAILED",
++ "ERROR_DS_INTERNAL_FAILURE",
++ "ERROR_DS_UNKNOWN_ERROR",
++ "ERROR_DS_ROOT_REQUIRES_CLASS_TOP",
++ "ERROR_DS_REFUSING_FSMO_ROLES",
++ "ERROR_DS_MISSING_FSMO_SETTINGS",
++ "ERROR_DS_UNABLE_TO_SURRENDER_ROLES",
++ "ERROR_DS_DRA_GENERIC",
++ "ERROR_DS_DRA_INVALID_PARAMETER",
++ "ERROR_DS_DRA_BUSY",
++ "ERROR_DS_DRA_BAD_DN",
++ "ERROR_DS_DRA_BAD_NC",
++ "ERROR_DS_DRA_DN_EXISTS",
++ "ERROR_DS_DRA_INTERNAL_ERROR",
++ "ERROR_DS_DRA_INCONSISTENT_DIT",
++ "ERROR_DS_DRA_CONNECTION_FAILED",
++ "ERROR_DS_DRA_BAD_INSTANCE_TYPE",
++ "ERROR_DS_DRA_OUT_OF_MEM",
++ "ERROR_DS_DRA_MAIL_PROBLEM",
++ "ERROR_DS_DRA_REF_ALREADY_EXISTS",
++ "ERROR_DS_DRA_REF_NOT_FOUND",
++ "ERROR_DS_DRA_OBJ_IS_REP_SOURCE",
++ "ERROR_DS_DRA_DB_ERROR",
++ "ERROR_DS_DRA_NO_REPLICA",
++ "ERROR_DS_DRA_ACCESS_DENIED",
++ "ERROR_DS_DRA_NOT_SUPPORTED",
++ "ERROR_DS_DRA_RPC_CANCELLED",
++ "ERROR_DS_DRA_SOURCE_DISABLED",
++ "ERROR_DS_DRA_SINK_DISABLED",
++ "ERROR_DS_DRA_NAME_COLLISION",
++ "ERROR_DS_DRA_SOURCE_REINSTALLED",
++ "ERROR_DS_DRA_MISSING_PARENT",
++ "ERROR_DS_DRA_PREEMPTED",
++ "ERROR_DS_DRA_ABANDON_SYNC",
++ "ERROR_DS_DRA_SHUTDOWN",
++ "ERROR_DS_DRA_INCOMPATIBLE_PARTIAL_SET",
++ "ERROR_DS_DRA_SOURCE_IS_PARTIAL_REPLICA",
++ "ERROR_DS_DRA_EXTN_CONNECTION_FAILED",
++ "ERROR_DS_INSTALL_SCHEMA_MISMATCH",
++ "ERROR_DS_DUP_LINK_ID",
++ "ERROR_DS_NAME_ERROR_RESOLVING",
++ "ERROR_DS_NAME_ERROR_NOT_FOUND",
++ "ERROR_DS_NAME_ERROR_NOT_UNIQUE",
++ "ERROR_DS_NAME_ERROR_NO_MAPPING",
++ "ERROR_DS_NAME_ERROR_DOMAIN_ONLY",
++ "ERROR_DS_NAME_ERROR_NO_SYNTACTICAL_MAPPING",
++ "ERROR_DS_CONSTRUCTED_ATT_MOD",
++ "ERROR_DS_WRONG_OM_OBJ_CLASS",
++ "ERROR_DS_DRA_REPL_PENDING",
++ "ERROR_DS_DS_REQUIRED",
++ "ERROR_DS_INVALID_LDAP_DISPLAY_NAME",
++ "ERROR_DS_NON_BASE_SEARCH",
++ "ERROR_DS_CANT_RETRIEVE_ATTS",
++ "ERROR_DS_BACKLINK_WITHOUT_LINK",
++ "ERROR_DS_EPOCH_MISMATCH",
++ "ERROR_DS_SRC_NAME_MISMATCH",
++ "ERROR_DS_SRC_AND_DST_NC_IDENTICAL",
++ "ERROR_DS_DST_NC_MISMATCH",
++ "ERROR_DS_NOT_AUTHORITIVE_FOR_DST_NC",
++ "ERROR_DS_SRC_GUID_MISMATCH",
++ "ERROR_DS_CANT_MOVE_DELETED_OBJECT",
++ "ERROR_DS_PDC_OPERATION_IN_PROGRESS",
++ "ERROR_DS_CROSS_DOMAIN_CLEANUP_REQD",
++ "ERROR_DS_ILLEGAL_XDOM_MOVE_OPERATION",
++ "ERROR_DS_CANT_WITH_ACCT_GROUP_MEMBERSHPS",
++ "ERROR_DS_NC_MUST_HAVE_NC_PARENT",
++ "ERROR_DS_CR_IMPOSSIBLE_TO_VALIDATE",
++ "ERROR_DS_DST_DOMAIN_NOT_NATIVE",
++ "ERROR_DS_MISSING_INFRASTRUCTURE_CONTAINER",
++ "ERROR_DS_CANT_MOVE_ACCOUNT_GROUP",
++ "ERROR_DS_CANT_MOVE_RESOURCE_GROUP",
++ "ERROR_DS_INVALID_SEARCH_FLAG",
++ "ERROR_DS_NO_TREE_DELETE_ABOVE_NC",
++ "ERROR_DS_COULDNT_LOCK_TREE_FOR_DELETE",
++ "ERROR_DS_COULDNT_IDENTIFY_OBJECTS_FOR_TREE_DELETE",
++ "ERROR_DS_SAM_INIT_FAILURE",
++ "ERROR_DS_SENSITIVE_GROUP_VIOLATION",
++ "ERROR_DS_CANT_MOD_PRIMARYGROUPID",
++ "ERROR_DS_ILLEGAL_BASE_SCHEMA_MOD",
++ "ERROR_DS_NONSAFE_SCHEMA_CHANGE",
++ "ERROR_DS_SCHEMA_UPDATE_DISALLOWED",
++ "ERROR_DS_CANT_CREATE_UNDER_SCHEMA",
++ "ERROR_DS_INSTALL_NO_SRC_SCH_VERSION",
++ "ERROR_DS_INSTALL_NO_SCH_VERSION_IN_INIFILE",
++ "ERROR_DS_INVALID_GROUP_TYPE",
++ "ERROR_DS_NO_NEST_GLOBALGROUP_IN_MIXEDDOMAIN",
++ "ERROR_DS_NO_NEST_LOCALGROUP_IN_MIXEDDOMAIN",
++ "ERROR_DS_GLOBAL_CANT_HAVE_LOCAL_MEMBER",
++ "ERROR_DS_GLOBAL_CANT_HAVE_UNIVERSAL_MEMBER",
++ "ERROR_DS_UNIVERSAL_CANT_HAVE_LOCAL_MEMBER",
++ "ERROR_DS_GLOBAL_CANT_HAVE_CROSSDOMAIN_MEMBER",
++ "ERROR_DS_LOCAL_CANT_HAVE_CROSSDOMAIN_LOCAL_MEMBER",
++ "ERROR_DS_HAVE_PRIMARY_MEMBERS",
++ "ERROR_DS_STRING_SD_CONVERSION_FAILED",
++ "ERROR_DS_NAMING_MASTER_GC",
++ "ERROR_DS_DNS_LOOKUP_FAILURE",
++ "ERROR_DS_COULDNT_UPDATE_SPNS",
++ "ERROR_DS_CANT_RETRIEVE_SD",
++ "ERROR_DS_KEY_NOT_UNIQUE",
++ "ERROR_DS_WRONG_LINKED_ATT_SYNTAX",
++ "ERROR_DS_SAM_NEED_BOOTKEY_PASSWORD",
++ "ERROR_DS_SAM_NEED_BOOTKEY_FLOPPY",
++ "ERROR_DS_CANT_START",
++ "ERROR_DS_INIT_FAILURE",
++ "ERROR_DS_NO_PKT_PRIVACY_ON_CONNECTION",
++ "ERROR_DS_SOURCE_DOMAIN_IN_FOREST",
++ "ERROR_DS_DESTINATION_DOMAIN_NOT_IN_FOREST",
++ "ERROR_DS_DESTINATION_AUDITING_NOT_ENABLED",
++ "ERROR_DS_CANT_FIND_DC_FOR_SRC_DOMAIN",
++ "ERROR_DS_SRC_OBJ_NOT_GROUP_OR_USER",
++ "ERROR_DS_SRC_SID_EXISTS_IN_FOREST",
++ "ERROR_DS_SRC_AND_DST_OBJECT_CLASS_MISMATCH",
++ "ERROR_SAM_INIT_FAILURE",
++ "ERROR_DS_DRA_SCHEMA_INFO_SHIP",
++ "ERROR_DS_DRA_SCHEMA_CONFLICT",
++ "ERROR_DS_DRA_EARLIER_SCHEMA_CONFLICT",
++ "ERROR_DS_DRA_OBJ_NC_MISMATCH",
++ "ERROR_DS_NC_STILL_HAS_DSAS",
++ "ERROR_DS_GC_REQUIRED",
++ "ERROR_DS_LOCAL_MEMBER_OF_LOCAL_ONLY",
++ "ERROR_DS_NO_FPO_IN_UNIVERSAL_GROUPS",
++ "ERROR_DS_CANT_ADD_TO_GC",
++ "ERROR_DS_NO_CHECKPOINT_WITH_PDC",
++ "ERROR_DS_SOURCE_AUDITING_NOT_ENABLED",
++ "ERROR_DS_CANT_CREATE_IN_NONDOMAIN_NC",
++ "ERROR_DS_INVALID_NAME_FOR_SPN",
++ "ERROR_DS_FILTER_USES_CONTRUCTED_ATTRS",
++ "ERROR_DS_UNICODEPWD_NOT_IN_QUOTES",
++ "ERROR_DS_MACHINE_ACCOUNT_QUOTA_EXCEEDED",
++ "ERROR_DS_MUST_BE_RUN_ON_DST_DC",
++ "ERROR_DS_SRC_DC_MUST_BE_SP4_OR_GREATER",
++ "ERROR_DS_CANT_TREE_DELETE_CRITICAL_OBJ",
++ "ERROR_DS_INIT_FAILURE_CONSOLE",
++ "ERROR_DS_SAM_INIT_FAILURE_CONSOLE",
++ "ERROR_DS_FOREST_VERSION_TOO_HIGH",
++ "ERROR_DS_DOMAIN_VERSION_TOO_HIGH",
++ "ERROR_DS_FOREST_VERSION_TOO_LOW",
++ "ERROR_DS_DOMAIN_VERSION_TOO_LOW",
++ "ERROR_DS_INCOMPATIBLE_VERSION",
++ "ERROR_DS_LOW_DSA_VERSION",
++ "ERROR_DS_NO_BEHAVIOR_VERSION_IN_MIXEDDOMAIN",
++ "ERROR_DS_NOT_SUPPORTED_SORT_ORDER",
++ "ERROR_DS_NAME_NOT_UNIQUE",
++ "ERROR_DS_MACHINE_ACCOUNT_CREATED_PRENT4",
++ "ERROR_DS_OUT_OF_VERSION_STORE",
++ "ERROR_DS_INCOMPATIBLE_CONTROLS_USED",
++ "ERROR_DS_NO_REF_DOMAIN",
++ "ERROR_DS_RESERVED_LINK_ID",
++ "ERROR_DS_LINK_ID_NOT_AVAILABLE",
++ "ERROR_DS_AG_CANT_HAVE_UNIVERSAL_MEMBER",
++ "ERROR_DS_MODIFYDN_DISALLOWED_BY_INSTANCE_TYPE",
++ "ERROR_DS_NO_OBJECT_MOVE_IN_SCHEMA_NC",
++ "ERROR_DS_MODIFYDN_DISALLOWED_BY_FLAG",
++ "ERROR_DS_MODIFYDN_WRONG_GRANDPARENT",
++ "ERROR_DS_NAME_ERROR_TRUST_REFERRAL",
++ "ERROR_NOT_SUPPORTED_ON_STANDARD_SERVER",
++ "ERROR_DS_CANT_ACCESS_REMOTE_PART_OF_AD",
++ "ERROR_DS_CR_IMPOSSIBLE_TO_VALIDATE_V2",
++ "ERROR_DS_THREAD_LIMIT_EXCEEDED",
++ "ERROR_DS_NOT_CLOSEST",
++ "ERROR_DS_CANT_DERIVE_SPN_WITHOUT_SERVER_REF",
++ "ERROR_DS_SINGLE_USER_MODE_FAILED",
++ "ERROR_DS_NTDSCRIPT_SYNTAX_ERROR",
++ "ERROR_DS_NTDSCRIPT_PROCESS_ERROR",
++ "ERROR_DS_DIFFERENT_REPL_EPOCHS",
++ "ERROR_DS_DRS_EXTENSIONS_CHANGED",
++ "ERROR_DS_REPLICA_SET_CHANGE_NOT_ALLOWED_ON_DISABLED_CR",
++ "ERROR_DS_NO_MSDS_INTID",
++ "ERROR_DS_DUP_MSDS_INTID",
++ "ERROR_DS_EXISTS_IN_RDNATTID",
++ "ERROR_DS_AUTHORIZATION_FAILED",
++ "ERROR_DS_INVALID_SCRIPT",
++ "ERROR_DS_REMOTE_CROSSREF_OP_FAILED",
++ "ERROR_DS_CROSS_REF_BUSY",
++ "ERROR_DS_CANT_DERIVE_SPN_FOR_DELETED_DOMAIN",
++ "ERROR_DS_CANT_DEMOTE_WITH_WRITEABLE_NC",
++ "ERROR_DS_DUPLICATE_ID_FOUND",
++ "ERROR_DS_INSUFFICIENT_ATTR_TO_CREATE_OBJECT",
++ "ERROR_DS_GROUP_CONVERSION_ERROR",
++ "ERROR_DS_CANT_MOVE_APP_BASIC_GROUP",
++ "ERROR_DS_CANT_MOVE_APP_QUERY_GROUP",
++ "ERROR_DS_ROLE_NOT_VERIFIED",
++ "ERROR_DS_WKO_CONTAINER_CANNOT_BE_SPECIAL",
++ "ERROR_DS_DOMAIN_RENAME_IN_PROGRESS",
++ "ERROR_DS_EXISTING_AD_CHILD_NC",
++ "ERROR_DS_REPL_LIFETIME_EXCEEDED",
++ "ERROR_DS_DISALLOWED_IN_SYSTEM_CONTAINER",
++ "ERROR_DS_LDAP_SEND_QUEUE_FULL",
++ "ERROR_DS_DRA_OUT_SCHEDULE_WINDOW",
++ "ERROR_DS_POLICY_NOT_KNOWN",
++ "ERROR_NO_SITE_SETTINGS_OBJECT",
++ "ERROR_NO_SECRETS",
++ "ERROR_NO_WRITABLE_DC_FOUND",
++ "ERROR_DS_NO_SERVER_OBJECT",
++ "ERROR_DS_NO_NTDSA_OBJECT",
++ "ERROR_DS_NON_ASQ_SEARCH",
++ "ERROR_DS_AUDIT_FAILURE",
++ "ERROR_DS_INVALID_SEARCH_FLAG_SUBTREE",
++ "ERROR_DS_INVALID_SEARCH_FLAG_TUPLE",
++ "ERROR_DS_HIERARCHY_TABLE_TOO_DEEP",
++ "ERROR_DS_DRA_CORRUPT_UTD_VECTOR",
++ "ERROR_DS_DRA_SECRETS_DENIED",
++ "ERROR_DS_RESERVED_MAPI_ID",
++ "ERROR_DS_MAPI_ID_NOT_AVAILABLE",
++ "ERROR_DS_DRA_MISSING_KRBTGT_SECRET",
++ "ERROR_DS_DOMAIN_NAME_EXISTS_IN_FOREST",
++ "ERROR_DS_FLAT_NAME_EXISTS_IN_FOREST",
++ "ERROR_INVALID_USER_PRINCIPAL_NAME",
++ "ERROR_DS_OID_MAPPED_GROUP_CANT_HAVE_MEMBERS",
++ "ERROR_DS_OID_NOT_FOUND",
++ "ERROR_DS_DRA_RECYCLED_TARGET",
++ "ERROR_DS_DISALLOWED_NC_REDIRECT",
++ "ERROR_DS_HIGH_ADLDS_FFL",
++ "ERROR_DS_HIGH_DSA_VERSION",
++ "ERROR_DS_LOW_ADLDS_FFL",
++ "ERROR_DOMAIN_SID_SAME_AS_LOCAL_WORKSTATION",
++ "ERROR_DS_UNDELETE_SAM_VALIDATION_FAILED",
++ "ERROR_INCORRECT_ACCOUNT_TYPE",
++ "ERROR_DS_SPN_VALUE_NOT_UNIQUE_IN_FOREST",
++ "ERROR_DS_UPN_VALUE_NOT_UNIQUE_IN_FOREST",
++ "ERROR_DS_MISSING_FOREST_TRUST",
++ "ERROR_DS_VALUE_KEY_NOT_UNIQUE",
++ "ERROR_IPSEC_QM_POLICY_EXISTS",
++ "ERROR_IPSEC_QM_POLICY_NOT_FOUND",
++ "ERROR_IPSEC_QM_POLICY_IN_USE",
++ "ERROR_IPSEC_MM_POLICY_EXISTS",
++ "ERROR_IPSEC_MM_POLICY_NOT_FOUND",
++ "ERROR_IPSEC_MM_POLICY_IN_USE",
++ "ERROR_IPSEC_MM_FILTER_EXISTS",
++ "ERROR_IPSEC_MM_FILTER_NOT_FOUND",
++ "ERROR_IPSEC_TRANSPORT_FILTER_EXISTS",
++ "ERROR_IPSEC_TRANSPORT_FILTER_NOT_FOUND",
++ "ERROR_IPSEC_MM_AUTH_EXISTS",
++ "ERROR_IPSEC_MM_AUTH_NOT_FOUND",
++ "ERROR_IPSEC_MM_AUTH_IN_USE",
++ "ERROR_IPSEC_DEFAULT_MM_POLICY_NOT_FOUND",
++ "ERROR_IPSEC_DEFAULT_MM_AUTH_NOT_FOUND",
++ "ERROR_IPSEC_DEFAULT_QM_POLICY_NOT_FOUND",
++ "ERROR_IPSEC_TUNNEL_FILTER_EXISTS",
++ "ERROR_IPSEC_TUNNEL_FILTER_NOT_FOUND",
++ "ERROR_IPSEC_MM_FILTER_PENDING_DELETION",
++ "ERROR_IPSEC_TRANSPORT_FILTER_PENDING_DELETION",
++ "ERROR_IPSEC_TUNNEL_FILTER_PENDING_DELETION",
++ "ERROR_IPSEC_MM_POLICY_PENDING_DELETION",
++ "ERROR_IPSEC_MM_AUTH_PENDING_DELETION",
++ "ERROR_IPSEC_QM_POLICY_PENDING_DELETION",
++ "ERROR_IPSEC_IKE_NEG_STATUS_BEGIN",
++ "ERROR_IPSEC_IKE_AUTH_FAIL",
++ "ERROR_IPSEC_IKE_ATTRIB_FAIL",
++ "ERROR_IPSEC_IKE_NEGOTIATION_PENDING",
++ "ERROR_IPSEC_IKE_GENERAL_PROCESSING_ERROR",
++ "ERROR_IPSEC_IKE_TIMED_OUT",
++ "ERROR_IPSEC_IKE_NO_CERT",
++ "ERROR_IPSEC_IKE_SA_DELETED",
++ "ERROR_IPSEC_IKE_SA_REAPED",
++ "ERROR_IPSEC_IKE_MM_ACQUIRE_DROP",
++ "ERROR_IPSEC_IKE_QM_ACQUIRE_DROP",
++ "ERROR_IPSEC_IKE_QUEUE_DROP_MM",
++ "ERROR_IPSEC_IKE_QUEUE_DROP_NO_MM",
++ "ERROR_IPSEC_IKE_DROP_NO_RESPONSE",
++ "ERROR_IPSEC_IKE_MM_DELAY_DROP",
++ "ERROR_IPSEC_IKE_QM_DELAY_DROP",
++ "ERROR_IPSEC_IKE_ERROR",
++ "ERROR_IPSEC_IKE_CRL_FAILED",
++ "ERROR_IPSEC_IKE_INVALID_KEY_USAGE",
++ "ERROR_IPSEC_IKE_INVALID_CERT_TYPE",
++ "ERROR_IPSEC_IKE_NO_PRIVATE_KEY",
++ "ERROR_IPSEC_IKE_SIMULTANEOUS_REKEY",
++ "ERROR_IPSEC_IKE_DH_FAIL",
++ "ERROR_IPSEC_IKE_CRITICAL_PAYLOAD_NOT_RECOGNIZED",
++ "ERROR_IPSEC_IKE_INVALID_HEADER",
++ "ERROR_IPSEC_IKE_NO_POLICY",
++ "ERROR_IPSEC_IKE_INVALID_SIGNATURE",
++ "ERROR_IPSEC_IKE_KERBEROS_ERROR",
++ "ERROR_IPSEC_IKE_NO_PUBLIC_KEY",
++ "ERROR_IPSEC_IKE_PROCESS_ERR",
++ "ERROR_IPSEC_IKE_PROCESS_ERR_SA",
++ "ERROR_IPSEC_IKE_PROCESS_ERR_PROP",
++ "ERROR_IPSEC_IKE_PROCESS_ERR_TRANS",
++ "ERROR_IPSEC_IKE_PROCESS_ERR_KE",
++ "ERROR_IPSEC_IKE_PROCESS_ERR_ID",
++ "ERROR_IPSEC_IKE_PROCESS_ERR_CERT",
++ "ERROR_IPSEC_IKE_PROCESS_ERR_CERT_REQ",
++ "ERROR_IPSEC_IKE_PROCESS_ERR_HASH",
++ "ERROR_IPSEC_IKE_PROCESS_ERR_SIG",
++ "ERROR_IPSEC_IKE_PROCESS_ERR_NONCE",
++ "ERROR_IPSEC_IKE_PROCESS_ERR_NOTIFY",
++ "ERROR_IPSEC_IKE_PROCESS_ERR_DELETE",
++ "ERROR_IPSEC_IKE_PROCESS_ERR_VENDOR",
++ "ERROR_IPSEC_IKE_INVALID_PAYLOAD",
++ "ERROR_IPSEC_IKE_LOAD_SOFT_SA",
++ "ERROR_IPSEC_IKE_SOFT_SA_TORN_DOWN",
++ "ERROR_IPSEC_IKE_INVALID_COOKIE",
++ "ERROR_IPSEC_IKE_NO_PEER_CERT",
++ "ERROR_IPSEC_IKE_PEER_CRL_FAILED",
++ "ERROR_IPSEC_IKE_POLICY_CHANGE",
++ "ERROR_IPSEC_IKE_NO_MM_POLICY",
++ "ERROR_IPSEC_IKE_NOTCBPRIV",
++ "ERROR_IPSEC_IKE_SECLOADFAIL",
++ "ERROR_IPSEC_IKE_FAILSSPINIT",
++ "ERROR_IPSEC_IKE_FAILQUERYSSP",
++ "ERROR_IPSEC_IKE_SRVACQFAIL",
++ "ERROR_IPSEC_IKE_SRVQUERYCRED",
++ "ERROR_IPSEC_IKE_GETSPIFAIL",
++ "ERROR_IPSEC_IKE_INVALID_FILTER",
++ "ERROR_IPSEC_IKE_OUT_OF_MEMORY",
++ "ERROR_IPSEC_IKE_ADD_UPDATE_KEY_FAILED",
++ "ERROR_IPSEC_IKE_INVALID_POLICY",
++ "ERROR_IPSEC_IKE_UNKNOWN_DOI",
++ "ERROR_IPSEC_IKE_INVALID_SITUATION",
++ "ERROR_IPSEC_IKE_DH_FAILURE",
++ "ERROR_IPSEC_IKE_INVALID_GROUP",
++ "ERROR_IPSEC_IKE_ENCRYPT",
++ "ERROR_IPSEC_IKE_DECRYPT",
++ "ERROR_IPSEC_IKE_POLICY_MATCH",
++ "ERROR_IPSEC_IKE_UNSUPPORTED_ID",
++ "ERROR_IPSEC_IKE_INVALID_HASH",
++ "ERROR_IPSEC_IKE_INVALID_HASH_ALG",
++ "ERROR_IPSEC_IKE_INVALID_HASH_SIZE",
++ "ERROR_IPSEC_IKE_INVALID_ENCRYPT_ALG",
++ "ERROR_IPSEC_IKE_INVALID_AUTH_ALG",
++ "ERROR_IPSEC_IKE_INVALID_SIG",
++ "ERROR_IPSEC_IKE_LOAD_FAILED",
++ "ERROR_IPSEC_IKE_RPC_DELETE",
++ "ERROR_IPSEC_IKE_BENIGN_REINIT",
++ "ERROR_IPSEC_IKE_INVALID_RESPONDER_LIFETIME_NOTIFY",
++ "ERROR_IPSEC_IKE_INVALID_MAJOR_VERSION",
++ "ERROR_IPSEC_IKE_INVALID_CERT_KEYLEN",
++ "ERROR_IPSEC_IKE_MM_LIMIT",
++ "ERROR_IPSEC_IKE_NEGOTIATION_DISABLED",
++ "ERROR_IPSEC_IKE_QM_LIMIT",
++ "ERROR_IPSEC_IKE_MM_EXPIRED",
++ "ERROR_IPSEC_IKE_PEER_MM_ASSUMED_INVALID",
++ "ERROR_IPSEC_IKE_CERT_CHAIN_POLICY_MISMATCH",
++ "ERROR_IPSEC_IKE_UNEXPECTED_MESSAGE_ID",
++ "ERROR_IPSEC_IKE_INVALID_AUTH_PAYLOAD",
++ "ERROR_IPSEC_IKE_DOS_COOKIE_SENT",
++ "ERROR_IPSEC_IKE_SHUTTING_DOWN",
++ "ERROR_IPSEC_IKE_CGA_AUTH_FAILED",
++ "ERROR_IPSEC_IKE_PROCESS_ERR_NATOA",
++ "ERROR_IPSEC_IKE_INVALID_MM_FOR_QM",
++ "ERROR_IPSEC_IKE_QM_EXPIRED",
++ "ERROR_IPSEC_IKE_TOO_MANY_FILTERS",
++ "ERROR_IPSEC_IKE_NEG_STATUS_END",
++ "ERROR_IPSEC_IKE_KILL_DUMMY_NAP_TUNNEL",
++ "ERROR_IPSEC_IKE_INNER_IP_ASSIGNMENT_FAILURE",
++ "ERROR_IPSEC_IKE_REQUIRE_CP_PAYLOAD_MISSING",
++ "ERROR_IPSEC_KEY_MODULE_IMPERSONATION_NEGOTIATION_PENDING",
++ "ERROR_IPSEC_IKE_COEXISTENCE_SUPPRESS",
++ "ERROR_IPSEC_IKE_RATELIMIT_DROP",
++ "ERROR_IPSEC_IKE_PEER_DOESNT_SUPPORT_MOBIKE",
++ "ERROR_IPSEC_IKE_AUTHORIZATION_FAILURE",
++ "ERROR_IPSEC_IKE_STRONG_CRED_AUTHORIZATION_FAILURE",
++ "ERROR_IPSEC_IKE_AUTHORIZATION_FAILURE_WITH_OPTIONAL_RETRY",
++ "ERROR_IPSEC_IKE_STRONG_CRED_AUTHORIZATION_AND_CERTMAP_FAILURE",
++ "ERROR_IPSEC_IKE_NEG_STATUS_EXTENDED_END",
++ "ERROR_IPSEC_BAD_SPI",
++ "ERROR_IPSEC_SA_LIFETIME_EXPIRED",
++ "ERROR_IPSEC_WRONG_SA",
++ "ERROR_IPSEC_REPLAY_CHECK_FAILED",
++ "ERROR_IPSEC_INVALID_PACKET",
++ "ERROR_IPSEC_INTEGRITY_CHECK_FAILED",
++ "ERROR_IPSEC_CLEAR_TEXT_DROP",
++ "ERROR_IPSEC_AUTH_FIREWALL_DROP",
++ "ERROR_IPSEC_THROTTLE_DROP",
++ "ERROR_IPSEC_DOSP_BLOCK",
++ "ERROR_IPSEC_DOSP_RECEIVED_MULTICAST",
++ "ERROR_IPSEC_DOSP_INVALID_PACKET",
++ "ERROR_IPSEC_DOSP_STATE_LOOKUP_FAILED",
++ "ERROR_IPSEC_DOSP_MAX_ENTRIES",
++ "ERROR_IPSEC_DOSP_KEYMOD_NOT_ALLOWED",
++ "ERROR_IPSEC_DOSP_NOT_INSTALLED",
++ "ERROR_IPSEC_DOSP_MAX_PER_IP_RATELIMIT_QUEUES",
++ "ERROR_SXS_SECTION_NOT_FOUND",
++ "ERROR_SXS_CANT_GEN_ACTCTX",
++ "ERROR_SXS_INVALID_ACTCTXDATA_FORMAT",
++ "ERROR_SXS_ASSEMBLY_NOT_FOUND",
++ "ERROR_SXS_MANIFEST_FORMAT_ERROR",
++ "ERROR_SXS_MANIFEST_PARSE_ERROR",
++ "ERROR_SXS_ACTIVATION_CONTEXT_DISABLED",
++ "ERROR_SXS_KEY_NOT_FOUND",
++ "ERROR_SXS_VERSION_CONFLICT",
++ "ERROR_SXS_WRONG_SECTION_TYPE",
++ "ERROR_SXS_THREAD_QUERIES_DISABLED",
++ "ERROR_SXS_PROCESS_DEFAULT_ALREADY_SET",
++ "ERROR_SXS_UNKNOWN_ENCODING_GROUP",
++ "ERROR_SXS_UNKNOWN_ENCODING",
++ "ERROR_SXS_INVALID_XML_NAMESPACE_URI",
++ "ERROR_SXS_ROOT_MANIFEST_DEPENDENCY_NOT_INSTALLED",
++ "ERROR_SXS_LEAF_MANIFEST_DEPENDENCY_NOT_INSTALLED",
++ "ERROR_SXS_INVALID_ASSEMBLY_IDENTITY_ATTRIBUTE",
++ "ERROR_SXS_MANIFEST_MISSING_REQUIRED_DEFAULT_NAMESPACE",
++ "ERROR_SXS_MANIFEST_INVALID_REQUIRED_DEFAULT_NAMESPACE",
++ "ERROR_SXS_PRIVATE_MANIFEST_CROSS_PATH_WITH_REPARSE_POINT",
++ "ERROR_SXS_DUPLICATE_DLL_NAME",
++ "ERROR_SXS_DUPLICATE_WINDOWCLASS_NAME",
++ "ERROR_SXS_DUPLICATE_CLSID",
++ "ERROR_SXS_DUPLICATE_IID",
++ "ERROR_SXS_DUPLICATE_TLBID",
++ "ERROR_SXS_DUPLICATE_PROGID",
++ "ERROR_SXS_DUPLICATE_ASSEMBLY_NAME",
++ "ERROR_SXS_FILE_HASH_MISMATCH",
++ "ERROR_SXS_POLICY_PARSE_ERROR",
++ "ERROR_SXS_XML_E_MISSINGQUOTE",
++ "ERROR_SXS_XML_E_COMMENTSYNTAX",
++ "ERROR_SXS_XML_E_BADSTARTNAMECHAR",
++ "ERROR_SXS_XML_E_BADNAMECHAR",
++ "ERROR_SXS_XML_E_BADCHARINSTRING",
++ "ERROR_SXS_XML_E_XMLDECLSYNTAX",
++ "ERROR_SXS_XML_E_BADCHARDATA",
++ "ERROR_SXS_XML_E_MISSINGWHITESPACE",
++ "ERROR_SXS_XML_E_EXPECTINGTAGEND",
++ "ERROR_SXS_XML_E_MISSINGSEMICOLON",
++ "ERROR_SXS_XML_E_UNBALANCEDPAREN",
++ "ERROR_SXS_XML_E_INTERNALERROR",
++ "ERROR_SXS_XML_E_UNEXPECTED_WHITESPACE",
++ "ERROR_SXS_XML_E_INCOMPLETE_ENCODING",
++ "ERROR_SXS_XML_E_MISSING_PAREN",
++ "ERROR_SXS_XML_E_EXPECTINGCLOSEQUOTE",
++ "ERROR_SXS_XML_E_MULTIPLE_COLONS",
++ "ERROR_SXS_XML_E_INVALID_DECIMAL",
++ "ERROR_SXS_XML_E_INVALID_HEXIDECIMAL",
++ "ERROR_SXS_XML_E_INVALID_UNICODE",
++ "ERROR_SXS_XML_E_WHITESPACEORQUESTIONMARK",
++ "ERROR_SXS_XML_E_UNEXPECTEDENDTAG",
++ "ERROR_SXS_XML_E_UNCLOSEDTAG",
++ "ERROR_SXS_XML_E_DUPLICATEATTRIBUTE",
++ "ERROR_SXS_XML_E_MULTIPLEROOTS",
++ "ERROR_SXS_XML_E_INVALIDATROOTLEVEL",
++ "ERROR_SXS_XML_E_BADXMLDECL",
++ "ERROR_SXS_XML_E_MISSINGROOT",
++ "ERROR_SXS_XML_E_UNEXPECTEDEOF",
++ "ERROR_SXS_XML_E_BADPEREFINSUBSET",
++ "ERROR_SXS_XML_E_UNCLOSEDSTARTTAG",
++ "ERROR_SXS_XML_E_UNCLOSEDENDTAG",
++ "ERROR_SXS_XML_E_UNCLOSEDSTRING",
++ "ERROR_SXS_XML_E_UNCLOSEDCOMMENT",
++ "ERROR_SXS_XML_E_UNCLOSEDDECL",
++ "ERROR_SXS_XML_E_UNCLOSEDCDATA",
++ "ERROR_SXS_XML_E_RESERVEDNAMESPACE",
++ "ERROR_SXS_XML_E_INVALIDENCODING",
++ "ERROR_SXS_XML_E_INVALIDSWITCH",
++ "ERROR_SXS_XML_E_BADXMLCASE",
++ "ERROR_SXS_XML_E_INVALID_STANDALONE",
++ "ERROR_SXS_XML_E_UNEXPECTED_STANDALONE",
++ "ERROR_SXS_XML_E_INVALID_VERSION",
++ "ERROR_SXS_XML_E_MISSINGEQUALS",
++ "ERROR_SXS_PROTECTION_RECOVERY_FAILED",
++ "ERROR_SXS_PROTECTION_PUBLIC_KEY_TOO_SHORT",
++ "ERROR_SXS_PROTECTION_CATALOG_NOT_VALID",
++ "ERROR_SXS_UNTRANSLATABLE_HRESULT",
++ "ERROR_SXS_PROTECTION_CATALOG_FILE_MISSING",
++ "ERROR_SXS_MISSING_ASSEMBLY_IDENTITY_ATTRIBUTE",
++ "ERROR_SXS_INVALID_ASSEMBLY_IDENTITY_ATTRIBUTE_NAME",
++ "ERROR_SXS_ASSEMBLY_MISSING",
++ "ERROR_SXS_CORRUPT_ACTIVATION_STACK",
++ "ERROR_SXS_CORRUPTION",
++ "ERROR_SXS_EARLY_DEACTIVATION",
++ "ERROR_SXS_INVALID_DEACTIVATION",
++ "ERROR_SXS_MULTIPLE_DEACTIVATION",
++ "ERROR_SXS_PROCESS_TERMINATION_REQUESTED",
++ "ERROR_SXS_RELEASE_ACTIVATION_CONTEXT",
++ "ERROR_SXS_SYSTEM_DEFAULT_ACTIVATION_CONTEXT_EMPTY",
++ "ERROR_SXS_INVALID_IDENTITY_ATTRIBUTE_VALUE",
++ "ERROR_SXS_INVALID_IDENTITY_ATTRIBUTE_NAME",
++ "ERROR_SXS_IDENTITY_DUPLICATE_ATTRIBUTE",
++ "ERROR_SXS_IDENTITY_PARSE_ERROR",
++ "ERROR_MALFORMED_SUBSTITUTION_STRING",
++ "ERROR_SXS_INCORRECT_PUBLIC_KEY_TOKEN",
++ "ERROR_UNMAPPED_SUBSTITUTION_STRING",
++ "ERROR_SXS_ASSEMBLY_NOT_LOCKED",
++ "ERROR_SXS_COMPONENT_STORE_CORRUPT",
++ "ERROR_ADVANCED_INSTALLER_FAILED",
++ "ERROR_XML_ENCODING_MISMATCH",
++ "ERROR_SXS_MANIFEST_IDENTITY_SAME_BUT_CONTENTS_DIFFERENT",
++ "ERROR_SXS_IDENTITIES_DIFFERENT",
++ "ERROR_SXS_ASSEMBLY_IS_NOT_A_DEPLOYMENT",
++ "ERROR_SXS_FILE_NOT_PART_OF_ASSEMBLY",
++ "ERROR_SXS_MANIFEST_TOO_BIG",
++ "ERROR_SXS_SETTING_NOT_REGISTERED",
++ "ERROR_SXS_TRANSACTION_CLOSURE_INCOMPLETE",
++ "ERROR_SMI_PRIMITIVE_INSTALLER_FAILED",
++ "ERROR_GENERIC_COMMAND_FAILED",
++ "ERROR_SXS_FILE_HASH_MISSING",
++ "ERROR_SXS_DUPLICATE_ACTIVATABLE_CLASS",
++ "ERROR_EVT_INVALID_CHANNEL_PATH",
++ "ERROR_EVT_INVALID_QUERY",
++ "ERROR_EVT_PUBLISHER_METADATA_NOT_FOUND",
++ "ERROR_EVT_EVENT_TEMPLATE_NOT_FOUND",
++ "ERROR_EVT_INVALID_PUBLISHER_NAME",
++ "ERROR_EVT_INVALID_EVENT_DATA",
++ "ERROR_EVT_CHANNEL_NOT_FOUND",
++ "ERROR_EVT_MALFORMED_XML_TEXT",
++ "ERROR_EVT_SUBSCRIPTION_TO_DIRECT_CHANNEL",
++ "ERROR_EVT_CONFIGURATION_ERROR",
++ "ERROR_EVT_QUERY_RESULT_STALE",
++ "ERROR_EVT_QUERY_RESULT_INVALID_POSITION",
++ "ERROR_EVT_NON_VALIDATING_MSXML",
++ "ERROR_EVT_FILTER_ALREADYSCOPED",
++ "ERROR_EVT_FILTER_NOTELTSET",
++ "ERROR_EVT_FILTER_INVARG",
++ "ERROR_EVT_FILTER_INVTEST",
++ "ERROR_EVT_FILTER_INVTYPE",
++ "ERROR_EVT_FILTER_PARSEERR",
++ "ERROR_EVT_FILTER_UNSUPPORTEDOP",
++ "ERROR_EVT_FILTER_UNEXPECTEDTOKEN",
++ "ERROR_EVT_INVALID_OPERATION_OVER_ENABLED_DIRECT_CHANNEL",
++ "ERROR_EVT_INVALID_CHANNEL_PROPERTY_VALUE",
++ "ERROR_EVT_INVALID_PUBLISHER_PROPERTY_VALUE",
++ "ERROR_EVT_CHANNEL_CANNOT_ACTIVATE",
++ "ERROR_EVT_FILTER_TOO_COMPLEX",
++ "ERROR_EVT_MESSAGE_NOT_FOUND",
++ "ERROR_EVT_MESSAGE_ID_NOT_FOUND",
++ "ERROR_EVT_UNRESOLVED_VALUE_INSERT",
++ "ERROR_EVT_UNRESOLVED_PARAMETER_INSERT",
++ "ERROR_EVT_MAX_INSERTS_REACHED",
++ "ERROR_EVT_EVENT_DEFINITION_NOT_FOUND",
++ "ERROR_EVT_MESSAGE_LOCALE_NOT_FOUND",
++ "ERROR_EVT_VERSION_TOO_OLD",
++ "ERROR_EVT_VERSION_TOO_NEW",
++ "ERROR_EVT_CANNOT_OPEN_CHANNEL_OF_QUERY",
++ "ERROR_EVT_PUBLISHER_DISABLED",
++ "ERROR_EVT_FILTER_OUT_OF_RANGE",
++ "ERROR_EC_SUBSCRIPTION_CANNOT_ACTIVATE",
++ "ERROR_EC_LOG_DISABLED",
++ "ERROR_EC_CIRCULAR_FORWARDING",
++ "ERROR_EC_CREDSTORE_FULL",
++ "ERROR_EC_CRED_NOT_FOUND",
++ "ERROR_EC_NO_ACTIVE_CHANNEL",
++ "ERROR_MUI_FILE_NOT_FOUND",
++ "ERROR_MUI_INVALID_FILE",
++ "ERROR_MUI_INVALID_RC_CONFIG",
++ "ERROR_MUI_INVALID_LOCALE_NAME",
++ "ERROR_MUI_INVALID_ULTIMATEFALLBACK_NAME",
++ "ERROR_MUI_FILE_NOT_LOADED",
++ "ERROR_RESOURCE_ENUM_USER_STOP",
++ "ERROR_MUI_INTLSETTINGS_UILANG_NOT_INSTALLED",
++ "ERROR_MUI_INTLSETTINGS_INVALID_LOCALE_NAME",
++ "ERROR_MRM_RUNTIME_NO_DEFAULT_OR_NEUTRAL_RESOURCE",
++ "ERROR_MRM_INVALID_PRICONFIG",
++ "ERROR_MRM_INVALID_FILE_TYPE",
++ "ERROR_MRM_UNKNOWN_QUALIFIER",
++ "ERROR_MRM_INVALID_QUALIFIER_VALUE",
++ "ERROR_MRM_NO_CANDIDATE",
++ "ERROR_MRM_NO_MATCH_OR_DEFAULT_CANDIDATE",
++ "ERROR_MRM_RESOURCE_TYPE_MISMATCH",
++ "ERROR_MRM_DUPLICATE_MAP_NAME",
++ "ERROR_MRM_DUPLICATE_ENTRY",
++ "ERROR_MRM_INVALID_RESOURCE_IDENTIFIER",
++ "ERROR_MRM_FILEPATH_TOO_LONG",
++ "ERROR_MRM_UNSUPPORTED_DIRECTORY_TYPE",
++ "ERROR_MRM_INVALID_PRI_FILE",
++ "ERROR_MRM_NAMED_RESOURCE_NOT_FOUND",
++ "ERROR_MRM_MAP_NOT_FOUND",
++ "ERROR_MRM_UNSUPPORTED_PROFILE_TYPE",
++ "ERROR_MRM_INVALID_QUALIFIER_OPERATOR",
++ "ERROR_MRM_INDETERMINATE_QUALIFIER_VALUE",
++ "ERROR_MRM_AUTOMERGE_ENABLED",
++ "ERROR_MRM_TOO_MANY_RESOURCES",
++ "ERROR_MRM_UNSUPPORTED_FILE_TYPE_FOR_MERGE",
++ "ERROR_MRM_UNSUPPORTED_FILE_TYPE_FOR_LOAD_UNLOAD_PRI_FILE",
++ "ERROR_MRM_NO_CURRENT_VIEW_ON_THREAD",
++ "ERROR_DIFFERENT_PROFILE_RESOURCE_MANAGER_EXIST",
++ "ERROR_OPERATION_NOT_ALLOWED_FROM_SYSTEM_COMPONENT",
++ "ERROR_MRM_DIRECT_REF_TO_NON_DEFAULT_RESOURCE",
++ "ERROR_MRM_GENERATION_COUNT_MISMATCH",
++ "ERROR_PRI_MERGE_VERSION_MISMATCH",
++ "ERROR_PRI_MERGE_MISSING_SCHEMA",
++ "ERROR_PRI_MERGE_LOAD_FILE_FAILED",
++ "ERROR_PRI_MERGE_ADD_FILE_FAILED",
++ "ERROR_PRI_MERGE_WRITE_FILE_FAILED",
++ "ERROR_PRI_MERGE_MULTIPLE_PACKAGE_FAMILIES_NOT_ALLOWED",
++ "ERROR_PRI_MERGE_MULTIPLE_MAIN_PACKAGES_NOT_ALLOWED",
++ "ERROR_PRI_MERGE_BUNDLE_PACKAGES_NOT_ALLOWED",
++ "ERROR_PRI_MERGE_MAIN_PACKAGE_REQUIRED",
++ "ERROR_PRI_MERGE_RESOURCE_PACKAGE_REQUIRED",
++ "ERROR_PRI_MERGE_INVALID_FILE_NAME",
++ "ERROR_MRM_PACKAGE_NOT_FOUND",
++ "ERROR_MRM_MISSING_DEFAULT_LANGUAGE",
++ "ERROR_MCA_INVALID_CAPABILITIES_STRING",
++ "ERROR_MCA_INVALID_VCP_VERSION",
++ "ERROR_MCA_MONITOR_VIOLATES_MCCS_SPECIFICATION",
++ "ERROR_MCA_MCCS_VERSION_MISMATCH",
++ "ERROR_MCA_UNSUPPORTED_MCCS_VERSION",
++ "ERROR_MCA_INTERNAL_ERROR",
++ "ERROR_MCA_INVALID_TECHNOLOGY_TYPE_RETURNED",
++ "ERROR_MCA_UNSUPPORTED_COLOR_TEMPERATURE",
++ "ERROR_AMBIGUOUS_SYSTEM_DEVICE",
++ "ERROR_SYSTEM_DEVICE_NOT_FOUND",
++ "ERROR_HASH_NOT_SUPPORTED",
++ "ERROR_HASH_NOT_PRESENT",
++ "ERROR_SECONDARY_IC_PROVIDER_NOT_REGISTERED",
++ "ERROR_GPIO_CLIENT_INFORMATION_INVALID",
++ "ERROR_GPIO_VERSION_NOT_SUPPORTED",
++ "ERROR_GPIO_INVALID_REGISTRATION_PACKET",
++ "ERROR_GPIO_OPERATION_DENIED",
++ "ERROR_GPIO_INCOMPATIBLE_CONNECT_MODE",
++ "ERROR_GPIO_INTERRUPT_ALREADY_UNMASKED",
++ "ERROR_CANNOT_SWITCH_RUNLEVEL",
++ "ERROR_INVALID_RUNLEVEL_SETTING",
++ "ERROR_RUNLEVEL_SWITCH_TIMEOUT",
++ "ERROR_RUNLEVEL_SWITCH_AGENT_TIMEOUT",
++ "ERROR_RUNLEVEL_SWITCH_IN_PROGRESS",
++ "ERROR_SERVICES_FAILED_AUTOSTART",
++ "ERROR_COM_TASK_STOP_PENDING",
++ "ERROR_INSTALL_OPEN_PACKAGE_FAILED",
++ "ERROR_INSTALL_PACKAGE_NOT_FOUND",
++ "ERROR_INSTALL_INVALID_PACKAGE",
++ "ERROR_INSTALL_RESOLVE_DEPENDENCY_FAILED",
++ "ERROR_INSTALL_OUT_OF_DISK_SPACE",
++ "ERROR_INSTALL_NETWORK_FAILURE",
++ "ERROR_INSTALL_REGISTRATION_FAILURE",
++ "ERROR_INSTALL_DEREGISTRATION_FAILURE",
++ "ERROR_INSTALL_CANCEL",
++ "ERROR_INSTALL_FAILED",
++ "ERROR_REMOVE_FAILED",
++ "ERROR_PACKAGE_ALREADY_EXISTS",
++ "ERROR_NEEDS_REMEDIATION",
++ "ERROR_INSTALL_PREREQUISITE_FAILED",
++ "ERROR_PACKAGE_REPOSITORY_CORRUPTED",
++ "ERROR_INSTALL_POLICY_FAILURE",
++ "ERROR_PACKAGE_UPDATING",
++ "ERROR_DEPLOYMENT_BLOCKED_BY_POLICY",
++ "ERROR_PACKAGES_IN_USE",
++ "ERROR_RECOVERY_FILE_CORRUPT",
++ "ERROR_INVALID_STAGED_SIGNATURE",
++ "ERROR_DELETING_EXISTING_APPLICATIONDATA_STORE_FAILED",
++ "ERROR_INSTALL_PACKAGE_DOWNGRADE",
++ "ERROR_SYSTEM_NEEDS_REMEDIATION",
++ "ERROR_APPX_INTEGRITY_FAILURE_CLR_NGEN",
++ "ERROR_RESILIENCY_FILE_CORRUPT",
++ "ERROR_INSTALL_FIREWALL_SERVICE_NOT_RUNNING",
++ "ERROR_PACKAGE_MOVE_FAILED",
++ "ERROR_INSTALL_VOLUME_NOT_EMPTY",
++ "ERROR_INSTALL_VOLUME_OFFLINE",
++ "ERROR_INSTALL_VOLUME_CORRUPT",
++ "ERROR_NEEDS_REGISTRATION",
++ "ERROR_INSTALL_WRONG_PROCESSOR_ARCHITECTURE",
++ "ERROR_DEV_SIDELOAD_LIMIT_EXCEEDED",
++ "ERROR_INSTALL_OPTIONAL_PACKAGE_REQUIRES_MAIN_PACKAGE",
++ "ERROR_PACKAGE_NOT_SUPPORTED_ON_FILESYSTEM",
++ "ERROR_PACKAGE_MOVE_BLOCKED_BY_STREAMING",
++ "ERROR_INSTALL_OPTIONAL_PACKAGE_APPLICATIONID_NOT_UNIQUE",
++ "ERROR_PACKAGE_STAGING_ONHOLD",
++ "ERROR_INSTALL_INVALID_RELATED_SET_UPDATE",
++ "ERROR_INSTALL_OPTIONAL_PACKAGE_REQUIRES_MAIN_PACKAGE_FULLTRUST_CAPABILITY",
++ "ERROR_DEPLOYMENT_BLOCKED_BY_USER_LOG_OFF",
++ "ERROR_PROVISION_OPTIONAL_PACKAGE_REQUIRES_MAIN_PACKAGE_PROVISIONED",
++ "ERROR_PACKAGES_REPUTATION_CHECK_FAILED",
++ "ERROR_PACKAGES_REPUTATION_CHECK_TIMEDOUT",
++ "ERROR_DEPLOYMENT_OPTION_NOT_SUPPORTED",
++ "ERROR_APPINSTALLER_ACTIVATION_BLOCKED",
++ "ERROR_REGISTRATION_FROM_REMOTE_DRIVE_NOT_SUPPORTED",
++ "ERROR_APPX_RAW_DATA_WRITE_FAILED",
++ "ERROR_DEPLOYMENT_BLOCKED_BY_VOLUME_POLICY_PACKAGE",
++ "ERROR_DEPLOYMENT_BLOCKED_BY_VOLUME_POLICY_MACHINE",
++ "ERROR_DEPLOYMENT_BLOCKED_BY_PROFILE_POLICY",
++ "ERROR_DEPLOYMENT_FAILED_CONFLICTING_MUTABLE_PACKAGE_DIRECTORY",
++ "ERROR_SINGLETON_RESOURCE_INSTALLED_IN_ACTIVE_USER",
++ "ERROR_DIFFERENT_VERSION_OF_PACKAGED_SERVICE_INSTALLED",
++ "ERROR_SERVICE_EXISTS_AS_NON_PACKAGED_SERVICE",
++ "ERROR_PACKAGED_SERVICE_REQUIRES_ADMIN_PRIVILEGES",
++ "ERROR_REDIRECTION_TO_DEFAULT_ACCOUNT_NOT_ALLOWED",
++ "ERROR_PACKAGE_LACKS_CAPABILITY_TO_DEPLOY_ON_HOST",
++ "ERROR_UNSIGNED_PACKAGE_INVALID_CONTENT",
++ "ERROR_UNSIGNED_PACKAGE_INVALID_PUBLISHER_NAMESPACE",
++ "ERROR_SIGNED_PACKAGE_INVALID_PUBLISHER_NAMESPACE",
++ "ERROR_PACKAGE_EXTERNAL_LOCATION_NOT_ALLOWED",
++ "ERROR_INSTALL_FULLTRUST_HOSTRUNTIME_REQUIRES_MAIN_PACKAGE_FULLTRUST_CAPABILITY",
++ "ERROR_STATE_LOAD_STORE_FAILED",
++ "ERROR_STATE_GET_VERSION_FAILED",
++ "ERROR_STATE_SET_VERSION_FAILED",
++ "ERROR_STATE_STRUCTURED_RESET_FAILED",
++ "ERROR_STATE_OPEN_CONTAINER_FAILED",
++ "ERROR_STATE_CREATE_CONTAINER_FAILED",
++ "ERROR_STATE_DELETE_CONTAINER_FAILED",
++ "ERROR_STATE_READ_SETTING_FAILED",
++ "ERROR_STATE_WRITE_SETTING_FAILED",
++ "ERROR_STATE_DELETE_SETTING_FAILED",
++ "ERROR_STATE_QUERY_SETTING_FAILED",
++ "ERROR_STATE_READ_COMPOSITE_SETTING_FAILED",
++ "ERROR_STATE_WRITE_COMPOSITE_SETTING_FAILED",
++ "ERROR_STATE_ENUMERATE_CONTAINER_FAILED",
++ "ERROR_STATE_ENUMERATE_SETTINGS_FAILED",
++ "ERROR_STATE_COMPOSITE_SETTING_VALUE_SIZE_LIMIT_EXCEEDED",
++ "ERROR_STATE_SETTING_VALUE_SIZE_LIMIT_EXCEEDED",
++ "ERROR_STATE_SETTING_NAME_SIZE_LIMIT_EXCEEDED",
++ "ERROR_STATE_CONTAINER_NAME_SIZE_LIMIT_EXCEEDED",
++ "ERROR_API_UNAVAILABLE",
++};
++
++const char* WinErrorToString(uint16_t error) {
++ auto itr = std::find(std::begin(kWinErrorValues),
++ std::end(kWinErrorValues),
++ error);
++ if (itr == std::end(kWinErrorValues)) {
++ return nullptr;
++ }
++
++ return kWinErrorStrings[itr - std::begin(kWinErrorValues)];
+ }
+
+ } // namespace google_breakpad
+diff --git a/src/processor/symbolic_constants_win.h b/src/processor/symbolic_constants_win.h
+--- a/src/processor/symbolic_constants_win.h
++++ b/src/processor/symbolic_constants_win.h
+@@ -31,24 +31,31 @@
+ //
+ // Provides a means to convert NTSTATUS codes to strings.
+ //
+ // Author: Ben Wagner
+
+ #ifndef GOOGLE_BREAKPAD_PROCESSOR_SYMBOLIC_CONSTANTS_WIN_H_
+ #define GOOGLE_BREAKPAD_PROCESSOR_SYMBOLIC_CONSTANTS_WIN_H_
+
++#include <stdint.h>
+ #include <string>
+
+ #include "common/using_std_string.h"
+ #include "google_breakpad/common/breakpad_types.h"
+
+ namespace google_breakpad {
+
+-/* Converts a NTSTATUS code to a reason string. */
+-string NTStatusToString(uint32_t ntstatus);
++/* Converts an NTSTATUS code to its string representation. Returns nullptr if
++ * no entry corresponds to the code. */
++const char* NTStatusToString(uint32_t ntstatus);
+
+-/* Converts a FAST_FAIL code to a reason string. */
+-string FastFailToString(uint32_t fast_fail_code);
++/* Converts a FAST_FAIL code to its string representation. Returns nullptr if
++ * no entry corresponds to the code. */
++const char* FastFailToString(uint32_t fast_fail_code);
++
++/* Converts an ERROR code to its string representation. Returns nullptr if
++ * no entry corresponds to the code. */
++const char* WinErrorToString(uint16_t error);
+
+ } // namespace google_breakpad
+
+ #endif // GOOGLE_BREAKPAD_PROCESSOR_SYMBOLIC_CONSTANTS_WIN_H_
diff --git a/toolkit/crashreporter/breakpad-patches/23-si-user-si-kernel-siginfo.patch b/toolkit/crashreporter/breakpad-patches/23-si-user-si-kernel-siginfo.patch
new file mode 100644
index 0000000000..9e779f7dd8
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-patches/23-si-user-si-kernel-siginfo.patch
@@ -0,0 +1,76 @@
+diff --git a/src/google_breakpad/common/minidump_exception_linux.h b/src/google_breakpad/common/minidump_exception_linux.h
+--- a/src/google_breakpad/common/minidump_exception_linux.h
++++ b/src/google_breakpad/common/minidump_exception_linux.h
+@@ -83,16 +83,20 @@ typedef enum {
+ MD_EXCEPTION_CODE_LIN_DUMP_REQUESTED = 0xFFFFFFFF /* No exception,
+ dump requested. */
+ } MDExceptionCodeLinux;
+
+ /* For (MDException).exception_flags. These values come from
+ * asm-generic/siginfo.h.
+ */
+ typedef enum {
++ /* Generic */
++ MD_EXCEPTION_FLAG_LIN_SI_USER = 0,
++ MD_EXCEPTION_FLAG_LIN_SI_KERNEL = 0x80,
++
+ /* SIGILL */
+ MD_EXCEPTION_FLAG_LIN_ILL_ILLOPC = 1,
+ MD_EXCEPTION_FLAG_LIN_ILL_ILLOPN = 2,
+ MD_EXCEPTION_FLAG_LIN_ILL_ILLADR = 3,
+ MD_EXCEPTION_FLAG_LIN_ILL_ILLTRP = 4,
+ MD_EXCEPTION_FLAG_LIN_ILL_PRVOPC = 5,
+ MD_EXCEPTION_FLAG_LIN_ILL_PRVREG = 6,
+ MD_EXCEPTION_FLAG_LIN_ILL_COPROC = 7,
+diff --git a/src/processor/minidump_processor.cc b/src/processor/minidump_processor.cc
+--- a/src/processor/minidump_processor.cc
++++ b/src/processor/minidump_processor.cc
+@@ -1401,16 +1401,22 @@ string MinidumpProcessor::GetCrashReason
+ reason = "SIGTRAP";
+ break;
+ case MD_EXCEPTION_CODE_LIN_SIGABRT:
+ reason = "SIGABRT";
+ break;
+ case MD_EXCEPTION_CODE_LIN_SIGBUS:
+ reason = "SIGBUS / ";
+ switch (exception_flags) {
++ case MD_EXCEPTION_FLAG_LIN_SI_USER:
++ reason.append("SI_USER");
++ break;
++ case MD_EXCEPTION_FLAG_LIN_SI_KERNEL:
++ reason.append("SI_KERNEL");
++ break;
+ case MD_EXCEPTION_FLAG_LIN_BUS_ADRALN:
+ reason.append("BUS_ADRALN");
+ break;
+ case MD_EXCEPTION_FLAG_LIN_BUS_ADRERR:
+ reason.append("BUS_ADRERR");
+ break;
+ case MD_EXCEPTION_FLAG_LIN_BUS_OBJERR:
+ reason.append("BUS_OBJERR");
+@@ -1462,18 +1468,24 @@ string MinidumpProcessor::GetCrashReason
+ break;
+ case MD_EXCEPTION_CODE_LIN_SIGKILL:
+ reason = "SIGKILL";
+ break;
+ case MD_EXCEPTION_CODE_LIN_SIGUSR1:
+ reason = "SIGUSR1";
+ break;
+ case MD_EXCEPTION_CODE_LIN_SIGSEGV:
+- reason = "SIGSEGV /";
++ reason = "SIGSEGV / ";
+ switch (exception_flags) {
++ case MD_EXCEPTION_FLAG_LIN_SI_USER:
++ reason.append("SI_USER");
++ break;
++ case MD_EXCEPTION_FLAG_LIN_SI_KERNEL:
++ reason.append("SI_KERNEL");
++ break;
+ case MD_EXCEPTION_FLAG_LIN_SEGV_MAPERR:
+ reason.append("SEGV_MAPERR");
+ break;
+ case MD_EXCEPTION_FLAG_LIN_SEGV_ACCERR:
+ reason.append("SEGV_ACCERR");
+ break;
+ case MD_EXCEPTION_FLAG_LIN_SEGV_BNDERR:
+ reason.append("SEGV_BNDERR");
diff --git a/toolkit/crashreporter/breakpad-patches/24-macos-exc-resource.patch b/toolkit/crashreporter/breakpad-patches/24-macos-exc-resource.patch
new file mode 100644
index 0000000000..29cf116048
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-patches/24-macos-exc-resource.patch
@@ -0,0 +1,155 @@
+diff --git a/src/google_breakpad/common/minidump_exception_mac.h b/src/google_breakpad/common/minidump_exception_mac.h
+--- a/src/google_breakpad/common/minidump_exception_mac.h
++++ b/src/google_breakpad/common/minidump_exception_mac.h
+@@ -62,16 +62,18 @@ typedef enum {
+ MD_EXCEPTION_MAC_BREAKPOINT = 6, /* code is CPU-specific */
+ /* EXC_BREAKPOINT */
+ MD_EXCEPTION_MAC_SYSCALL = 7,
+ /* EXC_SYSCALL */
+ MD_EXCEPTION_MAC_MACH_SYSCALL = 8,
+ /* EXC_MACH_SYSCALL */
+ MD_EXCEPTION_MAC_RPC_ALERT = 9,
+ /* EXC_RPC_ALERT */
++ MD_EXCEPTION_MAC_RESOURCE = 11,
++ /* EXC_RESOURCE */
+ MD_EXCEPTION_MAC_SIMULATED = 0x43507378
+ /* Fake exception code used by Crashpad's SimulateCrash ('CPsx'). */
+ } MDExceptionMac;
+
+ /* For (MDException).exception_flags. Breakpad minidump extension for Mac OS X
+ * support. Based on Darwin/Mac OS X' mach/ppc/exception.h and
+ * mach/i386/exception.h. This is what Mac OS X calls a "code". */
+ typedef enum {
+@@ -201,9 +203,42 @@ typedef enum {
+ /* EXC_I386_PGFLT = 14: should not occur in user space */
+ /* EXC_I386_EXTERRFLT = 16: mapped to EXC_ARITHMETIC/EXC_I386_EXTERR */
+ MD_EXCEPTION_CODE_MAC_X86_ALIGNMENT_FAULT = 17
+ /* EXC_ALIGNFLT (for vector operations) */
+ /* EXC_I386_ENOEXTFLT = 32: should be handled by the kernel */
+ /* EXC_I386_ENDPERR = 33: should not occur */
+ } MDExceptionCodeMac;
+
++// The following definitions were taken from Darwin/XNU kernel sources.
++// See https://github.com/apple/darwin-xnu/blob/main/osfmk/kern/exc_resource.h
++
++typedef enum MDMacExcResourceType {
++ MD_MAC_EXC_RESOURCE_TYPE_CPU = 1,
++ MD_MAC_EXC_RESOURCE_TYPE_WAKEUPS = 2,
++ MD_MAC_EXC_RESOURCE_TYPE_MEMORY = 3,
++ MD_MAC_EXC_RESOURCE_TYPE_IO = 4,
++ MD_MAC_EXC_RESOURCE_TYPE_THREADS = 5
++} MDMacExcResourceType;
++
++typedef enum MDMacExcResourceFlavorCpu {
++ MD_MAC_EXC_RESOURCE_FLAVOR_CPU_MONITOR = 1,
++ MD_MAC_EXC_RESOURCE_FLAVOR_CPU_MONITOR_FATAL = 2
++} MDMacExcResourceFlavorCpu;
++
++typedef enum MDMacExcResourceFlavorWakeup {
++ MD_MAC_EXC_RESOURCE_FLAVOR_WAKEUPS_MONITOR = 1,
++} MDMacExcResourceFlavorWakeup;
++
++typedef enum MDMacExcResourceFlavorMemory {
++ MD_MAC_EXC_RESOURCE_FLAVOR_HIGH_WATERMARK = 1,
++} MDMacExcResourceFlavorMemory;
++
++typedef enum MDMacExcResourceIOFlavor {
++ MD_MAC_EXC_RESOURCE_FLAVOR_IO_PHYSICAL_WRITES = 1,
++ MD_MAC_EXC_RESOURCE_FLAVOR_IO_LOGICAL_WRITES = 2,
++} MDMacExcResourceIOFlavor;
++
++typedef enum MDMacExcResourceThreadsFlavor {
++ MD_MAC_EXC_RESOURCE_FLAVOR_THREADS_HIGH_WATERMARK = 1,
++} MDMacExcResourceThreadsFlavor;
++
+ #endif /* GOOGLE_BREAKPAD_COMMON_MINIDUMP_EXCEPTION_MAC_OSX_H__ */
+diff --git a/src/processor/minidump_processor.cc b/src/processor/minidump_processor.cc
+--- a/src/processor/minidump_processor.cc
++++ b/src/processor/minidump_processor.cc
+@@ -1143,16 +1143,86 @@ string MinidumpProcessor::GetCrashReason
+ case MD_EXCEPTION_MAC_MACH_SYSCALL:
+ reason = "EXC_MACH_SYSCALL / ";
+ reason.append(flags_string);
+ break;
+ case MD_EXCEPTION_MAC_RPC_ALERT:
+ reason = "EXC_RPC_ALERT / ";
+ reason.append(flags_string);
+ break;
++ case MD_EXCEPTION_MAC_RESOURCE:
++ reason = "EXC_RESOURCE / ";
++ {
++ uint32_t type = (exception_flags >> 29) & 0x7ULL;
++ uint32_t flavor = (exception_flags >> 26) & 0x7ULL;
++ char flavor_string[6] = {};
++ switch (type) {
++ case MD_MAC_EXC_RESOURCE_TYPE_CPU:
++ reason.append("RESOURCE_TYPE_CPU / ");
++ switch (flavor) {
++ case MD_MAC_EXC_RESOURCE_FLAVOR_CPU_MONITOR:
++ reason.append("FLAVOR_CPU_MONITOR");
++ break;
++ case MD_MAC_EXC_RESOURCE_FLAVOR_CPU_MONITOR_FATAL:
++ reason.append("FLAVOR_CPU_MONITOR_FATAL");
++ break;
++ default:
++ snprintf(flavor_string, sizeof(flavor_string), "%#3x", flavor);
++ reason.append(flavor_string);
++ break;
++ }
++ break;
++ case MD_MAC_EXC_RESOURCE_TYPE_WAKEUPS:
++ reason.append("RESOURCE_TYPE_WAKEUPS / ");
++ if (flavor == MD_MAC_EXC_RESOURCE_FLAVOR_WAKEUPS_MONITOR) {
++ reason.append("FLAVOR_WAKEUPS_MONITOR");
++ } else {
++ snprintf(flavor_string, sizeof(flavor_string), "%#3x", flavor);
++ reason.append(flavor_string);
++ }
++ break;
++ case MD_MAC_EXC_RESOURCE_TYPE_MEMORY:
++ reason.append("RESOURCE_TYPE_MEMORY / ");
++ if (flavor == MD_MAC_EXC_RESOURCE_FLAVOR_HIGH_WATERMARK) {
++ reason.append("FLAVOR_HIGH_WATERMARK");
++ } else {
++ snprintf(flavor_string, sizeof(flavor_string), "%#3x", flavor);
++ reason.append(flavor_string);
++ }
++ break;
++ case MD_MAC_EXC_RESOURCE_TYPE_IO:
++ reason.append("EXC_RESOURCE_TYPE_IO / ");
++ switch (flavor) {
++ case MD_MAC_EXC_RESOURCE_FLAVOR_IO_PHYSICAL_WRITES:
++ reason.append("FLAVOR_IO_PHYSICAL_WRITES");
++ break;
++ case MD_MAC_EXC_RESOURCE_FLAVOR_IO_LOGICAL_WRITES:
++ reason.append("FLAVOR_IO_LOGICAL_WRITES");
++ break;
++ default:
++ snprintf(flavor_string, sizeof(flavor_string), "%#3x", flavor);
++ reason.append(flavor_string);
++ break;
++ }
++ break;
++ case MD_MAC_EXC_RESOURCE_TYPE_THREADS:
++ reason.append("EXC_RESOURCE_TYPE_THREADS / ");
++ if (flavor == MD_MAC_EXC_RESOURCE_FLAVOR_THREADS_HIGH_WATERMARK) {
++ reason.append("FLAVOR_THREADS_HIGH_WATERMARK");
++ } else {
++ snprintf(flavor_string, sizeof(flavor_string), "%#3x", flavor);
++ reason.append(flavor_string);
++ }
++ break;
++ default:
++ reason.append(flags_string);
++ break;
++ }
++ }
++ break;
+ case MD_EXCEPTION_MAC_SIMULATED:
+ reason = "Simulated Exception";
+ break;
+ }
+ break;
+ }
+
+ case MD_OS_WIN32_NT:
diff --git a/toolkit/crashreporter/breakpad-patches/25-macos-exc-guard.patch b/toolkit/crashreporter/breakpad-patches/25-macos-exc-guard.patch
new file mode 100644
index 0000000000..512c8d8ebd
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-patches/25-macos-exc-guard.patch
@@ -0,0 +1,349 @@
+diff --git a/src/google_breakpad/common/minidump_exception_mac.h b/src/google_breakpad/common/minidump_exception_mac.h
+--- a/src/google_breakpad/common/minidump_exception_mac.h
++++ b/src/google_breakpad/common/minidump_exception_mac.h
+@@ -64,16 +64,18 @@ typedef enum {
+ MD_EXCEPTION_MAC_SYSCALL = 7,
+ /* EXC_SYSCALL */
+ MD_EXCEPTION_MAC_MACH_SYSCALL = 8,
+ /* EXC_MACH_SYSCALL */
+ MD_EXCEPTION_MAC_RPC_ALERT = 9,
+ /* EXC_RPC_ALERT */
+ MD_EXCEPTION_MAC_RESOURCE = 11,
+ /* EXC_RESOURCE */
++ MD_EXCEPTION_MAC_GUARD = 12,
++ /* EXC_GUARD */
+ MD_EXCEPTION_MAC_SIMULATED = 0x43507378
+ /* Fake exception code used by Crashpad's SimulateCrash ('CPsx'). */
+ } MDExceptionMac;
+
+ /* For (MDException).exception_flags. Breakpad minidump extension for Mac OS X
+ * support. Based on Darwin/Mac OS X' mach/ppc/exception.h and
+ * mach/i386/exception.h. This is what Mac OS X calls a "code". */
+ typedef enum {
+@@ -236,9 +238,77 @@ typedef enum MDMacExcResourceIOFlavor {
+ MD_MAC_EXC_RESOURCE_FLAVOR_IO_PHYSICAL_WRITES = 1,
+ MD_MAC_EXC_RESOURCE_FLAVOR_IO_LOGICAL_WRITES = 2,
+ } MDMacExcResourceIOFlavor;
+
+ typedef enum MDMacExcResourceThreadsFlavor {
+ MD_MAC_EXC_RESOURCE_FLAVOR_THREADS_HIGH_WATERMARK = 1,
+ } MDMacExcResourceThreadsFlavor;
+
++// See https://github.com/apple/darwin-xnu/blob/main/osfmk/kern/exc_guard.h
++
++typedef enum MDMacExcGuardType {
++ MD_MAC_EXC_GUARD_TYPE_NONE = 0x0,
++ MD_MAC_EXC_GUARD_TYPE_MACH_PORT = 0x1,
++ MD_MAC_EXC_GUARD_TYPE_FD = 0x2,
++ MD_MAC_EXC_GUARD_TYPE_USER = 0x3,
++ MD_MAC_EXC_GUARD_TYPE_VN = 0x4,
++ MD_MAC_EXC_GUARD_TYPE_VIRT_MEMORY = 0x5
++} MDMacExcGuardType;
++
++// See https://github.com/apple/darwin-xnu/osfmk/mach/port.h
++
++typedef enum MDMacExcGuardMachPortFlavor {
++ MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_DESTROY = 1u << 0,
++ MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_MOD_REFS = 1u << 1,
++ MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_SET_CONTEXT = 1u << 2,
++ MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_UNGUARDED = 1u << 3,
++ MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_INCORRECT_GUARD = 1u << 4,
++ MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_IMMOVABLE = 1u << 5,
++ MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_STRICT_REPLY = 1u << 6,
++ MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_MSG_FILTERED = 1u << 7,
++ MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_INVALID_RIGHT = 1u << 8,
++ MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_INVALID_NAME = 1u << 9,
++ MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_INVALID_VALUE = 1u << 10,
++ MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_INVALID_ARGUMENT = 1u << 11,
++ MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_RIGHT_EXISTS = 1u << 12,
++ MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_KERN_NO_SPACE = 1u << 13,
++ MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_KERN_FAILURE = 1u << 14,
++ MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_KERN_RESOURCE = 1u << 15,
++ MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_SEND_INVALID_REPLY = 1u << 16,
++ MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_SEND_INVALID_VOUCHER = 1u << 17,
++ MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_SEND_INVALID_RIGHT = 1u << 18,
++ MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_RCV_INVALID_NAME = 1u << 19,
++ MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_RCV_GUARDED_DESC = 1u << 20,
++ MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_MOD_REFS_NON_FATAL = 1u << 21,
++ MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_IMMOVABLE_NON_FATAL = 1u << 22,
++} MDMacExcGuardMachPortFlavor;
++
++// See https://github.com/apple/darwin-xnu/blob/main/bsd/sys/guarded.h
++
++typedef enum MDMacExcGuardFDFlavor {
++ MD_MAC_EXC_GUARD_FD_FLAVOR_GUARD_EXC_CLOSE = 1u << 0,
++ MD_MAC_EXC_GUARD_FD_FLAVOR_GUARD_EXC_DUP = 1u << 1,
++ MD_MAC_EXC_GUARD_FD_FLAVOR_GUARD_EXC_NOCLOEXEC = 1u << 2,
++ MD_MAC_EXC_GUARD_FD_FLAVOR_GUARD_EXC_SOCKET_IPC = 1u << 3,
++ MD_MAC_EXC_GUARD_FD_FLAVOR_GUARD_EXC_FILEPORT = 1u << 4,
++ MD_MAC_EXC_GUARD_FD_FLAVOR_GUARD_EXC_MISMATCH = 1u << 5,
++ MD_MAC_EXC_GUARD_FD_FLAVOR_GUARD_EXC_WRITE = 1u << 6
++} MDMacExcGuardFDFlavor;
++
++
++typedef enum MDMacExcGuardVNFlavor {
++ MD_MAC_EXC_GUARD_FD_FLAVOR_GUARD_EXC_RENAME_TO = 1u << 0,
++ MD_MAC_EXC_GUARD_FD_FLAVOR_GUARD_EXC_RENAME_FROM = 1u << 1,
++ MD_MAC_EXC_GUARD_FD_FLAVOR_GUARD_EXC_UNLINK = 1u << 2,
++ MD_MAC_EXC_GUARD_FD_FLAVOR_GUARD_EXC_WRITE_OTHER = 1u << 3,
++ MD_MAC_EXC_GUARD_FD_FLAVOR_GUARD_EXC_TRUNC_OTHER = 1u << 4,
++ MD_MAC_EXC_GUARD_FD_FLAVOR_GUARD_EXC_LINK = 1u << 5,
++ MD_MAC_EXC_GUARD_FD_FLAVOR_GUARD_EXC_EXCHDATA = 1u << 6,
++} MDMacExcGuardVNFlavor;
++
++// See https://github.com/apple/darwin-xnu/osfmk/mach/vm_statistics.h
++
++typedef enum MDMacExcGuardVirtMemoryFlavor {
++ MD_MAC_EXC_GUARD_VIRT_MEMORY_FLAVOR_GUARD_EXC_DEALLOC_GAP = 1u << 0
++} MDMacExcGuardVirtMemoryFlavor;
++
+ #endif /* GOOGLE_BREAKPAD_COMMON_MINIDUMP_EXCEPTION_MAC_OSX_H__ */
+diff --git a/src/processor/minidump_processor.cc b/src/processor/minidump_processor.cc
+--- a/src/processor/minidump_processor.cc
++++ b/src/processor/minidump_processor.cc
+@@ -1213,16 +1213,245 @@ string MinidumpProcessor::GetCrashReason
+ }
+ break;
+ default:
+ reason.append(flags_string);
+ break;
+ }
+ }
+ break;
++ case MD_EXCEPTION_MAC_GUARD:
++ reason = "EXC_GUARD / ";
++ {
++ uint32_t type = (exception_flags >> 29) & 0x7ULL;
++ uint32_t flavor = exception_flags & 0x1FFFFFFFULL;
++ switch (type) {
++ case MD_MAC_EXC_GUARD_TYPE_NONE:
++ reason.append("GUARD_TYPE_NONE");
++ break;
++ case MD_MAC_EXC_GUARD_TYPE_MACH_PORT:
++ reason.append("GUARD_TYPE_MACH_PORT");
++
++ if (flavor) {
++ std::vector<std::string> flavors;
++
++ if (flavor & MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_DESTROY) {
++ flavors.push_back("GUARD_EXC_DESTROY");
++ }
++
++ if (flavor & MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_MOD_REFS) {
++ flavors.push_back("GUARD_EXC_MOD_REFS");
++ }
++
++ if (flavor & MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_SET_CONTEXT) {
++ flavors.push_back("GUARD_EXC_SET_CONTEXT");
++ }
++
++ if (flavor & MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_SET_CONTEXT) {
++ flavors.push_back("GUARD_EXC_SET_CONTEXT");
++ }
++
++ if (flavor & MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_UNGUARDED) {
++ flavors.push_back("GUARD_EXC_UNGUARDED");
++ }
++
++ if (flavor & MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_INCORRECT_GUARD) {
++ flavors.push_back("GUARD_EXC_INCORRECT_GUARD");
++ }
++
++ if (flavor & MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_IMMOVABLE) {
++ flavors.push_back("GUARD_EXC_IMMOVABLE");
++ }
++
++ if (flavor & MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_STRICT_REPLY) {
++ flavors.push_back("GUARD_EXC_STRICT_REPLY");
++ }
++
++ if (flavor & MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_MSG_FILTERED) {
++ flavors.push_back("GUARD_EXC_MSG_FILTERED");
++ }
++
++ if (flavor & MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_INVALID_RIGHT) {
++ flavors.push_back("GUARD_EXC_INVALID_RIGHT");
++ }
++
++ if (flavor & MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_INVALID_NAME) {
++ flavors.push_back("GUARD_EXC_INVALID_NAME");
++ }
++
++ if (flavor & MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_INVALID_VALUE) {
++ flavors.push_back("GUARD_EXC_INVALID_VALUE");
++ }
++
++ if (flavor & MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_INVALID_ARGUMENT) {
++ flavors.push_back("GUARD_EXC_INVALID_ARGUMENT");
++ }
++
++ if (flavor & MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_RIGHT_EXISTS) {
++ flavors.push_back("GUARD_EXC_RIGHT_EXISTS");
++ }
++
++ if (flavor & MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_KERN_NO_SPACE) {
++ flavors.push_back("GUARD_EXC_KERN_NO_SPACE");
++ }
++
++ if (flavor & MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_KERN_FAILURE) {
++ flavors.push_back("GUARD_EXC_KERN_FAILURE");
++ }
++
++ if (flavor & MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_KERN_RESOURCE) {
++ flavors.push_back("GUARD_EXC_KERN_RESOURCE");
++ }
++
++ if (flavor & MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_SEND_INVALID_REPLY) {
++ flavors.push_back("GUARD_EXC_SEND_INVALID_REPLY");
++ }
++
++ if (flavor & MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_SEND_INVALID_VOUCHER) {
++ flavors.push_back("GUARD_EXC_SEND_INVALID_VOUCHER");
++ }
++
++ if (flavor & MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_SEND_INVALID_RIGHT) {
++ flavors.push_back("GUARD_EXC_SEND_INVALID_RIGHT");
++ }
++
++ if (flavor & MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_RCV_INVALID_NAME) {
++ flavors.push_back("GUARD_EXC_RCV_INVALID_NAME");
++ }
++
++ if (flavor & MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_RCV_GUARDED_DESC) {
++ flavors.push_back("GUARD_EXC_RCV_GUARDED_DESC");
++ }
++
++ if (flavor & MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_MOD_REFS_NON_FATAL) {
++ flavors.push_back("GUARD_EXC_MOD_REFS_NON_FATAL");
++ }
++
++ if (flavor & MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_IMMOVABLE_NON_FATAL) {
++ flavors.push_back("GUARD_EXC_IMMOVABLE_NON_FATAL");
++ }
++
++ reason.append(" / ");
++ for (size_t i = 0; i < flavors.size(); i++) {
++ if (i > 0) {
++ reason.append(" | ");
++ }
++
++ reason.append(flavors[i]);
++ }
++ }
++
++ break;
++ case MD_MAC_EXC_GUARD_TYPE_FD:
++ reason.append("GUARD_TYPE_FD");
++
++ if (flavor) {
++ std::vector<std::string> flavors;
++
++ if (flavor & MD_MAC_EXC_GUARD_FD_FLAVOR_GUARD_EXC_CLOSE) {
++ flavors.push_back("GUARD_EXC_CLOSE");
++ }
++
++ if (flavor & MD_MAC_EXC_GUARD_FD_FLAVOR_GUARD_EXC_DUP) {
++ flavors.push_back("GUARD_EXC_DUP");
++ }
++
++ if (flavor & MD_MAC_EXC_GUARD_FD_FLAVOR_GUARD_EXC_NOCLOEXEC) {
++ flavors.push_back("GUARD_EXC_NOCLOEXEC");
++ }
++
++ if (flavor & MD_MAC_EXC_GUARD_FD_FLAVOR_GUARD_EXC_SOCKET_IPC) {
++ flavors.push_back("GUARD_EXC_SOCKET_IPC");
++ }
++
++ if (flavor & MD_MAC_EXC_GUARD_FD_FLAVOR_GUARD_EXC_FILEPORT) {
++ flavors.push_back("GUARD_EXC_FILEPORT");
++ }
++
++ if (flavor & MD_MAC_EXC_GUARD_FD_FLAVOR_GUARD_EXC_MISMATCH) {
++ flavors.push_back("GUARD_EXC_MISMATCH");
++ }
++
++ if (flavor & MD_MAC_EXC_GUARD_FD_FLAVOR_GUARD_EXC_WRITE) {
++ flavors.push_back("GUARD_EXC_WRITE");
++ }
++
++ reason.append(" / ");
++ for (size_t i = 0; i < flavors.size(); i++) {
++ if (i > 0) {
++ reason.append(" | ");
++ }
++
++ reason.append(flavors[i]);
++ }
++ }
++
++ break;
++ case MD_MAC_EXC_GUARD_TYPE_USER:
++ reason.append("GUARD_TYPE_USER");
++ break;
++ case MD_MAC_EXC_GUARD_TYPE_VN:
++ reason.append("GUARD_TYPE_VN");
++
++ if (flavor) {
++ std::vector<std::string> flavors;
++
++ if (flavor & MD_MAC_EXC_GUARD_FD_FLAVOR_GUARD_EXC_RENAME_TO) {
++ flavors.push_back("GUARD_EXC_RENAME_TO");
++ }
++
++ if (flavor & MD_MAC_EXC_GUARD_FD_FLAVOR_GUARD_EXC_RENAME_FROM) {
++ flavors.push_back("GUARD_EXC_RENAME_FROM");
++ }
++
++ if (flavor & MD_MAC_EXC_GUARD_FD_FLAVOR_GUARD_EXC_UNLINK) {
++ flavors.push_back("GUARD_EXC_UNLINK");
++ }
++
++ if (flavor & MD_MAC_EXC_GUARD_FD_FLAVOR_GUARD_EXC_WRITE_OTHER) {
++ flavors.push_back("GUARD_EXC_WRITE_OTHER");
++ }
++
++ if (flavor & MD_MAC_EXC_GUARD_FD_FLAVOR_GUARD_EXC_TRUNC_OTHER) {
++ flavors.push_back("GUARD_EXC_TRUNC_OTHER");
++ }
++
++ if (flavor & MD_MAC_EXC_GUARD_FD_FLAVOR_GUARD_EXC_LINK) {
++ flavors.push_back("GUARD_EXC_LINK");
++ }
++
++ if (flavor & MD_MAC_EXC_GUARD_FD_FLAVOR_GUARD_EXC_EXCHDATA) {
++ flavors.push_back("GUARD_EXC_EXCHDATA");
++ }
++
++ reason.append(" / ");
++ for (size_t i = 0; i < flavors.size(); i++) {
++ if (i > 0) {
++ reason.append(" | ");
++ }
++
++ reason.append(flavors[i]);
++ }
++ }
++
++ break;
++ case MD_MAC_EXC_GUARD_TYPE_VIRT_MEMORY:
++ reason.append("GUARD_TYPE_VIRT_MEMORY");
++
++ if (flavor & MD_MAC_EXC_GUARD_VIRT_MEMORY_FLAVOR_GUARD_EXC_DEALLOC_GAP) {
++ reason.append(" / GUARD_EXC_DEALLOC_GAP");
++ }
++
++ break;
++ default:
++ reason.append(flags_string);
++ break;
++ }
++ }
++ break;
+ case MD_EXCEPTION_MAC_SIMULATED:
+ reason = "Simulated Exception";
+ break;
+ }
+ break;
+ }
+
+ case MD_OS_WIN32_NT:
diff --git a/toolkit/crashreporter/breakpad-patches/26-print-thread-tid.patch b/toolkit/crashreporter/breakpad-patches/26-print-thread-tid.patch
new file mode 100644
index 0000000000..f81ca774bd
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-patches/26-print-thread-tid.patch
@@ -0,0 +1,44 @@
+diff --git a/src/processor/stackwalk_common.cc b/src/processor/stackwalk_common.cc
+--- a/src/processor/stackwalk_common.cc
++++ b/src/processor/stackwalk_common.cc
+@@ -879,18 +879,19 @@ void PrintProcessState(const ProcessStat
+ }
+
+ // If the thread that requested the dump is known, print it first.
+ int requesting_thread = process_state.requesting_thread();
+ if (requesting_thread != -1) {
+ const CallStack* requesting_thread_callstack =
+ process_state.threads()->at(requesting_thread);
+ printf("\n"
+- "Thread %d (%s)",
++ "Thread %d tid %u (%s)",
+ requesting_thread,
++ requesting_thread_callstack->tid(),
+ process_state.crashed() ? "crashed" :
+ "requested dump, did not crash");
+ if (!requesting_thread_callstack->name().empty()) {
+ printf(" - %s", requesting_thread_callstack->name().c_str());
+ }
+ PrintStack(requesting_thread_callstack, cpu,
+ output_stack_contents,
+ process_state.thread_memory_regions()->at(requesting_thread),
+@@ -899,17 +900,17 @@ void PrintProcessState(const ProcessStat
+
+ // Print all of the threads in the dump.
+ int thread_count = process_state.threads()->size();
+ for (int thread_index = 0; thread_index < thread_count; ++thread_index) {
+ if (thread_index != requesting_thread) {
+ // Don't print the crash thread again, it was already printed.
+ const CallStack* callstack = process_state.threads()->at(thread_index);
+ printf("\n"
+- "Thread %d", thread_index);
++ "Thread %d tid %u", thread_index, callstack->tid());
+ if (!callstack->name().empty()) {
+ printf(" - %s", callstack->name().c_str());
+ }
+ printf("\n");
+ PrintStack(callstack, cpu,
+ output_stack_contents,
+ process_state.thread_memory_regions()->at(thread_index),
+ process_state.modules(), resolver);
+
diff --git a/toolkit/crashreporter/breakpad-patches/27-fix-unified-builds-bug-1733547.patch b/toolkit/crashreporter/breakpad-patches/27-fix-unified-builds-bug-1733547.patch
new file mode 100644
index 0000000000..5afc50316e
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-patches/27-fix-unified-builds-bug-1733547.patch
@@ -0,0 +1,22 @@
+diff --git a/src/processor/stack_frame_symbolizer.cc b/src/processor/stack_frame_symbolizer.cc
+--- a/src/processor/stack_frame_symbolizer.cc
++++ b/src/processor/stack_frame_symbolizer.cc
+@@ -124,17 +124,16 @@ StackFrameSymbolizer::SymbolizerResult S
+
+ case SymbolSupplier::INTERRUPT:
+ return kInterrupt;
+
+ default:
+ BPLOG(ERROR) << "Unknown SymbolResult enum: " << symbol_result;
+ return kError;
+ }
+- return kError;
+ }
+
+ WindowsFrameInfo* StackFrameSymbolizer::FindWindowsFrameInfo(
+ const StackFrame* frame) {
+ return resolver_ ? resolver_->FindWindowsFrameInfo(frame) : NULL;
+ }
+
+ CFIFrameInfo* StackFrameSymbolizer::FindCFIFrameInfo(
+
diff --git a/toolkit/crashreporter/breakpad-patches/28-no-garbage-in-code-ids.patch b/toolkit/crashreporter/breakpad-patches/28-no-garbage-in-code-ids.patch
new file mode 100644
index 0000000000..64f791d01e
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-patches/28-no-garbage-in-code-ids.patch
@@ -0,0 +1,34 @@
+diff --git a/src/common/linux/file_id.cc b/src/common/linux/file_id.cc
+--- a/src/common/linux/file_id.cc
++++ b/src/common/linux/file_id.cc
+@@ -115,28 +115,27 @@ static bool FindElfBuildIDNote(const voi
+
+ 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) ||
+ text_size == 0) {
+ return false;
+ }
+
+ // Only provide |kMDGUIDSize| bytes to keep identifiers produced by this
+ // function backwards-compatible.
++ identifier.resize(kMDGUIDSize);
+ 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;
+ }
+
diff --git a/toolkit/crashreporter/breakpad-patches/29-cpu-context-packing.patch b/toolkit/crashreporter/breakpad-patches/29-cpu-context-packing.patch
new file mode 100644
index 0000000000..f6ef0c4d29
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-patches/29-cpu-context-packing.patch
@@ -0,0 +1,118 @@
+diff --git a/src/google_breakpad/common/minidump_cpu_arm64.h b/src/google_breakpad/common/minidump_cpu_arm64.h
+--- a/src/google_breakpad/common/minidump_cpu_arm64.h
++++ b/src/google_breakpad/common/minidump_cpu_arm64.h
+@@ -86,16 +86,20 @@ typedef struct {
+ #define MD_CONTEXT_ARM64_INTEGER (MD_CONTEXT_ARM64 | 0x00000002)
+ #define MD_CONTEXT_ARM64_FLOATING_POINT (MD_CONTEXT_ARM64 | 0x00000004)
+ #define MD_CONTEXT_ARM64_DEBUG (MD_CONTEXT_ARM64 | 0x00000008)
+ #define MD_CONTEXT_ARM64_FULL (MD_CONTEXT_ARM64_CONTROL | \
+ MD_CONTEXT_ARM64_INTEGER | \
+ MD_CONTEXT_ARM64_FLOATING_POINT)
+ #define MD_CONTEXT_ARM64_ALL (MD_CONTEXT_ARM64_FULL | MD_CONTEXT_ARM64_DEBUG)
+
++/* Use the same 32-bit alignment when accessing these structures from 64-bit
++ * code as is used natively in 32-bit code. */
++#pragma pack(push, 4)
++
+ typedef struct {
+ /* Determines which fields of this struct are populated */
+ uint32_t context_flags;
+
+ /* CPSR (flags, basically): 32 bits:
+ bit 31 - N (negative)
+ bit 30 - Z (zero)
+ bit 29 - C (carry)
+@@ -125,20 +129,16 @@ typedef struct {
+ typedef struct {
+ uint32_t fpsr; /* FPU status register */
+ uint32_t fpcr; /* FPU control register */
+
+ /* 32 128-bit floating point registers, d0 .. d31. */
+ uint128_struct regs[MD_FLOATINGSAVEAREA_ARM64_FPR_COUNT];
+ } MDFloatingSaveAreaARM64_Old;
+
+-/* Use the same 32-bit alignment when accessing this structure from 64-bit code
+- * as is used natively in 32-bit code. */
+-#pragma pack(push, 4)
+-
+ typedef struct {
+ /* The next field determines the layout of the structure, and which parts
+ * of it are populated
+ */
+ uint64_t context_flags;
+
+ /* 33 64-bit integer registers, x0 .. x31 + the PC
+ * Note the following fixed uses:
+diff --git a/src/google_breakpad/common/minidump_cpu_ppc.h b/src/google_breakpad/common/minidump_cpu_ppc.h
+--- a/src/google_breakpad/common/minidump_cpu_ppc.h
++++ b/src/google_breakpad/common/minidump_cpu_ppc.h
+@@ -73,16 +73,20 @@
+ /*
+ * Breakpad minidump extension for PowerPC support. Based on Darwin/Mac OS X'
+ * mach/ppc/_types.h
+ */
+
+ #ifndef GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_PPC_H__
+ #define GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_PPC_H__
+
++/* Use the same 32-bit alignment when accessing these structures from 64-bit
++ * code as is used natively in 32-bit code. */
++#pragma pack(push, 4)
++
+ #define MD_FLOATINGSAVEAREA_PPC_FPR_COUNT 32
+
+ typedef struct {
+ /* fpregs is a double[32] in mach/ppc/_types.h, but a uint64_t is used
+ * here for precise sizing. */
+ uint64_t fpregs[MD_FLOATINGSAVEAREA_PPC_FPR_COUNT];
+ uint32_t fpscr_pad;
+ uint32_t fpscr; /* Status/control */
+@@ -99,25 +103,16 @@ typedef struct {
+ uint32_t save_pad5[4];
+ uint32_t save_vrvalid; /* Indicates which vector registers are saved */
+ uint32_t save_pad6[7];
+ } MDVectorSaveAreaPPC; /* ppc_vector_state */
+
+
+ #define MD_CONTEXT_PPC_GPR_COUNT 32
+
+-/* Use the same 32-bit alignment when accessing this structure from 64-bit code
+- * as is used natively in 32-bit code. #pragma pack is a MSVC extension
+- * supported by gcc. */
+-#if defined(__SUNPRO_C) || defined(__SUNPRO_CC)
+-#pragma pack(4)
+-#else
+-#pragma pack(push, 4)
+-#endif
+-
+ typedef struct {
+ /* context_flags is not present in ppc_thread_state, but it aids
+ * identification of MDRawContextPPC among other raw context types,
+ * and it guarantees alignment when we get to float_save. */
+ uint32_t context_flags;
+
+ uint32_t srr0; /* Machine status save/restore: stores pc
+ * (instruction) */
+@@ -140,21 +135,17 @@ typedef struct {
+ MDVectorSaveAreaPPC vector_save;
+ } MDRawContextPPC; /* Based on ppc_thread_state */
+
+ /* Indices into gpr for registers with a dedicated or conventional purpose. */
+ enum MDPPCRegisterNumbers {
+ MD_CONTEXT_PPC_REG_SP = 1
+ };
+
+-#if defined(__SUNPRO_C) || defined(__SUNPRO_CC)
+-#pragma pack(0)
+-#else
+ #pragma pack(pop)
+-#endif
+
+ /* For (MDRawContextPPC).context_flags. These values indicate the type of
+ * context stored in the structure. MD_CONTEXT_PPC is Breakpad-defined. Its
+ * value was chosen to avoid likely conflicts with MD_CONTEXT_* for other
+ * CPUs. */
+ #define MD_CONTEXT_PPC 0x20000000
+ #define MD_CONTEXT_PPC_BASE (MD_CONTEXT_PPC | 0x00000001)
+ #define MD_CONTEXT_PPC_FLOATING_POINT (MD_CONTEXT_PPC | 0x00000008)
+
diff --git a/toolkit/crashreporter/breakpad-patches/30-sign-compare.patch b/toolkit/crashreporter/breakpad-patches/30-sign-compare.patch
new file mode 100644
index 0000000000..5fbf075810
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-patches/30-sign-compare.patch
@@ -0,0 +1,11 @@
+--- a/src/client/windows/crash_generation/crash_generation_server.cc
++++ b/src/client/windows/crash_generation/crash_generation_server.cc
+@@ -954,7 +954,7 @@ bool CrashGenerationServer::GenerateDump(const ClientInfo& client,
+ }
+
+ // Allocate AppMemory instances for exception context.
+- for (int i = 0; i < kExceptionAppMemoryRegions; i++) {
++ for (size_t i = 0; i < kExceptionAppMemoryRegions; i++) {
+ AppMemory app_memory;
+ app_memory.ptr = reinterpret_cast<ULONG64>(nullptr);
+ app_memory.length = 0;
diff --git a/toolkit/crashreporter/breakpad-patches/README b/toolkit/crashreporter/breakpad-patches/README
new file mode 100644
index 0000000000..b3f23b255f
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-patches/README
@@ -0,0 +1,4 @@
+Do not land local patches to Breakpad without the approval of
+Ted Mielczarek <ted@mielczarek.org>
+
+All local patches must be in the process of being upstreamed. \ No newline at end of file
diff --git a/toolkit/crashreporter/breakpad-windows-libxul/moz.build b/toolkit/crashreporter/breakpad-windows-libxul/moz.build
new file mode 100644
index 0000000000..ab517eb5a7
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-windows-libxul/moz.build
@@ -0,0 +1,29 @@
+# -*- 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/.
+
+Library("google_breakpad_libxul_s")
+
+FINAL_LIBRARY = "xul"
+
+for var in ("UNICODE", "UNICODE_", "BREAKPAD_NO_TERMINATE_THREAD"):
+ DEFINES[var] = True
+
+LOCAL_INCLUDES += [
+ "/toolkit/crashreporter/breakpad-client",
+ "/toolkit/crashreporter/google-breakpad/src",
+]
+
+include("/toolkit/crashreporter/google-breakpad/src/common/windows/objs.mozbuild")
+include("/toolkit/crashreporter/breakpad-client/windows/handler/objs.mozbuild")
+include("/toolkit/crashreporter/breakpad-client/windows/crash_generation/objs.mozbuild")
+include("/toolkit/crashreporter/breakpad-client/windows/common/objs.mozbuild")
+
+SOURCES += objs_common
+SOURCES += objs_crash_generation
+SOURCES += objs_handler
+SOURCES += objs_client_common
+
+DisableStlWrapping()
diff --git a/toolkit/crashreporter/breakpad-windows-standalone/moz.build b/toolkit/crashreporter/breakpad-windows-standalone/moz.build
new file mode 100644
index 0000000000..8d6033e076
--- /dev/null
+++ b/toolkit/crashreporter/breakpad-windows-standalone/moz.build
@@ -0,0 +1,29 @@
+# -*- 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/.
+
+FINAL_LIBRARY = "breakpadinjector"
+
+for var in ("UNICODE", "UNICODE_", "BREAKPAD_NO_TERMINATE_THREAD"):
+ DEFINES[var] = True
+
+LOCAL_INCLUDES += [
+ "/toolkit/crashreporter/breakpad-client",
+ "/toolkit/crashreporter/google-breakpad/src",
+]
+
+include("/toolkit/crashreporter/google-breakpad/src/common/windows/objs.mozbuild")
+include("/toolkit/crashreporter/breakpad-client/windows/handler/objs.mozbuild")
+include("/toolkit/crashreporter/breakpad-client/windows/crash_generation/objs.mozbuild")
+include("/toolkit/crashreporter/breakpad-client/windows/common/objs.mozbuild")
+
+SOURCES += objs_common
+SOURCES += objs_crash_generation
+SOURCES += objs_handler
+SOURCES += objs_client_common
+
+USE_STATIC_LIBS = True
+
+DisableStlWrapping()
diff --git a/toolkit/crashreporter/client/Makefile.in b/toolkit/crashreporter/client/Makefile.in
new file mode 100644
index 0000000000..a3110090b2
--- /dev/null
+++ b/toolkit/crashreporter/client/Makefile.in
@@ -0,0 +1,19 @@
+# vim:set ts=8 sw=8 sts=8 noet:
+# 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/.
+
+ifeq ($(OS_ARCH),WINNT)
+MOZ_WINCONSOLE = 0
+endif
+
+include $(topsrcdir)/config/rules.mk
+
+ifeq ($(OS_ARCH),Darwin)
+libs::
+ $(NSINSTALL) -D $(DIST)/bin/crashreporter.app
+ rsync -a -C --exclude '*.in' $(srcdir)/macbuild/Contents $(DIST)/bin/crashreporter.app
+ $(call py_action,preprocessor,-Fsubstitution --output-encoding utf-16 -DAPP_NAME='$(MOZ_APP_DISPLAYNAME)' $(srcdir)/macbuild/Contents/Resources/English.lproj/InfoPlist.strings.in -o $(DIST)/bin/crashreporter.app/Contents/Resources/English.lproj/InfoPlist.strings)
+ $(NSINSTALL) -D $(DIST)/bin/crashreporter.app/Contents/MacOS
+ $(NSINSTALL) $(DIST)/bin/crashreporter $(DIST)/bin/crashreporter.app/Contents/MacOS
+endif
diff --git a/toolkit/crashreporter/client/Throbber-small.avi b/toolkit/crashreporter/client/Throbber-small.avi
new file mode 100644
index 0000000000..640ea62c0e
--- /dev/null
+++ b/toolkit/crashreporter/client/Throbber-small.avi
Binary files differ
diff --git a/toolkit/crashreporter/client/Throbber-small.gif b/toolkit/crashreporter/client/Throbber-small.gif
new file mode 100644
index 0000000000..cce32f20f4
--- /dev/null
+++ b/toolkit/crashreporter/client/Throbber-small.gif
Binary files differ
diff --git a/toolkit/crashreporter/client/crashreporter.cpp b/toolkit/crashreporter/client/crashreporter.cpp
new file mode 100644
index 0000000000..4426e6446c
--- /dev/null
+++ b/toolkit/crashreporter/client/crashreporter.cpp
@@ -0,0 +1,833 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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 "crashreporter.h"
+
+#ifdef _MSC_VER
+// Disable exception handler warnings.
+# pragma warning(disable : 4530)
+#endif
+
+#include <fstream>
+#include <iomanip>
+#include <sstream>
+#include <memory>
+#include <ctime>
+#include <cstdlib>
+#include <cstring>
+#include <string>
+#include <utility>
+
+#ifdef XP_LINUX
+# include <dlfcn.h>
+#endif
+
+#include "json/json.h"
+#include "nss.h"
+#include "sechash.h"
+
+using std::ifstream;
+using std::ios;
+using std::istream;
+using std::istringstream;
+using std::ofstream;
+using std::ostream;
+using std::ostringstream;
+using std::string;
+using std::unique_ptr;
+using std::vector;
+
+namespace CrashReporter {
+
+StringTable gStrings;
+Json::Value gData;
+string gSettingsPath;
+string gEventsPath;
+string gPingPath;
+int gArgc;
+char** gArgv;
+bool gAutoSubmit;
+
+enum SubmissionResult { Succeeded, Failed };
+
+static unique_ptr<ofstream> gLogStream(nullptr);
+static string gReporterDumpFile;
+static string gExtraFile;
+static string gMemoryFile;
+
+static const char kExtraDataExtension[] = ".extra";
+static const char kMemoryReportExtension[] = ".memory.json.gz";
+
+void UIError(const string& message) {
+ if (gAutoSubmit) {
+ return;
+ }
+
+ string errorMessage;
+ if (!gStrings[ST_CRASHREPORTERERROR].empty()) {
+ char buf[2048];
+ snprintf(buf, 2048, gStrings[ST_CRASHREPORTERERROR].c_str(),
+ message.c_str());
+ errorMessage = buf;
+ } else {
+ errorMessage = message;
+ }
+
+ UIError_impl(errorMessage);
+}
+
+static string Unescape(const string& str) {
+ string ret;
+ for (string::const_iterator iter = str.begin(); iter != str.end(); iter++) {
+ if (*iter == '\\') {
+ iter++;
+ if (*iter == '\\') {
+ ret.push_back('\\');
+ } else if (*iter == 'n') {
+ ret.push_back('\n');
+ } else if (*iter == 't') {
+ ret.push_back('\t');
+ }
+ } else {
+ ret.push_back(*iter);
+ }
+ }
+
+ return ret;
+}
+
+bool ReadStrings(istream& in, StringTable& strings, bool unescape) {
+ string currentSection;
+ while (!in.eof()) {
+ string line;
+ std::getline(in, line);
+ int sep = line.find('=');
+ if (sep >= 0) {
+ string key, value;
+ key = line.substr(0, sep);
+ value = line.substr(sep + 1);
+ if (unescape) value = Unescape(value);
+ strings[key] = value;
+ }
+ }
+
+ return true;
+}
+
+bool ReadStringsFromFile(const string& path, StringTable& strings,
+ bool unescape) {
+ ifstream* f = UIOpenRead(path, ios::in);
+ bool success = false;
+ if (f->is_open()) {
+ success = ReadStrings(*f, strings, unescape);
+ f->close();
+ }
+
+ delete f;
+ return success;
+}
+
+static bool ReadExtraFile(const string& aExtraDataPath, Json::Value& aExtra) {
+ bool success = false;
+ ifstream* f = UIOpenRead(aExtraDataPath, ios::in);
+ if (f->is_open()) {
+ Json::CharReaderBuilder builder;
+ success = parseFromStream(builder, *f, &aExtra, nullptr);
+ }
+
+ delete f;
+ return success;
+}
+
+static string Basename(const string& file) {
+ string::size_type slashIndex = file.rfind(UI_DIR_SEPARATOR);
+ if (slashIndex != string::npos) {
+ return file.substr(slashIndex + 1);
+ }
+ return file;
+}
+
+static bool ReadEventFile(const string& aPath, string& aEventVersion,
+ string& aTime, string& aUuid, Json::Value& aData) {
+ bool res = false;
+ ifstream* f = UIOpenRead(aPath, ios::binary);
+
+ if (f->is_open()) {
+ std::getline(*f, aEventVersion, '\n');
+ res = f->good();
+ std::getline(*f, aTime, '\n');
+ res &= f->good();
+ std::getline(*f, aUuid, '\n');
+ res &= f->good();
+
+ if (res) {
+ Json::CharReaderBuilder builder;
+ res = parseFromStream(builder, *f, &aData, nullptr);
+ }
+ }
+
+ delete f;
+ return res;
+}
+
+static void OverwriteEventFile(const string& aPath, const string& aEventVersion,
+ const string& aTime, const string& aUuid,
+ const Json::Value& aData) {
+ ofstream* f = UIOpenWrite(aPath, ios::binary | ios::trunc);
+ if (f->is_open()) {
+ f->write(aEventVersion.c_str(), aEventVersion.length()) << '\n';
+ f->write(aTime.c_str(), aTime.length()) << '\n';
+ f->write(aUuid.c_str(), aUuid.length()) << '\n';
+
+ Json::StreamWriterBuilder builder;
+ builder["indentation"] = "";
+ std::unique_ptr<Json::StreamWriter> writer(builder.newStreamWriter());
+ writer->write(aData, f);
+ *f << "\n";
+ }
+
+ delete f;
+}
+
+static void UpdateEventFile(const Json::Value& aExtraData, const string& aHash,
+ const string& aPingUuid) {
+ if (gEventsPath.empty()) {
+ // If there is no path for finding the crash event, skip this step.
+ return;
+ }
+
+ string localId = CrashReporter::GetDumpLocalID();
+ string path = gEventsPath + UI_DIR_SEPARATOR + localId;
+ string eventVersion;
+ string crashTime;
+ string crashUuid;
+ Json::Value eventData;
+
+ if (!ReadEventFile(path, eventVersion, crashTime, crashUuid, eventData)) {
+ return;
+ }
+
+ if (!aHash.empty()) {
+ eventData["MinidumpSha256Hash"] = aHash;
+ }
+
+ if (!aPingUuid.empty()) {
+ eventData["CrashPingUUID"] = aPingUuid;
+ }
+
+ if (aExtraData.isMember("StackTraces")) {
+ eventData["StackTraces"] = aExtraData["StackTraces"];
+ }
+
+ OverwriteEventFile(path, eventVersion, crashTime, crashUuid, eventData);
+}
+
+static void WriteSubmissionEvent(SubmissionResult result,
+ const string& remoteId) {
+ if (gEventsPath.empty()) {
+ // If there is no path for writing the submission event, skip it.
+ return;
+ }
+
+ string localId = CrashReporter::GetDumpLocalID();
+ string fpath = gEventsPath + UI_DIR_SEPARATOR + localId + "-submission";
+ ofstream* f = UIOpenWrite(fpath, ios::binary);
+ time_t tm;
+ time(&tm);
+
+ if (f->is_open()) {
+ *f << "crash.submission.1\n";
+ *f << tm << "\n";
+ *f << localId << "\n";
+ *f << (result == Succeeded ? "true" : "false") << "\n";
+ *f << remoteId;
+
+ f->close();
+ }
+
+ delete f;
+}
+
+void LogMessage(const std::string& message) {
+ if (gLogStream.get()) {
+ char date[64];
+ time_t tm;
+ time(&tm);
+ if (strftime(date, sizeof(date) - 1, "%c", localtime(&tm)) == 0)
+ date[0] = '\0';
+ (*gLogStream) << "[" << date << "] " << message << std::endl;
+ }
+}
+
+static void OpenLogFile() {
+ string logPath = gSettingsPath + UI_DIR_SEPARATOR + "submit.log";
+ gLogStream.reset(UIOpenWrite(logPath, ios::app));
+}
+
+static bool ReadConfig() {
+ string iniPath;
+ if (!UIGetIniPath(iniPath)) {
+ return false;
+ }
+
+ if (!ReadStringsFromFile(iniPath, gStrings, true)) return false;
+
+ // See if we have a string override file, if so process it
+ char* overrideEnv = getenv("MOZ_CRASHREPORTER_STRINGS_OVERRIDE");
+ if (overrideEnv && *overrideEnv && UIFileExists(overrideEnv))
+ ReadStringsFromFile(overrideEnv, gStrings, true);
+
+ return true;
+}
+
+static string GetAdditionalFilename(const string& dumpfile,
+ const char* extension) {
+ string filename(dumpfile);
+ int dot = filename.rfind('.');
+ if (dot < 0) return "";
+
+ filename.replace(dot, filename.length() - dot, extension);
+ return filename;
+}
+
+static bool MoveCrashData(const string& toDir, string& dumpfile,
+ string& extrafile, string& memoryfile) {
+ if (!UIEnsurePathExists(toDir)) {
+ UIError(gStrings[ST_ERROR_CREATEDUMPDIR]);
+ return false;
+ }
+
+ string newDump = toDir + UI_DIR_SEPARATOR + Basename(dumpfile);
+ string newExtra = toDir + UI_DIR_SEPARATOR + Basename(extrafile);
+ string newMemory = toDir + UI_DIR_SEPARATOR + Basename(memoryfile);
+
+ if (!UIMoveFile(dumpfile, newDump)) {
+ UIError(gStrings[ST_ERROR_DUMPFILEMOVE]);
+ return false;
+ }
+
+ if (!UIMoveFile(extrafile, newExtra)) {
+ UIError(gStrings[ST_ERROR_EXTRAFILEMOVE]);
+ return false;
+ }
+
+ if (!memoryfile.empty()) {
+ // Ignore errors from moving the memory file
+ if (!UIMoveFile(memoryfile, newMemory)) {
+ UIDeleteFile(memoryfile);
+ newMemory.erase();
+ }
+ memoryfile = newMemory;
+ }
+
+ dumpfile = newDump;
+ extrafile = newExtra;
+
+ return true;
+}
+
+static bool AddSubmittedReport(const string& serverResponse) {
+ StringTable responseItems;
+ istringstream in(serverResponse);
+ ReadStrings(in, responseItems, false);
+
+ if (responseItems.find("StopSendingReportsFor") != responseItems.end()) {
+ // server wants to tell us to stop sending reports for a certain version
+ string reportPath = gSettingsPath + UI_DIR_SEPARATOR + "EndOfLife" +
+ responseItems["StopSendingReportsFor"];
+
+ ofstream* reportFile = UIOpenWrite(reportPath, ios::trunc);
+ if (reportFile->is_open()) {
+ // don't really care about the contents
+ *reportFile << 1 << "\n";
+ reportFile->close();
+ }
+ delete reportFile;
+ }
+
+ if (responseItems.find("Discarded") != responseItems.end()) {
+ // server discarded this report... save it so the user can resubmit it
+ // manually
+ return false;
+ }
+
+ if (responseItems.find("CrashID") == responseItems.end()) return false;
+
+ string submittedDir = gSettingsPath + UI_DIR_SEPARATOR + "submitted";
+ if (!UIEnsurePathExists(submittedDir)) {
+ return false;
+ }
+
+ string path =
+ submittedDir + UI_DIR_SEPARATOR + responseItems["CrashID"] + ".txt";
+
+ ofstream* file = UIOpenWrite(path, ios::trunc);
+ if (!file->is_open()) {
+ delete file;
+ return false;
+ }
+
+ char buf[1024];
+ snprintf(buf, 1024, gStrings["CrashID"].c_str(),
+ responseItems["CrashID"].c_str());
+ *file << buf << "\n";
+
+ if (responseItems.find("ViewURL") != responseItems.end()) {
+ snprintf(buf, 1024, gStrings["CrashDetailsURL"].c_str(),
+ responseItems["ViewURL"].c_str());
+ *file << buf << "\n";
+ }
+
+ file->close();
+ delete file;
+
+ WriteSubmissionEvent(Succeeded, responseItems["CrashID"]);
+ return true;
+}
+
+void DeleteDump() {
+ const char* noDelete = getenv("MOZ_CRASHREPORTER_NO_DELETE_DUMP");
+ if (!noDelete || *noDelete == '\0') {
+ if (!gReporterDumpFile.empty()) UIDeleteFile(gReporterDumpFile);
+ if (!gExtraFile.empty()) UIDeleteFile(gExtraFile);
+ if (!gMemoryFile.empty()) UIDeleteFile(gMemoryFile);
+ }
+}
+
+void SendCompleted(bool success, const string& serverResponse) {
+ if (success) {
+ if (AddSubmittedReport(serverResponse)) {
+ DeleteDump();
+ } else {
+ string directory = gReporterDumpFile;
+ int slashpos = directory.find_last_of("/\\");
+ if (slashpos < 2) return;
+ directory.resize(slashpos);
+ UIPruneSavedDumps(directory);
+ WriteSubmissionEvent(Failed, "");
+ }
+ } else {
+ WriteSubmissionEvent(Failed, "");
+ }
+}
+
+static string ComputeDumpHash() {
+#ifdef XP_LINUX
+ // On Linux we rely on the system-provided libcurl which uses nss so we have
+ // to also use the system-provided nss instead of the ones we have bundled.
+ const char* libnssNames[] = {
+ "libnss3.so",
+# ifndef HAVE_64BIT_BUILD
+ // 32-bit versions on 64-bit hosts
+ "/usr/lib32/libnss3.so",
+# endif
+ };
+ void* lib = nullptr;
+
+ for (const char* libname : libnssNames) {
+ lib = dlopen(libname, RTLD_NOW);
+
+ if (lib) {
+ break;
+ }
+ }
+
+ if (!lib) {
+ return "";
+ }
+
+ SECStatus (*NSS_Initialize)(const char*, const char*, const char*,
+ const char*, PRUint32);
+ HASHContext* (*HASH_Create)(HASH_HashType);
+ void (*HASH_Destroy)(HASHContext*);
+ void (*HASH_Begin)(HASHContext*);
+ void (*HASH_Update)(HASHContext*, const unsigned char*, unsigned int);
+ void (*HASH_End)(HASHContext*, unsigned char*, unsigned int*, unsigned int);
+
+ *(void**)(&NSS_Initialize) = dlsym(lib, "NSS_Initialize");
+ *(void**)(&HASH_Create) = dlsym(lib, "HASH_Create");
+ *(void**)(&HASH_Destroy) = dlsym(lib, "HASH_Destroy");
+ *(void**)(&HASH_Begin) = dlsym(lib, "HASH_Begin");
+ *(void**)(&HASH_Update) = dlsym(lib, "HASH_Update");
+ *(void**)(&HASH_End) = dlsym(lib, "HASH_End");
+
+ if (!HASH_Create || !HASH_Destroy || !HASH_Begin || !HASH_Update ||
+ !HASH_End) {
+ return "";
+ }
+#endif
+ // Minimal NSS initialization so we can use the hash functions
+ const PRUint32 kNssFlags = NSS_INIT_READONLY | NSS_INIT_NOROOTINIT |
+ NSS_INIT_NOMODDB | NSS_INIT_NOCERTDB;
+ if (NSS_Initialize(nullptr, "", "", "", kNssFlags) != SECSuccess) {
+ return "";
+ }
+
+ HASHContext* hashContext = HASH_Create(HASH_AlgSHA256);
+
+ if (!hashContext) {
+ return "";
+ }
+
+ HASH_Begin(hashContext);
+
+ ifstream* f = UIOpenRead(gReporterDumpFile, ios::binary);
+ bool error = false;
+
+ // Read the minidump contents
+ if (f->is_open()) {
+ uint8_t buff[4096];
+
+ do {
+ f->read((char*)buff, sizeof(buff));
+
+ if (f->bad()) {
+ error = true;
+ break;
+ }
+
+ HASH_Update(hashContext, buff, f->gcount());
+ } while (!f->eof());
+
+ f->close();
+ } else {
+ error = true;
+ }
+
+ delete f;
+
+ // Finalize the hash computation
+ uint8_t result[SHA256_LENGTH];
+ uint32_t resultLen = 0;
+
+ HASH_End(hashContext, result, &resultLen, SHA256_LENGTH);
+
+ if (resultLen != SHA256_LENGTH) {
+ error = true;
+ }
+
+ HASH_Destroy(hashContext);
+
+ if (!error) {
+ ostringstream hash;
+
+ for (size_t i = 0; i < SHA256_LENGTH; i++) {
+ hash << std::setw(2) << std::setfill('0') << std::hex
+ << static_cast<unsigned int>(result[i]);
+ }
+
+ return hash.str();
+ }
+ return ""; // If we encountered an error, return an empty hash
+}
+
+string GetDumpLocalID() {
+ string localId = Basename(gReporterDumpFile);
+ string::size_type dot = localId.rfind('.');
+
+ if (dot == string::npos) return "";
+
+ return localId.substr(0, dot);
+}
+
+string GetProgramPath(const string& exename) {
+ string path = gArgv[0];
+ size_t pos = path.rfind(UI_CRASH_REPORTER_FILENAME BIN_SUFFIX);
+ path.erase(pos);
+#ifdef XP_MACOSX
+ // On macOS the crash reporter client is shipped as an application bundle
+ // contained within Firefox' main application bundle. So when it's invoked
+ // its current working directory looks like:
+ // Firefox.app/Contents/MacOS/crashreporter.app/Contents/MacOS/
+ // The other applications we ship with Firefox are stored in the main bundle
+ // (Firefox.app/Contents/MacOS/) so we we need to go back three directories
+ // to reach them.
+ path.append("../../../");
+#endif // XP_MACOSX
+ path.append(exename + BIN_SUFFIX);
+
+ return path;
+}
+
+} // namespace CrashReporter
+
+using namespace CrashReporter;
+
+Json::Value kEmptyJsonString("");
+
+void RewriteStrings(Json::Value& aExtraData) {
+ // rewrite some UI strings with the values from the query parameters
+ string product = aExtraData.get("ProductName", kEmptyJsonString).asString();
+ Json::Value mozilla("Mozilla");
+ string vendor = aExtraData.get("Vendor", mozilla).asString();
+
+ char buf[4096];
+ snprintf(buf, sizeof(buf), gStrings[ST_CRASHREPORTERVENDORTITLE].c_str(),
+ vendor.c_str());
+ gStrings[ST_CRASHREPORTERTITLE] = buf;
+
+ string str = gStrings[ST_CRASHREPORTERPRODUCTERROR];
+ // Only do the replacement here if the string has two
+ // format specifiers to start. Otherwise
+ // we assume it has the product name hardcoded.
+ string::size_type pos = str.find("%s");
+ if (pos != string::npos) pos = str.find("%s", pos + 2);
+ if (pos != string::npos) {
+ // Leave a format specifier for UIError to fill in
+ snprintf(buf, sizeof(buf), gStrings[ST_CRASHREPORTERPRODUCTERROR].c_str(),
+ product.c_str(), "%s");
+ gStrings[ST_CRASHREPORTERERROR] = buf;
+ } else {
+ // product name is hardcoded
+ gStrings[ST_CRASHREPORTERERROR] = str;
+ }
+
+ snprintf(buf, sizeof(buf), gStrings[ST_CRASHREPORTERDESCRIPTION].c_str(),
+ product.c_str());
+ gStrings[ST_CRASHREPORTERDESCRIPTION] = buf;
+
+ snprintf(buf, sizeof(buf), gStrings[ST_CHECKSUBMIT].c_str(), vendor.c_str());
+ gStrings[ST_CHECKSUBMIT] = buf;
+
+ snprintf(buf, sizeof(buf), gStrings[ST_RESTART].c_str(), product.c_str());
+ gStrings[ST_RESTART] = buf;
+
+ snprintf(buf, sizeof(buf), gStrings[ST_QUIT].c_str(), product.c_str());
+ gStrings[ST_QUIT] = buf;
+
+ snprintf(buf, sizeof(buf), gStrings[ST_ERROR_ENDOFLIFE].c_str(),
+ product.c_str());
+ gStrings[ST_ERROR_ENDOFLIFE] = buf;
+}
+
+bool CheckEndOfLifed(const Json::Value& aVersion) {
+ if (!aVersion.isString()) {
+ return false;
+ }
+
+ string reportPath =
+ gSettingsPath + UI_DIR_SEPARATOR + "EndOfLife" + aVersion.asString();
+ return UIFileExists(reportPath);
+}
+
+int main(int argc, char** argv) {
+ gArgc = argc;
+ gArgv = argv;
+
+ string autoSubmitEnv = UIGetEnv("MOZ_CRASHREPORTER_AUTO_SUBMIT");
+ gAutoSubmit = !autoSubmitEnv.empty();
+
+ if (!ReadConfig()) {
+ UIError("Couldn't read configuration.");
+ return 0;
+ }
+
+ if (!UIInit()) {
+ return 0;
+ }
+
+ if (argc > 1) {
+ gReporterDumpFile = argv[1];
+ }
+
+ if (gReporterDumpFile.empty()) {
+ // no dump file specified, run the default UI
+ if (!gAutoSubmit) {
+ UIShowDefaultUI();
+ }
+ } else {
+ // Start by running minidump analyzer to gather stack traces.
+ string reporterDumpFile = gReporterDumpFile;
+ vector<string> args = {reporterDumpFile};
+ string dumpAllThreadsEnv = UIGetEnv("MOZ_CRASHREPORTER_DUMP_ALL_THREADS");
+ if (!dumpAllThreadsEnv.empty()) {
+ args.insert(args.begin(), "--full");
+ }
+ UIRunProgram(CrashReporter::GetProgramPath(UI_MINIDUMP_ANALYZER_FILENAME),
+ args,
+ /* wait */ true);
+
+ // go ahead with the crash reporter
+ gExtraFile = GetAdditionalFilename(gReporterDumpFile, kExtraDataExtension);
+ if (gExtraFile.empty()) {
+ UIError(gStrings[ST_ERROR_BADARGUMENTS]);
+ return 0;
+ }
+
+ if (!UIFileExists(gExtraFile)) {
+ UIError(gStrings[ST_ERROR_EXTRAFILEEXISTS]);
+ return 0;
+ }
+
+ gMemoryFile =
+ GetAdditionalFilename(gReporterDumpFile, kMemoryReportExtension);
+ if (!UIFileExists(gMemoryFile)) {
+ gMemoryFile.erase();
+ }
+
+ Json::Value extraData;
+ if (!ReadExtraFile(gExtraFile, extraData)) {
+ UIError(gStrings[ST_ERROR_EXTRAFILEREAD]);
+ return 0;
+ }
+
+ if (!extraData.isMember("ProductName")) {
+ UIError(gStrings[ST_ERROR_NOPRODUCTNAME]);
+ return 0;
+ }
+
+ // There is enough information in the extra file to rewrite strings
+ // to be product specific
+ RewriteStrings(extraData);
+
+ if (!extraData.isMember("ServerURL")) {
+ UIError(gStrings[ST_ERROR_NOSERVERURL]);
+ return 0;
+ }
+
+ // Hopefully the settings path exists in the environment. Try that before
+ // asking the platform-specific code to guess.
+ gSettingsPath = UIGetEnv("MOZ_CRASHREPORTER_DATA_DIRECTORY");
+ if (gSettingsPath.empty()) {
+ string product =
+ extraData.get("ProductName", kEmptyJsonString).asString();
+ string vendor = extraData.get("Vendor", kEmptyJsonString).asString();
+
+ if (!UIGetSettingsPath(vendor, product, gSettingsPath)) {
+ gSettingsPath.clear();
+ }
+ }
+
+ if (gSettingsPath.empty() || !UIEnsurePathExists(gSettingsPath)) {
+ UIError(gStrings[ST_ERROR_NOSETTINGSPATH]);
+ return 0;
+ }
+
+ OpenLogFile();
+
+ gEventsPath = UIGetEnv("MOZ_CRASHREPORTER_EVENTS_DIRECTORY");
+ gPingPath = UIGetEnv("MOZ_CRASHREPORTER_PING_DIRECTORY");
+
+ // Assemble and send the crash ping
+ string hash = ComputeDumpHash();
+
+ string pingUuid;
+ SendCrashPing(extraData, hash, pingUuid, gPingPath);
+ UpdateEventFile(extraData, hash, pingUuid);
+
+ if (!UIFileExists(gReporterDumpFile)) {
+ UIError(gStrings[ST_ERROR_DUMPFILEEXISTS]);
+ return 0;
+ }
+
+ string pendingDir = gSettingsPath + UI_DIR_SEPARATOR + "pending";
+ if (!MoveCrashData(pendingDir, gReporterDumpFile, gExtraFile,
+ gMemoryFile)) {
+ return 0;
+ }
+
+ string sendURL = extraData.get("ServerURL", kEmptyJsonString).asString();
+ // we don't need to actually send these
+ extraData.removeMember("ServerURL");
+ extraData.removeMember("StackTraces");
+
+ extraData["SubmittedFrom"] = "Client";
+ extraData["Throttleable"] = "1";
+
+ // re-set XUL_APP_FILE for xulrunner wrapped apps
+ const char* appfile = getenv("MOZ_CRASHREPORTER_RESTART_XUL_APP_FILE");
+ if (appfile && *appfile) {
+ const char prefix[] = "XUL_APP_FILE=";
+ char* env = (char*)malloc(strlen(appfile) + strlen(prefix) + 1);
+ if (!env) {
+ UIError("Out of memory");
+ return 0;
+ }
+ strcpy(env, prefix);
+ strcat(env, appfile);
+ putenv(env);
+ free(env);
+ }
+
+ vector<string> restartArgs;
+
+ ostringstream paramName;
+ int i = 0;
+ paramName << "MOZ_CRASHREPORTER_RESTART_ARG_" << i++;
+ const char* param = getenv(paramName.str().c_str());
+ while (param && *param) {
+ restartArgs.push_back(param);
+
+ paramName.str("");
+ paramName << "MOZ_CRASHREPORTER_RESTART_ARG_" << i++;
+ param = getenv(paramName.str().c_str());
+ }
+
+ // allow override of the server url via environment variable
+ // XXX: remove this in the far future when our robot
+ // masters force everyone to use XULRunner
+ char* urlEnv = getenv("MOZ_CRASHREPORTER_URL");
+ if (urlEnv && *urlEnv) {
+ sendURL = urlEnv;
+ }
+
+ // see if this version has been end-of-lifed
+
+ if (extraData.isMember("Version") &&
+ CheckEndOfLifed(extraData["Version"])) {
+ UIError(gStrings[ST_ERROR_ENDOFLIFE]);
+ DeleteDump();
+ return 0;
+ }
+
+ StringTable files;
+ files["upload_file_minidump"] = gReporterDumpFile;
+ if (!gMemoryFile.empty()) {
+ files["memory_report"] = gMemoryFile;
+ }
+
+ if (!UIShowCrashUI(files, extraData, sendURL, restartArgs)) {
+ DeleteDump();
+ }
+ }
+
+ UIShutdown();
+
+ return 0;
+}
+
+#if defined(XP_WIN) && !defined(__GNUC__)
+# include <windows.h>
+
+// We need WinMain in order to not be a console app. This function is unused
+// if we are a console application.
+int WINAPI wWinMain(HINSTANCE, HINSTANCE, LPWSTR args, int) {
+ // Remove everything except close window from the context menu
+ {
+ HKEY hkApp;
+ RegCreateKeyExW(HKEY_CURRENT_USER, L"Software\\Classes\\Applications", 0,
+ nullptr, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, nullptr,
+ &hkApp, nullptr);
+ RegCloseKey(hkApp);
+ if (RegCreateKeyExW(HKEY_CURRENT_USER,
+ L"Software\\Classes\\Applications\\crashreporter.exe",
+ 0, nullptr, REG_OPTION_VOLATILE, KEY_SET_VALUE, nullptr,
+ &hkApp, nullptr) == ERROR_SUCCESS) {
+ RegSetValueExW(hkApp, L"IsHostApp", 0, REG_NONE, 0, 0);
+ RegSetValueExW(hkApp, L"NoOpenWith", 0, REG_NONE, 0, 0);
+ RegSetValueExW(hkApp, L"NoStartPage", 0, REG_NONE, 0, 0);
+ RegCloseKey(hkApp);
+ }
+ }
+
+ char** argv = static_cast<char**>(malloc(__argc * sizeof(char*)));
+ for (int i = 0; i < __argc; i++) {
+ argv[i] = strdup(WideToUTF8(__wargv[i]).c_str());
+ }
+
+ // Do the real work.
+ return main(__argc, argv);
+}
+#endif
diff --git a/toolkit/crashreporter/client/crashreporter.exe.manifest b/toolkit/crashreporter/client/crashreporter.exe.manifest
new file mode 100644
index 0000000000..81aa1465c6
--- /dev/null
+++ b/toolkit/crashreporter/client/crashreporter.exe.manifest
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
+<assemblyIdentity
+ version="1.0.0.0"
+ processorArchitecture="*"
+ name="CrashReporter"
+ type="win32"
+/>
+<description>Crash Reporter</description>
+<dependency>
+ <dependentAssembly>
+ <assemblyIdentity
+ type="win32"
+ name="Microsoft.Windows.Common-Controls"
+ version="6.0.0.0"
+ processorArchitecture="*"
+ publicKeyToken="6595b64144ccf1df"
+ language="*"
+ />
+ </dependentAssembly>
+</dependency>
+<ms_asmv3:trustInfo xmlns:ms_asmv3="urn:schemas-microsoft-com:asm.v3">
+ <ms_asmv3:security>
+ <ms_asmv3:requestedPrivileges>
+ <ms_asmv3:requestedExecutionLevel level="asInvoker" uiAccess="false" />
+ </ms_asmv3:requestedPrivileges>
+ </ms_asmv3:security>
+</ms_asmv3:trustInfo>
+ <ms_asmv3:application xmlns:ms_asmv3="urn:schemas-microsoft-com:asm.v3">
+ <ms_asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
+ <gdiScaling xmlns="http://schemas.microsoft.com/SMI/2017/WindowsSettings">true</gdiScaling>
+ </ms_asmv3:windowsSettings>
+ </ms_asmv3:application>
+ <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
+ <application>
+ <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
+ <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
+ <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
+ <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
+ </application>
+ </compatibility>
+</assembly>
diff --git a/toolkit/crashreporter/client/crashreporter.h b/toolkit/crashreporter/client/crashreporter.h
new file mode 100644
index 0000000000..d0ac7a8626
--- /dev/null
+++ b/toolkit/crashreporter/client/crashreporter.h
@@ -0,0 +1,159 @@
+/* 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/. */
+
+#ifndef CRASHREPORTER_H__
+#define CRASHREPORTER_H__
+
+#ifdef _MSC_VER
+# pragma warning(push)
+// Disable exception handler warnings.
+# pragma warning(disable : 4530)
+#endif
+
+#include <string>
+#include <map>
+#include <vector>
+#include <stdlib.h>
+#include <stdio.h>
+#include <iostream>
+#include <fstream>
+
+#define MAX_COMMENT_LENGTH 10000
+
+#if defined(XP_WIN)
+
+# include <windows.h>
+
+# define UI_DIR_SEPARATOR "\\"
+
+std::string WideToUTF8(const std::wstring& wide, bool* success = 0);
+
+#else
+
+# define UI_DIR_SEPARATOR "/"
+
+#endif
+
+#include "json/json.h"
+
+#define UI_CRASH_REPORTER_FILENAME "crashreporter"
+#define UI_MINIDUMP_ANALYZER_FILENAME "minidump-analyzer"
+#define UI_PING_SENDER_FILENAME "pingsender"
+
+typedef std::map<std::string, std::string> StringTable;
+
+#define ST_CRASHREPORTERTITLE "CrashReporterTitle"
+#define ST_CRASHREPORTERVENDORTITLE "CrashReporterVendorTitle"
+#define ST_CRASHREPORTERERROR "CrashReporterErrorText"
+#define ST_CRASHREPORTERPRODUCTERROR "CrashReporterProductErrorText2"
+#define ST_CRASHREPORTERHEADER "CrashReporterSorry"
+#define ST_CRASHREPORTERDESCRIPTION "CrashReporterDescriptionText2"
+#define ST_CRASHREPORTERDEFAULT "CrashReporterDefault"
+#define ST_VIEWREPORT "Details"
+#define ST_VIEWREPORTTITLE "ViewReportTitle"
+#define ST_COMMENTGRAYTEXT "CommentGrayText"
+#define ST_EXTRAREPORTINFO "ExtraReportInfo"
+#define ST_CHECKSUBMIT "CheckSendReport"
+#define ST_CHECKURL "CheckIncludeURL"
+#define ST_REPORTPRESUBMIT "ReportPreSubmit2"
+#define ST_REPORTDURINGSUBMIT "ReportDuringSubmit2"
+#define ST_REPORTSUBMITSUCCESS "ReportSubmitSuccess"
+#define ST_SUBMITFAILED "ReportSubmitFailed"
+#define ST_QUIT "Quit2"
+#define ST_RESTART "Restart"
+#define ST_OK "Ok"
+#define ST_CLOSE "Close"
+
+#define ST_ERROR_BADARGUMENTS "ErrorBadArguments"
+#define ST_ERROR_EXTRAFILEEXISTS "ErrorExtraFileExists"
+#define ST_ERROR_EXTRAFILEREAD "ErrorExtraFileRead"
+#define ST_ERROR_EXTRAFILEMOVE "ErrorExtraFileMove"
+#define ST_ERROR_DUMPFILEEXISTS "ErrorDumpFileExists"
+#define ST_ERROR_DUMPFILEMOVE "ErrorDumpFileMove"
+#define ST_ERROR_NOPRODUCTNAME "ErrorNoProductName"
+#define ST_ERROR_NOSERVERURL "ErrorNoServerURL"
+#define ST_ERROR_NOSETTINGSPATH "ErrorNoSettingsPath"
+#define ST_ERROR_CREATEDUMPDIR "ErrorCreateDumpDir"
+#define ST_ERROR_ENDOFLIFE "ErrorEndOfLife"
+
+//=============================================================================
+// implemented in crashreporter.cpp and ping.cpp
+//=============================================================================
+
+namespace CrashReporter {
+extern StringTable gStrings;
+extern std::string gSettingsPath;
+extern std::string gEventsPath;
+extern int gArgc;
+extern char** gArgv;
+extern bool gAutoSubmit;
+
+void UIError(const std::string& message);
+
+// The UI finished sending the report
+void SendCompleted(bool success, const std::string& serverResponse);
+
+bool ReadStrings(std::istream& in, StringTable& strings, bool unescape);
+bool ReadStringsFromFile(const std::string& path, StringTable& strings,
+ bool unescape);
+void LogMessage(const std::string& message);
+void DeleteDump();
+
+std::string GetDumpLocalID();
+std::string GetProgramPath(const std::string& exename);
+
+// Telemetry ping
+bool SendCrashPing(Json::Value& extra, const std::string& hash,
+ std::string& pingUuid, const std::string& pingDir);
+
+static const unsigned int kSaveCount = 10;
+} // namespace CrashReporter
+
+//=============================================================================
+// implemented in the platform-specific files
+//=============================================================================
+
+bool UIInit();
+void UIShutdown();
+
+// Run the UI for when the app was launched without a dump file
+void UIShowDefaultUI();
+
+// Run the UI for when the app was launched with a dump file
+// Return true if the user sent (or tried to send) the crash report,
+// false if they chose not to, and it should be deleted.
+bool UIShowCrashUI(const StringTable& files, const Json::Value& queryParameters,
+ const std::string& sendURL,
+ const std::vector<std::string>& restartArgs);
+
+void UIError_impl(const std::string& message);
+
+bool UIGetIniPath(std::string& path);
+bool UIGetSettingsPath(const std::string& vendor, const std::string& product,
+ std::string& settingsPath);
+bool UIEnsurePathExists(const std::string& path);
+bool UIFileExists(const std::string& path);
+bool UIMoveFile(const std::string& oldfile, const std::string& newfile);
+bool UIDeleteFile(const std::string& oldfile);
+std::ifstream* UIOpenRead(const std::string& filename,
+ std::ios_base::openmode mode);
+std::ofstream* UIOpenWrite(const std::string& filename,
+ std::ios_base::openmode mode);
+void UIPruneSavedDumps(const std::string& directory);
+
+// Run the program specified by exename, passing it the parameters in arg.
+// If wait is true, wait for the program to terminate execution before
+// returning. Returns true if the program was launched correctly, false
+// otherwise.
+bool UIRunProgram(const std::string& exename,
+ const std::vector<std::string>& args, bool wait = false);
+
+// Read the environment variable specified by name
+std::string UIGetEnv(const std::string& name);
+
+#ifdef _MSC_VER
+# pragma warning(pop)
+#endif
+
+#endif
diff --git a/toolkit/crashreporter/client/crashreporter.ico b/toolkit/crashreporter/client/crashreporter.ico
new file mode 100644
index 0000000000..29ac3c6189
--- /dev/null
+++ b/toolkit/crashreporter/client/crashreporter.ico
Binary files differ
diff --git a/toolkit/crashreporter/client/crashreporter.rc b/toolkit/crashreporter/client/crashreporter.rc
new file mode 100755
index 0000000000..f6042bf2e5
--- /dev/null
+++ b/toolkit/crashreporter/client/crashreporter.rc
@@ -0,0 +1,143 @@
+/* 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/. */
+
+// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "winresrc.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include ""winresrc.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDI_MAINICON ICON "crashreporter.ico"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// AVI
+//
+
+IDR_THROBBER AVI "Throbber-small.avi"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_SENDDIALOG DIALOGEX 0, 0, 241, 187
+STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+EXSTYLE WS_EX_APPWINDOW
+CAPTION "Sending Crash Report..."
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ CONTROL "",IDC_DESCRIPTIONTEXT,"RICHEDIT50W",ES_MULTILINE | ES_READONLY,8,7,226,12,WS_EX_TRANSPARENT
+ CONTROL "tell mozilla about this crash so they can fix it",IDC_SUBMITREPORTCHECK,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,25,222,10
+ CHECKBOX "details...",IDC_VIEWREPORTBUTTON,24,40,54,14,BS_PUSHLIKE
+ EDITTEXT IDC_COMMENTTEXT,24,59,210,43,ES_MULTILINE | ES_WANTRETURN | WS_VSCROLL
+ CONTROL "include the address of the page i was on",IDC_INCLUDEURLCHECK,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,24,107,210,10
+ CONTROL "",IDC_THROBBER,"SysAnimate32",ACS_TRANSPARENT | NOT WS_VISIBLE | WS_TABSTOP,4,152,16,16
+ LTEXT "your crash report will be submitted when you restart",IDC_PROGRESSTEXT,24,152,210,10,SS_NOPREFIX
+ DEFPUSHBUTTON "restart firefox",IDC_RESTARTBUTTON,84,166,68,14
+ PUSHBUTTON "quit without sending",IDC_CLOSEBUTTON,157,166,77,14
+END
+
+IDD_VIEWREPORTDIALOG DIALOGEX 0, 0, 208, 126
+STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION
+CAPTION "view report"
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ CONTROL "",IDC_VIEWREPORTTEXT,"RICHEDIT50W",ES_MULTILINE | ES_READONLY | WS_BORDER | WS_VSCROLL | WS_TABSTOP,7,7,194,92
+ DEFPUSHBUTTON "OK",IDOK,151,105,50,14
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO
+BEGIN
+ IDD_SENDDIALOG, DIALOG
+ BEGIN
+ LEFTMARGIN, 8
+ RIGHTMARGIN, 234
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 180
+ END
+
+ IDD_VIEWREPORTDIALOG, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 201
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 119
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+#endif // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/toolkit/crashreporter/client/crashreporter_gtk_common.cpp b/toolkit/crashreporter/client/crashreporter_gtk_common.cpp
new file mode 100644
index 0000000000..d4bed0209c
--- /dev/null
+++ b/toolkit/crashreporter/client/crashreporter_gtk_common.cpp
@@ -0,0 +1,361 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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 "crashreporter.h"
+
+#include <unistd.h>
+#include <dlfcn.h>
+#include <errno.h>
+#include <glib.h>
+#include <gtk/gtk.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <gdk/gdkkeysyms.h>
+
+#include <algorithm>
+#include <string>
+#include <vector>
+
+#include "common/linux/http_upload.h"
+#include "crashreporter.h"
+#include "crashreporter_gtk_common.h"
+
+#ifndef GDK_KEY_Escape
+# define GDK_KEY_Escape GDK_Escape
+#endif
+
+using std::string;
+using std::vector;
+
+using namespace CrashReporter;
+
+GtkWidget* gWindow = 0;
+GtkWidget* gSubmitReportCheck = 0;
+GtkWidget* gIncludeURLCheck = 0;
+GtkWidget* gThrobber = 0;
+GtkWidget* gProgressLabel = 0;
+GtkWidget* gCloseButton = 0;
+GtkWidget* gRestartButton = 0;
+
+bool gInitialized = false;
+bool gDidTrySend = false;
+StringTable gFiles;
+Json::Value gQueryParameters;
+string gHttpProxy;
+string gAuth;
+string gCACertificateFile;
+string gSendURL;
+string gURLParameter;
+vector<string> gRestartArgs;
+GThread* gSendThreadID;
+
+// From crashreporter_linux.cpp
+void SendReport();
+void DisableGUIAndSendReport();
+void TryInitGnome();
+void UpdateSubmit();
+
+static bool RestartApplication() {
+ char** argv = reinterpret_cast<char**>(
+ malloc(sizeof(char*) * (gRestartArgs.size() + 1)));
+
+ if (!argv) return false;
+
+ unsigned int i;
+ for (i = 0; i < gRestartArgs.size(); i++) {
+ argv[i] = (char*)gRestartArgs[i].c_str();
+ }
+ argv[i] = 0;
+
+ pid_t pid = fork();
+ if (pid == -1) {
+ free(argv);
+ return false;
+ } else if (pid == 0) {
+ (void)execv(argv[0], argv);
+ _exit(1);
+ }
+
+ free(argv);
+
+ return true;
+}
+
+// Quit the app, used as a timeout callback
+gboolean CloseApp(gpointer data) {
+ if (!gAutoSubmit) {
+ gtk_main_quit();
+ }
+ g_thread_join(gSendThreadID);
+ return FALSE;
+}
+
+static gboolean ReportCompleted(gpointer success) {
+ gtk_widget_hide(gThrobber);
+ string str =
+ success ? gStrings[ST_REPORTSUBMITSUCCESS] : gStrings[ST_SUBMITFAILED];
+ gtk_label_set_text(GTK_LABEL(gProgressLabel), str.c_str());
+ g_timeout_add(5000, CloseApp, 0);
+ return FALSE;
+}
+
+#define HTTP_PROXY_DIR "/system/http_proxy"
+
+void LoadProxyinfo() {
+ class GConfClient;
+ typedef GConfClient* (*_gconf_default_fn)();
+ typedef gboolean (*_gconf_bool_fn)(GConfClient*, const gchar*, GError**);
+ typedef gint (*_gconf_int_fn)(GConfClient*, const gchar*, GError**);
+ typedef gchar* (*_gconf_string_fn)(GConfClient*, const gchar*, GError**);
+
+ if (getenv("http_proxy"))
+ return; // libcurl can use the value from the environment
+
+ static void* gconfLib = dlopen("libgconf-2.so.4", RTLD_LAZY);
+ if (!gconfLib) return;
+
+ _gconf_default_fn gconf_client_get_default =
+ (_gconf_default_fn)dlsym(gconfLib, "gconf_client_get_default");
+ _gconf_bool_fn gconf_client_get_bool =
+ (_gconf_bool_fn)dlsym(gconfLib, "gconf_client_get_bool");
+ _gconf_int_fn gconf_client_get_int =
+ (_gconf_int_fn)dlsym(gconfLib, "gconf_client_get_int");
+ _gconf_string_fn gconf_client_get_string =
+ (_gconf_string_fn)dlsym(gconfLib, "gconf_client_get_string");
+
+ if (!(gconf_client_get_default && gconf_client_get_bool &&
+ gconf_client_get_int && gconf_client_get_string)) {
+ dlclose(gconfLib);
+ return;
+ }
+
+ GConfClient* conf = gconf_client_get_default();
+
+ if (gconf_client_get_bool(conf, HTTP_PROXY_DIR "/use_http_proxy", nullptr)) {
+ gint port;
+ gchar *host = nullptr, *httpproxy = nullptr;
+
+ host = gconf_client_get_string(conf, HTTP_PROXY_DIR "/host", nullptr);
+ port = gconf_client_get_int(conf, HTTP_PROXY_DIR "/port", nullptr);
+
+ if (port && host && *host != '\0') {
+ httpproxy = g_strdup_printf("http://%s:%d/", host, port);
+ gHttpProxy = httpproxy;
+ }
+
+ g_free(host);
+ g_free(httpproxy);
+
+ if (gconf_client_get_bool(conf, HTTP_PROXY_DIR "/use_authentication",
+ nullptr)) {
+ gchar *user, *password, *auth = nullptr;
+
+ user = gconf_client_get_string(
+ conf, HTTP_PROXY_DIR "/authentication_user", nullptr);
+ password = gconf_client_get_string(
+ conf, HTTP_PROXY_DIR "/authentication_password", nullptr);
+
+ if (user && password) {
+ auth = g_strdup_printf("%s:%s", user, password);
+ gAuth = auth;
+ }
+
+ g_free(user);
+ g_free(password);
+ g_free(auth);
+ }
+ }
+
+ g_object_unref(conf);
+
+ // Don't dlclose gconfLib as libORBit-2 uses atexit().
+}
+
+gpointer SendThread(gpointer args) {
+ Json::StreamWriterBuilder builder;
+ builder["indentation"] = "";
+ string parameters(writeString(builder, gQueryParameters));
+
+ string response, error;
+ long response_code;
+
+ bool success = google_breakpad::HTTPUpload::SendRequest(
+ gSendURL, parameters, gFiles, gHttpProxy, gAuth, gCACertificateFile,
+ &response, &response_code, &error);
+ if (success) {
+ LogMessage("Crash report submitted successfully");
+ } else {
+ LogMessage("Crash report submission failed: " + error);
+ }
+
+ SendCompleted(success, response);
+
+ if (!gAutoSubmit) {
+ // Apparently glib is threadsafe, and will schedule this
+ // on the main thread, see:
+ // http://library.gnome.org/devel/gtk-faq/stable/x499.html
+ g_idle_add(ReportCompleted, (gpointer)success);
+ }
+
+ return nullptr;
+}
+
+gboolean WindowDeleted(GtkWidget* window, GdkEvent* event, gpointer userData) {
+ SaveSettings();
+ gtk_main_quit();
+ return TRUE;
+}
+
+gboolean check_escape(GtkWidget* window, GdkEventKey* event,
+ gpointer userData) {
+ if (event->keyval == GDK_KEY_Escape) {
+ gtk_main_quit();
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static void MaybeSubmitReport() {
+ if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(gSubmitReportCheck))) {
+ gDidTrySend = true;
+ DisableGUIAndSendReport();
+ } else {
+ gtk_main_quit();
+ }
+}
+
+void CloseClicked(GtkButton* button, gpointer userData) {
+ SaveSettings();
+ MaybeSubmitReport();
+}
+
+void RestartClicked(GtkButton* button, gpointer userData) {
+ SaveSettings();
+ RestartApplication();
+ MaybeSubmitReport();
+}
+
+static void UpdateURL() {
+ if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(gIncludeURLCheck))) {
+ gQueryParameters["URL"] = gURLParameter;
+ } else {
+ gQueryParameters.removeMember("URL");
+ }
+}
+
+void SubmitReportChecked(GtkButton* sender, gpointer userData) {
+ UpdateSubmit();
+}
+
+void IncludeURLClicked(GtkButton* sender, gpointer userData) { UpdateURL(); }
+
+/* === Crashreporter UI Functions === */
+
+bool UIInit() {
+ // breakpad probably left us with blocked signals, unblock them here
+ sigset_t signals, old;
+ sigfillset(&signals);
+ sigprocmask(SIG_UNBLOCK, &signals, &old);
+
+ // tell glib we're going to use threads
+ g_thread_init(nullptr);
+
+ if (gtk_init_check(&gArgc, &gArgv)) {
+ gInitialized = true;
+
+ if (gStrings.find("isRTL") != gStrings.end() && gStrings["isRTL"] == "yes")
+ gtk_widget_set_default_direction(GTK_TEXT_DIR_RTL);
+
+ return true;
+ }
+
+ return false;
+}
+
+void UIShowDefaultUI() {
+ GtkWidget* errorDialog = gtk_message_dialog_new(
+ nullptr, GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, "%s",
+ gStrings[ST_CRASHREPORTERDEFAULT].c_str());
+
+ gtk_window_set_title(GTK_WINDOW(errorDialog),
+ gStrings[ST_CRASHREPORTERTITLE].c_str());
+ gtk_dialog_run(GTK_DIALOG(errorDialog));
+}
+
+void UIError_impl(const string& message) {
+ if (!gInitialized) {
+ // Didn't initialize, this is the best we can do
+ printf("Error: %s\n", message.c_str());
+ return;
+ }
+
+ GtkWidget* errorDialog =
+ gtk_message_dialog_new(nullptr, GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR,
+ GTK_BUTTONS_CLOSE, "%s", message.c_str());
+
+ gtk_window_set_title(GTK_WINDOW(errorDialog),
+ gStrings[ST_CRASHREPORTERTITLE].c_str());
+ gtk_dialog_run(GTK_DIALOG(errorDialog));
+}
+
+bool UIGetIniPath(string& path) {
+ path = gArgv[0];
+ path.append(".ini");
+
+ return true;
+}
+
+/*
+ * Settings are stored in ~/.vendor/product, or
+ * ~/.product if vendor is empty.
+ */
+bool UIGetSettingsPath(const string& vendor, const string& product,
+ string& settingsPath) {
+ char* home = getenv("HOME");
+
+ if (!home) return false;
+
+ settingsPath = home;
+ settingsPath += "/.";
+ if (!vendor.empty()) {
+ string lc_vendor;
+ std::transform(vendor.begin(), vendor.end(), back_inserter(lc_vendor),
+ (int (*)(int))std::tolower);
+ settingsPath += lc_vendor + "/";
+ }
+ string lc_product;
+ std::transform(product.begin(), product.end(), back_inserter(lc_product),
+ (int (*)(int))std::tolower);
+ settingsPath += lc_product + "/Crash Reports";
+ return true;
+}
+
+bool UIMoveFile(const string& file, const string& newfile) {
+ if (!rename(file.c_str(), newfile.c_str())) return true;
+ if (errno != EXDEV) return false;
+
+ // use system /bin/mv instead, time to fork
+ pid_t pID = vfork();
+ if (pID < 0) {
+ // Failed to fork
+ return false;
+ }
+ if (pID == 0) {
+ char* const args[4] = {const_cast<char*>("mv"), strdup(file.c_str()),
+ strdup(newfile.c_str()), 0};
+ if (args[1] && args[2]) execve("/bin/mv", args, 0);
+ free(args[1]);
+ free(args[2]);
+ exit(-1);
+ }
+ int status;
+ waitpid(pID, &status, 0);
+ return UIFileExists(newfile);
+}
diff --git a/toolkit/crashreporter/client/crashreporter_gtk_common.h b/toolkit/crashreporter/client/crashreporter_gtk_common.h
new file mode 100644
index 0000000000..208c7ba6b0
--- /dev/null
+++ b/toolkit/crashreporter/client/crashreporter_gtk_common.h
@@ -0,0 +1,50 @@
+/* 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/. */
+
+#ifndef CRASHREPORTER_GTK_COMMON_H__
+#define CRASHREPORTER_GTK_COMMON_H__
+
+#include <glib.h>
+#include <gtk/gtk.h>
+
+#include <string>
+#include <vector>
+
+#include "json/json.h"
+
+const char kIniFile[] = "crashreporter.ini";
+
+extern GtkWidget* gWindow;
+extern GtkWidget* gSubmitReportCheck;
+extern GtkWidget* gIncludeURLCheck;
+extern GtkWidget* gThrobber;
+extern GtkWidget* gProgressLabel;
+extern GtkWidget* gCloseButton;
+extern GtkWidget* gRestartButton;
+
+extern std::vector<std::string> gRestartArgs;
+extern GThread* gSendThreadID;
+
+extern bool gInitialized;
+extern bool gDidTrySend;
+extern StringTable gFiles;
+extern Json::Value gQueryParameters;
+extern std::string gHttpProxy;
+extern std::string gAuth;
+extern std::string gCACertificateFile;
+extern std::string gSendURL;
+extern std::string gURLParameter;
+
+void LoadProxyinfo();
+gboolean CloseApp(gpointer data);
+gpointer SendThread(gpointer args);
+gboolean WindowDeleted(GtkWidget* window, GdkEvent* event, gpointer userData);
+gboolean check_escape(GtkWidget* window, GdkEventKey* event, gpointer data);
+void SubmitReportChecked(GtkButton* sender, gpointer userData);
+void IncludeURLClicked(GtkButton* sender, gpointer userData);
+void CloseClicked(GtkButton* button, gpointer userData);
+void RestartClicked(GtkButton* button, gpointer userData);
+void SaveSettings(void);
+
+#endif // CRASHREPORTER_GTK_COMMON_H__
diff --git a/toolkit/crashreporter/client/crashreporter_linux.cpp b/toolkit/crashreporter/client/crashreporter_linux.cpp
new file mode 100644
index 0000000000..d11f10a472
--- /dev/null
+++ b/toolkit/crashreporter/client/crashreporter_linux.cpp
@@ -0,0 +1,525 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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 <dlfcn.h>
+#include <fcntl.h>
+#include <glib.h>
+#include <gtk/gtk.h>
+#include <string.h>
+
+#include <cctype>
+
+#include "crashreporter.h"
+#include "crashreporter_gtk_common.h"
+
+#define LABEL_MAX_CHAR_WIDTH 48
+
+using std::ios;
+using std::string;
+using std::vector;
+
+using namespace CrashReporter;
+
+static GtkWidget* gViewReportButton = 0;
+static GtkWidget* gCommentTextLabel = 0;
+static GtkWidget* gCommentText = 0;
+
+static bool gCommentFieldHint = true;
+
+// handle from dlopen'ing libgnome
+static void* gnomeLib = nullptr;
+// handle from dlopen'ing libgnomeui
+static void* gnomeuiLib = nullptr;
+
+static void LoadSettings() {
+ /*
+ * NOTE! This code needs to stay in sync with the preference checking
+ * code in in nsExceptionHandler.cpp.
+ */
+
+ bool includeURL = true;
+ bool submitReport = true;
+ StringTable settings;
+ if (ReadStringsFromFile(gSettingsPath + "/" + kIniFile, settings, true)) {
+ if (settings.find("IncludeURL") != settings.end()) {
+ includeURL = settings["IncludeURL"][0] != '0';
+ }
+ if (settings.find("SubmitReport") != settings.end()) {
+ submitReport = settings["SubmitReport"][0] != '0';
+ }
+ }
+
+ if (gIncludeURLCheck) {
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gIncludeURLCheck),
+ includeURL);
+ }
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gSubmitReportCheck),
+ submitReport);
+}
+
+static string Escape(const string& str) {
+ string ret;
+ for (auto c : str) {
+ if (c == '\\') {
+ ret += "\\\\";
+ } else if (c == '\n') {
+ ret += "\\n";
+ } else if (c == '\t') {
+ ret += "\\t";
+ } else {
+ ret.push_back(c);
+ }
+ }
+
+ return ret;
+}
+
+static bool WriteStrings(std::ostream& out, const string& header,
+ StringTable& strings, bool escape) {
+ out << "[" << header << "]" << std::endl;
+ for (const auto& iter : strings) {
+ out << iter.first << "=";
+ if (escape) {
+ out << Escape(iter.second);
+ } else {
+ out << iter.second;
+ }
+
+ out << std::endl;
+ }
+
+ return true;
+}
+
+static bool WriteStringsToFile(const string& path, const string& header,
+ StringTable& strings, bool escape) {
+ std::ofstream* f = UIOpenWrite(path, ios::trunc);
+ bool success = false;
+ if (f->is_open()) {
+ success = WriteStrings(*f, header, strings, escape);
+ f->close();
+ }
+
+ delete f;
+ return success;
+}
+
+void SaveSettings() {
+ /*
+ * NOTE! This code needs to stay in sync with the preference setting
+ * code in in nsExceptionHandler.cpp.
+ */
+
+ StringTable settings;
+
+ ReadStringsFromFile(gSettingsPath + "/" + kIniFile, settings, true);
+ if (gIncludeURLCheck != 0)
+ settings["IncludeURL"] =
+ gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(gIncludeURLCheck)) ? "1"
+ : "0";
+ settings["SubmitReport"] =
+ gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(gSubmitReportCheck)) ? "1"
+ : "0";
+
+ WriteStringsToFile(gSettingsPath + "/" + kIniFile, "Crash Reporter", settings,
+ true);
+}
+
+void SendReport() {
+ LoadProxyinfo();
+
+ // spawn a thread to do the sending
+ gSendThreadID = g_thread_create(SendThread, nullptr, TRUE, nullptr);
+}
+
+void DisableGUIAndSendReport() {
+ // disable all our gui controls, show the throbber + change the progress text
+ gtk_widget_set_sensitive(gSubmitReportCheck, FALSE);
+ gtk_widget_set_sensitive(gViewReportButton, FALSE);
+ gtk_widget_set_sensitive(gCommentText, FALSE);
+ if (gIncludeURLCheck) gtk_widget_set_sensitive(gIncludeURLCheck, FALSE);
+ gtk_widget_set_sensitive(gCloseButton, FALSE);
+ if (gRestartButton) gtk_widget_set_sensitive(gRestartButton, FALSE);
+ gtk_widget_show_all(gThrobber);
+ gtk_label_set_text(GTK_LABEL(gProgressLabel),
+ gStrings[ST_REPORTDURINGSUBMIT].c_str());
+
+ SendReport();
+}
+
+static void ShowReportInfo(GtkTextView* viewReportTextView) {
+ GtkTextBuffer* buffer = gtk_text_view_get_buffer(viewReportTextView);
+
+ GtkTextIter start, end;
+ gtk_text_buffer_get_start_iter(buffer, &start);
+ gtk_text_buffer_get_end_iter(buffer, &end);
+
+ gtk_text_buffer_delete(buffer, &start, &end);
+
+ for (Json::ValueConstIterator iter = gQueryParameters.begin();
+ iter != gQueryParameters.end(); ++iter) {
+ gtk_text_buffer_insert(buffer, &end, iter.name().c_str(),
+ iter.name().length());
+ gtk_text_buffer_insert(buffer, &end, ": ", -1);
+ string value;
+ if (iter->isString()) {
+ value = iter->asString();
+ } else {
+ Json::StreamWriterBuilder builder;
+ builder["indentation"] = "";
+ value = writeString(builder, *iter);
+ }
+ gtk_text_buffer_insert(buffer, &end, value.c_str(), value.length());
+ gtk_text_buffer_insert(buffer, &end, "\n", -1);
+ }
+
+ gtk_text_buffer_insert(buffer, &end, "\n", -1);
+ gtk_text_buffer_insert(buffer, &end, gStrings[ST_EXTRAREPORTINFO].c_str(),
+ -1);
+}
+
+void UpdateSubmit() {
+ if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(gSubmitReportCheck))) {
+ gtk_widget_set_sensitive(gViewReportButton, TRUE);
+ gtk_widget_set_sensitive(gCommentText, TRUE);
+ if (gIncludeURLCheck) gtk_widget_set_sensitive(gIncludeURLCheck, TRUE);
+ gtk_label_set_text(GTK_LABEL(gProgressLabel),
+ gStrings[ST_REPORTPRESUBMIT].c_str());
+ } else {
+ gtk_widget_set_sensitive(gViewReportButton, FALSE);
+ gtk_widget_set_sensitive(gCommentText, FALSE);
+ if (gIncludeURLCheck) gtk_widget_set_sensitive(gIncludeURLCheck, FALSE);
+ gtk_label_set_text(GTK_LABEL(gProgressLabel), "");
+ }
+}
+
+static void ViewReportClicked(GtkButton* button, gpointer userData) {
+ GtkDialog* dialog = GTK_DIALOG(gtk_dialog_new_with_buttons(
+ gStrings[ST_VIEWREPORTTITLE].c_str(), GTK_WINDOW(gWindow),
+ GTK_DIALOG_MODAL, GTK_STOCK_OK, GTK_RESPONSE_OK, nullptr));
+
+ GtkWidget* scrolled = gtk_scrolled_window_new(0, 0);
+ gtk_container_add(GTK_CONTAINER(gtk_dialog_get_content_area(dialog)),
+ scrolled);
+ gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
+ GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
+ gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled),
+ GTK_SHADOW_IN);
+ gtk_widget_set_vexpand(scrolled, TRUE);
+
+ GtkWidget* viewReportTextView = gtk_text_view_new();
+ gtk_container_add(GTK_CONTAINER(scrolled), viewReportTextView);
+ gtk_text_view_set_editable(GTK_TEXT_VIEW(viewReportTextView), FALSE);
+ gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(viewReportTextView), GTK_WRAP_WORD);
+ gtk_widget_set_size_request(GTK_WIDGET(viewReportTextView), -1, 100);
+
+ ShowReportInfo(GTK_TEXT_VIEW(viewReportTextView));
+
+ gtk_dialog_set_default_response(dialog, GTK_RESPONSE_OK);
+ gtk_widget_set_size_request(GTK_WIDGET(dialog), 400, 200);
+ gtk_widget_show_all(GTK_WIDGET(dialog));
+ gtk_dialog_run(dialog);
+ gtk_widget_destroy(GTK_WIDGET(dialog));
+}
+
+static void CommentChanged(GtkTextBuffer* buffer, gpointer userData) {
+ GtkTextIter start, end;
+ gtk_text_buffer_get_start_iter(buffer, &start);
+ gtk_text_buffer_get_end_iter(buffer, &end);
+ const char* comment = gtk_text_buffer_get_text(buffer, &start, &end, TRUE);
+ if (comment[0] == '\0' || gCommentFieldHint) {
+ gQueryParameters.removeMember("Comments");
+ } else {
+ gQueryParameters["Comments"] = comment;
+ }
+}
+
+static void CommentInsert(GtkTextBuffer* buffer, GtkTextIter* location,
+ gchar* text, gint len, gpointer userData) {
+ GtkTextIter start, end;
+ gtk_text_buffer_get_start_iter(buffer, &start);
+ gtk_text_buffer_get_end_iter(buffer, &end);
+ const char* comment = gtk_text_buffer_get_text(buffer, &start, &end, TRUE);
+
+ // limit to 500 bytes in utf-8
+ if (strlen(comment) + len > MAX_COMMENT_LENGTH) {
+ g_signal_stop_emission_by_name(buffer, "insert-text");
+ }
+}
+
+static void UpdateHintText(GtkWidget* widget, gboolean gainedFocus,
+ bool* hintShowing, const char* hintText) {
+ GtkTextBuffer* buffer = nullptr;
+ if (GTK_IS_TEXT_VIEW(widget))
+ buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(widget));
+
+ if (gainedFocus) {
+ if (*hintShowing) {
+ if (buffer == nullptr) { // sort of cheating
+ gtk_entry_set_text(GTK_ENTRY(widget), "");
+ } else { // GtkTextView
+ gtk_text_buffer_set_text(buffer, "", 0);
+ }
+ gtk_widget_modify_text(widget, GTK_STATE_NORMAL, nullptr);
+ *hintShowing = false;
+ }
+ } else {
+ // lost focus
+ const char* text = nullptr;
+ if (buffer == nullptr) {
+ text = gtk_entry_get_text(GTK_ENTRY(widget));
+ } else {
+ GtkTextIter start, end;
+ gtk_text_buffer_get_start_iter(buffer, &start);
+ gtk_text_buffer_get_end_iter(buffer, &end);
+ text = gtk_text_buffer_get_text(buffer, &start, &end, TRUE);
+ }
+
+ if (text == nullptr || text[0] == '\0') {
+ *hintShowing = true;
+
+ if (buffer == nullptr) {
+ gtk_entry_set_text(GTK_ENTRY(widget), hintText);
+ } else {
+ gtk_text_buffer_set_text(buffer, hintText, -1);
+ }
+
+ gtk_widget_modify_text(
+ widget, GTK_STATE_NORMAL,
+ &gtk_widget_get_style(widget)->text[GTK_STATE_INSENSITIVE]);
+ }
+ }
+}
+
+static gboolean CommentFocusChange(GtkWidget* widget, GdkEventFocus* event,
+ gpointer userData) {
+ UpdateHintText(widget, event->in, &gCommentFieldHint,
+ gStrings[ST_COMMENTGRAYTEXT].c_str());
+
+ return FALSE;
+}
+
+typedef struct _GnomeProgram GnomeProgram;
+typedef struct _GnomeModuleInfo GnomeModuleInfo;
+typedef GnomeProgram* (*_gnome_program_init_fn)(const char*, const char*,
+ const GnomeModuleInfo*, int,
+ char**, const char*, ...);
+typedef const GnomeModuleInfo* (*_libgnomeui_module_info_get_fn)();
+
+void TryInitGnome() {
+ gnomeLib = dlopen("libgnome-2.so.0", RTLD_LAZY);
+ if (!gnomeLib) return;
+
+ gnomeuiLib = dlopen("libgnomeui-2.so.0", RTLD_LAZY);
+ if (!gnomeuiLib) return;
+
+ _gnome_program_init_fn gnome_program_init =
+ (_gnome_program_init_fn)(dlsym(gnomeLib, "gnome_program_init"));
+ _libgnomeui_module_info_get_fn libgnomeui_module_info_get =
+ (_libgnomeui_module_info_get_fn)(dlsym(gnomeuiLib,
+ "libgnomeui_module_info_get"));
+
+ if (gnome_program_init && libgnomeui_module_info_get) {
+ gnome_program_init("crashreporter", "1.0", libgnomeui_module_info_get(),
+ gArgc, gArgv, nullptr);
+ }
+}
+
+/* === Crashreporter UI Functions === */
+
+/*
+ * Anything not listed here is in crashreporter_gtk_common.cpp:
+ * UIInit
+ * UIShowDefaultUI
+ * UIError_impl
+ * UIGetIniPath
+ * UIGetSettingsPath
+ * UIEnsurePathExists
+ * UIFileExists
+ * UIMoveFile
+ * UIDeleteFile
+ * UIOpenRead
+ * UIOpenWrite
+ */
+
+void UIShutdown() {
+ if (gnomeuiLib) dlclose(gnomeuiLib);
+ // Don't dlclose gnomeLib as libgnomevfs and libORBit-2 use atexit().
+}
+
+bool UIShowCrashUI(const StringTable& files, const Json::Value& queryParameters,
+ const string& sendURL, const vector<string>& restartArgs) {
+ gFiles = files;
+ gQueryParameters = queryParameters;
+ gSendURL = sendURL;
+ gRestartArgs = restartArgs;
+ if (gQueryParameters.isMember("URL")) {
+ gURLParameter = gQueryParameters["URL"].asString();
+ }
+
+ if (gAutoSubmit) {
+ SendReport();
+ CloseApp(nullptr);
+ return true;
+ }
+
+ gWindow = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+ gtk_window_set_title(GTK_WINDOW(gWindow),
+ gStrings[ST_CRASHREPORTERTITLE].c_str());
+ gtk_window_set_resizable(GTK_WINDOW(gWindow), FALSE);
+ gtk_window_set_position(GTK_WINDOW(gWindow), GTK_WIN_POS_CENTER);
+ gtk_container_set_border_width(GTK_CONTAINER(gWindow), 12);
+ g_signal_connect(gWindow, "delete-event", G_CALLBACK(WindowDeleted), 0);
+ g_signal_connect(gWindow, "key_press_event", G_CALLBACK(check_escape),
+ nullptr);
+
+ GtkWidget* vbox = gtk_vbox_new(FALSE, 6);
+ gtk_container_add(GTK_CONTAINER(gWindow), vbox);
+
+ GtkWidget* titleLabel = gtk_label_new("");
+ gtk_box_pack_start(GTK_BOX(vbox), titleLabel, FALSE, FALSE, 0);
+ gtk_misc_set_alignment(GTK_MISC(titleLabel), 0, 0.5);
+ char* markup =
+ g_strdup_printf("<b>%s</b>", gStrings[ST_CRASHREPORTERHEADER].c_str());
+ gtk_label_set_markup(GTK_LABEL(titleLabel), markup);
+ g_free(markup);
+
+ GtkWidget* descriptionLabel =
+ gtk_label_new(gStrings[ST_CRASHREPORTERDESCRIPTION].c_str());
+ gtk_box_pack_start(GTK_BOX(vbox), descriptionLabel, TRUE, TRUE, 0);
+ // force the label to line wrap
+ gtk_label_set_max_width_chars(GTK_LABEL(descriptionLabel),
+ LABEL_MAX_CHAR_WIDTH);
+ gtk_label_set_line_wrap(GTK_LABEL(descriptionLabel), TRUE);
+ gtk_label_set_selectable(GTK_LABEL(descriptionLabel), TRUE);
+ gtk_misc_set_alignment(GTK_MISC(descriptionLabel), 0, 0.5);
+
+ // this is honestly how they suggest you indent a section
+ GtkWidget* indentBox = gtk_hbox_new(FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(vbox), indentBox, FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(indentBox), gtk_label_new(""), FALSE, FALSE, 6);
+
+ GtkWidget* innerVBox1 = gtk_vbox_new(FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(indentBox), innerVBox1, TRUE, TRUE, 0);
+
+ gSubmitReportCheck =
+ gtk_check_button_new_with_label(gStrings[ST_CHECKSUBMIT].c_str());
+ gtk_box_pack_start(GTK_BOX(innerVBox1), gSubmitReportCheck, FALSE, FALSE, 0);
+ g_signal_connect(gSubmitReportCheck, "clicked",
+ G_CALLBACK(SubmitReportChecked), 0);
+
+ // indent again, below the "submit report" checkbox
+ GtkWidget* indentBox2 = gtk_hbox_new(FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(innerVBox1), indentBox2, FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(indentBox2), gtk_label_new(""), FALSE, FALSE, 6);
+
+ GtkWidget* innerVBox = gtk_vbox_new(FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(indentBox2), innerVBox, TRUE, TRUE, 0);
+ gtk_box_set_spacing(GTK_BOX(innerVBox), 6);
+
+ GtkWidget* viewReportButtonBox = gtk_hbutton_box_new();
+ gtk_box_pack_start(GTK_BOX(innerVBox), viewReportButtonBox, FALSE, FALSE, 0);
+ gtk_box_set_spacing(GTK_BOX(viewReportButtonBox), 6);
+ gtk_button_box_set_layout(GTK_BUTTON_BOX(viewReportButtonBox),
+ GTK_BUTTONBOX_START);
+
+ gViewReportButton =
+ gtk_button_new_with_label(gStrings[ST_VIEWREPORT].c_str());
+ gtk_box_pack_start(GTK_BOX(viewReportButtonBox), gViewReportButton, FALSE,
+ FALSE, 0);
+ g_signal_connect(gViewReportButton, "clicked", G_CALLBACK(ViewReportClicked),
+ 0);
+
+ GtkWidget* scrolled = gtk_scrolled_window_new(0, 0);
+ gtk_container_add(GTK_CONTAINER(innerVBox), scrolled);
+ gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
+ GTK_POLICY_NEVER, GTK_POLICY_ALWAYS);
+ gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled),
+ GTK_SHADOW_IN);
+ gtk_scrolled_window_set_min_content_height(GTK_SCROLLED_WINDOW(scrolled),
+ 100);
+
+ gCommentTextLabel = gtk_label_new(gStrings[ST_COMMENTGRAYTEXT].c_str());
+ gCommentText = gtk_text_view_new();
+ gtk_label_set_mnemonic_widget(GTK_LABEL(gCommentTextLabel), gCommentText);
+ gtk_text_view_set_accepts_tab(GTK_TEXT_VIEW(gCommentText), FALSE);
+ g_signal_connect(gCommentText, "focus-in-event",
+ G_CALLBACK(CommentFocusChange), 0);
+ g_signal_connect(gCommentText, "focus-out-event",
+ G_CALLBACK(CommentFocusChange), 0);
+
+ GtkTextBuffer* commentBuffer =
+ gtk_text_view_get_buffer(GTK_TEXT_VIEW(gCommentText));
+ g_signal_connect(commentBuffer, "changed", G_CALLBACK(CommentChanged), 0);
+ g_signal_connect(commentBuffer, "insert-text", G_CALLBACK(CommentInsert), 0);
+
+ gtk_container_add(GTK_CONTAINER(scrolled), gCommentText);
+ gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(gCommentText), GTK_WRAP_WORD_CHAR);
+ gtk_widget_set_size_request(GTK_WIDGET(gCommentText), -1, 100);
+
+ if (gQueryParameters.isMember("URL")) {
+ gIncludeURLCheck =
+ gtk_check_button_new_with_label(gStrings[ST_CHECKURL].c_str());
+ gtk_box_pack_start(GTK_BOX(innerVBox), gIncludeURLCheck, FALSE, FALSE, 0);
+ g_signal_connect(gIncludeURLCheck, "clicked", G_CALLBACK(IncludeURLClicked),
+ 0);
+ // on by default
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gIncludeURLCheck), TRUE);
+ }
+
+ GtkWidget* progressBox = gtk_hbox_new(FALSE, 6);
+ gtk_box_pack_start(GTK_BOX(vbox), progressBox, TRUE, TRUE, 0);
+
+ // Get the throbber image from alongside the executable
+ char* dir = g_path_get_dirname(gArgv[0]);
+ char* path = g_build_filename(dir, "Throbber-small.gif", nullptr);
+ g_free(dir);
+ gThrobber = gtk_image_new_from_file(path);
+ gtk_box_pack_start(GTK_BOX(progressBox), gThrobber, FALSE, FALSE, 0);
+
+ gProgressLabel = gtk_label_new(gStrings[ST_REPORTPRESUBMIT].c_str());
+ gtk_box_pack_start(GTK_BOX(progressBox), gProgressLabel, TRUE, TRUE, 0);
+ // force the label to line wrap
+ gtk_label_set_max_width_chars(GTK_LABEL(gProgressLabel),
+ LABEL_MAX_CHAR_WIDTH);
+ gtk_label_set_line_wrap(GTK_LABEL(gProgressLabel), TRUE);
+
+ GtkWidget* buttonBox = gtk_hbutton_box_new();
+ gtk_box_pack_end(GTK_BOX(vbox), buttonBox, FALSE, FALSE, 0);
+ gtk_box_set_spacing(GTK_BOX(buttonBox), 6);
+ gtk_button_box_set_layout(GTK_BUTTON_BOX(buttonBox), GTK_BUTTONBOX_END);
+
+ gCloseButton = gtk_button_new_with_label(gStrings[ST_QUIT].c_str());
+ gtk_box_pack_start(GTK_BOX(buttonBox), gCloseButton, FALSE, FALSE, 0);
+ gtk_widget_set_can_default(gCloseButton, TRUE);
+ g_signal_connect(gCloseButton, "clicked", G_CALLBACK(CloseClicked), 0);
+
+ gRestartButton = 0;
+ if (!restartArgs.empty()) {
+ gRestartButton = gtk_button_new_with_label(gStrings[ST_RESTART].c_str());
+ gtk_box_pack_start(GTK_BOX(buttonBox), gRestartButton, FALSE, FALSE, 0);
+ gtk_widget_set_can_default(gRestartButton, TRUE);
+ g_signal_connect(gRestartButton, "clicked", G_CALLBACK(RestartClicked), 0);
+ }
+
+ gtk_widget_grab_focus(gSubmitReportCheck);
+
+ gtk_widget_grab_default(gRestartButton ? gRestartButton : gCloseButton);
+
+ LoadSettings();
+
+ UpdateSubmit();
+
+ UpdateHintText(gCommentText, FALSE, &gCommentFieldHint,
+ gStrings[ST_COMMENTGRAYTEXT].c_str());
+
+ gtk_widget_show_all(gWindow);
+ // stick this here to avoid the show_all above...
+ gtk_widget_hide(gThrobber);
+
+ gtk_main();
+
+ return gDidTrySend;
+}
diff --git a/toolkit/crashreporter/client/crashreporter_osx.h b/toolkit/crashreporter/client/crashreporter_osx.h
new file mode 100644
index 0000000000..19282a3fe6
--- /dev/null
+++ b/toolkit/crashreporter/client/crashreporter_osx.h
@@ -0,0 +1,107 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/. */
+
+#ifndef CRASHREPORTER_OSX_H__
+#define CRASHREPORTER_OSX_H__
+
+#include <Cocoa/Cocoa.h>
+#include "HTTPMultipartUpload.h"
+#include "crashreporter.h"
+#include "json/json.h"
+
+// Defined below
+@class TextViewWithPlaceHolder;
+
+@interface CrashReporterUI : NSObject {
+ IBOutlet NSWindow* mWindow;
+
+ /* Crash reporter view */
+ IBOutlet NSTextField* mHeaderLabel;
+ IBOutlet NSTextField* mDescriptionLabel;
+ IBOutlet NSButton* mViewReportButton;
+ IBOutlet NSScrollView* mCommentScrollView;
+ IBOutlet TextViewWithPlaceHolder* mCommentText;
+ IBOutlet NSButton* mSubmitReportButton;
+ IBOutlet NSButton* mIncludeURLButton;
+ IBOutlet NSButton* mEmailMeButton;
+ IBOutlet NSTextField* mEmailText;
+ IBOutlet NSButton* mCloseButton;
+ IBOutlet NSButton* mRestartButton;
+ IBOutlet NSProgressIndicator* mProgressIndicator;
+ IBOutlet NSTextField* mProgressText;
+
+ /* Error view */
+ IBOutlet NSView* mErrorView;
+ IBOutlet NSTextField* mErrorHeaderLabel;
+ IBOutlet NSTextField* mErrorLabel;
+ IBOutlet NSButton* mErrorCloseButton;
+
+ /* For "show info" alert */
+ IBOutlet NSWindow* mViewReportWindow;
+ IBOutlet NSTextView* mViewReportTextView;
+ IBOutlet NSButton* mViewReportOkButton;
+
+ HTTPMultipartUpload* mPost;
+}
+
+- (void)showCrashUI:(const StringTable&)files
+ queryParameters:(const Json::Value&)queryParameters
+ sendURL:(const std::string&)sendURL;
+- (void)showErrorUI:(const std::string&)message;
+- (void)showReportInfo;
+- (void)maybeSubmitReport;
+- (void)closeMeDown:(id)unused;
+
+- (IBAction)submitReportClicked:(id)sender;
+- (IBAction)viewReportClicked:(id)sender;
+- (IBAction)viewReportOkClicked:(id)sender;
+- (IBAction)closeClicked:(id)sender;
+- (IBAction)restartClicked:(id)sender;
+- (IBAction)includeURLClicked:(id)sender;
+
+- (void)textDidChange:(NSNotification*)aNotification;
+- (BOOL)textView:(NSTextView*)aTextView
+ shouldChangeTextInRange:(NSRange)affectedCharRange
+ replacementString:(NSString*)replacementString;
+
+- (void)doInitialResizing;
+- (float)setStringFitVertically:(NSControl*)control
+ string:(NSString*)str
+ resizeWindow:(BOOL)resizeWindow;
+- (void)setView:(NSView*)v animate:(BOOL)animate;
+- (void)enableControls:(BOOL)enabled;
+- (void)updateSubmit;
+- (void)updateURL;
+- (void)updateEmail;
+- (void)sendReport;
+- (bool)setupPost;
+- (void)uploadThread:(HTTPMultipartUpload*)post;
+- (void)uploadComplete:(NSData*)data;
+
+- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication*)theApplication;
+- (void)applicationWillTerminate:(NSNotification*)aNotification;
+
+@end
+
+/*
+ * Subclass NSTextView to provide a text view with placeholder text.
+ * Also provide a setEnabled implementation.
+ */
+@interface TextViewWithPlaceHolder : NSTextView {
+ NSMutableAttributedString* mPlaceHolderString;
+}
+
+- (BOOL)becomeFirstResponder;
+- (void)drawRect:(NSRect)rect;
+- (BOOL)resignFirstResponder;
+- (void)setPlaceholder:(NSString*)placeholder;
+- (void)insertTab:(id)sender;
+- (void)insertBacktab:(id)sender;
+- (void)setEnabled:(BOOL)enabled;
+- (void)dealloc;
+
+@end
+
+#endif
diff --git a/toolkit/crashreporter/client/crashreporter_osx.mm b/toolkit/crashreporter/client/crashreporter_osx.mm
new file mode 100644
index 0000000000..38b3349a04
--- /dev/null
+++ b/toolkit/crashreporter/client/crashreporter_osx.mm
@@ -0,0 +1,762 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/. */
+
+#import <Cocoa/Cocoa.h>
+#import <CoreFoundation/CoreFoundation.h>
+#include "crashreporter.h"
+#include "crashreporter_osx.h"
+#include <crt_externs.h>
+#include <spawn.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <sstream>
+
+using std::ostringstream;
+using std::string;
+using std::vector;
+
+using namespace CrashReporter;
+
+static NSAutoreleasePool* gMainPool;
+static CrashReporterUI* gUI = 0;
+static StringTable gFiles;
+static Json::Value gQueryParameters;
+static string gURLParameter;
+static string gSendURL;
+static vector<string> gRestartArgs;
+static bool gDidTrySend = false;
+static bool gRTLlayout = false;
+
+static cpu_type_t pref_cpu_types[2] = {
+#if defined(__i386__)
+ CPU_TYPE_X86,
+#elif defined(__x86_64__)
+ CPU_TYPE_X86_64,
+#elif defined(__ppc__)
+ CPU_TYPE_POWERPC,
+#elif defined(__aarch64__)
+ CPU_TYPE_ARM64,
+#endif
+ CPU_TYPE_ANY};
+
+#define NSSTR(s) [NSString stringWithUTF8String:(s).c_str()]
+
+static NSString* Str(const char* aName) {
+ string str = gStrings[aName];
+ if (str.empty()) str = "?";
+ return NSSTR(str);
+}
+
+static bool RestartApplication() {
+ vector<char*> argv(gRestartArgs.size() + 1);
+
+ posix_spawnattr_t spawnattr;
+ if (posix_spawnattr_init(&spawnattr) != 0) {
+ return false;
+ }
+
+ // Set spawn attributes.
+ size_t attr_count = sizeof(pref_cpu_types) / sizeof(pref_cpu_types[0]);
+ size_t attr_ocount = 0;
+ if (posix_spawnattr_setbinpref_np(&spawnattr, attr_count, pref_cpu_types, &attr_ocount) != 0 ||
+ attr_ocount != attr_count) {
+ posix_spawnattr_destroy(&spawnattr);
+ return false;
+ }
+
+ unsigned int i;
+ for (i = 0; i < gRestartArgs.size(); i++) {
+ argv[i] = (char*)gRestartArgs[i].c_str();
+ }
+ argv[i] = 0;
+
+ char** env = NULL;
+ char*** nsEnv = _NSGetEnviron();
+ if (nsEnv) env = *nsEnv;
+ int result = posix_spawnp(NULL, argv[0], NULL, &spawnattr, &argv[0], env);
+
+ posix_spawnattr_destroy(&spawnattr);
+
+ return result == 0;
+}
+
+@implementation CrashReporterUI
+
+- (void)awakeFromNib {
+ gUI = self;
+ [mWindow center];
+
+ [mWindow setTitle:[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleName"]];
+ [NSApp activateIgnoringOtherApps:YES];
+}
+
+- (void)showCrashUI:(const StringTable&)files
+ queryParameters:(const Json::Value&)queryParameters
+ sendURL:(const string&)sendURL {
+ gFiles = files;
+ gQueryParameters = queryParameters;
+ gSendURL = sendURL;
+
+ if (gAutoSubmit) {
+ gDidTrySend = true;
+ [self sendReport];
+ return;
+ }
+
+ [mWindow setTitle:Str(ST_CRASHREPORTERTITLE)];
+ [mHeaderLabel setStringValue:Str(ST_CRASHREPORTERHEADER)];
+
+ NSRect viewReportFrame = [mViewReportButton frame];
+ [mViewReportButton setTitle:Str(ST_VIEWREPORT)];
+ [mViewReportButton sizeToFit];
+ if (gRTLlayout) {
+ // sizeToFit will keep the left side fixed, so realign
+ float oldWidth = viewReportFrame.size.width;
+ viewReportFrame = [mViewReportButton frame];
+ viewReportFrame.origin.x += oldWidth - viewReportFrame.size.width;
+ [mViewReportButton setFrame:viewReportFrame];
+ }
+
+ [mSubmitReportButton setTitle:Str(ST_CHECKSUBMIT)];
+ [mIncludeURLButton setTitle:Str(ST_CHECKURL)];
+ [mViewReportOkButton setTitle:Str(ST_OK)];
+
+ [mCommentText setPlaceholder:Str(ST_COMMENTGRAYTEXT)];
+ if (gRTLlayout) [mCommentText toggleBaseWritingDirection:self];
+
+ if (gQueryParameters.isMember("URL")) {
+ // save the URL value in case the checkbox gets unchecked
+ gURLParameter = gQueryParameters["URL"].asString();
+ } else {
+ // no URL specified, hide checkbox
+ [mIncludeURLButton removeFromSuperview];
+ // shrink window to fit
+ NSRect frame = [mWindow frame];
+ NSRect includeURLFrame = [mIncludeURLButton frame];
+ NSRect emailFrame = [mEmailMeButton frame];
+ int buttonMask = [mViewReportButton autoresizingMask];
+ int checkMask = [mSubmitReportButton autoresizingMask];
+ int commentScrollMask = [mCommentScrollView autoresizingMask];
+
+ [mViewReportButton setAutoresizingMask:NSViewMinYMargin];
+ [mSubmitReportButton setAutoresizingMask:NSViewMinYMargin];
+ [mCommentScrollView setAutoresizingMask:NSViewMinYMargin];
+
+ // remove all the space in between
+ frame.size.height -= includeURLFrame.origin.y - emailFrame.origin.y;
+ [mWindow setFrame:frame display:true animate:NO];
+
+ [mViewReportButton setAutoresizingMask:buttonMask];
+ [mSubmitReportButton setAutoresizingMask:checkMask];
+ [mCommentScrollView setAutoresizingMask:commentScrollMask];
+ }
+
+ // resize some buttons horizontally and possibly some controls vertically
+ [self doInitialResizing];
+
+ // load default state of submit checkbox
+ // we don't just do this via IB because we want the default to be
+ // off a certain percentage of the time
+ BOOL submitChecked = YES;
+ NSUserDefaults* userDefaults = [NSUserDefaults standardUserDefaults];
+ if (nil != [userDefaults objectForKey:@"submitReport"]) {
+ submitChecked = [userDefaults boolForKey:@"submitReport"];
+ } else {
+ [userDefaults setBool:submitChecked forKey:@"submitReport"];
+ }
+ [mSubmitReportButton setState:(submitChecked ? NSOnState : NSOffState)];
+
+ // load default state of include URL checkbox
+ BOOL includeChecked = YES;
+ if (nil != [userDefaults objectForKey:@"IncludeURL"]) {
+ includeChecked = [userDefaults boolForKey:@"IncludeURL"];
+ } else {
+ [userDefaults setBool:includeChecked forKey:@"IncludeURL"];
+ }
+ [mIncludeURLButton setState:(includeChecked ? NSOnState : NSOffState)];
+
+ [self updateSubmit];
+ [self updateURL];
+ [self updateEmail];
+
+ [mWindow makeKeyAndOrderFront:nil];
+}
+
+- (void)showErrorUI:(const string&)message {
+ [self setView:mErrorView animate:NO];
+
+ [mErrorHeaderLabel setStringValue:Str(ST_CRASHREPORTERHEADER)];
+ [self setStringFitVertically:mErrorLabel string:NSSTR(message) resizeWindow:YES];
+ [mErrorCloseButton setTitle:Str(ST_OK)];
+
+ [mErrorCloseButton setKeyEquivalent:@"\r"];
+ [mWindow makeFirstResponder:mErrorCloseButton];
+ [mWindow makeKeyAndOrderFront:nil];
+}
+
+- (void)showReportInfo {
+ NSDictionary* boldAttr = @{
+ NSFontAttributeName : [NSFont boldSystemFontOfSize:[NSFont smallSystemFontSize]],
+ NSForegroundColorAttributeName : NSColor.textColor,
+ };
+ NSDictionary* normalAttr = @{
+ NSFontAttributeName : [NSFont systemFontOfSize:[NSFont smallSystemFontSize]],
+ NSForegroundColorAttributeName : NSColor.textColor,
+ };
+
+ [mViewReportTextView setString:@""];
+ for (Json::ValueConstIterator iter = gQueryParameters.begin(); iter != gQueryParameters.end();
+ ++iter) {
+ NSAttributedString* key = [[NSAttributedString alloc] initWithString:NSSTR(iter.name() + ": ")
+ attributes:boldAttr];
+ string str;
+ if (iter->isString()) {
+ str = iter->asString();
+ } else {
+ Json::StreamWriterBuilder builder;
+ builder["indentation"] = "";
+ str = writeString(builder, *iter);
+ }
+ NSAttributedString* value = [[NSAttributedString alloc] initWithString:NSSTR(str + "\n")
+ attributes:normalAttr];
+ [[mViewReportTextView textStorage] appendAttributedString:key];
+ [[mViewReportTextView textStorage] appendAttributedString:value];
+ [key release];
+ [value release];
+ }
+
+ NSAttributedString* extra =
+ [[NSAttributedString alloc] initWithString:NSSTR("\n" + gStrings[ST_EXTRAREPORTINFO])
+ attributes:normalAttr];
+ [[mViewReportTextView textStorage] appendAttributedString:extra];
+ [extra release];
+}
+
+- (void)maybeSubmitReport {
+ if ([mSubmitReportButton state] == NSOnState) {
+ [self setStringFitVertically:mProgressText string:Str(ST_REPORTDURINGSUBMIT) resizeWindow:YES];
+ // disable all the controls
+ [self enableControls:NO];
+ [mSubmitReportButton setEnabled:NO];
+ [mRestartButton setEnabled:NO];
+ [mCloseButton setEnabled:NO];
+ [mProgressIndicator startAnimation:self];
+ gDidTrySend = true;
+ [self sendReport];
+ } else {
+ [NSApp terminate:self];
+ }
+}
+
+- (void)closeMeDown:(id)unused {
+ [NSApp terminate:self];
+}
+
+- (IBAction)submitReportClicked:(id)sender {
+ [self updateSubmit];
+ NSUserDefaults* userDefaults = [NSUserDefaults standardUserDefaults];
+ [userDefaults setBool:([mSubmitReportButton state] == NSOnState) forKey:@"submitReport"];
+ [userDefaults synchronize];
+}
+
+- (IBAction)viewReportClicked:(id)sender {
+ [self showReportInfo];
+ [NSApp beginSheet:mViewReportWindow
+ modalForWindow:mWindow
+ modalDelegate:nil
+ didEndSelector:nil
+ contextInfo:nil];
+}
+
+- (IBAction)viewReportOkClicked:(id)sender {
+ [mViewReportWindow orderOut:nil];
+ [NSApp endSheet:mViewReportWindow];
+}
+
+- (IBAction)closeClicked:(id)sender {
+ [self maybeSubmitReport];
+}
+
+- (IBAction)restartClicked:(id)sender {
+ RestartApplication();
+ [self maybeSubmitReport];
+}
+
+- (IBAction)includeURLClicked:(id)sender {
+ [self updateURL];
+ NSUserDefaults* userDefaults = [NSUserDefaults standardUserDefaults];
+ [userDefaults setBool:([mIncludeURLButton state] == NSOnState) forKey:@"IncludeURL"];
+ [userDefaults synchronize];
+}
+
+- (void)textDidChange:(NSNotification*)aNotification {
+ // update comment parameter
+ if ([[[mCommentText textStorage] mutableString] length] > 0)
+ gQueryParameters["Comments"] = [[[mCommentText textStorage] mutableString] UTF8String];
+ else
+ gQueryParameters.removeMember("Comments");
+}
+
+// Limit the comment field to 500 bytes in UTF-8
+- (BOOL)textView:(NSTextView*)aTextView
+ shouldChangeTextInRange:(NSRange)affectedCharRange
+ replacementString:(NSString*)replacementString {
+ // current string length + replacement text length - replaced range length
+ if (([[aTextView string] lengthOfBytesUsingEncoding:NSUTF8StringEncoding] +
+ [replacementString lengthOfBytesUsingEncoding:NSUTF8StringEncoding] -
+ [[[aTextView string] substringWithRange:affectedCharRange]
+ lengthOfBytesUsingEncoding:NSUTF8StringEncoding]) > MAX_COMMENT_LENGTH) {
+ return NO;
+ }
+ return YES;
+}
+
+- (void)doInitialResizing {
+ NSRect windowFrame = [mWindow frame];
+ NSRect restartFrame = [mRestartButton frame];
+ NSRect closeFrame = [mCloseButton frame];
+ // resize close button to fit text
+ float oldCloseWidth = closeFrame.size.width;
+ [mCloseButton setTitle:Str(ST_QUIT)];
+ [mCloseButton sizeToFit];
+ closeFrame = [mCloseButton frame];
+ // move close button left if it grew
+ if (!gRTLlayout) {
+ closeFrame.origin.x -= closeFrame.size.width - oldCloseWidth;
+ }
+
+ if (gRestartArgs.size() == 0) {
+ [mRestartButton removeFromSuperview];
+ if (!gRTLlayout) {
+ closeFrame.origin.x =
+ restartFrame.origin.x + (restartFrame.size.width - closeFrame.size.width);
+ } else {
+ closeFrame.origin.x = restartFrame.origin.x;
+ }
+ [mCloseButton setFrame:closeFrame];
+ [mCloseButton setKeyEquivalent:@"\r"];
+ } else {
+ [mRestartButton setTitle:Str(ST_RESTART)];
+ // resize "restart" button
+ float oldRestartWidth = restartFrame.size.width;
+ [mRestartButton sizeToFit];
+ restartFrame = [mRestartButton frame];
+ if (!gRTLlayout) {
+ // move left by the amount that the button grew
+ restartFrame.origin.x -= restartFrame.size.width - oldRestartWidth;
+ closeFrame.origin.x -= restartFrame.size.width - oldRestartWidth;
+ } else {
+ // shift the close button right in RTL
+ closeFrame.origin.x += restartFrame.size.width - oldRestartWidth;
+ }
+ [mRestartButton setFrame:restartFrame];
+ [mCloseButton setFrame:closeFrame];
+ // possibly resize window if both buttons no longer fit
+ // leave 20 px from either side of the window, and 12 px
+ // between the buttons
+ float neededWidth = closeFrame.size.width + restartFrame.size.width + 2 * 20 + 12;
+
+ if (neededWidth > windowFrame.size.width) {
+ windowFrame.size.width = neededWidth;
+ [mWindow setFrame:windowFrame display:true animate:NO];
+ }
+ [mRestartButton setKeyEquivalent:@"\r"];
+ }
+
+ NSButton* checkboxes[] = {mSubmitReportButton, mIncludeURLButton};
+
+ for (auto checkbox : checkboxes) {
+ NSRect frame = [checkbox frame];
+ [checkbox sizeToFit];
+ if (gRTLlayout) {
+ // sizeToFit will keep the left side fixed, so realign
+ float oldWidth = frame.size.width;
+ frame = [checkbox frame];
+ frame.origin.x += oldWidth - frame.size.width;
+ [checkbox setFrame:frame];
+ }
+ // keep existing spacing on left side, + 20 px spare on right
+ float neededWidth = frame.origin.x + checkbox.intrinsicContentSize.width + 20;
+ if (neededWidth > windowFrame.size.width) {
+ windowFrame.size.width = neededWidth;
+ [mWindow setFrame:windowFrame display:true animate:NO];
+ }
+ }
+
+ // do this down here because we may have made the window wider
+ // up above
+ [self setStringFitVertically:mDescriptionLabel
+ string:Str(ST_CRASHREPORTERDESCRIPTION)
+ resizeWindow:YES];
+
+ // now pin all the controls (except quit/submit) in place,
+ // if we lengthen the window after this, it's just to lengthen
+ // the progress text, so nothing above that text should move.
+ NSView* views[] = {mSubmitReportButton, mViewReportButton, mCommentScrollView,
+ mIncludeURLButton, mProgressIndicator, mProgressText};
+ for (auto view : views) {
+ [view setAutoresizingMask:NSViewMinYMargin];
+ }
+}
+
+- (float)setStringFitVertically:(NSControl*)control
+ string:(NSString*)str
+ resizeWindow:(BOOL)resizeWindow {
+ // hack to make the text field grow vertically
+ NSRect frame = [control frame];
+ float oldHeight = frame.size.height;
+
+ frame.size.height = 10000;
+ NSSize oldCellSize = [[control cell] cellSizeForBounds:frame];
+ [control setStringValue:str];
+ NSSize newCellSize = [[control cell] cellSizeForBounds:frame];
+
+ float delta = newCellSize.height - oldCellSize.height;
+ frame.origin.y -= delta;
+ frame.size.height = oldHeight + delta;
+ [control setFrame:frame];
+
+ if (resizeWindow) {
+ NSRect frame = [mWindow frame];
+ frame.origin.y -= delta;
+ frame.size.height += delta;
+ [mWindow setFrame:frame display:true animate:NO];
+ }
+
+ return delta;
+}
+
+- (void)setView:(NSView*)v animate:(BOOL)animate {
+ NSRect frame = [mWindow frame];
+
+ NSRect oldViewFrame = [[mWindow contentView] frame];
+ NSRect newViewFrame = [v frame];
+
+ frame.origin.y += oldViewFrame.size.height - newViewFrame.size.height;
+ frame.size.height -= oldViewFrame.size.height - newViewFrame.size.height;
+
+ frame.origin.x += oldViewFrame.size.width - newViewFrame.size.width;
+ frame.size.width -= oldViewFrame.size.width - newViewFrame.size.width;
+
+ [mWindow setContentView:v];
+ [mWindow setFrame:frame display:true animate:animate];
+}
+
+- (void)enableControls:(BOOL)enabled {
+ [mViewReportButton setEnabled:enabled];
+ [mIncludeURLButton setEnabled:enabled];
+ [mCommentText setEnabled:enabled];
+ [mCommentScrollView setHasVerticalScroller:enabled];
+}
+
+- (void)updateSubmit {
+ if ([mSubmitReportButton state] == NSOnState) {
+ [self setStringFitVertically:mProgressText string:Str(ST_REPORTPRESUBMIT) resizeWindow:YES];
+ [mProgressText setHidden:NO];
+ // enable all the controls
+ [self enableControls:YES];
+ } else {
+ // not submitting, disable all the controls under
+ // the submit checkbox, and hide the status text
+ [mProgressText setHidden:YES];
+ [self enableControls:NO];
+ }
+}
+
+- (void)updateURL {
+ if ([mIncludeURLButton state] == NSOnState && !gURLParameter.empty()) {
+ gQueryParameters["URL"] = gURLParameter;
+ } else {
+ gQueryParameters.removeMember("URL");
+ }
+}
+
+- (void)updateEmail {
+ // In order to remove the email fields, we have to edit the .nib files which
+ // we can't do with current xcode so we make them hidden; updating the
+ // crashreporter interface for mac is covered in bug #1696164
+ [mEmailMeButton setHidden:YES];
+ [mEmailText setHidden:YES];
+}
+
+- (void)sendReport {
+ if (![self setupPost]) {
+ LogMessage("Crash report submission failed: could not set up POST data");
+
+ if (gAutoSubmit) {
+ [NSApp terminate:self];
+ }
+
+ [self setStringFitVertically:mProgressText string:Str(ST_SUBMITFAILED) resizeWindow:YES];
+ // quit after 5 seconds
+ [self performSelector:@selector(closeMeDown:) withObject:nil afterDelay:5.0];
+ }
+
+ [NSThread detachNewThreadSelector:@selector(uploadThread:) toTarget:self withObject:mPost];
+}
+
+- (bool)setupPost {
+ NSURL* url =
+ [NSURL URLWithString:[NSSTR(gSendURL)
+ stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
+ if (!url) return false;
+
+ mPost = [[HTTPMultipartUpload alloc] initWithURL:url];
+ if (!mPost) return false;
+
+ for (StringTable::const_iterator i = gFiles.begin(); i != gFiles.end(); i++) {
+ [mPost addFileAtPath:NSSTR(i->second) name:NSSTR(i->first)];
+ }
+
+ Json::StreamWriterBuilder builder;
+ builder["indentation"] = "";
+ string output = writeString(builder, gQueryParameters).append("\r\n");
+ NSMutableString* parameters = [[NSMutableString alloc] initWithUTF8String:output.c_str()];
+
+ [mPost setParameters:parameters];
+ [parameters release];
+
+ return true;
+}
+
+- (void)uploadComplete:(NSData*)data {
+ NSHTTPURLResponse* response = [mPost response];
+ [mPost release];
+
+ bool success;
+ string reply;
+ if (!data || !response || [response statusCode] != 200) {
+ success = false;
+ reply = "";
+
+ // if data is nil, we probably logged an error in uploadThread
+ if (data != nil && response != nil) {
+ ostringstream message;
+ message << "Crash report submission failed: server returned status " << [response statusCode];
+ LogMessage(message.str());
+ }
+ } else {
+ success = true;
+ LogMessage("Crash report submitted successfully");
+
+ NSString* encodingName = [response textEncodingName];
+ NSStringEncoding encoding;
+ if (encodingName) {
+ encoding = CFStringConvertEncodingToNSStringEncoding(
+ CFStringConvertIANACharSetNameToEncoding((CFStringRef)encodingName));
+ } else {
+ encoding = NSISOLatin1StringEncoding;
+ }
+ NSString* r = [[NSString alloc] initWithData:data encoding:encoding];
+ reply = [r UTF8String];
+ [r release];
+ }
+
+ SendCompleted(success, reply);
+
+ if (gAutoSubmit) {
+ [NSApp terminate:self];
+ }
+
+ [mProgressIndicator stopAnimation:self];
+ if (success) {
+ [self setStringFitVertically:mProgressText string:Str(ST_REPORTSUBMITSUCCESS) resizeWindow:YES];
+ } else {
+ [self setStringFitVertically:mProgressText string:Str(ST_SUBMITFAILED) resizeWindow:YES];
+ }
+ // quit after 5 seconds
+ [self performSelector:@selector(closeMeDown:) withObject:nil afterDelay:5.0];
+}
+
+- (void)uploadThread:(HTTPMultipartUpload*)post {
+ NSAutoreleasePool* autoreleasepool = [[NSAutoreleasePool alloc] init];
+ NSError* error = nil;
+ NSData* data = [post send:&error];
+ if (error) {
+ data = nil;
+ NSString* errorDesc = [error localizedDescription];
+ string message = [errorDesc UTF8String];
+ LogMessage("Crash report submission failed: " + message);
+ }
+
+ [self performSelectorOnMainThread:@selector(uploadComplete:) withObject:data waitUntilDone:YES];
+
+ [autoreleasepool release];
+}
+
+// to get auto-quit when we close the window
+- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication*)theApplication {
+ return YES;
+}
+
+- (void)applicationWillTerminate:(NSNotification*)aNotification {
+ // since we use [NSApp terminate:] we never return to main,
+ // so do our cleanup here
+ if (!gDidTrySend) DeleteDump();
+}
+
+@end
+
+@implementation TextViewWithPlaceHolder
+
+- (BOOL)becomeFirstResponder {
+ [self setNeedsDisplay:YES];
+ return [super becomeFirstResponder];
+}
+
+- (void)drawRect:(NSRect)rect {
+ [super drawRect:rect];
+ if (mPlaceHolderString && [[self string] isEqualToString:@""] &&
+ self != [[self window] firstResponder])
+ [mPlaceHolderString drawInRect:[self frame]];
+}
+
+- (BOOL)resignFirstResponder {
+ [self setNeedsDisplay:YES];
+ return [super resignFirstResponder];
+}
+
+- (void)setPlaceholder:(NSString*)placeholder {
+ NSColor* txtColor = [NSColor disabledControlTextColor];
+ NSDictionary* txtDict =
+ [NSDictionary dictionaryWithObjectsAndKeys:txtColor, NSForegroundColorAttributeName, nil];
+ mPlaceHolderString = [[NSMutableAttributedString alloc] initWithString:placeholder
+ attributes:txtDict];
+ if (gRTLlayout)
+ [mPlaceHolderString setAlignment:NSTextAlignmentRight
+ range:NSMakeRange(0, [placeholder length])];
+}
+
+- (void)insertTab:(id)sender {
+ // don't actually want to insert tabs, just tab to next control
+ [[self window] selectNextKeyView:sender];
+}
+
+- (void)insertBacktab:(id)sender {
+ [[self window] selectPreviousKeyView:sender];
+}
+
+- (void)setEnabled:(BOOL)enabled {
+ [self setSelectable:enabled];
+ [self setEditable:enabled];
+ if (![[self string] isEqualToString:@""]) {
+ NSAttributedString* colorString;
+ NSColor* txtColor;
+ if (enabled)
+ txtColor = [NSColor textColor];
+ else
+ txtColor = [NSColor disabledControlTextColor];
+ NSDictionary* txtDict =
+ [NSDictionary dictionaryWithObjectsAndKeys:txtColor, NSForegroundColorAttributeName, nil];
+ colorString = [[NSAttributedString alloc] initWithString:[self string] attributes:txtDict];
+ [[self textStorage] setAttributedString:colorString];
+ [self setInsertionPointColor:txtColor];
+ [colorString release];
+ }
+}
+
+- (void)dealloc {
+ [mPlaceHolderString release];
+ [super dealloc];
+}
+
+@end
+
+/* === Crashreporter UI Functions === */
+
+bool UIInit() {
+ gMainPool = [[NSAutoreleasePool alloc] init];
+ [NSApplication sharedApplication];
+
+ if (gStrings.find("isRTL") != gStrings.end() && gStrings["isRTL"] == "yes") gRTLlayout = true;
+
+ if (gAutoSubmit) {
+ gUI = [[CrashReporterUI alloc] init];
+ } else {
+ [[NSBundle mainBundle] loadNibNamed:(gRTLlayout ? @"MainMenuRTL" : @"MainMenu")
+ owner:NSApp
+ topLevelObjects:nil];
+ }
+
+ return true;
+}
+
+void UIShutdown() { [gMainPool release]; }
+
+void UIShowDefaultUI() {
+ [gUI showErrorUI:gStrings[ST_CRASHREPORTERDEFAULT]];
+ [NSApp run];
+}
+
+bool UIShowCrashUI(const StringTable& files, const Json::Value& queryParameters,
+ const string& sendURL, const vector<string>& restartArgs) {
+ gRestartArgs = restartArgs;
+
+ [gUI showCrashUI:files queryParameters:queryParameters sendURL:sendURL];
+ [NSApp run];
+
+ return gDidTrySend;
+}
+
+void UIError_impl(const string& message) {
+ if (!gUI) {
+ // UI failed to initialize, printing is the best we can do
+ printf("Error: %s\n", message.c_str());
+ return;
+ }
+
+ [gUI showErrorUI:message];
+ [NSApp run];
+}
+
+bool UIGetIniPath(string& path) {
+ NSString* tmpPath = [NSString stringWithUTF8String:gArgv[0]];
+ NSString* iniName = [tmpPath lastPathComponent];
+ iniName = [iniName stringByAppendingPathExtension:@"ini"];
+ tmpPath = [tmpPath stringByDeletingLastPathComponent];
+ tmpPath = [tmpPath stringByDeletingLastPathComponent];
+ tmpPath = [tmpPath stringByAppendingPathComponent:@"Resources"];
+ tmpPath = [tmpPath stringByAppendingPathComponent:iniName];
+ path = [tmpPath UTF8String];
+ return true;
+}
+
+bool UIGetSettingsPath(const string& vendor, const string& product, string& settingsPath) {
+ NSArray* paths =
+ NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES);
+ NSString* destPath = [paths firstObject];
+
+ // Note that MacOS ignores the vendor when creating the profile hierarchy -
+ // all application preferences directories live alongside one another in
+ // ~/Library/Application Support/
+ destPath = [destPath stringByAppendingPathComponent:NSSTR(product)];
+ // Thunderbird stores its profile in ~/Library/Thunderbird,
+ // but we're going to put stuff in ~/Library/Application Support/Thunderbird
+ // anyway, so we have to ensure that path exists.
+ string tempPath = [destPath UTF8String];
+ if (!UIEnsurePathExists(tempPath)) return false;
+
+ destPath = [destPath stringByAppendingPathComponent:@"Crash Reports"];
+
+ settingsPath = [destPath UTF8String];
+
+ return true;
+}
+
+bool UIMoveFile(const string& file, const string& newfile) {
+ if (!rename(file.c_str(), newfile.c_str())) return true;
+ if (errno != EXDEV) return false;
+
+ NSFileManager* fileManager = [NSFileManager defaultManager];
+ NSString* source = [fileManager stringWithFileSystemRepresentation:file.c_str()
+ length:file.length()];
+ NSString* dest = [fileManager stringWithFileSystemRepresentation:newfile.c_str()
+ length:newfile.length()];
+ if (!source || !dest) return false;
+
+ [fileManager moveItemAtPath:source toPath:dest error:NULL];
+ return UIFileExists(newfile);
+}
diff --git a/toolkit/crashreporter/client/crashreporter_unix_common.cpp b/toolkit/crashreporter/client/crashreporter_unix_common.cpp
new file mode 100644
index 0000000000..0cecc6262a
--- /dev/null
+++ b/toolkit/crashreporter/client/crashreporter_unix_common.cpp
@@ -0,0 +1,139 @@
+/* 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 "crashreporter.h"
+
+#include <algorithm>
+#include <sys/wait.h>
+
+#include <dirent.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+using namespace CrashReporter;
+using std::ios_base;
+using std::sort;
+using std::string;
+using std::vector;
+
+struct FileData {
+ time_t timestamp;
+ string path;
+};
+
+static bool CompareFDTime(const FileData& fd1, const FileData& fd2) {
+ return fd1.timestamp > fd2.timestamp;
+}
+
+void UIPruneSavedDumps(const string& directory) {
+ DIR* dirfd = opendir(directory.c_str());
+ if (!dirfd) return;
+
+ vector<FileData> dumpfiles;
+
+ while (dirent* dir = readdir(dirfd)) {
+ FileData fd;
+ fd.path = directory + '/' + dir->d_name;
+ if (fd.path.size() < 5) continue;
+
+ if (fd.path.compare(fd.path.size() - 4, 4, ".dmp") != 0) continue;
+
+ struct stat st;
+ if (stat(fd.path.c_str(), &st)) {
+ closedir(dirfd);
+ return;
+ }
+
+ fd.timestamp = st.st_mtime;
+
+ dumpfiles.push_back(fd);
+ }
+
+ closedir(dirfd);
+
+ sort(dumpfiles.begin(), dumpfiles.end(), CompareFDTime);
+
+ while (dumpfiles.size() > kSaveCount) {
+ // get the path of the oldest file
+ string path = dumpfiles[dumpfiles.size() - 1].path;
+ UIDeleteFile(path.c_str());
+
+ // s/.dmp/.extra/
+ path.replace(path.size() - 4, 4, ".extra");
+ UIDeleteFile(path.c_str());
+
+ dumpfiles.pop_back();
+ }
+}
+
+bool UIRunProgram(const string& exename, const vector<string>& args,
+ bool wait) {
+ pid_t pid = fork();
+
+ if (pid == -1) {
+ return false;
+ } else if (pid == 0) {
+ // Child
+ size_t argvLen = args.size() + 2;
+ vector<char*> argv(argvLen);
+
+ argv[0] = const_cast<char*>(exename.c_str());
+
+ for (size_t i = 0; i < args.size(); i++) {
+ argv[i + 1] = const_cast<char*>(args[i].c_str());
+ }
+
+ argv[argvLen - 1] = nullptr;
+
+ // Run the program
+ int rv = execv(exename.c_str(), argv.data());
+
+ if (rv == -1) {
+ exit(EXIT_FAILURE);
+ }
+ } else {
+ // Parent
+ if (wait) {
+ waitpid(pid, nullptr, 0);
+ }
+ }
+
+ return true;
+}
+
+bool UIEnsurePathExists(const string& path) {
+ int ret = mkdir(path.c_str(), S_IRWXU);
+ int e = errno;
+ if (ret == -1 && e != EEXIST) return false;
+
+ return true;
+}
+
+bool UIFileExists(const string& path) {
+ struct stat sb;
+ int ret = stat(path.c_str(), &sb);
+ if (ret == -1 || !(sb.st_mode & S_IFREG)) return false;
+
+ return true;
+}
+
+bool UIDeleteFile(const string& file) { return (unlink(file.c_str()) != -1); }
+
+std::ifstream* UIOpenRead(const string& filename, ios_base::openmode mode) {
+ return new std::ifstream(filename.c_str(), mode);
+}
+
+std::ofstream* UIOpenWrite(const string& filename, ios_base::openmode mode) {
+ return new std::ofstream(filename.c_str(), mode);
+}
+
+string UIGetEnv(const string& name) {
+ const char* var = getenv(name.c_str());
+ if (var && *var) {
+ return var;
+ }
+
+ return "";
+}
diff --git a/toolkit/crashreporter/client/crashreporter_win.cpp b/toolkit/crashreporter/client/crashreporter_win.cpp
new file mode 100644
index 0000000000..e680aa37c9
--- /dev/null
+++ b/toolkit/crashreporter/client/crashreporter_win.cpp
@@ -0,0 +1,1295 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/. */
+
+#ifdef WIN32_LEAN_AND_MEAN
+# undef WIN32_LEAN_AND_MEAN
+#endif
+
+#include "crashreporter.h"
+
+#include <windows.h>
+#include <versionhelpers.h>
+#include <commctrl.h>
+#include <richedit.h>
+#include <shellapi.h>
+#include <shlobj.h>
+#include <shlwapi.h>
+#include <math.h>
+#include <set>
+#include <algorithm>
+#include "resource.h"
+#include "windows/sender/crash_report_sender.h"
+#include "common/windows/string_utils-inl.h"
+
+#define SUBMIT_REPORT_VALUE L"SubmitCrashReport"
+#define INCLUDE_URL_VALUE L"IncludeURL"
+
+#define SENDURL_ORIGINAL L"https://crash-reports.mozilla.com/submit"
+#define SENDURL_XPSP2 L"https://crash-reports-xpsp2.mozilla.com/submit"
+
+#define WM_UPLOADCOMPLETE WM_APP
+
+// Thanks, Windows.h :(
+#undef min
+#undef max
+
+using std::ifstream;
+using std::ios;
+using std::ios_base;
+using std::map;
+using std::ofstream;
+using std::set;
+using std::string;
+using std::vector;
+using std::wstring;
+
+using namespace CrashReporter;
+
+typedef struct {
+ HWND hDlg;
+ Json::Value queryParameters;
+ map<wstring, wstring> files;
+ wstring sendURL;
+
+ wstring serverResponse;
+} SendThreadData;
+
+/*
+ * Per http://msdn2.microsoft.com/en-us/library/ms645398(VS.85).aspx
+ * "The DLGTEMPLATEEX structure is not defined in any standard header file.
+ * The structure definition is provided here to explain the format of an
+ * extended template for a dialog box.
+ */
+typedef struct {
+ WORD dlgVer;
+ WORD signature;
+ DWORD helpID;
+ DWORD exStyle;
+ // There's more to this struct, but it has weird variable-length
+ // members, and I only actually need to touch exStyle on an existing
+ // instance, so I've omitted the rest.
+} DLGTEMPLATEEX;
+
+static HANDLE gThreadHandle;
+static SendThreadData gSendData = {
+ 0,
+};
+static vector<string> gRestartArgs;
+static Json::Value gQueryParameters;
+static wstring gCrashReporterKey(L"Software\\Mozilla\\Crash Reporter");
+static string gURLParameter;
+static int gCheckboxPadding = 6;
+static bool gRTLlayout = false;
+
+// When vertically resizing the dialog, these items should move down
+static set<UINT> gAttachedBottom;
+
+// Default set of items for gAttachedBottom
+static const UINT kDefaultAttachedBottom[] = {
+ IDC_SUBMITREPORTCHECK, IDC_VIEWREPORTBUTTON, IDC_COMMENTTEXT,
+ IDC_INCLUDEURLCHECK, IDC_PROGRESSTEXT, IDC_THROBBER,
+ IDC_CLOSEBUTTON, IDC_RESTARTBUTTON,
+};
+
+static wstring UTF8ToWide(const string& utf8, bool* success = 0);
+static DWORD WINAPI SendThreadProc(LPVOID param);
+
+static wstring Str(const char* key) { return UTF8ToWide(gStrings[key]); }
+
+/* === win32 helper functions === */
+
+static void DoInitCommonControls() {
+ INITCOMMONCONTROLSEX ic;
+ ic.dwSize = sizeof(INITCOMMONCONTROLSEX);
+ ic.dwICC = ICC_PROGRESS_CLASS;
+ InitCommonControlsEx(&ic);
+ // also get the rich edit control
+ LoadLibrary(L"Msftedit.dll");
+}
+
+static bool GetBoolValue(HKEY hRegKey, LPCTSTR valueName, DWORD* value) {
+ DWORD type, dataSize;
+ dataSize = sizeof(DWORD);
+ if (RegQueryValueEx(hRegKey, valueName, nullptr, &type, (LPBYTE)value,
+ &dataSize) == ERROR_SUCCESS &&
+ type == REG_DWORD)
+ return true;
+
+ return false;
+}
+
+static bool CheckBoolKey(const wchar_t* key, const wchar_t* valueName,
+ bool* enabled) {
+ /*
+ * NOTE! This code needs to stay in sync with the preference checking
+ * code in in nsExceptionHandler.cpp.
+ */
+ *enabled = false;
+ bool found = false;
+ HKEY hRegKey;
+ DWORD val;
+ // see if our reg key is set globally
+ if (RegOpenKey(HKEY_LOCAL_MACHINE, key, &hRegKey) == ERROR_SUCCESS) {
+ if (GetBoolValue(hRegKey, valueName, &val)) {
+ *enabled = (val == 1);
+ found = true;
+ }
+ RegCloseKey(hRegKey);
+ } else {
+ // look for it in user settings
+ if (RegOpenKey(HKEY_CURRENT_USER, key, &hRegKey) == ERROR_SUCCESS) {
+ if (GetBoolValue(hRegKey, valueName, &val)) {
+ *enabled = (val == 1);
+ found = true;
+ }
+ RegCloseKey(hRegKey);
+ }
+ }
+
+ return found;
+}
+
+static void SetBoolKey(const wchar_t* key, const wchar_t* value, bool enabled) {
+ /*
+ * NOTE! This code needs to stay in sync with the preference setting
+ * code in in nsExceptionHandler.cpp.
+ */
+ HKEY hRegKey;
+
+ if (RegCreateKey(HKEY_CURRENT_USER, key, &hRegKey) == ERROR_SUCCESS) {
+ DWORD data = (enabled ? 1 : 0);
+ RegSetValueEx(hRegKey, value, 0, REG_DWORD, (LPBYTE)&data, sizeof(data));
+ RegCloseKey(hRegKey);
+ }
+}
+
+static string FormatLastError() {
+ DWORD err = GetLastError();
+ LPWSTR s;
+ string message = "Crash report submission failed: ";
+ // odds are it's a WinInet error
+ HANDLE hInetModule = GetModuleHandle(L"WinInet.dll");
+ if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_FROM_HMODULE,
+ hInetModule, err, 0, (LPWSTR)&s, 0, nullptr) != 0) {
+ message += WideToUTF8(s, nullptr);
+ LocalFree(s);
+ // strip off any trailing newlines
+ string::size_type n = message.find_last_not_of("\r\n");
+ if (n < message.size() - 1) {
+ message.erase(n + 1);
+ }
+ } else {
+ char buf[64];
+ sprintf(buf, "Unknown error, error code: 0x%08x",
+ static_cast<unsigned int>(err));
+ message += buf;
+ }
+ return message;
+}
+
+#define TS_DRAW 2
+#define BP_CHECKBOX 3
+
+typedef HANDLE(WINAPI* OpenThemeDataPtr)(HWND hwnd, LPCWSTR pszClassList);
+typedef HRESULT(WINAPI* CloseThemeDataPtr)(HANDLE hTheme);
+typedef HRESULT(WINAPI* GetThemePartSizePtr)(HANDLE hTheme, HDC hdc,
+ int iPartId, int iStateId,
+ RECT* prc, int ts, SIZE* psz);
+typedef HRESULT(WINAPI* GetThemeContentRectPtr)(HANDLE hTheme, HDC hdc,
+ int iPartId, int iStateId,
+ const RECT* pRect,
+ RECT* pContentRect);
+
+static void GetThemeSizes(HWND hwnd) {
+ HMODULE themeDLL = LoadLibrary(L"uxtheme.dll");
+
+ if (!themeDLL) return;
+
+ OpenThemeDataPtr openTheme =
+ (OpenThemeDataPtr)GetProcAddress(themeDLL, "OpenThemeData");
+ CloseThemeDataPtr closeTheme =
+ (CloseThemeDataPtr)GetProcAddress(themeDLL, "CloseThemeData");
+ GetThemePartSizePtr getThemePartSize =
+ (GetThemePartSizePtr)GetProcAddress(themeDLL, "GetThemePartSize");
+
+ if (!openTheme || !closeTheme || !getThemePartSize) {
+ FreeLibrary(themeDLL);
+ return;
+ }
+
+ HANDLE buttonTheme = openTheme(hwnd, L"Button");
+ if (!buttonTheme) {
+ FreeLibrary(themeDLL);
+ return;
+ }
+ HDC hdc = GetDC(hwnd);
+ SIZE s;
+ getThemePartSize(buttonTheme, hdc, BP_CHECKBOX, 0, nullptr, TS_DRAW, &s);
+ gCheckboxPadding = s.cx;
+ closeTheme(buttonTheme);
+ FreeLibrary(themeDLL);
+}
+
+// Gets the position of a window relative to another window's client area
+static void GetRelativeRect(HWND hwnd, HWND hwndParent, RECT* r) {
+ GetWindowRect(hwnd, r);
+ MapWindowPoints(nullptr, hwndParent, (POINT*)r, 2);
+}
+
+static void SetDlgItemVisible(HWND hwndDlg, UINT item, bool visible) {
+ HWND hwnd = GetDlgItem(hwndDlg, item);
+
+ ShowWindow(hwnd, visible ? SW_SHOW : SW_HIDE);
+}
+
+/* === Crash Reporting Dialog === */
+
+static void StretchDialog(HWND hwndDlg, int ydiff) {
+ RECT r;
+ GetWindowRect(hwndDlg, &r);
+ r.bottom += ydiff;
+ MoveWindow(hwndDlg, r.left, r.top, r.right - r.left, r.bottom - r.top, TRUE);
+}
+
+static void ReflowDialog(HWND hwndDlg, int ydiff) {
+ // Move items attached to the bottom down/up by as much as
+ // the window resize
+ for (set<UINT>::const_iterator item = gAttachedBottom.begin();
+ item != gAttachedBottom.end(); item++) {
+ RECT r;
+ HWND hwnd = GetDlgItem(hwndDlg, *item);
+ GetRelativeRect(hwnd, hwndDlg, &r);
+ r.top += ydiff;
+ r.bottom += ydiff;
+ MoveWindow(hwnd, r.left, r.top, r.right - r.left, r.bottom - r.top, TRUE);
+ }
+}
+
+static DWORD WINAPI SendThreadProc(LPVOID param) {
+ bool finishedOk;
+ SendThreadData* td = (SendThreadData*)param;
+
+ if (td->sendURL.empty()) {
+ finishedOk = false;
+ LogMessage("No server URL, not sending report");
+ } else {
+ Json::StreamWriterBuilder builder;
+ builder["indentation"] = "";
+ string parameters(Json::writeString(builder, td->queryParameters));
+ google_breakpad::CrashReportSender sender(L"");
+ finishedOk = (sender.SendCrashReport(td->sendURL, parameters, td->files,
+ &td->serverResponse) ==
+ google_breakpad::RESULT_SUCCEEDED);
+ if (finishedOk) {
+ LogMessage("Crash report submitted successfully");
+ } else {
+ // get an error string and print it to the log
+ // XXX: would be nice to get the HTTP status code here, filed:
+ // http://code.google.com/p/google-breakpad/issues/detail?id=220
+ LogMessage(FormatLastError());
+ }
+ }
+
+ if (gAutoSubmit) {
+ // Ordinarily this is done on the main thread in CrashReporterDialogProc,
+ // for auto submit we don't run that and it should be safe to finish up
+ // here as is done on other platforms.
+ SendCompleted(finishedOk, WideToUTF8(gSendData.serverResponse));
+ } else {
+ PostMessage(td->hDlg, WM_UPLOADCOMPLETE, finishedOk ? 1 : 0, 0);
+ }
+
+ return 0;
+}
+
+static void EndCrashReporterDialog(HWND hwndDlg, int code) {
+ // Save the current values to the registry
+ SetBoolKey(gCrashReporterKey.c_str(), INCLUDE_URL_VALUE,
+ IsDlgButtonChecked(hwndDlg, IDC_INCLUDEURLCHECK) != 0);
+ SetBoolKey(gCrashReporterKey.c_str(), SUBMIT_REPORT_VALUE,
+ IsDlgButtonChecked(hwndDlg, IDC_SUBMITREPORTCHECK) != 0);
+
+ EndDialog(hwndDlg, code);
+}
+
+static void MaybeResizeProgressText(HWND hwndDlg) {
+ HWND hwndProgress = GetDlgItem(hwndDlg, IDC_PROGRESSTEXT);
+ HDC hdc = GetDC(hwndProgress);
+ HFONT hfont = (HFONT)SendMessage(hwndProgress, WM_GETFONT, 0, 0);
+ if (hfont) SelectObject(hdc, hfont);
+ SIZE size;
+ RECT rect;
+ GetRelativeRect(hwndProgress, hwndDlg, &rect);
+
+ wchar_t text[1024];
+ GetWindowText(hwndProgress, text, 1024);
+
+ if (!GetTextExtentPoint32(hdc, text, wcslen(text), &size)) return;
+
+ if (size.cx < (rect.right - rect.left)) return;
+
+ // Figure out how much we need to resize things vertically
+ // This is sort of a fudge, but it should be good enough.
+ int wantedHeight =
+ size.cy * (int)ceil((float)size.cx / (float)(rect.right - rect.left));
+ int diff = wantedHeight - (rect.bottom - rect.top);
+ if (diff <= 0) return;
+
+ MoveWindow(hwndProgress, rect.left, rect.top, rect.right - rect.left,
+ wantedHeight, TRUE);
+
+ gAttachedBottom.clear();
+ gAttachedBottom.insert(IDC_CLOSEBUTTON);
+ gAttachedBottom.insert(IDC_RESTARTBUTTON);
+
+ StretchDialog(hwndDlg, diff);
+
+ for (size_t i = 0; i < sizeof(kDefaultAttachedBottom) / sizeof(UINT); i++) {
+ gAttachedBottom.insert(kDefaultAttachedBottom[i]);
+ }
+}
+
+static void MaybeSendReport(HWND hwndDlg) {
+ if (!IsDlgButtonChecked(hwndDlg, IDC_SUBMITREPORTCHECK)) {
+ EndCrashReporterDialog(hwndDlg, 0);
+ return;
+ }
+
+ // disable all the form controls
+ EnableWindow(GetDlgItem(hwndDlg, IDC_SUBMITREPORTCHECK), false);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_VIEWREPORTBUTTON), false);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_COMMENTTEXT), false);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_INCLUDEURLCHECK), false);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_CLOSEBUTTON), false);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_RESTARTBUTTON), false);
+
+ SetDlgItemText(hwndDlg, IDC_PROGRESSTEXT, Str(ST_REPORTDURINGSUBMIT).c_str());
+ MaybeResizeProgressText(hwndDlg);
+ // start throbber
+ // play entire AVI, and loop
+ Animate_Play(GetDlgItem(hwndDlg, IDC_THROBBER), 0, -1, -1);
+ SetDlgItemVisible(hwndDlg, IDC_THROBBER, true);
+ gThreadHandle = nullptr;
+ gSendData.hDlg = hwndDlg;
+ gSendData.queryParameters = gQueryParameters;
+
+ gThreadHandle =
+ CreateThread(nullptr, 0, SendThreadProc, &gSendData, 0, nullptr);
+}
+
+static void RestartApplication() {
+ wstring cmdLine;
+
+ for (unsigned int i = 0; i < gRestartArgs.size(); i++) {
+ cmdLine += L"\"" + UTF8ToWide(gRestartArgs[i]) + L"\" ";
+ }
+
+ STARTUPINFO si;
+ PROCESS_INFORMATION pi;
+
+ ZeroMemory(&si, sizeof(si));
+ si.cb = sizeof(si);
+ si.dwFlags = STARTF_USESHOWWINDOW;
+ si.wShowWindow = SW_SHOWNORMAL;
+ ZeroMemory(&pi, sizeof(pi));
+
+ if (CreateProcess(nullptr, (LPWSTR)cmdLine.c_str(), nullptr, nullptr, FALSE,
+ 0, nullptr, nullptr, &si, &pi)) {
+ CloseHandle(pi.hProcess);
+ CloseHandle(pi.hThread);
+ }
+}
+
+static void ShowReportInfo(HWND hwndDlg) {
+ wstring description;
+
+ for (Json::ValueConstIterator iter = gQueryParameters.begin();
+ iter != gQueryParameters.end(); ++iter) {
+ description += UTF8ToWide(iter.name());
+ description += L": ";
+ string value;
+ if (iter->isString()) {
+ value = iter->asString();
+ } else {
+ Json::StreamWriterBuilder builder;
+ builder["indentation"] = "";
+ value = Json::writeString(builder, *iter);
+ }
+ description += UTF8ToWide(value);
+ description += L"\n";
+ }
+
+ description += L"\n";
+ description += Str(ST_EXTRAREPORTINFO);
+
+ SetDlgItemText(hwndDlg, IDC_VIEWREPORTTEXT, description.c_str());
+}
+
+static void UpdateURL(HWND hwndDlg) {
+ if (IsDlgButtonChecked(hwndDlg, IDC_INCLUDEURLCHECK)) {
+ gQueryParameters["URL"] = gURLParameter;
+ } else {
+ gQueryParameters.removeMember("URL");
+ }
+}
+
+static void UpdateComment(HWND hwndDlg) {
+ wchar_t comment[MAX_COMMENT_LENGTH + 1];
+ GetDlgItemTextW(hwndDlg, IDC_COMMENTTEXT, comment,
+ sizeof(comment) / sizeof(comment[0]));
+ if (wcslen(comment) > 0)
+ gQueryParameters["Comments"] = WideToUTF8(comment);
+ else
+ gQueryParameters.removeMember("Comments");
+}
+
+/*
+ * Dialog procedure for the "view report" dialog.
+ */
+static BOOL CALLBACK ViewReportDialogProc(HWND hwndDlg, UINT message,
+ WPARAM wParam, LPARAM lParam) {
+ switch (message) {
+ case WM_INITDIALOG: {
+ SetWindowText(hwndDlg, Str(ST_VIEWREPORTTITLE).c_str());
+ SetDlgItemText(hwndDlg, IDOK, Str(ST_OK).c_str());
+ SendDlgItemMessage(hwndDlg, IDC_VIEWREPORTTEXT, EM_SETTARGETDEVICE,
+ (WPARAM) nullptr, 0);
+ ShowReportInfo(hwndDlg);
+ SetFocus(GetDlgItem(hwndDlg, IDOK));
+ return FALSE;
+ }
+
+ case WM_COMMAND: {
+ if (HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == IDOK)
+ EndDialog(hwndDlg, 0);
+ return FALSE;
+ }
+ }
+ return FALSE;
+}
+
+// Return the number of bytes this string will take encoded
+// in UTF-8
+static inline int BytesInUTF8(wchar_t* str) {
+ // Just count size of buffer for UTF-8, minus one
+ // (we don't need to count the null terminator)
+ return WideCharToMultiByte(CP_UTF8, 0, str, -1, nullptr, 0, nullptr,
+ nullptr) -
+ 1;
+}
+
+// Calculate the length of the text in this edit control (in bytes,
+// in the UTF-8 encoding) after replacing the current selection
+// with |insert|.
+static int NewTextLength(HWND hwndEdit, wchar_t* insert) {
+ wchar_t current[MAX_COMMENT_LENGTH + 1];
+
+ GetWindowText(hwndEdit, current, MAX_COMMENT_LENGTH + 1);
+ DWORD selStart, selEnd;
+ SendMessage(hwndEdit, EM_GETSEL, (WPARAM)&selStart, (LPARAM)&selEnd);
+
+ int selectionLength = 0;
+ if (selEnd - selStart > 0) {
+ wchar_t selection[MAX_COMMENT_LENGTH + 1];
+ google_breakpad::WindowsStringUtils::safe_wcsncpy(
+ selection, MAX_COMMENT_LENGTH + 1, current + selStart,
+ selEnd - selStart);
+ selection[selEnd - selStart] = '\0';
+ selectionLength = BytesInUTF8(selection);
+ }
+
+ // current string length + replacement text length
+ // - replaced selection length
+ return BytesInUTF8(current) + BytesInUTF8(insert) - selectionLength;
+}
+
+// Window procedure for subclassing edit controls
+static LRESULT CALLBACK EditSubclassProc(HWND hwnd, UINT uMsg, WPARAM wParam,
+ LPARAM lParam) {
+ static WNDPROC super = nullptr;
+
+ if (super == nullptr) super = (WNDPROC)GetWindowLongPtr(hwnd, GWLP_USERDATA);
+
+ switch (uMsg) {
+ case WM_PAINT: {
+ HDC hdc;
+ PAINTSTRUCT ps;
+ RECT r;
+ wchar_t windowText[1024];
+
+ GetWindowText(hwnd, windowText, 1024);
+ // if the control contains text or is focused, draw it normally
+ if (GetFocus() == hwnd || windowText[0] != '\0')
+ return CallWindowProc(super, hwnd, uMsg, wParam, lParam);
+
+ GetClientRect(hwnd, &r);
+ hdc = BeginPaint(hwnd, &ps);
+ FillRect(hdc, &r,
+ GetSysColorBrush(IsWindowEnabled(hwnd) ? COLOR_WINDOW
+ : COLOR_BTNFACE));
+ SetTextColor(hdc, GetSysColor(COLOR_GRAYTEXT));
+ SelectObject(hdc, (HFONT)GetStockObject(DEFAULT_GUI_FONT));
+ SetBkMode(hdc, TRANSPARENT);
+ wchar_t* txt = (wchar_t*)GetProp(hwnd, L"PROP_GRAYTEXT");
+ // Get the actual edit control rect
+ CallWindowProc(super, hwnd, EM_GETRECT, 0, (LPARAM)&r);
+ UINT format = DT_EDITCONTROL | DT_NOPREFIX | DT_WORDBREAK | DT_INTERNAL;
+ if (gRTLlayout) format |= DT_RIGHT;
+ if (txt) DrawText(hdc, txt, wcslen(txt), &r, format);
+ EndPaint(hwnd, &ps);
+ return 0;
+ }
+
+ // We handle WM_CHAR and WM_PASTE to limit the comment box to 500
+ // bytes in UTF-8.
+ case WM_CHAR: {
+ // Leave accelerator keys and non-printing chars (except LF) alone
+ if (wParam & (1 << 24) || wParam & (1 << 29) ||
+ (wParam < ' ' && wParam != '\n'))
+ break;
+
+ wchar_t ch[2] = {(wchar_t)wParam, 0};
+ if (NewTextLength(hwnd, ch) > MAX_COMMENT_LENGTH) return 0;
+
+ break;
+ }
+
+ case WM_PASTE: {
+ if (IsClipboardFormatAvailable(CF_UNICODETEXT) && OpenClipboard(hwnd)) {
+ HGLOBAL hg = GetClipboardData(CF_UNICODETEXT);
+ wchar_t* pastedText = (wchar_t*)GlobalLock(hg);
+ int newSize = 0;
+
+ if (pastedText) newSize = NewTextLength(hwnd, pastedText);
+
+ GlobalUnlock(hg);
+ CloseClipboard();
+
+ if (newSize > MAX_COMMENT_LENGTH) return 0;
+ }
+ break;
+ }
+
+ case WM_SETFOCUS:
+ case WM_KILLFOCUS: {
+ RECT r;
+ GetClientRect(hwnd, &r);
+ InvalidateRect(hwnd, &r, TRUE);
+ break;
+ }
+
+ case WM_DESTROY: {
+ // cleanup our property
+ HGLOBAL hData = RemoveProp(hwnd, L"PROP_GRAYTEXT");
+ if (hData) GlobalFree(hData);
+ }
+ }
+
+ return CallWindowProc(super, hwnd, uMsg, wParam, lParam);
+}
+
+// Resize a control to fit this text
+static int ResizeControl(HWND hwndButton, RECT& rect, wstring text,
+ bool shiftLeft, int userDefinedPadding) {
+ HDC hdc = GetDC(hwndButton);
+ HFONT hfont = (HFONT)SendMessage(hwndButton, WM_GETFONT, 0, 0);
+ if (hfont) SelectObject(hdc, hfont);
+ SIZE size, oldSize;
+ int sizeDiff = 0;
+
+ wchar_t oldText[1024];
+ GetWindowText(hwndButton, oldText, 1024);
+
+ if (GetTextExtentPoint32(hdc, text.c_str(), text.length(), &size)
+ // default text on the button
+ && GetTextExtentPoint32(hdc, oldText, wcslen(oldText), &oldSize)) {
+ /*
+ Expand control widths to accomidate wider text strings. For most
+ controls (including buttons) the text padding is defined by the
+ dialog's rc file. Some controls (such as checkboxes) have padding
+ that extends to the end of the dialog, in which case we ignore the
+ rc padding and rely on a user defined value passed in through
+ userDefinedPadding.
+ */
+ int textIncrease = size.cx - oldSize.cx;
+ if (textIncrease < 0) return 0;
+ int existingTextPadding;
+ if (userDefinedPadding == 0)
+ existingTextPadding = (rect.right - rect.left) - oldSize.cx;
+ else
+ existingTextPadding = userDefinedPadding;
+ sizeDiff = textIncrease + existingTextPadding;
+
+ if (shiftLeft) {
+ // shift left by the amount the button should grow
+ rect.left -= sizeDiff;
+ } else {
+ // grow right instead
+ rect.right += sizeDiff;
+ }
+ MoveWindow(hwndButton, rect.left, rect.top, rect.right - rect.left,
+ rect.bottom - rect.top, TRUE);
+ }
+ return sizeDiff;
+}
+
+// The window was resized horizontally, so widen some of our
+// controls to make use of the space
+static void StretchControlsToFit(HWND hwndDlg) {
+ int controls[] = {IDC_DESCRIPTIONTEXT, IDC_SUBMITREPORTCHECK, IDC_COMMENTTEXT,
+ IDC_INCLUDEURLCHECK, IDC_PROGRESSTEXT};
+
+ RECT dlgRect;
+ GetClientRect(hwndDlg, &dlgRect);
+
+ for (size_t i = 0; i < sizeof(controls) / sizeof(controls[0]); i++) {
+ RECT r;
+ HWND hwndControl = GetDlgItem(hwndDlg, controls[i]);
+ GetRelativeRect(hwndControl, hwndDlg, &r);
+ // 6 pixel spacing on the right
+ if (r.right + 6 != dlgRect.right) {
+ r.right = dlgRect.right - 6;
+ MoveWindow(hwndControl, r.left, r.top, r.right - r.left, r.bottom - r.top,
+ TRUE);
+ }
+ }
+}
+
+static void SubmitReportChecked(HWND hwndDlg) {
+ bool enabled = (IsDlgButtonChecked(hwndDlg, IDC_SUBMITREPORTCHECK) != 0);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_VIEWREPORTBUTTON), enabled);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_COMMENTTEXT), enabled);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_INCLUDEURLCHECK), enabled);
+ SetDlgItemVisible(hwndDlg, IDC_PROGRESSTEXT, enabled);
+}
+
+static INT_PTR DialogBoxParamMaybeRTL(UINT idd, HWND hwndParent,
+ DLGPROC dlgProc, LPARAM param) {
+ INT_PTR rv = 0;
+ if (gRTLlayout) {
+ // We need to toggle the WS_EX_LAYOUTRTL style flag on the dialog
+ // template.
+ HRSRC hDialogRC = FindResource(nullptr, MAKEINTRESOURCE(idd), RT_DIALOG);
+ HGLOBAL hDlgTemplate = LoadResource(nullptr, hDialogRC);
+ DLGTEMPLATEEX* pDlgTemplate = (DLGTEMPLATEEX*)LockResource(hDlgTemplate);
+ unsigned long sizeDlg = SizeofResource(nullptr, hDialogRC);
+ HGLOBAL hMyDlgTemplate = GlobalAlloc(GPTR, sizeDlg);
+ DLGTEMPLATEEX* pMyDlgTemplate = (DLGTEMPLATEEX*)GlobalLock(hMyDlgTemplate);
+ memcpy(pMyDlgTemplate, pDlgTemplate, sizeDlg);
+
+ pMyDlgTemplate->exStyle |= WS_EX_LAYOUTRTL;
+
+ rv = DialogBoxIndirectParam(nullptr, (LPCDLGTEMPLATE)pMyDlgTemplate,
+ hwndParent, dlgProc, param);
+ GlobalUnlock(hMyDlgTemplate);
+ GlobalFree(hMyDlgTemplate);
+ } else {
+ rv = DialogBoxParam(nullptr, MAKEINTRESOURCE(idd), hwndParent, dlgProc,
+ param);
+ }
+
+ return rv;
+}
+
+static BOOL CALLBACK CrashReporterDialogProc(HWND hwndDlg, UINT message,
+ WPARAM wParam, LPARAM lParam) {
+ static int sHeight = 0;
+
+ bool success;
+ bool enabled;
+
+ switch (message) {
+ case WM_INITDIALOG: {
+ GetThemeSizes(hwndDlg);
+ RECT r;
+ GetClientRect(hwndDlg, &r);
+ sHeight = r.bottom - r.top;
+
+ SetWindowText(hwndDlg, Str(ST_CRASHREPORTERTITLE).c_str());
+ HICON hIcon =
+ LoadIcon(GetModuleHandle(nullptr), MAKEINTRESOURCE(IDI_MAINICON));
+ SendMessage(hwndDlg, WM_SETICON, ICON_SMALL, (LPARAM)hIcon);
+ SendMessage(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM)hIcon);
+
+ // resize the "View Report" button based on the string length
+ RECT rect;
+ HWND hwnd = GetDlgItem(hwndDlg, IDC_VIEWREPORTBUTTON);
+ GetRelativeRect(hwnd, hwndDlg, &rect);
+ ResizeControl(hwnd, rect, Str(ST_VIEWREPORT), false, 0);
+ SetDlgItemText(hwndDlg, IDC_VIEWREPORTBUTTON, Str(ST_VIEWREPORT).c_str());
+
+ hwnd = GetDlgItem(hwndDlg, IDC_SUBMITREPORTCHECK);
+ GetRelativeRect(hwnd, hwndDlg, &rect);
+ long maxdiff = ResizeControl(hwnd, rect, Str(ST_CHECKSUBMIT), false,
+ gCheckboxPadding);
+ SetDlgItemText(hwndDlg, IDC_SUBMITREPORTCHECK,
+ Str(ST_CHECKSUBMIT).c_str());
+
+ if (!CheckBoolKey(gCrashReporterKey.c_str(), SUBMIT_REPORT_VALUE,
+ &enabled))
+ enabled = true;
+
+ CheckDlgButton(hwndDlg, IDC_SUBMITREPORTCHECK,
+ enabled ? BST_CHECKED : BST_UNCHECKED);
+ SubmitReportChecked(hwndDlg);
+
+ HWND hwndComment = GetDlgItem(hwndDlg, IDC_COMMENTTEXT);
+ WNDPROC OldWndProc = (WNDPROC)SetWindowLongPtr(
+ hwndComment, GWLP_WNDPROC, (LONG_PTR)EditSubclassProc);
+
+ // Subclass comment edit control to get placeholder text
+ SetWindowLongPtr(hwndComment, GWLP_USERDATA, (LONG_PTR)OldWndProc);
+ wstring commentGrayText = Str(ST_COMMENTGRAYTEXT);
+ wchar_t* hMem = (wchar_t*)GlobalAlloc(
+ GPTR, (commentGrayText.length() + 1) * sizeof(wchar_t));
+ wcscpy(hMem, commentGrayText.c_str());
+ SetProp(hwndComment, L"PROP_GRAYTEXT", hMem);
+
+ hwnd = GetDlgItem(hwndDlg, IDC_INCLUDEURLCHECK);
+ GetRelativeRect(hwnd, hwndDlg, &rect);
+ long diff =
+ ResizeControl(hwnd, rect, Str(ST_CHECKURL), false, gCheckboxPadding);
+ maxdiff = std::max(diff, maxdiff);
+ SetDlgItemText(hwndDlg, IDC_INCLUDEURLCHECK, Str(ST_CHECKURL).c_str());
+
+ // want this on by default
+ if (CheckBoolKey(gCrashReporterKey.c_str(), INCLUDE_URL_VALUE,
+ &enabled) &&
+ !enabled) {
+ CheckDlgButton(hwndDlg, IDC_INCLUDEURLCHECK, BST_UNCHECKED);
+ } else {
+ CheckDlgButton(hwndDlg, IDC_INCLUDEURLCHECK, BST_CHECKED);
+ }
+
+ SetDlgItemText(hwndDlg, IDC_PROGRESSTEXT,
+ Str(ST_REPORTPRESUBMIT).c_str());
+
+ RECT closeRect;
+ HWND hwndClose = GetDlgItem(hwndDlg, IDC_CLOSEBUTTON);
+ GetRelativeRect(hwndClose, hwndDlg, &closeRect);
+
+ RECT restartRect;
+ HWND hwndRestart = GetDlgItem(hwndDlg, IDC_RESTARTBUTTON);
+ GetRelativeRect(hwndRestart, hwndDlg, &restartRect);
+
+ // set the close button text and shift the buttons around
+ // since the size may need to change
+ int sizeDiff = ResizeControl(hwndClose, closeRect, Str(ST_QUIT), true, 0);
+ restartRect.left -= sizeDiff;
+ restartRect.right -= sizeDiff;
+ SetDlgItemText(hwndDlg, IDC_CLOSEBUTTON, Str(ST_QUIT).c_str());
+
+ if (gRestartArgs.size() > 0) {
+ // Resize restart button to fit text
+ ResizeControl(hwndRestart, restartRect, Str(ST_RESTART), true, 0);
+ SetDlgItemText(hwndDlg, IDC_RESTARTBUTTON, Str(ST_RESTART).c_str());
+ } else {
+ // No restart arguments, so just hide the restart button
+ SetDlgItemVisible(hwndDlg, IDC_RESTARTBUTTON, false);
+ }
+ // See if we need to widen the window
+ // Leave 6 pixels on either side + 6 pixels between the buttons
+ int neededSize = closeRect.right - closeRect.left + restartRect.right -
+ restartRect.left + 6 * 3;
+ GetClientRect(hwndDlg, &r);
+ // We may already have resized one of the checkboxes above
+ maxdiff = std::max(maxdiff, neededSize - (r.right - r.left));
+
+ if (maxdiff > 0) {
+ // widen window
+ GetWindowRect(hwndDlg, &r);
+ r.right += maxdiff;
+ MoveWindow(hwndDlg, r.left, r.top, r.right - r.left, r.bottom - r.top,
+ TRUE);
+ // shift both buttons right
+ if (restartRect.left + maxdiff < 6) maxdiff += 6;
+ closeRect.left += maxdiff;
+ closeRect.right += maxdiff;
+ restartRect.left += maxdiff;
+ restartRect.right += maxdiff;
+ MoveWindow(hwndClose, closeRect.left, closeRect.top,
+ closeRect.right - closeRect.left,
+ closeRect.bottom - closeRect.top, TRUE);
+ StretchControlsToFit(hwndDlg);
+ }
+ // need to move the restart button regardless
+ MoveWindow(hwndRestart, restartRect.left, restartRect.top,
+ restartRect.right - restartRect.left,
+ restartRect.bottom - restartRect.top, TRUE);
+
+ // Resize the description text last, in case the window was resized
+ // before this.
+ SendDlgItemMessage(hwndDlg, IDC_DESCRIPTIONTEXT, EM_SETEVENTMASK,
+ (WPARAM) nullptr, ENM_REQUESTRESIZE);
+
+ wstring description = Str(ST_CRASHREPORTERHEADER);
+ description += L"\n\n";
+ description += Str(ST_CRASHREPORTERDESCRIPTION);
+ SetDlgItemText(hwndDlg, IDC_DESCRIPTIONTEXT, description.c_str());
+
+ // Make the title bold.
+ CHARFORMAT fmt = {
+ 0,
+ };
+ fmt.cbSize = sizeof(fmt);
+ fmt.dwMask = CFM_BOLD;
+ fmt.dwEffects = CFE_BOLD;
+ SendDlgItemMessage(hwndDlg, IDC_DESCRIPTIONTEXT, EM_SETSEL, 0,
+ Str(ST_CRASHREPORTERHEADER).length());
+ SendDlgItemMessage(hwndDlg, IDC_DESCRIPTIONTEXT, EM_SETCHARFORMAT,
+ SCF_SELECTION, (LPARAM)&fmt);
+ SendDlgItemMessage(hwndDlg, IDC_DESCRIPTIONTEXT, EM_SETSEL, 0, 0);
+ // Force redraw.
+ SendDlgItemMessage(hwndDlg, IDC_DESCRIPTIONTEXT, EM_SETTARGETDEVICE,
+ (WPARAM) nullptr, 0);
+ // Force resize.
+ SendDlgItemMessage(hwndDlg, IDC_DESCRIPTIONTEXT, EM_REQUESTRESIZE, 0, 0);
+
+ // if no URL was given, hide the URL checkbox
+ if (!gQueryParameters.isMember("URL")) {
+ RECT urlCheckRect;
+ GetWindowRect(GetDlgItem(hwndDlg, IDC_INCLUDEURLCHECK), &urlCheckRect);
+
+ SetDlgItemVisible(hwndDlg, IDC_INCLUDEURLCHECK, false);
+
+ gAttachedBottom.erase(IDC_VIEWREPORTBUTTON);
+ gAttachedBottom.erase(IDC_SUBMITREPORTCHECK);
+ gAttachedBottom.erase(IDC_COMMENTTEXT);
+
+ StretchDialog(hwndDlg, urlCheckRect.top - urlCheckRect.bottom);
+
+ gAttachedBottom.insert(IDC_VIEWREPORTBUTTON);
+ gAttachedBottom.insert(IDC_SUBMITREPORTCHECK);
+ gAttachedBottom.insert(IDC_COMMENTTEXT);
+ }
+
+ MaybeResizeProgressText(hwndDlg);
+
+ // Open the AVI resource for the throbber
+ Animate_Open(GetDlgItem(hwndDlg, IDC_THROBBER),
+ MAKEINTRESOURCE(IDR_THROBBER));
+
+ UpdateURL(hwndDlg);
+
+ SetFocus(GetDlgItem(hwndDlg, IDC_SUBMITREPORTCHECK));
+ return FALSE;
+ }
+ case WM_SIZE: {
+ ReflowDialog(hwndDlg, HIWORD(lParam) - sHeight);
+ sHeight = HIWORD(lParam);
+ InvalidateRect(hwndDlg, nullptr, TRUE);
+ return FALSE;
+ }
+ case WM_NOTIFY: {
+ NMHDR* notification = reinterpret_cast<NMHDR*>(lParam);
+ if (notification->code == EN_REQUESTRESIZE) {
+ // Resizing the rich edit control to fit the description text.
+ REQRESIZE* reqresize = reinterpret_cast<REQRESIZE*>(lParam);
+ RECT newSize = reqresize->rc;
+ RECT oldSize;
+ GetRelativeRect(notification->hwndFrom, hwndDlg, &oldSize);
+
+ // resize the text box as requested
+ MoveWindow(notification->hwndFrom, newSize.left, newSize.top,
+ newSize.right - newSize.left, newSize.bottom - newSize.top,
+ TRUE);
+
+ // Resize the dialog to fit (the WM_SIZE handler will move the controls)
+ StretchDialog(hwndDlg, newSize.bottom - oldSize.bottom);
+ }
+ return FALSE;
+ }
+ case WM_COMMAND: {
+ if (HIWORD(wParam) == BN_CLICKED) {
+ switch (LOWORD(wParam)) {
+ case IDC_VIEWREPORTBUTTON:
+ DialogBoxParamMaybeRTL(IDD_VIEWREPORTDIALOG, hwndDlg,
+ (DLGPROC)ViewReportDialogProc, 0);
+ break;
+ case IDC_SUBMITREPORTCHECK:
+ SubmitReportChecked(hwndDlg);
+ break;
+ case IDC_INCLUDEURLCHECK:
+ UpdateURL(hwndDlg);
+ break;
+ case IDC_CLOSEBUTTON:
+ MaybeSendReport(hwndDlg);
+ break;
+ case IDC_RESTARTBUTTON:
+ RestartApplication();
+ MaybeSendReport(hwndDlg);
+ break;
+ }
+ } else if (HIWORD(wParam) == EN_CHANGE) {
+ switch (LOWORD(wParam)) {
+ case IDC_COMMENTTEXT:
+ UpdateComment(hwndDlg);
+ }
+ }
+
+ return FALSE;
+ }
+ case WM_UPLOADCOMPLETE: {
+ WaitForSingleObject(gThreadHandle, INFINITE);
+ success = (wParam == 1);
+ SendCompleted(success, WideToUTF8(gSendData.serverResponse));
+ // hide throbber
+ Animate_Stop(GetDlgItem(hwndDlg, IDC_THROBBER));
+ SetDlgItemVisible(hwndDlg, IDC_THROBBER, false);
+
+ SetDlgItemText(hwndDlg, IDC_PROGRESSTEXT,
+ success ? Str(ST_REPORTSUBMITSUCCESS).c_str()
+ : Str(ST_SUBMITFAILED).c_str());
+ MaybeResizeProgressText(hwndDlg);
+ // close dialog after 5 seconds
+ SetTimer(hwndDlg, 0, 5000, nullptr);
+ //
+ return TRUE;
+ }
+
+ case WM_TIMER: {
+ // The "1" gets used down in UIShowCrashUI to indicate that we at least
+ // tried to send the report.
+ EndCrashReporterDialog(hwndDlg, 1);
+ return FALSE;
+ }
+
+ case WM_CLOSE: {
+ EndCrashReporterDialog(hwndDlg, 0);
+ return FALSE;
+ }
+ }
+ return FALSE;
+}
+
+static wstring UTF8ToWide(const string& utf8, bool* success) {
+ wchar_t* buffer = nullptr;
+ int buffer_size =
+ MultiByteToWideChar(CP_UTF8, 0, utf8.c_str(), -1, nullptr, 0);
+ if (buffer_size == 0) {
+ if (success) *success = false;
+ return L"";
+ }
+
+ buffer = new wchar_t[buffer_size];
+ if (buffer == nullptr) {
+ if (success) *success = false;
+ return L"";
+ }
+
+ MultiByteToWideChar(CP_UTF8, 0, utf8.c_str(), -1, buffer, buffer_size);
+ wstring str = buffer;
+ delete[] buffer;
+
+ if (success) *success = true;
+
+ return str;
+}
+
+static string WideToMBCP(const wstring& wide, unsigned int cp,
+ bool* success = nullptr) {
+ char* buffer = nullptr;
+ int buffer_size = WideCharToMultiByte(cp, 0, wide.c_str(), -1, nullptr, 0,
+ nullptr, nullptr);
+ if (buffer_size == 0) {
+ if (success) *success = false;
+ return "";
+ }
+
+ buffer = new char[buffer_size];
+ if (buffer == nullptr) {
+ if (success) *success = false;
+ return "";
+ }
+
+ WideCharToMultiByte(cp, 0, wide.c_str(), -1, buffer, buffer_size, nullptr,
+ nullptr);
+ string mb = buffer;
+ delete[] buffer;
+
+ if (success) *success = true;
+
+ return mb;
+}
+
+string WideToUTF8(const wstring& wide, bool* success) {
+ return WideToMBCP(wide, CP_UTF8, success);
+}
+
+/* === Crashreporter UI Functions === */
+
+bool UIInit() {
+ for (size_t i = 0; i < sizeof(kDefaultAttachedBottom) / sizeof(UINT); i++) {
+ gAttachedBottom.insert(kDefaultAttachedBottom[i]);
+ }
+
+ DoInitCommonControls();
+
+ return true;
+}
+
+void UIShutdown() {}
+
+void UIShowDefaultUI() {
+ MessageBox(nullptr, Str(ST_CRASHREPORTERDEFAULT).c_str(), L"Crash Reporter",
+ MB_OK | MB_ICONSTOP);
+}
+
+static bool CanUseMainCrashReportServer() {
+ // Any NT from 6.0 and above is fine.
+ if (IsWindowsVersionOrGreater(6, 0, 0)) {
+ return true;
+ }
+
+ // On NT 5 servers, we need Server 2003 SP2.
+ if (IsWindowsServer()) {
+ return IsWindowsVersionOrGreater(5, 2, 2);
+ }
+
+ // Otherwise we have an NT 5 client.
+ // We need exactly XP SP3 (version 5.1 SP3 but not version 5.2).
+ return (IsWindowsVersionOrGreater(5, 1, 3) &&
+ !IsWindowsVersionOrGreater(5, 2, 0));
+}
+
+bool UIShowCrashUI(const StringTable& files, const Json::Value& queryParameters,
+ const string& sendURL, const vector<string>& restartArgs) {
+ gSendData.hDlg = nullptr;
+ gSendData.sendURL = UTF8ToWide(sendURL);
+
+ // Older Windows don't support the crash report server's crypto.
+ // This is a hack to use an alternate server.
+ if (!CanUseMainCrashReportServer() &&
+ gSendData.sendURL.find(SENDURL_ORIGINAL) == 0) {
+ gSendData.sendURL.replace(0, ARRAYSIZE(SENDURL_ORIGINAL) - 1,
+ SENDURL_XPSP2);
+ }
+
+ for (StringTable::const_iterator i = files.begin(); i != files.end(); i++) {
+ gSendData.files[UTF8ToWide(i->first)] = UTF8ToWide(i->second);
+ }
+
+ gQueryParameters = queryParameters;
+
+ if (gQueryParameters.isMember("Vendor")) {
+ gCrashReporterKey = L"Software\\";
+ string vendor = gQueryParameters["Vendor"].asString();
+ if (!vendor.empty()) {
+ gCrashReporterKey += UTF8ToWide(vendor) + L"\\";
+ }
+ string productName = gQueryParameters["ProductName"].asString();
+ gCrashReporterKey += UTF8ToWide(productName) + L"\\Crash Reporter";
+ }
+
+ if (gQueryParameters.isMember("URL")) {
+ gURLParameter = gQueryParameters["URL"].asString();
+ }
+
+ gRestartArgs = restartArgs;
+
+ if (gStrings.find("isRTL") != gStrings.end() && gStrings["isRTL"] == "yes")
+ gRTLlayout = true;
+
+ if (gAutoSubmit) {
+ gSendData.queryParameters = gQueryParameters;
+
+ gThreadHandle =
+ CreateThread(nullptr, 0, SendThreadProc, &gSendData, 0, nullptr);
+ WaitForSingleObject(gThreadHandle, INFINITE);
+ // SendCompleted was called from SendThreadProc
+ return true;
+ }
+
+ return 1 == DialogBoxParamMaybeRTL(IDD_SENDDIALOG, nullptr,
+ (DLGPROC)CrashReporterDialogProc, 0);
+}
+
+void UIError_impl(const string& message) {
+ wstring title = Str(ST_CRASHREPORTERTITLE);
+ if (title.empty()) title = L"Crash Reporter Error";
+
+ MessageBox(nullptr, UTF8ToWide(message).c_str(), title.c_str(),
+ MB_OK | MB_ICONSTOP);
+}
+
+bool UIGetIniPath(string& path) {
+ wchar_t fileName[MAX_PATH];
+ if (GetModuleFileName(nullptr, fileName, MAX_PATH)) {
+ // get crashreporter ini
+ wchar_t* s = wcsrchr(fileName, '.');
+ if (s) {
+ wcscpy(s, L".ini");
+ path = WideToUTF8(fileName);
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool UIGetSettingsPath(const string& vendor, const string& product,
+ string& settings_path) {
+ wchar_t path[MAX_PATH] = {};
+ HRESULT hRes = SHGetFolderPath(nullptr, CSIDL_APPDATA, nullptr, 0, path);
+ if (FAILED(hRes)) {
+ // This provides a fallback for getting the path to APPDATA by querying the
+ // registry when the call to SHGetFolderPath is unable to provide this path
+ // (Bug 513958).
+ HKEY key;
+ DWORD type, dwRes;
+ DWORD size = sizeof(path) - 1;
+ dwRes = ::RegOpenKeyExW(HKEY_CURRENT_USER,
+ L"Software\\Microsoft\\Windows\\CurrentVersion\\Exp"
+ L"lorer\\Shell Folders",
+ 0, KEY_READ, &key);
+ if (dwRes != ERROR_SUCCESS) return false;
+
+ dwRes =
+ RegQueryValueExW(key, L"AppData", nullptr, &type, (LPBYTE)&path, &size);
+ ::RegCloseKey(key);
+ // The call to RegQueryValueExW must succeed, the type must be REG_SZ, the
+ // buffer size must not equal 0, and the buffer size be a multiple of 2.
+ if (dwRes != ERROR_SUCCESS || type != REG_SZ || size == 0 || size % 2 != 0)
+ return false;
+ }
+
+ if (!vendor.empty()) {
+ PathAppend(path, UTF8ToWide(vendor).c_str());
+ }
+ PathAppend(path, UTF8ToWide(product).c_str());
+ PathAppend(path, L"Crash Reports");
+ settings_path = WideToUTF8(path);
+ return true;
+}
+
+bool UIEnsurePathExists(const string& path) {
+ if (CreateDirectory(UTF8ToWide(path).c_str(), nullptr) == 0) {
+ if (GetLastError() != ERROR_ALREADY_EXISTS) return false;
+ }
+
+ return true;
+}
+
+bool UIFileExists(const string& path) {
+ DWORD attrs = GetFileAttributes(UTF8ToWide(path).c_str());
+ return (attrs != INVALID_FILE_ATTRIBUTES);
+}
+
+bool UIMoveFile(const string& oldfile, const string& newfile) {
+ if (oldfile == newfile) return true;
+
+ return MoveFile(UTF8ToWide(oldfile).c_str(), UTF8ToWide(newfile).c_str()) ==
+ TRUE;
+}
+
+bool UIDeleteFile(const string& oldfile) {
+ return DeleteFile(UTF8ToWide(oldfile).c_str()) == TRUE;
+}
+
+ifstream* UIOpenRead(const string& filename, ios_base::openmode mode) {
+#if defined(_MSC_VER)
+ ifstream* file = new ifstream();
+ file->open(UTF8ToWide(filename).c_str(), mode);
+#else // GCC
+ ifstream* file =
+ new ifstream(WideToMBCP(UTF8ToWide(filename), CP_ACP).c_str(), mode);
+#endif // _MSC_VER
+
+ return file;
+}
+
+ofstream* UIOpenWrite(const string& filename, ios_base::openmode mode) {
+#if defined(_MSC_VER)
+ ofstream* file = new ofstream();
+ file->open(UTF8ToWide(filename).c_str(), mode);
+#else // GCC
+ ofstream* file =
+ new ofstream(WideToMBCP(UTF8ToWide(filename), CP_ACP).c_str(), mode);
+#endif // _MSC_VER
+
+ return file;
+}
+
+struct FileData {
+ FILETIME timestamp;
+ wstring path;
+};
+
+static bool CompareFDTime(const FileData& fd1, const FileData& fd2) {
+ return CompareFileTime(&fd1.timestamp, &fd2.timestamp) > 0;
+}
+
+void UIPruneSavedDumps(const std::string& directory) {
+ wstring wdirectory = UTF8ToWide(directory);
+
+ WIN32_FIND_DATA fdata;
+ wstring findpath = wdirectory + L"\\*.dmp";
+ HANDLE dirlist = FindFirstFile(findpath.c_str(), &fdata);
+ if (dirlist == INVALID_HANDLE_VALUE) return;
+
+ vector<FileData> dumpfiles;
+
+ for (BOOL ok = true; ok; ok = FindNextFile(dirlist, &fdata)) {
+ FileData fd = {fdata.ftLastWriteTime, wdirectory + L"\\" + fdata.cFileName};
+ dumpfiles.push_back(fd);
+ }
+
+ sort(dumpfiles.begin(), dumpfiles.end(), CompareFDTime);
+
+ while (dumpfiles.size() > kSaveCount) {
+ // get the path of the oldest file
+ wstring path = (--dumpfiles.end())->path;
+ DeleteFile(path.c_str());
+
+ // s/.dmp/.extra/
+ path.replace(path.size() - 4, 4, L".extra");
+ DeleteFile(path.c_str());
+
+ dumpfiles.pop_back();
+ }
+ FindClose(dirlist);
+}
+
+bool UIRunProgram(const string& exename, const std::vector<std::string>& args,
+ bool wait) {
+ wstring cmdLine = L"\"" + UTF8ToWide(exename) + L"\" ";
+
+ for (auto arg : args) {
+ cmdLine += L"\"" + UTF8ToWide(arg) + L"\" ";
+ }
+
+ STARTUPINFO si = {};
+ si.cb = sizeof(si);
+ PROCESS_INFORMATION pi = {};
+
+ if (!CreateProcess(/* lpApplicationName */ nullptr, (LPWSTR)cmdLine.c_str(),
+ /* lpProcessAttributes */ nullptr,
+ /* lpThreadAttributes */ nullptr,
+ /* bInheritHandles */ false,
+ NORMAL_PRIORITY_CLASS | CREATE_NO_WINDOW,
+ /* lpEnvironment */ nullptr,
+ /* lpCurrentDirectory */ nullptr, &si, &pi)) {
+ return false;
+ }
+
+ if (wait) {
+ WaitForSingleObject(pi.hProcess, INFINITE);
+ }
+
+ CloseHandle(pi.hProcess);
+ CloseHandle(pi.hThread);
+ return true;
+}
+
+string UIGetEnv(const string& name) {
+ const wchar_t* var = _wgetenv(UTF8ToWide(name).c_str());
+ if (var && *var) {
+ return WideToUTF8(var);
+ }
+
+ return "";
+}
diff --git a/toolkit/crashreporter/client/macbuild/Contents/Info.plist b/toolkit/crashreporter/client/macbuild/Contents/Info.plist
new file mode 100644
index 0000000000..51d6c4de37
--- /dev/null
+++ b/toolkit/crashreporter/client/macbuild/Contents/Info.plist
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>English</string>
+ <key>CFBundleDisplayName</key>
+ <string>crashreporter</string>
+ <key>CFBundleExecutable</key>
+ <string>crashreporter</string>
+ <key>CFBundleIconFile</key>
+ <string>crashreporter.icns</string>
+ <key>CFBundleIdentifier</key>
+ <string>org.mozilla.crashreporter</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleName</key>
+ <string>crashreporter</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string>1.0</string>
+ <key>LSHasLocalizedDisplayName</key>
+ <true/>
+ <key>NSMainNibFile</key>
+ <string>MainMenu</string>
+ <key>NSRequiresAquaSystemAppearance</key>
+ <false/>
+ <key>NSPrincipalClass</key>
+ <string>NSApplication</string>
+ <key>LSUIElement</key>
+ <true/>
+</dict>
+</plist>
diff --git a/toolkit/crashreporter/client/macbuild/Contents/PkgInfo b/toolkit/crashreporter/client/macbuild/Contents/PkgInfo
new file mode 100644
index 0000000000..cae6d0a58f
--- /dev/null
+++ b/toolkit/crashreporter/client/macbuild/Contents/PkgInfo
@@ -0,0 +1,2 @@
+APPL????
+
diff --git a/toolkit/crashreporter/client/macbuild/Contents/Resources/English.lproj/InfoPlist.strings.in b/toolkit/crashreporter/client/macbuild/Contents/Resources/English.lproj/InfoPlist.strings.in
new file mode 100644
index 0000000000..e08ce59eb6
--- /dev/null
+++ b/toolkit/crashreporter/client/macbuild/Contents/Resources/English.lproj/InfoPlist.strings.in
@@ -0,0 +1,8 @@
+/* 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/. */
+
+/* Localized versions of Info.plist keys */
+
+CFBundleName = "Crash Reporter";
+CFBundleDisplayName = "@APP_NAME@ Crash Reporter";
diff --git a/toolkit/crashreporter/client/macbuild/Contents/Resources/English.lproj/MainMenu.nib/classes.nib b/toolkit/crashreporter/client/macbuild/Contents/Resources/English.lproj/MainMenu.nib/classes.nib
new file mode 100644
index 0000000000..254131e431
--- /dev/null
+++ b/toolkit/crashreporter/client/macbuild/Contents/Resources/English.lproj/MainMenu.nib/classes.nib
@@ -0,0 +1,100 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>IBClasses</key>
+ <array>
+ <dict>
+ <key>ACTIONS</key>
+ <dict>
+ <key>closeClicked</key>
+ <string>id</string>
+ <key>includeURLClicked</key>
+ <string>id</string>
+ <key>restartClicked</key>
+ <string>id</string>
+ <key>submitReportClicked</key>
+ <string>id</string>
+ <key>viewReportClicked</key>
+ <string>id</string>
+ <key>viewReportOkClicked</key>
+ <string>id</string>
+ </dict>
+ <key>CLASS</key>
+ <string>CrashReporterUI</string>
+ <key>LANGUAGE</key>
+ <string>ObjC</string>
+ <key>OUTLETS</key>
+ <dict>
+ <key>mCloseButton</key>
+ <string>NSButton</string>
+ <key>mCommentScrollView</key>
+ <string>NSScrollView</string>
+ <key>mCommentText</key>
+ <string>TextViewWithPlaceHolder</string>
+ <key>mDescriptionLabel</key>
+ <string>NSTextField</string>
+ <key>mEmailMeButton</key>
+ <string>NSButton</string>
+ <key>mEmailText</key>
+ <string>NSTextField</string>
+ <key>mErrorCloseButton</key>
+ <string>NSButton</string>
+ <key>mErrorHeaderLabel</key>
+ <string>NSTextField</string>
+ <key>mErrorLabel</key>
+ <string>NSTextField</string>
+ <key>mErrorView</key>
+ <string>NSView</string>
+ <key>mHeaderLabel</key>
+ <string>NSTextField</string>
+ <key>mIncludeURLButton</key>
+ <string>NSButton</string>
+ <key>mProgressIndicator</key>
+ <string>NSProgressIndicator</string>
+ <key>mProgressText</key>
+ <string>NSTextField</string>
+ <key>mRestartButton</key>
+ <string>NSButton</string>
+ <key>mSubmitReportButton</key>
+ <string>NSButton</string>
+ <key>mViewReportButton</key>
+ <string>NSButton</string>
+ <key>mViewReportOkButton</key>
+ <string>NSButton</string>
+ <key>mViewReportTextView</key>
+ <string>NSTextView</string>
+ <key>mViewReportWindow</key>
+ <string>NSWindow</string>
+ <key>mWindow</key>
+ <string>NSWindow</string>
+ </dict>
+ <key>SUPERCLASS</key>
+ <string>NSObject</string>
+ </dict>
+ <dict>
+ <key>ACTIONS</key>
+ <dict>
+ <key>insertTab</key>
+ <string>id</string>
+ </dict>
+ <key>CLASS</key>
+ <string>TextViewWithPlaceHolder</string>
+ <key>LANGUAGE</key>
+ <string>ObjC</string>
+ <key>SUPERCLASS</key>
+ <string>NSTextView</string>
+ </dict>
+ <dict>
+ <key>CLASS</key>
+ <string>FirstResponder</string>
+ <key>LANGUAGE</key>
+ <string>ObjC</string>
+ <key>SUPERCLASS</key>
+ <string>NSObject</string>
+ </dict>
+ </array>
+ <key>IBVersion</key>
+ <string>1</string>
+</dict>
+</plist>
diff --git a/toolkit/crashreporter/client/macbuild/Contents/Resources/English.lproj/MainMenu.nib/info.nib b/toolkit/crashreporter/client/macbuild/Contents/Resources/English.lproj/MainMenu.nib/info.nib
new file mode 100644
index 0000000000..517349ffce
--- /dev/null
+++ b/toolkit/crashreporter/client/macbuild/Contents/Resources/English.lproj/MainMenu.nib/info.nib
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>IBFramework Version</key>
+ <string>629</string>
+ <key>IBOldestOS</key>
+ <integer>5</integer>
+ <key>IBOpenObjects</key>
+ <array>
+ <integer>2</integer>
+ </array>
+ <key>IBSystem Version</key>
+ <string>9C7010</string>
+ <key>targetFramework</key>
+ <string>IBCocoaFramework</string>
+</dict>
+</plist>
diff --git a/toolkit/crashreporter/client/macbuild/Contents/Resources/English.lproj/MainMenu.nib/keyedobjects.nib b/toolkit/crashreporter/client/macbuild/Contents/Resources/English.lproj/MainMenu.nib/keyedobjects.nib
new file mode 100644
index 0000000000..bfdcccb74c
--- /dev/null
+++ b/toolkit/crashreporter/client/macbuild/Contents/Resources/English.lproj/MainMenu.nib/keyedobjects.nib
Binary files differ
diff --git a/toolkit/crashreporter/client/macbuild/Contents/Resources/English.lproj/MainMenuRTL.nib/classes.nib b/toolkit/crashreporter/client/macbuild/Contents/Resources/English.lproj/MainMenuRTL.nib/classes.nib
new file mode 100644
index 0000000000..254131e431
--- /dev/null
+++ b/toolkit/crashreporter/client/macbuild/Contents/Resources/English.lproj/MainMenuRTL.nib/classes.nib
@@ -0,0 +1,100 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>IBClasses</key>
+ <array>
+ <dict>
+ <key>ACTIONS</key>
+ <dict>
+ <key>closeClicked</key>
+ <string>id</string>
+ <key>includeURLClicked</key>
+ <string>id</string>
+ <key>restartClicked</key>
+ <string>id</string>
+ <key>submitReportClicked</key>
+ <string>id</string>
+ <key>viewReportClicked</key>
+ <string>id</string>
+ <key>viewReportOkClicked</key>
+ <string>id</string>
+ </dict>
+ <key>CLASS</key>
+ <string>CrashReporterUI</string>
+ <key>LANGUAGE</key>
+ <string>ObjC</string>
+ <key>OUTLETS</key>
+ <dict>
+ <key>mCloseButton</key>
+ <string>NSButton</string>
+ <key>mCommentScrollView</key>
+ <string>NSScrollView</string>
+ <key>mCommentText</key>
+ <string>TextViewWithPlaceHolder</string>
+ <key>mDescriptionLabel</key>
+ <string>NSTextField</string>
+ <key>mEmailMeButton</key>
+ <string>NSButton</string>
+ <key>mEmailText</key>
+ <string>NSTextField</string>
+ <key>mErrorCloseButton</key>
+ <string>NSButton</string>
+ <key>mErrorHeaderLabel</key>
+ <string>NSTextField</string>
+ <key>mErrorLabel</key>
+ <string>NSTextField</string>
+ <key>mErrorView</key>
+ <string>NSView</string>
+ <key>mHeaderLabel</key>
+ <string>NSTextField</string>
+ <key>mIncludeURLButton</key>
+ <string>NSButton</string>
+ <key>mProgressIndicator</key>
+ <string>NSProgressIndicator</string>
+ <key>mProgressText</key>
+ <string>NSTextField</string>
+ <key>mRestartButton</key>
+ <string>NSButton</string>
+ <key>mSubmitReportButton</key>
+ <string>NSButton</string>
+ <key>mViewReportButton</key>
+ <string>NSButton</string>
+ <key>mViewReportOkButton</key>
+ <string>NSButton</string>
+ <key>mViewReportTextView</key>
+ <string>NSTextView</string>
+ <key>mViewReportWindow</key>
+ <string>NSWindow</string>
+ <key>mWindow</key>
+ <string>NSWindow</string>
+ </dict>
+ <key>SUPERCLASS</key>
+ <string>NSObject</string>
+ </dict>
+ <dict>
+ <key>ACTIONS</key>
+ <dict>
+ <key>insertTab</key>
+ <string>id</string>
+ </dict>
+ <key>CLASS</key>
+ <string>TextViewWithPlaceHolder</string>
+ <key>LANGUAGE</key>
+ <string>ObjC</string>
+ <key>SUPERCLASS</key>
+ <string>NSTextView</string>
+ </dict>
+ <dict>
+ <key>CLASS</key>
+ <string>FirstResponder</string>
+ <key>LANGUAGE</key>
+ <string>ObjC</string>
+ <key>SUPERCLASS</key>
+ <string>NSObject</string>
+ </dict>
+ </array>
+ <key>IBVersion</key>
+ <string>1</string>
+</dict>
+</plist>
diff --git a/toolkit/crashreporter/client/macbuild/Contents/Resources/English.lproj/MainMenuRTL.nib/info.nib b/toolkit/crashreporter/client/macbuild/Contents/Resources/English.lproj/MainMenuRTL.nib/info.nib
new file mode 100644
index 0000000000..4a2251aaf5
--- /dev/null
+++ b/toolkit/crashreporter/client/macbuild/Contents/Resources/English.lproj/MainMenuRTL.nib/info.nib
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>IBFramework Version</key>
+ <string>629</string>
+ <key>IBOldestOS</key>
+ <integer>5</integer>
+ <key>IBOpenObjects</key>
+ <array>
+ <integer>2</integer>
+ </array>
+ <key>IBSystem Version</key>
+ <string>9D34</string>
+ <key>targetFramework</key>
+ <string>IBCocoaFramework</string>
+</dict>
+</plist>
diff --git a/toolkit/crashreporter/client/macbuild/Contents/Resources/English.lproj/MainMenuRTL.nib/keyedobjects.nib b/toolkit/crashreporter/client/macbuild/Contents/Resources/English.lproj/MainMenuRTL.nib/keyedobjects.nib
new file mode 100644
index 0000000000..6c93849b94
--- /dev/null
+++ b/toolkit/crashreporter/client/macbuild/Contents/Resources/English.lproj/MainMenuRTL.nib/keyedobjects.nib
Binary files differ
diff --git a/toolkit/crashreporter/client/macbuild/Contents/Resources/crashreporter.icns b/toolkit/crashreporter/client/macbuild/Contents/Resources/crashreporter.icns
new file mode 100644
index 0000000000..341cd05a4d
--- /dev/null
+++ b/toolkit/crashreporter/client/macbuild/Contents/Resources/crashreporter.icns
Binary files differ
diff --git a/toolkit/crashreporter/client/moz.build b/toolkit/crashreporter/client/moz.build
new file mode 100644
index 0000000000..f678ca1cd6
--- /dev/null
+++ b/toolkit/crashreporter/client/moz.build
@@ -0,0 +1,96 @@
+# -*- 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_TARGET"] != "Android":
+ Program("crashreporter")
+
+ UNIFIED_SOURCES += [
+ "../CrashAnnotations.cpp",
+ "crashreporter.cpp",
+ "ping.cpp",
+ ]
+
+ LOCAL_INCLUDES += [
+ "/toolkit/components/jsoncpp/include",
+ ]
+
+ USE_LIBS += [
+ "jsoncpp",
+ ]
+
+if CONFIG["OS_ARCH"] == "WINNT":
+ UNIFIED_SOURCES += [
+ "crashreporter_win.cpp",
+ ]
+ include("/toolkit/crashreporter/breakpad-client/windows/sender/objs.mozbuild")
+ SOURCES += objs_sender
+ SOURCES += [
+ "../google-breakpad/src/common/windows/http_upload.cc",
+ ]
+ DEFINES["UNICODE"] = True
+ DEFINES["_UNICODE"] = True
+ USE_LIBS += [
+ "nss",
+ ]
+ OS_LIBS += [
+ "advapi32",
+ "comctl32",
+ "gdi32",
+ "ole32",
+ "shell32",
+ "wininet",
+ "shlwapi",
+ "user32",
+ ]
+elif CONFIG["OS_ARCH"] == "Darwin":
+ UNIFIED_SOURCES += [
+ "../google-breakpad/src/common/mac/HTTPMultipartUpload.m",
+ "crashreporter_osx.mm",
+ "crashreporter_unix_common.cpp",
+ ]
+ LOCAL_INCLUDES += [
+ "../google-breakpad/src/common/mac",
+ ]
+ OS_LIBS += ["-framework Cocoa"]
+ USE_LIBS += [
+ "nss",
+ ]
+ LDFLAGS += ["-Wl,-rpath,@executable_path/../../../"]
+elif CONFIG["OS_ARCH"] == "SunOS":
+ SOURCES += [
+ "crashreporter_linux.cpp",
+ "crashreporter_unix.cpp",
+ ]
+ USE_LIBS += [
+ "breakpad_solaris_common_s",
+ ]
+
+if CONFIG["MOZ_WIDGET_TOOLKIT"] == "gtk":
+ UNIFIED_SOURCES += [
+ "../google-breakpad/src/common/linux/http_upload.cc",
+ "crashreporter_gtk_common.cpp",
+ "crashreporter_linux.cpp",
+ "crashreporter_unix_common.cpp",
+ ]
+ OS_LIBS += CONFIG["MOZ_GTK3_LIBS"]
+ OS_LIBS += CONFIG["MOZ_GTHREAD_LIBS"]
+ CXXFLAGS += CONFIG["MOZ_GTK3_CFLAGS"]
+ CXXFLAGS += CONFIG["MOZ_GTHREAD_CFLAGS"]
+
+if CONFIG["OS_ARCH"] == "Linux" or CONFIG["OS_ARCH"] == "SunOS":
+ FINAL_TARGET_FILES += [
+ "Throbber-small.gif",
+ ]
+
+DEFINES["BIN_SUFFIX"] = '"%s"' % CONFIG["BIN_SUFFIX"]
+
+RCINCLUDE = "crashreporter.rc"
+
+# Don't use the STL wrappers in the crashreporter clients; they don't
+# link with -lmozalloc, and it really doesn't matter here anyway.
+DisableStlWrapping()
+
+include("/toolkit/crashreporter/crashreporter.mozbuild")
diff --git a/toolkit/crashreporter/client/ping.cpp b/toolkit/crashreporter/client/ping.cpp
new file mode 100644
index 0000000000..72dc163de2
--- /dev/null
+++ b/toolkit/crashreporter/client/ping.cpp
@@ -0,0 +1,324 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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 "crashreporter.h"
+
+#include <cstring>
+#include <ctime>
+#include <string>
+
+#if defined(XP_LINUX)
+# include <fcntl.h>
+# include <unistd.h>
+# include <sys/stat.h>
+#elif defined(XP_MACOSX)
+# include <CoreFoundation/CoreFoundation.h>
+#elif defined(XP_WIN)
+# include <objbase.h>
+#endif
+
+#include "json/json.h"
+
+#include "CrashAnnotations.h"
+
+using std::string;
+
+namespace CrashReporter {
+
+struct UUID {
+ uint32_t m0;
+ uint16_t m1;
+ uint16_t m2;
+ uint8_t m3[8];
+};
+
+// Generates an UUID; the code here is mostly copied from nsUUIDGenerator.cpp
+static string GenerateUUID() {
+ UUID id = {};
+
+#if defined(XP_WIN) // Windows
+ HRESULT hr = CoCreateGuid((GUID*)&id);
+ if (FAILED(hr)) {
+ return "";
+ }
+#elif defined(XP_MACOSX) // MacOS X
+ CFUUIDRef uuid = CFUUIDCreate(kCFAllocatorDefault);
+ if (!uuid) {
+ return "";
+ }
+
+ CFUUIDBytes bytes = CFUUIDGetUUIDBytes(uuid);
+ memcpy(&id, &bytes, sizeof(UUID));
+
+ CFRelease(uuid);
+#elif defined(HAVE_ARC4RANDOM_BUF) // Android, BSD, ...
+ arc4random_buf(&id, sizeof(UUID));
+#else // Linux
+ int fd = open("/dev/urandom", O_RDONLY);
+
+ if (fd == -1) {
+ return "";
+ }
+
+ if (read(fd, &id, sizeof(UUID)) != sizeof(UUID)) {
+ close(fd);
+ return "";
+ }
+
+ close(fd);
+#endif
+
+ /* Put in the version */
+ id.m2 &= 0x0fff;
+ id.m2 |= 0x4000;
+
+ /* Put in the variant */
+ id.m3[0] &= 0x3f;
+ id.m3[0] |= 0x80;
+
+ const char* kUUIDFormatString =
+ "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x";
+ const size_t kUUIDFormatStringLength = 36;
+ char str[kUUIDFormatStringLength + 1] = {'\0'};
+
+ int num = snprintf(str, kUUIDFormatStringLength + 1, kUUIDFormatString, id.m0,
+ id.m1, id.m2, id.m3[0], id.m3[1], id.m3[2], id.m3[3],
+ id.m3[4], id.m3[5], id.m3[6], id.m3[7]);
+
+ if (num != kUUIDFormatStringLength) {
+ return "";
+ }
+
+ return str;
+}
+
+const char kISO8601Date[] = "%F";
+const char kISO8601DateHours[] = "%FT%H:00:00.000Z";
+
+// Return the current date as a string in the specified format, the following
+// constants are provided:
+// - kISO8601Date, the ISO 8601 date format, YYYY-MM-DD
+// - kISO8601DateHours, the ISO 8601 full date format, YYYY-MM-DDTHH:00:00.000Z
+static string CurrentDate(string format) {
+ time_t now;
+ time(&now);
+ char buf[64]; // This should be plenty
+ strftime(buf, sizeof buf, format.c_str(), gmtime(&now));
+ return buf;
+}
+
+const char kTelemetryClientId[] = "TelemetryClientId";
+const char kTelemetryUrl[] = "TelemetryServerURL";
+const char kTelemetrySessionId[] = "TelemetrySessionId";
+const int kTelemetryVersion = 4;
+
+// Create the payload.metadata node of the crash ping using fields extracted
+// from the .extra file
+static Json::Value CreateMetadataNode(const Json::Value& aExtra) {
+ Json::Value node;
+
+ for (Json::ValueConstIterator iter = aExtra.begin(); iter != aExtra.end();
+ ++iter) {
+ Annotation annotation;
+
+ if (AnnotationFromString(annotation, iter.memberName())) {
+ if (IsAnnotationAllowlistedForPing(annotation)) {
+ node[iter.memberName()] = *iter;
+ }
+ }
+ }
+
+ return node;
+}
+
+// Create the payload node of the crash ping
+static Json::Value CreatePayloadNode(const Json::Value& aExtra,
+ const string& aHash,
+ const string& aSessionId) {
+ Json::Value payload;
+
+ payload["sessionId"] = aSessionId;
+ payload["version"] = 1;
+ payload["crashDate"] = CurrentDate(kISO8601Date);
+ payload["crashTime"] = CurrentDate(kISO8601DateHours);
+ payload["hasCrashEnvironment"] = true;
+ payload["crashId"] = CrashReporter::GetDumpLocalID();
+ payload["minidumpSha256Hash"] = aHash;
+ payload["processType"] = "main"; // This is always a main crash
+ if (aExtra.isMember("StackTraces")) {
+ payload["stackTraces"] = aExtra["StackTraces"];
+ }
+
+ // Assemble the payload metadata
+ payload["metadata"] = CreateMetadataNode(aExtra);
+
+ return payload;
+}
+
+// Create the application node of the crash ping
+static Json::Value CreateApplicationNode(
+ const string& aVendor, const string& aName, const string& aVersion,
+ const string& aDisplayVersion, const string& aPlatformVersion,
+ const string& aChannel, const string& aBuildId, const string& aArchitecture,
+ const string& aXpcomAbi) {
+ Json::Value application;
+
+ application["vendor"] = aVendor;
+ application["name"] = aName;
+ application["buildId"] = aBuildId;
+ application["displayVersion"] = aDisplayVersion;
+ application["platformVersion"] = aPlatformVersion;
+ application["version"] = aVersion;
+ application["channel"] = aChannel;
+ if (!aArchitecture.empty()) {
+ application["architecture"] = aArchitecture;
+ }
+ if (!aXpcomAbi.empty()) {
+ application["xpcomAbi"] = aXpcomAbi;
+ }
+
+ return application;
+}
+
+// Create the root node of the crash ping
+static Json::Value CreateRootNode(
+ const Json::Value& aExtra, const string& aUuid, const string& aHash,
+ const string& aClientId, const string& aSessionId, const string& aName,
+ const string& aVersion, const string& aChannel, const string& aBuildId) {
+ Json::Value root;
+ root["type"] = "crash"; // This is a crash ping
+ root["id"] = aUuid;
+ root["version"] = kTelemetryVersion;
+ root["creationDate"] = CurrentDate(kISO8601DateHours);
+ root["clientId"] = aClientId;
+
+ // Parse the telemetry environment
+ Json::Value environment;
+ Json::Reader reader;
+ string architecture;
+ string xpcomAbi;
+ string displayVersion;
+ string platformVersion;
+
+ if (reader.parse(aExtra["TelemetryEnvironment"].asString(), environment,
+ /* collectComments */ false)) {
+ if (environment.isMember("build") && environment["build"].isObject()) {
+ Json::Value build = environment["build"];
+ if (build.isMember("architecture") && build["architecture"].isString()) {
+ architecture = build["architecture"].asString();
+ }
+ if (build.isMember("xpcomAbi") && build["xpcomAbi"].isString()) {
+ xpcomAbi = build["xpcomAbi"].asString();
+ }
+ if (build.isMember("displayVersion") &&
+ build["displayVersion"].isString()) {
+ displayVersion = build["displayVersion"].asString();
+ }
+ if (build.isMember("platformVersion") &&
+ build["platformVersion"].isString()) {
+ platformVersion = build["platformVersion"].asString();
+ }
+ }
+
+ root["environment"] = environment;
+ }
+
+ root["payload"] = CreatePayloadNode(aExtra, aHash, aSessionId);
+ root["application"] = CreateApplicationNode(
+ aExtra["Vendor"].asString(), aName, aVersion, displayVersion,
+ platformVersion, aChannel, aBuildId, architecture, xpcomAbi);
+
+ return root;
+}
+
+// Generates the URL used to submit the crash ping, see TelemetrySend.sys.mjs
+string GenerateSubmissionUrl(const string& aUrl, const string& aId,
+ const string& aName, const string& aVersion,
+ const string& aChannel, const string& aBuildId) {
+ return aUrl + "/submit/telemetry/" + aId + "/crash/" + aName + "/" +
+ aVersion + "/" + aChannel + "/" + aBuildId +
+ "?v=" + std::to_string(kTelemetryVersion);
+}
+
+// Write out the ping into the specified file.
+//
+// Returns true if the ping was written out successfully, false otherwise.
+static bool WritePing(const string& aPath, const string& aPing) {
+ std::ofstream* f = UIOpenWrite(aPath, std::ios::trunc);
+ bool success = false;
+
+ if (f->is_open()) {
+ *f << aPing;
+ f->close();
+ success = f->good();
+ }
+
+ delete f;
+ return success;
+}
+
+// Assembles the crash ping using the JSON data extracted from the .extra file
+// and sends it using the crash sender. All the telemetry specific data but the
+// environment will be stripped from the annotations so that it won't be sent
+// together with the crash report.
+//
+// Note that the crash ping sender is invoked in a fire-and-forget way so this
+// won't block waiting for the ping to be delivered.
+//
+// Returns true if the ping was assembled and handed over to the pingsender
+// correctly, also populates the aPingUuid parameter with the ping UUID. Returns
+// false otherwise and leaves the aPingUuid parameter unmodified.
+bool SendCrashPing(Json::Value& aExtra, const string& aHash, string& aPingUuid,
+ const string& pingDir) {
+ // Remove the telemetry-related data from the crash annotations
+ Json::Value value;
+ aExtra.removeMember(kTelemetryClientId, &value);
+ string clientId = value.asString();
+ aExtra.removeMember(kTelemetryUrl, &value);
+ string serverUrl = value.asString();
+ aExtra.removeMember(kTelemetrySessionId, &value);
+ string sessionId = value.asString();
+
+ if (clientId.empty() || serverUrl.empty() || sessionId.empty()) {
+ return false;
+ }
+
+ string buildId = aExtra["BuildID"].asString();
+ string channel = aExtra["ReleaseChannel"].asString();
+ string name = aExtra["ProductName"].asString();
+ string version = aExtra["Version"].asString();
+ string uuid = GenerateUUID();
+ string url =
+ GenerateSubmissionUrl(serverUrl, uuid, name, version, channel, buildId);
+
+ if (serverUrl.empty() || uuid.empty()) {
+ return false;
+ }
+
+ Json::Value root = CreateRootNode(aExtra, uuid, aHash, clientId, sessionId,
+ name, version, channel, buildId);
+
+ // Write out the result to the pending pings directory
+ Json::StreamWriterBuilder builder;
+ builder["indentation"] = "";
+ string ping = Json::writeString(builder, root);
+ string pingPath = pingDir + UI_DIR_SEPARATOR + uuid + ".json";
+
+ if (!WritePing(pingPath, ping)) {
+ return false;
+ }
+
+ // Hand over the ping to the sender
+ std::vector<string> args = {url, pingPath};
+ if (UIRunProgram(CrashReporter::GetProgramPath(UI_PING_SENDER_FILENAME),
+ args)) {
+ aPingUuid = uuid;
+ return true;
+ } else {
+ return false;
+ }
+}
+
+} // namespace CrashReporter
diff --git a/toolkit/crashreporter/client/resource.h b/toolkit/crashreporter/client/resource.h
new file mode 100644
index 0000000000..2e7917daa4
--- /dev/null
+++ b/toolkit/crashreporter/client/resource.h
@@ -0,0 +1,35 @@
+/* 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/. */
+
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by crashreporter.rc
+//
+#define IDD_SENDDIALOG 102
+#define IDR_THROBBER 103
+#define IDD_VIEWREPORTDIALOG 104
+#define IDI_MAINICON 105
+#define IDC_PROGRESS 1003
+#define IDC_DESCRIPTIONTEXT 1004
+#define IDC_CLOSEBUTTON 1005
+#define IDC_VIEWREPORTBUTTON 1006
+#define IDC_SUBMITREPORTCHECK 1007
+#define IDC_INCLUDEURLCHECK 1010
+#define IDC_COMMENTTEXT 1011
+#define IDC_RESTARTBUTTON 1012
+#define IDC_DESCRIPTIONLABEL 1013
+#define IDC_PROGRESSTEXT 1014
+#define IDC_THROBBER 1015
+#define IDC_VIEWREPORTTEXT 1016
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+# ifndef APSTUDIO_READONLY_SYMBOLS
+# define _APS_NEXT_RESOURCE_VALUE 106
+# define _APS_NEXT_COMMAND_VALUE 40001
+# define _APS_NEXT_CONTROL_VALUE 1017
+# define _APS_NEXT_SYMED_VALUE 101
+# endif
+#endif
diff --git a/toolkit/crashreporter/content/crashes.css b/toolkit/crashreporter/content/crashes.css
new file mode 100644
index 0000000000..3f08455005
--- /dev/null
+++ b/toolkit/crashreporter/content/crashes.css
@@ -0,0 +1,70 @@
+/* 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/. */
+
+:root {
+ font-family: sans-serif;
+ margin: 40px auto;
+ min-width: 30em;
+ max-width: 60em;
+}
+
+.hidden {
+ display: none;
+}
+
+/* Table layout */
+
+table {
+ width: 100%;
+ padding-bottom: 2em;
+ border-spacing: 0;
+}
+
+th {
+ text-align: start;
+}
+
+th, td {
+ border-bottom: 1px solid var(--in-content-border-color);
+}
+
+th,
+#submitted td {
+ /* Unsubmitted table already gets spacing from button */
+ padding-block: 10px;
+}
+
+.submit-button,
+.crash-link {
+ float: inline-end;
+}
+
+/* Other elements */
+
+.table-title-container {
+ align-items: center;
+ display: flex;
+ justify-content: space-between;
+}
+
+.submitting {
+ background-image: url(chrome://global/skin/icons/loading.png);
+ background-position: center;
+ background-repeat: no-repeat;
+ background-size: 16px;
+}
+
+@media (min-resolution: 1.1dppx) {
+ .submitting {
+ background-image: url(chrome://global/skin/icons/loading@2x.png);
+ }
+}
+
+.submitting .submit-crash-button-label {
+ display: none;
+}
+
+.failed-to-submit {
+ color: #ca8695;
+}
diff --git a/toolkit/crashreporter/content/crashes.html b/toolkit/crashreporter/content/crashes.html
new file mode 100644
index 0000000000..088e01762f
--- /dev/null
+++ b/toolkit/crashreporter/content/crashes.html
@@ -0,0 +1,99 @@
+<!-- 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/. -->
+
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta
+ http-equiv="Content-Security-Policy"
+ content="default-src chrome:; object-src 'none'"
+ />
+ <meta charset="utf-8" />
+ <meta nem="color-scheme" content="light dark" />
+ <link rel="localization" href="crashreporter/aboutcrashes.ftl" />
+ <link rel="stylesheet" href="chrome://global/content/crashes.css" />
+ <link
+ rel="stylesheet"
+ media="screen, projection"
+ href="chrome://global/skin/in-content/common.css"
+ />
+ <script src="chrome://global/content/crashes.js"></script>
+ <title data-l10n-id="crash-reports-title"></title>
+ </head>
+
+ <body>
+ <p id="noConfig" class="hidden" data-l10n-id="no-config-label"></p>
+ <p
+ id="noSubmittedReports"
+ class="hidden"
+ data-l10n-id="no-reports-label"
+ ></p>
+
+ <div id="reportListUnsubmitted" class="hidden">
+ <div class="table-title-container">
+ <h2 data-l10n-id="crashes-unsubmitted-label"></h2>
+ <button
+ id="submitAllUnsubmittedReports"
+ class="submit-button"
+ data-l10n-id="submit-all-button-label"
+ ></button>
+ <button
+ id="clearUnsubmittedReports"
+ data-l10n-id="delete-button-label"
+ ></button>
+ </div>
+ <table>
+ <thead>
+ <tr>
+ <th data-l10n-id="id-heading"></th>
+ <th data-l10n-id="date-crashed-heading"></th>
+ <th></th>
+ </tr>
+ </thead>
+ <tbody id="unsubmitted"></tbody>
+ </table>
+ </div>
+
+ <div id="reportListSubmitted" class="hidden">
+ <div class="table-title-container">
+ <h2 data-l10n-id="crashes-submitted-label"></h2>
+ <button
+ id="clearSubmittedReports"
+ data-l10n-id="delete-button-label"
+ ></button>
+ </div>
+ <table>
+ <thead>
+ <tr>
+ <th data-l10n-id="id-heading"></th>
+ <th data-l10n-id="date-submitted-heading"></th>
+ <th></th>
+ </tr>
+ </thead>
+ <tbody id="submitted"></tbody>
+ </table>
+ </div>
+ </body>
+
+ <template id="crashReportRow">
+ <tr>
+ <td class="crash-id"></td>
+ <td></td>
+ <td></td>
+ </tr>
+ </template>
+
+ <template id="crashSubmitButton">
+ <button class="submit-button">
+ <span
+ class="submit-crash-button-label"
+ data-l10n-id="submit-crash-button-label"
+ ></span>
+ </button>
+ </template>
+
+ <template id="viewCrashLink">
+ <a class="crash-link" data-l10n-id="view-crash-button-label"></a>
+ </template>
+</html>
diff --git a/toolkit/crashreporter/content/crashes.js b/toolkit/crashreporter/content/crashes.js
new file mode 100644
index 0000000000..fe3b2e7225
--- /dev/null
+++ b/toolkit/crashreporter/content/crashes.js
@@ -0,0 +1,316 @@
+/* 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/. */
+
+let reportURL;
+
+const { CrashReports } = ChromeUtils.importESModule(
+ "resource://gre/modules/CrashReports.sys.mjs"
+);
+
+ChromeUtils.defineESModuleGetters(this, {
+ CrashSubmit: "resource://gre/modules/CrashSubmit.sys.mjs",
+});
+
+document.addEventListener("DOMContentLoaded", () => {
+ populateReportLists();
+ document
+ .getElementById("clearUnsubmittedReports")
+ .addEventListener("click", () => {
+ clearUnsubmittedReports().catch(console.error);
+ });
+ document
+ .getElementById("submitAllUnsubmittedReports")
+ .addEventListener("click", () => {
+ submitAllUnsubmittedReports().catch(console.error);
+ });
+ document
+ .getElementById("clearSubmittedReports")
+ .addEventListener("click", () => {
+ clearSubmittedReports().catch(console.error);
+ });
+});
+
+const buildID = Services.appinfo.appBuildID;
+
+/**
+ * Adds the crash reports with submission buttons and links
+ * to the unsubmitted and submitted crash report lists.
+ * If breakpad.reportURL is not set, displays a misconfiguration message
+ * instead.
+ */
+function populateReportLists() {
+ try {
+ reportURL = Services.prefs.getCharPref("breakpad.reportURL");
+ // Ignore any non http/https urls
+ if (!/^https?:/i.test(reportURL)) {
+ reportURL = null;
+ }
+ } catch (e) {
+ reportURL = null;
+ }
+ if (!reportURL) {
+ document.getElementById("noConfig").classList.remove("hidden");
+ return;
+ }
+
+ const reports = CrashReports.getReports();
+ const dateFormatter = new Services.intl.DateTimeFormat(undefined, {
+ timeStyle: "short",
+ dateStyle: "short",
+ });
+ reports.forEach(report =>
+ addReportRow(report.pending, report.id, report.date, dateFormatter)
+ );
+ showAppropriateSections();
+}
+
+/**
+ * Adds a crash report with the appropriate submission button
+ * or viewing link to the unsubmitted or submitted report list
+ * based on isPending.
+ *
+ * @param {Boolean} isPending whether the crash is up for submission
+ * @param {String} id the unique id of the crash report
+ * @param {Date} date either the date of crash or date of submission
+ * @param {Object} dateFormatter formatter for presenting dates to users
+ */
+function addReportRow(isPending, id, date, dateFormatter) {
+ const rowTemplate = document.getElementById("crashReportRow");
+ const row = document
+ .importNode(rowTemplate.content, true)
+ .querySelector("tr");
+ row.id = id;
+
+ const cells = row.querySelectorAll("td");
+ cells[0].appendChild(document.createTextNode(id));
+ cells[1].appendChild(document.createTextNode(dateFormatter.format(date)));
+
+ if (isPending) {
+ const buttonTemplate = document.getElementById("crashSubmitButton");
+ const button = document
+ .importNode(buttonTemplate.content, true)
+ .querySelector("button");
+ const buttonText = button.querySelector("span");
+ button.addEventListener("click", () =>
+ submitPendingReport(id, row, button, buttonText, dateFormatter)
+ );
+ cells[2].appendChild(button);
+ document.getElementById("unsubmitted").appendChild(row);
+ } else {
+ const linkTemplate = document.getElementById("viewCrashLink");
+ const link = document
+ .importNode(linkTemplate.content, true)
+ .querySelector("a");
+ link.href = `${reportURL}${id}`;
+ cells[2].appendChild(link);
+ document.getElementById("submitted").appendChild(row);
+ }
+}
+
+/**
+ * Shows or hides each of the unsubmitted and submitted report list
+ * based on whether they contain at least one crash report.
+ * If hidden, the submitted report list is replaced by a message
+ * indicating that no crash reports have been submitted.
+ */
+function showAppropriateSections() {
+ let hasUnsubmitted =
+ document.getElementById("unsubmitted").childElementCount > 0;
+ document
+ .getElementById("reportListUnsubmitted")
+ .classList.toggle("hidden", !hasUnsubmitted);
+
+ let hasSubmitted = document.getElementById("submitted").childElementCount > 0;
+ document
+ .getElementById("reportListSubmitted")
+ .classList.toggle("hidden", !hasSubmitted);
+ document
+ .getElementById("noSubmittedReports")
+ .classList.toggle("hidden", hasSubmitted);
+}
+
+/**
+ * Changes the provided button to display a spinner. Then, tries to submit the
+ * crash report for the provided id. On success, removes the crash report from
+ * the list of unsubmitted crash reports and adds a new crash report to the list
+ * of submitted crash reports. On failure, changes the provided button to display
+ * a red error message.
+ *
+ * @param {String} reportId the unique id of the crash report
+ * @param {HTMLTableRowElement} row the table row of the crash report
+ * @param {HTMLButtonElement} button the button pressed to start the submission
+ * @param {HTMLSpanElement} buttonText the text inside the pressed button
+ * @param {Object} dateFormatter formatter for presenting dates to users
+ */
+function submitPendingReport(reportId, row, button, buttonText, dateFormatter) {
+ button.classList.add("submitting");
+ document.getElementById("submitAllUnsubmittedReports").disabled = true;
+ CrashSubmit.submit(reportId, CrashSubmit.SUBMITTED_FROM_ABOUT_CRASHES, {
+ noThrottle: true,
+ })
+ .then(
+ remoteCrashID => {
+ document.getElementById("unsubmitted").removeChild(row);
+ const report = CrashReports.getReports().filter(
+ report => report.id === remoteCrashID
+ );
+ addReportRow(false, remoteCrashID, report.date, dateFormatter);
+ showAppropriateSections();
+ dispatchEvent("CrashSubmitSucceeded");
+ },
+ () => {
+ button.classList.remove("submitting");
+ button.classList.add("failed-to-submit");
+ document.l10n.setAttributes(
+ buttonText,
+ "submit-crash-button-failure-label"
+ );
+ dispatchEvent("CrashSubmitFailed");
+ }
+ )
+ .finally(() => {
+ document.getElementById("submitAllUnsubmittedReports").disabled = false;
+ });
+}
+
+/**
+ * Deletes unsubmitted and old crash reports from the user's device.
+ * Then, hides the list of unsubmitted crash reports.
+ */
+async function clearUnsubmittedReports() {
+ const [title, description] = await document.l10n.formatValues([
+ { id: "delete-confirm-title" },
+ { id: "delete-unsubmitted-description" },
+ ]);
+ if (!Services.prompt.confirm(window, title, description)) {
+ return;
+ }
+
+ await enqueueCleanup(() => cleanupFolder(CrashReports.pendingDir.path));
+ await enqueueCleanup(clearOldReports);
+ document.getElementById("reportListUnsubmitted").classList.add("hidden");
+}
+
+/**
+ * Submits all the pending crash reports and removes all pending reports from pending reports list
+ * and add them to submitted crash reports.
+ */
+async function submitAllUnsubmittedReports() {
+ for (
+ var i = 0;
+ i < document.getElementById("unsubmitted").childNodes.length;
+ i++
+ ) {
+ document
+ .getElementById("unsubmitted")
+ .childNodes[i].cells[2].childNodes[0].click();
+ }
+}
+
+/**
+ * Deletes submitted and old crash reports from the user's device.
+ * Then, hides the list of submitted crash reports.
+ */
+async function clearSubmittedReports() {
+ const [title, description] = await document.l10n.formatValues([
+ { id: "delete-confirm-title" },
+ { id: "delete-submitted-description" },
+ ]);
+ if (!Services.prompt.confirm(window, title, description)) {
+ return;
+ }
+
+ await enqueueCleanup(async () =>
+ cleanupFolder(
+ CrashReports.submittedDir.path,
+ async entry => entry.name.startsWith("bp-") && entry.name.endsWith(".txt")
+ )
+ );
+ await enqueueCleanup(clearOldReports);
+ document.getElementById("reportListSubmitted").classList.add("hidden");
+ document.getElementById("noSubmittedReports").classList.remove("hidden");
+}
+
+/**
+ * Deletes old crash reports from the user's device.
+ */
+async function clearOldReports() {
+ const oneYearAgo = Date.now() - 31586000000;
+ await cleanupFolder(CrashReports.reportsDir.path, async entry => {
+ if (
+ !entry.name.startsWith("InstallTime") ||
+ entry.name == "InstallTime" + buildID
+ ) {
+ return false;
+ }
+
+ const stat = await IOUtils.stat(entry.path);
+ return stat.lastModified < oneYearAgo;
+ });
+}
+
+/**
+ * Deletes files from the user's device at the specified path
+ * that match the provided filter.
+ *
+ * @param {String} path the directory location to delete form
+ * @param {Function} filter function taking in a file entry and
+ * returning whether to delete the file
+ */
+async function cleanupFolder(path, filter) {
+ function entry(path) {
+ return {
+ path,
+ name: PathUtils.filename(path),
+ };
+ }
+ let children;
+ try {
+ children = await IOUtils.getChildren(path);
+ } catch (e) {
+ if (DOMException.isInstance(e) || e.name !== "NotFoundError") {
+ throw e;
+ }
+ }
+
+ for (const childPath of children) {
+ if (!filter || (await filter(entry(childPath)))) {
+ await IOUtils.remove(childPath);
+ }
+ }
+}
+
+/**
+ * Dispatches an event with the specified name.
+ *
+ * @param {String} name the name of the event
+ */
+function dispatchEvent(name) {
+ const event = document.createEvent("Events");
+ event.initEvent(name, true, false);
+ document.dispatchEvent(event);
+}
+
+let cleanupQueue = Promise.resolve();
+
+/**
+ * Enqueue a cleanup function.
+ *
+ * Instead of directly calling cleanup functions as a result of DOM
+ * interactions, queue them through this function so that we do not have
+ * overlapping executions of cleanup functions.
+ *
+ * Cleanup functions overlapping could cause a race where one function is
+ * attempting to stat a file while another function is attempting to delete it,
+ * causing an exception.
+ *
+ * @param fn The cleanup function to call. It will be called once the last
+ * cleanup function has resolved.
+ *
+ * @returns A promise to await instead of awaiting the cleanup function.
+ */
+function enqueueCleanup(fn) {
+ cleanupQueue = cleanupQueue.then(fn);
+ return cleanupQueue;
+}
diff --git a/toolkit/crashreporter/crashreporter.mozbuild b/toolkit/crashreporter/crashreporter.mozbuild
new file mode 100644
index 0000000000..8d94b5a179
--- /dev/null
+++ b/toolkit/crashreporter/crashreporter.mozbuild
@@ -0,0 +1,34 @@
+# -*- 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/.
+
+LOCAL_INCLUDES += [
+ '/toolkit/crashreporter/breakpad-client',
+ '/toolkit/crashreporter/google-breakpad/src',
+]
+
+# Suppress warnings in third-party code.
+if CONFIG['CC_TYPE'] == 'clang-cl':
+ CXXFLAGS += [
+ '-Wno-macro-redefined',
+ ]
+elif CONFIG['CC_TYPE'] in ('clang', 'gcc'):
+ CXXFLAGS += [
+ '-Wno-unused-local-typedefs',
+ '-Wno-deprecated-declarations',
+ '-Wno-bool-compare',
+ '-Wno-unused-but-set-variable',
+ ]
+
+if CONFIG['CC_TYPE'] in ('clang', 'clang-cl'):
+ CXXFLAGS += [
+ '-Wno-c++11-narrowing',
+ ]
+
+CXXFLAGS += [
+ '-Wno-implicit-fallthrough',
+]
+
+DEFINES['NO_STABS_SUPPORT'] = True
diff --git a/toolkit/crashreporter/docs/Using_the_Mozilla_symbol_server.rst b/toolkit/crashreporter/docs/Using_the_Mozilla_symbol_server.rst
new file mode 100644
index 0000000000..3f6dc11645
--- /dev/null
+++ b/toolkit/crashreporter/docs/Using_the_Mozilla_symbol_server.rst
@@ -0,0 +1,168 @@
+Using the Mozilla symbol server
+===============================
+
+The Mozilla project runs a symbol server for trunk Firefox nightly and
+release builds on Windows. Symbols are available for at least 30
+previous days worth of nightly builds, and Firefox releases from
+2.0.0.4. This allows debugging of those builds without forcing all users
+to download large debugging files. The server functions like
+`Microsoft's symbol server <https://docs.microsoft.com/windows/win32/dxtecharts/debugging-with-symbols>`__
+so the documentation there can be useful.
+
+Note that because Mozilla release builds are heavily optimized,
+debugging is not always easy. The debugger will not be able to show you
+the content of all variables and the execution path can seem strange
+because of inlining, tail calls, and other compiler optimizations. The
+only workaround is to build an unoptimized local build.
+
+The official symbol server URL for Firefox is ``https://symbols.mozilla.org/``.
+You cannot visit this URL directly: you must add it to the symbol path of your
+debugging tool. In the examples below, a local cache directory is used to avoid
+repeatedly fetching the PDB from the server. Replace
+``C:\Users\myname\symbols`` with an appropriate cache directory on your
+machine.
+
+Using the symbol server in Microsoft Visual C++
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+|The Tools menu of Visual C++ with the Options item selected| |The
+Visual C++ 2017 Symbols pane of the Options dialog with the Mozilla
+symbol server configured|
+
+Using the symbol server in Windbg
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The Windbg symbol path is configured with a string value delimited with
+asterisk characters. To use only the Mozilla symbol server, add the
+following entry to your symbol path (**note:** you can replace ``C:\symcache\``
+with any writable directory on your computer, if you'd prefer a different
+location for downloaded symbols):
+
+.. code::
+
+ SRV*c:\symcache\*https://symbols.mozilla.org/
+
+Set this string as ``_NT_SYMBOL_PATH`` in the environment, using
+the Windbg menus, or by typing the ``.sympath`` command. If you
+would like to get symbols from Microsoft's symbol server as well, you
+should list that first (**note:** you can replace ``C:\symcache\``
+with any writable directory on your computer, if you'd prefer a different
+location for downloaded symbols):
+
+.. code::
+
+ SRV*c:\symcache\*http://msdl.microsoft.com/download/symbols;SRV*c:\symcache\*https://symbols.mozilla.org/
+
+|Image:symbol-server-windbg-menu.jpg| |The WinDbg Symbol Search Path
+dialog with the Mozilla symbol server configured|
+
+Downloading symbols using symchk.exe
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+You can also download the symbols using symchk.exe, part of Microsoft's
+Debugging Tools for Windows. The command should look like this (again,
+you can replace ``C:\symcache\`` with any writable directory on
+your computer, if you'd prefer a different location for downloaded
+symbols):
+
+::
+
+ "C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\symchk.exe" /r "C:\Program Files\Mozilla Firefox/*" /s SRV*C:\symcache\*https://symbols.mozilla.org/
+
+Note the ``\*`` after the Mozilla directory. The output of this command should
+be similar to:
+
+::
+
+ SYMCHK: api-ms-win-core-file-l1-2-0.dll FAILED - api-ms-win-core-file-l1-2-0.pdb mismatched or not found
+ SYMCHK: api-ms-win-core-file-l2-1-0.dll FAILED - api-ms-win-core-file-l2-1-0.pdb mismatched or not found
+ SYMCHK: api-ms-win-core-localization-l1-2-0.dll FAILED - api-ms-win-core-localization-l1-2-0.pdb mismatched or not found
+ SYMCHK: api-ms-win-core-processthreads-l1-1-1.dll FAILED - api-ms-win-core-processthreads-l1-1-1.pdb mismatched or not found
+ SYMCHK: api-ms-win-core-synch-l1-2-0.dll FAILED - api-ms-win-core-synch-l1-2-0.pdb mismatched or not found
+ SYMCHK: api-ms-win-core-timezone-l1-1-0.dll FAILED - api-ms-win-core-timezone-l1-1-0.pdb mismatched or not found
+ SYMCHK: api-ms-win-crt-conio-l1-1-0.dll FAILED - api-ms-win-crt-conio-l1-1-0.pdb mismatched or not found
+ SYMCHK: api-ms-win-crt-convert-l1-1-0.dll FAILED - api-ms-win-crt-convert-l1-1-0.pdb mismatched or not found
+ SYMCHK: api-ms-win-crt-environment-l1-1-0.dll FAILED - api-ms-win-crt-environment-l1-1-0.pdb mismatched or not found
+ SYMCHK: api-ms-win-crt-filesystem-l1-1-0.dll FAILED - api-ms-win-crt-filesystem-l1-1-0.pdb mismatched or not found
+ SYMCHK: api-ms-win-crt-heap-l1-1-0.dll FAILED - api-ms-win-crt-heap-l1-1-0.pdb mismatched or not found
+ SYMCHK: api-ms-win-crt-locale-l1-1-0.dll FAILED - api-ms-win-crt-locale-l1-1-0.pdb mismatched or not found
+ SYMCHK: api-ms-win-crt-math-l1-1-0.dll FAILED - api-ms-win-crt-math-l1-1-0.pdb mismatched or not found
+ SYMCHK: api-ms-win-crt-multibyte-l1-1-0.dll FAILED - api-ms-win-crt-multibyte-l1-1-0.pdb mismatched or not found
+ SYMCHK: api-ms-win-crt-private-l1-1-0.dll FAILED - api-ms-win-crt-private-l1-1-0.pdb mismatched or not found
+ SYMCHK: api-ms-win-crt-process-l1-1-0.dll FAILED - api-ms-win-crt-process-l1-1-0.pdb mismatched or not found
+ SYMCHK: api-ms-win-crt-runtime-l1-1-0.dll FAILED - api-ms-win-crt-runtime-l1-1-0.pdb mismatched or not found
+ SYMCHK: api-ms-win-crt-stdio-l1-1-0.dll FAILED - api-ms-win-crt-stdio-l1-1-0.pdb mismatched or not found
+ SYMCHK: api-ms-win-crt-string-l1-1-0.dll FAILED - api-ms-win-crt-string-l1-1-0.pdb mismatched or not found
+ SYMCHK: api-ms-win-crt-time-l1-1-0.dll FAILED - api-ms-win-crt-time-l1-1-0.pdb mismatched or not found
+ SYMCHK: api-ms-win-crt-utility-l1-1-0.dll FAILED - api-ms-win-crt-utility-l1-1-0.pdb mismatched or not found
+ SYMCHK: d3dcompiler_47.dll FAILED - D3DCompiler_47.pdb mismatched or not found
+ SYMCHK: maintenanceservice_installer.exe FAILED - Built without debugging information.
+ SYMCHK: msvcp140.dll FAILED - msvcp140.amd64.pdb mismatched or not found
+ SYMCHK: ucrtbase.dll FAILED - ucrtbase.pdb mismatched or not found
+ SYMCHK: vcruntime140.dll FAILED - vcruntime140.amd64.pdb mismatched or not found
+ SYMCHK: helper.exe FAILED - Built without debugging information.
+
+ SYMCHK: FAILED files = 27
+ SYMCHK: PASSED + IGNORED files = 60
+
+.. _Downloading symbols on Linux / Mac OS X:
+
+Downloading symbols on Linux / Mac OS X
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+If you are on Linux and running GDB 7.9 or newer, you can use `this GDB
+Python script <https://gist.github.com/luser/193572147c401c8a965c>`__ to
+automatically fetch symbols. You will need to source this script before
+loading symbols (the part where it spends a few seconds loading each .so
+when you attach gdb). If you want to reload symbols, you can try:
+
+::
+
+ nosharedlibrary
+ sharedlibrary lib
+
+On older GDB and Mac OS X there is a `Python script to download symbols
+from the Mozilla symbol
+server <http://hg.mozilla.org/users/jwatt_jwatt.org/fetch-symbols>`__
+for :ref:`gdb <Debugging Firefox with GDB>`, Shark and other software
+that uses symbols. Note that the symbol file for the XUL library is very
+large and takes some time to download. This may make it appear as if the
+script has gotten stuck, but it will continue.
+
+Symbol indices are named like so:
+symbols.mozilla.org/{lowercased:Name}/{lowercased:Name}-{Version}-{Platform}-{BuildID}-symbols.txt.
+The Platform is either 'Darwin' (for Mac) or 'Linux'. The rest of values
+are based on the contents of the application.ini file under the [App]
+heading: For example, the Thunderbird 3.1b2 release with
+Name=Thunderbird, Version=3.1b2, BuildID=20100430125415 would have a
+filename of "thunderbird-3.1b2-Linux-20100430125415-symbols.txt" under
+the thunderbird directory at symbols.mozilla.org. Its contents are a
+list of paths to files, all relative to the directory the
+BLAH-symbols.txt file is found in.
+
+The source server
+~~~~~~~~~~~~~~~~~
+
+In addition to symbols, Mozilla also has a
+:ref:`source server <Using The Mozilla Source Server>`, letting you do
+source-level debugging and inspection on demand.
+
+Troubleshooting: Symbols will not download
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+If symbols will not download no matter what you do, the problem may be
+that Internet Explorer has been set to the **Work Offline** mode. You
+will not receive any warnings of this in Windbg, Visual C++ or Visual
+Studio. Even using the command line with symchk.exe to download symbols
+will fail. This is because Microsoft uses Internet Explorer's internet &
+proxy settings to download the symbol files. Check the File menu of
+Internet Explorer to ensure "Work Offline" is unchecked.
+
+.. |The Tools menu of Visual C++ with the Options item selected| image:: img/vs_tools_options.png
+ :class: internal
+.. |The Visual C++ 2017 Symbols pane of the Options dialog with the Mozilla symbol server configured| image:: img/snip_20170901070042.png
+ :class: internal
+.. |Image:symbol-server-windbg-menu.jpg| image:: img/symbol-server-windbg-menu.jpg
+ :class: internal
+.. |The WinDbg Symbol Search Path dialog with the Mozilla symbol server configured| image:: img/snip_20170901081816.png
+ :class: internal
diff --git a/toolkit/crashreporter/docs/img/snip_20170901070042.png b/toolkit/crashreporter/docs/img/snip_20170901070042.png
new file mode 100644
index 0000000000..94f266d91e
--- /dev/null
+++ b/toolkit/crashreporter/docs/img/snip_20170901070042.png
Binary files differ
diff --git a/toolkit/crashreporter/docs/img/snip_20170901081816.png b/toolkit/crashreporter/docs/img/snip_20170901081816.png
new file mode 100644
index 0000000000..550f0d28ea
--- /dev/null
+++ b/toolkit/crashreporter/docs/img/snip_20170901081816.png
Binary files differ
diff --git a/toolkit/crashreporter/docs/img/symbol-server-windbg-menu.jpg b/toolkit/crashreporter/docs/img/symbol-server-windbg-menu.jpg
new file mode 100644
index 0000000000..000bc761d7
--- /dev/null
+++ b/toolkit/crashreporter/docs/img/symbol-server-windbg-menu.jpg
Binary files differ
diff --git a/toolkit/crashreporter/docs/img/vs_tools_options.png b/toolkit/crashreporter/docs/img/vs_tools_options.png
new file mode 100644
index 0000000000..c16d2094a6
--- /dev/null
+++ b/toolkit/crashreporter/docs/img/vs_tools_options.png
Binary files differ
diff --git a/toolkit/crashreporter/docs/index.rst b/toolkit/crashreporter/docs/index.rst
new file mode 100644
index 0000000000..57b4c3a5e5
--- /dev/null
+++ b/toolkit/crashreporter/docs/index.rst
@@ -0,0 +1,265 @@
+==============
+Crash Reporter
+==============
+
+Overview
+========
+
+The **crash reporter** is a subsystem to record and manage application
+crash data.
+
+While the subsystem is known as *crash reporter*, it helps to think of
+it more as a *process dump manager*. This is because the heart of this
+subsystem is really managing process dump files and these files are
+created not only from process crashes but also from hangs and other
+exceptional events.
+
+The crash reporter subsystem is composed of a number of pieces working
+together.
+
+Breakpad
+ Breakpad is a library and set of tools to make collecting process
+ information (notably dumps from crashes) easy. Breakpad is a 3rd
+ party project (originally developed by Google) that is imported into
+ the tree.
+
+Dump files
+ Breakpad produces files called *dump files* that hold process data
+ (stacks, heap data, etc).
+
+Crash Reporter Client
+ The crash reporter client is a standalone executable that is launched
+ to handle dump files. This application optionally submits crashes to
+ Mozilla (or the configured server).
+
+Minidump Analyzer
+ The minidump analyzer is a standalone executable that is launched by the
+ crash reporter client or by the browser itself to extract stack traces from
+ the dump files generated during a crash. It appends the stack traces to the
+ .extra file associated with the crash dump.
+
+Ping Sender
+ The ping sender is a standalone executable that is launched by the crash
+ reporter client to deliver a crash ping to our telemetry servers. The ping
+ sender is used to speed up delivery of the crash ping which would otherwise
+ have to wait for Firefox to be restarted in order to be sent.
+
+How Main-Process Crash Handling Works
+=====================================
+
+The crash handler is hooked up very early in the Gecko process lifetime.
+It all starts in ``XREMain::XRE_mainInit()`` from ``nsAppRunner.cpp``.
+Assuming crash reporting is enabled, this startup function registers an
+exception handler for the process and tells the crash reporter subsystem
+about basic metadata such as the application name and version.
+
+The registration of the crash reporter exception handler doubles as
+initialization of the crash reporter itself. This happens in
+``CrashReporter::SetExceptionHandler()`` from ``nsExceptionHandler.cpp``.
+The crash reporter figures out what application to use for reporting
+dumped crashes and where to store these dump files on disk. The Breakpad
+exception handler (really just a mechanism for dumping process state) is
+initialized as part of this function. The Breakpad exception handler is
+a ``google_breakpad::ExceptionHandler`` instance and it's stored as
+``gExceptionHandler``.
+
+As the application runs, various other systems may write *annotations*
+or *notes* to the crash reporter to indicate state of the application,
+help with possible reasons for a current or future crash, etc. These are
+performed via ``CrashReporter::AnnotateCrashReport()`` and
+``CrashReporter::AppendAppNotesToCrashReport()`` from
+``nsExceptionHandler.h``.
+
+For well running applications, this is all that happens. However, if a
+crash or similar exceptional event occurs (such as a hang), we need to
+write a crash report.
+
+When an event worthy of writing a dump occurs, the Breakpad exception
+handler is invoked and Breakpad does its thing. When Breakpad has
+finished, it calls back into ``CrashReporter::MinidumpCallback()`` from
+``nsExceptionHandler.cpp`` to tell the crash reporter about what was
+written.
+
+``MinidumpCallback()`` performs a number of actions once a dump has been
+written. It writes a file with the time of the crash so other systems can
+easily determine the time of the last crash. It supplements the dump
+file with an *extra* file containing Mozilla-specific metadata. This data
+includes the annotations set via ``CrashReporter::AnnotateCrashReport()``
+as well as time since last crash, whether garbage collection was active at
+the time of the crash, memory statistics, etc.
+
+If the *crash reporter client* is enabled, ``MinidumpCallback()`` invokes
+it. It simply tries to create a new *crash reporter client* process (e.g.
+*crashreporter.exe*) with the path to the written minidump file as an
+argument.
+
+The *crash reporter client* performs a number of roles. There's a lot going
+on, so you may want to look at ``main()`` in ``crashreporter.cpp``. First,
+stack traces are extracted from the dump via the *minidump analyzer* tool.
+The resulting traces are appended to the .extra file of the crash together with
+the SHA256 hash of the minidump file. Once this
+is done a crash ping is assembled holding the same information as the one
+generated by the ```CrashManager``` and it's sent to the telemetry servers via
+the *ping sender* program. The UUID of the ping is then stored in the extra
+file; the ```CrashManager``` will later pick it up and generate a new ping
+with the same UUID so that the telemetry server can deduplicate both pings.
+Then, the
+*crash reporter client* verifies that the dump data is sane. If it isn't
+(e.g. required metadata is missing), the dump data is ignored. If dump data
+looks sane, the dump data
+is moved into the *pending* directory for the configured data directory
+(defined via the ``MOZ_CRASHREPORTER_DATA_DIRECTORY`` environment variable
+or from the UI). Once this is done, the main crash reporter UI is displayed
+via ``UIShowCrashUI()``. The crash reporter UI is platform specific: there
+are separate versions for Windows, OS X, and various \*NIX presentation
+flavors (such as GTK). The basic gist is a dialog is displayed to the user
+and the user has the opportunity to submit this dump data to a remote
+server.
+
+If a dump is submitted via the crash reporter, the raw dump files are
+removed from the *pending* directory and a file containing the
+crash ID from the remote server for the submitted dump is created in the
+*submitted* directory.
+
+If the user chooses not to submit a dump in the crash reporter UI, the dump
+files are deleted.
+
+And that's pretty much what happens when a crash/dump is written!
+
+Plugin and Child Process Crashes
+================================
+
+Crashes in plugin and child processes are also managed by the crash
+reporting subsystem.
+
+Child process crashes are handled by the ``mozilla::dom::CrashReporterParent``
+class defined in ``dom/ipc``. When a child process crashes, the toplevel IPDL
+actor should check for it by calling TakeMinidump in its ``ActorDestroy``
+Method: see ``mozilla::plugins::PluginModuleParent::ActorDestroy`` and
+``mozilla::plugins::PluginModuleParent::ProcessFirstMinidump``. That method
+is responsible for calling
+``mozilla::dom::CrashReporterParent::GenerateCrashReportForMinidump`` with
+appropriate crash annotations specific to the crash. All child-process
+crashes are annotated with a ``ProcessType`` annotation, such as "content" or
+"plugin".
+
+Once the minidump file has been generated the
+``mozilla::dom::CrashReporterHost`` is notified of the crash. It will first
+try to extract the stack traces from the minidump file using the
+*minidump analyzer*. Then the stack traces will be stored in the extra file
+together with the rest of the crash annotations and finally the crash will be
+recorded by calling ```CrashService.addCrash()```. This last step adds the
+crash to the ```CrashManager``` database and automatically sends a crash ping
+with information about the crash.
+
+Submission of child process crashes is handled by application code. This
+code prompts the user to submit crashes in context-appropriate UI and then
+submits the crashes using ``CrashSubmit.jsm``.
+
+Memory Reports
+==============
+
+When a process detects that it is running low on memory, a memory report is
+saved. If the process crashes, the memory report will be included with the crash
+report. ``nsThread::SaveMemoryReportNearOOM()`` checks to see if the process is
+low on memory every 30 seconds at most and saves a report every 3 minutes at
+most. Since a child process cannot actually save to the hard drive, it instead
+notifies its parent process, which saves the report for it. If a crash does
+occur, the memory report is moved to the *pending* directory with the other dump
+data and an annotation is added to indicate the presence of the report. This
+happens in ``nsExceptionHandler.cpp``, but occurs in different functions
+depending on what process crashed. When the main process crashes, this happens
+in ``MinidumpCallback()``. When a child process crashes, it happens in
+``OnChildProcessDumpRequested()``, with the annotation being added in
+``WriteExtraData()``.
+
+Plugin Hangs
+============
+
+Plugin hangs are handled as crash reports. If a plugin doesn't respond to an
+IPC message after 60 seconds, the plugin IPC code will take minidumps of all
+of the processes involved and then kill the plugin.
+
+In this case, there will be only one .extra file with the crash report metadata,
+but there will be multiple dump files: at least one for the browser process and
+one for the plugin process. All of these files are submitted together as a
+unit. Before submission, the filenames of the files are linked:
+
+- **uuid.extra** - *annotations, includes the `additional_minidumps` annotation
+ holding a comma-separated list of the additional minidumps*
+- **uuid.dmp** - *plugin process dump file*
+- **uuid-<other>.dmp** - *other process dump file as listed in
+ additional_minidumps*
+
+about:crashes
+=============
+
+If the crash reporter subsystem is enabled, the *about:crashes*
+page will be registered with the application. This page provides
+information about previous and submitted crashes.
+
+It is also possible to submit crashes from *about:crashes*.
+
+Environment variables affecting crash reporting
+===============================================
+
+The exception handler and crash reporter client behavior can be altered by
+setting certain environment variables, some of these variables are used for
+testing but quite a few have only internal users.
+
+User-specified environment variables
+------------------------------------
+
+- ``MOZ_CRASHREPORTER`` - The opposite of MOZ_CRASHREPORTER_DISABLE, force
+ crash reporting on even if disabled in application.ini. You must use this to
+ enable crash reporting on debug builds.
+- ``MOZ_CRASHREPORTER_DISABLE`` - Disable Breakpad crash reporting completely
+ in non-debug builds. You can use this if you would rather use the JIT
+ debugger on Windows with the symbol server, for example.
+- ``MOZ_CRASHREPORTER_FULLDUMP`` - Store full application memory in the
+ minidump, so you can open it in a Microsoft debugger. Don't submit it to the
+ server. (Windows only.)
+- ``MOZ_CRASHREPORTER_NO_DELETE_DUMP`` - Don't delete the crash report dump
+ file after submitting it to the server. Minidumps will still be moved to the
+ "Crash Reports/pending" directory.
+- ``MOZ_CRASHREPORTER_NO_REPORT`` - Save the minidump file but don't launch the
+ crash reporting UI or send the report to the server. Minidumps will be stored
+ in the user's profile directory, in a subdirectory named "minidumps".
+- ``MOZ_CRASHREPORTER_SHUTDOWN`` - Save the minidump and then force the
+ application to close. This is useful for content crashes that don't normally
+ close the chrome (main application) processes. This variable would cause the
+ application to close as well.
+- ``MOZ_CRASHREPORTER_URL`` - Sets the URL that the crash reporter will submit
+ reports to.
+
+Environment variables used internally
+-------------------------------------
+
+- ``MOZ_CRASHREPORTER_AUTO_SUBMIT`` - When set causes the crash reporter client
+ to skip the UI flow and submit the crash report directly.
+- ``MOZ_CRASHREPORTER_DATA_DIRECTORY`` - Platform dependent data directory, the
+ pending crash reports will be stored in a subdirectory of this path. This
+ overrides the default one generated by the client's code.
+- ``MOZ_CRASHREPORTER_DUMP_ALL_THREADS`` - When set to 1 stack traces for
+ all threads are generated and sent in the crash ping, when not set only the
+ trace for the crashing thread will be generated instead.
+- ``MOZ_CRASHREPORTER_EVENTS_DIRECTORY`` - Path of the directory holding the
+ crash event files.
+- ``MOZ_CRASHREPORTER_PING_DIRECTORY`` - Path of the directory holding the
+ pending crash ping files.
+- ``MOZ_CRASHREPORTER_RESTART_ARG_<n>`` - Each of these variable specifies one
+ of the arguments that had been passed to the application, the crash reporter
+ client uses them for restarting it.
+- ``MOZ_CRASHREPORTER_RESTART_XUL_APP_FILE`` - If a XUL app file was specified
+ when starting the app it has to be stored in this variable so that the crash
+ reporter client can restart the application.
+- ``MOZ_CRASHREPORTER_STRINGS_OVERRIDE`` - Overrides the path used to load the
+ .ini file holding the strings used in the crash reporter client UI.
+
+Other topics
+============
+
+.. toctree::
+ :titlesonly:
+
+ Using_the_Mozilla_symbol_server
diff --git a/toolkit/crashreporter/generate_crash_reporter_sources.py b/toolkit/crashreporter/generate_crash_reporter_sources.py
new file mode 100644
index 0000000000..9d066a814c
--- /dev/null
+++ b/toolkit/crashreporter/generate_crash_reporter_sources.py
@@ -0,0 +1,205 @@
+# 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/.
+
+import string
+import sys
+import textwrap
+
+import yaml
+
+###############################################################################
+# Language-agnostic functionality #
+###############################################################################
+
+template_header = (
+ "/* This file was autogenerated by "
+ "toolkit/crashreporter/generate_crash_reporter_sources.py. DO NOT EDIT */\n\n"
+)
+
+
+def validate_annotations(annotations):
+ """Ensure that the annotations have all the required fields"""
+
+ for (name, data) in sorted(annotations.items()):
+ if "description" not in data:
+ print("Annotation " + name + " does not have a description\n")
+ sys.exit(1)
+ if "type" not in data:
+ print("Annotation " + name + " does not have a type\n")
+ sys.exit(1)
+ else:
+ annotation_type = data.get("type")
+ valid_types = ["boolean", "integer", "string"]
+ if not any(annotation_type == t for t in valid_types):
+ print(
+ "Annotation "
+ + name
+ + " has an unknown type: "
+ + annotation_type
+ + "\n"
+ )
+ sys.exit(1)
+
+
+def read_annotations(annotations_filename):
+ """Read the annotations from a YAML file.
+ If an error is encountered quit the program."""
+
+ try:
+ with open(annotations_filename, "r") as annotations_file:
+ annotations = yaml.safe_load(annotations_file)
+ except (IOError, ValueError) as e:
+ print("Error parsing " + annotations_filename + ":\n" + str(e) + "\n")
+ sys.exit(1)
+
+ validate_annotations(annotations)
+
+ return annotations
+
+
+def read_template(template_filename):
+ """Read the contents of the template.
+ If an error is encountered quit the program."""
+
+ try:
+ with open(template_filename, "r") as template_file:
+ template = template_file.read()
+ except IOError as ex:
+ print("Error when reading " + template_filename + ":\n" + str(ex) + "\n")
+ sys.exit(1)
+
+ return template
+
+
+def extract_crash_ping_allowlist(annotations):
+ """Extract an array holding the names of the annotations allowlisted for
+ inclusion in the crash ping."""
+
+ return [
+ name for (name, data) in sorted(annotations.items()) if data.get("ping", False)
+ ]
+
+
+###############################################################################
+# C++ code generation #
+###############################################################################
+
+
+def generate_strings(annotations):
+ """Generate strings corresponding to every annotation."""
+
+ names = [
+ ' "' + data.get("altname", name) + '"'
+ for (name, data) in sorted(annotations.items())
+ ]
+
+ return ",\n".join(names)
+
+
+def generate_enum(annotations):
+ """Generate the C++ typed enum holding all the annotations and return it
+ as a string."""
+
+ enum = ""
+
+ for i, (name, _) in enumerate(sorted(annotations.items())):
+ enum += " " + name + " = " + str(i) + ",\n"
+
+ enum += " Count = " + str(len(annotations))
+
+ return enum
+
+
+def generate_array_initializer(contents):
+ """Generates the initializer for a C++ array of annotations."""
+
+ initializer = [" Annotation::" + name for name in contents]
+
+ return ",\n".join(initializer)
+
+
+def generate_header(template, annotations):
+ """Generate a header by filling the template with the the list of
+ annotations and return it as a string."""
+
+ allowlist = extract_crash_ping_allowlist(annotations)
+
+ return template_header + string.Template(template).substitute(
+ {
+ "enum": generate_enum(annotations),
+ "strings": generate_strings(annotations),
+ "allowlist": generate_array_initializer(allowlist),
+ }
+ )
+
+
+def emit_header(output, template_filename, annotations_filename):
+ """Generate the C++ header from the template and write it out."""
+
+ annotations = read_annotations(annotations_filename)
+ template = read_template(template_filename)
+ generated_header = generate_header(template, annotations)
+
+ try:
+ output.write(generated_header)
+ except IOError as ex:
+ print("Error while writing out the generated file:\n" + str(ex) + "\n")
+ sys.exit(1)
+
+
+###############################################################################
+# Java code generation #
+###############################################################################
+
+
+def generate_java_array_initializer(contents):
+ """Generates the initializer for an array of strings.
+ Effectively turns `["a", "b"]` into ' \"a\",\n \"b\"\n'."""
+
+ initializer = ""
+
+ for name in contents:
+ initializer += ' "' + name + '",\n'
+
+ return initializer.strip(",\n")
+
+
+def generate_class(template, annotations):
+ """Fill the class template from the list of annotations."""
+
+ allowlist = extract_crash_ping_allowlist(annotations)
+
+ return template_header + string.Template(template).substitute(
+ {
+ "allowlist": generate_java_array_initializer(allowlist),
+ }
+ )
+
+
+def emit_class(output, annotations_filename):
+ """Generate the CrashReporterConstants.java file."""
+
+ template = textwrap.dedent(
+ """\
+ package org.mozilla.gecko;
+
+ /**
+ * Constants used by the crash reporter. These are generated so that they
+ * are kept in sync with the other C++ and JS users.
+ */
+ public class CrashReporterConstants {
+ public static final String[] ANNOTATION_ALLOWLIST = {
+ ${allowlist}
+ };
+ }"""
+ )
+
+ annotations = read_annotations(annotations_filename)
+ generated_class = generate_class(template, annotations)
+
+ try:
+ output.write(generated_class)
+ except IOError as ex:
+ print("Error while writing out the generated file:\n" + str(ex) + "\n")
+ sys.exit(1)
diff --git a/toolkit/crashreporter/google-breakpad/.gitignore b/toolkit/crashreporter/google-breakpad/.gitignore
new file mode 100644
index 0000000000..058e18361b
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/.gitignore
@@ -0,0 +1,90 @@
+# 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.
+
+# Ignore other VCSs.
+.repo/
+.svn/
+
+# Ignore common compiled artifacts.
+*~
+*.dwo
+*.o
+lib*.a
+/breakpad.pc
+/breakpad-client.pc
+/src/client/linux/linux_client_unittest_shlib
+/src/client/linux/linux_dumper_unittest_helper
+/src/common/linux/google_crashdump_uploader_test
+/src/processor/microdump_stackwalk
+/src/processor/minidump_dump
+/src/processor/minidump_stackwalk
+/src/tools/linux/core2md/core2md
+/src/tools/linux/dump_syms/dump_syms
+/src/tools/linux/md2core/minidump-2-core
+/src/tools/linux/symupload/minidump_upload
+/src/tools/linux/symupload/sym_upload
+/src/tools/mac/dump_syms/dump_syms
+/src/tools/mac/dump_syms/dump_syms_mac
+
+# Ignore unit test artifacts.
+*_unittest
+*.log
+*.trs
+
+# Ignore autotools generated artifacts.
+.deps
+.dirstamp
+autom4te.cache/
+/config.cache
+config.h
+/config.log
+/config.status
+/Makefile
+stamp-h1
+
+# Ignore GYP generated Visual Studio artifacts.
+*.filters
+*.sdf
+*.sln
+*.suo
+*.vcproj
+*.vcxproj
+
+# Ignore GYP generated Makefiles
+src/Makefile
+*.Makefile
+*.target.mk
+
+# Ignore compiled Python files.
+*.pyc
+
+# Ignore directories gclient syncs.
+src/testing
+src/third_party/lss
+src/third_party/protobuf
+src/tools/gyp
diff --git a/toolkit/crashreporter/google-breakpad/AUTHORS b/toolkit/crashreporter/google-breakpad/AUTHORS
new file mode 100644
index 0000000000..4858b377c7
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/AUTHORS
@@ -0,0 +1 @@
+opensource@google.com
diff --git a/toolkit/crashreporter/google-breakpad/ChangeLog b/toolkit/crashreporter/google-breakpad/ChangeLog
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/ChangeLog
diff --git a/toolkit/crashreporter/google-breakpad/DEPS b/toolkit/crashreporter/google-breakpad/DEPS
new file mode 100644
index 0000000000..3ddaf4e3a7
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/DEPS
@@ -0,0 +1,84 @@
+# Copyright 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 used to mimic the svn:externals mechanism for gclient (both Git and
+# SVN) based checkouts of Breakpad. As such, its use is entirely optional. If
+# using a manually managed SVN checkout as opposed to a gclient managed checkout
+# you can still use the hooks mechanism for generating project files by calling
+# 'gclient runhooks' rather than 'gclient sync'.
+
+deps = {
+ # Testing libraries and utilities.
+ "src/src/testing":
+ "https://github.com/google/googletest.git" +
+ "@5ec7f0c4a113e2f18ac2c6cc7df51ad6afc24081",
+
+ # Protobuf.
+ "src/src/third_party/protobuf/protobuf":
+ "https://github.com/google/protobuf.git" +
+ "@cb6dd4ef5f82e41e06179dcd57d3b1d9246ad6ac",
+
+ # GYP project generator.
+ "src/src/tools/gyp":
+ "https://chromium.googlesource.com/external/gyp/" +
+ "@324dd166b7c0b39d513026fa52d6280ac6d56770",
+
+ # Linux syscall support.
+ "src/src/third_party/lss":
+ "https://chromium.googlesource.com/linux-syscall-support/" +
+ "@fd00dbbd0c06a309c657d89e9430143b179ff6db",
+}
+
+hooks = [
+ {
+ # Keep the manifest up to date.
+ "action": ["python", "src/src/tools/python/deps-to-manifest.py",
+ "src/DEPS", "src/default.xml"],
+ },
+]
+
+hooks_os = {
+ 'win': [
+ {
+ # TODO(chrisha): Fix the GYP files so that they work without
+ # --no-circular-check.
+ "pattern": ".",
+ "action": ["python",
+ "src/src/tools/gyp/gyp_main.py",
+ "--no-circular-check",
+ "src/src/client/windows/breakpad_client.gyp"],
+ },
+ {
+ # XXX: this and above should all be wired into build/all.gyp ?
+ "action": ["python",
+ "src/src/tools/gyp/gyp_main.py",
+ "--no-circular-check",
+ "src/src/tools/windows/tools_windows.gyp"],
+ },
+ ],
+}
diff --git a/toolkit/crashreporter/google-breakpad/GIT-INFO b/toolkit/crashreporter/google-breakpad/GIT-INFO
new file mode 100644
index 0000000000..44c344fb8b
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/GIT-INFO
@@ -0,0 +1 @@
+5bba75bfd6ec386b8e3af0b91332388a378135bf
diff --git a/toolkit/crashreporter/google-breakpad/INSTALL b/toolkit/crashreporter/google-breakpad/INSTALL
new file mode 100644
index 0000000000..007e9396d0
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/INSTALL
@@ -0,0 +1,370 @@
+Installation Instructions
+*************************
+
+Copyright (C) 1994-1996, 1999-2002, 2004-2013 Free Software Foundation,
+Inc.
+
+ Copying and distribution of this file, with or without modification,
+are permitted in any medium without royalty provided the copyright
+notice and this notice are preserved. This file is offered as-is,
+without warranty of any kind.
+
+Basic Installation
+==================
+
+ Briefly, the shell commands `./configure; make; make install' should
+configure, build, and install this package. The following
+more-detailed instructions are generic; see the `README' file for
+instructions specific to this package. Some packages provide this
+`INSTALL' file but do not implement all of the features documented
+below. The lack of an optional feature in a given package is not
+necessarily a bug. More recommendations for GNU packages can be found
+in *note Makefile Conventions: (standards)Makefile Conventions.
+
+ The `configure' shell script attempts to guess correct values for
+various system-dependent variables used during compilation. It uses
+those values to create a `Makefile' in each directory of the package.
+It may also create one or more `.h' files containing system-dependent
+definitions. Finally, it creates a shell script `config.status' that
+you can run in the future to recreate the current configuration, and a
+file `config.log' containing compiler output (useful mainly for
+debugging `configure').
+
+ It can also use an optional file (typically called `config.cache'
+and enabled with `--cache-file=config.cache' or simply `-C') that saves
+the results of its tests to speed up reconfiguring. Caching is
+disabled by default to prevent problems with accidental use of stale
+cache files.
+
+ If you need to do unusual things to compile the package, please try
+to figure out how `configure' could check whether to do them, and mail
+diffs or instructions to the address given in the `README' so they can
+be considered for the next release. If you are using the cache, and at
+some point `config.cache' contains results you don't want to keep, you
+may remove or edit it.
+
+ The file `configure.ac' (or `configure.in') is used to create
+`configure' by a program called `autoconf'. You need `configure.ac' if
+you want to change it or regenerate `configure' using a newer version
+of `autoconf'.
+
+ The simplest way to compile this package is:
+
+ 1. `cd' to the directory containing the package's source code and type
+ `./configure' to configure the package for your system.
+
+ Running `configure' might take a while. While running, it prints
+ some messages telling which features it is checking for.
+
+ 2. Type `make' to compile the package.
+
+ 3. Optionally, type `make check' to run any self-tests that come with
+ the package, generally using the just-built uninstalled binaries.
+
+ 4. Type `make install' to install the programs and any data files and
+ documentation. When installing into a prefix owned by root, it is
+ recommended that the package be configured and built as a regular
+ user, and only the `make install' phase executed with root
+ privileges.
+
+ 5. Optionally, type `make installcheck' to repeat any self-tests, but
+ this time using the binaries in their final installed location.
+ This target does not install anything. Running this target as a
+ regular user, particularly if the prior `make install' required
+ root privileges, verifies that the installation completed
+ correctly.
+
+ 6. You can remove the program binaries and object files from the
+ source code directory by typing `make clean'. To also remove the
+ files that `configure' created (so you can compile the package for
+ a different kind of computer), type `make distclean'. There is
+ also a `make maintainer-clean' target, but that is intended mainly
+ for the package's developers. If you use it, you may have to get
+ all sorts of other programs in order to regenerate files that came
+ with the distribution.
+
+ 7. Often, you can also type `make uninstall' to remove the installed
+ files again. In practice, not all packages have tested that
+ uninstallation works correctly, even though it is required by the
+ GNU Coding Standards.
+
+ 8. Some packages, particularly those that use Automake, provide `make
+ distcheck', which can by used by developers to test that all other
+ targets like `make install' and `make uninstall' work correctly.
+ This target is generally not run by end users.
+
+Compilers and Options
+=====================
+
+ Some systems require unusual options for compilation or linking that
+the `configure' script does not know about. Run `./configure --help'
+for details on some of the pertinent environment variables.
+
+ You can give `configure' initial values for configuration parameters
+by setting variables in the command line or in the environment. Here
+is an example:
+
+ ./configure CC=c99 CFLAGS=-g LIBS=-lposix
+
+ *Note Defining Variables::, for more details.
+
+Compiling For Multiple Architectures
+====================================
+
+ You can compile the package for more than one kind of computer at the
+same time, by placing the object files for each architecture in their
+own directory. To do this, you can use GNU `make'. `cd' to the
+directory where you want the object files and executables to go and run
+the `configure' script. `configure' automatically checks for the
+source code in the directory that `configure' is in and in `..'. This
+is known as a "VPATH" build.
+
+ With a non-GNU `make', it is safer to compile the package for one
+architecture at a time in the source code directory. After you have
+installed the package for one architecture, use `make distclean' before
+reconfiguring for another architecture.
+
+ On MacOS X 10.5 and later systems, you can create libraries and
+executables that work on multiple system types--known as "fat" or
+"universal" binaries--by specifying multiple `-arch' options to the
+compiler but only a single `-arch' option to the preprocessor. Like
+this:
+
+ ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
+ CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
+ CPP="gcc -E" CXXCPP="g++ -E"
+
+ This is not guaranteed to produce working output in all cases, you
+may have to build one architecture at a time and combine the results
+using the `lipo' tool if you have problems.
+
+Installation Names
+==================
+
+ By default, `make install' installs the package's commands under
+`/usr/local/bin', include files under `/usr/local/include', etc. You
+can specify an installation prefix other than `/usr/local' by giving
+`configure' the option `--prefix=PREFIX', where PREFIX must be an
+absolute file name.
+
+ You can specify separate installation prefixes for
+architecture-specific files and architecture-independent files. If you
+pass the option `--exec-prefix=PREFIX' to `configure', the package uses
+PREFIX as the prefix for installing programs and libraries.
+Documentation and other data files still use the regular prefix.
+
+ In addition, if you use an unusual directory layout you can give
+options like `--bindir=DIR' to specify different values for particular
+kinds of files. Run `configure --help' for a list of the directories
+you can set and what kinds of files go in them. In general, the
+default for these options is expressed in terms of `${prefix}', so that
+specifying just `--prefix' will affect all of the other directory
+specifications that were not explicitly provided.
+
+ The most portable way to affect installation locations is to pass the
+correct locations to `configure'; however, many packages provide one or
+both of the following shortcuts of passing variable assignments to the
+`make install' command line to change installation locations without
+having to reconfigure or recompile.
+
+ The first method involves providing an override variable for each
+affected directory. For example, `make install
+prefix=/alternate/directory' will choose an alternate location for all
+directory configuration variables that were expressed in terms of
+`${prefix}'. Any directories that were specified during `configure',
+but not in terms of `${prefix}', must each be overridden at install
+time for the entire installation to be relocated. The approach of
+makefile variable overrides for each directory variable is required by
+the GNU Coding Standards, and ideally causes no recompilation.
+However, some platforms have known limitations with the semantics of
+shared libraries that end up requiring recompilation when using this
+method, particularly noticeable in packages that use GNU Libtool.
+
+ The second method involves providing the `DESTDIR' variable. For
+example, `make install DESTDIR=/alternate/directory' will prepend
+`/alternate/directory' before all installation names. The approach of
+`DESTDIR' overrides is not required by the GNU Coding Standards, and
+does not work on platforms that have drive letters. On the other hand,
+it does better at avoiding recompilation issues, and works well even
+when some directory options were not specified in terms of `${prefix}'
+at `configure' time.
+
+Optional Features
+=================
+
+ If the package supports it, you can cause programs to be installed
+with an extra prefix or suffix on their names by giving `configure' the
+option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
+
+ Some packages pay attention to `--enable-FEATURE' options to
+`configure', where FEATURE indicates an optional part of the package.
+They may also pay attention to `--with-PACKAGE' options, where PACKAGE
+is something like `gnu-as' or `x' (for the X Window System). The
+`README' should mention any `--enable-' and `--with-' options that the
+package recognizes.
+
+ For packages that use the X Window System, `configure' can usually
+find the X include and library files automatically, but if it doesn't,
+you can use the `configure' options `--x-includes=DIR' and
+`--x-libraries=DIR' to specify their locations.
+
+ Some packages offer the ability to configure how verbose the
+execution of `make' will be. For these packages, running `./configure
+--enable-silent-rules' sets the default to minimal output, which can be
+overridden with `make V=1'; while running `./configure
+--disable-silent-rules' sets the default to verbose, which can be
+overridden with `make V=0'.
+
+Particular systems
+==================
+
+ On HP-UX, the default C compiler is not ANSI C compatible. If GNU
+CC is not installed, it is recommended to use the following options in
+order to use an ANSI C compiler:
+
+ ./configure CC="cc -Ae -D_XOPEN_SOURCE=500"
+
+and if that doesn't work, install pre-built binaries of GCC for HP-UX.
+
+ HP-UX `make' updates targets which have the same time stamps as
+their prerequisites, which makes it generally unusable when shipped
+generated files such as `configure' are involved. Use GNU `make'
+instead.
+
+ On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot
+parse its `<wchar.h>' header file. The option `-nodtk' can be used as
+a workaround. If GNU CC is not installed, it is therefore recommended
+to try
+
+ ./configure CC="cc"
+
+and if that doesn't work, try
+
+ ./configure CC="cc -nodtk"
+
+ On Solaris, don't put `/usr/ucb' early in your `PATH'. This
+directory contains several dysfunctional programs; working variants of
+these programs are available in `/usr/bin'. So, if you need `/usr/ucb'
+in your `PATH', put it _after_ `/usr/bin'.
+
+ On Haiku, software installed for all users goes in `/boot/common',
+not `/usr/local'. It is recommended to use the following options:
+
+ ./configure --prefix=/boot/common
+
+Specifying the System Type
+==========================
+
+ There may be some features `configure' cannot figure out
+automatically, but needs to determine by the type of machine the package
+will run on. Usually, assuming the package is built to be run on the
+_same_ architectures, `configure' can figure that out, but if it prints
+a message saying it cannot guess the machine type, give it the
+`--build=TYPE' option. TYPE can either be a short name for the system
+type, such as `sun4', or a canonical name which has the form:
+
+ CPU-COMPANY-SYSTEM
+
+where SYSTEM can have one of these forms:
+
+ OS
+ KERNEL-OS
+
+ See the file `config.sub' for the possible values of each field. If
+`config.sub' isn't included in this package, then this package doesn't
+need to know the machine type.
+
+ If you are _building_ compiler tools for cross-compiling, you should
+use the option `--target=TYPE' to select the type of system they will
+produce code for.
+
+ If you want to _use_ a cross compiler, that generates code for a
+platform different from the build platform, you should specify the
+"host" platform (i.e., that on which the generated programs will
+eventually be run) with `--host=TYPE'.
+
+Sharing Defaults
+================
+
+ If you want to set default values for `configure' scripts to share,
+you can create a site shell script called `config.site' that gives
+default values for variables like `CC', `cache_file', and `prefix'.
+`configure' looks for `PREFIX/share/config.site' if it exists, then
+`PREFIX/etc/config.site' if it exists. Or, you can set the
+`CONFIG_SITE' environment variable to the location of the site script.
+A warning: not all `configure' scripts look for a site script.
+
+Defining Variables
+==================
+
+ Variables not defined in a site shell script can be set in the
+environment passed to `configure'. However, some packages may run
+configure again during the build, and the customized values of these
+variables may be lost. In order to avoid this problem, you should set
+them in the `configure' command line, using `VAR=value'. For example:
+
+ ./configure CC=/usr/local2/bin/gcc
+
+causes the specified `gcc' to be used as the C compiler (unless it is
+overridden in the site shell script).
+
+Unfortunately, this technique does not work for `CONFIG_SHELL' due to
+an Autoconf limitation. Until the limitation is lifted, you can use
+this workaround:
+
+ CONFIG_SHELL=/bin/bash ./configure CONFIG_SHELL=/bin/bash
+
+`configure' Invocation
+======================
+
+ `configure' recognizes the following options to control how it
+operates.
+
+`--help'
+`-h'
+ Print a summary of all of the options to `configure', and exit.
+
+`--help=short'
+`--help=recursive'
+ Print a summary of the options unique to this package's
+ `configure', and exit. The `short' variant lists options used
+ only in the top level, while the `recursive' variant lists options
+ also present in any nested packages.
+
+`--version'
+`-V'
+ Print the version of Autoconf used to generate the `configure'
+ script, and exit.
+
+`--cache-file=FILE'
+ Enable the cache: use and save the results of the tests in FILE,
+ traditionally `config.cache'. FILE defaults to `/dev/null' to
+ disable caching.
+
+`--config-cache'
+`-C'
+ Alias for `--cache-file=config.cache'.
+
+`--quiet'
+`--silent'
+`-q'
+ Do not print messages saying which checks are being made. To
+ suppress all normal output, redirect it to `/dev/null' (any error
+ messages will still be shown).
+
+`--srcdir=DIR'
+ Look for the package's source code in directory DIR. Usually
+ `configure' can determine that directory automatically.
+
+`--prefix=DIR'
+ Use DIR as the installation prefix. *note Installation Names::
+ for more details, including other options available for fine-tuning
+ the installation locations.
+
+`--no-create'
+`-n'
+ Run the configure checks, but stop before creating any output
+ files.
+
+`configure' also accepts some other, not widely useful, options. Run
+`configure --help' for more details.
diff --git a/toolkit/crashreporter/google-breakpad/LICENSE b/toolkit/crashreporter/google-breakpad/LICENSE
new file mode 100644
index 0000000000..95207bdf6f
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/LICENSE
@@ -0,0 +1,50 @@
+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.
+
+--------------------------------------------------------------------
+
+Copyright 2001-2004 Unicode, Inc.
+
+Disclaimer
+
+This source code is provided as is by Unicode, Inc. No claims are
+made as to fitness for any particular purpose. No warranties of any
+kind are expressed or implied. The recipient agrees to determine
+applicability of information provided. If this file has been
+purchased on magnetic or optical media from Unicode, Inc., the
+sole remedy for any claim will be exchange of defective media
+within 90 days of receipt.
+
+Limitations on Rights to Redistribute This Code
+
+Unicode, Inc. hereby grants the right to freely use the information
+supplied in this file in the creation of products supporting the
+Unicode Standard, and to make copies of this file in any form
+for internal or external distribution as long as this notice
+remains attached.
diff --git a/toolkit/crashreporter/google-breakpad/Makefile.am b/toolkit/crashreporter/google-breakpad/Makefile.am
new file mode 100644
index 0000000000..9a25d9d415
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/Makefile.am
@@ -0,0 +1,1576 @@
+## Process this file with automake to produce Makefile.in
+
+# 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.
+
+
+# This allows #includes to be relative to src/
+AM_CPPFLAGS = -I$(top_srcdir)/src
+AM_CFLAGS =
+AM_CXXFLAGS =
+
+if ANDROID_HOST
+# This allows using fixed NDK headers when building for Android.
+AM_CXXFLAGS += -I$(top_srcdir)/src/common/android/include
+# This is only necessary for building the unit tests until GTest is upgraded
+# to a future version.
+AM_CXXFLAGS += -I$(top_srcdir)/src/common/android/testing/include
+endif
+
+AM_CXXFLAGS += $(WARN_CXXFLAGS)
+
+if LINUX_HOST
+# Build as PIC on Linux, for linux_client_unittest_shlib
+AM_CFLAGS += -fPIC
+AM_CXXFLAGS += -fPIC
+endif
+
+# Specify include paths for ac macros
+ACLOCAL_AMFLAGS = -I m4
+
+# License file is called LICENSE not COPYING
+AUTOMAKE_OPTIONS = foreign
+
+## Documentation
+docdir = $(prefix)/share/doc/$(PACKAGE)-$(VERSION)
+
+dist_doc_DATA = \
+ AUTHORS \
+ ChangeLog \
+ INSTALL \
+ LICENSE \
+ NEWS \
+ README.md
+
+## Headers
+if LINUX_HOST
+includeclhdir = $(includedir)/$(PACKAGE)/client/linux/handler
+includeclh_HEADERS = $(top_srcdir)/src/client/linux/handler/*.h
+
+includecldwcdir = $(includedir)/$(PACKAGE)/client/linux/dump_writer_common
+includecldwc_HEADERS = $(top_srcdir)/src/client/linux/dump_writer_common/*.h
+
+includeclmdir = $(includedir)/$(PACKAGE)/client/linux/minidump_writer
+includeclm_HEADERS = $(top_srcdir)/src/client/linux/minidump_writer/*.h
+
+includeclcdir = $(includedir)/$(PACKAGE)/client/linux/crash_generation
+includeclc_HEADERS = $(top_srcdir)/src/client/linux/crash_generation/*.h
+
+includelssdir = $(includedir)/$(PACKAGE)/third_party/lss
+includelss_HEADERS = $(top_srcdir)/src/third_party/lss/*.h
+
+includecldir = $(includedir)/$(PACKAGE)/common/linux
+includecl_HEADERS = $(top_srcdir)/src/common/linux/*.h
+endif
+
+includegbcdir = $(includedir)/$(PACKAGE)/google_breakpad/common
+includegbc_HEADERS = $(top_srcdir)/src/google_breakpad/common/*.h
+
+includecdir = $(includedir)/$(PACKAGE)/common
+includec_HEADERS = $(top_srcdir)/src/common/*.h
+
+includepdir = $(includedir)/$(PACKAGE)/processor
+includep_HEADERS = $(top_srcdir)/src/processor/*.h
+
+## pkgconfig files
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA =
+
+## Common test logic
+if SYSTEM_TEST_LIBS
+TEST_CFLAGS = $(GTEST_CFLAGS) $(GMOCK_CFLAGS)
+TEST_LIBS = $(GTEST_LIBS) -lgtest_main $(GMOCK_LIBS)
+TEST_DEPS =
+else
+TEST_CFLAGS = \
+ -I$(top_srcdir)/src/testing/include \
+ -I$(top_srcdir)/src/testing/googletest/include \
+ -I$(top_srcdir)/src/testing/googletest \
+ -I$(top_srcdir)/src/testing/googlemock/include \
+ -I$(top_srcdir)/src/testing/googlemock \
+ -I$(top_srcdir)/src/testing
+TEST_LIBS = src/testing/libtesting.a
+TEST_DEPS = $(TEST_LIBS)
+endif
+
+## Libraries
+check_LIBRARIES =
+noinst_LIBRARIES =
+lib_LIBRARIES =
+bin_PROGRAMS =
+check_PROGRAMS =
+EXTRA_PROGRAMS =
+CLEANFILES =
+
+check_LIBRARIES += src/testing/libtesting.a
+
+if !SYSTEM_TEST_LIBS
+src_testing_libtesting_a_SOURCES = \
+ src/breakpad_googletest_includes.h \
+ src/testing/googletest/src/gtest-all.cc \
+ src/testing/googletest/src/gtest_main.cc \
+ src/testing/googlemock/src/gmock-all.cc
+src_testing_libtesting_a_CPPFLAGS = \
+ $(AM_CPPFLAGS) $(TEST_CFLAGS)
+endif
+
+if !DISABLE_PROCESSOR
+lib_LIBRARIES += src/libbreakpad.a
+pkgconfig_DATA += breakpad.pc
+noinst_LIBRARIES += src/third_party/libdisasm/libdisasm.a
+endif
+
+if LINUX_HOST
+lib_LIBRARIES += src/client/linux/libbreakpad_client.a
+pkgconfig_DATA += breakpad-client.pc
+
+src_client_linux_libbreakpad_client_a_SOURCES = \
+ src/client/linux/crash_generation/crash_generation_client.cc \
+ src/client/linux/crash_generation/crash_generation_server.cc \
+ src/client/linux/dump_writer_common/thread_info.cc \
+ src/client/linux/dump_writer_common/ucontext_reader.cc \
+ src/client/linux/handler/exception_handler.cc \
+ src/client/linux/handler/exception_handler.h \
+ src/client/linux/handler/minidump_descriptor.cc \
+ src/client/linux/handler/minidump_descriptor.h \
+ src/client/linux/log/log.cc \
+ src/client/linux/log/log.h \
+ src/client/linux/microdump_writer/microdump_writer.cc \
+ src/client/linux/microdump_writer/microdump_writer.h \
+ src/client/linux/minidump_writer/linux_core_dumper.cc \
+ src/client/linux/minidump_writer/linux_dumper.cc \
+ src/client/linux/minidump_writer/linux_ptrace_dumper.cc \
+ src/client/linux/minidump_writer/minidump_writer.cc \
+ src/client/minidump_file_writer-inl.h \
+ src/client/minidump_file_writer.cc \
+ src/client/minidump_file_writer.h \
+ src/common/convert_UTF.cc \
+ src/common/convert_UTF.h \
+ src/common/md5.cc \
+ src/common/md5.h \
+ src/common/string_conversion.cc \
+ src/common/string_conversion.h \
+ src/common/linux/elf_core_dump.cc \
+ src/common/linux/elfutils.cc \
+ src/common/linux/elfutils.h \
+ src/common/linux/file_id.cc \
+ src/common/linux/file_id.h \
+ src/common/linux/guid_creator.cc \
+ src/common/linux/guid_creator.h \
+ src/common/linux/linux_libc_support.cc \
+ src/common/linux/memory_mapped_file.cc \
+ src/common/linux/safe_readlink.cc
+if !HAVE_GETCONTEXT
+src_client_linux_libbreakpad_client_a_SOURCES += \
+ src/common/linux/breakpad_getcontext.S
+endif
+endif LINUX_HOST
+
+if !DISABLE_PROCESSOR
+src_libbreakpad_a_SOURCES = \
+ src/google_breakpad/common/breakpad_types.h \
+ src/google_breakpad/common/minidump_format.h \
+ src/google_breakpad/common/minidump_size.h \
+ src/google_breakpad/processor/basic_source_line_resolver.h \
+ src/google_breakpad/processor/call_stack.h \
+ src/google_breakpad/processor/code_module.h \
+ src/google_breakpad/processor/code_modules.h \
+ src/google_breakpad/processor/dump_context.h \
+ src/google_breakpad/processor/dump_object.h \
+ src/google_breakpad/processor/exploitability.h \
+ src/google_breakpad/processor/fast_source_line_resolver.h \
+ src/google_breakpad/processor/memory_region.h \
+ src/google_breakpad/processor/microdump.h \
+ src/google_breakpad/processor/microdump_processor.h \
+ src/google_breakpad/processor/minidump.h \
+ src/google_breakpad/processor/minidump_processor.h \
+ src/google_breakpad/processor/process_result.h \
+ src/google_breakpad/processor/process_state.h \
+ src/google_breakpad/processor/proc_maps_linux.h \
+ src/google_breakpad/processor/source_line_resolver_base.h \
+ src/google_breakpad/processor/source_line_resolver_interface.h \
+ src/google_breakpad/processor/stack_frame.h \
+ src/google_breakpad/processor/stack_frame_cpu.h \
+ src/google_breakpad/processor/stack_frame_symbolizer.h \
+ src/google_breakpad/processor/stackwalker.h \
+ src/google_breakpad/processor/symbol_supplier.h \
+ src/google_breakpad/processor/system_info.h \
+ src/processor/address_map-inl.h \
+ src/processor/address_map.h \
+ src/processor/basic_code_module.h \
+ src/processor/basic_code_modules.cc \
+ src/processor/basic_code_modules.h \
+ src/processor/basic_source_line_resolver_types.h \
+ src/processor/basic_source_line_resolver.cc \
+ src/processor/call_stack.cc \
+ src/processor/cfi_frame_info.cc \
+ src/processor/cfi_frame_info.h \
+ src/processor/contained_range_map-inl.h \
+ src/processor/contained_range_map.h \
+ src/processor/convert_old_arm64_context.cc \
+ src/processor/convert_old_arm64_context.h \
+ src/processor/disassembler_x86.h \
+ src/processor/disassembler_x86.cc \
+ src/processor/dump_context.cc \
+ src/processor/dump_object.cc \
+ src/processor/exploitability.cc \
+ src/processor/exploitability_linux.h \
+ src/processor/exploitability_linux.cc \
+ src/processor/exploitability_win.h \
+ src/processor/exploitability_win.cc \
+ src/processor/fast_source_line_resolver_types.h \
+ src/processor/fast_source_line_resolver.cc \
+ src/processor/linked_ptr.h \
+ src/processor/logging.h \
+ src/processor/logging.cc \
+ src/processor/map_serializers-inl.h \
+ src/processor/map_serializers.h \
+ src/processor/microdump.cc \
+ src/processor/microdump_processor.cc \
+ src/processor/minidump.cc \
+ src/processor/minidump_processor.cc \
+ src/processor/module_comparer.cc \
+ src/processor/module_comparer.h \
+ src/processor/module_factory.h \
+ src/processor/module_serializer.cc \
+ src/processor/module_serializer.h \
+ src/processor/pathname_stripper.cc \
+ src/processor/pathname_stripper.h \
+ src/processor/postfix_evaluator-inl.h \
+ src/processor/postfix_evaluator.h \
+ src/processor/process_state.cc \
+ src/processor/proc_maps_linux.cc \
+ src/processor/range_map-inl.h \
+ src/processor/range_map.h \
+ src/processor/simple_serializer-inl.h \
+ src/processor/simple_serializer.h \
+ src/processor/simple_symbol_supplier.cc \
+ src/processor/simple_symbol_supplier.h \
+ src/processor/windows_frame_info.h \
+ src/processor/source_line_resolver_base_types.h \
+ src/processor/source_line_resolver_base.cc \
+ src/processor/stack_frame_cpu.cc \
+ src/processor/stack_frame_symbolizer.cc \
+ src/processor/stackwalker.cc \
+ src/processor/stackwalker_amd64.cc \
+ src/processor/stackwalker_amd64.h \
+ src/processor/stackwalker_arm.cc \
+ src/processor/stackwalker_arm.h \
+ src/processor/stackwalker_arm64.cc \
+ src/processor/stackwalker_arm64.h \
+ src/processor/stackwalker_address_list.cc \
+ src/processor/stackwalker_address_list.h \
+ src/processor/stackwalker_mips.cc \
+ src/processor/stackwalker_mips.h \
+ src/processor/stackwalker_ppc.cc \
+ src/processor/stackwalker_ppc.h \
+ src/processor/stackwalker_ppc64.cc \
+ src/processor/stackwalker_ppc64.h \
+ src/processor/stackwalker_sparc.cc \
+ src/processor/stackwalker_sparc.h \
+ src/processor/stackwalker_x86.cc \
+ src/processor/stackwalker_x86.h \
+ src/processor/static_address_map-inl.h \
+ src/processor/static_address_map.h \
+ src/processor/static_contained_range_map-inl.h \
+ src/processor/static_contained_range_map.h \
+ src/processor/static_map_iterator-inl.h \
+ src/processor/static_map_iterator.h \
+ src/processor/static_map-inl.h \
+ src/processor/static_map.h \
+ src/processor/static_range_map-inl.h \
+ src/processor/static_range_map.h \
+ src/processor/symbolic_constants_win.cc \
+ src/processor/symbolic_constants_win.h \
+ src/processor/tokenize.cc \
+ src/processor/tokenize.h
+
+src_third_party_libdisasm_libdisasm_a_SOURCES = \
+ src/third_party/libdisasm/ia32_implicit.c \
+ src/third_party/libdisasm/ia32_implicit.h \
+ src/third_party/libdisasm/ia32_insn.c \
+ src/third_party/libdisasm/ia32_insn.h \
+ src/third_party/libdisasm/ia32_invariant.c \
+ src/third_party/libdisasm/ia32_invariant.h \
+ src/third_party/libdisasm/ia32_modrm.c \
+ src/third_party/libdisasm/ia32_modrm.h \
+ src/third_party/libdisasm/ia32_opcode_tables.c \
+ src/third_party/libdisasm/ia32_opcode_tables.h \
+ src/third_party/libdisasm/ia32_operand.c \
+ src/third_party/libdisasm/ia32_operand.h \
+ src/third_party/libdisasm/ia32_reg.c \
+ src/third_party/libdisasm/ia32_reg.h \
+ src/third_party/libdisasm/ia32_settings.c \
+ src/third_party/libdisasm/ia32_settings.h \
+ src/third_party/libdisasm/libdis.h \
+ src/third_party/libdisasm/qword.h \
+ src/third_party/libdisasm/x86_disasm.c \
+ src/third_party/libdisasm/x86_format.c \
+ src/third_party/libdisasm/x86_imm.c \
+ src/third_party/libdisasm/x86_imm.h \
+ src/third_party/libdisasm/x86_insn.c \
+ src/third_party/libdisasm/x86_misc.c \
+ src/third_party/libdisasm/x86_operand_list.c \
+ src/third_party/libdisasm/x86_operand_list.h
+
+## Programs
+bin_PROGRAMS += \
+ src/processor/microdump_stackwalk \
+ src/processor/minidump_dump \
+ src/processor/minidump_stackwalk
+endif !DISABLE_PROCESSOR
+
+if LINUX_HOST
+EXTRA_PROGRAMS += \
+ src/client/linux/linux_dumper_unittest_helper
+CLEANFILES += \
+ src/client/linux/linux_dumper_unittest_helper
+
+if !DISABLE_TOOLS
+bin_PROGRAMS += \
+ src/tools/linux/core2md/core2md \
+ src/tools/linux/dump_syms/dump_syms \
+ src/tools/linux/md2core/minidump-2-core \
+ src/tools/linux/symupload/minidump_upload \
+ src/tools/linux/symupload/sym_upload
+if X86_HOST
+bin_PROGRAMS += \
+ src/tools/mac/dump_syms/dump_syms_mac
+endif
+endif
+endif LINUX_HOST
+
+
+## Tests
+if !DISABLE_PROCESSOR
+check_PROGRAMS += \
+ src/common/test_assembler_unittest \
+ src/processor/address_map_unittest \
+ src/processor/basic_source_line_resolver_unittest \
+ src/processor/cfi_frame_info_unittest \
+ src/processor/contained_range_map_unittest \
+ src/processor/disassembler_x86_unittest \
+ src/processor/exploitability_unittest \
+ src/processor/fast_source_line_resolver_unittest \
+ src/processor/map_serializers_unittest \
+ src/processor/microdump_processor_unittest \
+ src/processor/minidump_processor_unittest \
+ src/processor/minidump_unittest \
+ src/processor/static_address_map_unittest \
+ src/processor/static_contained_range_map_unittest \
+ src/processor/static_map_unittest \
+ src/processor/static_range_map_unittest \
+ src/processor/pathname_stripper_unittest \
+ src/processor/postfix_evaluator_unittest \
+ src/processor/proc_maps_linux_unittest \
+ src/processor/range_map_truncate_lower_unittest \
+ src/processor/range_map_truncate_upper_unittest \
+ src/processor/range_map_unittest \
+ src/processor/stackwalker_amd64_unittest \
+ src/processor/stackwalker_arm_unittest \
+ src/processor/stackwalker_arm64_unittest \
+ src/processor/stackwalker_address_list_unittest \
+ src/processor/stackwalker_mips_unittest \
+ src/processor/stackwalker_mips64_unittest \
+ src/processor/stackwalker_x86_unittest \
+ src/processor/synth_minidump_unittest
+endif
+
+if LINUX_HOST
+EXTRA_PROGRAMS += \
+ src/client/linux/linux_client_unittest_shlib
+CLEANFILES += \
+ src/client/linux/linux_client_unittest_shlib
+
+check_PROGRAMS += \
+ src/client/linux/linux_client_unittest \
+ src/common/linux/google_crashdump_uploader_test
+
+if !DISABLE_TOOLS
+check_PROGRAMS += \
+ src/common/dumper_unittest \
+ src/tools/linux/md2core/minidump_2_core_unittest
+if X86_HOST
+check_PROGRAMS += \
+ src/common/mac/macho_reader_unittest
+endif
+endif
+endif LINUX_HOST
+
+if !DISABLE_PROCESSOR
+if SELFTEST
+check_PROGRAMS += \
+ src/processor/stackwalker_selftest
+endif SELFTEST
+endif !DISABLE_PROCESSOR
+
+if !DISABLE_PROCESSOR
+check_SCRIPTS = \
+ src/processor/microdump_stackwalk_test \
+ src/processor/microdump_stackwalk_machine_readable_test \
+ src/processor/minidump_dump_test \
+ src/processor/minidump_stackwalk_test \
+ src/processor/minidump_stackwalk_machine_readable_test
+endif
+
+TESTS = $(check_PROGRAMS) $(check_SCRIPTS)
+
+if ANDROID_HOST
+# Since Autotools 1.2, tests are run through a special "test driver" script.
+# Unfortunately, it's not possible anymore to specify an alternative shell to
+# run them on connected devices, so use a slightly modified version of the
+# driver for Android.
+LOG_DRIVER = $(top_srcdir)/android/test-driver
+else
+# The default Autotools test driver script.
+if TESTS_AS_ROOT
+LOG_DRIVER = $(top_srcdir)/autotools/root-test-driver $(top_srcdir)/autotools/test-driver
+else
+LOG_DRIVER = $(top_srcdir)/autotools/test-driver
+endif !TESTS_AS_ROOT
+endif !ANDROID_HOST
+
+if LINUX_HOST
+src_client_linux_linux_dumper_unittest_helper_SOURCES = \
+ src/client/linux/minidump_writer/linux_dumper_unittest_helper.cc
+src_client_linux_linux_dumper_unittest_helper_LDFLAGS=$(PTHREAD_CFLAGS)
+src_client_linux_linux_dumper_unittest_helper_CC=$(PTHREAD_CC)
+if ANDROID_HOST
+# On Android PTHREAD_CFLAGS is empty, and adding src/common/android/include
+# to the include path is necessary to build this program.
+src_client_linux_linux_dumper_unittest_helper_CXXFLAGS=$(AM_CXXFLAGS)
+else
+src_client_linux_linux_dumper_unittest_helper_CXXFLAGS=$(PTHREAD_CFLAGS)
+endif
+
+src_client_linux_linux_client_unittest_shlib_SOURCES = \
+ $(src_testing_libtesting_a_SOURCES) \
+ src/client/linux/handler/exception_handler_unittest.cc \
+ src/client/linux/microdump_writer/microdump_writer_unittest.cc \
+ src/client/linux/minidump_writer/directory_reader_unittest.cc \
+ src/client/linux/minidump_writer/cpu_set_unittest.cc \
+ src/client/linux/minidump_writer/line_reader_unittest.cc \
+ src/client/linux/minidump_writer/linux_core_dumper.cc \
+ src/client/linux/minidump_writer/linux_core_dumper_unittest.cc \
+ src/client/linux/minidump_writer/linux_ptrace_dumper_unittest.cc \
+ src/client/linux/minidump_writer/minidump_writer_unittest.cc \
+ src/client/linux/minidump_writer/minidump_writer_unittest_utils.cc \
+ src/client/linux/minidump_writer/proc_cpuinfo_reader_unittest.cc \
+ src/common/linux/elf_core_dump.cc \
+ src/common/linux/linux_libc_support_unittest.cc \
+ src/common/linux/tests/auto_testfile.h \
+ src/common/linux/tests/crash_generator.cc \
+ src/common/memory_allocator_unittest.cc \
+ src/common/tests/auto_tempdir.h \
+ src/common/tests/file_utils.cc \
+ src/common/tests/file_utils.h \
+ src/processor/basic_code_modules.cc \
+ src/processor/convert_old_arm64_context.cc \
+ src/processor/dump_context.cc \
+ src/processor/dump_object.cc \
+ src/processor/logging.cc \
+ src/processor/minidump.cc \
+ src/processor/pathname_stripper.cc \
+ src/processor/proc_maps_linux.cc
+if !HAVE_GETCONTEXT
+src_client_linux_linux_client_unittest_shlib_SOURCES += \
+ src/common/linux/breakpad_getcontext.S
+endif
+
+src_client_linux_linux_client_unittest_shlib_CPPFLAGS = \
+ $(AM_CPPFLAGS) $(TEST_CFLAGS)
+src_client_linux_linux_client_unittest_shlib_LDFLAGS = \
+ -shared \
+ -Wl,-h,linux_client_unittest_shlib
+src_client_linux_linux_client_unittest_shlib_LDADD = \
+ src/client/linux/crash_generation/crash_generation_client.o \
+ src/client/linux/dump_writer_common/thread_info.o \
+ src/client/linux/dump_writer_common/ucontext_reader.o \
+ src/client/linux/handler/exception_handler.o \
+ src/client/linux/handler/minidump_descriptor.o \
+ src/client/linux/log/log.o \
+ src/client/linux/microdump_writer/microdump_writer.o \
+ src/client/linux/minidump_writer/linux_dumper.o \
+ src/client/linux/minidump_writer/linux_ptrace_dumper.o \
+ src/client/linux/minidump_writer/minidump_writer.o \
+ src/client/minidump_file_writer.o \
+ src/common/convert_UTF.o \
+ src/common/md5.o \
+ src/common/linux/elfutils.o \
+ src/common/linux/file_id.o \
+ src/common/linux/guid_creator.o \
+ src/common/linux/linux_libc_support.o \
+ src/common/linux/memory_mapped_file.o \
+ src/common/linux/safe_readlink.o \
+ src/common/string_conversion.o \
+ $(TEST_LIBS) \
+ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
+if !HAVE_GETCONTEXT
+src_client_linux_linux_client_unittest_shlib_SOURCES += \
+ src/common/linux/breakpad_getcontext_unittest.cc
+endif
+if ANDROID_HOST
+src_client_linux_linux_client_unittest_shlib_LDFLAGS += \
+ -llog -lm
+endif
+
+src_client_linux_linux_client_unittest_shlib_DEPENDENCIES = \
+ src/client/linux/linux_dumper_unittest_helper \
+ src/client/linux/libbreakpad_client.a \
+ $(TEST_DEPS) \
+ src/libbreakpad.a
+
+src_client_linux_linux_client_unittest_SOURCES =
+# The extra-long build id is for a test in minidump_writer_unittest.cc.
+src_client_linux_linux_client_unittest_LDFLAGS = \
+ -Wl,-rpath,'$$ORIGIN' \
+ -Wl,--build-id=0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+if ANDROID_HOST
+src_client_linux_linux_client_unittest_LDFLAGS += \
+ -llog
+endif
+
+src_client_linux_linux_client_unittest_LDADD = \
+ src/client/linux/linux_client_unittest_shlib \
+ $(TEST_LIBS)
+
+src_client_linux_linux_client_unittest_DEPENDENCIES = \
+ src/client/linux/linux_client_unittest_shlib
+
+if !DISABLE_TOOLS
+src_tools_linux_core2md_core2md_SOURCES = \
+ src/tools/linux/core2md/core2md.cc
+
+src_tools_linux_core2md_core2md_LDADD = \
+ src/client/linux/libbreakpad_client.a
+
+src_tools_linux_dump_syms_dump_syms_SOURCES = \
+ src/common/dwarf_cfi_to_module.cc \
+ src/common/dwarf_cu_to_module.cc \
+ src/common/dwarf_line_to_module.cc \
+ src/common/dwarf_range_list_handler.cc \
+ src/common/language.cc \
+ src/common/module.cc \
+ src/common/path_helper.cc \
+ src/common/stabs_reader.cc \
+ src/common/stabs_to_module.cc \
+ src/common/dwarf/bytereader.cc \
+ src/common/dwarf/dwarf2diehandler.cc \
+ src/common/dwarf/dwarf2reader.cc \
+ src/common/dwarf/elf_reader.cc \
+ src/common/linux/crc32.cc \
+ src/common/linux/dump_symbols.cc \
+ src/common/linux/dump_symbols.h \
+ src/common/linux/elf_symbols_to_module.cc \
+ src/common/linux/elf_symbols_to_module.h \
+ src/common/linux/elfutils.cc \
+ src/common/linux/file_id.cc \
+ src/common/linux/linux_libc_support.cc \
+ src/common/linux/memory_mapped_file.cc \
+ src/common/linux/safe_readlink.cc \
+ src/tools/linux/dump_syms/dump_syms.cc
+src_tools_linux_dump_syms_dump_syms_CXXFLAGS = \
+ $(RUST_DEMANGLE_CFLAGS)
+src_tools_linux_dump_syms_dump_syms_LDADD = \
+ $(RUST_DEMANGLE_LIBS)
+
+src_tools_linux_md2core_minidump_2_core_SOURCES = \
+ src/common/linux/memory_mapped_file.cc \
+ src/common/path_helper.cc \
+ src/tools/linux/md2core/minidump-2-core.cc \
+ src/tools/linux/md2core/minidump_memory_range.h
+
+src_tools_linux_symupload_minidump_upload_SOURCES = \
+ src/common/linux/http_upload.cc \
+ src/tools/linux/symupload/minidump_upload.cc
+src_tools_linux_symupload_minidump_upload_LDADD = -ldl
+
+src_tools_linux_symupload_sym_upload_SOURCES = \
+ src/common/linux/http_upload.cc \
+ src/common/linux/http_upload.h \
+ src/common/linux/libcurl_wrapper.cc \
+ src/common/linux/libcurl_wrapper.h \
+ src/common/linux/symbol_collector_client.cc \
+ src/common/linux/symbol_collector_client.h \
+ src/common/linux/symbol_upload.cc \
+ src/common/linux/symbol_upload.h \
+ src/tools/linux/symupload/sym_upload.cc
+src_tools_linux_symupload_sym_upload_LDADD = -ldl
+
+src_tools_mac_dump_syms_dump_syms_mac_SOURCES = \
+ src/common/dwarf_cfi_to_module.cc \
+ src/common/dwarf_cu_to_module.cc \
+ src/common/dwarf_line_to_module.cc \
+ src/common/dwarf_range_list_handler.cc \
+ src/common/language.cc \
+ src/common/md5.cc \
+ src/common/module.cc \
+ src/common/path_helper.cc \
+ src/common/stabs_reader.cc \
+ src/common/stabs_to_module.cc \
+ src/common/dwarf/bytereader.cc \
+ src/common/dwarf/dwarf2diehandler.cc \
+ src/common/dwarf/dwarf2reader.cc \
+ src/common/dwarf/elf_reader.cc \
+ src/common/mac/arch_utilities.cc \
+ src/common/mac/dump_syms.cc \
+ src/common/mac/dump_syms.h \
+ src/common/mac/file_id.cc \
+ src/common/mac/file_id.h \
+ src/common/mac/macho_id.cc \
+ src/common/mac/macho_id.h \
+ src/common/mac/macho_reader.cc \
+ src/common/mac/macho_reader.h \
+ src/common/mac/macho_utilities.cc \
+ src/common/mac/macho_utilities.h \
+ src/common/mac/macho_walker.cc \
+ src/common/mac/macho_walker.h \
+ src/tools/mac/dump_syms/dump_syms_tool.cc
+src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS= \
+ -I$(top_srcdir)/src/third_party/mac_headers \
+ $(RUST_DEMANGLE_CFLAGS) \
+ -DHAVE_MACH_O_NLIST_H
+src_tools_mac_dump_syms_dump_syms_mac_LDADD= \
+ $(RUST_DEMANGLE_LIBS)
+
+src_common_dumper_unittest_SOURCES = \
+ src/common/byte_cursor_unittest.cc \
+ src/common/convert_UTF.cc \
+ src/common/dwarf_cfi_to_module.cc \
+ src/common/dwarf_cfi_to_module_unittest.cc \
+ src/common/dwarf_cu_to_module.cc \
+ src/common/dwarf_cu_to_module_unittest.cc \
+ src/common/dwarf_line_to_module.cc \
+ src/common/dwarf_line_to_module_unittest.cc \
+ src/common/dwarf_range_list_handler.cc \
+ src/common/language.cc \
+ src/common/memory_range_unittest.cc \
+ src/common/module.cc \
+ src/common/module_unittest.cc \
+ src/common/path_helper.cc \
+ src/common/stabs_reader.cc \
+ src/common/stabs_reader_unittest.cc \
+ src/common/stabs_to_module.cc \
+ src/common/stabs_to_module_unittest.cc \
+ src/common/string_conversion.cc \
+ src/common/string_conversion_unittest.cc \
+ src/common/test_assembler.cc \
+ src/common/dwarf/bytereader.cc \
+ src/common/dwarf/bytereader.h \
+ src/common/dwarf/bytereader-inl.h \
+ src/common/dwarf/bytereader_unittest.cc \
+ src/common/dwarf/cfi_assembler.cc \
+ src/common/dwarf/cfi_assembler.h \
+ src/common/dwarf/dwarf2diehandler.cc \
+ src/common/dwarf/dwarf2diehandler_unittest.cc \
+ src/common/dwarf/dwarf2reader.cc \
+ src/common/dwarf/dwarf2reader.h \
+ src/common/dwarf/elf_reader.cc \
+ src/common/dwarf/elf_reader.h \
+ src/common/dwarf/dwarf2reader_cfi_unittest.cc \
+ src/common/dwarf/dwarf2reader_die_unittest.cc \
+ src/common/dwarf/dwarf2reader_test_common.h \
+ src/common/linux/crc32.cc \
+ src/common/linux/dump_symbols.cc \
+ src/common/linux/dump_symbols_unittest.cc \
+ src/common/linux/elf_core_dump.cc \
+ src/common/linux/elf_core_dump_unittest.cc \
+ src/common/linux/elf_symbols_to_module.cc \
+ src/common/linux/elf_symbols_to_module_unittest.cc \
+ src/common/linux/elfutils.cc \
+ src/common/linux/file_id.cc \
+ src/common/linux/file_id_unittest.cc \
+ src/common/linux/linux_libc_support.cc \
+ src/common/linux/memory_mapped_file.cc \
+ src/common/linux/memory_mapped_file_unittest.cc \
+ src/common/linux/safe_readlink.cc \
+ src/common/linux/safe_readlink_unittest.cc \
+ src/common/linux/synth_elf.cc \
+ src/common/linux/synth_elf_unittest.cc \
+ src/common/linux/tests/crash_generator.cc \
+ src/common/linux/tests/crash_generator.h \
+ src/common/testdata/func-line-pairing.h \
+ src/common/tests/file_utils.cc
+src_common_dumper_unittest_CPPFLAGS = \
+ $(AM_CPPFLAGS) $(TEST_CFLAGS) \
+ $(RUST_DEMANGLE_CFLAGS) \
+ $(PTHREAD_CFLAGS)
+src_common_dumper_unittest_LDADD = \
+ $(TEST_LIBS) \
+ $(RUST_DEMANGLE_LIBS) \
+ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
+
+src_common_mac_macho_reader_unittest_SOURCES = \
+ src/common/dwarf_cfi_to_module.cc \
+ src/common/dwarf_cu_to_module.cc \
+ src/common/dwarf_line_to_module.cc \
+ src/common/language.cc \
+ src/common/md5.cc \
+ src/common/module.cc \
+ src/common/path_helper.cc \
+ src/common/stabs_reader.cc \
+ src/common/stabs_to_module.cc \
+ src/common/test_assembler.cc \
+ src/common/dwarf/bytereader.cc \
+ src/common/dwarf/cfi_assembler.cc \
+ src/common/dwarf/dwarf2diehandler.cc \
+ src/common/dwarf/dwarf2reader.cc \
+ src/common/dwarf/elf_reader.cc \
+ src/common/mac/arch_utilities.cc \
+ src/common/mac/file_id.cc \
+ src/common/mac/macho_id.cc \
+ src/common/mac/macho_reader.cc \
+ src/common/mac/macho_reader_unittest.cc \
+ src/common/mac/macho_utilities.cc \
+ src/common/mac/macho_walker.cc \
+ src/common/tests/file_utils.cc
+src_common_mac_macho_reader_unittest_CPPFLAGS = \
+ $(AM_CPPFLAGS) $(TEST_CFLAGS) \
+ -I$(top_srcdir)/src/third_party/mac_headers \
+ -DHAVE_MACH_O_NLIST_H \
+ $(PTHREAD_CFLAGS)
+src_common_mac_macho_reader_unittest_LDADD = \
+ $(TEST_LIBS) \
+ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
+endif
+
+src_common_linux_google_crashdump_uploader_test_SOURCES = \
+ src/common/linux/google_crashdump_uploader.cc \
+ src/common/linux/google_crashdump_uploader_test.cc \
+ src/common/linux/libcurl_wrapper.cc
+src_common_linux_google_crashdump_uploader_test_CPPFLAGS = \
+ $(AM_CPPFLAGS) $(TEST_CFLAGS)
+src_common_linux_google_crashdump_uploader_test_LDADD = \
+ $(TEST_LIBS) \
+ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS) \
+ -ldl
+
+src_tools_linux_md2core_minidump_2_core_unittest_SOURCES = \
+ src/tools/linux/md2core/minidump_memory_range_unittest.cc
+src_tools_linux_md2core_minidump_2_core_unittest_CPPFLAGS = \
+ $(AM_CPPFLAGS) $(TEST_CFLAGS)
+src_tools_linux_md2core_minidump_2_core_unittest_LDADD = \
+ $(TEST_LIBS) \
+ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
+
+endif LINUX_HOST
+
+if !DISABLE_PROCESSOR
+src_processor_address_map_unittest_SOURCES = \
+ src/processor/address_map_unittest.cc
+src_processor_address_map_unittest_LDADD = \
+ src/processor/logging.o \
+ src/processor/pathname_stripper.o
+
+src_processor_basic_source_line_resolver_unittest_SOURCES = \
+ src/processor/basic_source_line_resolver_unittest.cc
+src_processor_basic_source_line_resolver_unittest_CPPFLAGS = \
+ $(AM_CPPFLAGS) $(TEST_CFLAGS)
+src_processor_basic_source_line_resolver_unittest_LDADD = \
+ src/processor/basic_source_line_resolver.o \
+ src/processor/cfi_frame_info.o \
+ src/processor/pathname_stripper.o \
+ src/processor/logging.o \
+ src/processor/source_line_resolver_base.o \
+ src/processor/tokenize.o \
+ $(TEST_LIBS) \
+ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
+
+src_processor_cfi_frame_info_unittest_SOURCES = \
+ src/processor/cfi_frame_info_unittest.cc
+src_processor_cfi_frame_info_unittest_LDADD = \
+ src/processor/cfi_frame_info.o \
+ src/processor/logging.o \
+ src/processor/pathname_stripper.o \
+ $(TEST_LIBS) \
+ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
+src_processor_cfi_frame_info_unittest_CPPFLAGS = \
+ $(AM_CPPFLAGS) $(TEST_CFLAGS)
+
+src_processor_contained_range_map_unittest_SOURCES = \
+ src/processor/contained_range_map_unittest.cc
+src_processor_contained_range_map_unittest_LDADD = \
+ src/processor/logging.o \
+ src/processor/pathname_stripper.o
+
+src_processor_exploitability_unittest_SOURCES = \
+ src/processor/exploitability_unittest.cc
+src_processor_exploitability_unittest_CPPFLAGS = \
+ $(AM_CPPFLAGS) $(TEST_CFLAGS)
+src_processor_exploitability_unittest_LDADD = \
+ src/processor/convert_old_arm64_context.o \
+ src/processor/minidump_processor.o \
+ src/processor/process_state.o \
+ src/processor/disassembler_x86.o \
+ src/processor/exploitability.o \
+ src/processor/exploitability_linux.o \
+ src/processor/exploitability_win.o \
+ src/processor/basic_code_modules.o \
+ src/processor/basic_source_line_resolver.o \
+ src/processor/call_stack.o \
+ src/processor/cfi_frame_info.o \
+ src/processor/dump_context.o \
+ src/processor/dump_object.o \
+ src/processor/logging.o \
+ src/processor/minidump.o \
+ src/processor/pathname_stripper.o \
+ src/processor/proc_maps_linux.o \
+ src/processor/simple_symbol_supplier.o \
+ src/processor/source_line_resolver_base.o \
+ src/processor/stack_frame_cpu.o \
+ src/processor/stack_frame_symbolizer.o \
+ src/processor/stackwalker.o \
+ src/processor/stackwalker_address_list.o \
+ src/processor/stackwalker_amd64.o \
+ src/processor/stackwalker_arm.o \
+ src/processor/stackwalker_arm64.o \
+ src/processor/stackwalker_mips.o \
+ src/processor/stackwalker_ppc.o \
+ src/processor/stackwalker_ppc64.o \
+ src/processor/stackwalker_sparc.o \
+ src/processor/stackwalker_x86.o \
+ src/processor/symbolic_constants_win.o \
+ src/processor/tokenize.o \
+ src/third_party/libdisasm/libdisasm.a \
+ $(TEST_LIBS) \
+ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
+
+src_processor_disassembler_x86_unittest_SOURCES = \
+ src/processor/disassembler_x86_unittest.cc
+src_processor_disassembler_x86_unittest_CPPFLAGS = \
+ $(AM_CPPFLAGS) $(TEST_CFLAGS)
+src_processor_disassembler_x86_unittest_LDADD = \
+ src/processor/disassembler_x86.o \
+ src/third_party/libdisasm/libdisasm.a \
+ $(TEST_LIBS) \
+ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
+
+src_processor_fast_source_line_resolver_unittest_SOURCES = \
+ src/processor/fast_source_line_resolver_unittest.cc
+src_processor_fast_source_line_resolver_unittest_CPPFLAGS = \
+ $(AM_CPPFLAGS) $(TEST_CFLAGS)
+src_processor_fast_source_line_resolver_unittest_LDADD = \
+ src/processor/fast_source_line_resolver.o \
+ src/processor/basic_source_line_resolver.o \
+ src/processor/cfi_frame_info.o \
+ src/processor/module_comparer.o \
+ src/processor/module_serializer.o \
+ src/processor/pathname_stripper.o \
+ src/processor/logging.o \
+ src/processor/source_line_resolver_base.o \
+ src/processor/tokenize.o \
+ $(TEST_LIBS) \
+ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
+
+src_processor_map_serializers_unittest_SOURCES = \
+ src/processor/map_serializers_unittest.cc
+src_processor_map_serializers_unittest_CPPFLAGS = \
+ $(AM_CPPFLAGS) $(TEST_CFLAGS)
+src_processor_map_serializers_unittest_LDADD = \
+ src/processor/logging.o \
+ src/processor/pathname_stripper.o \
+ $(TEST_LIBS) \
+ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
+
+src_processor_microdump_processor_unittest_SOURCES = \
+ src/processor/microdump_processor_unittest.cc
+src_processor_microdump_processor_unittest_CPPFLAGS = \
+ $(AM_CPPFLAGS) $(TEST_CFLAGS)
+src_processor_microdump_processor_unittest_LDADD = \
+ src/processor/basic_code_modules.o \
+ src/processor/basic_source_line_resolver.o \
+ src/processor/call_stack.o \
+ src/processor/convert_old_arm64_context.o \
+ src/processor/cfi_frame_info.o \
+ src/processor/dump_context.o \
+ src/processor/dump_object.o \
+ src/processor/logging.o \
+ src/processor/microdump.o \
+ src/processor/microdump_processor.o \
+ src/processor/pathname_stripper.o \
+ src/processor/process_state.o \
+ src/processor/simple_symbol_supplier.o \
+ src/processor/source_line_resolver_base.o \
+ src/processor/stack_frame_symbolizer.o \
+ src/processor/stackwalker.o \
+ src/processor/stackwalker_address_list.o \
+ src/processor/stackwalker_amd64.o \
+ src/processor/stackwalker_arm.o \
+ src/processor/stackwalker_arm64.o \
+ src/processor/stackwalker_mips.o \
+ src/processor/stackwalker_ppc.o \
+ src/processor/stackwalker_ppc64.o \
+ src/processor/stackwalker_sparc.o \
+ src/processor/stackwalker_x86.o \
+ src/processor/tokenize.o \
+ $(TEST_LIBS) \
+ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
+
+src_processor_minidump_processor_unittest_SOURCES = \
+ src/processor/minidump_processor_unittest.cc
+src_processor_minidump_processor_unittest_CPPFLAGS = \
+ $(AM_CPPFLAGS) $(TEST_CFLAGS)
+src_processor_minidump_processor_unittest_LDADD = \
+ src/processor/basic_code_modules.o \
+ src/processor/basic_source_line_resolver.o \
+ src/processor/call_stack.o \
+ src/processor/cfi_frame_info.o \
+ src/processor/convert_old_arm64_context.o \
+ src/processor/disassembler_x86.o \
+ src/processor/dump_context.o \
+ src/processor/dump_object.o \
+ src/processor/exploitability.o \
+ src/processor/exploitability_linux.o \
+ src/processor/exploitability_win.o \
+ src/processor/logging.o \
+ src/processor/minidump_processor.o \
+ src/processor/minidump.o \
+ src/processor/pathname_stripper.o \
+ src/processor/process_state.o \
+ src/processor/proc_maps_linux.o \
+ src/processor/source_line_resolver_base.o \
+ src/processor/stack_frame_cpu.o \
+ src/processor/stack_frame_symbolizer.o \
+ src/processor/stackwalker.o \
+ src/processor/stackwalker_address_list.o \
+ src/processor/stackwalker_amd64.o \
+ src/processor/stackwalker_arm.o \
+ src/processor/stackwalker_arm64.o \
+ src/processor/stackwalker_mips.o \
+ src/processor/stackwalker_ppc.o \
+ src/processor/stackwalker_ppc64.o \
+ src/processor/stackwalker_sparc.o \
+ src/processor/stackwalker_x86.o \
+ src/processor/symbolic_constants_win.o \
+ src/processor/tokenize.o \
+ src/third_party/libdisasm/libdisasm.a \
+ $(TEST_LIBS) \
+ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
+
+src_processor_minidump_unittest_SOURCES = \
+ src/common/test_assembler.cc \
+ src/processor/minidump_unittest.cc \
+ src/processor/synth_minidump.cc
+src_processor_minidump_unittest_CPPFLAGS = \
+ $(AM_CPPFLAGS) $(TEST_CFLAGS)
+src_processor_minidump_unittest_LDADD = \
+ src/processor/basic_code_modules.o \
+ src/processor/convert_old_arm64_context.o \
+ src/processor/dump_context.o \
+ src/processor/dump_object.o \
+ src/processor/logging.o \
+ src/processor/minidump.o \
+ src/processor/pathname_stripper.o \
+ src/processor/proc_maps_linux.o \
+ $(TEST_LIBS) \
+ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
+
+src_processor_proc_maps_linux_unittest_SOURCES = \
+ src/processor/proc_maps_linux.cc \
+ src/processor/proc_maps_linux_unittest.cc
+src_processor_proc_maps_linux_unittest_CPPFLAGS = \
+ $(AM_CPPFLAGS) $(TEST_CFLAGS)
+src_processor_proc_maps_linux_unittest_LDADD = \
+ src/processor/logging.o \
+ src/processor/pathname_stripper.o \
+ src/third_party/libdisasm/libdisasm.a \
+ $(TEST_LIBS) \
+ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
+
+src_processor_static_address_map_unittest_SOURCES = \
+ src/processor/static_address_map_unittest.cc
+src_processor_static_address_map_unittest_CPPFLAGS = \
+ $(AM_CPPFLAGS) $(TEST_CFLAGS)
+src_processor_static_address_map_unittest_LDADD = \
+ src/processor/logging.o \
+ src/processor/pathname_stripper.o \
+ $(TEST_LIBS) \
+ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
+
+src_processor_static_contained_range_map_unittest_SOURCES = \
+ src/processor/static_contained_range_map_unittest.cc
+src_processor_static_contained_range_map_unittest_CPPFLAGS = \
+ $(AM_CPPFLAGS) $(TEST_CFLAGS)
+src_processor_static_contained_range_map_unittest_LDADD = \
+ src/processor/logging.o \
+ src/processor/pathname_stripper.o \
+ $(TEST_LIBS) \
+ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
+
+src_processor_static_map_unittest_SOURCES = \
+ src/processor/static_map_unittest.cc
+src_processor_static_map_unittest_CPPFLAGS = \
+ $(AM_CPPFLAGS) $(TEST_CFLAGS)
+src_processor_static_map_unittest_LDADD = \
+ src/processor/logging.o \
+ src/processor/pathname_stripper.o \
+ $(TEST_LIBS) \
+ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
+
+src_processor_static_range_map_unittest_SOURCES = \
+ src/processor/static_range_map_unittest.cc
+src_processor_static_range_map_unittest_CPPFLAGS = \
+ $(AM_CPPFLAGS) $(TEST_CFLAGS)
+src_processor_static_range_map_unittest_LDADD = \
+ src/processor/logging.o \
+ src/processor/pathname_stripper.o \
+ $(TEST_LIBS) \
+ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
+
+src_processor_pathname_stripper_unittest_SOURCES = \
+ src/processor/pathname_stripper_unittest.cc
+src_processor_pathname_stripper_unittest_LDADD = \
+ src/processor/pathname_stripper.o \
+ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
+
+src_processor_postfix_evaluator_unittest_SOURCES = \
+ src/processor/postfix_evaluator_unittest.cc
+src_processor_postfix_evaluator_unittest_LDADD = \
+ src/processor/logging.o \
+ src/processor/pathname_stripper.o \
+ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
+
+src_processor_range_map_truncate_lower_unittest_SOURCES = \
+ src/processor/range_map_truncate_lower_unittest.cc
+src_processor_range_map_truncate_lower_unittest_LDADD = \
+ src/processor/logging.o \
+ src/processor/pathname_stripper.o \
+ $(TEST_LIBS) \
+ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
+src_processor_range_map_truncate_lower_unittest_CPPFLAGS = \
+ $(AM_CPPFLAGS) $(TEST_CFLAGS)
+
+src_processor_range_map_truncate_upper_unittest_SOURCES = \
+ src/processor/range_map_truncate_upper_unittest.cc
+src_processor_range_map_truncate_upper_unittest_LDADD = \
+ src/processor/logging.o \
+ src/processor/pathname_stripper.o \
+ $(TEST_LIBS) \
+ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
+src_processor_range_map_truncate_upper_unittest_CPPFLAGS = \
+ $(AM_CPPFLAGS) $(TEST_CFLAGS)
+
+src_processor_range_map_unittest_SOURCES = \
+ src/processor/range_map_unittest.cc
+src_processor_range_map_unittest_LDADD = \
+ src/processor/logging.o \
+ src/processor/pathname_stripper.o \
+ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
+
+src_processor_stackwalker_selftest_SOURCES = \
+ src/processor/stackwalker_selftest.cc
+src_processor_stackwalker_selftest_LDADD = \
+ src/processor/basic_code_modules.o \
+ src/processor/basic_source_line_resolver.o \
+ src/processor/call_stack.o \
+ src/processor/disassembler_x86.o \
+ src/processor/exploitability.o \
+ src/processor/exploitability_linux.o \
+ src/processor/exploitability_win.o \
+ src/processor/logging.o \
+ src/processor/minidump.o \
+ src/processor/pathname_stripper.o \
+ src/processor/proc_maps_linux.o \
+ src/processor/source_line_resolver_base.o \
+ src/processor/stack_frame_cpu.o \
+ src/processor/stack_frame_symbolizer.o \
+ src/processor/stackwalker.o \
+ src/processor/stackwalker_address_list.o \
+ src/processor/stackwalker_amd64.o \
+ src/processor/stackwalker_arm.o \
+ src/processor/stackwalker_arm64.o \
+ src/processor/stackwalker_mips.o \
+ src/processor/stackwalker_ppc.o \
+ src/processor/stackwalker_ppc64.o \
+ src/processor/stackwalker_sparc.o \
+ src/processor/stackwalker_x86.o \
+ src/processor/tokenize.o \
+ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
+
+src_processor_stackwalker_amd64_unittest_SOURCES = \
+ src/common/test_assembler.cc \
+ src/processor/stackwalker_amd64_unittest.cc
+src_processor_stackwalker_amd64_unittest_LDADD = \
+ src/libbreakpad.a \
+ $(TEST_LIBS) \
+ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
+src_processor_stackwalker_amd64_unittest_CPPFLAGS = \
+ $(AM_CPPFLAGS) $(TEST_CFLAGS)
+
+src_processor_stackwalker_arm_unittest_SOURCES = \
+ src/common/test_assembler.cc \
+ src/processor/stackwalker_arm_unittest.cc
+src_processor_stackwalker_arm_unittest_LDADD = \
+ src/libbreakpad.a \
+ $(TEST_LIBS) \
+ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
+src_processor_stackwalker_arm_unittest_CPPFLAGS = \
+ $(AM_CPPFLAGS) $(TEST_CFLAGS)
+
+src_processor_stackwalker_arm64_unittest_SOURCES = \
+ src/common/test_assembler.cc \
+ src/processor/stackwalker_arm64_unittest.cc
+src_processor_stackwalker_arm64_unittest_LDADD = \
+ src/libbreakpad.a \
+ $(TEST_LIBS) \
+ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
+src_processor_stackwalker_arm64_unittest_CPPFLAGS = \
+ $(AM_CPPFLAGS) $(TEST_CFLAGS)
+
+src_processor_stackwalker_address_list_unittest_SOURCES = \
+ src/common/test_assembler.cc \
+ src/processor/stackwalker_address_list_unittest.cc
+src_processor_stackwalker_address_list_unittest_LDADD = \
+ src/libbreakpad.a \
+ $(TEST_LIBS) \
+ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
+src_processor_stackwalker_address_list_unittest_CPPFLAGS = \
+ $(AM_CPPFLAGS) $(TEST_CFLAGS)
+
+src_processor_stackwalker_mips_unittest_SOURCES = \
+ src/common/test_assembler.cc \
+ src/processor/stackwalker_mips_unittest.cc
+src_processor_stackwalker_mips_unittest_LDADD = \
+ src/libbreakpad.a \
+ $(TEST_LIBS) \
+ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
+src_processor_stackwalker_mips_unittest_CPPFLAGS = \
+ $(AM_CPPFLAGS) $(TEST_CFLAGS)
+
+src_processor_stackwalker_mips64_unittest_SOURCES = \
+ src/common/test_assembler.cc \
+ src/processor/stackwalker_mips64_unittest.cc
+src_processor_stackwalker_mips64_unittest_LDADD = \
+ src/libbreakpad.a \
+ $(TEST_LIBS) \
+ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
+src_processor_stackwalker_mips64_unittest_CPPFLAGS = \
+ $(AM_CPPFLAGS) $(TEST_CFLAGS)
+
+src_processor_stackwalker_x86_unittest_SOURCES = \
+ src/common/test_assembler.cc \
+ src/processor/stackwalker_x86_unittest.cc
+src_processor_stackwalker_x86_unittest_LDADD = \
+ src/libbreakpad.a \
+ $(TEST_LIBS) \
+ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
+src_processor_stackwalker_x86_unittest_CPPFLAGS = \
+ $(AM_CPPFLAGS) $(TEST_CFLAGS)
+
+src_processor_synth_minidump_unittest_SOURCES = \
+ src/common/test_assembler.cc \
+ src/common/test_assembler.h \
+ src/processor/synth_minidump_unittest.cc \
+ src/processor/synth_minidump.cc \
+ src/processor/synth_minidump.h
+src_processor_synth_minidump_unittest_CPPFLAGS = \
+ $(AM_CPPFLAGS) $(TEST_CFLAGS)
+src_processor_synth_minidump_unittest_LDADD = \
+ $(TEST_LIBS) \
+ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
+
+src_common_test_assembler_unittest_SOURCES = \
+ src/common/test_assembler.cc \
+ src/common/test_assembler.h \
+ src/common/test_assembler_unittest.cc
+src_common_test_assembler_unittest_CPPFLAGS = \
+ $(AM_CPPFLAGS) $(TEST_CFLAGS)
+src_common_test_assembler_unittest_LDADD = \
+ $(TEST_LIBS) \
+ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
+
+## Non-installables
+noinst_PROGRAMS =
+noinst_SCRIPTS = $(check_SCRIPTS)
+
+src_processor_minidump_dump_SOURCES = \
+ src/processor/minidump_dump.cc
+src_processor_minidump_dump_LDADD = \
+ src/processor/basic_code_modules.o \
+ src/processor/convert_old_arm64_context.o \
+ src/processor/dump_context.o \
+ src/processor/dump_object.o \
+ src/processor/logging.o \
+ src/processor/minidump.o \
+ src/processor/pathname_stripper.o \
+ src/processor/proc_maps_linux.o
+
+src_processor_microdump_stackwalk_SOURCES = \
+ src/processor/microdump_stackwalk.cc
+src_processor_microdump_stackwalk_LDADD = \
+ src/common/path_helper.o \
+ src/processor/basic_code_modules.o \
+ src/processor/basic_source_line_resolver.o \
+ src/processor/call_stack.o \
+ src/processor/convert_old_arm64_context.o \
+ src/processor/cfi_frame_info.o \
+ src/processor/disassembler_x86.o \
+ src/processor/dump_context.o \
+ src/processor/dump_object.o \
+ src/processor/logging.o \
+ src/processor/microdump.o \
+ src/processor/microdump_processor.o \
+ src/processor/pathname_stripper.o \
+ src/processor/process_state.o \
+ src/processor/simple_symbol_supplier.o \
+ src/processor/source_line_resolver_base.o \
+ src/processor/stack_frame_cpu.o \
+ src/processor/stack_frame_symbolizer.o \
+ src/processor/stackwalk_common.o \
+ src/processor/stackwalker.o \
+ src/processor/stackwalker_address_list.o \
+ src/processor/stackwalker_amd64.o \
+ src/processor/stackwalker_arm.o \
+ src/processor/stackwalker_arm64.o \
+ src/processor/stackwalker_mips.o \
+ src/processor/stackwalker_ppc.o \
+ src/processor/stackwalker_ppc64.o \
+ src/processor/stackwalker_sparc.o \
+ src/processor/stackwalker_x86.o \
+ src/processor/tokenize.o \
+ src/third_party/libdisasm/libdisasm.a
+
+src_processor_minidump_stackwalk_SOURCES = \
+ src/processor/minidump_stackwalk.cc
+src_processor_minidump_stackwalk_LDADD = \
+ src/common/path_helper.o \
+ src/processor/basic_code_modules.o \
+ src/processor/basic_source_line_resolver.o \
+ src/processor/call_stack.o \
+ src/processor/cfi_frame_info.o \
+ src/processor/convert_old_arm64_context.o \
+ src/processor/disassembler_x86.o \
+ src/processor/dump_context.o \
+ src/processor/dump_object.o \
+ src/processor/exploitability.o \
+ src/processor/exploitability_linux.o \
+ src/processor/exploitability_win.o \
+ src/processor/logging.o \
+ src/processor/minidump.o \
+ src/processor/minidump_processor.o \
+ src/processor/pathname_stripper.o \
+ src/processor/process_state.o \
+ src/processor/proc_maps_linux.o \
+ src/processor/simple_symbol_supplier.o \
+ src/processor/source_line_resolver_base.o \
+ src/processor/stack_frame_cpu.o \
+ src/processor/stack_frame_symbolizer.o \
+ src/processor/stackwalk_common.o \
+ src/processor/stackwalker.o \
+ src/processor/stackwalker_address_list.o \
+ src/processor/stackwalker_amd64.o \
+ src/processor/stackwalker_arm.o \
+ src/processor/stackwalker_arm64.o \
+ src/processor/stackwalker_mips.o \
+ src/processor/stackwalker_ppc.o \
+ src/processor/stackwalker_ppc64.o \
+ src/processor/stackwalker_sparc.o \
+ src/processor/stackwalker_x86.o \
+ src/processor/symbolic_constants_win.o \
+ src/processor/tokenize.o \
+ src/third_party/libdisasm/libdisasm.a
+
+endif !DISABLE_PROCESSOR
+
+## Additional files to be included in a source distribution
+##
+## find src/client src/common src/processor/testdata src/tools \
+## -type f \! -path '*/.svn/*' -print | sort | \
+## sed -e s/'^\(.*\)$'/'\t\1 \\'/
+EXTRA_DIST = \
+ $(SCRIPTS) \
+ src/client/linux/data/linux-gate-amd.sym \
+ src/client/linux/data/linux-gate-intel.sym \
+ src/client/mac/handler/breakpad_nlist_64.cc \
+ src/client/mac/handler/breakpad_nlist_64.h \
+ src/client/mac/handler/dynamic_images.cc \
+ src/client/mac/handler/dynamic_images.h \
+ src/client/mac/handler/exception_handler.cc \
+ src/client/mac/handler/exception_handler.h \
+ src/client/mac/handler/mach_vm_compat.h \
+ src/client/mac/handler/minidump_generator.cc \
+ src/client/mac/handler/minidump_generator.h \
+ src/client/mac/handler/minidump_test.xcodeproj/project.pbxproj \
+ src/client/mac/handler/minidump_tests32-Info.plist \
+ src/client/mac/handler/minidump_tests64-Info.plist \
+ src/client/mac/handler/obj-cTestCases-Info.plist \
+ src/client/mac/handler/protected_memory_allocator.cc \
+ src/client/mac/handler/protected_memory_allocator.h \
+ src/client/mac/handler/ucontext_compat.h \
+ src/client/mac/handler/testcases/testdata/dump_syms_i386_breakpad.sym \
+ src/client/mac/tests/BreakpadFramework_Test.mm \
+ src/client/mac/tests/crash_generation_server_test.cc \
+ src/client/mac/tests/exception_handler_test.cc \
+ src/client/mac/tests/minidump_generator_test.cc \
+ src/client/mac/tests/minidump_generator_test_helper.cc \
+ src/client/mac/tests/spawn_child_process.h \
+ src/client/mac/tests/testlogging.h \
+ src/client/minidump_file_writer_unittest.cc \
+ src/client/solaris/handler/Makefile \
+ src/client/solaris/handler/exception_handler.cc \
+ src/client/solaris/handler/exception_handler.h \
+ src/client/solaris/handler/exception_handler_test.cc \
+ src/client/solaris/handler/minidump_generator.cc \
+ src/client/solaris/handler/minidump_generator.h \
+ src/client/solaris/handler/minidump_test.cc \
+ src/client/solaris/handler/solaris_lwp.cc \
+ src/client/solaris/handler/solaris_lwp.h \
+ src/client/windows/breakpad_client.gyp \
+ src/client/windows/handler/exception_handler.cc \
+ src/client/windows/handler/exception_handler.h \
+ src/client/windows/handler/exception_handler.gyp \
+ src/client/windows/sender/crash_report_sender.cc \
+ src/client/windows/sender/crash_report_sender.h \
+ src/client/windows/sender/crash_report_sender.gyp \
+ src/common/dwarf/dwarf2diehandler.h \
+ src/common/dwarf/dwarf2enums.h \
+ src/common/dwarf/line_state_machine.h \
+ src/common/dwarf/types.h \
+ src/common/mac/arch_utilities.h \
+ src/common/mac/byteswap.h \
+ src/common/mac/HTTPMultipartUpload.h \
+ src/common/mac/HTTPMultipartUpload.m \
+ src/common/mac/string_utilities.cc \
+ src/common/mac/string_utilities.h \
+ src/common/mac/super_fat_arch.h \
+ src/common/scoped_ptr.h \
+ src/common/solaris/dump_symbols.cc \
+ src/common/solaris/dump_symbols.h \
+ src/common/solaris/file_id.cc \
+ src/common/solaris/file_id.h \
+ src/common/solaris/guid_creator.cc \
+ src/common/solaris/guid_creator.h \
+ src/common/solaris/message_output.h \
+ src/common/windows/guid_string.cc \
+ src/common/windows/guid_string.h \
+ src/common/windows/http_upload.cc \
+ src/common/windows/http_upload.h \
+ src/common/windows/pdb_source_line_writer.cc \
+ src/common/windows/pdb_source_line_writer.h \
+ src/common/windows/string_utils-inl.h \
+ src/common/windows/string_utils.cc \
+ src/processor/microdump_stackwalk_test_vars \
+ src/processor/stackwalk_common.cc \
+ src/processor/stackwalk_common.h \
+ src/processor/stackwalker_selftest_sol.s \
+ src/processor/testdata/ascii_read_av_block_write.dmp \
+ src/processor/testdata/ascii_read_av_clobber_write.dmp \
+ src/processor/testdata/ascii_read_av_conditional.dmp \
+ src/processor/testdata/ascii_read_av.dmp \
+ src/processor/testdata/ascii_read_av_then_jmp.dmp \
+ src/processor/testdata/ascii_read_av_xchg_write.dmp \
+ src/processor/testdata/ascii_write_av_arg_to_call.dmp \
+ src/processor/testdata/ascii_write_av.dmp \
+ src/processor/testdata/exec_av_on_stack.dmp \
+ src/processor/testdata/linux_divide_by_zero.dmp \
+ src/processor/testdata/linux_executable_heap.dmp \
+ src/processor/testdata/linux_executable_stack.dmp \
+ src/processor/testdata/linux_inside_module_exe_region1.dmp \
+ src/processor/testdata/linux_inside_module_exe_region2.dmp \
+ src/processor/testdata/linux_jmp_to_0.dmp \
+ src/processor/testdata/linux_jmp_to_module_not_exe_region.dmp \
+ src/processor/testdata/linux_null_dereference.dmp \
+ src/processor/testdata/linux_null_read_av.dmp \
+ src/processor/testdata/linux_outside_module.dmp \
+ src/processor/testdata/linux_overflow.dmp \
+ src/processor/testdata/linux_raise_sigabrt.dmp \
+ src/processor/testdata/linux_stack_pointer_in_module.dmp \
+ src/processor/testdata/linux_stack_pointer_in_stack.dmp \
+ src/processor/testdata/linux_stack_pointer_in_stack_alt_name.dmp \
+ src/processor/testdata/linux_stacksmash.dmp \
+ src/processor/testdata/linux_write_to_nonwritable_module.dmp \
+ src/processor/testdata/linux_write_to_nonwritable_region_math.dmp \
+ src/processor/testdata/linux_write_to_outside_module.dmp \
+ src/processor/testdata/linux_write_to_outside_module_via_math.dmp \
+ src/processor/testdata/linux_write_to_under_4k.dmp \
+ src/processor/testdata/microdump-arm64.dmp \
+ src/processor/testdata/microdump-arm.dmp \
+ src/processor/testdata/microdump-mips32.dmp \
+ src/processor/testdata/microdump-mips64.dmp \
+ src/processor/testdata/microdump-multiple.dmp \
+ src/processor/testdata/microdump.stackwalk-arm64.out \
+ src/processor/testdata/microdump.stackwalk-arm.out \
+ src/processor/testdata/microdump.stackwalk.machine_readable-arm64.out \
+ src/processor/testdata/microdump.stackwalk.machine_readable-arm.out \
+ src/processor/testdata/microdump-withcrashreason.dmp \
+ src/processor/testdata/microdump-x86.dmp \
+ src/processor/testdata/minidump_32bit_crash_addr.dmp \
+ src/processor/testdata/minidump2.dmp \
+ src/processor/testdata/minidump2.dump.out \
+ src/processor/testdata/minidump2.stackwalk.machine_readable.out \
+ src/processor/testdata/minidump2.stackwalk.out \
+ src/processor/testdata/module0.out \
+ src/processor/testdata/module1.out \
+ src/processor/testdata/module2.out \
+ src/processor/testdata/module3_bad.out \
+ src/processor/testdata/module4_bad.out \
+ src/processor/testdata/null_read_av.dmp \
+ src/processor/testdata/null_write_av.dmp \
+ src/processor/testdata/read_av_clobber_write.dmp \
+ src/processor/testdata/read_av_conditional.dmp \
+ src/processor/testdata/read_av_non_null.dmp \
+ src/processor/testdata/stack_exhaustion.dmp \
+ src/processor/testdata/write_av_non_null.dmp \
+ src/processor/testdata/symbols/kernel32.pdb/BCE8785C57B44245A669896B6A19B9542/kernel32.sym \
+ src/processor/testdata/symbols/ld-2.13.so/C32AD7E235EA6112E02A5B9D6219C4850/ld-2.13.so.sym \
+ src/processor/testdata/symbols/libc-2.13.so/F4F8DFCD5A5FB5A7CE64717E9E6AE3890/libc-2.13.so.sym \
+ src/processor/testdata/symbols/libgcc_s.so.1/18B180F90887D8F8B5C35D185444AF4C0/libgcc_s.so.1.sym \
+ src/processor/testdata/symbols/microdump/breakpad_unittests/D6D1FEC9A15DE7F38A236898871A2E770/breakpad_unittests.sym \
+ src/processor/testdata/symbols/microdump/breakpad_unittests/DA7778FB66018A4E9B4110ED06E730D00/breakpad_unittests.sym \
+ src/processor/testdata/symbols/microdump/crash_example/6E72E2F1A5F59AB3D51356FDFE394D490/crash_example.sym \
+ src/processor/testdata/symbols/microdump/crash_example/8F36148CC4647A8116CAF2A25F591F570/crash_example.sym \
+ src/processor/testdata/symbols/null_read_av/7B7D1968FF0D47AE4366E9C3A7E1B6750/null_read_av.sym \
+ src/processor/testdata/symbols/overflow/B0E1FC01EF48E39CAF5C881D2DF0C3840/overflow.sym \
+ src/processor/testdata/symbols/test_app.pdb/5A9832E5287241C1838ED98914E9B7FF1/test_app.sym \
+ src/processor/testdata/test_app.cc \
+ src/testing/googletest/include/gtest/gtest.h \
+ src/testing/googletest/include/gtest/gtest-death-test.h \
+ src/testing/googletest/include/gtest/gtest-matchers.h \
+ src/testing/googletest/include/gtest/gtest-message.h \
+ src/testing/googletest/include/gtest/gtest-param-test.h \
+ src/testing/googletest/include/gtest/gtest-printers.h \
+ src/testing/googletest/include/gtest/gtest-spi.h \
+ src/testing/googletest/include/gtest/gtest-test-part.h \
+ src/testing/googletest/include/gtest/gtest-typed-test.h \
+ src/testing/googletest/include/gtest/gtest_pred_impl.h \
+ src/testing/googletest/include/gtest/gtest_prod.h \
+ src/testing/googletest/include/gtest/internal/custom/gtest-port.h \
+ src/testing/googletest/include/gtest/internal/custom/gtest-printers.h \
+ src/testing/googletest/include/gtest/internal/custom/gtest.h \
+ src/testing/googletest/include/gtest/internal/gtest-death-test-internal.h \
+ src/testing/googletest/include/gtest/internal/gtest-filepath.h \
+ src/testing/googletest/include/gtest/internal/gtest-internal.h \
+ src/testing/googletest/include/gtest/internal/gtest-param-util-generated.h \
+ src/testing/googletest/include/gtest/internal/gtest-param-util.h \
+ src/testing/googletest/include/gtest/internal/gtest-port-arch.h \
+ src/testing/googletest/include/gtest/internal/gtest-port.h \
+ src/testing/googletest/include/gtest/internal/gtest-string.h \
+ src/testing/googletest/include/gtest/internal/gtest-type-util.h \
+ src/testing/googletest/src/gtest.cc \
+ src/testing/googletest/src/gtest-death-test.cc \
+ src/testing/googletest/src/gtest-filepath.cc \
+ src/testing/googletest/src/gtest-internal-inl.h \
+ src/testing/googletest/src/gtest-matchers.cc \
+ src/testing/googletest/src/gtest-port.cc \
+ src/testing/googletest/src/gtest-printers.cc \
+ src/testing/googletest/src/gtest-test-part.cc \
+ src/testing/googletest/src/gtest-typed-test.cc \
+ src/testing/googlemock/include/gmock/gmock.h \
+ src/testing/googlemock/include/gmock/gmock-actions.h \
+ src/testing/googlemock/include/gmock/gmock-cardinalities.h \
+ src/testing/googlemock/include/gmock/gmock-function-mocker.h \
+ src/testing/googlemock/include/gmock/gmock-generated-actions.h \
+ src/testing/googlemock/include/gmock/gmock-generated-function-mockers.h \
+ src/testing/googlemock/include/gmock/gmock-generated-matchers.h \
+ src/testing/googlemock/include/gmock/gmock-matchers.h \
+ src/testing/googlemock/include/gmock/gmock-more-actions.h \
+ src/testing/googlemock/include/gmock/gmock-more-matchers.h \
+ src/testing/googlemock/include/gmock/gmock-nice-strict.h \
+ src/testing/googlemock/include/gmock/gmock-spec-builders.h \
+ src/testing/googlemock/include/gmock/internal/custom/gmock-generated-actions.h \
+ src/testing/googlemock/include/gmock/internal/custom/gmock-matchers.h \
+ src/testing/googlemock/include/gmock/internal/custom/gmock-port.h \
+ src/testing/googlemock/include/gmock/internal/gmock-internal-utils.h \
+ src/testing/googlemock/include/gmock/internal/gmock-port.h \
+ src/testing/googlemock/include/gmock/internal/gmock-pp.h \
+ src/testing/googlemock/src/gmock.cc \
+ src/testing/googlemock/src/gmock-cardinalities.cc \
+ src/testing/googlemock/src/gmock-internal-utils.cc \
+ src/testing/googlemock/src/gmock-matchers.cc \
+ src/testing/googlemock/src/gmock-spec-builders.cc \
+ src/testing/googlemock/src/gmock_main.cc \
+ src/third_party/curl/COPYING \
+ src/third_party/curl/curlbuild.h \
+ src/third_party/curl/curl.h \
+ src/third_party/curl/curlrules.h \
+ src/third_party/curl/curlver.h \
+ src/third_party/curl/easy.h \
+ src/third_party/curl/mprintf.h \
+ src/third_party/curl/multi.h \
+ src/third_party/curl/stdcheaders.h \
+ src/third_party/curl/typecheck-gcc.h \
+ src/third_party/curl/types.h \
+ src/third_party/mac_headers/architecture/byte_order.h \
+ src/third_party/mac_headers/i386/_types.h \
+ src/third_party/mac_headers/mach/boolean.h \
+ src/third_party/mac_headers/mach/i386/boolean.h \
+ src/third_party/mac_headers/mach/i386/vm_param.h \
+ src/third_party/mac_headers/mach/i386/vm_types.h \
+ src/third_party/mac_headers/mach/machine/boolean.h \
+ src/third_party/mac_headers/mach/machine.h \
+ src/third_party/mac_headers/mach/machine/thread_state.h \
+ src/third_party/mac_headers/mach/machine/thread_status.h \
+ src/third_party/mac_headers/mach/machine/vm_types.h \
+ src/third_party/mac_headers/mach-o/arch.h \
+ src/third_party/mac_headers/mach-o/fat.h \
+ src/third_party/mac_headers/mach-o/loader.h \
+ src/third_party/mac_headers/mach-o/nlist.h \
+ src/third_party/mac_headers/mach/thread_status.h \
+ src/third_party/mac_headers/mach/vm_prot.h \
+ src/third_party/mac_headers/README \
+ src/third_party/musl/README \
+ src/third_party/musl/COPYRIGHT \
+ src/third_party/musl/README.breakpad \
+ src/third_party/musl/VERSION \
+ src/third_party/musl/include/elf.h \
+ src/tools/mac/crash_report/crash_report.mm \
+ src/tools/mac/crash_report/crash_report.xcodeproj/project.pbxproj \
+ src/tools/mac/crash_report/on_demand_symbol_supplier.h \
+ src/tools/mac/crash_report/on_demand_symbol_supplier.mm \
+ src/tools/mac/dump_syms/dump_syms.xcodeproj/project.pbxproj \
+ src/tools/mac/dump_syms/dump_syms_tool.cc \
+ src/tools/mac/symupload/minidump_upload.m \
+ src/tools/mac/symupload/symupload.m \
+ src/tools/mac/symupload/symupload.xcodeproj/project.pbxproj \
+ src/tools/solaris/dump_syms/Makefile \
+ src/tools/solaris/dump_syms/dump_syms.cc \
+ src/tools/solaris/dump_syms/run_regtest.sh \
+ src/tools/solaris/dump_syms/testdata/dump_syms_regtest.cc \
+ src/tools/solaris/dump_syms/testdata/dump_syms_regtest.o \
+ src/tools/solaris/dump_syms/testdata/dump_syms_regtest.stabs \
+ src/tools/solaris/dump_syms/testdata/dump_syms_regtest.sym \
+ src/tools/windows/converter/ms_symbol_server_converter.cc \
+ src/tools/windows/converter/ms_symbol_server_converter.h \
+ src/tools/windows/converter/ms_symbol_server_converter.gyp \
+ src/tools/windows/dump_syms/dump_syms.cc \
+ src/tools/windows/dump_syms/dump_syms.gyp \
+ src/tools/windows/dump_syms/run_regtest.sh \
+ src/tools/windows/dump_syms/testdata/dump_syms_regtest.cc \
+ src/tools/windows/dump_syms/testdata/dump_syms_regtest.pdb \
+ src/tools/windows/dump_syms/testdata/dump_syms_regtest.sym \
+ src/tools/windows/dump_syms/testdata/dump_syms_regtest64.sym \
+ src/tools/windows/dump_syms/testdata/omap_reorder_bbs.sym \
+ src/tools/windows/dump_syms/testdata/omap_reorder_funcs.sym \
+ src/tools/windows/dump_syms/testdata/omap_stretched.sym \
+ src/tools/windows/dump_syms/testdata/omap_stretched_filled.sym \
+ src/tools/windows/symupload/symupload.cc \
+ src/tools/windows/symupload/symupload.gyp
+
+mostlyclean-local:
+ -find src -name '*.dwo' -exec rm -f {} +
diff --git a/toolkit/crashreporter/google-breakpad/Makefile.in b/toolkit/crashreporter/google-breakpad/Makefile.in
new file mode 100644
index 0000000000..2bdd83b043
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/Makefile.in
@@ -0,0 +1,8223 @@
+# Makefile.in generated by automake 1.15 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2014 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+# 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.
+
+
+
+
+
+VPATH = @srcdir@
+am__is_gnu_make = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+
+# This allows using fixed NDK headers when building for Android.
+# This is only necessary for building the unit tests until GTest is upgraded
+# to a future version.
+@ANDROID_HOST_TRUE@am__append_1 = \
+@ANDROID_HOST_TRUE@ -I$(top_srcdir)/src/common/android/include \
+@ANDROID_HOST_TRUE@ -I$(top_srcdir)/src/common/android/testing/include
+
+# These are good warnings to be treated as errors
+@GCC_TRUE@am__append_2 = \
+@GCC_TRUE@ -Werror=missing-braces \
+@GCC_TRUE@ -Werror=non-virtual-dtor \
+@GCC_TRUE@ -Werror=overloaded-virtual \
+@GCC_TRUE@ -Werror=reorder \
+@GCC_TRUE@ -Werror=sign-compare \
+@GCC_TRUE@ -Werror=unused-variable \
+@GCC_TRUE@ -Werror=vla
+
+
+# Build as PIC on Linux, for linux_client_unittest_shlib
+@LINUX_HOST_TRUE@am__append_3 = -fPIC
+@LINUX_HOST_TRUE@am__append_4 = -fPIC
+bin_PROGRAMS = $(am__EXEEXT_2) $(am__EXEEXT_3) $(am__EXEEXT_4)
+check_PROGRAMS = $(am__EXEEXT_5) $(am__EXEEXT_6) $(am__EXEEXT_7) \
+ $(am__EXEEXT_8) $(am__EXEEXT_9)
+EXTRA_PROGRAMS = $(am__EXEEXT_1)
+@DISABLE_PROCESSOR_FALSE@am__append_5 = src/libbreakpad.a
+@DISABLE_PROCESSOR_FALSE@am__append_6 = breakpad.pc
+@DISABLE_PROCESSOR_FALSE@am__append_7 = src/third_party/libdisasm/libdisasm.a
+@LINUX_HOST_TRUE@am__append_8 = src/client/linux/libbreakpad_client.a
+@LINUX_HOST_TRUE@am__append_9 = breakpad-client.pc
+@ANDROID_HOST_TRUE@@LINUX_HOST_TRUE@am__append_10 = \
+@ANDROID_HOST_TRUE@@LINUX_HOST_TRUE@ src/common/android/breakpad_getcontext.S
+
+@DISABLE_PROCESSOR_FALSE@am__append_11 = \
+@DISABLE_PROCESSOR_FALSE@ src/processor/microdump_stackwalk \
+@DISABLE_PROCESSOR_FALSE@ src/processor/minidump_dump \
+@DISABLE_PROCESSOR_FALSE@ src/processor/minidump_stackwalk
+
+@LINUX_HOST_TRUE@am__append_12 = src/client/linux/linux_dumper_unittest_helper \
+@LINUX_HOST_TRUE@ src/client/linux/linux_client_unittest_shlib
+@LINUX_HOST_TRUE@am__append_13 = src/client/linux/linux_dumper_unittest_helper \
+@LINUX_HOST_TRUE@ src/client/linux/linux_client_unittest_shlib
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@am__append_14 = \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/tools/linux/core2md/core2md \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/tools/linux/dump_syms/dump_syms \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/tools/linux/md2core/minidump-2-core \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/tools/linux/symupload/minidump_upload \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/tools/linux/symupload/sym_upload
+
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@@X86_HOST_TRUE@am__append_15 = \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@@X86_HOST_TRUE@ src/tools/mac/dump_syms/dump_syms_mac
+
+@DISABLE_PROCESSOR_FALSE@am__append_16 = \
+@DISABLE_PROCESSOR_FALSE@ src/common/test_assembler_unittest \
+@DISABLE_PROCESSOR_FALSE@ src/processor/address_map_unittest \
+@DISABLE_PROCESSOR_FALSE@ src/processor/basic_source_line_resolver_unittest \
+@DISABLE_PROCESSOR_FALSE@ src/processor/cfi_frame_info_unittest \
+@DISABLE_PROCESSOR_FALSE@ src/processor/contained_range_map_unittest \
+@DISABLE_PROCESSOR_FALSE@ src/processor/disassembler_x86_unittest \
+@DISABLE_PROCESSOR_FALSE@ src/processor/exploitability_unittest \
+@DISABLE_PROCESSOR_FALSE@ src/processor/fast_source_line_resolver_unittest \
+@DISABLE_PROCESSOR_FALSE@ src/processor/map_serializers_unittest \
+@DISABLE_PROCESSOR_FALSE@ src/processor/microdump_processor_unittest \
+@DISABLE_PROCESSOR_FALSE@ src/processor/minidump_processor_unittest \
+@DISABLE_PROCESSOR_FALSE@ src/processor/minidump_unittest \
+@DISABLE_PROCESSOR_FALSE@ src/processor/static_address_map_unittest \
+@DISABLE_PROCESSOR_FALSE@ src/processor/static_contained_range_map_unittest \
+@DISABLE_PROCESSOR_FALSE@ src/processor/static_map_unittest \
+@DISABLE_PROCESSOR_FALSE@ src/processor/static_range_map_unittest \
+@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper_unittest \
+@DISABLE_PROCESSOR_FALSE@ src/processor/postfix_evaluator_unittest \
+@DISABLE_PROCESSOR_FALSE@ src/processor/proc_maps_linux_unittest \
+@DISABLE_PROCESSOR_FALSE@ src/processor/range_map_shrink_down_unittest \
+@DISABLE_PROCESSOR_FALSE@ src/processor/range_map_unittest \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_amd64_unittest \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm_unittest \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm64_unittest \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_address_list_unittest \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_mips_unittest \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_mips64_unittest \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_x86_unittest \
+@DISABLE_PROCESSOR_FALSE@ src/processor/synth_minidump_unittest
+
+@LINUX_HOST_TRUE@am__append_17 = \
+@LINUX_HOST_TRUE@ src/client/linux/linux_client_unittest
+
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@am__append_18 = \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dumper_unittest \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/tools/linux/md2core/minidump_2_core_unittest
+
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@@X86_HOST_TRUE@am__append_19 = \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@@X86_HOST_TRUE@ src/common/mac/macho_reader_unittest
+
+@DISABLE_PROCESSOR_FALSE@@SELFTEST_TRUE@am__append_20 = \
+@DISABLE_PROCESSOR_FALSE@@SELFTEST_TRUE@ src/processor/stackwalker_selftest
+
+@ANDROID_HOST_TRUE@@LINUX_HOST_TRUE@am__append_21 = \
+@ANDROID_HOST_TRUE@@LINUX_HOST_TRUE@ src/common/android/breakpad_getcontext.S
+
+@ANDROID_HOST_TRUE@@LINUX_HOST_TRUE@am__append_22 = \
+@ANDROID_HOST_TRUE@@LINUX_HOST_TRUE@ src/common/android/breakpad_getcontext_unittest.cc
+
+@ANDROID_HOST_TRUE@@LINUX_HOST_TRUE@am__append_23 = \
+@ANDROID_HOST_TRUE@@LINUX_HOST_TRUE@ -llog -lm
+
+@ANDROID_HOST_TRUE@@LINUX_HOST_TRUE@am__append_24 = \
+@ANDROID_HOST_TRUE@@LINUX_HOST_TRUE@ -llog
+
+noinst_PROGRAMS =
+subdir = .
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ax_pthread.m4 \
+ $(top_srcdir)/m4/ax_cxx_compile_stdcxx.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+DIST_COMMON = $(srcdir)/Makefile.am $(top_srcdir)/configure \
+ $(am__configure_deps) $(dist_doc_DATA) $(includec_HEADERS) \
+ $(am__includecl_HEADERS_DIST) $(am__includeclc_HEADERS_DIST) \
+ $(am__includecldwc_HEADERS_DIST) \
+ $(am__includeclh_HEADERS_DIST) $(am__includeclm_HEADERS_DIST) \
+ $(includegbc_HEADERS) $(am__includelss_HEADERS_DIST) \
+ $(includep_HEADERS) $(am__DIST_COMMON)
+am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
+ configure.lineno config.status.lineno
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/src/config.h
+CONFIG_CLEAN_FILES = breakpad.pc breakpad-client.pc
+CONFIG_CLEAN_VPATH_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+ test -z "$$files" \
+ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+ $(am__cd) "$$dir" && rm -f $$files; }; \
+ }
+am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" \
+ "$(DESTDIR)$(docdir)" "$(DESTDIR)$(pkgconfigdir)" \
+ "$(DESTDIR)$(includecdir)" "$(DESTDIR)$(includecldir)" \
+ "$(DESTDIR)$(includeclcdir)" "$(DESTDIR)$(includecldwcdir)" \
+ "$(DESTDIR)$(includeclhdir)" "$(DESTDIR)$(includeclmdir)" \
+ "$(DESTDIR)$(includegbcdir)" "$(DESTDIR)$(includelssdir)" \
+ "$(DESTDIR)$(includepdir)"
+LIBRARIES = $(lib_LIBRARIES) $(noinst_LIBRARIES)
+ARFLAGS = cru
+AM_V_AR = $(am__v_AR_@AM_V@)
+am__v_AR_ = $(am__v_AR_@AM_DEFAULT_V@)
+am__v_AR_0 = @echo " AR " $@;
+am__v_AR_1 =
+src_client_linux_libbreakpad_client_a_AR = $(AR) $(ARFLAGS)
+src_client_linux_libbreakpad_client_a_LIBADD =
+am__src_client_linux_libbreakpad_client_a_SOURCES_DIST = \
+ src/client/linux/crash_generation/crash_generation_client.cc \
+ src/client/linux/crash_generation/crash_generation_server.cc \
+ src/client/linux/dump_writer_common/thread_info.cc \
+ src/client/linux/dump_writer_common/ucontext_reader.cc \
+ src/client/linux/handler/exception_handler.cc \
+ src/client/linux/handler/exception_handler.h \
+ src/client/linux/handler/minidump_descriptor.cc \
+ src/client/linux/handler/minidump_descriptor.h \
+ src/client/linux/log/log.cc src/client/linux/log/log.h \
+ src/client/linux/microdump_writer/microdump_writer.cc \
+ src/client/linux/microdump_writer/microdump_writer.h \
+ src/client/linux/minidump_writer/linux_core_dumper.cc \
+ src/client/linux/minidump_writer/linux_dumper.cc \
+ src/client/linux/minidump_writer/linux_ptrace_dumper.cc \
+ src/client/linux/minidump_writer/minidump_writer.cc \
+ src/client/minidump_file_writer-inl.h \
+ src/client/minidump_file_writer.cc \
+ src/client/minidump_file_writer.h src/common/convert_UTF.c \
+ src/common/convert_UTF.h src/common/md5.cc src/common/md5.h \
+ src/common/string_conversion.cc src/common/string_conversion.h \
+ src/common/linux/elf_core_dump.cc src/common/linux/elfutils.cc \
+ src/common/linux/elfutils.h src/common/linux/file_id.cc \
+ src/common/linux/file_id.h src/common/linux/guid_creator.cc \
+ src/common/linux/guid_creator.h \
+ src/common/linux/linux_libc_support.cc \
+ src/common/linux/memory_mapped_file.cc \
+ src/common/linux/safe_readlink.cc \
+ src/common/android/breakpad_getcontext.S
+am__dirstamp = $(am__leading_dot)dirstamp
+@ANDROID_HOST_TRUE@@LINUX_HOST_TRUE@am__objects_1 = src/common/android/breakpad_getcontext.$(OBJEXT)
+@LINUX_HOST_TRUE@am_src_client_linux_libbreakpad_client_a_OBJECTS = src/client/linux/crash_generation/crash_generation_client.$(OBJEXT) \
+@LINUX_HOST_TRUE@ src/client/linux/crash_generation/crash_generation_server.$(OBJEXT) \
+@LINUX_HOST_TRUE@ src/client/linux/dump_writer_common/thread_info.$(OBJEXT) \
+@LINUX_HOST_TRUE@ src/client/linux/dump_writer_common/ucontext_reader.$(OBJEXT) \
+@LINUX_HOST_TRUE@ src/client/linux/handler/exception_handler.$(OBJEXT) \
+@LINUX_HOST_TRUE@ src/client/linux/handler/minidump_descriptor.$(OBJEXT) \
+@LINUX_HOST_TRUE@ src/client/linux/log/log.$(OBJEXT) \
+@LINUX_HOST_TRUE@ src/client/linux/microdump_writer/microdump_writer.$(OBJEXT) \
+@LINUX_HOST_TRUE@ src/client/linux/minidump_writer/linux_core_dumper.$(OBJEXT) \
+@LINUX_HOST_TRUE@ src/client/linux/minidump_writer/linux_dumper.$(OBJEXT) \
+@LINUX_HOST_TRUE@ src/client/linux/minidump_writer/linux_ptrace_dumper.$(OBJEXT) \
+@LINUX_HOST_TRUE@ src/client/linux/minidump_writer/minidump_writer.$(OBJEXT) \
+@LINUX_HOST_TRUE@ src/client/minidump_file_writer.$(OBJEXT) \
+@LINUX_HOST_TRUE@ src/common/convert_UTF.$(OBJEXT) \
+@LINUX_HOST_TRUE@ src/common/md5.$(OBJEXT) \
+@LINUX_HOST_TRUE@ src/common/string_conversion.$(OBJEXT) \
+@LINUX_HOST_TRUE@ src/common/linux/elf_core_dump.$(OBJEXT) \
+@LINUX_HOST_TRUE@ src/common/linux/elfutils.$(OBJEXT) \
+@LINUX_HOST_TRUE@ src/common/linux/file_id.$(OBJEXT) \
+@LINUX_HOST_TRUE@ src/common/linux/guid_creator.$(OBJEXT) \
+@LINUX_HOST_TRUE@ src/common/linux/linux_libc_support.$(OBJEXT) \
+@LINUX_HOST_TRUE@ src/common/linux/memory_mapped_file.$(OBJEXT) \
+@LINUX_HOST_TRUE@ src/common/linux/safe_readlink.$(OBJEXT) \
+@LINUX_HOST_TRUE@ $(am__objects_1)
+src_client_linux_libbreakpad_client_a_OBJECTS = \
+ $(am_src_client_linux_libbreakpad_client_a_OBJECTS)
+src_libbreakpad_a_AR = $(AR) $(ARFLAGS)
+src_libbreakpad_a_LIBADD =
+am__src_libbreakpad_a_SOURCES_DIST = \
+ src/google_breakpad/common/breakpad_types.h \
+ src/google_breakpad/common/minidump_format.h \
+ src/google_breakpad/common/minidump_size.h \
+ src/google_breakpad/processor/basic_source_line_resolver.h \
+ src/google_breakpad/processor/call_stack.h \
+ src/google_breakpad/processor/code_module.h \
+ src/google_breakpad/processor/code_modules.h \
+ src/google_breakpad/processor/dump_context.h \
+ src/google_breakpad/processor/dump_object.h \
+ src/google_breakpad/processor/exploitability.h \
+ src/google_breakpad/processor/fast_source_line_resolver.h \
+ src/google_breakpad/processor/memory_region.h \
+ src/google_breakpad/processor/microdump.h \
+ src/google_breakpad/processor/microdump_processor.h \
+ src/google_breakpad/processor/minidump.h \
+ src/google_breakpad/processor/minidump_processor.h \
+ src/google_breakpad/processor/process_result.h \
+ src/google_breakpad/processor/process_state.h \
+ src/google_breakpad/processor/proc_maps_linux.h \
+ src/google_breakpad/processor/source_line_resolver_base.h \
+ src/google_breakpad/processor/source_line_resolver_interface.h \
+ src/google_breakpad/processor/stack_frame.h \
+ src/google_breakpad/processor/stack_frame_cpu.h \
+ src/google_breakpad/processor/stack_frame_symbolizer.h \
+ src/google_breakpad/processor/stackwalker.h \
+ src/google_breakpad/processor/symbol_supplier.h \
+ src/google_breakpad/processor/system_info.h \
+ src/processor/address_map-inl.h src/processor/address_map.h \
+ src/processor/basic_code_module.h \
+ src/processor/basic_code_modules.cc \
+ src/processor/basic_code_modules.h \
+ src/processor/basic_source_line_resolver_types.h \
+ src/processor/basic_source_line_resolver.cc \
+ src/processor/call_stack.cc src/processor/cfi_frame_info.cc \
+ src/processor/cfi_frame_info.h \
+ src/processor/contained_range_map-inl.h \
+ src/processor/contained_range_map.h \
+ src/processor/disassembler_x86.h \
+ src/processor/disassembler_x86.cc \
+ src/processor/dump_context.cc src/processor/dump_object.cc \
+ src/processor/exploitability.cc \
+ src/processor/exploitability_linux.h \
+ src/processor/exploitability_linux.cc \
+ src/processor/exploitability_win.h \
+ src/processor/exploitability_win.cc \
+ src/processor/fast_source_line_resolver_types.h \
+ src/processor/fast_source_line_resolver.cc \
+ src/processor/linked_ptr.h src/processor/logging.h \
+ src/processor/logging.cc src/processor/map_serializers-inl.h \
+ src/processor/map_serializers.h src/processor/microdump.cc \
+ src/processor/microdump_processor.cc src/processor/minidump.cc \
+ src/processor/minidump_processor.cc \
+ src/processor/module_comparer.cc \
+ src/processor/module_comparer.h src/processor/module_factory.h \
+ src/processor/module_serializer.cc \
+ src/processor/module_serializer.h \
+ src/processor/pathname_stripper.cc \
+ src/processor/pathname_stripper.h \
+ src/processor/postfix_evaluator-inl.h \
+ src/processor/postfix_evaluator.h \
+ src/processor/process_state.cc \
+ src/processor/proc_maps_linux.cc src/processor/range_map-inl.h \
+ src/processor/range_map.h \
+ src/processor/simple_serializer-inl.h \
+ src/processor/simple_serializer.h \
+ src/processor/simple_symbol_supplier.cc \
+ src/processor/simple_symbol_supplier.h \
+ src/processor/windows_frame_info.h \
+ src/processor/source_line_resolver_base_types.h \
+ src/processor/source_line_resolver_base.cc \
+ src/processor/stack_frame_cpu.cc \
+ src/processor/stack_frame_symbolizer.cc \
+ src/processor/stackwalker.cc \
+ src/processor/stackwalker_amd64.cc \
+ src/processor/stackwalker_amd64.h \
+ src/processor/stackwalker_arm.cc \
+ src/processor/stackwalker_arm.h \
+ src/processor/stackwalker_arm64.cc \
+ src/processor/stackwalker_arm64.h \
+ src/processor/stackwalker_address_list.cc \
+ src/processor/stackwalker_address_list.h \
+ src/processor/stackwalker_mips.cc \
+ src/processor/stackwalker_mips.h \
+ src/processor/stackwalker_ppc.cc \
+ src/processor/stackwalker_ppc.h \
+ src/processor/stackwalker_ppc64.cc \
+ src/processor/stackwalker_ppc64.h \
+ src/processor/stackwalker_sparc.cc \
+ src/processor/stackwalker_sparc.h \
+ src/processor/stackwalker_x86.cc \
+ src/processor/stackwalker_x86.h \
+ src/processor/static_address_map-inl.h \
+ src/processor/static_address_map.h \
+ src/processor/static_contained_range_map-inl.h \
+ src/processor/static_contained_range_map.h \
+ src/processor/static_map_iterator-inl.h \
+ src/processor/static_map_iterator.h \
+ src/processor/static_map-inl.h src/processor/static_map.h \
+ src/processor/static_range_map-inl.h \
+ src/processor/static_range_map.h \
+ src/processor/symbolic_constants_win.cc \
+ src/processor/symbolic_constants_win.h \
+ src/processor/tokenize.cc src/processor/tokenize.h
+@DISABLE_PROCESSOR_FALSE@am_src_libbreakpad_a_OBJECTS = src/processor/basic_code_modules.$(OBJEXT) \
+@DISABLE_PROCESSOR_FALSE@ src/processor/basic_source_line_resolver.$(OBJEXT) \
+@DISABLE_PROCESSOR_FALSE@ src/processor/call_stack.$(OBJEXT) \
+@DISABLE_PROCESSOR_FALSE@ src/processor/cfi_frame_info.$(OBJEXT) \
+@DISABLE_PROCESSOR_FALSE@ src/processor/disassembler_x86.$(OBJEXT) \
+@DISABLE_PROCESSOR_FALSE@ src/processor/dump_context.$(OBJEXT) \
+@DISABLE_PROCESSOR_FALSE@ src/processor/dump_object.$(OBJEXT) \
+@DISABLE_PROCESSOR_FALSE@ src/processor/exploitability.$(OBJEXT) \
+@DISABLE_PROCESSOR_FALSE@ src/processor/exploitability_linux.$(OBJEXT) \
+@DISABLE_PROCESSOR_FALSE@ src/processor/exploitability_win.$(OBJEXT) \
+@DISABLE_PROCESSOR_FALSE@ src/processor/fast_source_line_resolver.$(OBJEXT) \
+@DISABLE_PROCESSOR_FALSE@ src/processor/logging.$(OBJEXT) \
+@DISABLE_PROCESSOR_FALSE@ src/processor/microdump.$(OBJEXT) \
+@DISABLE_PROCESSOR_FALSE@ src/processor/microdump_processor.$(OBJEXT) \
+@DISABLE_PROCESSOR_FALSE@ src/processor/minidump.$(OBJEXT) \
+@DISABLE_PROCESSOR_FALSE@ src/processor/minidump_processor.$(OBJEXT) \
+@DISABLE_PROCESSOR_FALSE@ src/processor/module_comparer.$(OBJEXT) \
+@DISABLE_PROCESSOR_FALSE@ src/processor/module_serializer.$(OBJEXT) \
+@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.$(OBJEXT) \
+@DISABLE_PROCESSOR_FALSE@ src/processor/process_state.$(OBJEXT) \
+@DISABLE_PROCESSOR_FALSE@ src/processor/proc_maps_linux.$(OBJEXT) \
+@DISABLE_PROCESSOR_FALSE@ src/processor/simple_symbol_supplier.$(OBJEXT) \
+@DISABLE_PROCESSOR_FALSE@ src/processor/source_line_resolver_base.$(OBJEXT) \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stack_frame_cpu.$(OBJEXT) \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stack_frame_symbolizer.$(OBJEXT) \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker.$(OBJEXT) \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_amd64.$(OBJEXT) \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm.$(OBJEXT) \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm64.$(OBJEXT) \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_address_list.$(OBJEXT) \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_mips.$(OBJEXT) \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_ppc.$(OBJEXT) \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_ppc64.$(OBJEXT) \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_sparc.$(OBJEXT) \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_x86.$(OBJEXT) \
+@DISABLE_PROCESSOR_FALSE@ src/processor/symbolic_constants_win.$(OBJEXT) \
+@DISABLE_PROCESSOR_FALSE@ src/processor/tokenize.$(OBJEXT)
+src_libbreakpad_a_OBJECTS = $(am_src_libbreakpad_a_OBJECTS)
+src_testing_libtesting_a_AR = $(AR) $(ARFLAGS)
+src_testing_libtesting_a_LIBADD =
+am__src_testing_libtesting_a_SOURCES_DIST = \
+ src/breakpad_googletest_includes.h \
+ src/testing/gtest/src/gtest-all.cc \
+ src/testing/gtest/src/gtest_main.cc \
+ src/testing/src/gmock-all.cc
+@SYSTEM_TEST_LIBS_FALSE@am_src_testing_libtesting_a_OBJECTS = src/testing/gtest/src/src_testing_libtesting_a-gtest-all.$(OBJEXT) \
+@SYSTEM_TEST_LIBS_FALSE@ src/testing/gtest/src/src_testing_libtesting_a-gtest_main.$(OBJEXT) \
+@SYSTEM_TEST_LIBS_FALSE@ src/testing/src/src_testing_libtesting_a-gmock-all.$(OBJEXT)
+src_testing_libtesting_a_OBJECTS = \
+ $(am_src_testing_libtesting_a_OBJECTS)
+src_third_party_libdisasm_libdisasm_a_AR = $(AR) $(ARFLAGS)
+src_third_party_libdisasm_libdisasm_a_LIBADD =
+am__src_third_party_libdisasm_libdisasm_a_SOURCES_DIST = \
+ src/third_party/libdisasm/ia32_implicit.c \
+ src/third_party/libdisasm/ia32_implicit.h \
+ src/third_party/libdisasm/ia32_insn.c \
+ src/third_party/libdisasm/ia32_insn.h \
+ src/third_party/libdisasm/ia32_invariant.c \
+ src/third_party/libdisasm/ia32_invariant.h \
+ src/third_party/libdisasm/ia32_modrm.c \
+ src/third_party/libdisasm/ia32_modrm.h \
+ src/third_party/libdisasm/ia32_opcode_tables.c \
+ src/third_party/libdisasm/ia32_opcode_tables.h \
+ src/third_party/libdisasm/ia32_operand.c \
+ src/third_party/libdisasm/ia32_operand.h \
+ src/third_party/libdisasm/ia32_reg.c \
+ src/third_party/libdisasm/ia32_reg.h \
+ src/third_party/libdisasm/ia32_settings.c \
+ src/third_party/libdisasm/ia32_settings.h \
+ src/third_party/libdisasm/libdis.h \
+ src/third_party/libdisasm/qword.h \
+ src/third_party/libdisasm/x86_disasm.c \
+ src/third_party/libdisasm/x86_format.c \
+ src/third_party/libdisasm/x86_imm.c \
+ src/third_party/libdisasm/x86_imm.h \
+ src/third_party/libdisasm/x86_insn.c \
+ src/third_party/libdisasm/x86_misc.c \
+ src/third_party/libdisasm/x86_operand_list.c \
+ src/third_party/libdisasm/x86_operand_list.h
+@DISABLE_PROCESSOR_FALSE@am_src_third_party_libdisasm_libdisasm_a_OBJECTS = src/third_party/libdisasm/ia32_implicit.$(OBJEXT) \
+@DISABLE_PROCESSOR_FALSE@ src/third_party/libdisasm/ia32_insn.$(OBJEXT) \
+@DISABLE_PROCESSOR_FALSE@ src/third_party/libdisasm/ia32_invariant.$(OBJEXT) \
+@DISABLE_PROCESSOR_FALSE@ src/third_party/libdisasm/ia32_modrm.$(OBJEXT) \
+@DISABLE_PROCESSOR_FALSE@ src/third_party/libdisasm/ia32_opcode_tables.$(OBJEXT) \
+@DISABLE_PROCESSOR_FALSE@ src/third_party/libdisasm/ia32_operand.$(OBJEXT) \
+@DISABLE_PROCESSOR_FALSE@ src/third_party/libdisasm/ia32_reg.$(OBJEXT) \
+@DISABLE_PROCESSOR_FALSE@ src/third_party/libdisasm/ia32_settings.$(OBJEXT) \
+@DISABLE_PROCESSOR_FALSE@ src/third_party/libdisasm/x86_disasm.$(OBJEXT) \
+@DISABLE_PROCESSOR_FALSE@ src/third_party/libdisasm/x86_format.$(OBJEXT) \
+@DISABLE_PROCESSOR_FALSE@ src/third_party/libdisasm/x86_imm.$(OBJEXT) \
+@DISABLE_PROCESSOR_FALSE@ src/third_party/libdisasm/x86_insn.$(OBJEXT) \
+@DISABLE_PROCESSOR_FALSE@ src/third_party/libdisasm/x86_misc.$(OBJEXT) \
+@DISABLE_PROCESSOR_FALSE@ src/third_party/libdisasm/x86_operand_list.$(OBJEXT)
+src_third_party_libdisasm_libdisasm_a_OBJECTS = \
+ $(am_src_third_party_libdisasm_libdisasm_a_OBJECTS)
+@LINUX_HOST_TRUE@am__EXEEXT_1 = src/client/linux/linux_dumper_unittest_helper$(EXEEXT) \
+@LINUX_HOST_TRUE@ src/client/linux/linux_client_unittest_shlib$(EXEEXT)
+@DISABLE_PROCESSOR_FALSE@am__EXEEXT_2 = src/processor/microdump_stackwalk$(EXEEXT) \
+@DISABLE_PROCESSOR_FALSE@ src/processor/minidump_dump$(EXEEXT) \
+@DISABLE_PROCESSOR_FALSE@ src/processor/minidump_stackwalk$(EXEEXT)
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@am__EXEEXT_3 = src/tools/linux/core2md/core2md$(EXEEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/tools/linux/dump_syms/dump_syms$(EXEEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/tools/linux/md2core/minidump-2-core$(EXEEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/tools/linux/symupload/minidump_upload$(EXEEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/tools/linux/symupload/sym_upload$(EXEEXT)
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@@X86_HOST_TRUE@am__EXEEXT_4 = src/tools/mac/dump_syms/dump_syms_mac$(EXEEXT)
+@DISABLE_PROCESSOR_FALSE@am__EXEEXT_5 = src/common/test_assembler_unittest$(EXEEXT) \
+@DISABLE_PROCESSOR_FALSE@ src/processor/address_map_unittest$(EXEEXT) \
+@DISABLE_PROCESSOR_FALSE@ src/processor/basic_source_line_resolver_unittest$(EXEEXT) \
+@DISABLE_PROCESSOR_FALSE@ src/processor/cfi_frame_info_unittest$(EXEEXT) \
+@DISABLE_PROCESSOR_FALSE@ src/processor/contained_range_map_unittest$(EXEEXT) \
+@DISABLE_PROCESSOR_FALSE@ src/processor/disassembler_x86_unittest$(EXEEXT) \
+@DISABLE_PROCESSOR_FALSE@ src/processor/exploitability_unittest$(EXEEXT) \
+@DISABLE_PROCESSOR_FALSE@ src/processor/fast_source_line_resolver_unittest$(EXEEXT) \
+@DISABLE_PROCESSOR_FALSE@ src/processor/map_serializers_unittest$(EXEEXT) \
+@DISABLE_PROCESSOR_FALSE@ src/processor/microdump_processor_unittest$(EXEEXT) \
+@DISABLE_PROCESSOR_FALSE@ src/processor/minidump_processor_unittest$(EXEEXT) \
+@DISABLE_PROCESSOR_FALSE@ src/processor/minidump_unittest$(EXEEXT) \
+@DISABLE_PROCESSOR_FALSE@ src/processor/static_address_map_unittest$(EXEEXT) \
+@DISABLE_PROCESSOR_FALSE@ src/processor/static_contained_range_map_unittest$(EXEEXT) \
+@DISABLE_PROCESSOR_FALSE@ src/processor/static_map_unittest$(EXEEXT) \
+@DISABLE_PROCESSOR_FALSE@ src/processor/static_range_map_unittest$(EXEEXT) \
+@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper_unittest$(EXEEXT) \
+@DISABLE_PROCESSOR_FALSE@ src/processor/postfix_evaluator_unittest$(EXEEXT) \
+@DISABLE_PROCESSOR_FALSE@ src/processor/proc_maps_linux_unittest$(EXEEXT) \
+@DISABLE_PROCESSOR_FALSE@ src/processor/range_map_shrink_down_unittest$(EXEEXT) \
+@DISABLE_PROCESSOR_FALSE@ src/processor/range_map_unittest$(EXEEXT) \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_amd64_unittest$(EXEEXT) \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm_unittest$(EXEEXT) \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm64_unittest$(EXEEXT) \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_address_list_unittest$(EXEEXT) \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_mips_unittest$(EXEEXT) \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_mips64_unittest$(EXEEXT) \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_x86_unittest$(EXEEXT) \
+@DISABLE_PROCESSOR_FALSE@ src/processor/synth_minidump_unittest$(EXEEXT)
+@LINUX_HOST_TRUE@am__EXEEXT_6 = src/client/linux/linux_client_unittest$(EXEEXT)
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@am__EXEEXT_7 = src/common/dumper_unittest$(EXEEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/tools/linux/md2core/minidump_2_core_unittest$(EXEEXT)
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@@X86_HOST_TRUE@am__EXEEXT_8 = src/common/mac/macho_reader_unittest$(EXEEXT)
+@DISABLE_PROCESSOR_FALSE@@SELFTEST_TRUE@am__EXEEXT_9 = src/processor/stackwalker_selftest$(EXEEXT)
+PROGRAMS = $(bin_PROGRAMS) $(noinst_PROGRAMS)
+am_src_client_linux_linux_client_unittest_OBJECTS =
+src_client_linux_linux_client_unittest_OBJECTS = \
+ $(am_src_client_linux_linux_client_unittest_OBJECTS)
+am__DEPENDENCIES_1 =
+@SYSTEM_TEST_LIBS_FALSE@am__DEPENDENCIES_2 = src/testing/libtesting.a
+@SYSTEM_TEST_LIBS_TRUE@am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1) \
+@SYSTEM_TEST_LIBS_TRUE@ $(am__DEPENDENCIES_1)
+src_client_linux_linux_client_unittest_LINK = $(CCLD) $(AM_CFLAGS) \
+ $(CFLAGS) $(src_client_linux_linux_client_unittest_LDFLAGS) \
+ $(LDFLAGS) -o $@
+am__src_client_linux_linux_client_unittest_shlib_SOURCES_DIST = \
+ src/breakpad_googletest_includes.h \
+ src/testing/gtest/src/gtest-all.cc \
+ src/testing/gtest/src/gtest_main.cc \
+ src/testing/src/gmock-all.cc \
+ src/client/linux/handler/exception_handler_unittest.cc \
+ src/client/linux/minidump_writer/directory_reader_unittest.cc \
+ src/client/linux/minidump_writer/cpu_set_unittest.cc \
+ src/client/linux/minidump_writer/line_reader_unittest.cc \
+ src/client/linux/minidump_writer/linux_core_dumper.cc \
+ src/client/linux/minidump_writer/linux_core_dumper_unittest.cc \
+ src/client/linux/minidump_writer/linux_ptrace_dumper_unittest.cc \
+ src/client/linux/minidump_writer/minidump_writer_unittest.cc \
+ src/client/linux/minidump_writer/minidump_writer_unittest_utils.cc \
+ src/client/linux/minidump_writer/proc_cpuinfo_reader_unittest.cc \
+ src/common/linux/elf_core_dump.cc \
+ src/common/linux/linux_libc_support_unittest.cc \
+ src/common/linux/tests/auto_testfile.h \
+ src/common/linux/tests/crash_generator.cc \
+ src/common/memory_allocator_unittest.cc \
+ src/common/tests/auto_tempdir.h src/common/tests/file_utils.cc \
+ src/common/tests/file_utils.h \
+ src/processor/basic_code_modules.cc \
+ src/processor/dump_context.cc src/processor/dump_object.cc \
+ src/processor/logging.cc src/processor/minidump.cc \
+ src/processor/pathname_stripper.cc \
+ src/processor/proc_maps_linux.cc \
+ src/common/android/breakpad_getcontext.S \
+ src/client/linux/microdump_writer/microdump_writer_unittest.cc \
+ src/common/android/breakpad_getcontext_unittest.cc
+@SYSTEM_TEST_LIBS_FALSE@am__objects_2 = src/testing/gtest/src/src_client_linux_linux_client_unittest_shlib-gtest-all.$(OBJEXT) \
+@SYSTEM_TEST_LIBS_FALSE@ src/testing/gtest/src/src_client_linux_linux_client_unittest_shlib-gtest_main.$(OBJEXT) \
+@SYSTEM_TEST_LIBS_FALSE@ src/testing/src/src_client_linux_linux_client_unittest_shlib-gmock-all.$(OBJEXT)
+@ANDROID_HOST_TRUE@@LINUX_HOST_TRUE@am__objects_3 = src/common/android/src_client_linux_linux_client_unittest_shlib-breakpad_getcontext.$(OBJEXT)
+@ANDROID_HOST_TRUE@@LINUX_HOST_TRUE@am__objects_4 = src/common/android/src_client_linux_linux_client_unittest_shlib-breakpad_getcontext_unittest.$(OBJEXT)
+@LINUX_HOST_TRUE@am_src_client_linux_linux_client_unittest_shlib_OBJECTS = \
+@LINUX_HOST_TRUE@ $(am__objects_2) \
+@LINUX_HOST_TRUE@ src/client/linux/handler/src_client_linux_linux_client_unittest_shlib-exception_handler_unittest.$(OBJEXT) \
+@LINUX_HOST_TRUE@ src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-directory_reader_unittest.$(OBJEXT) \
+@LINUX_HOST_TRUE@ src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-cpu_set_unittest.$(OBJEXT) \
+@LINUX_HOST_TRUE@ src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-line_reader_unittest.$(OBJEXT) \
+@LINUX_HOST_TRUE@ src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-linux_core_dumper.$(OBJEXT) \
+@LINUX_HOST_TRUE@ src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-linux_core_dumper_unittest.$(OBJEXT) \
+@LINUX_HOST_TRUE@ src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-linux_ptrace_dumper_unittest.$(OBJEXT) \
+@LINUX_HOST_TRUE@ src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-minidump_writer_unittest.$(OBJEXT) \
+@LINUX_HOST_TRUE@ src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-minidump_writer_unittest_utils.$(OBJEXT) \
+@LINUX_HOST_TRUE@ src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-proc_cpuinfo_reader_unittest.$(OBJEXT) \
+@LINUX_HOST_TRUE@ src/common/linux/src_client_linux_linux_client_unittest_shlib-elf_core_dump.$(OBJEXT) \
+@LINUX_HOST_TRUE@ src/common/linux/src_client_linux_linux_client_unittest_shlib-linux_libc_support_unittest.$(OBJEXT) \
+@LINUX_HOST_TRUE@ src/common/linux/tests/src_client_linux_linux_client_unittest_shlib-crash_generator.$(OBJEXT) \
+@LINUX_HOST_TRUE@ src/common/src_client_linux_linux_client_unittest_shlib-memory_allocator_unittest.$(OBJEXT) \
+@LINUX_HOST_TRUE@ src/common/tests/src_client_linux_linux_client_unittest_shlib-file_utils.$(OBJEXT) \
+@LINUX_HOST_TRUE@ src/processor/src_client_linux_linux_client_unittest_shlib-basic_code_modules.$(OBJEXT) \
+@LINUX_HOST_TRUE@ src/processor/src_client_linux_linux_client_unittest_shlib-dump_context.$(OBJEXT) \
+@LINUX_HOST_TRUE@ src/processor/src_client_linux_linux_client_unittest_shlib-dump_object.$(OBJEXT) \
+@LINUX_HOST_TRUE@ src/processor/src_client_linux_linux_client_unittest_shlib-logging.$(OBJEXT) \
+@LINUX_HOST_TRUE@ src/processor/src_client_linux_linux_client_unittest_shlib-minidump.$(OBJEXT) \
+@LINUX_HOST_TRUE@ src/processor/src_client_linux_linux_client_unittest_shlib-pathname_stripper.$(OBJEXT) \
+@LINUX_HOST_TRUE@ src/processor/src_client_linux_linux_client_unittest_shlib-proc_maps_linux.$(OBJEXT) \
+@LINUX_HOST_TRUE@ $(am__objects_3) \
+@LINUX_HOST_TRUE@ src/client/linux/microdump_writer/src_client_linux_linux_client_unittest_shlib-microdump_writer_unittest.$(OBJEXT) \
+@LINUX_HOST_TRUE@ $(am__objects_4)
+src_client_linux_linux_client_unittest_shlib_OBJECTS = \
+ $(am_src_client_linux_linux_client_unittest_shlib_OBJECTS)
+src_client_linux_linux_client_unittest_shlib_LINK = $(CXXLD) \
+ $(AM_CXXFLAGS) $(CXXFLAGS) \
+ $(src_client_linux_linux_client_unittest_shlib_LDFLAGS) \
+ $(LDFLAGS) -o $@
+am__src_client_linux_linux_dumper_unittest_helper_SOURCES_DIST = src/client/linux/minidump_writer/linux_dumper_unittest_helper.cc
+@LINUX_HOST_TRUE@am_src_client_linux_linux_dumper_unittest_helper_OBJECTS = src/client/linux/minidump_writer/src_client_linux_linux_dumper_unittest_helper-linux_dumper_unittest_helper.$(OBJEXT)
+src_client_linux_linux_dumper_unittest_helper_OBJECTS = \
+ $(am_src_client_linux_linux_dumper_unittest_helper_OBJECTS)
+src_client_linux_linux_dumper_unittest_helper_LDADD = $(LDADD)
+src_client_linux_linux_dumper_unittest_helper_LINK = $(CXXLD) \
+ $(src_client_linux_linux_dumper_unittest_helper_CXXFLAGS) \
+ $(CXXFLAGS) \
+ $(src_client_linux_linux_dumper_unittest_helper_LDFLAGS) \
+ $(LDFLAGS) -o $@
+am__src_common_dumper_unittest_SOURCES_DIST = \
+ src/common/byte_cursor_unittest.cc \
+ src/common/dwarf_cfi_to_module.cc \
+ src/common/dwarf_cfi_to_module_unittest.cc \
+ src/common/dwarf_cu_to_module.cc \
+ src/common/dwarf_cu_to_module_unittest.cc \
+ src/common/dwarf_line_to_module.cc \
+ src/common/dwarf_line_to_module_unittest.cc \
+ src/common/language.cc src/common/memory_range_unittest.cc \
+ src/common/module.cc src/common/module_unittest.cc \
+ src/common/stabs_reader.cc src/common/stabs_reader_unittest.cc \
+ src/common/stabs_to_module.cc \
+ src/common/stabs_to_module_unittest.cc \
+ src/common/test_assembler.cc src/common/dwarf/bytereader.cc \
+ src/common/dwarf/bytereader.h \
+ src/common/dwarf/bytereader-inl.h \
+ src/common/dwarf/bytereader_unittest.cc \
+ src/common/dwarf/cfi_assembler.cc \
+ src/common/dwarf/cfi_assembler.h \
+ src/common/dwarf/dwarf2diehandler.cc \
+ src/common/dwarf/dwarf2diehandler_unittest.cc \
+ src/common/dwarf/dwarf2reader.cc \
+ src/common/dwarf/dwarf2reader.h src/common/dwarf/elf_reader.cc \
+ src/common/dwarf/elf_reader.h \
+ src/common/dwarf/dwarf2reader_cfi_unittest.cc \
+ src/common/dwarf/dwarf2reader_die_unittest.cc \
+ src/common/dwarf/dwarf2reader_test_common.h \
+ src/common/linux/crc32.cc src/common/linux/dump_symbols.cc \
+ src/common/linux/dump_symbols_unittest.cc \
+ src/common/linux/elf_core_dump.cc \
+ src/common/linux/elf_core_dump_unittest.cc \
+ src/common/linux/elf_symbols_to_module.cc \
+ src/common/linux/elf_symbols_to_module_unittest.cc \
+ src/common/linux/elfutils.cc src/common/linux/file_id.cc \
+ src/common/linux/file_id_unittest.cc \
+ src/common/linux/linux_libc_support.cc \
+ src/common/linux/memory_mapped_file.cc \
+ src/common/linux/memory_mapped_file_unittest.cc \
+ src/common/linux/safe_readlink.cc \
+ src/common/linux/safe_readlink_unittest.cc \
+ src/common/linux/synth_elf.cc \
+ src/common/linux/synth_elf_unittest.cc \
+ src/common/linux/tests/crash_generator.cc \
+ src/common/linux/tests/crash_generator.h \
+ src/common/testdata/func-line-pairing.h \
+ src/common/tests/file_utils.cc
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@am_src_common_dumper_unittest_OBJECTS = src/common/src_common_dumper_unittest-byte_cursor_unittest.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/src_common_dumper_unittest-dwarf_cfi_to_module.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/src_common_dumper_unittest-dwarf_cfi_to_module_unittest.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/src_common_dumper_unittest-dwarf_cu_to_module.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/src_common_dumper_unittest-dwarf_cu_to_module_unittest.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/src_common_dumper_unittest-dwarf_line_to_module.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/src_common_dumper_unittest-dwarf_line_to_module_unittest.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/src_common_dumper_unittest-language.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/src_common_dumper_unittest-memory_range_unittest.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/src_common_dumper_unittest-module.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/src_common_dumper_unittest-module_unittest.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/src_common_dumper_unittest-stabs_reader.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/src_common_dumper_unittest-stabs_reader_unittest.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/src_common_dumper_unittest-stabs_to_module.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/src_common_dumper_unittest-stabs_to_module_unittest.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/src_common_dumper_unittest-test_assembler.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/src_common_dumper_unittest-bytereader.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/src_common_dumper_unittest-bytereader_unittest.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/src_common_dumper_unittest-cfi_assembler.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/src_common_dumper_unittest-dwarf2diehandler.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/src_common_dumper_unittest-dwarf2diehandler_unittest.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/src_common_dumper_unittest-dwarf2reader.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/src_common_dumper_unittest-elf_reader.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/src_common_dumper_unittest-dwarf2reader_cfi_unittest.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/src_common_dumper_unittest-dwarf2reader_die_unittest.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/src_common_dumper_unittest-crc32.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/src_common_dumper_unittest-dump_symbols.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/src_common_dumper_unittest-dump_symbols_unittest.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/src_common_dumper_unittest-elf_core_dump.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/src_common_dumper_unittest-elf_core_dump_unittest.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/src_common_dumper_unittest-elf_symbols_to_module.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/src_common_dumper_unittest-elf_symbols_to_module_unittest.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/src_common_dumper_unittest-elfutils.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/src_common_dumper_unittest-file_id.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/src_common_dumper_unittest-file_id_unittest.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/src_common_dumper_unittest-linux_libc_support.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/src_common_dumper_unittest-memory_mapped_file.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/src_common_dumper_unittest-memory_mapped_file_unittest.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/src_common_dumper_unittest-safe_readlink.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/src_common_dumper_unittest-safe_readlink_unittest.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/src_common_dumper_unittest-synth_elf.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/src_common_dumper_unittest-synth_elf_unittest.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/tests/src_common_dumper_unittest-crash_generator.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/tests/src_common_dumper_unittest-file_utils.$(OBJEXT)
+src_common_dumper_unittest_OBJECTS = \
+ $(am_src_common_dumper_unittest_OBJECTS)
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@src_common_dumper_unittest_DEPENDENCIES = \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ $(am__DEPENDENCIES_2) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ $(am__DEPENDENCIES_1) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ $(am__DEPENDENCIES_1)
+am__src_common_mac_macho_reader_unittest_SOURCES_DIST = \
+ src/common/dwarf_cfi_to_module.cc \
+ src/common/dwarf_cu_to_module.cc \
+ src/common/dwarf_line_to_module.cc src/common/language.cc \
+ src/common/md5.cc src/common/module.cc \
+ src/common/stabs_reader.cc src/common/stabs_to_module.cc \
+ src/common/test_assembler.cc src/common/dwarf/bytereader.cc \
+ src/common/dwarf/cfi_assembler.cc \
+ src/common/dwarf/dwarf2diehandler.cc \
+ src/common/dwarf/dwarf2reader.cc \
+ src/common/dwarf/elf_reader.cc \
+ src/common/mac/arch_utilities.cc src/common/mac/file_id.cc \
+ src/common/mac/macho_id.cc src/common/mac/macho_reader.cc \
+ src/common/mac/macho_reader_unittest.cc \
+ src/common/mac/macho_utilities.cc \
+ src/common/mac/macho_walker.cc src/common/tests/file_utils.cc
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@am_src_common_mac_macho_reader_unittest_OBJECTS = src/common/src_common_mac_macho_reader_unittest-dwarf_cfi_to_module.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/src_common_mac_macho_reader_unittest-dwarf_cu_to_module.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/src_common_mac_macho_reader_unittest-dwarf_line_to_module.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/src_common_mac_macho_reader_unittest-language.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/src_common_mac_macho_reader_unittest-md5.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/src_common_mac_macho_reader_unittest-module.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/src_common_mac_macho_reader_unittest-stabs_reader.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/src_common_mac_macho_reader_unittest-stabs_to_module.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/src_common_mac_macho_reader_unittest-test_assembler.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/src_common_mac_macho_reader_unittest-bytereader.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/src_common_mac_macho_reader_unittest-cfi_assembler.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/src_common_mac_macho_reader_unittest-dwarf2diehandler.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/src_common_mac_macho_reader_unittest-dwarf2reader.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/src_common_mac_macho_reader_unittest-elf_reader.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/mac/src_common_mac_macho_reader_unittest-arch_utilities.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/mac/src_common_mac_macho_reader_unittest-file_id.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/mac/src_common_mac_macho_reader_unittest-macho_id.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/mac/src_common_mac_macho_reader_unittest-macho_reader.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/mac/src_common_mac_macho_reader_unittest-macho_reader_unittest.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/mac/src_common_mac_macho_reader_unittest-macho_utilities.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/mac/src_common_mac_macho_reader_unittest-macho_walker.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/tests/src_common_mac_macho_reader_unittest-file_utils.$(OBJEXT)
+src_common_mac_macho_reader_unittest_OBJECTS = \
+ $(am_src_common_mac_macho_reader_unittest_OBJECTS)
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@src_common_mac_macho_reader_unittest_DEPENDENCIES = \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ $(am__DEPENDENCIES_2) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ $(am__DEPENDENCIES_1) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ $(am__DEPENDENCIES_1)
+am__src_common_test_assembler_unittest_SOURCES_DIST = \
+ src/common/test_assembler.cc src/common/test_assembler.h \
+ src/common/test_assembler_unittest.cc
+@DISABLE_PROCESSOR_FALSE@am_src_common_test_assembler_unittest_OBJECTS = src/common/src_common_test_assembler_unittest-test_assembler.$(OBJEXT) \
+@DISABLE_PROCESSOR_FALSE@ src/common/src_common_test_assembler_unittest-test_assembler_unittest.$(OBJEXT)
+src_common_test_assembler_unittest_OBJECTS = \
+ $(am_src_common_test_assembler_unittest_OBJECTS)
+@DISABLE_PROCESSOR_FALSE@src_common_test_assembler_unittest_DEPENDENCIES = \
+@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_2) \
+@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_1) \
+@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_1)
+am__src_processor_address_map_unittest_SOURCES_DIST = \
+ src/processor/address_map_unittest.cc
+@DISABLE_PROCESSOR_FALSE@am_src_processor_address_map_unittest_OBJECTS = src/processor/address_map_unittest.$(OBJEXT)
+src_processor_address_map_unittest_OBJECTS = \
+ $(am_src_processor_address_map_unittest_OBJECTS)
+@DISABLE_PROCESSOR_FALSE@src_processor_address_map_unittest_DEPENDENCIES = \
+@DISABLE_PROCESSOR_FALSE@ src/processor/logging.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o
+am__src_processor_basic_source_line_resolver_unittest_SOURCES_DIST = \
+ src/processor/basic_source_line_resolver_unittest.cc
+@DISABLE_PROCESSOR_FALSE@am_src_processor_basic_source_line_resolver_unittest_OBJECTS = src/processor/src_processor_basic_source_line_resolver_unittest-basic_source_line_resolver_unittest.$(OBJEXT)
+src_processor_basic_source_line_resolver_unittest_OBJECTS = $(am_src_processor_basic_source_line_resolver_unittest_OBJECTS)
+@DISABLE_PROCESSOR_FALSE@src_processor_basic_source_line_resolver_unittest_DEPENDENCIES = src/processor/basic_source_line_resolver.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/cfi_frame_info.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/logging.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/source_line_resolver_base.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/tokenize.o \
+@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_2) \
+@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_1) \
+@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_1)
+am__src_processor_cfi_frame_info_unittest_SOURCES_DIST = \
+ src/processor/cfi_frame_info_unittest.cc
+@DISABLE_PROCESSOR_FALSE@am_src_processor_cfi_frame_info_unittest_OBJECTS = src/processor/src_processor_cfi_frame_info_unittest-cfi_frame_info_unittest.$(OBJEXT)
+src_processor_cfi_frame_info_unittest_OBJECTS = \
+ $(am_src_processor_cfi_frame_info_unittest_OBJECTS)
+@DISABLE_PROCESSOR_FALSE@src_processor_cfi_frame_info_unittest_DEPENDENCIES = \
+@DISABLE_PROCESSOR_FALSE@ src/processor/cfi_frame_info.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/logging.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
+@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_2) \
+@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_1) \
+@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_1)
+am__src_processor_contained_range_map_unittest_SOURCES_DIST = \
+ src/processor/contained_range_map_unittest.cc
+@DISABLE_PROCESSOR_FALSE@am_src_processor_contained_range_map_unittest_OBJECTS = src/processor/contained_range_map_unittest.$(OBJEXT)
+src_processor_contained_range_map_unittest_OBJECTS = \
+ $(am_src_processor_contained_range_map_unittest_OBJECTS)
+@DISABLE_PROCESSOR_FALSE@src_processor_contained_range_map_unittest_DEPENDENCIES = \
+@DISABLE_PROCESSOR_FALSE@ src/processor/logging.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o
+am__src_processor_disassembler_x86_unittest_SOURCES_DIST = \
+ src/processor/disassembler_x86_unittest.cc
+@DISABLE_PROCESSOR_FALSE@am_src_processor_disassembler_x86_unittest_OBJECTS = src/processor/src_processor_disassembler_x86_unittest-disassembler_x86_unittest.$(OBJEXT)
+src_processor_disassembler_x86_unittest_OBJECTS = \
+ $(am_src_processor_disassembler_x86_unittest_OBJECTS)
+@DISABLE_PROCESSOR_FALSE@src_processor_disassembler_x86_unittest_DEPENDENCIES = \
+@DISABLE_PROCESSOR_FALSE@ src/processor/disassembler_x86.o \
+@DISABLE_PROCESSOR_FALSE@ src/third_party/libdisasm/libdisasm.a \
+@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_2) \
+@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_1) \
+@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_1)
+am__src_processor_exploitability_unittest_SOURCES_DIST = \
+ src/processor/exploitability_unittest.cc
+@DISABLE_PROCESSOR_FALSE@am_src_processor_exploitability_unittest_OBJECTS = src/processor/src_processor_exploitability_unittest-exploitability_unittest.$(OBJEXT)
+src_processor_exploitability_unittest_OBJECTS = \
+ $(am_src_processor_exploitability_unittest_OBJECTS)
+@DISABLE_PROCESSOR_FALSE@src_processor_exploitability_unittest_DEPENDENCIES = \
+@DISABLE_PROCESSOR_FALSE@ src/processor/minidump_processor.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/process_state.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/disassembler_x86.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/exploitability.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/exploitability_linux.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/exploitability_win.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/basic_code_modules.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/basic_source_line_resolver.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/call_stack.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/cfi_frame_info.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/dump_context.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/dump_object.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/logging.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/minidump.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/proc_maps_linux.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/simple_symbol_supplier.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/source_line_resolver_base.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stack_frame_cpu.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stack_frame_symbolizer.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_address_list.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_amd64.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm64.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_mips.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_ppc.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_ppc64.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_sparc.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_x86.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/symbolic_constants_win.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/tokenize.o \
+@DISABLE_PROCESSOR_FALSE@ src/third_party/libdisasm/libdisasm.a \
+@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_2) \
+@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_1) \
+@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_1)
+am__src_processor_fast_source_line_resolver_unittest_SOURCES_DIST = \
+ src/processor/fast_source_line_resolver_unittest.cc
+@DISABLE_PROCESSOR_FALSE@am_src_processor_fast_source_line_resolver_unittest_OBJECTS = src/processor/src_processor_fast_source_line_resolver_unittest-fast_source_line_resolver_unittest.$(OBJEXT)
+src_processor_fast_source_line_resolver_unittest_OBJECTS = $(am_src_processor_fast_source_line_resolver_unittest_OBJECTS)
+@DISABLE_PROCESSOR_FALSE@src_processor_fast_source_line_resolver_unittest_DEPENDENCIES = src/processor/fast_source_line_resolver.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/basic_source_line_resolver.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/cfi_frame_info.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/module_comparer.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/module_serializer.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/logging.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/source_line_resolver_base.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/tokenize.o \
+@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_2) \
+@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_1) \
+@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_1)
+am__src_processor_map_serializers_unittest_SOURCES_DIST = \
+ src/processor/map_serializers_unittest.cc
+@DISABLE_PROCESSOR_FALSE@am_src_processor_map_serializers_unittest_OBJECTS = src/processor/src_processor_map_serializers_unittest-map_serializers_unittest.$(OBJEXT)
+src_processor_map_serializers_unittest_OBJECTS = \
+ $(am_src_processor_map_serializers_unittest_OBJECTS)
+@DISABLE_PROCESSOR_FALSE@src_processor_map_serializers_unittest_DEPENDENCIES = \
+@DISABLE_PROCESSOR_FALSE@ src/processor/logging.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
+@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_2) \
+@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_1) \
+@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_1)
+am__src_processor_microdump_processor_unittest_SOURCES_DIST = \
+ src/processor/microdump_processor_unittest.cc
+@DISABLE_PROCESSOR_FALSE@am_src_processor_microdump_processor_unittest_OBJECTS = src/processor/src_processor_microdump_processor_unittest-microdump_processor_unittest.$(OBJEXT)
+src_processor_microdump_processor_unittest_OBJECTS = \
+ $(am_src_processor_microdump_processor_unittest_OBJECTS)
+@DISABLE_PROCESSOR_FALSE@src_processor_microdump_processor_unittest_DEPENDENCIES = \
+@DISABLE_PROCESSOR_FALSE@ src/processor/basic_code_modules.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/basic_source_line_resolver.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/call_stack.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/cfi_frame_info.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/dump_context.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/dump_object.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/logging.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/microdump.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/microdump_processor.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/process_state.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/simple_symbol_supplier.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/source_line_resolver_base.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stack_frame_symbolizer.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_address_list.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_amd64.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm64.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_mips.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_ppc.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_ppc64.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_sparc.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_x86.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/tokenize.o \
+@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_2) \
+@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_1) \
+@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_1)
+am__src_processor_microdump_stackwalk_SOURCES_DIST = \
+ src/processor/microdump_stackwalk.cc
+@DISABLE_PROCESSOR_FALSE@am_src_processor_microdump_stackwalk_OBJECTS = src/processor/microdump_stackwalk.$(OBJEXT)
+src_processor_microdump_stackwalk_OBJECTS = \
+ $(am_src_processor_microdump_stackwalk_OBJECTS)
+@DISABLE_PROCESSOR_FALSE@src_processor_microdump_stackwalk_DEPENDENCIES = \
+@DISABLE_PROCESSOR_FALSE@ src/processor/basic_code_modules.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/basic_source_line_resolver.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/call_stack.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/cfi_frame_info.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/disassembler_x86.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/dump_context.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/dump_object.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/logging.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/microdump.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/microdump_processor.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/process_state.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/simple_symbol_supplier.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/source_line_resolver_base.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stack_frame_cpu.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stack_frame_symbolizer.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalk_common.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_address_list.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_amd64.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm64.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_mips.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_ppc.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_ppc64.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_sparc.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_x86.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/tokenize.o \
+@DISABLE_PROCESSOR_FALSE@ src/third_party/libdisasm/libdisasm.a
+am__src_processor_minidump_dump_SOURCES_DIST = \
+ src/processor/minidump_dump.cc
+@DISABLE_PROCESSOR_FALSE@am_src_processor_minidump_dump_OBJECTS = src/processor/minidump_dump.$(OBJEXT)
+src_processor_minidump_dump_OBJECTS = \
+ $(am_src_processor_minidump_dump_OBJECTS)
+@DISABLE_PROCESSOR_FALSE@src_processor_minidump_dump_DEPENDENCIES = \
+@DISABLE_PROCESSOR_FALSE@ src/processor/basic_code_modules.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/dump_context.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/dump_object.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/logging.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/minidump.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/proc_maps_linux.o
+am__src_processor_minidump_processor_unittest_SOURCES_DIST = \
+ src/processor/minidump_processor_unittest.cc
+@DISABLE_PROCESSOR_FALSE@am_src_processor_minidump_processor_unittest_OBJECTS = src/processor/src_processor_minidump_processor_unittest-minidump_processor_unittest.$(OBJEXT)
+src_processor_minidump_processor_unittest_OBJECTS = \
+ $(am_src_processor_minidump_processor_unittest_OBJECTS)
+@DISABLE_PROCESSOR_FALSE@src_processor_minidump_processor_unittest_DEPENDENCIES = \
+@DISABLE_PROCESSOR_FALSE@ src/processor/basic_code_modules.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/basic_source_line_resolver.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/call_stack.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/cfi_frame_info.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/disassembler_x86.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/dump_context.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/dump_object.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/exploitability.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/exploitability_linux.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/exploitability_win.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/logging.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/minidump_processor.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/minidump.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/process_state.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/proc_maps_linux.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/source_line_resolver_base.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stack_frame_cpu.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stack_frame_symbolizer.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_address_list.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_amd64.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm64.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_mips.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_ppc.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_ppc64.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_sparc.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_x86.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/symbolic_constants_win.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/tokenize.o \
+@DISABLE_PROCESSOR_FALSE@ src/third_party/libdisasm/libdisasm.a \
+@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_2) \
+@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_1) \
+@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_1)
+am__src_processor_minidump_stackwalk_SOURCES_DIST = \
+ src/processor/minidump_stackwalk.cc
+@DISABLE_PROCESSOR_FALSE@am_src_processor_minidump_stackwalk_OBJECTS = src/processor/minidump_stackwalk.$(OBJEXT)
+src_processor_minidump_stackwalk_OBJECTS = \
+ $(am_src_processor_minidump_stackwalk_OBJECTS)
+@DISABLE_PROCESSOR_FALSE@src_processor_minidump_stackwalk_DEPENDENCIES = \
+@DISABLE_PROCESSOR_FALSE@ src/processor/basic_code_modules.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/basic_source_line_resolver.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/call_stack.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/cfi_frame_info.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/disassembler_x86.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/dump_context.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/dump_object.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/exploitability.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/exploitability_linux.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/exploitability_win.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/logging.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/minidump.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/minidump_processor.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/process_state.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/proc_maps_linux.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/simple_symbol_supplier.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/source_line_resolver_base.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stack_frame_cpu.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stack_frame_symbolizer.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalk_common.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_address_list.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_amd64.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm64.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_mips.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_ppc.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_ppc64.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_sparc.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_x86.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/symbolic_constants_win.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/tokenize.o \
+@DISABLE_PROCESSOR_FALSE@ src/third_party/libdisasm/libdisasm.a
+am__src_processor_minidump_unittest_SOURCES_DIST = \
+ src/common/test_assembler.cc \
+ src/processor/minidump_unittest.cc \
+ src/processor/synth_minidump.cc
+@DISABLE_PROCESSOR_FALSE@am_src_processor_minidump_unittest_OBJECTS = src/common/src_processor_minidump_unittest-test_assembler.$(OBJEXT) \
+@DISABLE_PROCESSOR_FALSE@ src/processor/src_processor_minidump_unittest-minidump_unittest.$(OBJEXT) \
+@DISABLE_PROCESSOR_FALSE@ src/processor/src_processor_minidump_unittest-synth_minidump.$(OBJEXT)
+src_processor_minidump_unittest_OBJECTS = \
+ $(am_src_processor_minidump_unittest_OBJECTS)
+@DISABLE_PROCESSOR_FALSE@src_processor_minidump_unittest_DEPENDENCIES = \
+@DISABLE_PROCESSOR_FALSE@ src/processor/basic_code_modules.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/dump_context.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/dump_object.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/logging.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/minidump.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/proc_maps_linux.o \
+@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_2) \
+@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_1) \
+@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_1)
+am__src_processor_pathname_stripper_unittest_SOURCES_DIST = \
+ src/processor/pathname_stripper_unittest.cc
+@DISABLE_PROCESSOR_FALSE@am_src_processor_pathname_stripper_unittest_OBJECTS = src/processor/pathname_stripper_unittest.$(OBJEXT)
+src_processor_pathname_stripper_unittest_OBJECTS = \
+ $(am_src_processor_pathname_stripper_unittest_OBJECTS)
+@DISABLE_PROCESSOR_FALSE@src_processor_pathname_stripper_unittest_DEPENDENCIES = \
+@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
+@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_1) \
+@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_1)
+am__src_processor_postfix_evaluator_unittest_SOURCES_DIST = \
+ src/processor/postfix_evaluator_unittest.cc
+@DISABLE_PROCESSOR_FALSE@am_src_processor_postfix_evaluator_unittest_OBJECTS = src/processor/postfix_evaluator_unittest.$(OBJEXT)
+src_processor_postfix_evaluator_unittest_OBJECTS = \
+ $(am_src_processor_postfix_evaluator_unittest_OBJECTS)
+@DISABLE_PROCESSOR_FALSE@src_processor_postfix_evaluator_unittest_DEPENDENCIES = \
+@DISABLE_PROCESSOR_FALSE@ src/processor/logging.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
+@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_1) \
+@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_1)
+am__src_processor_proc_maps_linux_unittest_SOURCES_DIST = \
+ src/processor/proc_maps_linux.cc \
+ src/processor/proc_maps_linux_unittest.cc
+@DISABLE_PROCESSOR_FALSE@am_src_processor_proc_maps_linux_unittest_OBJECTS = src/processor/src_processor_proc_maps_linux_unittest-proc_maps_linux.$(OBJEXT) \
+@DISABLE_PROCESSOR_FALSE@ src/processor/src_processor_proc_maps_linux_unittest-proc_maps_linux_unittest.$(OBJEXT)
+src_processor_proc_maps_linux_unittest_OBJECTS = \
+ $(am_src_processor_proc_maps_linux_unittest_OBJECTS)
+@DISABLE_PROCESSOR_FALSE@src_processor_proc_maps_linux_unittest_DEPENDENCIES = \
+@DISABLE_PROCESSOR_FALSE@ src/processor/logging.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
+@DISABLE_PROCESSOR_FALSE@ src/third_party/libdisasm/libdisasm.a \
+@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_2) \
+@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_1) \
+@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_1)
+am__src_processor_range_map_shrink_down_unittest_SOURCES_DIST = \
+ src/processor/range_map_shrink_down_unittest.cc
+@DISABLE_PROCESSOR_FALSE@am_src_processor_range_map_shrink_down_unittest_OBJECTS = src/processor/src_processor_range_map_shrink_down_unittest-range_map_shrink_down_unittest.$(OBJEXT)
+src_processor_range_map_shrink_down_unittest_OBJECTS = \
+ $(am_src_processor_range_map_shrink_down_unittest_OBJECTS)
+@DISABLE_PROCESSOR_FALSE@src_processor_range_map_shrink_down_unittest_DEPENDENCIES = \
+@DISABLE_PROCESSOR_FALSE@ src/processor/logging.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
+@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_2) \
+@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_1) \
+@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_1)
+am__src_processor_range_map_unittest_SOURCES_DIST = \
+ src/processor/range_map_unittest.cc
+@DISABLE_PROCESSOR_FALSE@am_src_processor_range_map_unittest_OBJECTS = src/processor/range_map_unittest.$(OBJEXT)
+src_processor_range_map_unittest_OBJECTS = \
+ $(am_src_processor_range_map_unittest_OBJECTS)
+@DISABLE_PROCESSOR_FALSE@src_processor_range_map_unittest_DEPENDENCIES = \
+@DISABLE_PROCESSOR_FALSE@ src/processor/logging.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
+@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_1) \
+@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_1)
+am__src_processor_stackwalker_address_list_unittest_SOURCES_DIST = \
+ src/common/test_assembler.cc \
+ src/processor/stackwalker_address_list_unittest.cc
+@DISABLE_PROCESSOR_FALSE@am_src_processor_stackwalker_address_list_unittest_OBJECTS = src/common/src_processor_stackwalker_address_list_unittest-test_assembler.$(OBJEXT) \
+@DISABLE_PROCESSOR_FALSE@ src/processor/src_processor_stackwalker_address_list_unittest-stackwalker_address_list_unittest.$(OBJEXT)
+src_processor_stackwalker_address_list_unittest_OBJECTS = \
+ $(am_src_processor_stackwalker_address_list_unittest_OBJECTS)
+@DISABLE_PROCESSOR_FALSE@src_processor_stackwalker_address_list_unittest_DEPENDENCIES = \
+@DISABLE_PROCESSOR_FALSE@ src/libbreakpad.a \
+@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_2) \
+@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_1) \
+@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_1)
+am__src_processor_stackwalker_amd64_unittest_SOURCES_DIST = \
+ src/common/test_assembler.cc \
+ src/processor/stackwalker_amd64_unittest.cc
+@DISABLE_PROCESSOR_FALSE@am_src_processor_stackwalker_amd64_unittest_OBJECTS = src/common/src_processor_stackwalker_amd64_unittest-test_assembler.$(OBJEXT) \
+@DISABLE_PROCESSOR_FALSE@ src/processor/src_processor_stackwalker_amd64_unittest-stackwalker_amd64_unittest.$(OBJEXT)
+src_processor_stackwalker_amd64_unittest_OBJECTS = \
+ $(am_src_processor_stackwalker_amd64_unittest_OBJECTS)
+@DISABLE_PROCESSOR_FALSE@src_processor_stackwalker_amd64_unittest_DEPENDENCIES = \
+@DISABLE_PROCESSOR_FALSE@ src/libbreakpad.a \
+@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_2) \
+@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_1) \
+@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_1)
+am__src_processor_stackwalker_arm64_unittest_SOURCES_DIST = \
+ src/common/test_assembler.cc \
+ src/processor/stackwalker_arm64_unittest.cc
+@DISABLE_PROCESSOR_FALSE@am_src_processor_stackwalker_arm64_unittest_OBJECTS = src/common/src_processor_stackwalker_arm64_unittest-test_assembler.$(OBJEXT) \
+@DISABLE_PROCESSOR_FALSE@ src/processor/src_processor_stackwalker_arm64_unittest-stackwalker_arm64_unittest.$(OBJEXT)
+src_processor_stackwalker_arm64_unittest_OBJECTS = \
+ $(am_src_processor_stackwalker_arm64_unittest_OBJECTS)
+@DISABLE_PROCESSOR_FALSE@src_processor_stackwalker_arm64_unittest_DEPENDENCIES = \
+@DISABLE_PROCESSOR_FALSE@ src/libbreakpad.a \
+@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_2) \
+@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_1) \
+@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_1)
+am__src_processor_stackwalker_arm_unittest_SOURCES_DIST = \
+ src/common/test_assembler.cc \
+ src/processor/stackwalker_arm_unittest.cc
+@DISABLE_PROCESSOR_FALSE@am_src_processor_stackwalker_arm_unittest_OBJECTS = src/common/src_processor_stackwalker_arm_unittest-test_assembler.$(OBJEXT) \
+@DISABLE_PROCESSOR_FALSE@ src/processor/src_processor_stackwalker_arm_unittest-stackwalker_arm_unittest.$(OBJEXT)
+src_processor_stackwalker_arm_unittest_OBJECTS = \
+ $(am_src_processor_stackwalker_arm_unittest_OBJECTS)
+@DISABLE_PROCESSOR_FALSE@src_processor_stackwalker_arm_unittest_DEPENDENCIES = \
+@DISABLE_PROCESSOR_FALSE@ src/libbreakpad.a \
+@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_2) \
+@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_1) \
+@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_1)
+am__src_processor_stackwalker_mips64_unittest_SOURCES_DIST = \
+ src/common/test_assembler.cc \
+ src/processor/stackwalker_mips64_unittest.cc
+@DISABLE_PROCESSOR_FALSE@am_src_processor_stackwalker_mips64_unittest_OBJECTS = src/common/src_processor_stackwalker_mips64_unittest-test_assembler.$(OBJEXT) \
+@DISABLE_PROCESSOR_FALSE@ src/processor/src_processor_stackwalker_mips64_unittest-stackwalker_mips64_unittest.$(OBJEXT)
+src_processor_stackwalker_mips64_unittest_OBJECTS = \
+ $(am_src_processor_stackwalker_mips64_unittest_OBJECTS)
+@DISABLE_PROCESSOR_FALSE@src_processor_stackwalker_mips64_unittest_DEPENDENCIES = \
+@DISABLE_PROCESSOR_FALSE@ src/libbreakpad.a \
+@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_2) \
+@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_1) \
+@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_1)
+am__src_processor_stackwalker_mips_unittest_SOURCES_DIST = \
+ src/common/test_assembler.cc \
+ src/processor/stackwalker_mips_unittest.cc
+@DISABLE_PROCESSOR_FALSE@am_src_processor_stackwalker_mips_unittest_OBJECTS = src/common/src_processor_stackwalker_mips_unittest-test_assembler.$(OBJEXT) \
+@DISABLE_PROCESSOR_FALSE@ src/processor/src_processor_stackwalker_mips_unittest-stackwalker_mips_unittest.$(OBJEXT)
+src_processor_stackwalker_mips_unittest_OBJECTS = \
+ $(am_src_processor_stackwalker_mips_unittest_OBJECTS)
+@DISABLE_PROCESSOR_FALSE@src_processor_stackwalker_mips_unittest_DEPENDENCIES = \
+@DISABLE_PROCESSOR_FALSE@ src/libbreakpad.a \
+@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_2) \
+@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_1) \
+@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_1)
+am__src_processor_stackwalker_selftest_SOURCES_DIST = \
+ src/processor/stackwalker_selftest.cc
+@DISABLE_PROCESSOR_FALSE@am_src_processor_stackwalker_selftest_OBJECTS = src/processor/stackwalker_selftest.$(OBJEXT)
+src_processor_stackwalker_selftest_OBJECTS = \
+ $(am_src_processor_stackwalker_selftest_OBJECTS)
+@DISABLE_PROCESSOR_FALSE@src_processor_stackwalker_selftest_DEPENDENCIES = \
+@DISABLE_PROCESSOR_FALSE@ src/processor/basic_code_modules.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/basic_source_line_resolver.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/call_stack.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/disassembler_x86.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/exploitability.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/exploitability_linux.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/exploitability_win.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/logging.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/minidump.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/proc_maps_linux.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/source_line_resolver_base.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stack_frame_cpu.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stack_frame_symbolizer.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_address_list.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_amd64.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm64.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_mips.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_ppc.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_ppc64.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_sparc.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_x86.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/tokenize.o \
+@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_1) \
+@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_1)
+am__src_processor_stackwalker_x86_unittest_SOURCES_DIST = \
+ src/common/test_assembler.cc \
+ src/processor/stackwalker_x86_unittest.cc
+@DISABLE_PROCESSOR_FALSE@am_src_processor_stackwalker_x86_unittest_OBJECTS = src/common/src_processor_stackwalker_x86_unittest-test_assembler.$(OBJEXT) \
+@DISABLE_PROCESSOR_FALSE@ src/processor/src_processor_stackwalker_x86_unittest-stackwalker_x86_unittest.$(OBJEXT)
+src_processor_stackwalker_x86_unittest_OBJECTS = \
+ $(am_src_processor_stackwalker_x86_unittest_OBJECTS)
+@DISABLE_PROCESSOR_FALSE@src_processor_stackwalker_x86_unittest_DEPENDENCIES = \
+@DISABLE_PROCESSOR_FALSE@ src/libbreakpad.a \
+@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_2) \
+@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_1) \
+@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_1)
+am__src_processor_static_address_map_unittest_SOURCES_DIST = \
+ src/processor/static_address_map_unittest.cc
+@DISABLE_PROCESSOR_FALSE@am_src_processor_static_address_map_unittest_OBJECTS = src/processor/src_processor_static_address_map_unittest-static_address_map_unittest.$(OBJEXT)
+src_processor_static_address_map_unittest_OBJECTS = \
+ $(am_src_processor_static_address_map_unittest_OBJECTS)
+@DISABLE_PROCESSOR_FALSE@src_processor_static_address_map_unittest_DEPENDENCIES = \
+@DISABLE_PROCESSOR_FALSE@ src/processor/logging.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
+@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_2) \
+@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_1) \
+@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_1)
+am__src_processor_static_contained_range_map_unittest_SOURCES_DIST = \
+ src/processor/static_contained_range_map_unittest.cc
+@DISABLE_PROCESSOR_FALSE@am_src_processor_static_contained_range_map_unittest_OBJECTS = src/processor/src_processor_static_contained_range_map_unittest-static_contained_range_map_unittest.$(OBJEXT)
+src_processor_static_contained_range_map_unittest_OBJECTS = $(am_src_processor_static_contained_range_map_unittest_OBJECTS)
+@DISABLE_PROCESSOR_FALSE@src_processor_static_contained_range_map_unittest_DEPENDENCIES = \
+@DISABLE_PROCESSOR_FALSE@ src/processor/logging.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
+@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_2) \
+@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_1) \
+@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_1)
+am__src_processor_static_map_unittest_SOURCES_DIST = \
+ src/processor/static_map_unittest.cc
+@DISABLE_PROCESSOR_FALSE@am_src_processor_static_map_unittest_OBJECTS = src/processor/src_processor_static_map_unittest-static_map_unittest.$(OBJEXT)
+src_processor_static_map_unittest_OBJECTS = \
+ $(am_src_processor_static_map_unittest_OBJECTS)
+@DISABLE_PROCESSOR_FALSE@src_processor_static_map_unittest_DEPENDENCIES = \
+@DISABLE_PROCESSOR_FALSE@ src/processor/logging.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
+@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_2) \
+@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_1) \
+@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_1)
+am__src_processor_static_range_map_unittest_SOURCES_DIST = \
+ src/processor/static_range_map_unittest.cc
+@DISABLE_PROCESSOR_FALSE@am_src_processor_static_range_map_unittest_OBJECTS = src/processor/src_processor_static_range_map_unittest-static_range_map_unittest.$(OBJEXT)
+src_processor_static_range_map_unittest_OBJECTS = \
+ $(am_src_processor_static_range_map_unittest_OBJECTS)
+@DISABLE_PROCESSOR_FALSE@src_processor_static_range_map_unittest_DEPENDENCIES = \
+@DISABLE_PROCESSOR_FALSE@ src/processor/logging.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
+@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_2) \
+@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_1) \
+@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_1)
+am__src_processor_synth_minidump_unittest_SOURCES_DIST = \
+ src/common/test_assembler.cc src/common/test_assembler.h \
+ src/processor/synth_minidump_unittest.cc \
+ src/processor/synth_minidump.cc src/processor/synth_minidump.h
+@DISABLE_PROCESSOR_FALSE@am_src_processor_synth_minidump_unittest_OBJECTS = src/common/src_processor_synth_minidump_unittest-test_assembler.$(OBJEXT) \
+@DISABLE_PROCESSOR_FALSE@ src/processor/src_processor_synth_minidump_unittest-synth_minidump_unittest.$(OBJEXT) \
+@DISABLE_PROCESSOR_FALSE@ src/processor/src_processor_synth_minidump_unittest-synth_minidump.$(OBJEXT)
+src_processor_synth_minidump_unittest_OBJECTS = \
+ $(am_src_processor_synth_minidump_unittest_OBJECTS)
+@DISABLE_PROCESSOR_FALSE@src_processor_synth_minidump_unittest_DEPENDENCIES = \
+@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_2) \
+@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_1) \
+@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_1)
+am__src_tools_linux_core2md_core2md_SOURCES_DIST = \
+ src/tools/linux/core2md/core2md.cc
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@am_src_tools_linux_core2md_core2md_OBJECTS = src/tools/linux/core2md/core2md.$(OBJEXT)
+src_tools_linux_core2md_core2md_OBJECTS = \
+ $(am_src_tools_linux_core2md_core2md_OBJECTS)
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@src_tools_linux_core2md_core2md_DEPENDENCIES = src/client/linux/libbreakpad_client.a
+am__src_tools_linux_dump_syms_dump_syms_SOURCES_DIST = \
+ src/common/dwarf_cfi_to_module.cc \
+ src/common/dwarf_cu_to_module.cc \
+ src/common/dwarf_line_to_module.cc src/common/language.cc \
+ src/common/module.cc src/common/stabs_reader.cc \
+ src/common/stabs_to_module.cc src/common/dwarf/bytereader.cc \
+ src/common/dwarf/dwarf2diehandler.cc \
+ src/common/dwarf/dwarf2reader.cc \
+ src/common/dwarf/elf_reader.cc src/common/linux/crc32.cc \
+ src/common/linux/dump_symbols.cc \
+ src/common/linux/dump_symbols.h \
+ src/common/linux/elf_symbols_to_module.cc \
+ src/common/linux/elf_symbols_to_module.h \
+ src/common/linux/elfutils.cc src/common/linux/file_id.cc \
+ src/common/linux/linux_libc_support.cc \
+ src/common/linux/memory_mapped_file.cc \
+ src/common/linux/safe_readlink.cc \
+ src/tools/linux/dump_syms/dump_syms.cc
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@am_src_tools_linux_dump_syms_dump_syms_OBJECTS = src/common/dwarf_cfi_to_module.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf_cu_to_module.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf_line_to_module.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/language.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/module.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/stabs_reader.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/stabs_to_module.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/bytereader.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/dwarf2diehandler.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/dwarf2reader.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/elf_reader.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/crc32.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/dump_symbols.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/elf_symbols_to_module.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/elfutils.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/file_id.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/linux_libc_support.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/memory_mapped_file.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/safe_readlink.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/tools/linux/dump_syms/dump_syms.$(OBJEXT)
+src_tools_linux_dump_syms_dump_syms_OBJECTS = \
+ $(am_src_tools_linux_dump_syms_dump_syms_OBJECTS)
+src_tools_linux_dump_syms_dump_syms_LDADD = $(LDADD)
+am__src_tools_linux_md2core_minidump_2_core_SOURCES_DIST = \
+ src/common/linux/memory_mapped_file.cc \
+ src/tools/linux/md2core/minidump-2-core.cc \
+ src/tools/linux/md2core/minidump_memory_range.h
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@am_src_tools_linux_md2core_minidump_2_core_OBJECTS = src/common/linux/memory_mapped_file.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/tools/linux/md2core/minidump-2-core.$(OBJEXT)
+src_tools_linux_md2core_minidump_2_core_OBJECTS = \
+ $(am_src_tools_linux_md2core_minidump_2_core_OBJECTS)
+src_tools_linux_md2core_minidump_2_core_LDADD = $(LDADD)
+am__src_tools_linux_md2core_minidump_2_core_unittest_SOURCES_DIST = \
+ src/tools/linux/md2core/minidump_memory_range_unittest.cc
+@LINUX_HOST_TRUE@am_src_tools_linux_md2core_minidump_2_core_unittest_OBJECTS = src/tools/linux/md2core/src_tools_linux_md2core_minidump_2_core_unittest-minidump_memory_range_unittest.$(OBJEXT)
+src_tools_linux_md2core_minidump_2_core_unittest_OBJECTS = $(am_src_tools_linux_md2core_minidump_2_core_unittest_OBJECTS)
+@LINUX_HOST_TRUE@src_tools_linux_md2core_minidump_2_core_unittest_DEPENDENCIES = \
+@LINUX_HOST_TRUE@ $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1) \
+@LINUX_HOST_TRUE@ $(am__DEPENDENCIES_1)
+am__src_tools_linux_symupload_minidump_upload_SOURCES_DIST = \
+ src/common/linux/http_upload.cc \
+ src/tools/linux/symupload/minidump_upload.cc
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@am_src_tools_linux_symupload_minidump_upload_OBJECTS = src/common/linux/http_upload.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/tools/linux/symupload/minidump_upload.$(OBJEXT)
+src_tools_linux_symupload_minidump_upload_OBJECTS = \
+ $(am_src_tools_linux_symupload_minidump_upload_OBJECTS)
+src_tools_linux_symupload_minidump_upload_DEPENDENCIES =
+am__src_tools_linux_symupload_sym_upload_SOURCES_DIST = \
+ src/common/linux/http_upload.cc src/common/linux/http_upload.h \
+ src/common/linux/symbol_upload.cc \
+ src/common/linux/symbol_upload.h \
+ src/tools/linux/symupload/sym_upload.cc
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@am_src_tools_linux_symupload_sym_upload_OBJECTS = src/common/linux/http_upload.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/symbol_upload.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/tools/linux/symupload/sym_upload.$(OBJEXT)
+src_tools_linux_symupload_sym_upload_OBJECTS = \
+ $(am_src_tools_linux_symupload_sym_upload_OBJECTS)
+src_tools_linux_symupload_sym_upload_DEPENDENCIES =
+am__src_tools_mac_dump_syms_dump_syms_mac_SOURCES_DIST = \
+ src/common/dwarf_cfi_to_module.cc \
+ src/common/dwarf_cu_to_module.cc \
+ src/common/dwarf_line_to_module.cc src/common/language.cc \
+ src/common/md5.cc src/common/module.cc \
+ src/common/stabs_reader.cc src/common/stabs_to_module.cc \
+ src/common/dwarf/bytereader.cc \
+ src/common/dwarf/dwarf2diehandler.cc \
+ src/common/dwarf/dwarf2reader.cc \
+ src/common/dwarf/elf_reader.cc \
+ src/common/mac/arch_utilities.cc src/common/mac/dump_syms.cc \
+ src/common/mac/dump_syms.h src/common/mac/file_id.cc \
+ src/common/mac/file_id.h src/common/mac/macho_id.cc \
+ src/common/mac/macho_id.h src/common/mac/macho_reader.cc \
+ src/common/mac/macho_reader.h \
+ src/common/mac/macho_utilities.cc \
+ src/common/mac/macho_utilities.h \
+ src/common/mac/macho_walker.cc src/common/mac/macho_walker.h \
+ src/tools/mac/dump_syms/dump_syms_tool.cc
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@am_src_tools_mac_dump_syms_dump_syms_mac_OBJECTS = src/common/src_tools_mac_dump_syms_dump_syms_mac-dwarf_cfi_to_module.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/src_tools_mac_dump_syms_dump_syms_mac-dwarf_cu_to_module.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/src_tools_mac_dump_syms_dump_syms_mac-dwarf_line_to_module.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/src_tools_mac_dump_syms_dump_syms_mac-language.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/src_tools_mac_dump_syms_dump_syms_mac-md5.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/src_tools_mac_dump_syms_dump_syms_mac-module.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/src_tools_mac_dump_syms_dump_syms_mac-stabs_reader.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/src_tools_mac_dump_syms_dump_syms_mac-stabs_to_module.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-bytereader.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-dwarf2diehandler.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-dwarf2reader.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-elf_reader.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-arch_utilities.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-dump_syms.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-file_id.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-macho_id.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-macho_reader.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-macho_utilities.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-macho_walker.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/tools/mac/dump_syms/src_tools_mac_dump_syms_dump_syms_mac-dump_syms_tool.$(OBJEXT)
+src_tools_mac_dump_syms_dump_syms_mac_OBJECTS = \
+ $(am_src_tools_mac_dump_syms_dump_syms_mac_OBJECTS)
+src_tools_mac_dump_syms_dump_syms_mac_LDADD = $(LDADD)
+src_tools_mac_dump_syms_dump_syms_mac_LINK = $(CXXLD) \
+ $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+SCRIPTS = $(noinst_SCRIPTS)
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/src
+depcomp = $(SHELL) $(top_srcdir)/autotools/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+AM_V_lt = $(am__v_lt_@AM_V@)
+am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+am__v_lt_1 =
+CPPASCOMPILE = $(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CCASFLAGS) $(CCASFLAGS)
+AM_V_CPPAS = $(am__v_CPPAS_@AM_V@)
+am__v_CPPAS_ = $(am__v_CPPAS_@AM_DEFAULT_V@)
+am__v_CPPAS_0 = @echo " CPPAS " $@;
+am__v_CPPAS_1 =
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo " CC " $@;
+am__v_CC_1 =
+CCLD = $(CC)
+LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo " CCLD " $@;
+am__v_CCLD_1 =
+CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+AM_V_CXX = $(am__v_CXX_@AM_V@)
+am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@)
+am__v_CXX_0 = @echo " CXX " $@;
+am__v_CXX_1 =
+CXXLD = $(CXX)
+CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \
+ -o $@
+AM_V_CXXLD = $(am__v_CXXLD_@AM_V@)
+am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@)
+am__v_CXXLD_0 = @echo " CXXLD " $@;
+am__v_CXXLD_1 =
+SOURCES = $(src_client_linux_libbreakpad_client_a_SOURCES) \
+ $(src_libbreakpad_a_SOURCES) \
+ $(src_testing_libtesting_a_SOURCES) \
+ $(src_third_party_libdisasm_libdisasm_a_SOURCES) \
+ $(src_client_linux_linux_client_unittest_SOURCES) \
+ $(src_client_linux_linux_client_unittest_shlib_SOURCES) \
+ $(src_client_linux_linux_dumper_unittest_helper_SOURCES) \
+ $(src_common_dumper_unittest_SOURCES) \
+ $(src_common_mac_macho_reader_unittest_SOURCES) \
+ $(src_common_test_assembler_unittest_SOURCES) \
+ $(src_processor_address_map_unittest_SOURCES) \
+ $(src_processor_basic_source_line_resolver_unittest_SOURCES) \
+ $(src_processor_cfi_frame_info_unittest_SOURCES) \
+ $(src_processor_contained_range_map_unittest_SOURCES) \
+ $(src_processor_disassembler_x86_unittest_SOURCES) \
+ $(src_processor_exploitability_unittest_SOURCES) \
+ $(src_processor_fast_source_line_resolver_unittest_SOURCES) \
+ $(src_processor_map_serializers_unittest_SOURCES) \
+ $(src_processor_microdump_processor_unittest_SOURCES) \
+ $(src_processor_microdump_stackwalk_SOURCES) \
+ $(src_processor_minidump_dump_SOURCES) \
+ $(src_processor_minidump_processor_unittest_SOURCES) \
+ $(src_processor_minidump_stackwalk_SOURCES) \
+ $(src_processor_minidump_unittest_SOURCES) \
+ $(src_processor_pathname_stripper_unittest_SOURCES) \
+ $(src_processor_postfix_evaluator_unittest_SOURCES) \
+ $(src_processor_proc_maps_linux_unittest_SOURCES) \
+ $(src_processor_range_map_shrink_down_unittest_SOURCES) \
+ $(src_processor_range_map_unittest_SOURCES) \
+ $(src_processor_stackwalker_address_list_unittest_SOURCES) \
+ $(src_processor_stackwalker_amd64_unittest_SOURCES) \
+ $(src_processor_stackwalker_arm64_unittest_SOURCES) \
+ $(src_processor_stackwalker_arm_unittest_SOURCES) \
+ $(src_processor_stackwalker_mips64_unittest_SOURCES) \
+ $(src_processor_stackwalker_mips_unittest_SOURCES) \
+ $(src_processor_stackwalker_selftest_SOURCES) \
+ $(src_processor_stackwalker_x86_unittest_SOURCES) \
+ $(src_processor_static_address_map_unittest_SOURCES) \
+ $(src_processor_static_contained_range_map_unittest_SOURCES) \
+ $(src_processor_static_map_unittest_SOURCES) \
+ $(src_processor_static_range_map_unittest_SOURCES) \
+ $(src_processor_synth_minidump_unittest_SOURCES) \
+ $(src_tools_linux_core2md_core2md_SOURCES) \
+ $(src_tools_linux_dump_syms_dump_syms_SOURCES) \
+ $(src_tools_linux_md2core_minidump_2_core_SOURCES) \
+ $(src_tools_linux_md2core_minidump_2_core_unittest_SOURCES) \
+ $(src_tools_linux_symupload_minidump_upload_SOURCES) \
+ $(src_tools_linux_symupload_sym_upload_SOURCES) \
+ $(src_tools_mac_dump_syms_dump_syms_mac_SOURCES)
+DIST_SOURCES = \
+ $(am__src_client_linux_libbreakpad_client_a_SOURCES_DIST) \
+ $(am__src_libbreakpad_a_SOURCES_DIST) \
+ $(am__src_testing_libtesting_a_SOURCES_DIST) \
+ $(am__src_third_party_libdisasm_libdisasm_a_SOURCES_DIST) \
+ $(src_client_linux_linux_client_unittest_SOURCES) \
+ $(am__src_client_linux_linux_client_unittest_shlib_SOURCES_DIST) \
+ $(am__src_client_linux_linux_dumper_unittest_helper_SOURCES_DIST) \
+ $(am__src_common_dumper_unittest_SOURCES_DIST) \
+ $(am__src_common_mac_macho_reader_unittest_SOURCES_DIST) \
+ $(am__src_common_test_assembler_unittest_SOURCES_DIST) \
+ $(am__src_processor_address_map_unittest_SOURCES_DIST) \
+ $(am__src_processor_basic_source_line_resolver_unittest_SOURCES_DIST) \
+ $(am__src_processor_cfi_frame_info_unittest_SOURCES_DIST) \
+ $(am__src_processor_contained_range_map_unittest_SOURCES_DIST) \
+ $(am__src_processor_disassembler_x86_unittest_SOURCES_DIST) \
+ $(am__src_processor_exploitability_unittest_SOURCES_DIST) \
+ $(am__src_processor_fast_source_line_resolver_unittest_SOURCES_DIST) \
+ $(am__src_processor_map_serializers_unittest_SOURCES_DIST) \
+ $(am__src_processor_microdump_processor_unittest_SOURCES_DIST) \
+ $(am__src_processor_microdump_stackwalk_SOURCES_DIST) \
+ $(am__src_processor_minidump_dump_SOURCES_DIST) \
+ $(am__src_processor_minidump_processor_unittest_SOURCES_DIST) \
+ $(am__src_processor_minidump_stackwalk_SOURCES_DIST) \
+ $(am__src_processor_minidump_unittest_SOURCES_DIST) \
+ $(am__src_processor_pathname_stripper_unittest_SOURCES_DIST) \
+ $(am__src_processor_postfix_evaluator_unittest_SOURCES_DIST) \
+ $(am__src_processor_proc_maps_linux_unittest_SOURCES_DIST) \
+ $(am__src_processor_range_map_shrink_down_unittest_SOURCES_DIST) \
+ $(am__src_processor_range_map_unittest_SOURCES_DIST) \
+ $(am__src_processor_stackwalker_address_list_unittest_SOURCES_DIST) \
+ $(am__src_processor_stackwalker_amd64_unittest_SOURCES_DIST) \
+ $(am__src_processor_stackwalker_arm64_unittest_SOURCES_DIST) \
+ $(am__src_processor_stackwalker_arm_unittest_SOURCES_DIST) \
+ $(am__src_processor_stackwalker_mips64_unittest_SOURCES_DIST) \
+ $(am__src_processor_stackwalker_mips_unittest_SOURCES_DIST) \
+ $(am__src_processor_stackwalker_selftest_SOURCES_DIST) \
+ $(am__src_processor_stackwalker_x86_unittest_SOURCES_DIST) \
+ $(am__src_processor_static_address_map_unittest_SOURCES_DIST) \
+ $(am__src_processor_static_contained_range_map_unittest_SOURCES_DIST) \
+ $(am__src_processor_static_map_unittest_SOURCES_DIST) \
+ $(am__src_processor_static_range_map_unittest_SOURCES_DIST) \
+ $(am__src_processor_synth_minidump_unittest_SOURCES_DIST) \
+ $(am__src_tools_linux_core2md_core2md_SOURCES_DIST) \
+ $(am__src_tools_linux_dump_syms_dump_syms_SOURCES_DIST) \
+ $(am__src_tools_linux_md2core_minidump_2_core_SOURCES_DIST) \
+ $(am__src_tools_linux_md2core_minidump_2_core_unittest_SOURCES_DIST) \
+ $(am__src_tools_linux_symupload_minidump_upload_SOURCES_DIST) \
+ $(am__src_tools_linux_symupload_sym_upload_SOURCES_DIST) \
+ $(am__src_tools_mac_dump_syms_dump_syms_mac_SOURCES_DIST)
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+DATA = $(dist_doc_DATA) $(pkgconfig_DATA)
+am__includecl_HEADERS_DIST = $(top_srcdir)/src/common/linux/*.h
+am__includeclc_HEADERS_DIST = \
+ $(top_srcdir)/src/client/linux/crash_generation/*.h
+am__includecldwc_HEADERS_DIST = \
+ $(top_srcdir)/src/client/linux/dump_writer_common/*.h
+am__includeclh_HEADERS_DIST = \
+ $(top_srcdir)/src/client/linux/handler/*.h
+am__includeclm_HEADERS_DIST = \
+ $(top_srcdir)/src/client/linux/minidump_writer/*.h
+am__includelss_HEADERS_DIST = $(top_srcdir)/src/third_party/lss/*.h
+HEADERS = $(includec_HEADERS) $(includecl_HEADERS) \
+ $(includeclc_HEADERS) $(includecldwc_HEADERS) \
+ $(includeclh_HEADERS) $(includeclm_HEADERS) \
+ $(includegbc_HEADERS) $(includelss_HEADERS) \
+ $(includep_HEADERS)
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates. Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+ BEGIN { nonempty = 0; } \
+ { items[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique. This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+ list='$(am__tagged_files)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+CSCOPE = cscope
+AM_RECURSIVE_TARGETS = cscope check recheck
+am__tty_colors_dummy = \
+ mgn= red= grn= lgn= blu= brg= std=; \
+ am__color_tests=no
+am__tty_colors = { \
+ $(am__tty_colors_dummy); \
+ if test "X$(AM_COLOR_TESTS)" = Xno; then \
+ am__color_tests=no; \
+ elif test "X$(AM_COLOR_TESTS)" = Xalways; then \
+ am__color_tests=yes; \
+ elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \
+ am__color_tests=yes; \
+ fi; \
+ if test $$am__color_tests = yes; then \
+ red=''; \
+ grn=''; \
+ lgn=''; \
+ blu=''; \
+ mgn=''; \
+ brg=''; \
+ std=''; \
+ fi; \
+}
+am__recheck_rx = ^[ ]*:recheck:[ ]*
+am__global_test_result_rx = ^[ ]*:global-test-result:[ ]*
+am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]*
+# A command that, given a newline-separated list of test names on the
+# standard input, print the name of the tests that are to be re-run
+# upon "make recheck".
+am__list_recheck_tests = $(AWK) '{ \
+ recheck = 1; \
+ while ((rc = (getline line < ($$0 ".trs"))) != 0) \
+ { \
+ if (rc < 0) \
+ { \
+ if ((getline line2 < ($$0 ".log")) < 0) \
+ recheck = 0; \
+ break; \
+ } \
+ else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \
+ { \
+ recheck = 0; \
+ break; \
+ } \
+ else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \
+ { \
+ break; \
+ } \
+ }; \
+ if (recheck) \
+ print $$0; \
+ close ($$0 ".trs"); \
+ close ($$0 ".log"); \
+}'
+# A command that, given a newline-separated list of test names on the
+# standard input, create the global log from their .trs and .log files.
+am__create_global_log = $(AWK) ' \
+function fatal(msg) \
+{ \
+ print "fatal: making $@: " msg | "cat >&2"; \
+ exit 1; \
+} \
+function rst_section(header) \
+{ \
+ print header; \
+ len = length(header); \
+ for (i = 1; i <= len; i = i + 1) \
+ printf "="; \
+ printf "\n\n"; \
+} \
+{ \
+ copy_in_global_log = 1; \
+ global_test_result = "RUN"; \
+ while ((rc = (getline line < ($$0 ".trs"))) != 0) \
+ { \
+ if (rc < 0) \
+ fatal("failed to read from " $$0 ".trs"); \
+ if (line ~ /$(am__global_test_result_rx)/) \
+ { \
+ sub("$(am__global_test_result_rx)", "", line); \
+ sub("[ ]*$$", "", line); \
+ global_test_result = line; \
+ } \
+ else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \
+ copy_in_global_log = 0; \
+ }; \
+ if (copy_in_global_log) \
+ { \
+ rst_section(global_test_result ": " $$0); \
+ while ((rc = (getline line < ($$0 ".log"))) != 0) \
+ { \
+ if (rc < 0) \
+ fatal("failed to read from " $$0 ".log"); \
+ print line; \
+ }; \
+ printf "\n"; \
+ }; \
+ close ($$0 ".trs"); \
+ close ($$0 ".log"); \
+}'
+# Restructured Text title.
+am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; }
+# Solaris 10 'make', and several other traditional 'make' implementations,
+# pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it
+# by disabling -e (using the XSI extension "set +e") if it's set.
+am__sh_e_setup = case $$- in *e*) set +e;; esac
+# Default flags passed to test drivers.
+am__common_driver_flags = \
+ --color-tests "$$am__color_tests" \
+ --enable-hard-errors "$$am__enable_hard_errors" \
+ --expect-failure "$$am__expect_failure"
+# To be inserted before the command running the test. Creates the
+# directory for the log if needed. Stores in $dir the directory
+# containing $f, in $tst the test, in $log the log. Executes the
+# developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and
+# passes TESTS_ENVIRONMENT. Set up options for the wrapper that
+# will run the test scripts (or their associated LOG_COMPILER, if
+# thy have one).
+am__check_pre = \
+$(am__sh_e_setup); \
+$(am__vpath_adj_setup) $(am__vpath_adj) \
+$(am__tty_colors); \
+srcdir=$(srcdir); export srcdir; \
+case "$@" in \
+ */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \
+ *) am__odir=.;; \
+esac; \
+test "x$$am__odir" = x"." || test -d "$$am__odir" \
+ || $(MKDIR_P) "$$am__odir" || exit $$?; \
+if test -f "./$$f"; then dir=./; \
+elif test -f "$$f"; then dir=; \
+else dir="$(srcdir)/"; fi; \
+tst=$$dir$$f; log='$@'; \
+if test -n '$(DISABLE_HARD_ERRORS)'; then \
+ am__enable_hard_errors=no; \
+else \
+ am__enable_hard_errors=yes; \
+fi; \
+case " $(XFAIL_TESTS) " in \
+ *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \
+ am__expect_failure=yes;; \
+ *) \
+ am__expect_failure=no;; \
+esac; \
+$(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT)
+# A shell command to get the names of the tests scripts with any registered
+# extension removed (i.e., equivalently, the names of the test logs, with
+# the '.log' extension removed). The result is saved in the shell variable
+# '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly,
+# we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)",
+# since that might cause problem with VPATH rewrites for suffix-less tests.
+# See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'.
+am__set_TESTS_bases = \
+ bases='$(TEST_LOGS)'; \
+ bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \
+ bases=`echo $$bases`
+RECHECK_LOGS = $(TEST_LOGS)
+TEST_SUITE_LOG = test-suite.log
+TEST_EXTENSIONS = @EXEEXT@ .test
+LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS)
+am__set_b = \
+ case '$@' in \
+ */*) \
+ case '$*' in \
+ */*) b='$*';; \
+ *) b=`echo '$@' | sed 's/\.log$$//'`; \
+ esac;; \
+ *) \
+ b='$*';; \
+ esac
+am__test_logs1 = $(TESTS:=.log)
+am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log)
+TEST_LOGS = $(am__test_logs2:.test.log=.log)
+TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/autotools/test-driver
+TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \
+ $(TEST_LOG_FLAGS)
+am__DIST_COMMON = $(srcdir)/Makefile.in \
+ $(srcdir)/breakpad-client.pc.in $(srcdir)/breakpad.pc.in \
+ $(top_srcdir)/autotools/ar-lib $(top_srcdir)/autotools/compile \
+ $(top_srcdir)/autotools/config.guess \
+ $(top_srcdir)/autotools/config.sub \
+ $(top_srcdir)/autotools/depcomp \
+ $(top_srcdir)/autotools/install-sh \
+ $(top_srcdir)/autotools/missing \
+ $(top_srcdir)/autotools/test-driver \
+ $(top_srcdir)/src/config.h.in AUTHORS ChangeLog INSTALL NEWS \
+ autotools/ar-lib autotools/compile autotools/config.guess \
+ autotools/config.sub autotools/depcomp autotools/install-sh \
+ autotools/ltmain.sh autotools/missing
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+distdir = $(PACKAGE)-$(VERSION)
+top_distdir = $(distdir)
+am__remove_distdir = \
+ if test -d "$(distdir)"; then \
+ find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \
+ && rm -rf "$(distdir)" \
+ || { sleep 5 && rm -rf "$(distdir)"; }; \
+ else :; fi
+am__post_remove_distdir = $(am__remove_distdir)
+DIST_ARCHIVES = $(distdir).tar.gz
+GZIP_ENV = --best
+DIST_TARGETS = dist-gzip
+distuninstallcheck_listfiles = find . -type f -print
+am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \
+ | sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$'
+distcleancheck_listfiles = find . -type f -print
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCAS = @CCAS@
+CCASDEPMODE = @CCASDEPMODE@
+CCASFLAGS = @CCASFLAGS@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+GMOCK_CFLAGS = @GMOCK_CFLAGS@
+GMOCK_CONFIG = @GMOCK_CONFIG@
+GMOCK_LIBS = @GMOCK_LIBS@
+GREP = @GREP@
+GTEST_CFLAGS = @GTEST_CFLAGS@
+GTEST_CONFIG = @GTEST_CONFIG@
+GTEST_LIBS = @GTEST_LIBS@
+HAVE_CXX11 = @HAVE_CXX11@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PTHREAD_CC = @PTHREAD_CC@
+PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
+PTHREAD_LIBS = @PTHREAD_LIBS@
+RANLIB = @RANLIB@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+ax_pthread_config = @ax_pthread_config@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = $(prefix)/share/doc/$(PACKAGE)-$(VERSION)
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+
+# This allows #includes to be relative to src/
+AM_CPPFLAGS = -I$(top_srcdir)/src
+AM_CFLAGS = $(am__append_3)
+AM_CXXFLAGS = $(am__append_1) $(am__append_2) $(am__append_4)
+
+# Specify include paths for ac macros
+ACLOCAL_AMFLAGS = -I m4
+
+# License file is called LICENSE not COPYING
+AUTOMAKE_OPTIONS = foreign
+dist_doc_DATA = \
+ AUTHORS \
+ ChangeLog \
+ INSTALL \
+ LICENSE \
+ NEWS \
+ README.md
+
+@LINUX_HOST_TRUE@includeclhdir = $(includedir)/$(PACKAGE)/client/linux/handler
+@LINUX_HOST_TRUE@includeclh_HEADERS = $(top_srcdir)/src/client/linux/handler/*.h
+@LINUX_HOST_TRUE@includecldwcdir = $(includedir)/$(PACKAGE)/client/linux/dump_writer_common
+@LINUX_HOST_TRUE@includecldwc_HEADERS = $(top_srcdir)/src/client/linux/dump_writer_common/*.h
+@LINUX_HOST_TRUE@includeclmdir = $(includedir)/$(PACKAGE)/client/linux/minidump_writer
+@LINUX_HOST_TRUE@includeclm_HEADERS = $(top_srcdir)/src/client/linux/minidump_writer/*.h
+@LINUX_HOST_TRUE@includeclcdir = $(includedir)/$(PACKAGE)/client/linux/crash_generation
+@LINUX_HOST_TRUE@includeclc_HEADERS = $(top_srcdir)/src/client/linux/crash_generation/*.h
+@LINUX_HOST_TRUE@includelssdir = $(includedir)/$(PACKAGE)/third_party/lss
+@LINUX_HOST_TRUE@includelss_HEADERS = $(top_srcdir)/src/third_party/lss/*.h
+@LINUX_HOST_TRUE@includecldir = $(includedir)/$(PACKAGE)/common/linux
+@LINUX_HOST_TRUE@includecl_HEADERS = $(top_srcdir)/src/common/linux/*.h
+includegbcdir = $(includedir)/$(PACKAGE)/google_breakpad/common
+includegbc_HEADERS = $(top_srcdir)/src/google_breakpad/common/*.h
+includecdir = $(includedir)/$(PACKAGE)/common
+includec_HEADERS = $(top_srcdir)/src/common/*.h
+includepdir = $(includedir)/$(PACKAGE)/processor
+includep_HEADERS = $(top_srcdir)/src/processor/*.h
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = $(am__append_6) $(am__append_9)
+@SYSTEM_TEST_LIBS_FALSE@TEST_CFLAGS = \
+@SYSTEM_TEST_LIBS_FALSE@ -I$(top_srcdir)/src/testing/include \
+@SYSTEM_TEST_LIBS_FALSE@ -I$(top_srcdir)/src/testing/gtest/include \
+@SYSTEM_TEST_LIBS_FALSE@ -I$(top_srcdir)/src/testing/gtest \
+@SYSTEM_TEST_LIBS_FALSE@ -I$(top_srcdir)/src/testing
+
+@SYSTEM_TEST_LIBS_TRUE@TEST_CFLAGS = $(GTEST_CFLAGS) $(GMOCK_CFLAGS)
+@SYSTEM_TEST_LIBS_FALSE@TEST_LIBS = src/testing/libtesting.a
+@SYSTEM_TEST_LIBS_TRUE@TEST_LIBS = $(GTEST_LIBS) -lgtest_main $(GMOCK_LIBS)
+@SYSTEM_TEST_LIBS_FALSE@TEST_DEPS = $(TEST_LIBS)
+@SYSTEM_TEST_LIBS_TRUE@TEST_DEPS =
+check_LIBRARIES = src/testing/libtesting.a
+noinst_LIBRARIES = $(am__append_7)
+lib_LIBRARIES = $(am__append_5) $(am__append_8)
+CLEANFILES = $(am__append_13)
+@SYSTEM_TEST_LIBS_FALSE@src_testing_libtesting_a_SOURCES = \
+@SYSTEM_TEST_LIBS_FALSE@ src/breakpad_googletest_includes.h \
+@SYSTEM_TEST_LIBS_FALSE@ src/testing/gtest/src/gtest-all.cc \
+@SYSTEM_TEST_LIBS_FALSE@ src/testing/gtest/src/gtest_main.cc \
+@SYSTEM_TEST_LIBS_FALSE@ src/testing/src/gmock-all.cc
+
+@SYSTEM_TEST_LIBS_FALSE@src_testing_libtesting_a_CPPFLAGS = \
+@SYSTEM_TEST_LIBS_FALSE@ $(AM_CPPFLAGS) $(TEST_CFLAGS)
+
+@LINUX_HOST_TRUE@src_client_linux_libbreakpad_client_a_SOURCES = src/client/linux/crash_generation/crash_generation_client.cc \
+@LINUX_HOST_TRUE@ src/client/linux/crash_generation/crash_generation_server.cc \
+@LINUX_HOST_TRUE@ src/client/linux/dump_writer_common/thread_info.cc \
+@LINUX_HOST_TRUE@ src/client/linux/dump_writer_common/ucontext_reader.cc \
+@LINUX_HOST_TRUE@ src/client/linux/handler/exception_handler.cc \
+@LINUX_HOST_TRUE@ src/client/linux/handler/exception_handler.h \
+@LINUX_HOST_TRUE@ src/client/linux/handler/minidump_descriptor.cc \
+@LINUX_HOST_TRUE@ src/client/linux/handler/minidump_descriptor.h \
+@LINUX_HOST_TRUE@ src/client/linux/log/log.cc \
+@LINUX_HOST_TRUE@ src/client/linux/log/log.h \
+@LINUX_HOST_TRUE@ src/client/linux/microdump_writer/microdump_writer.cc \
+@LINUX_HOST_TRUE@ src/client/linux/microdump_writer/microdump_writer.h \
+@LINUX_HOST_TRUE@ src/client/linux/minidump_writer/linux_core_dumper.cc \
+@LINUX_HOST_TRUE@ src/client/linux/minidump_writer/linux_dumper.cc \
+@LINUX_HOST_TRUE@ src/client/linux/minidump_writer/linux_ptrace_dumper.cc \
+@LINUX_HOST_TRUE@ src/client/linux/minidump_writer/minidump_writer.cc \
+@LINUX_HOST_TRUE@ src/client/minidump_file_writer-inl.h \
+@LINUX_HOST_TRUE@ src/client/minidump_file_writer.cc \
+@LINUX_HOST_TRUE@ src/client/minidump_file_writer.h \
+@LINUX_HOST_TRUE@ src/common/convert_UTF.c \
+@LINUX_HOST_TRUE@ src/common/convert_UTF.h src/common/md5.cc \
+@LINUX_HOST_TRUE@ src/common/md5.h \
+@LINUX_HOST_TRUE@ src/common/string_conversion.cc \
+@LINUX_HOST_TRUE@ src/common/string_conversion.h \
+@LINUX_HOST_TRUE@ src/common/linux/elf_core_dump.cc \
+@LINUX_HOST_TRUE@ src/common/linux/elfutils.cc \
+@LINUX_HOST_TRUE@ src/common/linux/elfutils.h \
+@LINUX_HOST_TRUE@ src/common/linux/file_id.cc \
+@LINUX_HOST_TRUE@ src/common/linux/file_id.h \
+@LINUX_HOST_TRUE@ src/common/linux/guid_creator.cc \
+@LINUX_HOST_TRUE@ src/common/linux/guid_creator.h \
+@LINUX_HOST_TRUE@ src/common/linux/linux_libc_support.cc \
+@LINUX_HOST_TRUE@ src/common/linux/memory_mapped_file.cc \
+@LINUX_HOST_TRUE@ src/common/linux/safe_readlink.cc \
+@LINUX_HOST_TRUE@ $(am__append_10)
+@DISABLE_PROCESSOR_FALSE@src_libbreakpad_a_SOURCES = \
+@DISABLE_PROCESSOR_FALSE@ src/google_breakpad/common/breakpad_types.h \
+@DISABLE_PROCESSOR_FALSE@ src/google_breakpad/common/minidump_format.h \
+@DISABLE_PROCESSOR_FALSE@ src/google_breakpad/common/minidump_size.h \
+@DISABLE_PROCESSOR_FALSE@ src/google_breakpad/processor/basic_source_line_resolver.h \
+@DISABLE_PROCESSOR_FALSE@ src/google_breakpad/processor/call_stack.h \
+@DISABLE_PROCESSOR_FALSE@ src/google_breakpad/processor/code_module.h \
+@DISABLE_PROCESSOR_FALSE@ src/google_breakpad/processor/code_modules.h \
+@DISABLE_PROCESSOR_FALSE@ src/google_breakpad/processor/dump_context.h \
+@DISABLE_PROCESSOR_FALSE@ src/google_breakpad/processor/dump_object.h \
+@DISABLE_PROCESSOR_FALSE@ src/google_breakpad/processor/exploitability.h \
+@DISABLE_PROCESSOR_FALSE@ src/google_breakpad/processor/fast_source_line_resolver.h \
+@DISABLE_PROCESSOR_FALSE@ src/google_breakpad/processor/memory_region.h \
+@DISABLE_PROCESSOR_FALSE@ src/google_breakpad/processor/microdump.h \
+@DISABLE_PROCESSOR_FALSE@ src/google_breakpad/processor/microdump_processor.h \
+@DISABLE_PROCESSOR_FALSE@ src/google_breakpad/processor/minidump.h \
+@DISABLE_PROCESSOR_FALSE@ src/google_breakpad/processor/minidump_processor.h \
+@DISABLE_PROCESSOR_FALSE@ src/google_breakpad/processor/process_result.h \
+@DISABLE_PROCESSOR_FALSE@ src/google_breakpad/processor/process_state.h \
+@DISABLE_PROCESSOR_FALSE@ src/google_breakpad/processor/proc_maps_linux.h \
+@DISABLE_PROCESSOR_FALSE@ src/google_breakpad/processor/source_line_resolver_base.h \
+@DISABLE_PROCESSOR_FALSE@ src/google_breakpad/processor/source_line_resolver_interface.h \
+@DISABLE_PROCESSOR_FALSE@ src/google_breakpad/processor/stack_frame.h \
+@DISABLE_PROCESSOR_FALSE@ src/google_breakpad/processor/stack_frame_cpu.h \
+@DISABLE_PROCESSOR_FALSE@ src/google_breakpad/processor/stack_frame_symbolizer.h \
+@DISABLE_PROCESSOR_FALSE@ src/google_breakpad/processor/stackwalker.h \
+@DISABLE_PROCESSOR_FALSE@ src/google_breakpad/processor/symbol_supplier.h \
+@DISABLE_PROCESSOR_FALSE@ src/google_breakpad/processor/system_info.h \
+@DISABLE_PROCESSOR_FALSE@ src/processor/address_map-inl.h \
+@DISABLE_PROCESSOR_FALSE@ src/processor/address_map.h \
+@DISABLE_PROCESSOR_FALSE@ src/processor/basic_code_module.h \
+@DISABLE_PROCESSOR_FALSE@ src/processor/basic_code_modules.cc \
+@DISABLE_PROCESSOR_FALSE@ src/processor/basic_code_modules.h \
+@DISABLE_PROCESSOR_FALSE@ src/processor/basic_source_line_resolver_types.h \
+@DISABLE_PROCESSOR_FALSE@ src/processor/basic_source_line_resolver.cc \
+@DISABLE_PROCESSOR_FALSE@ src/processor/call_stack.cc \
+@DISABLE_PROCESSOR_FALSE@ src/processor/cfi_frame_info.cc \
+@DISABLE_PROCESSOR_FALSE@ src/processor/cfi_frame_info.h \
+@DISABLE_PROCESSOR_FALSE@ src/processor/contained_range_map-inl.h \
+@DISABLE_PROCESSOR_FALSE@ src/processor/contained_range_map.h \
+@DISABLE_PROCESSOR_FALSE@ src/processor/disassembler_x86.h \
+@DISABLE_PROCESSOR_FALSE@ src/processor/disassembler_x86.cc \
+@DISABLE_PROCESSOR_FALSE@ src/processor/dump_context.cc \
+@DISABLE_PROCESSOR_FALSE@ src/processor/dump_object.cc \
+@DISABLE_PROCESSOR_FALSE@ src/processor/exploitability.cc \
+@DISABLE_PROCESSOR_FALSE@ src/processor/exploitability_linux.h \
+@DISABLE_PROCESSOR_FALSE@ src/processor/exploitability_linux.cc \
+@DISABLE_PROCESSOR_FALSE@ src/processor/exploitability_win.h \
+@DISABLE_PROCESSOR_FALSE@ src/processor/exploitability_win.cc \
+@DISABLE_PROCESSOR_FALSE@ src/processor/fast_source_line_resolver_types.h \
+@DISABLE_PROCESSOR_FALSE@ src/processor/fast_source_line_resolver.cc \
+@DISABLE_PROCESSOR_FALSE@ src/processor/linked_ptr.h \
+@DISABLE_PROCESSOR_FALSE@ src/processor/logging.h \
+@DISABLE_PROCESSOR_FALSE@ src/processor/logging.cc \
+@DISABLE_PROCESSOR_FALSE@ src/processor/map_serializers-inl.h \
+@DISABLE_PROCESSOR_FALSE@ src/processor/map_serializers.h \
+@DISABLE_PROCESSOR_FALSE@ src/processor/microdump.cc \
+@DISABLE_PROCESSOR_FALSE@ src/processor/microdump_processor.cc \
+@DISABLE_PROCESSOR_FALSE@ src/processor/minidump.cc \
+@DISABLE_PROCESSOR_FALSE@ src/processor/minidump_processor.cc \
+@DISABLE_PROCESSOR_FALSE@ src/processor/module_comparer.cc \
+@DISABLE_PROCESSOR_FALSE@ src/processor/module_comparer.h \
+@DISABLE_PROCESSOR_FALSE@ src/processor/module_factory.h \
+@DISABLE_PROCESSOR_FALSE@ src/processor/module_serializer.cc \
+@DISABLE_PROCESSOR_FALSE@ src/processor/module_serializer.h \
+@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.cc \
+@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.h \
+@DISABLE_PROCESSOR_FALSE@ src/processor/postfix_evaluator-inl.h \
+@DISABLE_PROCESSOR_FALSE@ src/processor/postfix_evaluator.h \
+@DISABLE_PROCESSOR_FALSE@ src/processor/process_state.cc \
+@DISABLE_PROCESSOR_FALSE@ src/processor/proc_maps_linux.cc \
+@DISABLE_PROCESSOR_FALSE@ src/processor/range_map-inl.h \
+@DISABLE_PROCESSOR_FALSE@ src/processor/range_map.h \
+@DISABLE_PROCESSOR_FALSE@ src/processor/simple_serializer-inl.h \
+@DISABLE_PROCESSOR_FALSE@ src/processor/simple_serializer.h \
+@DISABLE_PROCESSOR_FALSE@ src/processor/simple_symbol_supplier.cc \
+@DISABLE_PROCESSOR_FALSE@ src/processor/simple_symbol_supplier.h \
+@DISABLE_PROCESSOR_FALSE@ src/processor/windows_frame_info.h \
+@DISABLE_PROCESSOR_FALSE@ src/processor/source_line_resolver_base_types.h \
+@DISABLE_PROCESSOR_FALSE@ src/processor/source_line_resolver_base.cc \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stack_frame_cpu.cc \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stack_frame_symbolizer.cc \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker.cc \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_amd64.cc \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_amd64.h \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm.cc \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm.h \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm64.cc \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm64.h \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_address_list.cc \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_address_list.h \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_mips.cc \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_mips.h \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_ppc.cc \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_ppc.h \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_ppc64.cc \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_ppc64.h \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_sparc.cc \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_sparc.h \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_x86.cc \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_x86.h \
+@DISABLE_PROCESSOR_FALSE@ src/processor/static_address_map-inl.h \
+@DISABLE_PROCESSOR_FALSE@ src/processor/static_address_map.h \
+@DISABLE_PROCESSOR_FALSE@ src/processor/static_contained_range_map-inl.h \
+@DISABLE_PROCESSOR_FALSE@ src/processor/static_contained_range_map.h \
+@DISABLE_PROCESSOR_FALSE@ src/processor/static_map_iterator-inl.h \
+@DISABLE_PROCESSOR_FALSE@ src/processor/static_map_iterator.h \
+@DISABLE_PROCESSOR_FALSE@ src/processor/static_map-inl.h \
+@DISABLE_PROCESSOR_FALSE@ src/processor/static_map.h \
+@DISABLE_PROCESSOR_FALSE@ src/processor/static_range_map-inl.h \
+@DISABLE_PROCESSOR_FALSE@ src/processor/static_range_map.h \
+@DISABLE_PROCESSOR_FALSE@ src/processor/symbolic_constants_win.cc \
+@DISABLE_PROCESSOR_FALSE@ src/processor/symbolic_constants_win.h \
+@DISABLE_PROCESSOR_FALSE@ src/processor/tokenize.cc \
+@DISABLE_PROCESSOR_FALSE@ src/processor/tokenize.h
+
+@DISABLE_PROCESSOR_FALSE@src_third_party_libdisasm_libdisasm_a_SOURCES = \
+@DISABLE_PROCESSOR_FALSE@ src/third_party/libdisasm/ia32_implicit.c \
+@DISABLE_PROCESSOR_FALSE@ src/third_party/libdisasm/ia32_implicit.h \
+@DISABLE_PROCESSOR_FALSE@ src/third_party/libdisasm/ia32_insn.c \
+@DISABLE_PROCESSOR_FALSE@ src/third_party/libdisasm/ia32_insn.h \
+@DISABLE_PROCESSOR_FALSE@ src/third_party/libdisasm/ia32_invariant.c \
+@DISABLE_PROCESSOR_FALSE@ src/third_party/libdisasm/ia32_invariant.h \
+@DISABLE_PROCESSOR_FALSE@ src/third_party/libdisasm/ia32_modrm.c \
+@DISABLE_PROCESSOR_FALSE@ src/third_party/libdisasm/ia32_modrm.h \
+@DISABLE_PROCESSOR_FALSE@ src/third_party/libdisasm/ia32_opcode_tables.c \
+@DISABLE_PROCESSOR_FALSE@ src/third_party/libdisasm/ia32_opcode_tables.h \
+@DISABLE_PROCESSOR_FALSE@ src/third_party/libdisasm/ia32_operand.c \
+@DISABLE_PROCESSOR_FALSE@ src/third_party/libdisasm/ia32_operand.h \
+@DISABLE_PROCESSOR_FALSE@ src/third_party/libdisasm/ia32_reg.c \
+@DISABLE_PROCESSOR_FALSE@ src/third_party/libdisasm/ia32_reg.h \
+@DISABLE_PROCESSOR_FALSE@ src/third_party/libdisasm/ia32_settings.c \
+@DISABLE_PROCESSOR_FALSE@ src/third_party/libdisasm/ia32_settings.h \
+@DISABLE_PROCESSOR_FALSE@ src/third_party/libdisasm/libdis.h \
+@DISABLE_PROCESSOR_FALSE@ src/third_party/libdisasm/qword.h \
+@DISABLE_PROCESSOR_FALSE@ src/third_party/libdisasm/x86_disasm.c \
+@DISABLE_PROCESSOR_FALSE@ src/third_party/libdisasm/x86_format.c \
+@DISABLE_PROCESSOR_FALSE@ src/third_party/libdisasm/x86_imm.c \
+@DISABLE_PROCESSOR_FALSE@ src/third_party/libdisasm/x86_imm.h \
+@DISABLE_PROCESSOR_FALSE@ src/third_party/libdisasm/x86_insn.c \
+@DISABLE_PROCESSOR_FALSE@ src/third_party/libdisasm/x86_misc.c \
+@DISABLE_PROCESSOR_FALSE@ src/third_party/libdisasm/x86_operand_list.c \
+@DISABLE_PROCESSOR_FALSE@ src/third_party/libdisasm/x86_operand_list.h
+
+@DISABLE_PROCESSOR_FALSE@check_SCRIPTS = \
+@DISABLE_PROCESSOR_FALSE@ src/processor/microdump_stackwalk_test \
+@DISABLE_PROCESSOR_FALSE@ src/processor/microdump_stackwalk_machine_readable_test \
+@DISABLE_PROCESSOR_FALSE@ src/processor/minidump_dump_test \
+@DISABLE_PROCESSOR_FALSE@ src/processor/minidump_stackwalk_test \
+@DISABLE_PROCESSOR_FALSE@ src/processor/minidump_stackwalk_machine_readable_test
+
+TESTS = $(check_PROGRAMS) $(check_SCRIPTS)
+# The default Autotools test driver script.
+@ANDROID_HOST_FALSE@LOG_DRIVER = $(top_srcdir)/autotools/test-driver
+
+# Since Autotools 1.2, tests are run through a special "test driver" script.
+# Unfortunately, it's not possible anymore to specify an alternative shell to
+# run them on connected devices, so use a slightly modified version of the
+# driver for Android.
+@ANDROID_HOST_TRUE@LOG_DRIVER = $(top_srcdir)/android/test-driver
+@LINUX_HOST_TRUE@src_client_linux_linux_dumper_unittest_helper_SOURCES = \
+@LINUX_HOST_TRUE@ src/client/linux/minidump_writer/linux_dumper_unittest_helper.cc
+
+@LINUX_HOST_TRUE@src_client_linux_linux_dumper_unittest_helper_LDFLAGS = $(PTHREAD_CFLAGS)
+@LINUX_HOST_TRUE@src_client_linux_linux_dumper_unittest_helper_CC = $(PTHREAD_CC)
+@ANDROID_HOST_FALSE@@LINUX_HOST_TRUE@src_client_linux_linux_dumper_unittest_helper_CXXFLAGS = $(PTHREAD_CFLAGS)
+# On Android PTHREAD_CFLAGS is empty, and adding src/common/android/include
+# to the include path is necessary to build this program.
+@ANDROID_HOST_TRUE@@LINUX_HOST_TRUE@src_client_linux_linux_dumper_unittest_helper_CXXFLAGS = $(AM_CXXFLAGS)
+@LINUX_HOST_TRUE@src_client_linux_linux_client_unittest_shlib_SOURCES = \
+@LINUX_HOST_TRUE@ $(src_testing_libtesting_a_SOURCES) \
+@LINUX_HOST_TRUE@ src/client/linux/handler/exception_handler_unittest.cc \
+@LINUX_HOST_TRUE@ src/client/linux/minidump_writer/directory_reader_unittest.cc \
+@LINUX_HOST_TRUE@ src/client/linux/minidump_writer/cpu_set_unittest.cc \
+@LINUX_HOST_TRUE@ src/client/linux/minidump_writer/line_reader_unittest.cc \
+@LINUX_HOST_TRUE@ src/client/linux/minidump_writer/linux_core_dumper.cc \
+@LINUX_HOST_TRUE@ src/client/linux/minidump_writer/linux_core_dumper_unittest.cc \
+@LINUX_HOST_TRUE@ src/client/linux/minidump_writer/linux_ptrace_dumper_unittest.cc \
+@LINUX_HOST_TRUE@ src/client/linux/minidump_writer/minidump_writer_unittest.cc \
+@LINUX_HOST_TRUE@ src/client/linux/minidump_writer/minidump_writer_unittest_utils.cc \
+@LINUX_HOST_TRUE@ src/client/linux/minidump_writer/proc_cpuinfo_reader_unittest.cc \
+@LINUX_HOST_TRUE@ src/common/linux/elf_core_dump.cc \
+@LINUX_HOST_TRUE@ src/common/linux/linux_libc_support_unittest.cc \
+@LINUX_HOST_TRUE@ src/common/linux/tests/auto_testfile.h \
+@LINUX_HOST_TRUE@ src/common/linux/tests/crash_generator.cc \
+@LINUX_HOST_TRUE@ src/common/memory_allocator_unittest.cc \
+@LINUX_HOST_TRUE@ src/common/tests/auto_tempdir.h \
+@LINUX_HOST_TRUE@ src/common/tests/file_utils.cc \
+@LINUX_HOST_TRUE@ src/common/tests/file_utils.h \
+@LINUX_HOST_TRUE@ src/processor/basic_code_modules.cc \
+@LINUX_HOST_TRUE@ src/processor/dump_context.cc \
+@LINUX_HOST_TRUE@ src/processor/dump_object.cc \
+@LINUX_HOST_TRUE@ src/processor/logging.cc \
+@LINUX_HOST_TRUE@ src/processor/minidump.cc \
+@LINUX_HOST_TRUE@ src/processor/pathname_stripper.cc \
+@LINUX_HOST_TRUE@ src/processor/proc_maps_linux.cc \
+@LINUX_HOST_TRUE@ $(am__append_21) \
+@LINUX_HOST_TRUE@ src/client/linux/microdump_writer/microdump_writer_unittest.cc \
+@LINUX_HOST_TRUE@ $(am__append_22)
+@LINUX_HOST_TRUE@src_client_linux_linux_client_unittest_shlib_CPPFLAGS = \
+@LINUX_HOST_TRUE@ $(AM_CPPFLAGS) $(TEST_CFLAGS)
+
+@LINUX_HOST_TRUE@src_client_linux_linux_client_unittest_shlib_LDFLAGS = \
+@LINUX_HOST_TRUE@ -shared -Wl,-h,linux_client_unittest_shlib \
+@LINUX_HOST_TRUE@ $(am__append_23)
+@LINUX_HOST_TRUE@src_client_linux_linux_client_unittest_shlib_LDADD = \
+@LINUX_HOST_TRUE@ src/client/linux/crash_generation/crash_generation_client.o \
+@LINUX_HOST_TRUE@ src/client/linux/dump_writer_common/thread_info.o \
+@LINUX_HOST_TRUE@ src/client/linux/dump_writer_common/ucontext_reader.o \
+@LINUX_HOST_TRUE@ src/client/linux/handler/exception_handler.o \
+@LINUX_HOST_TRUE@ src/client/linux/handler/minidump_descriptor.o \
+@LINUX_HOST_TRUE@ src/client/linux/log/log.o \
+@LINUX_HOST_TRUE@ src/client/linux/microdump_writer/microdump_writer.o \
+@LINUX_HOST_TRUE@ src/client/linux/minidump_writer/linux_dumper.o \
+@LINUX_HOST_TRUE@ src/client/linux/minidump_writer/linux_ptrace_dumper.o \
+@LINUX_HOST_TRUE@ src/client/linux/minidump_writer/minidump_writer.o \
+@LINUX_HOST_TRUE@ src/client/minidump_file_writer.o \
+@LINUX_HOST_TRUE@ src/common/convert_UTF.o \
+@LINUX_HOST_TRUE@ src/common/md5.o \
+@LINUX_HOST_TRUE@ src/common/linux/elfutils.o \
+@LINUX_HOST_TRUE@ src/common/linux/file_id.o \
+@LINUX_HOST_TRUE@ src/common/linux/guid_creator.o \
+@LINUX_HOST_TRUE@ src/common/linux/linux_libc_support.o \
+@LINUX_HOST_TRUE@ src/common/linux/memory_mapped_file.o \
+@LINUX_HOST_TRUE@ src/common/linux/safe_readlink.o \
+@LINUX_HOST_TRUE@ src/common/string_conversion.o \
+@LINUX_HOST_TRUE@ $(TEST_LIBS) \
+@LINUX_HOST_TRUE@ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
+
+@LINUX_HOST_TRUE@src_client_linux_linux_client_unittest_shlib_DEPENDENCIES = \
+@LINUX_HOST_TRUE@ src/client/linux/linux_dumper_unittest_helper \
+@LINUX_HOST_TRUE@ src/client/linux/libbreakpad_client.a \
+@LINUX_HOST_TRUE@ $(TEST_DEPS) \
+@LINUX_HOST_TRUE@ src/libbreakpad.a
+
+@LINUX_HOST_TRUE@src_client_linux_linux_client_unittest_SOURCES =
+# The extra-long build id is for a test in minidump_writer_unittest.cc.
+@LINUX_HOST_TRUE@src_client_linux_linux_client_unittest_LDFLAGS = \
+@LINUX_HOST_TRUE@ -Wl,-rpath,'$$ORIGIN' \
+@LINUX_HOST_TRUE@ -Wl,--build-id=0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f \
+@LINUX_HOST_TRUE@ $(am__append_24)
+@LINUX_HOST_TRUE@src_client_linux_linux_client_unittest_LDADD = \
+@LINUX_HOST_TRUE@ src/client/linux/linux_client_unittest_shlib \
+@LINUX_HOST_TRUE@ $(TEST_LIBS)
+
+@LINUX_HOST_TRUE@src_client_linux_linux_client_unittest_DEPENDENCIES = \
+@LINUX_HOST_TRUE@ src/client/linux/linux_client_unittest_shlib
+
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@src_tools_linux_core2md_core2md_SOURCES = \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/tools/linux/core2md/core2md.cc
+
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@src_tools_linux_core2md_core2md_LDADD = \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/client/linux/libbreakpad_client.a
+
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@src_tools_linux_dump_syms_dump_syms_SOURCES = \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf_cfi_to_module.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf_cu_to_module.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf_line_to_module.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/language.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/module.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/stabs_reader.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/stabs_to_module.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/bytereader.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/dwarf2diehandler.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/dwarf2reader.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/elf_reader.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/crc32.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/dump_symbols.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/dump_symbols.h \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/elf_symbols_to_module.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/elf_symbols_to_module.h \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/elfutils.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/file_id.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/linux_libc_support.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/memory_mapped_file.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/safe_readlink.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/tools/linux/dump_syms/dump_syms.cc
+
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@src_tools_linux_md2core_minidump_2_core_SOURCES = \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/memory_mapped_file.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/tools/linux/md2core/minidump-2-core.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/tools/linux/md2core/minidump_memory_range.h
+
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@src_tools_linux_symupload_minidump_upload_SOURCES = \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/http_upload.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/tools/linux/symupload/minidump_upload.cc
+
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@src_tools_linux_symupload_minidump_upload_LDADD = -ldl
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@src_tools_linux_symupload_sym_upload_SOURCES = \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/http_upload.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/http_upload.h \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/symbol_upload.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/symbol_upload.h \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/tools/linux/symupload/sym_upload.cc
+
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@src_tools_linux_symupload_sym_upload_LDADD = -ldl
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@src_tools_mac_dump_syms_dump_syms_mac_SOURCES = \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf_cfi_to_module.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf_cu_to_module.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf_line_to_module.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/language.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/md5.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/module.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/stabs_reader.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/stabs_to_module.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/bytereader.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/dwarf2diehandler.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/dwarf2reader.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/elf_reader.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/mac/arch_utilities.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/mac/dump_syms.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/mac/dump_syms.h \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/mac/file_id.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/mac/file_id.h \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/mac/macho_id.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/mac/macho_id.h \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/mac/macho_reader.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/mac/macho_reader.h \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/mac/macho_utilities.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/mac/macho_utilities.h \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/mac/macho_walker.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/mac/macho_walker.h \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/tools/mac/dump_syms/dump_syms_tool.cc
+
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS = \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ -I$(top_srcdir)/src/third_party/mac_headers \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ -DHAVE_MACH_O_NLIST_H
+
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@src_common_dumper_unittest_SOURCES = \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/byte_cursor_unittest.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf_cfi_to_module.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf_cfi_to_module_unittest.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf_cu_to_module.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf_cu_to_module_unittest.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf_line_to_module.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf_line_to_module_unittest.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/language.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/memory_range_unittest.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/module.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/module_unittest.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/stabs_reader.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/stabs_reader_unittest.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/stabs_to_module.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/stabs_to_module_unittest.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/test_assembler.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/bytereader.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/bytereader.h \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/bytereader-inl.h \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/bytereader_unittest.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/cfi_assembler.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/cfi_assembler.h \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/dwarf2diehandler.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/dwarf2diehandler_unittest.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/dwarf2reader.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/dwarf2reader.h \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/elf_reader.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/elf_reader.h \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/dwarf2reader_cfi_unittest.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/dwarf2reader_die_unittest.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/dwarf2reader_test_common.h \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/crc32.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/dump_symbols.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/dump_symbols_unittest.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/elf_core_dump.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/elf_core_dump_unittest.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/elf_symbols_to_module.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/elf_symbols_to_module_unittest.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/elfutils.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/file_id.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/file_id_unittest.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/linux_libc_support.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/memory_mapped_file.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/memory_mapped_file_unittest.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/safe_readlink.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/safe_readlink_unittest.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/synth_elf.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/synth_elf_unittest.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/tests/crash_generator.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/tests/crash_generator.h \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/testdata/func-line-pairing.h \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/tests/file_utils.cc
+
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@src_common_dumper_unittest_CPPFLAGS = \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ $(AM_CPPFLAGS) $(TEST_CFLAGS) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ $(PTHREAD_CFLAGS)
+
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@src_common_dumper_unittest_LDADD = \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ $(TEST_LIBS) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
+
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@src_common_mac_macho_reader_unittest_SOURCES = \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf_cfi_to_module.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf_cu_to_module.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf_line_to_module.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/language.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/md5.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/module.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/stabs_reader.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/stabs_to_module.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/test_assembler.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/bytereader.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/cfi_assembler.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/dwarf2diehandler.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/dwarf2reader.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/elf_reader.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/mac/arch_utilities.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/mac/file_id.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/mac/macho_id.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/mac/macho_reader.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/mac/macho_reader_unittest.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/mac/macho_utilities.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/mac/macho_walker.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/tests/file_utils.cc
+
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@src_common_mac_macho_reader_unittest_CPPFLAGS = \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ $(AM_CPPFLAGS) $(TEST_CFLAGS) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ -I$(top_srcdir)/src/third_party/mac_headers \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ -DHAVE_MACH_O_NLIST_H \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ $(PTHREAD_CFLAGS)
+
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@src_common_mac_macho_reader_unittest_LDADD = \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ $(TEST_LIBS) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
+
+@LINUX_HOST_TRUE@src_tools_linux_md2core_minidump_2_core_unittest_SOURCES = \
+@LINUX_HOST_TRUE@ src/tools/linux/md2core/minidump_memory_range_unittest.cc
+
+@LINUX_HOST_TRUE@src_tools_linux_md2core_minidump_2_core_unittest_CPPFLAGS = \
+@LINUX_HOST_TRUE@ $(AM_CPPFLAGS) $(TEST_CFLAGS)
+
+@LINUX_HOST_TRUE@src_tools_linux_md2core_minidump_2_core_unittest_LDADD = \
+@LINUX_HOST_TRUE@ $(TEST_LIBS) \
+@LINUX_HOST_TRUE@ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
+
+@DISABLE_PROCESSOR_FALSE@src_processor_address_map_unittest_SOURCES = \
+@DISABLE_PROCESSOR_FALSE@ src/processor/address_map_unittest.cc
+
+@DISABLE_PROCESSOR_FALSE@src_processor_address_map_unittest_LDADD = \
+@DISABLE_PROCESSOR_FALSE@ src/processor/logging.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o
+
+@DISABLE_PROCESSOR_FALSE@src_processor_basic_source_line_resolver_unittest_SOURCES = \
+@DISABLE_PROCESSOR_FALSE@ src/processor/basic_source_line_resolver_unittest.cc
+
+@DISABLE_PROCESSOR_FALSE@src_processor_basic_source_line_resolver_unittest_CPPFLAGS = \
+@DISABLE_PROCESSOR_FALSE@ $(AM_CPPFLAGS) $(TEST_CFLAGS)
+
+@DISABLE_PROCESSOR_FALSE@src_processor_basic_source_line_resolver_unittest_LDADD = \
+@DISABLE_PROCESSOR_FALSE@ src/processor/basic_source_line_resolver.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/cfi_frame_info.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/logging.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/source_line_resolver_base.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/tokenize.o \
+@DISABLE_PROCESSOR_FALSE@ $(TEST_LIBS) \
+@DISABLE_PROCESSOR_FALSE@ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
+
+@DISABLE_PROCESSOR_FALSE@src_processor_cfi_frame_info_unittest_SOURCES = \
+@DISABLE_PROCESSOR_FALSE@ src/processor/cfi_frame_info_unittest.cc
+
+@DISABLE_PROCESSOR_FALSE@src_processor_cfi_frame_info_unittest_LDADD = \
+@DISABLE_PROCESSOR_FALSE@ src/processor/cfi_frame_info.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/logging.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
+@DISABLE_PROCESSOR_FALSE@ $(TEST_LIBS) \
+@DISABLE_PROCESSOR_FALSE@ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
+
+@DISABLE_PROCESSOR_FALSE@src_processor_cfi_frame_info_unittest_CPPFLAGS = \
+@DISABLE_PROCESSOR_FALSE@ $(AM_CPPFLAGS) $(TEST_CFLAGS)
+
+@DISABLE_PROCESSOR_FALSE@src_processor_contained_range_map_unittest_SOURCES = \
+@DISABLE_PROCESSOR_FALSE@ src/processor/contained_range_map_unittest.cc
+
+@DISABLE_PROCESSOR_FALSE@src_processor_contained_range_map_unittest_LDADD = \
+@DISABLE_PROCESSOR_FALSE@ src/processor/logging.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o
+
+@DISABLE_PROCESSOR_FALSE@src_processor_exploitability_unittest_SOURCES = \
+@DISABLE_PROCESSOR_FALSE@ src/processor/exploitability_unittest.cc
+
+@DISABLE_PROCESSOR_FALSE@src_processor_exploitability_unittest_CPPFLAGS = \
+@DISABLE_PROCESSOR_FALSE@ $(AM_CPPFLAGS) $(TEST_CFLAGS)
+
+@DISABLE_PROCESSOR_FALSE@src_processor_exploitability_unittest_LDADD = \
+@DISABLE_PROCESSOR_FALSE@ src/processor/minidump_processor.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/process_state.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/disassembler_x86.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/exploitability.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/exploitability_linux.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/exploitability_win.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/basic_code_modules.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/basic_source_line_resolver.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/call_stack.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/cfi_frame_info.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/dump_context.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/dump_object.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/logging.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/minidump.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/proc_maps_linux.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/simple_symbol_supplier.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/source_line_resolver_base.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stack_frame_cpu.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stack_frame_symbolizer.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_address_list.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_amd64.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm64.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_mips.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_ppc.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_ppc64.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_sparc.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_x86.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/symbolic_constants_win.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/tokenize.o \
+@DISABLE_PROCESSOR_FALSE@ src/third_party/libdisasm/libdisasm.a \
+@DISABLE_PROCESSOR_FALSE@ $(TEST_LIBS) \
+@DISABLE_PROCESSOR_FALSE@ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
+
+@DISABLE_PROCESSOR_FALSE@src_processor_disassembler_x86_unittest_SOURCES = \
+@DISABLE_PROCESSOR_FALSE@ src/processor/disassembler_x86_unittest.cc
+
+@DISABLE_PROCESSOR_FALSE@src_processor_disassembler_x86_unittest_CPPFLAGS = \
+@DISABLE_PROCESSOR_FALSE@ $(AM_CPPFLAGS) $(TEST_CFLAGS)
+
+@DISABLE_PROCESSOR_FALSE@src_processor_disassembler_x86_unittest_LDADD = \
+@DISABLE_PROCESSOR_FALSE@ src/processor/disassembler_x86.o \
+@DISABLE_PROCESSOR_FALSE@ src/third_party/libdisasm/libdisasm.a \
+@DISABLE_PROCESSOR_FALSE@ $(TEST_LIBS) \
+@DISABLE_PROCESSOR_FALSE@ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
+
+@DISABLE_PROCESSOR_FALSE@src_processor_fast_source_line_resolver_unittest_SOURCES = \
+@DISABLE_PROCESSOR_FALSE@ src/processor/fast_source_line_resolver_unittest.cc
+
+@DISABLE_PROCESSOR_FALSE@src_processor_fast_source_line_resolver_unittest_CPPFLAGS = \
+@DISABLE_PROCESSOR_FALSE@ $(AM_CPPFLAGS) $(TEST_CFLAGS)
+
+@DISABLE_PROCESSOR_FALSE@src_processor_fast_source_line_resolver_unittest_LDADD = \
+@DISABLE_PROCESSOR_FALSE@ src/processor/fast_source_line_resolver.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/basic_source_line_resolver.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/cfi_frame_info.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/module_comparer.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/module_serializer.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/logging.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/source_line_resolver_base.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/tokenize.o \
+@DISABLE_PROCESSOR_FALSE@ $(TEST_LIBS) \
+@DISABLE_PROCESSOR_FALSE@ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
+
+@DISABLE_PROCESSOR_FALSE@src_processor_map_serializers_unittest_SOURCES = \
+@DISABLE_PROCESSOR_FALSE@ src/processor/map_serializers_unittest.cc
+
+@DISABLE_PROCESSOR_FALSE@src_processor_map_serializers_unittest_CPPFLAGS = \
+@DISABLE_PROCESSOR_FALSE@ $(AM_CPPFLAGS) $(TEST_CFLAGS)
+
+@DISABLE_PROCESSOR_FALSE@src_processor_map_serializers_unittest_LDADD = \
+@DISABLE_PROCESSOR_FALSE@ src/processor/logging.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
+@DISABLE_PROCESSOR_FALSE@ $(TEST_LIBS) \
+@DISABLE_PROCESSOR_FALSE@ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
+
+@DISABLE_PROCESSOR_FALSE@src_processor_microdump_processor_unittest_SOURCES = \
+@DISABLE_PROCESSOR_FALSE@ src/processor/microdump_processor_unittest.cc
+
+@DISABLE_PROCESSOR_FALSE@src_processor_microdump_processor_unittest_CPPFLAGS = \
+@DISABLE_PROCESSOR_FALSE@ $(AM_CPPFLAGS) $(TEST_CFLAGS)
+
+@DISABLE_PROCESSOR_FALSE@src_processor_microdump_processor_unittest_LDADD = \
+@DISABLE_PROCESSOR_FALSE@ src/processor/basic_code_modules.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/basic_source_line_resolver.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/call_stack.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/cfi_frame_info.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/dump_context.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/dump_object.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/logging.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/microdump.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/microdump_processor.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/process_state.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/simple_symbol_supplier.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/source_line_resolver_base.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stack_frame_symbolizer.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_address_list.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_amd64.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm64.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_mips.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_ppc.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_ppc64.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_sparc.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_x86.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/tokenize.o \
+@DISABLE_PROCESSOR_FALSE@ $(TEST_LIBS) \
+@DISABLE_PROCESSOR_FALSE@ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
+
+@DISABLE_PROCESSOR_FALSE@src_processor_minidump_processor_unittest_SOURCES = \
+@DISABLE_PROCESSOR_FALSE@ src/processor/minidump_processor_unittest.cc
+
+@DISABLE_PROCESSOR_FALSE@src_processor_minidump_processor_unittest_CPPFLAGS = \
+@DISABLE_PROCESSOR_FALSE@ $(AM_CPPFLAGS) $(TEST_CFLAGS)
+
+@DISABLE_PROCESSOR_FALSE@src_processor_minidump_processor_unittest_LDADD = \
+@DISABLE_PROCESSOR_FALSE@ src/processor/basic_code_modules.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/basic_source_line_resolver.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/call_stack.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/cfi_frame_info.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/disassembler_x86.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/dump_context.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/dump_object.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/exploitability.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/exploitability_linux.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/exploitability_win.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/logging.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/minidump_processor.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/minidump.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/process_state.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/proc_maps_linux.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/source_line_resolver_base.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stack_frame_cpu.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stack_frame_symbolizer.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_address_list.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_amd64.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm64.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_mips.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_ppc.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_ppc64.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_sparc.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_x86.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/symbolic_constants_win.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/tokenize.o \
+@DISABLE_PROCESSOR_FALSE@ src/third_party/libdisasm/libdisasm.a \
+@DISABLE_PROCESSOR_FALSE@ $(TEST_LIBS) \
+@DISABLE_PROCESSOR_FALSE@ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
+
+@DISABLE_PROCESSOR_FALSE@src_processor_minidump_unittest_SOURCES = \
+@DISABLE_PROCESSOR_FALSE@ src/common/test_assembler.cc \
+@DISABLE_PROCESSOR_FALSE@ src/processor/minidump_unittest.cc \
+@DISABLE_PROCESSOR_FALSE@ src/processor/synth_minidump.cc
+
+@DISABLE_PROCESSOR_FALSE@src_processor_minidump_unittest_CPPFLAGS = \
+@DISABLE_PROCESSOR_FALSE@ $(AM_CPPFLAGS) $(TEST_CFLAGS)
+
+@DISABLE_PROCESSOR_FALSE@src_processor_minidump_unittest_LDADD = \
+@DISABLE_PROCESSOR_FALSE@ src/processor/basic_code_modules.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/dump_context.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/dump_object.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/logging.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/minidump.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/proc_maps_linux.o \
+@DISABLE_PROCESSOR_FALSE@ $(TEST_LIBS) \
+@DISABLE_PROCESSOR_FALSE@ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
+
+@DISABLE_PROCESSOR_FALSE@src_processor_proc_maps_linux_unittest_SOURCES = \
+@DISABLE_PROCESSOR_FALSE@ src/processor/proc_maps_linux.cc \
+@DISABLE_PROCESSOR_FALSE@ src/processor/proc_maps_linux_unittest.cc
+
+@DISABLE_PROCESSOR_FALSE@src_processor_proc_maps_linux_unittest_CPPFLAGS = \
+@DISABLE_PROCESSOR_FALSE@ $(AM_CPPFLAGS) $(TEST_CFLAGS)
+
+@DISABLE_PROCESSOR_FALSE@src_processor_proc_maps_linux_unittest_LDADD = \
+@DISABLE_PROCESSOR_FALSE@ src/processor/logging.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
+@DISABLE_PROCESSOR_FALSE@ src/third_party/libdisasm/libdisasm.a \
+@DISABLE_PROCESSOR_FALSE@ $(TEST_LIBS) \
+@DISABLE_PROCESSOR_FALSE@ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
+
+@DISABLE_PROCESSOR_FALSE@src_processor_static_address_map_unittest_SOURCES = \
+@DISABLE_PROCESSOR_FALSE@ src/processor/static_address_map_unittest.cc
+
+@DISABLE_PROCESSOR_FALSE@src_processor_static_address_map_unittest_CPPFLAGS = \
+@DISABLE_PROCESSOR_FALSE@ $(AM_CPPFLAGS) $(TEST_CFLAGS)
+
+@DISABLE_PROCESSOR_FALSE@src_processor_static_address_map_unittest_LDADD = \
+@DISABLE_PROCESSOR_FALSE@ src/processor/logging.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
+@DISABLE_PROCESSOR_FALSE@ $(TEST_LIBS) \
+@DISABLE_PROCESSOR_FALSE@ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
+
+@DISABLE_PROCESSOR_FALSE@src_processor_static_contained_range_map_unittest_SOURCES = \
+@DISABLE_PROCESSOR_FALSE@ src/processor/static_contained_range_map_unittest.cc
+
+@DISABLE_PROCESSOR_FALSE@src_processor_static_contained_range_map_unittest_CPPFLAGS = \
+@DISABLE_PROCESSOR_FALSE@ $(AM_CPPFLAGS) $(TEST_CFLAGS)
+
+@DISABLE_PROCESSOR_FALSE@src_processor_static_contained_range_map_unittest_LDADD = \
+@DISABLE_PROCESSOR_FALSE@ src/processor/logging.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
+@DISABLE_PROCESSOR_FALSE@ $(TEST_LIBS) \
+@DISABLE_PROCESSOR_FALSE@ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
+
+@DISABLE_PROCESSOR_FALSE@src_processor_static_map_unittest_SOURCES = \
+@DISABLE_PROCESSOR_FALSE@ src/processor/static_map_unittest.cc
+
+@DISABLE_PROCESSOR_FALSE@src_processor_static_map_unittest_CPPFLAGS = \
+@DISABLE_PROCESSOR_FALSE@ $(AM_CPPFLAGS) $(TEST_CFLAGS)
+
+@DISABLE_PROCESSOR_FALSE@src_processor_static_map_unittest_LDADD = \
+@DISABLE_PROCESSOR_FALSE@ src/processor/logging.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
+@DISABLE_PROCESSOR_FALSE@ $(TEST_LIBS) \
+@DISABLE_PROCESSOR_FALSE@ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
+
+@DISABLE_PROCESSOR_FALSE@src_processor_static_range_map_unittest_SOURCES = \
+@DISABLE_PROCESSOR_FALSE@ src/processor/static_range_map_unittest.cc
+
+@DISABLE_PROCESSOR_FALSE@src_processor_static_range_map_unittest_CPPFLAGS = \
+@DISABLE_PROCESSOR_FALSE@ $(AM_CPPFLAGS) $(TEST_CFLAGS)
+
+@DISABLE_PROCESSOR_FALSE@src_processor_static_range_map_unittest_LDADD = \
+@DISABLE_PROCESSOR_FALSE@ src/processor/logging.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
+@DISABLE_PROCESSOR_FALSE@ $(TEST_LIBS) \
+@DISABLE_PROCESSOR_FALSE@ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
+
+@DISABLE_PROCESSOR_FALSE@src_processor_pathname_stripper_unittest_SOURCES = \
+@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper_unittest.cc
+
+@DISABLE_PROCESSOR_FALSE@src_processor_pathname_stripper_unittest_LDADD = \
+@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
+@DISABLE_PROCESSOR_FALSE@ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
+
+@DISABLE_PROCESSOR_FALSE@src_processor_postfix_evaluator_unittest_SOURCES = \
+@DISABLE_PROCESSOR_FALSE@ src/processor/postfix_evaluator_unittest.cc
+
+@DISABLE_PROCESSOR_FALSE@src_processor_postfix_evaluator_unittest_LDADD = \
+@DISABLE_PROCESSOR_FALSE@ src/processor/logging.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
+@DISABLE_PROCESSOR_FALSE@ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
+
+@DISABLE_PROCESSOR_FALSE@src_processor_range_map_shrink_down_unittest_SOURCES = \
+@DISABLE_PROCESSOR_FALSE@ src/processor/range_map_shrink_down_unittest.cc
+
+@DISABLE_PROCESSOR_FALSE@src_processor_range_map_shrink_down_unittest_LDADD = \
+@DISABLE_PROCESSOR_FALSE@ src/processor/logging.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
+@DISABLE_PROCESSOR_FALSE@ $(TEST_LIBS) \
+@DISABLE_PROCESSOR_FALSE@ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
+
+@DISABLE_PROCESSOR_FALSE@src_processor_range_map_shrink_down_unittest_CPPFLAGS = \
+@DISABLE_PROCESSOR_FALSE@ $(AM_CPPFLAGS) $(TEST_CFLAGS)
+
+@DISABLE_PROCESSOR_FALSE@src_processor_range_map_unittest_SOURCES = \
+@DISABLE_PROCESSOR_FALSE@ src/processor/range_map_unittest.cc
+
+@DISABLE_PROCESSOR_FALSE@src_processor_range_map_unittest_LDADD = \
+@DISABLE_PROCESSOR_FALSE@ src/processor/logging.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
+@DISABLE_PROCESSOR_FALSE@ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
+
+@DISABLE_PROCESSOR_FALSE@src_processor_stackwalker_selftest_SOURCES = \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_selftest.cc
+
+@DISABLE_PROCESSOR_FALSE@src_processor_stackwalker_selftest_LDADD = \
+@DISABLE_PROCESSOR_FALSE@ src/processor/basic_code_modules.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/basic_source_line_resolver.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/call_stack.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/disassembler_x86.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/exploitability.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/exploitability_linux.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/exploitability_win.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/logging.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/minidump.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/proc_maps_linux.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/source_line_resolver_base.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stack_frame_cpu.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stack_frame_symbolizer.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_address_list.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_amd64.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm64.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_mips.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_ppc.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_ppc64.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_sparc.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_x86.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/tokenize.o \
+@DISABLE_PROCESSOR_FALSE@ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
+
+@DISABLE_PROCESSOR_FALSE@src_processor_stackwalker_amd64_unittest_SOURCES = \
+@DISABLE_PROCESSOR_FALSE@ src/common/test_assembler.cc \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_amd64_unittest.cc
+
+@DISABLE_PROCESSOR_FALSE@src_processor_stackwalker_amd64_unittest_LDADD = \
+@DISABLE_PROCESSOR_FALSE@ src/libbreakpad.a \
+@DISABLE_PROCESSOR_FALSE@ $(TEST_LIBS) \
+@DISABLE_PROCESSOR_FALSE@ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
+
+@DISABLE_PROCESSOR_FALSE@src_processor_stackwalker_amd64_unittest_CPPFLAGS = \
+@DISABLE_PROCESSOR_FALSE@ $(AM_CPPFLAGS) $(TEST_CFLAGS)
+
+@DISABLE_PROCESSOR_FALSE@src_processor_stackwalker_arm_unittest_SOURCES = \
+@DISABLE_PROCESSOR_FALSE@ src/common/test_assembler.cc \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm_unittest.cc
+
+@DISABLE_PROCESSOR_FALSE@src_processor_stackwalker_arm_unittest_LDADD = \
+@DISABLE_PROCESSOR_FALSE@ src/libbreakpad.a \
+@DISABLE_PROCESSOR_FALSE@ $(TEST_LIBS) \
+@DISABLE_PROCESSOR_FALSE@ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
+
+@DISABLE_PROCESSOR_FALSE@src_processor_stackwalker_arm_unittest_CPPFLAGS = \
+@DISABLE_PROCESSOR_FALSE@ $(AM_CPPFLAGS) $(TEST_CFLAGS)
+
+@DISABLE_PROCESSOR_FALSE@src_processor_stackwalker_arm64_unittest_SOURCES = \
+@DISABLE_PROCESSOR_FALSE@ src/common/test_assembler.cc \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm64_unittest.cc
+
+@DISABLE_PROCESSOR_FALSE@src_processor_stackwalker_arm64_unittest_LDADD = \
+@DISABLE_PROCESSOR_FALSE@ src/libbreakpad.a \
+@DISABLE_PROCESSOR_FALSE@ $(TEST_LIBS) \
+@DISABLE_PROCESSOR_FALSE@ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
+
+@DISABLE_PROCESSOR_FALSE@src_processor_stackwalker_arm64_unittest_CPPFLAGS = \
+@DISABLE_PROCESSOR_FALSE@ $(AM_CPPFLAGS) $(TEST_CFLAGS)
+
+@DISABLE_PROCESSOR_FALSE@src_processor_stackwalker_address_list_unittest_SOURCES = \
+@DISABLE_PROCESSOR_FALSE@ src/common/test_assembler.cc \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_address_list_unittest.cc
+
+@DISABLE_PROCESSOR_FALSE@src_processor_stackwalker_address_list_unittest_LDADD = \
+@DISABLE_PROCESSOR_FALSE@ src/libbreakpad.a \
+@DISABLE_PROCESSOR_FALSE@ $(TEST_LIBS) \
+@DISABLE_PROCESSOR_FALSE@ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
+
+@DISABLE_PROCESSOR_FALSE@src_processor_stackwalker_address_list_unittest_CPPFLAGS = \
+@DISABLE_PROCESSOR_FALSE@ $(AM_CPPFLAGS) $(TEST_CFLAGS)
+
+@DISABLE_PROCESSOR_FALSE@src_processor_stackwalker_mips_unittest_SOURCES = \
+@DISABLE_PROCESSOR_FALSE@ src/common/test_assembler.cc \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_mips_unittest.cc
+
+@DISABLE_PROCESSOR_FALSE@src_processor_stackwalker_mips_unittest_LDADD = \
+@DISABLE_PROCESSOR_FALSE@ src/libbreakpad.a \
+@DISABLE_PROCESSOR_FALSE@ $(TEST_LIBS) \
+@DISABLE_PROCESSOR_FALSE@ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
+
+@DISABLE_PROCESSOR_FALSE@src_processor_stackwalker_mips_unittest_CPPFLAGS = \
+@DISABLE_PROCESSOR_FALSE@ $(AM_CPPFLAGS) $(TEST_CFLAGS)
+
+@DISABLE_PROCESSOR_FALSE@src_processor_stackwalker_mips64_unittest_SOURCES = \
+@DISABLE_PROCESSOR_FALSE@ src/common/test_assembler.cc \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_mips64_unittest.cc
+
+@DISABLE_PROCESSOR_FALSE@src_processor_stackwalker_mips64_unittest_LDADD = \
+@DISABLE_PROCESSOR_FALSE@ src/libbreakpad.a \
+@DISABLE_PROCESSOR_FALSE@ $(TEST_LIBS) \
+@DISABLE_PROCESSOR_FALSE@ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
+
+@DISABLE_PROCESSOR_FALSE@src_processor_stackwalker_mips64_unittest_CPPFLAGS = \
+@DISABLE_PROCESSOR_FALSE@ $(AM_CPPFLAGS) $(TEST_CFLAGS)
+
+@DISABLE_PROCESSOR_FALSE@src_processor_stackwalker_x86_unittest_SOURCES = \
+@DISABLE_PROCESSOR_FALSE@ src/common/test_assembler.cc \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_x86_unittest.cc
+
+@DISABLE_PROCESSOR_FALSE@src_processor_stackwalker_x86_unittest_LDADD = \
+@DISABLE_PROCESSOR_FALSE@ src/libbreakpad.a \
+@DISABLE_PROCESSOR_FALSE@ $(TEST_LIBS) \
+@DISABLE_PROCESSOR_FALSE@ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
+
+@DISABLE_PROCESSOR_FALSE@src_processor_stackwalker_x86_unittest_CPPFLAGS = \
+@DISABLE_PROCESSOR_FALSE@ $(AM_CPPFLAGS) $(TEST_CFLAGS)
+
+@DISABLE_PROCESSOR_FALSE@src_processor_synth_minidump_unittest_SOURCES = \
+@DISABLE_PROCESSOR_FALSE@ src/common/test_assembler.cc \
+@DISABLE_PROCESSOR_FALSE@ src/common/test_assembler.h \
+@DISABLE_PROCESSOR_FALSE@ src/processor/synth_minidump_unittest.cc \
+@DISABLE_PROCESSOR_FALSE@ src/processor/synth_minidump.cc \
+@DISABLE_PROCESSOR_FALSE@ src/processor/synth_minidump.h
+
+@DISABLE_PROCESSOR_FALSE@src_processor_synth_minidump_unittest_CPPFLAGS = \
+@DISABLE_PROCESSOR_FALSE@ $(AM_CPPFLAGS) $(TEST_CFLAGS)
+
+@DISABLE_PROCESSOR_FALSE@src_processor_synth_minidump_unittest_LDADD = \
+@DISABLE_PROCESSOR_FALSE@ $(TEST_LIBS) \
+@DISABLE_PROCESSOR_FALSE@ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
+
+@DISABLE_PROCESSOR_FALSE@src_common_test_assembler_unittest_SOURCES = \
+@DISABLE_PROCESSOR_FALSE@ src/common/test_assembler.cc \
+@DISABLE_PROCESSOR_FALSE@ src/common/test_assembler.h \
+@DISABLE_PROCESSOR_FALSE@ src/common/test_assembler_unittest.cc
+
+@DISABLE_PROCESSOR_FALSE@src_common_test_assembler_unittest_CPPFLAGS = \
+@DISABLE_PROCESSOR_FALSE@ $(AM_CPPFLAGS) $(TEST_CFLAGS)
+
+@DISABLE_PROCESSOR_FALSE@src_common_test_assembler_unittest_LDADD = \
+@DISABLE_PROCESSOR_FALSE@ $(TEST_LIBS) \
+@DISABLE_PROCESSOR_FALSE@ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
+
+@DISABLE_PROCESSOR_FALSE@noinst_SCRIPTS = $(check_SCRIPTS)
+@DISABLE_PROCESSOR_FALSE@src_processor_minidump_dump_SOURCES = \
+@DISABLE_PROCESSOR_FALSE@ src/processor/minidump_dump.cc
+
+@DISABLE_PROCESSOR_FALSE@src_processor_minidump_dump_LDADD = \
+@DISABLE_PROCESSOR_FALSE@ src/processor/basic_code_modules.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/dump_context.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/dump_object.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/logging.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/minidump.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/proc_maps_linux.o
+
+@DISABLE_PROCESSOR_FALSE@src_processor_microdump_stackwalk_SOURCES = \
+@DISABLE_PROCESSOR_FALSE@ src/processor/microdump_stackwalk.cc
+
+@DISABLE_PROCESSOR_FALSE@src_processor_microdump_stackwalk_LDADD = \
+@DISABLE_PROCESSOR_FALSE@ src/processor/basic_code_modules.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/basic_source_line_resolver.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/call_stack.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/cfi_frame_info.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/disassembler_x86.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/dump_context.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/dump_object.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/logging.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/microdump.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/microdump_processor.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/process_state.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/simple_symbol_supplier.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/source_line_resolver_base.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stack_frame_cpu.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stack_frame_symbolizer.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalk_common.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_address_list.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_amd64.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm64.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_mips.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_ppc.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_ppc64.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_sparc.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_x86.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/tokenize.o \
+@DISABLE_PROCESSOR_FALSE@ src/third_party/libdisasm/libdisasm.a
+
+@DISABLE_PROCESSOR_FALSE@src_processor_minidump_stackwalk_SOURCES = \
+@DISABLE_PROCESSOR_FALSE@ src/processor/minidump_stackwalk.cc
+
+@DISABLE_PROCESSOR_FALSE@src_processor_minidump_stackwalk_LDADD = \
+@DISABLE_PROCESSOR_FALSE@ src/processor/basic_code_modules.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/basic_source_line_resolver.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/call_stack.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/cfi_frame_info.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/disassembler_x86.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/dump_context.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/dump_object.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/exploitability.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/exploitability_linux.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/exploitability_win.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/logging.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/minidump.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/minidump_processor.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/process_state.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/proc_maps_linux.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/simple_symbol_supplier.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/source_line_resolver_base.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stack_frame_cpu.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stack_frame_symbolizer.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalk_common.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_address_list.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_amd64.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm64.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_mips.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_ppc.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_ppc64.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_sparc.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_x86.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/symbolic_constants_win.o \
+@DISABLE_PROCESSOR_FALSE@ src/processor/tokenize.o \
+@DISABLE_PROCESSOR_FALSE@ src/third_party/libdisasm/libdisasm.a
+
+EXTRA_DIST = \
+ $(SCRIPTS) \
+ src/client/linux/data/linux-gate-amd.sym \
+ src/client/linux/data/linux-gate-intel.sym \
+ src/client/mac/handler/breakpad_nlist_64.cc \
+ src/client/mac/handler/breakpad_nlist_64.h \
+ src/client/mac/handler/dynamic_images.cc \
+ src/client/mac/handler/dynamic_images.h \
+ src/client/mac/handler/exception_handler.cc \
+ src/client/mac/handler/exception_handler.h \
+ src/client/mac/handler/mach_vm_compat.h \
+ src/client/mac/handler/minidump_generator.cc \
+ src/client/mac/handler/minidump_generator.h \
+ src/client/mac/handler/minidump_test.xcodeproj/project.pbxproj \
+ src/client/mac/handler/minidump_tests32-Info.plist \
+ src/client/mac/handler/minidump_tests64-Info.plist \
+ src/client/mac/handler/obj-cTestCases-Info.plist \
+ src/client/mac/handler/protected_memory_allocator.cc \
+ src/client/mac/handler/protected_memory_allocator.h \
+ src/client/mac/handler/ucontext_compat.h \
+ src/client/mac/handler/testcases/testdata/dump_syms_i386_breakpad.sym \
+ src/client/mac/tests/BreakpadFramework_Test.mm \
+ src/client/mac/tests/crash_generation_server_test.cc \
+ src/client/mac/tests/exception_handler_test.cc \
+ src/client/mac/tests/minidump_generator_test.cc \
+ src/client/mac/tests/minidump_generator_test_helper.cc \
+ src/client/mac/tests/spawn_child_process.h \
+ src/client/mac/tests/testlogging.h \
+ src/client/minidump_file_writer_unittest.cc \
+ src/client/solaris/handler/Makefile \
+ src/client/solaris/handler/exception_handler.cc \
+ src/client/solaris/handler/exception_handler.h \
+ src/client/solaris/handler/exception_handler_test.cc \
+ src/client/solaris/handler/minidump_generator.cc \
+ src/client/solaris/handler/minidump_generator.h \
+ src/client/solaris/handler/minidump_test.cc \
+ src/client/solaris/handler/solaris_lwp.cc \
+ src/client/solaris/handler/solaris_lwp.h \
+ src/client/windows/breakpad_client.gyp \
+ src/client/windows/handler/exception_handler.cc \
+ src/client/windows/handler/exception_handler.h \
+ src/client/windows/handler/exception_handler.gyp \
+ src/client/windows/sender/crash_report_sender.cc \
+ src/client/windows/sender/crash_report_sender.h \
+ src/client/windows/sender/crash_report_sender.gyp \
+ src/common/dwarf/dwarf2diehandler.h \
+ src/common/dwarf/dwarf2enums.h \
+ src/common/dwarf/line_state_machine.h \
+ src/common/dwarf/types.h \
+ src/common/mac/arch_utilities.h \
+ src/common/mac/byteswap.h \
+ src/common/mac/HTTPMultipartUpload.h \
+ src/common/mac/HTTPMultipartUpload.m \
+ src/common/mac/string_utilities.cc \
+ src/common/mac/string_utilities.h \
+ src/common/mac/super_fat_arch.h \
+ src/common/scoped_ptr.h \
+ src/common/solaris/dump_symbols.cc \
+ src/common/solaris/dump_symbols.h \
+ src/common/solaris/file_id.cc \
+ src/common/solaris/file_id.h \
+ src/common/solaris/guid_creator.cc \
+ src/common/solaris/guid_creator.h \
+ src/common/solaris/message_output.h \
+ src/common/windows/guid_string.cc \
+ src/common/windows/guid_string.h \
+ src/common/windows/http_upload.cc \
+ src/common/windows/http_upload.h \
+ src/common/windows/pdb_source_line_writer.cc \
+ src/common/windows/pdb_source_line_writer.h \
+ src/common/windows/string_utils-inl.h \
+ src/common/windows/string_utils.cc \
+ src/processor/stackwalk_common.cc \
+ src/processor/stackwalk_common.h \
+ src/processor/stackwalker_selftest_sol.s \
+ src/processor/testdata/ascii_read_av_block_write.dmp \
+ src/processor/testdata/ascii_read_av_clobber_write.dmp \
+ src/processor/testdata/ascii_read_av_conditional.dmp \
+ src/processor/testdata/ascii_read_av.dmp \
+ src/processor/testdata/ascii_read_av_then_jmp.dmp \
+ src/processor/testdata/ascii_read_av_xchg_write.dmp \
+ src/processor/testdata/ascii_write_av_arg_to_call.dmp \
+ src/processor/testdata/ascii_write_av.dmp \
+ src/processor/testdata/exec_av_on_stack.dmp \
+ src/processor/testdata/linux_divide_by_zero.dmp \
+ src/processor/testdata/linux_executable_heap.dmp \
+ src/processor/testdata/linux_executable_stack.dmp \
+ src/processor/testdata/linux_inside_module_exe_region1.dmp \
+ src/processor/testdata/linux_inside_module_exe_region2.dmp \
+ src/processor/testdata/linux_jmp_to_0.dmp \
+ src/processor/testdata/linux_jmp_to_module_not_exe_region.dmp \
+ src/processor/testdata/linux_null_dereference.dmp \
+ src/processor/testdata/linux_null_read_av.dmp \
+ src/processor/testdata/linux_outside_module.dmp \
+ src/processor/testdata/linux_overflow.dmp \
+ src/processor/testdata/linux_raise_sigabrt.dmp \
+ src/processor/testdata/linux_stack_pointer_in_module.dmp \
+ src/processor/testdata/linux_stack_pointer_in_stack.dmp \
+ src/processor/testdata/linux_stacksmash.dmp \
+ src/processor/testdata/linux_write_to_nonwritable_module.dmp \
+ src/processor/testdata/linux_write_to_nonwritable_region_math.dmp \
+ src/processor/testdata/linux_write_to_outside_module.dmp \
+ src/processor/testdata/linux_write_to_outside_module_via_math.dmp \
+ src/processor/testdata/linux_write_to_under_4k.dmp \
+ src/processor/testdata/microdump-arm64.dmp \
+ src/processor/testdata/microdump-arm.dmp \
+ src/processor/testdata/microdump-mips32.dmp \
+ src/processor/testdata/microdump-mips64.dmp \
+ src/processor/testdata/microdump-multiple.dmp \
+ src/processor/testdata/microdump.stackwalk-arm64.out \
+ src/processor/testdata/microdump.stackwalk-arm.out \
+ src/processor/testdata/microdump.stackwalk.machine_readable-arm64.out \
+ src/processor/testdata/microdump.stackwalk.machine_readable-arm.out \
+ src/processor/testdata/microdump-x86.dmp \
+ src/processor/testdata/minidump2.dmp \
+ src/processor/testdata/minidump2.dump.out \
+ src/processor/testdata/minidump2.stackwalk.machine_readable.out \
+ src/processor/testdata/minidump2.stackwalk.out \
+ src/processor/testdata/module0.out \
+ src/processor/testdata/module1.out \
+ src/processor/testdata/module2.out \
+ src/processor/testdata/module3_bad.out \
+ src/processor/testdata/module4_bad.out \
+ src/processor/testdata/null_read_av.dmp \
+ src/processor/testdata/null_write_av.dmp \
+ src/processor/testdata/read_av_clobber_write.dmp \
+ src/processor/testdata/read_av_conditional.dmp \
+ src/processor/testdata/read_av_non_null.dmp \
+ src/processor/testdata/stack_exhaustion.dmp \
+ src/processor/testdata/write_av_non_null.dmp \
+ src/processor/testdata/symbols/kernel32.pdb/BCE8785C57B44245A669896B6A19B9542/kernel32.sym \
+ src/processor/testdata/symbols/ld-2.13.so/C32AD7E235EA6112E02A5B9D6219C4850/ld-2.13.so.sym \
+ src/processor/testdata/symbols/libc-2.13.so/F4F8DFCD5A5FB5A7CE64717E9E6AE3890/libc-2.13.so.sym \
+ src/processor/testdata/symbols/libgcc_s.so.1/18B180F90887D8F8B5C35D185444AF4C0/libgcc_s.so.1.sym \
+ src/processor/testdata/symbols/microdump/breakpad_unittests/D6D1FEC9A15DE7F38A236898871A2E770/breakpad_unittests.sym \
+ src/processor/testdata/symbols/microdump/breakpad_unittests/DA7778FB66018A4E9B4110ED06E730D00/breakpad_unittests.sym \
+ src/processor/testdata/symbols/microdump/crash_example/6E72E2F1A5F59AB3D51356FDFE394D490/crash_example.sym \
+ src/processor/testdata/symbols/microdump/crash_example/8F36148CC4647A8116CAF2A25F591F570/crash_example.sym \
+ src/processor/testdata/symbols/null_read_av/7B7D1968FF0D47AE4366E9C3A7E1B6750/null_read_av.sym \
+ src/processor/testdata/symbols/overflow/B0E1FC01EF48E39CAF5C881D2DF0C3840/overflow.sym \
+ src/processor/testdata/symbols/test_app.pdb/5A9832E5287241C1838ED98914E9B7FF1/test_app.sym \
+ src/processor/testdata/test_app.cc \
+ src/testing/gtest/include/gtest/gtest.h \
+ src/testing/gtest/include/gtest/gtest-death-test.h \
+ src/testing/gtest/include/gtest/gtest-message.h \
+ src/testing/gtest/include/gtest/gtest-param-test.h \
+ src/testing/gtest/include/gtest/gtest-printers.h \
+ src/testing/gtest/include/gtest/gtest-spi.h \
+ src/testing/gtest/include/gtest/gtest-test-part.h \
+ src/testing/gtest/include/gtest/gtest-typed-test.h \
+ src/testing/gtest/include/gtest/gtest_pred_impl.h \
+ src/testing/gtest/include/gtest/gtest_prod.h \
+ src/testing/gtest/include/gtest/internal/gtest-death-test-internal.h \
+ src/testing/gtest/include/gtest/internal/gtest-filepath.h \
+ src/testing/gtest/include/gtest/internal/gtest-internal.h \
+ src/testing/gtest/include/gtest/internal/gtest-linked_ptr.h \
+ src/testing/gtest/include/gtest/internal/gtest-param-util-generated.h \
+ src/testing/gtest/include/gtest/internal/gtest-param-util.h \
+ src/testing/gtest/include/gtest/internal/gtest-port.h \
+ src/testing/gtest/include/gtest/internal/gtest-string.h \
+ src/testing/gtest/include/gtest/internal/gtest-tuple.h \
+ src/testing/gtest/include/gtest/internal/gtest-type-util.h \
+ src/testing/gtest/src/gtest.cc \
+ src/testing/gtest/src/gtest-death-test.cc \
+ src/testing/gtest/src/gtest-filepath.cc \
+ src/testing/gtest/src/gtest-internal-inl.h \
+ src/testing/gtest/src/gtest-port.cc \
+ src/testing/gtest/src/gtest-printers.cc \
+ src/testing/gtest/src/gtest-test-part.cc \
+ src/testing/gtest/src/gtest-typed-test.cc \
+ src/testing/include/gmock/gmock.h \
+ src/testing/include/gmock/gmock-actions.h \
+ src/testing/include/gmock/gmock-cardinalities.h \
+ src/testing/include/gmock/gmock-generated-actions.h \
+ src/testing/include/gmock/gmock-generated-function-mockers.h \
+ src/testing/include/gmock/gmock-generated-matchers.h \
+ src/testing/include/gmock/gmock-generated-nice-strict.h \
+ src/testing/include/gmock/gmock-matchers.h \
+ src/testing/include/gmock/gmock-more-actions.h \
+ src/testing/include/gmock/gmock-more-matchers.h \
+ src/testing/include/gmock/gmock-spec-builders.h \
+ src/testing/include/gmock/internal/gmock-generated-internal-utils.h \
+ src/testing/include/gmock/internal/gmock-internal-utils.h \
+ src/testing/include/gmock/internal/gmock-port.h \
+ src/testing/src/gmock.cc \
+ src/testing/src/gmock-cardinalities.cc \
+ src/testing/src/gmock-internal-utils.cc \
+ src/testing/src/gmock-matchers.cc \
+ src/testing/src/gmock-spec-builders.cc \
+ src/testing/src/gmock_main.cc \
+ src/third_party/curl/COPYING \
+ src/third_party/curl/curlbuild.h \
+ src/third_party/curl/curl.h \
+ src/third_party/curl/curlrules.h \
+ src/third_party/curl/curlver.h \
+ src/third_party/curl/easy.h \
+ src/third_party/curl/mprintf.h \
+ src/third_party/curl/multi.h \
+ src/third_party/curl/stdcheaders.h \
+ src/third_party/curl/typecheck-gcc.h \
+ src/third_party/curl/types.h \
+ src/third_party/mac_headers/architecture/byte_order.h \
+ src/third_party/mac_headers/i386/_types.h \
+ src/third_party/mac_headers/mach/boolean.h \
+ src/third_party/mac_headers/mach/i386/boolean.h \
+ src/third_party/mac_headers/mach/i386/vm_param.h \
+ src/third_party/mac_headers/mach/i386/vm_types.h \
+ src/third_party/mac_headers/mach/machine/boolean.h \
+ src/third_party/mac_headers/mach/machine.h \
+ src/third_party/mac_headers/mach/machine/thread_state.h \
+ src/third_party/mac_headers/mach/machine/thread_status.h \
+ src/third_party/mac_headers/mach/machine/vm_types.h \
+ src/third_party/mac_headers/mach-o/arch.h \
+ src/third_party/mac_headers/mach-o/fat.h \
+ src/third_party/mac_headers/mach-o/loader.h \
+ src/third_party/mac_headers/mach-o/nlist.h \
+ src/third_party/mac_headers/mach/thread_status.h \
+ src/third_party/mac_headers/mach/vm_prot.h \
+ src/third_party/mac_headers/README \
+ src/third_party/musl/README \
+ src/third_party/musl/COPYRIGHT \
+ src/third_party/musl/README.breakpad \
+ src/third_party/musl/VERSION \
+ src/third_party/musl/include/elf.h \
+ src/tools/mac/crash_report/crash_report.mm \
+ src/tools/mac/crash_report/crash_report.xcodeproj/project.pbxproj \
+ src/tools/mac/crash_report/on_demand_symbol_supplier.h \
+ src/tools/mac/crash_report/on_demand_symbol_supplier.mm \
+ src/tools/mac/dump_syms/dump_syms.xcodeproj/project.pbxproj \
+ src/tools/mac/dump_syms/dump_syms_tool.cc \
+ src/tools/mac/symupload/minidump_upload.m \
+ src/tools/mac/symupload/symupload.m \
+ src/tools/mac/symupload/symupload.xcodeproj/project.pbxproj \
+ src/tools/solaris/dump_syms/Makefile \
+ src/tools/solaris/dump_syms/dump_syms.cc \
+ src/tools/solaris/dump_syms/run_regtest.sh \
+ src/tools/solaris/dump_syms/testdata/dump_syms_regtest.cc \
+ src/tools/solaris/dump_syms/testdata/dump_syms_regtest.o \
+ src/tools/solaris/dump_syms/testdata/dump_syms_regtest.stabs \
+ src/tools/solaris/dump_syms/testdata/dump_syms_regtest.sym \
+ src/tools/windows/converter/ms_symbol_server_converter.cc \
+ src/tools/windows/converter/ms_symbol_server_converter.h \
+ src/tools/windows/converter/ms_symbol_server_converter.gyp \
+ src/tools/windows/dump_syms/dump_syms.cc \
+ src/tools/windows/dump_syms/dump_syms.gyp \
+ src/tools/windows/dump_syms/run_regtest.sh \
+ src/tools/windows/dump_syms/testdata/dump_syms_regtest.cc \
+ src/tools/windows/dump_syms/testdata/dump_syms_regtest.pdb \
+ src/tools/windows/dump_syms/testdata/dump_syms_regtest.sym \
+ src/tools/windows/dump_syms/testdata/dump_syms_regtest64.sym \
+ src/tools/windows/dump_syms/testdata/omap_reorder_bbs.sym \
+ src/tools/windows/dump_syms/testdata/omap_reorder_funcs.sym \
+ src/tools/windows/dump_syms/testdata/omap_stretched.sym \
+ src/tools/windows/dump_syms/testdata/omap_stretched_filled.sym \
+ src/tools/windows/symupload/symupload.cc \
+ src/tools/windows/symupload/symupload.gyp
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .S .c .cc .log .o .obj .test .test$(EXEEXT) .trs
+am--refresh: Makefile
+ @:
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ echo ' cd $(srcdir) && $(AUTOMAKE) --foreign'; \
+ $(am__cd) $(srcdir) && $(AUTOMAKE) --foreign \
+ && exit 0; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ echo ' $(SHELL) ./config.status'; \
+ $(SHELL) ./config.status;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ $(SHELL) ./config.status --recheck
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ $(am__cd) $(srcdir) && $(AUTOCONF)
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)
+$(am__aclocal_m4_deps):
+
+src/config.h: src/stamp-h1
+ @test -f $@ || rm -f src/stamp-h1
+ @test -f $@ || $(MAKE) $(AM_MAKEFLAGS) src/stamp-h1
+
+src/stamp-h1: $(top_srcdir)/src/config.h.in $(top_builddir)/config.status
+ @rm -f src/stamp-h1
+ cd $(top_builddir) && $(SHELL) ./config.status src/config.h
+$(top_srcdir)/src/config.h.in: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ ($(am__cd) $(top_srcdir) && $(AUTOHEADER))
+ rm -f src/stamp-h1
+ touch $@
+
+distclean-hdr:
+ -rm -f src/config.h src/stamp-h1
+breakpad.pc: $(top_builddir)/config.status $(srcdir)/breakpad.pc.in
+ cd $(top_builddir) && $(SHELL) ./config.status $@
+breakpad-client.pc: $(top_builddir)/config.status $(srcdir)/breakpad-client.pc.in
+ cd $(top_builddir) && $(SHELL) ./config.status $@
+
+clean-checkLIBRARIES:
+ -test -z "$(check_LIBRARIES)" || rm -f $(check_LIBRARIES)
+install-libLIBRARIES: $(lib_LIBRARIES)
+ @$(NORMAL_INSTALL)
+ @list='$(lib_LIBRARIES)'; test -n "$(libdir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \
+ echo " $(INSTALL_DATA) $$list2 '$(DESTDIR)$(libdir)'"; \
+ $(INSTALL_DATA) $$list2 "$(DESTDIR)$(libdir)" || exit $$?; }
+ @$(POST_INSTALL)
+ @list='$(lib_LIBRARIES)'; test -n "$(libdir)" || list=; \
+ for p in $$list; do \
+ if test -f $$p; then \
+ $(am__strip_dir) \
+ echo " ( cd '$(DESTDIR)$(libdir)' && $(RANLIB) $$f )"; \
+ ( cd "$(DESTDIR)$(libdir)" && $(RANLIB) $$f ) || exit $$?; \
+ else :; fi; \
+ done
+
+uninstall-libLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(lib_LIBRARIES)'; test -n "$(libdir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ dir='$(DESTDIR)$(libdir)'; $(am__uninstall_files_from_dir)
+
+clean-libLIBRARIES:
+ -test -z "$(lib_LIBRARIES)" || rm -f $(lib_LIBRARIES)
+
+clean-noinstLIBRARIES:
+ -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
+src/client/linux/crash_generation/$(am__dirstamp):
+ @$(MKDIR_P) src/client/linux/crash_generation
+ @: > src/client/linux/crash_generation/$(am__dirstamp)
+src/client/linux/crash_generation/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) src/client/linux/crash_generation/$(DEPDIR)
+ @: > src/client/linux/crash_generation/$(DEPDIR)/$(am__dirstamp)
+src/client/linux/crash_generation/crash_generation_client.$(OBJEXT): \
+ src/client/linux/crash_generation/$(am__dirstamp) \
+ src/client/linux/crash_generation/$(DEPDIR)/$(am__dirstamp)
+src/client/linux/crash_generation/crash_generation_server.$(OBJEXT): \
+ src/client/linux/crash_generation/$(am__dirstamp) \
+ src/client/linux/crash_generation/$(DEPDIR)/$(am__dirstamp)
+src/client/linux/dump_writer_common/$(am__dirstamp):
+ @$(MKDIR_P) src/client/linux/dump_writer_common
+ @: > src/client/linux/dump_writer_common/$(am__dirstamp)
+src/client/linux/dump_writer_common/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) src/client/linux/dump_writer_common/$(DEPDIR)
+ @: > src/client/linux/dump_writer_common/$(DEPDIR)/$(am__dirstamp)
+src/client/linux/dump_writer_common/thread_info.$(OBJEXT): \
+ src/client/linux/dump_writer_common/$(am__dirstamp) \
+ src/client/linux/dump_writer_common/$(DEPDIR)/$(am__dirstamp)
+src/client/linux/dump_writer_common/ucontext_reader.$(OBJEXT): \
+ src/client/linux/dump_writer_common/$(am__dirstamp) \
+ src/client/linux/dump_writer_common/$(DEPDIR)/$(am__dirstamp)
+src/client/linux/handler/$(am__dirstamp):
+ @$(MKDIR_P) src/client/linux/handler
+ @: > src/client/linux/handler/$(am__dirstamp)
+src/client/linux/handler/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) src/client/linux/handler/$(DEPDIR)
+ @: > src/client/linux/handler/$(DEPDIR)/$(am__dirstamp)
+src/client/linux/handler/exception_handler.$(OBJEXT): \
+ src/client/linux/handler/$(am__dirstamp) \
+ src/client/linux/handler/$(DEPDIR)/$(am__dirstamp)
+src/client/linux/handler/minidump_descriptor.$(OBJEXT): \
+ src/client/linux/handler/$(am__dirstamp) \
+ src/client/linux/handler/$(DEPDIR)/$(am__dirstamp)
+src/client/linux/log/$(am__dirstamp):
+ @$(MKDIR_P) src/client/linux/log
+ @: > src/client/linux/log/$(am__dirstamp)
+src/client/linux/log/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) src/client/linux/log/$(DEPDIR)
+ @: > src/client/linux/log/$(DEPDIR)/$(am__dirstamp)
+src/client/linux/log/log.$(OBJEXT): \
+ src/client/linux/log/$(am__dirstamp) \
+ src/client/linux/log/$(DEPDIR)/$(am__dirstamp)
+src/client/linux/microdump_writer/$(am__dirstamp):
+ @$(MKDIR_P) src/client/linux/microdump_writer
+ @: > src/client/linux/microdump_writer/$(am__dirstamp)
+src/client/linux/microdump_writer/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) src/client/linux/microdump_writer/$(DEPDIR)
+ @: > src/client/linux/microdump_writer/$(DEPDIR)/$(am__dirstamp)
+src/client/linux/microdump_writer/microdump_writer.$(OBJEXT): \
+ src/client/linux/microdump_writer/$(am__dirstamp) \
+ src/client/linux/microdump_writer/$(DEPDIR)/$(am__dirstamp)
+src/client/linux/minidump_writer/$(am__dirstamp):
+ @$(MKDIR_P) src/client/linux/minidump_writer
+ @: > src/client/linux/minidump_writer/$(am__dirstamp)
+src/client/linux/minidump_writer/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) src/client/linux/minidump_writer/$(DEPDIR)
+ @: > src/client/linux/minidump_writer/$(DEPDIR)/$(am__dirstamp)
+src/client/linux/minidump_writer/linux_core_dumper.$(OBJEXT): \
+ src/client/linux/minidump_writer/$(am__dirstamp) \
+ src/client/linux/minidump_writer/$(DEPDIR)/$(am__dirstamp)
+src/client/linux/minidump_writer/linux_dumper.$(OBJEXT): \
+ src/client/linux/minidump_writer/$(am__dirstamp) \
+ src/client/linux/minidump_writer/$(DEPDIR)/$(am__dirstamp)
+src/client/linux/minidump_writer/linux_ptrace_dumper.$(OBJEXT): \
+ src/client/linux/minidump_writer/$(am__dirstamp) \
+ src/client/linux/minidump_writer/$(DEPDIR)/$(am__dirstamp)
+src/client/linux/minidump_writer/minidump_writer.$(OBJEXT): \
+ src/client/linux/minidump_writer/$(am__dirstamp) \
+ src/client/linux/minidump_writer/$(DEPDIR)/$(am__dirstamp)
+src/client/$(am__dirstamp):
+ @$(MKDIR_P) src/client
+ @: > src/client/$(am__dirstamp)
+src/client/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) src/client/$(DEPDIR)
+ @: > src/client/$(DEPDIR)/$(am__dirstamp)
+src/client/minidump_file_writer.$(OBJEXT): src/client/$(am__dirstamp) \
+ src/client/$(DEPDIR)/$(am__dirstamp)
+src/common/$(am__dirstamp):
+ @$(MKDIR_P) src/common
+ @: > src/common/$(am__dirstamp)
+src/common/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) src/common/$(DEPDIR)
+ @: > src/common/$(DEPDIR)/$(am__dirstamp)
+src/common/convert_UTF.$(OBJEXT): src/common/$(am__dirstamp) \
+ src/common/$(DEPDIR)/$(am__dirstamp)
+src/common/md5.$(OBJEXT): src/common/$(am__dirstamp) \
+ src/common/$(DEPDIR)/$(am__dirstamp)
+src/common/string_conversion.$(OBJEXT): src/common/$(am__dirstamp) \
+ src/common/$(DEPDIR)/$(am__dirstamp)
+src/common/linux/$(am__dirstamp):
+ @$(MKDIR_P) src/common/linux
+ @: > src/common/linux/$(am__dirstamp)
+src/common/linux/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) src/common/linux/$(DEPDIR)
+ @: > src/common/linux/$(DEPDIR)/$(am__dirstamp)
+src/common/linux/elf_core_dump.$(OBJEXT): \
+ src/common/linux/$(am__dirstamp) \
+ src/common/linux/$(DEPDIR)/$(am__dirstamp)
+src/common/linux/elfutils.$(OBJEXT): src/common/linux/$(am__dirstamp) \
+ src/common/linux/$(DEPDIR)/$(am__dirstamp)
+src/common/linux/file_id.$(OBJEXT): src/common/linux/$(am__dirstamp) \
+ src/common/linux/$(DEPDIR)/$(am__dirstamp)
+src/common/linux/guid_creator.$(OBJEXT): \
+ src/common/linux/$(am__dirstamp) \
+ src/common/linux/$(DEPDIR)/$(am__dirstamp)
+src/common/linux/linux_libc_support.$(OBJEXT): \
+ src/common/linux/$(am__dirstamp) \
+ src/common/linux/$(DEPDIR)/$(am__dirstamp)
+src/common/linux/memory_mapped_file.$(OBJEXT): \
+ src/common/linux/$(am__dirstamp) \
+ src/common/linux/$(DEPDIR)/$(am__dirstamp)
+src/common/linux/safe_readlink.$(OBJEXT): \
+ src/common/linux/$(am__dirstamp) \
+ src/common/linux/$(DEPDIR)/$(am__dirstamp)
+src/common/android/$(am__dirstamp):
+ @$(MKDIR_P) src/common/android
+ @: > src/common/android/$(am__dirstamp)
+src/common/android/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) src/common/android/$(DEPDIR)
+ @: > src/common/android/$(DEPDIR)/$(am__dirstamp)
+src/common/android/breakpad_getcontext.$(OBJEXT): \
+ src/common/android/$(am__dirstamp) \
+ src/common/android/$(DEPDIR)/$(am__dirstamp)
+src/client/linux/$(am__dirstamp):
+ @$(MKDIR_P) src/client/linux
+ @: > src/client/linux/$(am__dirstamp)
+
+src/client/linux/libbreakpad_client.a: $(src_client_linux_libbreakpad_client_a_OBJECTS) $(src_client_linux_libbreakpad_client_a_DEPENDENCIES) $(EXTRA_src_client_linux_libbreakpad_client_a_DEPENDENCIES) src/client/linux/$(am__dirstamp)
+ $(AM_V_at)-rm -f src/client/linux/libbreakpad_client.a
+ $(AM_V_AR)$(src_client_linux_libbreakpad_client_a_AR) src/client/linux/libbreakpad_client.a $(src_client_linux_libbreakpad_client_a_OBJECTS) $(src_client_linux_libbreakpad_client_a_LIBADD)
+ $(AM_V_at)$(RANLIB) src/client/linux/libbreakpad_client.a
+src/processor/$(am__dirstamp):
+ @$(MKDIR_P) src/processor
+ @: > src/processor/$(am__dirstamp)
+src/processor/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) src/processor/$(DEPDIR)
+ @: > src/processor/$(DEPDIR)/$(am__dirstamp)
+src/processor/basic_code_modules.$(OBJEXT): \
+ src/processor/$(am__dirstamp) \
+ src/processor/$(DEPDIR)/$(am__dirstamp)
+src/processor/basic_source_line_resolver.$(OBJEXT): \
+ src/processor/$(am__dirstamp) \
+ src/processor/$(DEPDIR)/$(am__dirstamp)
+src/processor/call_stack.$(OBJEXT): src/processor/$(am__dirstamp) \
+ src/processor/$(DEPDIR)/$(am__dirstamp)
+src/processor/cfi_frame_info.$(OBJEXT): src/processor/$(am__dirstamp) \
+ src/processor/$(DEPDIR)/$(am__dirstamp)
+src/processor/disassembler_x86.$(OBJEXT): \
+ src/processor/$(am__dirstamp) \
+ src/processor/$(DEPDIR)/$(am__dirstamp)
+src/processor/dump_context.$(OBJEXT): src/processor/$(am__dirstamp) \
+ src/processor/$(DEPDIR)/$(am__dirstamp)
+src/processor/dump_object.$(OBJEXT): src/processor/$(am__dirstamp) \
+ src/processor/$(DEPDIR)/$(am__dirstamp)
+src/processor/exploitability.$(OBJEXT): src/processor/$(am__dirstamp) \
+ src/processor/$(DEPDIR)/$(am__dirstamp)
+src/processor/exploitability_linux.$(OBJEXT): \
+ src/processor/$(am__dirstamp) \
+ src/processor/$(DEPDIR)/$(am__dirstamp)
+src/processor/exploitability_win.$(OBJEXT): \
+ src/processor/$(am__dirstamp) \
+ src/processor/$(DEPDIR)/$(am__dirstamp)
+src/processor/fast_source_line_resolver.$(OBJEXT): \
+ src/processor/$(am__dirstamp) \
+ src/processor/$(DEPDIR)/$(am__dirstamp)
+src/processor/logging.$(OBJEXT): src/processor/$(am__dirstamp) \
+ src/processor/$(DEPDIR)/$(am__dirstamp)
+src/processor/microdump.$(OBJEXT): src/processor/$(am__dirstamp) \
+ src/processor/$(DEPDIR)/$(am__dirstamp)
+src/processor/microdump_processor.$(OBJEXT): \
+ src/processor/$(am__dirstamp) \
+ src/processor/$(DEPDIR)/$(am__dirstamp)
+src/processor/minidump.$(OBJEXT): src/processor/$(am__dirstamp) \
+ src/processor/$(DEPDIR)/$(am__dirstamp)
+src/processor/minidump_processor.$(OBJEXT): \
+ src/processor/$(am__dirstamp) \
+ src/processor/$(DEPDIR)/$(am__dirstamp)
+src/processor/module_comparer.$(OBJEXT): \
+ src/processor/$(am__dirstamp) \
+ src/processor/$(DEPDIR)/$(am__dirstamp)
+src/processor/module_serializer.$(OBJEXT): \
+ src/processor/$(am__dirstamp) \
+ src/processor/$(DEPDIR)/$(am__dirstamp)
+src/processor/pathname_stripper.$(OBJEXT): \
+ src/processor/$(am__dirstamp) \
+ src/processor/$(DEPDIR)/$(am__dirstamp)
+src/processor/process_state.$(OBJEXT): src/processor/$(am__dirstamp) \
+ src/processor/$(DEPDIR)/$(am__dirstamp)
+src/processor/proc_maps_linux.$(OBJEXT): \
+ src/processor/$(am__dirstamp) \
+ src/processor/$(DEPDIR)/$(am__dirstamp)
+src/processor/simple_symbol_supplier.$(OBJEXT): \
+ src/processor/$(am__dirstamp) \
+ src/processor/$(DEPDIR)/$(am__dirstamp)
+src/processor/source_line_resolver_base.$(OBJEXT): \
+ src/processor/$(am__dirstamp) \
+ src/processor/$(DEPDIR)/$(am__dirstamp)
+src/processor/stack_frame_cpu.$(OBJEXT): \
+ src/processor/$(am__dirstamp) \
+ src/processor/$(DEPDIR)/$(am__dirstamp)
+src/processor/stack_frame_symbolizer.$(OBJEXT): \
+ src/processor/$(am__dirstamp) \
+ src/processor/$(DEPDIR)/$(am__dirstamp)
+src/processor/stackwalker.$(OBJEXT): src/processor/$(am__dirstamp) \
+ src/processor/$(DEPDIR)/$(am__dirstamp)
+src/processor/stackwalker_amd64.$(OBJEXT): \
+ src/processor/$(am__dirstamp) \
+ src/processor/$(DEPDIR)/$(am__dirstamp)
+src/processor/stackwalker_arm.$(OBJEXT): \
+ src/processor/$(am__dirstamp) \
+ src/processor/$(DEPDIR)/$(am__dirstamp)
+src/processor/stackwalker_arm64.$(OBJEXT): \
+ src/processor/$(am__dirstamp) \
+ src/processor/$(DEPDIR)/$(am__dirstamp)
+src/processor/stackwalker_address_list.$(OBJEXT): \
+ src/processor/$(am__dirstamp) \
+ src/processor/$(DEPDIR)/$(am__dirstamp)
+src/processor/stackwalker_mips.$(OBJEXT): \
+ src/processor/$(am__dirstamp) \
+ src/processor/$(DEPDIR)/$(am__dirstamp)
+src/processor/stackwalker_ppc.$(OBJEXT): \
+ src/processor/$(am__dirstamp) \
+ src/processor/$(DEPDIR)/$(am__dirstamp)
+src/processor/stackwalker_ppc64.$(OBJEXT): \
+ src/processor/$(am__dirstamp) \
+ src/processor/$(DEPDIR)/$(am__dirstamp)
+src/processor/stackwalker_sparc.$(OBJEXT): \
+ src/processor/$(am__dirstamp) \
+ src/processor/$(DEPDIR)/$(am__dirstamp)
+src/processor/stackwalker_x86.$(OBJEXT): \
+ src/processor/$(am__dirstamp) \
+ src/processor/$(DEPDIR)/$(am__dirstamp)
+src/processor/symbolic_constants_win.$(OBJEXT): \
+ src/processor/$(am__dirstamp) \
+ src/processor/$(DEPDIR)/$(am__dirstamp)
+src/processor/tokenize.$(OBJEXT): src/processor/$(am__dirstamp) \
+ src/processor/$(DEPDIR)/$(am__dirstamp)
+src/$(am__dirstamp):
+ @$(MKDIR_P) src
+ @: > src/$(am__dirstamp)
+
+src/libbreakpad.a: $(src_libbreakpad_a_OBJECTS) $(src_libbreakpad_a_DEPENDENCIES) $(EXTRA_src_libbreakpad_a_DEPENDENCIES) src/$(am__dirstamp)
+ $(AM_V_at)-rm -f src/libbreakpad.a
+ $(AM_V_AR)$(src_libbreakpad_a_AR) src/libbreakpad.a $(src_libbreakpad_a_OBJECTS) $(src_libbreakpad_a_LIBADD)
+ $(AM_V_at)$(RANLIB) src/libbreakpad.a
+src/testing/gtest/src/$(am__dirstamp):
+ @$(MKDIR_P) src/testing/gtest/src
+ @: > src/testing/gtest/src/$(am__dirstamp)
+src/testing/gtest/src/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) src/testing/gtest/src/$(DEPDIR)
+ @: > src/testing/gtest/src/$(DEPDIR)/$(am__dirstamp)
+src/testing/gtest/src/src_testing_libtesting_a-gtest-all.$(OBJEXT): \
+ src/testing/gtest/src/$(am__dirstamp) \
+ src/testing/gtest/src/$(DEPDIR)/$(am__dirstamp)
+src/testing/gtest/src/src_testing_libtesting_a-gtest_main.$(OBJEXT): \
+ src/testing/gtest/src/$(am__dirstamp) \
+ src/testing/gtest/src/$(DEPDIR)/$(am__dirstamp)
+src/testing/src/$(am__dirstamp):
+ @$(MKDIR_P) src/testing/src
+ @: > src/testing/src/$(am__dirstamp)
+src/testing/src/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) src/testing/src/$(DEPDIR)
+ @: > src/testing/src/$(DEPDIR)/$(am__dirstamp)
+src/testing/src/src_testing_libtesting_a-gmock-all.$(OBJEXT): \
+ src/testing/src/$(am__dirstamp) \
+ src/testing/src/$(DEPDIR)/$(am__dirstamp)
+src/testing/$(am__dirstamp):
+ @$(MKDIR_P) src/testing
+ @: > src/testing/$(am__dirstamp)
+
+src/testing/libtesting.a: $(src_testing_libtesting_a_OBJECTS) $(src_testing_libtesting_a_DEPENDENCIES) $(EXTRA_src_testing_libtesting_a_DEPENDENCIES) src/testing/$(am__dirstamp)
+ $(AM_V_at)-rm -f src/testing/libtesting.a
+ $(AM_V_AR)$(src_testing_libtesting_a_AR) src/testing/libtesting.a $(src_testing_libtesting_a_OBJECTS) $(src_testing_libtesting_a_LIBADD)
+ $(AM_V_at)$(RANLIB) src/testing/libtesting.a
+src/third_party/libdisasm/$(am__dirstamp):
+ @$(MKDIR_P) src/third_party/libdisasm
+ @: > src/third_party/libdisasm/$(am__dirstamp)
+src/third_party/libdisasm/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) src/third_party/libdisasm/$(DEPDIR)
+ @: > src/third_party/libdisasm/$(DEPDIR)/$(am__dirstamp)
+src/third_party/libdisasm/ia32_implicit.$(OBJEXT): \
+ src/third_party/libdisasm/$(am__dirstamp) \
+ src/third_party/libdisasm/$(DEPDIR)/$(am__dirstamp)
+src/third_party/libdisasm/ia32_insn.$(OBJEXT): \
+ src/third_party/libdisasm/$(am__dirstamp) \
+ src/third_party/libdisasm/$(DEPDIR)/$(am__dirstamp)
+src/third_party/libdisasm/ia32_invariant.$(OBJEXT): \
+ src/third_party/libdisasm/$(am__dirstamp) \
+ src/third_party/libdisasm/$(DEPDIR)/$(am__dirstamp)
+src/third_party/libdisasm/ia32_modrm.$(OBJEXT): \
+ src/third_party/libdisasm/$(am__dirstamp) \
+ src/third_party/libdisasm/$(DEPDIR)/$(am__dirstamp)
+src/third_party/libdisasm/ia32_opcode_tables.$(OBJEXT): \
+ src/third_party/libdisasm/$(am__dirstamp) \
+ src/third_party/libdisasm/$(DEPDIR)/$(am__dirstamp)
+src/third_party/libdisasm/ia32_operand.$(OBJEXT): \
+ src/third_party/libdisasm/$(am__dirstamp) \
+ src/third_party/libdisasm/$(DEPDIR)/$(am__dirstamp)
+src/third_party/libdisasm/ia32_reg.$(OBJEXT): \
+ src/third_party/libdisasm/$(am__dirstamp) \
+ src/third_party/libdisasm/$(DEPDIR)/$(am__dirstamp)
+src/third_party/libdisasm/ia32_settings.$(OBJEXT): \
+ src/third_party/libdisasm/$(am__dirstamp) \
+ src/third_party/libdisasm/$(DEPDIR)/$(am__dirstamp)
+src/third_party/libdisasm/x86_disasm.$(OBJEXT): \
+ src/third_party/libdisasm/$(am__dirstamp) \
+ src/third_party/libdisasm/$(DEPDIR)/$(am__dirstamp)
+src/third_party/libdisasm/x86_format.$(OBJEXT): \
+ src/third_party/libdisasm/$(am__dirstamp) \
+ src/third_party/libdisasm/$(DEPDIR)/$(am__dirstamp)
+src/third_party/libdisasm/x86_imm.$(OBJEXT): \
+ src/third_party/libdisasm/$(am__dirstamp) \
+ src/third_party/libdisasm/$(DEPDIR)/$(am__dirstamp)
+src/third_party/libdisasm/x86_insn.$(OBJEXT): \
+ src/third_party/libdisasm/$(am__dirstamp) \
+ src/third_party/libdisasm/$(DEPDIR)/$(am__dirstamp)
+src/third_party/libdisasm/x86_misc.$(OBJEXT): \
+ src/third_party/libdisasm/$(am__dirstamp) \
+ src/third_party/libdisasm/$(DEPDIR)/$(am__dirstamp)
+src/third_party/libdisasm/x86_operand_list.$(OBJEXT): \
+ src/third_party/libdisasm/$(am__dirstamp) \
+ src/third_party/libdisasm/$(DEPDIR)/$(am__dirstamp)
+
+src/third_party/libdisasm/libdisasm.a: $(src_third_party_libdisasm_libdisasm_a_OBJECTS) $(src_third_party_libdisasm_libdisasm_a_DEPENDENCIES) $(EXTRA_src_third_party_libdisasm_libdisasm_a_DEPENDENCIES) src/third_party/libdisasm/$(am__dirstamp)
+ $(AM_V_at)-rm -f src/third_party/libdisasm/libdisasm.a
+ $(AM_V_AR)$(src_third_party_libdisasm_libdisasm_a_AR) src/third_party/libdisasm/libdisasm.a $(src_third_party_libdisasm_libdisasm_a_OBJECTS) $(src_third_party_libdisasm_libdisasm_a_LIBADD)
+ $(AM_V_at)$(RANLIB) src/third_party/libdisasm/libdisasm.a
+install-binPROGRAMS: $(bin_PROGRAMS)
+ @$(NORMAL_INSTALL)
+ @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
+ if test -n "$$list"; then \
+ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \
+ fi; \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed 's/$(EXEEXT)$$//' | \
+ while read p p1; do if test -f $$p \
+ ; then echo "$$p"; echo "$$p"; else :; fi; \
+ done | \
+ sed -e 'p;s,.*/,,;n;h' \
+ -e 's|.*|.|' \
+ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
+ sed 'N;N;N;s,\n, ,g' | \
+ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
+ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
+ if ($$2 == $$4) files[d] = files[d] " " $$1; \
+ else { print "f", $$3 "/" $$4, $$1; } } \
+ END { for (d in files) print "f", d, files[d] }' | \
+ while read type dir files; do \
+ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
+ test -z "$$files" || { \
+ echo " $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \
+ $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \
+ } \
+ ; done
+
+uninstall-binPROGRAMS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
+ files=`for p in $$list; do echo "$$p"; done | \
+ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
+ -e 's/$$/$(EXEEXT)/' \
+ `; \
+ test -n "$$list" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(bindir)" && rm -f $$files
+
+clean-binPROGRAMS:
+ -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
+
+clean-checkPROGRAMS:
+ -test -z "$(check_PROGRAMS)" || rm -f $(check_PROGRAMS)
+
+clean-noinstPROGRAMS:
+ -test -z "$(noinst_PROGRAMS)" || rm -f $(noinst_PROGRAMS)
+
+src/client/linux/linux_client_unittest$(EXEEXT): $(src_client_linux_linux_client_unittest_OBJECTS) $(src_client_linux_linux_client_unittest_DEPENDENCIES) $(EXTRA_src_client_linux_linux_client_unittest_DEPENDENCIES) src/client/linux/$(am__dirstamp)
+ @rm -f src/client/linux/linux_client_unittest$(EXEEXT)
+ $(AM_V_CCLD)$(src_client_linux_linux_client_unittest_LINK) $(src_client_linux_linux_client_unittest_OBJECTS) $(src_client_linux_linux_client_unittest_LDADD) $(LIBS)
+src/testing/gtest/src/src_client_linux_linux_client_unittest_shlib-gtest-all.$(OBJEXT): \
+ src/testing/gtest/src/$(am__dirstamp) \
+ src/testing/gtest/src/$(DEPDIR)/$(am__dirstamp)
+src/testing/gtest/src/src_client_linux_linux_client_unittest_shlib-gtest_main.$(OBJEXT): \
+ src/testing/gtest/src/$(am__dirstamp) \
+ src/testing/gtest/src/$(DEPDIR)/$(am__dirstamp)
+src/testing/src/src_client_linux_linux_client_unittest_shlib-gmock-all.$(OBJEXT): \
+ src/testing/src/$(am__dirstamp) \
+ src/testing/src/$(DEPDIR)/$(am__dirstamp)
+src/client/linux/handler/src_client_linux_linux_client_unittest_shlib-exception_handler_unittest.$(OBJEXT): \
+ src/client/linux/handler/$(am__dirstamp) \
+ src/client/linux/handler/$(DEPDIR)/$(am__dirstamp)
+src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-directory_reader_unittest.$(OBJEXT): \
+ src/client/linux/minidump_writer/$(am__dirstamp) \
+ src/client/linux/minidump_writer/$(DEPDIR)/$(am__dirstamp)
+src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-cpu_set_unittest.$(OBJEXT): \
+ src/client/linux/minidump_writer/$(am__dirstamp) \
+ src/client/linux/minidump_writer/$(DEPDIR)/$(am__dirstamp)
+src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-line_reader_unittest.$(OBJEXT): \
+ src/client/linux/minidump_writer/$(am__dirstamp) \
+ src/client/linux/minidump_writer/$(DEPDIR)/$(am__dirstamp)
+src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-linux_core_dumper.$(OBJEXT): \
+ src/client/linux/minidump_writer/$(am__dirstamp) \
+ src/client/linux/minidump_writer/$(DEPDIR)/$(am__dirstamp)
+src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-linux_core_dumper_unittest.$(OBJEXT): \
+ src/client/linux/minidump_writer/$(am__dirstamp) \
+ src/client/linux/minidump_writer/$(DEPDIR)/$(am__dirstamp)
+src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-linux_ptrace_dumper_unittest.$(OBJEXT): \
+ src/client/linux/minidump_writer/$(am__dirstamp) \
+ src/client/linux/minidump_writer/$(DEPDIR)/$(am__dirstamp)
+src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-minidump_writer_unittest.$(OBJEXT): \
+ src/client/linux/minidump_writer/$(am__dirstamp) \
+ src/client/linux/minidump_writer/$(DEPDIR)/$(am__dirstamp)
+src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-minidump_writer_unittest_utils.$(OBJEXT): \
+ src/client/linux/minidump_writer/$(am__dirstamp) \
+ src/client/linux/minidump_writer/$(DEPDIR)/$(am__dirstamp)
+src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-proc_cpuinfo_reader_unittest.$(OBJEXT): \
+ src/client/linux/minidump_writer/$(am__dirstamp) \
+ src/client/linux/minidump_writer/$(DEPDIR)/$(am__dirstamp)
+src/common/linux/src_client_linux_linux_client_unittest_shlib-elf_core_dump.$(OBJEXT): \
+ src/common/linux/$(am__dirstamp) \
+ src/common/linux/$(DEPDIR)/$(am__dirstamp)
+src/common/linux/src_client_linux_linux_client_unittest_shlib-linux_libc_support_unittest.$(OBJEXT): \
+ src/common/linux/$(am__dirstamp) \
+ src/common/linux/$(DEPDIR)/$(am__dirstamp)
+src/common/linux/tests/$(am__dirstamp):
+ @$(MKDIR_P) src/common/linux/tests
+ @: > src/common/linux/tests/$(am__dirstamp)
+src/common/linux/tests/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) src/common/linux/tests/$(DEPDIR)
+ @: > src/common/linux/tests/$(DEPDIR)/$(am__dirstamp)
+src/common/linux/tests/src_client_linux_linux_client_unittest_shlib-crash_generator.$(OBJEXT): \
+ src/common/linux/tests/$(am__dirstamp) \
+ src/common/linux/tests/$(DEPDIR)/$(am__dirstamp)
+src/common/src_client_linux_linux_client_unittest_shlib-memory_allocator_unittest.$(OBJEXT): \
+ src/common/$(am__dirstamp) \
+ src/common/$(DEPDIR)/$(am__dirstamp)
+src/common/tests/$(am__dirstamp):
+ @$(MKDIR_P) src/common/tests
+ @: > src/common/tests/$(am__dirstamp)
+src/common/tests/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) src/common/tests/$(DEPDIR)
+ @: > src/common/tests/$(DEPDIR)/$(am__dirstamp)
+src/common/tests/src_client_linux_linux_client_unittest_shlib-file_utils.$(OBJEXT): \
+ src/common/tests/$(am__dirstamp) \
+ src/common/tests/$(DEPDIR)/$(am__dirstamp)
+src/processor/src_client_linux_linux_client_unittest_shlib-basic_code_modules.$(OBJEXT): \
+ src/processor/$(am__dirstamp) \
+ src/processor/$(DEPDIR)/$(am__dirstamp)
+src/processor/src_client_linux_linux_client_unittest_shlib-dump_context.$(OBJEXT): \
+ src/processor/$(am__dirstamp) \
+ src/processor/$(DEPDIR)/$(am__dirstamp)
+src/processor/src_client_linux_linux_client_unittest_shlib-dump_object.$(OBJEXT): \
+ src/processor/$(am__dirstamp) \
+ src/processor/$(DEPDIR)/$(am__dirstamp)
+src/processor/src_client_linux_linux_client_unittest_shlib-logging.$(OBJEXT): \
+ src/processor/$(am__dirstamp) \
+ src/processor/$(DEPDIR)/$(am__dirstamp)
+src/processor/src_client_linux_linux_client_unittest_shlib-minidump.$(OBJEXT): \
+ src/processor/$(am__dirstamp) \
+ src/processor/$(DEPDIR)/$(am__dirstamp)
+src/processor/src_client_linux_linux_client_unittest_shlib-pathname_stripper.$(OBJEXT): \
+ src/processor/$(am__dirstamp) \
+ src/processor/$(DEPDIR)/$(am__dirstamp)
+src/processor/src_client_linux_linux_client_unittest_shlib-proc_maps_linux.$(OBJEXT): \
+ src/processor/$(am__dirstamp) \
+ src/processor/$(DEPDIR)/$(am__dirstamp)
+src/common/android/src_client_linux_linux_client_unittest_shlib-breakpad_getcontext.$(OBJEXT): \
+ src/common/android/$(am__dirstamp) \
+ src/common/android/$(DEPDIR)/$(am__dirstamp)
+src/client/linux/microdump_writer/src_client_linux_linux_client_unittest_shlib-microdump_writer_unittest.$(OBJEXT): \
+ src/client/linux/microdump_writer/$(am__dirstamp) \
+ src/client/linux/microdump_writer/$(DEPDIR)/$(am__dirstamp)
+src/common/android/src_client_linux_linux_client_unittest_shlib-breakpad_getcontext_unittest.$(OBJEXT): \
+ src/common/android/$(am__dirstamp) \
+ src/common/android/$(DEPDIR)/$(am__dirstamp)
+
+src/client/linux/linux_client_unittest_shlib$(EXEEXT): $(src_client_linux_linux_client_unittest_shlib_OBJECTS) $(src_client_linux_linux_client_unittest_shlib_DEPENDENCIES) $(EXTRA_src_client_linux_linux_client_unittest_shlib_DEPENDENCIES) src/client/linux/$(am__dirstamp)
+ @rm -f src/client/linux/linux_client_unittest_shlib$(EXEEXT)
+ $(AM_V_CXXLD)$(src_client_linux_linux_client_unittest_shlib_LINK) $(src_client_linux_linux_client_unittest_shlib_OBJECTS) $(src_client_linux_linux_client_unittest_shlib_LDADD) $(LIBS)
+src/client/linux/minidump_writer/src_client_linux_linux_dumper_unittest_helper-linux_dumper_unittest_helper.$(OBJEXT): \
+ src/client/linux/minidump_writer/$(am__dirstamp) \
+ src/client/linux/minidump_writer/$(DEPDIR)/$(am__dirstamp)
+
+src/client/linux/linux_dumper_unittest_helper$(EXEEXT): $(src_client_linux_linux_dumper_unittest_helper_OBJECTS) $(src_client_linux_linux_dumper_unittest_helper_DEPENDENCIES) $(EXTRA_src_client_linux_linux_dumper_unittest_helper_DEPENDENCIES) src/client/linux/$(am__dirstamp)
+ @rm -f src/client/linux/linux_dumper_unittest_helper$(EXEEXT)
+ $(AM_V_CXXLD)$(src_client_linux_linux_dumper_unittest_helper_LINK) $(src_client_linux_linux_dumper_unittest_helper_OBJECTS) $(src_client_linux_linux_dumper_unittest_helper_LDADD) $(LIBS)
+src/common/src_common_dumper_unittest-byte_cursor_unittest.$(OBJEXT): \
+ src/common/$(am__dirstamp) \
+ src/common/$(DEPDIR)/$(am__dirstamp)
+src/common/src_common_dumper_unittest-dwarf_cfi_to_module.$(OBJEXT): \
+ src/common/$(am__dirstamp) \
+ src/common/$(DEPDIR)/$(am__dirstamp)
+src/common/src_common_dumper_unittest-dwarf_cfi_to_module_unittest.$(OBJEXT): \
+ src/common/$(am__dirstamp) \
+ src/common/$(DEPDIR)/$(am__dirstamp)
+src/common/src_common_dumper_unittest-dwarf_cu_to_module.$(OBJEXT): \
+ src/common/$(am__dirstamp) \
+ src/common/$(DEPDIR)/$(am__dirstamp)
+src/common/src_common_dumper_unittest-dwarf_cu_to_module_unittest.$(OBJEXT): \
+ src/common/$(am__dirstamp) \
+ src/common/$(DEPDIR)/$(am__dirstamp)
+src/common/src_common_dumper_unittest-dwarf_line_to_module.$(OBJEXT): \
+ src/common/$(am__dirstamp) \
+ src/common/$(DEPDIR)/$(am__dirstamp)
+src/common/src_common_dumper_unittest-dwarf_line_to_module_unittest.$(OBJEXT): \
+ src/common/$(am__dirstamp) \
+ src/common/$(DEPDIR)/$(am__dirstamp)
+src/common/src_common_dumper_unittest-language.$(OBJEXT): \
+ src/common/$(am__dirstamp) \
+ src/common/$(DEPDIR)/$(am__dirstamp)
+src/common/src_common_dumper_unittest-memory_range_unittest.$(OBJEXT): \
+ src/common/$(am__dirstamp) \
+ src/common/$(DEPDIR)/$(am__dirstamp)
+src/common/src_common_dumper_unittest-module.$(OBJEXT): \
+ src/common/$(am__dirstamp) \
+ src/common/$(DEPDIR)/$(am__dirstamp)
+src/common/src_common_dumper_unittest-module_unittest.$(OBJEXT): \
+ src/common/$(am__dirstamp) \
+ src/common/$(DEPDIR)/$(am__dirstamp)
+src/common/src_common_dumper_unittest-stabs_reader.$(OBJEXT): \
+ src/common/$(am__dirstamp) \
+ src/common/$(DEPDIR)/$(am__dirstamp)
+src/common/src_common_dumper_unittest-stabs_reader_unittest.$(OBJEXT): \
+ src/common/$(am__dirstamp) \
+ src/common/$(DEPDIR)/$(am__dirstamp)
+src/common/src_common_dumper_unittest-stabs_to_module.$(OBJEXT): \
+ src/common/$(am__dirstamp) \
+ src/common/$(DEPDIR)/$(am__dirstamp)
+src/common/src_common_dumper_unittest-stabs_to_module_unittest.$(OBJEXT): \
+ src/common/$(am__dirstamp) \
+ src/common/$(DEPDIR)/$(am__dirstamp)
+src/common/src_common_dumper_unittest-test_assembler.$(OBJEXT): \
+ src/common/$(am__dirstamp) \
+ src/common/$(DEPDIR)/$(am__dirstamp)
+src/common/dwarf/$(am__dirstamp):
+ @$(MKDIR_P) src/common/dwarf
+ @: > src/common/dwarf/$(am__dirstamp)
+src/common/dwarf/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) src/common/dwarf/$(DEPDIR)
+ @: > src/common/dwarf/$(DEPDIR)/$(am__dirstamp)
+src/common/dwarf/src_common_dumper_unittest-bytereader.$(OBJEXT): \
+ src/common/dwarf/$(am__dirstamp) \
+ src/common/dwarf/$(DEPDIR)/$(am__dirstamp)
+src/common/dwarf/src_common_dumper_unittest-bytereader_unittest.$(OBJEXT): \
+ src/common/dwarf/$(am__dirstamp) \
+ src/common/dwarf/$(DEPDIR)/$(am__dirstamp)
+src/common/dwarf/src_common_dumper_unittest-cfi_assembler.$(OBJEXT): \
+ src/common/dwarf/$(am__dirstamp) \
+ src/common/dwarf/$(DEPDIR)/$(am__dirstamp)
+src/common/dwarf/src_common_dumper_unittest-dwarf2diehandler.$(OBJEXT): \
+ src/common/dwarf/$(am__dirstamp) \
+ src/common/dwarf/$(DEPDIR)/$(am__dirstamp)
+src/common/dwarf/src_common_dumper_unittest-dwarf2diehandler_unittest.$(OBJEXT): \
+ src/common/dwarf/$(am__dirstamp) \
+ src/common/dwarf/$(DEPDIR)/$(am__dirstamp)
+src/common/dwarf/src_common_dumper_unittest-dwarf2reader.$(OBJEXT): \
+ src/common/dwarf/$(am__dirstamp) \
+ src/common/dwarf/$(DEPDIR)/$(am__dirstamp)
+src/common/dwarf/src_common_dumper_unittest-elf_reader.$(OBJEXT): \
+ src/common/dwarf/$(am__dirstamp) \
+ src/common/dwarf/$(DEPDIR)/$(am__dirstamp)
+src/common/dwarf/src_common_dumper_unittest-dwarf2reader_cfi_unittest.$(OBJEXT): \
+ src/common/dwarf/$(am__dirstamp) \
+ src/common/dwarf/$(DEPDIR)/$(am__dirstamp)
+src/common/dwarf/src_common_dumper_unittest-dwarf2reader_die_unittest.$(OBJEXT): \
+ src/common/dwarf/$(am__dirstamp) \
+ src/common/dwarf/$(DEPDIR)/$(am__dirstamp)
+src/common/linux/src_common_dumper_unittest-crc32.$(OBJEXT): \
+ src/common/linux/$(am__dirstamp) \
+ src/common/linux/$(DEPDIR)/$(am__dirstamp)
+src/common/linux/src_common_dumper_unittest-dump_symbols.$(OBJEXT): \
+ src/common/linux/$(am__dirstamp) \
+ src/common/linux/$(DEPDIR)/$(am__dirstamp)
+src/common/linux/src_common_dumper_unittest-dump_symbols_unittest.$(OBJEXT): \
+ src/common/linux/$(am__dirstamp) \
+ src/common/linux/$(DEPDIR)/$(am__dirstamp)
+src/common/linux/src_common_dumper_unittest-elf_core_dump.$(OBJEXT): \
+ src/common/linux/$(am__dirstamp) \
+ src/common/linux/$(DEPDIR)/$(am__dirstamp)
+src/common/linux/src_common_dumper_unittest-elf_core_dump_unittest.$(OBJEXT): \
+ src/common/linux/$(am__dirstamp) \
+ src/common/linux/$(DEPDIR)/$(am__dirstamp)
+src/common/linux/src_common_dumper_unittest-elf_symbols_to_module.$(OBJEXT): \
+ src/common/linux/$(am__dirstamp) \
+ src/common/linux/$(DEPDIR)/$(am__dirstamp)
+src/common/linux/src_common_dumper_unittest-elf_symbols_to_module_unittest.$(OBJEXT): \
+ src/common/linux/$(am__dirstamp) \
+ src/common/linux/$(DEPDIR)/$(am__dirstamp)
+src/common/linux/src_common_dumper_unittest-elfutils.$(OBJEXT): \
+ src/common/linux/$(am__dirstamp) \
+ src/common/linux/$(DEPDIR)/$(am__dirstamp)
+src/common/linux/src_common_dumper_unittest-file_id.$(OBJEXT): \
+ src/common/linux/$(am__dirstamp) \
+ src/common/linux/$(DEPDIR)/$(am__dirstamp)
+src/common/linux/src_common_dumper_unittest-file_id_unittest.$(OBJEXT): \
+ src/common/linux/$(am__dirstamp) \
+ src/common/linux/$(DEPDIR)/$(am__dirstamp)
+src/common/linux/src_common_dumper_unittest-linux_libc_support.$(OBJEXT): \
+ src/common/linux/$(am__dirstamp) \
+ src/common/linux/$(DEPDIR)/$(am__dirstamp)
+src/common/linux/src_common_dumper_unittest-memory_mapped_file.$(OBJEXT): \
+ src/common/linux/$(am__dirstamp) \
+ src/common/linux/$(DEPDIR)/$(am__dirstamp)
+src/common/linux/src_common_dumper_unittest-memory_mapped_file_unittest.$(OBJEXT): \
+ src/common/linux/$(am__dirstamp) \
+ src/common/linux/$(DEPDIR)/$(am__dirstamp)
+src/common/linux/src_common_dumper_unittest-safe_readlink.$(OBJEXT): \
+ src/common/linux/$(am__dirstamp) \
+ src/common/linux/$(DEPDIR)/$(am__dirstamp)
+src/common/linux/src_common_dumper_unittest-safe_readlink_unittest.$(OBJEXT): \
+ src/common/linux/$(am__dirstamp) \
+ src/common/linux/$(DEPDIR)/$(am__dirstamp)
+src/common/linux/src_common_dumper_unittest-synth_elf.$(OBJEXT): \
+ src/common/linux/$(am__dirstamp) \
+ src/common/linux/$(DEPDIR)/$(am__dirstamp)
+src/common/linux/src_common_dumper_unittest-synth_elf_unittest.$(OBJEXT): \
+ src/common/linux/$(am__dirstamp) \
+ src/common/linux/$(DEPDIR)/$(am__dirstamp)
+src/common/linux/tests/src_common_dumper_unittest-crash_generator.$(OBJEXT): \
+ src/common/linux/tests/$(am__dirstamp) \
+ src/common/linux/tests/$(DEPDIR)/$(am__dirstamp)
+src/common/tests/src_common_dumper_unittest-file_utils.$(OBJEXT): \
+ src/common/tests/$(am__dirstamp) \
+ src/common/tests/$(DEPDIR)/$(am__dirstamp)
+
+src/common/dumper_unittest$(EXEEXT): $(src_common_dumper_unittest_OBJECTS) $(src_common_dumper_unittest_DEPENDENCIES) $(EXTRA_src_common_dumper_unittest_DEPENDENCIES) src/common/$(am__dirstamp)
+ @rm -f src/common/dumper_unittest$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(src_common_dumper_unittest_OBJECTS) $(src_common_dumper_unittest_LDADD) $(LIBS)
+src/common/src_common_mac_macho_reader_unittest-dwarf_cfi_to_module.$(OBJEXT): \
+ src/common/$(am__dirstamp) \
+ src/common/$(DEPDIR)/$(am__dirstamp)
+src/common/src_common_mac_macho_reader_unittest-dwarf_cu_to_module.$(OBJEXT): \
+ src/common/$(am__dirstamp) \
+ src/common/$(DEPDIR)/$(am__dirstamp)
+src/common/src_common_mac_macho_reader_unittest-dwarf_line_to_module.$(OBJEXT): \
+ src/common/$(am__dirstamp) \
+ src/common/$(DEPDIR)/$(am__dirstamp)
+src/common/src_common_mac_macho_reader_unittest-language.$(OBJEXT): \
+ src/common/$(am__dirstamp) \
+ src/common/$(DEPDIR)/$(am__dirstamp)
+src/common/src_common_mac_macho_reader_unittest-md5.$(OBJEXT): \
+ src/common/$(am__dirstamp) \
+ src/common/$(DEPDIR)/$(am__dirstamp)
+src/common/src_common_mac_macho_reader_unittest-module.$(OBJEXT): \
+ src/common/$(am__dirstamp) \
+ src/common/$(DEPDIR)/$(am__dirstamp)
+src/common/src_common_mac_macho_reader_unittest-stabs_reader.$(OBJEXT): \
+ src/common/$(am__dirstamp) \
+ src/common/$(DEPDIR)/$(am__dirstamp)
+src/common/src_common_mac_macho_reader_unittest-stabs_to_module.$(OBJEXT): \
+ src/common/$(am__dirstamp) \
+ src/common/$(DEPDIR)/$(am__dirstamp)
+src/common/src_common_mac_macho_reader_unittest-test_assembler.$(OBJEXT): \
+ src/common/$(am__dirstamp) \
+ src/common/$(DEPDIR)/$(am__dirstamp)
+src/common/dwarf/src_common_mac_macho_reader_unittest-bytereader.$(OBJEXT): \
+ src/common/dwarf/$(am__dirstamp) \
+ src/common/dwarf/$(DEPDIR)/$(am__dirstamp)
+src/common/dwarf/src_common_mac_macho_reader_unittest-cfi_assembler.$(OBJEXT): \
+ src/common/dwarf/$(am__dirstamp) \
+ src/common/dwarf/$(DEPDIR)/$(am__dirstamp)
+src/common/dwarf/src_common_mac_macho_reader_unittest-dwarf2diehandler.$(OBJEXT): \
+ src/common/dwarf/$(am__dirstamp) \
+ src/common/dwarf/$(DEPDIR)/$(am__dirstamp)
+src/common/dwarf/src_common_mac_macho_reader_unittest-dwarf2reader.$(OBJEXT): \
+ src/common/dwarf/$(am__dirstamp) \
+ src/common/dwarf/$(DEPDIR)/$(am__dirstamp)
+src/common/dwarf/src_common_mac_macho_reader_unittest-elf_reader.$(OBJEXT): \
+ src/common/dwarf/$(am__dirstamp) \
+ src/common/dwarf/$(DEPDIR)/$(am__dirstamp)
+src/common/mac/$(am__dirstamp):
+ @$(MKDIR_P) src/common/mac
+ @: > src/common/mac/$(am__dirstamp)
+src/common/mac/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) src/common/mac/$(DEPDIR)
+ @: > src/common/mac/$(DEPDIR)/$(am__dirstamp)
+src/common/mac/src_common_mac_macho_reader_unittest-arch_utilities.$(OBJEXT): \
+ src/common/mac/$(am__dirstamp) \
+ src/common/mac/$(DEPDIR)/$(am__dirstamp)
+src/common/mac/src_common_mac_macho_reader_unittest-file_id.$(OBJEXT): \
+ src/common/mac/$(am__dirstamp) \
+ src/common/mac/$(DEPDIR)/$(am__dirstamp)
+src/common/mac/src_common_mac_macho_reader_unittest-macho_id.$(OBJEXT): \
+ src/common/mac/$(am__dirstamp) \
+ src/common/mac/$(DEPDIR)/$(am__dirstamp)
+src/common/mac/src_common_mac_macho_reader_unittest-macho_reader.$(OBJEXT): \
+ src/common/mac/$(am__dirstamp) \
+ src/common/mac/$(DEPDIR)/$(am__dirstamp)
+src/common/mac/src_common_mac_macho_reader_unittest-macho_reader_unittest.$(OBJEXT): \
+ src/common/mac/$(am__dirstamp) \
+ src/common/mac/$(DEPDIR)/$(am__dirstamp)
+src/common/mac/src_common_mac_macho_reader_unittest-macho_utilities.$(OBJEXT): \
+ src/common/mac/$(am__dirstamp) \
+ src/common/mac/$(DEPDIR)/$(am__dirstamp)
+src/common/mac/src_common_mac_macho_reader_unittest-macho_walker.$(OBJEXT): \
+ src/common/mac/$(am__dirstamp) \
+ src/common/mac/$(DEPDIR)/$(am__dirstamp)
+src/common/tests/src_common_mac_macho_reader_unittest-file_utils.$(OBJEXT): \
+ src/common/tests/$(am__dirstamp) \
+ src/common/tests/$(DEPDIR)/$(am__dirstamp)
+
+src/common/mac/macho_reader_unittest$(EXEEXT): $(src_common_mac_macho_reader_unittest_OBJECTS) $(src_common_mac_macho_reader_unittest_DEPENDENCIES) $(EXTRA_src_common_mac_macho_reader_unittest_DEPENDENCIES) src/common/mac/$(am__dirstamp)
+ @rm -f src/common/mac/macho_reader_unittest$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(src_common_mac_macho_reader_unittest_OBJECTS) $(src_common_mac_macho_reader_unittest_LDADD) $(LIBS)
+src/common/src_common_test_assembler_unittest-test_assembler.$(OBJEXT): \
+ src/common/$(am__dirstamp) \
+ src/common/$(DEPDIR)/$(am__dirstamp)
+src/common/src_common_test_assembler_unittest-test_assembler_unittest.$(OBJEXT): \
+ src/common/$(am__dirstamp) \
+ src/common/$(DEPDIR)/$(am__dirstamp)
+
+src/common/test_assembler_unittest$(EXEEXT): $(src_common_test_assembler_unittest_OBJECTS) $(src_common_test_assembler_unittest_DEPENDENCIES) $(EXTRA_src_common_test_assembler_unittest_DEPENDENCIES) src/common/$(am__dirstamp)
+ @rm -f src/common/test_assembler_unittest$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(src_common_test_assembler_unittest_OBJECTS) $(src_common_test_assembler_unittest_LDADD) $(LIBS)
+src/processor/address_map_unittest.$(OBJEXT): \
+ src/processor/$(am__dirstamp) \
+ src/processor/$(DEPDIR)/$(am__dirstamp)
+
+src/processor/address_map_unittest$(EXEEXT): $(src_processor_address_map_unittest_OBJECTS) $(src_processor_address_map_unittest_DEPENDENCIES) $(EXTRA_src_processor_address_map_unittest_DEPENDENCIES) src/processor/$(am__dirstamp)
+ @rm -f src/processor/address_map_unittest$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(src_processor_address_map_unittest_OBJECTS) $(src_processor_address_map_unittest_LDADD) $(LIBS)
+src/processor/src_processor_basic_source_line_resolver_unittest-basic_source_line_resolver_unittest.$(OBJEXT): \
+ src/processor/$(am__dirstamp) \
+ src/processor/$(DEPDIR)/$(am__dirstamp)
+
+src/processor/basic_source_line_resolver_unittest$(EXEEXT): $(src_processor_basic_source_line_resolver_unittest_OBJECTS) $(src_processor_basic_source_line_resolver_unittest_DEPENDENCIES) $(EXTRA_src_processor_basic_source_line_resolver_unittest_DEPENDENCIES) src/processor/$(am__dirstamp)
+ @rm -f src/processor/basic_source_line_resolver_unittest$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(src_processor_basic_source_line_resolver_unittest_OBJECTS) $(src_processor_basic_source_line_resolver_unittest_LDADD) $(LIBS)
+src/processor/src_processor_cfi_frame_info_unittest-cfi_frame_info_unittest.$(OBJEXT): \
+ src/processor/$(am__dirstamp) \
+ src/processor/$(DEPDIR)/$(am__dirstamp)
+
+src/processor/cfi_frame_info_unittest$(EXEEXT): $(src_processor_cfi_frame_info_unittest_OBJECTS) $(src_processor_cfi_frame_info_unittest_DEPENDENCIES) $(EXTRA_src_processor_cfi_frame_info_unittest_DEPENDENCIES) src/processor/$(am__dirstamp)
+ @rm -f src/processor/cfi_frame_info_unittest$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(src_processor_cfi_frame_info_unittest_OBJECTS) $(src_processor_cfi_frame_info_unittest_LDADD) $(LIBS)
+src/processor/contained_range_map_unittest.$(OBJEXT): \
+ src/processor/$(am__dirstamp) \
+ src/processor/$(DEPDIR)/$(am__dirstamp)
+
+src/processor/contained_range_map_unittest$(EXEEXT): $(src_processor_contained_range_map_unittest_OBJECTS) $(src_processor_contained_range_map_unittest_DEPENDENCIES) $(EXTRA_src_processor_contained_range_map_unittest_DEPENDENCIES) src/processor/$(am__dirstamp)
+ @rm -f src/processor/contained_range_map_unittest$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(src_processor_contained_range_map_unittest_OBJECTS) $(src_processor_contained_range_map_unittest_LDADD) $(LIBS)
+src/processor/src_processor_disassembler_x86_unittest-disassembler_x86_unittest.$(OBJEXT): \
+ src/processor/$(am__dirstamp) \
+ src/processor/$(DEPDIR)/$(am__dirstamp)
+
+src/processor/disassembler_x86_unittest$(EXEEXT): $(src_processor_disassembler_x86_unittest_OBJECTS) $(src_processor_disassembler_x86_unittest_DEPENDENCIES) $(EXTRA_src_processor_disassembler_x86_unittest_DEPENDENCIES) src/processor/$(am__dirstamp)
+ @rm -f src/processor/disassembler_x86_unittest$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(src_processor_disassembler_x86_unittest_OBJECTS) $(src_processor_disassembler_x86_unittest_LDADD) $(LIBS)
+src/processor/src_processor_exploitability_unittest-exploitability_unittest.$(OBJEXT): \
+ src/processor/$(am__dirstamp) \
+ src/processor/$(DEPDIR)/$(am__dirstamp)
+
+src/processor/exploitability_unittest$(EXEEXT): $(src_processor_exploitability_unittest_OBJECTS) $(src_processor_exploitability_unittest_DEPENDENCIES) $(EXTRA_src_processor_exploitability_unittest_DEPENDENCIES) src/processor/$(am__dirstamp)
+ @rm -f src/processor/exploitability_unittest$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(src_processor_exploitability_unittest_OBJECTS) $(src_processor_exploitability_unittest_LDADD) $(LIBS)
+src/processor/src_processor_fast_source_line_resolver_unittest-fast_source_line_resolver_unittest.$(OBJEXT): \
+ src/processor/$(am__dirstamp) \
+ src/processor/$(DEPDIR)/$(am__dirstamp)
+
+src/processor/fast_source_line_resolver_unittest$(EXEEXT): $(src_processor_fast_source_line_resolver_unittest_OBJECTS) $(src_processor_fast_source_line_resolver_unittest_DEPENDENCIES) $(EXTRA_src_processor_fast_source_line_resolver_unittest_DEPENDENCIES) src/processor/$(am__dirstamp)
+ @rm -f src/processor/fast_source_line_resolver_unittest$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(src_processor_fast_source_line_resolver_unittest_OBJECTS) $(src_processor_fast_source_line_resolver_unittest_LDADD) $(LIBS)
+src/processor/src_processor_map_serializers_unittest-map_serializers_unittest.$(OBJEXT): \
+ src/processor/$(am__dirstamp) \
+ src/processor/$(DEPDIR)/$(am__dirstamp)
+
+src/processor/map_serializers_unittest$(EXEEXT): $(src_processor_map_serializers_unittest_OBJECTS) $(src_processor_map_serializers_unittest_DEPENDENCIES) $(EXTRA_src_processor_map_serializers_unittest_DEPENDENCIES) src/processor/$(am__dirstamp)
+ @rm -f src/processor/map_serializers_unittest$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(src_processor_map_serializers_unittest_OBJECTS) $(src_processor_map_serializers_unittest_LDADD) $(LIBS)
+src/processor/src_processor_microdump_processor_unittest-microdump_processor_unittest.$(OBJEXT): \
+ src/processor/$(am__dirstamp) \
+ src/processor/$(DEPDIR)/$(am__dirstamp)
+
+src/processor/microdump_processor_unittest$(EXEEXT): $(src_processor_microdump_processor_unittest_OBJECTS) $(src_processor_microdump_processor_unittest_DEPENDENCIES) $(EXTRA_src_processor_microdump_processor_unittest_DEPENDENCIES) src/processor/$(am__dirstamp)
+ @rm -f src/processor/microdump_processor_unittest$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(src_processor_microdump_processor_unittest_OBJECTS) $(src_processor_microdump_processor_unittest_LDADD) $(LIBS)
+src/processor/microdump_stackwalk.$(OBJEXT): \
+ src/processor/$(am__dirstamp) \
+ src/processor/$(DEPDIR)/$(am__dirstamp)
+
+src/processor/microdump_stackwalk$(EXEEXT): $(src_processor_microdump_stackwalk_OBJECTS) $(src_processor_microdump_stackwalk_DEPENDENCIES) $(EXTRA_src_processor_microdump_stackwalk_DEPENDENCIES) src/processor/$(am__dirstamp)
+ @rm -f src/processor/microdump_stackwalk$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(src_processor_microdump_stackwalk_OBJECTS) $(src_processor_microdump_stackwalk_LDADD) $(LIBS)
+src/processor/minidump_dump.$(OBJEXT): src/processor/$(am__dirstamp) \
+ src/processor/$(DEPDIR)/$(am__dirstamp)
+
+src/processor/minidump_dump$(EXEEXT): $(src_processor_minidump_dump_OBJECTS) $(src_processor_minidump_dump_DEPENDENCIES) $(EXTRA_src_processor_minidump_dump_DEPENDENCIES) src/processor/$(am__dirstamp)
+ @rm -f src/processor/minidump_dump$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(src_processor_minidump_dump_OBJECTS) $(src_processor_minidump_dump_LDADD) $(LIBS)
+src/processor/src_processor_minidump_processor_unittest-minidump_processor_unittest.$(OBJEXT): \
+ src/processor/$(am__dirstamp) \
+ src/processor/$(DEPDIR)/$(am__dirstamp)
+
+src/processor/minidump_processor_unittest$(EXEEXT): $(src_processor_minidump_processor_unittest_OBJECTS) $(src_processor_minidump_processor_unittest_DEPENDENCIES) $(EXTRA_src_processor_minidump_processor_unittest_DEPENDENCIES) src/processor/$(am__dirstamp)
+ @rm -f src/processor/minidump_processor_unittest$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(src_processor_minidump_processor_unittest_OBJECTS) $(src_processor_minidump_processor_unittest_LDADD) $(LIBS)
+src/processor/minidump_stackwalk.$(OBJEXT): \
+ src/processor/$(am__dirstamp) \
+ src/processor/$(DEPDIR)/$(am__dirstamp)
+
+src/processor/minidump_stackwalk$(EXEEXT): $(src_processor_minidump_stackwalk_OBJECTS) $(src_processor_minidump_stackwalk_DEPENDENCIES) $(EXTRA_src_processor_minidump_stackwalk_DEPENDENCIES) src/processor/$(am__dirstamp)
+ @rm -f src/processor/minidump_stackwalk$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(src_processor_minidump_stackwalk_OBJECTS) $(src_processor_minidump_stackwalk_LDADD) $(LIBS)
+src/common/src_processor_minidump_unittest-test_assembler.$(OBJEXT): \
+ src/common/$(am__dirstamp) \
+ src/common/$(DEPDIR)/$(am__dirstamp)
+src/processor/src_processor_minidump_unittest-minidump_unittest.$(OBJEXT): \
+ src/processor/$(am__dirstamp) \
+ src/processor/$(DEPDIR)/$(am__dirstamp)
+src/processor/src_processor_minidump_unittest-synth_minidump.$(OBJEXT): \
+ src/processor/$(am__dirstamp) \
+ src/processor/$(DEPDIR)/$(am__dirstamp)
+
+src/processor/minidump_unittest$(EXEEXT): $(src_processor_minidump_unittest_OBJECTS) $(src_processor_minidump_unittest_DEPENDENCIES) $(EXTRA_src_processor_minidump_unittest_DEPENDENCIES) src/processor/$(am__dirstamp)
+ @rm -f src/processor/minidump_unittest$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(src_processor_minidump_unittest_OBJECTS) $(src_processor_minidump_unittest_LDADD) $(LIBS)
+src/processor/pathname_stripper_unittest.$(OBJEXT): \
+ src/processor/$(am__dirstamp) \
+ src/processor/$(DEPDIR)/$(am__dirstamp)
+
+src/processor/pathname_stripper_unittest$(EXEEXT): $(src_processor_pathname_stripper_unittest_OBJECTS) $(src_processor_pathname_stripper_unittest_DEPENDENCIES) $(EXTRA_src_processor_pathname_stripper_unittest_DEPENDENCIES) src/processor/$(am__dirstamp)
+ @rm -f src/processor/pathname_stripper_unittest$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(src_processor_pathname_stripper_unittest_OBJECTS) $(src_processor_pathname_stripper_unittest_LDADD) $(LIBS)
+src/processor/postfix_evaluator_unittest.$(OBJEXT): \
+ src/processor/$(am__dirstamp) \
+ src/processor/$(DEPDIR)/$(am__dirstamp)
+
+src/processor/postfix_evaluator_unittest$(EXEEXT): $(src_processor_postfix_evaluator_unittest_OBJECTS) $(src_processor_postfix_evaluator_unittest_DEPENDENCIES) $(EXTRA_src_processor_postfix_evaluator_unittest_DEPENDENCIES) src/processor/$(am__dirstamp)
+ @rm -f src/processor/postfix_evaluator_unittest$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(src_processor_postfix_evaluator_unittest_OBJECTS) $(src_processor_postfix_evaluator_unittest_LDADD) $(LIBS)
+src/processor/src_processor_proc_maps_linux_unittest-proc_maps_linux.$(OBJEXT): \
+ src/processor/$(am__dirstamp) \
+ src/processor/$(DEPDIR)/$(am__dirstamp)
+src/processor/src_processor_proc_maps_linux_unittest-proc_maps_linux_unittest.$(OBJEXT): \
+ src/processor/$(am__dirstamp) \
+ src/processor/$(DEPDIR)/$(am__dirstamp)
+
+src/processor/proc_maps_linux_unittest$(EXEEXT): $(src_processor_proc_maps_linux_unittest_OBJECTS) $(src_processor_proc_maps_linux_unittest_DEPENDENCIES) $(EXTRA_src_processor_proc_maps_linux_unittest_DEPENDENCIES) src/processor/$(am__dirstamp)
+ @rm -f src/processor/proc_maps_linux_unittest$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(src_processor_proc_maps_linux_unittest_OBJECTS) $(src_processor_proc_maps_linux_unittest_LDADD) $(LIBS)
+src/processor/src_processor_range_map_shrink_down_unittest-range_map_shrink_down_unittest.$(OBJEXT): \
+ src/processor/$(am__dirstamp) \
+ src/processor/$(DEPDIR)/$(am__dirstamp)
+
+src/processor/range_map_shrink_down_unittest$(EXEEXT): $(src_processor_range_map_shrink_down_unittest_OBJECTS) $(src_processor_range_map_shrink_down_unittest_DEPENDENCIES) $(EXTRA_src_processor_range_map_shrink_down_unittest_DEPENDENCIES) src/processor/$(am__dirstamp)
+ @rm -f src/processor/range_map_shrink_down_unittest$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(src_processor_range_map_shrink_down_unittest_OBJECTS) $(src_processor_range_map_shrink_down_unittest_LDADD) $(LIBS)
+src/processor/range_map_unittest.$(OBJEXT): \
+ src/processor/$(am__dirstamp) \
+ src/processor/$(DEPDIR)/$(am__dirstamp)
+
+src/processor/range_map_unittest$(EXEEXT): $(src_processor_range_map_unittest_OBJECTS) $(src_processor_range_map_unittest_DEPENDENCIES) $(EXTRA_src_processor_range_map_unittest_DEPENDENCIES) src/processor/$(am__dirstamp)
+ @rm -f src/processor/range_map_unittest$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(src_processor_range_map_unittest_OBJECTS) $(src_processor_range_map_unittest_LDADD) $(LIBS)
+src/common/src_processor_stackwalker_address_list_unittest-test_assembler.$(OBJEXT): \
+ src/common/$(am__dirstamp) \
+ src/common/$(DEPDIR)/$(am__dirstamp)
+src/processor/src_processor_stackwalker_address_list_unittest-stackwalker_address_list_unittest.$(OBJEXT): \
+ src/processor/$(am__dirstamp) \
+ src/processor/$(DEPDIR)/$(am__dirstamp)
+
+src/processor/stackwalker_address_list_unittest$(EXEEXT): $(src_processor_stackwalker_address_list_unittest_OBJECTS) $(src_processor_stackwalker_address_list_unittest_DEPENDENCIES) $(EXTRA_src_processor_stackwalker_address_list_unittest_DEPENDENCIES) src/processor/$(am__dirstamp)
+ @rm -f src/processor/stackwalker_address_list_unittest$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(src_processor_stackwalker_address_list_unittest_OBJECTS) $(src_processor_stackwalker_address_list_unittest_LDADD) $(LIBS)
+src/common/src_processor_stackwalker_amd64_unittest-test_assembler.$(OBJEXT): \
+ src/common/$(am__dirstamp) \
+ src/common/$(DEPDIR)/$(am__dirstamp)
+src/processor/src_processor_stackwalker_amd64_unittest-stackwalker_amd64_unittest.$(OBJEXT): \
+ src/processor/$(am__dirstamp) \
+ src/processor/$(DEPDIR)/$(am__dirstamp)
+
+src/processor/stackwalker_amd64_unittest$(EXEEXT): $(src_processor_stackwalker_amd64_unittest_OBJECTS) $(src_processor_stackwalker_amd64_unittest_DEPENDENCIES) $(EXTRA_src_processor_stackwalker_amd64_unittest_DEPENDENCIES) src/processor/$(am__dirstamp)
+ @rm -f src/processor/stackwalker_amd64_unittest$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(src_processor_stackwalker_amd64_unittest_OBJECTS) $(src_processor_stackwalker_amd64_unittest_LDADD) $(LIBS)
+src/common/src_processor_stackwalker_arm64_unittest-test_assembler.$(OBJEXT): \
+ src/common/$(am__dirstamp) \
+ src/common/$(DEPDIR)/$(am__dirstamp)
+src/processor/src_processor_stackwalker_arm64_unittest-stackwalker_arm64_unittest.$(OBJEXT): \
+ src/processor/$(am__dirstamp) \
+ src/processor/$(DEPDIR)/$(am__dirstamp)
+
+src/processor/stackwalker_arm64_unittest$(EXEEXT): $(src_processor_stackwalker_arm64_unittest_OBJECTS) $(src_processor_stackwalker_arm64_unittest_DEPENDENCIES) $(EXTRA_src_processor_stackwalker_arm64_unittest_DEPENDENCIES) src/processor/$(am__dirstamp)
+ @rm -f src/processor/stackwalker_arm64_unittest$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(src_processor_stackwalker_arm64_unittest_OBJECTS) $(src_processor_stackwalker_arm64_unittest_LDADD) $(LIBS)
+src/common/src_processor_stackwalker_arm_unittest-test_assembler.$(OBJEXT): \
+ src/common/$(am__dirstamp) \
+ src/common/$(DEPDIR)/$(am__dirstamp)
+src/processor/src_processor_stackwalker_arm_unittest-stackwalker_arm_unittest.$(OBJEXT): \
+ src/processor/$(am__dirstamp) \
+ src/processor/$(DEPDIR)/$(am__dirstamp)
+
+src/processor/stackwalker_arm_unittest$(EXEEXT): $(src_processor_stackwalker_arm_unittest_OBJECTS) $(src_processor_stackwalker_arm_unittest_DEPENDENCIES) $(EXTRA_src_processor_stackwalker_arm_unittest_DEPENDENCIES) src/processor/$(am__dirstamp)
+ @rm -f src/processor/stackwalker_arm_unittest$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(src_processor_stackwalker_arm_unittest_OBJECTS) $(src_processor_stackwalker_arm_unittest_LDADD) $(LIBS)
+src/common/src_processor_stackwalker_mips64_unittest-test_assembler.$(OBJEXT): \
+ src/common/$(am__dirstamp) \
+ src/common/$(DEPDIR)/$(am__dirstamp)
+src/processor/src_processor_stackwalker_mips64_unittest-stackwalker_mips64_unittest.$(OBJEXT): \
+ src/processor/$(am__dirstamp) \
+ src/processor/$(DEPDIR)/$(am__dirstamp)
+
+src/processor/stackwalker_mips64_unittest$(EXEEXT): $(src_processor_stackwalker_mips64_unittest_OBJECTS) $(src_processor_stackwalker_mips64_unittest_DEPENDENCIES) $(EXTRA_src_processor_stackwalker_mips64_unittest_DEPENDENCIES) src/processor/$(am__dirstamp)
+ @rm -f src/processor/stackwalker_mips64_unittest$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(src_processor_stackwalker_mips64_unittest_OBJECTS) $(src_processor_stackwalker_mips64_unittest_LDADD) $(LIBS)
+src/common/src_processor_stackwalker_mips_unittest-test_assembler.$(OBJEXT): \
+ src/common/$(am__dirstamp) \
+ src/common/$(DEPDIR)/$(am__dirstamp)
+src/processor/src_processor_stackwalker_mips_unittest-stackwalker_mips_unittest.$(OBJEXT): \
+ src/processor/$(am__dirstamp) \
+ src/processor/$(DEPDIR)/$(am__dirstamp)
+
+src/processor/stackwalker_mips_unittest$(EXEEXT): $(src_processor_stackwalker_mips_unittest_OBJECTS) $(src_processor_stackwalker_mips_unittest_DEPENDENCIES) $(EXTRA_src_processor_stackwalker_mips_unittest_DEPENDENCIES) src/processor/$(am__dirstamp)
+ @rm -f src/processor/stackwalker_mips_unittest$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(src_processor_stackwalker_mips_unittest_OBJECTS) $(src_processor_stackwalker_mips_unittest_LDADD) $(LIBS)
+src/processor/stackwalker_selftest.$(OBJEXT): \
+ src/processor/$(am__dirstamp) \
+ src/processor/$(DEPDIR)/$(am__dirstamp)
+
+src/processor/stackwalker_selftest$(EXEEXT): $(src_processor_stackwalker_selftest_OBJECTS) $(src_processor_stackwalker_selftest_DEPENDENCIES) $(EXTRA_src_processor_stackwalker_selftest_DEPENDENCIES) src/processor/$(am__dirstamp)
+ @rm -f src/processor/stackwalker_selftest$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(src_processor_stackwalker_selftest_OBJECTS) $(src_processor_stackwalker_selftest_LDADD) $(LIBS)
+src/common/src_processor_stackwalker_x86_unittest-test_assembler.$(OBJEXT): \
+ src/common/$(am__dirstamp) \
+ src/common/$(DEPDIR)/$(am__dirstamp)
+src/processor/src_processor_stackwalker_x86_unittest-stackwalker_x86_unittest.$(OBJEXT): \
+ src/processor/$(am__dirstamp) \
+ src/processor/$(DEPDIR)/$(am__dirstamp)
+
+src/processor/stackwalker_x86_unittest$(EXEEXT): $(src_processor_stackwalker_x86_unittest_OBJECTS) $(src_processor_stackwalker_x86_unittest_DEPENDENCIES) $(EXTRA_src_processor_stackwalker_x86_unittest_DEPENDENCIES) src/processor/$(am__dirstamp)
+ @rm -f src/processor/stackwalker_x86_unittest$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(src_processor_stackwalker_x86_unittest_OBJECTS) $(src_processor_stackwalker_x86_unittest_LDADD) $(LIBS)
+src/processor/src_processor_static_address_map_unittest-static_address_map_unittest.$(OBJEXT): \
+ src/processor/$(am__dirstamp) \
+ src/processor/$(DEPDIR)/$(am__dirstamp)
+
+src/processor/static_address_map_unittest$(EXEEXT): $(src_processor_static_address_map_unittest_OBJECTS) $(src_processor_static_address_map_unittest_DEPENDENCIES) $(EXTRA_src_processor_static_address_map_unittest_DEPENDENCIES) src/processor/$(am__dirstamp)
+ @rm -f src/processor/static_address_map_unittest$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(src_processor_static_address_map_unittest_OBJECTS) $(src_processor_static_address_map_unittest_LDADD) $(LIBS)
+src/processor/src_processor_static_contained_range_map_unittest-static_contained_range_map_unittest.$(OBJEXT): \
+ src/processor/$(am__dirstamp) \
+ src/processor/$(DEPDIR)/$(am__dirstamp)
+
+src/processor/static_contained_range_map_unittest$(EXEEXT): $(src_processor_static_contained_range_map_unittest_OBJECTS) $(src_processor_static_contained_range_map_unittest_DEPENDENCIES) $(EXTRA_src_processor_static_contained_range_map_unittest_DEPENDENCIES) src/processor/$(am__dirstamp)
+ @rm -f src/processor/static_contained_range_map_unittest$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(src_processor_static_contained_range_map_unittest_OBJECTS) $(src_processor_static_contained_range_map_unittest_LDADD) $(LIBS)
+src/processor/src_processor_static_map_unittest-static_map_unittest.$(OBJEXT): \
+ src/processor/$(am__dirstamp) \
+ src/processor/$(DEPDIR)/$(am__dirstamp)
+
+src/processor/static_map_unittest$(EXEEXT): $(src_processor_static_map_unittest_OBJECTS) $(src_processor_static_map_unittest_DEPENDENCIES) $(EXTRA_src_processor_static_map_unittest_DEPENDENCIES) src/processor/$(am__dirstamp)
+ @rm -f src/processor/static_map_unittest$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(src_processor_static_map_unittest_OBJECTS) $(src_processor_static_map_unittest_LDADD) $(LIBS)
+src/processor/src_processor_static_range_map_unittest-static_range_map_unittest.$(OBJEXT): \
+ src/processor/$(am__dirstamp) \
+ src/processor/$(DEPDIR)/$(am__dirstamp)
+
+src/processor/static_range_map_unittest$(EXEEXT): $(src_processor_static_range_map_unittest_OBJECTS) $(src_processor_static_range_map_unittest_DEPENDENCIES) $(EXTRA_src_processor_static_range_map_unittest_DEPENDENCIES) src/processor/$(am__dirstamp)
+ @rm -f src/processor/static_range_map_unittest$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(src_processor_static_range_map_unittest_OBJECTS) $(src_processor_static_range_map_unittest_LDADD) $(LIBS)
+src/common/src_processor_synth_minidump_unittest-test_assembler.$(OBJEXT): \
+ src/common/$(am__dirstamp) \
+ src/common/$(DEPDIR)/$(am__dirstamp)
+src/processor/src_processor_synth_minidump_unittest-synth_minidump_unittest.$(OBJEXT): \
+ src/processor/$(am__dirstamp) \
+ src/processor/$(DEPDIR)/$(am__dirstamp)
+src/processor/src_processor_synth_minidump_unittest-synth_minidump.$(OBJEXT): \
+ src/processor/$(am__dirstamp) \
+ src/processor/$(DEPDIR)/$(am__dirstamp)
+
+src/processor/synth_minidump_unittest$(EXEEXT): $(src_processor_synth_minidump_unittest_OBJECTS) $(src_processor_synth_minidump_unittest_DEPENDENCIES) $(EXTRA_src_processor_synth_minidump_unittest_DEPENDENCIES) src/processor/$(am__dirstamp)
+ @rm -f src/processor/synth_minidump_unittest$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(src_processor_synth_minidump_unittest_OBJECTS) $(src_processor_synth_minidump_unittest_LDADD) $(LIBS)
+src/tools/linux/core2md/$(am__dirstamp):
+ @$(MKDIR_P) src/tools/linux/core2md
+ @: > src/tools/linux/core2md/$(am__dirstamp)
+src/tools/linux/core2md/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) src/tools/linux/core2md/$(DEPDIR)
+ @: > src/tools/linux/core2md/$(DEPDIR)/$(am__dirstamp)
+src/tools/linux/core2md/core2md.$(OBJEXT): \
+ src/tools/linux/core2md/$(am__dirstamp) \
+ src/tools/linux/core2md/$(DEPDIR)/$(am__dirstamp)
+
+src/tools/linux/core2md/core2md$(EXEEXT): $(src_tools_linux_core2md_core2md_OBJECTS) $(src_tools_linux_core2md_core2md_DEPENDENCIES) $(EXTRA_src_tools_linux_core2md_core2md_DEPENDENCIES) src/tools/linux/core2md/$(am__dirstamp)
+ @rm -f src/tools/linux/core2md/core2md$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(src_tools_linux_core2md_core2md_OBJECTS) $(src_tools_linux_core2md_core2md_LDADD) $(LIBS)
+src/common/dwarf_cfi_to_module.$(OBJEXT): src/common/$(am__dirstamp) \
+ src/common/$(DEPDIR)/$(am__dirstamp)
+src/common/dwarf_cu_to_module.$(OBJEXT): src/common/$(am__dirstamp) \
+ src/common/$(DEPDIR)/$(am__dirstamp)
+src/common/dwarf_line_to_module.$(OBJEXT): src/common/$(am__dirstamp) \
+ src/common/$(DEPDIR)/$(am__dirstamp)
+src/common/language.$(OBJEXT): src/common/$(am__dirstamp) \
+ src/common/$(DEPDIR)/$(am__dirstamp)
+src/common/module.$(OBJEXT): src/common/$(am__dirstamp) \
+ src/common/$(DEPDIR)/$(am__dirstamp)
+src/common/stabs_reader.$(OBJEXT): src/common/$(am__dirstamp) \
+ src/common/$(DEPDIR)/$(am__dirstamp)
+src/common/stabs_to_module.$(OBJEXT): src/common/$(am__dirstamp) \
+ src/common/$(DEPDIR)/$(am__dirstamp)
+src/common/dwarf/bytereader.$(OBJEXT): \
+ src/common/dwarf/$(am__dirstamp) \
+ src/common/dwarf/$(DEPDIR)/$(am__dirstamp)
+src/common/dwarf/dwarf2diehandler.$(OBJEXT): \
+ src/common/dwarf/$(am__dirstamp) \
+ src/common/dwarf/$(DEPDIR)/$(am__dirstamp)
+src/common/dwarf/dwarf2reader.$(OBJEXT): \
+ src/common/dwarf/$(am__dirstamp) \
+ src/common/dwarf/$(DEPDIR)/$(am__dirstamp)
+src/common/dwarf/elf_reader.$(OBJEXT): \
+ src/common/dwarf/$(am__dirstamp) \
+ src/common/dwarf/$(DEPDIR)/$(am__dirstamp)
+src/common/linux/crc32.$(OBJEXT): src/common/linux/$(am__dirstamp) \
+ src/common/linux/$(DEPDIR)/$(am__dirstamp)
+src/common/linux/dump_symbols.$(OBJEXT): \
+ src/common/linux/$(am__dirstamp) \
+ src/common/linux/$(DEPDIR)/$(am__dirstamp)
+src/common/linux/elf_symbols_to_module.$(OBJEXT): \
+ src/common/linux/$(am__dirstamp) \
+ src/common/linux/$(DEPDIR)/$(am__dirstamp)
+src/tools/linux/dump_syms/$(am__dirstamp):
+ @$(MKDIR_P) src/tools/linux/dump_syms
+ @: > src/tools/linux/dump_syms/$(am__dirstamp)
+src/tools/linux/dump_syms/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) src/tools/linux/dump_syms/$(DEPDIR)
+ @: > src/tools/linux/dump_syms/$(DEPDIR)/$(am__dirstamp)
+src/tools/linux/dump_syms/dump_syms.$(OBJEXT): \
+ src/tools/linux/dump_syms/$(am__dirstamp) \
+ src/tools/linux/dump_syms/$(DEPDIR)/$(am__dirstamp)
+
+src/tools/linux/dump_syms/dump_syms$(EXEEXT): $(src_tools_linux_dump_syms_dump_syms_OBJECTS) $(src_tools_linux_dump_syms_dump_syms_DEPENDENCIES) $(EXTRA_src_tools_linux_dump_syms_dump_syms_DEPENDENCIES) src/tools/linux/dump_syms/$(am__dirstamp)
+ @rm -f src/tools/linux/dump_syms/dump_syms$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(src_tools_linux_dump_syms_dump_syms_OBJECTS) $(src_tools_linux_dump_syms_dump_syms_LDADD) $(LIBS)
+src/tools/linux/md2core/$(am__dirstamp):
+ @$(MKDIR_P) src/tools/linux/md2core
+ @: > src/tools/linux/md2core/$(am__dirstamp)
+src/tools/linux/md2core/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) src/tools/linux/md2core/$(DEPDIR)
+ @: > src/tools/linux/md2core/$(DEPDIR)/$(am__dirstamp)
+src/tools/linux/md2core/minidump-2-core.$(OBJEXT): \
+ src/tools/linux/md2core/$(am__dirstamp) \
+ src/tools/linux/md2core/$(DEPDIR)/$(am__dirstamp)
+
+src/tools/linux/md2core/minidump-2-core$(EXEEXT): $(src_tools_linux_md2core_minidump_2_core_OBJECTS) $(src_tools_linux_md2core_minidump_2_core_DEPENDENCIES) $(EXTRA_src_tools_linux_md2core_minidump_2_core_DEPENDENCIES) src/tools/linux/md2core/$(am__dirstamp)
+ @rm -f src/tools/linux/md2core/minidump-2-core$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(src_tools_linux_md2core_minidump_2_core_OBJECTS) $(src_tools_linux_md2core_minidump_2_core_LDADD) $(LIBS)
+src/tools/linux/md2core/src_tools_linux_md2core_minidump_2_core_unittest-minidump_memory_range_unittest.$(OBJEXT): \
+ src/tools/linux/md2core/$(am__dirstamp) \
+ src/tools/linux/md2core/$(DEPDIR)/$(am__dirstamp)
+
+src/tools/linux/md2core/minidump_2_core_unittest$(EXEEXT): $(src_tools_linux_md2core_minidump_2_core_unittest_OBJECTS) $(src_tools_linux_md2core_minidump_2_core_unittest_DEPENDENCIES) $(EXTRA_src_tools_linux_md2core_minidump_2_core_unittest_DEPENDENCIES) src/tools/linux/md2core/$(am__dirstamp)
+ @rm -f src/tools/linux/md2core/minidump_2_core_unittest$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(src_tools_linux_md2core_minidump_2_core_unittest_OBJECTS) $(src_tools_linux_md2core_minidump_2_core_unittest_LDADD) $(LIBS)
+src/common/linux/http_upload.$(OBJEXT): \
+ src/common/linux/$(am__dirstamp) \
+ src/common/linux/$(DEPDIR)/$(am__dirstamp)
+src/tools/linux/symupload/$(am__dirstamp):
+ @$(MKDIR_P) src/tools/linux/symupload
+ @: > src/tools/linux/symupload/$(am__dirstamp)
+src/tools/linux/symupload/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) src/tools/linux/symupload/$(DEPDIR)
+ @: > src/tools/linux/symupload/$(DEPDIR)/$(am__dirstamp)
+src/tools/linux/symupload/minidump_upload.$(OBJEXT): \
+ src/tools/linux/symupload/$(am__dirstamp) \
+ src/tools/linux/symupload/$(DEPDIR)/$(am__dirstamp)
+
+src/tools/linux/symupload/minidump_upload$(EXEEXT): $(src_tools_linux_symupload_minidump_upload_OBJECTS) $(src_tools_linux_symupload_minidump_upload_DEPENDENCIES) $(EXTRA_src_tools_linux_symupload_minidump_upload_DEPENDENCIES) src/tools/linux/symupload/$(am__dirstamp)
+ @rm -f src/tools/linux/symupload/minidump_upload$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(src_tools_linux_symupload_minidump_upload_OBJECTS) $(src_tools_linux_symupload_minidump_upload_LDADD) $(LIBS)
+src/common/linux/symbol_upload.$(OBJEXT): \
+ src/common/linux/$(am__dirstamp) \
+ src/common/linux/$(DEPDIR)/$(am__dirstamp)
+src/tools/linux/symupload/sym_upload.$(OBJEXT): \
+ src/tools/linux/symupload/$(am__dirstamp) \
+ src/tools/linux/symupload/$(DEPDIR)/$(am__dirstamp)
+
+src/tools/linux/symupload/sym_upload$(EXEEXT): $(src_tools_linux_symupload_sym_upload_OBJECTS) $(src_tools_linux_symupload_sym_upload_DEPENDENCIES) $(EXTRA_src_tools_linux_symupload_sym_upload_DEPENDENCIES) src/tools/linux/symupload/$(am__dirstamp)
+ @rm -f src/tools/linux/symupload/sym_upload$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(src_tools_linux_symupload_sym_upload_OBJECTS) $(src_tools_linux_symupload_sym_upload_LDADD) $(LIBS)
+src/common/src_tools_mac_dump_syms_dump_syms_mac-dwarf_cfi_to_module.$(OBJEXT): \
+ src/common/$(am__dirstamp) \
+ src/common/$(DEPDIR)/$(am__dirstamp)
+src/common/src_tools_mac_dump_syms_dump_syms_mac-dwarf_cu_to_module.$(OBJEXT): \
+ src/common/$(am__dirstamp) \
+ src/common/$(DEPDIR)/$(am__dirstamp)
+src/common/src_tools_mac_dump_syms_dump_syms_mac-dwarf_line_to_module.$(OBJEXT): \
+ src/common/$(am__dirstamp) \
+ src/common/$(DEPDIR)/$(am__dirstamp)
+src/common/src_tools_mac_dump_syms_dump_syms_mac-language.$(OBJEXT): \
+ src/common/$(am__dirstamp) \
+ src/common/$(DEPDIR)/$(am__dirstamp)
+src/common/src_tools_mac_dump_syms_dump_syms_mac-md5.$(OBJEXT): \
+ src/common/$(am__dirstamp) \
+ src/common/$(DEPDIR)/$(am__dirstamp)
+src/common/src_tools_mac_dump_syms_dump_syms_mac-module.$(OBJEXT): \
+ src/common/$(am__dirstamp) \
+ src/common/$(DEPDIR)/$(am__dirstamp)
+src/common/src_tools_mac_dump_syms_dump_syms_mac-stabs_reader.$(OBJEXT): \
+ src/common/$(am__dirstamp) \
+ src/common/$(DEPDIR)/$(am__dirstamp)
+src/common/src_tools_mac_dump_syms_dump_syms_mac-stabs_to_module.$(OBJEXT): \
+ src/common/$(am__dirstamp) \
+ src/common/$(DEPDIR)/$(am__dirstamp)
+src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-bytereader.$(OBJEXT): \
+ src/common/dwarf/$(am__dirstamp) \
+ src/common/dwarf/$(DEPDIR)/$(am__dirstamp)
+src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-dwarf2diehandler.$(OBJEXT): \
+ src/common/dwarf/$(am__dirstamp) \
+ src/common/dwarf/$(DEPDIR)/$(am__dirstamp)
+src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-dwarf2reader.$(OBJEXT): \
+ src/common/dwarf/$(am__dirstamp) \
+ src/common/dwarf/$(DEPDIR)/$(am__dirstamp)
+src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-elf_reader.$(OBJEXT): \
+ src/common/dwarf/$(am__dirstamp) \
+ src/common/dwarf/$(DEPDIR)/$(am__dirstamp)
+src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-arch_utilities.$(OBJEXT): \
+ src/common/mac/$(am__dirstamp) \
+ src/common/mac/$(DEPDIR)/$(am__dirstamp)
+src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-dump_syms.$(OBJEXT): \
+ src/common/mac/$(am__dirstamp) \
+ src/common/mac/$(DEPDIR)/$(am__dirstamp)
+src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-file_id.$(OBJEXT): \
+ src/common/mac/$(am__dirstamp) \
+ src/common/mac/$(DEPDIR)/$(am__dirstamp)
+src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-macho_id.$(OBJEXT): \
+ src/common/mac/$(am__dirstamp) \
+ src/common/mac/$(DEPDIR)/$(am__dirstamp)
+src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-macho_reader.$(OBJEXT): \
+ src/common/mac/$(am__dirstamp) \
+ src/common/mac/$(DEPDIR)/$(am__dirstamp)
+src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-macho_utilities.$(OBJEXT): \
+ src/common/mac/$(am__dirstamp) \
+ src/common/mac/$(DEPDIR)/$(am__dirstamp)
+src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-macho_walker.$(OBJEXT): \
+ src/common/mac/$(am__dirstamp) \
+ src/common/mac/$(DEPDIR)/$(am__dirstamp)
+src/tools/mac/dump_syms/$(am__dirstamp):
+ @$(MKDIR_P) src/tools/mac/dump_syms
+ @: > src/tools/mac/dump_syms/$(am__dirstamp)
+src/tools/mac/dump_syms/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) src/tools/mac/dump_syms/$(DEPDIR)
+ @: > src/tools/mac/dump_syms/$(DEPDIR)/$(am__dirstamp)
+src/tools/mac/dump_syms/src_tools_mac_dump_syms_dump_syms_mac-dump_syms_tool.$(OBJEXT): \
+ src/tools/mac/dump_syms/$(am__dirstamp) \
+ src/tools/mac/dump_syms/$(DEPDIR)/$(am__dirstamp)
+
+src/tools/mac/dump_syms/dump_syms_mac$(EXEEXT): $(src_tools_mac_dump_syms_dump_syms_mac_OBJECTS) $(src_tools_mac_dump_syms_dump_syms_mac_DEPENDENCIES) $(EXTRA_src_tools_mac_dump_syms_dump_syms_mac_DEPENDENCIES) src/tools/mac/dump_syms/$(am__dirstamp)
+ @rm -f src/tools/mac/dump_syms/dump_syms_mac$(EXEEXT)
+ $(AM_V_CXXLD)$(src_tools_mac_dump_syms_dump_syms_mac_LINK) $(src_tools_mac_dump_syms_dump_syms_mac_OBJECTS) $(src_tools_mac_dump_syms_dump_syms_mac_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+ -rm -f src/client/*.$(OBJEXT)
+ -rm -f src/client/linux/crash_generation/*.$(OBJEXT)
+ -rm -f src/client/linux/dump_writer_common/*.$(OBJEXT)
+ -rm -f src/client/linux/handler/*.$(OBJEXT)
+ -rm -f src/client/linux/log/*.$(OBJEXT)
+ -rm -f src/client/linux/microdump_writer/*.$(OBJEXT)
+ -rm -f src/client/linux/minidump_writer/*.$(OBJEXT)
+ -rm -f src/common/*.$(OBJEXT)
+ -rm -f src/common/android/*.$(OBJEXT)
+ -rm -f src/common/dwarf/*.$(OBJEXT)
+ -rm -f src/common/linux/*.$(OBJEXT)
+ -rm -f src/common/linux/tests/*.$(OBJEXT)
+ -rm -f src/common/mac/*.$(OBJEXT)
+ -rm -f src/common/tests/*.$(OBJEXT)
+ -rm -f src/processor/*.$(OBJEXT)
+ -rm -f src/testing/gtest/src/*.$(OBJEXT)
+ -rm -f src/testing/src/*.$(OBJEXT)
+ -rm -f src/third_party/libdisasm/*.$(OBJEXT)
+ -rm -f src/tools/linux/core2md/*.$(OBJEXT)
+ -rm -f src/tools/linux/dump_syms/*.$(OBJEXT)
+ -rm -f src/tools/linux/md2core/*.$(OBJEXT)
+ -rm -f src/tools/linux/symupload/*.$(OBJEXT)
+ -rm -f src/tools/mac/dump_syms/*.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@src/client/$(DEPDIR)/minidump_file_writer.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/client/linux/crash_generation/$(DEPDIR)/crash_generation_client.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/client/linux/crash_generation/$(DEPDIR)/crash_generation_server.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/client/linux/dump_writer_common/$(DEPDIR)/thread_info.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/client/linux/dump_writer_common/$(DEPDIR)/ucontext_reader.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/client/linux/handler/$(DEPDIR)/exception_handler.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/client/linux/handler/$(DEPDIR)/minidump_descriptor.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/client/linux/handler/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-exception_handler_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/client/linux/log/$(DEPDIR)/log.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/client/linux/microdump_writer/$(DEPDIR)/microdump_writer.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/client/linux/microdump_writer/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-microdump_writer_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/client/linux/minidump_writer/$(DEPDIR)/linux_core_dumper.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/client/linux/minidump_writer/$(DEPDIR)/linux_dumper.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/client/linux/minidump_writer/$(DEPDIR)/linux_ptrace_dumper.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/client/linux/minidump_writer/$(DEPDIR)/minidump_writer.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/client/linux/minidump_writer/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-cpu_set_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/client/linux/minidump_writer/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-directory_reader_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/client/linux/minidump_writer/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-line_reader_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/client/linux/minidump_writer/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-linux_core_dumper.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/client/linux/minidump_writer/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-linux_core_dumper_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/client/linux/minidump_writer/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-linux_ptrace_dumper_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/client/linux/minidump_writer/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-minidump_writer_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/client/linux/minidump_writer/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-minidump_writer_unittest_utils.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/client/linux/minidump_writer/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-proc_cpuinfo_reader_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/client/linux/minidump_writer/$(DEPDIR)/src_client_linux_linux_dumper_unittest_helper-linux_dumper_unittest_helper.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/convert_UTF.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/dwarf_cfi_to_module.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/dwarf_cu_to_module.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/dwarf_line_to_module.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/language.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/md5.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/module.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-memory_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_common_dumper_unittest-byte_cursor_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_common_dumper_unittest-dwarf_cfi_to_module.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_common_dumper_unittest-dwarf_cfi_to_module_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_common_dumper_unittest-dwarf_cu_to_module.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_common_dumper_unittest-dwarf_cu_to_module_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_common_dumper_unittest-dwarf_line_to_module.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_common_dumper_unittest-dwarf_line_to_module_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_common_dumper_unittest-language.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_common_dumper_unittest-memory_range_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_common_dumper_unittest-module.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_common_dumper_unittest-module_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_common_dumper_unittest-stabs_reader.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_common_dumper_unittest-stabs_reader_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_common_dumper_unittest-stabs_to_module.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_common_dumper_unittest-stabs_to_module_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_common_dumper_unittest-test_assembler.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_common_mac_macho_reader_unittest-dwarf_cfi_to_module.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_common_mac_macho_reader_unittest-dwarf_cu_to_module.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_common_mac_macho_reader_unittest-dwarf_line_to_module.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_common_mac_macho_reader_unittest-language.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_common_mac_macho_reader_unittest-md5.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_common_mac_macho_reader_unittest-module.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_common_mac_macho_reader_unittest-stabs_reader.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_common_mac_macho_reader_unittest-stabs_to_module.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_common_mac_macho_reader_unittest-test_assembler.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_common_test_assembler_unittest-test_assembler.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_common_test_assembler_unittest-test_assembler_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_processor_minidump_unittest-test_assembler.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_processor_stackwalker_address_list_unittest-test_assembler.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_processor_stackwalker_amd64_unittest-test_assembler.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_processor_stackwalker_arm64_unittest-test_assembler.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_processor_stackwalker_arm_unittest-test_assembler.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_processor_stackwalker_mips64_unittest-test_assembler.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_processor_stackwalker_mips_unittest-test_assembler.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_processor_stackwalker_x86_unittest-test_assembler.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_processor_synth_minidump_unittest-test_assembler.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-dwarf_cfi_to_module.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-dwarf_cu_to_module.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-dwarf_line_to_module.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-language.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-md5.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-module.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-stabs_reader.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-stabs_to_module.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/stabs_reader.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/stabs_to_module.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/string_conversion.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/android/$(DEPDIR)/breakpad_getcontext.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/android/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-breakpad_getcontext.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/android/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-breakpad_getcontext_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/dwarf/$(DEPDIR)/bytereader.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/dwarf/$(DEPDIR)/dwarf2diehandler.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/dwarf/$(DEPDIR)/dwarf2reader.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/dwarf/$(DEPDIR)/elf_reader.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-bytereader.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-bytereader_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-cfi_assembler.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-dwarf2diehandler.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-dwarf2diehandler_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-dwarf2reader.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-dwarf2reader_cfi_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-dwarf2reader_die_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-elf_reader.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/dwarf/$(DEPDIR)/src_common_mac_macho_reader_unittest-bytereader.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/dwarf/$(DEPDIR)/src_common_mac_macho_reader_unittest-cfi_assembler.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/dwarf/$(DEPDIR)/src_common_mac_macho_reader_unittest-dwarf2diehandler.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/dwarf/$(DEPDIR)/src_common_mac_macho_reader_unittest-dwarf2reader.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/dwarf/$(DEPDIR)/src_common_mac_macho_reader_unittest-elf_reader.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/dwarf/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-bytereader.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/dwarf/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-dwarf2diehandler.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/dwarf/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-dwarf2reader.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/dwarf/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-elf_reader.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/crc32.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/dump_symbols.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/elf_core_dump.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/elf_symbols_to_module.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/elfutils.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/file_id.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/guid_creator.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/http_upload.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/linux_libc_support.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/memory_mapped_file.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/safe_readlink.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-elf_core_dump.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-linux_libc_support_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/src_common_dumper_unittest-crc32.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/src_common_dumper_unittest-dump_symbols.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/src_common_dumper_unittest-dump_symbols_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/src_common_dumper_unittest-elf_core_dump.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/src_common_dumper_unittest-elf_core_dump_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/src_common_dumper_unittest-elf_symbols_to_module.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/src_common_dumper_unittest-elf_symbols_to_module_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/src_common_dumper_unittest-elfutils.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/src_common_dumper_unittest-file_id.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/src_common_dumper_unittest-file_id_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/src_common_dumper_unittest-linux_libc_support.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/src_common_dumper_unittest-memory_mapped_file.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/src_common_dumper_unittest-memory_mapped_file_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/src_common_dumper_unittest-safe_readlink.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/src_common_dumper_unittest-safe_readlink_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/src_common_dumper_unittest-synth_elf.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/src_common_dumper_unittest-synth_elf_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/symbol_upload.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/tests/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-crash_generator.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/tests/$(DEPDIR)/src_common_dumper_unittest-crash_generator.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/mac/$(DEPDIR)/src_common_mac_macho_reader_unittest-arch_utilities.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/mac/$(DEPDIR)/src_common_mac_macho_reader_unittest-file_id.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/mac/$(DEPDIR)/src_common_mac_macho_reader_unittest-macho_id.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/mac/$(DEPDIR)/src_common_mac_macho_reader_unittest-macho_reader.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/mac/$(DEPDIR)/src_common_mac_macho_reader_unittest-macho_reader_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/mac/$(DEPDIR)/src_common_mac_macho_reader_unittest-macho_utilities.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/mac/$(DEPDIR)/src_common_mac_macho_reader_unittest-macho_walker.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/mac/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-arch_utilities.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/mac/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-dump_syms.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/mac/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-file_id.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/mac/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-macho_id.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/mac/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-macho_reader.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/mac/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-macho_utilities.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/mac/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-macho_walker.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/tests/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-file_utils.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/tests/$(DEPDIR)/src_common_dumper_unittest-file_utils.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/tests/$(DEPDIR)/src_common_mac_macho_reader_unittest-file_utils.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/address_map_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/basic_code_modules.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/basic_source_line_resolver.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/call_stack.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/cfi_frame_info.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/contained_range_map_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/disassembler_x86.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/dump_context.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/dump_object.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/exploitability.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/exploitability_linux.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/exploitability_win.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/fast_source_line_resolver.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/logging.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/microdump.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/microdump_processor.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/microdump_stackwalk.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/minidump.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/minidump_dump.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/minidump_processor.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/minidump_stackwalk.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/module_comparer.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/module_serializer.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/pathname_stripper.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/pathname_stripper_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/postfix_evaluator_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/proc_maps_linux.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/process_state.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/range_map_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/simple_symbol_supplier.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/source_line_resolver_base.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-basic_code_modules.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-dump_context.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-dump_object.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-logging.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-minidump.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-pathname_stripper.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-proc_maps_linux.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/src_processor_basic_source_line_resolver_unittest-basic_source_line_resolver_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/src_processor_cfi_frame_info_unittest-cfi_frame_info_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/src_processor_disassembler_x86_unittest-disassembler_x86_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/src_processor_exploitability_unittest-exploitability_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/src_processor_fast_source_line_resolver_unittest-fast_source_line_resolver_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/src_processor_map_serializers_unittest-map_serializers_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/src_processor_microdump_processor_unittest-microdump_processor_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/src_processor_minidump_processor_unittest-minidump_processor_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/src_processor_minidump_unittest-minidump_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/src_processor_minidump_unittest-synth_minidump.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/src_processor_proc_maps_linux_unittest-proc_maps_linux.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/src_processor_proc_maps_linux_unittest-proc_maps_linux_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/src_processor_range_map_shrink_down_unittest-range_map_shrink_down_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/src_processor_stackwalker_address_list_unittest-stackwalker_address_list_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/src_processor_stackwalker_amd64_unittest-stackwalker_amd64_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/src_processor_stackwalker_arm64_unittest-stackwalker_arm64_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/src_processor_stackwalker_arm_unittest-stackwalker_arm_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/src_processor_stackwalker_mips64_unittest-stackwalker_mips64_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/src_processor_stackwalker_mips_unittest-stackwalker_mips_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/src_processor_stackwalker_x86_unittest-stackwalker_x86_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/src_processor_static_address_map_unittest-static_address_map_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/src_processor_static_contained_range_map_unittest-static_contained_range_map_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/src_processor_static_map_unittest-static_map_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/src_processor_static_range_map_unittest-static_range_map_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/src_processor_synth_minidump_unittest-synth_minidump.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/src_processor_synth_minidump_unittest-synth_minidump_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/stack_frame_cpu.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/stack_frame_symbolizer.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/stackwalker.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/stackwalker_address_list.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/stackwalker_amd64.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/stackwalker_arm.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/stackwalker_arm64.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/stackwalker_mips.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/stackwalker_ppc.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/stackwalker_ppc64.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/stackwalker_selftest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/stackwalker_sparc.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/stackwalker_x86.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/symbolic_constants_win.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/tokenize.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/testing/gtest/src/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-gtest-all.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/testing/gtest/src/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-gtest_main.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/testing/gtest/src/$(DEPDIR)/src_testing_libtesting_a-gtest-all.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/testing/gtest/src/$(DEPDIR)/src_testing_libtesting_a-gtest_main.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/testing/src/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-gmock-all.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/testing/src/$(DEPDIR)/src_testing_libtesting_a-gmock-all.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/third_party/libdisasm/$(DEPDIR)/ia32_implicit.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/third_party/libdisasm/$(DEPDIR)/ia32_insn.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/third_party/libdisasm/$(DEPDIR)/ia32_invariant.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/third_party/libdisasm/$(DEPDIR)/ia32_modrm.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/third_party/libdisasm/$(DEPDIR)/ia32_opcode_tables.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/third_party/libdisasm/$(DEPDIR)/ia32_operand.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/third_party/libdisasm/$(DEPDIR)/ia32_reg.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/third_party/libdisasm/$(DEPDIR)/ia32_settings.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/third_party/libdisasm/$(DEPDIR)/x86_disasm.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/third_party/libdisasm/$(DEPDIR)/x86_format.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/third_party/libdisasm/$(DEPDIR)/x86_imm.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/third_party/libdisasm/$(DEPDIR)/x86_insn.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/third_party/libdisasm/$(DEPDIR)/x86_misc.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/third_party/libdisasm/$(DEPDIR)/x86_operand_list.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/tools/linux/core2md/$(DEPDIR)/core2md.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/tools/linux/dump_syms/$(DEPDIR)/dump_syms.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/tools/linux/md2core/$(DEPDIR)/minidump-2-core.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/tools/linux/md2core/$(DEPDIR)/src_tools_linux_md2core_minidump_2_core_unittest-minidump_memory_range_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/tools/linux/symupload/$(DEPDIR)/minidump_upload.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/tools/linux/symupload/$(DEPDIR)/sym_upload.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/tools/mac/dump_syms/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-dump_syms_tool.Po@am__quote@
+
+.S.o:
+@am__fastdepCCAS_TRUE@ $(AM_V_CPPAS)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
+@am__fastdepCCAS_TRUE@ $(CPPASCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCCAS_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ DEPDIR=$(DEPDIR) $(CCASDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS@am__nodep@)$(CPPASCOMPILE) -c -o $@ $<
+
+.S.obj:
+@am__fastdepCCAS_TRUE@ $(AM_V_CPPAS)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
+@am__fastdepCCAS_TRUE@ $(CPPASCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
+@am__fastdepCCAS_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ DEPDIR=$(DEPDIR) $(CCASDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS@am__nodep@)$(CPPASCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+src/common/android/src_client_linux_linux_client_unittest_shlib-breakpad_getcontext.o: src/common/android/breakpad_getcontext.S
+@am__fastdepCCAS_TRUE@ $(AM_V_CPPAS)$(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CCASFLAGS) $(CCASFLAGS) -MT src/common/android/src_client_linux_linux_client_unittest_shlib-breakpad_getcontext.o -MD -MP -MF src/common/android/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-breakpad_getcontext.Tpo -c -o src/common/android/src_client_linux_linux_client_unittest_shlib-breakpad_getcontext.o `test -f 'src/common/android/breakpad_getcontext.S' || echo '$(srcdir)/'`src/common/android/breakpad_getcontext.S
+@am__fastdepCCAS_TRUE@ $(AM_V_at)$(am__mv) src/common/android/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-breakpad_getcontext.Tpo src/common/android/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-breakpad_getcontext.Po
+@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS)source='src/common/android/breakpad_getcontext.S' object='src/common/android/src_client_linux_linux_client_unittest_shlib-breakpad_getcontext.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ DEPDIR=$(DEPDIR) $(CCASDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS@am__nodep@)$(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CCASFLAGS) $(CCASFLAGS) -c -o src/common/android/src_client_linux_linux_client_unittest_shlib-breakpad_getcontext.o `test -f 'src/common/android/breakpad_getcontext.S' || echo '$(srcdir)/'`src/common/android/breakpad_getcontext.S
+
+src/common/android/src_client_linux_linux_client_unittest_shlib-breakpad_getcontext.obj: src/common/android/breakpad_getcontext.S
+@am__fastdepCCAS_TRUE@ $(AM_V_CPPAS)$(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CCASFLAGS) $(CCASFLAGS) -MT src/common/android/src_client_linux_linux_client_unittest_shlib-breakpad_getcontext.obj -MD -MP -MF src/common/android/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-breakpad_getcontext.Tpo -c -o src/common/android/src_client_linux_linux_client_unittest_shlib-breakpad_getcontext.obj `if test -f 'src/common/android/breakpad_getcontext.S'; then $(CYGPATH_W) 'src/common/android/breakpad_getcontext.S'; else $(CYGPATH_W) '$(srcdir)/src/common/android/breakpad_getcontext.S'; fi`
+@am__fastdepCCAS_TRUE@ $(AM_V_at)$(am__mv) src/common/android/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-breakpad_getcontext.Tpo src/common/android/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-breakpad_getcontext.Po
+@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS)source='src/common/android/breakpad_getcontext.S' object='src/common/android/src_client_linux_linux_client_unittest_shlib-breakpad_getcontext.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ DEPDIR=$(DEPDIR) $(CCASDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS@am__nodep@)$(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CCASFLAGS) $(CCASFLAGS) -c -o src/common/android/src_client_linux_linux_client_unittest_shlib-breakpad_getcontext.obj `if test -f 'src/common/android/breakpad_getcontext.S'; then $(CYGPATH_W) 'src/common/android/breakpad_getcontext.S'; else $(CYGPATH_W) '$(srcdir)/src/common/android/breakpad_getcontext.S'; fi`
+
+.c.o:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.cc.o:
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
+@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $<
+
+.cc.obj:
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
+@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
+@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+src/testing/gtest/src/src_testing_libtesting_a-gtest-all.o: src/testing/gtest/src/gtest-all.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_testing_libtesting_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/testing/gtest/src/src_testing_libtesting_a-gtest-all.o -MD -MP -MF src/testing/gtest/src/$(DEPDIR)/src_testing_libtesting_a-gtest-all.Tpo -c -o src/testing/gtest/src/src_testing_libtesting_a-gtest-all.o `test -f 'src/testing/gtest/src/gtest-all.cc' || echo '$(srcdir)/'`src/testing/gtest/src/gtest-all.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/testing/gtest/src/$(DEPDIR)/src_testing_libtesting_a-gtest-all.Tpo src/testing/gtest/src/$(DEPDIR)/src_testing_libtesting_a-gtest-all.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/testing/gtest/src/gtest-all.cc' object='src/testing/gtest/src/src_testing_libtesting_a-gtest-all.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_testing_libtesting_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/testing/gtest/src/src_testing_libtesting_a-gtest-all.o `test -f 'src/testing/gtest/src/gtest-all.cc' || echo '$(srcdir)/'`src/testing/gtest/src/gtest-all.cc
+
+src/testing/gtest/src/src_testing_libtesting_a-gtest-all.obj: src/testing/gtest/src/gtest-all.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_testing_libtesting_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/testing/gtest/src/src_testing_libtesting_a-gtest-all.obj -MD -MP -MF src/testing/gtest/src/$(DEPDIR)/src_testing_libtesting_a-gtest-all.Tpo -c -o src/testing/gtest/src/src_testing_libtesting_a-gtest-all.obj `if test -f 'src/testing/gtest/src/gtest-all.cc'; then $(CYGPATH_W) 'src/testing/gtest/src/gtest-all.cc'; else $(CYGPATH_W) '$(srcdir)/src/testing/gtest/src/gtest-all.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/testing/gtest/src/$(DEPDIR)/src_testing_libtesting_a-gtest-all.Tpo src/testing/gtest/src/$(DEPDIR)/src_testing_libtesting_a-gtest-all.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/testing/gtest/src/gtest-all.cc' object='src/testing/gtest/src/src_testing_libtesting_a-gtest-all.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_testing_libtesting_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/testing/gtest/src/src_testing_libtesting_a-gtest-all.obj `if test -f 'src/testing/gtest/src/gtest-all.cc'; then $(CYGPATH_W) 'src/testing/gtest/src/gtest-all.cc'; else $(CYGPATH_W) '$(srcdir)/src/testing/gtest/src/gtest-all.cc'; fi`
+
+src/testing/gtest/src/src_testing_libtesting_a-gtest_main.o: src/testing/gtest/src/gtest_main.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_testing_libtesting_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/testing/gtest/src/src_testing_libtesting_a-gtest_main.o -MD -MP -MF src/testing/gtest/src/$(DEPDIR)/src_testing_libtesting_a-gtest_main.Tpo -c -o src/testing/gtest/src/src_testing_libtesting_a-gtest_main.o `test -f 'src/testing/gtest/src/gtest_main.cc' || echo '$(srcdir)/'`src/testing/gtest/src/gtest_main.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/testing/gtest/src/$(DEPDIR)/src_testing_libtesting_a-gtest_main.Tpo src/testing/gtest/src/$(DEPDIR)/src_testing_libtesting_a-gtest_main.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/testing/gtest/src/gtest_main.cc' object='src/testing/gtest/src/src_testing_libtesting_a-gtest_main.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_testing_libtesting_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/testing/gtest/src/src_testing_libtesting_a-gtest_main.o `test -f 'src/testing/gtest/src/gtest_main.cc' || echo '$(srcdir)/'`src/testing/gtest/src/gtest_main.cc
+
+src/testing/gtest/src/src_testing_libtesting_a-gtest_main.obj: src/testing/gtest/src/gtest_main.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_testing_libtesting_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/testing/gtest/src/src_testing_libtesting_a-gtest_main.obj -MD -MP -MF src/testing/gtest/src/$(DEPDIR)/src_testing_libtesting_a-gtest_main.Tpo -c -o src/testing/gtest/src/src_testing_libtesting_a-gtest_main.obj `if test -f 'src/testing/gtest/src/gtest_main.cc'; then $(CYGPATH_W) 'src/testing/gtest/src/gtest_main.cc'; else $(CYGPATH_W) '$(srcdir)/src/testing/gtest/src/gtest_main.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/testing/gtest/src/$(DEPDIR)/src_testing_libtesting_a-gtest_main.Tpo src/testing/gtest/src/$(DEPDIR)/src_testing_libtesting_a-gtest_main.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/testing/gtest/src/gtest_main.cc' object='src/testing/gtest/src/src_testing_libtesting_a-gtest_main.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_testing_libtesting_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/testing/gtest/src/src_testing_libtesting_a-gtest_main.obj `if test -f 'src/testing/gtest/src/gtest_main.cc'; then $(CYGPATH_W) 'src/testing/gtest/src/gtest_main.cc'; else $(CYGPATH_W) '$(srcdir)/src/testing/gtest/src/gtest_main.cc'; fi`
+
+src/testing/src/src_testing_libtesting_a-gmock-all.o: src/testing/src/gmock-all.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_testing_libtesting_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/testing/src/src_testing_libtesting_a-gmock-all.o -MD -MP -MF src/testing/src/$(DEPDIR)/src_testing_libtesting_a-gmock-all.Tpo -c -o src/testing/src/src_testing_libtesting_a-gmock-all.o `test -f 'src/testing/src/gmock-all.cc' || echo '$(srcdir)/'`src/testing/src/gmock-all.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/testing/src/$(DEPDIR)/src_testing_libtesting_a-gmock-all.Tpo src/testing/src/$(DEPDIR)/src_testing_libtesting_a-gmock-all.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/testing/src/gmock-all.cc' object='src/testing/src/src_testing_libtesting_a-gmock-all.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_testing_libtesting_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/testing/src/src_testing_libtesting_a-gmock-all.o `test -f 'src/testing/src/gmock-all.cc' || echo '$(srcdir)/'`src/testing/src/gmock-all.cc
+
+src/testing/src/src_testing_libtesting_a-gmock-all.obj: src/testing/src/gmock-all.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_testing_libtesting_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/testing/src/src_testing_libtesting_a-gmock-all.obj -MD -MP -MF src/testing/src/$(DEPDIR)/src_testing_libtesting_a-gmock-all.Tpo -c -o src/testing/src/src_testing_libtesting_a-gmock-all.obj `if test -f 'src/testing/src/gmock-all.cc'; then $(CYGPATH_W) 'src/testing/src/gmock-all.cc'; else $(CYGPATH_W) '$(srcdir)/src/testing/src/gmock-all.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/testing/src/$(DEPDIR)/src_testing_libtesting_a-gmock-all.Tpo src/testing/src/$(DEPDIR)/src_testing_libtesting_a-gmock-all.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/testing/src/gmock-all.cc' object='src/testing/src/src_testing_libtesting_a-gmock-all.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_testing_libtesting_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/testing/src/src_testing_libtesting_a-gmock-all.obj `if test -f 'src/testing/src/gmock-all.cc'; then $(CYGPATH_W) 'src/testing/src/gmock-all.cc'; else $(CYGPATH_W) '$(srcdir)/src/testing/src/gmock-all.cc'; fi`
+
+src/testing/gtest/src/src_client_linux_linux_client_unittest_shlib-gtest-all.o: src/testing/gtest/src/gtest-all.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/testing/gtest/src/src_client_linux_linux_client_unittest_shlib-gtest-all.o -MD -MP -MF src/testing/gtest/src/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-gtest-all.Tpo -c -o src/testing/gtest/src/src_client_linux_linux_client_unittest_shlib-gtest-all.o `test -f 'src/testing/gtest/src/gtest-all.cc' || echo '$(srcdir)/'`src/testing/gtest/src/gtest-all.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/testing/gtest/src/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-gtest-all.Tpo src/testing/gtest/src/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-gtest-all.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/testing/gtest/src/gtest-all.cc' object='src/testing/gtest/src/src_client_linux_linux_client_unittest_shlib-gtest-all.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/testing/gtest/src/src_client_linux_linux_client_unittest_shlib-gtest-all.o `test -f 'src/testing/gtest/src/gtest-all.cc' || echo '$(srcdir)/'`src/testing/gtest/src/gtest-all.cc
+
+src/testing/gtest/src/src_client_linux_linux_client_unittest_shlib-gtest-all.obj: src/testing/gtest/src/gtest-all.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/testing/gtest/src/src_client_linux_linux_client_unittest_shlib-gtest-all.obj -MD -MP -MF src/testing/gtest/src/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-gtest-all.Tpo -c -o src/testing/gtest/src/src_client_linux_linux_client_unittest_shlib-gtest-all.obj `if test -f 'src/testing/gtest/src/gtest-all.cc'; then $(CYGPATH_W) 'src/testing/gtest/src/gtest-all.cc'; else $(CYGPATH_W) '$(srcdir)/src/testing/gtest/src/gtest-all.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/testing/gtest/src/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-gtest-all.Tpo src/testing/gtest/src/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-gtest-all.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/testing/gtest/src/gtest-all.cc' object='src/testing/gtest/src/src_client_linux_linux_client_unittest_shlib-gtest-all.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/testing/gtest/src/src_client_linux_linux_client_unittest_shlib-gtest-all.obj `if test -f 'src/testing/gtest/src/gtest-all.cc'; then $(CYGPATH_W) 'src/testing/gtest/src/gtest-all.cc'; else $(CYGPATH_W) '$(srcdir)/src/testing/gtest/src/gtest-all.cc'; fi`
+
+src/testing/gtest/src/src_client_linux_linux_client_unittest_shlib-gtest_main.o: src/testing/gtest/src/gtest_main.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/testing/gtest/src/src_client_linux_linux_client_unittest_shlib-gtest_main.o -MD -MP -MF src/testing/gtest/src/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-gtest_main.Tpo -c -o src/testing/gtest/src/src_client_linux_linux_client_unittest_shlib-gtest_main.o `test -f 'src/testing/gtest/src/gtest_main.cc' || echo '$(srcdir)/'`src/testing/gtest/src/gtest_main.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/testing/gtest/src/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-gtest_main.Tpo src/testing/gtest/src/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-gtest_main.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/testing/gtest/src/gtest_main.cc' object='src/testing/gtest/src/src_client_linux_linux_client_unittest_shlib-gtest_main.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/testing/gtest/src/src_client_linux_linux_client_unittest_shlib-gtest_main.o `test -f 'src/testing/gtest/src/gtest_main.cc' || echo '$(srcdir)/'`src/testing/gtest/src/gtest_main.cc
+
+src/testing/gtest/src/src_client_linux_linux_client_unittest_shlib-gtest_main.obj: src/testing/gtest/src/gtest_main.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/testing/gtest/src/src_client_linux_linux_client_unittest_shlib-gtest_main.obj -MD -MP -MF src/testing/gtest/src/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-gtest_main.Tpo -c -o src/testing/gtest/src/src_client_linux_linux_client_unittest_shlib-gtest_main.obj `if test -f 'src/testing/gtest/src/gtest_main.cc'; then $(CYGPATH_W) 'src/testing/gtest/src/gtest_main.cc'; else $(CYGPATH_W) '$(srcdir)/src/testing/gtest/src/gtest_main.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/testing/gtest/src/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-gtest_main.Tpo src/testing/gtest/src/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-gtest_main.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/testing/gtest/src/gtest_main.cc' object='src/testing/gtest/src/src_client_linux_linux_client_unittest_shlib-gtest_main.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/testing/gtest/src/src_client_linux_linux_client_unittest_shlib-gtest_main.obj `if test -f 'src/testing/gtest/src/gtest_main.cc'; then $(CYGPATH_W) 'src/testing/gtest/src/gtest_main.cc'; else $(CYGPATH_W) '$(srcdir)/src/testing/gtest/src/gtest_main.cc'; fi`
+
+src/testing/src/src_client_linux_linux_client_unittest_shlib-gmock-all.o: src/testing/src/gmock-all.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/testing/src/src_client_linux_linux_client_unittest_shlib-gmock-all.o -MD -MP -MF src/testing/src/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-gmock-all.Tpo -c -o src/testing/src/src_client_linux_linux_client_unittest_shlib-gmock-all.o `test -f 'src/testing/src/gmock-all.cc' || echo '$(srcdir)/'`src/testing/src/gmock-all.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/testing/src/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-gmock-all.Tpo src/testing/src/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-gmock-all.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/testing/src/gmock-all.cc' object='src/testing/src/src_client_linux_linux_client_unittest_shlib-gmock-all.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/testing/src/src_client_linux_linux_client_unittest_shlib-gmock-all.o `test -f 'src/testing/src/gmock-all.cc' || echo '$(srcdir)/'`src/testing/src/gmock-all.cc
+
+src/testing/src/src_client_linux_linux_client_unittest_shlib-gmock-all.obj: src/testing/src/gmock-all.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/testing/src/src_client_linux_linux_client_unittest_shlib-gmock-all.obj -MD -MP -MF src/testing/src/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-gmock-all.Tpo -c -o src/testing/src/src_client_linux_linux_client_unittest_shlib-gmock-all.obj `if test -f 'src/testing/src/gmock-all.cc'; then $(CYGPATH_W) 'src/testing/src/gmock-all.cc'; else $(CYGPATH_W) '$(srcdir)/src/testing/src/gmock-all.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/testing/src/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-gmock-all.Tpo src/testing/src/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-gmock-all.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/testing/src/gmock-all.cc' object='src/testing/src/src_client_linux_linux_client_unittest_shlib-gmock-all.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/testing/src/src_client_linux_linux_client_unittest_shlib-gmock-all.obj `if test -f 'src/testing/src/gmock-all.cc'; then $(CYGPATH_W) 'src/testing/src/gmock-all.cc'; else $(CYGPATH_W) '$(srcdir)/src/testing/src/gmock-all.cc'; fi`
+
+src/client/linux/handler/src_client_linux_linux_client_unittest_shlib-exception_handler_unittest.o: src/client/linux/handler/exception_handler_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/client/linux/handler/src_client_linux_linux_client_unittest_shlib-exception_handler_unittest.o -MD -MP -MF src/client/linux/handler/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-exception_handler_unittest.Tpo -c -o src/client/linux/handler/src_client_linux_linux_client_unittest_shlib-exception_handler_unittest.o `test -f 'src/client/linux/handler/exception_handler_unittest.cc' || echo '$(srcdir)/'`src/client/linux/handler/exception_handler_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/client/linux/handler/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-exception_handler_unittest.Tpo src/client/linux/handler/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-exception_handler_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/client/linux/handler/exception_handler_unittest.cc' object='src/client/linux/handler/src_client_linux_linux_client_unittest_shlib-exception_handler_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/client/linux/handler/src_client_linux_linux_client_unittest_shlib-exception_handler_unittest.o `test -f 'src/client/linux/handler/exception_handler_unittest.cc' || echo '$(srcdir)/'`src/client/linux/handler/exception_handler_unittest.cc
+
+src/client/linux/handler/src_client_linux_linux_client_unittest_shlib-exception_handler_unittest.obj: src/client/linux/handler/exception_handler_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/client/linux/handler/src_client_linux_linux_client_unittest_shlib-exception_handler_unittest.obj -MD -MP -MF src/client/linux/handler/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-exception_handler_unittest.Tpo -c -o src/client/linux/handler/src_client_linux_linux_client_unittest_shlib-exception_handler_unittest.obj `if test -f 'src/client/linux/handler/exception_handler_unittest.cc'; then $(CYGPATH_W) 'src/client/linux/handler/exception_handler_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/client/linux/handler/exception_handler_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/client/linux/handler/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-exception_handler_unittest.Tpo src/client/linux/handler/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-exception_handler_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/client/linux/handler/exception_handler_unittest.cc' object='src/client/linux/handler/src_client_linux_linux_client_unittest_shlib-exception_handler_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/client/linux/handler/src_client_linux_linux_client_unittest_shlib-exception_handler_unittest.obj `if test -f 'src/client/linux/handler/exception_handler_unittest.cc'; then $(CYGPATH_W) 'src/client/linux/handler/exception_handler_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/client/linux/handler/exception_handler_unittest.cc'; fi`
+
+src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-directory_reader_unittest.o: src/client/linux/minidump_writer/directory_reader_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-directory_reader_unittest.o -MD -MP -MF src/client/linux/minidump_writer/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-directory_reader_unittest.Tpo -c -o src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-directory_reader_unittest.o `test -f 'src/client/linux/minidump_writer/directory_reader_unittest.cc' || echo '$(srcdir)/'`src/client/linux/minidump_writer/directory_reader_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/client/linux/minidump_writer/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-directory_reader_unittest.Tpo src/client/linux/minidump_writer/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-directory_reader_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/client/linux/minidump_writer/directory_reader_unittest.cc' object='src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-directory_reader_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-directory_reader_unittest.o `test -f 'src/client/linux/minidump_writer/directory_reader_unittest.cc' || echo '$(srcdir)/'`src/client/linux/minidump_writer/directory_reader_unittest.cc
+
+src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-directory_reader_unittest.obj: src/client/linux/minidump_writer/directory_reader_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-directory_reader_unittest.obj -MD -MP -MF src/client/linux/minidump_writer/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-directory_reader_unittest.Tpo -c -o src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-directory_reader_unittest.obj `if test -f 'src/client/linux/minidump_writer/directory_reader_unittest.cc'; then $(CYGPATH_W) 'src/client/linux/minidump_writer/directory_reader_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/client/linux/minidump_writer/directory_reader_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/client/linux/minidump_writer/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-directory_reader_unittest.Tpo src/client/linux/minidump_writer/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-directory_reader_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/client/linux/minidump_writer/directory_reader_unittest.cc' object='src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-directory_reader_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-directory_reader_unittest.obj `if test -f 'src/client/linux/minidump_writer/directory_reader_unittest.cc'; then $(CYGPATH_W) 'src/client/linux/minidump_writer/directory_reader_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/client/linux/minidump_writer/directory_reader_unittest.cc'; fi`
+
+src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-cpu_set_unittest.o: src/client/linux/minidump_writer/cpu_set_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-cpu_set_unittest.o -MD -MP -MF src/client/linux/minidump_writer/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-cpu_set_unittest.Tpo -c -o src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-cpu_set_unittest.o `test -f 'src/client/linux/minidump_writer/cpu_set_unittest.cc' || echo '$(srcdir)/'`src/client/linux/minidump_writer/cpu_set_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/client/linux/minidump_writer/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-cpu_set_unittest.Tpo src/client/linux/minidump_writer/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-cpu_set_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/client/linux/minidump_writer/cpu_set_unittest.cc' object='src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-cpu_set_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-cpu_set_unittest.o `test -f 'src/client/linux/minidump_writer/cpu_set_unittest.cc' || echo '$(srcdir)/'`src/client/linux/minidump_writer/cpu_set_unittest.cc
+
+src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-cpu_set_unittest.obj: src/client/linux/minidump_writer/cpu_set_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-cpu_set_unittest.obj -MD -MP -MF src/client/linux/minidump_writer/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-cpu_set_unittest.Tpo -c -o src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-cpu_set_unittest.obj `if test -f 'src/client/linux/minidump_writer/cpu_set_unittest.cc'; then $(CYGPATH_W) 'src/client/linux/minidump_writer/cpu_set_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/client/linux/minidump_writer/cpu_set_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/client/linux/minidump_writer/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-cpu_set_unittest.Tpo src/client/linux/minidump_writer/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-cpu_set_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/client/linux/minidump_writer/cpu_set_unittest.cc' object='src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-cpu_set_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-cpu_set_unittest.obj `if test -f 'src/client/linux/minidump_writer/cpu_set_unittest.cc'; then $(CYGPATH_W) 'src/client/linux/minidump_writer/cpu_set_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/client/linux/minidump_writer/cpu_set_unittest.cc'; fi`
+
+src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-line_reader_unittest.o: src/client/linux/minidump_writer/line_reader_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-line_reader_unittest.o -MD -MP -MF src/client/linux/minidump_writer/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-line_reader_unittest.Tpo -c -o src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-line_reader_unittest.o `test -f 'src/client/linux/minidump_writer/line_reader_unittest.cc' || echo '$(srcdir)/'`src/client/linux/minidump_writer/line_reader_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/client/linux/minidump_writer/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-line_reader_unittest.Tpo src/client/linux/minidump_writer/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-line_reader_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/client/linux/minidump_writer/line_reader_unittest.cc' object='src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-line_reader_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-line_reader_unittest.o `test -f 'src/client/linux/minidump_writer/line_reader_unittest.cc' || echo '$(srcdir)/'`src/client/linux/minidump_writer/line_reader_unittest.cc
+
+src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-line_reader_unittest.obj: src/client/linux/minidump_writer/line_reader_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-line_reader_unittest.obj -MD -MP -MF src/client/linux/minidump_writer/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-line_reader_unittest.Tpo -c -o src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-line_reader_unittest.obj `if test -f 'src/client/linux/minidump_writer/line_reader_unittest.cc'; then $(CYGPATH_W) 'src/client/linux/minidump_writer/line_reader_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/client/linux/minidump_writer/line_reader_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/client/linux/minidump_writer/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-line_reader_unittest.Tpo src/client/linux/minidump_writer/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-line_reader_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/client/linux/minidump_writer/line_reader_unittest.cc' object='src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-line_reader_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-line_reader_unittest.obj `if test -f 'src/client/linux/minidump_writer/line_reader_unittest.cc'; then $(CYGPATH_W) 'src/client/linux/minidump_writer/line_reader_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/client/linux/minidump_writer/line_reader_unittest.cc'; fi`
+
+src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-linux_core_dumper.o: src/client/linux/minidump_writer/linux_core_dumper.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-linux_core_dumper.o -MD -MP -MF src/client/linux/minidump_writer/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-linux_core_dumper.Tpo -c -o src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-linux_core_dumper.o `test -f 'src/client/linux/minidump_writer/linux_core_dumper.cc' || echo '$(srcdir)/'`src/client/linux/minidump_writer/linux_core_dumper.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/client/linux/minidump_writer/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-linux_core_dumper.Tpo src/client/linux/minidump_writer/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-linux_core_dumper.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/client/linux/minidump_writer/linux_core_dumper.cc' object='src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-linux_core_dumper.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-linux_core_dumper.o `test -f 'src/client/linux/minidump_writer/linux_core_dumper.cc' || echo '$(srcdir)/'`src/client/linux/minidump_writer/linux_core_dumper.cc
+
+src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-linux_core_dumper.obj: src/client/linux/minidump_writer/linux_core_dumper.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-linux_core_dumper.obj -MD -MP -MF src/client/linux/minidump_writer/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-linux_core_dumper.Tpo -c -o src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-linux_core_dumper.obj `if test -f 'src/client/linux/minidump_writer/linux_core_dumper.cc'; then $(CYGPATH_W) 'src/client/linux/minidump_writer/linux_core_dumper.cc'; else $(CYGPATH_W) '$(srcdir)/src/client/linux/minidump_writer/linux_core_dumper.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/client/linux/minidump_writer/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-linux_core_dumper.Tpo src/client/linux/minidump_writer/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-linux_core_dumper.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/client/linux/minidump_writer/linux_core_dumper.cc' object='src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-linux_core_dumper.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-linux_core_dumper.obj `if test -f 'src/client/linux/minidump_writer/linux_core_dumper.cc'; then $(CYGPATH_W) 'src/client/linux/minidump_writer/linux_core_dumper.cc'; else $(CYGPATH_W) '$(srcdir)/src/client/linux/minidump_writer/linux_core_dumper.cc'; fi`
+
+src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-linux_core_dumper_unittest.o: src/client/linux/minidump_writer/linux_core_dumper_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-linux_core_dumper_unittest.o -MD -MP -MF src/client/linux/minidump_writer/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-linux_core_dumper_unittest.Tpo -c -o src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-linux_core_dumper_unittest.o `test -f 'src/client/linux/minidump_writer/linux_core_dumper_unittest.cc' || echo '$(srcdir)/'`src/client/linux/minidump_writer/linux_core_dumper_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/client/linux/minidump_writer/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-linux_core_dumper_unittest.Tpo src/client/linux/minidump_writer/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-linux_core_dumper_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/client/linux/minidump_writer/linux_core_dumper_unittest.cc' object='src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-linux_core_dumper_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-linux_core_dumper_unittest.o `test -f 'src/client/linux/minidump_writer/linux_core_dumper_unittest.cc' || echo '$(srcdir)/'`src/client/linux/minidump_writer/linux_core_dumper_unittest.cc
+
+src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-linux_core_dumper_unittest.obj: src/client/linux/minidump_writer/linux_core_dumper_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-linux_core_dumper_unittest.obj -MD -MP -MF src/client/linux/minidump_writer/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-linux_core_dumper_unittest.Tpo -c -o src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-linux_core_dumper_unittest.obj `if test -f 'src/client/linux/minidump_writer/linux_core_dumper_unittest.cc'; then $(CYGPATH_W) 'src/client/linux/minidump_writer/linux_core_dumper_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/client/linux/minidump_writer/linux_core_dumper_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/client/linux/minidump_writer/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-linux_core_dumper_unittest.Tpo src/client/linux/minidump_writer/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-linux_core_dumper_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/client/linux/minidump_writer/linux_core_dumper_unittest.cc' object='src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-linux_core_dumper_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-linux_core_dumper_unittest.obj `if test -f 'src/client/linux/minidump_writer/linux_core_dumper_unittest.cc'; then $(CYGPATH_W) 'src/client/linux/minidump_writer/linux_core_dumper_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/client/linux/minidump_writer/linux_core_dumper_unittest.cc'; fi`
+
+src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-linux_ptrace_dumper_unittest.o: src/client/linux/minidump_writer/linux_ptrace_dumper_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-linux_ptrace_dumper_unittest.o -MD -MP -MF src/client/linux/minidump_writer/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-linux_ptrace_dumper_unittest.Tpo -c -o src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-linux_ptrace_dumper_unittest.o `test -f 'src/client/linux/minidump_writer/linux_ptrace_dumper_unittest.cc' || echo '$(srcdir)/'`src/client/linux/minidump_writer/linux_ptrace_dumper_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/client/linux/minidump_writer/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-linux_ptrace_dumper_unittest.Tpo src/client/linux/minidump_writer/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-linux_ptrace_dumper_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/client/linux/minidump_writer/linux_ptrace_dumper_unittest.cc' object='src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-linux_ptrace_dumper_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-linux_ptrace_dumper_unittest.o `test -f 'src/client/linux/minidump_writer/linux_ptrace_dumper_unittest.cc' || echo '$(srcdir)/'`src/client/linux/minidump_writer/linux_ptrace_dumper_unittest.cc
+
+src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-linux_ptrace_dumper_unittest.obj: src/client/linux/minidump_writer/linux_ptrace_dumper_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-linux_ptrace_dumper_unittest.obj -MD -MP -MF src/client/linux/minidump_writer/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-linux_ptrace_dumper_unittest.Tpo -c -o src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-linux_ptrace_dumper_unittest.obj `if test -f 'src/client/linux/minidump_writer/linux_ptrace_dumper_unittest.cc'; then $(CYGPATH_W) 'src/client/linux/minidump_writer/linux_ptrace_dumper_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/client/linux/minidump_writer/linux_ptrace_dumper_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/client/linux/minidump_writer/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-linux_ptrace_dumper_unittest.Tpo src/client/linux/minidump_writer/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-linux_ptrace_dumper_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/client/linux/minidump_writer/linux_ptrace_dumper_unittest.cc' object='src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-linux_ptrace_dumper_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-linux_ptrace_dumper_unittest.obj `if test -f 'src/client/linux/minidump_writer/linux_ptrace_dumper_unittest.cc'; then $(CYGPATH_W) 'src/client/linux/minidump_writer/linux_ptrace_dumper_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/client/linux/minidump_writer/linux_ptrace_dumper_unittest.cc'; fi`
+
+src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-minidump_writer_unittest.o: src/client/linux/minidump_writer/minidump_writer_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-minidump_writer_unittest.o -MD -MP -MF src/client/linux/minidump_writer/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-minidump_writer_unittest.Tpo -c -o src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-minidump_writer_unittest.o `test -f 'src/client/linux/minidump_writer/minidump_writer_unittest.cc' || echo '$(srcdir)/'`src/client/linux/minidump_writer/minidump_writer_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/client/linux/minidump_writer/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-minidump_writer_unittest.Tpo src/client/linux/minidump_writer/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-minidump_writer_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/client/linux/minidump_writer/minidump_writer_unittest.cc' object='src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-minidump_writer_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-minidump_writer_unittest.o `test -f 'src/client/linux/minidump_writer/minidump_writer_unittest.cc' || echo '$(srcdir)/'`src/client/linux/minidump_writer/minidump_writer_unittest.cc
+
+src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-minidump_writer_unittest.obj: src/client/linux/minidump_writer/minidump_writer_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-minidump_writer_unittest.obj -MD -MP -MF src/client/linux/minidump_writer/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-minidump_writer_unittest.Tpo -c -o src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-minidump_writer_unittest.obj `if test -f 'src/client/linux/minidump_writer/minidump_writer_unittest.cc'; then $(CYGPATH_W) 'src/client/linux/minidump_writer/minidump_writer_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/client/linux/minidump_writer/minidump_writer_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/client/linux/minidump_writer/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-minidump_writer_unittest.Tpo src/client/linux/minidump_writer/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-minidump_writer_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/client/linux/minidump_writer/minidump_writer_unittest.cc' object='src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-minidump_writer_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-minidump_writer_unittest.obj `if test -f 'src/client/linux/minidump_writer/minidump_writer_unittest.cc'; then $(CYGPATH_W) 'src/client/linux/minidump_writer/minidump_writer_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/client/linux/minidump_writer/minidump_writer_unittest.cc'; fi`
+
+src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-minidump_writer_unittest_utils.o: src/client/linux/minidump_writer/minidump_writer_unittest_utils.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-minidump_writer_unittest_utils.o -MD -MP -MF src/client/linux/minidump_writer/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-minidump_writer_unittest_utils.Tpo -c -o src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-minidump_writer_unittest_utils.o `test -f 'src/client/linux/minidump_writer/minidump_writer_unittest_utils.cc' || echo '$(srcdir)/'`src/client/linux/minidump_writer/minidump_writer_unittest_utils.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/client/linux/minidump_writer/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-minidump_writer_unittest_utils.Tpo src/client/linux/minidump_writer/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-minidump_writer_unittest_utils.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/client/linux/minidump_writer/minidump_writer_unittest_utils.cc' object='src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-minidump_writer_unittest_utils.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-minidump_writer_unittest_utils.o `test -f 'src/client/linux/minidump_writer/minidump_writer_unittest_utils.cc' || echo '$(srcdir)/'`src/client/linux/minidump_writer/minidump_writer_unittest_utils.cc
+
+src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-minidump_writer_unittest_utils.obj: src/client/linux/minidump_writer/minidump_writer_unittest_utils.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-minidump_writer_unittest_utils.obj -MD -MP -MF src/client/linux/minidump_writer/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-minidump_writer_unittest_utils.Tpo -c -o src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-minidump_writer_unittest_utils.obj `if test -f 'src/client/linux/minidump_writer/minidump_writer_unittest_utils.cc'; then $(CYGPATH_W) 'src/client/linux/minidump_writer/minidump_writer_unittest_utils.cc'; else $(CYGPATH_W) '$(srcdir)/src/client/linux/minidump_writer/minidump_writer_unittest_utils.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/client/linux/minidump_writer/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-minidump_writer_unittest_utils.Tpo src/client/linux/minidump_writer/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-minidump_writer_unittest_utils.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/client/linux/minidump_writer/minidump_writer_unittest_utils.cc' object='src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-minidump_writer_unittest_utils.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-minidump_writer_unittest_utils.obj `if test -f 'src/client/linux/minidump_writer/minidump_writer_unittest_utils.cc'; then $(CYGPATH_W) 'src/client/linux/minidump_writer/minidump_writer_unittest_utils.cc'; else $(CYGPATH_W) '$(srcdir)/src/client/linux/minidump_writer/minidump_writer_unittest_utils.cc'; fi`
+
+src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-proc_cpuinfo_reader_unittest.o: src/client/linux/minidump_writer/proc_cpuinfo_reader_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-proc_cpuinfo_reader_unittest.o -MD -MP -MF src/client/linux/minidump_writer/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-proc_cpuinfo_reader_unittest.Tpo -c -o src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-proc_cpuinfo_reader_unittest.o `test -f 'src/client/linux/minidump_writer/proc_cpuinfo_reader_unittest.cc' || echo '$(srcdir)/'`src/client/linux/minidump_writer/proc_cpuinfo_reader_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/client/linux/minidump_writer/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-proc_cpuinfo_reader_unittest.Tpo src/client/linux/minidump_writer/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-proc_cpuinfo_reader_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/client/linux/minidump_writer/proc_cpuinfo_reader_unittest.cc' object='src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-proc_cpuinfo_reader_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-proc_cpuinfo_reader_unittest.o `test -f 'src/client/linux/minidump_writer/proc_cpuinfo_reader_unittest.cc' || echo '$(srcdir)/'`src/client/linux/minidump_writer/proc_cpuinfo_reader_unittest.cc
+
+src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-proc_cpuinfo_reader_unittest.obj: src/client/linux/minidump_writer/proc_cpuinfo_reader_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-proc_cpuinfo_reader_unittest.obj -MD -MP -MF src/client/linux/minidump_writer/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-proc_cpuinfo_reader_unittest.Tpo -c -o src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-proc_cpuinfo_reader_unittest.obj `if test -f 'src/client/linux/minidump_writer/proc_cpuinfo_reader_unittest.cc'; then $(CYGPATH_W) 'src/client/linux/minidump_writer/proc_cpuinfo_reader_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/client/linux/minidump_writer/proc_cpuinfo_reader_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/client/linux/minidump_writer/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-proc_cpuinfo_reader_unittest.Tpo src/client/linux/minidump_writer/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-proc_cpuinfo_reader_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/client/linux/minidump_writer/proc_cpuinfo_reader_unittest.cc' object='src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-proc_cpuinfo_reader_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-proc_cpuinfo_reader_unittest.obj `if test -f 'src/client/linux/minidump_writer/proc_cpuinfo_reader_unittest.cc'; then $(CYGPATH_W) 'src/client/linux/minidump_writer/proc_cpuinfo_reader_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/client/linux/minidump_writer/proc_cpuinfo_reader_unittest.cc'; fi`
+
+src/common/linux/src_client_linux_linux_client_unittest_shlib-elf_core_dump.o: src/common/linux/elf_core_dump.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/linux/src_client_linux_linux_client_unittest_shlib-elf_core_dump.o -MD -MP -MF src/common/linux/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-elf_core_dump.Tpo -c -o src/common/linux/src_client_linux_linux_client_unittest_shlib-elf_core_dump.o `test -f 'src/common/linux/elf_core_dump.cc' || echo '$(srcdir)/'`src/common/linux/elf_core_dump.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/linux/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-elf_core_dump.Tpo src/common/linux/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-elf_core_dump.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/linux/elf_core_dump.cc' object='src/common/linux/src_client_linux_linux_client_unittest_shlib-elf_core_dump.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/linux/src_client_linux_linux_client_unittest_shlib-elf_core_dump.o `test -f 'src/common/linux/elf_core_dump.cc' || echo '$(srcdir)/'`src/common/linux/elf_core_dump.cc
+
+src/common/linux/src_client_linux_linux_client_unittest_shlib-elf_core_dump.obj: src/common/linux/elf_core_dump.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/linux/src_client_linux_linux_client_unittest_shlib-elf_core_dump.obj -MD -MP -MF src/common/linux/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-elf_core_dump.Tpo -c -o src/common/linux/src_client_linux_linux_client_unittest_shlib-elf_core_dump.obj `if test -f 'src/common/linux/elf_core_dump.cc'; then $(CYGPATH_W) 'src/common/linux/elf_core_dump.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/linux/elf_core_dump.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/linux/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-elf_core_dump.Tpo src/common/linux/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-elf_core_dump.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/linux/elf_core_dump.cc' object='src/common/linux/src_client_linux_linux_client_unittest_shlib-elf_core_dump.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/linux/src_client_linux_linux_client_unittest_shlib-elf_core_dump.obj `if test -f 'src/common/linux/elf_core_dump.cc'; then $(CYGPATH_W) 'src/common/linux/elf_core_dump.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/linux/elf_core_dump.cc'; fi`
+
+src/common/linux/src_client_linux_linux_client_unittest_shlib-linux_libc_support_unittest.o: src/common/linux/linux_libc_support_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/linux/src_client_linux_linux_client_unittest_shlib-linux_libc_support_unittest.o -MD -MP -MF src/common/linux/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-linux_libc_support_unittest.Tpo -c -o src/common/linux/src_client_linux_linux_client_unittest_shlib-linux_libc_support_unittest.o `test -f 'src/common/linux/linux_libc_support_unittest.cc' || echo '$(srcdir)/'`src/common/linux/linux_libc_support_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/linux/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-linux_libc_support_unittest.Tpo src/common/linux/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-linux_libc_support_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/linux/linux_libc_support_unittest.cc' object='src/common/linux/src_client_linux_linux_client_unittest_shlib-linux_libc_support_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/linux/src_client_linux_linux_client_unittest_shlib-linux_libc_support_unittest.o `test -f 'src/common/linux/linux_libc_support_unittest.cc' || echo '$(srcdir)/'`src/common/linux/linux_libc_support_unittest.cc
+
+src/common/linux/src_client_linux_linux_client_unittest_shlib-linux_libc_support_unittest.obj: src/common/linux/linux_libc_support_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/linux/src_client_linux_linux_client_unittest_shlib-linux_libc_support_unittest.obj -MD -MP -MF src/common/linux/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-linux_libc_support_unittest.Tpo -c -o src/common/linux/src_client_linux_linux_client_unittest_shlib-linux_libc_support_unittest.obj `if test -f 'src/common/linux/linux_libc_support_unittest.cc'; then $(CYGPATH_W) 'src/common/linux/linux_libc_support_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/linux/linux_libc_support_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/linux/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-linux_libc_support_unittest.Tpo src/common/linux/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-linux_libc_support_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/linux/linux_libc_support_unittest.cc' object='src/common/linux/src_client_linux_linux_client_unittest_shlib-linux_libc_support_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/linux/src_client_linux_linux_client_unittest_shlib-linux_libc_support_unittest.obj `if test -f 'src/common/linux/linux_libc_support_unittest.cc'; then $(CYGPATH_W) 'src/common/linux/linux_libc_support_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/linux/linux_libc_support_unittest.cc'; fi`
+
+src/common/linux/tests/src_client_linux_linux_client_unittest_shlib-crash_generator.o: src/common/linux/tests/crash_generator.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/linux/tests/src_client_linux_linux_client_unittest_shlib-crash_generator.o -MD -MP -MF src/common/linux/tests/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-crash_generator.Tpo -c -o src/common/linux/tests/src_client_linux_linux_client_unittest_shlib-crash_generator.o `test -f 'src/common/linux/tests/crash_generator.cc' || echo '$(srcdir)/'`src/common/linux/tests/crash_generator.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/linux/tests/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-crash_generator.Tpo src/common/linux/tests/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-crash_generator.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/linux/tests/crash_generator.cc' object='src/common/linux/tests/src_client_linux_linux_client_unittest_shlib-crash_generator.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/linux/tests/src_client_linux_linux_client_unittest_shlib-crash_generator.o `test -f 'src/common/linux/tests/crash_generator.cc' || echo '$(srcdir)/'`src/common/linux/tests/crash_generator.cc
+
+src/common/linux/tests/src_client_linux_linux_client_unittest_shlib-crash_generator.obj: src/common/linux/tests/crash_generator.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/linux/tests/src_client_linux_linux_client_unittest_shlib-crash_generator.obj -MD -MP -MF src/common/linux/tests/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-crash_generator.Tpo -c -o src/common/linux/tests/src_client_linux_linux_client_unittest_shlib-crash_generator.obj `if test -f 'src/common/linux/tests/crash_generator.cc'; then $(CYGPATH_W) 'src/common/linux/tests/crash_generator.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/linux/tests/crash_generator.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/linux/tests/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-crash_generator.Tpo src/common/linux/tests/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-crash_generator.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/linux/tests/crash_generator.cc' object='src/common/linux/tests/src_client_linux_linux_client_unittest_shlib-crash_generator.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/linux/tests/src_client_linux_linux_client_unittest_shlib-crash_generator.obj `if test -f 'src/common/linux/tests/crash_generator.cc'; then $(CYGPATH_W) 'src/common/linux/tests/crash_generator.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/linux/tests/crash_generator.cc'; fi`
+
+src/common/src_client_linux_linux_client_unittest_shlib-memory_allocator_unittest.o: src/common/memory_allocator_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_client_linux_linux_client_unittest_shlib-memory_allocator_unittest.o -MD -MP -MF src/common/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-memory_allocator_unittest.Tpo -c -o src/common/src_client_linux_linux_client_unittest_shlib-memory_allocator_unittest.o `test -f 'src/common/memory_allocator_unittest.cc' || echo '$(srcdir)/'`src/common/memory_allocator_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-memory_allocator_unittest.Tpo src/common/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-memory_allocator_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/memory_allocator_unittest.cc' object='src/common/src_client_linux_linux_client_unittest_shlib-memory_allocator_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_client_linux_linux_client_unittest_shlib-memory_allocator_unittest.o `test -f 'src/common/memory_allocator_unittest.cc' || echo '$(srcdir)/'`src/common/memory_allocator_unittest.cc
+
+src/common/src_client_linux_linux_client_unittest_shlib-memory_allocator_unittest.obj: src/common/memory_allocator_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_client_linux_linux_client_unittest_shlib-memory_allocator_unittest.obj -MD -MP -MF src/common/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-memory_allocator_unittest.Tpo -c -o src/common/src_client_linux_linux_client_unittest_shlib-memory_allocator_unittest.obj `if test -f 'src/common/memory_allocator_unittest.cc'; then $(CYGPATH_W) 'src/common/memory_allocator_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/memory_allocator_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-memory_allocator_unittest.Tpo src/common/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-memory_allocator_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/memory_allocator_unittest.cc' object='src/common/src_client_linux_linux_client_unittest_shlib-memory_allocator_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_client_linux_linux_client_unittest_shlib-memory_allocator_unittest.obj `if test -f 'src/common/memory_allocator_unittest.cc'; then $(CYGPATH_W) 'src/common/memory_allocator_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/memory_allocator_unittest.cc'; fi`
+
+src/common/tests/src_client_linux_linux_client_unittest_shlib-file_utils.o: src/common/tests/file_utils.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/tests/src_client_linux_linux_client_unittest_shlib-file_utils.o -MD -MP -MF src/common/tests/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-file_utils.Tpo -c -o src/common/tests/src_client_linux_linux_client_unittest_shlib-file_utils.o `test -f 'src/common/tests/file_utils.cc' || echo '$(srcdir)/'`src/common/tests/file_utils.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/tests/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-file_utils.Tpo src/common/tests/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-file_utils.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/tests/file_utils.cc' object='src/common/tests/src_client_linux_linux_client_unittest_shlib-file_utils.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/tests/src_client_linux_linux_client_unittest_shlib-file_utils.o `test -f 'src/common/tests/file_utils.cc' || echo '$(srcdir)/'`src/common/tests/file_utils.cc
+
+src/common/tests/src_client_linux_linux_client_unittest_shlib-file_utils.obj: src/common/tests/file_utils.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/tests/src_client_linux_linux_client_unittest_shlib-file_utils.obj -MD -MP -MF src/common/tests/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-file_utils.Tpo -c -o src/common/tests/src_client_linux_linux_client_unittest_shlib-file_utils.obj `if test -f 'src/common/tests/file_utils.cc'; then $(CYGPATH_W) 'src/common/tests/file_utils.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/tests/file_utils.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/tests/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-file_utils.Tpo src/common/tests/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-file_utils.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/tests/file_utils.cc' object='src/common/tests/src_client_linux_linux_client_unittest_shlib-file_utils.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/tests/src_client_linux_linux_client_unittest_shlib-file_utils.obj `if test -f 'src/common/tests/file_utils.cc'; then $(CYGPATH_W) 'src/common/tests/file_utils.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/tests/file_utils.cc'; fi`
+
+src/processor/src_client_linux_linux_client_unittest_shlib-basic_code_modules.o: src/processor/basic_code_modules.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/processor/src_client_linux_linux_client_unittest_shlib-basic_code_modules.o -MD -MP -MF src/processor/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-basic_code_modules.Tpo -c -o src/processor/src_client_linux_linux_client_unittest_shlib-basic_code_modules.o `test -f 'src/processor/basic_code_modules.cc' || echo '$(srcdir)/'`src/processor/basic_code_modules.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/processor/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-basic_code_modules.Tpo src/processor/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-basic_code_modules.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/processor/basic_code_modules.cc' object='src/processor/src_client_linux_linux_client_unittest_shlib-basic_code_modules.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/processor/src_client_linux_linux_client_unittest_shlib-basic_code_modules.o `test -f 'src/processor/basic_code_modules.cc' || echo '$(srcdir)/'`src/processor/basic_code_modules.cc
+
+src/processor/src_client_linux_linux_client_unittest_shlib-basic_code_modules.obj: src/processor/basic_code_modules.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/processor/src_client_linux_linux_client_unittest_shlib-basic_code_modules.obj -MD -MP -MF src/processor/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-basic_code_modules.Tpo -c -o src/processor/src_client_linux_linux_client_unittest_shlib-basic_code_modules.obj `if test -f 'src/processor/basic_code_modules.cc'; then $(CYGPATH_W) 'src/processor/basic_code_modules.cc'; else $(CYGPATH_W) '$(srcdir)/src/processor/basic_code_modules.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/processor/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-basic_code_modules.Tpo src/processor/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-basic_code_modules.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/processor/basic_code_modules.cc' object='src/processor/src_client_linux_linux_client_unittest_shlib-basic_code_modules.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/processor/src_client_linux_linux_client_unittest_shlib-basic_code_modules.obj `if test -f 'src/processor/basic_code_modules.cc'; then $(CYGPATH_W) 'src/processor/basic_code_modules.cc'; else $(CYGPATH_W) '$(srcdir)/src/processor/basic_code_modules.cc'; fi`
+
+src/processor/src_client_linux_linux_client_unittest_shlib-dump_context.o: src/processor/dump_context.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/processor/src_client_linux_linux_client_unittest_shlib-dump_context.o -MD -MP -MF src/processor/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-dump_context.Tpo -c -o src/processor/src_client_linux_linux_client_unittest_shlib-dump_context.o `test -f 'src/processor/dump_context.cc' || echo '$(srcdir)/'`src/processor/dump_context.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/processor/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-dump_context.Tpo src/processor/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-dump_context.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/processor/dump_context.cc' object='src/processor/src_client_linux_linux_client_unittest_shlib-dump_context.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/processor/src_client_linux_linux_client_unittest_shlib-dump_context.o `test -f 'src/processor/dump_context.cc' || echo '$(srcdir)/'`src/processor/dump_context.cc
+
+src/processor/src_client_linux_linux_client_unittest_shlib-dump_context.obj: src/processor/dump_context.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/processor/src_client_linux_linux_client_unittest_shlib-dump_context.obj -MD -MP -MF src/processor/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-dump_context.Tpo -c -o src/processor/src_client_linux_linux_client_unittest_shlib-dump_context.obj `if test -f 'src/processor/dump_context.cc'; then $(CYGPATH_W) 'src/processor/dump_context.cc'; else $(CYGPATH_W) '$(srcdir)/src/processor/dump_context.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/processor/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-dump_context.Tpo src/processor/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-dump_context.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/processor/dump_context.cc' object='src/processor/src_client_linux_linux_client_unittest_shlib-dump_context.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/processor/src_client_linux_linux_client_unittest_shlib-dump_context.obj `if test -f 'src/processor/dump_context.cc'; then $(CYGPATH_W) 'src/processor/dump_context.cc'; else $(CYGPATH_W) '$(srcdir)/src/processor/dump_context.cc'; fi`
+
+src/processor/src_client_linux_linux_client_unittest_shlib-dump_object.o: src/processor/dump_object.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/processor/src_client_linux_linux_client_unittest_shlib-dump_object.o -MD -MP -MF src/processor/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-dump_object.Tpo -c -o src/processor/src_client_linux_linux_client_unittest_shlib-dump_object.o `test -f 'src/processor/dump_object.cc' || echo '$(srcdir)/'`src/processor/dump_object.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/processor/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-dump_object.Tpo src/processor/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-dump_object.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/processor/dump_object.cc' object='src/processor/src_client_linux_linux_client_unittest_shlib-dump_object.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/processor/src_client_linux_linux_client_unittest_shlib-dump_object.o `test -f 'src/processor/dump_object.cc' || echo '$(srcdir)/'`src/processor/dump_object.cc
+
+src/processor/src_client_linux_linux_client_unittest_shlib-dump_object.obj: src/processor/dump_object.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/processor/src_client_linux_linux_client_unittest_shlib-dump_object.obj -MD -MP -MF src/processor/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-dump_object.Tpo -c -o src/processor/src_client_linux_linux_client_unittest_shlib-dump_object.obj `if test -f 'src/processor/dump_object.cc'; then $(CYGPATH_W) 'src/processor/dump_object.cc'; else $(CYGPATH_W) '$(srcdir)/src/processor/dump_object.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/processor/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-dump_object.Tpo src/processor/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-dump_object.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/processor/dump_object.cc' object='src/processor/src_client_linux_linux_client_unittest_shlib-dump_object.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/processor/src_client_linux_linux_client_unittest_shlib-dump_object.obj `if test -f 'src/processor/dump_object.cc'; then $(CYGPATH_W) 'src/processor/dump_object.cc'; else $(CYGPATH_W) '$(srcdir)/src/processor/dump_object.cc'; fi`
+
+src/processor/src_client_linux_linux_client_unittest_shlib-logging.o: src/processor/logging.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/processor/src_client_linux_linux_client_unittest_shlib-logging.o -MD -MP -MF src/processor/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-logging.Tpo -c -o src/processor/src_client_linux_linux_client_unittest_shlib-logging.o `test -f 'src/processor/logging.cc' || echo '$(srcdir)/'`src/processor/logging.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/processor/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-logging.Tpo src/processor/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-logging.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/processor/logging.cc' object='src/processor/src_client_linux_linux_client_unittest_shlib-logging.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/processor/src_client_linux_linux_client_unittest_shlib-logging.o `test -f 'src/processor/logging.cc' || echo '$(srcdir)/'`src/processor/logging.cc
+
+src/processor/src_client_linux_linux_client_unittest_shlib-logging.obj: src/processor/logging.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/processor/src_client_linux_linux_client_unittest_shlib-logging.obj -MD -MP -MF src/processor/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-logging.Tpo -c -o src/processor/src_client_linux_linux_client_unittest_shlib-logging.obj `if test -f 'src/processor/logging.cc'; then $(CYGPATH_W) 'src/processor/logging.cc'; else $(CYGPATH_W) '$(srcdir)/src/processor/logging.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/processor/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-logging.Tpo src/processor/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-logging.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/processor/logging.cc' object='src/processor/src_client_linux_linux_client_unittest_shlib-logging.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/processor/src_client_linux_linux_client_unittest_shlib-logging.obj `if test -f 'src/processor/logging.cc'; then $(CYGPATH_W) 'src/processor/logging.cc'; else $(CYGPATH_W) '$(srcdir)/src/processor/logging.cc'; fi`
+
+src/processor/src_client_linux_linux_client_unittest_shlib-minidump.o: src/processor/minidump.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/processor/src_client_linux_linux_client_unittest_shlib-minidump.o -MD -MP -MF src/processor/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-minidump.Tpo -c -o src/processor/src_client_linux_linux_client_unittest_shlib-minidump.o `test -f 'src/processor/minidump.cc' || echo '$(srcdir)/'`src/processor/minidump.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/processor/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-minidump.Tpo src/processor/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-minidump.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/processor/minidump.cc' object='src/processor/src_client_linux_linux_client_unittest_shlib-minidump.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/processor/src_client_linux_linux_client_unittest_shlib-minidump.o `test -f 'src/processor/minidump.cc' || echo '$(srcdir)/'`src/processor/minidump.cc
+
+src/processor/src_client_linux_linux_client_unittest_shlib-minidump.obj: src/processor/minidump.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/processor/src_client_linux_linux_client_unittest_shlib-minidump.obj -MD -MP -MF src/processor/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-minidump.Tpo -c -o src/processor/src_client_linux_linux_client_unittest_shlib-minidump.obj `if test -f 'src/processor/minidump.cc'; then $(CYGPATH_W) 'src/processor/minidump.cc'; else $(CYGPATH_W) '$(srcdir)/src/processor/minidump.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/processor/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-minidump.Tpo src/processor/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-minidump.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/processor/minidump.cc' object='src/processor/src_client_linux_linux_client_unittest_shlib-minidump.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/processor/src_client_linux_linux_client_unittest_shlib-minidump.obj `if test -f 'src/processor/minidump.cc'; then $(CYGPATH_W) 'src/processor/minidump.cc'; else $(CYGPATH_W) '$(srcdir)/src/processor/minidump.cc'; fi`
+
+src/processor/src_client_linux_linux_client_unittest_shlib-pathname_stripper.o: src/processor/pathname_stripper.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/processor/src_client_linux_linux_client_unittest_shlib-pathname_stripper.o -MD -MP -MF src/processor/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-pathname_stripper.Tpo -c -o src/processor/src_client_linux_linux_client_unittest_shlib-pathname_stripper.o `test -f 'src/processor/pathname_stripper.cc' || echo '$(srcdir)/'`src/processor/pathname_stripper.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/processor/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-pathname_stripper.Tpo src/processor/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-pathname_stripper.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/processor/pathname_stripper.cc' object='src/processor/src_client_linux_linux_client_unittest_shlib-pathname_stripper.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/processor/src_client_linux_linux_client_unittest_shlib-pathname_stripper.o `test -f 'src/processor/pathname_stripper.cc' || echo '$(srcdir)/'`src/processor/pathname_stripper.cc
+
+src/processor/src_client_linux_linux_client_unittest_shlib-pathname_stripper.obj: src/processor/pathname_stripper.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/processor/src_client_linux_linux_client_unittest_shlib-pathname_stripper.obj -MD -MP -MF src/processor/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-pathname_stripper.Tpo -c -o src/processor/src_client_linux_linux_client_unittest_shlib-pathname_stripper.obj `if test -f 'src/processor/pathname_stripper.cc'; then $(CYGPATH_W) 'src/processor/pathname_stripper.cc'; else $(CYGPATH_W) '$(srcdir)/src/processor/pathname_stripper.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/processor/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-pathname_stripper.Tpo src/processor/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-pathname_stripper.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/processor/pathname_stripper.cc' object='src/processor/src_client_linux_linux_client_unittest_shlib-pathname_stripper.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/processor/src_client_linux_linux_client_unittest_shlib-pathname_stripper.obj `if test -f 'src/processor/pathname_stripper.cc'; then $(CYGPATH_W) 'src/processor/pathname_stripper.cc'; else $(CYGPATH_W) '$(srcdir)/src/processor/pathname_stripper.cc'; fi`
+
+src/processor/src_client_linux_linux_client_unittest_shlib-proc_maps_linux.o: src/processor/proc_maps_linux.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/processor/src_client_linux_linux_client_unittest_shlib-proc_maps_linux.o -MD -MP -MF src/processor/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-proc_maps_linux.Tpo -c -o src/processor/src_client_linux_linux_client_unittest_shlib-proc_maps_linux.o `test -f 'src/processor/proc_maps_linux.cc' || echo '$(srcdir)/'`src/processor/proc_maps_linux.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/processor/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-proc_maps_linux.Tpo src/processor/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-proc_maps_linux.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/processor/proc_maps_linux.cc' object='src/processor/src_client_linux_linux_client_unittest_shlib-proc_maps_linux.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/processor/src_client_linux_linux_client_unittest_shlib-proc_maps_linux.o `test -f 'src/processor/proc_maps_linux.cc' || echo '$(srcdir)/'`src/processor/proc_maps_linux.cc
+
+src/processor/src_client_linux_linux_client_unittest_shlib-proc_maps_linux.obj: src/processor/proc_maps_linux.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/processor/src_client_linux_linux_client_unittest_shlib-proc_maps_linux.obj -MD -MP -MF src/processor/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-proc_maps_linux.Tpo -c -o src/processor/src_client_linux_linux_client_unittest_shlib-proc_maps_linux.obj `if test -f 'src/processor/proc_maps_linux.cc'; then $(CYGPATH_W) 'src/processor/proc_maps_linux.cc'; else $(CYGPATH_W) '$(srcdir)/src/processor/proc_maps_linux.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/processor/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-proc_maps_linux.Tpo src/processor/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-proc_maps_linux.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/processor/proc_maps_linux.cc' object='src/processor/src_client_linux_linux_client_unittest_shlib-proc_maps_linux.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/processor/src_client_linux_linux_client_unittest_shlib-proc_maps_linux.obj `if test -f 'src/processor/proc_maps_linux.cc'; then $(CYGPATH_W) 'src/processor/proc_maps_linux.cc'; else $(CYGPATH_W) '$(srcdir)/src/processor/proc_maps_linux.cc'; fi`
+
+src/client/linux/microdump_writer/src_client_linux_linux_client_unittest_shlib-microdump_writer_unittest.o: src/client/linux/microdump_writer/microdump_writer_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/client/linux/microdump_writer/src_client_linux_linux_client_unittest_shlib-microdump_writer_unittest.o -MD -MP -MF src/client/linux/microdump_writer/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-microdump_writer_unittest.Tpo -c -o src/client/linux/microdump_writer/src_client_linux_linux_client_unittest_shlib-microdump_writer_unittest.o `test -f 'src/client/linux/microdump_writer/microdump_writer_unittest.cc' || echo '$(srcdir)/'`src/client/linux/microdump_writer/microdump_writer_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/client/linux/microdump_writer/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-microdump_writer_unittest.Tpo src/client/linux/microdump_writer/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-microdump_writer_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/client/linux/microdump_writer/microdump_writer_unittest.cc' object='src/client/linux/microdump_writer/src_client_linux_linux_client_unittest_shlib-microdump_writer_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/client/linux/microdump_writer/src_client_linux_linux_client_unittest_shlib-microdump_writer_unittest.o `test -f 'src/client/linux/microdump_writer/microdump_writer_unittest.cc' || echo '$(srcdir)/'`src/client/linux/microdump_writer/microdump_writer_unittest.cc
+
+src/client/linux/microdump_writer/src_client_linux_linux_client_unittest_shlib-microdump_writer_unittest.obj: src/client/linux/microdump_writer/microdump_writer_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/client/linux/microdump_writer/src_client_linux_linux_client_unittest_shlib-microdump_writer_unittest.obj -MD -MP -MF src/client/linux/microdump_writer/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-microdump_writer_unittest.Tpo -c -o src/client/linux/microdump_writer/src_client_linux_linux_client_unittest_shlib-microdump_writer_unittest.obj `if test -f 'src/client/linux/microdump_writer/microdump_writer_unittest.cc'; then $(CYGPATH_W) 'src/client/linux/microdump_writer/microdump_writer_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/client/linux/microdump_writer/microdump_writer_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/client/linux/microdump_writer/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-microdump_writer_unittest.Tpo src/client/linux/microdump_writer/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-microdump_writer_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/client/linux/microdump_writer/microdump_writer_unittest.cc' object='src/client/linux/microdump_writer/src_client_linux_linux_client_unittest_shlib-microdump_writer_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/client/linux/microdump_writer/src_client_linux_linux_client_unittest_shlib-microdump_writer_unittest.obj `if test -f 'src/client/linux/microdump_writer/microdump_writer_unittest.cc'; then $(CYGPATH_W) 'src/client/linux/microdump_writer/microdump_writer_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/client/linux/microdump_writer/microdump_writer_unittest.cc'; fi`
+
+src/common/android/src_client_linux_linux_client_unittest_shlib-breakpad_getcontext_unittest.o: src/common/android/breakpad_getcontext_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/android/src_client_linux_linux_client_unittest_shlib-breakpad_getcontext_unittest.o -MD -MP -MF src/common/android/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-breakpad_getcontext_unittest.Tpo -c -o src/common/android/src_client_linux_linux_client_unittest_shlib-breakpad_getcontext_unittest.o `test -f 'src/common/android/breakpad_getcontext_unittest.cc' || echo '$(srcdir)/'`src/common/android/breakpad_getcontext_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/android/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-breakpad_getcontext_unittest.Tpo src/common/android/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-breakpad_getcontext_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/android/breakpad_getcontext_unittest.cc' object='src/common/android/src_client_linux_linux_client_unittest_shlib-breakpad_getcontext_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/android/src_client_linux_linux_client_unittest_shlib-breakpad_getcontext_unittest.o `test -f 'src/common/android/breakpad_getcontext_unittest.cc' || echo '$(srcdir)/'`src/common/android/breakpad_getcontext_unittest.cc
+
+src/common/android/src_client_linux_linux_client_unittest_shlib-breakpad_getcontext_unittest.obj: src/common/android/breakpad_getcontext_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/android/src_client_linux_linux_client_unittest_shlib-breakpad_getcontext_unittest.obj -MD -MP -MF src/common/android/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-breakpad_getcontext_unittest.Tpo -c -o src/common/android/src_client_linux_linux_client_unittest_shlib-breakpad_getcontext_unittest.obj `if test -f 'src/common/android/breakpad_getcontext_unittest.cc'; then $(CYGPATH_W) 'src/common/android/breakpad_getcontext_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/android/breakpad_getcontext_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/android/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-breakpad_getcontext_unittest.Tpo src/common/android/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-breakpad_getcontext_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/android/breakpad_getcontext_unittest.cc' object='src/common/android/src_client_linux_linux_client_unittest_shlib-breakpad_getcontext_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/android/src_client_linux_linux_client_unittest_shlib-breakpad_getcontext_unittest.obj `if test -f 'src/common/android/breakpad_getcontext_unittest.cc'; then $(CYGPATH_W) 'src/common/android/breakpad_getcontext_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/android/breakpad_getcontext_unittest.cc'; fi`
+
+src/client/linux/minidump_writer/src_client_linux_linux_dumper_unittest_helper-linux_dumper_unittest_helper.o: src/client/linux/minidump_writer/linux_dumper_unittest_helper.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_client_linux_linux_dumper_unittest_helper_CXXFLAGS) $(CXXFLAGS) -MT src/client/linux/minidump_writer/src_client_linux_linux_dumper_unittest_helper-linux_dumper_unittest_helper.o -MD -MP -MF src/client/linux/minidump_writer/$(DEPDIR)/src_client_linux_linux_dumper_unittest_helper-linux_dumper_unittest_helper.Tpo -c -o src/client/linux/minidump_writer/src_client_linux_linux_dumper_unittest_helper-linux_dumper_unittest_helper.o `test -f 'src/client/linux/minidump_writer/linux_dumper_unittest_helper.cc' || echo '$(srcdir)/'`src/client/linux/minidump_writer/linux_dumper_unittest_helper.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/client/linux/minidump_writer/$(DEPDIR)/src_client_linux_linux_dumper_unittest_helper-linux_dumper_unittest_helper.Tpo src/client/linux/minidump_writer/$(DEPDIR)/src_client_linux_linux_dumper_unittest_helper-linux_dumper_unittest_helper.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/client/linux/minidump_writer/linux_dumper_unittest_helper.cc' object='src/client/linux/minidump_writer/src_client_linux_linux_dumper_unittest_helper-linux_dumper_unittest_helper.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_client_linux_linux_dumper_unittest_helper_CXXFLAGS) $(CXXFLAGS) -c -o src/client/linux/minidump_writer/src_client_linux_linux_dumper_unittest_helper-linux_dumper_unittest_helper.o `test -f 'src/client/linux/minidump_writer/linux_dumper_unittest_helper.cc' || echo '$(srcdir)/'`src/client/linux/minidump_writer/linux_dumper_unittest_helper.cc
+
+src/client/linux/minidump_writer/src_client_linux_linux_dumper_unittest_helper-linux_dumper_unittest_helper.obj: src/client/linux/minidump_writer/linux_dumper_unittest_helper.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_client_linux_linux_dumper_unittest_helper_CXXFLAGS) $(CXXFLAGS) -MT src/client/linux/minidump_writer/src_client_linux_linux_dumper_unittest_helper-linux_dumper_unittest_helper.obj -MD -MP -MF src/client/linux/minidump_writer/$(DEPDIR)/src_client_linux_linux_dumper_unittest_helper-linux_dumper_unittest_helper.Tpo -c -o src/client/linux/minidump_writer/src_client_linux_linux_dumper_unittest_helper-linux_dumper_unittest_helper.obj `if test -f 'src/client/linux/minidump_writer/linux_dumper_unittest_helper.cc'; then $(CYGPATH_W) 'src/client/linux/minidump_writer/linux_dumper_unittest_helper.cc'; else $(CYGPATH_W) '$(srcdir)/src/client/linux/minidump_writer/linux_dumper_unittest_helper.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/client/linux/minidump_writer/$(DEPDIR)/src_client_linux_linux_dumper_unittest_helper-linux_dumper_unittest_helper.Tpo src/client/linux/minidump_writer/$(DEPDIR)/src_client_linux_linux_dumper_unittest_helper-linux_dumper_unittest_helper.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/client/linux/minidump_writer/linux_dumper_unittest_helper.cc' object='src/client/linux/minidump_writer/src_client_linux_linux_dumper_unittest_helper-linux_dumper_unittest_helper.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_client_linux_linux_dumper_unittest_helper_CXXFLAGS) $(CXXFLAGS) -c -o src/client/linux/minidump_writer/src_client_linux_linux_dumper_unittest_helper-linux_dumper_unittest_helper.obj `if test -f 'src/client/linux/minidump_writer/linux_dumper_unittest_helper.cc'; then $(CYGPATH_W) 'src/client/linux/minidump_writer/linux_dumper_unittest_helper.cc'; else $(CYGPATH_W) '$(srcdir)/src/client/linux/minidump_writer/linux_dumper_unittest_helper.cc'; fi`
+
+src/common/src_common_dumper_unittest-byte_cursor_unittest.o: src/common/byte_cursor_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_common_dumper_unittest-byte_cursor_unittest.o -MD -MP -MF src/common/$(DEPDIR)/src_common_dumper_unittest-byte_cursor_unittest.Tpo -c -o src/common/src_common_dumper_unittest-byte_cursor_unittest.o `test -f 'src/common/byte_cursor_unittest.cc' || echo '$(srcdir)/'`src/common/byte_cursor_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_common_dumper_unittest-byte_cursor_unittest.Tpo src/common/$(DEPDIR)/src_common_dumper_unittest-byte_cursor_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/byte_cursor_unittest.cc' object='src/common/src_common_dumper_unittest-byte_cursor_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_common_dumper_unittest-byte_cursor_unittest.o `test -f 'src/common/byte_cursor_unittest.cc' || echo '$(srcdir)/'`src/common/byte_cursor_unittest.cc
+
+src/common/src_common_dumper_unittest-byte_cursor_unittest.obj: src/common/byte_cursor_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_common_dumper_unittest-byte_cursor_unittest.obj -MD -MP -MF src/common/$(DEPDIR)/src_common_dumper_unittest-byte_cursor_unittest.Tpo -c -o src/common/src_common_dumper_unittest-byte_cursor_unittest.obj `if test -f 'src/common/byte_cursor_unittest.cc'; then $(CYGPATH_W) 'src/common/byte_cursor_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/byte_cursor_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_common_dumper_unittest-byte_cursor_unittest.Tpo src/common/$(DEPDIR)/src_common_dumper_unittest-byte_cursor_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/byte_cursor_unittest.cc' object='src/common/src_common_dumper_unittest-byte_cursor_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_common_dumper_unittest-byte_cursor_unittest.obj `if test -f 'src/common/byte_cursor_unittest.cc'; then $(CYGPATH_W) 'src/common/byte_cursor_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/byte_cursor_unittest.cc'; fi`
+
+src/common/src_common_dumper_unittest-dwarf_cfi_to_module.o: src/common/dwarf_cfi_to_module.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_common_dumper_unittest-dwarf_cfi_to_module.o -MD -MP -MF src/common/$(DEPDIR)/src_common_dumper_unittest-dwarf_cfi_to_module.Tpo -c -o src/common/src_common_dumper_unittest-dwarf_cfi_to_module.o `test -f 'src/common/dwarf_cfi_to_module.cc' || echo '$(srcdir)/'`src/common/dwarf_cfi_to_module.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_common_dumper_unittest-dwarf_cfi_to_module.Tpo src/common/$(DEPDIR)/src_common_dumper_unittest-dwarf_cfi_to_module.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/dwarf_cfi_to_module.cc' object='src/common/src_common_dumper_unittest-dwarf_cfi_to_module.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_common_dumper_unittest-dwarf_cfi_to_module.o `test -f 'src/common/dwarf_cfi_to_module.cc' || echo '$(srcdir)/'`src/common/dwarf_cfi_to_module.cc
+
+src/common/src_common_dumper_unittest-dwarf_cfi_to_module.obj: src/common/dwarf_cfi_to_module.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_common_dumper_unittest-dwarf_cfi_to_module.obj -MD -MP -MF src/common/$(DEPDIR)/src_common_dumper_unittest-dwarf_cfi_to_module.Tpo -c -o src/common/src_common_dumper_unittest-dwarf_cfi_to_module.obj `if test -f 'src/common/dwarf_cfi_to_module.cc'; then $(CYGPATH_W) 'src/common/dwarf_cfi_to_module.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/dwarf_cfi_to_module.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_common_dumper_unittest-dwarf_cfi_to_module.Tpo src/common/$(DEPDIR)/src_common_dumper_unittest-dwarf_cfi_to_module.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/dwarf_cfi_to_module.cc' object='src/common/src_common_dumper_unittest-dwarf_cfi_to_module.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_common_dumper_unittest-dwarf_cfi_to_module.obj `if test -f 'src/common/dwarf_cfi_to_module.cc'; then $(CYGPATH_W) 'src/common/dwarf_cfi_to_module.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/dwarf_cfi_to_module.cc'; fi`
+
+src/common/src_common_dumper_unittest-dwarf_cfi_to_module_unittest.o: src/common/dwarf_cfi_to_module_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_common_dumper_unittest-dwarf_cfi_to_module_unittest.o -MD -MP -MF src/common/$(DEPDIR)/src_common_dumper_unittest-dwarf_cfi_to_module_unittest.Tpo -c -o src/common/src_common_dumper_unittest-dwarf_cfi_to_module_unittest.o `test -f 'src/common/dwarf_cfi_to_module_unittest.cc' || echo '$(srcdir)/'`src/common/dwarf_cfi_to_module_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_common_dumper_unittest-dwarf_cfi_to_module_unittest.Tpo src/common/$(DEPDIR)/src_common_dumper_unittest-dwarf_cfi_to_module_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/dwarf_cfi_to_module_unittest.cc' object='src/common/src_common_dumper_unittest-dwarf_cfi_to_module_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_common_dumper_unittest-dwarf_cfi_to_module_unittest.o `test -f 'src/common/dwarf_cfi_to_module_unittest.cc' || echo '$(srcdir)/'`src/common/dwarf_cfi_to_module_unittest.cc
+
+src/common/src_common_dumper_unittest-dwarf_cfi_to_module_unittest.obj: src/common/dwarf_cfi_to_module_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_common_dumper_unittest-dwarf_cfi_to_module_unittest.obj -MD -MP -MF src/common/$(DEPDIR)/src_common_dumper_unittest-dwarf_cfi_to_module_unittest.Tpo -c -o src/common/src_common_dumper_unittest-dwarf_cfi_to_module_unittest.obj `if test -f 'src/common/dwarf_cfi_to_module_unittest.cc'; then $(CYGPATH_W) 'src/common/dwarf_cfi_to_module_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/dwarf_cfi_to_module_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_common_dumper_unittest-dwarf_cfi_to_module_unittest.Tpo src/common/$(DEPDIR)/src_common_dumper_unittest-dwarf_cfi_to_module_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/dwarf_cfi_to_module_unittest.cc' object='src/common/src_common_dumper_unittest-dwarf_cfi_to_module_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_common_dumper_unittest-dwarf_cfi_to_module_unittest.obj `if test -f 'src/common/dwarf_cfi_to_module_unittest.cc'; then $(CYGPATH_W) 'src/common/dwarf_cfi_to_module_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/dwarf_cfi_to_module_unittest.cc'; fi`
+
+src/common/src_common_dumper_unittest-dwarf_cu_to_module.o: src/common/dwarf_cu_to_module.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_common_dumper_unittest-dwarf_cu_to_module.o -MD -MP -MF src/common/$(DEPDIR)/src_common_dumper_unittest-dwarf_cu_to_module.Tpo -c -o src/common/src_common_dumper_unittest-dwarf_cu_to_module.o `test -f 'src/common/dwarf_cu_to_module.cc' || echo '$(srcdir)/'`src/common/dwarf_cu_to_module.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_common_dumper_unittest-dwarf_cu_to_module.Tpo src/common/$(DEPDIR)/src_common_dumper_unittest-dwarf_cu_to_module.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/dwarf_cu_to_module.cc' object='src/common/src_common_dumper_unittest-dwarf_cu_to_module.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_common_dumper_unittest-dwarf_cu_to_module.o `test -f 'src/common/dwarf_cu_to_module.cc' || echo '$(srcdir)/'`src/common/dwarf_cu_to_module.cc
+
+src/common/src_common_dumper_unittest-dwarf_cu_to_module.obj: src/common/dwarf_cu_to_module.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_common_dumper_unittest-dwarf_cu_to_module.obj -MD -MP -MF src/common/$(DEPDIR)/src_common_dumper_unittest-dwarf_cu_to_module.Tpo -c -o src/common/src_common_dumper_unittest-dwarf_cu_to_module.obj `if test -f 'src/common/dwarf_cu_to_module.cc'; then $(CYGPATH_W) 'src/common/dwarf_cu_to_module.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/dwarf_cu_to_module.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_common_dumper_unittest-dwarf_cu_to_module.Tpo src/common/$(DEPDIR)/src_common_dumper_unittest-dwarf_cu_to_module.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/dwarf_cu_to_module.cc' object='src/common/src_common_dumper_unittest-dwarf_cu_to_module.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_common_dumper_unittest-dwarf_cu_to_module.obj `if test -f 'src/common/dwarf_cu_to_module.cc'; then $(CYGPATH_W) 'src/common/dwarf_cu_to_module.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/dwarf_cu_to_module.cc'; fi`
+
+src/common/src_common_dumper_unittest-dwarf_cu_to_module_unittest.o: src/common/dwarf_cu_to_module_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_common_dumper_unittest-dwarf_cu_to_module_unittest.o -MD -MP -MF src/common/$(DEPDIR)/src_common_dumper_unittest-dwarf_cu_to_module_unittest.Tpo -c -o src/common/src_common_dumper_unittest-dwarf_cu_to_module_unittest.o `test -f 'src/common/dwarf_cu_to_module_unittest.cc' || echo '$(srcdir)/'`src/common/dwarf_cu_to_module_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_common_dumper_unittest-dwarf_cu_to_module_unittest.Tpo src/common/$(DEPDIR)/src_common_dumper_unittest-dwarf_cu_to_module_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/dwarf_cu_to_module_unittest.cc' object='src/common/src_common_dumper_unittest-dwarf_cu_to_module_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_common_dumper_unittest-dwarf_cu_to_module_unittest.o `test -f 'src/common/dwarf_cu_to_module_unittest.cc' || echo '$(srcdir)/'`src/common/dwarf_cu_to_module_unittest.cc
+
+src/common/src_common_dumper_unittest-dwarf_cu_to_module_unittest.obj: src/common/dwarf_cu_to_module_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_common_dumper_unittest-dwarf_cu_to_module_unittest.obj -MD -MP -MF src/common/$(DEPDIR)/src_common_dumper_unittest-dwarf_cu_to_module_unittest.Tpo -c -o src/common/src_common_dumper_unittest-dwarf_cu_to_module_unittest.obj `if test -f 'src/common/dwarf_cu_to_module_unittest.cc'; then $(CYGPATH_W) 'src/common/dwarf_cu_to_module_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/dwarf_cu_to_module_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_common_dumper_unittest-dwarf_cu_to_module_unittest.Tpo src/common/$(DEPDIR)/src_common_dumper_unittest-dwarf_cu_to_module_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/dwarf_cu_to_module_unittest.cc' object='src/common/src_common_dumper_unittest-dwarf_cu_to_module_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_common_dumper_unittest-dwarf_cu_to_module_unittest.obj `if test -f 'src/common/dwarf_cu_to_module_unittest.cc'; then $(CYGPATH_W) 'src/common/dwarf_cu_to_module_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/dwarf_cu_to_module_unittest.cc'; fi`
+
+src/common/src_common_dumper_unittest-dwarf_line_to_module.o: src/common/dwarf_line_to_module.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_common_dumper_unittest-dwarf_line_to_module.o -MD -MP -MF src/common/$(DEPDIR)/src_common_dumper_unittest-dwarf_line_to_module.Tpo -c -o src/common/src_common_dumper_unittest-dwarf_line_to_module.o `test -f 'src/common/dwarf_line_to_module.cc' || echo '$(srcdir)/'`src/common/dwarf_line_to_module.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_common_dumper_unittest-dwarf_line_to_module.Tpo src/common/$(DEPDIR)/src_common_dumper_unittest-dwarf_line_to_module.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/dwarf_line_to_module.cc' object='src/common/src_common_dumper_unittest-dwarf_line_to_module.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_common_dumper_unittest-dwarf_line_to_module.o `test -f 'src/common/dwarf_line_to_module.cc' || echo '$(srcdir)/'`src/common/dwarf_line_to_module.cc
+
+src/common/src_common_dumper_unittest-dwarf_line_to_module.obj: src/common/dwarf_line_to_module.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_common_dumper_unittest-dwarf_line_to_module.obj -MD -MP -MF src/common/$(DEPDIR)/src_common_dumper_unittest-dwarf_line_to_module.Tpo -c -o src/common/src_common_dumper_unittest-dwarf_line_to_module.obj `if test -f 'src/common/dwarf_line_to_module.cc'; then $(CYGPATH_W) 'src/common/dwarf_line_to_module.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/dwarf_line_to_module.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_common_dumper_unittest-dwarf_line_to_module.Tpo src/common/$(DEPDIR)/src_common_dumper_unittest-dwarf_line_to_module.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/dwarf_line_to_module.cc' object='src/common/src_common_dumper_unittest-dwarf_line_to_module.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_common_dumper_unittest-dwarf_line_to_module.obj `if test -f 'src/common/dwarf_line_to_module.cc'; then $(CYGPATH_W) 'src/common/dwarf_line_to_module.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/dwarf_line_to_module.cc'; fi`
+
+src/common/src_common_dumper_unittest-dwarf_line_to_module_unittest.o: src/common/dwarf_line_to_module_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_common_dumper_unittest-dwarf_line_to_module_unittest.o -MD -MP -MF src/common/$(DEPDIR)/src_common_dumper_unittest-dwarf_line_to_module_unittest.Tpo -c -o src/common/src_common_dumper_unittest-dwarf_line_to_module_unittest.o `test -f 'src/common/dwarf_line_to_module_unittest.cc' || echo '$(srcdir)/'`src/common/dwarf_line_to_module_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_common_dumper_unittest-dwarf_line_to_module_unittest.Tpo src/common/$(DEPDIR)/src_common_dumper_unittest-dwarf_line_to_module_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/dwarf_line_to_module_unittest.cc' object='src/common/src_common_dumper_unittest-dwarf_line_to_module_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_common_dumper_unittest-dwarf_line_to_module_unittest.o `test -f 'src/common/dwarf_line_to_module_unittest.cc' || echo '$(srcdir)/'`src/common/dwarf_line_to_module_unittest.cc
+
+src/common/src_common_dumper_unittest-dwarf_line_to_module_unittest.obj: src/common/dwarf_line_to_module_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_common_dumper_unittest-dwarf_line_to_module_unittest.obj -MD -MP -MF src/common/$(DEPDIR)/src_common_dumper_unittest-dwarf_line_to_module_unittest.Tpo -c -o src/common/src_common_dumper_unittest-dwarf_line_to_module_unittest.obj `if test -f 'src/common/dwarf_line_to_module_unittest.cc'; then $(CYGPATH_W) 'src/common/dwarf_line_to_module_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/dwarf_line_to_module_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_common_dumper_unittest-dwarf_line_to_module_unittest.Tpo src/common/$(DEPDIR)/src_common_dumper_unittest-dwarf_line_to_module_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/dwarf_line_to_module_unittest.cc' object='src/common/src_common_dumper_unittest-dwarf_line_to_module_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_common_dumper_unittest-dwarf_line_to_module_unittest.obj `if test -f 'src/common/dwarf_line_to_module_unittest.cc'; then $(CYGPATH_W) 'src/common/dwarf_line_to_module_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/dwarf_line_to_module_unittest.cc'; fi`
+
+src/common/src_common_dumper_unittest-language.o: src/common/language.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_common_dumper_unittest-language.o -MD -MP -MF src/common/$(DEPDIR)/src_common_dumper_unittest-language.Tpo -c -o src/common/src_common_dumper_unittest-language.o `test -f 'src/common/language.cc' || echo '$(srcdir)/'`src/common/language.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_common_dumper_unittest-language.Tpo src/common/$(DEPDIR)/src_common_dumper_unittest-language.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/language.cc' object='src/common/src_common_dumper_unittest-language.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_common_dumper_unittest-language.o `test -f 'src/common/language.cc' || echo '$(srcdir)/'`src/common/language.cc
+
+src/common/src_common_dumper_unittest-language.obj: src/common/language.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_common_dumper_unittest-language.obj -MD -MP -MF src/common/$(DEPDIR)/src_common_dumper_unittest-language.Tpo -c -o src/common/src_common_dumper_unittest-language.obj `if test -f 'src/common/language.cc'; then $(CYGPATH_W) 'src/common/language.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/language.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_common_dumper_unittest-language.Tpo src/common/$(DEPDIR)/src_common_dumper_unittest-language.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/language.cc' object='src/common/src_common_dumper_unittest-language.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_common_dumper_unittest-language.obj `if test -f 'src/common/language.cc'; then $(CYGPATH_W) 'src/common/language.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/language.cc'; fi`
+
+src/common/src_common_dumper_unittest-memory_range_unittest.o: src/common/memory_range_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_common_dumper_unittest-memory_range_unittest.o -MD -MP -MF src/common/$(DEPDIR)/src_common_dumper_unittest-memory_range_unittest.Tpo -c -o src/common/src_common_dumper_unittest-memory_range_unittest.o `test -f 'src/common/memory_range_unittest.cc' || echo '$(srcdir)/'`src/common/memory_range_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_common_dumper_unittest-memory_range_unittest.Tpo src/common/$(DEPDIR)/src_common_dumper_unittest-memory_range_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/memory_range_unittest.cc' object='src/common/src_common_dumper_unittest-memory_range_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_common_dumper_unittest-memory_range_unittest.o `test -f 'src/common/memory_range_unittest.cc' || echo '$(srcdir)/'`src/common/memory_range_unittest.cc
+
+src/common/src_common_dumper_unittest-memory_range_unittest.obj: src/common/memory_range_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_common_dumper_unittest-memory_range_unittest.obj -MD -MP -MF src/common/$(DEPDIR)/src_common_dumper_unittest-memory_range_unittest.Tpo -c -o src/common/src_common_dumper_unittest-memory_range_unittest.obj `if test -f 'src/common/memory_range_unittest.cc'; then $(CYGPATH_W) 'src/common/memory_range_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/memory_range_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_common_dumper_unittest-memory_range_unittest.Tpo src/common/$(DEPDIR)/src_common_dumper_unittest-memory_range_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/memory_range_unittest.cc' object='src/common/src_common_dumper_unittest-memory_range_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_common_dumper_unittest-memory_range_unittest.obj `if test -f 'src/common/memory_range_unittest.cc'; then $(CYGPATH_W) 'src/common/memory_range_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/memory_range_unittest.cc'; fi`
+
+src/common/src_common_dumper_unittest-module.o: src/common/module.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_common_dumper_unittest-module.o -MD -MP -MF src/common/$(DEPDIR)/src_common_dumper_unittest-module.Tpo -c -o src/common/src_common_dumper_unittest-module.o `test -f 'src/common/module.cc' || echo '$(srcdir)/'`src/common/module.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_common_dumper_unittest-module.Tpo src/common/$(DEPDIR)/src_common_dumper_unittest-module.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/module.cc' object='src/common/src_common_dumper_unittest-module.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_common_dumper_unittest-module.o `test -f 'src/common/module.cc' || echo '$(srcdir)/'`src/common/module.cc
+
+src/common/src_common_dumper_unittest-module.obj: src/common/module.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_common_dumper_unittest-module.obj -MD -MP -MF src/common/$(DEPDIR)/src_common_dumper_unittest-module.Tpo -c -o src/common/src_common_dumper_unittest-module.obj `if test -f 'src/common/module.cc'; then $(CYGPATH_W) 'src/common/module.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/module.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_common_dumper_unittest-module.Tpo src/common/$(DEPDIR)/src_common_dumper_unittest-module.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/module.cc' object='src/common/src_common_dumper_unittest-module.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_common_dumper_unittest-module.obj `if test -f 'src/common/module.cc'; then $(CYGPATH_W) 'src/common/module.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/module.cc'; fi`
+
+src/common/src_common_dumper_unittest-module_unittest.o: src/common/module_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_common_dumper_unittest-module_unittest.o -MD -MP -MF src/common/$(DEPDIR)/src_common_dumper_unittest-module_unittest.Tpo -c -o src/common/src_common_dumper_unittest-module_unittest.o `test -f 'src/common/module_unittest.cc' || echo '$(srcdir)/'`src/common/module_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_common_dumper_unittest-module_unittest.Tpo src/common/$(DEPDIR)/src_common_dumper_unittest-module_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/module_unittest.cc' object='src/common/src_common_dumper_unittest-module_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_common_dumper_unittest-module_unittest.o `test -f 'src/common/module_unittest.cc' || echo '$(srcdir)/'`src/common/module_unittest.cc
+
+src/common/src_common_dumper_unittest-module_unittest.obj: src/common/module_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_common_dumper_unittest-module_unittest.obj -MD -MP -MF src/common/$(DEPDIR)/src_common_dumper_unittest-module_unittest.Tpo -c -o src/common/src_common_dumper_unittest-module_unittest.obj `if test -f 'src/common/module_unittest.cc'; then $(CYGPATH_W) 'src/common/module_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/module_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_common_dumper_unittest-module_unittest.Tpo src/common/$(DEPDIR)/src_common_dumper_unittest-module_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/module_unittest.cc' object='src/common/src_common_dumper_unittest-module_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_common_dumper_unittest-module_unittest.obj `if test -f 'src/common/module_unittest.cc'; then $(CYGPATH_W) 'src/common/module_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/module_unittest.cc'; fi`
+
+src/common/src_common_dumper_unittest-stabs_reader.o: src/common/stabs_reader.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_common_dumper_unittest-stabs_reader.o -MD -MP -MF src/common/$(DEPDIR)/src_common_dumper_unittest-stabs_reader.Tpo -c -o src/common/src_common_dumper_unittest-stabs_reader.o `test -f 'src/common/stabs_reader.cc' || echo '$(srcdir)/'`src/common/stabs_reader.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_common_dumper_unittest-stabs_reader.Tpo src/common/$(DEPDIR)/src_common_dumper_unittest-stabs_reader.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/stabs_reader.cc' object='src/common/src_common_dumper_unittest-stabs_reader.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_common_dumper_unittest-stabs_reader.o `test -f 'src/common/stabs_reader.cc' || echo '$(srcdir)/'`src/common/stabs_reader.cc
+
+src/common/src_common_dumper_unittest-stabs_reader.obj: src/common/stabs_reader.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_common_dumper_unittest-stabs_reader.obj -MD -MP -MF src/common/$(DEPDIR)/src_common_dumper_unittest-stabs_reader.Tpo -c -o src/common/src_common_dumper_unittest-stabs_reader.obj `if test -f 'src/common/stabs_reader.cc'; then $(CYGPATH_W) 'src/common/stabs_reader.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/stabs_reader.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_common_dumper_unittest-stabs_reader.Tpo src/common/$(DEPDIR)/src_common_dumper_unittest-stabs_reader.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/stabs_reader.cc' object='src/common/src_common_dumper_unittest-stabs_reader.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_common_dumper_unittest-stabs_reader.obj `if test -f 'src/common/stabs_reader.cc'; then $(CYGPATH_W) 'src/common/stabs_reader.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/stabs_reader.cc'; fi`
+
+src/common/src_common_dumper_unittest-stabs_reader_unittest.o: src/common/stabs_reader_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_common_dumper_unittest-stabs_reader_unittest.o -MD -MP -MF src/common/$(DEPDIR)/src_common_dumper_unittest-stabs_reader_unittest.Tpo -c -o src/common/src_common_dumper_unittest-stabs_reader_unittest.o `test -f 'src/common/stabs_reader_unittest.cc' || echo '$(srcdir)/'`src/common/stabs_reader_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_common_dumper_unittest-stabs_reader_unittest.Tpo src/common/$(DEPDIR)/src_common_dumper_unittest-stabs_reader_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/stabs_reader_unittest.cc' object='src/common/src_common_dumper_unittest-stabs_reader_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_common_dumper_unittest-stabs_reader_unittest.o `test -f 'src/common/stabs_reader_unittest.cc' || echo '$(srcdir)/'`src/common/stabs_reader_unittest.cc
+
+src/common/src_common_dumper_unittest-stabs_reader_unittest.obj: src/common/stabs_reader_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_common_dumper_unittest-stabs_reader_unittest.obj -MD -MP -MF src/common/$(DEPDIR)/src_common_dumper_unittest-stabs_reader_unittest.Tpo -c -o src/common/src_common_dumper_unittest-stabs_reader_unittest.obj `if test -f 'src/common/stabs_reader_unittest.cc'; then $(CYGPATH_W) 'src/common/stabs_reader_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/stabs_reader_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_common_dumper_unittest-stabs_reader_unittest.Tpo src/common/$(DEPDIR)/src_common_dumper_unittest-stabs_reader_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/stabs_reader_unittest.cc' object='src/common/src_common_dumper_unittest-stabs_reader_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_common_dumper_unittest-stabs_reader_unittest.obj `if test -f 'src/common/stabs_reader_unittest.cc'; then $(CYGPATH_W) 'src/common/stabs_reader_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/stabs_reader_unittest.cc'; fi`
+
+src/common/src_common_dumper_unittest-stabs_to_module.o: src/common/stabs_to_module.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_common_dumper_unittest-stabs_to_module.o -MD -MP -MF src/common/$(DEPDIR)/src_common_dumper_unittest-stabs_to_module.Tpo -c -o src/common/src_common_dumper_unittest-stabs_to_module.o `test -f 'src/common/stabs_to_module.cc' || echo '$(srcdir)/'`src/common/stabs_to_module.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_common_dumper_unittest-stabs_to_module.Tpo src/common/$(DEPDIR)/src_common_dumper_unittest-stabs_to_module.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/stabs_to_module.cc' object='src/common/src_common_dumper_unittest-stabs_to_module.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_common_dumper_unittest-stabs_to_module.o `test -f 'src/common/stabs_to_module.cc' || echo '$(srcdir)/'`src/common/stabs_to_module.cc
+
+src/common/src_common_dumper_unittest-stabs_to_module.obj: src/common/stabs_to_module.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_common_dumper_unittest-stabs_to_module.obj -MD -MP -MF src/common/$(DEPDIR)/src_common_dumper_unittest-stabs_to_module.Tpo -c -o src/common/src_common_dumper_unittest-stabs_to_module.obj `if test -f 'src/common/stabs_to_module.cc'; then $(CYGPATH_W) 'src/common/stabs_to_module.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/stabs_to_module.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_common_dumper_unittest-stabs_to_module.Tpo src/common/$(DEPDIR)/src_common_dumper_unittest-stabs_to_module.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/stabs_to_module.cc' object='src/common/src_common_dumper_unittest-stabs_to_module.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_common_dumper_unittest-stabs_to_module.obj `if test -f 'src/common/stabs_to_module.cc'; then $(CYGPATH_W) 'src/common/stabs_to_module.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/stabs_to_module.cc'; fi`
+
+src/common/src_common_dumper_unittest-stabs_to_module_unittest.o: src/common/stabs_to_module_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_common_dumper_unittest-stabs_to_module_unittest.o -MD -MP -MF src/common/$(DEPDIR)/src_common_dumper_unittest-stabs_to_module_unittest.Tpo -c -o src/common/src_common_dumper_unittest-stabs_to_module_unittest.o `test -f 'src/common/stabs_to_module_unittest.cc' || echo '$(srcdir)/'`src/common/stabs_to_module_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_common_dumper_unittest-stabs_to_module_unittest.Tpo src/common/$(DEPDIR)/src_common_dumper_unittest-stabs_to_module_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/stabs_to_module_unittest.cc' object='src/common/src_common_dumper_unittest-stabs_to_module_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_common_dumper_unittest-stabs_to_module_unittest.o `test -f 'src/common/stabs_to_module_unittest.cc' || echo '$(srcdir)/'`src/common/stabs_to_module_unittest.cc
+
+src/common/src_common_dumper_unittest-stabs_to_module_unittest.obj: src/common/stabs_to_module_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_common_dumper_unittest-stabs_to_module_unittest.obj -MD -MP -MF src/common/$(DEPDIR)/src_common_dumper_unittest-stabs_to_module_unittest.Tpo -c -o src/common/src_common_dumper_unittest-stabs_to_module_unittest.obj `if test -f 'src/common/stabs_to_module_unittest.cc'; then $(CYGPATH_W) 'src/common/stabs_to_module_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/stabs_to_module_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_common_dumper_unittest-stabs_to_module_unittest.Tpo src/common/$(DEPDIR)/src_common_dumper_unittest-stabs_to_module_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/stabs_to_module_unittest.cc' object='src/common/src_common_dumper_unittest-stabs_to_module_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_common_dumper_unittest-stabs_to_module_unittest.obj `if test -f 'src/common/stabs_to_module_unittest.cc'; then $(CYGPATH_W) 'src/common/stabs_to_module_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/stabs_to_module_unittest.cc'; fi`
+
+src/common/src_common_dumper_unittest-test_assembler.o: src/common/test_assembler.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_common_dumper_unittest-test_assembler.o -MD -MP -MF src/common/$(DEPDIR)/src_common_dumper_unittest-test_assembler.Tpo -c -o src/common/src_common_dumper_unittest-test_assembler.o `test -f 'src/common/test_assembler.cc' || echo '$(srcdir)/'`src/common/test_assembler.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_common_dumper_unittest-test_assembler.Tpo src/common/$(DEPDIR)/src_common_dumper_unittest-test_assembler.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/test_assembler.cc' object='src/common/src_common_dumper_unittest-test_assembler.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_common_dumper_unittest-test_assembler.o `test -f 'src/common/test_assembler.cc' || echo '$(srcdir)/'`src/common/test_assembler.cc
+
+src/common/src_common_dumper_unittest-test_assembler.obj: src/common/test_assembler.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_common_dumper_unittest-test_assembler.obj -MD -MP -MF src/common/$(DEPDIR)/src_common_dumper_unittest-test_assembler.Tpo -c -o src/common/src_common_dumper_unittest-test_assembler.obj `if test -f 'src/common/test_assembler.cc'; then $(CYGPATH_W) 'src/common/test_assembler.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/test_assembler.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_common_dumper_unittest-test_assembler.Tpo src/common/$(DEPDIR)/src_common_dumper_unittest-test_assembler.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/test_assembler.cc' object='src/common/src_common_dumper_unittest-test_assembler.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_common_dumper_unittest-test_assembler.obj `if test -f 'src/common/test_assembler.cc'; then $(CYGPATH_W) 'src/common/test_assembler.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/test_assembler.cc'; fi`
+
+src/common/dwarf/src_common_dumper_unittest-bytereader.o: src/common/dwarf/bytereader.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/dwarf/src_common_dumper_unittest-bytereader.o -MD -MP -MF src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-bytereader.Tpo -c -o src/common/dwarf/src_common_dumper_unittest-bytereader.o `test -f 'src/common/dwarf/bytereader.cc' || echo '$(srcdir)/'`src/common/dwarf/bytereader.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-bytereader.Tpo src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-bytereader.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/dwarf/bytereader.cc' object='src/common/dwarf/src_common_dumper_unittest-bytereader.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/dwarf/src_common_dumper_unittest-bytereader.o `test -f 'src/common/dwarf/bytereader.cc' || echo '$(srcdir)/'`src/common/dwarf/bytereader.cc
+
+src/common/dwarf/src_common_dumper_unittest-bytereader.obj: src/common/dwarf/bytereader.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/dwarf/src_common_dumper_unittest-bytereader.obj -MD -MP -MF src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-bytereader.Tpo -c -o src/common/dwarf/src_common_dumper_unittest-bytereader.obj `if test -f 'src/common/dwarf/bytereader.cc'; then $(CYGPATH_W) 'src/common/dwarf/bytereader.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/dwarf/bytereader.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-bytereader.Tpo src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-bytereader.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/dwarf/bytereader.cc' object='src/common/dwarf/src_common_dumper_unittest-bytereader.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/dwarf/src_common_dumper_unittest-bytereader.obj `if test -f 'src/common/dwarf/bytereader.cc'; then $(CYGPATH_W) 'src/common/dwarf/bytereader.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/dwarf/bytereader.cc'; fi`
+
+src/common/dwarf/src_common_dumper_unittest-bytereader_unittest.o: src/common/dwarf/bytereader_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/dwarf/src_common_dumper_unittest-bytereader_unittest.o -MD -MP -MF src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-bytereader_unittest.Tpo -c -o src/common/dwarf/src_common_dumper_unittest-bytereader_unittest.o `test -f 'src/common/dwarf/bytereader_unittest.cc' || echo '$(srcdir)/'`src/common/dwarf/bytereader_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-bytereader_unittest.Tpo src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-bytereader_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/dwarf/bytereader_unittest.cc' object='src/common/dwarf/src_common_dumper_unittest-bytereader_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/dwarf/src_common_dumper_unittest-bytereader_unittest.o `test -f 'src/common/dwarf/bytereader_unittest.cc' || echo '$(srcdir)/'`src/common/dwarf/bytereader_unittest.cc
+
+src/common/dwarf/src_common_dumper_unittest-bytereader_unittest.obj: src/common/dwarf/bytereader_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/dwarf/src_common_dumper_unittest-bytereader_unittest.obj -MD -MP -MF src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-bytereader_unittest.Tpo -c -o src/common/dwarf/src_common_dumper_unittest-bytereader_unittest.obj `if test -f 'src/common/dwarf/bytereader_unittest.cc'; then $(CYGPATH_W) 'src/common/dwarf/bytereader_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/dwarf/bytereader_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-bytereader_unittest.Tpo src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-bytereader_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/dwarf/bytereader_unittest.cc' object='src/common/dwarf/src_common_dumper_unittest-bytereader_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/dwarf/src_common_dumper_unittest-bytereader_unittest.obj `if test -f 'src/common/dwarf/bytereader_unittest.cc'; then $(CYGPATH_W) 'src/common/dwarf/bytereader_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/dwarf/bytereader_unittest.cc'; fi`
+
+src/common/dwarf/src_common_dumper_unittest-cfi_assembler.o: src/common/dwarf/cfi_assembler.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/dwarf/src_common_dumper_unittest-cfi_assembler.o -MD -MP -MF src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-cfi_assembler.Tpo -c -o src/common/dwarf/src_common_dumper_unittest-cfi_assembler.o `test -f 'src/common/dwarf/cfi_assembler.cc' || echo '$(srcdir)/'`src/common/dwarf/cfi_assembler.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-cfi_assembler.Tpo src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-cfi_assembler.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/dwarf/cfi_assembler.cc' object='src/common/dwarf/src_common_dumper_unittest-cfi_assembler.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/dwarf/src_common_dumper_unittest-cfi_assembler.o `test -f 'src/common/dwarf/cfi_assembler.cc' || echo '$(srcdir)/'`src/common/dwarf/cfi_assembler.cc
+
+src/common/dwarf/src_common_dumper_unittest-cfi_assembler.obj: src/common/dwarf/cfi_assembler.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/dwarf/src_common_dumper_unittest-cfi_assembler.obj -MD -MP -MF src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-cfi_assembler.Tpo -c -o src/common/dwarf/src_common_dumper_unittest-cfi_assembler.obj `if test -f 'src/common/dwarf/cfi_assembler.cc'; then $(CYGPATH_W) 'src/common/dwarf/cfi_assembler.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/dwarf/cfi_assembler.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-cfi_assembler.Tpo src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-cfi_assembler.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/dwarf/cfi_assembler.cc' object='src/common/dwarf/src_common_dumper_unittest-cfi_assembler.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/dwarf/src_common_dumper_unittest-cfi_assembler.obj `if test -f 'src/common/dwarf/cfi_assembler.cc'; then $(CYGPATH_W) 'src/common/dwarf/cfi_assembler.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/dwarf/cfi_assembler.cc'; fi`
+
+src/common/dwarf/src_common_dumper_unittest-dwarf2diehandler.o: src/common/dwarf/dwarf2diehandler.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/dwarf/src_common_dumper_unittest-dwarf2diehandler.o -MD -MP -MF src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-dwarf2diehandler.Tpo -c -o src/common/dwarf/src_common_dumper_unittest-dwarf2diehandler.o `test -f 'src/common/dwarf/dwarf2diehandler.cc' || echo '$(srcdir)/'`src/common/dwarf/dwarf2diehandler.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-dwarf2diehandler.Tpo src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-dwarf2diehandler.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/dwarf/dwarf2diehandler.cc' object='src/common/dwarf/src_common_dumper_unittest-dwarf2diehandler.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/dwarf/src_common_dumper_unittest-dwarf2diehandler.o `test -f 'src/common/dwarf/dwarf2diehandler.cc' || echo '$(srcdir)/'`src/common/dwarf/dwarf2diehandler.cc
+
+src/common/dwarf/src_common_dumper_unittest-dwarf2diehandler.obj: src/common/dwarf/dwarf2diehandler.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/dwarf/src_common_dumper_unittest-dwarf2diehandler.obj -MD -MP -MF src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-dwarf2diehandler.Tpo -c -o src/common/dwarf/src_common_dumper_unittest-dwarf2diehandler.obj `if test -f 'src/common/dwarf/dwarf2diehandler.cc'; then $(CYGPATH_W) 'src/common/dwarf/dwarf2diehandler.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/dwarf/dwarf2diehandler.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-dwarf2diehandler.Tpo src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-dwarf2diehandler.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/dwarf/dwarf2diehandler.cc' object='src/common/dwarf/src_common_dumper_unittest-dwarf2diehandler.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/dwarf/src_common_dumper_unittest-dwarf2diehandler.obj `if test -f 'src/common/dwarf/dwarf2diehandler.cc'; then $(CYGPATH_W) 'src/common/dwarf/dwarf2diehandler.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/dwarf/dwarf2diehandler.cc'; fi`
+
+src/common/dwarf/src_common_dumper_unittest-dwarf2diehandler_unittest.o: src/common/dwarf/dwarf2diehandler_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/dwarf/src_common_dumper_unittest-dwarf2diehandler_unittest.o -MD -MP -MF src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-dwarf2diehandler_unittest.Tpo -c -o src/common/dwarf/src_common_dumper_unittest-dwarf2diehandler_unittest.o `test -f 'src/common/dwarf/dwarf2diehandler_unittest.cc' || echo '$(srcdir)/'`src/common/dwarf/dwarf2diehandler_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-dwarf2diehandler_unittest.Tpo src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-dwarf2diehandler_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/dwarf/dwarf2diehandler_unittest.cc' object='src/common/dwarf/src_common_dumper_unittest-dwarf2diehandler_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/dwarf/src_common_dumper_unittest-dwarf2diehandler_unittest.o `test -f 'src/common/dwarf/dwarf2diehandler_unittest.cc' || echo '$(srcdir)/'`src/common/dwarf/dwarf2diehandler_unittest.cc
+
+src/common/dwarf/src_common_dumper_unittest-dwarf2diehandler_unittest.obj: src/common/dwarf/dwarf2diehandler_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/dwarf/src_common_dumper_unittest-dwarf2diehandler_unittest.obj -MD -MP -MF src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-dwarf2diehandler_unittest.Tpo -c -o src/common/dwarf/src_common_dumper_unittest-dwarf2diehandler_unittest.obj `if test -f 'src/common/dwarf/dwarf2diehandler_unittest.cc'; then $(CYGPATH_W) 'src/common/dwarf/dwarf2diehandler_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/dwarf/dwarf2diehandler_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-dwarf2diehandler_unittest.Tpo src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-dwarf2diehandler_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/dwarf/dwarf2diehandler_unittest.cc' object='src/common/dwarf/src_common_dumper_unittest-dwarf2diehandler_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/dwarf/src_common_dumper_unittest-dwarf2diehandler_unittest.obj `if test -f 'src/common/dwarf/dwarf2diehandler_unittest.cc'; then $(CYGPATH_W) 'src/common/dwarf/dwarf2diehandler_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/dwarf/dwarf2diehandler_unittest.cc'; fi`
+
+src/common/dwarf/src_common_dumper_unittest-dwarf2reader.o: src/common/dwarf/dwarf2reader.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/dwarf/src_common_dumper_unittest-dwarf2reader.o -MD -MP -MF src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-dwarf2reader.Tpo -c -o src/common/dwarf/src_common_dumper_unittest-dwarf2reader.o `test -f 'src/common/dwarf/dwarf2reader.cc' || echo '$(srcdir)/'`src/common/dwarf/dwarf2reader.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-dwarf2reader.Tpo src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-dwarf2reader.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/dwarf/dwarf2reader.cc' object='src/common/dwarf/src_common_dumper_unittest-dwarf2reader.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/dwarf/src_common_dumper_unittest-dwarf2reader.o `test -f 'src/common/dwarf/dwarf2reader.cc' || echo '$(srcdir)/'`src/common/dwarf/dwarf2reader.cc
+
+src/common/dwarf/src_common_dumper_unittest-dwarf2reader.obj: src/common/dwarf/dwarf2reader.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/dwarf/src_common_dumper_unittest-dwarf2reader.obj -MD -MP -MF src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-dwarf2reader.Tpo -c -o src/common/dwarf/src_common_dumper_unittest-dwarf2reader.obj `if test -f 'src/common/dwarf/dwarf2reader.cc'; then $(CYGPATH_W) 'src/common/dwarf/dwarf2reader.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/dwarf/dwarf2reader.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-dwarf2reader.Tpo src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-dwarf2reader.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/dwarf/dwarf2reader.cc' object='src/common/dwarf/src_common_dumper_unittest-dwarf2reader.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/dwarf/src_common_dumper_unittest-dwarf2reader.obj `if test -f 'src/common/dwarf/dwarf2reader.cc'; then $(CYGPATH_W) 'src/common/dwarf/dwarf2reader.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/dwarf/dwarf2reader.cc'; fi`
+
+src/common/dwarf/src_common_dumper_unittest-elf_reader.o: src/common/dwarf/elf_reader.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/dwarf/src_common_dumper_unittest-elf_reader.o -MD -MP -MF src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-elf_reader.Tpo -c -o src/common/dwarf/src_common_dumper_unittest-elf_reader.o `test -f 'src/common/dwarf/elf_reader.cc' || echo '$(srcdir)/'`src/common/dwarf/elf_reader.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-elf_reader.Tpo src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-elf_reader.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/dwarf/elf_reader.cc' object='src/common/dwarf/src_common_dumper_unittest-elf_reader.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/dwarf/src_common_dumper_unittest-elf_reader.o `test -f 'src/common/dwarf/elf_reader.cc' || echo '$(srcdir)/'`src/common/dwarf/elf_reader.cc
+
+src/common/dwarf/src_common_dumper_unittest-elf_reader.obj: src/common/dwarf/elf_reader.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/dwarf/src_common_dumper_unittest-elf_reader.obj -MD -MP -MF src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-elf_reader.Tpo -c -o src/common/dwarf/src_common_dumper_unittest-elf_reader.obj `if test -f 'src/common/dwarf/elf_reader.cc'; then $(CYGPATH_W) 'src/common/dwarf/elf_reader.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/dwarf/elf_reader.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-elf_reader.Tpo src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-elf_reader.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/dwarf/elf_reader.cc' object='src/common/dwarf/src_common_dumper_unittest-elf_reader.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/dwarf/src_common_dumper_unittest-elf_reader.obj `if test -f 'src/common/dwarf/elf_reader.cc'; then $(CYGPATH_W) 'src/common/dwarf/elf_reader.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/dwarf/elf_reader.cc'; fi`
+
+src/common/dwarf/src_common_dumper_unittest-dwarf2reader_cfi_unittest.o: src/common/dwarf/dwarf2reader_cfi_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/dwarf/src_common_dumper_unittest-dwarf2reader_cfi_unittest.o -MD -MP -MF src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-dwarf2reader_cfi_unittest.Tpo -c -o src/common/dwarf/src_common_dumper_unittest-dwarf2reader_cfi_unittest.o `test -f 'src/common/dwarf/dwarf2reader_cfi_unittest.cc' || echo '$(srcdir)/'`src/common/dwarf/dwarf2reader_cfi_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-dwarf2reader_cfi_unittest.Tpo src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-dwarf2reader_cfi_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/dwarf/dwarf2reader_cfi_unittest.cc' object='src/common/dwarf/src_common_dumper_unittest-dwarf2reader_cfi_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/dwarf/src_common_dumper_unittest-dwarf2reader_cfi_unittest.o `test -f 'src/common/dwarf/dwarf2reader_cfi_unittest.cc' || echo '$(srcdir)/'`src/common/dwarf/dwarf2reader_cfi_unittest.cc
+
+src/common/dwarf/src_common_dumper_unittest-dwarf2reader_cfi_unittest.obj: src/common/dwarf/dwarf2reader_cfi_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/dwarf/src_common_dumper_unittest-dwarf2reader_cfi_unittest.obj -MD -MP -MF src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-dwarf2reader_cfi_unittest.Tpo -c -o src/common/dwarf/src_common_dumper_unittest-dwarf2reader_cfi_unittest.obj `if test -f 'src/common/dwarf/dwarf2reader_cfi_unittest.cc'; then $(CYGPATH_W) 'src/common/dwarf/dwarf2reader_cfi_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/dwarf/dwarf2reader_cfi_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-dwarf2reader_cfi_unittest.Tpo src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-dwarf2reader_cfi_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/dwarf/dwarf2reader_cfi_unittest.cc' object='src/common/dwarf/src_common_dumper_unittest-dwarf2reader_cfi_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/dwarf/src_common_dumper_unittest-dwarf2reader_cfi_unittest.obj `if test -f 'src/common/dwarf/dwarf2reader_cfi_unittest.cc'; then $(CYGPATH_W) 'src/common/dwarf/dwarf2reader_cfi_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/dwarf/dwarf2reader_cfi_unittest.cc'; fi`
+
+src/common/dwarf/src_common_dumper_unittest-dwarf2reader_die_unittest.o: src/common/dwarf/dwarf2reader_die_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/dwarf/src_common_dumper_unittest-dwarf2reader_die_unittest.o -MD -MP -MF src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-dwarf2reader_die_unittest.Tpo -c -o src/common/dwarf/src_common_dumper_unittest-dwarf2reader_die_unittest.o `test -f 'src/common/dwarf/dwarf2reader_die_unittest.cc' || echo '$(srcdir)/'`src/common/dwarf/dwarf2reader_die_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-dwarf2reader_die_unittest.Tpo src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-dwarf2reader_die_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/dwarf/dwarf2reader_die_unittest.cc' object='src/common/dwarf/src_common_dumper_unittest-dwarf2reader_die_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/dwarf/src_common_dumper_unittest-dwarf2reader_die_unittest.o `test -f 'src/common/dwarf/dwarf2reader_die_unittest.cc' || echo '$(srcdir)/'`src/common/dwarf/dwarf2reader_die_unittest.cc
+
+src/common/dwarf/src_common_dumper_unittest-dwarf2reader_die_unittest.obj: src/common/dwarf/dwarf2reader_die_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/dwarf/src_common_dumper_unittest-dwarf2reader_die_unittest.obj -MD -MP -MF src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-dwarf2reader_die_unittest.Tpo -c -o src/common/dwarf/src_common_dumper_unittest-dwarf2reader_die_unittest.obj `if test -f 'src/common/dwarf/dwarf2reader_die_unittest.cc'; then $(CYGPATH_W) 'src/common/dwarf/dwarf2reader_die_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/dwarf/dwarf2reader_die_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-dwarf2reader_die_unittest.Tpo src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-dwarf2reader_die_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/dwarf/dwarf2reader_die_unittest.cc' object='src/common/dwarf/src_common_dumper_unittest-dwarf2reader_die_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/dwarf/src_common_dumper_unittest-dwarf2reader_die_unittest.obj `if test -f 'src/common/dwarf/dwarf2reader_die_unittest.cc'; then $(CYGPATH_W) 'src/common/dwarf/dwarf2reader_die_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/dwarf/dwarf2reader_die_unittest.cc'; fi`
+
+src/common/linux/src_common_dumper_unittest-crc32.o: src/common/linux/crc32.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/linux/src_common_dumper_unittest-crc32.o -MD -MP -MF src/common/linux/$(DEPDIR)/src_common_dumper_unittest-crc32.Tpo -c -o src/common/linux/src_common_dumper_unittest-crc32.o `test -f 'src/common/linux/crc32.cc' || echo '$(srcdir)/'`src/common/linux/crc32.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/linux/$(DEPDIR)/src_common_dumper_unittest-crc32.Tpo src/common/linux/$(DEPDIR)/src_common_dumper_unittest-crc32.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/linux/crc32.cc' object='src/common/linux/src_common_dumper_unittest-crc32.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/linux/src_common_dumper_unittest-crc32.o `test -f 'src/common/linux/crc32.cc' || echo '$(srcdir)/'`src/common/linux/crc32.cc
+
+src/common/linux/src_common_dumper_unittest-crc32.obj: src/common/linux/crc32.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/linux/src_common_dumper_unittest-crc32.obj -MD -MP -MF src/common/linux/$(DEPDIR)/src_common_dumper_unittest-crc32.Tpo -c -o src/common/linux/src_common_dumper_unittest-crc32.obj `if test -f 'src/common/linux/crc32.cc'; then $(CYGPATH_W) 'src/common/linux/crc32.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/linux/crc32.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/linux/$(DEPDIR)/src_common_dumper_unittest-crc32.Tpo src/common/linux/$(DEPDIR)/src_common_dumper_unittest-crc32.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/linux/crc32.cc' object='src/common/linux/src_common_dumper_unittest-crc32.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/linux/src_common_dumper_unittest-crc32.obj `if test -f 'src/common/linux/crc32.cc'; then $(CYGPATH_W) 'src/common/linux/crc32.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/linux/crc32.cc'; fi`
+
+src/common/linux/src_common_dumper_unittest-dump_symbols.o: src/common/linux/dump_symbols.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/linux/src_common_dumper_unittest-dump_symbols.o -MD -MP -MF src/common/linux/$(DEPDIR)/src_common_dumper_unittest-dump_symbols.Tpo -c -o src/common/linux/src_common_dumper_unittest-dump_symbols.o `test -f 'src/common/linux/dump_symbols.cc' || echo '$(srcdir)/'`src/common/linux/dump_symbols.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/linux/$(DEPDIR)/src_common_dumper_unittest-dump_symbols.Tpo src/common/linux/$(DEPDIR)/src_common_dumper_unittest-dump_symbols.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/linux/dump_symbols.cc' object='src/common/linux/src_common_dumper_unittest-dump_symbols.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/linux/src_common_dumper_unittest-dump_symbols.o `test -f 'src/common/linux/dump_symbols.cc' || echo '$(srcdir)/'`src/common/linux/dump_symbols.cc
+
+src/common/linux/src_common_dumper_unittest-dump_symbols.obj: src/common/linux/dump_symbols.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/linux/src_common_dumper_unittest-dump_symbols.obj -MD -MP -MF src/common/linux/$(DEPDIR)/src_common_dumper_unittest-dump_symbols.Tpo -c -o src/common/linux/src_common_dumper_unittest-dump_symbols.obj `if test -f 'src/common/linux/dump_symbols.cc'; then $(CYGPATH_W) 'src/common/linux/dump_symbols.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/linux/dump_symbols.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/linux/$(DEPDIR)/src_common_dumper_unittest-dump_symbols.Tpo src/common/linux/$(DEPDIR)/src_common_dumper_unittest-dump_symbols.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/linux/dump_symbols.cc' object='src/common/linux/src_common_dumper_unittest-dump_symbols.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/linux/src_common_dumper_unittest-dump_symbols.obj `if test -f 'src/common/linux/dump_symbols.cc'; then $(CYGPATH_W) 'src/common/linux/dump_symbols.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/linux/dump_symbols.cc'; fi`
+
+src/common/linux/src_common_dumper_unittest-dump_symbols_unittest.o: src/common/linux/dump_symbols_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/linux/src_common_dumper_unittest-dump_symbols_unittest.o -MD -MP -MF src/common/linux/$(DEPDIR)/src_common_dumper_unittest-dump_symbols_unittest.Tpo -c -o src/common/linux/src_common_dumper_unittest-dump_symbols_unittest.o `test -f 'src/common/linux/dump_symbols_unittest.cc' || echo '$(srcdir)/'`src/common/linux/dump_symbols_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/linux/$(DEPDIR)/src_common_dumper_unittest-dump_symbols_unittest.Tpo src/common/linux/$(DEPDIR)/src_common_dumper_unittest-dump_symbols_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/linux/dump_symbols_unittest.cc' object='src/common/linux/src_common_dumper_unittest-dump_symbols_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/linux/src_common_dumper_unittest-dump_symbols_unittest.o `test -f 'src/common/linux/dump_symbols_unittest.cc' || echo '$(srcdir)/'`src/common/linux/dump_symbols_unittest.cc
+
+src/common/linux/src_common_dumper_unittest-dump_symbols_unittest.obj: src/common/linux/dump_symbols_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/linux/src_common_dumper_unittest-dump_symbols_unittest.obj -MD -MP -MF src/common/linux/$(DEPDIR)/src_common_dumper_unittest-dump_symbols_unittest.Tpo -c -o src/common/linux/src_common_dumper_unittest-dump_symbols_unittest.obj `if test -f 'src/common/linux/dump_symbols_unittest.cc'; then $(CYGPATH_W) 'src/common/linux/dump_symbols_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/linux/dump_symbols_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/linux/$(DEPDIR)/src_common_dumper_unittest-dump_symbols_unittest.Tpo src/common/linux/$(DEPDIR)/src_common_dumper_unittest-dump_symbols_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/linux/dump_symbols_unittest.cc' object='src/common/linux/src_common_dumper_unittest-dump_symbols_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/linux/src_common_dumper_unittest-dump_symbols_unittest.obj `if test -f 'src/common/linux/dump_symbols_unittest.cc'; then $(CYGPATH_W) 'src/common/linux/dump_symbols_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/linux/dump_symbols_unittest.cc'; fi`
+
+src/common/linux/src_common_dumper_unittest-elf_core_dump.o: src/common/linux/elf_core_dump.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/linux/src_common_dumper_unittest-elf_core_dump.o -MD -MP -MF src/common/linux/$(DEPDIR)/src_common_dumper_unittest-elf_core_dump.Tpo -c -o src/common/linux/src_common_dumper_unittest-elf_core_dump.o `test -f 'src/common/linux/elf_core_dump.cc' || echo '$(srcdir)/'`src/common/linux/elf_core_dump.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/linux/$(DEPDIR)/src_common_dumper_unittest-elf_core_dump.Tpo src/common/linux/$(DEPDIR)/src_common_dumper_unittest-elf_core_dump.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/linux/elf_core_dump.cc' object='src/common/linux/src_common_dumper_unittest-elf_core_dump.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/linux/src_common_dumper_unittest-elf_core_dump.o `test -f 'src/common/linux/elf_core_dump.cc' || echo '$(srcdir)/'`src/common/linux/elf_core_dump.cc
+
+src/common/linux/src_common_dumper_unittest-elf_core_dump.obj: src/common/linux/elf_core_dump.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/linux/src_common_dumper_unittest-elf_core_dump.obj -MD -MP -MF src/common/linux/$(DEPDIR)/src_common_dumper_unittest-elf_core_dump.Tpo -c -o src/common/linux/src_common_dumper_unittest-elf_core_dump.obj `if test -f 'src/common/linux/elf_core_dump.cc'; then $(CYGPATH_W) 'src/common/linux/elf_core_dump.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/linux/elf_core_dump.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/linux/$(DEPDIR)/src_common_dumper_unittest-elf_core_dump.Tpo src/common/linux/$(DEPDIR)/src_common_dumper_unittest-elf_core_dump.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/linux/elf_core_dump.cc' object='src/common/linux/src_common_dumper_unittest-elf_core_dump.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/linux/src_common_dumper_unittest-elf_core_dump.obj `if test -f 'src/common/linux/elf_core_dump.cc'; then $(CYGPATH_W) 'src/common/linux/elf_core_dump.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/linux/elf_core_dump.cc'; fi`
+
+src/common/linux/src_common_dumper_unittest-elf_core_dump_unittest.o: src/common/linux/elf_core_dump_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/linux/src_common_dumper_unittest-elf_core_dump_unittest.o -MD -MP -MF src/common/linux/$(DEPDIR)/src_common_dumper_unittest-elf_core_dump_unittest.Tpo -c -o src/common/linux/src_common_dumper_unittest-elf_core_dump_unittest.o `test -f 'src/common/linux/elf_core_dump_unittest.cc' || echo '$(srcdir)/'`src/common/linux/elf_core_dump_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/linux/$(DEPDIR)/src_common_dumper_unittest-elf_core_dump_unittest.Tpo src/common/linux/$(DEPDIR)/src_common_dumper_unittest-elf_core_dump_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/linux/elf_core_dump_unittest.cc' object='src/common/linux/src_common_dumper_unittest-elf_core_dump_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/linux/src_common_dumper_unittest-elf_core_dump_unittest.o `test -f 'src/common/linux/elf_core_dump_unittest.cc' || echo '$(srcdir)/'`src/common/linux/elf_core_dump_unittest.cc
+
+src/common/linux/src_common_dumper_unittest-elf_core_dump_unittest.obj: src/common/linux/elf_core_dump_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/linux/src_common_dumper_unittest-elf_core_dump_unittest.obj -MD -MP -MF src/common/linux/$(DEPDIR)/src_common_dumper_unittest-elf_core_dump_unittest.Tpo -c -o src/common/linux/src_common_dumper_unittest-elf_core_dump_unittest.obj `if test -f 'src/common/linux/elf_core_dump_unittest.cc'; then $(CYGPATH_W) 'src/common/linux/elf_core_dump_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/linux/elf_core_dump_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/linux/$(DEPDIR)/src_common_dumper_unittest-elf_core_dump_unittest.Tpo src/common/linux/$(DEPDIR)/src_common_dumper_unittest-elf_core_dump_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/linux/elf_core_dump_unittest.cc' object='src/common/linux/src_common_dumper_unittest-elf_core_dump_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/linux/src_common_dumper_unittest-elf_core_dump_unittest.obj `if test -f 'src/common/linux/elf_core_dump_unittest.cc'; then $(CYGPATH_W) 'src/common/linux/elf_core_dump_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/linux/elf_core_dump_unittest.cc'; fi`
+
+src/common/linux/src_common_dumper_unittest-elf_symbols_to_module.o: src/common/linux/elf_symbols_to_module.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/linux/src_common_dumper_unittest-elf_symbols_to_module.o -MD -MP -MF src/common/linux/$(DEPDIR)/src_common_dumper_unittest-elf_symbols_to_module.Tpo -c -o src/common/linux/src_common_dumper_unittest-elf_symbols_to_module.o `test -f 'src/common/linux/elf_symbols_to_module.cc' || echo '$(srcdir)/'`src/common/linux/elf_symbols_to_module.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/linux/$(DEPDIR)/src_common_dumper_unittest-elf_symbols_to_module.Tpo src/common/linux/$(DEPDIR)/src_common_dumper_unittest-elf_symbols_to_module.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/linux/elf_symbols_to_module.cc' object='src/common/linux/src_common_dumper_unittest-elf_symbols_to_module.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/linux/src_common_dumper_unittest-elf_symbols_to_module.o `test -f 'src/common/linux/elf_symbols_to_module.cc' || echo '$(srcdir)/'`src/common/linux/elf_symbols_to_module.cc
+
+src/common/linux/src_common_dumper_unittest-elf_symbols_to_module.obj: src/common/linux/elf_symbols_to_module.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/linux/src_common_dumper_unittest-elf_symbols_to_module.obj -MD -MP -MF src/common/linux/$(DEPDIR)/src_common_dumper_unittest-elf_symbols_to_module.Tpo -c -o src/common/linux/src_common_dumper_unittest-elf_symbols_to_module.obj `if test -f 'src/common/linux/elf_symbols_to_module.cc'; then $(CYGPATH_W) 'src/common/linux/elf_symbols_to_module.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/linux/elf_symbols_to_module.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/linux/$(DEPDIR)/src_common_dumper_unittest-elf_symbols_to_module.Tpo src/common/linux/$(DEPDIR)/src_common_dumper_unittest-elf_symbols_to_module.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/linux/elf_symbols_to_module.cc' object='src/common/linux/src_common_dumper_unittest-elf_symbols_to_module.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/linux/src_common_dumper_unittest-elf_symbols_to_module.obj `if test -f 'src/common/linux/elf_symbols_to_module.cc'; then $(CYGPATH_W) 'src/common/linux/elf_symbols_to_module.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/linux/elf_symbols_to_module.cc'; fi`
+
+src/common/linux/src_common_dumper_unittest-elf_symbols_to_module_unittest.o: src/common/linux/elf_symbols_to_module_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/linux/src_common_dumper_unittest-elf_symbols_to_module_unittest.o -MD -MP -MF src/common/linux/$(DEPDIR)/src_common_dumper_unittest-elf_symbols_to_module_unittest.Tpo -c -o src/common/linux/src_common_dumper_unittest-elf_symbols_to_module_unittest.o `test -f 'src/common/linux/elf_symbols_to_module_unittest.cc' || echo '$(srcdir)/'`src/common/linux/elf_symbols_to_module_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/linux/$(DEPDIR)/src_common_dumper_unittest-elf_symbols_to_module_unittest.Tpo src/common/linux/$(DEPDIR)/src_common_dumper_unittest-elf_symbols_to_module_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/linux/elf_symbols_to_module_unittest.cc' object='src/common/linux/src_common_dumper_unittest-elf_symbols_to_module_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/linux/src_common_dumper_unittest-elf_symbols_to_module_unittest.o `test -f 'src/common/linux/elf_symbols_to_module_unittest.cc' || echo '$(srcdir)/'`src/common/linux/elf_symbols_to_module_unittest.cc
+
+src/common/linux/src_common_dumper_unittest-elf_symbols_to_module_unittest.obj: src/common/linux/elf_symbols_to_module_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/linux/src_common_dumper_unittest-elf_symbols_to_module_unittest.obj -MD -MP -MF src/common/linux/$(DEPDIR)/src_common_dumper_unittest-elf_symbols_to_module_unittest.Tpo -c -o src/common/linux/src_common_dumper_unittest-elf_symbols_to_module_unittest.obj `if test -f 'src/common/linux/elf_symbols_to_module_unittest.cc'; then $(CYGPATH_W) 'src/common/linux/elf_symbols_to_module_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/linux/elf_symbols_to_module_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/linux/$(DEPDIR)/src_common_dumper_unittest-elf_symbols_to_module_unittest.Tpo src/common/linux/$(DEPDIR)/src_common_dumper_unittest-elf_symbols_to_module_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/linux/elf_symbols_to_module_unittest.cc' object='src/common/linux/src_common_dumper_unittest-elf_symbols_to_module_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/linux/src_common_dumper_unittest-elf_symbols_to_module_unittest.obj `if test -f 'src/common/linux/elf_symbols_to_module_unittest.cc'; then $(CYGPATH_W) 'src/common/linux/elf_symbols_to_module_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/linux/elf_symbols_to_module_unittest.cc'; fi`
+
+src/common/linux/src_common_dumper_unittest-elfutils.o: src/common/linux/elfutils.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/linux/src_common_dumper_unittest-elfutils.o -MD -MP -MF src/common/linux/$(DEPDIR)/src_common_dumper_unittest-elfutils.Tpo -c -o src/common/linux/src_common_dumper_unittest-elfutils.o `test -f 'src/common/linux/elfutils.cc' || echo '$(srcdir)/'`src/common/linux/elfutils.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/linux/$(DEPDIR)/src_common_dumper_unittest-elfutils.Tpo src/common/linux/$(DEPDIR)/src_common_dumper_unittest-elfutils.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/linux/elfutils.cc' object='src/common/linux/src_common_dumper_unittest-elfutils.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/linux/src_common_dumper_unittest-elfutils.o `test -f 'src/common/linux/elfutils.cc' || echo '$(srcdir)/'`src/common/linux/elfutils.cc
+
+src/common/linux/src_common_dumper_unittest-elfutils.obj: src/common/linux/elfutils.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/linux/src_common_dumper_unittest-elfutils.obj -MD -MP -MF src/common/linux/$(DEPDIR)/src_common_dumper_unittest-elfutils.Tpo -c -o src/common/linux/src_common_dumper_unittest-elfutils.obj `if test -f 'src/common/linux/elfutils.cc'; then $(CYGPATH_W) 'src/common/linux/elfutils.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/linux/elfutils.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/linux/$(DEPDIR)/src_common_dumper_unittest-elfutils.Tpo src/common/linux/$(DEPDIR)/src_common_dumper_unittest-elfutils.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/linux/elfutils.cc' object='src/common/linux/src_common_dumper_unittest-elfutils.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/linux/src_common_dumper_unittest-elfutils.obj `if test -f 'src/common/linux/elfutils.cc'; then $(CYGPATH_W) 'src/common/linux/elfutils.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/linux/elfutils.cc'; fi`
+
+src/common/linux/src_common_dumper_unittest-file_id.o: src/common/linux/file_id.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/linux/src_common_dumper_unittest-file_id.o -MD -MP -MF src/common/linux/$(DEPDIR)/src_common_dumper_unittest-file_id.Tpo -c -o src/common/linux/src_common_dumper_unittest-file_id.o `test -f 'src/common/linux/file_id.cc' || echo '$(srcdir)/'`src/common/linux/file_id.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/linux/$(DEPDIR)/src_common_dumper_unittest-file_id.Tpo src/common/linux/$(DEPDIR)/src_common_dumper_unittest-file_id.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/linux/file_id.cc' object='src/common/linux/src_common_dumper_unittest-file_id.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/linux/src_common_dumper_unittest-file_id.o `test -f 'src/common/linux/file_id.cc' || echo '$(srcdir)/'`src/common/linux/file_id.cc
+
+src/common/linux/src_common_dumper_unittest-file_id.obj: src/common/linux/file_id.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/linux/src_common_dumper_unittest-file_id.obj -MD -MP -MF src/common/linux/$(DEPDIR)/src_common_dumper_unittest-file_id.Tpo -c -o src/common/linux/src_common_dumper_unittest-file_id.obj `if test -f 'src/common/linux/file_id.cc'; then $(CYGPATH_W) 'src/common/linux/file_id.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/linux/file_id.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/linux/$(DEPDIR)/src_common_dumper_unittest-file_id.Tpo src/common/linux/$(DEPDIR)/src_common_dumper_unittest-file_id.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/linux/file_id.cc' object='src/common/linux/src_common_dumper_unittest-file_id.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/linux/src_common_dumper_unittest-file_id.obj `if test -f 'src/common/linux/file_id.cc'; then $(CYGPATH_W) 'src/common/linux/file_id.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/linux/file_id.cc'; fi`
+
+src/common/linux/src_common_dumper_unittest-file_id_unittest.o: src/common/linux/file_id_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/linux/src_common_dumper_unittest-file_id_unittest.o -MD -MP -MF src/common/linux/$(DEPDIR)/src_common_dumper_unittest-file_id_unittest.Tpo -c -o src/common/linux/src_common_dumper_unittest-file_id_unittest.o `test -f 'src/common/linux/file_id_unittest.cc' || echo '$(srcdir)/'`src/common/linux/file_id_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/linux/$(DEPDIR)/src_common_dumper_unittest-file_id_unittest.Tpo src/common/linux/$(DEPDIR)/src_common_dumper_unittest-file_id_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/linux/file_id_unittest.cc' object='src/common/linux/src_common_dumper_unittest-file_id_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/linux/src_common_dumper_unittest-file_id_unittest.o `test -f 'src/common/linux/file_id_unittest.cc' || echo '$(srcdir)/'`src/common/linux/file_id_unittest.cc
+
+src/common/linux/src_common_dumper_unittest-file_id_unittest.obj: src/common/linux/file_id_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/linux/src_common_dumper_unittest-file_id_unittest.obj -MD -MP -MF src/common/linux/$(DEPDIR)/src_common_dumper_unittest-file_id_unittest.Tpo -c -o src/common/linux/src_common_dumper_unittest-file_id_unittest.obj `if test -f 'src/common/linux/file_id_unittest.cc'; then $(CYGPATH_W) 'src/common/linux/file_id_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/linux/file_id_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/linux/$(DEPDIR)/src_common_dumper_unittest-file_id_unittest.Tpo src/common/linux/$(DEPDIR)/src_common_dumper_unittest-file_id_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/linux/file_id_unittest.cc' object='src/common/linux/src_common_dumper_unittest-file_id_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/linux/src_common_dumper_unittest-file_id_unittest.obj `if test -f 'src/common/linux/file_id_unittest.cc'; then $(CYGPATH_W) 'src/common/linux/file_id_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/linux/file_id_unittest.cc'; fi`
+
+src/common/linux/src_common_dumper_unittest-linux_libc_support.o: src/common/linux/linux_libc_support.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/linux/src_common_dumper_unittest-linux_libc_support.o -MD -MP -MF src/common/linux/$(DEPDIR)/src_common_dumper_unittest-linux_libc_support.Tpo -c -o src/common/linux/src_common_dumper_unittest-linux_libc_support.o `test -f 'src/common/linux/linux_libc_support.cc' || echo '$(srcdir)/'`src/common/linux/linux_libc_support.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/linux/$(DEPDIR)/src_common_dumper_unittest-linux_libc_support.Tpo src/common/linux/$(DEPDIR)/src_common_dumper_unittest-linux_libc_support.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/linux/linux_libc_support.cc' object='src/common/linux/src_common_dumper_unittest-linux_libc_support.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/linux/src_common_dumper_unittest-linux_libc_support.o `test -f 'src/common/linux/linux_libc_support.cc' || echo '$(srcdir)/'`src/common/linux/linux_libc_support.cc
+
+src/common/linux/src_common_dumper_unittest-linux_libc_support.obj: src/common/linux/linux_libc_support.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/linux/src_common_dumper_unittest-linux_libc_support.obj -MD -MP -MF src/common/linux/$(DEPDIR)/src_common_dumper_unittest-linux_libc_support.Tpo -c -o src/common/linux/src_common_dumper_unittest-linux_libc_support.obj `if test -f 'src/common/linux/linux_libc_support.cc'; then $(CYGPATH_W) 'src/common/linux/linux_libc_support.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/linux/linux_libc_support.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/linux/$(DEPDIR)/src_common_dumper_unittest-linux_libc_support.Tpo src/common/linux/$(DEPDIR)/src_common_dumper_unittest-linux_libc_support.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/linux/linux_libc_support.cc' object='src/common/linux/src_common_dumper_unittest-linux_libc_support.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/linux/src_common_dumper_unittest-linux_libc_support.obj `if test -f 'src/common/linux/linux_libc_support.cc'; then $(CYGPATH_W) 'src/common/linux/linux_libc_support.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/linux/linux_libc_support.cc'; fi`
+
+src/common/linux/src_common_dumper_unittest-memory_mapped_file.o: src/common/linux/memory_mapped_file.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/linux/src_common_dumper_unittest-memory_mapped_file.o -MD -MP -MF src/common/linux/$(DEPDIR)/src_common_dumper_unittest-memory_mapped_file.Tpo -c -o src/common/linux/src_common_dumper_unittest-memory_mapped_file.o `test -f 'src/common/linux/memory_mapped_file.cc' || echo '$(srcdir)/'`src/common/linux/memory_mapped_file.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/linux/$(DEPDIR)/src_common_dumper_unittest-memory_mapped_file.Tpo src/common/linux/$(DEPDIR)/src_common_dumper_unittest-memory_mapped_file.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/linux/memory_mapped_file.cc' object='src/common/linux/src_common_dumper_unittest-memory_mapped_file.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/linux/src_common_dumper_unittest-memory_mapped_file.o `test -f 'src/common/linux/memory_mapped_file.cc' || echo '$(srcdir)/'`src/common/linux/memory_mapped_file.cc
+
+src/common/linux/src_common_dumper_unittest-memory_mapped_file.obj: src/common/linux/memory_mapped_file.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/linux/src_common_dumper_unittest-memory_mapped_file.obj -MD -MP -MF src/common/linux/$(DEPDIR)/src_common_dumper_unittest-memory_mapped_file.Tpo -c -o src/common/linux/src_common_dumper_unittest-memory_mapped_file.obj `if test -f 'src/common/linux/memory_mapped_file.cc'; then $(CYGPATH_W) 'src/common/linux/memory_mapped_file.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/linux/memory_mapped_file.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/linux/$(DEPDIR)/src_common_dumper_unittest-memory_mapped_file.Tpo src/common/linux/$(DEPDIR)/src_common_dumper_unittest-memory_mapped_file.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/linux/memory_mapped_file.cc' object='src/common/linux/src_common_dumper_unittest-memory_mapped_file.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/linux/src_common_dumper_unittest-memory_mapped_file.obj `if test -f 'src/common/linux/memory_mapped_file.cc'; then $(CYGPATH_W) 'src/common/linux/memory_mapped_file.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/linux/memory_mapped_file.cc'; fi`
+
+src/common/linux/src_common_dumper_unittest-memory_mapped_file_unittest.o: src/common/linux/memory_mapped_file_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/linux/src_common_dumper_unittest-memory_mapped_file_unittest.o -MD -MP -MF src/common/linux/$(DEPDIR)/src_common_dumper_unittest-memory_mapped_file_unittest.Tpo -c -o src/common/linux/src_common_dumper_unittest-memory_mapped_file_unittest.o `test -f 'src/common/linux/memory_mapped_file_unittest.cc' || echo '$(srcdir)/'`src/common/linux/memory_mapped_file_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/linux/$(DEPDIR)/src_common_dumper_unittest-memory_mapped_file_unittest.Tpo src/common/linux/$(DEPDIR)/src_common_dumper_unittest-memory_mapped_file_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/linux/memory_mapped_file_unittest.cc' object='src/common/linux/src_common_dumper_unittest-memory_mapped_file_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/linux/src_common_dumper_unittest-memory_mapped_file_unittest.o `test -f 'src/common/linux/memory_mapped_file_unittest.cc' || echo '$(srcdir)/'`src/common/linux/memory_mapped_file_unittest.cc
+
+src/common/linux/src_common_dumper_unittest-memory_mapped_file_unittest.obj: src/common/linux/memory_mapped_file_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/linux/src_common_dumper_unittest-memory_mapped_file_unittest.obj -MD -MP -MF src/common/linux/$(DEPDIR)/src_common_dumper_unittest-memory_mapped_file_unittest.Tpo -c -o src/common/linux/src_common_dumper_unittest-memory_mapped_file_unittest.obj `if test -f 'src/common/linux/memory_mapped_file_unittest.cc'; then $(CYGPATH_W) 'src/common/linux/memory_mapped_file_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/linux/memory_mapped_file_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/linux/$(DEPDIR)/src_common_dumper_unittest-memory_mapped_file_unittest.Tpo src/common/linux/$(DEPDIR)/src_common_dumper_unittest-memory_mapped_file_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/linux/memory_mapped_file_unittest.cc' object='src/common/linux/src_common_dumper_unittest-memory_mapped_file_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/linux/src_common_dumper_unittest-memory_mapped_file_unittest.obj `if test -f 'src/common/linux/memory_mapped_file_unittest.cc'; then $(CYGPATH_W) 'src/common/linux/memory_mapped_file_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/linux/memory_mapped_file_unittest.cc'; fi`
+
+src/common/linux/src_common_dumper_unittest-safe_readlink.o: src/common/linux/safe_readlink.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/linux/src_common_dumper_unittest-safe_readlink.o -MD -MP -MF src/common/linux/$(DEPDIR)/src_common_dumper_unittest-safe_readlink.Tpo -c -o src/common/linux/src_common_dumper_unittest-safe_readlink.o `test -f 'src/common/linux/safe_readlink.cc' || echo '$(srcdir)/'`src/common/linux/safe_readlink.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/linux/$(DEPDIR)/src_common_dumper_unittest-safe_readlink.Tpo src/common/linux/$(DEPDIR)/src_common_dumper_unittest-safe_readlink.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/linux/safe_readlink.cc' object='src/common/linux/src_common_dumper_unittest-safe_readlink.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/linux/src_common_dumper_unittest-safe_readlink.o `test -f 'src/common/linux/safe_readlink.cc' || echo '$(srcdir)/'`src/common/linux/safe_readlink.cc
+
+src/common/linux/src_common_dumper_unittest-safe_readlink.obj: src/common/linux/safe_readlink.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/linux/src_common_dumper_unittest-safe_readlink.obj -MD -MP -MF src/common/linux/$(DEPDIR)/src_common_dumper_unittest-safe_readlink.Tpo -c -o src/common/linux/src_common_dumper_unittest-safe_readlink.obj `if test -f 'src/common/linux/safe_readlink.cc'; then $(CYGPATH_W) 'src/common/linux/safe_readlink.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/linux/safe_readlink.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/linux/$(DEPDIR)/src_common_dumper_unittest-safe_readlink.Tpo src/common/linux/$(DEPDIR)/src_common_dumper_unittest-safe_readlink.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/linux/safe_readlink.cc' object='src/common/linux/src_common_dumper_unittest-safe_readlink.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/linux/src_common_dumper_unittest-safe_readlink.obj `if test -f 'src/common/linux/safe_readlink.cc'; then $(CYGPATH_W) 'src/common/linux/safe_readlink.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/linux/safe_readlink.cc'; fi`
+
+src/common/linux/src_common_dumper_unittest-safe_readlink_unittest.o: src/common/linux/safe_readlink_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/linux/src_common_dumper_unittest-safe_readlink_unittest.o -MD -MP -MF src/common/linux/$(DEPDIR)/src_common_dumper_unittest-safe_readlink_unittest.Tpo -c -o src/common/linux/src_common_dumper_unittest-safe_readlink_unittest.o `test -f 'src/common/linux/safe_readlink_unittest.cc' || echo '$(srcdir)/'`src/common/linux/safe_readlink_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/linux/$(DEPDIR)/src_common_dumper_unittest-safe_readlink_unittest.Tpo src/common/linux/$(DEPDIR)/src_common_dumper_unittest-safe_readlink_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/linux/safe_readlink_unittest.cc' object='src/common/linux/src_common_dumper_unittest-safe_readlink_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/linux/src_common_dumper_unittest-safe_readlink_unittest.o `test -f 'src/common/linux/safe_readlink_unittest.cc' || echo '$(srcdir)/'`src/common/linux/safe_readlink_unittest.cc
+
+src/common/linux/src_common_dumper_unittest-safe_readlink_unittest.obj: src/common/linux/safe_readlink_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/linux/src_common_dumper_unittest-safe_readlink_unittest.obj -MD -MP -MF src/common/linux/$(DEPDIR)/src_common_dumper_unittest-safe_readlink_unittest.Tpo -c -o src/common/linux/src_common_dumper_unittest-safe_readlink_unittest.obj `if test -f 'src/common/linux/safe_readlink_unittest.cc'; then $(CYGPATH_W) 'src/common/linux/safe_readlink_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/linux/safe_readlink_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/linux/$(DEPDIR)/src_common_dumper_unittest-safe_readlink_unittest.Tpo src/common/linux/$(DEPDIR)/src_common_dumper_unittest-safe_readlink_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/linux/safe_readlink_unittest.cc' object='src/common/linux/src_common_dumper_unittest-safe_readlink_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/linux/src_common_dumper_unittest-safe_readlink_unittest.obj `if test -f 'src/common/linux/safe_readlink_unittest.cc'; then $(CYGPATH_W) 'src/common/linux/safe_readlink_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/linux/safe_readlink_unittest.cc'; fi`
+
+src/common/linux/src_common_dumper_unittest-synth_elf.o: src/common/linux/synth_elf.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/linux/src_common_dumper_unittest-synth_elf.o -MD -MP -MF src/common/linux/$(DEPDIR)/src_common_dumper_unittest-synth_elf.Tpo -c -o src/common/linux/src_common_dumper_unittest-synth_elf.o `test -f 'src/common/linux/synth_elf.cc' || echo '$(srcdir)/'`src/common/linux/synth_elf.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/linux/$(DEPDIR)/src_common_dumper_unittest-synth_elf.Tpo src/common/linux/$(DEPDIR)/src_common_dumper_unittest-synth_elf.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/linux/synth_elf.cc' object='src/common/linux/src_common_dumper_unittest-synth_elf.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/linux/src_common_dumper_unittest-synth_elf.o `test -f 'src/common/linux/synth_elf.cc' || echo '$(srcdir)/'`src/common/linux/synth_elf.cc
+
+src/common/linux/src_common_dumper_unittest-synth_elf.obj: src/common/linux/synth_elf.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/linux/src_common_dumper_unittest-synth_elf.obj -MD -MP -MF src/common/linux/$(DEPDIR)/src_common_dumper_unittest-synth_elf.Tpo -c -o src/common/linux/src_common_dumper_unittest-synth_elf.obj `if test -f 'src/common/linux/synth_elf.cc'; then $(CYGPATH_W) 'src/common/linux/synth_elf.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/linux/synth_elf.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/linux/$(DEPDIR)/src_common_dumper_unittest-synth_elf.Tpo src/common/linux/$(DEPDIR)/src_common_dumper_unittest-synth_elf.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/linux/synth_elf.cc' object='src/common/linux/src_common_dumper_unittest-synth_elf.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/linux/src_common_dumper_unittest-synth_elf.obj `if test -f 'src/common/linux/synth_elf.cc'; then $(CYGPATH_W) 'src/common/linux/synth_elf.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/linux/synth_elf.cc'; fi`
+
+src/common/linux/src_common_dumper_unittest-synth_elf_unittest.o: src/common/linux/synth_elf_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/linux/src_common_dumper_unittest-synth_elf_unittest.o -MD -MP -MF src/common/linux/$(DEPDIR)/src_common_dumper_unittest-synth_elf_unittest.Tpo -c -o src/common/linux/src_common_dumper_unittest-synth_elf_unittest.o `test -f 'src/common/linux/synth_elf_unittest.cc' || echo '$(srcdir)/'`src/common/linux/synth_elf_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/linux/$(DEPDIR)/src_common_dumper_unittest-synth_elf_unittest.Tpo src/common/linux/$(DEPDIR)/src_common_dumper_unittest-synth_elf_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/linux/synth_elf_unittest.cc' object='src/common/linux/src_common_dumper_unittest-synth_elf_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/linux/src_common_dumper_unittest-synth_elf_unittest.o `test -f 'src/common/linux/synth_elf_unittest.cc' || echo '$(srcdir)/'`src/common/linux/synth_elf_unittest.cc
+
+src/common/linux/src_common_dumper_unittest-synth_elf_unittest.obj: src/common/linux/synth_elf_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/linux/src_common_dumper_unittest-synth_elf_unittest.obj -MD -MP -MF src/common/linux/$(DEPDIR)/src_common_dumper_unittest-synth_elf_unittest.Tpo -c -o src/common/linux/src_common_dumper_unittest-synth_elf_unittest.obj `if test -f 'src/common/linux/synth_elf_unittest.cc'; then $(CYGPATH_W) 'src/common/linux/synth_elf_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/linux/synth_elf_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/linux/$(DEPDIR)/src_common_dumper_unittest-synth_elf_unittest.Tpo src/common/linux/$(DEPDIR)/src_common_dumper_unittest-synth_elf_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/linux/synth_elf_unittest.cc' object='src/common/linux/src_common_dumper_unittest-synth_elf_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/linux/src_common_dumper_unittest-synth_elf_unittest.obj `if test -f 'src/common/linux/synth_elf_unittest.cc'; then $(CYGPATH_W) 'src/common/linux/synth_elf_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/linux/synth_elf_unittest.cc'; fi`
+
+src/common/linux/tests/src_common_dumper_unittest-crash_generator.o: src/common/linux/tests/crash_generator.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/linux/tests/src_common_dumper_unittest-crash_generator.o -MD -MP -MF src/common/linux/tests/$(DEPDIR)/src_common_dumper_unittest-crash_generator.Tpo -c -o src/common/linux/tests/src_common_dumper_unittest-crash_generator.o `test -f 'src/common/linux/tests/crash_generator.cc' || echo '$(srcdir)/'`src/common/linux/tests/crash_generator.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/linux/tests/$(DEPDIR)/src_common_dumper_unittest-crash_generator.Tpo src/common/linux/tests/$(DEPDIR)/src_common_dumper_unittest-crash_generator.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/linux/tests/crash_generator.cc' object='src/common/linux/tests/src_common_dumper_unittest-crash_generator.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/linux/tests/src_common_dumper_unittest-crash_generator.o `test -f 'src/common/linux/tests/crash_generator.cc' || echo '$(srcdir)/'`src/common/linux/tests/crash_generator.cc
+
+src/common/linux/tests/src_common_dumper_unittest-crash_generator.obj: src/common/linux/tests/crash_generator.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/linux/tests/src_common_dumper_unittest-crash_generator.obj -MD -MP -MF src/common/linux/tests/$(DEPDIR)/src_common_dumper_unittest-crash_generator.Tpo -c -o src/common/linux/tests/src_common_dumper_unittest-crash_generator.obj `if test -f 'src/common/linux/tests/crash_generator.cc'; then $(CYGPATH_W) 'src/common/linux/tests/crash_generator.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/linux/tests/crash_generator.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/linux/tests/$(DEPDIR)/src_common_dumper_unittest-crash_generator.Tpo src/common/linux/tests/$(DEPDIR)/src_common_dumper_unittest-crash_generator.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/linux/tests/crash_generator.cc' object='src/common/linux/tests/src_common_dumper_unittest-crash_generator.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/linux/tests/src_common_dumper_unittest-crash_generator.obj `if test -f 'src/common/linux/tests/crash_generator.cc'; then $(CYGPATH_W) 'src/common/linux/tests/crash_generator.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/linux/tests/crash_generator.cc'; fi`
+
+src/common/tests/src_common_dumper_unittest-file_utils.o: src/common/tests/file_utils.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/tests/src_common_dumper_unittest-file_utils.o -MD -MP -MF src/common/tests/$(DEPDIR)/src_common_dumper_unittest-file_utils.Tpo -c -o src/common/tests/src_common_dumper_unittest-file_utils.o `test -f 'src/common/tests/file_utils.cc' || echo '$(srcdir)/'`src/common/tests/file_utils.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/tests/$(DEPDIR)/src_common_dumper_unittest-file_utils.Tpo src/common/tests/$(DEPDIR)/src_common_dumper_unittest-file_utils.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/tests/file_utils.cc' object='src/common/tests/src_common_dumper_unittest-file_utils.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/tests/src_common_dumper_unittest-file_utils.o `test -f 'src/common/tests/file_utils.cc' || echo '$(srcdir)/'`src/common/tests/file_utils.cc
+
+src/common/tests/src_common_dumper_unittest-file_utils.obj: src/common/tests/file_utils.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/tests/src_common_dumper_unittest-file_utils.obj -MD -MP -MF src/common/tests/$(DEPDIR)/src_common_dumper_unittest-file_utils.Tpo -c -o src/common/tests/src_common_dumper_unittest-file_utils.obj `if test -f 'src/common/tests/file_utils.cc'; then $(CYGPATH_W) 'src/common/tests/file_utils.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/tests/file_utils.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/tests/$(DEPDIR)/src_common_dumper_unittest-file_utils.Tpo src/common/tests/$(DEPDIR)/src_common_dumper_unittest-file_utils.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/tests/file_utils.cc' object='src/common/tests/src_common_dumper_unittest-file_utils.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/tests/src_common_dumper_unittest-file_utils.obj `if test -f 'src/common/tests/file_utils.cc'; then $(CYGPATH_W) 'src/common/tests/file_utils.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/tests/file_utils.cc'; fi`
+
+src/common/src_common_mac_macho_reader_unittest-dwarf_cfi_to_module.o: src/common/dwarf_cfi_to_module.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_common_mac_macho_reader_unittest-dwarf_cfi_to_module.o -MD -MP -MF src/common/$(DEPDIR)/src_common_mac_macho_reader_unittest-dwarf_cfi_to_module.Tpo -c -o src/common/src_common_mac_macho_reader_unittest-dwarf_cfi_to_module.o `test -f 'src/common/dwarf_cfi_to_module.cc' || echo '$(srcdir)/'`src/common/dwarf_cfi_to_module.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_common_mac_macho_reader_unittest-dwarf_cfi_to_module.Tpo src/common/$(DEPDIR)/src_common_mac_macho_reader_unittest-dwarf_cfi_to_module.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/dwarf_cfi_to_module.cc' object='src/common/src_common_mac_macho_reader_unittest-dwarf_cfi_to_module.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_common_mac_macho_reader_unittest-dwarf_cfi_to_module.o `test -f 'src/common/dwarf_cfi_to_module.cc' || echo '$(srcdir)/'`src/common/dwarf_cfi_to_module.cc
+
+src/common/src_common_mac_macho_reader_unittest-dwarf_cfi_to_module.obj: src/common/dwarf_cfi_to_module.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_common_mac_macho_reader_unittest-dwarf_cfi_to_module.obj -MD -MP -MF src/common/$(DEPDIR)/src_common_mac_macho_reader_unittest-dwarf_cfi_to_module.Tpo -c -o src/common/src_common_mac_macho_reader_unittest-dwarf_cfi_to_module.obj `if test -f 'src/common/dwarf_cfi_to_module.cc'; then $(CYGPATH_W) 'src/common/dwarf_cfi_to_module.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/dwarf_cfi_to_module.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_common_mac_macho_reader_unittest-dwarf_cfi_to_module.Tpo src/common/$(DEPDIR)/src_common_mac_macho_reader_unittest-dwarf_cfi_to_module.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/dwarf_cfi_to_module.cc' object='src/common/src_common_mac_macho_reader_unittest-dwarf_cfi_to_module.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_common_mac_macho_reader_unittest-dwarf_cfi_to_module.obj `if test -f 'src/common/dwarf_cfi_to_module.cc'; then $(CYGPATH_W) 'src/common/dwarf_cfi_to_module.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/dwarf_cfi_to_module.cc'; fi`
+
+src/common/src_common_mac_macho_reader_unittest-dwarf_cu_to_module.o: src/common/dwarf_cu_to_module.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_common_mac_macho_reader_unittest-dwarf_cu_to_module.o -MD -MP -MF src/common/$(DEPDIR)/src_common_mac_macho_reader_unittest-dwarf_cu_to_module.Tpo -c -o src/common/src_common_mac_macho_reader_unittest-dwarf_cu_to_module.o `test -f 'src/common/dwarf_cu_to_module.cc' || echo '$(srcdir)/'`src/common/dwarf_cu_to_module.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_common_mac_macho_reader_unittest-dwarf_cu_to_module.Tpo src/common/$(DEPDIR)/src_common_mac_macho_reader_unittest-dwarf_cu_to_module.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/dwarf_cu_to_module.cc' object='src/common/src_common_mac_macho_reader_unittest-dwarf_cu_to_module.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_common_mac_macho_reader_unittest-dwarf_cu_to_module.o `test -f 'src/common/dwarf_cu_to_module.cc' || echo '$(srcdir)/'`src/common/dwarf_cu_to_module.cc
+
+src/common/src_common_mac_macho_reader_unittest-dwarf_cu_to_module.obj: src/common/dwarf_cu_to_module.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_common_mac_macho_reader_unittest-dwarf_cu_to_module.obj -MD -MP -MF src/common/$(DEPDIR)/src_common_mac_macho_reader_unittest-dwarf_cu_to_module.Tpo -c -o src/common/src_common_mac_macho_reader_unittest-dwarf_cu_to_module.obj `if test -f 'src/common/dwarf_cu_to_module.cc'; then $(CYGPATH_W) 'src/common/dwarf_cu_to_module.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/dwarf_cu_to_module.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_common_mac_macho_reader_unittest-dwarf_cu_to_module.Tpo src/common/$(DEPDIR)/src_common_mac_macho_reader_unittest-dwarf_cu_to_module.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/dwarf_cu_to_module.cc' object='src/common/src_common_mac_macho_reader_unittest-dwarf_cu_to_module.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_common_mac_macho_reader_unittest-dwarf_cu_to_module.obj `if test -f 'src/common/dwarf_cu_to_module.cc'; then $(CYGPATH_W) 'src/common/dwarf_cu_to_module.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/dwarf_cu_to_module.cc'; fi`
+
+src/common/src_common_mac_macho_reader_unittest-dwarf_line_to_module.o: src/common/dwarf_line_to_module.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_common_mac_macho_reader_unittest-dwarf_line_to_module.o -MD -MP -MF src/common/$(DEPDIR)/src_common_mac_macho_reader_unittest-dwarf_line_to_module.Tpo -c -o src/common/src_common_mac_macho_reader_unittest-dwarf_line_to_module.o `test -f 'src/common/dwarf_line_to_module.cc' || echo '$(srcdir)/'`src/common/dwarf_line_to_module.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_common_mac_macho_reader_unittest-dwarf_line_to_module.Tpo src/common/$(DEPDIR)/src_common_mac_macho_reader_unittest-dwarf_line_to_module.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/dwarf_line_to_module.cc' object='src/common/src_common_mac_macho_reader_unittest-dwarf_line_to_module.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_common_mac_macho_reader_unittest-dwarf_line_to_module.o `test -f 'src/common/dwarf_line_to_module.cc' || echo '$(srcdir)/'`src/common/dwarf_line_to_module.cc
+
+src/common/src_common_mac_macho_reader_unittest-dwarf_line_to_module.obj: src/common/dwarf_line_to_module.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_common_mac_macho_reader_unittest-dwarf_line_to_module.obj -MD -MP -MF src/common/$(DEPDIR)/src_common_mac_macho_reader_unittest-dwarf_line_to_module.Tpo -c -o src/common/src_common_mac_macho_reader_unittest-dwarf_line_to_module.obj `if test -f 'src/common/dwarf_line_to_module.cc'; then $(CYGPATH_W) 'src/common/dwarf_line_to_module.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/dwarf_line_to_module.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_common_mac_macho_reader_unittest-dwarf_line_to_module.Tpo src/common/$(DEPDIR)/src_common_mac_macho_reader_unittest-dwarf_line_to_module.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/dwarf_line_to_module.cc' object='src/common/src_common_mac_macho_reader_unittest-dwarf_line_to_module.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_common_mac_macho_reader_unittest-dwarf_line_to_module.obj `if test -f 'src/common/dwarf_line_to_module.cc'; then $(CYGPATH_W) 'src/common/dwarf_line_to_module.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/dwarf_line_to_module.cc'; fi`
+
+src/common/src_common_mac_macho_reader_unittest-language.o: src/common/language.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_common_mac_macho_reader_unittest-language.o -MD -MP -MF src/common/$(DEPDIR)/src_common_mac_macho_reader_unittest-language.Tpo -c -o src/common/src_common_mac_macho_reader_unittest-language.o `test -f 'src/common/language.cc' || echo '$(srcdir)/'`src/common/language.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_common_mac_macho_reader_unittest-language.Tpo src/common/$(DEPDIR)/src_common_mac_macho_reader_unittest-language.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/language.cc' object='src/common/src_common_mac_macho_reader_unittest-language.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_common_mac_macho_reader_unittest-language.o `test -f 'src/common/language.cc' || echo '$(srcdir)/'`src/common/language.cc
+
+src/common/src_common_mac_macho_reader_unittest-language.obj: src/common/language.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_common_mac_macho_reader_unittest-language.obj -MD -MP -MF src/common/$(DEPDIR)/src_common_mac_macho_reader_unittest-language.Tpo -c -o src/common/src_common_mac_macho_reader_unittest-language.obj `if test -f 'src/common/language.cc'; then $(CYGPATH_W) 'src/common/language.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/language.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_common_mac_macho_reader_unittest-language.Tpo src/common/$(DEPDIR)/src_common_mac_macho_reader_unittest-language.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/language.cc' object='src/common/src_common_mac_macho_reader_unittest-language.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_common_mac_macho_reader_unittest-language.obj `if test -f 'src/common/language.cc'; then $(CYGPATH_W) 'src/common/language.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/language.cc'; fi`
+
+src/common/src_common_mac_macho_reader_unittest-md5.o: src/common/md5.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_common_mac_macho_reader_unittest-md5.o -MD -MP -MF src/common/$(DEPDIR)/src_common_mac_macho_reader_unittest-md5.Tpo -c -o src/common/src_common_mac_macho_reader_unittest-md5.o `test -f 'src/common/md5.cc' || echo '$(srcdir)/'`src/common/md5.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_common_mac_macho_reader_unittest-md5.Tpo src/common/$(DEPDIR)/src_common_mac_macho_reader_unittest-md5.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/md5.cc' object='src/common/src_common_mac_macho_reader_unittest-md5.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_common_mac_macho_reader_unittest-md5.o `test -f 'src/common/md5.cc' || echo '$(srcdir)/'`src/common/md5.cc
+
+src/common/src_common_mac_macho_reader_unittest-md5.obj: src/common/md5.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_common_mac_macho_reader_unittest-md5.obj -MD -MP -MF src/common/$(DEPDIR)/src_common_mac_macho_reader_unittest-md5.Tpo -c -o src/common/src_common_mac_macho_reader_unittest-md5.obj `if test -f 'src/common/md5.cc'; then $(CYGPATH_W) 'src/common/md5.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/md5.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_common_mac_macho_reader_unittest-md5.Tpo src/common/$(DEPDIR)/src_common_mac_macho_reader_unittest-md5.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/md5.cc' object='src/common/src_common_mac_macho_reader_unittest-md5.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_common_mac_macho_reader_unittest-md5.obj `if test -f 'src/common/md5.cc'; then $(CYGPATH_W) 'src/common/md5.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/md5.cc'; fi`
+
+src/common/src_common_mac_macho_reader_unittest-module.o: src/common/module.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_common_mac_macho_reader_unittest-module.o -MD -MP -MF src/common/$(DEPDIR)/src_common_mac_macho_reader_unittest-module.Tpo -c -o src/common/src_common_mac_macho_reader_unittest-module.o `test -f 'src/common/module.cc' || echo '$(srcdir)/'`src/common/module.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_common_mac_macho_reader_unittest-module.Tpo src/common/$(DEPDIR)/src_common_mac_macho_reader_unittest-module.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/module.cc' object='src/common/src_common_mac_macho_reader_unittest-module.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_common_mac_macho_reader_unittest-module.o `test -f 'src/common/module.cc' || echo '$(srcdir)/'`src/common/module.cc
+
+src/common/src_common_mac_macho_reader_unittest-module.obj: src/common/module.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_common_mac_macho_reader_unittest-module.obj -MD -MP -MF src/common/$(DEPDIR)/src_common_mac_macho_reader_unittest-module.Tpo -c -o src/common/src_common_mac_macho_reader_unittest-module.obj `if test -f 'src/common/module.cc'; then $(CYGPATH_W) 'src/common/module.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/module.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_common_mac_macho_reader_unittest-module.Tpo src/common/$(DEPDIR)/src_common_mac_macho_reader_unittest-module.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/module.cc' object='src/common/src_common_mac_macho_reader_unittest-module.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_common_mac_macho_reader_unittest-module.obj `if test -f 'src/common/module.cc'; then $(CYGPATH_W) 'src/common/module.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/module.cc'; fi`
+
+src/common/src_common_mac_macho_reader_unittest-stabs_reader.o: src/common/stabs_reader.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_common_mac_macho_reader_unittest-stabs_reader.o -MD -MP -MF src/common/$(DEPDIR)/src_common_mac_macho_reader_unittest-stabs_reader.Tpo -c -o src/common/src_common_mac_macho_reader_unittest-stabs_reader.o `test -f 'src/common/stabs_reader.cc' || echo '$(srcdir)/'`src/common/stabs_reader.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_common_mac_macho_reader_unittest-stabs_reader.Tpo src/common/$(DEPDIR)/src_common_mac_macho_reader_unittest-stabs_reader.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/stabs_reader.cc' object='src/common/src_common_mac_macho_reader_unittest-stabs_reader.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_common_mac_macho_reader_unittest-stabs_reader.o `test -f 'src/common/stabs_reader.cc' || echo '$(srcdir)/'`src/common/stabs_reader.cc
+
+src/common/src_common_mac_macho_reader_unittest-stabs_reader.obj: src/common/stabs_reader.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_common_mac_macho_reader_unittest-stabs_reader.obj -MD -MP -MF src/common/$(DEPDIR)/src_common_mac_macho_reader_unittest-stabs_reader.Tpo -c -o src/common/src_common_mac_macho_reader_unittest-stabs_reader.obj `if test -f 'src/common/stabs_reader.cc'; then $(CYGPATH_W) 'src/common/stabs_reader.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/stabs_reader.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_common_mac_macho_reader_unittest-stabs_reader.Tpo src/common/$(DEPDIR)/src_common_mac_macho_reader_unittest-stabs_reader.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/stabs_reader.cc' object='src/common/src_common_mac_macho_reader_unittest-stabs_reader.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_common_mac_macho_reader_unittest-stabs_reader.obj `if test -f 'src/common/stabs_reader.cc'; then $(CYGPATH_W) 'src/common/stabs_reader.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/stabs_reader.cc'; fi`
+
+src/common/src_common_mac_macho_reader_unittest-stabs_to_module.o: src/common/stabs_to_module.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_common_mac_macho_reader_unittest-stabs_to_module.o -MD -MP -MF src/common/$(DEPDIR)/src_common_mac_macho_reader_unittest-stabs_to_module.Tpo -c -o src/common/src_common_mac_macho_reader_unittest-stabs_to_module.o `test -f 'src/common/stabs_to_module.cc' || echo '$(srcdir)/'`src/common/stabs_to_module.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_common_mac_macho_reader_unittest-stabs_to_module.Tpo src/common/$(DEPDIR)/src_common_mac_macho_reader_unittest-stabs_to_module.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/stabs_to_module.cc' object='src/common/src_common_mac_macho_reader_unittest-stabs_to_module.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_common_mac_macho_reader_unittest-stabs_to_module.o `test -f 'src/common/stabs_to_module.cc' || echo '$(srcdir)/'`src/common/stabs_to_module.cc
+
+src/common/src_common_mac_macho_reader_unittest-stabs_to_module.obj: src/common/stabs_to_module.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_common_mac_macho_reader_unittest-stabs_to_module.obj -MD -MP -MF src/common/$(DEPDIR)/src_common_mac_macho_reader_unittest-stabs_to_module.Tpo -c -o src/common/src_common_mac_macho_reader_unittest-stabs_to_module.obj `if test -f 'src/common/stabs_to_module.cc'; then $(CYGPATH_W) 'src/common/stabs_to_module.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/stabs_to_module.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_common_mac_macho_reader_unittest-stabs_to_module.Tpo src/common/$(DEPDIR)/src_common_mac_macho_reader_unittest-stabs_to_module.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/stabs_to_module.cc' object='src/common/src_common_mac_macho_reader_unittest-stabs_to_module.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_common_mac_macho_reader_unittest-stabs_to_module.obj `if test -f 'src/common/stabs_to_module.cc'; then $(CYGPATH_W) 'src/common/stabs_to_module.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/stabs_to_module.cc'; fi`
+
+src/common/src_common_mac_macho_reader_unittest-test_assembler.o: src/common/test_assembler.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_common_mac_macho_reader_unittest-test_assembler.o -MD -MP -MF src/common/$(DEPDIR)/src_common_mac_macho_reader_unittest-test_assembler.Tpo -c -o src/common/src_common_mac_macho_reader_unittest-test_assembler.o `test -f 'src/common/test_assembler.cc' || echo '$(srcdir)/'`src/common/test_assembler.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_common_mac_macho_reader_unittest-test_assembler.Tpo src/common/$(DEPDIR)/src_common_mac_macho_reader_unittest-test_assembler.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/test_assembler.cc' object='src/common/src_common_mac_macho_reader_unittest-test_assembler.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_common_mac_macho_reader_unittest-test_assembler.o `test -f 'src/common/test_assembler.cc' || echo '$(srcdir)/'`src/common/test_assembler.cc
+
+src/common/src_common_mac_macho_reader_unittest-test_assembler.obj: src/common/test_assembler.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_common_mac_macho_reader_unittest-test_assembler.obj -MD -MP -MF src/common/$(DEPDIR)/src_common_mac_macho_reader_unittest-test_assembler.Tpo -c -o src/common/src_common_mac_macho_reader_unittest-test_assembler.obj `if test -f 'src/common/test_assembler.cc'; then $(CYGPATH_W) 'src/common/test_assembler.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/test_assembler.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_common_mac_macho_reader_unittest-test_assembler.Tpo src/common/$(DEPDIR)/src_common_mac_macho_reader_unittest-test_assembler.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/test_assembler.cc' object='src/common/src_common_mac_macho_reader_unittest-test_assembler.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_common_mac_macho_reader_unittest-test_assembler.obj `if test -f 'src/common/test_assembler.cc'; then $(CYGPATH_W) 'src/common/test_assembler.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/test_assembler.cc'; fi`
+
+src/common/dwarf/src_common_mac_macho_reader_unittest-bytereader.o: src/common/dwarf/bytereader.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/dwarf/src_common_mac_macho_reader_unittest-bytereader.o -MD -MP -MF src/common/dwarf/$(DEPDIR)/src_common_mac_macho_reader_unittest-bytereader.Tpo -c -o src/common/dwarf/src_common_mac_macho_reader_unittest-bytereader.o `test -f 'src/common/dwarf/bytereader.cc' || echo '$(srcdir)/'`src/common/dwarf/bytereader.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/dwarf/$(DEPDIR)/src_common_mac_macho_reader_unittest-bytereader.Tpo src/common/dwarf/$(DEPDIR)/src_common_mac_macho_reader_unittest-bytereader.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/dwarf/bytereader.cc' object='src/common/dwarf/src_common_mac_macho_reader_unittest-bytereader.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/dwarf/src_common_mac_macho_reader_unittest-bytereader.o `test -f 'src/common/dwarf/bytereader.cc' || echo '$(srcdir)/'`src/common/dwarf/bytereader.cc
+
+src/common/dwarf/src_common_mac_macho_reader_unittest-bytereader.obj: src/common/dwarf/bytereader.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/dwarf/src_common_mac_macho_reader_unittest-bytereader.obj -MD -MP -MF src/common/dwarf/$(DEPDIR)/src_common_mac_macho_reader_unittest-bytereader.Tpo -c -o src/common/dwarf/src_common_mac_macho_reader_unittest-bytereader.obj `if test -f 'src/common/dwarf/bytereader.cc'; then $(CYGPATH_W) 'src/common/dwarf/bytereader.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/dwarf/bytereader.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/dwarf/$(DEPDIR)/src_common_mac_macho_reader_unittest-bytereader.Tpo src/common/dwarf/$(DEPDIR)/src_common_mac_macho_reader_unittest-bytereader.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/dwarf/bytereader.cc' object='src/common/dwarf/src_common_mac_macho_reader_unittest-bytereader.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/dwarf/src_common_mac_macho_reader_unittest-bytereader.obj `if test -f 'src/common/dwarf/bytereader.cc'; then $(CYGPATH_W) 'src/common/dwarf/bytereader.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/dwarf/bytereader.cc'; fi`
+
+src/common/dwarf/src_common_mac_macho_reader_unittest-cfi_assembler.o: src/common/dwarf/cfi_assembler.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/dwarf/src_common_mac_macho_reader_unittest-cfi_assembler.o -MD -MP -MF src/common/dwarf/$(DEPDIR)/src_common_mac_macho_reader_unittest-cfi_assembler.Tpo -c -o src/common/dwarf/src_common_mac_macho_reader_unittest-cfi_assembler.o `test -f 'src/common/dwarf/cfi_assembler.cc' || echo '$(srcdir)/'`src/common/dwarf/cfi_assembler.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/dwarf/$(DEPDIR)/src_common_mac_macho_reader_unittest-cfi_assembler.Tpo src/common/dwarf/$(DEPDIR)/src_common_mac_macho_reader_unittest-cfi_assembler.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/dwarf/cfi_assembler.cc' object='src/common/dwarf/src_common_mac_macho_reader_unittest-cfi_assembler.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/dwarf/src_common_mac_macho_reader_unittest-cfi_assembler.o `test -f 'src/common/dwarf/cfi_assembler.cc' || echo '$(srcdir)/'`src/common/dwarf/cfi_assembler.cc
+
+src/common/dwarf/src_common_mac_macho_reader_unittest-cfi_assembler.obj: src/common/dwarf/cfi_assembler.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/dwarf/src_common_mac_macho_reader_unittest-cfi_assembler.obj -MD -MP -MF src/common/dwarf/$(DEPDIR)/src_common_mac_macho_reader_unittest-cfi_assembler.Tpo -c -o src/common/dwarf/src_common_mac_macho_reader_unittest-cfi_assembler.obj `if test -f 'src/common/dwarf/cfi_assembler.cc'; then $(CYGPATH_W) 'src/common/dwarf/cfi_assembler.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/dwarf/cfi_assembler.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/dwarf/$(DEPDIR)/src_common_mac_macho_reader_unittest-cfi_assembler.Tpo src/common/dwarf/$(DEPDIR)/src_common_mac_macho_reader_unittest-cfi_assembler.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/dwarf/cfi_assembler.cc' object='src/common/dwarf/src_common_mac_macho_reader_unittest-cfi_assembler.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/dwarf/src_common_mac_macho_reader_unittest-cfi_assembler.obj `if test -f 'src/common/dwarf/cfi_assembler.cc'; then $(CYGPATH_W) 'src/common/dwarf/cfi_assembler.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/dwarf/cfi_assembler.cc'; fi`
+
+src/common/dwarf/src_common_mac_macho_reader_unittest-dwarf2diehandler.o: src/common/dwarf/dwarf2diehandler.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/dwarf/src_common_mac_macho_reader_unittest-dwarf2diehandler.o -MD -MP -MF src/common/dwarf/$(DEPDIR)/src_common_mac_macho_reader_unittest-dwarf2diehandler.Tpo -c -o src/common/dwarf/src_common_mac_macho_reader_unittest-dwarf2diehandler.o `test -f 'src/common/dwarf/dwarf2diehandler.cc' || echo '$(srcdir)/'`src/common/dwarf/dwarf2diehandler.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/dwarf/$(DEPDIR)/src_common_mac_macho_reader_unittest-dwarf2diehandler.Tpo src/common/dwarf/$(DEPDIR)/src_common_mac_macho_reader_unittest-dwarf2diehandler.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/dwarf/dwarf2diehandler.cc' object='src/common/dwarf/src_common_mac_macho_reader_unittest-dwarf2diehandler.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/dwarf/src_common_mac_macho_reader_unittest-dwarf2diehandler.o `test -f 'src/common/dwarf/dwarf2diehandler.cc' || echo '$(srcdir)/'`src/common/dwarf/dwarf2diehandler.cc
+
+src/common/dwarf/src_common_mac_macho_reader_unittest-dwarf2diehandler.obj: src/common/dwarf/dwarf2diehandler.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/dwarf/src_common_mac_macho_reader_unittest-dwarf2diehandler.obj -MD -MP -MF src/common/dwarf/$(DEPDIR)/src_common_mac_macho_reader_unittest-dwarf2diehandler.Tpo -c -o src/common/dwarf/src_common_mac_macho_reader_unittest-dwarf2diehandler.obj `if test -f 'src/common/dwarf/dwarf2diehandler.cc'; then $(CYGPATH_W) 'src/common/dwarf/dwarf2diehandler.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/dwarf/dwarf2diehandler.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/dwarf/$(DEPDIR)/src_common_mac_macho_reader_unittest-dwarf2diehandler.Tpo src/common/dwarf/$(DEPDIR)/src_common_mac_macho_reader_unittest-dwarf2diehandler.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/dwarf/dwarf2diehandler.cc' object='src/common/dwarf/src_common_mac_macho_reader_unittest-dwarf2diehandler.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/dwarf/src_common_mac_macho_reader_unittest-dwarf2diehandler.obj `if test -f 'src/common/dwarf/dwarf2diehandler.cc'; then $(CYGPATH_W) 'src/common/dwarf/dwarf2diehandler.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/dwarf/dwarf2diehandler.cc'; fi`
+
+src/common/dwarf/src_common_mac_macho_reader_unittest-dwarf2reader.o: src/common/dwarf/dwarf2reader.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/dwarf/src_common_mac_macho_reader_unittest-dwarf2reader.o -MD -MP -MF src/common/dwarf/$(DEPDIR)/src_common_mac_macho_reader_unittest-dwarf2reader.Tpo -c -o src/common/dwarf/src_common_mac_macho_reader_unittest-dwarf2reader.o `test -f 'src/common/dwarf/dwarf2reader.cc' || echo '$(srcdir)/'`src/common/dwarf/dwarf2reader.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/dwarf/$(DEPDIR)/src_common_mac_macho_reader_unittest-dwarf2reader.Tpo src/common/dwarf/$(DEPDIR)/src_common_mac_macho_reader_unittest-dwarf2reader.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/dwarf/dwarf2reader.cc' object='src/common/dwarf/src_common_mac_macho_reader_unittest-dwarf2reader.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/dwarf/src_common_mac_macho_reader_unittest-dwarf2reader.o `test -f 'src/common/dwarf/dwarf2reader.cc' || echo '$(srcdir)/'`src/common/dwarf/dwarf2reader.cc
+
+src/common/dwarf/src_common_mac_macho_reader_unittest-dwarf2reader.obj: src/common/dwarf/dwarf2reader.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/dwarf/src_common_mac_macho_reader_unittest-dwarf2reader.obj -MD -MP -MF src/common/dwarf/$(DEPDIR)/src_common_mac_macho_reader_unittest-dwarf2reader.Tpo -c -o src/common/dwarf/src_common_mac_macho_reader_unittest-dwarf2reader.obj `if test -f 'src/common/dwarf/dwarf2reader.cc'; then $(CYGPATH_W) 'src/common/dwarf/dwarf2reader.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/dwarf/dwarf2reader.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/dwarf/$(DEPDIR)/src_common_mac_macho_reader_unittest-dwarf2reader.Tpo src/common/dwarf/$(DEPDIR)/src_common_mac_macho_reader_unittest-dwarf2reader.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/dwarf/dwarf2reader.cc' object='src/common/dwarf/src_common_mac_macho_reader_unittest-dwarf2reader.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/dwarf/src_common_mac_macho_reader_unittest-dwarf2reader.obj `if test -f 'src/common/dwarf/dwarf2reader.cc'; then $(CYGPATH_W) 'src/common/dwarf/dwarf2reader.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/dwarf/dwarf2reader.cc'; fi`
+
+src/common/dwarf/src_common_mac_macho_reader_unittest-elf_reader.o: src/common/dwarf/elf_reader.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/dwarf/src_common_mac_macho_reader_unittest-elf_reader.o -MD -MP -MF src/common/dwarf/$(DEPDIR)/src_common_mac_macho_reader_unittest-elf_reader.Tpo -c -o src/common/dwarf/src_common_mac_macho_reader_unittest-elf_reader.o `test -f 'src/common/dwarf/elf_reader.cc' || echo '$(srcdir)/'`src/common/dwarf/elf_reader.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/dwarf/$(DEPDIR)/src_common_mac_macho_reader_unittest-elf_reader.Tpo src/common/dwarf/$(DEPDIR)/src_common_mac_macho_reader_unittest-elf_reader.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/dwarf/elf_reader.cc' object='src/common/dwarf/src_common_mac_macho_reader_unittest-elf_reader.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/dwarf/src_common_mac_macho_reader_unittest-elf_reader.o `test -f 'src/common/dwarf/elf_reader.cc' || echo '$(srcdir)/'`src/common/dwarf/elf_reader.cc
+
+src/common/dwarf/src_common_mac_macho_reader_unittest-elf_reader.obj: src/common/dwarf/elf_reader.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/dwarf/src_common_mac_macho_reader_unittest-elf_reader.obj -MD -MP -MF src/common/dwarf/$(DEPDIR)/src_common_mac_macho_reader_unittest-elf_reader.Tpo -c -o src/common/dwarf/src_common_mac_macho_reader_unittest-elf_reader.obj `if test -f 'src/common/dwarf/elf_reader.cc'; then $(CYGPATH_W) 'src/common/dwarf/elf_reader.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/dwarf/elf_reader.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/dwarf/$(DEPDIR)/src_common_mac_macho_reader_unittest-elf_reader.Tpo src/common/dwarf/$(DEPDIR)/src_common_mac_macho_reader_unittest-elf_reader.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/dwarf/elf_reader.cc' object='src/common/dwarf/src_common_mac_macho_reader_unittest-elf_reader.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/dwarf/src_common_mac_macho_reader_unittest-elf_reader.obj `if test -f 'src/common/dwarf/elf_reader.cc'; then $(CYGPATH_W) 'src/common/dwarf/elf_reader.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/dwarf/elf_reader.cc'; fi`
+
+src/common/mac/src_common_mac_macho_reader_unittest-arch_utilities.o: src/common/mac/arch_utilities.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/mac/src_common_mac_macho_reader_unittest-arch_utilities.o -MD -MP -MF src/common/mac/$(DEPDIR)/src_common_mac_macho_reader_unittest-arch_utilities.Tpo -c -o src/common/mac/src_common_mac_macho_reader_unittest-arch_utilities.o `test -f 'src/common/mac/arch_utilities.cc' || echo '$(srcdir)/'`src/common/mac/arch_utilities.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/mac/$(DEPDIR)/src_common_mac_macho_reader_unittest-arch_utilities.Tpo src/common/mac/$(DEPDIR)/src_common_mac_macho_reader_unittest-arch_utilities.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/mac/arch_utilities.cc' object='src/common/mac/src_common_mac_macho_reader_unittest-arch_utilities.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/mac/src_common_mac_macho_reader_unittest-arch_utilities.o `test -f 'src/common/mac/arch_utilities.cc' || echo '$(srcdir)/'`src/common/mac/arch_utilities.cc
+
+src/common/mac/src_common_mac_macho_reader_unittest-arch_utilities.obj: src/common/mac/arch_utilities.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/mac/src_common_mac_macho_reader_unittest-arch_utilities.obj -MD -MP -MF src/common/mac/$(DEPDIR)/src_common_mac_macho_reader_unittest-arch_utilities.Tpo -c -o src/common/mac/src_common_mac_macho_reader_unittest-arch_utilities.obj `if test -f 'src/common/mac/arch_utilities.cc'; then $(CYGPATH_W) 'src/common/mac/arch_utilities.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/mac/arch_utilities.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/mac/$(DEPDIR)/src_common_mac_macho_reader_unittest-arch_utilities.Tpo src/common/mac/$(DEPDIR)/src_common_mac_macho_reader_unittest-arch_utilities.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/mac/arch_utilities.cc' object='src/common/mac/src_common_mac_macho_reader_unittest-arch_utilities.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/mac/src_common_mac_macho_reader_unittest-arch_utilities.obj `if test -f 'src/common/mac/arch_utilities.cc'; then $(CYGPATH_W) 'src/common/mac/arch_utilities.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/mac/arch_utilities.cc'; fi`
+
+src/common/mac/src_common_mac_macho_reader_unittest-file_id.o: src/common/mac/file_id.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/mac/src_common_mac_macho_reader_unittest-file_id.o -MD -MP -MF src/common/mac/$(DEPDIR)/src_common_mac_macho_reader_unittest-file_id.Tpo -c -o src/common/mac/src_common_mac_macho_reader_unittest-file_id.o `test -f 'src/common/mac/file_id.cc' || echo '$(srcdir)/'`src/common/mac/file_id.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/mac/$(DEPDIR)/src_common_mac_macho_reader_unittest-file_id.Tpo src/common/mac/$(DEPDIR)/src_common_mac_macho_reader_unittest-file_id.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/mac/file_id.cc' object='src/common/mac/src_common_mac_macho_reader_unittest-file_id.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/mac/src_common_mac_macho_reader_unittest-file_id.o `test -f 'src/common/mac/file_id.cc' || echo '$(srcdir)/'`src/common/mac/file_id.cc
+
+src/common/mac/src_common_mac_macho_reader_unittest-file_id.obj: src/common/mac/file_id.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/mac/src_common_mac_macho_reader_unittest-file_id.obj -MD -MP -MF src/common/mac/$(DEPDIR)/src_common_mac_macho_reader_unittest-file_id.Tpo -c -o src/common/mac/src_common_mac_macho_reader_unittest-file_id.obj `if test -f 'src/common/mac/file_id.cc'; then $(CYGPATH_W) 'src/common/mac/file_id.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/mac/file_id.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/mac/$(DEPDIR)/src_common_mac_macho_reader_unittest-file_id.Tpo src/common/mac/$(DEPDIR)/src_common_mac_macho_reader_unittest-file_id.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/mac/file_id.cc' object='src/common/mac/src_common_mac_macho_reader_unittest-file_id.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/mac/src_common_mac_macho_reader_unittest-file_id.obj `if test -f 'src/common/mac/file_id.cc'; then $(CYGPATH_W) 'src/common/mac/file_id.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/mac/file_id.cc'; fi`
+
+src/common/mac/src_common_mac_macho_reader_unittest-macho_id.o: src/common/mac/macho_id.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/mac/src_common_mac_macho_reader_unittest-macho_id.o -MD -MP -MF src/common/mac/$(DEPDIR)/src_common_mac_macho_reader_unittest-macho_id.Tpo -c -o src/common/mac/src_common_mac_macho_reader_unittest-macho_id.o `test -f 'src/common/mac/macho_id.cc' || echo '$(srcdir)/'`src/common/mac/macho_id.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/mac/$(DEPDIR)/src_common_mac_macho_reader_unittest-macho_id.Tpo src/common/mac/$(DEPDIR)/src_common_mac_macho_reader_unittest-macho_id.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/mac/macho_id.cc' object='src/common/mac/src_common_mac_macho_reader_unittest-macho_id.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/mac/src_common_mac_macho_reader_unittest-macho_id.o `test -f 'src/common/mac/macho_id.cc' || echo '$(srcdir)/'`src/common/mac/macho_id.cc
+
+src/common/mac/src_common_mac_macho_reader_unittest-macho_id.obj: src/common/mac/macho_id.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/mac/src_common_mac_macho_reader_unittest-macho_id.obj -MD -MP -MF src/common/mac/$(DEPDIR)/src_common_mac_macho_reader_unittest-macho_id.Tpo -c -o src/common/mac/src_common_mac_macho_reader_unittest-macho_id.obj `if test -f 'src/common/mac/macho_id.cc'; then $(CYGPATH_W) 'src/common/mac/macho_id.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/mac/macho_id.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/mac/$(DEPDIR)/src_common_mac_macho_reader_unittest-macho_id.Tpo src/common/mac/$(DEPDIR)/src_common_mac_macho_reader_unittest-macho_id.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/mac/macho_id.cc' object='src/common/mac/src_common_mac_macho_reader_unittest-macho_id.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/mac/src_common_mac_macho_reader_unittest-macho_id.obj `if test -f 'src/common/mac/macho_id.cc'; then $(CYGPATH_W) 'src/common/mac/macho_id.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/mac/macho_id.cc'; fi`
+
+src/common/mac/src_common_mac_macho_reader_unittest-macho_reader.o: src/common/mac/macho_reader.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/mac/src_common_mac_macho_reader_unittest-macho_reader.o -MD -MP -MF src/common/mac/$(DEPDIR)/src_common_mac_macho_reader_unittest-macho_reader.Tpo -c -o src/common/mac/src_common_mac_macho_reader_unittest-macho_reader.o `test -f 'src/common/mac/macho_reader.cc' || echo '$(srcdir)/'`src/common/mac/macho_reader.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/mac/$(DEPDIR)/src_common_mac_macho_reader_unittest-macho_reader.Tpo src/common/mac/$(DEPDIR)/src_common_mac_macho_reader_unittest-macho_reader.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/mac/macho_reader.cc' object='src/common/mac/src_common_mac_macho_reader_unittest-macho_reader.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/mac/src_common_mac_macho_reader_unittest-macho_reader.o `test -f 'src/common/mac/macho_reader.cc' || echo '$(srcdir)/'`src/common/mac/macho_reader.cc
+
+src/common/mac/src_common_mac_macho_reader_unittest-macho_reader.obj: src/common/mac/macho_reader.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/mac/src_common_mac_macho_reader_unittest-macho_reader.obj -MD -MP -MF src/common/mac/$(DEPDIR)/src_common_mac_macho_reader_unittest-macho_reader.Tpo -c -o src/common/mac/src_common_mac_macho_reader_unittest-macho_reader.obj `if test -f 'src/common/mac/macho_reader.cc'; then $(CYGPATH_W) 'src/common/mac/macho_reader.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/mac/macho_reader.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/mac/$(DEPDIR)/src_common_mac_macho_reader_unittest-macho_reader.Tpo src/common/mac/$(DEPDIR)/src_common_mac_macho_reader_unittest-macho_reader.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/mac/macho_reader.cc' object='src/common/mac/src_common_mac_macho_reader_unittest-macho_reader.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/mac/src_common_mac_macho_reader_unittest-macho_reader.obj `if test -f 'src/common/mac/macho_reader.cc'; then $(CYGPATH_W) 'src/common/mac/macho_reader.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/mac/macho_reader.cc'; fi`
+
+src/common/mac/src_common_mac_macho_reader_unittest-macho_reader_unittest.o: src/common/mac/macho_reader_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/mac/src_common_mac_macho_reader_unittest-macho_reader_unittest.o -MD -MP -MF src/common/mac/$(DEPDIR)/src_common_mac_macho_reader_unittest-macho_reader_unittest.Tpo -c -o src/common/mac/src_common_mac_macho_reader_unittest-macho_reader_unittest.o `test -f 'src/common/mac/macho_reader_unittest.cc' || echo '$(srcdir)/'`src/common/mac/macho_reader_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/mac/$(DEPDIR)/src_common_mac_macho_reader_unittest-macho_reader_unittest.Tpo src/common/mac/$(DEPDIR)/src_common_mac_macho_reader_unittest-macho_reader_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/mac/macho_reader_unittest.cc' object='src/common/mac/src_common_mac_macho_reader_unittest-macho_reader_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/mac/src_common_mac_macho_reader_unittest-macho_reader_unittest.o `test -f 'src/common/mac/macho_reader_unittest.cc' || echo '$(srcdir)/'`src/common/mac/macho_reader_unittest.cc
+
+src/common/mac/src_common_mac_macho_reader_unittest-macho_reader_unittest.obj: src/common/mac/macho_reader_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/mac/src_common_mac_macho_reader_unittest-macho_reader_unittest.obj -MD -MP -MF src/common/mac/$(DEPDIR)/src_common_mac_macho_reader_unittest-macho_reader_unittest.Tpo -c -o src/common/mac/src_common_mac_macho_reader_unittest-macho_reader_unittest.obj `if test -f 'src/common/mac/macho_reader_unittest.cc'; then $(CYGPATH_W) 'src/common/mac/macho_reader_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/mac/macho_reader_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/mac/$(DEPDIR)/src_common_mac_macho_reader_unittest-macho_reader_unittest.Tpo src/common/mac/$(DEPDIR)/src_common_mac_macho_reader_unittest-macho_reader_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/mac/macho_reader_unittest.cc' object='src/common/mac/src_common_mac_macho_reader_unittest-macho_reader_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/mac/src_common_mac_macho_reader_unittest-macho_reader_unittest.obj `if test -f 'src/common/mac/macho_reader_unittest.cc'; then $(CYGPATH_W) 'src/common/mac/macho_reader_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/mac/macho_reader_unittest.cc'; fi`
+
+src/common/mac/src_common_mac_macho_reader_unittest-macho_utilities.o: src/common/mac/macho_utilities.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/mac/src_common_mac_macho_reader_unittest-macho_utilities.o -MD -MP -MF src/common/mac/$(DEPDIR)/src_common_mac_macho_reader_unittest-macho_utilities.Tpo -c -o src/common/mac/src_common_mac_macho_reader_unittest-macho_utilities.o `test -f 'src/common/mac/macho_utilities.cc' || echo '$(srcdir)/'`src/common/mac/macho_utilities.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/mac/$(DEPDIR)/src_common_mac_macho_reader_unittest-macho_utilities.Tpo src/common/mac/$(DEPDIR)/src_common_mac_macho_reader_unittest-macho_utilities.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/mac/macho_utilities.cc' object='src/common/mac/src_common_mac_macho_reader_unittest-macho_utilities.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/mac/src_common_mac_macho_reader_unittest-macho_utilities.o `test -f 'src/common/mac/macho_utilities.cc' || echo '$(srcdir)/'`src/common/mac/macho_utilities.cc
+
+src/common/mac/src_common_mac_macho_reader_unittest-macho_utilities.obj: src/common/mac/macho_utilities.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/mac/src_common_mac_macho_reader_unittest-macho_utilities.obj -MD -MP -MF src/common/mac/$(DEPDIR)/src_common_mac_macho_reader_unittest-macho_utilities.Tpo -c -o src/common/mac/src_common_mac_macho_reader_unittest-macho_utilities.obj `if test -f 'src/common/mac/macho_utilities.cc'; then $(CYGPATH_W) 'src/common/mac/macho_utilities.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/mac/macho_utilities.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/mac/$(DEPDIR)/src_common_mac_macho_reader_unittest-macho_utilities.Tpo src/common/mac/$(DEPDIR)/src_common_mac_macho_reader_unittest-macho_utilities.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/mac/macho_utilities.cc' object='src/common/mac/src_common_mac_macho_reader_unittest-macho_utilities.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/mac/src_common_mac_macho_reader_unittest-macho_utilities.obj `if test -f 'src/common/mac/macho_utilities.cc'; then $(CYGPATH_W) 'src/common/mac/macho_utilities.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/mac/macho_utilities.cc'; fi`
+
+src/common/mac/src_common_mac_macho_reader_unittest-macho_walker.o: src/common/mac/macho_walker.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/mac/src_common_mac_macho_reader_unittest-macho_walker.o -MD -MP -MF src/common/mac/$(DEPDIR)/src_common_mac_macho_reader_unittest-macho_walker.Tpo -c -o src/common/mac/src_common_mac_macho_reader_unittest-macho_walker.o `test -f 'src/common/mac/macho_walker.cc' || echo '$(srcdir)/'`src/common/mac/macho_walker.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/mac/$(DEPDIR)/src_common_mac_macho_reader_unittest-macho_walker.Tpo src/common/mac/$(DEPDIR)/src_common_mac_macho_reader_unittest-macho_walker.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/mac/macho_walker.cc' object='src/common/mac/src_common_mac_macho_reader_unittest-macho_walker.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/mac/src_common_mac_macho_reader_unittest-macho_walker.o `test -f 'src/common/mac/macho_walker.cc' || echo '$(srcdir)/'`src/common/mac/macho_walker.cc
+
+src/common/mac/src_common_mac_macho_reader_unittest-macho_walker.obj: src/common/mac/macho_walker.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/mac/src_common_mac_macho_reader_unittest-macho_walker.obj -MD -MP -MF src/common/mac/$(DEPDIR)/src_common_mac_macho_reader_unittest-macho_walker.Tpo -c -o src/common/mac/src_common_mac_macho_reader_unittest-macho_walker.obj `if test -f 'src/common/mac/macho_walker.cc'; then $(CYGPATH_W) 'src/common/mac/macho_walker.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/mac/macho_walker.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/mac/$(DEPDIR)/src_common_mac_macho_reader_unittest-macho_walker.Tpo src/common/mac/$(DEPDIR)/src_common_mac_macho_reader_unittest-macho_walker.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/mac/macho_walker.cc' object='src/common/mac/src_common_mac_macho_reader_unittest-macho_walker.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/mac/src_common_mac_macho_reader_unittest-macho_walker.obj `if test -f 'src/common/mac/macho_walker.cc'; then $(CYGPATH_W) 'src/common/mac/macho_walker.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/mac/macho_walker.cc'; fi`
+
+src/common/tests/src_common_mac_macho_reader_unittest-file_utils.o: src/common/tests/file_utils.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/tests/src_common_mac_macho_reader_unittest-file_utils.o -MD -MP -MF src/common/tests/$(DEPDIR)/src_common_mac_macho_reader_unittest-file_utils.Tpo -c -o src/common/tests/src_common_mac_macho_reader_unittest-file_utils.o `test -f 'src/common/tests/file_utils.cc' || echo '$(srcdir)/'`src/common/tests/file_utils.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/tests/$(DEPDIR)/src_common_mac_macho_reader_unittest-file_utils.Tpo src/common/tests/$(DEPDIR)/src_common_mac_macho_reader_unittest-file_utils.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/tests/file_utils.cc' object='src/common/tests/src_common_mac_macho_reader_unittest-file_utils.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/tests/src_common_mac_macho_reader_unittest-file_utils.o `test -f 'src/common/tests/file_utils.cc' || echo '$(srcdir)/'`src/common/tests/file_utils.cc
+
+src/common/tests/src_common_mac_macho_reader_unittest-file_utils.obj: src/common/tests/file_utils.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/tests/src_common_mac_macho_reader_unittest-file_utils.obj -MD -MP -MF src/common/tests/$(DEPDIR)/src_common_mac_macho_reader_unittest-file_utils.Tpo -c -o src/common/tests/src_common_mac_macho_reader_unittest-file_utils.obj `if test -f 'src/common/tests/file_utils.cc'; then $(CYGPATH_W) 'src/common/tests/file_utils.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/tests/file_utils.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/tests/$(DEPDIR)/src_common_mac_macho_reader_unittest-file_utils.Tpo src/common/tests/$(DEPDIR)/src_common_mac_macho_reader_unittest-file_utils.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/tests/file_utils.cc' object='src/common/tests/src_common_mac_macho_reader_unittest-file_utils.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/tests/src_common_mac_macho_reader_unittest-file_utils.obj `if test -f 'src/common/tests/file_utils.cc'; then $(CYGPATH_W) 'src/common/tests/file_utils.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/tests/file_utils.cc'; fi`
+
+src/common/src_common_test_assembler_unittest-test_assembler.o: src/common/test_assembler.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_test_assembler_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_common_test_assembler_unittest-test_assembler.o -MD -MP -MF src/common/$(DEPDIR)/src_common_test_assembler_unittest-test_assembler.Tpo -c -o src/common/src_common_test_assembler_unittest-test_assembler.o `test -f 'src/common/test_assembler.cc' || echo '$(srcdir)/'`src/common/test_assembler.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_common_test_assembler_unittest-test_assembler.Tpo src/common/$(DEPDIR)/src_common_test_assembler_unittest-test_assembler.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/test_assembler.cc' object='src/common/src_common_test_assembler_unittest-test_assembler.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_test_assembler_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_common_test_assembler_unittest-test_assembler.o `test -f 'src/common/test_assembler.cc' || echo '$(srcdir)/'`src/common/test_assembler.cc
+
+src/common/src_common_test_assembler_unittest-test_assembler.obj: src/common/test_assembler.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_test_assembler_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_common_test_assembler_unittest-test_assembler.obj -MD -MP -MF src/common/$(DEPDIR)/src_common_test_assembler_unittest-test_assembler.Tpo -c -o src/common/src_common_test_assembler_unittest-test_assembler.obj `if test -f 'src/common/test_assembler.cc'; then $(CYGPATH_W) 'src/common/test_assembler.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/test_assembler.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_common_test_assembler_unittest-test_assembler.Tpo src/common/$(DEPDIR)/src_common_test_assembler_unittest-test_assembler.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/test_assembler.cc' object='src/common/src_common_test_assembler_unittest-test_assembler.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_test_assembler_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_common_test_assembler_unittest-test_assembler.obj `if test -f 'src/common/test_assembler.cc'; then $(CYGPATH_W) 'src/common/test_assembler.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/test_assembler.cc'; fi`
+
+src/common/src_common_test_assembler_unittest-test_assembler_unittest.o: src/common/test_assembler_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_test_assembler_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_common_test_assembler_unittest-test_assembler_unittest.o -MD -MP -MF src/common/$(DEPDIR)/src_common_test_assembler_unittest-test_assembler_unittest.Tpo -c -o src/common/src_common_test_assembler_unittest-test_assembler_unittest.o `test -f 'src/common/test_assembler_unittest.cc' || echo '$(srcdir)/'`src/common/test_assembler_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_common_test_assembler_unittest-test_assembler_unittest.Tpo src/common/$(DEPDIR)/src_common_test_assembler_unittest-test_assembler_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/test_assembler_unittest.cc' object='src/common/src_common_test_assembler_unittest-test_assembler_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_test_assembler_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_common_test_assembler_unittest-test_assembler_unittest.o `test -f 'src/common/test_assembler_unittest.cc' || echo '$(srcdir)/'`src/common/test_assembler_unittest.cc
+
+src/common/src_common_test_assembler_unittest-test_assembler_unittest.obj: src/common/test_assembler_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_test_assembler_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_common_test_assembler_unittest-test_assembler_unittest.obj -MD -MP -MF src/common/$(DEPDIR)/src_common_test_assembler_unittest-test_assembler_unittest.Tpo -c -o src/common/src_common_test_assembler_unittest-test_assembler_unittest.obj `if test -f 'src/common/test_assembler_unittest.cc'; then $(CYGPATH_W) 'src/common/test_assembler_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/test_assembler_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_common_test_assembler_unittest-test_assembler_unittest.Tpo src/common/$(DEPDIR)/src_common_test_assembler_unittest-test_assembler_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/test_assembler_unittest.cc' object='src/common/src_common_test_assembler_unittest-test_assembler_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_test_assembler_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_common_test_assembler_unittest-test_assembler_unittest.obj `if test -f 'src/common/test_assembler_unittest.cc'; then $(CYGPATH_W) 'src/common/test_assembler_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/test_assembler_unittest.cc'; fi`
+
+src/processor/src_processor_basic_source_line_resolver_unittest-basic_source_line_resolver_unittest.o: src/processor/basic_source_line_resolver_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_basic_source_line_resolver_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/processor/src_processor_basic_source_line_resolver_unittest-basic_source_line_resolver_unittest.o -MD -MP -MF src/processor/$(DEPDIR)/src_processor_basic_source_line_resolver_unittest-basic_source_line_resolver_unittest.Tpo -c -o src/processor/src_processor_basic_source_line_resolver_unittest-basic_source_line_resolver_unittest.o `test -f 'src/processor/basic_source_line_resolver_unittest.cc' || echo '$(srcdir)/'`src/processor/basic_source_line_resolver_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/processor/$(DEPDIR)/src_processor_basic_source_line_resolver_unittest-basic_source_line_resolver_unittest.Tpo src/processor/$(DEPDIR)/src_processor_basic_source_line_resolver_unittest-basic_source_line_resolver_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/processor/basic_source_line_resolver_unittest.cc' object='src/processor/src_processor_basic_source_line_resolver_unittest-basic_source_line_resolver_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_basic_source_line_resolver_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/processor/src_processor_basic_source_line_resolver_unittest-basic_source_line_resolver_unittest.o `test -f 'src/processor/basic_source_line_resolver_unittest.cc' || echo '$(srcdir)/'`src/processor/basic_source_line_resolver_unittest.cc
+
+src/processor/src_processor_basic_source_line_resolver_unittest-basic_source_line_resolver_unittest.obj: src/processor/basic_source_line_resolver_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_basic_source_line_resolver_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/processor/src_processor_basic_source_line_resolver_unittest-basic_source_line_resolver_unittest.obj -MD -MP -MF src/processor/$(DEPDIR)/src_processor_basic_source_line_resolver_unittest-basic_source_line_resolver_unittest.Tpo -c -o src/processor/src_processor_basic_source_line_resolver_unittest-basic_source_line_resolver_unittest.obj `if test -f 'src/processor/basic_source_line_resolver_unittest.cc'; then $(CYGPATH_W) 'src/processor/basic_source_line_resolver_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/processor/basic_source_line_resolver_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/processor/$(DEPDIR)/src_processor_basic_source_line_resolver_unittest-basic_source_line_resolver_unittest.Tpo src/processor/$(DEPDIR)/src_processor_basic_source_line_resolver_unittest-basic_source_line_resolver_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/processor/basic_source_line_resolver_unittest.cc' object='src/processor/src_processor_basic_source_line_resolver_unittest-basic_source_line_resolver_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_basic_source_line_resolver_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/processor/src_processor_basic_source_line_resolver_unittest-basic_source_line_resolver_unittest.obj `if test -f 'src/processor/basic_source_line_resolver_unittest.cc'; then $(CYGPATH_W) 'src/processor/basic_source_line_resolver_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/processor/basic_source_line_resolver_unittest.cc'; fi`
+
+src/processor/src_processor_cfi_frame_info_unittest-cfi_frame_info_unittest.o: src/processor/cfi_frame_info_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_cfi_frame_info_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/processor/src_processor_cfi_frame_info_unittest-cfi_frame_info_unittest.o -MD -MP -MF src/processor/$(DEPDIR)/src_processor_cfi_frame_info_unittest-cfi_frame_info_unittest.Tpo -c -o src/processor/src_processor_cfi_frame_info_unittest-cfi_frame_info_unittest.o `test -f 'src/processor/cfi_frame_info_unittest.cc' || echo '$(srcdir)/'`src/processor/cfi_frame_info_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/processor/$(DEPDIR)/src_processor_cfi_frame_info_unittest-cfi_frame_info_unittest.Tpo src/processor/$(DEPDIR)/src_processor_cfi_frame_info_unittest-cfi_frame_info_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/processor/cfi_frame_info_unittest.cc' object='src/processor/src_processor_cfi_frame_info_unittest-cfi_frame_info_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_cfi_frame_info_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/processor/src_processor_cfi_frame_info_unittest-cfi_frame_info_unittest.o `test -f 'src/processor/cfi_frame_info_unittest.cc' || echo '$(srcdir)/'`src/processor/cfi_frame_info_unittest.cc
+
+src/processor/src_processor_cfi_frame_info_unittest-cfi_frame_info_unittest.obj: src/processor/cfi_frame_info_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_cfi_frame_info_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/processor/src_processor_cfi_frame_info_unittest-cfi_frame_info_unittest.obj -MD -MP -MF src/processor/$(DEPDIR)/src_processor_cfi_frame_info_unittest-cfi_frame_info_unittest.Tpo -c -o src/processor/src_processor_cfi_frame_info_unittest-cfi_frame_info_unittest.obj `if test -f 'src/processor/cfi_frame_info_unittest.cc'; then $(CYGPATH_W) 'src/processor/cfi_frame_info_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/processor/cfi_frame_info_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/processor/$(DEPDIR)/src_processor_cfi_frame_info_unittest-cfi_frame_info_unittest.Tpo src/processor/$(DEPDIR)/src_processor_cfi_frame_info_unittest-cfi_frame_info_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/processor/cfi_frame_info_unittest.cc' object='src/processor/src_processor_cfi_frame_info_unittest-cfi_frame_info_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_cfi_frame_info_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/processor/src_processor_cfi_frame_info_unittest-cfi_frame_info_unittest.obj `if test -f 'src/processor/cfi_frame_info_unittest.cc'; then $(CYGPATH_W) 'src/processor/cfi_frame_info_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/processor/cfi_frame_info_unittest.cc'; fi`
+
+src/processor/src_processor_disassembler_x86_unittest-disassembler_x86_unittest.o: src/processor/disassembler_x86_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_disassembler_x86_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/processor/src_processor_disassembler_x86_unittest-disassembler_x86_unittest.o -MD -MP -MF src/processor/$(DEPDIR)/src_processor_disassembler_x86_unittest-disassembler_x86_unittest.Tpo -c -o src/processor/src_processor_disassembler_x86_unittest-disassembler_x86_unittest.o `test -f 'src/processor/disassembler_x86_unittest.cc' || echo '$(srcdir)/'`src/processor/disassembler_x86_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/processor/$(DEPDIR)/src_processor_disassembler_x86_unittest-disassembler_x86_unittest.Tpo src/processor/$(DEPDIR)/src_processor_disassembler_x86_unittest-disassembler_x86_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/processor/disassembler_x86_unittest.cc' object='src/processor/src_processor_disassembler_x86_unittest-disassembler_x86_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_disassembler_x86_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/processor/src_processor_disassembler_x86_unittest-disassembler_x86_unittest.o `test -f 'src/processor/disassembler_x86_unittest.cc' || echo '$(srcdir)/'`src/processor/disassembler_x86_unittest.cc
+
+src/processor/src_processor_disassembler_x86_unittest-disassembler_x86_unittest.obj: src/processor/disassembler_x86_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_disassembler_x86_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/processor/src_processor_disassembler_x86_unittest-disassembler_x86_unittest.obj -MD -MP -MF src/processor/$(DEPDIR)/src_processor_disassembler_x86_unittest-disassembler_x86_unittest.Tpo -c -o src/processor/src_processor_disassembler_x86_unittest-disassembler_x86_unittest.obj `if test -f 'src/processor/disassembler_x86_unittest.cc'; then $(CYGPATH_W) 'src/processor/disassembler_x86_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/processor/disassembler_x86_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/processor/$(DEPDIR)/src_processor_disassembler_x86_unittest-disassembler_x86_unittest.Tpo src/processor/$(DEPDIR)/src_processor_disassembler_x86_unittest-disassembler_x86_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/processor/disassembler_x86_unittest.cc' object='src/processor/src_processor_disassembler_x86_unittest-disassembler_x86_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_disassembler_x86_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/processor/src_processor_disassembler_x86_unittest-disassembler_x86_unittest.obj `if test -f 'src/processor/disassembler_x86_unittest.cc'; then $(CYGPATH_W) 'src/processor/disassembler_x86_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/processor/disassembler_x86_unittest.cc'; fi`
+
+src/processor/src_processor_exploitability_unittest-exploitability_unittest.o: src/processor/exploitability_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_exploitability_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/processor/src_processor_exploitability_unittest-exploitability_unittest.o -MD -MP -MF src/processor/$(DEPDIR)/src_processor_exploitability_unittest-exploitability_unittest.Tpo -c -o src/processor/src_processor_exploitability_unittest-exploitability_unittest.o `test -f 'src/processor/exploitability_unittest.cc' || echo '$(srcdir)/'`src/processor/exploitability_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/processor/$(DEPDIR)/src_processor_exploitability_unittest-exploitability_unittest.Tpo src/processor/$(DEPDIR)/src_processor_exploitability_unittest-exploitability_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/processor/exploitability_unittest.cc' object='src/processor/src_processor_exploitability_unittest-exploitability_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_exploitability_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/processor/src_processor_exploitability_unittest-exploitability_unittest.o `test -f 'src/processor/exploitability_unittest.cc' || echo '$(srcdir)/'`src/processor/exploitability_unittest.cc
+
+src/processor/src_processor_exploitability_unittest-exploitability_unittest.obj: src/processor/exploitability_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_exploitability_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/processor/src_processor_exploitability_unittest-exploitability_unittest.obj -MD -MP -MF src/processor/$(DEPDIR)/src_processor_exploitability_unittest-exploitability_unittest.Tpo -c -o src/processor/src_processor_exploitability_unittest-exploitability_unittest.obj `if test -f 'src/processor/exploitability_unittest.cc'; then $(CYGPATH_W) 'src/processor/exploitability_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/processor/exploitability_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/processor/$(DEPDIR)/src_processor_exploitability_unittest-exploitability_unittest.Tpo src/processor/$(DEPDIR)/src_processor_exploitability_unittest-exploitability_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/processor/exploitability_unittest.cc' object='src/processor/src_processor_exploitability_unittest-exploitability_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_exploitability_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/processor/src_processor_exploitability_unittest-exploitability_unittest.obj `if test -f 'src/processor/exploitability_unittest.cc'; then $(CYGPATH_W) 'src/processor/exploitability_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/processor/exploitability_unittest.cc'; fi`
+
+src/processor/src_processor_fast_source_line_resolver_unittest-fast_source_line_resolver_unittest.o: src/processor/fast_source_line_resolver_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_fast_source_line_resolver_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/processor/src_processor_fast_source_line_resolver_unittest-fast_source_line_resolver_unittest.o -MD -MP -MF src/processor/$(DEPDIR)/src_processor_fast_source_line_resolver_unittest-fast_source_line_resolver_unittest.Tpo -c -o src/processor/src_processor_fast_source_line_resolver_unittest-fast_source_line_resolver_unittest.o `test -f 'src/processor/fast_source_line_resolver_unittest.cc' || echo '$(srcdir)/'`src/processor/fast_source_line_resolver_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/processor/$(DEPDIR)/src_processor_fast_source_line_resolver_unittest-fast_source_line_resolver_unittest.Tpo src/processor/$(DEPDIR)/src_processor_fast_source_line_resolver_unittest-fast_source_line_resolver_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/processor/fast_source_line_resolver_unittest.cc' object='src/processor/src_processor_fast_source_line_resolver_unittest-fast_source_line_resolver_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_fast_source_line_resolver_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/processor/src_processor_fast_source_line_resolver_unittest-fast_source_line_resolver_unittest.o `test -f 'src/processor/fast_source_line_resolver_unittest.cc' || echo '$(srcdir)/'`src/processor/fast_source_line_resolver_unittest.cc
+
+src/processor/src_processor_fast_source_line_resolver_unittest-fast_source_line_resolver_unittest.obj: src/processor/fast_source_line_resolver_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_fast_source_line_resolver_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/processor/src_processor_fast_source_line_resolver_unittest-fast_source_line_resolver_unittest.obj -MD -MP -MF src/processor/$(DEPDIR)/src_processor_fast_source_line_resolver_unittest-fast_source_line_resolver_unittest.Tpo -c -o src/processor/src_processor_fast_source_line_resolver_unittest-fast_source_line_resolver_unittest.obj `if test -f 'src/processor/fast_source_line_resolver_unittest.cc'; then $(CYGPATH_W) 'src/processor/fast_source_line_resolver_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/processor/fast_source_line_resolver_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/processor/$(DEPDIR)/src_processor_fast_source_line_resolver_unittest-fast_source_line_resolver_unittest.Tpo src/processor/$(DEPDIR)/src_processor_fast_source_line_resolver_unittest-fast_source_line_resolver_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/processor/fast_source_line_resolver_unittest.cc' object='src/processor/src_processor_fast_source_line_resolver_unittest-fast_source_line_resolver_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_fast_source_line_resolver_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/processor/src_processor_fast_source_line_resolver_unittest-fast_source_line_resolver_unittest.obj `if test -f 'src/processor/fast_source_line_resolver_unittest.cc'; then $(CYGPATH_W) 'src/processor/fast_source_line_resolver_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/processor/fast_source_line_resolver_unittest.cc'; fi`
+
+src/processor/src_processor_map_serializers_unittest-map_serializers_unittest.o: src/processor/map_serializers_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_map_serializers_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/processor/src_processor_map_serializers_unittest-map_serializers_unittest.o -MD -MP -MF src/processor/$(DEPDIR)/src_processor_map_serializers_unittest-map_serializers_unittest.Tpo -c -o src/processor/src_processor_map_serializers_unittest-map_serializers_unittest.o `test -f 'src/processor/map_serializers_unittest.cc' || echo '$(srcdir)/'`src/processor/map_serializers_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/processor/$(DEPDIR)/src_processor_map_serializers_unittest-map_serializers_unittest.Tpo src/processor/$(DEPDIR)/src_processor_map_serializers_unittest-map_serializers_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/processor/map_serializers_unittest.cc' object='src/processor/src_processor_map_serializers_unittest-map_serializers_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_map_serializers_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/processor/src_processor_map_serializers_unittest-map_serializers_unittest.o `test -f 'src/processor/map_serializers_unittest.cc' || echo '$(srcdir)/'`src/processor/map_serializers_unittest.cc
+
+src/processor/src_processor_map_serializers_unittest-map_serializers_unittest.obj: src/processor/map_serializers_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_map_serializers_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/processor/src_processor_map_serializers_unittest-map_serializers_unittest.obj -MD -MP -MF src/processor/$(DEPDIR)/src_processor_map_serializers_unittest-map_serializers_unittest.Tpo -c -o src/processor/src_processor_map_serializers_unittest-map_serializers_unittest.obj `if test -f 'src/processor/map_serializers_unittest.cc'; then $(CYGPATH_W) 'src/processor/map_serializers_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/processor/map_serializers_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/processor/$(DEPDIR)/src_processor_map_serializers_unittest-map_serializers_unittest.Tpo src/processor/$(DEPDIR)/src_processor_map_serializers_unittest-map_serializers_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/processor/map_serializers_unittest.cc' object='src/processor/src_processor_map_serializers_unittest-map_serializers_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_map_serializers_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/processor/src_processor_map_serializers_unittest-map_serializers_unittest.obj `if test -f 'src/processor/map_serializers_unittest.cc'; then $(CYGPATH_W) 'src/processor/map_serializers_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/processor/map_serializers_unittest.cc'; fi`
+
+src/processor/src_processor_microdump_processor_unittest-microdump_processor_unittest.o: src/processor/microdump_processor_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_microdump_processor_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/processor/src_processor_microdump_processor_unittest-microdump_processor_unittest.o -MD -MP -MF src/processor/$(DEPDIR)/src_processor_microdump_processor_unittest-microdump_processor_unittest.Tpo -c -o src/processor/src_processor_microdump_processor_unittest-microdump_processor_unittest.o `test -f 'src/processor/microdump_processor_unittest.cc' || echo '$(srcdir)/'`src/processor/microdump_processor_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/processor/$(DEPDIR)/src_processor_microdump_processor_unittest-microdump_processor_unittest.Tpo src/processor/$(DEPDIR)/src_processor_microdump_processor_unittest-microdump_processor_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/processor/microdump_processor_unittest.cc' object='src/processor/src_processor_microdump_processor_unittest-microdump_processor_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_microdump_processor_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/processor/src_processor_microdump_processor_unittest-microdump_processor_unittest.o `test -f 'src/processor/microdump_processor_unittest.cc' || echo '$(srcdir)/'`src/processor/microdump_processor_unittest.cc
+
+src/processor/src_processor_microdump_processor_unittest-microdump_processor_unittest.obj: src/processor/microdump_processor_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_microdump_processor_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/processor/src_processor_microdump_processor_unittest-microdump_processor_unittest.obj -MD -MP -MF src/processor/$(DEPDIR)/src_processor_microdump_processor_unittest-microdump_processor_unittest.Tpo -c -o src/processor/src_processor_microdump_processor_unittest-microdump_processor_unittest.obj `if test -f 'src/processor/microdump_processor_unittest.cc'; then $(CYGPATH_W) 'src/processor/microdump_processor_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/processor/microdump_processor_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/processor/$(DEPDIR)/src_processor_microdump_processor_unittest-microdump_processor_unittest.Tpo src/processor/$(DEPDIR)/src_processor_microdump_processor_unittest-microdump_processor_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/processor/microdump_processor_unittest.cc' object='src/processor/src_processor_microdump_processor_unittest-microdump_processor_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_microdump_processor_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/processor/src_processor_microdump_processor_unittest-microdump_processor_unittest.obj `if test -f 'src/processor/microdump_processor_unittest.cc'; then $(CYGPATH_W) 'src/processor/microdump_processor_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/processor/microdump_processor_unittest.cc'; fi`
+
+src/processor/src_processor_minidump_processor_unittest-minidump_processor_unittest.o: src/processor/minidump_processor_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_minidump_processor_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/processor/src_processor_minidump_processor_unittest-minidump_processor_unittest.o -MD -MP -MF src/processor/$(DEPDIR)/src_processor_minidump_processor_unittest-minidump_processor_unittest.Tpo -c -o src/processor/src_processor_minidump_processor_unittest-minidump_processor_unittest.o `test -f 'src/processor/minidump_processor_unittest.cc' || echo '$(srcdir)/'`src/processor/minidump_processor_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/processor/$(DEPDIR)/src_processor_minidump_processor_unittest-minidump_processor_unittest.Tpo src/processor/$(DEPDIR)/src_processor_minidump_processor_unittest-minidump_processor_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/processor/minidump_processor_unittest.cc' object='src/processor/src_processor_minidump_processor_unittest-minidump_processor_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_minidump_processor_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/processor/src_processor_minidump_processor_unittest-minidump_processor_unittest.o `test -f 'src/processor/minidump_processor_unittest.cc' || echo '$(srcdir)/'`src/processor/minidump_processor_unittest.cc
+
+src/processor/src_processor_minidump_processor_unittest-minidump_processor_unittest.obj: src/processor/minidump_processor_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_minidump_processor_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/processor/src_processor_minidump_processor_unittest-minidump_processor_unittest.obj -MD -MP -MF src/processor/$(DEPDIR)/src_processor_minidump_processor_unittest-minidump_processor_unittest.Tpo -c -o src/processor/src_processor_minidump_processor_unittest-minidump_processor_unittest.obj `if test -f 'src/processor/minidump_processor_unittest.cc'; then $(CYGPATH_W) 'src/processor/minidump_processor_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/processor/minidump_processor_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/processor/$(DEPDIR)/src_processor_minidump_processor_unittest-minidump_processor_unittest.Tpo src/processor/$(DEPDIR)/src_processor_minidump_processor_unittest-minidump_processor_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/processor/minidump_processor_unittest.cc' object='src/processor/src_processor_minidump_processor_unittest-minidump_processor_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_minidump_processor_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/processor/src_processor_minidump_processor_unittest-minidump_processor_unittest.obj `if test -f 'src/processor/minidump_processor_unittest.cc'; then $(CYGPATH_W) 'src/processor/minidump_processor_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/processor/minidump_processor_unittest.cc'; fi`
+
+src/common/src_processor_minidump_unittest-test_assembler.o: src/common/test_assembler.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_minidump_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_processor_minidump_unittest-test_assembler.o -MD -MP -MF src/common/$(DEPDIR)/src_processor_minidump_unittest-test_assembler.Tpo -c -o src/common/src_processor_minidump_unittest-test_assembler.o `test -f 'src/common/test_assembler.cc' || echo '$(srcdir)/'`src/common/test_assembler.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_processor_minidump_unittest-test_assembler.Tpo src/common/$(DEPDIR)/src_processor_minidump_unittest-test_assembler.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/test_assembler.cc' object='src/common/src_processor_minidump_unittest-test_assembler.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_minidump_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_processor_minidump_unittest-test_assembler.o `test -f 'src/common/test_assembler.cc' || echo '$(srcdir)/'`src/common/test_assembler.cc
+
+src/common/src_processor_minidump_unittest-test_assembler.obj: src/common/test_assembler.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_minidump_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_processor_minidump_unittest-test_assembler.obj -MD -MP -MF src/common/$(DEPDIR)/src_processor_minidump_unittest-test_assembler.Tpo -c -o src/common/src_processor_minidump_unittest-test_assembler.obj `if test -f 'src/common/test_assembler.cc'; then $(CYGPATH_W) 'src/common/test_assembler.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/test_assembler.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_processor_minidump_unittest-test_assembler.Tpo src/common/$(DEPDIR)/src_processor_minidump_unittest-test_assembler.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/test_assembler.cc' object='src/common/src_processor_minidump_unittest-test_assembler.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_minidump_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_processor_minidump_unittest-test_assembler.obj `if test -f 'src/common/test_assembler.cc'; then $(CYGPATH_W) 'src/common/test_assembler.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/test_assembler.cc'; fi`
+
+src/processor/src_processor_minidump_unittest-minidump_unittest.o: src/processor/minidump_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_minidump_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/processor/src_processor_minidump_unittest-minidump_unittest.o -MD -MP -MF src/processor/$(DEPDIR)/src_processor_minidump_unittest-minidump_unittest.Tpo -c -o src/processor/src_processor_minidump_unittest-minidump_unittest.o `test -f 'src/processor/minidump_unittest.cc' || echo '$(srcdir)/'`src/processor/minidump_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/processor/$(DEPDIR)/src_processor_minidump_unittest-minidump_unittest.Tpo src/processor/$(DEPDIR)/src_processor_minidump_unittest-minidump_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/processor/minidump_unittest.cc' object='src/processor/src_processor_minidump_unittest-minidump_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_minidump_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/processor/src_processor_minidump_unittest-minidump_unittest.o `test -f 'src/processor/minidump_unittest.cc' || echo '$(srcdir)/'`src/processor/minidump_unittest.cc
+
+src/processor/src_processor_minidump_unittest-minidump_unittest.obj: src/processor/minidump_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_minidump_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/processor/src_processor_minidump_unittest-minidump_unittest.obj -MD -MP -MF src/processor/$(DEPDIR)/src_processor_minidump_unittest-minidump_unittest.Tpo -c -o src/processor/src_processor_minidump_unittest-minidump_unittest.obj `if test -f 'src/processor/minidump_unittest.cc'; then $(CYGPATH_W) 'src/processor/minidump_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/processor/minidump_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/processor/$(DEPDIR)/src_processor_minidump_unittest-minidump_unittest.Tpo src/processor/$(DEPDIR)/src_processor_minidump_unittest-minidump_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/processor/minidump_unittest.cc' object='src/processor/src_processor_minidump_unittest-minidump_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_minidump_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/processor/src_processor_minidump_unittest-minidump_unittest.obj `if test -f 'src/processor/minidump_unittest.cc'; then $(CYGPATH_W) 'src/processor/minidump_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/processor/minidump_unittest.cc'; fi`
+
+src/processor/src_processor_minidump_unittest-synth_minidump.o: src/processor/synth_minidump.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_minidump_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/processor/src_processor_minidump_unittest-synth_minidump.o -MD -MP -MF src/processor/$(DEPDIR)/src_processor_minidump_unittest-synth_minidump.Tpo -c -o src/processor/src_processor_minidump_unittest-synth_minidump.o `test -f 'src/processor/synth_minidump.cc' || echo '$(srcdir)/'`src/processor/synth_minidump.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/processor/$(DEPDIR)/src_processor_minidump_unittest-synth_minidump.Tpo src/processor/$(DEPDIR)/src_processor_minidump_unittest-synth_minidump.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/processor/synth_minidump.cc' object='src/processor/src_processor_minidump_unittest-synth_minidump.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_minidump_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/processor/src_processor_minidump_unittest-synth_minidump.o `test -f 'src/processor/synth_minidump.cc' || echo '$(srcdir)/'`src/processor/synth_minidump.cc
+
+src/processor/src_processor_minidump_unittest-synth_minidump.obj: src/processor/synth_minidump.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_minidump_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/processor/src_processor_minidump_unittest-synth_minidump.obj -MD -MP -MF src/processor/$(DEPDIR)/src_processor_minidump_unittest-synth_minidump.Tpo -c -o src/processor/src_processor_minidump_unittest-synth_minidump.obj `if test -f 'src/processor/synth_minidump.cc'; then $(CYGPATH_W) 'src/processor/synth_minidump.cc'; else $(CYGPATH_W) '$(srcdir)/src/processor/synth_minidump.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/processor/$(DEPDIR)/src_processor_minidump_unittest-synth_minidump.Tpo src/processor/$(DEPDIR)/src_processor_minidump_unittest-synth_minidump.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/processor/synth_minidump.cc' object='src/processor/src_processor_minidump_unittest-synth_minidump.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_minidump_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/processor/src_processor_minidump_unittest-synth_minidump.obj `if test -f 'src/processor/synth_minidump.cc'; then $(CYGPATH_W) 'src/processor/synth_minidump.cc'; else $(CYGPATH_W) '$(srcdir)/src/processor/synth_minidump.cc'; fi`
+
+src/processor/src_processor_proc_maps_linux_unittest-proc_maps_linux.o: src/processor/proc_maps_linux.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_proc_maps_linux_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/processor/src_processor_proc_maps_linux_unittest-proc_maps_linux.o -MD -MP -MF src/processor/$(DEPDIR)/src_processor_proc_maps_linux_unittest-proc_maps_linux.Tpo -c -o src/processor/src_processor_proc_maps_linux_unittest-proc_maps_linux.o `test -f 'src/processor/proc_maps_linux.cc' || echo '$(srcdir)/'`src/processor/proc_maps_linux.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/processor/$(DEPDIR)/src_processor_proc_maps_linux_unittest-proc_maps_linux.Tpo src/processor/$(DEPDIR)/src_processor_proc_maps_linux_unittest-proc_maps_linux.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/processor/proc_maps_linux.cc' object='src/processor/src_processor_proc_maps_linux_unittest-proc_maps_linux.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_proc_maps_linux_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/processor/src_processor_proc_maps_linux_unittest-proc_maps_linux.o `test -f 'src/processor/proc_maps_linux.cc' || echo '$(srcdir)/'`src/processor/proc_maps_linux.cc
+
+src/processor/src_processor_proc_maps_linux_unittest-proc_maps_linux.obj: src/processor/proc_maps_linux.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_proc_maps_linux_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/processor/src_processor_proc_maps_linux_unittest-proc_maps_linux.obj -MD -MP -MF src/processor/$(DEPDIR)/src_processor_proc_maps_linux_unittest-proc_maps_linux.Tpo -c -o src/processor/src_processor_proc_maps_linux_unittest-proc_maps_linux.obj `if test -f 'src/processor/proc_maps_linux.cc'; then $(CYGPATH_W) 'src/processor/proc_maps_linux.cc'; else $(CYGPATH_W) '$(srcdir)/src/processor/proc_maps_linux.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/processor/$(DEPDIR)/src_processor_proc_maps_linux_unittest-proc_maps_linux.Tpo src/processor/$(DEPDIR)/src_processor_proc_maps_linux_unittest-proc_maps_linux.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/processor/proc_maps_linux.cc' object='src/processor/src_processor_proc_maps_linux_unittest-proc_maps_linux.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_proc_maps_linux_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/processor/src_processor_proc_maps_linux_unittest-proc_maps_linux.obj `if test -f 'src/processor/proc_maps_linux.cc'; then $(CYGPATH_W) 'src/processor/proc_maps_linux.cc'; else $(CYGPATH_W) '$(srcdir)/src/processor/proc_maps_linux.cc'; fi`
+
+src/processor/src_processor_proc_maps_linux_unittest-proc_maps_linux_unittest.o: src/processor/proc_maps_linux_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_proc_maps_linux_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/processor/src_processor_proc_maps_linux_unittest-proc_maps_linux_unittest.o -MD -MP -MF src/processor/$(DEPDIR)/src_processor_proc_maps_linux_unittest-proc_maps_linux_unittest.Tpo -c -o src/processor/src_processor_proc_maps_linux_unittest-proc_maps_linux_unittest.o `test -f 'src/processor/proc_maps_linux_unittest.cc' || echo '$(srcdir)/'`src/processor/proc_maps_linux_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/processor/$(DEPDIR)/src_processor_proc_maps_linux_unittest-proc_maps_linux_unittest.Tpo src/processor/$(DEPDIR)/src_processor_proc_maps_linux_unittest-proc_maps_linux_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/processor/proc_maps_linux_unittest.cc' object='src/processor/src_processor_proc_maps_linux_unittest-proc_maps_linux_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_proc_maps_linux_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/processor/src_processor_proc_maps_linux_unittest-proc_maps_linux_unittest.o `test -f 'src/processor/proc_maps_linux_unittest.cc' || echo '$(srcdir)/'`src/processor/proc_maps_linux_unittest.cc
+
+src/processor/src_processor_proc_maps_linux_unittest-proc_maps_linux_unittest.obj: src/processor/proc_maps_linux_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_proc_maps_linux_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/processor/src_processor_proc_maps_linux_unittest-proc_maps_linux_unittest.obj -MD -MP -MF src/processor/$(DEPDIR)/src_processor_proc_maps_linux_unittest-proc_maps_linux_unittest.Tpo -c -o src/processor/src_processor_proc_maps_linux_unittest-proc_maps_linux_unittest.obj `if test -f 'src/processor/proc_maps_linux_unittest.cc'; then $(CYGPATH_W) 'src/processor/proc_maps_linux_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/processor/proc_maps_linux_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/processor/$(DEPDIR)/src_processor_proc_maps_linux_unittest-proc_maps_linux_unittest.Tpo src/processor/$(DEPDIR)/src_processor_proc_maps_linux_unittest-proc_maps_linux_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/processor/proc_maps_linux_unittest.cc' object='src/processor/src_processor_proc_maps_linux_unittest-proc_maps_linux_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_proc_maps_linux_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/processor/src_processor_proc_maps_linux_unittest-proc_maps_linux_unittest.obj `if test -f 'src/processor/proc_maps_linux_unittest.cc'; then $(CYGPATH_W) 'src/processor/proc_maps_linux_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/processor/proc_maps_linux_unittest.cc'; fi`
+
+src/processor/src_processor_range_map_shrink_down_unittest-range_map_shrink_down_unittest.o: src/processor/range_map_shrink_down_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_range_map_shrink_down_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/processor/src_processor_range_map_shrink_down_unittest-range_map_shrink_down_unittest.o -MD -MP -MF src/processor/$(DEPDIR)/src_processor_range_map_shrink_down_unittest-range_map_shrink_down_unittest.Tpo -c -o src/processor/src_processor_range_map_shrink_down_unittest-range_map_shrink_down_unittest.o `test -f 'src/processor/range_map_shrink_down_unittest.cc' || echo '$(srcdir)/'`src/processor/range_map_shrink_down_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/processor/$(DEPDIR)/src_processor_range_map_shrink_down_unittest-range_map_shrink_down_unittest.Tpo src/processor/$(DEPDIR)/src_processor_range_map_shrink_down_unittest-range_map_shrink_down_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/processor/range_map_shrink_down_unittest.cc' object='src/processor/src_processor_range_map_shrink_down_unittest-range_map_shrink_down_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_range_map_shrink_down_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/processor/src_processor_range_map_shrink_down_unittest-range_map_shrink_down_unittest.o `test -f 'src/processor/range_map_shrink_down_unittest.cc' || echo '$(srcdir)/'`src/processor/range_map_shrink_down_unittest.cc
+
+src/processor/src_processor_range_map_shrink_down_unittest-range_map_shrink_down_unittest.obj: src/processor/range_map_shrink_down_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_range_map_shrink_down_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/processor/src_processor_range_map_shrink_down_unittest-range_map_shrink_down_unittest.obj -MD -MP -MF src/processor/$(DEPDIR)/src_processor_range_map_shrink_down_unittest-range_map_shrink_down_unittest.Tpo -c -o src/processor/src_processor_range_map_shrink_down_unittest-range_map_shrink_down_unittest.obj `if test -f 'src/processor/range_map_shrink_down_unittest.cc'; then $(CYGPATH_W) 'src/processor/range_map_shrink_down_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/processor/range_map_shrink_down_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/processor/$(DEPDIR)/src_processor_range_map_shrink_down_unittest-range_map_shrink_down_unittest.Tpo src/processor/$(DEPDIR)/src_processor_range_map_shrink_down_unittest-range_map_shrink_down_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/processor/range_map_shrink_down_unittest.cc' object='src/processor/src_processor_range_map_shrink_down_unittest-range_map_shrink_down_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_range_map_shrink_down_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/processor/src_processor_range_map_shrink_down_unittest-range_map_shrink_down_unittest.obj `if test -f 'src/processor/range_map_shrink_down_unittest.cc'; then $(CYGPATH_W) 'src/processor/range_map_shrink_down_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/processor/range_map_shrink_down_unittest.cc'; fi`
+
+src/common/src_processor_stackwalker_address_list_unittest-test_assembler.o: src/common/test_assembler.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_stackwalker_address_list_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_processor_stackwalker_address_list_unittest-test_assembler.o -MD -MP -MF src/common/$(DEPDIR)/src_processor_stackwalker_address_list_unittest-test_assembler.Tpo -c -o src/common/src_processor_stackwalker_address_list_unittest-test_assembler.o `test -f 'src/common/test_assembler.cc' || echo '$(srcdir)/'`src/common/test_assembler.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_processor_stackwalker_address_list_unittest-test_assembler.Tpo src/common/$(DEPDIR)/src_processor_stackwalker_address_list_unittest-test_assembler.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/test_assembler.cc' object='src/common/src_processor_stackwalker_address_list_unittest-test_assembler.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_stackwalker_address_list_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_processor_stackwalker_address_list_unittest-test_assembler.o `test -f 'src/common/test_assembler.cc' || echo '$(srcdir)/'`src/common/test_assembler.cc
+
+src/common/src_processor_stackwalker_address_list_unittest-test_assembler.obj: src/common/test_assembler.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_stackwalker_address_list_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_processor_stackwalker_address_list_unittest-test_assembler.obj -MD -MP -MF src/common/$(DEPDIR)/src_processor_stackwalker_address_list_unittest-test_assembler.Tpo -c -o src/common/src_processor_stackwalker_address_list_unittest-test_assembler.obj `if test -f 'src/common/test_assembler.cc'; then $(CYGPATH_W) 'src/common/test_assembler.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/test_assembler.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_processor_stackwalker_address_list_unittest-test_assembler.Tpo src/common/$(DEPDIR)/src_processor_stackwalker_address_list_unittest-test_assembler.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/test_assembler.cc' object='src/common/src_processor_stackwalker_address_list_unittest-test_assembler.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_stackwalker_address_list_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_processor_stackwalker_address_list_unittest-test_assembler.obj `if test -f 'src/common/test_assembler.cc'; then $(CYGPATH_W) 'src/common/test_assembler.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/test_assembler.cc'; fi`
+
+src/processor/src_processor_stackwalker_address_list_unittest-stackwalker_address_list_unittest.o: src/processor/stackwalker_address_list_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_stackwalker_address_list_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/processor/src_processor_stackwalker_address_list_unittest-stackwalker_address_list_unittest.o -MD -MP -MF src/processor/$(DEPDIR)/src_processor_stackwalker_address_list_unittest-stackwalker_address_list_unittest.Tpo -c -o src/processor/src_processor_stackwalker_address_list_unittest-stackwalker_address_list_unittest.o `test -f 'src/processor/stackwalker_address_list_unittest.cc' || echo '$(srcdir)/'`src/processor/stackwalker_address_list_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/processor/$(DEPDIR)/src_processor_stackwalker_address_list_unittest-stackwalker_address_list_unittest.Tpo src/processor/$(DEPDIR)/src_processor_stackwalker_address_list_unittest-stackwalker_address_list_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/processor/stackwalker_address_list_unittest.cc' object='src/processor/src_processor_stackwalker_address_list_unittest-stackwalker_address_list_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_stackwalker_address_list_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/processor/src_processor_stackwalker_address_list_unittest-stackwalker_address_list_unittest.o `test -f 'src/processor/stackwalker_address_list_unittest.cc' || echo '$(srcdir)/'`src/processor/stackwalker_address_list_unittest.cc
+
+src/processor/src_processor_stackwalker_address_list_unittest-stackwalker_address_list_unittest.obj: src/processor/stackwalker_address_list_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_stackwalker_address_list_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/processor/src_processor_stackwalker_address_list_unittest-stackwalker_address_list_unittest.obj -MD -MP -MF src/processor/$(DEPDIR)/src_processor_stackwalker_address_list_unittest-stackwalker_address_list_unittest.Tpo -c -o src/processor/src_processor_stackwalker_address_list_unittest-stackwalker_address_list_unittest.obj `if test -f 'src/processor/stackwalker_address_list_unittest.cc'; then $(CYGPATH_W) 'src/processor/stackwalker_address_list_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/processor/stackwalker_address_list_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/processor/$(DEPDIR)/src_processor_stackwalker_address_list_unittest-stackwalker_address_list_unittest.Tpo src/processor/$(DEPDIR)/src_processor_stackwalker_address_list_unittest-stackwalker_address_list_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/processor/stackwalker_address_list_unittest.cc' object='src/processor/src_processor_stackwalker_address_list_unittest-stackwalker_address_list_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_stackwalker_address_list_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/processor/src_processor_stackwalker_address_list_unittest-stackwalker_address_list_unittest.obj `if test -f 'src/processor/stackwalker_address_list_unittest.cc'; then $(CYGPATH_W) 'src/processor/stackwalker_address_list_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/processor/stackwalker_address_list_unittest.cc'; fi`
+
+src/common/src_processor_stackwalker_amd64_unittest-test_assembler.o: src/common/test_assembler.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_stackwalker_amd64_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_processor_stackwalker_amd64_unittest-test_assembler.o -MD -MP -MF src/common/$(DEPDIR)/src_processor_stackwalker_amd64_unittest-test_assembler.Tpo -c -o src/common/src_processor_stackwalker_amd64_unittest-test_assembler.o `test -f 'src/common/test_assembler.cc' || echo '$(srcdir)/'`src/common/test_assembler.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_processor_stackwalker_amd64_unittest-test_assembler.Tpo src/common/$(DEPDIR)/src_processor_stackwalker_amd64_unittest-test_assembler.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/test_assembler.cc' object='src/common/src_processor_stackwalker_amd64_unittest-test_assembler.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_stackwalker_amd64_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_processor_stackwalker_amd64_unittest-test_assembler.o `test -f 'src/common/test_assembler.cc' || echo '$(srcdir)/'`src/common/test_assembler.cc
+
+src/common/src_processor_stackwalker_amd64_unittest-test_assembler.obj: src/common/test_assembler.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_stackwalker_amd64_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_processor_stackwalker_amd64_unittest-test_assembler.obj -MD -MP -MF src/common/$(DEPDIR)/src_processor_stackwalker_amd64_unittest-test_assembler.Tpo -c -o src/common/src_processor_stackwalker_amd64_unittest-test_assembler.obj `if test -f 'src/common/test_assembler.cc'; then $(CYGPATH_W) 'src/common/test_assembler.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/test_assembler.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_processor_stackwalker_amd64_unittest-test_assembler.Tpo src/common/$(DEPDIR)/src_processor_stackwalker_amd64_unittest-test_assembler.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/test_assembler.cc' object='src/common/src_processor_stackwalker_amd64_unittest-test_assembler.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_stackwalker_amd64_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_processor_stackwalker_amd64_unittest-test_assembler.obj `if test -f 'src/common/test_assembler.cc'; then $(CYGPATH_W) 'src/common/test_assembler.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/test_assembler.cc'; fi`
+
+src/processor/src_processor_stackwalker_amd64_unittest-stackwalker_amd64_unittest.o: src/processor/stackwalker_amd64_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_stackwalker_amd64_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/processor/src_processor_stackwalker_amd64_unittest-stackwalker_amd64_unittest.o -MD -MP -MF src/processor/$(DEPDIR)/src_processor_stackwalker_amd64_unittest-stackwalker_amd64_unittest.Tpo -c -o src/processor/src_processor_stackwalker_amd64_unittest-stackwalker_amd64_unittest.o `test -f 'src/processor/stackwalker_amd64_unittest.cc' || echo '$(srcdir)/'`src/processor/stackwalker_amd64_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/processor/$(DEPDIR)/src_processor_stackwalker_amd64_unittest-stackwalker_amd64_unittest.Tpo src/processor/$(DEPDIR)/src_processor_stackwalker_amd64_unittest-stackwalker_amd64_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/processor/stackwalker_amd64_unittest.cc' object='src/processor/src_processor_stackwalker_amd64_unittest-stackwalker_amd64_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_stackwalker_amd64_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/processor/src_processor_stackwalker_amd64_unittest-stackwalker_amd64_unittest.o `test -f 'src/processor/stackwalker_amd64_unittest.cc' || echo '$(srcdir)/'`src/processor/stackwalker_amd64_unittest.cc
+
+src/processor/src_processor_stackwalker_amd64_unittest-stackwalker_amd64_unittest.obj: src/processor/stackwalker_amd64_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_stackwalker_amd64_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/processor/src_processor_stackwalker_amd64_unittest-stackwalker_amd64_unittest.obj -MD -MP -MF src/processor/$(DEPDIR)/src_processor_stackwalker_amd64_unittest-stackwalker_amd64_unittest.Tpo -c -o src/processor/src_processor_stackwalker_amd64_unittest-stackwalker_amd64_unittest.obj `if test -f 'src/processor/stackwalker_amd64_unittest.cc'; then $(CYGPATH_W) 'src/processor/stackwalker_amd64_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/processor/stackwalker_amd64_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/processor/$(DEPDIR)/src_processor_stackwalker_amd64_unittest-stackwalker_amd64_unittest.Tpo src/processor/$(DEPDIR)/src_processor_stackwalker_amd64_unittest-stackwalker_amd64_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/processor/stackwalker_amd64_unittest.cc' object='src/processor/src_processor_stackwalker_amd64_unittest-stackwalker_amd64_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_stackwalker_amd64_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/processor/src_processor_stackwalker_amd64_unittest-stackwalker_amd64_unittest.obj `if test -f 'src/processor/stackwalker_amd64_unittest.cc'; then $(CYGPATH_W) 'src/processor/stackwalker_amd64_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/processor/stackwalker_amd64_unittest.cc'; fi`
+
+src/common/src_processor_stackwalker_arm64_unittest-test_assembler.o: src/common/test_assembler.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_stackwalker_arm64_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_processor_stackwalker_arm64_unittest-test_assembler.o -MD -MP -MF src/common/$(DEPDIR)/src_processor_stackwalker_arm64_unittest-test_assembler.Tpo -c -o src/common/src_processor_stackwalker_arm64_unittest-test_assembler.o `test -f 'src/common/test_assembler.cc' || echo '$(srcdir)/'`src/common/test_assembler.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_processor_stackwalker_arm64_unittest-test_assembler.Tpo src/common/$(DEPDIR)/src_processor_stackwalker_arm64_unittest-test_assembler.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/test_assembler.cc' object='src/common/src_processor_stackwalker_arm64_unittest-test_assembler.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_stackwalker_arm64_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_processor_stackwalker_arm64_unittest-test_assembler.o `test -f 'src/common/test_assembler.cc' || echo '$(srcdir)/'`src/common/test_assembler.cc
+
+src/common/src_processor_stackwalker_arm64_unittest-test_assembler.obj: src/common/test_assembler.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_stackwalker_arm64_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_processor_stackwalker_arm64_unittest-test_assembler.obj -MD -MP -MF src/common/$(DEPDIR)/src_processor_stackwalker_arm64_unittest-test_assembler.Tpo -c -o src/common/src_processor_stackwalker_arm64_unittest-test_assembler.obj `if test -f 'src/common/test_assembler.cc'; then $(CYGPATH_W) 'src/common/test_assembler.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/test_assembler.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_processor_stackwalker_arm64_unittest-test_assembler.Tpo src/common/$(DEPDIR)/src_processor_stackwalker_arm64_unittest-test_assembler.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/test_assembler.cc' object='src/common/src_processor_stackwalker_arm64_unittest-test_assembler.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_stackwalker_arm64_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_processor_stackwalker_arm64_unittest-test_assembler.obj `if test -f 'src/common/test_assembler.cc'; then $(CYGPATH_W) 'src/common/test_assembler.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/test_assembler.cc'; fi`
+
+src/processor/src_processor_stackwalker_arm64_unittest-stackwalker_arm64_unittest.o: src/processor/stackwalker_arm64_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_stackwalker_arm64_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/processor/src_processor_stackwalker_arm64_unittest-stackwalker_arm64_unittest.o -MD -MP -MF src/processor/$(DEPDIR)/src_processor_stackwalker_arm64_unittest-stackwalker_arm64_unittest.Tpo -c -o src/processor/src_processor_stackwalker_arm64_unittest-stackwalker_arm64_unittest.o `test -f 'src/processor/stackwalker_arm64_unittest.cc' || echo '$(srcdir)/'`src/processor/stackwalker_arm64_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/processor/$(DEPDIR)/src_processor_stackwalker_arm64_unittest-stackwalker_arm64_unittest.Tpo src/processor/$(DEPDIR)/src_processor_stackwalker_arm64_unittest-stackwalker_arm64_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/processor/stackwalker_arm64_unittest.cc' object='src/processor/src_processor_stackwalker_arm64_unittest-stackwalker_arm64_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_stackwalker_arm64_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/processor/src_processor_stackwalker_arm64_unittest-stackwalker_arm64_unittest.o `test -f 'src/processor/stackwalker_arm64_unittest.cc' || echo '$(srcdir)/'`src/processor/stackwalker_arm64_unittest.cc
+
+src/processor/src_processor_stackwalker_arm64_unittest-stackwalker_arm64_unittest.obj: src/processor/stackwalker_arm64_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_stackwalker_arm64_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/processor/src_processor_stackwalker_arm64_unittest-stackwalker_arm64_unittest.obj -MD -MP -MF src/processor/$(DEPDIR)/src_processor_stackwalker_arm64_unittest-stackwalker_arm64_unittest.Tpo -c -o src/processor/src_processor_stackwalker_arm64_unittest-stackwalker_arm64_unittest.obj `if test -f 'src/processor/stackwalker_arm64_unittest.cc'; then $(CYGPATH_W) 'src/processor/stackwalker_arm64_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/processor/stackwalker_arm64_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/processor/$(DEPDIR)/src_processor_stackwalker_arm64_unittest-stackwalker_arm64_unittest.Tpo src/processor/$(DEPDIR)/src_processor_stackwalker_arm64_unittest-stackwalker_arm64_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/processor/stackwalker_arm64_unittest.cc' object='src/processor/src_processor_stackwalker_arm64_unittest-stackwalker_arm64_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_stackwalker_arm64_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/processor/src_processor_stackwalker_arm64_unittest-stackwalker_arm64_unittest.obj `if test -f 'src/processor/stackwalker_arm64_unittest.cc'; then $(CYGPATH_W) 'src/processor/stackwalker_arm64_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/processor/stackwalker_arm64_unittest.cc'; fi`
+
+src/common/src_processor_stackwalker_arm_unittest-test_assembler.o: src/common/test_assembler.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_stackwalker_arm_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_processor_stackwalker_arm_unittest-test_assembler.o -MD -MP -MF src/common/$(DEPDIR)/src_processor_stackwalker_arm_unittest-test_assembler.Tpo -c -o src/common/src_processor_stackwalker_arm_unittest-test_assembler.o `test -f 'src/common/test_assembler.cc' || echo '$(srcdir)/'`src/common/test_assembler.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_processor_stackwalker_arm_unittest-test_assembler.Tpo src/common/$(DEPDIR)/src_processor_stackwalker_arm_unittest-test_assembler.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/test_assembler.cc' object='src/common/src_processor_stackwalker_arm_unittest-test_assembler.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_stackwalker_arm_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_processor_stackwalker_arm_unittest-test_assembler.o `test -f 'src/common/test_assembler.cc' || echo '$(srcdir)/'`src/common/test_assembler.cc
+
+src/common/src_processor_stackwalker_arm_unittest-test_assembler.obj: src/common/test_assembler.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_stackwalker_arm_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_processor_stackwalker_arm_unittest-test_assembler.obj -MD -MP -MF src/common/$(DEPDIR)/src_processor_stackwalker_arm_unittest-test_assembler.Tpo -c -o src/common/src_processor_stackwalker_arm_unittest-test_assembler.obj `if test -f 'src/common/test_assembler.cc'; then $(CYGPATH_W) 'src/common/test_assembler.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/test_assembler.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_processor_stackwalker_arm_unittest-test_assembler.Tpo src/common/$(DEPDIR)/src_processor_stackwalker_arm_unittest-test_assembler.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/test_assembler.cc' object='src/common/src_processor_stackwalker_arm_unittest-test_assembler.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_stackwalker_arm_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_processor_stackwalker_arm_unittest-test_assembler.obj `if test -f 'src/common/test_assembler.cc'; then $(CYGPATH_W) 'src/common/test_assembler.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/test_assembler.cc'; fi`
+
+src/processor/src_processor_stackwalker_arm_unittest-stackwalker_arm_unittest.o: src/processor/stackwalker_arm_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_stackwalker_arm_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/processor/src_processor_stackwalker_arm_unittest-stackwalker_arm_unittest.o -MD -MP -MF src/processor/$(DEPDIR)/src_processor_stackwalker_arm_unittest-stackwalker_arm_unittest.Tpo -c -o src/processor/src_processor_stackwalker_arm_unittest-stackwalker_arm_unittest.o `test -f 'src/processor/stackwalker_arm_unittest.cc' || echo '$(srcdir)/'`src/processor/stackwalker_arm_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/processor/$(DEPDIR)/src_processor_stackwalker_arm_unittest-stackwalker_arm_unittest.Tpo src/processor/$(DEPDIR)/src_processor_stackwalker_arm_unittest-stackwalker_arm_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/processor/stackwalker_arm_unittest.cc' object='src/processor/src_processor_stackwalker_arm_unittest-stackwalker_arm_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_stackwalker_arm_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/processor/src_processor_stackwalker_arm_unittest-stackwalker_arm_unittest.o `test -f 'src/processor/stackwalker_arm_unittest.cc' || echo '$(srcdir)/'`src/processor/stackwalker_arm_unittest.cc
+
+src/processor/src_processor_stackwalker_arm_unittest-stackwalker_arm_unittest.obj: src/processor/stackwalker_arm_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_stackwalker_arm_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/processor/src_processor_stackwalker_arm_unittest-stackwalker_arm_unittest.obj -MD -MP -MF src/processor/$(DEPDIR)/src_processor_stackwalker_arm_unittest-stackwalker_arm_unittest.Tpo -c -o src/processor/src_processor_stackwalker_arm_unittest-stackwalker_arm_unittest.obj `if test -f 'src/processor/stackwalker_arm_unittest.cc'; then $(CYGPATH_W) 'src/processor/stackwalker_arm_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/processor/stackwalker_arm_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/processor/$(DEPDIR)/src_processor_stackwalker_arm_unittest-stackwalker_arm_unittest.Tpo src/processor/$(DEPDIR)/src_processor_stackwalker_arm_unittest-stackwalker_arm_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/processor/stackwalker_arm_unittest.cc' object='src/processor/src_processor_stackwalker_arm_unittest-stackwalker_arm_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_stackwalker_arm_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/processor/src_processor_stackwalker_arm_unittest-stackwalker_arm_unittest.obj `if test -f 'src/processor/stackwalker_arm_unittest.cc'; then $(CYGPATH_W) 'src/processor/stackwalker_arm_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/processor/stackwalker_arm_unittest.cc'; fi`
+
+src/common/src_processor_stackwalker_mips64_unittest-test_assembler.o: src/common/test_assembler.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_stackwalker_mips64_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_processor_stackwalker_mips64_unittest-test_assembler.o -MD -MP -MF src/common/$(DEPDIR)/src_processor_stackwalker_mips64_unittest-test_assembler.Tpo -c -o src/common/src_processor_stackwalker_mips64_unittest-test_assembler.o `test -f 'src/common/test_assembler.cc' || echo '$(srcdir)/'`src/common/test_assembler.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_processor_stackwalker_mips64_unittest-test_assembler.Tpo src/common/$(DEPDIR)/src_processor_stackwalker_mips64_unittest-test_assembler.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/test_assembler.cc' object='src/common/src_processor_stackwalker_mips64_unittest-test_assembler.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_stackwalker_mips64_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_processor_stackwalker_mips64_unittest-test_assembler.o `test -f 'src/common/test_assembler.cc' || echo '$(srcdir)/'`src/common/test_assembler.cc
+
+src/common/src_processor_stackwalker_mips64_unittest-test_assembler.obj: src/common/test_assembler.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_stackwalker_mips64_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_processor_stackwalker_mips64_unittest-test_assembler.obj -MD -MP -MF src/common/$(DEPDIR)/src_processor_stackwalker_mips64_unittest-test_assembler.Tpo -c -o src/common/src_processor_stackwalker_mips64_unittest-test_assembler.obj `if test -f 'src/common/test_assembler.cc'; then $(CYGPATH_W) 'src/common/test_assembler.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/test_assembler.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_processor_stackwalker_mips64_unittest-test_assembler.Tpo src/common/$(DEPDIR)/src_processor_stackwalker_mips64_unittest-test_assembler.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/test_assembler.cc' object='src/common/src_processor_stackwalker_mips64_unittest-test_assembler.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_stackwalker_mips64_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_processor_stackwalker_mips64_unittest-test_assembler.obj `if test -f 'src/common/test_assembler.cc'; then $(CYGPATH_W) 'src/common/test_assembler.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/test_assembler.cc'; fi`
+
+src/processor/src_processor_stackwalker_mips64_unittest-stackwalker_mips64_unittest.o: src/processor/stackwalker_mips64_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_stackwalker_mips64_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/processor/src_processor_stackwalker_mips64_unittest-stackwalker_mips64_unittest.o -MD -MP -MF src/processor/$(DEPDIR)/src_processor_stackwalker_mips64_unittest-stackwalker_mips64_unittest.Tpo -c -o src/processor/src_processor_stackwalker_mips64_unittest-stackwalker_mips64_unittest.o `test -f 'src/processor/stackwalker_mips64_unittest.cc' || echo '$(srcdir)/'`src/processor/stackwalker_mips64_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/processor/$(DEPDIR)/src_processor_stackwalker_mips64_unittest-stackwalker_mips64_unittest.Tpo src/processor/$(DEPDIR)/src_processor_stackwalker_mips64_unittest-stackwalker_mips64_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/processor/stackwalker_mips64_unittest.cc' object='src/processor/src_processor_stackwalker_mips64_unittest-stackwalker_mips64_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_stackwalker_mips64_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/processor/src_processor_stackwalker_mips64_unittest-stackwalker_mips64_unittest.o `test -f 'src/processor/stackwalker_mips64_unittest.cc' || echo '$(srcdir)/'`src/processor/stackwalker_mips64_unittest.cc
+
+src/processor/src_processor_stackwalker_mips64_unittest-stackwalker_mips64_unittest.obj: src/processor/stackwalker_mips64_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_stackwalker_mips64_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/processor/src_processor_stackwalker_mips64_unittest-stackwalker_mips64_unittest.obj -MD -MP -MF src/processor/$(DEPDIR)/src_processor_stackwalker_mips64_unittest-stackwalker_mips64_unittest.Tpo -c -o src/processor/src_processor_stackwalker_mips64_unittest-stackwalker_mips64_unittest.obj `if test -f 'src/processor/stackwalker_mips64_unittest.cc'; then $(CYGPATH_W) 'src/processor/stackwalker_mips64_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/processor/stackwalker_mips64_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/processor/$(DEPDIR)/src_processor_stackwalker_mips64_unittest-stackwalker_mips64_unittest.Tpo src/processor/$(DEPDIR)/src_processor_stackwalker_mips64_unittest-stackwalker_mips64_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/processor/stackwalker_mips64_unittest.cc' object='src/processor/src_processor_stackwalker_mips64_unittest-stackwalker_mips64_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_stackwalker_mips64_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/processor/src_processor_stackwalker_mips64_unittest-stackwalker_mips64_unittest.obj `if test -f 'src/processor/stackwalker_mips64_unittest.cc'; then $(CYGPATH_W) 'src/processor/stackwalker_mips64_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/processor/stackwalker_mips64_unittest.cc'; fi`
+
+src/common/src_processor_stackwalker_mips_unittest-test_assembler.o: src/common/test_assembler.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_stackwalker_mips_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_processor_stackwalker_mips_unittest-test_assembler.o -MD -MP -MF src/common/$(DEPDIR)/src_processor_stackwalker_mips_unittest-test_assembler.Tpo -c -o src/common/src_processor_stackwalker_mips_unittest-test_assembler.o `test -f 'src/common/test_assembler.cc' || echo '$(srcdir)/'`src/common/test_assembler.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_processor_stackwalker_mips_unittest-test_assembler.Tpo src/common/$(DEPDIR)/src_processor_stackwalker_mips_unittest-test_assembler.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/test_assembler.cc' object='src/common/src_processor_stackwalker_mips_unittest-test_assembler.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_stackwalker_mips_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_processor_stackwalker_mips_unittest-test_assembler.o `test -f 'src/common/test_assembler.cc' || echo '$(srcdir)/'`src/common/test_assembler.cc
+
+src/common/src_processor_stackwalker_mips_unittest-test_assembler.obj: src/common/test_assembler.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_stackwalker_mips_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_processor_stackwalker_mips_unittest-test_assembler.obj -MD -MP -MF src/common/$(DEPDIR)/src_processor_stackwalker_mips_unittest-test_assembler.Tpo -c -o src/common/src_processor_stackwalker_mips_unittest-test_assembler.obj `if test -f 'src/common/test_assembler.cc'; then $(CYGPATH_W) 'src/common/test_assembler.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/test_assembler.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_processor_stackwalker_mips_unittest-test_assembler.Tpo src/common/$(DEPDIR)/src_processor_stackwalker_mips_unittest-test_assembler.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/test_assembler.cc' object='src/common/src_processor_stackwalker_mips_unittest-test_assembler.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_stackwalker_mips_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_processor_stackwalker_mips_unittest-test_assembler.obj `if test -f 'src/common/test_assembler.cc'; then $(CYGPATH_W) 'src/common/test_assembler.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/test_assembler.cc'; fi`
+
+src/processor/src_processor_stackwalker_mips_unittest-stackwalker_mips_unittest.o: src/processor/stackwalker_mips_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_stackwalker_mips_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/processor/src_processor_stackwalker_mips_unittest-stackwalker_mips_unittest.o -MD -MP -MF src/processor/$(DEPDIR)/src_processor_stackwalker_mips_unittest-stackwalker_mips_unittest.Tpo -c -o src/processor/src_processor_stackwalker_mips_unittest-stackwalker_mips_unittest.o `test -f 'src/processor/stackwalker_mips_unittest.cc' || echo '$(srcdir)/'`src/processor/stackwalker_mips_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/processor/$(DEPDIR)/src_processor_stackwalker_mips_unittest-stackwalker_mips_unittest.Tpo src/processor/$(DEPDIR)/src_processor_stackwalker_mips_unittest-stackwalker_mips_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/processor/stackwalker_mips_unittest.cc' object='src/processor/src_processor_stackwalker_mips_unittest-stackwalker_mips_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_stackwalker_mips_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/processor/src_processor_stackwalker_mips_unittest-stackwalker_mips_unittest.o `test -f 'src/processor/stackwalker_mips_unittest.cc' || echo '$(srcdir)/'`src/processor/stackwalker_mips_unittest.cc
+
+src/processor/src_processor_stackwalker_mips_unittest-stackwalker_mips_unittest.obj: src/processor/stackwalker_mips_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_stackwalker_mips_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/processor/src_processor_stackwalker_mips_unittest-stackwalker_mips_unittest.obj -MD -MP -MF src/processor/$(DEPDIR)/src_processor_stackwalker_mips_unittest-stackwalker_mips_unittest.Tpo -c -o src/processor/src_processor_stackwalker_mips_unittest-stackwalker_mips_unittest.obj `if test -f 'src/processor/stackwalker_mips_unittest.cc'; then $(CYGPATH_W) 'src/processor/stackwalker_mips_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/processor/stackwalker_mips_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/processor/$(DEPDIR)/src_processor_stackwalker_mips_unittest-stackwalker_mips_unittest.Tpo src/processor/$(DEPDIR)/src_processor_stackwalker_mips_unittest-stackwalker_mips_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/processor/stackwalker_mips_unittest.cc' object='src/processor/src_processor_stackwalker_mips_unittest-stackwalker_mips_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_stackwalker_mips_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/processor/src_processor_stackwalker_mips_unittest-stackwalker_mips_unittest.obj `if test -f 'src/processor/stackwalker_mips_unittest.cc'; then $(CYGPATH_W) 'src/processor/stackwalker_mips_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/processor/stackwalker_mips_unittest.cc'; fi`
+
+src/common/src_processor_stackwalker_x86_unittest-test_assembler.o: src/common/test_assembler.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_stackwalker_x86_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_processor_stackwalker_x86_unittest-test_assembler.o -MD -MP -MF src/common/$(DEPDIR)/src_processor_stackwalker_x86_unittest-test_assembler.Tpo -c -o src/common/src_processor_stackwalker_x86_unittest-test_assembler.o `test -f 'src/common/test_assembler.cc' || echo '$(srcdir)/'`src/common/test_assembler.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_processor_stackwalker_x86_unittest-test_assembler.Tpo src/common/$(DEPDIR)/src_processor_stackwalker_x86_unittest-test_assembler.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/test_assembler.cc' object='src/common/src_processor_stackwalker_x86_unittest-test_assembler.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_stackwalker_x86_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_processor_stackwalker_x86_unittest-test_assembler.o `test -f 'src/common/test_assembler.cc' || echo '$(srcdir)/'`src/common/test_assembler.cc
+
+src/common/src_processor_stackwalker_x86_unittest-test_assembler.obj: src/common/test_assembler.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_stackwalker_x86_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_processor_stackwalker_x86_unittest-test_assembler.obj -MD -MP -MF src/common/$(DEPDIR)/src_processor_stackwalker_x86_unittest-test_assembler.Tpo -c -o src/common/src_processor_stackwalker_x86_unittest-test_assembler.obj `if test -f 'src/common/test_assembler.cc'; then $(CYGPATH_W) 'src/common/test_assembler.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/test_assembler.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_processor_stackwalker_x86_unittest-test_assembler.Tpo src/common/$(DEPDIR)/src_processor_stackwalker_x86_unittest-test_assembler.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/test_assembler.cc' object='src/common/src_processor_stackwalker_x86_unittest-test_assembler.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_stackwalker_x86_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_processor_stackwalker_x86_unittest-test_assembler.obj `if test -f 'src/common/test_assembler.cc'; then $(CYGPATH_W) 'src/common/test_assembler.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/test_assembler.cc'; fi`
+
+src/processor/src_processor_stackwalker_x86_unittest-stackwalker_x86_unittest.o: src/processor/stackwalker_x86_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_stackwalker_x86_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/processor/src_processor_stackwalker_x86_unittest-stackwalker_x86_unittest.o -MD -MP -MF src/processor/$(DEPDIR)/src_processor_stackwalker_x86_unittest-stackwalker_x86_unittest.Tpo -c -o src/processor/src_processor_stackwalker_x86_unittest-stackwalker_x86_unittest.o `test -f 'src/processor/stackwalker_x86_unittest.cc' || echo '$(srcdir)/'`src/processor/stackwalker_x86_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/processor/$(DEPDIR)/src_processor_stackwalker_x86_unittest-stackwalker_x86_unittest.Tpo src/processor/$(DEPDIR)/src_processor_stackwalker_x86_unittest-stackwalker_x86_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/processor/stackwalker_x86_unittest.cc' object='src/processor/src_processor_stackwalker_x86_unittest-stackwalker_x86_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_stackwalker_x86_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/processor/src_processor_stackwalker_x86_unittest-stackwalker_x86_unittest.o `test -f 'src/processor/stackwalker_x86_unittest.cc' || echo '$(srcdir)/'`src/processor/stackwalker_x86_unittest.cc
+
+src/processor/src_processor_stackwalker_x86_unittest-stackwalker_x86_unittest.obj: src/processor/stackwalker_x86_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_stackwalker_x86_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/processor/src_processor_stackwalker_x86_unittest-stackwalker_x86_unittest.obj -MD -MP -MF src/processor/$(DEPDIR)/src_processor_stackwalker_x86_unittest-stackwalker_x86_unittest.Tpo -c -o src/processor/src_processor_stackwalker_x86_unittest-stackwalker_x86_unittest.obj `if test -f 'src/processor/stackwalker_x86_unittest.cc'; then $(CYGPATH_W) 'src/processor/stackwalker_x86_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/processor/stackwalker_x86_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/processor/$(DEPDIR)/src_processor_stackwalker_x86_unittest-stackwalker_x86_unittest.Tpo src/processor/$(DEPDIR)/src_processor_stackwalker_x86_unittest-stackwalker_x86_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/processor/stackwalker_x86_unittest.cc' object='src/processor/src_processor_stackwalker_x86_unittest-stackwalker_x86_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_stackwalker_x86_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/processor/src_processor_stackwalker_x86_unittest-stackwalker_x86_unittest.obj `if test -f 'src/processor/stackwalker_x86_unittest.cc'; then $(CYGPATH_W) 'src/processor/stackwalker_x86_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/processor/stackwalker_x86_unittest.cc'; fi`
+
+src/processor/src_processor_static_address_map_unittest-static_address_map_unittest.o: src/processor/static_address_map_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_static_address_map_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/processor/src_processor_static_address_map_unittest-static_address_map_unittest.o -MD -MP -MF src/processor/$(DEPDIR)/src_processor_static_address_map_unittest-static_address_map_unittest.Tpo -c -o src/processor/src_processor_static_address_map_unittest-static_address_map_unittest.o `test -f 'src/processor/static_address_map_unittest.cc' || echo '$(srcdir)/'`src/processor/static_address_map_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/processor/$(DEPDIR)/src_processor_static_address_map_unittest-static_address_map_unittest.Tpo src/processor/$(DEPDIR)/src_processor_static_address_map_unittest-static_address_map_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/processor/static_address_map_unittest.cc' object='src/processor/src_processor_static_address_map_unittest-static_address_map_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_static_address_map_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/processor/src_processor_static_address_map_unittest-static_address_map_unittest.o `test -f 'src/processor/static_address_map_unittest.cc' || echo '$(srcdir)/'`src/processor/static_address_map_unittest.cc
+
+src/processor/src_processor_static_address_map_unittest-static_address_map_unittest.obj: src/processor/static_address_map_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_static_address_map_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/processor/src_processor_static_address_map_unittest-static_address_map_unittest.obj -MD -MP -MF src/processor/$(DEPDIR)/src_processor_static_address_map_unittest-static_address_map_unittest.Tpo -c -o src/processor/src_processor_static_address_map_unittest-static_address_map_unittest.obj `if test -f 'src/processor/static_address_map_unittest.cc'; then $(CYGPATH_W) 'src/processor/static_address_map_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/processor/static_address_map_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/processor/$(DEPDIR)/src_processor_static_address_map_unittest-static_address_map_unittest.Tpo src/processor/$(DEPDIR)/src_processor_static_address_map_unittest-static_address_map_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/processor/static_address_map_unittest.cc' object='src/processor/src_processor_static_address_map_unittest-static_address_map_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_static_address_map_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/processor/src_processor_static_address_map_unittest-static_address_map_unittest.obj `if test -f 'src/processor/static_address_map_unittest.cc'; then $(CYGPATH_W) 'src/processor/static_address_map_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/processor/static_address_map_unittest.cc'; fi`
+
+src/processor/src_processor_static_contained_range_map_unittest-static_contained_range_map_unittest.o: src/processor/static_contained_range_map_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_static_contained_range_map_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/processor/src_processor_static_contained_range_map_unittest-static_contained_range_map_unittest.o -MD -MP -MF src/processor/$(DEPDIR)/src_processor_static_contained_range_map_unittest-static_contained_range_map_unittest.Tpo -c -o src/processor/src_processor_static_contained_range_map_unittest-static_contained_range_map_unittest.o `test -f 'src/processor/static_contained_range_map_unittest.cc' || echo '$(srcdir)/'`src/processor/static_contained_range_map_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/processor/$(DEPDIR)/src_processor_static_contained_range_map_unittest-static_contained_range_map_unittest.Tpo src/processor/$(DEPDIR)/src_processor_static_contained_range_map_unittest-static_contained_range_map_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/processor/static_contained_range_map_unittest.cc' object='src/processor/src_processor_static_contained_range_map_unittest-static_contained_range_map_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_static_contained_range_map_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/processor/src_processor_static_contained_range_map_unittest-static_contained_range_map_unittest.o `test -f 'src/processor/static_contained_range_map_unittest.cc' || echo '$(srcdir)/'`src/processor/static_contained_range_map_unittest.cc
+
+src/processor/src_processor_static_contained_range_map_unittest-static_contained_range_map_unittest.obj: src/processor/static_contained_range_map_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_static_contained_range_map_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/processor/src_processor_static_contained_range_map_unittest-static_contained_range_map_unittest.obj -MD -MP -MF src/processor/$(DEPDIR)/src_processor_static_contained_range_map_unittest-static_contained_range_map_unittest.Tpo -c -o src/processor/src_processor_static_contained_range_map_unittest-static_contained_range_map_unittest.obj `if test -f 'src/processor/static_contained_range_map_unittest.cc'; then $(CYGPATH_W) 'src/processor/static_contained_range_map_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/processor/static_contained_range_map_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/processor/$(DEPDIR)/src_processor_static_contained_range_map_unittest-static_contained_range_map_unittest.Tpo src/processor/$(DEPDIR)/src_processor_static_contained_range_map_unittest-static_contained_range_map_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/processor/static_contained_range_map_unittest.cc' object='src/processor/src_processor_static_contained_range_map_unittest-static_contained_range_map_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_static_contained_range_map_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/processor/src_processor_static_contained_range_map_unittest-static_contained_range_map_unittest.obj `if test -f 'src/processor/static_contained_range_map_unittest.cc'; then $(CYGPATH_W) 'src/processor/static_contained_range_map_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/processor/static_contained_range_map_unittest.cc'; fi`
+
+src/processor/src_processor_static_map_unittest-static_map_unittest.o: src/processor/static_map_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_static_map_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/processor/src_processor_static_map_unittest-static_map_unittest.o -MD -MP -MF src/processor/$(DEPDIR)/src_processor_static_map_unittest-static_map_unittest.Tpo -c -o src/processor/src_processor_static_map_unittest-static_map_unittest.o `test -f 'src/processor/static_map_unittest.cc' || echo '$(srcdir)/'`src/processor/static_map_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/processor/$(DEPDIR)/src_processor_static_map_unittest-static_map_unittest.Tpo src/processor/$(DEPDIR)/src_processor_static_map_unittest-static_map_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/processor/static_map_unittest.cc' object='src/processor/src_processor_static_map_unittest-static_map_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_static_map_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/processor/src_processor_static_map_unittest-static_map_unittest.o `test -f 'src/processor/static_map_unittest.cc' || echo '$(srcdir)/'`src/processor/static_map_unittest.cc
+
+src/processor/src_processor_static_map_unittest-static_map_unittest.obj: src/processor/static_map_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_static_map_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/processor/src_processor_static_map_unittest-static_map_unittest.obj -MD -MP -MF src/processor/$(DEPDIR)/src_processor_static_map_unittest-static_map_unittest.Tpo -c -o src/processor/src_processor_static_map_unittest-static_map_unittest.obj `if test -f 'src/processor/static_map_unittest.cc'; then $(CYGPATH_W) 'src/processor/static_map_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/processor/static_map_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/processor/$(DEPDIR)/src_processor_static_map_unittest-static_map_unittest.Tpo src/processor/$(DEPDIR)/src_processor_static_map_unittest-static_map_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/processor/static_map_unittest.cc' object='src/processor/src_processor_static_map_unittest-static_map_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_static_map_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/processor/src_processor_static_map_unittest-static_map_unittest.obj `if test -f 'src/processor/static_map_unittest.cc'; then $(CYGPATH_W) 'src/processor/static_map_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/processor/static_map_unittest.cc'; fi`
+
+src/processor/src_processor_static_range_map_unittest-static_range_map_unittest.o: src/processor/static_range_map_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_static_range_map_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/processor/src_processor_static_range_map_unittest-static_range_map_unittest.o -MD -MP -MF src/processor/$(DEPDIR)/src_processor_static_range_map_unittest-static_range_map_unittest.Tpo -c -o src/processor/src_processor_static_range_map_unittest-static_range_map_unittest.o `test -f 'src/processor/static_range_map_unittest.cc' || echo '$(srcdir)/'`src/processor/static_range_map_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/processor/$(DEPDIR)/src_processor_static_range_map_unittest-static_range_map_unittest.Tpo src/processor/$(DEPDIR)/src_processor_static_range_map_unittest-static_range_map_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/processor/static_range_map_unittest.cc' object='src/processor/src_processor_static_range_map_unittest-static_range_map_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_static_range_map_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/processor/src_processor_static_range_map_unittest-static_range_map_unittest.o `test -f 'src/processor/static_range_map_unittest.cc' || echo '$(srcdir)/'`src/processor/static_range_map_unittest.cc
+
+src/processor/src_processor_static_range_map_unittest-static_range_map_unittest.obj: src/processor/static_range_map_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_static_range_map_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/processor/src_processor_static_range_map_unittest-static_range_map_unittest.obj -MD -MP -MF src/processor/$(DEPDIR)/src_processor_static_range_map_unittest-static_range_map_unittest.Tpo -c -o src/processor/src_processor_static_range_map_unittest-static_range_map_unittest.obj `if test -f 'src/processor/static_range_map_unittest.cc'; then $(CYGPATH_W) 'src/processor/static_range_map_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/processor/static_range_map_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/processor/$(DEPDIR)/src_processor_static_range_map_unittest-static_range_map_unittest.Tpo src/processor/$(DEPDIR)/src_processor_static_range_map_unittest-static_range_map_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/processor/static_range_map_unittest.cc' object='src/processor/src_processor_static_range_map_unittest-static_range_map_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_static_range_map_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/processor/src_processor_static_range_map_unittest-static_range_map_unittest.obj `if test -f 'src/processor/static_range_map_unittest.cc'; then $(CYGPATH_W) 'src/processor/static_range_map_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/processor/static_range_map_unittest.cc'; fi`
+
+src/common/src_processor_synth_minidump_unittest-test_assembler.o: src/common/test_assembler.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_synth_minidump_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_processor_synth_minidump_unittest-test_assembler.o -MD -MP -MF src/common/$(DEPDIR)/src_processor_synth_minidump_unittest-test_assembler.Tpo -c -o src/common/src_processor_synth_minidump_unittest-test_assembler.o `test -f 'src/common/test_assembler.cc' || echo '$(srcdir)/'`src/common/test_assembler.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_processor_synth_minidump_unittest-test_assembler.Tpo src/common/$(DEPDIR)/src_processor_synth_minidump_unittest-test_assembler.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/test_assembler.cc' object='src/common/src_processor_synth_minidump_unittest-test_assembler.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_synth_minidump_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_processor_synth_minidump_unittest-test_assembler.o `test -f 'src/common/test_assembler.cc' || echo '$(srcdir)/'`src/common/test_assembler.cc
+
+src/common/src_processor_synth_minidump_unittest-test_assembler.obj: src/common/test_assembler.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_synth_minidump_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_processor_synth_minidump_unittest-test_assembler.obj -MD -MP -MF src/common/$(DEPDIR)/src_processor_synth_minidump_unittest-test_assembler.Tpo -c -o src/common/src_processor_synth_minidump_unittest-test_assembler.obj `if test -f 'src/common/test_assembler.cc'; then $(CYGPATH_W) 'src/common/test_assembler.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/test_assembler.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_processor_synth_minidump_unittest-test_assembler.Tpo src/common/$(DEPDIR)/src_processor_synth_minidump_unittest-test_assembler.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/test_assembler.cc' object='src/common/src_processor_synth_minidump_unittest-test_assembler.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_synth_minidump_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_processor_synth_minidump_unittest-test_assembler.obj `if test -f 'src/common/test_assembler.cc'; then $(CYGPATH_W) 'src/common/test_assembler.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/test_assembler.cc'; fi`
+
+src/processor/src_processor_synth_minidump_unittest-synth_minidump_unittest.o: src/processor/synth_minidump_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_synth_minidump_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/processor/src_processor_synth_minidump_unittest-synth_minidump_unittest.o -MD -MP -MF src/processor/$(DEPDIR)/src_processor_synth_minidump_unittest-synth_minidump_unittest.Tpo -c -o src/processor/src_processor_synth_minidump_unittest-synth_minidump_unittest.o `test -f 'src/processor/synth_minidump_unittest.cc' || echo '$(srcdir)/'`src/processor/synth_minidump_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/processor/$(DEPDIR)/src_processor_synth_minidump_unittest-synth_minidump_unittest.Tpo src/processor/$(DEPDIR)/src_processor_synth_minidump_unittest-synth_minidump_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/processor/synth_minidump_unittest.cc' object='src/processor/src_processor_synth_minidump_unittest-synth_minidump_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_synth_minidump_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/processor/src_processor_synth_minidump_unittest-synth_minidump_unittest.o `test -f 'src/processor/synth_minidump_unittest.cc' || echo '$(srcdir)/'`src/processor/synth_minidump_unittest.cc
+
+src/processor/src_processor_synth_minidump_unittest-synth_minidump_unittest.obj: src/processor/synth_minidump_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_synth_minidump_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/processor/src_processor_synth_minidump_unittest-synth_minidump_unittest.obj -MD -MP -MF src/processor/$(DEPDIR)/src_processor_synth_minidump_unittest-synth_minidump_unittest.Tpo -c -o src/processor/src_processor_synth_minidump_unittest-synth_minidump_unittest.obj `if test -f 'src/processor/synth_minidump_unittest.cc'; then $(CYGPATH_W) 'src/processor/synth_minidump_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/processor/synth_minidump_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/processor/$(DEPDIR)/src_processor_synth_minidump_unittest-synth_minidump_unittest.Tpo src/processor/$(DEPDIR)/src_processor_synth_minidump_unittest-synth_minidump_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/processor/synth_minidump_unittest.cc' object='src/processor/src_processor_synth_minidump_unittest-synth_minidump_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_synth_minidump_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/processor/src_processor_synth_minidump_unittest-synth_minidump_unittest.obj `if test -f 'src/processor/synth_minidump_unittest.cc'; then $(CYGPATH_W) 'src/processor/synth_minidump_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/processor/synth_minidump_unittest.cc'; fi`
+
+src/processor/src_processor_synth_minidump_unittest-synth_minidump.o: src/processor/synth_minidump.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_synth_minidump_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/processor/src_processor_synth_minidump_unittest-synth_minidump.o -MD -MP -MF src/processor/$(DEPDIR)/src_processor_synth_minidump_unittest-synth_minidump.Tpo -c -o src/processor/src_processor_synth_minidump_unittest-synth_minidump.o `test -f 'src/processor/synth_minidump.cc' || echo '$(srcdir)/'`src/processor/synth_minidump.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/processor/$(DEPDIR)/src_processor_synth_minidump_unittest-synth_minidump.Tpo src/processor/$(DEPDIR)/src_processor_synth_minidump_unittest-synth_minidump.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/processor/synth_minidump.cc' object='src/processor/src_processor_synth_minidump_unittest-synth_minidump.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_synth_minidump_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/processor/src_processor_synth_minidump_unittest-synth_minidump.o `test -f 'src/processor/synth_minidump.cc' || echo '$(srcdir)/'`src/processor/synth_minidump.cc
+
+src/processor/src_processor_synth_minidump_unittest-synth_minidump.obj: src/processor/synth_minidump.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_synth_minidump_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/processor/src_processor_synth_minidump_unittest-synth_minidump.obj -MD -MP -MF src/processor/$(DEPDIR)/src_processor_synth_minidump_unittest-synth_minidump.Tpo -c -o src/processor/src_processor_synth_minidump_unittest-synth_minidump.obj `if test -f 'src/processor/synth_minidump.cc'; then $(CYGPATH_W) 'src/processor/synth_minidump.cc'; else $(CYGPATH_W) '$(srcdir)/src/processor/synth_minidump.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/processor/$(DEPDIR)/src_processor_synth_minidump_unittest-synth_minidump.Tpo src/processor/$(DEPDIR)/src_processor_synth_minidump_unittest-synth_minidump.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/processor/synth_minidump.cc' object='src/processor/src_processor_synth_minidump_unittest-synth_minidump.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_synth_minidump_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/processor/src_processor_synth_minidump_unittest-synth_minidump.obj `if test -f 'src/processor/synth_minidump.cc'; then $(CYGPATH_W) 'src/processor/synth_minidump.cc'; else $(CYGPATH_W) '$(srcdir)/src/processor/synth_minidump.cc'; fi`
+
+src/tools/linux/md2core/src_tools_linux_md2core_minidump_2_core_unittest-minidump_memory_range_unittest.o: src/tools/linux/md2core/minidump_memory_range_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_tools_linux_md2core_minidump_2_core_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/tools/linux/md2core/src_tools_linux_md2core_minidump_2_core_unittest-minidump_memory_range_unittest.o -MD -MP -MF src/tools/linux/md2core/$(DEPDIR)/src_tools_linux_md2core_minidump_2_core_unittest-minidump_memory_range_unittest.Tpo -c -o src/tools/linux/md2core/src_tools_linux_md2core_minidump_2_core_unittest-minidump_memory_range_unittest.o `test -f 'src/tools/linux/md2core/minidump_memory_range_unittest.cc' || echo '$(srcdir)/'`src/tools/linux/md2core/minidump_memory_range_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tools/linux/md2core/$(DEPDIR)/src_tools_linux_md2core_minidump_2_core_unittest-minidump_memory_range_unittest.Tpo src/tools/linux/md2core/$(DEPDIR)/src_tools_linux_md2core_minidump_2_core_unittest-minidump_memory_range_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tools/linux/md2core/minidump_memory_range_unittest.cc' object='src/tools/linux/md2core/src_tools_linux_md2core_minidump_2_core_unittest-minidump_memory_range_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_tools_linux_md2core_minidump_2_core_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/tools/linux/md2core/src_tools_linux_md2core_minidump_2_core_unittest-minidump_memory_range_unittest.o `test -f 'src/tools/linux/md2core/minidump_memory_range_unittest.cc' || echo '$(srcdir)/'`src/tools/linux/md2core/minidump_memory_range_unittest.cc
+
+src/tools/linux/md2core/src_tools_linux_md2core_minidump_2_core_unittest-minidump_memory_range_unittest.obj: src/tools/linux/md2core/minidump_memory_range_unittest.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_tools_linux_md2core_minidump_2_core_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/tools/linux/md2core/src_tools_linux_md2core_minidump_2_core_unittest-minidump_memory_range_unittest.obj -MD -MP -MF src/tools/linux/md2core/$(DEPDIR)/src_tools_linux_md2core_minidump_2_core_unittest-minidump_memory_range_unittest.Tpo -c -o src/tools/linux/md2core/src_tools_linux_md2core_minidump_2_core_unittest-minidump_memory_range_unittest.obj `if test -f 'src/tools/linux/md2core/minidump_memory_range_unittest.cc'; then $(CYGPATH_W) 'src/tools/linux/md2core/minidump_memory_range_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/tools/linux/md2core/minidump_memory_range_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tools/linux/md2core/$(DEPDIR)/src_tools_linux_md2core_minidump_2_core_unittest-minidump_memory_range_unittest.Tpo src/tools/linux/md2core/$(DEPDIR)/src_tools_linux_md2core_minidump_2_core_unittest-minidump_memory_range_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tools/linux/md2core/minidump_memory_range_unittest.cc' object='src/tools/linux/md2core/src_tools_linux_md2core_minidump_2_core_unittest-minidump_memory_range_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_tools_linux_md2core_minidump_2_core_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/tools/linux/md2core/src_tools_linux_md2core_minidump_2_core_unittest-minidump_memory_range_unittest.obj `if test -f 'src/tools/linux/md2core/minidump_memory_range_unittest.cc'; then $(CYGPATH_W) 'src/tools/linux/md2core/minidump_memory_range_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/tools/linux/md2core/minidump_memory_range_unittest.cc'; fi`
+
+src/common/src_tools_mac_dump_syms_dump_syms_mac-dwarf_cfi_to_module.o: src/common/dwarf_cfi_to_module.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_tools_mac_dump_syms_dump_syms_mac-dwarf_cfi_to_module.o -MD -MP -MF src/common/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-dwarf_cfi_to_module.Tpo -c -o src/common/src_tools_mac_dump_syms_dump_syms_mac-dwarf_cfi_to_module.o `test -f 'src/common/dwarf_cfi_to_module.cc' || echo '$(srcdir)/'`src/common/dwarf_cfi_to_module.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-dwarf_cfi_to_module.Tpo src/common/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-dwarf_cfi_to_module.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/dwarf_cfi_to_module.cc' object='src/common/src_tools_mac_dump_syms_dump_syms_mac-dwarf_cfi_to_module.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_tools_mac_dump_syms_dump_syms_mac-dwarf_cfi_to_module.o `test -f 'src/common/dwarf_cfi_to_module.cc' || echo '$(srcdir)/'`src/common/dwarf_cfi_to_module.cc
+
+src/common/src_tools_mac_dump_syms_dump_syms_mac-dwarf_cfi_to_module.obj: src/common/dwarf_cfi_to_module.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_tools_mac_dump_syms_dump_syms_mac-dwarf_cfi_to_module.obj -MD -MP -MF src/common/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-dwarf_cfi_to_module.Tpo -c -o src/common/src_tools_mac_dump_syms_dump_syms_mac-dwarf_cfi_to_module.obj `if test -f 'src/common/dwarf_cfi_to_module.cc'; then $(CYGPATH_W) 'src/common/dwarf_cfi_to_module.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/dwarf_cfi_to_module.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-dwarf_cfi_to_module.Tpo src/common/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-dwarf_cfi_to_module.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/dwarf_cfi_to_module.cc' object='src/common/src_tools_mac_dump_syms_dump_syms_mac-dwarf_cfi_to_module.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_tools_mac_dump_syms_dump_syms_mac-dwarf_cfi_to_module.obj `if test -f 'src/common/dwarf_cfi_to_module.cc'; then $(CYGPATH_W) 'src/common/dwarf_cfi_to_module.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/dwarf_cfi_to_module.cc'; fi`
+
+src/common/src_tools_mac_dump_syms_dump_syms_mac-dwarf_cu_to_module.o: src/common/dwarf_cu_to_module.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_tools_mac_dump_syms_dump_syms_mac-dwarf_cu_to_module.o -MD -MP -MF src/common/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-dwarf_cu_to_module.Tpo -c -o src/common/src_tools_mac_dump_syms_dump_syms_mac-dwarf_cu_to_module.o `test -f 'src/common/dwarf_cu_to_module.cc' || echo '$(srcdir)/'`src/common/dwarf_cu_to_module.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-dwarf_cu_to_module.Tpo src/common/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-dwarf_cu_to_module.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/dwarf_cu_to_module.cc' object='src/common/src_tools_mac_dump_syms_dump_syms_mac-dwarf_cu_to_module.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_tools_mac_dump_syms_dump_syms_mac-dwarf_cu_to_module.o `test -f 'src/common/dwarf_cu_to_module.cc' || echo '$(srcdir)/'`src/common/dwarf_cu_to_module.cc
+
+src/common/src_tools_mac_dump_syms_dump_syms_mac-dwarf_cu_to_module.obj: src/common/dwarf_cu_to_module.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_tools_mac_dump_syms_dump_syms_mac-dwarf_cu_to_module.obj -MD -MP -MF src/common/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-dwarf_cu_to_module.Tpo -c -o src/common/src_tools_mac_dump_syms_dump_syms_mac-dwarf_cu_to_module.obj `if test -f 'src/common/dwarf_cu_to_module.cc'; then $(CYGPATH_W) 'src/common/dwarf_cu_to_module.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/dwarf_cu_to_module.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-dwarf_cu_to_module.Tpo src/common/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-dwarf_cu_to_module.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/dwarf_cu_to_module.cc' object='src/common/src_tools_mac_dump_syms_dump_syms_mac-dwarf_cu_to_module.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_tools_mac_dump_syms_dump_syms_mac-dwarf_cu_to_module.obj `if test -f 'src/common/dwarf_cu_to_module.cc'; then $(CYGPATH_W) 'src/common/dwarf_cu_to_module.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/dwarf_cu_to_module.cc'; fi`
+
+src/common/src_tools_mac_dump_syms_dump_syms_mac-dwarf_line_to_module.o: src/common/dwarf_line_to_module.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_tools_mac_dump_syms_dump_syms_mac-dwarf_line_to_module.o -MD -MP -MF src/common/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-dwarf_line_to_module.Tpo -c -o src/common/src_tools_mac_dump_syms_dump_syms_mac-dwarf_line_to_module.o `test -f 'src/common/dwarf_line_to_module.cc' || echo '$(srcdir)/'`src/common/dwarf_line_to_module.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-dwarf_line_to_module.Tpo src/common/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-dwarf_line_to_module.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/dwarf_line_to_module.cc' object='src/common/src_tools_mac_dump_syms_dump_syms_mac-dwarf_line_to_module.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_tools_mac_dump_syms_dump_syms_mac-dwarf_line_to_module.o `test -f 'src/common/dwarf_line_to_module.cc' || echo '$(srcdir)/'`src/common/dwarf_line_to_module.cc
+
+src/common/src_tools_mac_dump_syms_dump_syms_mac-dwarf_line_to_module.obj: src/common/dwarf_line_to_module.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_tools_mac_dump_syms_dump_syms_mac-dwarf_line_to_module.obj -MD -MP -MF src/common/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-dwarf_line_to_module.Tpo -c -o src/common/src_tools_mac_dump_syms_dump_syms_mac-dwarf_line_to_module.obj `if test -f 'src/common/dwarf_line_to_module.cc'; then $(CYGPATH_W) 'src/common/dwarf_line_to_module.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/dwarf_line_to_module.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-dwarf_line_to_module.Tpo src/common/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-dwarf_line_to_module.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/dwarf_line_to_module.cc' object='src/common/src_tools_mac_dump_syms_dump_syms_mac-dwarf_line_to_module.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_tools_mac_dump_syms_dump_syms_mac-dwarf_line_to_module.obj `if test -f 'src/common/dwarf_line_to_module.cc'; then $(CYGPATH_W) 'src/common/dwarf_line_to_module.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/dwarf_line_to_module.cc'; fi`
+
+src/common/src_tools_mac_dump_syms_dump_syms_mac-language.o: src/common/language.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_tools_mac_dump_syms_dump_syms_mac-language.o -MD -MP -MF src/common/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-language.Tpo -c -o src/common/src_tools_mac_dump_syms_dump_syms_mac-language.o `test -f 'src/common/language.cc' || echo '$(srcdir)/'`src/common/language.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-language.Tpo src/common/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-language.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/language.cc' object='src/common/src_tools_mac_dump_syms_dump_syms_mac-language.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_tools_mac_dump_syms_dump_syms_mac-language.o `test -f 'src/common/language.cc' || echo '$(srcdir)/'`src/common/language.cc
+
+src/common/src_tools_mac_dump_syms_dump_syms_mac-language.obj: src/common/language.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_tools_mac_dump_syms_dump_syms_mac-language.obj -MD -MP -MF src/common/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-language.Tpo -c -o src/common/src_tools_mac_dump_syms_dump_syms_mac-language.obj `if test -f 'src/common/language.cc'; then $(CYGPATH_W) 'src/common/language.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/language.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-language.Tpo src/common/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-language.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/language.cc' object='src/common/src_tools_mac_dump_syms_dump_syms_mac-language.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_tools_mac_dump_syms_dump_syms_mac-language.obj `if test -f 'src/common/language.cc'; then $(CYGPATH_W) 'src/common/language.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/language.cc'; fi`
+
+src/common/src_tools_mac_dump_syms_dump_syms_mac-md5.o: src/common/md5.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_tools_mac_dump_syms_dump_syms_mac-md5.o -MD -MP -MF src/common/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-md5.Tpo -c -o src/common/src_tools_mac_dump_syms_dump_syms_mac-md5.o `test -f 'src/common/md5.cc' || echo '$(srcdir)/'`src/common/md5.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-md5.Tpo src/common/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-md5.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/md5.cc' object='src/common/src_tools_mac_dump_syms_dump_syms_mac-md5.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_tools_mac_dump_syms_dump_syms_mac-md5.o `test -f 'src/common/md5.cc' || echo '$(srcdir)/'`src/common/md5.cc
+
+src/common/src_tools_mac_dump_syms_dump_syms_mac-md5.obj: src/common/md5.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_tools_mac_dump_syms_dump_syms_mac-md5.obj -MD -MP -MF src/common/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-md5.Tpo -c -o src/common/src_tools_mac_dump_syms_dump_syms_mac-md5.obj `if test -f 'src/common/md5.cc'; then $(CYGPATH_W) 'src/common/md5.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/md5.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-md5.Tpo src/common/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-md5.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/md5.cc' object='src/common/src_tools_mac_dump_syms_dump_syms_mac-md5.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_tools_mac_dump_syms_dump_syms_mac-md5.obj `if test -f 'src/common/md5.cc'; then $(CYGPATH_W) 'src/common/md5.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/md5.cc'; fi`
+
+src/common/src_tools_mac_dump_syms_dump_syms_mac-module.o: src/common/module.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_tools_mac_dump_syms_dump_syms_mac-module.o -MD -MP -MF src/common/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-module.Tpo -c -o src/common/src_tools_mac_dump_syms_dump_syms_mac-module.o `test -f 'src/common/module.cc' || echo '$(srcdir)/'`src/common/module.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-module.Tpo src/common/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-module.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/module.cc' object='src/common/src_tools_mac_dump_syms_dump_syms_mac-module.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_tools_mac_dump_syms_dump_syms_mac-module.o `test -f 'src/common/module.cc' || echo '$(srcdir)/'`src/common/module.cc
+
+src/common/src_tools_mac_dump_syms_dump_syms_mac-module.obj: src/common/module.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_tools_mac_dump_syms_dump_syms_mac-module.obj -MD -MP -MF src/common/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-module.Tpo -c -o src/common/src_tools_mac_dump_syms_dump_syms_mac-module.obj `if test -f 'src/common/module.cc'; then $(CYGPATH_W) 'src/common/module.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/module.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-module.Tpo src/common/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-module.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/module.cc' object='src/common/src_tools_mac_dump_syms_dump_syms_mac-module.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_tools_mac_dump_syms_dump_syms_mac-module.obj `if test -f 'src/common/module.cc'; then $(CYGPATH_W) 'src/common/module.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/module.cc'; fi`
+
+src/common/src_tools_mac_dump_syms_dump_syms_mac-stabs_reader.o: src/common/stabs_reader.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_tools_mac_dump_syms_dump_syms_mac-stabs_reader.o -MD -MP -MF src/common/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-stabs_reader.Tpo -c -o src/common/src_tools_mac_dump_syms_dump_syms_mac-stabs_reader.o `test -f 'src/common/stabs_reader.cc' || echo '$(srcdir)/'`src/common/stabs_reader.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-stabs_reader.Tpo src/common/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-stabs_reader.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/stabs_reader.cc' object='src/common/src_tools_mac_dump_syms_dump_syms_mac-stabs_reader.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_tools_mac_dump_syms_dump_syms_mac-stabs_reader.o `test -f 'src/common/stabs_reader.cc' || echo '$(srcdir)/'`src/common/stabs_reader.cc
+
+src/common/src_tools_mac_dump_syms_dump_syms_mac-stabs_reader.obj: src/common/stabs_reader.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_tools_mac_dump_syms_dump_syms_mac-stabs_reader.obj -MD -MP -MF src/common/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-stabs_reader.Tpo -c -o src/common/src_tools_mac_dump_syms_dump_syms_mac-stabs_reader.obj `if test -f 'src/common/stabs_reader.cc'; then $(CYGPATH_W) 'src/common/stabs_reader.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/stabs_reader.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-stabs_reader.Tpo src/common/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-stabs_reader.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/stabs_reader.cc' object='src/common/src_tools_mac_dump_syms_dump_syms_mac-stabs_reader.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_tools_mac_dump_syms_dump_syms_mac-stabs_reader.obj `if test -f 'src/common/stabs_reader.cc'; then $(CYGPATH_W) 'src/common/stabs_reader.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/stabs_reader.cc'; fi`
+
+src/common/src_tools_mac_dump_syms_dump_syms_mac-stabs_to_module.o: src/common/stabs_to_module.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_tools_mac_dump_syms_dump_syms_mac-stabs_to_module.o -MD -MP -MF src/common/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-stabs_to_module.Tpo -c -o src/common/src_tools_mac_dump_syms_dump_syms_mac-stabs_to_module.o `test -f 'src/common/stabs_to_module.cc' || echo '$(srcdir)/'`src/common/stabs_to_module.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-stabs_to_module.Tpo src/common/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-stabs_to_module.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/stabs_to_module.cc' object='src/common/src_tools_mac_dump_syms_dump_syms_mac-stabs_to_module.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_tools_mac_dump_syms_dump_syms_mac-stabs_to_module.o `test -f 'src/common/stabs_to_module.cc' || echo '$(srcdir)/'`src/common/stabs_to_module.cc
+
+src/common/src_tools_mac_dump_syms_dump_syms_mac-stabs_to_module.obj: src/common/stabs_to_module.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_tools_mac_dump_syms_dump_syms_mac-stabs_to_module.obj -MD -MP -MF src/common/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-stabs_to_module.Tpo -c -o src/common/src_tools_mac_dump_syms_dump_syms_mac-stabs_to_module.obj `if test -f 'src/common/stabs_to_module.cc'; then $(CYGPATH_W) 'src/common/stabs_to_module.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/stabs_to_module.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-stabs_to_module.Tpo src/common/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-stabs_to_module.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/stabs_to_module.cc' object='src/common/src_tools_mac_dump_syms_dump_syms_mac-stabs_to_module.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_tools_mac_dump_syms_dump_syms_mac-stabs_to_module.obj `if test -f 'src/common/stabs_to_module.cc'; then $(CYGPATH_W) 'src/common/stabs_to_module.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/stabs_to_module.cc'; fi`
+
+src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-bytereader.o: src/common/dwarf/bytereader.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) -MT src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-bytereader.o -MD -MP -MF src/common/dwarf/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-bytereader.Tpo -c -o src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-bytereader.o `test -f 'src/common/dwarf/bytereader.cc' || echo '$(srcdir)/'`src/common/dwarf/bytereader.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/dwarf/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-bytereader.Tpo src/common/dwarf/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-bytereader.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/dwarf/bytereader.cc' object='src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-bytereader.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) -c -o src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-bytereader.o `test -f 'src/common/dwarf/bytereader.cc' || echo '$(srcdir)/'`src/common/dwarf/bytereader.cc
+
+src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-bytereader.obj: src/common/dwarf/bytereader.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) -MT src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-bytereader.obj -MD -MP -MF src/common/dwarf/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-bytereader.Tpo -c -o src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-bytereader.obj `if test -f 'src/common/dwarf/bytereader.cc'; then $(CYGPATH_W) 'src/common/dwarf/bytereader.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/dwarf/bytereader.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/dwarf/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-bytereader.Tpo src/common/dwarf/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-bytereader.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/dwarf/bytereader.cc' object='src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-bytereader.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) -c -o src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-bytereader.obj `if test -f 'src/common/dwarf/bytereader.cc'; then $(CYGPATH_W) 'src/common/dwarf/bytereader.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/dwarf/bytereader.cc'; fi`
+
+src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-dwarf2diehandler.o: src/common/dwarf/dwarf2diehandler.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) -MT src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-dwarf2diehandler.o -MD -MP -MF src/common/dwarf/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-dwarf2diehandler.Tpo -c -o src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-dwarf2diehandler.o `test -f 'src/common/dwarf/dwarf2diehandler.cc' || echo '$(srcdir)/'`src/common/dwarf/dwarf2diehandler.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/dwarf/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-dwarf2diehandler.Tpo src/common/dwarf/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-dwarf2diehandler.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/dwarf/dwarf2diehandler.cc' object='src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-dwarf2diehandler.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) -c -o src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-dwarf2diehandler.o `test -f 'src/common/dwarf/dwarf2diehandler.cc' || echo '$(srcdir)/'`src/common/dwarf/dwarf2diehandler.cc
+
+src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-dwarf2diehandler.obj: src/common/dwarf/dwarf2diehandler.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) -MT src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-dwarf2diehandler.obj -MD -MP -MF src/common/dwarf/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-dwarf2diehandler.Tpo -c -o src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-dwarf2diehandler.obj `if test -f 'src/common/dwarf/dwarf2diehandler.cc'; then $(CYGPATH_W) 'src/common/dwarf/dwarf2diehandler.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/dwarf/dwarf2diehandler.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/dwarf/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-dwarf2diehandler.Tpo src/common/dwarf/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-dwarf2diehandler.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/dwarf/dwarf2diehandler.cc' object='src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-dwarf2diehandler.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) -c -o src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-dwarf2diehandler.obj `if test -f 'src/common/dwarf/dwarf2diehandler.cc'; then $(CYGPATH_W) 'src/common/dwarf/dwarf2diehandler.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/dwarf/dwarf2diehandler.cc'; fi`
+
+src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-dwarf2reader.o: src/common/dwarf/dwarf2reader.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) -MT src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-dwarf2reader.o -MD -MP -MF src/common/dwarf/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-dwarf2reader.Tpo -c -o src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-dwarf2reader.o `test -f 'src/common/dwarf/dwarf2reader.cc' || echo '$(srcdir)/'`src/common/dwarf/dwarf2reader.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/dwarf/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-dwarf2reader.Tpo src/common/dwarf/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-dwarf2reader.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/dwarf/dwarf2reader.cc' object='src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-dwarf2reader.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) -c -o src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-dwarf2reader.o `test -f 'src/common/dwarf/dwarf2reader.cc' || echo '$(srcdir)/'`src/common/dwarf/dwarf2reader.cc
+
+src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-dwarf2reader.obj: src/common/dwarf/dwarf2reader.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) -MT src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-dwarf2reader.obj -MD -MP -MF src/common/dwarf/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-dwarf2reader.Tpo -c -o src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-dwarf2reader.obj `if test -f 'src/common/dwarf/dwarf2reader.cc'; then $(CYGPATH_W) 'src/common/dwarf/dwarf2reader.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/dwarf/dwarf2reader.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/dwarf/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-dwarf2reader.Tpo src/common/dwarf/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-dwarf2reader.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/dwarf/dwarf2reader.cc' object='src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-dwarf2reader.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) -c -o src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-dwarf2reader.obj `if test -f 'src/common/dwarf/dwarf2reader.cc'; then $(CYGPATH_W) 'src/common/dwarf/dwarf2reader.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/dwarf/dwarf2reader.cc'; fi`
+
+src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-elf_reader.o: src/common/dwarf/elf_reader.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) -MT src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-elf_reader.o -MD -MP -MF src/common/dwarf/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-elf_reader.Tpo -c -o src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-elf_reader.o `test -f 'src/common/dwarf/elf_reader.cc' || echo '$(srcdir)/'`src/common/dwarf/elf_reader.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/dwarf/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-elf_reader.Tpo src/common/dwarf/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-elf_reader.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/dwarf/elf_reader.cc' object='src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-elf_reader.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) -c -o src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-elf_reader.o `test -f 'src/common/dwarf/elf_reader.cc' || echo '$(srcdir)/'`src/common/dwarf/elf_reader.cc
+
+src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-elf_reader.obj: src/common/dwarf/elf_reader.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) -MT src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-elf_reader.obj -MD -MP -MF src/common/dwarf/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-elf_reader.Tpo -c -o src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-elf_reader.obj `if test -f 'src/common/dwarf/elf_reader.cc'; then $(CYGPATH_W) 'src/common/dwarf/elf_reader.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/dwarf/elf_reader.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/dwarf/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-elf_reader.Tpo src/common/dwarf/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-elf_reader.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/dwarf/elf_reader.cc' object='src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-elf_reader.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) -c -o src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-elf_reader.obj `if test -f 'src/common/dwarf/elf_reader.cc'; then $(CYGPATH_W) 'src/common/dwarf/elf_reader.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/dwarf/elf_reader.cc'; fi`
+
+src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-arch_utilities.o: src/common/mac/arch_utilities.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) -MT src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-arch_utilities.o -MD -MP -MF src/common/mac/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-arch_utilities.Tpo -c -o src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-arch_utilities.o `test -f 'src/common/mac/arch_utilities.cc' || echo '$(srcdir)/'`src/common/mac/arch_utilities.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/mac/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-arch_utilities.Tpo src/common/mac/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-arch_utilities.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/mac/arch_utilities.cc' object='src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-arch_utilities.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) -c -o src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-arch_utilities.o `test -f 'src/common/mac/arch_utilities.cc' || echo '$(srcdir)/'`src/common/mac/arch_utilities.cc
+
+src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-arch_utilities.obj: src/common/mac/arch_utilities.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) -MT src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-arch_utilities.obj -MD -MP -MF src/common/mac/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-arch_utilities.Tpo -c -o src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-arch_utilities.obj `if test -f 'src/common/mac/arch_utilities.cc'; then $(CYGPATH_W) 'src/common/mac/arch_utilities.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/mac/arch_utilities.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/mac/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-arch_utilities.Tpo src/common/mac/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-arch_utilities.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/mac/arch_utilities.cc' object='src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-arch_utilities.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) -c -o src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-arch_utilities.obj `if test -f 'src/common/mac/arch_utilities.cc'; then $(CYGPATH_W) 'src/common/mac/arch_utilities.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/mac/arch_utilities.cc'; fi`
+
+src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-dump_syms.o: src/common/mac/dump_syms.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) -MT src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-dump_syms.o -MD -MP -MF src/common/mac/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-dump_syms.Tpo -c -o src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-dump_syms.o `test -f 'src/common/mac/dump_syms.cc' || echo '$(srcdir)/'`src/common/mac/dump_syms.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/mac/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-dump_syms.Tpo src/common/mac/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-dump_syms.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/mac/dump_syms.cc' object='src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-dump_syms.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) -c -o src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-dump_syms.o `test -f 'src/common/mac/dump_syms.cc' || echo '$(srcdir)/'`src/common/mac/dump_syms.cc
+
+src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-dump_syms.obj: src/common/mac/dump_syms.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) -MT src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-dump_syms.obj -MD -MP -MF src/common/mac/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-dump_syms.Tpo -c -o src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-dump_syms.obj `if test -f 'src/common/mac/dump_syms.cc'; then $(CYGPATH_W) 'src/common/mac/dump_syms.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/mac/dump_syms.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/mac/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-dump_syms.Tpo src/common/mac/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-dump_syms.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/mac/dump_syms.cc' object='src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-dump_syms.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) -c -o src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-dump_syms.obj `if test -f 'src/common/mac/dump_syms.cc'; then $(CYGPATH_W) 'src/common/mac/dump_syms.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/mac/dump_syms.cc'; fi`
+
+src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-file_id.o: src/common/mac/file_id.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) -MT src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-file_id.o -MD -MP -MF src/common/mac/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-file_id.Tpo -c -o src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-file_id.o `test -f 'src/common/mac/file_id.cc' || echo '$(srcdir)/'`src/common/mac/file_id.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/mac/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-file_id.Tpo src/common/mac/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-file_id.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/mac/file_id.cc' object='src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-file_id.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) -c -o src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-file_id.o `test -f 'src/common/mac/file_id.cc' || echo '$(srcdir)/'`src/common/mac/file_id.cc
+
+src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-file_id.obj: src/common/mac/file_id.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) -MT src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-file_id.obj -MD -MP -MF src/common/mac/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-file_id.Tpo -c -o src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-file_id.obj `if test -f 'src/common/mac/file_id.cc'; then $(CYGPATH_W) 'src/common/mac/file_id.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/mac/file_id.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/mac/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-file_id.Tpo src/common/mac/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-file_id.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/mac/file_id.cc' object='src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-file_id.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) -c -o src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-file_id.obj `if test -f 'src/common/mac/file_id.cc'; then $(CYGPATH_W) 'src/common/mac/file_id.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/mac/file_id.cc'; fi`
+
+src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-macho_id.o: src/common/mac/macho_id.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) -MT src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-macho_id.o -MD -MP -MF src/common/mac/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-macho_id.Tpo -c -o src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-macho_id.o `test -f 'src/common/mac/macho_id.cc' || echo '$(srcdir)/'`src/common/mac/macho_id.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/mac/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-macho_id.Tpo src/common/mac/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-macho_id.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/mac/macho_id.cc' object='src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-macho_id.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) -c -o src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-macho_id.o `test -f 'src/common/mac/macho_id.cc' || echo '$(srcdir)/'`src/common/mac/macho_id.cc
+
+src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-macho_id.obj: src/common/mac/macho_id.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) -MT src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-macho_id.obj -MD -MP -MF src/common/mac/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-macho_id.Tpo -c -o src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-macho_id.obj `if test -f 'src/common/mac/macho_id.cc'; then $(CYGPATH_W) 'src/common/mac/macho_id.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/mac/macho_id.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/mac/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-macho_id.Tpo src/common/mac/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-macho_id.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/mac/macho_id.cc' object='src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-macho_id.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) -c -o src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-macho_id.obj `if test -f 'src/common/mac/macho_id.cc'; then $(CYGPATH_W) 'src/common/mac/macho_id.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/mac/macho_id.cc'; fi`
+
+src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-macho_reader.o: src/common/mac/macho_reader.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) -MT src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-macho_reader.o -MD -MP -MF src/common/mac/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-macho_reader.Tpo -c -o src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-macho_reader.o `test -f 'src/common/mac/macho_reader.cc' || echo '$(srcdir)/'`src/common/mac/macho_reader.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/mac/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-macho_reader.Tpo src/common/mac/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-macho_reader.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/mac/macho_reader.cc' object='src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-macho_reader.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) -c -o src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-macho_reader.o `test -f 'src/common/mac/macho_reader.cc' || echo '$(srcdir)/'`src/common/mac/macho_reader.cc
+
+src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-macho_reader.obj: src/common/mac/macho_reader.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) -MT src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-macho_reader.obj -MD -MP -MF src/common/mac/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-macho_reader.Tpo -c -o src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-macho_reader.obj `if test -f 'src/common/mac/macho_reader.cc'; then $(CYGPATH_W) 'src/common/mac/macho_reader.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/mac/macho_reader.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/mac/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-macho_reader.Tpo src/common/mac/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-macho_reader.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/mac/macho_reader.cc' object='src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-macho_reader.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) -c -o src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-macho_reader.obj `if test -f 'src/common/mac/macho_reader.cc'; then $(CYGPATH_W) 'src/common/mac/macho_reader.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/mac/macho_reader.cc'; fi`
+
+src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-macho_utilities.o: src/common/mac/macho_utilities.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) -MT src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-macho_utilities.o -MD -MP -MF src/common/mac/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-macho_utilities.Tpo -c -o src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-macho_utilities.o `test -f 'src/common/mac/macho_utilities.cc' || echo '$(srcdir)/'`src/common/mac/macho_utilities.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/mac/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-macho_utilities.Tpo src/common/mac/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-macho_utilities.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/mac/macho_utilities.cc' object='src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-macho_utilities.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) -c -o src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-macho_utilities.o `test -f 'src/common/mac/macho_utilities.cc' || echo '$(srcdir)/'`src/common/mac/macho_utilities.cc
+
+src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-macho_utilities.obj: src/common/mac/macho_utilities.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) -MT src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-macho_utilities.obj -MD -MP -MF src/common/mac/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-macho_utilities.Tpo -c -o src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-macho_utilities.obj `if test -f 'src/common/mac/macho_utilities.cc'; then $(CYGPATH_W) 'src/common/mac/macho_utilities.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/mac/macho_utilities.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/mac/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-macho_utilities.Tpo src/common/mac/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-macho_utilities.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/mac/macho_utilities.cc' object='src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-macho_utilities.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) -c -o src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-macho_utilities.obj `if test -f 'src/common/mac/macho_utilities.cc'; then $(CYGPATH_W) 'src/common/mac/macho_utilities.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/mac/macho_utilities.cc'; fi`
+
+src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-macho_walker.o: src/common/mac/macho_walker.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) -MT src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-macho_walker.o -MD -MP -MF src/common/mac/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-macho_walker.Tpo -c -o src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-macho_walker.o `test -f 'src/common/mac/macho_walker.cc' || echo '$(srcdir)/'`src/common/mac/macho_walker.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/mac/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-macho_walker.Tpo src/common/mac/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-macho_walker.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/mac/macho_walker.cc' object='src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-macho_walker.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) -c -o src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-macho_walker.o `test -f 'src/common/mac/macho_walker.cc' || echo '$(srcdir)/'`src/common/mac/macho_walker.cc
+
+src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-macho_walker.obj: src/common/mac/macho_walker.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) -MT src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-macho_walker.obj -MD -MP -MF src/common/mac/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-macho_walker.Tpo -c -o src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-macho_walker.obj `if test -f 'src/common/mac/macho_walker.cc'; then $(CYGPATH_W) 'src/common/mac/macho_walker.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/mac/macho_walker.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/mac/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-macho_walker.Tpo src/common/mac/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-macho_walker.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/mac/macho_walker.cc' object='src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-macho_walker.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) -c -o src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-macho_walker.obj `if test -f 'src/common/mac/macho_walker.cc'; then $(CYGPATH_W) 'src/common/mac/macho_walker.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/mac/macho_walker.cc'; fi`
+
+src/tools/mac/dump_syms/src_tools_mac_dump_syms_dump_syms_mac-dump_syms_tool.o: src/tools/mac/dump_syms/dump_syms_tool.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) -MT src/tools/mac/dump_syms/src_tools_mac_dump_syms_dump_syms_mac-dump_syms_tool.o -MD -MP -MF src/tools/mac/dump_syms/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-dump_syms_tool.Tpo -c -o src/tools/mac/dump_syms/src_tools_mac_dump_syms_dump_syms_mac-dump_syms_tool.o `test -f 'src/tools/mac/dump_syms/dump_syms_tool.cc' || echo '$(srcdir)/'`src/tools/mac/dump_syms/dump_syms_tool.cc
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tools/mac/dump_syms/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-dump_syms_tool.Tpo src/tools/mac/dump_syms/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-dump_syms_tool.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tools/mac/dump_syms/dump_syms_tool.cc' object='src/tools/mac/dump_syms/src_tools_mac_dump_syms_dump_syms_mac-dump_syms_tool.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) -c -o src/tools/mac/dump_syms/src_tools_mac_dump_syms_dump_syms_mac-dump_syms_tool.o `test -f 'src/tools/mac/dump_syms/dump_syms_tool.cc' || echo '$(srcdir)/'`src/tools/mac/dump_syms/dump_syms_tool.cc
+
+src/tools/mac/dump_syms/src_tools_mac_dump_syms_dump_syms_mac-dump_syms_tool.obj: src/tools/mac/dump_syms/dump_syms_tool.cc
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) -MT src/tools/mac/dump_syms/src_tools_mac_dump_syms_dump_syms_mac-dump_syms_tool.obj -MD -MP -MF src/tools/mac/dump_syms/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-dump_syms_tool.Tpo -c -o src/tools/mac/dump_syms/src_tools_mac_dump_syms_dump_syms_mac-dump_syms_tool.obj `if test -f 'src/tools/mac/dump_syms/dump_syms_tool.cc'; then $(CYGPATH_W) 'src/tools/mac/dump_syms/dump_syms_tool.cc'; else $(CYGPATH_W) '$(srcdir)/src/tools/mac/dump_syms/dump_syms_tool.cc'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/tools/mac/dump_syms/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-dump_syms_tool.Tpo src/tools/mac/dump_syms/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-dump_syms_tool.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/tools/mac/dump_syms/dump_syms_tool.cc' object='src/tools/mac/dump_syms/src_tools_mac_dump_syms_dump_syms_mac-dump_syms_tool.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) -c -o src/tools/mac/dump_syms/src_tools_mac_dump_syms_dump_syms_mac-dump_syms_tool.obj `if test -f 'src/tools/mac/dump_syms/dump_syms_tool.cc'; then $(CYGPATH_W) 'src/tools/mac/dump_syms/dump_syms_tool.cc'; else $(CYGPATH_W) '$(srcdir)/src/tools/mac/dump_syms/dump_syms_tool.cc'; fi`
+install-dist_docDATA: $(dist_doc_DATA)
+ @$(NORMAL_INSTALL)
+ @list='$(dist_doc_DATA)'; test -n "$(docdir)" || list=; \
+ if test -n "$$list"; then \
+ echo " $(MKDIR_P) '$(DESTDIR)$(docdir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(docdir)" || exit 1; \
+ fi; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(docdir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(docdir)" || exit $$?; \
+ done
+
+uninstall-dist_docDATA:
+ @$(NORMAL_UNINSTALL)
+ @list='$(dist_doc_DATA)'; test -n "$(docdir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ dir='$(DESTDIR)$(docdir)'; $(am__uninstall_files_from_dir)
+install-pkgconfigDATA: $(pkgconfig_DATA)
+ @$(NORMAL_INSTALL)
+ @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \
+ if test -n "$$list"; then \
+ echo " $(MKDIR_P) '$(DESTDIR)$(pkgconfigdir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(pkgconfigdir)" || exit 1; \
+ fi; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgconfigdir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgconfigdir)" || exit $$?; \
+ done
+
+uninstall-pkgconfigDATA:
+ @$(NORMAL_UNINSTALL)
+ @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ dir='$(DESTDIR)$(pkgconfigdir)'; $(am__uninstall_files_from_dir)
+install-includecHEADERS: $(includec_HEADERS)
+ @$(NORMAL_INSTALL)
+ @list='$(includec_HEADERS)'; test -n "$(includecdir)" || list=; \
+ if test -n "$$list"; then \
+ echo " $(MKDIR_P) '$(DESTDIR)$(includecdir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(includecdir)" || exit 1; \
+ fi; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(includecdir)'"; \
+ $(INSTALL_HEADER) $$files "$(DESTDIR)$(includecdir)" || exit $$?; \
+ done
+
+uninstall-includecHEADERS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(includec_HEADERS)'; test -n "$(includecdir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ dir='$(DESTDIR)$(includecdir)'; $(am__uninstall_files_from_dir)
+install-includeclHEADERS: $(includecl_HEADERS)
+ @$(NORMAL_INSTALL)
+ @list='$(includecl_HEADERS)'; test -n "$(includecldir)" || list=; \
+ if test -n "$$list"; then \
+ echo " $(MKDIR_P) '$(DESTDIR)$(includecldir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(includecldir)" || exit 1; \
+ fi; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(includecldir)'"; \
+ $(INSTALL_HEADER) $$files "$(DESTDIR)$(includecldir)" || exit $$?; \
+ done
+
+uninstall-includeclHEADERS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(includecl_HEADERS)'; test -n "$(includecldir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ dir='$(DESTDIR)$(includecldir)'; $(am__uninstall_files_from_dir)
+install-includeclcHEADERS: $(includeclc_HEADERS)
+ @$(NORMAL_INSTALL)
+ @list='$(includeclc_HEADERS)'; test -n "$(includeclcdir)" || list=; \
+ if test -n "$$list"; then \
+ echo " $(MKDIR_P) '$(DESTDIR)$(includeclcdir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(includeclcdir)" || exit 1; \
+ fi; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(includeclcdir)'"; \
+ $(INSTALL_HEADER) $$files "$(DESTDIR)$(includeclcdir)" || exit $$?; \
+ done
+
+uninstall-includeclcHEADERS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(includeclc_HEADERS)'; test -n "$(includeclcdir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ dir='$(DESTDIR)$(includeclcdir)'; $(am__uninstall_files_from_dir)
+install-includecldwcHEADERS: $(includecldwc_HEADERS)
+ @$(NORMAL_INSTALL)
+ @list='$(includecldwc_HEADERS)'; test -n "$(includecldwcdir)" || list=; \
+ if test -n "$$list"; then \
+ echo " $(MKDIR_P) '$(DESTDIR)$(includecldwcdir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(includecldwcdir)" || exit 1; \
+ fi; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(includecldwcdir)'"; \
+ $(INSTALL_HEADER) $$files "$(DESTDIR)$(includecldwcdir)" || exit $$?; \
+ done
+
+uninstall-includecldwcHEADERS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(includecldwc_HEADERS)'; test -n "$(includecldwcdir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ dir='$(DESTDIR)$(includecldwcdir)'; $(am__uninstall_files_from_dir)
+install-includeclhHEADERS: $(includeclh_HEADERS)
+ @$(NORMAL_INSTALL)
+ @list='$(includeclh_HEADERS)'; test -n "$(includeclhdir)" || list=; \
+ if test -n "$$list"; then \
+ echo " $(MKDIR_P) '$(DESTDIR)$(includeclhdir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(includeclhdir)" || exit 1; \
+ fi; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(includeclhdir)'"; \
+ $(INSTALL_HEADER) $$files "$(DESTDIR)$(includeclhdir)" || exit $$?; \
+ done
+
+uninstall-includeclhHEADERS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(includeclh_HEADERS)'; test -n "$(includeclhdir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ dir='$(DESTDIR)$(includeclhdir)'; $(am__uninstall_files_from_dir)
+install-includeclmHEADERS: $(includeclm_HEADERS)
+ @$(NORMAL_INSTALL)
+ @list='$(includeclm_HEADERS)'; test -n "$(includeclmdir)" || list=; \
+ if test -n "$$list"; then \
+ echo " $(MKDIR_P) '$(DESTDIR)$(includeclmdir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(includeclmdir)" || exit 1; \
+ fi; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(includeclmdir)'"; \
+ $(INSTALL_HEADER) $$files "$(DESTDIR)$(includeclmdir)" || exit $$?; \
+ done
+
+uninstall-includeclmHEADERS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(includeclm_HEADERS)'; test -n "$(includeclmdir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ dir='$(DESTDIR)$(includeclmdir)'; $(am__uninstall_files_from_dir)
+install-includegbcHEADERS: $(includegbc_HEADERS)
+ @$(NORMAL_INSTALL)
+ @list='$(includegbc_HEADERS)'; test -n "$(includegbcdir)" || list=; \
+ if test -n "$$list"; then \
+ echo " $(MKDIR_P) '$(DESTDIR)$(includegbcdir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(includegbcdir)" || exit 1; \
+ fi; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(includegbcdir)'"; \
+ $(INSTALL_HEADER) $$files "$(DESTDIR)$(includegbcdir)" || exit $$?; \
+ done
+
+uninstall-includegbcHEADERS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(includegbc_HEADERS)'; test -n "$(includegbcdir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ dir='$(DESTDIR)$(includegbcdir)'; $(am__uninstall_files_from_dir)
+install-includelssHEADERS: $(includelss_HEADERS)
+ @$(NORMAL_INSTALL)
+ @list='$(includelss_HEADERS)'; test -n "$(includelssdir)" || list=; \
+ if test -n "$$list"; then \
+ echo " $(MKDIR_P) '$(DESTDIR)$(includelssdir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(includelssdir)" || exit 1; \
+ fi; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(includelssdir)'"; \
+ $(INSTALL_HEADER) $$files "$(DESTDIR)$(includelssdir)" || exit $$?; \
+ done
+
+uninstall-includelssHEADERS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(includelss_HEADERS)'; test -n "$(includelssdir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ dir='$(DESTDIR)$(includelssdir)'; $(am__uninstall_files_from_dir)
+install-includepHEADERS: $(includep_HEADERS)
+ @$(NORMAL_INSTALL)
+ @list='$(includep_HEADERS)'; test -n "$(includepdir)" || list=; \
+ if test -n "$$list"; then \
+ echo " $(MKDIR_P) '$(DESTDIR)$(includepdir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(includepdir)" || exit 1; \
+ fi; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(includepdir)'"; \
+ $(INSTALL_HEADER) $$files "$(DESTDIR)$(includepdir)" || exit $$?; \
+ done
+
+uninstall-includepHEADERS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(includep_HEADERS)'; test -n "$(includepdir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ dir='$(DESTDIR)$(includepdir)'; $(am__uninstall_files_from_dir)
+
+ID: $(am__tagged_files)
+ $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ set x; \
+ here=`pwd`; \
+ $(am__define_uniq_tagged_files); \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ $(am__define_uniq_tagged_files); \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+cscope: cscope.files
+ test ! -s cscope.files \
+ || $(CSCOPE) -b -q $(AM_CSCOPEFLAGS) $(CSCOPEFLAGS) -i cscope.files $(CSCOPE_ARGS)
+clean-cscope:
+ -rm -f cscope.files
+cscope.files: clean-cscope cscopelist
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+ list='$(am__tagged_files)'; \
+ case "$(srcdir)" in \
+ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+ *) sdir=$(subdir)/$(srcdir) ;; \
+ esac; \
+ for i in $$list; do \
+ if test -f "$$i"; then \
+ echo "$(subdir)/$$i"; \
+ else \
+ echo "$$sdir/$$i"; \
+ fi; \
+ done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+ -rm -f cscope.out cscope.in.out cscope.po.out cscope.files
+
+# Recover from deleted '.trs' file; this should ensure that
+# "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create
+# both 'foo.log' and 'foo.trs'. Break the recipe in two subshells
+# to avoid problems with "make -n".
+.log.trs:
+ rm -f $< $@
+ $(MAKE) $(AM_MAKEFLAGS) $<
+
+# Leading 'am--fnord' is there to ensure the list of targets does not
+# expand to empty, as could happen e.g. with make check TESTS=''.
+am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck)
+am--force-recheck:
+ @:
+
+$(TEST_SUITE_LOG): $(TEST_LOGS)
+ @$(am__set_TESTS_bases); \
+ am__f_ok () { test -f "$$1" && test -r "$$1"; }; \
+ redo_bases=`for i in $$bases; do \
+ am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \
+ done`; \
+ if test -n "$$redo_bases"; then \
+ redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \
+ redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \
+ if $(am__make_dryrun); then :; else \
+ rm -f $$redo_logs && rm -f $$redo_results || exit 1; \
+ fi; \
+ fi; \
+ if test -n "$$am__remaking_logs"; then \
+ echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \
+ "recursion detected" >&2; \
+ elif test -n "$$redo_logs"; then \
+ am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \
+ fi; \
+ if $(am__make_dryrun); then :; else \
+ st=0; \
+ errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \
+ for i in $$redo_bases; do \
+ test -f $$i.trs && test -r $$i.trs \
+ || { echo "$$errmsg $$i.trs" >&2; st=1; }; \
+ test -f $$i.log && test -r $$i.log \
+ || { echo "$$errmsg $$i.log" >&2; st=1; }; \
+ done; \
+ test $$st -eq 0 || exit 1; \
+ fi
+ @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \
+ ws='[ ]'; \
+ results=`for b in $$bases; do echo $$b.trs; done`; \
+ test -n "$$results" || results=/dev/null; \
+ all=` grep "^$$ws*:test-result:" $$results | wc -l`; \
+ pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \
+ fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \
+ skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \
+ xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \
+ xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \
+ error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \
+ if test `expr $$fail + $$xpass + $$error` -eq 0; then \
+ success=true; \
+ else \
+ success=false; \
+ fi; \
+ br='==================='; br=$$br$$br$$br$$br; \
+ result_count () \
+ { \
+ if test x"$$1" = x"--maybe-color"; then \
+ maybe_colorize=yes; \
+ elif test x"$$1" = x"--no-color"; then \
+ maybe_colorize=no; \
+ else \
+ echo "$@: invalid 'result_count' usage" >&2; exit 4; \
+ fi; \
+ shift; \
+ desc=$$1 count=$$2; \
+ if test $$maybe_colorize = yes && test $$count -gt 0; then \
+ color_start=$$3 color_end=$$std; \
+ else \
+ color_start= color_end=; \
+ fi; \
+ echo "$${color_start}# $$desc $$count$${color_end}"; \
+ }; \
+ create_testsuite_report () \
+ { \
+ result_count $$1 "TOTAL:" $$all "$$brg"; \
+ result_count $$1 "PASS: " $$pass "$$grn"; \
+ result_count $$1 "SKIP: " $$skip "$$blu"; \
+ result_count $$1 "XFAIL:" $$xfail "$$lgn"; \
+ result_count $$1 "FAIL: " $$fail "$$red"; \
+ result_count $$1 "XPASS:" $$xpass "$$red"; \
+ result_count $$1 "ERROR:" $$error "$$mgn"; \
+ }; \
+ { \
+ echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \
+ $(am__rst_title); \
+ create_testsuite_report --no-color; \
+ echo; \
+ echo ".. contents:: :depth: 2"; \
+ echo; \
+ for b in $$bases; do echo $$b; done \
+ | $(am__create_global_log); \
+ } >$(TEST_SUITE_LOG).tmp || exit 1; \
+ mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \
+ if $$success; then \
+ col="$$grn"; \
+ else \
+ col="$$red"; \
+ test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \
+ fi; \
+ echo "$${col}$$br$${std}"; \
+ echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \
+ echo "$${col}$$br$${std}"; \
+ create_testsuite_report --maybe-color; \
+ echo "$$col$$br$$std"; \
+ if $$success; then :; else \
+ echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \
+ if test -n "$(PACKAGE_BUGREPORT)"; then \
+ echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \
+ fi; \
+ echo "$$col$$br$$std"; \
+ fi; \
+ $$success || exit 1
+
+check-TESTS:
+ @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list
+ @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list
+ @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG)
+ @set +e; $(am__set_TESTS_bases); \
+ log_list=`for i in $$bases; do echo $$i.log; done`; \
+ trs_list=`for i in $$bases; do echo $$i.trs; done`; \
+ log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \
+ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \
+ exit $$?;
+recheck: all $(check_LIBRARIES) $(check_PROGRAMS) $(check_SCRIPTS)
+ @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG)
+ @set +e; $(am__set_TESTS_bases); \
+ bases=`for i in $$bases; do echo $$i; done \
+ | $(am__list_recheck_tests)` || exit 1; \
+ log_list=`for i in $$bases; do echo $$i.log; done`; \
+ log_list=`echo $$log_list`; \
+ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \
+ am__force_recheck=am--force-recheck \
+ TEST_LOGS="$$log_list"; \
+ exit $$?
+src/common/test_assembler_unittest.log: src/common/test_assembler_unittest$(EXEEXT)
+ @p='src/common/test_assembler_unittest$(EXEEXT)'; \
+ b='src/common/test_assembler_unittest'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+src/processor/address_map_unittest.log: src/processor/address_map_unittest$(EXEEXT)
+ @p='src/processor/address_map_unittest$(EXEEXT)'; \
+ b='src/processor/address_map_unittest'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+src/processor/basic_source_line_resolver_unittest.log: src/processor/basic_source_line_resolver_unittest$(EXEEXT)
+ @p='src/processor/basic_source_line_resolver_unittest$(EXEEXT)'; \
+ b='src/processor/basic_source_line_resolver_unittest'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+src/processor/cfi_frame_info_unittest.log: src/processor/cfi_frame_info_unittest$(EXEEXT)
+ @p='src/processor/cfi_frame_info_unittest$(EXEEXT)'; \
+ b='src/processor/cfi_frame_info_unittest'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+src/processor/contained_range_map_unittest.log: src/processor/contained_range_map_unittest$(EXEEXT)
+ @p='src/processor/contained_range_map_unittest$(EXEEXT)'; \
+ b='src/processor/contained_range_map_unittest'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+src/processor/disassembler_x86_unittest.log: src/processor/disassembler_x86_unittest$(EXEEXT)
+ @p='src/processor/disassembler_x86_unittest$(EXEEXT)'; \
+ b='src/processor/disassembler_x86_unittest'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+src/processor/exploitability_unittest.log: src/processor/exploitability_unittest$(EXEEXT)
+ @p='src/processor/exploitability_unittest$(EXEEXT)'; \
+ b='src/processor/exploitability_unittest'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+src/processor/fast_source_line_resolver_unittest.log: src/processor/fast_source_line_resolver_unittest$(EXEEXT)
+ @p='src/processor/fast_source_line_resolver_unittest$(EXEEXT)'; \
+ b='src/processor/fast_source_line_resolver_unittest'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+src/processor/map_serializers_unittest.log: src/processor/map_serializers_unittest$(EXEEXT)
+ @p='src/processor/map_serializers_unittest$(EXEEXT)'; \
+ b='src/processor/map_serializers_unittest'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+src/processor/microdump_processor_unittest.log: src/processor/microdump_processor_unittest$(EXEEXT)
+ @p='src/processor/microdump_processor_unittest$(EXEEXT)'; \
+ b='src/processor/microdump_processor_unittest'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+src/processor/minidump_processor_unittest.log: src/processor/minidump_processor_unittest$(EXEEXT)
+ @p='src/processor/minidump_processor_unittest$(EXEEXT)'; \
+ b='src/processor/minidump_processor_unittest'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+src/processor/minidump_unittest.log: src/processor/minidump_unittest$(EXEEXT)
+ @p='src/processor/minidump_unittest$(EXEEXT)'; \
+ b='src/processor/minidump_unittest'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+src/processor/static_address_map_unittest.log: src/processor/static_address_map_unittest$(EXEEXT)
+ @p='src/processor/static_address_map_unittest$(EXEEXT)'; \
+ b='src/processor/static_address_map_unittest'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+src/processor/static_contained_range_map_unittest.log: src/processor/static_contained_range_map_unittest$(EXEEXT)
+ @p='src/processor/static_contained_range_map_unittest$(EXEEXT)'; \
+ b='src/processor/static_contained_range_map_unittest'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+src/processor/static_map_unittest.log: src/processor/static_map_unittest$(EXEEXT)
+ @p='src/processor/static_map_unittest$(EXEEXT)'; \
+ b='src/processor/static_map_unittest'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+src/processor/static_range_map_unittest.log: src/processor/static_range_map_unittest$(EXEEXT)
+ @p='src/processor/static_range_map_unittest$(EXEEXT)'; \
+ b='src/processor/static_range_map_unittest'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+src/processor/pathname_stripper_unittest.log: src/processor/pathname_stripper_unittest$(EXEEXT)
+ @p='src/processor/pathname_stripper_unittest$(EXEEXT)'; \
+ b='src/processor/pathname_stripper_unittest'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+src/processor/postfix_evaluator_unittest.log: src/processor/postfix_evaluator_unittest$(EXEEXT)
+ @p='src/processor/postfix_evaluator_unittest$(EXEEXT)'; \
+ b='src/processor/postfix_evaluator_unittest'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+src/processor/proc_maps_linux_unittest.log: src/processor/proc_maps_linux_unittest$(EXEEXT)
+ @p='src/processor/proc_maps_linux_unittest$(EXEEXT)'; \
+ b='src/processor/proc_maps_linux_unittest'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+src/processor/range_map_shrink_down_unittest.log: src/processor/range_map_shrink_down_unittest$(EXEEXT)
+ @p='src/processor/range_map_shrink_down_unittest$(EXEEXT)'; \
+ b='src/processor/range_map_shrink_down_unittest'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+src/processor/range_map_unittest.log: src/processor/range_map_unittest$(EXEEXT)
+ @p='src/processor/range_map_unittest$(EXEEXT)'; \
+ b='src/processor/range_map_unittest'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+src/processor/stackwalker_amd64_unittest.log: src/processor/stackwalker_amd64_unittest$(EXEEXT)
+ @p='src/processor/stackwalker_amd64_unittest$(EXEEXT)'; \
+ b='src/processor/stackwalker_amd64_unittest'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+src/processor/stackwalker_arm_unittest.log: src/processor/stackwalker_arm_unittest$(EXEEXT)
+ @p='src/processor/stackwalker_arm_unittest$(EXEEXT)'; \
+ b='src/processor/stackwalker_arm_unittest'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+src/processor/stackwalker_arm64_unittest.log: src/processor/stackwalker_arm64_unittest$(EXEEXT)
+ @p='src/processor/stackwalker_arm64_unittest$(EXEEXT)'; \
+ b='src/processor/stackwalker_arm64_unittest'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+src/processor/stackwalker_address_list_unittest.log: src/processor/stackwalker_address_list_unittest$(EXEEXT)
+ @p='src/processor/stackwalker_address_list_unittest$(EXEEXT)'; \
+ b='src/processor/stackwalker_address_list_unittest'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+src/processor/stackwalker_mips_unittest.log: src/processor/stackwalker_mips_unittest$(EXEEXT)
+ @p='src/processor/stackwalker_mips_unittest$(EXEEXT)'; \
+ b='src/processor/stackwalker_mips_unittest'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+src/processor/stackwalker_mips64_unittest.log: src/processor/stackwalker_mips64_unittest$(EXEEXT)
+ @p='src/processor/stackwalker_mips64_unittest$(EXEEXT)'; \
+ b='src/processor/stackwalker_mips64_unittest'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+src/processor/stackwalker_x86_unittest.log: src/processor/stackwalker_x86_unittest$(EXEEXT)
+ @p='src/processor/stackwalker_x86_unittest$(EXEEXT)'; \
+ b='src/processor/stackwalker_x86_unittest'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+src/processor/synth_minidump_unittest.log: src/processor/synth_minidump_unittest$(EXEEXT)
+ @p='src/processor/synth_minidump_unittest$(EXEEXT)'; \
+ b='src/processor/synth_minidump_unittest'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+src/client/linux/linux_client_unittest.log: src/client/linux/linux_client_unittest$(EXEEXT)
+ @p='src/client/linux/linux_client_unittest$(EXEEXT)'; \
+ b='src/client/linux/linux_client_unittest'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+src/common/dumper_unittest.log: src/common/dumper_unittest$(EXEEXT)
+ @p='src/common/dumper_unittest$(EXEEXT)'; \
+ b='src/common/dumper_unittest'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+src/tools/linux/md2core/minidump_2_core_unittest.log: src/tools/linux/md2core/minidump_2_core_unittest$(EXEEXT)
+ @p='src/tools/linux/md2core/minidump_2_core_unittest$(EXEEXT)'; \
+ b='src/tools/linux/md2core/minidump_2_core_unittest'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+src/common/mac/macho_reader_unittest.log: src/common/mac/macho_reader_unittest$(EXEEXT)
+ @p='src/common/mac/macho_reader_unittest$(EXEEXT)'; \
+ b='src/common/mac/macho_reader_unittest'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+src/processor/stackwalker_selftest.log: src/processor/stackwalker_selftest$(EXEEXT)
+ @p='src/processor/stackwalker_selftest$(EXEEXT)'; \
+ b='src/processor/stackwalker_selftest'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+src/processor/microdump_stackwalk_test.log: src/processor/microdump_stackwalk_test
+ @p='src/processor/microdump_stackwalk_test'; \
+ b='src/processor/microdump_stackwalk_test'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+src/processor/microdump_stackwalk_machine_readable_test.log: src/processor/microdump_stackwalk_machine_readable_test
+ @p='src/processor/microdump_stackwalk_machine_readable_test'; \
+ b='src/processor/microdump_stackwalk_machine_readable_test'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+src/processor/minidump_dump_test.log: src/processor/minidump_dump_test
+ @p='src/processor/minidump_dump_test'; \
+ b='src/processor/minidump_dump_test'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+src/processor/minidump_stackwalk_test.log: src/processor/minidump_stackwalk_test
+ @p='src/processor/minidump_stackwalk_test'; \
+ b='src/processor/minidump_stackwalk_test'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+src/processor/minidump_stackwalk_machine_readable_test.log: src/processor/minidump_stackwalk_machine_readable_test
+ @p='src/processor/minidump_stackwalk_machine_readable_test'; \
+ b='src/processor/minidump_stackwalk_machine_readable_test'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+.test.log:
+ @p='$<'; \
+ $(am__set_b); \
+ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+@am__EXEEXT_TRUE@.test$(EXEEXT).log:
+@am__EXEEXT_TRUE@ @p='$<'; \
+@am__EXEEXT_TRUE@ $(am__set_b); \
+@am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \
+@am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \
+@am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \
+@am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT)
+
+distdir: $(DISTFILES)
+ $(am__remove_distdir)
+ test -d "$(distdir)" || mkdir "$(distdir)"
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+ -test -n "$(am__skip_mode_fix)" \
+ || find "$(distdir)" -type d ! -perm -755 \
+ -exec chmod u+rwx,go+rx {} \; -o \
+ ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \
+ ! -type d ! -perm -400 -exec chmod a+r {} \; -o \
+ ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \
+ || chmod -R a+r "$(distdir)"
+dist-gzip: distdir
+ tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
+ $(am__post_remove_distdir)
+
+dist-bzip2: distdir
+ tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2
+ $(am__post_remove_distdir)
+
+dist-lzip: distdir
+ tardir=$(distdir) && $(am__tar) | lzip -c $${LZIP_OPT--9} >$(distdir).tar.lz
+ $(am__post_remove_distdir)
+
+dist-xz: distdir
+ tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz
+ $(am__post_remove_distdir)
+
+dist-tarZ: distdir
+ @echo WARNING: "Support for distribution archives compressed with" \
+ "legacy program 'compress' is deprecated." >&2
+ @echo WARNING: "It will be removed altogether in Automake 2.0" >&2
+ tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z
+ $(am__post_remove_distdir)
+
+dist-shar: distdir
+ @echo WARNING: "Support for shar distribution archives is" \
+ "deprecated." >&2
+ @echo WARNING: "It will be removed altogether in Automake 2.0" >&2
+ shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz
+ $(am__post_remove_distdir)
+
+dist-zip: distdir
+ -rm -f $(distdir).zip
+ zip -rq $(distdir).zip $(distdir)
+ $(am__post_remove_distdir)
+
+dist dist-all:
+ $(MAKE) $(AM_MAKEFLAGS) $(DIST_TARGETS) am__post_remove_distdir='@:'
+ $(am__post_remove_distdir)
+
+# This target untars the dist file and tries a VPATH configuration. Then
+# it guarantees that the distribution is self-contained by making another
+# tarfile.
+distcheck: dist
+ case '$(DIST_ARCHIVES)' in \
+ *.tar.gz*) \
+ GZIP=$(GZIP_ENV) gzip -dc $(distdir).tar.gz | $(am__untar) ;;\
+ *.tar.bz2*) \
+ bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\
+ *.tar.lz*) \
+ lzip -dc $(distdir).tar.lz | $(am__untar) ;;\
+ *.tar.xz*) \
+ xz -dc $(distdir).tar.xz | $(am__untar) ;;\
+ *.tar.Z*) \
+ uncompress -c $(distdir).tar.Z | $(am__untar) ;;\
+ *.shar.gz*) \
+ GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\
+ *.zip*) \
+ unzip $(distdir).zip ;;\
+ esac
+ chmod -R a-w $(distdir)
+ chmod u+w $(distdir)
+ mkdir $(distdir)/_build $(distdir)/_build/sub $(distdir)/_inst
+ chmod a-w $(distdir)
+ test -d $(distdir)/_build || exit 0; \
+ dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \
+ && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \
+ && am__cwd=`pwd` \
+ && $(am__cd) $(distdir)/_build/sub \
+ && ../../configure \
+ $(AM_DISTCHECK_CONFIGURE_FLAGS) \
+ $(DISTCHECK_CONFIGURE_FLAGS) \
+ --srcdir=../.. --prefix="$$dc_install_base" \
+ && $(MAKE) $(AM_MAKEFLAGS) \
+ && $(MAKE) $(AM_MAKEFLAGS) dvi \
+ && $(MAKE) $(AM_MAKEFLAGS) check \
+ && $(MAKE) $(AM_MAKEFLAGS) install \
+ && $(MAKE) $(AM_MAKEFLAGS) installcheck \
+ && $(MAKE) $(AM_MAKEFLAGS) uninstall \
+ && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \
+ distuninstallcheck \
+ && chmod -R a-w "$$dc_install_base" \
+ && ({ \
+ (cd ../.. && umask 077 && mkdir "$$dc_destdir") \
+ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \
+ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \
+ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \
+ distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \
+ } || { rm -rf "$$dc_destdir"; exit 1; }) \
+ && rm -rf "$$dc_destdir" \
+ && $(MAKE) $(AM_MAKEFLAGS) dist \
+ && rm -rf $(DIST_ARCHIVES) \
+ && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \
+ && cd "$$am__cwd" \
+ || exit 1
+ $(am__post_remove_distdir)
+ @(echo "$(distdir) archives ready for distribution: "; \
+ list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \
+ sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x'
+distuninstallcheck:
+ @test -n '$(distuninstallcheck_dir)' || { \
+ echo 'ERROR: trying to run $@ with an empty' \
+ '$$(distuninstallcheck_dir)' >&2; \
+ exit 1; \
+ }; \
+ $(am__cd) '$(distuninstallcheck_dir)' || { \
+ echo 'ERROR: cannot chdir into $(distuninstallcheck_dir)' >&2; \
+ exit 1; \
+ }; \
+ test `$(am__distuninstallcheck_listfiles) | wc -l` -eq 0 \
+ || { echo "ERROR: files left after uninstall:" ; \
+ if test -n "$(DESTDIR)"; then \
+ echo " (check DESTDIR support)"; \
+ fi ; \
+ $(distuninstallcheck_listfiles) ; \
+ exit 1; } >&2
+distcleancheck: distclean
+ @if test '$(srcdir)' = . ; then \
+ echo "ERROR: distcleancheck can only run from a VPATH build" ; \
+ exit 1 ; \
+ fi
+ @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \
+ || { echo "ERROR: files left in build directory after distclean:" ; \
+ $(distcleancheck_listfiles) ; \
+ exit 1; } >&2
+check-am: all-am
+ $(MAKE) $(AM_MAKEFLAGS) $(check_LIBRARIES) $(check_PROGRAMS) \
+ $(check_SCRIPTS)
+ $(MAKE) $(AM_MAKEFLAGS) check-TESTS
+check: check-am
+all-am: Makefile $(LIBRARIES) $(PROGRAMS) $(SCRIPTS) $(DATA) \
+ $(HEADERS)
+installdirs:
+ for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(docdir)" "$(DESTDIR)$(pkgconfigdir)" "$(DESTDIR)$(includecdir)" "$(DESTDIR)$(includecldir)" "$(DESTDIR)$(includeclcdir)" "$(DESTDIR)$(includecldwcdir)" "$(DESTDIR)$(includeclhdir)" "$(DESTDIR)$(includeclmdir)" "$(DESTDIR)$(includegbcdir)" "$(DESTDIR)$(includelssdir)" "$(DESTDIR)$(includepdir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+ -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS)
+ -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs)
+ -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG)
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+ -rm -f src/$(am__dirstamp)
+ -rm -f src/client/$(DEPDIR)/$(am__dirstamp)
+ -rm -f src/client/$(am__dirstamp)
+ -rm -f src/client/linux/$(am__dirstamp)
+ -rm -f src/client/linux/crash_generation/$(DEPDIR)/$(am__dirstamp)
+ -rm -f src/client/linux/crash_generation/$(am__dirstamp)
+ -rm -f src/client/linux/dump_writer_common/$(DEPDIR)/$(am__dirstamp)
+ -rm -f src/client/linux/dump_writer_common/$(am__dirstamp)
+ -rm -f src/client/linux/handler/$(DEPDIR)/$(am__dirstamp)
+ -rm -f src/client/linux/handler/$(am__dirstamp)
+ -rm -f src/client/linux/log/$(DEPDIR)/$(am__dirstamp)
+ -rm -f src/client/linux/log/$(am__dirstamp)
+ -rm -f src/client/linux/microdump_writer/$(DEPDIR)/$(am__dirstamp)
+ -rm -f src/client/linux/microdump_writer/$(am__dirstamp)
+ -rm -f src/client/linux/minidump_writer/$(DEPDIR)/$(am__dirstamp)
+ -rm -f src/client/linux/minidump_writer/$(am__dirstamp)
+ -rm -f src/common/$(DEPDIR)/$(am__dirstamp)
+ -rm -f src/common/$(am__dirstamp)
+ -rm -f src/common/android/$(DEPDIR)/$(am__dirstamp)
+ -rm -f src/common/android/$(am__dirstamp)
+ -rm -f src/common/dwarf/$(DEPDIR)/$(am__dirstamp)
+ -rm -f src/common/dwarf/$(am__dirstamp)
+ -rm -f src/common/linux/$(DEPDIR)/$(am__dirstamp)
+ -rm -f src/common/linux/$(am__dirstamp)
+ -rm -f src/common/linux/tests/$(DEPDIR)/$(am__dirstamp)
+ -rm -f src/common/linux/tests/$(am__dirstamp)
+ -rm -f src/common/mac/$(DEPDIR)/$(am__dirstamp)
+ -rm -f src/common/mac/$(am__dirstamp)
+ -rm -f src/common/tests/$(DEPDIR)/$(am__dirstamp)
+ -rm -f src/common/tests/$(am__dirstamp)
+ -rm -f src/processor/$(DEPDIR)/$(am__dirstamp)
+ -rm -f src/processor/$(am__dirstamp)
+ -rm -f src/testing/$(am__dirstamp)
+ -rm -f src/testing/gtest/src/$(DEPDIR)/$(am__dirstamp)
+ -rm -f src/testing/gtest/src/$(am__dirstamp)
+ -rm -f src/testing/src/$(DEPDIR)/$(am__dirstamp)
+ -rm -f src/testing/src/$(am__dirstamp)
+ -rm -f src/third_party/libdisasm/$(DEPDIR)/$(am__dirstamp)
+ -rm -f src/third_party/libdisasm/$(am__dirstamp)
+ -rm -f src/tools/linux/core2md/$(DEPDIR)/$(am__dirstamp)
+ -rm -f src/tools/linux/core2md/$(am__dirstamp)
+ -rm -f src/tools/linux/dump_syms/$(DEPDIR)/$(am__dirstamp)
+ -rm -f src/tools/linux/dump_syms/$(am__dirstamp)
+ -rm -f src/tools/linux/md2core/$(DEPDIR)/$(am__dirstamp)
+ -rm -f src/tools/linux/md2core/$(am__dirstamp)
+ -rm -f src/tools/linux/symupload/$(DEPDIR)/$(am__dirstamp)
+ -rm -f src/tools/linux/symupload/$(am__dirstamp)
+ -rm -f src/tools/mac/dump_syms/$(DEPDIR)/$(am__dirstamp)
+ -rm -f src/tools/mac/dump_syms/$(am__dirstamp)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-binPROGRAMS clean-checkLIBRARIES clean-checkPROGRAMS \
+ clean-generic clean-libLIBRARIES clean-noinstLIBRARIES \
+ clean-noinstPROGRAMS mostlyclean-am
+
+distclean: distclean-am
+ -rm -f $(am__CONFIG_DISTCLEAN_FILES)
+ -rm -rf src/client/$(DEPDIR) src/client/linux/crash_generation/$(DEPDIR) src/client/linux/dump_writer_common/$(DEPDIR) src/client/linux/handler/$(DEPDIR) src/client/linux/log/$(DEPDIR) src/client/linux/microdump_writer/$(DEPDIR) src/client/linux/minidump_writer/$(DEPDIR) src/common/$(DEPDIR) src/common/android/$(DEPDIR) src/common/dwarf/$(DEPDIR) src/common/linux/$(DEPDIR) src/common/linux/tests/$(DEPDIR) src/common/mac/$(DEPDIR) src/common/tests/$(DEPDIR) src/processor/$(DEPDIR) src/testing/gtest/src/$(DEPDIR) src/testing/src/$(DEPDIR) src/third_party/libdisasm/$(DEPDIR) src/tools/linux/core2md/$(DEPDIR) src/tools/linux/dump_syms/$(DEPDIR) src/tools/linux/md2core/$(DEPDIR) src/tools/linux/symupload/$(DEPDIR) src/tools/mac/dump_syms/$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-hdr distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-dist_docDATA install-includecHEADERS \
+ install-includeclHEADERS install-includeclcHEADERS \
+ install-includecldwcHEADERS install-includeclhHEADERS \
+ install-includeclmHEADERS install-includegbcHEADERS \
+ install-includelssHEADERS install-includepHEADERS \
+ install-pkgconfigDATA
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am: install-binPROGRAMS install-libLIBRARIES
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -f $(am__CONFIG_DISTCLEAN_FILES)
+ -rm -rf $(top_srcdir)/autom4te.cache
+ -rm -rf src/client/$(DEPDIR) src/client/linux/crash_generation/$(DEPDIR) src/client/linux/dump_writer_common/$(DEPDIR) src/client/linux/handler/$(DEPDIR) src/client/linux/log/$(DEPDIR) src/client/linux/microdump_writer/$(DEPDIR) src/client/linux/minidump_writer/$(DEPDIR) src/common/$(DEPDIR) src/common/android/$(DEPDIR) src/common/dwarf/$(DEPDIR) src/common/linux/$(DEPDIR) src/common/linux/tests/$(DEPDIR) src/common/mac/$(DEPDIR) src/common/tests/$(DEPDIR) src/processor/$(DEPDIR) src/testing/gtest/src/$(DEPDIR) src/testing/src/$(DEPDIR) src/third_party/libdisasm/$(DEPDIR) src/tools/linux/core2md/$(DEPDIR) src/tools/linux/dump_syms/$(DEPDIR) src/tools/linux/md2core/$(DEPDIR) src/tools/linux/symupload/$(DEPDIR) src/tools/mac/dump_syms/$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-local
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-binPROGRAMS uninstall-dist_docDATA \
+ uninstall-includecHEADERS uninstall-includeclHEADERS \
+ uninstall-includeclcHEADERS uninstall-includecldwcHEADERS \
+ uninstall-includeclhHEADERS uninstall-includeclmHEADERS \
+ uninstall-includegbcHEADERS uninstall-includelssHEADERS \
+ uninstall-includepHEADERS uninstall-libLIBRARIES \
+ uninstall-pkgconfigDATA
+
+.MAKE: check-am install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--refresh check check-TESTS \
+ check-am clean clean-binPROGRAMS clean-checkLIBRARIES \
+ clean-checkPROGRAMS clean-cscope clean-generic \
+ clean-libLIBRARIES clean-noinstLIBRARIES clean-noinstPROGRAMS \
+ cscope cscopelist-am ctags ctags-am dist dist-all dist-bzip2 \
+ dist-gzip dist-lzip dist-shar dist-tarZ dist-xz dist-zip \
+ distcheck distclean distclean-compile distclean-generic \
+ distclean-hdr distclean-tags distcleancheck distdir \
+ distuninstallcheck dvi dvi-am html html-am info info-am \
+ install install-am install-binPROGRAMS install-data \
+ install-data-am install-dist_docDATA install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-includecHEADERS \
+ install-includeclHEADERS install-includeclcHEADERS \
+ install-includecldwcHEADERS install-includeclhHEADERS \
+ install-includeclmHEADERS install-includegbcHEADERS \
+ install-includelssHEADERS install-includepHEADERS install-info \
+ install-info-am install-libLIBRARIES install-man install-pdf \
+ install-pdf-am install-pkgconfigDATA install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-local pdf \
+ pdf-am ps ps-am recheck tags tags-am uninstall uninstall-am \
+ uninstall-binPROGRAMS uninstall-dist_docDATA \
+ uninstall-includecHEADERS uninstall-includeclHEADERS \
+ uninstall-includeclcHEADERS uninstall-includecldwcHEADERS \
+ uninstall-includeclhHEADERS uninstall-includeclmHEADERS \
+ uninstall-includegbcHEADERS uninstall-includelssHEADERS \
+ uninstall-includepHEADERS uninstall-libLIBRARIES \
+ uninstall-pkgconfigDATA
+
+.PRECIOUS: Makefile
+
+
+mostlyclean-local:
+ -find src -name '*.dwo' -exec rm -f {} +
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/toolkit/crashreporter/google-breakpad/NEWS b/toolkit/crashreporter/google-breakpad/NEWS
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/NEWS
diff --git a/toolkit/crashreporter/google-breakpad/README.ANDROID b/toolkit/crashreporter/google-breakpad/README.ANDROID
new file mode 100644
index 0000000000..30959ed3a2
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/README.ANDROID
@@ -0,0 +1,139 @@
+Google Breakpad for Android
+===========================
+
+This document explains how to use the Google Breakpad client library
+on Android, and later generate valid stack traces from the minidumps
+it generates.
+
+This release supports ARM, x86 and MIPS based Android systems.
+This release requires NDK release r11c or higher.
+
+I. Building the client library:
+===============================
+
+The Android client is built as a static library that you can
+link into your own Android native code. There are two ways to
+build it:
+
+I.1. Building with ndk-build:
+-----------------------------
+
+If you're using the ndk-build build system, you can follow
+these simple steps:
+
+ 1/ Include android/google_breakpad/Android.mk from your own
+ project's Android.mk
+
+ This can be done either directly, or using ndk-build's
+ import-module feature.
+
+ 2/ Link the library to one of your modules by using:
+
+ LOCAL_STATIC_LIBRARIES += breakpad_client
+
+NOTE: The client library requires a C++ STL implementation,
+ which you can select with APP_STL in your Application.mk
+
+ It has been tested succesfully with both STLport and GNU libstdc++
+
+
+I.2. Building with a standalone Android toolchain:
+--------------------------------------------------
+
+All you need to do is configure your build with the right 'host'
+value, and disable the processor and tools, as in:
+
+ $GOOGLE_BREAKPAD_PATH/configure --host=arm-linux-androideabi \
+ --disable-processor \
+ --disable-tools
+ make -j4
+
+The library will be under src/client/linux/libbreakpad_client.a
+
+You can also use 'make check' to run the test suite on a connected
+Android device. This requires the Android 'adb' tool to be in your
+path.
+
+II. Using the client library in Android:
+========================================
+
+The usage instructions are very similar to the Linux ones that are
+found at https://chromium.googlesource.com/breakpad/breakpad/+/master/docs/linux_starter_guide.md
+
+1/ You need to include "client/linux/handler/exception_handler.h" from a C++
+ source file.
+
+2/ If you're not using ndk-build, you also need to:
+
+ - add the following to your compiler include search paths:
+ $GOOGLE_BREAKPAD_PATH/src
+ $GOOGLE_BREAKPAD_PATH/src/common/android/include
+
+ - add -llog to your linker flags
+
+ Note that ndk-build does that for your automatically.
+
+3/ Keep in mind that there is no /tmp directory on Android.
+
+ If you use the library from a regular Android applications, specify a
+ path under your app-specific storage directory. An alternative is to
+ store them on the SDCard, but this requires a specific permission.
+
+For a concrete example, see the sample test application under
+android/sample_app. See its README for more information.
+
+
+III. Getting a stack trace on the host:
+=======================================
+
+This process is similar to other platforms, but here's a quick example:
+
+1/ Retrieve the minidumps on your development machine.
+
+2/ Dump the symbols for your native libraries with the 'dump_syms' tool.
+ This first requires building the host version of Google Breakpad, then
+ calling:
+
+ dump_syms $PROJECT_PATH/obj/local/$ABI/libfoo.so > libfoo.so.sym
+
+3/ Create the symbol directory hierarchy.
+
+ The first line of the generated libfoo.so.sym will have a "MODULE"
+ entry that carries a hexadecimal version number, e.g.:
+
+ MODULE Linux arm D51B4A5504974FA6ECC1869CAEE3603B0 test_google_breakpad
+
+ Note: The second field could be either 'Linux' or 'Android'.
+
+ Extract the version number, and a 'symbol' directory, for example:
+
+ $PROJECT_PATH/symbols/libfoo.so/$VERSION/
+
+ Copy/Move your libfoo.sym file there.
+
+4/ Invoke minidump_stackwalk to create the stack trace:
+
+ minidump_stackwalk $MINIDUMP_FILE $PROJECT_PATH/symbols
+
+Note that various helper scripts can be found on the web to automate these
+steps.
+
+IV. Verifying the Android build library:
+========================================
+
+If you modify Google Breakpad and want to check that it still works correctly
+on Android, please run the android/run-checks.sh script which will do all
+necessary verifications for you. This includes:
+
+ - Rebuilding the full host binaries.
+ - Rebuilding the full Android binaries with configure/make.
+ - Rebuilding the client library unit tests, and running them on a device.
+ - Rebuilding the client library with ndk-build.
+ - Building, installing and running a test crasher program on a device.
+ - Extracting the corresponding minidump, dumping the test program symbols
+ and generating a stack trace.
+ - Checking the generated stack trace for valid source locations.
+
+For more details, please run:
+
+ android/run-checks.sh --help-all
diff --git a/toolkit/crashreporter/google-breakpad/README.md b/toolkit/crashreporter/google-breakpad/README.md
new file mode 100644
index 0000000000..caefdd28c3
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/README.md
@@ -0,0 +1,82 @@
+# Breakpad
+
+Breakpad is a set of client and server components which implement a
+crash-reporting system.
+
+* [Homepage](https://chromium.googlesource.com/breakpad/breakpad/)
+* [Documentation](https://chromium.googlesource.com/breakpad/breakpad/+/master/docs/)
+* [Bugs](https://bugs.chromium.org/p/google-breakpad/)
+* Discussion/Questions: [google-breakpad-discuss@googlegroups.com](https://groups.google.com/d/forum/google-breakpad-discuss)
+* Developer/Reviews: [google-breakpad-dev@googlegroups.com](https://groups.google.com/d/forum/google-breakpad-dev)
+* Tests: [![Build Status](https://travis-ci.org/google/breakpad.svg?branch=master)](https://travis-ci.org/google/breakpad) [![Build status](https://ci.appveyor.com/api/projects/status/eguv4emv2rhq68u2?svg=true)](https://ci.appveyor.com/project/vapier/breakpad)
+* Coverage [![Coverity Status](https://scan.coverity.com/projects/9215/badge.svg)](https://scan.coverity.com/projects/google-breakpad)
+
+## Getting started (from master)
+
+1. First, [download depot_tools](http://dev.chromium.org/developers/how-tos/install-depot-tools)
+ and ensure that they’re in your `PATH`.
+
+2. Create a new directory for checking out the source code (it must be named
+ breakpad).
+
+ ```sh
+ mkdir breakpad && cd breakpad
+ ```
+
+3. Run the `fetch` tool from depot_tools to download all the source repos.
+
+ ```sh
+ fetch breakpad
+ cd src
+ ```
+
+4. Build the source.
+
+ ```sh
+ ./configure && make
+ ```
+
+ You can also cd to another directory and run configure from there to build
+ outside the source tree.
+
+ This will build the processor tools (`src/processor/minidump_stackwalk`,
+ `src/processor/minidump_dump`, etc), and when building on Linux it will
+ also build the client libraries and some tools
+ (`src/tools/linux/dump_syms/dump_syms`,
+ `src/tools/linux/md2core/minidump-2-core`, etc).
+
+5. Optionally, run tests.
+
+ ```sh
+ make check
+ ```
+
+6. Optionally, install the built libraries
+
+ ```sh
+ make install
+ ```
+
+If you need to reconfigure your build be sure to run `make distclean` first.
+
+To update an existing checkout to a newer revision, you can
+`git pull` as usual, but then you should run `gclient sync` to ensure that the
+dependent repos are up-to-date.
+
+## To request change review
+
+1. Follow the steps above to get the source and build it.
+
+2. Make changes. Build and test your changes.
+ For core code like processor use methods above.
+ For linux/mac/windows, there are test targets in each project file.
+
+3. Commit your changes to your local repo and upload them to the server.
+ http://dev.chromium.org/developers/contributing-code
+ e.g. `git commit ... && git cl upload ...`
+ You will be prompted for credential and a description.
+
+4. At https://chromium-review.googlesource.com/ you'll find your issue listed;
+ click on it, then “Add reviewer”, and enter in the code reviewer. Depending
+ on your settings, you may not see an email, but the reviewer has been
+ notified with google-breakpad-dev@googlegroups.com always CC’d.
diff --git a/toolkit/crashreporter/google-breakpad/aclocal.m4 b/toolkit/crashreporter/google-breakpad/aclocal.m4
new file mode 100644
index 0000000000..b6aeaa4498
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/aclocal.m4
@@ -0,0 +1,1304 @@
+# generated automatically by aclocal 1.15.1 -*- Autoconf -*-
+
+# Copyright (C) 1996-2017 Free Software Foundation, Inc.
+
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])])
+m4_ifndef([AC_AUTOCONF_VERSION],
+ [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
+m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.69],,
+[m4_warning([this file was generated for autoconf 2.69.
+You have another version of autoconf. It may work, but is not guaranteed to.
+If you have problems, you may need to regenerate the build system entirely.
+To do so, use the procedure documented by the package, typically 'autoreconf'.])])
+
+# Copyright (C) 2002-2017 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_AUTOMAKE_VERSION(VERSION)
+# ----------------------------
+# Automake X.Y traces this macro to ensure aclocal.m4 has been
+# generated from the m4 files accompanying Automake X.Y.
+# (This private macro should not be called outside this file.)
+AC_DEFUN([AM_AUTOMAKE_VERSION],
+[am__api_version='1.15'
+dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to
+dnl require some minimum version. Point them to the right macro.
+m4_if([$1], [1.15.1], [],
+ [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl
+])
+
+# _AM_AUTOCONF_VERSION(VERSION)
+# -----------------------------
+# aclocal traces this macro to find the Autoconf version.
+# This is a private macro too. Using m4_define simplifies
+# the logic in aclocal, which can simply ignore this definition.
+m4_define([_AM_AUTOCONF_VERSION], [])
+
+# AM_SET_CURRENT_AUTOMAKE_VERSION
+# -------------------------------
+# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced.
+# This function is AC_REQUIREd by AM_INIT_AUTOMAKE.
+AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
+[AM_AUTOMAKE_VERSION([1.15.1])dnl
+m4_ifndef([AC_AUTOCONF_VERSION],
+ [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
+_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))])
+
+# Copyright (C) 2011-2017 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_PROG_AR([ACT-IF-FAIL])
+# -------------------------
+# Try to determine the archiver interface, and trigger the ar-lib wrapper
+# if it is needed. If the detection of archiver interface fails, run
+# ACT-IF-FAIL (default is to abort configure with a proper error message).
+AC_DEFUN([AM_PROG_AR],
+[AC_BEFORE([$0], [LT_INIT])dnl
+AC_BEFORE([$0], [AC_PROG_LIBTOOL])dnl
+AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+AC_REQUIRE_AUX_FILE([ar-lib])dnl
+AC_CHECK_TOOLS([AR], [ar lib "link -lib"], [false])
+: ${AR=ar}
+
+AC_CACHE_CHECK([the archiver ($AR) interface], [am_cv_ar_interface],
+ [AC_LANG_PUSH([C])
+ am_cv_ar_interface=ar
+ AC_COMPILE_IFELSE([AC_LANG_SOURCE([[int some_variable = 0;]])],
+ [am_ar_try='$AR cru libconftest.a conftest.$ac_objext >&AS_MESSAGE_LOG_FD'
+ AC_TRY_EVAL([am_ar_try])
+ if test "$ac_status" -eq 0; then
+ am_cv_ar_interface=ar
+ else
+ am_ar_try='$AR -NOLOGO -OUT:conftest.lib conftest.$ac_objext >&AS_MESSAGE_LOG_FD'
+ AC_TRY_EVAL([am_ar_try])
+ if test "$ac_status" -eq 0; then
+ am_cv_ar_interface=lib
+ else
+ am_cv_ar_interface=unknown
+ fi
+ fi
+ rm -f conftest.lib libconftest.a
+ ])
+ AC_LANG_POP([C])])
+
+case $am_cv_ar_interface in
+ar)
+ ;;
+lib)
+ # Microsoft lib, so override with the ar-lib wrapper script.
+ # FIXME: It is wrong to rewrite AR.
+ # But if we don't then we get into trouble of one sort or another.
+ # A longer-term fix would be to have automake use am__AR in this case,
+ # and then we could set am__AR="$am_aux_dir/ar-lib \$(AR)" or something
+ # similar.
+ AR="$am_aux_dir/ar-lib $AR"
+ ;;
+unknown)
+ m4_default([$1],
+ [AC_MSG_ERROR([could not determine $AR interface])])
+ ;;
+esac
+AC_SUBST([AR])dnl
+])
+
+# Figure out how to run the assembler. -*- Autoconf -*-
+
+# Copyright (C) 2001-2017 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_PROG_AS
+# ----------
+AC_DEFUN([AM_PROG_AS],
+[# By default we simply use the C compiler to build assembly code.
+AC_REQUIRE([AC_PROG_CC])
+test "${CCAS+set}" = set || CCAS=$CC
+test "${CCASFLAGS+set}" = set || CCASFLAGS=$CFLAGS
+AC_ARG_VAR([CCAS], [assembler compiler command (defaults to CC)])
+AC_ARG_VAR([CCASFLAGS], [assembler compiler flags (defaults to CFLAGS)])
+_AM_IF_OPTION([no-dependencies],, [_AM_DEPENDENCIES([CCAS])])dnl
+])
+
+# AM_AUX_DIR_EXPAND -*- Autoconf -*-
+
+# Copyright (C) 2001-2017 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets
+# $ac_aux_dir to '$srcdir/foo'. In other projects, it is set to
+# '$srcdir', '$srcdir/..', or '$srcdir/../..'.
+#
+# Of course, Automake must honor this variable whenever it calls a
+# tool from the auxiliary directory. The problem is that $srcdir (and
+# therefore $ac_aux_dir as well) can be either absolute or relative,
+# depending on how configure is run. This is pretty annoying, since
+# it makes $ac_aux_dir quite unusable in subdirectories: in the top
+# source directory, any form will work fine, but in subdirectories a
+# relative path needs to be adjusted first.
+#
+# $ac_aux_dir/missing
+# fails when called from a subdirectory if $ac_aux_dir is relative
+# $top_srcdir/$ac_aux_dir/missing
+# fails if $ac_aux_dir is absolute,
+# fails when called from a subdirectory in a VPATH build with
+# a relative $ac_aux_dir
+#
+# The reason of the latter failure is that $top_srcdir and $ac_aux_dir
+# are both prefixed by $srcdir. In an in-source build this is usually
+# harmless because $srcdir is '.', but things will broke when you
+# start a VPATH build or use an absolute $srcdir.
+#
+# So we could use something similar to $top_srcdir/$ac_aux_dir/missing,
+# iff we strip the leading $srcdir from $ac_aux_dir. That would be:
+# am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"`
+# and then we would define $MISSING as
+# MISSING="\${SHELL} $am_aux_dir/missing"
+# This will work as long as MISSING is not called from configure, because
+# unfortunately $(top_srcdir) has no meaning in configure.
+# However there are other variables, like CC, which are often used in
+# configure, and could therefore not use this "fixed" $ac_aux_dir.
+#
+# Another solution, used here, is to always expand $ac_aux_dir to an
+# absolute PATH. The drawback is that using absolute paths prevent a
+# configured tree to be moved without reconfiguration.
+
+AC_DEFUN([AM_AUX_DIR_EXPAND],
+[AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl
+# Expand $ac_aux_dir to an absolute path.
+am_aux_dir=`cd "$ac_aux_dir" && pwd`
+])
+
+# AM_CONDITIONAL -*- Autoconf -*-
+
+# Copyright (C) 1997-2017 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_CONDITIONAL(NAME, SHELL-CONDITION)
+# -------------------------------------
+# Define a conditional.
+AC_DEFUN([AM_CONDITIONAL],
+[AC_PREREQ([2.52])dnl
+ m4_if([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])],
+ [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl
+AC_SUBST([$1_TRUE])dnl
+AC_SUBST([$1_FALSE])dnl
+_AM_SUBST_NOTMAKE([$1_TRUE])dnl
+_AM_SUBST_NOTMAKE([$1_FALSE])dnl
+m4_define([_AM_COND_VALUE_$1], [$2])dnl
+if $2; then
+ $1_TRUE=
+ $1_FALSE='#'
+else
+ $1_TRUE='#'
+ $1_FALSE=
+fi
+AC_CONFIG_COMMANDS_PRE(
+[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then
+ AC_MSG_ERROR([[conditional "$1" was never defined.
+Usually this means the macro was only invoked conditionally.]])
+fi])])
+
+# Copyright (C) 1999-2017 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+
+# There are a few dirty hacks below to avoid letting 'AC_PROG_CC' be
+# written in clear, in which case automake, when reading aclocal.m4,
+# will think it sees a *use*, and therefore will trigger all it's
+# C support machinery. Also note that it means that autoscan, seeing
+# CC etc. in the Makefile, will ask for an AC_PROG_CC use...
+
+
+# _AM_DEPENDENCIES(NAME)
+# ----------------------
+# See how the compiler implements dependency checking.
+# NAME is "CC", "CXX", "OBJC", "OBJCXX", "UPC", or "GJC".
+# We try a few techniques and use that to set a single cache variable.
+#
+# We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was
+# modified to invoke _AM_DEPENDENCIES(CC); we would have a circular
+# dependency, and given that the user is not expected to run this macro,
+# just rely on AC_PROG_CC.
+AC_DEFUN([_AM_DEPENDENCIES],
+[AC_REQUIRE([AM_SET_DEPDIR])dnl
+AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl
+AC_REQUIRE([AM_MAKE_INCLUDE])dnl
+AC_REQUIRE([AM_DEP_TRACK])dnl
+
+m4_if([$1], [CC], [depcc="$CC" am_compiler_list=],
+ [$1], [CXX], [depcc="$CXX" am_compiler_list=],
+ [$1], [OBJC], [depcc="$OBJC" am_compiler_list='gcc3 gcc'],
+ [$1], [OBJCXX], [depcc="$OBJCXX" am_compiler_list='gcc3 gcc'],
+ [$1], [UPC], [depcc="$UPC" am_compiler_list=],
+ [$1], [GCJ], [depcc="$GCJ" am_compiler_list='gcc3 gcc'],
+ [depcc="$$1" am_compiler_list=])
+
+AC_CACHE_CHECK([dependency style of $depcc],
+ [am_cv_$1_dependencies_compiler_type],
+[if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+ # We make a subdir and do the tests there. Otherwise we can end up
+ # making bogus files that we don't know about and never remove. For
+ # instance it was reported that on HP-UX the gcc test will end up
+ # making a dummy file named 'D' -- because '-MD' means "put the output
+ # in D".
+ rm -rf conftest.dir
+ mkdir conftest.dir
+ # Copy depcomp to subdir because otherwise we won't find it if we're
+ # using a relative directory.
+ cp "$am_depcomp" conftest.dir
+ cd conftest.dir
+ # We will build objects and dependencies in a subdirectory because
+ # it helps to detect inapplicable dependency modes. For instance
+ # both Tru64's cc and ICC support -MD to output dependencies as a
+ # side effect of compilation, but ICC will put the dependencies in
+ # the current directory while Tru64 will put them in the object
+ # directory.
+ mkdir sub
+
+ am_cv_$1_dependencies_compiler_type=none
+ if test "$am_compiler_list" = ""; then
+ am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp`
+ fi
+ am__universal=false
+ m4_case([$1], [CC],
+ [case " $depcc " in #(
+ *\ -arch\ *\ -arch\ *) am__universal=true ;;
+ esac],
+ [CXX],
+ [case " $depcc " in #(
+ *\ -arch\ *\ -arch\ *) am__universal=true ;;
+ esac])
+
+ for depmode in $am_compiler_list; do
+ # Setup a source with many dependencies, because some compilers
+ # like to wrap large dependency lists on column 80 (with \), and
+ # we should not choose a depcomp mode which is confused by this.
+ #
+ # We need to recreate these files for each test, as the compiler may
+ # overwrite some of them when testing with obscure command lines.
+ # This happens at least with the AIX C compiler.
+ : > sub/conftest.c
+ for i in 1 2 3 4 5 6; do
+ echo '#include "conftst'$i'.h"' >> sub/conftest.c
+ # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with
+ # Solaris 10 /bin/sh.
+ echo '/* dummy */' > sub/conftst$i.h
+ done
+ echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+
+ # We check with '-c' and '-o' for the sake of the "dashmstdout"
+ # mode. It turns out that the SunPro C++ compiler does not properly
+ # handle '-M -o', and we need to detect this. Also, some Intel
+ # versions had trouble with output in subdirs.
+ am__obj=sub/conftest.${OBJEXT-o}
+ am__minus_obj="-o $am__obj"
+ case $depmode in
+ gcc)
+ # This depmode causes a compiler race in universal mode.
+ test "$am__universal" = false || continue
+ ;;
+ nosideeffect)
+ # After this tag, mechanisms are not by side-effect, so they'll
+ # only be used when explicitly requested.
+ if test "x$enable_dependency_tracking" = xyes; then
+ continue
+ else
+ break
+ fi
+ ;;
+ msvc7 | msvc7msys | msvisualcpp | msvcmsys)
+ # This compiler won't grok '-c -o', but also, the minuso test has
+ # not run yet. These depmodes are late enough in the game, and
+ # so weak that their functioning should not be impacted.
+ am__obj=conftest.${OBJEXT-o}
+ am__minus_obj=
+ ;;
+ none) break ;;
+ esac
+ if depmode=$depmode \
+ source=sub/conftest.c object=$am__obj \
+ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \
+ >/dev/null 2>conftest.err &&
+ grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
+ grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
+ grep $am__obj sub/conftest.Po > /dev/null 2>&1 &&
+ ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+ # icc doesn't choke on unknown options, it will just issue warnings
+ # or remarks (even with -Werror). So we grep stderr for any message
+ # that says an option was ignored or not supported.
+ # When given -MP, icc 7.0 and 7.1 complain thusly:
+ # icc: Command line warning: ignoring option '-M'; no argument required
+ # The diagnosis changed in icc 8.0:
+ # icc: Command line remark: option '-MP' not supported
+ if (grep 'ignoring option' conftest.err ||
+ grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
+ am_cv_$1_dependencies_compiler_type=$depmode
+ break
+ fi
+ fi
+ done
+
+ cd ..
+ rm -rf conftest.dir
+else
+ am_cv_$1_dependencies_compiler_type=none
+fi
+])
+AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type])
+AM_CONDITIONAL([am__fastdep$1], [
+ test "x$enable_dependency_tracking" != xno \
+ && test "$am_cv_$1_dependencies_compiler_type" = gcc3])
+])
+
+
+# AM_SET_DEPDIR
+# -------------
+# Choose a directory name for dependency files.
+# This macro is AC_REQUIREd in _AM_DEPENDENCIES.
+AC_DEFUN([AM_SET_DEPDIR],
+[AC_REQUIRE([AM_SET_LEADING_DOT])dnl
+AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl
+])
+
+
+# AM_DEP_TRACK
+# ------------
+AC_DEFUN([AM_DEP_TRACK],
+[AC_ARG_ENABLE([dependency-tracking], [dnl
+AS_HELP_STRING(
+ [--enable-dependency-tracking],
+ [do not reject slow dependency extractors])
+AS_HELP_STRING(
+ [--disable-dependency-tracking],
+ [speeds up one-time build])])
+if test "x$enable_dependency_tracking" != xno; then
+ am_depcomp="$ac_aux_dir/depcomp"
+ AMDEPBACKSLASH='\'
+ am__nodep='_no'
+fi
+AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno])
+AC_SUBST([AMDEPBACKSLASH])dnl
+_AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl
+AC_SUBST([am__nodep])dnl
+_AM_SUBST_NOTMAKE([am__nodep])dnl
+])
+
+# Generate code to set up dependency tracking. -*- Autoconf -*-
+
+# Copyright (C) 1999-2017 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+
+# _AM_OUTPUT_DEPENDENCY_COMMANDS
+# ------------------------------
+AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS],
+[{
+ # Older Autoconf quotes --file arguments for eval, but not when files
+ # are listed without --file. Let's play safe and only enable the eval
+ # if we detect the quoting.
+ case $CONFIG_FILES in
+ *\'*) eval set x "$CONFIG_FILES" ;;
+ *) set x $CONFIG_FILES ;;
+ esac
+ shift
+ for mf
+ do
+ # Strip MF so we end up with the name of the file.
+ mf=`echo "$mf" | sed -e 's/:.*$//'`
+ # Check whether this is an Automake generated Makefile or not.
+ # We used to match only the files named 'Makefile.in', but
+ # some people rename them; so instead we look at the file content.
+ # Grep'ing the first line is not enough: some people post-process
+ # each Makefile.in and add a new line on top of each file to say so.
+ # Grep'ing the whole file is not good either: AIX grep has a line
+ # limit of 2048, but all sed's we know have understand at least 4000.
+ if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then
+ dirpart=`AS_DIRNAME("$mf")`
+ else
+ continue
+ fi
+ # Extract the definition of DEPDIR, am__include, and am__quote
+ # from the Makefile without running 'make'.
+ DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
+ test -z "$DEPDIR" && continue
+ am__include=`sed -n 's/^am__include = //p' < "$mf"`
+ test -z "$am__include" && continue
+ am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
+ # Find all dependency output files, they are included files with
+ # $(DEPDIR) in their names. We invoke sed twice because it is the
+ # simplest approach to changing $(DEPDIR) to its actual value in the
+ # expansion.
+ for file in `sed -n "
+ s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \
+ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do
+ # Make sure the directory exists.
+ test -f "$dirpart/$file" && continue
+ fdir=`AS_DIRNAME(["$file"])`
+ AS_MKDIR_P([$dirpart/$fdir])
+ # echo "creating $dirpart/$file"
+ echo '# dummy' > "$dirpart/$file"
+ done
+ done
+}
+])# _AM_OUTPUT_DEPENDENCY_COMMANDS
+
+
+# AM_OUTPUT_DEPENDENCY_COMMANDS
+# -----------------------------
+# This macro should only be invoked once -- use via AC_REQUIRE.
+#
+# This code is only required when automatic dependency tracking
+# is enabled. FIXME. This creates each '.P' file that we will
+# need in order to bootstrap the dependency handling code.
+AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS],
+[AC_CONFIG_COMMANDS([depfiles],
+ [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS],
+ [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"])
+])
+
+# Do all the work for Automake. -*- Autoconf -*-
+
+# Copyright (C) 1996-2017 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This macro actually does too much. Some checks are only needed if
+# your package does certain things. But this isn't really a big deal.
+
+dnl Redefine AC_PROG_CC to automatically invoke _AM_PROG_CC_C_O.
+m4_define([AC_PROG_CC],
+m4_defn([AC_PROG_CC])
+[_AM_PROG_CC_C_O
+])
+
+# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE])
+# AM_INIT_AUTOMAKE([OPTIONS])
+# -----------------------------------------------
+# The call with PACKAGE and VERSION arguments is the old style
+# call (pre autoconf-2.50), which is being phased out. PACKAGE
+# and VERSION should now be passed to AC_INIT and removed from
+# the call to AM_INIT_AUTOMAKE.
+# We support both call styles for the transition. After
+# the next Automake release, Autoconf can make the AC_INIT
+# arguments mandatory, and then we can depend on a new Autoconf
+# release and drop the old call support.
+AC_DEFUN([AM_INIT_AUTOMAKE],
+[AC_PREREQ([2.65])dnl
+dnl Autoconf wants to disallow AM_ names. We explicitly allow
+dnl the ones we care about.
+m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl
+AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl
+AC_REQUIRE([AC_PROG_INSTALL])dnl
+if test "`cd $srcdir && pwd`" != "`pwd`"; then
+ # Use -I$(srcdir) only when $(srcdir) != ., so that make's output
+ # is not polluted with repeated "-I."
+ AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl
+ # test to see if srcdir already configured
+ if test -f $srcdir/config.status; then
+ AC_MSG_ERROR([source directory already configured; run "make distclean" there first])
+ fi
+fi
+
+# test whether we have cygpath
+if test -z "$CYGPATH_W"; then
+ if (cygpath --version) >/dev/null 2>/dev/null; then
+ CYGPATH_W='cygpath -w'
+ else
+ CYGPATH_W=echo
+ fi
+fi
+AC_SUBST([CYGPATH_W])
+
+# Define the identity of the package.
+dnl Distinguish between old-style and new-style calls.
+m4_ifval([$2],
+[AC_DIAGNOSE([obsolete],
+ [$0: two- and three-arguments forms are deprecated.])
+m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl
+ AC_SUBST([PACKAGE], [$1])dnl
+ AC_SUBST([VERSION], [$2])],
+[_AM_SET_OPTIONS([$1])dnl
+dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT.
+m4_if(
+ m4_ifdef([AC_PACKAGE_NAME], [ok]):m4_ifdef([AC_PACKAGE_VERSION], [ok]),
+ [ok:ok],,
+ [m4_fatal([AC_INIT should be called with package and version arguments])])dnl
+ AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl
+ AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl
+
+_AM_IF_OPTION([no-define],,
+[AC_DEFINE_UNQUOTED([PACKAGE], ["$PACKAGE"], [Name of package])
+ AC_DEFINE_UNQUOTED([VERSION], ["$VERSION"], [Version number of package])])dnl
+
+# Some tools Automake needs.
+AC_REQUIRE([AM_SANITY_CHECK])dnl
+AC_REQUIRE([AC_ARG_PROGRAM])dnl
+AM_MISSING_PROG([ACLOCAL], [aclocal-${am__api_version}])
+AM_MISSING_PROG([AUTOCONF], [autoconf])
+AM_MISSING_PROG([AUTOMAKE], [automake-${am__api_version}])
+AM_MISSING_PROG([AUTOHEADER], [autoheader])
+AM_MISSING_PROG([MAKEINFO], [makeinfo])
+AC_REQUIRE([AM_PROG_INSTALL_SH])dnl
+AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl
+AC_REQUIRE([AC_PROG_MKDIR_P])dnl
+# For better backward compatibility. To be removed once Automake 1.9.x
+# dies out for good. For more background, see:
+# <http://lists.gnu.org/archive/html/automake/2012-07/msg00001.html>
+# <http://lists.gnu.org/archive/html/automake/2012-07/msg00014.html>
+AC_SUBST([mkdir_p], ['$(MKDIR_P)'])
+# We need awk for the "check" target (and possibly the TAP driver). The
+# system "awk" is bad on some platforms.
+AC_REQUIRE([AC_PROG_AWK])dnl
+AC_REQUIRE([AC_PROG_MAKE_SET])dnl
+AC_REQUIRE([AM_SET_LEADING_DOT])dnl
+_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])],
+ [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])],
+ [_AM_PROG_TAR([v7])])])
+_AM_IF_OPTION([no-dependencies],,
+[AC_PROVIDE_IFELSE([AC_PROG_CC],
+ [_AM_DEPENDENCIES([CC])],
+ [m4_define([AC_PROG_CC],
+ m4_defn([AC_PROG_CC])[_AM_DEPENDENCIES([CC])])])dnl
+AC_PROVIDE_IFELSE([AC_PROG_CXX],
+ [_AM_DEPENDENCIES([CXX])],
+ [m4_define([AC_PROG_CXX],
+ m4_defn([AC_PROG_CXX])[_AM_DEPENDENCIES([CXX])])])dnl
+AC_PROVIDE_IFELSE([AC_PROG_OBJC],
+ [_AM_DEPENDENCIES([OBJC])],
+ [m4_define([AC_PROG_OBJC],
+ m4_defn([AC_PROG_OBJC])[_AM_DEPENDENCIES([OBJC])])])dnl
+AC_PROVIDE_IFELSE([AC_PROG_OBJCXX],
+ [_AM_DEPENDENCIES([OBJCXX])],
+ [m4_define([AC_PROG_OBJCXX],
+ m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])dnl
+])
+AC_REQUIRE([AM_SILENT_RULES])dnl
+dnl The testsuite driver may need to know about EXEEXT, so add the
+dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This
+dnl macro is hooked onto _AC_COMPILER_EXEEXT early, see below.
+AC_CONFIG_COMMANDS_PRE(dnl
+[m4_provide_if([_AM_COMPILER_EXEEXT],
+ [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl
+
+# POSIX will say in a future version that running "rm -f" with no argument
+# is OK; and we want to be able to make that assumption in our Makefile
+# recipes. So use an aggressive probe to check that the usage we want is
+# actually supported "in the wild" to an acceptable degree.
+# See automake bug#10828.
+# To make any issue more visible, cause the running configure to be aborted
+# by default if the 'rm' program in use doesn't match our expectations; the
+# user can still override this though.
+if rm -f && rm -fr && rm -rf; then : OK; else
+ cat >&2 <<'END'
+Oops!
+
+Your 'rm' program seems unable to run without file operands specified
+on the command line, even when the '-f' option is present. This is contrary
+to the behaviour of most rm programs out there, and not conforming with
+the upcoming POSIX standard: <http://austingroupbugs.net/view.php?id=542>
+
+Please tell bug-automake@gnu.org about your system, including the value
+of your $PATH and any error possibly output before this message. This
+can help us improve future automake versions.
+
+END
+ if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then
+ echo 'Configuration will proceed anyway, since you have set the' >&2
+ echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2
+ echo >&2
+ else
+ cat >&2 <<'END'
+Aborting the configuration process, to ensure you take notice of the issue.
+
+You can download and install GNU coreutils to get an 'rm' implementation
+that behaves properly: <http://www.gnu.org/software/coreutils/>.
+
+If you want to complete the configuration process using your problematic
+'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM
+to "yes", and re-run configure.
+
+END
+ AC_MSG_ERROR([Your 'rm' program is bad, sorry.])
+ fi
+fi
+dnl The trailing newline in this macro's definition is deliberate, for
+dnl backward compatibility and to allow trailing 'dnl'-style comments
+dnl after the AM_INIT_AUTOMAKE invocation. See automake bug#16841.
+])
+
+dnl Hook into '_AC_COMPILER_EXEEXT' early to learn its expansion. Do not
+dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further
+dnl mangled by Autoconf and run in a shell conditional statement.
+m4_define([_AC_COMPILER_EXEEXT],
+m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])])
+
+# When config.status generates a header, we must update the stamp-h file.
+# This file resides in the same directory as the config header
+# that is generated. The stamp files are numbered to have different names.
+
+# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the
+# loop where config.status creates the headers, so we can generate
+# our stamp files there.
+AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK],
+[# Compute $1's index in $config_headers.
+_am_arg=$1
+_am_stamp_count=1
+for _am_header in $config_headers :; do
+ case $_am_header in
+ $_am_arg | $_am_arg:* )
+ break ;;
+ * )
+ _am_stamp_count=`expr $_am_stamp_count + 1` ;;
+ esac
+done
+echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count])
+
+# Copyright (C) 2001-2017 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_PROG_INSTALL_SH
+# ------------------
+# Define $install_sh.
+AC_DEFUN([AM_PROG_INSTALL_SH],
+[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+if test x"${install_sh+set}" != xset; then
+ case $am_aux_dir in
+ *\ * | *\ *)
+ install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;;
+ *)
+ install_sh="\${SHELL} $am_aux_dir/install-sh"
+ esac
+fi
+AC_SUBST([install_sh])])
+
+# Copyright (C) 2003-2017 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# Check whether the underlying file-system supports filenames
+# with a leading dot. For instance MS-DOS doesn't.
+AC_DEFUN([AM_SET_LEADING_DOT],
+[rm -rf .tst 2>/dev/null
+mkdir .tst 2>/dev/null
+if test -d .tst; then
+ am__leading_dot=.
+else
+ am__leading_dot=_
+fi
+rmdir .tst 2>/dev/null
+AC_SUBST([am__leading_dot])])
+
+# Add --enable-maintainer-mode option to configure. -*- Autoconf -*-
+# From Jim Meyering
+
+# Copyright (C) 1996-2017 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_MAINTAINER_MODE([DEFAULT-MODE])
+# ----------------------------------
+# Control maintainer-specific portions of Makefiles.
+# Default is to disable them, unless 'enable' is passed literally.
+# For symmetry, 'disable' may be passed as well. Anyway, the user
+# can override the default with the --enable/--disable switch.
+AC_DEFUN([AM_MAINTAINER_MODE],
+[m4_case(m4_default([$1], [disable]),
+ [enable], [m4_define([am_maintainer_other], [disable])],
+ [disable], [m4_define([am_maintainer_other], [enable])],
+ [m4_define([am_maintainer_other], [enable])
+ m4_warn([syntax], [unexpected argument to AM@&t@_MAINTAINER_MODE: $1])])
+AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles])
+ dnl maintainer-mode's default is 'disable' unless 'enable' is passed
+ AC_ARG_ENABLE([maintainer-mode],
+ [AS_HELP_STRING([--]am_maintainer_other[-maintainer-mode],
+ am_maintainer_other[ make rules and dependencies not useful
+ (and sometimes confusing) to the casual installer])],
+ [USE_MAINTAINER_MODE=$enableval],
+ [USE_MAINTAINER_MODE=]m4_if(am_maintainer_other, [enable], [no], [yes]))
+ AC_MSG_RESULT([$USE_MAINTAINER_MODE])
+ AM_CONDITIONAL([MAINTAINER_MODE], [test $USE_MAINTAINER_MODE = yes])
+ MAINT=$MAINTAINER_MODE_TRUE
+ AC_SUBST([MAINT])dnl
+]
+)
+
+# Check to see how 'make' treats includes. -*- Autoconf -*-
+
+# Copyright (C) 2001-2017 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_MAKE_INCLUDE()
+# -----------------
+# Check to see how make treats includes.
+AC_DEFUN([AM_MAKE_INCLUDE],
+[am_make=${MAKE-make}
+cat > confinc << 'END'
+am__doit:
+ @echo this is the am__doit target
+.PHONY: am__doit
+END
+# If we don't find an include directive, just comment out the code.
+AC_MSG_CHECKING([for style of include used by $am_make])
+am__include="#"
+am__quote=
+_am_result=none
+# First try GNU make style include.
+echo "include confinc" > confmf
+# Ignore all kinds of additional output from 'make'.
+case `$am_make -s -f confmf 2> /dev/null` in #(
+*the\ am__doit\ target*)
+ am__include=include
+ am__quote=
+ _am_result=GNU
+ ;;
+esac
+# Now try BSD make style include.
+if test "$am__include" = "#"; then
+ echo '.include "confinc"' > confmf
+ case `$am_make -s -f confmf 2> /dev/null` in #(
+ *the\ am__doit\ target*)
+ am__include=.include
+ am__quote="\""
+ _am_result=BSD
+ ;;
+ esac
+fi
+AC_SUBST([am__include])
+AC_SUBST([am__quote])
+AC_MSG_RESULT([$_am_result])
+rm -f confinc confmf
+])
+
+# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*-
+
+# Copyright (C) 1997-2017 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_MISSING_PROG(NAME, PROGRAM)
+# ------------------------------
+AC_DEFUN([AM_MISSING_PROG],
+[AC_REQUIRE([AM_MISSING_HAS_RUN])
+$1=${$1-"${am_missing_run}$2"}
+AC_SUBST($1)])
+
+# AM_MISSING_HAS_RUN
+# ------------------
+# Define MISSING if not defined so far and test if it is modern enough.
+# If it is, set am_missing_run to use it, otherwise, to nothing.
+AC_DEFUN([AM_MISSING_HAS_RUN],
+[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+AC_REQUIRE_AUX_FILE([missing])dnl
+if test x"${MISSING+set}" != xset; then
+ case $am_aux_dir in
+ *\ * | *\ *)
+ MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;;
+ *)
+ MISSING="\${SHELL} $am_aux_dir/missing" ;;
+ esac
+fi
+# Use eval to expand $SHELL
+if eval "$MISSING --is-lightweight"; then
+ am_missing_run="$MISSING "
+else
+ am_missing_run=
+ AC_MSG_WARN(['missing' script is too old or missing])
+fi
+])
+
+# -*- Autoconf -*-
+# Obsolete and "removed" macros, that must however still report explicit
+# error messages when used, to smooth transition.
+#
+# Copyright (C) 1996-2017 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+AC_DEFUN([AM_CONFIG_HEADER],
+[AC_DIAGNOSE([obsolete],
+['$0': this macro is obsolete.
+You should use the 'AC][_CONFIG_HEADERS' macro instead.])dnl
+AC_CONFIG_HEADERS($@)])
+
+AC_DEFUN([AM_PROG_CC_STDC],
+[AC_PROG_CC
+am_cv_prog_cc_stdc=$ac_cv_prog_cc_stdc
+AC_DIAGNOSE([obsolete],
+['$0': this macro is obsolete.
+You should simply use the 'AC][_PROG_CC' macro instead.
+Also, your code should no longer depend upon 'am_cv_prog_cc_stdc',
+but upon 'ac_cv_prog_cc_stdc'.])])
+
+AC_DEFUN([AM_C_PROTOTYPES],
+ [AC_FATAL([automatic de-ANSI-fication support has been removed])])
+AU_DEFUN([fp_C_PROTOTYPES], [AM_C_PROTOTYPES])
+
+# Helper functions for option handling. -*- Autoconf -*-
+
+# Copyright (C) 2001-2017 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# _AM_MANGLE_OPTION(NAME)
+# -----------------------
+AC_DEFUN([_AM_MANGLE_OPTION],
+[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])])
+
+# _AM_SET_OPTION(NAME)
+# --------------------
+# Set option NAME. Presently that only means defining a flag for this option.
+AC_DEFUN([_AM_SET_OPTION],
+[m4_define(_AM_MANGLE_OPTION([$1]), [1])])
+
+# _AM_SET_OPTIONS(OPTIONS)
+# ------------------------
+# OPTIONS is a space-separated list of Automake options.
+AC_DEFUN([_AM_SET_OPTIONS],
+[m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])])
+
+# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET])
+# -------------------------------------------
+# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise.
+AC_DEFUN([_AM_IF_OPTION],
+[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])])
+
+# Copyright (C) 1999-2017 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# _AM_PROG_CC_C_O
+# ---------------
+# Like AC_PROG_CC_C_O, but changed for automake. We rewrite AC_PROG_CC
+# to automatically call this.
+AC_DEFUN([_AM_PROG_CC_C_O],
+[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+AC_REQUIRE_AUX_FILE([compile])dnl
+AC_LANG_PUSH([C])dnl
+AC_CACHE_CHECK(
+ [whether $CC understands -c and -o together],
+ [am_cv_prog_cc_c_o],
+ [AC_LANG_CONFTEST([AC_LANG_PROGRAM([])])
+ # Make sure it works both with $CC and with simple cc.
+ # Following AC_PROG_CC_C_O, we do the test twice because some
+ # compilers refuse to overwrite an existing .o file with -o,
+ # though they will create one.
+ am_cv_prog_cc_c_o=yes
+ for am_i in 1 2; do
+ if AM_RUN_LOG([$CC -c conftest.$ac_ext -o conftest2.$ac_objext]) \
+ && test -f conftest2.$ac_objext; then
+ : OK
+ else
+ am_cv_prog_cc_c_o=no
+ break
+ fi
+ done
+ rm -f core conftest*
+ unset am_i])
+if test "$am_cv_prog_cc_c_o" != yes; then
+ # Losing compiler, so override with the script.
+ # FIXME: It is wrong to rewrite CC.
+ # But if we don't then we get into trouble of one sort or another.
+ # A longer-term fix would be to have automake use am__CC in this case,
+ # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)"
+ CC="$am_aux_dir/compile $CC"
+fi
+AC_LANG_POP([C])])
+
+# For backward compatibility.
+AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])])
+
+# Copyright (C) 2001-2017 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_RUN_LOG(COMMAND)
+# -------------------
+# Run COMMAND, save the exit status in ac_status, and log it.
+# (This has been adapted from Autoconf's _AC_RUN_LOG macro.)
+AC_DEFUN([AM_RUN_LOG],
+[{ echo "$as_me:$LINENO: $1" >&AS_MESSAGE_LOG_FD
+ ($1) >&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
+ (exit $ac_status); }])
+
+# Check to make sure that the build environment is sane. -*- Autoconf -*-
+
+# Copyright (C) 1996-2017 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_SANITY_CHECK
+# ---------------
+AC_DEFUN([AM_SANITY_CHECK],
+[AC_MSG_CHECKING([whether build environment is sane])
+# Reject unsafe characters in $srcdir or the absolute working directory
+# name. Accept space and tab only in the latter.
+am_lf='
+'
+case `pwd` in
+ *[[\\\"\#\$\&\'\`$am_lf]]*)
+ AC_MSG_ERROR([unsafe absolute working directory name]);;
+esac
+case $srcdir in
+ *[[\\\"\#\$\&\'\`$am_lf\ \ ]]*)
+ AC_MSG_ERROR([unsafe srcdir value: '$srcdir']);;
+esac
+
+# Do 'set' in a subshell so we don't clobber the current shell's
+# arguments. Must try -L first in case configure is actually a
+# symlink; some systems play weird games with the mod time of symlinks
+# (eg FreeBSD returns the mod time of the symlink's containing
+# directory).
+if (
+ am_has_slept=no
+ for am_try in 1 2; do
+ echo "timestamp, slept: $am_has_slept" > conftest.file
+ set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null`
+ if test "$[*]" = "X"; then
+ # -L didn't work.
+ set X `ls -t "$srcdir/configure" conftest.file`
+ fi
+ if test "$[*]" != "X $srcdir/configure conftest.file" \
+ && test "$[*]" != "X conftest.file $srcdir/configure"; then
+
+ # If neither matched, then we have a broken ls. This can happen
+ # if, for instance, CONFIG_SHELL is bash and it inherits a
+ # broken ls alias from the environment. This has actually
+ # happened. Such a system could not be considered "sane".
+ AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken
+ alias in your environment])
+ fi
+ if test "$[2]" = conftest.file || test $am_try -eq 2; then
+ break
+ fi
+ # Just in case.
+ sleep 1
+ am_has_slept=yes
+ done
+ test "$[2]" = conftest.file
+ )
+then
+ # Ok.
+ :
+else
+ AC_MSG_ERROR([newly created file is older than distributed files!
+Check your system clock])
+fi
+AC_MSG_RESULT([yes])
+# If we didn't sleep, we still need to ensure time stamps of config.status and
+# generated files are strictly newer.
+am_sleep_pid=
+if grep 'slept: no' conftest.file >/dev/null 2>&1; then
+ ( sleep 1 ) &
+ am_sleep_pid=$!
+fi
+AC_CONFIG_COMMANDS_PRE(
+ [AC_MSG_CHECKING([that generated files are newer than configure])
+ if test -n "$am_sleep_pid"; then
+ # Hide warnings about reused PIDs.
+ wait $am_sleep_pid 2>/dev/null
+ fi
+ AC_MSG_RESULT([done])])
+rm -f conftest.file
+])
+
+# Copyright (C) 2009-2017 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_SILENT_RULES([DEFAULT])
+# --------------------------
+# Enable less verbose build rules; with the default set to DEFAULT
+# ("yes" being less verbose, "no" or empty being verbose).
+AC_DEFUN([AM_SILENT_RULES],
+[AC_ARG_ENABLE([silent-rules], [dnl
+AS_HELP_STRING(
+ [--enable-silent-rules],
+ [less verbose build output (undo: "make V=1")])
+AS_HELP_STRING(
+ [--disable-silent-rules],
+ [verbose build output (undo: "make V=0")])dnl
+])
+case $enable_silent_rules in @%:@ (((
+ yes) AM_DEFAULT_VERBOSITY=0;;
+ no) AM_DEFAULT_VERBOSITY=1;;
+ *) AM_DEFAULT_VERBOSITY=m4_if([$1], [yes], [0], [1]);;
+esac
+dnl
+dnl A few 'make' implementations (e.g., NonStop OS and NextStep)
+dnl do not support nested variable expansions.
+dnl See automake bug#9928 and bug#10237.
+am_make=${MAKE-make}
+AC_CACHE_CHECK([whether $am_make supports nested variables],
+ [am_cv_make_support_nested_variables],
+ [if AS_ECHO([['TRUE=$(BAR$(V))
+BAR0=false
+BAR1=true
+V=1
+am__doit:
+ @$(TRUE)
+.PHONY: am__doit']]) | $am_make -f - >/dev/null 2>&1; then
+ am_cv_make_support_nested_variables=yes
+else
+ am_cv_make_support_nested_variables=no
+fi])
+if test $am_cv_make_support_nested_variables = yes; then
+ dnl Using '$V' instead of '$(V)' breaks IRIX make.
+ AM_V='$(V)'
+ AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)'
+else
+ AM_V=$AM_DEFAULT_VERBOSITY
+ AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY
+fi
+AC_SUBST([AM_V])dnl
+AM_SUBST_NOTMAKE([AM_V])dnl
+AC_SUBST([AM_DEFAULT_V])dnl
+AM_SUBST_NOTMAKE([AM_DEFAULT_V])dnl
+AC_SUBST([AM_DEFAULT_VERBOSITY])dnl
+AM_BACKSLASH='\'
+AC_SUBST([AM_BACKSLASH])dnl
+_AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl
+])
+
+# Copyright (C) 2001-2017 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_PROG_INSTALL_STRIP
+# ---------------------
+# One issue with vendor 'install' (even GNU) is that you can't
+# specify the program used to strip binaries. This is especially
+# annoying in cross-compiling environments, where the build's strip
+# is unlikely to handle the host's binaries.
+# Fortunately install-sh will honor a STRIPPROG variable, so we
+# always use install-sh in "make install-strip", and initialize
+# STRIPPROG with the value of the STRIP variable (set by the user).
+AC_DEFUN([AM_PROG_INSTALL_STRIP],
+[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl
+# Installed binaries are usually stripped using 'strip' when the user
+# run "make install-strip". However 'strip' might not be the right
+# tool to use in cross-compilation environments, therefore Automake
+# will honor the 'STRIP' environment variable to overrule this program.
+dnl Don't test for $cross_compiling = yes, because it might be 'maybe'.
+if test "$cross_compiling" != no; then
+ AC_CHECK_TOOL([STRIP], [strip], :)
+fi
+INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
+AC_SUBST([INSTALL_STRIP_PROGRAM])])
+
+# Copyright (C) 2006-2017 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# _AM_SUBST_NOTMAKE(VARIABLE)
+# ---------------------------
+# Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in.
+# This macro is traced by Automake.
+AC_DEFUN([_AM_SUBST_NOTMAKE])
+
+# AM_SUBST_NOTMAKE(VARIABLE)
+# --------------------------
+# Public sister of _AM_SUBST_NOTMAKE.
+AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)])
+
+# Check how to create a tarball. -*- Autoconf -*-
+
+# Copyright (C) 2004-2017 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# _AM_PROG_TAR(FORMAT)
+# --------------------
+# Check how to create a tarball in format FORMAT.
+# FORMAT should be one of 'v7', 'ustar', or 'pax'.
+#
+# Substitute a variable $(am__tar) that is a command
+# writing to stdout a FORMAT-tarball containing the directory
+# $tardir.
+# tardir=directory && $(am__tar) > result.tar
+#
+# Substitute a variable $(am__untar) that extract such
+# a tarball read from stdin.
+# $(am__untar) < result.tar
+#
+AC_DEFUN([_AM_PROG_TAR],
+[# Always define AMTAR for backward compatibility. Yes, it's still used
+# in the wild :-( We should find a proper way to deprecate it ...
+AC_SUBST([AMTAR], ['$${TAR-tar}'])
+
+# We'll loop over all known methods to create a tar archive until one works.
+_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none'
+
+m4_if([$1], [v7],
+ [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'],
+
+ [m4_case([$1],
+ [ustar],
+ [# The POSIX 1988 'ustar' format is defined with fixed-size fields.
+ # There is notably a 21 bits limit for the UID and the GID. In fact,
+ # the 'pax' utility can hang on bigger UID/GID (see automake bug#8343
+ # and bug#13588).
+ am_max_uid=2097151 # 2^21 - 1
+ am_max_gid=$am_max_uid
+ # The $UID and $GID variables are not portable, so we need to resort
+ # to the POSIX-mandated id(1) utility. Errors in the 'id' calls
+ # below are definitely unexpected, so allow the users to see them
+ # (that is, avoid stderr redirection).
+ am_uid=`id -u || echo unknown`
+ am_gid=`id -g || echo unknown`
+ AC_MSG_CHECKING([whether UID '$am_uid' is supported by ustar format])
+ if test $am_uid -le $am_max_uid; then
+ AC_MSG_RESULT([yes])
+ else
+ AC_MSG_RESULT([no])
+ _am_tools=none
+ fi
+ AC_MSG_CHECKING([whether GID '$am_gid' is supported by ustar format])
+ if test $am_gid -le $am_max_gid; then
+ AC_MSG_RESULT([yes])
+ else
+ AC_MSG_RESULT([no])
+ _am_tools=none
+ fi],
+
+ [pax],
+ [],
+
+ [m4_fatal([Unknown tar format])])
+
+ AC_MSG_CHECKING([how to create a $1 tar archive])
+
+ # Go ahead even if we have the value already cached. We do so because we
+ # need to set the values for the 'am__tar' and 'am__untar' variables.
+ _am_tools=${am_cv_prog_tar_$1-$_am_tools}
+
+ for _am_tool in $_am_tools; do
+ case $_am_tool in
+ gnutar)
+ for _am_tar in tar gnutar gtar; do
+ AM_RUN_LOG([$_am_tar --version]) && break
+ done
+ am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"'
+ am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"'
+ am__untar="$_am_tar -xf -"
+ ;;
+ plaintar)
+ # Must skip GNU tar: if it does not support --format= it doesn't create
+ # ustar tarball either.
+ (tar --version) >/dev/null 2>&1 && continue
+ am__tar='tar chf - "$$tardir"'
+ am__tar_='tar chf - "$tardir"'
+ am__untar='tar xf -'
+ ;;
+ pax)
+ am__tar='pax -L -x $1 -w "$$tardir"'
+ am__tar_='pax -L -x $1 -w "$tardir"'
+ am__untar='pax -r'
+ ;;
+ cpio)
+ am__tar='find "$$tardir" -print | cpio -o -H $1 -L'
+ am__tar_='find "$tardir" -print | cpio -o -H $1 -L'
+ am__untar='cpio -i -H $1 -d'
+ ;;
+ none)
+ am__tar=false
+ am__tar_=false
+ am__untar=false
+ ;;
+ esac
+
+ # If the value was cached, stop now. We just wanted to have am__tar
+ # and am__untar set.
+ test -n "${am_cv_prog_tar_$1}" && break
+
+ # tar/untar a dummy directory, and stop if the command works.
+ rm -rf conftest.dir
+ mkdir conftest.dir
+ echo GrepMe > conftest.dir/file
+ AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar])
+ rm -rf conftest.dir
+ if test -s conftest.tar; then
+ AM_RUN_LOG([$am__untar <conftest.tar])
+ AM_RUN_LOG([cat conftest.dir/file])
+ grep GrepMe conftest.dir/file >/dev/null 2>&1 && break
+ fi
+ done
+ rm -rf conftest.dir
+
+ AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool])
+ AC_MSG_RESULT([$am_cv_prog_tar_$1])])
+
+AC_SUBST([am__tar])
+AC_SUBST([am__untar])
+]) # _AM_PROG_TAR
+
+m4_include([m4/ax_append_compile_flags.m4])
+m4_include([m4/ax_append_flag.m4])
+m4_include([m4/ax_check_compile_flag.m4])
+m4_include([m4/ax_check_define.m4])
+m4_include([m4/ax_cxx_compile_stdcxx.m4])
+m4_include([m4/ax_pthread.m4])
+m4_include([m4/ax_require_defined.m4])
diff --git a/toolkit/crashreporter/google-breakpad/android/common-functions.sh b/toolkit/crashreporter/google-breakpad/android/common-functions.sh
new file mode 100755
index 0000000000..c00e34f997
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/android/common-functions.sh
@@ -0,0 +1,372 @@
+# 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.
+
+# Collection of common shell functions for 'run-checks.sh' et 'test-shell.sh'
+
+# All internal variables and functions use an underscore as a prefix
+# (e.g. _VERBOSE, _ALL_CLEANUPS, etc..).
+
+# Sanitize the environment
+export LANG=C
+export LC_ALL=C
+
+if [ "$BASH_VERSION" ]; then
+ set -o posix
+fi
+
+# Utility functions
+
+_ALL_CLEANUPS=
+
+# Register a function to be called when the script exits, even in case of
+# Ctrl-C, logout, etc.
+# $1: function name.
+atexit () {
+ if [ -z "$_ALL_CLEANUPS" ]; then
+ _ALL_CLEANUPS=$1
+ # Ensure a clean exit when the script is:
+ # - Exiting normally (EXIT)
+ # - Interrupted by Ctrl-C (INT)
+ # - Interrupted by log out (HUP)
+ # - Being asked to quit nicely (TERM)
+ # - Being asked to quit and dump core (QUIT)
+ trap "_exit_cleanups \$?" EXIT INT HUP QUIT TERM
+ else
+ _ALL_CLEANUPS="$_ALL_CLEANUPS $1"
+ fi
+}
+
+# Called on exit if at least one function was registered with atexit
+# $1: final exit status code
+_exit_cleanups () {
+ local CLEANUP CLEANUPS
+ # Ignore calls to atexit during cleanups
+ CLEANUPS=$_ALL_CLEANUPS
+ _ALL_CLEANUPS=
+ for CLEANUP in $CLEANUPS; do
+ ($CLEANUP)
+ done
+ exit "$@"
+}
+
+
+
+
+# Dump a panic message then exit.
+# $1+: message
+panic () {
+ echo "ERROR: $@" >&2
+ exit 1
+}
+
+# If the previous command failed, dump a panic message then exit.
+# $1+: message.
+fail_panic () {
+ if [ $? != 0 ]; then
+ panic "$@"
+ fi;
+}
+
+_VERBOSE=0
+
+# Increase verbosity for dump/log/run/run2 functions
+increase_verbosity () {
+ _VERBOSE=$(( $_VERBOSE + 1 ))
+}
+
+# Decrease verbosity
+decrease_verbosity () {
+ _VERBOSE=$(( $_VERBOSE - 1 ))
+}
+
+# Returns success iff verbosity level is higher than a specific value
+# $1: verbosity level
+verbosity_is_higher_than () {
+ [ "$_VERBOSE" -gt "$1" ]
+}
+
+# Returns success iff verbosity level is lower than a specific value
+# $1: verbosity level
+verbosity_is_lower_than () {
+ [ "$_VERBOSE" -le "$1" ]
+}
+
+# Dump message to stdout, unless verbosity is < 0, i.e. --quiet was called
+# $1+: message
+dump () {
+ if [ "$_VERBOSE" -ge 0 ]; then
+ printf "%s\n" "$*"
+ fi
+}
+
+# If --verbose was used, dump a message to stdout.
+# $1+: message
+log () {
+ if [ "$_VERBOSE" -ge 1 ]; then
+ printf "%s\n" "$*"
+ fi
+}
+
+_RUN_LOG=
+
+# Set a run log file that can be used to collect the output of commands that
+# are not displayed.
+set_run_log () {
+ _RUN_LOG=$1
+}
+
+# Run a command. Output depends on $_VERBOSE:
+# $_VERBOSE <= 0: Run command, store output into the run log
+# $_VERBOSE >= 1: Dump command, run it, output goest to stdout
+# Note: Ideally, the command's output would go to the run log for $_VERBOSE >= 1
+# but the 'tee' tool doesn't preserve the status code of its input pipe
+# in case of error.
+run () {
+ local LOGILE
+ if [ "$_RUN_LOG" ]; then
+ LOGFILE=$_RUN_LOG
+ else
+ LOGFILE=/dev/null
+ fi
+
+ if [ "$_VERBOSE" -ge 1 ]; then
+ echo "COMMAND: $@"
+ "$@"
+ else
+ "$@" >>$LOGFILE 2>&1
+ fi
+}
+
+# Same as run(), but only dump command output for $_VERBOSE >= 2
+run2 () {
+ local LOGILE
+ if [ "$_RUN_LOG" ]; then
+ LOGFILE=$_RUN_LOG
+ else
+ LOGFILE=/dev/null
+ fi
+
+ if [ "$_VERBOSE" -ge 1 ]; then
+ echo "COMMAND: $@"
+ fi
+ if [ "$_VERBOSE" -ge 2 ]; then
+ "$@"
+ else
+ "$@" >>$LOGFILE 2>&1
+ fi
+}
+
+# Extract number of cores to speed up the builds
+# Out: number of CPU cores
+get_core_count () {
+ case $(uname -s) in
+ Linux)
+ grep -c -e '^processor' /proc/cpuinfo
+ ;;
+ Darwin)
+ sysctl -n hw.ncpu
+ ;;
+ CYGWIN*|*_NT-*)
+ echo $NUMBER_OF_PROCESSORS
+ ;;
+ *)
+ echo 1
+ ;;
+ esac
+}
+
+
+# Check for the Android ADB program.
+#
+# On success, return nothing, but updates internal variables so later calls to
+# adb_shell, adb_push, etc.. will work. You can get the path to the ADB program
+# with adb_get_program if needed.
+#
+# On failure, returns 1, and updates the internal adb error message, which can
+# be retrieved with adb_get_error.
+#
+# $1: optional ADB program path.
+# Return: success or failure.
+_ADB=
+_ADB_STATUS=
+_ADB_ERROR=
+
+adb_check () {
+ # First, try to find the executable in the path, or the SDK install dir.
+ _ADB=$1
+ if [ -z "$_ADB" ]; then
+ _ADB=$(which adb 2>/dev/null)
+ if [ -z "$_ADB" -a "$ANDROID_SDK_ROOT" ]; then
+ _ADB=$ANDROID_SDK_ROOT/platform-tools/adb
+ if [ ! -f "$_ADB" ]; then
+ _ADB=
+ fi
+ fi
+ if [ -z "$_ADB" ]; then
+ _ADB_STATUS=1
+ _ADB_ERROR="The Android 'adb' tool is not in your path."
+ return 1
+ fi
+ fi
+
+ log "Found ADB program: $_ADB"
+
+ # Check that it works correctly
+ local ADB_VERSION
+ ADB_VERSION=$("$_ADB" version 2>/dev/null)
+ case $ADB_VERSION in
+ "Android Debug Bridge "*) # Pass
+ log "Found ADB version: $ADB_VERSION"
+ ;;
+ *) # Fail
+ _ADB_ERROR="Your ADB binary reports a bad version ($ADB_VERSION): $_ADB"
+ _ADB_STATUS=1
+ return 1
+ esac
+
+ _ADB_STATUS=0
+ return 0
+}
+
+
+# Return the path to the Android ADB program, if correctly detected.
+# On failure, return the empty string.
+# Out: ADB program path (or empty on failure)
+# Return: success or failure.
+adb_get_program () {
+ # Return cached value as soon as possible.
+ if [ -z "$_ADB_STATUS" ]; then
+ adb_check $1
+ fi
+ echo "$_ADB"
+ return $_ADB_STATUS
+}
+
+# Return the error corresponding to the last ADB function failure.
+adb_get_error () {
+ echo "$_ADB_ERROR"
+}
+
+# Check that there is one device connected through ADB.
+# In case of failure, use adb_get_error to know why this failed.
+# $1: Optional adb program path
+# Return: success or failure.
+_ADB_DEVICE=
+_ADB_DEVICE_STATUS=
+adb_check_device () {
+ if [ "$_ADB_DEVICE_STATUS" ]; then
+ return $_ADB_DEVICE_STATUS
+ fi
+
+ # Check for ADB.
+ if ! adb_check $1; then
+ _ADB_DEVICE_STATUS=$_ADB_STATUS
+ return 1
+ fi
+
+ local ADB_DEVICES NUM_DEVICES FINGERPRINT
+
+ # Count the number of connected devices.
+ ADB_DEVICES=$("$_ADB" devices 2>/dev/null | awk '$2 == "device" { print $1; }')
+ NUM_DEVICES=$(echo "$ADB_DEVICES" | wc -l)
+ case $NUM_DEVICES in
+ 0)
+ _ADB_ERROR="No Android device connected. Please connect one to your machine."
+ _ADB_DEVICE_STATUS=1
+ return 1
+ ;;
+ 1) # Pass
+ # Ensure the same device will be called in later adb_shell calls.
+ export ANDROID_SERIAL=$ADB_DEVICES
+ ;;
+ *) # 2 or more devices.
+ if [ "$ANDROID_SERIAL" ]; then
+ ADB_DEVICES=$ANDROID_SERIAL
+ NUM_DEVICES=1
+ else
+ _ADB_ERROR="More than one Android device connected. \
+Please define ANDROID_SERIAL in your environment"
+ _ADB_DEVICE_STATUS=1
+ return 1
+ fi
+ ;;
+ esac
+
+ _ADB_DEVICE_STATUS=0
+ _ADB_DEVICE=$ADB_DEVICES
+
+ FINGERPRINT=$(adb_shell getprop ro.build.fingerprint)
+ log "Using ADB device: $ANDROID_SERIAL ($FINGERPRINT)"
+ return 0
+}
+
+# The 'adb shell' command is pretty hopeless, try to make sense of it by:
+# 1/ Removing trailing \r from line endings.
+# 2/ Ensuring the function returns the command's status code.
+#
+# $1+: Command
+# Out: command output (stdout + stderr combined)
+# Return: command exit status
+adb_shell () {
+ local RET ADB_LOG
+ # Check for ADB device.
+ adb_check_device || return 1
+ ADB_LOG=$(mktemp "${TMPDIR:-/tmp}/adb-XXXXXXXX")
+ "$_ADB" shell "$@" ";" echo \$? > "$ADB_LOG" 2>&1
+ sed -i -e 's![[:cntrl:]]!!g' "$ADB_LOG" # Remove \r.
+ RET=$(sed -e '$!d' "$ADB_LOG") # Last line contains status code.
+ sed -e '$d' "$ADB_LOG" # Print everything except last line.
+ rm -f "$ADB_LOG"
+ return $RET
+}
+
+# Push a file to a device.
+# $1: source file path
+# $2: device target file path
+# Return: success or failure.
+adb_push () {
+ adb_check_device || return 1
+ run "$_ADB" push "$1" "$2"
+}
+
+# Pull a file from a device
+# $1: device file path
+# $2: target host file path
+# Return: success or failure.
+adb_pull () {
+ adb_check_device || return 1
+ run "$_ADB" pull "$1" "$2"
+}
+
+# Same as adb_push, but will panic if the operations didn't succeed.
+adb_install () {
+ adb_push "$@"
+ fail_panic "Failed to install $1 to the Android device at $2"
+}
+
diff --git a/toolkit/crashreporter/google-breakpad/android/google_breakpad/Android.mk b/toolkit/crashreporter/google-breakpad/android/google_breakpad/Android.mk
new file mode 100644
index 0000000000..8618492774
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/android/google_breakpad/Android.mk
@@ -0,0 +1,104 @@
+# 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.
+
+# ndk-build module definition for the Google Breakpad client library
+#
+# To use this file, do the following:
+#
+# 1/ Include this file from your own Android.mk, either directly
+# or with through the NDK's import-module function.
+#
+# 2/ Use the client static library in your project with:
+#
+# LOCAL_STATIC_LIBRARIES += breakpad_client
+#
+# 3/ In your source code, include "src/client/linux/exception_handler.h"
+# and use the Linux instructions to use it.
+#
+# This module works with either the STLport or GNU libstdc++, but you need
+# to select one in your Application.mk
+#
+
+# The top Google Breakpad directory.
+# We assume this Android.mk to be under 'android/google_breakpad'
+
+LOCAL_PATH := $(call my-dir)/../..
+
+# Defube the client library module, as a simple static library that
+# exports the right include path / linker flags to its users.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := breakpad_client
+
+LOCAL_CPP_EXTENSION := .cc
+
+# Breakpad uses inline ARM assembly that requires the library
+# to be built in ARM mode. Otherwise, the build will fail with
+# cryptic assembler messages like:
+# Compile++ thumb : google_breakpad_client <= crash_generation_client.cc
+# /tmp/cc8aMSoD.s: Assembler messages:
+# /tmp/cc8aMSoD.s:132: Error: invalid immediate: 288 is out of range
+# /tmp/cc8aMSoD.s:244: Error: invalid immediate: 296 is out of range
+LOCAL_ARM_MODE := arm
+
+# List of client source files, directly taken from Makefile.am
+LOCAL_SRC_FILES := \
+ src/client/linux/crash_generation/crash_generation_client.cc \
+ src/client/linux/dump_writer_common/thread_info.cc \
+ src/client/linux/dump_writer_common/ucontext_reader.cc \
+ src/client/linux/handler/exception_handler.cc \
+ src/client/linux/handler/minidump_descriptor.cc \
+ src/client/linux/log/log.cc \
+ src/client/linux/microdump_writer/microdump_writer.cc \
+ src/client/linux/minidump_writer/linux_dumper.cc \
+ src/client/linux/minidump_writer/linux_ptrace_dumper.cc \
+ src/client/linux/minidump_writer/minidump_writer.cc \
+ src/client/minidump_file_writer.cc \
+ src/common/convert_UTF.cc \
+ src/common/md5.cc \
+ src/common/string_conversion.cc \
+ src/common/linux/breakpad_getcontext.S \
+ src/common/linux/elfutils.cc \
+ src/common/linux/file_id.cc \
+ src/common/linux/guid_creator.cc \
+ src/common/linux/linux_libc_support.cc \
+ src/common/linux/memory_mapped_file.cc \
+ src/common/linux/safe_readlink.cc
+
+LOCAL_C_INCLUDES := $(LOCAL_PATH)/src/common/android/include \
+ $(LOCAL_PATH)/src \
+ $(LSS_PATH)
+
+LOCAL_EXPORT_C_INCLUDES := $(LOCAL_C_INCLUDES)
+LOCAL_EXPORT_LDLIBS := -llog
+
+include $(BUILD_STATIC_LIBRARY)
+
+# Done.
diff --git a/toolkit/crashreporter/google-breakpad/android/run-checks.sh b/toolkit/crashreporter/google-breakpad/android/run-checks.sh
new file mode 100755
index 0000000000..51d2d50231
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/android/run-checks.sh
@@ -0,0 +1,555 @@
+#!/bin/sh
+# 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.
+
+# Sanitize the environment
+export LANG=C
+export LC_ALL=C
+
+if [ "$BASH_VERSION" ]; then
+ set -o posix
+fi
+
+PROGDIR=$(dirname "$0")
+PROGDIR=$(cd "$PROGDIR" && pwd)
+PROGNAME=$(basename "$0")
+
+. $PROGDIR/common-functions.sh
+
+DEFAULT_ABI="armeabi"
+VALID_ABIS="armeabi armeabi-v7a x86 mips"
+
+ABI=
+ADB=
+ALL_TESTS=
+ENABLE_M32=
+HELP=
+HELP_ALL=
+NDK_DIR=
+NO_CLEANUP=
+NO_DEVICE=
+NUM_JOBS=$(get_core_count)
+TMPDIR=
+
+for opt do
+ # The following extracts the value if the option is like --name=<value>.
+ optarg=$(expr -- $opt : '^--[^=]*=\(.*\)$')
+ case $opt in
+ --abi=*) ABI=$optarg;;
+ --adb=*) ADB=$optarg;;
+ --all-tests) ALL_TESTS=true;;
+ --enable-m32) ENABLE_M32=true;;
+ --help|-h|-?) HELP=TRUE;;
+ --help-all) HELP_ALL=true;;
+ --jobs=*) NUM_JOBS=$optarg;;
+ --ndk-dir=*) NDK_DIR=$optarg;;
+ --tmp-dir=*) TMPDIR=$optarg;;
+ --no-cleanup) NO_CLEANUP=true;;
+ --no-device) NO_DEVICE=true;;
+ --quiet) decrease_verbosity;;
+ --verbose) increase_verbosity;;
+ -*) panic "Invalid option '$opt', see --help for details.";;
+ *) panic "This script doesn't take any parameters. See --help for details."
+ ;;
+ esac
+done
+
+if [ "$HELP" -o "$HELP_ALL" ]; then
+ echo "\
+ Usage: $PROGNAME [options]
+
+ This script is used to check that your Google Breakpad source tree can
+ be properly built for Android, and that the client library and host tools
+ work properly together.
+"
+ if [ "$HELP_ALL" ]; then
+ echo "\
+ In more details, this script will:
+
+ - Rebuild the host version of Google Breakpad in a temporary
+ directory (with the Auto-tools based build system).
+
+ - Rebuild the Android client library with the Google Breakpad build
+ system (using autotools/configure). This requires that you define
+ ANDROID_NDK_ROOT in your environment to point to a valid Android NDK
+ installation directory, or use the --ndk-dir=<path> option.
+
+ - Rebuild the Android client library and a test crashing program with the
+ Android NDK build system (ndk-build).
+
+ - Require an Android device connected to your machine, and the 'adb'
+ tool in your path. They are used to:
+
+ - Install and run a test crashing program.
+ - Extract the corresponding minidump from the device.
+ - Dump the symbols from the test program on the host with 'dump_syms'
+ - Generate a stack trace with 'minidump_stackwalk'
+ - Check the stack trace content for valid source file locations.
+
+ You can however skip this requirement and only test the builds by using
+ the --no-device flag.
+
+ By default, all generated files will be created in a temporary directory
+ that is removed when the script completion. If you want to inspect the
+ files, use the --no-cleanup option.
+
+ Finally, use --verbose to increase the verbosity level, this will help
+ you see which exact commands are being issues and their result. Use the
+ flag twice for even more output. Use --quiet to decrease verbosity
+ instead and run the script silently.
+
+ If you have a device connected, the script will probe it to determine
+ its primary CPU ABI, and build the test program for it. You can however
+ use the --abi=<name> option to override this (this can be useful to check
+ the secondary ABI, e.g. using --abi=armeabi to check that such a program
+ works correctly on an ARMv7-A device).
+
+ If you don't have a device connected, the test program will be built (but
+ not run) with the default '$DEFAULT_ABI' ABI. Again, you can use
+ --abi=<name> to override this. Valid ABI names are:
+
+ $VALID_ABIS
+
+ The script will only run the client library unit test on the device
+ by default. You can use --all-tests to also build and run the unit
+ tests for the Breakpad tools and processor, but be warned that this
+ adds several minutes of testing time. --all-tests will also run the
+ host unit tests suite.
+"
+
+ fi # HELP_ALL
+
+ echo "\
+ Valid options:
+
+ --help|-h|-? Display this message.
+ --help-all Display extended help.
+ --enable-m32 Build 32-bit version of host tools.
+ --abi=<name> Specify target CPU ABI [auto-detected].
+ --jobs=<count> Run <count> build tasks in parallel [$NUM_JOBS].
+ --ndk-dir=<path> Specify NDK installation directory.
+ --tmp-dir=<path> Specify temporary directory (will be wiped-out).
+ --adb=<path> Specify adb program path.
+ --no-cleanup Don't remove temporary directory after completion.
+ --no-device Do not try to detect devices, nor run crash test.
+ --all-tests Run all unit tests (i.e. tools and processor ones too).
+ --verbose Increase verbosity.
+ --quiet Decrease verbosity."
+
+ exit 0
+fi
+
+TESTAPP_DIR=$PROGDIR/sample_app
+
+# Select NDK install directory.
+if [ -z "$NDK_DIR" ]; then
+ if [ -z "$ANDROID_NDK_ROOT" ]; then
+ panic "Please define ANDROID_NDK_ROOT in your environment, or use \
+--ndk-dir=<path>."
+ fi
+ NDK_DIR="$ANDROID_NDK_ROOT"
+ log "Found NDK directory: $NDK_DIR"
+else
+ log "Using NDK directory: $NDK_DIR"
+fi
+# Small sanity check.
+NDK_BUILD="$NDK_DIR/ndk-build"
+if [ ! -f "$NDK_BUILD" ]; then
+ panic "Your NDK directory is not valid (missing ndk-build): $NDK_DIR"
+fi
+
+# Ensure the temporary directory is deleted on exit, except if the --no-cleanup
+# option is used.
+
+clean_tmpdir () {
+ if [ "$TMPDIR" ]; then
+ if [ -z "$NO_CLEANUP" ]; then
+ log "Cleaning up: $TMPDIR"
+ rm -rf "$TMPDIR"
+ else
+ dump "Temporary directory contents preserved: $TMPDIR"
+ fi
+ fi
+ exit "$@"
+}
+
+atexit clean_tmpdir
+
+# If --tmp-dir=<path> is not used, create a temporary directory.
+# Otherwise, start by cleaning up the user-provided path.
+if [ -z "$TMPDIR" ]; then
+ TMPDIR=$(mktemp -d /tmp/$PROGNAME.XXXXXXXX)
+ fail_panic "Can't create temporary directory!"
+ log "Using temporary directory: $TMPDIR"
+else
+ if [ ! -d "$TMPDIR" ]; then
+ mkdir -p "$TMPDIR"
+ fail_panic "Can't create temporary directory: $TMPDIR"
+ else
+ log "Cleaning up temporary directory: $TMPDIR"
+ rm -rf "$TMPDIR"/*
+ fail_panic "Cannot cleanup temporary directory!"
+ fi
+fi
+
+if [ -z "$NO_DEVICE" ]; then
+ if ! adb_check_device $ADB; then
+ echo "$(adb_get_error)"
+ echo "Use --no-device to build the code without running any tests."
+ exit 1
+ fi
+fi
+
+BUILD_LOG="$TMPDIR/build.log"
+RUN_LOG="$TMPDIR/run.log"
+CRASH_LOG="$TMPDIR/crash.log"
+
+set_run_log "$RUN_LOG"
+
+TMPHOST="$TMPDIR/host-local"
+
+cd "$TMPDIR"
+
+# Build host version of the tools
+dump "Building host binaries."
+CONFIGURE_FLAGS=
+if [ "$ENABLE_M32" ]; then
+ CONFIGURE_FLAGS="$CONFIGURE_FLAGS --enable-m32"
+fi
+(
+ run mkdir "$TMPDIR/build-host" &&
+ run cd "$TMPDIR/build-host" &&
+ run2 "$PROGDIR/../configure" --prefix="$TMPHOST" $CONFIGURE_FLAGS &&
+ run2 make -j$NUM_JOBS install
+)
+fail_panic "Can't build host binaries!"
+
+if [ "$ALL_TESTS" ]; then
+ dump "Running host unit tests."
+ (
+ run cd "$TMPDIR/build-host" &&
+ run2 make -j$NUM_JOBS check
+ )
+ fail_panic "Host unit tests failed!!"
+fi
+
+TMPBIN=$TMPHOST/bin
+
+# Generate a stand-alone NDK toolchain
+
+# Extract CPU ABI and architecture from device, if any.
+if adb_check_device; then
+ DEVICE_ABI=$(adb_shell getprop ro.product.cpu.abi)
+ DEVICE_ABI2=$(adb_shell getprop ro.product.cpu.abi2)
+ if [ -z "$DEVICE_ABI" ]; then
+ panic "Can't extract ABI from connected device!"
+ fi
+ if [ "$DEVICE_ABI2" ]; then
+ dump "Found device ABIs: $DEVICE_ABI $DEVICE_ABI2"
+ else
+ dump "Found device ABI: $DEVICE_ABI"
+ DEVICE_ABI2=$DEVICE_ABI
+ fi
+
+ # If --abi=<name> is used, check that the device supports it.
+ if [ "$ABI" -a "$DEVICE_ABI" != "$ABI" -a "$DEVICE_ABI2" != "$ABI" ]; then
+ dump "ERROR: Device ABI(s) do not match --abi command-line value ($ABI)!"
+ panic "Please use --no-device to skip device tests."
+ fi
+
+ if [ -z "$ABI" ]; then
+ ABI=$DEVICE_ABI
+ dump "Using CPU ABI: $ABI (device)"
+ else
+ dump "Using CPU ABI: $ABI (command-line)"
+ fi
+else
+ if [ -z "$ABI" ]; then
+ # No device connected, choose default ABI
+ ABI=$DEFAULT_ABI
+ dump "Using CPU ABI: $ABI (default)"
+ else
+ dump "Using CPU ABI: $ABI (command-line)"
+ fi
+fi
+
+# Check the ABI value
+VALID=
+for VALID_ABI in $VALID_ABIS; do
+ if [ "$ABI" = "$VALID_ABI" ]; then
+ VALID=true
+ break
+ fi
+done
+
+if [ -z "$VALID" ]; then
+ panic "Unknown CPU ABI '$ABI'. Valid values are: $VALID_ABIS"
+fi
+
+# Extract architecture name from ABI
+case $ABI in
+ armeabi*) ARCH=arm;;
+ *) ARCH=$ABI;;
+esac
+
+# Extract GNU configuration name
+case $ARCH in
+ arm)
+ GNU_CONFIG=arm-linux-androideabi
+ ;;
+ x86)
+ GNU_CONFIG=i686-linux-android
+ ;;
+ mips)
+ GNU_CONFIG=mipsel-linux-android
+ ;;
+ *)
+ GNU_CONFIG="$ARCH-linux-android"
+ ;;
+esac
+
+# Generate standalone NDK toolchain installation
+NDK_STANDALONE="$TMPDIR/ndk-$ARCH-toolchain"
+echo "Generating NDK standalone toolchain installation"
+mkdir -p "$NDK_STANDALONE"
+# NOTE: The --platform=android-9 is required to provide <regex.h> for GTest.
+run "$NDK_DIR/build/tools/make-standalone-toolchain.sh" \
+ --arch="$ARCH" \
+ --platform=android-9 \
+ --install-dir="$NDK_STANDALONE"
+fail_panic "Can't generate standalone NDK toolchain installation!"
+
+# Rebuild the client library, processor and tools with the auto-tools based
+# build system. Even though it's not going to be used, this checks that this
+# still works correctly.
+echo "Building full Android binaries with configure/make"
+TMPTARGET="$TMPDIR/target-local"
+(
+ PATH="$NDK_STANDALONE/bin:$PATH"
+ run mkdir "$TMPTARGET" &&
+ run mkdir "$TMPDIR"/build-target &&
+ run cd "$TMPDIR"/build-target &&
+ run2 "$PROGDIR"/../configure --prefix="$TMPTARGET" \
+ --host="$GNU_CONFIG" &&
+ run2 make -j$NUM_JOBS install
+)
+fail_panic "Could not rebuild Android binaries!"
+
+# Build and/or run unit test suite.
+# If --no-device is used, only rebuild it, otherwise, run in on the
+# connected device.
+if [ "$NO_DEVICE" ]; then
+ ACTION="Building"
+ # This is a trick to force the Makefile to ignore running the scripts.
+ TESTS_ENVIRONMENT="TESTS_ENVIRONMENT=true"
+else
+ ACTION="Running"
+ TESTS_ENVIRONMENT=
+fi
+
+(
+ PATH="$NDK_STANDALONE/bin:$PATH"
+ run cd "$TMPDIR"/build-target &&
+ # Reconfigure to only run the client unit test suite.
+ # This one should _never_ fail.
+ dump "$ACTION Android client library unit tests."
+ run2 "$PROGDIR"/../configure --prefix="$TMPTARGET" \
+ --host="$GNU_CONFIG" \
+ --disable-tools \
+ --disable-processor &&
+ run make -j$NUM_JOBS check $TESTS_ENVIRONMENT || exit $?
+
+ if [ "$ALL_TESTS" ]; then
+ dump "$ACTION Tools and processor unit tests."
+ # Reconfigure to run the processor and tools tests.
+ # Most of these fail for now, so do not worry about it.
+ run2 "$PROGDIR"/../configure --prefix="$TMPTARGET" \
+ --host="$GNU_CONFIG" &&
+ run make -j$NUM_JOBS check $TESTS_ENVIRONMENT
+ if [ $? != 0 ]; then
+ dump "Tools and processor unit tests failed as expected. \
+Use --verbose for results."
+ fi
+ fi
+)
+fail_panic "Client library unit test suite failed!"
+
+# Copy sources to temporary directory
+PROJECT_DIR=$TMPDIR/project
+dump "Copying test program sources to: $PROJECT_DIR"
+run cp -r "$TESTAPP_DIR" "$PROJECT_DIR" &&
+run rm -rf "$PROJECT_DIR/obj" &&
+run rm -rf "$PROJECT_DIR/libs"
+fail_panic "Could not copy test program sources to: $PROJECT_DIR"
+
+# Build the test program with ndk-build.
+dump "Building test program with ndk-build"
+export NDK_MODULE_PATH="$PROGDIR"
+NDK_BUILD_FLAGS="-j$NUM_JOBS"
+if verbosity_is_higher_than 1; then
+ NDK_BUILD_FLAGS="$NDK_BUILD_FLAGS NDK_LOG=1 V=1"
+fi
+run "$NDK_DIR/ndk-build" -C "$PROJECT_DIR" $NDK_BUILD_FLAGS APP_ABI=$ABI
+fail_panic "Can't build test program!"
+
+# Unless --no-device was used, stop right here if ADB isn't in the path,
+# or there is no connected device.
+if [ "$NO_DEVICE" ]; then
+ dump "Done. Please connect a device to run all tests!"
+ clean_exit 0
+fi
+
+# Push the program to the device.
+TESTAPP=test_google_breakpad
+TESTAPP_FILE="$PROJECT_DIR/libs/$ABI/test_google_breakpad"
+if [ ! -f "$TESTAPP_FILE" ]; then
+ panic "Device requires '$ABI' binaries. None found!"
+fi
+
+# Run the program there
+dump "Installing test program on device"
+DEVICE_TMP=/data/local/tmp
+adb_push "$TESTAPP_FILE" "$DEVICE_TMP/"
+fail_panic "Cannot push test program to device!"
+
+dump "Running test program on device"
+adb_shell cd "$DEVICE_TMP" "&&" ./$TESTAPP > "$CRASH_LOG" 2>/dev/null
+if [ $? = 0 ]; then
+ panic "Test program did *not* crash as expected!"
+fi
+if verbosity_is_higher_than 0; then
+ echo -n "Crash log: "
+ cat "$CRASH_LOG"
+fi
+
+# Extract minidump from device
+MINIDUMP_NAME=$(awk '$1 == "Dump" && $2 == "path:" { print $3; }' "$CRASH_LOG")
+MINIDUMP_NAME=$(basename "$MINIDUMP_NAME")
+if [ -z "$MINIDUMP_NAME" ]; then
+ panic "Test program didn't write minidump properly!"
+fi
+
+dump "Extracting minidump: $MINIDUMP_NAME"
+adb_pull "$DEVICE_TMP/$MINIDUMP_NAME" .
+fail_panic "Can't extract minidump!"
+
+dump "Parsing test program symbols"
+if verbosity_is_higher_than 1; then
+ log "COMMAND: $TMPBIN/dump_syms \
+ $PROJECT_DIR/obj/local/$ABI/$TESTAPP >$TESTAPP.sym"
+fi
+"$TMPBIN/dump_syms" "$PROJECT_DIR/obj/local/$ABI/$TESTAPP" > $TESTAPP.sym
+fail_panic "dump_syms doesn't work!"
+
+VERSION=$(awk '$1 == "MODULE" { print $4; }' $TESTAPP.sym)
+dump "Found module version: $VERSION"
+if [ -z "$VERSION" ]; then
+ echo "ERROR: Can't find proper module version from symbol dump!"
+ head -n5 $TESTAPP.sym
+ clean_exit 1
+fi
+
+run mkdir -p "$TMPDIR/symbols/$TESTAPP/$VERSION"
+run mv $TESTAPP.sym "$TMPDIR/symbols/$TESTAPP/$VERSION/"
+
+dump "Generating stack trace"
+# Don't use 'run' to be able to send stdout and stderr to two different files.
+log "COMMAND: $TMPBIN/minidump_stackwalk $MINIDUMP_NAME symbols"
+"$TMPBIN/minidump_stackwalk" $MINIDUMP_NAME \
+ "$TMPDIR/symbols" \
+ > "$BUILD_LOG" 2>>"$RUN_LOG"
+fail_panic "minidump_stackwalk doesn't work!"
+
+dump "Checking stack trace content"
+
+if verbosity_is_higher_than 1; then
+ cat "$BUILD_LOG"
+fi
+
+# The generated stack trace should look like the following:
+#
+# Thread 0 (crashed)
+# 0 test_google_breakpad!crash [test_breakpad.cpp : 17 + 0x4]
+# r4 = 0x00015530 r5 = 0xbea2cbe4 r6 = 0xffffff38 r7 = 0xbea2cb5c
+# r8 = 0x00000000 r9 = 0x00000000 r10 = 0x00000000 fp = 0x00000000
+# sp = 0xbea2cb50 lr = 0x00009025 pc = 0x00008f84
+# Found by: given as instruction pointer in context
+# 1 test_google_breakpad!main [test_breakpad.cpp : 25 + 0x3]
+# r4 = 0x00015530 r5 = 0xbea2cbe4 r6 = 0xffffff38 r7 = 0xbea2cb5c
+# r8 = 0x00000000 r9 = 0x00000000 r10 = 0x00000000 fp = 0x00000000
+# sp = 0xbea2cb50 pc = 0x00009025
+# Found by: call frame info
+# 2 libc.so + 0x164e5
+# r4 = 0x00008f64 r5 = 0xbea2cc34 r6 = 0x00000001 r7 = 0xbea2cc3c
+# r8 = 0x00000000 r9 = 0x00000000 r10 = 0x00000000 fp = 0x00000000
+# sp = 0xbea2cc18 pc = 0x400c34e7
+# Found by: call frame info
+# ...
+#
+# The most important part for us is ensuring that the source location could
+# be extracted, so look at the 'test_breakpad.cpp' references here.
+#
+# First, extract all the lines with test_google_breakpad! in them, and
+# dump the corresponding crash location.
+#
+# Note that if the source location can't be extracted, the second field
+# will only be 'test_google_breakpad' without the exclamation mark.
+#
+LOCATIONS=$(awk '$2 ~ "^test_google_breakpad!.*" { print $3; }' "$BUILD_LOG")
+
+if [ -z "$LOCATIONS" ]; then
+ if verbosity_is_lower_than 1; then
+ cat "$BUILD_LOG"
+ fi
+ panic "No source location found in stack trace!"
+fi
+
+# Now check that they all match "[<source file>"
+BAD_LOCATIONS=
+for LOCATION in $LOCATIONS; do
+ case $LOCATION in
+ # Escape the opening bracket, or some shells like Dash will not
+ # match them properly.
+ \[*.cpp|\[*.cc|\[*.h) # These are valid source locations in our executable
+ ;;
+ *) # Everything else is not!
+ BAD_LOCATIONS="$BAD_LOCATIONS $LOCATION"
+ ;;
+ esac
+done
+
+if [ "$BAD_LOCATIONS" ]; then
+ dump "ERROR: Generated stack trace doesn't contain valid source locations:"
+ cat "$BUILD_LOG"
+ echo "Bad locations are: $BAD_LOCATIONS"
+ exit 1
+fi
+
+echo "All clear! Congratulations."
+
diff --git a/toolkit/crashreporter/google-breakpad/android/sample_app/README b/toolkit/crashreporter/google-breakpad/android/sample_app/README
new file mode 100644
index 0000000000..aa19dbb447
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/android/sample_app/README
@@ -0,0 +1,32 @@
+This is a sample Android executable that can be used to test the
+Google Breakpad client library on Android.
+
+Its purpose is simply to crash and generate a minidump under /data/local/tmp.
+
+Build instructions:
+
+ cd android/sample_app
+ $NDK/ndk-build
+
+ Where $NDK points to a valid Android NDK installation.
+
+Usage instructions:
+
+ After buildind the test program, send it to a device, then run it as
+ the shell UID:
+
+ adb push libs/armeabi/test_google_breakpad /data/local/tmp
+ adb shell /data/local/tmp/test_google_breakpad
+
+ This will simply crash after dumping the name of the generated minidump
+ file.
+
+ See jni/test_breakpad.cpp for details.
+
+ Use 'armeabi-v7a' instead of 'armeabi' above to test the ARMv7-A version
+ of the binary.
+
+Note:
+ If you plan to use the library in a regular Android application, store
+ the minidump files either to your app-specific directory, or to the SDCard
+ (the latter requiring a specific permission).
diff --git a/toolkit/crashreporter/google-breakpad/android/sample_app/jni/Android.mk b/toolkit/crashreporter/google-breakpad/android/sample_app/jni/Android.mk
new file mode 100644
index 0000000000..61487b52c1
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/android/sample_app/jni/Android.mk
@@ -0,0 +1,44 @@
+# 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.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := test_google_breakpad
+LOCAL_SRC_FILES := test_breakpad.cpp
+LOCAL_STATIC_LIBRARIES += breakpad_client
+include $(BUILD_EXECUTABLE)
+
+# If NDK_MODULE_PATH is defined, import the module, otherwise do a direct
+# includes. This allows us to build in all scenarios easily.
+ifneq ($(NDK_MODULE_PATH),)
+ $(call import-module,google_breakpad)
+else
+ include $(LOCAL_PATH)/../../google_breakpad/Android.mk
+endif
diff --git a/toolkit/crashreporter/google-breakpad/android/sample_app/jni/Application.mk b/toolkit/crashreporter/google-breakpad/android/sample_app/jni/Application.mk
new file mode 100644
index 0000000000..9728017d3f
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/android/sample_app/jni/Application.mk
@@ -0,0 +1,32 @@
+# 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.
+
+APP_STL := stlport_static
+APP_ABI := all
+APP_CXXFLAGS := -std=c++11 -D__STDC_LIMIT_MACROS
diff --git a/toolkit/crashreporter/google-breakpad/android/sample_app/jni/test_breakpad.cpp b/toolkit/crashreporter/google-breakpad/android/sample_app/jni/test_breakpad.cpp
new file mode 100644
index 0000000000..9c4ebbb148
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/android/sample_app/jni/test_breakpad.cpp
@@ -0,0 +1,57 @@
+// 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 <stdio.h>
+
+#include "client/linux/handler/exception_handler.h"
+#include "client/linux/handler/minidump_descriptor.h"
+
+namespace {
+
+bool DumpCallback(const google_breakpad::MinidumpDescriptor& descriptor,
+ void* context,
+ bool succeeded) {
+ printf("Dump path: %s\n", descriptor.path());
+ return succeeded;
+}
+
+void Crash() {
+ volatile int* a = reinterpret_cast<volatile int*>(NULL);
+ *a = 1;
+}
+
+} // namespace
+
+int main(int argc, char* argv[]) {
+ google_breakpad::MinidumpDescriptor descriptor(".");
+ google_breakpad::ExceptionHandler eh(descriptor, NULL, DumpCallback,
+ NULL, true, -1);
+ Crash();
+ return 0;
+}
diff --git a/toolkit/crashreporter/google-breakpad/android/test-driver b/toolkit/crashreporter/google-breakpad/android/test-driver
new file mode 100755
index 0000000000..eaaac6b295
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/android/test-driver
@@ -0,0 +1,131 @@
+#! /bin/sh
+# test-driver - basic testsuite driver script.
+
+# Slightly modified for Android, see ANDROID comment below.
+
+scriptversion=2012-06-27.10; # UTC
+
+# Copyright (C) 2011-2013 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# This file is maintained in Automake, please report
+# bugs to <bug-automake@gnu.org> or send patches to
+# <automake-patches@gnu.org>.
+
+# Make unconditional expansion of undefined variables an error. This
+# helps a lot in preventing typo-related bugs.
+set -u
+
+usage_error ()
+{
+ echo "$0: $*" >&2
+ print_usage >&2
+ exit 2
+}
+
+print_usage ()
+{
+ cat <<END
+Usage:
+ test-driver --test-name=NAME --log-file=PATH --trs-file=PATH
+ [--expect-failure={yes|no}] [--color-tests={yes|no}]
+ [--enable-hard-errors={yes|no}] [--] TEST-SCRIPT
+The '--test-name', '--log-file' and '--trs-file' options are mandatory.
+END
+}
+
+# TODO: better error handling in option parsing (in particular, ensure
+# TODO: $log_file, $trs_file and $test_name are defined).
+test_name= # Used for reporting.
+log_file= # Where to save the output of the test script.
+trs_file= # Where to save the metadata of the test run.
+expect_failure=no
+color_tests=no
+enable_hard_errors=yes
+while test $# -gt 0; do
+ case $1 in
+ --help) print_usage; exit $?;;
+ --version) echo "test-driver $scriptversion"; exit $?;;
+ --test-name) test_name=$2; shift;;
+ --log-file) log_file=$2; shift;;
+ --trs-file) trs_file=$2; shift;;
+ --color-tests) color_tests=$2; shift;;
+ --expect-failure) expect_failure=$2; shift;;
+ --enable-hard-errors) enable_hard_errors=$2; shift;;
+ --) shift; break;;
+ -*) usage_error "invalid option: '$1'";;
+ esac
+ shift
+done
+
+if test $color_tests = yes; then
+ # Keep this in sync with 'lib/am/check.am:$(am__tty_colors)'.
+ red='' # Red.
+ grn='' # Green.
+ lgn='' # Light green.
+ blu='' # Blue.
+ mgn='' # Magenta.
+ std='' # No color.
+else
+ red= grn= lgn= blu= mgn= std=
+fi
+
+do_exit='rm -f $log_file $trs_file; (exit $st); exit $st'
+trap "st=129; $do_exit" 1
+trap "st=130; $do_exit" 2
+trap "st=141; $do_exit" 13
+trap "st=143; $do_exit" 15
+
+# Test script is run here.
+# ANDROID: old line was: "$@" > $log_file 2>&1
+progdir=$(dirname "$0")
+"$progdir/test-shell.sh" "$@" > $log_file 2>&1
+estatus=$?
+if test $enable_hard_errors = no && test $estatus -eq 99; then
+ estatus=1
+fi
+
+case $estatus:$expect_failure in
+ 0:yes) col=$red res=XPASS recheck=yes gcopy=yes;;
+ 0:*) col=$grn res=PASS recheck=no gcopy=no;;
+ 77:*) col=$blu res=SKIP recheck=no gcopy=yes;;
+ 99:*) col=$mgn res=ERROR recheck=yes gcopy=yes;;
+ *:yes) col=$lgn res=XFAIL recheck=no gcopy=yes;;
+ *:*) col=$red res=FAIL recheck=yes gcopy=yes;;
+esac
+
+# Report outcome to console.
+echo "${col}${res}${std}: $test_name"
+
+# Register the test result, and other relevant metadata.
+echo ":test-result: $res" > $trs_file
+echo ":global-test-result: $res" >> $trs_file
+echo ":recheck: $recheck" >> $trs_file
+echo ":copy-in-global-log: $gcopy" >> $trs_file
+
+# Local Variables:
+# mode: shell-script
+# sh-indentation: 2
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-time-zone: "UTC"
+# time-stamp-end: "; # UTC"
+# End:
diff --git a/toolkit/crashreporter/google-breakpad/android/test-shell.sh b/toolkit/crashreporter/google-breakpad/android/test-shell.sh
new file mode 100755
index 0000000000..3677d8755a
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/android/test-shell.sh
@@ -0,0 +1,131 @@
+#!/bin/sh
+#
+# 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 special shell wrapper that can be used to run the Google Breakpad unit
+# tests on a connected Android device.
+#
+# This is designed to be called from the Makefile during 'make check'
+#
+
+PROGDIR=$(dirname "$0")
+PROGNAME=$(basename "$0")
+. $PROGDIR/common-functions.sh
+
+# Extract test program name first.
+TEST_PROGRAM=$1
+shift
+
+if [ -z "$TEST_PROGRAM" ]; then
+ panic "No test program/script name on the command-line!"
+fi
+
+if [ ! -f "$TEST_PROGRAM" ]; then
+ panic "Can't find test program/script: $TEST_PROGRAM"
+fi
+
+# Create test directory on the device
+TEST_DIR=/data/local/tmp/test-google-breakpad-$$
+adb_shell mkdir "$TEST_DIR" ||
+ panic "Can't create test directory on device: $TEST_DIR"
+
+# Ensure that it is always removed when the script exits.
+clean_test_dir () {
+ # Don't care about success/failure, use '$ADB shell' directly.
+ adb_shell rm -r "$TEST_DIR"
+}
+
+atexit clean_test_dir
+
+TEST_PROGRAM_NAME=$(basename "$TEST_PROGRAM")
+TEST_PROGRAM_DIR=$(dirname "$TEST_PROGRAM")
+
+# Handle special case(s) here.
+DATA_FILES=
+case $TEST_PROGRAM_NAME in
+ linux_client_unittest)
+ # linux_client_unittest will call another executable at runtime, ensure
+ # it is installed too.
+ adb_install "$TEST_PROGRAM_DIR/linux_dumper_unittest_helper" "$TEST_DIR"
+ # linux_client_unittest loads a shared library at runtime, ensure it is
+ # installed too.
+ adb_install "$TEST_PROGRAM_DIR/linux_client_unittest_shlib" "$TEST_DIR"
+ ;;
+ basic_source_line_resolver_unittest)
+ DATA_FILES="module1.out \
+ module2.out \
+ module3_bad.out \
+ module4_bad.out"
+ ;;
+ exploitability_unittest)
+ DATA_FILES="scii_read_av.dmp \
+ ascii_read_av_block_write.dmp \
+ ascii_read_av_clobber_write.dmp \
+ ascii_read_av_conditional.dmp \
+ ascii_read_av_non_null.dmp \
+ ascii_read_av_then_jmp.dmp \
+ ascii_read_av_xchg_write.dmp \
+ ascii_write_av.dmp \
+ ascii_write_av_arg_to_call.dmp \
+ exec_av_on_stack.dmp \
+ null_read_av.dmp \
+ null_write_av.dmp \
+ read_av.dmp \
+ null_read_av.dmp \
+ write_av_non_null.dmp"
+ ;;
+ fast_source_line_resolver_unittest)
+ DATA_FILES="module0.out \
+ module1.out \
+ module2.out \
+ module3_bad.out \
+ module4_bad.out"
+ ;;
+ minidump_processor_unittest|minidump_unittest)
+ DATA_FILES="src/processor/testdata/minidump2.dmp"
+ ;;
+esac
+
+# Install the data files, their path is relative to the environment
+# variable 'srcdir'
+for FILE in $DATA_FILES; do
+ FILEDIR=src/processor/testdata/$(dirname "$FILE")
+ adb_shell mkdir -p "$TEST_DIR/$FILEDIR"
+ adb_install "${srcdir:-.}/$FILE" "$TEST_DIR"/"$FILE"
+done
+
+# Copy test program to device
+adb_install "$TEST_PROGRAM" "$TEST_DIR"
+
+# Run it
+adb_shell "cd $TEST_DIR && LD_LIBRARY_PATH=. ./$TEST_PROGRAM_NAME $@"
+
+# Note: exiting here will call cleanup_exit which will remove the temporary
+# files from the device.
diff --git a/toolkit/crashreporter/google-breakpad/breakpad-client.pc.in b/toolkit/crashreporter/google-breakpad/breakpad-client.pc.in
new file mode 100644
index 0000000000..fcd2fa27e7
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/breakpad-client.pc.in
@@ -0,0 +1,10 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@/@PACKAGE_NAME@
+
+Name: google-breakpad-client
+Description: An open-source multi-platform crash reporting system
+Version: @PACKAGE_VERSION@
+Libs: -L${libdir} -lbreakpad_client @PTHREAD_LIBS@
+Cflags: -I${includedir} @PTHREAD_CFLAGS@
diff --git a/toolkit/crashreporter/google-breakpad/breakpad.pc.in b/toolkit/crashreporter/google-breakpad/breakpad.pc.in
new file mode 100644
index 0000000000..9aec9f8cb4
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/breakpad.pc.in
@@ -0,0 +1,10 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@/@PACKAGE_NAME@
+
+Name: google-breakpad
+Description: An open-source multi-platform crash reporting system
+Version: @PACKAGE_VERSION@
+Libs: -L${libdir} -lbreakpad @PTHREAD_LIBS@
+Cflags: -I${includedir} @PTHREAD_CFLAGS@
diff --git a/toolkit/crashreporter/google-breakpad/codereview.settings b/toolkit/crashreporter/google-breakpad/codereview.settings
new file mode 100644
index 0000000000..3f93733e4a
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/codereview.settings
@@ -0,0 +1,3 @@
+GERRIT_HOST: True
+CODE_REVIEW_SERVER: chromium-review.googlesource.com
+VIEW_VC: https://chromium.googlesource.com/breakpad/breakpad/+/
diff --git a/toolkit/crashreporter/google-breakpad/configure b/toolkit/crashreporter/google-breakpad/configure
new file mode 100755
index 0000000000..5e4b3d2e80
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/configure
@@ -0,0 +1,9231 @@
+#! /bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.69 for breakpad 0.1.
+#
+# Report bugs to <google-breakpad-dev@googlegroups.com>.
+#
+#
+# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
+#
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='print -r --'
+ as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='printf %s\n'
+ as_echo_n='printf %s'
+else
+ if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+ as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+ as_echo_n='/usr/ucb/echo -n'
+ else
+ as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+ as_echo_n_body='eval
+ arg=$1;
+ case $arg in #(
+ *"$as_nl"*)
+ expr "X$arg" : "X\\(.*\\)$as_nl";
+ arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+ esac;
+ expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+ '
+ export as_echo_n_body
+ as_echo_n='sh -c $as_echo_n_body as_echo'
+ fi
+ export as_echo_body
+ as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ PATH_SEPARATOR=:
+ (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+ (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+ PATH_SEPARATOR=';'
+ }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" "" $as_nl"
+
+# Find who we are. Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there. '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+# Use a proper internal environment variable to ensure we don't fall
+ # into an infinite loop, continuously re-executing ourselves.
+ if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then
+ _as_can_reexec=no; export _as_can_reexec;
+ # We cannot yet assume a decent shell, so we have to provide a
+# neutralization value for shells without unset; and this also
+# works around shells that cannot unset nonexistent variables.
+# Preserve -v and -x to the replacement shell.
+BASH_ENV=/dev/null
+ENV=/dev/null
+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+case $- in # ((((
+ *v*x* | *x*v* ) as_opts=-vx ;;
+ *v* ) as_opts=-v ;;
+ *x* ) as_opts=-x ;;
+ * ) as_opts= ;;
+esac
+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed `exec'.
+$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+as_fn_exit 255
+ fi
+ # We don't want this to propagate to other subprocesses.
+ { _as_can_reexec=; unset _as_can_reexec;}
+if test "x$CONFIG_SHELL" = x; then
+ as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '\${1+\"\$@\"}'='\"\$@\"'
+ setopt NO_GLOB_SUBST
+else
+ case \`(set -o) 2>/dev/null\` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+"
+ as_required="as_fn_return () { (exit \$1); }
+as_fn_success () { as_fn_return 0; }
+as_fn_failure () { as_fn_return 1; }
+as_fn_ret_success () { return 0; }
+as_fn_ret_failure () { return 1; }
+
+exitcode=0
+as_fn_success || { exitcode=1; echo as_fn_success failed.; }
+as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; }
+as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; }
+as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; }
+if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then :
+
+else
+ exitcode=1; echo positional parameters were not saved.
+fi
+test x\$exitcode = x0 || exit 1
+test -x / || exit 1"
+ as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
+ as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
+ eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
+ test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1
+test \$(( 1 + 1 )) = 2 || exit 1"
+ if (eval "$as_required") 2>/dev/null; then :
+ as_have_required=yes
+else
+ as_have_required=no
+fi
+ if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then :
+
+else
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+as_found=false
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ as_found=:
+ case $as_dir in #(
+ /*)
+ for as_base in sh bash ksh sh5; do
+ # Try only shells that exist, to save several forks.
+ as_shell=$as_dir/$as_base
+ if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
+ { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then :
+ CONFIG_SHELL=$as_shell as_have_required=yes
+ if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then :
+ break 2
+fi
+fi
+ done;;
+ esac
+ as_found=false
+done
+$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
+ { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then :
+ CONFIG_SHELL=$SHELL as_have_required=yes
+fi; }
+IFS=$as_save_IFS
+
+
+ if test "x$CONFIG_SHELL" != x; then :
+ export CONFIG_SHELL
+ # We cannot yet assume a decent shell, so we have to provide a
+# neutralization value for shells without unset; and this also
+# works around shells that cannot unset nonexistent variables.
+# Preserve -v and -x to the replacement shell.
+BASH_ENV=/dev/null
+ENV=/dev/null
+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+case $- in # ((((
+ *v*x* | *x*v* ) as_opts=-vx ;;
+ *v* ) as_opts=-v ;;
+ *x* ) as_opts=-x ;;
+ * ) as_opts= ;;
+esac
+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed `exec'.
+$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+exit 255
+fi
+
+ if test x$as_have_required = xno; then :
+ $as_echo "$0: This script requires a shell more modern than all"
+ $as_echo "$0: the shells that I found on your system."
+ if test x${ZSH_VERSION+set} = xset ; then
+ $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should"
+ $as_echo "$0: be upgraded to zsh 4.3.4 or later."
+ else
+ $as_echo "$0: Please tell bug-autoconf@gnu.org and
+$0: google-breakpad-dev@googlegroups.com about your system,
+$0: including any error possibly output before this
+$0: message. Then install a modern shell, or manually run
+$0: the script under such a shell if you do have one."
+ fi
+ exit 1
+fi
+fi
+fi
+SHELL=${CONFIG_SHELL-/bin/sh}
+export SHELL
+# Unset more variables known to interfere with behavior of common tools.
+CLICOLOR_FORCE= GREP_OPTIONS=
+unset CLICOLOR_FORCE GREP_OPTIONS
+
+## --------------------- ##
+## M4sh Shell Functions. ##
+## --------------------- ##
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+ { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+ return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+ set +e
+ as_fn_set_status $1
+ exit $1
+} # as_fn_exit
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+ case $as_dir in #(
+ -*) as_dir=./$as_dir;;
+ esac
+ test -d "$as_dir" || eval $as_mkdir_p || {
+ as_dirs=
+ while :; do
+ case $as_dir in #(
+ *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+ *) as_qdir=$as_dir;;
+ esac
+ as_dirs="'$as_qdir' $as_dirs"
+ as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ test -d "$as_dir" && break
+ done
+ test -z "$as_dirs" || eval "mkdir $as_dirs"
+ } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+ test -f "$1" && test -x "$1"
+} # as_fn_executable_p
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+ eval 'as_fn_append ()
+ {
+ eval $1+=\$2
+ }'
+else
+ as_fn_append ()
+ {
+ eval $1=\$$1\$2
+ }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+ eval 'as_fn_arith ()
+ {
+ as_val=$(( $* ))
+ }'
+else
+ as_fn_arith ()
+ {
+ as_val=`expr "$@" || test $? -eq 1`
+ }
+fi # as_fn_arith
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+ as_status=$1; test $as_status -eq 0 && as_status=1
+ if test "$4"; then
+ as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+ fi
+ $as_echo "$as_me: error: $2" >&2
+ as_fn_exit $as_status
+} # as_fn_error
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+
+ as_lineno_1=$LINENO as_lineno_1a=$LINENO
+ as_lineno_2=$LINENO as_lineno_2a=$LINENO
+ eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" &&
+ test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || {
+ # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-)
+ sed -n '
+ p
+ /[$]LINENO/=
+ ' <$as_myself |
+ sed '
+ s/[$]LINENO.*/&-/
+ t lineno
+ b
+ :lineno
+ N
+ :loop
+ s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+ t loop
+ s/-\n.*//
+ ' >$as_me.lineno &&
+ chmod +x "$as_me.lineno" ||
+ { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
+
+ # If we had to re-execute with $CONFIG_SHELL, we're ensured to have
+ # already done that, so ensure we don't try to do so again and fall
+ # in an infinite loop. This has already happened in practice.
+ _as_can_reexec=no; export _as_can_reexec
+ # Don't try to exec as it changes $[0], causing all sort of problems
+ # (the dirname of $[0] is not the place where we might find the
+ # original and so on. Autoconf is especially sensitive to this).
+ . "./$as_me.lineno"
+ # Exit status is that of the last command.
+ exit
+}
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+ case `echo 'xy\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ xy) ECHO_C='\c';;
+ *) echo `echo ksh88 bug on AIX 6.1` > /dev/null
+ ECHO_T=' ';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+ if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -pR'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -pR'
+ elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+ else
+ as_ln_s='cp -pR'
+ fi
+else
+ as_ln_s='cp -pR'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p='mkdir -p "$as_dir"'
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+test -n "$DJDIR" || exec 7<&0 </dev/null
+exec 6>&1
+
+# Name of the host.
+# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_clean_files=
+ac_config_libobj_dir=.
+LIBOBJS=
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+
+# Identity of this package.
+PACKAGE_NAME='breakpad'
+PACKAGE_TARNAME='breakpad'
+PACKAGE_VERSION='0.1'
+PACKAGE_STRING='breakpad 0.1'
+PACKAGE_BUGREPORT='google-breakpad-dev@googlegroups.com'
+PACKAGE_URL=''
+
+ac_unique_file="README.md"
+# Factoring default headers for most tests.
+ac_includes_default="\
+#include <stdio.h>
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#ifdef STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# ifdef HAVE_STDLIB_H
+# include <stdlib.h>
+# endif
+#endif
+#ifdef HAVE_STRING_H
+# if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+# include <memory.h>
+# endif
+# include <string.h>
+#endif
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#ifdef HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif"
+
+ac_subst_vars='am__EXEEXT_FALSE
+am__EXEEXT_TRUE
+LTLIBOBJS
+LIBOBJS
+TESTS_AS_ROOT_FALSE
+TESTS_AS_ROOT_TRUE
+RUST_DEMANGLE_LIBS
+RUST_DEMANGLE_CFLAGS
+SELFTEST_FALSE
+SELFTEST_TRUE
+GTEST_LIBS
+GTEST_CFLAGS
+GMOCK_LIBS
+GMOCK_CFLAGS
+SYSTEM_TEST_LIBS_FALSE
+SYSTEM_TEST_LIBS_TRUE
+DISABLE_TOOLS_FALSE
+DISABLE_TOOLS_TRUE
+DISABLE_PROCESSOR_FALSE
+DISABLE_PROCESSOR_TRUE
+X86_HOST_FALSE
+X86_HOST_TRUE
+ANDROID_HOST_FALSE
+ANDROID_HOST_TRUE
+LINUX_HOST_FALSE
+LINUX_HOST_TRUE
+WARN_CXXFLAGS
+HAVE_CXX11
+HAVE_GETCONTEXT_FALSE
+HAVE_GETCONTEXT_TRUE
+PTHREAD_CFLAGS
+PTHREAD_LIBS
+PTHREAD_CC
+ax_pthread_config
+EGREP
+GREP
+RANLIB
+am__fastdepCXX_FALSE
+am__fastdepCXX_TRUE
+CXXDEPMODE
+ac_ct_CXX
+CXXFLAGS
+CXX
+CPP
+am__fastdepCCAS_FALSE
+am__fastdepCCAS_TRUE
+CCASDEPMODE
+CCASFLAGS
+CCAS
+am__fastdepCC_FALSE
+am__fastdepCC_TRUE
+CCDEPMODE
+am__nodep
+AMDEPBACKSLASH
+AMDEP_FALSE
+AMDEP_TRUE
+am__quote
+am__include
+DEPDIR
+OBJEXT
+EXEEXT
+ac_ct_CC
+CPPFLAGS
+LDFLAGS
+CFLAGS
+CC
+ac_ct_AR
+AR
+MAINT
+MAINTAINER_MODE_FALSE
+MAINTAINER_MODE_TRUE
+AM_BACKSLASH
+AM_DEFAULT_VERBOSITY
+AM_DEFAULT_V
+AM_V
+am__untar
+am__tar
+AMTAR
+am__leading_dot
+SET_MAKE
+AWK
+mkdir_p
+MKDIR_P
+INSTALL_STRIP_PROGRAM
+STRIP
+install_sh
+MAKEINFO
+AUTOHEADER
+AUTOMAKE
+AUTOCONF
+ACLOCAL
+VERSION
+PACKAGE
+CYGPATH_W
+am__isrc
+INSTALL_DATA
+INSTALL_SCRIPT
+INSTALL_PROGRAM
+host_os
+host_vendor
+host_cpu
+host
+build_os
+build_vendor
+build_cpu
+build
+target_alias
+host_alias
+build_alias
+LIBS
+ECHO_T
+ECHO_N
+ECHO_C
+DEFS
+mandir
+localedir
+libdir
+psdir
+pdfdir
+dvidir
+htmldir
+infodir
+docdir
+oldincludedir
+includedir
+localstatedir
+sharedstatedir
+sysconfdir
+datadir
+datarootdir
+libexecdir
+sbindir
+bindir
+program_transform_name
+prefix
+exec_prefix
+PACKAGE_URL
+PACKAGE_BUGREPORT
+PACKAGE_STRING
+PACKAGE_VERSION
+PACKAGE_TARNAME
+PACKAGE_NAME
+PATH_SEPARATOR
+SHELL'
+ac_subst_files=''
+ac_user_opts='
+enable_option_checking
+enable_silent_rules
+enable_maintainer_mode
+enable_dependency_tracking
+enable_m32
+enable_largefile
+enable_processor
+enable_tools
+enable_system_test_libs
+enable_selftest
+with_rust_demangle
+with_tests_as_root
+'
+ ac_precious_vars='build_alias
+host_alias
+target_alias
+CC
+CFLAGS
+LDFLAGS
+LIBS
+CPPFLAGS
+CCAS
+CCASFLAGS
+CPP
+CXX
+CXXFLAGS
+CCC
+GMOCK_CFLAGS
+GMOCK_LIBS
+GTEST_CFLAGS
+GTEST_LIBS
+RUST_DEMANGLE_CFLAGS
+RUST_DEMANGLE_LIBS'
+
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+ac_unrecognized_opts=
+ac_unrecognized_sep=
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+# (The list follows the same order as the GNU Coding Standards.)
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datarootdir='${prefix}/share'
+datadir='${datarootdir}'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
+infodir='${datarootdir}/info'
+htmldir='${docdir}'
+dvidir='${docdir}'
+pdfdir='${docdir}'
+psdir='${docdir}'
+libdir='${exec_prefix}/lib'
+localedir='${datarootdir}/locale'
+mandir='${datarootdir}/man'
+
+ac_prev=
+ac_dashdash=
+for ac_option
+do
+ # If the previous option needs an argument, assign it.
+ if test -n "$ac_prev"; then
+ eval $ac_prev=\$ac_option
+ ac_prev=
+ continue
+ fi
+
+ case $ac_option in
+ *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
+ *=) ac_optarg= ;;
+ *) ac_optarg=yes ;;
+ esac
+
+ # Accept the important Cygnus configure options, so we can diagnose typos.
+
+ case $ac_dashdash$ac_option in
+ --)
+ ac_dashdash=yes ;;
+
+ -bindir | --bindir | --bindi | --bind | --bin | --bi)
+ ac_prev=bindir ;;
+ -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+ bindir=$ac_optarg ;;
+
+ -build | --build | --buil | --bui | --bu)
+ ac_prev=build_alias ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+ build_alias=$ac_optarg ;;
+
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ cache_file=$ac_optarg ;;
+
+ --config-cache | -C)
+ cache_file=config.cache ;;
+
+ -datadir | --datadir | --datadi | --datad)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=*)
+ datadir=$ac_optarg ;;
+
+ -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \
+ | --dataroo | --dataro | --datar)
+ ac_prev=datarootdir ;;
+ -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \
+ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
+ datarootdir=$ac_optarg ;;
+
+ -disable-* | --disable-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid feature name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"enable_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval enable_$ac_useropt=no ;;
+
+ -docdir | --docdir | --docdi | --doc | --do)
+ ac_prev=docdir ;;
+ -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)
+ docdir=$ac_optarg ;;
+
+ -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
+ ac_prev=dvidir ;;
+ -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
+ dvidir=$ac_optarg ;;
+
+ -enable-* | --enable-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid feature name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"enable_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval enable_$ac_useropt=\$ac_optarg ;;
+
+ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+ | --exec | --exe | --ex)
+ ac_prev=exec_prefix ;;
+ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+ | --exec=* | --exe=* | --ex=*)
+ exec_prefix=$ac_optarg ;;
+
+ -gas | --gas | --ga | --g)
+ # Obsolete; use --with-gas.
+ with_gas=yes ;;
+
+ -help | --help | --hel | --he | -h)
+ ac_init_help=long ;;
+ -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+ ac_init_help=recursive ;;
+ -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+ ac_init_help=short ;;
+
+ -host | --host | --hos | --ho)
+ ac_prev=host_alias ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+ host_alias=$ac_optarg ;;
+
+ -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)
+ ac_prev=htmldir ;;
+ -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \
+ | --ht=*)
+ htmldir=$ac_optarg ;;
+
+ -includedir | --includedir | --includedi | --included | --include \
+ | --includ | --inclu | --incl | --inc)
+ ac_prev=includedir ;;
+ -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+ | --includ=* | --inclu=* | --incl=* | --inc=*)
+ includedir=$ac_optarg ;;
+
+ -infodir | --infodir | --infodi | --infod | --info | --inf)
+ ac_prev=infodir ;;
+ -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+ infodir=$ac_optarg ;;
+
+ -libdir | --libdir | --libdi | --libd)
+ ac_prev=libdir ;;
+ -libdir=* | --libdir=* | --libdi=* | --libd=*)
+ libdir=$ac_optarg ;;
+
+ -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+ | --libexe | --libex | --libe)
+ ac_prev=libexecdir ;;
+ -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+ | --libexe=* | --libex=* | --libe=*)
+ libexecdir=$ac_optarg ;;
+
+ -localedir | --localedir | --localedi | --localed | --locale)
+ ac_prev=localedir ;;
+ -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)
+ localedir=$ac_optarg ;;
+
+ -localstatedir | --localstatedir | --localstatedi | --localstated \
+ | --localstate | --localstat | --localsta | --localst | --locals)
+ ac_prev=localstatedir ;;
+ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)
+ localstatedir=$ac_optarg ;;
+
+ -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+ ac_prev=mandir ;;
+ -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+ mandir=$ac_optarg ;;
+
+ -nfp | --nfp | --nf)
+ # Obsolete; use --without-fp.
+ with_fp=no ;;
+
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c | -n)
+ no_create=yes ;;
+
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+ no_recursion=yes ;;
+
+ -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+ | --oldin | --oldi | --old | --ol | --o)
+ ac_prev=oldincludedir ;;
+ -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+ oldincludedir=$ac_optarg ;;
+
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ prefix=$ac_optarg ;;
+
+ -program-prefix | --program-prefix | --program-prefi | --program-pref \
+ | --program-pre | --program-pr | --program-p)
+ ac_prev=program_prefix ;;
+ -program-prefix=* | --program-prefix=* | --program-prefi=* \
+ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+ program_prefix=$ac_optarg ;;
+
+ -program-suffix | --program-suffix | --program-suffi | --program-suff \
+ | --program-suf | --program-su | --program-s)
+ ac_prev=program_suffix ;;
+ -program-suffix=* | --program-suffix=* | --program-suffi=* \
+ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+ program_suffix=$ac_optarg ;;
+
+ -program-transform-name | --program-transform-name \
+ | --program-transform-nam | --program-transform-na \
+ | --program-transform-n | --program-transform- \
+ | --program-transform | --program-transfor \
+ | --program-transfo | --program-transf \
+ | --program-trans | --program-tran \
+ | --progr-tra | --program-tr | --program-t)
+ ac_prev=program_transform_name ;;
+ -program-transform-name=* | --program-transform-name=* \
+ | --program-transform-nam=* | --program-transform-na=* \
+ | --program-transform-n=* | --program-transform-=* \
+ | --program-transform=* | --program-transfor=* \
+ | --program-transfo=* | --program-transf=* \
+ | --program-trans=* | --program-tran=* \
+ | --progr-tra=* | --program-tr=* | --program-t=*)
+ program_transform_name=$ac_optarg ;;
+
+ -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)
+ ac_prev=pdfdir ;;
+ -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)
+ pdfdir=$ac_optarg ;;
+
+ -psdir | --psdir | --psdi | --psd | --ps)
+ ac_prev=psdir ;;
+ -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
+ psdir=$ac_optarg ;;
+
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ silent=yes ;;
+
+ -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+ ac_prev=sbindir ;;
+ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+ | --sbi=* | --sb=*)
+ sbindir=$ac_optarg ;;
+
+ -sharedstatedir | --sharedstatedir | --sharedstatedi \
+ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+ | --sharedst | --shareds | --shared | --share | --shar \
+ | --sha | --sh)
+ ac_prev=sharedstatedir ;;
+ -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+ | --sha=* | --sh=*)
+ sharedstatedir=$ac_optarg ;;
+
+ -site | --site | --sit)
+ ac_prev=site ;;
+ -site=* | --site=* | --sit=*)
+ site=$ac_optarg ;;
+
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ srcdir=$ac_optarg ;;
+
+ -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+ | --syscon | --sysco | --sysc | --sys | --sy)
+ ac_prev=sysconfdir ;;
+ -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+ sysconfdir=$ac_optarg ;;
+
+ -target | --target | --targe | --targ | --tar | --ta | --t)
+ ac_prev=target_alias ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+ target_alias=$ac_optarg ;;
+
+ -v | -verbose | --verbose | --verbos | --verbo | --verb)
+ verbose=yes ;;
+
+ -version | --version | --versio | --versi | --vers | -V)
+ ac_init_version=: ;;
+
+ -with-* | --with-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid package name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"with_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval with_$ac_useropt=\$ac_optarg ;;
+
+ -without-* | --without-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid package name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"with_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval with_$ac_useropt=no ;;
+
+ --x)
+ # Obsolete; use --with-x.
+ with_x=yes ;;
+
+ -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+ | --x-incl | --x-inc | --x-in | --x-i)
+ ac_prev=x_includes ;;
+ -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+ x_includes=$ac_optarg ;;
+
+ -x-libraries | --x-libraries | --x-librarie | --x-librari \
+ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+ ac_prev=x_libraries ;;
+ -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+ x_libraries=$ac_optarg ;;
+
+ -*) as_fn_error $? "unrecognized option: \`$ac_option'
+Try \`$0 --help' for more information"
+ ;;
+
+ *=*)
+ ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+ # Reject names that are not valid shell variable names.
+ case $ac_envvar in #(
+ '' | [0-9]* | *[!_$as_cr_alnum]* )
+ as_fn_error $? "invalid variable name: \`$ac_envvar'" ;;
+ esac
+ eval $ac_envvar=\$ac_optarg
+ export $ac_envvar ;;
+
+ *)
+ # FIXME: should be removed in autoconf 3.0.
+ $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+ expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+ : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}"
+ ;;
+
+ esac
+done
+
+if test -n "$ac_prev"; then
+ ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+ as_fn_error $? "missing argument to $ac_option"
+fi
+
+if test -n "$ac_unrecognized_opts"; then
+ case $enable_option_checking in
+ no) ;;
+ fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;;
+ *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
+ esac
+fi
+
+# Check all directory arguments for consistency.
+for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
+ datadir sysconfdir sharedstatedir localstatedir includedir \
+ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
+ libdir localedir mandir
+do
+ eval ac_val=\$$ac_var
+ # Remove trailing slashes.
+ case $ac_val in
+ */ )
+ ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'`
+ eval $ac_var=\$ac_val;;
+ esac
+ # Be sure to have absolute directory names.
+ case $ac_val in
+ [\\/$]* | ?:[\\/]* ) continue;;
+ NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
+ esac
+ as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val"
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+ if test "x$build_alias" = x; then
+ cross_compiling=maybe
+ elif test "x$build_alias" != "x$host_alias"; then
+ cross_compiling=yes
+ fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+ac_pwd=`pwd` && test -n "$ac_pwd" &&
+ac_ls_di=`ls -di .` &&
+ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
+ as_fn_error $? "working directory cannot be determined"
+test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
+ as_fn_error $? "pwd does not report name of working directory"
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+ ac_srcdir_defaulted=yes
+ # Try the directory containing this script, then the parent directory.
+ ac_confdir=`$as_dirname -- "$as_myself" ||
+$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_myself" : 'X\(//\)[^/]' \| \
+ X"$as_myself" : 'X\(//\)$' \| \
+ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_myself" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ srcdir=$ac_confdir
+ if test ! -r "$srcdir/$ac_unique_file"; then
+ srcdir=..
+ fi
+else
+ ac_srcdir_defaulted=no
+fi
+if test ! -r "$srcdir/$ac_unique_file"; then
+ test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
+ as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir"
+fi
+ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
+ac_abs_confdir=`(
+ cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg"
+ pwd)`
+# When building in place, set srcdir=.
+if test "$ac_abs_confdir" = "$ac_pwd"; then
+ srcdir=.
+fi
+# Remove unnecessary trailing slashes from srcdir.
+# Double slashes in file names in object file debugging info
+# mess up M-x gdb in Emacs.
+case $srcdir in
+*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;
+esac
+for ac_var in $ac_precious_vars; do
+ eval ac_env_${ac_var}_set=\${${ac_var}+set}
+ eval ac_env_${ac_var}_value=\$${ac_var}
+ eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}
+ eval ac_cv_env_${ac_var}_value=\$${ac_var}
+done
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat <<_ACEOF
+\`configure' configures breakpad 0.1 to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE. See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+ -h, --help display this help and exit
+ --help=short display options specific to this package
+ --help=recursive display the short help of all the included packages
+ -V, --version display version information and exit
+ -q, --quiet, --silent do not print \`checking ...' messages
+ --cache-file=FILE cache test results in FILE [disabled]
+ -C, --config-cache alias for \`--cache-file=config.cache'
+ -n, --no-create do not create output files
+ --srcdir=DIR find the sources in DIR [configure dir or \`..']
+
+Installation directories:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+ --bindir=DIR user executables [EPREFIX/bin]
+ --sbindir=DIR system admin executables [EPREFIX/sbin]
+ --libexecdir=DIR program executables [EPREFIX/libexec]
+ --sysconfdir=DIR read-only single-machine data [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data [PREFIX/var]
+ --libdir=DIR object code libraries [EPREFIX/lib]
+ --includedir=DIR C header files [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc [/usr/include]
+ --datarootdir=DIR read-only arch.-independent data root [PREFIX/share]
+ --datadir=DIR read-only architecture-independent data [DATAROOTDIR]
+ --infodir=DIR info documentation [DATAROOTDIR/info]
+ --localedir=DIR locale-dependent data [DATAROOTDIR/locale]
+ --mandir=DIR man documentation [DATAROOTDIR/man]
+ --docdir=DIR documentation root [DATAROOTDIR/doc/breakpad]
+ --htmldir=DIR html documentation [DOCDIR]
+ --dvidir=DIR dvi documentation [DOCDIR]
+ --pdfdir=DIR pdf documentation [DOCDIR]
+ --psdir=DIR ps documentation [DOCDIR]
+_ACEOF
+
+ cat <<\_ACEOF
+
+Program names:
+ --program-prefix=PREFIX prepend PREFIX to installed program names
+ --program-suffix=SUFFIX append SUFFIX to installed program names
+ --program-transform-name=PROGRAM run sed PROGRAM on installed program names
+
+System types:
+ --build=BUILD configure for building on BUILD [guessed]
+ --host=HOST cross-compile to build programs to run on HOST [BUILD]
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+ case $ac_init_help in
+ short | recursive ) echo "Configuration of breakpad 0.1:";;
+ esac
+ cat <<\_ACEOF
+
+Optional Features:
+ --disable-option-checking ignore unrecognized --enable/--with options
+ --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
+ --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
+ --enable-silent-rules less verbose build output (undo: "make V=1")
+ --disable-silent-rules verbose build output (undo: "make V=0")
+ --enable-maintainer-mode
+ enable make rules and dependencies not useful (and
+ sometimes confusing) to the casual installer
+ --enable-dependency-tracking
+ do not reject slow dependency extractors
+ --disable-dependency-tracking
+ speeds up one-time build
+ --enable-m32 Compile/build with -m32 (default is no)
+ --disable-largefile omit support for large files
+ --disable-processor Don't build processor library (default is no)
+ --disable-tools Don't build tool binaries (default is no)
+ --enable-system-test-libs
+ Use gtest/gmock/etc... from the system instead of
+ the local copies (default is local)
+ --enable-selftest Run extra tests with "make check" (may conflict with
+ optimizations) (default is no)
+
+Optional Packages:
+ --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
+ --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
+ --with-rust-demangle=/path/to/rust-demangle-capi
+ Link against the rust-demangle library to demangle
+ Rust language symbols during symbol dumping (default
+ is no) Pass the path to the crate root.
+ --with-tests-as-root Run the tests as root. Use this on platforms like
+ travis-ci.org that require root privileges to use
+ ptrace (default is no)
+
+Some influential environment variables:
+ CC C compiler command
+ CFLAGS C compiler flags
+ LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a
+ nonstandard directory <lib dir>
+ LIBS libraries to pass to the linker, e.g. -l<library>
+ CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if
+ you have headers in a nonstandard directory <include dir>
+ CCAS assembler compiler command (defaults to CC)
+ CCASFLAGS assembler compiler flags (defaults to CFLAGS)
+ CPP C preprocessor
+ CXX C++ compiler command
+ CXXFLAGS C++ compiler flags
+ GMOCK_CFLAGS
+ Compiler flags for gmock
+ GMOCK_LIBS Linker flags for gmock
+ GTEST_CFLAGS
+ Compiler flags for gtest
+ GTEST_LIBS Linker flags for gtest
+ RUST_DEMANGLE_CFLAGS
+ Compiler flags for rust-demangle
+ RUST_DEMANGLE_LIBS
+ Linker flags for rust-demangle
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+Report bugs to <google-breakpad-dev@googlegroups.com>.
+_ACEOF
+ac_status=$?
+fi
+
+if test "$ac_init_help" = "recursive"; then
+ # If there are subdirs, report their specific --help.
+ for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+ test -d "$ac_dir" ||
+ { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } ||
+ continue
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+ cd "$ac_dir" || { ac_status=$?; continue; }
+ # Check for guested configure.
+ if test -f "$ac_srcdir/configure.gnu"; then
+ echo &&
+ $SHELL "$ac_srcdir/configure.gnu" --help=recursive
+ elif test -f "$ac_srcdir/configure"; then
+ echo &&
+ $SHELL "$ac_srcdir/configure" --help=recursive
+ else
+ $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+ fi || ac_status=$?
+ cd "$ac_pwd" || { ac_status=$?; break; }
+ done
+fi
+
+test -n "$ac_init_help" && exit $ac_status
+if $ac_init_version; then
+ cat <<\_ACEOF
+breakpad configure 0.1
+generated by GNU Autoconf 2.69
+
+Copyright (C) 2012 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+ exit
+fi
+
+## ------------------------ ##
+## Autoconf initialization. ##
+## ------------------------ ##
+
+# ac_fn_c_try_compile LINENO
+# --------------------------
+# Try to compile conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_compile ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ rm -f conftest.$ac_objext
+ if { { ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compile") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_compile
+
+# ac_fn_c_try_cpp LINENO
+# ----------------------
+# Try to preprocess conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_cpp ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ if { { ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } > conftest.i && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_cpp
+
+# ac_fn_cxx_try_compile LINENO
+# ----------------------------
+# Try to compile conftest.$ac_ext, and return whether this succeeded.
+ac_fn_cxx_try_compile ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ rm -f conftest.$ac_objext
+ if { { ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compile") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_cxx_try_compile
+
+# ac_fn_c_try_run LINENO
+# ----------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes
+# that executables *can* be run.
+ac_fn_c_try_run ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ if { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && { ac_try='./conftest$ac_exeext'
+ { { case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; }; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: program exited with status $ac_status" >&5
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=$ac_status
+fi
+ rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_run
+
+# ac_fn_c_try_link LINENO
+# -----------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_link ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ rm -f conftest.$ac_objext conftest$ac_exeext
+ if { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext && {
+ test "$cross_compiling" = yes ||
+ test -x conftest$ac_exeext
+ }; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information
+ # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would
+ # interfere with the next link command; also delete a directory that is
+ # left behind by Apple's compiler. We do this before executing the actions.
+ rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_link
+
+# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES
+# -------------------------------------------------------
+# Tests whether HEADER exists, giving a warning if it cannot be compiled using
+# the include files in INCLUDES and setting the cache variable VAR
+# accordingly.
+ac_fn_c_check_header_mongrel ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ if eval \${$3+:} false; then :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+ $as_echo_n "(cached) " >&6
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+else
+ # Is the header compilable?
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5
+$as_echo_n "checking $2 usability... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+#include <$2>
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_header_compiler=yes
+else
+ ac_header_compiler=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5
+$as_echo "$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5
+$as_echo_n "checking $2 presence... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <$2>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+ ac_header_preproc=yes
+else
+ ac_header_preproc=no
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5
+$as_echo "$ac_header_preproc" >&6; }
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #((
+ yes:no: )
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5
+$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
+$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
+ ;;
+ no:yes:* )
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5
+$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5
+$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5
+$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5
+$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
+$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
+( $as_echo "## --------------------------------------------------- ##
+## Report this to google-breakpad-dev@googlegroups.com ##
+## --------------------------------------------------- ##"
+ ) | sed "s/^/$as_me: WARNING: /" >&2
+ ;;
+esac
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ eval "$3=\$ac_header_compiler"
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+fi
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_header_mongrel
+
+# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES
+# -------------------------------------------------------
+# Tests whether HEADER exists and can be compiled using the include files in
+# INCLUDES, setting the cache variable VAR accordingly.
+ac_fn_c_check_header_compile ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+#include <$2>
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ eval "$3=yes"
+else
+ eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_header_compile
+
+# ac_fn_c_check_func LINENO FUNC VAR
+# ----------------------------------
+# Tests whether FUNC exists, setting the cache variable VAR accordingly
+ac_fn_c_check_func ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+/* Define $2 to an innocuous variant, in case <limits.h> declares $2.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define $2 innocuous_$2
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $2 (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $2
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $2 ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined __stub_$2 || defined __stub___$2
+choke me
+#endif
+
+int
+main ()
+{
+return $2 ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ eval "$3=yes"
+else
+ eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_func
+cat >config.log <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by breakpad $as_me 0.1, which was
+generated by GNU Autoconf 2.69. Invocation command line was
+
+ $ $0 $@
+
+_ACEOF
+exec 5>>config.log
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown`
+
+/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown`
+/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown`
+/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ $as_echo "PATH: $as_dir"
+ done
+IFS=$as_save_IFS
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+ for ac_arg
+ do
+ case $ac_arg in
+ -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ continue ;;
+ *\'*)
+ ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ case $ac_pass in
+ 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;;
+ 2)
+ as_fn_append ac_configure_args1 " '$ac_arg'"
+ if test $ac_must_keep_next = true; then
+ ac_must_keep_next=false # Got value, back to normal.
+ else
+ case $ac_arg in
+ *=* | --config-cache | -C | -disable-* | --disable-* \
+ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+ | -with-* | --with-* | -without-* | --without-* | --x)
+ case "$ac_configure_args0 " in
+ "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+ esac
+ ;;
+ -* ) ac_must_keep_next=true ;;
+ esac
+ fi
+ as_fn_append ac_configure_args " '$ac_arg'"
+ ;;
+ esac
+ done
+done
+{ ac_configure_args0=; unset ac_configure_args0;}
+{ ac_configure_args1=; unset ac_configure_args1;}
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log. We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Use '\'' to represent an apostrophe within the trap.
+# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
+trap 'exit_status=$?
+ # Save into config.log some information that might help in debugging.
+ {
+ echo
+
+ $as_echo "## ---------------- ##
+## Cache variables. ##
+## ---------------- ##"
+ echo
+ # The following way of writing the cache mishandles newlines in values,
+(
+ for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
+ eval ac_val=\$$ac_var
+ case $ac_val in #(
+ *${as_nl}*)
+ case $ac_var in #(
+ *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+ esac
+ case $ac_var in #(
+ _ | IFS | as_nl) ;; #(
+ BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+ *) { eval $ac_var=; unset $ac_var;} ;;
+ esac ;;
+ esac
+ done
+ (set) 2>&1 |
+ case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(
+ *${as_nl}ac_space=\ *)
+ sed -n \
+ "s/'\''/'\''\\\\'\'''\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"
+ ;; #(
+ *)
+ sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+ ;;
+ esac |
+ sort
+)
+ echo
+
+ $as_echo "## ----------------- ##
+## Output variables. ##
+## ----------------- ##"
+ echo
+ for ac_var in $ac_subst_vars
+ do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ esac
+ $as_echo "$ac_var='\''$ac_val'\''"
+ done | sort
+ echo
+
+ if test -n "$ac_subst_files"; then
+ $as_echo "## ------------------- ##
+## File substitutions. ##
+## ------------------- ##"
+ echo
+ for ac_var in $ac_subst_files
+ do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ esac
+ $as_echo "$ac_var='\''$ac_val'\''"
+ done | sort
+ echo
+ fi
+
+ if test -s confdefs.h; then
+ $as_echo "## ----------- ##
+## confdefs.h. ##
+## ----------- ##"
+ echo
+ cat confdefs.h
+ echo
+ fi
+ test "$ac_signal" != 0 &&
+ $as_echo "$as_me: caught signal $ac_signal"
+ $as_echo "$as_me: exit $exit_status"
+ } >&5
+ rm -f core *.core core.conftest.* &&
+ rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
+ exit $exit_status
+' 0
+for ac_signal in 1 2 13 15; do
+ trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -f -r conftest* confdefs.h
+
+$as_echo "/* confdefs.h */" > confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_URL "$PACKAGE_URL"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer an explicitly selected file to automatically selected ones.
+ac_site_file1=NONE
+ac_site_file2=NONE
+if test -n "$CONFIG_SITE"; then
+ # We do not want a PATH search for config.site.
+ case $CONFIG_SITE in #((
+ -*) ac_site_file1=./$CONFIG_SITE;;
+ */*) ac_site_file1=$CONFIG_SITE;;
+ *) ac_site_file1=./$CONFIG_SITE;;
+ esac
+elif test "x$prefix" != xNONE; then
+ ac_site_file1=$prefix/share/config.site
+ ac_site_file2=$prefix/etc/config.site
+else
+ ac_site_file1=$ac_default_prefix/share/config.site
+ ac_site_file2=$ac_default_prefix/etc/config.site
+fi
+for ac_site_file in "$ac_site_file1" "$ac_site_file2"
+do
+ test "x$ac_site_file" = xNONE && continue
+ if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
+$as_echo "$as_me: loading site script $ac_site_file" >&6;}
+ sed 's/^/| /' "$ac_site_file" >&5
+ . "$ac_site_file" \
+ || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "failed to load site script $ac_site_file
+See \`config.log' for more details" "$LINENO" 5; }
+ fi
+done
+
+if test -r "$cache_file"; then
+ # Some versions of bash will fail to source /dev/null (special files
+ # actually), so we avoid doing that. DJGPP emulates it as a regular file.
+ if test /dev/null != "$cache_file" && test -f "$cache_file"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
+$as_echo "$as_me: loading cache $cache_file" >&6;}
+ case $cache_file in
+ [\\/]* | ?:[\\/]* ) . "$cache_file";;
+ *) . "./$cache_file";;
+ esac
+ fi
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5
+$as_echo "$as_me: creating cache $cache_file" >&6;}
+ >$cache_file
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in $ac_precious_vars; do
+ eval ac_old_set=\$ac_cv_env_${ac_var}_set
+ eval ac_new_set=\$ac_env_${ac_var}_set
+ eval ac_old_val=\$ac_cv_env_${ac_var}_value
+ eval ac_new_val=\$ac_env_${ac_var}_value
+ case $ac_old_set,$ac_new_set in
+ set,)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,set)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,);;
+ *)
+ if test "x$ac_old_val" != "x$ac_new_val"; then
+ # differences in whitespace do not lead to failure.
+ ac_old_val_w=`echo x $ac_old_val`
+ ac_new_val_w=`echo x $ac_new_val`
+ if test "$ac_old_val_w" != "$ac_new_val_w"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5
+$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+ ac_cache_corrupted=:
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
+$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
+ eval $ac_var=\$ac_old_val
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5
+$as_echo "$as_me: former value: \`$ac_old_val'" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5
+$as_echo "$as_me: current value: \`$ac_new_val'" >&2;}
+ fi;;
+ esac
+ # Pass precious variables to config.status.
+ if test "$ac_new_set" = set; then
+ case $ac_new_val in
+ *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+ *) ac_arg=$ac_var=$ac_new_val ;;
+ esac
+ case " $ac_configure_args " in
+ *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy.
+ *) as_fn_append ac_configure_args " '$ac_arg'" ;;
+ esac
+ fi
+done
+if $ac_cache_corrupted; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
+$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+ as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5
+fi
+## -------------------- ##
+## Main body of script. ##
+## -------------------- ##
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+ac_aux_dir=
+for ac_dir in autotools "$srcdir"/autotools; do
+ if test -f "$ac_dir/install-sh"; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install-sh -c"
+ break
+ elif test -f "$ac_dir/install.sh"; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install.sh -c"
+ break
+ elif test -f "$ac_dir/shtool"; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/shtool install -c"
+ break
+ fi
+done
+if test -z "$ac_aux_dir"; then
+ as_fn_error $? "cannot find install-sh, install.sh, or shtool in autotools \"$srcdir\"/autotools" "$LINENO" 5
+fi
+
+# These three variables are undocumented and unsupported,
+# and are intended to be withdrawn in a future Autoconf release.
+# They can cause serious problems if a builder's source tree is in a directory
+# whose full name contains unusual characters.
+ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var.
+ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var.
+ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var.
+
+
+
+# Make sure we can run config.sub.
+$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 ||
+ as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5
+$as_echo_n "checking build system type... " >&6; }
+if ${ac_cv_build+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_build_alias=$build_alias
+test "x$ac_build_alias" = x &&
+ ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"`
+test "x$ac_build_alias" = x &&
+ as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5
+ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` ||
+ as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5
+$as_echo "$ac_cv_build" >&6; }
+case $ac_cv_build in
+*-*-*) ;;
+*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;;
+esac
+build=$ac_cv_build
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_build
+shift
+build_cpu=$1
+build_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+build_os=$*
+IFS=$ac_save_IFS
+case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5
+$as_echo_n "checking host system type... " >&6; }
+if ${ac_cv_host+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test "x$host_alias" = x; then
+ ac_cv_host=$ac_cv_build
+else
+ ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` ||
+ as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5
+$as_echo "$ac_cv_host" >&6; }
+case $ac_cv_host in
+*-*-*) ;;
+*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;;
+esac
+host=$ac_cv_host
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_host
+shift
+host_cpu=$1
+host_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+host_os=$*
+IFS=$ac_save_IFS
+case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac
+
+
+
+am__api_version='1.15'
+
+# Find a good install program. We prefer a C program (faster),
+# so one script is as good as another. But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AmigaOS /C/install, which installs bootblocks on floppy discs
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# OS/2's system install, which has a completely different semantic
+# ./install, which can be erroneously created by make from ./install.sh.
+# Reject install programs that cannot install multiple files.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5
+$as_echo_n "checking for a BSD-compatible install... " >&6; }
+if test -z "$INSTALL"; then
+if ${ac_cv_path_install+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ # Account for people who put trailing slashes in PATH elements.
+case $as_dir/ in #((
+ ./ | .// | /[cC]/* | \
+ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
+ ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \
+ /usr/ucb/* ) ;;
+ *)
+ # OSF1 and SCO ODT 3.0 have their own names for install.
+ # Don't use installbsd from OSF since it installs stuff as root
+ # by default.
+ for ac_prog in ginstall scoinst install; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then
+ if test $ac_prog = install &&
+ grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+ # AIX install. It has an incompatible calling convention.
+ :
+ elif test $ac_prog = install &&
+ grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+ # program-specific install script used by HP pwplus--don't use.
+ :
+ else
+ rm -rf conftest.one conftest.two conftest.dir
+ echo one > conftest.one
+ echo two > conftest.two
+ mkdir conftest.dir
+ if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" &&
+ test -s conftest.one && test -s conftest.two &&
+ test -s conftest.dir/conftest.one &&
+ test -s conftest.dir/conftest.two
+ then
+ ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
+ break 3
+ fi
+ fi
+ fi
+ done
+ done
+ ;;
+esac
+
+ done
+IFS=$as_save_IFS
+
+rm -rf conftest.one conftest.two conftest.dir
+
+fi
+ if test "${ac_cv_path_install+set}" = set; then
+ INSTALL=$ac_cv_path_install
+ else
+ # As a last resort, use the slow shell script. Don't cache a
+ # value for INSTALL within a source directory, because that will
+ # break other packages using the cache if that directory is
+ # removed, or if the value is a relative name.
+ INSTALL=$ac_install_sh
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5
+$as_echo "$INSTALL" >&6; }
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5
+$as_echo_n "checking whether build environment is sane... " >&6; }
+# Reject unsafe characters in $srcdir or the absolute working directory
+# name. Accept space and tab only in the latter.
+am_lf='
+'
+case `pwd` in
+ *[\\\"\#\$\&\'\`$am_lf]*)
+ as_fn_error $? "unsafe absolute working directory name" "$LINENO" 5;;
+esac
+case $srcdir in
+ *[\\\"\#\$\&\'\`$am_lf\ \ ]*)
+ as_fn_error $? "unsafe srcdir value: '$srcdir'" "$LINENO" 5;;
+esac
+
+# Do 'set' in a subshell so we don't clobber the current shell's
+# arguments. Must try -L first in case configure is actually a
+# symlink; some systems play weird games with the mod time of symlinks
+# (eg FreeBSD returns the mod time of the symlink's containing
+# directory).
+if (
+ am_has_slept=no
+ for am_try in 1 2; do
+ echo "timestamp, slept: $am_has_slept" > conftest.file
+ set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null`
+ if test "$*" = "X"; then
+ # -L didn't work.
+ set X `ls -t "$srcdir/configure" conftest.file`
+ fi
+ if test "$*" != "X $srcdir/configure conftest.file" \
+ && test "$*" != "X conftest.file $srcdir/configure"; then
+
+ # If neither matched, then we have a broken ls. This can happen
+ # if, for instance, CONFIG_SHELL is bash and it inherits a
+ # broken ls alias from the environment. This has actually
+ # happened. Such a system could not be considered "sane".
+ as_fn_error $? "ls -t appears to fail. Make sure there is not a broken
+ alias in your environment" "$LINENO" 5
+ fi
+ if test "$2" = conftest.file || test $am_try -eq 2; then
+ break
+ fi
+ # Just in case.
+ sleep 1
+ am_has_slept=yes
+ done
+ test "$2" = conftest.file
+ )
+then
+ # Ok.
+ :
+else
+ as_fn_error $? "newly created file is older than distributed files!
+Check your system clock" "$LINENO" 5
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+# If we didn't sleep, we still need to ensure time stamps of config.status and
+# generated files are strictly newer.
+am_sleep_pid=
+if grep 'slept: no' conftest.file >/dev/null 2>&1; then
+ ( sleep 1 ) &
+ am_sleep_pid=$!
+fi
+
+rm -f conftest.file
+
+test "$program_prefix" != NONE &&
+ program_transform_name="s&^&$program_prefix&;$program_transform_name"
+# Use a double $ so make ignores it.
+test "$program_suffix" != NONE &&
+ program_transform_name="s&\$&$program_suffix&;$program_transform_name"
+# Double any \ or $.
+# By default was `s,x,x', remove it if useless.
+ac_script='s/[\\$]/&&/g;s/;s,x,x,$//'
+program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"`
+
+# Expand $ac_aux_dir to an absolute path.
+am_aux_dir=`cd "$ac_aux_dir" && pwd`
+
+if test x"${MISSING+set}" != xset; then
+ case $am_aux_dir in
+ *\ * | *\ *)
+ MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;;
+ *)
+ MISSING="\${SHELL} $am_aux_dir/missing" ;;
+ esac
+fi
+# Use eval to expand $SHELL
+if eval "$MISSING --is-lightweight"; then
+ am_missing_run="$MISSING "
+else
+ am_missing_run=
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 'missing' script is too old or missing" >&5
+$as_echo "$as_me: WARNING: 'missing' script is too old or missing" >&2;}
+fi
+
+if test x"${install_sh+set}" != xset; then
+ case $am_aux_dir in
+ *\ * | *\ *)
+ install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;;
+ *)
+ install_sh="\${SHELL} $am_aux_dir/install-sh"
+ esac
+fi
+
+# Installed binaries are usually stripped using 'strip' when the user
+# run "make install-strip". However 'strip' might not be the right
+# tool to use in cross-compilation environments, therefore Automake
+# will honor the 'STRIP' environment variable to overrule this program.
+if test "$cross_compiling" != no; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args.
+set dummy ${ac_tool_prefix}strip; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_STRIP+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$STRIP"; then
+ ac_cv_prog_STRIP="$STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_STRIP="${ac_tool_prefix}strip"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+STRIP=$ac_cv_prog_STRIP
+if test -n "$STRIP"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5
+$as_echo "$STRIP" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_STRIP"; then
+ ac_ct_STRIP=$STRIP
+ # Extract the first word of "strip", so it can be a program name with args.
+set dummy strip; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_STRIP+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_STRIP"; then
+ ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_STRIP="strip"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP
+if test -n "$ac_ct_STRIP"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5
+$as_echo "$ac_ct_STRIP" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_STRIP" = x; then
+ STRIP=":"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ STRIP=$ac_ct_STRIP
+ fi
+else
+ STRIP="$ac_cv_prog_STRIP"
+fi
+
+fi
+INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5
+$as_echo_n "checking for a thread-safe mkdir -p... " >&6; }
+if test -z "$MKDIR_P"; then
+ if ${ac_cv_path_mkdir+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_prog in mkdir gmkdir; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext" || continue
+ case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #(
+ 'mkdir (GNU coreutils) '* | \
+ 'mkdir (coreutils) '* | \
+ 'mkdir (fileutils) '4.1*)
+ ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext
+ break 3;;
+ esac
+ done
+ done
+ done
+IFS=$as_save_IFS
+
+fi
+
+ test -d ./--version && rmdir ./--version
+ if test "${ac_cv_path_mkdir+set}" = set; then
+ MKDIR_P="$ac_cv_path_mkdir -p"
+ else
+ # As a last resort, use the slow shell script. Don't cache a
+ # value for MKDIR_P within a source directory, because that will
+ # break other packages using the cache if that directory is
+ # removed, or if the value is a relative name.
+ MKDIR_P="$ac_install_sh -d"
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5
+$as_echo "$MKDIR_P" >&6; }
+
+for ac_prog in gawk mawk nawk awk
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_AWK+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$AWK"; then
+ ac_cv_prog_AWK="$AWK" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_AWK="$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+AWK=$ac_cv_prog_AWK
+if test -n "$AWK"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5
+$as_echo "$AWK" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$AWK" && break
+done
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5
+$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; }
+set x ${MAKE-make}
+ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'`
+if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat >conftest.make <<\_ACEOF
+SHELL = /bin/sh
+all:
+ @echo '@@@%%%=$(MAKE)=@@@%%%'
+_ACEOF
+# GNU make sometimes prints "make[1]: Entering ...", which would confuse us.
+case `${MAKE-make} -f conftest.make 2>/dev/null` in
+ *@@@%%%=?*=@@@%%%*)
+ eval ac_cv_prog_make_${ac_make}_set=yes;;
+ *)
+ eval ac_cv_prog_make_${ac_make}_set=no;;
+esac
+rm -f conftest.make
+fi
+if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ SET_MAKE=
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ SET_MAKE="MAKE=${MAKE-make}"
+fi
+
+rm -rf .tst 2>/dev/null
+mkdir .tst 2>/dev/null
+if test -d .tst; then
+ am__leading_dot=.
+else
+ am__leading_dot=_
+fi
+rmdir .tst 2>/dev/null
+
+# Check whether --enable-silent-rules was given.
+if test "${enable_silent_rules+set}" = set; then :
+ enableval=$enable_silent_rules;
+fi
+
+case $enable_silent_rules in # (((
+ yes) AM_DEFAULT_VERBOSITY=0;;
+ no) AM_DEFAULT_VERBOSITY=1;;
+ *) AM_DEFAULT_VERBOSITY=1;;
+esac
+am_make=${MAKE-make}
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5
+$as_echo_n "checking whether $am_make supports nested variables... " >&6; }
+if ${am_cv_make_support_nested_variables+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if $as_echo 'TRUE=$(BAR$(V))
+BAR0=false
+BAR1=true
+V=1
+am__doit:
+ @$(TRUE)
+.PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then
+ am_cv_make_support_nested_variables=yes
+else
+ am_cv_make_support_nested_variables=no
+fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5
+$as_echo "$am_cv_make_support_nested_variables" >&6; }
+if test $am_cv_make_support_nested_variables = yes; then
+ AM_V='$(V)'
+ AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)'
+else
+ AM_V=$AM_DEFAULT_VERBOSITY
+ AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY
+fi
+AM_BACKSLASH='\'
+
+if test "`cd $srcdir && pwd`" != "`pwd`"; then
+ # Use -I$(srcdir) only when $(srcdir) != ., so that make's output
+ # is not polluted with repeated "-I."
+ am__isrc=' -I$(srcdir)'
+ # test to see if srcdir already configured
+ if test -f $srcdir/config.status; then
+ as_fn_error $? "source directory already configured; run \"make distclean\" there first" "$LINENO" 5
+ fi
+fi
+
+# test whether we have cygpath
+if test -z "$CYGPATH_W"; then
+ if (cygpath --version) >/dev/null 2>/dev/null; then
+ CYGPATH_W='cygpath -w'
+ else
+ CYGPATH_W=echo
+ fi
+fi
+
+
+# Define the identity of the package.
+ PACKAGE='breakpad'
+ VERSION='0.1'
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE "$PACKAGE"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define VERSION "$VERSION"
+_ACEOF
+
+# Some tools Automake needs.
+
+ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"}
+
+
+AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"}
+
+
+AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"}
+
+
+AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"}
+
+
+MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"}
+
+# For better backward compatibility. To be removed once Automake 1.9.x
+# dies out for good. For more background, see:
+# <http://lists.gnu.org/archive/html/automake/2012-07/msg00001.html>
+# <http://lists.gnu.org/archive/html/automake/2012-07/msg00014.html>
+mkdir_p='$(MKDIR_P)'
+
+# We need awk for the "check" target (and possibly the TAP driver). The
+# system "awk" is bad on some platforms.
+# Always define AMTAR for backward compatibility. Yes, it's still used
+# in the wild :-( We should find a proper way to deprecate it ...
+AMTAR='$${TAR-tar}'
+
+
+# We'll loop over all known methods to create a tar archive until one works.
+_am_tools='gnutar plaintar pax cpio none'
+
+# The POSIX 1988 'ustar' format is defined with fixed-size fields.
+ # There is notably a 21 bits limit for the UID and the GID. In fact,
+ # the 'pax' utility can hang on bigger UID/GID (see automake bug#8343
+ # and bug#13588).
+ am_max_uid=2097151 # 2^21 - 1
+ am_max_gid=$am_max_uid
+ # The $UID and $GID variables are not portable, so we need to resort
+ # to the POSIX-mandated id(1) utility. Errors in the 'id' calls
+ # below are definitely unexpected, so allow the users to see them
+ # (that is, avoid stderr redirection).
+ am_uid=`id -u || echo unknown`
+ am_gid=`id -g || echo unknown`
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether UID '$am_uid' is supported by ustar format" >&5
+$as_echo_n "checking whether UID '$am_uid' is supported by ustar format... " >&6; }
+ if test $am_uid -le $am_max_uid; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ _am_tools=none
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether GID '$am_gid' is supported by ustar format" >&5
+$as_echo_n "checking whether GID '$am_gid' is supported by ustar format... " >&6; }
+ if test $am_gid -le $am_max_gid; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ _am_tools=none
+ fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to create a ustar tar archive" >&5
+$as_echo_n "checking how to create a ustar tar archive... " >&6; }
+
+ # Go ahead even if we have the value already cached. We do so because we
+ # need to set the values for the 'am__tar' and 'am__untar' variables.
+ _am_tools=${am_cv_prog_tar_ustar-$_am_tools}
+
+ for _am_tool in $_am_tools; do
+ case $_am_tool in
+ gnutar)
+ for _am_tar in tar gnutar gtar; do
+ { echo "$as_me:$LINENO: $_am_tar --version" >&5
+ ($_am_tar --version) >&5 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && break
+ done
+ am__tar="$_am_tar --format=ustar -chf - "'"$$tardir"'
+ am__tar_="$_am_tar --format=ustar -chf - "'"$tardir"'
+ am__untar="$_am_tar -xf -"
+ ;;
+ plaintar)
+ # Must skip GNU tar: if it does not support --format= it doesn't create
+ # ustar tarball either.
+ (tar --version) >/dev/null 2>&1 && continue
+ am__tar='tar chf - "$$tardir"'
+ am__tar_='tar chf - "$tardir"'
+ am__untar='tar xf -'
+ ;;
+ pax)
+ am__tar='pax -L -x ustar -w "$$tardir"'
+ am__tar_='pax -L -x ustar -w "$tardir"'
+ am__untar='pax -r'
+ ;;
+ cpio)
+ am__tar='find "$$tardir" -print | cpio -o -H ustar -L'
+ am__tar_='find "$tardir" -print | cpio -o -H ustar -L'
+ am__untar='cpio -i -H ustar -d'
+ ;;
+ none)
+ am__tar=false
+ am__tar_=false
+ am__untar=false
+ ;;
+ esac
+
+ # If the value was cached, stop now. We just wanted to have am__tar
+ # and am__untar set.
+ test -n "${am_cv_prog_tar_ustar}" && break
+
+ # tar/untar a dummy directory, and stop if the command works.
+ rm -rf conftest.dir
+ mkdir conftest.dir
+ echo GrepMe > conftest.dir/file
+ { echo "$as_me:$LINENO: tardir=conftest.dir && eval $am__tar_ >conftest.tar" >&5
+ (tardir=conftest.dir && eval $am__tar_ >conftest.tar) >&5 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+ rm -rf conftest.dir
+ if test -s conftest.tar; then
+ { echo "$as_me:$LINENO: $am__untar <conftest.tar" >&5
+ ($am__untar <conftest.tar) >&5 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+ { echo "$as_me:$LINENO: cat conftest.dir/file" >&5
+ (cat conftest.dir/file) >&5 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+ grep GrepMe conftest.dir/file >/dev/null 2>&1 && break
+ fi
+ done
+ rm -rf conftest.dir
+
+ if ${am_cv_prog_tar_ustar+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ am_cv_prog_tar_ustar=$_am_tool
+fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_tar_ustar" >&5
+$as_echo "$am_cv_prog_tar_ustar" >&6; }
+
+
+
+
+
+
+# POSIX will say in a future version that running "rm -f" with no argument
+# is OK; and we want to be able to make that assumption in our Makefile
+# recipes. So use an aggressive probe to check that the usage we want is
+# actually supported "in the wild" to an acceptable degree.
+# See automake bug#10828.
+# To make any issue more visible, cause the running configure to be aborted
+# by default if the 'rm' program in use doesn't match our expectations; the
+# user can still override this though.
+if rm -f && rm -fr && rm -rf; then : OK; else
+ cat >&2 <<'END'
+Oops!
+
+Your 'rm' program seems unable to run without file operands specified
+on the command line, even when the '-f' option is present. This is contrary
+to the behaviour of most rm programs out there, and not conforming with
+the upcoming POSIX standard: <http://austingroupbugs.net/view.php?id=542>
+
+Please tell bug-automake@gnu.org about your system, including the value
+of your $PATH and any error possibly output before this message. This
+can help us improve future automake versions.
+
+END
+ if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then
+ echo 'Configuration will proceed anyway, since you have set the' >&2
+ echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2
+ echo >&2
+ else
+ cat >&2 <<'END'
+Aborting the configuration process, to ensure you take notice of the issue.
+
+You can download and install GNU coreutils to get an 'rm' implementation
+that behaves properly: <http://www.gnu.org/software/coreutils/>.
+
+If you want to complete the configuration process using your problematic
+'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM
+to "yes", and re-run configure.
+
+END
+ as_fn_error $? "Your 'rm' program is bad, sorry." "$LINENO" 5
+ fi
+fi
+
+ac_config_headers="$ac_config_headers src/config.h"
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable maintainer-specific portions of Makefiles" >&5
+$as_echo_n "checking whether to enable maintainer-specific portions of Makefiles... " >&6; }
+ # Check whether --enable-maintainer-mode was given.
+if test "${enable_maintainer_mode+set}" = set; then :
+ enableval=$enable_maintainer_mode; USE_MAINTAINER_MODE=$enableval
+else
+ USE_MAINTAINER_MODE=no
+fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $USE_MAINTAINER_MODE" >&5
+$as_echo "$USE_MAINTAINER_MODE" >&6; }
+ if test $USE_MAINTAINER_MODE = yes; then
+ MAINTAINER_MODE_TRUE=
+ MAINTAINER_MODE_FALSE='#'
+else
+ MAINTAINER_MODE_TRUE='#'
+ MAINTAINER_MODE_FALSE=
+fi
+
+ MAINT=$MAINTAINER_MODE_TRUE
+
+
+
+DEPDIR="${am__leading_dot}deps"
+
+ac_config_commands="$ac_config_commands depfiles"
+
+
+am_make=${MAKE-make}
+cat > confinc << 'END'
+am__doit:
+ @echo this is the am__doit target
+.PHONY: am__doit
+END
+# If we don't find an include directive, just comment out the code.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for style of include used by $am_make" >&5
+$as_echo_n "checking for style of include used by $am_make... " >&6; }
+am__include="#"
+am__quote=
+_am_result=none
+# First try GNU make style include.
+echo "include confinc" > confmf
+# Ignore all kinds of additional output from 'make'.
+case `$am_make -s -f confmf 2> /dev/null` in #(
+*the\ am__doit\ target*)
+ am__include=include
+ am__quote=
+ _am_result=GNU
+ ;;
+esac
+# Now try BSD make style include.
+if test "$am__include" = "#"; then
+ echo '.include "confinc"' > confmf
+ case `$am_make -s -f confmf 2> /dev/null` in #(
+ *the\ am__doit\ target*)
+ am__include=.include
+ am__quote="\""
+ _am_result=BSD
+ ;;
+ esac
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $_am_result" >&5
+$as_echo "$_am_result" >&6; }
+rm -f confinc confmf
+
+# Check whether --enable-dependency-tracking was given.
+if test "${enable_dependency_tracking+set}" = set; then :
+ enableval=$enable_dependency_tracking;
+fi
+
+if test "x$enable_dependency_tracking" != xno; then
+ am_depcomp="$ac_aux_dir/depcomp"
+ AMDEPBACKSLASH='\'
+ am__nodep='_no'
+fi
+ if test "x$enable_dependency_tracking" != xno; then
+ AMDEP_TRUE=
+ AMDEP_FALSE='#'
+else
+ AMDEP_TRUE='#'
+ AMDEP_FALSE=
+fi
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="${ac_tool_prefix}gcc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+ ac_ct_CC=$CC
+ # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CC="gcc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+else
+ CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="${ac_tool_prefix}cc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ fi
+fi
+if test -z "$CC"; then
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+ ac_prog_rejected=yes
+ continue
+ fi
+ ac_cv_prog_CC="cc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+if test $ac_prog_rejected = yes; then
+ # We found a bogon in the path, so make sure we never use it.
+ set dummy $ac_cv_prog_CC
+ shift
+ if test $# != 0; then
+ # We chose a different compiler from the bogus one.
+ # However, it has the same basename, so the bogon will be chosen
+ # first if we set CC to just the basename; use the full file name.
+ shift
+ ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+ fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ for ac_prog in cl.exe
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$CC" && break
+ done
+fi
+if test -z "$CC"; then
+ ac_ct_CC=$CC
+ for ac_prog in cl.exe
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CC="$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$ac_ct_CC" && break
+done
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+fi
+
+fi
+
+
+test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "no acceptable C compiler found in \$PATH
+See \`config.log' for more details" "$LINENO" 5; }
+
+# Provide some information about the compiler.
+$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion; do
+ { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ sed '10a\
+... rest of stderr output deleted ...
+ 10q' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ fi
+ rm -f conftest.er1 conftest.err
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+done
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5
+$as_echo_n "checking whether the C compiler works... " >&6; }
+ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+
+# The possible output files:
+ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*"
+
+ac_rmfiles=
+for ac_file in $ac_files
+do
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+ * ) ac_rmfiles="$ac_rmfiles $ac_file";;
+ esac
+done
+rm -f $ac_rmfiles
+
+if { { ac_try="$ac_link_default"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link_default") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then :
+ # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
+# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
+# in a Makefile. We should not override ac_cv_exeext if it was cached,
+# so that the user can short-circuit this test for compilers unknown to
+# Autoconf.
+for ac_file in $ac_files ''
+do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj )
+ ;;
+ [ab].out )
+ # We found the default executable, but exeext='' is most
+ # certainly right.
+ break;;
+ *.* )
+ if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
+ then :; else
+ ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ fi
+ # We set ac_cv_exeext here because the later test for it is not
+ # safe: cross compilers may not add the suffix if given an `-o'
+ # argument, so we may need to know it at that point already.
+ # Even if this section looks crufty: it has the advantage of
+ # actually working.
+ break;;
+ * )
+ break;;
+ esac
+done
+test "$ac_cv_exeext" = no && ac_cv_exeext=
+
+else
+ ac_file=''
+fi
+if test -z "$ac_file"; then :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+$as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "C compiler cannot create executables
+See \`config.log' for more details" "$LINENO" 5; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5
+$as_echo_n "checking for C compiler default output file name... " >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5
+$as_echo "$ac_file" >&6; }
+ac_exeext=$ac_cv_exeext
+
+rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out
+ac_clean_files=$ac_clean_files_save
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5
+$as_echo_n "checking for suffix of executables... " >&6; }
+if { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then :
+ # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+ *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ break;;
+ * ) break;;
+ esac
+done
+else
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+rm -f conftest conftest$ac_cv_exeext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
+$as_echo "$ac_cv_exeext" >&6; }
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdio.h>
+int
+main ()
+{
+FILE *f = fopen ("conftest.out", "w");
+ return ferror (f) || fclose (f) != 0;
+
+ ;
+ return 0;
+}
+_ACEOF
+ac_clean_files="$ac_clean_files conftest.out"
+# Check that the compiler produces executables we can run. If not, either
+# the compiler is broken, or we cross compile.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5
+$as_echo_n "checking whether we are cross compiling... " >&6; }
+if test "$cross_compiling" != yes; then
+ { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ if { ac_try='./conftest$ac_cv_exeext'
+ { { case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; }; then
+ cross_compiling=no
+ else
+ if test "$cross_compiling" = maybe; then
+ cross_compiling=yes
+ else
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details" "$LINENO" 5; }
+ fi
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
+$as_echo "$cross_compiling" >&6; }
+
+rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out
+ac_clean_files=$ac_clean_files_save
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
+$as_echo_n "checking for suffix of object files... " >&6; }
+if ${ac_cv_objext+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { { ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compile") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then :
+ for ac_file in conftest.o conftest.obj conftest.*; do
+ test -f "$ac_file" || continue;
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;;
+ *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+ break;;
+ esac
+done
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot compute suffix of object files: cannot compile
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5
+$as_echo "$ac_cv_objext" >&6; }
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5
+$as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
+if ${ac_cv_c_compiler_gnu+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+#ifndef __GNUC__
+ choke me
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_compiler_gnu=yes
+else
+ ac_compiler_gnu=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
+$as_echo "$ac_cv_c_compiler_gnu" >&6; }
+if test $ac_compiler_gnu = yes; then
+ GCC=yes
+else
+ GCC=
+fi
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
+$as_echo_n "checking whether $CC accepts -g... " >&6; }
+if ${ac_cv_prog_cc_g+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_save_c_werror_flag=$ac_c_werror_flag
+ ac_c_werror_flag=yes
+ ac_cv_prog_cc_g=no
+ CFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_g=yes
+else
+ CFLAGS=""
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+else
+ ac_c_werror_flag=$ac_save_c_werror_flag
+ CFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_g=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ac_c_werror_flag=$ac_save_c_werror_flag
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
+$as_echo "$ac_cv_prog_cc_g" >&6; }
+if test "$ac_test_CFLAGS" = set; then
+ CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+ if test "$GCC" = yes; then
+ CFLAGS="-g -O2"
+ else
+ CFLAGS="-g"
+ fi
+else
+ if test "$GCC" = yes; then
+ CFLAGS="-O2"
+ else
+ CFLAGS=
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5
+$as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
+if ${ac_cv_prog_cc_c89+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdarg.h>
+#include <stdio.h>
+struct stat;
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+ char **p;
+ int i;
+{
+ return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+ char *s;
+ va_list v;
+ va_start (v,p);
+ s = g (p, va_arg (v,int));
+ va_end (v);
+ return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has
+ function prototypes and stuff, but not '\xHH' hex character constants.
+ These don't provoke an error unfortunately, instead are silently treated
+ as 'x'. The following induces an error, until -std is added to get
+ proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an
+ array size at least. It's necessary to write '\x00'==0 to get something
+ that's true only with -std. */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+ inside strings and character constants. */
+#define FOO(x) 'x'
+int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1];
+ ;
+ return 0;
+}
+_ACEOF
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
+ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+ CC="$ac_save_CC $ac_arg"
+ if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_c89=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext
+ test "x$ac_cv_prog_cc_c89" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+
+fi
+# AC_CACHE_VAL
+case "x$ac_cv_prog_cc_c89" in
+ x)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+$as_echo "none needed" >&6; } ;;
+ xno)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+$as_echo "unsupported" >&6; } ;;
+ *)
+ CC="$CC $ac_cv_prog_cc_c89"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
+$as_echo "$ac_cv_prog_cc_c89" >&6; } ;;
+esac
+if test "x$ac_cv_prog_cc_c89" != xno; then :
+
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together" >&5
+$as_echo_n "checking whether $CC understands -c and -o together... " >&6; }
+if ${am_cv_prog_cc_c_o+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+ # Make sure it works both with $CC and with simple cc.
+ # Following AC_PROG_CC_C_O, we do the test twice because some
+ # compilers refuse to overwrite an existing .o file with -o,
+ # though they will create one.
+ am_cv_prog_cc_c_o=yes
+ for am_i in 1 2; do
+ if { echo "$as_me:$LINENO: $CC -c conftest.$ac_ext -o conftest2.$ac_objext" >&5
+ ($CC -c conftest.$ac_ext -o conftest2.$ac_objext) >&5 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } \
+ && test -f conftest2.$ac_objext; then
+ : OK
+ else
+ am_cv_prog_cc_c_o=no
+ break
+ fi
+ done
+ rm -f core conftest*
+ unset am_i
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5
+$as_echo "$am_cv_prog_cc_c_o" >&6; }
+if test "$am_cv_prog_cc_c_o" != yes; then
+ # Losing compiler, so override with the script.
+ # FIXME: It is wrong to rewrite CC.
+ # But if we don't then we get into trouble of one sort or another.
+ # A longer-term fix would be to have automake use am__CC in this case,
+ # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)"
+ CC="$am_aux_dir/compile $CC"
+fi
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+depcc="$CC" am_compiler_list=
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5
+$as_echo_n "checking dependency style of $depcc... " >&6; }
+if ${am_cv_CC_dependencies_compiler_type+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+ # We make a subdir and do the tests there. Otherwise we can end up
+ # making bogus files that we don't know about and never remove. For
+ # instance it was reported that on HP-UX the gcc test will end up
+ # making a dummy file named 'D' -- because '-MD' means "put the output
+ # in D".
+ rm -rf conftest.dir
+ mkdir conftest.dir
+ # Copy depcomp to subdir because otherwise we won't find it if we're
+ # using a relative directory.
+ cp "$am_depcomp" conftest.dir
+ cd conftest.dir
+ # We will build objects and dependencies in a subdirectory because
+ # it helps to detect inapplicable dependency modes. For instance
+ # both Tru64's cc and ICC support -MD to output dependencies as a
+ # side effect of compilation, but ICC will put the dependencies in
+ # the current directory while Tru64 will put them in the object
+ # directory.
+ mkdir sub
+
+ am_cv_CC_dependencies_compiler_type=none
+ if test "$am_compiler_list" = ""; then
+ am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp`
+ fi
+ am__universal=false
+ case " $depcc " in #(
+ *\ -arch\ *\ -arch\ *) am__universal=true ;;
+ esac
+
+ for depmode in $am_compiler_list; do
+ # Setup a source with many dependencies, because some compilers
+ # like to wrap large dependency lists on column 80 (with \), and
+ # we should not choose a depcomp mode which is confused by this.
+ #
+ # We need to recreate these files for each test, as the compiler may
+ # overwrite some of them when testing with obscure command lines.
+ # This happens at least with the AIX C compiler.
+ : > sub/conftest.c
+ for i in 1 2 3 4 5 6; do
+ echo '#include "conftst'$i'.h"' >> sub/conftest.c
+ # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with
+ # Solaris 10 /bin/sh.
+ echo '/* dummy */' > sub/conftst$i.h
+ done
+ echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+
+ # We check with '-c' and '-o' for the sake of the "dashmstdout"
+ # mode. It turns out that the SunPro C++ compiler does not properly
+ # handle '-M -o', and we need to detect this. Also, some Intel
+ # versions had trouble with output in subdirs.
+ am__obj=sub/conftest.${OBJEXT-o}
+ am__minus_obj="-o $am__obj"
+ case $depmode in
+ gcc)
+ # This depmode causes a compiler race in universal mode.
+ test "$am__universal" = false || continue
+ ;;
+ nosideeffect)
+ # After this tag, mechanisms are not by side-effect, so they'll
+ # only be used when explicitly requested.
+ if test "x$enable_dependency_tracking" = xyes; then
+ continue
+ else
+ break
+ fi
+ ;;
+ msvc7 | msvc7msys | msvisualcpp | msvcmsys)
+ # This compiler won't grok '-c -o', but also, the minuso test has
+ # not run yet. These depmodes are late enough in the game, and
+ # so weak that their functioning should not be impacted.
+ am__obj=conftest.${OBJEXT-o}
+ am__minus_obj=
+ ;;
+ none) break ;;
+ esac
+ if depmode=$depmode \
+ source=sub/conftest.c object=$am__obj \
+ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \
+ >/dev/null 2>conftest.err &&
+ grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
+ grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
+ grep $am__obj sub/conftest.Po > /dev/null 2>&1 &&
+ ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+ # icc doesn't choke on unknown options, it will just issue warnings
+ # or remarks (even with -Werror). So we grep stderr for any message
+ # that says an option was ignored or not supported.
+ # When given -MP, icc 7.0 and 7.1 complain thusly:
+ # icc: Command line warning: ignoring option '-M'; no argument required
+ # The diagnosis changed in icc 8.0:
+ # icc: Command line remark: option '-MP' not supported
+ if (grep 'ignoring option' conftest.err ||
+ grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
+ am_cv_CC_dependencies_compiler_type=$depmode
+ break
+ fi
+ fi
+ done
+
+ cd ..
+ rm -rf conftest.dir
+else
+ am_cv_CC_dependencies_compiler_type=none
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5
+$as_echo "$am_cv_CC_dependencies_compiler_type" >&6; }
+CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type
+
+ if
+ test "x$enable_dependency_tracking" != xno \
+ && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then
+ am__fastdepCC_TRUE=
+ am__fastdepCC_FALSE='#'
+else
+ am__fastdepCC_TRUE='#'
+ am__fastdepCC_FALSE=
+fi
+
+
+
+if test -n "$ac_tool_prefix"; then
+ for ac_prog in ar lib "link -lib"
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_AR+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$AR"; then
+ ac_cv_prog_AR="$AR" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_AR="$ac_tool_prefix$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+AR=$ac_cv_prog_AR
+if test -n "$AR"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5
+$as_echo "$AR" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$AR" && break
+ done
+fi
+if test -z "$AR"; then
+ ac_ct_AR=$AR
+ for ac_prog in ar lib "link -lib"
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_AR+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_AR"; then
+ ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_AR="$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_AR=$ac_cv_prog_ac_ct_AR
+if test -n "$ac_ct_AR"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5
+$as_echo "$ac_ct_AR" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$ac_ct_AR" && break
+done
+
+ if test "x$ac_ct_AR" = x; then
+ AR="false"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ AR=$ac_ct_AR
+ fi
+fi
+
+: ${AR=ar}
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the archiver ($AR) interface" >&5
+$as_echo_n "checking the archiver ($AR) interface... " >&6; }
+if ${am_cv_ar_interface+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+ am_cv_ar_interface=ar
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+int some_variable = 0;
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ am_ar_try='$AR cru libconftest.a conftest.$ac_objext >&5'
+ { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$am_ar_try\""; } >&5
+ (eval $am_ar_try) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ if test "$ac_status" -eq 0; then
+ am_cv_ar_interface=ar
+ else
+ am_ar_try='$AR -NOLOGO -OUT:conftest.lib conftest.$ac_objext >&5'
+ { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$am_ar_try\""; } >&5
+ (eval $am_ar_try) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ if test "$ac_status" -eq 0; then
+ am_cv_ar_interface=lib
+ else
+ am_cv_ar_interface=unknown
+ fi
+ fi
+ rm -f conftest.lib libconftest.a
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_ar_interface" >&5
+$as_echo "$am_cv_ar_interface" >&6; }
+
+case $am_cv_ar_interface in
+ar)
+ ;;
+lib)
+ # Microsoft lib, so override with the ar-lib wrapper script.
+ # FIXME: It is wrong to rewrite AR.
+ # But if we don't then we get into trouble of one sort or another.
+ # A longer-term fix would be to have automake use am__AR in this case,
+ # and then we could set am__AR="$am_aux_dir/ar-lib \$(AR)" or something
+ # similar.
+ AR="$am_aux_dir/ar-lib $AR"
+ ;;
+unknown)
+ as_fn_error $? "could not determine $AR interface" "$LINENO" 5
+ ;;
+esac
+
+# By default we simply use the C compiler to build assembly code.
+
+test "${CCAS+set}" = set || CCAS=$CC
+test "${CCASFLAGS+set}" = set || CCASFLAGS=$CFLAGS
+
+
+
+depcc="$CCAS" am_compiler_list=
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5
+$as_echo_n "checking dependency style of $depcc... " >&6; }
+if ${am_cv_CCAS_dependencies_compiler_type+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+ # We make a subdir and do the tests there. Otherwise we can end up
+ # making bogus files that we don't know about and never remove. For
+ # instance it was reported that on HP-UX the gcc test will end up
+ # making a dummy file named 'D' -- because '-MD' means "put the output
+ # in D".
+ rm -rf conftest.dir
+ mkdir conftest.dir
+ # Copy depcomp to subdir because otherwise we won't find it if we're
+ # using a relative directory.
+ cp "$am_depcomp" conftest.dir
+ cd conftest.dir
+ # We will build objects and dependencies in a subdirectory because
+ # it helps to detect inapplicable dependency modes. For instance
+ # both Tru64's cc and ICC support -MD to output dependencies as a
+ # side effect of compilation, but ICC will put the dependencies in
+ # the current directory while Tru64 will put them in the object
+ # directory.
+ mkdir sub
+
+ am_cv_CCAS_dependencies_compiler_type=none
+ if test "$am_compiler_list" = ""; then
+ am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp`
+ fi
+ am__universal=false
+
+
+ for depmode in $am_compiler_list; do
+ # Setup a source with many dependencies, because some compilers
+ # like to wrap large dependency lists on column 80 (with \), and
+ # we should not choose a depcomp mode which is confused by this.
+ #
+ # We need to recreate these files for each test, as the compiler may
+ # overwrite some of them when testing with obscure command lines.
+ # This happens at least with the AIX C compiler.
+ : > sub/conftest.c
+ for i in 1 2 3 4 5 6; do
+ echo '#include "conftst'$i'.h"' >> sub/conftest.c
+ # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with
+ # Solaris 10 /bin/sh.
+ echo '/* dummy */' > sub/conftst$i.h
+ done
+ echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+
+ # We check with '-c' and '-o' for the sake of the "dashmstdout"
+ # mode. It turns out that the SunPro C++ compiler does not properly
+ # handle '-M -o', and we need to detect this. Also, some Intel
+ # versions had trouble with output in subdirs.
+ am__obj=sub/conftest.${OBJEXT-o}
+ am__minus_obj="-o $am__obj"
+ case $depmode in
+ gcc)
+ # This depmode causes a compiler race in universal mode.
+ test "$am__universal" = false || continue
+ ;;
+ nosideeffect)
+ # After this tag, mechanisms are not by side-effect, so they'll
+ # only be used when explicitly requested.
+ if test "x$enable_dependency_tracking" = xyes; then
+ continue
+ else
+ break
+ fi
+ ;;
+ msvc7 | msvc7msys | msvisualcpp | msvcmsys)
+ # This compiler won't grok '-c -o', but also, the minuso test has
+ # not run yet. These depmodes are late enough in the game, and
+ # so weak that their functioning should not be impacted.
+ am__obj=conftest.${OBJEXT-o}
+ am__minus_obj=
+ ;;
+ none) break ;;
+ esac
+ if depmode=$depmode \
+ source=sub/conftest.c object=$am__obj \
+ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \
+ >/dev/null 2>conftest.err &&
+ grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
+ grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
+ grep $am__obj sub/conftest.Po > /dev/null 2>&1 &&
+ ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+ # icc doesn't choke on unknown options, it will just issue warnings
+ # or remarks (even with -Werror). So we grep stderr for any message
+ # that says an option was ignored or not supported.
+ # When given -MP, icc 7.0 and 7.1 complain thusly:
+ # icc: Command line warning: ignoring option '-M'; no argument required
+ # The diagnosis changed in icc 8.0:
+ # icc: Command line remark: option '-MP' not supported
+ if (grep 'ignoring option' conftest.err ||
+ grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
+ am_cv_CCAS_dependencies_compiler_type=$depmode
+ break
+ fi
+ fi
+ done
+
+ cd ..
+ rm -rf conftest.dir
+else
+ am_cv_CCAS_dependencies_compiler_type=none
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CCAS_dependencies_compiler_type" >&5
+$as_echo "$am_cv_CCAS_dependencies_compiler_type" >&6; }
+CCASDEPMODE=depmode=$am_cv_CCAS_dependencies_compiler_type
+
+ if
+ test "x$enable_dependency_tracking" != xno \
+ && test "$am_cv_CCAS_dependencies_compiler_type" = gcc3; then
+ am__fastdepCCAS_TRUE=
+ am__fastdepCCAS_FALSE='#'
+else
+ am__fastdepCCAS_TRUE='#'
+ am__fastdepCCAS_FALSE=
+fi
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="${ac_tool_prefix}gcc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+ ac_ct_CC=$CC
+ # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CC="gcc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+else
+ CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="${ac_tool_prefix}cc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ fi
+fi
+if test -z "$CC"; then
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+ ac_prog_rejected=yes
+ continue
+ fi
+ ac_cv_prog_CC="cc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+if test $ac_prog_rejected = yes; then
+ # We found a bogon in the path, so make sure we never use it.
+ set dummy $ac_cv_prog_CC
+ shift
+ if test $# != 0; then
+ # We chose a different compiler from the bogus one.
+ # However, it has the same basename, so the bogon will be chosen
+ # first if we set CC to just the basename; use the full file name.
+ shift
+ ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+ fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ for ac_prog in cl.exe
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$CC" && break
+ done
+fi
+if test -z "$CC"; then
+ ac_ct_CC=$CC
+ for ac_prog in cl.exe
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CC="$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$ac_ct_CC" && break
+done
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+fi
+
+fi
+
+
+test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "no acceptable C compiler found in \$PATH
+See \`config.log' for more details" "$LINENO" 5; }
+
+# Provide some information about the compiler.
+$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion; do
+ { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ sed '10a\
+... rest of stderr output deleted ...
+ 10q' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ fi
+ rm -f conftest.er1 conftest.err
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+done
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5
+$as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
+if ${ac_cv_c_compiler_gnu+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+#ifndef __GNUC__
+ choke me
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_compiler_gnu=yes
+else
+ ac_compiler_gnu=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
+$as_echo "$ac_cv_c_compiler_gnu" >&6; }
+if test $ac_compiler_gnu = yes; then
+ GCC=yes
+else
+ GCC=
+fi
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
+$as_echo_n "checking whether $CC accepts -g... " >&6; }
+if ${ac_cv_prog_cc_g+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_save_c_werror_flag=$ac_c_werror_flag
+ ac_c_werror_flag=yes
+ ac_cv_prog_cc_g=no
+ CFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_g=yes
+else
+ CFLAGS=""
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+else
+ ac_c_werror_flag=$ac_save_c_werror_flag
+ CFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_g=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ac_c_werror_flag=$ac_save_c_werror_flag
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
+$as_echo "$ac_cv_prog_cc_g" >&6; }
+if test "$ac_test_CFLAGS" = set; then
+ CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+ if test "$GCC" = yes; then
+ CFLAGS="-g -O2"
+ else
+ CFLAGS="-g"
+ fi
+else
+ if test "$GCC" = yes; then
+ CFLAGS="-O2"
+ else
+ CFLAGS=
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5
+$as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
+if ${ac_cv_prog_cc_c89+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdarg.h>
+#include <stdio.h>
+struct stat;
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+ char **p;
+ int i;
+{
+ return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+ char *s;
+ va_list v;
+ va_start (v,p);
+ s = g (p, va_arg (v,int));
+ va_end (v);
+ return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has
+ function prototypes and stuff, but not '\xHH' hex character constants.
+ These don't provoke an error unfortunately, instead are silently treated
+ as 'x'. The following induces an error, until -std is added to get
+ proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an
+ array size at least. It's necessary to write '\x00'==0 to get something
+ that's true only with -std. */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+ inside strings and character constants. */
+#define FOO(x) 'x'
+int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1];
+ ;
+ return 0;
+}
+_ACEOF
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
+ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+ CC="$ac_save_CC $ac_arg"
+ if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_c89=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext
+ test "x$ac_cv_prog_cc_c89" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+
+fi
+# AC_CACHE_VAL
+case "x$ac_cv_prog_cc_c89" in
+ x)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+$as_echo "none needed" >&6; } ;;
+ xno)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+$as_echo "unsupported" >&6; } ;;
+ *)
+ CC="$CC $ac_cv_prog_cc_c89"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
+$as_echo "$ac_cv_prog_cc_c89" >&6; } ;;
+esac
+if test "x$ac_cv_prog_cc_c89" != xno; then :
+
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together" >&5
+$as_echo_n "checking whether $CC understands -c and -o together... " >&6; }
+if ${am_cv_prog_cc_c_o+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+ # Make sure it works both with $CC and with simple cc.
+ # Following AC_PROG_CC_C_O, we do the test twice because some
+ # compilers refuse to overwrite an existing .o file with -o,
+ # though they will create one.
+ am_cv_prog_cc_c_o=yes
+ for am_i in 1 2; do
+ if { echo "$as_me:$LINENO: $CC -c conftest.$ac_ext -o conftest2.$ac_objext" >&5
+ ($CC -c conftest.$ac_ext -o conftest2.$ac_objext) >&5 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } \
+ && test -f conftest2.$ac_objext; then
+ : OK
+ else
+ am_cv_prog_cc_c_o=no
+ break
+ fi
+ done
+ rm -f core conftest*
+ unset am_i
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5
+$as_echo "$am_cv_prog_cc_c_o" >&6; }
+if test "$am_cv_prog_cc_c_o" != yes; then
+ # Losing compiler, so override with the script.
+ # FIXME: It is wrong to rewrite CC.
+ # But if we don't then we get into trouble of one sort or another.
+ # A longer-term fix would be to have automake use am__CC in this case,
+ # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)"
+ CC="$am_aux_dir/compile $CC"
+fi
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+depcc="$CC" am_compiler_list=
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5
+$as_echo_n "checking dependency style of $depcc... " >&6; }
+if ${am_cv_CC_dependencies_compiler_type+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+ # We make a subdir and do the tests there. Otherwise we can end up
+ # making bogus files that we don't know about and never remove. For
+ # instance it was reported that on HP-UX the gcc test will end up
+ # making a dummy file named 'D' -- because '-MD' means "put the output
+ # in D".
+ rm -rf conftest.dir
+ mkdir conftest.dir
+ # Copy depcomp to subdir because otherwise we won't find it if we're
+ # using a relative directory.
+ cp "$am_depcomp" conftest.dir
+ cd conftest.dir
+ # We will build objects and dependencies in a subdirectory because
+ # it helps to detect inapplicable dependency modes. For instance
+ # both Tru64's cc and ICC support -MD to output dependencies as a
+ # side effect of compilation, but ICC will put the dependencies in
+ # the current directory while Tru64 will put them in the object
+ # directory.
+ mkdir sub
+
+ am_cv_CC_dependencies_compiler_type=none
+ if test "$am_compiler_list" = ""; then
+ am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp`
+ fi
+ am__universal=false
+ case " $depcc " in #(
+ *\ -arch\ *\ -arch\ *) am__universal=true ;;
+ esac
+
+ for depmode in $am_compiler_list; do
+ # Setup a source with many dependencies, because some compilers
+ # like to wrap large dependency lists on column 80 (with \), and
+ # we should not choose a depcomp mode which is confused by this.
+ #
+ # We need to recreate these files for each test, as the compiler may
+ # overwrite some of them when testing with obscure command lines.
+ # This happens at least with the AIX C compiler.
+ : > sub/conftest.c
+ for i in 1 2 3 4 5 6; do
+ echo '#include "conftst'$i'.h"' >> sub/conftest.c
+ # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with
+ # Solaris 10 /bin/sh.
+ echo '/* dummy */' > sub/conftst$i.h
+ done
+ echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+
+ # We check with '-c' and '-o' for the sake of the "dashmstdout"
+ # mode. It turns out that the SunPro C++ compiler does not properly
+ # handle '-M -o', and we need to detect this. Also, some Intel
+ # versions had trouble with output in subdirs.
+ am__obj=sub/conftest.${OBJEXT-o}
+ am__minus_obj="-o $am__obj"
+ case $depmode in
+ gcc)
+ # This depmode causes a compiler race in universal mode.
+ test "$am__universal" = false || continue
+ ;;
+ nosideeffect)
+ # After this tag, mechanisms are not by side-effect, so they'll
+ # only be used when explicitly requested.
+ if test "x$enable_dependency_tracking" = xyes; then
+ continue
+ else
+ break
+ fi
+ ;;
+ msvc7 | msvc7msys | msvisualcpp | msvcmsys)
+ # This compiler won't grok '-c -o', but also, the minuso test has
+ # not run yet. These depmodes are late enough in the game, and
+ # so weak that their functioning should not be impacted.
+ am__obj=conftest.${OBJEXT-o}
+ am__minus_obj=
+ ;;
+ none) break ;;
+ esac
+ if depmode=$depmode \
+ source=sub/conftest.c object=$am__obj \
+ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \
+ >/dev/null 2>conftest.err &&
+ grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
+ grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
+ grep $am__obj sub/conftest.Po > /dev/null 2>&1 &&
+ ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+ # icc doesn't choke on unknown options, it will just issue warnings
+ # or remarks (even with -Werror). So we grep stderr for any message
+ # that says an option was ignored or not supported.
+ # When given -MP, icc 7.0 and 7.1 complain thusly:
+ # icc: Command line warning: ignoring option '-M'; no argument required
+ # The diagnosis changed in icc 8.0:
+ # icc: Command line remark: option '-MP' not supported
+ if (grep 'ignoring option' conftest.err ||
+ grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
+ am_cv_CC_dependencies_compiler_type=$depmode
+ break
+ fi
+ fi
+ done
+
+ cd ..
+ rm -rf conftest.dir
+else
+ am_cv_CC_dependencies_compiler_type=none
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5
+$as_echo "$am_cv_CC_dependencies_compiler_type" >&6; }
+CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type
+
+ if
+ test "x$enable_dependency_tracking" != xno \
+ && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then
+ am__fastdepCC_TRUE=
+ am__fastdepCC_FALSE='#'
+else
+ am__fastdepCC_TRUE='#'
+ am__fastdepCC_FALSE=
+fi
+
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5
+$as_echo_n "checking how to run the C preprocessor... " >&6; }
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+ CPP=
+fi
+if test -z "$CPP"; then
+ if ${ac_cv_prog_CPP+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ # Double quotes because CPP needs to be expanded
+ for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
+ do
+ ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+
+else
+ # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether nonexistent headers
+ # can be detected and how.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+ # Broken: success on invalid input.
+continue
+else
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+ break
+fi
+
+ done
+ ac_cv_prog_CPP=$CPP
+
+fi
+ CPP=$ac_cv_prog_CPP
+else
+ ac_cv_prog_CPP=$CPP
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5
+$as_echo "$CPP" >&6; }
+ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+
+else
+ # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether nonexistent headers
+ # can be detected and how.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+ # Broken: success on invalid input.
+continue
+else
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+
+else
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+if test -z "$CXX"; then
+ if test -n "$CCC"; then
+ CXX=$CCC
+ else
+ if test -n "$ac_tool_prefix"; then
+ for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CXX+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CXX"; then
+ ac_cv_prog_CXX="$CXX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CXX="$ac_tool_prefix$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CXX=$ac_cv_prog_CXX
+if test -n "$CXX"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5
+$as_echo "$CXX" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$CXX" && break
+ done
+fi
+if test -z "$CXX"; then
+ ac_ct_CXX=$CXX
+ for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CXX+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_CXX"; then
+ ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CXX="$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CXX=$ac_cv_prog_ac_ct_CXX
+if test -n "$ac_ct_CXX"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CXX" >&5
+$as_echo "$ac_ct_CXX" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$ac_ct_CXX" && break
+done
+
+ if test "x$ac_ct_CXX" = x; then
+ CXX="g++"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CXX=$ac_ct_CXX
+ fi
+fi
+
+ fi
+fi
+# Provide some information about the compiler.
+$as_echo "$as_me:${as_lineno-$LINENO}: checking for C++ compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion; do
+ { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ sed '10a\
+... rest of stderr output deleted ...
+ 10q' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ fi
+ rm -f conftest.er1 conftest.err
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+done
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C++ compiler" >&5
+$as_echo_n "checking whether we are using the GNU C++ compiler... " >&6; }
+if ${ac_cv_cxx_compiler_gnu+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+#ifndef __GNUC__
+ choke me
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ ac_compiler_gnu=yes
+else
+ ac_compiler_gnu=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_cxx_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_compiler_gnu" >&5
+$as_echo "$ac_cv_cxx_compiler_gnu" >&6; }
+if test $ac_compiler_gnu = yes; then
+ GXX=yes
+else
+ GXX=
+fi
+ac_test_CXXFLAGS=${CXXFLAGS+set}
+ac_save_CXXFLAGS=$CXXFLAGS
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5
+$as_echo_n "checking whether $CXX accepts -g... " >&6; }
+if ${ac_cv_prog_cxx_g+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_save_cxx_werror_flag=$ac_cxx_werror_flag
+ ac_cxx_werror_flag=yes
+ ac_cv_prog_cxx_g=no
+ CXXFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ ac_cv_prog_cxx_g=yes
+else
+ CXXFLAGS=""
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+
+else
+ ac_cxx_werror_flag=$ac_save_cxx_werror_flag
+ CXXFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ ac_cv_prog_cxx_g=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ac_cxx_werror_flag=$ac_save_cxx_werror_flag
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_g" >&5
+$as_echo "$ac_cv_prog_cxx_g" >&6; }
+if test "$ac_test_CXXFLAGS" = set; then
+ CXXFLAGS=$ac_save_CXXFLAGS
+elif test $ac_cv_prog_cxx_g = yes; then
+ if test "$GXX" = yes; then
+ CXXFLAGS="-g -O2"
+ else
+ CXXFLAGS="-g"
+ fi
+else
+ if test "$GXX" = yes; then
+ CXXFLAGS="-O2"
+ else
+ CXXFLAGS=
+ fi
+fi
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+depcc="$CXX" am_compiler_list=
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5
+$as_echo_n "checking dependency style of $depcc... " >&6; }
+if ${am_cv_CXX_dependencies_compiler_type+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+ # We make a subdir and do the tests there. Otherwise we can end up
+ # making bogus files that we don't know about and never remove. For
+ # instance it was reported that on HP-UX the gcc test will end up
+ # making a dummy file named 'D' -- because '-MD' means "put the output
+ # in D".
+ rm -rf conftest.dir
+ mkdir conftest.dir
+ # Copy depcomp to subdir because otherwise we won't find it if we're
+ # using a relative directory.
+ cp "$am_depcomp" conftest.dir
+ cd conftest.dir
+ # We will build objects and dependencies in a subdirectory because
+ # it helps to detect inapplicable dependency modes. For instance
+ # both Tru64's cc and ICC support -MD to output dependencies as a
+ # side effect of compilation, but ICC will put the dependencies in
+ # the current directory while Tru64 will put them in the object
+ # directory.
+ mkdir sub
+
+ am_cv_CXX_dependencies_compiler_type=none
+ if test "$am_compiler_list" = ""; then
+ am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp`
+ fi
+ am__universal=false
+ case " $depcc " in #(
+ *\ -arch\ *\ -arch\ *) am__universal=true ;;
+ esac
+
+ for depmode in $am_compiler_list; do
+ # Setup a source with many dependencies, because some compilers
+ # like to wrap large dependency lists on column 80 (with \), and
+ # we should not choose a depcomp mode which is confused by this.
+ #
+ # We need to recreate these files for each test, as the compiler may
+ # overwrite some of them when testing with obscure command lines.
+ # This happens at least with the AIX C compiler.
+ : > sub/conftest.c
+ for i in 1 2 3 4 5 6; do
+ echo '#include "conftst'$i'.h"' >> sub/conftest.c
+ # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with
+ # Solaris 10 /bin/sh.
+ echo '/* dummy */' > sub/conftst$i.h
+ done
+ echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+
+ # We check with '-c' and '-o' for the sake of the "dashmstdout"
+ # mode. It turns out that the SunPro C++ compiler does not properly
+ # handle '-M -o', and we need to detect this. Also, some Intel
+ # versions had trouble with output in subdirs.
+ am__obj=sub/conftest.${OBJEXT-o}
+ am__minus_obj="-o $am__obj"
+ case $depmode in
+ gcc)
+ # This depmode causes a compiler race in universal mode.
+ test "$am__universal" = false || continue
+ ;;
+ nosideeffect)
+ # After this tag, mechanisms are not by side-effect, so they'll
+ # only be used when explicitly requested.
+ if test "x$enable_dependency_tracking" = xyes; then
+ continue
+ else
+ break
+ fi
+ ;;
+ msvc7 | msvc7msys | msvisualcpp | msvcmsys)
+ # This compiler won't grok '-c -o', but also, the minuso test has
+ # not run yet. These depmodes are late enough in the game, and
+ # so weak that their functioning should not be impacted.
+ am__obj=conftest.${OBJEXT-o}
+ am__minus_obj=
+ ;;
+ none) break ;;
+ esac
+ if depmode=$depmode \
+ source=sub/conftest.c object=$am__obj \
+ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \
+ >/dev/null 2>conftest.err &&
+ grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
+ grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
+ grep $am__obj sub/conftest.Po > /dev/null 2>&1 &&
+ ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+ # icc doesn't choke on unknown options, it will just issue warnings
+ # or remarks (even with -Werror). So we grep stderr for any message
+ # that says an option was ignored or not supported.
+ # When given -MP, icc 7.0 and 7.1 complain thusly:
+ # icc: Command line warning: ignoring option '-M'; no argument required
+ # The diagnosis changed in icc 8.0:
+ # icc: Command line remark: option '-MP' not supported
+ if (grep 'ignoring option' conftest.err ||
+ grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
+ am_cv_CXX_dependencies_compiler_type=$depmode
+ break
+ fi
+ fi
+ done
+
+ cd ..
+ rm -rf conftest.dir
+else
+ am_cv_CXX_dependencies_compiler_type=none
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CXX_dependencies_compiler_type" >&5
+$as_echo "$am_cv_CXX_dependencies_compiler_type" >&6; }
+CXXDEPMODE=depmode=$am_cv_CXX_dependencies_compiler_type
+
+ if
+ test "x$enable_dependency_tracking" != xno \
+ && test "$am_cv_CXX_dependencies_compiler_type" = gcc3; then
+ am__fastdepCXX_TRUE=
+ am__fastdepCXX_FALSE='#'
+else
+ am__fastdepCXX_TRUE='#'
+ am__fastdepCXX_FALSE=
+fi
+
+
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ranlib; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_RANLIB+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$RANLIB"; then
+ ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+RANLIB=$ac_cv_prog_RANLIB
+if test -n "$RANLIB"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5
+$as_echo "$RANLIB" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_RANLIB"; then
+ ac_ct_RANLIB=$RANLIB
+ # Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_RANLIB+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_RANLIB"; then
+ ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_RANLIB="ranlib"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
+if test -n "$ac_ct_RANLIB"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5
+$as_echo "$ac_ct_RANLIB" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_RANLIB" = x; then
+ RANLIB=":"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ RANLIB=$ac_ct_RANLIB
+ fi
+else
+ RANLIB="$ac_cv_prog_RANLIB"
+fi
+
+
+# Check whether --enable-m32 was given.
+if test "${enable_m32+set}" = set; then :
+ enableval=$enable_m32; case "${enableval}" in
+ yes)
+ CFLAGS="${CFLAGS} -m32"
+ CXXFLAGS="${CXXFLAGS} -m32"
+ usem32=true
+ ;;
+ no)
+ usem32=false
+ ;;
+ *)
+ as_fn_error $? "bad value ${enableval} for --enable-m32" "$LINENO" 5
+ ;;
+ esac
+else
+ usem32=false
+fi
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
+$as_echo_n "checking for grep that handles long lines and -e... " >&6; }
+if ${ac_cv_path_GREP+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -z "$GREP"; then
+ ac_path_GREP_found=false
+ # Loop through the user's path and test for each of PROGNAME-LIST
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_prog in grep ggrep; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
+ as_fn_executable_p "$ac_path_GREP" || continue
+# Check for GNU ac_path_GREP and select it if it is found.
+ # Check for GNU $ac_path_GREP
+case `"$ac_path_GREP" --version 2>&1` in
+*GNU*)
+ ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
+*)
+ ac_count=0
+ $as_echo_n 0123456789 >"conftest.in"
+ while :
+ do
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
+ mv "conftest.tmp" "conftest.in"
+ cp "conftest.in" "conftest.nl"
+ $as_echo 'GREP' >> "conftest.nl"
+ "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+ as_fn_arith $ac_count + 1 && ac_count=$as_val
+ if test $ac_count -gt ${ac_path_GREP_max-0}; then
+ # Best one so far, save it but keep looking for a better one
+ ac_cv_path_GREP="$ac_path_GREP"
+ ac_path_GREP_max=$ac_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test $ac_count -gt 10 && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+ $ac_path_GREP_found && break 3
+ done
+ done
+ done
+IFS=$as_save_IFS
+ if test -z "$ac_cv_path_GREP"; then
+ as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+ fi
+else
+ ac_cv_path_GREP=$GREP
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5
+$as_echo "$ac_cv_path_GREP" >&6; }
+ GREP="$ac_cv_path_GREP"
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5
+$as_echo_n "checking for egrep... " >&6; }
+if ${ac_cv_path_EGREP+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
+ then ac_cv_path_EGREP="$GREP -E"
+ else
+ if test -z "$EGREP"; then
+ ac_path_EGREP_found=false
+ # Loop through the user's path and test for each of PROGNAME-LIST
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_prog in egrep; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
+ as_fn_executable_p "$ac_path_EGREP" || continue
+# Check for GNU ac_path_EGREP and select it if it is found.
+ # Check for GNU $ac_path_EGREP
+case `"$ac_path_EGREP" --version 2>&1` in
+*GNU*)
+ ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
+*)
+ ac_count=0
+ $as_echo_n 0123456789 >"conftest.in"
+ while :
+ do
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
+ mv "conftest.tmp" "conftest.in"
+ cp "conftest.in" "conftest.nl"
+ $as_echo 'EGREP' >> "conftest.nl"
+ "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+ as_fn_arith $ac_count + 1 && ac_count=$as_val
+ if test $ac_count -gt ${ac_path_EGREP_max-0}; then
+ # Best one so far, save it but keep looking for a better one
+ ac_cv_path_EGREP="$ac_path_EGREP"
+ ac_path_EGREP_max=$ac_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test $ac_count -gt 10 && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+ $ac_path_EGREP_found && break 3
+ done
+ done
+ done
+IFS=$as_save_IFS
+ if test -z "$ac_cv_path_EGREP"; then
+ as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+ fi
+else
+ ac_cv_path_EGREP=$EGREP
+fi
+
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5
+$as_echo "$ac_cv_path_EGREP" >&6; }
+ EGREP="$ac_cv_path_EGREP"
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5
+$as_echo_n "checking for ANSI C header files... " >&6; }
+if ${ac_cv_header_stdc+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_header_stdc=yes
+else
+ ac_cv_header_stdc=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+ # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "memchr" >/dev/null 2>&1; then :
+
+else
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "free" >/dev/null 2>&1; then :
+
+else
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+ if test "$cross_compiling" = yes; then :
+ :
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <ctype.h>
+#include <stdlib.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+ (('a' <= (c) && (c) <= 'i') \
+ || ('j' <= (c) && (c) <= 'r') \
+ || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+ int i;
+ for (i = 0; i < 256; i++)
+ if (XOR (islower (i), ISLOWER (i))
+ || toupper (i) != TOUPPER (i))
+ return 2;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+
+else
+ ac_cv_header_stdc=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+ conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5
+$as_echo "$ac_cv_header_stdc" >&6; }
+if test $ac_cv_header_stdc = yes; then
+
+$as_echo "#define STDC_HEADERS 1" >>confdefs.h
+
+fi
+
+# Check whether --enable-largefile was given.
+if test "${enable_largefile+set}" = set; then :
+ enableval=$enable_largefile;
+fi
+
+if test "$enable_largefile" != no; then
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for special C compiler options needed for large files" >&5
+$as_echo_n "checking for special C compiler options needed for large files... " >&6; }
+if ${ac_cv_sys_largefile_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_cv_sys_largefile_CC=no
+ if test "$GCC" != yes; then
+ ac_save_CC=$CC
+ while :; do
+ # IRIX 6.2 and later do not support large files by default,
+ # so use the C compiler's -n32 option if that helps.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+ We can't simply define LARGE_OFF_T to be 9223372036854775807,
+ since some C++ compilers masquerading as C compilers
+ incorrectly reject 9223372036854775807. */
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+ int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+ && LARGE_OFF_T % 2147483647 == 1)
+ ? 1 : -1];
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+ if ac_fn_c_try_compile "$LINENO"; then :
+ break
+fi
+rm -f core conftest.err conftest.$ac_objext
+ CC="$CC -n32"
+ if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_sys_largefile_CC=' -n32'; break
+fi
+rm -f core conftest.err conftest.$ac_objext
+ break
+ done
+ CC=$ac_save_CC
+ rm -f conftest.$ac_ext
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_largefile_CC" >&5
+$as_echo "$ac_cv_sys_largefile_CC" >&6; }
+ if test "$ac_cv_sys_largefile_CC" != no; then
+ CC=$CC$ac_cv_sys_largefile_CC
+ fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _FILE_OFFSET_BITS value needed for large files" >&5
+$as_echo_n "checking for _FILE_OFFSET_BITS value needed for large files... " >&6; }
+if ${ac_cv_sys_file_offset_bits+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ while :; do
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+ We can't simply define LARGE_OFF_T to be 9223372036854775807,
+ since some C++ compilers masquerading as C compilers
+ incorrectly reject 9223372036854775807. */
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+ int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+ && LARGE_OFF_T % 2147483647 == 1)
+ ? 1 : -1];
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_sys_file_offset_bits=no; break
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#define _FILE_OFFSET_BITS 64
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+ We can't simply define LARGE_OFF_T to be 9223372036854775807,
+ since some C++ compilers masquerading as C compilers
+ incorrectly reject 9223372036854775807. */
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+ int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+ && LARGE_OFF_T % 2147483647 == 1)
+ ? 1 : -1];
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_sys_file_offset_bits=64; break
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ac_cv_sys_file_offset_bits=unknown
+ break
+done
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_file_offset_bits" >&5
+$as_echo "$ac_cv_sys_file_offset_bits" >&6; }
+case $ac_cv_sys_file_offset_bits in #(
+ no | unknown) ;;
+ *)
+cat >>confdefs.h <<_ACEOF
+#define _FILE_OFFSET_BITS $ac_cv_sys_file_offset_bits
+_ACEOF
+;;
+esac
+rm -rf conftest*
+ if test $ac_cv_sys_file_offset_bits = unknown; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _LARGE_FILES value needed for large files" >&5
+$as_echo_n "checking for _LARGE_FILES value needed for large files... " >&6; }
+if ${ac_cv_sys_large_files+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ while :; do
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+ We can't simply define LARGE_OFF_T to be 9223372036854775807,
+ since some C++ compilers masquerading as C compilers
+ incorrectly reject 9223372036854775807. */
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+ int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+ && LARGE_OFF_T % 2147483647 == 1)
+ ? 1 : -1];
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_sys_large_files=no; break
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#define _LARGE_FILES 1
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+ We can't simply define LARGE_OFF_T to be 9223372036854775807,
+ since some C++ compilers masquerading as C compilers
+ incorrectly reject 9223372036854775807. */
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+ int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+ && LARGE_OFF_T % 2147483647 == 1)
+ ? 1 : -1];
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_sys_large_files=1; break
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ac_cv_sys_large_files=unknown
+ break
+done
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_large_files" >&5
+$as_echo "$ac_cv_sys_large_files" >&6; }
+case $ac_cv_sys_large_files in #(
+ no | unknown) ;;
+ *)
+cat >>confdefs.h <<_ACEOF
+#define _LARGE_FILES $ac_cv_sys_large_files
+_ACEOF
+;;
+esac
+rm -rf conftest*
+ fi
+
+
+fi
+
+
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+ax_pthread_ok=no
+
+# We used to check for pthread.h first, but this fails if pthread.h
+# requires special compiler flags (e.g. on True64 or Sequent).
+# It gets checked for in the link test anyway.
+
+# First of all, check if the user has set any of the PTHREAD_LIBS,
+# etcetera environment variables, and if threads linking works using
+# them:
+if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+ save_LIBS="$LIBS"
+ LIBS="$PTHREAD_LIBS $LIBS"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS" >&5
+$as_echo_n "checking for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS... " >&6; }
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char pthread_join ();
+int
+main ()
+{
+return pthread_join ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ax_pthread_ok=yes
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_pthread_ok" >&5
+$as_echo "$ax_pthread_ok" >&6; }
+ if test x"$ax_pthread_ok" = xno; then
+ PTHREAD_LIBS=""
+ PTHREAD_CFLAGS=""
+ fi
+ LIBS="$save_LIBS"
+ CFLAGS="$save_CFLAGS"
+fi
+
+# We must check for the threads library under a number of different
+# names; the ordering is very important because some systems
+# (e.g. DEC) have both -lpthread and -lpthreads, where one of the
+# libraries is broken (non-POSIX).
+
+# Create a list of thread flags to try. Items starting with a "-" are
+# C compiler flags, and other items are library names, except for "none"
+# which indicates that we try without any flags at all, and "pthread-config"
+# which is a program returning the flags for the Pth emulation library.
+
+ax_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config"
+
+# The ordering *is* (sometimes) important. Some notes on the
+# individual items follow:
+
+# pthreads: AIX (must check this before -lpthread)
+# none: in case threads are in libc; should be tried before -Kthread and
+# other compiler flags to prevent continual compiler warnings
+# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h)
+# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able)
+# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread)
+# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads)
+# -pthreads: Solaris/gcc
+# -mthreads: Mingw32/gcc, Lynx/gcc
+# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it
+# doesn't hurt to check since this sometimes defines pthreads too;
+# also defines -D_REENTRANT)
+# ... -mt is also the pthreads flag for HP/aCC
+# pthread: Linux, etcetera
+# --thread-safe: KAI C++
+# pthread-config: use pthread-config program (for GNU Pth library)
+
+case "${host_cpu}-${host_os}" in
+ *solaris*)
+
+ # On Solaris (at least, for some versions), libc contains stubbed
+ # (non-functional) versions of the pthreads routines, so link-based
+ # tests will erroneously succeed. (We need to link with -pthreads/-mt/
+ # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather
+ # a function called by this macro, so we could check for that, but
+ # who knows whether they'll stub that too in a future libc.) So,
+ # we'll just look for -pthreads and -lpthread first:
+
+ ax_pthread_flags="-pthreads pthread -mt -pthread $ax_pthread_flags"
+ ;;
+
+ *-darwin*)
+ acx_pthread_flags="-pthread $acx_pthread_flags"
+ ;;
+esac
+
+if test x"$ax_pthread_ok" = xno; then
+for flag in $ax_pthread_flags; do
+
+ case $flag in
+ none)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether pthreads work without any flags" >&5
+$as_echo_n "checking whether pthreads work without any flags... " >&6; }
+ ;;
+
+ -*)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether pthreads work with $flag" >&5
+$as_echo_n "checking whether pthreads work with $flag... " >&6; }
+ PTHREAD_CFLAGS="$flag"
+ ;;
+
+ pthread-config)
+ # Extract the first word of "pthread-config", so it can be a program name with args.
+set dummy pthread-config; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ax_pthread_config+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ax_pthread_config"; then
+ ac_cv_prog_ax_pthread_config="$ax_pthread_config" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ax_pthread_config="yes"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ test -z "$ac_cv_prog_ax_pthread_config" && ac_cv_prog_ax_pthread_config="no"
+fi
+fi
+ax_pthread_config=$ac_cv_prog_ax_pthread_config
+if test -n "$ax_pthread_config"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_pthread_config" >&5
+$as_echo "$ax_pthread_config" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ if test x"$ax_pthread_config" = xno; then continue; fi
+ PTHREAD_CFLAGS="`pthread-config --cflags`"
+ PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`"
+ ;;
+
+ *)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for the pthreads library -l$flag" >&5
+$as_echo_n "checking for the pthreads library -l$flag... " >&6; }
+ PTHREAD_LIBS="-l$flag"
+ ;;
+ esac
+
+ save_LIBS="$LIBS"
+ save_CFLAGS="$CFLAGS"
+ LIBS="$PTHREAD_LIBS $LIBS"
+ CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+
+ # Check for various functions. We must include pthread.h,
+ # since some functions may be macros. (On the Sequent, we
+ # need a special flag -Kthread to make this header compile.)
+ # We check for pthread_join because it is in -lpthread on IRIX
+ # while pthread_create is in libc. We check for pthread_attr_init
+ # due to DEC craziness with -lpthreads. We check for
+ # pthread_cleanup_push because it is one of the few pthread
+ # functions on Solaris that doesn't have a non-functional libc stub.
+ # We try pthread_create on general principles.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <pthread.h>
+ static void routine(void* a) {a=0;}
+ static void* start_routine(void* a) {return a;}
+int
+main ()
+{
+pthread_t th; pthread_attr_t attr;
+ pthread_join(th, 0);
+ pthread_attr_init(&attr);
+ pthread_cleanup_push(routine, 0);
+ pthread_create(&th,0,start_routine,0);
+ pthread_cleanup_pop(0);
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ax_pthread_ok=yes
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+
+ LIBS="$save_LIBS"
+ CFLAGS="$save_CFLAGS"
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_pthread_ok" >&5
+$as_echo "$ax_pthread_ok" >&6; }
+ if test "x$ax_pthread_ok" = xyes; then
+ break;
+ fi
+
+ PTHREAD_LIBS=""
+ PTHREAD_CFLAGS=""
+done
+fi
+
+# Various other checks:
+if test "x$ax_pthread_ok" = xyes; then
+ save_LIBS="$LIBS"
+ LIBS="$PTHREAD_LIBS $LIBS"
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+
+ # Detect AIX lossage: JOINABLE attribute is called UNDETACHED.
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for joinable pthread attribute" >&5
+$as_echo_n "checking for joinable pthread attribute... " >&6; }
+ attr_name=unknown
+ for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <pthread.h>
+int
+main ()
+{
+int attr=$attr; return attr;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ attr_name=$attr; break
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ done
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $attr_name" >&5
+$as_echo "$attr_name" >&6; }
+ if test "$attr_name" != PTHREAD_CREATE_JOINABLE; then
+
+cat >>confdefs.h <<_ACEOF
+#define PTHREAD_CREATE_JOINABLE $attr_name
+_ACEOF
+
+ fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking if more special flags are required for pthreads" >&5
+$as_echo_n "checking if more special flags are required for pthreads... " >&6; }
+ flag=no
+ case "${host_cpu}-${host_os}" in
+ *-aix* | *-freebsd* | *-darwin*) flag="-D_THREAD_SAFE";;
+ *solaris* | *-osf* | *-hpux*) flag="-D_REENTRANT";;
+ esac
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${flag}" >&5
+$as_echo "${flag}" >&6; }
+ if test "x$flag" != xno; then
+ PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS"
+ fi
+
+ LIBS="$save_LIBS"
+ CFLAGS="$save_CFLAGS"
+
+ # More AIX lossage: must compile with xlc_r or cc_r
+ if test x"$GCC" != xyes; then
+ for ac_prog in xlc_r cc_r
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_PTHREAD_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$PTHREAD_CC"; then
+ ac_cv_prog_PTHREAD_CC="$PTHREAD_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_PTHREAD_CC="$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+PTHREAD_CC=$ac_cv_prog_PTHREAD_CC
+if test -n "$PTHREAD_CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PTHREAD_CC" >&5
+$as_echo "$PTHREAD_CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$PTHREAD_CC" && break
+done
+test -n "$PTHREAD_CC" || PTHREAD_CC="${CC}"
+
+ else
+ PTHREAD_CC=$CC
+ fi
+else
+ PTHREAD_CC="$CC"
+fi
+
+
+
+
+
+# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND:
+if test x"$ax_pthread_ok" = xyes; then
+
+$as_echo "#define HAVE_PTHREAD 1" >>confdefs.h
+
+ :
+else
+ ax_pthread_ok=no
+
+fi
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+# On IRIX 5.3, sys/types and inttypes.h are conflicting.
+for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
+ inttypes.h stdint.h unistd.h
+do :
+ as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default
+"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+for ac_header in a.out.h sys/random.h
+do :
+ as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+for ac_func in arc4random getcontext getrandom
+do :
+ as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+ if test "x$ac_cv_func_getcontext" = xyes; then
+ HAVE_GETCONTEXT_TRUE=
+ HAVE_GETCONTEXT_FALSE='#'
+else
+ HAVE_GETCONTEXT_TRUE='#'
+ HAVE_GETCONTEXT_FALSE=
+fi
+
+
+
+ ax_cxx_compile_cxx11_required=true
+ ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+ ac_success=no
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX supports C++11 features by default" >&5
+$as_echo_n "checking whether $CXX supports C++11 features by default... " >&6; }
+if ${ax_cv_cxx_compile_cxx11+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+
+// If the compiler admits that it is not ready for C++11, why torture it?
+// Hopefully, this will speed up the test.
+
+#ifndef __cplusplus
+
+#error "This is not a C++ compiler"
+
+#elif __cplusplus < 201103L
+
+#error "This is not a C++11 compiler"
+
+#else
+
+namespace cxx11
+{
+
+ namespace test_static_assert
+ {
+
+ template <typename T>
+ struct check
+ {
+ static_assert(sizeof(int) <= sizeof(T), "not big enough");
+ };
+
+ }
+
+ namespace test_final_override
+ {
+
+ struct Base
+ {
+ virtual void f() {}
+ };
+
+ struct Derived : public Base
+ {
+ virtual void f() override {}
+ };
+
+ }
+
+ namespace test_double_right_angle_brackets
+ {
+
+ template < typename T >
+ struct check {};
+
+ typedef check<void> single_type;
+ typedef check<check<void>> double_type;
+ typedef check<check<check<void>>> triple_type;
+ typedef check<check<check<check<void>>>> quadruple_type;
+
+ }
+
+ namespace test_decltype
+ {
+
+ int
+ f()
+ {
+ int a = 1;
+ decltype(a) b = 2;
+ return a + b;
+ }
+
+ }
+
+ namespace test_type_deduction
+ {
+
+ template < typename T1, typename T2 >
+ struct is_same
+ {
+ static const bool value = false;
+ };
+
+ template < typename T >
+ struct is_same<T, T>
+ {
+ static const bool value = true;
+ };
+
+ template < typename T1, typename T2 >
+ auto
+ add(T1 a1, T2 a2) -> decltype(a1 + a2)
+ {
+ return a1 + a2;
+ }
+
+ int
+ test(const int c, volatile int v)
+ {
+ static_assert(is_same<int, decltype(0)>::value == true, "");
+ static_assert(is_same<int, decltype(c)>::value == false, "");
+ static_assert(is_same<int, decltype(v)>::value == false, "");
+ auto ac = c;
+ auto av = v;
+ auto sumi = ac + av + 'x';
+ auto sumf = ac + av + 1.0;
+ static_assert(is_same<int, decltype(ac)>::value == true, "");
+ static_assert(is_same<int, decltype(av)>::value == true, "");
+ static_assert(is_same<int, decltype(sumi)>::value == true, "");
+ static_assert(is_same<int, decltype(sumf)>::value == false, "");
+ static_assert(is_same<int, decltype(add(c, v))>::value == true, "");
+ return (sumf > 0.0) ? sumi : add(c, v);
+ }
+
+ }
+
+ namespace test_noexcept
+ {
+
+ int f() { return 0; }
+ int g() noexcept { return 0; }
+
+ static_assert(noexcept(f()) == false, "");
+ static_assert(noexcept(g()) == true, "");
+
+ }
+
+ namespace test_constexpr
+ {
+
+ template < typename CharT >
+ unsigned long constexpr
+ strlen_c_r(const CharT *const s, const unsigned long acc) noexcept
+ {
+ return *s ? strlen_c_r(s + 1, acc + 1) : acc;
+ }
+
+ template < typename CharT >
+ unsigned long constexpr
+ strlen_c(const CharT *const s) noexcept
+ {
+ return strlen_c_r(s, 0UL);
+ }
+
+ static_assert(strlen_c("") == 0UL, "");
+ static_assert(strlen_c("1") == 1UL, "");
+ static_assert(strlen_c("example") == 7UL, "");
+ static_assert(strlen_c("another\0example") == 7UL, "");
+
+ }
+
+ namespace test_rvalue_references
+ {
+
+ template < int N >
+ struct answer
+ {
+ static constexpr int value = N;
+ };
+
+ answer<1> f(int&) { return answer<1>(); }
+ answer<2> f(const int&) { return answer<2>(); }
+ answer<3> f(int&&) { return answer<3>(); }
+
+ void
+ test()
+ {
+ int i = 0;
+ const int c = 0;
+ static_assert(decltype(f(i))::value == 1, "");
+ static_assert(decltype(f(c))::value == 2, "");
+ static_assert(decltype(f(0))::value == 3, "");
+ }
+
+ }
+
+ namespace test_uniform_initialization
+ {
+
+ struct test
+ {
+ static const int zero {};
+ static const int one {1};
+ };
+
+ static_assert(test::zero == 0, "");
+ static_assert(test::one == 1, "");
+
+ }
+
+ namespace test_lambdas
+ {
+
+ void
+ test1()
+ {
+ auto lambda1 = [](){};
+ auto lambda2 = lambda1;
+ lambda1();
+ lambda2();
+ }
+
+ int
+ test2()
+ {
+ auto a = [](int i, int j){ return i + j; }(1, 2);
+ auto b = []() -> int { return '0'; }();
+ auto c = [=](){ return a + b; }();
+ auto d = [&](){ return c; }();
+ auto e = [a, &b](int x) mutable {
+ const auto identity = [](int y){ return y; };
+ for (auto i = 0; i < a; ++i)
+ a += b--;
+ return x + identity(a + b);
+ }(0);
+ return a + b + c + d + e;
+ }
+
+ int
+ test3()
+ {
+ const auto nullary = [](){ return 0; };
+ const auto unary = [](int x){ return x; };
+ using nullary_t = decltype(nullary);
+ using unary_t = decltype(unary);
+ const auto higher1st = [](nullary_t f){ return f(); };
+ const auto higher2nd = [unary](nullary_t f1){
+ return [unary, f1](unary_t f2){ return f2(unary(f1())); };
+ };
+ return higher1st(nullary) + higher2nd(nullary)(unary);
+ }
+
+ }
+
+ namespace test_variadic_templates
+ {
+
+ template <int...>
+ struct sum;
+
+ template <int N0, int... N1toN>
+ struct sum<N0, N1toN...>
+ {
+ static constexpr auto value = N0 + sum<N1toN...>::value;
+ };
+
+ template <>
+ struct sum<>
+ {
+ static constexpr auto value = 0;
+ };
+
+ static_assert(sum<>::value == 0, "");
+ static_assert(sum<1>::value == 1, "");
+ static_assert(sum<23>::value == 23, "");
+ static_assert(sum<1, 2>::value == 3, "");
+ static_assert(sum<5, 5, 11>::value == 21, "");
+ static_assert(sum<2, 3, 5, 7, 11, 13>::value == 41, "");
+
+ }
+
+ // http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae
+ // Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function
+ // because of this.
+ namespace test_template_alias_sfinae
+ {
+
+ struct foo {};
+
+ template<typename T>
+ using member = typename T::member_type;
+
+ template<typename T>
+ void func(...) {}
+
+ template<typename T>
+ void func(member<T>*) {}
+
+ void test();
+
+ void test() { func<foo>(0); }
+
+ }
+
+} // namespace cxx11
+
+#endif // __cplusplus >= 201103L
+
+
+
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ ax_cv_cxx_compile_cxx11=yes
+else
+ ax_cv_cxx_compile_cxx11=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_cxx_compile_cxx11" >&5
+$as_echo "$ax_cv_cxx_compile_cxx11" >&6; }
+ if test x$ax_cv_cxx_compile_cxx11 = xyes; then
+ ac_success=yes
+ fi
+
+
+
+ if test x$ac_success = xno; then
+ for switch in -std=c++11 -std=c++0x +std=c++11 "-h std=c++11"; do
+ cachevar=`$as_echo "ax_cv_cxx_compile_cxx11_$switch" | $as_tr_sh`
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX supports C++11 features with $switch" >&5
+$as_echo_n "checking whether $CXX supports C++11 features with $switch... " >&6; }
+if eval \${$cachevar+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_save_CXXFLAGS="$CXXFLAGS"
+ CXXFLAGS="$CXXFLAGS $switch"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+
+// If the compiler admits that it is not ready for C++11, why torture it?
+// Hopefully, this will speed up the test.
+
+#ifndef __cplusplus
+
+#error "This is not a C++ compiler"
+
+#elif __cplusplus < 201103L
+
+#error "This is not a C++11 compiler"
+
+#else
+
+namespace cxx11
+{
+
+ namespace test_static_assert
+ {
+
+ template <typename T>
+ struct check
+ {
+ static_assert(sizeof(int) <= sizeof(T), "not big enough");
+ };
+
+ }
+
+ namespace test_final_override
+ {
+
+ struct Base
+ {
+ virtual void f() {}
+ };
+
+ struct Derived : public Base
+ {
+ virtual void f() override {}
+ };
+
+ }
+
+ namespace test_double_right_angle_brackets
+ {
+
+ template < typename T >
+ struct check {};
+
+ typedef check<void> single_type;
+ typedef check<check<void>> double_type;
+ typedef check<check<check<void>>> triple_type;
+ typedef check<check<check<check<void>>>> quadruple_type;
+
+ }
+
+ namespace test_decltype
+ {
+
+ int
+ f()
+ {
+ int a = 1;
+ decltype(a) b = 2;
+ return a + b;
+ }
+
+ }
+
+ namespace test_type_deduction
+ {
+
+ template < typename T1, typename T2 >
+ struct is_same
+ {
+ static const bool value = false;
+ };
+
+ template < typename T >
+ struct is_same<T, T>
+ {
+ static const bool value = true;
+ };
+
+ template < typename T1, typename T2 >
+ auto
+ add(T1 a1, T2 a2) -> decltype(a1 + a2)
+ {
+ return a1 + a2;
+ }
+
+ int
+ test(const int c, volatile int v)
+ {
+ static_assert(is_same<int, decltype(0)>::value == true, "");
+ static_assert(is_same<int, decltype(c)>::value == false, "");
+ static_assert(is_same<int, decltype(v)>::value == false, "");
+ auto ac = c;
+ auto av = v;
+ auto sumi = ac + av + 'x';
+ auto sumf = ac + av + 1.0;
+ static_assert(is_same<int, decltype(ac)>::value == true, "");
+ static_assert(is_same<int, decltype(av)>::value == true, "");
+ static_assert(is_same<int, decltype(sumi)>::value == true, "");
+ static_assert(is_same<int, decltype(sumf)>::value == false, "");
+ static_assert(is_same<int, decltype(add(c, v))>::value == true, "");
+ return (sumf > 0.0) ? sumi : add(c, v);
+ }
+
+ }
+
+ namespace test_noexcept
+ {
+
+ int f() { return 0; }
+ int g() noexcept { return 0; }
+
+ static_assert(noexcept(f()) == false, "");
+ static_assert(noexcept(g()) == true, "");
+
+ }
+
+ namespace test_constexpr
+ {
+
+ template < typename CharT >
+ unsigned long constexpr
+ strlen_c_r(const CharT *const s, const unsigned long acc) noexcept
+ {
+ return *s ? strlen_c_r(s + 1, acc + 1) : acc;
+ }
+
+ template < typename CharT >
+ unsigned long constexpr
+ strlen_c(const CharT *const s) noexcept
+ {
+ return strlen_c_r(s, 0UL);
+ }
+
+ static_assert(strlen_c("") == 0UL, "");
+ static_assert(strlen_c("1") == 1UL, "");
+ static_assert(strlen_c("example") == 7UL, "");
+ static_assert(strlen_c("another\0example") == 7UL, "");
+
+ }
+
+ namespace test_rvalue_references
+ {
+
+ template < int N >
+ struct answer
+ {
+ static constexpr int value = N;
+ };
+
+ answer<1> f(int&) { return answer<1>(); }
+ answer<2> f(const int&) { return answer<2>(); }
+ answer<3> f(int&&) { return answer<3>(); }
+
+ void
+ test()
+ {
+ int i = 0;
+ const int c = 0;
+ static_assert(decltype(f(i))::value == 1, "");
+ static_assert(decltype(f(c))::value == 2, "");
+ static_assert(decltype(f(0))::value == 3, "");
+ }
+
+ }
+
+ namespace test_uniform_initialization
+ {
+
+ struct test
+ {
+ static const int zero {};
+ static const int one {1};
+ };
+
+ static_assert(test::zero == 0, "");
+ static_assert(test::one == 1, "");
+
+ }
+
+ namespace test_lambdas
+ {
+
+ void
+ test1()
+ {
+ auto lambda1 = [](){};
+ auto lambda2 = lambda1;
+ lambda1();
+ lambda2();
+ }
+
+ int
+ test2()
+ {
+ auto a = [](int i, int j){ return i + j; }(1, 2);
+ auto b = []() -> int { return '0'; }();
+ auto c = [=](){ return a + b; }();
+ auto d = [&](){ return c; }();
+ auto e = [a, &b](int x) mutable {
+ const auto identity = [](int y){ return y; };
+ for (auto i = 0; i < a; ++i)
+ a += b--;
+ return x + identity(a + b);
+ }(0);
+ return a + b + c + d + e;
+ }
+
+ int
+ test3()
+ {
+ const auto nullary = [](){ return 0; };
+ const auto unary = [](int x){ return x; };
+ using nullary_t = decltype(nullary);
+ using unary_t = decltype(unary);
+ const auto higher1st = [](nullary_t f){ return f(); };
+ const auto higher2nd = [unary](nullary_t f1){
+ return [unary, f1](unary_t f2){ return f2(unary(f1())); };
+ };
+ return higher1st(nullary) + higher2nd(nullary)(unary);
+ }
+
+ }
+
+ namespace test_variadic_templates
+ {
+
+ template <int...>
+ struct sum;
+
+ template <int N0, int... N1toN>
+ struct sum<N0, N1toN...>
+ {
+ static constexpr auto value = N0 + sum<N1toN...>::value;
+ };
+
+ template <>
+ struct sum<>
+ {
+ static constexpr auto value = 0;
+ };
+
+ static_assert(sum<>::value == 0, "");
+ static_assert(sum<1>::value == 1, "");
+ static_assert(sum<23>::value == 23, "");
+ static_assert(sum<1, 2>::value == 3, "");
+ static_assert(sum<5, 5, 11>::value == 21, "");
+ static_assert(sum<2, 3, 5, 7, 11, 13>::value == 41, "");
+
+ }
+
+ // http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae
+ // Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function
+ // because of this.
+ namespace test_template_alias_sfinae
+ {
+
+ struct foo {};
+
+ template<typename T>
+ using member = typename T::member_type;
+
+ template<typename T>
+ void func(...) {}
+
+ template<typename T>
+ void func(member<T>*) {}
+
+ void test();
+
+ void test() { func<foo>(0); }
+
+ }
+
+} // namespace cxx11
+
+#endif // __cplusplus >= 201103L
+
+
+
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ eval $cachevar=yes
+else
+ eval $cachevar=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ CXXFLAGS="$ac_save_CXXFLAGS"
+fi
+eval ac_res=\$$cachevar
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+ if eval test x\$$cachevar = xyes; then
+ CXXFLAGS="$CXXFLAGS $switch"
+ ac_success=yes
+ break
+ fi
+ done
+ fi
+ ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+ if test x$ax_cxx_compile_cxx11_required = xtrue; then
+ if test x$ac_success = xno; then
+ as_fn_error $? "*** A compiler with support for C++11 language features is required." "$LINENO" 5
+ fi
+ else
+ if test x$ac_success = xno; then
+ HAVE_CXX11=0
+ { $as_echo "$as_me:${as_lineno-$LINENO}: No compiler with C++11 support was found" >&5
+$as_echo "$as_me: No compiler with C++11 support was found" >&6;}
+ else
+ HAVE_CXX11=1
+
+$as_echo "#define HAVE_CXX11 1" >>confdefs.h
+
+ fi
+
+
+ fi
+
+
+WARN_CXXFLAGS=
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C++ compiler accepts -Werror=unknown-warning-option" >&5
+$as_echo_n "checking whether C++ compiler accepts -Werror=unknown-warning-option... " >&6; }
+if ${ax_cv_check_cxxflags___Werror_unknown_warning_option+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ ax_check_save_flags=$CXXFLAGS
+ CXXFLAGS="$CXXFLAGS -Werror=unknown-warning-option"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ ax_cv_check_cxxflags___Werror_unknown_warning_option=yes
+else
+ ax_cv_check_cxxflags___Werror_unknown_warning_option=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ CXXFLAGS=$ax_check_save_flags
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cxxflags___Werror_unknown_warning_option" >&5
+$as_echo "$ax_cv_check_cxxflags___Werror_unknown_warning_option" >&6; }
+if test "x$ax_cv_check_cxxflags___Werror_unknown_warning_option" = xyes; then :
+
+ ax_compiler_flags_test="-Werror=unknown-warning-option"
+
+else
+
+ ax_compiler_flags_test=""
+
+fi
+
+
+
+
+
+for flag in -Wmissing-braces -Wnon-virtual-dtor -Woverloaded-virtual -Wreorder -Wsign-compare -Wunused-local-typedefs -Wunused-variable -Wvla ; do
+ as_CACHEVAR=`$as_echo "ax_cv_check_cxxflags_${ax_compiler_flags_test}_$flag" | $as_tr_sh`
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C++ compiler accepts $flag" >&5
+$as_echo_n "checking whether C++ compiler accepts $flag... " >&6; }
+if eval \${$as_CACHEVAR+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ ax_check_save_flags=$CXXFLAGS
+ CXXFLAGS="$CXXFLAGS ${ax_compiler_flags_test} $flag"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ eval "$as_CACHEVAR=yes"
+else
+ eval "$as_CACHEVAR=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ CXXFLAGS=$ax_check_save_flags
+fi
+eval ac_res=\$$as_CACHEVAR
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then :
+
+if ${WARN_CXXFLAGS+:} false; then :
+
+ case " $WARN_CXXFLAGS " in #(
+ *" $flag "*) :
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: : WARN_CXXFLAGS already contains \$flag"; } >&5
+ (: WARN_CXXFLAGS already contains $flag) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append WARN_CXXFLAGS " $flag"
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: : WARN_CXXFLAGS=\"\$WARN_CXXFLAGS\""; } >&5
+ (: WARN_CXXFLAGS="$WARN_CXXFLAGS") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else
+
+ WARN_CXXFLAGS=$flag
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: : WARN_CXXFLAGS=\"\$WARN_CXXFLAGS\""; } >&5
+ (: WARN_CXXFLAGS="$WARN_CXXFLAGS") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+
+fi
+
+else
+ :
+fi
+
+done
+
+as_fn_append WARN_CXXFLAGS " -Werror"
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for O_CLOEXEC defined in fcntl.h" >&5
+$as_echo_n "checking for O_CLOEXEC defined in fcntl.h... " >&6; }
+if ${ac_cv_defined_O_CLOEXEC_fcntl_h+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <fcntl.h>
+int
+main ()
+{
+
+ #ifdef O_CLOEXEC
+ int ok;
+ #else
+ choke me
+ #endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_defined_O_CLOEXEC_fcntl_h=yes
+else
+ ac_cv_defined_O_CLOEXEC_fcntl_h=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_defined_O_CLOEXEC_fcntl_h" >&5
+$as_echo "$ac_cv_defined_O_CLOEXEC_fcntl_h" >&6; }
+if test $ac_cv_defined_O_CLOEXEC_fcntl_h != "no"; then :
+
+else
+
+$as_echo "#define O_CLOEXEC 0" >>confdefs.h
+
+fi
+
+# Only build Linux client libs when compiling for Linux
+case $host in
+ *-*-linux* | *-android* )
+ LINUX_HOST=true
+ ;;
+esac
+ if test x$LINUX_HOST = xtrue; then
+ LINUX_HOST_TRUE=
+ LINUX_HOST_FALSE='#'
+else
+ LINUX_HOST_TRUE='#'
+ LINUX_HOST_FALSE=
+fi
+
+
+# Only use Android support headers when compiling for Android
+case $host in
+ *-android*)
+ ANDROID_HOST=true
+ ;;
+esac
+ if test x$ANDROID_HOST = xtrue; then
+ ANDROID_HOST_TRUE=
+ ANDROID_HOST_FALSE='#'
+else
+ ANDROID_HOST_TRUE='#'
+ ANDROID_HOST_FALSE=
+fi
+
+
+# Some tools (like mac ones) only support x86 currently.
+case $host_cpu in
+ i?86|x86_64)
+ X86_HOST=true
+ ;;
+esac
+ if test x$X86_HOST = xtrue; then
+ X86_HOST_TRUE=
+ X86_HOST_FALSE='#'
+else
+ X86_HOST_TRUE='#'
+ X86_HOST_FALSE=
+fi
+
+
+# Check whether --enable-processor was given.
+if test "${enable_processor+set}" = set; then :
+ enableval=$enable_processor; case "${enableval}" in
+ yes)
+ disable_processor=false
+ ;;
+ no)
+ disable_processor=true
+ ;;
+ *)
+ as_fn_error $? "bad value ${enableval} for --disable-processor" "$LINENO" 5
+ ;;
+ esac
+else
+ disable_processor=false
+fi
+
+ if test x$disable_processor = xtrue; then
+ DISABLE_PROCESSOR_TRUE=
+ DISABLE_PROCESSOR_FALSE='#'
+else
+ DISABLE_PROCESSOR_TRUE='#'
+ DISABLE_PROCESSOR_FALSE=
+fi
+
+
+# Check whether --enable-tools was given.
+if test "${enable_tools+set}" = set; then :
+ enableval=$enable_tools; case "${enableval}" in
+ yes)
+ disable_tools=false
+ ;;
+ no)
+ disable_tools=true
+ ;;
+ *)
+ as_fn_error $? "bad value ${enableval} for --disable-tools" "$LINENO" 5
+ ;;
+ esac
+else
+ disable_tools=false
+fi
+
+ if test x$disable_tools = xtrue; then
+ DISABLE_TOOLS_TRUE=
+ DISABLE_TOOLS_FALSE='#'
+else
+ DISABLE_TOOLS_TRUE='#'
+ DISABLE_TOOLS_FALSE=
+fi
+
+
+if test x$LINUX_HOST = xfalse -a x$disable_processor = xtrue -a x$disable_tools = xtrue; then
+ as_fn_error $? "--disable-processor and --disable-tools were specified, and not building for Linux. Nothing to build!" "$LINENO" 5
+fi
+
+# Check whether --enable-system-test-libs was given.
+if test "${enable_system_test_libs+set}" = set; then :
+ enableval=$enable_system_test_libs; case "${enableval}" in
+ yes)
+ system_test_libs=true
+ ;;
+ no)
+ system_test_libs=false
+ ;;
+ *)
+ as_fn_error $? "bad value ${enableval} for --enable-system-test-libs" "$LINENO" 5
+ ;;
+ esac
+else
+ system_test_libs=false
+fi
+
+ if test x$system_test_libs = xtrue; then
+ SYSTEM_TEST_LIBS_TRUE=
+ SYSTEM_TEST_LIBS_FALSE='#'
+else
+ SYSTEM_TEST_LIBS_TRUE='#'
+ SYSTEM_TEST_LIBS_FALSE=
+fi
+
+
+
+
+
+
+if test x$system_test_libs = xtrue; then
+ : "${GMOCK_CFLAGS:=-pthread}"
+ : "${GMOCK_LIBS:=-lgmock -lgtest -pthread -lpthread}"
+ : "${GTEST_CFLAGS:=-pthread}"
+ : "${GTEST_LIBS:=-lgtest -pthread -lpthread}"
+fi
+
+# Check whether --enable-selftest was given.
+if test "${enable_selftest+set}" = set; then :
+ enableval=$enable_selftest; case "${enableval}" in
+ yes)
+ selftest=true
+ ;;
+ no)
+ selftest=false
+ ;;
+ *)
+ as_fn_error $? "bad value ${enableval} for --enable-selftest" "$LINENO" 5
+ ;;
+ esac
+else
+ selftest=false
+fi
+
+ if test x$selftest = xtrue; then
+ SELFTEST_TRUE=
+ SELFTEST_FALSE='#'
+else
+ SELFTEST_TRUE='#'
+ SELFTEST_FALSE=
+fi
+
+
+
+# Check whether --with-rust-demangle was given.
+if test "${with_rust_demangle+set}" = set; then :
+ withval=$with_rust_demangle; case "${withval}" in
+ yes)
+ as_fn_error $? "You must pass the path to the rust-demangle-capi crate for --with-rust-demangle" "$LINENO" 5
+ ;;
+ no)
+ rust_demangle=false
+ ;;
+ *)
+ if ! test -f "${withval}/Cargo.toml"; then
+ as_fn_error $? "You must pass the path to the rust-demangle-capi crate for --with-rust-demangle" "$LINENO" 5
+ fi
+ RUST_DEMANGLE_CFLAGS="-DHAVE_RUST_DEMANGLE -I${withval}/target/include"
+ RUST_DEMANGLE_LIBS="-L${withval}/target/release -lrust_demangle -lpthread -ldl"
+ ;;
+ esac
+else
+ rust_demangle=false
+fi
+
+
+
+
+
+# Check whether --with-tests-as-root was given.
+if test "${with_tests_as_root+set}" = set; then :
+ withval=$with_tests_as_root; case "${withval}" in
+ yes)
+ tests_as_root=true
+ ;;
+ no)
+ tests_as_root=false
+ ;;
+ *)
+ as_fn_error $? "--with-tests-as-root can only be \"yes\" or \"no\"" "$LINENO" 5
+ ;;
+ esac
+else
+ tests_as_root=false
+fi
+
+ if test x$tests_as_root = xtrue; then
+ TESTS_AS_ROOT_TRUE=
+ TESTS_AS_ROOT_FALSE='#'
+else
+ TESTS_AS_ROOT_TRUE='#'
+ TESTS_AS_ROOT_FALSE=
+fi
+
+
+ac_config_files="$ac_config_files breakpad.pc breakpad-client.pc Makefile"
+
+
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems. If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, we kill variables containing newlines.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(
+ for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
+ eval ac_val=\$$ac_var
+ case $ac_val in #(
+ *${as_nl}*)
+ case $ac_var in #(
+ *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+ esac
+ case $ac_var in #(
+ _ | IFS | as_nl) ;; #(
+ BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+ *) { eval $ac_var=; unset $ac_var;} ;;
+ esac ;;
+ esac
+ done
+
+ (set) 2>&1 |
+ case $as_nl`(ac_space=' '; set) 2>&1` in #(
+ *${as_nl}ac_space=\ *)
+ # `set' does not quote correctly, so add quotes: double-quote
+ # substitution turns \\\\ into \\, and sed turns \\ into \.
+ sed -n \
+ "s/'/'\\\\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+ ;; #(
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+ ;;
+ esac |
+ sort
+) |
+ sed '
+ /^ac_cv_env_/b end
+ t clear
+ :clear
+ s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+ t end
+ s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+ :end' >>confcache
+if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
+ if test -w "$cache_file"; then
+ if test "x$cache_file" != "x/dev/null"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
+$as_echo "$as_me: updating cache $cache_file" >&6;}
+ if test ! -f "$cache_file" || test -h "$cache_file"; then
+ cat confcache >"$cache_file"
+ else
+ case $cache_file in #(
+ */* | ?:*)
+ mv -f confcache "$cache_file"$$ &&
+ mv -f "$cache_file"$$ "$cache_file" ;; #(
+ *)
+ mv -f confcache "$cache_file" ;;
+ esac
+ fi
+ fi
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
+$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;}
+ fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+DEFS=-DHAVE_CONFIG_H
+
+ac_libobjs=
+ac_ltlibobjs=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+ # 1. Remove the extension, and $U if already installed.
+ ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
+ ac_i=`$as_echo "$ac_i" | sed "$ac_script"`
+ # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR
+ # will be set to the directory where LIBOBJS objects are built.
+ as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext"
+ as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking that generated files are newer than configure" >&5
+$as_echo_n "checking that generated files are newer than configure... " >&6; }
+ if test -n "$am_sleep_pid"; then
+ # Hide warnings about reused PIDs.
+ wait $am_sleep_pid 2>/dev/null
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: done" >&5
+$as_echo "done" >&6; }
+ if test -n "$EXEEXT"; then
+ am__EXEEXT_TRUE=
+ am__EXEEXT_FALSE='#'
+else
+ am__EXEEXT_TRUE='#'
+ am__EXEEXT_FALSE=
+fi
+
+if test -z "${MAINTAINER_MODE_TRUE}" && test -z "${MAINTAINER_MODE_FALSE}"; then
+ as_fn_error $? "conditional \"MAINTAINER_MODE\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then
+ as_fn_error $? "conditional \"AMDEP\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then
+ as_fn_error $? "conditional \"am__fastdepCC\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${am__fastdepCCAS_TRUE}" && test -z "${am__fastdepCCAS_FALSE}"; then
+ as_fn_error $? "conditional \"am__fastdepCCAS\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then
+ as_fn_error $? "conditional \"am__fastdepCC\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${am__fastdepCXX_TRUE}" && test -z "${am__fastdepCXX_FALSE}"; then
+ as_fn_error $? "conditional \"am__fastdepCXX\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${HAVE_GETCONTEXT_TRUE}" && test -z "${HAVE_GETCONTEXT_FALSE}"; then
+ as_fn_error $? "conditional \"HAVE_GETCONTEXT\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${LINUX_HOST_TRUE}" && test -z "${LINUX_HOST_FALSE}"; then
+ as_fn_error $? "conditional \"LINUX_HOST\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ANDROID_HOST_TRUE}" && test -z "${ANDROID_HOST_FALSE}"; then
+ as_fn_error $? "conditional \"ANDROID_HOST\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${X86_HOST_TRUE}" && test -z "${X86_HOST_FALSE}"; then
+ as_fn_error $? "conditional \"X86_HOST\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${DISABLE_PROCESSOR_TRUE}" && test -z "${DISABLE_PROCESSOR_FALSE}"; then
+ as_fn_error $? "conditional \"DISABLE_PROCESSOR\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${DISABLE_TOOLS_TRUE}" && test -z "${DISABLE_TOOLS_FALSE}"; then
+ as_fn_error $? "conditional \"DISABLE_TOOLS\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${SYSTEM_TEST_LIBS_TRUE}" && test -z "${SYSTEM_TEST_LIBS_FALSE}"; then
+ as_fn_error $? "conditional \"SYSTEM_TEST_LIBS\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${SELFTEST_TRUE}" && test -z "${SELFTEST_FALSE}"; then
+ as_fn_error $? "conditional \"SELFTEST\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${TESTS_AS_ROOT_TRUE}" && test -z "${TESTS_AS_ROOT_FALSE}"; then
+ as_fn_error $? "conditional \"TESTS_AS_ROOT\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+
+: "${CONFIG_STATUS=./config.status}"
+ac_write_fail=0
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
+$as_echo "$as_me: creating $CONFIG_STATUS" >&6;}
+as_write_fail=0
+cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+
+SHELL=\${CONFIG_SHELL-$SHELL}
+export SHELL
+_ASEOF
+cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='print -r --'
+ as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='printf %s\n'
+ as_echo_n='printf %s'
+else
+ if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+ as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+ as_echo_n='/usr/ucb/echo -n'
+ else
+ as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+ as_echo_n_body='eval
+ arg=$1;
+ case $arg in #(
+ *"$as_nl"*)
+ expr "X$arg" : "X\\(.*\\)$as_nl";
+ arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+ esac;
+ expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+ '
+ export as_echo_n_body
+ as_echo_n='sh -c $as_echo_n_body as_echo'
+ fi
+ export as_echo_body
+ as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ PATH_SEPARATOR=:
+ (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+ (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+ PATH_SEPARATOR=';'
+ }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" "" $as_nl"
+
+# Find who we are. Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there. '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+ as_status=$1; test $as_status -eq 0 && as_status=1
+ if test "$4"; then
+ as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+ fi
+ $as_echo "$as_me: error: $2" >&2
+ as_fn_exit $as_status
+} # as_fn_error
+
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+ return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+ set +e
+ as_fn_set_status $1
+ exit $1
+} # as_fn_exit
+
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+ { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+ eval 'as_fn_append ()
+ {
+ eval $1+=\$2
+ }'
+else
+ as_fn_append ()
+ {
+ eval $1=\$$1\$2
+ }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+ eval 'as_fn_arith ()
+ {
+ as_val=$(( $* ))
+ }'
+else
+ as_fn_arith ()
+ {
+ as_val=`expr "$@" || test $? -eq 1`
+ }
+fi # as_fn_arith
+
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+ case `echo 'xy\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ xy) ECHO_C='\c';;
+ *) echo `echo ksh88 bug on AIX 6.1` > /dev/null
+ ECHO_T=' ';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+ if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -pR'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -pR'
+ elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+ else
+ as_ln_s='cp -pR'
+ fi
+else
+ as_ln_s='cp -pR'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+ case $as_dir in #(
+ -*) as_dir=./$as_dir;;
+ esac
+ test -d "$as_dir" || eval $as_mkdir_p || {
+ as_dirs=
+ while :; do
+ case $as_dir in #(
+ *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+ *) as_qdir=$as_dir;;
+ esac
+ as_dirs="'$as_qdir' $as_dirs"
+ as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ test -d "$as_dir" && break
+ done
+ test -z "$as_dirs" || eval "mkdir $as_dirs"
+ } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p='mkdir -p "$as_dir"'
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+ test -f "$1" && test -x "$1"
+} # as_fn_executable_p
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+exec 6>&1
+## ----------------------------------- ##
+## Main body of $CONFIG_STATUS script. ##
+## ----------------------------------- ##
+_ASEOF
+test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# Save the log message, to keep $0 and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.
+ac_log="
+This file was extended by breakpad $as_me 0.1, which was
+generated by GNU Autoconf 2.69. Invocation command line was
+
+ CONFIG_FILES = $CONFIG_FILES
+ CONFIG_HEADERS = $CONFIG_HEADERS
+ CONFIG_LINKS = $CONFIG_LINKS
+ CONFIG_COMMANDS = $CONFIG_COMMANDS
+ $ $0 $@
+
+on `(hostname || uname -n) 2>/dev/null | sed 1q`
+"
+
+_ACEOF
+
+case $ac_config_files in *"
+"*) set x $ac_config_files; shift; ac_config_files=$*;;
+esac
+
+case $ac_config_headers in *"
+"*) set x $ac_config_headers; shift; ac_config_headers=$*;;
+esac
+
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+# Files that config.status was made for.
+config_files="$ac_config_files"
+config_headers="$ac_config_headers"
+config_commands="$ac_config_commands"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+ac_cs_usage="\
+\`$as_me' instantiates files and other configuration actions
+from templates according to the current configuration. Unless the files
+and actions are specified as TAGs, all are instantiated by default.
+
+Usage: $0 [OPTION]... [TAG]...
+
+ -h, --help print this help, then exit
+ -V, --version print version number and configuration settings, then exit
+ --config print configuration, then exit
+ -q, --quiet, --silent
+ do not print progress messages
+ -d, --debug don't remove temporary files
+ --recheck update $as_me by reconfiguring in the same conditions
+ --file=FILE[:TEMPLATE]
+ instantiate the configuration file FILE
+ --header=FILE[:TEMPLATE]
+ instantiate the configuration header FILE
+
+Configuration files:
+$config_files
+
+Configuration headers:
+$config_headers
+
+Configuration commands:
+$config_commands
+
+Report bugs to <google-breakpad-dev@googlegroups.com>."
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
+ac_cs_version="\\
+breakpad config.status 0.1
+configured by $0, generated by GNU Autoconf 2.69,
+ with options \\"\$ac_cs_config\\"
+
+Copyright (C) 2012 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+
+ac_pwd='$ac_pwd'
+srcdir='$srcdir'
+INSTALL='$INSTALL'
+MKDIR_P='$MKDIR_P'
+AWK='$AWK'
+test -n "\$AWK" || AWK=awk
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# The default lists apply if the user does not specify any file.
+ac_need_defaults=:
+while test $# != 0
+do
+ case $1 in
+ --*=?*)
+ ac_option=`expr "X$1" : 'X\([^=]*\)='`
+ ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
+ ac_shift=:
+ ;;
+ --*=)
+ ac_option=`expr "X$1" : 'X\([^=]*\)='`
+ ac_optarg=
+ ac_shift=:
+ ;;
+ *)
+ ac_option=$1
+ ac_optarg=$2
+ ac_shift=shift
+ ;;
+ esac
+
+ case $ac_option in
+ # Handling of the options.
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ ac_cs_recheck=: ;;
+ --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
+ $as_echo "$ac_cs_version"; exit ;;
+ --config | --confi | --conf | --con | --co | --c )
+ $as_echo "$ac_cs_config"; exit ;;
+ --debug | --debu | --deb | --de | --d | -d )
+ debug=: ;;
+ --file | --fil | --fi | --f )
+ $ac_shift
+ case $ac_optarg in
+ *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ '') as_fn_error $? "missing file argument" ;;
+ esac
+ as_fn_append CONFIG_FILES " '$ac_optarg'"
+ ac_need_defaults=false;;
+ --header | --heade | --head | --hea )
+ $ac_shift
+ case $ac_optarg in
+ *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ as_fn_append CONFIG_HEADERS " '$ac_optarg'"
+ ac_need_defaults=false;;
+ --he | --h)
+ # Conflict between --help and --header
+ as_fn_error $? "ambiguous option: \`$1'
+Try \`$0 --help' for more information.";;
+ --help | --hel | -h )
+ $as_echo "$ac_cs_usage"; exit ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil | --si | --s)
+ ac_cs_silent=: ;;
+
+ # This is an error.
+ -*) as_fn_error $? "unrecognized option: \`$1'
+Try \`$0 --help' for more information." ;;
+
+ *) as_fn_append ac_config_targets " $1"
+ ac_need_defaults=false ;;
+
+ esac
+ shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+ exec 6>/dev/null
+ ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+if \$ac_cs_recheck; then
+ set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+ shift
+ \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6
+ CONFIG_SHELL='$SHELL'
+ export CONFIG_SHELL
+ exec "\$@"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+exec 5>>config.log
+{
+ echo
+ sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+ $as_echo "$ac_log"
+} >&5
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+#
+# INIT-COMMANDS
+#
+AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+
+# Handling of arguments.
+for ac_config_target in $ac_config_targets
+do
+ case $ac_config_target in
+ "src/config.h") CONFIG_HEADERS="$CONFIG_HEADERS src/config.h" ;;
+ "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;;
+ "breakpad.pc") CONFIG_FILES="$CONFIG_FILES breakpad.pc" ;;
+ "breakpad-client.pc") CONFIG_FILES="$CONFIG_FILES breakpad-client.pc" ;;
+ "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+
+ *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
+ esac
+done
+
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used. Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+ test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+ test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
+ test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands
+fi
+
+# Have a temporary directory for convenience. Make it in the build tree
+# simply because there is no reason against having it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Hook for its removal unless debugging.
+# Note that there is a small window in which the directory will not be cleaned:
+# after its creation but before its name has been assigned to `$tmp'.
+$debug ||
+{
+ tmp= ac_tmp=
+ trap 'exit_status=$?
+ : "${ac_tmp:=$tmp}"
+ { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status
+' 0
+ trap 'as_fn_exit 1' 1 2 13 15
+}
+# Create a (secure) tmp directory for tmp files.
+
+{
+ tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
+ test -d "$tmp"
+} ||
+{
+ tmp=./conf$$-$RANDOM
+ (umask 077 && mkdir "$tmp")
+} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5
+ac_tmp=$tmp
+
+# Set up the scripts for CONFIG_FILES section.
+# No need to generate them if there are no CONFIG_FILES.
+# This happens for instance with `./config.status config.h'.
+if test -n "$CONFIG_FILES"; then
+
+
+ac_cr=`echo X | tr X '\015'`
+# On cygwin, bash can eat \r inside `` if the user requested igncr.
+# But we know of no other shell where ac_cr would be empty at this
+# point, so we can use a bashism as a fallback.
+if test "x$ac_cr" = x; then
+ eval ac_cr=\$\'\\r\'
+fi
+ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' </dev/null 2>/dev/null`
+if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then
+ ac_cs_awk_cr='\\r'
+else
+ ac_cs_awk_cr=$ac_cr
+fi
+
+echo 'BEGIN {' >"$ac_tmp/subs1.awk" &&
+_ACEOF
+
+
+{
+ echo "cat >conf$$subs.awk <<_ACEOF" &&
+ echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' &&
+ echo "_ACEOF"
+} >conf$$subs.sh ||
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'`
+ac_delim='%!_!# '
+for ac_last_try in false false false false false :; do
+ . ./conf$$subs.sh ||
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+
+ ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X`
+ if test $ac_delim_n = $ac_delim_num; then
+ break
+ elif $ac_last_try; then
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+ else
+ ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+ fi
+done
+rm -f conf$$subs.sh
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK &&
+_ACEOF
+sed -n '
+h
+s/^/S["/; s/!.*/"]=/
+p
+g
+s/^[^!]*!//
+:repl
+t repl
+s/'"$ac_delim"'$//
+t delim
+:nl
+h
+s/\(.\{148\}\)..*/\1/
+t more1
+s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/
+p
+n
+b repl
+:more1
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t nl
+:delim
+h
+s/\(.\{148\}\)..*/\1/
+t more2
+s/["\\]/\\&/g; s/^/"/; s/$/"/
+p
+b
+:more2
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t delim
+' <conf$$subs.awk | sed '
+/^[^""]/{
+ N
+ s/\n//
+}
+' >>$CONFIG_STATUS || ac_write_fail=1
+rm -f conf$$subs.awk
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACAWK
+cat >>"\$ac_tmp/subs1.awk" <<_ACAWK &&
+ for (key in S) S_is_set[key] = 1
+ FS = ""
+
+}
+{
+ line = $ 0
+ nfields = split(line, field, "@")
+ substed = 0
+ len = length(field[1])
+ for (i = 2; i < nfields; i++) {
+ key = field[i]
+ keylen = length(key)
+ if (S_is_set[key]) {
+ value = S[key]
+ line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3)
+ len += length(value) + length(field[++i])
+ substed = 1
+ } else
+ len += 1 + keylen
+ }
+
+ print line
+}
+
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then
+ sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g"
+else
+ cat
+fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \
+ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5
+_ACEOF
+
+# VPATH may cause trouble with some makes, so we remove sole $(srcdir),
+# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{
+h
+s///
+s/^/:/
+s/[ ]*$/:/
+s/:\$(srcdir):/:/g
+s/:\${srcdir}:/:/g
+s/:@srcdir@:/:/g
+s/^:*//
+s/:*$//
+x
+s/\(=[ ]*\).*/\1/
+G
+s/\n//
+s/^[^=]*=[ ]*$//
+}'
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+fi # test -n "$CONFIG_FILES"
+
+# Set up the scripts for CONFIG_HEADERS section.
+# No need to generate them if there are no CONFIG_HEADERS.
+# This happens for instance with `./config.status Makefile'.
+if test -n "$CONFIG_HEADERS"; then
+cat >"$ac_tmp/defines.awk" <<\_ACAWK ||
+BEGIN {
+_ACEOF
+
+# Transform confdefs.h into an awk script `defines.awk', embedded as
+# here-document in config.status, that substitutes the proper values into
+# config.h.in to produce config.h.
+
+# Create a delimiter string that does not exist in confdefs.h, to ease
+# handling of long lines.
+ac_delim='%!_!# '
+for ac_last_try in false false :; do
+ ac_tt=`sed -n "/$ac_delim/p" confdefs.h`
+ if test -z "$ac_tt"; then
+ break
+ elif $ac_last_try; then
+ as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5
+ else
+ ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+ fi
+done
+
+# For the awk script, D is an array of macro values keyed by name,
+# likewise P contains macro parameters if any. Preserve backslash
+# newline sequences.
+
+ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]*
+sed -n '
+s/.\{148\}/&'"$ac_delim"'/g
+t rset
+:rset
+s/^[ ]*#[ ]*define[ ][ ]*/ /
+t def
+d
+:def
+s/\\$//
+t bsnl
+s/["\\]/\\&/g
+s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\
+D["\1"]=" \3"/p
+s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p
+d
+:bsnl
+s/["\\]/\\&/g
+s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\
+D["\1"]=" \3\\\\\\n"\\/p
+t cont
+s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p
+t cont
+d
+:cont
+n
+s/.\{148\}/&'"$ac_delim"'/g
+t clear
+:clear
+s/\\$//
+t bsnlc
+s/["\\]/\\&/g; s/^/"/; s/$/"/p
+d
+:bsnlc
+s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p
+b cont
+' <confdefs.h | sed '
+s/'"$ac_delim"'/"\\\
+"/g' >>$CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ for (key in D) D_is_set[key] = 1
+ FS = ""
+}
+/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ {
+ line = \$ 0
+ split(line, arg, " ")
+ if (arg[1] == "#") {
+ defundef = arg[2]
+ mac1 = arg[3]
+ } else {
+ defundef = substr(arg[1], 2)
+ mac1 = arg[2]
+ }
+ split(mac1, mac2, "(") #)
+ macro = mac2[1]
+ prefix = substr(line, 1, index(line, defundef) - 1)
+ if (D_is_set[macro]) {
+ # Preserve the white space surrounding the "#".
+ print prefix "define", macro P[macro] D[macro]
+ next
+ } else {
+ # Replace #undef with comments. This is necessary, for example,
+ # in the case of _POSIX_SOURCE, which is predefined and required
+ # on some systems where configure will not decide to define it.
+ if (defundef == "undef") {
+ print "/*", prefix defundef, macro, "*/"
+ next
+ }
+ }
+}
+{ print }
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+ as_fn_error $? "could not setup config headers machinery" "$LINENO" 5
+fi # test -n "$CONFIG_HEADERS"
+
+
+eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS"
+shift
+for ac_tag
+do
+ case $ac_tag in
+ :[FHLC]) ac_mode=$ac_tag; continue;;
+ esac
+ case $ac_mode$ac_tag in
+ :[FHL]*:*);;
+ :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;;
+ :[FH]-) ac_tag=-:-;;
+ :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
+ esac
+ ac_save_IFS=$IFS
+ IFS=:
+ set x $ac_tag
+ IFS=$ac_save_IFS
+ shift
+ ac_file=$1
+ shift
+
+ case $ac_mode in
+ :L) ac_source=$1;;
+ :[FH])
+ ac_file_inputs=
+ for ac_f
+ do
+ case $ac_f in
+ -) ac_f="$ac_tmp/stdin";;
+ *) # Look for the file first in the build tree, then in the source tree
+ # (if the path is not absolute). The absolute path cannot be DOS-style,
+ # because $ac_f cannot contain `:'.
+ test -f "$ac_f" ||
+ case $ac_f in
+ [\\/$]*) false;;
+ *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
+ esac ||
+ as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;;
+ esac
+ case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
+ as_fn_append ac_file_inputs " '$ac_f'"
+ done
+
+ # Let's still pretend it is `configure' which instantiates (i.e., don't
+ # use $as_me), people would be surprised to read:
+ # /* config.h. Generated by config.status. */
+ configure_input='Generated from '`
+ $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
+ `' by configure.'
+ if test x"$ac_file" != x-; then
+ configure_input="$ac_file. $configure_input"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
+$as_echo "$as_me: creating $ac_file" >&6;}
+ fi
+ # Neutralize special characters interpreted by sed in replacement strings.
+ case $configure_input in #(
+ *\&* | *\|* | *\\* )
+ ac_sed_conf_input=`$as_echo "$configure_input" |
+ sed 's/[\\\\&|]/\\\\&/g'`;; #(
+ *) ac_sed_conf_input=$configure_input;;
+ esac
+
+ case $ac_tag in
+ *:-:* | *:-) cat >"$ac_tmp/stdin" \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;;
+ esac
+ ;;
+ esac
+
+ ac_dir=`$as_dirname -- "$ac_file" ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$ac_file" : 'X\(//\)[^/]' \| \
+ X"$ac_file" : 'X\(//\)$' \| \
+ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$ac_file" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ as_dir="$ac_dir"; as_fn_mkdir_p
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+
+ case $ac_mode in
+ :F)
+ #
+ # CONFIG_FILE
+ #
+
+ case $INSTALL in
+ [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
+ *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;;
+ esac
+ ac_MKDIR_P=$MKDIR_P
+ case $MKDIR_P in
+ [\\/$]* | ?:[\\/]* ) ;;
+ */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;;
+ esac
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# If the template does not know about datarootdir, expand it.
+# FIXME: This hack should be removed a few years after 2.60.
+ac_datarootdir_hack=; ac_datarootdir_seen=
+ac_sed_dataroot='
+/datarootdir/ {
+ p
+ q
+}
+/@datadir@/p
+/@docdir@/p
+/@infodir@/p
+/@localedir@/p
+/@mandir@/p'
+case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in
+*datarootdir*) ac_datarootdir_seen=yes;;
+*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ ac_datarootdir_hack='
+ s&@datadir@&$datadir&g
+ s&@docdir@&$docdir&g
+ s&@infodir@&$infodir&g
+ s&@localedir@&$localedir&g
+ s&@mandir@&$mandir&g
+ s&\\\${datarootdir}&$datarootdir&g' ;;
+esac
+_ACEOF
+
+# Neutralize VPATH when `$srcdir' = `.'.
+# Shell code in configure.ac might set extrasub.
+# FIXME: do we really want to maintain this feature?
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_sed_extra="$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s|@configure_input@|$ac_sed_conf_input|;t t
+s&@top_builddir@&$ac_top_builddir_sub&;t t
+s&@top_build_prefix@&$ac_top_build_prefix&;t t
+s&@srcdir@&$ac_srcdir&;t t
+s&@abs_srcdir@&$ac_abs_srcdir&;t t
+s&@top_srcdir@&$ac_top_srcdir&;t t
+s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
+s&@builddir@&$ac_builddir&;t t
+s&@abs_builddir@&$ac_abs_builddir&;t t
+s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
+s&@INSTALL@&$ac_INSTALL&;t t
+s&@MKDIR_P@&$ac_MKDIR_P&;t t
+$ac_datarootdir_hack
+"
+eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \
+ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+
+test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
+ { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } &&
+ { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \
+ "$ac_tmp/out"`; test -z "$ac_out"; } &&
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined" >&5
+$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined" >&2;}
+
+ rm -f "$ac_tmp/stdin"
+ case $ac_file in
+ -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";;
+ *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";;
+ esac \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ ;;
+ :H)
+ #
+ # CONFIG_HEADER
+ #
+ if test x"$ac_file" != x-; then
+ {
+ $as_echo "/* $configure_input */" \
+ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs"
+ } >"$ac_tmp/config.h" \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5
+$as_echo "$as_me: $ac_file is unchanged" >&6;}
+ else
+ rm -f "$ac_file"
+ mv "$ac_tmp/config.h" "$ac_file" \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ fi
+ else
+ $as_echo "/* $configure_input */" \
+ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \
+ || as_fn_error $? "could not create -" "$LINENO" 5
+ fi
+# Compute "$ac_file"'s index in $config_headers.
+_am_arg="$ac_file"
+_am_stamp_count=1
+for _am_header in $config_headers :; do
+ case $_am_header in
+ $_am_arg | $_am_arg:* )
+ break ;;
+ * )
+ _am_stamp_count=`expr $_am_stamp_count + 1` ;;
+ esac
+done
+echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" ||
+$as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$_am_arg" : 'X\(//\)[^/]' \| \
+ X"$_am_arg" : 'X\(//\)$' \| \
+ X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$_am_arg" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`/stamp-h$_am_stamp_count
+ ;;
+
+ :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5
+$as_echo "$as_me: executing $ac_file commands" >&6;}
+ ;;
+ esac
+
+
+ case $ac_file$ac_mode in
+ "depfiles":C) test x"$AMDEP_TRUE" != x"" || {
+ # Older Autoconf quotes --file arguments for eval, but not when files
+ # are listed without --file. Let's play safe and only enable the eval
+ # if we detect the quoting.
+ case $CONFIG_FILES in
+ *\'*) eval set x "$CONFIG_FILES" ;;
+ *) set x $CONFIG_FILES ;;
+ esac
+ shift
+ for mf
+ do
+ # Strip MF so we end up with the name of the file.
+ mf=`echo "$mf" | sed -e 's/:.*$//'`
+ # Check whether this is an Automake generated Makefile or not.
+ # We used to match only the files named 'Makefile.in', but
+ # some people rename them; so instead we look at the file content.
+ # Grep'ing the first line is not enough: some people post-process
+ # each Makefile.in and add a new line on top of each file to say so.
+ # Grep'ing the whole file is not good either: AIX grep has a line
+ # limit of 2048, but all sed's we know have understand at least 4000.
+ if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then
+ dirpart=`$as_dirname -- "$mf" ||
+$as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$mf" : 'X\(//\)[^/]' \| \
+ X"$mf" : 'X\(//\)$' \| \
+ X"$mf" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$mf" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ else
+ continue
+ fi
+ # Extract the definition of DEPDIR, am__include, and am__quote
+ # from the Makefile without running 'make'.
+ DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
+ test -z "$DEPDIR" && continue
+ am__include=`sed -n 's/^am__include = //p' < "$mf"`
+ test -z "$am__include" && continue
+ am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
+ # Find all dependency output files, they are included files with
+ # $(DEPDIR) in their names. We invoke sed twice because it is the
+ # simplest approach to changing $(DEPDIR) to its actual value in the
+ # expansion.
+ for file in `sed -n "
+ s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \
+ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do
+ # Make sure the directory exists.
+ test -f "$dirpart/$file" && continue
+ fdir=`$as_dirname -- "$file" ||
+$as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$file" : 'X\(//\)[^/]' \| \
+ X"$file" : 'X\(//\)$' \| \
+ X"$file" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$file" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ as_dir=$dirpart/$fdir; as_fn_mkdir_p
+ # echo "creating $dirpart/$file"
+ echo '# dummy' > "$dirpart/$file"
+ done
+ done
+}
+ ;;
+
+ esac
+done # for ac_tag
+
+
+as_fn_exit 0
+_ACEOF
+ac_clean_files=$ac_clean_files_save
+
+test $ac_write_fail = 0 ||
+ as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded. So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status. When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+ ac_cs_success=:
+ ac_config_status_args=
+ test "$silent" = yes &&
+ ac_config_status_args="$ac_config_status_args --quiet"
+ exec 5>/dev/null
+ $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+ exec 5>>config.log
+ # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+ # would make configure fail if this is the last instruction.
+ $ac_cs_success || as_fn_exit 1
+fi
+if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
+$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
+fi
+
diff --git a/toolkit/crashreporter/google-breakpad/configure.ac b/toolkit/crashreporter/google-breakpad/configure.ac
new file mode 100644
index 0000000000..08513687f3
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/configure.ac
@@ -0,0 +1,271 @@
+# 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.
+
+
+AC_PREREQ(2.64)
+
+AC_INIT(breakpad, 0.1, google-breakpad-dev@googlegroups.com)
+dnl Sanity check: the argument is just a file that should exist.
+AC_CONFIG_SRCDIR(README.md)
+AC_CONFIG_AUX_DIR(autotools)
+AC_CONFIG_MACRO_DIR([m4])
+AC_CANONICAL_HOST
+
+AM_INIT_AUTOMAKE(subdir-objects tar-ustar 1.11.1)
+AM_CONFIG_HEADER(src/config.h)
+AM_MAINTAINER_MODE
+
+AM_PROG_AR
+AM_PROG_AS
+AC_PROG_CC
+AM_PROG_CC_C_O
+AC_PROG_CPP
+AC_PROG_CXX
+AC_PROG_RANLIB
+
+dnl This must come before all the feature tests below.
+AC_ARG_ENABLE(m32,
+ AS_HELP_STRING([--enable-m32],
+ [Compile/build with -m32]
+ [(default is no)]),
+ [case "${enableval}" in
+ yes)
+ CFLAGS="${CFLAGS} -m32"
+ CXXFLAGS="${CXXFLAGS} -m32"
+ usem32=true
+ ;;
+ no)
+ usem32=false
+ ;;
+ *)
+ AC_MSG_ERROR(bad value ${enableval} for --enable-m32)
+ ;;
+ esac],
+ [usem32=false])
+
+AC_HEADER_STDC
+AC_SYS_LARGEFILE
+AX_PTHREAD
+AC_CHECK_HEADERS([a.out.h sys/random.h])
+AC_CHECK_FUNCS([arc4random getcontext getrandom])
+AM_CONDITIONAL([HAVE_GETCONTEXT], [test "x$ac_cv_func_getcontext" = xyes])
+
+AX_CXX_COMPILE_STDCXX(11, noext, mandatory)
+
+dnl Test supported warning flags.
+WARN_CXXFLAGS=
+dnl This warning flag is used by clang. Its default behavior is to warn when
+dnl given an unknown flag rather than error out.
+AC_LANG_PUSH([C++])
+AX_CHECK_COMPILE_FLAG([-Werror=unknown-warning-option],[
+ ax_compiler_flags_test="-Werror=unknown-warning-option"
+],[
+ ax_compiler_flags_test=""
+])
+AX_APPEND_COMPILE_FLAGS(m4_flatten([
+ -Wmissing-braces
+ -Wnon-virtual-dtor
+ -Woverloaded-virtual
+ -Wreorder
+ -Wsign-compare
+ -Wunused-local-typedefs
+ -Wunused-variable
+ -Wvla
+]), [WARN_CXXFLAGS], [${ax_compiler_flags_test}])
+AS_VAR_APPEND([WARN_CXXFLAGS], " -Werror")
+AC_LANG_POP([C++])
+AC_SUBST([WARN_CXXFLAGS])
+
+dnl Test support for O_CLOEXEC
+AX_CHECK_DEFINE([fcntl.h], [O_CLOEXEC], [],
+ [AC_DEFINE([O_CLOEXEC], [0], [Fallback definition for old systems])])
+
+# Only build Linux client libs when compiling for Linux
+case $host in
+ *-*-linux* | *-android* )
+ LINUX_HOST=true
+ ;;
+esac
+AM_CONDITIONAL(LINUX_HOST, test x$LINUX_HOST = xtrue)
+
+# Only use Android support headers when compiling for Android
+case $host in
+ *-android*)
+ ANDROID_HOST=true
+ ;;
+esac
+AM_CONDITIONAL(ANDROID_HOST, test x$ANDROID_HOST = xtrue)
+
+# Some tools (like mac ones) only support x86 currently.
+case $host_cpu in
+ i?86|x86_64)
+ X86_HOST=true
+ ;;
+esac
+AM_CONDITIONAL(X86_HOST, test x$X86_HOST = xtrue)
+
+AC_ARG_ENABLE(processor,
+ AS_HELP_STRING([--disable-processor],
+ [Don't build processor library]
+ [(default is no)]),
+ [case "${enableval}" in
+ yes)
+ disable_processor=false
+ ;;
+ no)
+ disable_processor=true
+ ;;
+ *)
+ AC_MSG_ERROR(bad value ${enableval} for --disable-processor)
+ ;;
+ esac],
+ [disable_processor=false])
+AM_CONDITIONAL(DISABLE_PROCESSOR, test x$disable_processor = xtrue)
+
+AC_ARG_ENABLE(tools,
+ AS_HELP_STRING([--disable-tools],
+ [Don't build tool binaries]
+ [(default is no)]),
+ [case "${enableval}" in
+ yes)
+ disable_tools=false
+ ;;
+ no)
+ disable_tools=true
+ ;;
+ *)
+ AC_MSG_ERROR(bad value ${enableval} for --disable-tools)
+ ;;
+ esac],
+ [disable_tools=false])
+AM_CONDITIONAL(DISABLE_TOOLS, test x$disable_tools = xtrue)
+
+if test x$LINUX_HOST = xfalse -a x$disable_processor = xtrue -a x$disable_tools = xtrue; then
+ AC_MSG_ERROR([--disable-processor and --disable-tools were specified, and not building for Linux. Nothing to build!])
+fi
+
+AC_ARG_ENABLE(system-test-libs,
+ AS_HELP_STRING([--enable-system-test-libs],
+ [Use gtest/gmock/etc... from the system instead ]
+ [of the local copies (default is local)]),
+ [case "${enableval}" in
+ yes)
+ system_test_libs=true
+ ;;
+ no)
+ system_test_libs=false
+ ;;
+ *)
+ AC_MSG_ERROR(bad value ${enableval} for --enable-system-test-libs)
+ ;;
+ esac],
+ [system_test_libs=false])
+AM_CONDITIONAL(SYSTEM_TEST_LIBS, test x$system_test_libs = xtrue)
+
+AC_ARG_VAR([GMOCK_CFLAGS], [Compiler flags for gmock])
+AC_ARG_VAR([GMOCK_LIBS], [Linker flags for gmock])
+AC_ARG_VAR([GTEST_CFLAGS], [Compiler flags for gtest])
+AC_ARG_VAR([GTEST_LIBS], [Linker flags for gtest])
+if test x$system_test_libs = xtrue; then
+ : "${GMOCK_CFLAGS:=-pthread}"
+ : "${GMOCK_LIBS:=-lgmock -lgtest -pthread -lpthread}"
+ : "${GTEST_CFLAGS:=-pthread}"
+ : "${GTEST_LIBS:=-lgtest -pthread -lpthread}"
+fi
+
+AC_ARG_ENABLE(selftest,
+ AS_HELP_STRING([--enable-selftest],
+ [Run extra tests with "make check" ]
+ [(may conflict with optimizations) ]
+ [(default is no)]),
+ [case "${enableval}" in
+ yes)
+ selftest=true
+ ;;
+ no)
+ selftest=false
+ ;;
+ *)
+ AC_MSG_ERROR(bad value ${enableval} for --enable-selftest)
+ ;;
+ esac],
+ [selftest=false])
+AM_CONDITIONAL(SELFTEST, test x$selftest = xtrue)
+
+AC_ARG_WITH(rust-demangle,
+ AS_HELP_STRING([--with-rust-demangle=/path/to/rust-demangle-capi],
+ [Link against the rust-demangle library]
+ [to demangle Rust language symbols during]
+ [symbol dumping (default is no)]
+ [Pass the path to the crate root.]),
+ [case "${withval}" in
+ yes)
+ AC_MSG_ERROR(You must pass the path to the rust-demangle-capi crate for --with-rust-demangle)
+ ;;
+ no)
+ rust_demangle=false
+ ;;
+ *)
+ if ! test -f "${withval}/Cargo.toml"; then
+ AC_MSG_ERROR(You must pass the path to the rust-demangle-capi crate for --with-rust-demangle)
+ fi
+ RUST_DEMANGLE_CFLAGS="-DHAVE_RUST_DEMANGLE -I${withval}/target/include"
+ RUST_DEMANGLE_LIBS="-L${withval}/target/release -lrust_demangle -lpthread -ldl"
+ ;;
+ esac],
+ [rust_demangle=false])
+AC_ARG_VAR([RUST_DEMANGLE_CFLAGS], [Compiler flags for rust-demangle])
+AC_ARG_VAR([RUST_DEMANGLE_LIBS], [Linker flags for rust-demangle])
+
+AC_ARG_WITH(tests-as-root,
+ AS_HELP_STRING([--with-tests-as-root],
+ [Run the tests as root. Use this on platforms]
+ [like travis-ci.org that require root privileges]
+ [to use ptrace (default is no)]),
+ [case "${withval}" in
+ yes)
+ tests_as_root=true
+ ;;
+ no)
+ tests_as_root=false
+ ;;
+ *)
+ AC_MSG_ERROR(--with-tests-as-root can only be "yes" or "no")
+ ;;
+ esac],
+ [tests_as_root=false])
+AM_CONDITIONAL(TESTS_AS_ROOT, test x$tests_as_root = xtrue)
+
+AC_CONFIG_FILES(m4_flatten([
+ breakpad.pc
+ breakpad-client.pc
+ Makefile
+]))
+
+AC_OUTPUT
diff --git a/toolkit/crashreporter/google-breakpad/default.xml b/toolkit/crashreporter/google-breakpad/default.xml
new file mode 100644
index 0000000000..195bbb592e
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/default.xml
@@ -0,0 +1,43 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- AUTOGENERATED BY deps-to-manifest.py; DO NOT EDIT -->
+<manifest>
+
+ <default revision='refs/heads/master'
+ remote='chromium'
+ sync-c='true'
+ sync-j='8' />
+
+ <remote name='github'
+ fetch='https://github.com/'
+ review='' />
+
+ <remote name='chromium'
+ fetch='https://chromium.googlesource.com/'
+ review='https://chromium-review.googlesource.com' />
+
+ <project path='src'
+ name='breakpad/breakpad'
+ revision='refs/heads/master'
+ remote='chromium' />
+
+ <project path='src/src/tools/gyp'
+ name='external/gyp/'
+ revision='324dd166b7c0b39d513026fa52d6280ac6d56770'
+ remote='chromium' />
+
+ <project path='src/src/testing'
+ name='google/googletest.git'
+ revision='5ec7f0c4a113e2f18ac2c6cc7df51ad6afc24081'
+ remote='github' />
+
+ <project path='src/src/third_party/lss'
+ name='linux-syscall-support/'
+ revision='fd00dbbd0c06a309c657d89e9430143b179ff6db'
+ remote='chromium' />
+
+ <project path='src/src/third_party/protobuf/protobuf'
+ name='google/protobuf.git'
+ revision='cb6dd4ef5f82e41e06179dcd57d3b1d9246ad6ac'
+ remote='github' />
+
+</manifest>
diff --git a/toolkit/crashreporter/google-breakpad/src/breakpad_googletest_includes.h b/toolkit/crashreporter/google-breakpad/src/breakpad_googletest_includes.h
new file mode 100644
index 0000000000..19a3e98077
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/breakpad_googletest_includes.h
@@ -0,0 +1,57 @@
+// 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 BREAKPAD_GOOGLETEST_INCLUDES_H__
+#define BREAKPAD_GOOGLETEST_INCLUDES_H__
+
+#include "gtest/gtest.h"
+#include "gmock/gmock.h"
+
+// If AddressSanitizer is used, NULL pointer dereferences generate SIGILL
+// (illegal instruction) instead of SIGSEGV (segmentation fault). Also,
+// the number of memory regions differs, so there is no point in running
+// this test if AddressSanitizer is used.
+//
+// Ideally we'd use this attribute to disable ASAN on a per-func basis,
+// but this doesn't seem to actually work, and it's changed names over
+// time. So just stick with disabling the actual tests.
+// http://crbug.com/304575
+//#define NO_ASAN __attribute__((no_sanitize_address))
+#if defined(__clang__) && defined(__has_feature)
+// Have to keep this check sep from above as newer gcc will barf on it.
+# if __has_feature(address_sanitizer)
+# define ADDRESS_SANITIZER
+# endif
+#elif defined(__GNUC__) && defined(__SANITIZE_ADDRESS__)
+# define ADDRESS_SANITIZER
+#else
+# undef ADDRESS_SANITIZER
+#endif
+
+#endif // BREAKPAD_GOOGLETEST_INCLUDES_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/build/all.gyp b/toolkit/crashreporter/google-breakpad/src/build/all.gyp
new file mode 100644
index 0000000000..4b59d917bb
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/build/all.gyp
@@ -0,0 +1,41 @@
+# 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.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'All',
+ 'type': 'none',
+ 'dependencies': [
+ '../common/common.gyp:*',
+ '../processor/processor.gyp:*',
+ '../tools/tools.gyp:*',
+ ],
+ },
+ ],
+}
diff --git a/toolkit/crashreporter/google-breakpad/src/build/common.gypi b/toolkit/crashreporter/google-breakpad/src/build/common.gypi
new file mode 100644
index 0000000000..29990c6591
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/build/common.gypi
@@ -0,0 +1,1045 @@
+# Copyright 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.
+
+# IMPORTANT:
+# Please don't directly include this file if you are building via gyp_chromium,
+# since gyp_chromium is automatically forcing its inclusion.
+{
+ 'variables': {
+ # Variables expected to be overriden on the GYP command line (-D) or by
+ # ~/.gyp/include.gypi.
+
+ # Putting a variables dict inside another variables dict looks kind of
+ # weird. This is necessary to get these variables defined for the conditions
+ # within this variables dict that operate on these variables.
+ 'variables': {
+ 'variables': {
+ # Compute the architecture that we're building on.
+ 'conditions': [
+ [ 'OS=="linux" or OS=="freebsd" or OS=="openbsd"', {
+ # This handles the Linux platforms we generally deal with. Anything
+ # else gets passed through, which probably won't work very well; such
+ # hosts should pass an explicit target_arch to gyp.
+ 'host_arch%':
+ '<!(uname -m | sed -e "s/i.86/ia32/;s/x86_64/x64/;s/amd64/x64/;s/arm.*/arm/")',
+ }, { # OS!="linux"
+ 'host_arch%': 'ia32',
+ }],
+ ],
+ },
+
+ 'host_arch%': '<(host_arch)',
+
+ # Default architecture we're building for is the architecture we're
+ # building on.
+ 'target_arch%': '<(host_arch)',
+
+ # This variable tells WebCore.gyp and JavaScriptCore.gyp whether they are
+ # are built under a chromium full build (1) or a webkit.org chromium
+ # build (0).
+ 'inside_chromium_build%': 1,
+
+ # Set to 1 compile with -fPIC cflag on linux. This is a must for shared
+ # libraries on linux x86-64 and arm.
+ 'linux_fpic%': 0,
+
+ # Python version.
+ 'python_ver%': '2.5',
+
+ # Determine ARM compilation flags.
+ 'arm_version%': 7,
+
+ # Set Neon compilation flags (only meaningful if arm_version==7).
+ 'arm_neon%': 1,
+
+ # The system root for cross-compiles. Default: none.
+ 'sysroot%': '',
+
+ # On Linux, we build with sse2 for Chromium builds.
+ 'disable_sse2%': 0,
+ },
+
+ 'target_arch%': '<(target_arch)',
+ 'host_arch%': '<(host_arch)',
+ 'inside_chromium_build%': '<(inside_chromium_build)',
+ 'linux_fpic%': '<(linux_fpic)',
+ 'python_ver%': '<(python_ver)',
+ 'arm_version%': '<(arm_version)',
+ 'arm_neon%': '<(arm_neon)',
+ 'sysroot%': '<(sysroot)',
+ 'disable_sse2%': '<(disable_sse2)',
+
+ # The release channel that this build targets. This is used to restrict
+ # channel-specific build options, like which installer packages to create.
+ # The default is 'all', which does no channel-specific filtering.
+ 'channel%': 'all',
+
+ # Override chromium_mac_pch and set it to 0 to suppress the use of
+ # precompiled headers on the Mac. Prefix header injection may still be
+ # used, but prefix headers will not be precompiled. This is useful when
+ # using distcc to distribute a build to compile slaves that don't
+ # share the same compiler executable as the system driving the compilation,
+ # because precompiled headers rely on pointers into a specific compiler
+ # executable's image. Setting this to 0 is needed to use an experimental
+ # Linux-Mac cross compiler distcc farm.
+ 'chromium_mac_pch%': 1,
+
+ # Mac OS X SDK and deployment target support.
+ # The SDK identifies the version of the system headers that will be used,
+ # and corresponds to the MAC_OS_X_VERSION_MAX_ALLOWED compile-time macro.
+ # "Maximum allowed" refers to the operating system version whose APIs are
+ # available in the headers.
+ # The deployment target identifies the minimum system version that the
+ # built products are expected to function on. It corresponds to the
+ # MAC_OS_X_VERSION_MIN_REQUIRED compile-time macro.
+ # To ensure these macros are available, #include <AvailabilityMacros.h>.
+ # Additional documentation on these macros is available at
+ # http://developer.apple.com/mac/library/technotes/tn2002/tn2064.html#SECTION3
+ # Chrome normally builds with the Mac OS X 10.5 SDK and sets the
+ # deployment target to 10.5. Other projects, such as O3D, may override
+ # these defaults.
+ 'mac_sdk%': '10.5',
+ 'mac_deployment_target%': '10.5',
+
+ # Set to 1 to enable code coverage. In addition to build changes
+ # (e.g. extra CFLAGS), also creates a new target in the src/chrome
+ # project file called "coverage".
+ # Currently ignored on Windows.
+ 'coverage%': 0,
+
+ # Although base/allocator lets you select a heap library via an
+ # environment variable, the libcmt shim it uses sometimes gets in
+ # the way. To disable it entirely, and switch to normal msvcrt, do e.g.
+ # 'win_use_allocator_shim': 0,
+ # 'win_release_RuntimeLibrary': 2
+ # to ~/.gyp/include.gypi, gclient runhooks --force, and do a release build.
+ 'win_use_allocator_shim%': 1, # 0 = shim allocator via libcmt; 1 = msvcrt
+
+ # Whether usage of OpenMAX is enabled.
+ 'enable_openmax%': 0,
+
+ # TODO(bradnelson): eliminate this when possible.
+ # To allow local gyp files to prevent release.vsprops from being included.
+ # Yes(1) means include release.vsprops.
+ # Once all vsprops settings are migrated into gyp, this can go away.
+ 'msvs_use_common_release%': 1,
+
+ # TODO(bradnelson): eliminate this when possible.
+ # To allow local gyp files to override additional linker options for msvs.
+ # Yes(1) means set use the common linker options.
+ 'msvs_use_common_linker_extras%': 1,
+
+ # TODO(sgk): eliminate this if possible.
+ # It would be nicer to support this via a setting in 'target_defaults'
+ # in chrome/app/locales/locales.gypi overriding the setting in the
+ # 'Debug' configuration in the 'target_defaults' dict below,
+ # but that doesn't work as we'd like.
+ 'msvs_debug_link_incremental%': '2',
+
+ # This is the location of the sandbox binary. Chrome looks for this before
+ # running the zygote process. If found, and SUID, it will be used to
+ # sandbox the zygote process and, thus, all renderer processes.
+ 'linux_sandbox_path%': '',
+
+ # Set this to true to enable SELinux support.
+ 'selinux%': 0,
+
+ # Strip the binary after dumping symbols.
+ 'linux_strip_binary%': 0,
+
+ # Enable TCMalloc.
+ 'linux_use_tcmalloc%': 1,
+
+ # Disable TCMalloc's debugallocation.
+ 'linux_use_debugallocation%': 0,
+
+ # Disable TCMalloc's heapchecker.
+ 'linux_use_heapchecker%': 0,
+
+ # Set to 1 to turn on seccomp sandbox by default.
+ # (Note: this is ignored for official builds.)
+ 'linux_use_seccomp_sandbox%': 0,
+
+ # Set to select the Title Case versions of strings in GRD files.
+ 'use_titlecase_in_grd%': 0,
+
+ # Used to disable Native Client at compile time, for platforms where it
+ # isn't supported
+ 'disable_nacl%': 0,
+
+ # Set Thumb compilation flags.
+ 'arm_thumb%': 0,
+
+ # Set ARM fpu compilation flags (only meaningful if arm_version==7 and
+ # arm_neon==0).
+ 'arm_fpu%': 'vfpv3',
+
+ # Enable new NPDevice API.
+ 'enable_new_npdevice_api%': 0,
+
+ 'conditions': [
+ # Whether to use multiple cores to compile with visual studio. This is
+ # optional because it sometimes causes corruption on VS 2005.
+ # It is on by default on VS 2008 and off on VS 2005.
+ ['OS=="win"', {
+ 'conditions': [
+ ['MSVS_VERSION=="2005"', {
+ 'msvs_multi_core_compile%': 0,
+ },{
+ 'msvs_multi_core_compile%': 1,
+ }],
+ # Don't do incremental linking for large modules on 32-bit.
+ ['MSVS_OS_BITS==32', {
+ 'msvs_large_module_debug_link_mode%': '1', # No
+ },{
+ 'msvs_large_module_debug_link_mode%': '2', # Yes
+ }],
+ ],
+ 'nacl_win64_defines': [
+ # This flag is used to minimize dependencies when building
+ # Native Client loader for 64-bit Windows.
+ 'NACL_WIN64',
+ ],
+ }],
+ ],
+
+ # NOTE: When these end up in the Mac bundle, we need to replace '-' for '_'
+ # so Cocoa is happy (http://crbug.com/20441).
+ 'locales': [
+ 'am', 'ar', 'bg', 'bn', 'ca', 'cs', 'da', 'de', 'el', 'en-GB',
+ 'en-US', 'es-419', 'es', 'et', 'fi', 'fil', 'fr', 'gu', 'he',
+ 'hi', 'hr', 'hu', 'id', 'it', 'ja', 'kn', 'ko', 'lt', 'lv',
+ 'ml', 'mr', 'nb', 'nl', 'pl', 'pt-BR', 'pt-PT', 'ro', 'ru',
+ 'sk', 'sl', 'sr', 'sv', 'sw', 'ta', 'te', 'th', 'tr', 'uk',
+ 'vi', 'zh-CN', 'zh-TW',
+ ],
+ },
+ 'target_defaults': {
+ 'includes': [
+ 'filename_rules.gypi',
+ ],
+ 'variables': {
+ # See http://gcc.gnu.org/onlinedocs/gcc-4.4.2/gcc/Optimize-Options.html
+ 'mac_release_optimization%': '3', # Use -O3 unless overridden
+ 'mac_debug_optimization%': '0', # Use -O0 unless overridden
+ # See http://msdn.microsoft.com/en-us/library/aa652360(VS.71).aspx
+ 'win_release_Optimization%': '2', # 2 = /Os
+ 'win_debug_Optimization%': '0', # 0 = /Od
+ # See http://msdn.microsoft.com/en-us/library/aa652367(VS.71).aspx
+ 'win_release_RuntimeLibrary%': '0', # 0 = /MT (nondebug static)
+ 'win_debug_RuntimeLibrary%': '1', # 1 = /MTd (debug static)
+
+ 'release_extra_cflags%': '',
+ 'debug_extra_cflags%': '',
+ 'release_valgrind_build%': 0,
+ },
+ 'conditions': [
+ ['selinux==1', {
+ 'defines': ['CHROMIUM_SELINUX=1'],
+ }],
+ ['win_use_allocator_shim==0', {
+ 'conditions': [
+ ['OS=="win"', {
+ 'defines': ['NO_TCMALLOC'],
+ }],
+ ],
+ }],
+ ['coverage!=0', {
+ 'conditions': [
+ ['OS=="mac"', {
+ 'xcode_settings': {
+ 'GCC_INSTRUMENT_PROGRAM_FLOW_ARCS': 'YES', # -fprofile-arcs
+ 'GCC_GENERATE_TEST_COVERAGE_FILES': 'YES', # -ftest-coverage
+ },
+ # Add -lgcov for types executable, shared_library, and
+ # loadable_module; not for static_library.
+ # This is a delayed conditional.
+ 'target_conditions': [
+ ['_type!="static_library"', {
+ 'xcode_settings': { 'OTHER_LDFLAGS': [ '-lgcov' ] },
+ }],
+ ],
+ }],
+ # Linux gyp (into scons) doesn't like target_conditions?
+ # TODO(???): track down why 'target_conditions' doesn't work
+ # on Linux gyp into scons like it does on Mac gyp into xcodeproj.
+ ['OS=="linux"', {
+ 'cflags': [ '-ftest-coverage',
+ '-fprofile-arcs' ],
+ 'link_settings': { 'libraries': [ '-lgcov' ] },
+ }],
+ # Finally, for Windows, we simply turn on profiling.
+ ['OS=="win"', {
+ 'msvs_settings': {
+ 'VCLinkerTool': {
+ 'Profile': 'true',
+ },
+ 'VCCLCompilerTool': {
+ # /Z7, not /Zi, so coverage is happyb
+ 'DebugInformationFormat': '1',
+ 'AdditionalOptions': ['/Yd'],
+ }
+ }
+ }], # OS==win
+ ], # conditions for coverage
+ }], # coverage!=0
+ ], # conditions for 'target_defaults'
+ 'target_conditions': [
+ [ 'OS=="linux" or OS=="freebsd" or OS=="openbsd"', {
+ 'cflags!': [
+ '-Wall',
+ '-Wextra',
+ '-Werror',
+ ],
+ }],
+ [ 'OS=="win"', {
+ 'defines': [
+ '_CRT_SECURE_NO_DEPRECATE',
+ '_CRT_NONSTDC_NO_WARNINGS',
+ '_CRT_NONSTDC_NO_DEPRECATE',
+ # This is required for ATL to use XP-safe versions of its functions.
+ '_USING_V110_SDK71_',
+ ],
+ 'msvs_disabled_warnings': [4800],
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ 'WarnAsError': 'true',
+ 'Detect64BitPortabilityProblems': 'false',
+ },
+ },
+ }],
+ [ 'OS=="mac"', {
+ 'xcode_settings': {
+ 'GCC_TREAT_WARNINGS_AS_ERRORS': 'NO',
+ 'WARNING_CFLAGS!': ['-Wall'],
+ },
+ }],
+ ], # target_conditions for 'target_defaults'
+ 'default_configuration': 'Debug',
+ 'configurations': {
+ # VCLinkerTool LinkIncremental values below:
+ # 0 == default
+ # 1 == /INCREMENTAL:NO
+ # 2 == /INCREMENTAL
+ # Debug links incremental, Release does not.
+ #
+ # Abstract base configurations to cover common
+ # attributes.
+ #
+ 'Common_Base': {
+ 'abstract': 1,
+ 'msvs_configuration_attributes': {
+ 'OutputDirectory': '$(SolutionDir)$(ConfigurationName)',
+ 'IntermediateDirectory': '$(OutDir)\\obj\\$(ProjectName)',
+ 'CharacterSet': '1',
+ },
+ },
+ 'x86_Base': {
+ 'abstract': 1,
+ 'msvs_settings': {
+ 'VCLinkerTool': {
+ 'MinimumRequiredVersion': '5.01', # XP.
+ 'TargetMachine': '1',
+ },
+ },
+ 'msvs_configuration_platform': 'Win32',
+ },
+ 'x64_Base': {
+ 'abstract': 1,
+ 'msvs_configuration_platform': 'x64',
+ 'msvs_settings': {
+ 'VCLinkerTool': {
+ 'TargetMachine': '17', # x86 - 64
+ 'AdditionalLibraryDirectories!':
+ ['<(DEPTH)/third_party/platformsdk_win7/files/Lib'],
+ 'AdditionalLibraryDirectories':
+ ['<(DEPTH)/third_party/platformsdk_win7/files/Lib/x64'],
+ },
+ 'VCLibrarianTool': {
+ 'AdditionalLibraryDirectories!':
+ ['<(DEPTH)/third_party/platformsdk_win7/files/Lib'],
+ 'AdditionalLibraryDirectories':
+ ['<(DEPTH)/third_party/platformsdk_win7/files/Lib/x64'],
+ },
+ },
+ 'defines': [
+ # Not sure if tcmalloc works on 64-bit Windows.
+ 'NO_TCMALLOC',
+ ],
+ },
+ 'Debug_Base': {
+ 'abstract': 1,
+ 'xcode_settings': {
+ 'COPY_PHASE_STRIP': 'NO',
+ 'GCC_OPTIMIZATION_LEVEL': '<(mac_debug_optimization)',
+ 'OTHER_CFLAGS': [ '<@(debug_extra_cflags)', ],
+ },
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ 'Optimization': '<(win_debug_Optimization)',
+ 'PreprocessorDefinitions': ['_DEBUG'],
+ 'BasicRuntimeChecks': '3',
+ 'RuntimeLibrary': '<(win_debug_RuntimeLibrary)',
+ },
+ 'VCLinkerTool': {
+ 'LinkIncremental': '<(msvs_debug_link_incremental)',
+ },
+ 'VCResourceCompilerTool': {
+ 'PreprocessorDefinitions': ['_DEBUG'],
+ },
+ },
+ 'conditions': [
+ ['OS=="linux"', {
+ 'cflags': [
+ '<@(debug_extra_cflags)',
+ ],
+ }],
+ ],
+ },
+ 'Release_Base': {
+ 'abstract': 1,
+ 'defines': [
+ 'NDEBUG',
+ ],
+ 'xcode_settings': {
+ 'DEAD_CODE_STRIPPING': 'YES', # -Wl,-dead_strip
+ 'GCC_OPTIMIZATION_LEVEL': '<(mac_release_optimization)',
+ 'OTHER_CFLAGS': [ '<@(release_extra_cflags)', ],
+ },
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ 'Optimization': '<(win_release_Optimization)',
+ 'RuntimeLibrary': '<(win_release_RuntimeLibrary)',
+ },
+ 'VCLinkerTool': {
+ 'LinkIncremental': '1',
+ },
+ },
+ 'conditions': [
+ ['release_valgrind_build==0', {
+ 'defines': ['NVALGRIND'],
+ }],
+ ['win_use_allocator_shim==0', {
+ 'defines': ['NO_TCMALLOC'],
+ }],
+ ['win_release_RuntimeLibrary==2', {
+ # Visual C++ 2008 barfs when building anything with /MD (msvcrt):
+ # VC\include\typeinfo(139) : warning C4275: non dll-interface
+ # class 'stdext::exception' used as base for dll-interface
+ # class 'std::bad_cast'
+ 'msvs_disabled_warnings': [4275],
+ }],
+ ['OS=="linux"', {
+ 'cflags': [
+ '<@(release_extra_cflags)',
+ ],
+ }],
+ ],
+ },
+ 'Purify_Base': {
+ 'abstract': 1,
+ 'defines': [
+ 'PURIFY',
+ 'NO_TCMALLOC',
+ ],
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ 'Optimization': '0',
+ 'RuntimeLibrary': '0',
+ 'BufferSecurityCheck': 'false',
+ },
+ 'VCLinkerTool': {
+ 'EnableCOMDATFolding': '1',
+ 'LinkIncremental': '1',
+ },
+ },
+ },
+ #
+ # Concrete configurations
+ #
+ 'Debug': {
+ 'inherit_from': ['Common_Base', 'x86_Base', 'Debug_Base'],
+ },
+ 'Release': {
+ 'inherit_from': ['Common_Base', 'x86_Base', 'Release_Base'],
+ 'conditions': [
+ ['msvs_use_common_release', {
+ 'defines': ['OFFICIAL_BUILD'],
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ 'Optimization': '3',
+ 'StringPooling': 'true',
+ 'OmitFramePointers': 'true',
+ 'InlineFunctionExpansion': '2',
+ 'EnableIntrinsicFunctions': 'true',
+ 'FavorSizeOrSpeed': '2',
+ 'OmitFramePointers': 'true',
+ 'EnableFiberSafeOptimizations': 'true',
+ 'WholeProgramOptimization': 'true',
+ },
+ 'VCLibrarianTool': {
+ 'AdditionalOptions': ['/ltcg', '/expectedoutputsize:120000000'],
+ },
+ 'VCLinkerTool': {
+ 'LinkIncremental': '1',
+ 'OptimizeReferences': '2',
+ 'EnableCOMDATFolding': '2',
+ 'OptimizeForWindows98': '1',
+ 'LinkTimeCodeGeneration': '1',
+ },
+ },
+ }],
+ ]
+ },
+ 'conditions': [
+ [ 'OS=="win"', {
+ # TODO(bradnelson): add a gyp mechanism to make this more graceful.
+ 'Purify': {
+ 'inherit_from': ['Common_Base', 'x86_Base', 'Release_Base', 'Purify'],
+ },
+ 'Debug_x64': {
+ 'inherit_from': ['Common_Base', 'x64_Base', 'Debug_Base'],
+ },
+ 'Release_x64': {
+ 'inherit_from': ['Common_Base', 'x64_Base', 'Release_Base'],
+ },
+ 'Purify_x64': {
+ 'inherit_from': ['Common_Base', 'x64_Base', 'Release_Base', 'Purify_Base'],
+ },
+ }],
+ ],
+ },
+ },
+ 'conditions': [
+ ['OS=="linux" or OS=="freebsd" or OS=="openbsd" or OS=="solaris"', {
+ 'target_defaults': {
+ # Enable -Werror by default, but put it in a variable so it can
+ # be disabled in ~/.gyp/include.gypi on the valgrind builders.
+ 'variables': {
+ # Use -fno-strict-aliasing by default since gcc 4.4 has periodic
+ # issues that slip through the cracks. We could do this just for
+ # gcc 4.4 but it makes more sense to be consistent on all
+ # compilers in use. TODO(Craig): turn this off again when
+ # there is some 4.4 test infrastructure in place and existing
+ # aliasing issues have been fixed.
+ 'no_strict_aliasing%': 1,
+ 'conditions': [['OS=="linux"', {'werror%': '-Werror',}],
+ ['OS=="freebsd"', {'werror%': '',}],
+ ['OS=="openbsd"', {'werror%': '',}],
+ ],
+ },
+ 'cflags': [
+ '<(werror)', # See note above about the werror variable.
+ '-pthread',
+ '-fno-exceptions',
+ '-Wall',
+ # TODO(evan): turn this back on once all the builds work.
+ # '-Wextra',
+ # Don't warn about unused function params. We use those everywhere.
+ '-Wno-unused-parameter',
+ # Don't warn about the "struct foo f = {0};" initialization pattern.
+ '-Wno-missing-field-initializers',
+ '-D_FILE_OFFSET_BITS=64',
+ # Don't export any symbols (for example, to plugins we dlopen()).
+ # Note: this is *required* to make some plugins work.
+ '-fvisibility=hidden',
+ ],
+ 'cflags_cc': [
+ '-frtti',
+ '-fno-threadsafe-statics',
+ # Make inline functions have hidden visiblity by default.
+ # Surprisingly, not covered by -fvisibility=hidden.
+ '-fvisibility-inlines-hidden',
+ ],
+ 'ldflags': [
+ '-pthread', '-Wl,-z,noexecstack',
+ ],
+ 'scons_variable_settings': {
+ 'LIBPATH': ['$LIB_DIR'],
+ # Linking of large files uses lots of RAM, so serialize links
+ # using the handy flock command from util-linux.
+ 'FLOCK_LINK': ['flock', '$TOP_BUILDDIR/linker.lock', '$LINK'],
+ 'FLOCK_SHLINK': ['flock', '$TOP_BUILDDIR/linker.lock', '$SHLINK'],
+ 'FLOCK_LDMODULE': ['flock', '$TOP_BUILDDIR/linker.lock', '$LDMODULE'],
+
+ # We have several cases where archives depend on each other in
+ # a cyclic fashion. Since the GNU linker does only a single
+ # pass over the archives we surround the libraries with
+ # --start-group and --end-group (aka -( and -) ). That causes
+ # ld to loop over the group until no more undefined symbols
+ # are found. In an ideal world we would only make groups from
+ # those libraries which we knew to be in cycles. However,
+ # that's tough with SCons, so we bodge it by making all the
+ # archives a group by redefining the linking command here.
+ #
+ # TODO: investigate whether we still have cycles that
+ # require --{start,end}-group. There has been a lot of
+ # refactoring since this was first coded, which might have
+ # eliminated the circular dependencies.
+ #
+ # Note: $_LIBDIRFLAGS comes before ${LINK,SHLINK,LDMODULE}FLAGS
+ # so that we prefer our own built libraries (e.g. -lpng) to
+ # system versions of libraries that pkg-config might turn up.
+ # TODO(sgk): investigate handling this not by re-ordering the
+ # flags this way, but by adding a hook to use the SCons
+ # ParseFlags() option on the output from pkg-config.
+ 'LINKCOM': [['$FLOCK_LINK', '-o', '$TARGET',
+ '$_LIBDIRFLAGS', '$LINKFLAGS', '$SOURCES',
+ '-Wl,--start-group', '$_LIBFLAGS', '-Wl,--end-group']],
+ 'SHLINKCOM': [['$FLOCK_SHLINK', '-o', '$TARGET',
+ '$_LIBDIRFLAGS', '$SHLINKFLAGS', '$SOURCES',
+ '-Wl,--start-group', '$_LIBFLAGS', '-Wl,--end-group']],
+ 'LDMODULECOM': [['$FLOCK_LDMODULE', '-o', '$TARGET',
+ '$_LIBDIRFLAGS', '$LDMODULEFLAGS', '$SOURCES',
+ '-Wl,--start-group', '$_LIBFLAGS', '-Wl,--end-group']],
+ 'IMPLICIT_COMMAND_DEPENDENCIES': 0,
+ },
+ 'scons_import_variables': [
+ 'AS',
+ 'CC',
+ 'CXX',
+ 'LINK',
+ ],
+ 'scons_propagate_variables': [
+ 'AS',
+ 'CC',
+ 'CCACHE_DIR',
+ 'CXX',
+ 'DISTCC_DIR',
+ 'DISTCC_HOSTS',
+ 'HOME',
+ 'INCLUDE_SERVER_ARGS',
+ 'INCLUDE_SERVER_PORT',
+ 'LINK',
+ 'CHROME_BUILD_TYPE',
+ 'CHROMIUM_BUILD',
+ 'OFFICIAL_BUILD',
+ ],
+ 'configurations': {
+ 'Debug_Base': {
+ 'variables': {
+ 'debug_optimize%': '0',
+ },
+ 'defines': [
+ '_DEBUG',
+ ],
+ 'cflags': [
+ '-O>(debug_optimize)',
+ '-g',
+ # One can use '-gstabs' to enable building the debugging
+ # information in STABS format for breakpad's dumpsyms.
+ ],
+ 'ldflags': [
+ '-rdynamic', # Allows backtrace to resolve symbols.
+ ],
+ },
+ 'Release_Base': {
+ 'variables': {
+ 'release_optimize%': '2',
+ },
+ 'cflags': [
+ '-O>(release_optimize)',
+ # Don't emit the GCC version ident directives, they just end up
+ # in the .comment section taking up binary size.
+ '-fno-ident',
+ # Put data and code in their own sections, so that unused symbols
+ # can be removed at link time with --gc-sections.
+ '-fdata-sections',
+ '-ffunction-sections',
+ ],
+ 'ldflags': [
+ '-Wl,--gc-sections',
+ ],
+ },
+ },
+ 'variants': {
+ 'coverage': {
+ 'cflags': ['-fprofile-arcs', '-ftest-coverage'],
+ 'ldflags': ['-fprofile-arcs'],
+ },
+ 'profile': {
+ 'cflags': ['-pg', '-g'],
+ 'ldflags': ['-pg'],
+ },
+ 'symbols': {
+ 'cflags': ['-g'],
+ },
+ },
+ 'conditions': [
+ [ 'target_arch=="ia32"', {
+ 'asflags': [
+ # Needed so that libs with .s files (e.g. libicudata.a)
+ # are compatible with the general 32-bit-ness.
+ '-32',
+ ],
+ # All floating-point computations on x87 happens in 80-bit
+ # precision. Because the C and C++ language standards allow
+ # the compiler to keep the floating-point values in higher
+ # precision than what's specified in the source and doing so
+ # is more efficient than constantly rounding up to 64-bit or
+ # 32-bit precision as specified in the source, the compiler,
+ # especially in the optimized mode, tries very hard to keep
+ # values in x87 floating-point stack (in 80-bit precision)
+ # as long as possible. This has important side effects, that
+ # the real value used in computation may change depending on
+ # how the compiler did the optimization - that is, the value
+ # kept in 80-bit is different than the value rounded down to
+ # 64-bit or 32-bit. There are possible compiler options to make
+ # this behavior consistent (e.g. -ffloat-store would keep all
+ # floating-values in the memory, thus force them to be rounded
+ # to its original precision) but they have significant runtime
+ # performance penalty.
+ #
+ # -mfpmath=sse -msse2 makes the compiler use SSE instructions
+ # which keep floating-point values in SSE registers in its
+ # native precision (32-bit for single precision, and 64-bit for
+ # double precision values). This means the floating-point value
+ # used during computation does not change depending on how the
+ # compiler optimized the code, since the value is always kept
+ # in its specified precision.
+ 'conditions': [
+ ['disable_sse2==0', {
+ 'cflags': [
+ '-march=pentium4',
+ '-msse2',
+ '-mfpmath=sse',
+ ],
+ }],
+ ],
+ # -mmmx allows mmintrin.h to be used for mmx intrinsics.
+ # video playback is mmx and sse2 optimized.
+ 'cflags': [
+ '-m32',
+ '-mmmx',
+ ],
+ 'ldflags': [
+ '-m32',
+ ],
+ }],
+ ['target_arch=="arm"', {
+ 'target_conditions': [
+ ['_toolset=="target"', {
+ 'cflags_cc': [
+ # The codesourcery arm-2009q3 toolchain warns at that the ABI
+ # has changed whenever it encounters a varargs function. This
+ # silences those warnings, as they are not helpful and
+ # clutter legitimate warnings.
+ '-Wno-abi',
+ ],
+ 'conditions': [
+ ['arm_thumb == 1', {
+ 'cflags': [
+ '-mthumb',
+ # TODO(piman): -Wa,-mimplicit-it=thumb is needed for
+ # inline assembly that uses condition codes but it's
+ # suboptimal. Better would be to #ifdef __thumb__ at the
+ # right place and have a separate thumb path.
+ '-Wa,-mimplicit-it=thumb',
+ ]
+ }],
+ ['arm_version==7', {
+ 'cflags': [
+ '-march=armv7-a',
+ '-mtune=cortex-a8',
+ '-mfloat-abi=softfp',
+ ],
+ 'conditions': [
+ ['arm_neon==1', {
+ 'cflags': [ '-mfpu=neon', ],
+ }, {
+ 'cflags': [ '-mfpu=<(arm_fpu)', ],
+ }]
+ ],
+ }],
+ ],
+ }],
+ ],
+ }],
+ ['linux_fpic==1', {
+ 'cflags': [
+ '-fPIC',
+ ],
+ }],
+ ['sysroot!=""', {
+ 'target_conditions': [
+ ['_toolset=="target"', {
+ 'cflags': [
+ '--sysroot=<(sysroot)',
+ ],
+ 'ldflags': [
+ '--sysroot=<(sysroot)',
+ ],
+ }]]
+ }],
+ ['no_strict_aliasing==1', {
+ 'cflags': [
+ '-fno-strict-aliasing',
+ ],
+ }],
+ ['linux_use_heapchecker==1', {
+ 'variables': {'linux_use_tcmalloc%': 1},
+ }],
+ ['linux_use_tcmalloc==0', {
+ 'defines': ['NO_TCMALLOC'],
+ }],
+ ['linux_use_heapchecker==0', {
+ 'defines': ['NO_HEAPCHECKER'],
+ }],
+ ],
+ },
+ }],
+ # FreeBSD-specific options; note that most FreeBSD options are set above,
+ # with Linux.
+ ['OS=="freebsd"', {
+ 'target_defaults': {
+ 'ldflags': [
+ '-Wl,--no-keep-memory',
+ ],
+ },
+ }],
+ ['OS=="solaris"', {
+ 'cflags!': ['-fvisibility=hidden'],
+ 'cflags_cc!': ['-fvisibility-inlines-hidden'],
+ }],
+ ['OS=="mac"', {
+ 'target_defaults': {
+ 'variables': {
+ # This should be 'mac_real_dsym%', but there seems to be a bug
+ # with % in variables that are intended to be set to different
+ # values in different targets, like this one.
+ 'mac_real_dsym': 0, # Fake .dSYMs are fine in most cases.
+ },
+ 'mac_bundle': 0,
+ 'xcode_settings': {
+ 'ALWAYS_SEARCH_USER_PATHS': 'NO',
+ 'GCC_C_LANGUAGE_STANDARD': 'c99', # -std=c99
+ 'GCC_CW_ASM_SYNTAX': 'NO', # No -fasm-blocks
+ 'GCC_DYNAMIC_NO_PIC': 'NO', # No -mdynamic-no-pic
+ # (Equivalent to -fPIC)
+ 'GCC_ENABLE_CPP_EXCEPTIONS': 'NO', # -fno-exceptions
+ 'GCC_ENABLE_CPP_RTTI': 'YES', # -frtti
+ 'GCC_ENABLE_PASCAL_STRINGS': 'NO', # No -mpascal-strings
+ # GCC_INLINES_ARE_PRIVATE_EXTERN maps to -fvisibility-inlines-hidden
+ 'GCC_INLINES_ARE_PRIVATE_EXTERN': 'YES',
+ 'GCC_OBJC_CALL_CXX_CDTORS': 'YES', # -fobjc-call-cxx-cdtors
+ 'GCC_SYMBOLS_PRIVATE_EXTERN': 'YES', # -fvisibility=hidden
+ 'GCC_THREADSAFE_STATICS': 'NO', # -fno-threadsafe-statics
+ 'GCC_TREAT_WARNINGS_AS_ERRORS': 'YES', # -Werror
+ 'GCC_VERSION': '4.2',
+ 'GCC_WARN_ABOUT_MISSING_NEWLINE': 'YES', # -Wnewline-eof
+ # MACOSX_DEPLOYMENT_TARGET maps to -mmacosx-version-min
+ 'MACOSX_DEPLOYMENT_TARGET': '<(mac_deployment_target)',
+ 'PREBINDING': 'NO', # No -Wl,-prebind
+ 'USE_HEADERMAP': 'NO',
+ 'WARNING_CFLAGS': ['-Wall', '-Wendif-labels'],
+ 'conditions': [
+ ['chromium_mac_pch', {'GCC_PRECOMPILE_PREFIX_HEADER': 'YES'},
+ {'GCC_PRECOMPILE_PREFIX_HEADER': 'NO'}
+ ],
+ ],
+ },
+ 'target_conditions': [
+ ['_type!="static_library"', {
+ 'xcode_settings': {'OTHER_LDFLAGS': ['-Wl,-search_paths_first']},
+ }],
+ ['_mac_bundle', {
+ 'xcode_settings': {'OTHER_LDFLAGS': ['-Wl,-ObjC']},
+ }],
+ ], # target_conditions
+ }, # target_defaults
+ }], # OS=="mac"
+ ['OS=="win"', {
+ 'target_defaults': {
+ 'defines': [
+ '_WIN32_WINNT=0x0600',
+ 'WINVER=0x0600',
+ 'WIN32',
+ '_WINDOWS',
+ '_HAS_EXCEPTIONS=0',
+ 'NOMINMAX',
+ '_CRT_RAND_S',
+ 'CERT_CHAIN_PARA_HAS_EXTRA_FIELDS',
+ 'WIN32_LEAN_AND_MEAN',
+ '_SECURE_ATL',
+ '_HAS_TR1=0',
+ ],
+ 'msvs_system_include_dirs': [
+ '<(DEPTH)/third_party/platformsdk_win7/files/Include',
+ '$(VSInstallDir)/VC/atlmfc/include',
+ ],
+ 'msvs_cygwin_dirs': ['<(DEPTH)/third_party/cygwin'],
+ 'msvs_disabled_warnings': [
+ 4091, 4100, 4127, 4366, 4396, 4503, 4512, 4819, 4995, 4702
+ ],
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ 'MinimalRebuild': 'false',
+ 'ExceptionHandling': '0',
+ 'BufferSecurityCheck': 'true',
+ 'EnableFunctionLevelLinking': 'true',
+ 'RuntimeTypeInfo': 'false',
+ 'WarningLevel': '4',
+ 'WarnAsError': 'true',
+ 'DebugInformationFormat': '3',
+ 'conditions': [
+ [ 'msvs_multi_core_compile', {
+ 'AdditionalOptions': ['/MP'],
+ }],
+ ],
+ },
+ 'VCLibrarianTool': {
+ 'AdditionalOptions': ['/ignore:4221'],
+ 'AdditionalLibraryDirectories':
+ ['<(DEPTH)/third_party/platformsdk_win7/files/Lib'],
+ },
+ 'VCLinkerTool': {
+ 'AdditionalDependencies': [
+ 'wininet.lib',
+ 'version.lib',
+ 'msimg32.lib',
+ 'ws2_32.lib',
+ 'usp10.lib',
+ 'psapi.lib',
+ 'dbghelp.lib',
+ ],
+ 'AdditionalLibraryDirectories':
+ ['<(DEPTH)/third_party/platformsdk_win7/files/Lib'],
+ 'GenerateDebugInformation': 'true',
+ 'MapFileName': '$(OutDir)\\$(TargetName).map',
+ 'ImportLibrary': '$(OutDir)\\lib\\$(TargetName).lib',
+ 'FixedBaseAddress': '1',
+ # SubSystem values:
+ # 0 == not set
+ # 1 == /SUBSYSTEM:CONSOLE
+ # 2 == /SUBSYSTEM:WINDOWS
+ # Most of the executables we'll ever create are tests
+ # and utilities with console output.
+ 'SubSystem': '1',
+ },
+ 'VCMIDLTool': {
+ 'GenerateStublessProxies': 'true',
+ 'TypeLibraryName': '$(InputName).tlb',
+ 'OutputDirectory': '$(IntDir)',
+ 'HeaderFileName': '$(InputName).h',
+ 'DLLDataFileName': 'dlldata.c',
+ 'InterfaceIdentifierFileName': '$(InputName)_i.c',
+ 'ProxyFileName': '$(InputName)_p.c',
+ },
+ 'VCResourceCompilerTool': {
+ 'Culture' : '1033',
+ 'AdditionalIncludeDirectories': ['<(DEPTH)'],
+ },
+ },
+ },
+ }],
+ ['disable_nacl==1 or OS=="freebsd" or OS=="openbsd" or OS=="solaris"', {
+ 'target_defaults': {
+ 'defines': [
+ 'DISABLE_NACL',
+ ],
+ },
+ }],
+ ['OS=="win" and msvs_use_common_linker_extras', {
+ 'target_defaults': {
+ 'msvs_settings': {
+ 'VCLinkerTool': {
+ 'DelayLoadDLLs': [
+ 'dbghelp.dll',
+ 'dwmapi.dll',
+ 'uxtheme.dll',
+ ],
+ },
+ },
+ 'configurations': {
+ 'x86_Base': {
+ 'msvs_settings': {
+ 'VCLinkerTool': {
+ 'AdditionalOptions': [
+ '/safeseh',
+ '/dynamicbase',
+ '/ignore:4199',
+ '/ignore:4221',
+ '/nxcompat',
+ ],
+ },
+ },
+ },
+ 'x64_Base': {
+ 'msvs_settings': {
+ 'VCLinkerTool': {
+ 'AdditionalOptions': [
+ # safeseh is not compatible with x64
+ '/dynamicbase',
+ '/ignore:4199',
+ '/ignore:4221',
+ '/nxcompat',
+ ],
+ },
+ },
+ },
+ },
+ },
+ }],
+ ['enable_new_npdevice_api==1', {
+ 'target_defaults': {
+ 'defines': [
+ 'ENABLE_NEW_NPDEVICE_API',
+ ],
+ },
+ }],
+ ],
+ 'scons_settings': {
+ 'sconsbuild_dir': '<(DEPTH)/sconsbuild',
+ 'tools': ['ar', 'as', 'gcc', 'g++', 'gnulink', 'chromium_builders'],
+ },
+ 'xcode_settings': {
+ # DON'T ADD ANYTHING NEW TO THIS BLOCK UNLESS YOU REALLY REALLY NEED IT!
+ # This block adds *project-wide* configuration settings to each project
+ # file. It's almost always wrong to put things here. Specify your
+ # custom xcode_settings in target_defaults to add them to targets instead.
+
+ # In an Xcode Project Info window, the "Base SDK for All Configurations"
+ # setting sets the SDK on a project-wide basis. In order to get the
+ # configured SDK to show properly in the Xcode UI, SDKROOT must be set
+ # here at the project level.
+ 'SDKROOT': 'macosx<(mac_sdk)', # -isysroot
+
+ # The Xcode generator will look for an xcode_settings section at the root
+ # of each dict and use it to apply settings on a file-wide basis. Most
+ # settings should not be here, they should be in target-specific
+ # xcode_settings sections, or better yet, should use non-Xcode-specific
+ # settings in target dicts. SYMROOT is a special case, because many other
+ # Xcode variables depend on it, including variables such as
+ # PROJECT_DERIVED_FILE_DIR. When a source group corresponding to something
+ # like PROJECT_DERIVED_FILE_DIR is added to a project, in order for the
+ # files to appear (when present) in the UI as actual files and not red
+ # red "missing file" proxies, the correct path to PROJECT_DERIVED_FILE_DIR,
+ # and therefore SYMROOT, needs to be set at the project level.
+ 'SYMROOT': '<(DEPTH)/xcodebuild',
+ },
+}
diff --git a/toolkit/crashreporter/google-breakpad/src/build/filename_rules.gypi b/toolkit/crashreporter/google-breakpad/src/build/filename_rules.gypi
new file mode 100644
index 0000000000..78cd1808a9
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/build/filename_rules.gypi
@@ -0,0 +1,57 @@
+# 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_conditions': [
+ ['OS!="win"', {
+ 'sources/': [
+ ['exclude', '(^|/)windows/'],
+ ],
+ }],
+ ['OS!="linux"', {
+ 'sources/': [
+ ['exclude', '(^|/)linux/'],
+ ],
+ }],
+ ['OS!="mac"', {
+ 'sources/': [
+ ['exclude', '(^|/)mac/'],
+ ],
+ }],
+ ['OS!="android"', {
+ 'sources/': [
+ ['exclude', '(^|/)android/'],
+ ],
+ }],
+ ['OS!="solaris"', {
+ 'sources/': [
+ ['exclude', '(^|/)solaris/'],
+ ],
+ }],
+ ],
+}
diff --git a/toolkit/crashreporter/google-breakpad/src/build/gyp_breakpad b/toolkit/crashreporter/google-breakpad/src/build/gyp_breakpad
new file mode 100755
index 0000000000..0b8077d2f4
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/build/gyp_breakpad
@@ -0,0 +1,67 @@
+#!/usr/bin/env python
+
+# 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.
+
+import os
+import platform
+import sys
+
+script_dir = os.path.dirname(os.path.realpath(__file__))
+breakpad_root = os.path.abspath(os.path.join(script_dir, os.pardir))
+
+sys.path.insert(0, os.path.join(breakpad_root, 'tools', 'gyp', 'pylib'))
+import gyp
+
+def run_gyp(args):
+ rc = gyp.main(args)
+ if rc != 0:
+ print 'Error running GYP'
+ sys.exit(rc)
+
+
+def main():
+ args = sys.argv[1:]
+ args.append(os.path.join(script_dir, 'all.gyp'))
+
+ args.append('-I')
+ args.append(os.path.join(breakpad_root, 'build', 'common.gypi'))
+
+ args.extend(['-D', 'gyp_output_dir=out'])
+
+ # Set the GYP DEPTH variable to the root of the project.
+ args.append('--depth=' + os.path.relpath(breakpad_root))
+
+ print 'Updating projects from gyp files...'
+ sys.stdout.flush()
+
+ run_gyp(args)
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/toolkit/crashreporter/google-breakpad/src/build/testing.gyp b/toolkit/crashreporter/google-breakpad/src/build/testing.gyp
new file mode 100644
index 0000000000..6a459a646f
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/build/testing.gyp
@@ -0,0 +1,90 @@
+# 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.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'gtest',
+ 'type': 'static_library',
+ 'sources': [
+ '../testing/googletest/src/gtest-all.cc',
+ ],
+ 'include_dirs': [
+ '../testing/googletest',
+ '../testing/googletest/include',
+ ],
+ 'direct_dependent_settings': {
+ 'include_dirs': [
+ '../testing/googletest/include',
+ ],
+ },
+ },
+ {
+ 'target_name': 'gtest_main',
+ 'type': 'static_library',
+ 'dependencies': [
+ 'gtest',
+ ],
+ 'sources': [
+ '../testing/googletest/src/gtest_main.cc',
+ ],
+ },
+ {
+ 'target_name': 'gmock',
+ 'type': 'static_library',
+ 'dependencies': [
+ 'gtest',
+ ],
+ 'sources': [
+ '../testing/googlemock/src/gmock-all.cc',
+ ],
+ 'include_dirs': [
+ '../testing/googlemock',
+ '../testing/googlemock/include',
+ ],
+ 'direct_dependent_settings': {
+ 'include_dirs': [
+ '../testing/googlemock/include',
+ ],
+ },
+ 'export_dependent_settings': [
+ 'gtest',
+ ],
+ },
+ {
+ 'target_name': 'gmock_main',
+ 'type': 'static_library',
+ 'dependencies': [
+ 'gmock',
+ ],
+ 'sources': [
+ '../testing/googlemock/src/gmock_main.cc',
+ ],
+ },
+ ],
+}
diff --git a/toolkit/crashreporter/google-breakpad/src/common/android/include/asm-mips/README.md b/toolkit/crashreporter/google-breakpad/src/common/android/include/asm-mips/README.md
new file mode 100644
index 0000000000..b56ee60f13
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/android/include/asm-mips/README.md
@@ -0,0 +1,9 @@
+# asm-mips
+
+The files in this directory are almost direct copies from Android NDK r12, with
+the exception of changing the include guards to Breakpad ones. They are copied
+from the MIPS asm/ directory, but are meant to be used as replacements for both
+asm/ and machine/ includes since the files in each are largely duplicates.
+
+Some MIPS asm/ and all machine/ headers were removed in the move to unified NDK
+headers, so Breakpad fails to compile on newer NDK versions without these files. \ No newline at end of file
diff --git a/toolkit/crashreporter/google-breakpad/src/common/android/include/asm-mips/asm.h b/toolkit/crashreporter/google-breakpad/src/common/android/include/asm-mips/asm.h
new file mode 100644
index 0000000000..8f086e7566
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/android/include/asm-mips/asm.h
@@ -0,0 +1,270 @@
+#ifndef GOOGLE_BREAKPAD_COMMON_ANDROID_INCLUDE_ASM_MIPS_ASM_H
+#define GOOGLE_BREAKPAD_COMMON_ANDROID_INCLUDE_ASM_MIPS_ASM_H
+
+#if defined(__has_include_next) && __has_include_next(<asm/asm.h>)
+#include_next <asm/asm.h>
+#else
+
+/****************************************************************************
+ ****************************************************************************
+ ***
+ *** This header was automatically generated from a Linux kernel header
+ *** of the same name, to make information necessary for userspace to
+ *** call into the kernel available to libc. It contains only constants,
+ *** structures, and macros generated from the original header, and thus,
+ *** contains no copyrightable information.
+ ***
+ *** To edit the content of this header, modify the corresponding
+ *** source file (e.g. under external/kernel-headers/original/) then
+ *** run bionic/libc/kernel/tools/update_all.py
+ ***
+ *** Any manual change here will be lost the next time this script will
+ *** be run. You've been warned!
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+
+#include <asm/sgidefs.h>
+#ifndef CAT
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#ifdef __STDC__
+#define __CAT(str1, str2) str1##str2
+#else
+#define __CAT(str1, str2) str1 str2
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#endif
+#define CAT(str1, str2) __CAT(str1, str2)
+#endif
+#ifdef __PIC__
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define CPRESTORE(register) .cprestore register
+#define CPADD(register) .cpadd register
+#define CPLOAD(register) .cpload register
+#else
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define CPRESTORE(register)
+#define CPADD(register)
+#define CPLOAD(register)
+#endif
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define LEAF(symbol) .globl symbol; .align 2; .type symbol, @function; .ent symbol, 0; symbol: .frame sp, 0, ra
+#define NESTED(symbol, framesize, rpc) .globl symbol; .align 2; .type symbol, @function; .ent symbol, 0; symbol: .frame sp, framesize, rpc
+#define END(function) .end function; .size function, .-function
+#define EXPORT(symbol) .globl symbol; symbol:
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define FEXPORT(symbol) .globl symbol; .type symbol, @function; symbol:
+#define ABS(symbol,value) .globl symbol; symbol = value
+#define PANIC(msg) .set push; .set reorder; PTR_LA a0, 8f; jal panic; 9: b 9b; .set pop; TEXT(msg)
+#define PRINT(string)
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define TEXT(msg) .pushsection .data; 8: .asciiz msg; .popsection;
+#define TTABLE(string) .pushsection .text; .word 1f; .popsection .pushsection .data; 1: .asciiz string; .popsection
+#define PREF(hint, addr)
+#define PREFX(hint, addr)
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#if _MIPS_ISA == _MIPS_ISA_MIPS1
+#define MOVN(rd, rs, rt) .set push; .set reorder; beqz rt, 9f; move rd, rs; .set pop; 9:
+#define MOVZ(rd, rs, rt) .set push; .set reorder; bnez rt, 9f; move rd, rs; .set pop; 9:
+#endif
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#if _MIPS_ISA == _MIPS_ISA_MIPS2 || _MIPS_ISA == _MIPS_ISA_MIPS3
+#define MOVN(rd, rs, rt) .set push; .set noreorder; bnezl rt, 9f; move rd, rs; .set pop; 9:
+#define MOVZ(rd, rs, rt) .set push; .set noreorder; beqzl rt, 9f; move rd, rs; .set pop; 9:
+#endif
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#if _MIPS_ISA == _MIPS_ISA_MIPS4 || _MIPS_ISA == _MIPS_ISA_MIPS5 || _MIPS_ISA == _MIPS_ISA_MIPS32 || _MIPS_ISA == _MIPS_ISA_MIPS64
+#define MOVN(rd, rs, rt) movn rd, rs, rt
+#define MOVZ(rd, rs, rt) movz rd, rs, rt
+#endif
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#if _MIPS_SIM == _MIPS_SIM_ABI32
+#define ALSZ 7
+#define ALMASK ~7
+#endif
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#if _MIPS_SIM == _MIPS_SIM_NABI32 || _MIPS_SIM == _MIPS_SIM_ABI64
+#define ALSZ 15
+#define ALMASK ~15
+#endif
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#ifdef __mips64
+#define SZREG 8
+#else
+#define SZREG 4
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#endif
+#if _MIPS_SIM == _MIPS_SIM_ABI32
+#define REG_S sw
+#define REG_L lw
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define REG_SUBU subu
+#define REG_ADDU addu
+#endif
+#if _MIPS_SIM == _MIPS_SIM_NABI32 || _MIPS_SIM == _MIPS_SIM_ABI64
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define REG_S sd
+#define REG_L ld
+#define REG_SUBU dsubu
+#define REG_ADDU daddu
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#endif
+#if _MIPS_SZINT == 32
+#define INT_ADD add
+#define INT_ADDU addu
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define INT_ADDI addi
+#define INT_ADDIU addiu
+#define INT_SUB sub
+#define INT_SUBU subu
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define INT_L lw
+#define INT_S sw
+#define INT_SLL sll
+#define INT_SLLV sllv
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define INT_SRL srl
+#define INT_SRLV srlv
+#define INT_SRA sra
+#define INT_SRAV srav
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#endif
+#if _MIPS_SZINT == 64
+#define INT_ADD dadd
+#define INT_ADDU daddu
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define INT_ADDI daddi
+#define INT_ADDIU daddiu
+#define INT_SUB dsub
+#define INT_SUBU dsubu
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define INT_L ld
+#define INT_S sd
+#define INT_SLL dsll
+#define INT_SLLV dsllv
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define INT_SRL dsrl
+#define INT_SRLV dsrlv
+#define INT_SRA dsra
+#define INT_SRAV dsrav
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#endif
+#if _MIPS_SZLONG == 32
+#define LONG_ADD add
+#define LONG_ADDU addu
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define LONG_ADDI addi
+#define LONG_ADDIU addiu
+#define LONG_SUB sub
+#define LONG_SUBU subu
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define LONG_L lw
+#define LONG_S sw
+#define LONG_SLL sll
+#define LONG_SLLV sllv
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define LONG_SRL srl
+#define LONG_SRLV srlv
+#define LONG_SRA sra
+#define LONG_SRAV srav
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define LONG .word
+#define LONGSIZE 4
+#define LONGMASK 3
+#define LONGLOG 2
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#endif
+#if _MIPS_SZLONG == 64
+#define LONG_ADD dadd
+#define LONG_ADDU daddu
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define LONG_ADDI daddi
+#define LONG_ADDIU daddiu
+#define LONG_SUB dsub
+#define LONG_SUBU dsubu
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define LONG_L ld
+#define LONG_S sd
+#define LONG_SLL dsll
+#define LONG_SLLV dsllv
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define LONG_SRL dsrl
+#define LONG_SRLV dsrlv
+#define LONG_SRA dsra
+#define LONG_SRAV dsrav
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define LONG .dword
+#define LONGSIZE 8
+#define LONGMASK 7
+#define LONGLOG 3
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#endif
+#if _MIPS_SZPTR == 32
+#define PTR_ADD add
+#define PTR_ADDU addu
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define PTR_ADDI addi
+#define PTR_ADDIU addiu
+#define PTR_SUB sub
+#define PTR_SUBU subu
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define PTR_L lw
+#define PTR_S sw
+#define PTR_LA la
+#define PTR_LI li
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define PTR_SLL sll
+#define PTR_SLLV sllv
+#define PTR_SRL srl
+#define PTR_SRLV srlv
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define PTR_SRA sra
+#define PTR_SRAV srav
+#define PTR_SCALESHIFT 2
+#define PTR .word
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define PTRSIZE 4
+#define PTRLOG 2
+#endif
+#if _MIPS_SZPTR == 64
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define PTR_ADD dadd
+#define PTR_ADDU daddu
+#define PTR_ADDI daddi
+#define PTR_ADDIU daddiu
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define PTR_SUB dsub
+#define PTR_SUBU dsubu
+#define PTR_L ld
+#define PTR_S sd
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define PTR_LA dla
+#define PTR_LI dli
+#define PTR_SLL dsll
+#define PTR_SLLV dsllv
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define PTR_SRL dsrl
+#define PTR_SRLV dsrlv
+#define PTR_SRA dsra
+#define PTR_SRAV dsrav
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define PTR_SCALESHIFT 3
+#define PTR .dword
+#define PTRSIZE 8
+#define PTRLOG 3
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#endif
+#if _MIPS_SIM == _MIPS_SIM_ABI32
+#define MFC0 mfc0
+#define MTC0 mtc0
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#endif
+#if _MIPS_SIM == _MIPS_SIM_NABI32 || _MIPS_SIM == _MIPS_SIM_ABI64
+#define MFC0 dmfc0
+#define MTC0 dmtc0
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#endif
+#define SSNOP sll zero, zero, 1
+#define R10KCBARRIER(addr)
+#endif // defined(__has_include_next) && __has_include_next(<asm/asm.h>)
+#endif // GOOGLE_BREAKPAD_COMMON_ANDROID_INCLUDE_ASM_MIPS_ASM_H
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
diff --git a/toolkit/crashreporter/google-breakpad/src/common/android/include/asm-mips/fpregdef.h b/toolkit/crashreporter/google-breakpad/src/common/android/include/asm-mips/fpregdef.h
new file mode 100644
index 0000000000..a6eedc0e98
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/android/include/asm-mips/fpregdef.h
@@ -0,0 +1,117 @@
+#ifndef GOOGLE_BREAKPAD_COMMON_ANDROID_INCLUDE_ASM_MIPS_FPREGDEF_H
+#define GOOGLE_BREAKPAD_COMMON_ANDROID_INCLUDE_ASM_MIPS_FPREGDEF_H
+
+#if defined(__has_include_next) && __has_include_next(<asm/fpregdef.h>)
+#include_next <asm/fpregdef.h>
+#else
+
+/****************************************************************************
+ ****************************************************************************
+ ***
+ *** This header was automatically generated from a Linux kernel header
+ *** of the same name, to make information necessary for userspace to
+ *** call into the kernel available to libc. It contains only constants,
+ *** structures, and macros generated from the original header, and thus,
+ *** contains no copyrightable information.
+ ***
+ *** To edit the content of this header, modify the corresponding
+ *** source file (e.g. under external/kernel-headers/original/) then
+ *** run bionic/libc/kernel/tools/update_all.py
+ ***
+ *** Any manual change here will be lost the next time this script will
+ *** be run. You've been warned!
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+
+#include <asm/sgidefs.h>
+#if _MIPS_SIM == _MIPS_SIM_ABI32
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define fv0 $f0
+#define fv0f $f1
+#define fv1 $f2
+#define fv1f $f3
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define fa0 $f12
+#define fa0f $f13
+#define fa1 $f14
+#define fa1f $f15
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define ft0 $f4
+#define ft0f $f5
+#define ft1 $f6
+#define ft1f $f7
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define ft2 $f8
+#define ft2f $f9
+#define ft3 $f10
+#define ft3f $f11
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define ft4 $f16
+#define ft4f $f17
+#define ft5 $f18
+#define ft5f $f19
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define fs0 $f20
+#define fs0f $f21
+#define fs1 $f22
+#define fs1f $f23
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define fs2 $f24
+#define fs2f $f25
+#define fs3 $f26
+#define fs3f $f27
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define fs4 $f28
+#define fs4f $f29
+#define fs5 $f30
+#define fs5f $f31
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define fcr31 $31
+#endif
+#if _MIPS_SIM == _MIPS_SIM_ABI64 || _MIPS_SIM == _MIPS_SIM_NABI32
+#define fv0 $f0
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define fv1 $f2
+#define fa0 $f12
+#define fa1 $f13
+#define fa2 $f14
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define fa3 $f15
+#define fa4 $f16
+#define fa5 $f17
+#define fa6 $f18
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define fa7 $f19
+#define ft0 $f4
+#define ft1 $f5
+#define ft2 $f6
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define ft3 $f7
+#define ft4 $f8
+#define ft5 $f9
+#define ft6 $f10
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define ft7 $f11
+#define ft8 $f20
+#define ft9 $f21
+#define ft10 $f22
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define ft11 $f23
+#define ft12 $f1
+#define ft13 $f3
+#define fs0 $f24
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define fs1 $f25
+#define fs2 $f26
+#define fs3 $f27
+#define fs4 $f28
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define fs5 $f29
+#define fs6 $f30
+#define fs7 $f31
+#define fcr31 $31
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#endif
+#endif // defined(__has_include_next) && __has_include_next(<asm/fpregdef.h>)
+#endif // GOOGLE_BREAKPAD_COMMON_ANDROID_INCLUDE_ASM_MIPS_FPREGDEF_H
diff --git a/toolkit/crashreporter/google-breakpad/src/common/android/include/asm-mips/regdef.h b/toolkit/crashreporter/google-breakpad/src/common/android/include/asm-mips/regdef.h
new file mode 100644
index 0000000000..a7fd769059
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/android/include/asm-mips/regdef.h
@@ -0,0 +1,125 @@
+#ifndef GOOGLE_BREAKPAD_COMMON_ANDROID_INCLUDE_ASM_MIPS_REGDEF_H
+#define GOOGLE_BREAKPAD_COMMON_ANDROID_INCLUDE_ASM_MIPS_REGDEF_H
+
+#if defined(__has_include_next) && __has_include_next(<asm/regdef.h>)
+#include_next <asm/regdef.h>
+#else
+
+/****************************************************************************
+ ****************************************************************************
+ ***
+ *** This header was automatically generated from a Linux kernel header
+ *** of the same name, to make information necessary for userspace to
+ *** call into the kernel available to libc. It contains only constants,
+ *** structures, and macros generated from the original header, and thus,
+ *** contains no copyrightable information.
+ ***
+ *** To edit the content of this header, modify the corresponding
+ *** source file (e.g. under external/kernel-headers/original/) then
+ *** run bionic/libc/kernel/tools/update_all.py
+ ***
+ *** Any manual change here will be lost the next time this script will
+ *** be run. You've been warned!
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+
+#include <asm/sgidefs.h>
+#if _MIPS_SIM == _MIPS_SIM_ABI32
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define zero $0
+#define AT $1
+#define v0 $2
+#define v1 $3
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define a0 $4
+#define a1 $5
+#define a2 $6
+#define a3 $7
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define t0 $8
+#define t1 $9
+#define t2 $10
+#define t3 $11
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define t4 $12
+#define t5 $13
+#define t6 $14
+#define t7 $15
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define s0 $16
+#define s1 $17
+#define s2 $18
+#define s3 $19
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define s4 $20
+#define s5 $21
+#define s6 $22
+#define s7 $23
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define t8 $24
+#define t9 $25
+#define jp $25
+#define k0 $26
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define k1 $27
+#define gp $28
+#define sp $29
+#define fp $30
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define s8 $30
+#define ra $31
+#endif
+#if _MIPS_SIM == _MIPS_SIM_ABI64 || _MIPS_SIM == _MIPS_SIM_NABI32
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define zero $0
+#define AT $at
+#define v0 $2
+#define v1 $3
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define a0 $4
+#define a1 $5
+#define a2 $6
+#define a3 $7
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define a4 $8
+#define ta0 $8
+#define a5 $9
+#define ta1 $9
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define a6 $10
+#define ta2 $10
+#define a7 $11
+#define ta3 $11
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define t0 $12
+#define t1 $13
+#define t2 $14
+#define t3 $15
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define s0 $16
+#define s1 $17
+#define s2 $18
+#define s3 $19
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define s4 $20
+#define s5 $21
+#define s6 $22
+#define s7 $23
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define t8 $24
+#define t9 $25
+#define jp $25
+#define k0 $26
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define k1 $27
+#define gp $28
+#define sp $29
+#define fp $30
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define s8 $30
+#define ra $31
+#endif
+#endif // defined(__has_include_next) && __has_include_next(<asm/regdef.h>)
+#endif // GOOGLE_BREAKPAD_COMMON_ANDROID_INCLUDE_ASM_MIPS_REGDEF_H
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
diff --git a/toolkit/crashreporter/google-breakpad/src/common/android/include/elf.h b/toolkit/crashreporter/google-breakpad/src/common/android/include/elf.h
new file mode 100644
index 0000000000..e6f0c672f9
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/android/include/elf.h
@@ -0,0 +1,157 @@
+// 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;
+
+
+// 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
new file mode 100644
index 0000000000..4324629df7
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/android/include/link.h
@@ -0,0 +1,77 @@
+// 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>
+
+#include <android/api-level.h>
+
+// TODO(rmcilroy): Remove this file once the NDK API level is updated to at
+// least 21 for all architectures. https://crbug.com/358831
+
+// These structures are only present in traditional headers at API level 21 and
+// above. Unified headers define these structures regardless of the chosen API
+// level. __ANDROID_API_N__ is a proxy for determining whether unified headers
+// are in use. It’s only defined by unified headers.
+#if __ANDROID_API__ < 21 && !defined(__ANDROID_API_N__)
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+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;
+};
+
+#ifdef __cplusplus
+} // extern "C"
+#endif // __cplusplus
+
+#endif // __ANDROID_API__ < 21 && !defined(__ANDROID_API_N__)
+
+#endif /* GOOGLE_BREAKPAD_ANDROID_INCLUDE_LINK_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
new file mode 100644
index 0000000000..cd92902151
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/android/include/stab.h
@@ -0,0 +1,100 @@
+// 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
new file mode 100644
index 0000000000..185124364e
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/android/include/sys/procfs.h
@@ -0,0 +1,124 @@
+// 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/user.h b/toolkit/crashreporter/google-breakpad/src/common/android/include/sys/user.h
new file mode 100644
index 0000000000..9c27ef0225
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/android/include/sys/user.h
@@ -0,0 +1,69 @@
+// 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.
+
+// TODO(primiano): remove these changes after Chromium has stably rolled to
+// an NDK with the appropriate fixes. https://crbug.com/358831
+
+// With traditional headers, <sys/user.h> forgot to do this. Unified headers get
+// it right.
+#include <sys/types.h>
+
+#include_next <sys/user.h>
+
+#include <android/api-level.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#if defined(__i386__)
+#if __ANDROID_API__ < 21 && !defined(__ANDROID_API_N__)
+
+// user_fpxregs_struct was called user_fxsr_struct in traditional headers before
+// API level 21. Unified headers call it user_fpxregs_struct regardless of the
+// chosen API level. __ANDROID_API_N__ is a proxy for determining whether
+// unified headers are in use. It’s only defined by unified headers.
+typedef struct user_fxsr_struct user_fpxregs_struct;
+
+#endif // __ANDROID_API__ < 21 && !defined(__ANDROID_API_N__)
+#endif // defined(__i386__)
+
+#ifdef __cplusplus
+} // extern "C"
+#endif // __cplusplus
+
+#endif // GOOGLE_BREAKPAD_COMMON_ANDROID_INCLUDE_SYS_USER_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
new file mode 100644
index 0000000000..85373fd2a0
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/android/testing/include/wchar.h
@@ -0,0 +1,76 @@
+// 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
new file mode 100644
index 0000000000..b86e2cd783
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/android/testing/mkdtemp.h
@@ -0,0 +1,110 @@
+// 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
new file mode 100644
index 0000000000..20c1208480
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/android/testing/pthread_fixes.h
@@ -0,0 +1,94 @@
+// 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)
+
+} // namespace
+
+#endif // GOOGLE_BREAKPAD_COMMON_ANDROID_TESTING_PTHREAD_FIXES_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
new file mode 100644
index 0000000000..2d1ed983dc
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/arm_ex_reader.cc
@@ -0,0 +1,487 @@
+
+/* 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
new file mode 100644
index 0000000000..9b54e8a0be
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/arm_ex_reader.h
@@ -0,0 +1,114 @@
+/* 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
new file mode 100644
index 0000000000..c326744f64
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/arm_ex_to_module.cc
@@ -0,0 +1,209 @@
+
+/* 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
new file mode 100644
index 0000000000..f413a16a93
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/arm_ex_to_module.h
@@ -0,0 +1,119 @@
+/* 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
new file mode 100644
index 0000000000..9426c1f6c2
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/basictypes.h
@@ -0,0 +1,58 @@
+// 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
new file mode 100644
index 0000000000..accd54e0a4
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/byte_cursor.h
@@ -0,0 +1,265 @@
+// -*- 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
new file mode 100644
index 0000000000..06bfd89d73
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/byte_cursor_unittest.cc
@@ -0,0 +1,776 @@
+// 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
new file mode 100644
index 0000000000..c1dbb0febf
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/common.gyp
@@ -0,0 +1,260 @@
+# 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"', {
+ # Assume glibc.
+ 'defines': ['HAVE_A_OUT_H', 'HAVE_GETCONTEXT'],
+ 'sources!': [
+ 'linux/breakpad_getcontext.S',
+ 'linux/breakpad_getcontext.h',
+ 'linux/breakpad_getcontext_unittest.cc',
+ ],
+ }],
+ ['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/include/elf.h',
+ 'android/include/link.h',
+ 'android/include/stab.h',
+ 'android/include/sys/procfs.h',
+ 'android/include/sys/user.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.cc',
+ '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/breakpad_getcontext.S',
+ 'linux/breakpad_getcontext.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/symbol_collector_client.cc',
+ 'linux/symbol_collector_client.h',
+ 'linux/synth_elf.cc',
+ 'linux/synth_elf.h',
+ 'long_string_dictionary.cc',
+ 'long_string_dictionary.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_allocator.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': [
+ '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/breakpad_getcontext_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',
+ 'long_string_dictionary_unittest.cc',
+ 'mac/macho_reader_unittest.cc',
+ 'memory_allocator_unittest.cc',
+ 'memory_range_unittest.cc',
+ 'module_unittest.cc',
+ 'simple_string_dictionary_unittest.cc',
+ 'stabs_reader_unittest.cc',
+ 'stabs_to_module_unittest.cc',
+ 'string_conversion_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.gyp:gmock_main',
+ '../build/testing.gyp:gmock',
+ '../build/testing.gyp:gtest',
+ ],
+ 'libraries': [
+ '-ldl',
+ ],
+ },
+ ],
+}
diff --git a/toolkit/crashreporter/google-breakpad/src/common/convert_UTF.cc b/toolkit/crashreporter/google-breakpad/src/common/convert_UTF.cc
new file mode 100644
index 0000000000..4a5df1eb27
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/convert_UTF.cc
@@ -0,0 +1,591 @@
+/*
+ * 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
+
+#include "common/macros.h"
+
+namespace google_breakpad {
+
+namespace {
+
+const int halfShift = 10; /* used for shifting by 10 bits */
+
+const UTF32 halfBase = 0x0010000UL;
+const UTF32 halfMask = 0x3FFUL;
+
+} // namespace
+
+#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
+
+/* --------------------------------------------------------------------- */
+
+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;
+}
+
+/* --------------------------------------------------------------------- */
+
+namespace {
+
+/*
+ * 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.
+ */
+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.
+ */
+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.
+ */
+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.
+*/
+
+} // namespace
+
+/* --------------------------------------------------------------------- */
+
+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;
+ BP_FALLTHROUGH;
+ case 3:
+ *--target = (UTF8)((ch | byteMark) & byteMask);
+ ch >>= 6;
+ BP_FALLTHROUGH;
+ case 2:
+ *--target = (UTF8)((ch | byteMark) & byteMask);
+ ch >>= 6;
+ BP_FALLTHROUGH;
+ case 1:
+ *--target = (UTF8)(ch | firstByteMark[bytesToWrite]);
+ }
+ target += bytesToWrite;
+ }
+*sourceStart = source;
+*targetStart = target;
+return result;
+}
+
+/* --------------------------------------------------------------------- */
+
+namespace {
+
+/*
+ * 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.
+ */
+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;
+ BP_FALLTHROUGH;
+ case 3:
+ if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false;
+ BP_FALLTHROUGH;
+ 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;
+ }
+ BP_FALLTHROUGH;
+ case 1: if (*source >= 0x80 && *source < 0xC2) return false;
+ }
+ if (*source > 0xF4) return false;
+ return true;
+}
+
+} // namespace
+
+/* --------------------------------------------------------------------- */
+
+/*
+ * 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) {
+ /* remember, illegal UTF-8 */
+ case 5: ch += *source++; ch <<= 6; BP_FALLTHROUGH;
+ /* remember, illegal UTF-8 */
+ case 4: ch += *source++; ch <<= 6; BP_FALLTHROUGH;
+ case 3: ch += *source++; ch <<= 6; BP_FALLTHROUGH;
+ case 2: ch += *source++; ch <<= 6; BP_FALLTHROUGH;
+ case 1: ch += *source++; ch <<= 6; BP_FALLTHROUGH;
+ 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;
+ BP_FALLTHROUGH;
+ case 3:
+ *--target = (UTF8)((ch | byteMark) & byteMask);
+ ch >>= 6;
+ BP_FALLTHROUGH;
+ case 2:
+ *--target = (UTF8)((ch | byteMark) & byteMask);
+ ch >>= 6;
+ BP_FALLTHROUGH;
+ 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; BP_FALLTHROUGH;
+ case 4: ch += *source++; ch <<= 6; BP_FALLTHROUGH;
+ case 3: ch += *source++; ch <<= 6; BP_FALLTHROUGH;
+ case 2: ch += *source++; ch <<= 6; BP_FALLTHROUGH;
+ case 1: ch += *source++; ch <<= 6; BP_FALLTHROUGH;
+ 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.
+
+--------------------------------------------------------------------- */
+
+} // namespace google_breakpad
diff --git a/toolkit/crashreporter/google-breakpad/src/common/convert_UTF.h b/toolkit/crashreporter/google-breakpad/src/common/convert_UTF.h
new file mode 100644
index 0000000000..2f69495d24
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/convert_UTF.h
@@ -0,0 +1,159 @@
+/*
+ * 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.
+------------------------------------------------------------------------ */
+
+namespace google_breakpad {
+
+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;
+
+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);
+
+} // namespace google_breakpad
+
+/* --------------------------------------------------------------------- */
+
+#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
new file mode 100644
index 0000000000..42c92f943f
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/dwarf/bytereader-inl.h
@@ -0,0 +1,170 @@
+// 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
new file mode 100644
index 0000000000..14b43adb8f
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/dwarf/bytereader.cc
@@ -0,0 +1,250 @@
+// 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
new file mode 100644
index 0000000000..59d4303480
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/dwarf/bytereader.h
@@ -0,0 +1,315 @@
+// -*- 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
new file mode 100644
index 0000000000..e66062d1fe
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/dwarf/bytereader_unittest.cc
@@ -0,0 +1,707 @@
+// 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
new file mode 100644
index 0000000000..2dc2208577
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/dwarf/cfi_assembler.cc
@@ -0,0 +1,204 @@
+// 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,
+ uint8_t address_size,
+ uint8_t segment_size) {
+ 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);
+ if (version >= 4) {
+ D8(address_size);
+ D8(segment_size);
+ }
+ 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
new file mode 100644
index 0000000000..bd7354d127
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/dwarf/cfi_assembler.h
@@ -0,0 +1,271 @@
+// -*- 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,
+ uint8_t address_size = 8,
+ uint8_t segment_size = 0);
+
+ // 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
new file mode 100644
index 0000000000..94542b5ea9
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/dwarf/dwarf2diehandler.cc
@@ -0,0 +1,199 @@
+// 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
new file mode 100644
index 0000000000..a1e589a863
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/dwarf/dwarf2diehandler.h
@@ -0,0 +1,365 @@
+// -*- 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
new file mode 100644
index 0000000000..db70eb31b9
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/dwarf/dwarf2diehandler_unittest.cc
@@ -0,0 +1,527 @@
+// -*- 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
new file mode 100644
index 0000000000..4316a89ccd
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/dwarf/dwarf2enums.h
@@ -0,0 +1,679 @@
+// -*- 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,
+ // DWARF 4
+ DW_AT_linkage_name = 0x6e,
+ // 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,
+ DW_LANG_Rust =0x001c,
+ DW_LANG_Swift =0x001e,
+ // 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
new file mode 100644
index 0000000000..3e6a3e89f4
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/dwarf/dwarf2reader.cc
@@ -0,0 +1,2815 @@
+// 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;
+
+ if (header_.version >= 4) {
+ __attribute__((unused)) uint8 max_ops_per_insn =
+ reader_->ReadOneByte(lineptr);
+ ++lineptr;
+ assert(max_ops_per_insn == 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;
+}
+
+RangeListReader::RangeListReader(const uint8_t *buffer, uint64 size,
+ ByteReader *reader, RangeListHandler *handler)
+ : buffer_(buffer), size_(size), reader_(reader), handler_(handler) { }
+
+bool RangeListReader::ReadRangeList(uint64 offset) {
+ const uint64 max_address =
+ (reader_->AddressSize() == 4) ? 0xffffffffUL
+ : 0xffffffffffffffffULL;
+ const uint64 entry_size = reader_->AddressSize() * 2;
+ bool list_end = false;
+
+ do {
+ if (offset > size_ - entry_size) {
+ return false; // Invalid range detected
+ }
+
+ uint64 start_address = reader_->ReadAddress(buffer_ + offset);
+ uint64 end_address =
+ reader_->ReadAddress(buffer_ + offset + reader_->AddressSize());
+
+ if (start_address == max_address) { // Base address selection
+ handler_->SetBaseAddress(end_address);
+ } else if (start_address == 0 && end_address == 0) { // End-of-list
+ handler_->Finish();
+ list_end = true;
+ } else { // Add a range entry
+ handler_->AddRange(start_address, end_address);
+ }
+
+ offset += entry_size;
+ } while (!list_end);
+
+ return true;
+}
+
+// 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, REG can be recovered using
+ // this rule. If REG 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 reg) 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 4 (there was never a
+ // version 2 of CFI data). For .eh_frame, we handle versions 1 and 4 as well;
+ // the difference between those versions seems to be the same as for
+ // .debug_frame.
+ if (cie->version < 1 || cie->version > 4) {
+ 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;
+ }
+ }
+
+ if (cie->version >= 4) {
+ cie->address_size = *cursor++;
+ if (cie->address_size != 8 && cie->address_size != 4) {
+ reporter_->UnexpectedAddressSize(cie->offset, cie->address_size);
+ return false;
+ }
+
+ cie->segment_size = *cursor++;
+ if (cie->segment_size != 0) {
+ reporter_->UnexpectedSegmentSize(cie->offset, cie->segment_size);
+ 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;
+
+ // TODO(nbilling): This could lead to strange behavior if a single buffer
+ // contained a mixture of DWARF versions as well as address sizes. Not
+ // sure if it's worth handling such a case.
+
+ // DWARF4 CIE specifies address_size, so use it for this call frame.
+ if (cie.version >= 4) {
+ reader_->SetAddressSize(cie.address_size);
+ }
+
+ // 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::UnexpectedAddressSize(uint64 offset,
+ uint8_t address_size) {
+ fprintf(stderr,
+ "%s: CFI frame description entry at offset 0x%llx in '%s':"
+ " CIE specifies unexpected address size: %d\n",
+ filename_.c_str(), offset, section_.c_str(), address_size);
+}
+
+void CallFrameInfo::Reporter::UnexpectedSegmentSize(uint64 offset,
+ uint8_t segment_size) {
+ fprintf(stderr,
+ "%s: CFI frame description entry at offset 0x%llx in '%s':"
+ " CIE specifies unexpected segment size: %d\n",
+ filename_.c_str(), offset, section_.c_str(), segment_size);
+}
+
+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
new file mode 100644
index 0000000000..902d9ef1f4
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/dwarf/dwarf2reader.h
@@ -0,0 +1,1331 @@
+// -*- 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) { }
+};
+
+class RangeListHandler {
+ public:
+ RangeListHandler() { }
+
+ virtual ~RangeListHandler() { }
+
+ // Add a range.
+ virtual void AddRange(uint64 begin, uint64 end) { };
+
+ // A new base address must be set for computing the ranges' addresses.
+ virtual void SetBaseAddress(uint64 base_address) { };
+
+ // Finish processing the range list.
+ virtual void Finish() { };
+};
+
+class RangeListReader {
+ public:
+ RangeListReader(const uint8_t *buffer, uint64 size, ByteReader *reader,
+ RangeListHandler *handler);
+
+ bool ReadRangeList(uint64 offset);
+
+ private:
+ const uint8_t *buffer_;
+ uint64 size_;
+ ByteReader* reader_;
+ RangeListHandler *handler_;
+};
+
+// 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;
+
+ // These were only introduced in DWARF4, so will not be set in older
+ // versions.
+ uint8 address_size;
+ uint8 segment_size;
+ };
+
+ // 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 an address size we don't know how
+ // to handle.
+ virtual void UnexpectedAddressSize(uint64 offset, uint8_t address_size);
+
+ // The FDE at OFFSET refers to a CIE with an segment descriptor size we
+ // don't know how to handle.
+ virtual void UnexpectedSegmentSize(uint64 offset, uint8_t segment_size);
+
+ // 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
new file mode 100644
index 0000000000..35d4f340d7
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/dwarf/dwarf2reader_cfi_unittest.cc
@@ -0,0 +1,2582 @@
+// 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(UnexpectedAddressSize, void(uint64, uint8_t));
+ MOCK_METHOD2(UnexpectedSegmentSize, void(uint64, uint8_t));
+ 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());
+}
+
+TEST_F(CFI, CIEVersion4AdditionalFields) {
+ CFISection section(kBigEndian, 8);
+ Label cie;
+ section
+ .Mark(&cie)
+ // CIE version 4 with expected address (64bit) and segment size.
+ .CIEHeader(0x0ab4758d, 0xc010fdf7, 0x89, 4, "", true, 8, 0)
+ .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, 4, "", 0x89))
+ .WillOnce(Return(true));
+ EXPECT_CALL(handler, End()).WillOnce(Return(true));
+ }
+
+ string contents;
+ EXPECT_TRUE(section.GetContents(&contents));
+ ByteReader byte_reader(ENDIANNESS_BIG);
+ CallFrameInfo parser(reinterpret_cast<const uint8_t *>(contents.data()),
+ contents.size(),
+ &byte_reader, &handler, &reporter);
+ EXPECT_TRUE(parser.Start());
+}
+
+TEST_F(CFI, CIEVersion4AdditionalFields32BitAddress) {
+ CFISection section(kBigEndian, 4);
+ Label cie;
+ section
+ .Mark(&cie)
+ // CIE version 4 with expected address (32bit) and segment size.
+ .CIEHeader(0x0ab4758d, 0xc010fdf7, 0x89, 4, "", true, 4, 0)
+ .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, 4, "", 0x89))
+ .WillOnce(Return(true));
+ EXPECT_CALL(handler, End()).WillOnce(Return(true));
+ }
+
+ string contents;
+ EXPECT_TRUE(section.GetContents(&contents));
+ ByteReader byte_reader(ENDIANNESS_BIG);
+ CallFrameInfo parser(reinterpret_cast<const uint8_t *>(contents.data()),
+ contents.size(),
+ &byte_reader, &handler, &reporter);
+ EXPECT_TRUE(parser.Start());
+}
+
+TEST_F(CFI, CIEVersion4AdditionalFieldsUnexpectedAddressSize) {
+ CFISection section(kBigEndian, 4);
+ Label cie;
+
+ section
+ .Mark(&cie)
+ // Unexpected address size.
+ .CIEHeader(0x4be22f75, 0x2492236e, 0x6b6efb87, 4, "", true, 3, 0)
+ .FinishEntry()
+ // FDE, citing that CIE.
+ .FDEHeader(cie, 0x86763f2b, 0x2a66dc23)
+ .FinishEntry();
+
+ PERHAPS_WRITE_DEBUG_FRAME_FILE("AdditionalFieldsUnexpectedAddress", section);
+
+ EXPECT_CALL(reporter, UnexpectedAddressSize(_, 3))
+ .WillOnce(Return());
+
+ string contents;
+ EXPECT_TRUE(section.GetContents(&contents));
+ ByteReader byte_reader(ENDIANNESS_BIG);
+ CallFrameInfo parser(reinterpret_cast<const uint8_t *>(contents.data()),
+ contents.size(),
+ &byte_reader, &handler, &reporter);
+ EXPECT_FALSE(parser.Start());
+}
+
+TEST_F(CFI, CIEVersion4AdditionalFieldsUnexpectedSegmentSize) {
+ CFISection section(kBigEndian, 8);
+ Label cie;
+
+ section
+ .Mark(&cie)
+ .CIEHeader(0xf8bc4399, 0x8cf09931, 0xf2f519b2, 4, "", true, 8, 7)
+ .FinishEntry()
+ .FDEHeader(cie, 0x7bf0fda0, 0xcbcd28d8)
+ .FinishEntry();
+
+ PERHAPS_WRITE_DEBUG_FRAME_FILE("AdditionalFieldsUnexpectedSegment", section);
+
+ EXPECT_CALL(reporter, UnexpectedSegmentSize(_, 7))
+ .WillOnce(Return());
+
+ string contents;
+ EXPECT_TRUE(section.GetContents(&contents));
+ ByteReader byte_reader(ENDIANNESS_BIG);
+ CallFrameInfo parser(reinterpret_cast<const uint8_t *>(contents.data()),
+ contents.size(),
+ &byte_reader, &handler, &reporter);
+ EXPECT_FALSE(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
new file mode 100644
index 0000000000..71418eb8d7
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/dwarf/dwarf2reader_die_unittest.cc
@@ -0,0 +1,487 @@
+// 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
new file mode 100644
index 0000000000..e91de90610
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/dwarf/dwarf2reader_test_common.h
@@ -0,0 +1,149 @@
+// -*- 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
new file mode 100644
index 0000000000..7e4be639a7
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/dwarf/elf_reader.cc
@@ -0,0 +1,1274 @@
+// 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
+// the machine's native word size. 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 <fcntl.h>
+#include <limits.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.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__ || __FreeBSD__
+#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 ULONG_MAX == 0xffffffff
+#define NATIVE_ELF_ARCH Elf32
+#elif ULONG_MAX == 0xffffffffffffffff
+#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
new file mode 100644
index 0000000000..b1bb67a882
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/dwarf/elf_reader.h
@@ -0,0 +1,166 @@
+// 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"
+#include "common/using_std_string.h"
+
+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
new file mode 100644
index 0000000000..ee198fc5d2
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/dwarf/functioninfo.cc
@@ -0,0 +1,234 @@
+// 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;
+ case DW_AT_ranges:
+ current_function_info_->ranges = data;
+ 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
new file mode 100644
index 0000000000..9efae6d4ee
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/dwarf/functioninfo.h
@@ -0,0 +1,190 @@
+// 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;
+ // Ranges offset
+ uint64 ranges;
+};
+
+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
new file mode 100644
index 0000000000..0ff72abcfc
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/dwarf/line_state_machine.h
@@ -0,0 +1,61 @@
+// 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/types.h b/toolkit/crashreporter/google-breakpad/src/common/dwarf/types.h
new file mode 100644
index 0000000000..59dda31600
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/dwarf/types.h
@@ -0,0 +1,51 @@
+// 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
new file mode 100644
index 0000000000..bd298a2f79
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/dwarf_cfi_to_module.cc
@@ -0,0 +1,295 @@
+// -*- 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 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
new file mode 100644
index 0000000000..a5302e15eb
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/dwarf_cfi_to_module.h
@@ -0,0 +1,202 @@
+// -*- 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 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 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
new file mode 100644
index 0000000000..807d1b20c3
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/dwarf_cfi_to_module_unittest.cc
@@ -0,0 +1,306 @@
+// 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
new file mode 100644
index 0000000000..56399c3a0b
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/dwarf_cu_to_module.cc
@@ -0,0 +1,1243 @@
+// 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>
+#include <inttypes.h>
+#include <stdint.h>
+#include <stdio.h>
+
+#include <algorithm>
+#include <numeric>
+#include <utility>
+
+#include "common/dwarf_line_to_module.h"
+#include "common/unordered.h"
+
+namespace google_breakpad {
+
+using std::accumulate;
+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,
+ RangesHandler *ranges_handler_arg)
+ : file_context(file_context_arg),
+ reporter(reporter_arg),
+ ranges_handler(ranges_handler_arg),
+ language(Language::CPlusPlus),
+ low_pc(0),
+ high_pc(0),
+ ranges(0) {}
+
+ ~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;
+
+ // For reading ranges from the .debug_ranges section
+ RangesHandler *ranges_handler;
+
+ // The source language of this compilation unit.
+ const Language *language;
+
+ // Addresses covered by this CU. If high_pc_ is non-zero then the CU covers
+ // low_pc to high_pc, otherwise ranges is non-zero and low_pc represents
+ // the base address of the ranges covered by the CU.
+ uint64 low_pc;
+ uint64 high_pc;
+ uint64 ranges;
+
+ // 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;
+
+ // Keep a list of forward references from DW_AT_abstract_origin and
+ // DW_AT_specification attributes so names can be fixed up.
+ std::map<uint64_t, Module::Function *> forward_ref_die_to_func;
+};
+
+// 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),
+ forward_ref_die_offset_(0) { }
+
+ // 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 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_;
+
+ // If this DIE has a DW_AT_specification or DW_AT_abstract_origin and it is a
+ // forward reference, no Specification will be available. Track the reference
+ // to be fixed up when the DIE is parsed.
+ uint64_t forward_ref_die_offset_;
+
+ // 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_;
+
+ // The non-demangled value of the DW_AT_MIPS_linkage_name attribute,
+ // it its content count not be demangled.
+ string raw_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 if (data > offset_) {
+ forward_ref_die_offset_ = data;
+ } else {
+ 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:
+ case dwarf2reader::DW_AT_linkage_name: {
+ string demangled;
+ Language::DemangleResult result =
+ cu_context_->language->DemangleName(data, &demangled);
+ switch (result) {
+ case Language::kDemangleSuccess:
+ demangled_name_ = AddStringToPool(demangled);
+ break;
+
+ case Language::kDemangleFailure:
+ cu_context_->reporter->DemangleError(data);
+ // fallthrough
+ case Language::kDontDemangle:
+ demangled_name_.clear();
+ raw_name_ = AddStringToPool(data);
+ break;
+ }
+ 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;
+ else if (!raw_name_.empty())
+ unqualified_name = &raw_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),
+ ranges_(0), 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.
+ uint64 ranges_; // DW_AT_ranges
+ 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;
+ case dwarf2reader::DW_AT_ranges:
+ ranges_ = 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 if (data > offset_) {
+ forward_ref_die_offset_ = data;
+ } 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;
+}
+
+static bool IsEmptyRange(const vector<Module::Range>& ranges) {
+ uint64 size = accumulate(ranges.cbegin(), ranges.cend(), 0,
+ [](uint64 total, Module::Range entry) {
+ return total + entry.size;
+ }
+ );
+
+ return size == 0;
+}
+
+void DwarfCUToModule::FuncHandler::Finish() {
+ vector<Module::Range> ranges;
+
+ // Check if this DIE was one of the forward references that was not able
+ // to be processed, and fix up the name of the appropriate Module::Function.
+ // "name_" will have already been fixed up in EndAttributes().
+ if (!name_.empty()) {
+ auto iter = cu_context_->forward_ref_die_to_func.find(offset_);
+ if (iter != cu_context_->forward_ref_die_to_func.end())
+ iter->second->name = name_;
+ }
+
+ if (!ranges_) {
+ // Make high_pc_ an address, if it isn't already.
+ if (high_pc_form_ != dwarf2reader::DW_FORM_addr &&
+ high_pc_form_ != dwarf2reader::DW_FORM_GNU_addr_index) {
+ high_pc_ += low_pc_;
+ }
+
+ Module::Range range(low_pc_, high_pc_ - low_pc_);
+ ranges.push_back(range);
+ } else {
+ RangesHandler *ranges_handler = cu_context_->ranges_handler;
+
+ if (ranges_handler) {
+ if (!ranges_handler->ReadRanges(ranges_, cu_context_->low_pc, &ranges)) {
+ ranges.clear();
+ cu_context_->reporter->MalformedRangeList(ranges_);
+ }
+ } else {
+ cu_context_->reporter->MissingRanges();
+ }
+ }
+
+ // Did we collect the information we need? Not all DWARF function
+ // entries are non-empty (for example, inlined functions that were never
+ // used), but all the ones we're interested in cover a non-empty range of
+ // bytes.
+ if (!IsEmptyRange(ranges)) {
+ low_pc_ = ranges.front().address;
+
+ // Malformed DWARF may omit the name, but all Module::Functions must
+ // have names.
+ string name;
+ if (!name_.empty()) {
+ name = name_;
+ } else {
+ // If we have a forward reference to a DW_AT_specification or
+ // DW_AT_abstract_origin, then don't warn, the name will be fixed up
+ // later
+ if (forward_ref_die_offset_ == 0)
+ 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->ranges = ranges;
+ 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());
+ if (forward_ref_die_offset_ != 0) {
+ auto iter =
+ cu_context_->forward_ref_die_to_func.find(forward_ref_die_offset_);
+ if (iter == cu_context_->forward_ref_die_to_func.end()) {
+ cu_context_->reporter->UnknownSpecification(offset_,
+ forward_ref_die_offset_);
+ } else {
+ iter->second = cu_context_->functions.back();
+ }
+ }
+ }
+ } 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 was not"
+ " marked as a declaration\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 was not"
+ " marked as an inline\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",
+ IsEmptyRange(function.ranges) ? " (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) {
+ CUHeading();
+ fprintf(stderr, "%s: warning: failed to demangle %s\n",
+ filename_.c_str(), input.c_str());
+}
+
+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);
+}
+
+void DwarfCUToModule::WarningReporter::MalformedRangeList(uint64 offset) {
+ CUHeading();
+ fprintf(stderr, "%s: warning: the range list at offset 0x%llx falls out of "
+ "the .debug_ranges section.\n",
+ filename_.c_str(), offset);
+}
+
+void DwarfCUToModule::WarningReporter::MissingRanges() {
+ CUHeading();
+ fprintf(stderr, "%s: warning: A DW_AT_ranges attribute was encountered but "
+ "the .debug_ranges section is missing.\n", filename_.c_str());
+}
+
+DwarfCUToModule::DwarfCUToModule(FileContext *file_context,
+ LineToModuleHandler *line_reader,
+ RangesHandler *ranges_handler,
+ WarningReporter *reporter)
+ : line_reader_(line_reader),
+ cu_context_(new CUContext(file_context, reporter, ranges_handler)),
+ 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;
+ case dwarf2reader::DW_AT_low_pc:
+ cu_context_->low_pc = data;
+ break;
+ case dwarf2reader::DW_AT_high_pc:
+ cu_context_->high_pc = data;
+ break;
+ case dwarf2reader::DW_AT_ranges:
+ cu_context_->ranges = 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:
+ case dwarf2reader::DW_TAG_module:
+ 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;
+
+ case dwarf2reader::DW_LANG_Swift:
+ cu_context_->language = Language::Swift;
+ break;
+
+ case dwarf2reader::DW_LANG_Rust:
+ cu_context_->language = Language::Rust;
+ 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 {
+class FunctionRange {
+ public:
+ FunctionRange(const Module::Range &range, Module::Function *function) :
+ address(range.address), size(range.size), function(function) { }
+
+ void AddLine(Module::Line &line) {
+ function->lines.push_back(line);
+ }
+
+ Module::Address address;
+ Module::Address size;
+ Module::Function *function;
+};
+
+// Fills an array of ranges with pointers to the functions which owns
+// them. The array is sorted in ascending order and the ranges are non
+// empty and non-overlapping.
+
+static void FillSortedFunctionRanges(vector<FunctionRange> &dest_ranges,
+ vector<Module::Function *> *functions) {
+ for (vector<Module::Function *>::const_iterator func_it = functions->cbegin();
+ func_it != functions->cend();
+ func_it++)
+ {
+ Module::Function *func = *func_it;
+ vector<Module::Range> &ranges = func->ranges;
+ for (vector<Module::Range>::const_iterator ranges_it = ranges.cbegin();
+ ranges_it != ranges.cend();
+ ++ranges_it) {
+ FunctionRange range(*ranges_it, func);
+ if (range.size != 0) {
+ dest_ranges.push_back(range);
+ }
+ }
+ }
+
+ sort(dest_ranges.begin(), dest_ranges.end(),
+ [](const FunctionRange &fr1, const FunctionRange &fr2) {
+ return fr1.address < fr2.address;
+ }
+ );
+}
+
+// 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;
+
+ // Prepare a sorted list of ranges with range-to-function mapping
+ vector<FunctionRange> sorted_ranges;
+ FillSortedFunctionRanges(sorted_ranges, functions);
+
+ // Make a single pass through both the range and line vectors from lower to
+ // higher addresses, populating each range's function lines vector with lines
+ // from our lines_ vector that fall within the range.
+ vector<FunctionRange>::iterator range_it = sorted_ranges.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.
+ FunctionRange *range;
+ const Module::Line *line;
+
+ // Start current at the beginning of the first line or function,
+ // whichever is earlier.
+ if (range_it != sorted_ranges.end() && line_it != lines_.end()) {
+ range = &*range_it;
+ line = &*line_it;
+ current = std::min(range->address, line->address);
+ } else if (line_it != lines_.end()) {
+ range = NULL;
+ line = &*line_it;
+ current = line->address;
+ } else if (range_it != sorted_ranges.end()) {
+ range = &*range_it;
+ line = NULL;
+ current = range->address;
+ } else {
+ return;
+ }
+
+ while (range || 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
+ // range 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 range, 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 range 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 range
+ // iterator. So neither iterator moves.
+
+ // Assert the first invariant (see above).
+ assert(!range || current < range->address || within(*range, 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 (range && current >= range->address) {
+ if (line && current >= line->address) {
+ // Covered by both a line and a range.
+ Module::Address range_left = range->size - (current - range->address);
+ Module::Address line_left = line->size - (current - line->address);
+ // This may overflow, but things work out.
+ next_transition = current + std::min(range_left, line_left);
+ Module::Line l = *line;
+ l.address = current;
+ l.size = next_transition - current;
+ range->AddLine(l);
+ last_line_used = line;
+ } else {
+ // Covered by a range, but no line.
+ if (range->function != last_function_cited) {
+ reporter->UncoveredFunction(*(range->function));
+ last_function_cited = range->function;
+ }
+ if (line && within(*range, line->address))
+ next_transition = line->address;
+ else
+ // If this overflows, we'll catch it below.
+ next_transition = range->address + range->size;
+ }
+ } else {
+ if (line && current >= line->address) {
+ // Covered by a line, but no range.
+ //
+ // 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
+ && !(range
+ && line == last_line_used
+ && range->address - line->address == line->size)) {
+ reporter->UncoveredLine(*line);
+ last_line_cited = line;
+ }
+ if (range && within(*line, range->address))
+ next_transition = range->address;
+ else
+ // If this overflows, we'll catch it below.
+ next_transition = line->address + line->size;
+ } else {
+ // Covered by neither a range nor a line. By the invariant,
+ // both range and line begin after CURRENT. The next transition
+ // is the start of the next range or next line, whichever
+ // is earliest.
+ assert(range || line);
+ if (range && line)
+ next_transition = std::min(range->address, line->address);
+ else if (range)
+ next_transition = range->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 (range_it != sorted_ranges.end()
+ && next_transition >= range_it->address
+ && !within(*range_it, next_transition))
+ range_it++;
+ range = (range_it != sorted_ranges.end()) ? &(*range_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
new file mode 100644
index 0000000000..f73a3c933b
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/dwarf_cu_to_module.h
@@ -0,0 +1,345 @@
+// -*- 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 range lists for
+ // DwarfCUToModule.
+ class RangesHandler {
+ public:
+ RangesHandler() { }
+ virtual ~RangesHandler() { }
+
+ // Called when finishing a function to populate the function's ranges.
+ // The ranges' entries are read starting from offset in the .debug_ranges
+ // section, base_address holds the base PC the range list values are
+ // offsets off. Return false if the rangelist falls out of the
+ // .debug_ranges section.
+ virtual bool ReadRanges(uint64 offset, Module::Address base_address,
+ vector<Module::Range>* ranges) = 0;
+ };
+
+ // 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);
+
+ // 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);
+
+ // The DW_AT_ranges at offset is malformed (truncated or outside of the
+ // .debug_ranges section's bound).
+ virtual void MalformedRangeList(uint64 offset);
+
+ // A DW_AT_ranges attribute was encountered but the no .debug_ranges
+ // section was found.
+ virtual void MissingRanges();
+
+ 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,
+ RangesHandler *ranges_handler,
+ 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
new file mode 100644
index 0000000000..aef69221ce
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/dwarf_cu_to_module_unittest.cc
@@ -0,0 +1,1854 @@
+// 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_METHOD1(DemangleError, void(const string &input));
+ 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_,
+ /* ranges_reader */ nullptr, &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->ranges[0].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) {
+ // Language defaults to C++, so no need to set it here.
+ 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, MangledNameSwift) {
+ // Swift mangled names should pass through untouched.
+ SetLanguage(dwarf2reader::DW_LANG_Swift);
+ PushLine(0x93cd3dfc1aa10097ULL, 0x0397d47a0b4ca0d4ULL, "line-file", 54883661);
+ StartCU();
+ const string kName = "_TFC9swifttest5Shape17simpleDescriptionfS0_FT_Si";
+ DeclarationDIE(&root_handler_, 0xcd3c51b946fb1eeeLL,
+ dwarf2reader::DW_TAG_subprogram, "declaration-name",
+ kName);
+ DefinitionDIE(&root_handler_, dwarf2reader::DW_TAG_subprogram,
+ 0xcd3c51b946fb1eeeLL, "",
+ 0x93cd3dfc1aa10097ULL, 0x0397d47a0b4ca0d4ULL);
+ root_handler_.Finish();
+
+ TestFunctionCount(1);
+ TestFunction(0, kName,
+ 0x93cd3dfc1aa10097ULL, 0x0397d47a0b4ca0d4ULL);
+}
+
+TEST_F(Specifications, MangledNameRust) {
+ SetLanguage(dwarf2reader::DW_LANG_Rust);
+ PushLine(0x93cd3dfc1aa10097ULL, 0x0397d47a0b4ca0d4ULL, "line-file", 54883661);
+
+ StartCU();
+ const string kName = "_ZN14rustc_demangle8demangle17h373defa94bffacdeE";
+ DeclarationDIE(&root_handler_, 0xcd3c51b946fb1eeeLL,
+ dwarf2reader::DW_TAG_subprogram, "declaration-name",
+ kName);
+ DefinitionDIE(&root_handler_, dwarf2reader::DW_TAG_subprogram,
+ 0xcd3c51b946fb1eeeLL, "",
+ 0x93cd3dfc1aa10097ULL, 0x0397d47a0b4ca0d4ULL);
+ root_handler_.Finish();
+
+ TestFunctionCount(1);
+ TestFunction(0,
+#ifndef HAVE_RUST_DEMANGLE
+ // Rust mangled names should pass through untouched if not
+ // using rust-demangle.
+ kName,
+#else
+ // If rust-demangle is available this should be properly
+ // demangled.
+ "rustc_demangle::demangle",
+#endif
+ 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, nullptr, &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, nullptr, &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, nullptr, &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, nullptr, &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, nullptr, &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, nullptr, &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");
+
+ Module::Range range(0x19c45c30770c1eb0ULL, 0x89808a5bdfa0a6a3ULL);
+ function.ranges.push_back(range);
+ 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
new file mode 100644
index 0000000000..258b0b603f
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/dwarf_line_to_module.cc
@@ -0,0 +1,143 @@
+// 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
new file mode 100644
index 0000000000..1fdd4cb716
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/dwarf_line_to_module.h
@@ -0,0 +1,188 @@
+// -*- 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
new file mode 100644
index 0000000000..7c0fcfd35a
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/dwarf_line_to_module_unittest.cc
@@ -0,0 +1,391 @@
+// 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/dwarf_range_list_handler.cc b/toolkit/crashreporter/google-breakpad/src/common/dwarf_range_list_handler.cc
new file mode 100644
index 0000000000..8733df3611
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/dwarf_range_list_handler.cc
@@ -0,0 +1,60 @@
+// Copyright (c) 2018 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: Gabriele Svelto <gsvelto@mozilla.com>
+// <gabriele.svelto@gmail.com>
+
+// dwarf_range_list_handler.cc: Implementation of DwarfRangeListHandler class.
+// See dwarf_range_list_handler.h for details.
+
+#include <algorithm>
+
+#include "common/dwarf_range_list_handler.h"
+
+namespace google_breakpad {
+
+void DwarfRangeListHandler::AddRange(uint64 begin, uint64 end) {
+ Module::Range r(begin + base_address_, end - begin);
+
+ ranges_->push_back(r);
+}
+
+void DwarfRangeListHandler::SetBaseAddress(uint64 base_address) {
+ base_address_ = base_address;
+}
+
+void DwarfRangeListHandler::Finish() {
+ std::sort(ranges_->begin(), ranges_->end(),
+ [](const Module::Range &a, const Module::Range &b) {
+ return a.address < b.address;
+ }
+ );
+}
+
+} // namespace google_breakpad
diff --git a/toolkit/crashreporter/google-breakpad/src/common/dwarf_range_list_handler.h b/toolkit/crashreporter/google-breakpad/src/common/dwarf_range_list_handler.h
new file mode 100644
index 0000000000..bd0996863d
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/dwarf_range_list_handler.h
@@ -0,0 +1,79 @@
+// -*- mode: c++ -*-
+
+// Copyright (c) 2018 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: Gabriele Svelto <gsvelto@mozilla.com>
+// <gabriele.svelto@gmail.com>
+
+// The DwarfRangeListHandler class accepts rangelist data from a DWARF parser
+// and adds it to a google_breakpad::Function or other objects supporting
+// ranges.
+
+#ifndef COMMON_LINUX_DWARF_RANGE_LIST_HANDLER_H
+#define COMMON_LINUX_DWARF_RANGE_LIST_HANDLER_H
+
+#include <vector>
+
+#include "common/module.h"
+#include "common/dwarf/dwarf2reader.h"
+
+namespace google_breakpad {
+
+// A class for producing a vector of google_breakpad::Module::Range
+// instances from a parsed DWARF range list.
+
+class DwarfRangeListHandler: public dwarf2reader::RangeListHandler {
+ public:
+ DwarfRangeListHandler(uint64 base_address, vector<Module::Range> *ranges)
+ : base_address_(base_address), ranges_(ranges) { }
+
+ ~DwarfRangeListHandler() { }
+
+ // Add a range to the list
+ void AddRange(uint64 begin, uint64 end);
+
+ // Record the new base address and use it for the following entries
+ void SetBaseAddress(uint64 base_address);
+
+ // Sort the ranges so that they are in ascending order of starting address
+ void Finish();
+
+ private:
+ // The current PC to add to every entry, this can be overridden by a special
+ // list entry
+ uint64 base_address_;
+
+ // The list of ranges to be populated
+ vector<Module::Range> *ranges_;
+};
+
+} // namespace google_breakpad
+
+#endif // COMMON_LINUX_DWARF_RANGE_LIST_HANDLER_H
diff --git a/toolkit/crashreporter/google-breakpad/src/common/language.cc b/toolkit/crashreporter/google-breakpad/src/common/language.cc
new file mode 100644
index 0000000000..978fb85567
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/language.cc
@@ -0,0 +1,197 @@
+// 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"
+
+#include <stdlib.h>
+
+#if !defined(__ANDROID__)
+#include <cxxabi.h>
+#endif
+
+#if defined(HAVE_RUST_DEMANGLE)
+#include <rust_demangle.h>
+#endif
+
+#include <limits>
+
+namespace {
+
+string MakeQualifiedNameWithSeparator(const string& parent_name,
+ const char* separator,
+ const string& name) {
+ if (parent_name.empty()) {
+ return name;
+ }
+
+ return parent_name + separator + name;
+}
+
+} // namespace
+
+namespace google_breakpad {
+
+// C++ language-specific operations.
+class CPPLanguage: public Language {
+ public:
+ CPPLanguage() {}
+
+ string MakeQualifiedName(const string &parent_name,
+ const string &name) const {
+ return MakeQualifiedNameWithSeparator(parent_name, "::", name);
+ }
+
+ virtual DemangleResult DemangleName(const string& mangled,
+ string* demangled) const {
+#if defined(__ANDROID__)
+ // Android NDK doesn't provide abi::__cxa_demangle.
+ demangled->clear();
+ return kDontDemangle;
+#else
+ int status;
+ char* demangled_c =
+ abi::__cxa_demangle(mangled.c_str(), NULL, NULL, &status);
+
+ DemangleResult result;
+ if (status == 0) {
+ result = kDemangleSuccess;
+ demangled->assign(demangled_c);
+ } else {
+ result = kDemangleFailure;
+ demangled->clear();
+ }
+
+ if (demangled_c) {
+ free(reinterpret_cast<void*>(demangled_c));
+ }
+
+ return result;
+#endif
+ }
+};
+
+CPPLanguage CPPLanguageSingleton;
+
+// Java language-specific operations.
+class JavaLanguage: public Language {
+ public:
+ JavaLanguage() {}
+
+ string MakeQualifiedName(const string &parent_name,
+ const string &name) const {
+ return MakeQualifiedNameWithSeparator(parent_name, ".", name);
+ }
+};
+
+JavaLanguage JavaLanguageSingleton;
+
+// Swift language-specific operations.
+class SwiftLanguage: public Language {
+ public:
+ SwiftLanguage() {}
+
+ string MakeQualifiedName(const string &parent_name,
+ const string &name) const {
+ return MakeQualifiedNameWithSeparator(parent_name, ".", name);
+ }
+
+ virtual DemangleResult DemangleName(const string& mangled,
+ string* demangled) const {
+ // There is no programmatic interface to a Swift demangler. Pass through the
+ // mangled form because it encodes more information than the qualified name
+ // that would have been built by MakeQualifiedName(). The output can be
+ // post-processed by xcrun swift-demangle to transform mangled Swift names
+ // into something more readable.
+ demangled->assign(mangled);
+ return kDemangleSuccess;
+ }
+};
+
+SwiftLanguage SwiftLanguageSingleton;
+
+// Rust language-specific operations.
+class RustLanguage: public Language {
+ public:
+ RustLanguage() {}
+
+ string MakeQualifiedName(const string &parent_name,
+ const string &name) const {
+ return MakeQualifiedNameWithSeparator(parent_name, ".", name);
+ }
+
+ virtual DemangleResult DemangleName(const string& mangled,
+ string* demangled) const {
+ // Rust names use GCC C++ name mangling, but demangling them with
+ // abi_demangle doesn't produce stellar results due to them having
+ // another layer of encoding.
+ // If callers provide rustc-demangle, use that.
+#if defined(HAVE_RUST_DEMANGLE)
+ char* rust_demangled = rust_demangle(mangled.c_str());
+ if (rust_demangled == nullptr) {
+ return kDemangleFailure;
+ }
+ demangled->assign(rust_demangled);
+ free_rust_demangled_name(rust_demangled);
+#else
+ // Otherwise, pass through the mangled name so callers can demangle
+ // after the fact.
+ demangled->assign(mangled);
+#endif
+ return kDemangleSuccess;
+ }
+};
+
+RustLanguage RustLanguageSingleton;
+
+// Assembler language-specific operations.
+class AssemblerLanguage: public Language {
+ public:
+ AssemblerLanguage() {}
+
+ 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::Swift = &SwiftLanguageSingleton;
+const Language * const Language::Rust = &RustLanguageSingleton;
+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
new file mode 100644
index 0000000000..2d2dbcd9e9
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/language.h
@@ -0,0 +1,105 @@
+// -*- 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;
+
+ enum DemangleResult {
+ // Demangling was not performed because it’s not appropriate to attempt.
+ kDontDemangle = -1,
+
+ kDemangleSuccess,
+ kDemangleFailure,
+ };
+
+ // Wraps abi::__cxa_demangle() or similar for languages where appropriate.
+ virtual DemangleResult DemangleName(const string& mangled,
+ string* demangled) const {
+ demangled->clear();
+ return kDontDemangle;
+ }
+
+ // Instances for specific languages.
+ static const Language * const CPlusPlus,
+ * const Java,
+ * const Swift,
+ * const Rust,
+ * const Assembler;
+};
+
+} // namespace google_breakpad
+
+#endif // COMMON_LINUX_LANGUAGE_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/breakpad_getcontext.S b/toolkit/crashreporter/google-breakpad/src/common/linux/breakpad_getcontext.S
new file mode 100644
index 0000000000..fea0109d15
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/linux/breakpad_getcontext.S
@@ -0,0 +1,486 @@
+// 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 when getcontext() is not available in libc.
+
+#include "common/linux/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.
+#include <asm-mips/asm.h>
+#include <asm-mips/regdef.h>
+#if _MIPS_SIM == _ABIO32
+#include <asm-mips/fpregdef.h>
+#endif
+
+// from asm-mips/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/linux/breakpad_getcontext.h b/toolkit/crashreporter/google-breakpad/src/common/linux/breakpad_getcontext.h
new file mode 100644
index 0000000000..1418cde621
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/linux/breakpad_getcontext.h
@@ -0,0 +1,56 @@
+// 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_LINUX_INCLUDE_UCONTEXT_H
+#define GOOGLE_BREAKPAD_COMMON_LINUX_INCLUDE_UCONTEXT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifndef HAVE_GETCONTEXT
+
+#include <signal.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+// Provided by src/common/linux/breakpad_getcontext.S
+int breakpad_getcontext(ucontext_t* ucp);
+
+#define getcontext(x) breakpad_getcontext(x)
+
+#ifdef __cplusplus
+} // extern "C"
+#endif // __cplusplus
+
+#endif // HAVE_GETCONTEXT
+
+#endif // GOOGLE_BREAKPAD_COMMON_LINUX_INCLUDE_UCONTEXT_H
diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/breakpad_getcontext_unittest.cc b/toolkit/crashreporter/google-breakpad/src/common/linux/breakpad_getcontext_unittest.cc
new file mode 100644
index 0000000000..a57bfedf9b
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/linux/breakpad_getcontext_unittest.cc
@@ -0,0 +1,194 @@
+// 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.
+
+// asm/sigcontext.h can't be included with signal.h on glibc or
+// musl, so only compare _libc_fpstate and _fpstate on Android.
+#if defined(__ANDROID__) && defined(__x86_64__)
+#include <asm/sigcontext.h>
+#endif
+
+#include <sys/ucontext.h>
+
+#include <type_traits>
+
+#include "breakpad_googletest_includes.h"
+#include "common/linux/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);
+
+#if defined(__ANDROID__)
+ // 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);
+#endif
+
+ 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(std::remove_pointer<fpregset_t>::type,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/linux/crc32.cc b/toolkit/crashreporter/google-breakpad/src/common/linux/crc32.cc
new file mode 100644
index 0000000000..8df636ce4d
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/linux/crc32.cc
@@ -0,0 +1,70 @@
+// 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
new file mode 100644
index 0000000000..e3d9db92be
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/linux/crc32.h
@@ -0,0 +1,53 @@
+// 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
new file mode 100644
index 0000000000..e398f7b392
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/linux/dump_symbols.cc
@@ -0,0 +1,1218 @@
+// 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 <limits.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/dwarf_range_list_handler.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_allocator.h"
+#include "common/module.h"
+#include "common/path_helper.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::DwarfRangeListHandler;
+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
+
+//
+// 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;
+}
+
+// Find the set of address ranges for all PT_LOAD segments.
+template <typename ElfClass>
+vector<Module::Range> GetPtLoadSegmentRanges(
+ const typename ElfClass::Phdr* program_headers,
+ int nheader) {
+ typedef typename ElfClass::Phdr Phdr;
+ vector<Module::Range> ranges;
+
+ for (int i = 0; i < nheader; ++i) {
+ const Phdr& header = program_headers[i];
+ if (header.p_type == PT_LOAD) {
+ ranges.push_back(Module::Range(header.p_vaddr, header.p_memsz));
+ }
+ }
+ return ranges;
+}
+
+#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 range handler that accepts rangelist data parsed by
+// dwarf2reader::RangeListReader and populates a range vector (typically
+// owned by a function) with the results.
+class DumperRangesHandler : public DwarfCUToModule::RangesHandler {
+ public:
+ DumperRangesHandler(const uint8_t *buffer, uint64 size,
+ dwarf2reader::ByteReader* reader)
+ : buffer_(buffer), size_(size), reader_(reader) { }
+
+ bool ReadRanges(uint64 offset, Module::Address base_address,
+ vector<Module::Range>* ranges) {
+ DwarfRangeListHandler handler(base_address, ranges);
+ dwarf2reader::RangeListReader rangelist_reader(buffer_, size_, reader_,
+ &handler);
+
+ return rangelist_reader.ReadRangeList(offset);
+ }
+
+ private:
+ const uint8_t *buffer_;
+ uint64 size_;
+ dwarf2reader::ByteReader* reader_;
+};
+
+// 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);
+ }
+
+ // Optional .debug_ranges reader
+ scoped_ptr<DumperRangesHandler> ranges_handler;
+ dwarf2reader::SectionMap::const_iterator ranges_entry =
+ file_context.section_map().find(".debug_ranges");
+ if (ranges_entry != file_context.section_map().end()) {
+ const std::pair<const uint8_t *, uint64>& ranges_section =
+ ranges_entry->second;
+ ranges_handler.reset(
+ new DumperRangesHandler(ranges_section.first, ranges_section.second,
+ &byte_reader));
+ }
+
+ // 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,
+ ranges_handler.get(), &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;
+
+ 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);
+
+ // Allow filtering of extraneous debug information in partitioned libraries.
+ // Such libraries contain debug information for all libraries extracted from
+ // the same combined library, implying extensive duplication.
+ vector<Module::Range> address_ranges = GetPtLoadSegmentRanges<ElfClass>(
+ GetOffset<ElfClass, Phdr>(elf_header, elf_header->e_phoff),
+ elf_header->e_phnum);
+ module->SetAddressRanges(address_ranges);
+
+ 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;
+
+ 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", SHT_PROGBITS,
+ sections, names, names_end,
+ elf_header->e_shnum);
+
+ // .debug_info section type is SHT_PROGBITS for mips on pnacl toolchains,
+ // but MIPS_DWARF for regular gnu toolchains, so both need to be checked
+ if (elf_header->e_machine == EM_MIPS && !dwarf_section) {
+ dwarf_section =
+ FindElfSectionByName<ElfClass>(".debug_info", SHT_MIPS_DWARF,
+ 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", SHT_PROGBITS,
+ sections, names, names_end,
+ elf_header->e_shnum);
+
+ // .debug_frame section type is SHT_PROGBITS for mips on pnacl toolchains,
+ // but MIPS_DWARF for regular gnu toolchains, so both need to be checked
+ if (elf_header->e_machine == EM_MIPS && !dwarf_cfi_section) {
+ dwarf_cfi_section =
+ FindElfSectionByName<ElfClass>(".debug_frame", SHT_MIPS_DWARF,
+ 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;
+ }
+}
+
+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,
+ const string& obj_os,
+ 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;
+ }
+
+ char name_buf[NAME_MAX] = {};
+ std::string name = google_breakpad::ElfFileSoNameFromMappedFile(
+ elf_header, name_buf, sizeof(name_buf))
+ ? name_buf
+ : google_breakpad::BaseName(obj_filename);
+
+ // 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, obj_os, architecture, id, code_id));
+
+ return true;
+}
+
+template<typename ElfClass>
+bool ReadSymbolDataElfClass(const typename ElfClass::Ehdr* elf_header,
+ const string& obj_filename,
+ const string& obj_os,
+ 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, obj_os,
+ 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 string& obj_os,
+ 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, obj_os,
+ debug_dirs, options, module);
+ }
+ if (elfclass == ELFCLASS64) {
+ return ReadSymbolDataElfClass<ElfClass64>(
+ reinterpret_cast<const Elf64_Ehdr*>(obj_file), obj_filename, obj_os,
+ debug_dirs, options, module);
+ }
+
+ return false;
+}
+
+bool WriteSymbolFile(const string &load_path,
+ const string &obj_file,
+ const string &obj_os,
+ const std::vector<string>& debug_dirs,
+ const DumpOptions& options,
+ std::ostream &sym_stream) {
+ Module* module;
+ if (!ReadSymbolData(load_path, obj_file, obj_os, 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& load_path,
+ const string& obj_file,
+ const string& obj_os,
+ std::ostream &sym_stream) {
+ MmapWrapper map_wrapper;
+ void* elf_header = NULL;
+ if (!LoadELF(load_path, &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, obj_os,
+ 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, obj_os,
+ 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& load_path,
+ const string& obj_file,
+ const string& obj_os,
+ const std::vector<string>& debug_dirs,
+ const DumpOptions& options,
+ Module** module) {
+ MmapWrapper map_wrapper;
+ void* elf_header = NULL;
+ if (!LoadELF(load_path, &map_wrapper, &elf_header))
+ return false;
+
+ return ReadSymbolDataInternal(reinterpret_cast<uint8_t*>(elf_header),
+ obj_file, obj_os, 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
new file mode 100644
index 0000000000..eaddd8b2ec
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/linux/dump_symbols.h
@@ -0,0 +1,93 @@
+// -*- 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 &load_path,
+ const string &obj_file,
+ const string &obj_os,
+ 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. |obj_file| becomes the MODULE file name and |obj_os|
+// becomes the MODULE operating system.
+bool WriteSymbolFileHeader(const string& load_path,
+ const string& obj_file,
+ const string& obj_os,
+ 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& load_path,
+ const string& obj_file,
+ const string& obj_os,
+ 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
new file mode 100644
index 0000000000..54c2109625
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/linux/dump_symbols_unittest.cc
@@ -0,0 +1,208 @@
+// 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 string& obj_os,
+ 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_SUITE(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",
+ "Linux",
+ 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",
+ "Linux",
+ 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",
+ "Linux",
+ 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
new file mode 100644
index 0000000000..3f1d184817
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/linux/eintr_wrapper.h
@@ -0,0 +1,58 @@
+// 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
new file mode 100644
index 0000000000..0e7db7b1fa
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/linux/elf_core_dump.cc
@@ -0,0 +1,179 @@
+// 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
new file mode 100644
index 0000000000..6e153745db
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/linux/elf_core_dump.h
@@ -0,0 +1,149 @@
+// 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 <limits.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 native word size.
+ typedef ElfW(Ehdr) Ehdr;
+ typedef ElfW(Nhdr) Nhdr;
+ typedef ElfW(Phdr) Phdr;
+ typedef ElfW(Word) Word;
+ typedef ElfW(Addr) Addr;
+#if ULONG_MAX == 0xffffffff
+ static const int kClass = ELFCLASS32;
+#elif ULONG_MAX == 0xffffffffffffffff
+ static const int kClass = ELFCLASS64;
+#else
+#error "Unsupported word size 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
new file mode 100644
index 0000000000..2399c12fda
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/linux/elf_core_dump_unittest.cc
@@ -0,0 +1,265 @@
+// 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();
+ }
+
+#if defined(THREAD_SANITIZER)
+ for (std::set<pid_t>::const_iterator expected = expected_thread_ids.begin();
+ expected != expected_thread_ids.end();
+ ++expected) {
+ EXPECT_NE(actual_thread_ids.find(*expected), actual_thread_ids.end());
+ }
+ EXPECT_GE(num_nt_prstatus, kNumOfThreads);
+#else
+ EXPECT_EQ(actual_thread_ids, expected_thread_ids);
+ EXPECT_EQ(num_nt_prstatus, kNumOfThreads);
+#endif
+ EXPECT_EQ(1U, num_nt_prpsinfo);
+#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
new file mode 100644
index 0000000000..0a3dfedb57
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/linux/elf_gnu_compat.h
@@ -0,0 +1,51 @@
+// -*- 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
+
+// Newer Linux systems offer this.
+#ifndef NT_SIGINFO
+#define NT_SIGINFO 0x53494749
+#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
new file mode 100644
index 0000000000..562875e11b
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/linux/elf_symbols_to_module.cc
@@ -0,0 +1,178 @@
+// -*- 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
new file mode 100644
index 0000000000..2e7c097151
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/linux/elf_symbols_to_module.h
@@ -0,0 +1,58 @@
+// -*- 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
new file mode 100644
index 0000000000..8984449ab6
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/linux/elf_symbols_to_module_unittest.cc
@@ -0,0 +1,370 @@
+// 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
new file mode 100644
index 0000000000..e56b37a9f5
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/linux/elfutils-inl.h
@@ -0,0 +1,74 @@
+// 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
new file mode 100644
index 0000000000..e2e16e6dfd
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/linux/elfutils.cc
@@ -0,0 +1,241 @@
+// 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"
+
+#if defined(__FreeBSD__)
+# define ElfW(type) Elf_##type
+#endif
+
+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,
+ wasteful_vector<ElfSegment> *segments) {
+ typedef typename ElfClass::Ehdr Ehdr;
+ typedef typename ElfClass::Phdr Phdr;
+
+ assert(elf_base);
+ assert(segments);
+
+ 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) {
+ ElfSegment seg = {};
+ seg.start = elf_base + phdrs[i].p_offset;
+ seg.size = phdrs[i].p_filesz;
+ segments->push_back(seg);
+ }
+ }
+}
+
+} // 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) {
+ 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);
+ 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 FindElfSegments(const void* elf_mapped_base,
+ uint32_t segment_type,
+ wasteful_vector<ElfSegment>* segments) {
+ assert(elf_mapped_base);
+ assert(segments);
+
+ if (!IsValidElf(elf_mapped_base))
+ return false;
+
+ int cls = ElfClass(elf_mapped_base);
+ const char* elf_base =
+ static_cast<const char*>(elf_mapped_base);
+
+ if (cls == ELFCLASS32) {
+ FindElfClassSegment<ElfClass32>(elf_base, segment_type, segments);
+ return true;
+ } else if (cls == ELFCLASS64) {
+ FindElfClassSegment<ElfClass64>(elf_base, segment_type, segments);
+ return true;
+ }
+
+ return false;
+}
+
+template <typename ElfClass>
+bool FindElfSoNameFromDynamicSection(const void* section_start,
+ size_t section_size,
+ const void* dynstr_start,
+ size_t dynstr_size,
+ char* soname,
+ size_t soname_size) {
+ typedef typename ElfClass::Dyn Dyn;
+
+ auto* dynamic = static_cast<const Dyn*>(section_start);
+ size_t dcount = section_size / sizeof(Dyn);
+ for (const Dyn* dyn = dynamic; dyn < dynamic + dcount; ++dyn) {
+ if (dyn->d_tag == DT_SONAME) {
+ const char* dynstr = static_cast<const char*>(dynstr_start);
+ if (dyn->d_un.d_val >= dynstr_size) {
+ // Beyond the end of the dynstr section
+ return false;
+ }
+ const char* str = dynstr + dyn->d_un.d_val;
+ const size_t maxsize = dynstr_size - dyn->d_un.d_val;
+ my_strlcpy(soname, str, maxsize < soname_size ? maxsize : soname_size);
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool ElfFileSoNameFromMappedFile(const void* elf_base,
+ char* soname,
+ size_t soname_size) {
+ if (!IsValidElf(elf_base)) {
+ // Not ELF
+ return false;
+ }
+
+ const void* segment_start;
+ size_t segment_size;
+ if (!FindElfSection(elf_base, ".dynamic", SHT_DYNAMIC, &segment_start,
+ &segment_size)) {
+ // No dynamic section
+ return false;
+ }
+
+ const void* dynstr_start;
+ size_t dynstr_size;
+ if (!FindElfSection(elf_base, ".dynstr", SHT_STRTAB, &dynstr_start,
+ &dynstr_size)) {
+ // No dynstr section
+ return false;
+ }
+
+ int cls = ElfClass(elf_base);
+ return cls == ELFCLASS32 ? FindElfSoNameFromDynamicSection<ElfClass32>(
+ segment_start, segment_size, dynstr_start,
+ dynstr_size, soname, soname_size)
+ : FindElfSoNameFromDynamicSection<ElfClass64>(
+ segment_start, segment_size, dynstr_start,
+ dynstr_size, soname, soname_size);
+}
+
+} // 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
new file mode 100644
index 0000000000..aefb6cf5f8
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/linux/elfutils.h
@@ -0,0 +1,135 @@
+// 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>
+
+#include "common/memory_allocator.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_Dyn Dyn;
+ 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_Dyn Dyn;
+ 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.
+bool FindElfSection(const void *elf_mapped_base,
+ const char *section_name,
+ uint32_t section_type,
+ const void **section_start,
+ size_t *section_size);
+
+// 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);
+
+struct ElfSegment {
+ const void* start;
+ size_t size;
+};
+
+// Attempt to find all segments of type |segment_type| in the ELF
+// binary data at |elf_mapped_base|. On success, returns true and fills
+// |*segments| with a list of segments of the given type.
+bool FindElfSegments(const void* elf_mapped_base,
+ uint32_t segment_type,
+ wasteful_vector<ElfSegment>* segments);
+
+// 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);
+
+// Read the value of DT_SONAME from the elf file mapped at |elf_base|. Returns
+// true and fills |soname| with the result if found.
+bool ElfFileSoNameFromMappedFile(const void* elf_base,
+ char* soname,
+ size_t soname_size);
+
+} // 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
new file mode 100644
index 0000000000..701a4f070f
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/linux/file_id.cc
@@ -0,0 +1,200 @@
+// 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.
+
+static bool ElfClassBuildIDNoteIdentifier(const void *section, size_t length,
+ wasteful_vector<uint8_t>& identifier) {
+ static_assert(sizeof(ElfClass32::Nhdr) == sizeof(ElfClass64::Nhdr),
+ "Elf32_Nhdr and Elf64_Nhdr should be the same");
+ typedef typename ElfClass32::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) {
+ PageAllocator allocator;
+ // lld normally creates 2 PT_NOTEs, gold normally creates 1.
+ auto_wasteful_vector<ElfSegment, 2> segs(&allocator);
+ if (FindElfSegments(elf_mapped_base, PT_NOTE, &segs)) {
+ for (ElfSegment& seg : segs) {
+ if (ElfClassBuildIDNoteIdentifier(seg.start, seg.size, identifier)) {
+ return true;
+ }
+ }
+ }
+
+ void* note_section;
+ size_t note_size;
+ if (FindElfSection(elf_mapped_base, ".note.gnu.build-id", SHT_NOTE,
+ (const void**)&note_section, &note_size)) {
+ return ElfClassBuildIDNoteIdentifier(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) {
+ void* text_section;
+ size_t text_size;
+ if (!FindElfSection(elf_mapped_base, ".text", SHT_PROGBITS,
+ (const void**)&text_section, &text_size) ||
+ text_size == 0) {
+ return false;
+ }
+
+ // Only provide |kMDGUIDSize| bytes to keep identifiers produced by this
+ // function backwards-compatible.
+ identifier.resize(kMDGUIDSize);
+ 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
new file mode 100644
index 0000000000..4aff021ded
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/linux/file_id.h
@@ -0,0 +1,88 @@
+// 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_allocator.h"
+#include "common/using_std_string.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 string ConvertIdentifierToUUIDString(
+ const wasteful_vector<uint8_t>& identifier);
+
+ // Convert the entire |identifier| data to a hex string.
+ static string ConvertIdentifierToString(
+ const wasteful_vector<uint8_t>& identifier);
+
+ private:
+ // Storage for the path specified
+ 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
new file mode 100644
index 0000000000..f4f9ac45ce
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/linux/file_id_unittest.cc
@@ -0,0 +1,372 @@
+// 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_SUITE(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);
+}
+
+TYPED_TEST(FileIDTest, BuildIDMultiplePH) {
+ 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 notes1(kLittleEndian);
+ notes1.AddNote(0, "Linux",
+ reinterpret_cast<const uint8_t *>("\0x42\0x02\0\0"), 4);
+ Notes notes2(kLittleEndian);
+ notes2.AddNote(NT_GNU_BUILD_ID, "GNU", kExpectedIdentifierBytes,
+ sizeof(kExpectedIdentifierBytes));
+ int note1_idx = elf.AddSection(".note1", notes1, SHT_NOTE);
+ int note2_idx = elf.AddSection(".note2", notes2, SHT_NOTE);
+ elf.AddSegment(note1_idx, note1_idx, PT_NOTE);
+ elf.AddSegment(note2_idx, note2_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
new file mode 100644
index 0000000000..a0d940b614
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/linux/google_crashdump_uploader.cc
@@ -0,0 +1,207 @@
+// 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_;
+ long status_code;
+ bool success = http_layer_->SendRequest(crash_server_,
+ parameters_,
+ &status_code,
+ http_response_header,
+ http_response_body);
+ if (http_status_code) {
+ *http_status_code = status_code;
+ }
+ return success;
+}
+}
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
new file mode 100644
index 0000000000..a2d0575b5e
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/linux/google_crashdump_uploader.h
@@ -0,0 +1,107 @@
+// 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
new file mode 100644
index 0000000000..3d6612e821
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/linux/google_crashdump_uploader_test.cc
@@ -0,0 +1,170 @@
+// 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,
+ long* 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
new file mode 100644
index 0000000000..03e3d781fb
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/linux/guid_creator.cc
@@ -0,0 +1,189 @@
+// 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.
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "common/linux/eintr_wrapper.h"
+#include "common/linux/guid_creator.h"
+
+#include <assert.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <time.h>
+#include <unistd.h>
+
+#if defined(HAVE_SYS_RANDOM_H)
+#include <sys/random.h>
+#endif
+
+//
+// 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) {
+#if defined(HAVE_ARC4RANDOM) // Android, BSD, ...
+ CreateGuidFromArc4Random(guid);
+#else // Linux
+ bool success = false;
+
+#if defined(HAVE_SYS_RANDOM_H) && defined(HAVE_GETRANDOM)
+ success = CreateGUIDFromGetrandom(guid);
+#endif // HAVE_SYS_RANDOM_H && HAVE_GETRANDOM
+ if (!success) {
+ success = CreateGUIDFromDevUrandom(guid);
+ }
+
+ if (!success) {
+ CreateGUIDFromRand(guid);
+ success = true;
+ }
+#endif
+
+ // Put in the version according to RFC 4122.
+ guid->data3 &= 0x0fff;
+ guid->data3 |= 0x4000;
+
+ // Put in the variant according to RFC 4122.
+ guid->data4[0] &= 0x3f;
+ guid->data4[0] |= 0x80;
+
+ return true;
+ }
+
+ private:
+#ifdef HAVE_ARC4RANDOM
+ static void CreateGuidFromArc4Random(GUID *guid) {
+ char *buf = reinterpret_cast<char *>(guid);
+
+ for (size_t i = 0; i < sizeof(GUID); i += sizeof(uint32_t)) {
+ uint32_t random_data = arc4random();
+
+ memcpy(buf + i, &random_data, sizeof(uint32_t));
+ }
+ }
+#else
+ static void InitOnce() {
+ pthread_once(&once_control, &InitOnceImpl);
+ }
+
+ static void InitOnceImpl() {
+ // time(NULL) is a very poor seed, so lacking anything better mix an
+ // address into it. We drop the four rightmost bits as they're likely to
+ // be 0 on almost all architectures.
+ srand(time(NULL) | ((uintptr_t)&once_control >> 4));
+ }
+
+ static pthread_once_t once_control;
+
+#if defined(HAVE_SYS_RANDOM_H) && defined(HAVE_GETRANDOM)
+ static bool CreateGUIDFromGetrandom(GUID *guid) {
+ char *buf = reinterpret_cast<char *>(guid);
+ int read_bytes = getrandom(buf, sizeof(GUID), GRND_NONBLOCK);
+
+ return (read_bytes == static_cast<int>(sizeof(GUID)));
+ }
+#endif // HAVE_SYS_RANDOM_H && HAVE_GETRANDOM
+
+ // Populate the GUID using random bytes read from /dev/urandom, returns false
+ // if the GUID wasn't fully populated with random data.
+ static bool CreateGUIDFromDevUrandom(GUID *guid) {
+ char *buf = reinterpret_cast<char *>(guid);
+ int fd = open("/dev/urandom", O_RDONLY | O_CLOEXEC);
+
+ if (fd == -1) {
+ return false;
+ }
+
+ ssize_t read_bytes = HANDLE_EINTR(read(fd, buf, sizeof(GUID)));
+ close(fd);
+
+ return (read_bytes == static_cast<ssize_t>(sizeof(GUID)));
+ }
+
+ // Populate the GUID using a stream of random bytes obtained from rand().
+ static void CreateGUIDFromRand(GUID *guid) {
+ char *buf = reinterpret_cast<char *>(guid);
+
+ InitOnce();
+
+ for (size_t i = 0; i < sizeof(GUID); i++) {
+ buf[i] = rand();
+ }
+ }
+#endif
+};
+
+#ifndef HAVE_ARC4RANDOM
+pthread_once_t GUIDGenerator::once_control = PTHREAD_ONCE_INIT;
+#endif
+
+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
new file mode 100644
index 0000000000..c86d856c4d
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/linux/guid_creator.h
@@ -0,0 +1,48 @@
+// 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
new file mode 100644
index 0000000000..0a1019dd0d
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/linux/http_upload.cc
@@ -0,0 +1,210 @@
+// 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 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;
+
+ // 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");
+ (*curl_formadd)(&formpost, &lastptr, CURLFORM_COPYNAME, "extra",
+ CURLFORM_BUFFER, "extra.json", CURLFORM_BUFFERPTR,
+ parameters.c_str(), CURLFORM_BUFFERLENGTH,
+ parameters.length(), CURLFORM_CONTENTTYPE, "application/json",
+ CURLFORM_END);
+
+ // Add form files.
+ map<string, string>::const_iterator iter = files.begin();
+ 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");
+}
+
+} // 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
new file mode 100644
index 0000000000..95dedebc3b
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/linux/http_upload.h
@@ -0,0 +1,84 @@
+// 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
+// parameters encoded in a JSON string, 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">.
+ // Parameters are specified as a JSON-encoded string in |parameters|.
+ // 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 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 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
new file mode 100644
index 0000000000..efd274c20c
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/linux/ignore_ret.h
@@ -0,0 +1,40 @@
+// 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
new file mode 100644
index 0000000000..e96c203852
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/linux/libcurl_wrapper.cc
@@ -0,0 +1,338 @@
+// 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),
+ curl_lib_(nullptr),
+ last_curl_error_(""),
+ curl_(nullptr),
+ formpost_(nullptr),
+ lastptr_(nullptr),
+ headerlist_(nullptr) {}
+
+LibcurlWrapper::~LibcurlWrapper() {
+ if (init_ok_) {
+ (*easy_cleanup_)(curl_);
+ dlclose(curl_lib_);
+ }
+}
+
+bool LibcurlWrapper::SetProxy(const string& proxy_host,
+ const string& proxy_userpwd) {
+ if (!CheckInit()) 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 (!CheckInit()) 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,
+ long* http_status_code,
+ string* http_header_data,
+ string* http_response_data) {
+ if (!CheckInit()) return false;
+
+ 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_);
+
+ return SendRequestInner(url, http_status_code, http_header_data,
+ http_response_data);
+}
+
+bool LibcurlWrapper::SendGetRequest(const string& url,
+ long* http_status_code,
+ string* http_header_data,
+ string* http_response_data) {
+ if (!CheckInit()) return false;
+
+ (*easy_setopt_)(curl_, CURLOPT_HTTPGET, 1L);
+
+ return SendRequestInner(url, http_status_code, http_header_data,
+ http_response_data);
+}
+
+bool LibcurlWrapper::SendPutRequest(const string& url,
+ const string& path,
+ long* http_status_code,
+ string* http_header_data,
+ string* http_response_data) {
+ if (!CheckInit()) return false;
+
+ FILE* file = fopen(path.c_str(), "rb");
+ (*easy_setopt_)(curl_, CURLOPT_UPLOAD, 1L);
+ (*easy_setopt_)(curl_, CURLOPT_PUT, 1L);
+ (*easy_setopt_)(curl_, CURLOPT_READDATA, file);
+
+ bool success = SendRequestInner(url, http_status_code, http_header_data,
+ http_response_data);
+
+ fclose(file);
+ return success;
+}
+
+bool LibcurlWrapper::SendSimplePostRequest(const string& url,
+ const string& body,
+ const string& content_type,
+ long* http_status_code,
+ string* http_header_data,
+ string* http_response_data) {
+ if (!CheckInit()) return false;
+
+ (*easy_setopt_)(curl_, CURLOPT_POSTFIELDSIZE, body.size());
+ (*easy_setopt_)(curl_, CURLOPT_COPYPOSTFIELDS, body.c_str());
+
+ if (!content_type.empty()) {
+ string content_type_header = "Content-Type: " + content_type;
+ headerlist_ = (*slist_append_)(
+ headerlist_,
+ content_type_header.c_str());
+ }
+
+ return SendRequestInner(url, http_status_code, http_header_data,
+ http_response_data);
+}
+
+bool LibcurlWrapper::Init() {
+ // First check to see if libcurl was statically linked:
+ curl_lib_ = dlopen(nullptr, RTLD_NOW);
+ if (curl_lib_ &&
+ (!dlsym(curl_lib_, "curl_easy_init") ||
+ !dlsym(curl_lib_, "curl_easy_setopt"))) {
+ // Not statically linked, try again below.
+ dlerror(); // Clear dlerror before attempting to open libraries.
+ dlclose(curl_lib_);
+ curl_lib_ = nullptr;
+ }
+ if (!curl_lib_) {
+ 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 false;
+ }
+
+ if (!SetFunctionPointers()) {
+ std::cout << "Could not find function pointers";
+ return false;
+ }
+
+ curl_ = (*easy_init_)();
+
+ last_curl_error_ = "No Error";
+
+ if (!curl_) {
+ dlclose(curl_lib_);
+ std::cout << "Curl initialization failed";
+ return false;
+ }
+
+ init_ok_ = true;
+ 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(easy_reset_,
+ "curl_easy_reset",
+ void(*)(CURL*));
+
+ 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;
+}
+
+bool LibcurlWrapper::SendRequestInner(const string& url,
+ long* http_status_code,
+ string* http_header_data,
+ string* http_response_data) {
+ string url_copy(url);
+ (*easy_setopt_)(curl_, CURLOPT_URL, url_copy.c_str());
+
+ // Disable 100-continue header.
+ char buf[] = "Expect:";
+ headerlist_ = (*slist_append_)(headerlist_, buf);
+ (*easy_setopt_)(curl_, CURLOPT_HTTPHEADER, headerlist_);
+
+ if (http_response_data != nullptr) {
+ 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 != nullptr) {
+ 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 != nullptr) {
+ (*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
+
+ Reset();
+
+ return err_code == CURLE_OK;
+}
+
+void LibcurlWrapper::Reset() {
+ if (headerlist_ != nullptr) {
+ (*slist_free_all_)(headerlist_);
+ headerlist_ = nullptr;
+ }
+
+ if (formpost_ != nullptr) {
+ (*formfree_)(formpost_);
+ formpost_ = nullptr;
+ }
+
+ (*easy_reset_)(curl_);
+}
+
+bool LibcurlWrapper::CheckInit() {
+ if (!init_ok_) {
+ std::cout << "LibcurlWrapper: You must call Init(), and have it return "
+ "'true' before invoking any other methods.\n";
+ return false;
+ }
+
+ return true;
+}
+
+} // namespace google_breakpad
diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/libcurl_wrapper.h b/toolkit/crashreporter/google-breakpad/src/common/linux/libcurl_wrapper.h
new file mode 100644
index 0000000000..77aa6cbb72
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/linux/libcurl_wrapper.h
@@ -0,0 +1,119 @@
+// 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,
+ long* http_status_code,
+ string* http_header_data,
+ string* http_response_data);
+ bool SendGetRequest(const string& url,
+ long* http_status_code,
+ string* http_header_data,
+ string* http_response_data);
+ bool SendPutRequest(const string& url,
+ const string& path,
+ long* http_status_code,
+ string* http_header_data,
+ string* http_response_data);
+ bool SendSimplePostRequest(const string& url,
+ const string& body,
+ const string& content_type,
+ long* 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 SendRequestInner(const string& url,
+ long* http_status_code,
+ string* http_header_data,
+ string* http_response_data);
+
+ void Reset();
+
+ bool CheckInit();
+
+ 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 (*easy_reset_)(CURL*);
+ 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
new file mode 100644
index 0000000000..79281a9043
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/linux/linux_libc_support.cc
@@ -0,0 +1,248 @@
+// 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;
+}
+
+const char* my_strstr(const char* haystack, const char* needle) {
+ while (*haystack != 0) {
+ if((*haystack == *needle) &&
+ (my_strncmp(haystack, needle, my_strlen(needle)) == 0)) {
+ return haystack;
+ }
+ haystack++;
+ }
+ return nullptr;
+}
+
+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
new file mode 100644
index 0000000000..03e3aa0657
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/linux/linux_libc_support.h
@@ -0,0 +1,98 @@
+// 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);
+
+extern const char *my_strstr(const char *haystack, const 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
new file mode 100644
index 0000000000..adadfed44d
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/linux/linux_libc_support_unittest.cc
@@ -0,0 +1,213 @@
+// 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
new file mode 100644
index 0000000000..4e938269f2
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/linux/memory_mapped_file.cc
@@ -0,0 +1,107 @@
+// 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
new file mode 100644
index 0000000000..fa660cc91a
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/linux/memory_mapped_file.h
@@ -0,0 +1,87 @@
+// 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
new file mode 100644
index 0000000000..fad59f40cd
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/linux/memory_mapped_file_unittest.cc
@@ -0,0 +1,208 @@
+// 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
new file mode 100644
index 0000000000..ecd1e5ffe7
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/linux/moz.build
@@ -0,0 +1,42 @@
+# -*- 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',
+ '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',
+ ]
+
+if CONFIG['OS_TARGET'] == 'Android':
+ DEFINES['ANDROID_NDK_MAJOR_VERSION'] = CONFIG['ANDROID_NDK_MAJOR_VERSION']
+ DEFINES['ANDROID_NDK_MINOR_VERSION'] = CONFIG['ANDROID_NDK_MINOR_VERSION']
+ COMPILE_FLAGS['OS_INCLUDES'] += [
+ '-I%s/toolkit/crashreporter/google-breakpad/src/common/android/include' % TOPSRCDIR,
+ ]
+
+if not CONFIG['HAVE_GETCONTEXT']:
+ # We don't support unifying assembly files.
+ SOURCES += [
+ 'breakpad_getcontext.S',
+ ]
+
+Library('breakpad_linux_common_s')
+
+include('/toolkit/crashreporter/crashreporter.mozbuild')
+
+if CONFIG['CC_TYPE'] in ('clang', 'gcc'):
+ CXXFLAGS += ['-Wno-error=stack-protector']
diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/safe_readlink.cc b/toolkit/crashreporter/google-breakpad/src/common/linux/safe_readlink.cc
new file mode 100644
index 0000000000..870c28af3b
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/linux/safe_readlink.cc
@@ -0,0 +1,53 @@
+// 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
new file mode 100644
index 0000000000..4ae131b580
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/linux/safe_readlink.h
@@ -0,0 +1,65 @@
+// 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
new file mode 100644
index 0000000000..d346b2a807
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/linux/safe_readlink_unittest.cc
@@ -0,0 +1,89 @@
+// 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_collector_client.cc b/toolkit/crashreporter/google-breakpad/src/common/linux/symbol_collector_client.cc
new file mode 100644
index 0000000000..92b25ddba9
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/linux/symbol_collector_client.cc
@@ -0,0 +1,195 @@
+// Copyright (c) 2019 Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "common/linux/symbol_collector_client.h"
+
+#include <stdio.h>
+
+#include <iostream>
+#include <regex>
+
+#include "common/linux/libcurl_wrapper.h"
+
+namespace google_breakpad {
+namespace sym_upload {
+
+// static
+bool SymbolCollectorClient::CreateUploadUrl(
+ LibcurlWrapper* libcurl_wrapper,
+ const string& api_url,
+ const string& api_key,
+ UploadUrlResponse* uploadUrlResponse) {
+ string header, response;
+ long response_code;
+
+ string url = api_url + "/v1/uploads:create";
+ if (!api_key.empty()) {
+ url += "?key=" + api_key;
+ }
+
+ if (!libcurl_wrapper->SendSimplePostRequest(url,
+ /*body=*/"",
+ /*content_type=*/"",
+ &response_code,
+ &header,
+ &response)) {
+ printf("Failed to create upload url.\n");
+ printf("Response code: %ld\n", response_code);
+ printf("Response:\n");
+ printf("%s\n", response.c_str());
+ return false;
+ }
+
+ // Note camel-case rather than underscores.
+ std::regex upload_url_regex("\"uploadUrl\": \"([^\"]+)\"");
+ std::regex upload_key_regex("\"uploadKey\": \"([^\"]+)\"");
+
+ std::smatch upload_url_match;
+ if (!std::regex_search(response, upload_url_match, upload_url_regex) ||
+ upload_url_match.size() != 2) {
+ printf("Failed to parse create url response.");
+ printf("Response:\n");
+ printf("%s\n", response.c_str());
+ return false;
+ }
+ string upload_url = upload_url_match[1].str();
+
+ std::smatch upload_key_match;
+ if (!std::regex_search(response, upload_key_match, upload_key_regex) ||
+ upload_key_match.size() != 2) {
+ printf("Failed to parse create url response.");
+ printf("Response:\n");
+ printf("%s\n", response.c_str());
+ return false;
+ }
+ string upload_key = upload_key_match[1].str();
+
+ uploadUrlResponse->upload_url = upload_url;
+ uploadUrlResponse->upload_key = upload_key;
+ return true;
+}
+
+// static
+CompleteUploadResult SymbolCollectorClient::CompleteUpload(
+ LibcurlWrapper* libcurl_wrapper,
+ const string& api_url,
+ const string& api_key,
+ const string& upload_key,
+ const string& debug_file,
+ const string& debug_id,
+ const string& type) {
+ string header, response;
+ long response_code;
+
+ string url = api_url + "/v1/uploads/" + upload_key + ":complete";
+ if (!api_key.empty()) {
+ url += "?key=" + api_key;
+ }
+ string body =
+ "{ symbol_id: {"
+ "debug_file: \"" + debug_file + "\", "
+ "debug_id: \"" + debug_id + "\" }, "
+ "symbol_upload_type: \"" + type + "\" }";
+
+ if (!libcurl_wrapper->SendSimplePostRequest(url,
+ body,
+ "application/son",
+ &response_code,
+ &header,
+ &response)) {
+ printf("Failed to complete upload.\n");
+ printf("Response code: %ld\n", response_code);
+ printf("Response:\n");
+ printf("%s\n", response.c_str());
+ return CompleteUploadResult::Error;
+ }
+
+ std::regex result_regex("\"result\": \"([^\"]+)\"");
+ std::smatch result_match;
+ if (!std::regex_search(response, result_match, result_regex) ||
+ result_match.size() != 2) {
+ printf("Failed to parse complete upload response.");
+ printf("Response:\n");
+ printf("%s\n", response.c_str());
+ return CompleteUploadResult::Error;
+ }
+ string result = result_match[1].str();
+
+ if (result.compare("DUPLICATE_DATA") == 0) {
+ return CompleteUploadResult::DuplicateData;
+ }
+
+ return CompleteUploadResult::Ok;
+}
+
+// static
+SymbolStatus SymbolCollectorClient::CheckSymbolStatus(
+ LibcurlWrapper* libcurl_wrapper,
+ const string& api_url,
+ const string& api_key,
+ const string& debug_file,
+ const string& debug_id) {
+ string header, response;
+ long response_code;
+ string url = api_url +
+ "/v1/symbols/" + debug_file + "/" + debug_id + ":checkStatus";
+ if (!api_key.empty()) {
+ url += "?key=" + api_key;
+ }
+
+ if (!libcurl_wrapper->SendGetRequest(
+ url,
+ &response_code,
+ &header,
+ &response)) {
+ printf("Failed to check symbol status, error message.\n");
+ printf("Response code: %ld\n", response_code);
+ printf("Response:\n");
+ printf("%s\n", response.c_str());
+ return SymbolStatus::Unknown;
+ }
+
+ std::regex status_regex("\"status\": \"([^\"]+)\"");
+ std::smatch status_match;
+ if (!std::regex_search(response, status_match, status_regex) ||
+ status_match.size() != 2) {
+ printf("Failed to parse check symbol status response.");
+ printf("Response:\n");
+ printf("%s\n", response.c_str());
+ return SymbolStatus::Unknown;
+ }
+ string status = status_match[1].str();
+
+ return (status.compare("FOUND") == 0) ?
+ SymbolStatus::Found :
+ SymbolStatus::Missing;
+}
+
+} // namespace sym_upload
+} // namespace google_breakpad
diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/symbol_collector_client.h b/toolkit/crashreporter/google-breakpad/src/common/linux/symbol_collector_client.h
new file mode 100644
index 0000000000..0e23242a2b
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/linux/symbol_collector_client.h
@@ -0,0 +1,88 @@
+// Copyright (c) 2019, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef COMMON_LINUX_SYMBOL_COLLECTOR_CLIENT_H_
+#define COMMON_LINUX_SYMBOL_COLLECTOR_CLIENT_H_
+
+#include <string>
+
+#include "common/linux/libcurl_wrapper.h"
+#include "common/using_std_string.h"
+
+namespace google_breakpad {
+namespace sym_upload {
+
+struct UploadUrlResponse {
+ string upload_url;
+ string upload_key;
+};
+
+enum SymbolStatus {
+ Found,
+ Missing,
+ Unknown
+};
+
+enum CompleteUploadResult {
+ Ok,
+ DuplicateData,
+ Error
+};
+
+// Helper class to communicate with a sym-upload-v2 service over HTTP/REST,
+// via libcurl.
+class SymbolCollectorClient {
+ public:
+ static bool CreateUploadUrl(
+ LibcurlWrapper* libcurl_wrapper,
+ const string& api_url,
+ const string& api_key,
+ UploadUrlResponse* uploadUrlResponse);
+
+ static CompleteUploadResult CompleteUpload(
+ LibcurlWrapper* libcurl_wrapper,
+ const string& api_url,
+ const string& api_key,
+ const string& upload_key,
+ const string& debug_file,
+ const string& debug_id,
+ const string& type);
+
+ static SymbolStatus CheckSymbolStatus(
+ LibcurlWrapper* libcurl_wrapper,
+ const string& api_url,
+ const string& api_key,
+ const string& debug_file,
+ const string& debug_id);
+};
+
+} // namespace sym_upload
+} // namespace google_breakpad
+
+#endif // COMMON_LINUX_SYMBOL_COLLECTOR_CLIENT_H_
diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/symbol_upload.cc b/toolkit/crashreporter/google-breakpad/src/common/linux/symbol_upload.cc
new file mode 100644
index 0000000000..87741a0a21
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/linux/symbol_upload.cc
@@ -0,0 +1,284 @@
+// 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/symbol_upload.h"
+
+#include <assert.h>
+#include <stdio.h>
+
+#include <functional>
+#include <iostream>
+#include <vector>
+
+#include "common/linux/http_upload.h"
+#include "common/linux/libcurl_wrapper.h"
+#include "common/linux/symbol_collector_client.h"
+
+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;
+}
+
+// |options| describes the current sym_upload options.
+// |module_parts| contains the strings parsed from the MODULE entry of the
+// Breakpad symbol file being uploaded.
+// |compacted_id| is the debug_id from the MODULE entry of the Breakpad symbol
+// file being uploaded, with all hyphens removed.
+bool SymUploadV1Start(
+ const Options& options,
+ std::vector<string> module_parts,
+ const string& compacted_id) {
+ std::map<string, string> parameters;
+ // 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,
+ /*ca_certificate_file=*/"",
+ &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");
+ }
+
+ return success;
+}
+
+// |options| describes the current sym_upload options.
+// |code_id| is the basename of the module for which symbols are being
+// uploaded.
+// |debug_id| is the debug_id of the module for which symbols are being
+// uploaded.
+bool SymUploadV2Start(
+ const Options& options,
+ const string& code_file,
+ const string& debug_id,
+ const string& type) {
+ google_breakpad::LibcurlWrapper libcurl_wrapper;
+ if (!libcurl_wrapper.Init()) {
+ printf("Failed to init google_breakpad::LibcurlWrapper.\n");
+ return false;
+ }
+
+ if (!options.force) {
+ SymbolStatus symbolStatus = SymbolCollectorClient::CheckSymbolStatus(
+ &libcurl_wrapper,
+ options.uploadURLStr,
+ options.api_key,
+ code_file,
+ debug_id);
+ if (symbolStatus == SymbolStatus::Found) {
+ printf("Symbol file already exists, upload aborted."
+ " Use \"-f\" to overwrite.\n");
+ return true;
+ } else if (symbolStatus == SymbolStatus::Unknown) {
+ printf("Failed to check for existing symbol.\n");
+ return false;
+ }
+ }
+
+ UploadUrlResponse uploadUrlResponse;
+ if (!SymbolCollectorClient::CreateUploadUrl(
+ &libcurl_wrapper,
+ options.uploadURLStr,
+ options.api_key,
+ &uploadUrlResponse)) {
+ printf("Failed to create upload URL.\n");
+ return false;
+ }
+
+ string signed_url = uploadUrlResponse.upload_url;
+ string upload_key = uploadUrlResponse.upload_key;
+ string header;
+ string response;
+ long response_code;
+
+ if (!libcurl_wrapper.SendPutRequest(signed_url,
+ options.symbolsPath,
+ &response_code,
+ &header,
+ &response)) {
+ printf("Failed to send symbol file.\n");
+ printf("Response code: %ld\n", response_code);
+ printf("Response:\n");
+ printf("%s\n", response.c_str());
+ return false;
+ } else if (response_code == 0) {
+ printf("Failed to send symbol file: No response code\n");
+ return false;
+ } 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());
+ return false;
+ }
+
+ CompleteUploadResult completeUploadResult =
+ SymbolCollectorClient::CompleteUpload(&libcurl_wrapper,
+ options.uploadURLStr,
+ options.api_key,
+ upload_key,
+ code_file,
+ debug_id,
+ type);
+ if (completeUploadResult == CompleteUploadResult::Error) {
+ printf("Failed to complete upload.\n");
+ return false;
+ } else if (completeUploadResult == CompleteUploadResult::DuplicateData) {
+ printf("Uploaded file checksum matched existing file checksum,"
+ " no change necessary.\n");
+ } else {
+ printf("Successfully sent the symbol file.\n");
+ }
+
+ return true;
+}
+
+//=============================================================================
+void Start(Options* options) {
+ if (options->upload_protocol == UploadProtocol::SYM_UPLOAD_V2) {
+ string code_file;
+ string debug_id;
+ string type;
+
+ if (options->type.empty() || options->type == kBreakpadSymbolType) {
+ // Breakpad upload so read these from input file.
+ std::vector<string> module_parts;
+ if (!ModuleDataForSymbolFile(options->symbolsPath, &module_parts)) {
+ fprintf(stderr, "Failed to parse symbol file!\n");
+ return;
+ }
+ code_file = module_parts[4];
+ debug_id = CompactIdentifier(module_parts[3]);
+ type = kBreakpadSymbolType;
+ } else {
+ // Native upload so these must be explicitly set.
+ code_file = options->code_file;
+ debug_id = options->debug_id;
+ type = options->type;
+ }
+
+ options->success = SymUploadV2Start(*options, code_file, debug_id, type);
+ } else {
+ std::vector<string> module_parts;
+ if (!ModuleDataForSymbolFile(options->symbolsPath, &module_parts)) {
+ fprintf(stderr, "Failed to parse symbol file!\n");
+ return;
+ }
+ const string compacted_id = CompactIdentifier(module_parts[3]);
+ options->success = SymUploadV1Start(*options, module_parts, compacted_id);
+ }
+}
+
+} // 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
new file mode 100644
index 0000000000..9033152bf2
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/linux/symbol_upload.h
@@ -0,0 +1,76 @@
+// -*- 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 {
+
+enum class UploadProtocol {
+ SYM_UPLOAD_V1,
+ SYM_UPLOAD_V2,
+};
+
+constexpr char kBreakpadSymbolType[] = "BREAKPAD";
+
+struct Options {
+ Options() : upload_protocol(UploadProtocol::SYM_UPLOAD_V1), force(false) {}
+
+ string symbolsPath;
+ string uploadURLStr;
+ string proxy;
+ string proxy_user_pwd;
+ string version;
+ bool success;
+ UploadProtocol upload_protocol;
+ bool force;
+ string api_key;
+
+ // These only need to be set for native symbol uploads.
+ string code_file;
+ string debug_id;
+ string type;
+};
+
+// 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
new file mode 100644
index 0000000000..98e81dab75
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/linux/synth_elf.cc
@@ -0,0 +1,263 @@
+#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
new file mode 100644
index 0000000000..1d2a20ca22
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/linux/synth_elf.h
@@ -0,0 +1,197 @@
+// -*- 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
new file mode 100644
index 0000000000..cd74c28624
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/linux/synth_elf_unittest.cc
@@ -0,0 +1,413 @@
+// 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_SUITE(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
new file mode 100644
index 0000000000..92fe017b92
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/linux/tests/auto_testfile.h
@@ -0,0 +1,124 @@
+// 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
new file mode 100644
index 0000000000..6896a688d9
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/linux/tests/crash_generator.cc
@@ -0,0 +1,329 @@
+// 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 <sched.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) {
+ sched_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) {
+ // Custom signal handlers, which may have been installed by a test launcher,
+ // are undesirable in this child.
+ if (signal(crash_signal, SIG_DFL) == SIG_ERR) {
+ perror("CrashGenerator: signal");
+ exit(1);
+ }
+ 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://bugs.chromium.org/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
new file mode 100644
index 0000000000..7e2fcbf98a
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/linux/tests/crash_generator.h
@@ -0,0 +1,117 @@
+// 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/linux/ucontext_constants.h b/toolkit/crashreporter/google-breakpad/src/common/linux/ucontext_constants.h
new file mode 100644
index 0000000000..c390508a1a
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/linux/ucontext_constants.h
@@ -0,0 +1,153 @@
+// 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 signal.h.
+//
+// Used by src/common/linux/breakpad_getcontext.S
+// Tested by src/common/linux/breakpad_getcontext_unittest.cc
+//
+// This header should not be used by anything else.
+
+#ifndef GOOGLEBREAKPAD_COMMON_LINUX_UCONTEXT_CONSTANTS_H
+#define GOOGLEBREAKPAD_COMMON_LINUX_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
+#if defined(__BIONIC__)
+#define UCONTEXT_FPREGS_MEM_OFFSET 116
+#else
+#define UCONTEXT_FPREGS_MEM_OFFSET 236
+#endif
+
+#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
+#if defined(__BIONIC__)
+#define MCONTEXT_FPREGS_MEM 304
+#else
+#define MCONTEXT_FPREGS_MEM 424
+#endif
+#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/long_string_dictionary.cc b/toolkit/crashreporter/google-breakpad/src/common/long_string_dictionary.cc
new file mode 100644
index 0000000000..46bbf61370
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/long_string_dictionary.cc
@@ -0,0 +1,178 @@
+// Copyright (c) 2017, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "common/long_string_dictionary.h"
+
+#include <assert.h>
+#include <string.h>
+
+#include <algorithm>
+#include <string>
+
+#include "common/simple_string_dictionary.h"
+
+#define arraysize(f) (sizeof(f) / sizeof(*f))
+
+namespace {
+// Suffixes for segment keys.
+const char* const kSuffixes[] = {"__1", "__2", "__3", "__4", "__5", "__6",
+ "__7", "__8", "__9", "__10"};
+#if !defined(NDEBUG)
+// The maximum suffix string length.
+const size_t kMaxSuffixLength = 4;
+#endif
+} // namespace
+
+namespace google_breakpad {
+
+using std::string;
+
+void LongStringDictionary::SetKeyValue(const char* key, const char* value) {
+ assert(key);
+ if (!key)
+ return;
+
+ RemoveKey(key);
+
+ if (!value) {
+ return;
+ }
+
+ // Key must not be an empty string.
+ assert(key[0] != '\0');
+ if (key[0] == '\0')
+ return;
+
+ // If the value is not valid for segmentation, forwards the key and the value
+ // to SetKeyValue of SimpleStringDictionary and returns.
+ size_t value_length = strlen(value);
+ if (value_length <= (value_size - 1)) {
+ SimpleStringDictionary::SetKeyValue(key, value);
+ return;
+ }
+
+ size_t key_length = strlen(key);
+ assert(key_length + kMaxSuffixLength <= (key_size - 1));
+
+ char segment_key[key_size];
+ char segment_value[value_size];
+
+ strcpy(segment_key, key);
+
+ const char* remain_value = value;
+ size_t remain_value_length = strlen(value);
+
+ for (unsigned long i = 0; i < arraysize(kSuffixes); i++) {
+ if (remain_value_length == 0) {
+ return;
+ }
+
+ strcpy(segment_key + key_length, kSuffixes[i]);
+
+ size_t segment_value_length =
+ std::min(remain_value_length, value_size - 1);
+
+ strncpy(segment_value, remain_value, segment_value_length);
+ segment_value[segment_value_length] = '\0';
+
+ remain_value += segment_value_length;
+ remain_value_length -= segment_value_length;
+
+ SimpleStringDictionary::SetKeyValue(segment_key, segment_value);
+ }
+}
+
+bool LongStringDictionary::RemoveKey(const char* key) {
+ assert(key);
+ if (!key)
+ return false;
+
+ if (SimpleStringDictionary::RemoveKey(key)) {
+ return true;
+ }
+
+ size_t key_length = strlen(key);
+ assert(key_length + kMaxSuffixLength <= (key_size - 1));
+
+ char segment_key[key_size];
+ strcpy(segment_key, key);
+
+ unsigned long i = 0;
+ for (; i < arraysize(kSuffixes); i++) {
+ strcpy(segment_key + key_length, kSuffixes[i]);
+ if (!SimpleStringDictionary::RemoveKey(segment_key)) {
+ break;
+ }
+ }
+ return i != 0;
+}
+
+const string LongStringDictionary::GetValueForKey(const char* key) const {
+ assert(key);
+ if (!key)
+ return "";
+
+ // Key must not be an empty string.
+ assert(key[0] != '\0');
+ if (key[0] == '\0')
+ return "";
+
+ const char* value = SimpleStringDictionary::GetValueForKey(key);
+ if (value)
+ return string(value);
+
+ size_t key_length = strlen(key);
+ assert(key_length + kMaxSuffixLength <= (key_size - 1));
+
+ bool found_segment = false;
+ char segment_key[key_size];
+ string return_value;
+
+ strcpy(segment_key, key);
+ for (unsigned long i = 0; i < arraysize(kSuffixes); i++) {
+ strcpy(segment_key + key_length, kSuffixes[i]);
+
+ const char* segment_value =
+ SimpleStringDictionary::GetValueForKey(segment_key);
+
+ if (segment_value != NULL) {
+ found_segment = true;
+ return_value.append(segment_value);
+ } else {
+ break;
+ }
+ }
+
+ if (found_segment) {
+ return return_value;
+ }
+ return "";
+}
+
+} // namespace google_breakpad
diff --git a/toolkit/crashreporter/google-breakpad/src/common/long_string_dictionary.h b/toolkit/crashreporter/google-breakpad/src/common/long_string_dictionary.h
new file mode 100644
index 0000000000..68bf03de2f
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/long_string_dictionary.h
@@ -0,0 +1,87 @@
+// Copyright (c) 2017, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef COMMON_LONG_STRING_DICTIONARY_H_
+#define COMMON_LONG_STRING_DICTIONARY_H_
+
+#include <string>
+
+#include "common/simple_string_dictionary.h"
+
+namespace google_breakpad {
+// key_size is the maxium size that |key| can take in
+// SimpleStringDictionary which is defined in simple_string_dictionary.h.
+//
+// value_size is the maxium size that |value| can take in
+// SimpleStringDictionary which is defined in simple_string_dictionary.h.
+//
+// LongStringDictionary is a subclass of SimpleStringDictionary which supports
+// longer values to be stored in the dictionary. The maximum length supported is
+// (value_size - 1) * 10.
+//
+// For example, LongStringDictionary will store long value with key 'abc' into
+// segment values with segment keys 'abc__1', 'abc__2', 'abc__3', ...
+//
+// Clients must avoid using the same suffixes as their key's suffix when
+// LongStringDictionary is used.
+class LongStringDictionary : public SimpleStringDictionary {
+ public:
+ // Stores |value| into |key|, or segment values into segment keys. The maxium
+ // number of segments is 10. If |value| can not be stored in 10 segments, it
+ // will be truncated. Replacing the existing value if |key| is already present
+ // and replacing the existing segment values if segment keys are already
+ // present.
+ //
+ // |key| must not be NULL. If the |value| need to be divided into segments,
+ // the lengh of |key| must be smaller enough so that lengths of segment keys
+ // which are key with suffixes are all samller than (key_size - 1). Currently,
+ // the max length of suffixes are 4.
+ //
+ // If |value| is NULL, the key and its corresponding segment keys are 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);
+
+ // Given |key|, removes any associated value or associated segment values.
+ // |key| must not be NULL. If the key is not found, searchs its segment keys
+ // and removes corresponding segment values if found.
+ bool RemoveKey(const char* key);
+
+ // Given |key|, returns its corresponding |value|. |key| must not be NULL. If
+ // the key is found, its corresponding |value| is returned.
+ //
+ // If no corresponding |value| is found, segment keys of the given |key| will
+ // be used to search for corresponding segment values. If segment values
+ // exist, assembled value from them is returned. If no segment value exists,
+ // NULL is returned.
+ const std::string GetValueForKey(const char* key) const;
+};
+} // namespace google_breakpad
+
+#endif // COMMON_LONG_STRING_DICTIONARY_H_
diff --git a/toolkit/crashreporter/google-breakpad/src/common/long_string_dictionary_unittest.cc b/toolkit/crashreporter/google-breakpad/src/common/long_string_dictionary_unittest.cc
new file mode 100644
index 0000000000..f9b645ba7b
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/long_string_dictionary_unittest.cc
@@ -0,0 +1,301 @@
+// Copyright (c) 2017, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <algorithm>
+#include <string>
+
+#include "breakpad_googletest_includes.h"
+#include "common/long_string_dictionary.h"
+
+namespace google_breakpad {
+
+using std::string;
+
+TEST(LongStringDictionary, LongStringDictionary) {
+ // Make a new dictionary
+ LongStringDictionary dict;
+
+ // Set three distinct values on three keys
+ dict.SetKeyValue("key1", "value1");
+ dict.SetKeyValue("key2", "value2");
+ dict.SetKeyValue("key3", "value3");
+
+ EXPECT_EQ("value1", dict.GetValueForKey("key1"));
+ EXPECT_EQ("value2", dict.GetValueForKey("key2"));
+ EXPECT_EQ("value3", dict.GetValueForKey("key3"));
+ EXPECT_EQ(3u, dict.GetCount());
+ // try an unknown key
+ EXPECT_EQ("", dict.GetValueForKey("key4"));
+
+ // Remove a key
+ dict.RemoveKey("key3");
+
+ // Now make sure it's not there anymore
+ EXPECT_EQ("", dict.GetValueForKey("key3"));
+
+ // Remove by setting value to NULL
+ dict.SetKeyValue("key2", NULL);
+
+ // Now make sure it's not there anymore
+ EXPECT_EQ("", dict.GetValueForKey("key2"));
+}
+
+// Add a bunch of values to the dictionary, remove some entries in the middle,
+// and then add more.
+TEST(LongStringDictionary, Iterator) {
+ LongStringDictionary* dict = new LongStringDictionary();
+ ASSERT_TRUE(dict);
+
+ char key[LongStringDictionary::key_size];
+ char value[LongStringDictionary::value_size];
+
+ const int kDictionaryCapacity = LongStringDictionary::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(LongStringDictionary, AddRemove) {
+ LongStringDictionary dict;
+ dict.SetKeyValue("rob", "ert");
+ dict.SetKeyValue("mike", "pink");
+ dict.SetKeyValue("mark", "allays");
+
+ EXPECT_EQ(3u, dict.GetCount());
+ EXPECT_EQ("ert", dict.GetValueForKey("rob"));
+ EXPECT_EQ("pink", dict.GetValueForKey("mike"));
+ EXPECT_EQ("allays", dict.GetValueForKey("mark"));
+
+ dict.RemoveKey("mike");
+
+ EXPECT_EQ(2u, dict.GetCount());
+ EXPECT_EQ("", dict.GetValueForKey("mike"));
+
+ dict.SetKeyValue("mark", "mal");
+ EXPECT_EQ(2u, dict.GetCount());
+ EXPECT_EQ("mal", dict.GetValueForKey("mark"));
+
+ dict.RemoveKey("mark");
+ EXPECT_EQ(1u, dict.GetCount());
+ EXPECT_EQ("", dict.GetValueForKey("mark"));
+}
+
+TEST(LongStringDictionary, AddRemoveLongValue) {
+ LongStringDictionary dict;
+
+ string long_value = string(256, 'x');
+ dict.SetKeyValue("rob", long_value.c_str());
+
+ EXPECT_EQ(2u, dict.GetCount());
+
+ string long_value_part_1 = string(255, 'x');
+
+ EXPECT_EQ(long_value_part_1, dict.GetValueForKey("rob__1"));
+ EXPECT_EQ("x", dict.GetValueForKey("rob__2"));
+
+ EXPECT_EQ(long_value, dict.GetValueForKey("rob"));
+
+ dict.RemoveKey("rob");
+ EXPECT_EQ(0u, dict.GetCount());
+}
+
+TEST(LongStringDictionary, AddRemoveSuperLongValue) {
+ LongStringDictionary dict;
+
+ string long_value = string(255 * 10, 'x');
+ dict.SetKeyValue("rob", long_value.c_str());
+
+ EXPECT_EQ(10u, dict.GetCount());
+
+ string long_value_part = string(255, 'x');
+
+ EXPECT_EQ(long_value_part, dict.GetValueForKey("rob__1"));
+ EXPECT_EQ(long_value_part, dict.GetValueForKey("rob__2"));
+ EXPECT_EQ(long_value_part, dict.GetValueForKey("rob__3"));
+ EXPECT_EQ(long_value_part, dict.GetValueForKey("rob__4"));
+ EXPECT_EQ(long_value_part, dict.GetValueForKey("rob__5"));
+ EXPECT_EQ(long_value_part, dict.GetValueForKey("rob__6"));
+ EXPECT_EQ(long_value_part, dict.GetValueForKey("rob__7"));
+ EXPECT_EQ(long_value_part, dict.GetValueForKey("rob__8"));
+ EXPECT_EQ(long_value_part, dict.GetValueForKey("rob__9"));
+ EXPECT_EQ(long_value_part, dict.GetValueForKey("rob__10"));
+ EXPECT_EQ(10u, dict.GetCount());
+
+ EXPECT_EQ(long_value, dict.GetValueForKey("rob"));
+
+ dict.RemoveKey("rob");
+ EXPECT_EQ(0u, dict.GetCount());
+}
+
+TEST(LongStringDictionary, TruncateSuperLongValue) {
+ LongStringDictionary dict;
+
+ string long_value = string(255 * 11, 'x');
+ dict.SetKeyValue("rob", long_value.c_str());
+
+ EXPECT_EQ(10u, dict.GetCount());
+
+ string long_value_part = string(255, 'x');
+
+ EXPECT_EQ(long_value_part, dict.GetValueForKey("rob__1"));
+ EXPECT_EQ(long_value_part, dict.GetValueForKey("rob__2"));
+ EXPECT_EQ(long_value_part, dict.GetValueForKey("rob__3"));
+ EXPECT_EQ(long_value_part, dict.GetValueForKey("rob__4"));
+ EXPECT_EQ(long_value_part, dict.GetValueForKey("rob__5"));
+ EXPECT_EQ(long_value_part, dict.GetValueForKey("rob__6"));
+ EXPECT_EQ(long_value_part, dict.GetValueForKey("rob__7"));
+ EXPECT_EQ(long_value_part, dict.GetValueForKey("rob__8"));
+ EXPECT_EQ(long_value_part, dict.GetValueForKey("rob__9"));
+ EXPECT_EQ(long_value_part, dict.GetValueForKey("rob__10"));
+ EXPECT_EQ(10u, dict.GetCount());
+
+ string expected_long_value = string(255 * 10, 'x');
+ EXPECT_EQ(expected_long_value, dict.GetValueForKey("rob"));
+
+ dict.RemoveKey("rob");
+ EXPECT_EQ(0u, dict.GetCount());
+}
+
+TEST(LongStringDictionary, OverrideLongValue) {
+ LongStringDictionary dict;
+
+ string long_value = string(255 * 10, 'x');
+ dict.SetKeyValue("rob", long_value.c_str());
+
+ EXPECT_EQ(10u, dict.GetCount());
+ EXPECT_EQ(long_value, dict.GetValueForKey("rob"));
+
+ dict.SetKeyValue("rob", "short_value");
+
+ EXPECT_EQ(1u, dict.GetCount());
+ EXPECT_EQ("short_value", dict.GetValueForKey("rob"));
+}
+
+TEST(LongStringDictionary, OverrideShortValue) {
+ LongStringDictionary dict;
+
+ dict.SetKeyValue("rob", "short_value");
+
+ EXPECT_EQ(1u, dict.GetCount());
+ EXPECT_EQ("short_value", dict.GetValueForKey("rob"));
+
+ string long_value = string(255 * 10, 'x');
+ dict.SetKeyValue("rob", long_value.c_str());
+
+ EXPECT_EQ(10u, dict.GetCount());
+ EXPECT_EQ(long_value, dict.GetValueForKey("rob"));
+}
+
+} // namespace google_breakpad
diff --git a/toolkit/crashreporter/google-breakpad/src/common/mac/Breakpad.xcconfig b/toolkit/crashreporter/google-breakpad/src/common/mac/Breakpad.xcconfig
new file mode 100644
index 0000000000..f091369081
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/mac/Breakpad.xcconfig
@@ -0,0 +1,52 @@
+// 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
new file mode 100644
index 0000000000..94cdd8cfca
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/mac/BreakpadDebug.xcconfig
@@ -0,0 +1,32 @@
+// 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
new file mode 100644
index 0000000000..920f277db8
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/mac/BreakpadRelease.xcconfig
@@ -0,0 +1,34 @@
+// 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
new file mode 100644
index 0000000000..fce2990a3e
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/mac/GTMDefines.h
@@ -0,0 +1,396 @@
+//
+// 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 __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 https://github.com/google/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
+
+// 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
+ #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
+
+// ============================================================================
+
+// 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
new file mode 100644
index 0000000000..c4fd140290
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/mac/GTMLogger.h
@@ -0,0 +1,504 @@
+//
+// 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
new file mode 100644
index 0000000000..ebc5836a25
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/mac/GTMLogger.m
@@ -0,0 +1,611 @@
+//
+// 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
new file mode 100644
index 0000000000..0cea733e5d
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/mac/HTTPMultipartUpload.h
@@ -0,0 +1,61 @@
+// 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)
+ NSMutableString *parameters_; // The JSON payload 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:(NSMutableString *)parameters;
+- (NSMutableString *)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
new file mode 100644
index 0000000000..d2480493f6
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/mac/HTTPMultipartUpload.m
@@ -0,0 +1,262 @@
+// 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:] which is
+// available on iOS 7+.
+static NSData *SendSynchronousNSURLRequest(NSURLRequest *req,
+ NSURLResponse **out_response,
+ NSError **out_error) {
+#if (defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && defined(__IPHONE_7_0) && \
+ __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_7_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 *)formDataForJSON:(NSString *)json;
+- (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 *)formDataForJSON:(NSString *)json {
+ NSMutableData *data = [NSMutableData data];
+ NSString *fmt = @"--%@\r\nContent-Disposition: form-data; name=\"extra\"; "
+ "filename=\"extra.json\"\r\nContent-Type: application/json\r\n\r\n";
+ NSString *form = [NSString stringWithFormat:fmt, boundary_];
+
+ [data appendData:[form dataUsingEncoding:NSUTF8StringEncoding]];
+ [data appendData:[json dataUsingEncoding:NSUTF8StringEncoding]];
+
+ return data;
+}
+
+//=============================================================================
+- (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:(NSMutableString *)parameters {
+ if (parameters != parameters_) {
+ [parameters_ release];
+ parameters_ = [parameters mutableCopy];
+ }
+}
+
+//=============================================================================
+- (NSMutableString *)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:60.0];
+
+ NSMutableData *postBody = [NSMutableData data];
+
+ [req setValue:[NSString stringWithFormat:@"multipart/form-data; boundary=%@",
+ boundary_] forHTTPHeaderField:@"Content-type"];
+
+ // Add JSON parameters to the message
+ [postBody appendData:[self formDataForJSON:parameters_]];
+
+ // Add any files to the message
+ NSArray *fileNames = [files_ allKeys];
+ for (NSString *name in fileNames) {
+ 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
new file mode 100644
index 0000000000..e3d4a0fdbc
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/mac/MachIPC.h
@@ -0,0 +1,303 @@
+// 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 {
+#ifndef PRINT_MACH_RESULT
+#define PRINT_MACH_RESULT(result_, message_) \
+ printf(message_" %s (%d)\n", mach_error_string(result_), result_ );
+#endif
+
+//==============================================================================
+// 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
new file mode 100644
index 0000000000..dc9773f77a
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/mac/MachIPC.mm
@@ -0,0 +1,306 @@
+// 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
new file mode 100644
index 0000000000..c0e4bac54b
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/mac/arch_utilities.cc
@@ -0,0 +1,264 @@
+// 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
+
+#ifndef CPU_SUBTYPE_ARM64_E
+#define CPU_SUBTYPE_ARM64_E (static_cast<cpu_subtype_t>(2))
+#endif // CPU_SUBTYPE_ARM64_E
+
+namespace {
+
+const NXArchInfo* ArchInfo_arm64(cpu_subtype_t cpu_subtype) {
+ const char* name = NULL;
+ switch (cpu_subtype) {
+ case CPU_SUBTYPE_ARM64_ALL:
+ name = "arm64";
+ break;
+ case CPU_SUBTYPE_ARM64_E:
+ name = "arm64e";
+ break;
+ default:
+ return NULL;
+ }
+
+ NXArchInfo* arm64 = new NXArchInfo;
+ *arm64 = *NXGetArchInfoFromCpuType(CPU_TYPE_ARM,
+ CPU_SUBTYPE_ARM_V7);
+ arm64->name = name;
+ arm64->cputype = CPU_TYPE_ARM64;
+ arm64->cpusubtype = cpu_subtype;
+ 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);
+
+ if (!strcmp("arm64e", arch_name))
+ return BreakpadGetArchInfoFromCpuType(CPU_TYPE_ARM64,
+ CPU_SUBTYPE_ARM64_E);
+
+ // 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(cpu_subtype);
+ return arm64;
+ }
+
+ if (cpu_type == CPU_TYPE_ARM64 && cpu_subtype == CPU_SUBTYPE_ARM64_E) {
+ static const NXArchInfo* arm64e = ArchInfo_arm64(cpu_subtype);
+ return arm64e;
+ }
+
+ // 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_x86_64h,
+ kArch_arm,
+ kArch_arm64,
+ kArch_arm64e,
+ 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"
+ },
+ {
+ "x86_64h",
+ CPU_TYPE_X86_64,
+ CPU_SUBTYPE_X86_64_H,
+ NX_LittleEndian,
+ "Intel x86-64h Haswell"
+ },
+ {
+ "arm",
+ CPU_TYPE_ARM,
+ CPU_SUBTYPE_ARM_ALL,
+ NX_LittleEndian,
+ "ARM"
+ },
+ {
+ "arm64",
+ CPU_TYPE_ARM64,
+ CPU_SUBTYPE_ARM64_ALL,
+ NX_LittleEndian,
+ "ARM64"
+ },
+ {
+ "arm64e",
+ CPU_TYPE_ARM64,
+ CPU_SUBTYPE_ARM64_E,
+ NX_LittleEndian,
+ "ARM64e"
+ },
+ {
+ "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) {
+ const NXArchInfo *candidate = NULL;
+ for (int arch = 0; arch < kNumArchitectures; ++arch) {
+ if (kKnownArchitectures[arch].cputype == cputype) {
+ if (kKnownArchitectures[arch].cpusubtype == cpusubtype) {
+ return &kKnownArchitectures[arch];
+ }
+ if (!candidate) {
+ candidate = &kKnownArchitectures[arch];
+ }
+ }
+ }
+ return candidate;
+}
+
+struct fat_arch *NXFindBestFatArch(cpu_type_t cputype,
+ cpu_subtype_t cpusubtype,
+ struct fat_arch *fat_archs,
+ uint32_t nfat_archs) {
+ struct fat_arch *candidate = NULL;
+ for (uint32_t f = 0; f < nfat_archs; ++f) {
+ if (fat_archs[f].cputype == cputype) {
+ if (fat_archs[f].cpusubtype == cpusubtype) {
+ return &fat_archs[f];
+ }
+ if (!candidate) {
+ candidate = &fat_archs[f];
+ }
+ }
+ }
+ return candidate;
+}
+#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
new file mode 100644
index 0000000000..397c1f5873
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/mac/arch_utilities.h
@@ -0,0 +1,47 @@
+// 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
new file mode 100644
index 0000000000..d875d95b5f
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/mac/bootstrap_compat.cc
@@ -0,0 +1,42 @@
+// 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
new file mode 100644
index 0000000000..8ca7357c34
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/mac/bootstrap_compat.h
@@ -0,0 +1,54 @@
+// 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
new file mode 100644
index 0000000000..b7bbc0b95b
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/mac/byteswap.h
@@ -0,0 +1,73 @@
+// -*- 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
new file mode 100644
index 0000000000..3c48f23528
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/mac/dump_syms.cc
@@ -0,0 +1,679 @@
+// -*- 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.cc: Create a symbol file for use with minidumps
+
+#include "common/mac/dump_syms.h"
+
+#include <assert.h>
+#include <dirent.h>
+#include <errno.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/dwarf_range_list_handler.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/path_helper.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::DwarfRangeListHandler;
+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 & ~CPU_SUBTYPE_MASK;
+ 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 range handler that accepts rangelist data parsed by
+// dwarf2reader::RangeListReader and populates a range vector (typically
+// owned by a function) with the results.
+class DumpSymbols::DumperRangesHandler:
+ public DwarfCUToModule::RangesHandler {
+ public:
+ DumperRangesHandler(const uint8_t *buffer, uint64 size,
+ dwarf2reader::ByteReader* reader)
+ : buffer_(buffer), size_(size), reader_(reader) { }
+
+ bool ReadRanges(uint64 offset, Module::Address base_address,
+ vector<Module::Range>* ranges) {
+ DwarfRangeListHandler handler(base_address, ranges);
+ dwarf2reader::RangeListReader rangelist_reader(buffer_, size_, reader_,
+ &handler);
+
+ return rangelist_reader.ReadRangeList(offset);
+ }
+
+ private:
+ const uint8_t *buffer_;
+ uint64 size_;
+ dwarf2reader::ByteReader* reader_;
+};
+
+// 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 = google_breakpad::BaseName(object_filename_);
+
+ // 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;
+}
+
+void 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");
+ // There had better be a __debug_info section!
+ if (debug_info_entry == file_context.section_map().end()) {
+ fprintf(stderr, "%s: __DWARF segment of file has no __debug_info section\n",
+ selected_object_name_.c_str());
+ return;
+ }
+ const std::pair<const uint8_t*, uint64>& debug_info_section =
+ debug_info_entry->second;
+
+ // Build a line-to-module loader for the root handler to use.
+ DumperLineToModule line_to_module(&byte_reader);
+
+ // Optional .debug_ranges reader
+ scoped_ptr<DumperRangesHandler> ranges_handler;
+ dwarf2reader::SectionMap::const_iterator ranges_entry =
+ file_context.section_map().find("__debug_ranges");
+ if (ranges_entry != file_context.section_map().end()) {
+ const std::pair<const uint8_t *, uint64>& ranges_section =
+ ranges_entry->second;
+ ranges_handler.reset(
+ new DumperRangesHandler(ranges_section.first, ranges_section.second,
+ &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,
+ ranges_handler.get(), &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();
+ }
+}
+
+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) {
+ dumper_.ReadDwarf(module_, reader_, section_map, handle_inter_cu_refs_);
+ }
+ 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
new file mode 100644
index 0000000000..1e57f86ddd
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/mac/dump_syms.h
@@ -0,0 +1,196 @@
+// -*- 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 DumperRangesHandler;
+ 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|.
+ void 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
new file mode 100644
index 0000000000..4661d5d625
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/mac/file_id.cc
@@ -0,0 +1,106 @@
+// 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
new file mode 100644
index 0000000000..5d60e84c9a
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/mac/file_id.h
@@ -0,0 +1,81 @@
+// 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
new file mode 100644
index 0000000000..245be82659
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/mac/launch_reporter.cc
@@ -0,0 +1,84 @@
+// 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
new file mode 100644
index 0000000000..4531123c2d
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/mac/launch_reporter.h
@@ -0,0 +1,43 @@
+// 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
new file mode 100644
index 0000000000..c396ad888d
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/mac/macho_id.cc
@@ -0,0 +1,369 @@
+// 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
new file mode 100644
index 0000000000..1037549124
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/mac/macho_id.h
@@ -0,0 +1,131 @@
+// 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
new file mode 100644
index 0000000000..91e1fdd2b2
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/mac/macho_reader.cc
@@ -0,0 +1,558 @@
+// 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>
+
+#include <limits>
+
+// 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);
+ cursor
+ .Read(word_size, false, &segment.vmaddr)
+ .Read(word_size, false, &segment.vmsize)
+ .Read(word_size, false, &segment.fileoff)
+ .Read(word_size, false, &segment.filesize);
+ cursor >> segment.maxprot
+ >> segment.initprot
+ >> segment.nsects
+ >> segment.flags;
+ if (!cursor) {
+ reporter_->LoadCommandTooShort(index, type);
+ return false;
+ }
+ if (segment.fileoff > buffer_.Size() ||
+ segment.filesize > buffer_.Size() - segment.fileoff) {
+ 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 (segment.fileoff == 0 && segment.filesize == 0) {
+ segment.contents.start = segment.contents.end = NULL;
+ } else {
+ segment.contents.start = buffer_.start + segment.fileoff;
+ segment.contents.end = segment.contents.start + segment.filesize;
+ }
+ // 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, offset;
+ uint32_t dummy32;
+ cursor
+ .CString(&section.section_name, 16)
+ .CString(&section.segment_name, 16)
+ .Read(word_size, false, &section.address)
+ .Read(word_size, false, &size)
+ .Read(sizeof(uint32_t), false, &offset) // clears high bits of |offset|
+ >> section.align
+ >> dummy32
+ >> dummy32
+ >> section.flags
+ >> dummy32
+ >> dummy32;
+ if (section.bits_64)
+ cursor >> dummy32;
+ if (!cursor) {
+ reporter_->SectionsMissing(segment.name);
+ return false;
+ }
+
+ // Even 64-bit Mach-O isn’t a true 64-bit format in that it doesn’t handle
+ // 64-bit file offsets gracefully. Segment load commands do contain 64-bit
+ // file offsets, but sections within do not. Because segments load
+ // contiguously, recompute each section’s file offset on the basis of its
+ // containing segment’s file offset and the difference between the section’s
+ // and segment’s load addresses. If truncation is detected, honor the
+ // recomputed offset.
+ if (segment.bits_64 &&
+ segment.fileoff + segment.filesize >
+ std::numeric_limits<uint32_t>::max()) {
+ const uint64_t section_offset_recomputed =
+ segment.fileoff + section.address - segment.vmaddr;
+ if (offset == static_cast<uint32_t>(section_offset_recomputed)) {
+ offset = section_offset_recomputed;
+ }
+ }
+
+ 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
new file mode 100644
index 0000000000..145d17d1f2
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/mac/macho_reader.h
@@ -0,0 +1,464 @@
+// -*- 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 file offset and size of the segment in the Mach-O image.
+ uint64_t fileoff;
+ uint64_t filesize;
+
+ // 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
new file mode 100644
index 0000000000..d8459d8cd4
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/mac/macho_reader_unittest.cc
@@ -0,0 +1,1902 @@
+// 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_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_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
new file mode 100644
index 0000000000..f56fe768c1
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/mac/macho_utilities.cc
@@ -0,0 +1,155 @@
+// 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
new file mode 100644
index 0000000000..00563a77c8
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/mac/macho_utilities.h
@@ -0,0 +1,95 @@
+// 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
new file mode 100644
index 0000000000..a30f52c7e5
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/mac/macho_walker.cc
@@ -0,0 +1,272 @@
+// 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);
+
+ header.cpusubtype &= ~CPU_SUBTYPE_MASK;
+
+ 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);
+
+ arch.cpusubtype &= ~CPU_SUBTYPE_MASK;
+
+ 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
new file mode 100644
index 0000000000..dd535814a1
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/mac/macho_walker.h
@@ -0,0 +1,119 @@
+// 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
new file mode 100644
index 0000000000..23fc2207a4
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/mac/moz.build
@@ -0,0 +1,27 @@
+# -*- 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',
+]
+
+SOURCES += [
+ 'bootstrap_compat.cc',
+ 'HTTPMultipartUpload.m',
+ 'MachIPC.mm',
+ 'string_utilities.cc',
+]
+
+Library('breakpad_mac_common_s')
+
+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
new file mode 100644
index 0000000000..d6d1bef971
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/mac/scoped_task_suspend-inl.h
@@ -0,0 +1,56 @@
+// 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
new file mode 100644
index 0000000000..07c0f42680
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/mac/string_utilities.cc
@@ -0,0 +1,84 @@
+// 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
new file mode 100644
index 0000000000..6d89c834e7
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/mac/string_utilities.h
@@ -0,0 +1,52 @@
+// 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
new file mode 100644
index 0000000000..501c8652a1
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/mac/super_fat_arch.h
@@ -0,0 +1,88 @@
+// 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
new file mode 100644
index 0000000000..ce3d9022cd
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/mac/testing/GTMSenTestCase.h
@@ -0,0 +1,1110 @@
+//
+// 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
new file mode 100644
index 0000000000..162f01e97c
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/mac/testing/GTMSenTestCase.m
@@ -0,0 +1,428 @@
+//
+// 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/macros.h b/toolkit/crashreporter/google-breakpad/src/common/macros.h
new file mode 100644
index 0000000000..14bb3f7bd3
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/macros.h
@@ -0,0 +1,45 @@
+// Copyright (c) 2019, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef BREAKPAD_COMMON_MACROS_H_
+#define BREAKPAD_COMMON_MACROS_H_
+
+// Ensure that this macro definition stays in a private header file: clang
+// suggests the first macro expanding to [[clang::fallthrough]] in its
+// diagnostics, so if BP_FALLTHROUGH is visible in code depending on breakpad,
+// clang would suggest BP_FALLTHROUGH for code depending on breakpad, instead of
+// the client code's own fallthrough macro.
+// TODO(thakis): Once everyone uses C++17, use its [[fallthrough]] instead.
+#if defined(__clang__)
+#define BP_FALLTHROUGH [[clang::fallthrough]]
+#else
+#define BP_FALLTHROUGH
+#endif
+
+#endif // BREAKPAD_COMMON_MACROS_H_
diff --git a/toolkit/crashreporter/google-breakpad/src/common/md5.cc b/toolkit/crashreporter/google-breakpad/src/common/md5.cc
new file mode 100644
index 0000000000..4f1ac8cad4
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/md5.cc
@@ -0,0 +1,251 @@
+/*
+ * 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 */
+ memcpy(&ctx->in[14], &ctx->bits[0], sizeof(u32));
+ memcpy(&ctx->in[15], &ctx->bits[1], sizeof(u32));
+
+ 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
new file mode 100644
index 0000000000..2ab0ab95ae
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/md5.h
@@ -0,0 +1,27 @@
+// 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_allocator.h b/toolkit/crashreporter/google-breakpad/src/common/memory_allocator.h
new file mode 100644
index 0000000000..b7f9168c14
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/memory_allocator.h
@@ -0,0 +1,252 @@
+// 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_ALLOCATOR_H_
+#define GOOGLE_BREAKPAD_COMMON_MEMORY_ALLOCATOR_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
+
+#if defined(__APPLE__) || defined(__FreeBSD__)
+#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 {
+ using AllocatorTraits = std::allocator_traits<std::allocator<T>>;
+ using value_type = typename AllocatorTraits::value_type;
+ using pointer = typename AllocatorTraits::pointer;
+ using difference_type = typename AllocatorTraits::difference_type;
+ using size_type = typename AllocatorTraits::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_ALLOCATOR_H_
diff --git a/toolkit/crashreporter/google-breakpad/src/common/memory_allocator_unittest.cc b/toolkit/crashreporter/google-breakpad/src/common/memory_allocator_unittest.cc
new file mode 100644
index 0000000000..43c86314c6
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/memory_allocator_unittest.cc
@@ -0,0 +1,124 @@
+// 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_allocator.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/memory_range.h b/toolkit/crashreporter/google-breakpad/src/common/memory_range.h
new file mode 100644
index 0000000000..41dd2da622
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/memory_range.h
@@ -0,0 +1,145 @@
+// 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
new file mode 100644
index 0000000000..f6cf8c8b2a
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/memory_range_unittest.cc
@@ -0,0 +1,193 @@
+// 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/minidump_type_helper.h b/toolkit/crashreporter/google-breakpad/src/common/minidump_type_helper.h
new file mode 100644
index 0000000000..5a7d5a6a87
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/minidump_type_helper.h
@@ -0,0 +1,56 @@
+// 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
new file mode 100644
index 0000000000..a3544029cb
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/module.cc
@@ -0,0 +1,387 @@
+// 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::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::SetAddressRanges(const vector<Range>& ranges) {
+ address_ranges_ = ranges;
+}
+
+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());
+
+ if (!AddressIsInModule(function->address)) {
+ return;
+ }
+
+ // 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.
+ for (const Range& range : function->ranges) {
+ Extern debug_ext(range.address);
+ ExternSet::iterator it_debug = externs_.lower_bound(&ext);
+ assert(it_debug == externs_.end() ||
+ (*it_debug)->address >= range.address + range.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) {
+ if (!AddressIsInModule(stack_frame_entry->address)) {
+ return;
+ }
+
+ 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) {
+ if (!AddressIsInModule(ext->address)) {
+ return;
+ }
+
+ 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::AddressIsInModule(Address address) const {
+ if (address_ranges_.empty()) {
+ return true;
+ }
+ for (const auto& segment : address_ranges_) {
+ if (address >= segment.address &&
+ address < segment.address + segment.size) {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool Module::Write(std::ostream &stream, SymbolData symbol_data) {
+ stream << "MODULE " << os_ << " " << architecture_ << " "
+ << id_ << " " << name_ << "\n";
+ if (!stream.good())
+ return ReportError();
+
+ if (!code_id_.empty()) {
+ stream << "INFO CODE_ID " << code_id_ << "\n";
+ }
+
+ 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 << "\n";
+ 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;
+ vector<Line>::iterator line_it = func->lines.begin();
+ for (auto range_it = func->ranges.cbegin();
+ range_it != func->ranges.cend(); ++range_it) {
+ stream << "FUNC " << hex
+ << (range_it->address - load_address_) << " "
+ << range_it->size << " "
+ << func->parameter_size << " "
+ << func->name << dec << "\n";
+
+ if (!stream.good())
+ return ReportError();
+
+ while ((line_it != func->lines.end()) &&
+ (line_it->address >= range_it->address) &&
+ (line_it->address < (range_it->address + range_it->size))) {
+ stream << hex
+ << (line_it->address - load_address_) << " "
+ << line_it->size << " "
+ << dec
+ << line_it->number << " "
+ << line_it->file->source_id << "\n";
+
+ if (!stream.good())
+ return ReportError();
+
+ ++line_it;
+ }
+ }
+ }
+
+ // 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 << "\n";
+ }
+ }
+
+ 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 << "\n";
+
+ // 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 << "\n";
+ }
+ }
+ }
+
+ 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
new file mode 100644
index 0000000000..3775860526
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/module.h
@@ -0,0 +1,376 @@
+// -*- 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;
+ };
+
+ // An address range.
+ struct Range {
+ Range(const Address address_input, const Address size_input) :
+ address(address_input), size(size_input) { }
+
+ Address address;
+ Address size;
+ };
+
+ // A function.
+ struct Function {
+ Function(const string &name_input, const Address &address_input) :
+ name(name_input), address(address_input), 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.
+ string name;
+
+ // The start address and the address ranges covered by the function.
+ const Address address;
+ vector<Range> ranges;
+
+ // 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);
+
+ // Sets address filtering on elements added to the module. This allows
+ // libraries with extraneous debug symbols to generate symbol files containing
+ // only relevant symbols. For example, an LLD-generated partition library may
+ // contain debug information pertaining to all partitions derived from a
+ // single "combined" library. Filtering applies only to elements added after
+ // this method is called.
+ void SetAddressRanges(const vector<Range>& ranges);
+
+ // 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);
+
+ // Returns true of the specified address resides with an specified address
+ // range, or if no ranges have been specified.
+ bool AddressIsInModule(Address address) const;
+
+ // 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_;
+
+ // The set of valid address ranges of the module. If specified, attempts to
+ // add elements residing outside these ranges will be silently filtered.
+ vector<Range> address_ranges_;
+
+ // 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
new file mode 100644
index 0000000000..b855f186ba
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/module_unittest.cc
@@ -0,0 +1,674 @@
+// 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 = 0xd35402aac7a7ad5cULL;
+ const Module::Address DUP_SIZE = 0x200b26e605f99071ULL;
+ const Module::Address DUP_PARAMETER_SIZE = 0xf14ac4fed48c4a99ULL;
+
+ Module::Function* function = new Module::Function(name, DUP_ADDRESS);
+ Module::Range range(DUP_ADDRESS, DUP_SIZE);
+ function->ranges.push_back(range);
+ 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", 0xe165bf8023b9d9abULL);
+ Module::Range range(0xe165bf8023b9d9abULL, 0x1e4bb0eb1cbf5b09ULL);
+ function->ranges.push_back(range);
+ function->parameter_size = 0x772beee89114358aULL;
+ Module::Line line = { 0xe165bf8023b9d9abULL, 0x1e4bb0eb1cbf5b09ULL,
+ 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)", 0xbec774ea5dd935f3ULL);
+ Module::Range range(0xbec774ea5dd935f3ULL, 0x2922088f98d3f6fcULL);
+ function->ranges.push_back(range);
+ function->parameter_size = 0xe5e9aa008bd5f0d0ULL;
+
+ // Some source lines. The module should not sort these.
+ Module::Line line1 = { 0xbec774ea5dd935f3ULL, 0x1c2be6d6c5af2611ULL,
+ file1, 41676901 };
+ Module::Line line2 = { 0xdaf35bc123885c04ULL, 0xcf621b8d324d0ebULL,
+ 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(0x2ab698b0b6407073ULL);
+
+ 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", 0x9b926d464f0b9384ULL);
+ Module::Range range(0x9b926d464f0b9384ULL, 0x4f524a4ba795e6a6ULL);
+ function->ranges.push_back(range);
+ function->parameter_size = 0xbbe8133a6641c9b7ULL;
+
+ // Source files that refer to some files, but not others.
+ Module::Line line1 = { 0xab415089485e1a20ULL, 0x126e3124979291f2ULL,
+ file1, 137850127 };
+ Module::Line line2 = { 0xb2675b5c3c2ed33fULL, 0x1df77f5551dbd68cULL,
+ 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"
+ "ab415089485e1a20 126e3124979291f2 137850127 0\n"
+ "b2675b5c3c2ed33f 1df77f5551dbd68c 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)", 0xbec774ea5dd935f3ULL);
+ Module::Range range(0xbec774ea5dd935f3ULL, 0x2922088f98d3f6fcULL);
+ function->ranges.push_back(range);
+ function->parameter_size = 0xe5e9aa008bd5f0d0ULL;
+
+ // Some source lines. The module should not sort these.
+ Module::Line line1 = { 0xbec774ea5dd935f3ULL, 0x1c2be6d6c5af2611ULL,
+ 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(0x2ab698b0b6407073ULL);
+
+ 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", 0xd35024aa7ca7da5cULL);
+ Module::Range r1(0xd35024aa7ca7da5cULL, 0x200b26e605f99071ULL);
+ function1->ranges.push_back(r1);
+ function1->parameter_size = 0xf14ac4fed48c4a99ULL;
+
+ Module::Function* function2 = new Module::Function(
+ "_and_void", 0x2987743d0b35b13fULL);
+ Module::Range r2(0x2987743d0b35b13fULL, 0xb369db048deb3010ULL);
+ function2->ranges.push_back(r2);
+ function2->parameter_size = 0x938e556cb5a79988ULL;
+
+ // 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);
+ Module::Range range(0xfff0, 0x10);
+ function->ranges.push_back(range);
+ 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);
+ Module::Range range(0xfff0, 0x10);
+ function->ranges.push_back(range);
+ 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(Write, OutOfRangeAddresses) {
+ stringstream s;
+ Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID);
+
+ // Specify an allowed address range, representing a PT_LOAD segment in a
+ // module.
+ vector<Module::Range> address_ranges = {
+ Module::Range(0x2000ULL, 0x1000ULL),
+ };
+ m.SetAddressRanges(address_ranges);
+
+ // Add three stack frames (one lower, one in, and one higher than the allowed
+ // address range). Only the middle frame should be captured.
+ Module::StackFrameEntry* entry1 = new Module::StackFrameEntry();
+ entry1->address = 0x1000ULL;
+ entry1->size = 0x100ULL;
+ m.AddStackFrameEntry(entry1);
+ Module::StackFrameEntry* entry2 = new Module::StackFrameEntry();
+ entry2->address = 0x2000ULL;
+ entry2->size = 0x100ULL;
+ m.AddStackFrameEntry(entry2);
+ Module::StackFrameEntry* entry3 = new Module::StackFrameEntry();
+ entry3->address = 0x3000ULL;
+ entry3->size = 0x100ULL;
+ m.AddStackFrameEntry(entry3);
+
+ // Add a function outside the allowed range.
+ Module::File* file = m.FindFile("file_name.cc");
+ Module::Function* function = new Module::Function(
+ "function_name", 0x4000ULL);
+ Module::Range range(0x4000ULL, 0x1000ULL);
+ function->ranges.push_back(range);
+ function->parameter_size = 0x100ULL;
+ Module::Line line = { 0x4000ULL, 0x100ULL, file, 67519080 };
+ function->lines.push_back(line);
+ m.AddFunction(function);
+
+ // Add an extern outside the allowed range.
+ Module::Extern* extern1 = new Module::Extern(0x5000ULL);
+ extern1->name = "_xyz";
+ m.AddExtern(extern1);
+
+ m.Write(s, ALL_SYMBOL_DATA);
+
+ EXPECT_STREQ("MODULE os-name architecture id-string name with spaces\n"
+ "STACK CFI INIT 2000 100 \n",
+ s.str().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
new file mode 100644
index 0000000000..d3b55045d1
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/moz.build
@@ -0,0 +1,19 @@
+# -*- 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 += [
+ 'convert_UTF.cc',
+ 'string_conversion.cc',
+]
+
+if CONFIG['OS_ARCH'] == 'Darwin':
+ UNIFIED_SOURCES += [
+ 'md5.cc',
+ ]
+
+Library('breakpad_common_s')
+
+include('/toolkit/crashreporter/crashreporter.mozbuild')
diff --git a/toolkit/crashreporter/google-breakpad/src/common/path_helper.cc b/toolkit/crashreporter/google-breakpad/src/common/path_helper.cc
new file mode 100644
index 0000000000..61a6e31846
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/path_helper.cc
@@ -0,0 +1,55 @@
+// Copyright 2017, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "common/path_helper.h"
+
+#include <assert.h>
+#include <libgen.h>
+#include <stdlib.h>
+#include <string.h>
+
+namespace google_breakpad {
+
+string BaseName(const string& path) {
+ char* path_tmp = strdup(path.c_str());
+ assert(path_tmp);
+ string result(basename(path_tmp));
+ free(path_tmp);
+ return result;
+}
+
+string DirName(const string& path) {
+ char* path_tmp = strdup(path.c_str());
+ assert(path_tmp);
+ string result(dirname(path_tmp));
+ free(path_tmp);
+ return result;
+}
+
+} // namespace google_breakpad
diff --git a/toolkit/crashreporter/google-breakpad/src/common/path_helper.h b/toolkit/crashreporter/google-breakpad/src/common/path_helper.h
new file mode 100644
index 0000000000..2166ba018a
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/path_helper.h
@@ -0,0 +1,44 @@
+// Copyright 2017, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_BREAKPAD_COMMON_PATH_HELPER_H
+#define GOOGLE_BREAKPAD_COMMON_PATH_HELPER_H
+
+#include <string>
+
+#include "common/using_std_string.h"
+
+namespace google_breakpad {
+
+string BaseName(const string& path);
+string DirName(const string& path);
+
+} // namespace google_breakpad
+
+#endif // GOOGLE_BREAKPAD_COMMON_PATH_HELPER_H
diff --git a/toolkit/crashreporter/google-breakpad/src/common/scoped_ptr.h b/toolkit/crashreporter/google-breakpad/src/common/scoped_ptr.h
new file mode 100644
index 0000000000..d137c18681
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/scoped_ptr.h
@@ -0,0 +1,404 @@
+// 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
new file mode 100644
index 0000000000..e0a74ceeb4
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/simple_string_dictionary.cc
@@ -0,0 +1,45 @@
+// 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
new file mode 100644
index 0000000000..9484920537
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/simple_string_dictionary.h
@@ -0,0 +1,279 @@
+// 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;
+
+ size_t index = GetEntryIndexForKey(key);
+ if (index == num_entries)
+ return NULL;
+
+ return entries_[index].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. Returns an index into the map that can be used
+ // to quickly access the entry, or |num_entries| on failure or when clearing
+ // a key with a null value.
+ size_t SetKeyValue(const char* key, const char* value) {
+ if (!value) {
+ RemoveKey(key);
+ return num_entries;
+ }
+
+ assert(key);
+ if (!key)
+ return num_entries;
+
+ // Key must not be an empty string.
+ assert(key[0] != '\0');
+ if (key[0] == '\0')
+ return num_entries;
+
+ size_t entry_index = GetEntryIndexForKey(key);
+
+ // If it does not yet exist, attempt to insert it.
+ if (entry_index == num_entries) {
+ for (size_t i = 0; i < num_entries; ++i) {
+ if (!entries_[i].is_active()) {
+ entry_index = i;
+ Entry* 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_index == num_entries)
+ return num_entries;
+
+#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(entries_[entry_index].value, value, value_size);
+ entries_[entry_index].value[value_size - 1] = '\0';
+
+ return entry_index;
+ }
+
+ // Sets a value for a key that has already been set with SetKeyValue(), using
+ // the index returned from that function.
+ void SetValueAtIndex(size_t index, const char* value) {
+ assert(index < num_entries);
+ if (index >= num_entries)
+ return;
+
+ Entry* entry = &entries_[index];
+ assert(entry->key[0] != '\0');
+
+ 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. This invalidates the index
+ // returned by SetKeyValue().
+ bool RemoveKey(const char* key) {
+ assert(key);
+ if (!key)
+ return false;
+
+ return RemoveAtIndex(GetEntryIndexForKey(key));
+ }
+
+ // Removes a value and key using an index that was returned from
+ // SetKeyValue(). After a call to this function, the index is invalidated.
+ bool RemoveAtIndex(size_t index) {
+ if (index >= num_entries)
+ return false;
+
+ entries_[index].key[0] = '\0';
+ entries_[index].value[0] = '\0';
+ return true;
+ }
+
+ // 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:
+ size_t GetEntryIndexForKey(const char* key) const {
+ for (size_t i = 0; i < num_entries; ++i) {
+ if (strncmp(key, entries_[i].key, key_size) == 0) {
+ return i;
+ }
+ }
+ return num_entries;
+ }
+
+ 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
new file mode 100644
index 0000000000..e7b8fd7632
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/simple_string_dictionary_unittest.cc
@@ -0,0 +1,339 @@
+// 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"));
+}
+
+TEST(NonAllocatingMapTest, ByIndex) {
+ NonAllocatingMap<10, 10, 3> map;
+
+ size_t index1 = map.SetKeyValue("test", "one");
+ EXPECT_TRUE(index1 >= 0 && index1 <= map.num_entries);
+
+ size_t index2 = map.SetKeyValue("moo", "foo");
+ EXPECT_TRUE(index2 >= 0 && index2 <= map.num_entries);
+ EXPECT_NE(index1, index2);
+
+ size_t index3 = map.SetKeyValue("blob", "kebab");
+ EXPECT_TRUE(index3 >= 0 && index3 <= map.num_entries);
+ EXPECT_NE(index2, index3);
+
+ size_t index4 = map.SetKeyValue("nogo", "full");
+ EXPECT_TRUE(index4 == map.num_entries);
+
+ EXPECT_STREQ("one", map.GetValueForKey("test"));
+ EXPECT_STREQ("foo", map.GetValueForKey("moo"));
+ EXPECT_STREQ("kebab", map.GetValueForKey("blob"));
+
+ map.SetValueAtIndex(index2, "booo");
+ EXPECT_STREQ("booo", map.GetValueForKey("moo"));
+
+ EXPECT_TRUE(map.RemoveAtIndex(index1));
+ EXPECT_FALSE(map.GetValueForKey("test"));
+
+ EXPECT_FALSE(map.RemoveAtIndex(map.num_entries));
+ EXPECT_FALSE(map.RemoveAtIndex(9999));
+}
+
+#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
new file mode 100644
index 0000000000..168d0b2879
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/solaris/dump_symbols.cc
@@ -0,0 +1,681 @@
+// 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
new file mode 100644
index 0000000000..7f4baadcfc
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/solaris/dump_symbols.h
@@ -0,0 +1,49 @@
+// 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
new file mode 100644
index 0000000000..643a14629d
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/solaris/file_id.cc
@@ -0,0 +1,197 @@
+// 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
new file mode 100644
index 0000000000..375e857512
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/solaris/file_id.h
@@ -0,0 +1,66 @@
+// 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
new file mode 100644
index 0000000000..e9e6c6f5d2
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/solaris/guid_creator.cc
@@ -0,0 +1,84 @@
+// 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
new file mode 100644
index 0000000000..4aee3a1c24
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/solaris/guid_creator.h
@@ -0,0 +1,50 @@
+// 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
new file mode 100644
index 0000000000..3e3b1d4652
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/solaris/message_output.h
@@ -0,0 +1,54 @@
+// 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/stabs_reader.cc b/toolkit/crashreporter/google-breakpad/src/common/stabs_reader.cc
new file mode 100644
index 0000000000..6019fc7ee2
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/stabs_reader.cc
@@ -0,0 +1,315 @@
+// 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
new file mode 100644
index 0000000000..98ee2dd53b
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/stabs_reader.h
@@ -0,0 +1,325 @@
+// -*- 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
new file mode 100644
index 0000000000..a84da1c4ca
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/stabs_reader_unittest.cc
@@ -0,0 +1,611 @@
+// 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
new file mode 100644
index 0000000000..049a6cc63e
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/stabs_to_module.cc
@@ -0,0 +1,199 @@
+// 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);
+ Module::Range r(address, 0); // We compute this in StabsToModule::Finalize().
+ f->ranges.push_back(r);
+ 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->ranges[0].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->ranges[0].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->ranges[0].address + f->ranges[0].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
new file mode 100644
index 0000000000..5e04fa7927
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/stabs_to_module.h
@@ -0,0 +1,143 @@
+// -*- 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
new file mode 100644
index 0000000000..aae0047667
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/stabs_to_module_unittest.cc
@@ -0,0 +1,258 @@
+// 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->ranges[0].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->ranges[0].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->ranges[0].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->ranges[0].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
new file mode 100644
index 0000000000..a3dd50aab6
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/stdio_wrapper.h
@@ -0,0 +1,43 @@
+// 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
new file mode 100644
index 0000000000..11d60a3664
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/string_conversion.cc
@@ -0,0 +1,155 @@
+// 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();
+ 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 + 1;
+ uint16_t *target_ptr = out;
+ uint16_t *target_end_ptr = target_ptr + 2;
+ 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();
+ 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;
+ 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
new file mode 100644
index 0000000000..b9ba96a2e1
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/string_conversion.h
@@ -0,0 +1,68 @@
+// 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/string_conversion_unittest.cc b/toolkit/crashreporter/google-breakpad/src/common/string_conversion_unittest.cc
new file mode 100644
index 0000000000..e9f9b55d95
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/string_conversion_unittest.cc
@@ -0,0 +1,64 @@
+// Copyright (c) 2019, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// string_conversion_unittest.cc: Unit tests for google_breakpad::UTF* helpers.
+
+#include <string>
+#include <vector>
+
+#include "breakpad_googletest_includes.h"
+#include "common/string_conversion.h"
+
+using google_breakpad::UTF8ToUTF16;
+using google_breakpad::UTF8ToUTF16Char;
+using google_breakpad::UTF16ToUTF8;
+using std::vector;
+
+TEST(StringConversionTest, UTF8ToUTF16) {
+ const char in[] = "aßc";
+ vector<uint16_t> out;
+ vector<uint16_t> exp{'a', 0xdf, 'c', 0};
+ UTF8ToUTF16(in, &out);
+ EXPECT_EQ(4u, out.size());
+ EXPECT_EQ(exp, out);
+}
+
+TEST(StringConversionTest, UTF8ToUTF16Char) {
+ const char in[] = "a";
+ uint16_t out[3] = {0xff, 0xff, 0xff};
+ EXPECT_EQ(1, UTF8ToUTF16Char(in, 1, out));
+ EXPECT_EQ('a', out[0]);
+ EXPECT_EQ(0, out[1]);
+ EXPECT_EQ(0xff, out[2]);
+}
+
+TEST(StringConversionTest, UTF16ToUTF8) {
+ vector<uint16_t> in{'a', 0xdf, 'c', 0};
+ EXPECT_EQ("aßc", UTF16ToUTF8(in, false));
+}
diff --git a/toolkit/crashreporter/google-breakpad/src/common/symbol_data.h b/toolkit/crashreporter/google-breakpad/src/common/symbol_data.h
new file mode 100644
index 0000000000..2cf15a855d
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/symbol_data.h
@@ -0,0 +1,42 @@
+// -*- 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
new file mode 100644
index 0000000000..1e783b45c5
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/test_assembler.cc
@@ -0,0 +1,359 @@
+// 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
new file mode 100644
index 0000000000..373dbebacd
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/test_assembler.h
@@ -0,0 +1,484 @@
+// -*- 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
new file mode 100644
index 0000000000..94b5a5ce5f
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/test_assembler_unittest.cc
@@ -0,0 +1,1662 @@
+// 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
new file mode 100644
index 0000000000..05538f961b
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/testdata/func-line-pairing.h
@@ -0,0 +1,676 @@
+// -*- 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
new file mode 100644
index 0000000000..1df88db8bd
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/tests/auto_tempdir.h
@@ -0,0 +1,100 @@
+// 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
new file mode 100644
index 0000000000..1c041777cb
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/tests/file_utils.cc
@@ -0,0 +1,153 @@
+// 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
new file mode 100644
index 0000000000..c98a9bfa8b
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/tests/file_utils.h
@@ -0,0 +1,52 @@
+// 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
new file mode 100644
index 0000000000..c9cbd58546
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/unordered.h
@@ -0,0 +1,62 @@
+// 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 __gnu_cxx::hash_map<T, U, H> {};
+template <class T, class H = __gnu_cxx::hash<T> >
+struct unordered_set : public __gnu_cxx::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
new file mode 100644
index 0000000000..13c1da59cc
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/using_std_string.h
@@ -0,0 +1,65 @@
+// -*- 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
new file mode 100644
index 0000000000..5f7594b161
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/windows/common_windows.gyp
@@ -0,0 +1,112 @@
+# 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',
+ 'module_info.h',
+ 'omap.cc',
+ 'omap.h',
+ 'omap_internal.h',
+ 'pdb_source_line_writer.cc',
+ 'pdb_source_line_writer.h',
+ 'pe_source_line_writer.cc',
+ 'pe_source_line_writer.h',
+ 'pe_util.h',
+ 'pe_util.cc',
+ 'string_utils.cc',
+ 'string_utils-inl.h',
+ 'symbol_collector_client.cc',
+ 'symbol_collector_client.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
new file mode 100644
index 0000000000..ed8cb5b658
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/windows/dia_util.cc
@@ -0,0 +1,92 @@
+// 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
new file mode 100644
index 0000000000..b9e0df2d56
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/windows/dia_util.h
@@ -0,0 +1,64 @@
+// Copyright 2013 Google Inc. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// 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
new file mode 100644
index 0000000000..b7f877e66e
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/windows/guid_string.cc
@@ -0,0 +1,76 @@
+// 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
new file mode 100644
index 0000000000..48a5c1d370
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/windows/guid_string.h
@@ -0,0 +1,58 @@
+// 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
new file mode 100644
index 0000000000..5df17e1a88
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/windows/http_upload.cc
@@ -0,0 +1,493 @@
+// 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 <vector>
+
+#include "common/windows/string_utils-inl.h"
+
+#include "common/windows/http_upload.h"
+
+namespace {
+ using std::string;
+ using std::wstring;
+ using std::map;
+ using std::vector;
+ using std::ifstream;
+ using std::ios;
+
+ const wchar_t kUserAgent[] = L"Breakpad/1.0 (Windows)";
+
+ // Helper class which closes an internet handle when it goes away
+ class AutoInternetHandle {
+ public:
+ explicit AutoInternetHandle(HINTERNET handle) : handle_(handle) {}
+ ~AutoInternetHandle() {
+ if (handle_) {
+ InternetCloseHandle(handle_);
+ }
+ }
+
+ HINTERNET get() { return handle_; }
+
+ private:
+ HINTERNET handle_;
+ };
+
+ wstring 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;
+ }
+
+ string 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;
+ }
+
+ bool 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;
+ }
+
+ // Converts a UTF16 string to UTF8.
+ string WideToUTF8(const wstring &wide) {
+ return WideToMBCP(wide, CP_UTF8);
+ }
+
+ bool 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;
+ }
+
+ bool SendRequestInner(
+ const wstring& url,
+ const wstring& http_method,
+ const wstring& content_type_header,
+ const string& request_body,
+ int* timeout_ms,
+ wstring* response_body,
+ int* response_code) {
+ if (response_code) {
+ *response_code = 0;
+ }
+
+ // Break up the URL and make sure we can handle it
+ wchar_t scheme[16], host[256], path[1024];
+ 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)) {
+ DWORD err = GetLastError();
+ wprintf(L"%d\n", err);
+ 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(),
+ http_method.c_str(),
+ path,
+ NULL, // version
+ NULL, // referer
+ NULL, // agent type
+ http_open_flags,
+ NULL)); // context
+ if (!request.get()) {
+ return false;
+ }
+
+ if (!content_type_header.empty()) {
+ HttpAddRequestHeaders(request.get(),
+ content_type_header.c_str(),
+ static_cast<DWORD>(-1),
+ HTTP_ADDREQ_FLAG_ADD);
+ }
+
+ if (timeout_ms) {
+ if (!InternetSetOption(request.get(),
+ INTERNET_OPTION_SEND_TIMEOUT,
+ timeout_ms,
+ sizeof(*timeout_ms))) {
+ fwprintf(stderr, L"Could not unset send timeout, continuing...\n");
+ }
+
+ if (!InternetSetOption(request.get(),
+ INTERNET_OPTION_RECEIVE_TIMEOUT,
+ timeout_ms,
+ sizeof(*timeout_ms))) {
+ 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;
+ }
+
+ wstring 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);
+ }
+
+ wstring GenerateMultipartPostRequestHeader(const wstring &boundary) {
+ wstring header = L"Content-Type: multipart/form-data; boundary=";
+ header += boundary;
+ return header;
+ }
+
+ bool AppendFileToRequestBody(
+ const wstring& file_part_name,
+ const wstring& filename,
+ string* request_body) {
+ string file_part_name_utf8 = WideToUTF8(file_part_name);
+ if (file_part_name_utf8.empty()) {
+ return false;
+ }
+
+ string filename_utf8 = WideToUTF8(filename);
+ if (filename_utf8.empty()) {
+ return false;
+ }
+
+ 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");
+
+ vector<char> contents;
+ if (!GetFileContents(filename, &contents)) {
+ return false;
+ }
+
+ if (!contents.empty()) {
+ request_body->append(&(contents[0]), contents.size());
+ }
+ request_body->append("\r\n");
+
+ return true;
+ }
+
+ bool GenerateRequestBody(const string &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 the extra data as a single JSON form entry
+ request_body->append("--" + boundary_str + "\r\n");
+ request_body->append(
+ "Content-Disposition: form-data; "
+ "name=\"extra\"; "
+ "filename=\"extra.json\"\r\n");
+ request_body->append("Content-Type: application/json\r\n");
+ request_body->append("\r\n");
+
+ if (!parameters.empty()) {
+ request_body->append(parameters);
+ }
+ request_body->append("\r\n");
+
+ // Now append each upload file as a binary (octet-stream) part
+ for (map<wstring, wstring>::const_iterator pos = files.begin();
+ pos != files.end(); ++pos) {
+ request_body->append("--" + boundary_str + "\r\n");
+
+ if (!AppendFileToRequestBody(pos->first, pos->second, request_body)) {
+ return false;
+ }
+ }
+ request_body->append("--" + boundary_str + "--\r\n");
+ return true;
+ }
+}
+
+namespace google_breakpad {
+ bool HTTPUpload::SendPutRequest(
+ const wstring& url,
+ const wstring& path,
+ int* timeout_ms,
+ wstring* response_body,
+ int* response_code) {
+ string request_body;
+ if (!AppendFileToRequestBody(L"symbol_file", path, &request_body)) {
+ return false;
+ }
+
+ return SendRequestInner(
+ url,
+ L"PUT",
+ L"",
+ request_body,
+ timeout_ms,
+ response_body,
+ response_code);
+ }
+
+ bool HTTPUpload::SendGetRequest(
+ const wstring& url,
+ int* timeout_ms,
+ wstring* response_body,
+ int* response_code) {
+ return SendRequestInner(
+ url,
+ L"GET",
+ L"",
+ "",
+ timeout_ms,
+ response_body,
+ response_code);
+ }
+
+ bool HTTPUpload::SendMultipartPostRequest(
+ const wstring& url,
+ const string& parameters,
+ const map<wstring, wstring>& files,
+ int* timeout_ms,
+ wstring* response_body,
+ int* response_code) {
+ wstring boundary = GenerateMultipartBoundary();
+ wstring content_type_header = GenerateMultipartPostRequestHeader(boundary);
+
+ string request_body;
+ if (!GenerateRequestBody(parameters, files, boundary, &request_body)) {
+ return false;
+ }
+
+ return SendRequestInner(
+ url,
+ L"POST",
+ content_type_header,
+ request_body,
+ timeout_ms,
+ response_body,
+ response_code);
+ }
+
+ bool HTTPUpload::SendSimplePostRequest(
+ const wstring& url,
+ const wstring& body,
+ const wstring& content_type,
+ int *timeout_ms,
+ wstring *response_body,
+ int *response_code) {
+ return SendRequestInner(
+ url,
+ L"POST",
+ content_type,
+ WideToUTF8(body),
+ timeout_ms,
+ response_body,
+ response_code);
+ }
+} // 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
new file mode 100644
index 0000000000..1e47f5829f
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/windows/http_upload.h
@@ -0,0 +1,125 @@
+// 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
+// parameters encoded in a JSON string, 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>
+
+namespace google_breakpad {
+
+using std::map;
+using std::string;
+using std::wstring;
+
+class HTTPUpload {
+ public:
+ // Sends a PUT request containing the data in |path| to the given
+ // URL.
+ // 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 SendPutRequest(
+ const wstring& url,
+ const wstring& path,
+ int* timeout_ms,
+ wstring* response_body,
+ int* response_code);
+
+ // Sends a GET request to the given URL.
+ // 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 SendGetRequest(
+ const wstring& url,
+ int* timeout_ms,
+ wstring* response_body,
+ int* response_code);
+
+ // 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">.
+ // Parameters are specified as a JSON-encoded string in |parameters|.
+ // 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 SendMultipartPostRequest(
+ const wstring& url,
+ const string& parameters,
+ const map<wstring, wstring>& files,
+ int *timeout_ms,
+ wstring *response_body,
+ int *response_code);
+
+ // Sends a POST request, with the body set to |body|, to the given URL.
+ // 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 SendSimplePostRequest(
+ const wstring& url,
+ const wstring& body,
+ const wstring& content_type,
+ int *timeout_ms,
+ wstring *response_body,
+ int *response_code);
+
+ private:
+ // 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/module_info.h b/toolkit/crashreporter/google-breakpad/src/common/windows/module_info.h
new file mode 100644
index 0000000000..3dccc80882
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/windows/module_info.h
@@ -0,0 +1,75 @@
+// Copyright (c) 2019, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef COMMON_WINDOWS_MODULE_INFO_H_
+#define COMMON_WINDOWS_MODULE_INFO_H_
+
+#include <string>
+
+namespace google_breakpad {
+
+using std::wstring;
+// A structure that carries information that identifies a module.
+struct PDBModuleInfo {
+public:
+ // The basename of the pe/pdb file from which information was loaded.
+ wstring debug_file;
+
+ // The module's identifier. For recent pe/pdb files, the identifier consists
+ // of the pe/pdb's guid, in uppercase hexadecimal form without any dashes
+ // or separators, followed immediately by the pe/pdb's age, also in
+ // uppercase hexadecimal form. For older pe/pdb files which have no guid,
+ // the identifier is the pe/pdb's 32-bit signature value, in zero-padded
+ // hexadecimal form, followed immediately by the pe/pdb's age, in lowercase
+ // hexadecimal form.
+ wstring debug_identifier;
+
+ // A string identifying the cpu that the pe/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;
+};
+
+} // namespace google_breakpad
+
+#endif // COMMON_WINDOWS_MODULE_INFO_H_
diff --git a/toolkit/crashreporter/google-breakpad/src/common/windows/objs.mozbuild b/toolkit/crashreporter/google-breakpad/src/common/windows/objs.mozbuild
new file mode 100644
index 0000000000..5fcdae5a35
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/windows/objs.mozbuild
@@ -0,0 +1,15 @@
+# -*- 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
new file mode 100644
index 0000000000..ba3ce86b8b
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/windows/omap.cc
@@ -0,0 +1,716 @@
+// 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);
+ }
+}
+
+void BuildSubsequentRVAMap(const OmapData &omap_data,
+ std::map<DWORD, DWORD> *subsequent) {
+ assert(subsequent->empty());
+ const OmapFromTable &orig2tran =
+ reinterpret_cast<const OmapFromTable &>(omap_data.omap_from);
+
+ if (orig2tran.empty())
+ return;
+
+ for (size_t i = 0; i < orig2tran.size() - 1; ++i) {
+ // Expect that orig2tran is sorted.
+ if (orig2tran[i].rva_original >= orig2tran[i + 1].rva_original) {
+ fprintf(stderr, "OMAP 'from' table unexpectedly unsorted\n");
+ subsequent->clear();
+ return;
+ }
+ subsequent->insert(std::make_pair(orig2tran[i].rva_original,
+ orig2tran[i + 1].rva_original));
+ }
+}
+
+// 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);
+ BuildSubsequentRVAMap(omap_data, &image_map->subsequent_rva_block);
+}
+
+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
diff --git a/toolkit/crashreporter/google-breakpad/src/common/windows/omap.h b/toolkit/crashreporter/google-breakpad/src/common/windows/omap.h
new file mode 100644
index 0000000000..bc293afb51
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/windows/omap.h
@@ -0,0 +1,72 @@
+// 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
new file mode 100644
index 0000000000..2a4713d934
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/windows/omap_internal.h
@@ -0,0 +1,140 @@
+// 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 <map>
+#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;
+
+ std::map<DWORD, DWORD> subsequent_rva_block;
+};
+
+} // 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
new file mode 100644
index 0000000000..7fe66bd406
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/windows/omap_unittest.cc
@@ -0,0 +1,329 @@
+// 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 "breakpad_googletest_includes.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
new file mode 100644
index 0000000000..4030a2e953
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/windows/pdb_source_line_writer.cc
@@ -0,0 +1,1194 @@
+// 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 <algorithm>
+#include <limits>
+#include <map>
+#include <set>
+#include <utility>
+
+#include "common/windows/dia_util.h"
+#include "common/windows/guid_string.h"
+#include "common/windows/pe_util.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
+
+namespace google_breakpad {
+
+namespace {
+
+using std::vector;
+
+// The symbol (among possibly many) selected to represent an rva.
+struct SelectedSymbol {
+ SelectedSymbol(const CComPtr<IDiaSymbol>& symbol, bool is_public)
+ : symbol(symbol), is_public(is_public), is_multiple(false) {}
+
+ // The symbol to use for an rva.
+ CComPtr<IDiaSymbol> symbol;
+ // Whether this is a public or function symbol.
+ bool is_public;
+ // Whether the rva has multiple associated symbols. An rva will correspond to
+ // multiple symbols in the case of linker identical symbol folding.
+ bool is_multiple;
+};
+
+// Maps rva to the symbol to use for that address.
+typedef std::map<DWORD, SelectedSymbol> SymbolMap;
+
+// Record this in the map as the selected symbol for the rva if it satisfies the
+// necessary conditions.
+void MaybeRecordSymbol(DWORD rva,
+ const CComPtr<IDiaSymbol> symbol,
+ bool is_public,
+ SymbolMap* map) {
+ SymbolMap::iterator loc = map->find(rva);
+ if (loc == map->end()) {
+ map->insert(std::make_pair(rva, SelectedSymbol(symbol, is_public)));
+ return;
+ }
+
+ // Prefer function symbols to public symbols.
+ if (is_public && !loc->second.is_public) {
+ return;
+ }
+
+ loc->second.is_multiple = true;
+
+ // Take the 'least' symbol by lexicographical order of the decorated name. We
+ // use the decorated rather than undecorated name because computing the latter
+ // is expensive.
+ BSTR current_name, new_name;
+ loc->second.symbol->get_name(&current_name);
+ symbol->get_name(&new_name);
+ if (wcscmp(new_name, current_name) < 0) {
+ loc->second.symbol = symbol;
+ loc->second.is_public = is_public;
+ }
+}
+
+
+
+bool SymbolsMatch(IDiaSymbol* a, IDiaSymbol* b) {
+ DWORD a_section, a_offset, b_section, b_offset;
+ if (FAILED(a->get_addressSection(&a_section)) ||
+ FAILED(a->get_addressOffset(&a_offset)) ||
+ FAILED(b->get_addressSection(&b_section)) ||
+ FAILED(b->get_addressOffset(&b_offset)))
+ return false;
+ return a_section == b_section && a_offset == b_offset;
+}
+
+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() {
+ Close();
+}
+
+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_, "%lx %lx %lu %lu\n", ranges[i].rva, ranges[i].length,
+ line_num, source_id);
+ }
+ line.Release();
+ }
+ return true;
+}
+
+bool PDBSourceLineWriter::PrintFunction(IDiaSymbol *function,
+ IDiaSymbol *block,
+ bool has_multiple_symbols) {
+ // 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) {
+ const char* optional_multiple_field = has_multiple_symbols ? "m " : "";
+ fprintf(output_, "FUNC %s%lx %lx %x %ws\n", optional_multiple_field,
+ 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.
+ SymbolMap rva_symbol;
+ 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))) {
+ // Potentially record this as the canonical symbol for this rva.
+ MaybeRecordSymbol(rva, symbol, false, &rva_symbol);
+ } else {
+ fprintf(stderr, "get_relativeVirtualAddress failed on the symbol\n");
+ return false;
+ }
+
+ symbol.Release();
+ }
+
+ symbols.Release();
+ }
+
+ // Find all public symbols and record public symbols that are not also private
+ // symbols.
+ 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))) {
+ // Potentially record this as the canonical symbol for this rva.
+ MaybeRecordSymbol(rva, symbol, true, &rva_symbol);
+ } else {
+ fprintf(stderr, "get_relativeVirtualAddress failed on the symbol\n");
+ return false;
+ }
+
+ symbol.Release();
+ }
+
+ symbols.Release();
+ }
+
+ // For each rva, dump the selected symbol at the address.
+ SymbolMap::iterator it;
+ for (it = rva_symbol.begin(); it != rva_symbol.end(); ++it) {
+ CComPtr<IDiaSymbol> symbol = it->second.symbol;
+ // Only print public symbols if there is no function symbol for the address.
+ if (!it->second.is_public) {
+ if (!PrintFunction(symbol, symbol, it->second.is_multiple))
+ return false;
+ } else {
+ if (!PrintCodePublicSymbol(symbol, it->second.is_multiple))
+ 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, false)) {
+ 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 %lx %lx %lx %lx %x %lx %lx %lx %lx %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;
+ }
+
+ return PrintPEFrameData(code_file_, output_);
+}
+
+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 has_multiple_symbols) {
+ 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) {
+ const char* optional_multiple_field = has_multiple_symbols ? "m " : "";
+ fprintf(output_, "PUBLIC %s%lx %x %ws\n", optional_multiple_field,
+ ranges[i].rva, stack_param_size > 0 ? stack_param_size : 0,
+ name.m_str);
+ }
+
+ // Now walk the function in the original untranslated space, asking DIA
+ // what function is at that location, stepping through OMAP blocks. If
+ // we're still in the same function, emit another entry, because the
+ // symbol could have been split into multiple pieces. If we've gotten to
+ // another symbol in the original address space, then we're done for
+ // this symbol. See https://crbug.com/678874.
+ for (;;) {
+ // This steps to the next block in the original image. Simply doing
+ // rva++ would also be correct, but would emit tons of unnecessary
+ // entries.
+ rva = image_map_.subsequent_rva_block[rva];
+ if (rva == 0)
+ break;
+
+ CComPtr<IDiaSymbol> next_sym = NULL;
+ LONG displacement;
+ if (FAILED(session_->findSymbolByRVAEx(rva, SymTagPublicSymbol, &next_sym,
+ &displacement))) {
+ break;
+ }
+
+ if (!SymbolsMatch(symbol, next_sym))
+ break;
+
+ AddressRangeVector next_ranges;
+ MapAddressRange(image_map_, AddressRange(rva, 1), &next_ranges);
+ for (size_t i = 0; i < next_ranges.size(); ++i) {
+ fprintf(output_, "PUBLIC %lx %x %ws\n", next_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 (size_t 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;
+ }
+
+ // Extra scope to avoid goto jumping over variable initialization
+ {
+ 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::WriteSymbols(FILE *symbol_file) {
+ output_ = symbol_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() {
+ if (session_ != nullptr) {
+ 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
+ info->cpu = FileHeaderMachineToCpuString(static_cast<WORD>(machine_type));
+ } 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;
+ }
+
+ info->debug_identifier = GenerateDebugIdentifier(age, guid);
+ } else {
+ DWORD signature;
+ if (FAILED(global->get_signature(&signature))) {
+ return false;
+ }
+
+ info->debug_identifier = GenerateDebugIdentifier(age, signature);
+ }
+
+ 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;
+ }
+
+ return ReadPEInfo(code_file_, info);
+}
+
+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
new file mode 100644
index 0000000000..c0adf29f24
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/windows/pdb_source_line_writer.h
@@ -0,0 +1,226 @@
+// 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 <string>
+#include <unordered_map>
+
+#include "common/windows/module_info.h"
+#include "common/windows/omap.h"
+
+struct IDiaEnumLineNumbers;
+struct IDiaSession;
+struct IDiaSymbol;
+
+namespace google_breakpad {
+
+using std::wstring;
+using std::unordered_map;
+
+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);
+
+ // Closes the current pdb file and its associated resources.
+ void Close();
+
+ // 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 Breakpad symbol file from the current pdb file to |symbol_file|.
+ // Returns true on success.
+ bool WriteSymbols(FILE *symbol_file);
+
+ // 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. If has_multiple_symbols is true, this function's
+ // instructions correspond to multiple symbols. Returns true on success.
+ bool PrintFunction(IDiaSymbol *function, IDiaSymbol *block,
+ bool has_multiple_symbols);
+
+ // 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. If
+ // has_multiple_symbols is true, the symbol corresponds to a code address and
+ // the instructions correspond to multiple symbols.
+ bool PrintCodePublicSymbol(IDiaSymbol *symbol, bool has_multiple_symbols);
+
+ // 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/pe_source_line_writer.cc b/toolkit/crashreporter/google-breakpad/src/common/windows/pe_source_line_writer.cc
new file mode 100644
index 0000000000..cb6cc71396
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/windows/pe_source_line_writer.cc
@@ -0,0 +1,77 @@
+// Copyright (c) 2019, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "common/windows/pe_source_line_writer.h"
+
+#include "common/windows/pe_util.h"
+
+namespace google_breakpad {
+PESourceLineWriter::PESourceLineWriter(const wstring& pe_file) :
+ pe_file_(pe_file) {
+}
+
+PESourceLineWriter::~PESourceLineWriter() {
+}
+
+bool PESourceLineWriter::WriteSymbols(FILE* symbol_file) {
+ PDBModuleInfo module_info;
+ if (!GetModuleInfo(&module_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(symbol_file, "MODULE windows %ws %ws %ws\n",
+ module_info.cpu.c_str(), module_info.debug_identifier.c_str(),
+ module_info.debug_file.c_str());
+
+ PEModuleInfo pe_info;
+ if (!GetPEInfo(&pe_info)) {
+ return false;
+ }
+ fprintf(symbol_file, "INFO CODE_ID %ws %ws\n",
+ pe_info.code_identifier.c_str(),
+ pe_info.code_file.c_str());
+
+ if (!PrintPEFrameData(pe_file_, symbol_file)) {
+ return false;
+ }
+
+ return true;
+}
+
+bool PESourceLineWriter::GetModuleInfo(PDBModuleInfo* info) {
+ return ReadModuleInfo(pe_file_, info);
+}
+
+bool PESourceLineWriter::GetPEInfo(PEModuleInfo* info) {
+ return ReadPEInfo(pe_file_, info);
+}
+
+} // namespace google_breakpad
diff --git a/toolkit/crashreporter/google-breakpad/src/common/windows/pe_source_line_writer.h b/toolkit/crashreporter/google-breakpad/src/common/windows/pe_source_line_writer.h
new file mode 100644
index 0000000000..2bf1d4fd2b
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/windows/pe_source_line_writer.h
@@ -0,0 +1,69 @@
+// Copyright (c) 2019, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef COMMON_WINDOWS_PE_SOURCE_LINE_WRITER_H_
+#define COMMON_WINDOWS_PE_SOURCE_LINE_WRITER_H_
+
+#include <string>
+
+#include "common/basictypes.h"
+#include "common/windows/module_info.h"
+
+namespace google_breakpad {
+
+using std::wstring;
+
+// PESourceLineWriter uses a pe file produced by Visual C++ to output
+// a line/address map for use with BasicSourceLineResolver.
+// NOTE: Only supports PE32+ format, ie. a 64bit PE file.
+class PESourceLineWriter {
+public:
+ explicit PESourceLineWriter(const wstring& pe_file);
+ ~PESourceLineWriter();
+
+ // Writes Breakpad symbols from the pe file to |symbol_file|.
+ // Returns true on success.
+ bool WriteSymbols(FILE* symbol_file);
+
+ // Retrieves information about the module. Returns true on success.
+ bool GetModuleInfo(PDBModuleInfo* info);
+
+ // Retrieves information about the module's PE file. Returns
+ // true on success.
+ bool GetPEInfo(PEModuleInfo* info);
+
+private:
+ const wstring pe_file_;
+
+ DISALLOW_COPY_AND_ASSIGN(PESourceLineWriter);
+};
+
+} // namespace google_breakpad
+
+#endif // COMMON_WINDOWS_PE_SOURCE_LINE_WRITER_H_
diff --git a/toolkit/crashreporter/google-breakpad/src/common/windows/pe_util.cc b/toolkit/crashreporter/google-breakpad/src/common/windows/pe_util.cc
new file mode 100644
index 0000000000..6fa63fa3b5
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/windows/pe_util.cc
@@ -0,0 +1,407 @@
+// Copyright (c) 2019, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "pe_util.h"
+
+#include <windows.h>
+#include <winnt.h>
+#include <atlbase.h>
+#include <ImageHlp.h>
+
+#include <functional>
+
+#include "common/windows/string_utils-inl.h"
+#include "common/windows/guid_string.h"
+
+namespace {
+
+/*
+ * 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];
+};
+
+struct CV_INFO_PDB70 {
+ ULONG cv_signature;
+ GUID signature;
+ ULONG age;
+ CHAR pdb_filename[ANYSIZE_ARRAY];
+};
+
+#define CV_SIGNATURE_RSDS 'SDSR'
+
+// 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_;
+};
+} // namespace
+
+namespace google_breakpad {
+
+using std::unique_ptr;
+using google_breakpad::GUIDString;
+
+bool ReadModuleInfo(const wstring & pe_file, PDBModuleInfo * info) {
+ // Convert wchar to native charset because ImageLoad only takes
+ // a PSTR as input.
+ string img_file;
+ if (!WindowsStringUtils::safe_wcstombs(pe_file, &img_file)) {
+ fprintf(stderr, "Image path '%S' contains unrecognized characters.\n",
+ pe_file.c_str());
+ return false;
+ }
+
+ AutoImage img(ImageLoad((PSTR)img_file.c_str(), NULL));
+ if (!img) {
+ fprintf(stderr, "Failed to load %s\n", img_file.c_str());
+ return false;
+ }
+
+ info->cpu = FileHeaderMachineToCpuString(
+ img->FileHeader->FileHeader.Machine);
+
+ PIMAGE_OPTIONAL_HEADER64 optional_header =
+ &(reinterpret_cast<PIMAGE_NT_HEADERS64>(img->FileHeader))->OptionalHeader;
+
+ // Search debug directories for a guid signature & age
+ DWORD debug_rva = optional_header->
+ DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;
+ DWORD debug_size = optional_header->
+ DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size;
+ PIMAGE_DEBUG_DIRECTORY debug_directories =
+ static_cast<PIMAGE_DEBUG_DIRECTORY>(
+ ImageRvaToVa(img->FileHeader,
+ img->MappedAddress,
+ debug_rva,
+ &img->LastRvaSection));
+
+ for (DWORD i = 0; i < debug_size / sizeof(*debug_directories); i++) {
+ if (debug_directories[i].Type != IMAGE_DEBUG_TYPE_CODEVIEW ||
+ debug_directories[i].SizeOfData < sizeof(CV_INFO_PDB70)) {
+ continue;
+ }
+
+ struct CV_INFO_PDB70* cv_info = static_cast<CV_INFO_PDB70*>(ImageRvaToVa(
+ img->FileHeader,
+ img->MappedAddress,
+ debug_directories[i].AddressOfRawData,
+ &img->LastRvaSection));
+ if (cv_info->cv_signature != CV_SIGNATURE_RSDS) {
+ continue;
+ }
+
+ info->debug_identifier = GenerateDebugIdentifier(cv_info->age,
+ cv_info->signature);
+
+ // This code assumes that the pdb_filename is stored as ASCII without
+ // multibyte characters, but it's not clear if that's true.
+ size_t debug_file_length = strnlen_s(cv_info->pdb_filename, MAX_PATH);
+ if (debug_file_length < 0 || debug_file_length >= MAX_PATH) {
+ fprintf(stderr, "PE debug directory is corrupt.\n");
+ return false;
+ }
+ std::string debug_file(cv_info->pdb_filename, debug_file_length);
+ if (!WindowsStringUtils::safe_mbstowcs(debug_file, &info->debug_file)) {
+ fprintf(stderr, "PDB filename '%s' contains unrecognized characters.\n",
+ debug_file.c_str());
+ return false;
+ }
+ info->debug_file = WindowsStringUtils::GetBaseName(info->debug_file);
+
+ return true;
+ }
+
+ fprintf(stderr, "Image is missing debug information.\n");
+ return false;
+}
+
+bool ReadPEInfo(const wstring & pe_file, PEModuleInfo * info) {
+ // Convert wchar to native charset because ImageLoad only takes
+ // a PSTR as input.
+ string img_file;
+ if (!WindowsStringUtils::safe_wcstombs(pe_file, &img_file)) {
+ fprintf(stderr, "Image path '%S' contains unrecognized characters.\n",
+ pe_file.c_str());
+ return false;
+ }
+
+ AutoImage img(ImageLoad((PSTR)img_file.c_str(), NULL));
+ if (!img) {
+ fprintf(stderr, "Failed to open PE file: %S\n", pe_file.c_str());
+ return false;
+ }
+
+ info->code_file = WindowsStringUtils::GetBaseName(pe_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 PrintPEFrameData(const wstring & pe_file, FILE * out_file)
+{
+ // Convert wchar to native charset because ImageLoad only takes
+ // a PSTR as input.
+ string img_file;
+ if (!WindowsStringUtils::safe_wcstombs(pe_file, &img_file)) {
+ fprintf(stderr, "Image path '%S' contains unrecognized characters.\n",
+ pe_file.c_str());
+ return false;
+ }
+
+ AutoImage img(ImageLoad((PSTR)img_file.c_str(), NULL));
+ if (!img) {
+ fprintf(stderr, "Failed to load %s\n", img_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(out_file, "STACK CFI INIT %lx %lx .cfa: $rsp .ra: .cfa %lu - ^\n",
+ funcs[i].BeginAddress,
+ funcs[i].EndAddress - funcs[i].BeginAddress, rip_offset);
+ fprintf(out_file, "STACK CFI %lx .cfa: $rsp %lu +\n",
+ funcs[i].BeginAddress, stack_size);
+ }
+
+ return true;
+}
+
+wstring GenerateDebugIdentifier(DWORD age, GUID signature)
+{
+ // 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';
+
+ wstring debug_identifier = GUIDString::GUIDToSymbolServerWString(&signature);
+ debug_identifier.append(age_string);
+
+ return debug_identifier;
+}
+
+wstring GenerateDebugIdentifier(DWORD age, DWORD signature)
+{
+ // 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';
+
+ return wstring(identifier_string);
+}
+
+} // namespace google_breakpad
diff --git a/toolkit/crashreporter/google-breakpad/src/common/windows/pe_util.h b/toolkit/crashreporter/google-breakpad/src/common/windows/pe_util.h
new file mode 100644
index 0000000000..634ba29343
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/windows/pe_util.h
@@ -0,0 +1,78 @@
+// Copyright (c) 2019, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef COMMON_WINDOWS_PE_UTIL_H_
+#define COMMON_WINDOWS_PE_UTIL_H_
+
+#include <windows.h>
+
+#include "common/windows/module_info.h"
+
+namespace google_breakpad {
+
+using std::wstring;
+
+// Reads |pe_file| and populates |info|. Returns true on success.
+// Only supports PE32+ format, ie. a 64bit PE file.
+// Will fail if |pe_file| does not contain a valid CodeView record.
+bool ReadModuleInfo(const wstring& pe_file, PDBModuleInfo* info);
+
+// Reads |pe_file| and populates |info|. Returns true on success.
+bool ReadPEInfo(const wstring& pe_file, PEModuleInfo* info);
+
+// Reads |pe_file| and prints frame data (aka. unwind info) to |out_file|.
+// Only supports PE32+ format, ie. a 64bit PE file.
+bool PrintPEFrameData(const wstring& pe_file, FILE* out_file);
+
+// Combines a GUID |signature| and DWORD |age| to create a Breakpad debug
+// identifier.
+wstring GenerateDebugIdentifier(DWORD age, GUID signature);
+
+// Combines a DWORD |signature| and DWORD |age| to create a Breakpad debug
+// identifier.
+wstring GenerateDebugIdentifier(DWORD age, DWORD signature);
+
+// Converts |machine| enum value to the corresponding string used by Breakpad.
+// The enum is IMAGE_FILE_MACHINE_*, contained in winnt.h.
+constexpr const wchar_t* FileHeaderMachineToCpuString(WORD machine) {
+ switch (machine) {
+ case IMAGE_FILE_MACHINE_I386: {
+ return L"x86";
+ }
+ case IMAGE_FILE_MACHINE_IA64:
+ case IMAGE_FILE_MACHINE_AMD64: {
+ return L"x86_64";
+ }
+ default: { return L"unknown"; }
+ }
+}
+
+} // namespace google_breakpad
+
+#endif // COMMON_WINDOWS_PE_UTIL_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
new file mode 100644
index 0000000000..9b63607268
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/windows/string_utils-inl.h
@@ -0,0 +1,142 @@
+// 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
new file mode 100644
index 0000000000..272800035c
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/windows/string_utils.cc
@@ -0,0 +1,133 @@
+// 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
diff --git a/toolkit/crashreporter/google-breakpad/src/common/windows/symbol_collector_client.cc b/toolkit/crashreporter/google-breakpad/src/common/windows/symbol_collector_client.cc
new file mode 100644
index 0000000000..30c663ed37
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/windows/symbol_collector_client.cc
@@ -0,0 +1,155 @@
+#include "common/windows/symbol_collector_client.h"
+
+#include <stdio.h>
+
+#include <regex>
+
+#include "common/windows/http_upload.h"
+
+namespace google_breakpad {
+
+ // static
+ bool SymbolCollectorClient::CreateUploadUrl(
+ wstring& api_url,
+ wstring& api_key,
+ UploadUrlResponse *uploadUrlResponse) {
+ wstring url = api_url +
+ L"/v1/uploads:create"
+ L"?key=" + api_key;
+ wstring response;
+ int response_code;
+
+ if (!HTTPUpload::SendSimplePostRequest(
+ url,
+ L"",
+ L"",
+ NULL,
+ &response,
+ &response_code)) {
+ wprintf(L"Failed to create upload url.\n");
+ wprintf(L"Response code: %ld\n", response_code);
+ wprintf(L"Response:\n");
+ wprintf(L"%s\n", response.c_str());
+ return false;
+ }
+
+ // Note camel-case rather than underscores.
+ std::wregex upload_url_regex(L"\"uploadUrl\": \"([^\"]+)\"");
+ std::wregex upload_key_regex(L"\"uploadKey\": \"([^\"]+)\"");
+
+ std::wsmatch upload_url_match;
+ if (!std::regex_search(response, upload_url_match, upload_url_regex) ||
+ upload_url_match.size() != 2) {
+ wprintf(L"Failed to parse create url response.");
+ wprintf(L"Response:\n");
+ wprintf(L"%s\n", response.c_str());
+ return false;
+ }
+ wstring upload_url = upload_url_match[1].str();
+
+ std::wsmatch upload_key_match;
+ if (!std::regex_search(response, upload_key_match, upload_key_regex) ||
+ upload_key_match.size() != 2) {
+ wprintf(L"Failed to parse create url response.");
+ wprintf(L"Response:\n");
+ wprintf(L"%s\n", response.c_str());
+ return false;
+ }
+ wstring upload_key = upload_key_match[1].str();
+
+ uploadUrlResponse->upload_url = upload_url;
+ uploadUrlResponse->upload_key = upload_key;
+ return true;
+ }
+
+ // static
+ CompleteUploadResult SymbolCollectorClient::CompleteUpload(
+ wstring& api_url,
+ wstring& api_key,
+ const wstring& upload_key,
+ const wstring& debug_file,
+ const wstring& debug_id) {
+ wstring url = api_url +
+ L"/v1/uploads/" + upload_key + L":complete"
+ L"?key=" + api_key;
+ wstring body =
+ L"{ symbol_id: {"
+ L"debug_file: \"" + debug_file + L"\", "
+ L"debug_id: \"" + debug_id + L"\" "
+ L"} }";
+ wstring response;
+ int response_code;
+
+ if (!HTTPUpload::SendSimplePostRequest(
+ url,
+ body,
+ L"application/json",
+ NULL,
+ &response,
+ &response_code)) {
+ wprintf(L"Failed to complete upload.\n");
+ wprintf(L"Response code: %ld\n", response_code);
+ wprintf(L"Response:\n");
+ wprintf(L"%s\n", response.c_str());
+ return CompleteUploadResult::Error;
+ }
+
+ std::wregex result_regex(L"\"result\": \"([^\"]+)\"");
+ std::wsmatch result_match;
+ if (!std::regex_search(response, result_match, result_regex) ||
+ result_match.size() != 2) {
+ wprintf(L"Failed to parse complete upload response.");
+ wprintf(L"Response:\n");
+ wprintf(L"%s\n", response.c_str());
+ return CompleteUploadResult::Error;
+ }
+ wstring result = result_match[1].str();
+
+ if (result.compare(L"DUPLICATE_DATA") == 0) {
+ return CompleteUploadResult::DuplicateData;
+ }
+
+ return CompleteUploadResult::Ok;
+ }
+
+ // static
+ SymbolStatus SymbolCollectorClient::CheckSymbolStatus(
+ wstring& api_url,
+ wstring& api_key,
+ const wstring& debug_file,
+ const wstring& debug_id) {
+ wstring response;
+ int response_code;
+ wstring url = api_url +
+ L"/v1/symbols/" + debug_file + L"/" + debug_id + L":checkStatus"
+ L"?key=" + api_key;
+
+ if (!HTTPUpload::SendGetRequest(
+ url,
+ NULL,
+ &response,
+ &response_code)) {
+ wprintf(L"Failed to check symbol status.\n");
+ wprintf(L"Response code: %ld\n", response_code);
+ wprintf(L"Response:\n");
+ wprintf(L"%s\n", response.c_str());
+ return SymbolStatus::Unknown;
+ }
+
+ std::wregex status_regex(L"\"status\": \"([^\"]+)\"");
+ std::wsmatch status_match;
+ if (!std::regex_search(response, status_match, status_regex) ||
+ status_match.size() != 2) {
+ wprintf(L"Failed to parse check symbol status response.");
+ wprintf(L"Response:\n");
+ wprintf(L"%s\n", response.c_str());
+ return SymbolStatus::Unknown;
+ }
+ wstring status = status_match[1].str();
+
+ return (status.compare(L"FOUND") == 0) ?
+ SymbolStatus::Found :
+ SymbolStatus::Missing;
+ }
+
+} // namespace google_breakpad \ No newline at end of file
diff --git a/toolkit/crashreporter/google-breakpad/src/common/windows/symbol_collector_client.h b/toolkit/crashreporter/google-breakpad/src/common/windows/symbol_collector_client.h
new file mode 100644
index 0000000000..30e0cb3230
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/common/windows/symbol_collector_client.h
@@ -0,0 +1,89 @@
+// Copyright (c) 2019, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef COMMON_WINDOWS_SYMBOL_COLLECTOR_CLIENT_H_
+#define COMMON_WINDOWS_SYMBOL_COLLECTOR_CLIENT_H_
+
+#include <string>
+
+namespace google_breakpad {
+
+ using std::wstring;
+
+ struct UploadUrlResponse {
+ // URL at which to HTTP PUT symbol file.
+ wstring upload_url;
+ // Unique key used to complete upload of symbol file.
+ wstring upload_key;
+ };
+
+ enum SymbolStatus {
+ Found,
+ Missing,
+ Unknown
+ };
+
+ enum CompleteUploadResult {
+ Ok,
+ DuplicateData,
+ Error
+ };
+
+ // Client to interact with sym-upload-v2 API server via HTTP/REST.
+ class SymbolCollectorClient {
+ public:
+ // Returns a URL at which a symbol file can be HTTP PUT without
+ // authentication, along with an upload key that can be used to
+ // complete the upload process with CompleteUpload.
+ static bool CreateUploadUrl(
+ wstring& api_url,
+ wstring& api_key,
+ UploadUrlResponse *uploadUrlResponse);
+
+ // Notify the API that symbol file upload is finished and its contents
+ // are ready to be read and/or used for further processing.
+ static CompleteUploadResult CompleteUpload(
+ wstring& api_url,
+ wstring& api_key,
+ const wstring& upload_key,
+ const wstring& debug_file,
+ const wstring& debug_id);
+
+ // Returns whether or not a symbol file corresponding to the debug_file/
+ // debug_id pair is already present in symbol storage.
+ static SymbolStatus CheckSymbolStatus(
+ wstring& api_url,
+ wstring& api_key,
+ const wstring& debug_file,
+ const wstring& debug_id);
+ };
+
+} // namespace google_breakpad
+
+#endif // COMMON_WINDOWS_SYMBOL_COLLECTOR_CLIENT_H_
diff --git a/toolkit/crashreporter/google-breakpad/src/config.h.in b/toolkit/crashreporter/google-breakpad/src/config.h.in
new file mode 100644
index 0000000000..0553a24b34
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/config.h.in
@@ -0,0 +1,94 @@
+/* src/config.h.in. Generated from configure.ac by autoheader. */
+
+/* Define to 1 if you have the `arc4random' function. */
+#undef HAVE_ARC4RANDOM
+
+/* Define to 1 if you have the <a.out.h> header file. */
+#undef HAVE_A_OUT_H
+
+/* define if the compiler supports basic C++11 syntax */
+#undef HAVE_CXX11
+
+/* Define to 1 if you have the `getcontext' function. */
+#undef HAVE_GETCONTEXT
+
+/* Define to 1 if you have the `getrandom' function. */
+#undef HAVE_GETRANDOM
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define if you have POSIX threads libraries and header files. */
+#undef HAVE_PTHREAD
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if you have the <sys/random.h> header file. */
+#undef HAVE_SYS_RANDOM_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Fallback definition for old systems */
+#undef O_CLOEXEC
+
+/* Name of package */
+#undef PACKAGE
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the home page for this package. */
+#undef PACKAGE_URL
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* Define to necessary symbol if this constant uses a non-standard name on
+ your system. */
+#undef PTHREAD_CREATE_JOINABLE
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Version number of package */
+#undef VERSION
+
+/* Enable large inode numbers on Mac OS X 10.5. */
+#ifndef _DARWIN_USE_64_BIT_INODE
+# define _DARWIN_USE_64_BIT_INODE 1
+#endif
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+#undef _FILE_OFFSET_BITS
+
+/* Define for large files, on AIX-style hosts. */
+#undef _LARGE_FILES
diff --git a/toolkit/crashreporter/google-breakpad/src/google_breakpad/common/breakpad_types.h b/toolkit/crashreporter/google-breakpad/src/google_breakpad/common/breakpad_types.h
new file mode 100644
index 0000000000..d8828043ff
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/google_breakpad/common/breakpad_types.h
@@ -0,0 +1,68 @@
+/* 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. */
+
+/* breakpad_types.h: Precise-width types
+ *
+ * (This is C99 source, please don't corrupt it with C++.)
+ *
+ * This file ensures that types uintN_t are defined for N = 8, 16, 32, and
+ * 64. Types of precise widths are crucial to the task of writing data
+ * structures on one platform and reading them on another.
+ *
+ * Author: Mark Mentovai */
+
+#ifndef GOOGLE_BREAKPAD_COMMON_BREAKPAD_TYPES_H__
+#define GOOGLE_BREAKPAD_COMMON_BREAKPAD_TYPES_H__
+
+#if (defined(_INTTYPES_H) || defined(_INTTYPES_H_)) && \
+ !defined(__STDC_FORMAT_MACROS)
+#error "inttypes.h has already been included before this header file, but "
+#error "without __STDC_FORMAT_MACROS defined."
+#endif
+
+#ifndef __STDC_FORMAT_MACROS
+#define __STDC_FORMAT_MACROS
+#endif /* __STDC_FORMAT_MACROS */
+#include <inttypes.h>
+
+typedef struct {
+ uint64_t high;
+ uint64_t low;
+} uint128_struct;
+
+typedef uint64_t breakpad_time_t;
+
+/* Try to get PRIx64 from inttypes.h, but if it's not defined, fall back to
+ * llx, which is the format string for "long long" - this is a 64-bit
+ * integral type on many systems. */
+#ifndef PRIx64
+#define PRIx64 "llx"
+#endif /* !PRIx64 */
+
+#endif /* GOOGLE_BREAKPAD_COMMON_BREAKPAD_TYPES_H__ */
diff --git a/toolkit/crashreporter/google-breakpad/src/google_breakpad/common/minidump_cpu_amd64.h b/toolkit/crashreporter/google-breakpad/src/google_breakpad/common/minidump_cpu_amd64.h
new file mode 100644
index 0000000000..4256706d77
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/google_breakpad/common/minidump_cpu_amd64.h
@@ -0,0 +1,235 @@
+/* Copyright (c) 2006, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
+
+/* minidump_format.h: A cross-platform reimplementation of minidump-related
+ * portions of DbgHelp.h from the Windows Platform SDK.
+ *
+ * (This is C99 source, please don't corrupt it with C++.)
+ *
+ * This file contains the necessary definitions to read minidump files
+ * produced on amd64. These files may be read on any platform provided
+ * that the alignments of these structures on the processing system are
+ * identical to the alignments of these structures on the producing system.
+ * For this reason, precise-sized types are used. The structures defined
+ * by this file have been laid out to minimize alignment problems by ensuring
+ * ensuring that all members are aligned on their natural boundaries. In
+ * In some cases, tail-padding may be significant when different ABIs specify
+ * different tail-padding behaviors. To avoid problems when reading or
+ * writing affected structures, MD_*_SIZE macros are provided where needed,
+ * containing the useful size of the structures without padding.
+ *
+ * Structures that are defined by Microsoft to contain a zero-length array
+ * are instead defined here to contain an array with one element, as
+ * zero-length arrays are forbidden by standard C and C++. In these cases,
+ * *_minsize constants are provided to be used in place of sizeof. For a
+ * cleaner interface to these sizes when using C++, see minidump_size.h.
+ *
+ * These structures are also sufficient to populate minidump files.
+ *
+ * These definitions may be extended to support handling minidump files
+ * for other CPUs and other operating systems.
+ *
+ * Because precise data type sizes are crucial for this implementation to
+ * function properly and portably in terms of interoperability with minidumps
+ * produced by DbgHelp on Windows, a set of primitive types with known sizes
+ * are used as the basis of each structure defined by this file. DbgHelp
+ * on Windows is assumed to be the reference implementation; this file
+ * seeks to provide a cross-platform compatible implementation. To avoid
+ * collisions with the types and values defined and used by DbgHelp in the
+ * event that this implementation is used on Windows, each type and value
+ * defined here is given a new name, beginning with "MD". Names of the
+ * equivalent types and values in the Windows Platform SDK are given in
+ * comments.
+ *
+ * Author: Mark Mentovai
+ * Change to split into its own file: Neal Sidhwaney */
+
+#ifndef GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_AMD64_H__
+#define GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_AMD64_H__
+
+
+/*
+ * AMD64 support, see WINNT.H
+ */
+
+typedef struct {
+ uint16_t control_word;
+ uint16_t status_word;
+ uint8_t tag_word;
+ uint8_t reserved1;
+ uint16_t error_opcode;
+ uint32_t error_offset;
+ uint16_t error_selector;
+ uint16_t reserved2;
+ uint32_t data_offset;
+ uint16_t data_selector;
+ uint16_t reserved3;
+ uint32_t mx_csr;
+ uint32_t mx_csr_mask;
+ uint128_struct float_registers[8];
+ uint128_struct xmm_registers[16];
+ uint8_t reserved4[96];
+} MDXmmSaveArea32AMD64; /* XMM_SAVE_AREA32 */
+
+#define MD_CONTEXT_AMD64_VR_COUNT 26
+
+typedef struct {
+ /*
+ * Register parameter home addresses.
+ */
+ uint64_t p1_home;
+ uint64_t p2_home;
+ uint64_t p3_home;
+ uint64_t p4_home;
+ uint64_t p5_home;
+ uint64_t p6_home;
+
+ /* The next field determines the layout of the structure, and which parts
+ * of it are populated */
+ uint32_t context_flags;
+ uint32_t mx_csr;
+
+ /* The next register is included with MD_CONTEXT_AMD64_CONTROL */
+ uint16_t cs;
+
+ /* The next 4 registers are included with MD_CONTEXT_AMD64_SEGMENTS */
+ uint16_t ds;
+ uint16_t es;
+ uint16_t fs;
+ uint16_t gs;
+
+ /* The next 2 registers are included with MD_CONTEXT_AMD64_CONTROL */
+ uint16_t ss;
+ uint32_t eflags;
+
+ /* The next 6 registers are included with MD_CONTEXT_AMD64_DEBUG_REGISTERS */
+ uint64_t dr0;
+ uint64_t dr1;
+ uint64_t dr2;
+ uint64_t dr3;
+ uint64_t dr6;
+ uint64_t dr7;
+
+ /* The next 4 registers are included with MD_CONTEXT_AMD64_INTEGER */
+ uint64_t rax;
+ uint64_t rcx;
+ uint64_t rdx;
+ uint64_t rbx;
+
+ /* The next register is included with MD_CONTEXT_AMD64_CONTROL */
+ uint64_t rsp;
+
+ /* The next 11 registers are included with MD_CONTEXT_AMD64_INTEGER */
+ uint64_t rbp;
+ uint64_t rsi;
+ uint64_t rdi;
+ uint64_t r8;
+ uint64_t r9;
+ uint64_t r10;
+ uint64_t r11;
+ uint64_t r12;
+ uint64_t r13;
+ uint64_t r14;
+ uint64_t r15;
+
+ /* The next register is included with MD_CONTEXT_AMD64_CONTROL */
+ uint64_t rip;
+
+ /* The next set of registers are included with
+ * MD_CONTEXT_AMD64_FLOATING_POINT
+ */
+ union {
+ MDXmmSaveArea32AMD64 flt_save;
+ struct {
+ uint128_struct header[2];
+ uint128_struct legacy[8];
+ uint128_struct xmm0;
+ uint128_struct xmm1;
+ uint128_struct xmm2;
+ uint128_struct xmm3;
+ uint128_struct xmm4;
+ uint128_struct xmm5;
+ uint128_struct xmm6;
+ uint128_struct xmm7;
+ uint128_struct xmm8;
+ uint128_struct xmm9;
+ uint128_struct xmm10;
+ uint128_struct xmm11;
+ uint128_struct xmm12;
+ uint128_struct xmm13;
+ uint128_struct xmm14;
+ uint128_struct xmm15;
+ } sse_registers;
+ };
+
+ uint128_struct vector_register[MD_CONTEXT_AMD64_VR_COUNT];
+ uint64_t vector_control;
+
+ /* The next 5 registers are included with MD_CONTEXT_AMD64_DEBUG_REGISTERS */
+ uint64_t debug_control;
+ uint64_t last_branch_to_rip;
+ uint64_t last_branch_from_rip;
+ uint64_t last_exception_to_rip;
+ uint64_t last_exception_from_rip;
+
+} MDRawContextAMD64; /* CONTEXT */
+
+/* For (MDRawContextAMD64).context_flags. These values indicate the type of
+ * context stored in the structure. The high 24 bits identify the CPU, the
+ * low 8 bits identify the type of context saved. */
+#define MD_CONTEXT_AMD64 0x00100000 /* CONTEXT_AMD64 */
+#define MD_CONTEXT_AMD64_CONTROL (MD_CONTEXT_AMD64 | 0x00000001)
+ /* CONTEXT_CONTROL */
+#define MD_CONTEXT_AMD64_INTEGER (MD_CONTEXT_AMD64 | 0x00000002)
+ /* CONTEXT_INTEGER */
+#define MD_CONTEXT_AMD64_SEGMENTS (MD_CONTEXT_AMD64 | 0x00000004)
+ /* CONTEXT_SEGMENTS */
+#define MD_CONTEXT_AMD64_FLOATING_POINT (MD_CONTEXT_AMD64 | 0x00000008)
+ /* CONTEXT_FLOATING_POINT */
+#define MD_CONTEXT_AMD64_DEBUG_REGISTERS (MD_CONTEXT_AMD64 | 0x00000010)
+ /* CONTEXT_DEBUG_REGISTERS */
+#define MD_CONTEXT_AMD64_XSTATE (MD_CONTEXT_AMD64 | 0x00000040)
+ /* CONTEXT_XSTATE */
+
+/* WinNT.h refers to CONTEXT_MMX_REGISTERS but doesn't appear to define it
+ * I think it really means CONTEXT_FLOATING_POINT.
+ */
+
+#define MD_CONTEXT_AMD64_FULL (MD_CONTEXT_AMD64_CONTROL | \
+ MD_CONTEXT_AMD64_INTEGER | \
+ MD_CONTEXT_AMD64_FLOATING_POINT)
+ /* CONTEXT_FULL */
+
+#define MD_CONTEXT_AMD64_ALL (MD_CONTEXT_AMD64_FULL | \
+ MD_CONTEXT_AMD64_SEGMENTS | \
+ MD_CONTEXT_X86_DEBUG_REGISTERS)
+ /* CONTEXT_ALL */
+
+
+#endif /* GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_AMD64_H__ */
diff --git a/toolkit/crashreporter/google-breakpad/src/google_breakpad/common/minidump_cpu_arm.h b/toolkit/crashreporter/google-breakpad/src/google_breakpad/common/minidump_cpu_arm.h
new file mode 100644
index 0000000000..6a71138337
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/google_breakpad/common/minidump_cpu_arm.h
@@ -0,0 +1,151 @@
+/* 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. */
+
+/* minidump_format.h: A cross-platform reimplementation of minidump-related
+ * portions of DbgHelp.h from the Windows Platform SDK.
+ *
+ * (This is C99 source, please don't corrupt it with C++.)
+ *
+ * This file contains the necessary definitions to read minidump files
+ * produced on ARM. These files may be read on any platform provided
+ * that the alignments of these structures on the processing system are
+ * identical to the alignments of these structures on the producing system.
+ * For this reason, precise-sized types are used. The structures defined
+ * by this file have been laid out to minimize alignment problems by
+ * ensuring that all members are aligned on their natural boundaries.
+ * In some cases, tail-padding may be significant when different ABIs specify
+ * different tail-padding behaviors. To avoid problems when reading or
+ * writing affected structures, MD_*_SIZE macros are provided where needed,
+ * containing the useful size of the structures without padding.
+ *
+ * Structures that are defined by Microsoft to contain a zero-length array
+ * are instead defined here to contain an array with one element, as
+ * zero-length arrays are forbidden by standard C and C++. In these cases,
+ * *_minsize constants are provided to be used in place of sizeof. For a
+ * cleaner interface to these sizes when using C++, see minidump_size.h.
+ *
+ * These structures are also sufficient to populate minidump files.
+ *
+ * Because precise data type sizes are crucial for this implementation to
+ * function properly and portably, a set of primitive types with known sizes
+ * are used as the basis of each structure defined by this file.
+ *
+ * Author: Julian Seward
+ */
+
+/*
+ * ARM support
+ */
+
+#ifndef GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_ARM_H__
+#define GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_ARM_H__
+
+#define MD_FLOATINGSAVEAREA_ARM_FPR_COUNT 32
+#define MD_FLOATINGSAVEAREA_ARM_FPEXTRA_COUNT 8
+
+/*
+ * Note that these structures *do not* map directly to the CONTEXT
+ * structure defined in WinNT.h in the Windows Mobile SDK. That structure
+ * does not accomodate VFPv3, and I'm unsure if it was ever used in the
+ * wild anyway, as Windows CE only seems to produce "cedumps" which
+ * are not exactly minidumps.
+ */
+typedef struct {
+ uint64_t fpscr; /* FPU status register */
+
+ /* 32 64-bit floating point registers, d0 .. d31. */
+ uint64_t regs[MD_FLOATINGSAVEAREA_ARM_FPR_COUNT];
+
+ /* Miscellaneous control words */
+ uint32_t extra[MD_FLOATINGSAVEAREA_ARM_FPEXTRA_COUNT];
+} MDFloatingSaveAreaARM;
+
+#define MD_CONTEXT_ARM_GPR_COUNT 16
+
+typedef struct {
+ /* The next field determines the layout of the structure, and which parts
+ * of it are populated
+ */
+ uint32_t context_flags;
+
+ /* 16 32-bit integer registers, r0 .. r15
+ * Note the following fixed uses:
+ * r13 is the stack pointer
+ * r14 is the link register
+ * r15 is the program counter
+ */
+ uint32_t iregs[MD_CONTEXT_ARM_GPR_COUNT];
+
+ /* CPSR (flags, basically): 32 bits:
+ bit 31 - N (negative)
+ bit 30 - Z (zero)
+ bit 29 - C (carry)
+ bit 28 - V (overflow)
+ bit 27 - Q (saturation flag, sticky)
+ All other fields -- ignore */
+ uint32_t cpsr;
+
+ /* The next field is included with MD_CONTEXT_ARM_FLOATING_POINT */
+ MDFloatingSaveAreaARM float_save;
+
+} MDRawContextARM;
+
+/* Indices into iregs for registers with a dedicated or conventional
+ * purpose.
+ */
+enum MDARMRegisterNumbers {
+ MD_CONTEXT_ARM_REG_IOS_FP = 7,
+ MD_CONTEXT_ARM_REG_FP = 11,
+ MD_CONTEXT_ARM_REG_SP = 13,
+ MD_CONTEXT_ARM_REG_LR = 14,
+ MD_CONTEXT_ARM_REG_PC = 15
+};
+
+/* For (MDRawContextARM).context_flags. These values indicate the type of
+ * context stored in the structure. */
+/* CONTEXT_ARM from the Windows CE 5.0 SDK. This value isn't correct
+ * because this bit can be used for flags. Presumably this value was
+ * never actually used in minidumps, but only in "CEDumps" which
+ * are a whole parallel minidump file format for Windows CE.
+ * Therefore, Breakpad defines its own value for ARM CPUs.
+ */
+#define MD_CONTEXT_ARM_OLD 0x00000040
+/* This value was chosen to avoid likely conflicts with MD_CONTEXT_*
+ * for other CPUs. */
+#define MD_CONTEXT_ARM 0x40000000
+#define MD_CONTEXT_ARM_INTEGER (MD_CONTEXT_ARM | 0x00000002)
+#define MD_CONTEXT_ARM_FLOATING_POINT (MD_CONTEXT_ARM | 0x00000004)
+
+#define MD_CONTEXT_ARM_FULL (MD_CONTEXT_ARM_INTEGER | \
+ MD_CONTEXT_ARM_FLOATING_POINT)
+
+#define MD_CONTEXT_ARM_ALL (MD_CONTEXT_ARM_INTEGER | \
+ MD_CONTEXT_ARM_FLOATING_POINT)
+
+#endif /* GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_ARM_H__ */
diff --git a/toolkit/crashreporter/google-breakpad/src/google_breakpad/common/minidump_cpu_arm64.h b/toolkit/crashreporter/google-breakpad/src/google_breakpad/common/minidump_cpu_arm64.h
new file mode 100644
index 0000000000..a94962009e
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/google_breakpad/common/minidump_cpu_arm64.h
@@ -0,0 +1,192 @@
+/* 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. */
+
+/* minidump_format.h: A cross-platform reimplementation of minidump-related
+ * portions of DbgHelp.h from the Windows Platform SDK.
+ *
+ * (This is C99 source, please don't corrupt it with C++.)
+ *
+ * This file contains the necessary definitions to read minidump files
+ * produced on ARM. These files may be read on any platform provided
+ * that the alignments of these structures on the processing system are
+ * identical to the alignments of these structures on the producing system.
+ * For this reason, precise-sized types are used. The structures defined
+ * by this file have been laid out to minimize alignment problems by
+ * ensuring that all members are aligned on their natural boundaries.
+ * In some cases, tail-padding may be significant when different ABIs specify
+ * different tail-padding behaviors. To avoid problems when reading or
+ * writing affected structures, MD_*_SIZE macros are provided where needed,
+ * containing the useful size of the structures without padding.
+ *
+ * Structures that are defined by Microsoft to contain a zero-length array
+ * are instead defined here to contain an array with one element, as
+ * zero-length arrays are forbidden by standard C and C++. In these cases,
+ * *_minsize constants are provided to be used in place of sizeof. For a
+ * cleaner interface to these sizes when using C++, see minidump_size.h.
+ *
+ * These structures are also sufficient to populate minidump files.
+ *
+ * Because precise data type sizes are crucial for this implementation to
+ * function properly and portably, a set of primitive types with known sizes
+ * are used as the basis of each structure defined by this file.
+ *
+ * Author: Colin Blundell
+ */
+
+/*
+ * ARM64 support
+ */
+
+#ifndef GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_ARM64_H__
+#define GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_ARM64_H__
+
+#include "google_breakpad/common/breakpad_types.h"
+
+#define MD_FLOATINGSAVEAREA_ARM64_FPR_COUNT 32
+#define MD_CONTEXT_ARM64_GPR_COUNT 33
+
+typedef struct {
+ /* 32 128-bit floating point registers, d0 .. d31. */
+ uint128_struct regs[MD_FLOATINGSAVEAREA_ARM64_FPR_COUNT];
+
+ uint32_t fpcr; /* FPU control register */
+ uint32_t fpsr; /* FPU status register */
+} MDFloatingSaveAreaARM64;
+
+/* For (MDRawContextARM64).context_flags. These values indicate the type of
+ * context stored in the structure. */
+#define MD_CONTEXT_ARM64 0x00400000
+#define MD_CONTEXT_ARM64_CONTROL (MD_CONTEXT_ARM64 | 0x00000001)
+#define MD_CONTEXT_ARM64_INTEGER (MD_CONTEXT_ARM64 | 0x00000002)
+#define MD_CONTEXT_ARM64_FLOATING_POINT (MD_CONTEXT_ARM64 | 0x00000004)
+#define MD_CONTEXT_ARM64_DEBUG (MD_CONTEXT_ARM64 | 0x00000008)
+#define MD_CONTEXT_ARM64_FULL (MD_CONTEXT_ARM64_CONTROL | \
+ MD_CONTEXT_ARM64_INTEGER | \
+ MD_CONTEXT_ARM64_FLOATING_POINT)
+#define MD_CONTEXT_ARM64_ALL (MD_CONTEXT_ARM64_FULL | MD_CONTEXT_ARM64_DEBUG)
+
+/* Use the same 32-bit alignment when accessing these structures from 64-bit
+ * code as is used natively in 32-bit code. */
+#pragma pack(push, 4)
+
+typedef struct {
+ /* Determines which fields of this struct are populated */
+ uint32_t context_flags;
+
+ /* CPSR (flags, basically): 32 bits:
+ bit 31 - N (negative)
+ bit 30 - Z (zero)
+ bit 29 - C (carry)
+ bit 28 - V (overflow)
+ bit 27 - Q (saturation flag, sticky)
+ All other fields -- ignore */
+ uint32_t cpsr;
+
+ /* 33 64-bit integer registers, x0 .. x31 + the PC
+ * Note the following fixed uses:
+ * x29 is the frame pointer
+ * x30 is the link register
+ * x31 is the stack pointer
+ * The PC is effectively x32.
+ */
+ uint64_t iregs[MD_CONTEXT_ARM64_GPR_COUNT];
+
+ /* The next field is included with MD_CONTEXT64_ARM_FLOATING_POINT */
+ MDFloatingSaveAreaARM64 float_save;
+
+ uint32_t bcr[8];
+ uint64_t bvr[8];
+ uint32_t wcr[2];
+ uint64_t wvr[2];
+} MDRawContextARM64;
+
+typedef struct {
+ uint32_t fpsr; /* FPU status register */
+ uint32_t fpcr; /* FPU control register */
+
+ /* 32 128-bit floating point registers, d0 .. d31. */
+ uint128_struct regs[MD_FLOATINGSAVEAREA_ARM64_FPR_COUNT];
+} MDFloatingSaveAreaARM64_Old;
+
+typedef struct {
+ /* The next field determines the layout of the structure, and which parts
+ * of it are populated
+ */
+ uint64_t context_flags;
+
+ /* 33 64-bit integer registers, x0 .. x31 + the PC
+ * Note the following fixed uses:
+ * x29 is the frame pointer
+ * x30 is the link register
+ * x31 is the stack pointer
+ * The PC is effectively x32.
+ */
+ uint64_t iregs[MD_CONTEXT_ARM64_GPR_COUNT];
+
+ /* CPSR (flags, basically): 32 bits:
+ bit 31 - N (negative)
+ bit 30 - Z (zero)
+ bit 29 - C (carry)
+ bit 28 - V (overflow)
+ bit 27 - Q (saturation flag, sticky)
+ All other fields -- ignore */
+ uint32_t cpsr;
+
+ /* The next field is included with MD_CONTEXT64_ARM_FLOATING_POINT */
+ MDFloatingSaveAreaARM64_Old float_save;
+
+} MDRawContextARM64_Old;
+
+#pragma pack(pop)
+
+/* Indices into iregs for registers with a dedicated or conventional
+ * purpose.
+ */
+enum MDARM64RegisterNumbers {
+ MD_CONTEXT_ARM64_REG_FP = 29,
+ MD_CONTEXT_ARM64_REG_LR = 30,
+ MD_CONTEXT_ARM64_REG_SP = 31,
+ MD_CONTEXT_ARM64_REG_PC = 32
+};
+
+/* For (MDRawContextARM64_Old).context_flags. These values indicate the type of
+ * context stored in the structure. MD_CONTEXT_ARM64_OLD is Breakpad-defined.
+ * This value was chosen to avoid likely conflicts with MD_CONTEXT_*
+ * for other CPUs. */
+#define MD_CONTEXT_ARM64_OLD 0x80000000
+#define MD_CONTEXT_ARM64_INTEGER_OLD (MD_CONTEXT_ARM64_OLD | 0x00000002)
+#define MD_CONTEXT_ARM64_FLOATING_POINT_OLD (MD_CONTEXT_ARM64_OLD | 0x00000004)
+
+#define MD_CONTEXT_ARM64_FULL_OLD (MD_CONTEXT_ARM64_INTEGER_OLD | \
+ MD_CONTEXT_ARM64_FLOATING_POINT_OLD)
+
+#define MD_CONTEXT_ARM64_ALL_OLD (MD_CONTEXT_ARM64_INTEGER_OLD | \
+ MD_CONTEXT_ARM64_FLOATING_POINT_OLD)
+
+#endif /* GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_ARM64_H__ */
diff --git a/toolkit/crashreporter/google-breakpad/src/google_breakpad/common/minidump_cpu_mips.h b/toolkit/crashreporter/google-breakpad/src/google_breakpad/common/minidump_cpu_mips.h
new file mode 100644
index 0000000000..f4e2b5891c
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/google_breakpad/common/minidump_cpu_mips.h
@@ -0,0 +1,176 @@
+/* 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. */
+
+/* minidump_format.h: A cross-platform reimplementation of minidump-related
+ * portions of DbgHelp.h from the Windows Platform SDK.
+ *
+ * (This is C99 source, please don't corrupt it with C++.)
+ *
+ * This file contains the necessary definitions to read minidump files
+ * produced on MIPS. These files may be read on any platform provided
+ * that the alignments of these structures on the processing system are
+ * identical to the alignments of these structures on the producing system.
+ * For this reason, precise-sized types are used. The structures defined
+ * by this file have been laid out to minimize alignment problems by
+ * ensuring that all members are aligned on their natural boundaries.
+ * In some cases, tail-padding may be significant when different ABIs specify
+ * different tail-padding behaviors. To avoid problems when reading or
+ * writing affected structures, MD_*_SIZE macros are provided where needed,
+ * containing the useful size of the structures without padding.
+ *
+ * Structures that are defined by Microsoft to contain a zero-length array
+ * are instead defined here to contain an array with one element, as
+ * zero-length arrays are forbidden by standard C and C++. In these cases,
+ * *_minsize constants are provided to be used in place of sizeof. For a
+ * cleaner interface to these sizes when using C++, see minidump_size.h.
+ *
+ * These structures are also sufficient to populate minidump files.
+ *
+ * Because precise data type sizes are crucial for this implementation to
+ * function properly and portably, a set of primitive types with known sizes
+ * are used as the basis of each structure defined by this file.
+ *
+ * Author: Chris Dearman
+ */
+
+/*
+ * MIPS support
+ */
+
+#ifndef GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_MIPS_H__
+#define GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_MIPS_H__
+
+#define MD_CONTEXT_MIPS_GPR_COUNT 32
+#define MD_FLOATINGSAVEAREA_MIPS_FPR_COUNT 32
+#define MD_CONTEXT_MIPS_DSP_COUNT 3
+
+/*
+ * Note that these structures *do not* map directly to the CONTEXT
+ * structure defined in WinNT.h in the Windows Mobile SDK. That structure
+ * does not accomodate VFPv3, and I'm unsure if it was ever used in the
+ * wild anyway, as Windows CE only seems to produce "cedumps" which
+ * are not exactly minidumps.
+ */
+typedef struct {
+ /* 32 64-bit floating point registers, f0..f31 */
+ uint64_t regs[MD_FLOATINGSAVEAREA_MIPS_FPR_COUNT];
+
+ uint32_t fpcsr; /* FPU status register. */
+ uint32_t fir; /* FPU implementation register. */
+} MDFloatingSaveAreaMIPS;
+
+typedef struct {
+ /* The next field determines the layout of the structure, and which parts
+ * of it are populated.
+ */
+ uint32_t context_flags;
+ uint32_t _pad0;
+
+ /* 32 64-bit integer registers, r0..r31.
+ * Note the following fixed uses:
+ * r29 is the stack pointer.
+ * r31 is the return address.
+ */
+ uint64_t iregs[MD_CONTEXT_MIPS_GPR_COUNT];
+
+ /* multiply/divide result. */
+ uint64_t mdhi, mdlo;
+
+ /* DSP accumulators. */
+ uint32_t hi[MD_CONTEXT_MIPS_DSP_COUNT];
+ uint32_t lo[MD_CONTEXT_MIPS_DSP_COUNT];
+ uint32_t dsp_control;
+ uint32_t _pad1;
+
+ uint64_t epc;
+ uint64_t badvaddr;
+ uint32_t status;
+ uint32_t cause;
+
+ /* The next field is included with MD_CONTEXT_MIPS_FLOATING_POINT. */
+ MDFloatingSaveAreaMIPS float_save;
+
+} MDRawContextMIPS;
+
+/* Indices into iregs for registers with a dedicated or conventional
+ * purpose.
+ */
+enum MDMIPSRegisterNumbers {
+ MD_CONTEXT_MIPS_REG_S0 = 16,
+ MD_CONTEXT_MIPS_REG_S1 = 17,
+ MD_CONTEXT_MIPS_REG_S2 = 18,
+ MD_CONTEXT_MIPS_REG_S3 = 19,
+ MD_CONTEXT_MIPS_REG_S4 = 20,
+ MD_CONTEXT_MIPS_REG_S5 = 21,
+ MD_CONTEXT_MIPS_REG_S6 = 22,
+ MD_CONTEXT_MIPS_REG_S7 = 23,
+ MD_CONTEXT_MIPS_REG_GP = 28,
+ MD_CONTEXT_MIPS_REG_SP = 29,
+ MD_CONTEXT_MIPS_REG_FP = 30,
+ MD_CONTEXT_MIPS_REG_RA = 31,
+};
+
+/* For (MDRawContextMIPS).context_flags. These values indicate the type of
+ * context stored in the structure. */
+/* CONTEXT_MIPS from the Windows CE 5.0 SDK. This value isn't correct
+ * because this bit can be used for flags. Presumably this value was
+ * never actually used in minidumps, but only in "CEDumps" which
+ * are a whole parallel minidump file format for Windows CE.
+ * Therefore, Breakpad defines its own value for MIPS CPUs.
+ */
+#define MD_CONTEXT_MIPS 0x00040000
+#define MD_CONTEXT_MIPS_INTEGER (MD_CONTEXT_MIPS | 0x00000002)
+#define MD_CONTEXT_MIPS_FLOATING_POINT (MD_CONTEXT_MIPS | 0x00000004)
+#define MD_CONTEXT_MIPS_DSP (MD_CONTEXT_MIPS | 0x00000008)
+
+#define MD_CONTEXT_MIPS_FULL (MD_CONTEXT_MIPS_INTEGER | \
+ MD_CONTEXT_MIPS_FLOATING_POINT | \
+ MD_CONTEXT_MIPS_DSP)
+
+#define MD_CONTEXT_MIPS_ALL (MD_CONTEXT_MIPS_INTEGER | \
+ MD_CONTEXT_MIPS_FLOATING_POINT \
+ MD_CONTEXT_MIPS_DSP)
+
+/**
+ * Breakpad defines for MIPS64
+ */
+#define MD_CONTEXT_MIPS64 0x00080000
+#define MD_CONTEXT_MIPS64_INTEGER (MD_CONTEXT_MIPS64 | 0x00000002)
+#define MD_CONTEXT_MIPS64_FLOATING_POINT (MD_CONTEXT_MIPS64 | 0x00000004)
+#define MD_CONTEXT_MIPS64_DSP (MD_CONTEXT_MIPS64 | 0x00000008)
+
+#define MD_CONTEXT_MIPS64_FULL (MD_CONTEXT_MIPS64_INTEGER | \
+ MD_CONTEXT_MIPS64_FLOATING_POINT | \
+ MD_CONTEXT_MIPS64_DSP)
+
+#define MD_CONTEXT_MIPS64_ALL (MD_CONTEXT_MIPS64_INTEGER | \
+ MD_CONTEXT_MIPS64_FLOATING_POINT \
+ MD_CONTEXT_MIPS64_DSP)
+
+#endif // GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_MIPS_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/google_breakpad/common/minidump_cpu_ppc.h b/toolkit/crashreporter/google-breakpad/src/google_breakpad/common/minidump_cpu_ppc.h
new file mode 100644
index 0000000000..fcc85cd9b0
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/google_breakpad/common/minidump_cpu_ppc.h
@@ -0,0 +1,159 @@
+/* Copyright (c) 2006, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
+
+/* minidump_format.h: A cross-platform reimplementation of minidump-related
+ * portions of DbgHelp.h from the Windows Platform SDK.
+ *
+ * (This is C99 source, please don't corrupt it with C++.)
+ *
+ * This file contains the necessary definitions to read minidump files
+ * produced on ppc. These files may be read on any platform provided
+ * that the alignments of these structures on the processing system are
+ * identical to the alignments of these structures on the producing system.
+ * For this reason, precise-sized types are used. The structures defined
+ * by this file have been laid out to minimize alignment problems by ensuring
+ * ensuring that all members are aligned on their natural boundaries. In
+ * In some cases, tail-padding may be significant when different ABIs specify
+ * different tail-padding behaviors. To avoid problems when reading or
+ * writing affected structures, MD_*_SIZE macros are provided where needed,
+ * containing the useful size of the structures without padding.
+ *
+ * Structures that are defined by Microsoft to contain a zero-length array
+ * are instead defined here to contain an array with one element, as
+ * zero-length arrays are forbidden by standard C and C++. In these cases,
+ * *_minsize constants are provided to be used in place of sizeof. For a
+ * cleaner interface to these sizes when using C++, see minidump_size.h.
+ *
+ * These structures are also sufficient to populate minidump files.
+ *
+ * These definitions may be extended to support handling minidump files
+ * for other CPUs and other operating systems.
+ *
+ * Because precise data type sizes are crucial for this implementation to
+ * function properly and portably in terms of interoperability with minidumps
+ * produced by DbgHelp on Windows, a set of primitive types with known sizes
+ * are used as the basis of each structure defined by this file. DbgHelp
+ * on Windows is assumed to be the reference implementation; this file
+ * seeks to provide a cross-platform compatible implementation. To avoid
+ * collisions with the types and values defined and used by DbgHelp in the
+ * event that this implementation is used on Windows, each type and value
+ * defined here is given a new name, beginning with "MD". Names of the
+ * equivalent types and values in the Windows Platform SDK are given in
+ * comments.
+ *
+ * Author: Mark Mentovai
+ * Change to split into its own file: Neal Sidhwaney */
+
+/*
+ * Breakpad minidump extension for PowerPC support. Based on Darwin/Mac OS X'
+ * mach/ppc/_types.h
+ */
+
+#ifndef GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_PPC_H__
+#define GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_PPC_H__
+
+/* Use the same 32-bit alignment when accessing these structures from 64-bit
+ * code as is used natively in 32-bit code. */
+#pragma pack(push, 4)
+
+#define MD_FLOATINGSAVEAREA_PPC_FPR_COUNT 32
+
+typedef struct {
+ /* fpregs is a double[32] in mach/ppc/_types.h, but a uint64_t is used
+ * here for precise sizing. */
+ uint64_t fpregs[MD_FLOATINGSAVEAREA_PPC_FPR_COUNT];
+ uint32_t fpscr_pad;
+ uint32_t fpscr; /* Status/control */
+} MDFloatingSaveAreaPPC; /* Based on ppc_float_state */
+
+
+#define MD_VECTORSAVEAREA_PPC_VR_COUNT 32
+
+typedef struct {
+ /* Vector registers (including vscr) are 128 bits, but mach/ppc/_types.h
+ * exposes them as four 32-bit quantities. */
+ uint128_struct save_vr[MD_VECTORSAVEAREA_PPC_VR_COUNT];
+ uint128_struct save_vscr; /* Status/control */
+ uint32_t save_pad5[4];
+ uint32_t save_vrvalid; /* Indicates which vector registers are saved */
+ uint32_t save_pad6[7];
+} MDVectorSaveAreaPPC; /* ppc_vector_state */
+
+
+#define MD_CONTEXT_PPC_GPR_COUNT 32
+
+typedef struct {
+ /* context_flags is not present in ppc_thread_state, but it aids
+ * identification of MDRawContextPPC among other raw context types,
+ * and it guarantees alignment when we get to float_save. */
+ uint32_t context_flags;
+
+ uint32_t srr0; /* Machine status save/restore: stores pc
+ * (instruction) */
+ uint32_t srr1; /* Machine status save/restore: stores msr
+ * (ps, program/machine state) */
+ /* ppc_thread_state contains 32 fields, r0 .. r31. Here, an array is
+ * used for brevity. */
+ uint32_t gpr[MD_CONTEXT_PPC_GPR_COUNT];
+ uint32_t cr; /* Condition */
+ uint32_t xer; /* Integer (fiXed-point) exception */
+ uint32_t lr; /* Link */
+ uint32_t ctr; /* Count */
+ uint32_t mq; /* Multiply/Quotient (PPC 601, POWER only) */
+ uint32_t vrsave; /* Vector save */
+
+ /* float_save and vector_save aren't present in ppc_thread_state, but
+ * are represented in separate structures that still define a thread's
+ * context. */
+ MDFloatingSaveAreaPPC float_save;
+ MDVectorSaveAreaPPC vector_save;
+} MDRawContextPPC; /* Based on ppc_thread_state */
+
+/* Indices into gpr for registers with a dedicated or conventional purpose. */
+enum MDPPCRegisterNumbers {
+ MD_CONTEXT_PPC_REG_SP = 1
+};
+
+#pragma pack(pop)
+
+/* For (MDRawContextPPC).context_flags. These values indicate the type of
+ * context stored in the structure. MD_CONTEXT_PPC is Breakpad-defined. Its
+ * value was chosen to avoid likely conflicts with MD_CONTEXT_* for other
+ * CPUs. */
+#define MD_CONTEXT_PPC 0x20000000
+#define MD_CONTEXT_PPC_BASE (MD_CONTEXT_PPC | 0x00000001)
+#define MD_CONTEXT_PPC_FLOATING_POINT (MD_CONTEXT_PPC | 0x00000008)
+#define MD_CONTEXT_PPC_VECTOR (MD_CONTEXT_PPC | 0x00000020)
+
+#define MD_CONTEXT_PPC_FULL MD_CONTEXT_PPC_BASE
+#define MD_CONTEXT_PPC_ALL (MD_CONTEXT_PPC_FULL | \
+ MD_CONTEXT_PPC_FLOATING_POINT | \
+ MD_CONTEXT_PPC_VECTOR)
+
+#endif /* GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_PPC_H__ */
diff --git a/toolkit/crashreporter/google-breakpad/src/google_breakpad/common/minidump_cpu_ppc64.h b/toolkit/crashreporter/google-breakpad/src/google_breakpad/common/minidump_cpu_ppc64.h
new file mode 100644
index 0000000000..61f4193865
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/google_breakpad/common/minidump_cpu_ppc64.h
@@ -0,0 +1,134 @@
+/* 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. */
+
+/* minidump_format.h: A cross-platform reimplementation of minidump-related
+ * portions of DbgHelp.h from the Windows Platform SDK.
+ *
+ * (This is C99 source, please don't corrupt it with C++.)
+ *
+ * This file contains the necessary definitions to read minidump files
+ * produced on ppc64. These files may be read on any platform provided
+ * that the alignments of these structures on the processing system are
+ * identical to the alignments of these structures on the producing system.
+ * For this reason, precise-sized types are used. The structures defined
+ * by this file have been laid out to minimize alignment problems by ensuring
+ * ensuring that all members are aligned on their natural boundaries. In
+ * In some cases, tail-padding may be significant when different ABIs specify
+ * different tail-padding behaviors. To avoid problems when reading or
+ * writing affected structures, MD_*_SIZE macros are provided where needed,
+ * containing the useful size of the structures without padding.
+ *
+ * Structures that are defined by Microsoft to contain a zero-length array
+ * are instead defined here to contain an array with one element, as
+ * zero-length arrays are forbidden by standard C and C++. In these cases,
+ * *_minsize constants are provided to be used in place of sizeof. For a
+ * cleaner interface to these sizes when using C++, see minidump_size.h.
+ *
+ * These structures are also sufficient to populate minidump files.
+ *
+ * These definitions may be extended to support handling minidump files
+ * for other CPUs and other operating systems.
+ *
+ * Because precise data type sizes are crucial for this implementation to
+ * function properly and portably in terms of interoperability with minidumps
+ * produced by DbgHelp on Windows, a set of primitive types with known sizes
+ * are used as the basis of each structure defined by this file. DbgHelp
+ * on Windows is assumed to be the reference implementation; this file
+ * seeks to provide a cross-platform compatible implementation. To avoid
+ * collisions with the types and values defined and used by DbgHelp in the
+ * event that this implementation is used on Windows, each type and value
+ * defined here is given a new name, beginning with "MD". Names of the
+ * equivalent types and values in the Windows Platform SDK are given in
+ * comments.
+ *
+ * Author: Neal Sidhwaney */
+
+
+/*
+ * Breakpad minidump extension for PPC64 support. Based on Darwin/Mac OS X'
+ * mach/ppc/_types.h
+ */
+
+#ifndef GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_PPC64_H__
+#define GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_PPC64_H__
+
+#include "minidump_cpu_ppc.h"
+
+// these types are the same in ppc64 & ppc
+typedef MDFloatingSaveAreaPPC MDFloatingSaveAreaPPC64;
+typedef MDVectorSaveAreaPPC MDVectorSaveAreaPPC64;
+
+#define MD_CONTEXT_PPC64_GPR_COUNT MD_CONTEXT_PPC_GPR_COUNT
+
+typedef struct {
+ /* context_flags is not present in ppc_thread_state, but it aids
+ * identification of MDRawContextPPC among other raw context types,
+ * and it guarantees alignment when we get to float_save. */
+ uint64_t context_flags;
+
+ uint64_t srr0; /* Machine status save/restore: stores pc
+ * (instruction) */
+ uint64_t srr1; /* Machine status save/restore: stores msr
+ * (ps, program/machine state) */
+ /* ppc_thread_state contains 32 fields, r0 .. r31. Here, an array is
+ * used for brevity. */
+ uint64_t gpr[MD_CONTEXT_PPC64_GPR_COUNT];
+ uint64_t cr; /* Condition */
+ uint64_t xer; /* Integer (fiXed-point) exception */
+ uint64_t lr; /* Link */
+ uint64_t ctr; /* Count */
+ uint64_t vrsave; /* Vector save */
+
+ /* float_save and vector_save aren't present in ppc_thread_state, but
+ * are represented in separate structures that still define a thread's
+ * context. */
+ MDFloatingSaveAreaPPC float_save;
+ MDVectorSaveAreaPPC vector_save;
+} MDRawContextPPC64; /* Based on ppc_thread_state */
+
+/* Indices into gpr for registers with a dedicated or conventional purpose. */
+enum MDPPC64RegisterNumbers {
+ MD_CONTEXT_PPC64_REG_SP = 1
+};
+
+/* For (MDRawContextPPC).context_flags. These values indicate the type of
+ * context stored in the structure. MD_CONTEXT_PPC is Breakpad-defined. Its
+ * value was chosen to avoid likely conflicts with MD_CONTEXT_* for other
+ * CPUs. */
+#define MD_CONTEXT_PPC64 0x01000000
+#define MD_CONTEXT_PPC64_BASE (MD_CONTEXT_PPC64 | 0x00000001)
+#define MD_CONTEXT_PPC64_FLOATING_POINT (MD_CONTEXT_PPC64 | 0x00000008)
+#define MD_CONTEXT_PPC64_VECTOR (MD_CONTEXT_PPC64 | 0x00000020)
+
+#define MD_CONTEXT_PPC64_FULL MD_CONTEXT_PPC64_BASE
+#define MD_CONTEXT_PPC64_ALL (MD_CONTEXT_PPC64_FULL | \
+ MD_CONTEXT_PPC64_FLOATING_POINT | \
+ MD_CONTEXT_PPC64_VECTOR)
+
+#endif /* GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_PPC64_H__ */
diff --git a/toolkit/crashreporter/google-breakpad/src/google_breakpad/common/minidump_cpu_sparc.h b/toolkit/crashreporter/google-breakpad/src/google_breakpad/common/minidump_cpu_sparc.h
new file mode 100644
index 0000000000..95c08b1743
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/google_breakpad/common/minidump_cpu_sparc.h
@@ -0,0 +1,163 @@
+/* Copyright (c) 2006, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
+
+/* minidump_format.h: A cross-platform reimplementation of minidump-related
+ * portions of DbgHelp.h from the Windows Platform SDK.
+ *
+ * (This is C99 source, please don't corrupt it with C++.)
+ *
+ * This file contains the necessary definitions to read minidump files
+ * produced on sparc. These files may be read on any platform provided
+ * that the alignments of these structures on the processing system are
+ * identical to the alignments of these structures on the producing system.
+ * For this reason, precise-sized types are used. The structures defined
+ * by this file have been laid out to minimize alignment problems by ensuring
+ * ensuring that all members are aligned on their natural boundaries. In
+ * In some cases, tail-padding may be significant when different ABIs specify
+ * different tail-padding behaviors. To avoid problems when reading or
+ * writing affected structures, MD_*_SIZE macros are provided where needed,
+ * containing the useful size of the structures without padding.
+ *
+ * Structures that are defined by Microsoft to contain a zero-length array
+ * are instead defined here to contain an array with one element, as
+ * zero-length arrays are forbidden by standard C and C++. In these cases,
+ * *_minsize constants are provided to be used in place of sizeof. For a
+ * cleaner interface to these sizes when using C++, see minidump_size.h.
+ *
+ * These structures are also sufficient to populate minidump files.
+ *
+ * These definitions may be extended to support handling minidump files
+ * for other CPUs and other operating systems.
+ *
+ * Because precise data type sizes are crucial for this implementation to
+ * function properly and portably in terms of interoperability with minidumps
+ * produced by DbgHelp on Windows, a set of primitive types with known sizes
+ * are used as the basis of each structure defined by this file. DbgHelp
+ * on Windows is assumed to be the reference implementation; this file
+ * seeks to provide a cross-platform compatible implementation. To avoid
+ * collisions with the types and values defined and used by DbgHelp in the
+ * event that this implementation is used on Windows, each type and value
+ * defined here is given a new name, beginning with "MD". Names of the
+ * equivalent types and values in the Windows Platform SDK are given in
+ * comments.
+ *
+ * Author: Mark Mentovai
+ * Change to split into its own file: Neal Sidhwaney */
+
+/*
+ * SPARC support, see (solaris)sys/procfs_isa.h also
+ */
+
+#ifndef GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_SPARC_H__
+#define GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_SPARC_H__
+
+#define MD_FLOATINGSAVEAREA_SPARC_FPR_COUNT 32
+
+typedef struct {
+
+ /* FPU floating point regs */
+ uint64_t regs[MD_FLOATINGSAVEAREA_SPARC_FPR_COUNT];
+
+ uint64_t filler;
+ uint64_t fsr; /* FPU status register */
+} MDFloatingSaveAreaSPARC; /* FLOATING_SAVE_AREA */
+
+#define MD_CONTEXT_SPARC_GPR_COUNT 32
+
+typedef struct {
+ /* The next field determines the layout of the structure, and which parts
+ * of it are populated
+ */
+ uint32_t context_flags;
+ uint32_t flag_pad;
+ /*
+ * General register access (SPARC).
+ * Don't confuse definitions here with definitions in <sys/regset.h>.
+ * Registers are 32 bits for ILP32, 64 bits for LP64.
+ * SPARC V7/V8 is for 32bit, SPARC V9 is for 64bit
+ */
+
+ /* 32 Integer working registers */
+
+ /* g_r[0-7] global registers(g0-g7)
+ * g_r[8-15] out registers(o0-o7)
+ * g_r[16-23] local registers(l0-l7)
+ * g_r[24-31] in registers(i0-i7)
+ */
+ uint64_t g_r[MD_CONTEXT_SPARC_GPR_COUNT];
+
+ /* several control registers */
+
+ /* Processor State register(PSR) for SPARC V7/V8
+ * Condition Code register (CCR) for SPARC V9
+ */
+ uint64_t ccr;
+
+ uint64_t pc; /* Program Counter register (PC) */
+ uint64_t npc; /* Next Program Counter register (nPC) */
+ uint64_t y; /* Y register (Y) */
+
+ /* Address Space Identifier register (ASI) for SPARC V9
+ * WIM for SPARC V7/V8
+ */
+ uint64_t asi;
+
+ /* Floating-Point Registers State register (FPRS) for SPARC V9
+ * TBR for for SPARC V7/V8
+ */
+ uint64_t fprs;
+
+ /* The next field is included with MD_CONTEXT_SPARC_FLOATING_POINT */
+ MDFloatingSaveAreaSPARC float_save;
+
+} MDRawContextSPARC; /* CONTEXT_SPARC */
+
+/* Indices into g_r for registers with a dedicated or conventional purpose. */
+enum MDSPARCRegisterNumbers {
+ MD_CONTEXT_SPARC_REG_SP = 14
+};
+
+/* For (MDRawContextSPARC).context_flags. These values indicate the type of
+ * context stored in the structure. MD_CONTEXT_SPARC is Breakpad-defined. Its
+ * value was chosen to avoid likely conflicts with MD_CONTEXT_* for other
+ * CPUs. */
+#define MD_CONTEXT_SPARC 0x10000000
+#define MD_CONTEXT_SPARC_CONTROL (MD_CONTEXT_SPARC | 0x00000001)
+#define MD_CONTEXT_SPARC_INTEGER (MD_CONTEXT_SPARC | 0x00000002)
+#define MD_CONTEXT_SAPARC_FLOATING_POINT (MD_CONTEXT_SPARC | 0x00000004)
+#define MD_CONTEXT_SAPARC_EXTRA (MD_CONTEXT_SPARC | 0x00000008)
+
+#define MD_CONTEXT_SPARC_FULL (MD_CONTEXT_SPARC_CONTROL | \
+ MD_CONTEXT_SPARC_INTEGER)
+
+#define MD_CONTEXT_SPARC_ALL (MD_CONTEXT_SPARC_FULL | \
+ MD_CONTEXT_SAPARC_FLOATING_POINT | \
+ MD_CONTEXT_SAPARC_EXTRA)
+
+#endif /* GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_SPARC_H__ */
diff --git a/toolkit/crashreporter/google-breakpad/src/google_breakpad/common/minidump_cpu_x86.h b/toolkit/crashreporter/google-breakpad/src/google_breakpad/common/minidump_cpu_x86.h
new file mode 100644
index 0000000000..e09cb7cb52
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/google_breakpad/common/minidump_cpu_x86.h
@@ -0,0 +1,174 @@
+/* Copyright (c) 2006, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
+
+/* minidump_format.h: A cross-platform reimplementation of minidump-related
+ * portions of DbgHelp.h from the Windows Platform SDK.
+ *
+ * (This is C99 source, please don't corrupt it with C++.)
+ *
+ * This file contains the necessary definitions to read minidump files
+ * produced on x86. These files may be read on any platform provided
+ * that the alignments of these structures on the processing system are
+ * identical to the alignments of these structures on the producing system.
+ * For this reason, precise-sized types are used. The structures defined
+ * by this file have been laid out to minimize alignment problems by ensuring
+ * ensuring that all members are aligned on their natural boundaries. In
+ * In some cases, tail-padding may be significant when different ABIs specify
+ * different tail-padding behaviors. To avoid problems when reading or
+ * writing affected structures, MD_*_SIZE macros are provided where needed,
+ * containing the useful size of the structures without padding.
+ *
+ * Structures that are defined by Microsoft to contain a zero-length array
+ * are instead defined here to contain an array with one element, as
+ * zero-length arrays are forbidden by standard C and C++. In these cases,
+ * *_minsize constants are provided to be used in place of sizeof. For a
+ * cleaner interface to these sizes when using C++, see minidump_size.h.
+ *
+ * These structures are also sufficient to populate minidump files.
+ *
+ * These definitions may be extended to support handling minidump files
+ * for other CPUs and other operating systems.
+ *
+ * Because precise data type sizes are crucial for this implementation to
+ * function properly and portably in terms of interoperability with minidumps
+ * produced by DbgHelp on Windows, a set of primitive types with known sizes
+ * are used as the basis of each structure defined by this file. DbgHelp
+ * on Windows is assumed to be the reference implementation; this file
+ * seeks to provide a cross-platform compatible implementation. To avoid
+ * collisions with the types and values defined and used by DbgHelp in the
+ * event that this implementation is used on Windows, each type and value
+ * defined here is given a new name, beginning with "MD". Names of the
+ * equivalent types and values in the Windows Platform SDK are given in
+ * comments.
+ *
+ * Author: Mark Mentovai */
+
+#ifndef GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_X86_H__
+#define GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_X86_H__
+
+#define MD_FLOATINGSAVEAREA_X86_REGISTERAREA_SIZE 80
+ /* SIZE_OF_80387_REGISTERS */
+
+typedef struct {
+ uint32_t control_word;
+ uint32_t status_word;
+ uint32_t tag_word;
+ uint32_t error_offset;
+ uint32_t error_selector;
+ uint32_t data_offset;
+ uint32_t data_selector;
+
+ /* register_area contains eight 80-bit (x87 "long double") quantities for
+ * floating-point registers %st0 (%mm0) through %st7 (%mm7). */
+ uint8_t register_area[MD_FLOATINGSAVEAREA_X86_REGISTERAREA_SIZE];
+ uint32_t cr0_npx_state;
+} MDFloatingSaveAreaX86; /* FLOATING_SAVE_AREA */
+
+
+#define MD_CONTEXT_X86_EXTENDED_REGISTERS_SIZE 512
+ /* MAXIMUM_SUPPORTED_EXTENSION */
+
+typedef struct {
+ /* The next field determines the layout of the structure, and which parts
+ * of it are populated */
+ uint32_t context_flags;
+
+ /* The next 6 registers are included with MD_CONTEXT_X86_DEBUG_REGISTERS */
+ uint32_t dr0;
+ uint32_t dr1;
+ uint32_t dr2;
+ uint32_t dr3;
+ uint32_t dr6;
+ uint32_t dr7;
+
+ /* The next field is included with MD_CONTEXT_X86_FLOATING_POINT */
+ MDFloatingSaveAreaX86 float_save;
+
+ /* The next 4 registers are included with MD_CONTEXT_X86_SEGMENTS */
+ uint32_t gs;
+ uint32_t fs;
+ uint32_t es;
+ uint32_t ds;
+ /* The next 6 registers are included with MD_CONTEXT_X86_INTEGER */
+ uint32_t edi;
+ uint32_t esi;
+ uint32_t ebx;
+ uint32_t edx;
+ uint32_t ecx;
+ uint32_t eax;
+
+ /* The next 6 registers are included with MD_CONTEXT_X86_CONTROL */
+ uint32_t ebp;
+ uint32_t eip;
+ uint32_t cs; /* WinNT.h says "must be sanitized" */
+ uint32_t eflags; /* WinNT.h says "must be sanitized" */
+ uint32_t esp;
+ uint32_t ss;
+
+ /* The next field is included with MD_CONTEXT_X86_EXTENDED_REGISTERS.
+ * It contains vector (MMX/SSE) registers. It it laid out in the
+ * format used by the fxsave and fsrstor instructions, so it includes
+ * a copy of the x87 floating-point registers as well. See FXSAVE in
+ * "Intel Architecture Software Developer's Manual, Volume 2." */
+ uint8_t extended_registers[
+ MD_CONTEXT_X86_EXTENDED_REGISTERS_SIZE];
+} MDRawContextX86; /* CONTEXT */
+
+/* For (MDRawContextX86).context_flags. These values indicate the type of
+ * context stored in the structure. The high 24 bits identify the CPU, the
+ * low 8 bits identify the type of context saved. */
+#define MD_CONTEXT_X86 0x00010000
+ /* CONTEXT_i386, CONTEXT_i486: identifies CPU */
+#define MD_CONTEXT_X86_CONTROL (MD_CONTEXT_X86 | 0x00000001)
+ /* CONTEXT_CONTROL */
+#define MD_CONTEXT_X86_INTEGER (MD_CONTEXT_X86 | 0x00000002)
+ /* CONTEXT_INTEGER */
+#define MD_CONTEXT_X86_SEGMENTS (MD_CONTEXT_X86 | 0x00000004)
+ /* CONTEXT_SEGMENTS */
+#define MD_CONTEXT_X86_FLOATING_POINT (MD_CONTEXT_X86 | 0x00000008)
+ /* CONTEXT_FLOATING_POINT */
+#define MD_CONTEXT_X86_DEBUG_REGISTERS (MD_CONTEXT_X86 | 0x00000010)
+ /* CONTEXT_DEBUG_REGISTERS */
+#define MD_CONTEXT_X86_EXTENDED_REGISTERS (MD_CONTEXT_X86 | 0x00000020)
+ /* CONTEXT_EXTENDED_REGISTERS */
+#define MD_CONTEXT_X86_XSTATE (MD_CONTEXT_X86 | 0x00000040)
+ /* CONTEXT_XSTATE */
+
+#define MD_CONTEXT_X86_FULL (MD_CONTEXT_X86_CONTROL | \
+ MD_CONTEXT_X86_INTEGER | \
+ MD_CONTEXT_X86_SEGMENTS)
+ /* CONTEXT_FULL */
+
+#define MD_CONTEXT_X86_ALL (MD_CONTEXT_X86_FULL | \
+ MD_CONTEXT_X86_FLOATING_POINT | \
+ MD_CONTEXT_X86_DEBUG_REGISTERS | \
+ MD_CONTEXT_X86_EXTENDED_REGISTERS)
+ /* CONTEXT_ALL */
+
+#endif /* GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_X86_H__ */
diff --git a/toolkit/crashreporter/google-breakpad/src/google_breakpad/common/minidump_exception_fuchsia.h b/toolkit/crashreporter/google-breakpad/src/google_breakpad/common/minidump_exception_fuchsia.h
new file mode 100644
index 0000000000..f26a8a2ae0
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/google_breakpad/common/minidump_exception_fuchsia.h
@@ -0,0 +1,58 @@
+/* Copyright (c) 2019, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
+
+/* minidump_exception_fuchsia.h: A definition of exception codes for Fuchsia.
+ *
+ * Author: Ivan Penkov */
+
+#ifndef GOOGLE_BREAKPAD_COMMON_MINIDUMP_EXCEPTION_FUCHSIA_H_
+#define GOOGLE_BREAKPAD_COMMON_MINIDUMP_EXCEPTION_FUCHSIA_H_
+
+#include <stddef.h>
+
+#include "google_breakpad/common/breakpad_types.h"
+
+// Based on zircon/system/public/zircon/syscalls/exception.h
+typedef enum {
+ // Architectural exceptions
+ MD_EXCEPTION_CODE_FUCHSIA_GENERAL = 0x8,
+ MD_EXCEPTION_CODE_FUCHSIA_FATAL_PAGE_FAULT = 0x108,
+ MD_EXCEPTION_CODE_FUCHSIA_UNDEFINED_INSTRUCTION = 0x208,
+ MD_EXCEPTION_CODE_FUCHSIA_SW_BREAKPOINT = 0x308,
+ MD_EXCEPTION_CODE_FUCHSIA_HW_BREAKPOINT = 0x408,
+ MD_EXCEPTION_CODE_FUCHSIA_UNALIGNED_ACCESS = 0x508,
+ //
+ // Synthetic exceptions
+ MD_EXCEPTION_CODE_FUCHSIA_THREAD_STARTING = 0x8008,
+ MD_EXCEPTION_CODE_FUCHSIA_THREAD_EXITING = 0x8108,
+ MD_EXCEPTION_CODE_FUCHSIA_POLICY_ERROR = 0x8208,
+ MD_EXCEPTION_CODE_FUCHSIA_PROCESS_STARTING = 0x8308,
+} MDExceptionCodeFuchsia;
+
+#endif // GOOGLE_BREAKPAD_COMMON_MINIDUMP_EXCEPTION_FUCHSIA_H_
diff --git a/toolkit/crashreporter/google-breakpad/src/google_breakpad/common/minidump_exception_linux.h b/toolkit/crashreporter/google-breakpad/src/google_breakpad/common/minidump_exception_linux.h
new file mode 100644
index 0000000000..19e2f2588c
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/google_breakpad/common/minidump_exception_linux.h
@@ -0,0 +1,129 @@
+/* Copyright (c) 2006, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
+
+/* minidump_exception_linux.h: A definition of exception codes for
+ * Linux
+ *
+ * (This is C99 source, please don't corrupt it with C++.)
+ *
+ * Author: Mark Mentovai
+ * Split into its own file: Neal Sidhwaney */
+
+
+#ifndef GOOGLE_BREAKPAD_COMMON_MINIDUMP_EXCEPTION_LINUX_H__
+#define GOOGLE_BREAKPAD_COMMON_MINIDUMP_EXCEPTION_LINUX_H__
+
+#include <stddef.h>
+
+#include "google_breakpad/common/breakpad_types.h"
+
+
+/* For (MDException).exception_code. These values come from bits/signum.h.
+ */
+typedef enum {
+ MD_EXCEPTION_CODE_LIN_SIGHUP = 1, /* Hangup (POSIX) */
+ MD_EXCEPTION_CODE_LIN_SIGINT = 2, /* Interrupt (ANSI) */
+ MD_EXCEPTION_CODE_LIN_SIGQUIT = 3, /* Quit (POSIX) */
+ MD_EXCEPTION_CODE_LIN_SIGILL = 4, /* Illegal instruction (ANSI) */
+ MD_EXCEPTION_CODE_LIN_SIGTRAP = 5, /* Trace trap (POSIX) */
+ MD_EXCEPTION_CODE_LIN_SIGABRT = 6, /* Abort (ANSI) */
+ MD_EXCEPTION_CODE_LIN_SIGBUS = 7, /* BUS error (4.2 BSD) */
+ MD_EXCEPTION_CODE_LIN_SIGFPE = 8, /* Floating-point exception (ANSI) */
+ MD_EXCEPTION_CODE_LIN_SIGKILL = 9, /* Kill, unblockable (POSIX) */
+ MD_EXCEPTION_CODE_LIN_SIGUSR1 = 10, /* User-defined signal 1 (POSIX). */
+ MD_EXCEPTION_CODE_LIN_SIGSEGV = 11, /* Segmentation violation (ANSI) */
+ MD_EXCEPTION_CODE_LIN_SIGUSR2 = 12, /* User-defined signal 2 (POSIX) */
+ MD_EXCEPTION_CODE_LIN_SIGPIPE = 13, /* Broken pipe (POSIX) */
+ MD_EXCEPTION_CODE_LIN_SIGALRM = 14, /* Alarm clock (POSIX) */
+ MD_EXCEPTION_CODE_LIN_SIGTERM = 15, /* Termination (ANSI) */
+ MD_EXCEPTION_CODE_LIN_SIGSTKFLT = 16, /* Stack faultd */
+ MD_EXCEPTION_CODE_LIN_SIGCHLD = 17, /* Child status has changed (POSIX) */
+ MD_EXCEPTION_CODE_LIN_SIGCONT = 18, /* Continue (POSIX) */
+ MD_EXCEPTION_CODE_LIN_SIGSTOP = 19, /* Stop, unblockable (POSIX) */
+ MD_EXCEPTION_CODE_LIN_SIGTSTP = 20, /* Keyboard stop (POSIX) */
+ MD_EXCEPTION_CODE_LIN_SIGTTIN = 21, /* Background read from tty (POSIX) */
+ MD_EXCEPTION_CODE_LIN_SIGTTOU = 22, /* Background write to tty (POSIX) */
+ MD_EXCEPTION_CODE_LIN_SIGURG = 23,
+ /* Urgent condition on socket (4.2 BSD) */
+ MD_EXCEPTION_CODE_LIN_SIGXCPU = 24, /* CPU limit exceeded (4.2 BSD) */
+ MD_EXCEPTION_CODE_LIN_SIGXFSZ = 25,
+ /* File size limit exceeded (4.2 BSD) */
+ MD_EXCEPTION_CODE_LIN_SIGVTALRM = 26, /* Virtual alarm clock (4.2 BSD) */
+ MD_EXCEPTION_CODE_LIN_SIGPROF = 27, /* Profiling alarm clock (4.2 BSD) */
+ MD_EXCEPTION_CODE_LIN_SIGWINCH = 28, /* Window size change (4.3 BSD, Sun) */
+ MD_EXCEPTION_CODE_LIN_SIGIO = 29, /* I/O now possible (4.2 BSD) */
+ MD_EXCEPTION_CODE_LIN_SIGPWR = 30, /* Power failure restart (System V) */
+ MD_EXCEPTION_CODE_LIN_SIGSYS = 31, /* Bad system call */
+ MD_EXCEPTION_CODE_LIN_DUMP_REQUESTED = 0xFFFFFFFF /* No exception,
+ dump requested. */
+} MDExceptionCodeLinux;
+
+/* For (MDException).exception_flags. These values come from
+ * asm-generic/siginfo.h.
+ */
+typedef enum {
+ /* Generic */
+ MD_EXCEPTION_FLAG_LIN_SI_USER = 0,
+ MD_EXCEPTION_FLAG_LIN_SI_KERNEL = 0x80,
+
+ /* SIGILL */
+ MD_EXCEPTION_FLAG_LIN_ILL_ILLOPC = 1,
+ MD_EXCEPTION_FLAG_LIN_ILL_ILLOPN = 2,
+ MD_EXCEPTION_FLAG_LIN_ILL_ILLADR = 3,
+ MD_EXCEPTION_FLAG_LIN_ILL_ILLTRP = 4,
+ MD_EXCEPTION_FLAG_LIN_ILL_PRVOPC = 5,
+ MD_EXCEPTION_FLAG_LIN_ILL_PRVREG = 6,
+ MD_EXCEPTION_FLAG_LIN_ILL_COPROC = 7,
+ MD_EXCEPTION_FLAG_LIN_ILL_BADSTK = 8,
+
+ /* SIGFPE */
+ MD_EXCEPTION_FLAG_LIN_FPE_INTDIV = 1,
+ MD_EXCEPTION_FLAG_LIN_FPE_INTOVF = 2,
+ MD_EXCEPTION_FLAG_LIN_FPE_FLTDIV = 3,
+ MD_EXCEPTION_FLAG_LIN_FPE_FLTOVF = 4,
+ MD_EXCEPTION_FLAG_LIN_FPE_FLTUND = 5,
+ MD_EXCEPTION_FLAG_LIN_FPE_FLTRES = 6,
+ MD_EXCEPTION_FLAG_LIN_FPE_FLTINV = 7,
+ MD_EXCEPTION_FLAG_LIN_FPE_FLTSUB = 8,
+
+ /* SIGSEGV */
+ MD_EXCEPTION_FLAG_LIN_SEGV_MAPERR = 1,
+ MD_EXCEPTION_FLAG_LIN_SEGV_ACCERR = 2,
+ MD_EXCEPTION_FLAG_LIN_SEGV_BNDERR = 3,
+ MD_EXCEPTION_FLAG_LIN_SEGV_PKUERR = 4,
+
+ /* SIGBUS */
+ MD_EXCEPTION_FLAG_LIN_BUS_ADRALN = 1,
+ MD_EXCEPTION_FLAG_LIN_BUS_ADRERR = 2,
+ MD_EXCEPTION_FLAG_LIN_BUS_OBJERR = 3,
+ MD_EXCEPTION_FLAG_LIN_BUS_MCEERR_AR = 4,
+ MD_EXCEPTION_FLAG_LIN_BUS_MCEERR_AO = 5,
+} MDExceptionFlagLinux;
+
+#endif /* GOOGLE_BREAKPAD_COMMON_MINIDUMP_EXCEPTION_LINUX_H__ */
diff --git a/toolkit/crashreporter/google-breakpad/src/google_breakpad/common/minidump_exception_mac.h b/toolkit/crashreporter/google-breakpad/src/google_breakpad/common/minidump_exception_mac.h
new file mode 100644
index 0000000000..b26d6c0af0
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/google_breakpad/common/minidump_exception_mac.h
@@ -0,0 +1,314 @@
+/* Copyright (c) 2006, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
+
+/* minidump_exception_mac.h: A definition of exception codes for Mac
+ * OS X
+ *
+ * (This is C99 source, please don't corrupt it with C++.)
+ *
+ * Author: Mark Mentovai
+ * Split into its own file: Neal Sidhwaney */
+
+
+#ifndef GOOGLE_BREAKPAD_COMMON_MINIDUMP_EXCEPTION_MAC_H__
+#define GOOGLE_BREAKPAD_COMMON_MINIDUMP_EXCEPTION_MAC_H__
+
+#include <stddef.h>
+
+#include "google_breakpad/common/breakpad_types.h"
+
+/* For (MDException).exception_code. Breakpad minidump extension for Mac OS X
+ * support. Based on Darwin/Mac OS X' mach/exception_types.h. This is
+ * what Mac OS X calls an "exception", not a "code". */
+typedef enum {
+ /* Exception code. The high 16 bits of exception_code contains one of
+ * these values. */
+ MD_EXCEPTION_MAC_BAD_ACCESS = 1, /* code can be a kern_return_t */
+ /* EXC_BAD_ACCESS */
+ MD_EXCEPTION_MAC_BAD_INSTRUCTION = 2, /* code is CPU-specific */
+ /* EXC_BAD_INSTRUCTION */
+ MD_EXCEPTION_MAC_ARITHMETIC = 3, /* code is CPU-specific */
+ /* EXC_ARITHMETIC */
+ MD_EXCEPTION_MAC_EMULATION = 4, /* code is CPU-specific */
+ /* EXC_EMULATION */
+ MD_EXCEPTION_MAC_SOFTWARE = 5,
+ /* EXC_SOFTWARE */
+ MD_EXCEPTION_MAC_BREAKPOINT = 6, /* code is CPU-specific */
+ /* EXC_BREAKPOINT */
+ MD_EXCEPTION_MAC_SYSCALL = 7,
+ /* EXC_SYSCALL */
+ MD_EXCEPTION_MAC_MACH_SYSCALL = 8,
+ /* EXC_MACH_SYSCALL */
+ MD_EXCEPTION_MAC_RPC_ALERT = 9,
+ /* EXC_RPC_ALERT */
+ MD_EXCEPTION_MAC_RESOURCE = 11,
+ /* EXC_RESOURCE */
+ MD_EXCEPTION_MAC_GUARD = 12,
+ /* EXC_GUARD */
+ MD_EXCEPTION_MAC_SIMULATED = 0x43507378
+ /* Fake exception code used by Crashpad's SimulateCrash ('CPsx'). */
+} MDExceptionMac;
+
+/* For (MDException).exception_flags. Breakpad minidump extension for Mac OS X
+ * support. Based on Darwin/Mac OS X' mach/ppc/exception.h and
+ * mach/i386/exception.h. This is what Mac OS X calls a "code". */
+typedef enum {
+ /* With MD_EXCEPTION_BAD_ACCESS. These are relevant kern_return_t values
+ * from mach/kern_return.h. */
+ MD_EXCEPTION_CODE_MAC_INVALID_ADDRESS = 1,
+ /* KERN_INVALID_ADDRESS */
+ MD_EXCEPTION_CODE_MAC_PROTECTION_FAILURE = 2,
+ /* KERN_PROTECTION_FAILURE */
+ MD_EXCEPTION_CODE_MAC_NO_ACCESS = 8,
+ /* KERN_NO_ACCESS */
+ MD_EXCEPTION_CODE_MAC_MEMORY_FAILURE = 9,
+ /* KERN_MEMORY_FAILURE */
+ MD_EXCEPTION_CODE_MAC_MEMORY_ERROR = 10,
+ /* KERN_MEMORY_ERROR */
+ MD_EXCEPTION_CODE_MAC_CODESIGN_ERROR = 50,
+ /* KERN_CODESIGN_ERROR */
+
+ /* With MD_EXCEPTION_SOFTWARE */
+ MD_EXCEPTION_CODE_MAC_BAD_SYSCALL = 0x00010000, /* Mach SIGSYS */
+ MD_EXCEPTION_CODE_MAC_BAD_PIPE = 0x00010001, /* Mach SIGPIPE */
+ MD_EXCEPTION_CODE_MAC_ABORT = 0x00010002, /* Mach SIGABRT */
+ /* Custom values */
+ MD_EXCEPTION_CODE_MAC_NS_EXCEPTION = 0xDEADC0DE, /* uncaught NSException */
+
+ /* With MD_EXCEPTION_MAC_BAD_ACCESS on arm */
+ MD_EXCEPTION_CODE_MAC_ARM_DA_ALIGN = 0x0101, /* EXC_ARM_DA_ALIGN */
+ MD_EXCEPTION_CODE_MAC_ARM_DA_DEBUG = 0x0102, /* EXC_ARM_DA_DEBUG */
+
+ /* With MD_EXCEPTION_MAC_BAD_INSTRUCTION on arm */
+ MD_EXCEPTION_CODE_MAC_ARM_UNDEFINED = 1, /* EXC_ARM_UNDEFINED */
+
+ /* With MD_EXCEPTION_MAC_BREAKPOINT on arm */
+ MD_EXCEPTION_CODE_MAC_ARM_BREAKPOINT = 1, /* EXC_ARM_BREAKPOINT */
+
+ /* With MD_EXCEPTION_MAC_BAD_ACCESS on ppc */
+ MD_EXCEPTION_CODE_MAC_PPC_VM_PROT_READ = 0x0101,
+ /* EXC_PPC_VM_PROT_READ */
+ MD_EXCEPTION_CODE_MAC_PPC_BADSPACE = 0x0102,
+ /* EXC_PPC_BADSPACE */
+ MD_EXCEPTION_CODE_MAC_PPC_UNALIGNED = 0x0103,
+ /* EXC_PPC_UNALIGNED */
+
+ /* With MD_EXCEPTION_MAC_BAD_INSTRUCTION on ppc */
+ MD_EXCEPTION_CODE_MAC_PPC_INVALID_SYSCALL = 1,
+ /* EXC_PPC_INVALID_SYSCALL */
+ MD_EXCEPTION_CODE_MAC_PPC_UNIMPLEMENTED_INSTRUCTION = 2,
+ /* EXC_PPC_UNIPL_INST */
+ MD_EXCEPTION_CODE_MAC_PPC_PRIVILEGED_INSTRUCTION = 3,
+ /* EXC_PPC_PRIVINST */
+ MD_EXCEPTION_CODE_MAC_PPC_PRIVILEGED_REGISTER = 4,
+ /* EXC_PPC_PRIVREG */
+ MD_EXCEPTION_CODE_MAC_PPC_TRACE = 5,
+ /* EXC_PPC_TRACE */
+ MD_EXCEPTION_CODE_MAC_PPC_PERFORMANCE_MONITOR = 6,
+ /* EXC_PPC_PERFMON */
+
+ /* With MD_EXCEPTION_MAC_ARITHMETIC on ppc */
+ MD_EXCEPTION_CODE_MAC_PPC_OVERFLOW = 1,
+ /* EXC_PPC_OVERFLOW */
+ MD_EXCEPTION_CODE_MAC_PPC_ZERO_DIVIDE = 2,
+ /* EXC_PPC_ZERO_DIVIDE */
+ MD_EXCEPTION_CODE_MAC_PPC_FLOAT_INEXACT = 3,
+ /* EXC_FLT_INEXACT */
+ MD_EXCEPTION_CODE_MAC_PPC_FLOAT_ZERO_DIVIDE = 4,
+ /* EXC_PPC_FLT_ZERO_DIVIDE */
+ MD_EXCEPTION_CODE_MAC_PPC_FLOAT_UNDERFLOW = 5,
+ /* EXC_PPC_FLT_UNDERFLOW */
+ MD_EXCEPTION_CODE_MAC_PPC_FLOAT_OVERFLOW = 6,
+ /* EXC_PPC_FLT_OVERFLOW */
+ MD_EXCEPTION_CODE_MAC_PPC_FLOAT_NOT_A_NUMBER = 7,
+ /* EXC_PPC_FLT_NOT_A_NUMBER */
+
+ /* With MD_EXCEPTION_MAC_EMULATION on ppc */
+ MD_EXCEPTION_CODE_MAC_PPC_NO_EMULATION = 8,
+ /* EXC_PPC_NOEMULATION */
+ MD_EXCEPTION_CODE_MAC_PPC_ALTIVEC_ASSIST = 9,
+ /* EXC_PPC_ALTIVECASSIST */
+
+ /* With MD_EXCEPTION_MAC_SOFTWARE on ppc */
+ MD_EXCEPTION_CODE_MAC_PPC_TRAP = 0x00000001, /* EXC_PPC_TRAP */
+ MD_EXCEPTION_CODE_MAC_PPC_MIGRATE = 0x00010100, /* EXC_PPC_MIGRATE */
+
+ /* With MD_EXCEPTION_MAC_BREAKPOINT on ppc */
+ MD_EXCEPTION_CODE_MAC_PPC_BREAKPOINT = 1, /* EXC_PPC_BREAKPOINT */
+
+ /* With MD_EXCEPTION_MAC_BAD_INSTRUCTION on x86, see also x86 interrupt
+ * values below. */
+ MD_EXCEPTION_CODE_MAC_X86_INVALID_OPERATION = 1, /* EXC_I386_INVOP */
+
+ /* With MD_EXCEPTION_MAC_ARITHMETIC on x86 */
+ MD_EXCEPTION_CODE_MAC_X86_DIV = 1, /* EXC_I386_DIV */
+ MD_EXCEPTION_CODE_MAC_X86_INTO = 2, /* EXC_I386_INTO */
+ MD_EXCEPTION_CODE_MAC_X86_NOEXT = 3, /* EXC_I386_NOEXT */
+ MD_EXCEPTION_CODE_MAC_X86_EXTOVR = 4, /* EXC_I386_EXTOVR */
+ MD_EXCEPTION_CODE_MAC_X86_EXTERR = 5, /* EXC_I386_EXTERR */
+ MD_EXCEPTION_CODE_MAC_X86_EMERR = 6, /* EXC_I386_EMERR */
+ MD_EXCEPTION_CODE_MAC_X86_BOUND = 7, /* EXC_I386_BOUND */
+ MD_EXCEPTION_CODE_MAC_X86_SSEEXTERR = 8, /* EXC_I386_SSEEXTERR */
+
+ /* With MD_EXCEPTION_MAC_BREAKPOINT on x86 */
+ MD_EXCEPTION_CODE_MAC_X86_SGL = 1, /* EXC_I386_SGL */
+ MD_EXCEPTION_CODE_MAC_X86_BPT = 2, /* EXC_I386_BPT */
+
+ /* With MD_EXCEPTION_MAC_BAD_INSTRUCTION on x86. These are the raw
+ * x86 interrupt codes. Most of these are mapped to other Mach
+ * exceptions and codes, are handled, or should not occur in user space.
+ * A few of these will do occur with MD_EXCEPTION_MAC_BAD_INSTRUCTION. */
+ /* EXC_I386_DIVERR = 0: mapped to EXC_ARITHMETIC/EXC_I386_DIV */
+ /* EXC_I386_SGLSTP = 1: mapped to EXC_BREAKPOINT/EXC_I386_SGL */
+ /* EXC_I386_NMIFLT = 2: should not occur in user space */
+ /* EXC_I386_BPTFLT = 3: mapped to EXC_BREAKPOINT/EXC_I386_BPT */
+ /* EXC_I386_INTOFLT = 4: mapped to EXC_ARITHMETIC/EXC_I386_INTO */
+ /* EXC_I386_BOUNDFLT = 5: mapped to EXC_ARITHMETIC/EXC_I386_BOUND */
+ /* EXC_I386_INVOPFLT = 6: mapped to EXC_BAD_INSTRUCTION/EXC_I386_INVOP */
+ /* EXC_I386_NOEXTFLT = 7: should be handled by the kernel */
+ /* EXC_I386_DBLFLT = 8: should be handled (if possible) by the kernel */
+ /* EXC_I386_EXTOVRFLT = 9: mapped to EXC_BAD_ACCESS/(PROT_READ|PROT_EXEC) */
+ MD_EXCEPTION_CODE_MAC_X86_INVALID_TASK_STATE_SEGMENT = 10,
+ /* EXC_INVTSSFLT */
+ MD_EXCEPTION_CODE_MAC_X86_SEGMENT_NOT_PRESENT = 11,
+ /* EXC_SEGNPFLT */
+ MD_EXCEPTION_CODE_MAC_X86_STACK_FAULT = 12,
+ /* EXC_STKFLT */
+ MD_EXCEPTION_CODE_MAC_X86_GENERAL_PROTECTION_FAULT = 13,
+ /* EXC_GPFLT */
+ /* EXC_I386_PGFLT = 14: should not occur in user space */
+ /* EXC_I386_EXTERRFLT = 16: mapped to EXC_ARITHMETIC/EXC_I386_EXTERR */
+ MD_EXCEPTION_CODE_MAC_X86_ALIGNMENT_FAULT = 17
+ /* EXC_ALIGNFLT (for vector operations) */
+ /* EXC_I386_ENOEXTFLT = 32: should be handled by the kernel */
+ /* EXC_I386_ENDPERR = 33: should not occur */
+} MDExceptionCodeMac;
+
+// The following definitions were taken from Darwin/XNU kernel sources.
+// See https://github.com/apple/darwin-xnu/blob/main/osfmk/kern/exc_resource.h
+
+typedef enum MDMacExcResourceType {
+ MD_MAC_EXC_RESOURCE_TYPE_CPU = 1,
+ MD_MAC_EXC_RESOURCE_TYPE_WAKEUPS = 2,
+ MD_MAC_EXC_RESOURCE_TYPE_MEMORY = 3,
+ MD_MAC_EXC_RESOURCE_TYPE_IO = 4,
+ MD_MAC_EXC_RESOURCE_TYPE_THREADS = 5
+} MDMacExcResourceType;
+
+typedef enum MDMacExcResourceFlavorCpu {
+ MD_MAC_EXC_RESOURCE_FLAVOR_CPU_MONITOR = 1,
+ MD_MAC_EXC_RESOURCE_FLAVOR_CPU_MONITOR_FATAL = 2
+} MDMacExcResourceFlavorCpu;
+
+typedef enum MDMacExcResourceFlavorWakeup {
+ MD_MAC_EXC_RESOURCE_FLAVOR_WAKEUPS_MONITOR = 1,
+} MDMacExcResourceFlavorWakeup;
+
+typedef enum MDMacExcResourceFlavorMemory {
+ MD_MAC_EXC_RESOURCE_FLAVOR_HIGH_WATERMARK = 1,
+} MDMacExcResourceFlavorMemory;
+
+typedef enum MDMacExcResourceIOFlavor {
+ MD_MAC_EXC_RESOURCE_FLAVOR_IO_PHYSICAL_WRITES = 1,
+ MD_MAC_EXC_RESOURCE_FLAVOR_IO_LOGICAL_WRITES = 2,
+} MDMacExcResourceIOFlavor;
+
+typedef enum MDMacExcResourceThreadsFlavor {
+ MD_MAC_EXC_RESOURCE_FLAVOR_THREADS_HIGH_WATERMARK = 1,
+} MDMacExcResourceThreadsFlavor;
+
+// See https://github.com/apple/darwin-xnu/blob/main/osfmk/kern/exc_guard.h
+
+typedef enum MDMacExcGuardType {
+ MD_MAC_EXC_GUARD_TYPE_NONE = 0x0,
+ MD_MAC_EXC_GUARD_TYPE_MACH_PORT = 0x1,
+ MD_MAC_EXC_GUARD_TYPE_FD = 0x2,
+ MD_MAC_EXC_GUARD_TYPE_USER = 0x3,
+ MD_MAC_EXC_GUARD_TYPE_VN = 0x4,
+ MD_MAC_EXC_GUARD_TYPE_VIRT_MEMORY = 0x5
+} MDMacExcGuardType;
+
+// See https://github.com/apple/darwin-xnu/osfmk/mach/port.h
+
+typedef enum MDMacExcGuardMachPortFlavor {
+ MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_DESTROY = 1u << 0,
+ MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_MOD_REFS = 1u << 1,
+ MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_SET_CONTEXT = 1u << 2,
+ MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_UNGUARDED = 1u << 3,
+ MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_INCORRECT_GUARD = 1u << 4,
+ MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_IMMOVABLE = 1u << 5,
+ MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_STRICT_REPLY = 1u << 6,
+ MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_MSG_FILTERED = 1u << 7,
+ MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_INVALID_RIGHT = 1u << 8,
+ MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_INVALID_NAME = 1u << 9,
+ MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_INVALID_VALUE = 1u << 10,
+ MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_INVALID_ARGUMENT = 1u << 11,
+ MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_RIGHT_EXISTS = 1u << 12,
+ MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_KERN_NO_SPACE = 1u << 13,
+ MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_KERN_FAILURE = 1u << 14,
+ MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_KERN_RESOURCE = 1u << 15,
+ MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_SEND_INVALID_REPLY = 1u << 16,
+ MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_SEND_INVALID_VOUCHER = 1u << 17,
+ MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_SEND_INVALID_RIGHT = 1u << 18,
+ MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_RCV_INVALID_NAME = 1u << 19,
+ MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_RCV_GUARDED_DESC = 1u << 20,
+ MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_MOD_REFS_NON_FATAL = 1u << 21,
+ MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_IMMOVABLE_NON_FATAL = 1u << 22,
+} MDMacExcGuardMachPortFlavor;
+
+// See https://github.com/apple/darwin-xnu/blob/main/bsd/sys/guarded.h
+
+typedef enum MDMacExcGuardFDFlavor {
+ MD_MAC_EXC_GUARD_FD_FLAVOR_GUARD_EXC_CLOSE = 1u << 0,
+ MD_MAC_EXC_GUARD_FD_FLAVOR_GUARD_EXC_DUP = 1u << 1,
+ MD_MAC_EXC_GUARD_FD_FLAVOR_GUARD_EXC_NOCLOEXEC = 1u << 2,
+ MD_MAC_EXC_GUARD_FD_FLAVOR_GUARD_EXC_SOCKET_IPC = 1u << 3,
+ MD_MAC_EXC_GUARD_FD_FLAVOR_GUARD_EXC_FILEPORT = 1u << 4,
+ MD_MAC_EXC_GUARD_FD_FLAVOR_GUARD_EXC_MISMATCH = 1u << 5,
+ MD_MAC_EXC_GUARD_FD_FLAVOR_GUARD_EXC_WRITE = 1u << 6
+} MDMacExcGuardFDFlavor;
+
+
+typedef enum MDMacExcGuardVNFlavor {
+ MD_MAC_EXC_GUARD_FD_FLAVOR_GUARD_EXC_RENAME_TO = 1u << 0,
+ MD_MAC_EXC_GUARD_FD_FLAVOR_GUARD_EXC_RENAME_FROM = 1u << 1,
+ MD_MAC_EXC_GUARD_FD_FLAVOR_GUARD_EXC_UNLINK = 1u << 2,
+ MD_MAC_EXC_GUARD_FD_FLAVOR_GUARD_EXC_WRITE_OTHER = 1u << 3,
+ MD_MAC_EXC_GUARD_FD_FLAVOR_GUARD_EXC_TRUNC_OTHER = 1u << 4,
+ MD_MAC_EXC_GUARD_FD_FLAVOR_GUARD_EXC_LINK = 1u << 5,
+ MD_MAC_EXC_GUARD_FD_FLAVOR_GUARD_EXC_EXCHDATA = 1u << 6,
+} MDMacExcGuardVNFlavor;
+
+// See https://github.com/apple/darwin-xnu/osfmk/mach/vm_statistics.h
+
+typedef enum MDMacExcGuardVirtMemoryFlavor {
+ MD_MAC_EXC_GUARD_VIRT_MEMORY_FLAVOR_GUARD_EXC_DEALLOC_GAP = 1u << 0
+} MDMacExcGuardVirtMemoryFlavor;
+
+#endif /* GOOGLE_BREAKPAD_COMMON_MINIDUMP_EXCEPTION_MAC_OSX_H__ */
diff --git a/toolkit/crashreporter/google-breakpad/src/google_breakpad/common/minidump_exception_ps3.h b/toolkit/crashreporter/google-breakpad/src/google_breakpad/common/minidump_exception_ps3.h
new file mode 100644
index 0000000000..adff5a6bbc
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/google_breakpad/common/minidump_exception_ps3.h
@@ -0,0 +1,67 @@
+/* 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. */
+
+/* minidump_exception_ps3.h: A definition of exception codes for
+ * PS3 */
+
+
+#ifndef GOOGLE_BREAKPAD_COMMON_MINIDUMP_EXCEPTION_PS3_H__
+#define GOOGLE_BREAKPAD_COMMON_MINIDUMP_EXCEPTION_PS3_H__
+
+#include <stddef.h>
+
+#include "google_breakpad/common/breakpad_types.h"
+
+typedef enum {
+ MD_EXCEPTION_CODE_PS3_UNKNOWN = 0,
+ MD_EXCEPTION_CODE_PS3_TRAP_EXCEP = 1,
+ MD_EXCEPTION_CODE_PS3_PRIV_INSTR = 2,
+ MD_EXCEPTION_CODE_PS3_ILLEGAL_INSTR = 3,
+ MD_EXCEPTION_CODE_PS3_INSTR_STORAGE = 4,
+ MD_EXCEPTION_CODE_PS3_INSTR_SEGMENT = 5,
+ MD_EXCEPTION_CODE_PS3_DATA_STORAGE = 6,
+ MD_EXCEPTION_CODE_PS3_DATA_SEGMENT = 7,
+ MD_EXCEPTION_CODE_PS3_FLOAT_POINT = 8,
+ MD_EXCEPTION_CODE_PS3_DABR_MATCH = 9,
+ MD_EXCEPTION_CODE_PS3_ALIGN_EXCEP = 10,
+ MD_EXCEPTION_CODE_PS3_MEMORY_ACCESS = 11,
+ MD_EXCEPTION_CODE_PS3_COPRO_ALIGN = 12,
+ MD_EXCEPTION_CODE_PS3_COPRO_INVALID_COM = 13,
+ MD_EXCEPTION_CODE_PS3_COPRO_ERR = 14,
+ MD_EXCEPTION_CODE_PS3_COPRO_FIR = 15,
+ MD_EXCEPTION_CODE_PS3_COPRO_DATA_SEGMENT = 16,
+ MD_EXCEPTION_CODE_PS3_COPRO_DATA_STORAGE = 17,
+ MD_EXCEPTION_CODE_PS3_COPRO_STOP_INSTR = 18,
+ MD_EXCEPTION_CODE_PS3_COPRO_HALT_INSTR = 19,
+ MD_EXCEPTION_CODE_PS3_COPRO_HALTINST_UNKNOWN = 20,
+ MD_EXCEPTION_CODE_PS3_COPRO_MEMORY_ACCESS = 21,
+ MD_EXCEPTION_CODE_PS3_GRAPHIC = 22
+} MDExceptionCodePS3;
+
+#endif /* GOOGLE_BREAKPAD_COMMON_MINIDUMP_EXCEPTION_PS3_H__ */
diff --git a/toolkit/crashreporter/google-breakpad/src/google_breakpad/common/minidump_exception_solaris.h b/toolkit/crashreporter/google-breakpad/src/google_breakpad/common/minidump_exception_solaris.h
new file mode 100644
index 0000000000..f18ddf4247
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/google_breakpad/common/minidump_exception_solaris.h
@@ -0,0 +1,94 @@
+/* Copyright (c) 2006, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
+
+/* minidump_exception_solaris.h: A definition of exception codes for
+ * Solaris
+ *
+ * (This is C99 source, please don't corrupt it with C++.)
+ *
+ * Author: Mark Mentovai
+ * Split into its own file: Neal Sidhwaney */
+
+
+#ifndef GOOGLE_BREAKPAD_COMMON_MINIDUMP_EXCEPTION_SOLARIS_H__
+#define GOOGLE_BREAKPAD_COMMON_MINIDUMP_EXCEPTION_SOLARIS_H__
+
+#include <stddef.h>
+
+#include "google_breakpad/common/breakpad_types.h"
+
+/* For (MDException).exception_code. These values come from sys/iso/signal_iso.h
+ */
+typedef enum {
+ MD_EXCEPTION_CODE_SOL_SIGHUP = 1, /* Hangup */
+ MD_EXCEPTION_CODE_SOL_SIGINT = 2, /* interrupt (rubout) */
+ MD_EXCEPTION_CODE_SOL_SIGQUIT = 3, /* quit (ASCII FS) */
+ MD_EXCEPTION_CODE_SOL_SIGILL = 4, /* illegal instruction (not reset when caught) */
+ MD_EXCEPTION_CODE_SOL_SIGTRAP = 5, /* trace trap (not reset when caught) */
+ MD_EXCEPTION_CODE_SOL_SIGIOT = 6, /* IOT instruction */
+ MD_EXCEPTION_CODE_SOL_SIGABRT = 6, /* used by abort, replace SIGIOT in the future */
+ MD_EXCEPTION_CODE_SOL_SIGEMT = 7, /* EMT instruction */
+ MD_EXCEPTION_CODE_SOL_SIGFPE = 8, /* floating point exception */
+ MD_EXCEPTION_CODE_SOL_SIGKILL = 9, /* kill (cannot be caught or ignored) */
+ MD_EXCEPTION_CODE_SOL_SIGBUS = 10, /* bus error */
+ MD_EXCEPTION_CODE_SOL_SIGSEGV = 11, /* segmentation violation */
+ MD_EXCEPTION_CODE_SOL_SIGSYS = 12, /* bad argument to system call */
+ MD_EXCEPTION_CODE_SOL_SIGPIPE = 13, /* write on a pipe with no one to read it */
+ MD_EXCEPTION_CODE_SOL_SIGALRM = 14, /* alarm clock */
+ MD_EXCEPTION_CODE_SOL_SIGTERM = 15, /* software termination signal from kill */
+ MD_EXCEPTION_CODE_SOL_SIGUSR1 = 16, /* user defined signal 1 */
+ MD_EXCEPTION_CODE_SOL_SIGUSR2 = 17, /* user defined signal 2 */
+ MD_EXCEPTION_CODE_SOL_SIGCLD = 18, /* child status change */
+ MD_EXCEPTION_CODE_SOL_SIGCHLD = 18, /* child status change alias (POSIX) */
+ MD_EXCEPTION_CODE_SOL_SIGPWR = 19, /* power-fail restart */
+ MD_EXCEPTION_CODE_SOL_SIGWINCH = 20, /* window size change */
+ MD_EXCEPTION_CODE_SOL_SIGURG = 21, /* urgent socket condition */
+ MD_EXCEPTION_CODE_SOL_SIGPOLL = 22, /* pollable event occurred */
+ MD_EXCEPTION_CODE_SOL_SIGIO = 22, /* socket I/O possible (SIGPOLL alias) */
+ MD_EXCEPTION_CODE_SOL_SIGSTOP = 23, /* stop (cannot be caught or ignored) */
+ MD_EXCEPTION_CODE_SOL_SIGTSTP = 24, /* user stop requested from tty */
+ MD_EXCEPTION_CODE_SOL_SIGCONT = 25, /* stopped process has been continued */
+ MD_EXCEPTION_CODE_SOL_SIGTTIN = 26, /* background tty read attempted */
+ MD_EXCEPTION_CODE_SOL_SIGTTOU = 27, /* background tty write attempted */
+ MD_EXCEPTION_CODE_SOL_SIGVTALRM = 28, /* virtual timer expired */
+ MD_EXCEPTION_CODE_SOL_SIGPROF = 29, /* profiling timer expired */
+ MD_EXCEPTION_CODE_SOL_SIGXCPU = 30, /* exceeded cpu limit */
+ MD_EXCEPTION_CODE_SOL_SIGXFSZ = 31, /* exceeded file size limit */
+ MD_EXCEPTION_CODE_SOL_SIGWAITING = 32, /* reserved signal no longer used by threading code */
+ MD_EXCEPTION_CODE_SOL_SIGLWP = 33, /* reserved signal no longer used by threading code */
+ MD_EXCEPTION_CODE_SOL_SIGFREEZE = 34, /* special signal used by CPR */
+ MD_EXCEPTION_CODE_SOL_SIGTHAW = 35, /* special signal used by CPR */
+ MD_EXCEPTION_CODE_SOL_SIGCANCEL = 36, /* reserved signal for thread cancellation */
+ MD_EXCEPTION_CODE_SOL_SIGLOST = 37, /* resource lost (eg, record-lock lost) */
+ MD_EXCEPTION_CODE_SOL_SIGXRES = 38, /* resource control exceeded */
+ MD_EXCEPTION_CODE_SOL_SIGJVM1 = 39, /* reserved signal for Java Virtual Machine */
+ MD_EXCEPTION_CODE_SOL_SIGJVM2 = 40 /* reserved signal for Java Virtual Machine */
+} MDExceptionCodeSolaris;
+
+#endif /* GOOGLE_BREAKPAD_COMMON_MINIDUMP_EXCEPTION_SOLARIS_H__ */
diff --git a/toolkit/crashreporter/google-breakpad/src/google_breakpad/common/minidump_exception_win32.h b/toolkit/crashreporter/google-breakpad/src/google_breakpad/common/minidump_exception_win32.h
new file mode 100644
index 0000000000..159f53f663
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/google_breakpad/common/minidump_exception_win32.h
@@ -0,0 +1,5575 @@
+/* Copyright (c) 2006, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
+
+/* minidump_exception_win32.h: Definitions of exception codes for
+ * Win32 platform
+ *
+ * (This is C99 source, please don't corrupt it with C++.)
+ *
+ * Author: Mark Mentovai
+ * Split into its own file: Neal Sidhwaney */
+
+
+#ifndef GOOGLE_BREAKPAD_COMMON_MINIDUMP_EXCEPTION_WIN32_H__
+#define GOOGLE_BREAKPAD_COMMON_MINIDUMP_EXCEPTION_WIN32_H__
+
+#include <stddef.h>
+
+#include "google_breakpad/common/breakpad_types.h"
+
+
+/* For (MDException).exception_code. These values come from WinBase.h */
+typedef enum {
+ MD_EXCEPTION_CODE_WIN_GUARD_PAGE_VIOLATION = 0x80000001,
+ /* EXCEPTION_GUARD_PAGE */
+ MD_EXCEPTION_CODE_WIN_DATATYPE_MISALIGNMENT = 0x80000002,
+ /* EXCEPTION_DATATYPE_MISALIGNMENT */
+ MD_EXCEPTION_CODE_WIN_BREAKPOINT = 0x80000003,
+ /* EXCEPTION_BREAKPOINT */
+ MD_EXCEPTION_CODE_WIN_SINGLE_STEP = 0x80000004,
+ /* EXCEPTION_SINGLE_STEP */
+ MD_EXCEPTION_CODE_WIN_ACCESS_VIOLATION = 0xc0000005,
+ /* EXCEPTION_ACCESS_VIOLATION */
+ MD_EXCEPTION_CODE_WIN_IN_PAGE_ERROR = 0xc0000006,
+ /* EXCEPTION_IN_PAGE_ERROR */
+ MD_EXCEPTION_CODE_WIN_INVALID_HANDLE = 0xc0000008,
+ /* EXCEPTION_INVALID_HANDLE */
+ MD_EXCEPTION_CODE_WIN_ILLEGAL_INSTRUCTION = 0xc000001d,
+ /* EXCEPTION_ILLEGAL_INSTRUCTION */
+ MD_EXCEPTION_CODE_WIN_NONCONTINUABLE_EXCEPTION = 0xc0000025,
+ /* EXCEPTION_NONCONTINUABLE_EXCEPTION */
+ MD_EXCEPTION_CODE_WIN_INVALID_DISPOSITION = 0xc0000026,
+ /* EXCEPTION_INVALID_DISPOSITION */
+ MD_EXCEPTION_CODE_WIN_ARRAY_BOUNDS_EXCEEDED = 0xc000008c,
+ /* EXCEPTION_BOUNDS_EXCEEDED */
+ MD_EXCEPTION_CODE_WIN_FLOAT_DENORMAL_OPERAND = 0xc000008d,
+ /* EXCEPTION_FLT_DENORMAL_OPERAND */
+ MD_EXCEPTION_CODE_WIN_FLOAT_DIVIDE_BY_ZERO = 0xc000008e,
+ /* EXCEPTION_FLT_DIVIDE_BY_ZERO */
+ MD_EXCEPTION_CODE_WIN_FLOAT_INEXACT_RESULT = 0xc000008f,
+ /* EXCEPTION_FLT_INEXACT_RESULT */
+ MD_EXCEPTION_CODE_WIN_FLOAT_INVALID_OPERATION = 0xc0000090,
+ /* EXCEPTION_FLT_INVALID_OPERATION */
+ MD_EXCEPTION_CODE_WIN_FLOAT_OVERFLOW = 0xc0000091,
+ /* EXCEPTION_FLT_OVERFLOW */
+ MD_EXCEPTION_CODE_WIN_FLOAT_STACK_CHECK = 0xc0000092,
+ /* EXCEPTION_FLT_STACK_CHECK */
+ MD_EXCEPTION_CODE_WIN_FLOAT_UNDERFLOW = 0xc0000093,
+ /* EXCEPTION_FLT_UNDERFLOW */
+ MD_EXCEPTION_CODE_WIN_INTEGER_DIVIDE_BY_ZERO = 0xc0000094,
+ /* EXCEPTION_INT_DIVIDE_BY_ZERO */
+ MD_EXCEPTION_CODE_WIN_INTEGER_OVERFLOW = 0xc0000095,
+ /* EXCEPTION_INT_OVERFLOW */
+ MD_EXCEPTION_CODE_WIN_PRIVILEGED_INSTRUCTION = 0xc0000096,
+ /* EXCEPTION_PRIV_INSTRUCTION */
+ MD_EXCEPTION_CODE_WIN_STACK_OVERFLOW = 0xc00000fd,
+ /* EXCEPTION_STACK_OVERFLOW */
+ MD_EXCEPTION_CODE_WIN_BAD_FUNCTION_TABLE = 0xc00000ff,
+ /* EXCEPTION_BAD_FUNCTION_TABLE */
+ MD_EXCEPTION_CODE_WIN_POSSIBLE_DEADLOCK = 0xc0000194,
+ /* EXCEPTION_POSSIBLE_DEADLOCK */
+ MD_EXCEPTION_OUT_OF_MEMORY = 0xe0000008,
+ /* Exception thrown by Chromium allocators to indicate OOM.
+ See base/process/memory.h in Chromium for rationale. */
+ MD_EXCEPTION_CODE_WIN_UNHANDLED_CPP_EXCEPTION = 0xe06d7363,
+ /* Per http://support.microsoft.com/kb/185294,
+ generated by Visual C++ compiler */
+ MD_EXCEPTION_CODE_WIN_SIMULATED = 0x0517a7ed
+ /* Fake exception code used by Crashpad's
+ CrashpadClient::DumpWithoutCrash. */
+} MDExceptionCodeWin;
+
+
+/* For (MDException).exception_information[2], when (MDException).exception_code
+ * is MD_EXCEPTION_CODE_WIN_IN_PAGE_ERROR. This describes the underlying reason
+ * for the error. These values come from ntstatus.h.
+ *
+ * The content of this enum was created from ntstatus.h in the 10 SDK
+ * (version 10.0.19041.0) with
+ *
+ * egrep '#define [A-Z_0-9]+\s+\(\(NTSTATUS\)0x[048C][0-9A-F]+L\)' ntstatus.h
+ * | tr -d '\r'
+ * | sed -r 's@#define ([A-Z_0-9]+)\s+\(\(NTSTATUS\)(0x[048C][0-9A-F]+)L\).*@\2 \1@'
+ * | sort
+ * | sed -r 's@(0x[048C][0-9A-F]+) ([A-Z_0-9]+)@ MD_NTSTATUS_WIN_\2 = \1,@'
+ *
+ * With easy copy to clipboard with
+ * | xclip -selection c # on linux
+ * | clip # on windows
+ * | pbcopy # on mac */
+typedef enum {
+ MD_NTSTATUS_WIN_STATUS_SUCCESS = 0x00000000,
+ MD_NTSTATUS_WIN_STATUS_WAIT_0 = 0x00000000,
+ MD_NTSTATUS_WIN_STATUS_WAIT_1 = 0x00000001,
+ MD_NTSTATUS_WIN_STATUS_WAIT_2 = 0x00000002,
+ MD_NTSTATUS_WIN_STATUS_WAIT_3 = 0x00000003,
+ MD_NTSTATUS_WIN_STATUS_WAIT_63 = 0x0000003F,
+ MD_NTSTATUS_WIN_STATUS_ABANDONED = 0x00000080,
+ MD_NTSTATUS_WIN_STATUS_ABANDONED_WAIT_0 = 0x00000080,
+ MD_NTSTATUS_WIN_STATUS_ABANDONED_WAIT_63 = 0x000000BF,
+ MD_NTSTATUS_WIN_STATUS_USER_APC = 0x000000C0,
+ MD_NTSTATUS_WIN_STATUS_ALREADY_COMPLETE = 0x000000FF,
+ MD_NTSTATUS_WIN_STATUS_KERNEL_APC = 0x00000100,
+ MD_NTSTATUS_WIN_STATUS_ALERTED = 0x00000101,
+ MD_NTSTATUS_WIN_STATUS_TIMEOUT = 0x00000102,
+ MD_NTSTATUS_WIN_STATUS_PENDING = 0x00000103,
+ MD_NTSTATUS_WIN_STATUS_REPARSE = 0x00000104,
+ MD_NTSTATUS_WIN_STATUS_MORE_ENTRIES = 0x00000105,
+ MD_NTSTATUS_WIN_STATUS_NOT_ALL_ASSIGNED = 0x00000106,
+ MD_NTSTATUS_WIN_STATUS_SOME_NOT_MAPPED = 0x00000107,
+ MD_NTSTATUS_WIN_STATUS_OPLOCK_BREAK_IN_PROGRESS = 0x00000108,
+ MD_NTSTATUS_WIN_STATUS_VOLUME_MOUNTED = 0x00000109,
+ MD_NTSTATUS_WIN_STATUS_RXACT_COMMITTED = 0x0000010A,
+ MD_NTSTATUS_WIN_STATUS_NOTIFY_CLEANUP = 0x0000010B,
+ MD_NTSTATUS_WIN_STATUS_NOTIFY_ENUM_DIR = 0x0000010C,
+ MD_NTSTATUS_WIN_STATUS_NO_QUOTAS_FOR_ACCOUNT = 0x0000010D,
+ MD_NTSTATUS_WIN_STATUS_PRIMARY_TRANSPORT_CONNECT_FAILED = 0x0000010E,
+ MD_NTSTATUS_WIN_STATUS_PAGE_FAULT_TRANSITION = 0x00000110,
+ MD_NTSTATUS_WIN_STATUS_PAGE_FAULT_DEMAND_ZERO = 0x00000111,
+ MD_NTSTATUS_WIN_STATUS_PAGE_FAULT_COPY_ON_WRITE = 0x00000112,
+ MD_NTSTATUS_WIN_STATUS_PAGE_FAULT_GUARD_PAGE = 0x00000113,
+ MD_NTSTATUS_WIN_STATUS_PAGE_FAULT_PAGING_FILE = 0x00000114,
+ MD_NTSTATUS_WIN_STATUS_CACHE_PAGE_LOCKED = 0x00000115,
+ MD_NTSTATUS_WIN_STATUS_CRASH_DUMP = 0x00000116,
+ MD_NTSTATUS_WIN_STATUS_BUFFER_ALL_ZEROS = 0x00000117,
+ MD_NTSTATUS_WIN_STATUS_REPARSE_OBJECT = 0x00000118,
+ MD_NTSTATUS_WIN_STATUS_RESOURCE_REQUIREMENTS_CHANGED = 0x00000119,
+ MD_NTSTATUS_WIN_STATUS_TRANSLATION_COMPLETE = 0x00000120,
+ MD_NTSTATUS_WIN_STATUS_DS_MEMBERSHIP_EVALUATED_LOCALLY = 0x00000121,
+ MD_NTSTATUS_WIN_STATUS_NOTHING_TO_TERMINATE = 0x00000122,
+ MD_NTSTATUS_WIN_STATUS_PROCESS_NOT_IN_JOB = 0x00000123,
+ MD_NTSTATUS_WIN_STATUS_PROCESS_IN_JOB = 0x00000124,
+ MD_NTSTATUS_WIN_STATUS_VOLSNAP_HIBERNATE_READY = 0x00000125,
+ MD_NTSTATUS_WIN_STATUS_FSFILTER_OP_COMPLETED_SUCCESSFULLY = 0x00000126,
+ MD_NTSTATUS_WIN_STATUS_INTERRUPT_VECTOR_ALREADY_CONNECTED = 0x00000127,
+ MD_NTSTATUS_WIN_STATUS_INTERRUPT_STILL_CONNECTED = 0x00000128,
+ MD_NTSTATUS_WIN_STATUS_PROCESS_CLONED = 0x00000129,
+ MD_NTSTATUS_WIN_STATUS_FILE_LOCKED_WITH_ONLY_READERS = 0x0000012A,
+ MD_NTSTATUS_WIN_STATUS_FILE_LOCKED_WITH_WRITERS = 0x0000012B,
+ MD_NTSTATUS_WIN_STATUS_VALID_IMAGE_HASH = 0x0000012C,
+ MD_NTSTATUS_WIN_STATUS_VALID_CATALOG_HASH = 0x0000012D,
+ MD_NTSTATUS_WIN_STATUS_VALID_STRONG_CODE_HASH = 0x0000012E,
+ MD_NTSTATUS_WIN_STATUS_GHOSTED = 0x0000012F,
+ MD_NTSTATUS_WIN_STATUS_DATA_OVERWRITTEN = 0x00000130,
+ MD_NTSTATUS_WIN_STATUS_RESOURCEMANAGER_READ_ONLY = 0x00000202,
+ MD_NTSTATUS_WIN_STATUS_RING_PREVIOUSLY_EMPTY = 0x00000210,
+ MD_NTSTATUS_WIN_STATUS_RING_PREVIOUSLY_FULL = 0x00000211,
+ MD_NTSTATUS_WIN_STATUS_RING_PREVIOUSLY_ABOVE_QUOTA = 0x00000212,
+ MD_NTSTATUS_WIN_STATUS_RING_NEWLY_EMPTY = 0x00000213,
+ MD_NTSTATUS_WIN_STATUS_RING_SIGNAL_OPPOSITE_ENDPOINT = 0x00000214,
+ MD_NTSTATUS_WIN_STATUS_OPLOCK_SWITCHED_TO_NEW_HANDLE = 0x00000215,
+ MD_NTSTATUS_WIN_STATUS_OPLOCK_HANDLE_CLOSED = 0x00000216,
+ MD_NTSTATUS_WIN_STATUS_WAIT_FOR_OPLOCK = 0x00000367,
+ MD_NTSTATUS_WIN_STATUS_REPARSE_GLOBAL = 0x00000368,
+ MD_NTSTATUS_WIN_DBG_EXCEPTION_HANDLED = 0x00010001,
+ MD_NTSTATUS_WIN_DBG_CONTINUE = 0x00010002,
+ MD_NTSTATUS_WIN_STATUS_FLT_IO_COMPLETE = 0x001C0001,
+ MD_NTSTATUS_WIN_STATUS_RTPM_CONTEXT_CONTINUE = 0x00293000,
+ MD_NTSTATUS_WIN_STATUS_RTPM_CONTEXT_COMPLETE = 0x00293001,
+ MD_NTSTATUS_WIN_STATUS_HV_PENDING_PAGE_REQUESTS = 0x00350059,
+ MD_NTSTATUS_WIN_STATUS_SPACES_REPAIRED = 0x00E70000,
+ MD_NTSTATUS_WIN_STATUS_SPACES_PAUSE = 0x00E70001,
+ MD_NTSTATUS_WIN_STATUS_SPACES_COMPLETE = 0x00E70002,
+ MD_NTSTATUS_WIN_STATUS_SPACES_REDIRECT = 0x00E70003,
+ MD_NTSTATUS_WIN_STATUS_OBJECT_NAME_EXISTS = 0x40000000,
+ MD_NTSTATUS_WIN_STATUS_THREAD_WAS_SUSPENDED = 0x40000001,
+ MD_NTSTATUS_WIN_STATUS_WORKING_SET_LIMIT_RANGE = 0x40000002,
+ MD_NTSTATUS_WIN_STATUS_IMAGE_NOT_AT_BASE = 0x40000003,
+ MD_NTSTATUS_WIN_STATUS_RXACT_STATE_CREATED = 0x40000004,
+ MD_NTSTATUS_WIN_STATUS_SEGMENT_NOTIFICATION = 0x40000005,
+ MD_NTSTATUS_WIN_STATUS_LOCAL_USER_SESSION_KEY = 0x40000006,
+ MD_NTSTATUS_WIN_STATUS_BAD_CURRENT_DIRECTORY = 0x40000007,
+ MD_NTSTATUS_WIN_STATUS_SERIAL_MORE_WRITES = 0x40000008,
+ MD_NTSTATUS_WIN_STATUS_REGISTRY_RECOVERED = 0x40000009,
+ MD_NTSTATUS_WIN_STATUS_FT_READ_RECOVERY_FROM_BACKUP = 0x4000000A,
+ MD_NTSTATUS_WIN_STATUS_FT_WRITE_RECOVERY = 0x4000000B,
+ MD_NTSTATUS_WIN_STATUS_SERIAL_COUNTER_TIMEOUT = 0x4000000C,
+ MD_NTSTATUS_WIN_STATUS_NULL_LM_PASSWORD = 0x4000000D,
+ MD_NTSTATUS_WIN_STATUS_IMAGE_MACHINE_TYPE_MISMATCH = 0x4000000E,
+ MD_NTSTATUS_WIN_STATUS_RECEIVE_PARTIAL = 0x4000000F,
+ MD_NTSTATUS_WIN_STATUS_RECEIVE_EXPEDITED = 0x40000010,
+ MD_NTSTATUS_WIN_STATUS_RECEIVE_PARTIAL_EXPEDITED = 0x40000011,
+ MD_NTSTATUS_WIN_STATUS_EVENT_DONE = 0x40000012,
+ MD_NTSTATUS_WIN_STATUS_EVENT_PENDING = 0x40000013,
+ MD_NTSTATUS_WIN_STATUS_CHECKING_FILE_SYSTEM = 0x40000014,
+ MD_NTSTATUS_WIN_STATUS_FATAL_APP_EXIT = 0x40000015,
+ MD_NTSTATUS_WIN_STATUS_PREDEFINED_HANDLE = 0x40000016,
+ MD_NTSTATUS_WIN_STATUS_WAS_UNLOCKED = 0x40000017,
+ MD_NTSTATUS_WIN_STATUS_SERVICE_NOTIFICATION = 0x40000018,
+ MD_NTSTATUS_WIN_STATUS_WAS_LOCKED = 0x40000019,
+ MD_NTSTATUS_WIN_STATUS_LOG_HARD_ERROR = 0x4000001A,
+ MD_NTSTATUS_WIN_STATUS_ALREADY_WIN32 = 0x4000001B,
+ MD_NTSTATUS_WIN_STATUS_WX86_UNSIMULATE = 0x4000001C,
+ MD_NTSTATUS_WIN_STATUS_WX86_CONTINUE = 0x4000001D,
+ MD_NTSTATUS_WIN_STATUS_WX86_SINGLE_STEP = 0x4000001E,
+ MD_NTSTATUS_WIN_STATUS_WX86_BREAKPOINT = 0x4000001F,
+ MD_NTSTATUS_WIN_STATUS_WX86_EXCEPTION_CONTINUE = 0x40000020,
+ MD_NTSTATUS_WIN_STATUS_WX86_EXCEPTION_LASTCHANCE = 0x40000021,
+ MD_NTSTATUS_WIN_STATUS_WX86_EXCEPTION_CHAIN = 0x40000022,
+ MD_NTSTATUS_WIN_STATUS_IMAGE_MACHINE_TYPE_MISMATCH_EXE = 0x40000023,
+ MD_NTSTATUS_WIN_STATUS_NO_YIELD_PERFORMED = 0x40000024,
+ MD_NTSTATUS_WIN_STATUS_TIMER_RESUME_IGNORED = 0x40000025,
+ MD_NTSTATUS_WIN_STATUS_ARBITRATION_UNHANDLED = 0x40000026,
+ MD_NTSTATUS_WIN_STATUS_CARDBUS_NOT_SUPPORTED = 0x40000027,
+ MD_NTSTATUS_WIN_STATUS_WX86_CREATEWX86TIB = 0x40000028,
+ MD_NTSTATUS_WIN_STATUS_MP_PROCESSOR_MISMATCH = 0x40000029,
+ MD_NTSTATUS_WIN_STATUS_HIBERNATED = 0x4000002A,
+ MD_NTSTATUS_WIN_STATUS_RESUME_HIBERNATION = 0x4000002B,
+ MD_NTSTATUS_WIN_STATUS_FIRMWARE_UPDATED = 0x4000002C,
+ MD_NTSTATUS_WIN_STATUS_DRIVERS_LEAKING_LOCKED_PAGES = 0x4000002D,
+ MD_NTSTATUS_WIN_STATUS_MESSAGE_RETRIEVED = 0x4000002E,
+ MD_NTSTATUS_WIN_STATUS_SYSTEM_POWERSTATE_TRANSITION = 0x4000002F,
+ MD_NTSTATUS_WIN_STATUS_ALPC_CHECK_COMPLETION_LIST = 0x40000030,
+ MD_NTSTATUS_WIN_STATUS_SYSTEM_POWERSTATE_COMPLEX_TRANSITION = 0x40000031,
+ MD_NTSTATUS_WIN_STATUS_ACCESS_AUDIT_BY_POLICY = 0x40000032,
+ MD_NTSTATUS_WIN_STATUS_ABANDON_HIBERFILE = 0x40000033,
+ MD_NTSTATUS_WIN_STATUS_BIZRULES_NOT_ENABLED = 0x40000034,
+ MD_NTSTATUS_WIN_STATUS_FT_READ_FROM_COPY = 0x40000035,
+ MD_NTSTATUS_WIN_STATUS_IMAGE_AT_DIFFERENT_BASE = 0x40000036,
+ MD_NTSTATUS_WIN_STATUS_PATCH_DEFERRED = 0x40000037,
+ MD_NTSTATUS_WIN_STATUS_WAKE_SYSTEM = 0x40000294,
+ MD_NTSTATUS_WIN_STATUS_DS_SHUTTING_DOWN = 0x40000370,
+ MD_NTSTATUS_WIN_STATUS_DISK_REPAIR_REDIRECTED = 0x40000807,
+ MD_NTSTATUS_WIN_STATUS_SERVICES_FAILED_AUTOSTART = 0x4000A144,
+ MD_NTSTATUS_WIN_DBG_REPLY_LATER = 0x40010001,
+ MD_NTSTATUS_WIN_DBG_UNABLE_TO_PROVIDE_HANDLE = 0x40010002,
+ MD_NTSTATUS_WIN_DBG_TERMINATE_THREAD = 0x40010003,
+ MD_NTSTATUS_WIN_DBG_TERMINATE_PROCESS = 0x40010004,
+ MD_NTSTATUS_WIN_DBG_CONTROL_C = 0x40010005,
+ MD_NTSTATUS_WIN_DBG_PRINTEXCEPTION_C = 0x40010006,
+ MD_NTSTATUS_WIN_DBG_RIPEXCEPTION = 0x40010007,
+ MD_NTSTATUS_WIN_DBG_CONTROL_BREAK = 0x40010008,
+ MD_NTSTATUS_WIN_DBG_COMMAND_EXCEPTION = 0x40010009,
+ MD_NTSTATUS_WIN_DBG_PRINTEXCEPTION_WIDE_C = 0x4001000A,
+ MD_NTSTATUS_WIN_RPC_NT_UUID_LOCAL_ONLY = 0x40020056,
+ MD_NTSTATUS_WIN_RPC_NT_SEND_INCOMPLETE = 0x400200AF,
+ MD_NTSTATUS_WIN_STATUS_CTX_CDM_CONNECT = 0x400A0004,
+ MD_NTSTATUS_WIN_STATUS_CTX_CDM_DISCONNECT = 0x400A0005,
+ MD_NTSTATUS_WIN_STATUS_SXS_RELEASE_ACTIVATION_CONTEXT = 0x4015000D,
+ MD_NTSTATUS_WIN_STATUS_HEURISTIC_DAMAGE_POSSIBLE = 0x40190001,
+ MD_NTSTATUS_WIN_STATUS_RECOVERY_NOT_NEEDED = 0x40190034,
+ MD_NTSTATUS_WIN_STATUS_RM_ALREADY_STARTED = 0x40190035,
+ MD_NTSTATUS_WIN_STATUS_LOG_NO_RESTART = 0x401A000C,
+ MD_NTSTATUS_WIN_STATUS_VIDEO_DRIVER_DEBUG_REPORT_REQUEST = 0x401B00EC,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_PARTIAL_DATA_POPULATED = 0x401E000A,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_SKIP_ALLOCATION_PREPARATION = 0x401E0201,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_MODE_NOT_PINNED = 0x401E0307,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_NO_PREFERRED_MODE = 0x401E031E,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_DATASET_IS_EMPTY = 0x401E034B,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_NO_MORE_ELEMENTS_IN_DATASET = 0x401E034C,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_PATH_CONTENT_GEOMETRY_TRANSFORMATION_NOT_PINNED = 0x401E0351,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_UNKNOWN_CHILD_STATUS = 0x401E042F,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_LEADLINK_START_DEFERRED = 0x401E0437,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_POLLING_TOO_FREQUENTLY = 0x401E0439,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_START_DEFERRED = 0x401E043A,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_DEPENDABLE_CHILD_STATUS = 0x401E043C,
+ MD_NTSTATUS_WIN_STATUS_NDIS_INDICATION_REQUIRED = 0x40230001,
+ MD_NTSTATUS_WIN_STATUS_PCP_UNSUPPORTED_PSS_SALT = 0x40292023,
+ MD_NTSTATUS_WIN_STATUS_GUARD_PAGE_VIOLATION = 0x80000001,
+ MD_NTSTATUS_WIN_STATUS_DATATYPE_MISALIGNMENT = 0x80000002,
+ MD_NTSTATUS_WIN_STATUS_BREAKPOINT = 0x80000003,
+ MD_NTSTATUS_WIN_STATUS_SINGLE_STEP = 0x80000004,
+ MD_NTSTATUS_WIN_STATUS_BUFFER_OVERFLOW = 0x80000005,
+ MD_NTSTATUS_WIN_STATUS_NO_MORE_FILES = 0x80000006,
+ MD_NTSTATUS_WIN_STATUS_WAKE_SYSTEM_DEBUGGER = 0x80000007,
+ MD_NTSTATUS_WIN_STATUS_HANDLES_CLOSED = 0x8000000A,
+ MD_NTSTATUS_WIN_STATUS_NO_INHERITANCE = 0x8000000B,
+ MD_NTSTATUS_WIN_STATUS_GUID_SUBSTITUTION_MADE = 0x8000000C,
+ MD_NTSTATUS_WIN_STATUS_PARTIAL_COPY = 0x8000000D,
+ MD_NTSTATUS_WIN_STATUS_DEVICE_PAPER_EMPTY = 0x8000000E,
+ MD_NTSTATUS_WIN_STATUS_DEVICE_POWERED_OFF = 0x8000000F,
+ MD_NTSTATUS_WIN_STATUS_DEVICE_OFF_LINE = 0x80000010,
+ MD_NTSTATUS_WIN_STATUS_DEVICE_BUSY = 0x80000011,
+ MD_NTSTATUS_WIN_STATUS_NO_MORE_EAS = 0x80000012,
+ MD_NTSTATUS_WIN_STATUS_INVALID_EA_NAME = 0x80000013,
+ MD_NTSTATUS_WIN_STATUS_EA_LIST_INCONSISTENT = 0x80000014,
+ MD_NTSTATUS_WIN_STATUS_INVALID_EA_FLAG = 0x80000015,
+ MD_NTSTATUS_WIN_STATUS_VERIFY_REQUIRED = 0x80000016,
+ MD_NTSTATUS_WIN_STATUS_EXTRANEOUS_INFORMATION = 0x80000017,
+ MD_NTSTATUS_WIN_STATUS_RXACT_COMMIT_NECESSARY = 0x80000018,
+ MD_NTSTATUS_WIN_STATUS_NO_MORE_ENTRIES = 0x8000001A,
+ MD_NTSTATUS_WIN_STATUS_FILEMARK_DETECTED = 0x8000001B,
+ MD_NTSTATUS_WIN_STATUS_MEDIA_CHANGED = 0x8000001C,
+ MD_NTSTATUS_WIN_STATUS_BUS_RESET = 0x8000001D,
+ MD_NTSTATUS_WIN_STATUS_END_OF_MEDIA = 0x8000001E,
+ MD_NTSTATUS_WIN_STATUS_BEGINNING_OF_MEDIA = 0x8000001F,
+ MD_NTSTATUS_WIN_STATUS_MEDIA_CHECK = 0x80000020,
+ MD_NTSTATUS_WIN_STATUS_SETMARK_DETECTED = 0x80000021,
+ MD_NTSTATUS_WIN_STATUS_NO_DATA_DETECTED = 0x80000022,
+ MD_NTSTATUS_WIN_STATUS_REDIRECTOR_HAS_OPEN_HANDLES = 0x80000023,
+ MD_NTSTATUS_WIN_STATUS_SERVER_HAS_OPEN_HANDLES = 0x80000024,
+ MD_NTSTATUS_WIN_STATUS_ALREADY_DISCONNECTED = 0x80000025,
+ MD_NTSTATUS_WIN_STATUS_LONGJUMP = 0x80000026,
+ MD_NTSTATUS_WIN_STATUS_CLEANER_CARTRIDGE_INSTALLED = 0x80000027,
+ MD_NTSTATUS_WIN_STATUS_PLUGPLAY_QUERY_VETOED = 0x80000028,
+ MD_NTSTATUS_WIN_STATUS_UNWIND_CONSOLIDATE = 0x80000029,
+ MD_NTSTATUS_WIN_STATUS_REGISTRY_HIVE_RECOVERED = 0x8000002A,
+ MD_NTSTATUS_WIN_STATUS_DLL_MIGHT_BE_INSECURE = 0x8000002B,
+ MD_NTSTATUS_WIN_STATUS_DLL_MIGHT_BE_INCOMPATIBLE = 0x8000002C,
+ MD_NTSTATUS_WIN_STATUS_STOPPED_ON_SYMLINK = 0x8000002D,
+ MD_NTSTATUS_WIN_STATUS_CANNOT_GRANT_REQUESTED_OPLOCK = 0x8000002E,
+ MD_NTSTATUS_WIN_STATUS_NO_ACE_CONDITION = 0x8000002F,
+ MD_NTSTATUS_WIN_STATUS_DEVICE_SUPPORT_IN_PROGRESS = 0x80000030,
+ MD_NTSTATUS_WIN_STATUS_DEVICE_POWER_CYCLE_REQUIRED = 0x80000031,
+ MD_NTSTATUS_WIN_STATUS_NO_WORK_DONE = 0x80000032,
+ MD_NTSTATUS_WIN_STATUS_RETURN_ADDRESS_HIJACK_ATTEMPT = 0x80000033,
+ MD_NTSTATUS_WIN_STATUS_DEVICE_REQUIRES_CLEANING = 0x80000288,
+ MD_NTSTATUS_WIN_STATUS_DEVICE_DOOR_OPEN = 0x80000289,
+ MD_NTSTATUS_WIN_STATUS_DATA_LOST_REPAIR = 0x80000803,
+ MD_NTSTATUS_WIN_STATUS_GPIO_INTERRUPT_ALREADY_UNMASKED = 0x8000A127,
+ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_PROPERTY_BLOB_CHECKSUM_MISMATCH = 0x8000CF00,
+ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_PROPERTY_BLOB_TOO_LARGE = 0x8000CF04,
+ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_TOO_MANY_PROPERTY_BLOBS = 0x8000CF05,
+ MD_NTSTATUS_WIN_DBG_EXCEPTION_NOT_HANDLED = 0x80010001,
+ MD_NTSTATUS_WIN_STATUS_CLUSTER_NODE_ALREADY_UP = 0x80130001,
+ MD_NTSTATUS_WIN_STATUS_CLUSTER_NODE_ALREADY_DOWN = 0x80130002,
+ MD_NTSTATUS_WIN_STATUS_CLUSTER_NETWORK_ALREADY_ONLINE = 0x80130003,
+ MD_NTSTATUS_WIN_STATUS_CLUSTER_NETWORK_ALREADY_OFFLINE = 0x80130004,
+ MD_NTSTATUS_WIN_STATUS_CLUSTER_NODE_ALREADY_MEMBER = 0x80130005,
+ MD_NTSTATUS_WIN_STATUS_COULD_NOT_RESIZE_LOG = 0x80190009,
+ MD_NTSTATUS_WIN_STATUS_NO_TXF_METADATA = 0x80190029,
+ MD_NTSTATUS_WIN_STATUS_CANT_RECOVER_WITH_HANDLE_OPEN = 0x80190031,
+ MD_NTSTATUS_WIN_STATUS_TXF_METADATA_ALREADY_PRESENT = 0x80190041,
+ MD_NTSTATUS_WIN_STATUS_TRANSACTION_SCOPE_CALLBACKS_NOT_SET = 0x80190042,
+ MD_NTSTATUS_WIN_STATUS_VIDEO_HUNG_DISPLAY_DRIVER_THREAD_RECOVERED = 0x801B00EB,
+ MD_NTSTATUS_WIN_STATUS_FLT_BUFFER_TOO_SMALL = 0x801C0001,
+ MD_NTSTATUS_WIN_STATUS_FVE_PARTIAL_METADATA = 0x80210001,
+ MD_NTSTATUS_WIN_STATUS_FVE_TRANSIENT_STATE = 0x80210002,
+ MD_NTSTATUS_WIN_STATUS_VID_REMOTE_NODE_PARENT_GPA_PAGES_USED = 0x80370001,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_INCOMPLETE_REGENERATION = 0x80380001,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_INCOMPLETE_DISK_MIGRATION = 0x80380002,
+ MD_NTSTATUS_WIN_STATUS_BCD_NOT_ALL_ENTRIES_IMPORTED = 0x80390001,
+ MD_NTSTATUS_WIN_STATUS_BCD_NOT_ALL_ENTRIES_SYNCHRONIZED = 0x80390003,
+ MD_NTSTATUS_WIN_STATUS_QUERY_STORAGE_ERROR = 0x803A0001,
+ MD_NTSTATUS_WIN_STATUS_GDI_HANDLE_LEAK = 0x803F0001,
+ MD_NTSTATUS_WIN_STATUS_SECUREBOOT_NOT_ENABLED = 0x80430006,
+ MD_NTSTATUS_WIN_STATUS_UNSUCCESSFUL = 0xC0000001,
+ MD_NTSTATUS_WIN_STATUS_NOT_IMPLEMENTED = 0xC0000002,
+ MD_NTSTATUS_WIN_STATUS_INVALID_INFO_CLASS = 0xC0000003,
+ MD_NTSTATUS_WIN_STATUS_INFO_LENGTH_MISMATCH = 0xC0000004,
+ MD_NTSTATUS_WIN_STATUS_ACCESS_VIOLATION = 0xC0000005,
+ MD_NTSTATUS_WIN_STATUS_IN_PAGE_ERROR = 0xC0000006,
+ MD_NTSTATUS_WIN_STATUS_PAGEFILE_QUOTA = 0xC0000007,
+ MD_NTSTATUS_WIN_STATUS_INVALID_HANDLE = 0xC0000008,
+ MD_NTSTATUS_WIN_STATUS_BAD_INITIAL_STACK = 0xC0000009,
+ MD_NTSTATUS_WIN_STATUS_BAD_INITIAL_PC = 0xC000000A,
+ MD_NTSTATUS_WIN_STATUS_INVALID_CID = 0xC000000B,
+ MD_NTSTATUS_WIN_STATUS_TIMER_NOT_CANCELED = 0xC000000C,
+ MD_NTSTATUS_WIN_STATUS_INVALID_PARAMETER = 0xC000000D,
+ MD_NTSTATUS_WIN_STATUS_NO_SUCH_DEVICE = 0xC000000E,
+ MD_NTSTATUS_WIN_STATUS_NO_SUCH_FILE = 0xC000000F,
+ MD_NTSTATUS_WIN_STATUS_INVALID_DEVICE_REQUEST = 0xC0000010,
+ MD_NTSTATUS_WIN_STATUS_END_OF_FILE = 0xC0000011,
+ MD_NTSTATUS_WIN_STATUS_WRONG_VOLUME = 0xC0000012,
+ MD_NTSTATUS_WIN_STATUS_NO_MEDIA_IN_DEVICE = 0xC0000013,
+ MD_NTSTATUS_WIN_STATUS_UNRECOGNIZED_MEDIA = 0xC0000014,
+ MD_NTSTATUS_WIN_STATUS_NONEXISTENT_SECTOR = 0xC0000015,
+ MD_NTSTATUS_WIN_STATUS_MORE_PROCESSING_REQUIRED = 0xC0000016,
+ MD_NTSTATUS_WIN_STATUS_NO_MEMORY = 0xC0000017,
+ MD_NTSTATUS_WIN_STATUS_CONFLICTING_ADDRESSES = 0xC0000018,
+ MD_NTSTATUS_WIN_STATUS_NOT_MAPPED_VIEW = 0xC0000019,
+ MD_NTSTATUS_WIN_STATUS_UNABLE_TO_FREE_VM = 0xC000001A,
+ MD_NTSTATUS_WIN_STATUS_UNABLE_TO_DELETE_SECTION = 0xC000001B,
+ MD_NTSTATUS_WIN_STATUS_INVALID_SYSTEM_SERVICE = 0xC000001C,
+ MD_NTSTATUS_WIN_STATUS_ILLEGAL_INSTRUCTION = 0xC000001D,
+ MD_NTSTATUS_WIN_STATUS_INVALID_LOCK_SEQUENCE = 0xC000001E,
+ MD_NTSTATUS_WIN_STATUS_INVALID_VIEW_SIZE = 0xC000001F,
+ MD_NTSTATUS_WIN_STATUS_INVALID_FILE_FOR_SECTION = 0xC0000020,
+ MD_NTSTATUS_WIN_STATUS_ALREADY_COMMITTED = 0xC0000021,
+ MD_NTSTATUS_WIN_STATUS_ACCESS_DENIED = 0xC0000022,
+ MD_NTSTATUS_WIN_STATUS_BUFFER_TOO_SMALL = 0xC0000023,
+ MD_NTSTATUS_WIN_STATUS_OBJECT_TYPE_MISMATCH = 0xC0000024,
+ MD_NTSTATUS_WIN_STATUS_NONCONTINUABLE_EXCEPTION = 0xC0000025,
+ MD_NTSTATUS_WIN_STATUS_INVALID_DISPOSITION = 0xC0000026,
+ MD_NTSTATUS_WIN_STATUS_UNWIND = 0xC0000027,
+ MD_NTSTATUS_WIN_STATUS_BAD_STACK = 0xC0000028,
+ MD_NTSTATUS_WIN_STATUS_INVALID_UNWIND_TARGET = 0xC0000029,
+ MD_NTSTATUS_WIN_STATUS_NOT_LOCKED = 0xC000002A,
+ MD_NTSTATUS_WIN_STATUS_PARITY_ERROR = 0xC000002B,
+ MD_NTSTATUS_WIN_STATUS_UNABLE_TO_DECOMMIT_VM = 0xC000002C,
+ MD_NTSTATUS_WIN_STATUS_NOT_COMMITTED = 0xC000002D,
+ MD_NTSTATUS_WIN_STATUS_INVALID_PORT_ATTRIBUTES = 0xC000002E,
+ MD_NTSTATUS_WIN_STATUS_PORT_MESSAGE_TOO_LONG = 0xC000002F,
+ MD_NTSTATUS_WIN_STATUS_INVALID_PARAMETER_MIX = 0xC0000030,
+ MD_NTSTATUS_WIN_STATUS_INVALID_QUOTA_LOWER = 0xC0000031,
+ MD_NTSTATUS_WIN_STATUS_DISK_CORRUPT_ERROR = 0xC0000032,
+ MD_NTSTATUS_WIN_STATUS_OBJECT_NAME_INVALID = 0xC0000033,
+ MD_NTSTATUS_WIN_STATUS_OBJECT_NAME_NOT_FOUND = 0xC0000034,
+ MD_NTSTATUS_WIN_STATUS_OBJECT_NAME_COLLISION = 0xC0000035,
+ MD_NTSTATUS_WIN_STATUS_PORT_DO_NOT_DISTURB = 0xC0000036,
+ MD_NTSTATUS_WIN_STATUS_PORT_DISCONNECTED = 0xC0000037,
+ MD_NTSTATUS_WIN_STATUS_DEVICE_ALREADY_ATTACHED = 0xC0000038,
+ MD_NTSTATUS_WIN_STATUS_OBJECT_PATH_INVALID = 0xC0000039,
+ MD_NTSTATUS_WIN_STATUS_OBJECT_PATH_NOT_FOUND = 0xC000003A,
+ MD_NTSTATUS_WIN_STATUS_OBJECT_PATH_SYNTAX_BAD = 0xC000003B,
+ MD_NTSTATUS_WIN_STATUS_DATA_OVERRUN = 0xC000003C,
+ MD_NTSTATUS_WIN_STATUS_DATA_LATE_ERROR = 0xC000003D,
+ MD_NTSTATUS_WIN_STATUS_DATA_ERROR = 0xC000003E,
+ MD_NTSTATUS_WIN_STATUS_CRC_ERROR = 0xC000003F,
+ MD_NTSTATUS_WIN_STATUS_SECTION_TOO_BIG = 0xC0000040,
+ MD_NTSTATUS_WIN_STATUS_PORT_CONNECTION_REFUSED = 0xC0000041,
+ MD_NTSTATUS_WIN_STATUS_INVALID_PORT_HANDLE = 0xC0000042,
+ MD_NTSTATUS_WIN_STATUS_SHARING_VIOLATION = 0xC0000043,
+ MD_NTSTATUS_WIN_STATUS_QUOTA_EXCEEDED = 0xC0000044,
+ MD_NTSTATUS_WIN_STATUS_INVALID_PAGE_PROTECTION = 0xC0000045,
+ MD_NTSTATUS_WIN_STATUS_MUTANT_NOT_OWNED = 0xC0000046,
+ MD_NTSTATUS_WIN_STATUS_SEMAPHORE_LIMIT_EXCEEDED = 0xC0000047,
+ MD_NTSTATUS_WIN_STATUS_PORT_ALREADY_SET = 0xC0000048,
+ MD_NTSTATUS_WIN_STATUS_SECTION_NOT_IMAGE = 0xC0000049,
+ MD_NTSTATUS_WIN_STATUS_SUSPEND_COUNT_EXCEEDED = 0xC000004A,
+ MD_NTSTATUS_WIN_STATUS_THREAD_IS_TERMINATING = 0xC000004B,
+ MD_NTSTATUS_WIN_STATUS_BAD_WORKING_SET_LIMIT = 0xC000004C,
+ MD_NTSTATUS_WIN_STATUS_INCOMPATIBLE_FILE_MAP = 0xC000004D,
+ MD_NTSTATUS_WIN_STATUS_SECTION_PROTECTION = 0xC000004E,
+ MD_NTSTATUS_WIN_STATUS_EAS_NOT_SUPPORTED = 0xC000004F,
+ MD_NTSTATUS_WIN_STATUS_EA_TOO_LARGE = 0xC0000050,
+ MD_NTSTATUS_WIN_STATUS_NONEXISTENT_EA_ENTRY = 0xC0000051,
+ MD_NTSTATUS_WIN_STATUS_NO_EAS_ON_FILE = 0xC0000052,
+ MD_NTSTATUS_WIN_STATUS_EA_CORRUPT_ERROR = 0xC0000053,
+ MD_NTSTATUS_WIN_STATUS_FILE_LOCK_CONFLICT = 0xC0000054,
+ MD_NTSTATUS_WIN_STATUS_LOCK_NOT_GRANTED = 0xC0000055,
+ MD_NTSTATUS_WIN_STATUS_DELETE_PENDING = 0xC0000056,
+ MD_NTSTATUS_WIN_STATUS_CTL_FILE_NOT_SUPPORTED = 0xC0000057,
+ MD_NTSTATUS_WIN_STATUS_UNKNOWN_REVISION = 0xC0000058,
+ MD_NTSTATUS_WIN_STATUS_REVISION_MISMATCH = 0xC0000059,
+ MD_NTSTATUS_WIN_STATUS_INVALID_OWNER = 0xC000005A,
+ MD_NTSTATUS_WIN_STATUS_INVALID_PRIMARY_GROUP = 0xC000005B,
+ MD_NTSTATUS_WIN_STATUS_NO_IMPERSONATION_TOKEN = 0xC000005C,
+ MD_NTSTATUS_WIN_STATUS_CANT_DISABLE_MANDATORY = 0xC000005D,
+ MD_NTSTATUS_WIN_STATUS_NO_LOGON_SERVERS = 0xC000005E,
+ MD_NTSTATUS_WIN_STATUS_NO_SUCH_LOGON_SESSION = 0xC000005F,
+ MD_NTSTATUS_WIN_STATUS_NO_SUCH_PRIVILEGE = 0xC0000060,
+ MD_NTSTATUS_WIN_STATUS_PRIVILEGE_NOT_HELD = 0xC0000061,
+ MD_NTSTATUS_WIN_STATUS_INVALID_ACCOUNT_NAME = 0xC0000062,
+ MD_NTSTATUS_WIN_STATUS_USER_EXISTS = 0xC0000063,
+ MD_NTSTATUS_WIN_STATUS_NO_SUCH_USER = 0xC0000064,
+ MD_NTSTATUS_WIN_STATUS_GROUP_EXISTS = 0xC0000065,
+ MD_NTSTATUS_WIN_STATUS_NO_SUCH_GROUP = 0xC0000066,
+ MD_NTSTATUS_WIN_STATUS_MEMBER_IN_GROUP = 0xC0000067,
+ MD_NTSTATUS_WIN_STATUS_MEMBER_NOT_IN_GROUP = 0xC0000068,
+ MD_NTSTATUS_WIN_STATUS_LAST_ADMIN = 0xC0000069,
+ MD_NTSTATUS_WIN_STATUS_WRONG_PASSWORD = 0xC000006A,
+ MD_NTSTATUS_WIN_STATUS_ILL_FORMED_PASSWORD = 0xC000006B,
+ MD_NTSTATUS_WIN_STATUS_PASSWORD_RESTRICTION = 0xC000006C,
+ MD_NTSTATUS_WIN_STATUS_LOGON_FAILURE = 0xC000006D,
+ MD_NTSTATUS_WIN_STATUS_ACCOUNT_RESTRICTION = 0xC000006E,
+ MD_NTSTATUS_WIN_STATUS_INVALID_LOGON_HOURS = 0xC000006F,
+ MD_NTSTATUS_WIN_STATUS_INVALID_WORKSTATION = 0xC0000070,
+ MD_NTSTATUS_WIN_STATUS_PASSWORD_EXPIRED = 0xC0000071,
+ MD_NTSTATUS_WIN_STATUS_ACCOUNT_DISABLED = 0xC0000072,
+ MD_NTSTATUS_WIN_STATUS_NONE_MAPPED = 0xC0000073,
+ MD_NTSTATUS_WIN_STATUS_TOO_MANY_LUIDS_REQUESTED = 0xC0000074,
+ MD_NTSTATUS_WIN_STATUS_LUIDS_EXHAUSTED = 0xC0000075,
+ MD_NTSTATUS_WIN_STATUS_INVALID_SUB_AUTHORITY = 0xC0000076,
+ MD_NTSTATUS_WIN_STATUS_INVALID_ACL = 0xC0000077,
+ MD_NTSTATUS_WIN_STATUS_INVALID_SID = 0xC0000078,
+ MD_NTSTATUS_WIN_STATUS_INVALID_SECURITY_DESCR = 0xC0000079,
+ MD_NTSTATUS_WIN_STATUS_PROCEDURE_NOT_FOUND = 0xC000007A,
+ MD_NTSTATUS_WIN_STATUS_INVALID_IMAGE_FORMAT = 0xC000007B,
+ MD_NTSTATUS_WIN_STATUS_NO_TOKEN = 0xC000007C,
+ MD_NTSTATUS_WIN_STATUS_BAD_INHERITANCE_ACL = 0xC000007D,
+ MD_NTSTATUS_WIN_STATUS_RANGE_NOT_LOCKED = 0xC000007E,
+ MD_NTSTATUS_WIN_STATUS_DISK_FULL = 0xC000007F,
+ MD_NTSTATUS_WIN_STATUS_SERVER_DISABLED = 0xC0000080,
+ MD_NTSTATUS_WIN_STATUS_SERVER_NOT_DISABLED = 0xC0000081,
+ MD_NTSTATUS_WIN_STATUS_TOO_MANY_GUIDS_REQUESTED = 0xC0000082,
+ MD_NTSTATUS_WIN_STATUS_GUIDS_EXHAUSTED = 0xC0000083,
+ MD_NTSTATUS_WIN_STATUS_INVALID_ID_AUTHORITY = 0xC0000084,
+ MD_NTSTATUS_WIN_STATUS_AGENTS_EXHAUSTED = 0xC0000085,
+ MD_NTSTATUS_WIN_STATUS_INVALID_VOLUME_LABEL = 0xC0000086,
+ MD_NTSTATUS_WIN_STATUS_SECTION_NOT_EXTENDED = 0xC0000087,
+ MD_NTSTATUS_WIN_STATUS_NOT_MAPPED_DATA = 0xC0000088,
+ MD_NTSTATUS_WIN_STATUS_RESOURCE_DATA_NOT_FOUND = 0xC0000089,
+ MD_NTSTATUS_WIN_STATUS_RESOURCE_TYPE_NOT_FOUND = 0xC000008A,
+ MD_NTSTATUS_WIN_STATUS_RESOURCE_NAME_NOT_FOUND = 0xC000008B,
+ MD_NTSTATUS_WIN_STATUS_ARRAY_BOUNDS_EXCEEDED = 0xC000008C,
+ MD_NTSTATUS_WIN_STATUS_FLOAT_DENORMAL_OPERAND = 0xC000008D,
+ MD_NTSTATUS_WIN_STATUS_FLOAT_DIVIDE_BY_ZERO = 0xC000008E,
+ MD_NTSTATUS_WIN_STATUS_FLOAT_INEXACT_RESULT = 0xC000008F,
+ MD_NTSTATUS_WIN_STATUS_FLOAT_INVALID_OPERATION = 0xC0000090,
+ MD_NTSTATUS_WIN_STATUS_FLOAT_OVERFLOW = 0xC0000091,
+ MD_NTSTATUS_WIN_STATUS_FLOAT_STACK_CHECK = 0xC0000092,
+ MD_NTSTATUS_WIN_STATUS_FLOAT_UNDERFLOW = 0xC0000093,
+ MD_NTSTATUS_WIN_STATUS_INTEGER_DIVIDE_BY_ZERO = 0xC0000094,
+ MD_NTSTATUS_WIN_STATUS_INTEGER_OVERFLOW = 0xC0000095,
+ MD_NTSTATUS_WIN_STATUS_PRIVILEGED_INSTRUCTION = 0xC0000096,
+ MD_NTSTATUS_WIN_STATUS_TOO_MANY_PAGING_FILES = 0xC0000097,
+ MD_NTSTATUS_WIN_STATUS_FILE_INVALID = 0xC0000098,
+ MD_NTSTATUS_WIN_STATUS_ALLOTTED_SPACE_EXCEEDED = 0xC0000099,
+ MD_NTSTATUS_WIN_STATUS_INSUFFICIENT_RESOURCES = 0xC000009A,
+ MD_NTSTATUS_WIN_STATUS_DFS_EXIT_PATH_FOUND = 0xC000009B,
+ MD_NTSTATUS_WIN_STATUS_DEVICE_DATA_ERROR = 0xC000009C,
+ MD_NTSTATUS_WIN_STATUS_DEVICE_NOT_CONNECTED = 0xC000009D,
+ MD_NTSTATUS_WIN_STATUS_DEVICE_POWER_FAILURE = 0xC000009E,
+ MD_NTSTATUS_WIN_STATUS_FREE_VM_NOT_AT_BASE = 0xC000009F,
+ MD_NTSTATUS_WIN_STATUS_MEMORY_NOT_ALLOCATED = 0xC00000A0,
+ MD_NTSTATUS_WIN_STATUS_WORKING_SET_QUOTA = 0xC00000A1,
+ MD_NTSTATUS_WIN_STATUS_MEDIA_WRITE_PROTECTED = 0xC00000A2,
+ MD_NTSTATUS_WIN_STATUS_DEVICE_NOT_READY = 0xC00000A3,
+ MD_NTSTATUS_WIN_STATUS_INVALID_GROUP_ATTRIBUTES = 0xC00000A4,
+ MD_NTSTATUS_WIN_STATUS_BAD_IMPERSONATION_LEVEL = 0xC00000A5,
+ MD_NTSTATUS_WIN_STATUS_CANT_OPEN_ANONYMOUS = 0xC00000A6,
+ MD_NTSTATUS_WIN_STATUS_BAD_VALIDATION_CLASS = 0xC00000A7,
+ MD_NTSTATUS_WIN_STATUS_BAD_TOKEN_TYPE = 0xC00000A8,
+ MD_NTSTATUS_WIN_STATUS_BAD_MASTER_BOOT_RECORD = 0xC00000A9,
+ MD_NTSTATUS_WIN_STATUS_INSTRUCTION_MISALIGNMENT = 0xC00000AA,
+ MD_NTSTATUS_WIN_STATUS_INSTANCE_NOT_AVAILABLE = 0xC00000AB,
+ MD_NTSTATUS_WIN_STATUS_PIPE_NOT_AVAILABLE = 0xC00000AC,
+ MD_NTSTATUS_WIN_STATUS_INVALID_PIPE_STATE = 0xC00000AD,
+ MD_NTSTATUS_WIN_STATUS_PIPE_BUSY = 0xC00000AE,
+ MD_NTSTATUS_WIN_STATUS_ILLEGAL_FUNCTION = 0xC00000AF,
+ MD_NTSTATUS_WIN_STATUS_PIPE_DISCONNECTED = 0xC00000B0,
+ MD_NTSTATUS_WIN_STATUS_PIPE_CLOSING = 0xC00000B1,
+ MD_NTSTATUS_WIN_STATUS_PIPE_CONNECTED = 0xC00000B2,
+ MD_NTSTATUS_WIN_STATUS_PIPE_LISTENING = 0xC00000B3,
+ MD_NTSTATUS_WIN_STATUS_INVALID_READ_MODE = 0xC00000B4,
+ MD_NTSTATUS_WIN_STATUS_IO_TIMEOUT = 0xC00000B5,
+ MD_NTSTATUS_WIN_STATUS_FILE_FORCED_CLOSED = 0xC00000B6,
+ MD_NTSTATUS_WIN_STATUS_PROFILING_NOT_STARTED = 0xC00000B7,
+ MD_NTSTATUS_WIN_STATUS_PROFILING_NOT_STOPPED = 0xC00000B8,
+ MD_NTSTATUS_WIN_STATUS_COULD_NOT_INTERPRET = 0xC00000B9,
+ MD_NTSTATUS_WIN_STATUS_FILE_IS_A_DIRECTORY = 0xC00000BA,
+ MD_NTSTATUS_WIN_STATUS_NOT_SUPPORTED = 0xC00000BB,
+ MD_NTSTATUS_WIN_STATUS_REMOTE_NOT_LISTENING = 0xC00000BC,
+ MD_NTSTATUS_WIN_STATUS_DUPLICATE_NAME = 0xC00000BD,
+ MD_NTSTATUS_WIN_STATUS_BAD_NETWORK_PATH = 0xC00000BE,
+ MD_NTSTATUS_WIN_STATUS_NETWORK_BUSY = 0xC00000BF,
+ MD_NTSTATUS_WIN_STATUS_DEVICE_DOES_NOT_EXIST = 0xC00000C0,
+ MD_NTSTATUS_WIN_STATUS_TOO_MANY_COMMANDS = 0xC00000C1,
+ MD_NTSTATUS_WIN_STATUS_ADAPTER_HARDWARE_ERROR = 0xC00000C2,
+ MD_NTSTATUS_WIN_STATUS_INVALID_NETWORK_RESPONSE = 0xC00000C3,
+ MD_NTSTATUS_WIN_STATUS_UNEXPECTED_NETWORK_ERROR = 0xC00000C4,
+ MD_NTSTATUS_WIN_STATUS_BAD_REMOTE_ADAPTER = 0xC00000C5,
+ MD_NTSTATUS_WIN_STATUS_PRINT_QUEUE_FULL = 0xC00000C6,
+ MD_NTSTATUS_WIN_STATUS_NO_SPOOL_SPACE = 0xC00000C7,
+ MD_NTSTATUS_WIN_STATUS_PRINT_CANCELLED = 0xC00000C8,
+ MD_NTSTATUS_WIN_STATUS_NETWORK_NAME_DELETED = 0xC00000C9,
+ MD_NTSTATUS_WIN_STATUS_NETWORK_ACCESS_DENIED = 0xC00000CA,
+ MD_NTSTATUS_WIN_STATUS_BAD_DEVICE_TYPE = 0xC00000CB,
+ MD_NTSTATUS_WIN_STATUS_BAD_NETWORK_NAME = 0xC00000CC,
+ MD_NTSTATUS_WIN_STATUS_TOO_MANY_NAMES = 0xC00000CD,
+ MD_NTSTATUS_WIN_STATUS_TOO_MANY_SESSIONS = 0xC00000CE,
+ MD_NTSTATUS_WIN_STATUS_SHARING_PAUSED = 0xC00000CF,
+ MD_NTSTATUS_WIN_STATUS_REQUEST_NOT_ACCEPTED = 0xC00000D0,
+ MD_NTSTATUS_WIN_STATUS_REDIRECTOR_PAUSED = 0xC00000D1,
+ MD_NTSTATUS_WIN_STATUS_NET_WRITE_FAULT = 0xC00000D2,
+ MD_NTSTATUS_WIN_STATUS_PROFILING_AT_LIMIT = 0xC00000D3,
+ MD_NTSTATUS_WIN_STATUS_NOT_SAME_DEVICE = 0xC00000D4,
+ MD_NTSTATUS_WIN_STATUS_FILE_RENAMED = 0xC00000D5,
+ MD_NTSTATUS_WIN_STATUS_VIRTUAL_CIRCUIT_CLOSED = 0xC00000D6,
+ MD_NTSTATUS_WIN_STATUS_NO_SECURITY_ON_OBJECT = 0xC00000D7,
+ MD_NTSTATUS_WIN_STATUS_CANT_WAIT = 0xC00000D8,
+ MD_NTSTATUS_WIN_STATUS_PIPE_EMPTY = 0xC00000D9,
+ MD_NTSTATUS_WIN_STATUS_CANT_ACCESS_DOMAIN_INFO = 0xC00000DA,
+ MD_NTSTATUS_WIN_STATUS_CANT_TERMINATE_SELF = 0xC00000DB,
+ MD_NTSTATUS_WIN_STATUS_INVALID_SERVER_STATE = 0xC00000DC,
+ MD_NTSTATUS_WIN_STATUS_INVALID_DOMAIN_STATE = 0xC00000DD,
+ MD_NTSTATUS_WIN_STATUS_INVALID_DOMAIN_ROLE = 0xC00000DE,
+ MD_NTSTATUS_WIN_STATUS_NO_SUCH_DOMAIN = 0xC00000DF,
+ MD_NTSTATUS_WIN_STATUS_DOMAIN_EXISTS = 0xC00000E0,
+ MD_NTSTATUS_WIN_STATUS_DOMAIN_LIMIT_EXCEEDED = 0xC00000E1,
+ MD_NTSTATUS_WIN_STATUS_OPLOCK_NOT_GRANTED = 0xC00000E2,
+ MD_NTSTATUS_WIN_STATUS_INVALID_OPLOCK_PROTOCOL = 0xC00000E3,
+ MD_NTSTATUS_WIN_STATUS_INTERNAL_DB_CORRUPTION = 0xC00000E4,
+ MD_NTSTATUS_WIN_STATUS_INTERNAL_ERROR = 0xC00000E5,
+ MD_NTSTATUS_WIN_STATUS_GENERIC_NOT_MAPPED = 0xC00000E6,
+ MD_NTSTATUS_WIN_STATUS_BAD_DESCRIPTOR_FORMAT = 0xC00000E7,
+ MD_NTSTATUS_WIN_STATUS_INVALID_USER_BUFFER = 0xC00000E8,
+ MD_NTSTATUS_WIN_STATUS_UNEXPECTED_IO_ERROR = 0xC00000E9,
+ MD_NTSTATUS_WIN_STATUS_UNEXPECTED_MM_CREATE_ERR = 0xC00000EA,
+ MD_NTSTATUS_WIN_STATUS_UNEXPECTED_MM_MAP_ERROR = 0xC00000EB,
+ MD_NTSTATUS_WIN_STATUS_UNEXPECTED_MM_EXTEND_ERR = 0xC00000EC,
+ MD_NTSTATUS_WIN_STATUS_NOT_LOGON_PROCESS = 0xC00000ED,
+ MD_NTSTATUS_WIN_STATUS_LOGON_SESSION_EXISTS = 0xC00000EE,
+ MD_NTSTATUS_WIN_STATUS_INVALID_PARAMETER_1 = 0xC00000EF,
+ MD_NTSTATUS_WIN_STATUS_INVALID_PARAMETER_2 = 0xC00000F0,
+ MD_NTSTATUS_WIN_STATUS_INVALID_PARAMETER_3 = 0xC00000F1,
+ MD_NTSTATUS_WIN_STATUS_INVALID_PARAMETER_4 = 0xC00000F2,
+ MD_NTSTATUS_WIN_STATUS_INVALID_PARAMETER_5 = 0xC00000F3,
+ MD_NTSTATUS_WIN_STATUS_INVALID_PARAMETER_6 = 0xC00000F4,
+ MD_NTSTATUS_WIN_STATUS_INVALID_PARAMETER_7 = 0xC00000F5,
+ MD_NTSTATUS_WIN_STATUS_INVALID_PARAMETER_8 = 0xC00000F6,
+ MD_NTSTATUS_WIN_STATUS_INVALID_PARAMETER_9 = 0xC00000F7,
+ MD_NTSTATUS_WIN_STATUS_INVALID_PARAMETER_10 = 0xC00000F8,
+ MD_NTSTATUS_WIN_STATUS_INVALID_PARAMETER_11 = 0xC00000F9,
+ MD_NTSTATUS_WIN_STATUS_INVALID_PARAMETER_12 = 0xC00000FA,
+ MD_NTSTATUS_WIN_STATUS_REDIRECTOR_NOT_STARTED = 0xC00000FB,
+ MD_NTSTATUS_WIN_STATUS_REDIRECTOR_STARTED = 0xC00000FC,
+ MD_NTSTATUS_WIN_STATUS_STACK_OVERFLOW = 0xC00000FD,
+ MD_NTSTATUS_WIN_STATUS_NO_SUCH_PACKAGE = 0xC00000FE,
+ MD_NTSTATUS_WIN_STATUS_BAD_FUNCTION_TABLE = 0xC00000FF,
+ MD_NTSTATUS_WIN_STATUS_VARIABLE_NOT_FOUND = 0xC0000100,
+ MD_NTSTATUS_WIN_STATUS_DIRECTORY_NOT_EMPTY = 0xC0000101,
+ MD_NTSTATUS_WIN_STATUS_FILE_CORRUPT_ERROR = 0xC0000102,
+ MD_NTSTATUS_WIN_STATUS_NOT_A_DIRECTORY = 0xC0000103,
+ MD_NTSTATUS_WIN_STATUS_BAD_LOGON_SESSION_STATE = 0xC0000104,
+ MD_NTSTATUS_WIN_STATUS_LOGON_SESSION_COLLISION = 0xC0000105,
+ MD_NTSTATUS_WIN_STATUS_NAME_TOO_LONG = 0xC0000106,
+ MD_NTSTATUS_WIN_STATUS_FILES_OPEN = 0xC0000107,
+ MD_NTSTATUS_WIN_STATUS_CONNECTION_IN_USE = 0xC0000108,
+ MD_NTSTATUS_WIN_STATUS_MESSAGE_NOT_FOUND = 0xC0000109,
+ MD_NTSTATUS_WIN_STATUS_PROCESS_IS_TERMINATING = 0xC000010A,
+ MD_NTSTATUS_WIN_STATUS_INVALID_LOGON_TYPE = 0xC000010B,
+ MD_NTSTATUS_WIN_STATUS_NO_GUID_TRANSLATION = 0xC000010C,
+ MD_NTSTATUS_WIN_STATUS_CANNOT_IMPERSONATE = 0xC000010D,
+ MD_NTSTATUS_WIN_STATUS_IMAGE_ALREADY_LOADED = 0xC000010E,
+ MD_NTSTATUS_WIN_STATUS_ABIOS_NOT_PRESENT = 0xC000010F,
+ MD_NTSTATUS_WIN_STATUS_ABIOS_LID_NOT_EXIST = 0xC0000110,
+ MD_NTSTATUS_WIN_STATUS_ABIOS_LID_ALREADY_OWNED = 0xC0000111,
+ MD_NTSTATUS_WIN_STATUS_ABIOS_NOT_LID_OWNER = 0xC0000112,
+ MD_NTSTATUS_WIN_STATUS_ABIOS_INVALID_COMMAND = 0xC0000113,
+ MD_NTSTATUS_WIN_STATUS_ABIOS_INVALID_LID = 0xC0000114,
+ MD_NTSTATUS_WIN_STATUS_ABIOS_SELECTOR_NOT_AVAILABLE = 0xC0000115,
+ MD_NTSTATUS_WIN_STATUS_ABIOS_INVALID_SELECTOR = 0xC0000116,
+ MD_NTSTATUS_WIN_STATUS_NO_LDT = 0xC0000117,
+ MD_NTSTATUS_WIN_STATUS_INVALID_LDT_SIZE = 0xC0000118,
+ MD_NTSTATUS_WIN_STATUS_INVALID_LDT_OFFSET = 0xC0000119,
+ MD_NTSTATUS_WIN_STATUS_INVALID_LDT_DESCRIPTOR = 0xC000011A,
+ MD_NTSTATUS_WIN_STATUS_INVALID_IMAGE_NE_FORMAT = 0xC000011B,
+ MD_NTSTATUS_WIN_STATUS_RXACT_INVALID_STATE = 0xC000011C,
+ MD_NTSTATUS_WIN_STATUS_RXACT_COMMIT_FAILURE = 0xC000011D,
+ MD_NTSTATUS_WIN_STATUS_MAPPED_FILE_SIZE_ZERO = 0xC000011E,
+ MD_NTSTATUS_WIN_STATUS_TOO_MANY_OPENED_FILES = 0xC000011F,
+ MD_NTSTATUS_WIN_STATUS_CANCELLED = 0xC0000120,
+ MD_NTSTATUS_WIN_STATUS_CANNOT_DELETE = 0xC0000121,
+ MD_NTSTATUS_WIN_STATUS_INVALID_COMPUTER_NAME = 0xC0000122,
+ MD_NTSTATUS_WIN_STATUS_FILE_DELETED = 0xC0000123,
+ MD_NTSTATUS_WIN_STATUS_SPECIAL_ACCOUNT = 0xC0000124,
+ MD_NTSTATUS_WIN_STATUS_SPECIAL_GROUP = 0xC0000125,
+ MD_NTSTATUS_WIN_STATUS_SPECIAL_USER = 0xC0000126,
+ MD_NTSTATUS_WIN_STATUS_MEMBERS_PRIMARY_GROUP = 0xC0000127,
+ MD_NTSTATUS_WIN_STATUS_FILE_CLOSED = 0xC0000128,
+ MD_NTSTATUS_WIN_STATUS_TOO_MANY_THREADS = 0xC0000129,
+ MD_NTSTATUS_WIN_STATUS_THREAD_NOT_IN_PROCESS = 0xC000012A,
+ MD_NTSTATUS_WIN_STATUS_TOKEN_ALREADY_IN_USE = 0xC000012B,
+ MD_NTSTATUS_WIN_STATUS_PAGEFILE_QUOTA_EXCEEDED = 0xC000012C,
+ MD_NTSTATUS_WIN_STATUS_COMMITMENT_LIMIT = 0xC000012D,
+ MD_NTSTATUS_WIN_STATUS_INVALID_IMAGE_LE_FORMAT = 0xC000012E,
+ MD_NTSTATUS_WIN_STATUS_INVALID_IMAGE_NOT_MZ = 0xC000012F,
+ MD_NTSTATUS_WIN_STATUS_INVALID_IMAGE_PROTECT = 0xC0000130,
+ MD_NTSTATUS_WIN_STATUS_INVALID_IMAGE_WIN_16 = 0xC0000131,
+ MD_NTSTATUS_WIN_STATUS_LOGON_SERVER_CONFLICT = 0xC0000132,
+ MD_NTSTATUS_WIN_STATUS_TIME_DIFFERENCE_AT_DC = 0xC0000133,
+ MD_NTSTATUS_WIN_STATUS_SYNCHRONIZATION_REQUIRED = 0xC0000134,
+ MD_NTSTATUS_WIN_STATUS_DLL_NOT_FOUND = 0xC0000135,
+ MD_NTSTATUS_WIN_STATUS_OPEN_FAILED = 0xC0000136,
+ MD_NTSTATUS_WIN_STATUS_IO_PRIVILEGE_FAILED = 0xC0000137,
+ MD_NTSTATUS_WIN_STATUS_ORDINAL_NOT_FOUND = 0xC0000138,
+ MD_NTSTATUS_WIN_STATUS_ENTRYPOINT_NOT_FOUND = 0xC0000139,
+ MD_NTSTATUS_WIN_STATUS_CONTROL_C_EXIT = 0xC000013A,
+ MD_NTSTATUS_WIN_STATUS_LOCAL_DISCONNECT = 0xC000013B,
+ MD_NTSTATUS_WIN_STATUS_REMOTE_DISCONNECT = 0xC000013C,
+ MD_NTSTATUS_WIN_STATUS_REMOTE_RESOURCES = 0xC000013D,
+ MD_NTSTATUS_WIN_STATUS_LINK_FAILED = 0xC000013E,
+ MD_NTSTATUS_WIN_STATUS_LINK_TIMEOUT = 0xC000013F,
+ MD_NTSTATUS_WIN_STATUS_INVALID_CONNECTION = 0xC0000140,
+ MD_NTSTATUS_WIN_STATUS_INVALID_ADDRESS = 0xC0000141,
+ MD_NTSTATUS_WIN_STATUS_DLL_INIT_FAILED = 0xC0000142,
+ MD_NTSTATUS_WIN_STATUS_MISSING_SYSTEMFILE = 0xC0000143,
+ MD_NTSTATUS_WIN_STATUS_UNHANDLED_EXCEPTION = 0xC0000144,
+ MD_NTSTATUS_WIN_STATUS_APP_INIT_FAILURE = 0xC0000145,
+ MD_NTSTATUS_WIN_STATUS_PAGEFILE_CREATE_FAILED = 0xC0000146,
+ MD_NTSTATUS_WIN_STATUS_NO_PAGEFILE = 0xC0000147,
+ MD_NTSTATUS_WIN_STATUS_INVALID_LEVEL = 0xC0000148,
+ MD_NTSTATUS_WIN_STATUS_WRONG_PASSWORD_CORE = 0xC0000149,
+ MD_NTSTATUS_WIN_STATUS_ILLEGAL_FLOAT_CONTEXT = 0xC000014A,
+ MD_NTSTATUS_WIN_STATUS_PIPE_BROKEN = 0xC000014B,
+ MD_NTSTATUS_WIN_STATUS_REGISTRY_CORRUPT = 0xC000014C,
+ MD_NTSTATUS_WIN_STATUS_REGISTRY_IO_FAILED = 0xC000014D,
+ MD_NTSTATUS_WIN_STATUS_NO_EVENT_PAIR = 0xC000014E,
+ MD_NTSTATUS_WIN_STATUS_UNRECOGNIZED_VOLUME = 0xC000014F,
+ MD_NTSTATUS_WIN_STATUS_SERIAL_NO_DEVICE_INITED = 0xC0000150,
+ MD_NTSTATUS_WIN_STATUS_NO_SUCH_ALIAS = 0xC0000151,
+ MD_NTSTATUS_WIN_STATUS_MEMBER_NOT_IN_ALIAS = 0xC0000152,
+ MD_NTSTATUS_WIN_STATUS_MEMBER_IN_ALIAS = 0xC0000153,
+ MD_NTSTATUS_WIN_STATUS_ALIAS_EXISTS = 0xC0000154,
+ MD_NTSTATUS_WIN_STATUS_LOGON_NOT_GRANTED = 0xC0000155,
+ MD_NTSTATUS_WIN_STATUS_TOO_MANY_SECRETS = 0xC0000156,
+ MD_NTSTATUS_WIN_STATUS_SECRET_TOO_LONG = 0xC0000157,
+ MD_NTSTATUS_WIN_STATUS_INTERNAL_DB_ERROR = 0xC0000158,
+ MD_NTSTATUS_WIN_STATUS_FULLSCREEN_MODE = 0xC0000159,
+ MD_NTSTATUS_WIN_STATUS_TOO_MANY_CONTEXT_IDS = 0xC000015A,
+ MD_NTSTATUS_WIN_STATUS_LOGON_TYPE_NOT_GRANTED = 0xC000015B,
+ MD_NTSTATUS_WIN_STATUS_NOT_REGISTRY_FILE = 0xC000015C,
+ MD_NTSTATUS_WIN_STATUS_NT_CROSS_ENCRYPTION_REQUIRED = 0xC000015D,
+ MD_NTSTATUS_WIN_STATUS_DOMAIN_CTRLR_CONFIG_ERROR = 0xC000015E,
+ MD_NTSTATUS_WIN_STATUS_FT_MISSING_MEMBER = 0xC000015F,
+ MD_NTSTATUS_WIN_STATUS_ILL_FORMED_SERVICE_ENTRY = 0xC0000160,
+ MD_NTSTATUS_WIN_STATUS_ILLEGAL_CHARACTER = 0xC0000161,
+ MD_NTSTATUS_WIN_STATUS_UNMAPPABLE_CHARACTER = 0xC0000162,
+ MD_NTSTATUS_WIN_STATUS_UNDEFINED_CHARACTER = 0xC0000163,
+ MD_NTSTATUS_WIN_STATUS_FLOPPY_VOLUME = 0xC0000164,
+ MD_NTSTATUS_WIN_STATUS_FLOPPY_ID_MARK_NOT_FOUND = 0xC0000165,
+ MD_NTSTATUS_WIN_STATUS_FLOPPY_WRONG_CYLINDER = 0xC0000166,
+ MD_NTSTATUS_WIN_STATUS_FLOPPY_UNKNOWN_ERROR = 0xC0000167,
+ MD_NTSTATUS_WIN_STATUS_FLOPPY_BAD_REGISTERS = 0xC0000168,
+ MD_NTSTATUS_WIN_STATUS_DISK_RECALIBRATE_FAILED = 0xC0000169,
+ MD_NTSTATUS_WIN_STATUS_DISK_OPERATION_FAILED = 0xC000016A,
+ MD_NTSTATUS_WIN_STATUS_DISK_RESET_FAILED = 0xC000016B,
+ MD_NTSTATUS_WIN_STATUS_SHARED_IRQ_BUSY = 0xC000016C,
+ MD_NTSTATUS_WIN_STATUS_FT_ORPHANING = 0xC000016D,
+ MD_NTSTATUS_WIN_STATUS_BIOS_FAILED_TO_CONNECT_INTERRUPT = 0xC000016E,
+ MD_NTSTATUS_WIN_STATUS_PARTITION_FAILURE = 0xC0000172,
+ MD_NTSTATUS_WIN_STATUS_INVALID_BLOCK_LENGTH = 0xC0000173,
+ MD_NTSTATUS_WIN_STATUS_DEVICE_NOT_PARTITIONED = 0xC0000174,
+ MD_NTSTATUS_WIN_STATUS_UNABLE_TO_LOCK_MEDIA = 0xC0000175,
+ MD_NTSTATUS_WIN_STATUS_UNABLE_TO_UNLOAD_MEDIA = 0xC0000176,
+ MD_NTSTATUS_WIN_STATUS_EOM_OVERFLOW = 0xC0000177,
+ MD_NTSTATUS_WIN_STATUS_NO_MEDIA = 0xC0000178,
+ MD_NTSTATUS_WIN_STATUS_NO_SUCH_MEMBER = 0xC000017A,
+ MD_NTSTATUS_WIN_STATUS_INVALID_MEMBER = 0xC000017B,
+ MD_NTSTATUS_WIN_STATUS_KEY_DELETED = 0xC000017C,
+ MD_NTSTATUS_WIN_STATUS_NO_LOG_SPACE = 0xC000017D,
+ MD_NTSTATUS_WIN_STATUS_TOO_MANY_SIDS = 0xC000017E,
+ MD_NTSTATUS_WIN_STATUS_LM_CROSS_ENCRYPTION_REQUIRED = 0xC000017F,
+ MD_NTSTATUS_WIN_STATUS_KEY_HAS_CHILDREN = 0xC0000180,
+ MD_NTSTATUS_WIN_STATUS_CHILD_MUST_BE_VOLATILE = 0xC0000181,
+ MD_NTSTATUS_WIN_STATUS_DEVICE_CONFIGURATION_ERROR = 0xC0000182,
+ MD_NTSTATUS_WIN_STATUS_DRIVER_INTERNAL_ERROR = 0xC0000183,
+ MD_NTSTATUS_WIN_STATUS_INVALID_DEVICE_STATE = 0xC0000184,
+ MD_NTSTATUS_WIN_STATUS_IO_DEVICE_ERROR = 0xC0000185,
+ MD_NTSTATUS_WIN_STATUS_DEVICE_PROTOCOL_ERROR = 0xC0000186,
+ MD_NTSTATUS_WIN_STATUS_BACKUP_CONTROLLER = 0xC0000187,
+ MD_NTSTATUS_WIN_STATUS_LOG_FILE_FULL = 0xC0000188,
+ MD_NTSTATUS_WIN_STATUS_TOO_LATE = 0xC0000189,
+ MD_NTSTATUS_WIN_STATUS_NO_TRUST_LSA_SECRET = 0xC000018A,
+ MD_NTSTATUS_WIN_STATUS_NO_TRUST_SAM_ACCOUNT = 0xC000018B,
+ MD_NTSTATUS_WIN_STATUS_TRUSTED_DOMAIN_FAILURE = 0xC000018C,
+ MD_NTSTATUS_WIN_STATUS_TRUSTED_RELATIONSHIP_FAILURE = 0xC000018D,
+ MD_NTSTATUS_WIN_STATUS_EVENTLOG_FILE_CORRUPT = 0xC000018E,
+ MD_NTSTATUS_WIN_STATUS_EVENTLOG_CANT_START = 0xC000018F,
+ MD_NTSTATUS_WIN_STATUS_TRUST_FAILURE = 0xC0000190,
+ MD_NTSTATUS_WIN_STATUS_MUTANT_LIMIT_EXCEEDED = 0xC0000191,
+ MD_NTSTATUS_WIN_STATUS_NETLOGON_NOT_STARTED = 0xC0000192,
+ MD_NTSTATUS_WIN_STATUS_ACCOUNT_EXPIRED = 0xC0000193,
+ MD_NTSTATUS_WIN_STATUS_POSSIBLE_DEADLOCK = 0xC0000194,
+ MD_NTSTATUS_WIN_STATUS_NETWORK_CREDENTIAL_CONFLICT = 0xC0000195,
+ MD_NTSTATUS_WIN_STATUS_REMOTE_SESSION_LIMIT = 0xC0000196,
+ MD_NTSTATUS_WIN_STATUS_EVENTLOG_FILE_CHANGED = 0xC0000197,
+ MD_NTSTATUS_WIN_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT = 0xC0000198,
+ MD_NTSTATUS_WIN_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT = 0xC0000199,
+ MD_NTSTATUS_WIN_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT = 0xC000019A,
+ MD_NTSTATUS_WIN_STATUS_DOMAIN_TRUST_INCONSISTENT = 0xC000019B,
+ MD_NTSTATUS_WIN_STATUS_FS_DRIVER_REQUIRED = 0xC000019C,
+ MD_NTSTATUS_WIN_STATUS_IMAGE_ALREADY_LOADED_AS_DLL = 0xC000019D,
+ MD_NTSTATUS_WIN_STATUS_INCOMPATIBLE_WITH_GLOBAL_SHORT_NAME_REGISTRY_SETTING = 0xC000019E,
+ MD_NTSTATUS_WIN_STATUS_SHORT_NAMES_NOT_ENABLED_ON_VOLUME = 0xC000019F,
+ MD_NTSTATUS_WIN_STATUS_SECURITY_STREAM_IS_INCONSISTENT = 0xC00001A0,
+ MD_NTSTATUS_WIN_STATUS_INVALID_LOCK_RANGE = 0xC00001A1,
+ MD_NTSTATUS_WIN_STATUS_INVALID_ACE_CONDITION = 0xC00001A2,
+ MD_NTSTATUS_WIN_STATUS_IMAGE_SUBSYSTEM_NOT_PRESENT = 0xC00001A3,
+ MD_NTSTATUS_WIN_STATUS_NOTIFICATION_GUID_ALREADY_DEFINED = 0xC00001A4,
+ MD_NTSTATUS_WIN_STATUS_INVALID_EXCEPTION_HANDLER = 0xC00001A5,
+ MD_NTSTATUS_WIN_STATUS_DUPLICATE_PRIVILEGES = 0xC00001A6,
+ MD_NTSTATUS_WIN_STATUS_NOT_ALLOWED_ON_SYSTEM_FILE = 0xC00001A7,
+ MD_NTSTATUS_WIN_STATUS_REPAIR_NEEDED = 0xC00001A8,
+ MD_NTSTATUS_WIN_STATUS_QUOTA_NOT_ENABLED = 0xC00001A9,
+ MD_NTSTATUS_WIN_STATUS_NO_APPLICATION_PACKAGE = 0xC00001AA,
+ MD_NTSTATUS_WIN_STATUS_FILE_METADATA_OPTIMIZATION_IN_PROGRESS = 0xC00001AB,
+ MD_NTSTATUS_WIN_STATUS_NOT_SAME_OBJECT = 0xC00001AC,
+ MD_NTSTATUS_WIN_STATUS_FATAL_MEMORY_EXHAUSTION = 0xC00001AD,
+ MD_NTSTATUS_WIN_STATUS_ERROR_PROCESS_NOT_IN_JOB = 0xC00001AE,
+ MD_NTSTATUS_WIN_STATUS_CPU_SET_INVALID = 0xC00001AF,
+ MD_NTSTATUS_WIN_STATUS_IO_DEVICE_INVALID_DATA = 0xC00001B0,
+ MD_NTSTATUS_WIN_STATUS_IO_UNALIGNED_WRITE = 0xC00001B1,
+ MD_NTSTATUS_WIN_STATUS_CONTROL_STACK_VIOLATION = 0xC00001B2,
+ MD_NTSTATUS_WIN_STATUS_NETWORK_OPEN_RESTRICTION = 0xC0000201,
+ MD_NTSTATUS_WIN_STATUS_NO_USER_SESSION_KEY = 0xC0000202,
+ MD_NTSTATUS_WIN_STATUS_USER_SESSION_DELETED = 0xC0000203,
+ MD_NTSTATUS_WIN_STATUS_RESOURCE_LANG_NOT_FOUND = 0xC0000204,
+ MD_NTSTATUS_WIN_STATUS_INSUFF_SERVER_RESOURCES = 0xC0000205,
+ MD_NTSTATUS_WIN_STATUS_INVALID_BUFFER_SIZE = 0xC0000206,
+ MD_NTSTATUS_WIN_STATUS_INVALID_ADDRESS_COMPONENT = 0xC0000207,
+ MD_NTSTATUS_WIN_STATUS_INVALID_ADDRESS_WILDCARD = 0xC0000208,
+ MD_NTSTATUS_WIN_STATUS_TOO_MANY_ADDRESSES = 0xC0000209,
+ MD_NTSTATUS_WIN_STATUS_ADDRESS_ALREADY_EXISTS = 0xC000020A,
+ MD_NTSTATUS_WIN_STATUS_ADDRESS_CLOSED = 0xC000020B,
+ MD_NTSTATUS_WIN_STATUS_CONNECTION_DISCONNECTED = 0xC000020C,
+ MD_NTSTATUS_WIN_STATUS_CONNECTION_RESET = 0xC000020D,
+ MD_NTSTATUS_WIN_STATUS_TOO_MANY_NODES = 0xC000020E,
+ MD_NTSTATUS_WIN_STATUS_TRANSACTION_ABORTED = 0xC000020F,
+ MD_NTSTATUS_WIN_STATUS_TRANSACTION_TIMED_OUT = 0xC0000210,
+ MD_NTSTATUS_WIN_STATUS_TRANSACTION_NO_RELEASE = 0xC0000211,
+ MD_NTSTATUS_WIN_STATUS_TRANSACTION_NO_MATCH = 0xC0000212,
+ MD_NTSTATUS_WIN_STATUS_TRANSACTION_RESPONDED = 0xC0000213,
+ MD_NTSTATUS_WIN_STATUS_TRANSACTION_INVALID_ID = 0xC0000214,
+ MD_NTSTATUS_WIN_STATUS_TRANSACTION_INVALID_TYPE = 0xC0000215,
+ MD_NTSTATUS_WIN_STATUS_NOT_SERVER_SESSION = 0xC0000216,
+ MD_NTSTATUS_WIN_STATUS_NOT_CLIENT_SESSION = 0xC0000217,
+ MD_NTSTATUS_WIN_STATUS_CANNOT_LOAD_REGISTRY_FILE = 0xC0000218,
+ MD_NTSTATUS_WIN_STATUS_DEBUG_ATTACH_FAILED = 0xC0000219,
+ MD_NTSTATUS_WIN_STATUS_SYSTEM_PROCESS_TERMINATED = 0xC000021A,
+ MD_NTSTATUS_WIN_STATUS_DATA_NOT_ACCEPTED = 0xC000021B,
+ MD_NTSTATUS_WIN_STATUS_NO_BROWSER_SERVERS_FOUND = 0xC000021C,
+ MD_NTSTATUS_WIN_STATUS_VDM_HARD_ERROR = 0xC000021D,
+ MD_NTSTATUS_WIN_STATUS_DRIVER_CANCEL_TIMEOUT = 0xC000021E,
+ MD_NTSTATUS_WIN_STATUS_REPLY_MESSAGE_MISMATCH = 0xC000021F,
+ MD_NTSTATUS_WIN_STATUS_MAPPED_ALIGNMENT = 0xC0000220,
+ MD_NTSTATUS_WIN_STATUS_IMAGE_CHECKSUM_MISMATCH = 0xC0000221,
+ MD_NTSTATUS_WIN_STATUS_LOST_WRITEBEHIND_DATA = 0xC0000222,
+ MD_NTSTATUS_WIN_STATUS_CLIENT_SERVER_PARAMETERS_INVALID = 0xC0000223,
+ MD_NTSTATUS_WIN_STATUS_PASSWORD_MUST_CHANGE = 0xC0000224,
+ MD_NTSTATUS_WIN_STATUS_NOT_FOUND = 0xC0000225,
+ MD_NTSTATUS_WIN_STATUS_NOT_TINY_STREAM = 0xC0000226,
+ MD_NTSTATUS_WIN_STATUS_RECOVERY_FAILURE = 0xC0000227,
+ MD_NTSTATUS_WIN_STATUS_STACK_OVERFLOW_READ = 0xC0000228,
+ MD_NTSTATUS_WIN_STATUS_FAIL_CHECK = 0xC0000229,
+ MD_NTSTATUS_WIN_STATUS_DUPLICATE_OBJECTID = 0xC000022A,
+ MD_NTSTATUS_WIN_STATUS_OBJECTID_EXISTS = 0xC000022B,
+ MD_NTSTATUS_WIN_STATUS_CONVERT_TO_LARGE = 0xC000022C,
+ MD_NTSTATUS_WIN_STATUS_RETRY = 0xC000022D,
+ MD_NTSTATUS_WIN_STATUS_FOUND_OUT_OF_SCOPE = 0xC000022E,
+ MD_NTSTATUS_WIN_STATUS_ALLOCATE_BUCKET = 0xC000022F,
+ MD_NTSTATUS_WIN_STATUS_PROPSET_NOT_FOUND = 0xC0000230,
+ MD_NTSTATUS_WIN_STATUS_MARSHALL_OVERFLOW = 0xC0000231,
+ MD_NTSTATUS_WIN_STATUS_INVALID_VARIANT = 0xC0000232,
+ MD_NTSTATUS_WIN_STATUS_DOMAIN_CONTROLLER_NOT_FOUND = 0xC0000233,
+ MD_NTSTATUS_WIN_STATUS_ACCOUNT_LOCKED_OUT = 0xC0000234,
+ MD_NTSTATUS_WIN_STATUS_HANDLE_NOT_CLOSABLE = 0xC0000235,
+ MD_NTSTATUS_WIN_STATUS_CONNECTION_REFUSED = 0xC0000236,
+ MD_NTSTATUS_WIN_STATUS_GRACEFUL_DISCONNECT = 0xC0000237,
+ MD_NTSTATUS_WIN_STATUS_ADDRESS_ALREADY_ASSOCIATED = 0xC0000238,
+ MD_NTSTATUS_WIN_STATUS_ADDRESS_NOT_ASSOCIATED = 0xC0000239,
+ MD_NTSTATUS_WIN_STATUS_CONNECTION_INVALID = 0xC000023A,
+ MD_NTSTATUS_WIN_STATUS_CONNECTION_ACTIVE = 0xC000023B,
+ MD_NTSTATUS_WIN_STATUS_NETWORK_UNREACHABLE = 0xC000023C,
+ MD_NTSTATUS_WIN_STATUS_HOST_UNREACHABLE = 0xC000023D,
+ MD_NTSTATUS_WIN_STATUS_PROTOCOL_UNREACHABLE = 0xC000023E,
+ MD_NTSTATUS_WIN_STATUS_PORT_UNREACHABLE = 0xC000023F,
+ MD_NTSTATUS_WIN_STATUS_REQUEST_ABORTED = 0xC0000240,
+ MD_NTSTATUS_WIN_STATUS_CONNECTION_ABORTED = 0xC0000241,
+ MD_NTSTATUS_WIN_STATUS_BAD_COMPRESSION_BUFFER = 0xC0000242,
+ MD_NTSTATUS_WIN_STATUS_USER_MAPPED_FILE = 0xC0000243,
+ MD_NTSTATUS_WIN_STATUS_AUDIT_FAILED = 0xC0000244,
+ MD_NTSTATUS_WIN_STATUS_TIMER_RESOLUTION_NOT_SET = 0xC0000245,
+ MD_NTSTATUS_WIN_STATUS_CONNECTION_COUNT_LIMIT = 0xC0000246,
+ MD_NTSTATUS_WIN_STATUS_LOGIN_TIME_RESTRICTION = 0xC0000247,
+ MD_NTSTATUS_WIN_STATUS_LOGIN_WKSTA_RESTRICTION = 0xC0000248,
+ MD_NTSTATUS_WIN_STATUS_IMAGE_MP_UP_MISMATCH = 0xC0000249,
+ MD_NTSTATUS_WIN_STATUS_INSUFFICIENT_LOGON_INFO = 0xC0000250,
+ MD_NTSTATUS_WIN_STATUS_BAD_DLL_ENTRYPOINT = 0xC0000251,
+ MD_NTSTATUS_WIN_STATUS_BAD_SERVICE_ENTRYPOINT = 0xC0000252,
+ MD_NTSTATUS_WIN_STATUS_LPC_REPLY_LOST = 0xC0000253,
+ MD_NTSTATUS_WIN_STATUS_IP_ADDRESS_CONFLICT1 = 0xC0000254,
+ MD_NTSTATUS_WIN_STATUS_IP_ADDRESS_CONFLICT2 = 0xC0000255,
+ MD_NTSTATUS_WIN_STATUS_REGISTRY_QUOTA_LIMIT = 0xC0000256,
+ MD_NTSTATUS_WIN_STATUS_PATH_NOT_COVERED = 0xC0000257,
+ MD_NTSTATUS_WIN_STATUS_NO_CALLBACK_ACTIVE = 0xC0000258,
+ MD_NTSTATUS_WIN_STATUS_LICENSE_QUOTA_EXCEEDED = 0xC0000259,
+ MD_NTSTATUS_WIN_STATUS_PWD_TOO_SHORT = 0xC000025A,
+ MD_NTSTATUS_WIN_STATUS_PWD_TOO_RECENT = 0xC000025B,
+ MD_NTSTATUS_WIN_STATUS_PWD_HISTORY_CONFLICT = 0xC000025C,
+ MD_NTSTATUS_WIN_STATUS_PLUGPLAY_NO_DEVICE = 0xC000025E,
+ MD_NTSTATUS_WIN_STATUS_UNSUPPORTED_COMPRESSION = 0xC000025F,
+ MD_NTSTATUS_WIN_STATUS_INVALID_HW_PROFILE = 0xC0000260,
+ MD_NTSTATUS_WIN_STATUS_INVALID_PLUGPLAY_DEVICE_PATH = 0xC0000261,
+ MD_NTSTATUS_WIN_STATUS_DRIVER_ORDINAL_NOT_FOUND = 0xC0000262,
+ MD_NTSTATUS_WIN_STATUS_DRIVER_ENTRYPOINT_NOT_FOUND = 0xC0000263,
+ MD_NTSTATUS_WIN_STATUS_RESOURCE_NOT_OWNED = 0xC0000264,
+ MD_NTSTATUS_WIN_STATUS_TOO_MANY_LINKS = 0xC0000265,
+ MD_NTSTATUS_WIN_STATUS_QUOTA_LIST_INCONSISTENT = 0xC0000266,
+ MD_NTSTATUS_WIN_STATUS_FILE_IS_OFFLINE = 0xC0000267,
+ MD_NTSTATUS_WIN_STATUS_EVALUATION_EXPIRATION = 0xC0000268,
+ MD_NTSTATUS_WIN_STATUS_ILLEGAL_DLL_RELOCATION = 0xC0000269,
+ MD_NTSTATUS_WIN_STATUS_LICENSE_VIOLATION = 0xC000026A,
+ MD_NTSTATUS_WIN_STATUS_DLL_INIT_FAILED_LOGOFF = 0xC000026B,
+ MD_NTSTATUS_WIN_STATUS_DRIVER_UNABLE_TO_LOAD = 0xC000026C,
+ MD_NTSTATUS_WIN_STATUS_DFS_UNAVAILABLE = 0xC000026D,
+ MD_NTSTATUS_WIN_STATUS_VOLUME_DISMOUNTED = 0xC000026E,
+ MD_NTSTATUS_WIN_STATUS_WX86_INTERNAL_ERROR = 0xC000026F,
+ MD_NTSTATUS_WIN_STATUS_WX86_FLOAT_STACK_CHECK = 0xC0000270,
+ MD_NTSTATUS_WIN_STATUS_VALIDATE_CONTINUE = 0xC0000271,
+ MD_NTSTATUS_WIN_STATUS_NO_MATCH = 0xC0000272,
+ MD_NTSTATUS_WIN_STATUS_NO_MORE_MATCHES = 0xC0000273,
+ MD_NTSTATUS_WIN_STATUS_NOT_A_REPARSE_POINT = 0xC0000275,
+ MD_NTSTATUS_WIN_STATUS_IO_REPARSE_TAG_INVALID = 0xC0000276,
+ MD_NTSTATUS_WIN_STATUS_IO_REPARSE_TAG_MISMATCH = 0xC0000277,
+ MD_NTSTATUS_WIN_STATUS_IO_REPARSE_DATA_INVALID = 0xC0000278,
+ MD_NTSTATUS_WIN_STATUS_IO_REPARSE_TAG_NOT_HANDLED = 0xC0000279,
+ MD_NTSTATUS_WIN_STATUS_PWD_TOO_LONG = 0xC000027A,
+ MD_NTSTATUS_WIN_STATUS_STOWED_EXCEPTION = 0xC000027B,
+ MD_NTSTATUS_WIN_STATUS_CONTEXT_STOWED_EXCEPTION = 0xC000027C,
+ MD_NTSTATUS_WIN_STATUS_REPARSE_POINT_NOT_RESOLVED = 0xC0000280,
+ MD_NTSTATUS_WIN_STATUS_DIRECTORY_IS_A_REPARSE_POINT = 0xC0000281,
+ MD_NTSTATUS_WIN_STATUS_RANGE_LIST_CONFLICT = 0xC0000282,
+ MD_NTSTATUS_WIN_STATUS_SOURCE_ELEMENT_EMPTY = 0xC0000283,
+ MD_NTSTATUS_WIN_STATUS_DESTINATION_ELEMENT_FULL = 0xC0000284,
+ MD_NTSTATUS_WIN_STATUS_ILLEGAL_ELEMENT_ADDRESS = 0xC0000285,
+ MD_NTSTATUS_WIN_STATUS_MAGAZINE_NOT_PRESENT = 0xC0000286,
+ MD_NTSTATUS_WIN_STATUS_REINITIALIZATION_NEEDED = 0xC0000287,
+ MD_NTSTATUS_WIN_STATUS_ENCRYPTION_FAILED = 0xC000028A,
+ MD_NTSTATUS_WIN_STATUS_DECRYPTION_FAILED = 0xC000028B,
+ MD_NTSTATUS_WIN_STATUS_RANGE_NOT_FOUND = 0xC000028C,
+ MD_NTSTATUS_WIN_STATUS_NO_RECOVERY_POLICY = 0xC000028D,
+ MD_NTSTATUS_WIN_STATUS_NO_EFS = 0xC000028E,
+ MD_NTSTATUS_WIN_STATUS_WRONG_EFS = 0xC000028F,
+ MD_NTSTATUS_WIN_STATUS_NO_USER_KEYS = 0xC0000290,
+ MD_NTSTATUS_WIN_STATUS_FILE_NOT_ENCRYPTED = 0xC0000291,
+ MD_NTSTATUS_WIN_STATUS_NOT_EXPORT_FORMAT = 0xC0000292,
+ MD_NTSTATUS_WIN_STATUS_FILE_ENCRYPTED = 0xC0000293,
+ MD_NTSTATUS_WIN_STATUS_WMI_GUID_NOT_FOUND = 0xC0000295,
+ MD_NTSTATUS_WIN_STATUS_WMI_INSTANCE_NOT_FOUND = 0xC0000296,
+ MD_NTSTATUS_WIN_STATUS_WMI_ITEMID_NOT_FOUND = 0xC0000297,
+ MD_NTSTATUS_WIN_STATUS_WMI_TRY_AGAIN = 0xC0000298,
+ MD_NTSTATUS_WIN_STATUS_SHARED_POLICY = 0xC0000299,
+ MD_NTSTATUS_WIN_STATUS_POLICY_OBJECT_NOT_FOUND = 0xC000029A,
+ MD_NTSTATUS_WIN_STATUS_POLICY_ONLY_IN_DS = 0xC000029B,
+ MD_NTSTATUS_WIN_STATUS_VOLUME_NOT_UPGRADED = 0xC000029C,
+ MD_NTSTATUS_WIN_STATUS_REMOTE_STORAGE_NOT_ACTIVE = 0xC000029D,
+ MD_NTSTATUS_WIN_STATUS_REMOTE_STORAGE_MEDIA_ERROR = 0xC000029E,
+ MD_NTSTATUS_WIN_STATUS_NO_TRACKING_SERVICE = 0xC000029F,
+ MD_NTSTATUS_WIN_STATUS_SERVER_SID_MISMATCH = 0xC00002A0,
+ MD_NTSTATUS_WIN_STATUS_DS_NO_ATTRIBUTE_OR_VALUE = 0xC00002A1,
+ MD_NTSTATUS_WIN_STATUS_DS_INVALID_ATTRIBUTE_SYNTAX = 0xC00002A2,
+ MD_NTSTATUS_WIN_STATUS_DS_ATTRIBUTE_TYPE_UNDEFINED = 0xC00002A3,
+ MD_NTSTATUS_WIN_STATUS_DS_ATTRIBUTE_OR_VALUE_EXISTS = 0xC00002A4,
+ MD_NTSTATUS_WIN_STATUS_DS_BUSY = 0xC00002A5,
+ MD_NTSTATUS_WIN_STATUS_DS_UNAVAILABLE = 0xC00002A6,
+ MD_NTSTATUS_WIN_STATUS_DS_NO_RIDS_ALLOCATED = 0xC00002A7,
+ MD_NTSTATUS_WIN_STATUS_DS_NO_MORE_RIDS = 0xC00002A8,
+ MD_NTSTATUS_WIN_STATUS_DS_INCORRECT_ROLE_OWNER = 0xC00002A9,
+ MD_NTSTATUS_WIN_STATUS_DS_RIDMGR_INIT_ERROR = 0xC00002AA,
+ MD_NTSTATUS_WIN_STATUS_DS_OBJ_CLASS_VIOLATION = 0xC00002AB,
+ MD_NTSTATUS_WIN_STATUS_DS_CANT_ON_NON_LEAF = 0xC00002AC,
+ MD_NTSTATUS_WIN_STATUS_DS_CANT_ON_RDN = 0xC00002AD,
+ MD_NTSTATUS_WIN_STATUS_DS_CANT_MOD_OBJ_CLASS = 0xC00002AE,
+ MD_NTSTATUS_WIN_STATUS_DS_CROSS_DOM_MOVE_FAILED = 0xC00002AF,
+ MD_NTSTATUS_WIN_STATUS_DS_GC_NOT_AVAILABLE = 0xC00002B0,
+ MD_NTSTATUS_WIN_STATUS_DIRECTORY_SERVICE_REQUIRED = 0xC00002B1,
+ MD_NTSTATUS_WIN_STATUS_REPARSE_ATTRIBUTE_CONFLICT = 0xC00002B2,
+ MD_NTSTATUS_WIN_STATUS_CANT_ENABLE_DENY_ONLY = 0xC00002B3,
+ MD_NTSTATUS_WIN_STATUS_FLOAT_MULTIPLE_FAULTS = 0xC00002B4,
+ MD_NTSTATUS_WIN_STATUS_FLOAT_MULTIPLE_TRAPS = 0xC00002B5,
+ MD_NTSTATUS_WIN_STATUS_DEVICE_REMOVED = 0xC00002B6,
+ MD_NTSTATUS_WIN_STATUS_JOURNAL_DELETE_IN_PROGRESS = 0xC00002B7,
+ MD_NTSTATUS_WIN_STATUS_JOURNAL_NOT_ACTIVE = 0xC00002B8,
+ MD_NTSTATUS_WIN_STATUS_NOINTERFACE = 0xC00002B9,
+ MD_NTSTATUS_WIN_STATUS_DS_RIDMGR_DISABLED = 0xC00002BA,
+ MD_NTSTATUS_WIN_STATUS_DS_ADMIN_LIMIT_EXCEEDED = 0xC00002C1,
+ MD_NTSTATUS_WIN_STATUS_DRIVER_FAILED_SLEEP = 0xC00002C2,
+ MD_NTSTATUS_WIN_STATUS_MUTUAL_AUTHENTICATION_FAILED = 0xC00002C3,
+ MD_NTSTATUS_WIN_STATUS_CORRUPT_SYSTEM_FILE = 0xC00002C4,
+ MD_NTSTATUS_WIN_STATUS_DATATYPE_MISALIGNMENT_ERROR = 0xC00002C5,
+ MD_NTSTATUS_WIN_STATUS_WMI_READ_ONLY = 0xC00002C6,
+ MD_NTSTATUS_WIN_STATUS_WMI_SET_FAILURE = 0xC00002C7,
+ MD_NTSTATUS_WIN_STATUS_COMMITMENT_MINIMUM = 0xC00002C8,
+ MD_NTSTATUS_WIN_STATUS_REG_NAT_CONSUMPTION = 0xC00002C9,
+ MD_NTSTATUS_WIN_STATUS_TRANSPORT_FULL = 0xC00002CA,
+ MD_NTSTATUS_WIN_STATUS_DS_SAM_INIT_FAILURE = 0xC00002CB,
+ MD_NTSTATUS_WIN_STATUS_ONLY_IF_CONNECTED = 0xC00002CC,
+ MD_NTSTATUS_WIN_STATUS_DS_SENSITIVE_GROUP_VIOLATION = 0xC00002CD,
+ MD_NTSTATUS_WIN_STATUS_PNP_RESTART_ENUMERATION = 0xC00002CE,
+ MD_NTSTATUS_WIN_STATUS_JOURNAL_ENTRY_DELETED = 0xC00002CF,
+ MD_NTSTATUS_WIN_STATUS_DS_CANT_MOD_PRIMARYGROUPID = 0xC00002D0,
+ MD_NTSTATUS_WIN_STATUS_SYSTEM_IMAGE_BAD_SIGNATURE = 0xC00002D1,
+ MD_NTSTATUS_WIN_STATUS_PNP_REBOOT_REQUIRED = 0xC00002D2,
+ MD_NTSTATUS_WIN_STATUS_POWER_STATE_INVALID = 0xC00002D3,
+ MD_NTSTATUS_WIN_STATUS_DS_INVALID_GROUP_TYPE = 0xC00002D4,
+ MD_NTSTATUS_WIN_STATUS_DS_NO_NEST_GLOBALGROUP_IN_MIXEDDOMAIN = 0xC00002D5,
+ MD_NTSTATUS_WIN_STATUS_DS_NO_NEST_LOCALGROUP_IN_MIXEDDOMAIN = 0xC00002D6,
+ MD_NTSTATUS_WIN_STATUS_DS_GLOBAL_CANT_HAVE_LOCAL_MEMBER = 0xC00002D7,
+ MD_NTSTATUS_WIN_STATUS_DS_GLOBAL_CANT_HAVE_UNIVERSAL_MEMBER = 0xC00002D8,
+ MD_NTSTATUS_WIN_STATUS_DS_UNIVERSAL_CANT_HAVE_LOCAL_MEMBER = 0xC00002D9,
+ MD_NTSTATUS_WIN_STATUS_DS_GLOBAL_CANT_HAVE_CROSSDOMAIN_MEMBER = 0xC00002DA,
+ MD_NTSTATUS_WIN_STATUS_DS_LOCAL_CANT_HAVE_CROSSDOMAIN_LOCAL_MEMBER = 0xC00002DB,
+ MD_NTSTATUS_WIN_STATUS_DS_HAVE_PRIMARY_MEMBERS = 0xC00002DC,
+ MD_NTSTATUS_WIN_STATUS_WMI_NOT_SUPPORTED = 0xC00002DD,
+ MD_NTSTATUS_WIN_STATUS_INSUFFICIENT_POWER = 0xC00002DE,
+ MD_NTSTATUS_WIN_STATUS_SAM_NEED_BOOTKEY_PASSWORD = 0xC00002DF,
+ MD_NTSTATUS_WIN_STATUS_SAM_NEED_BOOTKEY_FLOPPY = 0xC00002E0,
+ MD_NTSTATUS_WIN_STATUS_DS_CANT_START = 0xC00002E1,
+ MD_NTSTATUS_WIN_STATUS_DS_INIT_FAILURE = 0xC00002E2,
+ MD_NTSTATUS_WIN_STATUS_SAM_INIT_FAILURE = 0xC00002E3,
+ MD_NTSTATUS_WIN_STATUS_DS_GC_REQUIRED = 0xC00002E4,
+ MD_NTSTATUS_WIN_STATUS_DS_LOCAL_MEMBER_OF_LOCAL_ONLY = 0xC00002E5,
+ MD_NTSTATUS_WIN_STATUS_DS_NO_FPO_IN_UNIVERSAL_GROUPS = 0xC00002E6,
+ MD_NTSTATUS_WIN_STATUS_DS_MACHINE_ACCOUNT_QUOTA_EXCEEDED = 0xC00002E7,
+ MD_NTSTATUS_WIN_STATUS_MULTIPLE_FAULT_VIOLATION = 0xC00002E8,
+ MD_NTSTATUS_WIN_STATUS_CURRENT_DOMAIN_NOT_ALLOWED = 0xC00002E9,
+ MD_NTSTATUS_WIN_STATUS_CANNOT_MAKE = 0xC00002EA,
+ MD_NTSTATUS_WIN_STATUS_SYSTEM_SHUTDOWN = 0xC00002EB,
+ MD_NTSTATUS_WIN_STATUS_DS_INIT_FAILURE_CONSOLE = 0xC00002EC,
+ MD_NTSTATUS_WIN_STATUS_DS_SAM_INIT_FAILURE_CONSOLE = 0xC00002ED,
+ MD_NTSTATUS_WIN_STATUS_UNFINISHED_CONTEXT_DELETED = 0xC00002EE,
+ MD_NTSTATUS_WIN_STATUS_NO_TGT_REPLY = 0xC00002EF,
+ MD_NTSTATUS_WIN_STATUS_OBJECTID_NOT_FOUND = 0xC00002F0,
+ MD_NTSTATUS_WIN_STATUS_NO_IP_ADDRESSES = 0xC00002F1,
+ MD_NTSTATUS_WIN_STATUS_WRONG_CREDENTIAL_HANDLE = 0xC00002F2,
+ MD_NTSTATUS_WIN_STATUS_CRYPTO_SYSTEM_INVALID = 0xC00002F3,
+ MD_NTSTATUS_WIN_STATUS_MAX_REFERRALS_EXCEEDED = 0xC00002F4,
+ MD_NTSTATUS_WIN_STATUS_MUST_BE_KDC = 0xC00002F5,
+ MD_NTSTATUS_WIN_STATUS_STRONG_CRYPTO_NOT_SUPPORTED = 0xC00002F6,
+ MD_NTSTATUS_WIN_STATUS_TOO_MANY_PRINCIPALS = 0xC00002F7,
+ MD_NTSTATUS_WIN_STATUS_NO_PA_DATA = 0xC00002F8,
+ MD_NTSTATUS_WIN_STATUS_PKINIT_NAME_MISMATCH = 0xC00002F9,
+ MD_NTSTATUS_WIN_STATUS_SMARTCARD_LOGON_REQUIRED = 0xC00002FA,
+ MD_NTSTATUS_WIN_STATUS_KDC_INVALID_REQUEST = 0xC00002FB,
+ MD_NTSTATUS_WIN_STATUS_KDC_UNABLE_TO_REFER = 0xC00002FC,
+ MD_NTSTATUS_WIN_STATUS_KDC_UNKNOWN_ETYPE = 0xC00002FD,
+ MD_NTSTATUS_WIN_STATUS_SHUTDOWN_IN_PROGRESS = 0xC00002FE,
+ MD_NTSTATUS_WIN_STATUS_SERVER_SHUTDOWN_IN_PROGRESS = 0xC00002FF,
+ MD_NTSTATUS_WIN_STATUS_NOT_SUPPORTED_ON_SBS = 0xC0000300,
+ MD_NTSTATUS_WIN_STATUS_WMI_GUID_DISCONNECTED = 0xC0000301,
+ MD_NTSTATUS_WIN_STATUS_WMI_ALREADY_DISABLED = 0xC0000302,
+ MD_NTSTATUS_WIN_STATUS_WMI_ALREADY_ENABLED = 0xC0000303,
+ MD_NTSTATUS_WIN_STATUS_MFT_TOO_FRAGMENTED = 0xC0000304,
+ MD_NTSTATUS_WIN_STATUS_COPY_PROTECTION_FAILURE = 0xC0000305,
+ MD_NTSTATUS_WIN_STATUS_CSS_AUTHENTICATION_FAILURE = 0xC0000306,
+ MD_NTSTATUS_WIN_STATUS_CSS_KEY_NOT_PRESENT = 0xC0000307,
+ MD_NTSTATUS_WIN_STATUS_CSS_KEY_NOT_ESTABLISHED = 0xC0000308,
+ MD_NTSTATUS_WIN_STATUS_CSS_SCRAMBLED_SECTOR = 0xC0000309,
+ MD_NTSTATUS_WIN_STATUS_CSS_REGION_MISMATCH = 0xC000030A,
+ MD_NTSTATUS_WIN_STATUS_CSS_RESETS_EXHAUSTED = 0xC000030B,
+ MD_NTSTATUS_WIN_STATUS_PASSWORD_CHANGE_REQUIRED = 0xC000030C,
+ MD_NTSTATUS_WIN_STATUS_LOST_MODE_LOGON_RESTRICTION = 0xC000030D,
+ MD_NTSTATUS_WIN_STATUS_PKINIT_FAILURE = 0xC0000320,
+ MD_NTSTATUS_WIN_STATUS_SMARTCARD_SUBSYSTEM_FAILURE = 0xC0000321,
+ MD_NTSTATUS_WIN_STATUS_NO_KERB_KEY = 0xC0000322,
+ MD_NTSTATUS_WIN_STATUS_HOST_DOWN = 0xC0000350,
+ MD_NTSTATUS_WIN_STATUS_UNSUPPORTED_PREAUTH = 0xC0000351,
+ MD_NTSTATUS_WIN_STATUS_EFS_ALG_BLOB_TOO_BIG = 0xC0000352,
+ MD_NTSTATUS_WIN_STATUS_PORT_NOT_SET = 0xC0000353,
+ MD_NTSTATUS_WIN_STATUS_DEBUGGER_INACTIVE = 0xC0000354,
+ MD_NTSTATUS_WIN_STATUS_DS_VERSION_CHECK_FAILURE = 0xC0000355,
+ MD_NTSTATUS_WIN_STATUS_AUDITING_DISABLED = 0xC0000356,
+ MD_NTSTATUS_WIN_STATUS_PRENT4_MACHINE_ACCOUNT = 0xC0000357,
+ MD_NTSTATUS_WIN_STATUS_DS_AG_CANT_HAVE_UNIVERSAL_MEMBER = 0xC0000358,
+ MD_NTSTATUS_WIN_STATUS_INVALID_IMAGE_WIN_32 = 0xC0000359,
+ MD_NTSTATUS_WIN_STATUS_INVALID_IMAGE_WIN_64 = 0xC000035A,
+ MD_NTSTATUS_WIN_STATUS_BAD_BINDINGS = 0xC000035B,
+ MD_NTSTATUS_WIN_STATUS_NETWORK_SESSION_EXPIRED = 0xC000035C,
+ MD_NTSTATUS_WIN_STATUS_APPHELP_BLOCK = 0xC000035D,
+ MD_NTSTATUS_WIN_STATUS_ALL_SIDS_FILTERED = 0xC000035E,
+ MD_NTSTATUS_WIN_STATUS_NOT_SAFE_MODE_DRIVER = 0xC000035F,
+ MD_NTSTATUS_WIN_STATUS_ACCESS_DISABLED_BY_POLICY_DEFAULT = 0xC0000361,
+ MD_NTSTATUS_WIN_STATUS_ACCESS_DISABLED_BY_POLICY_PATH = 0xC0000362,
+ MD_NTSTATUS_WIN_STATUS_ACCESS_DISABLED_BY_POLICY_PUBLISHER = 0xC0000363,
+ MD_NTSTATUS_WIN_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER = 0xC0000364,
+ MD_NTSTATUS_WIN_STATUS_FAILED_DRIVER_ENTRY = 0xC0000365,
+ MD_NTSTATUS_WIN_STATUS_DEVICE_ENUMERATION_ERROR = 0xC0000366,
+ MD_NTSTATUS_WIN_STATUS_MOUNT_POINT_NOT_RESOLVED = 0xC0000368,
+ MD_NTSTATUS_WIN_STATUS_INVALID_DEVICE_OBJECT_PARAMETER = 0xC0000369,
+ MD_NTSTATUS_WIN_STATUS_MCA_OCCURED = 0xC000036A,
+ MD_NTSTATUS_WIN_STATUS_DRIVER_BLOCKED_CRITICAL = 0xC000036B,
+ MD_NTSTATUS_WIN_STATUS_DRIVER_BLOCKED = 0xC000036C,
+ MD_NTSTATUS_WIN_STATUS_DRIVER_DATABASE_ERROR = 0xC000036D,
+ MD_NTSTATUS_WIN_STATUS_SYSTEM_HIVE_TOO_LARGE = 0xC000036E,
+ MD_NTSTATUS_WIN_STATUS_INVALID_IMPORT_OF_NON_DLL = 0xC000036F,
+ MD_NTSTATUS_WIN_STATUS_NO_SECRETS = 0xC0000371,
+ MD_NTSTATUS_WIN_STATUS_ACCESS_DISABLED_NO_SAFER_UI_BY_POLICY = 0xC0000372,
+ MD_NTSTATUS_WIN_STATUS_FAILED_STACK_SWITCH = 0xC0000373,
+ MD_NTSTATUS_WIN_STATUS_HEAP_CORRUPTION = 0xC0000374,
+ MD_NTSTATUS_WIN_STATUS_SMARTCARD_WRONG_PIN = 0xC0000380,
+ MD_NTSTATUS_WIN_STATUS_SMARTCARD_CARD_BLOCKED = 0xC0000381,
+ MD_NTSTATUS_WIN_STATUS_SMARTCARD_CARD_NOT_AUTHENTICATED = 0xC0000382,
+ MD_NTSTATUS_WIN_STATUS_SMARTCARD_NO_CARD = 0xC0000383,
+ MD_NTSTATUS_WIN_STATUS_SMARTCARD_NO_KEY_CONTAINER = 0xC0000384,
+ MD_NTSTATUS_WIN_STATUS_SMARTCARD_NO_CERTIFICATE = 0xC0000385,
+ MD_NTSTATUS_WIN_STATUS_SMARTCARD_NO_KEYSET = 0xC0000386,
+ MD_NTSTATUS_WIN_STATUS_SMARTCARD_IO_ERROR = 0xC0000387,
+ MD_NTSTATUS_WIN_STATUS_DOWNGRADE_DETECTED = 0xC0000388,
+ MD_NTSTATUS_WIN_STATUS_SMARTCARD_CERT_REVOKED = 0xC0000389,
+ MD_NTSTATUS_WIN_STATUS_ISSUING_CA_UNTRUSTED = 0xC000038A,
+ MD_NTSTATUS_WIN_STATUS_REVOCATION_OFFLINE_C = 0xC000038B,
+ MD_NTSTATUS_WIN_STATUS_PKINIT_CLIENT_FAILURE = 0xC000038C,
+ MD_NTSTATUS_WIN_STATUS_SMARTCARD_CERT_EXPIRED = 0xC000038D,
+ MD_NTSTATUS_WIN_STATUS_DRIVER_FAILED_PRIOR_UNLOAD = 0xC000038E,
+ MD_NTSTATUS_WIN_STATUS_SMARTCARD_SILENT_CONTEXT = 0xC000038F,
+ MD_NTSTATUS_WIN_STATUS_PER_USER_TRUST_QUOTA_EXCEEDED = 0xC0000401,
+ MD_NTSTATUS_WIN_STATUS_ALL_USER_TRUST_QUOTA_EXCEEDED = 0xC0000402,
+ MD_NTSTATUS_WIN_STATUS_USER_DELETE_TRUST_QUOTA_EXCEEDED = 0xC0000403,
+ MD_NTSTATUS_WIN_STATUS_DS_NAME_NOT_UNIQUE = 0xC0000404,
+ MD_NTSTATUS_WIN_STATUS_DS_DUPLICATE_ID_FOUND = 0xC0000405,
+ MD_NTSTATUS_WIN_STATUS_DS_GROUP_CONVERSION_ERROR = 0xC0000406,
+ MD_NTSTATUS_WIN_STATUS_VOLSNAP_PREPARE_HIBERNATE = 0xC0000407,
+ MD_NTSTATUS_WIN_STATUS_USER2USER_REQUIRED = 0xC0000408,
+ MD_NTSTATUS_WIN_STATUS_STACK_BUFFER_OVERRUN = 0xC0000409,
+ MD_NTSTATUS_WIN_STATUS_NO_S4U_PROT_SUPPORT = 0xC000040A,
+ MD_NTSTATUS_WIN_STATUS_CROSSREALM_DELEGATION_FAILURE = 0xC000040B,
+ MD_NTSTATUS_WIN_STATUS_REVOCATION_OFFLINE_KDC = 0xC000040C,
+ MD_NTSTATUS_WIN_STATUS_ISSUING_CA_UNTRUSTED_KDC = 0xC000040D,
+ MD_NTSTATUS_WIN_STATUS_KDC_CERT_EXPIRED = 0xC000040E,
+ MD_NTSTATUS_WIN_STATUS_KDC_CERT_REVOKED = 0xC000040F,
+ MD_NTSTATUS_WIN_STATUS_PARAMETER_QUOTA_EXCEEDED = 0xC0000410,
+ MD_NTSTATUS_WIN_STATUS_HIBERNATION_FAILURE = 0xC0000411,
+ MD_NTSTATUS_WIN_STATUS_DELAY_LOAD_FAILED = 0xC0000412,
+ MD_NTSTATUS_WIN_STATUS_AUTHENTICATION_FIREWALL_FAILED = 0xC0000413,
+ MD_NTSTATUS_WIN_STATUS_VDM_DISALLOWED = 0xC0000414,
+ MD_NTSTATUS_WIN_STATUS_HUNG_DISPLAY_DRIVER_THREAD = 0xC0000415,
+ MD_NTSTATUS_WIN_STATUS_INSUFFICIENT_RESOURCE_FOR_SPECIFIED_SHARED_SECTION_SIZE = 0xC0000416,
+ MD_NTSTATUS_WIN_STATUS_INVALID_CRUNTIME_PARAMETER = 0xC0000417,
+ MD_NTSTATUS_WIN_STATUS_NTLM_BLOCKED = 0xC0000418,
+ MD_NTSTATUS_WIN_STATUS_DS_SRC_SID_EXISTS_IN_FOREST = 0xC0000419,
+ MD_NTSTATUS_WIN_STATUS_DS_DOMAIN_NAME_EXISTS_IN_FOREST = 0xC000041A,
+ MD_NTSTATUS_WIN_STATUS_DS_FLAT_NAME_EXISTS_IN_FOREST = 0xC000041B,
+ MD_NTSTATUS_WIN_STATUS_INVALID_USER_PRINCIPAL_NAME = 0xC000041C,
+ MD_NTSTATUS_WIN_STATUS_FATAL_USER_CALLBACK_EXCEPTION = 0xC000041D,
+ MD_NTSTATUS_WIN_STATUS_ASSERTION_FAILURE = 0xC0000420,
+ MD_NTSTATUS_WIN_STATUS_VERIFIER_STOP = 0xC0000421,
+ MD_NTSTATUS_WIN_STATUS_CALLBACK_POP_STACK = 0xC0000423,
+ MD_NTSTATUS_WIN_STATUS_INCOMPATIBLE_DRIVER_BLOCKED = 0xC0000424,
+ MD_NTSTATUS_WIN_STATUS_HIVE_UNLOADED = 0xC0000425,
+ MD_NTSTATUS_WIN_STATUS_COMPRESSION_DISABLED = 0xC0000426,
+ MD_NTSTATUS_WIN_STATUS_FILE_SYSTEM_LIMITATION = 0xC0000427,
+ MD_NTSTATUS_WIN_STATUS_INVALID_IMAGE_HASH = 0xC0000428,
+ MD_NTSTATUS_WIN_STATUS_NOT_CAPABLE = 0xC0000429,
+ MD_NTSTATUS_WIN_STATUS_REQUEST_OUT_OF_SEQUENCE = 0xC000042A,
+ MD_NTSTATUS_WIN_STATUS_IMPLEMENTATION_LIMIT = 0xC000042B,
+ MD_NTSTATUS_WIN_STATUS_ELEVATION_REQUIRED = 0xC000042C,
+ MD_NTSTATUS_WIN_STATUS_NO_SECURITY_CONTEXT = 0xC000042D,
+ MD_NTSTATUS_WIN_STATUS_PKU2U_CERT_FAILURE = 0xC000042F,
+ MD_NTSTATUS_WIN_STATUS_BEYOND_VDL = 0xC0000432,
+ MD_NTSTATUS_WIN_STATUS_ENCOUNTERED_WRITE_IN_PROGRESS = 0xC0000433,
+ MD_NTSTATUS_WIN_STATUS_PTE_CHANGED = 0xC0000434,
+ MD_NTSTATUS_WIN_STATUS_PURGE_FAILED = 0xC0000435,
+ MD_NTSTATUS_WIN_STATUS_CRED_REQUIRES_CONFIRMATION = 0xC0000440,
+ MD_NTSTATUS_WIN_STATUS_CS_ENCRYPTION_INVALID_SERVER_RESPONSE = 0xC0000441,
+ MD_NTSTATUS_WIN_STATUS_CS_ENCRYPTION_UNSUPPORTED_SERVER = 0xC0000442,
+ MD_NTSTATUS_WIN_STATUS_CS_ENCRYPTION_EXISTING_ENCRYPTED_FILE = 0xC0000443,
+ MD_NTSTATUS_WIN_STATUS_CS_ENCRYPTION_NEW_ENCRYPTED_FILE = 0xC0000444,
+ MD_NTSTATUS_WIN_STATUS_CS_ENCRYPTION_FILE_NOT_CSE = 0xC0000445,
+ MD_NTSTATUS_WIN_STATUS_INVALID_LABEL = 0xC0000446,
+ MD_NTSTATUS_WIN_STATUS_DRIVER_PROCESS_TERMINATED = 0xC0000450,
+ MD_NTSTATUS_WIN_STATUS_AMBIGUOUS_SYSTEM_DEVICE = 0xC0000451,
+ MD_NTSTATUS_WIN_STATUS_SYSTEM_DEVICE_NOT_FOUND = 0xC0000452,
+ MD_NTSTATUS_WIN_STATUS_RESTART_BOOT_APPLICATION = 0xC0000453,
+ MD_NTSTATUS_WIN_STATUS_INSUFFICIENT_NVRAM_RESOURCES = 0xC0000454,
+ MD_NTSTATUS_WIN_STATUS_INVALID_SESSION = 0xC0000455,
+ MD_NTSTATUS_WIN_STATUS_THREAD_ALREADY_IN_SESSION = 0xC0000456,
+ MD_NTSTATUS_WIN_STATUS_THREAD_NOT_IN_SESSION = 0xC0000457,
+ MD_NTSTATUS_WIN_STATUS_INVALID_WEIGHT = 0xC0000458,
+ MD_NTSTATUS_WIN_STATUS_REQUEST_PAUSED = 0xC0000459,
+ MD_NTSTATUS_WIN_STATUS_NO_RANGES_PROCESSED = 0xC0000460,
+ MD_NTSTATUS_WIN_STATUS_DISK_RESOURCES_EXHAUSTED = 0xC0000461,
+ MD_NTSTATUS_WIN_STATUS_NEEDS_REMEDIATION = 0xC0000462,
+ MD_NTSTATUS_WIN_STATUS_DEVICE_FEATURE_NOT_SUPPORTED = 0xC0000463,
+ MD_NTSTATUS_WIN_STATUS_DEVICE_UNREACHABLE = 0xC0000464,
+ MD_NTSTATUS_WIN_STATUS_INVALID_TOKEN = 0xC0000465,
+ MD_NTSTATUS_WIN_STATUS_SERVER_UNAVAILABLE = 0xC0000466,
+ MD_NTSTATUS_WIN_STATUS_FILE_NOT_AVAILABLE = 0xC0000467,
+ MD_NTSTATUS_WIN_STATUS_DEVICE_INSUFFICIENT_RESOURCES = 0xC0000468,
+ MD_NTSTATUS_WIN_STATUS_PACKAGE_UPDATING = 0xC0000469,
+ MD_NTSTATUS_WIN_STATUS_NOT_READ_FROM_COPY = 0xC000046A,
+ MD_NTSTATUS_WIN_STATUS_FT_WRITE_FAILURE = 0xC000046B,
+ MD_NTSTATUS_WIN_STATUS_FT_DI_SCAN_REQUIRED = 0xC000046C,
+ MD_NTSTATUS_WIN_STATUS_OBJECT_NOT_EXTERNALLY_BACKED = 0xC000046D,
+ MD_NTSTATUS_WIN_STATUS_EXTERNAL_BACKING_PROVIDER_UNKNOWN = 0xC000046E,
+ MD_NTSTATUS_WIN_STATUS_COMPRESSION_NOT_BENEFICIAL = 0xC000046F,
+ MD_NTSTATUS_WIN_STATUS_DATA_CHECKSUM_ERROR = 0xC0000470,
+ MD_NTSTATUS_WIN_STATUS_INTERMIXED_KERNEL_EA_OPERATION = 0xC0000471,
+ MD_NTSTATUS_WIN_STATUS_TRIM_READ_ZERO_NOT_SUPPORTED = 0xC0000472,
+ MD_NTSTATUS_WIN_STATUS_TOO_MANY_SEGMENT_DESCRIPTORS = 0xC0000473,
+ MD_NTSTATUS_WIN_STATUS_INVALID_OFFSET_ALIGNMENT = 0xC0000474,
+ MD_NTSTATUS_WIN_STATUS_INVALID_FIELD_IN_PARAMETER_LIST = 0xC0000475,
+ MD_NTSTATUS_WIN_STATUS_OPERATION_IN_PROGRESS = 0xC0000476,
+ MD_NTSTATUS_WIN_STATUS_INVALID_INITIATOR_TARGET_PATH = 0xC0000477,
+ MD_NTSTATUS_WIN_STATUS_SCRUB_DATA_DISABLED = 0xC0000478,
+ MD_NTSTATUS_WIN_STATUS_NOT_REDUNDANT_STORAGE = 0xC0000479,
+ MD_NTSTATUS_WIN_STATUS_RESIDENT_FILE_NOT_SUPPORTED = 0xC000047A,
+ MD_NTSTATUS_WIN_STATUS_COMPRESSED_FILE_NOT_SUPPORTED = 0xC000047B,
+ MD_NTSTATUS_WIN_STATUS_DIRECTORY_NOT_SUPPORTED = 0xC000047C,
+ MD_NTSTATUS_WIN_STATUS_IO_OPERATION_TIMEOUT = 0xC000047D,
+ MD_NTSTATUS_WIN_STATUS_SYSTEM_NEEDS_REMEDIATION = 0xC000047E,
+ MD_NTSTATUS_WIN_STATUS_APPX_INTEGRITY_FAILURE_CLR_NGEN = 0xC000047F,
+ MD_NTSTATUS_WIN_STATUS_SHARE_UNAVAILABLE = 0xC0000480,
+ MD_NTSTATUS_WIN_STATUS_APISET_NOT_HOSTED = 0xC0000481,
+ MD_NTSTATUS_WIN_STATUS_APISET_NOT_PRESENT = 0xC0000482,
+ MD_NTSTATUS_WIN_STATUS_DEVICE_HARDWARE_ERROR = 0xC0000483,
+ MD_NTSTATUS_WIN_STATUS_FIRMWARE_SLOT_INVALID = 0xC0000484,
+ MD_NTSTATUS_WIN_STATUS_FIRMWARE_IMAGE_INVALID = 0xC0000485,
+ MD_NTSTATUS_WIN_STATUS_STORAGE_TOPOLOGY_ID_MISMATCH = 0xC0000486,
+ MD_NTSTATUS_WIN_STATUS_WIM_NOT_BOOTABLE = 0xC0000487,
+ MD_NTSTATUS_WIN_STATUS_BLOCKED_BY_PARENTAL_CONTROLS = 0xC0000488,
+ MD_NTSTATUS_WIN_STATUS_NEEDS_REGISTRATION = 0xC0000489,
+ MD_NTSTATUS_WIN_STATUS_QUOTA_ACTIVITY = 0xC000048A,
+ MD_NTSTATUS_WIN_STATUS_CALLBACK_INVOKE_INLINE = 0xC000048B,
+ MD_NTSTATUS_WIN_STATUS_BLOCK_TOO_MANY_REFERENCES = 0xC000048C,
+ MD_NTSTATUS_WIN_STATUS_MARKED_TO_DISALLOW_WRITES = 0xC000048D,
+ MD_NTSTATUS_WIN_STATUS_NETWORK_ACCESS_DENIED_EDP = 0xC000048E,
+ MD_NTSTATUS_WIN_STATUS_ENCLAVE_FAILURE = 0xC000048F,
+ MD_NTSTATUS_WIN_STATUS_PNP_NO_COMPAT_DRIVERS = 0xC0000490,
+ MD_NTSTATUS_WIN_STATUS_PNP_DRIVER_PACKAGE_NOT_FOUND = 0xC0000491,
+ MD_NTSTATUS_WIN_STATUS_PNP_DRIVER_CONFIGURATION_NOT_FOUND = 0xC0000492,
+ MD_NTSTATUS_WIN_STATUS_PNP_DRIVER_CONFIGURATION_INCOMPLETE = 0xC0000493,
+ MD_NTSTATUS_WIN_STATUS_PNP_FUNCTION_DRIVER_REQUIRED = 0xC0000494,
+ MD_NTSTATUS_WIN_STATUS_PNP_DEVICE_CONFIGURATION_PENDING = 0xC0000495,
+ MD_NTSTATUS_WIN_STATUS_DEVICE_HINT_NAME_BUFFER_TOO_SMALL = 0xC0000496,
+ MD_NTSTATUS_WIN_STATUS_PACKAGE_NOT_AVAILABLE = 0xC0000497,
+ MD_NTSTATUS_WIN_STATUS_DEVICE_IN_MAINTENANCE = 0xC0000499,
+ MD_NTSTATUS_WIN_STATUS_NOT_SUPPORTED_ON_DAX = 0xC000049A,
+ MD_NTSTATUS_WIN_STATUS_FREE_SPACE_TOO_FRAGMENTED = 0xC000049B,
+ MD_NTSTATUS_WIN_STATUS_DAX_MAPPING_EXISTS = 0xC000049C,
+ MD_NTSTATUS_WIN_STATUS_CHILD_PROCESS_BLOCKED = 0xC000049D,
+ MD_NTSTATUS_WIN_STATUS_STORAGE_LOST_DATA_PERSISTENCE = 0xC000049E,
+ MD_NTSTATUS_WIN_STATUS_VRF_CFG_AND_IO_ENABLED = 0xC000049F,
+ MD_NTSTATUS_WIN_STATUS_PARTITION_TERMINATING = 0xC00004A0,
+ MD_NTSTATUS_WIN_STATUS_EXTERNAL_SYSKEY_NOT_SUPPORTED = 0xC00004A1,
+ MD_NTSTATUS_WIN_STATUS_ENCLAVE_VIOLATION = 0xC00004A2,
+ MD_NTSTATUS_WIN_STATUS_FILE_PROTECTED_UNDER_DPL = 0xC00004A3,
+ MD_NTSTATUS_WIN_STATUS_VOLUME_NOT_CLUSTER_ALIGNED = 0xC00004A4,
+ MD_NTSTATUS_WIN_STATUS_NO_PHYSICALLY_ALIGNED_FREE_SPACE_FOUND = 0xC00004A5,
+ MD_NTSTATUS_WIN_STATUS_APPX_FILE_NOT_ENCRYPTED = 0xC00004A6,
+ MD_NTSTATUS_WIN_STATUS_RWRAW_ENCRYPTED_FILE_NOT_ENCRYPTED = 0xC00004A7,
+ MD_NTSTATUS_WIN_STATUS_RWRAW_ENCRYPTED_INVALID_EDATAINFO_FILEOFFSET = 0xC00004A8,
+ MD_NTSTATUS_WIN_STATUS_RWRAW_ENCRYPTED_INVALID_EDATAINFO_FILERANGE = 0xC00004A9,
+ MD_NTSTATUS_WIN_STATUS_RWRAW_ENCRYPTED_INVALID_EDATAINFO_PARAMETER = 0xC00004AA,
+ MD_NTSTATUS_WIN_STATUS_FT_READ_FAILURE = 0xC00004AB,
+ MD_NTSTATUS_WIN_STATUS_PATCH_CONFLICT = 0xC00004AC,
+ MD_NTSTATUS_WIN_STATUS_STORAGE_RESERVE_ID_INVALID = 0xC00004AD,
+ MD_NTSTATUS_WIN_STATUS_STORAGE_RESERVE_DOES_NOT_EXIST = 0xC00004AE,
+ MD_NTSTATUS_WIN_STATUS_STORAGE_RESERVE_ALREADY_EXISTS = 0xC00004AF,
+ MD_NTSTATUS_WIN_STATUS_STORAGE_RESERVE_NOT_EMPTY = 0xC00004B0,
+ MD_NTSTATUS_WIN_STATUS_NOT_A_DAX_VOLUME = 0xC00004B1,
+ MD_NTSTATUS_WIN_STATUS_NOT_DAX_MAPPABLE = 0xC00004B2,
+ MD_NTSTATUS_WIN_STATUS_CASE_DIFFERING_NAMES_IN_DIR = 0xC00004B3,
+ MD_NTSTATUS_WIN_STATUS_FILE_NOT_SUPPORTED = 0xC00004B4,
+ MD_NTSTATUS_WIN_STATUS_NOT_SUPPORTED_WITH_BTT = 0xC00004B5,
+ MD_NTSTATUS_WIN_STATUS_ENCRYPTION_DISABLED = 0xC00004B6,
+ MD_NTSTATUS_WIN_STATUS_ENCRYPTING_METADATA_DISALLOWED = 0xC00004B7,
+ MD_NTSTATUS_WIN_STATUS_CANT_CLEAR_ENCRYPTION_FLAG = 0xC00004B8,
+ MD_NTSTATUS_WIN_STATUS_UNSATISFIED_DEPENDENCIES = 0xC00004B9,
+ MD_NTSTATUS_WIN_STATUS_CASE_SENSITIVE_PATH = 0xC00004BA,
+ MD_NTSTATUS_WIN_STATUS_HAS_SYSTEM_CRITICAL_FILES = 0xC00004BD,
+ MD_NTSTATUS_WIN_STATUS_INVALID_TASK_NAME = 0xC0000500,
+ MD_NTSTATUS_WIN_STATUS_INVALID_TASK_INDEX = 0xC0000501,
+ MD_NTSTATUS_WIN_STATUS_THREAD_ALREADY_IN_TASK = 0xC0000502,
+ MD_NTSTATUS_WIN_STATUS_CALLBACK_BYPASS = 0xC0000503,
+ MD_NTSTATUS_WIN_STATUS_UNDEFINED_SCOPE = 0xC0000504,
+ MD_NTSTATUS_WIN_STATUS_INVALID_CAP = 0xC0000505,
+ MD_NTSTATUS_WIN_STATUS_NOT_GUI_PROCESS = 0xC0000506,
+ MD_NTSTATUS_WIN_STATUS_DEVICE_HUNG = 0xC0000507,
+ MD_NTSTATUS_WIN_STATUS_CONTAINER_ASSIGNED = 0xC0000508,
+ MD_NTSTATUS_WIN_STATUS_JOB_NO_CONTAINER = 0xC0000509,
+ MD_NTSTATUS_WIN_STATUS_DEVICE_UNRESPONSIVE = 0xC000050A,
+ MD_NTSTATUS_WIN_STATUS_REPARSE_POINT_ENCOUNTERED = 0xC000050B,
+ MD_NTSTATUS_WIN_STATUS_ATTRIBUTE_NOT_PRESENT = 0xC000050C,
+ MD_NTSTATUS_WIN_STATUS_NOT_A_TIERED_VOLUME = 0xC000050D,
+ MD_NTSTATUS_WIN_STATUS_ALREADY_HAS_STREAM_ID = 0xC000050E,
+ MD_NTSTATUS_WIN_STATUS_JOB_NOT_EMPTY = 0xC000050F,
+ MD_NTSTATUS_WIN_STATUS_ALREADY_INITIALIZED = 0xC0000510,
+ MD_NTSTATUS_WIN_STATUS_ENCLAVE_NOT_TERMINATED = 0xC0000511,
+ MD_NTSTATUS_WIN_STATUS_ENCLAVE_IS_TERMINATING = 0xC0000512,
+ MD_NTSTATUS_WIN_STATUS_SMB1_NOT_AVAILABLE = 0xC0000513,
+ MD_NTSTATUS_WIN_STATUS_SMR_GARBAGE_COLLECTION_REQUIRED = 0xC0000514,
+ MD_NTSTATUS_WIN_STATUS_INTERRUPTED = 0xC0000515,
+ MD_NTSTATUS_WIN_STATUS_THREAD_NOT_RUNNING = 0xC0000516,
+ MD_NTSTATUS_WIN_STATUS_FAIL_FAST_EXCEPTION = 0xC0000602,
+ MD_NTSTATUS_WIN_STATUS_IMAGE_CERT_REVOKED = 0xC0000603,
+ MD_NTSTATUS_WIN_STATUS_DYNAMIC_CODE_BLOCKED = 0xC0000604,
+ MD_NTSTATUS_WIN_STATUS_IMAGE_CERT_EXPIRED = 0xC0000605,
+ MD_NTSTATUS_WIN_STATUS_STRICT_CFG_VIOLATION = 0xC0000606,
+ MD_NTSTATUS_WIN_STATUS_SET_CONTEXT_DENIED = 0xC000060A,
+ MD_NTSTATUS_WIN_STATUS_CROSS_PARTITION_VIOLATION = 0xC000060B,
+ MD_NTSTATUS_WIN_STATUS_PORT_CLOSED = 0xC0000700,
+ MD_NTSTATUS_WIN_STATUS_MESSAGE_LOST = 0xC0000701,
+ MD_NTSTATUS_WIN_STATUS_INVALID_MESSAGE = 0xC0000702,
+ MD_NTSTATUS_WIN_STATUS_REQUEST_CANCELED = 0xC0000703,
+ MD_NTSTATUS_WIN_STATUS_RECURSIVE_DISPATCH = 0xC0000704,
+ MD_NTSTATUS_WIN_STATUS_LPC_RECEIVE_BUFFER_EXPECTED = 0xC0000705,
+ MD_NTSTATUS_WIN_STATUS_LPC_INVALID_CONNECTION_USAGE = 0xC0000706,
+ MD_NTSTATUS_WIN_STATUS_LPC_REQUESTS_NOT_ALLOWED = 0xC0000707,
+ MD_NTSTATUS_WIN_STATUS_RESOURCE_IN_USE = 0xC0000708,
+ MD_NTSTATUS_WIN_STATUS_HARDWARE_MEMORY_ERROR = 0xC0000709,
+ MD_NTSTATUS_WIN_STATUS_THREADPOOL_HANDLE_EXCEPTION = 0xC000070A,
+ MD_NTSTATUS_WIN_STATUS_THREADPOOL_SET_EVENT_ON_COMPLETION_FAILED = 0xC000070B,
+ MD_NTSTATUS_WIN_STATUS_THREADPOOL_RELEASE_SEMAPHORE_ON_COMPLETION_FAILED = 0xC000070C,
+ MD_NTSTATUS_WIN_STATUS_THREADPOOL_RELEASE_MUTEX_ON_COMPLETION_FAILED = 0xC000070D,
+ MD_NTSTATUS_WIN_STATUS_THREADPOOL_FREE_LIBRARY_ON_COMPLETION_FAILED = 0xC000070E,
+ MD_NTSTATUS_WIN_STATUS_THREADPOOL_RELEASED_DURING_OPERATION = 0xC000070F,
+ MD_NTSTATUS_WIN_STATUS_CALLBACK_RETURNED_WHILE_IMPERSONATING = 0xC0000710,
+ MD_NTSTATUS_WIN_STATUS_APC_RETURNED_WHILE_IMPERSONATING = 0xC0000711,
+ MD_NTSTATUS_WIN_STATUS_PROCESS_IS_PROTECTED = 0xC0000712,
+ MD_NTSTATUS_WIN_STATUS_MCA_EXCEPTION = 0xC0000713,
+ MD_NTSTATUS_WIN_STATUS_CERTIFICATE_MAPPING_NOT_UNIQUE = 0xC0000714,
+ MD_NTSTATUS_WIN_STATUS_SYMLINK_CLASS_DISABLED = 0xC0000715,
+ MD_NTSTATUS_WIN_STATUS_INVALID_IDN_NORMALIZATION = 0xC0000716,
+ MD_NTSTATUS_WIN_STATUS_NO_UNICODE_TRANSLATION = 0xC0000717,
+ MD_NTSTATUS_WIN_STATUS_ALREADY_REGISTERED = 0xC0000718,
+ MD_NTSTATUS_WIN_STATUS_CONTEXT_MISMATCH = 0xC0000719,
+ MD_NTSTATUS_WIN_STATUS_PORT_ALREADY_HAS_COMPLETION_LIST = 0xC000071A,
+ MD_NTSTATUS_WIN_STATUS_CALLBACK_RETURNED_THREAD_PRIORITY = 0xC000071B,
+ MD_NTSTATUS_WIN_STATUS_INVALID_THREAD = 0xC000071C,
+ MD_NTSTATUS_WIN_STATUS_CALLBACK_RETURNED_TRANSACTION = 0xC000071D,
+ MD_NTSTATUS_WIN_STATUS_CALLBACK_RETURNED_LDR_LOCK = 0xC000071E,
+ MD_NTSTATUS_WIN_STATUS_CALLBACK_RETURNED_LANG = 0xC000071F,
+ MD_NTSTATUS_WIN_STATUS_CALLBACK_RETURNED_PRI_BACK = 0xC0000720,
+ MD_NTSTATUS_WIN_STATUS_CALLBACK_RETURNED_THREAD_AFFINITY = 0xC0000721,
+ MD_NTSTATUS_WIN_STATUS_LPC_HANDLE_COUNT_EXCEEDED = 0xC0000722,
+ MD_NTSTATUS_WIN_STATUS_EXECUTABLE_MEMORY_WRITE = 0xC0000723,
+ MD_NTSTATUS_WIN_STATUS_KERNEL_EXECUTABLE_MEMORY_WRITE = 0xC0000724,
+ MD_NTSTATUS_WIN_STATUS_ATTACHED_EXECUTABLE_MEMORY_WRITE = 0xC0000725,
+ MD_NTSTATUS_WIN_STATUS_TRIGGERED_EXECUTABLE_MEMORY_WRITE = 0xC0000726,
+ MD_NTSTATUS_WIN_STATUS_DISK_REPAIR_DISABLED = 0xC0000800,
+ MD_NTSTATUS_WIN_STATUS_DS_DOMAIN_RENAME_IN_PROGRESS = 0xC0000801,
+ MD_NTSTATUS_WIN_STATUS_DISK_QUOTA_EXCEEDED = 0xC0000802,
+ MD_NTSTATUS_WIN_STATUS_CONTENT_BLOCKED = 0xC0000804,
+ MD_NTSTATUS_WIN_STATUS_BAD_CLUSTERS = 0xC0000805,
+ MD_NTSTATUS_WIN_STATUS_VOLUME_DIRTY = 0xC0000806,
+ MD_NTSTATUS_WIN_STATUS_DISK_REPAIR_UNSUCCESSFUL = 0xC0000808,
+ MD_NTSTATUS_WIN_STATUS_CORRUPT_LOG_OVERFULL = 0xC0000809,
+ MD_NTSTATUS_WIN_STATUS_CORRUPT_LOG_CORRUPTED = 0xC000080A,
+ MD_NTSTATUS_WIN_STATUS_CORRUPT_LOG_UNAVAILABLE = 0xC000080B,
+ MD_NTSTATUS_WIN_STATUS_CORRUPT_LOG_DELETED_FULL = 0xC000080C,
+ MD_NTSTATUS_WIN_STATUS_CORRUPT_LOG_CLEARED = 0xC000080D,
+ MD_NTSTATUS_WIN_STATUS_ORPHAN_NAME_EXHAUSTED = 0xC000080E,
+ MD_NTSTATUS_WIN_STATUS_PROACTIVE_SCAN_IN_PROGRESS = 0xC000080F,
+ MD_NTSTATUS_WIN_STATUS_ENCRYPTED_IO_NOT_POSSIBLE = 0xC0000810,
+ MD_NTSTATUS_WIN_STATUS_CORRUPT_LOG_UPLEVEL_RECORDS = 0xC0000811,
+ MD_NTSTATUS_WIN_STATUS_FILE_CHECKED_OUT = 0xC0000901,
+ MD_NTSTATUS_WIN_STATUS_CHECKOUT_REQUIRED = 0xC0000902,
+ MD_NTSTATUS_WIN_STATUS_BAD_FILE_TYPE = 0xC0000903,
+ MD_NTSTATUS_WIN_STATUS_FILE_TOO_LARGE = 0xC0000904,
+ MD_NTSTATUS_WIN_STATUS_FORMS_AUTH_REQUIRED = 0xC0000905,
+ MD_NTSTATUS_WIN_STATUS_VIRUS_INFECTED = 0xC0000906,
+ MD_NTSTATUS_WIN_STATUS_VIRUS_DELETED = 0xC0000907,
+ MD_NTSTATUS_WIN_STATUS_BAD_MCFG_TABLE = 0xC0000908,
+ MD_NTSTATUS_WIN_STATUS_CANNOT_BREAK_OPLOCK = 0xC0000909,
+ MD_NTSTATUS_WIN_STATUS_BAD_KEY = 0xC000090A,
+ MD_NTSTATUS_WIN_STATUS_BAD_DATA = 0xC000090B,
+ MD_NTSTATUS_WIN_STATUS_NO_KEY = 0xC000090C,
+ MD_NTSTATUS_WIN_STATUS_FILE_HANDLE_REVOKED = 0xC0000910,
+ MD_NTSTATUS_WIN_STATUS_WOW_ASSERTION = 0xC0009898,
+ MD_NTSTATUS_WIN_STATUS_INVALID_SIGNATURE = 0xC000A000,
+ MD_NTSTATUS_WIN_STATUS_HMAC_NOT_SUPPORTED = 0xC000A001,
+ MD_NTSTATUS_WIN_STATUS_AUTH_TAG_MISMATCH = 0xC000A002,
+ MD_NTSTATUS_WIN_STATUS_INVALID_STATE_TRANSITION = 0xC000A003,
+ MD_NTSTATUS_WIN_STATUS_INVALID_KERNEL_INFO_VERSION = 0xC000A004,
+ MD_NTSTATUS_WIN_STATUS_INVALID_PEP_INFO_VERSION = 0xC000A005,
+ MD_NTSTATUS_WIN_STATUS_HANDLE_REVOKED = 0xC000A006,
+ MD_NTSTATUS_WIN_STATUS_EOF_ON_GHOSTED_RANGE = 0xC000A007,
+ MD_NTSTATUS_WIN_STATUS_CC_NEEDS_CALLBACK_SECTION_DRAIN = 0xC000A008,
+ MD_NTSTATUS_WIN_STATUS_IPSEC_QUEUE_OVERFLOW = 0xC000A010,
+ MD_NTSTATUS_WIN_STATUS_ND_QUEUE_OVERFLOW = 0xC000A011,
+ MD_NTSTATUS_WIN_STATUS_HOPLIMIT_EXCEEDED = 0xC000A012,
+ MD_NTSTATUS_WIN_STATUS_PROTOCOL_NOT_SUPPORTED = 0xC000A013,
+ MD_NTSTATUS_WIN_STATUS_FASTPATH_REJECTED = 0xC000A014,
+ MD_NTSTATUS_WIN_STATUS_LOST_WRITEBEHIND_DATA_NETWORK_DISCONNECTED = 0xC000A080,
+ MD_NTSTATUS_WIN_STATUS_LOST_WRITEBEHIND_DATA_NETWORK_SERVER_ERROR = 0xC000A081,
+ MD_NTSTATUS_WIN_STATUS_LOST_WRITEBEHIND_DATA_LOCAL_DISK_ERROR = 0xC000A082,
+ MD_NTSTATUS_WIN_STATUS_XML_PARSE_ERROR = 0xC000A083,
+ MD_NTSTATUS_WIN_STATUS_XMLDSIG_ERROR = 0xC000A084,
+ MD_NTSTATUS_WIN_STATUS_WRONG_COMPARTMENT = 0xC000A085,
+ MD_NTSTATUS_WIN_STATUS_AUTHIP_FAILURE = 0xC000A086,
+ MD_NTSTATUS_WIN_STATUS_DS_OID_MAPPED_GROUP_CANT_HAVE_MEMBERS = 0xC000A087,
+ MD_NTSTATUS_WIN_STATUS_DS_OID_NOT_FOUND = 0xC000A088,
+ MD_NTSTATUS_WIN_STATUS_INCORRECT_ACCOUNT_TYPE = 0xC000A089,
+ MD_NTSTATUS_WIN_STATUS_HASH_NOT_SUPPORTED = 0xC000A100,
+ MD_NTSTATUS_WIN_STATUS_HASH_NOT_PRESENT = 0xC000A101,
+ MD_NTSTATUS_WIN_STATUS_SECONDARY_IC_PROVIDER_NOT_REGISTERED = 0xC000A121,
+ MD_NTSTATUS_WIN_STATUS_GPIO_CLIENT_INFORMATION_INVALID = 0xC000A122,
+ MD_NTSTATUS_WIN_STATUS_GPIO_VERSION_NOT_SUPPORTED = 0xC000A123,
+ MD_NTSTATUS_WIN_STATUS_GPIO_INVALID_REGISTRATION_PACKET = 0xC000A124,
+ MD_NTSTATUS_WIN_STATUS_GPIO_OPERATION_DENIED = 0xC000A125,
+ MD_NTSTATUS_WIN_STATUS_GPIO_INCOMPATIBLE_CONNECT_MODE = 0xC000A126,
+ MD_NTSTATUS_WIN_STATUS_CANNOT_SWITCH_RUNLEVEL = 0xC000A141,
+ MD_NTSTATUS_WIN_STATUS_INVALID_RUNLEVEL_SETTING = 0xC000A142,
+ MD_NTSTATUS_WIN_STATUS_RUNLEVEL_SWITCH_TIMEOUT = 0xC000A143,
+ MD_NTSTATUS_WIN_STATUS_RUNLEVEL_SWITCH_AGENT_TIMEOUT = 0xC000A145,
+ MD_NTSTATUS_WIN_STATUS_RUNLEVEL_SWITCH_IN_PROGRESS = 0xC000A146,
+ MD_NTSTATUS_WIN_STATUS_NOT_APPCONTAINER = 0xC000A200,
+ MD_NTSTATUS_WIN_STATUS_NOT_SUPPORTED_IN_APPCONTAINER = 0xC000A201,
+ MD_NTSTATUS_WIN_STATUS_INVALID_PACKAGE_SID_LENGTH = 0xC000A202,
+ MD_NTSTATUS_WIN_STATUS_LPAC_ACCESS_DENIED = 0xC000A203,
+ MD_NTSTATUS_WIN_STATUS_ADMINLESS_ACCESS_DENIED = 0xC000A204,
+ MD_NTSTATUS_WIN_STATUS_APP_DATA_NOT_FOUND = 0xC000A281,
+ MD_NTSTATUS_WIN_STATUS_APP_DATA_EXPIRED = 0xC000A282,
+ MD_NTSTATUS_WIN_STATUS_APP_DATA_CORRUPT = 0xC000A283,
+ MD_NTSTATUS_WIN_STATUS_APP_DATA_LIMIT_EXCEEDED = 0xC000A284,
+ MD_NTSTATUS_WIN_STATUS_APP_DATA_REBOOT_REQUIRED = 0xC000A285,
+ MD_NTSTATUS_WIN_STATUS_OFFLOAD_READ_FLT_NOT_SUPPORTED = 0xC000A2A1,
+ MD_NTSTATUS_WIN_STATUS_OFFLOAD_WRITE_FLT_NOT_SUPPORTED = 0xC000A2A2,
+ MD_NTSTATUS_WIN_STATUS_OFFLOAD_READ_FILE_NOT_SUPPORTED = 0xC000A2A3,
+ MD_NTSTATUS_WIN_STATUS_OFFLOAD_WRITE_FILE_NOT_SUPPORTED = 0xC000A2A4,
+ MD_NTSTATUS_WIN_STATUS_WOF_WIM_HEADER_CORRUPT = 0xC000A2A5,
+ MD_NTSTATUS_WIN_STATUS_WOF_WIM_RESOURCE_TABLE_CORRUPT = 0xC000A2A6,
+ MD_NTSTATUS_WIN_STATUS_WOF_FILE_RESOURCE_TABLE_CORRUPT = 0xC000A2A7,
+ MD_NTSTATUS_WIN_STATUS_CIMFS_IMAGE_CORRUPT = 0xC000C001,
+ MD_NTSTATUS_WIN_STATUS_FILE_SYSTEM_VIRTUALIZATION_UNAVAILABLE = 0xC000CE01,
+ MD_NTSTATUS_WIN_STATUS_FILE_SYSTEM_VIRTUALIZATION_METADATA_CORRUPT = 0xC000CE02,
+ MD_NTSTATUS_WIN_STATUS_FILE_SYSTEM_VIRTUALIZATION_BUSY = 0xC000CE03,
+ MD_NTSTATUS_WIN_STATUS_FILE_SYSTEM_VIRTUALIZATION_PROVIDER_UNKNOWN = 0xC000CE04,
+ MD_NTSTATUS_WIN_STATUS_FILE_SYSTEM_VIRTUALIZATION_INVALID_OPERATION = 0xC000CE05,
+ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_SYNC_ROOT_METADATA_CORRUPT = 0xC000CF00,
+ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_PROVIDER_NOT_RUNNING = 0xC000CF01,
+ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_METADATA_CORRUPT = 0xC000CF02,
+ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_METADATA_TOO_LARGE = 0xC000CF03,
+ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_PROPERTY_VERSION_NOT_SUPPORTED = 0xC000CF06,
+ MD_NTSTATUS_WIN_STATUS_NOT_A_CLOUD_FILE = 0xC000CF07,
+ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_NOT_IN_SYNC = 0xC000CF08,
+ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_ALREADY_CONNECTED = 0xC000CF09,
+ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_NOT_SUPPORTED = 0xC000CF0A,
+ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_INVALID_REQUEST = 0xC000CF0B,
+ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_READ_ONLY_VOLUME = 0xC000CF0C,
+ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_CONNECTED_PROVIDER_ONLY = 0xC000CF0D,
+ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_VALIDATION_FAILED = 0xC000CF0E,
+ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_AUTHENTICATION_FAILED = 0xC000CF0F,
+ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_INSUFFICIENT_RESOURCES = 0xC000CF10,
+ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_NETWORK_UNAVAILABLE = 0xC000CF11,
+ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_UNSUCCESSFUL = 0xC000CF12,
+ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_NOT_UNDER_SYNC_ROOT = 0xC000CF13,
+ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_IN_USE = 0xC000CF14,
+ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_PINNED = 0xC000CF15,
+ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_REQUEST_ABORTED = 0xC000CF16,
+ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_PROPERTY_CORRUPT = 0xC000CF17,
+ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_ACCESS_DENIED = 0xC000CF18,
+ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_INCOMPATIBLE_HARDLINKS = 0xC000CF19,
+ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_PROPERTY_LOCK_CONFLICT = 0xC000CF1A,
+ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_REQUEST_CANCELED = 0xC000CF1B,
+ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_PROVIDER_TERMINATED = 0xC000CF1D,
+ MD_NTSTATUS_WIN_STATUS_NOT_A_CLOUD_SYNC_ROOT = 0xC000CF1E,
+ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_REQUEST_TIMEOUT = 0xC000CF1F,
+ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_DEHYDRATION_DISALLOWED = 0xC000CF20,
+ MD_NTSTATUS_WIN_STATUS_FILE_SNAP_IN_PROGRESS = 0xC000F500,
+ MD_NTSTATUS_WIN_STATUS_FILE_SNAP_USER_SECTION_NOT_SUPPORTED = 0xC000F501,
+ MD_NTSTATUS_WIN_STATUS_FILE_SNAP_MODIFY_NOT_SUPPORTED = 0xC000F502,
+ MD_NTSTATUS_WIN_STATUS_FILE_SNAP_IO_NOT_COORDINATED = 0xC000F503,
+ MD_NTSTATUS_WIN_STATUS_FILE_SNAP_UNEXPECTED_ERROR = 0xC000F504,
+ MD_NTSTATUS_WIN_STATUS_FILE_SNAP_INVALID_PARAMETER = 0xC000F505,
+ MD_NTSTATUS_WIN_DBG_NO_STATE_CHANGE = 0xC0010001,
+ MD_NTSTATUS_WIN_DBG_APP_NOT_IDLE = 0xC0010002,
+ MD_NTSTATUS_WIN_RPC_NT_INVALID_STRING_BINDING = 0xC0020001,
+ MD_NTSTATUS_WIN_RPC_NT_WRONG_KIND_OF_BINDING = 0xC0020002,
+ MD_NTSTATUS_WIN_RPC_NT_INVALID_BINDING = 0xC0020003,
+ MD_NTSTATUS_WIN_RPC_NT_PROTSEQ_NOT_SUPPORTED = 0xC0020004,
+ MD_NTSTATUS_WIN_RPC_NT_INVALID_RPC_PROTSEQ = 0xC0020005,
+ MD_NTSTATUS_WIN_RPC_NT_INVALID_STRING_UUID = 0xC0020006,
+ MD_NTSTATUS_WIN_RPC_NT_INVALID_ENDPOINT_FORMAT = 0xC0020007,
+ MD_NTSTATUS_WIN_RPC_NT_INVALID_NET_ADDR = 0xC0020008,
+ MD_NTSTATUS_WIN_RPC_NT_NO_ENDPOINT_FOUND = 0xC0020009,
+ MD_NTSTATUS_WIN_RPC_NT_INVALID_TIMEOUT = 0xC002000A,
+ MD_NTSTATUS_WIN_RPC_NT_OBJECT_NOT_FOUND = 0xC002000B,
+ MD_NTSTATUS_WIN_RPC_NT_ALREADY_REGISTERED = 0xC002000C,
+ MD_NTSTATUS_WIN_RPC_NT_TYPE_ALREADY_REGISTERED = 0xC002000D,
+ MD_NTSTATUS_WIN_RPC_NT_ALREADY_LISTENING = 0xC002000E,
+ MD_NTSTATUS_WIN_RPC_NT_NO_PROTSEQS_REGISTERED = 0xC002000F,
+ MD_NTSTATUS_WIN_RPC_NT_NOT_LISTENING = 0xC0020010,
+ MD_NTSTATUS_WIN_RPC_NT_UNKNOWN_MGR_TYPE = 0xC0020011,
+ MD_NTSTATUS_WIN_RPC_NT_UNKNOWN_IF = 0xC0020012,
+ MD_NTSTATUS_WIN_RPC_NT_NO_BINDINGS = 0xC0020013,
+ MD_NTSTATUS_WIN_RPC_NT_NO_PROTSEQS = 0xC0020014,
+ MD_NTSTATUS_WIN_RPC_NT_CANT_CREATE_ENDPOINT = 0xC0020015,
+ MD_NTSTATUS_WIN_RPC_NT_OUT_OF_RESOURCES = 0xC0020016,
+ MD_NTSTATUS_WIN_RPC_NT_SERVER_UNAVAILABLE = 0xC0020017,
+ MD_NTSTATUS_WIN_RPC_NT_SERVER_TOO_BUSY = 0xC0020018,
+ MD_NTSTATUS_WIN_RPC_NT_INVALID_NETWORK_OPTIONS = 0xC0020019,
+ MD_NTSTATUS_WIN_RPC_NT_NO_CALL_ACTIVE = 0xC002001A,
+ MD_NTSTATUS_WIN_RPC_NT_CALL_FAILED = 0xC002001B,
+ MD_NTSTATUS_WIN_RPC_NT_CALL_FAILED_DNE = 0xC002001C,
+ MD_NTSTATUS_WIN_RPC_NT_PROTOCOL_ERROR = 0xC002001D,
+ MD_NTSTATUS_WIN_RPC_NT_UNSUPPORTED_TRANS_SYN = 0xC002001F,
+ MD_NTSTATUS_WIN_RPC_NT_UNSUPPORTED_TYPE = 0xC0020021,
+ MD_NTSTATUS_WIN_RPC_NT_INVALID_TAG = 0xC0020022,
+ MD_NTSTATUS_WIN_RPC_NT_INVALID_BOUND = 0xC0020023,
+ MD_NTSTATUS_WIN_RPC_NT_NO_ENTRY_NAME = 0xC0020024,
+ MD_NTSTATUS_WIN_RPC_NT_INVALID_NAME_SYNTAX = 0xC0020025,
+ MD_NTSTATUS_WIN_RPC_NT_UNSUPPORTED_NAME_SYNTAX = 0xC0020026,
+ MD_NTSTATUS_WIN_RPC_NT_UUID_NO_ADDRESS = 0xC0020028,
+ MD_NTSTATUS_WIN_RPC_NT_DUPLICATE_ENDPOINT = 0xC0020029,
+ MD_NTSTATUS_WIN_RPC_NT_UNKNOWN_AUTHN_TYPE = 0xC002002A,
+ MD_NTSTATUS_WIN_RPC_NT_MAX_CALLS_TOO_SMALL = 0xC002002B,
+ MD_NTSTATUS_WIN_RPC_NT_STRING_TOO_LONG = 0xC002002C,
+ MD_NTSTATUS_WIN_RPC_NT_PROTSEQ_NOT_FOUND = 0xC002002D,
+ MD_NTSTATUS_WIN_RPC_NT_PROCNUM_OUT_OF_RANGE = 0xC002002E,
+ MD_NTSTATUS_WIN_RPC_NT_BINDING_HAS_NO_AUTH = 0xC002002F,
+ MD_NTSTATUS_WIN_RPC_NT_UNKNOWN_AUTHN_SERVICE = 0xC0020030,
+ MD_NTSTATUS_WIN_RPC_NT_UNKNOWN_AUTHN_LEVEL = 0xC0020031,
+ MD_NTSTATUS_WIN_RPC_NT_INVALID_AUTH_IDENTITY = 0xC0020032,
+ MD_NTSTATUS_WIN_RPC_NT_UNKNOWN_AUTHZ_SERVICE = 0xC0020033,
+ MD_NTSTATUS_WIN_EPT_NT_INVALID_ENTRY = 0xC0020034,
+ MD_NTSTATUS_WIN_EPT_NT_CANT_PERFORM_OP = 0xC0020035,
+ MD_NTSTATUS_WIN_EPT_NT_NOT_REGISTERED = 0xC0020036,
+ MD_NTSTATUS_WIN_RPC_NT_NOTHING_TO_EXPORT = 0xC0020037,
+ MD_NTSTATUS_WIN_RPC_NT_INCOMPLETE_NAME = 0xC0020038,
+ MD_NTSTATUS_WIN_RPC_NT_INVALID_VERS_OPTION = 0xC0020039,
+ MD_NTSTATUS_WIN_RPC_NT_NO_MORE_MEMBERS = 0xC002003A,
+ MD_NTSTATUS_WIN_RPC_NT_NOT_ALL_OBJS_UNEXPORTED = 0xC002003B,
+ MD_NTSTATUS_WIN_RPC_NT_INTERFACE_NOT_FOUND = 0xC002003C,
+ MD_NTSTATUS_WIN_RPC_NT_ENTRY_ALREADY_EXISTS = 0xC002003D,
+ MD_NTSTATUS_WIN_RPC_NT_ENTRY_NOT_FOUND = 0xC002003E,
+ MD_NTSTATUS_WIN_RPC_NT_NAME_SERVICE_UNAVAILABLE = 0xC002003F,
+ MD_NTSTATUS_WIN_RPC_NT_INVALID_NAF_ID = 0xC0020040,
+ MD_NTSTATUS_WIN_RPC_NT_CANNOT_SUPPORT = 0xC0020041,
+ MD_NTSTATUS_WIN_RPC_NT_NO_CONTEXT_AVAILABLE = 0xC0020042,
+ MD_NTSTATUS_WIN_RPC_NT_INTERNAL_ERROR = 0xC0020043,
+ MD_NTSTATUS_WIN_RPC_NT_ZERO_DIVIDE = 0xC0020044,
+ MD_NTSTATUS_WIN_RPC_NT_ADDRESS_ERROR = 0xC0020045,
+ MD_NTSTATUS_WIN_RPC_NT_FP_DIV_ZERO = 0xC0020046,
+ MD_NTSTATUS_WIN_RPC_NT_FP_UNDERFLOW = 0xC0020047,
+ MD_NTSTATUS_WIN_RPC_NT_FP_OVERFLOW = 0xC0020048,
+ MD_NTSTATUS_WIN_RPC_NT_CALL_IN_PROGRESS = 0xC0020049,
+ MD_NTSTATUS_WIN_RPC_NT_NO_MORE_BINDINGS = 0xC002004A,
+ MD_NTSTATUS_WIN_RPC_NT_GROUP_MEMBER_NOT_FOUND = 0xC002004B,
+ MD_NTSTATUS_WIN_EPT_NT_CANT_CREATE = 0xC002004C,
+ MD_NTSTATUS_WIN_RPC_NT_INVALID_OBJECT = 0xC002004D,
+ MD_NTSTATUS_WIN_RPC_NT_NO_INTERFACES = 0xC002004F,
+ MD_NTSTATUS_WIN_RPC_NT_CALL_CANCELLED = 0xC0020050,
+ MD_NTSTATUS_WIN_RPC_NT_BINDING_INCOMPLETE = 0xC0020051,
+ MD_NTSTATUS_WIN_RPC_NT_COMM_FAILURE = 0xC0020052,
+ MD_NTSTATUS_WIN_RPC_NT_UNSUPPORTED_AUTHN_LEVEL = 0xC0020053,
+ MD_NTSTATUS_WIN_RPC_NT_NO_PRINC_NAME = 0xC0020054,
+ MD_NTSTATUS_WIN_RPC_NT_NOT_RPC_ERROR = 0xC0020055,
+ MD_NTSTATUS_WIN_RPC_NT_SEC_PKG_ERROR = 0xC0020057,
+ MD_NTSTATUS_WIN_RPC_NT_NOT_CANCELLED = 0xC0020058,
+ MD_NTSTATUS_WIN_RPC_NT_INVALID_ASYNC_HANDLE = 0xC0020062,
+ MD_NTSTATUS_WIN_RPC_NT_INVALID_ASYNC_CALL = 0xC0020063,
+ MD_NTSTATUS_WIN_RPC_NT_PROXY_ACCESS_DENIED = 0xC0020064,
+ MD_NTSTATUS_WIN_RPC_NT_COOKIE_AUTH_FAILED = 0xC0020065,
+ MD_NTSTATUS_WIN_RPC_NT_NO_MORE_ENTRIES = 0xC0030001,
+ MD_NTSTATUS_WIN_RPC_NT_SS_CHAR_TRANS_OPEN_FAIL = 0xC0030002,
+ MD_NTSTATUS_WIN_RPC_NT_SS_CHAR_TRANS_SHORT_FILE = 0xC0030003,
+ MD_NTSTATUS_WIN_RPC_NT_SS_IN_NULL_CONTEXT = 0xC0030004,
+ MD_NTSTATUS_WIN_RPC_NT_SS_CONTEXT_MISMATCH = 0xC0030005,
+ MD_NTSTATUS_WIN_RPC_NT_SS_CONTEXT_DAMAGED = 0xC0030006,
+ MD_NTSTATUS_WIN_RPC_NT_SS_HANDLES_MISMATCH = 0xC0030007,
+ MD_NTSTATUS_WIN_RPC_NT_SS_CANNOT_GET_CALL_HANDLE = 0xC0030008,
+ MD_NTSTATUS_WIN_RPC_NT_NULL_REF_POINTER = 0xC0030009,
+ MD_NTSTATUS_WIN_RPC_NT_ENUM_VALUE_OUT_OF_RANGE = 0xC003000A,
+ MD_NTSTATUS_WIN_RPC_NT_BYTE_COUNT_TOO_SMALL = 0xC003000B,
+ MD_NTSTATUS_WIN_RPC_NT_BAD_STUB_DATA = 0xC003000C,
+ MD_NTSTATUS_WIN_RPC_NT_INVALID_ES_ACTION = 0xC0030059,
+ MD_NTSTATUS_WIN_RPC_NT_WRONG_ES_VERSION = 0xC003005A,
+ MD_NTSTATUS_WIN_RPC_NT_WRONG_STUB_VERSION = 0xC003005B,
+ MD_NTSTATUS_WIN_RPC_NT_INVALID_PIPE_OBJECT = 0xC003005C,
+ MD_NTSTATUS_WIN_RPC_NT_INVALID_PIPE_OPERATION = 0xC003005D,
+ MD_NTSTATUS_WIN_RPC_NT_WRONG_PIPE_VERSION = 0xC003005E,
+ MD_NTSTATUS_WIN_RPC_NT_PIPE_CLOSED = 0xC003005F,
+ MD_NTSTATUS_WIN_RPC_NT_PIPE_DISCIPLINE_ERROR = 0xC0030060,
+ MD_NTSTATUS_WIN_RPC_NT_PIPE_EMPTY = 0xC0030061,
+ MD_NTSTATUS_WIN_STATUS_PNP_BAD_MPS_TABLE = 0xC0040035,
+ MD_NTSTATUS_WIN_STATUS_PNP_TRANSLATION_FAILED = 0xC0040036,
+ MD_NTSTATUS_WIN_STATUS_PNP_IRQ_TRANSLATION_FAILED = 0xC0040037,
+ MD_NTSTATUS_WIN_STATUS_PNP_INVALID_ID = 0xC0040038,
+ MD_NTSTATUS_WIN_STATUS_IO_REISSUE_AS_CACHED = 0xC0040039,
+ MD_NTSTATUS_WIN_STATUS_CTX_WINSTATION_NAME_INVALID = 0xC00A0001,
+ MD_NTSTATUS_WIN_STATUS_CTX_INVALID_PD = 0xC00A0002,
+ MD_NTSTATUS_WIN_STATUS_CTX_PD_NOT_FOUND = 0xC00A0003,
+ MD_NTSTATUS_WIN_STATUS_CTX_CLOSE_PENDING = 0xC00A0006,
+ MD_NTSTATUS_WIN_STATUS_CTX_NO_OUTBUF = 0xC00A0007,
+ MD_NTSTATUS_WIN_STATUS_CTX_MODEM_INF_NOT_FOUND = 0xC00A0008,
+ MD_NTSTATUS_WIN_STATUS_CTX_INVALID_MODEMNAME = 0xC00A0009,
+ MD_NTSTATUS_WIN_STATUS_CTX_RESPONSE_ERROR = 0xC00A000A,
+ MD_NTSTATUS_WIN_STATUS_CTX_MODEM_RESPONSE_TIMEOUT = 0xC00A000B,
+ MD_NTSTATUS_WIN_STATUS_CTX_MODEM_RESPONSE_NO_CARRIER = 0xC00A000C,
+ MD_NTSTATUS_WIN_STATUS_CTX_MODEM_RESPONSE_NO_DIALTONE = 0xC00A000D,
+ MD_NTSTATUS_WIN_STATUS_CTX_MODEM_RESPONSE_BUSY = 0xC00A000E,
+ MD_NTSTATUS_WIN_STATUS_CTX_MODEM_RESPONSE_VOICE = 0xC00A000F,
+ MD_NTSTATUS_WIN_STATUS_CTX_TD_ERROR = 0xC00A0010,
+ MD_NTSTATUS_WIN_STATUS_CTX_LICENSE_CLIENT_INVALID = 0xC00A0012,
+ MD_NTSTATUS_WIN_STATUS_CTX_LICENSE_NOT_AVAILABLE = 0xC00A0013,
+ MD_NTSTATUS_WIN_STATUS_CTX_LICENSE_EXPIRED = 0xC00A0014,
+ MD_NTSTATUS_WIN_STATUS_CTX_WINSTATION_NOT_FOUND = 0xC00A0015,
+ MD_NTSTATUS_WIN_STATUS_CTX_WINSTATION_NAME_COLLISION = 0xC00A0016,
+ MD_NTSTATUS_WIN_STATUS_CTX_WINSTATION_BUSY = 0xC00A0017,
+ MD_NTSTATUS_WIN_STATUS_CTX_BAD_VIDEO_MODE = 0xC00A0018,
+ MD_NTSTATUS_WIN_STATUS_CTX_GRAPHICS_INVALID = 0xC00A0022,
+ MD_NTSTATUS_WIN_STATUS_CTX_NOT_CONSOLE = 0xC00A0024,
+ MD_NTSTATUS_WIN_STATUS_CTX_CLIENT_QUERY_TIMEOUT = 0xC00A0026,
+ MD_NTSTATUS_WIN_STATUS_CTX_CONSOLE_DISCONNECT = 0xC00A0027,
+ MD_NTSTATUS_WIN_STATUS_CTX_CONSOLE_CONNECT = 0xC00A0028,
+ MD_NTSTATUS_WIN_STATUS_CTX_SHADOW_DENIED = 0xC00A002A,
+ MD_NTSTATUS_WIN_STATUS_CTX_WINSTATION_ACCESS_DENIED = 0xC00A002B,
+ MD_NTSTATUS_WIN_STATUS_CTX_INVALID_WD = 0xC00A002E,
+ MD_NTSTATUS_WIN_STATUS_CTX_WD_NOT_FOUND = 0xC00A002F,
+ MD_NTSTATUS_WIN_STATUS_CTX_SHADOW_INVALID = 0xC00A0030,
+ MD_NTSTATUS_WIN_STATUS_CTX_SHADOW_DISABLED = 0xC00A0031,
+ MD_NTSTATUS_WIN_STATUS_RDP_PROTOCOL_ERROR = 0xC00A0032,
+ MD_NTSTATUS_WIN_STATUS_CTX_CLIENT_LICENSE_NOT_SET = 0xC00A0033,
+ MD_NTSTATUS_WIN_STATUS_CTX_CLIENT_LICENSE_IN_USE = 0xC00A0034,
+ MD_NTSTATUS_WIN_STATUS_CTX_SHADOW_ENDED_BY_MODE_CHANGE = 0xC00A0035,
+ MD_NTSTATUS_WIN_STATUS_CTX_SHADOW_NOT_RUNNING = 0xC00A0036,
+ MD_NTSTATUS_WIN_STATUS_CTX_LOGON_DISABLED = 0xC00A0037,
+ MD_NTSTATUS_WIN_STATUS_CTX_SECURITY_LAYER_ERROR = 0xC00A0038,
+ MD_NTSTATUS_WIN_STATUS_TS_INCOMPATIBLE_SESSIONS = 0xC00A0039,
+ MD_NTSTATUS_WIN_STATUS_TS_VIDEO_SUBSYSTEM_ERROR = 0xC00A003A,
+ MD_NTSTATUS_WIN_STATUS_MUI_FILE_NOT_FOUND = 0xC00B0001,
+ MD_NTSTATUS_WIN_STATUS_MUI_INVALID_FILE = 0xC00B0002,
+ MD_NTSTATUS_WIN_STATUS_MUI_INVALID_RC_CONFIG = 0xC00B0003,
+ MD_NTSTATUS_WIN_STATUS_MUI_INVALID_LOCALE_NAME = 0xC00B0004,
+ MD_NTSTATUS_WIN_STATUS_MUI_INVALID_ULTIMATEFALLBACK_NAME = 0xC00B0005,
+ MD_NTSTATUS_WIN_STATUS_MUI_FILE_NOT_LOADED = 0xC00B0006,
+ MD_NTSTATUS_WIN_STATUS_RESOURCE_ENUM_USER_STOP = 0xC00B0007,
+ MD_NTSTATUS_WIN_STATUS_CLUSTER_INVALID_NODE = 0xC0130001,
+ MD_NTSTATUS_WIN_STATUS_CLUSTER_NODE_EXISTS = 0xC0130002,
+ MD_NTSTATUS_WIN_STATUS_CLUSTER_JOIN_IN_PROGRESS = 0xC0130003,
+ MD_NTSTATUS_WIN_STATUS_CLUSTER_NODE_NOT_FOUND = 0xC0130004,
+ MD_NTSTATUS_WIN_STATUS_CLUSTER_LOCAL_NODE_NOT_FOUND = 0xC0130005,
+ MD_NTSTATUS_WIN_STATUS_CLUSTER_NETWORK_EXISTS = 0xC0130006,
+ MD_NTSTATUS_WIN_STATUS_CLUSTER_NETWORK_NOT_FOUND = 0xC0130007,
+ MD_NTSTATUS_WIN_STATUS_CLUSTER_NETINTERFACE_EXISTS = 0xC0130008,
+ MD_NTSTATUS_WIN_STATUS_CLUSTER_NETINTERFACE_NOT_FOUND = 0xC0130009,
+ MD_NTSTATUS_WIN_STATUS_CLUSTER_INVALID_REQUEST = 0xC013000A,
+ MD_NTSTATUS_WIN_STATUS_CLUSTER_INVALID_NETWORK_PROVIDER = 0xC013000B,
+ MD_NTSTATUS_WIN_STATUS_CLUSTER_NODE_DOWN = 0xC013000C,
+ MD_NTSTATUS_WIN_STATUS_CLUSTER_NODE_UNREACHABLE = 0xC013000D,
+ MD_NTSTATUS_WIN_STATUS_CLUSTER_NODE_NOT_MEMBER = 0xC013000E,
+ MD_NTSTATUS_WIN_STATUS_CLUSTER_JOIN_NOT_IN_PROGRESS = 0xC013000F,
+ MD_NTSTATUS_WIN_STATUS_CLUSTER_INVALID_NETWORK = 0xC0130010,
+ MD_NTSTATUS_WIN_STATUS_CLUSTER_NO_NET_ADAPTERS = 0xC0130011,
+ MD_NTSTATUS_WIN_STATUS_CLUSTER_NODE_UP = 0xC0130012,
+ MD_NTSTATUS_WIN_STATUS_CLUSTER_NODE_PAUSED = 0xC0130013,
+ MD_NTSTATUS_WIN_STATUS_CLUSTER_NODE_NOT_PAUSED = 0xC0130014,
+ MD_NTSTATUS_WIN_STATUS_CLUSTER_NO_SECURITY_CONTEXT = 0xC0130015,
+ MD_NTSTATUS_WIN_STATUS_CLUSTER_NETWORK_NOT_INTERNAL = 0xC0130016,
+ MD_NTSTATUS_WIN_STATUS_CLUSTER_POISONED = 0xC0130017,
+ MD_NTSTATUS_WIN_STATUS_CLUSTER_NON_CSV_PATH = 0xC0130018,
+ MD_NTSTATUS_WIN_STATUS_CLUSTER_CSV_VOLUME_NOT_LOCAL = 0xC0130019,
+ MD_NTSTATUS_WIN_STATUS_CLUSTER_CSV_READ_OPLOCK_BREAK_IN_PROGRESS = 0xC0130020,
+ MD_NTSTATUS_WIN_STATUS_CLUSTER_CSV_AUTO_PAUSE_ERROR = 0xC0130021,
+ MD_NTSTATUS_WIN_STATUS_CLUSTER_CSV_REDIRECTED = 0xC0130022,
+ MD_NTSTATUS_WIN_STATUS_CLUSTER_CSV_NOT_REDIRECTED = 0xC0130023,
+ MD_NTSTATUS_WIN_STATUS_CLUSTER_CSV_VOLUME_DRAINING = 0xC0130024,
+ MD_NTSTATUS_WIN_STATUS_CLUSTER_CSV_SNAPSHOT_CREATION_IN_PROGRESS = 0xC0130025,
+ MD_NTSTATUS_WIN_STATUS_CLUSTER_CSV_VOLUME_DRAINING_SUCCEEDED_DOWNLEVEL = 0xC0130026,
+ MD_NTSTATUS_WIN_STATUS_CLUSTER_CSV_NO_SNAPSHOTS = 0xC0130027,
+ MD_NTSTATUS_WIN_STATUS_CSV_IO_PAUSE_TIMEOUT = 0xC0130028,
+ MD_NTSTATUS_WIN_STATUS_CLUSTER_CSV_INVALID_HANDLE = 0xC0130029,
+ MD_NTSTATUS_WIN_STATUS_CLUSTER_CSV_SUPPORTED_ONLY_ON_COORDINATOR = 0xC0130030,
+ MD_NTSTATUS_WIN_STATUS_CLUSTER_CAM_TICKET_REPLAY_DETECTED = 0xC0130031,
+ MD_NTSTATUS_WIN_STATUS_ACPI_INVALID_OPCODE = 0xC0140001,
+ MD_NTSTATUS_WIN_STATUS_ACPI_STACK_OVERFLOW = 0xC0140002,
+ MD_NTSTATUS_WIN_STATUS_ACPI_ASSERT_FAILED = 0xC0140003,
+ MD_NTSTATUS_WIN_STATUS_ACPI_INVALID_INDEX = 0xC0140004,
+ MD_NTSTATUS_WIN_STATUS_ACPI_INVALID_ARGUMENT = 0xC0140005,
+ MD_NTSTATUS_WIN_STATUS_ACPI_FATAL = 0xC0140006,
+ MD_NTSTATUS_WIN_STATUS_ACPI_INVALID_SUPERNAME = 0xC0140007,
+ MD_NTSTATUS_WIN_STATUS_ACPI_INVALID_ARGTYPE = 0xC0140008,
+ MD_NTSTATUS_WIN_STATUS_ACPI_INVALID_OBJTYPE = 0xC0140009,
+ MD_NTSTATUS_WIN_STATUS_ACPI_INVALID_TARGETTYPE = 0xC014000A,
+ MD_NTSTATUS_WIN_STATUS_ACPI_INCORRECT_ARGUMENT_COUNT = 0xC014000B,
+ MD_NTSTATUS_WIN_STATUS_ACPI_ADDRESS_NOT_MAPPED = 0xC014000C,
+ MD_NTSTATUS_WIN_STATUS_ACPI_INVALID_EVENTTYPE = 0xC014000D,
+ MD_NTSTATUS_WIN_STATUS_ACPI_HANDLER_COLLISION = 0xC014000E,
+ MD_NTSTATUS_WIN_STATUS_ACPI_INVALID_DATA = 0xC014000F,
+ MD_NTSTATUS_WIN_STATUS_ACPI_INVALID_REGION = 0xC0140010,
+ MD_NTSTATUS_WIN_STATUS_ACPI_INVALID_ACCESS_SIZE = 0xC0140011,
+ MD_NTSTATUS_WIN_STATUS_ACPI_ACQUIRE_GLOBAL_LOCK = 0xC0140012,
+ MD_NTSTATUS_WIN_STATUS_ACPI_ALREADY_INITIALIZED = 0xC0140013,
+ MD_NTSTATUS_WIN_STATUS_ACPI_NOT_INITIALIZED = 0xC0140014,
+ MD_NTSTATUS_WIN_STATUS_ACPI_INVALID_MUTEX_LEVEL = 0xC0140015,
+ MD_NTSTATUS_WIN_STATUS_ACPI_MUTEX_NOT_OWNED = 0xC0140016,
+ MD_NTSTATUS_WIN_STATUS_ACPI_MUTEX_NOT_OWNER = 0xC0140017,
+ MD_NTSTATUS_WIN_STATUS_ACPI_RS_ACCESS = 0xC0140018,
+ MD_NTSTATUS_WIN_STATUS_ACPI_INVALID_TABLE = 0xC0140019,
+ MD_NTSTATUS_WIN_STATUS_ACPI_REG_HANDLER_FAILED = 0xC0140020,
+ MD_NTSTATUS_WIN_STATUS_ACPI_POWER_REQUEST_FAILED = 0xC0140021,
+ MD_NTSTATUS_WIN_STATUS_SXS_SECTION_NOT_FOUND = 0xC0150001,
+ MD_NTSTATUS_WIN_STATUS_SXS_CANT_GEN_ACTCTX = 0xC0150002,
+ MD_NTSTATUS_WIN_STATUS_SXS_INVALID_ACTCTXDATA_FORMAT = 0xC0150003,
+ MD_NTSTATUS_WIN_STATUS_SXS_ASSEMBLY_NOT_FOUND = 0xC0150004,
+ MD_NTSTATUS_WIN_STATUS_SXS_MANIFEST_FORMAT_ERROR = 0xC0150005,
+ MD_NTSTATUS_WIN_STATUS_SXS_MANIFEST_PARSE_ERROR = 0xC0150006,
+ MD_NTSTATUS_WIN_STATUS_SXS_ACTIVATION_CONTEXT_DISABLED = 0xC0150007,
+ MD_NTSTATUS_WIN_STATUS_SXS_KEY_NOT_FOUND = 0xC0150008,
+ MD_NTSTATUS_WIN_STATUS_SXS_VERSION_CONFLICT = 0xC0150009,
+ MD_NTSTATUS_WIN_STATUS_SXS_WRONG_SECTION_TYPE = 0xC015000A,
+ MD_NTSTATUS_WIN_STATUS_SXS_THREAD_QUERIES_DISABLED = 0xC015000B,
+ MD_NTSTATUS_WIN_STATUS_SXS_ASSEMBLY_MISSING = 0xC015000C,
+ MD_NTSTATUS_WIN_STATUS_SXS_PROCESS_DEFAULT_ALREADY_SET = 0xC015000E,
+ MD_NTSTATUS_WIN_STATUS_SXS_EARLY_DEACTIVATION = 0xC015000F,
+ MD_NTSTATUS_WIN_STATUS_SXS_INVALID_DEACTIVATION = 0xC0150010,
+ MD_NTSTATUS_WIN_STATUS_SXS_MULTIPLE_DEACTIVATION = 0xC0150011,
+ MD_NTSTATUS_WIN_STATUS_SXS_SYSTEM_DEFAULT_ACTIVATION_CONTEXT_EMPTY = 0xC0150012,
+ MD_NTSTATUS_WIN_STATUS_SXS_PROCESS_TERMINATION_REQUESTED = 0xC0150013,
+ MD_NTSTATUS_WIN_STATUS_SXS_CORRUPT_ACTIVATION_STACK = 0xC0150014,
+ MD_NTSTATUS_WIN_STATUS_SXS_CORRUPTION = 0xC0150015,
+ MD_NTSTATUS_WIN_STATUS_SXS_INVALID_IDENTITY_ATTRIBUTE_VALUE = 0xC0150016,
+ MD_NTSTATUS_WIN_STATUS_SXS_INVALID_IDENTITY_ATTRIBUTE_NAME = 0xC0150017,
+ MD_NTSTATUS_WIN_STATUS_SXS_IDENTITY_DUPLICATE_ATTRIBUTE = 0xC0150018,
+ MD_NTSTATUS_WIN_STATUS_SXS_IDENTITY_PARSE_ERROR = 0xC0150019,
+ MD_NTSTATUS_WIN_STATUS_SXS_COMPONENT_STORE_CORRUPT = 0xC015001A,
+ MD_NTSTATUS_WIN_STATUS_SXS_FILE_HASH_MISMATCH = 0xC015001B,
+ MD_NTSTATUS_WIN_STATUS_SXS_MANIFEST_IDENTITY_SAME_BUT_CONTENTS_DIFFERENT = 0xC015001C,
+ MD_NTSTATUS_WIN_STATUS_SXS_IDENTITIES_DIFFERENT = 0xC015001D,
+ MD_NTSTATUS_WIN_STATUS_SXS_ASSEMBLY_IS_NOT_A_DEPLOYMENT = 0xC015001E,
+ MD_NTSTATUS_WIN_STATUS_SXS_FILE_NOT_PART_OF_ASSEMBLY = 0xC015001F,
+ MD_NTSTATUS_WIN_STATUS_ADVANCED_INSTALLER_FAILED = 0xC0150020,
+ MD_NTSTATUS_WIN_STATUS_XML_ENCODING_MISMATCH = 0xC0150021,
+ MD_NTSTATUS_WIN_STATUS_SXS_MANIFEST_TOO_BIG = 0xC0150022,
+ MD_NTSTATUS_WIN_STATUS_SXS_SETTING_NOT_REGISTERED = 0xC0150023,
+ MD_NTSTATUS_WIN_STATUS_SXS_TRANSACTION_CLOSURE_INCOMPLETE = 0xC0150024,
+ MD_NTSTATUS_WIN_STATUS_SMI_PRIMITIVE_INSTALLER_FAILED = 0xC0150025,
+ MD_NTSTATUS_WIN_STATUS_GENERIC_COMMAND_FAILED = 0xC0150026,
+ MD_NTSTATUS_WIN_STATUS_SXS_FILE_HASH_MISSING = 0xC0150027,
+ MD_NTSTATUS_WIN_STATUS_TRANSACTIONAL_CONFLICT = 0xC0190001,
+ MD_NTSTATUS_WIN_STATUS_INVALID_TRANSACTION = 0xC0190002,
+ MD_NTSTATUS_WIN_STATUS_TRANSACTION_NOT_ACTIVE = 0xC0190003,
+ MD_NTSTATUS_WIN_STATUS_TM_INITIALIZATION_FAILED = 0xC0190004,
+ MD_NTSTATUS_WIN_STATUS_RM_NOT_ACTIVE = 0xC0190005,
+ MD_NTSTATUS_WIN_STATUS_RM_METADATA_CORRUPT = 0xC0190006,
+ MD_NTSTATUS_WIN_STATUS_TRANSACTION_NOT_JOINED = 0xC0190007,
+ MD_NTSTATUS_WIN_STATUS_DIRECTORY_NOT_RM = 0xC0190008,
+ MD_NTSTATUS_WIN_STATUS_TRANSACTIONS_UNSUPPORTED_REMOTE = 0xC019000A,
+ MD_NTSTATUS_WIN_STATUS_LOG_RESIZE_INVALID_SIZE = 0xC019000B,
+ MD_NTSTATUS_WIN_STATUS_REMOTE_FILE_VERSION_MISMATCH = 0xC019000C,
+ MD_NTSTATUS_WIN_STATUS_CRM_PROTOCOL_ALREADY_EXISTS = 0xC019000F,
+ MD_NTSTATUS_WIN_STATUS_TRANSACTION_PROPAGATION_FAILED = 0xC0190010,
+ MD_NTSTATUS_WIN_STATUS_CRM_PROTOCOL_NOT_FOUND = 0xC0190011,
+ MD_NTSTATUS_WIN_STATUS_TRANSACTION_SUPERIOR_EXISTS = 0xC0190012,
+ MD_NTSTATUS_WIN_STATUS_TRANSACTION_REQUEST_NOT_VALID = 0xC0190013,
+ MD_NTSTATUS_WIN_STATUS_TRANSACTION_NOT_REQUESTED = 0xC0190014,
+ MD_NTSTATUS_WIN_STATUS_TRANSACTION_ALREADY_ABORTED = 0xC0190015,
+ MD_NTSTATUS_WIN_STATUS_TRANSACTION_ALREADY_COMMITTED = 0xC0190016,
+ MD_NTSTATUS_WIN_STATUS_TRANSACTION_INVALID_MARSHALL_BUFFER = 0xC0190017,
+ MD_NTSTATUS_WIN_STATUS_CURRENT_TRANSACTION_NOT_VALID = 0xC0190018,
+ MD_NTSTATUS_WIN_STATUS_LOG_GROWTH_FAILED = 0xC0190019,
+ MD_NTSTATUS_WIN_STATUS_OBJECT_NO_LONGER_EXISTS = 0xC0190021,
+ MD_NTSTATUS_WIN_STATUS_STREAM_MINIVERSION_NOT_FOUND = 0xC0190022,
+ MD_NTSTATUS_WIN_STATUS_STREAM_MINIVERSION_NOT_VALID = 0xC0190023,
+ MD_NTSTATUS_WIN_STATUS_MINIVERSION_INACCESSIBLE_FROM_SPECIFIED_TRANSACTION = 0xC0190024,
+ MD_NTSTATUS_WIN_STATUS_CANT_OPEN_MINIVERSION_WITH_MODIFY_INTENT = 0xC0190025,
+ MD_NTSTATUS_WIN_STATUS_CANT_CREATE_MORE_STREAM_MINIVERSIONS = 0xC0190026,
+ MD_NTSTATUS_WIN_STATUS_HANDLE_NO_LONGER_VALID = 0xC0190028,
+ MD_NTSTATUS_WIN_STATUS_LOG_CORRUPTION_DETECTED = 0xC0190030,
+ MD_NTSTATUS_WIN_STATUS_RM_DISCONNECTED = 0xC0190032,
+ MD_NTSTATUS_WIN_STATUS_ENLISTMENT_NOT_SUPERIOR = 0xC0190033,
+ MD_NTSTATUS_WIN_STATUS_FILE_IDENTITY_NOT_PERSISTENT = 0xC0190036,
+ MD_NTSTATUS_WIN_STATUS_CANT_BREAK_TRANSACTIONAL_DEPENDENCY = 0xC0190037,
+ MD_NTSTATUS_WIN_STATUS_CANT_CROSS_RM_BOUNDARY = 0xC0190038,
+ MD_NTSTATUS_WIN_STATUS_TXF_DIR_NOT_EMPTY = 0xC0190039,
+ MD_NTSTATUS_WIN_STATUS_INDOUBT_TRANSACTIONS_EXIST = 0xC019003A,
+ MD_NTSTATUS_WIN_STATUS_TM_VOLATILE = 0xC019003B,
+ MD_NTSTATUS_WIN_STATUS_ROLLBACK_TIMER_EXPIRED = 0xC019003C,
+ MD_NTSTATUS_WIN_STATUS_TXF_ATTRIBUTE_CORRUPT = 0xC019003D,
+ MD_NTSTATUS_WIN_STATUS_EFS_NOT_ALLOWED_IN_TRANSACTION = 0xC019003E,
+ MD_NTSTATUS_WIN_STATUS_TRANSACTIONAL_OPEN_NOT_ALLOWED = 0xC019003F,
+ MD_NTSTATUS_WIN_STATUS_TRANSACTED_MAPPING_UNSUPPORTED_REMOTE = 0xC0190040,
+ MD_NTSTATUS_WIN_STATUS_TRANSACTION_REQUIRED_PROMOTION = 0xC0190043,
+ MD_NTSTATUS_WIN_STATUS_CANNOT_EXECUTE_FILE_IN_TRANSACTION = 0xC0190044,
+ MD_NTSTATUS_WIN_STATUS_TRANSACTIONS_NOT_FROZEN = 0xC0190045,
+ MD_NTSTATUS_WIN_STATUS_TRANSACTION_FREEZE_IN_PROGRESS = 0xC0190046,
+ MD_NTSTATUS_WIN_STATUS_NOT_SNAPSHOT_VOLUME = 0xC0190047,
+ MD_NTSTATUS_WIN_STATUS_NO_SAVEPOINT_WITH_OPEN_FILES = 0xC0190048,
+ MD_NTSTATUS_WIN_STATUS_SPARSE_NOT_ALLOWED_IN_TRANSACTION = 0xC0190049,
+ MD_NTSTATUS_WIN_STATUS_TM_IDENTITY_MISMATCH = 0xC019004A,
+ MD_NTSTATUS_WIN_STATUS_FLOATED_SECTION = 0xC019004B,
+ MD_NTSTATUS_WIN_STATUS_CANNOT_ACCEPT_TRANSACTED_WORK = 0xC019004C,
+ MD_NTSTATUS_WIN_STATUS_CANNOT_ABORT_TRANSACTIONS = 0xC019004D,
+ MD_NTSTATUS_WIN_STATUS_TRANSACTION_NOT_FOUND = 0xC019004E,
+ MD_NTSTATUS_WIN_STATUS_RESOURCEMANAGER_NOT_FOUND = 0xC019004F,
+ MD_NTSTATUS_WIN_STATUS_ENLISTMENT_NOT_FOUND = 0xC0190050,
+ MD_NTSTATUS_WIN_STATUS_TRANSACTIONMANAGER_NOT_FOUND = 0xC0190051,
+ MD_NTSTATUS_WIN_STATUS_TRANSACTIONMANAGER_NOT_ONLINE = 0xC0190052,
+ MD_NTSTATUS_WIN_STATUS_TRANSACTIONMANAGER_RECOVERY_NAME_COLLISION = 0xC0190053,
+ MD_NTSTATUS_WIN_STATUS_TRANSACTION_NOT_ROOT = 0xC0190054,
+ MD_NTSTATUS_WIN_STATUS_TRANSACTION_OBJECT_EXPIRED = 0xC0190055,
+ MD_NTSTATUS_WIN_STATUS_COMPRESSION_NOT_ALLOWED_IN_TRANSACTION = 0xC0190056,
+ MD_NTSTATUS_WIN_STATUS_TRANSACTION_RESPONSE_NOT_ENLISTED = 0xC0190057,
+ MD_NTSTATUS_WIN_STATUS_TRANSACTION_RECORD_TOO_LONG = 0xC0190058,
+ MD_NTSTATUS_WIN_STATUS_NO_LINK_TRACKING_IN_TRANSACTION = 0xC0190059,
+ MD_NTSTATUS_WIN_STATUS_OPERATION_NOT_SUPPORTED_IN_TRANSACTION = 0xC019005A,
+ MD_NTSTATUS_WIN_STATUS_TRANSACTION_INTEGRITY_VIOLATED = 0xC019005B,
+ MD_NTSTATUS_WIN_STATUS_TRANSACTIONMANAGER_IDENTITY_MISMATCH = 0xC019005C,
+ MD_NTSTATUS_WIN_STATUS_RM_CANNOT_BE_FROZEN_FOR_SNAPSHOT = 0xC019005D,
+ MD_NTSTATUS_WIN_STATUS_TRANSACTION_MUST_WRITETHROUGH = 0xC019005E,
+ MD_NTSTATUS_WIN_STATUS_TRANSACTION_NO_SUPERIOR = 0xC019005F,
+ MD_NTSTATUS_WIN_STATUS_EXPIRED_HANDLE = 0xC0190060,
+ MD_NTSTATUS_WIN_STATUS_TRANSACTION_NOT_ENLISTED = 0xC0190061,
+ MD_NTSTATUS_WIN_STATUS_LOG_SECTOR_INVALID = 0xC01A0001,
+ MD_NTSTATUS_WIN_STATUS_LOG_SECTOR_PARITY_INVALID = 0xC01A0002,
+ MD_NTSTATUS_WIN_STATUS_LOG_SECTOR_REMAPPED = 0xC01A0003,
+ MD_NTSTATUS_WIN_STATUS_LOG_BLOCK_INCOMPLETE = 0xC01A0004,
+ MD_NTSTATUS_WIN_STATUS_LOG_INVALID_RANGE = 0xC01A0005,
+ MD_NTSTATUS_WIN_STATUS_LOG_BLOCKS_EXHAUSTED = 0xC01A0006,
+ MD_NTSTATUS_WIN_STATUS_LOG_READ_CONTEXT_INVALID = 0xC01A0007,
+ MD_NTSTATUS_WIN_STATUS_LOG_RESTART_INVALID = 0xC01A0008,
+ MD_NTSTATUS_WIN_STATUS_LOG_BLOCK_VERSION = 0xC01A0009,
+ MD_NTSTATUS_WIN_STATUS_LOG_BLOCK_INVALID = 0xC01A000A,
+ MD_NTSTATUS_WIN_STATUS_LOG_READ_MODE_INVALID = 0xC01A000B,
+ MD_NTSTATUS_WIN_STATUS_LOG_METADATA_CORRUPT = 0xC01A000D,
+ MD_NTSTATUS_WIN_STATUS_LOG_METADATA_INVALID = 0xC01A000E,
+ MD_NTSTATUS_WIN_STATUS_LOG_METADATA_INCONSISTENT = 0xC01A000F,
+ MD_NTSTATUS_WIN_STATUS_LOG_RESERVATION_INVALID = 0xC01A0010,
+ MD_NTSTATUS_WIN_STATUS_LOG_CANT_DELETE = 0xC01A0011,
+ MD_NTSTATUS_WIN_STATUS_LOG_CONTAINER_LIMIT_EXCEEDED = 0xC01A0012,
+ MD_NTSTATUS_WIN_STATUS_LOG_START_OF_LOG = 0xC01A0013,
+ MD_NTSTATUS_WIN_STATUS_LOG_POLICY_ALREADY_INSTALLED = 0xC01A0014,
+ MD_NTSTATUS_WIN_STATUS_LOG_POLICY_NOT_INSTALLED = 0xC01A0015,
+ MD_NTSTATUS_WIN_STATUS_LOG_POLICY_INVALID = 0xC01A0016,
+ MD_NTSTATUS_WIN_STATUS_LOG_POLICY_CONFLICT = 0xC01A0017,
+ MD_NTSTATUS_WIN_STATUS_LOG_PINNED_ARCHIVE_TAIL = 0xC01A0018,
+ MD_NTSTATUS_WIN_STATUS_LOG_RECORD_NONEXISTENT = 0xC01A0019,
+ MD_NTSTATUS_WIN_STATUS_LOG_RECORDS_RESERVED_INVALID = 0xC01A001A,
+ MD_NTSTATUS_WIN_STATUS_LOG_SPACE_RESERVED_INVALID = 0xC01A001B,
+ MD_NTSTATUS_WIN_STATUS_LOG_TAIL_INVALID = 0xC01A001C,
+ MD_NTSTATUS_WIN_STATUS_LOG_FULL = 0xC01A001D,
+ MD_NTSTATUS_WIN_STATUS_LOG_MULTIPLEXED = 0xC01A001E,
+ MD_NTSTATUS_WIN_STATUS_LOG_DEDICATED = 0xC01A001F,
+ MD_NTSTATUS_WIN_STATUS_LOG_ARCHIVE_NOT_IN_PROGRESS = 0xC01A0020,
+ MD_NTSTATUS_WIN_STATUS_LOG_ARCHIVE_IN_PROGRESS = 0xC01A0021,
+ MD_NTSTATUS_WIN_STATUS_LOG_EPHEMERAL = 0xC01A0022,
+ MD_NTSTATUS_WIN_STATUS_LOG_NOT_ENOUGH_CONTAINERS = 0xC01A0023,
+ MD_NTSTATUS_WIN_STATUS_LOG_CLIENT_ALREADY_REGISTERED = 0xC01A0024,
+ MD_NTSTATUS_WIN_STATUS_LOG_CLIENT_NOT_REGISTERED = 0xC01A0025,
+ MD_NTSTATUS_WIN_STATUS_LOG_FULL_HANDLER_IN_PROGRESS = 0xC01A0026,
+ MD_NTSTATUS_WIN_STATUS_LOG_CONTAINER_READ_FAILED = 0xC01A0027,
+ MD_NTSTATUS_WIN_STATUS_LOG_CONTAINER_WRITE_FAILED = 0xC01A0028,
+ MD_NTSTATUS_WIN_STATUS_LOG_CONTAINER_OPEN_FAILED = 0xC01A0029,
+ MD_NTSTATUS_WIN_STATUS_LOG_CONTAINER_STATE_INVALID = 0xC01A002A,
+ MD_NTSTATUS_WIN_STATUS_LOG_STATE_INVALID = 0xC01A002B,
+ MD_NTSTATUS_WIN_STATUS_LOG_PINNED = 0xC01A002C,
+ MD_NTSTATUS_WIN_STATUS_LOG_METADATA_FLUSH_FAILED = 0xC01A002D,
+ MD_NTSTATUS_WIN_STATUS_LOG_INCONSISTENT_SECURITY = 0xC01A002E,
+ MD_NTSTATUS_WIN_STATUS_LOG_APPENDED_FLUSH_FAILED = 0xC01A002F,
+ MD_NTSTATUS_WIN_STATUS_LOG_PINNED_RESERVATION = 0xC01A0030,
+ MD_NTSTATUS_WIN_STATUS_VIDEO_HUNG_DISPLAY_DRIVER_THREAD = 0xC01B00EA,
+ MD_NTSTATUS_WIN_STATUS_FLT_NO_HANDLER_DEFINED = 0xC01C0001,
+ MD_NTSTATUS_WIN_STATUS_FLT_CONTEXT_ALREADY_DEFINED = 0xC01C0002,
+ MD_NTSTATUS_WIN_STATUS_FLT_INVALID_ASYNCHRONOUS_REQUEST = 0xC01C0003,
+ MD_NTSTATUS_WIN_STATUS_FLT_DISALLOW_FAST_IO = 0xC01C0004,
+ MD_NTSTATUS_WIN_STATUS_FLT_INVALID_NAME_REQUEST = 0xC01C0005,
+ MD_NTSTATUS_WIN_STATUS_FLT_NOT_SAFE_TO_POST_OPERATION = 0xC01C0006,
+ MD_NTSTATUS_WIN_STATUS_FLT_NOT_INITIALIZED = 0xC01C0007,
+ MD_NTSTATUS_WIN_STATUS_FLT_FILTER_NOT_READY = 0xC01C0008,
+ MD_NTSTATUS_WIN_STATUS_FLT_POST_OPERATION_CLEANUP = 0xC01C0009,
+ MD_NTSTATUS_WIN_STATUS_FLT_INTERNAL_ERROR = 0xC01C000A,
+ MD_NTSTATUS_WIN_STATUS_FLT_DELETING_OBJECT = 0xC01C000B,
+ MD_NTSTATUS_WIN_STATUS_FLT_MUST_BE_NONPAGED_POOL = 0xC01C000C,
+ MD_NTSTATUS_WIN_STATUS_FLT_DUPLICATE_ENTRY = 0xC01C000D,
+ MD_NTSTATUS_WIN_STATUS_FLT_CBDQ_DISABLED = 0xC01C000E,
+ MD_NTSTATUS_WIN_STATUS_FLT_DO_NOT_ATTACH = 0xC01C000F,
+ MD_NTSTATUS_WIN_STATUS_FLT_DO_NOT_DETACH = 0xC01C0010,
+ MD_NTSTATUS_WIN_STATUS_FLT_INSTANCE_ALTITUDE_COLLISION = 0xC01C0011,
+ MD_NTSTATUS_WIN_STATUS_FLT_INSTANCE_NAME_COLLISION = 0xC01C0012,
+ MD_NTSTATUS_WIN_STATUS_FLT_FILTER_NOT_FOUND = 0xC01C0013,
+ MD_NTSTATUS_WIN_STATUS_FLT_VOLUME_NOT_FOUND = 0xC01C0014,
+ MD_NTSTATUS_WIN_STATUS_FLT_INSTANCE_NOT_FOUND = 0xC01C0015,
+ MD_NTSTATUS_WIN_STATUS_FLT_CONTEXT_ALLOCATION_NOT_FOUND = 0xC01C0016,
+ MD_NTSTATUS_WIN_STATUS_FLT_INVALID_CONTEXT_REGISTRATION = 0xC01C0017,
+ MD_NTSTATUS_WIN_STATUS_FLT_NAME_CACHE_MISS = 0xC01C0018,
+ MD_NTSTATUS_WIN_STATUS_FLT_NO_DEVICE_OBJECT = 0xC01C0019,
+ MD_NTSTATUS_WIN_STATUS_FLT_VOLUME_ALREADY_MOUNTED = 0xC01C001A,
+ MD_NTSTATUS_WIN_STATUS_FLT_ALREADY_ENLISTED = 0xC01C001B,
+ MD_NTSTATUS_WIN_STATUS_FLT_CONTEXT_ALREADY_LINKED = 0xC01C001C,
+ MD_NTSTATUS_WIN_STATUS_FLT_NO_WAITER_FOR_REPLY = 0xC01C0020,
+ MD_NTSTATUS_WIN_STATUS_FLT_REGISTRATION_BUSY = 0xC01C0023,
+ MD_NTSTATUS_WIN_STATUS_MONITOR_NO_DESCRIPTOR = 0xC01D0001,
+ MD_NTSTATUS_WIN_STATUS_MONITOR_UNKNOWN_DESCRIPTOR_FORMAT = 0xC01D0002,
+ MD_NTSTATUS_WIN_STATUS_MONITOR_INVALID_DESCRIPTOR_CHECKSUM = 0xC01D0003,
+ MD_NTSTATUS_WIN_STATUS_MONITOR_INVALID_STANDARD_TIMING_BLOCK = 0xC01D0004,
+ MD_NTSTATUS_WIN_STATUS_MONITOR_WMI_DATABLOCK_REGISTRATION_FAILED = 0xC01D0005,
+ MD_NTSTATUS_WIN_STATUS_MONITOR_INVALID_SERIAL_NUMBER_MONDSC_BLOCK = 0xC01D0006,
+ MD_NTSTATUS_WIN_STATUS_MONITOR_INVALID_USER_FRIENDLY_MONDSC_BLOCK = 0xC01D0007,
+ MD_NTSTATUS_WIN_STATUS_MONITOR_NO_MORE_DESCRIPTOR_DATA = 0xC01D0008,
+ MD_NTSTATUS_WIN_STATUS_MONITOR_INVALID_DETAILED_TIMING_BLOCK = 0xC01D0009,
+ MD_NTSTATUS_WIN_STATUS_MONITOR_INVALID_MANUFACTURE_DATE = 0xC01D000A,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_NOT_EXCLUSIVE_MODE_OWNER = 0xC01E0000,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER = 0xC01E0001,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_DISPLAY_ADAPTER = 0xC01E0002,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_ADAPTER_WAS_RESET = 0xC01E0003,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_DRIVER_MODEL = 0xC01E0004,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_PRESENT_MODE_CHANGED = 0xC01E0005,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_PRESENT_OCCLUDED = 0xC01E0006,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_PRESENT_DENIED = 0xC01E0007,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_CANNOTCOLORCONVERT = 0xC01E0008,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_DRIVER_MISMATCH = 0xC01E0009,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_PRESENT_REDIRECTION_DISABLED = 0xC01E000B,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_PRESENT_UNOCCLUDED = 0xC01E000C,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_WINDOWDC_NOT_AVAILABLE = 0xC01E000D,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_WINDOWLESS_PRESENT_DISABLED = 0xC01E000E,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_PRESENT_INVALID_WINDOW = 0xC01E000F,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_PRESENT_BUFFER_NOT_BOUND = 0xC01E0010,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_VAIL_STATE_CHANGED = 0xC01E0011,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INDIRECT_DISPLAY_ABANDON_SWAPCHAIN = 0xC01E0012,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INDIRECT_DISPLAY_DEVICE_STOPPED = 0xC01E0013,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_NO_VIDEO_MEMORY = 0xC01E0100,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_CANT_LOCK_MEMORY = 0xC01E0101,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_ALLOCATION_BUSY = 0xC01E0102,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_TOO_MANY_REFERENCES = 0xC01E0103,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_TRY_AGAIN_LATER = 0xC01E0104,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_TRY_AGAIN_NOW = 0xC01E0105,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_ALLOCATION_INVALID = 0xC01E0106,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_UNSWIZZLING_APERTURE_UNAVAILABLE = 0xC01E0107,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_UNSWIZZLING_APERTURE_UNSUPPORTED = 0xC01E0108,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_CANT_EVICT_PINNED_ALLOCATION = 0xC01E0109,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_ALLOCATION_USAGE = 0xC01E0110,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_CANT_RENDER_LOCKED_ALLOCATION = 0xC01E0111,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_ALLOCATION_CLOSED = 0xC01E0112,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_ALLOCATION_INSTANCE = 0xC01E0113,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_ALLOCATION_HANDLE = 0xC01E0114,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_WRONG_ALLOCATION_DEVICE = 0xC01E0115,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_ALLOCATION_CONTENT_LOST = 0xC01E0116,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_GPU_EXCEPTION_ON_DEVICE = 0xC01E0200,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_VIDPN_TOPOLOGY = 0xC01E0300,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_VIDPN_TOPOLOGY_NOT_SUPPORTED = 0xC01E0301,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_VIDPN_TOPOLOGY_CURRENTLY_NOT_SUPPORTED = 0xC01E0302,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_VIDPN = 0xC01E0303,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_SOURCE = 0xC01E0304,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_TARGET = 0xC01E0305,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_VIDPN_MODALITY_NOT_SUPPORTED = 0xC01E0306,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_VIDPN_SOURCEMODESET = 0xC01E0308,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_VIDPN_TARGETMODESET = 0xC01E0309,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_FREQUENCY = 0xC01E030A,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_ACTIVE_REGION = 0xC01E030B,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_TOTAL_REGION = 0xC01E030C,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_SOURCE_MODE = 0xC01E0310,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_TARGET_MODE = 0xC01E0311,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_PINNED_MODE_MUST_REMAIN_IN_SET = 0xC01E0312,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_PATH_ALREADY_IN_TOPOLOGY = 0xC01E0313,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_MODE_ALREADY_IN_MODESET = 0xC01E0314,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_VIDEOPRESENTSOURCESET = 0xC01E0315,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_VIDEOPRESENTTARGETSET = 0xC01E0316,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_SOURCE_ALREADY_IN_SET = 0xC01E0317,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_TARGET_ALREADY_IN_SET = 0xC01E0318,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_VIDPN_PRESENT_PATH = 0xC01E0319,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_NO_RECOMMENDED_VIDPN_TOPOLOGY = 0xC01E031A,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_MONITOR_FREQUENCYRANGESET = 0xC01E031B,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_MONITOR_FREQUENCYRANGE = 0xC01E031C,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_FREQUENCYRANGE_NOT_IN_SET = 0xC01E031D,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_FREQUENCYRANGE_ALREADY_IN_SET = 0xC01E031F,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_STALE_MODESET = 0xC01E0320,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_MONITOR_SOURCEMODESET = 0xC01E0321,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_MONITOR_SOURCE_MODE = 0xC01E0322,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_NO_RECOMMENDED_FUNCTIONAL_VIDPN = 0xC01E0323,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_MODE_ID_MUST_BE_UNIQUE = 0xC01E0324,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_EMPTY_ADAPTER_MONITOR_MODE_SUPPORT_INTERSECTION = 0xC01E0325,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_VIDEO_PRESENT_TARGETS_LESS_THAN_SOURCES = 0xC01E0326,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_PATH_NOT_IN_TOPOLOGY = 0xC01E0327,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_ADAPTER_MUST_HAVE_AT_LEAST_ONE_SOURCE = 0xC01E0328,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_ADAPTER_MUST_HAVE_AT_LEAST_ONE_TARGET = 0xC01E0329,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_MONITORDESCRIPTORSET = 0xC01E032A,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_MONITORDESCRIPTOR = 0xC01E032B,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_MONITORDESCRIPTOR_NOT_IN_SET = 0xC01E032C,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_MONITORDESCRIPTOR_ALREADY_IN_SET = 0xC01E032D,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_MONITORDESCRIPTOR_ID_MUST_BE_UNIQUE = 0xC01E032E,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_VIDPN_TARGET_SUBSET_TYPE = 0xC01E032F,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_RESOURCES_NOT_RELATED = 0xC01E0330,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_SOURCE_ID_MUST_BE_UNIQUE = 0xC01E0331,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_TARGET_ID_MUST_BE_UNIQUE = 0xC01E0332,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_NO_AVAILABLE_VIDPN_TARGET = 0xC01E0333,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_MONITOR_COULD_NOT_BE_ASSOCIATED_WITH_ADAPTER = 0xC01E0334,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_NO_VIDPNMGR = 0xC01E0335,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_NO_ACTIVE_VIDPN = 0xC01E0336,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_STALE_VIDPN_TOPOLOGY = 0xC01E0337,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_MONITOR_NOT_CONNECTED = 0xC01E0338,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_SOURCE_NOT_IN_TOPOLOGY = 0xC01E0339,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_PRIMARYSURFACE_SIZE = 0xC01E033A,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_VISIBLEREGION_SIZE = 0xC01E033B,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_STRIDE = 0xC01E033C,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_PIXELFORMAT = 0xC01E033D,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_COLORBASIS = 0xC01E033E,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_PIXELVALUEACCESSMODE = 0xC01E033F,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_TARGET_NOT_IN_TOPOLOGY = 0xC01E0340,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_NO_DISPLAY_MODE_MANAGEMENT_SUPPORT = 0xC01E0341,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE = 0xC01E0342,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_CANT_ACCESS_ACTIVE_VIDPN = 0xC01E0343,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_PATH_IMPORTANCE_ORDINAL = 0xC01E0344,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_PATH_CONTENT_GEOMETRY_TRANSFORMATION = 0xC01E0345,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_PATH_CONTENT_GEOMETRY_TRANSFORMATION_NOT_SUPPORTED = 0xC01E0346,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_GAMMA_RAMP = 0xC01E0347,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_GAMMA_RAMP_NOT_SUPPORTED = 0xC01E0348,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_MULTISAMPLING_NOT_SUPPORTED = 0xC01E0349,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_MODE_NOT_IN_MODESET = 0xC01E034A,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_VIDPN_TOPOLOGY_RECOMMENDATION_REASON = 0xC01E034D,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_PATH_CONTENT_TYPE = 0xC01E034E,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_COPYPROTECTION_TYPE = 0xC01E034F,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_UNASSIGNED_MODESET_ALREADY_EXISTS = 0xC01E0350,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_SCANLINE_ORDERING = 0xC01E0352,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_TOPOLOGY_CHANGES_NOT_ALLOWED = 0xC01E0353,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_NO_AVAILABLE_IMPORTANCE_ORDINALS = 0xC01E0354,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INCOMPATIBLE_PRIVATE_FORMAT = 0xC01E0355,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_MODE_PRUNING_ALGORITHM = 0xC01E0356,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_MONITOR_CAPABILITY_ORIGIN = 0xC01E0357,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_MONITOR_FREQUENCYRANGE_CONSTRAINT = 0xC01E0358,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_MAX_NUM_PATHS_REACHED = 0xC01E0359,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_CANCEL_VIDPN_TOPOLOGY_AUGMENTATION = 0xC01E035A,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_CLIENT_TYPE = 0xC01E035B,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_CLIENTVIDPN_NOT_SET = 0xC01E035C,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_SPECIFIED_CHILD_ALREADY_CONNECTED = 0xC01E0400,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_CHILD_DESCRIPTOR_NOT_SUPPORTED = 0xC01E0401,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_NOT_A_LINKED_ADAPTER = 0xC01E0430,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_LEADLINK_NOT_ENUMERATED = 0xC01E0431,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_CHAINLINKS_NOT_ENUMERATED = 0xC01E0432,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_ADAPTER_CHAIN_NOT_READY = 0xC01E0433,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_CHAINLINKS_NOT_STARTED = 0xC01E0434,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_CHAINLINKS_NOT_POWERED_ON = 0xC01E0435,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INCONSISTENT_DEVICE_LINK_STATE = 0xC01E0436,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_NOT_POST_DEVICE_DRIVER = 0xC01E0438,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_ADAPTER_ACCESS_NOT_EXCLUDED = 0xC01E043B,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_NOT_SUPPORTED = 0xC01E0500,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_COPP_NOT_SUPPORTED = 0xC01E0501,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_UAB_NOT_SUPPORTED = 0xC01E0502,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_INVALID_ENCRYPTED_PARAMETERS = 0xC01E0503,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_NO_PROTECTED_OUTPUTS_EXIST = 0xC01E0505,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_INTERNAL_ERROR = 0xC01E050B,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_INVALID_HANDLE = 0xC01E050C,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_PVP_INVALID_CERTIFICATE_LENGTH = 0xC01E050E,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_SPANNING_MODE_ENABLED = 0xC01E050F,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_THEATER_MODE_ENABLED = 0xC01E0510,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_PVP_HFS_FAILED = 0xC01E0511,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_INVALID_SRM = 0xC01E0512,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_OUTPUT_DOES_NOT_SUPPORT_HDCP = 0xC01E0513,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_OUTPUT_DOES_NOT_SUPPORT_ACP = 0xC01E0514,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_OUTPUT_DOES_NOT_SUPPORT_CGMSA = 0xC01E0515,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_HDCP_SRM_NEVER_SET = 0xC01E0516,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_RESOLUTION_TOO_HIGH = 0xC01E0517,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_ALL_HDCP_HARDWARE_ALREADY_IN_USE = 0xC01E0518,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_PROTECTED_OUTPUT_NO_LONGER_EXISTS = 0xC01E051A,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_PROTECTED_OUTPUT_DOES_NOT_HAVE_COPP_SEMANTICS = 0xC01E051C,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_INVALID_INFORMATION_REQUEST = 0xC01E051D,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_DRIVER_INTERNAL_ERROR = 0xC01E051E,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_PROTECTED_OUTPUT_DOES_NOT_HAVE_OPM_SEMANTICS = 0xC01E051F,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_SIGNALING_NOT_SUPPORTED = 0xC01E0520,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_INVALID_CONFIGURATION_REQUEST = 0xC01E0521,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_I2C_NOT_SUPPORTED = 0xC01E0580,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_I2C_DEVICE_DOES_NOT_EXIST = 0xC01E0581,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_I2C_ERROR_TRANSMITTING_DATA = 0xC01E0582,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_I2C_ERROR_RECEIVING_DATA = 0xC01E0583,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_DDCCI_VCP_NOT_SUPPORTED = 0xC01E0584,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_DDCCI_INVALID_DATA = 0xC01E0585,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_DDCCI_MONITOR_RETURNED_INVALID_TIMING_STATUS_BYTE = 0xC01E0586,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_DDCCI_INVALID_CAPABILITIES_STRING = 0xC01E0587,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_MCA_INTERNAL_ERROR = 0xC01E0588,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_DDCCI_INVALID_MESSAGE_COMMAND = 0xC01E0589,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_DDCCI_INVALID_MESSAGE_LENGTH = 0xC01E058A,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_DDCCI_INVALID_MESSAGE_CHECKSUM = 0xC01E058B,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_PHYSICAL_MONITOR_HANDLE = 0xC01E058C,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_MONITOR_NO_LONGER_EXISTS = 0xC01E058D,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_ONLY_CONSOLE_SESSION_SUPPORTED = 0xC01E05E0,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_NO_DISPLAY_DEVICE_CORRESPONDS_TO_NAME = 0xC01E05E1,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_DISPLAY_DEVICE_NOT_ATTACHED_TO_DESKTOP = 0xC01E05E2,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_MIRRORING_DEVICES_NOT_SUPPORTED = 0xC01E05E3,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_POINTER = 0xC01E05E4,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_NO_MONITORS_CORRESPOND_TO_DISPLAY_DEVICE = 0xC01E05E5,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_PARAMETER_ARRAY_TOO_SMALL = 0xC01E05E6,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INTERNAL_ERROR = 0xC01E05E7,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_SESSION_TYPE_CHANGE_IN_PROGRESS = 0xC01E05E8,
+ MD_NTSTATUS_WIN_STATUS_FVE_LOCKED_VOLUME = 0xC0210000,
+ MD_NTSTATUS_WIN_STATUS_FVE_NOT_ENCRYPTED = 0xC0210001,
+ MD_NTSTATUS_WIN_STATUS_FVE_BAD_INFORMATION = 0xC0210002,
+ MD_NTSTATUS_WIN_STATUS_FVE_TOO_SMALL = 0xC0210003,
+ MD_NTSTATUS_WIN_STATUS_FVE_FAILED_WRONG_FS = 0xC0210004,
+ MD_NTSTATUS_WIN_STATUS_FVE_BAD_PARTITION_SIZE = 0xC0210005,
+ MD_NTSTATUS_WIN_STATUS_FVE_FS_NOT_EXTENDED = 0xC0210006,
+ MD_NTSTATUS_WIN_STATUS_FVE_FS_MOUNTED = 0xC0210007,
+ MD_NTSTATUS_WIN_STATUS_FVE_NO_LICENSE = 0xC0210008,
+ MD_NTSTATUS_WIN_STATUS_FVE_ACTION_NOT_ALLOWED = 0xC0210009,
+ MD_NTSTATUS_WIN_STATUS_FVE_BAD_DATA = 0xC021000A,
+ MD_NTSTATUS_WIN_STATUS_FVE_VOLUME_NOT_BOUND = 0xC021000B,
+ MD_NTSTATUS_WIN_STATUS_FVE_NOT_DATA_VOLUME = 0xC021000C,
+ MD_NTSTATUS_WIN_STATUS_FVE_CONV_READ_ERROR = 0xC021000D,
+ MD_NTSTATUS_WIN_STATUS_FVE_CONV_WRITE_ERROR = 0xC021000E,
+ MD_NTSTATUS_WIN_STATUS_FVE_OVERLAPPED_UPDATE = 0xC021000F,
+ MD_NTSTATUS_WIN_STATUS_FVE_FAILED_SECTOR_SIZE = 0xC0210010,
+ MD_NTSTATUS_WIN_STATUS_FVE_FAILED_AUTHENTICATION = 0xC0210011,
+ MD_NTSTATUS_WIN_STATUS_FVE_NOT_OS_VOLUME = 0xC0210012,
+ MD_NTSTATUS_WIN_STATUS_FVE_KEYFILE_NOT_FOUND = 0xC0210013,
+ MD_NTSTATUS_WIN_STATUS_FVE_KEYFILE_INVALID = 0xC0210014,
+ MD_NTSTATUS_WIN_STATUS_FVE_KEYFILE_NO_VMK = 0xC0210015,
+ MD_NTSTATUS_WIN_STATUS_FVE_TPM_DISABLED = 0xC0210016,
+ MD_NTSTATUS_WIN_STATUS_FVE_TPM_SRK_AUTH_NOT_ZERO = 0xC0210017,
+ MD_NTSTATUS_WIN_STATUS_FVE_TPM_INVALID_PCR = 0xC0210018,
+ MD_NTSTATUS_WIN_STATUS_FVE_TPM_NO_VMK = 0xC0210019,
+ MD_NTSTATUS_WIN_STATUS_FVE_PIN_INVALID = 0xC021001A,
+ MD_NTSTATUS_WIN_STATUS_FVE_AUTH_INVALID_APPLICATION = 0xC021001B,
+ MD_NTSTATUS_WIN_STATUS_FVE_AUTH_INVALID_CONFIG = 0xC021001C,
+ MD_NTSTATUS_WIN_STATUS_FVE_DEBUGGER_ENABLED = 0xC021001D,
+ MD_NTSTATUS_WIN_STATUS_FVE_DRY_RUN_FAILED = 0xC021001E,
+ MD_NTSTATUS_WIN_STATUS_FVE_BAD_METADATA_POINTER = 0xC021001F,
+ MD_NTSTATUS_WIN_STATUS_FVE_OLD_METADATA_COPY = 0xC0210020,
+ MD_NTSTATUS_WIN_STATUS_FVE_REBOOT_REQUIRED = 0xC0210021,
+ MD_NTSTATUS_WIN_STATUS_FVE_RAW_ACCESS = 0xC0210022,
+ MD_NTSTATUS_WIN_STATUS_FVE_RAW_BLOCKED = 0xC0210023,
+ MD_NTSTATUS_WIN_STATUS_FVE_NO_AUTOUNLOCK_MASTER_KEY = 0xC0210024,
+ MD_NTSTATUS_WIN_STATUS_FVE_MOR_FAILED = 0xC0210025,
+ MD_NTSTATUS_WIN_STATUS_FVE_NO_FEATURE_LICENSE = 0xC0210026,
+ MD_NTSTATUS_WIN_STATUS_FVE_POLICY_USER_DISABLE_RDV_NOT_ALLOWED = 0xC0210027,
+ MD_NTSTATUS_WIN_STATUS_FVE_CONV_RECOVERY_FAILED = 0xC0210028,
+ MD_NTSTATUS_WIN_STATUS_FVE_VIRTUALIZED_SPACE_TOO_BIG = 0xC0210029,
+ MD_NTSTATUS_WIN_STATUS_FVE_INVALID_DATUM_TYPE = 0xC021002A,
+ MD_NTSTATUS_WIN_STATUS_FVE_VOLUME_TOO_SMALL = 0xC0210030,
+ MD_NTSTATUS_WIN_STATUS_FVE_ENH_PIN_INVALID = 0xC0210031,
+ MD_NTSTATUS_WIN_STATUS_FVE_FULL_ENCRYPTION_NOT_ALLOWED_ON_TP_STORAGE = 0xC0210032,
+ MD_NTSTATUS_WIN_STATUS_FVE_WIPE_NOT_ALLOWED_ON_TP_STORAGE = 0xC0210033,
+ MD_NTSTATUS_WIN_STATUS_FVE_NOT_ALLOWED_ON_CSV_STACK = 0xC0210034,
+ MD_NTSTATUS_WIN_STATUS_FVE_NOT_ALLOWED_ON_CLUSTER = 0xC0210035,
+ MD_NTSTATUS_WIN_STATUS_FVE_NOT_ALLOWED_TO_UPGRADE_WHILE_CONVERTING = 0xC0210036,
+ MD_NTSTATUS_WIN_STATUS_FVE_WIPE_CANCEL_NOT_APPLICABLE = 0xC0210037,
+ MD_NTSTATUS_WIN_STATUS_FVE_EDRIVE_DRY_RUN_FAILED = 0xC0210038,
+ MD_NTSTATUS_WIN_STATUS_FVE_SECUREBOOT_DISABLED = 0xC0210039,
+ MD_NTSTATUS_WIN_STATUS_FVE_SECUREBOOT_CONFIG_CHANGE = 0xC021003A,
+ MD_NTSTATUS_WIN_STATUS_FVE_DEVICE_LOCKEDOUT = 0xC021003B,
+ MD_NTSTATUS_WIN_STATUS_FVE_VOLUME_EXTEND_PREVENTS_EOW_DECRYPT = 0xC021003C,
+ MD_NTSTATUS_WIN_STATUS_FVE_NOT_DE_VOLUME = 0xC021003D,
+ MD_NTSTATUS_WIN_STATUS_FVE_PROTECTION_DISABLED = 0xC021003E,
+ MD_NTSTATUS_WIN_STATUS_FVE_PROTECTION_CANNOT_BE_DISABLED = 0xC021003F,
+ MD_NTSTATUS_WIN_STATUS_FVE_OSV_KSR_NOT_ALLOWED = 0xC0210040,
+ MD_NTSTATUS_WIN_STATUS_FWP_CALLOUT_NOT_FOUND = 0xC0220001,
+ MD_NTSTATUS_WIN_STATUS_FWP_CONDITION_NOT_FOUND = 0xC0220002,
+ MD_NTSTATUS_WIN_STATUS_FWP_FILTER_NOT_FOUND = 0xC0220003,
+ MD_NTSTATUS_WIN_STATUS_FWP_LAYER_NOT_FOUND = 0xC0220004,
+ MD_NTSTATUS_WIN_STATUS_FWP_PROVIDER_NOT_FOUND = 0xC0220005,
+ MD_NTSTATUS_WIN_STATUS_FWP_PROVIDER_CONTEXT_NOT_FOUND = 0xC0220006,
+ MD_NTSTATUS_WIN_STATUS_FWP_SUBLAYER_NOT_FOUND = 0xC0220007,
+ MD_NTSTATUS_WIN_STATUS_FWP_NOT_FOUND = 0xC0220008,
+ MD_NTSTATUS_WIN_STATUS_FWP_ALREADY_EXISTS = 0xC0220009,
+ MD_NTSTATUS_WIN_STATUS_FWP_IN_USE = 0xC022000A,
+ MD_NTSTATUS_WIN_STATUS_FWP_DYNAMIC_SESSION_IN_PROGRESS = 0xC022000B,
+ MD_NTSTATUS_WIN_STATUS_FWP_WRONG_SESSION = 0xC022000C,
+ MD_NTSTATUS_WIN_STATUS_FWP_NO_TXN_IN_PROGRESS = 0xC022000D,
+ MD_NTSTATUS_WIN_STATUS_FWP_TXN_IN_PROGRESS = 0xC022000E,
+ MD_NTSTATUS_WIN_STATUS_FWP_TXN_ABORTED = 0xC022000F,
+ MD_NTSTATUS_WIN_STATUS_FWP_SESSION_ABORTED = 0xC0220010,
+ MD_NTSTATUS_WIN_STATUS_FWP_INCOMPATIBLE_TXN = 0xC0220011,
+ MD_NTSTATUS_WIN_STATUS_FWP_TIMEOUT = 0xC0220012,
+ MD_NTSTATUS_WIN_STATUS_FWP_NET_EVENTS_DISABLED = 0xC0220013,
+ MD_NTSTATUS_WIN_STATUS_FWP_INCOMPATIBLE_LAYER = 0xC0220014,
+ MD_NTSTATUS_WIN_STATUS_FWP_KM_CLIENTS_ONLY = 0xC0220015,
+ MD_NTSTATUS_WIN_STATUS_FWP_LIFETIME_MISMATCH = 0xC0220016,
+ MD_NTSTATUS_WIN_STATUS_FWP_BUILTIN_OBJECT = 0xC0220017,
+ MD_NTSTATUS_WIN_STATUS_FWP_TOO_MANY_CALLOUTS = 0xC0220018,
+ MD_NTSTATUS_WIN_STATUS_FWP_NOTIFICATION_DROPPED = 0xC0220019,
+ MD_NTSTATUS_WIN_STATUS_FWP_TRAFFIC_MISMATCH = 0xC022001A,
+ MD_NTSTATUS_WIN_STATUS_FWP_INCOMPATIBLE_SA_STATE = 0xC022001B,
+ MD_NTSTATUS_WIN_STATUS_FWP_NULL_POINTER = 0xC022001C,
+ MD_NTSTATUS_WIN_STATUS_FWP_INVALID_ENUMERATOR = 0xC022001D,
+ MD_NTSTATUS_WIN_STATUS_FWP_INVALID_FLAGS = 0xC022001E,
+ MD_NTSTATUS_WIN_STATUS_FWP_INVALID_NET_MASK = 0xC022001F,
+ MD_NTSTATUS_WIN_STATUS_FWP_INVALID_RANGE = 0xC0220020,
+ MD_NTSTATUS_WIN_STATUS_FWP_INVALID_INTERVAL = 0xC0220021,
+ MD_NTSTATUS_WIN_STATUS_FWP_ZERO_LENGTH_ARRAY = 0xC0220022,
+ MD_NTSTATUS_WIN_STATUS_FWP_NULL_DISPLAY_NAME = 0xC0220023,
+ MD_NTSTATUS_WIN_STATUS_FWP_INVALID_ACTION_TYPE = 0xC0220024,
+ MD_NTSTATUS_WIN_STATUS_FWP_INVALID_WEIGHT = 0xC0220025,
+ MD_NTSTATUS_WIN_STATUS_FWP_MATCH_TYPE_MISMATCH = 0xC0220026,
+ MD_NTSTATUS_WIN_STATUS_FWP_TYPE_MISMATCH = 0xC0220027,
+ MD_NTSTATUS_WIN_STATUS_FWP_OUT_OF_BOUNDS = 0xC0220028,
+ MD_NTSTATUS_WIN_STATUS_FWP_RESERVED = 0xC0220029,
+ MD_NTSTATUS_WIN_STATUS_FWP_DUPLICATE_CONDITION = 0xC022002A,
+ MD_NTSTATUS_WIN_STATUS_FWP_DUPLICATE_KEYMOD = 0xC022002B,
+ MD_NTSTATUS_WIN_STATUS_FWP_ACTION_INCOMPATIBLE_WITH_LAYER = 0xC022002C,
+ MD_NTSTATUS_WIN_STATUS_FWP_ACTION_INCOMPATIBLE_WITH_SUBLAYER = 0xC022002D,
+ MD_NTSTATUS_WIN_STATUS_FWP_CONTEXT_INCOMPATIBLE_WITH_LAYER = 0xC022002E,
+ MD_NTSTATUS_WIN_STATUS_FWP_CONTEXT_INCOMPATIBLE_WITH_CALLOUT = 0xC022002F,
+ MD_NTSTATUS_WIN_STATUS_FWP_INCOMPATIBLE_AUTH_METHOD = 0xC0220030,
+ MD_NTSTATUS_WIN_STATUS_FWP_INCOMPATIBLE_DH_GROUP = 0xC0220031,
+ MD_NTSTATUS_WIN_STATUS_FWP_EM_NOT_SUPPORTED = 0xC0220032,
+ MD_NTSTATUS_WIN_STATUS_FWP_NEVER_MATCH = 0xC0220033,
+ MD_NTSTATUS_WIN_STATUS_FWP_PROVIDER_CONTEXT_MISMATCH = 0xC0220034,
+ MD_NTSTATUS_WIN_STATUS_FWP_INVALID_PARAMETER = 0xC0220035,
+ MD_NTSTATUS_WIN_STATUS_FWP_TOO_MANY_SUBLAYERS = 0xC0220036,
+ MD_NTSTATUS_WIN_STATUS_FWP_CALLOUT_NOTIFICATION_FAILED = 0xC0220037,
+ MD_NTSTATUS_WIN_STATUS_FWP_INVALID_AUTH_TRANSFORM = 0xC0220038,
+ MD_NTSTATUS_WIN_STATUS_FWP_INVALID_CIPHER_TRANSFORM = 0xC0220039,
+ MD_NTSTATUS_WIN_STATUS_FWP_INCOMPATIBLE_CIPHER_TRANSFORM = 0xC022003A,
+ MD_NTSTATUS_WIN_STATUS_FWP_INVALID_TRANSFORM_COMBINATION = 0xC022003B,
+ MD_NTSTATUS_WIN_STATUS_FWP_DUPLICATE_AUTH_METHOD = 0xC022003C,
+ MD_NTSTATUS_WIN_STATUS_FWP_INVALID_TUNNEL_ENDPOINT = 0xC022003D,
+ MD_NTSTATUS_WIN_STATUS_FWP_L2_DRIVER_NOT_READY = 0xC022003E,
+ MD_NTSTATUS_WIN_STATUS_FWP_KEY_DICTATOR_ALREADY_REGISTERED = 0xC022003F,
+ MD_NTSTATUS_WIN_STATUS_FWP_KEY_DICTATION_INVALID_KEYING_MATERIAL = 0xC0220040,
+ MD_NTSTATUS_WIN_STATUS_FWP_CONNECTIONS_DISABLED = 0xC0220041,
+ MD_NTSTATUS_WIN_STATUS_FWP_INVALID_DNS_NAME = 0xC0220042,
+ MD_NTSTATUS_WIN_STATUS_FWP_STILL_ON = 0xC0220043,
+ MD_NTSTATUS_WIN_STATUS_FWP_IKEEXT_NOT_RUNNING = 0xC0220044,
+ MD_NTSTATUS_WIN_STATUS_FWP_TCPIP_NOT_READY = 0xC0220100,
+ MD_NTSTATUS_WIN_STATUS_FWP_INJECT_HANDLE_CLOSING = 0xC0220101,
+ MD_NTSTATUS_WIN_STATUS_FWP_INJECT_HANDLE_STALE = 0xC0220102,
+ MD_NTSTATUS_WIN_STATUS_FWP_CANNOT_PEND = 0xC0220103,
+ MD_NTSTATUS_WIN_STATUS_FWP_DROP_NOICMP = 0xC0220104,
+ MD_NTSTATUS_WIN_STATUS_NDIS_CLOSING = 0xC0230002,
+ MD_NTSTATUS_WIN_STATUS_NDIS_BAD_VERSION = 0xC0230004,
+ MD_NTSTATUS_WIN_STATUS_NDIS_BAD_CHARACTERISTICS = 0xC0230005,
+ MD_NTSTATUS_WIN_STATUS_NDIS_ADAPTER_NOT_FOUND = 0xC0230006,
+ MD_NTSTATUS_WIN_STATUS_NDIS_OPEN_FAILED = 0xC0230007,
+ MD_NTSTATUS_WIN_STATUS_NDIS_DEVICE_FAILED = 0xC0230008,
+ MD_NTSTATUS_WIN_STATUS_NDIS_MULTICAST_FULL = 0xC0230009,
+ MD_NTSTATUS_WIN_STATUS_NDIS_MULTICAST_EXISTS = 0xC023000A,
+ MD_NTSTATUS_WIN_STATUS_NDIS_MULTICAST_NOT_FOUND = 0xC023000B,
+ MD_NTSTATUS_WIN_STATUS_NDIS_REQUEST_ABORTED = 0xC023000C,
+ MD_NTSTATUS_WIN_STATUS_NDIS_RESET_IN_PROGRESS = 0xC023000D,
+ MD_NTSTATUS_WIN_STATUS_NDIS_INVALID_PACKET = 0xC023000F,
+ MD_NTSTATUS_WIN_STATUS_NDIS_INVALID_DEVICE_REQUEST = 0xC0230010,
+ MD_NTSTATUS_WIN_STATUS_NDIS_ADAPTER_NOT_READY = 0xC0230011,
+ MD_NTSTATUS_WIN_STATUS_NDIS_INVALID_LENGTH = 0xC0230014,
+ MD_NTSTATUS_WIN_STATUS_NDIS_INVALID_DATA = 0xC0230015,
+ MD_NTSTATUS_WIN_STATUS_NDIS_BUFFER_TOO_SHORT = 0xC0230016,
+ MD_NTSTATUS_WIN_STATUS_NDIS_INVALID_OID = 0xC0230017,
+ MD_NTSTATUS_WIN_STATUS_NDIS_ADAPTER_REMOVED = 0xC0230018,
+ MD_NTSTATUS_WIN_STATUS_NDIS_UNSUPPORTED_MEDIA = 0xC0230019,
+ MD_NTSTATUS_WIN_STATUS_NDIS_GROUP_ADDRESS_IN_USE = 0xC023001A,
+ MD_NTSTATUS_WIN_STATUS_NDIS_FILE_NOT_FOUND = 0xC023001B,
+ MD_NTSTATUS_WIN_STATUS_NDIS_ERROR_READING_FILE = 0xC023001C,
+ MD_NTSTATUS_WIN_STATUS_NDIS_ALREADY_MAPPED = 0xC023001D,
+ MD_NTSTATUS_WIN_STATUS_NDIS_RESOURCE_CONFLICT = 0xC023001E,
+ MD_NTSTATUS_WIN_STATUS_NDIS_MEDIA_DISCONNECTED = 0xC023001F,
+ MD_NTSTATUS_WIN_STATUS_NDIS_INVALID_ADDRESS = 0xC0230022,
+ MD_NTSTATUS_WIN_STATUS_NDIS_PAUSED = 0xC023002A,
+ MD_NTSTATUS_WIN_STATUS_NDIS_INTERFACE_NOT_FOUND = 0xC023002B,
+ MD_NTSTATUS_WIN_STATUS_NDIS_UNSUPPORTED_REVISION = 0xC023002C,
+ MD_NTSTATUS_WIN_STATUS_NDIS_INVALID_PORT = 0xC023002D,
+ MD_NTSTATUS_WIN_STATUS_NDIS_INVALID_PORT_STATE = 0xC023002E,
+ MD_NTSTATUS_WIN_STATUS_NDIS_LOW_POWER_STATE = 0xC023002F,
+ MD_NTSTATUS_WIN_STATUS_NDIS_REINIT_REQUIRED = 0xC0230030,
+ MD_NTSTATUS_WIN_STATUS_NDIS_NO_QUEUES = 0xC0230031,
+ MD_NTSTATUS_WIN_STATUS_NDIS_NOT_SUPPORTED = 0xC02300BB,
+ MD_NTSTATUS_WIN_STATUS_NDIS_OFFLOAD_POLICY = 0xC023100F,
+ MD_NTSTATUS_WIN_STATUS_NDIS_OFFLOAD_CONNECTION_REJECTED = 0xC0231012,
+ MD_NTSTATUS_WIN_STATUS_NDIS_OFFLOAD_PATH_REJECTED = 0xC0231013,
+ MD_NTSTATUS_WIN_STATUS_NDIS_DOT11_AUTO_CONFIG_ENABLED = 0xC0232000,
+ MD_NTSTATUS_WIN_STATUS_NDIS_DOT11_MEDIA_IN_USE = 0xC0232001,
+ MD_NTSTATUS_WIN_STATUS_NDIS_DOT11_POWER_STATE_INVALID = 0xC0232002,
+ MD_NTSTATUS_WIN_STATUS_NDIS_PM_WOL_PATTERN_LIST_FULL = 0xC0232003,
+ MD_NTSTATUS_WIN_STATUS_NDIS_PM_PROTOCOL_OFFLOAD_LIST_FULL = 0xC0232004,
+ MD_NTSTATUS_WIN_STATUS_NDIS_DOT11_AP_CHANNEL_CURRENTLY_NOT_AVAILABLE = 0xC0232005,
+ MD_NTSTATUS_WIN_STATUS_NDIS_DOT11_AP_BAND_CURRENTLY_NOT_AVAILABLE = 0xC0232006,
+ MD_NTSTATUS_WIN_STATUS_NDIS_DOT11_AP_CHANNEL_NOT_ALLOWED = 0xC0232007,
+ MD_NTSTATUS_WIN_STATUS_NDIS_DOT11_AP_BAND_NOT_ALLOWED = 0xC0232008,
+ MD_NTSTATUS_WIN_STATUS_QUIC_HANDSHAKE_FAILURE = 0xC0240000,
+ MD_NTSTATUS_WIN_STATUS_QUIC_VER_NEG_FAILURE = 0xC0240001,
+ MD_NTSTATUS_WIN_STATUS_TPM_ERROR_MASK = 0xC0290000,
+ MD_NTSTATUS_WIN_STATUS_TPM_AUTHFAIL = 0xC0290001,
+ MD_NTSTATUS_WIN_STATUS_TPM_BADINDEX = 0xC0290002,
+ MD_NTSTATUS_WIN_STATUS_TPM_BAD_PARAMETER = 0xC0290003,
+ MD_NTSTATUS_WIN_STATUS_TPM_AUDITFAILURE = 0xC0290004,
+ MD_NTSTATUS_WIN_STATUS_TPM_CLEAR_DISABLED = 0xC0290005,
+ MD_NTSTATUS_WIN_STATUS_TPM_DEACTIVATED = 0xC0290006,
+ MD_NTSTATUS_WIN_STATUS_TPM_DISABLED = 0xC0290007,
+ MD_NTSTATUS_WIN_STATUS_TPM_DISABLED_CMD = 0xC0290008,
+ MD_NTSTATUS_WIN_STATUS_TPM_FAIL = 0xC0290009,
+ MD_NTSTATUS_WIN_STATUS_TPM_BAD_ORDINAL = 0xC029000A,
+ MD_NTSTATUS_WIN_STATUS_TPM_INSTALL_DISABLED = 0xC029000B,
+ MD_NTSTATUS_WIN_STATUS_TPM_INVALID_KEYHANDLE = 0xC029000C,
+ MD_NTSTATUS_WIN_STATUS_TPM_KEYNOTFOUND = 0xC029000D,
+ MD_NTSTATUS_WIN_STATUS_TPM_INAPPROPRIATE_ENC = 0xC029000E,
+ MD_NTSTATUS_WIN_STATUS_TPM_MIGRATEFAIL = 0xC029000F,
+ MD_NTSTATUS_WIN_STATUS_TPM_INVALID_PCR_INFO = 0xC0290010,
+ MD_NTSTATUS_WIN_STATUS_TPM_NOSPACE = 0xC0290011,
+ MD_NTSTATUS_WIN_STATUS_TPM_NOSRK = 0xC0290012,
+ MD_NTSTATUS_WIN_STATUS_TPM_NOTSEALED_BLOB = 0xC0290013,
+ MD_NTSTATUS_WIN_STATUS_TPM_OWNER_SET = 0xC0290014,
+ MD_NTSTATUS_WIN_STATUS_TPM_RESOURCES = 0xC0290015,
+ MD_NTSTATUS_WIN_STATUS_TPM_SHORTRANDOM = 0xC0290016,
+ MD_NTSTATUS_WIN_STATUS_TPM_SIZE = 0xC0290017,
+ MD_NTSTATUS_WIN_STATUS_TPM_WRONGPCRVAL = 0xC0290018,
+ MD_NTSTATUS_WIN_STATUS_TPM_BAD_PARAM_SIZE = 0xC0290019,
+ MD_NTSTATUS_WIN_STATUS_TPM_SHA_THREAD = 0xC029001A,
+ MD_NTSTATUS_WIN_STATUS_TPM_SHA_ERROR = 0xC029001B,
+ MD_NTSTATUS_WIN_STATUS_TPM_FAILEDSELFTEST = 0xC029001C,
+ MD_NTSTATUS_WIN_STATUS_TPM_AUTH2FAIL = 0xC029001D,
+ MD_NTSTATUS_WIN_STATUS_TPM_BADTAG = 0xC029001E,
+ MD_NTSTATUS_WIN_STATUS_TPM_IOERROR = 0xC029001F,
+ MD_NTSTATUS_WIN_STATUS_TPM_ENCRYPT_ERROR = 0xC0290020,
+ MD_NTSTATUS_WIN_STATUS_TPM_DECRYPT_ERROR = 0xC0290021,
+ MD_NTSTATUS_WIN_STATUS_TPM_INVALID_AUTHHANDLE = 0xC0290022,
+ MD_NTSTATUS_WIN_STATUS_TPM_NO_ENDORSEMENT = 0xC0290023,
+ MD_NTSTATUS_WIN_STATUS_TPM_INVALID_KEYUSAGE = 0xC0290024,
+ MD_NTSTATUS_WIN_STATUS_TPM_WRONG_ENTITYTYPE = 0xC0290025,
+ MD_NTSTATUS_WIN_STATUS_TPM_INVALID_POSTINIT = 0xC0290026,
+ MD_NTSTATUS_WIN_STATUS_TPM_INAPPROPRIATE_SIG = 0xC0290027,
+ MD_NTSTATUS_WIN_STATUS_TPM_BAD_KEY_PROPERTY = 0xC0290028,
+ MD_NTSTATUS_WIN_STATUS_TPM_BAD_MIGRATION = 0xC0290029,
+ MD_NTSTATUS_WIN_STATUS_TPM_BAD_SCHEME = 0xC029002A,
+ MD_NTSTATUS_WIN_STATUS_TPM_BAD_DATASIZE = 0xC029002B,
+ MD_NTSTATUS_WIN_STATUS_TPM_BAD_MODE = 0xC029002C,
+ MD_NTSTATUS_WIN_STATUS_TPM_BAD_PRESENCE = 0xC029002D,
+ MD_NTSTATUS_WIN_STATUS_TPM_BAD_VERSION = 0xC029002E,
+ MD_NTSTATUS_WIN_STATUS_TPM_NO_WRAP_TRANSPORT = 0xC029002F,
+ MD_NTSTATUS_WIN_STATUS_TPM_AUDITFAIL_UNSUCCESSFUL = 0xC0290030,
+ MD_NTSTATUS_WIN_STATUS_TPM_AUDITFAIL_SUCCESSFUL = 0xC0290031,
+ MD_NTSTATUS_WIN_STATUS_TPM_NOTRESETABLE = 0xC0290032,
+ MD_NTSTATUS_WIN_STATUS_TPM_NOTLOCAL = 0xC0290033,
+ MD_NTSTATUS_WIN_STATUS_TPM_BAD_TYPE = 0xC0290034,
+ MD_NTSTATUS_WIN_STATUS_TPM_INVALID_RESOURCE = 0xC0290035,
+ MD_NTSTATUS_WIN_STATUS_TPM_NOTFIPS = 0xC0290036,
+ MD_NTSTATUS_WIN_STATUS_TPM_INVALID_FAMILY = 0xC0290037,
+ MD_NTSTATUS_WIN_STATUS_TPM_NO_NV_PERMISSION = 0xC0290038,
+ MD_NTSTATUS_WIN_STATUS_TPM_REQUIRES_SIGN = 0xC0290039,
+ MD_NTSTATUS_WIN_STATUS_TPM_KEY_NOTSUPPORTED = 0xC029003A,
+ MD_NTSTATUS_WIN_STATUS_TPM_AUTH_CONFLICT = 0xC029003B,
+ MD_NTSTATUS_WIN_STATUS_TPM_AREA_LOCKED = 0xC029003C,
+ MD_NTSTATUS_WIN_STATUS_TPM_BAD_LOCALITY = 0xC029003D,
+ MD_NTSTATUS_WIN_STATUS_TPM_READ_ONLY = 0xC029003E,
+ MD_NTSTATUS_WIN_STATUS_TPM_PER_NOWRITE = 0xC029003F,
+ MD_NTSTATUS_WIN_STATUS_TPM_FAMILYCOUNT = 0xC0290040,
+ MD_NTSTATUS_WIN_STATUS_TPM_WRITE_LOCKED = 0xC0290041,
+ MD_NTSTATUS_WIN_STATUS_TPM_BAD_ATTRIBUTES = 0xC0290042,
+ MD_NTSTATUS_WIN_STATUS_TPM_INVALID_STRUCTURE = 0xC0290043,
+ MD_NTSTATUS_WIN_STATUS_TPM_KEY_OWNER_CONTROL = 0xC0290044,
+ MD_NTSTATUS_WIN_STATUS_TPM_BAD_COUNTER = 0xC0290045,
+ MD_NTSTATUS_WIN_STATUS_TPM_NOT_FULLWRITE = 0xC0290046,
+ MD_NTSTATUS_WIN_STATUS_TPM_CONTEXT_GAP = 0xC0290047,
+ MD_NTSTATUS_WIN_STATUS_TPM_MAXNVWRITES = 0xC0290048,
+ MD_NTSTATUS_WIN_STATUS_TPM_NOOPERATOR = 0xC0290049,
+ MD_NTSTATUS_WIN_STATUS_TPM_RESOURCEMISSING = 0xC029004A,
+ MD_NTSTATUS_WIN_STATUS_TPM_DELEGATE_LOCK = 0xC029004B,
+ MD_NTSTATUS_WIN_STATUS_TPM_DELEGATE_FAMILY = 0xC029004C,
+ MD_NTSTATUS_WIN_STATUS_TPM_DELEGATE_ADMIN = 0xC029004D,
+ MD_NTSTATUS_WIN_STATUS_TPM_TRANSPORT_NOTEXCLUSIVE = 0xC029004E,
+ MD_NTSTATUS_WIN_STATUS_TPM_OWNER_CONTROL = 0xC029004F,
+ MD_NTSTATUS_WIN_STATUS_TPM_DAA_RESOURCES = 0xC0290050,
+ MD_NTSTATUS_WIN_STATUS_TPM_DAA_INPUT_DATA0 = 0xC0290051,
+ MD_NTSTATUS_WIN_STATUS_TPM_DAA_INPUT_DATA1 = 0xC0290052,
+ MD_NTSTATUS_WIN_STATUS_TPM_DAA_ISSUER_SETTINGS = 0xC0290053,
+ MD_NTSTATUS_WIN_STATUS_TPM_DAA_TPM_SETTINGS = 0xC0290054,
+ MD_NTSTATUS_WIN_STATUS_TPM_DAA_STAGE = 0xC0290055,
+ MD_NTSTATUS_WIN_STATUS_TPM_DAA_ISSUER_VALIDITY = 0xC0290056,
+ MD_NTSTATUS_WIN_STATUS_TPM_DAA_WRONG_W = 0xC0290057,
+ MD_NTSTATUS_WIN_STATUS_TPM_BAD_HANDLE = 0xC0290058,
+ MD_NTSTATUS_WIN_STATUS_TPM_BAD_DELEGATE = 0xC0290059,
+ MD_NTSTATUS_WIN_STATUS_TPM_BADCONTEXT = 0xC029005A,
+ MD_NTSTATUS_WIN_STATUS_TPM_TOOMANYCONTEXTS = 0xC029005B,
+ MD_NTSTATUS_WIN_STATUS_TPM_MA_TICKET_SIGNATURE = 0xC029005C,
+ MD_NTSTATUS_WIN_STATUS_TPM_MA_DESTINATION = 0xC029005D,
+ MD_NTSTATUS_WIN_STATUS_TPM_MA_SOURCE = 0xC029005E,
+ MD_NTSTATUS_WIN_STATUS_TPM_MA_AUTHORITY = 0xC029005F,
+ MD_NTSTATUS_WIN_STATUS_TPM_PERMANENTEK = 0xC0290061,
+ MD_NTSTATUS_WIN_STATUS_TPM_BAD_SIGNATURE = 0xC0290062,
+ MD_NTSTATUS_WIN_STATUS_TPM_NOCONTEXTSPACE = 0xC0290063,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_ASYMMETRIC = 0xC0290081,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_ATTRIBUTES = 0xC0290082,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_HASH = 0xC0290083,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_VALUE = 0xC0290084,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_HIERARCHY = 0xC0290085,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_KEY_SIZE = 0xC0290087,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_MGF = 0xC0290088,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_MODE = 0xC0290089,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_TYPE = 0xC029008A,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_HANDLE = 0xC029008B,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_KDF = 0xC029008C,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_RANGE = 0xC029008D,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_AUTH_FAIL = 0xC029008E,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_NONCE = 0xC029008F,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_PP = 0xC0290090,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_SCHEME = 0xC0290092,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_SIZE = 0xC0290095,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_SYMMETRIC = 0xC0290096,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_TAG = 0xC0290097,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_SELECTOR = 0xC0290098,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_INSUFFICIENT = 0xC029009A,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_SIGNATURE = 0xC029009B,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_KEY = 0xC029009C,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_POLICY_FAIL = 0xC029009D,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_INTEGRITY = 0xC029009F,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_TICKET = 0xC02900A0,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_RESERVED_BITS = 0xC02900A1,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_BAD_AUTH = 0xC02900A2,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_EXPIRED = 0xC02900A3,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_POLICY_CC = 0xC02900A4,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_BINDING = 0xC02900A5,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_CURVE = 0xC02900A6,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_ECC_POINT = 0xC02900A7,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_INITIALIZE = 0xC0290100,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_FAILURE = 0xC0290101,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_SEQUENCE = 0xC0290103,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_PRIVATE = 0xC029010B,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_HMAC = 0xC0290119,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_DISABLED = 0xC0290120,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_EXCLUSIVE = 0xC0290121,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_ECC_CURVE = 0xC0290123,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_AUTH_TYPE = 0xC0290124,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_AUTH_MISSING = 0xC0290125,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_POLICY = 0xC0290126,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_PCR = 0xC0290127,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_PCR_CHANGED = 0xC0290128,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_UPGRADE = 0xC029012D,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_TOO_MANY_CONTEXTS = 0xC029012E,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_AUTH_UNAVAILABLE = 0xC029012F,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_REBOOT = 0xC0290130,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_UNBALANCED = 0xC0290131,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_COMMAND_SIZE = 0xC0290142,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_COMMAND_CODE = 0xC0290143,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_AUTHSIZE = 0xC0290144,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_AUTH_CONTEXT = 0xC0290145,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_NV_RANGE = 0xC0290146,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_NV_SIZE = 0xC0290147,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_NV_LOCKED = 0xC0290148,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_NV_AUTHORIZATION = 0xC0290149,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_NV_UNINITIALIZED = 0xC029014A,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_NV_SPACE = 0xC029014B,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_NV_DEFINED = 0xC029014C,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_BAD_CONTEXT = 0xC0290150,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_CPHASH = 0xC0290151,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_PARENT = 0xC0290152,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_NEEDS_TEST = 0xC0290153,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_NO_RESULT = 0xC0290154,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_SENSITIVE = 0xC0290155,
+ MD_NTSTATUS_WIN_STATUS_TPM_COMMAND_BLOCKED = 0xC0290400,
+ MD_NTSTATUS_WIN_STATUS_TPM_INVALID_HANDLE = 0xC0290401,
+ MD_NTSTATUS_WIN_STATUS_TPM_DUPLICATE_VHANDLE = 0xC0290402,
+ MD_NTSTATUS_WIN_STATUS_TPM_EMBEDDED_COMMAND_BLOCKED = 0xC0290403,
+ MD_NTSTATUS_WIN_STATUS_TPM_EMBEDDED_COMMAND_UNSUPPORTED = 0xC0290404,
+ MD_NTSTATUS_WIN_STATUS_TPM_RETRY = 0xC0290800,
+ MD_NTSTATUS_WIN_STATUS_TPM_NEEDS_SELFTEST = 0xC0290801,
+ MD_NTSTATUS_WIN_STATUS_TPM_DOING_SELFTEST = 0xC0290802,
+ MD_NTSTATUS_WIN_STATUS_TPM_DEFEND_LOCK_RUNNING = 0xC0290803,
+ MD_NTSTATUS_WIN_STATUS_TPM_COMMAND_CANCELED = 0xC0291001,
+ MD_NTSTATUS_WIN_STATUS_TPM_TOO_MANY_CONTEXTS = 0xC0291002,
+ MD_NTSTATUS_WIN_STATUS_TPM_NOT_FOUND = 0xC0291003,
+ MD_NTSTATUS_WIN_STATUS_TPM_ACCESS_DENIED = 0xC0291004,
+ MD_NTSTATUS_WIN_STATUS_TPM_INSUFFICIENT_BUFFER = 0xC0291005,
+ MD_NTSTATUS_WIN_STATUS_TPM_PPI_FUNCTION_UNSUPPORTED = 0xC0291006,
+ MD_NTSTATUS_WIN_STATUS_PCP_ERROR_MASK = 0xC0292000,
+ MD_NTSTATUS_WIN_STATUS_PCP_DEVICE_NOT_READY = 0xC0292001,
+ MD_NTSTATUS_WIN_STATUS_PCP_INVALID_HANDLE = 0xC0292002,
+ MD_NTSTATUS_WIN_STATUS_PCP_INVALID_PARAMETER = 0xC0292003,
+ MD_NTSTATUS_WIN_STATUS_PCP_FLAG_NOT_SUPPORTED = 0xC0292004,
+ MD_NTSTATUS_WIN_STATUS_PCP_NOT_SUPPORTED = 0xC0292005,
+ MD_NTSTATUS_WIN_STATUS_PCP_BUFFER_TOO_SMALL = 0xC0292006,
+ MD_NTSTATUS_WIN_STATUS_PCP_INTERNAL_ERROR = 0xC0292007,
+ MD_NTSTATUS_WIN_STATUS_PCP_AUTHENTICATION_FAILED = 0xC0292008,
+ MD_NTSTATUS_WIN_STATUS_PCP_AUTHENTICATION_IGNORED = 0xC0292009,
+ MD_NTSTATUS_WIN_STATUS_PCP_POLICY_NOT_FOUND = 0xC029200A,
+ MD_NTSTATUS_WIN_STATUS_PCP_PROFILE_NOT_FOUND = 0xC029200B,
+ MD_NTSTATUS_WIN_STATUS_PCP_VALIDATION_FAILED = 0xC029200C,
+ MD_NTSTATUS_WIN_STATUS_PCP_DEVICE_NOT_FOUND = 0xC029200D,
+ MD_NTSTATUS_WIN_STATUS_PCP_WRONG_PARENT = 0xC029200E,
+ MD_NTSTATUS_WIN_STATUS_PCP_KEY_NOT_LOADED = 0xC029200F,
+ MD_NTSTATUS_WIN_STATUS_PCP_NO_KEY_CERTIFICATION = 0xC0292010,
+ MD_NTSTATUS_WIN_STATUS_PCP_KEY_NOT_FINALIZED = 0xC0292011,
+ MD_NTSTATUS_WIN_STATUS_PCP_ATTESTATION_CHALLENGE_NOT_SET = 0xC0292012,
+ MD_NTSTATUS_WIN_STATUS_PCP_NOT_PCR_BOUND = 0xC0292013,
+ MD_NTSTATUS_WIN_STATUS_PCP_KEY_ALREADY_FINALIZED = 0xC0292014,
+ MD_NTSTATUS_WIN_STATUS_PCP_KEY_USAGE_POLICY_NOT_SUPPORTED = 0xC0292015,
+ MD_NTSTATUS_WIN_STATUS_PCP_KEY_USAGE_POLICY_INVALID = 0xC0292016,
+ MD_NTSTATUS_WIN_STATUS_PCP_SOFT_KEY_ERROR = 0xC0292017,
+ MD_NTSTATUS_WIN_STATUS_PCP_KEY_NOT_AUTHENTICATED = 0xC0292018,
+ MD_NTSTATUS_WIN_STATUS_PCP_KEY_NOT_AIK = 0xC0292019,
+ MD_NTSTATUS_WIN_STATUS_PCP_KEY_NOT_SIGNING_KEY = 0xC029201A,
+ MD_NTSTATUS_WIN_STATUS_PCP_LOCKED_OUT = 0xC029201B,
+ MD_NTSTATUS_WIN_STATUS_PCP_CLAIM_TYPE_NOT_SUPPORTED = 0xC029201C,
+ MD_NTSTATUS_WIN_STATUS_PCP_TPM_VERSION_NOT_SUPPORTED = 0xC029201D,
+ MD_NTSTATUS_WIN_STATUS_PCP_BUFFER_LENGTH_MISMATCH = 0xC029201E,
+ MD_NTSTATUS_WIN_STATUS_PCP_IFX_RSA_KEY_CREATION_BLOCKED = 0xC029201F,
+ MD_NTSTATUS_WIN_STATUS_PCP_TICKET_MISSING = 0xC0292020,
+ MD_NTSTATUS_WIN_STATUS_PCP_RAW_POLICY_NOT_SUPPORTED = 0xC0292021,
+ MD_NTSTATUS_WIN_STATUS_PCP_KEY_HANDLE_INVALIDATED = 0xC0292022,
+ MD_NTSTATUS_WIN_STATUS_RTPM_NO_RESULT = 0xC0293002,
+ MD_NTSTATUS_WIN_STATUS_RTPM_PCR_READ_INCOMPLETE = 0xC0293003,
+ MD_NTSTATUS_WIN_STATUS_RTPM_INVALID_CONTEXT = 0xC0293004,
+ MD_NTSTATUS_WIN_STATUS_RTPM_UNSUPPORTED_CMD = 0xC0293005,
+ MD_NTSTATUS_WIN_STATUS_TPM_ZERO_EXHAUST_ENABLED = 0xC0294000,
+ MD_NTSTATUS_WIN_STATUS_HV_INVALID_HYPERCALL_CODE = 0xC0350002,
+ MD_NTSTATUS_WIN_STATUS_HV_INVALID_HYPERCALL_INPUT = 0xC0350003,
+ MD_NTSTATUS_WIN_STATUS_HV_INVALID_ALIGNMENT = 0xC0350004,
+ MD_NTSTATUS_WIN_STATUS_HV_INVALID_PARAMETER = 0xC0350005,
+ MD_NTSTATUS_WIN_STATUS_HV_ACCESS_DENIED = 0xC0350006,
+ MD_NTSTATUS_WIN_STATUS_HV_INVALID_PARTITION_STATE = 0xC0350007,
+ MD_NTSTATUS_WIN_STATUS_HV_OPERATION_DENIED = 0xC0350008,
+ MD_NTSTATUS_WIN_STATUS_HV_UNKNOWN_PROPERTY = 0xC0350009,
+ MD_NTSTATUS_WIN_STATUS_HV_PROPERTY_VALUE_OUT_OF_RANGE = 0xC035000A,
+ MD_NTSTATUS_WIN_STATUS_HV_INSUFFICIENT_MEMORY = 0xC035000B,
+ MD_NTSTATUS_WIN_STATUS_HV_PARTITION_TOO_DEEP = 0xC035000C,
+ MD_NTSTATUS_WIN_STATUS_HV_INVALID_PARTITION_ID = 0xC035000D,
+ MD_NTSTATUS_WIN_STATUS_HV_INVALID_VP_INDEX = 0xC035000E,
+ MD_NTSTATUS_WIN_STATUS_HV_INVALID_PORT_ID = 0xC0350011,
+ MD_NTSTATUS_WIN_STATUS_HV_INVALID_CONNECTION_ID = 0xC0350012,
+ MD_NTSTATUS_WIN_STATUS_HV_INSUFFICIENT_BUFFERS = 0xC0350013,
+ MD_NTSTATUS_WIN_STATUS_HV_NOT_ACKNOWLEDGED = 0xC0350014,
+ MD_NTSTATUS_WIN_STATUS_HV_INVALID_VP_STATE = 0xC0350015,
+ MD_NTSTATUS_WIN_STATUS_HV_ACKNOWLEDGED = 0xC0350016,
+ MD_NTSTATUS_WIN_STATUS_HV_INVALID_SAVE_RESTORE_STATE = 0xC0350017,
+ MD_NTSTATUS_WIN_STATUS_HV_INVALID_SYNIC_STATE = 0xC0350018,
+ MD_NTSTATUS_WIN_STATUS_HV_OBJECT_IN_USE = 0xC0350019,
+ MD_NTSTATUS_WIN_STATUS_HV_INVALID_PROXIMITY_DOMAIN_INFO = 0xC035001A,
+ MD_NTSTATUS_WIN_STATUS_HV_NO_DATA = 0xC035001B,
+ MD_NTSTATUS_WIN_STATUS_HV_INACTIVE = 0xC035001C,
+ MD_NTSTATUS_WIN_STATUS_HV_NO_RESOURCES = 0xC035001D,
+ MD_NTSTATUS_WIN_STATUS_HV_FEATURE_UNAVAILABLE = 0xC035001E,
+ MD_NTSTATUS_WIN_STATUS_HV_INSUFFICIENT_BUFFER = 0xC0350033,
+ MD_NTSTATUS_WIN_STATUS_HV_INSUFFICIENT_DEVICE_DOMAINS = 0xC0350038,
+ MD_NTSTATUS_WIN_STATUS_HV_CPUID_FEATURE_VALIDATION_ERROR = 0xC035003C,
+ MD_NTSTATUS_WIN_STATUS_HV_CPUID_XSAVE_FEATURE_VALIDATION_ERROR = 0xC035003D,
+ MD_NTSTATUS_WIN_STATUS_HV_PROCESSOR_STARTUP_TIMEOUT = 0xC035003E,
+ MD_NTSTATUS_WIN_STATUS_HV_SMX_ENABLED = 0xC035003F,
+ MD_NTSTATUS_WIN_STATUS_HV_INVALID_LP_INDEX = 0xC0350041,
+ MD_NTSTATUS_WIN_STATUS_HV_INVALID_REGISTER_VALUE = 0xC0350050,
+ MD_NTSTATUS_WIN_STATUS_HV_INVALID_VTL_STATE = 0xC0350051,
+ MD_NTSTATUS_WIN_STATUS_HV_NX_NOT_DETECTED = 0xC0350055,
+ MD_NTSTATUS_WIN_STATUS_HV_INVALID_DEVICE_ID = 0xC0350057,
+ MD_NTSTATUS_WIN_STATUS_HV_INVALID_DEVICE_STATE = 0xC0350058,
+ MD_NTSTATUS_WIN_STATUS_HV_PAGE_REQUEST_INVALID = 0xC0350060,
+ MD_NTSTATUS_WIN_STATUS_HV_INVALID_CPU_GROUP_ID = 0xC035006F,
+ MD_NTSTATUS_WIN_STATUS_HV_INVALID_CPU_GROUP_STATE = 0xC0350070,
+ MD_NTSTATUS_WIN_STATUS_HV_OPERATION_FAILED = 0xC0350071,
+ MD_NTSTATUS_WIN_STATUS_HV_NOT_ALLOWED_WITH_NESTED_VIRT_ACTIVE = 0xC0350072,
+ MD_NTSTATUS_WIN_STATUS_HV_INSUFFICIENT_ROOT_MEMORY = 0xC0350073,
+ MD_NTSTATUS_WIN_STATUS_HV_EVENT_BUFFER_ALREADY_FREED = 0xC0350074,
+ MD_NTSTATUS_WIN_STATUS_HV_INSUFFICIENT_CONTIGUOUS_MEMORY = 0xC0350075,
+ MD_NTSTATUS_WIN_STATUS_HV_NOT_PRESENT = 0xC0351000,
+ MD_NTSTATUS_WIN_STATUS_IPSEC_BAD_SPI = 0xC0360001,
+ MD_NTSTATUS_WIN_STATUS_IPSEC_SA_LIFETIME_EXPIRED = 0xC0360002,
+ MD_NTSTATUS_WIN_STATUS_IPSEC_WRONG_SA = 0xC0360003,
+ MD_NTSTATUS_WIN_STATUS_IPSEC_REPLAY_CHECK_FAILED = 0xC0360004,
+ MD_NTSTATUS_WIN_STATUS_IPSEC_INVALID_PACKET = 0xC0360005,
+ MD_NTSTATUS_WIN_STATUS_IPSEC_INTEGRITY_CHECK_FAILED = 0xC0360006,
+ MD_NTSTATUS_WIN_STATUS_IPSEC_CLEAR_TEXT_DROP = 0xC0360007,
+ MD_NTSTATUS_WIN_STATUS_IPSEC_AUTH_FIREWALL_DROP = 0xC0360008,
+ MD_NTSTATUS_WIN_STATUS_IPSEC_THROTTLE_DROP = 0xC0360009,
+ MD_NTSTATUS_WIN_STATUS_IPSEC_DOSP_BLOCK = 0xC0368000,
+ MD_NTSTATUS_WIN_STATUS_IPSEC_DOSP_RECEIVED_MULTICAST = 0xC0368001,
+ MD_NTSTATUS_WIN_STATUS_IPSEC_DOSP_INVALID_PACKET = 0xC0368002,
+ MD_NTSTATUS_WIN_STATUS_IPSEC_DOSP_STATE_LOOKUP_FAILED = 0xC0368003,
+ MD_NTSTATUS_WIN_STATUS_IPSEC_DOSP_MAX_ENTRIES = 0xC0368004,
+ MD_NTSTATUS_WIN_STATUS_IPSEC_DOSP_KEYMOD_NOT_ALLOWED = 0xC0368005,
+ MD_NTSTATUS_WIN_STATUS_IPSEC_DOSP_MAX_PER_IP_RATELIMIT_QUEUES = 0xC0368006,
+ MD_NTSTATUS_WIN_STATUS_VID_DUPLICATE_HANDLER = 0xC0370001,
+ MD_NTSTATUS_WIN_STATUS_VID_TOO_MANY_HANDLERS = 0xC0370002,
+ MD_NTSTATUS_WIN_STATUS_VID_QUEUE_FULL = 0xC0370003,
+ MD_NTSTATUS_WIN_STATUS_VID_HANDLER_NOT_PRESENT = 0xC0370004,
+ MD_NTSTATUS_WIN_STATUS_VID_INVALID_OBJECT_NAME = 0xC0370005,
+ MD_NTSTATUS_WIN_STATUS_VID_PARTITION_NAME_TOO_LONG = 0xC0370006,
+ MD_NTSTATUS_WIN_STATUS_VID_MESSAGE_QUEUE_NAME_TOO_LONG = 0xC0370007,
+ MD_NTSTATUS_WIN_STATUS_VID_PARTITION_ALREADY_EXISTS = 0xC0370008,
+ MD_NTSTATUS_WIN_STATUS_VID_PARTITION_DOES_NOT_EXIST = 0xC0370009,
+ MD_NTSTATUS_WIN_STATUS_VID_PARTITION_NAME_NOT_FOUND = 0xC037000A,
+ MD_NTSTATUS_WIN_STATUS_VID_MESSAGE_QUEUE_ALREADY_EXISTS = 0xC037000B,
+ MD_NTSTATUS_WIN_STATUS_VID_EXCEEDED_MBP_ENTRY_MAP_LIMIT = 0xC037000C,
+ MD_NTSTATUS_WIN_STATUS_VID_MB_STILL_REFERENCED = 0xC037000D,
+ MD_NTSTATUS_WIN_STATUS_VID_CHILD_GPA_PAGE_SET_CORRUPTED = 0xC037000E,
+ MD_NTSTATUS_WIN_STATUS_VID_INVALID_NUMA_SETTINGS = 0xC037000F,
+ MD_NTSTATUS_WIN_STATUS_VID_INVALID_NUMA_NODE_INDEX = 0xC0370010,
+ MD_NTSTATUS_WIN_STATUS_VID_NOTIFICATION_QUEUE_ALREADY_ASSOCIATED = 0xC0370011,
+ MD_NTSTATUS_WIN_STATUS_VID_INVALID_MEMORY_BLOCK_HANDLE = 0xC0370012,
+ MD_NTSTATUS_WIN_STATUS_VID_PAGE_RANGE_OVERFLOW = 0xC0370013,
+ MD_NTSTATUS_WIN_STATUS_VID_INVALID_MESSAGE_QUEUE_HANDLE = 0xC0370014,
+ MD_NTSTATUS_WIN_STATUS_VID_INVALID_GPA_RANGE_HANDLE = 0xC0370015,
+ MD_NTSTATUS_WIN_STATUS_VID_NO_MEMORY_BLOCK_NOTIFICATION_QUEUE = 0xC0370016,
+ MD_NTSTATUS_WIN_STATUS_VID_MEMORY_BLOCK_LOCK_COUNT_EXCEEDED = 0xC0370017,
+ MD_NTSTATUS_WIN_STATUS_VID_INVALID_PPM_HANDLE = 0xC0370018,
+ MD_NTSTATUS_WIN_STATUS_VID_MBPS_ARE_LOCKED = 0xC0370019,
+ MD_NTSTATUS_WIN_STATUS_VID_MESSAGE_QUEUE_CLOSED = 0xC037001A,
+ MD_NTSTATUS_WIN_STATUS_VID_VIRTUAL_PROCESSOR_LIMIT_EXCEEDED = 0xC037001B,
+ MD_NTSTATUS_WIN_STATUS_VID_STOP_PENDING = 0xC037001C,
+ MD_NTSTATUS_WIN_STATUS_VID_INVALID_PROCESSOR_STATE = 0xC037001D,
+ MD_NTSTATUS_WIN_STATUS_VID_EXCEEDED_KM_CONTEXT_COUNT_LIMIT = 0xC037001E,
+ MD_NTSTATUS_WIN_STATUS_VID_KM_INTERFACE_ALREADY_INITIALIZED = 0xC037001F,
+ MD_NTSTATUS_WIN_STATUS_VID_MB_PROPERTY_ALREADY_SET_RESET = 0xC0370020,
+ MD_NTSTATUS_WIN_STATUS_VID_MMIO_RANGE_DESTROYED = 0xC0370021,
+ MD_NTSTATUS_WIN_STATUS_VID_INVALID_CHILD_GPA_PAGE_SET = 0xC0370022,
+ MD_NTSTATUS_WIN_STATUS_VID_RESERVE_PAGE_SET_IS_BEING_USED = 0xC0370023,
+ MD_NTSTATUS_WIN_STATUS_VID_RESERVE_PAGE_SET_TOO_SMALL = 0xC0370024,
+ MD_NTSTATUS_WIN_STATUS_VID_MBP_ALREADY_LOCKED_USING_RESERVED_PAGE = 0xC0370025,
+ MD_NTSTATUS_WIN_STATUS_VID_MBP_COUNT_EXCEEDED_LIMIT = 0xC0370026,
+ MD_NTSTATUS_WIN_STATUS_VID_SAVED_STATE_CORRUPT = 0xC0370027,
+ MD_NTSTATUS_WIN_STATUS_VID_SAVED_STATE_UNRECOGNIZED_ITEM = 0xC0370028,
+ MD_NTSTATUS_WIN_STATUS_VID_SAVED_STATE_INCOMPATIBLE = 0xC0370029,
+ MD_NTSTATUS_WIN_STATUS_VID_VTL_ACCESS_DENIED = 0xC037002A,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_DATABASE_FULL = 0xC0380001,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_CONFIGURATION_CORRUPTED = 0xC0380002,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_CONFIGURATION_NOT_IN_SYNC = 0xC0380003,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_PACK_CONFIG_UPDATE_FAILED = 0xC0380004,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_CONTAINS_NON_SIMPLE_VOLUME = 0xC0380005,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_DUPLICATE = 0xC0380006,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_DYNAMIC = 0xC0380007,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_ID_INVALID = 0xC0380008,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_INVALID = 0xC0380009,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_LAST_VOTER = 0xC038000A,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_LAYOUT_INVALID = 0xC038000B,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_LAYOUT_NON_BASIC_BETWEEN_BASIC_PARTITIONS = 0xC038000C,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_LAYOUT_NOT_CYLINDER_ALIGNED = 0xC038000D,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_LAYOUT_PARTITIONS_TOO_SMALL = 0xC038000E,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_LAYOUT_PRIMARY_BETWEEN_LOGICAL_PARTITIONS = 0xC038000F,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_LAYOUT_TOO_MANY_PARTITIONS = 0xC0380010,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_MISSING = 0xC0380011,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_NOT_EMPTY = 0xC0380012,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_NOT_ENOUGH_SPACE = 0xC0380013,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_REVECTORING_FAILED = 0xC0380014,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_SECTOR_SIZE_INVALID = 0xC0380015,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_SET_NOT_CONTAINED = 0xC0380016,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_USED_BY_MULTIPLE_MEMBERS = 0xC0380017,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_USED_BY_MULTIPLE_PLEXES = 0xC0380018,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_DYNAMIC_DISK_NOT_SUPPORTED = 0xC0380019,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_EXTENT_ALREADY_USED = 0xC038001A,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_EXTENT_NOT_CONTIGUOUS = 0xC038001B,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_EXTENT_NOT_IN_PUBLIC_REGION = 0xC038001C,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_EXTENT_NOT_SECTOR_ALIGNED = 0xC038001D,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_EXTENT_OVERLAPS_EBR_PARTITION = 0xC038001E,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_EXTENT_VOLUME_LENGTHS_DO_NOT_MATCH = 0xC038001F,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_FAULT_TOLERANT_NOT_SUPPORTED = 0xC0380020,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_INTERLEAVE_LENGTH_INVALID = 0xC0380021,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_MAXIMUM_REGISTERED_USERS = 0xC0380022,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_MEMBER_IN_SYNC = 0xC0380023,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_MEMBER_INDEX_DUPLICATE = 0xC0380024,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_MEMBER_INDEX_INVALID = 0xC0380025,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_MEMBER_MISSING = 0xC0380026,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_MEMBER_NOT_DETACHED = 0xC0380027,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_MEMBER_REGENERATING = 0xC0380028,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_ALL_DISKS_FAILED = 0xC0380029,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_NO_REGISTERED_USERS = 0xC038002A,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_NO_SUCH_USER = 0xC038002B,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_NOTIFICATION_RESET = 0xC038002C,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_NUMBER_OF_MEMBERS_INVALID = 0xC038002D,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_NUMBER_OF_PLEXES_INVALID = 0xC038002E,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_PACK_DUPLICATE = 0xC038002F,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_PACK_ID_INVALID = 0xC0380030,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_PACK_INVALID = 0xC0380031,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_PACK_NAME_INVALID = 0xC0380032,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_PACK_OFFLINE = 0xC0380033,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_PACK_HAS_QUORUM = 0xC0380034,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_PACK_WITHOUT_QUORUM = 0xC0380035,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_PARTITION_STYLE_INVALID = 0xC0380036,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_PARTITION_UPDATE_FAILED = 0xC0380037,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_PLEX_IN_SYNC = 0xC0380038,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_PLEX_INDEX_DUPLICATE = 0xC0380039,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_PLEX_INDEX_INVALID = 0xC038003A,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_PLEX_LAST_ACTIVE = 0xC038003B,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_PLEX_MISSING = 0xC038003C,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_PLEX_REGENERATING = 0xC038003D,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_PLEX_TYPE_INVALID = 0xC038003E,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_PLEX_NOT_RAID5 = 0xC038003F,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_PLEX_NOT_SIMPLE = 0xC0380040,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_STRUCTURE_SIZE_INVALID = 0xC0380041,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_TOO_MANY_NOTIFICATION_REQUESTS = 0xC0380042,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_TRANSACTION_IN_PROGRESS = 0xC0380043,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_UNEXPECTED_DISK_LAYOUT_CHANGE = 0xC0380044,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_VOLUME_CONTAINS_MISSING_DISK = 0xC0380045,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_VOLUME_ID_INVALID = 0xC0380046,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_VOLUME_LENGTH_INVALID = 0xC0380047,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_VOLUME_LENGTH_NOT_SECTOR_SIZE_MULTIPLE = 0xC0380048,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_VOLUME_NOT_MIRRORED = 0xC0380049,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_VOLUME_NOT_RETAINED = 0xC038004A,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_VOLUME_OFFLINE = 0xC038004B,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_VOLUME_RETAINED = 0xC038004C,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_NUMBER_OF_EXTENTS_INVALID = 0xC038004D,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_DIFFERENT_SECTOR_SIZE = 0xC038004E,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_BAD_BOOT_DISK = 0xC038004F,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_PACK_CONFIG_OFFLINE = 0xC0380050,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_PACK_CONFIG_ONLINE = 0xC0380051,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_NOT_PRIMARY_PACK = 0xC0380052,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_PACK_LOG_UPDATE_FAILED = 0xC0380053,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_NUMBER_OF_DISKS_IN_PLEX_INVALID = 0xC0380054,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_NUMBER_OF_DISKS_IN_MEMBER_INVALID = 0xC0380055,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_VOLUME_MIRRORED = 0xC0380056,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_PLEX_NOT_SIMPLE_SPANNED = 0xC0380057,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_NO_VALID_LOG_COPIES = 0xC0380058,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_PRIMARY_PACK_PRESENT = 0xC0380059,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_NUMBER_OF_DISKS_INVALID = 0xC038005A,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_MIRROR_NOT_SUPPORTED = 0xC038005B,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_RAID5_NOT_SUPPORTED = 0xC038005C,
+ MD_NTSTATUS_WIN_STATUS_BCD_TOO_MANY_ELEMENTS = 0xC0390002,
+ MD_NTSTATUS_WIN_STATUS_VHD_DRIVE_FOOTER_MISSING = 0xC03A0001,
+ MD_NTSTATUS_WIN_STATUS_VHD_DRIVE_FOOTER_CHECKSUM_MISMATCH = 0xC03A0002,
+ MD_NTSTATUS_WIN_STATUS_VHD_DRIVE_FOOTER_CORRUPT = 0xC03A0003,
+ MD_NTSTATUS_WIN_STATUS_VHD_FORMAT_UNKNOWN = 0xC03A0004,
+ MD_NTSTATUS_WIN_STATUS_VHD_FORMAT_UNSUPPORTED_VERSION = 0xC03A0005,
+ MD_NTSTATUS_WIN_STATUS_VHD_SPARSE_HEADER_CHECKSUM_MISMATCH = 0xC03A0006,
+ MD_NTSTATUS_WIN_STATUS_VHD_SPARSE_HEADER_UNSUPPORTED_VERSION = 0xC03A0007,
+ MD_NTSTATUS_WIN_STATUS_VHD_SPARSE_HEADER_CORRUPT = 0xC03A0008,
+ MD_NTSTATUS_WIN_STATUS_VHD_BLOCK_ALLOCATION_FAILURE = 0xC03A0009,
+ MD_NTSTATUS_WIN_STATUS_VHD_BLOCK_ALLOCATION_TABLE_CORRUPT = 0xC03A000A,
+ MD_NTSTATUS_WIN_STATUS_VHD_INVALID_BLOCK_SIZE = 0xC03A000B,
+ MD_NTSTATUS_WIN_STATUS_VHD_BITMAP_MISMATCH = 0xC03A000C,
+ MD_NTSTATUS_WIN_STATUS_VHD_PARENT_VHD_NOT_FOUND = 0xC03A000D,
+ MD_NTSTATUS_WIN_STATUS_VHD_CHILD_PARENT_ID_MISMATCH = 0xC03A000E,
+ MD_NTSTATUS_WIN_STATUS_VHD_CHILD_PARENT_TIMESTAMP_MISMATCH = 0xC03A000F,
+ MD_NTSTATUS_WIN_STATUS_VHD_METADATA_READ_FAILURE = 0xC03A0010,
+ MD_NTSTATUS_WIN_STATUS_VHD_METADATA_WRITE_FAILURE = 0xC03A0011,
+ MD_NTSTATUS_WIN_STATUS_VHD_INVALID_SIZE = 0xC03A0012,
+ MD_NTSTATUS_WIN_STATUS_VHD_INVALID_FILE_SIZE = 0xC03A0013,
+ MD_NTSTATUS_WIN_STATUS_VIRTDISK_PROVIDER_NOT_FOUND = 0xC03A0014,
+ MD_NTSTATUS_WIN_STATUS_VIRTDISK_NOT_VIRTUAL_DISK = 0xC03A0015,
+ MD_NTSTATUS_WIN_STATUS_VHD_PARENT_VHD_ACCESS_DENIED = 0xC03A0016,
+ MD_NTSTATUS_WIN_STATUS_VHD_CHILD_PARENT_SIZE_MISMATCH = 0xC03A0017,
+ MD_NTSTATUS_WIN_STATUS_VHD_DIFFERENCING_CHAIN_CYCLE_DETECTED = 0xC03A0018,
+ MD_NTSTATUS_WIN_STATUS_VHD_DIFFERENCING_CHAIN_ERROR_IN_PARENT = 0xC03A0019,
+ MD_NTSTATUS_WIN_STATUS_VIRTUAL_DISK_LIMITATION = 0xC03A001A,
+ MD_NTSTATUS_WIN_STATUS_VHD_INVALID_TYPE = 0xC03A001B,
+ MD_NTSTATUS_WIN_STATUS_VHD_INVALID_STATE = 0xC03A001C,
+ MD_NTSTATUS_WIN_STATUS_VIRTDISK_UNSUPPORTED_DISK_SECTOR_SIZE = 0xC03A001D,
+ MD_NTSTATUS_WIN_STATUS_VIRTDISK_DISK_ALREADY_OWNED = 0xC03A001E,
+ MD_NTSTATUS_WIN_STATUS_VIRTDISK_DISK_ONLINE_AND_WRITABLE = 0xC03A001F,
+ MD_NTSTATUS_WIN_STATUS_CTLOG_TRACKING_NOT_INITIALIZED = 0xC03A0020,
+ MD_NTSTATUS_WIN_STATUS_CTLOG_LOGFILE_SIZE_EXCEEDED_MAXSIZE = 0xC03A0021,
+ MD_NTSTATUS_WIN_STATUS_CTLOG_VHD_CHANGED_OFFLINE = 0xC03A0022,
+ MD_NTSTATUS_WIN_STATUS_CTLOG_INVALID_TRACKING_STATE = 0xC03A0023,
+ MD_NTSTATUS_WIN_STATUS_CTLOG_INCONSISTENT_TRACKING_FILE = 0xC03A0024,
+ MD_NTSTATUS_WIN_STATUS_VHD_METADATA_FULL = 0xC03A0028,
+ MD_NTSTATUS_WIN_STATUS_VHD_INVALID_CHANGE_TRACKING_ID = 0xC03A0029,
+ MD_NTSTATUS_WIN_STATUS_VHD_CHANGE_TRACKING_DISABLED = 0xC03A002A,
+ MD_NTSTATUS_WIN_STATUS_VHD_MISSING_CHANGE_TRACKING_INFORMATION = 0xC03A0030,
+ MD_NTSTATUS_WIN_STATUS_VHD_RESIZE_WOULD_TRUNCATE_DATA = 0xC03A0031,
+ MD_NTSTATUS_WIN_STATUS_VHD_COULD_NOT_COMPUTE_MINIMUM_VIRTUAL_SIZE = 0xC03A0032,
+ MD_NTSTATUS_WIN_STATUS_VHD_ALREADY_AT_OR_BELOW_MINIMUM_VIRTUAL_SIZE = 0xC03A0033,
+ MD_NTSTATUS_WIN_STATUS_RKF_KEY_NOT_FOUND = 0xC0400001,
+ MD_NTSTATUS_WIN_STATUS_RKF_DUPLICATE_KEY = 0xC0400002,
+ MD_NTSTATUS_WIN_STATUS_RKF_BLOB_FULL = 0xC0400003,
+ MD_NTSTATUS_WIN_STATUS_RKF_STORE_FULL = 0xC0400004,
+ MD_NTSTATUS_WIN_STATUS_RKF_FILE_BLOCKED = 0xC0400005,
+ MD_NTSTATUS_WIN_STATUS_RKF_ACTIVE_KEY = 0xC0400006,
+ MD_NTSTATUS_WIN_STATUS_RDBSS_RESTART_OPERATION = 0xC0410001,
+ MD_NTSTATUS_WIN_STATUS_RDBSS_CONTINUE_OPERATION = 0xC0410002,
+ MD_NTSTATUS_WIN_STATUS_RDBSS_POST_OPERATION = 0xC0410003,
+ MD_NTSTATUS_WIN_STATUS_RDBSS_RETRY_LOOKUP = 0xC0410004,
+ MD_NTSTATUS_WIN_STATUS_BTH_ATT_INVALID_HANDLE = 0xC0420001,
+ MD_NTSTATUS_WIN_STATUS_BTH_ATT_READ_NOT_PERMITTED = 0xC0420002,
+ MD_NTSTATUS_WIN_STATUS_BTH_ATT_WRITE_NOT_PERMITTED = 0xC0420003,
+ MD_NTSTATUS_WIN_STATUS_BTH_ATT_INVALID_PDU = 0xC0420004,
+ MD_NTSTATUS_WIN_STATUS_BTH_ATT_INSUFFICIENT_AUTHENTICATION = 0xC0420005,
+ MD_NTSTATUS_WIN_STATUS_BTH_ATT_REQUEST_NOT_SUPPORTED = 0xC0420006,
+ MD_NTSTATUS_WIN_STATUS_BTH_ATT_INVALID_OFFSET = 0xC0420007,
+ MD_NTSTATUS_WIN_STATUS_BTH_ATT_INSUFFICIENT_AUTHORIZATION = 0xC0420008,
+ MD_NTSTATUS_WIN_STATUS_BTH_ATT_PREPARE_QUEUE_FULL = 0xC0420009,
+ MD_NTSTATUS_WIN_STATUS_BTH_ATT_ATTRIBUTE_NOT_FOUND = 0xC042000A,
+ MD_NTSTATUS_WIN_STATUS_BTH_ATT_ATTRIBUTE_NOT_LONG = 0xC042000B,
+ MD_NTSTATUS_WIN_STATUS_BTH_ATT_INSUFFICIENT_ENCRYPTION_KEY_SIZE = 0xC042000C,
+ MD_NTSTATUS_WIN_STATUS_BTH_ATT_INVALID_ATTRIBUTE_VALUE_LENGTH = 0xC042000D,
+ MD_NTSTATUS_WIN_STATUS_BTH_ATT_UNLIKELY = 0xC042000E,
+ MD_NTSTATUS_WIN_STATUS_BTH_ATT_INSUFFICIENT_ENCRYPTION = 0xC042000F,
+ MD_NTSTATUS_WIN_STATUS_BTH_ATT_UNSUPPORTED_GROUP_TYPE = 0xC0420010,
+ MD_NTSTATUS_WIN_STATUS_BTH_ATT_INSUFFICIENT_RESOURCES = 0xC0420011,
+ MD_NTSTATUS_WIN_STATUS_BTH_ATT_UNKNOWN_ERROR = 0xC0421000,
+ MD_NTSTATUS_WIN_STATUS_SECUREBOOT_ROLLBACK_DETECTED = 0xC0430001,
+ MD_NTSTATUS_WIN_STATUS_SECUREBOOT_POLICY_VIOLATION = 0xC0430002,
+ MD_NTSTATUS_WIN_STATUS_SECUREBOOT_INVALID_POLICY = 0xC0430003,
+ MD_NTSTATUS_WIN_STATUS_SECUREBOOT_POLICY_PUBLISHER_NOT_FOUND = 0xC0430004,
+ MD_NTSTATUS_WIN_STATUS_SECUREBOOT_POLICY_NOT_SIGNED = 0xC0430005,
+ MD_NTSTATUS_WIN_STATUS_SECUREBOOT_FILE_REPLACED = 0xC0430007,
+ MD_NTSTATUS_WIN_STATUS_SECUREBOOT_POLICY_NOT_AUTHORIZED = 0xC0430008,
+ MD_NTSTATUS_WIN_STATUS_SECUREBOOT_POLICY_UNKNOWN = 0xC0430009,
+ MD_NTSTATUS_WIN_STATUS_SECUREBOOT_POLICY_MISSING_ANTIROLLBACKVERSION = 0xC043000A,
+ MD_NTSTATUS_WIN_STATUS_SECUREBOOT_PLATFORM_ID_MISMATCH = 0xC043000B,
+ MD_NTSTATUS_WIN_STATUS_SECUREBOOT_POLICY_ROLLBACK_DETECTED = 0xC043000C,
+ MD_NTSTATUS_WIN_STATUS_SECUREBOOT_POLICY_UPGRADE_MISMATCH = 0xC043000D,
+ MD_NTSTATUS_WIN_STATUS_SECUREBOOT_REQUIRED_POLICY_FILE_MISSING = 0xC043000E,
+ MD_NTSTATUS_WIN_STATUS_SECUREBOOT_NOT_BASE_POLICY = 0xC043000F,
+ MD_NTSTATUS_WIN_STATUS_SECUREBOOT_NOT_SUPPLEMENTAL_POLICY = 0xC0430010,
+ MD_NTSTATUS_WIN_STATUS_AUDIO_ENGINE_NODE_NOT_FOUND = 0xC0440001,
+ MD_NTSTATUS_WIN_STATUS_HDAUDIO_EMPTY_CONNECTION_LIST = 0xC0440002,
+ MD_NTSTATUS_WIN_STATUS_HDAUDIO_CONNECTION_LIST_NOT_SUPPORTED = 0xC0440003,
+ MD_NTSTATUS_WIN_STATUS_HDAUDIO_NO_LOGICAL_DEVICES_CREATED = 0xC0440004,
+ MD_NTSTATUS_WIN_STATUS_HDAUDIO_NULL_LINKED_LIST_ENTRY = 0xC0440005,
+ MD_NTSTATUS_WIN_STATUS_VSM_NOT_INITIALIZED = 0xC0450000,
+ MD_NTSTATUS_WIN_STATUS_VSM_DMA_PROTECTION_NOT_IN_USE = 0xC0450001,
+ MD_NTSTATUS_WIN_STATUS_VOLSNAP_BOOTFILE_NOT_VALID = 0xC0500003,
+ MD_NTSTATUS_WIN_STATUS_VOLSNAP_ACTIVATION_TIMEOUT = 0xC0500004,
+ MD_NTSTATUS_WIN_STATUS_IO_PREEMPTED = 0xC0510001,
+ MD_NTSTATUS_WIN_STATUS_SVHDX_ERROR_STORED = 0xC05C0000,
+ MD_NTSTATUS_WIN_STATUS_SVHDX_ERROR_NOT_AVAILABLE = 0xC05CFF00,
+ MD_NTSTATUS_WIN_STATUS_SVHDX_UNIT_ATTENTION_AVAILABLE = 0xC05CFF01,
+ MD_NTSTATUS_WIN_STATUS_SVHDX_UNIT_ATTENTION_CAPACITY_DATA_CHANGED = 0xC05CFF02,
+ MD_NTSTATUS_WIN_STATUS_SVHDX_UNIT_ATTENTION_RESERVATIONS_PREEMPTED = 0xC05CFF03,
+ MD_NTSTATUS_WIN_STATUS_SVHDX_UNIT_ATTENTION_RESERVATIONS_RELEASED = 0xC05CFF04,
+ MD_NTSTATUS_WIN_STATUS_SVHDX_UNIT_ATTENTION_REGISTRATIONS_PREEMPTED = 0xC05CFF05,
+ MD_NTSTATUS_WIN_STATUS_SVHDX_UNIT_ATTENTION_OPERATING_DEFINITION_CHANGED = 0xC05CFF06,
+ MD_NTSTATUS_WIN_STATUS_SVHDX_RESERVATION_CONFLICT = 0xC05CFF07,
+ MD_NTSTATUS_WIN_STATUS_SVHDX_WRONG_FILE_TYPE = 0xC05CFF08,
+ MD_NTSTATUS_WIN_STATUS_SVHDX_VERSION_MISMATCH = 0xC05CFF09,
+ MD_NTSTATUS_WIN_STATUS_VHD_SHARED = 0xC05CFF0A,
+ MD_NTSTATUS_WIN_STATUS_SVHDX_NO_INITIATOR = 0xC05CFF0B,
+ MD_NTSTATUS_WIN_STATUS_VHDSET_BACKING_STORAGE_NOT_FOUND = 0xC05CFF0C,
+ MD_NTSTATUS_WIN_STATUS_SMB_NO_PREAUTH_INTEGRITY_HASH_OVERLAP = 0xC05D0000,
+ MD_NTSTATUS_WIN_STATUS_SMB_BAD_CLUSTER_DIALECT = 0xC05D0001,
+ MD_NTSTATUS_WIN_STATUS_SMB_GUEST_LOGON_BLOCKED = 0xC05D0002,
+ MD_NTSTATUS_WIN_STATUS_SPACES_FAULT_DOMAIN_TYPE_INVALID = 0xC0E70001,
+ MD_NTSTATUS_WIN_STATUS_SPACES_RESILIENCY_TYPE_INVALID = 0xC0E70003,
+ MD_NTSTATUS_WIN_STATUS_SPACES_DRIVE_SECTOR_SIZE_INVALID = 0xC0E70004,
+ MD_NTSTATUS_WIN_STATUS_SPACES_DRIVE_REDUNDANCY_INVALID = 0xC0E70006,
+ MD_NTSTATUS_WIN_STATUS_SPACES_NUMBER_OF_DATA_COPIES_INVALID = 0xC0E70007,
+ MD_NTSTATUS_WIN_STATUS_SPACES_INTERLEAVE_LENGTH_INVALID = 0xC0E70009,
+ MD_NTSTATUS_WIN_STATUS_SPACES_NUMBER_OF_COLUMNS_INVALID = 0xC0E7000A,
+ MD_NTSTATUS_WIN_STATUS_SPACES_NOT_ENOUGH_DRIVES = 0xC0E7000B,
+ MD_NTSTATUS_WIN_STATUS_SPACES_EXTENDED_ERROR = 0xC0E7000C,
+ MD_NTSTATUS_WIN_STATUS_SPACES_PROVISIONING_TYPE_INVALID = 0xC0E7000D,
+ MD_NTSTATUS_WIN_STATUS_SPACES_ALLOCATION_SIZE_INVALID = 0xC0E7000E,
+ MD_NTSTATUS_WIN_STATUS_SPACES_ENCLOSURE_AWARE_INVALID = 0xC0E7000F,
+ MD_NTSTATUS_WIN_STATUS_SPACES_WRITE_CACHE_SIZE_INVALID = 0xC0E70010,
+ MD_NTSTATUS_WIN_STATUS_SPACES_NUMBER_OF_GROUPS_INVALID = 0xC0E70011,
+ MD_NTSTATUS_WIN_STATUS_SPACES_DRIVE_OPERATIONAL_STATE_INVALID = 0xC0E70012,
+ MD_NTSTATUS_WIN_STATUS_SPACES_UPDATE_COLUMN_STATE = 0xC0E70013,
+ MD_NTSTATUS_WIN_STATUS_SPACES_MAP_REQUIRED = 0xC0E70014,
+ MD_NTSTATUS_WIN_STATUS_SPACES_UNSUPPORTED_VERSION = 0xC0E70015,
+ MD_NTSTATUS_WIN_STATUS_SPACES_CORRUPT_METADATA = 0xC0E70016,
+ MD_NTSTATUS_WIN_STATUS_SPACES_DRT_FULL = 0xC0E70017,
+ MD_NTSTATUS_WIN_STATUS_SPACES_INCONSISTENCY = 0xC0E70018,
+ MD_NTSTATUS_WIN_STATUS_SPACES_LOG_NOT_READY = 0xC0E70019,
+ MD_NTSTATUS_WIN_STATUS_SPACES_NO_REDUNDANCY = 0xC0E7001A,
+ MD_NTSTATUS_WIN_STATUS_SPACES_DRIVE_NOT_READY = 0xC0E7001B,
+ MD_NTSTATUS_WIN_STATUS_SPACES_DRIVE_SPLIT = 0xC0E7001C,
+ MD_NTSTATUS_WIN_STATUS_SPACES_DRIVE_LOST_DATA = 0xC0E7001D,
+ MD_NTSTATUS_WIN_STATUS_SPACES_ENTRY_INCOMPLETE = 0xC0E7001E,
+ MD_NTSTATUS_WIN_STATUS_SPACES_ENTRY_INVALID = 0xC0E7001F,
+ MD_NTSTATUS_WIN_STATUS_SPACES_MARK_DIRTY = 0xC0E70020,
+ MD_NTSTATUS_WIN_STATUS_SECCORE_INVALID_COMMAND = 0xC0E80000,
+ MD_NTSTATUS_WIN_STATUS_SYSTEM_INTEGRITY_ROLLBACK_DETECTED = 0xC0E90001,
+ MD_NTSTATUS_WIN_STATUS_SYSTEM_INTEGRITY_POLICY_VIOLATION = 0xC0E90002,
+ MD_NTSTATUS_WIN_STATUS_SYSTEM_INTEGRITY_INVALID_POLICY = 0xC0E90003,
+ MD_NTSTATUS_WIN_STATUS_SYSTEM_INTEGRITY_POLICY_NOT_SIGNED = 0xC0E90004,
+ MD_NTSTATUS_WIN_STATUS_SYSTEM_INTEGRITY_TOO_MANY_POLICIES = 0xC0E90005,
+ MD_NTSTATUS_WIN_STATUS_SYSTEM_INTEGRITY_SUPPLEMENTAL_POLICY_NOT_AUTHORIZED = 0xC0E90006,
+ MD_NTSTATUS_WIN_STATUS_NO_APPLICABLE_APP_LICENSES_FOUND = 0xC0EA0001,
+ MD_NTSTATUS_WIN_STATUS_CLIP_LICENSE_NOT_FOUND = 0xC0EA0002,
+ MD_NTSTATUS_WIN_STATUS_CLIP_DEVICE_LICENSE_MISSING = 0xC0EA0003,
+ MD_NTSTATUS_WIN_STATUS_CLIP_LICENSE_INVALID_SIGNATURE = 0xC0EA0004,
+ MD_NTSTATUS_WIN_STATUS_CLIP_KEYHOLDER_LICENSE_MISSING_OR_INVALID = 0xC0EA0005,
+ MD_NTSTATUS_WIN_STATUS_CLIP_LICENSE_EXPIRED = 0xC0EA0006,
+ MD_NTSTATUS_WIN_STATUS_CLIP_LICENSE_SIGNED_BY_UNKNOWN_SOURCE = 0xC0EA0007,
+ MD_NTSTATUS_WIN_STATUS_CLIP_LICENSE_NOT_SIGNED = 0xC0EA0008,
+ MD_NTSTATUS_WIN_STATUS_CLIP_LICENSE_HARDWARE_ID_OUT_OF_TOLERANCE = 0xC0EA0009,
+ MD_NTSTATUS_WIN_STATUS_CLIP_LICENSE_DEVICE_ID_MISMATCH = 0xC0EA000A,
+ MD_NTSTATUS_WIN_STATUS_PLATFORM_MANIFEST_NOT_AUTHORIZED = 0xC0EB0001,
+ MD_NTSTATUS_WIN_STATUS_PLATFORM_MANIFEST_INVALID = 0xC0EB0002,
+ MD_NTSTATUS_WIN_STATUS_PLATFORM_MANIFEST_FILE_NOT_AUTHORIZED = 0xC0EB0003,
+ MD_NTSTATUS_WIN_STATUS_PLATFORM_MANIFEST_CATALOG_NOT_AUTHORIZED = 0xC0EB0004,
+ MD_NTSTATUS_WIN_STATUS_PLATFORM_MANIFEST_BINARY_ID_NOT_FOUND = 0xC0EB0005,
+ MD_NTSTATUS_WIN_STATUS_PLATFORM_MANIFEST_NOT_ACTIVE = 0xC0EB0006,
+ MD_NTSTATUS_WIN_STATUS_PLATFORM_MANIFEST_NOT_SIGNED = 0xC0EB0007,
+ MD_NTSTATUS_WIN_STATUS_APPEXEC_CONDITION_NOT_SATISFIED = 0xC0EC0000,
+ MD_NTSTATUS_WIN_STATUS_APPEXEC_HANDLE_INVALIDATED = 0xC0EC0001,
+ MD_NTSTATUS_WIN_STATUS_APPEXEC_INVALID_HOST_GENERATION = 0xC0EC0002,
+ MD_NTSTATUS_WIN_STATUS_APPEXEC_UNEXPECTED_PROCESS_REGISTRATION = 0xC0EC0003,
+ MD_NTSTATUS_WIN_STATUS_APPEXEC_INVALID_HOST_STATE = 0xC0EC0004,
+ MD_NTSTATUS_WIN_STATUS_APPEXEC_NO_DONOR = 0xC0EC0005,
+ MD_NTSTATUS_WIN_STATUS_APPEXEC_HOST_ID_MISMATCH = 0xC0EC0006,
+ MD_NTSTATUS_WIN_STATUS_APPEXEC_UNKNOWN_USER = 0xC0EC0007,
+} MDNTStatusCodeWin;
+
+// These constants are defined in the MSDN documentation of
+// the EXCEPTION_RECORD structure.
+typedef enum {
+ MD_ACCESS_VIOLATION_WIN_READ = 0,
+ MD_ACCESS_VIOLATION_WIN_WRITE = 1,
+ MD_ACCESS_VIOLATION_WIN_EXEC = 8
+} MDAccessViolationTypeWin;
+
+// These constants are defined in the MSDN documentation of
+// the EXCEPTION_RECORD structure.
+typedef enum {
+ MD_IN_PAGE_ERROR_WIN_READ = 0,
+ MD_IN_PAGE_ERROR_WIN_WRITE = 1,
+ MD_IN_PAGE_ERROR_WIN_EXEC = 8
+} MDInPageErrorTypeWin;
+
+/* For (MDException).exception_information[0], when (MDException).exception_code
+ * is MD_EXCEPTION_CODE_WIN_STACK_BUFFER_OVERRUN. This describes the underlying
+ * reason for the crash. These values come from winnt.h.
+ *
+ * The content of this enum was created from winnt.h in the 10 SDK
+ * (version 10.0.19041.0) with
+ *
+ * egrep '#define FAST_FAIL_[A-Z_0-9]+\s+[0-9]' winnt.h
+ * | tr -d '\r'
+ * | sed -r 's@#define FAST_FAIL_([A-Z_0-9]+)\s+([0-9]+).*@\2 \1@'
+ * | sed -r 's@([0-9]+) ([A-Z_0-9]+)@ MD_FAST_FAIL_WIN_\2 = \1,@' */
+typedef enum {
+ MD_FAST_FAIL_WIN_LEGACY_GS_VIOLATION = 0,
+ MD_FAST_FAIL_WIN_VTGUARD_CHECK_FAILURE = 1,
+ MD_FAST_FAIL_WIN_STACK_COOKIE_CHECK_FAILURE = 2,
+ MD_FAST_FAIL_WIN_CORRUPT_LIST_ENTRY = 3,
+ MD_FAST_FAIL_WIN_INCORRECT_STACK = 4,
+ MD_FAST_FAIL_WIN_INVALID_ARG = 5,
+ MD_FAST_FAIL_WIN_GS_COOKIE_INIT = 6,
+ MD_FAST_FAIL_WIN_FATAL_APP_EXIT = 7,
+ MD_FAST_FAIL_WIN_RANGE_CHECK_FAILURE = 8,
+ MD_FAST_FAIL_WIN_UNSAFE_REGISTRY_ACCESS = 9,
+ MD_FAST_FAIL_WIN_GUARD_ICALL_CHECK_FAILURE = 10,
+ MD_FAST_FAIL_WIN_GUARD_WRITE_CHECK_FAILURE = 11,
+ MD_FAST_FAIL_WIN_INVALID_FIBER_SWITCH = 12,
+ MD_FAST_FAIL_WIN_INVALID_SET_OF_CONTEXT = 13,
+ MD_FAST_FAIL_WIN_INVALID_REFERENCE_COUNT = 14,
+ MD_FAST_FAIL_WIN_INVALID_JUMP_BUFFER = 18,
+ MD_FAST_FAIL_WIN_MRDATA_MODIFIED = 19,
+ MD_FAST_FAIL_WIN_CERTIFICATION_FAILURE = 20,
+ MD_FAST_FAIL_WIN_INVALID_EXCEPTION_CHAIN = 21,
+ MD_FAST_FAIL_WIN_CRYPTO_LIBRARY = 22,
+ MD_FAST_FAIL_WIN_INVALID_CALL_IN_DLL_CALLOUT = 23,
+ MD_FAST_FAIL_WIN_INVALID_IMAGE_BASE = 24,
+ MD_FAST_FAIL_WIN_DLOAD_PROTECTION_FAILURE = 25,
+ MD_FAST_FAIL_WIN_UNSAFE_EXTENSION_CALL = 26,
+ MD_FAST_FAIL_WIN_DEPRECATED_SERVICE_INVOKED = 27,
+ MD_FAST_FAIL_WIN_INVALID_BUFFER_ACCESS = 28,
+ MD_FAST_FAIL_WIN_INVALID_BALANCED_TREE = 29,
+ MD_FAST_FAIL_WIN_INVALID_NEXT_THREAD = 30,
+ MD_FAST_FAIL_WIN_GUARD_ICALL_CHECK_SUPPRESSED = 31,
+ MD_FAST_FAIL_WIN_APCS_DISABLED = 32,
+ MD_FAST_FAIL_WIN_INVALID_IDLE_STATE = 33,
+ MD_FAST_FAIL_WIN_MRDATA_PROTECTION_FAILURE = 34,
+ MD_FAST_FAIL_WIN_UNEXPECTED_HEAP_EXCEPTION = 35,
+ MD_FAST_FAIL_WIN_INVALID_LOCK_STATE = 36,
+ MD_FAST_FAIL_WIN_GUARD_JUMPTABLE = 37,
+ MD_FAST_FAIL_WIN_INVALID_LONGJUMP_TARGET = 38,
+ MD_FAST_FAIL_WIN_INVALID_DISPATCH_CONTEXT = 39,
+ MD_FAST_FAIL_WIN_INVALID_THREAD = 40,
+ MD_FAST_FAIL_WIN_INVALID_SYSCALL_NUMBER = 41,
+ MD_FAST_FAIL_WIN_INVALID_FILE_OPERATION = 42,
+ MD_FAST_FAIL_WIN_LPAC_ACCESS_DENIED = 43,
+ MD_FAST_FAIL_WIN_GUARD_SS_FAILURE = 44,
+ MD_FAST_FAIL_WIN_LOADER_CONTINUITY_FAILURE = 45,
+ MD_FAST_FAIL_WIN_GUARD_EXPORT_SUPPRESSION_FAILURE = 46,
+ MD_FAST_FAIL_WIN_INVALID_CONTROL_STACK = 47,
+ MD_FAST_FAIL_WIN_SET_CONTEXT_DENIED = 48,
+ MD_FAST_FAIL_WIN_INVALID_IAT = 49,
+ MD_FAST_FAIL_WIN_HEAP_METADATA_CORRUPTION = 50,
+ MD_FAST_FAIL_WIN_PAYLOAD_RESTRICTION_VIOLATION = 51,
+ MD_FAST_FAIL_WIN_LOW_LABEL_ACCESS_DENIED = 52,
+ MD_FAST_FAIL_WIN_ENCLAVE_CALL_FAILURE = 53,
+ MD_FAST_FAIL_WIN_UNHANDLED_LSS_EXCEPTON = 54,
+ MD_FAST_FAIL_WIN_ADMINLESS_ACCESS_DENIED = 55,
+ MD_FAST_FAIL_WIN_UNEXPECTED_CALL = 56,
+ MD_FAST_FAIL_WIN_CONTROL_INVALID_RETURN_ADDRESS = 57,
+ MD_FAST_FAIL_WIN_UNEXPECTED_HOST_BEHAVIOR = 58,
+ MD_FAST_FAIL_WIN_FLAGS_CORRUPTION = 59,
+ MD_FAST_FAIL_WIN_VEH_CORRUPTION = 60,
+ MD_FAST_FAIL_WIN_ETW_CORRUPTION = 61,
+ MD_FAST_FAIL_WIN_RIO_ABORT = 62,
+ MD_FAST_FAIL_WIN_INVALID_PFN = 63,
+} MDFastFailWin;
+
+/* For various (MDException).exception_information entries. This describes the
+* underlying reason for the crash. These values come from winerror.h.
+ *
+ * The content of this enum was created from winnt.h in the 10 SDK
+ * (version 10.0.19041.0) with
+ *
+ * egrep -o '#define ERROR_[A-Z_0-9]+\s+[0-9]+L' winerror.h
+ * | tr -d '\r'
+ * | sed -r 's@#define ERROR_([A-Z_0-9]+)\s+([0-9]+)L@\2 \1@'
+ * | sort -n
+ * | sed -r 's@([0-9]+) ([A-Z_0-9]+)@ MD_ERROR_WIN_\2 = \1,@' */
+typedef enum {
+ MD_ERROR_WIN_SUCCESS = 0,
+ MD_ERROR_WIN_INVALID_FUNCTION = 1,
+ MD_ERROR_WIN_FILE_NOT_FOUND = 2,
+ MD_ERROR_WIN_PATH_NOT_FOUND = 3,
+ MD_ERROR_WIN_TOO_MANY_OPEN_FILES = 4,
+ MD_ERROR_WIN_ACCESS_DENIED = 5,
+ MD_ERROR_WIN_INVALID_HANDLE = 6,
+ MD_ERROR_WIN_ARENA_TRASHED = 7,
+ MD_ERROR_WIN_NOT_ENOUGH_MEMORY = 8,
+ MD_ERROR_WIN_INVALID_BLOCK = 9,
+ MD_ERROR_WIN_BAD_ENVIRONMENT = 10,
+ MD_ERROR_WIN_BAD_FORMAT = 11,
+ MD_ERROR_WIN_INVALID_ACCESS = 12,
+ MD_ERROR_WIN_INVALID_DATA = 13,
+ MD_ERROR_WIN_OUTOFMEMORY = 14,
+ MD_ERROR_WIN_INVALID_DRIVE = 15,
+ MD_ERROR_WIN_CURRENT_DIRECTORY = 16,
+ MD_ERROR_WIN_NOT_SAME_DEVICE = 17,
+ MD_ERROR_WIN_NO_MORE_FILES = 18,
+ MD_ERROR_WIN_WRITE_PROTECT = 19,
+ MD_ERROR_WIN_BAD_UNIT = 20,
+ MD_ERROR_WIN_NOT_READY = 21,
+ MD_ERROR_WIN_BAD_COMMAND = 22,
+ MD_ERROR_WIN_CRC = 23,
+ MD_ERROR_WIN_BAD_LENGTH = 24,
+ MD_ERROR_WIN_SEEK = 25,
+ MD_ERROR_WIN_NOT_DOS_DISK = 26,
+ MD_ERROR_WIN_SECTOR_NOT_FOUND = 27,
+ MD_ERROR_WIN_OUT_OF_PAPER = 28,
+ MD_ERROR_WIN_WRITE_FAULT = 29,
+ MD_ERROR_WIN_READ_FAULT = 30,
+ MD_ERROR_WIN_GEN_FAILURE = 31,
+ MD_ERROR_WIN_SHARING_VIOLATION = 32,
+ MD_ERROR_WIN_LOCK_VIOLATION = 33,
+ MD_ERROR_WIN_WRONG_DISK = 34,
+ MD_ERROR_WIN_SHARING_BUFFER_EXCEEDED = 36,
+ MD_ERROR_WIN_HANDLE_EOF = 38,
+ MD_ERROR_WIN_HANDLE_DISK_FULL = 39,
+ MD_ERROR_WIN_NOT_SUPPORTED = 50,
+ MD_ERROR_WIN_REM_NOT_LIST = 51,
+ MD_ERROR_WIN_DUP_NAME = 52,
+ MD_ERROR_WIN_BAD_NETPATH = 53,
+ MD_ERROR_WIN_NETWORK_BUSY = 54,
+ MD_ERROR_WIN_DEV_NOT_EXIST = 55,
+ MD_ERROR_WIN_TOO_MANY_CMDS = 56,
+ MD_ERROR_WIN_ADAP_HDW_ERR = 57,
+ MD_ERROR_WIN_BAD_NET_RESP = 58,
+ MD_ERROR_WIN_UNEXP_NET_ERR = 59,
+ MD_ERROR_WIN_BAD_REM_ADAP = 60,
+ MD_ERROR_WIN_PRINTQ_FULL = 61,
+ MD_ERROR_WIN_NO_SPOOL_SPACE = 62,
+ MD_ERROR_WIN_PRINT_CANCELLED = 63,
+ MD_ERROR_WIN_NETNAME_DELETED = 64,
+ MD_ERROR_WIN_NETWORK_ACCESS_DENIED = 65,
+ MD_ERROR_WIN_BAD_DEV_TYPE = 66,
+ MD_ERROR_WIN_BAD_NET_NAME = 67,
+ MD_ERROR_WIN_TOO_MANY_NAMES = 68,
+ MD_ERROR_WIN_TOO_MANY_SESS = 69,
+ MD_ERROR_WIN_SHARING_PAUSED = 70,
+ MD_ERROR_WIN_REQ_NOT_ACCEP = 71,
+ MD_ERROR_WIN_REDIR_PAUSED = 72,
+ MD_ERROR_WIN_FILE_EXISTS = 80,
+ MD_ERROR_WIN_CANNOT_MAKE = 82,
+ MD_ERROR_WIN_FAIL_I24 = 83,
+ MD_ERROR_WIN_OUT_OF_STRUCTURES = 84,
+ MD_ERROR_WIN_ALREADY_ASSIGNED = 85,
+ MD_ERROR_WIN_INVALID_PASSWORD = 86,
+ MD_ERROR_WIN_INVALID_PARAMETER = 87,
+ MD_ERROR_WIN_NET_WRITE_FAULT = 88,
+ MD_ERROR_WIN_NO_PROC_SLOTS = 89,
+ MD_ERROR_WIN_TOO_MANY_SEMAPHORES = 100,
+ MD_ERROR_WIN_EXCL_SEM_ALREADY_OWNED = 101,
+ MD_ERROR_WIN_SEM_IS_SET = 102,
+ MD_ERROR_WIN_TOO_MANY_SEM_REQUESTS = 103,
+ MD_ERROR_WIN_INVALID_AT_INTERRUPT_TIME = 104,
+ MD_ERROR_WIN_SEM_OWNER_DIED = 105,
+ MD_ERROR_WIN_SEM_USER_LIMIT = 106,
+ MD_ERROR_WIN_DISK_CHANGE = 107,
+ MD_ERROR_WIN_DRIVE_LOCKED = 108,
+ MD_ERROR_WIN_BROKEN_PIPE = 109,
+ MD_ERROR_WIN_OPEN_FAILED = 110,
+ MD_ERROR_WIN_BUFFER_OVERFLOW = 111,
+ MD_ERROR_WIN_DISK_FULL = 112,
+ MD_ERROR_WIN_NO_MORE_SEARCH_HANDLES = 113,
+ MD_ERROR_WIN_INVALID_TARGET_HANDLE = 114,
+ MD_ERROR_WIN_INVALID_CATEGORY = 117,
+ MD_ERROR_WIN_INVALID_VERIFY_SWITCH = 118,
+ MD_ERROR_WIN_BAD_DRIVER_LEVEL = 119,
+ MD_ERROR_WIN_CALL_NOT_IMPLEMENTED = 120,
+ MD_ERROR_WIN_SEM_TIMEOUT = 121,
+ MD_ERROR_WIN_INSUFFICIENT_BUFFER = 122,
+ MD_ERROR_WIN_INVALID_NAME = 123,
+ MD_ERROR_WIN_INVALID_LEVEL = 124,
+ MD_ERROR_WIN_NO_VOLUME_LABEL = 125,
+ MD_ERROR_WIN_MOD_NOT_FOUND = 126,
+ MD_ERROR_WIN_PROC_NOT_FOUND = 127,
+ MD_ERROR_WIN_WAIT_NO_CHILDREN = 128,
+ MD_ERROR_WIN_CHILD_NOT_COMPLETE = 129,
+ MD_ERROR_WIN_DIRECT_ACCESS_HANDLE = 130,
+ MD_ERROR_WIN_NEGATIVE_SEEK = 131,
+ MD_ERROR_WIN_SEEK_ON_DEVICE = 132,
+ MD_ERROR_WIN_IS_JOIN_TARGET = 133,
+ MD_ERROR_WIN_IS_JOINED = 134,
+ MD_ERROR_WIN_IS_SUBSTED = 135,
+ MD_ERROR_WIN_NOT_JOINED = 136,
+ MD_ERROR_WIN_NOT_SUBSTED = 137,
+ MD_ERROR_WIN_JOIN_TO_JOIN = 138,
+ MD_ERROR_WIN_SUBST_TO_SUBST = 139,
+ MD_ERROR_WIN_JOIN_TO_SUBST = 140,
+ MD_ERROR_WIN_SUBST_TO_JOIN = 141,
+ MD_ERROR_WIN_BUSY_DRIVE = 142,
+ MD_ERROR_WIN_SAME_DRIVE = 143,
+ MD_ERROR_WIN_DIR_NOT_ROOT = 144,
+ MD_ERROR_WIN_DIR_NOT_EMPTY = 145,
+ MD_ERROR_WIN_IS_SUBST_PATH = 146,
+ MD_ERROR_WIN_IS_JOIN_PATH = 147,
+ MD_ERROR_WIN_PATH_BUSY = 148,
+ MD_ERROR_WIN_IS_SUBST_TARGET = 149,
+ MD_ERROR_WIN_SYSTEM_TRACE = 150,
+ MD_ERROR_WIN_INVALID_EVENT_COUNT = 151,
+ MD_ERROR_WIN_TOO_MANY_MUXWAITERS = 152,
+ MD_ERROR_WIN_INVALID_LIST_FORMAT = 153,
+ MD_ERROR_WIN_LABEL_TOO_LONG = 154,
+ MD_ERROR_WIN_TOO_MANY_TCBS = 155,
+ MD_ERROR_WIN_SIGNAL_REFUSED = 156,
+ MD_ERROR_WIN_DISCARDED = 157,
+ MD_ERROR_WIN_NOT_LOCKED = 158,
+ MD_ERROR_WIN_BAD_THREADID_ADDR = 159,
+ MD_ERROR_WIN_BAD_ARGUMENTS = 160,
+ MD_ERROR_WIN_BAD_PATHNAME = 161,
+ MD_ERROR_WIN_SIGNAL_PENDING = 162,
+ MD_ERROR_WIN_MAX_THRDS_REACHED = 164,
+ MD_ERROR_WIN_LOCK_FAILED = 167,
+ MD_ERROR_WIN_BUSY = 170,
+ MD_ERROR_WIN_DEVICE_SUPPORT_IN_PROGRESS = 171,
+ MD_ERROR_WIN_CANCEL_VIOLATION = 173,
+ MD_ERROR_WIN_ATOMIC_LOCKS_NOT_SUPPORTED = 174,
+ MD_ERROR_WIN_INVALID_SEGMENT_NUMBER = 180,
+ MD_ERROR_WIN_INVALID_ORDINAL = 182,
+ MD_ERROR_WIN_ALREADY_EXISTS = 183,
+ MD_ERROR_WIN_INVALID_FLAG_NUMBER = 186,
+ MD_ERROR_WIN_SEM_NOT_FOUND = 187,
+ MD_ERROR_WIN_INVALID_STARTING_CODESEG = 188,
+ MD_ERROR_WIN_INVALID_STACKSEG = 189,
+ MD_ERROR_WIN_INVALID_MODULETYPE = 190,
+ MD_ERROR_WIN_INVALID_EXE_SIGNATURE = 191,
+ MD_ERROR_WIN_EXE_MARKED_INVALID = 192,
+ MD_ERROR_WIN_BAD_EXE_FORMAT = 193,
+ MD_ERROR_WIN_INVALID_MINALLOCSIZE = 195,
+ MD_ERROR_WIN_DYNLINK_FROM_INVALID_RING = 196,
+ MD_ERROR_WIN_IOPL_NOT_ENABLED = 197,
+ MD_ERROR_WIN_INVALID_SEGDPL = 198,
+ MD_ERROR_WIN_RING2SEG_MUST_BE_MOVABLE = 200,
+ MD_ERROR_WIN_RELOC_CHAIN_XEEDS_SEGLIM = 201,
+ MD_ERROR_WIN_INFLOOP_IN_RELOC_CHAIN = 202,
+ MD_ERROR_WIN_ENVVAR_NOT_FOUND = 203,
+ MD_ERROR_WIN_NO_SIGNAL_SENT = 205,
+ MD_ERROR_WIN_FILENAME_EXCED_RANGE = 206,
+ MD_ERROR_WIN_RING2_STACK_IN_USE = 207,
+ MD_ERROR_WIN_META_EXPANSION_TOO_LONG = 208,
+ MD_ERROR_WIN_INVALID_SIGNAL_NUMBER = 209,
+ MD_ERROR_WIN_THREAD_1_INACTIVE = 210,
+ MD_ERROR_WIN_LOCKED = 212,
+ MD_ERROR_WIN_TOO_MANY_MODULES = 214,
+ MD_ERROR_WIN_NESTING_NOT_ALLOWED = 215,
+ MD_ERROR_WIN_EXE_MACHINE_TYPE_MISMATCH = 216,
+ MD_ERROR_WIN_EXE_CANNOT_MODIFY_SIGNED_BINARY = 217,
+ MD_ERROR_WIN_EXE_CANNOT_MODIFY_STRONG_SIGNED_BINARY = 218,
+ MD_ERROR_WIN_FILE_CHECKED_OUT = 220,
+ MD_ERROR_WIN_CHECKOUT_REQUIRED = 221,
+ MD_ERROR_WIN_BAD_FILE_TYPE = 222,
+ MD_ERROR_WIN_FILE_TOO_LARGE = 223,
+ MD_ERROR_WIN_FORMS_AUTH_REQUIRED = 224,
+ MD_ERROR_WIN_VIRUS_INFECTED = 225,
+ MD_ERROR_WIN_VIRUS_DELETED = 226,
+ MD_ERROR_WIN_PIPE_LOCAL = 229,
+ MD_ERROR_WIN_BAD_PIPE = 230,
+ MD_ERROR_WIN_PIPE_BUSY = 231,
+ MD_ERROR_WIN_NO_DATA = 232,
+ MD_ERROR_WIN_PIPE_NOT_CONNECTED = 233,
+ MD_ERROR_WIN_MORE_DATA = 234,
+ MD_ERROR_WIN_NO_WORK_DONE = 235,
+ MD_ERROR_WIN_VC_DISCONNECTED = 240,
+ MD_ERROR_WIN_INVALID_EA_NAME = 254,
+ MD_ERROR_WIN_EA_LIST_INCONSISTENT = 255,
+ MD_ERROR_WIN_NO_MORE_ITEMS = 259,
+ MD_ERROR_WIN_CANNOT_COPY = 266,
+ MD_ERROR_WIN_DIRECTORY = 267,
+ MD_ERROR_WIN_EAS_DIDNT_FIT = 275,
+ MD_ERROR_WIN_EA_FILE_CORRUPT = 276,
+ MD_ERROR_WIN_EA_TABLE_FULL = 277,
+ MD_ERROR_WIN_INVALID_EA_HANDLE = 278,
+ MD_ERROR_WIN_EAS_NOT_SUPPORTED = 282,
+ MD_ERROR_WIN_NOT_OWNER = 288,
+ MD_ERROR_WIN_TOO_MANY_POSTS = 298,
+ MD_ERROR_WIN_PARTIAL_COPY = 299,
+ MD_ERROR_WIN_OPLOCK_NOT_GRANTED = 300,
+ MD_ERROR_WIN_INVALID_OPLOCK_PROTOCOL = 301,
+ MD_ERROR_WIN_DISK_TOO_FRAGMENTED = 302,
+ MD_ERROR_WIN_DELETE_PENDING = 303,
+ MD_ERROR_WIN_INCOMPATIBLE_WITH_GLOBAL_SHORT_NAME_REGISTRY_SETTING = 304,
+ MD_ERROR_WIN_SHORT_NAMES_NOT_ENABLED_ON_VOLUME = 305,
+ MD_ERROR_WIN_SECURITY_STREAM_IS_INCONSISTENT = 306,
+ MD_ERROR_WIN_INVALID_LOCK_RANGE = 307,
+ MD_ERROR_WIN_IMAGE_SUBSYSTEM_NOT_PRESENT = 308,
+ MD_ERROR_WIN_NOTIFICATION_GUID_ALREADY_DEFINED = 309,
+ MD_ERROR_WIN_INVALID_EXCEPTION_HANDLER = 310,
+ MD_ERROR_WIN_DUPLICATE_PRIVILEGES = 311,
+ MD_ERROR_WIN_NO_RANGES_PROCESSED = 312,
+ MD_ERROR_WIN_NOT_ALLOWED_ON_SYSTEM_FILE = 313,
+ MD_ERROR_WIN_DISK_RESOURCES_EXHAUSTED = 314,
+ MD_ERROR_WIN_INVALID_TOKEN = 315,
+ MD_ERROR_WIN_DEVICE_FEATURE_NOT_SUPPORTED = 316,
+ MD_ERROR_WIN_MR_MID_NOT_FOUND = 317,
+ MD_ERROR_WIN_SCOPE_NOT_FOUND = 318,
+ MD_ERROR_WIN_UNDEFINED_SCOPE = 319,
+ MD_ERROR_WIN_INVALID_CAP = 320,
+ MD_ERROR_WIN_DEVICE_UNREACHABLE = 321,
+ MD_ERROR_WIN_DEVICE_NO_RESOURCES = 322,
+ MD_ERROR_WIN_DATA_CHECKSUM_ERROR = 323,
+ MD_ERROR_WIN_INTERMIXED_KERNEL_EA_OPERATION = 324,
+ MD_ERROR_WIN_FILE_LEVEL_TRIM_NOT_SUPPORTED = 326,
+ MD_ERROR_WIN_OFFSET_ALIGNMENT_VIOLATION = 327,
+ MD_ERROR_WIN_INVALID_FIELD_IN_PARAMETER_LIST = 328,
+ MD_ERROR_WIN_OPERATION_IN_PROGRESS = 329,
+ MD_ERROR_WIN_BAD_DEVICE_PATH = 330,
+ MD_ERROR_WIN_TOO_MANY_DESCRIPTORS = 331,
+ MD_ERROR_WIN_SCRUB_DATA_DISABLED = 332,
+ MD_ERROR_WIN_NOT_REDUNDANT_STORAGE = 333,
+ MD_ERROR_WIN_RESIDENT_FILE_NOT_SUPPORTED = 334,
+ MD_ERROR_WIN_COMPRESSED_FILE_NOT_SUPPORTED = 335,
+ MD_ERROR_WIN_DIRECTORY_NOT_SUPPORTED = 336,
+ MD_ERROR_WIN_NOT_READ_FROM_COPY = 337,
+ MD_ERROR_WIN_FT_WRITE_FAILURE = 338,
+ MD_ERROR_WIN_FT_DI_SCAN_REQUIRED = 339,
+ MD_ERROR_WIN_INVALID_KERNEL_INFO_VERSION = 340,
+ MD_ERROR_WIN_INVALID_PEP_INFO_VERSION = 341,
+ MD_ERROR_WIN_OBJECT_NOT_EXTERNALLY_BACKED = 342,
+ MD_ERROR_WIN_EXTERNAL_BACKING_PROVIDER_UNKNOWN = 343,
+ MD_ERROR_WIN_COMPRESSION_NOT_BENEFICIAL = 344,
+ MD_ERROR_WIN_STORAGE_TOPOLOGY_ID_MISMATCH = 345,
+ MD_ERROR_WIN_BLOCKED_BY_PARENTAL_CONTROLS = 346,
+ MD_ERROR_WIN_BLOCK_TOO_MANY_REFERENCES = 347,
+ MD_ERROR_WIN_MARKED_TO_DISALLOW_WRITES = 348,
+ MD_ERROR_WIN_ENCLAVE_FAILURE = 349,
+ MD_ERROR_WIN_FAIL_NOACTION_REBOOT = 350,
+ MD_ERROR_WIN_FAIL_SHUTDOWN = 351,
+ MD_ERROR_WIN_FAIL_RESTART = 352,
+ MD_ERROR_WIN_MAX_SESSIONS_REACHED = 353,
+ MD_ERROR_WIN_NETWORK_ACCESS_DENIED_EDP = 354,
+ MD_ERROR_WIN_DEVICE_HINT_NAME_BUFFER_TOO_SMALL = 355,
+ MD_ERROR_WIN_EDP_POLICY_DENIES_OPERATION = 356,
+ MD_ERROR_WIN_EDP_DPL_POLICY_CANT_BE_SATISFIED = 357,
+ MD_ERROR_WIN_CLOUD_FILE_SYNC_ROOT_METADATA_CORRUPT = 358,
+ MD_ERROR_WIN_DEVICE_IN_MAINTENANCE = 359,
+ MD_ERROR_WIN_NOT_SUPPORTED_ON_DAX = 360,
+ MD_ERROR_WIN_DAX_MAPPING_EXISTS = 361,
+ MD_ERROR_WIN_CLOUD_FILE_PROVIDER_NOT_RUNNING = 362,
+ MD_ERROR_WIN_CLOUD_FILE_METADATA_CORRUPT = 363,
+ MD_ERROR_WIN_CLOUD_FILE_METADATA_TOO_LARGE = 364,
+ MD_ERROR_WIN_CLOUD_FILE_PROPERTY_BLOB_TOO_LARGE = 365,
+ MD_ERROR_WIN_CLOUD_FILE_PROPERTY_BLOB_CHECKSUM_MISMATCH = 366,
+ MD_ERROR_WIN_CHILD_PROCESS_BLOCKED = 367,
+ MD_ERROR_WIN_STORAGE_LOST_DATA_PERSISTENCE = 368,
+ MD_ERROR_WIN_FILE_SYSTEM_VIRTUALIZATION_UNAVAILABLE = 369,
+ MD_ERROR_WIN_FILE_SYSTEM_VIRTUALIZATION_METADATA_CORRUPT = 370,
+ MD_ERROR_WIN_FILE_SYSTEM_VIRTUALIZATION_BUSY = 371,
+ MD_ERROR_WIN_FILE_SYSTEM_VIRTUALIZATION_PROVIDER_UNKNOWN = 372,
+ MD_ERROR_WIN_GDI_HANDLE_LEAK = 373,
+ MD_ERROR_WIN_CLOUD_FILE_TOO_MANY_PROPERTY_BLOBS = 374,
+ MD_ERROR_WIN_CLOUD_FILE_PROPERTY_VERSION_NOT_SUPPORTED = 375,
+ MD_ERROR_WIN_NOT_A_CLOUD_FILE = 376,
+ MD_ERROR_WIN_CLOUD_FILE_NOT_IN_SYNC = 377,
+ MD_ERROR_WIN_CLOUD_FILE_ALREADY_CONNECTED = 378,
+ MD_ERROR_WIN_CLOUD_FILE_NOT_SUPPORTED = 379,
+ MD_ERROR_WIN_CLOUD_FILE_INVALID_REQUEST = 380,
+ MD_ERROR_WIN_CLOUD_FILE_READ_ONLY_VOLUME = 381,
+ MD_ERROR_WIN_CLOUD_FILE_CONNECTED_PROVIDER_ONLY = 382,
+ MD_ERROR_WIN_CLOUD_FILE_VALIDATION_FAILED = 383,
+ MD_ERROR_WIN_SMB1_NOT_AVAILABLE = 384,
+ MD_ERROR_WIN_FILE_SYSTEM_VIRTUALIZATION_INVALID_OPERATION = 385,
+ MD_ERROR_WIN_CLOUD_FILE_AUTHENTICATION_FAILED = 386,
+ MD_ERROR_WIN_CLOUD_FILE_INSUFFICIENT_RESOURCES = 387,
+ MD_ERROR_WIN_CLOUD_FILE_NETWORK_UNAVAILABLE = 388,
+ MD_ERROR_WIN_CLOUD_FILE_UNSUCCESSFUL = 389,
+ MD_ERROR_WIN_CLOUD_FILE_NOT_UNDER_SYNC_ROOT = 390,
+ MD_ERROR_WIN_CLOUD_FILE_IN_USE = 391,
+ MD_ERROR_WIN_CLOUD_FILE_PINNED = 392,
+ MD_ERROR_WIN_CLOUD_FILE_REQUEST_ABORTED = 393,
+ MD_ERROR_WIN_CLOUD_FILE_PROPERTY_CORRUPT = 394,
+ MD_ERROR_WIN_CLOUD_FILE_ACCESS_DENIED = 395,
+ MD_ERROR_WIN_CLOUD_FILE_INCOMPATIBLE_HARDLINKS = 396,
+ MD_ERROR_WIN_CLOUD_FILE_PROPERTY_LOCK_CONFLICT = 397,
+ MD_ERROR_WIN_CLOUD_FILE_REQUEST_CANCELED = 398,
+ MD_ERROR_WIN_EXTERNAL_SYSKEY_NOT_SUPPORTED = 399,
+ MD_ERROR_WIN_THREAD_MODE_ALREADY_BACKGROUND = 400,
+ MD_ERROR_WIN_THREAD_MODE_NOT_BACKGROUND = 401,
+ MD_ERROR_WIN_PROCESS_MODE_ALREADY_BACKGROUND = 402,
+ MD_ERROR_WIN_PROCESS_MODE_NOT_BACKGROUND = 403,
+ MD_ERROR_WIN_CLOUD_FILE_PROVIDER_TERMINATED = 404,
+ MD_ERROR_WIN_NOT_A_CLOUD_SYNC_ROOT = 405,
+ MD_ERROR_WIN_FILE_PROTECTED_UNDER_DPL = 406,
+ MD_ERROR_WIN_VOLUME_NOT_CLUSTER_ALIGNED = 407,
+ MD_ERROR_WIN_NO_PHYSICALLY_ALIGNED_FREE_SPACE_FOUND = 408,
+ MD_ERROR_WIN_APPX_FILE_NOT_ENCRYPTED = 409,
+ MD_ERROR_WIN_RWRAW_ENCRYPTED_FILE_NOT_ENCRYPTED = 410,
+ MD_ERROR_WIN_RWRAW_ENCRYPTED_INVALID_EDATAINFO_FILEOFFSET = 411,
+ MD_ERROR_WIN_RWRAW_ENCRYPTED_INVALID_EDATAINFO_FILERANGE = 412,
+ MD_ERROR_WIN_RWRAW_ENCRYPTED_INVALID_EDATAINFO_PARAMETER = 413,
+ MD_ERROR_WIN_LINUX_SUBSYSTEM_NOT_PRESENT = 414,
+ MD_ERROR_WIN_FT_READ_FAILURE = 415,
+ MD_ERROR_WIN_STORAGE_RESERVE_ID_INVALID = 416,
+ MD_ERROR_WIN_STORAGE_RESERVE_DOES_NOT_EXIST = 417,
+ MD_ERROR_WIN_STORAGE_RESERVE_ALREADY_EXISTS = 418,
+ MD_ERROR_WIN_STORAGE_RESERVE_NOT_EMPTY = 419,
+ MD_ERROR_WIN_NOT_A_DAX_VOLUME = 420,
+ MD_ERROR_WIN_NOT_DAX_MAPPABLE = 421,
+ MD_ERROR_WIN_TIME_SENSITIVE_THREAD = 422,
+ MD_ERROR_WIN_DPL_NOT_SUPPORTED_FOR_USER = 423,
+ MD_ERROR_WIN_CASE_DIFFERING_NAMES_IN_DIR = 424,
+ MD_ERROR_WIN_FILE_NOT_SUPPORTED = 425,
+ MD_ERROR_WIN_CLOUD_FILE_REQUEST_TIMEOUT = 426,
+ MD_ERROR_WIN_NO_TASK_QUEUE = 427,
+ MD_ERROR_WIN_SRC_SRV_DLL_LOAD_FAILED = 428,
+ MD_ERROR_WIN_NOT_SUPPORTED_WITH_BTT = 429,
+ MD_ERROR_WIN_ENCRYPTION_DISABLED = 430,
+ MD_ERROR_WIN_ENCRYPTING_METADATA_DISALLOWED = 431,
+ MD_ERROR_WIN_CANT_CLEAR_ENCRYPTION_FLAG = 432,
+ MD_ERROR_WIN_NO_SUCH_DEVICE = 433,
+ MD_ERROR_WIN_CLOUD_FILE_DEHYDRATION_DISALLOWED = 434,
+ MD_ERROR_WIN_FILE_SNAP_IN_PROGRESS = 435,
+ MD_ERROR_WIN_FILE_SNAP_USER_SECTION_NOT_SUPPORTED = 436,
+ MD_ERROR_WIN_FILE_SNAP_MODIFY_NOT_SUPPORTED = 437,
+ MD_ERROR_WIN_FILE_SNAP_IO_NOT_COORDINATED = 438,
+ MD_ERROR_WIN_FILE_SNAP_UNEXPECTED_ERROR = 439,
+ MD_ERROR_WIN_FILE_SNAP_INVALID_PARAMETER = 440,
+ MD_ERROR_WIN_UNSATISFIED_DEPENDENCIES = 441,
+ MD_ERROR_WIN_CASE_SENSITIVE_PATH = 442,
+ MD_ERROR_WIN_UNEXPECTED_NTCACHEMANAGER_ERROR = 443,
+ MD_ERROR_WIN_LINUX_SUBSYSTEM_UPDATE_REQUIRED = 444,
+ MD_ERROR_WIN_DLP_POLICY_WARNS_AGAINST_OPERATION = 445,
+ MD_ERROR_WIN_DLP_POLICY_DENIES_OPERATION = 446,
+ MD_ERROR_WIN_DLP_POLICY_SILENTLY_FAIL = 449,
+ MD_ERROR_WIN_CAPAUTHZ_NOT_DEVUNLOCKED = 450,
+ MD_ERROR_WIN_CAPAUTHZ_CHANGE_TYPE = 451,
+ MD_ERROR_WIN_CAPAUTHZ_NOT_PROVISIONED = 452,
+ MD_ERROR_WIN_CAPAUTHZ_NOT_AUTHORIZED = 453,
+ MD_ERROR_WIN_CAPAUTHZ_NO_POLICY = 454,
+ MD_ERROR_WIN_CAPAUTHZ_DB_CORRUPTED = 455,
+ MD_ERROR_WIN_CAPAUTHZ_SCCD_INVALID_CATALOG = 456,
+ MD_ERROR_WIN_CAPAUTHZ_SCCD_NO_AUTH_ENTITY = 457,
+ MD_ERROR_WIN_CAPAUTHZ_SCCD_PARSE_ERROR = 458,
+ MD_ERROR_WIN_CAPAUTHZ_SCCD_DEV_MODE_REQUIRED = 459,
+ MD_ERROR_WIN_CAPAUTHZ_SCCD_NO_CAPABILITY_MATCH = 460,
+ MD_ERROR_WIN_CIMFS_IMAGE_CORRUPT = 470,
+ MD_ERROR_WIN_PNP_QUERY_REMOVE_DEVICE_TIMEOUT = 480,
+ MD_ERROR_WIN_PNP_QUERY_REMOVE_RELATED_DEVICE_TIMEOUT = 481,
+ MD_ERROR_WIN_PNP_QUERY_REMOVE_UNRELATED_DEVICE_TIMEOUT = 482,
+ MD_ERROR_WIN_DEVICE_HARDWARE_ERROR = 483,
+ MD_ERROR_WIN_INVALID_ADDRESS = 487,
+ MD_ERROR_WIN_HAS_SYSTEM_CRITICAL_FILES = 488,
+ MD_ERROR_WIN_USER_PROFILE_LOAD = 500,
+ MD_ERROR_WIN_ARITHMETIC_OVERFLOW = 534,
+ MD_ERROR_WIN_PIPE_CONNECTED = 535,
+ MD_ERROR_WIN_PIPE_LISTENING = 536,
+ MD_ERROR_WIN_VERIFIER_STOP = 537,
+ MD_ERROR_WIN_ABIOS_ERROR = 538,
+ MD_ERROR_WIN_WX86_WARNING = 539,
+ MD_ERROR_WIN_WX86_ERROR = 540,
+ MD_ERROR_WIN_TIMER_NOT_CANCELED = 541,
+ MD_ERROR_WIN_UNWIND = 542,
+ MD_ERROR_WIN_BAD_STACK = 543,
+ MD_ERROR_WIN_INVALID_UNWIND_TARGET = 544,
+ MD_ERROR_WIN_INVALID_PORT_ATTRIBUTES = 545,
+ MD_ERROR_WIN_PORT_MESSAGE_TOO_LONG = 546,
+ MD_ERROR_WIN_INVALID_QUOTA_LOWER = 547,
+ MD_ERROR_WIN_DEVICE_ALREADY_ATTACHED = 548,
+ MD_ERROR_WIN_INSTRUCTION_MISALIGNMENT = 549,
+ MD_ERROR_WIN_PROFILING_NOT_STARTED = 550,
+ MD_ERROR_WIN_PROFILING_NOT_STOPPED = 551,
+ MD_ERROR_WIN_COULD_NOT_INTERPRET = 552,
+ MD_ERROR_WIN_PROFILING_AT_LIMIT = 553,
+ MD_ERROR_WIN_CANT_WAIT = 554,
+ MD_ERROR_WIN_CANT_TERMINATE_SELF = 555,
+ MD_ERROR_WIN_UNEXPECTED_MM_CREATE_ERR = 556,
+ MD_ERROR_WIN_UNEXPECTED_MM_MAP_ERROR = 557,
+ MD_ERROR_WIN_UNEXPECTED_MM_EXTEND_ERR = 558,
+ MD_ERROR_WIN_BAD_FUNCTION_TABLE = 559,
+ MD_ERROR_WIN_NO_GUID_TRANSLATION = 560,
+ MD_ERROR_WIN_INVALID_LDT_SIZE = 561,
+ MD_ERROR_WIN_INVALID_LDT_OFFSET = 563,
+ MD_ERROR_WIN_INVALID_LDT_DESCRIPTOR = 564,
+ MD_ERROR_WIN_TOO_MANY_THREADS = 565,
+ MD_ERROR_WIN_THREAD_NOT_IN_PROCESS = 566,
+ MD_ERROR_WIN_PAGEFILE_QUOTA_EXCEEDED = 567,
+ MD_ERROR_WIN_LOGON_SERVER_CONFLICT = 568,
+ MD_ERROR_WIN_SYNCHRONIZATION_REQUIRED = 569,
+ MD_ERROR_WIN_NET_OPEN_FAILED = 570,
+ MD_ERROR_WIN_IO_PRIVILEGE_FAILED = 571,
+ MD_ERROR_WIN_CONTROL_C_EXIT = 572,
+ MD_ERROR_WIN_MISSING_SYSTEMFILE = 573,
+ MD_ERROR_WIN_UNHANDLED_EXCEPTION = 574,
+ MD_ERROR_WIN_APP_INIT_FAILURE = 575,
+ MD_ERROR_WIN_PAGEFILE_CREATE_FAILED = 576,
+ MD_ERROR_WIN_INVALID_IMAGE_HASH = 577,
+ MD_ERROR_WIN_NO_PAGEFILE = 578,
+ MD_ERROR_WIN_ILLEGAL_FLOAT_CONTEXT = 579,
+ MD_ERROR_WIN_NO_EVENT_PAIR = 580,
+ MD_ERROR_WIN_DOMAIN_CTRLR_CONFIG_ERROR = 581,
+ MD_ERROR_WIN_ILLEGAL_CHARACTER = 582,
+ MD_ERROR_WIN_UNDEFINED_CHARACTER = 583,
+ MD_ERROR_WIN_FLOPPY_VOLUME = 584,
+ MD_ERROR_WIN_BIOS_FAILED_TO_CONNECT_INTERRUPT = 585,
+ MD_ERROR_WIN_BACKUP_CONTROLLER = 586,
+ MD_ERROR_WIN_MUTANT_LIMIT_EXCEEDED = 587,
+ MD_ERROR_WIN_FS_DRIVER_REQUIRED = 588,
+ MD_ERROR_WIN_CANNOT_LOAD_REGISTRY_FILE = 589,
+ MD_ERROR_WIN_DEBUG_ATTACH_FAILED = 590,
+ MD_ERROR_WIN_SYSTEM_PROCESS_TERMINATED = 591,
+ MD_ERROR_WIN_DATA_NOT_ACCEPTED = 592,
+ MD_ERROR_WIN_VDM_HARD_ERROR = 593,
+ MD_ERROR_WIN_DRIVER_CANCEL_TIMEOUT = 594,
+ MD_ERROR_WIN_REPLY_MESSAGE_MISMATCH = 595,
+ MD_ERROR_WIN_LOST_WRITEBEHIND_DATA = 596,
+ MD_ERROR_WIN_CLIENT_SERVER_PARAMETERS_INVALID = 597,
+ MD_ERROR_WIN_NOT_TINY_STREAM = 598,
+ MD_ERROR_WIN_STACK_OVERFLOW_READ = 599,
+ MD_ERROR_WIN_CONVERT_TO_LARGE = 600,
+ MD_ERROR_WIN_FOUND_OUT_OF_SCOPE = 601,
+ MD_ERROR_WIN_ALLOCATE_BUCKET = 602,
+ MD_ERROR_WIN_MARSHALL_OVERFLOW = 603,
+ MD_ERROR_WIN_INVALID_VARIANT = 604,
+ MD_ERROR_WIN_BAD_COMPRESSION_BUFFER = 605,
+ MD_ERROR_WIN_AUDIT_FAILED = 606,
+ MD_ERROR_WIN_TIMER_RESOLUTION_NOT_SET = 607,
+ MD_ERROR_WIN_INSUFFICIENT_LOGON_INFO = 608,
+ MD_ERROR_WIN_BAD_DLL_ENTRYPOINT = 609,
+ MD_ERROR_WIN_BAD_SERVICE_ENTRYPOINT = 610,
+ MD_ERROR_WIN_IP_ADDRESS_CONFLICT1 = 611,
+ MD_ERROR_WIN_IP_ADDRESS_CONFLICT2 = 612,
+ MD_ERROR_WIN_REGISTRY_QUOTA_LIMIT = 613,
+ MD_ERROR_WIN_NO_CALLBACK_ACTIVE = 614,
+ MD_ERROR_WIN_PWD_TOO_SHORT = 615,
+ MD_ERROR_WIN_PWD_TOO_RECENT = 616,
+ MD_ERROR_WIN_PWD_HISTORY_CONFLICT = 617,
+ MD_ERROR_WIN_UNSUPPORTED_COMPRESSION = 618,
+ MD_ERROR_WIN_INVALID_HW_PROFILE = 619,
+ MD_ERROR_WIN_INVALID_PLUGPLAY_DEVICE_PATH = 620,
+ MD_ERROR_WIN_QUOTA_LIST_INCONSISTENT = 621,
+ MD_ERROR_WIN_EVALUATION_EXPIRATION = 622,
+ MD_ERROR_WIN_ILLEGAL_DLL_RELOCATION = 623,
+ MD_ERROR_WIN_DLL_INIT_FAILED_LOGOFF = 624,
+ MD_ERROR_WIN_VALIDATE_CONTINUE = 625,
+ MD_ERROR_WIN_NO_MORE_MATCHES = 626,
+ MD_ERROR_WIN_RANGE_LIST_CONFLICT = 627,
+ MD_ERROR_WIN_SERVER_SID_MISMATCH = 628,
+ MD_ERROR_WIN_CANT_ENABLE_DENY_ONLY = 629,
+ MD_ERROR_WIN_FLOAT_MULTIPLE_FAULTS = 630,
+ MD_ERROR_WIN_FLOAT_MULTIPLE_TRAPS = 631,
+ MD_ERROR_WIN_NOINTERFACE = 632,
+ MD_ERROR_WIN_DRIVER_FAILED_SLEEP = 633,
+ MD_ERROR_WIN_CORRUPT_SYSTEM_FILE = 634,
+ MD_ERROR_WIN_COMMITMENT_MINIMUM = 635,
+ MD_ERROR_WIN_PNP_RESTART_ENUMERATION = 636,
+ MD_ERROR_WIN_SYSTEM_IMAGE_BAD_SIGNATURE = 637,
+ MD_ERROR_WIN_PNP_REBOOT_REQUIRED = 638,
+ MD_ERROR_WIN_INSUFFICIENT_POWER = 639,
+ MD_ERROR_WIN_MULTIPLE_FAULT_VIOLATION = 640,
+ MD_ERROR_WIN_SYSTEM_SHUTDOWN = 641,
+ MD_ERROR_WIN_PORT_NOT_SET = 642,
+ MD_ERROR_WIN_DS_VERSION_CHECK_FAILURE = 643,
+ MD_ERROR_WIN_RANGE_NOT_FOUND = 644,
+ MD_ERROR_WIN_NOT_SAFE_MODE_DRIVER = 646,
+ MD_ERROR_WIN_FAILED_DRIVER_ENTRY = 647,
+ MD_ERROR_WIN_DEVICE_ENUMERATION_ERROR = 648,
+ MD_ERROR_WIN_MOUNT_POINT_NOT_RESOLVED = 649,
+ MD_ERROR_WIN_INVALID_DEVICE_OBJECT_PARAMETER = 650,
+ MD_ERROR_WIN_MCA_OCCURED = 651,
+ MD_ERROR_WIN_DRIVER_DATABASE_ERROR = 652,
+ MD_ERROR_WIN_SYSTEM_HIVE_TOO_LARGE = 653,
+ MD_ERROR_WIN_DRIVER_FAILED_PRIOR_UNLOAD = 654,
+ MD_ERROR_WIN_VOLSNAP_PREPARE_HIBERNATE = 655,
+ MD_ERROR_WIN_HIBERNATION_FAILURE = 656,
+ MD_ERROR_WIN_PWD_TOO_LONG = 657,
+ MD_ERROR_WIN_FILE_SYSTEM_LIMITATION = 665,
+ MD_ERROR_WIN_ASSERTION_FAILURE = 668,
+ MD_ERROR_WIN_ACPI_ERROR = 669,
+ MD_ERROR_WIN_WOW_ASSERTION = 670,
+ MD_ERROR_WIN_PNP_BAD_MPS_TABLE = 671,
+ MD_ERROR_WIN_PNP_TRANSLATION_FAILED = 672,
+ MD_ERROR_WIN_PNP_IRQ_TRANSLATION_FAILED = 673,
+ MD_ERROR_WIN_PNP_INVALID_ID = 674,
+ MD_ERROR_WIN_WAKE_SYSTEM_DEBUGGER = 675,
+ MD_ERROR_WIN_HANDLES_CLOSED = 676,
+ MD_ERROR_WIN_EXTRANEOUS_INFORMATION = 677,
+ MD_ERROR_WIN_RXACT_COMMIT_NECESSARY = 678,
+ MD_ERROR_WIN_MEDIA_CHECK = 679,
+ MD_ERROR_WIN_GUID_SUBSTITUTION_MADE = 680,
+ MD_ERROR_WIN_STOPPED_ON_SYMLINK = 681,
+ MD_ERROR_WIN_LONGJUMP = 682,
+ MD_ERROR_WIN_PLUGPLAY_QUERY_VETOED = 683,
+ MD_ERROR_WIN_UNWIND_CONSOLIDATE = 684,
+ MD_ERROR_WIN_REGISTRY_HIVE_RECOVERED = 685,
+ MD_ERROR_WIN_DLL_MIGHT_BE_INSECURE = 686,
+ MD_ERROR_WIN_DLL_MIGHT_BE_INCOMPATIBLE = 687,
+ MD_ERROR_WIN_DBG_EXCEPTION_NOT_HANDLED = 688,
+ MD_ERROR_WIN_DBG_REPLY_LATER = 689,
+ MD_ERROR_WIN_DBG_UNABLE_TO_PROVIDE_HANDLE = 690,
+ MD_ERROR_WIN_DBG_TERMINATE_THREAD = 691,
+ MD_ERROR_WIN_DBG_TERMINATE_PROCESS = 692,
+ MD_ERROR_WIN_DBG_CONTROL_C = 693,
+ MD_ERROR_WIN_DBG_PRINTEXCEPTION_C = 694,
+ MD_ERROR_WIN_DBG_RIPEXCEPTION = 695,
+ MD_ERROR_WIN_DBG_CONTROL_BREAK = 696,
+ MD_ERROR_WIN_DBG_COMMAND_EXCEPTION = 697,
+ MD_ERROR_WIN_OBJECT_NAME_EXISTS = 698,
+ MD_ERROR_WIN_THREAD_WAS_SUSPENDED = 699,
+ MD_ERROR_WIN_IMAGE_NOT_AT_BASE = 700,
+ MD_ERROR_WIN_RXACT_STATE_CREATED = 701,
+ MD_ERROR_WIN_SEGMENT_NOTIFICATION = 702,
+ MD_ERROR_WIN_BAD_CURRENT_DIRECTORY = 703,
+ MD_ERROR_WIN_FT_READ_RECOVERY_FROM_BACKUP = 704,
+ MD_ERROR_WIN_FT_WRITE_RECOVERY = 705,
+ MD_ERROR_WIN_IMAGE_MACHINE_TYPE_MISMATCH = 706,
+ MD_ERROR_WIN_RECEIVE_PARTIAL = 707,
+ MD_ERROR_WIN_RECEIVE_EXPEDITED = 708,
+ MD_ERROR_WIN_RECEIVE_PARTIAL_EXPEDITED = 709,
+ MD_ERROR_WIN_EVENT_DONE = 710,
+ MD_ERROR_WIN_EVENT_PENDING = 711,
+ MD_ERROR_WIN_CHECKING_FILE_SYSTEM = 712,
+ MD_ERROR_WIN_FATAL_APP_EXIT = 713,
+ MD_ERROR_WIN_PREDEFINED_HANDLE = 714,
+ MD_ERROR_WIN_WAS_UNLOCKED = 715,
+ MD_ERROR_WIN_SERVICE_NOTIFICATION = 716,
+ MD_ERROR_WIN_WAS_LOCKED = 717,
+ MD_ERROR_WIN_LOG_HARD_ERROR = 718,
+ MD_ERROR_WIN_ALREADY_WIN32 = 719,
+ MD_ERROR_WIN_IMAGE_MACHINE_TYPE_MISMATCH_EXE = 720,
+ MD_ERROR_WIN_NO_YIELD_PERFORMED = 721,
+ MD_ERROR_WIN_TIMER_RESUME_IGNORED = 722,
+ MD_ERROR_WIN_ARBITRATION_UNHANDLED = 723,
+ MD_ERROR_WIN_CARDBUS_NOT_SUPPORTED = 724,
+ MD_ERROR_WIN_MP_PROCESSOR_MISMATCH = 725,
+ MD_ERROR_WIN_HIBERNATED = 726,
+ MD_ERROR_WIN_RESUME_HIBERNATION = 727,
+ MD_ERROR_WIN_FIRMWARE_UPDATED = 728,
+ MD_ERROR_WIN_DRIVERS_LEAKING_LOCKED_PAGES = 729,
+ MD_ERROR_WIN_WAKE_SYSTEM = 730,
+ MD_ERROR_WIN_WAIT_1 = 731,
+ MD_ERROR_WIN_WAIT_2 = 732,
+ MD_ERROR_WIN_WAIT_3 = 733,
+ MD_ERROR_WIN_WAIT_63 = 734,
+ MD_ERROR_WIN_ABANDONED_WAIT_0 = 735,
+ MD_ERROR_WIN_ABANDONED_WAIT_63 = 736,
+ MD_ERROR_WIN_USER_APC = 737,
+ MD_ERROR_WIN_KERNEL_APC = 738,
+ MD_ERROR_WIN_ALERTED = 739,
+ MD_ERROR_WIN_ELEVATION_REQUIRED = 740,
+ MD_ERROR_WIN_REPARSE = 741,
+ MD_ERROR_WIN_OPLOCK_BREAK_IN_PROGRESS = 742,
+ MD_ERROR_WIN_VOLUME_MOUNTED = 743,
+ MD_ERROR_WIN_RXACT_COMMITTED = 744,
+ MD_ERROR_WIN_NOTIFY_CLEANUP = 745,
+ MD_ERROR_WIN_PRIMARY_TRANSPORT_CONNECT_FAILED = 746,
+ MD_ERROR_WIN_PAGE_FAULT_TRANSITION = 747,
+ MD_ERROR_WIN_PAGE_FAULT_DEMAND_ZERO = 748,
+ MD_ERROR_WIN_PAGE_FAULT_COPY_ON_WRITE = 749,
+ MD_ERROR_WIN_PAGE_FAULT_GUARD_PAGE = 750,
+ MD_ERROR_WIN_PAGE_FAULT_PAGING_FILE = 751,
+ MD_ERROR_WIN_CACHE_PAGE_LOCKED = 752,
+ MD_ERROR_WIN_CRASH_DUMP = 753,
+ MD_ERROR_WIN_BUFFER_ALL_ZEROS = 754,
+ MD_ERROR_WIN_REPARSE_OBJECT = 755,
+ MD_ERROR_WIN_RESOURCE_REQUIREMENTS_CHANGED = 756,
+ MD_ERROR_WIN_TRANSLATION_COMPLETE = 757,
+ MD_ERROR_WIN_NOTHING_TO_TERMINATE = 758,
+ MD_ERROR_WIN_PROCESS_NOT_IN_JOB = 759,
+ MD_ERROR_WIN_PROCESS_IN_JOB = 760,
+ MD_ERROR_WIN_VOLSNAP_HIBERNATE_READY = 761,
+ MD_ERROR_WIN_FSFILTER_OP_COMPLETED_SUCCESSFULLY = 762,
+ MD_ERROR_WIN_INTERRUPT_VECTOR_ALREADY_CONNECTED = 763,
+ MD_ERROR_WIN_INTERRUPT_STILL_CONNECTED = 764,
+ MD_ERROR_WIN_WAIT_FOR_OPLOCK = 765,
+ MD_ERROR_WIN_DBG_EXCEPTION_HANDLED = 766,
+ MD_ERROR_WIN_DBG_CONTINUE = 767,
+ MD_ERROR_WIN_CALLBACK_POP_STACK = 768,
+ MD_ERROR_WIN_COMPRESSION_DISABLED = 769,
+ MD_ERROR_WIN_CANTFETCHBACKWARDS = 770,
+ MD_ERROR_WIN_CANTSCROLLBACKWARDS = 771,
+ MD_ERROR_WIN_ROWSNOTRELEASED = 772,
+ MD_ERROR_WIN_BAD_ACCESSOR_FLAGS = 773,
+ MD_ERROR_WIN_ERRORS_ENCOUNTERED = 774,
+ MD_ERROR_WIN_NOT_CAPABLE = 775,
+ MD_ERROR_WIN_REQUEST_OUT_OF_SEQUENCE = 776,
+ MD_ERROR_WIN_VERSION_PARSE_ERROR = 777,
+ MD_ERROR_WIN_BADSTARTPOSITION = 778,
+ MD_ERROR_WIN_MEMORY_HARDWARE = 779,
+ MD_ERROR_WIN_DISK_REPAIR_DISABLED = 780,
+ MD_ERROR_WIN_INSUFFICIENT_RESOURCE_FOR_SPECIFIED_SHARED_SECTION_SIZE = 781,
+ MD_ERROR_WIN_SYSTEM_POWERSTATE_TRANSITION = 782,
+ MD_ERROR_WIN_SYSTEM_POWERSTATE_COMPLEX_TRANSITION = 783,
+ MD_ERROR_WIN_MCA_EXCEPTION = 784,
+ MD_ERROR_WIN_ACCESS_AUDIT_BY_POLICY = 785,
+ MD_ERROR_WIN_ACCESS_DISABLED_NO_SAFER_UI_BY_POLICY = 786,
+ MD_ERROR_WIN_ABANDON_HIBERFILE = 787,
+ MD_ERROR_WIN_LOST_WRITEBEHIND_DATA_NETWORK_DISCONNECTED = 788,
+ MD_ERROR_WIN_LOST_WRITEBEHIND_DATA_NETWORK_SERVER_ERROR = 789,
+ MD_ERROR_WIN_LOST_WRITEBEHIND_DATA_LOCAL_DISK_ERROR = 790,
+ MD_ERROR_WIN_BAD_MCFG_TABLE = 791,
+ MD_ERROR_WIN_DISK_REPAIR_REDIRECTED = 792,
+ MD_ERROR_WIN_DISK_REPAIR_UNSUCCESSFUL = 793,
+ MD_ERROR_WIN_CORRUPT_LOG_OVERFULL = 794,
+ MD_ERROR_WIN_CORRUPT_LOG_CORRUPTED = 795,
+ MD_ERROR_WIN_CORRUPT_LOG_UNAVAILABLE = 796,
+ MD_ERROR_WIN_CORRUPT_LOG_DELETED_FULL = 797,
+ MD_ERROR_WIN_CORRUPT_LOG_CLEARED = 798,
+ MD_ERROR_WIN_ORPHAN_NAME_EXHAUSTED = 799,
+ MD_ERROR_WIN_OPLOCK_SWITCHED_TO_NEW_HANDLE = 800,
+ MD_ERROR_WIN_CANNOT_GRANT_REQUESTED_OPLOCK = 801,
+ MD_ERROR_WIN_CANNOT_BREAK_OPLOCK = 802,
+ MD_ERROR_WIN_OPLOCK_HANDLE_CLOSED = 803,
+ MD_ERROR_WIN_NO_ACE_CONDITION = 804,
+ MD_ERROR_WIN_INVALID_ACE_CONDITION = 805,
+ MD_ERROR_WIN_FILE_HANDLE_REVOKED = 806,
+ MD_ERROR_WIN_IMAGE_AT_DIFFERENT_BASE = 807,
+ MD_ERROR_WIN_ENCRYPTED_IO_NOT_POSSIBLE = 808,
+ MD_ERROR_WIN_FILE_METADATA_OPTIMIZATION_IN_PROGRESS = 809,
+ MD_ERROR_WIN_QUOTA_ACTIVITY = 810,
+ MD_ERROR_WIN_HANDLE_REVOKED = 811,
+ MD_ERROR_WIN_CALLBACK_INVOKE_INLINE = 812,
+ MD_ERROR_WIN_CPU_SET_INVALID = 813,
+ MD_ERROR_WIN_ENCLAVE_NOT_TERMINATED = 814,
+ MD_ERROR_WIN_ENCLAVE_VIOLATION = 815,
+ MD_ERROR_WIN_EA_ACCESS_DENIED = 994,
+ MD_ERROR_WIN_OPERATION_ABORTED = 995,
+ MD_ERROR_WIN_IO_INCOMPLETE = 996,
+ MD_ERROR_WIN_IO_PENDING = 997,
+ MD_ERROR_WIN_NOACCESS = 998,
+ MD_ERROR_WIN_SWAPERROR = 999,
+ MD_ERROR_WIN_STACK_OVERFLOW = 1001,
+ MD_ERROR_WIN_INVALID_MESSAGE = 1002,
+ MD_ERROR_WIN_CAN_NOT_COMPLETE = 1003,
+ MD_ERROR_WIN_INVALID_FLAGS = 1004,
+ MD_ERROR_WIN_UNRECOGNIZED_VOLUME = 1005,
+ MD_ERROR_WIN_FILE_INVALID = 1006,
+ MD_ERROR_WIN_FULLSCREEN_MODE = 1007,
+ MD_ERROR_WIN_NO_TOKEN = 1008,
+ MD_ERROR_WIN_BADDB = 1009,
+ MD_ERROR_WIN_BADKEY = 1010,
+ MD_ERROR_WIN_CANTOPEN = 1011,
+ MD_ERROR_WIN_CANTREAD = 1012,
+ MD_ERROR_WIN_CANTWRITE = 1013,
+ MD_ERROR_WIN_REGISTRY_RECOVERED = 1014,
+ MD_ERROR_WIN_REGISTRY_CORRUPT = 1015,
+ MD_ERROR_WIN_REGISTRY_IO_FAILED = 1016,
+ MD_ERROR_WIN_NOT_REGISTRY_FILE = 1017,
+ MD_ERROR_WIN_KEY_DELETED = 1018,
+ MD_ERROR_WIN_NO_LOG_SPACE = 1019,
+ MD_ERROR_WIN_KEY_HAS_CHILDREN = 1020,
+ MD_ERROR_WIN_CHILD_MUST_BE_VOLATILE = 1021,
+ MD_ERROR_WIN_NOTIFY_ENUM_DIR = 1022,
+ MD_ERROR_WIN_DEPENDENT_SERVICES_RUNNING = 1051,
+ MD_ERROR_WIN_INVALID_SERVICE_CONTROL = 1052,
+ MD_ERROR_WIN_SERVICE_REQUEST_TIMEOUT = 1053,
+ MD_ERROR_WIN_SERVICE_NO_THREAD = 1054,
+ MD_ERROR_WIN_SERVICE_DATABASE_LOCKED = 1055,
+ MD_ERROR_WIN_SERVICE_ALREADY_RUNNING = 1056,
+ MD_ERROR_WIN_INVALID_SERVICE_ACCOUNT = 1057,
+ MD_ERROR_WIN_SERVICE_DISABLED = 1058,
+ MD_ERROR_WIN_CIRCULAR_DEPENDENCY = 1059,
+ MD_ERROR_WIN_SERVICE_DOES_NOT_EXIST = 1060,
+ MD_ERROR_WIN_SERVICE_CANNOT_ACCEPT_CTRL = 1061,
+ MD_ERROR_WIN_SERVICE_NOT_ACTIVE = 1062,
+ MD_ERROR_WIN_FAILED_SERVICE_CONTROLLER_CONNECT = 1063,
+ MD_ERROR_WIN_EXCEPTION_IN_SERVICE = 1064,
+ MD_ERROR_WIN_DATABASE_DOES_NOT_EXIST = 1065,
+ MD_ERROR_WIN_SERVICE_SPECIFIC_ERROR = 1066,
+ MD_ERROR_WIN_PROCESS_ABORTED = 1067,
+ MD_ERROR_WIN_SERVICE_DEPENDENCY_FAIL = 1068,
+ MD_ERROR_WIN_SERVICE_LOGON_FAILED = 1069,
+ MD_ERROR_WIN_SERVICE_START_HANG = 1070,
+ MD_ERROR_WIN_INVALID_SERVICE_LOCK = 1071,
+ MD_ERROR_WIN_SERVICE_MARKED_FOR_DELETE = 1072,
+ MD_ERROR_WIN_SERVICE_EXISTS = 1073,
+ MD_ERROR_WIN_ALREADY_RUNNING_LKG = 1074,
+ MD_ERROR_WIN_SERVICE_DEPENDENCY_DELETED = 1075,
+ MD_ERROR_WIN_BOOT_ALREADY_ACCEPTED = 1076,
+ MD_ERROR_WIN_SERVICE_NEVER_STARTED = 1077,
+ MD_ERROR_WIN_DUPLICATE_SERVICE_NAME = 1078,
+ MD_ERROR_WIN_DIFFERENT_SERVICE_ACCOUNT = 1079,
+ MD_ERROR_WIN_CANNOT_DETECT_DRIVER_FAILURE = 1080,
+ MD_ERROR_WIN_CANNOT_DETECT_PROCESS_ABORT = 1081,
+ MD_ERROR_WIN_NO_RECOVERY_PROGRAM = 1082,
+ MD_ERROR_WIN_SERVICE_NOT_IN_EXE = 1083,
+ MD_ERROR_WIN_NOT_SAFEBOOT_SERVICE = 1084,
+ MD_ERROR_WIN_END_OF_MEDIA = 1100,
+ MD_ERROR_WIN_FILEMARK_DETECTED = 1101,
+ MD_ERROR_WIN_BEGINNING_OF_MEDIA = 1102,
+ MD_ERROR_WIN_SETMARK_DETECTED = 1103,
+ MD_ERROR_WIN_NO_DATA_DETECTED = 1104,
+ MD_ERROR_WIN_PARTITION_FAILURE = 1105,
+ MD_ERROR_WIN_INVALID_BLOCK_LENGTH = 1106,
+ MD_ERROR_WIN_DEVICE_NOT_PARTITIONED = 1107,
+ MD_ERROR_WIN_UNABLE_TO_LOCK_MEDIA = 1108,
+ MD_ERROR_WIN_UNABLE_TO_UNLOAD_MEDIA = 1109,
+ MD_ERROR_WIN_MEDIA_CHANGED = 1110,
+ MD_ERROR_WIN_BUS_RESET = 1111,
+ MD_ERROR_WIN_NO_MEDIA_IN_DRIVE = 1112,
+ MD_ERROR_WIN_NO_UNICODE_TRANSLATION = 1113,
+ MD_ERROR_WIN_DLL_INIT_FAILED = 1114,
+ MD_ERROR_WIN_SHUTDOWN_IN_PROGRESS = 1115,
+ MD_ERROR_WIN_NO_SHUTDOWN_IN_PROGRESS = 1116,
+ MD_ERROR_WIN_IO_DEVICE = 1117,
+ MD_ERROR_WIN_SERIAL_NO_DEVICE = 1118,
+ MD_ERROR_WIN_IRQ_BUSY = 1119,
+ MD_ERROR_WIN_MORE_WRITES = 1120,
+ MD_ERROR_WIN_COUNTER_TIMEOUT = 1121,
+ MD_ERROR_WIN_FLOPPY_ID_MARK_NOT_FOUND = 1122,
+ MD_ERROR_WIN_FLOPPY_WRONG_CYLINDER = 1123,
+ MD_ERROR_WIN_FLOPPY_UNKNOWN_ERROR = 1124,
+ MD_ERROR_WIN_FLOPPY_BAD_REGISTERS = 1125,
+ MD_ERROR_WIN_DISK_RECALIBRATE_FAILED = 1126,
+ MD_ERROR_WIN_DISK_OPERATION_FAILED = 1127,
+ MD_ERROR_WIN_DISK_RESET_FAILED = 1128,
+ MD_ERROR_WIN_EOM_OVERFLOW = 1129,
+ MD_ERROR_WIN_NOT_ENOUGH_SERVER_MEMORY = 1130,
+ MD_ERROR_WIN_POSSIBLE_DEADLOCK = 1131,
+ MD_ERROR_WIN_MAPPED_ALIGNMENT = 1132,
+ MD_ERROR_WIN_SET_POWER_STATE_VETOED = 1140,
+ MD_ERROR_WIN_SET_POWER_STATE_FAILED = 1141,
+ MD_ERROR_WIN_TOO_MANY_LINKS = 1142,
+ MD_ERROR_WIN_OLD_WIN_VERSION = 1150,
+ MD_ERROR_WIN_APP_WRONG_OS = 1151,
+ MD_ERROR_WIN_SINGLE_INSTANCE_APP = 1152,
+ MD_ERROR_WIN_RMODE_APP = 1153,
+ MD_ERROR_WIN_INVALID_DLL = 1154,
+ MD_ERROR_WIN_NO_ASSOCIATION = 1155,
+ MD_ERROR_WIN_DDE_FAIL = 1156,
+ MD_ERROR_WIN_DLL_NOT_FOUND = 1157,
+ MD_ERROR_WIN_NO_MORE_USER_HANDLES = 1158,
+ MD_ERROR_WIN_MESSAGE_SYNC_ONLY = 1159,
+ MD_ERROR_WIN_SOURCE_ELEMENT_EMPTY = 1160,
+ MD_ERROR_WIN_DESTINATION_ELEMENT_FULL = 1161,
+ MD_ERROR_WIN_ILLEGAL_ELEMENT_ADDRESS = 1162,
+ MD_ERROR_WIN_MAGAZINE_NOT_PRESENT = 1163,
+ MD_ERROR_WIN_DEVICE_REINITIALIZATION_NEEDED = 1164,
+ MD_ERROR_WIN_DEVICE_REQUIRES_CLEANING = 1165,
+ MD_ERROR_WIN_DEVICE_DOOR_OPEN = 1166,
+ MD_ERROR_WIN_DEVICE_NOT_CONNECTED = 1167,
+ MD_ERROR_WIN_NOT_FOUND = 1168,
+ MD_ERROR_WIN_NO_MATCH = 1169,
+ MD_ERROR_WIN_SET_NOT_FOUND = 1170,
+ MD_ERROR_WIN_POINT_NOT_FOUND = 1171,
+ MD_ERROR_WIN_NO_TRACKING_SERVICE = 1172,
+ MD_ERROR_WIN_NO_VOLUME_ID = 1173,
+ MD_ERROR_WIN_UNABLE_TO_REMOVE_REPLACED = 1175,
+ MD_ERROR_WIN_UNABLE_TO_MOVE_REPLACEMENT = 1176,
+ MD_ERROR_WIN_UNABLE_TO_MOVE_REPLACEMENT_2 = 1177,
+ MD_ERROR_WIN_JOURNAL_DELETE_IN_PROGRESS = 1178,
+ MD_ERROR_WIN_JOURNAL_NOT_ACTIVE = 1179,
+ MD_ERROR_WIN_POTENTIAL_FILE_FOUND = 1180,
+ MD_ERROR_WIN_JOURNAL_ENTRY_DELETED = 1181,
+ MD_ERROR_WIN_VRF_CFG_AND_IO_ENABLED = 1183,
+ MD_ERROR_WIN_PARTITION_TERMINATING = 1184,
+ MD_ERROR_WIN_SHUTDOWN_IS_SCHEDULED = 1190,
+ MD_ERROR_WIN_SHUTDOWN_USERS_LOGGED_ON = 1191,
+ MD_ERROR_WIN_BAD_DEVICE = 1200,
+ MD_ERROR_WIN_CONNECTION_UNAVAIL = 1201,
+ MD_ERROR_WIN_DEVICE_ALREADY_REMEMBERED = 1202,
+ MD_ERROR_WIN_NO_NET_OR_BAD_PATH = 1203,
+ MD_ERROR_WIN_BAD_PROVIDER = 1204,
+ MD_ERROR_WIN_CANNOT_OPEN_PROFILE = 1205,
+ MD_ERROR_WIN_BAD_PROFILE = 1206,
+ MD_ERROR_WIN_NOT_CONTAINER = 1207,
+ MD_ERROR_WIN_EXTENDED_ERROR = 1208,
+ MD_ERROR_WIN_INVALID_GROUPNAME = 1209,
+ MD_ERROR_WIN_INVALID_COMPUTERNAME = 1210,
+ MD_ERROR_WIN_INVALID_EVENTNAME = 1211,
+ MD_ERROR_WIN_INVALID_DOMAINNAME = 1212,
+ MD_ERROR_WIN_INVALID_SERVICENAME = 1213,
+ MD_ERROR_WIN_INVALID_NETNAME = 1214,
+ MD_ERROR_WIN_INVALID_SHARENAME = 1215,
+ MD_ERROR_WIN_INVALID_PASSWORDNAME = 1216,
+ MD_ERROR_WIN_INVALID_MESSAGENAME = 1217,
+ MD_ERROR_WIN_INVALID_MESSAGEDEST = 1218,
+ MD_ERROR_WIN_SESSION_CREDENTIAL_CONFLICT = 1219,
+ MD_ERROR_WIN_REMOTE_SESSION_LIMIT_EXCEEDED = 1220,
+ MD_ERROR_WIN_DUP_DOMAINNAME = 1221,
+ MD_ERROR_WIN_NO_NETWORK = 1222,
+ MD_ERROR_WIN_CANCELLED = 1223,
+ MD_ERROR_WIN_USER_MAPPED_FILE = 1224,
+ MD_ERROR_WIN_CONNECTION_REFUSED = 1225,
+ MD_ERROR_WIN_GRACEFUL_DISCONNECT = 1226,
+ MD_ERROR_WIN_ADDRESS_ALREADY_ASSOCIATED = 1227,
+ MD_ERROR_WIN_ADDRESS_NOT_ASSOCIATED = 1228,
+ MD_ERROR_WIN_CONNECTION_INVALID = 1229,
+ MD_ERROR_WIN_CONNECTION_ACTIVE = 1230,
+ MD_ERROR_WIN_NETWORK_UNREACHABLE = 1231,
+ MD_ERROR_WIN_HOST_UNREACHABLE = 1232,
+ MD_ERROR_WIN_PROTOCOL_UNREACHABLE = 1233,
+ MD_ERROR_WIN_PORT_UNREACHABLE = 1234,
+ MD_ERROR_WIN_REQUEST_ABORTED = 1235,
+ MD_ERROR_WIN_CONNECTION_ABORTED = 1236,
+ MD_ERROR_WIN_RETRY = 1237,
+ MD_ERROR_WIN_CONNECTION_COUNT_LIMIT = 1238,
+ MD_ERROR_WIN_LOGIN_TIME_RESTRICTION = 1239,
+ MD_ERROR_WIN_LOGIN_WKSTA_RESTRICTION = 1240,
+ MD_ERROR_WIN_INCORRECT_ADDRESS = 1241,
+ MD_ERROR_WIN_ALREADY_REGISTERED = 1242,
+ MD_ERROR_WIN_SERVICE_NOT_FOUND = 1243,
+ MD_ERROR_WIN_NOT_AUTHENTICATED = 1244,
+ MD_ERROR_WIN_NOT_LOGGED_ON = 1245,
+ MD_ERROR_WIN_CONTINUE = 1246,
+ MD_ERROR_WIN_ALREADY_INITIALIZED = 1247,
+ MD_ERROR_WIN_NO_MORE_DEVICES = 1248,
+ MD_ERROR_WIN_NO_SUCH_SITE = 1249,
+ MD_ERROR_WIN_DOMAIN_CONTROLLER_EXISTS = 1250,
+ MD_ERROR_WIN_ONLY_IF_CONNECTED = 1251,
+ MD_ERROR_WIN_OVERRIDE_NOCHANGES = 1252,
+ MD_ERROR_WIN_BAD_USER_PROFILE = 1253,
+ MD_ERROR_WIN_NOT_SUPPORTED_ON_SBS = 1254,
+ MD_ERROR_WIN_SERVER_SHUTDOWN_IN_PROGRESS = 1255,
+ MD_ERROR_WIN_HOST_DOWN = 1256,
+ MD_ERROR_WIN_NON_ACCOUNT_SID = 1257,
+ MD_ERROR_WIN_NON_DOMAIN_SID = 1258,
+ MD_ERROR_WIN_APPHELP_BLOCK = 1259,
+ MD_ERROR_WIN_ACCESS_DISABLED_BY_POLICY = 1260,
+ MD_ERROR_WIN_REG_NAT_CONSUMPTION = 1261,
+ MD_ERROR_WIN_CSCSHARE_OFFLINE = 1262,
+ MD_ERROR_WIN_PKINIT_FAILURE = 1263,
+ MD_ERROR_WIN_SMARTCARD_SUBSYSTEM_FAILURE = 1264,
+ MD_ERROR_WIN_DOWNGRADE_DETECTED = 1265,
+ MD_ERROR_WIN_MACHINE_LOCKED = 1271,
+ MD_ERROR_WIN_SMB_GUEST_LOGON_BLOCKED = 1272,
+ MD_ERROR_WIN_CALLBACK_SUPPLIED_INVALID_DATA = 1273,
+ MD_ERROR_WIN_SYNC_FOREGROUND_REFRESH_REQUIRED = 1274,
+ MD_ERROR_WIN_DRIVER_BLOCKED = 1275,
+ MD_ERROR_WIN_INVALID_IMPORT_OF_NON_DLL = 1276,
+ MD_ERROR_WIN_ACCESS_DISABLED_WEBBLADE = 1277,
+ MD_ERROR_WIN_ACCESS_DISABLED_WEBBLADE_TAMPER = 1278,
+ MD_ERROR_WIN_RECOVERY_FAILURE = 1279,
+ MD_ERROR_WIN_ALREADY_FIBER = 1280,
+ MD_ERROR_WIN_ALREADY_THREAD = 1281,
+ MD_ERROR_WIN_STACK_BUFFER_OVERRUN = 1282,
+ MD_ERROR_WIN_PARAMETER_QUOTA_EXCEEDED = 1283,
+ MD_ERROR_WIN_DEBUGGER_INACTIVE = 1284,
+ MD_ERROR_WIN_DELAY_LOAD_FAILED = 1285,
+ MD_ERROR_WIN_VDM_DISALLOWED = 1286,
+ MD_ERROR_WIN_UNIDENTIFIED_ERROR = 1287,
+ MD_ERROR_WIN_INVALID_CRUNTIME_PARAMETER = 1288,
+ MD_ERROR_WIN_BEYOND_VDL = 1289,
+ MD_ERROR_WIN_INCOMPATIBLE_SERVICE_SID_TYPE = 1290,
+ MD_ERROR_WIN_DRIVER_PROCESS_TERMINATED = 1291,
+ MD_ERROR_WIN_IMPLEMENTATION_LIMIT = 1292,
+ MD_ERROR_WIN_PROCESS_IS_PROTECTED = 1293,
+ MD_ERROR_WIN_SERVICE_NOTIFY_CLIENT_LAGGING = 1294,
+ MD_ERROR_WIN_DISK_QUOTA_EXCEEDED = 1295,
+ MD_ERROR_WIN_CONTENT_BLOCKED = 1296,
+ MD_ERROR_WIN_INCOMPATIBLE_SERVICE_PRIVILEGE = 1297,
+ MD_ERROR_WIN_APP_HANG = 1298,
+ MD_ERROR_WIN_INVALID_LABEL = 1299,
+ MD_ERROR_WIN_NOT_ALL_ASSIGNED = 1300,
+ MD_ERROR_WIN_SOME_NOT_MAPPED = 1301,
+ MD_ERROR_WIN_NO_QUOTAS_FOR_ACCOUNT = 1302,
+ MD_ERROR_WIN_LOCAL_USER_SESSION_KEY = 1303,
+ MD_ERROR_WIN_NULL_LM_PASSWORD = 1304,
+ MD_ERROR_WIN_UNKNOWN_REVISION = 1305,
+ MD_ERROR_WIN_REVISION_MISMATCH = 1306,
+ MD_ERROR_WIN_INVALID_OWNER = 1307,
+ MD_ERROR_WIN_INVALID_PRIMARY_GROUP = 1308,
+ MD_ERROR_WIN_NO_IMPERSONATION_TOKEN = 1309,
+ MD_ERROR_WIN_CANT_DISABLE_MANDATORY = 1310,
+ MD_ERROR_WIN_NO_LOGON_SERVERS = 1311,
+ MD_ERROR_WIN_NO_SUCH_LOGON_SESSION = 1312,
+ MD_ERROR_WIN_NO_SUCH_PRIVILEGE = 1313,
+ MD_ERROR_WIN_PRIVILEGE_NOT_HELD = 1314,
+ MD_ERROR_WIN_INVALID_ACCOUNT_NAME = 1315,
+ MD_ERROR_WIN_USER_EXISTS = 1316,
+ MD_ERROR_WIN_NO_SUCH_USER = 1317,
+ MD_ERROR_WIN_GROUP_EXISTS = 1318,
+ MD_ERROR_WIN_NO_SUCH_GROUP = 1319,
+ MD_ERROR_WIN_MEMBER_IN_GROUP = 1320,
+ MD_ERROR_WIN_MEMBER_NOT_IN_GROUP = 1321,
+ MD_ERROR_WIN_LAST_ADMIN = 1322,
+ MD_ERROR_WIN_WRONG_PASSWORD = 1323,
+ MD_ERROR_WIN_ILL_FORMED_PASSWORD = 1324,
+ MD_ERROR_WIN_PASSWORD_RESTRICTION = 1325,
+ MD_ERROR_WIN_LOGON_FAILURE = 1326,
+ MD_ERROR_WIN_ACCOUNT_RESTRICTION = 1327,
+ MD_ERROR_WIN_INVALID_LOGON_HOURS = 1328,
+ MD_ERROR_WIN_INVALID_WORKSTATION = 1329,
+ MD_ERROR_WIN_PASSWORD_EXPIRED = 1330,
+ MD_ERROR_WIN_ACCOUNT_DISABLED = 1331,
+ MD_ERROR_WIN_NONE_MAPPED = 1332,
+ MD_ERROR_WIN_TOO_MANY_LUIDS_REQUESTED = 1333,
+ MD_ERROR_WIN_LUIDS_EXHAUSTED = 1334,
+ MD_ERROR_WIN_INVALID_SUB_AUTHORITY = 1335,
+ MD_ERROR_WIN_INVALID_ACL = 1336,
+ MD_ERROR_WIN_INVALID_SID = 1337,
+ MD_ERROR_WIN_INVALID_SECURITY_DESCR = 1338,
+ MD_ERROR_WIN_BAD_INHERITANCE_ACL = 1340,
+ MD_ERROR_WIN_SERVER_DISABLED = 1341,
+ MD_ERROR_WIN_SERVER_NOT_DISABLED = 1342,
+ MD_ERROR_WIN_INVALID_ID_AUTHORITY = 1343,
+ MD_ERROR_WIN_ALLOTTED_SPACE_EXCEEDED = 1344,
+ MD_ERROR_WIN_INVALID_GROUP_ATTRIBUTES = 1345,
+ MD_ERROR_WIN_BAD_IMPERSONATION_LEVEL = 1346,
+ MD_ERROR_WIN_CANT_OPEN_ANONYMOUS = 1347,
+ MD_ERROR_WIN_BAD_VALIDATION_CLASS = 1348,
+ MD_ERROR_WIN_BAD_TOKEN_TYPE = 1349,
+ MD_ERROR_WIN_NO_SECURITY_ON_OBJECT = 1350,
+ MD_ERROR_WIN_CANT_ACCESS_DOMAIN_INFO = 1351,
+ MD_ERROR_WIN_INVALID_SERVER_STATE = 1352,
+ MD_ERROR_WIN_INVALID_DOMAIN_STATE = 1353,
+ MD_ERROR_WIN_INVALID_DOMAIN_ROLE = 1354,
+ MD_ERROR_WIN_NO_SUCH_DOMAIN = 1355,
+ MD_ERROR_WIN_DOMAIN_EXISTS = 1356,
+ MD_ERROR_WIN_DOMAIN_LIMIT_EXCEEDED = 1357,
+ MD_ERROR_WIN_INTERNAL_DB_CORRUPTION = 1358,
+ MD_ERROR_WIN_INTERNAL_ERROR = 1359,
+ MD_ERROR_WIN_GENERIC_NOT_MAPPED = 1360,
+ MD_ERROR_WIN_BAD_DESCRIPTOR_FORMAT = 1361,
+ MD_ERROR_WIN_NOT_LOGON_PROCESS = 1362,
+ MD_ERROR_WIN_LOGON_SESSION_EXISTS = 1363,
+ MD_ERROR_WIN_NO_SUCH_PACKAGE = 1364,
+ MD_ERROR_WIN_BAD_LOGON_SESSION_STATE = 1365,
+ MD_ERROR_WIN_LOGON_SESSION_COLLISION = 1366,
+ MD_ERROR_WIN_INVALID_LOGON_TYPE = 1367,
+ MD_ERROR_WIN_CANNOT_IMPERSONATE = 1368,
+ MD_ERROR_WIN_RXACT_INVALID_STATE = 1369,
+ MD_ERROR_WIN_RXACT_COMMIT_FAILURE = 1370,
+ MD_ERROR_WIN_SPECIAL_ACCOUNT = 1371,
+ MD_ERROR_WIN_SPECIAL_GROUP = 1372,
+ MD_ERROR_WIN_SPECIAL_USER = 1373,
+ MD_ERROR_WIN_MEMBERS_PRIMARY_GROUP = 1374,
+ MD_ERROR_WIN_TOKEN_ALREADY_IN_USE = 1375,
+ MD_ERROR_WIN_NO_SUCH_ALIAS = 1376,
+ MD_ERROR_WIN_MEMBER_NOT_IN_ALIAS = 1377,
+ MD_ERROR_WIN_MEMBER_IN_ALIAS = 1378,
+ MD_ERROR_WIN_ALIAS_EXISTS = 1379,
+ MD_ERROR_WIN_LOGON_NOT_GRANTED = 1380,
+ MD_ERROR_WIN_TOO_MANY_SECRETS = 1381,
+ MD_ERROR_WIN_SECRET_TOO_LONG = 1382,
+ MD_ERROR_WIN_INTERNAL_DB_ERROR = 1383,
+ MD_ERROR_WIN_TOO_MANY_CONTEXT_IDS = 1384,
+ MD_ERROR_WIN_LOGON_TYPE_NOT_GRANTED = 1385,
+ MD_ERROR_WIN_NT_CROSS_ENCRYPTION_REQUIRED = 1386,
+ MD_ERROR_WIN_NO_SUCH_MEMBER = 1387,
+ MD_ERROR_WIN_INVALID_MEMBER = 1388,
+ MD_ERROR_WIN_TOO_MANY_SIDS = 1389,
+ MD_ERROR_WIN_LM_CROSS_ENCRYPTION_REQUIRED = 1390,
+ MD_ERROR_WIN_NO_INHERITANCE = 1391,
+ MD_ERROR_WIN_FILE_CORRUPT = 1392,
+ MD_ERROR_WIN_DISK_CORRUPT = 1393,
+ MD_ERROR_WIN_NO_USER_SESSION_KEY = 1394,
+ MD_ERROR_WIN_LICENSE_QUOTA_EXCEEDED = 1395,
+ MD_ERROR_WIN_WRONG_TARGET_NAME = 1396,
+ MD_ERROR_WIN_MUTUAL_AUTH_FAILED = 1397,
+ MD_ERROR_WIN_TIME_SKEW = 1398,
+ MD_ERROR_WIN_CURRENT_DOMAIN_NOT_ALLOWED = 1399,
+ MD_ERROR_WIN_INVALID_WINDOW_HANDLE = 1400,
+ MD_ERROR_WIN_INVALID_MENU_HANDLE = 1401,
+ MD_ERROR_WIN_INVALID_CURSOR_HANDLE = 1402,
+ MD_ERROR_WIN_INVALID_ACCEL_HANDLE = 1403,
+ MD_ERROR_WIN_INVALID_HOOK_HANDLE = 1404,
+ MD_ERROR_WIN_INVALID_DWP_HANDLE = 1405,
+ MD_ERROR_WIN_TLW_WITH_WSCHILD = 1406,
+ MD_ERROR_WIN_CANNOT_FIND_WND_CLASS = 1407,
+ MD_ERROR_WIN_WINDOW_OF_OTHER_THREAD = 1408,
+ MD_ERROR_WIN_HOTKEY_ALREADY_REGISTERED = 1409,
+ MD_ERROR_WIN_CLASS_ALREADY_EXISTS = 1410,
+ MD_ERROR_WIN_CLASS_DOES_NOT_EXIST = 1411,
+ MD_ERROR_WIN_CLASS_HAS_WINDOWS = 1412,
+ MD_ERROR_WIN_INVALID_INDEX = 1413,
+ MD_ERROR_WIN_INVALID_ICON_HANDLE = 1414,
+ MD_ERROR_WIN_PRIVATE_DIALOG_INDEX = 1415,
+ MD_ERROR_WIN_LISTBOX_ID_NOT_FOUND = 1416,
+ MD_ERROR_WIN_NO_WILDCARD_CHARACTERS = 1417,
+ MD_ERROR_WIN_CLIPBOARD_NOT_OPEN = 1418,
+ MD_ERROR_WIN_HOTKEY_NOT_REGISTERED = 1419,
+ MD_ERROR_WIN_WINDOW_NOT_DIALOG = 1420,
+ MD_ERROR_WIN_CONTROL_ID_NOT_FOUND = 1421,
+ MD_ERROR_WIN_INVALID_COMBOBOX_MESSAGE = 1422,
+ MD_ERROR_WIN_WINDOW_NOT_COMBOBOX = 1423,
+ MD_ERROR_WIN_INVALID_EDIT_HEIGHT = 1424,
+ MD_ERROR_WIN_DC_NOT_FOUND = 1425,
+ MD_ERROR_WIN_INVALID_HOOK_FILTER = 1426,
+ MD_ERROR_WIN_INVALID_FILTER_PROC = 1427,
+ MD_ERROR_WIN_HOOK_NEEDS_HMOD = 1428,
+ MD_ERROR_WIN_GLOBAL_ONLY_HOOK = 1429,
+ MD_ERROR_WIN_JOURNAL_HOOK_SET = 1430,
+ MD_ERROR_WIN_HOOK_NOT_INSTALLED = 1431,
+ MD_ERROR_WIN_INVALID_LB_MESSAGE = 1432,
+ MD_ERROR_WIN_SETCOUNT_ON_BAD_LB = 1433,
+ MD_ERROR_WIN_LB_WITHOUT_TABSTOPS = 1434,
+ MD_ERROR_WIN_DESTROY_OBJECT_OF_OTHER_THREAD = 1435,
+ MD_ERROR_WIN_CHILD_WINDOW_MENU = 1436,
+ MD_ERROR_WIN_NO_SYSTEM_MENU = 1437,
+ MD_ERROR_WIN_INVALID_MSGBOX_STYLE = 1438,
+ MD_ERROR_WIN_INVALID_SPI_VALUE = 1439,
+ MD_ERROR_WIN_SCREEN_ALREADY_LOCKED = 1440,
+ MD_ERROR_WIN_HWNDS_HAVE_DIFF_PARENT = 1441,
+ MD_ERROR_WIN_NOT_CHILD_WINDOW = 1442,
+ MD_ERROR_WIN_INVALID_GW_COMMAND = 1443,
+ MD_ERROR_WIN_INVALID_THREAD_ID = 1444,
+ MD_ERROR_WIN_NON_MDICHILD_WINDOW = 1445,
+ MD_ERROR_WIN_POPUP_ALREADY_ACTIVE = 1446,
+ MD_ERROR_WIN_NO_SCROLLBARS = 1447,
+ MD_ERROR_WIN_INVALID_SCROLLBAR_RANGE = 1448,
+ MD_ERROR_WIN_INVALID_SHOWWIN_COMMAND = 1449,
+ MD_ERROR_WIN_NO_SYSTEM_RESOURCES = 1450,
+ MD_ERROR_WIN_NONPAGED_SYSTEM_RESOURCES = 1451,
+ MD_ERROR_WIN_PAGED_SYSTEM_RESOURCES = 1452,
+ MD_ERROR_WIN_WORKING_SET_QUOTA = 1453,
+ MD_ERROR_WIN_PAGEFILE_QUOTA = 1454,
+ MD_ERROR_WIN_COMMITMENT_LIMIT = 1455,
+ MD_ERROR_WIN_MENU_ITEM_NOT_FOUND = 1456,
+ MD_ERROR_WIN_INVALID_KEYBOARD_HANDLE = 1457,
+ MD_ERROR_WIN_HOOK_TYPE_NOT_ALLOWED = 1458,
+ MD_ERROR_WIN_REQUIRES_INTERACTIVE_WINDOWSTATION = 1459,
+ MD_ERROR_WIN_TIMEOUT = 1460,
+ MD_ERROR_WIN_INVALID_MONITOR_HANDLE = 1461,
+ MD_ERROR_WIN_INCORRECT_SIZE = 1462,
+ MD_ERROR_WIN_SYMLINK_CLASS_DISABLED = 1463,
+ MD_ERROR_WIN_SYMLINK_NOT_SUPPORTED = 1464,
+ MD_ERROR_WIN_XML_PARSE_ERROR = 1465,
+ MD_ERROR_WIN_XMLDSIG_ERROR = 1466,
+ MD_ERROR_WIN_RESTART_APPLICATION = 1467,
+ MD_ERROR_WIN_WRONG_COMPARTMENT = 1468,
+ MD_ERROR_WIN_AUTHIP_FAILURE = 1469,
+ MD_ERROR_WIN_NO_NVRAM_RESOURCES = 1470,
+ MD_ERROR_WIN_NOT_GUI_PROCESS = 1471,
+ MD_ERROR_WIN_EVENTLOG_FILE_CORRUPT = 1500,
+ MD_ERROR_WIN_EVENTLOG_CANT_START = 1501,
+ MD_ERROR_WIN_LOG_FILE_FULL = 1502,
+ MD_ERROR_WIN_EVENTLOG_FILE_CHANGED = 1503,
+ MD_ERROR_WIN_CONTAINER_ASSIGNED = 1504,
+ MD_ERROR_WIN_JOB_NO_CONTAINER = 1505,
+ MD_ERROR_WIN_INVALID_TASK_NAME = 1550,
+ MD_ERROR_WIN_INVALID_TASK_INDEX = 1551,
+ MD_ERROR_WIN_THREAD_ALREADY_IN_TASK = 1552,
+ MD_ERROR_WIN_INSTALL_SERVICE_FAILURE = 1601,
+ MD_ERROR_WIN_INSTALL_USEREXIT = 1602,
+ MD_ERROR_WIN_INSTALL_FAILURE = 1603,
+ MD_ERROR_WIN_INSTALL_SUSPEND = 1604,
+ MD_ERROR_WIN_UNKNOWN_PRODUCT = 1605,
+ MD_ERROR_WIN_UNKNOWN_FEATURE = 1606,
+ MD_ERROR_WIN_UNKNOWN_COMPONENT = 1607,
+ MD_ERROR_WIN_UNKNOWN_PROPERTY = 1608,
+ MD_ERROR_WIN_INVALID_HANDLE_STATE = 1609,
+ MD_ERROR_WIN_BAD_CONFIGURATION = 1610,
+ MD_ERROR_WIN_INDEX_ABSENT = 1611,
+ MD_ERROR_WIN_INSTALL_SOURCE_ABSENT = 1612,
+ MD_ERROR_WIN_INSTALL_PACKAGE_VERSION = 1613,
+ MD_ERROR_WIN_PRODUCT_UNINSTALLED = 1614,
+ MD_ERROR_WIN_BAD_QUERY_SYNTAX = 1615,
+ MD_ERROR_WIN_INVALID_FIELD = 1616,
+ MD_ERROR_WIN_DEVICE_REMOVED = 1617,
+ MD_ERROR_WIN_INSTALL_ALREADY_RUNNING = 1618,
+ MD_ERROR_WIN_INSTALL_PACKAGE_OPEN_FAILED = 1619,
+ MD_ERROR_WIN_INSTALL_PACKAGE_INVALID = 1620,
+ MD_ERROR_WIN_INSTALL_UI_FAILURE = 1621,
+ MD_ERROR_WIN_INSTALL_LOG_FAILURE = 1622,
+ MD_ERROR_WIN_INSTALL_LANGUAGE_UNSUPPORTED = 1623,
+ MD_ERROR_WIN_INSTALL_TRANSFORM_FAILURE = 1624,
+ MD_ERROR_WIN_INSTALL_PACKAGE_REJECTED = 1625,
+ MD_ERROR_WIN_FUNCTION_NOT_CALLED = 1626,
+ MD_ERROR_WIN_FUNCTION_FAILED = 1627,
+ MD_ERROR_WIN_INVALID_TABLE = 1628,
+ MD_ERROR_WIN_DATATYPE_MISMATCH = 1629,
+ MD_ERROR_WIN_UNSUPPORTED_TYPE = 1630,
+ MD_ERROR_WIN_CREATE_FAILED = 1631,
+ MD_ERROR_WIN_INSTALL_TEMP_UNWRITABLE = 1632,
+ MD_ERROR_WIN_INSTALL_PLATFORM_UNSUPPORTED = 1633,
+ MD_ERROR_WIN_INSTALL_NOTUSED = 1634,
+ MD_ERROR_WIN_PATCH_PACKAGE_OPEN_FAILED = 1635,
+ MD_ERROR_WIN_PATCH_PACKAGE_INVALID = 1636,
+ MD_ERROR_WIN_PATCH_PACKAGE_UNSUPPORTED = 1637,
+ MD_ERROR_WIN_PRODUCT_VERSION = 1638,
+ MD_ERROR_WIN_INVALID_COMMAND_LINE = 1639,
+ MD_ERROR_WIN_INSTALL_REMOTE_DISALLOWED = 1640,
+ MD_ERROR_WIN_SUCCESS_REBOOT_INITIATED = 1641,
+ MD_ERROR_WIN_PATCH_TARGET_NOT_FOUND = 1642,
+ MD_ERROR_WIN_PATCH_PACKAGE_REJECTED = 1643,
+ MD_ERROR_WIN_INSTALL_TRANSFORM_REJECTED = 1644,
+ MD_ERROR_WIN_INSTALL_REMOTE_PROHIBITED = 1645,
+ MD_ERROR_WIN_PATCH_REMOVAL_UNSUPPORTED = 1646,
+ MD_ERROR_WIN_UNKNOWN_PATCH = 1647,
+ MD_ERROR_WIN_PATCH_NO_SEQUENCE = 1648,
+ MD_ERROR_WIN_PATCH_REMOVAL_DISALLOWED = 1649,
+ MD_ERROR_WIN_INVALID_PATCH_XML = 1650,
+ MD_ERROR_WIN_PATCH_MANAGED_ADVERTISED_PRODUCT = 1651,
+ MD_ERROR_WIN_INSTALL_SERVICE_SAFEBOOT = 1652,
+ MD_ERROR_WIN_FAIL_FAST_EXCEPTION = 1653,
+ MD_ERROR_WIN_INSTALL_REJECTED = 1654,
+ MD_ERROR_WIN_DYNAMIC_CODE_BLOCKED = 1655,
+ MD_ERROR_WIN_NOT_SAME_OBJECT = 1656,
+ MD_ERROR_WIN_STRICT_CFG_VIOLATION = 1657,
+ MD_ERROR_WIN_SET_CONTEXT_DENIED = 1660,
+ MD_ERROR_WIN_CROSS_PARTITION_VIOLATION = 1661,
+ MD_ERROR_WIN_RETURN_ADDRESS_HIJACK_ATTEMPT = 1662,
+ MD_ERROR_WIN_INVALID_USER_BUFFER = 1784,
+ MD_ERROR_WIN_UNRECOGNIZED_MEDIA = 1785,
+ MD_ERROR_WIN_NO_TRUST_LSA_SECRET = 1786,
+ MD_ERROR_WIN_NO_TRUST_SAM_ACCOUNT = 1787,
+ MD_ERROR_WIN_TRUSTED_DOMAIN_FAILURE = 1788,
+ MD_ERROR_WIN_TRUSTED_RELATIONSHIP_FAILURE = 1789,
+ MD_ERROR_WIN_TRUST_FAILURE = 1790,
+ MD_ERROR_WIN_NETLOGON_NOT_STARTED = 1792,
+ MD_ERROR_WIN_ACCOUNT_EXPIRED = 1793,
+ MD_ERROR_WIN_REDIRECTOR_HAS_OPEN_HANDLES = 1794,
+ MD_ERROR_WIN_PRINTER_DRIVER_ALREADY_INSTALLED = 1795,
+ MD_ERROR_WIN_UNKNOWN_PORT = 1796,
+ MD_ERROR_WIN_UNKNOWN_PRINTER_DRIVER = 1797,
+ MD_ERROR_WIN_UNKNOWN_PRINTPROCESSOR = 1798,
+ MD_ERROR_WIN_INVALID_SEPARATOR_FILE = 1799,
+ MD_ERROR_WIN_INVALID_PRIORITY = 1800,
+ MD_ERROR_WIN_INVALID_PRINTER_NAME = 1801,
+ MD_ERROR_WIN_PRINTER_ALREADY_EXISTS = 1802,
+ MD_ERROR_WIN_INVALID_PRINTER_COMMAND = 1803,
+ MD_ERROR_WIN_INVALID_DATATYPE = 1804,
+ MD_ERROR_WIN_INVALID_ENVIRONMENT = 1805,
+ MD_ERROR_WIN_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT = 1807,
+ MD_ERROR_WIN_NOLOGON_WORKSTATION_TRUST_ACCOUNT = 1808,
+ MD_ERROR_WIN_NOLOGON_SERVER_TRUST_ACCOUNT = 1809,
+ MD_ERROR_WIN_DOMAIN_TRUST_INCONSISTENT = 1810,
+ MD_ERROR_WIN_SERVER_HAS_OPEN_HANDLES = 1811,
+ MD_ERROR_WIN_RESOURCE_DATA_NOT_FOUND = 1812,
+ MD_ERROR_WIN_RESOURCE_TYPE_NOT_FOUND = 1813,
+ MD_ERROR_WIN_RESOURCE_NAME_NOT_FOUND = 1814,
+ MD_ERROR_WIN_RESOURCE_LANG_NOT_FOUND = 1815,
+ MD_ERROR_WIN_NOT_ENOUGH_QUOTA = 1816,
+ MD_ERROR_WIN_INVALID_TIME = 1901,
+ MD_ERROR_WIN_INVALID_FORM_NAME = 1902,
+ MD_ERROR_WIN_INVALID_FORM_SIZE = 1903,
+ MD_ERROR_WIN_ALREADY_WAITING = 1904,
+ MD_ERROR_WIN_PRINTER_DELETED = 1905,
+ MD_ERROR_WIN_INVALID_PRINTER_STATE = 1906,
+ MD_ERROR_WIN_PASSWORD_MUST_CHANGE = 1907,
+ MD_ERROR_WIN_DOMAIN_CONTROLLER_NOT_FOUND = 1908,
+ MD_ERROR_WIN_ACCOUNT_LOCKED_OUT = 1909,
+ MD_ERROR_WIN_NO_SITENAME = 1919,
+ MD_ERROR_WIN_CANT_ACCESS_FILE = 1920,
+ MD_ERROR_WIN_CANT_RESOLVE_FILENAME = 1921,
+ MD_ERROR_WIN_KM_DRIVER_BLOCKED = 1930,
+ MD_ERROR_WIN_CONTEXT_EXPIRED = 1931,
+ MD_ERROR_WIN_PER_USER_TRUST_QUOTA_EXCEEDED = 1932,
+ MD_ERROR_WIN_ALL_USER_TRUST_QUOTA_EXCEEDED = 1933,
+ MD_ERROR_WIN_USER_DELETE_TRUST_QUOTA_EXCEEDED = 1934,
+ MD_ERROR_WIN_AUTHENTICATION_FIREWALL_FAILED = 1935,
+ MD_ERROR_WIN_REMOTE_PRINT_CONNECTIONS_BLOCKED = 1936,
+ MD_ERROR_WIN_NTLM_BLOCKED = 1937,
+ MD_ERROR_WIN_PASSWORD_CHANGE_REQUIRED = 1938,
+ MD_ERROR_WIN_LOST_MODE_LOGON_RESTRICTION = 1939,
+ MD_ERROR_WIN_INVALID_PIXEL_FORMAT = 2000,
+ MD_ERROR_WIN_BAD_DRIVER = 2001,
+ MD_ERROR_WIN_INVALID_WINDOW_STYLE = 2002,
+ MD_ERROR_WIN_METAFILE_NOT_SUPPORTED = 2003,
+ MD_ERROR_WIN_TRANSFORM_NOT_SUPPORTED = 2004,
+ MD_ERROR_WIN_CLIPPING_NOT_SUPPORTED = 2005,
+ MD_ERROR_WIN_INVALID_CMM = 2010,
+ MD_ERROR_WIN_INVALID_PROFILE = 2011,
+ MD_ERROR_WIN_TAG_NOT_FOUND = 2012,
+ MD_ERROR_WIN_TAG_NOT_PRESENT = 2013,
+ MD_ERROR_WIN_DUPLICATE_TAG = 2014,
+ MD_ERROR_WIN_PROFILE_NOT_ASSOCIATED_WITH_DEVICE = 2015,
+ MD_ERROR_WIN_PROFILE_NOT_FOUND = 2016,
+ MD_ERROR_WIN_INVALID_COLORSPACE = 2017,
+ MD_ERROR_WIN_ICM_NOT_ENABLED = 2018,
+ MD_ERROR_WIN_DELETING_ICM_XFORM = 2019,
+ MD_ERROR_WIN_INVALID_TRANSFORM = 2020,
+ MD_ERROR_WIN_COLORSPACE_MISMATCH = 2021,
+ MD_ERROR_WIN_INVALID_COLORINDEX = 2022,
+ MD_ERROR_WIN_PROFILE_DOES_NOT_MATCH_DEVICE = 2023,
+ MD_ERROR_WIN_CONNECTED_OTHER_PASSWORD = 2108,
+ MD_ERROR_WIN_CONNECTED_OTHER_PASSWORD_DEFAULT = 2109,
+ MD_ERROR_WIN_BAD_USERNAME = 2202,
+ MD_ERROR_WIN_NOT_CONNECTED = 2250,
+ MD_ERROR_WIN_OPEN_FILES = 2401,
+ MD_ERROR_WIN_ACTIVE_CONNECTIONS = 2402,
+ MD_ERROR_WIN_DEVICE_IN_USE = 2404,
+ MD_ERROR_WIN_UNKNOWN_PRINT_MONITOR = 3000,
+ MD_ERROR_WIN_PRINTER_DRIVER_IN_USE = 3001,
+ MD_ERROR_WIN_SPOOL_FILE_NOT_FOUND = 3002,
+ MD_ERROR_WIN_SPL_NO_STARTDOC = 3003,
+ MD_ERROR_WIN_SPL_NO_ADDJOB = 3004,
+ MD_ERROR_WIN_PRINT_PROCESSOR_ALREADY_INSTALLED = 3005,
+ MD_ERROR_WIN_PRINT_MONITOR_ALREADY_INSTALLED = 3006,
+ MD_ERROR_WIN_INVALID_PRINT_MONITOR = 3007,
+ MD_ERROR_WIN_PRINT_MONITOR_IN_USE = 3008,
+ MD_ERROR_WIN_PRINTER_HAS_JOBS_QUEUED = 3009,
+ MD_ERROR_WIN_SUCCESS_REBOOT_REQUIRED = 3010,
+ MD_ERROR_WIN_SUCCESS_RESTART_REQUIRED = 3011,
+ MD_ERROR_WIN_PRINTER_NOT_FOUND = 3012,
+ MD_ERROR_WIN_PRINTER_DRIVER_WARNED = 3013,
+ MD_ERROR_WIN_PRINTER_DRIVER_BLOCKED = 3014,
+ MD_ERROR_WIN_PRINTER_DRIVER_PACKAGE_IN_USE = 3015,
+ MD_ERROR_WIN_CORE_DRIVER_PACKAGE_NOT_FOUND = 3016,
+ MD_ERROR_WIN_FAIL_REBOOT_REQUIRED = 3017,
+ MD_ERROR_WIN_FAIL_REBOOT_INITIATED = 3018,
+ MD_ERROR_WIN_PRINTER_DRIVER_DOWNLOAD_NEEDED = 3019,
+ MD_ERROR_WIN_PRINT_JOB_RESTART_REQUIRED = 3020,
+ MD_ERROR_WIN_INVALID_PRINTER_DRIVER_MANIFEST = 3021,
+ MD_ERROR_WIN_PRINTER_NOT_SHAREABLE = 3022,
+ MD_ERROR_WIN_REQUEST_PAUSED = 3050,
+ MD_ERROR_WIN_APPEXEC_CONDITION_NOT_SATISFIED = 3060,
+ MD_ERROR_WIN_APPEXEC_HANDLE_INVALIDATED = 3061,
+ MD_ERROR_WIN_APPEXEC_INVALID_HOST_GENERATION = 3062,
+ MD_ERROR_WIN_APPEXEC_UNEXPECTED_PROCESS_REGISTRATION = 3063,
+ MD_ERROR_WIN_APPEXEC_INVALID_HOST_STATE = 3064,
+ MD_ERROR_WIN_APPEXEC_NO_DONOR = 3065,
+ MD_ERROR_WIN_APPEXEC_HOST_ID_MISMATCH = 3066,
+ MD_ERROR_WIN_APPEXEC_UNKNOWN_USER = 3067,
+ MD_ERROR_WIN_IO_REISSUE_AS_CACHED = 3950,
+ MD_ERROR_WIN_WINS_INTERNAL = 4000,
+ MD_ERROR_WIN_CAN_NOT_DEL_LOCAL_WINS = 4001,
+ MD_ERROR_WIN_STATIC_INIT = 4002,
+ MD_ERROR_WIN_INC_BACKUP = 4003,
+ MD_ERROR_WIN_FULL_BACKUP = 4004,
+ MD_ERROR_WIN_REC_NON_EXISTENT = 4005,
+ MD_ERROR_WIN_RPL_NOT_ALLOWED = 4006,
+ MD_ERROR_WIN_DHCP_ADDRESS_CONFLICT = 4100,
+ MD_ERROR_WIN_WMI_GUID_NOT_FOUND = 4200,
+ MD_ERROR_WIN_WMI_INSTANCE_NOT_FOUND = 4201,
+ MD_ERROR_WIN_WMI_ITEMID_NOT_FOUND = 4202,
+ MD_ERROR_WIN_WMI_TRY_AGAIN = 4203,
+ MD_ERROR_WIN_WMI_DP_NOT_FOUND = 4204,
+ MD_ERROR_WIN_WMI_UNRESOLVED_INSTANCE_REF = 4205,
+ MD_ERROR_WIN_WMI_ALREADY_ENABLED = 4206,
+ MD_ERROR_WIN_WMI_GUID_DISCONNECTED = 4207,
+ MD_ERROR_WIN_WMI_SERVER_UNAVAILABLE = 4208,
+ MD_ERROR_WIN_WMI_DP_FAILED = 4209,
+ MD_ERROR_WIN_WMI_INVALID_MOF = 4210,
+ MD_ERROR_WIN_WMI_INVALID_REGINFO = 4211,
+ MD_ERROR_WIN_WMI_ALREADY_DISABLED = 4212,
+ MD_ERROR_WIN_WMI_READ_ONLY = 4213,
+ MD_ERROR_WIN_WMI_SET_FAILURE = 4214,
+ MD_ERROR_WIN_NOT_APPCONTAINER = 4250,
+ MD_ERROR_WIN_APPCONTAINER_REQUIRED = 4251,
+ MD_ERROR_WIN_NOT_SUPPORTED_IN_APPCONTAINER = 4252,
+ MD_ERROR_WIN_INVALID_PACKAGE_SID_LENGTH = 4253,
+ MD_ERROR_WIN_INVALID_MEDIA = 4300,
+ MD_ERROR_WIN_INVALID_LIBRARY = 4301,
+ MD_ERROR_WIN_INVALID_MEDIA_POOL = 4302,
+ MD_ERROR_WIN_DRIVE_MEDIA_MISMATCH = 4303,
+ MD_ERROR_WIN_MEDIA_OFFLINE = 4304,
+ MD_ERROR_WIN_LIBRARY_OFFLINE = 4305,
+ MD_ERROR_WIN_EMPTY = 4306,
+ MD_ERROR_WIN_NOT_EMPTY = 4307,
+ MD_ERROR_WIN_MEDIA_UNAVAILABLE = 4308,
+ MD_ERROR_WIN_RESOURCE_DISABLED = 4309,
+ MD_ERROR_WIN_INVALID_CLEANER = 4310,
+ MD_ERROR_WIN_UNABLE_TO_CLEAN = 4311,
+ MD_ERROR_WIN_OBJECT_NOT_FOUND = 4312,
+ MD_ERROR_WIN_DATABASE_FAILURE = 4313,
+ MD_ERROR_WIN_DATABASE_FULL = 4314,
+ MD_ERROR_WIN_MEDIA_INCOMPATIBLE = 4315,
+ MD_ERROR_WIN_RESOURCE_NOT_PRESENT = 4316,
+ MD_ERROR_WIN_INVALID_OPERATION = 4317,
+ MD_ERROR_WIN_MEDIA_NOT_AVAILABLE = 4318,
+ MD_ERROR_WIN_DEVICE_NOT_AVAILABLE = 4319,
+ MD_ERROR_WIN_REQUEST_REFUSED = 4320,
+ MD_ERROR_WIN_INVALID_DRIVE_OBJECT = 4321,
+ MD_ERROR_WIN_LIBRARY_FULL = 4322,
+ MD_ERROR_WIN_MEDIUM_NOT_ACCESSIBLE = 4323,
+ MD_ERROR_WIN_UNABLE_TO_LOAD_MEDIUM = 4324,
+ MD_ERROR_WIN_UNABLE_TO_INVENTORY_DRIVE = 4325,
+ MD_ERROR_WIN_UNABLE_TO_INVENTORY_SLOT = 4326,
+ MD_ERROR_WIN_UNABLE_TO_INVENTORY_TRANSPORT = 4327,
+ MD_ERROR_WIN_TRANSPORT_FULL = 4328,
+ MD_ERROR_WIN_CONTROLLING_IEPORT = 4329,
+ MD_ERROR_WIN_UNABLE_TO_EJECT_MOUNTED_MEDIA = 4330,
+ MD_ERROR_WIN_CLEANER_SLOT_SET = 4331,
+ MD_ERROR_WIN_CLEANER_SLOT_NOT_SET = 4332,
+ MD_ERROR_WIN_CLEANER_CARTRIDGE_SPENT = 4333,
+ MD_ERROR_WIN_UNEXPECTED_OMID = 4334,
+ MD_ERROR_WIN_CANT_DELETE_LAST_ITEM = 4335,
+ MD_ERROR_WIN_MESSAGE_EXCEEDS_MAX_SIZE = 4336,
+ MD_ERROR_WIN_VOLUME_CONTAINS_SYS_FILES = 4337,
+ MD_ERROR_WIN_INDIGENOUS_TYPE = 4338,
+ MD_ERROR_WIN_NO_SUPPORTING_DRIVES = 4339,
+ MD_ERROR_WIN_CLEANER_CARTRIDGE_INSTALLED = 4340,
+ MD_ERROR_WIN_IEPORT_FULL = 4341,
+ MD_ERROR_WIN_FILE_OFFLINE = 4350,
+ MD_ERROR_WIN_REMOTE_STORAGE_NOT_ACTIVE = 4351,
+ MD_ERROR_WIN_REMOTE_STORAGE_MEDIA_ERROR = 4352,
+ MD_ERROR_WIN_NOT_A_REPARSE_POINT = 4390,
+ MD_ERROR_WIN_REPARSE_ATTRIBUTE_CONFLICT = 4391,
+ MD_ERROR_WIN_INVALID_REPARSE_DATA = 4392,
+ MD_ERROR_WIN_REPARSE_TAG_INVALID = 4393,
+ MD_ERROR_WIN_REPARSE_TAG_MISMATCH = 4394,
+ MD_ERROR_WIN_REPARSE_POINT_ENCOUNTERED = 4395,
+ MD_ERROR_WIN_APP_DATA_NOT_FOUND = 4400,
+ MD_ERROR_WIN_APP_DATA_EXPIRED = 4401,
+ MD_ERROR_WIN_APP_DATA_CORRUPT = 4402,
+ MD_ERROR_WIN_APP_DATA_LIMIT_EXCEEDED = 4403,
+ MD_ERROR_WIN_APP_DATA_REBOOT_REQUIRED = 4404,
+ MD_ERROR_WIN_SECUREBOOT_ROLLBACK_DETECTED = 4420,
+ MD_ERROR_WIN_SECUREBOOT_POLICY_VIOLATION = 4421,
+ MD_ERROR_WIN_SECUREBOOT_INVALID_POLICY = 4422,
+ MD_ERROR_WIN_SECUREBOOT_POLICY_PUBLISHER_NOT_FOUND = 4423,
+ MD_ERROR_WIN_SECUREBOOT_POLICY_NOT_SIGNED = 4424,
+ MD_ERROR_WIN_SECUREBOOT_NOT_ENABLED = 4425,
+ MD_ERROR_WIN_SECUREBOOT_FILE_REPLACED = 4426,
+ MD_ERROR_WIN_SECUREBOOT_POLICY_NOT_AUTHORIZED = 4427,
+ MD_ERROR_WIN_SECUREBOOT_POLICY_UNKNOWN = 4428,
+ MD_ERROR_WIN_SECUREBOOT_POLICY_MISSING_ANTIROLLBACKVERSION = 4429,
+ MD_ERROR_WIN_SECUREBOOT_PLATFORM_ID_MISMATCH = 4430,
+ MD_ERROR_WIN_SECUREBOOT_POLICY_ROLLBACK_DETECTED = 4431,
+ MD_ERROR_WIN_SECUREBOOT_POLICY_UPGRADE_MISMATCH = 4432,
+ MD_ERROR_WIN_SECUREBOOT_REQUIRED_POLICY_FILE_MISSING = 4433,
+ MD_ERROR_WIN_SECUREBOOT_NOT_BASE_POLICY = 4434,
+ MD_ERROR_WIN_SECUREBOOT_NOT_SUPPLEMENTAL_POLICY = 4435,
+ MD_ERROR_WIN_OFFLOAD_READ_FLT_NOT_SUPPORTED = 4440,
+ MD_ERROR_WIN_OFFLOAD_WRITE_FLT_NOT_SUPPORTED = 4441,
+ MD_ERROR_WIN_OFFLOAD_READ_FILE_NOT_SUPPORTED = 4442,
+ MD_ERROR_WIN_OFFLOAD_WRITE_FILE_NOT_SUPPORTED = 4443,
+ MD_ERROR_WIN_ALREADY_HAS_STREAM_ID = 4444,
+ MD_ERROR_WIN_SMR_GARBAGE_COLLECTION_REQUIRED = 4445,
+ MD_ERROR_WIN_WOF_WIM_HEADER_CORRUPT = 4446,
+ MD_ERROR_WIN_WOF_WIM_RESOURCE_TABLE_CORRUPT = 4447,
+ MD_ERROR_WIN_WOF_FILE_RESOURCE_TABLE_CORRUPT = 4448,
+ MD_ERROR_WIN_VOLUME_NOT_SIS_ENABLED = 4500,
+ MD_ERROR_WIN_SYSTEM_INTEGRITY_ROLLBACK_DETECTED = 4550,
+ MD_ERROR_WIN_SYSTEM_INTEGRITY_POLICY_VIOLATION = 4551,
+ MD_ERROR_WIN_SYSTEM_INTEGRITY_INVALID_POLICY = 4552,
+ MD_ERROR_WIN_SYSTEM_INTEGRITY_POLICY_NOT_SIGNED = 4553,
+ MD_ERROR_WIN_SYSTEM_INTEGRITY_TOO_MANY_POLICIES = 4554,
+ MD_ERROR_WIN_SYSTEM_INTEGRITY_SUPPLEMENTAL_POLICY_NOT_AUTHORIZED = 4555,
+ MD_ERROR_WIN_VSM_NOT_INITIALIZED = 4560,
+ MD_ERROR_WIN_VSM_DMA_PROTECTION_NOT_IN_USE = 4561,
+ MD_ERROR_WIN_PLATFORM_MANIFEST_NOT_AUTHORIZED = 4570,
+ MD_ERROR_WIN_PLATFORM_MANIFEST_INVALID = 4571,
+ MD_ERROR_WIN_PLATFORM_MANIFEST_FILE_NOT_AUTHORIZED = 4572,
+ MD_ERROR_WIN_PLATFORM_MANIFEST_CATALOG_NOT_AUTHORIZED = 4573,
+ MD_ERROR_WIN_PLATFORM_MANIFEST_BINARY_ID_NOT_FOUND = 4574,
+ MD_ERROR_WIN_PLATFORM_MANIFEST_NOT_ACTIVE = 4575,
+ MD_ERROR_WIN_PLATFORM_MANIFEST_NOT_SIGNED = 4576,
+ MD_ERROR_WIN_DEPENDENT_RESOURCE_EXISTS = 5001,
+ MD_ERROR_WIN_DEPENDENCY_NOT_FOUND = 5002,
+ MD_ERROR_WIN_DEPENDENCY_ALREADY_EXISTS = 5003,
+ MD_ERROR_WIN_RESOURCE_NOT_ONLINE = 5004,
+ MD_ERROR_WIN_HOST_NODE_NOT_AVAILABLE = 5005,
+ MD_ERROR_WIN_RESOURCE_NOT_AVAILABLE = 5006,
+ MD_ERROR_WIN_RESOURCE_NOT_FOUND = 5007,
+ MD_ERROR_WIN_SHUTDOWN_CLUSTER = 5008,
+ MD_ERROR_WIN_CANT_EVICT_ACTIVE_NODE = 5009,
+ MD_ERROR_WIN_OBJECT_ALREADY_EXISTS = 5010,
+ MD_ERROR_WIN_OBJECT_IN_LIST = 5011,
+ MD_ERROR_WIN_GROUP_NOT_AVAILABLE = 5012,
+ MD_ERROR_WIN_GROUP_NOT_FOUND = 5013,
+ MD_ERROR_WIN_GROUP_NOT_ONLINE = 5014,
+ MD_ERROR_WIN_HOST_NODE_NOT_RESOURCE_OWNER = 5015,
+ MD_ERROR_WIN_HOST_NODE_NOT_GROUP_OWNER = 5016,
+ MD_ERROR_WIN_RESMON_CREATE_FAILED = 5017,
+ MD_ERROR_WIN_RESMON_ONLINE_FAILED = 5018,
+ MD_ERROR_WIN_RESOURCE_ONLINE = 5019,
+ MD_ERROR_WIN_QUORUM_RESOURCE = 5020,
+ MD_ERROR_WIN_NOT_QUORUM_CAPABLE = 5021,
+ MD_ERROR_WIN_CLUSTER_SHUTTING_DOWN = 5022,
+ MD_ERROR_WIN_INVALID_STATE = 5023,
+ MD_ERROR_WIN_RESOURCE_PROPERTIES_STORED = 5024,
+ MD_ERROR_WIN_NOT_QUORUM_CLASS = 5025,
+ MD_ERROR_WIN_CORE_RESOURCE = 5026,
+ MD_ERROR_WIN_QUORUM_RESOURCE_ONLINE_FAILED = 5027,
+ MD_ERROR_WIN_QUORUMLOG_OPEN_FAILED = 5028,
+ MD_ERROR_WIN_CLUSTERLOG_CORRUPT = 5029,
+ MD_ERROR_WIN_CLUSTERLOG_RECORD_EXCEEDS_MAXSIZE = 5030,
+ MD_ERROR_WIN_CLUSTERLOG_EXCEEDS_MAXSIZE = 5031,
+ MD_ERROR_WIN_CLUSTERLOG_CHKPOINT_NOT_FOUND = 5032,
+ MD_ERROR_WIN_CLUSTERLOG_NOT_ENOUGH_SPACE = 5033,
+ MD_ERROR_WIN_QUORUM_OWNER_ALIVE = 5034,
+ MD_ERROR_WIN_NETWORK_NOT_AVAILABLE = 5035,
+ MD_ERROR_WIN_NODE_NOT_AVAILABLE = 5036,
+ MD_ERROR_WIN_ALL_NODES_NOT_AVAILABLE = 5037,
+ MD_ERROR_WIN_RESOURCE_FAILED = 5038,
+ MD_ERROR_WIN_CLUSTER_INVALID_NODE = 5039,
+ MD_ERROR_WIN_CLUSTER_NODE_EXISTS = 5040,
+ MD_ERROR_WIN_CLUSTER_JOIN_IN_PROGRESS = 5041,
+ MD_ERROR_WIN_CLUSTER_NODE_NOT_FOUND = 5042,
+ MD_ERROR_WIN_CLUSTER_LOCAL_NODE_NOT_FOUND = 5043,
+ MD_ERROR_WIN_CLUSTER_NETWORK_EXISTS = 5044,
+ MD_ERROR_WIN_CLUSTER_NETWORK_NOT_FOUND = 5045,
+ MD_ERROR_WIN_CLUSTER_NETINTERFACE_EXISTS = 5046,
+ MD_ERROR_WIN_CLUSTER_NETINTERFACE_NOT_FOUND = 5047,
+ MD_ERROR_WIN_CLUSTER_INVALID_REQUEST = 5048,
+ MD_ERROR_WIN_CLUSTER_INVALID_NETWORK_PROVIDER = 5049,
+ MD_ERROR_WIN_CLUSTER_NODE_DOWN = 5050,
+ MD_ERROR_WIN_CLUSTER_NODE_UNREACHABLE = 5051,
+ MD_ERROR_WIN_CLUSTER_NODE_NOT_MEMBER = 5052,
+ MD_ERROR_WIN_CLUSTER_JOIN_NOT_IN_PROGRESS = 5053,
+ MD_ERROR_WIN_CLUSTER_INVALID_NETWORK = 5054,
+ MD_ERROR_WIN_CLUSTER_NODE_UP = 5056,
+ MD_ERROR_WIN_CLUSTER_IPADDR_IN_USE = 5057,
+ MD_ERROR_WIN_CLUSTER_NODE_NOT_PAUSED = 5058,
+ MD_ERROR_WIN_CLUSTER_NO_SECURITY_CONTEXT = 5059,
+ MD_ERROR_WIN_CLUSTER_NETWORK_NOT_INTERNAL = 5060,
+ MD_ERROR_WIN_CLUSTER_NODE_ALREADY_UP = 5061,
+ MD_ERROR_WIN_CLUSTER_NODE_ALREADY_DOWN = 5062,
+ MD_ERROR_WIN_CLUSTER_NETWORK_ALREADY_ONLINE = 5063,
+ MD_ERROR_WIN_CLUSTER_NETWORK_ALREADY_OFFLINE = 5064,
+ MD_ERROR_WIN_CLUSTER_NODE_ALREADY_MEMBER = 5065,
+ MD_ERROR_WIN_CLUSTER_LAST_INTERNAL_NETWORK = 5066,
+ MD_ERROR_WIN_CLUSTER_NETWORK_HAS_DEPENDENTS = 5067,
+ MD_ERROR_WIN_INVALID_OPERATION_ON_QUORUM = 5068,
+ MD_ERROR_WIN_DEPENDENCY_NOT_ALLOWED = 5069,
+ MD_ERROR_WIN_CLUSTER_NODE_PAUSED = 5070,
+ MD_ERROR_WIN_NODE_CANT_HOST_RESOURCE = 5071,
+ MD_ERROR_WIN_CLUSTER_NODE_NOT_READY = 5072,
+ MD_ERROR_WIN_CLUSTER_NODE_SHUTTING_DOWN = 5073,
+ MD_ERROR_WIN_CLUSTER_JOIN_ABORTED = 5074,
+ MD_ERROR_WIN_CLUSTER_INCOMPATIBLE_VERSIONS = 5075,
+ MD_ERROR_WIN_CLUSTER_MAXNUM_OF_RESOURCES_EXCEEDED = 5076,
+ MD_ERROR_WIN_CLUSTER_SYSTEM_CONFIG_CHANGED = 5077,
+ MD_ERROR_WIN_CLUSTER_RESOURCE_TYPE_NOT_FOUND = 5078,
+ MD_ERROR_WIN_CLUSTER_RESTYPE_NOT_SUPPORTED = 5079,
+ MD_ERROR_WIN_CLUSTER_RESNAME_NOT_FOUND = 5080,
+ MD_ERROR_WIN_CLUSTER_NO_RPC_PACKAGES_REGISTERED = 5081,
+ MD_ERROR_WIN_CLUSTER_OWNER_NOT_IN_PREFLIST = 5082,
+ MD_ERROR_WIN_CLUSTER_DATABASE_SEQMISMATCH = 5083,
+ MD_ERROR_WIN_RESMON_INVALID_STATE = 5084,
+ MD_ERROR_WIN_CLUSTER_GUM_NOT_LOCKER = 5085,
+ MD_ERROR_WIN_QUORUM_DISK_NOT_FOUND = 5086,
+ MD_ERROR_WIN_DATABASE_BACKUP_CORRUPT = 5087,
+ MD_ERROR_WIN_CLUSTER_NODE_ALREADY_HAS_DFS_ROOT = 5088,
+ MD_ERROR_WIN_RESOURCE_PROPERTY_UNCHANGEABLE = 5089,
+ MD_ERROR_WIN_NO_ADMIN_ACCESS_POINT = 5090,
+ MD_ERROR_WIN_CLUSTER_MEMBERSHIP_INVALID_STATE = 5890,
+ MD_ERROR_WIN_CLUSTER_QUORUMLOG_NOT_FOUND = 5891,
+ MD_ERROR_WIN_CLUSTER_MEMBERSHIP_HALT = 5892,
+ MD_ERROR_WIN_CLUSTER_INSTANCE_ID_MISMATCH = 5893,
+ MD_ERROR_WIN_CLUSTER_NETWORK_NOT_FOUND_FOR_IP = 5894,
+ MD_ERROR_WIN_CLUSTER_PROPERTY_DATA_TYPE_MISMATCH = 5895,
+ MD_ERROR_WIN_CLUSTER_EVICT_WITHOUT_CLEANUP = 5896,
+ MD_ERROR_WIN_CLUSTER_PARAMETER_MISMATCH = 5897,
+ MD_ERROR_WIN_NODE_CANNOT_BE_CLUSTERED = 5898,
+ MD_ERROR_WIN_CLUSTER_WRONG_OS_VERSION = 5899,
+ MD_ERROR_WIN_CLUSTER_CANT_CREATE_DUP_CLUSTER_NAME = 5900,
+ MD_ERROR_WIN_CLUSCFG_ALREADY_COMMITTED = 5901,
+ MD_ERROR_WIN_CLUSCFG_ROLLBACK_FAILED = 5902,
+ MD_ERROR_WIN_CLUSCFG_SYSTEM_DISK_DRIVE_LETTER_CONFLICT = 5903,
+ MD_ERROR_WIN_CLUSTER_OLD_VERSION = 5904,
+ MD_ERROR_WIN_CLUSTER_MISMATCHED_COMPUTER_ACCT_NAME = 5905,
+ MD_ERROR_WIN_CLUSTER_NO_NET_ADAPTERS = 5906,
+ MD_ERROR_WIN_CLUSTER_POISONED = 5907,
+ MD_ERROR_WIN_CLUSTER_GROUP_MOVING = 5908,
+ MD_ERROR_WIN_CLUSTER_RESOURCE_TYPE_BUSY = 5909,
+ MD_ERROR_WIN_RESOURCE_CALL_TIMED_OUT = 5910,
+ MD_ERROR_WIN_INVALID_CLUSTER_IPV6_ADDRESS = 5911,
+ MD_ERROR_WIN_CLUSTER_INTERNAL_INVALID_FUNCTION = 5912,
+ MD_ERROR_WIN_CLUSTER_PARAMETER_OUT_OF_BOUNDS = 5913,
+ MD_ERROR_WIN_CLUSTER_PARTIAL_SEND = 5914,
+ MD_ERROR_WIN_CLUSTER_REGISTRY_INVALID_FUNCTION = 5915,
+ MD_ERROR_WIN_CLUSTER_INVALID_STRING_TERMINATION = 5916,
+ MD_ERROR_WIN_CLUSTER_INVALID_STRING_FORMAT = 5917,
+ MD_ERROR_WIN_CLUSTER_DATABASE_TRANSACTION_IN_PROGRESS = 5918,
+ MD_ERROR_WIN_CLUSTER_DATABASE_TRANSACTION_NOT_IN_PROGRESS = 5919,
+ MD_ERROR_WIN_CLUSTER_NULL_DATA = 5920,
+ MD_ERROR_WIN_CLUSTER_PARTIAL_READ = 5921,
+ MD_ERROR_WIN_CLUSTER_PARTIAL_WRITE = 5922,
+ MD_ERROR_WIN_CLUSTER_CANT_DESERIALIZE_DATA = 5923,
+ MD_ERROR_WIN_DEPENDENT_RESOURCE_PROPERTY_CONFLICT = 5924,
+ MD_ERROR_WIN_CLUSTER_NO_QUORUM = 5925,
+ MD_ERROR_WIN_CLUSTER_INVALID_IPV6_NETWORK = 5926,
+ MD_ERROR_WIN_CLUSTER_INVALID_IPV6_TUNNEL_NETWORK = 5927,
+ MD_ERROR_WIN_QUORUM_NOT_ALLOWED_IN_THIS_GROUP = 5928,
+ MD_ERROR_WIN_DEPENDENCY_TREE_TOO_COMPLEX = 5929,
+ MD_ERROR_WIN_EXCEPTION_IN_RESOURCE_CALL = 5930,
+ MD_ERROR_WIN_CLUSTER_RHS_FAILED_INITIALIZATION = 5931,
+ MD_ERROR_WIN_CLUSTER_NOT_INSTALLED = 5932,
+ MD_ERROR_WIN_CLUSTER_RESOURCES_MUST_BE_ONLINE_ON_THE_SAME_NODE = 5933,
+ MD_ERROR_WIN_CLUSTER_MAX_NODES_IN_CLUSTER = 5934,
+ MD_ERROR_WIN_CLUSTER_TOO_MANY_NODES = 5935,
+ MD_ERROR_WIN_CLUSTER_OBJECT_ALREADY_USED = 5936,
+ MD_ERROR_WIN_NONCORE_GROUPS_FOUND = 5937,
+ MD_ERROR_WIN_FILE_SHARE_RESOURCE_CONFLICT = 5938,
+ MD_ERROR_WIN_CLUSTER_EVICT_INVALID_REQUEST = 5939,
+ MD_ERROR_WIN_CLUSTER_SINGLETON_RESOURCE = 5940,
+ MD_ERROR_WIN_CLUSTER_GROUP_SINGLETON_RESOURCE = 5941,
+ MD_ERROR_WIN_CLUSTER_RESOURCE_PROVIDER_FAILED = 5942,
+ MD_ERROR_WIN_CLUSTER_RESOURCE_CONFIGURATION_ERROR = 5943,
+ MD_ERROR_WIN_CLUSTER_GROUP_BUSY = 5944,
+ MD_ERROR_WIN_CLUSTER_NOT_SHARED_VOLUME = 5945,
+ MD_ERROR_WIN_CLUSTER_INVALID_SECURITY_DESCRIPTOR = 5946,
+ MD_ERROR_WIN_CLUSTER_SHARED_VOLUMES_IN_USE = 5947,
+ MD_ERROR_WIN_CLUSTER_USE_SHARED_VOLUMES_API = 5948,
+ MD_ERROR_WIN_CLUSTER_BACKUP_IN_PROGRESS = 5949,
+ MD_ERROR_WIN_NON_CSV_PATH = 5950,
+ MD_ERROR_WIN_CSV_VOLUME_NOT_LOCAL = 5951,
+ MD_ERROR_WIN_CLUSTER_WATCHDOG_TERMINATING = 5952,
+ MD_ERROR_WIN_CLUSTER_RESOURCE_VETOED_MOVE_INCOMPATIBLE_NODES = 5953,
+ MD_ERROR_WIN_CLUSTER_INVALID_NODE_WEIGHT = 5954,
+ MD_ERROR_WIN_CLUSTER_RESOURCE_VETOED_CALL = 5955,
+ MD_ERROR_WIN_RESMON_SYSTEM_RESOURCES_LACKING = 5956,
+ MD_ERROR_WIN_CLUSTER_RESOURCE_VETOED_MOVE_NOT_ENOUGH_RESOURCES_ON_DESTINATION = 5957,
+ MD_ERROR_WIN_CLUSTER_RESOURCE_VETOED_MOVE_NOT_ENOUGH_RESOURCES_ON_SOURCE = 5958,
+ MD_ERROR_WIN_CLUSTER_GROUP_QUEUED = 5959,
+ MD_ERROR_WIN_CLUSTER_RESOURCE_LOCKED_STATUS = 5960,
+ MD_ERROR_WIN_CLUSTER_SHARED_VOLUME_FAILOVER_NOT_ALLOWED = 5961,
+ MD_ERROR_WIN_CLUSTER_NODE_DRAIN_IN_PROGRESS = 5962,
+ MD_ERROR_WIN_CLUSTER_DISK_NOT_CONNECTED = 5963,
+ MD_ERROR_WIN_DISK_NOT_CSV_CAPABLE = 5964,
+ MD_ERROR_WIN_RESOURCE_NOT_IN_AVAILABLE_STORAGE = 5965,
+ MD_ERROR_WIN_CLUSTER_SHARED_VOLUME_REDIRECTED = 5966,
+ MD_ERROR_WIN_CLUSTER_SHARED_VOLUME_NOT_REDIRECTED = 5967,
+ MD_ERROR_WIN_CLUSTER_CANNOT_RETURN_PROPERTIES = 5968,
+ MD_ERROR_WIN_CLUSTER_RESOURCE_CONTAINS_UNSUPPORTED_DIFF_AREA_FOR_SHARED_VOLUMES = 5969,
+ MD_ERROR_WIN_CLUSTER_RESOURCE_IS_IN_MAINTENANCE_MODE = 5970,
+ MD_ERROR_WIN_CLUSTER_AFFINITY_CONFLICT = 5971,
+ MD_ERROR_WIN_CLUSTER_RESOURCE_IS_REPLICA_VIRTUAL_MACHINE = 5972,
+ MD_ERROR_WIN_CLUSTER_UPGRADE_INCOMPATIBLE_VERSIONS = 5973,
+ MD_ERROR_WIN_CLUSTER_UPGRADE_FIX_QUORUM_NOT_SUPPORTED = 5974,
+ MD_ERROR_WIN_CLUSTER_UPGRADE_RESTART_REQUIRED = 5975,
+ MD_ERROR_WIN_CLUSTER_UPGRADE_IN_PROGRESS = 5976,
+ MD_ERROR_WIN_CLUSTER_UPGRADE_INCOMPLETE = 5977,
+ MD_ERROR_WIN_CLUSTER_NODE_IN_GRACE_PERIOD = 5978,
+ MD_ERROR_WIN_CLUSTER_CSV_IO_PAUSE_TIMEOUT = 5979,
+ MD_ERROR_WIN_NODE_NOT_ACTIVE_CLUSTER_MEMBER = 5980,
+ MD_ERROR_WIN_CLUSTER_RESOURCE_NOT_MONITORED = 5981,
+ MD_ERROR_WIN_CLUSTER_RESOURCE_DOES_NOT_SUPPORT_UNMONITORED = 5982,
+ MD_ERROR_WIN_CLUSTER_RESOURCE_IS_REPLICATED = 5983,
+ MD_ERROR_WIN_CLUSTER_NODE_ISOLATED = 5984,
+ MD_ERROR_WIN_CLUSTER_NODE_QUARANTINED = 5985,
+ MD_ERROR_WIN_CLUSTER_DATABASE_UPDATE_CONDITION_FAILED = 5986,
+ MD_ERROR_WIN_CLUSTER_SPACE_DEGRADED = 5987,
+ MD_ERROR_WIN_CLUSTER_TOKEN_DELEGATION_NOT_SUPPORTED = 5988,
+ MD_ERROR_WIN_CLUSTER_CSV_INVALID_HANDLE = 5989,
+ MD_ERROR_WIN_CLUSTER_CSV_SUPPORTED_ONLY_ON_COORDINATOR = 5990,
+ MD_ERROR_WIN_GROUPSET_NOT_AVAILABLE = 5991,
+ MD_ERROR_WIN_GROUPSET_NOT_FOUND = 5992,
+ MD_ERROR_WIN_GROUPSET_CANT_PROVIDE = 5993,
+ MD_ERROR_WIN_CLUSTER_FAULT_DOMAIN_PARENT_NOT_FOUND = 5994,
+ MD_ERROR_WIN_CLUSTER_FAULT_DOMAIN_INVALID_HIERARCHY = 5995,
+ MD_ERROR_WIN_CLUSTER_FAULT_DOMAIN_FAILED_S2D_VALIDATION = 5996,
+ MD_ERROR_WIN_CLUSTER_FAULT_DOMAIN_S2D_CONNECTIVITY_LOSS = 5997,
+ MD_ERROR_WIN_CLUSTER_INVALID_INFRASTRUCTURE_FILESERVER_NAME = 5998,
+ MD_ERROR_WIN_CLUSTERSET_MANAGEMENT_CLUSTER_UNREACHABLE = 5999,
+ MD_ERROR_WIN_ENCRYPTION_FAILED = 6000,
+ MD_ERROR_WIN_DECRYPTION_FAILED = 6001,
+ MD_ERROR_WIN_FILE_ENCRYPTED = 6002,
+ MD_ERROR_WIN_NO_RECOVERY_POLICY = 6003,
+ MD_ERROR_WIN_NO_EFS = 6004,
+ MD_ERROR_WIN_WRONG_EFS = 6005,
+ MD_ERROR_WIN_NO_USER_KEYS = 6006,
+ MD_ERROR_WIN_FILE_NOT_ENCRYPTED = 6007,
+ MD_ERROR_WIN_NOT_EXPORT_FORMAT = 6008,
+ MD_ERROR_WIN_FILE_READ_ONLY = 6009,
+ MD_ERROR_WIN_DIR_EFS_DISALLOWED = 6010,
+ MD_ERROR_WIN_EFS_SERVER_NOT_TRUSTED = 6011,
+ MD_ERROR_WIN_BAD_RECOVERY_POLICY = 6012,
+ MD_ERROR_WIN_EFS_ALG_BLOB_TOO_BIG = 6013,
+ MD_ERROR_WIN_VOLUME_NOT_SUPPORT_EFS = 6014,
+ MD_ERROR_WIN_EFS_DISABLED = 6015,
+ MD_ERROR_WIN_EFS_VERSION_NOT_SUPPORT = 6016,
+ MD_ERROR_WIN_CS_ENCRYPTION_INVALID_SERVER_RESPONSE = 6017,
+ MD_ERROR_WIN_CS_ENCRYPTION_UNSUPPORTED_SERVER = 6018,
+ MD_ERROR_WIN_CS_ENCRYPTION_EXISTING_ENCRYPTED_FILE = 6019,
+ MD_ERROR_WIN_CS_ENCRYPTION_NEW_ENCRYPTED_FILE = 6020,
+ MD_ERROR_WIN_CS_ENCRYPTION_FILE_NOT_CSE = 6021,
+ MD_ERROR_WIN_ENCRYPTION_POLICY_DENIES_OPERATION = 6022,
+ MD_ERROR_WIN_WIP_ENCRYPTION_FAILED = 6023,
+ MD_ERROR_WIN_NO_BROWSER_SERVERS_FOUND = 6118,
+ MD_ERROR_WIN_CLUSTER_OBJECT_IS_CLUSTER_SET_VM = 6250,
+ MD_ERROR_WIN_LOG_SECTOR_INVALID = 6600,
+ MD_ERROR_WIN_LOG_SECTOR_PARITY_INVALID = 6601,
+ MD_ERROR_WIN_LOG_SECTOR_REMAPPED = 6602,
+ MD_ERROR_WIN_LOG_BLOCK_INCOMPLETE = 6603,
+ MD_ERROR_WIN_LOG_INVALID_RANGE = 6604,
+ MD_ERROR_WIN_LOG_BLOCKS_EXHAUSTED = 6605,
+ MD_ERROR_WIN_LOG_READ_CONTEXT_INVALID = 6606,
+ MD_ERROR_WIN_LOG_RESTART_INVALID = 6607,
+ MD_ERROR_WIN_LOG_BLOCK_VERSION = 6608,
+ MD_ERROR_WIN_LOG_BLOCK_INVALID = 6609,
+ MD_ERROR_WIN_LOG_READ_MODE_INVALID = 6610,
+ MD_ERROR_WIN_LOG_NO_RESTART = 6611,
+ MD_ERROR_WIN_LOG_METADATA_CORRUPT = 6612,
+ MD_ERROR_WIN_LOG_METADATA_INVALID = 6613,
+ MD_ERROR_WIN_LOG_METADATA_INCONSISTENT = 6614,
+ MD_ERROR_WIN_LOG_RESERVATION_INVALID = 6615,
+ MD_ERROR_WIN_LOG_CANT_DELETE = 6616,
+ MD_ERROR_WIN_LOG_CONTAINER_LIMIT_EXCEEDED = 6617,
+ MD_ERROR_WIN_LOG_START_OF_LOG = 6618,
+ MD_ERROR_WIN_LOG_POLICY_ALREADY_INSTALLED = 6619,
+ MD_ERROR_WIN_LOG_POLICY_NOT_INSTALLED = 6620,
+ MD_ERROR_WIN_LOG_POLICY_INVALID = 6621,
+ MD_ERROR_WIN_LOG_POLICY_CONFLICT = 6622,
+ MD_ERROR_WIN_LOG_PINNED_ARCHIVE_TAIL = 6623,
+ MD_ERROR_WIN_LOG_RECORD_NONEXISTENT = 6624,
+ MD_ERROR_WIN_LOG_RECORDS_RESERVED_INVALID = 6625,
+ MD_ERROR_WIN_LOG_SPACE_RESERVED_INVALID = 6626,
+ MD_ERROR_WIN_LOG_TAIL_INVALID = 6627,
+ MD_ERROR_WIN_LOG_FULL = 6628,
+ MD_ERROR_WIN_COULD_NOT_RESIZE_LOG = 6629,
+ MD_ERROR_WIN_LOG_MULTIPLEXED = 6630,
+ MD_ERROR_WIN_LOG_DEDICATED = 6631,
+ MD_ERROR_WIN_LOG_ARCHIVE_NOT_IN_PROGRESS = 6632,
+ MD_ERROR_WIN_LOG_ARCHIVE_IN_PROGRESS = 6633,
+ MD_ERROR_WIN_LOG_EPHEMERAL = 6634,
+ MD_ERROR_WIN_LOG_NOT_ENOUGH_CONTAINERS = 6635,
+ MD_ERROR_WIN_LOG_CLIENT_ALREADY_REGISTERED = 6636,
+ MD_ERROR_WIN_LOG_CLIENT_NOT_REGISTERED = 6637,
+ MD_ERROR_WIN_LOG_FULL_HANDLER_IN_PROGRESS = 6638,
+ MD_ERROR_WIN_LOG_CONTAINER_READ_FAILED = 6639,
+ MD_ERROR_WIN_LOG_CONTAINER_WRITE_FAILED = 6640,
+ MD_ERROR_WIN_LOG_CONTAINER_OPEN_FAILED = 6641,
+ MD_ERROR_WIN_LOG_CONTAINER_STATE_INVALID = 6642,
+ MD_ERROR_WIN_LOG_STATE_INVALID = 6643,
+ MD_ERROR_WIN_LOG_PINNED = 6644,
+ MD_ERROR_WIN_LOG_METADATA_FLUSH_FAILED = 6645,
+ MD_ERROR_WIN_LOG_INCONSISTENT_SECURITY = 6646,
+ MD_ERROR_WIN_LOG_APPENDED_FLUSH_FAILED = 6647,
+ MD_ERROR_WIN_LOG_PINNED_RESERVATION = 6648,
+ MD_ERROR_WIN_INVALID_TRANSACTION = 6700,
+ MD_ERROR_WIN_TRANSACTION_NOT_ACTIVE = 6701,
+ MD_ERROR_WIN_TRANSACTION_REQUEST_NOT_VALID = 6702,
+ MD_ERROR_WIN_TRANSACTION_NOT_REQUESTED = 6703,
+ MD_ERROR_WIN_TRANSACTION_ALREADY_ABORTED = 6704,
+ MD_ERROR_WIN_TRANSACTION_ALREADY_COMMITTED = 6705,
+ MD_ERROR_WIN_TM_INITIALIZATION_FAILED = 6706,
+ MD_ERROR_WIN_RESOURCEMANAGER_READ_ONLY = 6707,
+ MD_ERROR_WIN_TRANSACTION_NOT_JOINED = 6708,
+ MD_ERROR_WIN_TRANSACTION_SUPERIOR_EXISTS = 6709,
+ MD_ERROR_WIN_CRM_PROTOCOL_ALREADY_EXISTS = 6710,
+ MD_ERROR_WIN_TRANSACTION_PROPAGATION_FAILED = 6711,
+ MD_ERROR_WIN_CRM_PROTOCOL_NOT_FOUND = 6712,
+ MD_ERROR_WIN_TRANSACTION_INVALID_MARSHALL_BUFFER = 6713,
+ MD_ERROR_WIN_CURRENT_TRANSACTION_NOT_VALID = 6714,
+ MD_ERROR_WIN_TRANSACTION_NOT_FOUND = 6715,
+ MD_ERROR_WIN_RESOURCEMANAGER_NOT_FOUND = 6716,
+ MD_ERROR_WIN_ENLISTMENT_NOT_FOUND = 6717,
+ MD_ERROR_WIN_TRANSACTIONMANAGER_NOT_FOUND = 6718,
+ MD_ERROR_WIN_TRANSACTIONMANAGER_NOT_ONLINE = 6719,
+ MD_ERROR_WIN_TRANSACTIONMANAGER_RECOVERY_NAME_COLLISION = 6720,
+ MD_ERROR_WIN_TRANSACTION_NOT_ROOT = 6721,
+ MD_ERROR_WIN_TRANSACTION_OBJECT_EXPIRED = 6722,
+ MD_ERROR_WIN_TRANSACTION_RESPONSE_NOT_ENLISTED = 6723,
+ MD_ERROR_WIN_TRANSACTION_RECORD_TOO_LONG = 6724,
+ MD_ERROR_WIN_IMPLICIT_TRANSACTION_NOT_SUPPORTED = 6725,
+ MD_ERROR_WIN_TRANSACTION_INTEGRITY_VIOLATED = 6726,
+ MD_ERROR_WIN_TRANSACTIONMANAGER_IDENTITY_MISMATCH = 6727,
+ MD_ERROR_WIN_RM_CANNOT_BE_FROZEN_FOR_SNAPSHOT = 6728,
+ MD_ERROR_WIN_TRANSACTION_MUST_WRITETHROUGH = 6729,
+ MD_ERROR_WIN_TRANSACTION_NO_SUPERIOR = 6730,
+ MD_ERROR_WIN_HEURISTIC_DAMAGE_POSSIBLE = 6731,
+ MD_ERROR_WIN_TRANSACTIONAL_CONFLICT = 6800,
+ MD_ERROR_WIN_RM_NOT_ACTIVE = 6801,
+ MD_ERROR_WIN_RM_METADATA_CORRUPT = 6802,
+ MD_ERROR_WIN_DIRECTORY_NOT_RM = 6803,
+ MD_ERROR_WIN_TRANSACTIONS_UNSUPPORTED_REMOTE = 6805,
+ MD_ERROR_WIN_LOG_RESIZE_INVALID_SIZE = 6806,
+ MD_ERROR_WIN_OBJECT_NO_LONGER_EXISTS = 6807,
+ MD_ERROR_WIN_STREAM_MINIVERSION_NOT_FOUND = 6808,
+ MD_ERROR_WIN_STREAM_MINIVERSION_NOT_VALID = 6809,
+ MD_ERROR_WIN_MINIVERSION_INACCESSIBLE_FROM_SPECIFIED_TRANSACTION = 6810,
+ MD_ERROR_WIN_CANT_OPEN_MINIVERSION_WITH_MODIFY_INTENT = 6811,
+ MD_ERROR_WIN_CANT_CREATE_MORE_STREAM_MINIVERSIONS = 6812,
+ MD_ERROR_WIN_REMOTE_FILE_VERSION_MISMATCH = 6814,
+ MD_ERROR_WIN_HANDLE_NO_LONGER_VALID = 6815,
+ MD_ERROR_WIN_NO_TXF_METADATA = 6816,
+ MD_ERROR_WIN_LOG_CORRUPTION_DETECTED = 6817,
+ MD_ERROR_WIN_CANT_RECOVER_WITH_HANDLE_OPEN = 6818,
+ MD_ERROR_WIN_RM_DISCONNECTED = 6819,
+ MD_ERROR_WIN_ENLISTMENT_NOT_SUPERIOR = 6820,
+ MD_ERROR_WIN_RECOVERY_NOT_NEEDED = 6821,
+ MD_ERROR_WIN_RM_ALREADY_STARTED = 6822,
+ MD_ERROR_WIN_FILE_IDENTITY_NOT_PERSISTENT = 6823,
+ MD_ERROR_WIN_CANT_BREAK_TRANSACTIONAL_DEPENDENCY = 6824,
+ MD_ERROR_WIN_CANT_CROSS_RM_BOUNDARY = 6825,
+ MD_ERROR_WIN_TXF_DIR_NOT_EMPTY = 6826,
+ MD_ERROR_WIN_INDOUBT_TRANSACTIONS_EXIST = 6827,
+ MD_ERROR_WIN_TM_VOLATILE = 6828,
+ MD_ERROR_WIN_ROLLBACK_TIMER_EXPIRED = 6829,
+ MD_ERROR_WIN_TXF_ATTRIBUTE_CORRUPT = 6830,
+ MD_ERROR_WIN_EFS_NOT_ALLOWED_IN_TRANSACTION = 6831,
+ MD_ERROR_WIN_TRANSACTIONAL_OPEN_NOT_ALLOWED = 6832,
+ MD_ERROR_WIN_LOG_GROWTH_FAILED = 6833,
+ MD_ERROR_WIN_TRANSACTED_MAPPING_UNSUPPORTED_REMOTE = 6834,
+ MD_ERROR_WIN_TXF_METADATA_ALREADY_PRESENT = 6835,
+ MD_ERROR_WIN_TRANSACTION_SCOPE_CALLBACKS_NOT_SET = 6836,
+ MD_ERROR_WIN_TRANSACTION_REQUIRED_PROMOTION = 6837,
+ MD_ERROR_WIN_CANNOT_EXECUTE_FILE_IN_TRANSACTION = 6838,
+ MD_ERROR_WIN_TRANSACTIONS_NOT_FROZEN = 6839,
+ MD_ERROR_WIN_TRANSACTION_FREEZE_IN_PROGRESS = 6840,
+ MD_ERROR_WIN_NOT_SNAPSHOT_VOLUME = 6841,
+ MD_ERROR_WIN_NO_SAVEPOINT_WITH_OPEN_FILES = 6842,
+ MD_ERROR_WIN_DATA_LOST_REPAIR = 6843,
+ MD_ERROR_WIN_SPARSE_NOT_ALLOWED_IN_TRANSACTION = 6844,
+ MD_ERROR_WIN_TM_IDENTITY_MISMATCH = 6845,
+ MD_ERROR_WIN_FLOATED_SECTION = 6846,
+ MD_ERROR_WIN_CANNOT_ACCEPT_TRANSACTED_WORK = 6847,
+ MD_ERROR_WIN_CANNOT_ABORT_TRANSACTIONS = 6848,
+ MD_ERROR_WIN_BAD_CLUSTERS = 6849,
+ MD_ERROR_WIN_COMPRESSION_NOT_ALLOWED_IN_TRANSACTION = 6850,
+ MD_ERROR_WIN_VOLUME_DIRTY = 6851,
+ MD_ERROR_WIN_NO_LINK_TRACKING_IN_TRANSACTION = 6852,
+ MD_ERROR_WIN_OPERATION_NOT_SUPPORTED_IN_TRANSACTION = 6853,
+ MD_ERROR_WIN_EXPIRED_HANDLE = 6854,
+ MD_ERROR_WIN_TRANSACTION_NOT_ENLISTED = 6855,
+ MD_ERROR_WIN_CTX_WINSTATION_NAME_INVALID = 7001,
+ MD_ERROR_WIN_CTX_INVALID_PD = 7002,
+ MD_ERROR_WIN_CTX_PD_NOT_FOUND = 7003,
+ MD_ERROR_WIN_CTX_WD_NOT_FOUND = 7004,
+ MD_ERROR_WIN_CTX_CANNOT_MAKE_EVENTLOG_ENTRY = 7005,
+ MD_ERROR_WIN_CTX_SERVICE_NAME_COLLISION = 7006,
+ MD_ERROR_WIN_CTX_CLOSE_PENDING = 7007,
+ MD_ERROR_WIN_CTX_NO_OUTBUF = 7008,
+ MD_ERROR_WIN_CTX_MODEM_INF_NOT_FOUND = 7009,
+ MD_ERROR_WIN_CTX_INVALID_MODEMNAME = 7010,
+ MD_ERROR_WIN_CTX_MODEM_RESPONSE_ERROR = 7011,
+ MD_ERROR_WIN_CTX_MODEM_RESPONSE_TIMEOUT = 7012,
+ MD_ERROR_WIN_CTX_MODEM_RESPONSE_NO_CARRIER = 7013,
+ MD_ERROR_WIN_CTX_MODEM_RESPONSE_NO_DIALTONE = 7014,
+ MD_ERROR_WIN_CTX_MODEM_RESPONSE_BUSY = 7015,
+ MD_ERROR_WIN_CTX_MODEM_RESPONSE_VOICE = 7016,
+ MD_ERROR_WIN_CTX_TD_ERROR = 7017,
+ MD_ERROR_WIN_CTX_WINSTATION_NOT_FOUND = 7022,
+ MD_ERROR_WIN_CTX_WINSTATION_ALREADY_EXISTS = 7023,
+ MD_ERROR_WIN_CTX_WINSTATION_BUSY = 7024,
+ MD_ERROR_WIN_CTX_BAD_VIDEO_MODE = 7025,
+ MD_ERROR_WIN_CTX_GRAPHICS_INVALID = 7035,
+ MD_ERROR_WIN_CTX_LOGON_DISABLED = 7037,
+ MD_ERROR_WIN_CTX_NOT_CONSOLE = 7038,
+ MD_ERROR_WIN_CTX_CLIENT_QUERY_TIMEOUT = 7040,
+ MD_ERROR_WIN_CTX_CONSOLE_DISCONNECT = 7041,
+ MD_ERROR_WIN_CTX_CONSOLE_CONNECT = 7042,
+ MD_ERROR_WIN_CTX_SHADOW_DENIED = 7044,
+ MD_ERROR_WIN_CTX_WINSTATION_ACCESS_DENIED = 7045,
+ MD_ERROR_WIN_CTX_INVALID_WD = 7049,
+ MD_ERROR_WIN_CTX_SHADOW_INVALID = 7050,
+ MD_ERROR_WIN_CTX_SHADOW_DISABLED = 7051,
+ MD_ERROR_WIN_CTX_CLIENT_LICENSE_IN_USE = 7052,
+ MD_ERROR_WIN_CTX_CLIENT_LICENSE_NOT_SET = 7053,
+ MD_ERROR_WIN_CTX_LICENSE_NOT_AVAILABLE = 7054,
+ MD_ERROR_WIN_CTX_LICENSE_CLIENT_INVALID = 7055,
+ MD_ERROR_WIN_CTX_LICENSE_EXPIRED = 7056,
+ MD_ERROR_WIN_CTX_SHADOW_NOT_RUNNING = 7057,
+ MD_ERROR_WIN_CTX_SHADOW_ENDED_BY_MODE_CHANGE = 7058,
+ MD_ERROR_WIN_ACTIVATION_COUNT_EXCEEDED = 7059,
+ MD_ERROR_WIN_CTX_WINSTATIONS_DISABLED = 7060,
+ MD_ERROR_WIN_CTX_ENCRYPTION_LEVEL_REQUIRED = 7061,
+ MD_ERROR_WIN_CTX_SESSION_IN_USE = 7062,
+ MD_ERROR_WIN_CTX_NO_FORCE_LOGOFF = 7063,
+ MD_ERROR_WIN_CTX_ACCOUNT_RESTRICTION = 7064,
+ MD_ERROR_WIN_RDP_PROTOCOL_ERROR = 7065,
+ MD_ERROR_WIN_CTX_CDM_CONNECT = 7066,
+ MD_ERROR_WIN_CTX_CDM_DISCONNECT = 7067,
+ MD_ERROR_WIN_CTX_SECURITY_LAYER_ERROR = 7068,
+ MD_ERROR_WIN_TS_INCOMPATIBLE_SESSIONS = 7069,
+ MD_ERROR_WIN_TS_VIDEO_SUBSYSTEM_ERROR = 7070,
+ MD_ERROR_WIN_DS_NOT_INSTALLED = 8200,
+ MD_ERROR_WIN_DS_MEMBERSHIP_EVALUATED_LOCALLY = 8201,
+ MD_ERROR_WIN_DS_NO_ATTRIBUTE_OR_VALUE = 8202,
+ MD_ERROR_WIN_DS_INVALID_ATTRIBUTE_SYNTAX = 8203,
+ MD_ERROR_WIN_DS_ATTRIBUTE_TYPE_UNDEFINED = 8204,
+ MD_ERROR_WIN_DS_ATTRIBUTE_OR_VALUE_EXISTS = 8205,
+ MD_ERROR_WIN_DS_BUSY = 8206,
+ MD_ERROR_WIN_DS_UNAVAILABLE = 8207,
+ MD_ERROR_WIN_DS_NO_RIDS_ALLOCATED = 8208,
+ MD_ERROR_WIN_DS_NO_MORE_RIDS = 8209,
+ MD_ERROR_WIN_DS_INCORRECT_ROLE_OWNER = 8210,
+ MD_ERROR_WIN_DS_RIDMGR_INIT_ERROR = 8211,
+ MD_ERROR_WIN_DS_OBJ_CLASS_VIOLATION = 8212,
+ MD_ERROR_WIN_DS_CANT_ON_NON_LEAF = 8213,
+ MD_ERROR_WIN_DS_CANT_ON_RDN = 8214,
+ MD_ERROR_WIN_DS_CANT_MOD_OBJ_CLASS = 8215,
+ MD_ERROR_WIN_DS_CROSS_DOM_MOVE_ERROR = 8216,
+ MD_ERROR_WIN_DS_GC_NOT_AVAILABLE = 8217,
+ MD_ERROR_WIN_SHARED_POLICY = 8218,
+ MD_ERROR_WIN_POLICY_OBJECT_NOT_FOUND = 8219,
+ MD_ERROR_WIN_POLICY_ONLY_IN_DS = 8220,
+ MD_ERROR_WIN_PROMOTION_ACTIVE = 8221,
+ MD_ERROR_WIN_NO_PROMOTION_ACTIVE = 8222,
+ MD_ERROR_WIN_DS_OPERATIONS_ERROR = 8224,
+ MD_ERROR_WIN_DS_PROTOCOL_ERROR = 8225,
+ MD_ERROR_WIN_DS_TIMELIMIT_EXCEEDED = 8226,
+ MD_ERROR_WIN_DS_SIZELIMIT_EXCEEDED = 8227,
+ MD_ERROR_WIN_DS_ADMIN_LIMIT_EXCEEDED = 8228,
+ MD_ERROR_WIN_DS_COMPARE_FALSE = 8229,
+ MD_ERROR_WIN_DS_COMPARE_TRUE = 8230,
+ MD_ERROR_WIN_DS_AUTH_METHOD_NOT_SUPPORTED = 8231,
+ MD_ERROR_WIN_DS_STRONG_AUTH_REQUIRED = 8232,
+ MD_ERROR_WIN_DS_INAPPROPRIATE_AUTH = 8233,
+ MD_ERROR_WIN_DS_AUTH_UNKNOWN = 8234,
+ MD_ERROR_WIN_DS_REFERRAL = 8235,
+ MD_ERROR_WIN_DS_UNAVAILABLE_CRIT_EXTENSION = 8236,
+ MD_ERROR_WIN_DS_CONFIDENTIALITY_REQUIRED = 8237,
+ MD_ERROR_WIN_DS_INAPPROPRIATE_MATCHING = 8238,
+ MD_ERROR_WIN_DS_CONSTRAINT_VIOLATION = 8239,
+ MD_ERROR_WIN_DS_NO_SUCH_OBJECT = 8240,
+ MD_ERROR_WIN_DS_ALIAS_PROBLEM = 8241,
+ MD_ERROR_WIN_DS_INVALID_DN_SYNTAX = 8242,
+ MD_ERROR_WIN_DS_IS_LEAF = 8243,
+ MD_ERROR_WIN_DS_ALIAS_DEREF_PROBLEM = 8244,
+ MD_ERROR_WIN_DS_UNWILLING_TO_PERFORM = 8245,
+ MD_ERROR_WIN_DS_LOOP_DETECT = 8246,
+ MD_ERROR_WIN_DS_NAMING_VIOLATION = 8247,
+ MD_ERROR_WIN_DS_OBJECT_RESULTS_TOO_LARGE = 8248,
+ MD_ERROR_WIN_DS_AFFECTS_MULTIPLE_DSAS = 8249,
+ MD_ERROR_WIN_DS_SERVER_DOWN = 8250,
+ MD_ERROR_WIN_DS_LOCAL_ERROR = 8251,
+ MD_ERROR_WIN_DS_ENCODING_ERROR = 8252,
+ MD_ERROR_WIN_DS_DECODING_ERROR = 8253,
+ MD_ERROR_WIN_DS_FILTER_UNKNOWN = 8254,
+ MD_ERROR_WIN_DS_PARAM_ERROR = 8255,
+ MD_ERROR_WIN_DS_NOT_SUPPORTED = 8256,
+ MD_ERROR_WIN_DS_NO_RESULTS_RETURNED = 8257,
+ MD_ERROR_WIN_DS_CONTROL_NOT_FOUND = 8258,
+ MD_ERROR_WIN_DS_CLIENT_LOOP = 8259,
+ MD_ERROR_WIN_DS_REFERRAL_LIMIT_EXCEEDED = 8260,
+ MD_ERROR_WIN_DS_SORT_CONTROL_MISSING = 8261,
+ MD_ERROR_WIN_DS_OFFSET_RANGE_ERROR = 8262,
+ MD_ERROR_WIN_DS_RIDMGR_DISABLED = 8263,
+ MD_ERROR_WIN_DS_ROOT_MUST_BE_NC = 8301,
+ MD_ERROR_WIN_DS_ADD_REPLICA_INHIBITED = 8302,
+ MD_ERROR_WIN_DS_ATT_NOT_DEF_IN_SCHEMA = 8303,
+ MD_ERROR_WIN_DS_MAX_OBJ_SIZE_EXCEEDED = 8304,
+ MD_ERROR_WIN_DS_OBJ_STRING_NAME_EXISTS = 8305,
+ MD_ERROR_WIN_DS_NO_RDN_DEFINED_IN_SCHEMA = 8306,
+ MD_ERROR_WIN_DS_RDN_DOESNT_MATCH_SCHEMA = 8307,
+ MD_ERROR_WIN_DS_NO_REQUESTED_ATTS_FOUND = 8308,
+ MD_ERROR_WIN_DS_USER_BUFFER_TO_SMALL = 8309,
+ MD_ERROR_WIN_DS_ATT_IS_NOT_ON_OBJ = 8310,
+ MD_ERROR_WIN_DS_ILLEGAL_MOD_OPERATION = 8311,
+ MD_ERROR_WIN_DS_OBJ_TOO_LARGE = 8312,
+ MD_ERROR_WIN_DS_BAD_INSTANCE_TYPE = 8313,
+ MD_ERROR_WIN_DS_MASTERDSA_REQUIRED = 8314,
+ MD_ERROR_WIN_DS_OBJECT_CLASS_REQUIRED = 8315,
+ MD_ERROR_WIN_DS_MISSING_REQUIRED_ATT = 8316,
+ MD_ERROR_WIN_DS_ATT_NOT_DEF_FOR_CLASS = 8317,
+ MD_ERROR_WIN_DS_ATT_ALREADY_EXISTS = 8318,
+ MD_ERROR_WIN_DS_CANT_ADD_ATT_VALUES = 8320,
+ MD_ERROR_WIN_DS_SINGLE_VALUE_CONSTRAINT = 8321,
+ MD_ERROR_WIN_DS_RANGE_CONSTRAINT = 8322,
+ MD_ERROR_WIN_DS_ATT_VAL_ALREADY_EXISTS = 8323,
+ MD_ERROR_WIN_DS_CANT_REM_MISSING_ATT = 8324,
+ MD_ERROR_WIN_DS_CANT_REM_MISSING_ATT_VAL = 8325,
+ MD_ERROR_WIN_DS_ROOT_CANT_BE_SUBREF = 8326,
+ MD_ERROR_WIN_DS_NO_CHAINING = 8327,
+ MD_ERROR_WIN_DS_NO_CHAINED_EVAL = 8328,
+ MD_ERROR_WIN_DS_NO_PARENT_OBJECT = 8329,
+ MD_ERROR_WIN_DS_PARENT_IS_AN_ALIAS = 8330,
+ MD_ERROR_WIN_DS_CANT_MIX_MASTER_AND_REPS = 8331,
+ MD_ERROR_WIN_DS_CHILDREN_EXIST = 8332,
+ MD_ERROR_WIN_DS_OBJ_NOT_FOUND = 8333,
+ MD_ERROR_WIN_DS_ALIASED_OBJ_MISSING = 8334,
+ MD_ERROR_WIN_DS_BAD_NAME_SYNTAX = 8335,
+ MD_ERROR_WIN_DS_ALIAS_POINTS_TO_ALIAS = 8336,
+ MD_ERROR_WIN_DS_CANT_DEREF_ALIAS = 8337,
+ MD_ERROR_WIN_DS_OUT_OF_SCOPE = 8338,
+ MD_ERROR_WIN_DS_OBJECT_BEING_REMOVED = 8339,
+ MD_ERROR_WIN_DS_CANT_DELETE_DSA_OBJ = 8340,
+ MD_ERROR_WIN_DS_GENERIC_ERROR = 8341,
+ MD_ERROR_WIN_DS_DSA_MUST_BE_INT_MASTER = 8342,
+ MD_ERROR_WIN_DS_CLASS_NOT_DSA = 8343,
+ MD_ERROR_WIN_DS_INSUFF_ACCESS_RIGHTS = 8344,
+ MD_ERROR_WIN_DS_ILLEGAL_SUPERIOR = 8345,
+ MD_ERROR_WIN_DS_ATTRIBUTE_OWNED_BY_SAM = 8346,
+ MD_ERROR_WIN_DS_NAME_TOO_MANY_PARTS = 8347,
+ MD_ERROR_WIN_DS_NAME_TOO_LONG = 8348,
+ MD_ERROR_WIN_DS_NAME_VALUE_TOO_LONG = 8349,
+ MD_ERROR_WIN_DS_NAME_UNPARSEABLE = 8350,
+ MD_ERROR_WIN_DS_NAME_TYPE_UNKNOWN = 8351,
+ MD_ERROR_WIN_DS_NOT_AN_OBJECT = 8352,
+ MD_ERROR_WIN_DS_SEC_DESC_TOO_SHORT = 8353,
+ MD_ERROR_WIN_DS_SEC_DESC_INVALID = 8354,
+ MD_ERROR_WIN_DS_NO_DELETED_NAME = 8355,
+ MD_ERROR_WIN_DS_SUBREF_MUST_HAVE_PARENT = 8356,
+ MD_ERROR_WIN_DS_NCNAME_MUST_BE_NC = 8357,
+ MD_ERROR_WIN_DS_CANT_ADD_SYSTEM_ONLY = 8358,
+ MD_ERROR_WIN_DS_CLASS_MUST_BE_CONCRETE = 8359,
+ MD_ERROR_WIN_DS_INVALID_DMD = 8360,
+ MD_ERROR_WIN_DS_OBJ_GUID_EXISTS = 8361,
+ MD_ERROR_WIN_DS_NOT_ON_BACKLINK = 8362,
+ MD_ERROR_WIN_DS_NO_CROSSREF_FOR_NC = 8363,
+ MD_ERROR_WIN_DS_SHUTTING_DOWN = 8364,
+ MD_ERROR_WIN_DS_UNKNOWN_OPERATION = 8365,
+ MD_ERROR_WIN_DS_INVALID_ROLE_OWNER = 8366,
+ MD_ERROR_WIN_DS_COULDNT_CONTACT_FSMO = 8367,
+ MD_ERROR_WIN_DS_CROSS_NC_DN_RENAME = 8368,
+ MD_ERROR_WIN_DS_CANT_MOD_SYSTEM_ONLY = 8369,
+ MD_ERROR_WIN_DS_REPLICATOR_ONLY = 8370,
+ MD_ERROR_WIN_DS_OBJ_CLASS_NOT_DEFINED = 8371,
+ MD_ERROR_WIN_DS_OBJ_CLASS_NOT_SUBCLASS = 8372,
+ MD_ERROR_WIN_DS_NAME_REFERENCE_INVALID = 8373,
+ MD_ERROR_WIN_DS_CROSS_REF_EXISTS = 8374,
+ MD_ERROR_WIN_DS_CANT_DEL_MASTER_CROSSREF = 8375,
+ MD_ERROR_WIN_DS_SUBTREE_NOTIFY_NOT_NC_HEAD = 8376,
+ MD_ERROR_WIN_DS_NOTIFY_FILTER_TOO_COMPLEX = 8377,
+ MD_ERROR_WIN_DS_DUP_RDN = 8378,
+ MD_ERROR_WIN_DS_DUP_OID = 8379,
+ MD_ERROR_WIN_DS_DUP_MAPI_ID = 8380,
+ MD_ERROR_WIN_DS_DUP_SCHEMA_ID_GUID = 8381,
+ MD_ERROR_WIN_DS_DUP_LDAP_DISPLAY_NAME = 8382,
+ MD_ERROR_WIN_DS_SEMANTIC_ATT_TEST = 8383,
+ MD_ERROR_WIN_DS_SYNTAX_MISMATCH = 8384,
+ MD_ERROR_WIN_DS_EXISTS_IN_MUST_HAVE = 8385,
+ MD_ERROR_WIN_DS_EXISTS_IN_MAY_HAVE = 8386,
+ MD_ERROR_WIN_DS_NONEXISTENT_MAY_HAVE = 8387,
+ MD_ERROR_WIN_DS_NONEXISTENT_MUST_HAVE = 8388,
+ MD_ERROR_WIN_DS_AUX_CLS_TEST_FAIL = 8389,
+ MD_ERROR_WIN_DS_NONEXISTENT_POSS_SUP = 8390,
+ MD_ERROR_WIN_DS_SUB_CLS_TEST_FAIL = 8391,
+ MD_ERROR_WIN_DS_BAD_RDN_ATT_ID_SYNTAX = 8392,
+ MD_ERROR_WIN_DS_EXISTS_IN_AUX_CLS = 8393,
+ MD_ERROR_WIN_DS_EXISTS_IN_SUB_CLS = 8394,
+ MD_ERROR_WIN_DS_EXISTS_IN_POSS_SUP = 8395,
+ MD_ERROR_WIN_DS_RECALCSCHEMA_FAILED = 8396,
+ MD_ERROR_WIN_DS_TREE_DELETE_NOT_FINISHED = 8397,
+ MD_ERROR_WIN_DS_CANT_DELETE = 8398,
+ MD_ERROR_WIN_DS_ATT_SCHEMA_REQ_ID = 8399,
+ MD_ERROR_WIN_DS_BAD_ATT_SCHEMA_SYNTAX = 8400,
+ MD_ERROR_WIN_DS_CANT_CACHE_ATT = 8401,
+ MD_ERROR_WIN_DS_CANT_CACHE_CLASS = 8402,
+ MD_ERROR_WIN_DS_CANT_REMOVE_ATT_CACHE = 8403,
+ MD_ERROR_WIN_DS_CANT_REMOVE_CLASS_CACHE = 8404,
+ MD_ERROR_WIN_DS_CANT_RETRIEVE_DN = 8405,
+ MD_ERROR_WIN_DS_MISSING_SUPREF = 8406,
+ MD_ERROR_WIN_DS_CANT_RETRIEVE_INSTANCE = 8407,
+ MD_ERROR_WIN_DS_CODE_INCONSISTENCY = 8408,
+ MD_ERROR_WIN_DS_DATABASE_ERROR = 8409,
+ MD_ERROR_WIN_DS_GOVERNSID_MISSING = 8410,
+ MD_ERROR_WIN_DS_MISSING_EXPECTED_ATT = 8411,
+ MD_ERROR_WIN_DS_NCNAME_MISSING_CR_REF = 8412,
+ MD_ERROR_WIN_DS_SECURITY_CHECKING_ERROR = 8413,
+ MD_ERROR_WIN_DS_SCHEMA_NOT_LOADED = 8414,
+ MD_ERROR_WIN_DS_SCHEMA_ALLOC_FAILED = 8415,
+ MD_ERROR_WIN_DS_ATT_SCHEMA_REQ_SYNTAX = 8416,
+ MD_ERROR_WIN_DS_GCVERIFY_ERROR = 8417,
+ MD_ERROR_WIN_DS_DRA_SCHEMA_MISMATCH = 8418,
+ MD_ERROR_WIN_DS_CANT_FIND_DSA_OBJ = 8419,
+ MD_ERROR_WIN_DS_CANT_FIND_EXPECTED_NC = 8420,
+ MD_ERROR_WIN_DS_CANT_FIND_NC_IN_CACHE = 8421,
+ MD_ERROR_WIN_DS_CANT_RETRIEVE_CHILD = 8422,
+ MD_ERROR_WIN_DS_SECURITY_ILLEGAL_MODIFY = 8423,
+ MD_ERROR_WIN_DS_CANT_REPLACE_HIDDEN_REC = 8424,
+ MD_ERROR_WIN_DS_BAD_HIERARCHY_FILE = 8425,
+ MD_ERROR_WIN_DS_BUILD_HIERARCHY_TABLE_FAILED = 8426,
+ MD_ERROR_WIN_DS_CONFIG_PARAM_MISSING = 8427,
+ MD_ERROR_WIN_DS_COUNTING_AB_INDICES_FAILED = 8428,
+ MD_ERROR_WIN_DS_HIERARCHY_TABLE_MALLOC_FAILED = 8429,
+ MD_ERROR_WIN_DS_INTERNAL_FAILURE = 8430,
+ MD_ERROR_WIN_DS_UNKNOWN_ERROR = 8431,
+ MD_ERROR_WIN_DS_ROOT_REQUIRES_CLASS_TOP = 8432,
+ MD_ERROR_WIN_DS_REFUSING_FSMO_ROLES = 8433,
+ MD_ERROR_WIN_DS_MISSING_FSMO_SETTINGS = 8434,
+ MD_ERROR_WIN_DS_UNABLE_TO_SURRENDER_ROLES = 8435,
+ MD_ERROR_WIN_DS_DRA_GENERIC = 8436,
+ MD_ERROR_WIN_DS_DRA_INVALID_PARAMETER = 8437,
+ MD_ERROR_WIN_DS_DRA_BUSY = 8438,
+ MD_ERROR_WIN_DS_DRA_BAD_DN = 8439,
+ MD_ERROR_WIN_DS_DRA_BAD_NC = 8440,
+ MD_ERROR_WIN_DS_DRA_DN_EXISTS = 8441,
+ MD_ERROR_WIN_DS_DRA_INTERNAL_ERROR = 8442,
+ MD_ERROR_WIN_DS_DRA_INCONSISTENT_DIT = 8443,
+ MD_ERROR_WIN_DS_DRA_CONNECTION_FAILED = 8444,
+ MD_ERROR_WIN_DS_DRA_BAD_INSTANCE_TYPE = 8445,
+ MD_ERROR_WIN_DS_DRA_OUT_OF_MEM = 8446,
+ MD_ERROR_WIN_DS_DRA_MAIL_PROBLEM = 8447,
+ MD_ERROR_WIN_DS_DRA_REF_ALREADY_EXISTS = 8448,
+ MD_ERROR_WIN_DS_DRA_REF_NOT_FOUND = 8449,
+ MD_ERROR_WIN_DS_DRA_OBJ_IS_REP_SOURCE = 8450,
+ MD_ERROR_WIN_DS_DRA_DB_ERROR = 8451,
+ MD_ERROR_WIN_DS_DRA_NO_REPLICA = 8452,
+ MD_ERROR_WIN_DS_DRA_ACCESS_DENIED = 8453,
+ MD_ERROR_WIN_DS_DRA_NOT_SUPPORTED = 8454,
+ MD_ERROR_WIN_DS_DRA_RPC_CANCELLED = 8455,
+ MD_ERROR_WIN_DS_DRA_SOURCE_DISABLED = 8456,
+ MD_ERROR_WIN_DS_DRA_SINK_DISABLED = 8457,
+ MD_ERROR_WIN_DS_DRA_NAME_COLLISION = 8458,
+ MD_ERROR_WIN_DS_DRA_SOURCE_REINSTALLED = 8459,
+ MD_ERROR_WIN_DS_DRA_MISSING_PARENT = 8460,
+ MD_ERROR_WIN_DS_DRA_PREEMPTED = 8461,
+ MD_ERROR_WIN_DS_DRA_ABANDON_SYNC = 8462,
+ MD_ERROR_WIN_DS_DRA_SHUTDOWN = 8463,
+ MD_ERROR_WIN_DS_DRA_INCOMPATIBLE_PARTIAL_SET = 8464,
+ MD_ERROR_WIN_DS_DRA_SOURCE_IS_PARTIAL_REPLICA = 8465,
+ MD_ERROR_WIN_DS_DRA_EXTN_CONNECTION_FAILED = 8466,
+ MD_ERROR_WIN_DS_INSTALL_SCHEMA_MISMATCH = 8467,
+ MD_ERROR_WIN_DS_DUP_LINK_ID = 8468,
+ MD_ERROR_WIN_DS_NAME_ERROR_RESOLVING = 8469,
+ MD_ERROR_WIN_DS_NAME_ERROR_NOT_FOUND = 8470,
+ MD_ERROR_WIN_DS_NAME_ERROR_NOT_UNIQUE = 8471,
+ MD_ERROR_WIN_DS_NAME_ERROR_NO_MAPPING = 8472,
+ MD_ERROR_WIN_DS_NAME_ERROR_DOMAIN_ONLY = 8473,
+ MD_ERROR_WIN_DS_NAME_ERROR_NO_SYNTACTICAL_MAPPING = 8474,
+ MD_ERROR_WIN_DS_CONSTRUCTED_ATT_MOD = 8475,
+ MD_ERROR_WIN_DS_WRONG_OM_OBJ_CLASS = 8476,
+ MD_ERROR_WIN_DS_DRA_REPL_PENDING = 8477,
+ MD_ERROR_WIN_DS_DS_REQUIRED = 8478,
+ MD_ERROR_WIN_DS_INVALID_LDAP_DISPLAY_NAME = 8479,
+ MD_ERROR_WIN_DS_NON_BASE_SEARCH = 8480,
+ MD_ERROR_WIN_DS_CANT_RETRIEVE_ATTS = 8481,
+ MD_ERROR_WIN_DS_BACKLINK_WITHOUT_LINK = 8482,
+ MD_ERROR_WIN_DS_EPOCH_MISMATCH = 8483,
+ MD_ERROR_WIN_DS_SRC_NAME_MISMATCH = 8484,
+ MD_ERROR_WIN_DS_SRC_AND_DST_NC_IDENTICAL = 8485,
+ MD_ERROR_WIN_DS_DST_NC_MISMATCH = 8486,
+ MD_ERROR_WIN_DS_NOT_AUTHORITIVE_FOR_DST_NC = 8487,
+ MD_ERROR_WIN_DS_SRC_GUID_MISMATCH = 8488,
+ MD_ERROR_WIN_DS_CANT_MOVE_DELETED_OBJECT = 8489,
+ MD_ERROR_WIN_DS_PDC_OPERATION_IN_PROGRESS = 8490,
+ MD_ERROR_WIN_DS_CROSS_DOMAIN_CLEANUP_REQD = 8491,
+ MD_ERROR_WIN_DS_ILLEGAL_XDOM_MOVE_OPERATION = 8492,
+ MD_ERROR_WIN_DS_CANT_WITH_ACCT_GROUP_MEMBERSHPS = 8493,
+ MD_ERROR_WIN_DS_NC_MUST_HAVE_NC_PARENT = 8494,
+ MD_ERROR_WIN_DS_CR_IMPOSSIBLE_TO_VALIDATE = 8495,
+ MD_ERROR_WIN_DS_DST_DOMAIN_NOT_NATIVE = 8496,
+ MD_ERROR_WIN_DS_MISSING_INFRASTRUCTURE_CONTAINER = 8497,
+ MD_ERROR_WIN_DS_CANT_MOVE_ACCOUNT_GROUP = 8498,
+ MD_ERROR_WIN_DS_CANT_MOVE_RESOURCE_GROUP = 8499,
+ MD_ERROR_WIN_DS_INVALID_SEARCH_FLAG = 8500,
+ MD_ERROR_WIN_DS_NO_TREE_DELETE_ABOVE_NC = 8501,
+ MD_ERROR_WIN_DS_COULDNT_LOCK_TREE_FOR_DELETE = 8502,
+ MD_ERROR_WIN_DS_COULDNT_IDENTIFY_OBJECTS_FOR_TREE_DELETE = 8503,
+ MD_ERROR_WIN_DS_SAM_INIT_FAILURE = 8504,
+ MD_ERROR_WIN_DS_SENSITIVE_GROUP_VIOLATION = 8505,
+ MD_ERROR_WIN_DS_CANT_MOD_PRIMARYGROUPID = 8506,
+ MD_ERROR_WIN_DS_ILLEGAL_BASE_SCHEMA_MOD = 8507,
+ MD_ERROR_WIN_DS_NONSAFE_SCHEMA_CHANGE = 8508,
+ MD_ERROR_WIN_DS_SCHEMA_UPDATE_DISALLOWED = 8509,
+ MD_ERROR_WIN_DS_CANT_CREATE_UNDER_SCHEMA = 8510,
+ MD_ERROR_WIN_DS_INSTALL_NO_SRC_SCH_VERSION = 8511,
+ MD_ERROR_WIN_DS_INSTALL_NO_SCH_VERSION_IN_INIFILE = 8512,
+ MD_ERROR_WIN_DS_INVALID_GROUP_TYPE = 8513,
+ MD_ERROR_WIN_DS_NO_NEST_GLOBALGROUP_IN_MIXEDDOMAIN = 8514,
+ MD_ERROR_WIN_DS_NO_NEST_LOCALGROUP_IN_MIXEDDOMAIN = 8515,
+ MD_ERROR_WIN_DS_GLOBAL_CANT_HAVE_LOCAL_MEMBER = 8516,
+ MD_ERROR_WIN_DS_GLOBAL_CANT_HAVE_UNIVERSAL_MEMBER = 8517,
+ MD_ERROR_WIN_DS_UNIVERSAL_CANT_HAVE_LOCAL_MEMBER = 8518,
+ MD_ERROR_WIN_DS_GLOBAL_CANT_HAVE_CROSSDOMAIN_MEMBER = 8519,
+ MD_ERROR_WIN_DS_LOCAL_CANT_HAVE_CROSSDOMAIN_LOCAL_MEMBER = 8520,
+ MD_ERROR_WIN_DS_HAVE_PRIMARY_MEMBERS = 8521,
+ MD_ERROR_WIN_DS_STRING_SD_CONVERSION_FAILED = 8522,
+ MD_ERROR_WIN_DS_NAMING_MASTER_GC = 8523,
+ MD_ERROR_WIN_DS_DNS_LOOKUP_FAILURE = 8524,
+ MD_ERROR_WIN_DS_COULDNT_UPDATE_SPNS = 8525,
+ MD_ERROR_WIN_DS_CANT_RETRIEVE_SD = 8526,
+ MD_ERROR_WIN_DS_KEY_NOT_UNIQUE = 8527,
+ MD_ERROR_WIN_DS_WRONG_LINKED_ATT_SYNTAX = 8528,
+ MD_ERROR_WIN_DS_SAM_NEED_BOOTKEY_PASSWORD = 8529,
+ MD_ERROR_WIN_DS_SAM_NEED_BOOTKEY_FLOPPY = 8530,
+ MD_ERROR_WIN_DS_CANT_START = 8531,
+ MD_ERROR_WIN_DS_INIT_FAILURE = 8532,
+ MD_ERROR_WIN_DS_NO_PKT_PRIVACY_ON_CONNECTION = 8533,
+ MD_ERROR_WIN_DS_SOURCE_DOMAIN_IN_FOREST = 8534,
+ MD_ERROR_WIN_DS_DESTINATION_DOMAIN_NOT_IN_FOREST = 8535,
+ MD_ERROR_WIN_DS_DESTINATION_AUDITING_NOT_ENABLED = 8536,
+ MD_ERROR_WIN_DS_CANT_FIND_DC_FOR_SRC_DOMAIN = 8537,
+ MD_ERROR_WIN_DS_SRC_OBJ_NOT_GROUP_OR_USER = 8538,
+ MD_ERROR_WIN_DS_SRC_SID_EXISTS_IN_FOREST = 8539,
+ MD_ERROR_WIN_DS_SRC_AND_DST_OBJECT_CLASS_MISMATCH = 8540,
+ MD_ERROR_WIN_SAM_INIT_FAILURE = 8541,
+ MD_ERROR_WIN_DS_DRA_SCHEMA_INFO_SHIP = 8542,
+ MD_ERROR_WIN_DS_DRA_SCHEMA_CONFLICT = 8543,
+ MD_ERROR_WIN_DS_DRA_EARLIER_SCHEMA_CONFLICT = 8544,
+ MD_ERROR_WIN_DS_DRA_OBJ_NC_MISMATCH = 8545,
+ MD_ERROR_WIN_DS_NC_STILL_HAS_DSAS = 8546,
+ MD_ERROR_WIN_DS_GC_REQUIRED = 8547,
+ MD_ERROR_WIN_DS_LOCAL_MEMBER_OF_LOCAL_ONLY = 8548,
+ MD_ERROR_WIN_DS_NO_FPO_IN_UNIVERSAL_GROUPS = 8549,
+ MD_ERROR_WIN_DS_CANT_ADD_TO_GC = 8550,
+ MD_ERROR_WIN_DS_NO_CHECKPOINT_WITH_PDC = 8551,
+ MD_ERROR_WIN_DS_SOURCE_AUDITING_NOT_ENABLED = 8552,
+ MD_ERROR_WIN_DS_CANT_CREATE_IN_NONDOMAIN_NC = 8553,
+ MD_ERROR_WIN_DS_INVALID_NAME_FOR_SPN = 8554,
+ MD_ERROR_WIN_DS_FILTER_USES_CONTRUCTED_ATTRS = 8555,
+ MD_ERROR_WIN_DS_UNICODEPWD_NOT_IN_QUOTES = 8556,
+ MD_ERROR_WIN_DS_MACHINE_ACCOUNT_QUOTA_EXCEEDED = 8557,
+ MD_ERROR_WIN_DS_MUST_BE_RUN_ON_DST_DC = 8558,
+ MD_ERROR_WIN_DS_SRC_DC_MUST_BE_SP4_OR_GREATER = 8559,
+ MD_ERROR_WIN_DS_CANT_TREE_DELETE_CRITICAL_OBJ = 8560,
+ MD_ERROR_WIN_DS_INIT_FAILURE_CONSOLE = 8561,
+ MD_ERROR_WIN_DS_SAM_INIT_FAILURE_CONSOLE = 8562,
+ MD_ERROR_WIN_DS_FOREST_VERSION_TOO_HIGH = 8563,
+ MD_ERROR_WIN_DS_DOMAIN_VERSION_TOO_HIGH = 8564,
+ MD_ERROR_WIN_DS_FOREST_VERSION_TOO_LOW = 8565,
+ MD_ERROR_WIN_DS_DOMAIN_VERSION_TOO_LOW = 8566,
+ MD_ERROR_WIN_DS_INCOMPATIBLE_VERSION = 8567,
+ MD_ERROR_WIN_DS_LOW_DSA_VERSION = 8568,
+ MD_ERROR_WIN_DS_NO_BEHAVIOR_VERSION_IN_MIXEDDOMAIN = 8569,
+ MD_ERROR_WIN_DS_NOT_SUPPORTED_SORT_ORDER = 8570,
+ MD_ERROR_WIN_DS_NAME_NOT_UNIQUE = 8571,
+ MD_ERROR_WIN_DS_MACHINE_ACCOUNT_CREATED_PRENT4 = 8572,
+ MD_ERROR_WIN_DS_OUT_OF_VERSION_STORE = 8573,
+ MD_ERROR_WIN_DS_INCOMPATIBLE_CONTROLS_USED = 8574,
+ MD_ERROR_WIN_DS_NO_REF_DOMAIN = 8575,
+ MD_ERROR_WIN_DS_RESERVED_LINK_ID = 8576,
+ MD_ERROR_WIN_DS_LINK_ID_NOT_AVAILABLE = 8577,
+ MD_ERROR_WIN_DS_AG_CANT_HAVE_UNIVERSAL_MEMBER = 8578,
+ MD_ERROR_WIN_DS_MODIFYDN_DISALLOWED_BY_INSTANCE_TYPE = 8579,
+ MD_ERROR_WIN_DS_NO_OBJECT_MOVE_IN_SCHEMA_NC = 8580,
+ MD_ERROR_WIN_DS_MODIFYDN_DISALLOWED_BY_FLAG = 8581,
+ MD_ERROR_WIN_DS_MODIFYDN_WRONG_GRANDPARENT = 8582,
+ MD_ERROR_WIN_DS_NAME_ERROR_TRUST_REFERRAL = 8583,
+ MD_ERROR_WIN_NOT_SUPPORTED_ON_STANDARD_SERVER = 8584,
+ MD_ERROR_WIN_DS_CANT_ACCESS_REMOTE_PART_OF_AD = 8585,
+ MD_ERROR_WIN_DS_CR_IMPOSSIBLE_TO_VALIDATE_V2 = 8586,
+ MD_ERROR_WIN_DS_THREAD_LIMIT_EXCEEDED = 8587,
+ MD_ERROR_WIN_DS_NOT_CLOSEST = 8588,
+ MD_ERROR_WIN_DS_CANT_DERIVE_SPN_WITHOUT_SERVER_REF = 8589,
+ MD_ERROR_WIN_DS_SINGLE_USER_MODE_FAILED = 8590,
+ MD_ERROR_WIN_DS_NTDSCRIPT_SYNTAX_ERROR = 8591,
+ MD_ERROR_WIN_DS_NTDSCRIPT_PROCESS_ERROR = 8592,
+ MD_ERROR_WIN_DS_DIFFERENT_REPL_EPOCHS = 8593,
+ MD_ERROR_WIN_DS_DRS_EXTENSIONS_CHANGED = 8594,
+ MD_ERROR_WIN_DS_REPLICA_SET_CHANGE_NOT_ALLOWED_ON_DISABLED_CR = 8595,
+ MD_ERROR_WIN_DS_NO_MSDS_INTID = 8596,
+ MD_ERROR_WIN_DS_DUP_MSDS_INTID = 8597,
+ MD_ERROR_WIN_DS_EXISTS_IN_RDNATTID = 8598,
+ MD_ERROR_WIN_DS_AUTHORIZATION_FAILED = 8599,
+ MD_ERROR_WIN_DS_INVALID_SCRIPT = 8600,
+ MD_ERROR_WIN_DS_REMOTE_CROSSREF_OP_FAILED = 8601,
+ MD_ERROR_WIN_DS_CROSS_REF_BUSY = 8602,
+ MD_ERROR_WIN_DS_CANT_DERIVE_SPN_FOR_DELETED_DOMAIN = 8603,
+ MD_ERROR_WIN_DS_CANT_DEMOTE_WITH_WRITEABLE_NC = 8604,
+ MD_ERROR_WIN_DS_DUPLICATE_ID_FOUND = 8605,
+ MD_ERROR_WIN_DS_INSUFFICIENT_ATTR_TO_CREATE_OBJECT = 8606,
+ MD_ERROR_WIN_DS_GROUP_CONVERSION_ERROR = 8607,
+ MD_ERROR_WIN_DS_CANT_MOVE_APP_BASIC_GROUP = 8608,
+ MD_ERROR_WIN_DS_CANT_MOVE_APP_QUERY_GROUP = 8609,
+ MD_ERROR_WIN_DS_ROLE_NOT_VERIFIED = 8610,
+ MD_ERROR_WIN_DS_WKO_CONTAINER_CANNOT_BE_SPECIAL = 8611,
+ MD_ERROR_WIN_DS_DOMAIN_RENAME_IN_PROGRESS = 8612,
+ MD_ERROR_WIN_DS_EXISTING_AD_CHILD_NC = 8613,
+ MD_ERROR_WIN_DS_REPL_LIFETIME_EXCEEDED = 8614,
+ MD_ERROR_WIN_DS_DISALLOWED_IN_SYSTEM_CONTAINER = 8615,
+ MD_ERROR_WIN_DS_LDAP_SEND_QUEUE_FULL = 8616,
+ MD_ERROR_WIN_DS_DRA_OUT_SCHEDULE_WINDOW = 8617,
+ MD_ERROR_WIN_DS_POLICY_NOT_KNOWN = 8618,
+ MD_ERROR_WIN_NO_SITE_SETTINGS_OBJECT = 8619,
+ MD_ERROR_WIN_NO_SECRETS = 8620,
+ MD_ERROR_WIN_NO_WRITABLE_DC_FOUND = 8621,
+ MD_ERROR_WIN_DS_NO_SERVER_OBJECT = 8622,
+ MD_ERROR_WIN_DS_NO_NTDSA_OBJECT = 8623,
+ MD_ERROR_WIN_DS_NON_ASQ_SEARCH = 8624,
+ MD_ERROR_WIN_DS_AUDIT_FAILURE = 8625,
+ MD_ERROR_WIN_DS_INVALID_SEARCH_FLAG_SUBTREE = 8626,
+ MD_ERROR_WIN_DS_INVALID_SEARCH_FLAG_TUPLE = 8627,
+ MD_ERROR_WIN_DS_HIERARCHY_TABLE_TOO_DEEP = 8628,
+ MD_ERROR_WIN_DS_DRA_CORRUPT_UTD_VECTOR = 8629,
+ MD_ERROR_WIN_DS_DRA_SECRETS_DENIED = 8630,
+ MD_ERROR_WIN_DS_RESERVED_MAPI_ID = 8631,
+ MD_ERROR_WIN_DS_MAPI_ID_NOT_AVAILABLE = 8632,
+ MD_ERROR_WIN_DS_DRA_MISSING_KRBTGT_SECRET = 8633,
+ MD_ERROR_WIN_DS_DOMAIN_NAME_EXISTS_IN_FOREST = 8634,
+ MD_ERROR_WIN_DS_FLAT_NAME_EXISTS_IN_FOREST = 8635,
+ MD_ERROR_WIN_INVALID_USER_PRINCIPAL_NAME = 8636,
+ MD_ERROR_WIN_DS_OID_MAPPED_GROUP_CANT_HAVE_MEMBERS = 8637,
+ MD_ERROR_WIN_DS_OID_NOT_FOUND = 8638,
+ MD_ERROR_WIN_DS_DRA_RECYCLED_TARGET = 8639,
+ MD_ERROR_WIN_DS_DISALLOWED_NC_REDIRECT = 8640,
+ MD_ERROR_WIN_DS_HIGH_ADLDS_FFL = 8641,
+ MD_ERROR_WIN_DS_HIGH_DSA_VERSION = 8642,
+ MD_ERROR_WIN_DS_LOW_ADLDS_FFL = 8643,
+ MD_ERROR_WIN_DOMAIN_SID_SAME_AS_LOCAL_WORKSTATION = 8644,
+ MD_ERROR_WIN_DS_UNDELETE_SAM_VALIDATION_FAILED = 8645,
+ MD_ERROR_WIN_INCORRECT_ACCOUNT_TYPE = 8646,
+ MD_ERROR_WIN_DS_SPN_VALUE_NOT_UNIQUE_IN_FOREST = 8647,
+ MD_ERROR_WIN_DS_UPN_VALUE_NOT_UNIQUE_IN_FOREST = 8648,
+ MD_ERROR_WIN_DS_MISSING_FOREST_TRUST = 8649,
+ MD_ERROR_WIN_DS_VALUE_KEY_NOT_UNIQUE = 8650,
+ MD_ERROR_WIN_IPSEC_QM_POLICY_EXISTS = 13000,
+ MD_ERROR_WIN_IPSEC_QM_POLICY_NOT_FOUND = 13001,
+ MD_ERROR_WIN_IPSEC_QM_POLICY_IN_USE = 13002,
+ MD_ERROR_WIN_IPSEC_MM_POLICY_EXISTS = 13003,
+ MD_ERROR_WIN_IPSEC_MM_POLICY_NOT_FOUND = 13004,
+ MD_ERROR_WIN_IPSEC_MM_POLICY_IN_USE = 13005,
+ MD_ERROR_WIN_IPSEC_MM_FILTER_EXISTS = 13006,
+ MD_ERROR_WIN_IPSEC_MM_FILTER_NOT_FOUND = 13007,
+ MD_ERROR_WIN_IPSEC_TRANSPORT_FILTER_EXISTS = 13008,
+ MD_ERROR_WIN_IPSEC_TRANSPORT_FILTER_NOT_FOUND = 13009,
+ MD_ERROR_WIN_IPSEC_MM_AUTH_EXISTS = 13010,
+ MD_ERROR_WIN_IPSEC_MM_AUTH_NOT_FOUND = 13011,
+ MD_ERROR_WIN_IPSEC_MM_AUTH_IN_USE = 13012,
+ MD_ERROR_WIN_IPSEC_DEFAULT_MM_POLICY_NOT_FOUND = 13013,
+ MD_ERROR_WIN_IPSEC_DEFAULT_MM_AUTH_NOT_FOUND = 13014,
+ MD_ERROR_WIN_IPSEC_DEFAULT_QM_POLICY_NOT_FOUND = 13015,
+ MD_ERROR_WIN_IPSEC_TUNNEL_FILTER_EXISTS = 13016,
+ MD_ERROR_WIN_IPSEC_TUNNEL_FILTER_NOT_FOUND = 13017,
+ MD_ERROR_WIN_IPSEC_MM_FILTER_PENDING_DELETION = 13018,
+ MD_ERROR_WIN_IPSEC_TRANSPORT_FILTER_PENDING_DELETION = 13019,
+ MD_ERROR_WIN_IPSEC_TUNNEL_FILTER_PENDING_DELETION = 13020,
+ MD_ERROR_WIN_IPSEC_MM_POLICY_PENDING_DELETION = 13021,
+ MD_ERROR_WIN_IPSEC_MM_AUTH_PENDING_DELETION = 13022,
+ MD_ERROR_WIN_IPSEC_QM_POLICY_PENDING_DELETION = 13023,
+ MD_ERROR_WIN_IPSEC_IKE_NEG_STATUS_BEGIN = 13800,
+ MD_ERROR_WIN_IPSEC_IKE_AUTH_FAIL = 13801,
+ MD_ERROR_WIN_IPSEC_IKE_ATTRIB_FAIL = 13802,
+ MD_ERROR_WIN_IPSEC_IKE_NEGOTIATION_PENDING = 13803,
+ MD_ERROR_WIN_IPSEC_IKE_GENERAL_PROCESSING_ERROR = 13804,
+ MD_ERROR_WIN_IPSEC_IKE_TIMED_OUT = 13805,
+ MD_ERROR_WIN_IPSEC_IKE_NO_CERT = 13806,
+ MD_ERROR_WIN_IPSEC_IKE_SA_DELETED = 13807,
+ MD_ERROR_WIN_IPSEC_IKE_SA_REAPED = 13808,
+ MD_ERROR_WIN_IPSEC_IKE_MM_ACQUIRE_DROP = 13809,
+ MD_ERROR_WIN_IPSEC_IKE_QM_ACQUIRE_DROP = 13810,
+ MD_ERROR_WIN_IPSEC_IKE_QUEUE_DROP_MM = 13811,
+ MD_ERROR_WIN_IPSEC_IKE_QUEUE_DROP_NO_MM = 13812,
+ MD_ERROR_WIN_IPSEC_IKE_DROP_NO_RESPONSE = 13813,
+ MD_ERROR_WIN_IPSEC_IKE_MM_DELAY_DROP = 13814,
+ MD_ERROR_WIN_IPSEC_IKE_QM_DELAY_DROP = 13815,
+ MD_ERROR_WIN_IPSEC_IKE_ERROR = 13816,
+ MD_ERROR_WIN_IPSEC_IKE_CRL_FAILED = 13817,
+ MD_ERROR_WIN_IPSEC_IKE_INVALID_KEY_USAGE = 13818,
+ MD_ERROR_WIN_IPSEC_IKE_INVALID_CERT_TYPE = 13819,
+ MD_ERROR_WIN_IPSEC_IKE_NO_PRIVATE_KEY = 13820,
+ MD_ERROR_WIN_IPSEC_IKE_SIMULTANEOUS_REKEY = 13821,
+ MD_ERROR_WIN_IPSEC_IKE_DH_FAIL = 13822,
+ MD_ERROR_WIN_IPSEC_IKE_CRITICAL_PAYLOAD_NOT_RECOGNIZED = 13823,
+ MD_ERROR_WIN_IPSEC_IKE_INVALID_HEADER = 13824,
+ MD_ERROR_WIN_IPSEC_IKE_NO_POLICY = 13825,
+ MD_ERROR_WIN_IPSEC_IKE_INVALID_SIGNATURE = 13826,
+ MD_ERROR_WIN_IPSEC_IKE_KERBEROS_ERROR = 13827,
+ MD_ERROR_WIN_IPSEC_IKE_NO_PUBLIC_KEY = 13828,
+ MD_ERROR_WIN_IPSEC_IKE_PROCESS_ERR = 13829,
+ MD_ERROR_WIN_IPSEC_IKE_PROCESS_ERR_SA = 13830,
+ MD_ERROR_WIN_IPSEC_IKE_PROCESS_ERR_PROP = 13831,
+ MD_ERROR_WIN_IPSEC_IKE_PROCESS_ERR_TRANS = 13832,
+ MD_ERROR_WIN_IPSEC_IKE_PROCESS_ERR_KE = 13833,
+ MD_ERROR_WIN_IPSEC_IKE_PROCESS_ERR_ID = 13834,
+ MD_ERROR_WIN_IPSEC_IKE_PROCESS_ERR_CERT = 13835,
+ MD_ERROR_WIN_IPSEC_IKE_PROCESS_ERR_CERT_REQ = 13836,
+ MD_ERROR_WIN_IPSEC_IKE_PROCESS_ERR_HASH = 13837,
+ MD_ERROR_WIN_IPSEC_IKE_PROCESS_ERR_SIG = 13838,
+ MD_ERROR_WIN_IPSEC_IKE_PROCESS_ERR_NONCE = 13839,
+ MD_ERROR_WIN_IPSEC_IKE_PROCESS_ERR_NOTIFY = 13840,
+ MD_ERROR_WIN_IPSEC_IKE_PROCESS_ERR_DELETE = 13841,
+ MD_ERROR_WIN_IPSEC_IKE_PROCESS_ERR_VENDOR = 13842,
+ MD_ERROR_WIN_IPSEC_IKE_INVALID_PAYLOAD = 13843,
+ MD_ERROR_WIN_IPSEC_IKE_LOAD_SOFT_SA = 13844,
+ MD_ERROR_WIN_IPSEC_IKE_SOFT_SA_TORN_DOWN = 13845,
+ MD_ERROR_WIN_IPSEC_IKE_INVALID_COOKIE = 13846,
+ MD_ERROR_WIN_IPSEC_IKE_NO_PEER_CERT = 13847,
+ MD_ERROR_WIN_IPSEC_IKE_PEER_CRL_FAILED = 13848,
+ MD_ERROR_WIN_IPSEC_IKE_POLICY_CHANGE = 13849,
+ MD_ERROR_WIN_IPSEC_IKE_NO_MM_POLICY = 13850,
+ MD_ERROR_WIN_IPSEC_IKE_NOTCBPRIV = 13851,
+ MD_ERROR_WIN_IPSEC_IKE_SECLOADFAIL = 13852,
+ MD_ERROR_WIN_IPSEC_IKE_FAILSSPINIT = 13853,
+ MD_ERROR_WIN_IPSEC_IKE_FAILQUERYSSP = 13854,
+ MD_ERROR_WIN_IPSEC_IKE_SRVACQFAIL = 13855,
+ MD_ERROR_WIN_IPSEC_IKE_SRVQUERYCRED = 13856,
+ MD_ERROR_WIN_IPSEC_IKE_GETSPIFAIL = 13857,
+ MD_ERROR_WIN_IPSEC_IKE_INVALID_FILTER = 13858,
+ MD_ERROR_WIN_IPSEC_IKE_OUT_OF_MEMORY = 13859,
+ MD_ERROR_WIN_IPSEC_IKE_ADD_UPDATE_KEY_FAILED = 13860,
+ MD_ERROR_WIN_IPSEC_IKE_INVALID_POLICY = 13861,
+ MD_ERROR_WIN_IPSEC_IKE_UNKNOWN_DOI = 13862,
+ MD_ERROR_WIN_IPSEC_IKE_INVALID_SITUATION = 13863,
+ MD_ERROR_WIN_IPSEC_IKE_DH_FAILURE = 13864,
+ MD_ERROR_WIN_IPSEC_IKE_INVALID_GROUP = 13865,
+ MD_ERROR_WIN_IPSEC_IKE_ENCRYPT = 13866,
+ MD_ERROR_WIN_IPSEC_IKE_DECRYPT = 13867,
+ MD_ERROR_WIN_IPSEC_IKE_POLICY_MATCH = 13868,
+ MD_ERROR_WIN_IPSEC_IKE_UNSUPPORTED_ID = 13869,
+ MD_ERROR_WIN_IPSEC_IKE_INVALID_HASH = 13870,
+ MD_ERROR_WIN_IPSEC_IKE_INVALID_HASH_ALG = 13871,
+ MD_ERROR_WIN_IPSEC_IKE_INVALID_HASH_SIZE = 13872,
+ MD_ERROR_WIN_IPSEC_IKE_INVALID_ENCRYPT_ALG = 13873,
+ MD_ERROR_WIN_IPSEC_IKE_INVALID_AUTH_ALG = 13874,
+ MD_ERROR_WIN_IPSEC_IKE_INVALID_SIG = 13875,
+ MD_ERROR_WIN_IPSEC_IKE_LOAD_FAILED = 13876,
+ MD_ERROR_WIN_IPSEC_IKE_RPC_DELETE = 13877,
+ MD_ERROR_WIN_IPSEC_IKE_BENIGN_REINIT = 13878,
+ MD_ERROR_WIN_IPSEC_IKE_INVALID_RESPONDER_LIFETIME_NOTIFY = 13879,
+ MD_ERROR_WIN_IPSEC_IKE_INVALID_MAJOR_VERSION = 13880,
+ MD_ERROR_WIN_IPSEC_IKE_INVALID_CERT_KEYLEN = 13881,
+ MD_ERROR_WIN_IPSEC_IKE_MM_LIMIT = 13882,
+ MD_ERROR_WIN_IPSEC_IKE_NEGOTIATION_DISABLED = 13883,
+ MD_ERROR_WIN_IPSEC_IKE_QM_LIMIT = 13884,
+ MD_ERROR_WIN_IPSEC_IKE_MM_EXPIRED = 13885,
+ MD_ERROR_WIN_IPSEC_IKE_PEER_MM_ASSUMED_INVALID = 13886,
+ MD_ERROR_WIN_IPSEC_IKE_CERT_CHAIN_POLICY_MISMATCH = 13887,
+ MD_ERROR_WIN_IPSEC_IKE_UNEXPECTED_MESSAGE_ID = 13888,
+ MD_ERROR_WIN_IPSEC_IKE_INVALID_AUTH_PAYLOAD = 13889,
+ MD_ERROR_WIN_IPSEC_IKE_DOS_COOKIE_SENT = 13890,
+ MD_ERROR_WIN_IPSEC_IKE_SHUTTING_DOWN = 13891,
+ MD_ERROR_WIN_IPSEC_IKE_CGA_AUTH_FAILED = 13892,
+ MD_ERROR_WIN_IPSEC_IKE_PROCESS_ERR_NATOA = 13893,
+ MD_ERROR_WIN_IPSEC_IKE_INVALID_MM_FOR_QM = 13894,
+ MD_ERROR_WIN_IPSEC_IKE_QM_EXPIRED = 13895,
+ MD_ERROR_WIN_IPSEC_IKE_TOO_MANY_FILTERS = 13896,
+ MD_ERROR_WIN_IPSEC_IKE_NEG_STATUS_END = 13897,
+ MD_ERROR_WIN_IPSEC_IKE_KILL_DUMMY_NAP_TUNNEL = 13898,
+ MD_ERROR_WIN_IPSEC_IKE_INNER_IP_ASSIGNMENT_FAILURE = 13899,
+ MD_ERROR_WIN_IPSEC_IKE_REQUIRE_CP_PAYLOAD_MISSING = 13900,
+ MD_ERROR_WIN_IPSEC_KEY_MODULE_IMPERSONATION_NEGOTIATION_PENDING = 13901,
+ MD_ERROR_WIN_IPSEC_IKE_COEXISTENCE_SUPPRESS = 13902,
+ MD_ERROR_WIN_IPSEC_IKE_RATELIMIT_DROP = 13903,
+ MD_ERROR_WIN_IPSEC_IKE_PEER_DOESNT_SUPPORT_MOBIKE = 13904,
+ MD_ERROR_WIN_IPSEC_IKE_AUTHORIZATION_FAILURE = 13905,
+ MD_ERROR_WIN_IPSEC_IKE_STRONG_CRED_AUTHORIZATION_FAILURE = 13906,
+ MD_ERROR_WIN_IPSEC_IKE_AUTHORIZATION_FAILURE_WITH_OPTIONAL_RETRY = 13907,
+ MD_ERROR_WIN_IPSEC_IKE_STRONG_CRED_AUTHORIZATION_AND_CERTMAP_FAILURE = 13908,
+ MD_ERROR_WIN_IPSEC_IKE_NEG_STATUS_EXTENDED_END = 13909,
+ MD_ERROR_WIN_IPSEC_BAD_SPI = 13910,
+ MD_ERROR_WIN_IPSEC_SA_LIFETIME_EXPIRED = 13911,
+ MD_ERROR_WIN_IPSEC_WRONG_SA = 13912,
+ MD_ERROR_WIN_IPSEC_REPLAY_CHECK_FAILED = 13913,
+ MD_ERROR_WIN_IPSEC_INVALID_PACKET = 13914,
+ MD_ERROR_WIN_IPSEC_INTEGRITY_CHECK_FAILED = 13915,
+ MD_ERROR_WIN_IPSEC_CLEAR_TEXT_DROP = 13916,
+ MD_ERROR_WIN_IPSEC_AUTH_FIREWALL_DROP = 13917,
+ MD_ERROR_WIN_IPSEC_THROTTLE_DROP = 13918,
+ MD_ERROR_WIN_IPSEC_DOSP_BLOCK = 13925,
+ MD_ERROR_WIN_IPSEC_DOSP_RECEIVED_MULTICAST = 13926,
+ MD_ERROR_WIN_IPSEC_DOSP_INVALID_PACKET = 13927,
+ MD_ERROR_WIN_IPSEC_DOSP_STATE_LOOKUP_FAILED = 13928,
+ MD_ERROR_WIN_IPSEC_DOSP_MAX_ENTRIES = 13929,
+ MD_ERROR_WIN_IPSEC_DOSP_KEYMOD_NOT_ALLOWED = 13930,
+ MD_ERROR_WIN_IPSEC_DOSP_NOT_INSTALLED = 13931,
+ MD_ERROR_WIN_IPSEC_DOSP_MAX_PER_IP_RATELIMIT_QUEUES = 13932,
+ MD_ERROR_WIN_SXS_SECTION_NOT_FOUND = 14000,
+ MD_ERROR_WIN_SXS_CANT_GEN_ACTCTX = 14001,
+ MD_ERROR_WIN_SXS_INVALID_ACTCTXDATA_FORMAT = 14002,
+ MD_ERROR_WIN_SXS_ASSEMBLY_NOT_FOUND = 14003,
+ MD_ERROR_WIN_SXS_MANIFEST_FORMAT_ERROR = 14004,
+ MD_ERROR_WIN_SXS_MANIFEST_PARSE_ERROR = 14005,
+ MD_ERROR_WIN_SXS_ACTIVATION_CONTEXT_DISABLED = 14006,
+ MD_ERROR_WIN_SXS_KEY_NOT_FOUND = 14007,
+ MD_ERROR_WIN_SXS_VERSION_CONFLICT = 14008,
+ MD_ERROR_WIN_SXS_WRONG_SECTION_TYPE = 14009,
+ MD_ERROR_WIN_SXS_THREAD_QUERIES_DISABLED = 14010,
+ MD_ERROR_WIN_SXS_PROCESS_DEFAULT_ALREADY_SET = 14011,
+ MD_ERROR_WIN_SXS_UNKNOWN_ENCODING_GROUP = 14012,
+ MD_ERROR_WIN_SXS_UNKNOWN_ENCODING = 14013,
+ MD_ERROR_WIN_SXS_INVALID_XML_NAMESPACE_URI = 14014,
+ MD_ERROR_WIN_SXS_ROOT_MANIFEST_DEPENDENCY_NOT_INSTALLED = 14015,
+ MD_ERROR_WIN_SXS_LEAF_MANIFEST_DEPENDENCY_NOT_INSTALLED = 14016,
+ MD_ERROR_WIN_SXS_INVALID_ASSEMBLY_IDENTITY_ATTRIBUTE = 14017,
+ MD_ERROR_WIN_SXS_MANIFEST_MISSING_REQUIRED_DEFAULT_NAMESPACE = 14018,
+ MD_ERROR_WIN_SXS_MANIFEST_INVALID_REQUIRED_DEFAULT_NAMESPACE = 14019,
+ MD_ERROR_WIN_SXS_PRIVATE_MANIFEST_CROSS_PATH_WITH_REPARSE_POINT = 14020,
+ MD_ERROR_WIN_SXS_DUPLICATE_DLL_NAME = 14021,
+ MD_ERROR_WIN_SXS_DUPLICATE_WINDOWCLASS_NAME = 14022,
+ MD_ERROR_WIN_SXS_DUPLICATE_CLSID = 14023,
+ MD_ERROR_WIN_SXS_DUPLICATE_IID = 14024,
+ MD_ERROR_WIN_SXS_DUPLICATE_TLBID = 14025,
+ MD_ERROR_WIN_SXS_DUPLICATE_PROGID = 14026,
+ MD_ERROR_WIN_SXS_DUPLICATE_ASSEMBLY_NAME = 14027,
+ MD_ERROR_WIN_SXS_FILE_HASH_MISMATCH = 14028,
+ MD_ERROR_WIN_SXS_POLICY_PARSE_ERROR = 14029,
+ MD_ERROR_WIN_SXS_XML_E_MISSINGQUOTE = 14030,
+ MD_ERROR_WIN_SXS_XML_E_COMMENTSYNTAX = 14031,
+ MD_ERROR_WIN_SXS_XML_E_BADSTARTNAMECHAR = 14032,
+ MD_ERROR_WIN_SXS_XML_E_BADNAMECHAR = 14033,
+ MD_ERROR_WIN_SXS_XML_E_BADCHARINSTRING = 14034,
+ MD_ERROR_WIN_SXS_XML_E_XMLDECLSYNTAX = 14035,
+ MD_ERROR_WIN_SXS_XML_E_BADCHARDATA = 14036,
+ MD_ERROR_WIN_SXS_XML_E_MISSINGWHITESPACE = 14037,
+ MD_ERROR_WIN_SXS_XML_E_EXPECTINGTAGEND = 14038,
+ MD_ERROR_WIN_SXS_XML_E_MISSINGSEMICOLON = 14039,
+ MD_ERROR_WIN_SXS_XML_E_UNBALANCEDPAREN = 14040,
+ MD_ERROR_WIN_SXS_XML_E_INTERNALERROR = 14041,
+ MD_ERROR_WIN_SXS_XML_E_UNEXPECTED_WHITESPACE = 14042,
+ MD_ERROR_WIN_SXS_XML_E_INCOMPLETE_ENCODING = 14043,
+ MD_ERROR_WIN_SXS_XML_E_MISSING_PAREN = 14044,
+ MD_ERROR_WIN_SXS_XML_E_EXPECTINGCLOSEQUOTE = 14045,
+ MD_ERROR_WIN_SXS_XML_E_MULTIPLE_COLONS = 14046,
+ MD_ERROR_WIN_SXS_XML_E_INVALID_DECIMAL = 14047,
+ MD_ERROR_WIN_SXS_XML_E_INVALID_HEXIDECIMAL = 14048,
+ MD_ERROR_WIN_SXS_XML_E_INVALID_UNICODE = 14049,
+ MD_ERROR_WIN_SXS_XML_E_WHITESPACEORQUESTIONMARK = 14050,
+ MD_ERROR_WIN_SXS_XML_E_UNEXPECTEDENDTAG = 14051,
+ MD_ERROR_WIN_SXS_XML_E_UNCLOSEDTAG = 14052,
+ MD_ERROR_WIN_SXS_XML_E_DUPLICATEATTRIBUTE = 14053,
+ MD_ERROR_WIN_SXS_XML_E_MULTIPLEROOTS = 14054,
+ MD_ERROR_WIN_SXS_XML_E_INVALIDATROOTLEVEL = 14055,
+ MD_ERROR_WIN_SXS_XML_E_BADXMLDECL = 14056,
+ MD_ERROR_WIN_SXS_XML_E_MISSINGROOT = 14057,
+ MD_ERROR_WIN_SXS_XML_E_UNEXPECTEDEOF = 14058,
+ MD_ERROR_WIN_SXS_XML_E_BADPEREFINSUBSET = 14059,
+ MD_ERROR_WIN_SXS_XML_E_UNCLOSEDSTARTTAG = 14060,
+ MD_ERROR_WIN_SXS_XML_E_UNCLOSEDENDTAG = 14061,
+ MD_ERROR_WIN_SXS_XML_E_UNCLOSEDSTRING = 14062,
+ MD_ERROR_WIN_SXS_XML_E_UNCLOSEDCOMMENT = 14063,
+ MD_ERROR_WIN_SXS_XML_E_UNCLOSEDDECL = 14064,
+ MD_ERROR_WIN_SXS_XML_E_UNCLOSEDCDATA = 14065,
+ MD_ERROR_WIN_SXS_XML_E_RESERVEDNAMESPACE = 14066,
+ MD_ERROR_WIN_SXS_XML_E_INVALIDENCODING = 14067,
+ MD_ERROR_WIN_SXS_XML_E_INVALIDSWITCH = 14068,
+ MD_ERROR_WIN_SXS_XML_E_BADXMLCASE = 14069,
+ MD_ERROR_WIN_SXS_XML_E_INVALID_STANDALONE = 14070,
+ MD_ERROR_WIN_SXS_XML_E_UNEXPECTED_STANDALONE = 14071,
+ MD_ERROR_WIN_SXS_XML_E_INVALID_VERSION = 14072,
+ MD_ERROR_WIN_SXS_XML_E_MISSINGEQUALS = 14073,
+ MD_ERROR_WIN_SXS_PROTECTION_RECOVERY_FAILED = 14074,
+ MD_ERROR_WIN_SXS_PROTECTION_PUBLIC_KEY_TOO_SHORT = 14075,
+ MD_ERROR_WIN_SXS_PROTECTION_CATALOG_NOT_VALID = 14076,
+ MD_ERROR_WIN_SXS_UNTRANSLATABLE_HRESULT = 14077,
+ MD_ERROR_WIN_SXS_PROTECTION_CATALOG_FILE_MISSING = 14078,
+ MD_ERROR_WIN_SXS_MISSING_ASSEMBLY_IDENTITY_ATTRIBUTE = 14079,
+ MD_ERROR_WIN_SXS_INVALID_ASSEMBLY_IDENTITY_ATTRIBUTE_NAME = 14080,
+ MD_ERROR_WIN_SXS_ASSEMBLY_MISSING = 14081,
+ MD_ERROR_WIN_SXS_CORRUPT_ACTIVATION_STACK = 14082,
+ MD_ERROR_WIN_SXS_CORRUPTION = 14083,
+ MD_ERROR_WIN_SXS_EARLY_DEACTIVATION = 14084,
+ MD_ERROR_WIN_SXS_INVALID_DEACTIVATION = 14085,
+ MD_ERROR_WIN_SXS_MULTIPLE_DEACTIVATION = 14086,
+ MD_ERROR_WIN_SXS_PROCESS_TERMINATION_REQUESTED = 14087,
+ MD_ERROR_WIN_SXS_RELEASE_ACTIVATION_CONTEXT = 14088,
+ MD_ERROR_WIN_SXS_SYSTEM_DEFAULT_ACTIVATION_CONTEXT_EMPTY = 14089,
+ MD_ERROR_WIN_SXS_INVALID_IDENTITY_ATTRIBUTE_VALUE = 14090,
+ MD_ERROR_WIN_SXS_INVALID_IDENTITY_ATTRIBUTE_NAME = 14091,
+ MD_ERROR_WIN_SXS_IDENTITY_DUPLICATE_ATTRIBUTE = 14092,
+ MD_ERROR_WIN_SXS_IDENTITY_PARSE_ERROR = 14093,
+ MD_ERROR_WIN_MALFORMED_SUBSTITUTION_STRING = 14094,
+ MD_ERROR_WIN_SXS_INCORRECT_PUBLIC_KEY_TOKEN = 14095,
+ MD_ERROR_WIN_UNMAPPED_SUBSTITUTION_STRING = 14096,
+ MD_ERROR_WIN_SXS_ASSEMBLY_NOT_LOCKED = 14097,
+ MD_ERROR_WIN_SXS_COMPONENT_STORE_CORRUPT = 14098,
+ MD_ERROR_WIN_ADVANCED_INSTALLER_FAILED = 14099,
+ MD_ERROR_WIN_XML_ENCODING_MISMATCH = 14100,
+ MD_ERROR_WIN_SXS_MANIFEST_IDENTITY_SAME_BUT_CONTENTS_DIFFERENT = 14101,
+ MD_ERROR_WIN_SXS_IDENTITIES_DIFFERENT = 14102,
+ MD_ERROR_WIN_SXS_ASSEMBLY_IS_NOT_A_DEPLOYMENT = 14103,
+ MD_ERROR_WIN_SXS_FILE_NOT_PART_OF_ASSEMBLY = 14104,
+ MD_ERROR_WIN_SXS_MANIFEST_TOO_BIG = 14105,
+ MD_ERROR_WIN_SXS_SETTING_NOT_REGISTERED = 14106,
+ MD_ERROR_WIN_SXS_TRANSACTION_CLOSURE_INCOMPLETE = 14107,
+ MD_ERROR_WIN_SMI_PRIMITIVE_INSTALLER_FAILED = 14108,
+ MD_ERROR_WIN_GENERIC_COMMAND_FAILED = 14109,
+ MD_ERROR_WIN_SXS_FILE_HASH_MISSING = 14110,
+ MD_ERROR_WIN_SXS_DUPLICATE_ACTIVATABLE_CLASS = 14111,
+ MD_ERROR_WIN_EVT_INVALID_CHANNEL_PATH = 15000,
+ MD_ERROR_WIN_EVT_INVALID_QUERY = 15001,
+ MD_ERROR_WIN_EVT_PUBLISHER_METADATA_NOT_FOUND = 15002,
+ MD_ERROR_WIN_EVT_EVENT_TEMPLATE_NOT_FOUND = 15003,
+ MD_ERROR_WIN_EVT_INVALID_PUBLISHER_NAME = 15004,
+ MD_ERROR_WIN_EVT_INVALID_EVENT_DATA = 15005,
+ MD_ERROR_WIN_EVT_CHANNEL_NOT_FOUND = 15007,
+ MD_ERROR_WIN_EVT_MALFORMED_XML_TEXT = 15008,
+ MD_ERROR_WIN_EVT_SUBSCRIPTION_TO_DIRECT_CHANNEL = 15009,
+ MD_ERROR_WIN_EVT_CONFIGURATION_ERROR = 15010,
+ MD_ERROR_WIN_EVT_QUERY_RESULT_STALE = 15011,
+ MD_ERROR_WIN_EVT_QUERY_RESULT_INVALID_POSITION = 15012,
+ MD_ERROR_WIN_EVT_NON_VALIDATING_MSXML = 15013,
+ MD_ERROR_WIN_EVT_FILTER_ALREADYSCOPED = 15014,
+ MD_ERROR_WIN_EVT_FILTER_NOTELTSET = 15015,
+ MD_ERROR_WIN_EVT_FILTER_INVARG = 15016,
+ MD_ERROR_WIN_EVT_FILTER_INVTEST = 15017,
+ MD_ERROR_WIN_EVT_FILTER_INVTYPE = 15018,
+ MD_ERROR_WIN_EVT_FILTER_PARSEERR = 15019,
+ MD_ERROR_WIN_EVT_FILTER_UNSUPPORTEDOP = 15020,
+ MD_ERROR_WIN_EVT_FILTER_UNEXPECTEDTOKEN = 15021,
+ MD_ERROR_WIN_EVT_INVALID_OPERATION_OVER_ENABLED_DIRECT_CHANNEL = 15022,
+ MD_ERROR_WIN_EVT_INVALID_CHANNEL_PROPERTY_VALUE = 15023,
+ MD_ERROR_WIN_EVT_INVALID_PUBLISHER_PROPERTY_VALUE = 15024,
+ MD_ERROR_WIN_EVT_CHANNEL_CANNOT_ACTIVATE = 15025,
+ MD_ERROR_WIN_EVT_FILTER_TOO_COMPLEX = 15026,
+ MD_ERROR_WIN_EVT_MESSAGE_NOT_FOUND = 15027,
+ MD_ERROR_WIN_EVT_MESSAGE_ID_NOT_FOUND = 15028,
+ MD_ERROR_WIN_EVT_UNRESOLVED_VALUE_INSERT = 15029,
+ MD_ERROR_WIN_EVT_UNRESOLVED_PARAMETER_INSERT = 15030,
+ MD_ERROR_WIN_EVT_MAX_INSERTS_REACHED = 15031,
+ MD_ERROR_WIN_EVT_EVENT_DEFINITION_NOT_FOUND = 15032,
+ MD_ERROR_WIN_EVT_MESSAGE_LOCALE_NOT_FOUND = 15033,
+ MD_ERROR_WIN_EVT_VERSION_TOO_OLD = 15034,
+ MD_ERROR_WIN_EVT_VERSION_TOO_NEW = 15035,
+ MD_ERROR_WIN_EVT_CANNOT_OPEN_CHANNEL_OF_QUERY = 15036,
+ MD_ERROR_WIN_EVT_PUBLISHER_DISABLED = 15037,
+ MD_ERROR_WIN_EVT_FILTER_OUT_OF_RANGE = 15038,
+ MD_ERROR_WIN_EC_SUBSCRIPTION_CANNOT_ACTIVATE = 15080,
+ MD_ERROR_WIN_EC_LOG_DISABLED = 15081,
+ MD_ERROR_WIN_EC_CIRCULAR_FORWARDING = 15082,
+ MD_ERROR_WIN_EC_CREDSTORE_FULL = 15083,
+ MD_ERROR_WIN_EC_CRED_NOT_FOUND = 15084,
+ MD_ERROR_WIN_EC_NO_ACTIVE_CHANNEL = 15085,
+ MD_ERROR_WIN_MUI_FILE_NOT_FOUND = 15100,
+ MD_ERROR_WIN_MUI_INVALID_FILE = 15101,
+ MD_ERROR_WIN_MUI_INVALID_RC_CONFIG = 15102,
+ MD_ERROR_WIN_MUI_INVALID_LOCALE_NAME = 15103,
+ MD_ERROR_WIN_MUI_INVALID_ULTIMATEFALLBACK_NAME = 15104,
+ MD_ERROR_WIN_MUI_FILE_NOT_LOADED = 15105,
+ MD_ERROR_WIN_RESOURCE_ENUM_USER_STOP = 15106,
+ MD_ERROR_WIN_MUI_INTLSETTINGS_UILANG_NOT_INSTALLED = 15107,
+ MD_ERROR_WIN_MUI_INTLSETTINGS_INVALID_LOCALE_NAME = 15108,
+ MD_ERROR_WIN_MRM_RUNTIME_NO_DEFAULT_OR_NEUTRAL_RESOURCE = 15110,
+ MD_ERROR_WIN_MRM_INVALID_PRICONFIG = 15111,
+ MD_ERROR_WIN_MRM_INVALID_FILE_TYPE = 15112,
+ MD_ERROR_WIN_MRM_UNKNOWN_QUALIFIER = 15113,
+ MD_ERROR_WIN_MRM_INVALID_QUALIFIER_VALUE = 15114,
+ MD_ERROR_WIN_MRM_NO_CANDIDATE = 15115,
+ MD_ERROR_WIN_MRM_NO_MATCH_OR_DEFAULT_CANDIDATE = 15116,
+ MD_ERROR_WIN_MRM_RESOURCE_TYPE_MISMATCH = 15117,
+ MD_ERROR_WIN_MRM_DUPLICATE_MAP_NAME = 15118,
+ MD_ERROR_WIN_MRM_DUPLICATE_ENTRY = 15119,
+ MD_ERROR_WIN_MRM_INVALID_RESOURCE_IDENTIFIER = 15120,
+ MD_ERROR_WIN_MRM_FILEPATH_TOO_LONG = 15121,
+ MD_ERROR_WIN_MRM_UNSUPPORTED_DIRECTORY_TYPE = 15122,
+ MD_ERROR_WIN_MRM_INVALID_PRI_FILE = 15126,
+ MD_ERROR_WIN_MRM_NAMED_RESOURCE_NOT_FOUND = 15127,
+ MD_ERROR_WIN_MRM_MAP_NOT_FOUND = 15135,
+ MD_ERROR_WIN_MRM_UNSUPPORTED_PROFILE_TYPE = 15136,
+ MD_ERROR_WIN_MRM_INVALID_QUALIFIER_OPERATOR = 15137,
+ MD_ERROR_WIN_MRM_INDETERMINATE_QUALIFIER_VALUE = 15138,
+ MD_ERROR_WIN_MRM_AUTOMERGE_ENABLED = 15139,
+ MD_ERROR_WIN_MRM_TOO_MANY_RESOURCES = 15140,
+ MD_ERROR_WIN_MRM_UNSUPPORTED_FILE_TYPE_FOR_MERGE = 15141,
+ MD_ERROR_WIN_MRM_UNSUPPORTED_FILE_TYPE_FOR_LOAD_UNLOAD_PRI_FILE = 15142,
+ MD_ERROR_WIN_MRM_NO_CURRENT_VIEW_ON_THREAD = 15143,
+ MD_ERROR_WIN_DIFFERENT_PROFILE_RESOURCE_MANAGER_EXIST = 15144,
+ MD_ERROR_WIN_OPERATION_NOT_ALLOWED_FROM_SYSTEM_COMPONENT = 15145,
+ MD_ERROR_WIN_MRM_DIRECT_REF_TO_NON_DEFAULT_RESOURCE = 15146,
+ MD_ERROR_WIN_MRM_GENERATION_COUNT_MISMATCH = 15147,
+ MD_ERROR_WIN_PRI_MERGE_VERSION_MISMATCH = 15148,
+ MD_ERROR_WIN_PRI_MERGE_MISSING_SCHEMA = 15149,
+ MD_ERROR_WIN_PRI_MERGE_LOAD_FILE_FAILED = 15150,
+ MD_ERROR_WIN_PRI_MERGE_ADD_FILE_FAILED = 15151,
+ MD_ERROR_WIN_PRI_MERGE_WRITE_FILE_FAILED = 15152,
+ MD_ERROR_WIN_PRI_MERGE_MULTIPLE_PACKAGE_FAMILIES_NOT_ALLOWED = 15153,
+ MD_ERROR_WIN_PRI_MERGE_MULTIPLE_MAIN_PACKAGES_NOT_ALLOWED = 15154,
+ MD_ERROR_WIN_PRI_MERGE_BUNDLE_PACKAGES_NOT_ALLOWED = 15155,
+ MD_ERROR_WIN_PRI_MERGE_MAIN_PACKAGE_REQUIRED = 15156,
+ MD_ERROR_WIN_PRI_MERGE_RESOURCE_PACKAGE_REQUIRED = 15157,
+ MD_ERROR_WIN_PRI_MERGE_INVALID_FILE_NAME = 15158,
+ MD_ERROR_WIN_MRM_PACKAGE_NOT_FOUND = 15159,
+ MD_ERROR_WIN_MRM_MISSING_DEFAULT_LANGUAGE = 15160,
+ MD_ERROR_WIN_MCA_INVALID_CAPABILITIES_STRING = 15200,
+ MD_ERROR_WIN_MCA_INVALID_VCP_VERSION = 15201,
+ MD_ERROR_WIN_MCA_MONITOR_VIOLATES_MCCS_SPECIFICATION = 15202,
+ MD_ERROR_WIN_MCA_MCCS_VERSION_MISMATCH = 15203,
+ MD_ERROR_WIN_MCA_UNSUPPORTED_MCCS_VERSION = 15204,
+ MD_ERROR_WIN_MCA_INTERNAL_ERROR = 15205,
+ MD_ERROR_WIN_MCA_INVALID_TECHNOLOGY_TYPE_RETURNED = 15206,
+ MD_ERROR_WIN_MCA_UNSUPPORTED_COLOR_TEMPERATURE = 15207,
+ MD_ERROR_WIN_AMBIGUOUS_SYSTEM_DEVICE = 15250,
+ MD_ERROR_WIN_SYSTEM_DEVICE_NOT_FOUND = 15299,
+ MD_ERROR_WIN_HASH_NOT_SUPPORTED = 15300,
+ MD_ERROR_WIN_HASH_NOT_PRESENT = 15301,
+ MD_ERROR_WIN_SECONDARY_IC_PROVIDER_NOT_REGISTERED = 15321,
+ MD_ERROR_WIN_GPIO_CLIENT_INFORMATION_INVALID = 15322,
+ MD_ERROR_WIN_GPIO_VERSION_NOT_SUPPORTED = 15323,
+ MD_ERROR_WIN_GPIO_INVALID_REGISTRATION_PACKET = 15324,
+ MD_ERROR_WIN_GPIO_OPERATION_DENIED = 15325,
+ MD_ERROR_WIN_GPIO_INCOMPATIBLE_CONNECT_MODE = 15326,
+ MD_ERROR_WIN_GPIO_INTERRUPT_ALREADY_UNMASKED = 15327,
+ MD_ERROR_WIN_CANNOT_SWITCH_RUNLEVEL = 15400,
+ MD_ERROR_WIN_INVALID_RUNLEVEL_SETTING = 15401,
+ MD_ERROR_WIN_RUNLEVEL_SWITCH_TIMEOUT = 15402,
+ MD_ERROR_WIN_RUNLEVEL_SWITCH_AGENT_TIMEOUT = 15403,
+ MD_ERROR_WIN_RUNLEVEL_SWITCH_IN_PROGRESS = 15404,
+ MD_ERROR_WIN_SERVICES_FAILED_AUTOSTART = 15405,
+ MD_ERROR_WIN_COM_TASK_STOP_PENDING = 15501,
+ MD_ERROR_WIN_INSTALL_OPEN_PACKAGE_FAILED = 15600,
+ MD_ERROR_WIN_INSTALL_PACKAGE_NOT_FOUND = 15601,
+ MD_ERROR_WIN_INSTALL_INVALID_PACKAGE = 15602,
+ MD_ERROR_WIN_INSTALL_RESOLVE_DEPENDENCY_FAILED = 15603,
+ MD_ERROR_WIN_INSTALL_OUT_OF_DISK_SPACE = 15604,
+ MD_ERROR_WIN_INSTALL_NETWORK_FAILURE = 15605,
+ MD_ERROR_WIN_INSTALL_REGISTRATION_FAILURE = 15606,
+ MD_ERROR_WIN_INSTALL_DEREGISTRATION_FAILURE = 15607,
+ MD_ERROR_WIN_INSTALL_CANCEL = 15608,
+ MD_ERROR_WIN_INSTALL_FAILED = 15609,
+ MD_ERROR_WIN_REMOVE_FAILED = 15610,
+ MD_ERROR_WIN_PACKAGE_ALREADY_EXISTS = 15611,
+ MD_ERROR_WIN_NEEDS_REMEDIATION = 15612,
+ MD_ERROR_WIN_INSTALL_PREREQUISITE_FAILED = 15613,
+ MD_ERROR_WIN_PACKAGE_REPOSITORY_CORRUPTED = 15614,
+ MD_ERROR_WIN_INSTALL_POLICY_FAILURE = 15615,
+ MD_ERROR_WIN_PACKAGE_UPDATING = 15616,
+ MD_ERROR_WIN_DEPLOYMENT_BLOCKED_BY_POLICY = 15617,
+ MD_ERROR_WIN_PACKAGES_IN_USE = 15618,
+ MD_ERROR_WIN_RECOVERY_FILE_CORRUPT = 15619,
+ MD_ERROR_WIN_INVALID_STAGED_SIGNATURE = 15620,
+ MD_ERROR_WIN_DELETING_EXISTING_APPLICATIONDATA_STORE_FAILED = 15621,
+ MD_ERROR_WIN_INSTALL_PACKAGE_DOWNGRADE = 15622,
+ MD_ERROR_WIN_SYSTEM_NEEDS_REMEDIATION = 15623,
+ MD_ERROR_WIN_APPX_INTEGRITY_FAILURE_CLR_NGEN = 15624,
+ MD_ERROR_WIN_RESILIENCY_FILE_CORRUPT = 15625,
+ MD_ERROR_WIN_INSTALL_FIREWALL_SERVICE_NOT_RUNNING = 15626,
+ MD_ERROR_WIN_PACKAGE_MOVE_FAILED = 15627,
+ MD_ERROR_WIN_INSTALL_VOLUME_NOT_EMPTY = 15628,
+ MD_ERROR_WIN_INSTALL_VOLUME_OFFLINE = 15629,
+ MD_ERROR_WIN_INSTALL_VOLUME_CORRUPT = 15630,
+ MD_ERROR_WIN_NEEDS_REGISTRATION = 15631,
+ MD_ERROR_WIN_INSTALL_WRONG_PROCESSOR_ARCHITECTURE = 15632,
+ MD_ERROR_WIN_DEV_SIDELOAD_LIMIT_EXCEEDED = 15633,
+ MD_ERROR_WIN_INSTALL_OPTIONAL_PACKAGE_REQUIRES_MAIN_PACKAGE = 15634,
+ MD_ERROR_WIN_PACKAGE_NOT_SUPPORTED_ON_FILESYSTEM = 15635,
+ MD_ERROR_WIN_PACKAGE_MOVE_BLOCKED_BY_STREAMING = 15636,
+ MD_ERROR_WIN_INSTALL_OPTIONAL_PACKAGE_APPLICATIONID_NOT_UNIQUE = 15637,
+ MD_ERROR_WIN_PACKAGE_STAGING_ONHOLD = 15638,
+ MD_ERROR_WIN_INSTALL_INVALID_RELATED_SET_UPDATE = 15639,
+ MD_ERROR_WIN_INSTALL_OPTIONAL_PACKAGE_REQUIRES_MAIN_PACKAGE_FULLTRUST_CAPABILITY = 15640,
+ MD_ERROR_WIN_DEPLOYMENT_BLOCKED_BY_USER_LOG_OFF = 15641,
+ MD_ERROR_WIN_PROVISION_OPTIONAL_PACKAGE_REQUIRES_MAIN_PACKAGE_PROVISIONED = 15642,
+ MD_ERROR_WIN_PACKAGES_REPUTATION_CHECK_FAILED = 15643,
+ MD_ERROR_WIN_PACKAGES_REPUTATION_CHECK_TIMEDOUT = 15644,
+ MD_ERROR_WIN_DEPLOYMENT_OPTION_NOT_SUPPORTED = 15645,
+ MD_ERROR_WIN_APPINSTALLER_ACTIVATION_BLOCKED = 15646,
+ MD_ERROR_WIN_REGISTRATION_FROM_REMOTE_DRIVE_NOT_SUPPORTED = 15647,
+ MD_ERROR_WIN_APPX_RAW_DATA_WRITE_FAILED = 15648,
+ MD_ERROR_WIN_DEPLOYMENT_BLOCKED_BY_VOLUME_POLICY_PACKAGE = 15649,
+ MD_ERROR_WIN_DEPLOYMENT_BLOCKED_BY_VOLUME_POLICY_MACHINE = 15650,
+ MD_ERROR_WIN_DEPLOYMENT_BLOCKED_BY_PROFILE_POLICY = 15651,
+ MD_ERROR_WIN_DEPLOYMENT_FAILED_CONFLICTING_MUTABLE_PACKAGE_DIRECTORY = 15652,
+ MD_ERROR_WIN_SINGLETON_RESOURCE_INSTALLED_IN_ACTIVE_USER = 15653,
+ MD_ERROR_WIN_DIFFERENT_VERSION_OF_PACKAGED_SERVICE_INSTALLED = 15654,
+ MD_ERROR_WIN_SERVICE_EXISTS_AS_NON_PACKAGED_SERVICE = 15655,
+ MD_ERROR_WIN_PACKAGED_SERVICE_REQUIRES_ADMIN_PRIVILEGES = 15656,
+ MD_ERROR_WIN_REDIRECTION_TO_DEFAULT_ACCOUNT_NOT_ALLOWED = 15657,
+ MD_ERROR_WIN_PACKAGE_LACKS_CAPABILITY_TO_DEPLOY_ON_HOST = 15658,
+ MD_ERROR_WIN_UNSIGNED_PACKAGE_INVALID_CONTENT = 15659,
+ MD_ERROR_WIN_UNSIGNED_PACKAGE_INVALID_PUBLISHER_NAMESPACE = 15660,
+ MD_ERROR_WIN_SIGNED_PACKAGE_INVALID_PUBLISHER_NAMESPACE = 15661,
+ MD_ERROR_WIN_PACKAGE_EXTERNAL_LOCATION_NOT_ALLOWED = 15662,
+ MD_ERROR_WIN_INSTALL_FULLTRUST_HOSTRUNTIME_REQUIRES_MAIN_PACKAGE_FULLTRUST_CAPABILITY = 15663,
+ MD_ERROR_WIN_STATE_LOAD_STORE_FAILED = 15800,
+ MD_ERROR_WIN_STATE_GET_VERSION_FAILED = 15801,
+ MD_ERROR_WIN_STATE_SET_VERSION_FAILED = 15802,
+ MD_ERROR_WIN_STATE_STRUCTURED_RESET_FAILED = 15803,
+ MD_ERROR_WIN_STATE_OPEN_CONTAINER_FAILED = 15804,
+ MD_ERROR_WIN_STATE_CREATE_CONTAINER_FAILED = 15805,
+ MD_ERROR_WIN_STATE_DELETE_CONTAINER_FAILED = 15806,
+ MD_ERROR_WIN_STATE_READ_SETTING_FAILED = 15807,
+ MD_ERROR_WIN_STATE_WRITE_SETTING_FAILED = 15808,
+ MD_ERROR_WIN_STATE_DELETE_SETTING_FAILED = 15809,
+ MD_ERROR_WIN_STATE_QUERY_SETTING_FAILED = 15810,
+ MD_ERROR_WIN_STATE_READ_COMPOSITE_SETTING_FAILED = 15811,
+ MD_ERROR_WIN_STATE_WRITE_COMPOSITE_SETTING_FAILED = 15812,
+ MD_ERROR_WIN_STATE_ENUMERATE_CONTAINER_FAILED = 15813,
+ MD_ERROR_WIN_STATE_ENUMERATE_SETTINGS_FAILED = 15814,
+ MD_ERROR_WIN_STATE_COMPOSITE_SETTING_VALUE_SIZE_LIMIT_EXCEEDED = 15815,
+ MD_ERROR_WIN_STATE_SETTING_VALUE_SIZE_LIMIT_EXCEEDED = 15816,
+ MD_ERROR_WIN_STATE_SETTING_NAME_SIZE_LIMIT_EXCEEDED = 15817,
+ MD_ERROR_WIN_STATE_CONTAINER_NAME_SIZE_LIMIT_EXCEEDED = 15818,
+ MD_ERROR_WIN_API_UNAVAILABLE = 15841,
+} MDErrorWin;
+
+#endif /* GOOGLE_BREAKPAD_COMMON_MINIDUMP_EXCEPTION_WIN32_H__ */
diff --git a/toolkit/crashreporter/google-breakpad/src/google_breakpad/common/minidump_format.h b/toolkit/crashreporter/google-breakpad/src/google_breakpad/common/minidump_format.h
new file mode 100644
index 0000000000..4155a202dd
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/google_breakpad/common/minidump_format.h
@@ -0,0 +1,1178 @@
+/* Copyright (c) 2006, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
+
+/* minidump_format.h: A cross-platform reimplementation of minidump-related
+ * portions of DbgHelp.h from the Windows Platform SDK.
+ *
+ * (This is C99 source, please don't corrupt it with C++.)
+ *
+ * Structures that are defined by Microsoft to contain a zero-length array
+ * are instead defined here to contain an array with one element, as
+ * zero-length arrays are forbidden by standard C and C++. In these cases,
+ * *_minsize constants are provided to be used in place of sizeof. For a
+ * cleaner interface to these sizes when using C++, see minidump_size.h.
+ *
+ * These structures are also sufficient to populate minidump files.
+ *
+ * These definitions may be extended to support handling minidump files
+ * for other CPUs and other operating systems.
+ *
+ * Because precise data type sizes are crucial for this implementation to
+ * function properly and portably in terms of interoperability with minidumps
+ * produced by DbgHelp on Windows, a set of primitive types with known sizes
+ * are used as the basis of each structure defined by this file. DbgHelp
+ * on Windows is assumed to be the reference implementation; this file
+ * seeks to provide a cross-platform compatible implementation. To avoid
+ * collisions with the types and values defined and used by DbgHelp in the
+ * event that this implementation is used on Windows, each type and value
+ * defined here is given a new name, beginning with "MD". Names of the
+ * equivalent types and values in the Windows Platform SDK are given in
+ * comments.
+ *
+ * Author: Mark Mentovai */
+
+
+#ifndef GOOGLE_BREAKPAD_COMMON_MINIDUMP_FORMAT_H__
+#define GOOGLE_BREAKPAD_COMMON_MINIDUMP_FORMAT_H__
+
+#include <stddef.h>
+
+#include "google_breakpad/common/breakpad_types.h"
+
+
+#if defined(_MSC_VER)
+/* Disable "zero-sized array in struct/union" warnings when compiling in
+ * MSVC. DbgHelp.h does this too. */
+#pragma warning(push)
+#pragma warning(disable:4200)
+#endif /* _MSC_VER */
+
+
+/*
+ * guiddef.h
+ */
+
+typedef struct {
+ uint32_t data1;
+ uint16_t data2;
+ uint16_t data3;
+ uint8_t data4[8];
+} MDGUID; /* GUID */
+
+
+/*
+ * WinNT.h
+ */
+
+/* Non-x86 CPU identifiers found in the high 24 bits of
+ * (MDRawContext*).context_flags. These aren't used by Breakpad, but are
+ * defined here for reference, to avoid assigning values that conflict
+ * (although some values already conflict). */
+#define MD_CONTEXT_IA64 0x00080000 /* CONTEXT_IA64 */
+/* Additional values from winnt.h in the Windows CE 5.0 SDK: */
+#define MD_CONTEXT_SHX 0x000000c0 /* CONTEXT_SH4 (Super-H, includes SH3) */
+#define MD_CONTEXT_ALPHA 0x00020000 /* CONTEXT_ALPHA */
+
+/* As of Windows 7 SP1, the number of flag bits has increased to
+ * include 0x40 (CONTEXT_XSTATE):
+ * http://msdn.microsoft.com/en-us/library/hh134238%28v=vs.85%29.aspx */
+#define MD_CONTEXT_CPU_MASK 0xffffff00
+
+
+/* This is a base type for MDRawContextX86 and MDRawContextPPC. This
+ * structure should never be allocated directly. The actual structure type
+ * can be determined by examining the context_flags field. */
+typedef struct {
+ uint32_t context_flags;
+} MDRawContextBase;
+
+#include "minidump_cpu_amd64.h"
+#include "minidump_cpu_arm.h"
+#include "minidump_cpu_arm64.h"
+#include "minidump_cpu_mips.h"
+#include "minidump_cpu_ppc.h"
+#include "minidump_cpu_ppc64.h"
+#include "minidump_cpu_sparc.h"
+#include "minidump_cpu_x86.h"
+
+/*
+ * WinVer.h
+ */
+
+
+typedef struct {
+ uint32_t signature;
+ uint32_t struct_version;
+ uint32_t file_version_hi;
+ uint32_t file_version_lo;
+ uint32_t product_version_hi;
+ uint32_t product_version_lo;
+ uint32_t file_flags_mask; /* Identifies valid bits in fileFlags */
+ uint32_t file_flags;
+ uint32_t file_os;
+ uint32_t file_type;
+ uint32_t file_subtype;
+ uint32_t file_date_hi;
+ uint32_t file_date_lo;
+} MDVSFixedFileInfo; /* VS_FIXEDFILEINFO */
+
+/* For (MDVSFixedFileInfo).signature */
+#define MD_VSFIXEDFILEINFO_SIGNATURE 0xfeef04bd
+ /* VS_FFI_SIGNATURE */
+
+/* For (MDVSFixedFileInfo).version */
+#define MD_VSFIXEDFILEINFO_VERSION 0x00010000
+ /* VS_FFI_STRUCVERSION */
+
+/* For (MDVSFixedFileInfo).file_flags_mask and
+ * (MDVSFixedFileInfo).file_flags */
+#define MD_VSFIXEDFILEINFO_FILE_FLAGS_DEBUG 0x00000001
+ /* VS_FF_DEBUG */
+#define MD_VSFIXEDFILEINFO_FILE_FLAGS_PRERELEASE 0x00000002
+ /* VS_FF_PRERELEASE */
+#define MD_VSFIXEDFILEINFO_FILE_FLAGS_PATCHED 0x00000004
+ /* VS_FF_PATCHED */
+#define MD_VSFIXEDFILEINFO_FILE_FLAGS_PRIVATEBUILD 0x00000008
+ /* VS_FF_PRIVATEBUILD */
+#define MD_VSFIXEDFILEINFO_FILE_FLAGS_INFOINFERRED 0x00000010
+ /* VS_FF_INFOINFERRED */
+#define MD_VSFIXEDFILEINFO_FILE_FLAGS_SPECIALBUILD 0x00000020
+ /* VS_FF_SPECIALBUILD */
+
+/* For (MDVSFixedFileInfo).file_os: high 16 bits */
+#define MD_VSFIXEDFILEINFO_FILE_OS_UNKNOWN 0 /* VOS_UNKNOWN */
+#define MD_VSFIXEDFILEINFO_FILE_OS_DOS (1 << 16) /* VOS_DOS */
+#define MD_VSFIXEDFILEINFO_FILE_OS_OS216 (2 << 16) /* VOS_OS216 */
+#define MD_VSFIXEDFILEINFO_FILE_OS_OS232 (3 << 16) /* VOS_OS232 */
+#define MD_VSFIXEDFILEINFO_FILE_OS_NT (4 << 16) /* VOS_NT */
+#define MD_VSFIXEDFILEINFO_FILE_OS_WINCE (5 << 16) /* VOS_WINCE */
+/* Low 16 bits */
+#define MD_VSFIXEDFILEINFO_FILE_OS__BASE 0 /* VOS__BASE */
+#define MD_VSFIXEDFILEINFO_FILE_OS__WINDOWS16 1 /* VOS__WINDOWS16 */
+#define MD_VSFIXEDFILEINFO_FILE_OS__PM16 2 /* VOS__PM16 */
+#define MD_VSFIXEDFILEINFO_FILE_OS__PM32 3 /* VOS__PM32 */
+#define MD_VSFIXEDFILEINFO_FILE_OS__WINDOWS32 4 /* VOS__WINDOWS32 */
+
+/* For (MDVSFixedFileInfo).file_type */
+#define MD_VSFIXEDFILEINFO_FILE_TYPE_UNKNOWN 0 /* VFT_UNKNOWN */
+#define MD_VSFIXEDFILEINFO_FILE_TYPE_APP 1 /* VFT_APP */
+#define MD_VSFIXEDFILEINFO_FILE_TYPE_DLL 2 /* VFT_DLL */
+#define MD_VSFIXEDFILEINFO_FILE_TYPE_DRV 3 /* VFT_DLL */
+#define MD_VSFIXEDFILEINFO_FILE_TYPE_FONT 4 /* VFT_FONT */
+#define MD_VSFIXEDFILEINFO_FILE_TYPE_VXD 5 /* VFT_VXD */
+#define MD_VSFIXEDFILEINFO_FILE_TYPE_STATIC_LIB 7 /* VFT_STATIC_LIB */
+
+/* For (MDVSFixedFileInfo).file_subtype */
+#define MD_VSFIXEDFILEINFO_FILE_SUBTYPE_UNKNOWN 0
+ /* VFT2_UNKNOWN */
+/* with file_type = MD_VSFIXEDFILEINFO_FILETYPE_DRV */
+#define MD_VSFIXEDFILEINFO_FILE_SUBTYPE_DRV_PRINTER 1
+ /* VFT2_DRV_PRINTER */
+#define MD_VSFIXEDFILEINFO_FILE_SUBTYPE_DRV_KEYBOARD 2
+ /* VFT2_DRV_KEYBOARD */
+#define MD_VSFIXEDFILEINFO_FILE_SUBTYPE_DRV_LANGUAGE 3
+ /* VFT2_DRV_LANGUAGE */
+#define MD_VSFIXEDFILEINFO_FILE_SUBTYPE_DRV_DISPLAY 4
+ /* VFT2_DRV_DISPLAY */
+#define MD_VSFIXEDFILEINFO_FILE_SUBTYPE_DRV_MOUSE 5
+ /* VFT2_DRV_MOUSE */
+#define MD_VSFIXEDFILEINFO_FILE_SUBTYPE_DRV_NETWORK 6
+ /* VFT2_DRV_NETWORK */
+#define MD_VSFIXEDFILEINFO_FILE_SUBTYPE_DRV_SYSTEM 7
+ /* VFT2_DRV_SYSTEM */
+#define MD_VSFIXEDFILEINFO_FILE_SUBTYPE_DRV_INSTALLABLE 8
+ /* VFT2_DRV_INSTALLABLE */
+#define MD_VSFIXEDFILEINFO_FILE_SUBTYPE_DRV_SOUND 9
+ /* VFT2_DRV_SOUND */
+#define MD_VSFIXEDFILEINFO_FILE_SUBTYPE_DRV_COMM 10
+ /* VFT2_DRV_COMM */
+#define MD_VSFIXEDFILEINFO_FILE_SUBTYPE_DRV_INPUTMETHOD 11
+ /* VFT2_DRV_INPUTMETHOD */
+#define MD_VSFIXEDFILEINFO_FILE_SUBTYPE_DRV_VERSIONED_PRINTER 12
+ /* VFT2_DRV_VERSIONED_PRINTER */
+/* with file_type = MD_VSFIXEDFILEINFO_FILETYPE_FONT */
+#define MD_VSFIXEDFILEINFO_FILE_SUBTYPE_FONT_RASTER 1
+ /* VFT2_FONT_RASTER */
+#define MD_VSFIXEDFILEINFO_FILE_SUBTYPE_FONT_VECTOR 2
+ /* VFT2_FONT_VECTOR */
+#define MD_VSFIXEDFILEINFO_FILE_SUBTYPE_FONT_TRUETYPE 3
+ /* VFT2_FONT_TRUETYPE */
+
+
+/*
+ * DbgHelp.h
+ */
+
+
+/* An MDRVA is an offset into the minidump file. The beginning of the
+ * MDRawHeader is at offset 0. */
+typedef uint32_t MDRVA; /* RVA */
+typedef uint64_t MDRVA64; /* RVA64 */
+
+typedef struct {
+ uint32_t data_size;
+ MDRVA rva;
+} MDLocationDescriptor; /* MINIDUMP_LOCATION_DESCRIPTOR */
+
+
+typedef struct {
+ /* The base address of the memory range on the host that produced the
+ * minidump. */
+ uint64_t start_of_memory_range;
+
+ MDLocationDescriptor memory;
+} MDMemoryDescriptor; /* MINIDUMP_MEMORY_DESCRIPTOR */
+
+
+typedef struct {
+ uint32_t signature;
+ uint32_t version;
+ uint32_t stream_count;
+ MDRVA stream_directory_rva; /* A |stream_count|-sized array of
+ * MDRawDirectory structures. */
+ uint32_t checksum; /* Can be 0. In fact, that's all that's
+ * been found in minidump files. */
+ uint32_t time_date_stamp; /* time_t */
+ uint64_t flags;
+} MDRawHeader; /* MINIDUMP_HEADER */
+
+/* For (MDRawHeader).signature and (MDRawHeader).version. Note that only the
+ * low 16 bits of (MDRawHeader).version are MD_HEADER_VERSION. Per the
+ * documentation, the high 16 bits are implementation-specific. */
+#define MD_HEADER_SIGNATURE 0x504d444d /* 'PMDM' */
+ /* MINIDUMP_SIGNATURE */
+#define MD_HEADER_VERSION 0x0000a793 /* 42899 */
+ /* MINIDUMP_VERSION */
+
+/* For (MDRawHeader).flags: */
+typedef enum {
+ /* MD_NORMAL is the standard type of minidump. It includes full
+ * streams for the thread list, module list, exception, system info,
+ * and miscellaneous info. A memory list stream is also present,
+ * pointing to the same stack memory contained in the thread list,
+ * as well as a 256-byte region around the instruction address that
+ * was executing when the exception occurred. Stack memory is from
+ * 4 bytes below a thread's stack pointer up to the top of the
+ * memory region encompassing the stack. */
+ MD_NORMAL = 0x00000000,
+ MD_WITH_DATA_SEGS = 0x00000001,
+ MD_WITH_FULL_MEMORY = 0x00000002,
+ MD_WITH_HANDLE_DATA = 0x00000004,
+ MD_FILTER_MEMORY = 0x00000008,
+ MD_SCAN_MEMORY = 0x00000010,
+ MD_WITH_UNLOADED_MODULES = 0x00000020,
+ MD_WITH_INDIRECTLY_REFERENCED_MEMORY = 0x00000040,
+ MD_FILTER_MODULE_PATHS = 0x00000080,
+ MD_WITH_PROCESS_THREAD_DATA = 0x00000100,
+ MD_WITH_PRIVATE_READ_WRITE_MEMORY = 0x00000200,
+ MD_WITHOUT_OPTIONAL_DATA = 0x00000400,
+ MD_WITH_FULL_MEMORY_INFO = 0x00000800,
+ MD_WITH_THREAD_INFO = 0x00001000,
+ MD_WITH_CODE_SEGS = 0x00002000,
+ MD_WITHOUT_AUXILLIARY_SEGS = 0x00004000,
+ MD_WITH_FULL_AUXILLIARY_STATE = 0x00008000,
+ MD_WITH_PRIVATE_WRITE_COPY_MEMORY = 0x00010000,
+ MD_IGNORE_INACCESSIBLE_MEMORY = 0x00020000,
+ MD_WITH_TOKEN_INFORMATION = 0x00040000
+} MDType; /* MINIDUMP_TYPE */
+
+
+typedef struct {
+ uint32_t stream_type;
+ MDLocationDescriptor location;
+} MDRawDirectory; /* MINIDUMP_DIRECTORY */
+
+/* For (MDRawDirectory).stream_type */
+typedef enum {
+ MD_UNUSED_STREAM = 0,
+ MD_RESERVED_STREAM_0 = 1,
+ MD_RESERVED_STREAM_1 = 2,
+ MD_THREAD_LIST_STREAM = 3, /* MDRawThreadList */
+ MD_MODULE_LIST_STREAM = 4, /* MDRawModuleList */
+ MD_MEMORY_LIST_STREAM = 5, /* MDRawMemoryList */
+ MD_EXCEPTION_STREAM = 6, /* MDRawExceptionStream */
+ MD_SYSTEM_INFO_STREAM = 7, /* MDRawSystemInfo */
+ MD_THREAD_EX_LIST_STREAM = 8,
+ MD_MEMORY_64_LIST_STREAM = 9,
+ MD_COMMENT_STREAM_A = 10,
+ MD_COMMENT_STREAM_W = 11,
+ MD_HANDLE_DATA_STREAM = 12,
+ MD_FUNCTION_TABLE_STREAM = 13,
+ MD_UNLOADED_MODULE_LIST_STREAM = 14,
+ MD_MISC_INFO_STREAM = 15, /* MDRawMiscInfo */
+ MD_MEMORY_INFO_LIST_STREAM = 16, /* MDRawMemoryInfoList */
+ MD_THREAD_INFO_LIST_STREAM = 17,
+ MD_HANDLE_OPERATION_LIST_STREAM = 18,
+ MD_TOKEN_STREAM = 19,
+ MD_JAVASCRIPT_DATA_STREAM = 20,
+ MD_SYSTEM_MEMORY_INFO_STREAM = 21,
+ MD_PROCESS_VM_COUNTERS_STREAM = 22,
+ MD_IPT_TRACE_STREAM = 23,
+ MD_THREAD_NAMES_STREAM = 24,
+ MD_LAST_RESERVED_STREAM = 0x0000ffff,
+
+ /* Breakpad extension types. 0x4767 = "Gg" */
+ MD_BREAKPAD_INFO_STREAM = 0x47670001, /* MDRawBreakpadInfo */
+ MD_ASSERTION_INFO_STREAM = 0x47670002, /* MDRawAssertionInfo */
+ /* These are additional minidump stream values which are specific to
+ * the linux breakpad implementation. */
+ MD_LINUX_CPU_INFO = 0x47670003, /* /proc/cpuinfo */
+ MD_LINUX_PROC_STATUS = 0x47670004, /* /proc/$x/status */
+ MD_LINUX_LSB_RELEASE = 0x47670005, /* /etc/lsb-release */
+ MD_LINUX_CMD_LINE = 0x47670006, /* /proc/$x/cmdline */
+ MD_LINUX_ENVIRON = 0x47670007, /* /proc/$x/environ */
+ MD_LINUX_AUXV = 0x47670008, /* /proc/$x/auxv */
+ MD_LINUX_MAPS = 0x47670009, /* /proc/$x/maps */
+ MD_LINUX_DSO_DEBUG = 0x4767000A, /* MDRawDebug{32,64} */
+
+ /* Crashpad extension types. 0x4350 = "CP"
+ * See Crashpad's minidump/minidump_extensions.h. */
+ MD_CRASHPAD_INFO_STREAM = 0x43500001, /* MDRawCrashpadInfo */
+
+ /* Data from the __DATA,__crash_info section of every module which contains
+ * one that has useful data. Only available on macOS. 0x4D7A = "Mz". */
+ MOZ_MACOS_CRASH_INFO_STREAM = 0x4d7a0001,
+
+ /* The kernel boot args on the machine where the crashed process is
+ * running. Only available on macOS. 0x4D7A = "Mz". */
+ MOZ_MACOS_BOOTARGS_STREAM = 0x4d7a0002,
+} MDStreamType; /* MINIDUMP_STREAM_TYPE */
+
+
+typedef struct {
+ uint32_t length; /* Length of buffer in bytes (not characters),
+ * excluding 0-terminator */
+ uint16_t buffer[1]; /* UTF-16-encoded, 0-terminated */
+} MDString; /* MINIDUMP_STRING */
+
+static const size_t MDString_minsize = offsetof(MDString, buffer[0]);
+
+
+typedef struct {
+ uint32_t thread_id;
+ uint32_t suspend_count;
+ uint32_t priority_class;
+ uint32_t priority;
+ uint64_t teb; /* Thread environment block */
+ MDMemoryDescriptor stack;
+ MDLocationDescriptor thread_context; /* MDRawContext[CPU] */
+} MDRawThread; /* MINIDUMP_THREAD */
+
+
+typedef struct {
+ uint32_t number_of_threads;
+ MDRawThread threads[1];
+} MDRawThreadList; /* MINIDUMP_THREAD_LIST */
+
+static const size_t MDRawThreadList_minsize = offsetof(MDRawThreadList,
+ threads[0]);
+
+
+typedef struct {
+ uint64_t base_of_image;
+ uint32_t size_of_image;
+ uint32_t checksum; /* 0 if unknown */
+ uint32_t time_date_stamp; /* time_t */
+ MDRVA module_name_rva; /* MDString, pathname or filename */
+ MDVSFixedFileInfo version_info;
+
+ /* The next field stores a CodeView record and is populated when a module's
+ * debug information resides in a PDB file. It identifies the PDB file. */
+ MDLocationDescriptor cv_record;
+
+ /* The next field is populated when a module's debug information resides
+ * in a DBG file. It identifies the DBG file. This field is effectively
+ * obsolete with modules built by recent toolchains. */
+ MDLocationDescriptor misc_record;
+
+ /* Alignment problem: reserved0 and reserved1 are defined by the platform
+ * SDK as 64-bit quantities. However, that results in a structure whose
+ * alignment is unpredictable on different CPUs and ABIs. If the ABI
+ * specifies full alignment of 64-bit quantities in structures (as ppc
+ * does), there will be padding between miscRecord and reserved0. If
+ * 64-bit quantities can be aligned on 32-bit boundaries (as on x86),
+ * this padding will not exist. (Note that the structure up to this point
+ * contains 1 64-bit member followed by 21 32-bit members.)
+ * As a workaround, reserved0 and reserved1 are instead defined here as
+ * four 32-bit quantities. This should be harmless, as there are
+ * currently no known uses for these fields. */
+ uint32_t reserved0[2];
+ uint32_t reserved1[2];
+} MDRawModule; /* MINIDUMP_MODULE */
+
+/* The inclusion of a 64-bit type in MINIDUMP_MODULE forces the struct to
+ * be tail-padded out to a multiple of 64 bits under some ABIs (such as PPC).
+ * This doesn't occur on systems that don't tail-pad in this manner. Define
+ * this macro to be the usable size of the MDRawModule struct, and use it in
+ * place of sizeof(MDRawModule). */
+#define MD_MODULE_SIZE 108
+
+
+/* (MDRawModule).cv_record can reference MDCVInfoPDB20 or MDCVInfoPDB70.
+ * Ref.: http://www.debuginfo.com/articles/debuginfomatch.html
+ * MDCVInfoPDB70 is the expected structure type with recent toolchains. */
+
+typedef struct {
+ uint32_t signature;
+ uint32_t offset; /* Offset to debug data (expect 0 in minidump) */
+} MDCVHeader;
+
+typedef struct {
+ MDCVHeader cv_header;
+ uint32_t signature; /* time_t debug information created */
+ uint32_t age; /* revision of PDB file */
+ uint8_t pdb_file_name[1]; /* Pathname or filename of PDB file */
+} MDCVInfoPDB20;
+
+static const size_t MDCVInfoPDB20_minsize = offsetof(MDCVInfoPDB20,
+ pdb_file_name[0]);
+
+#define MD_CVINFOPDB20_SIGNATURE 0x3031424e /* cvHeader.signature = '01BN' */
+
+typedef struct {
+ uint32_t cv_signature;
+ MDGUID signature; /* GUID, identifies PDB file */
+ uint32_t age; /* Identifies incremental changes to PDB file */
+ uint8_t pdb_file_name[1]; /* Pathname or filename of PDB file,
+ * 0-terminated 8-bit character data (UTF-8?) */
+} MDCVInfoPDB70;
+
+static const size_t MDCVInfoPDB70_minsize = offsetof(MDCVInfoPDB70,
+ pdb_file_name[0]);
+
+#define MD_CVINFOPDB70_SIGNATURE 0x53445352 /* cvSignature = 'SDSR' */
+
+/*
+ * Modern ELF toolchains insert a "build id" into the ELF headers that
+ * usually contains a hash of some ELF headers + sections to uniquely
+ * identify a binary.
+ *
+ * https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/6/html/Developer_Guide/compiling-build-id.html
+ * https://sourceware.org/binutils/docs-2.26/ld/Options.html#index-g_t_002d_002dbuild_002did-292
+ */
+typedef struct {
+ uint32_t cv_signature;
+ uint8_t build_id[1]; /* Bytes of build id from GNU_BUILD_ID ELF note.
+ * This is variable-length, but usually 20 bytes
+ * as the binutils ld default is a SHA-1 hash. */
+} MDCVInfoELF;
+
+static const size_t MDCVInfoELF_minsize = offsetof(MDCVInfoELF,
+ build_id[0]);
+
+#define MD_CVINFOELF_SIGNATURE 0x4270454c /* cvSignature = 'BpEL' */
+
+/* In addition to the two CodeView record formats above, used for linking
+ * to external pdb files, it is possible for debugging data to be carried
+ * directly in the CodeView record itself. These signature values will
+ * be found in the first 4 bytes of the CodeView record. Additional values
+ * not commonly experienced in the wild are given by "Microsoft Symbol and
+ * Type Information", http://www.x86.org/ftp/manuals/tools/sym.pdf, section
+ * 7.2. An in-depth description of the CodeView 4.1 format is given by
+ * "Undocumented Windows 2000 Secrets", Windows 2000 Debugging Support/
+ * Microsoft Symbol File Internals/CodeView Subsections,
+ * http://www.rawol.com/features/undocumented/sbs-w2k-1-windows-2000-debugging-support.pdf
+ */
+#define MD_CVINFOCV41_SIGNATURE 0x3930424e /* '90BN', CodeView 4.10. */
+#define MD_CVINFOCV50_SIGNATURE 0x3131424e /* '11BN', CodeView 5.0,
+ * MS C7-format (/Z7). */
+
+#define MD_CVINFOUNKNOWN_SIGNATURE 0xffffffff /* An unlikely value. */
+
+/* (MDRawModule).miscRecord can reference MDImageDebugMisc. The Windows
+ * structure is actually defined in WinNT.h. This structure is effectively
+ * obsolete with modules built by recent toolchains. */
+
+typedef struct {
+ uint32_t data_type; /* IMAGE_DEBUG_TYPE_*, not defined here because
+ * this debug record type is mostly obsolete. */
+ uint32_t length; /* Length of entire MDImageDebugMisc structure */
+ uint8_t unicode; /* True if data is multibyte */
+ uint8_t reserved[3];
+ uint8_t data[1];
+} MDImageDebugMisc; /* IMAGE_DEBUG_MISC */
+
+static const size_t MDImageDebugMisc_minsize = offsetof(MDImageDebugMisc,
+ data[0]);
+
+
+typedef struct {
+ uint32_t number_of_modules;
+ MDRawModule modules[1];
+} MDRawModuleList; /* MINIDUMP_MODULE_LIST */
+
+static const size_t MDRawModuleList_minsize = offsetof(MDRawModuleList,
+ modules[0]);
+
+
+typedef struct {
+ uint32_t number_of_memory_ranges;
+ MDMemoryDescriptor memory_ranges[1];
+} MDRawMemoryList; /* MINIDUMP_MEMORY_LIST */
+
+static const size_t MDRawMemoryList_minsize = offsetof(MDRawMemoryList,
+ memory_ranges[0]);
+
+
+#define MD_EXCEPTION_MAXIMUM_PARAMETERS 15
+
+typedef struct {
+ uint32_t exception_code; /* Windows: MDExceptionCodeWin,
+ * Mac OS X: MDExceptionMac,
+ * Linux: MDExceptionCodeLinux. */
+ uint32_t exception_flags; /* Windows: 1 if noncontinuable,
+ Mac OS X: MDExceptionCodeMac. */
+ uint64_t exception_record; /* Address (in the minidump-producing host's
+ * memory) of another MDException, for
+ * nested exceptions. */
+ uint64_t exception_address; /* The address that caused the exception.
+ * Mac OS X: exception subcode (which is
+ * typically the address). */
+ uint32_t number_parameters; /* Number of valid elements in
+ * exception_information. */
+ uint32_t __align;
+ uint64_t exception_information[MD_EXCEPTION_MAXIMUM_PARAMETERS];
+} MDException; /* MINIDUMP_EXCEPTION */
+
+#include "minidump_exception_fuchsia.h"
+#include "minidump_exception_linux.h"
+#include "minidump_exception_mac.h"
+#include "minidump_exception_ps3.h"
+#include "minidump_exception_solaris.h"
+#include "minidump_exception_win32.h"
+
+typedef struct {
+ uint32_t thread_id; /* Thread in which the exception
+ * occurred. Corresponds to
+ * (MDRawThread).thread_id. */
+ uint32_t __align;
+ MDException exception_record;
+ MDLocationDescriptor thread_context; /* MDRawContext[CPU] */
+} MDRawExceptionStream; /* MINIDUMP_EXCEPTION_STREAM */
+
+
+typedef union {
+ struct {
+ uint32_t vendor_id[3]; /* cpuid 0: ebx, edx, ecx */
+ uint32_t version_information; /* cpuid 1: eax */
+ uint32_t feature_information; /* cpuid 1: edx */
+ uint32_t amd_extended_cpu_features; /* cpuid 0x80000001, ebx */
+ } x86_cpu_info;
+ struct {
+ uint32_t cpuid;
+ uint32_t elf_hwcaps; /* linux specific, 0 otherwise */
+ } arm_cpu_info;
+ struct {
+ uint64_t processor_features[2];
+ } other_cpu_info;
+} MDCPUInformation; /* CPU_INFORMATION */
+
+/* For (MDCPUInformation).arm_cpu_info.elf_hwcaps.
+ * This matches the Linux kernel definitions from <asm/hwcaps.h> */
+typedef enum {
+ MD_CPU_ARM_ELF_HWCAP_SWP = (1 << 0),
+ MD_CPU_ARM_ELF_HWCAP_HALF = (1 << 1),
+ MD_CPU_ARM_ELF_HWCAP_THUMB = (1 << 2),
+ MD_CPU_ARM_ELF_HWCAP_26BIT = (1 << 3),
+ MD_CPU_ARM_ELF_HWCAP_FAST_MULT = (1 << 4),
+ MD_CPU_ARM_ELF_HWCAP_FPA = (1 << 5),
+ MD_CPU_ARM_ELF_HWCAP_VFP = (1 << 6),
+ MD_CPU_ARM_ELF_HWCAP_EDSP = (1 << 7),
+ MD_CPU_ARM_ELF_HWCAP_JAVA = (1 << 8),
+ MD_CPU_ARM_ELF_HWCAP_IWMMXT = (1 << 9),
+ MD_CPU_ARM_ELF_HWCAP_CRUNCH = (1 << 10),
+ MD_CPU_ARM_ELF_HWCAP_THUMBEE = (1 << 11),
+ MD_CPU_ARM_ELF_HWCAP_NEON = (1 << 12),
+ MD_CPU_ARM_ELF_HWCAP_VFPv3 = (1 << 13),
+ MD_CPU_ARM_ELF_HWCAP_VFPv3D16 = (1 << 14),
+ MD_CPU_ARM_ELF_HWCAP_TLS = (1 << 15),
+ MD_CPU_ARM_ELF_HWCAP_VFPv4 = (1 << 16),
+ MD_CPU_ARM_ELF_HWCAP_IDIVA = (1 << 17),
+ MD_CPU_ARM_ELF_HWCAP_IDIVT = (1 << 18),
+} MDCPUInformationARMElfHwCaps;
+
+typedef struct {
+ /* The next 3 fields and numberOfProcessors are from the SYSTEM_INFO
+ * structure as returned by GetSystemInfo */
+ uint16_t processor_architecture;
+ uint16_t processor_level; /* x86: 5 = 586, 6 = 686, ... */
+ /* ARM: 6 = ARMv6, 7 = ARMv7 ... */
+ uint16_t processor_revision; /* x86: 0xMMSS, where MM=model,
+ * SS=stepping */
+ /* ARM: 0 */
+
+ uint8_t number_of_processors;
+ uint8_t product_type; /* Windows: VER_NT_* from WinNT.h */
+
+ /* The next 5 fields are from the OSVERSIONINFO structure as returned
+ * by GetVersionEx */
+ uint32_t major_version;
+ uint32_t minor_version;
+ uint32_t build_number;
+ uint32_t platform_id;
+ MDRVA csd_version_rva; /* MDString further identifying the
+ * host OS.
+ * Windows: name of the installed OS
+ * service pack.
+ * Mac OS X: the Apple OS build number
+ * (sw_vers -buildVersion).
+ * Linux: uname -srvmo */
+
+ uint16_t suite_mask; /* Windows: VER_SUITE_* from WinNT.h */
+ uint16_t reserved2;
+
+ MDCPUInformation cpu;
+} MDRawSystemInfo; /* MINIDUMP_SYSTEM_INFO */
+
+/* For (MDRawSystemInfo).processor_architecture: */
+typedef enum {
+ MD_CPU_ARCHITECTURE_X86 = 0, /* PROCESSOR_ARCHITECTURE_INTEL */
+ MD_CPU_ARCHITECTURE_MIPS = 1, /* PROCESSOR_ARCHITECTURE_MIPS */
+ MD_CPU_ARCHITECTURE_ALPHA = 2, /* PROCESSOR_ARCHITECTURE_ALPHA */
+ MD_CPU_ARCHITECTURE_PPC = 3, /* PROCESSOR_ARCHITECTURE_PPC */
+ MD_CPU_ARCHITECTURE_SHX = 4, /* PROCESSOR_ARCHITECTURE_SHX
+ * (Super-H) */
+ MD_CPU_ARCHITECTURE_ARM = 5, /* PROCESSOR_ARCHITECTURE_ARM */
+ MD_CPU_ARCHITECTURE_IA64 = 6, /* PROCESSOR_ARCHITECTURE_IA64 */
+ MD_CPU_ARCHITECTURE_ALPHA64 = 7, /* PROCESSOR_ARCHITECTURE_ALPHA64 */
+ MD_CPU_ARCHITECTURE_MSIL = 8, /* PROCESSOR_ARCHITECTURE_MSIL
+ * (Microsoft Intermediate Language) */
+ MD_CPU_ARCHITECTURE_AMD64 = 9, /* PROCESSOR_ARCHITECTURE_AMD64 */
+ MD_CPU_ARCHITECTURE_X86_WIN64 = 10,
+ /* PROCESSOR_ARCHITECTURE_IA32_ON_WIN64 (WoW64) */
+ MD_CPU_ARCHITECTURE_ARM64 = 12, /* PROCESSOR_ARCHITECTURE_ARM64 */
+ MD_CPU_ARCHITECTURE_SPARC = 0x8001, /* Breakpad-defined value for SPARC */
+ MD_CPU_ARCHITECTURE_PPC64 = 0x8002, /* Breakpad-defined value for PPC64 */
+ MD_CPU_ARCHITECTURE_ARM64_OLD = 0x8003, /* Breakpad-defined value for ARM64 */
+ MD_CPU_ARCHITECTURE_MIPS64 = 0x8004, /* Breakpad-defined value for MIPS64 */
+ MD_CPU_ARCHITECTURE_UNKNOWN = 0xffff /* PROCESSOR_ARCHITECTURE_UNKNOWN */
+} MDCPUArchitecture;
+
+/* For (MDRawSystemInfo).platform_id: */
+typedef enum {
+ MD_OS_WIN32S = 0, /* VER_PLATFORM_WIN32s (Windows 3.1) */
+ MD_OS_WIN32_WINDOWS = 1, /* VER_PLATFORM_WIN32_WINDOWS (Windows 95-98-Me) */
+ MD_OS_WIN32_NT = 2, /* VER_PLATFORM_WIN32_NT (Windows NT, 2000+) */
+ MD_OS_WIN32_CE = 3, /* VER_PLATFORM_WIN32_CE, VER_PLATFORM_WIN32_HH
+ * (Windows CE, Windows Mobile, "Handheld") */
+
+ /* The following values are Breakpad-defined. */
+ MD_OS_UNIX = 0x8000, /* Generic Unix-ish */
+ MD_OS_MAC_OS_X = 0x8101, /* Mac OS X/Darwin */
+ MD_OS_IOS = 0x8102, /* iOS */
+ MD_OS_LINUX = 0x8201, /* Linux */
+ MD_OS_SOLARIS = 0x8202, /* Solaris */
+ MD_OS_ANDROID = 0x8203, /* Android */
+ MD_OS_PS3 = 0x8204, /* PS3 */
+ MD_OS_NACL = 0x8205, /* Native Client (NaCl) */
+ MD_OS_FUCHSIA = 0x8206 /* Fuchsia */
+} MDOSPlatform;
+
+typedef struct {
+ uint64_t base_of_image;
+ uint32_t size_of_image;
+ uint32_t checksum;
+ uint32_t time_date_stamp;
+ MDRVA module_name_rva;
+} MDRawUnloadedModule;
+
+typedef struct {
+ uint32_t size_of_header;
+ uint32_t size_of_entry;
+ uint32_t number_of_entries;
+} MDRawUnloadedModuleList; /* MINIDUMP_UNLOADED_MODULE_LIST */
+
+typedef struct {
+ uint16_t year;
+ uint16_t month;
+ uint16_t day_of_week;
+ uint16_t day;
+ uint16_t hour;
+ uint16_t minute;
+ uint16_t second;
+ uint16_t milliseconds;
+} MDSystemTime; /* SYSTEMTIME */
+
+typedef struct {
+ /* Required field. The bias is the difference, in minutes, between
+ * Coordinated Universal Time (UTC) and local time.
+ * Formula: UTC = local time + bias */
+ int32_t bias;
+ /* A description for standard time. For example, "EST" could indicate Eastern
+ * Standard Time. In practice this contains the full time zone names. This
+ * string can be empty. */
+ uint16_t standard_name[32]; /* UTF-16-encoded, 0-terminated */
+ /* A MDSystemTime structure that contains a date and local time when the
+ * transition from daylight saving time to standard time occurs on this
+ * operating system. If the time zone does not support daylight saving time,
+ * the month member in the MDSystemTime structure is zero. */
+ MDSystemTime standard_date;
+ /* The bias value to be used during local time translations that occur during
+ * standard time. */
+ int32_t standard_bias;
+ /* A description for daylight saving time. For example, "PDT" could indicate
+ * Pacific Daylight Time. In practice this contains the full time zone names.
+ * This string can be empty. */
+ uint16_t daylight_name[32]; /* UTF-16-encoded, 0-terminated */
+ /* A MDSystemTime structure that contains a date and local time when the
+ * transition from standard time to daylight saving time occurs on this
+ * operating system. If the time zone does not support daylight saving time,
+ * the month member in the MDSystemTime structure is zero.*/
+ MDSystemTime daylight_date;
+ /* The bias value to be used during local time translations that occur during
+ * daylight saving time. */
+ int32_t daylight_bias;
+} MDTimeZoneInformation; /* TIME_ZONE_INFORMATION */
+
+/* MAX_PATH from windef.h */
+#define MD_MAX_PATH 260
+
+/* For MDXStateConfigFeatureMscInfo.features */
+typedef struct {
+ uint32_t offset;
+ uint32_t size;
+} MDXStateFeature;
+
+/* For MDXStateConfigFeatureMscInfo.enabled_features from winnt.h */
+typedef enum {
+ MD_XSTATE_LEGACY_FLOATING_POINT = 0, /* XSTATE_LEGACY_FLOATING_POINT */
+ MD_XSTATE_LEGACY_SSE = 1, /* XSTATE_LEGACY_SSE */
+ MD_XSTATE_GSSE = 2, /* XSTATE_GSSE */
+ MD_XSTATE_AVX = MD_XSTATE_GSSE, /* XSTATE_AVX */
+ MD_XSTATE_MPX_BNDREGS = 3, /* XSTATE_MPX_BNDREGS */
+ MD_XSTATE_MPX_BNDCSR = 4, /* XSTATE_MPX_BNDCSR */
+ MD_XSTATE_AVX512_KMASK = 5, /* XSTATE_AVX512_KMASK */
+ MD_XSTATE_AVX512_ZMM_H = 6, /* XSTATE_AVX512_ZMM_H */
+ MD_XSTATE_AVX512_ZMM = 7, /* XSTATE_AVX512_ZMM */
+ MD_XSTATE_IPT = 8, /* XSTATE_IPT */
+ MD_XSTATE_LWP = 62 /* XSTATE_LWP */
+} MDXStateFeatureFlag;
+
+/* MAXIMUM_XSTATE_FEATURES from winnt.h */
+#define MD_MAXIMUM_XSTATE_FEATURES 64
+
+/* For MDRawMiscInfo.xstate_data */
+typedef struct {
+ uint32_t size_of_info;
+ uint32_t context_size;
+ /* An entry in the features array is valid only if the corresponding bit in
+ * the enabled_features flag is set. */
+ uint64_t enabled_features;
+ MDXStateFeature features[MD_MAXIMUM_XSTATE_FEATURES];
+} MDXStateConfigFeatureMscInfo;
+
+
+/* The miscellaneous information stream contains a variety
+ * of small pieces of information. A member is valid if
+ * it's within the available size and its corresponding
+ * bit is set. */
+typedef struct {
+ uint32_t size_of_info; /* Length of entire MDRawMiscInfo structure. */
+ uint32_t flags1;
+
+ /* The next field is only valid if flags1 contains
+ * MD_MISCINFO_FLAGS1_PROCESS_ID. */
+ uint32_t process_id;
+
+ /* The next 3 fields are only valid if flags1 contains
+ * MD_MISCINFO_FLAGS1_PROCESS_TIMES. */
+ uint32_t process_create_time; /* time_t process started */
+ uint32_t process_user_time; /* seconds of user CPU time */
+ uint32_t process_kernel_time; /* seconds of kernel CPU time */
+
+ /* The following fields are not present in MINIDUMP_MISC_INFO but are
+ * in MINIDUMP_MISC_INFO_2. When this struct is populated, these values
+ * may not be set. Use flags1 and size_of_info to determine whether these
+ * values are present. These are only valid when flags1 contains
+ * MD_MISCINFO_FLAGS1_PROCESSOR_POWER_INFO. */
+ uint32_t processor_max_mhz;
+ uint32_t processor_current_mhz;
+ uint32_t processor_mhz_limit;
+ uint32_t processor_max_idle_state;
+ uint32_t processor_current_idle_state;
+
+ /* The following fields are not present in MINIDUMP_MISC_INFO_2 but are
+ * in MINIDUMP_MISC_INFO_3. When this struct is populated, these values
+ * may not be set. Use flags1 and size_of_info to determine whether these
+ * values are present. */
+
+ /* The following field is only valid if flags1 contains
+ * MD_MISCINFO_FLAGS1_PROCESS_INTEGRITY. */
+ uint32_t process_integrity_level;
+
+ /* The following field is only valid if flags1 contains
+ * MD_MISCINFO_FLAGS1_PROCESS_EXECUTE_FLAGS. */
+ uint32_t process_execute_flags;
+
+ /* The following field is only valid if flags1 contains
+ * MD_MISCINFO_FLAGS1_PROTECTED_PROCESS. */
+ uint32_t protected_process;
+
+ /* The following 2 fields are only valid if flags1 contains
+ * MD_MISCINFO_FLAGS1_TIMEZONE. */
+ uint32_t time_zone_id;
+ MDTimeZoneInformation time_zone;
+
+ /* The following fields are not present in MINIDUMP_MISC_INFO_3 but are
+ * in MINIDUMP_MISC_INFO_4. When this struct is populated, these values
+ * may not be set. Use flags1 and size_of_info to determine whether these
+ * values are present. */
+
+ /* The following 2 fields are only valid if flags1 contains
+ * MD_MISCINFO_FLAGS1_BUILDSTRING. */
+ uint16_t build_string[MD_MAX_PATH]; /* UTF-16-encoded, 0-terminated */
+ uint16_t dbg_bld_str[40]; /* UTF-16-encoded, 0-terminated */
+
+ /* The following fields are not present in MINIDUMP_MISC_INFO_4 but are
+ * in MINIDUMP_MISC_INFO_5. When this struct is populated, these values
+ * may not be set. Use flags1 and size_of_info to determine whether these
+ * values are present. */
+
+ /* The following field has its own flags for establishing the validity of
+ * the structure's contents.*/
+ MDXStateConfigFeatureMscInfo xstate_data;
+
+ /* The following field is only valid if flags1 contains
+ * MD_MISCINFO_FLAGS1_PROCESS_COOKIE. */
+ uint32_t process_cookie;
+} MDRawMiscInfo; /* MINIDUMP_MISC_INFO, MINIDUMP_MISC_INFO_2,
+ * MINIDUMP_MISC_INFO_3, MINIDUMP_MISC_INFO_4,
+ * MINIDUMP_MISC_INFO_5, MINIDUMP_MISC_INFO_N */
+
+static const size_t MD_MISCINFO_SIZE =
+ offsetof(MDRawMiscInfo, processor_max_mhz);
+static const size_t MD_MISCINFO2_SIZE =
+ offsetof(MDRawMiscInfo, process_integrity_level);
+static const size_t MD_MISCINFO3_SIZE =
+ offsetof(MDRawMiscInfo, build_string[0]);
+static const size_t MD_MISCINFO4_SIZE =
+ offsetof(MDRawMiscInfo, xstate_data);
+/* Version 5 of the MDRawMiscInfo structure is not a multiple of 8 in size and
+ * yet it contains some 8-bytes sized fields. This causes many compilers to
+ * round the structure size up to a multiple of 8 by adding padding at the end.
+ * The following hack is thus required for matching the proper on-disk size. */
+static const size_t MD_MISCINFO5_SIZE =
+ offsetof(MDRawMiscInfo, process_cookie) + sizeof(uint32_t);
+
+/* For (MDRawMiscInfo).flags1. These values indicate which fields in the
+ * MDRawMiscInfoStructure are valid. */
+typedef enum {
+ MD_MISCINFO_FLAGS1_PROCESS_ID = 0x00000001,
+ /* MINIDUMP_MISC1_PROCESS_ID */
+ MD_MISCINFO_FLAGS1_PROCESS_TIMES = 0x00000002,
+ /* MINIDUMP_MISC1_PROCESS_TIMES */
+ MD_MISCINFO_FLAGS1_PROCESSOR_POWER_INFO = 0x00000004,
+ /* MINIDUMP_MISC1_PROCESSOR_POWER_INFO */
+ MD_MISCINFO_FLAGS1_PROCESS_INTEGRITY = 0x00000010,
+ /* MINIDUMP_MISC3_PROCESS_INTEGRITY */
+ MD_MISCINFO_FLAGS1_PROCESS_EXECUTE_FLAGS = 0x00000020,
+ /* MINIDUMP_MISC3_PROCESS_EXECUTE_FLAGS */
+ MD_MISCINFO_FLAGS1_TIMEZONE = 0x00000040,
+ /* MINIDUMP_MISC3_TIMEZONE */
+ MD_MISCINFO_FLAGS1_PROTECTED_PROCESS = 0x00000080,
+ /* MINIDUMP_MISC3_PROTECTED_PROCESS */
+ MD_MISCINFO_FLAGS1_BUILDSTRING = 0x00000100,
+ /* MINIDUMP_MISC4_BUILDSTRING */
+ MD_MISCINFO_FLAGS1_PROCESS_COOKIE = 0x00000200,
+ /* MINIDUMP_MISC5_PROCESS_COOKIE */
+} MDMiscInfoFlags1;
+
+/*
+ * Around DbgHelp version 6.0, the style of new LIST structures changed
+ * from including an array of length 1 at the end of the struct to
+ * represent the variable-length data to including explicit
+ * "size of header", "size of entry" and "number of entries" fields
+ * in the header, presumably to allow backwards-compatibly-extending
+ * the structures in the future. The actual list entries follow the
+ * header data directly in this case.
+ */
+
+typedef struct {
+ uint32_t size_of_header; /* sizeof(MDRawMemoryInfoList) */
+ uint32_t size_of_entry; /* sizeof(MDRawMemoryInfo) */
+ uint64_t number_of_entries;
+} MDRawMemoryInfoList; /* MINIDUMP_MEMORY_INFO_LIST */
+
+typedef struct {
+ uint64_t base_address; /* Base address of a region of pages */
+ uint64_t allocation_base; /* Base address of a range of pages
+ * within this region. */
+ uint32_t allocation_protection; /* Memory protection when this region
+ * was originally allocated:
+ * MDMemoryProtection */
+ uint32_t __alignment1;
+ uint64_t region_size;
+ uint32_t state; /* MDMemoryState */
+ uint32_t protection; /* MDMemoryProtection */
+ uint32_t type; /* MDMemoryType */
+ uint32_t __alignment2;
+} MDRawMemoryInfo; /* MINIDUMP_MEMORY_INFO */
+
+/* For (MDRawMemoryInfo).state */
+typedef enum {
+ MD_MEMORY_STATE_COMMIT = 0x1000, /* physical storage has been allocated */
+ MD_MEMORY_STATE_RESERVE = 0x2000, /* reserved, but no physical storage */
+ MD_MEMORY_STATE_FREE = 0x10000 /* available to be allocated */
+} MDMemoryState;
+
+/* For (MDRawMemoryInfo).allocation_protection and .protection */
+typedef enum {
+ MD_MEMORY_PROTECT_NOACCESS = 0x01, /* PAGE_NOACCESS */
+ MD_MEMORY_PROTECT_READONLY = 0x02, /* PAGE_READONLY */
+ MD_MEMORY_PROTECT_READWRITE = 0x04, /* PAGE_READWRITE */
+ MD_MEMORY_PROTECT_WRITECOPY = 0x08, /* PAGE_WRITECOPY */
+ MD_MEMORY_PROTECT_EXECUTE = 0x10, /* PAGE_EXECUTE */
+ MD_MEMORY_PROTECT_EXECUTE_READ = 0x20, /* PAGE_EXECUTE_READ */
+ MD_MEMORY_PROTECT_EXECUTE_READWRITE = 0x40, /* PAGE_EXECUTE_READWRITE */
+ MD_MEMORY_PROTECT_EXECUTE_WRITECOPY = 0x80, /* PAGE_EXECUTE_WRITECOPY */
+ /* These options can be combined with the previous flags. */
+ MD_MEMORY_PROTECT_GUARD = 0x100, /* PAGE_GUARD */
+ MD_MEMORY_PROTECT_NOCACHE = 0x200, /* PAGE_NOCACHE */
+ MD_MEMORY_PROTECT_WRITECOMBINE = 0x400, /* PAGE_WRITECOMBINE */
+} MDMemoryProtection;
+
+/* Used to mask the mutually exclusive options from the combinable flags. */
+const uint32_t MD_MEMORY_PROTECTION_ACCESS_MASK = 0xFF;
+
+/* For (MDRawMemoryInfo).type */
+typedef enum {
+ MD_MEMORY_TYPE_PRIVATE = 0x20000, /* not shared by other processes */
+ MD_MEMORY_TYPE_MAPPED = 0x40000, /* mapped into the view of a section */
+ MD_MEMORY_TYPE_IMAGE = 0x1000000 /* mapped into the view of an image */
+} MDMemoryType;
+
+/*
+ * Breakpad extension types
+ */
+
+
+typedef struct {
+ /* validity is a bitmask with values from MDBreakpadInfoValidity, indicating
+ * which of the other fields in the structure are valid. */
+ uint32_t validity;
+
+ /* Thread ID of the handler thread. dump_thread_id should correspond to
+ * the thread_id of an MDRawThread in the minidump's MDRawThreadList if
+ * a dedicated thread in that list was used to produce the minidump. If
+ * the MDRawThreadList does not contain a dedicated thread used to produce
+ * the minidump, this field should be set to 0 and the validity field
+ * must not contain MD_BREAKPAD_INFO_VALID_DUMP_THREAD_ID. */
+ uint32_t dump_thread_id;
+
+ /* Thread ID of the thread that requested the minidump be produced. As
+ * with dump_thread_id, requesting_thread_id should correspond to the
+ * thread_id of an MDRawThread in the minidump's MDRawThreadList. For
+ * minidumps produced as a result of an exception, requesting_thread_id
+ * will be the same as the MDRawExceptionStream's thread_id field. For
+ * minidumps produced "manually" at the program's request,
+ * requesting_thread_id will indicate which thread caused the dump to be
+ * written. If the minidump was produced at the request of something
+ * other than a thread in the MDRawThreadList, this field should be set
+ * to 0 and the validity field must not contain
+ * MD_BREAKPAD_INFO_VALID_REQUESTING_THREAD_ID. */
+ uint32_t requesting_thread_id;
+} MDRawBreakpadInfo;
+
+/* For (MDRawBreakpadInfo).validity: */
+typedef enum {
+ /* When set, the dump_thread_id field is valid. */
+ MD_BREAKPAD_INFO_VALID_DUMP_THREAD_ID = 1 << 0,
+
+ /* When set, the requesting_thread_id field is valid. */
+ MD_BREAKPAD_INFO_VALID_REQUESTING_THREAD_ID = 1 << 1
+} MDBreakpadInfoValidity;
+
+typedef struct {
+ /* expression, function, and file are 0-terminated UTF-16 strings. They
+ * may be truncated if necessary, but should always be 0-terminated when
+ * written to a file.
+ * Fixed-length strings are used because MiniDumpWriteDump doesn't offer
+ * a way for user streams to point to arbitrary RVAs for strings. */
+ uint16_t expression[128]; /* Assertion that failed... */
+ uint16_t function[128]; /* ...within this function... */
+ uint16_t file[128]; /* ...in this file... */
+ uint32_t line; /* ...at this line. */
+ uint32_t type;
+} MDRawAssertionInfo;
+
+/* For (MDRawAssertionInfo).type: */
+typedef enum {
+ MD_ASSERTION_INFO_TYPE_UNKNOWN = 0,
+
+ /* Used for assertions that would be raised by the MSVC CRT but are
+ * directed to an invalid parameter handler instead. */
+ MD_ASSERTION_INFO_TYPE_INVALID_PARAMETER,
+
+ /* Used for assertions that would be raised by the MSVC CRT but are
+ * directed to a pure virtual call handler instead. */
+ MD_ASSERTION_INFO_TYPE_PURE_VIRTUAL_CALL
+} MDAssertionInfoData;
+
+/* These structs are used to store the DSO debug data in Linux minidumps,
+ * which is necessary for converting minidumps to usable coredumps.
+ * Because of a historical accident, several fields are variably encoded
+ * according to client word size, so tools potentially need to support both. */
+
+typedef struct {
+ uint32_t addr;
+ MDRVA name;
+ uint32_t ld;
+} MDRawLinkMap32;
+
+typedef struct {
+ uint32_t version;
+ MDRVA map; /* array of MDRawLinkMap32 */
+ uint32_t dso_count;
+ uint32_t brk;
+ uint32_t ldbase;
+ uint32_t dynamic;
+} MDRawDebug32;
+
+typedef struct {
+ uint64_t addr;
+ MDRVA name;
+ uint64_t ld;
+} MDRawLinkMap64;
+
+typedef struct {
+ uint32_t version;
+ MDRVA map; /* array of MDRawLinkMap64 */
+ uint32_t dso_count;
+ uint64_t brk;
+ uint64_t ldbase;
+ uint64_t dynamic;
+} MDRawDebug64;
+
+/* Crashpad extension types. See Crashpad's minidump/minidump_extensions.h. */
+
+typedef struct {
+ MDRVA key;
+ MDRVA value;
+} MDRawSimpleStringDictionaryEntry;
+
+typedef struct {
+ uint32_t count;
+ MDRawSimpleStringDictionaryEntry entries[0];
+} MDRawSimpleStringDictionary;
+
+typedef struct {
+ uint32_t version;
+ MDLocationDescriptor list_annotations;
+ MDLocationDescriptor simple_annotations; /* MDRawSimpleStringDictionary */
+} MDRawModuleCrashpadInfo;
+
+typedef struct {
+ uint32_t minidump_module_list_index;
+ MDLocationDescriptor location; /* MDRawModuleCrashpadInfo */
+} MDRawModuleCrashpadInfoLink;
+
+typedef struct {
+ uint32_t count;
+ MDLocationDescriptor modules[0]; /* MDRawModuleCrashpadInfoLink */
+} MDRawModuleCrashpadInfoList;
+
+typedef struct {
+ uint32_t version;
+ MDGUID report_id;
+ MDGUID client_id;
+ MDLocationDescriptor simple_annotations; /* MDRawSimpleStringDictionary */
+ MDLocationDescriptor module_list; /* MDRawModuleCrashpadInfoList */
+} MDRawCrashpadInfo;
+
+/* macOS __DATA,__crash_info data */
+
+typedef struct {
+ uint64_t stream_type; /* MOZ_MACOS_CRASH_INFO_STREAM */
+ uint64_t version;
+ uint64_t thread;
+ uint64_t dialog_mode;
+ uint64_t abort_cause; /* Only valid when 'version' > 4 */
+ /* If/when Apple adds more fields to crashreporter_annotations_t, add
+ * numerical fields here and change (MDRawMacCrashInfo).record_start_size
+ * accordingly. Make them all uint64_t, to keep this structure the same size
+ * on all platforms. 'data' should always be the last field. Add new string
+ * fields to the end of 'data'. */
+ /* 'data' currently contains five null-terminated uint8_t arrays, each
+ * possibly empty (containing only a single terminal null), stored one after
+ * the other:
+ * module_path;
+ * message;
+ * signature_string;
+ * backtrace;
+ * message2; */
+ uint8_t data[0];
+} MDRawMacCrashInfoRecord;
+
+/* This is the maximum supported size for each string in
+ * (MDRawMacCrashInfoRecord).data. If we encounter a string in the
+ * __crash_info section which seems larger than this, that's a sign of data
+ * corruption. */
+#define MACCRASHINFO_STRING_MAXSIZE 8192
+
+/* In principle there should only be one or two non-empty __DATA,__crash_info
+ * sections per process. But the __crash_info section is almost entirely
+ * undocumented, so just in case we set a large maximum. */
+#define MAC_CRASH_INFOS_MAX 20
+
+typedef struct {
+ uint32_t stream_type; /* MOZ_MACOS_CRASH_INFO_STREAM */
+ uint32_t record_count;
+ /* The size of the "fixed-size" part of MDRawMacCrashInfoRecord, before the
+ * 'data' field. This will always be 'sizeof(MDRawMacCrashInfoRecord)'. But
+ * that value may change if more numerical fields are added to
+ * MDRawMacCrashInfoRecord in the future. */
+ uint32_t record_start_size;
+ MDLocationDescriptor records[MAC_CRASH_INFOS_MAX];
+} MDRawMacCrashInfo;
+
+/* macOS kernel boot args */
+
+typedef struct __attribute__((packed,aligned(4))) {
+ uint32_t stream_type; /* MOZ_MACOS_BOOTARGS_STREAM */
+ MDRVA64 bootargs;
+} MDRawMacBootargs;
+
+/* Thread names */
+
+typedef struct __attribute__((packed,aligned(4))) {
+ uint32_t thread_id;
+ MDRVA64 rva_of_thread_name;
+} MDRawThreadName;
+
+typedef struct {
+ uint32_t number_of_thread_names;
+ MDRawThreadName thread_names[0];
+} MDRawThreadNamesList;
+
+#if defined(_MSC_VER)
+#pragma warning(pop)
+#endif /* _MSC_VER */
+
+
+#endif /* GOOGLE_BREAKPAD_COMMON_MINIDUMP_FORMAT_H__ */
diff --git a/toolkit/crashreporter/google-breakpad/src/google_breakpad/common/minidump_size.h b/toolkit/crashreporter/google-breakpad/src/google_breakpad/common/minidump_size.h
new file mode 100644
index 0000000000..fae57923cc
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/google_breakpad/common/minidump_size.h
@@ -0,0 +1,113 @@
+// 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. */
+
+// minidump_size.h: Provides a C++ template for programmatic access to
+// the sizes of various types defined in minidump_format.h.
+//
+// Author: Mark Mentovai
+
+#ifndef GOOGLE_BREAKPAD_COMMON_MINIDUMP_SIZE_H__
+#define GOOGLE_BREAKPAD_COMMON_MINIDUMP_SIZE_H__
+
+#include <sys/types.h>
+
+#include "google_breakpad/common/minidump_format.h"
+
+namespace google_breakpad {
+
+template<typename T>
+class minidump_size {
+ public:
+ static size_t size() { return sizeof(T); }
+};
+
+// Explicit specializations for variable-length types. The size returned
+// for these should be the size for an object without its variable-length
+// section.
+
+template<>
+class minidump_size<MDString> {
+ public:
+ static size_t size() { return MDString_minsize; }
+};
+
+template<>
+class minidump_size<MDRawThreadList> {
+ public:
+ static size_t size() { return MDRawThreadList_minsize; }
+};
+
+template<>
+class minidump_size<MDCVInfoPDB20> {
+ public:
+ static size_t size() { return MDCVInfoPDB20_minsize; }
+};
+
+template<>
+class minidump_size<MDCVInfoPDB70> {
+ public:
+ static size_t size() { return MDCVInfoPDB70_minsize; }
+};
+
+template<>
+class minidump_size<MDCVInfoELF> {
+ public:
+ static size_t size() { return MDCVInfoELF_minsize; }
+};
+
+template<>
+class minidump_size<MDImageDebugMisc> {
+ public:
+ static size_t size() { return MDImageDebugMisc_minsize; }
+};
+
+template<>
+class minidump_size<MDRawModuleList> {
+ public:
+ static size_t size() { return MDRawModuleList_minsize; }
+};
+
+template<>
+class minidump_size<MDRawMemoryList> {
+ public:
+ static size_t size() { return MDRawMemoryList_minsize; }
+};
+
+// Explicit specialization for MDRawModule, for which sizeof may include
+// tail-padding on some architectures but not others.
+
+template<>
+class minidump_size<MDRawModule> {
+ public:
+ static size_t size() { return MD_MODULE_SIZE; }
+};
+
+} // namespace google_breakpad
+
+#endif // GOOGLE_BREAKPAD_COMMON_MINIDUMP_SIZE_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/basic_source_line_resolver.h b/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/basic_source_line_resolver.h
new file mode 100644
index 0000000000..91fb784173
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/basic_source_line_resolver.h
@@ -0,0 +1,148 @@
+// 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.
+
+// basic_source_line_resolver.h: BasicSourceLineResolver is derived from
+// SourceLineResolverBase, and is a concrete implementation of
+// SourceLineResolverInterface, using address map files produced by a
+// compatible writer, e.g. PDBSourceLineWriter.
+//
+// see "processor/source_line_resolver_base.h"
+// and "source_line_resolver_interface.h" for more documentation.
+
+#ifndef GOOGLE_BREAKPAD_PROCESSOR_BASIC_SOURCE_LINE_RESOLVER_H__
+#define GOOGLE_BREAKPAD_PROCESSOR_BASIC_SOURCE_LINE_RESOLVER_H__
+
+#include <map>
+#include <string>
+
+#include "common/using_std_string.h"
+#include "google_breakpad/processor/source_line_resolver_base.h"
+
+namespace google_breakpad {
+
+using std::map;
+
+class BasicSourceLineResolver : public SourceLineResolverBase {
+ public:
+ BasicSourceLineResolver();
+ virtual ~BasicSourceLineResolver() { }
+
+ using SourceLineResolverBase::LoadModule;
+ using SourceLineResolverBase::LoadModuleUsingMapBuffer;
+ using SourceLineResolverBase::LoadModuleUsingMemoryBuffer;
+ using SourceLineResolverBase::ShouldDeleteMemoryBufferAfterLoadModule;
+ using SourceLineResolverBase::UnloadModule;
+ using SourceLineResolverBase::HasModule;
+ using SourceLineResolverBase::IsModuleCorrupt;
+ using SourceLineResolverBase::FillSourceLineInfo;
+ using SourceLineResolverBase::FindWindowsFrameInfo;
+ using SourceLineResolverBase::FindCFIFrameInfo;
+
+ private:
+ // friend declarations:
+ friend class BasicModuleFactory;
+ friend class ModuleComparer;
+ friend class ModuleSerializer;
+ template<class> friend class SimpleSerializer;
+
+ // Function derives from SourceLineResolverBase::Function.
+ struct Function;
+ // Module implements SourceLineResolverBase::Module interface.
+ class Module;
+
+ // Disallow unwanted copy ctor and assignment operator
+ BasicSourceLineResolver(const BasicSourceLineResolver&);
+ void operator=(const BasicSourceLineResolver&);
+};
+
+// Helper class, containing useful methods for parsing of Breakpad symbol files.
+class SymbolParseHelper {
+ public:
+ // Parses a |file_line| declaration. Returns true on success.
+ // Format: FILE <id> <filename>.
+ // Notice, that this method modifies the input |file_line| which is why it
+ // can't be const. On success, <id>, and <filename> are stored in |*index|,
+ // and |*filename|. No allocation is done, |*filename| simply points inside
+ // |file_line|.
+ static bool ParseFile(char *file_line, // in
+ long *index, // out
+ char **filename); // out
+
+ // Parses a |function_line| declaration. Returns true on success.
+ // Format: FUNC [<multiple>] <address> <size> <stack_param_size> <name>.
+ // Notice, that this method modifies the input |function_line| which is why it
+ // can't be const. On success, the presence of <multiple>, <address>, <size>,
+ // <stack_param_size>, and <name> are stored in |*is_multiple|, |*address|,
+ // |*size|, |*stack_param_size|, and |*name|. No allocation is done, |*name|
+ // simply points inside |function_line|.
+ static bool ParseFunction(char *function_line, // in
+ bool *is_multiple, // out
+ uint64_t *address, // out
+ uint64_t *size, // out
+ long *stack_param_size, // out
+ char **name); // out
+
+ // Parses a |line| declaration. Returns true on success.
+ // Format: <address> <size> <line number> <source file id>
+ // Notice, that this method modifies the input |function_line| which is why
+ // it can't be const. On success, <address>, <size>, <line number>, and
+ // <source file id> are stored in |*address|, |*size|, |*line_number|, and
+ // |*source_file|.
+ static bool ParseLine(char *line_line, // in
+ uint64_t *address, // out
+ uint64_t *size, // out
+ long *line_number, // out
+ long *source_file); // out
+
+ // Parses a |public_line| declaration. Returns true on success.
+ // Format: PUBLIC [<multiple>] <address> <stack_param_size> <name>
+ // Notice, that this method modifies the input |function_line| which is why
+ // it can't be const. On success, the presence of <multiple>, <address>,
+ // <stack_param_size>, <name> are stored in |*is_multiple|, |*address|,
+ // |*stack_param_size|, and |*name|. No allocation is done, |*name| simply
+ // points inside |public_line|.
+ static bool ParsePublicSymbol(char *public_line, // in
+ bool *is_multiple, // out
+ uint64_t *address, // out
+ long *stack_param_size, // out
+ char **name); // out
+
+ private:
+ // Used for success checks after strtoull and strtol.
+ static bool IsValidAfterNumber(char *after_number);
+
+ // Only allow static methods.
+ SymbolParseHelper();
+ SymbolParseHelper(const SymbolParseHelper&);
+ void operator=(const SymbolParseHelper&);
+};
+
+} // namespace google_breakpad
+
+#endif // GOOGLE_BREAKPAD_PROCESSOR_BASIC_SOURCE_LINE_RESOLVER_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/call_stack.h b/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/call_stack.h
new file mode 100644
index 0000000000..bf45e71bd1
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/call_stack.h
@@ -0,0 +1,97 @@
+// 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.
+
+// call_stack.h: A call stack comprised of stack frames.
+//
+// This class manages a vector of stack frames. It is used instead of
+// exposing the vector directly to allow the CallStack to own StackFrame
+// pointers without having to publicly export the linked_ptr class. A
+// CallStack must be composed of pointers instead of objects to allow for
+// CPU-specific StackFrame subclasses.
+//
+// By convention, the stack frame at index 0 is the innermost callee frame,
+// and the frame at the highest index in a call stack is the outermost
+// caller. CallStack only allows stacks to be built by pushing frames,
+// beginning with the innermost callee frame.
+//
+// Author: Mark Mentovai
+
+#ifndef GOOGLE_BREAKPAD_PROCESSOR_CALL_STACK_H__
+#define GOOGLE_BREAKPAD_PROCESSOR_CALL_STACK_H__
+
+#include <cstdint>
+#include <string>
+#include <vector>
+
+namespace google_breakpad {
+
+using std::vector;
+using std::string;
+
+struct StackFrame;
+template<typename T> class linked_ptr;
+
+class CallStack {
+ public:
+ CallStack() { Clear(); }
+ ~CallStack();
+
+ // Resets the CallStack to its initial empty state
+ void Clear();
+
+ const vector<StackFrame*>* frames() const { return &frames_; }
+
+ // Set the TID associated with this call stack.
+ void set_tid(uint32_t tid) { tid_ = tid; }
+ void set_last_error(uint32_t last_error) { last_error_ = last_error; }
+ void set_name(const string& name) { name_ = name; }
+
+ uint32_t tid() const { return tid_; }
+ uint32_t last_error() const { return last_error_; }
+ const string name() const { return name_; }
+
+ private:
+ // Stackwalker is responsible for building the frames_ vector.
+ friend class Stackwalker;
+
+ // Storage for pushed frames.
+ vector<StackFrame*> frames_;
+
+ // The TID associated with this call stack. Default to 0 if it's not
+ // available.
+ uint32_t tid_;
+ // The last error the OS set for this thread (win32's GetLastError())
+ uint32_t last_error_;
+ // The name of this thread, empty if it's not available
+ string name_;
+};
+
+} // namespace google_breakpad
+
+#endif // GOOGLE_BREAKPAD_PROCSSOR_CALL_STACK_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/code_module.h b/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/code_module.h
new file mode 100644
index 0000000000..29b8d9c9ab
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/code_module.h
@@ -0,0 +1,104 @@
+// 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.
+
+// code_module.h: Carries information about code modules that are loaded
+// into a process.
+//
+// Author: Mark Mentovai
+
+#ifndef GOOGLE_BREAKPAD_PROCESSOR_CODE_MODULE_H__
+#define GOOGLE_BREAKPAD_PROCESSOR_CODE_MODULE_H__
+
+#include <string>
+
+#include "common/using_std_string.h"
+#include "google_breakpad/common/breakpad_types.h"
+
+namespace google_breakpad {
+
+class CodeModule {
+ public:
+ virtual ~CodeModule() {}
+
+ // The base address of this code module as it was loaded by the process.
+ // (uint64_t)-1 on error.
+ virtual uint64_t base_address() const = 0;
+
+ // The size of the code module. 0 on error.
+ virtual uint64_t size() const = 0;
+
+ // The path or file name that the code module was loaded from. Empty on
+ // error.
+ virtual string code_file() const = 0;
+
+ // An identifying string used to discriminate between multiple versions and
+ // builds of the same code module. This may contain a uuid, timestamp,
+ // version number, or any combination of this or other information, in an
+ // implementation-defined format. Empty on error.
+ virtual string code_identifier() const = 0;
+
+ // The filename containing debugging information associated with the code
+ // module. If debugging information is stored in a file separate from the
+ // code module itself (as is the case when .pdb or .dSYM files are used),
+ // this will be different from code_file. If debugging information is
+ // stored in the code module itself (possibly prior to stripping), this
+ // will be the same as code_file. Empty on error.
+ virtual string debug_file() const = 0;
+
+ // An identifying string similar to code_identifier, but identifies a
+ // specific version and build of the associated debug file. This may be
+ // the same as code_identifier when the debug_file and code_file are
+ // identical or when the same identifier is used to identify distinct
+ // debug and code files.
+ virtual string debug_identifier() const = 0;
+
+ // A human-readable representation of the code module's version. Empty on
+ // error.
+ virtual string version() const = 0;
+
+ // Creates a new copy of this CodeModule object, which the caller takes
+ // ownership of. The new CodeModule may be of a different concrete class
+ // than the CodeModule being copied, but will behave identically to the
+ // copied CodeModule as far as the CodeModule interface is concerned.
+ virtual CodeModule* Copy() const = 0;
+
+ // Getter and setter for shrink_down_delta. This is used when the address
+ // range for a module is shrunk down due to address range conflicts with
+ // other modules. The base_address and size fields are not updated and they
+ // should always reflect the original values (reported in the minidump).
+ virtual uint64_t shrink_down_delta() const = 0;
+ virtual void SetShrinkDownDelta(uint64_t shrink_down_delta) = 0;
+
+ // Whether the module was unloaded from memory.
+ virtual bool is_unloaded() const = 0;
+};
+
+} // namespace google_breakpad
+
+#endif // GOOGLE_BREAKPAD_PROCESSOR_CODE_MODULE_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/code_modules.h b/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/code_modules.h
new file mode 100644
index 0000000000..74f113c19c
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/code_modules.h
@@ -0,0 +1,108 @@
+// 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.
+
+// code_modules.h: Contains all of the CodeModule objects that were loaded
+// into a single process.
+//
+// Author: Mark Mentovai
+
+#ifndef GOOGLE_BREAKPAD_PROCESSOR_CODE_MODULES_H__
+#define GOOGLE_BREAKPAD_PROCESSOR_CODE_MODULES_H__
+
+#include <stddef.h>
+
+#include <vector>
+
+#include "google_breakpad/common/breakpad_types.h"
+#include "processor/linked_ptr.h"
+
+namespace google_breakpad {
+
+class CodeModule;
+
+class CodeModules {
+ public:
+ virtual ~CodeModules() {}
+
+ // The number of contained CodeModule objects.
+ virtual unsigned int module_count() const = 0;
+
+ // Random access to modules. Returns the module whose code is present
+ // at the address indicated by |address|. If no module is present at this
+ // address, returns NULL. Ownership of the returned CodeModule is retained
+ // by the CodeModules object; pointers returned by this method are valid for
+ // comparison with pointers returned by the other Get methods.
+ virtual const CodeModule* GetModuleForAddress(uint64_t address) const = 0;
+
+ // Returns the module corresponding to the main executable. If there is
+ // no main executable, returns NULL. Ownership of the returned CodeModule
+ // is retained by the CodeModules object; pointers returned by this method
+ // are valid for comparison with pointers returned by the other Get
+ // methods.
+ virtual const CodeModule* GetMainModule() const = 0;
+
+ // Sequential access to modules. A sequence number of 0 corresponds to the
+ // module residing lowest in memory. If the sequence number is out of
+ // range, returns NULL. Ownership of the returned CodeModule is retained
+ // by the CodeModules object; pointers returned by this method are valid for
+ // comparison with pointers returned by the other Get methods.
+ virtual const CodeModule* GetModuleAtSequence(
+ unsigned int sequence) const = 0;
+
+ // Sequential access to modules. This is similar to GetModuleAtSequence,
+ // except no ordering requirement is enforced. A CodeModules implementation
+ // may return CodeModule objects from GetModuleAtIndex in any order it
+ // wishes, provided that the order remain the same throughout the life of
+ // the CodeModules object. Typically, GetModuleAtIndex would be used by
+ // a caller to enumerate all CodeModule objects quickly when the enumeration
+ // does not require any ordering. If the index argument is out of range,
+ // returns NULL. Ownership of the returned CodeModule is retained by
+ // the CodeModules object; pointers returned by this method are valid for
+ // comparison with pointers returned by the other Get methods.
+ virtual const CodeModule* GetModuleAtIndex(unsigned int index) const = 0;
+
+ // Creates a new copy of this CodeModules object, which the caller takes
+ // ownership of. The new object will also contain copies of the existing
+ // object's child CodeModule objects. The new CodeModules object may be of
+ // a different concrete class than the object being copied, but will behave
+ // identically to the copied object as far as the CodeModules and CodeModule
+ // interfaces are concerned, except that the order that GetModuleAtIndex
+ // returns objects in may differ between a copy and the original CodeModules
+ // object.
+ virtual const CodeModules* Copy() const = 0;
+
+ // Returns a vector of all modules which address ranges needed to be shrunk
+ // down due to address range conflicts with other modules.
+ virtual std::vector<linked_ptr<const CodeModule> >
+ GetShrunkRangeModules() const = 0;
+};
+
+} // namespace google_breakpad
+
+#endif // GOOGLE_BREAKPAD_PROCESSOR_CODE_MODULES_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/dump_context.h b/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/dump_context.h
new file mode 100644
index 0000000000..df80bf7ef7
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/dump_context.h
@@ -0,0 +1,116 @@
+// 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.
+
+// dump_context.h: A (mini/micro) dump CPU-specific context.
+
+#ifndef GOOGLE_BREAKPAD_PROCESSOR_DUMP_CONTEXT_H__
+#define GOOGLE_BREAKPAD_PROCESSOR_DUMP_CONTEXT_H__
+
+#include "google_breakpad/common/minidump_format.h"
+#include "google_breakpad/processor/dump_object.h"
+
+namespace google_breakpad {
+
+// DumpContext carries a CPU-specific MDRawContext structure, which contains CPU
+// context such as register states.
+class DumpContext : public DumpObject {
+ public:
+ virtual ~DumpContext();
+
+ // Returns an MD_CONTEXT_* value such as MD_CONTEXT_X86 or MD_CONTEXT_PPC
+ // identifying the CPU type that the context was collected from. The
+ // returned value will identify the CPU only, and will have any other
+ // MD_CONTEXT_* bits masked out. Returns 0 on failure.
+ uint32_t GetContextCPU() const;
+
+ // Return the raw value of |context_flags_|
+ uint32_t GetContextFlags() const;
+
+ // Returns raw CPU-specific context data for the named CPU type. If the
+ // context data does not match the CPU type or does not exist, returns NULL.
+ const MDRawContextAMD64* GetContextAMD64() const;
+ const MDRawContextARM* GetContextARM() const;
+ const MDRawContextARM64* GetContextARM64() const;
+ const MDRawContextMIPS* GetContextMIPS() const;
+ const MDRawContextPPC* GetContextPPC() const;
+ const MDRawContextPPC64* GetContextPPC64() const;
+ const MDRawContextSPARC* GetContextSPARC() const;
+ const MDRawContextX86* GetContextX86() const;
+
+ // A convenience method to get the instruction pointer out of the
+ // MDRawContext, since it varies per-CPU architecture.
+ bool GetInstructionPointer(uint64_t* ip) const;
+
+ // Similar to the GetInstructionPointer method, this method gets the stack
+ // pointer for all CPU architectures.
+ bool GetStackPointer(uint64_t* sp) const;
+
+ // Print a human-readable representation of the object to stdout.
+ void Print();
+
+ protected:
+ DumpContext();
+
+ // Sets row CPU-specific context data for the names CPU type.
+ void SetContextFlags(uint32_t context_flags);
+ void SetContextX86(MDRawContextX86* x86);
+ void SetContextPPC(MDRawContextPPC* ppc);
+ void SetContextPPC64(MDRawContextPPC64* ppc64);
+ void SetContextAMD64(MDRawContextAMD64* amd64);
+ void SetContextSPARC(MDRawContextSPARC* ctx_sparc);
+ void SetContextARM(MDRawContextARM* arm);
+ void SetContextARM64(MDRawContextARM64* arm64);
+ void SetContextMIPS(MDRawContextMIPS* ctx_mips);
+
+ // Free the CPU-specific context structure.
+ void FreeContext();
+
+ private:
+ // The CPU-specific context structure.
+ union {
+ MDRawContextBase* base;
+ MDRawContextX86* x86;
+ MDRawContextPPC* ppc;
+ MDRawContextPPC64* ppc64;
+ MDRawContextAMD64* amd64;
+ // on Solaris SPARC, sparc is defined as a numeric constant,
+ // so variables can NOT be named as sparc
+ MDRawContextSPARC* ctx_sparc;
+ MDRawContextARM* arm;
+ MDRawContextARM64* arm64;
+ MDRawContextMIPS* ctx_mips;
+ } context_;
+
+ // Store this separately because of the weirdo AMD64 context
+ uint32_t context_flags_;
+};
+
+} // namespace google_breakpad
+
+#endif // GOOGLE_BREAKPAD_PROCESSOR_DUMP_CONTEXT_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/dump_object.h b/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/dump_object.h
new file mode 100644
index 0000000000..112f687f4c
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/dump_object.h
@@ -0,0 +1,53 @@
+// 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.
+
+// dump_object.h: A base class for all mini/micro dump object.
+
+#ifndef GOOGLE_BREAKPAD_PROCESSOR_DUMP_OBJECT_H__
+#define GOOGLE_BREAKPAD_PROCESSOR_DUMP_OBJECT_H__
+
+namespace google_breakpad {
+
+// DumpObject is the base of various mini/micro dump's objects.
+class DumpObject {
+ public:
+ DumpObject();
+
+ bool valid() const { return valid_; }
+
+ protected:
+ // DumpObjects are not valid when created. When a subclass populates its own
+ // fields, it can set valid_ to true. Accessors and mutators may wish to
+ // consider or alter the valid_ state as they interact with objects.
+ bool valid_;
+};
+
+} // namespace google_breakpad
+
+#endif // GOOGLE_BREAKPAD_PROCESSOR_DUMP_OBJECT_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/exception_record.h b/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/exception_record.h
new file mode 100644
index 0000000000..eac6c90ae2
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/exception_record.h
@@ -0,0 +1,124 @@
+// Copyright (c) 2019 Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// exception_record.h: A snapshot of an exception record.
+//
+// Author: Ivan Penkov
+
+#ifndef THIRD_PARTY_BREAKPAD_SRC_GOOGLE_BREAKPAD_PROCESSOR_EXCEPTION_RECORD_H_
+#define THIRD_PARTY_BREAKPAD_SRC_GOOGLE_BREAKPAD_PROCESSOR_EXCEPTION_RECORD_H_
+
+#include <vector>
+
+namespace google_breakpad {
+
+// Additional argument that describes the exception.
+class ExceptionParameter {
+ public:
+ ExceptionParameter(uint64_t value, const string& description)
+ : value_(value), description_(description) {}
+ // Accessors. See the data declarations below.
+ uint64_t value() const { return value_; }
+ void set_value(uint64_t value) { value_ = value; }
+ const string& description() const { return description_; }
+ void set_description(const string& description) {
+ description_ = description;
+ }
+
+ private:
+ // Parameter value.
+ uint64_t value_;
+ // Human readable description/interpretation of the above value.
+ string description_;
+};
+
+// A snapshot of an exception record. Contains exception record details: code,
+// flags, address, parameters.
+class ExceptionRecord {
+ public:
+ // Accessors. See the data declarations below.
+ uint32_t code() const { return code_; }
+ const string& code_description() const { return code_description_; }
+ void set_code(uint32_t code, const string& description) {
+ code_ = code;
+ code_description_ = description;
+ }
+
+ uint32_t flags() const { return flags_; }
+ const string& flags_description() const { return flags_description_; }
+ void set_flags(uint32_t flags, const string& description) {
+ flags_ = flags;
+ flags_description_ = description;
+ }
+
+ uint64_t nested_exception_record_address() const {
+ return nested_exception_record_address_;
+ }
+ void set_nested_exception_record_address(
+ uint64_t nested_exception_record_address) {
+ nested_exception_record_address_ = nested_exception_record_address;
+ }
+
+ uint64_t address() const { return address_; }
+ void set_address(uint64_t address) { address_ = address; }
+
+ const std::vector<ExceptionParameter>* parameters() const {
+ return &parameters_;
+ }
+ void add_parameter(uint64_t value, const string& description) {
+ parameters_.push_back(ExceptionParameter(value, description));
+ }
+
+ private:
+ // Exception code.
+ uint32_t code_;
+ string code_description_;
+
+ // Exception flags.
+ uint32_t flags_;
+ string flags_description_;
+
+ // The address of an associated MDException structure. Exception records can
+ // be chained together to provide additional information when nested
+ // exceptions occur.
+ uint64_t nested_exception_record_address_;
+
+ // The memory address that caused the exception. For data access errors,
+ // this will be the data address that caused the fault. For code errors,
+ // this will be the address of the instruction that caused the fault.
+ uint64_t address_;
+
+ // An array of additional arguments that describe the exception.
+ std::vector<ExceptionParameter> parameters_;
+};
+
+} // namespace google_breakpad
+
+
+#endif // THIRD_PARTY_BREAKPAD_SRC_GOOGLE_BREAKPAD_PROCESSOR_EXCEPTION_RECORD_H_
diff --git a/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/exploitability.h b/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/exploitability.h
new file mode 100644
index 0000000000..014413c944
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/exploitability.h
@@ -0,0 +1,82 @@
+// 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.
+
+// exploitability_engine.h: Generic exploitability engine.
+//
+// The Exploitability class is an abstract base class providing common
+// generic methods that apply to exploitability engines for specific platforms.
+// Specific implementations will extend this class by providing run
+// methods to fill in the exploitability_ enumeration of the ProcessState
+// for a crash.
+//
+// Author: Cris Neckar
+
+#ifndef GOOGLE_BREAKPAD_PROCESSOR_EXPLOITABILITY_H_
+#define GOOGLE_BREAKPAD_PROCESSOR_EXPLOITABILITY_H_
+
+#include "google_breakpad/common/breakpad_types.h"
+#include "google_breakpad/processor/minidump.h"
+#include "google_breakpad/processor/process_state.h"
+
+namespace google_breakpad {
+
+class Exploitability {
+ public:
+ virtual ~Exploitability() {}
+
+ static Exploitability *ExploitabilityForPlatform(Minidump *dump,
+ ProcessState *process_state);
+
+ // The boolean parameter signals whether the exploitability engine is
+ // enabled to call out to objdump for disassembly. This is disabled by
+ // default. It is used to check the identity of the instruction that
+ // caused the program to crash. This should not be enabled if there are
+ // portability concerns.
+ static Exploitability *ExploitabilityForPlatform(Minidump *dump,
+ ProcessState *process_state,
+ bool enable_objdump);
+
+ ExploitabilityRating CheckExploitability();
+ bool AddressIsAscii(uint64_t);
+
+ protected:
+ Exploitability(Minidump *dump,
+ ProcessState *process_state);
+
+ Minidump *dump_;
+ ProcessState *process_state_;
+ SystemInfo *system_info_;
+
+ private:
+ virtual ExploitabilityRating CheckPlatformExploitability() = 0;
+};
+
+} // namespace google_breakpad
+
+#endif // GOOGLE_BREAKPAD_PROCESSOR_EXPLOITABILITY_H_
diff --git a/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/fast_source_line_resolver.h b/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/fast_source_line_resolver.h
new file mode 100644
index 0000000000..fdf9107766
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/fast_source_line_resolver.h
@@ -0,0 +1,100 @@
+// 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.
+//
+// fast_source_line_resolver.h: FastSourceLineResolver is derived from
+// SourceLineResolverBase, and is a concrete implementation of
+// SourceLineResolverInterface.
+//
+// FastSourceLineResolver is a sibling class of BasicSourceLineResolver. The
+// difference is FastSourceLineResolver loads a serialized memory chunk of data
+// which can be used directly a Module without parsing or copying of underlying
+// data. Therefore loading a symbol in FastSourceLineResolver is much faster
+// and more memory-efficient than BasicSourceLineResolver.
+//
+// See "source_line_resolver_base.h" and
+// "google_breakpad/source_line_resolver_interface.h" for more reference.
+//
+// Author: Siyang Xie (lambxsy@google.com)
+
+#ifndef GOOGLE_BREAKPAD_PROCESSOR_FAST_SOURCE_LINE_RESOLVER_H__
+#define GOOGLE_BREAKPAD_PROCESSOR_FAST_SOURCE_LINE_RESOLVER_H__
+
+#include <map>
+#include <string>
+
+#include "google_breakpad/processor/source_line_resolver_base.h"
+
+namespace google_breakpad {
+
+using std::map;
+
+class FastSourceLineResolver : public SourceLineResolverBase {
+ public:
+ FastSourceLineResolver();
+ virtual ~FastSourceLineResolver() { }
+
+ using SourceLineResolverBase::FillSourceLineInfo;
+ using SourceLineResolverBase::FindCFIFrameInfo;
+ using SourceLineResolverBase::FindWindowsFrameInfo;
+ using SourceLineResolverBase::HasModule;
+ using SourceLineResolverBase::IsModuleCorrupt;
+ using SourceLineResolverBase::LoadModule;
+ using SourceLineResolverBase::LoadModuleUsingMapBuffer;
+ using SourceLineResolverBase::LoadModuleUsingMemoryBuffer;
+ using SourceLineResolverBase::UnloadModule;
+
+ private:
+ // Friend declarations.
+ friend class ModuleComparer;
+ friend class ModuleSerializer;
+ friend class FastModuleFactory;
+
+ // Nested types that will derive from corresponding nested types defined in
+ // SourceLineResolverBase.
+ struct Line;
+ struct Function;
+ struct PublicSymbol;
+ class Module;
+
+ // Deserialize raw memory data to construct a WindowsFrameInfo object.
+ static WindowsFrameInfo CopyWFI(const char *raw_memory);
+
+ // FastSourceLineResolver requires the memory buffer stays alive during the
+ // lifetime of a corresponding module, therefore it needs to redefine this
+ // virtual method.
+ virtual bool ShouldDeleteMemoryBufferAfterLoadModule();
+
+ // Disallow unwanted copy ctor and assignment operator
+ FastSourceLineResolver(const FastSourceLineResolver&);
+ void operator=(const FastSourceLineResolver&);
+};
+
+} // namespace google_breakpad
+
+#endif // GOOGLE_BREAKPAD_PROCESSOR_FAST_SOURCE_LINE_RESOLVER_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/memory_region.h b/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/memory_region.h
new file mode 100644
index 0000000000..30f88df490
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/memory_region.h
@@ -0,0 +1,79 @@
+// 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.
+
+// memory_region.h: Access to memory regions.
+//
+// A MemoryRegion provides virtual access to a range of memory. It is an
+// abstraction allowing the actual source of memory to be independent of
+// methods which need to access a virtual memory space.
+//
+// Author: Mark Mentovai
+
+#ifndef GOOGLE_BREAKPAD_PROCESSOR_MEMORY_REGION_H__
+#define GOOGLE_BREAKPAD_PROCESSOR_MEMORY_REGION_H__
+
+
+#include "google_breakpad/common/breakpad_types.h"
+
+
+namespace google_breakpad {
+
+
+class MemoryRegion {
+ public:
+ virtual ~MemoryRegion() {}
+
+ // The base address of this memory region.
+ virtual uint64_t GetBase() const = 0;
+
+ // The size of this memory region.
+ virtual uint32_t GetSize() const = 0;
+
+ // Access to data of various sizes within the memory region. address
+ // is a pointer to read, and it must lie within the memory region as
+ // defined by its base address and size. The location pointed to by
+ // value is set to the value at address. Byte-swapping is performed
+ // if necessary so that the value is appropriate for the running
+ // program. Returns true on success. Fails and returns false if address
+ // is out of the region's bounds (after considering the width of value),
+ // or for other types of errors.
+ virtual bool GetMemoryAtAddress(uint64_t address, uint8_t* value) const = 0;
+ virtual bool GetMemoryAtAddress(uint64_t address, uint16_t* value) const = 0;
+ virtual bool GetMemoryAtAddress(uint64_t address, uint32_t* value) const = 0;
+ virtual bool GetMemoryAtAddress(uint64_t address, uint64_t* value) const = 0;
+
+ // Print a human-readable representation of the object to stdout.
+ virtual void Print() const = 0;
+};
+
+
+} // namespace google_breakpad
+
+
+#endif // GOOGLE_BREAKPAD_PROCESSOR_MEMORY_REGION_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/microdump.h b/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/microdump.h
new file mode 100644
index 0000000000..02ebdcd79b
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/microdump.h
@@ -0,0 +1,135 @@
+// 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.
+
+// microdump.h: A microdump reader. Microdump is a minified variant of a
+// minidump (see minidump.h for documentation) which contains the minimum
+// amount of information required to get a stack trace for the crashing thread.
+// The information contained in a microdump is:
+// - the crashing thread stack
+// - system information (os type / version)
+// - cpu context (state of the registers)
+// - list of mmaps
+
+#ifndef GOOGLE_BREAKPAD_PROCESSOR_MICRODUMP_H__
+#define GOOGLE_BREAKPAD_PROCESSOR_MICRODUMP_H__
+
+#include <string>
+#include <vector>
+
+#include "common/scoped_ptr.h"
+#include "common/using_std_string.h"
+#include "google_breakpad/processor/dump_context.h"
+#include "google_breakpad/processor/memory_region.h"
+#include "google_breakpad/processor/system_info.h"
+#include "processor/basic_code_modules.h"
+
+namespace google_breakpad {
+
+// MicrodumpModuleList contains all of the loaded code modules for a process
+// in the form of MicrodumpModules. It maintains a vector of these modules
+// and provides access to a code module corresponding to a specific address.
+class MicrodumpModules : public BasicCodeModules {
+ public:
+ // Takes over ownership of |module|.
+ void Add(const CodeModule* module);
+
+ // Enables/disables module address range shrink.
+ void SetEnableModuleShrink(bool is_enabled);
+};
+
+// MicrodumpContext carries a CPU-specific context.
+// See dump_context.h for documentation.
+class MicrodumpContext : public DumpContext {
+ public:
+ virtual void SetContextARM(MDRawContextARM* arm);
+ virtual void SetContextARM64(MDRawContextARM64* arm64);
+ virtual void SetContextX86(MDRawContextX86* x86);
+ virtual void SetContextMIPS(MDRawContextMIPS* mips32);
+ virtual void SetContextMIPS64(MDRawContextMIPS* mips64);
+};
+
+// This class provides access to microdump memory regions.
+// See memory_region.h for documentation.
+class MicrodumpMemoryRegion : public MemoryRegion {
+ public:
+ MicrodumpMemoryRegion();
+ virtual ~MicrodumpMemoryRegion() {}
+
+ // Set this region's address and contents. If we have placed an
+ // instance of this class in a test fixture class, individual tests
+ // can use this to provide the region's contents.
+ void Init(uint64_t base_address, const std::vector<uint8_t>& contents);
+
+ virtual uint64_t GetBase() const;
+ virtual uint32_t GetSize() const;
+
+ virtual bool GetMemoryAtAddress(uint64_t address, uint8_t* value) const;
+ virtual bool GetMemoryAtAddress(uint64_t address, uint16_t* value) const;
+ virtual bool GetMemoryAtAddress(uint64_t address, uint32_t* value) const;
+ virtual bool GetMemoryAtAddress(uint64_t address, uint64_t* value) const;
+
+ // Print a human-readable representation of the object to stdout.
+ virtual void Print() const;
+
+ private:
+ // Fetch a little-endian value from ADDRESS in contents_ whose size
+ // is BYTES, and store it in *VALUE. Returns true on success.
+ template<typename ValueType>
+ bool GetMemoryLittleEndian(uint64_t address, ValueType* value) const;
+
+ uint64_t base_address_;
+ std::vector<uint8_t> contents_;
+};
+
+// Microdump is the user's interface to a microdump file. It provides access to
+// the microdump's context, memory regions and modules.
+class Microdump {
+ public:
+ explicit Microdump(const string& contents);
+ virtual ~Microdump() {}
+
+ DumpContext* GetContext() { return context_.get(); }
+ MicrodumpMemoryRegion* GetMemory() { return stack_region_.get(); }
+ MicrodumpModules* GetModules() { return modules_.get(); }
+ SystemInfo* GetSystemInfo() { return system_info_.get(); }
+
+ string GetCrashReason() { return crash_reason_; }
+ uint64_t GetCrashAddress() { return crash_address_; }
+ private:
+ scoped_ptr<MicrodumpContext> context_;
+ scoped_ptr<MicrodumpMemoryRegion> stack_region_;
+ scoped_ptr<MicrodumpModules> modules_;
+ scoped_ptr<SystemInfo> system_info_;
+ string crash_reason_;
+ uint64_t crash_address_;
+};
+
+} // namespace google_breakpad
+
+#endif // GOOGLE_BREAKPAD_PROCESSOR_MICRODUMP_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/microdump_processor.h b/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/microdump_processor.h
new file mode 100644
index 0000000000..60d14a541f
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/microdump_processor.h
@@ -0,0 +1,64 @@
+// 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.
+
+// The processor for microdump (a reduced dump containing only the state of the
+// crashing thread). See crbug.com/410294 for more info and design docs.
+
+#ifndef GOOGLE_BREAKPAD_PROCESSOR_MICRODUMP_PROCESSOR_H__
+#define GOOGLE_BREAKPAD_PROCESSOR_MICRODUMP_PROCESSOR_H__
+
+#include <string>
+
+#include "common/using_std_string.h"
+#include "google_breakpad/processor/process_result.h"
+
+namespace google_breakpad {
+
+class Microdump;
+class ProcessState;
+class StackFrameSymbolizer;
+
+class MicrodumpProcessor {
+ public:
+ // Initializes the MicrodumpProcessor with a stack frame symbolizer.
+ // Does not take ownership of frame_symbolizer, which must NOT be NULL.
+ explicit MicrodumpProcessor(StackFrameSymbolizer* frame_symbolizer);
+
+ virtual ~MicrodumpProcessor();
+
+ // Processes the microdump contents and fills process_state with the result.
+ google_breakpad::ProcessResult Process(Microdump* microdump,
+ ProcessState* process_state);
+ private:
+ StackFrameSymbolizer* frame_symbolizer_;
+};
+
+} // namespace google_breakpad
+
+#endif // GOOGLE_BREAKPAD_PROCESSOR_MICRODUMP_PROCESSOR_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/minidump.h b/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/minidump.h
new file mode 100644
index 0000000000..b2eab95d8a
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/minidump.h
@@ -0,0 +1,1498 @@
+// Copyright (c) 2010 Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// minidump.h: A minidump reader.
+//
+// The basic structure of this module tracks the structure of the minidump
+// file itself. At the top level, a minidump file is represented by a
+// Minidump object. Like most other classes in this module, Minidump
+// provides a Read method that initializes the object with information from
+// the file. Most of the classes in this file are wrappers around the
+// "raw" structures found in the minidump file itself, and defined in
+// minidump_format.h. For example, each thread is represented by a
+// MinidumpThread object, whose parameters are specified in an MDRawThread
+// structure. A properly byte-swapped MDRawThread can be obtained from a
+// MinidumpThread easily by calling its thread() method.
+//
+// Most of the module lazily reads only the portion of the minidump file
+// necessary to fulfill the user's request. Calling Minidump::Read
+// only reads the minidump's directory. The thread list is not read until
+// it is needed, and even once it's read, the memory regions for each
+// thread's stack aren't read until they're needed. This strategy avoids
+// unnecessary file input, and allocating memory for data in which the user
+// has no interest. Note that although memory allocations for a typical
+// minidump file are not particularly large, it is possible for legitimate
+// minidumps to be sizable. A full-memory minidump, for example, contains
+// a snapshot of the entire mapped memory space. Even a normal minidump,
+// with stack memory only, can be large if, for example, the dump was
+// generated in response to a crash that occurred due to an infinite-
+// recursion bug that caused the stack's limits to be exceeded. Finally,
+// some users of this library will unfortunately find themselves in the
+// position of having to process potentially-hostile minidumps that might
+// attempt to cause problems by forcing the minidump processor to over-
+// allocate memory.
+//
+// Memory management in this module is based on a strict
+// you-don't-own-anything policy. The only object owned by the user is
+// the top-level Minidump object, the creation and destruction of which
+// must be the user's own responsibility. All other objects obtained
+// through interaction with this module are ultimately owned by the
+// Minidump object, and will be freed upon the Minidump object's destruction.
+// Because memory regions can potentially involve large allocations, a
+// FreeMemory method is provided by MinidumpMemoryRegion, allowing the user
+// to release data when it is no longer needed. Use of this method is
+// optional but recommended. If freed data is later required, it will
+// be read back in from the minidump file again.
+//
+// There is one exception to this memory management policy:
+// Minidump::ReadString will return a string object to the user, and the user
+// is responsible for its deletion.
+//
+// Author: Mark Mentovai
+
+#ifndef GOOGLE_BREAKPAD_PROCESSOR_MINIDUMP_H__
+#define GOOGLE_BREAKPAD_PROCESSOR_MINIDUMP_H__
+
+#include <stdint.h>
+
+#ifndef _WIN32
+#include <unistd.h>
+#endif
+
+#include <iostream>
+#include <map>
+#include <string>
+#include <vector>
+
+#include "common/basictypes.h"
+#include "common/using_std_string.h"
+#include "google_breakpad/processor/code_module.h"
+#include "google_breakpad/processor/code_modules.h"
+#include "google_breakpad/processor/dump_context.h"
+#include "google_breakpad/processor/dump_object.h"
+#include "google_breakpad/processor/memory_region.h"
+#include "google_breakpad/processor/proc_maps_linux.h"
+
+
+namespace google_breakpad {
+
+
+using std::map;
+using std::vector;
+
+
+class Minidump;
+template<typename AddressType, typename EntryType> class RangeMap;
+
+
+// MinidumpObject is the base of all Minidump* objects except for Minidump
+// itself.
+class MinidumpObject : public DumpObject {
+ public:
+ virtual ~MinidumpObject() {}
+
+ protected:
+ explicit MinidumpObject(Minidump* minidump);
+
+ // Refers to the Minidump object that is the ultimate parent of this
+ // Some MinidumpObjects are owned by other MinidumpObjects, but at the
+ // root of the ownership tree is always a Minidump. The Minidump object
+ // is kept here for access to its seeking and reading facilities, and
+ // for access to data about the minidump file itself, such as whether
+ // it should be byte-swapped.
+ Minidump* minidump_;
+};
+
+
+// This class exists primarily to provide a virtual destructor in a base
+// class common to all objects that might be stored in
+// Minidump::mStreamObjects. Some object types will never be stored in
+// Minidump::mStreamObjects, but are represented as streams and adhere to the
+// same interface, and may be derived from this class.
+class MinidumpStream : public MinidumpObject {
+ public:
+ virtual ~MinidumpStream() {}
+
+ protected:
+ explicit MinidumpStream(Minidump* minidump);
+
+ private:
+ // Populate (and validate) the MinidumpStream. minidump_ is expected
+ // to be positioned at the beginning of the stream, so that the next
+ // read from the minidump will be at the beginning of the stream.
+ // expected_size should be set to the stream's length as contained in
+ // the MDRawDirectory record or other identifying record. A class
+ // that implements MinidumpStream can compare expected_size to a
+ // known size as an integrity check.
+ virtual bool Read(uint32_t expected_size) = 0;
+
+ DISALLOW_COPY_AND_ASSIGN(MinidumpStream);
+};
+
+
+// MinidumpContext carries a CPU-specific MDRawContext structure, which
+// contains CPU context such as register states. Each thread has its
+// own context, and the exception record, if present, also has its own
+// context. Note that if the exception record is present, the context it
+// refers to is probably what the user wants to use for the exception
+// thread, instead of that thread's own context. The exception thread's
+// context (as opposed to the exception record's context) will contain
+// context for the exception handler (which performs minidump generation),
+// and not the context that caused the exception (which is probably what the
+// user wants).
+class MinidumpContext : public DumpContext {
+ public:
+ virtual ~MinidumpContext();
+
+ protected:
+ explicit MinidumpContext(Minidump* minidump);
+
+ private:
+ friend class MinidumpThread;
+ friend class MinidumpException;
+
+ bool Read(uint32_t expected_size);
+
+ // If the minidump contains a SYSTEM_INFO_STREAM, makes sure that the
+ // system info stream gives an appropriate CPU type matching the context
+ // CPU type in context_cpu_type. Returns false if the CPU type does not
+ // match. Returns true if the CPU type matches or if the minidump does
+ // not contain a system info stream.
+ bool CheckAgainstSystemInfo(uint32_t context_cpu_type);
+
+ // Refers to the Minidump object that is the ultimate parent of this
+ // Some MinidumpObjects are owned by other MinidumpObjects, but at the
+ // root of the ownership tree is always a Minidump. The Minidump object
+ // is kept here for access to its seeking and reading facilities, and
+ // for access to data about the minidump file itself, such as whether
+ // it should be byte-swapped.
+ Minidump* minidump_;
+
+ DISALLOW_COPY_AND_ASSIGN(MinidumpContext);
+};
+
+
+// MinidumpMemoryRegion does not wrap any MDRaw structure, and only contains
+// a reference to an MDMemoryDescriptor. This object is intended to wrap
+// portions of a minidump file that contain memory dumps. In normal
+// minidumps, each MinidumpThread owns a MinidumpMemoryRegion corresponding
+// to the thread's stack memory. MinidumpMemoryList also gives access to
+// memory regions in its list as MinidumpMemoryRegions. This class
+// adheres to MemoryRegion so that it may be used as a data provider to
+// the Stackwalker family of classes.
+class MinidumpMemoryRegion : public MinidumpObject,
+ public MemoryRegion {
+ public:
+ virtual ~MinidumpMemoryRegion();
+
+ static void set_max_bytes(uint32_t max_bytes) { max_bytes_ = max_bytes; }
+ static uint32_t max_bytes() { return max_bytes_; }
+
+ // Returns a pointer to the base of the memory region. Returns the
+ // cached value if available, otherwise, reads the minidump file and
+ // caches the memory region.
+ const uint8_t* GetMemory() const;
+
+ // The address of the base of the memory region.
+ uint64_t GetBase() const;
+
+ // The size, in bytes, of the memory region.
+ uint32_t GetSize() const;
+
+ // Frees the cached memory region, if cached.
+ void FreeMemory();
+
+ // Obtains the value of memory at the pointer specified by address.
+ bool GetMemoryAtAddress(uint64_t address, uint8_t* value) const;
+ bool GetMemoryAtAddress(uint64_t address, uint16_t* value) const;
+ bool GetMemoryAtAddress(uint64_t address, uint32_t* value) const;
+ bool GetMemoryAtAddress(uint64_t address, uint64_t* value) const;
+
+ // Print a human-readable representation of the object to stdout.
+ void Print() const;
+ void SetPrintMode(bool hexdump, unsigned int width);
+
+ protected:
+ explicit MinidumpMemoryRegion(Minidump* minidump);
+
+ private:
+ friend class MinidumpThread;
+ friend class MinidumpMemoryList;
+
+ // Identify the base address and size of the memory region, and the
+ // location it may be found in the minidump file.
+ void SetDescriptor(MDMemoryDescriptor* descriptor);
+
+ // Implementation for GetMemoryAtAddress
+ template<typename T> bool GetMemoryAtAddressInternal(uint64_t address,
+ T* value) const;
+
+ // Knobs for controlling display of memory printing.
+ bool hexdump_;
+ unsigned int hexdump_width_;
+
+ // The largest memory region that will be read from a minidump.
+ static uint32_t max_bytes_;
+
+ // Base address and size of the memory region, and its position in the
+ // minidump file.
+ MDMemoryDescriptor* descriptor_;
+
+ // Cached memory.
+ mutable vector<uint8_t>* memory_;
+};
+
+
+// MinidumpThread contains information about a thread of execution,
+// including a snapshot of the thread's stack and CPU context. For
+// the thread that caused an exception, the context carried by
+// MinidumpException is probably desired instead of the CPU context
+// provided here.
+// Note that a MinidumpThread may be valid() even if it does not
+// contain a memory region or context.
+class MinidumpThread : public MinidumpObject {
+ public:
+ virtual ~MinidumpThread();
+
+ const MDRawThread* thread() const { return valid_ ? &thread_ : NULL; }
+ // GetMemory may return NULL even if the MinidumpThread is valid,
+ // if the thread memory cannot be read.
+ virtual MinidumpMemoryRegion* GetMemory();
+ // Corresponds to win32's GetLastError function, which records the last
+ // error value set by the OS for this thread. A more useful error message
+ // can be produced by passing this value to FormatMessage:
+ //
+ // https://docs.microsoft.com/windows/win32/debug/retrieving-the-last-error-code
+ //
+ // The value may also be looked up in Microsoft's System Error Codes listing:
+ //
+ // https://docs.microsoft.com/windows/win32/debug/system-error-codes
+ virtual uint32_t GetLastError();
+ // GetContext may return NULL even if the MinidumpThread is valid.
+ virtual MinidumpContext* GetContext();
+
+ // The thread ID is used to determine if a thread is the exception thread,
+ // so a special getter is provided to retrieve this data from the
+ // MDRawThread structure. Returns false if the thread ID cannot be
+ // determined.
+ virtual bool GetThreadID(uint32_t *thread_id) const;
+
+ // Print a human-readable representation of the object to stdout.
+ void Print();
+
+ // Returns the start address of the thread stack memory region. Returns 0 if
+ // MinidumpThread is invalid. Note that this method can be called even when
+ // the thread memory cannot be read and GetMemory returns NULL.
+ virtual uint64_t GetStartOfStackMemoryRange() const;
+
+ protected:
+ explicit MinidumpThread(Minidump* minidump);
+
+ private:
+ // These objects are managed by MinidumpThreadList.
+ friend class MinidumpThreadList;
+
+ // This works like MinidumpStream::Read, but is driven by
+ // MinidumpThreadList. No size checking is done, because
+ // MinidumpThreadList handles that directly.
+ bool Read();
+
+ MDRawThread thread_;
+ MinidumpMemoryRegion* memory_;
+ MinidumpContext* context_;
+};
+
+
+// MinidumpThreadList contains all of the threads (as MinidumpThreads) in
+// a process.
+class MinidumpThreadList : public MinidumpStream {
+ public:
+ virtual ~MinidumpThreadList();
+
+ static void set_max_threads(uint32_t max_threads) {
+ max_threads_ = max_threads;
+ }
+ static uint32_t max_threads() { return max_threads_; }
+
+ virtual unsigned int thread_count() const {
+ return valid_ ? thread_count_ : 0;
+ }
+
+ // Sequential access to threads.
+ virtual MinidumpThread* GetThreadAtIndex(unsigned int index) const;
+
+ // Random access to threads.
+ MinidumpThread* GetThreadByID(uint32_t thread_id);
+
+ // Print a human-readable representation of the object to stdout.
+ void Print();
+
+ protected:
+ explicit MinidumpThreadList(Minidump* aMinidump);
+
+ private:
+ friend class Minidump;
+
+ typedef map<uint32_t, MinidumpThread*> IDToThreadMap;
+ typedef vector<MinidumpThread> MinidumpThreads;
+
+ static const uint32_t kStreamType = MD_THREAD_LIST_STREAM;
+
+ bool Read(uint32_t aExpectedSize) override;
+
+ // The largest number of threads that will be read from a minidump. The
+ // default is 256.
+ static uint32_t max_threads_;
+
+ // Access to threads using the thread ID as the key.
+ IDToThreadMap id_to_thread_map_;
+
+ // The list of threads.
+ MinidumpThreads* threads_;
+ uint32_t thread_count_;
+
+ DISALLOW_COPY_AND_ASSIGN(MinidumpThreadList);
+};
+
+
+// MinidumpModule wraps MDRawModule, which contains information about loaded
+// code modules. Access is provided to various data referenced indirectly
+// by MDRawModule, such as the module's name and a specification for where
+// to locate debugging information for the module.
+class MinidumpModule : public MinidumpObject,
+ public CodeModule {
+ public:
+ virtual ~MinidumpModule();
+
+ static void set_max_cv_bytes(uint32_t max_cv_bytes) {
+ max_cv_bytes_ = max_cv_bytes;
+ }
+ static uint32_t max_cv_bytes() { return max_cv_bytes_; }
+
+ static void set_max_misc_bytes(uint32_t max_misc_bytes) {
+ max_misc_bytes_ = max_misc_bytes;
+ }
+ static uint32_t max_misc_bytes() { return max_misc_bytes_; }
+
+ const MDRawModule* module() const { return valid_ ? &module_ : NULL; }
+
+ // CodeModule implementation
+ virtual uint64_t base_address() const {
+ return valid_ ? module_.base_of_image : static_cast<uint64_t>(-1);
+ }
+ virtual uint64_t size() const { return valid_ ? module_.size_of_image : 0; }
+ virtual string code_file() const;
+ virtual string code_identifier() const;
+ virtual string debug_file() const;
+ virtual string debug_identifier() const;
+ virtual string version() const;
+ virtual CodeModule* Copy() const;
+ virtual bool is_unloaded() const { return false; }
+
+ // Getter and setter for shrink_down_delta. This is used when the address
+ // range for a module is shrunk down due to address range conflicts with
+ // other modules. The base_address and size fields are not updated and they
+ // should always reflect the original values (reported in the minidump).
+ virtual uint64_t shrink_down_delta() const;
+ virtual void SetShrinkDownDelta(uint64_t shrink_down_delta);
+
+ // The CodeView record, which contains information to locate the module's
+ // debugging information (pdb). This is returned as uint8_t* because
+ // the data can be of types MDCVInfoPDB20* or MDCVInfoPDB70*, or it may be
+ // of a type unknown to Breakpad, in which case the raw data will still be
+ // returned but no byte-swapping will have been performed. Check the
+ // record's signature in the first four bytes to differentiate between
+ // the various types. Current toolchains generate modules which carry
+ // MDCVInfoPDB70 by default. Returns a pointer to the CodeView record on
+ // success, and NULL on failure. On success, the optional |size| argument
+ // is set to the size of the CodeView record.
+ const uint8_t* GetCVRecord(uint32_t* size);
+
+ // The miscellaneous debug record, which is obsolete. Current toolchains
+ // do not generate this type of debugging information (dbg), and this
+ // field is not expected to be present. Returns a pointer to the debugging
+ // record on success, and NULL on failure. On success, the optional |size|
+ // argument is set to the size of the debugging record.
+ const MDImageDebugMisc* GetMiscRecord(uint32_t* size);
+
+ // Print a human-readable representation of the object to stdout.
+ void Print();
+
+ private:
+ // These objects are managed by MinidumpModuleList.
+ friend class MinidumpModuleList;
+
+ explicit MinidumpModule(Minidump* minidump);
+
+ // This works like MinidumpStream::Read, but is driven by
+ // MinidumpModuleList. No size checking is done, because
+ // MinidumpModuleList handles that directly.
+ bool Read();
+
+ // Reads indirectly-referenced data, including the module name, CodeView
+ // record, and miscellaneous debugging record. This is necessary to allow
+ // MinidumpModuleList to fully construct MinidumpModule objects without
+ // requiring seeks to read a contiguous set of MinidumpModule objects.
+ // All auxiliary data should be available when Read is called, in order to
+ // allow the CodeModule getters to be const methods.
+ bool ReadAuxiliaryData();
+
+ // The largest number of bytes that will be read from a minidump for a
+ // CodeView record or miscellaneous debugging record, respectively. The
+ // default for each is 1024.
+ static uint32_t max_cv_bytes_;
+ static uint32_t max_misc_bytes_;
+
+ // True after a successful Read. This is different from valid_, which is
+ // not set true until ReadAuxiliaryData also completes successfully.
+ // module_valid_ is only used by ReadAuxiliaryData and the functions it
+ // calls to determine whether the object is ready for auxiliary data to
+ // be read.
+ bool module_valid_;
+
+ // True if debug info was read from the module. Certain modules
+ // may contain debug records in formats we don't support,
+ // so we can just set this to false to ignore them.
+ bool has_debug_info_;
+
+ MDRawModule module_;
+
+ // Cached module name.
+ const string* name_;
+
+ // Cached CodeView record - this is MDCVInfoPDB20 or (likely)
+ // MDCVInfoPDB70, or possibly something else entirely. Stored as a uint8_t
+ // because the structure contains a variable-sized string and its exact
+ // size cannot be known until it is processed.
+ vector<uint8_t>* cv_record_;
+
+ // If cv_record_ is present, cv_record_signature_ contains a copy of the
+ // CodeView record's first four bytes, for ease of determinining the
+ // type of structure that cv_record_ contains.
+ uint32_t cv_record_signature_;
+
+ // Cached MDImageDebugMisc (usually not present), stored as uint8_t
+ // because the structure contains a variable-sized string and its exact
+ // size cannot be known until it is processed.
+ vector<uint8_t>* misc_record_;
+};
+
+
+// MinidumpModuleList contains all of the loaded code modules for a process
+// in the form of MinidumpModules. It maintains a map of these modules
+// so that it may easily provide a code module corresponding to a specific
+// address.
+class MinidumpModuleList : public MinidumpStream,
+ public CodeModules {
+ public:
+ virtual ~MinidumpModuleList();
+
+ static void set_max_modules(uint32_t max_modules) {
+ max_modules_ = max_modules;
+ }
+ static uint32_t max_modules() { return max_modules_; }
+
+ // CodeModules implementation.
+ virtual unsigned int module_count() const {
+ return valid_ ? module_count_ : 0;
+ }
+ virtual const MinidumpModule* GetModuleForAddress(uint64_t address) const;
+ virtual const MinidumpModule* GetMainModule() const;
+ virtual const MinidumpModule* GetModuleAtSequence(
+ unsigned int sequence) const;
+ virtual const MinidumpModule* GetModuleAtIndex(unsigned int index) const;
+ virtual const CodeModules* Copy() const;
+
+ // Returns a vector of all modules which address ranges needed to be shrunk
+ // down due to address range conflicts with other modules.
+ virtual vector<linked_ptr<const CodeModule> > GetShrunkRangeModules() const;
+
+ // Print a human-readable representation of the object to stdout.
+ void Print();
+
+ protected:
+ explicit MinidumpModuleList(Minidump* minidump);
+
+ private:
+ friend class Minidump;
+
+ typedef vector<MinidumpModule> MinidumpModules;
+
+ static const uint32_t kStreamType = MD_MODULE_LIST_STREAM;
+
+ bool Read(uint32_t expected_size);
+
+ bool StoreRange(const MinidumpModule& module,
+ uint64_t base_address,
+ uint32_t module_index,
+ uint32_t module_count,
+ bool is_android);
+
+ // The largest number of modules that will be read from a minidump. The
+ // default is 1024.
+ static uint32_t max_modules_;
+
+ // Access to modules using addresses as the key.
+ RangeMap<uint64_t, unsigned int> *range_map_;
+
+ MinidumpModules *modules_;
+ uint32_t module_count_;
+
+ DISALLOW_COPY_AND_ASSIGN(MinidumpModuleList);
+};
+
+
+// MinidumpMemoryList corresponds to a minidump's MEMORY_LIST_STREAM stream,
+// which references the snapshots of all of the memory regions contained
+// within the minidump. For a normal minidump, this includes stack memory
+// (also referenced by each MinidumpThread, in fact, the MDMemoryDescriptors
+// here and in MDRawThread both point to exactly the same data in a
+// minidump file, conserving space), as well as a 256-byte snapshot of memory
+// surrounding the instruction pointer in the case of an exception. Other
+// types of minidumps may contain significantly more memory regions. Full-
+// memory minidumps contain all of a process' mapped memory.
+class MinidumpMemoryList : public MinidumpStream {
+ public:
+ virtual ~MinidumpMemoryList();
+
+ static void set_max_regions(uint32_t max_regions) {
+ max_regions_ = max_regions;
+ }
+ static uint32_t max_regions() { return max_regions_; }
+
+ unsigned int region_count() const { return valid_ ? region_count_ : 0; }
+
+ // Sequential access to memory regions.
+ MinidumpMemoryRegion* GetMemoryRegionAtIndex(unsigned int index);
+
+ // Random access to memory regions. Returns the region encompassing
+ // the address identified by address.
+ virtual MinidumpMemoryRegion* GetMemoryRegionForAddress(uint64_t address);
+
+ // Print a human-readable representation of the object to stdout.
+ void Print();
+
+ private:
+ friend class Minidump;
+ friend class MockMinidumpMemoryList;
+
+ typedef vector<MDMemoryDescriptor> MemoryDescriptors;
+ typedef vector<MinidumpMemoryRegion> MemoryRegions;
+
+ static const uint32_t kStreamType = MD_MEMORY_LIST_STREAM;
+
+ explicit MinidumpMemoryList(Minidump* minidump);
+
+ bool Read(uint32_t expected_size) override;
+
+ // The largest number of memory regions that will be read from a minidump.
+ // The default is 256.
+ static uint32_t max_regions_;
+
+ // Access to memory regions using addresses as the key.
+ RangeMap<uint64_t, unsigned int> *range_map_;
+
+ // The list of descriptors. This is maintained separately from the list
+ // of regions, because MemoryRegion doesn't own its MemoryDescriptor, it
+ // maintains a pointer to it. descriptors_ provides the storage for this
+ // purpose.
+ MemoryDescriptors *descriptors_;
+
+ // The list of regions.
+ MemoryRegions *regions_;
+ uint32_t region_count_;
+
+ DISALLOW_COPY_AND_ASSIGN(MinidumpMemoryList);
+};
+
+
+// MinidumpException wraps MDRawExceptionStream, which contains information
+// about the exception that caused the minidump to be generated, if the
+// minidump was generated in an exception handler called as a result of an
+// exception. It also provides access to a MinidumpContext object, which
+// contains the CPU context for the exception thread at the time the exception
+// occurred.
+class MinidumpException : public MinidumpStream {
+ public:
+ virtual ~MinidumpException();
+
+ const MDRawExceptionStream* exception() const {
+ return valid_ ? &exception_ : NULL;
+ }
+
+ // The thread ID is used to determine if a thread is the exception thread,
+ // so a special getter is provided to retrieve this data from the
+ // MDRawExceptionStream structure. Returns false if the thread ID cannot
+ // be determined.
+ bool GetThreadID(uint32_t *thread_id) const;
+
+ MinidumpContext* GetContext();
+
+ // Print a human-readable representation of the object to stdout.
+ void Print();
+
+ private:
+ friend class Minidump;
+
+ static const uint32_t kStreamType = MD_EXCEPTION_STREAM;
+
+ explicit MinidumpException(Minidump* minidump);
+
+ bool Read(uint32_t expected_size) override;
+
+ MDRawExceptionStream exception_;
+ MinidumpContext* context_;
+
+ DISALLOW_COPY_AND_ASSIGN(MinidumpException);
+};
+
+// MinidumpAssertion wraps MDRawAssertionInfo, which contains information
+// about an assertion that caused the minidump to be generated.
+class MinidumpAssertion : public MinidumpStream {
+ public:
+ virtual ~MinidumpAssertion();
+
+ const MDRawAssertionInfo* assertion() const {
+ return valid_ ? &assertion_ : NULL;
+ }
+
+ string expression() const {
+ return valid_ ? expression_ : "";
+ }
+
+ string function() const {
+ return valid_ ? function_ : "";
+ }
+
+ string file() const {
+ return valid_ ? file_ : "";
+ }
+
+ // Print a human-readable representation of the object to stdout.
+ void Print();
+
+ private:
+ friend class Minidump;
+
+ static const uint32_t kStreamType = MD_ASSERTION_INFO_STREAM;
+
+ explicit MinidumpAssertion(Minidump* minidump);
+
+ bool Read(uint32_t expected_size) override;
+
+ MDRawAssertionInfo assertion_;
+ string expression_;
+ string function_;
+ string file_;
+
+ DISALLOW_COPY_AND_ASSIGN(MinidumpAssertion);
+};
+
+
+// MinidumpSystemInfo wraps MDRawSystemInfo and provides information about
+// the system on which the minidump was generated. See also MinidumpMiscInfo.
+class MinidumpSystemInfo : public MinidumpStream {
+ public:
+ virtual ~MinidumpSystemInfo();
+
+ const MDRawSystemInfo* system_info() const {
+ return valid_ ? &system_info_ : NULL;
+ }
+
+ // GetOS and GetCPU return textual representations of the operating system
+ // and CPU that produced the minidump. Unlike most other Minidump* methods,
+ // they return string objects, not weak pointers. Defined values for
+ // GetOS() are "mac", "windows", and "linux". Defined values for GetCPU
+ // are "x86" and "ppc". These methods return an empty string when their
+ // values are unknown.
+ string GetOS();
+ string GetCPU();
+
+ // I don't know what CSD stands for, but this field is documented as
+ // returning a textual representation of the OS service pack. On other
+ // platforms, this provides additional information about an OS version
+ // level beyond major.minor.micro. Returns NULL if unknown.
+ const string* GetCSDVersion();
+
+ // If a CPU vendor string can be determined, returns a pointer to it,
+ // otherwise, returns NULL. CPU vendor strings can be determined from
+ // x86 CPUs with CPUID 0.
+ const string* GetCPUVendor();
+
+ // Print a human-readable representation of the object to stdout.
+ void Print();
+
+ protected:
+ explicit MinidumpSystemInfo(Minidump* minidump);
+ MDRawSystemInfo system_info_;
+
+ // Textual representation of the OS service pack, for minidumps produced
+ // by MiniDumpWriteDump on Windows.
+ const string* csd_version_;
+
+ private:
+ friend class Minidump;
+
+ static const uint32_t kStreamType = MD_SYSTEM_INFO_STREAM;
+
+ bool Read(uint32_t expected_size) override;
+
+ // A string identifying the CPU vendor, if known.
+ const string* cpu_vendor_;
+
+ DISALLOW_COPY_AND_ASSIGN(MinidumpSystemInfo);
+};
+
+
+// MinidumpUnloadedModule wraps MDRawUnloadedModule
+class MinidumpUnloadedModule : public MinidumpObject,
+ public CodeModule {
+ public:
+ ~MinidumpUnloadedModule() override;
+
+ const MDRawUnloadedModule* module() const {
+ return valid_ ? &unloaded_module_ : NULL;
+ }
+
+ // CodeModule implementation
+ uint64_t base_address() const override {
+ return valid_ ? unloaded_module_.base_of_image : 0;
+ }
+ uint64_t size() const override {
+ return valid_ ? unloaded_module_.size_of_image : 0;
+ }
+ string code_file() const override;
+ string code_identifier() const override;
+ string debug_file() const override;
+ string debug_identifier() const override;
+ string version() const override;
+ CodeModule* Copy() const override;
+ bool is_unloaded() const override { return true; }
+ uint64_t shrink_down_delta() const override;
+ void SetShrinkDownDelta(uint64_t shrink_down_delta) override;
+
+ // Print a human-readable representation of the object to stdout.
+ void Print();
+
+ protected:
+ explicit MinidumpUnloadedModule(Minidump* minidump);
+
+ private:
+ // These objects are managed by MinidumpUnloadedModuleList
+ friend class MinidumpUnloadedModuleList;
+
+ // This works like MinidumpStream::Read, but is driven by
+ // MinidumpUnloadedModuleList.
+ bool Read(uint32_t expected_size);
+
+ // Reads the module name. This is done separately from Read to
+ // allow contiguous reading of code modules by MinidumpUnloadedModuleList.
+ bool ReadAuxiliaryData();
+
+ // True after a successful Read. This is different from valid_, which
+ // is not set true until ReadAuxiliaryData also completes successfully.
+ // module_valid_ is only used by ReadAuxiliaryData and the functions it
+ // calls to determine whether the object is ready for auxiliary data to
+ // be read.
+ bool module_valid_;
+
+ MDRawUnloadedModule unloaded_module_;
+
+ // Cached module name
+ const string* name_;
+};
+
+
+// MinidumpUnloadedModuleList contains all the unloaded code modules for a
+// process in the form of MinidumpUnloadedModules. It maintains a map of
+// these modules so that it may easily provide a code module corresponding
+// to a specific address. If multiple modules in the list have identical
+// ranges, only the first module encountered is recorded in the range map.
+class MinidumpUnloadedModuleList : public MinidumpStream,
+ public CodeModules {
+ public:
+ ~MinidumpUnloadedModuleList() override;
+
+ static void set_max_modules(uint32_t max_modules) {
+ max_modules_ = max_modules;
+ }
+ static uint32_t max_modules() { return max_modules_; }
+
+ // CodeModules implementation.
+ unsigned int module_count() const override {
+ return valid_ ? module_count_ : 0;
+ }
+ const MinidumpUnloadedModule*
+ GetModuleForAddress(uint64_t address) const override;
+ const MinidumpUnloadedModule* GetMainModule() const override;
+ const MinidumpUnloadedModule*
+ GetModuleAtSequence(unsigned int sequence) const override;
+ const MinidumpUnloadedModule*
+ GetModuleAtIndex(unsigned int index) const override;
+ const CodeModules* Copy() const override;
+ vector<linked_ptr<const CodeModule>> GetShrunkRangeModules() const override;
+
+ // Print a human-readable representation of the object to stdout.
+ void Print();
+
+ protected:
+ explicit MinidumpUnloadedModuleList(Minidump* minidump_);
+
+ private:
+ friend class Minidump;
+
+ typedef vector<MinidumpUnloadedModule> MinidumpUnloadedModules;
+
+ static const uint32_t kStreamType = MD_UNLOADED_MODULE_LIST_STREAM;
+
+ bool Read(uint32_t expected_size_) override;
+
+ // The largest number of modules that will be read from a minidump. The
+ // default is 1024.
+ static uint32_t max_modules_;
+
+ // Access to module indices using addresses as the key.
+ RangeMap<uint64_t, unsigned int> *range_map_;
+
+ MinidumpUnloadedModules *unloaded_modules_;
+ uint32_t module_count_;
+
+ DISALLOW_COPY_AND_ASSIGN(MinidumpUnloadedModuleList);
+};
+
+
+// MinidumpMiscInfo wraps MDRawMiscInfo and provides information about
+// the process that generated the minidump, and optionally additional system
+// information. See also MinidumpSystemInfo.
+class MinidumpMiscInfo : public MinidumpStream {
+ public:
+ const MDRawMiscInfo* misc_info() const {
+ return valid_ ? &misc_info_ : NULL;
+ }
+
+ // Print a human-readable representation of the object to stdout.
+ void Print();
+
+ private:
+ friend class Minidump;
+ friend class TestMinidumpMiscInfo;
+
+ static const uint32_t kStreamType = MD_MISC_INFO_STREAM;
+
+ explicit MinidumpMiscInfo(Minidump* minidump_);
+
+ bool Read(uint32_t expected_size_) override;
+
+ MDRawMiscInfo misc_info_;
+
+ // Populated by Read. Contains the converted strings from the corresponding
+ // UTF-16 fields in misc_info_
+ string standard_name_;
+ string daylight_name_;
+ string build_string_;
+ string dbg_bld_str_;
+
+ DISALLOW_COPY_AND_ASSIGN(MinidumpMiscInfo);
+};
+
+
+// MinidumpBreakpadInfo wraps MDRawBreakpadInfo, which is an optional stream in
+// a minidump that provides additional information about the process state
+// at the time the minidump was generated.
+class MinidumpBreakpadInfo : public MinidumpStream {
+ public:
+ const MDRawBreakpadInfo* breakpad_info() const {
+ return valid_ ? &breakpad_info_ : NULL;
+ }
+
+ // These thread IDs are used to determine if threads deserve special
+ // treatment, so special getters are provided to retrieve this data from
+ // the MDRawBreakpadInfo structure. The getters return false if the thread
+ // IDs cannot be determined.
+ bool GetDumpThreadID(uint32_t *thread_id) const;
+ bool GetRequestingThreadID(uint32_t *thread_id) const;
+
+ // Print a human-readable representation of the object to stdout.
+ void Print();
+
+ private:
+ friend class Minidump;
+
+ static const uint32_t kStreamType = MD_BREAKPAD_INFO_STREAM;
+
+ explicit MinidumpBreakpadInfo(Minidump* minidump_);
+
+ bool Read(uint32_t expected_size_) override;
+
+ MDRawBreakpadInfo breakpad_info_;
+
+ DISALLOW_COPY_AND_ASSIGN(MinidumpBreakpadInfo);
+};
+
+// MinidumpMemoryInfo wraps MDRawMemoryInfo, which provides information
+// about mapped memory regions in a process, including their ranges
+// and protection.
+class MinidumpMemoryInfo : public MinidumpObject {
+ public:
+ const MDRawMemoryInfo* info() const { return valid_ ? &memory_info_ : NULL; }
+
+ // The address of the base of the memory region.
+ uint64_t GetBase() const { return valid_ ? memory_info_.base_address : 0; }
+
+ // The size, in bytes, of the memory region.
+ uint64_t GetSize() const { return valid_ ? memory_info_.region_size : 0; }
+
+ // Return true if the memory protection allows execution.
+ bool IsExecutable() const;
+
+ // Return true if the memory protection allows writing.
+ bool IsWritable() const;
+
+ // Print a human-readable representation of the object to stdout.
+ void Print();
+
+ private:
+ // These objects are managed by MinidumpMemoryInfoList.
+ friend class MinidumpMemoryInfoList;
+
+ explicit MinidumpMemoryInfo(Minidump* minidump_);
+
+ // This works like MinidumpStream::Read, but is driven by
+ // MinidumpMemoryInfoList. No size checking is done, because
+ // MinidumpMemoryInfoList handles that directly.
+ bool Read();
+
+ MDRawMemoryInfo memory_info_;
+};
+
+// MinidumpMemoryInfoList contains a list of information about
+// mapped memory regions for a process in the form of MDRawMemoryInfo.
+// It maintains a map of these structures so that it may easily provide
+// info corresponding to a specific address.
+class MinidumpMemoryInfoList : public MinidumpStream {
+ public:
+ virtual ~MinidumpMemoryInfoList();
+
+ unsigned int info_count() const { return valid_ ? info_count_ : 0; }
+
+ const MinidumpMemoryInfo* GetMemoryInfoForAddress(uint64_t address) const;
+ const MinidumpMemoryInfo* GetMemoryInfoAtIndex(unsigned int index) const;
+
+ // Print a human-readable representation of the object to stdout.
+ void Print();
+
+ private:
+ friend class Minidump;
+
+ typedef vector<MinidumpMemoryInfo> MinidumpMemoryInfos;
+
+ static const uint32_t kStreamType = MD_MEMORY_INFO_LIST_STREAM;
+
+ explicit MinidumpMemoryInfoList(Minidump* minidump_);
+
+ bool Read(uint32_t expected_size) override;
+
+ // Access to memory info using addresses as the key.
+ RangeMap<uint64_t, unsigned int> *range_map_;
+
+ MinidumpMemoryInfos* infos_;
+ uint32_t info_count_;
+
+ DISALLOW_COPY_AND_ASSIGN(MinidumpMemoryInfoList);
+};
+
+// MinidumpLinuxMaps wraps information about a single mapped memory region
+// from /proc/self/maps.
+class MinidumpLinuxMaps : public MinidumpObject {
+ public:
+ // The memory address of the base of the mapped region.
+ uint64_t GetBase() const { return valid_ ? region_.start : 0; }
+ // The size of the mapped region.
+ uint64_t GetSize() const { return valid_ ? region_.end - region_.start : 0; }
+
+ // The permissions of the mapped region.
+ bool IsReadable() const {
+ return valid_ ? region_.permissions & MappedMemoryRegion::READ : false;
+ }
+ bool IsWriteable() const {
+ return valid_ ? region_.permissions & MappedMemoryRegion::WRITE : false;
+ }
+ bool IsExecutable() const {
+ return valid_ ? region_.permissions & MappedMemoryRegion::EXECUTE : false;
+ }
+ bool IsPrivate() const {
+ return valid_ ? region_.permissions & MappedMemoryRegion::PRIVATE : false;
+ }
+
+ // The offset of the mapped region.
+ uint64_t GetOffset() const { return valid_ ? region_.offset : 0; }
+
+ // The major device number.
+ uint8_t GetMajorDevice() const { return valid_ ? region_.major_device : 0; }
+ // The minor device number.
+ uint8_t GetMinorDevice() const { return valid_ ? region_.minor_device : 0; }
+
+ // The inode of the mapped region.
+ uint64_t GetInode() const { return valid_ ? region_.inode : 0; }
+
+ // The pathname of the mapped region.
+ const string GetPathname() const { return valid_ ? region_.path : ""; }
+
+ // Print the contents of this mapping.
+ void Print() const;
+
+ private:
+ // These objects are managed by MinidumpLinuxMapsList.
+ friend class MinidumpLinuxMapsList;
+
+ // This caller owns the pointer.
+ explicit MinidumpLinuxMaps(Minidump *minidump);
+
+ // The memory region struct that this class wraps.
+ MappedMemoryRegion region_;
+
+ DISALLOW_COPY_AND_ASSIGN(MinidumpLinuxMaps);
+};
+
+// MinidumpLinuxMapsList corresponds to the Linux-exclusive MD_LINUX_MAPS
+// stream, which contains the contents of /prod/self/maps, which contains
+// the mapped memory regions and their access permissions.
+class MinidumpLinuxMapsList : public MinidumpStream {
+ public:
+ virtual ~MinidumpLinuxMapsList();
+
+ // Get number of mappings.
+ unsigned int get_maps_count() const { return valid_ ? maps_count_ : 0; }
+
+ // Get mapping at the given memory address. The caller owns the pointer.
+ const MinidumpLinuxMaps *GetLinuxMapsForAddress(uint64_t address) const;
+ // Get mapping at the given index. The caller owns the pointer.
+ const MinidumpLinuxMaps *GetLinuxMapsAtIndex(unsigned int index) const;
+
+ // Print the contents of /proc/self/maps to stdout.
+ void Print() const;
+
+ private:
+ friend class Minidump;
+
+ typedef vector<MinidumpLinuxMaps *> MinidumpLinuxMappings;
+
+ static const uint32_t kStreamType = MD_LINUX_MAPS;
+
+ // The caller owns the pointer.
+ explicit MinidumpLinuxMapsList(Minidump *minidump);
+
+ // Read and load the contents of the process mapping data.
+ // The stream should have data in the form of /proc/self/maps.
+ // This method returns whether the stream was read successfully.
+ bool Read(uint32_t expected_size) override;
+
+ // The list of individual mappings.
+ MinidumpLinuxMappings *maps_;
+ // The number of mappings.
+ uint32_t maps_count_;
+
+ DISALLOW_COPY_AND_ASSIGN(MinidumpLinuxMapsList);
+};
+
+// MinidumpCrashpadInfo wraps MDRawCrashpadInfo, which is an optional stream in
+// a minidump that provides additional information about the process state
+// at the time the minidump was generated.
+class MinidumpCrashpadInfo : public MinidumpStream {
+ public:
+ const MDRawCrashpadInfo* crashpad_info() const {
+ return valid_ ? &crashpad_info_ : NULL;
+ }
+
+ // Print a human-readable representation of the object to stdout.
+ void Print();
+
+ private:
+ friend class Minidump;
+
+ static const uint32_t kStreamType = MD_CRASHPAD_INFO_STREAM;
+
+ explicit MinidumpCrashpadInfo(Minidump* minidump_);
+
+ bool Read(uint32_t expected_size);
+
+ MDRawCrashpadInfo crashpad_info_;
+ std::vector<uint32_t> module_crashpad_info_links_;
+ std::vector<MDRawModuleCrashpadInfo> module_crashpad_info_;
+ std::vector<std::vector<std::string>> module_crashpad_info_list_annotations_;
+ std::vector<std::map<std::string, std::string>>
+ module_crashpad_info_simple_annotations_;
+ std::map<std::string, std::string> simple_annotations_;
+};
+
+// MinidumpMacCrashInfo wraps MDRawMacCrashInfo. It's an optional stream
+// in a minidump that records information from the __DATA,__crash_info
+// section of every module in the crashing process that contains one, and
+// which isn't empty of useful information. Only present on macOS.
+
+// Friendly wrapper for the information in MDRawMacCrashInfoRecord.
+typedef struct crash_info_record {
+ string module_path;
+ unsigned long version;
+ string message;
+ string signature_string;
+ string backtrace;
+ string message2;
+ unsigned long long thread;
+ unsigned int dialog_mode;
+ long long abort_cause; // Only valid when 'version' > 4
+ crash_info_record()
+ : version(0), thread(0), dialog_mode(0), abort_cause(0)
+ {}
+} crash_info_record_t;
+
+class MinidumpMacCrashInfo : public MinidumpStream {
+ public:
+ // A human-readable representation of the data from the __DATA,__crash_info
+ // sections in all of the crashing process's modules that have one, if
+ // it's not empty of useful data. Suitable for use by "minidump_stackwalk".
+ string description() const { return description_; }
+ // A "machine-readable" copy of the same information, suitable for use by
+ // "minidump_stalkwalk -m".
+ vector<crash_info_record_t> const records() {
+ return records_;
+ }
+
+ // Print a human-readable representation of the object to stdout.
+ void Print();
+
+ private:
+ friend class Minidump;
+
+ static const uint32_t kStreamType = MOZ_MACOS_CRASH_INFO_STREAM;
+
+ explicit MinidumpMacCrashInfo(Minidump* minidump_);
+
+ bool ReadCrashInfoRecord(MDLocationDescriptor location,
+ uint32_t record_start_size);
+ bool Read(uint32_t expected_size);
+
+ string description_;
+ vector<crash_info_record_t> records_;
+};
+
+// MinidumpThreadName wraps MDRawThreadName
+class MinidumpThreadName : public MinidumpObject {
+ public:
+ ~MinidumpThreadName() override;
+
+ const MDRawThreadName* thread_name() const {
+ if (valid_) {
+ return &thread_name_;
+ }
+
+ return NULL;
+ }
+
+ uint32_t thread_id() const {
+ if (valid_) {
+ return thread_name_.thread_id;
+ }
+
+ return 0;
+ }
+
+ string name() const;
+
+ // Print a human-readable representation of the object to stdout.
+ void Print();
+
+ protected:
+ explicit MinidumpThreadName(Minidump* minidump);
+
+ private:
+ // These objects are managed by MinidumpThreadNameList
+ friend class MinidumpThreadNamesList;
+
+ // This works like MinidumpStream::Read, but is driven by
+ // MinidumpThreadNameList.
+ bool Read(uint32_t expected_size);
+
+ // Reads the thread name. This is done separately from Read to
+ // allow contiguous reading of thread names by MinidumpThreadNameList.
+ bool ReadAuxiliaryData();
+
+ bool valid_;
+ MDRawThreadName thread_name_;
+ const string* name_;
+};
+
+
+// MinidumpThreadNamesList contains all the names for threads in a process
+// in the form of MinidumpThreadNames.
+class MinidumpThreadNamesList : public MinidumpStream {
+ public:
+ ~MinidumpThreadNamesList() override;
+
+ unsigned int name_count() const {
+ return valid_ ? name_count_ : 0;
+ }
+
+ const string GetNameForThreadId(uint32_t thread_id) const;
+
+ // Print a human-readable representation of the object to stdout.
+ void Print();
+
+ protected:
+ explicit MinidumpThreadNamesList(Minidump* minidump_);
+
+ private:
+ friend class Minidump;
+
+ typedef vector<MinidumpThreadName> MinidumpThreadNames;
+
+ static const uint32_t kStreamType = MD_THREAD_NAMES_STREAM;
+
+ bool Read(uint32_t expected_size_) override;
+
+ MinidumpThreadNames* thread_names_;
+ uint32_t name_count_;
+ bool valid_;
+
+ DISALLOW_COPY_AND_ASSIGN(MinidumpThreadNamesList);
+};
+
+// Minidump is the user's interface to a minidump file. It wraps MDRawHeader
+// and provides access to the minidump's top-level stream directory.
+class Minidump {
+ public:
+ // path is the pathname of a file containing the minidump.
+ explicit Minidump(const string& path,
+ bool hexdump=false,
+ unsigned int hexdump_width=16);
+ // input is an istream wrapping minidump data. Minidump holds a
+ // weak pointer to input, and the caller must ensure that the stream
+ // is valid as long as the Minidump object is.
+ explicit Minidump(std::istream& input);
+
+ virtual ~Minidump();
+
+ // path may be empty if the minidump was not opened from a file
+ virtual string path() const {
+ return path_;
+ }
+ static void set_max_streams(uint32_t max_streams) {
+ max_streams_ = max_streams;
+ }
+ static uint32_t max_streams() { return max_streams_; }
+
+ static void set_max_string_length(uint32_t max_string_length) {
+ max_string_length_ = max_string_length;
+ }
+ static uint32_t max_string_length() { return max_string_length_; }
+
+ virtual const MDRawHeader* header() const { return valid_ ? &header_ : NULL; }
+
+ // Reads the CPU information from the system info stream and generates the
+ // appropriate CPU flags. The returned context_cpu_flags are the same as
+ // if the CPU type bits were set in the context_flags of a context record.
+ // On success, context_cpu_flags will have the flags that identify the CPU.
+ // If a system info stream is missing, context_cpu_flags will be 0.
+ // Returns true if the current position in the stream was not changed.
+ // Returns false when the current location in the stream was changed and the
+ // attempt to restore the original position failed.
+ bool GetContextCPUFlagsFromSystemInfo(uint32_t* context_cpu_flags);
+
+ // Reads the minidump file's header and top-level stream directory.
+ // The minidump is expected to be positioned at the beginning of the
+ // header. Read() sets up the stream list and map, and validates the
+ // Minidump object.
+ virtual bool Read();
+
+ // The next set of methods are stubs that call GetStream. They exist to
+ // force code generation of the templatized API within the module, and
+ // to avoid exposing an ugly API (GetStream needs to accept a garbage
+ // parameter).
+ virtual MinidumpThreadList* GetThreadList();
+ virtual MinidumpModuleList* GetModuleList();
+ virtual MinidumpMemoryList* GetMemoryList();
+ virtual MinidumpException* GetException();
+ virtual MinidumpAssertion* GetAssertion();
+ virtual MinidumpSystemInfo* GetSystemInfo();
+ virtual MinidumpUnloadedModuleList* GetUnloadedModuleList();
+ virtual MinidumpMiscInfo* GetMiscInfo();
+ virtual MinidumpBreakpadInfo* GetBreakpadInfo();
+ virtual MinidumpMemoryInfoList* GetMemoryInfoList();
+ MinidumpCrashpadInfo* GetCrashpadInfo();
+ MinidumpMacCrashInfo* GetMacCrashInfo();
+ MinidumpThreadNamesList* GetThreadNamesList();
+
+ // The next method also calls GetStream, but is exclusive for Linux dumps.
+ virtual MinidumpLinuxMapsList *GetLinuxMapsList();
+
+ // The next set of methods are provided for users who wish to access
+ // data in minidump files directly, while leveraging the rest of
+ // this class and related classes to handle the basic minidump
+ // structure and known stream types.
+
+ unsigned int GetDirectoryEntryCount() const {
+ return valid_ ? header_.stream_count : 0;
+ }
+ const MDRawDirectory* GetDirectoryEntryAtIndex(unsigned int index) const;
+
+ // The next 2 methods are lower-level I/O routines. They use fd_.
+
+ // Reads count bytes from the minidump at the current position into
+ // the storage area pointed to by bytes. bytes must be of sufficient
+ // size. After the read, the file position is advanced by count.
+ bool ReadBytes(void* bytes, size_t count);
+
+ // Sets the position of the minidump file to offset.
+ bool SeekSet(off_t offset);
+
+ // Returns the current position of the minidump file.
+ off_t Tell();
+
+ // Medium-level I/O routines.
+
+ // ReadString returns a string which is owned by the caller! offset
+ // specifies the offset that a length-encoded string is stored at in the
+ // minidump file.
+ string* ReadString(off_t offset);
+
+ bool ReadUTF8String(off_t offset, string* string_utf8);
+
+ bool ReadStringList(off_t offset, std::vector<std::string>* string_list);
+
+ bool ReadSimpleStringDictionary(
+ off_t offset,
+ std::map<std::string, std::string>* simple_string_dictionary);
+
+ // SeekToStreamType positions the file at the beginning of a stream
+ // identified by stream_type, and informs the caller of the stream's
+ // length by setting *stream_length. Because stream_map maps each stream
+ // type to only one stream in the file, this might mislead the user into
+ // thinking that the stream that this seeks to is the only stream with
+ // type stream_type. That can't happen for streams that these classes
+ // deal with directly, because they're only supposed to be present in the
+ // file singly, and that's verified when stream_map_ is built. Users who
+ // are looking for other stream types should be aware of this
+ // possibility, and consider using GetDirectoryEntryAtIndex (possibly
+ // with GetDirectoryEntryCount) if expecting multiple streams of the same
+ // type in a single minidump file.
+ bool SeekToStreamType(uint32_t stream_type, uint32_t* stream_length);
+
+ bool swap() const { return valid_ ? swap_ : false; }
+
+ bool is_big_endian() const { return valid_ ? is_big_endian_ : false; }
+
+ // Print a human-readable representation of the object to stdout.
+ void Print();
+
+ // Is the OS Android.
+ bool IsAndroid();
+
+ // Determines the platform where the minidump was produced. |platform| is
+ // valid iff this method returns true.
+ bool GetPlatform(MDOSPlatform* platform);
+
+ // Get current hexdump display settings.
+ unsigned int HexdumpMode() const { return hexdump_ ? hexdump_width_ : 0; }
+
+ private:
+ // MinidumpStreamInfo is used in the MinidumpStreamMap. It lets
+ // the Minidump object locate interesting streams quickly, and
+ // provides a convenient place to stash MinidumpStream objects.
+ struct MinidumpStreamInfo {
+ MinidumpStreamInfo() : stream_index(0), stream(NULL) {}
+ ~MinidumpStreamInfo() { delete stream; }
+
+ // Index into the MinidumpDirectoryEntries vector
+ unsigned int stream_index;
+
+ // Pointer to the stream if cached, or NULL if not yet populated
+ MinidumpStream* stream;
+ };
+
+ typedef vector<MDRawDirectory> MinidumpDirectoryEntries;
+ typedef map<uint32_t, MinidumpStreamInfo> MinidumpStreamMap;
+
+ template<typename T> T* GetStream(T** stream);
+
+ // Opens the minidump file, or if already open, seeks to the beginning.
+ bool Open();
+
+ // The largest number of top-level streams that will be read from a minidump.
+ // Note that streams are only read (and only consume memory) as needed,
+ // when directed by the caller. The default is 128.
+ static uint32_t max_streams_;
+
+ // The maximum length of a UTF-16 string that will be read from a minidump
+ // in 16-bit words. The default is 1024. UTF-16 strings are converted
+ // to UTF-8 when stored in memory, and each UTF-16 word will be represented
+ // by as many as 3 bytes in UTF-8.
+ static unsigned int max_string_length_;
+
+ MDRawHeader header_;
+
+ // The list of streams.
+ MinidumpDirectoryEntries* directory_;
+
+ // Access to streams using the stream type as the key.
+ MinidumpStreamMap* stream_map_;
+
+ // The pathname of the minidump file to process, set in the constructor.
+ // This may be empty if the minidump was opened directly from a stream.
+ const string path_;
+
+ // The stream for all file I/O. Used by ReadBytes and SeekSet.
+ // Set based on the path in Open, or directly in the constructor.
+ std::istream* stream_;
+
+ // swap_ is true if the minidump file should be byte-swapped. If the
+ // minidump was produced by a CPU that is other-endian than the CPU
+ // processing the minidump, this will be true. If the two CPUs are
+ // same-endian, this will be false.
+ bool swap_;
+
+ // true if the minidump was produced by a big-endian cpu.
+ bool is_big_endian_;
+
+ // Validity of the Minidump structure, false immediately after
+ // construction or after a failed Read(); true following a successful
+ // Read().
+ bool valid_;
+
+ // Knobs for controlling display of memory printing.
+ bool hexdump_;
+ unsigned int hexdump_width_;
+
+ DISALLOW_COPY_AND_ASSIGN(Minidump);
+};
+
+
+} // namespace google_breakpad
+
+
+#endif // GOOGLE_BREAKPAD_PROCESSOR_MINIDUMP_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/minidump_processor.h b/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/minidump_processor.h
new file mode 100644
index 0000000000..387115ef71
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/minidump_processor.h
@@ -0,0 +1,147 @@
+// 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 GOOGLE_BREAKPAD_PROCESSOR_MINIDUMP_PROCESSOR_H__
+#define GOOGLE_BREAKPAD_PROCESSOR_MINIDUMP_PROCESSOR_H__
+
+#include <assert.h>
+#include <string>
+
+#include "common/using_std_string.h"
+#include "google_breakpad/common/breakpad_types.h"
+#include "google_breakpad/processor/process_result.h"
+
+namespace google_breakpad {
+
+class Minidump;
+class ProcessState;
+class StackFrameSymbolizer;
+class SourceLineResolverInterface;
+class SymbolSupplier;
+struct SystemInfo;
+
+class MinidumpProcessor {
+ public:
+ // Initializes this MinidumpProcessor. supplier should be an
+ // implementation of the SymbolSupplier abstract base class.
+ MinidumpProcessor(SymbolSupplier* supplier,
+ SourceLineResolverInterface* resolver);
+
+ // Initializes the MinidumpProcessor with the option of
+ // enabling the exploitability framework to analyze dumps
+ // for probable security relevance.
+ MinidumpProcessor(SymbolSupplier* supplier,
+ SourceLineResolverInterface* resolver,
+ bool enable_exploitability);
+
+ // Initializes the MinidumpProcessor with source line resolver helper, and
+ // the option of enabling the exploitability framework to analyze dumps
+ // for probable security relevance.
+ // Does not take ownership of resolver_helper, which must NOT be NULL.
+ MinidumpProcessor(StackFrameSymbolizer* stack_frame_symbolizer,
+ bool enable_exploitability);
+
+ ~MinidumpProcessor();
+
+ // Processes the minidump file and fills process_state with the result.
+ ProcessResult Process(const string &minidump_file,
+ ProcessState* process_state);
+
+ // Processes the minidump structure and fills process_state with the
+ // result.
+ ProcessResult Process(Minidump* minidump,
+ ProcessState* process_state);
+ // Populates the cpu_* fields of the |info| parameter with textual
+ // representations of the CPU type that the minidump in |dump| was
+ // produced on. Returns false if this information is not available in
+ // the minidump.
+ static bool GetCPUInfo(Minidump* dump, SystemInfo* info);
+
+ // Populates the os_* fields of the |info| parameter with textual
+ // representations of the operating system that the minidump in |dump|
+ // was produced on. Returns false if this information is not available in
+ // the minidump.
+ static bool GetOSInfo(Minidump* dump, SystemInfo* info);
+
+ // Populates the |process_create_time| parameter with the create time of the
+ // crashed process. Returns false if this information is not available in
+ // the minidump |dump|.
+ static bool GetProcessCreateTime(Minidump* dump,
+ uint32_t* process_create_time);
+
+ // Returns a textual representation of the reason that a crash occurred,
+ // if the minidump in dump was produced as a result of a crash. Returns
+ // an empty string if this information cannot be determined. If address
+ // is non-NULL, it will be set to contain the address that caused the
+ // exception, if this information is available. This will be a code
+ // address when the crash was caused by problems such as illegal
+ // instructions or divisions by zero, or a data address when the crash
+ // was caused by a memory access violation.
+ static string GetCrashReason(Minidump* dump, uint64_t* address);
+
+ // This function returns true if the passed-in error code is
+ // something unrecoverable(i.e. retry should not happen). For
+ // instance, if the minidump is corrupt, then it makes no sense to
+ // retry as we won't be able to glean additional information.
+ // However, as an example of the other case, the symbol supplier can
+ // return an error code indicating it was 'interrupted', which can
+ // happen of the symbols are fetched from a remote store, and a
+ // retry might be successful later on.
+ // You should not call this method with PROCESS_OK! Test for
+ // that separately before calling this.
+ static bool IsErrorUnrecoverable(ProcessResult p) {
+ assert(p != PROCESS_OK);
+ return (p != PROCESS_SYMBOL_SUPPLIER_INTERRUPTED);
+ }
+
+ // Returns a textual representation of an assertion included
+ // in the minidump. Returns an empty string if this information
+ // does not exist or cannot be determined.
+ static string GetAssertion(Minidump* dump);
+
+ void set_enable_objdump(bool enabled) { enable_objdump_ = enabled; }
+
+ private:
+ StackFrameSymbolizer* frame_symbolizer_;
+ // Indicate whether resolver_helper_ is owned by this instance.
+ bool own_frame_symbolizer_;
+
+ // This flag enables the exploitability scanner which attempts to
+ // guess how likely it is that the crash represents an exploitable
+ // memory corruption issue.
+ bool enable_exploitability_;
+
+ // This flag permits the exploitability scanner to shell out to objdump
+ // for purposes of disassembly.
+ bool enable_objdump_;
+};
+
+} // namespace google_breakpad
+
+#endif // GOOGLE_BREAKPAD_PROCESSOR_MINIDUMP_PROCESSOR_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/proc_maps_linux.h b/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/proc_maps_linux.h
new file mode 100644
index 0000000000..3045daa5f6
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/proc_maps_linux.h
@@ -0,0 +1,60 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_DEBUG_PROC_MAPS_LINUX_H_
+#define BASE_DEBUG_PROC_MAPS_LINUX_H_
+
+#include <string>
+#include <vector>
+
+#include "common/using_std_string.h"
+#include "google_breakpad/common/breakpad_types.h"
+
+namespace google_breakpad {
+
+// Describes a region of mapped memory and the path of the file mapped.
+struct MappedMemoryRegion {
+ enum Permission {
+ READ = 1 << 0,
+ WRITE = 1 << 1,
+ EXECUTE = 1 << 2,
+ PRIVATE = 1 << 3, // If set, region is private, otherwise it is shared.
+ };
+
+ // The address range [start,end) of mapped memory.
+ uint64_t start;
+ uint64_t end;
+
+ // Byte offset into |path| of the range mapped into memory.
+ uint64_t offset;
+
+ // Bitmask of read/write/execute/private/shared permissions.
+ uint8_t permissions;
+
+ // Major and minor devices.
+ uint8_t major_device;
+ uint8_t minor_device;
+
+ // Value of the inode.
+ uint64_t inode;
+
+ // Name of the file mapped into memory.
+ //
+ // NOTE: path names aren't guaranteed to point at valid files. For example,
+ // "[heap]" and "[stack]" are used to represent the location of the process'
+ // heap and stack, respectively.
+ string path;
+
+ // The line from /proc/<pid>/maps that this struct represents.
+ string line;
+};
+
+// Parses /proc/<pid>/maps input data and stores in |regions|. Returns true
+// and updates |regions| if and only if all of |input| was successfully parsed.
+bool ParseProcMaps(const string& input,
+ std::vector<MappedMemoryRegion>* regions);
+
+} // namespace google_breakpad
+
+#endif // BASE_DEBUG_PROC_MAPS_LINUX_H_
diff --git a/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/process_result.h b/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/process_result.h
new file mode 100644
index 0000000000..15c7213e9b
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/process_result.h
@@ -0,0 +1,66 @@
+// 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_PROCESSOR_PROCESS_RESULT_H__
+#define GOOGLE_BREAKPAD_PROCESSOR_PROCESS_RESULT_H__
+
+namespace google_breakpad {
+
+// Return type for MinidumpProcessor or MicrodumpProcessor's Process()
+enum ProcessResult {
+ PROCESS_OK, // The dump was processed
+ // successfully.
+
+ PROCESS_ERROR_MINIDUMP_NOT_FOUND, // The minidump file was not
+ // found.
+
+ PROCESS_ERROR_NO_MINIDUMP_HEADER, // The minidump file had no
+ // header.
+
+ PROCESS_ERROR_NO_THREAD_LIST, // The minidump file has no
+ // thread list.
+
+ PROCESS_ERROR_GETTING_THREAD, // There was an error getting one
+ // thread's data from th dump.
+
+ PROCESS_ERROR_GETTING_THREAD_ID, // There was an error getting a
+ // thread id from the thread's
+ // data.
+
+ PROCESS_ERROR_DUPLICATE_REQUESTING_THREADS, // There was more than one
+ // requesting thread.
+
+ PROCESS_SYMBOL_SUPPLIER_INTERRUPTED // The dump processing was
+ // interrupted by the
+ // SymbolSupplier(not fatal).
+};
+
+} // namespace google_breakpad
+
+#endif // GOOGLE_BREAKPAD_PROCESSOR_PROCESS_RESULT_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/process_state.h b/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/process_state.h
new file mode 100644
index 0000000000..37b208ecbe
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/process_state.h
@@ -0,0 +1,220 @@
+// 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.
+
+// process_state.h: A snapshot of a process, in a fully-digested state.
+//
+// Author: Mark Mentovai
+
+#ifndef GOOGLE_BREAKPAD_PROCESSOR_PROCESS_STATE_H__
+#define GOOGLE_BREAKPAD_PROCESSOR_PROCESS_STATE_H__
+
+#include <string>
+#include <vector>
+
+#include "common/using_std_string.h"
+#include "google_breakpad/common/breakpad_types.h"
+#include "google_breakpad/processor/code_modules.h"
+#include "google_breakpad/processor/exception_record.h"
+#include "google_breakpad/processor/minidump.h"
+#include "google_breakpad/processor/system_info.h"
+#include "processor/linked_ptr.h"
+
+namespace google_breakpad {
+
+using std::vector;
+
+class CallStack;
+class CodeModules;
+
+enum ExploitabilityRating {
+ EXPLOITABILITY_HIGH, // The crash likely represents
+ // a exploitable memory corruption
+ // vulnerability.
+
+ EXPLOITABILITY_MEDIUM, // The crash appears to corrupt
+ // memory in a way which may be
+ // exploitable in some situations.
+
+ EXPLOITABLITY_MEDIUM = EXPLOITABILITY_MEDIUM, // an old misspelling
+
+ EXPLOITABILITY_LOW, // The crash either does not corrupt
+ // memory directly or control over
+ // the affected data is limited. The
+ // issue may still be exploitable
+ // on certain platforms or situations.
+
+ EXPLOITABILITY_INTERESTING, // The crash does not appear to be
+ // directly exploitable. However it
+ // represents a condition which should
+ // be further analyzed.
+
+ EXPLOITABILITY_NONE, // The crash does not appear to represent
+ // an exploitable condition.
+
+ EXPLOITABILITY_NOT_ANALYZED, // The crash was not analyzed for
+ // exploitability because the engine
+ // was disabled.
+
+ EXPLOITABILITY_ERR_NOENGINE, // The supplied minidump's platform does
+ // not have a exploitability engine
+ // associated with it.
+
+ EXPLOITABILITY_ERR_PROCESSING // An error occured within the
+ // exploitability engine and no rating
+ // was calculated.
+};
+
+class ProcessState {
+ public:
+ ProcessState() : modules_(NULL), unloaded_modules_(NULL) { Clear(); }
+ ~ProcessState();
+
+ // Resets the ProcessState to its default values
+ void Clear();
+
+ // Accessors. See the data declarations below.
+ uint32_t time_date_stamp() const { return time_date_stamp_; }
+ uint32_t process_create_time() const { return process_create_time_; }
+ bool crashed() const { return crashed_; }
+ string crash_reason() const { return crash_reason_; }
+ uint64_t crash_address() const { return crash_address_; }
+ string assertion() const { return assertion_; }
+ int requesting_thread() const { return requesting_thread_; }
+ const ExceptionRecord* exception_record() const { return &exception_record_; }
+ const vector<CallStack*>* threads() const { return &threads_; }
+ const vector<MemoryRegion*>* thread_memory_regions() const {
+ return &thread_memory_regions_;
+ }
+ const SystemInfo* system_info() const { return &system_info_; }
+ string mac_crash_info() const { return mac_crash_info_; }
+ size_t mac_crash_info_records_count() const {
+ return mac_crash_info_records_.size();
+ }
+ const crash_info_record_t* mac_crash_info_records() const {
+ return reinterpret_cast<const crash_info_record_t*>(
+ &mac_crash_info_records_[0]);
+ }
+ const CodeModules* modules() const { return modules_; }
+ const CodeModules* unloaded_modules() const { return unloaded_modules_; }
+ const vector<linked_ptr<const CodeModule> >* shrunk_range_modules() const {
+ return &shrunk_range_modules_;
+ }
+ const vector<const CodeModule*>* modules_without_symbols() const {
+ return &modules_without_symbols_;
+ }
+ const vector<const CodeModule*>* modules_with_corrupt_symbols() const {
+ return &modules_with_corrupt_symbols_;
+ }
+ ExploitabilityRating exploitability() const { return exploitability_; }
+
+ private:
+ // MinidumpProcessor and MicrodumpProcessor are responsible for building
+ // ProcessState objects.
+ friend class MinidumpProcessor;
+ friend class MicrodumpProcessor;
+
+ // The time-date stamp of the minidump (time_t format)
+ uint32_t time_date_stamp_;
+
+ // The time-date stamp when the process was created (time_t format)
+ uint32_t process_create_time_;
+
+ // True if the process crashed, false if the dump was produced outside
+ // of an exception handler.
+ bool crashed_;
+
+ // If the process crashed, the type of crash. OS- and possibly CPU-
+ // specific. For example, "EXCEPTION_ACCESS_VIOLATION" (Windows),
+ // "EXC_BAD_ACCESS / KERN_INVALID_ADDRESS" (Mac OS X), "SIGSEGV"
+ // (other Unix).
+ string crash_reason_;
+
+ // If the process crashed, and if crash_reason implicates memory,
+ // the memory address that caused the crash. For data access errors,
+ // this will be the data address that caused the fault. For code errors,
+ // this will be the address of the instruction that caused the fault.
+ uint64_t crash_address_;
+
+ // If there was an assertion that was hit, a textual representation
+ // of that assertion, possibly including the file and line at which
+ // it occurred.
+ string assertion_;
+
+ // The index of the thread that requested a dump be written in the
+ // threads vector. If a dump was produced as a result of a crash, this
+ // will point to the thread that crashed. If the dump was produced as
+ // by user code without crashing, and the dump contains extended Breakpad
+ // information, this will point to the thread that requested the dump.
+ // If the dump was not produced as a result of an exception and no
+ // extended Breakpad information is present, this field will be set to -1,
+ // indicating that the dump thread is not available.
+ int requesting_thread_;
+
+ // Exception record details: code, flags, address, parameters.
+ ExceptionRecord exception_record_;
+
+ // Stacks for each thread (except possibly the exception handler
+ // thread) at the time of the crash.
+ vector<CallStack*> threads_;
+ vector<MemoryRegion*> thread_memory_regions_;
+
+ // OS and CPU information.
+ SystemInfo system_info_;
+
+ // Information from __DATA,__crash_info sections. Only present on macOS.
+ string mac_crash_info_;
+ vector<crash_info_record_t> mac_crash_info_records_;
+
+ // The modules that were loaded into the process represented by the
+ // ProcessState.
+ const CodeModules *modules_;
+
+ // The modules that have been unloaded from the process represented by the
+ // ProcessState.
+ const CodeModules *unloaded_modules_;
+
+ // The modules which virtual address ranges were shrunk down due to
+ // virtual address conflicts.
+ vector<linked_ptr<const CodeModule> > shrunk_range_modules_;
+
+ // The modules that didn't have symbols when the report was processed.
+ vector<const CodeModule*> modules_without_symbols_;
+
+ // The modules that had corrupt symbols when the report was processed.
+ vector<const CodeModule*> modules_with_corrupt_symbols_;
+
+ // The exploitability rating as determined by the exploitability
+ // engine. When the exploitability engine is not enabled this
+ // defaults to EXPLOITABILITY_NOT_ANALYZED.
+ ExploitabilityRating exploitability_;
+};
+
+} // namespace google_breakpad
+
+#endif // GOOGLE_BREAKPAD_PROCESSOR_PROCESS_STATE_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/source_line_resolver_base.h b/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/source_line_resolver_base.h
new file mode 100644
index 0000000000..c720b0c325
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/source_line_resolver_base.h
@@ -0,0 +1,128 @@
+// 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.
+//
+// source_line_resolver_base.h: SourceLineResolverBase, an (incomplete)
+// implementation of SourceLineResolverInterface. It serves as a common base
+// class for concrete implementations: FastSourceLineResolver and
+// BasicSourceLineResolver. It is designed for refactoring that removes
+// code redundancy in the two concrete source line resolver classes.
+//
+// See "google_breakpad/processor/source_line_resolver_interface.h" for more
+// documentation.
+
+// Author: Siyang Xie (lambxsy@google.com)
+
+#ifndef GOOGLE_BREAKPAD_PROCESSOR_SOURCE_LINE_RESOLVER_BASE_H__
+#define GOOGLE_BREAKPAD_PROCESSOR_SOURCE_LINE_RESOLVER_BASE_H__
+
+#include <map>
+#include <set>
+#include <string>
+
+#include "google_breakpad/processor/source_line_resolver_interface.h"
+
+namespace google_breakpad {
+
+using std::map;
+using std::set;
+
+// Forward declaration.
+// ModuleFactory is a simple factory interface for creating a Module instance
+// at run-time.
+class ModuleFactory;
+
+class SourceLineResolverBase : public SourceLineResolverInterface {
+ public:
+ // Read the symbol_data from a file with given file_name.
+ // The part of code was originally in BasicSourceLineResolver::Module's
+ // LoadMap() method.
+ // Place dynamically allocated heap buffer in symbol_data. Caller has the
+ // ownership of the buffer, and should call delete [] to free the buffer.
+ static bool ReadSymbolFile(const string &file_name,
+ char **symbol_data,
+ size_t *symbol_data_size);
+
+ protected:
+ // Users are not allowed create SourceLineResolverBase instance directly.
+ SourceLineResolverBase(ModuleFactory *module_factory);
+ virtual ~SourceLineResolverBase();
+
+ // Virtual methods inherited from SourceLineResolverInterface.
+ virtual bool LoadModule(const CodeModule *module, const string &map_file);
+ virtual bool LoadModuleUsingMapBuffer(const CodeModule *module,
+ const string &map_buffer);
+ virtual bool LoadModuleUsingMemoryBuffer(const CodeModule *module,
+ char *memory_buffer,
+ size_t memory_buffer_size);
+ virtual bool ShouldDeleteMemoryBufferAfterLoadModule();
+ virtual void UnloadModule(const CodeModule *module);
+ virtual bool HasModule(const CodeModule *module);
+ virtual bool IsModuleCorrupt(const CodeModule *module);
+ virtual void FillSourceLineInfo(StackFrame *frame);
+ virtual WindowsFrameInfo *FindWindowsFrameInfo(const StackFrame *frame);
+ virtual CFIFrameInfo *FindCFIFrameInfo(const StackFrame *frame);
+
+ // Nested structs and classes.
+ struct Line;
+ struct Function;
+ struct PublicSymbol;
+ struct CompareString {
+ bool operator()(const string &s1, const string &s2) const;
+ };
+ // Module is an interface for an in-memory symbol file.
+ class Module;
+ class AutoFileCloser;
+
+ // All of the modules that are loaded.
+ typedef map<string, Module*, CompareString> ModuleMap;
+ ModuleMap *modules_;
+
+ // The loaded modules that were detecting to be corrupt during load.
+ typedef set<string, CompareString> ModuleSet;
+ ModuleSet *corrupt_modules_;
+
+ // All of heap-allocated buffers that are owned locally by resolver.
+ typedef std::map<string, char*, CompareString> MemoryMap;
+ MemoryMap *memory_buffers_;
+
+ // Creates a concrete module at run-time.
+ ModuleFactory *module_factory_;
+
+ private:
+ // ModuleFactory needs to have access to protected type Module.
+ friend class ModuleFactory;
+
+ // Disallow unwanted copy ctor and assignment operator
+ SourceLineResolverBase(const SourceLineResolverBase&);
+ void operator=(const SourceLineResolverBase&);
+};
+
+} // namespace google_breakpad
+
+#endif // GOOGLE_BREAKPAD_PROCESSOR_SOURCE_LINE_RESOLVER_BASE_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/source_line_resolver_interface.h b/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/source_line_resolver_interface.h
new file mode 100644
index 0000000000..a694bf2ea1
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/source_line_resolver_interface.h
@@ -0,0 +1,117 @@
+// -*- 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.
+
+// Abstract interface to return function/file/line info for a memory address.
+
+#ifndef GOOGLE_BREAKPAD_PROCESSOR_SOURCE_LINE_RESOLVER_INTERFACE_H__
+#define GOOGLE_BREAKPAD_PROCESSOR_SOURCE_LINE_RESOLVER_INTERFACE_H__
+
+#include <string>
+
+#include "common/using_std_string.h"
+#include "google_breakpad/common/breakpad_types.h"
+#include "google_breakpad/processor/code_module.h"
+
+namespace google_breakpad {
+
+struct StackFrame;
+struct WindowsFrameInfo;
+class CFIFrameInfo;
+
+class SourceLineResolverInterface {
+ public:
+ typedef uint64_t MemAddr;
+
+ virtual ~SourceLineResolverInterface() {}
+
+ // Adds a module to this resolver, returning true on success.
+ //
+ // module should have at least the code_file, debug_file,
+ // and debug_identifier members populated.
+ //
+ // map_file should contain line/address mappings for this module.
+ virtual bool LoadModule(const CodeModule *module,
+ const string &map_file) = 0;
+ // Same as above, but takes the contents of a pre-read map buffer
+ virtual bool LoadModuleUsingMapBuffer(const CodeModule *module,
+ const string &map_buffer) = 0;
+
+ // Add an interface to load symbol using C-String data instead of string.
+ // This is useful in the optimization design for avoiding unnecessary copying
+ // of symbol data, in order to improve memory efficiency.
+ // LoadModuleUsingMemoryBuffer() does NOT take ownership of memory_buffer.
+ // LoadModuleUsingMemoryBuffer() null terminates the passed in buffer, if
+ // the last character is not a null terminator.
+ virtual bool LoadModuleUsingMemoryBuffer(const CodeModule *module,
+ char *memory_buffer,
+ size_t memory_buffer_size) = 0;
+
+ // Return true if the memory buffer should be deleted immediately after
+ // LoadModuleUsingMemoryBuffer(). Return false if the memory buffer has to be
+ // alive during the lifetime of the corresponding Module.
+ virtual bool ShouldDeleteMemoryBufferAfterLoadModule() = 0;
+
+ // Request that the specified module be unloaded from this resolver.
+ // A resolver may choose to ignore such a request.
+ virtual void UnloadModule(const CodeModule *module) = 0;
+
+ // Returns true if the module has been loaded.
+ virtual bool HasModule(const CodeModule *module) = 0;
+
+ // Returns true if the module has been loaded and it is corrupt.
+ virtual bool IsModuleCorrupt(const CodeModule *module) = 0;
+
+ // Fills in the function_base, function_name, source_file_name,
+ // and source_line fields of the StackFrame. The instruction and
+ // module_name fields must already be filled in.
+ virtual void FillSourceLineInfo(StackFrame *frame) = 0;
+
+ // If Windows stack walking information is available covering
+ // FRAME's instruction address, return a WindowsFrameInfo structure
+ // describing it. If the information is not available, returns NULL.
+ // A NULL return value does not indicate an error. The caller takes
+ // ownership of any returned WindowsFrameInfo object.
+ virtual WindowsFrameInfo *FindWindowsFrameInfo(const StackFrame *frame) = 0;
+
+ // If CFI stack walking information is available covering ADDRESS,
+ // return a CFIFrameInfo structure describing it. If the information
+ // is not available, return NULL. The caller takes ownership of any
+ // returned CFIFrameInfo object.
+ virtual CFIFrameInfo *FindCFIFrameInfo(const StackFrame *frame) = 0;
+
+ protected:
+ // SourceLineResolverInterface cannot be instantiated except by subclasses
+ SourceLineResolverInterface() {}
+};
+
+} // namespace google_breakpad
+
+#endif // GOOGLE_BREAKPAD_PROCESSOR_SOURCE_LINE_RESOLVER_INTERFACE_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/stack_frame.h b/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/stack_frame.h
new file mode 100644
index 0000000000..1491d78825
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/stack_frame.h
@@ -0,0 +1,144 @@
+// 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 GOOGLE_BREAKPAD_PROCESSOR_STACK_FRAME_H__
+#define GOOGLE_BREAKPAD_PROCESSOR_STACK_FRAME_H__
+
+#include <string>
+
+#include "common/using_std_string.h"
+#include "google_breakpad/common/breakpad_types.h"
+
+namespace google_breakpad {
+
+class CodeModule;
+
+struct StackFrame {
+ // Indicates how well the instruction pointer derived during
+ // stack walking is trusted. Since the stack walker can resort to
+ // stack scanning, it can wind up with dubious frames.
+ // In rough order of "trust metric".
+ enum FrameTrust {
+ FRAME_TRUST_NONE, // Unknown
+ FRAME_TRUST_SCAN, // Scanned the stack, found this
+ FRAME_TRUST_CFI_SCAN, // Found while scanning stack using call frame info
+ FRAME_TRUST_FP, // Derived from frame pointer
+ FRAME_TRUST_CFI, // Derived from call frame info
+ FRAME_TRUST_PREWALKED, // Explicitly provided by some external stack walker.
+ FRAME_TRUST_CONTEXT // Given as instruction pointer in a context
+ };
+
+ StackFrame()
+ : instruction(),
+ module(NULL),
+ function_name(),
+ function_base(),
+ source_file_name(),
+ source_line(),
+ source_line_base(),
+ trust(FRAME_TRUST_NONE) {}
+ virtual ~StackFrame() {}
+
+ // Return a string describing how this stack frame was found
+ // by the stackwalker.
+ string trust_description() const {
+ switch (trust) {
+ case StackFrame::FRAME_TRUST_CONTEXT:
+ return "given as instruction pointer in context";
+ case StackFrame::FRAME_TRUST_PREWALKED:
+ return "recovered by external stack walker";
+ case StackFrame::FRAME_TRUST_CFI:
+ return "call frame info";
+ case StackFrame::FRAME_TRUST_CFI_SCAN:
+ return "call frame info with scanning";
+ case StackFrame::FRAME_TRUST_FP:
+ return "previous frame's frame pointer";
+ case StackFrame::FRAME_TRUST_SCAN:
+ return "stack scanning";
+ default:
+ return "unknown";
+ }
+ }
+
+ // Return the actual return address, as saved on the stack or in a
+ // register. See the comments for 'instruction', below, for details.
+ virtual uint64_t ReturnAddress() const { return instruction; }
+
+ // The program counter location as an absolute virtual address.
+ //
+ // - For the innermost called frame in a stack, this will be an exact
+ // program counter or instruction pointer value.
+ //
+ // - For all other frames, this address is within the instruction that
+ // caused execution to branch to this frame's callee (although it may
+ // not point to the exact beginning of that instruction). This ensures
+ // that, when we look up the source code location for this frame, we
+ // get the source location of the call, not of the point at which
+ // control will resume when the call returns, which may be on the next
+ // line. (If the compiler knows the callee never returns, it may even
+ // place the call instruction at the very end of the caller's machine
+ // code, such that the "return address" (which will never be used)
+ // immediately after the call instruction is in an entirely different
+ // function, perhaps even from a different source file.)
+ //
+ // On some architectures, the return address as saved on the stack or in
+ // a register is fine for looking up the point of the call. On others, it
+ // requires adjustment. ReturnAddress returns the address as saved by the
+ // machine.
+ uint64_t instruction;
+
+ // The module in which the instruction resides.
+ const CodeModule *module;
+
+ // The function name, may be omitted if debug symbols are not available.
+ string function_name;
+
+ // The start address of the function, may be omitted if debug symbols
+ // are not available.
+ uint64_t function_base;
+
+ // The source file name, may be omitted if debug symbols are not available.
+ string source_file_name;
+
+ // The (1-based) source line number, may be omitted if debug symbols are
+ // not available.
+ int source_line;
+
+ // The start address of the source line, may be omitted if debug symbols
+ // are not available.
+ uint64_t source_line_base;
+
+ // Amount of trust the stack walker has in the instruction pointer
+ // of this frame.
+ FrameTrust trust;
+};
+
+} // namespace google_breakpad
+
+#endif // GOOGLE_BREAKPAD_PROCESSOR_STACK_FRAME_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/stack_frame_cpu.h b/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/stack_frame_cpu.h
new file mode 100644
index 0000000000..dc5d8ae673
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/stack_frame_cpu.h
@@ -0,0 +1,405 @@
+// -*- 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.
+
+// stack_frame_cpu.h: CPU-specific StackFrame extensions.
+//
+// These types extend the StackFrame structure to carry CPU-specific register
+// state. They are defined in this header instead of stack_frame.h to
+// avoid the need to include minidump_format.h when only the generic
+// StackFrame type is needed.
+//
+// Author: Mark Mentovai
+
+#ifndef GOOGLE_BREAKPAD_PROCESSOR_STACK_FRAME_CPU_H__
+#define GOOGLE_BREAKPAD_PROCESSOR_STACK_FRAME_CPU_H__
+
+#include "google_breakpad/common/minidump_format.h"
+#include "google_breakpad/processor/stack_frame.h"
+
+namespace google_breakpad {
+
+struct WindowsFrameInfo;
+class CFIFrameInfo;
+
+struct StackFrameX86 : public StackFrame {
+ // ContextValidity has one entry for each relevant hardware pointer
+ // register (%eip and %esp) and one entry for each general-purpose
+ // register. It's worthwhile having validity flags for caller-saves
+ // registers: they are valid in the youngest frame, and such a frame
+ // might save a callee-saves register in a caller-saves register, but
+ // SimpleCFIWalker won't touch registers unless they're marked as valid.
+ enum ContextValidity {
+ CONTEXT_VALID_NONE = 0,
+ CONTEXT_VALID_EIP = 1 << 0,
+ CONTEXT_VALID_ESP = 1 << 1,
+ CONTEXT_VALID_EBP = 1 << 2,
+ CONTEXT_VALID_EAX = 1 << 3,
+ CONTEXT_VALID_EBX = 1 << 4,
+ CONTEXT_VALID_ECX = 1 << 5,
+ CONTEXT_VALID_EDX = 1 << 6,
+ CONTEXT_VALID_ESI = 1 << 7,
+ CONTEXT_VALID_EDI = 1 << 8,
+ CONTEXT_VALID_ALL = -1
+ };
+
+ StackFrameX86()
+ : context(),
+ context_validity(CONTEXT_VALID_NONE),
+ windows_frame_info(NULL),
+ cfi_frame_info(NULL) {}
+ ~StackFrameX86();
+
+ // Overriden to return the return address as saved on the stack.
+ virtual uint64_t ReturnAddress() const;
+
+ // Register state. This is only fully valid for the topmost frame in a
+ // stack. In other frames, the values of nonvolatile registers may be
+ // present, given sufficient debugging information. Refer to
+ // context_validity.
+ MDRawContextX86 context;
+
+ // context_validity is actually ContextValidity, but int is used because
+ // the OR operator doesn't work well with enumerated types. This indicates
+ // which fields in context are valid.
+ int context_validity;
+
+ // Any stack walking information we found describing this.instruction.
+ // These may be NULL if there is no such information for that address.
+ WindowsFrameInfo *windows_frame_info;
+ CFIFrameInfo *cfi_frame_info;
+};
+
+struct StackFramePPC : public StackFrame {
+ // ContextValidity should eventually contain entries for the validity of
+ // other nonvolatile (callee-save) registers as in
+ // StackFrameX86::ContextValidity, but the ppc stackwalker doesn't currently
+ // locate registers other than the ones listed here.
+ enum ContextValidity {
+ CONTEXT_VALID_NONE = 0,
+ CONTEXT_VALID_SRR0 = 1 << 0,
+ CONTEXT_VALID_GPR1 = 1 << 1,
+ CONTEXT_VALID_ALL = -1
+ };
+
+ StackFramePPC() : context(), context_validity(CONTEXT_VALID_NONE) {}
+
+ // Register state. This is only fully valid for the topmost frame in a
+ // stack. In other frames, the values of nonvolatile registers may be
+ // present, given sufficient debugging information. Refer to
+ // context_validity.
+ MDRawContextPPC context;
+
+ // context_validity is actually ContextValidity, but int is used because
+ // the OR operator doesn't work well with enumerated types. This indicates
+ // which fields in context are valid.
+ int context_validity;
+};
+
+struct StackFramePPC64 : public StackFrame {
+ // ContextValidity should eventually contain entries for the validity of
+ // other nonvolatile (callee-save) registers as in
+ // StackFrameX86::ContextValidity, but the ppc stackwalker doesn't currently
+ // locate registers other than the ones listed here.
+ enum ContextValidity {
+ CONTEXT_VALID_NONE = 0,
+ CONTEXT_VALID_SRR0 = 1 << 0,
+ CONTEXT_VALID_GPR1 = 1 << 1,
+ CONTEXT_VALID_ALL = -1
+ };
+
+ StackFramePPC64() : context(), context_validity(CONTEXT_VALID_NONE) {}
+
+ // Register state. This is only fully valid for the topmost frame in a
+ // stack. In other frames, the values of nonvolatile registers may be
+ // present, given sufficient debugging information. Refer to
+ // context_validity.
+ MDRawContextPPC64 context;
+
+ // context_validity is actually ContextValidity, but int is used because
+ // the OR operator doesn't work well with enumerated types. This indicates
+ // which fields in context are valid.
+ int context_validity;
+};
+
+struct StackFrameAMD64 : public StackFrame {
+ // ContextValidity has one entry for each register that we might be able
+ // to recover.
+ enum ContextValidity {
+ CONTEXT_VALID_NONE = 0,
+ CONTEXT_VALID_RAX = 1 << 0,
+ CONTEXT_VALID_RDX = 1 << 1,
+ CONTEXT_VALID_RCX = 1 << 2,
+ CONTEXT_VALID_RBX = 1 << 3,
+ CONTEXT_VALID_RSI = 1 << 4,
+ CONTEXT_VALID_RDI = 1 << 5,
+ CONTEXT_VALID_RBP = 1 << 6,
+ CONTEXT_VALID_RSP = 1 << 7,
+ CONTEXT_VALID_R8 = 1 << 8,
+ CONTEXT_VALID_R9 = 1 << 9,
+ CONTEXT_VALID_R10 = 1 << 10,
+ CONTEXT_VALID_R11 = 1 << 11,
+ CONTEXT_VALID_R12 = 1 << 12,
+ CONTEXT_VALID_R13 = 1 << 13,
+ CONTEXT_VALID_R14 = 1 << 14,
+ CONTEXT_VALID_R15 = 1 << 15,
+ CONTEXT_VALID_RIP = 1 << 16,
+ CONTEXT_VALID_ALL = -1
+ };
+
+ StackFrameAMD64() : context(), context_validity(CONTEXT_VALID_NONE) {}
+
+ // Overriden to return the return address as saved on the stack.
+ virtual uint64_t ReturnAddress() const;
+
+ // Register state. This is only fully valid for the topmost frame in a
+ // stack. In other frames, which registers are present depends on what
+ // debugging information we had available. Refer to context_validity.
+ MDRawContextAMD64 context;
+
+ // For each register in context whose value has been recovered, we set
+ // the corresponding CONTEXT_VALID_ bit in context_validity.
+ //
+ // context_validity's type should actually be ContextValidity, but
+ // we use int instead because the bitwise inclusive or operator
+ // yields an int when applied to enum values, and C++ doesn't
+ // silently convert from ints to enums.
+ int context_validity;
+};
+
+struct StackFrameSPARC : public StackFrame {
+ // to be confirmed
+ enum ContextValidity {
+ CONTEXT_VALID_NONE = 0,
+ CONTEXT_VALID_PC = 1 << 0,
+ CONTEXT_VALID_SP = 1 << 1,
+ CONTEXT_VALID_FP = 1 << 2,
+ CONTEXT_VALID_ALL = -1
+ };
+
+ StackFrameSPARC() : context(), context_validity(CONTEXT_VALID_NONE) {}
+
+ // Register state. This is only fully valid for the topmost frame in a
+ // stack. In other frames, the values of nonvolatile registers may be
+ // present, given sufficient debugging information. Refer to
+ // context_validity.
+ MDRawContextSPARC context;
+
+ // context_validity is actually ContextValidity, but int is used because
+ // the OR operator doesn't work well with enumerated types. This indicates
+ // which fields in context are valid.
+ int context_validity;
+};
+
+struct StackFrameARM : public StackFrame {
+ // A flag for each register we might know.
+ enum ContextValidity {
+ CONTEXT_VALID_NONE = 0,
+ CONTEXT_VALID_R0 = 1 << 0,
+ CONTEXT_VALID_R1 = 1 << 1,
+ CONTEXT_VALID_R2 = 1 << 2,
+ CONTEXT_VALID_R3 = 1 << 3,
+ CONTEXT_VALID_R4 = 1 << 4,
+ CONTEXT_VALID_R5 = 1 << 5,
+ CONTEXT_VALID_R6 = 1 << 6,
+ CONTEXT_VALID_R7 = 1 << 7,
+ CONTEXT_VALID_R8 = 1 << 8,
+ CONTEXT_VALID_R9 = 1 << 9,
+ CONTEXT_VALID_R10 = 1 << 10,
+ CONTEXT_VALID_R11 = 1 << 11,
+ CONTEXT_VALID_R12 = 1 << 12,
+ CONTEXT_VALID_R13 = 1 << 13,
+ CONTEXT_VALID_R14 = 1 << 14,
+ CONTEXT_VALID_R15 = 1 << 15,
+ CONTEXT_VALID_ALL = ~CONTEXT_VALID_NONE,
+
+ // Aliases for registers with dedicated or conventional roles.
+ CONTEXT_VALID_FP = CONTEXT_VALID_R11,
+ CONTEXT_VALID_SP = CONTEXT_VALID_R13,
+ CONTEXT_VALID_LR = CONTEXT_VALID_R14,
+ CONTEXT_VALID_PC = CONTEXT_VALID_R15
+ };
+
+ StackFrameARM() : context(), context_validity(CONTEXT_VALID_NONE) {}
+
+ // Return the ContextValidity flag for register rN.
+ static ContextValidity RegisterValidFlag(int n) {
+ return ContextValidity(1 << n);
+ }
+
+ // Register state. This is only fully valid for the topmost frame in a
+ // stack. In other frames, the values of nonvolatile registers may be
+ // present, given sufficient debugging information. Refer to
+ // context_validity.
+ MDRawContextARM context;
+
+ // For each register in context whose value has been recovered, we set
+ // the corresponding CONTEXT_VALID_ bit in context_validity.
+ //
+ // context_validity's type should actually be ContextValidity, but
+ // we use int instead because the bitwise inclusive or operator
+ // yields an int when applied to enum values, and C++ doesn't
+ // silently convert from ints to enums.
+ int context_validity;
+};
+
+struct StackFrameARM64 : public StackFrame {
+ // A flag for each register we might know. Note that we can't use an enum
+ // here as there are 33 values to represent.
+ static const uint64_t CONTEXT_VALID_NONE = 0;
+ static const uint64_t CONTEXT_VALID_X0 = 1ULL << 0;
+ static const uint64_t CONTEXT_VALID_X1 = 1ULL << 1;
+ static const uint64_t CONTEXT_VALID_X2 = 1ULL << 2;
+ static const uint64_t CONTEXT_VALID_X3 = 1ULL << 3;
+ static const uint64_t CONTEXT_VALID_X4 = 1ULL << 4;
+ static const uint64_t CONTEXT_VALID_X5 = 1ULL << 5;
+ static const uint64_t CONTEXT_VALID_X6 = 1ULL << 6;
+ static const uint64_t CONTEXT_VALID_X7 = 1ULL << 7;
+ static const uint64_t CONTEXT_VALID_X8 = 1ULL << 8;
+ static const uint64_t CONTEXT_VALID_X9 = 1ULL << 9;
+ static const uint64_t CONTEXT_VALID_X10 = 1ULL << 10;
+ static const uint64_t CONTEXT_VALID_X11 = 1ULL << 11;
+ static const uint64_t CONTEXT_VALID_X12 = 1ULL << 12;
+ static const uint64_t CONTEXT_VALID_X13 = 1ULL << 13;
+ static const uint64_t CONTEXT_VALID_X14 = 1ULL << 14;
+ static const uint64_t CONTEXT_VALID_X15 = 1ULL << 15;
+ static const uint64_t CONTEXT_VALID_X16 = 1ULL << 16;
+ static const uint64_t CONTEXT_VALID_X17 = 1ULL << 17;
+ static const uint64_t CONTEXT_VALID_X18 = 1ULL << 18;
+ static const uint64_t CONTEXT_VALID_X19 = 1ULL << 19;
+ static const uint64_t CONTEXT_VALID_X20 = 1ULL << 20;
+ static const uint64_t CONTEXT_VALID_X21 = 1ULL << 21;
+ static const uint64_t CONTEXT_VALID_X22 = 1ULL << 22;
+ static const uint64_t CONTEXT_VALID_X23 = 1ULL << 23;
+ static const uint64_t CONTEXT_VALID_X24 = 1ULL << 24;
+ static const uint64_t CONTEXT_VALID_X25 = 1ULL << 25;
+ static const uint64_t CONTEXT_VALID_X26 = 1ULL << 26;
+ static const uint64_t CONTEXT_VALID_X27 = 1ULL << 27;
+ static const uint64_t CONTEXT_VALID_X28 = 1ULL << 28;
+ static const uint64_t CONTEXT_VALID_X29 = 1ULL << 29;
+ static const uint64_t CONTEXT_VALID_X30 = 1ULL << 30;
+ static const uint64_t CONTEXT_VALID_X31 = 1ULL << 31;
+ static const uint64_t CONTEXT_VALID_X32 = 1ULL << 32;
+ static const uint64_t CONTEXT_VALID_ALL = ~CONTEXT_VALID_NONE;
+
+ // Aliases for registers with dedicated or conventional roles.
+ static const uint64_t CONTEXT_VALID_FP = CONTEXT_VALID_X29;
+ static const uint64_t CONTEXT_VALID_LR = CONTEXT_VALID_X30;
+ static const uint64_t CONTEXT_VALID_SP = CONTEXT_VALID_X31;
+ static const uint64_t CONTEXT_VALID_PC = CONTEXT_VALID_X32;
+
+ StackFrameARM64() : context(),
+ context_validity(CONTEXT_VALID_NONE) {}
+
+ // Return the validity flag for register xN.
+ static uint64_t RegisterValidFlag(int n) {
+ return 1ULL << n;
+ }
+
+ // Register state. This is only fully valid for the topmost frame in a
+ // stack. In other frames, the values of nonvolatile registers may be
+ // present, given sufficient debugging information. Refer to
+ // context_validity.
+ MDRawContextARM64 context;
+
+ // For each register in context whose value has been recovered, we set
+ // the corresponding CONTEXT_VALID_ bit in context_validity.
+ uint64_t context_validity;
+};
+
+struct StackFrameMIPS : public StackFrame {
+ // MIPS callee save registers for o32 ABI (32bit registers) are:
+ // 1. $s0-$s7,
+ // 2. $sp, $fp
+ // 3. $f20-$f31
+ //
+ // The register structure is available at
+ // http://en.wikipedia.org/wiki/MIPS_architecture#Compiler_register_usage
+
+#define INDEX_MIPS_REG_S0 MD_CONTEXT_MIPS_REG_S0 // 16
+#define INDEX_MIPS_REG_S7 MD_CONTEXT_MIPS_REG_S7 // 23
+#define INDEX_MIPS_REG_GP MD_CONTEXT_MIPS_REG_GP // 28
+#define INDEX_MIPS_REG_RA MD_CONTEXT_MIPS_REG_RA // 31
+#define INDEX_MIPS_REG_PC 34
+#define SHIFT_MIPS_REG_S0 0
+#define SHIFT_MIPS_REG_GP 8
+#define SHIFT_MIPS_REG_PC 12
+
+ enum ContextValidity {
+ CONTEXT_VALID_NONE = 0,
+ CONTEXT_VALID_S0 = 1 << 0, // $16
+ CONTEXT_VALID_S1 = 1 << 1, // $17
+ CONTEXT_VALID_S2 = 1 << 2, // $18
+ CONTEXT_VALID_S3 = 1 << 3, // $19
+ CONTEXT_VALID_S4 = 1 << 4, // $20
+ CONTEXT_VALID_S5 = 1 << 5, // $21
+ CONTEXT_VALID_S6 = 1 << 6, // $22
+ CONTEXT_VALID_S7 = 1 << 7, // $23
+ // GP is not calee-save for o32 abi.
+ CONTEXT_VALID_GP = 1 << 8, // $28
+ CONTEXT_VALID_SP = 1 << 9, // $29
+ CONTEXT_VALID_FP = 1 << 10, // $30
+ CONTEXT_VALID_RA = 1 << 11, // $31
+ CONTEXT_VALID_PC = 1 << 12, // $34
+ CONTEXT_VALID_ALL = ~CONTEXT_VALID_NONE
+ };
+
+ // Return the ContextValidity flag for register rN.
+ static ContextValidity RegisterValidFlag(int n) {
+ if (n >= INDEX_MIPS_REG_S0 && n <= INDEX_MIPS_REG_S7)
+ return ContextValidity(1 << (n - INDEX_MIPS_REG_S0 + SHIFT_MIPS_REG_S0));
+ else if (n >= INDEX_MIPS_REG_GP && n <= INDEX_MIPS_REG_RA)
+ return ContextValidity(1 << (n - INDEX_MIPS_REG_GP + SHIFT_MIPS_REG_GP));
+ else if (n == INDEX_MIPS_REG_PC)
+ return ContextValidity(1 << SHIFT_MIPS_REG_PC);
+
+ return CONTEXT_VALID_NONE;
+ }
+
+ StackFrameMIPS() : context(), context_validity(CONTEXT_VALID_NONE) {}
+
+ // Register state. This is only fully valid for the topmost frame in a
+ // stack. In other frames, which registers are present depends on what
+ // debugging information were available. Refer to 'context_validity' below.
+ MDRawContextMIPS context;
+
+ // For each register in context whose value has been recovered,
+ // the corresponding CONTEXT_VALID_ bit in 'context_validity' is set.
+ //
+ // context_validity's type should actually be ContextValidity, but
+ // type int is used instead because the bitwise inclusive or operator
+ // yields an int when applied to enum values, and C++ doesn't
+ // silently convert from ints to enums.
+ int context_validity;
+};
+
+} // namespace google_breakpad
+
+#endif // GOOGLE_BREAKPAD_PROCESSOR_STACK_FRAME_CPU_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/stack_frame_symbolizer.h b/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/stack_frame_symbolizer.h
new file mode 100644
index 0000000000..0bbaae0a36
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/stack_frame_symbolizer.h
@@ -0,0 +1,110 @@
+// -*- 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.
+
+// Helper class that encapsulates the logic of how symbol supplier interacts
+// with source line resolver to fill stack frame information.
+
+#ifndef GOOGLE_BREAKPAD_PROCESSOR_STACK_FRAME_SYMBOLIZER_H__
+#define GOOGLE_BREAKPAD_PROCESSOR_STACK_FRAME_SYMBOLIZER_H__
+
+#include <set>
+#include <string>
+
+#include "common/using_std_string.h"
+#include "google_breakpad/common/breakpad_types.h"
+#include "google_breakpad/processor/code_module.h"
+
+namespace google_breakpad {
+class CFIFrameInfo;
+class CodeModules;
+class SymbolSupplier;
+class SourceLineResolverInterface;
+struct StackFrame;
+struct SystemInfo;
+struct WindowsFrameInfo;
+
+class StackFrameSymbolizer {
+ public:
+ enum SymbolizerResult {
+ // Symbol data was found and successfully loaded in resolver.
+ // This does NOT guarantee source line info is found within symbol file.
+ kNoError,
+ // This indicates non-critical error, such as, no code module found for
+ // frame's instruction, no symbol file, or resolver failed to load symbol.
+ kError,
+ // This indicates error for which stack walk should be interrupted
+ // and retried in future.
+ kInterrupt,
+ // Symbol data was found and loaded in resolver however some corruptions
+ // were detected.
+ kWarningCorruptSymbols,
+ };
+
+ StackFrameSymbolizer(SymbolSupplier* supplier,
+ SourceLineResolverInterface* resolver);
+
+ virtual ~StackFrameSymbolizer() { }
+
+ // Encapsulate the step of resolving source line info for a stack frame.
+ // "frame" must not be NULL.
+ virtual SymbolizerResult FillSourceLineInfo(
+ const CodeModules* modules,
+ const CodeModules* unloaded_modules,
+ const SystemInfo* system_info,
+ StackFrame* stack_frame);
+
+ virtual WindowsFrameInfo* FindWindowsFrameInfo(const StackFrame* frame);
+
+ virtual CFIFrameInfo* FindCFIFrameInfo(const StackFrame* frame);
+
+ // Reset internal (locally owned) data as if the helper is re-instantiated.
+ // A typical case is to call Reset() after processing an individual report
+ // before start to process next one, in order to reset internal information
+ // about missing symbols found so far.
+ virtual void Reset() { no_symbol_modules_.clear(); }
+
+ // Returns true if there is valid implementation for stack symbolization.
+ virtual bool HasImplementation() { return resolver_ && supplier_; }
+
+ SourceLineResolverInterface* resolver() { return resolver_; }
+ SymbolSupplier* supplier() { return supplier_; }
+
+ protected:
+ SymbolSupplier* supplier_;
+ SourceLineResolverInterface* resolver_;
+ // A list of modules known to have symbols missing. This helps avoid
+ // repeated lookups for the missing symbols within one minidump.
+ std::set<string> no_symbol_modules_;
+};
+
+} // namespace google_breakpad
+
+#endif // GOOGLE_BREAKPAD_PROCESSOR_STACK_FRAME_SYMBOLIZER_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/stackwalker.h b/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/stackwalker.h
new file mode 100644
index 0000000000..0c458d500e
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/stackwalker.h
@@ -0,0 +1,257 @@
+// 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.
+
+// stackwalker.h: Generic stackwalker.
+//
+// The Stackwalker class is an abstract base class providing common generic
+// methods that apply to stacks from all systems. Specific implementations
+// will extend this class by providing GetContextFrame and GetCallerFrame
+// methods to fill in system-specific data in a StackFrame structure.
+// Stackwalker assembles these StackFrame strucutres into a CallStack.
+//
+// Author: Mark Mentovai
+
+
+#ifndef GOOGLE_BREAKPAD_PROCESSOR_STACKWALKER_H__
+#define GOOGLE_BREAKPAD_PROCESSOR_STACKWALKER_H__
+
+#include <set>
+#include <string>
+#include <vector>
+
+#include "common/using_std_string.h"
+#include "google_breakpad/common/breakpad_types.h"
+#include "google_breakpad/processor/code_modules.h"
+#include "google_breakpad/processor/memory_region.h"
+#include "google_breakpad/processor/stack_frame_symbolizer.h"
+
+namespace google_breakpad {
+
+class CallStack;
+class DumpContext;
+class StackFrameSymbolizer;
+
+using std::set;
+using std::vector;
+
+class Stackwalker {
+ public:
+ virtual ~Stackwalker() {}
+
+ // Populates the given CallStack by calling GetContextFrame and
+ // GetCallerFrame. The frames are further processed to fill all available
+ // data. Returns true if the stackwalk completed, or false if it was
+ // interrupted by SymbolSupplier::GetSymbolFile().
+ // Upon return, |modules_without_symbols| will be populated with pointers to
+ // the code modules (CodeModule*) that DON'T have symbols.
+ // |modules_with_corrupt_symbols| will be populated with pointers to the
+ // modules which have corrupt symbols. |modules_without_symbols| and
+ // |modules_with_corrupt_symbols| DO NOT take ownership of the code modules.
+ // The lifetime of these code modules is the same as the lifetime of the
+ // CodeModules passed to the StackWalker constructor (which currently
+ // happens to be the lifetime of the Breakpad's ProcessingState object).
+ // There is a check for duplicate modules so no duplicates are expected.
+ bool Walk(CallStack* stack,
+ vector<const CodeModule*>* modules_without_symbols,
+ vector<const CodeModule*>* modules_with_corrupt_symbols);
+
+ // Returns a new concrete subclass suitable for the CPU that a stack was
+ // generated on, according to the CPU type indicated by the context
+ // argument. If no suitable concrete subclass exists, returns NULL.
+ static Stackwalker* StackwalkerForCPU(
+ const SystemInfo* system_info,
+ DumpContext* context,
+ MemoryRegion* memory,
+ const CodeModules* modules,
+ const CodeModules* unloaded_modules,
+ StackFrameSymbolizer* resolver_helper);
+
+
+ static void set_max_frames(uint32_t max_frames) {
+ max_frames_ = max_frames;
+ max_frames_set_ = true;
+ }
+ static uint32_t max_frames() { return max_frames_; }
+
+ static void set_max_frames_scanned(uint32_t max_frames_scanned) {
+ max_frames_scanned_ = max_frames_scanned;
+ }
+
+ protected:
+ // system_info identifies the operating system, NULL or empty if unknown.
+ // memory identifies a MemoryRegion that provides the stack memory
+ // for the stack to walk. modules, if non-NULL, is a CodeModules
+ // object that is used to look up which code module each stack frame is
+ // associated with. frame_symbolizer is a StackFrameSymbolizer object that
+ // encapsulates the logic of how source line resolver interacts with symbol
+ // supplier to symbolize stack frame and look up caller frame information
+ // (see stack_frame_symbolizer.h).
+ // frame_symbolizer MUST NOT be NULL (asserted).
+ Stackwalker(const SystemInfo* system_info,
+ MemoryRegion* memory,
+ const CodeModules* modules,
+ StackFrameSymbolizer* frame_symbolizer);
+
+ // This can be used to filter out potential return addresses when
+ // the stack walker resorts to stack scanning.
+ // Returns true if any of:
+ // * This address is within a loaded module, but we don't have symbols
+ // for that module.
+ // * This address is within a loaded module for which we have symbols,
+ // and falls inside a function in that module.
+ // Returns false otherwise.
+ bool InstructionAddressSeemsValid(uint64_t address) const;
+
+ // Checks whether we should stop the stack trace.
+ // (either we reached the end-of-stack or we detected a
+ // broken callstack invariant)
+ bool TerminateWalk(uint64_t caller_ip,
+ uint64_t caller_sp,
+ uint64_t callee_sp,
+ bool first_unwind) const;
+
+ // The default number of words to search through on the stack
+ // for a return address.
+ static const int kRASearchWords;
+
+ template<typename InstructionType>
+ bool ScanForReturnAddress(InstructionType location_start,
+ InstructionType* location_found,
+ InstructionType* ip_found,
+ bool is_context_frame) {
+ // When searching for the caller of the context frame,
+ // allow the scanner to look farther down the stack.
+ const int search_words = is_context_frame ?
+ kRASearchWords * 4 :
+ kRASearchWords;
+
+ return ScanForReturnAddress(location_start, location_found, ip_found,
+ search_words);
+ }
+
+ // Scan the stack starting at location_start, looking for an address
+ // that looks like a valid instruction pointer. Addresses must
+ // 1) be contained in the current stack memory
+ // 2) pass the checks in InstructionAddressSeemsValid
+ //
+ // Returns true if a valid-looking instruction pointer was found.
+ // When returning true, sets location_found to the address at which
+ // the value was found, and ip_found to the value contained at that
+ // location in memory.
+ template<typename InstructionType>
+ bool ScanForReturnAddress(InstructionType location_start,
+ InstructionType* location_found,
+ InstructionType* ip_found,
+ int searchwords) {
+ for (InstructionType location = location_start;
+ location <= location_start + searchwords * sizeof(InstructionType);
+ location += sizeof(InstructionType)) {
+ InstructionType ip;
+ if (!memory_->GetMemoryAtAddress(location, &ip))
+ break;
+
+ if (modules_ && modules_->GetModuleForAddress(ip) &&
+ InstructionAddressSeemsValid(ip)) {
+ *ip_found = ip;
+ *location_found = location;
+ return true;
+ }
+ }
+ // nothing found
+ return false;
+ }
+
+ // Information about the system that produced the minidump. Subclasses
+ // and the SymbolSupplier may find this information useful.
+ const SystemInfo* system_info_;
+
+ // The stack memory to walk. Subclasses will require this region to
+ // get information from the stack.
+ MemoryRegion* memory_;
+
+ // A list of modules, for populating each StackFrame's module information.
+ // This field is optional and may be NULL.
+ const CodeModules* modules_;
+
+ // A list of unloaded modules, for populating frames which aren't matched
+ // to any loaded modules.
+ // This field is optional and may be NULL.
+ const CodeModules* unloaded_modules_;
+
+ protected:
+ // The StackFrameSymbolizer implementation.
+ StackFrameSymbolizer* frame_symbolizer_;
+
+ private:
+ // Obtains the context frame, the innermost called procedure in a stack
+ // trace. Returns NULL on failure. GetContextFrame allocates a new
+ // StackFrame (or StackFrame subclass), ownership of which is taken by
+ // the caller.
+ virtual StackFrame* GetContextFrame() = 0;
+
+ // Obtains a caller frame. Each call to GetCallerFrame should return the
+ // frame that called the last frame returned by GetContextFrame or
+ // GetCallerFrame. To aid this purpose, stack contains the CallStack
+ // made of frames that have already been walked. GetCallerFrame should
+ // return NULL on failure or when there are no more caller frames (when
+ // the end of the stack has been reached). GetCallerFrame allocates a new
+ // StackFrame (or StackFrame subclass), ownership of which is taken by
+ // the caller. |stack_scan_allowed| controls whether stack scanning is
+ // an allowable frame-recovery method, since it is desirable to be able to
+ // disable stack scanning in performance-critical use cases.
+ //
+ // CONSIDER: a way to differentiate between:
+ // - full stack traces
+ // - explicitly truncated traces (max_frames_)
+ // - stopping after max scanned frames
+ // - failed stack walk (breaking one of the stack walk invariants)
+ //
+ virtual StackFrame* GetCallerFrame(const CallStack* stack,
+ bool stack_scan_allowed) = 0;
+
+ // The maximum number of frames Stackwalker will walk through.
+ // This defaults to 1024 to prevent infinite loops.
+ static uint32_t max_frames_;
+
+ // Keep track of whether max_frames_ has been set by the user, since
+ // it affects whether or not an error message is printed in the case
+ // where an unwind got stopped by the limit.
+ static bool max_frames_set_;
+
+ // The maximum number of stack-scanned and otherwise untrustworthy
+ // frames allowed. Stack-scanning can be expensive, so the option to
+ // disable or limit it is helpful in cases where unwind performance is
+ // important. This defaults to 1024, the same as max_frames_.
+ static uint32_t max_frames_scanned_;
+};
+
+} // namespace google_breakpad
+
+
+#endif // GOOGLE_BREAKPAD_PROCESSOR_STACKWALKER_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/symbol_supplier.h b/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/symbol_supplier.h
new file mode 100644
index 0000000000..a042081f3b
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/symbol_supplier.h
@@ -0,0 +1,99 @@
+// 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.
+
+// The caller may implement the SymbolSupplier abstract base class
+// to provide symbols for a given module.
+
+#ifndef GOOGLE_BREAKPAD_PROCESSOR_SYMBOL_SUPPLIER_H__
+#define GOOGLE_BREAKPAD_PROCESSOR_SYMBOL_SUPPLIER_H__
+
+#include <string>
+#include "common/using_std_string.h"
+
+namespace google_breakpad {
+
+class CodeModule;
+struct SystemInfo;
+
+class SymbolSupplier {
+ public:
+ // Result type for GetSymbolFile
+ enum SymbolResult {
+ // no symbols were found, but continue processing
+ NOT_FOUND,
+
+ // symbols were found, and the path has been placed in symbol_file
+ FOUND,
+
+ // stops processing the minidump immediately
+ INTERRUPT
+ };
+
+ virtual ~SymbolSupplier() {}
+
+ // Retrieves the symbol file for the given CodeModule, placing the
+ // path in symbol_file if successful. system_info contains strings
+ // identifying the operating system and CPU; SymbolSupplier may use
+ // to help locate the symbol file. system_info may be NULL or its
+ // fields may be empty if these values are unknown. symbol_file
+ // must be a pointer to a valid string
+ virtual SymbolResult GetSymbolFile(const CodeModule *module,
+ const SystemInfo *system_info,
+ string *symbol_file) = 0;
+ // Same as above, except also places symbol data into symbol_data.
+ // If symbol_data is NULL, the data is not returned.
+ // TODO(nealsid) Once we have symbol data caching behavior implemented
+ // investigate making all symbol suppliers implement all methods,
+ // and make this pure virtual
+ virtual SymbolResult GetSymbolFile(const CodeModule *module,
+ const SystemInfo *system_info,
+ string *symbol_file,
+ string *symbol_data) = 0;
+
+ // Same as above, except allocates data buffer on heap and then places the
+ // symbol data into the buffer as C-string.
+ // SymbolSupplier is responsible for deleting the data buffer. After the call
+ // to GetCStringSymbolData(), the caller should call FreeSymbolData(const
+ // Module *module) once the data buffer is no longer needed.
+ // If symbol_data is not NULL, symbol supplier won't return FOUND unless it
+ // returns a valid buffer in symbol_data, e.g., returns INTERRUPT on memory
+ // allocation failure.
+ virtual SymbolResult GetCStringSymbolData(const CodeModule *module,
+ const SystemInfo *system_info,
+ string *symbol_file,
+ char **symbol_data,
+ size_t *symbol_data_size) = 0;
+
+ // Frees the data buffer allocated for the module in GetCStringSymbolData.
+ virtual void FreeSymbolData(const CodeModule *module) = 0;
+};
+
+} // namespace google_breakpad
+
+#endif // GOOGLE_BREAKPAD_PROCESSOR_SYMBOL_SUPPLIER_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/system_info.h b/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/system_info.h
new file mode 100644
index 0000000000..8d2f60be48
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/system_info.h
@@ -0,0 +1,106 @@
+// 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.
+
+// system_info.h: Information about the system that was running a program
+// when a crash report was produced.
+//
+// Author: Mark Mentovai
+
+#ifndef GOOGLE_BREAKPAD_PROCESSOR_SYSTEM_INFO_H__
+#define GOOGLE_BREAKPAD_PROCESSOR_SYSTEM_INFO_H__
+
+#include <string>
+
+#include "common/using_std_string.h"
+
+namespace google_breakpad {
+
+struct SystemInfo {
+ public:
+ SystemInfo() : os(), os_short(), os_version(), cpu(), cpu_info(),
+ cpu_count(0), gl_version(), gl_vendor(), gl_renderer() {}
+
+ // Resets the SystemInfo object to its default values.
+ void Clear() {
+ os.clear();
+ os_short.clear();
+ os_version.clear();
+ cpu.clear();
+ cpu_info.clear();
+ cpu_count = 0;
+ gl_version.clear();
+ gl_vendor.clear();
+ gl_renderer.clear();
+ }
+
+ // A string identifying the operating system, such as "Windows NT",
+ // "Mac OS X", or "Linux". If the information is present in the dump but
+ // its value is unknown, this field will contain a numeric value. If
+ // the information is not present in the dump, this field will be empty.
+ string os;
+
+ // A short form of the os string, using lowercase letters and no spaces,
+ // suitable for use in a filesystem. Possible values include "windows",
+ // "mac", "linux" and "nacl". Empty if the information is not present
+ // in the dump or if the OS given by the dump is unknown. The values
+ // stored in this field should match those used by
+ // MinidumpSystemInfo::GetOS.
+ string os_short;
+
+ // A string identifying the version of the operating system, such as
+ // "5.1.2600 Service Pack 2" or "10.4.8 8L2127". If the dump does not
+ // contain this information, this field will be empty.
+ string os_version;
+
+ // A string identifying the basic CPU family, such as "x86" or "ppc".
+ // If this information is present in the dump but its value is unknown,
+ // this field will contain a numeric value. If the information is not
+ // present in the dump, this field will be empty. The values stored in
+ // this field should match those used by MinidumpSystemInfo::GetCPU.
+ string cpu;
+
+ // A string further identifying the specific CPU, such as
+ // "GenuineIntel level 6 model 13 stepping 8". If the information is not
+ // present in the dump, or additional identifying information is not
+ // defined for the CPU family, this field will be empty.
+ string cpu_info;
+
+ // The number of processors in the system. Will be greater than one for
+ // multi-core systems.
+ int cpu_count;
+
+ // The GPU information. Currently only populated in microdumps.
+ string gl_version;
+ string gl_vendor;
+ string gl_renderer;
+};
+
+} // namespace google_breakpad
+
+#endif // GOOGLE_BREAKPAD_PROCESSOR_SYSTEM_INFO_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/address_map-inl.h b/toolkit/crashreporter/google-breakpad/src/processor/address_map-inl.h
new file mode 100644
index 0000000000..251c44781a
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/address_map-inl.h
@@ -0,0 +1,93 @@
+// 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.
+
+// address_map-inl.h: Address map implementation.
+//
+// See address_map.h for documentation.
+//
+// Author: Mark Mentovai
+
+#ifndef PROCESSOR_ADDRESS_MAP_INL_H__
+#define PROCESSOR_ADDRESS_MAP_INL_H__
+
+#include "processor/address_map.h"
+
+#include <assert.h>
+
+#include "processor/logging.h"
+
+namespace google_breakpad {
+
+template<typename AddressType, typename EntryType>
+bool AddressMap<AddressType, EntryType>::Store(const AddressType &address,
+ const EntryType &entry) {
+ // Ensure that the specified address doesn't conflict with something already
+ // in the map.
+ if (map_.find(address) != map_.end()) {
+ BPLOG(INFO) << "Store failed, address " << HexString(address) <<
+ " is already present";
+ return false;
+ }
+
+ map_.insert(MapValue(address, entry));
+ return true;
+}
+
+template<typename AddressType, typename EntryType>
+bool AddressMap<AddressType, EntryType>::Retrieve(
+ const AddressType &address,
+ EntryType *entry, AddressType *entry_address) const {
+ BPLOG_IF(ERROR, !entry) << "AddressMap::Retrieve requires |entry|";
+ assert(entry);
+
+ // upper_bound gives the first element whose key is greater than address,
+ // but we want the first element whose key is less than or equal to address.
+ // Decrement the iterator to get there, but not if the upper_bound already
+ // points to the beginning of the map - in that case, address is lower than
+ // the lowest stored key, so return false.
+ MapConstIterator iterator = map_.upper_bound(address);
+ if (iterator == map_.begin())
+ return false;
+ --iterator;
+
+ *entry = iterator->second;
+ if (entry_address)
+ *entry_address = iterator->first;
+
+ return true;
+}
+
+template<typename AddressType, typename EntryType>
+void AddressMap<AddressType, EntryType>::Clear() {
+ map_.clear();
+}
+
+} // namespace google_breakpad
+
+#endif // PROCESSOR_ADDRESS_MAP_INL_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/address_map.h b/toolkit/crashreporter/google-breakpad/src/processor/address_map.h
new file mode 100644
index 0000000000..2972cbb9f8
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/address_map.h
@@ -0,0 +1,85 @@
+// Copyright (c) 2006, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// address_map.h: Address maps.
+//
+// An address map contains a set of objects keyed by address. Objects are
+// retrieved from the map by returning the object with the highest key less
+// than or equal to the lookup key.
+//
+// Author: Mark Mentovai
+
+#ifndef PROCESSOR_ADDRESS_MAP_H__
+#define PROCESSOR_ADDRESS_MAP_H__
+
+#include <map>
+
+namespace google_breakpad {
+
+// Forward declarations (for later friend declarations).
+template<class, class> class AddressMapSerializer;
+
+template<typename AddressType, typename EntryType>
+class AddressMap {
+ public:
+ AddressMap() : map_() {}
+
+ // Inserts an entry into the map. Returns false without storing the entry
+ // if an entry is already stored in the map at the same address as specified
+ // by the address argument.
+ bool Store(const AddressType &address, const EntryType &entry);
+
+ // Locates the entry stored at the highest address less than or equal to
+ // the address argument. If there is no such range, returns false. The
+ // entry is returned in entry, which is a required argument. If
+ // entry_address is not NULL, it will be set to the address that the entry
+ // was stored at.
+ bool Retrieve(const AddressType &address,
+ EntryType *entry, AddressType *entry_address) const;
+
+ // Empties the address map, restoring it to the same state as when it was
+ // initially created.
+ void Clear();
+
+ private:
+ friend class AddressMapSerializer<AddressType, EntryType>;
+ friend class ModuleComparer;
+
+ // Convenience types.
+ typedef std::map<AddressType, EntryType> AddressToEntryMap;
+ typedef typename AddressToEntryMap::const_iterator MapConstIterator;
+ typedef typename AddressToEntryMap::value_type MapValue;
+
+ // Maps the address of each entry to an EntryType.
+ AddressToEntryMap map_;
+};
+
+} // namespace google_breakpad
+
+#endif // PROCESSOR_ADDRESS_MAP_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/address_map_unittest.cc b/toolkit/crashreporter/google-breakpad/src/processor/address_map_unittest.cc
new file mode 100644
index 0000000000..9b4095b16c
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/address_map_unittest.cc
@@ -0,0 +1,196 @@
+// 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.
+
+// address_map_unittest.cc: Unit tests for AddressMap.
+//
+// Author: Mark Mentovai
+
+#include <limits.h>
+#include <stdio.h>
+
+#include "processor/address_map-inl.h"
+#include "processor/linked_ptr.h"
+#include "processor/logging.h"
+
+#define ASSERT_TRUE(condition) \
+ if (!(condition)) { \
+ fprintf(stderr, "FAIL: %s @ %s:%d\n", #condition, __FILE__, __LINE__); \
+ return false; \
+ }
+
+#define ASSERT_FALSE(condition) ASSERT_TRUE(!(condition))
+
+#define ASSERT_EQ(e1, e2) ASSERT_TRUE((e1) == (e2))
+
+namespace {
+
+using google_breakpad::AddressMap;
+using google_breakpad::linked_ptr;
+
+// A CountedObject holds an int. A global (not thread safe!) count of
+// allocated CountedObjects is maintained to help test memory management.
+class CountedObject {
+ public:
+ explicit CountedObject(int id) : id_(id) { ++count_; }
+ ~CountedObject() { --count_; }
+
+ static int count() { return count_; }
+ int id() const { return id_; }
+
+ private:
+ static int count_;
+ int id_;
+};
+
+int CountedObject::count_;
+
+typedef int AddressType;
+typedef AddressMap< AddressType, linked_ptr<CountedObject> > TestMap;
+
+static bool DoAddressMapTest() {
+ ASSERT_EQ(CountedObject::count(), 0);
+
+ TestMap test_map;
+ linked_ptr<CountedObject> entry;
+ AddressType address;
+
+ // Check that a new map is truly empty.
+ ASSERT_FALSE(test_map.Retrieve(0, &entry, &address));
+ ASSERT_FALSE(test_map.Retrieve(INT_MIN, &entry, &address));
+ ASSERT_FALSE(test_map.Retrieve(INT_MAX, &entry, &address));
+
+ // Check that Clear clears the map without leaking.
+ ASSERT_EQ(CountedObject::count(), 0);
+ ASSERT_TRUE(test_map.Store(1,
+ linked_ptr<CountedObject>(new CountedObject(0))));
+ ASSERT_TRUE(test_map.Retrieve(1, &entry, &address));
+ ASSERT_EQ(CountedObject::count(), 1);
+ test_map.Clear();
+ ASSERT_EQ(CountedObject::count(), 1); // still holding entry in this scope
+
+ // Check that a cleared map is truly empty.
+ ASSERT_FALSE(test_map.Retrieve(0, &entry, &address));
+ ASSERT_FALSE(test_map.Retrieve(INT_MIN, &entry, &address));
+ ASSERT_FALSE(test_map.Retrieve(INT_MAX, &entry, &address));
+
+ // Check a single-element map.
+ ASSERT_TRUE(test_map.Store(10,
+ linked_ptr<CountedObject>(new CountedObject(1))));
+ ASSERT_FALSE(test_map.Retrieve(9, &entry, &address));
+ ASSERT_TRUE(test_map.Retrieve(10, &entry, &address));
+ ASSERT_EQ(CountedObject::count(), 1);
+ ASSERT_EQ(entry->id(), 1);
+ ASSERT_EQ(address, 10);
+ ASSERT_TRUE(test_map.Retrieve(11, &entry, &address));
+ ASSERT_TRUE(test_map.Retrieve(11, &entry, NULL)); // NULL ok here
+
+ // Add some more elements.
+ ASSERT_TRUE(test_map.Store(5,
+ linked_ptr<CountedObject>(new CountedObject(2))));
+ ASSERT_EQ(CountedObject::count(), 2);
+ ASSERT_TRUE(test_map.Store(20,
+ linked_ptr<CountedObject>(new CountedObject(3))));
+ ASSERT_TRUE(test_map.Store(15,
+ linked_ptr<CountedObject>(new CountedObject(4))));
+ ASSERT_FALSE(test_map.Store(10,
+ linked_ptr<CountedObject>(new CountedObject(5)))); // already in map
+ ASSERT_TRUE(test_map.Store(16,
+ linked_ptr<CountedObject>(new CountedObject(6))));
+ ASSERT_TRUE(test_map.Store(14,
+ linked_ptr<CountedObject>(new CountedObject(7))));
+
+ // Nothing was stored with a key under 5. Don't use ASSERT inside loops
+ // because it won't show exactly which key/entry/address failed.
+ for (AddressType key = 0; key < 5; ++key) {
+ if (test_map.Retrieve(key, &entry, &address)) {
+ fprintf(stderr,
+ "FAIL: retrieve %d expected false observed true @ %s:%d\n",
+ key, __FILE__, __LINE__);
+ return false;
+ }
+ }
+
+ // Check everything that was stored.
+ const int id_verify[] = { 0, 0, 0, 0, 0, // unused
+ 2, 2, 2, 2, 2, // 5 - 9
+ 1, 1, 1, 1, 7, // 10 - 14
+ 4, 6, 6, 6, 6, // 15 - 19
+ 3, 3, 3, 3, 3, // 20 - 24
+ 3, 3, 3, 3, 3 }; // 25 - 29
+ const AddressType address_verify[] = { 0, 0, 0, 0, 0, // unused
+ 5, 5, 5, 5, 5, // 5 - 9
+ 10, 10, 10, 10, 14, // 10 - 14
+ 15, 16, 16, 16, 16, // 15 - 19
+ 20, 20, 20, 20, 20, // 20 - 24
+ 20, 20, 20, 20, 20 }; // 25 - 29
+
+ for (AddressType key = 5; key < 30; ++key) {
+ if (!test_map.Retrieve(key, &entry, &address)) {
+ fprintf(stderr,
+ "FAIL: retrieve %d expected true observed false @ %s:%d\n",
+ key, __FILE__, __LINE__);
+ return false;
+ }
+ if (entry->id() != id_verify[key]) {
+ fprintf(stderr,
+ "FAIL: retrieve %d expected entry %d observed %d @ %s:%d\n",
+ key, id_verify[key], entry->id(), __FILE__, __LINE__);
+ return false;
+ }
+ if (address != address_verify[key]) {
+ fprintf(stderr,
+ "FAIL: retrieve %d expected address %d observed %d @ %s:%d\n",
+ key, address_verify[key], address, __FILE__, __LINE__);
+ return false;
+ }
+ }
+
+ // The stored objects should still be in the map.
+ ASSERT_EQ(CountedObject::count(), 6);
+
+ return true;
+}
+
+static bool RunTests() {
+ if (!DoAddressMapTest())
+ return false;
+
+ // Leak check.
+ ASSERT_EQ(CountedObject::count(), 0);
+
+ return true;
+}
+
+} // namespace
+
+int main(int argc, char **argv) {
+ BPLOG_INIT(&argc, &argv);
+
+ return RunTests() ? 0 : 1;
+}
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/basic_code_module.h b/toolkit/crashreporter/google-breakpad/src/processor/basic_code_module.h
new file mode 100644
index 0000000000..35d66a6075
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/basic_code_module.h
@@ -0,0 +1,121 @@
+// 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.
+
+// basic_code_module.h: Carries information about code modules that are loaded
+// into a process.
+//
+// This is a basic concrete implementation of CodeModule. It cannot be
+// instantiated directly, only based on other objects that implement
+// the CodeModule interface. It exists to provide a CodeModule implementation
+// a place to store information when the life of the original object (such as
+// a MinidumpModule) cannot be guaranteed.
+//
+// Author: Mark Mentovai
+
+#ifndef PROCESSOR_BASIC_CODE_MODULE_H__
+#define PROCESSOR_BASIC_CODE_MODULE_H__
+
+#include <string>
+
+#include "common/using_std_string.h"
+#include "google_breakpad/processor/code_module.h"
+
+namespace google_breakpad {
+
+class BasicCodeModule : public CodeModule {
+ public:
+ // Creates a new BasicCodeModule given any existing CodeModule
+ // implementation. This is useful to make a copy of the data relevant to
+ // the CodeModule interface without requiring all of the resources that
+ // other CodeModule implementations may require.
+ explicit BasicCodeModule(const CodeModule *that)
+ : base_address_(that->base_address()),
+ size_(that->size()),
+ shrink_down_delta_(that->shrink_down_delta()),
+ code_file_(that->code_file()),
+ code_identifier_(that->code_identifier()),
+ debug_file_(that->debug_file()),
+ debug_identifier_(that->debug_identifier()),
+ version_(that->version()),
+ is_unloaded_(that->is_unloaded()) {}
+
+ BasicCodeModule(uint64_t base_address, uint64_t size,
+ const string &code_file,
+ const string &code_identifier,
+ const string &debug_file,
+ const string &debug_identifier,
+ const string &version,
+ const bool is_unloaded = false)
+ : base_address_(base_address),
+ size_(size),
+ shrink_down_delta_(0),
+ code_file_(code_file),
+ code_identifier_(code_identifier),
+ debug_file_(debug_file),
+ debug_identifier_(debug_identifier),
+ version_(version),
+ is_unloaded_(is_unloaded)
+ {}
+ virtual ~BasicCodeModule() {}
+
+ // See code_module.h for descriptions of these methods and the associated
+ // members.
+ virtual uint64_t base_address() const { return base_address_; }
+ virtual uint64_t size() const { return size_; }
+ virtual uint64_t shrink_down_delta() const { return shrink_down_delta_; }
+ virtual void SetShrinkDownDelta(uint64_t shrink_down_delta) {
+ shrink_down_delta_ = shrink_down_delta;
+ }
+ virtual string code_file() const { return code_file_; }
+ virtual string code_identifier() const { return code_identifier_; }
+ virtual string debug_file() const { return debug_file_; }
+ virtual string debug_identifier() const { return debug_identifier_; }
+ virtual string version() const { return version_; }
+ virtual CodeModule* Copy() const { return new BasicCodeModule(this); }
+ virtual bool is_unloaded() const { return is_unloaded_; }
+
+ private:
+ uint64_t base_address_;
+ uint64_t size_;
+ uint64_t shrink_down_delta_;
+ string code_file_;
+ string code_identifier_;
+ string debug_file_;
+ string debug_identifier_;
+ string version_;
+ bool is_unloaded_;
+
+ // Disallow copy constructor and assignment operator.
+ BasicCodeModule(const BasicCodeModule &that);
+ void operator=(const BasicCodeModule &that);
+};
+
+} // namespace google_breakpad
+
+#endif // PROCESSOR_BASIC_CODE_MODULE_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/basic_code_modules.cc b/toolkit/crashreporter/google-breakpad/src/processor/basic_code_modules.cc
new file mode 100644
index 0000000000..f71aeb7476
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/basic_code_modules.cc
@@ -0,0 +1,152 @@
+// 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.
+
+// basic_code_modules.cc: Contains all of the CodeModule objects that
+// were loaded into a single process.
+//
+// See basic_code_modules.h for documentation.
+//
+// Author: Mark Mentovai
+
+#include "processor/basic_code_modules.h"
+
+#include <assert.h>
+
+#include <vector>
+
+#include "google_breakpad/processor/code_module.h"
+#include "processor/linked_ptr.h"
+#include "processor/logging.h"
+#include "processor/range_map-inl.h"
+
+namespace google_breakpad {
+
+using std::vector;
+
+BasicCodeModules::BasicCodeModules(const CodeModules* that,
+ MergeRangeStrategy strategy)
+ : main_address_(0), map_() {
+ BPLOG_IF(ERROR, !that) << "BasicCodeModules::BasicCodeModules requires "
+ "|that|";
+ assert(that);
+
+ map_.SetMergeStrategy(strategy);
+
+ const CodeModule *main_module = that->GetMainModule();
+ if (main_module)
+ main_address_ = main_module->base_address();
+
+ unsigned int count = that->module_count();
+ for (unsigned int i = 0; i < count; ++i) {
+ // Make a copy of the module and insert it into the map. Use
+ // GetModuleAtIndex because ordering is unimportant when slurping the
+ // entire list, and GetModuleAtIndex may be faster than
+ // GetModuleAtSequence.
+ linked_ptr<const CodeModule> module(that->GetModuleAtIndex(i)->Copy());
+ if (!map_.StoreRange(module->base_address(), module->size(), module)) {
+ BPLOG(ERROR) << "Module " << module->code_file()
+ << " could not be stored";
+ }
+ }
+
+ // Report modules with shrunk ranges.
+ for (unsigned int i = 0; i < count; ++i) {
+ linked_ptr<const CodeModule> module(that->GetModuleAtIndex(i)->Copy());
+ uint64_t delta = 0;
+ if (map_.RetrieveRange(module->base_address() + module->size() - 1,
+ &module, NULL /* base */, &delta, NULL /* size */) &&
+ delta > 0) {
+ BPLOG(INFO) << "The range for module " << module->code_file()
+ << " was shrunk down by " << HexString(delta) << " bytes.";
+ linked_ptr<CodeModule> shrunk_range_module(module->Copy());
+ shrunk_range_module->SetShrinkDownDelta(delta);
+ shrunk_range_modules_.push_back(shrunk_range_module);
+ }
+ }
+
+ // TODO(ivanpe): Report modules with conflicting ranges. The list of such
+ // modules should be copied from |that|.
+}
+
+BasicCodeModules::BasicCodeModules() : main_address_(0), map_() { }
+
+BasicCodeModules::~BasicCodeModules() {
+}
+
+unsigned int BasicCodeModules::module_count() const {
+ return map_.GetCount();
+}
+
+const CodeModule* BasicCodeModules::GetModuleForAddress(
+ uint64_t address) const {
+ linked_ptr<const CodeModule> module;
+ if (!map_.RetrieveRange(address, &module, NULL /* base */, NULL /* delta */,
+ NULL /* size */)) {
+ BPLOG(INFO) << "No module at " << HexString(address);
+ return NULL;
+ }
+
+ return module.get();
+}
+
+const CodeModule* BasicCodeModules::GetMainModule() const {
+ return GetModuleForAddress(main_address_);
+}
+
+const CodeModule* BasicCodeModules::GetModuleAtSequence(
+ unsigned int sequence) const {
+ linked_ptr<const CodeModule> module;
+ if (!map_.RetrieveRangeAtIndex(sequence, &module, NULL /* base */,
+ NULL /* delta */, NULL /* size */)) {
+ BPLOG(ERROR) << "RetrieveRangeAtIndex failed for sequence " << sequence;
+ return NULL;
+ }
+
+ return module.get();
+}
+
+const CodeModule* BasicCodeModules::GetModuleAtIndex(
+ unsigned int index) const {
+ // This class stores everything in a RangeMap, without any more-efficient
+ // way to walk the list of CodeModule objects. Implement GetModuleAtIndex
+ // using GetModuleAtSequence, which meets all of the requirements, and
+ // in addition, guarantees ordering.
+ return GetModuleAtSequence(index);
+}
+
+const CodeModules* BasicCodeModules::Copy() const {
+ return new BasicCodeModules(this, map_.GetMergeStrategy());
+}
+
+vector<linked_ptr<const CodeModule> >
+BasicCodeModules::GetShrunkRangeModules() const {
+ return shrunk_range_modules_;
+}
+
+} // namespace google_breakpad
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/basic_code_modules.h b/toolkit/crashreporter/google-breakpad/src/processor/basic_code_modules.h
new file mode 100644
index 0000000000..45ebc53b24
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/basic_code_modules.h
@@ -0,0 +1,97 @@
+// 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.
+
+// basic_code_modules.h: Contains all of the CodeModule objects that
+// were loaded into a single process.
+//
+// This is a basic concrete implementation of CodeModules. It cannot be
+// instantiated directly, only based on other objects that implement
+// the CodeModules interface. It exists to provide a CodeModules
+// implementation a place to store information when the life of the original
+// object (such as a MinidumpModuleList) cannot be guaranteed.
+//
+// Author: Mark Mentovai
+
+#ifndef PROCESSOR_BASIC_CODE_MODULES_H__
+#define PROCESSOR_BASIC_CODE_MODULES_H__
+
+#include <stddef.h>
+
+#include <vector>
+
+#include "google_breakpad/processor/code_modules.h"
+#include "processor/linked_ptr.h"
+#include "processor/range_map.h"
+
+namespace google_breakpad {
+
+class BasicCodeModules : public CodeModules {
+ public:
+ // Creates a new BasicCodeModules object given any existing CodeModules
+ // implementation. This is useful to make a copy of the data relevant to
+ // the CodeModules and CodeModule interfaces without requiring all of the
+ // resources that other implementations may require. A copy will be
+ // made of each contained CodeModule using CodeModule::Copy.
+ BasicCodeModules(const CodeModules *that, MergeRangeStrategy strategy);
+
+ virtual ~BasicCodeModules();
+
+ // See code_modules.h for descriptions of these methods.
+ virtual unsigned int module_count() const;
+ virtual const CodeModule* GetModuleForAddress(uint64_t address) const;
+ virtual const CodeModule* GetMainModule() const;
+ virtual const CodeModule* GetModuleAtSequence(unsigned int sequence) const;
+ virtual const CodeModule* GetModuleAtIndex(unsigned int index) const;
+ virtual const CodeModules* Copy() const;
+ virtual std::vector<linked_ptr<const CodeModule> >
+ GetShrunkRangeModules() const;
+
+ protected:
+ BasicCodeModules();
+
+ // The base address of the main module.
+ uint64_t main_address_;
+
+ // The map used to contain each CodeModule, keyed by each CodeModule's
+ // address range.
+ RangeMap<uint64_t, linked_ptr<const CodeModule> > map_;
+
+ // A vector of all CodeModules that were shrunk downs due to
+ // address range conflicts.
+ std::vector<linked_ptr<const CodeModule> > shrunk_range_modules_;
+
+ private:
+ // Disallow copy constructor and assignment operator.
+ BasicCodeModules(const BasicCodeModules &that);
+ void operator=(const BasicCodeModules &that);
+};
+
+} // namespace google_breakpad
+
+#endif // PROCESSOR_BASIC_CODE_MODULES_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/basic_source_line_resolver.cc b/toolkit/crashreporter/google-breakpad/src/processor/basic_source_line_resolver.cc
new file mode 100644
index 0000000000..c4aa949caa
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/basic_source_line_resolver.cc
@@ -0,0 +1,657 @@
+// 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.
+//
+// basic_source_line_resolver.cc: BasicSourceLineResolver implementation.
+//
+// See basic_source_line_resolver.h and basic_source_line_resolver_types.h
+// for documentation.
+
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <limits>
+#include <map>
+#include <utility>
+#include <vector>
+
+#include "google_breakpad/processor/basic_source_line_resolver.h"
+#include "processor/basic_source_line_resolver_types.h"
+#include "processor/module_factory.h"
+
+#include "processor/tokenize.h"
+
+using std::map;
+using std::vector;
+using std::make_pair;
+
+namespace google_breakpad {
+
+#ifdef _WIN32
+#ifdef _MSC_VER
+#define strtok_r strtok_s
+#endif
+#define strtoull _strtoui64
+#endif
+
+namespace {
+
+// Utility function to tokenize given the presence of an optional initial
+// field. In this case, optional_field is the expected string for the optional
+// field, and max_tokens is the maximum number of tokens including the optional
+// field. Refer to the documentation for Tokenize for descriptions of the other
+// arguments.
+bool TokenizeWithOptionalField(char *line,
+ const char *optional_field,
+ const char *separators,
+ int max_tokens,
+ vector<char*> *tokens) {
+ // First tokenize assuming the optional field is not present. If we then see
+ // the optional field, additionally tokenize the last token into two tokens.
+ if (!Tokenize(line, separators, max_tokens - 1, tokens)) {
+ return false;
+ }
+
+ if (strcmp(tokens->front(), optional_field) == 0) {
+ // The optional field is present. Split the last token in two to recover the
+ // field prior to the last.
+ vector<char*> last_tokens;
+ if (!Tokenize(tokens->back(), separators, 2, &last_tokens)) {
+ return false;
+ }
+ // Replace the previous last token with the two new tokens.
+ tokens->pop_back();
+ tokens->push_back(last_tokens[0]);
+ tokens->push_back(last_tokens[1]);
+ }
+
+ return true;
+}
+
+} // namespace
+
+static const char *kWhitespace = " \r\n";
+static const int kMaxErrorsPrinted = 5;
+static const int kMaxErrorsBeforeBailing = 100;
+
+BasicSourceLineResolver::BasicSourceLineResolver() :
+ SourceLineResolverBase(new BasicModuleFactory) { }
+
+// static
+void BasicSourceLineResolver::Module::LogParseError(
+ const string &message,
+ int line_number,
+ int *num_errors) {
+ if (++(*num_errors) <= kMaxErrorsPrinted) {
+ if (line_number > 0) {
+ BPLOG(ERROR) << "Line " << line_number << ": " << message;
+ } else {
+ BPLOG(ERROR) << message;
+ }
+ }
+}
+
+bool BasicSourceLineResolver::Module::LoadMapFromMemory(
+ char *memory_buffer,
+ size_t memory_buffer_size) {
+ linked_ptr<Function> cur_func;
+ int line_number = 0;
+ int num_errors = 0;
+ char *save_ptr;
+
+ // If the length is 0, we can still pretend we have a symbol file. This is
+ // for scenarios that want to test symbol lookup, but don't necessarily care
+ // if certain modules do not have any information, like system libraries.
+ if (memory_buffer_size == 0) {
+ return true;
+ }
+
+ // Make sure the last character is null terminator.
+ size_t last_null_terminator = memory_buffer_size - 1;
+ if (memory_buffer[last_null_terminator] != '\0') {
+ memory_buffer[last_null_terminator] = '\0';
+ }
+
+ // Skip any null terminators at the end of the memory buffer, and make sure
+ // there are no other null terminators in the middle of the memory buffer.
+ bool has_null_terminator_in_the_middle = false;
+ while (last_null_terminator > 0 &&
+ memory_buffer[last_null_terminator - 1] == '\0') {
+ last_null_terminator--;
+ }
+ for (size_t i = 0; i < last_null_terminator; i++) {
+ if (memory_buffer[i] == '\0') {
+ memory_buffer[i] = '_';
+ has_null_terminator_in_the_middle = true;
+ }
+ }
+ if (has_null_terminator_in_the_middle) {
+ LogParseError(
+ "Null terminator is not expected in the middle of the symbol data",
+ line_number,
+ &num_errors);
+ }
+
+ char *buffer;
+ buffer = strtok_r(memory_buffer, "\r\n", &save_ptr);
+
+ while (buffer != NULL) {
+ ++line_number;
+
+ if (strncmp(buffer, "FILE ", 5) == 0) {
+ if (!ParseFile(buffer)) {
+ LogParseError("ParseFile on buffer failed", line_number, &num_errors);
+ }
+ } else if (strncmp(buffer, "STACK ", 6) == 0) {
+ if (!ParseStackInfo(buffer)) {
+ LogParseError("ParseStackInfo failed", line_number, &num_errors);
+ }
+ } else if (strncmp(buffer, "FUNC ", 5) == 0) {
+ cur_func.reset(ParseFunction(buffer));
+ if (!cur_func.get()) {
+ LogParseError("ParseFunction failed", line_number, &num_errors);
+ } else {
+ // StoreRange will fail if the function has an invalid address or size.
+ // We'll silently ignore this, the function and any corresponding lines
+ // will be destroyed when cur_func is released.
+ functions_.StoreRange(cur_func->address, cur_func->size, cur_func);
+ }
+ } else if (strncmp(buffer, "PUBLIC ", 7) == 0) {
+ // Clear cur_func: public symbols don't contain line number information.
+ cur_func.reset();
+
+ if (!ParsePublicSymbol(buffer)) {
+ LogParseError("ParsePublicSymbol failed", line_number, &num_errors);
+ }
+ } else if (strncmp(buffer, "MODULE ", 7) == 0) {
+ // Ignore these. They're not of any use to BasicSourceLineResolver,
+ // which is fed modules by a SymbolSupplier. These lines are present to
+ // aid other tools in properly placing symbol files so that they can
+ // be accessed by a SymbolSupplier.
+ //
+ // MODULE <guid> <age> <filename>
+ } else if (strncmp(buffer, "INFO ", 5) == 0) {
+ // Ignore these as well, they're similarly just for housekeeping.
+ //
+ // INFO CODE_ID <code id> <filename>
+ } else {
+ if (!cur_func.get()) {
+ LogParseError("Found source line data without a function",
+ line_number, &num_errors);
+ } else {
+ Line *line = ParseLine(buffer);
+ if (!line) {
+ LogParseError("ParseLine failed", line_number, &num_errors);
+ } else {
+ cur_func->lines.StoreRange(line->address, line->size,
+ linked_ptr<Line>(line));
+ }
+ }
+ }
+ if (num_errors > kMaxErrorsBeforeBailing) {
+ break;
+ }
+ buffer = strtok_r(NULL, "\r\n", &save_ptr);
+ }
+ is_corrupt_ = num_errors > 0;
+ return true;
+}
+
+void BasicSourceLineResolver::Module::LookupAddress(StackFrame *frame) const {
+ MemAddr address = frame->instruction - frame->module->base_address();
+
+ // First, look for a FUNC record that covers address. Use
+ // RetrieveNearestRange instead of RetrieveRange so that, if there
+ // is no such function, we can use the next function to bound the
+ // extent of the PUBLIC symbol we find, below. This does mean we
+ // need to check that address indeed falls within the function we
+ // find; do the range comparison in an overflow-friendly way.
+ linked_ptr<Function> func;
+ linked_ptr<PublicSymbol> public_symbol;
+ MemAddr function_base;
+ MemAddr function_size;
+ MemAddr public_address;
+ if (functions_.RetrieveNearestRange(address, &func, &function_base,
+ NULL /* delta */, &function_size) &&
+ address >= function_base && address - function_base < function_size) {
+ frame->function_name = func->name;
+ frame->function_base = frame->module->base_address() + function_base;
+
+ linked_ptr<Line> line;
+ MemAddr line_base;
+ if (func->lines.RetrieveRange(address, &line, &line_base, NULL /* delta */,
+ NULL /* size */)) {
+ FileMap::const_iterator it = files_.find(line->source_file_id);
+ if (it != files_.end()) {
+ frame->source_file_name = files_.find(line->source_file_id)->second;
+ }
+ frame->source_line = line->line;
+ frame->source_line_base = frame->module->base_address() + line_base;
+ }
+ } else if (public_symbols_.Retrieve(address,
+ &public_symbol, &public_address) &&
+ (!func.get() || public_address > function_base)) {
+ frame->function_name = public_symbol->name;
+ frame->function_base = frame->module->base_address() + public_address;
+ }
+}
+
+WindowsFrameInfo *BasicSourceLineResolver::Module::FindWindowsFrameInfo(
+ const StackFrame *frame) const {
+ MemAddr address = frame->instruction - frame->module->base_address();
+ scoped_ptr<WindowsFrameInfo> result(new WindowsFrameInfo());
+
+ // We only know about WindowsFrameInfo::STACK_INFO_FRAME_DATA and
+ // WindowsFrameInfo::STACK_INFO_FPO. Prefer them in this order.
+ // WindowsFrameInfo::STACK_INFO_FRAME_DATA is the newer type that
+ // includes its own program string.
+ // WindowsFrameInfo::STACK_INFO_FPO is the older type
+ // corresponding to the FPO_DATA struct. See stackwalker_x86.cc.
+ linked_ptr<WindowsFrameInfo> frame_info;
+ if ((windows_frame_info_[WindowsFrameInfo::STACK_INFO_FRAME_DATA]
+ .RetrieveRange(address, &frame_info))
+ || (windows_frame_info_[WindowsFrameInfo::STACK_INFO_FPO]
+ .RetrieveRange(address, &frame_info))) {
+ result->CopyFrom(*frame_info.get());
+ return result.release();
+ }
+
+ // Even without a relevant STACK line, many functions contain
+ // information about how much space their parameters consume on the
+ // stack. Use RetrieveNearestRange instead of RetrieveRange, so that
+ // we can use the function to bound the extent of the PUBLIC symbol,
+ // below. However, this does mean we need to check that ADDRESS
+ // falls within the retrieved function's range; do the range
+ // comparison in an overflow-friendly way.
+ linked_ptr<Function> function;
+ MemAddr function_base, function_size;
+ if (functions_.RetrieveNearestRange(address, &function, &function_base,
+ NULL /* delta */, &function_size) &&
+ address >= function_base && address - function_base < function_size) {
+ result->parameter_size = function->parameter_size;
+ result->valid |= WindowsFrameInfo::VALID_PARAMETER_SIZE;
+ return result.release();
+ }
+
+ // PUBLIC symbols might have a parameter size. Use the function we
+ // found above to limit the range the public symbol covers.
+ linked_ptr<PublicSymbol> public_symbol;
+ MemAddr public_address;
+ if (public_symbols_.Retrieve(address, &public_symbol, &public_address) &&
+ (!function.get() || public_address > function_base)) {
+ result->parameter_size = public_symbol->parameter_size;
+ }
+
+ return NULL;
+}
+
+CFIFrameInfo *BasicSourceLineResolver::Module::FindCFIFrameInfo(
+ const StackFrame *frame) const {
+ MemAddr address = frame->instruction - frame->module->base_address();
+ MemAddr initial_base, initial_size;
+ string initial_rules;
+
+ // Find the initial rule whose range covers this address. That
+ // provides an initial set of register recovery rules. Then, walk
+ // forward from the initial rule's starting address to frame's
+ // instruction address, applying delta rules.
+ if (!cfi_initial_rules_.RetrieveRange(address, &initial_rules, &initial_base,
+ NULL /* delta */, &initial_size)) {
+ return NULL;
+ }
+
+ // Create a frame info structure, and populate it with the rules from
+ // the STACK CFI INIT record.
+ scoped_ptr<CFIFrameInfo> rules(new CFIFrameInfo());
+ if (!ParseCFIRuleSet(initial_rules, rules.get()))
+ return NULL;
+
+ // Find the first delta rule that falls within the initial rule's range.
+ map<MemAddr, string>::const_iterator delta =
+ cfi_delta_rules_.lower_bound(initial_base);
+
+ // Apply delta rules up to and including the frame's address.
+ while (delta != cfi_delta_rules_.end() && delta->first <= address) {
+ ParseCFIRuleSet(delta->second, rules.get());
+ delta++;
+ }
+
+ return rules.release();
+}
+
+bool BasicSourceLineResolver::Module::ParseFile(char *file_line) {
+ long index;
+ char *filename;
+ if (SymbolParseHelper::ParseFile(file_line, &index, &filename)) {
+ files_.insert(make_pair(index, string(filename)));
+ return true;
+ }
+ return false;
+}
+
+BasicSourceLineResolver::Function*
+BasicSourceLineResolver::Module::ParseFunction(char *function_line) {
+ bool is_multiple;
+ uint64_t address;
+ uint64_t size;
+ long stack_param_size;
+ char *name;
+ if (SymbolParseHelper::ParseFunction(function_line, &is_multiple, &address,
+ &size, &stack_param_size, &name)) {
+ return new Function(name, address, size, stack_param_size, is_multiple);
+ }
+ return NULL;
+}
+
+BasicSourceLineResolver::Line* BasicSourceLineResolver::Module::ParseLine(
+ char *line_line) {
+ uint64_t address;
+ uint64_t size;
+ long line_number;
+ long source_file;
+
+ if (SymbolParseHelper::ParseLine(line_line, &address, &size, &line_number,
+ &source_file)) {
+ return new Line(address, size, source_file, line_number);
+ }
+ return NULL;
+}
+
+bool BasicSourceLineResolver::Module::ParsePublicSymbol(char *public_line) {
+ bool is_multiple;
+ uint64_t address;
+ long stack_param_size;
+ char *name;
+
+ if (SymbolParseHelper::ParsePublicSymbol(public_line, &is_multiple, &address,
+ &stack_param_size, &name)) {
+ // A few public symbols show up with an address of 0. This has been seen
+ // in the dumped output of ntdll.pdb for symbols such as _CIlog, _CIpow,
+ // RtlDescribeChunkLZNT1, and RtlReserveChunkLZNT1. They would conflict
+ // with one another if they were allowed into the public_symbols_ map,
+ // but since the address is obviously invalid, gracefully accept them
+ // as input without putting them into the map.
+ if (address == 0) {
+ return true;
+ }
+
+ linked_ptr<PublicSymbol> symbol(new PublicSymbol(name, address,
+ stack_param_size,
+ is_multiple));
+ return public_symbols_.Store(address, symbol);
+ }
+ return false;
+}
+
+bool BasicSourceLineResolver::Module::ParseStackInfo(char *stack_info_line) {
+ // Skip "STACK " prefix.
+ stack_info_line += 6;
+
+ // Find the token indicating what sort of stack frame walking
+ // information this is.
+ while (*stack_info_line == ' ')
+ stack_info_line++;
+ const char *platform = stack_info_line;
+ while (!strchr(kWhitespace, *stack_info_line))
+ stack_info_line++;
+ *stack_info_line++ = '\0';
+
+ // MSVC stack frame info.
+ if (strcmp(platform, "WIN") == 0) {
+ int type = 0;
+ uint64_t rva, code_size;
+ linked_ptr<WindowsFrameInfo>
+ stack_frame_info(WindowsFrameInfo::ParseFromString(stack_info_line,
+ type,
+ rva,
+ code_size));
+ if (stack_frame_info == NULL)
+ return false;
+
+ // TODO(mmentovai): I wanted to use StoreRange's return value as this
+ // method's return value, but MSVC infrequently outputs stack info that
+ // violates the containment rules. This happens with a section of code
+ // in strncpy_s in test_app.cc (testdata/minidump2). There, problem looks
+ // like this:
+ // STACK WIN 4 4242 1a a 0 ... (STACK WIN 4 base size prolog 0 ...)
+ // STACK WIN 4 4243 2e 9 0 ...
+ // ContainedRangeMap treats these two blocks as conflicting. In reality,
+ // when the prolog lengths are taken into account, the actual code of
+ // these blocks doesn't conflict. However, we can't take the prolog lengths
+ // into account directly here because we'd wind up with a different set
+ // of range conflicts when MSVC outputs stack info like this:
+ // STACK WIN 4 1040 73 33 0 ...
+ // STACK WIN 4 105a 59 19 0 ...
+ // because in both of these entries, the beginning of the code after the
+ // prolog is at 0x1073, and the last byte of contained code is at 0x10b2.
+ // Perhaps we could get away with storing ranges by rva + prolog_size
+ // if ContainedRangeMap were modified to allow replacement of
+ // already-stored values.
+
+ windows_frame_info_[type].StoreRange(rva, code_size, stack_frame_info);
+ return true;
+ } else if (strcmp(platform, "CFI") == 0) {
+ // DWARF CFI stack frame info
+ return ParseCFIFrameInfo(stack_info_line);
+ } else {
+ // Something unrecognized.
+ return false;
+ }
+}
+
+bool BasicSourceLineResolver::Module::ParseCFIFrameInfo(
+ char *stack_info_line) {
+ char *cursor;
+
+ // Is this an INIT record or a delta record?
+ char *init_or_address = strtok_r(stack_info_line, " \r\n", &cursor);
+ if (!init_or_address)
+ return false;
+
+ if (strcmp(init_or_address, "INIT") == 0) {
+ // This record has the form "STACK INIT <address> <size> <rules...>".
+ char *address_field = strtok_r(NULL, " \r\n", &cursor);
+ if (!address_field) return false;
+
+ char *size_field = strtok_r(NULL, " \r\n", &cursor);
+ if (!size_field) return false;
+
+ char *initial_rules = strtok_r(NULL, "\r\n", &cursor);
+ if (!initial_rules) return false;
+
+ MemAddr address = strtoul(address_field, NULL, 16);
+ MemAddr size = strtoul(size_field, NULL, 16);
+ cfi_initial_rules_.StoreRange(address, size, initial_rules);
+ return true;
+ }
+
+ // This record has the form "STACK <address> <rules...>".
+ char *address_field = init_or_address;
+ char *delta_rules = strtok_r(NULL, "\r\n", &cursor);
+ if (!delta_rules) return false;
+ MemAddr address = strtoul(address_field, NULL, 16);
+ cfi_delta_rules_[address] = delta_rules;
+ return true;
+}
+
+// static
+bool SymbolParseHelper::ParseFile(char *file_line, long *index,
+ char **filename) {
+ // FILE <id> <filename>
+ assert(strncmp(file_line, "FILE ", 5) == 0);
+ file_line += 5; // skip prefix
+
+ vector<char*> tokens;
+ if (!Tokenize(file_line, kWhitespace, 2, &tokens)) {
+ return false;
+ }
+
+ char *after_number;
+ *index = strtol(tokens[0], &after_number, 10);
+ if (!IsValidAfterNumber(after_number) || *index < 0 ||
+ *index == std::numeric_limits<long>::max()) {
+ return false;
+ }
+
+ *filename = tokens[1];
+ if (!*filename) {
+ return false;
+ }
+
+ return true;
+}
+
+// static
+bool SymbolParseHelper::ParseFunction(char *function_line, bool *is_multiple,
+ uint64_t *address, uint64_t *size,
+ long *stack_param_size, char **name) {
+ // FUNC [<multiple>] <address> <size> <stack_param_size> <name>
+ assert(strncmp(function_line, "FUNC ", 5) == 0);
+ function_line += 5; // skip prefix
+
+ vector<char*> tokens;
+ if (!TokenizeWithOptionalField(function_line, "m", kWhitespace, 5, &tokens)) {
+ return false;
+ }
+
+ *is_multiple = strcmp(tokens[0], "m") == 0;
+ int next_token = *is_multiple ? 1 : 0;
+
+ char *after_number;
+ *address = strtoull(tokens[next_token++], &after_number, 16);
+ if (!IsValidAfterNumber(after_number) ||
+ *address == std::numeric_limits<unsigned long long>::max()) {
+ return false;
+ }
+ *size = strtoull(tokens[next_token++], &after_number, 16);
+ if (!IsValidAfterNumber(after_number) ||
+ *size == std::numeric_limits<unsigned long long>::max()) {
+ return false;
+ }
+ *stack_param_size = strtol(tokens[next_token++], &after_number, 16);
+ if (!IsValidAfterNumber(after_number) ||
+ *stack_param_size == std::numeric_limits<long>::max() ||
+ *stack_param_size < 0) {
+ return false;
+ }
+ *name = tokens[next_token++];
+
+ return true;
+}
+
+// static
+bool SymbolParseHelper::ParseLine(char *line_line, uint64_t *address,
+ uint64_t *size, long *line_number,
+ long *source_file) {
+ // <address> <size> <line number> <source file id>
+ vector<char*> tokens;
+ if (!Tokenize(line_line, kWhitespace, 4, &tokens)) {
+ return false;
+ }
+
+ char *after_number;
+ *address = strtoull(tokens[0], &after_number, 16);
+ if (!IsValidAfterNumber(after_number) ||
+ *address == std::numeric_limits<unsigned long long>::max()) {
+ return false;
+ }
+ *size = strtoull(tokens[1], &after_number, 16);
+ if (!IsValidAfterNumber(after_number) ||
+ *size == std::numeric_limits<unsigned long long>::max()) {
+ return false;
+ }
+ *line_number = strtol(tokens[2], &after_number, 10);
+ if (!IsValidAfterNumber(after_number) ||
+ *line_number == std::numeric_limits<long>::max()) {
+ return false;
+ }
+ *source_file = strtol(tokens[3], &after_number, 10);
+ if (!IsValidAfterNumber(after_number) || *source_file < 0 ||
+ *source_file == std::numeric_limits<long>::max()) {
+ return false;
+ }
+
+ // Valid line numbers normally start from 1, however there are functions that
+ // are associated with a source file but not associated with any line number
+ // (block helper function) and for such functions the symbol file contains 0
+ // for the line numbers. Hence, 0 should be treated as a valid line number.
+ // For more information on block helper functions, please, take a look at:
+ // http://clang.llvm.org/docs/Block-ABI-Apple.html
+ if (*line_number < 0) {
+ return false;
+ }
+
+ return true;
+}
+
+// static
+bool SymbolParseHelper::ParsePublicSymbol(char *public_line, bool *is_multiple,
+ uint64_t *address,
+ long *stack_param_size,
+ char **name) {
+ // PUBLIC [<multiple>] <address> <stack_param_size> <name>
+ assert(strncmp(public_line, "PUBLIC ", 7) == 0);
+ public_line += 7; // skip prefix
+
+ vector<char*> tokens;
+ if (!TokenizeWithOptionalField(public_line, "m", kWhitespace, 4, &tokens)) {
+ return false;
+ }
+
+ *is_multiple = strcmp(tokens[0], "m") == 0;
+ int next_token = *is_multiple ? 1 : 0;
+
+ char *after_number;
+ *address = strtoull(tokens[next_token++], &after_number, 16);
+ if (!IsValidAfterNumber(after_number) ||
+ *address == std::numeric_limits<unsigned long long>::max()) {
+ return false;
+ }
+ *stack_param_size = strtol(tokens[next_token++], &after_number, 16);
+ if (!IsValidAfterNumber(after_number) ||
+ *stack_param_size == std::numeric_limits<long>::max() ||
+ *stack_param_size < 0) {
+ return false;
+ }
+ *name = tokens[next_token++];
+
+ return true;
+}
+
+// static
+bool SymbolParseHelper::IsValidAfterNumber(char *after_number) {
+ if (after_number != NULL && strchr(kWhitespace, *after_number) != NULL) {
+ return true;
+ }
+ return false;
+}
+
+} // namespace google_breakpad
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/basic_source_line_resolver_types.h b/toolkit/crashreporter/google-breakpad/src/processor/basic_source_line_resolver_types.h
new file mode 100644
index 0000000000..89eb57e88a
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/basic_source_line_resolver_types.h
@@ -0,0 +1,179 @@
+// 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.
+//
+// basic_source_line_types.h: definition of nested classes/structs in
+// BasicSourceLineResolver. It moves the definitions out of
+// basic_source_line_resolver.cc, so that other classes could have access
+// to these private nested types without including basic_source_line_resolver.cc
+//
+// Author: Siyang Xie (lambxsy@google.com)
+
+#ifndef PROCESSOR_BASIC_SOURCE_LINE_RESOLVER_TYPES_H__
+#define PROCESSOR_BASIC_SOURCE_LINE_RESOLVER_TYPES_H__
+
+#include <map>
+#include <string>
+
+#include "common/scoped_ptr.h"
+#include "google_breakpad/processor/basic_source_line_resolver.h"
+#include "processor/source_line_resolver_base_types.h"
+
+#include "processor/address_map-inl.h"
+#include "processor/range_map-inl.h"
+#include "processor/contained_range_map-inl.h"
+
+#include "processor/linked_ptr.h"
+#include "google_breakpad/processor/stack_frame.h"
+#include "processor/cfi_frame_info.h"
+#include "processor/windows_frame_info.h"
+
+namespace google_breakpad {
+
+struct
+BasicSourceLineResolver::Function : public SourceLineResolverBase::Function {
+ Function(const string &function_name,
+ MemAddr function_address,
+ MemAddr code_size,
+ int set_parameter_size,
+ bool is_mutiple) : Base(function_name,
+ function_address,
+ code_size,
+ set_parameter_size,
+ is_mutiple),
+ lines() { }
+ RangeMap< MemAddr, linked_ptr<Line> > lines;
+ private:
+ typedef SourceLineResolverBase::Function Base;
+};
+
+
+class BasicSourceLineResolver::Module : public SourceLineResolverBase::Module {
+ public:
+ explicit Module(const string &name) : name_(name), is_corrupt_(false) { }
+ virtual ~Module() { }
+
+ // Loads a map from the given buffer in char* type.
+ // Does NOT have ownership of memory_buffer.
+ // The passed in |memory buffer| is of size |memory_buffer_size|. If it is
+ // not null terminated, LoadMapFromMemory() will null terminate it by
+ // modifying the passed in buffer.
+ virtual bool LoadMapFromMemory(char *memory_buffer,
+ size_t memory_buffer_size);
+
+ // Tells whether the loaded symbol data is corrupt. Return value is
+ // undefined, if the symbol data hasn't been loaded yet.
+ virtual bool IsCorrupt() const { return is_corrupt_; }
+
+ // Looks up the given relative address, and fills the StackFrame struct
+ // with the result.
+ virtual void LookupAddress(StackFrame *frame) const;
+
+ // If Windows stack walking information is available covering ADDRESS,
+ // return a WindowsFrameInfo structure describing it. If the information
+ // is not available, returns NULL. A NULL return value does not indicate
+ // an error. The caller takes ownership of any returned WindowsFrameInfo
+ // object.
+ virtual WindowsFrameInfo *FindWindowsFrameInfo(const StackFrame *frame) const;
+
+ // If CFI stack walking information is available covering ADDRESS,
+ // return a CFIFrameInfo structure describing it. If the information
+ // is not available, return NULL. The caller takes ownership of any
+ // returned CFIFrameInfo object.
+ virtual CFIFrameInfo *FindCFIFrameInfo(const StackFrame *frame) const;
+
+ private:
+ // Friend declarations.
+ friend class BasicSourceLineResolver;
+ friend class ModuleComparer;
+ friend class ModuleSerializer;
+
+ typedef std::map<int, string> FileMap;
+
+ // Logs parse errors. |*num_errors| is increased every time LogParseError is
+ // called.
+ static void LogParseError(
+ const string &message,
+ int line_number,
+ int *num_errors);
+
+ // Parses a file declaration
+ bool ParseFile(char *file_line);
+
+ // Parses a function declaration, returning a new Function object.
+ Function* ParseFunction(char *function_line);
+
+ // Parses a line declaration, returning a new Line object.
+ Line* ParseLine(char *line_line);
+
+ // Parses a PUBLIC symbol declaration, storing it in public_symbols_.
+ // Returns false if an error occurs.
+ bool ParsePublicSymbol(char *public_line);
+
+ // Parses a STACK WIN or STACK CFI frame info declaration, storing
+ // it in the appropriate table.
+ bool ParseStackInfo(char *stack_info_line);
+
+ // Parses a STACK CFI record, storing it in cfi_frame_info_.
+ bool ParseCFIFrameInfo(char *stack_info_line);
+
+ string name_;
+ FileMap files_;
+ RangeMap< MemAddr, linked_ptr<Function> > functions_;
+ AddressMap< MemAddr, linked_ptr<PublicSymbol> > public_symbols_;
+ bool is_corrupt_;
+
+ // Each element in the array is a ContainedRangeMap for a type
+ // listed in WindowsFrameInfoTypes. These are split by type because
+ // there may be overlaps between maps of different types, but some
+ // information is only available as certain types.
+ ContainedRangeMap< MemAddr, linked_ptr<WindowsFrameInfo> >
+ windows_frame_info_[WindowsFrameInfo::STACK_INFO_LAST];
+
+ // DWARF CFI stack walking data. The Module stores the initial rule sets
+ // and rule deltas as strings, just as they appear in the symbol file:
+ // although the file may contain hundreds of thousands of STACK CFI
+ // records, walking a stack will only ever use a few of them, so it's
+ // best to delay parsing a record until it's actually needed.
+
+ // STACK CFI INIT records: for each range, an initial set of register
+ // recovery rules. The RangeMap's itself gives the starting and ending
+ // addresses.
+ RangeMap<MemAddr, string> cfi_initial_rules_;
+
+ // STACK CFI records: at a given address, the changes to the register
+ // recovery rules that take effect at that address. The map key is the
+ // starting address; the ending address is the key of the next entry in
+ // this map, or the end of the range as given by the cfi_initial_rules_
+ // entry (which FindCFIFrameInfo looks up first).
+ std::map<MemAddr, string> cfi_delta_rules_;
+};
+
+} // namespace google_breakpad
+
+#endif // PROCESSOR_BASIC_SOURCE_LINE_RESOLVER_TYPES_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/basic_source_line_resolver_unittest.cc b/toolkit/crashreporter/google-breakpad/src/processor/basic_source_line_resolver_unittest.cc
new file mode 100644
index 0000000000..90c3417236
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/basic_source_line_resolver_unittest.cc
@@ -0,0 +1,744 @@
+// 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 <stdio.h>
+
+#include <string>
+
+#include "breakpad_googletest_includes.h"
+#include "common/scoped_ptr.h"
+#include "common/using_std_string.h"
+#include "google_breakpad/processor/basic_source_line_resolver.h"
+#include "google_breakpad/processor/code_module.h"
+#include "google_breakpad/processor/stack_frame.h"
+#include "google_breakpad/processor/memory_region.h"
+#include "processor/linked_ptr.h"
+#include "processor/logging.h"
+#include "processor/windows_frame_info.h"
+#include "processor/cfi_frame_info.h"
+
+namespace {
+
+using google_breakpad::BasicSourceLineResolver;
+using google_breakpad::CFIFrameInfo;
+using google_breakpad::CodeModule;
+using google_breakpad::MemoryRegion;
+using google_breakpad::StackFrame;
+using google_breakpad::WindowsFrameInfo;
+using google_breakpad::linked_ptr;
+using google_breakpad::scoped_ptr;
+using google_breakpad::SymbolParseHelper;
+
+class TestCodeModule : public CodeModule {
+ public:
+ TestCodeModule(string code_file) : code_file_(code_file) {}
+ virtual ~TestCodeModule() {}
+
+ virtual uint64_t base_address() const { return 0; }
+ virtual uint64_t size() const { return 0xb000; }
+ virtual string code_file() const { return code_file_; }
+ virtual string code_identifier() const { return ""; }
+ virtual string debug_file() const { return ""; }
+ virtual string debug_identifier() const { return ""; }
+ virtual string version() const { return ""; }
+ virtual CodeModule* Copy() const {
+ return new TestCodeModule(code_file_);
+ }
+ virtual bool is_unloaded() const { return false; }
+ virtual uint64_t shrink_down_delta() const { return 0; }
+ virtual void SetShrinkDownDelta(uint64_t shrink_down_delta) {}
+
+ private:
+ string code_file_;
+};
+
+// A mock memory region object, for use by the STACK CFI tests.
+class MockMemoryRegion: public MemoryRegion {
+ uint64_t GetBase() const { return 0x10000; }
+ uint32_t GetSize() const { return 0x01000; }
+ bool GetMemoryAtAddress(uint64_t address, uint8_t *value) const {
+ *value = address & 0xff;
+ return true;
+ }
+ bool GetMemoryAtAddress(uint64_t address, uint16_t *value) const {
+ *value = address & 0xffff;
+ return true;
+ }
+ bool GetMemoryAtAddress(uint64_t address, uint32_t *value) const {
+ switch (address) {
+ case 0x10008: *value = 0x98ecadc3; break; // saved %ebx
+ case 0x1000c: *value = 0x878f7524; break; // saved %esi
+ case 0x10010: *value = 0x6312f9a5; break; // saved %edi
+ case 0x10014: *value = 0x10038; break; // caller's %ebp
+ case 0x10018: *value = 0xf6438648; break; // return address
+ default: *value = 0xdeadbeef; break; // junk
+ }
+ return true;
+ }
+ bool GetMemoryAtAddress(uint64_t address, uint64_t *value) const {
+ *value = address;
+ return true;
+ }
+ void Print() const {
+ assert(false);
+ }
+};
+
+// Verify that, for every association in ACTUAL, EXPECTED has the same
+// association. (That is, ACTUAL's associations should be a subset of
+// EXPECTED's.) Also verify that ACTUAL has associations for ".ra" and
+// ".cfa".
+static bool VerifyRegisters(
+ const char *file, int line,
+ const CFIFrameInfo::RegisterValueMap<uint32_t> &expected,
+ const CFIFrameInfo::RegisterValueMap<uint32_t> &actual) {
+ CFIFrameInfo::RegisterValueMap<uint32_t>::const_iterator a;
+ a = actual.find(".cfa");
+ if (a == actual.end())
+ return false;
+ a = actual.find(".ra");
+ if (a == actual.end())
+ return false;
+ for (a = actual.begin(); a != actual.end(); a++) {
+ CFIFrameInfo::RegisterValueMap<uint32_t>::const_iterator e =
+ expected.find(a->first);
+ if (e == expected.end()) {
+ fprintf(stderr, "%s:%d: unexpected register '%s' recovered, value 0x%x\n",
+ file, line, a->first.c_str(), a->second);
+ return false;
+ }
+ if (e->second != a->second) {
+ fprintf(stderr,
+ "%s:%d: register '%s' recovered value was 0x%x, expected 0x%x\n",
+ file, line, a->first.c_str(), a->second, e->second);
+ return false;
+ }
+ // Don't complain if this doesn't recover all registers. Although
+ // the DWARF spec says that unmentioned registers are undefined,
+ // GCC uses omission to mean that they are unchanged.
+ }
+ return true;
+}
+
+
+static bool VerifyEmpty(const StackFrame &frame) {
+ if (frame.function_name.empty() &&
+ frame.source_file_name.empty() &&
+ frame.source_line == 0)
+ return true;
+ return false;
+}
+
+static void ClearSourceLineInfo(StackFrame *frame) {
+ frame->function_name.clear();
+ frame->module = NULL;
+ frame->source_file_name.clear();
+ frame->source_line = 0;
+}
+
+class TestBasicSourceLineResolver : public ::testing::Test {
+public:
+ void SetUp() {
+ testdata_dir = string(getenv("srcdir") ? getenv("srcdir") : ".") +
+ "/src/processor/testdata";
+ }
+
+ BasicSourceLineResolver resolver;
+ string testdata_dir;
+};
+
+TEST_F(TestBasicSourceLineResolver, TestLoadAndResolve)
+{
+ TestCodeModule module1("module1");
+ ASSERT_TRUE(resolver.LoadModule(&module1, testdata_dir + "/module1.out"));
+ ASSERT_TRUE(resolver.HasModule(&module1));
+ TestCodeModule module2("module2");
+ ASSERT_TRUE(resolver.LoadModule(&module2, testdata_dir + "/module2.out"));
+ ASSERT_TRUE(resolver.HasModule(&module2));
+
+
+ StackFrame frame;
+ scoped_ptr<WindowsFrameInfo> windows_frame_info;
+ scoped_ptr<CFIFrameInfo> cfi_frame_info;
+ frame.instruction = 0x1000;
+ frame.module = NULL;
+ resolver.FillSourceLineInfo(&frame);
+ ASSERT_FALSE(frame.module);
+ ASSERT_TRUE(frame.function_name.empty());
+ ASSERT_EQ(frame.function_base, 0U);
+ ASSERT_TRUE(frame.source_file_name.empty());
+ ASSERT_EQ(frame.source_line, 0);
+ ASSERT_EQ(frame.source_line_base, 0U);
+
+ frame.module = &module1;
+ resolver.FillSourceLineInfo(&frame);
+ ASSERT_EQ(frame.function_name, "Function1_1");
+ ASSERT_TRUE(frame.module);
+ ASSERT_EQ(frame.module->code_file(), "module1");
+ ASSERT_EQ(frame.function_base, 0x1000U);
+ ASSERT_EQ(frame.source_file_name, "file1_1.cc");
+ ASSERT_EQ(frame.source_line, 44);
+ ASSERT_EQ(frame.source_line_base, 0x1000U);
+ windows_frame_info.reset(resolver.FindWindowsFrameInfo(&frame));
+ ASSERT_TRUE(windows_frame_info.get());
+ ASSERT_EQ(windows_frame_info->type_, WindowsFrameInfo::STACK_INFO_FRAME_DATA);
+ ASSERT_FALSE(windows_frame_info->allocates_base_pointer);
+ ASSERT_EQ(windows_frame_info->program_string,
+ "$eip 4 + ^ = $esp $ebp 8 + = $ebp $ebp ^ =");
+
+ ClearSourceLineInfo(&frame);
+ frame.instruction = 0x800;
+ frame.module = &module1;
+ resolver.FillSourceLineInfo(&frame);
+ ASSERT_TRUE(VerifyEmpty(frame));
+ windows_frame_info.reset(resolver.FindWindowsFrameInfo(&frame));
+ ASSERT_FALSE(windows_frame_info.get());
+
+ frame.instruction = 0x1280;
+ resolver.FillSourceLineInfo(&frame);
+ ASSERT_EQ(frame.function_name, "Function1_3");
+ ASSERT_TRUE(frame.source_file_name.empty());
+ ASSERT_EQ(frame.source_line, 0);
+ windows_frame_info.reset(resolver.FindWindowsFrameInfo(&frame));
+ ASSERT_TRUE(windows_frame_info.get());
+ ASSERT_EQ(windows_frame_info->type_, WindowsFrameInfo::STACK_INFO_UNKNOWN);
+ ASSERT_FALSE(windows_frame_info->allocates_base_pointer);
+ ASSERT_TRUE(windows_frame_info->program_string.empty());
+
+ frame.instruction = 0x1380;
+ resolver.FillSourceLineInfo(&frame);
+ ASSERT_EQ(frame.function_name, "Function1_4");
+ ASSERT_TRUE(frame.source_file_name.empty());
+ ASSERT_EQ(frame.source_line, 0);
+ windows_frame_info.reset(resolver.FindWindowsFrameInfo(&frame));
+ ASSERT_EQ(windows_frame_info->type_, WindowsFrameInfo::STACK_INFO_FRAME_DATA);
+ ASSERT_TRUE(windows_frame_info.get());
+ ASSERT_FALSE(windows_frame_info->allocates_base_pointer);
+ ASSERT_FALSE(windows_frame_info->program_string.empty());
+
+ frame.instruction = 0x2000;
+ windows_frame_info.reset(resolver.FindWindowsFrameInfo(&frame));
+ ASSERT_FALSE(windows_frame_info.get());
+
+ // module1 has STACK CFI records covering 3d40..3def;
+ // module2 has STACK CFI records covering 3df0..3e9f;
+ // check that FindCFIFrameInfo doesn't claim to find any outside those ranges.
+ frame.instruction = 0x3d3f;
+ frame.module = &module1;
+ cfi_frame_info.reset(resolver.FindCFIFrameInfo(&frame));
+ ASSERT_FALSE(cfi_frame_info.get());
+
+ frame.instruction = 0x3e9f;
+ frame.module = &module1;
+ cfi_frame_info.reset(resolver.FindCFIFrameInfo(&frame));
+ ASSERT_FALSE(cfi_frame_info.get());
+
+ CFIFrameInfo::RegisterValueMap<uint32_t> current_registers;
+ CFIFrameInfo::RegisterValueMap<uint32_t> caller_registers;
+ CFIFrameInfo::RegisterValueMap<uint32_t> expected_caller_registers;
+ MockMemoryRegion memory;
+
+ // Regardless of which instruction evaluation takes place at, it
+ // should produce the same values for the caller's registers.
+ expected_caller_registers[".cfa"] = 0x1001c;
+ expected_caller_registers[".ra"] = 0xf6438648;
+ expected_caller_registers["$ebp"] = 0x10038;
+ expected_caller_registers["$ebx"] = 0x98ecadc3;
+ expected_caller_registers["$esi"] = 0x878f7524;
+ expected_caller_registers["$edi"] = 0x6312f9a5;
+
+ frame.instruction = 0x3d40;
+ frame.module = &module1;
+ current_registers.clear();
+ current_registers["$esp"] = 0x10018;
+ current_registers["$ebp"] = 0x10038;
+ current_registers["$ebx"] = 0x98ecadc3;
+ current_registers["$esi"] = 0x878f7524;
+ current_registers["$edi"] = 0x6312f9a5;
+ cfi_frame_info.reset(resolver.FindCFIFrameInfo(&frame));
+ ASSERT_TRUE(cfi_frame_info.get());
+ ASSERT_TRUE(cfi_frame_info.get()
+ ->FindCallerRegs<uint32_t>(current_registers, memory,
+ &caller_registers));
+ ASSERT_TRUE(VerifyRegisters(__FILE__, __LINE__,
+ expected_caller_registers, caller_registers));
+
+ frame.instruction = 0x3d41;
+ current_registers["$esp"] = 0x10014;
+ cfi_frame_info.reset(resolver.FindCFIFrameInfo(&frame));
+ ASSERT_TRUE(cfi_frame_info.get());
+ ASSERT_TRUE(cfi_frame_info.get()
+ ->FindCallerRegs<uint32_t>(current_registers, memory,
+ &caller_registers));
+ ASSERT_TRUE(VerifyRegisters(__FILE__, __LINE__,
+ expected_caller_registers, caller_registers));
+
+ frame.instruction = 0x3d43;
+ current_registers["$ebp"] = 0x10014;
+ cfi_frame_info.reset(resolver.FindCFIFrameInfo(&frame));
+ ASSERT_TRUE(cfi_frame_info.get());
+ ASSERT_TRUE(cfi_frame_info.get()
+ ->FindCallerRegs<uint32_t>(current_registers, memory,
+ &caller_registers));
+ VerifyRegisters(__FILE__, __LINE__,
+ expected_caller_registers, caller_registers);
+
+ frame.instruction = 0x3d54;
+ current_registers["$ebx"] = 0x6864f054U;
+ cfi_frame_info.reset(resolver.FindCFIFrameInfo(&frame));
+ ASSERT_TRUE(cfi_frame_info.get());
+ ASSERT_TRUE(cfi_frame_info.get()
+ ->FindCallerRegs<uint32_t>(current_registers, memory,
+ &caller_registers));
+ VerifyRegisters(__FILE__, __LINE__,
+ expected_caller_registers, caller_registers);
+
+ frame.instruction = 0x3d5a;
+ current_registers["$esi"] = 0x6285f79aU;
+ cfi_frame_info.reset(resolver.FindCFIFrameInfo(&frame));
+ ASSERT_TRUE(cfi_frame_info.get());
+ ASSERT_TRUE(cfi_frame_info.get()
+ ->FindCallerRegs<uint32_t>(current_registers, memory,
+ &caller_registers));
+ VerifyRegisters(__FILE__, __LINE__,
+ expected_caller_registers, caller_registers);
+
+ frame.instruction = 0x3d84;
+ current_registers["$edi"] = 0x64061449U;
+ cfi_frame_info.reset(resolver.FindCFIFrameInfo(&frame));
+ ASSERT_TRUE(cfi_frame_info.get());
+ ASSERT_TRUE(cfi_frame_info.get()
+ ->FindCallerRegs<uint32_t>(current_registers, memory,
+ &caller_registers));
+ VerifyRegisters(__FILE__, __LINE__,
+ expected_caller_registers, caller_registers);
+
+ frame.instruction = 0x2900;
+ frame.module = &module1;
+ resolver.FillSourceLineInfo(&frame);
+ ASSERT_EQ(frame.function_name, string("PublicSymbol"));
+
+ frame.instruction = 0x4000;
+ frame.module = &module1;
+ resolver.FillSourceLineInfo(&frame);
+ ASSERT_EQ(frame.function_name, string("LargeFunction"));
+
+ frame.instruction = 0x2181;
+ frame.module = &module2;
+ resolver.FillSourceLineInfo(&frame);
+ ASSERT_EQ(frame.function_name, "Function2_2");
+ ASSERT_EQ(frame.function_base, 0x2170U);
+ ASSERT_TRUE(frame.module);
+ ASSERT_EQ(frame.module->code_file(), "module2");
+ ASSERT_EQ(frame.source_file_name, "file2_2.cc");
+ ASSERT_EQ(frame.source_line, 21);
+ ASSERT_EQ(frame.source_line_base, 0x2180U);
+ windows_frame_info.reset(resolver.FindWindowsFrameInfo(&frame));
+ ASSERT_TRUE(windows_frame_info.get());
+ ASSERT_EQ(windows_frame_info->type_, WindowsFrameInfo::STACK_INFO_FRAME_DATA);
+ ASSERT_EQ(windows_frame_info->prolog_size, 1U);
+
+ frame.instruction = 0x216f;
+ resolver.FillSourceLineInfo(&frame);
+ ASSERT_EQ(frame.function_name, "Public2_1");
+
+ ClearSourceLineInfo(&frame);
+ frame.instruction = 0x219f;
+ frame.module = &module2;
+ resolver.FillSourceLineInfo(&frame);
+ ASSERT_TRUE(frame.function_name.empty());
+
+ frame.instruction = 0x21a0;
+ frame.module = &module2;
+ resolver.FillSourceLineInfo(&frame);
+ ASSERT_EQ(frame.function_name, "Public2_2");
+}
+
+TEST_F(TestBasicSourceLineResolver, TestInvalidLoads)
+{
+ TestCodeModule module3("module3");
+ ASSERT_TRUE(resolver.LoadModule(&module3,
+ testdata_dir + "/module3_bad.out"));
+ ASSERT_TRUE(resolver.HasModule(&module3));
+ ASSERT_TRUE(resolver.IsModuleCorrupt(&module3));
+ TestCodeModule module4("module4");
+ ASSERT_TRUE(resolver.LoadModule(&module4,
+ testdata_dir + "/module4_bad.out"));
+ ASSERT_TRUE(resolver.HasModule(&module4));
+ ASSERT_TRUE(resolver.IsModuleCorrupt(&module4));
+ TestCodeModule module5("module5");
+ ASSERT_FALSE(resolver.LoadModule(&module5,
+ testdata_dir + "/invalid-filename"));
+ ASSERT_FALSE(resolver.HasModule(&module5));
+ TestCodeModule invalidmodule("invalid-module");
+ ASSERT_FALSE(resolver.HasModule(&invalidmodule));
+}
+
+TEST_F(TestBasicSourceLineResolver, TestUnload)
+{
+ TestCodeModule module1("module1");
+ ASSERT_FALSE(resolver.HasModule(&module1));
+ ASSERT_TRUE(resolver.LoadModule(&module1, testdata_dir + "/module1.out"));
+ ASSERT_TRUE(resolver.HasModule(&module1));
+ resolver.UnloadModule(&module1);
+ ASSERT_FALSE(resolver.HasModule(&module1));
+ ASSERT_TRUE(resolver.LoadModule(&module1, testdata_dir + "/module1.out"));
+ ASSERT_TRUE(resolver.HasModule(&module1));
+}
+
+// Test parsing of valid FILE lines. The format is:
+// FILE <id> <filename>
+TEST(SymbolParseHelper, ParseFileValid) {
+ long index;
+ char *filename;
+
+ char kTestLine[] = "FILE 1 file name";
+ ASSERT_TRUE(SymbolParseHelper::ParseFile(kTestLine, &index, &filename));
+ EXPECT_EQ(1, index);
+ EXPECT_EQ("file name", string(filename));
+
+ // 0 is a valid index.
+ char kTestLine1[] = "FILE 0 file name";
+ ASSERT_TRUE(SymbolParseHelper::ParseFile(kTestLine1, &index, &filename));
+ EXPECT_EQ(0, index);
+ EXPECT_EQ("file name", string(filename));
+}
+
+// Test parsing of invalid FILE lines. The format is:
+// FILE <id> <filename>
+TEST(SymbolParseHelper, ParseFileInvalid) {
+ long index;
+ char *filename;
+
+ // Test missing file name.
+ char kTestLine[] = "FILE 1 ";
+ ASSERT_FALSE(SymbolParseHelper::ParseFile(kTestLine, &index, &filename));
+
+ // Test bad index.
+ char kTestLine1[] = "FILE x1 file name";
+ ASSERT_FALSE(SymbolParseHelper::ParseFile(kTestLine1, &index, &filename));
+
+ // Test large index.
+ char kTestLine2[] = "FILE 123123123123123123123123 file name";
+ ASSERT_FALSE(SymbolParseHelper::ParseFile(kTestLine2, &index, &filename));
+
+ // Test negative index.
+ char kTestLine3[] = "FILE -2 file name";
+ ASSERT_FALSE(SymbolParseHelper::ParseFile(kTestLine3, &index, &filename));
+}
+
+// Test parsing of valid FUNC lines. The format is:
+// FUNC [<multiple>] <address> <size> <stack_param_size> <name>
+TEST(SymbolParseHelper, ParseFunctionValid) {
+ bool multiple;
+ uint64_t address;
+ uint64_t size;
+ long stack_param_size;
+ char *name;
+
+ char kTestLine[] = "FUNC 1 2 3 function name";
+ ASSERT_TRUE(SymbolParseHelper::ParseFunction(kTestLine, &multiple, &address,
+ &size, &stack_param_size,
+ &name));
+ EXPECT_FALSE(multiple);
+ EXPECT_EQ(1ULL, address);
+ EXPECT_EQ(2ULL, size);
+ EXPECT_EQ(3, stack_param_size);
+ EXPECT_EQ("function name", string(name));
+
+ // Test hex address, size, and param size.
+ char kTestLine1[] = "FUNC a1 a2 a3 function name";
+ ASSERT_TRUE(SymbolParseHelper::ParseFunction(kTestLine1, &multiple, &address,
+ &size, &stack_param_size,
+ &name));
+ EXPECT_FALSE(multiple);
+ EXPECT_EQ(0xa1ULL, address);
+ EXPECT_EQ(0xa2ULL, size);
+ EXPECT_EQ(0xa3, stack_param_size);
+ EXPECT_EQ("function name", string(name));
+
+ char kTestLine2[] = "FUNC 0 0 0 function name";
+ ASSERT_TRUE(SymbolParseHelper::ParseFunction(kTestLine2, &multiple, &address,
+ &size, &stack_param_size,
+ &name));
+ EXPECT_FALSE(multiple);
+ EXPECT_EQ(0ULL, address);
+ EXPECT_EQ(0ULL, size);
+ EXPECT_EQ(0, stack_param_size);
+ EXPECT_EQ("function name", string(name));
+
+ // Test optional multiple field.
+ char kTestLine3[] = "FUNC m a1 a2 a3 function name";
+ ASSERT_TRUE(SymbolParseHelper::ParseFunction(kTestLine3, &multiple, &address,
+ &size, &stack_param_size,
+ &name));
+ EXPECT_TRUE(multiple);
+ EXPECT_EQ(0xa1ULL, address);
+ EXPECT_EQ(0xa2ULL, size);
+ EXPECT_EQ(0xa3, stack_param_size);
+ EXPECT_EQ("function name", string(name));
+}
+
+// Test parsing of invalid FUNC lines. The format is:
+// FUNC [<multiple>] <address> <size> <stack_param_size> <name>
+TEST(SymbolParseHelper, ParseFunctionInvalid) {
+ bool multiple;
+ uint64_t address;
+ uint64_t size;
+ long stack_param_size;
+ char *name;
+
+ // Test missing function name.
+ char kTestLine[] = "FUNC 1 2 3 ";
+ ASSERT_FALSE(SymbolParseHelper::ParseFunction(kTestLine, &multiple, &address,
+ &size, &stack_param_size,
+ &name));
+ // Test bad address.
+ char kTestLine1[] = "FUNC 1z 2 3 function name";
+ ASSERT_FALSE(SymbolParseHelper::ParseFunction(kTestLine1, &multiple, &address,
+ &size, &stack_param_size,
+ &name));
+ // Test large address.
+ char kTestLine2[] = "FUNC 123123123123123123123123123 2 3 function name";
+ ASSERT_FALSE(SymbolParseHelper::ParseFunction(kTestLine2, &multiple, &address,
+ &size, &stack_param_size,
+ &name));
+ // Test bad size.
+ char kTestLine3[] = "FUNC 1 z2 3 function name";
+ ASSERT_FALSE(SymbolParseHelper::ParseFunction(kTestLine3, &multiple, &address,
+ &size, &stack_param_size,
+ &name));
+ // Test large size.
+ char kTestLine4[] = "FUNC 1 231231231231231231231231232 3 function name";
+ ASSERT_FALSE(SymbolParseHelper::ParseFunction(kTestLine4, &multiple, &address,
+ &size, &stack_param_size,
+ &name));
+ // Test bad param size.
+ char kTestLine5[] = "FUNC 1 2 3z function name";
+ ASSERT_FALSE(SymbolParseHelper::ParseFunction(kTestLine5, &multiple, &address,
+ &size, &stack_param_size,
+ &name));
+ // Test large param size.
+ char kTestLine6[] = "FUNC 1 2 312312312312312312312312323 function name";
+ ASSERT_FALSE(SymbolParseHelper::ParseFunction(kTestLine6, &multiple, &address,
+ &size, &stack_param_size,
+ &name));
+ // Negative param size.
+ char kTestLine7[] = "FUNC 1 2 -5 function name";
+ ASSERT_FALSE(SymbolParseHelper::ParseFunction(kTestLine7, &multiple, &address,
+ &size, &stack_param_size,
+ &name));
+ // Test invalid optional field.
+ char kTestLine8[] = "FUNC x 1 2 5 function name";
+ ASSERT_FALSE(SymbolParseHelper::ParseFunction(kTestLine8, &multiple, &address,
+ &size, &stack_param_size,
+ &name));
+}
+
+// Test parsing of valid lines. The format is:
+// <address> <size> <line number> <source file id>
+TEST(SymbolParseHelper, ParseLineValid) {
+ uint64_t address;
+ uint64_t size;
+ long line_number;
+ long source_file;
+
+ char kTestLine[] = "1 2 3 4";
+ ASSERT_TRUE(SymbolParseHelper::ParseLine(kTestLine, &address, &size,
+ &line_number, &source_file));
+ EXPECT_EQ(1ULL, address);
+ EXPECT_EQ(2ULL, size);
+ EXPECT_EQ(3, line_number);
+ EXPECT_EQ(4, source_file);
+
+ // Test hex size and address.
+ char kTestLine1[] = "a1 a2 3 4 // some comment";
+ ASSERT_TRUE(SymbolParseHelper::ParseLine(kTestLine1, &address, &size,
+ &line_number, &source_file));
+ EXPECT_EQ(0xa1ULL, address);
+ EXPECT_EQ(0xa2ULL, size);
+ EXPECT_EQ(3, line_number);
+ EXPECT_EQ(4, source_file);
+
+ // 0 is a valid line number.
+ char kTestLine2[] = "a1 a2 0 4 // some comment";
+ ASSERT_TRUE(SymbolParseHelper::ParseLine(kTestLine2, &address, &size,
+ &line_number, &source_file));
+ EXPECT_EQ(0xa1ULL, address);
+ EXPECT_EQ(0xa2ULL, size);
+ EXPECT_EQ(0, line_number);
+ EXPECT_EQ(4, source_file);
+}
+
+// Test parsing of invalid lines. The format is:
+// <address> <size> <line number> <source file id>
+TEST(SymbolParseHelper, ParseLineInvalid) {
+ uint64_t address;
+ uint64_t size;
+ long line_number;
+ long source_file;
+
+ // Test missing source file id.
+ char kTestLine[] = "1 2 3";
+ ASSERT_FALSE(SymbolParseHelper::ParseLine(kTestLine, &address, &size,
+ &line_number, &source_file));
+ // Test bad address.
+ char kTestLine1[] = "1z 2 3 4";
+ ASSERT_FALSE(SymbolParseHelper::ParseLine(kTestLine1, &address, &size,
+ &line_number, &source_file));
+ // Test large address.
+ char kTestLine2[] = "123123123123123123123123 2 3 4";
+ ASSERT_FALSE(SymbolParseHelper::ParseLine(kTestLine2, &address, &size,
+ &line_number, &source_file));
+ // Test bad size.
+ char kTestLine3[] = "1 z2 3 4";
+ ASSERT_FALSE(SymbolParseHelper::ParseLine(kTestLine3, &address, &size,
+ &line_number, &source_file));
+ // Test large size.
+ char kTestLine4[] = "1 123123123123123123123123 3 4";
+ ASSERT_FALSE(SymbolParseHelper::ParseLine(kTestLine4, &address, &size,
+ &line_number, &source_file));
+ // Test bad line number.
+ char kTestLine5[] = "1 2 z3 4";
+ ASSERT_FALSE(SymbolParseHelper::ParseLine(kTestLine5, &address, &size,
+ &line_number, &source_file));
+ // Test negative line number.
+ char kTestLine6[] = "1 2 -1 4";
+ ASSERT_FALSE(SymbolParseHelper::ParseLine(kTestLine6, &address, &size,
+ &line_number, &source_file));
+ // Test large line number.
+ char kTestLine7[] = "1 2 123123123123123123123 4";
+ ASSERT_FALSE(SymbolParseHelper::ParseLine(kTestLine7, &address, &size,
+ &line_number, &source_file));
+ // Test bad source file id.
+ char kTestLine8[] = "1 2 3 f";
+ ASSERT_FALSE(SymbolParseHelper::ParseLine(kTestLine8, &address, &size,
+ &line_number, &source_file));
+}
+
+// Test parsing of valid PUBLIC lines. The format is:
+// PUBLIC [<multiple>] <address> <stack_param_size> <name>
+TEST(SymbolParseHelper, ParsePublicSymbolValid) {
+ bool multiple;
+ uint64_t address;
+ long stack_param_size;
+ char *name;
+
+ char kTestLine[] = "PUBLIC 1 2 3";
+ ASSERT_TRUE(SymbolParseHelper::ParsePublicSymbol(kTestLine, &multiple,
+ &address, &stack_param_size,
+ &name));
+ EXPECT_FALSE(multiple);
+ EXPECT_EQ(1ULL, address);
+ EXPECT_EQ(2, stack_param_size);
+ EXPECT_EQ("3", string(name));
+
+ // Test hex size and address.
+ char kTestLine1[] = "PUBLIC a1 a2 function name";
+ ASSERT_TRUE(SymbolParseHelper::ParsePublicSymbol(kTestLine1, &multiple,
+ &address, &stack_param_size,
+ &name));
+ EXPECT_FALSE(multiple);
+ EXPECT_EQ(0xa1ULL, address);
+ EXPECT_EQ(0xa2, stack_param_size);
+ EXPECT_EQ("function name", string(name));
+
+ // Test 0 is a valid address.
+ char kTestLine2[] = "PUBLIC 0 a2 function name";
+ ASSERT_TRUE(SymbolParseHelper::ParsePublicSymbol(kTestLine2, &multiple,
+ &address, &stack_param_size,
+ &name));
+ EXPECT_FALSE(multiple);
+ EXPECT_EQ(0ULL, address);
+ EXPECT_EQ(0xa2, stack_param_size);
+ EXPECT_EQ("function name", string(name));
+
+ // Test optional multiple field.
+ char kTestLine3[] = "PUBLIC m a1 a2 function name";
+ ASSERT_TRUE(SymbolParseHelper::ParsePublicSymbol(kTestLine3, &multiple,
+ &address, &stack_param_size,
+ &name));
+ EXPECT_TRUE(multiple);
+ EXPECT_EQ(0xa1ULL, address);
+ EXPECT_EQ(0xa2, stack_param_size);
+ EXPECT_EQ("function name", string(name));
+}
+
+// Test parsing of invalid PUBLIC lines. The format is:
+// PUBLIC [<multiple>] <address> <stack_param_size> <name>
+TEST(SymbolParseHelper, ParsePublicSymbolInvalid) {
+ bool multiple;
+ uint64_t address;
+ long stack_param_size;
+ char *name;
+
+ // Test missing source function name.
+ char kTestLine[] = "PUBLIC 1 2 ";
+ ASSERT_FALSE(SymbolParseHelper::ParsePublicSymbol(kTestLine, &multiple,
+ &address, &stack_param_size,
+ &name));
+ // Test bad address.
+ char kTestLine1[] = "PUBLIC 1z 2 3";
+ ASSERT_FALSE(SymbolParseHelper::ParsePublicSymbol(kTestLine1, &multiple,
+ &address, &stack_param_size,
+ &name));
+ // Test large address.
+ char kTestLine2[] = "PUBLIC 123123123123123123123123 2 3";
+ ASSERT_FALSE(SymbolParseHelper::ParsePublicSymbol(kTestLine2, &multiple,
+ &address, &stack_param_size,
+ &name));
+ // Test bad param stack size.
+ char kTestLine3[] = "PUBLIC 1 z2 3";
+ ASSERT_FALSE(SymbolParseHelper::ParsePublicSymbol(kTestLine3, &multiple,
+ &address, &stack_param_size,
+ &name));
+ // Test large param stack size.
+ char kTestLine4[] = "PUBLIC 1 123123123123123123123123123 3";
+ ASSERT_FALSE(SymbolParseHelper::ParsePublicSymbol(kTestLine4, &multiple,
+ &address, &stack_param_size,
+ &name));
+ // Test negative param stack size.
+ char kTestLine5[] = "PUBLIC 1 -5 3";
+ ASSERT_FALSE(SymbolParseHelper::ParsePublicSymbol(kTestLine5, &multiple,
+ &address, &stack_param_size,
+ &name));
+ // Test invalid optional field.
+ char kTestLine6[] = "PUBLIC x 1 5 3";
+ ASSERT_FALSE(SymbolParseHelper::ParsePublicSymbol(kTestLine6, &multiple,
+ &address, &stack_param_size,
+ &name));
+}
+
+} // namespace
+
+int main(int argc, char *argv[]) {
+ ::testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/call_stack.cc b/toolkit/crashreporter/google-breakpad/src/processor/call_stack.cc
new file mode 100644
index 0000000000..16cde0aae8
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/call_stack.cc
@@ -0,0 +1,56 @@
+// 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.
+
+// call_stack.cc: A call stack comprised of stack frames.
+//
+// See call_stack.h for documentation.
+//
+// Author: Mark Mentovai
+
+#include "google_breakpad/processor/call_stack.h"
+#include "google_breakpad/processor/stack_frame.h"
+
+namespace google_breakpad {
+
+CallStack::~CallStack() {
+ Clear();
+}
+
+void CallStack::Clear() {
+ for (vector<StackFrame *>::const_iterator iterator = frames_.begin();
+ iterator != frames_.end();
+ ++iterator) {
+ delete *iterator;
+ }
+ tid_ = 0;
+ last_error_ = 0;
+ name_ = "";
+}
+
+} // namespace google_breakpad
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/cfi_frame_info-inl.h b/toolkit/crashreporter/google-breakpad/src/processor/cfi_frame_info-inl.h
new file mode 100644
index 0000000000..7e7af0af93
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/cfi_frame_info-inl.h
@@ -0,0 +1,119 @@
+// -*- 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_frame_info-inl.h: Definitions for cfi_frame_info.h inlined functions.
+
+#ifndef PROCESSOR_CFI_FRAME_INFO_INL_H_
+#define PROCESSOR_CFI_FRAME_INFO_INL_H_
+
+#include <string.h>
+
+namespace google_breakpad {
+
+template <typename RegisterType, class RawContextType>
+bool SimpleCFIWalker<RegisterType, RawContextType>::FindCallerRegisters(
+ const MemoryRegion &memory,
+ const CFIFrameInfo &cfi_frame_info,
+ const RawContextType &callee_context,
+ int callee_validity,
+ RawContextType *caller_context,
+ int *caller_validity) const {
+ typedef CFIFrameInfo::RegisterValueMap<RegisterType> ValueMap;
+ ValueMap callee_registers;
+ ValueMap caller_registers;
+ // Just for brevity.
+ typename ValueMap::const_iterator caller_none = caller_registers.end();
+
+ // Populate callee_registers with register values from callee_context.
+ for (size_t i = 0; i < map_size_; i++) {
+ const RegisterSet &r = register_map_[i];
+ if (callee_validity & r.validity_flag)
+ callee_registers[r.name] = callee_context.*r.context_member;
+ }
+
+ // Apply the rules, and see what register values they yield.
+ if (!cfi_frame_info.FindCallerRegs<RegisterType>(callee_registers, memory,
+ &caller_registers))
+ return false;
+
+ // Populate *caller_context with the values the rules placed in
+ // caller_registers.
+ memset(caller_context, 0xda, sizeof(*caller_context));
+ *caller_validity = 0;
+ for (size_t i = 0; i < map_size_; i++) {
+ const RegisterSet &r = register_map_[i];
+ typename ValueMap::const_iterator caller_entry;
+
+ // Did the rules provide a value for this register by its name?
+ caller_entry = caller_registers.find(r.name);
+ if (caller_entry != caller_none) {
+ caller_context->*r.context_member = caller_entry->second;
+ *caller_validity |= r.validity_flag;
+ continue;
+ }
+
+ // Did the rules provide a value for this register under its
+ // alternate name?
+ if (r.alternate_name) {
+ caller_entry = caller_registers.find(r.alternate_name);
+ if (caller_entry != caller_none) {
+ caller_context->*r.context_member = caller_entry->second;
+ *caller_validity |= r.validity_flag;
+ continue;
+ }
+ }
+
+ // Is this a callee-saves register? The walker assumes that these
+ // still hold the caller's value if the CFI doesn't mention them.
+ //
+ // Note that other frame walkers may fail to recover callee-saves
+ // registers; for example, the x86 "traditional" strategy only
+ // recovers %eip, %esp, and %ebp, even though %ebx, %esi, and %edi
+ // are callee-saves, too. It is not correct to blindly set the
+ // valid bit for all callee-saves registers, without first
+ // checking its validity bit in the callee.
+ if (r.callee_saves && (callee_validity & r.validity_flag) != 0) {
+ caller_context->*r.context_member = callee_context.*r.context_member;
+ *caller_validity |= r.validity_flag;
+ continue;
+ }
+
+ // Otherwise, the register's value is unknown.
+ }
+
+ return true;
+}
+
+} // namespace google_breakpad
+
+#endif // PROCESSOR_CFI_FRAME_INFO_INL_H_
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/cfi_frame_info.cc b/toolkit/crashreporter/google-breakpad/src/processor/cfi_frame_info.cc
new file mode 100644
index 0000000000..0c4af7ba84
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/cfi_frame_info.cc
@@ -0,0 +1,186 @@
+// 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_frame_info.cc: Implementation of CFIFrameInfo class.
+// See cfi_frame_info.h for details.
+
+#include "processor/cfi_frame_info.h"
+
+#include <string.h>
+
+#include <sstream>
+
+#include "common/scoped_ptr.h"
+#include "processor/postfix_evaluator-inl.h"
+
+namespace google_breakpad {
+
+#ifdef _MSC_VER
+#define strtok_r strtok_s
+#endif
+
+template<typename V>
+bool CFIFrameInfo::FindCallerRegs(const RegisterValueMap<V> &registers,
+ const MemoryRegion &memory,
+ RegisterValueMap<V> *caller_registers) const {
+ // If there are not rules for both .ra and .cfa in effect at this address,
+ // don't use this CFI data for stack walking.
+ if (cfa_rule_.empty() || ra_rule_.empty())
+ return false;
+
+ RegisterValueMap<V> working;
+ PostfixEvaluator<V> evaluator(&working, &memory);
+
+ caller_registers->clear();
+
+ // First, compute the CFA.
+ V cfa;
+ working = registers;
+ if (!evaluator.EvaluateForValue(cfa_rule_, &cfa))
+ return false;
+
+ // Then, compute the return address.
+ V ra;
+ working = registers;
+ working[".cfa"] = cfa;
+ if (!evaluator.EvaluateForValue(ra_rule_, &ra))
+ return false;
+
+ // Now, compute values for all the registers register_rules_ mentions.
+ for (RuleMap::const_iterator it = register_rules_.begin();
+ it != register_rules_.end(); it++) {
+ V value;
+ working = registers;
+ working[".cfa"] = cfa;
+ if (!evaluator.EvaluateForValue(it->second, &value))
+ return false;
+ (*caller_registers)[it->first] = value;
+ }
+
+ (*caller_registers)[".ra"] = ra;
+ (*caller_registers)[".cfa"] = cfa;
+
+ return true;
+}
+
+// Explicit instantiations for 32-bit and 64-bit architectures.
+template bool CFIFrameInfo::FindCallerRegs<uint32_t>(
+ const RegisterValueMap<uint32_t> &registers,
+ const MemoryRegion &memory,
+ RegisterValueMap<uint32_t> *caller_registers) const;
+template bool CFIFrameInfo::FindCallerRegs<uint64_t>(
+ const RegisterValueMap<uint64_t> &registers,
+ const MemoryRegion &memory,
+ RegisterValueMap<uint64_t> *caller_registers) const;
+
+string CFIFrameInfo::Serialize() const {
+ std::ostringstream stream;
+
+ if (!cfa_rule_.empty()) {
+ stream << ".cfa: " << cfa_rule_;
+ }
+ if (!ra_rule_.empty()) {
+ if (static_cast<std::streamoff>(stream.tellp()) != 0)
+ stream << " ";
+ stream << ".ra: " << ra_rule_;
+ }
+ for (RuleMap::const_iterator iter = register_rules_.begin();
+ iter != register_rules_.end();
+ ++iter) {
+ if (static_cast<std::streamoff>(stream.tellp()) != 0)
+ stream << " ";
+ stream << iter->first << ": " << iter->second;
+ }
+
+ return stream.str();
+}
+
+bool CFIRuleParser::Parse(const string &rule_set) {
+ size_t rule_set_len = rule_set.size();
+ scoped_array<char> working_copy(new char[rule_set_len + 1]);
+ memcpy(working_copy.get(), rule_set.data(), rule_set_len);
+ working_copy[rule_set_len] = '\0';
+
+ name_.clear();
+ expression_.clear();
+
+ char *cursor;
+ static const char token_breaks[] = " \t\r\n";
+ char *token = strtok_r(working_copy.get(), token_breaks, &cursor);
+
+ for (;;) {
+ // End of rule set?
+ if (!token) return Report();
+
+ // Register/pseudoregister name?
+ size_t token_len = strlen(token);
+ if (token_len >= 1 && token[token_len - 1] == ':') {
+ // Names can't be empty.
+ if (token_len < 2) return false;
+ // If there is any pending content, report it.
+ if (!name_.empty() || !expression_.empty()) {
+ if (!Report()) return false;
+ }
+ name_.assign(token, token_len - 1);
+ expression_.clear();
+ } else {
+ // Another expression component.
+ assert(token_len > 0); // strtok_r guarantees this, I think.
+ if (!expression_.empty())
+ expression_ += ' ';
+ expression_ += token;
+ }
+ token = strtok_r(NULL, token_breaks, &cursor);
+ }
+}
+
+bool CFIRuleParser::Report() {
+ if (name_.empty() || expression_.empty()) return false;
+ if (name_ == ".cfa") handler_->CFARule(expression_);
+ else if (name_ == ".ra") handler_->RARule(expression_);
+ else handler_->RegisterRule(name_, expression_);
+ return true;
+}
+
+void CFIFrameInfoParseHandler::CFARule(const string &expression) {
+ frame_info_->SetCFARule(expression);
+}
+
+void CFIFrameInfoParseHandler::RARule(const string &expression) {
+ frame_info_->SetRARule(expression);
+}
+
+void CFIFrameInfoParseHandler::RegisterRule(const string &name,
+ const string &expression) {
+ frame_info_->SetRegisterRule(name, expression);
+}
+
+} // namespace google_breakpad
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/cfi_frame_info.h b/toolkit/crashreporter/google-breakpad/src/processor/cfi_frame_info.h
new file mode 100644
index 0000000000..90a1b3d74a
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/cfi_frame_info.h
@@ -0,0 +1,275 @@
+// -*- 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_frame_info.h: Define the CFIFrameInfo class, which holds the
+// set of 'STACK CFI'-derived register recovery rules that apply at a
+// given instruction.
+
+#ifndef PROCESSOR_CFI_FRAME_INFO_H_
+#define PROCESSOR_CFI_FRAME_INFO_H_
+
+#include <map>
+#include <string>
+
+#include "common/using_std_string.h"
+#include "google_breakpad/common/breakpad_types.h"
+
+namespace google_breakpad {
+
+using std::map;
+
+class MemoryRegion;
+
+// A set of rules for recovering the calling frame's registers'
+// values, when the PC is at a given address in the current frame's
+// function. See the description of 'STACK CFI' records at:
+//
+// https://chromium.googlesource.com/breakpad/breakpad/+/master/docs/symbol_files.md
+//
+// To prepare an instance of CFIFrameInfo for use at a given
+// instruction, first populate it with the rules from the 'STACK CFI
+// INIT' record that covers that instruction, and then apply the
+// changes given by the 'STACK CFI' records up to our instruction's
+// address. Then, use the FindCallerRegs member function to apply the
+// rules to the callee frame's register values, yielding the caller
+// frame's register values.
+class CFIFrameInfo {
+ public:
+ // A map from register names onto values.
+ template<typename ValueType> class RegisterValueMap:
+ public map<string, ValueType> { };
+
+ // Set the expression for computing a call frame address, return
+ // address, or register's value. At least the CFA rule and the RA
+ // rule must be set before calling FindCallerRegs.
+ void SetCFARule(const string &expression) { cfa_rule_ = expression; }
+ void SetRARule(const string &expression) { ra_rule_ = expression; }
+ void SetRegisterRule(const string &register_name, const string &expression) {
+ register_rules_[register_name] = expression;
+ }
+
+ // Compute the values of the calling frame's registers, according to
+ // this rule set. Use ValueType in expression evaluation; this
+ // should be uint32_t on machines with 32-bit addresses, or
+ // uint64_t on machines with 64-bit addresses.
+ //
+ // Return true on success, false otherwise.
+ //
+ // MEMORY provides access to the contents of the stack. REGISTERS is
+ // a dictionary mapping the names of registers whose values are
+ // known in the current frame to their values. CALLER_REGISTERS is
+ // populated with the values of the recoverable registers in the
+ // frame that called the current frame.
+ //
+ // In addition, CALLER_REGISTERS[".ra"] will be the return address,
+ // and CALLER_REGISTERS[".cfa"] will be the call frame address.
+ // These may be helpful in computing the caller's PC and stack
+ // pointer, if their values are not explicitly specified.
+ template<typename ValueType>
+ bool FindCallerRegs(const RegisterValueMap<ValueType> &registers,
+ const MemoryRegion &memory,
+ RegisterValueMap<ValueType> *caller_registers) const;
+
+ // Serialize the rules in this object into a string in the format
+ // of STACK CFI records.
+ string Serialize() const;
+
+ private:
+
+ // A map from register names onto evaluation rules.
+ typedef map<string, string> RuleMap;
+
+ // In this type, a "postfix expression" is an expression of the sort
+ // interpreted by google_breakpad::PostfixEvaluator.
+
+ // A postfix expression for computing the current frame's CFA (call
+ // frame address). The CFA is a reference address for the frame that
+ // remains unchanged throughout the frame's lifetime. You should
+ // evaluate this expression with a dictionary initially populated
+ // with the values of the current frame's known registers.
+ string cfa_rule_;
+
+ // The following expressions should be evaluated with a dictionary
+ // initially populated with the values of the current frame's known
+ // registers, and with ".cfa" set to the result of evaluating the
+ // cfa_rule expression, above.
+
+ // A postfix expression for computing the current frame's return
+ // address.
+ string ra_rule_;
+
+ // For a register named REG, rules[REG] is a postfix expression
+ // which leaves the value of REG in the calling frame on the top of
+ // the stack. You should evaluate this expression
+ RuleMap register_rules_;
+};
+
+// A parser for STACK CFI-style rule sets.
+// This may seem bureaucratic: there's no legitimate run-time reason
+// to use a parser/handler pattern for this, as it's not a likely
+// reuse boundary. But doing so makes finer-grained unit testing
+// possible.
+class CFIRuleParser {
+ public:
+
+ class Handler {
+ public:
+ Handler() { }
+ virtual ~Handler() { }
+
+ // The input specifies EXPRESSION as the CFA/RA computation rule.
+ virtual void CFARule(const string &expression) = 0;
+ virtual void RARule(const string &expression) = 0;
+
+ // The input specifies EXPRESSION as the recovery rule for register NAME.
+ virtual void RegisterRule(const string &name, const string &expression) = 0;
+ };
+
+ // Construct a parser which feeds its results to HANDLER.
+ CFIRuleParser(Handler *handler) : handler_(handler) { }
+
+ // Parse RULE_SET as a set of CFA computation and RA/register
+ // recovery rules, as appearing in STACK CFI records. Report the
+ // results of parsing by making the appropriate calls to handler_.
+ // Return true if parsing was successful, false otherwise.
+ bool Parse(const string &rule_set);
+
+ private:
+ // Report any accumulated rule to handler_
+ bool Report();
+
+ // The handler to which the parser reports its findings.
+ Handler *handler_;
+
+ // Working data.
+ string name_, expression_;
+};
+
+// A handler for rule set parsing that populates a CFIFrameInfo with
+// the results.
+class CFIFrameInfoParseHandler: public CFIRuleParser::Handler {
+ public:
+ // Populate FRAME_INFO with the results of parsing.
+ CFIFrameInfoParseHandler(CFIFrameInfo *frame_info)
+ : frame_info_(frame_info) { }
+
+ void CFARule(const string &expression);
+ void RARule(const string &expression);
+ void RegisterRule(const string &name, const string &expression);
+
+ private:
+ CFIFrameInfo *frame_info_;
+};
+
+// A utility class template for simple 'STACK CFI'-driven stack walkers.
+// Given a CFIFrameInfo instance, a table describing the architecture's
+// register set, and a context holding the last frame's registers, an
+// instance of this class can populate a new context with the caller's
+// registers.
+//
+// This class template doesn't use any internal knowledge of CFIFrameInfo
+// or the other stack walking structures; it just uses the public interface
+// of CFIFrameInfo to do the usual things. But the logic it handles should
+// be common to many different architectures' stack walkers, so wrapping it
+// up in a class should allow the walkers to share code.
+//
+// RegisterType should be the type of this architecture's registers, either
+// uint32_t or uint64_t. RawContextType should be the raw context
+// structure type for this architecture.
+template <typename RegisterType, class RawContextType>
+class SimpleCFIWalker {
+ public:
+ // A structure describing one architecture register.
+ struct RegisterSet {
+ // The register name, as it appears in STACK CFI rules.
+ const char *name;
+
+ // An alternate name that the register's value might be found
+ // under in a register value dictionary, or NULL. When generating
+ // names, prefer NAME to this value. It's common to list ".cfa" as
+ // an alternative name for the stack pointer, and ".ra" as an
+ // alternative name for the instruction pointer.
+ const char *alternate_name;
+
+ // True if the callee is expected to preserve the value of this
+ // register. If this flag is true for some register R, and the STACK
+ // CFI records provide no rule to recover R, then SimpleCFIWalker
+ // assumes that the callee has not changed R's value, and the caller's
+ // value for R is that currently in the callee's context.
+ bool callee_saves;
+
+ // The ContextValidity flag representing the register's presence.
+ int validity_flag;
+
+ // A pointer to the RawContextType member that holds the
+ // register's value.
+ RegisterType RawContextType::*context_member;
+ };
+
+ // Create a simple CFI-based frame walker, given a description of the
+ // architecture's register set. REGISTER_MAP is an array of
+ // RegisterSet structures; MAP_SIZE is the number of elements in the
+ // array.
+ SimpleCFIWalker(const RegisterSet *register_map, size_t map_size)
+ : register_map_(register_map), map_size_(map_size) { }
+
+ // Compute the calling frame's raw context given the callee's raw
+ // context.
+ //
+ // Given:
+ //
+ // - MEMORY, holding the stack's contents,
+ // - CFI_FRAME_INFO, describing the called function,
+ // - CALLEE_CONTEXT, holding the called frame's registers, and
+ // - CALLEE_VALIDITY, indicating which registers in CALLEE_CONTEXT are valid,
+ //
+ // fill in CALLER_CONTEXT with the caller's register values, and set
+ // CALLER_VALIDITY to indicate which registers are valid in
+ // CALLER_CONTEXT. Return true on success, or false on failure.
+ bool FindCallerRegisters(const MemoryRegion &memory,
+ const CFIFrameInfo &cfi_frame_info,
+ const RawContextType &callee_context,
+ int callee_validity,
+ RawContextType *caller_context,
+ int *caller_validity) const;
+
+ private:
+ const RegisterSet *register_map_;
+ size_t map_size_;
+};
+
+} // namespace google_breakpad
+
+#include "cfi_frame_info-inl.h"
+
+#endif // PROCESSOR_CFI_FRAME_INFO_H_
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/cfi_frame_info_unittest.cc b/toolkit/crashreporter/google-breakpad/src/processor/cfi_frame_info_unittest.cc
new file mode 100644
index 0000000000..542b28492e
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/cfi_frame_info_unittest.cc
@@ -0,0 +1,546 @@
+// 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_frame_info_unittest.cc: Unit tests for CFIFrameInfo,
+// CFIRuleParser, CFIFrameInfoParseHandler, and SimpleCFIWalker.
+
+#include <string.h>
+
+#include "breakpad_googletest_includes.h"
+#include "common/using_std_string.h"
+#include "processor/cfi_frame_info.h"
+#include "google_breakpad/processor/memory_region.h"
+
+using google_breakpad::CFIFrameInfo;
+using google_breakpad::CFIFrameInfoParseHandler;
+using google_breakpad::CFIRuleParser;
+using google_breakpad::MemoryRegion;
+using google_breakpad::SimpleCFIWalker;
+using testing::_;
+using testing::A;
+using testing::AtMost;
+using testing::DoAll;
+using testing::Return;
+using testing::SetArgumentPointee;
+using testing::Test;
+
+class MockMemoryRegion: public MemoryRegion {
+ public:
+ MOCK_CONST_METHOD0(GetBase, uint64_t());
+ MOCK_CONST_METHOD0(GetSize, uint32_t());
+ MOCK_CONST_METHOD2(GetMemoryAtAddress, bool(uint64_t, uint8_t *));
+ MOCK_CONST_METHOD2(GetMemoryAtAddress, bool(uint64_t, uint16_t *));
+ MOCK_CONST_METHOD2(GetMemoryAtAddress, bool(uint64_t, uint32_t *));
+ MOCK_CONST_METHOD2(GetMemoryAtAddress, bool(uint64_t, uint64_t *));
+ MOCK_CONST_METHOD0(Print, void());
+};
+
+// Handy definitions for all tests.
+struct CFIFixture {
+
+ // Set up the mock memory object to expect no references.
+ void ExpectNoMemoryReferences() {
+ EXPECT_CALL(memory, GetBase()).Times(0);
+ EXPECT_CALL(memory, GetSize()).Times(0);
+ EXPECT_CALL(memory, GetMemoryAtAddress(_, A<uint8_t *>())).Times(0);
+ EXPECT_CALL(memory, GetMemoryAtAddress(_, A<uint16_t *>())).Times(0);
+ EXPECT_CALL(memory, GetMemoryAtAddress(_, A<uint32_t *>())).Times(0);
+ EXPECT_CALL(memory, GetMemoryAtAddress(_, A<uint64_t *>())).Times(0);
+ }
+
+ CFIFrameInfo cfi;
+ MockMemoryRegion memory;
+ CFIFrameInfo::RegisterValueMap<uint64_t> registers, caller_registers;
+};
+
+class Simple: public CFIFixture, public Test { };
+
+// FindCallerRegs should fail if no .cfa rule is provided.
+TEST_F(Simple, NoCFA) {
+ ExpectNoMemoryReferences();
+
+ cfi.SetRARule("0");
+ ASSERT_FALSE(cfi.FindCallerRegs<uint64_t>(registers, memory,
+ &caller_registers));
+ ASSERT_EQ(".ra: 0", cfi.Serialize());
+}
+
+// FindCallerRegs should fail if no .ra rule is provided.
+TEST_F(Simple, NoRA) {
+ ExpectNoMemoryReferences();
+
+ cfi.SetCFARule("0");
+ ASSERT_FALSE(cfi.FindCallerRegs<uint64_t>(registers, memory,
+ &caller_registers));
+ ASSERT_EQ(".cfa: 0", cfi.Serialize());
+}
+
+TEST_F(Simple, SetCFAAndRARule) {
+ ExpectNoMemoryReferences();
+
+ cfi.SetCFARule("330903416631436410");
+ cfi.SetRARule("5870666104170902211");
+ ASSERT_TRUE(cfi.FindCallerRegs<uint64_t>(registers, memory,
+ &caller_registers));
+ ASSERT_EQ(2U, caller_registers.size());
+ ASSERT_EQ(330903416631436410ULL, caller_registers[".cfa"]);
+ ASSERT_EQ(5870666104170902211ULL, caller_registers[".ra"]);
+
+ ASSERT_EQ(".cfa: 330903416631436410 .ra: 5870666104170902211",
+ cfi.Serialize());
+}
+
+TEST_F(Simple, SetManyRules) {
+ ExpectNoMemoryReferences();
+
+ cfi.SetCFARule("$temp1 68737028 = $temp2 61072337 = $temp1 $temp2 -");
+ cfi.SetRARule(".cfa 99804755 +");
+ cfi.SetRegisterRule("register1", ".cfa 54370437 *");
+ cfi.SetRegisterRule("vodkathumbscrewingly", "24076308 .cfa +");
+ cfi.SetRegisterRule("pubvexingfjordschmaltzy", ".cfa 29801007 -");
+ cfi.SetRegisterRule("uncopyrightables", "92642917 .cfa /");
+ ASSERT_TRUE(cfi.FindCallerRegs<uint64_t>(registers, memory,
+ &caller_registers));
+ ASSERT_EQ(6U, caller_registers.size());
+ ASSERT_EQ(7664691U, caller_registers[".cfa"]);
+ ASSERT_EQ(107469446U, caller_registers[".ra"]);
+ ASSERT_EQ(416732599139967ULL, caller_registers["register1"]);
+ ASSERT_EQ(31740999U, caller_registers["vodkathumbscrewingly"]);
+ ASSERT_EQ(-22136316ULL, caller_registers["pubvexingfjordschmaltzy"]);
+ ASSERT_EQ(12U, caller_registers["uncopyrightables"]);
+ ASSERT_EQ(".cfa: $temp1 68737028 = $temp2 61072337 = $temp1 $temp2 - "
+ ".ra: .cfa 99804755 + "
+ "pubvexingfjordschmaltzy: .cfa 29801007 - "
+ "register1: .cfa 54370437 * "
+ "uncopyrightables: 92642917 .cfa / "
+ "vodkathumbscrewingly: 24076308 .cfa +",
+ cfi.Serialize());
+}
+
+TEST_F(Simple, RulesOverride) {
+ ExpectNoMemoryReferences();
+
+ cfi.SetCFARule("330903416631436410");
+ cfi.SetRARule("5870666104170902211");
+ cfi.SetCFARule("2828089117179001");
+ ASSERT_TRUE(cfi.FindCallerRegs<uint64_t>(registers, memory,
+ &caller_registers));
+ ASSERT_EQ(2U, caller_registers.size());
+ ASSERT_EQ(2828089117179001ULL, caller_registers[".cfa"]);
+ ASSERT_EQ(5870666104170902211ULL, caller_registers[".ra"]);
+ ASSERT_EQ(".cfa: 2828089117179001 .ra: 5870666104170902211",
+ cfi.Serialize());
+}
+
+class Scope: public CFIFixture, public Test { };
+
+// There should be no value for .cfa in scope when evaluating the CFA rule.
+TEST_F(Scope, CFALacksCFA) {
+ ExpectNoMemoryReferences();
+
+ cfi.SetCFARule(".cfa");
+ cfi.SetRARule("0");
+ ASSERT_FALSE(cfi.FindCallerRegs<uint64_t>(registers, memory,
+ &caller_registers));
+}
+
+// There should be no value for .ra in scope when evaluating the CFA rule.
+TEST_F(Scope, CFALacksRA) {
+ ExpectNoMemoryReferences();
+
+ cfi.SetCFARule(".ra");
+ cfi.SetRARule("0");
+ ASSERT_FALSE(cfi.FindCallerRegs<uint64_t>(registers, memory,
+ &caller_registers));
+}
+
+// The current frame's registers should be in scope when evaluating
+// the CFA rule.
+TEST_F(Scope, CFASeesCurrentRegs) {
+ ExpectNoMemoryReferences();
+
+ registers[".baraminology"] = 0x06a7bc63e4f13893ULL;
+ registers[".ornithorhynchus"] = 0x5e0bf850bafce9d2ULL;
+ cfi.SetCFARule(".baraminology .ornithorhynchus +");
+ cfi.SetRARule("0");
+ ASSERT_TRUE(cfi.FindCallerRegs<uint64_t>(registers, memory,
+ &caller_registers));
+ ASSERT_EQ(2U, caller_registers.size());
+ ASSERT_EQ(0x06a7bc63e4f13893ULL + 0x5e0bf850bafce9d2ULL,
+ caller_registers[".cfa"]);
+}
+
+// .cfa should be in scope in the return address expression.
+TEST_F(Scope, RASeesCFA) {
+ ExpectNoMemoryReferences();
+
+ cfi.SetCFARule("48364076");
+ cfi.SetRARule(".cfa");
+ ASSERT_TRUE(cfi.FindCallerRegs<uint64_t>(registers, memory,
+ &caller_registers));
+ ASSERT_EQ(2U, caller_registers.size());
+ ASSERT_EQ(48364076U, caller_registers[".ra"]);
+}
+
+// There should be no value for .ra in scope when evaluating the CFA rule.
+TEST_F(Scope, RALacksRA) {
+ ExpectNoMemoryReferences();
+
+ cfi.SetCFARule("0");
+ cfi.SetRARule(".ra");
+ ASSERT_FALSE(cfi.FindCallerRegs<uint64_t>(registers, memory,
+ &caller_registers));
+}
+
+// The current frame's registers should be in scope in the return
+// address expression.
+TEST_F(Scope, RASeesCurrentRegs) {
+ ExpectNoMemoryReferences();
+
+ registers["noachian"] = 0x54dc4a5d8e5eb503ULL;
+ cfi.SetCFARule("10359370");
+ cfi.SetRARule("noachian");
+ ASSERT_TRUE(cfi.FindCallerRegs<uint64_t>(registers, memory,
+ &caller_registers));
+ ASSERT_EQ(2U, caller_registers.size());
+ ASSERT_EQ(0x54dc4a5d8e5eb503ULL, caller_registers[".ra"]);
+}
+
+// .cfa should be in scope for register rules.
+TEST_F(Scope, RegistersSeeCFA) {
+ ExpectNoMemoryReferences();
+
+ cfi.SetCFARule("6515179");
+ cfi.SetRARule(".cfa");
+ cfi.SetRegisterRule("rogerian", ".cfa");
+ ASSERT_TRUE(cfi.FindCallerRegs<uint64_t>(registers, memory,
+ &caller_registers));
+ ASSERT_EQ(3U, caller_registers.size());
+ ASSERT_EQ(6515179U, caller_registers["rogerian"]);
+}
+
+// The return address should not be in scope for register rules.
+TEST_F(Scope, RegsLackRA) {
+ ExpectNoMemoryReferences();
+
+ cfi.SetCFARule("42740329");
+ cfi.SetRARule("27045204");
+ cfi.SetRegisterRule("$r1", ".ra");
+ ASSERT_FALSE(cfi.FindCallerRegs<uint64_t>(registers, memory,
+ &caller_registers));
+}
+
+// Register rules can see the current frame's register values.
+TEST_F(Scope, RegsSeeRegs) {
+ ExpectNoMemoryReferences();
+
+ registers["$r1"] = 0x6ed3582c4bedb9adULL;
+ registers["$r2"] = 0xd27d9e742b8df6d0ULL;
+ cfi.SetCFARule("88239303");
+ cfi.SetRARule("30503835");
+ cfi.SetRegisterRule("$r1", "$r1 42175211 = $r2");
+ cfi.SetRegisterRule("$r2", "$r2 21357221 = $r1");
+ ASSERT_TRUE(cfi.FindCallerRegs<uint64_t>(registers, memory,
+ &caller_registers));
+ ASSERT_EQ(4U, caller_registers.size());
+ ASSERT_EQ(0xd27d9e742b8df6d0ULL, caller_registers["$r1"]);
+ ASSERT_EQ(0x6ed3582c4bedb9adULL, caller_registers["$r2"]);
+}
+
+// Each rule's temporaries are separate.
+TEST_F(Scope, SeparateTempsRA) {
+ ExpectNoMemoryReferences();
+
+ cfi.SetCFARule("$temp1 76569129 = $temp1");
+ cfi.SetRARule("0");
+ ASSERT_TRUE(cfi.FindCallerRegs<uint64_t>(registers, memory,
+ &caller_registers));
+
+ cfi.SetCFARule("$temp1 76569129 = $temp1");
+ cfi.SetRARule("$temp1");
+ ASSERT_FALSE(cfi.FindCallerRegs<uint64_t>(registers, memory,
+ &caller_registers));
+}
+
+class MockCFIRuleParserHandler: public CFIRuleParser::Handler {
+ public:
+ MOCK_METHOD1(CFARule, void(const string &));
+ MOCK_METHOD1(RARule, void(const string &));
+ MOCK_METHOD2(RegisterRule, void(const string &, const string &));
+};
+
+// A fixture class for testing CFIRuleParser.
+class CFIParserFixture {
+ public:
+ CFIParserFixture() : parser(&mock_handler) {
+ // Expect no parsing results to be reported to mock_handler. Individual
+ // tests can override this.
+ EXPECT_CALL(mock_handler, CFARule(_)).Times(0);
+ EXPECT_CALL(mock_handler, RARule(_)).Times(0);
+ EXPECT_CALL(mock_handler, RegisterRule(_, _)).Times(0);
+ }
+
+ MockCFIRuleParserHandler mock_handler;
+ CFIRuleParser parser;
+};
+
+class Parser: public CFIParserFixture, public Test { };
+
+TEST_F(Parser, Empty) {
+ EXPECT_FALSE(parser.Parse(""));
+}
+
+TEST_F(Parser, LoneColon) {
+ EXPECT_FALSE(parser.Parse(":"));
+}
+
+TEST_F(Parser, CFANoExpr) {
+ EXPECT_FALSE(parser.Parse(".cfa:"));
+}
+
+TEST_F(Parser, CFANoColonNoExpr) {
+ EXPECT_FALSE(parser.Parse(".cfa"));
+}
+
+TEST_F(Parser, RANoExpr) {
+ EXPECT_FALSE(parser.Parse(".ra:"));
+}
+
+TEST_F(Parser, RANoColonNoExpr) {
+ EXPECT_FALSE(parser.Parse(".ra"));
+}
+
+TEST_F(Parser, RegNoExpr) {
+ EXPECT_FALSE(parser.Parse("reg:"));
+}
+
+TEST_F(Parser, NoName) {
+ EXPECT_FALSE(parser.Parse("expr"));
+}
+
+TEST_F(Parser, NoNameTwo) {
+ EXPECT_FALSE(parser.Parse("expr1 expr2"));
+}
+
+TEST_F(Parser, StartsWithExpr) {
+ EXPECT_FALSE(parser.Parse("expr1 reg: expr2"));
+}
+
+TEST_F(Parser, CFA) {
+ EXPECT_CALL(mock_handler, CFARule("spleen")).WillOnce(Return());
+ EXPECT_TRUE(parser.Parse(".cfa: spleen"));
+}
+
+TEST_F(Parser, RA) {
+ EXPECT_CALL(mock_handler, RARule("notoriety")).WillOnce(Return());
+ EXPECT_TRUE(parser.Parse(".ra: notoriety"));
+}
+
+TEST_F(Parser, Reg) {
+ EXPECT_CALL(mock_handler, RegisterRule("nemo", "mellifluous"))
+ .WillOnce(Return());
+ EXPECT_TRUE(parser.Parse("nemo: mellifluous"));
+}
+
+TEST_F(Parser, CFARARegs) {
+ EXPECT_CALL(mock_handler, CFARule("cfa expression")).WillOnce(Return());
+ EXPECT_CALL(mock_handler, RARule("ra expression")).WillOnce(Return());
+ EXPECT_CALL(mock_handler, RegisterRule("galba", "praetorian"))
+ .WillOnce(Return());
+ EXPECT_CALL(mock_handler, RegisterRule("otho", "vitellius"))
+ .WillOnce(Return());
+ EXPECT_TRUE(parser.Parse(".cfa: cfa expression .ra: ra expression "
+ "galba: praetorian otho: vitellius"));
+}
+
+TEST_F(Parser, Whitespace) {
+ EXPECT_CALL(mock_handler, RegisterRule("r1", "r1 expression"))
+ .WillOnce(Return());
+ EXPECT_CALL(mock_handler, RegisterRule("r2", "r2 expression"))
+ .WillOnce(Return());
+ EXPECT_TRUE(parser.Parse(" r1:\tr1\nexpression \tr2:\t\rr2\r\n "
+ "expression \n"));
+}
+
+TEST_F(Parser, WhitespaceLoneColon) {
+ EXPECT_FALSE(parser.Parse(" \n:\t "));
+}
+
+TEST_F(Parser, EmptyName) {
+ EXPECT_CALL(mock_handler, RegisterRule("reg", _))
+ .Times(AtMost(1))
+ .WillRepeatedly(Return());
+ EXPECT_FALSE(parser.Parse("reg: expr1 : expr2"));
+}
+
+TEST_F(Parser, RuleLoneColon) {
+ EXPECT_CALL(mock_handler, RegisterRule("r1", "expr"))
+ .Times(AtMost(1))
+ .WillRepeatedly(Return());
+ EXPECT_FALSE(parser.Parse(" r1: expr :"));
+}
+
+TEST_F(Parser, RegNoExprRule) {
+ EXPECT_CALL(mock_handler, RegisterRule("r1", "expr"))
+ .Times(AtMost(1))
+ .WillRepeatedly(Return());
+ EXPECT_FALSE(parser.Parse("r0: r1: expr"));
+}
+
+class ParseHandlerFixture: public CFIFixture {
+ public:
+ ParseHandlerFixture() : CFIFixture(), handler(&cfi) { }
+ CFIFrameInfoParseHandler handler;
+};
+
+class ParseHandler: public ParseHandlerFixture, public Test { };
+
+TEST_F(ParseHandler, CFARARule) {
+ handler.CFARule("reg-for-cfa");
+ handler.RARule("reg-for-ra");
+ registers["reg-for-cfa"] = 0x268a9a4a3821a797ULL;
+ registers["reg-for-ra"] = 0x6301b475b8b91c02ULL;
+ ASSERT_TRUE(cfi.FindCallerRegs<uint64_t>(registers, memory,
+ &caller_registers));
+ ASSERT_EQ(0x268a9a4a3821a797ULL, caller_registers[".cfa"]);
+ ASSERT_EQ(0x6301b475b8b91c02ULL, caller_registers[".ra"]);
+}
+
+TEST_F(ParseHandler, RegisterRules) {
+ handler.CFARule("reg-for-cfa");
+ handler.RARule("reg-for-ra");
+ handler.RegisterRule("reg1", "reg-for-reg1");
+ handler.RegisterRule("reg2", "reg-for-reg2");
+ registers["reg-for-cfa"] = 0x268a9a4a3821a797ULL;
+ registers["reg-for-ra"] = 0x6301b475b8b91c02ULL;
+ registers["reg-for-reg1"] = 0x06cde8e2ff062481ULL;
+ registers["reg-for-reg2"] = 0xff0c4f76403173e2ULL;
+ ASSERT_TRUE(cfi.FindCallerRegs<uint64_t>(registers, memory,
+ &caller_registers));
+ ASSERT_EQ(0x268a9a4a3821a797ULL, caller_registers[".cfa"]);
+ ASSERT_EQ(0x6301b475b8b91c02ULL, caller_registers[".ra"]);
+ ASSERT_EQ(0x06cde8e2ff062481ULL, caller_registers["reg1"]);
+ ASSERT_EQ(0xff0c4f76403173e2ULL, caller_registers["reg2"]);
+}
+
+struct SimpleCFIWalkerFixture {
+ struct RawContext {
+ uint64_t r0, r1, r2, r3, r4, sp, pc;
+ };
+ enum Validity {
+ R0_VALID = 0x01,
+ R1_VALID = 0x02,
+ R2_VALID = 0x04,
+ R3_VALID = 0x08,
+ R4_VALID = 0x10,
+ SP_VALID = 0x20,
+ PC_VALID = 0x40
+ };
+ typedef SimpleCFIWalker<uint64_t, RawContext> CFIWalker;
+
+ SimpleCFIWalkerFixture()
+ : walker(register_map,
+ sizeof(register_map) / sizeof(register_map[0])) { }
+
+ static CFIWalker::RegisterSet register_map[7];
+ CFIFrameInfo call_frame_info;
+ CFIWalker walker;
+ MockMemoryRegion memory;
+ RawContext callee_context, caller_context;
+};
+
+SimpleCFIWalkerFixture::CFIWalker::RegisterSet
+SimpleCFIWalkerFixture::register_map[7] = {
+ { "r0", NULL, true, R0_VALID, &RawContext::r0 },
+ { "r1", NULL, true, R1_VALID, &RawContext::r1 },
+ { "r2", NULL, false, R2_VALID, &RawContext::r2 },
+ { "r3", NULL, false, R3_VALID, &RawContext::r3 },
+ { "r4", NULL, true, R4_VALID, &RawContext::r4 },
+ { "sp", ".cfa", true, SP_VALID, &RawContext::sp },
+ { "pc", ".ra", true, PC_VALID, &RawContext::pc },
+};
+
+class SimpleWalker: public SimpleCFIWalkerFixture, public Test { };
+
+TEST_F(SimpleWalker, Walk) {
+ // Stack_top is the current stack pointer, pointing to the lowest
+ // address of a frame that looks like this (all 64-bit words):
+ //
+ // sp -> saved r0
+ // garbage
+ // return address
+ // cfa ->
+ //
+ // r0 has been saved on the stack.
+ // r1 has been saved in r2.
+ // r2 and r3 are not recoverable.
+ // r4 is not recoverable, even though it is a callee-saves register.
+ // Some earlier frame's unwinder must have failed to recover it.
+
+ uint64_t stack_top = 0x83254944b20d5512ULL;
+
+ // Saved r0.
+ EXPECT_CALL(memory,
+ GetMemoryAtAddress(stack_top, A<uint64_t *>()))
+ .WillRepeatedly(DoAll(SetArgumentPointee<1>(0xdc1975eba8602302ULL),
+ Return(true)));
+ // Saved return address.
+ EXPECT_CALL(memory,
+ GetMemoryAtAddress(stack_top + 16, A<uint64_t *>()))
+ .WillRepeatedly(DoAll(SetArgumentPointee<1>(0xba5ad6d9acce28deULL),
+ Return(true)));
+
+ call_frame_info.SetCFARule("sp 24 +");
+ call_frame_info.SetRARule(".cfa 8 - ^");
+ call_frame_info.SetRegisterRule("r0", ".cfa 24 - ^");
+ call_frame_info.SetRegisterRule("r1", "r2");
+
+ callee_context.r0 = 0x94e030ca79edd119ULL;
+ callee_context.r1 = 0x937b4d7e95ce52d9ULL;
+ callee_context.r2 = 0x5fe0027416b8b62aULL; // caller's r1
+ // callee_context.r3 is not valid in callee.
+ // callee_context.r4 is not valid in callee.
+ callee_context.sp = stack_top;
+ callee_context.pc = 0x25b21b224311d280ULL;
+ int callee_validity = R0_VALID | R1_VALID | R2_VALID | SP_VALID | PC_VALID;
+
+ memset(&caller_context, 0, sizeof(caller_context));
+
+ int caller_validity;
+ EXPECT_TRUE(walker.FindCallerRegisters(memory, call_frame_info,
+ callee_context, callee_validity,
+ &caller_context, &caller_validity));
+ EXPECT_EQ(R0_VALID | R1_VALID | SP_VALID | PC_VALID, caller_validity);
+ EXPECT_EQ(0xdc1975eba8602302ULL, caller_context.r0);
+ EXPECT_EQ(0x5fe0027416b8b62aULL, caller_context.r1);
+ EXPECT_EQ(stack_top + 24, caller_context.sp);
+ EXPECT_EQ(0xba5ad6d9acce28deULL, caller_context.pc);
+}
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/contained_range_map-inl.h b/toolkit/crashreporter/google-breakpad/src/processor/contained_range_map-inl.h
new file mode 100644
index 0000000000..4c0ad41f94
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/contained_range_map-inl.h
@@ -0,0 +1,197 @@
+// 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.
+
+// contained_range_map-inl.h: Hierarchically-organized range map implementation.
+//
+// See contained_range_map.h for documentation.
+//
+// Author: Mark Mentovai
+
+#ifndef PROCESSOR_CONTAINED_RANGE_MAP_INL_H__
+#define PROCESSOR_CONTAINED_RANGE_MAP_INL_H__
+
+#include "processor/contained_range_map.h"
+
+#include <assert.h>
+
+#include "processor/logging.h"
+
+
+namespace google_breakpad {
+
+
+template<typename AddressType, typename EntryType>
+ContainedRangeMap<AddressType, EntryType>::~ContainedRangeMap() {
+ // Clear frees the children pointed to by the map, and frees the map itself.
+ Clear();
+}
+
+
+template<typename AddressType, typename EntryType>
+bool ContainedRangeMap<AddressType, EntryType>::StoreRange(
+ const AddressType &base, const AddressType &size, const EntryType &entry) {
+ AddressType high = base + size - 1;
+
+ // Check for undersize or overflow.
+ if (size <= 0 || high < base) {
+ //TODO(nealsid) We are commenting this out in order to prevent
+ // excessive logging. We plan to move to better logging as this
+ // failure happens quite often and is expected(see comment in
+ // basic_source_line_resolver.cc:671).
+ // BPLOG(INFO) << "StoreRange failed, " << HexString(base) << "+"
+ // << HexString(size) << ", " << HexString(high);
+ return false;
+ }
+
+ if (!map_)
+ map_ = new AddressToRangeMap();
+
+ MapIterator iterator_base = map_->lower_bound(base);
+ MapIterator iterator_high = map_->lower_bound(high);
+ MapIterator iterator_end = map_->end();
+
+ if (iterator_base == iterator_high && iterator_base != iterator_end &&
+ base >= iterator_base->second->base_) {
+ // The new range is entirely within an existing child range.
+
+ // If the new range's geometry is exactly equal to an existing child
+ // range's, it violates the containment rules, and an attempt to store
+ // it must fail. iterator_base->first contains the key, which was the
+ // containing child's high address.
+ if (iterator_base->second->base_ == base && iterator_base->first == high) {
+ // TODO(nealsid): See the TODO above on why this is commented out.
+// BPLOG(INFO) << "StoreRange failed, identical range is already "
+// "present: " << HexString(base) << "+" << HexString(size);
+ return false;
+ }
+
+ // Pass the new range on to the child to attempt to store.
+ return iterator_base->second->StoreRange(base, size, entry);
+ }
+
+ // iterator_high might refer to an irrelevant range: one whose base address
+ // is higher than the new range's high address. Set contains_high to true
+ // only if iterator_high refers to a range that is at least partially
+ // within the new range.
+ bool contains_high = iterator_high != iterator_end &&
+ high >= iterator_high->second->base_;
+
+ // If the new range encompasses any existing child ranges, it must do so
+ // fully. Partial containment isn't allowed.
+ if ((iterator_base != iterator_end && base > iterator_base->second->base_) ||
+ (contains_high && high < iterator_high->first)) {
+ // TODO(mmentovai): Some symbol files will trip this check frequently
+ // on STACK lines. Too many messages will be produced. These are more
+ // suitable for a DEBUG channel than an INFO channel.
+ // BPLOG(INFO) << "StoreRange failed, new range partially contains "
+ // "existing range: " << HexString(base) << "+" <<
+ // HexString(size);
+ return false;
+ }
+
+ // When copying and erasing contained ranges, the "end" iterator needs to
+ // point one past the last item of the range to copy. If contains_high is
+ // false, the iterator's already in the right place; the increment is safe
+ // because contains_high can't be true if iterator_high == iterator_end.
+ if (contains_high)
+ ++iterator_high;
+
+ // Optimization: if the iterators are equal, no child ranges would be
+ // moved. Create the new child range with a NULL map to conserve space
+ // in leaf nodes, of which there will be many.
+ AddressToRangeMap *child_map = NULL;
+
+ if (iterator_base != iterator_high) {
+ // The children of this range that are contained by the new range must
+ // be transferred over to the new range. Create the new child range map
+ // and copy the pointers to range maps it should contain into it.
+ child_map = new AddressToRangeMap(iterator_base, iterator_high);
+
+ // Remove the copied child pointers from this range's map of children.
+ map_->erase(iterator_base, iterator_high);
+ }
+
+ // Store the new range in the map by its high address. Any children that
+ // the new child range contains were formerly children of this range but
+ // are now this range's grandchildren. Ownership of these is transferred
+ // to the new child range.
+ map_->insert(MapValue(high,
+ new ContainedRangeMap(base, entry, child_map)));
+ return true;
+}
+
+
+template<typename AddressType, typename EntryType>
+bool ContainedRangeMap<AddressType, EntryType>::RetrieveRange(
+ const AddressType &address, EntryType *entry) const {
+ BPLOG_IF(ERROR, !entry) << "ContainedRangeMap::RetrieveRange requires "
+ "|entry|";
+ assert(entry);
+
+ // If nothing was ever stored, then there's nothing to retrieve.
+ if (!map_)
+ return false;
+
+ // Get an iterator to the child range whose high address is equal to or
+ // greater than the supplied address. If the supplied address is higher
+ // than all of the high addresses in the range, then this range does not
+ // contain a child at address, so return false. If the supplied address
+ // is lower than the base address of the child range, then it is not within
+ // the child range, so return false.
+ MapConstIterator iterator = map_->lower_bound(address);
+ if (iterator == map_->end() || address < iterator->second->base_)
+ return false;
+
+ // The child in iterator->second contains the specified address. Find out
+ // if it has a more-specific descendant that also contains it. If it does,
+ // it will set |entry| appropriately. If not, set |entry| to the child.
+ if (!iterator->second->RetrieveRange(address, entry))
+ *entry = iterator->second->entry_;
+
+ return true;
+}
+
+
+template<typename AddressType, typename EntryType>
+void ContainedRangeMap<AddressType, EntryType>::Clear() {
+ if (map_) {
+ MapConstIterator end = map_->end();
+ for (MapConstIterator child = map_->begin(); child != end; ++child)
+ delete child->second;
+
+ delete map_;
+ map_ = NULL;
+ }
+}
+
+
+} // namespace google_breakpad
+
+
+#endif // PROCESSOR_CONTAINED_RANGE_MAP_INL_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/contained_range_map.h b/toolkit/crashreporter/google-breakpad/src/processor/contained_range_map.h
new file mode 100644
index 0000000000..1015ae8cfd
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/contained_range_map.h
@@ -0,0 +1,150 @@
+// 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.
+
+// contained_range_map.h: Hierarchically-organized range maps.
+//
+// A contained range map is similar to a standard range map, except it allows
+// objects to be organized hierarchically. A contained range map allows
+// objects to contain other objects. It is not sensitive to the order that
+// objects are added to the map: larger, more general, containing objects
+// may be added either before or after smaller, more specific, contained
+// ones.
+//
+// Contained range maps guarantee that each object may only contain smaller
+// objects than itself, and that a parent object may only contain child
+// objects located entirely within the parent's address space. Attempts
+// to introduce objects (via StoreRange) that violate these rules will fail.
+// Retrieval (via RetrieveRange) always returns the most specific (smallest)
+// object that contains the address being queried. Note that while it is
+// not possible to insert two objects into a map that have exactly the same
+// geometry (base address and size), it is possible to completely mask a
+// larger object by inserting smaller objects that entirely fill the larger
+// object's address space.
+//
+// Internally, contained range maps are implemented as a tree. Each tree
+// node except for the root node describes an object in the map. Each node
+// maintains its list of children in a map similar to a standard range map,
+// keyed by the highest address that each child occupies. Each node's
+// children occupy address ranges entirely within the node. The root node
+// is the only node directly accessible to the user, and represents the
+// entire address space.
+//
+// Author: Mark Mentovai
+
+#ifndef PROCESSOR_CONTAINED_RANGE_MAP_H__
+#define PROCESSOR_CONTAINED_RANGE_MAP_H__
+
+
+#include <map>
+
+
+namespace google_breakpad {
+
+// Forward declarations (for later friend declarations of specialized template).
+template<class, class> class ContainedRangeMapSerializer;
+
+template<typename AddressType, typename EntryType>
+class ContainedRangeMap {
+ public:
+ // The default constructor creates a ContainedRangeMap with no geometry
+ // and no entry, and as such is only suitable for the root node of a
+ // ContainedRangeMap tree.
+ ContainedRangeMap() : base_(), entry_(), map_(NULL) {}
+
+ ~ContainedRangeMap();
+
+ // Inserts a range into the map. If the new range is encompassed by
+ // an existing child range, the new range is passed into the child range's
+ // StoreRange method. If the new range encompasses any existing child
+ // ranges, those child ranges are moved to the new range, becoming
+ // grandchildren of this ContainedRangeMap. Returns false for a
+ // parameter error, or if the ContainedRangeMap hierarchy guarantees
+ // would be violated.
+ bool StoreRange(const AddressType &base,
+ const AddressType &size,
+ const EntryType &entry);
+
+ // Retrieves the most specific (smallest) descendant range encompassing
+ // the specified address. This method will only return entries held by
+ // child ranges, and not the entry contained by |this|. This is necessary
+ // to support a sparsely-populated root range. If no descendant range
+ // encompasses the address, returns false.
+ bool RetrieveRange(const AddressType &address, EntryType *entry) const;
+
+ // Removes all children. Note that Clear only removes descendants,
+ // leaving the node on which it is called intact. Because the only
+ // meaningful things contained by a root node are descendants, this
+ // is sufficient to restore an entire ContainedRangeMap to its initial
+ // empty state when called on the root node.
+ void Clear();
+
+ private:
+ friend class ContainedRangeMapSerializer<AddressType, EntryType>;
+ friend class ModuleComparer;
+
+ // AddressToRangeMap stores pointers. This makes reparenting simpler in
+ // StoreRange, because it doesn't need to copy entire objects.
+ typedef std::map<AddressType, ContainedRangeMap *> AddressToRangeMap;
+ typedef typename AddressToRangeMap::const_iterator MapConstIterator;
+ typedef typename AddressToRangeMap::iterator MapIterator;
+ typedef typename AddressToRangeMap::value_type MapValue;
+
+ // Creates a new ContainedRangeMap with the specified base address, entry,
+ // and initial child map, which may be NULL. This is only used internally
+ // by ContainedRangeMap when it creates a new child.
+ ContainedRangeMap(const AddressType &base, const EntryType &entry,
+ AddressToRangeMap *map)
+ : base_(base), entry_(entry), map_(map) {}
+
+ // The base address of this range. The high address does not need to
+ // be stored, because it is used as the key to an object in its parent's
+ // map, and all ContainedRangeMaps except for the root range are contained
+ // within maps. The root range does not actually contain an entry, so its
+ // base_ field is meaningless, and the fact that it has no parent and thus
+ // no key is unimportant. For this reason, the base_ field should only be
+ // is accessed on child ContainedRangeMap objects, and never on |this|.
+ const AddressType base_;
+
+ // The entry corresponding to this range. The root range does not
+ // actually contain an entry, so its entry_ field is meaningless. For
+ // this reason, the entry_ field should only be accessed on child
+ // ContainedRangeMap objects, and never on |this|.
+ const EntryType entry_;
+
+ // The map containing child ranges, keyed by each child range's high
+ // address. This is a pointer to avoid allocating map structures for
+ // leaf nodes, where they are not needed.
+ AddressToRangeMap *map_;
+};
+
+
+} // namespace google_breakpad
+
+
+#endif // PROCESSOR_CONTAINED_RANGE_MAP_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/contained_range_map_unittest.cc b/toolkit/crashreporter/google-breakpad/src/processor/contained_range_map_unittest.cc
new file mode 100644
index 0000000000..e5910da0d5
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/contained_range_map_unittest.cc
@@ -0,0 +1,263 @@
+// 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.
+
+// contained_range_map_unittest.cc: Unit tests for ContainedRangeMap
+//
+// Author: Mark Mentovai
+
+#include <stdio.h>
+
+#include "processor/contained_range_map-inl.h"
+
+#include "processor/logging.h"
+
+
+#define ASSERT_TRUE(condition) \
+ if (!(condition)) { \
+ fprintf(stderr, "FAIL: %s @ %s:%d\n", #condition, __FILE__, __LINE__); \
+ return false; \
+ }
+
+#define ASSERT_FALSE(condition) ASSERT_TRUE(!(condition))
+
+
+namespace {
+
+
+using google_breakpad::ContainedRangeMap;
+
+
+static bool RunTests() {
+ ContainedRangeMap<unsigned int, int> crm;
+
+ // First, do the StoreRange tests. This validates the containment
+ // rules.
+ ASSERT_TRUE (crm.StoreRange(10, 10, 1));
+ ASSERT_FALSE(crm.StoreRange(10, 10, 2)); // exactly equal to 1
+ ASSERT_FALSE(crm.StoreRange(11, 10, 3)); // begins inside 1 and extends up
+ ASSERT_FALSE(crm.StoreRange( 9, 10, 4)); // begins below 1 and ends inside
+ ASSERT_TRUE (crm.StoreRange(11, 9, 5)); // contained by existing
+ ASSERT_TRUE (crm.StoreRange(12, 7, 6));
+ ASSERT_TRUE (crm.StoreRange( 9, 12, 7)); // contains existing
+ ASSERT_TRUE (crm.StoreRange( 9, 13, 8));
+ ASSERT_TRUE (crm.StoreRange( 8, 14, 9));
+ ASSERT_TRUE (crm.StoreRange(30, 3, 10));
+ ASSERT_TRUE (crm.StoreRange(33, 3, 11));
+ ASSERT_TRUE (crm.StoreRange(30, 6, 12)); // storable but totally masked
+ ASSERT_TRUE (crm.StoreRange(40, 8, 13)); // will be totally masked
+ ASSERT_TRUE (crm.StoreRange(40, 4, 14));
+ ASSERT_TRUE (crm.StoreRange(44, 4, 15));
+ ASSERT_FALSE(crm.StoreRange(32, 10, 16)); // begins in #10, ends in #14
+ ASSERT_FALSE(crm.StoreRange(50, 0, 17)); // zero length
+ ASSERT_TRUE (crm.StoreRange(50, 10, 18));
+ ASSERT_TRUE (crm.StoreRange(50, 1, 19));
+ ASSERT_TRUE (crm.StoreRange(59, 1, 20));
+ ASSERT_TRUE (crm.StoreRange(60, 1, 21));
+ ASSERT_TRUE (crm.StoreRange(69, 1, 22));
+ ASSERT_TRUE (crm.StoreRange(60, 10, 23));
+ ASSERT_TRUE (crm.StoreRange(68, 1, 24));
+ ASSERT_TRUE (crm.StoreRange(61, 1, 25));
+ ASSERT_TRUE (crm.StoreRange(61, 8, 26));
+ ASSERT_FALSE(crm.StoreRange(59, 9, 27));
+ ASSERT_FALSE(crm.StoreRange(59, 10, 28));
+ ASSERT_FALSE(crm.StoreRange(59, 11, 29));
+ ASSERT_TRUE (crm.StoreRange(70, 10, 30));
+ ASSERT_TRUE (crm.StoreRange(74, 2, 31));
+ ASSERT_TRUE (crm.StoreRange(77, 2, 32));
+ ASSERT_FALSE(crm.StoreRange(72, 6, 33));
+ ASSERT_TRUE (crm.StoreRange(80, 3, 34));
+ ASSERT_TRUE (crm.StoreRange(81, 1, 35));
+ ASSERT_TRUE (crm.StoreRange(82, 1, 36));
+ ASSERT_TRUE (crm.StoreRange(83, 3, 37));
+ ASSERT_TRUE (crm.StoreRange(84, 1, 38));
+ ASSERT_TRUE (crm.StoreRange(83, 1, 39));
+ ASSERT_TRUE (crm.StoreRange(86, 5, 40));
+ ASSERT_TRUE (crm.StoreRange(88, 1, 41));
+ ASSERT_TRUE (crm.StoreRange(90, 1, 42));
+ ASSERT_TRUE (crm.StoreRange(86, 1, 43));
+ ASSERT_TRUE (crm.StoreRange(87, 1, 44));
+ ASSERT_TRUE (crm.StoreRange(89, 1, 45));
+ ASSERT_TRUE (crm.StoreRange(87, 4, 46));
+ ASSERT_TRUE (crm.StoreRange(87, 3, 47));
+ ASSERT_FALSE(crm.StoreRange(86, 2, 48));
+
+ // Each element in test_data contains the expected result when calling
+ // RetrieveRange on an address.
+ const int test_data[] = {
+ 0, // 0
+ 0, // 1
+ 0, // 2
+ 0, // 3
+ 0, // 4
+ 0, // 5
+ 0, // 6
+ 0, // 7
+ 9, // 8
+ 7, // 9
+ 1, // 10
+ 5, // 11
+ 6, // 12
+ 6, // 13
+ 6, // 14
+ 6, // 15
+ 6, // 16
+ 6, // 17
+ 6, // 18
+ 5, // 19
+ 7, // 20
+ 8, // 21
+ 0, // 22
+ 0, // 23
+ 0, // 24
+ 0, // 25
+ 0, // 26
+ 0, // 27
+ 0, // 28
+ 0, // 29
+ 10, // 30
+ 10, // 31
+ 10, // 32
+ 11, // 33
+ 11, // 34
+ 11, // 35
+ 0, // 36
+ 0, // 37
+ 0, // 38
+ 0, // 39
+ 14, // 40
+ 14, // 41
+ 14, // 42
+ 14, // 43
+ 15, // 44
+ 15, // 45
+ 15, // 46
+ 15, // 47
+ 0, // 48
+ 0, // 49
+ 19, // 50
+ 18, // 51
+ 18, // 52
+ 18, // 53
+ 18, // 54
+ 18, // 55
+ 18, // 56
+ 18, // 57
+ 18, // 58
+ 20, // 59
+ 21, // 60
+ 25, // 61
+ 26, // 62
+ 26, // 63
+ 26, // 64
+ 26, // 65
+ 26, // 66
+ 26, // 67
+ 24, // 68
+ 22, // 69
+ 30, // 70
+ 30, // 71
+ 30, // 72
+ 30, // 73
+ 31, // 74
+ 31, // 75
+ 30, // 76
+ 32, // 77
+ 32, // 78
+ 30, // 79
+ 34, // 80
+ 35, // 81
+ 36, // 82
+ 39, // 83
+ 38, // 84
+ 37, // 85
+ 43, // 86
+ 44, // 87
+ 41, // 88
+ 45, // 89
+ 42, // 90
+ 0, // 91
+ 0, // 92
+ 0, // 93
+ 0, // 94
+ 0, // 95
+ 0, // 96
+ 0, // 97
+ 0, // 98
+ 0 // 99
+ };
+ unsigned int test_high = sizeof(test_data) / sizeof(int);
+
+ // Now, do the RetrieveRange tests. This further validates that the
+ // objects were stored properly and that retrieval returns the correct
+ // object.
+ // If GENERATE_TEST_DATA is defined, instead of the retrieval tests, a
+ // new test_data array will be printed. Exercise caution when doing this.
+ // Be sure to verify the results manually!
+#ifdef GENERATE_TEST_DATA
+ printf(" const int test_data[] = {\n");
+#endif // GENERATE_TEST_DATA
+
+ for (unsigned int address = 0; address < test_high; ++address) {
+ int value;
+ if (!crm.RetrieveRange(address, &value))
+ value = 0;
+
+#ifndef GENERATE_TEST_DATA
+ // Don't use ASSERT inside the loop because it won't show the failed
+ // |address|, and the line number will always be the same. That makes
+ // it difficult to figure out which test failed.
+ if (value != test_data[address]) {
+ fprintf(stderr, "FAIL: retrieve %d expected %d observed %d @ %s:%d\n",
+ address, test_data[address], value, __FILE__, __LINE__);
+ return false;
+ }
+#else // !GENERATE_TEST_DATA
+ printf(" %d%c%s // %d\n", value,
+ address == test_high - 1 ? ' ' : ',',
+ value < 10 ? " " : "",
+ address);
+#endif // !GENERATE_TEST_DATA
+ }
+
+#ifdef GENERATE_TEST_DATA
+ printf(" };\n");
+#endif // GENERATE_TEST_DATA
+
+ return true;
+}
+
+
+} // namespace
+
+
+int main(int argc, char **argv) {
+ BPLOG_INIT(&argc, &argv);
+
+ return RunTests() ? 0 : 1;
+}
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/convert_old_arm64_context.cc b/toolkit/crashreporter/google-breakpad/src/processor/convert_old_arm64_context.cc
new file mode 100644
index 0000000000..d4b749e7f2
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/convert_old_arm64_context.cc
@@ -0,0 +1,67 @@
+// Copyright (c) 2018, 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 "processor/convert_old_arm64_context.h"
+
+#include <string.h>
+
+namespace google_breakpad {
+
+void ConvertOldARM64Context(const MDRawContextARM64_Old& old,
+ MDRawContextARM64* context) {
+ context->context_flags = MD_CONTEXT_ARM64;
+ if (old.context_flags & MD_CONTEXT_ARM64_INTEGER_OLD) {
+ context->context_flags |=
+ MD_CONTEXT_ARM64_INTEGER | MD_CONTEXT_ARM64_CONTROL;
+ }
+ if (old.context_flags & MD_CONTEXT_ARM64_FLOATING_POINT_OLD) {
+ context->context_flags |= MD_CONTEXT_ARM64_FLOATING_POINT;
+ }
+
+ context->cpsr = old.cpsr;
+
+ static_assert(sizeof(old.iregs) == sizeof(context->iregs),
+ "iregs size mismatch");
+ memcpy(context->iregs, old.iregs, sizeof(context->iregs));
+
+ static_assert(sizeof(old.float_save.regs) == sizeof(context->float_save.regs),
+ "float_save.regs size mismatch");
+ memcpy(context->float_save.regs,
+ old.float_save.regs,
+ sizeof(context->float_save.regs));
+ context->float_save.fpcr = old.float_save.fpcr;
+ context->float_save.fpsr = old.float_save.fpsr;
+
+ memset(context->bcr, 0, sizeof(context->bcr));
+ memset(context->bvr, 0, sizeof(context->bvr));
+ memset(context->wcr, 0, sizeof(context->wcr));
+ memset(context->wvr, 0, sizeof(context->wvr));
+}
+
+} // namespace google_breakpad
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/convert_old_arm64_context.h b/toolkit/crashreporter/google-breakpad/src/processor/convert_old_arm64_context.h
new file mode 100644
index 0000000000..8c0dfe900c
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/convert_old_arm64_context.h
@@ -0,0 +1,42 @@
+// Copyright (c) 2018, 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 PROCESSOR_CONVERT_OLD_ARM64_CONTEXT_H__
+#define PROCESSOR_CONVERT_OLD_ARM64_CONTEXT_H__
+
+#include "google_breakpad/common/minidump_cpu_arm64.h"
+
+namespace google_breakpad {
+
+void ConvertOldARM64Context(const MDRawContextARM64_Old& old,
+ MDRawContextARM64* context);
+
+} // namespace google_breakpad
+
+#endif // PROCESSOR_CONVERT_OLD_ARM64_CONTEXT_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/disassembler_x86.cc b/toolkit/crashreporter/google-breakpad/src/processor/disassembler_x86.cc
new file mode 100644
index 0000000000..559022404f
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/disassembler_x86.cc
@@ -0,0 +1,240 @@
+// 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.
+
+// disassembler_x86.cc: simple x86 disassembler.
+//
+// Provides single step disassembly of x86 bytecode and flags instructions
+// that utilize known bad register values.
+//
+// Author: Cris Neckar
+
+#include "processor/disassembler_x86.h"
+
+#include <string.h>
+
+namespace google_breakpad {
+
+DisassemblerX86::DisassemblerX86(const uint8_t *bytecode,
+ uint32_t size,
+ uint32_t virtual_address) :
+ bytecode_(bytecode),
+ size_(size),
+ virtual_address_(virtual_address),
+ current_byte_offset_(0),
+ current_inst_offset_(0),
+ instr_valid_(false),
+ register_valid_(false),
+ pushed_bad_value_(false),
+ end_of_block_(false),
+ flags_(0) {
+ libdis::x86_init(libdis::opt_none, NULL, NULL);
+}
+
+DisassemblerX86::~DisassemblerX86() {
+ if (instr_valid_)
+ libdis::x86_oplist_free(&current_instr_);
+
+ libdis::x86_cleanup();
+}
+
+uint32_t DisassemblerX86::NextInstruction() {
+ if (instr_valid_)
+ libdis::x86_oplist_free(&current_instr_);
+
+ if (current_byte_offset_ >= size_) {
+ instr_valid_ = false;
+ return 0;
+ }
+ uint32_t instr_size = 0;
+ instr_size = libdis::x86_disasm((unsigned char *)bytecode_, size_,
+ virtual_address_, current_byte_offset_,
+ &current_instr_);
+ if (instr_size == 0) {
+ instr_valid_ = false;
+ return 0;
+ }
+
+ current_byte_offset_ += instr_size;
+ current_inst_offset_++;
+ instr_valid_ = libdis::x86_insn_is_valid(&current_instr_);
+ if (!instr_valid_)
+ return 0;
+
+ if (current_instr_.type == libdis::insn_return)
+ end_of_block_ = true;
+ libdis::x86_op_t *src = libdis::x86_get_src_operand(&current_instr_);
+ libdis::x86_op_t *dest = libdis::x86_get_dest_operand(&current_instr_);
+
+ if (register_valid_) {
+ switch (current_instr_.group) {
+ // Flag branches based off of bad registers and calls that occur
+ // after pushing bad values.
+ case libdis::insn_controlflow:
+ switch (current_instr_.type) {
+ case libdis::insn_jmp:
+ case libdis::insn_jcc:
+ case libdis::insn_call:
+ case libdis::insn_callcc:
+ if (dest) {
+ switch (dest->type) {
+ case libdis::op_expression:
+ if (dest->data.expression.base.id == bad_register_.id)
+ flags_ |= DISX86_BAD_BRANCH_TARGET;
+ break;
+ case libdis::op_register:
+ if (dest->data.reg.id == bad_register_.id)
+ flags_ |= DISX86_BAD_BRANCH_TARGET;
+ break;
+ default:
+ if (pushed_bad_value_ &&
+ (current_instr_.type == libdis::insn_call ||
+ current_instr_.type == libdis::insn_callcc))
+ flags_ |= DISX86_BAD_ARGUMENT_PASSED;
+ break;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ break;
+
+ // Flag block data operations that use bad registers for src or dest.
+ case libdis::insn_string:
+ if (dest && dest->type == libdis::op_expression &&
+ dest->data.expression.base.id == bad_register_.id)
+ flags_ |= DISX86_BAD_BLOCK_WRITE;
+ if (src && src->type == libdis::op_expression &&
+ src->data.expression.base.id == bad_register_.id)
+ flags_ |= DISX86_BAD_BLOCK_READ;
+ break;
+
+ // Flag comparisons based on bad data.
+ case libdis::insn_comparison:
+ if ((dest && dest->type == libdis::op_expression &&
+ dest->data.expression.base.id == bad_register_.id) ||
+ (src && src->type == libdis::op_expression &&
+ src->data.expression.base.id == bad_register_.id) ||
+ (dest && dest->type == libdis::op_register &&
+ dest->data.reg.id == bad_register_.id) ||
+ (src && src->type == libdis::op_register &&
+ src->data.reg.id == bad_register_.id))
+ flags_ |= DISX86_BAD_COMPARISON;
+ break;
+
+ // Flag any other instruction which derefs a bad register for
+ // src or dest.
+ default:
+ if (dest && dest->type == libdis::op_expression &&
+ dest->data.expression.base.id == bad_register_.id)
+ flags_ |= DISX86_BAD_WRITE;
+ if (src && src->type == libdis::op_expression &&
+ src->data.expression.base.id == bad_register_.id)
+ flags_ |= DISX86_BAD_READ;
+ break;
+ }
+ }
+
+ // When a register is marked as tainted check if it is pushed.
+ // TODO(cdn): may also want to check for MOVs into EBP offsets.
+ if (register_valid_ && dest && current_instr_.type == libdis::insn_push) {
+ switch (dest->type) {
+ case libdis::op_expression:
+ if (dest->data.expression.base.id == bad_register_.id ||
+ dest->data.expression.index.id == bad_register_.id)
+ pushed_bad_value_ = true;
+ break;
+ case libdis::op_register:
+ if (dest->data.reg.id == bad_register_.id)
+ pushed_bad_value_ = true;
+ break;
+ default:
+ break;
+ }
+ }
+
+ // Check if a tainted register value is clobbered.
+ // For conditional MOVs and XCHGs assume that
+ // there is a hit.
+ if (register_valid_) {
+ switch (current_instr_.type) {
+ case libdis::insn_xor:
+ if (src && src->type == libdis::op_register &&
+ dest && dest->type == libdis::op_register &&
+ src->data.reg.id == bad_register_.id &&
+ src->data.reg.id == dest->data.reg.id)
+ register_valid_ = false;
+ break;
+ case libdis::insn_pop:
+ case libdis::insn_mov:
+ case libdis::insn_movcc:
+ if (dest && dest->type == libdis::op_register &&
+ dest->data.reg.id == bad_register_.id)
+ register_valid_ = false;
+ break;
+ case libdis::insn_popregs:
+ register_valid_ = false;
+ break;
+ case libdis::insn_xchg:
+ case libdis::insn_xchgcc:
+ if (dest && dest->type == libdis::op_register &&
+ src && src->type == libdis::op_register) {
+ if (dest->data.reg.id == bad_register_.id)
+ memcpy(&bad_register_, &src->data.reg, sizeof(libdis::x86_reg_t));
+ else if (src->data.reg.id == bad_register_.id)
+ memcpy(&bad_register_, &dest->data.reg, sizeof(libdis::x86_reg_t));
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ return instr_size;
+}
+
+bool DisassemblerX86::setBadRead() {
+ if (!instr_valid_)
+ return false;
+
+ libdis::x86_op_t *operand = libdis::x86_get_src_operand(&current_instr_);
+ if (!operand || operand->type != libdis::op_expression)
+ return false;
+
+ memcpy(&bad_register_, &operand->data.expression.base,
+ sizeof(libdis::x86_reg_t));
+ register_valid_ = true;
+ return true;
+}
+
+bool DisassemblerX86::setBadWrite() {
+ if (!instr_valid_)
+ return false;
+
+ libdis::x86_op_t *operand = libdis::x86_get_dest_operand(&current_instr_);
+ if (!operand || operand->type != libdis::op_expression)
+ return false;
+
+ memcpy(&bad_register_, &operand->data.expression.base,
+ sizeof(libdis::x86_reg_t));
+ register_valid_ = true;
+ return true;
+}
+
+} // namespace google_breakpad
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/disassembler_x86.h b/toolkit/crashreporter/google-breakpad/src/processor/disassembler_x86.h
new file mode 100644
index 0000000000..7106941072
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/disassembler_x86.h
@@ -0,0 +1,127 @@
+// 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.
+
+// disassembler_x86.h: Basic x86 bytecode disassembler
+//
+// Provides a simple disassembler which wraps libdisasm. This allows simple
+// tests to be run against bytecode to test for various properties.
+//
+// Author: Cris Neckar
+
+#ifndef GOOGLE_BREAKPAD_PROCESSOR_DISASSEMBLER_X86_H_
+#define GOOGLE_BREAKPAD_PROCESSOR_DISASSEMBLER_X86_H_
+
+#include <stddef.h>
+#include <sys/types.h>
+
+#include "google_breakpad/common/breakpad_types.h"
+
+namespace libdis {
+#include "third_party/libdisasm/libdis.h"
+}
+
+namespace google_breakpad {
+
+enum {
+ DISX86_NONE = 0x0,
+ DISX86_BAD_BRANCH_TARGET = 0x1,
+ DISX86_BAD_ARGUMENT_PASSED = 0x2,
+ DISX86_BAD_WRITE = 0x4,
+ DISX86_BAD_BLOCK_WRITE = 0x8,
+ DISX86_BAD_READ = 0x10,
+ DISX86_BAD_BLOCK_READ = 0x20,
+ DISX86_BAD_COMPARISON = 0x40
+};
+
+class DisassemblerX86 {
+ public:
+ // TODO(cdn): Modify this class to take a MemoryRegion instead of just
+ // a raw buffer. This will make it easier to use this on arbitrary
+ // minidumps without first copying out the code segment.
+ DisassemblerX86(const uint8_t *bytecode, uint32_t, uint32_t);
+ ~DisassemblerX86();
+
+ // This walks to the next instruction in the memory region and
+ // sets flags based on the type of instruction and previous state
+ // including any registers marked as bad through setBadRead()
+ // or setBadWrite(). This method can be called in a loop to
+ // disassemble until the end of a region.
+ uint32_t NextInstruction();
+
+ // Indicates whether the current disassembled instruction was valid.
+ bool currentInstructionValid() { return instr_valid_; }
+
+ // Returns the current instruction as defined in libdis.h,
+ // or NULL if the current instruction is not valid.
+ const libdis::x86_insn_t* currentInstruction() {
+ return instr_valid_ ? &current_instr_ : NULL;
+ }
+
+ // Returns the type of the current instruction as defined in libdis.h.
+ libdis::x86_insn_group currentInstructionGroup() {
+ return current_instr_.group;
+ }
+
+ // Indicates whether a return instruction has been encountered.
+ bool endOfBlock() { return end_of_block_; }
+
+ // The flags set so far for the disassembly.
+ uint16_t flags() { return flags_; }
+
+ // This sets an indicator that the register used to determine
+ // src or dest for the current instruction is tainted. These can
+ // be used after examining the current instruction to indicate,
+ // for example that a bad read or write occurred and the pointer
+ // stored in the register is currently invalid.
+ bool setBadRead();
+ bool setBadWrite();
+
+ protected:
+ const uint8_t *bytecode_;
+ uint32_t size_;
+ uint32_t virtual_address_;
+ uint32_t current_byte_offset_;
+ uint32_t current_inst_offset_;
+
+ bool instr_valid_;
+ libdis::x86_insn_t current_instr_;
+
+ // TODO(cdn): Maybe also track an expression's index register.
+ // ex: mov eax, [ebx + ecx]; ebx is base, ecx is index.
+ bool register_valid_;
+ libdis::x86_reg_t bad_register_;
+
+ bool pushed_bad_value_;
+ bool end_of_block_;
+
+ uint16_t flags_;
+};
+
+} // namespace google_breakpad
+
+#endif // GOOGLE_BREAKPAD_PROCESSOR_DISASSEMBLER_X86_H_
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/disassembler_x86_unittest.cc b/toolkit/crashreporter/google-breakpad/src/processor/disassembler_x86_unittest.cc
new file mode 100644
index 0000000000..352905f20d
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/disassembler_x86_unittest.cc
@@ -0,0 +1,233 @@
+// 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 <unistd.h>
+
+#include "breakpad_googletest_includes.h"
+#include "processor/disassembler_x86.h"
+#include "third_party/libdisasm/libdis.h"
+
+namespace {
+
+using google_breakpad::DisassemblerX86;
+
+unsigned char just_return[] = "\xc3"; // retn
+
+unsigned char invalid_instruction[] = "\x00"; // invalid
+
+unsigned char read_eax_jmp_eax[] =
+ "\x8b\x18" // mov ebx, [eax];
+ "\x33\xc9" // xor ebx, ebx;
+ "\xff\x20" // jmp eax;
+ "\xc3"; // retn;
+
+unsigned char write_eax_arg_to_call[] =
+ "\x89\xa8\x00\x02\x00\x00" // mov [eax+200], ebp;
+ "\xc1\xeb\x02" // shr ebx, 2;
+ "\x50" // push eax;
+ "\xe8\xd1\x24\x77\x88" // call something;
+ "\xc3"; // retn;
+
+unsigned char read_edi_stosb[] =
+ "\x8b\x07" // mov eax, [edi];
+ "\x8b\xc8" // mov ecx, eax;
+ "\xf3\xaa" // rep stosb;
+ "\xc3"; // retn;
+
+unsigned char read_clobber_write[] =
+ "\x03\x18" // add ebx, [eax];
+ "\x8b\xc1" // mov eax, ecx;
+ "\x89\x10" // mov [eax], edx;
+ "\xc3"; // retn;
+
+unsigned char read_xchg_write[] =
+ "\x03\x18" // add ebx, [eax];
+ "\x91" // xchg eax, ecx;
+ "\x89\x18" // mov [eax], ebx;
+ "\x89\x11" // mov [ecx], edx;
+ "\xc3"; // retn;
+
+unsigned char read_cmp[] =
+ "\x03\x18" // add ebx, [eax];
+ "\x83\xf8\x00" // cmp eax, 0;
+ "\x74\x04" // je +4;
+ "\xc3"; // retn;
+
+TEST(DisassemblerX86Test, SimpleReturnInstruction) {
+ DisassemblerX86 dis(just_return, sizeof(just_return)-1, 0);
+ EXPECT_EQ(1U, dis.NextInstruction());
+ EXPECT_TRUE(dis.currentInstructionValid());
+ EXPECT_EQ(0U, dis.flags());
+ EXPECT_TRUE(dis.endOfBlock());
+ EXPECT_EQ(libdis::insn_controlflow, dis.currentInstructionGroup());
+ const libdis::x86_insn_t* instruction = dis.currentInstruction();
+ EXPECT_EQ(libdis::insn_controlflow, instruction->group);
+ EXPECT_EQ(libdis::insn_return, instruction->type);
+ EXPECT_EQ(0U, dis.NextInstruction());
+ EXPECT_FALSE(dis.currentInstructionValid());
+ EXPECT_EQ(NULL, dis.currentInstruction());
+}
+
+TEST(DisassemblerX86Test, SimpleInvalidInstruction) {
+ DisassemblerX86 dis(invalid_instruction, sizeof(invalid_instruction)-1, 0);
+ EXPECT_EQ(0U, dis.NextInstruction());
+ EXPECT_FALSE(dis.currentInstructionValid());
+}
+
+TEST(DisassemblerX86Test, BadReadLeadsToBranch) {
+ DisassemblerX86 dis(read_eax_jmp_eax, sizeof(read_eax_jmp_eax)-1, 0);
+ EXPECT_EQ(2U, dis.NextInstruction());
+ EXPECT_TRUE(dis.currentInstructionValid());
+ EXPECT_EQ(0U, dis.flags());
+ EXPECT_FALSE(dis.endOfBlock());
+ EXPECT_EQ(libdis::insn_move, dis.currentInstructionGroup());
+ EXPECT_TRUE(dis.setBadRead());
+ EXPECT_EQ(2U, dis.NextInstruction());
+ EXPECT_TRUE(dis.currentInstructionValid());
+ EXPECT_EQ(0U, dis.flags());
+ EXPECT_FALSE(dis.endOfBlock());
+ EXPECT_EQ(libdis::insn_logic, dis.currentInstructionGroup());
+ EXPECT_EQ(2U, dis.NextInstruction());
+ EXPECT_TRUE(dis.currentInstructionValid());
+ EXPECT_EQ(google_breakpad::DISX86_BAD_BRANCH_TARGET, dis.flags());
+ EXPECT_FALSE(dis.endOfBlock());
+ EXPECT_EQ(libdis::insn_controlflow, dis.currentInstructionGroup());
+}
+
+TEST(DisassemblerX86Test, BadWriteLeadsToPushedArg) {
+ DisassemblerX86 dis(write_eax_arg_to_call,
+ sizeof(write_eax_arg_to_call)-1, 0);
+ EXPECT_EQ(6U, dis.NextInstruction());
+ EXPECT_TRUE(dis.currentInstructionValid());
+ EXPECT_EQ(0U, dis.flags());
+ EXPECT_FALSE(dis.endOfBlock());
+ EXPECT_EQ(libdis::insn_move, dis.currentInstructionGroup());
+ EXPECT_TRUE(dis.setBadWrite());
+ EXPECT_EQ(3U, dis.NextInstruction());
+ EXPECT_TRUE(dis.currentInstructionValid());
+ EXPECT_EQ(0U, dis.flags());
+ EXPECT_FALSE(dis.endOfBlock());
+ EXPECT_EQ(libdis::insn_arithmetic, dis.currentInstructionGroup());
+ EXPECT_EQ(1U, dis.NextInstruction());
+ EXPECT_TRUE(dis.currentInstructionValid());
+ EXPECT_EQ(0U, dis.flags());
+ EXPECT_FALSE(dis.endOfBlock());
+ EXPECT_EQ(5U, dis.NextInstruction());
+ EXPECT_TRUE(dis.currentInstructionValid());
+ EXPECT_EQ(google_breakpad::DISX86_BAD_ARGUMENT_PASSED, dis.flags());
+ EXPECT_EQ(libdis::insn_controlflow, dis.currentInstructionGroup());
+ EXPECT_FALSE(dis.endOfBlock());
+}
+
+
+TEST(DisassemblerX86Test, BadReadLeadsToBlockWrite) {
+ DisassemblerX86 dis(read_edi_stosb, sizeof(read_edi_stosb)-1, 0);
+ EXPECT_EQ(2U, dis.NextInstruction());
+ EXPECT_TRUE(dis.currentInstructionValid());
+ EXPECT_EQ(0U, dis.flags());
+ EXPECT_FALSE(dis.endOfBlock());
+ EXPECT_EQ(libdis::insn_move, dis.currentInstructionGroup());
+ EXPECT_TRUE(dis.setBadRead());
+ EXPECT_EQ(2U, dis.NextInstruction());
+ EXPECT_TRUE(dis.currentInstructionValid());
+ EXPECT_EQ(0U, dis.flags());
+ EXPECT_FALSE(dis.endOfBlock());
+ EXPECT_EQ(libdis::insn_move, dis.currentInstructionGroup());
+ EXPECT_EQ(2U, dis.NextInstruction());
+ EXPECT_TRUE(dis.currentInstructionValid());
+ EXPECT_EQ(google_breakpad::DISX86_BAD_BLOCK_WRITE, dis.flags());
+ EXPECT_FALSE(dis.endOfBlock());
+ EXPECT_EQ(libdis::insn_string, dis.currentInstructionGroup());
+}
+
+TEST(DisassemblerX86Test, BadReadClobberThenWrite) {
+ DisassemblerX86 dis(read_clobber_write, sizeof(read_clobber_write)-1, 0);
+ EXPECT_EQ(2U, dis.NextInstruction());
+ EXPECT_TRUE(dis.currentInstructionValid());
+ EXPECT_EQ(0U, dis.flags());
+ EXPECT_FALSE(dis.endOfBlock());
+ EXPECT_EQ(libdis::insn_arithmetic, dis.currentInstructionGroup());
+ EXPECT_TRUE(dis.setBadRead());
+ EXPECT_EQ(2U, dis.NextInstruction());
+ EXPECT_TRUE(dis.currentInstructionValid());
+ EXPECT_EQ(0U, dis.flags());
+ EXPECT_FALSE(dis.endOfBlock());
+ EXPECT_EQ(libdis::insn_move, dis.currentInstructionGroup());
+ EXPECT_EQ(2U, dis.NextInstruction());
+ EXPECT_TRUE(dis.currentInstructionValid());
+ EXPECT_EQ(0U, dis.flags());
+ EXPECT_FALSE(dis.endOfBlock());
+ EXPECT_EQ(libdis::insn_move, dis.currentInstructionGroup());
+}
+
+TEST(DisassemblerX86Test, BadReadXCHGThenWrite) {
+ DisassemblerX86 dis(read_xchg_write, sizeof(read_xchg_write)-1, 0);
+ EXPECT_EQ(2U, dis.NextInstruction());
+ EXPECT_TRUE(dis.currentInstructionValid());
+ EXPECT_EQ(0U, dis.flags());
+ EXPECT_FALSE(dis.endOfBlock());
+ EXPECT_EQ(libdis::insn_arithmetic, dis.currentInstructionGroup());
+ EXPECT_TRUE(dis.setBadRead());
+ EXPECT_EQ(1U, dis.NextInstruction());
+ EXPECT_TRUE(dis.currentInstructionValid());
+ EXPECT_EQ(0U, dis.flags());
+ EXPECT_FALSE(dis.endOfBlock());
+ EXPECT_EQ(libdis::insn_move, dis.currentInstructionGroup());
+ EXPECT_EQ(2U, dis.NextInstruction());
+ EXPECT_TRUE(dis.currentInstructionValid());
+ EXPECT_EQ(0U, dis.flags());
+ EXPECT_FALSE(dis.endOfBlock());
+ EXPECT_EQ(libdis::insn_move, dis.currentInstructionGroup());
+ EXPECT_EQ(2U, dis.NextInstruction());
+ EXPECT_TRUE(dis.currentInstructionValid());
+ EXPECT_EQ(google_breakpad::DISX86_BAD_WRITE, dis.flags());
+ EXPECT_FALSE(dis.endOfBlock());
+ EXPECT_EQ(libdis::insn_move, dis.currentInstructionGroup());
+}
+
+TEST(DisassemblerX86Test, BadReadThenCMP) {
+ DisassemblerX86 dis(read_cmp, sizeof(read_cmp)-1, 0);
+ EXPECT_EQ(2U, dis.NextInstruction());
+ EXPECT_TRUE(dis.currentInstructionValid());
+ EXPECT_EQ(0U, dis.flags());
+ EXPECT_FALSE(dis.endOfBlock());
+ EXPECT_EQ(libdis::insn_arithmetic, dis.currentInstructionGroup());
+ EXPECT_TRUE(dis.setBadRead());
+ EXPECT_EQ(3U, dis.NextInstruction());
+ EXPECT_TRUE(dis.currentInstructionValid());
+ EXPECT_EQ(google_breakpad::DISX86_BAD_COMPARISON, dis.flags());
+ EXPECT_FALSE(dis.endOfBlock());
+ EXPECT_EQ(libdis::insn_comparison, dis.currentInstructionGroup());
+ EXPECT_EQ(2U, dis.NextInstruction());
+ EXPECT_TRUE(dis.currentInstructionValid());
+ EXPECT_EQ(google_breakpad::DISX86_BAD_COMPARISON, dis.flags());
+ EXPECT_FALSE(dis.endOfBlock());
+ EXPECT_EQ(libdis::insn_controlflow, dis.currentInstructionGroup());
+}
+}
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/dump_context.cc b/toolkit/crashreporter/google-breakpad/src/processor/dump_context.cc
new file mode 100644
index 0000000000..da531b74d0
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/dump_context.cc
@@ -0,0 +1,664 @@
+// 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.
+
+// dump_context.cc: A (mini/micro)dump context.
+//
+// See dump_context.h for documentation.
+
+#include "google_breakpad/processor/dump_context.h"
+
+#include <assert.h>
+
+#ifdef _WIN32
+#include <io.h>
+#else // _WIN32
+#include <unistd.h>
+#endif // _WIN32
+
+#include "common/stdio_wrapper.h"
+#include "processor/logging.h"
+
+namespace google_breakpad {
+
+DumpContext::DumpContext() : context_(),
+ context_flags_(0) { }
+
+DumpContext::~DumpContext() {
+ FreeContext();
+}
+
+uint32_t DumpContext::GetContextCPU() const {
+ if (!valid_) {
+ // Don't log a message, GetContextCPU can be legitimately called with
+ // valid_ false by FreeContext, which is called by Read.
+ return 0;
+ }
+
+ return context_flags_ & MD_CONTEXT_CPU_MASK;
+}
+
+uint32_t DumpContext::GetContextFlags() const {
+ return context_flags_;
+}
+
+const MDRawContextX86* DumpContext::GetContextX86() const {
+ if (GetContextCPU() != MD_CONTEXT_X86) {
+ BPLOG(ERROR) << "DumpContext cannot get x86 context";
+ return NULL;
+ }
+
+ return context_.x86;
+}
+
+const MDRawContextPPC* DumpContext::GetContextPPC() const {
+ if (GetContextCPU() != MD_CONTEXT_PPC) {
+ BPLOG(ERROR) << "DumpContext cannot get ppc context";
+ return NULL;
+ }
+
+ return context_.ppc;
+}
+
+const MDRawContextPPC64* DumpContext::GetContextPPC64() const {
+ if (GetContextCPU() != MD_CONTEXT_PPC64) {
+ BPLOG(ERROR) << "DumpContext cannot get ppc64 context";
+ return NULL;
+ }
+
+ return context_.ppc64;
+}
+
+const MDRawContextAMD64* DumpContext::GetContextAMD64() const {
+ if (GetContextCPU() != MD_CONTEXT_AMD64) {
+ BPLOG(ERROR) << "DumpContext cannot get amd64 context";
+ return NULL;
+ }
+
+ return context_.amd64;
+}
+
+const MDRawContextSPARC* DumpContext::GetContextSPARC() const {
+ if (GetContextCPU() != MD_CONTEXT_SPARC) {
+ BPLOG(ERROR) << "DumpContext cannot get sparc context";
+ return NULL;
+ }
+
+ return context_.ctx_sparc;
+}
+
+const MDRawContextARM* DumpContext::GetContextARM() const {
+ if (GetContextCPU() != MD_CONTEXT_ARM) {
+ BPLOG(ERROR) << "DumpContext cannot get arm context";
+ return NULL;
+ }
+
+ return context_.arm;
+}
+
+const MDRawContextARM64* DumpContext::GetContextARM64() const {
+ if (GetContextCPU() != MD_CONTEXT_ARM64) {
+ BPLOG(ERROR) << "DumpContext cannot get arm64 context";
+ return NULL;
+ }
+
+ return context_.arm64;
+}
+
+const MDRawContextMIPS* DumpContext::GetContextMIPS() const {
+ if ((GetContextCPU() != MD_CONTEXT_MIPS) &&
+ (GetContextCPU() != MD_CONTEXT_MIPS64)) {
+ BPLOG(ERROR) << "DumpContext cannot get MIPS context";
+ return NULL;
+ }
+
+ return context_.ctx_mips;
+}
+
+bool DumpContext::GetInstructionPointer(uint64_t* ip) const {
+ BPLOG_IF(ERROR, !ip) << "DumpContext::GetInstructionPointer requires |ip|";
+ assert(ip);
+ *ip = 0;
+
+ if (!valid_) {
+ BPLOG(ERROR) << "Invalid DumpContext for GetInstructionPointer";
+ return false;
+ }
+
+ switch (GetContextCPU()) {
+ case MD_CONTEXT_AMD64:
+ *ip = GetContextAMD64()->rip;
+ break;
+ case MD_CONTEXT_ARM:
+ *ip = GetContextARM()->iregs[MD_CONTEXT_ARM_REG_PC];
+ break;
+ case MD_CONTEXT_ARM64:
+ *ip = GetContextARM64()->iregs[MD_CONTEXT_ARM64_REG_PC];
+ break;
+ case MD_CONTEXT_PPC:
+ *ip = GetContextPPC()->srr0;
+ break;
+ case MD_CONTEXT_PPC64:
+ *ip = GetContextPPC64()->srr0;
+ break;
+ case MD_CONTEXT_SPARC:
+ *ip = GetContextSPARC()->pc;
+ break;
+ case MD_CONTEXT_X86:
+ *ip = GetContextX86()->eip;
+ break;
+ case MD_CONTEXT_MIPS:
+ case MD_CONTEXT_MIPS64:
+ *ip = GetContextMIPS()->epc;
+ break;
+ default:
+ // This should never happen.
+ BPLOG(ERROR) << "Unknown CPU architecture in GetInstructionPointer";
+ return false;
+ }
+ return true;
+}
+
+bool DumpContext::GetStackPointer(uint64_t* sp) const {
+ BPLOG_IF(ERROR, !sp) << "DumpContext::GetStackPointer requires |sp|";
+ assert(sp);
+ *sp = 0;
+
+ if (!valid_) {
+ BPLOG(ERROR) << "Invalid DumpContext for GetStackPointer";
+ return false;
+ }
+
+ switch (GetContextCPU()) {
+ case MD_CONTEXT_AMD64:
+ *sp = GetContextAMD64()->rsp;
+ break;
+ case MD_CONTEXT_ARM:
+ *sp = GetContextARM()->iregs[MD_CONTEXT_ARM_REG_SP];
+ break;
+ case MD_CONTEXT_ARM64:
+ *sp = GetContextARM64()->iregs[MD_CONTEXT_ARM64_REG_SP];
+ break;
+ case MD_CONTEXT_PPC:
+ *sp = GetContextPPC()->gpr[MD_CONTEXT_PPC_REG_SP];
+ break;
+ case MD_CONTEXT_PPC64:
+ *sp = GetContextPPC64()->gpr[MD_CONTEXT_PPC64_REG_SP];
+ break;
+ case MD_CONTEXT_SPARC:
+ *sp = GetContextSPARC()->g_r[MD_CONTEXT_SPARC_REG_SP];
+ break;
+ case MD_CONTEXT_X86:
+ *sp = GetContextX86()->esp;
+ break;
+ case MD_CONTEXT_MIPS:
+ case MD_CONTEXT_MIPS64:
+ *sp = GetContextMIPS()->iregs[MD_CONTEXT_MIPS_REG_SP];
+ break;
+ default:
+ // This should never happen.
+ BPLOG(ERROR) << "Unknown CPU architecture in GetStackPointer";
+ return false;
+ }
+ return true;
+}
+
+void DumpContext::SetContextFlags(uint32_t context_flags) {
+ context_flags_ = context_flags;
+}
+
+void DumpContext::SetContextX86(MDRawContextX86* x86) {
+ context_.x86 = x86;
+}
+
+void DumpContext::SetContextPPC(MDRawContextPPC* ppc) {
+ context_.ppc = ppc;
+}
+
+void DumpContext::SetContextPPC64(MDRawContextPPC64* ppc64) {
+ context_.ppc64 = ppc64;
+}
+
+void DumpContext::SetContextAMD64(MDRawContextAMD64* amd64) {
+ context_.amd64 = amd64;
+}
+
+void DumpContext::SetContextSPARC(MDRawContextSPARC* ctx_sparc) {
+ context_.ctx_sparc = ctx_sparc;
+}
+
+void DumpContext::SetContextARM(MDRawContextARM* arm) {
+ context_.arm = arm;
+}
+
+void DumpContext::SetContextARM64(MDRawContextARM64* arm64) {
+ context_.arm64 = arm64;
+}
+
+void DumpContext::SetContextMIPS(MDRawContextMIPS* ctx_mips) {
+ context_.ctx_mips = ctx_mips;
+}
+
+void DumpContext::FreeContext() {
+ switch (GetContextCPU()) {
+ case MD_CONTEXT_X86:
+ delete context_.x86;
+ break;
+
+ case MD_CONTEXT_PPC:
+ delete context_.ppc;
+ break;
+
+ case MD_CONTEXT_PPC64:
+ delete context_.ppc64;
+ break;
+
+ case MD_CONTEXT_AMD64:
+ delete context_.amd64;
+ break;
+
+ case MD_CONTEXT_SPARC:
+ delete context_.ctx_sparc;
+ break;
+
+ case MD_CONTEXT_ARM:
+ delete context_.arm;
+ break;
+
+ case MD_CONTEXT_ARM64:
+ delete context_.arm64;
+ break;
+
+ case MD_CONTEXT_MIPS:
+ case MD_CONTEXT_MIPS64:
+ delete context_.ctx_mips;
+ break;
+
+ default:
+ // There is no context record (valid_ is false) or there's a
+ // context record for an unknown CPU (shouldn't happen, only known
+ // records are stored by Read).
+ break;
+ }
+
+ context_flags_ = 0;
+ context_.base = NULL;
+}
+
+void DumpContext::Print() {
+ if (!valid_) {
+ BPLOG(ERROR) << "DumpContext cannot print invalid data";
+ return;
+ }
+
+ switch (GetContextCPU()) {
+ case MD_CONTEXT_X86: {
+ const MDRawContextX86* context_x86 = GetContextX86();
+ printf("MDRawContextX86\n");
+ printf(" context_flags = 0x%x\n",
+ context_x86->context_flags);
+ printf(" dr0 = 0x%x\n", context_x86->dr0);
+ printf(" dr1 = 0x%x\n", context_x86->dr1);
+ printf(" dr2 = 0x%x\n", context_x86->dr2);
+ printf(" dr3 = 0x%x\n", context_x86->dr3);
+ printf(" dr6 = 0x%x\n", context_x86->dr6);
+ printf(" dr7 = 0x%x\n", context_x86->dr7);
+ printf(" float_save.control_word = 0x%x\n",
+ context_x86->float_save.control_word);
+ printf(" float_save.status_word = 0x%x\n",
+ context_x86->float_save.status_word);
+ printf(" float_save.tag_word = 0x%x\n",
+ context_x86->float_save.tag_word);
+ printf(" float_save.error_offset = 0x%x\n",
+ context_x86->float_save.error_offset);
+ printf(" float_save.error_selector = 0x%x\n",
+ context_x86->float_save.error_selector);
+ printf(" float_save.data_offset = 0x%x\n",
+ context_x86->float_save.data_offset);
+ printf(" float_save.data_selector = 0x%x\n",
+ context_x86->float_save.data_selector);
+ printf(" float_save.register_area[%2d] = 0x",
+ MD_FLOATINGSAVEAREA_X86_REGISTERAREA_SIZE);
+ for (unsigned int register_index = 0;
+ register_index < MD_FLOATINGSAVEAREA_X86_REGISTERAREA_SIZE;
+ ++register_index) {
+ printf("%02x", context_x86->float_save.register_area[register_index]);
+ }
+ printf("\n");
+ printf(" float_save.cr0_npx_state = 0x%x\n",
+ context_x86->float_save.cr0_npx_state);
+ printf(" gs = 0x%x\n", context_x86->gs);
+ printf(" fs = 0x%x\n", context_x86->fs);
+ printf(" es = 0x%x\n", context_x86->es);
+ printf(" ds = 0x%x\n", context_x86->ds);
+ printf(" edi = 0x%x\n", context_x86->edi);
+ printf(" esi = 0x%x\n", context_x86->esi);
+ printf(" ebx = 0x%x\n", context_x86->ebx);
+ printf(" edx = 0x%x\n", context_x86->edx);
+ printf(" ecx = 0x%x\n", context_x86->ecx);
+ printf(" eax = 0x%x\n", context_x86->eax);
+ printf(" ebp = 0x%x\n", context_x86->ebp);
+ printf(" eip = 0x%x\n", context_x86->eip);
+ printf(" cs = 0x%x\n", context_x86->cs);
+ printf(" eflags = 0x%x\n", context_x86->eflags);
+ printf(" esp = 0x%x\n", context_x86->esp);
+ printf(" ss = 0x%x\n", context_x86->ss);
+ printf(" extended_registers[%3d] = 0x",
+ MD_CONTEXT_X86_EXTENDED_REGISTERS_SIZE);
+ for (unsigned int register_index = 0;
+ register_index < MD_CONTEXT_X86_EXTENDED_REGISTERS_SIZE;
+ ++register_index) {
+ printf("%02x", context_x86->extended_registers[register_index]);
+ }
+ printf("\n\n");
+
+ break;
+ }
+
+ case MD_CONTEXT_PPC: {
+ const MDRawContextPPC* context_ppc = GetContextPPC();
+ printf("MDRawContextPPC\n");
+ printf(" context_flags = 0x%x\n",
+ context_ppc->context_flags);
+ printf(" srr0 = 0x%x\n", context_ppc->srr0);
+ printf(" srr1 = 0x%x\n", context_ppc->srr1);
+ for (unsigned int gpr_index = 0;
+ gpr_index < MD_CONTEXT_PPC_GPR_COUNT;
+ ++gpr_index) {
+ printf(" gpr[%2d] = 0x%x\n",
+ gpr_index, context_ppc->gpr[gpr_index]);
+ }
+ printf(" cr = 0x%x\n", context_ppc->cr);
+ printf(" xer = 0x%x\n", context_ppc->xer);
+ printf(" lr = 0x%x\n", context_ppc->lr);
+ printf(" ctr = 0x%x\n", context_ppc->ctr);
+ printf(" mq = 0x%x\n", context_ppc->mq);
+ printf(" vrsave = 0x%x\n", context_ppc->vrsave);
+ for (unsigned int fpr_index = 0;
+ fpr_index < MD_FLOATINGSAVEAREA_PPC_FPR_COUNT;
+ ++fpr_index) {
+ printf(" float_save.fpregs[%2d] = 0x%" PRIx64 "\n",
+ fpr_index, context_ppc->float_save.fpregs[fpr_index]);
+ }
+ printf(" float_save.fpscr = 0x%x\n",
+ context_ppc->float_save.fpscr);
+ // TODO(mmentovai): print the 128-bit quantities in
+ // context_ppc->vector_save. This isn't done yet because printf
+ // doesn't support 128-bit quantities, and printing them using
+ // PRIx64 as two 64-bit quantities requires knowledge of the CPU's
+ // byte ordering.
+ printf(" vector_save.save_vrvalid = 0x%x\n",
+ context_ppc->vector_save.save_vrvalid);
+ printf("\n");
+
+ break;
+ }
+
+ case MD_CONTEXT_PPC64: {
+ const MDRawContextPPC64* context_ppc64 = GetContextPPC64();
+ printf("MDRawContextPPC64\n");
+ printf(" context_flags = 0x%" PRIx64 "\n",
+ context_ppc64->context_flags);
+ printf(" srr0 = 0x%" PRIx64 "\n",
+ context_ppc64->srr0);
+ printf(" srr1 = 0x%" PRIx64 "\n",
+ context_ppc64->srr1);
+ for (unsigned int gpr_index = 0;
+ gpr_index < MD_CONTEXT_PPC64_GPR_COUNT;
+ ++gpr_index) {
+ printf(" gpr[%2d] = 0x%" PRIx64 "\n",
+ gpr_index, context_ppc64->gpr[gpr_index]);
+ }
+ printf(" cr = 0x%" PRIx64 "\n", context_ppc64->cr);
+ printf(" xer = 0x%" PRIx64 "\n",
+ context_ppc64->xer);
+ printf(" lr = 0x%" PRIx64 "\n", context_ppc64->lr);
+ printf(" ctr = 0x%" PRIx64 "\n",
+ context_ppc64->ctr);
+ printf(" vrsave = 0x%" PRIx64 "\n",
+ context_ppc64->vrsave);
+ for (unsigned int fpr_index = 0;
+ fpr_index < MD_FLOATINGSAVEAREA_PPC_FPR_COUNT;
+ ++fpr_index) {
+ printf(" float_save.fpregs[%2d] = 0x%" PRIx64 "\n",
+ fpr_index, context_ppc64->float_save.fpregs[fpr_index]);
+ }
+ printf(" float_save.fpscr = 0x%x\n",
+ context_ppc64->float_save.fpscr);
+ // TODO(mmentovai): print the 128-bit quantities in
+ // context_ppc64->vector_save. This isn't done yet because printf
+ // doesn't support 128-bit quantities, and printing them using
+ // PRIx64 as two 64-bit quantities requires knowledge of the CPU's
+ // byte ordering.
+ printf(" vector_save.save_vrvalid = 0x%x\n",
+ context_ppc64->vector_save.save_vrvalid);
+ printf("\n");
+
+ break;
+ }
+
+ case MD_CONTEXT_AMD64: {
+ const MDRawContextAMD64* context_amd64 = GetContextAMD64();
+ printf("MDRawContextAMD64\n");
+ printf(" p1_home = 0x%" PRIx64 "\n",
+ context_amd64->p1_home);
+ printf(" p2_home = 0x%" PRIx64 "\n",
+ context_amd64->p2_home);
+ printf(" p3_home = 0x%" PRIx64 "\n",
+ context_amd64->p3_home);
+ printf(" p4_home = 0x%" PRIx64 "\n",
+ context_amd64->p4_home);
+ printf(" p5_home = 0x%" PRIx64 "\n",
+ context_amd64->p5_home);
+ printf(" p6_home = 0x%" PRIx64 "\n",
+ context_amd64->p6_home);
+ printf(" context_flags = 0x%x\n",
+ context_amd64->context_flags);
+ printf(" mx_csr = 0x%x\n",
+ context_amd64->mx_csr);
+ printf(" cs = 0x%x\n", context_amd64->cs);
+ printf(" ds = 0x%x\n", context_amd64->ds);
+ printf(" es = 0x%x\n", context_amd64->es);
+ printf(" fs = 0x%x\n", context_amd64->fs);
+ printf(" gs = 0x%x\n", context_amd64->gs);
+ printf(" ss = 0x%x\n", context_amd64->ss);
+ printf(" eflags = 0x%x\n", context_amd64->eflags);
+ printf(" dr0 = 0x%" PRIx64 "\n", context_amd64->dr0);
+ printf(" dr1 = 0x%" PRIx64 "\n", context_amd64->dr1);
+ printf(" dr2 = 0x%" PRIx64 "\n", context_amd64->dr2);
+ printf(" dr3 = 0x%" PRIx64 "\n", context_amd64->dr3);
+ printf(" dr6 = 0x%" PRIx64 "\n", context_amd64->dr6);
+ printf(" dr7 = 0x%" PRIx64 "\n", context_amd64->dr7);
+ printf(" rax = 0x%" PRIx64 "\n", context_amd64->rax);
+ printf(" rcx = 0x%" PRIx64 "\n", context_amd64->rcx);
+ printf(" rdx = 0x%" PRIx64 "\n", context_amd64->rdx);
+ printf(" rbx = 0x%" PRIx64 "\n", context_amd64->rbx);
+ printf(" rsp = 0x%" PRIx64 "\n", context_amd64->rsp);
+ printf(" rbp = 0x%" PRIx64 "\n", context_amd64->rbp);
+ printf(" rsi = 0x%" PRIx64 "\n", context_amd64->rsi);
+ printf(" rdi = 0x%" PRIx64 "\n", context_amd64->rdi);
+ printf(" r8 = 0x%" PRIx64 "\n", context_amd64->r8);
+ printf(" r9 = 0x%" PRIx64 "\n", context_amd64->r9);
+ printf(" r10 = 0x%" PRIx64 "\n", context_amd64->r10);
+ printf(" r11 = 0x%" PRIx64 "\n", context_amd64->r11);
+ printf(" r12 = 0x%" PRIx64 "\n", context_amd64->r12);
+ printf(" r13 = 0x%" PRIx64 "\n", context_amd64->r13);
+ printf(" r14 = 0x%" PRIx64 "\n", context_amd64->r14);
+ printf(" r15 = 0x%" PRIx64 "\n", context_amd64->r15);
+ printf(" rip = 0x%" PRIx64 "\n", context_amd64->rip);
+ // TODO: print xmm, vector, debug registers
+ printf("\n");
+ break;
+ }
+
+ case MD_CONTEXT_SPARC: {
+ const MDRawContextSPARC* context_sparc = GetContextSPARC();
+ printf("MDRawContextSPARC\n");
+ printf(" context_flags = 0x%x\n",
+ context_sparc->context_flags);
+ for (unsigned int g_r_index = 0;
+ g_r_index < MD_CONTEXT_SPARC_GPR_COUNT;
+ ++g_r_index) {
+ printf(" g_r[%2d] = 0x%" PRIx64 "\n",
+ g_r_index, context_sparc->g_r[g_r_index]);
+ }
+ printf(" ccr = 0x%" PRIx64 "\n", context_sparc->ccr);
+ printf(" pc = 0x%" PRIx64 "\n", context_sparc->pc);
+ printf(" npc = 0x%" PRIx64 "\n", context_sparc->npc);
+ printf(" y = 0x%" PRIx64 "\n", context_sparc->y);
+ printf(" asi = 0x%" PRIx64 "\n", context_sparc->asi);
+ printf(" fprs = 0x%" PRIx64 "\n", context_sparc->fprs);
+
+ for (unsigned int fpr_index = 0;
+ fpr_index < MD_FLOATINGSAVEAREA_SPARC_FPR_COUNT;
+ ++fpr_index) {
+ printf(" float_save.regs[%2d] = 0x%" PRIx64 "\n",
+ fpr_index, context_sparc->float_save.regs[fpr_index]);
+ }
+ printf(" float_save.filler = 0x%" PRIx64 "\n",
+ context_sparc->float_save.filler);
+ printf(" float_save.fsr = 0x%" PRIx64 "\n",
+ context_sparc->float_save.fsr);
+ break;
+ }
+
+ case MD_CONTEXT_ARM: {
+ const MDRawContextARM* context_arm = GetContextARM();
+ const char * const names[] = {
+ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
+ "r8", "r9", "r10", "r11", "r12", "sp", "lr", "pc",
+ };
+ printf("MDRawContextARM\n");
+ printf(" context_flags = 0x%x\n",
+ context_arm->context_flags);
+ for (unsigned int ireg_index = 0;
+ ireg_index < MD_CONTEXT_ARM_GPR_COUNT;
+ ++ireg_index) {
+ printf(" %-3s = 0x%x\n",
+ names[ireg_index], context_arm->iregs[ireg_index]);
+ }
+ printf(" cpsr = 0x%x\n", context_arm->cpsr);
+ printf(" float_save.fpscr = 0x%" PRIx64 "\n",
+ context_arm->float_save.fpscr);
+ for (unsigned int fpr_index = 0;
+ fpr_index < MD_FLOATINGSAVEAREA_ARM_FPR_COUNT;
+ ++fpr_index) {
+ printf(" float_save.regs[%2d] = 0x%" PRIx64 "\n",
+ fpr_index, context_arm->float_save.regs[fpr_index]);
+ }
+ for (unsigned int fpe_index = 0;
+ fpe_index < MD_FLOATINGSAVEAREA_ARM_FPEXTRA_COUNT;
+ ++fpe_index) {
+ printf(" float_save.extra[%2d] = 0x%" PRIx32 "\n",
+ fpe_index, context_arm->float_save.extra[fpe_index]);
+ }
+
+ break;
+ }
+
+ case MD_CONTEXT_ARM64: {
+ const MDRawContextARM64* context_arm64 = GetContextARM64();
+ printf("MDRawContextARM64\n");
+ printf(" context_flags = 0x%x\n",
+ context_arm64->context_flags);
+ for (unsigned int ireg_index = 0;
+ ireg_index < MD_CONTEXT_ARM64_GPR_COUNT;
+ ++ireg_index) {
+ printf(" iregs[%2d] = 0x%" PRIx64 "\n",
+ ireg_index, context_arm64->iregs[ireg_index]);
+ }
+ printf(" cpsr = 0x%x\n", context_arm64->cpsr);
+ printf(" float_save.fpsr = 0x%x\n", context_arm64->float_save.fpsr);
+ printf(" float_save.fpcr = 0x%x\n", context_arm64->float_save.fpcr);
+
+ for (unsigned int freg_index = 0;
+ freg_index < MD_FLOATINGSAVEAREA_ARM64_FPR_COUNT;
+ ++freg_index) {
+ uint128_struct fp_value = context_arm64->float_save.regs[freg_index];
+ printf(" float_save.regs[%2d] = 0x%" PRIx64 "%" PRIx64 "\n",
+ freg_index, fp_value.high, fp_value.low);
+ }
+
+ break;
+ }
+
+ case MD_CONTEXT_MIPS:
+ case MD_CONTEXT_MIPS64: {
+ const MDRawContextMIPS* context_mips = GetContextMIPS();
+ printf("MDRawContextMIPS\n");
+ printf(" context_flags = 0x%x\n",
+ context_mips->context_flags);
+ for (int ireg_index = 0;
+ ireg_index < MD_CONTEXT_MIPS_GPR_COUNT;
+ ++ireg_index) {
+ printf(" iregs[%2d] = 0x%" PRIx64 "\n",
+ ireg_index, context_mips->iregs[ireg_index]);
+ }
+ printf(" mdhi = 0x%" PRIx64 "\n",
+ context_mips->mdhi);
+ printf(" mdlo = 0x%" PRIx64 "\n",
+ context_mips->mdhi);
+ for (int dsp_index = 0;
+ dsp_index < MD_CONTEXT_MIPS_DSP_COUNT;
+ ++dsp_index) {
+ printf(" hi[%1d] = 0x%" PRIx32 "\n",
+ dsp_index, context_mips->hi[dsp_index]);
+ printf(" lo[%1d] = 0x%" PRIx32 "\n",
+ dsp_index, context_mips->lo[dsp_index]);
+ }
+ printf(" dsp_control = 0x%" PRIx32 "\n",
+ context_mips->dsp_control);
+ printf(" epc = 0x%" PRIx64 "\n",
+ context_mips->epc);
+ printf(" badvaddr = 0x%" PRIx64 "\n",
+ context_mips->badvaddr);
+ printf(" status = 0x%" PRIx32 "\n",
+ context_mips->status);
+ printf(" cause = 0x%" PRIx32 "\n",
+ context_mips->cause);
+
+ for (int fpr_index = 0;
+ fpr_index < MD_FLOATINGSAVEAREA_MIPS_FPR_COUNT;
+ ++fpr_index) {
+ printf(" float_save.regs[%2d] = 0x%" PRIx64 "\n",
+ fpr_index, context_mips->float_save.regs[fpr_index]);
+ }
+ printf(" float_save.fpcsr = 0x%" PRIx32 "\n",
+ context_mips->float_save.fpcsr);
+ printf(" float_save.fir = 0x%" PRIx32 "\n",
+ context_mips->float_save.fir);
+ break;
+ }
+
+ default: {
+ break;
+ }
+ }
+}
+
+} // namespace google_breakpad
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/dump_object.cc b/toolkit/crashreporter/google-breakpad/src/processor/dump_object.cc
new file mode 100644
index 0000000000..2c82b200b8
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/dump_object.cc
@@ -0,0 +1,39 @@
+// 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.
+
+// dump_object.cc: A base class for all mini/micro dump object.
+
+#include "google_breakpad/processor/dump_object.h"
+
+namespace google_breakpad {
+
+DumpObject::DumpObject() : valid_(false) {
+}
+
+} // namespace google_breakpad
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/exploitability.cc b/toolkit/crashreporter/google-breakpad/src/processor/exploitability.cc
new file mode 100644
index 0000000000..5f05b51052
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/exploitability.cc
@@ -0,0 +1,120 @@
+// 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.
+
+// exploitability_engine.cc: Generic exploitability engine.
+//
+// See exploitable_engine.h for documentation.
+//
+// Author: Cris Neckar
+
+
+#include <cassert>
+
+#include "common/scoped_ptr.h"
+#include "google_breakpad/processor/exploitability.h"
+#include "google_breakpad/processor/minidump.h"
+#include "google_breakpad/processor/process_state.h"
+#include "processor/exploitability_linux.h"
+#include "processor/exploitability_win.h"
+#include "processor/logging.h"
+
+namespace google_breakpad {
+
+Exploitability::Exploitability(Minidump *dump,
+ ProcessState *process_state)
+ : dump_(dump),
+ process_state_(process_state) {}
+
+ExploitabilityRating Exploitability::CheckExploitability() {
+ return CheckPlatformExploitability();
+}
+
+Exploitability *Exploitability::ExploitabilityForPlatform(
+ Minidump *dump,
+ ProcessState *process_state) {
+ return ExploitabilityForPlatform(dump, process_state, false);
+}
+
+Exploitability *Exploitability::ExploitabilityForPlatform(
+ Minidump *dump,
+ ProcessState *process_state,
+ bool enable_objdump) {
+ Exploitability *platform_exploitability = NULL;
+ MinidumpSystemInfo *minidump_system_info = dump->GetSystemInfo();
+ if (!minidump_system_info)
+ return NULL;
+
+ const MDRawSystemInfo *raw_system_info =
+ minidump_system_info->system_info();
+ if (!raw_system_info)
+ return NULL;
+
+ switch (raw_system_info->platform_id) {
+ case MD_OS_WIN32_NT:
+ case MD_OS_WIN32_WINDOWS: {
+ platform_exploitability = new ExploitabilityWin(dump, process_state);
+ break;
+ }
+ case MD_OS_LINUX: {
+ platform_exploitability = new ExploitabilityLinux(dump,
+ process_state,
+ enable_objdump);
+ break;
+ }
+ case MD_OS_MAC_OS_X:
+ case MD_OS_IOS:
+ case MD_OS_UNIX:
+ case MD_OS_SOLARIS:
+ case MD_OS_ANDROID:
+ case MD_OS_PS3:
+ case MD_OS_FUCHSIA:
+ default: {
+ platform_exploitability = NULL;
+ break;
+ }
+ }
+
+ BPLOG_IF(ERROR, !platform_exploitability) <<
+ "No Exploitability module for platform: " <<
+ process_state->system_info()->os;
+ return platform_exploitability;
+}
+
+bool Exploitability::AddressIsAscii(uint64_t address) {
+ for (int i = 0; i < 8; i++) {
+ uint8_t byte = (address >> (8*i)) & 0xff;
+ if ((byte >= ' ' && byte <= '~') || byte == 0)
+ continue;
+ return false;
+ }
+ return true;
+}
+
+} // namespace google_breakpad
+
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/exploitability_linux.cc b/toolkit/crashreporter/google-breakpad/src/processor/exploitability_linux.cc
new file mode 100644
index 0000000000..ccc9f1459c
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/exploitability_linux.cc
@@ -0,0 +1,626 @@
+// 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.
+
+// exploitability_linux.cc: Linux specific exploitability engine.
+//
+// Provides a guess at the exploitability of the crash for the Linux
+// platform given a minidump and process_state.
+//
+// Author: Matthew Riley
+
+#include "processor/exploitability_linux.h"
+
+#ifndef _WIN32
+#include <regex.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <sstream>
+#include <iterator>
+#endif // _WIN32
+
+#include <string.h>
+
+#include "google_breakpad/common/minidump_exception_linux.h"
+#include "google_breakpad/processor/call_stack.h"
+#include "google_breakpad/processor/process_state.h"
+#include "google_breakpad/processor/stack_frame.h"
+#include "processor/logging.h"
+
+namespace {
+
+// Prefixes for memory mapping names.
+constexpr char kHeapPrefix[] = "[heap";
+constexpr char kStackPrefix[] = "[stack";
+
+// This function in libc is called if the program was compiled with
+// -fstack-protector and a function's stack canary changes.
+constexpr char kStackCheckFailureFunction[] = "__stack_chk_fail";
+
+// This function in libc is called if the program was compiled with
+// -D_FORTIFY_SOURCE=2, a function like strcpy() is called, and the runtime
+// can determine that the call would overflow the target buffer.
+constexpr char kBoundsCheckFailureFunction[] = "__chk_fail";
+
+#ifndef _WIN32
+const unsigned int MAX_INSTRUCTION_LEN = 15;
+const unsigned int MAX_OBJDUMP_BUFFER_LEN = 4096;
+#endif // _WIN32
+
+} // namespace
+
+namespace google_breakpad {
+
+ExploitabilityLinux::ExploitabilityLinux(Minidump *dump,
+ ProcessState *process_state)
+ : Exploitability(dump, process_state),
+ enable_objdump_(false) { }
+
+ExploitabilityLinux::ExploitabilityLinux(Minidump *dump,
+ ProcessState *process_state,
+ bool enable_objdump)
+ : Exploitability(dump, process_state),
+ enable_objdump_(enable_objdump) { }
+
+
+ExploitabilityRating ExploitabilityLinux::CheckPlatformExploitability() {
+ // Check the crashing thread for functions suggesting a buffer overflow or
+ // stack smash.
+ if (process_state_->requesting_thread() != -1) {
+ CallStack* crashing_thread =
+ process_state_->threads()->at(process_state_->requesting_thread());
+ const vector<StackFrame*>& crashing_thread_frames =
+ *crashing_thread->frames();
+ for (size_t i = 0; i < crashing_thread_frames.size(); ++i) {
+ if (crashing_thread_frames[i]->function_name ==
+ kStackCheckFailureFunction) {
+ return EXPLOITABILITY_HIGH;
+ }
+
+ if (crashing_thread_frames[i]->function_name ==
+ kBoundsCheckFailureFunction) {
+ return EXPLOITABILITY_HIGH;
+ }
+ }
+ }
+
+ // Getting exception data. (It should exist for all minidumps.)
+ MinidumpException *exception = dump_->GetException();
+ if (exception == NULL) {
+ BPLOG(INFO) << "No exception record.";
+ return EXPLOITABILITY_ERR_PROCESSING;
+ }
+ const MDRawExceptionStream *raw_exception_stream = exception->exception();
+ if (raw_exception_stream == NULL) {
+ BPLOG(INFO) << "No raw exception stream.";
+ return EXPLOITABILITY_ERR_PROCESSING;
+ }
+
+ // Checking for benign exceptions that caused the crash.
+ if (this->BenignCrashTrigger(raw_exception_stream)) {
+ return EXPLOITABILITY_NONE;
+ }
+
+ // Check if the instruction pointer is in a valid instruction region
+ // by finding if it maps to an executable part of memory.
+ uint64_t instruction_ptr = 0;
+ uint64_t stack_ptr = 0;
+
+ const MinidumpContext *context = exception->GetContext();
+ if (context == NULL) {
+ BPLOG(INFO) << "No exception context.";
+ return EXPLOITABILITY_ERR_PROCESSING;
+ }
+
+ // Getting the instruction pointer.
+ if (!context->GetInstructionPointer(&instruction_ptr)) {
+ BPLOG(INFO) << "Failed to retrieve instruction pointer.";
+ return EXPLOITABILITY_ERR_PROCESSING;
+ }
+
+ // Getting the stack pointer.
+ if (!context->GetStackPointer(&stack_ptr)) {
+ BPLOG(INFO) << "Failed to retrieve stack pointer.";
+ return EXPLOITABILITY_ERR_PROCESSING;
+ }
+
+ // Checking for the instruction pointer in a valid instruction region,
+ // a misplaced stack pointer, and an executable stack or heap.
+ if (!this->InstructionPointerInCode(instruction_ptr) ||
+ this->StackPointerOffStack(stack_ptr) ||
+ this->ExecutableStackOrHeap()) {
+ return EXPLOITABILITY_HIGH;
+ }
+
+ // Check for write to read only memory or invalid memory, shelling out
+ // to objdump is enabled.
+ if (enable_objdump_ && this->EndedOnIllegalWrite(instruction_ptr)) {
+ return EXPLOITABILITY_HIGH;
+ }
+
+ // There was no strong evidence suggesting exploitability, but the minidump
+ // does not appear totally benign either.
+ return EXPLOITABILITY_INTERESTING;
+}
+
+bool ExploitabilityLinux::EndedOnIllegalWrite(uint64_t instruction_ptr) {
+#ifdef _WIN32
+ BPLOG(INFO) << "MinGW does not support fork and exec. Terminating method.";
+#else
+ // Get memory region containing instruction pointer.
+ MinidumpMemoryList *memory_list = dump_->GetMemoryList();
+ MinidumpMemoryRegion *memory_region =
+ memory_list ?
+ memory_list->GetMemoryRegionForAddress(instruction_ptr) : NULL;
+ if (!memory_region) {
+ BPLOG(INFO) << "No memory region around instruction pointer.";
+ return false;
+ }
+
+ // Get exception data to find architecture.
+ string architecture = "";
+ MinidumpException *exception = dump_->GetException();
+ // This should never evaluate to true, since this should not be reachable
+ // without checking for exception data earlier.
+ if (!exception) {
+ BPLOG(INFO) << "No exception data.";
+ return false;
+ }
+ const MDRawExceptionStream *raw_exception_stream = exception->exception();
+ const MinidumpContext *context = exception->GetContext();
+ // This should not evaluate to true, for the same reason mentioned above.
+ if (!raw_exception_stream || !context) {
+ BPLOG(INFO) << "No exception or architecture data.";
+ return false;
+ }
+ // Check architecture and set architecture variable to corresponding flag
+ // in objdump.
+ switch (context->GetContextCPU()) {
+ case MD_CONTEXT_X86:
+ architecture = "i386";
+ break;
+ case MD_CONTEXT_AMD64:
+ architecture = "i386:x86-64";
+ break;
+ default:
+ // Unsupported architecture. Note that ARM architectures are not
+ // supported because objdump does not support ARM.
+ return false;
+ break;
+ }
+
+ // Get memory region around instruction pointer and the number of bytes
+ // before and after the instruction pointer in the memory region.
+ const uint8_t *raw_memory = memory_region->GetMemory();
+ const uint64_t base = memory_region->GetBase();
+ if (base > instruction_ptr) {
+ BPLOG(ERROR) << "Memory region base value exceeds instruction pointer.";
+ return false;
+ }
+ const uint64_t offset = instruction_ptr - base;
+ if (memory_region->GetSize() < MAX_INSTRUCTION_LEN + offset) {
+ BPLOG(INFO) << "Not enough bytes left to guarantee complete instruction.";
+ return false;
+ }
+
+ // Convert bytes into objdump output.
+ char objdump_output_buffer[MAX_OBJDUMP_BUFFER_LEN] = {0};
+ DisassembleBytes(architecture,
+ raw_memory + offset,
+ MAX_OBJDUMP_BUFFER_LEN,
+ objdump_output_buffer);
+
+ string line;
+ if (!GetObjdumpInstructionLine(objdump_output_buffer, &line)) {
+ return false;
+ }
+
+ // Convert objdump instruction line into the operation and operands.
+ string instruction = "";
+ string dest = "";
+ string src = "";
+ TokenizeObjdumpInstruction(line, &instruction, &dest, &src);
+
+ // Check if the operation is a write to memory. First, the instruction
+ // must one that can write to memory. Second, the write destination
+ // must be a spot in memory rather than a register. Since there are no
+ // symbols from objdump, the destination will be enclosed by brackets.
+ if (dest.size() > 2 && dest.at(0) == '[' && dest.at(dest.size() - 1) == ']' &&
+ (!instruction.compare("mov") || !instruction.compare("inc") ||
+ !instruction.compare("dec") || !instruction.compare("and") ||
+ !instruction.compare("or") || !instruction.compare("xor") ||
+ !instruction.compare("not") || !instruction.compare("neg") ||
+ !instruction.compare("add") || !instruction.compare("sub") ||
+ !instruction.compare("shl") || !instruction.compare("shr"))) {
+ // Strip away enclosing brackets from the destination address.
+ dest = dest.substr(1, dest.size() - 2);
+ uint64_t write_address = 0;
+ CalculateAddress(dest, *context, &write_address);
+
+ // If the program crashed as a result of a write, the destination of
+ // the write must have been an address that did not permit writing.
+ // However, if the address is under 4k, due to program protections,
+ // the crash does not suggest exploitability for writes with such a
+ // low target address.
+ return write_address > 4096;
+ }
+#endif // _WIN32
+ return false;
+}
+
+#ifndef _WIN32
+bool ExploitabilityLinux::CalculateAddress(const string &address_expression,
+ const DumpContext &context,
+ uint64_t *write_address) {
+ // The destination should be the format reg+a or reg-a, where reg
+ // is a register and a is a hexadecimal constant. Although more complex
+ // expressions can make valid instructions, objdump's disassembly outputs
+ // it in this simpler format.
+ // TODO(liuandrew): Handle more complex formats, should they arise.
+
+ if (!write_address) {
+ BPLOG(ERROR) << "Null parameter.";
+ return false;
+ }
+
+ // Clone parameter into a non-const string.
+ string expression = address_expression;
+
+ // Parse out the constant that is added to the address (if it exists).
+ size_t delim = expression.find('+');
+ bool positive_add_constant = true;
+ // Check if constant is subtracted instead of added.
+ if (delim == string::npos) {
+ positive_add_constant = false;
+ delim = expression.find('-');
+ }
+ uint32_t add_constant = 0;
+ // Save constant and remove it from the expression.
+ if (delim != string::npos) {
+ if (!sscanf(expression.substr(delim + 1).c_str(), "%x", &add_constant)) {
+ BPLOG(ERROR) << "Failed to scan constant.";
+ return false;
+ }
+ expression = expression.substr(0, delim);
+ }
+
+ // Set the the write address to the corresponding register.
+ // TODO(liuandrew): Add support for partial registers, such as
+ // the rax/eax/ax/ah/al chain.
+ switch (context.GetContextCPU()) {
+ case MD_CONTEXT_X86:
+ if (!expression.compare("eax")) {
+ *write_address = context.GetContextX86()->eax;
+ } else if (!expression.compare("ebx")) {
+ *write_address = context.GetContextX86()->ebx;
+ } else if (!expression.compare("ecx")) {
+ *write_address = context.GetContextX86()->ecx;
+ } else if (!expression.compare("edx")) {
+ *write_address = context.GetContextX86()->edx;
+ } else if (!expression.compare("edi")) {
+ *write_address = context.GetContextX86()->edi;
+ } else if (!expression.compare("esi")) {
+ *write_address = context.GetContextX86()->esi;
+ } else if (!expression.compare("ebp")) {
+ *write_address = context.GetContextX86()->ebp;
+ } else if (!expression.compare("esp")) {
+ *write_address = context.GetContextX86()->esp;
+ } else if (!expression.compare("eip")) {
+ *write_address = context.GetContextX86()->eip;
+ } else {
+ BPLOG(ERROR) << "Unsupported register";
+ return false;
+ }
+ break;
+ case MD_CONTEXT_AMD64:
+ if (!expression.compare("rax")) {
+ *write_address = context.GetContextAMD64()->rax;
+ } else if (!expression.compare("rbx")) {
+ *write_address = context.GetContextAMD64()->rbx;
+ } else if (!expression.compare("rcx")) {
+ *write_address = context.GetContextAMD64()->rcx;
+ } else if (!expression.compare("rdx")) {
+ *write_address = context.GetContextAMD64()->rdx;
+ } else if (!expression.compare("rdi")) {
+ *write_address = context.GetContextAMD64()->rdi;
+ } else if (!expression.compare("rsi")) {
+ *write_address = context.GetContextAMD64()->rsi;
+ } else if (!expression.compare("rbp")) {
+ *write_address = context.GetContextAMD64()->rbp;
+ } else if (!expression.compare("rsp")) {
+ *write_address = context.GetContextAMD64()->rsp;
+ } else if (!expression.compare("rip")) {
+ *write_address = context.GetContextAMD64()->rip;
+ } else if (!expression.compare("r8")) {
+ *write_address = context.GetContextAMD64()->r8;
+ } else if (!expression.compare("r9")) {
+ *write_address = context.GetContextAMD64()->r9;
+ } else if (!expression.compare("r10")) {
+ *write_address = context.GetContextAMD64()->r10;
+ } else if (!expression.compare("r11")) {
+ *write_address = context.GetContextAMD64()->r11;
+ } else if (!expression.compare("r12")) {
+ *write_address = context.GetContextAMD64()->r12;
+ } else if (!expression.compare("r13")) {
+ *write_address = context.GetContextAMD64()->r13;
+ } else if (!expression.compare("r14")) {
+ *write_address = context.GetContextAMD64()->r14;
+ } else if (!expression.compare("r15")) {
+ *write_address = context.GetContextAMD64()->r15;
+ } else {
+ BPLOG(ERROR) << "Unsupported register";
+ return false;
+ }
+ break;
+ default:
+ // This should not occur since the same switch condition
+ // should have terminated this method.
+ return false;
+ break;
+ }
+
+ // Add or subtract constant from write address (if applicable).
+ *write_address =
+ positive_add_constant ?
+ *write_address + add_constant : *write_address - add_constant;
+
+ return true;
+}
+
+// static
+bool ExploitabilityLinux::GetObjdumpInstructionLine(
+ const char *objdump_output_buffer,
+ string *instruction_line) {
+ // Put buffer data into stream to output line-by-line.
+ std::stringstream objdump_stream;
+ objdump_stream.str(string(objdump_output_buffer));
+
+ // Pipe each output line into the string until the string contains the first
+ // instruction from objdump. All lines before the "<.data>:" section are
+ // skipped. Loop until the line shows the first instruction or there are no
+ // lines left.
+ bool data_section_seen = false;
+ do {
+ if (!getline(objdump_stream, *instruction_line)) {
+ BPLOG(INFO) << "Objdump instructions not found";
+ return false;
+ }
+ if (instruction_line->find("<.data>:") != string::npos) {
+ data_section_seen = true;
+ }
+ } while (!data_section_seen || instruction_line->find("0:") == string::npos);
+ // This first instruction contains the above substring.
+
+ return true;
+}
+
+bool ExploitabilityLinux::TokenizeObjdumpInstruction(const string &line,
+ string *operation,
+ string *dest,
+ string *src) {
+ if (!operation || !dest || !src) {
+ BPLOG(ERROR) << "Null parameters passed.";
+ return false;
+ }
+
+ // Set all pointer values to empty strings.
+ *operation = "";
+ *dest = "";
+ *src = "";
+
+ // Tokenize the objdump line.
+ vector<string> tokens;
+ std::istringstream line_stream(line);
+ copy(std::istream_iterator<string>(line_stream),
+ std::istream_iterator<string>(),
+ std::back_inserter(tokens));
+
+ // Regex for the data in hex form. Each byte is two hex digits.
+ regex_t regex;
+ regcomp(&regex, "^[[:xdigit:]]{2}$", REG_EXTENDED | REG_NOSUB);
+
+ // Find and set the location of the operator. The operator appears
+ // directly after the chain of bytes that define the instruction. The
+ // operands will be the last token, given that the instruction has operands.
+ // If not, the operator is the last token. The loop skips the first token
+ // because the first token is the instruction number (namely "0:").
+ string operands = "";
+ for (size_t i = 1; i < tokens.size(); i++) {
+ // Check if current token no longer is in byte format.
+ if (regexec(&regex, tokens[i].c_str(), 0, NULL, 0)) {
+ // instruction = tokens[i];
+ *operation = tokens[i];
+ // If the operator is the last token, there are no operands.
+ if (i != tokens.size() - 1) {
+ operands = tokens[tokens.size() - 1];
+ }
+ break;
+ }
+ }
+ regfree(&regex);
+
+ if (operation->empty()) {
+ BPLOG(ERROR) << "Failed to parse out operation from objdump instruction.";
+ return false;
+ }
+
+ // Split operands into source and destination (if applicable).
+ if (!operands.empty()) {
+ size_t delim = operands.find(',');
+ if (delim == string::npos) {
+ *dest = operands;
+ } else {
+ *dest = operands.substr(0, delim);
+ *src = operands.substr(delim + 1);
+ }
+ }
+ return true;
+}
+
+bool ExploitabilityLinux::DisassembleBytes(const string &architecture,
+ const uint8_t *raw_bytes,
+ const unsigned int buffer_len,
+ char *objdump_output_buffer) {
+ if (!raw_bytes || !objdump_output_buffer) {
+ BPLOG(ERROR) << "Bad input parameters.";
+ return false;
+ }
+
+ // Write raw bytes around instruction pointer to a temporary file to
+ // pass as an argument to objdump.
+ char raw_bytes_tmpfile[] = "/tmp/breakpad_mem_region-raw_bytes-XXXXXX";
+ int raw_bytes_fd = mkstemp(raw_bytes_tmpfile);
+ if (raw_bytes_fd < 0) {
+ BPLOG(ERROR) << "Failed to create tempfile.";
+ unlink(raw_bytes_tmpfile);
+ return false;
+ }
+ if (write(raw_bytes_fd, raw_bytes, MAX_INSTRUCTION_LEN)
+ != MAX_INSTRUCTION_LEN) {
+ BPLOG(ERROR) << "Writing of raw bytes failed.";
+ unlink(raw_bytes_tmpfile);
+ return false;
+ }
+
+ char cmd[1024] = {0};
+ snprintf(cmd,
+ 1024,
+ "objdump -D -b binary -M intel -m %s %s",
+ architecture.c_str(),
+ raw_bytes_tmpfile);
+ FILE *objdump_fp = popen(cmd, "r");
+ if (!objdump_fp) {
+ fclose(objdump_fp);
+ unlink(raw_bytes_tmpfile);
+ BPLOG(ERROR) << "Failed to call objdump.";
+ return false;
+ }
+ if (fread(objdump_output_buffer, 1, buffer_len, objdump_fp) <= 0) {
+ fclose(objdump_fp);
+ unlink(raw_bytes_tmpfile);
+ BPLOG(ERROR) << "Failed to read objdump output.";
+ return false;
+ }
+ fclose(objdump_fp);
+ unlink(raw_bytes_tmpfile);
+ return true;
+}
+#endif // _WIN32
+
+bool ExploitabilityLinux::StackPointerOffStack(uint64_t stack_ptr) {
+ MinidumpLinuxMapsList *linux_maps_list = dump_->GetLinuxMapsList();
+ // Inconclusive if there are no mappings available.
+ if (!linux_maps_list) {
+ return false;
+ }
+ const MinidumpLinuxMaps *linux_maps =
+ linux_maps_list->GetLinuxMapsForAddress(stack_ptr);
+ // Checks if the stack pointer maps to a valid mapping and if the mapping
+ // is not the stack. If the mapping has no name, it is inconclusive whether
+ // it is off the stack.
+ return !linux_maps || (linux_maps->GetPathname().compare("") &&
+ linux_maps->GetPathname().compare(
+ 0, strlen(kStackPrefix), kStackPrefix));
+}
+
+bool ExploitabilityLinux::ExecutableStackOrHeap() {
+ MinidumpLinuxMapsList *linux_maps_list = dump_->GetLinuxMapsList();
+ if (linux_maps_list) {
+ for (size_t i = 0; i < linux_maps_list->get_maps_count(); i++) {
+ const MinidumpLinuxMaps *linux_maps =
+ linux_maps_list->GetLinuxMapsAtIndex(i);
+ // Check for executable stack or heap for each mapping.
+ if (linux_maps && (!linux_maps->GetPathname().compare(
+ 0, strlen(kStackPrefix), kStackPrefix) ||
+ !linux_maps->GetPathname().compare(
+ 0, strlen(kHeapPrefix), kHeapPrefix)) &&
+ linux_maps->IsExecutable()) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+bool ExploitabilityLinux::InstructionPointerInCode(uint64_t instruction_ptr) {
+ // Get Linux memory mapping from /proc/self/maps. Checking whether the
+ // region the instruction pointer is in has executable permission can tell
+ // whether it is in a valid code region. If there is no mapping for the
+ // instruction pointer, it is indicative that the instruction pointer is
+ // not within a module, which implies that it is outside a valid area.
+ MinidumpLinuxMapsList *linux_maps_list = dump_->GetLinuxMapsList();
+ const MinidumpLinuxMaps *linux_maps =
+ linux_maps_list ?
+ linux_maps_list->GetLinuxMapsForAddress(instruction_ptr) : NULL;
+ return linux_maps ? linux_maps->IsExecutable() : false;
+}
+
+bool ExploitabilityLinux::BenignCrashTrigger(const MDRawExceptionStream
+ *raw_exception_stream) {
+ // Check the cause of crash.
+ // If the exception of the crash is a benign exception,
+ // it is probably not exploitable.
+ switch (raw_exception_stream->exception_record.exception_code) {
+ case MD_EXCEPTION_CODE_LIN_SIGHUP:
+ case MD_EXCEPTION_CODE_LIN_SIGINT:
+ case MD_EXCEPTION_CODE_LIN_SIGQUIT:
+ case MD_EXCEPTION_CODE_LIN_SIGTRAP:
+ case MD_EXCEPTION_CODE_LIN_SIGABRT:
+ case MD_EXCEPTION_CODE_LIN_SIGFPE:
+ case MD_EXCEPTION_CODE_LIN_SIGKILL:
+ case MD_EXCEPTION_CODE_LIN_SIGUSR1:
+ case MD_EXCEPTION_CODE_LIN_SIGUSR2:
+ case MD_EXCEPTION_CODE_LIN_SIGPIPE:
+ case MD_EXCEPTION_CODE_LIN_SIGALRM:
+ case MD_EXCEPTION_CODE_LIN_SIGTERM:
+ case MD_EXCEPTION_CODE_LIN_SIGCHLD:
+ case MD_EXCEPTION_CODE_LIN_SIGCONT:
+ case MD_EXCEPTION_CODE_LIN_SIGSTOP:
+ case MD_EXCEPTION_CODE_LIN_SIGTSTP:
+ case MD_EXCEPTION_CODE_LIN_SIGTTIN:
+ case MD_EXCEPTION_CODE_LIN_SIGTTOU:
+ case MD_EXCEPTION_CODE_LIN_SIGURG:
+ case MD_EXCEPTION_CODE_LIN_SIGXCPU:
+ case MD_EXCEPTION_CODE_LIN_SIGXFSZ:
+ case MD_EXCEPTION_CODE_LIN_SIGVTALRM:
+ case MD_EXCEPTION_CODE_LIN_SIGPROF:
+ case MD_EXCEPTION_CODE_LIN_SIGWINCH:
+ case MD_EXCEPTION_CODE_LIN_SIGIO:
+ case MD_EXCEPTION_CODE_LIN_SIGPWR:
+ case MD_EXCEPTION_CODE_LIN_SIGSYS:
+ case MD_EXCEPTION_CODE_LIN_DUMP_REQUESTED:
+ return true;
+ break;
+ default:
+ return false;
+ break;
+ }
+}
+
+} // namespace google_breakpad
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/exploitability_linux.h b/toolkit/crashreporter/google-breakpad/src/processor/exploitability_linux.h
new file mode 100644
index 0000000000..e3ff13b6e0
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/exploitability_linux.h
@@ -0,0 +1,129 @@
+// 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.
+
+// exploitability_linux.h: Linux specific exploitability engine.
+//
+// Provides a guess at the exploitability of the crash for the Linux
+// platform given a minidump and process_state.
+//
+// Author: Matthew Riley
+
+#ifndef GOOGLE_BREAKPAD_PROCESSOR_EXPLOITABILITY_LINUX_H_
+#define GOOGLE_BREAKPAD_PROCESSOR_EXPLOITABILITY_LINUX_H_
+
+#include "google_breakpad/common/breakpad_types.h"
+#include "google_breakpad/processor/exploitability.h"
+
+namespace google_breakpad {
+
+class ExploitabilityLinux : public Exploitability {
+ public:
+ ExploitabilityLinux(Minidump *dump,
+ ProcessState *process_state);
+
+ // Parameters are the minidump to analyze, the object representing process
+ // state, and whether to enable objdump disassembly.
+ // Enabling objdump will allow exploitability analysis to call out to
+ // objdump for diassembly. It is used to check the identity of the
+ // instruction that caused the program to crash. If there are any
+ // portability concerns, this should not be enabled.
+ ExploitabilityLinux(Minidump *dump,
+ ProcessState *process_state,
+ bool enable_objdump);
+
+ virtual ExploitabilityRating CheckPlatformExploitability();
+
+ private:
+ friend class ExploitabilityLinuxTest;
+
+ // Takes the address of the instruction pointer and returns
+ // whether the instruction pointer lies in a valid instruction region.
+ bool InstructionPointerInCode(uint64_t instruction_ptr);
+
+ // Checks the exception that triggered the creation of the
+ // minidump and reports whether the exception suggests no exploitability.
+ bool BenignCrashTrigger(const MDRawExceptionStream *raw_exception_stream);
+
+ // This method checks if the crash occurred during a write to read-only or
+ // invalid memory. It does so by checking if the instruction at the
+ // instruction pointer is a write instruction, and if the target of the
+ // instruction is at a spot in memory that prohibits writes.
+ bool EndedOnIllegalWrite(uint64_t instruction_ptr);
+
+#ifndef _WIN32
+ // Disassembles raw bytes via objdump and pipes the output into the provided
+ // buffer, given the desired architecture, the file from which objdump will
+ // read, and the buffer length. The method returns whether the disassembly
+ // was a success, and the caller owns all pointers.
+ static bool DisassembleBytes(const string &architecture,
+ const uint8_t *raw_bytes,
+ const unsigned int MAX_OBJDUMP_BUFFER_LEN,
+ char *objdump_output_buffer);
+
+ // Parses the objdump output given in |objdump_output_buffer| and extracts
+ // the line of the first instruction into |instruction_line|. Returns true
+ // when the instruction line is successfully extracted.
+ static bool GetObjdumpInstructionLine(
+ const char *objdump_output_buffer,
+ string *instruction_line);
+
+ // Tokenizes out the operation and operands from a line of instruction
+ // disassembled by objdump. This method modifies the pointers to match the
+ // tokens of the instruction, and returns if the tokenizing was a success.
+ // The caller owns all pointers.
+ static bool TokenizeObjdumpInstruction(const string &line,
+ string *operation,
+ string *dest,
+ string *src);
+
+ // Calculates the effective address of an expression in the form reg+a or
+ // reg-a, where 'reg' is a register and 'a' is a constant, and writes the
+ // result in the pointer. The method returns whether the calculation was
+ // a success. The caller owns the pointer.
+ static bool CalculateAddress(const string &address_expression,
+ const DumpContext &context,
+ uint64_t *write_address);
+#endif // _WIN32
+
+ // Checks if the stack pointer points to a memory mapping that is not
+ // labelled as the stack.
+ bool StackPointerOffStack(uint64_t stack_ptr);
+
+ // Checks if the stack or heap are marked executable according
+ // to the memory mappings.
+ bool ExecutableStackOrHeap();
+
+ // Whether this exploitability engine is permitted to shell out to objdump
+ // to disassemble raw bytes.
+ bool enable_objdump_;
+};
+
+} // namespace google_breakpad
+
+#endif // GOOGLE_BREAKPAD_PROCESSOR_EXPLOITABILITY_LINUX_H_
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/exploitability_unittest.cc b/toolkit/crashreporter/google-breakpad/src/processor/exploitability_unittest.cc
new file mode 100644
index 0000000000..528ee5f213
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/exploitability_unittest.cc
@@ -0,0 +1,306 @@
+// 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 <stdlib.h>
+#include <unistd.h>
+
+#include <string>
+
+#include "breakpad_googletest_includes.h"
+#include "common/using_std_string.h"
+#include "google_breakpad/processor/basic_source_line_resolver.h"
+#include "google_breakpad/processor/minidump_processor.h"
+#include "google_breakpad/processor/process_state.h"
+#ifndef _WIN32
+#include "processor/exploitability_linux.h"
+#endif // _WIN32
+#include "processor/simple_symbol_supplier.h"
+
+#ifndef _WIN32
+namespace google_breakpad {
+
+class ExploitabilityLinuxTest : public ExploitabilityLinux {
+ public:
+ using ExploitabilityLinux::CalculateAddress;
+ using ExploitabilityLinux::DisassembleBytes;
+ using ExploitabilityLinux::GetObjdumpInstructionLine;
+ using ExploitabilityLinux::TokenizeObjdumpInstruction;
+};
+
+class ExploitabilityLinuxTestMinidumpContext : public MinidumpContext {
+ public:
+ explicit ExploitabilityLinuxTestMinidumpContext(
+ const MDRawContextAMD64& context) : MinidumpContext(NULL) {
+ valid_ = true;
+ SetContextAMD64(new MDRawContextAMD64(context));
+ SetContextFlags(MD_CONTEXT_AMD64);
+ }
+};
+
+} // namespace google_breakpad
+#endif // _WIN32
+
+namespace {
+
+using google_breakpad::BasicSourceLineResolver;
+#ifndef _WIN32
+using google_breakpad::ExploitabilityLinuxTest;
+using google_breakpad::ExploitabilityLinuxTestMinidumpContext;
+#endif // _WIN32
+using google_breakpad::MinidumpProcessor;
+using google_breakpad::ProcessState;
+using google_breakpad::SimpleSymbolSupplier;
+
+string TestDataDir() {
+ return string(getenv("srcdir") ? getenv("srcdir") : ".") +
+ "/src/processor/testdata";
+}
+
+// Find the given dump file in <srcdir>/src/processor/testdata, process it,
+// and get the exploitability rating. Returns EXPLOITABILITY_ERR_PROCESSING
+// if the crash dump can't be processed.
+google_breakpad::ExploitabilityRating
+ExploitabilityFor(const string& filename) {
+ SimpleSymbolSupplier supplier(TestDataDir() + "/symbols");
+ BasicSourceLineResolver resolver;
+ MinidumpProcessor processor(&supplier, &resolver, true);
+ processor.set_enable_objdump(true);
+ ProcessState state;
+
+ string minidump_file = TestDataDir() + "/" + filename;
+
+ if (processor.Process(minidump_file, &state) !=
+ google_breakpad::PROCESS_OK) {
+ return google_breakpad::EXPLOITABILITY_ERR_PROCESSING;
+ }
+
+ return state.exploitability();
+}
+
+TEST(ExploitabilityTest, TestWindowsEngine) {
+ ASSERT_EQ(google_breakpad::EXPLOITABILITY_HIGH,
+ ExploitabilityFor("ascii_read_av.dmp"));
+ ASSERT_EQ(google_breakpad::EXPLOITABILITY_HIGH,
+ ExploitabilityFor("ascii_read_av_block_write.dmp"));
+ ASSERT_EQ(google_breakpad::EXPLOITABILITY_HIGH,
+ ExploitabilityFor("ascii_read_av_clobber_write.dmp"));
+ ASSERT_EQ(google_breakpad::EXPLOITABILITY_HIGH,
+ ExploitabilityFor("ascii_read_av_conditional.dmp"));
+ ASSERT_EQ(google_breakpad::EXPLOITABILITY_HIGH,
+ ExploitabilityFor("ascii_read_av_then_jmp.dmp"));
+ ASSERT_EQ(google_breakpad::EXPLOITABILITY_HIGH,
+ ExploitabilityFor("ascii_read_av_xchg_write.dmp"));
+ ASSERT_EQ(google_breakpad::EXPLOITABILITY_HIGH,
+ ExploitabilityFor("ascii_write_av.dmp"));
+ ASSERT_EQ(google_breakpad::EXPLOITABILITY_HIGH,
+ ExploitabilityFor("ascii_write_av_arg_to_call.dmp"));
+ ASSERT_EQ(google_breakpad::EXPLOITABILITY_NONE,
+ ExploitabilityFor("null_read_av.dmp"));
+ ASSERT_EQ(google_breakpad::EXPLOITABILITY_NONE,
+ ExploitabilityFor("null_write_av.dmp"));
+ ASSERT_EQ(google_breakpad::EXPLOITABILITY_NONE,
+ ExploitabilityFor("stack_exhaustion.dmp"));
+ ASSERT_EQ(google_breakpad::EXPLOITABILITY_HIGH,
+ ExploitabilityFor("exec_av_on_stack.dmp"));
+ ASSERT_EQ(google_breakpad::EXPLOITABILITY_MEDIUM,
+ ExploitabilityFor("write_av_non_null.dmp"));
+ ASSERT_EQ(google_breakpad::EXPLOITABILITY_LOW,
+ ExploitabilityFor("read_av_non_null.dmp"));
+ ASSERT_EQ(google_breakpad::EXPLOITABILITY_LOW,
+ ExploitabilityFor("read_av_clobber_write.dmp"));
+ ASSERT_EQ(google_breakpad::EXPLOITABILITY_LOW,
+ ExploitabilityFor("read_av_conditional.dmp"));
+}
+
+TEST(ExploitabilityTest, TestLinuxEngine) {
+ ASSERT_EQ(google_breakpad::EXPLOITABILITY_INTERESTING,
+ ExploitabilityFor("linux_null_read_av.dmp"));
+ ASSERT_EQ(google_breakpad::EXPLOITABILITY_HIGH,
+ ExploitabilityFor("linux_overflow.dmp"));
+ ASSERT_EQ(google_breakpad::EXPLOITABILITY_HIGH,
+ ExploitabilityFor("linux_stacksmash.dmp"));
+ ASSERT_EQ(google_breakpad::EXPLOITABILITY_NONE,
+ ExploitabilityFor("linux_divide_by_zero.dmp"));
+ ASSERT_EQ(google_breakpad::EXPLOITABILITY_INTERESTING,
+ ExploitabilityFor("linux_null_dereference.dmp"));
+ ASSERT_EQ(google_breakpad::EXPLOITABILITY_HIGH,
+ ExploitabilityFor("linux_jmp_to_0.dmp"));
+ ASSERT_EQ(google_breakpad::EXPLOITABILITY_HIGH,
+ ExploitabilityFor("linux_outside_module.dmp"));
+ ASSERT_EQ(google_breakpad::EXPLOITABILITY_NONE,
+ ExploitabilityFor("linux_raise_sigabrt.dmp"));
+ ASSERT_EQ(google_breakpad::EXPLOITABILITY_INTERESTING,
+ ExploitabilityFor("linux_inside_module_exe_region1.dmp"));
+ ASSERT_EQ(google_breakpad::EXPLOITABILITY_INTERESTING,
+ ExploitabilityFor("linux_inside_module_exe_region2.dmp"));
+ ASSERT_EQ(google_breakpad::EXPLOITABILITY_INTERESTING,
+ ExploitabilityFor("linux_stack_pointer_in_stack.dmp"));
+ ASSERT_EQ(google_breakpad::EXPLOITABILITY_INTERESTING,
+ ExploitabilityFor("linux_stack_pointer_in_stack_alt_name.dmp"));
+ ASSERT_EQ(google_breakpad::EXPLOITABILITY_HIGH,
+ ExploitabilityFor("linux_stack_pointer_in_module.dmp"));
+ ASSERT_EQ(google_breakpad::EXPLOITABILITY_HIGH,
+ ExploitabilityFor("linux_executable_stack.dmp"));
+ ASSERT_EQ(google_breakpad::EXPLOITABILITY_HIGH,
+ ExploitabilityFor("linux_executable_heap.dmp"));
+ ASSERT_EQ(google_breakpad::EXPLOITABILITY_HIGH,
+ ExploitabilityFor("linux_jmp_to_module_not_exe_region.dmp"));
+#ifndef _WIN32
+ ASSERT_EQ(google_breakpad::EXPLOITABILITY_HIGH,
+ ExploitabilityFor("linux_write_to_nonwritable_module.dmp"));
+ ASSERT_EQ(google_breakpad::EXPLOITABILITY_HIGH,
+ ExploitabilityFor("linux_write_to_nonwritable_region_math.dmp"));
+ ASSERT_EQ(google_breakpad::EXPLOITABILITY_HIGH,
+ ExploitabilityFor("linux_write_to_outside_module.dmp"));
+ ASSERT_EQ(google_breakpad::EXPLOITABILITY_HIGH,
+ ExploitabilityFor("linux_write_to_outside_module_via_math.dmp"));
+ ASSERT_EQ(google_breakpad::EXPLOITABILITY_INTERESTING,
+ ExploitabilityFor("linux_write_to_under_4k.dmp"));
+#endif // _WIN32
+}
+
+#ifndef _WIN32
+TEST(ExploitabilityLinuxUtilsTest, DisassembleBytesTest) {
+ ASSERT_FALSE(ExploitabilityLinuxTest::DisassembleBytes("", NULL, 5, NULL));
+ uint8_t bytes[6] = {0xc7, 0x0, 0x5, 0x0, 0x0, 0x0};
+ char buffer[1024] = {0};
+ ASSERT_TRUE(ExploitabilityLinuxTest::DisassembleBytes("i386:x86-64",
+ bytes,
+ 1024,
+ buffer));
+ std::stringstream objdump_stream;
+ objdump_stream.str(string(buffer));
+ string line = "";
+ while (line.find("<.data>") == string::npos)
+ getline(objdump_stream, line);
+ getline(objdump_stream, line);
+ ASSERT_EQ(line, " 0:\tc7 00 05 00 00 00 \tmov DWORD PTR [rax],0x5");
+}
+
+TEST(ExploitabilityLinuxUtilsTest, GetObjdumpInstructionLine) {
+ string disassebly =
+ "\n"
+ "/tmp/breakpad_mem_region-raw_bytes-tMmMo0: file format binary\n"
+ "// Trying to confuse the parser 0:\n"
+ "\n"
+ "Disassembly of section .data:\n"
+ "\n"
+ "0000000000000000 <.data>:\n"
+ " 0:\tc7 00 01 00 00 00 \tmov DWORD PTR [rax],0x1\n"
+ " 6:\t5d \tpop rbp\n"
+ " 7:\tc3 \tret \n"
+ " 8:\t55 \tpush rbp\n"
+ " 9:\t48 89 e5 \tmov rbp,rsp\n"
+ " c:\t53 \tpush rbx\n"
+ " d:\t48 \trex.W\n"
+ " e:\t81 \t.byte 0x81\n";
+ string line;
+ EXPECT_TRUE(ExploitabilityLinuxTest::GetObjdumpInstructionLine(
+ disassebly.c_str(), &line));
+ EXPECT_EQ(" 0:\tc7 00 01 00 00 00 \tmov DWORD PTR [rax],0x1", line);
+
+ // There is no "0:" after "<.data>:". Expected to return false.
+ disassebly =
+ "\n"
+ "/tmp/breakpad_mem_region-raw_bytes-tMmMo0: file format binary\n"
+ "// Trying to confuse the parser 0:\n"
+ "\n"
+ "Disassembly of section .data:\n"
+ "\n"
+ " 0:\tc7 00 01 00 00 00 \tmov DWORD PTR [rax],0x1\n"
+ " 6:\t5d \tpop rbp\n"
+ " 7:\tc3 \tret \n"
+ " 8:\t55 \tpush rbp\n"
+ " 9:\t48 89 e5 \tmov rbp,rsp\n"
+ " d:\t48 \trex.W\n"
+ "0000000000000000 <.data>:\n"
+ " c:\t53 \tpush rbx\n";
+ EXPECT_FALSE(ExploitabilityLinuxTest::GetObjdumpInstructionLine(
+ disassebly.c_str(), &line));
+}
+
+TEST(ExploitabilityLinuxUtilsTest, TokenizeObjdumpInstructionTest) {
+ ASSERT_FALSE(ExploitabilityLinuxTest::TokenizeObjdumpInstruction("",
+ NULL,
+ NULL,
+ NULL));
+ string line = "0: c7 00 05 00 00 00 mov DWORD PTR [rax],0x5";
+ string operation = "";
+ string dest = "";
+ string src = "";
+ ASSERT_TRUE(ExploitabilityLinuxTest::TokenizeObjdumpInstruction(line,
+ &operation,
+ &dest,
+ &src));
+ ASSERT_EQ(operation, "mov");
+ ASSERT_EQ(dest, "[rax]");
+ ASSERT_EQ(src, "0x5");
+ line = "0: c3 ret";
+ ASSERT_TRUE(ExploitabilityLinuxTest::TokenizeObjdumpInstruction(line,
+ &operation,
+ &dest,
+ &src));
+ ASSERT_EQ(operation, "ret");
+ ASSERT_EQ(dest, "");
+ ASSERT_EQ(src, "");
+ line = "0: 5f pop rdi";
+ ASSERT_TRUE(ExploitabilityLinuxTest::TokenizeObjdumpInstruction(line,
+ &operation,
+ &dest,
+ &src));
+ ASSERT_EQ(operation, "pop");
+ ASSERT_EQ(dest, "rdi");
+ ASSERT_EQ(src, "");
+}
+
+TEST(ExploitabilityLinuxUtilsTest, CalculateAddressTest) {
+ MDRawContextAMD64 raw_context;
+ raw_context.rdx = 12345;
+ ExploitabilityLinuxTestMinidumpContext context(raw_context);
+ ASSERT_EQ(context.GetContextAMD64()->rdx, 12345U);
+ ASSERT_FALSE(ExploitabilityLinuxTest::CalculateAddress("", context, NULL));
+ uint64_t write_address = 0;
+ ASSERT_TRUE(ExploitabilityLinuxTest::CalculateAddress("rdx-0x4D2",
+ context,
+ &write_address));
+ ASSERT_EQ(write_address, 11111U);
+ ASSERT_TRUE(ExploitabilityLinuxTest::CalculateAddress("rdx+0x4D2",
+ context,
+ &write_address));
+ ASSERT_EQ(write_address, 13579U);
+ ASSERT_FALSE(ExploitabilityLinuxTest::CalculateAddress("rdx+rax",
+ context,
+ &write_address));
+ ASSERT_FALSE(ExploitabilityLinuxTest::CalculateAddress("0x3482+0x4D2",
+ context,
+ &write_address));
+}
+#endif // _WIN32
+
+} // namespace
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/exploitability_win.cc b/toolkit/crashreporter/google-breakpad/src/processor/exploitability_win.cc
new file mode 100644
index 0000000000..515b9727bf
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/exploitability_win.cc
@@ -0,0 +1,283 @@
+// 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.
+
+// exploitability_win.cc: Windows specific exploitability engine.
+//
+// Provides a guess at the exploitability of the crash for the Windows
+// platform given a minidump and process_state.
+//
+// Author: Cris Neckar
+
+#include <vector>
+
+#include "processor/exploitability_win.h"
+
+#include "common/scoped_ptr.h"
+#include "google_breakpad/common/minidump_exception_win32.h"
+#include "google_breakpad/processor/minidump.h"
+#include "processor/disassembler_x86.h"
+#include "processor/logging.h"
+
+#include "third_party/libdisasm/libdis.h"
+
+namespace google_breakpad {
+
+// The cutoff that we use to judge if and address is likely an offset
+// from various interesting addresses.
+static const uint64_t kProbableNullOffset = 4096;
+static const uint64_t kProbableStackOffset = 8192;
+
+// The various cutoffs for the different ratings.
+static const size_t kHighCutoff = 100;
+static const size_t kMediumCutoff = 80;
+static const size_t kLowCutoff = 50;
+static const size_t kInterestingCutoff = 25;
+
+// Predefined incremental values for conditional weighting.
+static const size_t kTinyBump = 5;
+static const size_t kSmallBump = 20;
+static const size_t kMediumBump = 50;
+static const size_t kLargeBump = 70;
+static const size_t kHugeBump = 90;
+
+// The maximum number of bytes to disassemble past the program counter.
+static const size_t kDisassembleBytesBeyondPC = 2048;
+
+ExploitabilityWin::ExploitabilityWin(Minidump *dump,
+ ProcessState *process_state)
+ : Exploitability(dump, process_state) { }
+
+ExploitabilityRating ExploitabilityWin::CheckPlatformExploitability() {
+ MinidumpException *exception = dump_->GetException();
+ if (!exception) {
+ BPLOG(INFO) << "Minidump does not have exception record.";
+ return EXPLOITABILITY_ERR_PROCESSING;
+ }
+
+ const MDRawExceptionStream *raw_exception = exception->exception();
+ if (!raw_exception) {
+ BPLOG(INFO) << "Could not obtain raw exception info.";
+ return EXPLOITABILITY_ERR_PROCESSING;
+ }
+
+ const MinidumpContext *context = exception->GetContext();
+ if (!context) {
+ BPLOG(INFO) << "Could not obtain exception context.";
+ return EXPLOITABILITY_ERR_PROCESSING;
+ }
+
+ MinidumpMemoryList *memory_list = dump_->GetMemoryList();
+ bool memory_available = true;
+ if (!memory_list) {
+ BPLOG(INFO) << "Minidump memory segments not available.";
+ memory_available = false;
+ }
+ uint64_t address = process_state_->crash_address();
+ uint32_t exception_code = raw_exception->exception_record.exception_code;
+
+ uint32_t exploitability_weight = 0;
+
+ uint64_t stack_ptr = 0;
+ uint64_t instruction_ptr = 0;
+
+ // Getting the instruction pointer.
+ if (!context->GetInstructionPointer(&instruction_ptr)) {
+ return EXPLOITABILITY_ERR_PROCESSING;
+ }
+
+ // Getting the stack pointer.
+ if (!context->GetStackPointer(&stack_ptr)) {
+ return EXPLOITABILITY_ERR_PROCESSING;
+ }
+
+ // Check if we are executing on the stack.
+ if (instruction_ptr <= (stack_ptr + kProbableStackOffset) &&
+ instruction_ptr >= (stack_ptr - kProbableStackOffset))
+ exploitability_weight += kHugeBump;
+
+ switch (exception_code) {
+ // This is almost certainly recursion.
+ case MD_EXCEPTION_CODE_WIN_STACK_OVERFLOW:
+ exploitability_weight += kTinyBump;
+ break;
+
+ // These exceptions tend to be benign and we can generally ignore them.
+ case MD_EXCEPTION_CODE_WIN_INTEGER_DIVIDE_BY_ZERO:
+ case MD_EXCEPTION_CODE_WIN_INTEGER_OVERFLOW:
+ case MD_EXCEPTION_CODE_WIN_FLOAT_DIVIDE_BY_ZERO:
+ case MD_EXCEPTION_CODE_WIN_FLOAT_INEXACT_RESULT:
+ case MD_EXCEPTION_CODE_WIN_FLOAT_OVERFLOW:
+ case MD_EXCEPTION_CODE_WIN_FLOAT_UNDERFLOW:
+ case MD_EXCEPTION_CODE_WIN_IN_PAGE_ERROR:
+ exploitability_weight += kTinyBump;
+ break;
+
+ // These exceptions will typically mean that we have jumped where we
+ // shouldn't.
+ case MD_EXCEPTION_CODE_WIN_ILLEGAL_INSTRUCTION:
+ case MD_EXCEPTION_CODE_WIN_FLOAT_INVALID_OPERATION:
+ case MD_EXCEPTION_CODE_WIN_PRIVILEGED_INSTRUCTION:
+ exploitability_weight += kLargeBump;
+ break;
+
+ // These represent bugs in exception handlers.
+ case MD_EXCEPTION_CODE_WIN_INVALID_DISPOSITION:
+ case MD_EXCEPTION_CODE_WIN_NONCONTINUABLE_EXCEPTION:
+ exploitability_weight += kSmallBump;
+ break;
+
+ case MD_NTSTATUS_WIN_STATUS_HEAP_CORRUPTION:
+ case MD_NTSTATUS_WIN_STATUS_STACK_BUFFER_OVERRUN:
+ exploitability_weight += kHugeBump;
+ break;
+
+ case MD_EXCEPTION_CODE_WIN_GUARD_PAGE_VIOLATION:
+ exploitability_weight += kLargeBump;
+ break;
+
+ case MD_EXCEPTION_CODE_WIN_ACCESS_VIOLATION:
+ bool near_null = (address <= kProbableNullOffset);
+ bool bad_read = false;
+ bool bad_write = false;
+ if (raw_exception->exception_record.number_parameters >= 1) {
+ MDAccessViolationTypeWin av_type =
+ static_cast<MDAccessViolationTypeWin>
+ (raw_exception->exception_record.exception_information[0]);
+ switch (av_type) {
+ case MD_ACCESS_VIOLATION_WIN_READ:
+ bad_read = true;
+ if (near_null)
+ exploitability_weight += kSmallBump;
+ else
+ exploitability_weight += kMediumBump;
+ break;
+ case MD_ACCESS_VIOLATION_WIN_WRITE:
+ bad_write = true;
+ if (near_null)
+ exploitability_weight += kSmallBump;
+ else
+ exploitability_weight += kHugeBump;
+ break;
+ case MD_ACCESS_VIOLATION_WIN_EXEC:
+ if (near_null)
+ exploitability_weight += kSmallBump;
+ else
+ exploitability_weight += kHugeBump;
+ break;
+ default:
+ BPLOG(INFO) << "Unrecognized access violation type.";
+ return EXPLOITABILITY_ERR_PROCESSING;
+ break;
+ }
+ MinidumpMemoryRegion *instruction_region = 0;
+ if (memory_available) {
+ instruction_region =
+ memory_list->GetMemoryRegionForAddress(instruction_ptr);
+ }
+ if (!near_null && instruction_region &&
+ context->GetContextCPU() == MD_CONTEXT_X86 &&
+ (bad_read || bad_write)) {
+ // Perform checks related to memory around instruction pointer.
+ uint32_t memory_offset =
+ instruction_ptr - instruction_region->GetBase();
+ uint32_t available_memory =
+ instruction_region->GetSize() - memory_offset;
+ available_memory = available_memory > kDisassembleBytesBeyondPC ?
+ kDisassembleBytesBeyondPC : available_memory;
+ if (available_memory) {
+ const uint8_t *raw_memory =
+ instruction_region->GetMemory() + memory_offset;
+ DisassemblerX86 disassembler(raw_memory,
+ available_memory,
+ instruction_ptr);
+ disassembler.NextInstruction();
+ if (bad_read)
+ disassembler.setBadRead();
+ else
+ disassembler.setBadWrite();
+ if (disassembler.currentInstructionValid()) {
+ // Check if the faulting instruction falls into one of
+ // several interesting groups.
+ switch (disassembler.currentInstructionGroup()) {
+ case libdis::insn_controlflow:
+ exploitability_weight += kLargeBump;
+ break;
+ case libdis::insn_string:
+ exploitability_weight += kHugeBump;
+ break;
+ default:
+ break;
+ }
+ // Loop the disassembler through the code and check if it
+ // IDed any interesting conditions in the near future.
+ // Multiple flags may be set so treat each equally.
+ while (disassembler.NextInstruction() &&
+ disassembler.currentInstructionValid() &&
+ !disassembler.endOfBlock())
+ continue;
+ if (disassembler.flags() & DISX86_BAD_BRANCH_TARGET)
+ exploitability_weight += kLargeBump;
+ if (disassembler.flags() & DISX86_BAD_ARGUMENT_PASSED)
+ exploitability_weight += kTinyBump;
+ if (disassembler.flags() & DISX86_BAD_WRITE)
+ exploitability_weight += kMediumBump;
+ if (disassembler.flags() & DISX86_BAD_BLOCK_WRITE)
+ exploitability_weight += kMediumBump;
+ if (disassembler.flags() & DISX86_BAD_READ)
+ exploitability_weight += kTinyBump;
+ if (disassembler.flags() & DISX86_BAD_BLOCK_READ)
+ exploitability_weight += kTinyBump;
+ if (disassembler.flags() & DISX86_BAD_COMPARISON)
+ exploitability_weight += kTinyBump;
+ }
+ }
+ }
+ if (!near_null && AddressIsAscii(address))
+ exploitability_weight += kMediumBump;
+ } else {
+ BPLOG(INFO) << "Access violation type parameter missing.";
+ return EXPLOITABILITY_ERR_PROCESSING;
+ }
+ }
+
+ // Based on the calculated weight we return a simplified classification.
+ BPLOG(INFO) << "Calculated exploitability weight: " << exploitability_weight;
+ if (exploitability_weight >= kHighCutoff)
+ return EXPLOITABILITY_HIGH;
+ if (exploitability_weight >= kMediumCutoff)
+ return EXPLOITABLITY_MEDIUM;
+ if (exploitability_weight >= kLowCutoff)
+ return EXPLOITABILITY_LOW;
+ if (exploitability_weight >= kInterestingCutoff)
+ return EXPLOITABILITY_INTERESTING;
+
+ return EXPLOITABILITY_NONE;
+}
+
+} // namespace google_breakpad
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/exploitability_win.h b/toolkit/crashreporter/google-breakpad/src/processor/exploitability_win.h
new file mode 100644
index 0000000000..4e08aef030
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/exploitability_win.h
@@ -0,0 +1,55 @@
+// 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.
+
+// exploitability_win.h: Windows specific exploitability engine.
+//
+// Provides a guess at the exploitability of the crash for the Windows
+// platform given a minidump and process_state.
+//
+// Author: Cris Neckar
+
+#ifndef GOOGLE_BREAKPAD_PROCESSOR_EXPLOITABILITY_WIN_H_
+#define GOOGLE_BREAKPAD_PROCESSOR_EXPLOITABILITY_WIN_H_
+
+#include "google_breakpad/common/breakpad_types.h"
+#include "google_breakpad/processor/exploitability.h"
+
+namespace google_breakpad {
+
+class ExploitabilityWin : public Exploitability {
+ public:
+ ExploitabilityWin(Minidump *dump,
+ ProcessState *process_state);
+
+ virtual ExploitabilityRating CheckPlatformExploitability();
+};
+
+} // namespace google_breakpad
+
+#endif // GOOGLE_BREAKPAD_PROCESSOR_EXPLOITABILITY_WIN_H_
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/fast_source_line_resolver.cc b/toolkit/crashreporter/google-breakpad/src/processor/fast_source_line_resolver.cc
new file mode 100644
index 0000000000..4a3d000714
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/fast_source_line_resolver.cc
@@ -0,0 +1,275 @@
+// 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.
+//
+// fast_source_line_resolver.cc: FastSourceLineResolver is a concrete class that
+// implements SourceLineResolverInterface. Both FastSourceLineResolver and
+// BasicSourceLineResolver inherit from SourceLineResolverBase class to reduce
+// code redundancy.
+//
+// See fast_source_line_resolver.h and fast_source_line_resolver_types.h
+// for more documentation.
+//
+// Author: Siyang Xie (lambxsy@google.com)
+
+#include "google_breakpad/processor/fast_source_line_resolver.h"
+#include "processor/fast_source_line_resolver_types.h"
+
+#include <map>
+#include <string>
+#include <utility>
+
+#include "common/scoped_ptr.h"
+#include "common/using_std_string.h"
+#include "processor/module_factory.h"
+#include "processor/simple_serializer-inl.h"
+
+using std::map;
+using std::make_pair;
+
+namespace google_breakpad {
+
+FastSourceLineResolver::FastSourceLineResolver()
+ : SourceLineResolverBase(new FastModuleFactory) { }
+
+bool FastSourceLineResolver::ShouldDeleteMemoryBufferAfterLoadModule() {
+ return false;
+}
+
+void FastSourceLineResolver::Module::LookupAddress(StackFrame *frame) const {
+ MemAddr address = frame->instruction - frame->module->base_address();
+
+ // First, look for a FUNC record that covers address. Use
+ // RetrieveNearestRange instead of RetrieveRange so that, if there
+ // is no such function, we can use the next function to bound the
+ // extent of the PUBLIC symbol we find, below. This does mean we
+ // need to check that address indeed falls within the function we
+ // find; do the range comparison in an overflow-friendly way.
+ scoped_ptr<Function> func(new Function);
+ const Function* func_ptr = 0;
+ scoped_ptr<PublicSymbol> public_symbol(new PublicSymbol);
+ const PublicSymbol* public_symbol_ptr = 0;
+ MemAddr function_base;
+ MemAddr function_size;
+ MemAddr public_address;
+
+ if (functions_.RetrieveNearestRange(address, func_ptr,
+ &function_base, &function_size) &&
+ address >= function_base && address - function_base < function_size) {
+ func.get()->CopyFrom(func_ptr);
+ frame->function_name = func->name;
+ frame->function_base = frame->module->base_address() + function_base;
+
+ scoped_ptr<Line> line(new Line);
+ const Line* line_ptr = 0;
+ MemAddr line_base;
+ if (func->lines.RetrieveRange(address, line_ptr, &line_base, NULL)) {
+ line.get()->CopyFrom(line_ptr);
+ FileMap::iterator it = files_.find(line->source_file_id);
+ if (it != files_.end()) {
+ frame->source_file_name =
+ files_.find(line->source_file_id).GetValuePtr();
+ }
+ frame->source_line = line->line;
+ frame->source_line_base = frame->module->base_address() + line_base;
+ }
+ } else if (public_symbols_.Retrieve(address,
+ public_symbol_ptr, &public_address) &&
+ (!func_ptr || public_address > function_base)) {
+ public_symbol.get()->CopyFrom(public_symbol_ptr);
+ frame->function_name = public_symbol->name;
+ frame->function_base = frame->module->base_address() + public_address;
+ }
+}
+
+// WFI: WindowsFrameInfo.
+// Returns a WFI object reading from a raw memory chunk of data
+WindowsFrameInfo FastSourceLineResolver::CopyWFI(const char *raw) {
+ const WindowsFrameInfo::StackInfoTypes type =
+ static_cast<const WindowsFrameInfo::StackInfoTypes>(
+ *reinterpret_cast<const int32_t*>(raw));
+
+ // The first 8 bytes of int data are unused.
+ // They correspond to "StackInfoTypes type_;" and "int valid;"
+ // data member of WFI.
+ const uint32_t *para_uint32 = reinterpret_cast<const uint32_t*>(
+ raw + 2 * sizeof(int32_t));
+
+ uint32_t prolog_size = para_uint32[0];;
+ uint32_t epilog_size = para_uint32[1];
+ uint32_t parameter_size = para_uint32[2];
+ uint32_t saved_register_size = para_uint32[3];
+ uint32_t local_size = para_uint32[4];
+ uint32_t max_stack_size = para_uint32[5];
+ const char *boolean = reinterpret_cast<const char*>(para_uint32 + 6);
+ bool allocates_base_pointer = (*boolean != 0);
+ string program_string = boolean + 1;
+
+ return WindowsFrameInfo(type,
+ prolog_size,
+ epilog_size,
+ parameter_size,
+ saved_register_size,
+ local_size,
+ max_stack_size,
+ allocates_base_pointer,
+ program_string);
+}
+
+// Loads a map from the given buffer in char* type.
+// Does NOT take ownership of mem_buffer.
+// In addition, treat mem_buffer as const char*.
+bool FastSourceLineResolver::Module::LoadMapFromMemory(
+ char *memory_buffer,
+ size_t memory_buffer_size) {
+ if (!memory_buffer) return false;
+
+ // Read the "is_corrupt" flag.
+ const char *mem_buffer = memory_buffer;
+ mem_buffer = SimpleSerializer<bool>::Read(mem_buffer, &is_corrupt_);
+
+ const uint32_t *map_sizes = reinterpret_cast<const uint32_t*>(mem_buffer);
+
+ unsigned int header_size = kNumberMaps_ * sizeof(unsigned int);
+
+ // offsets[]: an array of offset addresses (with respect to mem_buffer),
+ // for each "Static***Map" component of Module.
+ // "Static***Map": static version of std::map or map wrapper, i.e., StaticMap,
+ // StaticAddressMap, StaticContainedRangeMap, and StaticRangeMap.
+ unsigned int offsets[kNumberMaps_];
+ offsets[0] = header_size;
+ for (int i = 1; i < kNumberMaps_; ++i) {
+ offsets[i] = offsets[i - 1] + map_sizes[i - 1];
+ }
+
+ // Use pointers to construct Static*Map data members in Module:
+ int map_id = 0;
+ files_ = StaticMap<int, char>(mem_buffer + offsets[map_id++]);
+ functions_ =
+ StaticRangeMap<MemAddr, Function>(mem_buffer + offsets[map_id++]);
+ public_symbols_ =
+ StaticAddressMap<MemAddr, PublicSymbol>(mem_buffer + offsets[map_id++]);
+ for (int i = 0; i < WindowsFrameInfo::STACK_INFO_LAST; ++i)
+ windows_frame_info_[i] =
+ StaticContainedRangeMap<MemAddr, char>(mem_buffer + offsets[map_id++]);
+
+ cfi_initial_rules_ =
+ StaticRangeMap<MemAddr, char>(mem_buffer + offsets[map_id++]);
+ cfi_delta_rules_ = StaticMap<MemAddr, char>(mem_buffer + offsets[map_id++]);
+
+ return true;
+}
+
+WindowsFrameInfo *FastSourceLineResolver::Module::FindWindowsFrameInfo(
+ const StackFrame *frame) const {
+ MemAddr address = frame->instruction - frame->module->base_address();
+ scoped_ptr<WindowsFrameInfo> result(new WindowsFrameInfo());
+
+ // We only know about WindowsFrameInfo::STACK_INFO_FRAME_DATA and
+ // WindowsFrameInfo::STACK_INFO_FPO. Prefer them in this order.
+ // WindowsFrameInfo::STACK_INFO_FRAME_DATA is the newer type that
+ // includes its own program string.
+ // WindowsFrameInfo::STACK_INFO_FPO is the older type
+ // corresponding to the FPO_DATA struct. See stackwalker_x86.cc.
+ const char* frame_info_ptr;
+ if ((windows_frame_info_[WindowsFrameInfo::STACK_INFO_FRAME_DATA]
+ .RetrieveRange(address, frame_info_ptr))
+ || (windows_frame_info_[WindowsFrameInfo::STACK_INFO_FPO]
+ .RetrieveRange(address, frame_info_ptr))) {
+ result->CopyFrom(CopyWFI(frame_info_ptr));
+ return result.release();
+ }
+
+ // Even without a relevant STACK line, many functions contain
+ // information about how much space their parameters consume on the
+ // stack. Use RetrieveNearestRange instead of RetrieveRange, so that
+ // we can use the function to bound the extent of the PUBLIC symbol,
+ // below. However, this does mean we need to check that ADDRESS
+ // falls within the retrieved function's range; do the range
+ // comparison in an overflow-friendly way.
+ scoped_ptr<Function> function(new Function);
+ const Function* function_ptr = 0;
+ MemAddr function_base, function_size;
+ if (functions_.RetrieveNearestRange(address, function_ptr,
+ &function_base, &function_size) &&
+ address >= function_base && address - function_base < function_size) {
+ function.get()->CopyFrom(function_ptr);
+ result->parameter_size = function->parameter_size;
+ result->valid |= WindowsFrameInfo::VALID_PARAMETER_SIZE;
+ return result.release();
+ }
+
+ // PUBLIC symbols might have a parameter size. Use the function we
+ // found above to limit the range the public symbol covers.
+ scoped_ptr<PublicSymbol> public_symbol(new PublicSymbol);
+ const PublicSymbol* public_symbol_ptr = 0;
+ MemAddr public_address;
+ if (public_symbols_.Retrieve(address, public_symbol_ptr, &public_address) &&
+ (!function_ptr || public_address > function_base)) {
+ public_symbol.get()->CopyFrom(public_symbol_ptr);
+ result->parameter_size = public_symbol->parameter_size;
+ }
+
+ return NULL;
+}
+
+CFIFrameInfo *FastSourceLineResolver::Module::FindCFIFrameInfo(
+ const StackFrame *frame) const {
+ MemAddr address = frame->instruction - frame->module->base_address();
+ MemAddr initial_base, initial_size;
+ const char* initial_rules = NULL;
+
+ // Find the initial rule whose range covers this address. That
+ // provides an initial set of register recovery rules. Then, walk
+ // forward from the initial rule's starting address to frame's
+ // instruction address, applying delta rules.
+ if (!cfi_initial_rules_.RetrieveRange(address, initial_rules,
+ &initial_base, &initial_size)) {
+ return NULL;
+ }
+
+ // Create a frame info structure, and populate it with the rules from
+ // the STACK CFI INIT record.
+ scoped_ptr<CFIFrameInfo> rules(new CFIFrameInfo());
+ if (!ParseCFIRuleSet(initial_rules, rules.get()))
+ return NULL;
+
+ // Find the first delta rule that falls within the initial rule's range.
+ StaticMap<MemAddr, char>::iterator delta =
+ cfi_delta_rules_.lower_bound(initial_base);
+
+ // Apply delta rules up to and including the frame's address.
+ while (delta != cfi_delta_rules_.end() && delta.GetKey() <= address) {
+ ParseCFIRuleSet(delta.GetValuePtr(), rules.get());
+ delta++;
+ }
+
+ return rules.release();
+}
+
+} // namespace google_breakpad
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/fast_source_line_resolver_types.h b/toolkit/crashreporter/google-breakpad/src/processor/fast_source_line_resolver_types.h
new file mode 100644
index 0000000000..2c010470f5
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/fast_source_line_resolver_types.h
@@ -0,0 +1,185 @@
+// 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.
+//
+// fast_source_line_resolver_types.h: definition of nested classes/structs in
+// FastSourceLineResolver. It moves the definitions out of
+// fast_source_line_resolver.cc, so that other classes could have access
+// to these private nested types without including fast_source_line_resolver.cc
+//
+// Author: lambxsy@google.com (Siyang Xie)
+
+#ifndef PROCESSOR_FAST_SOURCE_LINE_RESOLVER_TYPES_H__
+#define PROCESSOR_FAST_SOURCE_LINE_RESOLVER_TYPES_H__
+
+#include "google_breakpad/processor/fast_source_line_resolver.h"
+#include "processor/source_line_resolver_base_types.h"
+
+#include <map>
+#include <string>
+
+#include "google_breakpad/processor/stack_frame.h"
+#include "processor/cfi_frame_info.h"
+#include "processor/static_address_map-inl.h"
+#include "processor/static_contained_range_map-inl.h"
+#include "processor/static_map.h"
+#include "processor/static_range_map-inl.h"
+#include "processor/windows_frame_info.h"
+
+namespace google_breakpad {
+
+struct FastSourceLineResolver::Line : public SourceLineResolverBase::Line {
+ void CopyFrom(const Line *line_ptr) {
+ const char *raw = reinterpret_cast<const char*>(line_ptr);
+ CopyFrom(raw);
+ }
+
+ // De-serialize the memory data of a Line.
+ void CopyFrom(const char *raw) {
+ address = *(reinterpret_cast<const MemAddr*>(raw));
+ size = *(reinterpret_cast<const MemAddr*>(raw + sizeof(address)));
+ source_file_id = *(reinterpret_cast<const int32_t *>(
+ raw + 2 * sizeof(address)));
+ line = *(reinterpret_cast<const int32_t*>(
+ raw + 2 * sizeof(address) + sizeof(source_file_id)));
+ }
+};
+
+struct FastSourceLineResolver::Function :
+public SourceLineResolverBase::Function {
+ void CopyFrom(const Function *func_ptr) {
+ const char *raw = reinterpret_cast<const char*>(func_ptr);
+ CopyFrom(raw);
+ }
+
+ // De-serialize the memory data of a Function.
+ void CopyFrom(const char *raw) {
+ size_t name_size = strlen(raw) + 1;
+ name = raw;
+ address = *(reinterpret_cast<const MemAddr*>(raw + name_size));
+ size = *(reinterpret_cast<const MemAddr*>(
+ raw + name_size + sizeof(MemAddr)));
+ parameter_size = *(reinterpret_cast<const int32_t*>(
+ raw + name_size + 2 * sizeof(MemAddr)));
+ lines = StaticRangeMap<MemAddr, Line>(
+ raw + name_size + 2 * sizeof(MemAddr) + sizeof(int32_t));
+ }
+
+ StaticRangeMap<MemAddr, Line> lines;
+};
+
+struct FastSourceLineResolver::PublicSymbol :
+public SourceLineResolverBase::PublicSymbol {
+ void CopyFrom(const PublicSymbol *public_symbol_ptr) {
+ const char *raw = reinterpret_cast<const char*>(public_symbol_ptr);
+ CopyFrom(raw);
+ }
+
+ // De-serialize the memory data of a PublicSymbol.
+ void CopyFrom(const char *raw) {
+ size_t name_size = strlen(raw) + 1;
+ name = raw;
+ address = *(reinterpret_cast<const MemAddr*>(raw + name_size));
+ parameter_size = *(reinterpret_cast<const int32_t*>(
+ raw + name_size + sizeof(MemAddr)));
+ }
+};
+
+class FastSourceLineResolver::Module: public SourceLineResolverBase::Module {
+ public:
+ explicit Module(const string &name) : name_(name), is_corrupt_(false) { }
+ virtual ~Module() { }
+
+ // Looks up the given relative address, and fills the StackFrame struct
+ // with the result.
+ virtual void LookupAddress(StackFrame *frame) const;
+
+ // Loads a map from the given buffer in char* type.
+ virtual bool LoadMapFromMemory(char *memory_buffer,
+ size_t memory_buffer_size);
+
+ // Tells whether the loaded symbol data is corrupt. Return value is
+ // undefined, if the symbol data hasn't been loaded yet.
+ virtual bool IsCorrupt() const { return is_corrupt_; }
+
+ // If Windows stack walking information is available covering ADDRESS,
+ // return a WindowsFrameInfo structure describing it. If the information
+ // is not available, returns NULL. A NULL return value does not indicate
+ // an error. The caller takes ownership of any returned WindowsFrameInfo
+ // object.
+ virtual WindowsFrameInfo *FindWindowsFrameInfo(const StackFrame *frame) const;
+
+ // If CFI stack walking information is available covering ADDRESS,
+ // return a CFIFrameInfo structure describing it. If the information
+ // is not available, return NULL. The caller takes ownership of any
+ // returned CFIFrameInfo object.
+ virtual CFIFrameInfo *FindCFIFrameInfo(const StackFrame *frame) const;
+
+ // Number of serialized map components of Module.
+ static const int kNumberMaps_ = 5 + WindowsFrameInfo::STACK_INFO_LAST;
+
+ private:
+ friend class FastSourceLineResolver;
+ friend class ModuleComparer;
+ typedef StaticMap<int, char> FileMap;
+
+ string name_;
+ StaticMap<int, char> files_;
+ StaticRangeMap<MemAddr, Function> functions_;
+ StaticAddressMap<MemAddr, PublicSymbol> public_symbols_;
+ bool is_corrupt_;
+
+ // Each element in the array is a ContainedRangeMap for a type
+ // listed in WindowsFrameInfoTypes. These are split by type because
+ // there may be overlaps between maps of different types, but some
+ // information is only available as certain types.
+ StaticContainedRangeMap<MemAddr, char>
+ windows_frame_info_[WindowsFrameInfo::STACK_INFO_LAST];
+
+ // DWARF CFI stack walking data. The Module stores the initial rule sets
+ // and rule deltas as strings, just as they appear in the symbol file:
+ // although the file may contain hundreds of thousands of STACK CFI
+ // records, walking a stack will only ever use a few of them, so it's
+ // best to delay parsing a record until it's actually needed.
+ //
+ // STACK CFI INIT records: for each range, an initial set of register
+ // recovery rules. The RangeMap's itself gives the starting and ending
+ // addresses.
+ StaticRangeMap<MemAddr, char> cfi_initial_rules_;
+
+ // STACK CFI records: at a given address, the changes to the register
+ // recovery rules that take effect at that address. The map key is the
+ // starting address; the ending address is the key of the next entry in
+ // this map, or the end of the range as given by the cfi_initial_rules_
+ // entry (which FindCFIFrameInfo looks up first).
+ StaticMap<MemAddr, char> cfi_delta_rules_;
+};
+
+} // namespace google_breakpad
+
+#endif // PROCESSOR_FAST_SOURCE_LINE_RESOLVER_TYPES_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/fast_source_line_resolver_unittest.cc b/toolkit/crashreporter/google-breakpad/src/processor/fast_source_line_resolver_unittest.cc
new file mode 100644
index 0000000000..87b13c522e
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/fast_source_line_resolver_unittest.cc
@@ -0,0 +1,492 @@
+// 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.
+//
+// fast_source_line_resolver_unittest.cc: Unit tests for FastSourceLineResolver.
+// Two different approaches for testing fast source line resolver:
+// First, use the same unit test data for basic source line resolver.
+// Second, read data from symbol files, load them as basic modules, and then
+// serialize them and load the serialized data as fast modules. Then compare
+// modules to assure the fast module contains exactly the same data as
+// basic module.
+//
+// Author: Siyang Xie (lambxsy@google.com)
+
+#include <assert.h>
+#include <stdio.h>
+
+#include <sstream>
+#include <string>
+
+#include "breakpad_googletest_includes.h"
+#include "common/using_std_string.h"
+#include "google_breakpad/processor/code_module.h"
+#include "google_breakpad/processor/stack_frame.h"
+#include "google_breakpad/processor/memory_region.h"
+#include "processor/logging.h"
+#include "processor/module_serializer.h"
+#include "processor/module_comparer.h"
+
+namespace {
+
+using google_breakpad::SourceLineResolverBase;
+using google_breakpad::BasicSourceLineResolver;
+using google_breakpad::FastSourceLineResolver;
+using google_breakpad::ModuleSerializer;
+using google_breakpad::ModuleComparer;
+using google_breakpad::CFIFrameInfo;
+using google_breakpad::CodeModule;
+using google_breakpad::MemoryRegion;
+using google_breakpad::StackFrame;
+using google_breakpad::WindowsFrameInfo;
+using google_breakpad::linked_ptr;
+using google_breakpad::scoped_ptr;
+
+class TestCodeModule : public CodeModule {
+ public:
+ explicit TestCodeModule(string code_file) : code_file_(code_file) {}
+ virtual ~TestCodeModule() {}
+
+ virtual uint64_t base_address() const { return 0; }
+ virtual uint64_t size() const { return 0xb000; }
+ virtual string code_file() const { return code_file_; }
+ virtual string code_identifier() const { return ""; }
+ virtual string debug_file() const { return ""; }
+ virtual string debug_identifier() const { return ""; }
+ virtual string version() const { return ""; }
+ virtual CodeModule* Copy() const {
+ return new TestCodeModule(code_file_);
+ }
+ virtual bool is_unloaded() const { return false; }
+ virtual uint64_t shrink_down_delta() const { return 0; }
+ virtual void SetShrinkDownDelta(uint64_t shrink_down_delta) {}
+
+ private:
+ string code_file_;
+};
+
+// A mock memory region object, for use by the STACK CFI tests.
+class MockMemoryRegion: public MemoryRegion {
+ uint64_t GetBase() const { return 0x10000; }
+ uint32_t GetSize() const { return 0x01000; }
+ bool GetMemoryAtAddress(uint64_t address, uint8_t *value) const {
+ *value = address & 0xff;
+ return true;
+ }
+ bool GetMemoryAtAddress(uint64_t address, uint16_t *value) const {
+ *value = address & 0xffff;
+ return true;
+ }
+ bool GetMemoryAtAddress(uint64_t address, uint32_t *value) const {
+ switch (address) {
+ case 0x10008: *value = 0x98ecadc3; break; // saved %ebx
+ case 0x1000c: *value = 0x878f7524; break; // saved %esi
+ case 0x10010: *value = 0x6312f9a5; break; // saved %edi
+ case 0x10014: *value = 0x10038; break; // caller's %ebp
+ case 0x10018: *value = 0xf6438648; break; // return address
+ default: *value = 0xdeadbeef; break; // junk
+ }
+ return true;
+ }
+ bool GetMemoryAtAddress(uint64_t address, uint64_t *value) const {
+ *value = address;
+ return true;
+ }
+ void Print() const {
+ assert(false);
+ }
+};
+
+// Verify that, for every association in ACTUAL, EXPECTED has the same
+// association. (That is, ACTUAL's associations should be a subset of
+// EXPECTED's.) Also verify that ACTUAL has associations for ".ra" and
+// ".cfa".
+static bool VerifyRegisters(
+ const char *file, int line,
+ const CFIFrameInfo::RegisterValueMap<uint32_t> &expected,
+ const CFIFrameInfo::RegisterValueMap<uint32_t> &actual) {
+ CFIFrameInfo::RegisterValueMap<uint32_t>::const_iterator a;
+ a = actual.find(".cfa");
+ if (a == actual.end())
+ return false;
+ a = actual.find(".ra");
+ if (a == actual.end())
+ return false;
+ for (a = actual.begin(); a != actual.end(); a++) {
+ CFIFrameInfo::RegisterValueMap<uint32_t>::const_iterator e =
+ expected.find(a->first);
+ if (e == expected.end()) {
+ fprintf(stderr, "%s:%d: unexpected register '%s' recovered, value 0x%x\n",
+ file, line, a->first.c_str(), a->second);
+ return false;
+ }
+ if (e->second != a->second) {
+ fprintf(stderr,
+ "%s:%d: register '%s' recovered value was 0x%x, expected 0x%x\n",
+ file, line, a->first.c_str(), a->second, e->second);
+ return false;
+ }
+ // Don't complain if this doesn't recover all registers. Although
+ // the DWARF spec says that unmentioned registers are undefined,
+ // GCC uses omission to mean that they are unchanged.
+ }
+ return true;
+}
+
+static bool VerifyEmpty(const StackFrame &frame) {
+ if (frame.function_name.empty() &&
+ frame.source_file_name.empty() &&
+ frame.source_line == 0)
+ return true;
+ return false;
+}
+
+static void ClearSourceLineInfo(StackFrame *frame) {
+ frame->function_name.clear();
+ frame->module = NULL;
+ frame->source_file_name.clear();
+ frame->source_line = 0;
+}
+
+class TestFastSourceLineResolver : public ::testing::Test {
+ public:
+ void SetUp() {
+ testdata_dir = string(getenv("srcdir") ? getenv("srcdir") : ".") +
+ "/src/processor/testdata";
+ }
+
+ string symbol_file(int file_index) {
+ std::stringstream ss;
+ ss << testdata_dir << "/module" << file_index << ".out";
+ return ss.str();
+ }
+
+ ModuleSerializer serializer;
+ BasicSourceLineResolver basic_resolver;
+ FastSourceLineResolver fast_resolver;
+ ModuleComparer module_comparer;
+
+ string testdata_dir;
+};
+
+// Test adapted from basic_source_line_resolver_unittest.
+TEST_F(TestFastSourceLineResolver, TestLoadAndResolve) {
+ TestCodeModule module1("module1");
+ ASSERT_TRUE(basic_resolver.LoadModule(&module1, symbol_file(1)));
+ ASSERT_TRUE(basic_resolver.HasModule(&module1));
+ // Convert module1 to fast_module:
+ ASSERT_TRUE(serializer.ConvertOneModule(
+ module1.code_file(), &basic_resolver, &fast_resolver));
+ ASSERT_TRUE(fast_resolver.HasModule(&module1));
+
+ TestCodeModule module2("module2");
+ ASSERT_TRUE(basic_resolver.LoadModule(&module2, symbol_file(2)));
+ ASSERT_TRUE(basic_resolver.HasModule(&module2));
+ // Convert module2 to fast_module:
+ ASSERT_TRUE(serializer.ConvertOneModule(
+ module2.code_file(), &basic_resolver, &fast_resolver));
+ ASSERT_TRUE(fast_resolver.HasModule(&module2));
+
+ StackFrame frame;
+ scoped_ptr<WindowsFrameInfo> windows_frame_info;
+ scoped_ptr<CFIFrameInfo> cfi_frame_info;
+ frame.instruction = 0x1000;
+ frame.module = NULL;
+ fast_resolver.FillSourceLineInfo(&frame);
+ ASSERT_FALSE(frame.module);
+ ASSERT_TRUE(frame.function_name.empty());
+ ASSERT_EQ(frame.function_base, 0U);
+ ASSERT_TRUE(frame.source_file_name.empty());
+ ASSERT_EQ(frame.source_line, 0);
+ ASSERT_EQ(frame.source_line_base, 0U);
+
+ frame.module = &module1;
+ fast_resolver.FillSourceLineInfo(&frame);
+ ASSERT_EQ(frame.function_name, "Function1_1");
+ ASSERT_TRUE(frame.module);
+ ASSERT_EQ(frame.module->code_file(), "module1");
+ ASSERT_EQ(frame.function_base, 0x1000U);
+ ASSERT_EQ(frame.source_file_name, "file1_1.cc");
+ ASSERT_EQ(frame.source_line, 44);
+ ASSERT_EQ(frame.source_line_base, 0x1000U);
+ windows_frame_info.reset(fast_resolver.FindWindowsFrameInfo(&frame));
+ ASSERT_TRUE(windows_frame_info.get());
+ ASSERT_FALSE(windows_frame_info->allocates_base_pointer);
+ ASSERT_EQ(windows_frame_info->program_string,
+ "$eip 4 + ^ = $esp $ebp 8 + = $ebp $ebp ^ =");
+
+ ClearSourceLineInfo(&frame);
+ frame.instruction = 0x800;
+ frame.module = &module1;
+ fast_resolver.FillSourceLineInfo(&frame);
+ ASSERT_TRUE(VerifyEmpty(frame));
+ windows_frame_info.reset(fast_resolver.FindWindowsFrameInfo(&frame));
+ ASSERT_FALSE(windows_frame_info.get());
+
+ frame.instruction = 0x1280;
+ fast_resolver.FillSourceLineInfo(&frame);
+ ASSERT_EQ(frame.function_name, "Function1_3");
+ ASSERT_TRUE(frame.source_file_name.empty());
+ ASSERT_EQ(frame.source_line, 0);
+ windows_frame_info.reset(fast_resolver.FindWindowsFrameInfo(&frame));
+ ASSERT_TRUE(windows_frame_info.get());
+ ASSERT_EQ(windows_frame_info->type_, WindowsFrameInfo::STACK_INFO_UNKNOWN);
+ ASSERT_FALSE(windows_frame_info->allocates_base_pointer);
+ ASSERT_TRUE(windows_frame_info->program_string.empty());
+
+ frame.instruction = 0x1380;
+ fast_resolver.FillSourceLineInfo(&frame);
+ ASSERT_EQ(frame.function_name, "Function1_4");
+ ASSERT_TRUE(frame.source_file_name.empty());
+ ASSERT_EQ(frame.source_line, 0);
+ windows_frame_info.reset(fast_resolver.FindWindowsFrameInfo(&frame));
+ ASSERT_TRUE(windows_frame_info.get());
+ ASSERT_EQ(windows_frame_info->type_, WindowsFrameInfo::STACK_INFO_FRAME_DATA);
+ ASSERT_FALSE(windows_frame_info->allocates_base_pointer);
+ ASSERT_FALSE(windows_frame_info->program_string.empty());
+
+ frame.instruction = 0x2000;
+ windows_frame_info.reset(fast_resolver.FindWindowsFrameInfo(&frame));
+ ASSERT_FALSE(windows_frame_info.get());
+
+ // module1 has STACK CFI records covering 3d40..3def;
+ // module2 has STACK CFI records covering 3df0..3e9f;
+ // check that FindCFIFrameInfo doesn't claim to find any outside those ranges.
+ frame.instruction = 0x3d3f;
+ frame.module = &module1;
+ cfi_frame_info.reset(fast_resolver.FindCFIFrameInfo(&frame));
+ ASSERT_FALSE(cfi_frame_info.get());
+
+ frame.instruction = 0x3e9f;
+ frame.module = &module1;
+ cfi_frame_info.reset(fast_resolver.FindCFIFrameInfo(&frame));
+ ASSERT_FALSE(cfi_frame_info.get());
+
+ CFIFrameInfo::RegisterValueMap<uint32_t> current_registers;
+ CFIFrameInfo::RegisterValueMap<uint32_t> caller_registers;
+ CFIFrameInfo::RegisterValueMap<uint32_t> expected_caller_registers;
+ MockMemoryRegion memory;
+
+ // Regardless of which instruction evaluation takes place at, it
+ // should produce the same values for the caller's registers.
+ expected_caller_registers[".cfa"] = 0x1001c;
+ expected_caller_registers[".ra"] = 0xf6438648;
+ expected_caller_registers["$ebp"] = 0x10038;
+ expected_caller_registers["$ebx"] = 0x98ecadc3;
+ expected_caller_registers["$esi"] = 0x878f7524;
+ expected_caller_registers["$edi"] = 0x6312f9a5;
+
+ frame.instruction = 0x3d40;
+ frame.module = &module1;
+ current_registers.clear();
+ current_registers["$esp"] = 0x10018;
+ current_registers["$ebp"] = 0x10038;
+ current_registers["$ebx"] = 0x98ecadc3;
+ current_registers["$esi"] = 0x878f7524;
+ current_registers["$edi"] = 0x6312f9a5;
+ cfi_frame_info.reset(fast_resolver.FindCFIFrameInfo(&frame));
+ ASSERT_TRUE(cfi_frame_info.get());
+ ASSERT_TRUE(cfi_frame_info.get()
+ ->FindCallerRegs<uint32_t>(current_registers, memory,
+ &caller_registers));
+ ASSERT_TRUE(VerifyRegisters(__FILE__, __LINE__,
+ expected_caller_registers, caller_registers));
+
+ frame.instruction = 0x3d41;
+ current_registers["$esp"] = 0x10014;
+ cfi_frame_info.reset(fast_resolver.FindCFIFrameInfo(&frame));
+ ASSERT_TRUE(cfi_frame_info.get());
+ ASSERT_TRUE(cfi_frame_info.get()
+ ->FindCallerRegs<uint32_t>(current_registers, memory,
+ &caller_registers));
+ ASSERT_TRUE(VerifyRegisters(__FILE__, __LINE__,
+ expected_caller_registers, caller_registers));
+
+ frame.instruction = 0x3d43;
+ current_registers["$ebp"] = 0x10014;
+ cfi_frame_info.reset(fast_resolver.FindCFIFrameInfo(&frame));
+ ASSERT_TRUE(cfi_frame_info.get());
+ ASSERT_TRUE(cfi_frame_info.get()
+ ->FindCallerRegs<uint32_t>(current_registers, memory,
+ &caller_registers));
+ VerifyRegisters(__FILE__, __LINE__,
+ expected_caller_registers, caller_registers);
+
+ frame.instruction = 0x3d54;
+ current_registers["$ebx"] = 0x6864f054U;
+ cfi_frame_info.reset(fast_resolver.FindCFIFrameInfo(&frame));
+ ASSERT_TRUE(cfi_frame_info.get());
+ ASSERT_TRUE(cfi_frame_info.get()
+ ->FindCallerRegs<uint32_t>(current_registers, memory,
+ &caller_registers));
+ VerifyRegisters(__FILE__, __LINE__,
+ expected_caller_registers, caller_registers);
+
+ frame.instruction = 0x3d5a;
+ current_registers["$esi"] = 0x6285f79aU;
+ cfi_frame_info.reset(fast_resolver.FindCFIFrameInfo(&frame));
+ ASSERT_TRUE(cfi_frame_info.get());
+ ASSERT_TRUE(cfi_frame_info.get()
+ ->FindCallerRegs<uint32_t>(current_registers, memory,
+ &caller_registers));
+ VerifyRegisters(__FILE__, __LINE__,
+ expected_caller_registers, caller_registers);
+
+ frame.instruction = 0x3d84;
+ current_registers["$edi"] = 0x64061449U;
+ cfi_frame_info.reset(fast_resolver.FindCFIFrameInfo(&frame));
+ ASSERT_TRUE(cfi_frame_info.get());
+ ASSERT_TRUE(cfi_frame_info.get()
+ ->FindCallerRegs<uint32_t>(current_registers, memory,
+ &caller_registers));
+ VerifyRegisters(__FILE__, __LINE__,
+ expected_caller_registers, caller_registers);
+
+ frame.instruction = 0x2900;
+ frame.module = &module1;
+ fast_resolver.FillSourceLineInfo(&frame);
+ ASSERT_EQ(frame.function_name, string("PublicSymbol"));
+
+ frame.instruction = 0x4000;
+ frame.module = &module1;
+ fast_resolver.FillSourceLineInfo(&frame);
+ ASSERT_EQ(frame.function_name, string("LargeFunction"));
+
+ frame.instruction = 0x2181;
+ frame.module = &module2;
+ fast_resolver.FillSourceLineInfo(&frame);
+ ASSERT_EQ(frame.function_name, "Function2_2");
+ ASSERT_EQ(frame.function_base, 0x2170U);
+ ASSERT_TRUE(frame.module);
+ ASSERT_EQ(frame.module->code_file(), "module2");
+ ASSERT_EQ(frame.source_file_name, "file2_2.cc");
+ ASSERT_EQ(frame.source_line, 21);
+ ASSERT_EQ(frame.source_line_base, 0x2180U);
+ windows_frame_info.reset(fast_resolver.FindWindowsFrameInfo(&frame));
+ ASSERT_TRUE(windows_frame_info.get());
+ ASSERT_EQ(windows_frame_info->type_, WindowsFrameInfo::STACK_INFO_FRAME_DATA);
+ ASSERT_EQ(windows_frame_info->prolog_size, 1U);
+
+ frame.instruction = 0x216f;
+ fast_resolver.FillSourceLineInfo(&frame);
+ ASSERT_EQ(frame.function_name, "Public2_1");
+
+ ClearSourceLineInfo(&frame);
+ frame.instruction = 0x219f;
+ frame.module = &module2;
+ fast_resolver.FillSourceLineInfo(&frame);
+ ASSERT_TRUE(frame.function_name.empty());
+
+ frame.instruction = 0x21a0;
+ frame.module = &module2;
+ fast_resolver.FillSourceLineInfo(&frame);
+ ASSERT_EQ(frame.function_name, "Public2_2");
+}
+
+TEST_F(TestFastSourceLineResolver, TestInvalidLoads) {
+ TestCodeModule module3("module3");
+ ASSERT_TRUE(basic_resolver.LoadModule(&module3,
+ testdata_dir + "/module3_bad.out"));
+ ASSERT_TRUE(basic_resolver.HasModule(&module3));
+ ASSERT_TRUE(basic_resolver.IsModuleCorrupt(&module3));
+ // Convert module3 to fast_module:
+ ASSERT_TRUE(serializer.ConvertOneModule(module3.code_file(),
+ &basic_resolver,
+ &fast_resolver));
+ ASSERT_TRUE(fast_resolver.HasModule(&module3));
+ ASSERT_TRUE(fast_resolver.IsModuleCorrupt(&module3));
+
+ TestCodeModule module4("module4");
+ ASSERT_TRUE(basic_resolver.LoadModule(&module4,
+ testdata_dir + "/module4_bad.out"));
+ ASSERT_TRUE(basic_resolver.HasModule(&module4));
+ ASSERT_TRUE(basic_resolver.IsModuleCorrupt(&module4));
+ // Convert module4 to fast_module:
+ ASSERT_TRUE(serializer.ConvertOneModule(module4.code_file(),
+ &basic_resolver,
+ &fast_resolver));
+ ASSERT_TRUE(fast_resolver.HasModule(&module4));
+ ASSERT_TRUE(fast_resolver.IsModuleCorrupt(&module4));
+
+ TestCodeModule module5("module5");
+ ASSERT_FALSE(fast_resolver.LoadModule(&module5,
+ testdata_dir + "/invalid-filename"));
+ ASSERT_FALSE(fast_resolver.HasModule(&module5));
+
+ TestCodeModule invalidmodule("invalid-module");
+ ASSERT_FALSE(fast_resolver.HasModule(&invalidmodule));
+}
+
+TEST_F(TestFastSourceLineResolver, TestUnload) {
+ TestCodeModule module1("module1");
+ ASSERT_FALSE(basic_resolver.HasModule(&module1));
+
+ ASSERT_TRUE(basic_resolver.LoadModule(&module1, symbol_file(1)));
+ ASSERT_TRUE(basic_resolver.HasModule(&module1));
+ // Convert module1 to fast_module.
+ ASSERT_TRUE(serializer.ConvertOneModule(module1.code_file(),
+ &basic_resolver,
+ &fast_resolver));
+ ASSERT_TRUE(fast_resolver.HasModule(&module1));
+ basic_resolver.UnloadModule(&module1);
+ fast_resolver.UnloadModule(&module1);
+ ASSERT_FALSE(fast_resolver.HasModule(&module1));
+
+ ASSERT_TRUE(basic_resolver.LoadModule(&module1, symbol_file(1)));
+ ASSERT_TRUE(basic_resolver.HasModule(&module1));
+ // Convert module1 to fast_module.
+ ASSERT_TRUE(serializer.ConvertOneModule(module1.code_file(),
+ &basic_resolver,
+ &fast_resolver));
+ ASSERT_TRUE(fast_resolver.HasModule(&module1));
+}
+
+TEST_F(TestFastSourceLineResolver, CompareModule) {
+ char *symbol_data;
+ size_t symbol_data_size;
+ string symbol_data_string;
+ string filename;
+
+ for (int module_index = 0; module_index < 3; ++module_index) {
+ std::stringstream ss;
+ ss << testdata_dir << "/module" << module_index << ".out";
+ filename = ss.str();
+ ASSERT_TRUE(SourceLineResolverBase::ReadSymbolFile(
+ symbol_file(module_index), &symbol_data, &symbol_data_size));
+ symbol_data_string.assign(symbol_data, symbol_data_size);
+ delete [] symbol_data;
+ ASSERT_TRUE(module_comparer.Compare(symbol_data_string));
+ }
+}
+
+} // namespace
+
+int main(int argc, char *argv[]) {
+ ::testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/linked_ptr.h b/toolkit/crashreporter/google-breakpad/src/processor/linked_ptr.h
new file mode 100644
index 0000000000..72fbba84a9
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/linked_ptr.h
@@ -0,0 +1,193 @@
+// 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.
+
+// A "smart" pointer type with reference tracking. Every pointer to a
+// particular object is kept on a circular linked list. When the last pointer
+// to an object is destroyed or reassigned, the object is deleted.
+//
+// Used properly, this deletes the object when the last reference goes away.
+// There are several caveats:
+// - Like all reference counting schemes, cycles lead to leaks.
+// - Each smart pointer is actually two pointers (8 bytes instead of 4).
+// - Every time a pointer is assigned, the entire list of pointers to that
+// object is traversed. This class is therefore NOT SUITABLE when there
+// will often be more than two or three pointers to a particular object.
+// - References are only tracked as long as linked_ptr<> objects are copied.
+// If a linked_ptr<> is converted to a raw pointer and back, BAD THINGS
+// will happen (double deletion).
+//
+// A good use of this class is storing object references in STL containers.
+// You can safely put linked_ptr<> in a vector<>.
+// Other uses may not be as good.
+//
+// Note: If you use an incomplete type with linked_ptr<>, the class
+// *containing* linked_ptr<> must have a constructor and destructor (even
+// if they do nothing!).
+
+#ifndef PROCESSOR_LINKED_PTR_H__
+#define PROCESSOR_LINKED_PTR_H__
+
+namespace google_breakpad {
+
+// This is used internally by all instances of linked_ptr<>. It needs to be
+// a non-template class because different types of linked_ptr<> can refer to
+// the same object (linked_ptr<Superclass>(obj) vs linked_ptr<Subclass>(obj)).
+// So, it needs to be possible for different types of linked_ptr to participate
+// in the same circular linked list, so we need a single class type here.
+//
+// DO NOT USE THIS CLASS DIRECTLY YOURSELF. Use linked_ptr<T>.
+class linked_ptr_internal {
+ public:
+ // Create a new circle that includes only this instance.
+ void join_new() {
+ next_ = this;
+ }
+
+ // Join an existing circle.
+ void join(linked_ptr_internal const* ptr) {
+ linked_ptr_internal const* p = ptr;
+ while (p->next_ != ptr) p = p->next_;
+ p->next_ = this;
+ next_ = ptr;
+ }
+
+ // Leave whatever circle we're part of. Returns true iff we were the
+ // last member of the circle. Once this is done, you can join() another.
+ bool depart() {
+ if (next_ == this) return true;
+ linked_ptr_internal const* p = next_;
+ while (p->next_ != this) p = p->next_;
+ p->next_ = next_;
+ return false;
+ }
+
+ private:
+ mutable linked_ptr_internal const* next_;
+};
+
+template <typename T>
+class linked_ptr {
+ public:
+ typedef T element_type;
+
+ // Take over ownership of a raw pointer. This should happen as soon as
+ // possible after the object is created.
+ explicit linked_ptr(T* ptr = NULL) { capture(ptr); }
+ ~linked_ptr() { depart(); }
+
+ // Copy an existing linked_ptr<>, adding ourselves to the list of references.
+ template <typename U> linked_ptr(linked_ptr<U> const& ptr) { copy(&ptr); }
+ linked_ptr(linked_ptr const& ptr) { copy(&ptr); }
+
+ // Assignment releases the old value and acquires the new.
+ template <typename U> linked_ptr& operator=(linked_ptr<U> const& ptr) {
+ depart();
+ copy(&ptr);
+ return *this;
+ }
+
+ linked_ptr& operator=(linked_ptr const& ptr) {
+ if (&ptr != this) {
+ depart();
+ copy(&ptr);
+ }
+ return *this;
+ }
+
+ // Smart pointer members.
+ void reset(T* ptr = NULL) { depart(); capture(ptr); }
+ T* get() const { return value_; }
+ T* operator->() const { return value_; }
+ T& operator*() const { return *value_; }
+ // Release ownership of the pointed object and returns it.
+ // Sole ownership by this linked_ptr object is required.
+ T* release() {
+ link_.depart();
+ T* v = value_;
+ value_ = NULL;
+ return v;
+ }
+
+ bool operator==(T* p) const { return value_ == p; }
+ bool operator!=(T* p) const { return value_ != p; }
+ template <typename U>
+ bool operator==(linked_ptr<U> const& ptr) const {
+ return value_ == ptr.get();
+ }
+ template <typename U>
+ bool operator!=(linked_ptr<U> const& ptr) const {
+ return value_ != ptr.get();
+ }
+
+ private:
+ template <typename U>
+ friend class linked_ptr;
+
+ T* value_;
+ linked_ptr_internal link_;
+
+ void depart() {
+ if (link_.depart()) delete value_;
+ }
+
+ void capture(T* ptr) {
+ value_ = ptr;
+ link_.join_new();
+ }
+
+ template <typename U> void copy(linked_ptr<U> const* ptr) {
+ value_ = ptr->get();
+ if (value_)
+ link_.join(&ptr->link_);
+ else
+ link_.join_new();
+ }
+};
+
+template<typename T> inline
+bool operator==(T* ptr, const linked_ptr<T>& x) {
+ return ptr == x.get();
+}
+
+template<typename T> inline
+bool operator!=(T* ptr, const linked_ptr<T>& x) {
+ return ptr != x.get();
+}
+
+// A function to convert T* into linked_ptr<T>
+// Doing e.g. make_linked_ptr(new FooBarBaz<type>(arg)) is a shorter notation
+// for linked_ptr<FooBarBaz<type> >(new FooBarBaz<type>(arg))
+template <typename T>
+linked_ptr<T> make_linked_ptr(T* ptr) {
+ return linked_ptr<T>(ptr);
+}
+
+} // namespace google_breakpad
+
+#endif // PROCESSOR_LINKED_PTR_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/logging.cc b/toolkit/crashreporter/google-breakpad/src/processor/logging.cc
new file mode 100644
index 0000000000..d59175a735
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/logging.cc
@@ -0,0 +1,114 @@
+// 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.
+
+// logging.cc: Breakpad logging
+//
+// See logging.h for documentation.
+//
+// Author: Mark Mentovai
+
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+#include <time.h>
+
+#include <string>
+
+#include "common/stdio_wrapper.h"
+#include "common/using_std_string.h"
+#include "processor/logging.h"
+#include "processor/pathname_stripper.h"
+
+namespace google_breakpad {
+
+LogStream::LogStream(std::ostream &stream, Severity severity,
+ const char *file, int line)
+ : stream_(stream) {
+ time_t clock;
+ time(&clock);
+ struct tm tm_struct;
+#ifdef _WIN32
+ localtime_s(&tm_struct, &clock);
+#else
+ localtime_r(&clock, &tm_struct);
+#endif
+ char time_string[20];
+ strftime(time_string, sizeof(time_string), "%Y-%m-%d %H:%M:%S", &tm_struct);
+
+ const char *severity_string = "UNKNOWN_SEVERITY";
+ switch (severity) {
+ case SEVERITY_INFO:
+ severity_string = "INFO";
+ break;
+ case SEVERITY_ERROR:
+ severity_string = "ERROR";
+ break;
+ case SEVERITY_CRITICAL:
+ severity_string = "CRITICAL";
+ break;
+ }
+
+ stream_ << time_string << ": " << PathnameStripper::File(file) << ":" <<
+ line << ": " << severity_string << ": ";
+}
+
+LogStream::~LogStream() {
+ stream_ << std::endl;
+}
+
+string HexString(uint32_t number) {
+ char buffer[11];
+ snprintf(buffer, sizeof(buffer), "0x%x", number);
+ return string(buffer);
+}
+
+string HexString(uint64_t number) {
+ char buffer[19];
+ snprintf(buffer, sizeof(buffer), "0x%" PRIx64, number);
+ return string(buffer);
+}
+
+string HexString(int number) {
+ char buffer[19];
+ snprintf(buffer, sizeof(buffer), "0x%x", number);
+ return string(buffer);
+}
+
+int ErrnoString(string *error_string) {
+ assert(error_string);
+
+ // strerror isn't necessarily thread-safe. strerror_r would be preferrable,
+ // but GNU libc uses a nonstandard strerror_r by default, which returns a
+ // char* (rather than an int success indicator) and doesn't necessarily
+ // use the supplied buffer.
+ error_string->assign(strerror(errno));
+ return errno;
+}
+
+} // namespace google_breakpad
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/logging.h b/toolkit/crashreporter/google-breakpad/src/processor/logging.h
new file mode 100644
index 0000000000..43f3cfc951
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/logging.h
@@ -0,0 +1,188 @@
+// 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.
+
+// logging.h: Breakpad logging
+//
+// Breakpad itself uses Breakpad logging with statements of the form:
+// BPLOG(severity) << "message";
+// severity may be INFO, ERROR, or other values defined in this file.
+//
+// BPLOG is an overridable macro so that users can customize Breakpad's
+// logging. Left at the default, logging messages are sent to stderr along
+// with a timestamp and the source code location that produced a message.
+// The streams may be changed by redefining BPLOG_*_STREAM, the logging
+// behavior may be changed by redefining BPLOG_*, and the entire logging
+// system may be overridden by redefining BPLOG(severity). These
+// redefinitions may be passed to the preprocessor as a command-line flag
+// (-D).
+//
+// If an additional header is required to override Breakpad logging, it can
+// be specified by the BP_LOGGING_INCLUDE macro. If defined, this header
+// will #include the header specified by that macro.
+//
+// If any initialization is needed before logging, it can be performed by
+// a function called through the BPLOG_INIT macro. Each main function of
+// an executable program in the Breakpad processor library calls
+// BPLOG_INIT(&argc, &argv); before any logging can be performed; define
+// BPLOG_INIT appropriately if initialization is required.
+//
+// Author: Mark Mentovai
+
+#ifndef PROCESSOR_LOGGING_H__
+#define PROCESSOR_LOGGING_H__
+
+#include <iostream>
+#include <string>
+
+#include "common/using_std_string.h"
+#include "google_breakpad/common/breakpad_types.h"
+
+#ifdef BP_LOGGING_INCLUDE
+#include BP_LOGGING_INCLUDE
+#endif // BP_LOGGING_INCLUDE
+
+namespace google_breakpad {
+
+// These are defined in Microsoft headers.
+#ifdef SEVERITY_ERROR
+#undef SEVERITY_ERROR
+#endif
+
+#ifdef ERROR
+#undef ERROR
+#endif
+
+class LogStream {
+ public:
+ enum Severity {
+ SEVERITY_INFO,
+ SEVERITY_ERROR,
+ SEVERITY_CRITICAL
+ };
+
+ // Begin logging a message to the stream identified by |stream|, at the
+ // indicated severity. The file and line parameters should be set so as to
+ // identify the line of source code that is producing a message.
+ LogStream(std::ostream &stream, Severity severity,
+ const char *file, int line);
+
+ // Finish logging by printing a newline and flushing the output stream.
+ ~LogStream();
+
+ template<typename T> std::ostream& operator<<(const T &t) {
+ return stream_ << t;
+ }
+
+ private:
+ std::ostream &stream_;
+
+ // Disallow copy constructor and assignment operator
+ explicit LogStream(const LogStream &that);
+ void operator=(const LogStream &that);
+};
+
+// This class is used to explicitly ignore values in the conditional logging
+// macros. This avoids compiler warnings like "value computed is not used"
+// and "statement has no effect".
+class LogMessageVoidify {
+ public:
+ LogMessageVoidify() {}
+
+ // This has to be an operator with a precedence lower than << but higher
+ // than ?:
+ void operator&(std::ostream &) {}
+};
+
+// Returns number formatted as a hexadecimal string, such as "0x7b".
+string HexString(uint32_t number);
+string HexString(uint64_t number);
+string HexString(int number);
+
+// Returns the error code as set in the global errno variable, and sets
+// error_string, a required argument, to a string describing that error
+// code.
+int ErrnoString(string *error_string);
+
+} // namespace google_breakpad
+
+#ifndef BPLOG_INIT
+#define BPLOG_INIT(pargc, pargv)
+#endif // BPLOG_INIT
+
+#ifndef BPLOG_LAZY_STREAM
+#define BPLOG_LAZY_STREAM(stream, condition) \
+ !(condition) ? (void) 0 : \
+ google_breakpad::LogMessageVoidify() & (BPLOG_ ## stream)
+#endif
+
+#ifndef BPLOG_MINIMUM_SEVERITY
+#define BPLOG_MINIMUM_SEVERITY SEVERITY_INFO
+#endif
+
+#define BPLOG_LOG_IS_ON(severity) \
+ ((google_breakpad::LogStream::SEVERITY_ ## severity) >= \
+ (google_breakpad::LogStream::BPLOG_MINIMUM_SEVERITY))
+
+#ifndef BPLOG
+#define BPLOG(severity) BPLOG_LAZY_STREAM(severity, BPLOG_LOG_IS_ON(severity))
+#endif // BPLOG
+
+#ifndef BPLOG_INFO
+#ifndef BPLOG_INFO_STREAM
+#define BPLOG_INFO_STREAM std::clog
+#endif // BPLOG_INFO_STREAM
+#define BPLOG_INFO google_breakpad::LogStream(BPLOG_INFO_STREAM, \
+ google_breakpad::LogStream::SEVERITY_INFO, \
+ __FILE__, __LINE__)
+#endif // BPLOG_INFO
+
+#ifndef BPLOG_ERROR
+#ifndef BPLOG_ERROR_STREAM
+#define BPLOG_ERROR_STREAM std::cerr
+#endif // BPLOG_ERROR_STREAM
+#define BPLOG_ERROR google_breakpad::LogStream(BPLOG_ERROR_STREAM, \
+ google_breakpad::LogStream::SEVERITY_ERROR, \
+ __FILE__, __LINE__)
+#endif // BPLOG_ERROR
+
+#ifndef BPLOG_CRITICAL
+#ifndef BPLOG_CRITICAL_STREAM
+#define BPLOG_CRITICAL_STREAM std::cerr
+#endif // BPLOG_CRITICAL_STREAM
+#define BPLOG_CRITICAL google_breakpad::LogStream(BPLOG_CRITICAL_STREAM, \
+ google_breakpad::LogStream::SEVERITY_CRITICAL, \
+ __FILE__, __LINE__)
+#endif // BPLOG_CRITICAL
+
+#ifndef BPLOG_IF
+#define BPLOG_IF(severity, condition) \
+ BPLOG_LAZY_STREAM(severity, ((condition) && BPLOG_LOG_IS_ON(severity)))
+#endif // BPLOG_IF
+
+#endif // PROCESSOR_LOGGING_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/map_serializers-inl.h b/toolkit/crashreporter/google-breakpad/src/processor/map_serializers-inl.h
new file mode 100644
index 0000000000..61c7bbd7c8
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/map_serializers-inl.h
@@ -0,0 +1,266 @@
+// 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.
+//
+// map_serializers_inl.h: implementation for serializing std::map and its
+// wrapper classes.
+//
+// See map_serializers.h for documentation.
+//
+// Author: Siyang Xie (lambxsy@google.com)
+
+#ifndef PROCESSOR_MAP_SERIALIZERS_INL_H__
+#define PROCESSOR_MAP_SERIALIZERS_INL_H__
+
+#include <map>
+#include <string>
+
+#include "processor/map_serializers.h"
+#include "processor/simple_serializer.h"
+
+#include "processor/address_map-inl.h"
+#include "processor/range_map-inl.h"
+#include "processor/contained_range_map-inl.h"
+
+#include "processor/logging.h"
+
+namespace google_breakpad {
+
+template<typename Key, typename Value>
+size_t StdMapSerializer<Key, Value>::SizeOf(
+ const std::map<Key, Value> &m) const {
+ size_t size = 0;
+ size_t header_size = (1 + m.size()) * sizeof(uint32_t);
+ size += header_size;
+
+ typename std::map<Key, Value>::const_iterator iter;
+ for (iter = m.begin(); iter != m.end(); ++iter) {
+ size += key_serializer_.SizeOf(iter->first);
+ size += value_serializer_.SizeOf(iter->second);
+ }
+ return size;
+}
+
+template<typename Key, typename Value>
+char *StdMapSerializer<Key, Value>::Write(const std::map<Key, Value> &m,
+ char *dest) const {
+ if (!dest) {
+ BPLOG(ERROR) << "StdMapSerializer failed: write to NULL address.";
+ return NULL;
+ }
+ char *start_address = dest;
+
+ // Write header:
+ // Number of nodes.
+ dest = SimpleSerializer<uint32_t>::Write(m.size(), dest);
+ // Nodes offsets.
+ uint32_t *offsets = reinterpret_cast<uint32_t*>(dest);
+ dest += sizeof(uint32_t) * m.size();
+
+ char *key_address = dest;
+ dest += sizeof(Key) * m.size();
+
+ // Traverse map.
+ typename std::map<Key, Value>::const_iterator iter;
+ int index = 0;
+ for (iter = m.begin(); iter != m.end(); ++iter, ++index) {
+ offsets[index] = static_cast<uint32_t>(dest - start_address);
+ key_address = key_serializer_.Write(iter->first, key_address);
+ dest = value_serializer_.Write(iter->second, dest);
+ }
+ return dest;
+}
+
+template<typename Key, typename Value>
+char *StdMapSerializer<Key, Value>::Serialize(
+ const std::map<Key, Value> &m, unsigned int *size) const {
+ // Compute size of memory to be allocated.
+ unsigned int size_to_alloc = SizeOf(m);
+ // Allocate memory.
+ char *serialized_data = new char[size_to_alloc];
+ if (!serialized_data) {
+ BPLOG(INFO) << "StdMapSerializer memory allocation failed.";
+ if (size) *size = 0;
+ return NULL;
+ }
+ // Write serialized data into memory.
+ Write(m, serialized_data);
+
+ if (size) *size = size_to_alloc;
+ return serialized_data;
+}
+
+template<typename Address, typename Entry>
+size_t RangeMapSerializer<Address, Entry>::SizeOf(
+ const RangeMap<Address, Entry> &m) const {
+ size_t size = 0;
+ size_t header_size = (1 + m.map_.size()) * sizeof(uint32_t);
+ size += header_size;
+
+ typename std::map<Address, Range>::const_iterator iter;
+ for (iter = m.map_.begin(); iter != m.map_.end(); ++iter) {
+ // Size of key (high address).
+ size += address_serializer_.SizeOf(iter->first);
+ // Size of base (low address).
+ size += address_serializer_.SizeOf(iter->second.base());
+ // Size of entry.
+ size += entry_serializer_.SizeOf(iter->second.entry());
+ }
+ return size;
+}
+
+template<typename Address, typename Entry>
+char *RangeMapSerializer<Address, Entry>::Write(
+ const RangeMap<Address, Entry> &m, char *dest) const {
+ if (!dest) {
+ BPLOG(ERROR) << "RangeMapSerializer failed: write to NULL address.";
+ return NULL;
+ }
+ char *start_address = dest;
+
+ // Write header:
+ // Number of nodes.
+ dest = SimpleSerializer<uint32_t>::Write(m.map_.size(), dest);
+ // Nodes offsets.
+ uint32_t *offsets = reinterpret_cast<uint32_t*>(dest);
+ dest += sizeof(uint32_t) * m.map_.size();
+
+ char *key_address = dest;
+ dest += sizeof(Address) * m.map_.size();
+
+ // Traverse map.
+ typename std::map<Address, Range>::const_iterator iter;
+ int index = 0;
+ for (iter = m.map_.begin(); iter != m.map_.end(); ++iter, ++index) {
+ offsets[index] = static_cast<uint32_t>(dest - start_address);
+ key_address = address_serializer_.Write(iter->first, key_address);
+ dest = address_serializer_.Write(iter->second.base(), dest);
+ dest = entry_serializer_.Write(iter->second.entry(), dest);
+ }
+ return dest;
+}
+
+template<typename Address, typename Entry>
+char *RangeMapSerializer<Address, Entry>::Serialize(
+ const RangeMap<Address, Entry> &m, unsigned int *size) const {
+ // Compute size of memory to be allocated.
+ unsigned int size_to_alloc = SizeOf(m);
+ // Allocate memory.
+ char *serialized_data = new char[size_to_alloc];
+ if (!serialized_data) {
+ BPLOG(INFO) << "RangeMapSerializer memory allocation failed.";
+ if (size) *size = 0;
+ return NULL;
+ }
+
+ // Write serialized data into memory.
+ Write(m, serialized_data);
+
+ if (size) *size = size_to_alloc;
+ return serialized_data;
+}
+
+
+template<class AddrType, class EntryType>
+size_t ContainedRangeMapSerializer<AddrType, EntryType>::SizeOf(
+ const ContainedRangeMap<AddrType, EntryType> *m) const {
+ size_t size = 0;
+ size_t header_size = addr_serializer_.SizeOf(m->base_)
+ + entry_serializer_.SizeOf(m->entry_)
+ + sizeof(uint32_t);
+ size += header_size;
+ // In case m.map_ == NULL, we treat it as an empty map:
+ size += sizeof(uint32_t);
+ if (m->map_) {
+ size += m->map_->size() * sizeof(uint32_t);
+ typename Map::const_iterator iter;
+ for (iter = m->map_->begin(); iter != m->map_->end(); ++iter) {
+ size += addr_serializer_.SizeOf(iter->first);
+ // Recursive calculation of size:
+ size += SizeOf(iter->second);
+ }
+ }
+ return size;
+}
+
+template<class AddrType, class EntryType>
+char *ContainedRangeMapSerializer<AddrType, EntryType>::Write(
+ const ContainedRangeMap<AddrType, EntryType> *m, char *dest) const {
+ if (!dest) {
+ BPLOG(ERROR) << "StdMapSerializer failed: write to NULL address.";
+ return NULL;
+ }
+ dest = addr_serializer_.Write(m->base_, dest);
+ dest = SimpleSerializer<uint32_t>::Write(entry_serializer_.SizeOf(m->entry_),
+ dest);
+ dest = entry_serializer_.Write(m->entry_, dest);
+
+ // Write map<<AddrType, ContainedRangeMap*>:
+ char *map_address = dest;
+ if (m->map_ == NULL) {
+ dest = SimpleSerializer<uint32_t>::Write(0, dest);
+ } else {
+ dest = SimpleSerializer<uint32_t>::Write(m->map_->size(), dest);
+ uint32_t *offsets = reinterpret_cast<uint32_t*>(dest);
+ dest += sizeof(uint32_t) * m->map_->size();
+
+ char *key_address = dest;
+ dest += sizeof(AddrType) * m->map_->size();
+
+ // Traverse map.
+ typename Map::const_iterator iter;
+ int index = 0;
+ for (iter = m->map_->begin(); iter != m->map_->end(); ++iter, ++index) {
+ offsets[index] = static_cast<uint32_t>(dest - map_address);
+ key_address = addr_serializer_.Write(iter->first, key_address);
+ // Recursively write.
+ dest = Write(iter->second, dest);
+ }
+ }
+ return dest;
+}
+
+template<class AddrType, class EntryType>
+char *ContainedRangeMapSerializer<AddrType, EntryType>::Serialize(
+ const ContainedRangeMap<AddrType, EntryType> *m, unsigned int *size) const {
+ unsigned int size_to_alloc = SizeOf(m);
+ // Allocating memory.
+ char *serialized_data = new char[size_to_alloc];
+ if (!serialized_data) {
+ BPLOG(INFO) << "ContainedRangeMapSerializer memory allocation failed.";
+ if (size) *size = 0;
+ return NULL;
+ }
+ Write(m, serialized_data);
+ if (size) *size = size_to_alloc;
+ return serialized_data;
+}
+
+} // namespace google_breakpad
+
+#endif // PROCESSOR_MAP_SERIALIZERS_INL_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/map_serializers.h b/toolkit/crashreporter/google-breakpad/src/processor/map_serializers.h
new file mode 100644
index 0000000000..a0b9d3fd67
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/map_serializers.h
@@ -0,0 +1,168 @@
+// 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.
+//
+// map_serializers.h: defines templates for serializing std::map and its
+// wrappers: AddressMap, RangeMap, and ContainedRangeMap.
+//
+// Author: Siyang Xie (lambxsy@google.com)
+
+
+#ifndef PROCESSOR_MAP_SERIALIZERS_H__
+#define PROCESSOR_MAP_SERIALIZERS_H__
+
+#include <map>
+#include <string>
+
+#include "processor/simple_serializer.h"
+
+#include "processor/address_map-inl.h"
+#include "processor/range_map-inl.h"
+#include "processor/contained_range_map-inl.h"
+
+namespace google_breakpad {
+
+// StdMapSerializer allocates memory and serializes an std::map instance into a
+// chunk of memory data.
+template<typename Key, typename Value>
+class StdMapSerializer {
+ public:
+ // Calculate the memory size of serialized data.
+ size_t SizeOf(const std::map<Key, Value> &m) const;
+
+ // Writes the serialized data to memory with start address = dest,
+ // and returns the "end" of data, i.e., return the address follow the final
+ // byte of data.
+ // NOTE: caller has to allocate enough memory before invoke Write() method.
+ char* Write(const std::map<Key, Value> &m, char* dest) const;
+
+ // Serializes a std::map object into a chunk of memory data with format
+ // described in "StaticMap.h" comment.
+ // Returns a pointer to the serialized data. If size != NULL, *size is set
+ // to the size of serialized data, i.e., SizeOf(m).
+ // Caller has the ownership of memory allocated as "new char[]".
+ char* Serialize(const std::map<Key, Value> &m, unsigned int *size) const;
+
+ private:
+ SimpleSerializer<Key> key_serializer_;
+ SimpleSerializer<Value> value_serializer_;
+};
+
+// AddressMapSerializer allocates memory and serializes an AddressMap into a
+// chunk of memory data.
+template<typename Addr, typename Entry>
+class AddressMapSerializer {
+ public:
+ // Calculate the memory size of serialized data.
+ size_t SizeOf(const AddressMap<Addr, Entry> &m) const {
+ return std_map_serializer_.SizeOf(m.map_);
+ }
+
+ // Write the serialized data to specified memory location. Return the "end"
+ // of data, i.e., return the address after the final byte of data.
+ // NOTE: caller has to allocate enough memory before invoke Write() method.
+ char* Write(const AddressMap<Addr, Entry> &m, char *dest) const {
+ return std_map_serializer_.Write(m.map_, dest);
+ }
+
+ // Serializes an AddressMap object into a chunk of memory data.
+ // Returns a pointer to the serialized data. If size != NULL, *size is set
+ // to the size of serialized data, i.e., SizeOf(m).
+ // Caller has the ownership of memory allocated as "new char[]".
+ char* Serialize(const AddressMap<Addr, Entry> &m, unsigned int *size) const {
+ return std_map_serializer_.Serialize(m.map_, size);
+ }
+
+ private:
+ // AddressMapSerializer is a simple wrapper of StdMapSerializer, just as
+ // AddressMap is a simple wrapper of std::map.
+ StdMapSerializer<Addr, Entry> std_map_serializer_;
+};
+
+// RangeMapSerializer allocates memory and serializes a RangeMap instance into a
+// chunk of memory data.
+template<typename Address, typename Entry>
+class RangeMapSerializer {
+ public:
+ // Calculate the memory size of serialized data.
+ size_t SizeOf(const RangeMap<Address, Entry> &m) const;
+
+ // Write the serialized data to specified memory location. Return the "end"
+ // of data, i.e., return the address after the final byte of data.
+ // NOTE: caller has to allocate enough memory before invoke Write() method.
+ char* Write(const RangeMap<Address, Entry> &m, char* dest) const;
+
+ // Serializes a RangeMap object into a chunk of memory data.
+ // Returns a pointer to the serialized data. If size != NULL, *size is set
+ // to the size of serialized data, i.e., SizeOf(m).
+ // Caller has the ownership of memory allocated as "new char[]".
+ char* Serialize(const RangeMap<Address, Entry> &m, unsigned int *size) const;
+
+ private:
+ // Convenient type name for Range.
+ typedef typename RangeMap<Address, Entry>::Range Range;
+
+ // Serializer for RangeMap's key and Range::base_.
+ SimpleSerializer<Address> address_serializer_;
+ // Serializer for RangeMap::Range::entry_.
+ SimpleSerializer<Entry> entry_serializer_;
+};
+
+// ContainedRangeMapSerializer allocates memory and serializes a
+// ContainedRangeMap instance into a chunk of memory data.
+template<class AddrType, class EntryType>
+class ContainedRangeMapSerializer {
+ public:
+ // Calculate the memory size of serialized data.
+ size_t SizeOf(const ContainedRangeMap<AddrType, EntryType> *m) const;
+
+ // Write the serialized data to specified memory location. Return the "end"
+ // of data, i.e., return the address after the final byte of data.
+ // NOTE: caller has to allocate enough memory before invoke Write() method.
+ char* Write(const ContainedRangeMap<AddrType, EntryType> *m,
+ char* dest) const;
+
+ // Serializes a ContainedRangeMap object into a chunk of memory data.
+ // Returns a pointer to the serialized data. If size != NULL, *size is set
+ // to the size of serialized data, i.e., SizeOf(m).
+ // Caller has the ownership of memory allocated as "new char[]".
+ char* Serialize(const ContainedRangeMap<AddrType, EntryType> *m,
+ unsigned int *size) const;
+
+ private:
+ // Convenient type name for the underlying map type.
+ typedef std::map<AddrType, ContainedRangeMap<AddrType, EntryType>*> Map;
+
+ // Serializer for addresses and entries stored in ContainedRangeMap.
+ SimpleSerializer<AddrType> addr_serializer_;
+ SimpleSerializer<EntryType> entry_serializer_;
+};
+
+} // namespace google_breakpad
+
+#endif // PROCESSOR_MAP_SERIALIZERS_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/map_serializers_unittest.cc b/toolkit/crashreporter/google-breakpad/src/processor/map_serializers_unittest.cc
new file mode 100644
index 0000000000..0d872ec2e2
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/map_serializers_unittest.cc
@@ -0,0 +1,386 @@
+// 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.
+
+// map_serializers_unittest.cc: Unit tests for std::map serializer and
+// std::map wrapper serializers.
+//
+// Author: Siyang Xie (lambxsy@google.com)
+
+#include <climits>
+#include <map>
+#include <string>
+#include <utility>
+#include <iostream>
+#include <sstream>
+
+#include "breakpad_googletest_includes.h"
+#include "map_serializers-inl.h"
+
+#include "processor/address_map-inl.h"
+#include "processor/range_map-inl.h"
+#include "processor/contained_range_map-inl.h"
+
+typedef int32_t AddrType;
+typedef int32_t EntryType;
+
+class TestStdMapSerializer : public ::testing::Test {
+ protected:
+ void SetUp() {
+ serialized_size_ = 0;
+ serialized_data_ = NULL;
+ }
+
+ void TearDown() {
+ delete [] serialized_data_;
+ }
+
+ std::map<AddrType, EntryType> std_map_;
+ google_breakpad::StdMapSerializer<AddrType, EntryType> serializer_;
+ uint32_t serialized_size_;
+ char *serialized_data_;
+};
+
+TEST_F(TestStdMapSerializer, EmptyMapTestCase) {
+ const int32_t correct_data[] = { 0 };
+ uint32_t correct_size = sizeof(correct_data);
+
+ // std_map_ is empty.
+ serialized_data_ = serializer_.Serialize(std_map_, &serialized_size_);
+
+ EXPECT_EQ(correct_size, serialized_size_);
+ EXPECT_EQ(memcmp(correct_data, serialized_data_, correct_size), 0);
+}
+
+TEST_F(TestStdMapSerializer, MapWithTwoElementsTestCase) {
+ const int32_t correct_data[] = {
+ // # of nodes
+ 2,
+ // Offsets
+ 20, 24,
+ // Keys
+ 1, 3,
+ // Values
+ 2, 6
+ };
+ uint32_t correct_size = sizeof(correct_data);
+
+ std_map_.insert(std::make_pair(1, 2));
+ std_map_.insert(std::make_pair(3, 6));
+
+ serialized_data_ = serializer_.Serialize(std_map_, &serialized_size_);
+
+ EXPECT_EQ(correct_size, serialized_size_);
+ EXPECT_EQ(memcmp(correct_data, serialized_data_, correct_size), 0);
+}
+
+TEST_F(TestStdMapSerializer, MapWithFiveElementsTestCase) {
+ const int32_t correct_data[] = {
+ // # of nodes
+ 5,
+ // Offsets
+ 44, 48, 52, 56, 60,
+ // Keys
+ 1, 2, 3, 4, 5,
+ // Values
+ 11, 12, 13, 14, 15
+ };
+ uint32_t correct_size = sizeof(correct_data);
+
+ for (int i = 1; i < 6; ++i)
+ std_map_.insert(std::make_pair(i, 10 + i));
+
+ serialized_data_ = serializer_.Serialize(std_map_, &serialized_size_);
+
+ EXPECT_EQ(correct_size, serialized_size_);
+ EXPECT_EQ(memcmp(correct_data, serialized_data_, correct_size), 0);
+}
+
+class TestAddressMapSerializer : public ::testing::Test {
+ protected:
+ void SetUp() {
+ serialized_size_ = 0;
+ serialized_data_ = 0;
+ }
+
+ void TearDown() {
+ delete [] serialized_data_;
+ }
+
+ google_breakpad::AddressMap<AddrType, EntryType> address_map_;
+ google_breakpad::AddressMapSerializer<AddrType, EntryType> serializer_;
+ uint32_t serialized_size_;
+ char *serialized_data_;
+};
+
+TEST_F(TestAddressMapSerializer, EmptyMapTestCase) {
+ const int32_t correct_data[] = { 0 };
+ uint32_t correct_size = sizeof(correct_data);
+
+ // std_map_ is empty.
+ serialized_data_ = serializer_.Serialize(address_map_, &serialized_size_);
+
+ EXPECT_EQ(correct_size, serialized_size_);
+ EXPECT_EQ(memcmp(correct_data, serialized_data_, correct_size), 0);
+}
+
+TEST_F(TestAddressMapSerializer, MapWithTwoElementsTestCase) {
+ const int32_t correct_data[] = {
+ // # of nodes
+ 2,
+ // Offsets
+ 20, 24,
+ // Keys
+ 1, 3,
+ // Values
+ 2, 6
+ };
+ uint32_t correct_size = sizeof(correct_data);
+
+ address_map_.Store(1, 2);
+ address_map_.Store(3, 6);
+
+ serialized_data_ = serializer_.Serialize(address_map_, &serialized_size_);
+
+ EXPECT_EQ(correct_size, serialized_size_);
+ EXPECT_EQ(memcmp(correct_data, serialized_data_, correct_size), 0);
+}
+
+TEST_F(TestAddressMapSerializer, MapWithFourElementsTestCase) {
+ const int32_t correct_data[] = {
+ // # of nodes
+ 4,
+ // Offsets
+ 36, 40, 44, 48,
+ // Keys
+ -6, -4, 8, 123,
+ // Values
+ 2, 3, 5, 8
+ };
+ uint32_t correct_size = sizeof(correct_data);
+
+ address_map_.Store(-6, 2);
+ address_map_.Store(-4, 3);
+ address_map_.Store(8, 5);
+ address_map_.Store(123, 8);
+
+ serialized_data_ = serializer_.Serialize(address_map_, &serialized_size_);
+
+ EXPECT_EQ(correct_size, serialized_size_);
+ EXPECT_EQ(memcmp(correct_data, serialized_data_, correct_size), 0);
+}
+
+
+class TestRangeMapSerializer : public ::testing::Test {
+ protected:
+ void SetUp() {
+ serialized_size_ = 0;
+ serialized_data_ = 0;
+ }
+
+ void TearDown() {
+ delete [] serialized_data_;
+ }
+
+ google_breakpad::RangeMap<AddrType, EntryType> range_map_;
+ google_breakpad::RangeMapSerializer<AddrType, EntryType> serializer_;
+ uint32_t serialized_size_;
+ char *serialized_data_;
+};
+
+TEST_F(TestRangeMapSerializer, EmptyMapTestCase) {
+ const int32_t correct_data[] = { 0 };
+ uint32_t correct_size = sizeof(correct_data);
+
+ // range_map_ is empty.
+ serialized_data_ = serializer_.Serialize(range_map_, &serialized_size_);
+
+ EXPECT_EQ(correct_size, serialized_size_);
+ EXPECT_EQ(memcmp(correct_data, serialized_data_, correct_size), 0);
+}
+
+TEST_F(TestRangeMapSerializer, MapWithOneRangeTestCase) {
+ const int32_t correct_data[] = {
+ // # of nodes
+ 1,
+ // Offsets
+ 12,
+ // Keys: high address
+ 10,
+ // Values: (low address, entry) pairs
+ 1, 6
+ };
+ uint32_t correct_size = sizeof(correct_data);
+
+ range_map_.StoreRange(1, 10, 6);
+
+ serialized_data_ = serializer_.Serialize(range_map_, &serialized_size_);
+
+ EXPECT_EQ(correct_size, serialized_size_);
+ EXPECT_EQ(memcmp(correct_data, serialized_data_, correct_size), 0);
+}
+
+TEST_F(TestRangeMapSerializer, MapWithThreeRangesTestCase) {
+ const int32_t correct_data[] = {
+ // # of nodes
+ 3,
+ // Offsets
+ 28, 36, 44,
+ // Keys: high address
+ 5, 9, 20,
+ // Values: (low address, entry) pairs
+ 2, 1, 6, 2, 10, 3
+ };
+ uint32_t correct_size = sizeof(correct_data);
+
+ ASSERT_TRUE(range_map_.StoreRange(2, 4, 1));
+ ASSERT_TRUE(range_map_.StoreRange(6, 4, 2));
+ ASSERT_TRUE(range_map_.StoreRange(10, 11, 3));
+
+ serialized_data_ = serializer_.Serialize(range_map_, &serialized_size_);
+
+ EXPECT_EQ(correct_size, serialized_size_);
+ EXPECT_EQ(memcmp(correct_data, serialized_data_, correct_size), 0);
+}
+
+
+class TestContainedRangeMapSerializer : public ::testing::Test {
+ protected:
+ void SetUp() {
+ serialized_size_ = 0;
+ serialized_data_ = 0;
+ }
+
+ void TearDown() {
+ delete [] serialized_data_;
+ }
+
+ google_breakpad::ContainedRangeMap<AddrType, EntryType> crm_map_;
+ google_breakpad::ContainedRangeMapSerializer<AddrType, EntryType> serializer_;
+ uint32_t serialized_size_;
+ char *serialized_data_;
+};
+
+TEST_F(TestContainedRangeMapSerializer, EmptyMapTestCase) {
+ const int32_t correct_data[] = {
+ 0, // base address of root
+ 4, // size of entry
+ 0, // entry stored at root
+ 0 // empty map stored at root
+ };
+ uint32_t correct_size = sizeof(correct_data);
+
+ // crm_map_ is empty.
+ serialized_data_ = serializer_.Serialize(&crm_map_, &serialized_size_);
+
+ EXPECT_EQ(correct_size, serialized_size_);
+ EXPECT_EQ(memcmp(correct_data, serialized_data_, correct_size), 0);
+}
+
+TEST_F(TestContainedRangeMapSerializer, MapWithOneRangeTestCase) {
+ const int32_t correct_data[] = {
+ 0, // base address of root
+ 4, // size of entry
+ 0, // entry stored at root
+ // Map stored at root node:
+ 1, // # of nodes
+ 12, // offset
+ 9, // key
+ // value: a child ContainedRangeMap
+ 3, // base address of child CRM
+ 4, // size of entry
+ -1, // entry stored in child CRM
+ 0 // empty sub-map stored in child CRM
+ };
+ uint32_t correct_size = sizeof(correct_data);
+
+ crm_map_.StoreRange(3, 7, -1);
+
+ serialized_data_ = serializer_.Serialize(&crm_map_, &serialized_size_);
+
+ EXPECT_EQ(correct_size, serialized_size_);
+ EXPECT_EQ(memcmp(correct_data, serialized_data_, correct_size), 0);
+}
+
+TEST_F(TestContainedRangeMapSerializer, MapWithTwoLevelsTestCase) {
+ // Tree structure of ranges:
+ // root level 0
+ // |
+ // map
+ // / \ level 1: child1, child2
+ // 2~8 10~20
+ // | |
+ // map map
+ // / \ |
+ // 3~4 6~7 16-20 level 2: grandchild1, grandchild2, grandchild3
+
+ const int32_t correct_data[] = {
+ // root: base, entry_size, entry
+ 0, 4, 0,
+ // root's map: # of nodes, offset1, offset2, key1, key2
+ 2, 20, 84, 8, 20,
+ // child1: base, entry_size, entry:
+ 2, 4, -1,
+ // child1's map: # of nodes, offset1, offset2, key1, key2
+ 2, 20, 36, 4, 7,
+ // grandchild1: base, entry_size, entry, empty_map
+ 3, 4, -1, 0,
+ // grandchild2: base, entry_size, entry, empty_map
+ 6, 4, -1, 0,
+ // child2: base, entry_size, entry:
+ 10, 4, -1,
+ // child2's map: # of nodes, offset1, key1
+ 1, 12, 20,
+ // grandchild3: base, entry_size, entry, empty_map
+ 16, 4, -1, 0
+ };
+ uint32_t correct_size = sizeof(correct_data);
+
+ // Store child1.
+ ASSERT_TRUE(crm_map_.StoreRange(2, 7, -1));
+ // Store child2.
+ ASSERT_TRUE(crm_map_.StoreRange(10, 11, -1));
+ // Store grandchild1.
+ ASSERT_TRUE(crm_map_.StoreRange(3, 2, -1));
+ // Store grandchild2.
+ ASSERT_TRUE(crm_map_.StoreRange(6, 2, -1));
+ // Store grandchild3.
+ ASSERT_TRUE(crm_map_.StoreRange(16, 5, -1));
+
+ serialized_data_ = serializer_.Serialize(&crm_map_, &serialized_size_);
+
+ EXPECT_EQ(correct_size, serialized_size_);
+ EXPECT_EQ(memcmp(correct_data, serialized_data_, correct_size), 0);
+}
+
+
+int main(int argc, char *argv[]) {
+ ::testing::InitGoogleTest(&argc, argv);
+
+ return RUN_ALL_TESTS();
+}
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/microdump.cc b/toolkit/crashreporter/google-breakpad/src/processor/microdump.cc
new file mode 100644
index 0000000000..d8141a2a8f
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/microdump.cc
@@ -0,0 +1,405 @@
+// 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.
+
+// microdump.cc: A microdump reader.
+//
+// See microdump.h for documentation.
+
+#include "google_breakpad/processor/microdump.h"
+
+#include <stdio.h>
+#include <string.h>
+
+#include <memory>
+#include <sstream>
+#include <string>
+#include <vector>
+
+#include "google_breakpad/common/minidump_cpu_arm.h"
+#include "google_breakpad/processor/code_module.h"
+#include "processor/basic_code_module.h"
+#include "processor/convert_old_arm64_context.h"
+#include "processor/linked_ptr.h"
+#include "processor/logging.h"
+#include "processor/range_map-inl.h"
+
+namespace {
+static const char kGoogleBreakpadKey[] = "google-breakpad";
+static const char kMicrodumpBegin[] = "-----BEGIN BREAKPAD MICRODUMP-----";
+static const char kMicrodumpEnd[] = "-----END BREAKPAD MICRODUMP-----";
+static const char kOsKey[] = ": O ";
+static const char kCpuKey[] = ": C ";
+static const char kCrashReasonKey[] = ": R ";
+static const char kGpuKey[] = ": G ";
+static const char kMmapKey[] = ": M ";
+static const char kStackKey[] = ": S ";
+static const char kStackFirstLineKey[] = ": S 0 ";
+static const char kArmArchitecture[] = "arm";
+static const char kArm64Architecture[] = "arm64";
+static const char kX86Architecture[] = "x86";
+static const char kMipsArchitecture[] = "mips";
+static const char kMips64Architecture[] = "mips64";
+static const char kGpuUnknown[] = "UNKNOWN";
+
+template<typename T>
+T HexStrToL(const string& str) {
+ uint64_t res = 0;
+ std::istringstream ss(str);
+ ss >> std::hex >> res;
+ return static_cast<T>(res);
+}
+
+std::vector<uint8_t> ParseHexBuf(const string& str) {
+ std::vector<uint8_t> buf;
+ for (size_t i = 0; i < str.length(); i += 2) {
+ buf.push_back(HexStrToL<uint8_t>(str.substr(i, 2)));
+ }
+ return buf;
+}
+
+bool GetLine(std::istringstream* istream, string* str) {
+ if (std::getline(*istream, *str)) {
+ // Trim any trailing newline from the end of the line. Allows us
+ // to seamlessly handle both Windows/DOS and Unix formatted input. The
+ // adb tool generally writes logcat dumps in Windows/DOS format.
+ if (!str->empty() && str->at(str->size() - 1) == '\r') {
+ str->erase(str->size() - 1);
+ }
+ return true;
+ }
+ return false;
+}
+
+} // namespace
+
+namespace google_breakpad {
+
+//
+// MicrodumpModules
+//
+
+void MicrodumpModules::Add(const CodeModule* module) {
+ linked_ptr<const CodeModule> module_ptr(module);
+ if (!map_.StoreRange(module->base_address(), module->size(), module_ptr)) {
+ BPLOG(ERROR) << "Module " << module->code_file() <<
+ " could not be stored";
+ }
+}
+
+void MicrodumpModules::SetEnableModuleShrink(bool is_enabled) {
+ map_.SetMergeStrategy(is_enabled ? MergeRangeStrategy::kTruncateUpper
+ : MergeRangeStrategy::kExclusiveRanges);
+}
+
+//
+// MicrodumpContext
+//
+
+void MicrodumpContext::SetContextARM(MDRawContextARM* arm) {
+ DumpContext::SetContextFlags(MD_CONTEXT_ARM);
+ DumpContext::SetContextARM(arm);
+ valid_ = true;
+}
+
+void MicrodumpContext::SetContextARM64(MDRawContextARM64* arm64) {
+ DumpContext::SetContextFlags(MD_CONTEXT_ARM64);
+ DumpContext::SetContextARM64(arm64);
+ valid_ = true;
+}
+
+void MicrodumpContext::SetContextX86(MDRawContextX86* x86) {
+ DumpContext::SetContextFlags(MD_CONTEXT_X86);
+ DumpContext::SetContextX86(x86);
+ valid_ = true;
+}
+
+void MicrodumpContext::SetContextMIPS(MDRawContextMIPS* mips32) {
+ DumpContext::SetContextFlags(MD_CONTEXT_MIPS);
+ DumpContext::SetContextMIPS(mips32);
+ valid_ = true;
+}
+
+void MicrodumpContext::SetContextMIPS64(MDRawContextMIPS* mips64) {
+ DumpContext::SetContextFlags(MD_CONTEXT_MIPS64);
+ DumpContext::SetContextMIPS(mips64);
+ valid_ = true;
+}
+
+
+//
+// MicrodumpMemoryRegion
+//
+
+MicrodumpMemoryRegion::MicrodumpMemoryRegion() : base_address_(0) { }
+
+void MicrodumpMemoryRegion::Init(uint64_t base_address,
+ const std::vector<uint8_t>& contents) {
+ base_address_ = base_address;
+ contents_ = contents;
+}
+
+uint64_t MicrodumpMemoryRegion::GetBase() const { return base_address_; }
+
+uint32_t MicrodumpMemoryRegion::GetSize() const { return contents_.size(); }
+
+bool MicrodumpMemoryRegion::GetMemoryAtAddress(uint64_t address,
+ uint8_t* value) const {
+ return GetMemoryLittleEndian(address, value);
+}
+
+bool MicrodumpMemoryRegion::GetMemoryAtAddress(uint64_t address,
+ uint16_t* value) const {
+ return GetMemoryLittleEndian(address, value);
+}
+
+bool MicrodumpMemoryRegion::GetMemoryAtAddress(uint64_t address,
+ uint32_t* value) const {
+ return GetMemoryLittleEndian(address, value);
+}
+
+bool MicrodumpMemoryRegion::GetMemoryAtAddress(uint64_t address,
+ uint64_t* value) const {
+ return GetMemoryLittleEndian(address, value);
+}
+
+template<typename ValueType>
+bool MicrodumpMemoryRegion::GetMemoryLittleEndian(uint64_t address,
+ ValueType* value) const {
+ if (address < base_address_ ||
+ address - base_address_ + sizeof(ValueType) > contents_.size())
+ return false;
+ ValueType v = 0;
+ uint64_t start = address - base_address_;
+ // The loop condition is odd, but it's correct for size_t.
+ for (size_t i = sizeof(ValueType) - 1; i < sizeof(ValueType); i--)
+ v = (v << 8) | static_cast<uint8_t>(contents_[start + i]);
+ *value = v;
+ return true;
+}
+
+void MicrodumpMemoryRegion::Print() const {
+ // Not reached, just needed to honor the base class contract.
+ assert(false);
+}
+
+//
+// Microdump
+//
+Microdump::Microdump(const string& contents)
+ : context_(new MicrodumpContext()),
+ stack_region_(new MicrodumpMemoryRegion()),
+ modules_(new MicrodumpModules()),
+ system_info_(new SystemInfo()),
+ crash_reason_(),
+ crash_address_(0u) {
+ assert(!contents.empty());
+
+ bool in_microdump = false;
+ string line;
+ uint64_t stack_start = 0;
+ std::vector<uint8_t> stack_content;
+ string arch;
+
+ std::istringstream stream(contents);
+ while (GetLine(&stream, &line)) {
+ if (line.find(kGoogleBreakpadKey) == string::npos) {
+ continue;
+ }
+ if (line.find(kMicrodumpBegin) != string::npos) {
+ in_microdump = true;
+ continue;
+ }
+ if (!in_microdump) {
+ continue;
+ }
+ if (line.find(kMicrodumpEnd) != string::npos) {
+ break;
+ }
+
+ size_t pos;
+ if ((pos = line.find(kOsKey)) != string::npos) {
+ string os_str(line, pos + strlen(kOsKey));
+ std::istringstream os_tokens(os_str);
+ string os_id;
+ string num_cpus;
+ string os_version;
+ // This reflect the actual HW arch and might not match the arch emulated
+ // for the execution (e.g., running a 32-bit binary on a 64-bit cpu).
+ string hw_arch;
+
+ os_tokens >> os_id;
+ os_tokens >> arch;
+ os_tokens >> num_cpus;
+ os_tokens >> hw_arch;
+ GetLine(&os_tokens, &os_version);
+ os_version.erase(0, 1); // remove leading space.
+
+ system_info_->cpu = arch;
+ system_info_->cpu_count = HexStrToL<uint8_t>(num_cpus);
+ system_info_->os_version = os_version;
+
+ if (os_id == "L") {
+ system_info_->os = "Linux";
+ system_info_->os_short = "linux";
+ } else if (os_id == "A") {
+ system_info_->os = "Android";
+ system_info_->os_short = "android";
+ modules_->SetEnableModuleShrink(true);
+ }
+
+ // OS line also contains release and version for future use.
+ } else if ((pos = line.find(kStackKey)) != string::npos) {
+ if (line.find(kStackFirstLineKey) != string::npos) {
+ // The first line of the stack (S 0 stack header) provides the value of
+ // the stack pointer, the start address of the stack being dumped and
+ // the length of the stack. We could use it in future to double check
+ // that we received all the stack as expected.
+ continue;
+ }
+ string stack_str(line, pos + strlen(kStackKey));
+ std::istringstream stack_tokens(stack_str);
+ string start_addr_str;
+ string raw_content;
+ stack_tokens >> start_addr_str;
+ stack_tokens >> raw_content;
+ uint64_t start_addr = HexStrToL<uint64_t>(start_addr_str);
+
+ if (stack_start != 0) {
+ // Verify that the stack chunks in the microdump are contiguous.
+ assert(start_addr == stack_start + stack_content.size());
+ } else {
+ stack_start = start_addr;
+ }
+ std::vector<uint8_t> chunk = ParseHexBuf(raw_content);
+ stack_content.insert(stack_content.end(), chunk.begin(), chunk.end());
+
+ } else if ((pos = line.find(kCpuKey)) != string::npos) {
+ string cpu_state_str(line, pos + strlen(kCpuKey));
+ std::vector<uint8_t> cpu_state_raw = ParseHexBuf(cpu_state_str);
+ if (strcmp(arch.c_str(), kArmArchitecture) == 0) {
+ if (cpu_state_raw.size() != sizeof(MDRawContextARM)) {
+ std::cerr << "Malformed CPU context. Got " << cpu_state_raw.size()
+ << " bytes instead of " << sizeof(MDRawContextARM)
+ << std::endl;
+ continue;
+ }
+ MDRawContextARM* arm = new MDRawContextARM();
+ memcpy(arm, &cpu_state_raw[0], cpu_state_raw.size());
+ context_->SetContextARM(arm);
+ } else if (strcmp(arch.c_str(), kArm64Architecture) == 0) {
+ if (cpu_state_raw.size() == sizeof(MDRawContextARM64)) {
+ MDRawContextARM64* arm = new MDRawContextARM64();
+ memcpy(arm, &cpu_state_raw[0], cpu_state_raw.size());
+ context_->SetContextARM64(arm);
+ } else if (cpu_state_raw.size() == sizeof(MDRawContextARM64_Old)) {
+ MDRawContextARM64_Old old_arm;
+ memcpy(&old_arm, &cpu_state_raw[0], cpu_state_raw.size());
+ MDRawContextARM64* new_arm = new MDRawContextARM64();
+ ConvertOldARM64Context(old_arm, new_arm);
+ context_->SetContextARM64(new_arm);
+ } else {
+ std::cerr << "Malformed CPU context. Got " << cpu_state_raw.size()
+ << " bytes instead of " << sizeof(MDRawContextARM64)
+ << std::endl;
+ continue;
+ }
+ } else if (strcmp(arch.c_str(), kX86Architecture) == 0) {
+ if (cpu_state_raw.size() != sizeof(MDRawContextX86)) {
+ std::cerr << "Malformed CPU context. Got " << cpu_state_raw.size()
+ << " bytes instead of " << sizeof(MDRawContextX86)
+ << std::endl;
+ continue;
+ }
+ MDRawContextX86* x86 = new MDRawContextX86();
+ memcpy(x86, &cpu_state_raw[0], cpu_state_raw.size());
+ context_->SetContextX86(x86);
+ } else if (strcmp(arch.c_str(), kMipsArchitecture) == 0) {
+ if (cpu_state_raw.size() != sizeof(MDRawContextMIPS)) {
+ std::cerr << "Malformed CPU context. Got " << cpu_state_raw.size()
+ << " bytes instead of " << sizeof(MDRawContextMIPS)
+ << std::endl;
+ continue;
+ }
+ MDRawContextMIPS* mips32 = new MDRawContextMIPS();
+ memcpy(mips32, &cpu_state_raw[0], cpu_state_raw.size());
+ context_->SetContextMIPS(mips32);
+ } else if (strcmp(arch.c_str(), kMips64Architecture) == 0) {
+ if (cpu_state_raw.size() != sizeof(MDRawContextMIPS)) {
+ std::cerr << "Malformed CPU context. Got " << cpu_state_raw.size()
+ << " bytes instead of " << sizeof(MDRawContextMIPS)
+ << std::endl;
+ continue;
+ }
+ MDRawContextMIPS* mips64 = new MDRawContextMIPS();
+ memcpy(mips64, &cpu_state_raw[0], cpu_state_raw.size());
+ context_->SetContextMIPS64(mips64);
+ } else {
+ std::cerr << "Unsupported architecture: " << arch << std::endl;
+ }
+ } else if ((pos = line.find(kCrashReasonKey)) != string::npos) {
+ string crash_reason_str(line, pos + strlen(kCrashReasonKey));
+ std::istringstream crash_reason_tokens(crash_reason_str);
+ string signal;
+ string address;
+ crash_reason_tokens >> signal;
+ crash_reason_tokens >> crash_reason_;
+ crash_reason_tokens >> address;
+ crash_address_ = HexStrToL<uint64_t>(address);
+ } else if ((pos = line.find(kGpuKey)) != string::npos) {
+ string gpu_str(line, pos + strlen(kGpuKey));
+ if (strcmp(gpu_str.c_str(), kGpuUnknown) != 0) {
+ std::istringstream gpu_tokens(gpu_str);
+ std::getline(gpu_tokens, system_info_->gl_version, '|');
+ std::getline(gpu_tokens, system_info_->gl_vendor, '|');
+ std::getline(gpu_tokens, system_info_->gl_renderer, '|');
+ }
+ } else if ((pos = line.find(kMmapKey)) != string::npos) {
+ string mmap_line(line, pos + strlen(kMmapKey));
+ std::istringstream mmap_tokens(mmap_line);
+ string addr, offset, size, identifier, filename;
+ mmap_tokens >> addr;
+ mmap_tokens >> offset;
+ mmap_tokens >> size;
+ mmap_tokens >> identifier;
+ mmap_tokens >> filename;
+
+ modules_->Add(new BasicCodeModule(
+ HexStrToL<uint64_t>(addr), // base_address
+ HexStrToL<uint64_t>(size), // size
+ filename, // code_file
+ identifier, // code_identifier
+ filename, // debug_file
+ identifier, // debug_identifier
+ "")); // version
+ }
+ }
+ stack_region_->Init(stack_start, stack_content);
+}
+
+} // namespace google_breakpad
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/microdump_processor.cc b/toolkit/crashreporter/google-breakpad/src/processor/microdump_processor.cc
new file mode 100644
index 0000000000..2d3a9558a6
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/microdump_processor.cc
@@ -0,0 +1,97 @@
+// 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.
+
+// microdump_processor.cc: A microdump processor.
+//
+// See microdump_processor.h for documentation.
+
+#include "google_breakpad/processor/microdump_processor.h"
+
+#include <assert.h>
+
+#include <string>
+
+#include "common/using_std_string.h"
+#include "google_breakpad/processor/call_stack.h"
+#include "google_breakpad/processor/microdump.h"
+#include "google_breakpad/processor/process_state.h"
+#include "google_breakpad/processor/stackwalker.h"
+#include "google_breakpad/processor/stack_frame_symbolizer.h"
+#include "processor/logging.h"
+
+namespace google_breakpad {
+
+MicrodumpProcessor::MicrodumpProcessor(StackFrameSymbolizer* frame_symbolizer)
+ : frame_symbolizer_(frame_symbolizer) {
+ assert(frame_symbolizer);
+}
+
+MicrodumpProcessor::~MicrodumpProcessor() {}
+
+ProcessResult MicrodumpProcessor::Process(Microdump *microdump,
+ ProcessState* process_state) {
+ assert(process_state);
+
+ process_state->Clear();
+
+ process_state->modules_ = microdump->GetModules()->Copy();
+ scoped_ptr<Stackwalker> stackwalker(
+ Stackwalker::StackwalkerForCPU(
+ &process_state->system_info_,
+ microdump->GetContext(),
+ microdump->GetMemory(),
+ process_state->modules_,
+ /* unloaded_modules= */ NULL,
+ frame_symbolizer_));
+
+ scoped_ptr<CallStack> stack(new CallStack());
+ if (stackwalker.get()) {
+ if (!stackwalker->Walk(stack.get(),
+ &process_state->modules_without_symbols_,
+ &process_state->modules_with_corrupt_symbols_)) {
+ BPLOG(INFO) << "Processing was interrupted.";
+ return PROCESS_SYMBOL_SUPPLIER_INTERRUPTED;
+ }
+ } else {
+ BPLOG(ERROR) << "No stackwalker found for microdump.";
+ return PROCESS_ERROR_NO_THREAD_LIST;
+ }
+
+ process_state->threads_.push_back(stack.release());
+ process_state->thread_memory_regions_.push_back(microdump->GetMemory());
+ process_state->crashed_ = true;
+ process_state->requesting_thread_ = 0;
+ process_state->system_info_ = *microdump->GetSystemInfo();
+ process_state->crash_reason_ = microdump->GetCrashReason();
+ process_state->crash_address_ = microdump->GetCrashAddress();
+
+ return PROCESS_OK;
+}
+
+} // namespace google_breakpad
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/microdump_processor_unittest.cc b/toolkit/crashreporter/google-breakpad/src/processor/microdump_processor_unittest.cc
new file mode 100644
index 0000000000..83bdef9524
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/microdump_processor_unittest.cc
@@ -0,0 +1,285 @@
+// 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.
+
+// Unit test for MicrodumpProcessor.
+
+#include <fstream>
+#include <iostream>
+#include <string>
+#include <vector>
+
+#include "breakpad_googletest_includes.h"
+#include "google_breakpad/processor/basic_source_line_resolver.h"
+#include "google_breakpad/processor/call_stack.h"
+#include "google_breakpad/processor/microdump.h"
+#include "google_breakpad/processor/microdump_processor.h"
+#include "google_breakpad/processor/process_state.h"
+#include "google_breakpad/processor/stack_frame.h"
+#include "google_breakpad/processor/stack_frame_symbolizer.h"
+#include "processor/simple_symbol_supplier.h"
+#include "processor/stackwalker_unittest_utils.h"
+
+namespace {
+
+using google_breakpad::BasicSourceLineResolver;
+using google_breakpad::Microdump;
+using google_breakpad::MicrodumpProcessor;
+using google_breakpad::ProcessState;
+using google_breakpad::SimpleSymbolSupplier;
+using google_breakpad::StackFrameSymbolizer;
+
+class MicrodumpProcessorTest : public ::testing::Test {
+ public:
+ MicrodumpProcessorTest()
+ : files_path_(string(getenv("srcdir") ? getenv("srcdir") : ".") +
+ "/src/processor/testdata/") {
+ }
+
+ void ReadFile(const string& file_name, string* file_contents) {
+ assert(file_contents);
+ std::ifstream file_stream(file_name.c_str(), std::ios::in);
+ ASSERT_TRUE(file_stream.good());
+ std::vector<char> bytes;
+ file_stream.seekg(0, std::ios_base::end);
+ ASSERT_TRUE(file_stream.good());
+ bytes.resize(file_stream.tellg());
+ file_stream.seekg(0, std::ios_base::beg);
+ ASSERT_TRUE(file_stream.good());
+ file_stream.read(&bytes[0], bytes.size());
+ ASSERT_TRUE(file_stream.good());
+ *file_contents = string(&bytes[0], bytes.size());
+ }
+
+ google_breakpad::ProcessResult ProcessMicrodump(
+ const string& symbols_file,
+ const string& microdump_contents,
+ ProcessState* state) {
+ SimpleSymbolSupplier supplier(symbols_file);
+ BasicSourceLineResolver resolver;
+ StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
+ MicrodumpProcessor processor(&frame_symbolizer);
+
+ Microdump microdump(microdump_contents);
+ return processor.Process(&microdump, state);
+ }
+
+ void AnalyzeDump(const string& microdump_file_name, bool omit_symbols,
+ int expected_cpu_count, ProcessState* state) {
+ string symbols_file = omit_symbols ? "" : files_path_ + "symbols/microdump";
+ string microdump_file_path = files_path_ + microdump_file_name;
+ string microdump_contents;
+ ReadFile(microdump_file_path, &microdump_contents);
+
+ google_breakpad::ProcessResult result =
+ ProcessMicrodump(symbols_file, microdump_contents, state);
+
+ ASSERT_EQ(google_breakpad::PROCESS_OK, result);
+ ASSERT_TRUE(state->crashed());
+ ASSERT_EQ(0, state->requesting_thread());
+ ASSERT_EQ(1U, state->threads()->size());
+
+ ASSERT_EQ(expected_cpu_count, state->system_info()->cpu_count);
+ ASSERT_EQ("android", state->system_info()->os_short);
+ ASSERT_EQ("Android", state->system_info()->os);
+ }
+
+ string files_path_;
+};
+
+TEST_F(MicrodumpProcessorTest, TestProcess_Invalid) {
+ ProcessState state;
+ google_breakpad::ProcessResult result =
+ ProcessMicrodump("", "This is not a valid microdump", &state);
+ ASSERT_EQ(google_breakpad::PROCESS_ERROR_NO_THREAD_LIST, result);
+}
+
+TEST_F(MicrodumpProcessorTest, TestProcess_WithoutCrashReason) {
+ ProcessState state;
+ AnalyzeDump("microdump-arm64.dmp", true /* omit_symbols */,
+ 2 /* expected_cpu_count */, &state);
+ ASSERT_EQ(state.crash_reason(), "");
+ ASSERT_EQ(state.crash_address(), 0x0u);
+}
+
+TEST_F(MicrodumpProcessorTest, TestProcess_WithCrashReason) {
+ ProcessState state;
+ AnalyzeDump("microdump-withcrashreason.dmp", true /* omit_symbols */,
+ 8 /* expected_cpu_count */, &state);
+ ASSERT_EQ(state.crash_reason(), "SIGTRAP");
+ ASSERT_EQ(state.crash_address(), 0x4A7CB000u);
+}
+
+TEST_F(MicrodumpProcessorTest, TestProcess_MissingSymbols) {
+ ProcessState state;
+ AnalyzeDump("microdump-arm64.dmp", true /* omit_symbols */,
+ 2 /* expected_cpu_count */, &state);
+
+ ASSERT_EQ(8U, state.modules()->module_count());
+ ASSERT_EQ("arm64", state.system_info()->cpu);
+ ASSERT_EQ("OS 64 VERSION INFO", state.system_info()->os_version);
+ ASSERT_EQ(1U, state.threads()->size());
+ ASSERT_EQ(11U, state.threads()->at(0)->frames()->size());
+
+ ASSERT_EQ("",
+ state.threads()->at(0)->frames()->at(0)->function_name);
+ ASSERT_EQ("",
+ state.threads()->at(0)->frames()->at(3)->function_name);
+}
+
+TEST_F(MicrodumpProcessorTest, TestProcess_UnsupportedArch) {
+ string microdump_contents =
+ "W/google-breakpad(26491): -----BEGIN BREAKPAD MICRODUMP-----\n"
+ "W/google-breakpad(26491): O A \"unsupported-arch\"\n"
+ "W/google-breakpad(26491): S 0 A48BD840 A48BD000 00002000\n";
+
+ ProcessState state;
+
+ google_breakpad::ProcessResult result =
+ ProcessMicrodump("", microdump_contents, &state);
+
+ ASSERT_EQ(google_breakpad::PROCESS_ERROR_NO_THREAD_LIST, result);
+}
+
+TEST_F(MicrodumpProcessorTest, TestProcessArm) {
+ ProcessState state;
+ AnalyzeDump("microdump-arm.dmp", false /* omit_symbols */,
+ 2 /* expected_cpu_count*/, &state);
+
+ ASSERT_EQ(6U, state.modules()->module_count());
+ ASSERT_EQ("arm", state.system_info()->cpu);
+ ASSERT_EQ("OpenGL ES 3.0 V@104.0 AU@ (GIT@Id3510ff6dc)",
+ state.system_info()->gl_version);
+ ASSERT_EQ("Qualcomm", state.system_info()->gl_vendor);
+ ASSERT_EQ("Adreno (TM) 330", state.system_info()->gl_renderer);
+ ASSERT_EQ("OS VERSION INFO", state.system_info()->os_version);
+ ASSERT_EQ(8U, state.threads()->at(0)->frames()->size());
+ ASSERT_EQ("MicrodumpWriterTest_Setup_Test::TestBody",
+ state.threads()->at(0)->frames()->at(0)->function_name);
+ ASSERT_EQ("testing::Test::Run",
+ state.threads()->at(0)->frames()->at(1)->function_name);
+ ASSERT_EQ("main",
+ state.threads()->at(0)->frames()->at(6)->function_name);
+ ASSERT_EQ("breakpad_unittests",
+ state.threads()->at(0)->frames()->at(6)->module->code_file());
+}
+
+TEST_F(MicrodumpProcessorTest, TestProcessArm64) {
+ ProcessState state;
+ AnalyzeDump("microdump-arm64.dmp", false /* omit_symbols */,
+ 2 /* expected_cpu_count*/, &state);
+
+ ASSERT_EQ(8U, state.modules()->module_count());
+ ASSERT_EQ("arm64", state.system_info()->cpu);
+ ASSERT_EQ("OS 64 VERSION INFO", state.system_info()->os_version);
+ ASSERT_EQ(9U, state.threads()->at(0)->frames()->size());
+ ASSERT_EQ("MicrodumpWriterTest_Setup_Test::TestBody",
+ state.threads()->at(0)->frames()->at(0)->function_name);
+ ASSERT_EQ("testing::Test::Run",
+ state.threads()->at(0)->frames()->at(2)->function_name);
+ ASSERT_EQ("main",
+ state.threads()->at(0)->frames()->at(7)->function_name);
+ ASSERT_EQ("breakpad_unittests",
+ state.threads()->at(0)->frames()->at(7)->module->code_file());
+}
+
+TEST_F(MicrodumpProcessorTest, TestProcessX86) {
+ ProcessState state;
+ AnalyzeDump("microdump-x86.dmp", false /* omit_symbols */,
+ 4 /* expected_cpu_count */, &state);
+
+ ASSERT_EQ(124U, state.modules()->module_count());
+ ASSERT_EQ("x86", state.system_info()->cpu);
+ ASSERT_EQ("asus/WW_Z00A/Z00A:5.0/LRX21V/2.19.40.22_20150627_5104_user:user/"
+ "release-keys", state.system_info()->os_version);
+ ASSERT_EQ(17U, state.threads()->at(0)->frames()->size());
+ ASSERT_EQ("libc.so",
+ state.threads()->at(0)->frames()->at(0)->module->debug_file());
+ // TODO(mmandlis): Get symbols for the test X86 microdump and test function
+ // names.
+}
+
+TEST_F(MicrodumpProcessorTest, TestProcessMultiple) {
+ ProcessState state;
+ AnalyzeDump("microdump-multiple.dmp", false /* omit_symbols */,
+ 6 /* expected_cpu_count */, &state);
+ ASSERT_EQ(156U, state.modules()->module_count());
+ ASSERT_EQ("arm", state.system_info()->cpu);
+ ASSERT_EQ("lge/p1_tmo_us/p1:6.0/MRA58K/1603210524c8d:user/release-keys",
+ state.system_info()->os_version);
+ ASSERT_EQ(5U, state.threads()->at(0)->frames()->size());
+}
+
+TEST_F(MicrodumpProcessorTest, TestProcessMips) {
+ ProcessState state;
+ AnalyzeDump("microdump-mips32.dmp", false /* omit_symbols */,
+ 2 /* expected_cpu_count */, &state);
+
+ ASSERT_EQ(7U, state.modules()->module_count());
+ ASSERT_EQ("mips", state.system_info()->cpu);
+ ASSERT_EQ("3.0.8-g893bf16 #7 SMP PREEMPT Fri Jul 10 15:20:59 PDT 2015",
+ state.system_info()->os_version);
+ ASSERT_EQ(4U, state.threads()->at(0)->frames()->size());
+
+ ASSERT_EQ("blaTest",
+ state.threads()->at(0)->frames()->at(0)->function_name);
+ ASSERT_EQ("Crash",
+ state.threads()->at(0)->frames()->at(1)->function_name);
+ ASSERT_EQ("main",
+ state.threads()->at(0)->frames()->at(2)->function_name);
+ ASSERT_EQ("crash_example",
+ state.threads()->at(0)->frames()->at(0)->module->debug_file());
+}
+
+TEST_F(MicrodumpProcessorTest, TestProcessMips64) {
+ ProcessState state;
+ AnalyzeDump("microdump-mips64.dmp", false /* omit_symbols */,
+ 1 /* expected_cpu_count */, &state);
+
+ ASSERT_EQ(8U, state.modules()->module_count());
+ ASSERT_EQ("mips64", state.system_info()->cpu);
+ ASSERT_EQ("3.10.0-gf185e20 #112 PREEMPT Mon Oct 5 11:12:49 PDT 2015",
+ state.system_info()->os_version);
+ ASSERT_EQ(4U, state.threads()->at(0)->frames()->size());
+
+ ASSERT_EQ("blaTest",
+ state.threads()->at(0)->frames()->at(0)->function_name);
+ ASSERT_EQ("Crash",
+ state.threads()->at(0)->frames()->at(1)->function_name);
+ ASSERT_EQ("main",
+ state.threads()->at(0)->frames()->at(2)->function_name);
+ ASSERT_EQ("crash_example",
+ state.threads()->at(0)->frames()->at(0)->module->debug_file());
+}
+
+} // namespace
+
+int main(int argc, char* argv[]) {
+ ::testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/microdump_stackwalk.cc b/toolkit/crashreporter/google-breakpad/src/processor/microdump_stackwalk.cc
new file mode 100644
index 0000000000..220396ed93
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/microdump_stackwalk.cc
@@ -0,0 +1,181 @@
+// 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.
+
+// microdump_stackwalk.cc: Process a microdump with MicrodumpProcessor, printing
+// the results, including stack traces.
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <fstream>
+#include <string>
+#include <vector>
+
+#include "common/path_helper.h"
+#include "common/scoped_ptr.h"
+#include "common/using_std_string.h"
+#include "google_breakpad/processor/basic_source_line_resolver.h"
+#include "google_breakpad/processor/microdump.h"
+#include "google_breakpad/processor/microdump_processor.h"
+#include "google_breakpad/processor/process_state.h"
+#include "google_breakpad/processor/stack_frame_symbolizer.h"
+#include "processor/logging.h"
+#include "processor/simple_symbol_supplier.h"
+#include "processor/stackwalk_common.h"
+
+
+namespace {
+
+struct Options {
+ bool machine_readable;
+ bool output_stack_contents;
+
+ string microdump_file;
+ std::vector<string> symbol_paths;
+};
+
+using google_breakpad::BasicSourceLineResolver;
+using google_breakpad::Microdump;
+using google_breakpad::MicrodumpProcessor;
+using google_breakpad::ProcessResult;
+using google_breakpad::ProcessState;
+using google_breakpad::scoped_ptr;
+using google_breakpad::SimpleSymbolSupplier;
+using google_breakpad::StackFrameSymbolizer;
+
+// Processes |options.microdump_file| using
+// MicrodumpProcessor. |options.symbol_path|, if non-empty, is the
+// base directory of a symbol storage area, laid out in the format
+// required by SimpleSymbolSupplier. If such a storage area is
+// specified, it is made available for use by the MicrodumpProcessor.
+//
+// Returns the value of MicrodumpProcessor::Process. If processing succeeds,
+// prints identifying OS and CPU information from the microdump, crash
+// information and call stacks for the crashing thread.
+// All information is printed to stdout.
+int PrintMicrodumpProcess(const Options& options) {
+ std::ifstream file_stream(options.microdump_file);
+ std::vector<char> bytes;
+ file_stream.seekg(0, std::ios_base::end);
+ bytes.resize(file_stream.tellg());
+ if (bytes.empty()) {
+ BPLOG(ERROR) << "Microdump is empty.";
+ return 1;
+ }
+ file_stream.seekg(0, std::ios_base::beg);
+ file_stream.read(&bytes[0], bytes.size());
+ string microdump_content(&bytes[0], bytes.size());
+
+ scoped_ptr<SimpleSymbolSupplier> symbol_supplier;
+ if (!options.symbol_paths.empty()) {
+ symbol_supplier.reset(new SimpleSymbolSupplier(options.symbol_paths));
+ }
+
+ BasicSourceLineResolver resolver;
+ StackFrameSymbolizer frame_symbolizer(symbol_supplier.get(), &resolver);
+ ProcessState process_state;
+ MicrodumpProcessor microdump_processor(&frame_symbolizer);
+ Microdump microdump(microdump_content);
+ ProcessResult res = microdump_processor.Process(&microdump,
+ &process_state);
+
+ if (res == google_breakpad::PROCESS_OK) {
+ if (options.machine_readable) {
+ PrintProcessStateMachineReadable(process_state);
+ } else {
+ PrintProcessState(process_state, options.output_stack_contents, &resolver);
+ }
+ return 0;
+ }
+
+ BPLOG(ERROR) << "MicrodumpProcessor::Process failed (code = " << res << ")";
+ return 1;
+}
+
+} // namespace
+
+static void Usage(int argc, const char *argv[], bool error) {
+ fprintf(error ? stderr : stdout,
+ "Usage: %s [options] <microdump-file> [symbol-path ...]\n"
+ "\n"
+ "Output a stack trace for the provided microdump\n"
+ "\n"
+ "Options:\n"
+ "\n"
+ " -m Output in machine-readable format\n"
+ " -s Output stack contents\n",
+ google_breakpad::BaseName(argv[0]).c_str());
+}
+
+static void SetupOptions(int argc, const char *argv[], Options* options) {
+ int ch;
+
+ options->machine_readable = false;
+ options->output_stack_contents = false;
+
+ while ((ch = getopt(argc, (char * const *)argv, "hms")) != -1) {
+ switch (ch) {
+ case 'h':
+ Usage(argc, argv, false);
+ exit(0);
+ break;
+
+ case 'm':
+ options->machine_readable = true;
+ break;
+ case 's':
+ options->output_stack_contents = true;
+ break;
+
+ case '?':
+ Usage(argc, argv, true);
+ exit(1);
+ break;
+ }
+ }
+
+ if ((argc - optind) == 0) {
+ fprintf(stderr, "%s: Missing microdump file\n", argv[0]);
+ Usage(argc, argv, true);
+ exit(1);
+ }
+
+ options->microdump_file = argv[optind];
+
+ for (int argi = optind + 1; argi < argc; ++argi)
+ options->symbol_paths.push_back(argv[argi]);
+}
+
+int main(int argc, const char* argv[]) {
+ Options options;
+ SetupOptions(argc, argv, &options);
+
+ return PrintMicrodumpProcess(options);
+}
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/microdump_stackwalk_machine_readable_test b/toolkit/crashreporter/google-breakpad/src/processor/microdump_stackwalk_machine_readable_test
new file mode 100755
index 0000000000..f5614e20f2
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/microdump_stackwalk_machine_readable_test
@@ -0,0 +1,43 @@
+#!/bin/sh
+
+# 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.
+
+. "${0%/*}/microdump_stackwalk_test_vars" || exit 1 # for MICRODUMP_SUPPORTED_ARCHS.
+testdata_dir=$srcdir/src/processor/testdata
+
+set -e # Bail out with an error if any of the commands below fails.
+for ARCH in $MICRODUMP_SUPPORTED_ARCHS; do
+ echo "Testing microdump_stackwalk -m for arch $ARCH"
+ ./src/processor/microdump_stackwalk -m $testdata_dir/microdump-${ARCH}.dmp \
+ $testdata_dir/symbols/microdump | \
+ tr -d '\015' | \
+ diff -u $testdata_dir/microdump.stackwalk.machine_readable-${ARCH}.out -
+done
+exit 0
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/microdump_stackwalk_test b/toolkit/crashreporter/google-breakpad/src/processor/microdump_stackwalk_test
new file mode 100755
index 0000000000..e189765660
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/microdump_stackwalk_test
@@ -0,0 +1,43 @@
+#!/bin/sh
+
+# 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.
+
+. "${0%/*}/microdump_stackwalk_test_vars" || exit 1 # for MICRODUMP_SUPPORTED_ARCHS.
+testdata_dir=$srcdir/src/processor/testdata
+
+set -e # Bail out with an error if any of the commands below fails.
+for ARCH in $MICRODUMP_SUPPORTED_ARCHS; do
+ echo "Testing microdump_stackwalk for arch $ARCH"
+ ./src/processor/microdump_stackwalk $testdata_dir/microdump-${ARCH}.dmp \
+ $testdata_dir/symbols/microdump | \
+ tr -d '\015' | \
+ diff -u $testdata_dir/microdump.stackwalk-${ARCH}.out -
+done
+exit 0
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/microdump_stackwalk_test_vars b/toolkit/crashreporter/google-breakpad/src/processor/microdump_stackwalk_test_vars
new file mode 100644
index 0000000000..a8b0e0df5a
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/microdump_stackwalk_test_vars
@@ -0,0 +1 @@
+MICRODUMP_SUPPORTED_ARCHS="arm arm64"
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/minidump.cc b/toolkit/crashreporter/google-breakpad/src/processor/minidump.cc
new file mode 100644
index 0000000000..3ba2437af3
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/minidump.cc
@@ -0,0 +1,6445 @@
+// Copyright (c) 2010 Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// minidump.cc: A minidump reader.
+//
+// See minidump.h for documentation.
+//
+// Author: Mark Mentovai
+
+#include "google_breakpad/processor/minidump.h"
+
+#include <assert.h>
+#include <fcntl.h>
+#include <stddef.h>
+#include <string.h>
+#include <time.h>
+
+#ifdef _WIN32
+#include <io.h>
+#else // _WIN32
+#include <unistd.h>
+#endif // _WIN32
+
+#include <algorithm>
+#include <fstream>
+#include <limits>
+#include <utility>
+
+#include "processor/range_map-inl.h"
+
+#include "common/macros.h"
+#include "common/scoped_ptr.h"
+#include "common/stdio_wrapper.h"
+#include "google_breakpad/processor/dump_context.h"
+#include "processor/basic_code_module.h"
+#include "processor/basic_code_modules.h"
+#include "processor/convert_old_arm64_context.h"
+#include "processor/logging.h"
+
+namespace google_breakpad {
+
+using std::istream;
+using std::ifstream;
+using std::numeric_limits;
+using std::vector;
+
+namespace {
+
+// Returns true iff |context_size| matches exactly one of the sizes of the
+// various MDRawContext* types.
+// TODO(blundell): This function can be removed once
+// https://bugs.chromium.org/p/google-breakpad/issues/detail?id=550 is fixed.
+bool IsContextSizeUnique(uint32_t context_size) {
+ int num_matching_contexts = 0;
+ if (context_size == sizeof(MDRawContextX86))
+ num_matching_contexts++;
+ if (context_size == sizeof(MDRawContextPPC))
+ num_matching_contexts++;
+ if (context_size == sizeof(MDRawContextPPC64))
+ num_matching_contexts++;
+ if (context_size == sizeof(MDRawContextAMD64))
+ num_matching_contexts++;
+ if (context_size == sizeof(MDRawContextSPARC))
+ num_matching_contexts++;
+ if (context_size == sizeof(MDRawContextARM))
+ num_matching_contexts++;
+ if (context_size == sizeof(MDRawContextARM64))
+ num_matching_contexts++;
+ if (context_size == sizeof(MDRawContextARM64_Old))
+ num_matching_contexts++;
+ if (context_size == sizeof(MDRawContextMIPS))
+ num_matching_contexts++;
+ return num_matching_contexts == 1;
+}
+
+//
+// Swapping routines
+//
+// Inlining these doesn't increase code size significantly, and it saves
+// a whole lot of unnecessary jumping back and forth.
+//
+
+
+// Swapping an 8-bit quantity is a no-op. This function is only provided
+// to account for certain templatized operations that require swapping for
+// wider types but handle uint8_t too
+// (MinidumpMemoryRegion::GetMemoryAtAddressInternal).
+inline void Swap(uint8_t* value) {}
+
+// Optimization: don't need to AND the furthest right shift, because we're
+// shifting an unsigned quantity. The standard requires zero-filling in this
+// case. If the quantities were signed, a bitmask whould be needed for this
+// right shift to avoid an arithmetic shift (which retains the sign bit).
+// The furthest left shift never needs to be ANDed bitmask.
+
+inline void Swap(uint16_t* value) {
+ *value = (*value >> 8) | (*value << 8);
+}
+
+inline void Swap(uint32_t* value) {
+ *value = (*value >> 24) |
+ ((*value >> 8) & 0x0000ff00) |
+ ((*value << 8) & 0x00ff0000) |
+ (*value << 24);
+}
+
+inline void Swap(uint64_t* value) {
+ uint32_t* value32 = reinterpret_cast<uint32_t*>(value);
+ Swap(&value32[0]);
+ Swap(&value32[1]);
+ uint32_t temp = value32[0];
+ value32[0] = value32[1];
+ value32[1] = temp;
+}
+
+
+// Given a pointer to a 128-bit int in the minidump data, set the "low"
+// and "high" fields appropriately.
+void Normalize128(uint128_struct* value, bool is_big_endian) {
+ // The struct format is [high, low], so if the format is big-endian,
+ // the most significant bytes will already be in the high field.
+ if (!is_big_endian) {
+ uint64_t temp = value->low;
+ value->low = value->high;
+ value->high = temp;
+ }
+}
+
+// This just swaps each int64 half of the 128-bit value.
+// The value should also be normalized by calling Normalize128().
+void Swap(uint128_struct* value) {
+ Swap(&value->low);
+ Swap(&value->high);
+}
+
+// Swapping signed integers
+inline void Swap(int32_t* value) {
+ Swap(reinterpret_cast<uint32_t*>(value));
+}
+
+inline void Swap(MDLocationDescriptor* location_descriptor) {
+ Swap(&location_descriptor->data_size);
+ Swap(&location_descriptor->rva);
+}
+
+inline void Swap(MDMemoryDescriptor* memory_descriptor) {
+ Swap(&memory_descriptor->start_of_memory_range);
+ Swap(&memory_descriptor->memory);
+}
+
+inline void Swap(MDGUID* guid) {
+ Swap(&guid->data1);
+ Swap(&guid->data2);
+ Swap(&guid->data3);
+ // Don't swap guid->data4[] because it contains 8-bit quantities.
+}
+
+inline void Swap(MDSystemTime* system_time) {
+ Swap(&system_time->year);
+ Swap(&system_time->month);
+ Swap(&system_time->day_of_week);
+ Swap(&system_time->day);
+ Swap(&system_time->hour);
+ Swap(&system_time->minute);
+ Swap(&system_time->second);
+ Swap(&system_time->milliseconds);
+}
+
+inline void Swap(MDXStateFeature* xstate_feature) {
+ Swap(&xstate_feature->offset);
+ Swap(&xstate_feature->size);
+}
+
+inline void Swap(MDXStateConfigFeatureMscInfo* xstate_feature_info) {
+ Swap(&xstate_feature_info->size_of_info);
+ Swap(&xstate_feature_info->context_size);
+ Swap(&xstate_feature_info->enabled_features);
+
+ for (size_t i = 0; i < MD_MAXIMUM_XSTATE_FEATURES; i++) {
+ Swap(&xstate_feature_info->features[i]);
+ }
+}
+
+inline void Swap(MDRawSimpleStringDictionaryEntry* entry) {
+ Swap(&entry->key);
+ Swap(&entry->value);
+}
+
+inline void Swap(uint16_t* data, size_t size_in_bytes) {
+ size_t data_length = size_in_bytes / sizeof(data[0]);
+ for (size_t i = 0; i < data_length; i++) {
+ Swap(&data[i]);
+ }
+}
+
+//
+// Character conversion routines
+//
+
+
+// Standard wide-character conversion routines depend on the system's own
+// idea of what width a wide character should be: some use 16 bits, and
+// some use 32 bits. For the purposes of a minidump, wide strings are
+// always represented with 16-bit UTF-16 chracters. iconv isn't available
+// everywhere, and its interface varies where it is available. iconv also
+// deals purely with char* pointers, so in addition to considering the swap
+// parameter, a converter that uses iconv would also need to take the host
+// CPU's endianness into consideration. It doesn't seems worth the trouble
+// of making it a dependency when we don't care about anything but UTF-16.
+string* UTF16ToUTF8(const vector<uint16_t>& in, bool swap) {
+ scoped_ptr<string> out(new string());
+
+ // Set the string's initial capacity to the number of UTF-16 characters,
+ // because the UTF-8 representation will always be at least this long.
+ // If the UTF-8 representation is longer, the string will grow dynamically.
+ out->reserve(in.size());
+
+ for (vector<uint16_t>::const_iterator iterator = in.begin();
+ iterator != in.end();
+ ++iterator) {
+ // Get a 16-bit value from the input
+ uint16_t in_word = *iterator;
+ if (swap)
+ Swap(&in_word);
+
+ // Convert the input value (in_word) into a Unicode code point (unichar).
+ uint32_t unichar;
+ if (in_word >= 0xdc00 && in_word <= 0xdcff) {
+ BPLOG(ERROR) << "UTF16ToUTF8 found low surrogate " <<
+ HexString(in_word) << " without high";
+ return NULL;
+ } else if (in_word >= 0xd800 && in_word <= 0xdbff) {
+ // High surrogate.
+ unichar = (in_word - 0xd7c0) << 10;
+ if (++iterator == in.end()) {
+ BPLOG(ERROR) << "UTF16ToUTF8 found high surrogate " <<
+ HexString(in_word) << " at end of string";
+ return NULL;
+ }
+ uint32_t high_word = in_word;
+ in_word = *iterator;
+ if (in_word < 0xdc00 || in_word > 0xdcff) {
+ BPLOG(ERROR) << "UTF16ToUTF8 found high surrogate " <<
+ HexString(high_word) << " without low " <<
+ HexString(in_word);
+ return NULL;
+ }
+ unichar |= in_word & 0x03ff;
+ } else {
+ // The ordinary case, a single non-surrogate Unicode character encoded
+ // as a single 16-bit value.
+ unichar = in_word;
+ }
+
+ // Convert the Unicode code point (unichar) into its UTF-8 representation,
+ // appending it to the out string.
+ if (unichar < 0x80) {
+ (*out) += static_cast<char>(unichar);
+ } else if (unichar < 0x800) {
+ (*out) += 0xc0 | static_cast<char>(unichar >> 6);
+ (*out) += 0x80 | static_cast<char>(unichar & 0x3f);
+ } else if (unichar < 0x10000) {
+ (*out) += 0xe0 | static_cast<char>(unichar >> 12);
+ (*out) += 0x80 | static_cast<char>((unichar >> 6) & 0x3f);
+ (*out) += 0x80 | static_cast<char>(unichar & 0x3f);
+ } else if (unichar < 0x200000) {
+ (*out) += 0xf0 | static_cast<char>(unichar >> 18);
+ (*out) += 0x80 | static_cast<char>((unichar >> 12) & 0x3f);
+ (*out) += 0x80 | static_cast<char>((unichar >> 6) & 0x3f);
+ (*out) += 0x80 | static_cast<char>(unichar & 0x3f);
+ } else {
+ BPLOG(ERROR) << "UTF16ToUTF8 cannot represent high value " <<
+ HexString(unichar) << " in UTF-8";
+ return NULL;
+ }
+ }
+
+ return out.release();
+}
+
+// Return the smaller of the number of code units in the UTF-16 string,
+// not including the terminating null word, or maxlen.
+size_t UTF16codeunits(const uint16_t* string, size_t maxlen) {
+ size_t count = 0;
+ while (count < maxlen && string[count] != 0)
+ count++;
+ return count;
+}
+
+inline void Swap(MDTimeZoneInformation* time_zone) {
+ Swap(&time_zone->bias);
+ // Skip time_zone->standard_name. No need to swap UTF-16 fields.
+ // The swap will be done as part of the conversion to UTF-8.
+ Swap(&time_zone->standard_date);
+ Swap(&time_zone->standard_bias);
+ // Skip time_zone->daylight_name. No need to swap UTF-16 fields.
+ // The swap will be done as part of the conversion to UTF-8.
+ Swap(&time_zone->daylight_date);
+ Swap(&time_zone->daylight_bias);
+}
+
+void ConvertUTF16BufferToUTF8String(const uint16_t* utf16_data,
+ size_t max_length_in_bytes,
+ string* utf8_result,
+ bool swap) {
+ // Since there is no explicit byte length for each string, use
+ // UTF16codeunits to calculate word length, then derive byte
+ // length from that.
+ size_t max_word_length = max_length_in_bytes / sizeof(utf16_data[0]);
+ size_t word_length = UTF16codeunits(utf16_data, max_word_length);
+ if (word_length > 0) {
+ size_t byte_length = word_length * sizeof(utf16_data[0]);
+ vector<uint16_t> utf16_vector(word_length);
+ memcpy(&utf16_vector[0], &utf16_data[0], byte_length);
+ scoped_ptr<string> temp(UTF16ToUTF8(utf16_vector, swap));
+ if (temp.get()) {
+ utf8_result->assign(*temp);
+ }
+ } else {
+ utf8_result->clear();
+ }
+}
+
+
+// For fields that may or may not be valid, PrintValueOrInvalid will print the
+// string "(invalid)" if the field is not valid, and will print the value if
+// the field is valid. The value is printed as hexadecimal or decimal.
+
+enum NumberFormat {
+ kNumberFormatDecimal,
+ kNumberFormatHexadecimal,
+};
+
+void PrintValueOrInvalid(bool valid,
+ NumberFormat number_format,
+ uint32_t value) {
+ if (!valid) {
+ printf("(invalid)\n");
+ } else if (number_format == kNumberFormatDecimal) {
+ printf("%d\n", value);
+ } else {
+ printf("0x%x\n", value);
+ }
+}
+
+// Converts a time_t to a string showing the time in UTC.
+string TimeTToUTCString(time_t tt) {
+ struct tm timestruct;
+#ifdef _WIN32
+ gmtime_s(&timestruct, &tt);
+#else
+ gmtime_r(&tt, &timestruct);
+#endif
+
+ char timestr[20];
+ size_t rv = strftime(timestr, 20, "%Y-%m-%d %H:%M:%S", &timestruct);
+ if (rv == 0) {
+ return string();
+ }
+
+ return string(timestr);
+}
+
+string MDGUIDToString(const MDGUID& uuid) {
+ char buf[37];
+ snprintf(buf, sizeof(buf), "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+ uuid.data1,
+ uuid.data2,
+ uuid.data3,
+ uuid.data4[0],
+ uuid.data4[1],
+ uuid.data4[2],
+ uuid.data4[3],
+ uuid.data4[4],
+ uuid.data4[5],
+ uuid.data4[6],
+ uuid.data4[7]);
+ return std::string(buf);
+}
+
+bool IsDevAshmem(const string& filename) {
+ const string kDevAshmem("/dev/ashmem/");
+ return filename.compare(0, kDevAshmem.length(), kDevAshmem) == 0;
+}
+
+} // namespace
+
+//
+// MinidumpObject
+//
+
+
+MinidumpObject::MinidumpObject(Minidump* minidump)
+ : DumpObject(),
+ minidump_(minidump) {
+}
+
+
+//
+// MinidumpStream
+//
+
+
+MinidumpStream::MinidumpStream(Minidump* minidump)
+ : MinidumpObject(minidump) {
+}
+
+
+//
+// MinidumpContext
+//
+
+
+MinidumpContext::MinidumpContext(Minidump* minidump)
+ : DumpContext(),
+ minidump_(minidump) {
+}
+
+MinidumpContext::~MinidumpContext() {
+}
+
+bool MinidumpContext::Read(uint32_t expected_size) {
+ valid_ = false;
+
+ // Certain raw context types are currently assumed to have unique sizes.
+ if (!IsContextSizeUnique(sizeof(MDRawContextPPC64))) {
+ BPLOG(ERROR) << "sizeof(MDRawContextPPC64) cannot match the size of any "
+ << "other raw context";
+ return false;
+ }
+ if (!IsContextSizeUnique(sizeof(MDRawContextARM64_Old))) {
+ BPLOG(ERROR) << "sizeof(MDRawContextARM64_Old) cannot match the size of any "
+ << "other raw context";
+ return false;
+ }
+
+ FreeContext();
+
+ if (expected_size == sizeof(MDRawContextPPC64)) {
+ // |context_flags| of MDRawContextPPC64 is 64 bits, but other MDRawContext
+ // in the else case have 32 bits |context_flags|, so special case it here.
+ uint64_t context_flags;
+ if (!minidump_->ReadBytes(&context_flags, sizeof(context_flags))) {
+ BPLOG(ERROR) << "MinidumpContext could not read context flags";
+ return false;
+ }
+ if (minidump_->swap())
+ Swap(&context_flags);
+
+ uint32_t cpu_type = context_flags & MD_CONTEXT_CPU_MASK;
+ scoped_ptr<MDRawContextPPC64> context_ppc64(new MDRawContextPPC64());
+
+ if (cpu_type == 0) {
+ if (minidump_->GetContextCPUFlagsFromSystemInfo(&cpu_type)) {
+ context_ppc64->context_flags |= cpu_type;
+ } else {
+ BPLOG(ERROR) << "Failed to preserve the current stream position";
+ return false;
+ }
+ }
+
+ if (cpu_type != MD_CONTEXT_PPC64) {
+ // TODO: Fall through to switch below.
+ // https://bugs.chromium.org/p/google-breakpad/issues/detail?id=550
+ BPLOG(ERROR) << "MinidumpContext not actually ppc64 context";
+ return false;
+ }
+
+ // Set the context_flags member, which has already been read, and
+ // read the rest of the structure beginning with the first member
+ // after context_flags.
+ context_ppc64->context_flags = context_flags;
+
+ size_t flags_size = sizeof(context_ppc64->context_flags);
+ uint8_t* context_after_flags =
+ reinterpret_cast<uint8_t*>(context_ppc64.get()) + flags_size;
+ if (!minidump_->ReadBytes(context_after_flags,
+ sizeof(MDRawContextPPC64) - flags_size)) {
+ BPLOG(ERROR) << "MinidumpContext could not read ppc64 context";
+ return false;
+ }
+
+ // Do this after reading the entire MDRawContext structure because
+ // GetSystemInfo may seek minidump to a new position.
+ if (!CheckAgainstSystemInfo(cpu_type)) {
+ BPLOG(ERROR) << "MinidumpContext ppc64 does not match system info";
+ return false;
+ }
+ if (minidump_->swap()) {
+ // context_ppc64->context_flags was already swapped.
+ Swap(&context_ppc64->srr0);
+ Swap(&context_ppc64->srr1);
+ for (unsigned int gpr_index = 0;
+ gpr_index < MD_CONTEXT_PPC64_GPR_COUNT;
+ ++gpr_index) {
+ Swap(&context_ppc64->gpr[gpr_index]);
+ }
+ Swap(&context_ppc64->cr);
+ Swap(&context_ppc64->xer);
+ Swap(&context_ppc64->lr);
+ Swap(&context_ppc64->ctr);
+ Swap(&context_ppc64->vrsave);
+ for (unsigned int fpr_index = 0;
+ fpr_index < MD_FLOATINGSAVEAREA_PPC_FPR_COUNT;
+ ++fpr_index) {
+ Swap(&context_ppc64->float_save.fpregs[fpr_index]);
+ }
+ // Don't swap context_ppc64->float_save.fpscr_pad because it is only
+ // used for padding.
+ Swap(&context_ppc64->float_save.fpscr);
+ for (unsigned int vr_index = 0;
+ vr_index < MD_VECTORSAVEAREA_PPC_VR_COUNT;
+ ++vr_index) {
+ Normalize128(&context_ppc64->vector_save.save_vr[vr_index], true);
+ Swap(&context_ppc64->vector_save.save_vr[vr_index]);
+ }
+ Swap(&context_ppc64->vector_save.save_vscr);
+ // Don't swap the padding fields in vector_save.
+ Swap(&context_ppc64->vector_save.save_vrvalid);
+ }
+
+ SetContextFlags(static_cast<uint32_t>(context_ppc64->context_flags));
+
+ // Check for data loss when converting context flags from uint64_t into
+ // uint32_t
+ if (static_cast<uint64_t>(GetContextFlags()) !=
+ context_ppc64->context_flags) {
+ BPLOG(ERROR) << "Data loss detected when converting PPC64 context_flags";
+ return false;
+ }
+
+ SetContextPPC64(context_ppc64.release());
+ } else if (expected_size == sizeof(MDRawContextARM64_Old)) {
+ // |context_flags| of MDRawContextARM64_Old is 64 bits, but other MDRawContext
+ // in the else case have 32 bits |context_flags|, so special case it here.
+ uint64_t context_flags;
+
+ BPLOG(INFO) << "MinidumpContext: looks like ARM64 context";
+
+ if (!minidump_->ReadBytes(&context_flags, sizeof(context_flags))) {
+ BPLOG(ERROR) << "MinidumpContext could not read context flags";
+ return false;
+ }
+ if (minidump_->swap())
+ Swap(&context_flags);
+
+ scoped_ptr<MDRawContextARM64_Old> context_arm64(new MDRawContextARM64_Old());
+
+ uint32_t cpu_type = context_flags & MD_CONTEXT_CPU_MASK;
+ if (cpu_type == 0) {
+ if (minidump_->GetContextCPUFlagsFromSystemInfo(&cpu_type)) {
+ context_arm64->context_flags |= cpu_type;
+ } else {
+ BPLOG(ERROR) << "Failed to preserve the current stream position";
+ return false;
+ }
+ }
+
+ if (cpu_type != MD_CONTEXT_ARM64_OLD) {
+ // TODO: Fall through to switch below.
+ // https://bugs.chromium.org/p/google-breakpad/issues/detail?id=550
+ BPLOG(ERROR) << "MinidumpContext not actually arm64 context";
+ return false;
+ }
+
+ // Set the context_flags member, which has already been read, and
+ // read the rest of the structure beginning with the first member
+ // after context_flags.
+ context_arm64->context_flags = context_flags;
+
+ size_t flags_size = sizeof(context_arm64->context_flags);
+ uint8_t* context_after_flags =
+ reinterpret_cast<uint8_t*>(context_arm64.get()) + flags_size;
+ if (!minidump_->ReadBytes(context_after_flags,
+ sizeof(MDRawContextARM64_Old) - flags_size)) {
+ BPLOG(ERROR) << "MinidumpContext could not read arm64 context";
+ return false;
+ }
+
+ // Do this after reading the entire MDRawContext structure because
+ // GetSystemInfo may seek minidump to a new position.
+ if (!CheckAgainstSystemInfo(cpu_type)) {
+ BPLOG(ERROR) << "MinidumpContext arm64 does not match system info";
+ return false;
+ }
+
+ if (minidump_->swap()) {
+ // context_arm64->context_flags was already swapped.
+ for (unsigned int ireg_index = 0;
+ ireg_index < MD_CONTEXT_ARM64_GPR_COUNT;
+ ++ireg_index) {
+ Swap(&context_arm64->iregs[ireg_index]);
+ }
+ Swap(&context_arm64->cpsr);
+ Swap(&context_arm64->float_save.fpsr);
+ Swap(&context_arm64->float_save.fpcr);
+ for (unsigned int fpr_index = 0;
+ fpr_index < MD_FLOATINGSAVEAREA_ARM64_FPR_COUNT;
+ ++fpr_index) {
+ Normalize128(&context_arm64->float_save.regs[fpr_index],
+ minidump_->is_big_endian());
+ Swap(&context_arm64->float_save.regs[fpr_index]);
+ }
+ }
+
+ scoped_ptr<MDRawContextARM64> new_context(new MDRawContextARM64());
+ ConvertOldARM64Context(*context_arm64.get(), new_context.get());
+ SetContextFlags(new_context->context_flags);
+ SetContextARM64(new_context.release());
+ } else {
+ uint32_t cpu_type = 0;
+ if (!minidump_->GetContextCPUFlagsFromSystemInfo(&cpu_type)) {
+ BPLOG(ERROR) << "Failed to preserve the current stream position";
+ return false;
+ }
+
+ uint32_t context_flags = 0;
+ if ((cpu_type == 0) || cpu_type != MD_CONTEXT_AMD64) {
+ if (!minidump_->ReadBytes(&context_flags, sizeof(context_flags))) {
+ BPLOG(ERROR) << "MinidumpContext could not read context flags";
+ return false;
+ }
+
+ if (minidump_->swap())
+ Swap(&context_flags);
+
+ if ((context_flags & MD_CONTEXT_CPU_MASK) == 0) {
+ // Unfortunately the flag for MD_CONTEXT_ARM that was taken
+ // from a Windows CE SDK header conflicts in practice with
+ // the CONTEXT_XSTATE flag. MD_CONTEXT_ARM has been renumbered,
+ // but handle dumps with the legacy value gracefully here.
+ if (context_flags & MD_CONTEXT_ARM_OLD) {
+ context_flags |= MD_CONTEXT_ARM;
+ context_flags &= ~MD_CONTEXT_ARM_OLD;
+ cpu_type = MD_CONTEXT_ARM;
+ } else {
+ context_flags |= cpu_type;
+ }
+ } else {
+ cpu_type = context_flags & MD_CONTEXT_CPU_MASK;
+ }
+ }
+
+ // Allocate the context structure for the correct CPU and fill it. The
+ // casts are slightly unorthodox, but it seems better to do that than to
+ // maintain a separate pointer for each type of CPU context structure
+ // when only one of them will be used.
+ switch (cpu_type) {
+ case MD_CONTEXT_AMD64: {
+ if (expected_size != sizeof(MDRawContextAMD64)) {
+ BPLOG(INFO) << "MinidumpContext AMD64 size mismatch, " <<
+ expected_size << " != " << sizeof(MDRawContextAMD64);
+ }
+ BPLOG(INFO) << "MinidumpContext: looks like AMD64 context";
+
+ scoped_ptr<MDRawContextAMD64> context_amd64(new MDRawContextAMD64());
+ if (!minidump_->ReadBytes(context_amd64.get(),
+ sizeof(MDRawContextAMD64))) {
+ BPLOG(ERROR) << "MinidumpContext could not read amd64 context";
+ return false;
+ }
+
+ if (minidump_->swap())
+ Swap(&context_amd64->context_flags);
+
+ // Update context_flags since we haven't done it yet
+ context_flags = context_amd64->context_flags;
+
+ if (cpu_type != (context_flags & MD_CONTEXT_CPU_MASK)) {
+ BPLOG(ERROR) << "MinidumpContext amd64 does not match system info";
+ return false;
+ }
+
+ // Normalize the 128-bit types in the dump.
+ // Since this is AMD64, by definition, the values are little-endian.
+ for (unsigned int vr_index = 0;
+ vr_index < MD_CONTEXT_AMD64_VR_COUNT;
+ ++vr_index)
+ Normalize128(&context_amd64->vector_register[vr_index], false);
+
+ if (minidump_->swap()) {
+ Swap(&context_amd64->p1_home);
+ Swap(&context_amd64->p2_home);
+ Swap(&context_amd64->p3_home);
+ Swap(&context_amd64->p4_home);
+ Swap(&context_amd64->p5_home);
+ Swap(&context_amd64->p6_home);
+ // context_flags is already swapped
+ Swap(&context_amd64->mx_csr);
+ Swap(&context_amd64->cs);
+ Swap(&context_amd64->ds);
+ Swap(&context_amd64->es);
+ Swap(&context_amd64->fs);
+ Swap(&context_amd64->ss);
+ Swap(&context_amd64->eflags);
+ Swap(&context_amd64->dr0);
+ Swap(&context_amd64->dr1);
+ Swap(&context_amd64->dr2);
+ Swap(&context_amd64->dr3);
+ Swap(&context_amd64->dr6);
+ Swap(&context_amd64->dr7);
+ Swap(&context_amd64->rax);
+ Swap(&context_amd64->rcx);
+ Swap(&context_amd64->rdx);
+ Swap(&context_amd64->rbx);
+ Swap(&context_amd64->rsp);
+ Swap(&context_amd64->rbp);
+ Swap(&context_amd64->rsi);
+ Swap(&context_amd64->rdi);
+ Swap(&context_amd64->r8);
+ Swap(&context_amd64->r9);
+ Swap(&context_amd64->r10);
+ Swap(&context_amd64->r11);
+ Swap(&context_amd64->r12);
+ Swap(&context_amd64->r13);
+ Swap(&context_amd64->r14);
+ Swap(&context_amd64->r15);
+ Swap(&context_amd64->rip);
+ // FIXME: I'm not sure what actually determines
+ // which member of the union {flt_save, sse_registers}
+ // is valid. We're not currently using either,
+ // but it would be good to have them swapped properly.
+
+ for (unsigned int vr_index = 0;
+ vr_index < MD_CONTEXT_AMD64_VR_COUNT;
+ ++vr_index)
+ Swap(&context_amd64->vector_register[vr_index]);
+ Swap(&context_amd64->vector_control);
+ Swap(&context_amd64->debug_control);
+ Swap(&context_amd64->last_branch_to_rip);
+ Swap(&context_amd64->last_branch_from_rip);
+ Swap(&context_amd64->last_exception_to_rip);
+ Swap(&context_amd64->last_exception_from_rip);
+ }
+
+ SetContextFlags(context_amd64->context_flags);
+
+ SetContextAMD64(context_amd64.release());
+ minidump_->SeekSet(
+ (minidump_->Tell() - sizeof(MDRawContextAMD64)) + expected_size);
+ break;
+ }
+ case MD_CONTEXT_X86: {
+ if (expected_size != sizeof(MDRawContextX86)) {
+ BPLOG(INFO) << "MinidumpContext x86 size mismatch, " <<
+ expected_size << " != " << sizeof(MDRawContextX86);
+ }
+
+ scoped_ptr<MDRawContextX86> context_x86(new MDRawContextX86());
+
+ // Set the context_flags member, which has already been read, and
+ // read the rest of the structure beginning with the first member
+ // after context_flags.
+ context_x86->context_flags = context_flags;
+
+ size_t flags_size = sizeof(context_x86->context_flags);
+ uint8_t* context_after_flags =
+ reinterpret_cast<uint8_t*>(context_x86.get()) + flags_size;
+ if (!minidump_->ReadBytes(context_after_flags,
+ sizeof(MDRawContextX86) - flags_size)) {
+ BPLOG(ERROR) << "MinidumpContext could not read x86 context";
+ return false;
+ }
+
+ // Do this after reading the entire MDRawContext structure because
+ // GetSystemInfo may seek minidump to a new position.
+ if (!CheckAgainstSystemInfo(cpu_type)) {
+ BPLOG(ERROR) << "MinidumpContext x86 does not match system info";
+ return false;
+ }
+
+ if (minidump_->swap()) {
+ // context_x86->context_flags was already swapped.
+ Swap(&context_x86->dr0);
+ Swap(&context_x86->dr1);
+ Swap(&context_x86->dr2);
+ Swap(&context_x86->dr3);
+ Swap(&context_x86->dr6);
+ Swap(&context_x86->dr7);
+ Swap(&context_x86->float_save.control_word);
+ Swap(&context_x86->float_save.status_word);
+ Swap(&context_x86->float_save.tag_word);
+ Swap(&context_x86->float_save.error_offset);
+ Swap(&context_x86->float_save.error_selector);
+ Swap(&context_x86->float_save.data_offset);
+ Swap(&context_x86->float_save.data_selector);
+ // context_x86->float_save.register_area[] contains 8-bit quantities
+ // and does not need to be swapped.
+ Swap(&context_x86->float_save.cr0_npx_state);
+ Swap(&context_x86->gs);
+ Swap(&context_x86->fs);
+ Swap(&context_x86->es);
+ Swap(&context_x86->ds);
+ Swap(&context_x86->edi);
+ Swap(&context_x86->esi);
+ Swap(&context_x86->ebx);
+ Swap(&context_x86->edx);
+ Swap(&context_x86->ecx);
+ Swap(&context_x86->eax);
+ Swap(&context_x86->ebp);
+ Swap(&context_x86->eip);
+ Swap(&context_x86->cs);
+ Swap(&context_x86->eflags);
+ Swap(&context_x86->esp);
+ Swap(&context_x86->ss);
+ // context_x86->extended_registers[] contains 8-bit quantities and
+ // does not need to be swapped.
+ }
+
+ SetContextX86(context_x86.release());
+ minidump_->SeekSet(
+ (minidump_->Tell() - sizeof(MDRawContextX86)) + expected_size);
+
+ break;
+ }
+
+ case MD_CONTEXT_PPC: {
+ if (expected_size != sizeof(MDRawContextPPC)) {
+ BPLOG(ERROR) << "MinidumpContext ppc size mismatch, " <<
+ expected_size << " != " << sizeof(MDRawContextPPC);
+ return false;
+ }
+
+ scoped_ptr<MDRawContextPPC> context_ppc(new MDRawContextPPC());
+
+ // Set the context_flags member, which has already been read, and
+ // read the rest of the structure beginning with the first member
+ // after context_flags.
+ context_ppc->context_flags = context_flags;
+
+ size_t flags_size = sizeof(context_ppc->context_flags);
+ uint8_t* context_after_flags =
+ reinterpret_cast<uint8_t*>(context_ppc.get()) + flags_size;
+ if (!minidump_->ReadBytes(context_after_flags,
+ sizeof(MDRawContextPPC) - flags_size)) {
+ BPLOG(ERROR) << "MinidumpContext could not read ppc context";
+ return false;
+ }
+
+ // Do this after reading the entire MDRawContext structure because
+ // GetSystemInfo may seek minidump to a new position.
+ if (!CheckAgainstSystemInfo(cpu_type)) {
+ BPLOG(ERROR) << "MinidumpContext ppc does not match system info";
+ return false;
+ }
+
+ // Normalize the 128-bit types in the dump.
+ // Since this is PowerPC, by definition, the values are big-endian.
+ for (unsigned int vr_index = 0;
+ vr_index < MD_VECTORSAVEAREA_PPC_VR_COUNT;
+ ++vr_index) {
+ Normalize128(&context_ppc->vector_save.save_vr[vr_index], true);
+ }
+
+ if (minidump_->swap()) {
+ // context_ppc->context_flags was already swapped.
+ Swap(&context_ppc->srr0);
+ Swap(&context_ppc->srr1);
+ for (unsigned int gpr_index = 0;
+ gpr_index < MD_CONTEXT_PPC_GPR_COUNT;
+ ++gpr_index) {
+ Swap(&context_ppc->gpr[gpr_index]);
+ }
+ Swap(&context_ppc->cr);
+ Swap(&context_ppc->xer);
+ Swap(&context_ppc->lr);
+ Swap(&context_ppc->ctr);
+ Swap(&context_ppc->mq);
+ Swap(&context_ppc->vrsave);
+ for (unsigned int fpr_index = 0;
+ fpr_index < MD_FLOATINGSAVEAREA_PPC_FPR_COUNT;
+ ++fpr_index) {
+ Swap(&context_ppc->float_save.fpregs[fpr_index]);
+ }
+ // Don't swap context_ppc->float_save.fpscr_pad because it is only
+ // used for padding.
+ Swap(&context_ppc->float_save.fpscr);
+ for (unsigned int vr_index = 0;
+ vr_index < MD_VECTORSAVEAREA_PPC_VR_COUNT;
+ ++vr_index) {
+ Swap(&context_ppc->vector_save.save_vr[vr_index]);
+ }
+ Swap(&context_ppc->vector_save.save_vscr);
+ // Don't swap the padding fields in vector_save.
+ Swap(&context_ppc->vector_save.save_vrvalid);
+ }
+
+ SetContextPPC(context_ppc.release());
+
+ break;
+ }
+
+ case MD_CONTEXT_SPARC: {
+ if (expected_size != sizeof(MDRawContextSPARC)) {
+ BPLOG(ERROR) << "MinidumpContext sparc size mismatch, " <<
+ expected_size << " != " << sizeof(MDRawContextSPARC);
+ return false;
+ }
+
+ scoped_ptr<MDRawContextSPARC> context_sparc(new MDRawContextSPARC());
+
+ // Set the context_flags member, which has already been read, and
+ // read the rest of the structure beginning with the first member
+ // after context_flags.
+ context_sparc->context_flags = context_flags;
+
+ size_t flags_size = sizeof(context_sparc->context_flags);
+ uint8_t* context_after_flags =
+ reinterpret_cast<uint8_t*>(context_sparc.get()) + flags_size;
+ if (!minidump_->ReadBytes(context_after_flags,
+ sizeof(MDRawContextSPARC) - flags_size)) {
+ BPLOG(ERROR) << "MinidumpContext could not read sparc context";
+ return false;
+ }
+
+ // Do this after reading the entire MDRawContext structure because
+ // GetSystemInfo may seek minidump to a new position.
+ if (!CheckAgainstSystemInfo(cpu_type)) {
+ BPLOG(ERROR) << "MinidumpContext sparc does not match system info";
+ return false;
+ }
+
+ if (minidump_->swap()) {
+ // context_sparc->context_flags was already swapped.
+ for (unsigned int gpr_index = 0;
+ gpr_index < MD_CONTEXT_SPARC_GPR_COUNT;
+ ++gpr_index) {
+ Swap(&context_sparc->g_r[gpr_index]);
+ }
+ Swap(&context_sparc->ccr);
+ Swap(&context_sparc->pc);
+ Swap(&context_sparc->npc);
+ Swap(&context_sparc->y);
+ Swap(&context_sparc->asi);
+ Swap(&context_sparc->fprs);
+ for (unsigned int fpr_index = 0;
+ fpr_index < MD_FLOATINGSAVEAREA_SPARC_FPR_COUNT;
+ ++fpr_index) {
+ Swap(&context_sparc->float_save.regs[fpr_index]);
+ }
+ Swap(&context_sparc->float_save.filler);
+ Swap(&context_sparc->float_save.fsr);
+ }
+ SetContextSPARC(context_sparc.release());
+
+ break;
+ }
+
+ case MD_CONTEXT_ARM: {
+ if (expected_size != sizeof(MDRawContextARM)) {
+ BPLOG(ERROR) << "MinidumpContext arm size mismatch, " <<
+ expected_size << " != " << sizeof(MDRawContextARM);
+ return false;
+ }
+
+ scoped_ptr<MDRawContextARM> context_arm(new MDRawContextARM());
+
+ // Set the context_flags member, which has already been read, and
+ // read the rest of the structure beginning with the first member
+ // after context_flags.
+ context_arm->context_flags = context_flags;
+
+ size_t flags_size = sizeof(context_arm->context_flags);
+ uint8_t* context_after_flags =
+ reinterpret_cast<uint8_t*>(context_arm.get()) + flags_size;
+ if (!minidump_->ReadBytes(context_after_flags,
+ sizeof(MDRawContextARM) - flags_size)) {
+ BPLOG(ERROR) << "MinidumpContext could not read arm context";
+ return false;
+ }
+
+ // Do this after reading the entire MDRawContext structure because
+ // GetSystemInfo may seek minidump to a new position.
+ if (!CheckAgainstSystemInfo(cpu_type)) {
+ BPLOG(ERROR) << "MinidumpContext arm does not match system info";
+ return false;
+ }
+
+ if (minidump_->swap()) {
+ // context_arm->context_flags was already swapped.
+ for (unsigned int ireg_index = 0;
+ ireg_index < MD_CONTEXT_ARM_GPR_COUNT;
+ ++ireg_index) {
+ Swap(&context_arm->iregs[ireg_index]);
+ }
+ Swap(&context_arm->cpsr);
+ Swap(&context_arm->float_save.fpscr);
+ for (unsigned int fpr_index = 0;
+ fpr_index < MD_FLOATINGSAVEAREA_ARM_FPR_COUNT;
+ ++fpr_index) {
+ Swap(&context_arm->float_save.regs[fpr_index]);
+ }
+ for (unsigned int fpe_index = 0;
+ fpe_index < MD_FLOATINGSAVEAREA_ARM_FPEXTRA_COUNT;
+ ++fpe_index) {
+ Swap(&context_arm->float_save.extra[fpe_index]);
+ }
+ }
+ SetContextARM(context_arm.release());
+
+ break;
+ }
+
+ case MD_CONTEXT_ARM64: {
+ if (expected_size != sizeof(MDRawContextARM64)) {
+ BPLOG(ERROR) << "MinidumpContext arm64 size mismatch, " <<
+ expected_size << " != " << sizeof(MDRawContextARM64);
+ return false;
+ }
+
+ scoped_ptr<MDRawContextARM64> context_arm64(new MDRawContextARM64());
+
+ // Set the context_flags member, which has already been read, and
+ // read the rest of the structure beginning with the first member
+ // after context_flags.
+ context_arm64->context_flags = context_flags;
+
+ size_t flags_size = sizeof(context_arm64->context_flags);
+ uint8_t* context_after_flags =
+ reinterpret_cast<uint8_t*>(context_arm64.get()) + flags_size;
+ if (!minidump_->ReadBytes(context_after_flags,
+ sizeof(*context_arm64) - flags_size)) {
+ BPLOG(ERROR) << "MinidumpContext could not read arm64 context";
+ return false;
+ }
+
+ // Do this after reading the entire MDRawContext structure because
+ // GetSystemInfo may seek minidump to a new position.
+ if (!CheckAgainstSystemInfo(cpu_type)) {
+ BPLOG(ERROR) << "MinidumpContext arm does not match system info";
+ return false;
+ }
+
+ if (minidump_->swap()) {
+ // context_arm64->context_flags was already swapped.
+ for (unsigned int ireg_index = 0;
+ ireg_index < MD_CONTEXT_ARM64_GPR_COUNT;
+ ++ireg_index) {
+ Swap(&context_arm64->iregs[ireg_index]);
+ }
+ Swap(&context_arm64->cpsr);
+ Swap(&context_arm64->float_save.fpsr);
+ Swap(&context_arm64->float_save.fpcr);
+ for (unsigned int fpr_index = 0;
+ fpr_index < MD_FLOATINGSAVEAREA_ARM64_FPR_COUNT;
+ ++fpr_index) {
+ Normalize128(&context_arm64->float_save.regs[fpr_index],
+ minidump_->is_big_endian());
+ Swap(&context_arm64->float_save.regs[fpr_index]);
+ }
+ }
+ SetContextARM64(context_arm64.release());
+ break;
+ }
+
+ case MD_CONTEXT_MIPS:
+ case MD_CONTEXT_MIPS64: {
+ if (expected_size != sizeof(MDRawContextMIPS)) {
+ BPLOG(ERROR) << "MinidumpContext MIPS size mismatch, "
+ << expected_size
+ << " != "
+ << sizeof(MDRawContextMIPS);
+ return false;
+ }
+
+ scoped_ptr<MDRawContextMIPS> context_mips(new MDRawContextMIPS());
+
+ // Set the context_flags member, which has already been read, and
+ // read the rest of the structure beginning with the first member
+ // after context_flags.
+ context_mips->context_flags = context_flags;
+
+ size_t flags_size = sizeof(context_mips->context_flags);
+ uint8_t* context_after_flags =
+ reinterpret_cast<uint8_t*>(context_mips.get()) + flags_size;
+ if (!minidump_->ReadBytes(context_after_flags,
+ sizeof(MDRawContextMIPS) - flags_size)) {
+ BPLOG(ERROR) << "MinidumpContext could not read MIPS context";
+ return false;
+ }
+
+ // Do this after reading the entire MDRawContext structure because
+ // GetSystemInfo may seek minidump to a new position.
+ if (!CheckAgainstSystemInfo(cpu_type)) {
+ BPLOG(ERROR) << "MinidumpContext MIPS does not match system info";
+ return false;
+ }
+
+ if (minidump_->swap()) {
+ // context_mips->context_flags was already swapped.
+ for (int ireg_index = 0;
+ ireg_index < MD_CONTEXT_MIPS_GPR_COUNT;
+ ++ireg_index) {
+ Swap(&context_mips->iregs[ireg_index]);
+ }
+ Swap(&context_mips->mdhi);
+ Swap(&context_mips->mdlo);
+ for (int dsp_index = 0;
+ dsp_index < MD_CONTEXT_MIPS_DSP_COUNT;
+ ++dsp_index) {
+ Swap(&context_mips->hi[dsp_index]);
+ Swap(&context_mips->lo[dsp_index]);
+ }
+ Swap(&context_mips->dsp_control);
+ Swap(&context_mips->epc);
+ Swap(&context_mips->badvaddr);
+ Swap(&context_mips->status);
+ Swap(&context_mips->cause);
+ for (int fpr_index = 0;
+ fpr_index < MD_FLOATINGSAVEAREA_MIPS_FPR_COUNT;
+ ++fpr_index) {
+ Swap(&context_mips->float_save.regs[fpr_index]);
+ }
+ Swap(&context_mips->float_save.fpcsr);
+ Swap(&context_mips->float_save.fir);
+ }
+ SetContextMIPS(context_mips.release());
+
+ break;
+ }
+
+ default: {
+ // Unknown context type - Don't log as an error yet. Let the
+ // caller work that out.
+ BPLOG(INFO) << "MinidumpContext unknown context type " <<
+ HexString(cpu_type);
+ return false;
+ break;
+ }
+ }
+ SetContextFlags(context_flags);
+ }
+
+ valid_ = true;
+ return true;
+}
+
+bool MinidumpContext::CheckAgainstSystemInfo(uint32_t context_cpu_type) {
+ // It's OK if the minidump doesn't contain an MD_SYSTEM_INFO_STREAM,
+ // as this function just implements a sanity check.
+ MinidumpSystemInfo* system_info = minidump_->GetSystemInfo();
+ if (!system_info) {
+ BPLOG(INFO) << "MinidumpContext could not be compared against "
+ "MinidumpSystemInfo";
+ return true;
+ }
+
+ // If there is an MD_SYSTEM_INFO_STREAM, it should contain valid system info.
+ const MDRawSystemInfo* raw_system_info = system_info->system_info();
+ if (!raw_system_info) {
+ BPLOG(INFO) << "MinidumpContext could not be compared against "
+ "MDRawSystemInfo";
+ return false;
+ }
+
+ MDCPUArchitecture system_info_cpu_type = static_cast<MDCPUArchitecture>(
+ raw_system_info->processor_architecture);
+
+ // Compare the CPU type of the context record to the CPU type in the
+ // minidump's system info stream.
+ bool return_value = false;
+ switch (context_cpu_type) {
+ case MD_CONTEXT_X86:
+ if (system_info_cpu_type == MD_CPU_ARCHITECTURE_X86 ||
+ system_info_cpu_type == MD_CPU_ARCHITECTURE_X86_WIN64 ||
+ system_info_cpu_type == MD_CPU_ARCHITECTURE_AMD64) {
+ return_value = true;
+ }
+ break;
+
+ case MD_CONTEXT_PPC:
+ if (system_info_cpu_type == MD_CPU_ARCHITECTURE_PPC)
+ return_value = true;
+ break;
+
+ case MD_CONTEXT_PPC64:
+ if (system_info_cpu_type == MD_CPU_ARCHITECTURE_PPC64)
+ return_value = true;
+ break;
+
+ case MD_CONTEXT_AMD64:
+ if (system_info_cpu_type == MD_CPU_ARCHITECTURE_AMD64)
+ return_value = true;
+ break;
+
+ case MD_CONTEXT_SPARC:
+ if (system_info_cpu_type == MD_CPU_ARCHITECTURE_SPARC)
+ return_value = true;
+ break;
+
+ case MD_CONTEXT_ARM:
+ if (system_info_cpu_type == MD_CPU_ARCHITECTURE_ARM)
+ return_value = true;
+ break;
+
+ case MD_CONTEXT_ARM64:
+ if (system_info_cpu_type == MD_CPU_ARCHITECTURE_ARM64)
+ return_value = true;
+ break;
+
+ case MD_CONTEXT_ARM64_OLD:
+ if (system_info_cpu_type == MD_CPU_ARCHITECTURE_ARM64_OLD)
+ return_value = true;
+ break;
+
+ case MD_CONTEXT_MIPS:
+ if (system_info_cpu_type == MD_CPU_ARCHITECTURE_MIPS)
+ return_value = true;
+ break;
+
+ case MD_CONTEXT_MIPS64:
+ if (system_info_cpu_type == MD_CPU_ARCHITECTURE_MIPS64)
+ return_value = true;
+ break;
+ }
+
+ BPLOG_IF(ERROR, !return_value) << "MinidumpContext CPU " <<
+ HexString(context_cpu_type) <<
+ " wrong for MinidumpSystemInfo CPU " <<
+ HexString(system_info_cpu_type);
+
+ return return_value;
+}
+
+
+//
+// MinidumpMemoryRegion
+//
+
+
+uint32_t MinidumpMemoryRegion::max_bytes_ = 64 * 1024 * 1024; // 64MB
+
+
+MinidumpMemoryRegion::MinidumpMemoryRegion(Minidump* minidump)
+ : MinidumpObject(minidump),
+ descriptor_(NULL),
+ memory_(NULL) {
+ hexdump_width_ = minidump_ ? minidump_->HexdumpMode() : 0;
+ hexdump_ = hexdump_width_ != 0;
+}
+
+
+MinidumpMemoryRegion::~MinidumpMemoryRegion() {
+ delete memory_;
+}
+
+
+void MinidumpMemoryRegion::SetDescriptor(MDMemoryDescriptor* descriptor) {
+ descriptor_ = descriptor;
+ valid_ = descriptor &&
+ descriptor_->memory.data_size <=
+ numeric_limits<uint64_t>::max() -
+ descriptor_->start_of_memory_range;
+}
+
+
+const uint8_t* MinidumpMemoryRegion::GetMemory() const {
+ if (!valid_) {
+ BPLOG(ERROR) << "Invalid MinidumpMemoryRegion for GetMemory";
+ return NULL;
+ }
+
+ if (!memory_) {
+ if (descriptor_->memory.data_size == 0) {
+ BPLOG(ERROR) << "MinidumpMemoryRegion is empty";
+ return NULL;
+ }
+
+ if (!minidump_->SeekSet(descriptor_->memory.rva)) {
+ BPLOG(ERROR) << "MinidumpMemoryRegion could not seek to memory region";
+ return NULL;
+ }
+
+ if (descriptor_->memory.data_size > max_bytes_) {
+ BPLOG(ERROR) << "MinidumpMemoryRegion size " <<
+ descriptor_->memory.data_size << " exceeds maximum " <<
+ max_bytes_;
+ return NULL;
+ }
+
+ scoped_ptr< vector<uint8_t> > memory(
+ new vector<uint8_t>(descriptor_->memory.data_size));
+
+ if (!minidump_->ReadBytes(&(*memory)[0], descriptor_->memory.data_size)) {
+ BPLOG(ERROR) << "MinidumpMemoryRegion could not read memory region";
+ return NULL;
+ }
+
+ memory_ = memory.release();
+ }
+
+ return &(*memory_)[0];
+}
+
+
+uint64_t MinidumpMemoryRegion::GetBase() const {
+ if (!valid_) {
+ BPLOG(ERROR) << "Invalid MinidumpMemoryRegion for GetBase";
+ return static_cast<uint64_t>(-1);
+ }
+
+ return descriptor_->start_of_memory_range;
+}
+
+
+uint32_t MinidumpMemoryRegion::GetSize() const {
+ if (!valid_) {
+ BPLOG(ERROR) << "Invalid MinidumpMemoryRegion for GetSize";
+ return 0;
+ }
+
+ return descriptor_->memory.data_size;
+}
+
+
+void MinidumpMemoryRegion::FreeMemory() {
+ delete memory_;
+ memory_ = NULL;
+}
+
+
+template<typename T>
+bool MinidumpMemoryRegion::GetMemoryAtAddressInternal(uint64_t address,
+ T* value) const {
+ BPLOG_IF(ERROR, !value) << "MinidumpMemoryRegion::GetMemoryAtAddressInternal "
+ "requires |value|";
+ assert(value);
+ *value = 0;
+
+ if (!valid_) {
+ BPLOG(ERROR) << "Invalid MinidumpMemoryRegion for "
+ "GetMemoryAtAddressInternal";
+ return false;
+ }
+
+ // Common failure case
+ if (address < descriptor_->start_of_memory_range ||
+ sizeof(T) > numeric_limits<uint64_t>::max() - address ||
+ address + sizeof(T) > descriptor_->start_of_memory_range +
+ descriptor_->memory.data_size) {
+ BPLOG(INFO) << "MinidumpMemoryRegion request out of range: " <<
+ HexString(address) << "+" << sizeof(T) << "/" <<
+ HexString(descriptor_->start_of_memory_range) << "+" <<
+ HexString(descriptor_->memory.data_size);
+ return false;
+ }
+
+ const uint8_t* memory = GetMemory();
+ if (!memory) {
+ // GetMemory already logged a perfectly good message.
+ return false;
+ }
+
+ // If the CPU requires memory accesses to be aligned, this can crash.
+ // x86 and ppc are able to cope, though.
+ *value = *reinterpret_cast<const T*>(
+ &memory[address - descriptor_->start_of_memory_range]);
+
+ if (minidump_->swap())
+ Swap(value);
+
+ return true;
+}
+
+
+bool MinidumpMemoryRegion::GetMemoryAtAddress(uint64_t address,
+ uint8_t* value) const {
+ return GetMemoryAtAddressInternal(address, value);
+}
+
+
+bool MinidumpMemoryRegion::GetMemoryAtAddress(uint64_t address,
+ uint16_t* value) const {
+ return GetMemoryAtAddressInternal(address, value);
+}
+
+
+bool MinidumpMemoryRegion::GetMemoryAtAddress(uint64_t address,
+ uint32_t* value) const {
+ return GetMemoryAtAddressInternal(address, value);
+}
+
+
+bool MinidumpMemoryRegion::GetMemoryAtAddress(uint64_t address,
+ uint64_t* value) const {
+ return GetMemoryAtAddressInternal(address, value);
+}
+
+
+void MinidumpMemoryRegion::Print() const {
+ if (!valid_) {
+ BPLOG(ERROR) << "MinidumpMemoryRegion cannot print invalid data";
+ return;
+ }
+
+ const uint8_t* memory = GetMemory();
+ if (memory) {
+ if (hexdump_) {
+ // Pretty hexdump view.
+ for (unsigned int byte_index = 0;
+ byte_index < descriptor_->memory.data_size;
+ byte_index += hexdump_width_) {
+ // In case the memory won't fill a whole line.
+ unsigned int num_bytes = std::min(
+ descriptor_->memory.data_size - byte_index, hexdump_width_);
+
+ // Display the leading address.
+ printf("%08x ", byte_index);
+
+ // Show the bytes in hex.
+ for (unsigned int i = 0; i < hexdump_width_; ++i) {
+ if (i < num_bytes) {
+ // Show the single byte of memory in hex.
+ printf("%02x ", memory[byte_index + i]);
+ } else {
+ // If this line doesn't fill up, pad it out.
+ printf(" ");
+ }
+
+ // Insert a space every 8 bytes to make it more readable.
+ if (((i + 1) % 8) == 0) {
+ printf(" ");
+ }
+ }
+
+ // Decode the line as ASCII.
+ printf("|");
+ for (unsigned int i = 0; i < hexdump_width_; ++i) {
+ if (i < num_bytes) {
+ uint8_t byte = memory[byte_index + i];
+ printf("%c", isprint(byte) ? byte : '.');
+ } else {
+ // If this line doesn't fill up, pad it out.
+ printf(" ");
+ }
+ }
+ printf("|\n");
+ }
+ } else {
+ // Ugly raw string view.
+ printf("0x");
+ for (unsigned int i = 0;
+ i < descriptor_->memory.data_size;
+ i++) {
+ printf("%02x", memory[i]);
+ }
+ printf("\n");
+ }
+ } else {
+ printf("No memory\n");
+ }
+}
+
+
+void MinidumpMemoryRegion::SetPrintMode(bool hexdump,
+ unsigned int hexdump_width) {
+ // Require the width to be a multiple of 8 bytes.
+ if (hexdump_width == 0 || (hexdump_width % 8) != 0) {
+ BPLOG(ERROR) << "MinidumpMemoryRegion print hexdump_width must be "
+ "multiple of 8, not " << hexdump_width;
+ return;
+ }
+
+ hexdump_ = hexdump;
+ hexdump_width_ = hexdump_width;
+}
+
+
+//
+// MinidumpThread
+//
+
+
+MinidumpThread::MinidumpThread(Minidump* minidump)
+ : MinidumpObject(minidump),
+ thread_(),
+ memory_(NULL),
+ context_(NULL) {
+}
+
+
+MinidumpThread::~MinidumpThread() {
+ delete memory_;
+ delete context_;
+}
+
+
+bool MinidumpThread::Read() {
+ // Invalidate cached data.
+ delete memory_;
+ memory_ = NULL;
+ delete context_;
+ context_ = NULL;
+
+ valid_ = false;
+
+ if (!minidump_->ReadBytes(&thread_, sizeof(thread_))) {
+ BPLOG(ERROR) << "MinidumpThread cannot read thread";
+ return false;
+ }
+
+ if (minidump_->swap()) {
+ Swap(&thread_.thread_id);
+ Swap(&thread_.suspend_count);
+ Swap(&thread_.priority_class);
+ Swap(&thread_.priority);
+ Swap(&thread_.teb);
+ Swap(&thread_.stack);
+ Swap(&thread_.thread_context);
+ }
+
+ // Check for base + size overflow or undersize.
+ if (thread_.stack.memory.rva == 0 ||
+ thread_.stack.memory.data_size == 0 ||
+ thread_.stack.memory.data_size > numeric_limits<uint64_t>::max() -
+ thread_.stack.start_of_memory_range) {
+ // This is ok, but log an error anyway.
+ BPLOG(ERROR) << "MinidumpThread has a memory region problem, " <<
+ HexString(thread_.stack.start_of_memory_range) << "+" <<
+ HexString(thread_.stack.memory.data_size) <<
+ ", RVA 0x" << HexString(thread_.stack.memory.rva);
+ } else {
+ memory_ = new MinidumpMemoryRegion(minidump_);
+ memory_->SetDescriptor(&thread_.stack);
+ }
+
+ valid_ = true;
+ return true;
+}
+
+uint64_t MinidumpThread::GetStartOfStackMemoryRange() const {
+ if (!valid_) {
+ BPLOG(ERROR) << "GetStartOfStackMemoryRange: Invalid MinidumpThread";
+ return 0;
+ }
+
+ return thread_.stack.start_of_memory_range;
+}
+
+MinidumpMemoryRegion* MinidumpThread::GetMemory() {
+ if (!valid_) {
+ BPLOG(ERROR) << "Invalid MinidumpThread for GetMemory";
+ return NULL;
+ }
+
+ return memory_;
+}
+
+uint32_t MinidumpThread::GetLastError() {
+ if (!valid_) {
+ BPLOG(ERROR) << "Cannot retrieve GetLastError() from an invalid thread";
+ return 0;
+ }
+
+ if (!thread_.teb) {
+ BPLOG(ERROR) << "Cannot retrieve GetLastError() without a valid TEB pointer";
+ return 0;
+ }
+
+ auto memory = minidump_->GetMemoryList();
+ if (!memory) {
+ BPLOG(ERROR) << "Cannot retrieve GetLastError() without a valid memory list";
+ return 0;
+ }
+
+ auto context = GetContext();
+ if (!context) {
+ BPLOG(ERROR) << "Cannot retrieve GetLastError()'s without a valid context";
+ return 0;
+ }
+
+ uint64_t pointer_width = 0;
+ switch (context_->GetContextCPU()) {
+ case MD_CONTEXT_X86:
+ pointer_width = 4;
+ break;
+ case MD_CONTEXT_AMD64:
+ case MD_CONTEXT_ARM64:
+ pointer_width = 8;
+ break;
+ default:
+ BPLOG(ERROR) << "GetLastError() isn't implemented for this CPU type yet";
+ return 0;
+ }
+
+ auto region = memory->GetMemoryRegionForAddress(thread_.teb);
+ if (!region) {
+ BPLOG(ERROR) << "GetLastError()'s memory isn't mapped in this minidump";
+ return 0;
+ }
+
+ // The TEB is opaque but we know the value we want lives at this offset
+ // from reverse engineering.
+ uint64_t offset = pointer_width * 13;
+ uint32_t error = 0;
+ if (!region->GetMemoryAtAddress(thread_.teb + offset, &error)) {
+ BPLOG(ERROR) << "GetLastError()'s memory isn't mapped in this minidump";
+ return 0;
+ }
+
+ if (minidump_->swap()) {
+ Swap(&error);
+ }
+
+ return error;
+}
+
+
+
+MinidumpContext* MinidumpThread::GetContext() {
+ if (!valid_) {
+ BPLOG(ERROR) << "Invalid MinidumpThread for GetContext";
+ return NULL;
+ }
+
+ if (!context_) {
+ if (!minidump_->SeekSet(thread_.thread_context.rva)) {
+ BPLOG(ERROR) << "MinidumpThread cannot seek to context";
+ return NULL;
+ }
+
+ scoped_ptr<MinidumpContext> context(new MinidumpContext(minidump_));
+
+ if (!context->Read(thread_.thread_context.data_size)) {
+ BPLOG(ERROR) << "MinidumpThread cannot read context";
+ return NULL;
+ }
+
+ context_ = context.release();
+ }
+
+ return context_;
+}
+
+
+bool MinidumpThread::GetThreadID(uint32_t *thread_id) const {
+ BPLOG_IF(ERROR, !thread_id) << "MinidumpThread::GetThreadID requires "
+ "|thread_id|";
+ assert(thread_id);
+ *thread_id = 0;
+
+ if (!valid_) {
+ BPLOG(ERROR) << "Invalid MinidumpThread for GetThreadID";
+ return false;
+ }
+
+ *thread_id = thread_.thread_id;
+ return true;
+}
+
+
+void MinidumpThread::Print() {
+ if (!valid_) {
+ BPLOG(ERROR) << "MinidumpThread cannot print invalid data";
+ return;
+ }
+
+ printf("MDRawThread\n");
+ printf(" thread_id = 0x%x\n", thread_.thread_id);
+ printf(" suspend_count = %d\n", thread_.suspend_count);
+ printf(" priority_class = 0x%x\n", thread_.priority_class);
+ printf(" priority = 0x%x\n", thread_.priority);
+ printf(" teb = 0x%" PRIx64 "\n", thread_.teb);
+ printf(" stack.start_of_memory_range = 0x%" PRIx64 "\n",
+ thread_.stack.start_of_memory_range);
+ printf(" stack.memory.data_size = 0x%x\n",
+ thread_.stack.memory.data_size);
+ printf(" stack.memory.rva = 0x%x\n", thread_.stack.memory.rva);
+ printf(" thread_context.data_size = 0x%x\n",
+ thread_.thread_context.data_size);
+ printf(" thread_context.rva = 0x%x\n",
+ thread_.thread_context.rva);
+
+ MinidumpContext* context = GetContext();
+ if (context) {
+ printf("\n");
+ context->Print();
+ } else {
+ printf(" (no context)\n");
+ printf("\n");
+ }
+
+ MinidumpMemoryRegion* memory = GetMemory();
+ if (memory) {
+ printf("Stack\n");
+ memory->Print();
+ } else {
+ printf("No stack\n");
+ }
+ printf("\n");
+}
+
+
+//
+// MinidumpThreadList
+//
+
+
+uint32_t MinidumpThreadList::max_threads_ = 4096;
+
+
+MinidumpThreadList::MinidumpThreadList(Minidump* minidump)
+ : MinidumpStream(minidump),
+ id_to_thread_map_(),
+ threads_(NULL),
+ thread_count_(0) {
+}
+
+
+MinidumpThreadList::~MinidumpThreadList() {
+ delete threads_;
+}
+
+
+bool MinidumpThreadList::Read(uint32_t expected_size) {
+ // Invalidate cached data.
+ id_to_thread_map_.clear();
+ delete threads_;
+ threads_ = NULL;
+ thread_count_ = 0;
+
+ valid_ = false;
+
+ uint32_t thread_count;
+ if (expected_size < sizeof(thread_count)) {
+ BPLOG(ERROR) << "MinidumpThreadList count size mismatch, " <<
+ expected_size << " < " << sizeof(thread_count);
+ return false;
+ }
+ if (!minidump_->ReadBytes(&thread_count, sizeof(thread_count))) {
+ BPLOG(ERROR) << "MinidumpThreadList cannot read thread count";
+ return false;
+ }
+
+ if (minidump_->swap())
+ Swap(&thread_count);
+
+ if (thread_count > numeric_limits<uint32_t>::max() / sizeof(MDRawThread)) {
+ BPLOG(ERROR) << "MinidumpThreadList thread count " << thread_count <<
+ " would cause multiplication overflow";
+ return false;
+ }
+
+ if (expected_size != sizeof(thread_count) +
+ thread_count * sizeof(MDRawThread)) {
+ // may be padded with 4 bytes on 64bit ABIs for alignment
+ if (expected_size == sizeof(thread_count) + 4 +
+ thread_count * sizeof(MDRawThread)) {
+ uint32_t useless;
+ if (!minidump_->ReadBytes(&useless, 4)) {
+ BPLOG(ERROR) << "MinidumpThreadList cannot read threadlist padded "
+ "bytes";
+ return false;
+ }
+ } else {
+ BPLOG(ERROR) << "MinidumpThreadList size mismatch, " << expected_size <<
+ " != " << sizeof(thread_count) +
+ thread_count * sizeof(MDRawThread);
+ return false;
+ }
+ }
+
+
+ if (thread_count > max_threads_) {
+ BPLOG(ERROR) << "MinidumpThreadList count " << thread_count <<
+ " exceeds maximum " << max_threads_;
+ return false;
+ }
+
+ if (thread_count != 0) {
+ scoped_ptr<MinidumpThreads> threads(
+ new MinidumpThreads(thread_count, MinidumpThread(minidump_)));
+
+ for (unsigned int thread_index = 0;
+ thread_index < thread_count;
+ ++thread_index) {
+ MinidumpThread* thread = &(*threads)[thread_index];
+
+ // Assume that the file offset is correct after the last read.
+ if (!thread->Read()) {
+ BPLOG(ERROR) << "MinidumpThreadList cannot read thread " <<
+ thread_index << "/" << thread_count;
+ return false;
+ }
+
+ uint32_t thread_id;
+ if (!thread->GetThreadID(&thread_id)) {
+ BPLOG(ERROR) << "MinidumpThreadList cannot get thread ID for thread " <<
+ thread_index << "/" << thread_count;
+ return false;
+ }
+
+ if (GetThreadByID(thread_id)) {
+ // Another thread with this ID is already in the list. Data error.
+ BPLOG(ERROR) << "MinidumpThreadList found multiple threads with ID " <<
+ HexString(thread_id) << " at thread " <<
+ thread_index << "/" << thread_count;
+ return false;
+ }
+ id_to_thread_map_[thread_id] = thread;
+ }
+
+ threads_ = threads.release();
+ }
+
+ thread_count_ = thread_count;
+
+ valid_ = true;
+ return true;
+}
+
+
+MinidumpThread* MinidumpThreadList::GetThreadAtIndex(unsigned int index)
+ const {
+ if (!valid_) {
+ BPLOG(ERROR) << "Invalid MinidumpThreadList for GetThreadAtIndex";
+ return NULL;
+ }
+
+ if (index >= thread_count_) {
+ BPLOG(ERROR) << "MinidumpThreadList index out of range: " <<
+ index << "/" << thread_count_;
+ return NULL;
+ }
+
+ return &(*threads_)[index];
+}
+
+
+MinidumpThread* MinidumpThreadList::GetThreadByID(uint32_t thread_id) {
+ // Don't check valid_. Read calls this method before everything is
+ // validated. It is safe to not check valid_ here.
+ return id_to_thread_map_[thread_id];
+}
+
+
+void MinidumpThreadList::Print() {
+ if (!valid_) {
+ BPLOG(ERROR) << "MinidumpThreadList cannot print invalid data";
+ return;
+ }
+
+ printf("MinidumpThreadList\n");
+ printf(" thread_count = %d\n", thread_count_);
+ printf("\n");
+
+ for (unsigned int thread_index = 0;
+ thread_index < thread_count_;
+ ++thread_index) {
+ printf("thread[%d]\n", thread_index);
+
+ (*threads_)[thread_index].Print();
+ }
+}
+
+
+//
+// MinidumpModule
+//
+
+
+uint32_t MinidumpModule::max_cv_bytes_ = 32768;
+uint32_t MinidumpModule::max_misc_bytes_ = 32768;
+
+
+MinidumpModule::MinidumpModule(Minidump* minidump)
+ : MinidumpObject(minidump),
+ module_valid_(false),
+ has_debug_info_(false),
+ module_(),
+ name_(NULL),
+ cv_record_(NULL),
+ cv_record_signature_(MD_CVINFOUNKNOWN_SIGNATURE),
+ misc_record_(NULL) {
+}
+
+
+MinidumpModule::~MinidumpModule() {
+ delete name_;
+ delete cv_record_;
+ delete misc_record_;
+}
+
+
+bool MinidumpModule::Read() {
+ // Invalidate cached data.
+ delete name_;
+ name_ = NULL;
+ delete cv_record_;
+ cv_record_ = NULL;
+ cv_record_signature_ = MD_CVINFOUNKNOWN_SIGNATURE;
+ delete misc_record_;
+ misc_record_ = NULL;
+
+ module_valid_ = false;
+ has_debug_info_ = false;
+ valid_ = false;
+
+ if (!minidump_->ReadBytes(&module_, MD_MODULE_SIZE)) {
+ BPLOG(ERROR) << "MinidumpModule cannot read module";
+ return false;
+ }
+
+ if (minidump_->swap()) {
+ Swap(&module_.base_of_image);
+ Swap(&module_.size_of_image);
+ Swap(&module_.checksum);
+ Swap(&module_.time_date_stamp);
+ Swap(&module_.module_name_rva);
+ Swap(&module_.version_info.signature);
+ Swap(&module_.version_info.struct_version);
+ Swap(&module_.version_info.file_version_hi);
+ Swap(&module_.version_info.file_version_lo);
+ Swap(&module_.version_info.product_version_hi);
+ Swap(&module_.version_info.product_version_lo);
+ Swap(&module_.version_info.file_flags_mask);
+ Swap(&module_.version_info.file_flags);
+ Swap(&module_.version_info.file_os);
+ Swap(&module_.version_info.file_type);
+ Swap(&module_.version_info.file_subtype);
+ Swap(&module_.version_info.file_date_hi);
+ Swap(&module_.version_info.file_date_lo);
+ Swap(&module_.cv_record);
+ Swap(&module_.misc_record);
+ // Don't swap reserved fields because their contents are unknown (as
+ // are their proper widths).
+ }
+
+ // Check for base + size overflow or undersize.
+ if (module_.size_of_image == 0 ||
+ module_.size_of_image >
+ numeric_limits<uint64_t>::max() - module_.base_of_image) {
+ BPLOG(ERROR) << "MinidumpModule has a module problem, " <<
+ HexString(module_.base_of_image) << "+" <<
+ HexString(module_.size_of_image);
+ return false;
+ }
+
+ module_valid_ = true;
+ return true;
+}
+
+
+bool MinidumpModule::ReadAuxiliaryData() {
+ if (!module_valid_) {
+ BPLOG(ERROR) << "Invalid MinidumpModule for ReadAuxiliaryData";
+ return false;
+ }
+
+ // Each module must have a name.
+ name_ = minidump_->ReadString(module_.module_name_rva);
+ if (!name_) {
+ BPLOG(ERROR) << "MinidumpModule could not read name";
+ return false;
+ }
+
+ // At this point, we have enough info for the module to be valid.
+ valid_ = true;
+
+ // CodeView and miscellaneous debug records are only required if the
+ // module indicates that they exist.
+ if (module_.cv_record.data_size && !GetCVRecord(NULL)) {
+ BPLOG(ERROR) << "MinidumpModule has no CodeView record, "
+ "but one was expected";
+ return false;
+ }
+
+ if (module_.misc_record.data_size && !GetMiscRecord(NULL)) {
+ BPLOG(ERROR) << "MinidumpModule has no miscellaneous debug record, "
+ "but one was expected";
+ return false;
+ }
+
+ has_debug_info_ = true;
+ return true;
+}
+
+
+string MinidumpModule::code_file() const {
+ if (!valid_) {
+ BPLOG(ERROR) << "Invalid MinidumpModule for code_file";
+ return "";
+ }
+
+ return *name_;
+}
+
+
+string MinidumpModule::code_identifier() const {
+ if (!valid_) {
+ BPLOG(ERROR) << "Invalid MinidumpModule for code_identifier";
+ return "";
+ }
+
+ if (!has_debug_info_)
+ return "";
+
+ MinidumpSystemInfo *minidump_system_info = minidump_->GetSystemInfo();
+ if (!minidump_system_info) {
+ BPLOG(ERROR) << "MinidumpModule code_identifier requires "
+ "MinidumpSystemInfo";
+ return "";
+ }
+
+ const MDRawSystemInfo *raw_system_info = minidump_system_info->system_info();
+ if (!raw_system_info) {
+ BPLOG(ERROR) << "MinidumpModule code_identifier requires MDRawSystemInfo";
+ return "";
+ }
+
+ string identifier;
+
+ switch (raw_system_info->platform_id) {
+ case MD_OS_WIN32_NT:
+ case MD_OS_WIN32_WINDOWS: {
+ // Use the same format that the MS symbol server uses in filesystem
+ // hierarchies.
+ char identifier_string[17];
+ snprintf(identifier_string, sizeof(identifier_string), "%08X%x",
+ module_.time_date_stamp, module_.size_of_image);
+ identifier = identifier_string;
+ break;
+ }
+
+ case MD_OS_ANDROID:
+ case MD_OS_FUCHSIA:
+ case MD_OS_LINUX: {
+ // If ELF CodeView data is present, return the debug id.
+ if (cv_record_ && cv_record_signature_ == MD_CVINFOELF_SIGNATURE) {
+ const MDCVInfoELF* cv_record_elf =
+ reinterpret_cast<const MDCVInfoELF*>(&(*cv_record_)[0]);
+ assert(cv_record_elf->cv_signature == MD_CVINFOELF_SIGNATURE);
+
+ for (unsigned int build_id_index = 0;
+ build_id_index < (cv_record_->size() - MDCVInfoELF_minsize);
+ ++build_id_index) {
+ char hexbyte[3];
+ snprintf(hexbyte, sizeof(hexbyte), "%02x",
+ cv_record_elf->build_id[build_id_index]);
+ identifier += hexbyte;
+ }
+ break;
+ }
+ // Otherwise fall through to the case below.
+ BP_FALLTHROUGH;
+ }
+
+ case MD_OS_MAC_OS_X:
+ case MD_OS_IOS:
+ case MD_OS_SOLARIS:
+ case MD_OS_NACL:
+ case MD_OS_PS3: {
+ // TODO(mmentovai): support uuid extension if present, otherwise fall
+ // back to version (from LC_ID_DYLIB?), otherwise fall back to something
+ // else.
+ identifier = "id";
+ break;
+ }
+
+ default: {
+ // Without knowing what OS generated the dump, we can't generate a good
+ // identifier. Return an empty string, signalling failure.
+ BPLOG(ERROR) << "MinidumpModule code_identifier requires known platform, "
+ "found " << HexString(raw_system_info->platform_id);
+ break;
+ }
+ }
+
+ return identifier;
+}
+
+
+string MinidumpModule::debug_file() const {
+ if (!valid_) {
+ BPLOG(ERROR) << "Invalid MinidumpModule for debug_file";
+ return "";
+ }
+
+ if (!has_debug_info_)
+ return "";
+
+ string file;
+ // Prefer the CodeView record if present.
+ if (cv_record_) {
+ if (cv_record_signature_ == MD_CVINFOPDB70_SIGNATURE) {
+ // It's actually an MDCVInfoPDB70 structure.
+ const MDCVInfoPDB70* cv_record_70 =
+ reinterpret_cast<const MDCVInfoPDB70*>(&(*cv_record_)[0]);
+ assert(cv_record_70->cv_signature == MD_CVINFOPDB70_SIGNATURE);
+
+ // GetCVRecord guarantees pdb_file_name is null-terminated.
+ file = reinterpret_cast<const char*>(cv_record_70->pdb_file_name);
+ } else if (cv_record_signature_ == MD_CVINFOPDB20_SIGNATURE) {
+ // It's actually an MDCVInfoPDB20 structure.
+ const MDCVInfoPDB20* cv_record_20 =
+ reinterpret_cast<const MDCVInfoPDB20*>(&(*cv_record_)[0]);
+ assert(cv_record_20->cv_header.signature == MD_CVINFOPDB20_SIGNATURE);
+
+ // GetCVRecord guarantees pdb_file_name is null-terminated.
+ file = reinterpret_cast<const char*>(cv_record_20->pdb_file_name);
+ } else if (cv_record_signature_ == MD_CVINFOELF_SIGNATURE) {
+ // It's actually an MDCVInfoELF structure.
+ assert(reinterpret_cast<const MDCVInfoELF*>(&(*cv_record_)[0])->
+ cv_signature == MD_CVINFOELF_SIGNATURE);
+
+ // For MDCVInfoELF, the debug file is the code file.
+ file = *name_;
+ }
+
+ // If there's a CodeView record but it doesn't match a known signature,
+ // try the miscellaneous record.
+ }
+
+ if (file.empty()) {
+ // No usable CodeView record. Try the miscellaneous debug record.
+ if (misc_record_) {
+ const MDImageDebugMisc* misc_record =
+ reinterpret_cast<const MDImageDebugMisc *>(&(*misc_record_)[0]);
+ if (!misc_record->unicode) {
+ // If it's not Unicode, just stuff it into the string. It's unclear
+ // if misc_record->data is 0-terminated, so use an explicit size.
+ file = string(
+ reinterpret_cast<const char*>(misc_record->data),
+ module_.misc_record.data_size - MDImageDebugMisc_minsize);
+ } else {
+ // There's a misc_record but it encodes the debug filename in UTF-16.
+ // (Actually, because miscellaneous records are so old, it's probably
+ // UCS-2.) Convert it to UTF-8 for congruity with the other strings
+ // that this method (and all other methods in the Minidump family)
+ // return.
+
+ size_t bytes =
+ module_.misc_record.data_size - MDImageDebugMisc_minsize;
+ if (bytes % 2 == 0) {
+ size_t utf16_words = bytes / 2;
+
+ // UTF16ToUTF8 expects a vector<uint16_t>, so create a temporary one
+ // and copy the UTF-16 data into it.
+ vector<uint16_t> string_utf16(utf16_words);
+ if (utf16_words)
+ memcpy(&string_utf16[0], &misc_record->data, bytes);
+
+ // GetMiscRecord already byte-swapped the data[] field if it contains
+ // UTF-16, so pass false as the swap argument.
+ scoped_ptr<string> new_file(UTF16ToUTF8(string_utf16, false));
+ if (new_file.get() != nullptr) {
+ file = *new_file;
+ }
+ }
+ }
+ }
+ }
+
+ // Relatively common case
+ BPLOG_IF(INFO, file.empty()) << "MinidumpModule could not determine "
+ "debug_file for " << *name_;
+
+ return file;
+}
+
+static string guid_and_age_to_debug_id(const MDGUID& guid,
+ uint32_t age) {
+ char identifier_string[41];
+ snprintf(identifier_string, sizeof(identifier_string),
+ "%08X%04X%04X%02X%02X%02X%02X%02X%02X%02X%02X%x",
+ guid.data1,
+ guid.data2,
+ guid.data3,
+ guid.data4[0],
+ guid.data4[1],
+ guid.data4[2],
+ guid.data4[3],
+ guid.data4[4],
+ guid.data4[5],
+ guid.data4[6],
+ guid.data4[7],
+ age);
+ return identifier_string;
+}
+
+string MinidumpModule::debug_identifier() const {
+ if (!valid_) {
+ BPLOG(ERROR) << "Invalid MinidumpModule for debug_identifier";
+ return "";
+ }
+
+ if (!has_debug_info_)
+ return "";
+
+ string identifier;
+
+ // Use the CodeView record if present.
+ if (cv_record_) {
+ if (cv_record_signature_ == MD_CVINFOPDB70_SIGNATURE) {
+ // It's actually an MDCVInfoPDB70 structure.
+ const MDCVInfoPDB70* cv_record_70 =
+ reinterpret_cast<const MDCVInfoPDB70*>(&(*cv_record_)[0]);
+ assert(cv_record_70->cv_signature == MD_CVINFOPDB70_SIGNATURE);
+
+ // Use the same format that the MS symbol server uses in filesystem
+ // hierarchies.
+ identifier = guid_and_age_to_debug_id(cv_record_70->signature,
+ cv_record_70->age);
+ } else if (cv_record_signature_ == MD_CVINFOPDB20_SIGNATURE) {
+ // It's actually an MDCVInfoPDB20 structure.
+ const MDCVInfoPDB20* cv_record_20 =
+ reinterpret_cast<const MDCVInfoPDB20*>(&(*cv_record_)[0]);
+ assert(cv_record_20->cv_header.signature == MD_CVINFOPDB20_SIGNATURE);
+
+ // Use the same format that the MS symbol server uses in filesystem
+ // hierarchies.
+ char identifier_string[17];
+ snprintf(identifier_string, sizeof(identifier_string),
+ "%08X%x", cv_record_20->signature, cv_record_20->age);
+ identifier = identifier_string;
+ } else if (cv_record_signature_ == MD_CVINFOELF_SIGNATURE) {
+ // It's actually an MDCVInfoELF structure.
+ const MDCVInfoELF* cv_record_elf =
+ reinterpret_cast<const MDCVInfoELF*>(&(*cv_record_)[0]);
+ assert(cv_record_elf->cv_signature == MD_CVINFOELF_SIGNATURE);
+
+ // For backwards-compatibility, stuff as many bytes as will fit into
+ // a MDGUID and use the MS symbol server format as MDCVInfoPDB70 does
+ // with age = 0. Historically Breakpad would do this during dump
+ // writing to fit the build id data into a MDCVInfoPDB70 struct.
+ // The full build id is available by calling code_identifier.
+ MDGUID guid = {0};
+ memcpy(&guid, &cv_record_elf->build_id,
+ std::min(cv_record_->size() - MDCVInfoELF_minsize,
+ sizeof(MDGUID)));
+ identifier = guid_and_age_to_debug_id(guid, 0);
+ }
+ }
+
+ // TODO(mmentovai): if there's no usable CodeView record, there might be a
+ // miscellaneous debug record. It only carries a filename, though, and no
+ // identifier. I'm not sure what the right thing to do for the identifier
+ // is in that case, but I don't expect to find many modules without a
+ // CodeView record (or some other Breakpad extension structure in place of
+ // a CodeView record). Treat it as an error (empty identifier) for now.
+
+ // TODO(mmentovai): on the Mac, provide fallbacks as in code_identifier().
+
+ // Relatively common case
+ BPLOG_IF(INFO, identifier.empty()) << "MinidumpModule could not determine "
+ "debug_identifier for " << *name_;
+
+ return identifier;
+}
+
+
+string MinidumpModule::version() const {
+ if (!valid_) {
+ BPLOG(ERROR) << "Invalid MinidumpModule for version";
+ return "";
+ }
+
+ string version;
+
+ if (module_.version_info.signature == MD_VSFIXEDFILEINFO_SIGNATURE &&
+ module_.version_info.struct_version & MD_VSFIXEDFILEINFO_VERSION) {
+ char version_string[24];
+ snprintf(version_string, sizeof(version_string), "%u.%u.%u.%u",
+ module_.version_info.file_version_hi >> 16,
+ module_.version_info.file_version_hi & 0xffff,
+ module_.version_info.file_version_lo >> 16,
+ module_.version_info.file_version_lo & 0xffff);
+ version = version_string;
+ }
+
+ // TODO(mmentovai): possibly support other struct types in place of
+ // the one used with MD_VSFIXEDFILEINFO_SIGNATURE. We can possibly use
+ // a different structure that better represents versioning facilities on
+ // Mac OS X and Linux, instead of forcing them to adhere to the dotted
+ // quad of 16-bit ints that Windows uses.
+
+ BPLOG_IF(INFO, version.empty()) << "MinidumpModule could not determine "
+ "version for " << *name_;
+
+ return version;
+}
+
+
+CodeModule* MinidumpModule::Copy() const {
+ return new BasicCodeModule(this);
+}
+
+
+uint64_t MinidumpModule::shrink_down_delta() const {
+ return 0;
+}
+
+void MinidumpModule::SetShrinkDownDelta(uint64_t shrink_down_delta) {
+ // Not implemented
+ assert(false);
+}
+
+
+const uint8_t* MinidumpModule::GetCVRecord(uint32_t* size) {
+ if (!module_valid_) {
+ BPLOG(ERROR) << "Invalid MinidumpModule for GetCVRecord";
+ return NULL;
+ }
+
+ if (!cv_record_) {
+ // This just guards against 0-sized CodeView records; more specific checks
+ // are used when the signature is checked against various structure types.
+ if (module_.cv_record.data_size == 0) {
+ return NULL;
+ }
+
+ if (!minidump_->SeekSet(module_.cv_record.rva)) {
+ BPLOG(ERROR) << "MinidumpModule could not seek to CodeView record";
+ return NULL;
+ }
+
+ if (module_.cv_record.data_size > max_cv_bytes_) {
+ BPLOG(ERROR) << "MinidumpModule CodeView record size " <<
+ module_.cv_record.data_size << " exceeds maximum " <<
+ max_cv_bytes_;
+ return NULL;
+ }
+
+ // Allocating something that will be accessed as MDCVInfoPDB70 or
+ // MDCVInfoPDB20 but is allocated as uint8_t[] can cause alignment
+ // problems. x86 and ppc are able to cope, though. This allocation
+ // style is needed because the MDCVInfoPDB70 or MDCVInfoPDB20 are
+ // variable-sized due to their pdb_file_name fields; these structures
+ // are not MDCVInfoPDB70_minsize or MDCVInfoPDB20_minsize and treating
+ // them as such would result in incomplete structures or overruns.
+ scoped_ptr< vector<uint8_t> > cv_record(
+ new vector<uint8_t>(module_.cv_record.data_size));
+
+ if (!minidump_->ReadBytes(&(*cv_record)[0], module_.cv_record.data_size)) {
+ BPLOG(ERROR) << "MinidumpModule could not read CodeView record";
+ return NULL;
+ }
+
+ uint32_t signature = MD_CVINFOUNKNOWN_SIGNATURE;
+ if (module_.cv_record.data_size > sizeof(signature)) {
+ MDCVInfoPDB70* cv_record_signature =
+ reinterpret_cast<MDCVInfoPDB70*>(&(*cv_record)[0]);
+ signature = cv_record_signature->cv_signature;
+ if (minidump_->swap())
+ Swap(&signature);
+ }
+
+ if (signature == MD_CVINFOPDB70_SIGNATURE) {
+ // Now that the structure type is known, recheck the size,
+ // ensuring at least one byte for the null terminator.
+ if (MDCVInfoPDB70_minsize + 1 > module_.cv_record.data_size) {
+ BPLOG(ERROR) << "MinidumpModule CodeView7 record size mismatch, " <<
+ MDCVInfoPDB70_minsize << " > " <<
+ module_.cv_record.data_size;
+ return NULL;
+ }
+
+ if (minidump_->swap()) {
+ MDCVInfoPDB70* cv_record_70 =
+ reinterpret_cast<MDCVInfoPDB70*>(&(*cv_record)[0]);
+ Swap(&cv_record_70->cv_signature);
+ Swap(&cv_record_70->signature);
+ Swap(&cv_record_70->age);
+ // Don't swap cv_record_70.pdb_file_name because it's an array of 8-bit
+ // quantities. (It's a path, is it UTF-8?)
+ }
+
+ // The last field of either structure is null-terminated 8-bit character
+ // data. Ensure that it's null-terminated.
+ if ((*cv_record)[module_.cv_record.data_size - 1] != '\0') {
+ BPLOG(ERROR) << "MinidumpModule CodeView7 record string is not "
+ "0-terminated";
+ return NULL;
+ }
+ } else if (signature == MD_CVINFOPDB20_SIGNATURE) {
+ // Now that the structure type is known, recheck the size,
+ // ensuring at least one byte for the null terminator.
+ if (MDCVInfoPDB20_minsize + 1 > module_.cv_record.data_size) {
+ BPLOG(ERROR) << "MinidumpModule CodeView2 record size mismatch, " <<
+ MDCVInfoPDB20_minsize << " > " <<
+ module_.cv_record.data_size;
+ return NULL;
+ }
+ if (minidump_->swap()) {
+ MDCVInfoPDB20* cv_record_20 =
+ reinterpret_cast<MDCVInfoPDB20*>(&(*cv_record)[0]);
+ Swap(&cv_record_20->cv_header.signature);
+ Swap(&cv_record_20->cv_header.offset);
+ Swap(&cv_record_20->signature);
+ Swap(&cv_record_20->age);
+ // Don't swap cv_record_20.pdb_file_name because it's an array of 8-bit
+ // quantities. (It's a path, is it UTF-8?)
+ }
+
+ // The last field of either structure is null-terminated 8-bit character
+ // data. Ensure that it's null-terminated.
+ if ((*cv_record)[module_.cv_record.data_size - 1] != '\0') {
+ BPLOG(ERROR) << "MindumpModule CodeView2 record string is not "
+ "0-terminated";
+ return NULL;
+ }
+ } else if (signature == MD_CVINFOELF_SIGNATURE) {
+ // Now that the structure type is known, recheck the size.
+ if (MDCVInfoELF_minsize > module_.cv_record.data_size) {
+ BPLOG(ERROR) << "MinidumpModule CodeViewELF record size mismatch, " <<
+ MDCVInfoELF_minsize << " > " <<
+ module_.cv_record.data_size;
+ return NULL;
+ }
+ if (minidump_->swap()) {
+ MDCVInfoELF* cv_record_elf =
+ reinterpret_cast<MDCVInfoELF*>(&(*cv_record)[0]);
+ Swap(&cv_record_elf->cv_signature);
+ }
+ }
+
+ // If the signature doesn't match something above, it's not something
+ // that Breakpad can presently handle directly. Because some modules in
+ // the wild contain such CodeView records as MD_CVINFOCV50_SIGNATURE,
+ // don't bail out here - allow the data to be returned to the user,
+ // although byte-swapping can't be done.
+
+ // Store the vector type because that's how storage was allocated, but
+ // return it casted to uint8_t*.
+ cv_record_ = cv_record.release();
+ cv_record_signature_ = signature;
+ }
+
+ if (size)
+ *size = module_.cv_record.data_size;
+
+ return &(*cv_record_)[0];
+}
+
+
+const MDImageDebugMisc* MinidumpModule::GetMiscRecord(uint32_t* size) {
+ if (!module_valid_) {
+ BPLOG(ERROR) << "Invalid MinidumpModule for GetMiscRecord";
+ return NULL;
+ }
+
+ if (!misc_record_) {
+ if (module_.misc_record.data_size == 0) {
+ return NULL;
+ }
+
+ if (MDImageDebugMisc_minsize > module_.misc_record.data_size) {
+ BPLOG(ERROR) << "MinidumpModule miscellaneous debugging record "
+ "size mismatch, " << MDImageDebugMisc_minsize << " > " <<
+ module_.misc_record.data_size;
+ return NULL;
+ }
+
+ if (!minidump_->SeekSet(module_.misc_record.rva)) {
+ BPLOG(ERROR) << "MinidumpModule could not seek to miscellaneous "
+ "debugging record";
+ return NULL;
+ }
+
+ if (module_.misc_record.data_size > max_misc_bytes_) {
+ BPLOG(ERROR) << "MinidumpModule miscellaneous debugging record size " <<
+ module_.misc_record.data_size << " exceeds maximum " <<
+ max_misc_bytes_;
+ return NULL;
+ }
+
+ // Allocating something that will be accessed as MDImageDebugMisc but
+ // is allocated as uint8_t[] can cause alignment problems. x86 and
+ // ppc are able to cope, though. This allocation style is needed
+ // because the MDImageDebugMisc is variable-sized due to its data field;
+ // this structure is not MDImageDebugMisc_minsize and treating it as such
+ // would result in an incomplete structure or an overrun.
+ scoped_ptr< vector<uint8_t> > misc_record_mem(
+ new vector<uint8_t>(module_.misc_record.data_size));
+ MDImageDebugMisc* misc_record =
+ reinterpret_cast<MDImageDebugMisc*>(&(*misc_record_mem)[0]);
+
+ if (!minidump_->ReadBytes(misc_record, module_.misc_record.data_size)) {
+ BPLOG(ERROR) << "MinidumpModule could not read miscellaneous debugging "
+ "record";
+ return NULL;
+ }
+
+ if (minidump_->swap()) {
+ Swap(&misc_record->data_type);
+ Swap(&misc_record->length);
+ // Don't swap misc_record.unicode because it's an 8-bit quantity.
+ // Don't swap the reserved fields for the same reason, and because
+ // they don't contain any valid data.
+ if (misc_record->unicode) {
+ // There is a potential alignment problem, but shouldn't be a problem
+ // in practice due to the layout of MDImageDebugMisc.
+ uint16_t* data16 = reinterpret_cast<uint16_t*>(&(misc_record->data));
+ size_t dataBytes = module_.misc_record.data_size -
+ MDImageDebugMisc_minsize;
+ Swap(data16, dataBytes);
+ }
+ }
+
+ if (module_.misc_record.data_size != misc_record->length) {
+ BPLOG(ERROR) << "MinidumpModule miscellaneous debugging record data "
+ "size mismatch, " << module_.misc_record.data_size <<
+ " != " << misc_record->length;
+ return NULL;
+ }
+
+ // Store the vector type because that's how storage was allocated, but
+ // return it casted to MDImageDebugMisc*.
+ misc_record_ = misc_record_mem.release();
+ }
+
+ if (size)
+ *size = module_.misc_record.data_size;
+
+ return reinterpret_cast<MDImageDebugMisc*>(&(*misc_record_)[0]);
+}
+
+
+void MinidumpModule::Print() {
+ if (!valid_) {
+ BPLOG(ERROR) << "MinidumpModule cannot print invalid data";
+ return;
+ }
+
+ printf("MDRawModule\n");
+ printf(" base_of_image = 0x%" PRIx64 "\n",
+ module_.base_of_image);
+ printf(" size_of_image = 0x%x\n",
+ module_.size_of_image);
+ printf(" checksum = 0x%x\n",
+ module_.checksum);
+ printf(" time_date_stamp = 0x%x %s\n",
+ module_.time_date_stamp,
+ TimeTToUTCString(module_.time_date_stamp).c_str());
+ printf(" module_name_rva = 0x%x\n",
+ module_.module_name_rva);
+ printf(" version_info.signature = 0x%x\n",
+ module_.version_info.signature);
+ printf(" version_info.struct_version = 0x%x\n",
+ module_.version_info.struct_version);
+ printf(" version_info.file_version = 0x%x:0x%x\n",
+ module_.version_info.file_version_hi,
+ module_.version_info.file_version_lo);
+ printf(" version_info.product_version = 0x%x:0x%x\n",
+ module_.version_info.product_version_hi,
+ module_.version_info.product_version_lo);
+ printf(" version_info.file_flags_mask = 0x%x\n",
+ module_.version_info.file_flags_mask);
+ printf(" version_info.file_flags = 0x%x\n",
+ module_.version_info.file_flags);
+ printf(" version_info.file_os = 0x%x\n",
+ module_.version_info.file_os);
+ printf(" version_info.file_type = 0x%x\n",
+ module_.version_info.file_type);
+ printf(" version_info.file_subtype = 0x%x\n",
+ module_.version_info.file_subtype);
+ printf(" version_info.file_date = 0x%x:0x%x\n",
+ module_.version_info.file_date_hi,
+ module_.version_info.file_date_lo);
+ printf(" cv_record.data_size = %d\n",
+ module_.cv_record.data_size);
+ printf(" cv_record.rva = 0x%x\n",
+ module_.cv_record.rva);
+ printf(" misc_record.data_size = %d\n",
+ module_.misc_record.data_size);
+ printf(" misc_record.rva = 0x%x\n",
+ module_.misc_record.rva);
+
+ printf(" (code_file) = \"%s\"\n", code_file().c_str());
+ printf(" (code_identifier) = \"%s\"\n",
+ code_identifier().c_str());
+
+ uint32_t cv_record_size;
+ const uint8_t *cv_record = GetCVRecord(&cv_record_size);
+ if (cv_record) {
+ if (cv_record_signature_ == MD_CVINFOPDB70_SIGNATURE) {
+ const MDCVInfoPDB70* cv_record_70 =
+ reinterpret_cast<const MDCVInfoPDB70*>(cv_record);
+ assert(cv_record_70->cv_signature == MD_CVINFOPDB70_SIGNATURE);
+
+ printf(" (cv_record).cv_signature = 0x%x\n",
+ cv_record_70->cv_signature);
+ printf(" (cv_record).signature = %s\n",
+ MDGUIDToString(cv_record_70->signature).c_str());
+ printf(" (cv_record).age = %d\n",
+ cv_record_70->age);
+ printf(" (cv_record).pdb_file_name = \"%s\"\n",
+ cv_record_70->pdb_file_name);
+ } else if (cv_record_signature_ == MD_CVINFOPDB20_SIGNATURE) {
+ const MDCVInfoPDB20* cv_record_20 =
+ reinterpret_cast<const MDCVInfoPDB20*>(cv_record);
+ assert(cv_record_20->cv_header.signature == MD_CVINFOPDB20_SIGNATURE);
+
+ printf(" (cv_record).cv_header.signature = 0x%x\n",
+ cv_record_20->cv_header.signature);
+ printf(" (cv_record).cv_header.offset = 0x%x\n",
+ cv_record_20->cv_header.offset);
+ printf(" (cv_record).signature = 0x%x %s\n",
+ cv_record_20->signature,
+ TimeTToUTCString(cv_record_20->signature).c_str());
+ printf(" (cv_record).age = %d\n",
+ cv_record_20->age);
+ printf(" (cv_record).pdb_file_name = \"%s\"\n",
+ cv_record_20->pdb_file_name);
+ } else if (cv_record_signature_ == MD_CVINFOELF_SIGNATURE) {
+ const MDCVInfoELF* cv_record_elf =
+ reinterpret_cast<const MDCVInfoELF*>(cv_record);
+ assert(cv_record_elf->cv_signature == MD_CVINFOELF_SIGNATURE);
+
+ printf(" (cv_record).cv_signature = 0x%x\n",
+ cv_record_elf->cv_signature);
+ printf(" (cv_record).build_id = ");
+ for (unsigned int build_id_index = 0;
+ build_id_index < (cv_record_size - MDCVInfoELF_minsize);
+ ++build_id_index) {
+ printf("%02x", cv_record_elf->build_id[build_id_index]);
+ }
+ printf("\n");
+ } else {
+ printf(" (cv_record) = ");
+ for (unsigned int cv_byte_index = 0;
+ cv_byte_index < cv_record_size;
+ ++cv_byte_index) {
+ printf("%02x", cv_record[cv_byte_index]);
+ }
+ printf("\n");
+ }
+ } else {
+ printf(" (cv_record) = (null)\n");
+ }
+
+ const MDImageDebugMisc* misc_record = GetMiscRecord(NULL);
+ if (misc_record) {
+ printf(" (misc_record).data_type = 0x%x\n",
+ misc_record->data_type);
+ printf(" (misc_record).length = 0x%x\n",
+ misc_record->length);
+ printf(" (misc_record).unicode = %d\n",
+ misc_record->unicode);
+ if (misc_record->unicode) {
+ string misc_record_data_utf8;
+ ConvertUTF16BufferToUTF8String(
+ reinterpret_cast<const uint16_t*>(misc_record->data),
+ misc_record->length - offsetof(MDImageDebugMisc, data),
+ &misc_record_data_utf8,
+ false); // already swapped
+ printf(" (misc_record).data = \"%s\"\n",
+ misc_record_data_utf8.c_str());
+ } else {
+ printf(" (misc_record).data = \"%s\"\n",
+ misc_record->data);
+ }
+ } else {
+ printf(" (misc_record) = (null)\n");
+ }
+
+ printf(" (debug_file) = \"%s\"\n", debug_file().c_str());
+ printf(" (debug_identifier) = \"%s\"\n",
+ debug_identifier().c_str());
+ printf(" (version) = \"%s\"\n", version().c_str());
+ printf("\n");
+}
+
+
+//
+// MinidumpModuleList
+//
+
+
+uint32_t MinidumpModuleList::max_modules_ = 2048;
+
+
+MinidumpModuleList::MinidumpModuleList(Minidump* minidump)
+ : MinidumpStream(minidump),
+ range_map_(new RangeMap<uint64_t, unsigned int>()),
+ modules_(NULL),
+ module_count_(0) {
+ MDOSPlatform platform;
+ if (minidump_->GetPlatform(&platform) &&
+ (platform == MD_OS_ANDROID || platform == MD_OS_LINUX)) {
+ range_map_->SetMergeStrategy(MergeRangeStrategy::kTruncateLower);
+ }
+}
+
+
+MinidumpModuleList::~MinidumpModuleList() {
+ delete range_map_;
+ delete modules_;
+}
+
+
+bool MinidumpModuleList::Read(uint32_t expected_size) {
+ // Invalidate cached data.
+ range_map_->Clear();
+ delete modules_;
+ modules_ = NULL;
+ module_count_ = 0;
+
+ valid_ = false;
+
+ uint32_t module_count;
+ if (expected_size < sizeof(module_count)) {
+ BPLOG(ERROR) << "MinidumpModuleList count size mismatch, " <<
+ expected_size << " < " << sizeof(module_count);
+ return false;
+ }
+ if (!minidump_->ReadBytes(&module_count, sizeof(module_count))) {
+ BPLOG(ERROR) << "MinidumpModuleList could not read module count";
+ return false;
+ }
+
+ if (minidump_->swap())
+ Swap(&module_count);
+
+ if (module_count > numeric_limits<uint32_t>::max() / MD_MODULE_SIZE) {
+ BPLOG(ERROR) << "MinidumpModuleList module count " << module_count <<
+ " would cause multiplication overflow";
+ return false;
+ }
+
+ if (expected_size != sizeof(module_count) +
+ module_count * MD_MODULE_SIZE) {
+ // may be padded with 4 bytes on 64bit ABIs for alignment
+ if (expected_size == sizeof(module_count) + 4 +
+ module_count * MD_MODULE_SIZE) {
+ uint32_t useless;
+ if (!minidump_->ReadBytes(&useless, 4)) {
+ BPLOG(ERROR) << "MinidumpModuleList cannot read modulelist padded "
+ "bytes";
+ return false;
+ }
+ } else {
+ BPLOG(ERROR) << "MinidumpModuleList size mismatch, " << expected_size <<
+ " != " << sizeof(module_count) +
+ module_count * MD_MODULE_SIZE;
+ return false;
+ }
+ }
+
+ if (module_count > max_modules_) {
+ BPLOG(ERROR) << "MinidumpModuleList count " << module_count <<
+ " exceeds maximum " << max_modules_;
+ return false;
+ }
+
+ if (module_count != 0) {
+ scoped_ptr<MinidumpModules> modules(
+ new MinidumpModules(module_count, MinidumpModule(minidump_)));
+
+ for (uint32_t module_index = 0; module_index < module_count;
+ ++module_index) {
+ MinidumpModule* module = &(*modules)[module_index];
+
+ // Assume that the file offset is correct after the last read.
+ if (!module->Read()) {
+ BPLOG(ERROR) << "MinidumpModuleList could not read module " <<
+ module_index << "/" << module_count;
+ return false;
+ }
+ }
+
+ // Loop through the module list once more to read additional data and
+ // build the range map. This is done in a second pass because
+ // MinidumpModule::ReadAuxiliaryData seeks around, and if it were
+ // included in the loop above, additional seeks would be needed where
+ // none are now to read contiguous data.
+ uint64_t last_end_address = 0;
+ for (uint32_t module_index = 0; module_index < module_count;
+ ++module_index) {
+ MinidumpModule& module = (*modules)[module_index];
+
+ // ReadAuxiliaryData fails if any data that the module indicates should
+ // exist is missing, but we treat some such cases as valid anyway. See
+ // issue #222: if a debugging record is of a format that's too large to
+ // handle, it shouldn't render the entire dump invalid. Check module
+ // validity before giving up.
+ if (!module.ReadAuxiliaryData() && !module.valid()) {
+ BPLOG(ERROR) << "MinidumpModuleList could not read required module "
+ "auxiliary data for module " <<
+ module_index << "/" << module_count;
+ return false;
+ }
+
+ // It is safe to use module->code_file() after successfully calling
+ // module->ReadAuxiliaryData or noting that the module is valid.
+
+ uint64_t base_address = module.base_address();
+ uint64_t module_size = module.size();
+ if (base_address == static_cast<uint64_t>(-1)) {
+ BPLOG(ERROR) << "MinidumpModuleList found bad base address for module "
+ << module_index << "/" << module_count << ", "
+ << module.code_file();
+ return false;
+ }
+
+ // Some minidumps have additional modules in the list that are duplicates.
+ // Ignore them. See https://crbug.com/838322
+ uint32_t existing_module_index;
+ if (range_map_->RetrieveRange(base_address, &existing_module_index,
+ nullptr, nullptr, nullptr) &&
+ existing_module_index < module_count) {
+ const MinidumpModule& existing_module =
+ (*modules)[existing_module_index];
+ if (existing_module.base_address() == module.base_address() &&
+ existing_module.size() == module.size() &&
+ existing_module.code_file() == module.code_file() &&
+ existing_module.code_identifier() == module.code_identifier()) {
+ continue;
+ }
+ }
+
+ const bool is_android = minidump_->IsAndroid();
+ if (!StoreRange(module, base_address, module_index, module_count,
+ is_android)) {
+ if (!is_android || base_address >= last_end_address) {
+ BPLOG(ERROR) << "MinidumpModuleList could not store module "
+ << module_index << "/" << module_count << ", "
+ << module.code_file() << ", " << HexString(base_address)
+ << "+" << HexString(module_size);
+ return false;
+ }
+
+ // If failed due to apparent range overlap the cause may be the client
+ // correction applied for Android packed relocations. If this is the
+ // case, back out the client correction and retry.
+ assert(is_android);
+ module_size -= last_end_address - base_address;
+ base_address = last_end_address;
+ if (!range_map_->StoreRange(base_address, module_size, module_index)) {
+ BPLOG(ERROR) << "MinidumpModuleList could not store module "
+ << module_index << "/" << module_count << ", "
+ << module.code_file() << ", " << HexString(base_address)
+ << "+" << HexString(module_size) << ", after adjusting";
+ return false;
+ }
+ }
+ last_end_address = base_address + module_size;
+ }
+
+ modules_ = modules.release();
+ }
+
+ module_count_ = module_count;
+
+ valid_ = true;
+ return true;
+}
+
+bool MinidumpModuleList::StoreRange(const MinidumpModule& module,
+ uint64_t base_address,
+ uint32_t module_index,
+ uint32_t module_count,
+ bool is_android) {
+ if (range_map_->StoreRange(base_address, module.size(), module_index))
+ return true;
+
+ // Android's shared memory implementation /dev/ashmem can contain duplicate
+ // entries for JITted code, so ignore these.
+ // TODO(wfh): Remove this code when Android is fixed.
+ // See https://crbug.com/439531
+ if (is_android && IsDevAshmem(module.code_file())) {
+ BPLOG(INFO) << "MinidumpModuleList ignoring overlapping module "
+ << module_index << "/" << module_count << ", "
+ << module.code_file() << ", " << HexString(base_address) << "+"
+ << HexString(module.size());
+ return true;
+ }
+
+ return false;
+}
+
+const MinidumpModule* MinidumpModuleList::GetModuleForAddress(
+ uint64_t address) const {
+ if (!valid_) {
+ BPLOG(ERROR) << "Invalid MinidumpModuleList for GetModuleForAddress";
+ return NULL;
+ }
+
+ unsigned int module_index;
+ if (!range_map_->RetrieveRange(address, &module_index, NULL /* base */,
+ NULL /* delta */, NULL /* size */)) {
+ BPLOG(INFO) << "MinidumpModuleList has no module at " <<
+ HexString(address);
+ return NULL;
+ }
+
+ return GetModuleAtIndex(module_index);
+}
+
+
+const MinidumpModule* MinidumpModuleList::GetMainModule() const {
+ if (!valid_) {
+ BPLOG(ERROR) << "Invalid MinidumpModuleList for GetMainModule";
+ return NULL;
+ }
+
+ // The main code module is the first one present in a minidump file's
+ // MDRawModuleList.
+ return GetModuleAtIndex(0);
+}
+
+
+const MinidumpModule* MinidumpModuleList::GetModuleAtSequence(
+ unsigned int sequence) const {
+ if (!valid_) {
+ BPLOG(ERROR) << "Invalid MinidumpModuleList for GetModuleAtSequence";
+ return NULL;
+ }
+
+ if (sequence >= module_count_) {
+ BPLOG(ERROR) << "MinidumpModuleList sequence out of range: " <<
+ sequence << "/" << module_count_;
+ return NULL;
+ }
+
+ unsigned int module_index;
+ if (!range_map_->RetrieveRangeAtIndex(sequence, &module_index,
+ NULL /* base */, NULL /* delta */,
+ NULL /* size */)) {
+ BPLOG(ERROR) << "MinidumpModuleList has no module at sequence " << sequence;
+ return NULL;
+ }
+
+ return GetModuleAtIndex(module_index);
+}
+
+
+const MinidumpModule* MinidumpModuleList::GetModuleAtIndex(
+ unsigned int index) const {
+ if (!valid_) {
+ BPLOG(ERROR) << "Invalid MinidumpModuleList for GetModuleAtIndex";
+ return NULL;
+ }
+
+ if (index >= module_count_) {
+ BPLOG(ERROR) << "MinidumpModuleList index out of range: " <<
+ index << "/" << module_count_;
+ return NULL;
+ }
+
+ return &(*modules_)[index];
+}
+
+
+const CodeModules* MinidumpModuleList::Copy() const {
+ return new BasicCodeModules(this, range_map_->GetMergeStrategy());
+}
+
+vector<linked_ptr<const CodeModule> >
+MinidumpModuleList::GetShrunkRangeModules() const {
+ return vector<linked_ptr<const CodeModule> >();
+}
+
+void MinidumpModuleList::Print() {
+ if (!valid_) {
+ BPLOG(ERROR) << "MinidumpModuleList cannot print invalid data";
+ return;
+ }
+
+ printf("MinidumpModuleList\n");
+ printf(" module_count = %d\n", module_count_);
+ printf("\n");
+
+ for (unsigned int module_index = 0;
+ module_index < module_count_;
+ ++module_index) {
+ printf("module[%d]\n", module_index);
+
+ (*modules_)[module_index].Print();
+ }
+}
+
+
+//
+// MinidumpMemoryList
+//
+
+
+uint32_t MinidumpMemoryList::max_regions_ = 4096;
+
+
+MinidumpMemoryList::MinidumpMemoryList(Minidump* minidump)
+ : MinidumpStream(minidump),
+ range_map_(new RangeMap<uint64_t, unsigned int>()),
+ descriptors_(NULL),
+ regions_(NULL),
+ region_count_(0) {
+}
+
+
+MinidumpMemoryList::~MinidumpMemoryList() {
+ delete range_map_;
+ delete descriptors_;
+ delete regions_;
+}
+
+
+bool MinidumpMemoryList::Read(uint32_t expected_size) {
+ // Invalidate cached data.
+ delete descriptors_;
+ descriptors_ = NULL;
+ delete regions_;
+ regions_ = NULL;
+ range_map_->Clear();
+ region_count_ = 0;
+
+ valid_ = false;
+
+ uint32_t region_count;
+ if (expected_size < sizeof(region_count)) {
+ BPLOG(ERROR) << "MinidumpMemoryList count size mismatch, " <<
+ expected_size << " < " << sizeof(region_count);
+ return false;
+ }
+ if (!minidump_->ReadBytes(&region_count, sizeof(region_count))) {
+ BPLOG(ERROR) << "MinidumpMemoryList could not read memory region count";
+ return false;
+ }
+
+ if (minidump_->swap())
+ Swap(&region_count);
+
+ if (region_count >
+ numeric_limits<uint32_t>::max() / sizeof(MDMemoryDescriptor)) {
+ BPLOG(ERROR) << "MinidumpMemoryList region count " << region_count <<
+ " would cause multiplication overflow";
+ return false;
+ }
+
+ if (expected_size != sizeof(region_count) +
+ region_count * sizeof(MDMemoryDescriptor)) {
+ // may be padded with 4 bytes on 64bit ABIs for alignment
+ if (expected_size == sizeof(region_count) + 4 +
+ region_count * sizeof(MDMemoryDescriptor)) {
+ uint32_t useless;
+ if (!minidump_->ReadBytes(&useless, 4)) {
+ BPLOG(ERROR) << "MinidumpMemoryList cannot read memorylist padded "
+ "bytes";
+ return false;
+ }
+ } else {
+ BPLOG(ERROR) << "MinidumpMemoryList size mismatch, " << expected_size <<
+ " != " << sizeof(region_count) +
+ region_count * sizeof(MDMemoryDescriptor);
+ return false;
+ }
+ }
+
+ if (region_count > max_regions_) {
+ BPLOG(ERROR) << "MinidumpMemoryList count " << region_count <<
+ " exceeds maximum " << max_regions_;
+ return false;
+ }
+
+ if (region_count != 0) {
+ scoped_ptr<MemoryDescriptors> descriptors(
+ new MemoryDescriptors(region_count));
+
+ // Read the entire array in one fell swoop, instead of reading one entry
+ // at a time in the loop.
+ if (!minidump_->ReadBytes(&(*descriptors)[0],
+ sizeof(MDMemoryDescriptor) * region_count)) {
+ BPLOG(ERROR) << "MinidumpMemoryList could not read memory region list";
+ return false;
+ }
+
+ scoped_ptr<MemoryRegions> regions(
+ new MemoryRegions(region_count, MinidumpMemoryRegion(minidump_)));
+
+ for (unsigned int region_index = 0;
+ region_index < region_count;
+ ++region_index) {
+ MDMemoryDescriptor* descriptor = &(*descriptors)[region_index];
+
+ if (minidump_->swap())
+ Swap(descriptor);
+
+ uint64_t base_address = descriptor->start_of_memory_range;
+ uint32_t region_size = descriptor->memory.data_size;
+
+ // Check for base + size overflow or undersize.
+ if (region_size == 0 ||
+ region_size > numeric_limits<uint64_t>::max() - base_address) {
+ BPLOG(ERROR) << "MinidumpMemoryList has a memory region problem, " <<
+ " region " << region_index << "/" << region_count <<
+ ", " << HexString(base_address) << "+" <<
+ HexString(region_size);
+ return false;
+ }
+
+ if (!range_map_->StoreRange(base_address, region_size, region_index)) {
+ BPLOG(ERROR) << "MinidumpMemoryList could not store memory region " <<
+ region_index << "/" << region_count << ", " <<
+ HexString(base_address) << "+" <<
+ HexString(region_size);
+ return false;
+ }
+
+ (*regions)[region_index].SetDescriptor(descriptor);
+ }
+
+ descriptors_ = descriptors.release();
+ regions_ = regions.release();
+ }
+
+ region_count_ = region_count;
+
+ valid_ = true;
+ return true;
+}
+
+
+MinidumpMemoryRegion* MinidumpMemoryList::GetMemoryRegionAtIndex(
+ unsigned int index) {
+ if (!valid_) {
+ BPLOG(ERROR) << "Invalid MinidumpMemoryList for GetMemoryRegionAtIndex";
+ return NULL;
+ }
+
+ if (index >= region_count_) {
+ BPLOG(ERROR) << "MinidumpMemoryList index out of range: " <<
+ index << "/" << region_count_;
+ return NULL;
+ }
+
+ return &(*regions_)[index];
+}
+
+
+MinidumpMemoryRegion* MinidumpMemoryList::GetMemoryRegionForAddress(
+ uint64_t address) {
+ if (!valid_) {
+ BPLOG(ERROR) << "Invalid MinidumpMemoryList for GetMemoryRegionForAddress";
+ return NULL;
+ }
+
+ unsigned int region_index;
+ if (!range_map_->RetrieveRange(address, &region_index, NULL /* base */,
+ NULL /* delta */, NULL /* size */)) {
+ BPLOG(INFO) << "MinidumpMemoryList has no memory region at " <<
+ HexString(address);
+ return NULL;
+ }
+
+ return GetMemoryRegionAtIndex(region_index);
+}
+
+
+void MinidumpMemoryList::Print() {
+ if (!valid_) {
+ BPLOG(ERROR) << "MinidumpMemoryList cannot print invalid data";
+ return;
+ }
+
+ printf("MinidumpMemoryList\n");
+ printf(" region_count = %d\n", region_count_);
+ printf("\n");
+
+ for (unsigned int region_index = 0;
+ region_index < region_count_;
+ ++region_index) {
+ MDMemoryDescriptor* descriptor = &(*descriptors_)[region_index];
+ printf("region[%d]\n", region_index);
+ printf("MDMemoryDescriptor\n");
+ printf(" start_of_memory_range = 0x%" PRIx64 "\n",
+ descriptor->start_of_memory_range);
+ printf(" memory.data_size = 0x%x\n", descriptor->memory.data_size);
+ printf(" memory.rva = 0x%x\n", descriptor->memory.rva);
+ MinidumpMemoryRegion* region = GetMemoryRegionAtIndex(region_index);
+ if (region) {
+ printf("Memory\n");
+ region->Print();
+ } else {
+ printf("No memory\n");
+ }
+ printf("\n");
+ }
+}
+
+
+//
+// MinidumpException
+//
+
+
+MinidumpException::MinidumpException(Minidump* minidump)
+ : MinidumpStream(minidump),
+ exception_(),
+ context_(NULL) {
+}
+
+
+MinidumpException::~MinidumpException() {
+ delete context_;
+}
+
+
+bool MinidumpException::Read(uint32_t expected_size) {
+ // Invalidate cached data.
+ delete context_;
+ context_ = NULL;
+
+ valid_ = false;
+
+ if (expected_size != sizeof(exception_)) {
+ BPLOG(ERROR) << "MinidumpException size mismatch, " << expected_size <<
+ " != " << sizeof(exception_);
+ return false;
+ }
+
+ if (!minidump_->ReadBytes(&exception_, sizeof(exception_))) {
+ BPLOG(ERROR) << "MinidumpException cannot read exception";
+ return false;
+ }
+
+ if (minidump_->swap()) {
+ Swap(&exception_.thread_id);
+ // exception_.__align is for alignment only and does not need to be
+ // swapped.
+ Swap(&exception_.exception_record.exception_code);
+ Swap(&exception_.exception_record.exception_flags);
+ Swap(&exception_.exception_record.exception_record);
+ Swap(&exception_.exception_record.exception_address);
+ Swap(&exception_.exception_record.number_parameters);
+ // exception_.exception_record.__align is for alignment only and does not
+ // need to be swapped.
+ for (unsigned int parameter_index = 0;
+ parameter_index < MD_EXCEPTION_MAXIMUM_PARAMETERS;
+ ++parameter_index) {
+ Swap(&exception_.exception_record.exception_information[parameter_index]);
+ }
+ Swap(&exception_.thread_context);
+ }
+
+ valid_ = true;
+ return true;
+}
+
+
+bool MinidumpException::GetThreadID(uint32_t *thread_id) const {
+ BPLOG_IF(ERROR, !thread_id) << "MinidumpException::GetThreadID requires "
+ "|thread_id|";
+ assert(thread_id);
+ *thread_id = 0;
+
+ if (!valid_) {
+ BPLOG(ERROR) << "Invalid MinidumpException for GetThreadID";
+ return false;
+ }
+
+ *thread_id = exception_.thread_id;
+ return true;
+}
+
+
+MinidumpContext* MinidumpException::GetContext() {
+ if (!valid_) {
+ BPLOG(ERROR) << "Invalid MinidumpException for GetContext";
+ return NULL;
+ }
+
+ if (!context_) {
+ if (!minidump_->SeekSet(exception_.thread_context.rva)) {
+ BPLOG(ERROR) << "MinidumpException cannot seek to context";
+ return NULL;
+ }
+
+ scoped_ptr<MinidumpContext> context(new MinidumpContext(minidump_));
+
+ // Don't log as an error if we can still fall back on the thread's context
+ // (which must be possible if we got this far.)
+ if (!context->Read(exception_.thread_context.data_size)) {
+ BPLOG(INFO) << "MinidumpException cannot read context";
+ return NULL;
+ }
+
+ context_ = context.release();
+ }
+
+ return context_;
+}
+
+
+void MinidumpException::Print() {
+ if (!valid_) {
+ BPLOG(ERROR) << "MinidumpException cannot print invalid data";
+ return;
+ }
+
+ printf("MDException\n");
+ printf(" thread_id = 0x%x\n",
+ exception_.thread_id);
+ printf(" exception_record.exception_code = 0x%x\n",
+ exception_.exception_record.exception_code);
+ printf(" exception_record.exception_flags = 0x%x\n",
+ exception_.exception_record.exception_flags);
+ printf(" exception_record.exception_record = 0x%" PRIx64 "\n",
+ exception_.exception_record.exception_record);
+ printf(" exception_record.exception_address = 0x%" PRIx64 "\n",
+ exception_.exception_record.exception_address);
+ printf(" exception_record.number_parameters = %d\n",
+ exception_.exception_record.number_parameters);
+ for (unsigned int parameterIndex = 0;
+ parameterIndex < exception_.exception_record.number_parameters;
+ ++parameterIndex) {
+ printf(" exception_record.exception_information[%2d] = 0x%" PRIx64 "\n",
+ parameterIndex,
+ exception_.exception_record.exception_information[parameterIndex]);
+ }
+ printf(" thread_context.data_size = %d\n",
+ exception_.thread_context.data_size);
+ printf(" thread_context.rva = 0x%x\n",
+ exception_.thread_context.rva);
+ MinidumpContext* context = GetContext();
+ if (context) {
+ printf("\n");
+ context->Print();
+ } else {
+ printf(" (no context)\n");
+ printf("\n");
+ }
+}
+
+//
+// MinidumpAssertion
+//
+
+
+MinidumpAssertion::MinidumpAssertion(Minidump* minidump)
+ : MinidumpStream(minidump),
+ assertion_(),
+ expression_(),
+ function_(),
+ file_() {
+}
+
+
+MinidumpAssertion::~MinidumpAssertion() {
+}
+
+
+bool MinidumpAssertion::Read(uint32_t expected_size) {
+ // Invalidate cached data.
+ valid_ = false;
+
+ if (expected_size != sizeof(assertion_)) {
+ BPLOG(ERROR) << "MinidumpAssertion size mismatch, " << expected_size <<
+ " != " << sizeof(assertion_);
+ return false;
+ }
+
+ if (!minidump_->ReadBytes(&assertion_, sizeof(assertion_))) {
+ BPLOG(ERROR) << "MinidumpAssertion cannot read assertion";
+ return false;
+ }
+
+ // Each of {expression, function, file} is a UTF-16 string,
+ // we'll convert them to UTF-8 for ease of use.
+ ConvertUTF16BufferToUTF8String(assertion_.expression,
+ sizeof(assertion_.expression), &expression_,
+ minidump_->swap());
+ ConvertUTF16BufferToUTF8String(assertion_.function,
+ sizeof(assertion_.function), &function_,
+ minidump_->swap());
+ ConvertUTF16BufferToUTF8String(assertion_.file, sizeof(assertion_.file),
+ &file_, minidump_->swap());
+
+ if (minidump_->swap()) {
+ Swap(&assertion_.line);
+ Swap(&assertion_.type);
+ }
+
+ valid_ = true;
+ return true;
+}
+
+void MinidumpAssertion::Print() {
+ if (!valid_) {
+ BPLOG(ERROR) << "MinidumpAssertion cannot print invalid data";
+ return;
+ }
+
+ printf("MDAssertion\n");
+ printf(" expression = %s\n",
+ expression_.c_str());
+ printf(" function = %s\n",
+ function_.c_str());
+ printf(" file = %s\n",
+ file_.c_str());
+ printf(" line = %u\n",
+ assertion_.line);
+ printf(" type = %u\n",
+ assertion_.type);
+ printf("\n");
+}
+
+//
+// MinidumpSystemInfo
+//
+
+
+MinidumpSystemInfo::MinidumpSystemInfo(Minidump* minidump)
+ : MinidumpStream(minidump),
+ system_info_(),
+ csd_version_(NULL),
+ cpu_vendor_(NULL) {
+}
+
+
+MinidumpSystemInfo::~MinidumpSystemInfo() {
+ delete csd_version_;
+ delete cpu_vendor_;
+}
+
+
+bool MinidumpSystemInfo::Read(uint32_t expected_size) {
+ // Invalidate cached data.
+ delete csd_version_;
+ csd_version_ = NULL;
+ delete cpu_vendor_;
+ cpu_vendor_ = NULL;
+
+ valid_ = false;
+
+ if (expected_size != sizeof(system_info_)) {
+ BPLOG(ERROR) << "MinidumpSystemInfo size mismatch, " << expected_size <<
+ " != " << sizeof(system_info_);
+ return false;
+ }
+
+ if (!minidump_->ReadBytes(&system_info_, sizeof(system_info_))) {
+ BPLOG(ERROR) << "MinidumpSystemInfo cannot read system info";
+ return false;
+ }
+
+ if (minidump_->swap()) {
+ Swap(&system_info_.processor_architecture);
+ Swap(&system_info_.processor_level);
+ Swap(&system_info_.processor_revision);
+ // number_of_processors and product_type are 8-bit quantities and need no
+ // swapping.
+ Swap(&system_info_.major_version);
+ Swap(&system_info_.minor_version);
+ Swap(&system_info_.build_number);
+ Swap(&system_info_.platform_id);
+ Swap(&system_info_.csd_version_rva);
+ Swap(&system_info_.suite_mask);
+ // Don't swap the reserved2 field because its contents are unknown.
+
+ if (system_info_.processor_architecture == MD_CPU_ARCHITECTURE_X86 ||
+ system_info_.processor_architecture == MD_CPU_ARCHITECTURE_X86_WIN64) {
+ for (unsigned int i = 0; i < 3; ++i)
+ Swap(&system_info_.cpu.x86_cpu_info.vendor_id[i]);
+ Swap(&system_info_.cpu.x86_cpu_info.version_information);
+ Swap(&system_info_.cpu.x86_cpu_info.feature_information);
+ Swap(&system_info_.cpu.x86_cpu_info.amd_extended_cpu_features);
+ } else {
+ for (unsigned int i = 0; i < 2; ++i)
+ Swap(&system_info_.cpu.other_cpu_info.processor_features[i]);
+ }
+ }
+
+ valid_ = true;
+ return true;
+}
+
+
+string MinidumpSystemInfo::GetOS() {
+ string os;
+
+ if (!valid_) {
+ BPLOG(ERROR) << "Invalid MinidumpSystemInfo for GetOS";
+ return os;
+ }
+
+ switch (system_info_.platform_id) {
+ case MD_OS_WIN32_NT:
+ case MD_OS_WIN32_WINDOWS:
+ os = "windows";
+ break;
+
+ case MD_OS_MAC_OS_X:
+ os = "mac";
+ break;
+
+ case MD_OS_IOS:
+ os = "ios";
+ break;
+
+ case MD_OS_LINUX:
+ os = "linux";
+ break;
+
+ case MD_OS_SOLARIS:
+ os = "solaris";
+ break;
+
+ case MD_OS_ANDROID:
+ os = "android";
+ break;
+
+ case MD_OS_PS3:
+ os = "ps3";
+ break;
+
+ case MD_OS_NACL:
+ os = "nacl";
+ break;
+
+ case MD_OS_FUCHSIA:
+ os = "fuchsia";
+ break;
+
+ default:
+ BPLOG(ERROR) << "MinidumpSystemInfo unknown OS for platform " <<
+ HexString(system_info_.platform_id);
+ break;
+ }
+
+ return os;
+}
+
+
+string MinidumpSystemInfo::GetCPU() {
+ if (!valid_) {
+ BPLOG(ERROR) << "Invalid MinidumpSystemInfo for GetCPU";
+ return "";
+ }
+
+ string cpu;
+
+ switch (system_info_.processor_architecture) {
+ case MD_CPU_ARCHITECTURE_X86:
+ case MD_CPU_ARCHITECTURE_X86_WIN64:
+ cpu = "x86";
+ break;
+
+ case MD_CPU_ARCHITECTURE_AMD64:
+ cpu = "x86-64";
+ break;
+
+ case MD_CPU_ARCHITECTURE_PPC:
+ cpu = "ppc";
+ break;
+
+ case MD_CPU_ARCHITECTURE_PPC64:
+ cpu = "ppc64";
+ break;
+
+ case MD_CPU_ARCHITECTURE_SPARC:
+ cpu = "sparc";
+ break;
+
+ case MD_CPU_ARCHITECTURE_ARM:
+ cpu = "arm";
+ break;
+
+ case MD_CPU_ARCHITECTURE_ARM64:
+ case MD_CPU_ARCHITECTURE_ARM64_OLD:
+ cpu = "arm64";
+ break;
+
+ default:
+ BPLOG(ERROR) << "MinidumpSystemInfo unknown CPU for architecture " <<
+ HexString(system_info_.processor_architecture);
+ break;
+ }
+
+ return cpu;
+}
+
+
+const string* MinidumpSystemInfo::GetCSDVersion() {
+ if (!valid_) {
+ BPLOG(ERROR) << "Invalid MinidumpSystemInfo for GetCSDVersion";
+ return NULL;
+ }
+
+ if (!csd_version_)
+ csd_version_ = minidump_->ReadString(system_info_.csd_version_rva);
+
+ BPLOG_IF(ERROR, !csd_version_) << "MinidumpSystemInfo could not read "
+ "CSD version";
+
+ return csd_version_;
+}
+
+
+const string* MinidumpSystemInfo::GetCPUVendor() {
+ if (!valid_) {
+ BPLOG(ERROR) << "Invalid MinidumpSystemInfo for GetCPUVendor";
+ return NULL;
+ }
+
+ // CPU vendor information can only be determined from x86 minidumps.
+ if (!cpu_vendor_ &&
+ (system_info_.processor_architecture == MD_CPU_ARCHITECTURE_X86 ||
+ system_info_.processor_architecture == MD_CPU_ARCHITECTURE_X86_WIN64)) {
+ char cpu_vendor_string[13];
+ snprintf(cpu_vendor_string, sizeof(cpu_vendor_string),
+ "%c%c%c%c%c%c%c%c%c%c%c%c",
+ system_info_.cpu.x86_cpu_info.vendor_id[0] & 0xff,
+ (system_info_.cpu.x86_cpu_info.vendor_id[0] >> 8) & 0xff,
+ (system_info_.cpu.x86_cpu_info.vendor_id[0] >> 16) & 0xff,
+ (system_info_.cpu.x86_cpu_info.vendor_id[0] >> 24) & 0xff,
+ system_info_.cpu.x86_cpu_info.vendor_id[1] & 0xff,
+ (system_info_.cpu.x86_cpu_info.vendor_id[1] >> 8) & 0xff,
+ (system_info_.cpu.x86_cpu_info.vendor_id[1] >> 16) & 0xff,
+ (system_info_.cpu.x86_cpu_info.vendor_id[1] >> 24) & 0xff,
+ system_info_.cpu.x86_cpu_info.vendor_id[2] & 0xff,
+ (system_info_.cpu.x86_cpu_info.vendor_id[2] >> 8) & 0xff,
+ (system_info_.cpu.x86_cpu_info.vendor_id[2] >> 16) & 0xff,
+ (system_info_.cpu.x86_cpu_info.vendor_id[2] >> 24) & 0xff);
+ cpu_vendor_ = new string(cpu_vendor_string);
+ }
+
+ return cpu_vendor_;
+}
+
+
+void MinidumpSystemInfo::Print() {
+ if (!valid_) {
+ BPLOG(ERROR) << "MinidumpSystemInfo cannot print invalid data";
+ return;
+ }
+
+ printf("MDRawSystemInfo\n");
+ printf(" processor_architecture = 0x%x\n",
+ system_info_.processor_architecture);
+ printf(" processor_level = %d\n",
+ system_info_.processor_level);
+ printf(" processor_revision = 0x%x\n",
+ system_info_.processor_revision);
+ printf(" number_of_processors = %d\n",
+ system_info_.number_of_processors);
+ printf(" product_type = %d\n",
+ system_info_.product_type);
+ printf(" major_version = %d\n",
+ system_info_.major_version);
+ printf(" minor_version = %d\n",
+ system_info_.minor_version);
+ printf(" build_number = %d\n",
+ system_info_.build_number);
+ printf(" platform_id = 0x%x\n",
+ system_info_.platform_id);
+ printf(" csd_version_rva = 0x%x\n",
+ system_info_.csd_version_rva);
+ printf(" suite_mask = 0x%x\n",
+ system_info_.suite_mask);
+ if (system_info_.processor_architecture == MD_CPU_ARCHITECTURE_X86 ||
+ system_info_.processor_architecture == MD_CPU_ARCHITECTURE_X86_WIN64) {
+ printf(" cpu.x86_cpu_info (valid):\n");
+ } else {
+ printf(" cpu.x86_cpu_info (invalid):\n");
+ }
+ for (unsigned int i = 0; i < 3; ++i) {
+ printf(" cpu.x86_cpu_info.vendor_id[%d] = 0x%x\n",
+ i, system_info_.cpu.x86_cpu_info.vendor_id[i]);
+ }
+ printf(" cpu.x86_cpu_info.version_information = 0x%x\n",
+ system_info_.cpu.x86_cpu_info.version_information);
+ printf(" cpu.x86_cpu_info.feature_information = 0x%x\n",
+ system_info_.cpu.x86_cpu_info.feature_information);
+ printf(" cpu.x86_cpu_info.amd_extended_cpu_features = 0x%x\n",
+ system_info_.cpu.x86_cpu_info.amd_extended_cpu_features);
+ if (system_info_.processor_architecture != MD_CPU_ARCHITECTURE_X86 &&
+ system_info_.processor_architecture != MD_CPU_ARCHITECTURE_X86_WIN64) {
+ printf(" cpu.other_cpu_info (valid):\n");
+ for (unsigned int i = 0; i < 2; ++i) {
+ printf(" cpu.other_cpu_info.processor_features[%d] = 0x%" PRIx64 "\n",
+ i, system_info_.cpu.other_cpu_info.processor_features[i]);
+ }
+ }
+ const string* csd_version = GetCSDVersion();
+ if (csd_version) {
+ printf(" (csd_version) = \"%s\"\n",
+ csd_version->c_str());
+ } else {
+ printf(" (csd_version) = (null)\n");
+ }
+ const string* cpu_vendor = GetCPUVendor();
+ if (cpu_vendor) {
+ printf(" (cpu_vendor) = \"%s\"\n",
+ cpu_vendor->c_str());
+ } else {
+ printf(" (cpu_vendor) = (null)\n");
+ }
+ printf("\n");
+}
+
+
+//
+// MinidumpUnloadedModule
+//
+
+
+MinidumpUnloadedModule::MinidumpUnloadedModule(Minidump* minidump)
+ : MinidumpObject(minidump),
+ module_valid_(false),
+ unloaded_module_(),
+ name_(NULL) {
+
+}
+
+MinidumpUnloadedModule::~MinidumpUnloadedModule() {
+ delete name_;
+}
+
+void MinidumpUnloadedModule::Print() {
+ if (!valid_) {
+ BPLOG(ERROR) << "MinidumpUnloadedModule cannot print invalid data";
+ return;
+ }
+
+ printf("MDRawUnloadedModule\n");
+ printf(" base_of_image = 0x%" PRIx64 "\n",
+ unloaded_module_.base_of_image);
+ printf(" size_of_image = 0x%x\n",
+ unloaded_module_.size_of_image);
+ printf(" checksum = 0x%x\n",
+ unloaded_module_.checksum);
+ printf(" time_date_stamp = 0x%x %s\n",
+ unloaded_module_.time_date_stamp,
+ TimeTToUTCString(unloaded_module_.time_date_stamp).c_str());
+ printf(" module_name_rva = 0x%x\n",
+ unloaded_module_.module_name_rva);
+
+ printf(" (code_file) = \"%s\"\n", code_file().c_str());
+ printf(" (code_identifier) = \"%s\"\n",
+ code_identifier().c_str());
+
+ printf(" (debug_file) = \"%s\"\n", debug_file().c_str());
+ printf(" (debug_identifier) = \"%s\"\n",
+ debug_identifier().c_str());
+ printf(" (version) = \"%s\"\n", version().c_str());
+ printf("\n");
+}
+
+string MinidumpUnloadedModule::code_file() const {
+ if (!valid_) {
+ BPLOG(ERROR) << "Invalid MinidumpUnloadedModule for code_file";
+ return "";
+ }
+
+ return *name_;
+}
+
+string MinidumpUnloadedModule::code_identifier() const {
+ if (!valid_) {
+ BPLOG(ERROR) << "Invalid MinidumpUnloadedModule for code_identifier";
+ return "";
+ }
+
+ MinidumpSystemInfo *minidump_system_info = minidump_->GetSystemInfo();
+ if (!minidump_system_info) {
+ BPLOG(ERROR) << "MinidumpUnloadedModule code_identifier requires "
+ "MinidumpSystemInfo";
+ return "";
+ }
+
+ const MDRawSystemInfo *raw_system_info = minidump_system_info->system_info();
+ if (!raw_system_info) {
+ BPLOG(ERROR) << "MinidumpUnloadedModule code_identifier requires "
+ << "MDRawSystemInfo";
+ return "";
+ }
+
+ string identifier;
+
+ switch (raw_system_info->platform_id) {
+ case MD_OS_WIN32_NT:
+ case MD_OS_WIN32_WINDOWS: {
+ // Use the same format that the MS symbol server uses in filesystem
+ // hierarchies.
+ char identifier_string[17];
+ snprintf(identifier_string, sizeof(identifier_string), "%08X%x",
+ unloaded_module_.time_date_stamp,
+ unloaded_module_.size_of_image);
+ identifier = identifier_string;
+ break;
+ }
+
+ case MD_OS_ANDROID:
+ case MD_OS_LINUX:
+ case MD_OS_MAC_OS_X:
+ case MD_OS_IOS:
+ case MD_OS_SOLARIS:
+ case MD_OS_NACL:
+ case MD_OS_PS3: {
+ // TODO(mmentovai): support uuid extension if present, otherwise fall
+ // back to version (from LC_ID_DYLIB?), otherwise fall back to something
+ // else.
+ identifier = "id";
+ break;
+ }
+
+ default: {
+ // Without knowing what OS generated the dump, we can't generate a good
+ // identifier. Return an empty string, signalling failure.
+ BPLOG(ERROR) << "MinidumpUnloadedModule code_identifier requires known "
+ << "platform, found "
+ << HexString(raw_system_info->platform_id);
+ break;
+ }
+ }
+
+ return identifier;
+}
+
+string MinidumpUnloadedModule::debug_file() const {
+ return ""; // No debug info provided with unloaded modules
+}
+
+string MinidumpUnloadedModule::debug_identifier() const {
+ return ""; // No debug info provided with unloaded modules
+}
+
+string MinidumpUnloadedModule::version() const {
+ return ""; // No version info provided with unloaded modules
+}
+
+CodeModule* MinidumpUnloadedModule::Copy() const {
+ return new BasicCodeModule(this);
+}
+
+uint64_t MinidumpUnloadedModule::shrink_down_delta() const {
+ return 0;
+}
+
+void MinidumpUnloadedModule::SetShrinkDownDelta(uint64_t shrink_down_delta) {
+ // Not implemented
+ assert(false);
+}
+
+bool MinidumpUnloadedModule::Read(uint32_t expected_size) {
+
+ delete name_;
+ valid_ = false;
+
+ if (expected_size < sizeof(unloaded_module_)) {
+ BPLOG(ERROR) << "MinidumpUnloadedModule expected size is less than size "
+ << "of struct " << expected_size << " < "
+ << sizeof(unloaded_module_);
+ return false;
+ }
+
+ if (!minidump_->ReadBytes(&unloaded_module_, sizeof(unloaded_module_))) {
+ BPLOG(ERROR) << "MinidumpUnloadedModule cannot read module";
+ return false;
+ }
+
+ if (expected_size > sizeof(unloaded_module_)) {
+ uint32_t module_bytes_remaining = expected_size - sizeof(unloaded_module_);
+ off_t pos = minidump_->Tell();
+ if (!minidump_->SeekSet(pos + module_bytes_remaining)) {
+ BPLOG(ERROR) << "MinidumpUnloadedModule unable to seek to end of module";
+ return false;
+ }
+ }
+
+ if (minidump_->swap()) {
+ Swap(&unloaded_module_.base_of_image);
+ Swap(&unloaded_module_.size_of_image);
+ Swap(&unloaded_module_.checksum);
+ Swap(&unloaded_module_.time_date_stamp);
+ Swap(&unloaded_module_.module_name_rva);
+ }
+
+ // Check for base + size overflow or undersize.
+ if (unloaded_module_.size_of_image == 0 ||
+ unloaded_module_.size_of_image >
+ numeric_limits<uint64_t>::max() - unloaded_module_.base_of_image) {
+ BPLOG(ERROR) << "MinidumpUnloadedModule has a module problem, " <<
+ HexString(unloaded_module_.base_of_image) << "+" <<
+ HexString(unloaded_module_.size_of_image);
+ return false;
+ }
+
+
+ module_valid_ = true;
+ return true;
+}
+
+bool MinidumpUnloadedModule::ReadAuxiliaryData() {
+ if (!module_valid_) {
+ BPLOG(ERROR) << "Invalid MinidumpUnloadedModule for ReadAuxiliaryData";
+ return false;
+ }
+
+ // Each module must have a name.
+ name_ = minidump_->ReadString(unloaded_module_.module_name_rva);
+ if (!name_) {
+ BPLOG(ERROR) << "MinidumpUnloadedModule could not read name";
+ return false;
+ }
+
+ // At this point, we have enough info for the module to be valid.
+ valid_ = true;
+ return true;
+}
+
+//
+// MinidumpUnloadedModuleList
+//
+
+
+uint32_t MinidumpUnloadedModuleList::max_modules_ = 2048;
+
+
+MinidumpUnloadedModuleList::MinidumpUnloadedModuleList(Minidump* minidump)
+ : MinidumpStream(minidump),
+ range_map_(new RangeMap<uint64_t, unsigned int>()),
+ unloaded_modules_(NULL),
+ module_count_(0) {
+ range_map_->SetMergeStrategy(MergeRangeStrategy::kTruncateLower);
+}
+
+MinidumpUnloadedModuleList::~MinidumpUnloadedModuleList() {
+ delete range_map_;
+ delete unloaded_modules_;
+}
+
+void MinidumpUnloadedModuleList::Print() {
+ if (!valid_) {
+ BPLOG(ERROR) << "MinidumpUnloadedModuleList cannot print invalid data";
+ return;
+ }
+
+ printf("MinidumpUnloadedModuleList\n");
+ printf(" module_count = %d\n", module_count_);
+ printf("\n");
+
+ for (unsigned int module_index = 0;
+ module_index < module_count_;
+ ++module_index) {
+ printf("module[%d]\n", module_index);
+
+ (*unloaded_modules_)[module_index].Print();
+ }
+}
+
+bool MinidumpUnloadedModuleList::Read(uint32_t expected_size) {
+ range_map_->Clear();
+ delete unloaded_modules_;
+ unloaded_modules_ = NULL;
+ module_count_ = 0;
+
+ valid_ = false;
+
+ uint32_t size_of_header;
+ if (!minidump_->ReadBytes(&size_of_header, sizeof(size_of_header))) {
+ BPLOG(ERROR) << "MinidumpUnloadedModuleList could not read header size";
+ return false;
+ }
+
+ uint32_t size_of_entry;
+ if (!minidump_->ReadBytes(&size_of_entry, sizeof(size_of_entry))) {
+ BPLOG(ERROR) << "MinidumpUnloadedModuleList could not read entry size";
+ return false;
+ }
+
+ uint32_t number_of_entries;
+ if (!minidump_->ReadBytes(&number_of_entries, sizeof(number_of_entries))) {
+ BPLOG(ERROR) <<
+ "MinidumpUnloadedModuleList could not read number of entries";
+ return false;
+ }
+
+ if (minidump_->swap()) {
+ Swap(&size_of_header);
+ Swap(&size_of_entry);
+ Swap(&number_of_entries);
+ }
+
+ uint32_t header_bytes_remaining = size_of_header - sizeof(size_of_header) -
+ sizeof(size_of_entry) - sizeof(number_of_entries);
+ if (header_bytes_remaining) {
+ off_t pos = minidump_->Tell();
+ if (!minidump_->SeekSet(pos + header_bytes_remaining)) {
+ BPLOG(ERROR) << "MinidumpUnloadedModuleList could not read header sized "
+ << size_of_header;
+ return false;
+ }
+ }
+
+ if (expected_size != size_of_header + (size_of_entry * number_of_entries)) {
+ BPLOG(ERROR) << "MinidumpUnloadedModuleList expected_size mismatch " <<
+ expected_size << " != " << size_of_header << " + (" <<
+ size_of_entry << " * " << number_of_entries << ")";
+ return false;
+ }
+
+ if (number_of_entries > max_modules_) {
+ BPLOG(ERROR) << "MinidumpUnloadedModuleList count " <<
+ number_of_entries << " exceeds maximum " << max_modules_;
+ return false;
+ }
+
+ if (number_of_entries != 0) {
+ scoped_ptr<MinidumpUnloadedModules> modules(
+ new MinidumpUnloadedModules(number_of_entries,
+ MinidumpUnloadedModule(minidump_)));
+
+ for (unsigned int module_index = 0;
+ module_index < number_of_entries;
+ ++module_index) {
+ MinidumpUnloadedModule* module = &(*modules)[module_index];
+
+ if (!module->Read(size_of_entry)) {
+ BPLOG(ERROR) << "MinidumpUnloadedModuleList could not read module " <<
+ module_index << "/" << number_of_entries;
+ return false;
+ }
+ }
+
+ for (unsigned int module_index = 0;
+ module_index < number_of_entries;
+ ++module_index) {
+ MinidumpUnloadedModule* module = &(*modules)[module_index];
+
+ if (!module->ReadAuxiliaryData()) {
+ BPLOG(ERROR) << "MinidumpUnloadedModuleList could not read required "
+ "module auxiliary data for module " <<
+ module_index << "/" << number_of_entries;
+ return false;
+ }
+
+ uint64_t base_address = module->base_address();
+ uint64_t module_size = module->size();
+
+ // Ignore any failures for conflicting address ranges
+ range_map_->StoreRange(base_address, module_size, module_index);
+
+ }
+ unloaded_modules_ = modules.release();
+ }
+
+ module_count_ = number_of_entries;
+ valid_ = true;
+ return true;
+}
+
+const MinidumpUnloadedModule* MinidumpUnloadedModuleList::GetModuleForAddress(
+ uint64_t address) const {
+ if (!valid_) {
+ BPLOG(ERROR)
+ << "Invalid MinidumpUnloadedModuleList for GetModuleForAddress";
+ return NULL;
+ }
+
+ unsigned int module_index;
+ if (!range_map_->RetrieveRange(address, &module_index, NULL /* base */,
+ NULL /* delta */, NULL /* size */)) {
+ BPLOG(INFO) << "MinidumpUnloadedModuleList has no module at "
+ << HexString(address);
+ return NULL;
+ }
+
+ return GetModuleAtIndex(module_index);
+}
+
+const MinidumpUnloadedModule*
+MinidumpUnloadedModuleList::GetMainModule() const {
+ return NULL;
+}
+
+const MinidumpUnloadedModule*
+MinidumpUnloadedModuleList::GetModuleAtSequence(unsigned int sequence) const {
+ if (!valid_) {
+ BPLOG(ERROR)
+ << "Invalid MinidumpUnloadedModuleList for GetModuleAtSequence";
+ return NULL;
+ }
+
+ if (sequence >= module_count_) {
+ BPLOG(ERROR) << "MinidumpUnloadedModuleList sequence out of range: "
+ << sequence << "/" << module_count_;
+ return NULL;
+ }
+
+ unsigned int module_index;
+ if (!range_map_->RetrieveRangeAtIndex(sequence, &module_index,
+ NULL /* base */, NULL /* delta */,
+ NULL /* size */)) {
+ BPLOG(ERROR) << "MinidumpUnloadedModuleList has no module at sequence "
+ << sequence;
+ return NULL;
+ }
+
+ return GetModuleAtIndex(module_index);
+}
+
+const MinidumpUnloadedModule*
+MinidumpUnloadedModuleList::GetModuleAtIndex(
+ unsigned int index) const {
+ if (!valid_) {
+ BPLOG(ERROR) << "Invalid MinidumpUnloadedModuleList for GetModuleAtIndex";
+ return NULL;
+ }
+
+ if (index >= module_count_) {
+ BPLOG(ERROR) << "MinidumpUnloadedModuleList index out of range: "
+ << index << "/" << module_count_;
+ return NULL;
+ }
+
+ return &(*unloaded_modules_)[index];
+}
+
+const CodeModules* MinidumpUnloadedModuleList::Copy() const {
+ return new BasicCodeModules(this, range_map_->GetMergeStrategy());
+}
+
+vector<linked_ptr<const CodeModule>>
+MinidumpUnloadedModuleList::GetShrunkRangeModules() const {
+ return vector<linked_ptr<const CodeModule> >();
+}
+
+
+//
+// MinidumpMiscInfo
+//
+
+
+MinidumpMiscInfo::MinidumpMiscInfo(Minidump* minidump)
+ : MinidumpStream(minidump),
+ misc_info_() {
+}
+
+
+bool MinidumpMiscInfo::Read(uint32_t expected_size) {
+ valid_ = false;
+
+ size_t padding = 0;
+ if (expected_size != MD_MISCINFO_SIZE &&
+ expected_size != MD_MISCINFO2_SIZE &&
+ expected_size != MD_MISCINFO3_SIZE &&
+ expected_size != MD_MISCINFO4_SIZE &&
+ expected_size != MD_MISCINFO5_SIZE) {
+ if (expected_size > MD_MISCINFO5_SIZE) {
+ // Only read the part of the misc info structure we know how to handle
+ BPLOG(INFO) << "MinidumpMiscInfo size larger than expected "
+ << expected_size << ", skipping over the unknown part";
+ padding = expected_size - MD_MISCINFO5_SIZE;
+ expected_size = MD_MISCINFO5_SIZE;
+ } else {
+ BPLOG(ERROR) << "MinidumpMiscInfo size mismatch, " << expected_size
+ << " != " << MD_MISCINFO_SIZE << ", " << MD_MISCINFO2_SIZE
+ << ", " << MD_MISCINFO3_SIZE << ", " << MD_MISCINFO4_SIZE
+ << ", " << MD_MISCINFO5_SIZE << ")";
+ return false;
+ }
+ }
+
+ if (!minidump_->ReadBytes(&misc_info_, expected_size)) {
+ BPLOG(ERROR) << "MinidumpMiscInfo cannot read miscellaneous info";
+ return false;
+ }
+
+ if (padding != 0) {
+ off_t saved_position = minidump_->Tell();
+ if (saved_position == -1) {
+ BPLOG(ERROR) << "MinidumpMiscInfo could not tell the current position";
+ return false;
+ }
+
+ if (!minidump_->SeekSet(saved_position + static_cast<off_t>(padding))) {
+ BPLOG(ERROR) << "MinidumpMiscInfo could not seek past the miscellaneous "
+ << "info structure";
+ return false;
+ }
+ }
+
+ if (minidump_->swap()) {
+ // Swap version 1 fields
+ Swap(&misc_info_.size_of_info);
+ Swap(&misc_info_.flags1);
+ Swap(&misc_info_.process_id);
+ Swap(&misc_info_.process_create_time);
+ Swap(&misc_info_.process_user_time);
+ Swap(&misc_info_.process_kernel_time);
+ if (misc_info_.size_of_info > MD_MISCINFO_SIZE) {
+ // Swap version 2 fields
+ Swap(&misc_info_.processor_max_mhz);
+ Swap(&misc_info_.processor_current_mhz);
+ Swap(&misc_info_.processor_mhz_limit);
+ Swap(&misc_info_.processor_max_idle_state);
+ Swap(&misc_info_.processor_current_idle_state);
+ }
+ if (misc_info_.size_of_info > MD_MISCINFO2_SIZE) {
+ // Swap version 3 fields
+ Swap(&misc_info_.process_integrity_level);
+ Swap(&misc_info_.process_execute_flags);
+ Swap(&misc_info_.protected_process);
+ Swap(&misc_info_.time_zone_id);
+ Swap(&misc_info_.time_zone);
+ }
+ if (misc_info_.size_of_info > MD_MISCINFO3_SIZE) {
+ // Swap version 4 fields.
+ // Do not swap UTF-16 strings. The swap is done as part of the
+ // conversion to UTF-8 (code follows below).
+ }
+ if (misc_info_.size_of_info > MD_MISCINFO4_SIZE) {
+ // Swap version 5 fields
+ Swap(&misc_info_.xstate_data);
+ Swap(&misc_info_.process_cookie);
+ }
+ }
+
+ if (expected_size + padding != misc_info_.size_of_info) {
+ BPLOG(ERROR) << "MinidumpMiscInfo size mismatch, " <<
+ expected_size << " != " << misc_info_.size_of_info;
+ return false;
+ }
+
+ // Convert UTF-16 strings
+ if (misc_info_.size_of_info > MD_MISCINFO2_SIZE) {
+ // Convert UTF-16 strings in version 3 fields
+ ConvertUTF16BufferToUTF8String(misc_info_.time_zone.standard_name,
+ sizeof(misc_info_.time_zone.standard_name),
+ &standard_name_, minidump_->swap());
+ ConvertUTF16BufferToUTF8String(misc_info_.time_zone.daylight_name,
+ sizeof(misc_info_.time_zone.daylight_name),
+ &daylight_name_, minidump_->swap());
+ }
+ if (misc_info_.size_of_info > MD_MISCINFO3_SIZE) {
+ // Convert UTF-16 strings in version 4 fields
+ ConvertUTF16BufferToUTF8String(misc_info_.build_string,
+ sizeof(misc_info_.build_string),
+ &build_string_, minidump_->swap());
+ ConvertUTF16BufferToUTF8String(misc_info_.dbg_bld_str,
+ sizeof(misc_info_.dbg_bld_str),
+ &dbg_bld_str_, minidump_->swap());
+ }
+
+ valid_ = true;
+ return true;
+}
+
+
+void MinidumpMiscInfo::Print() {
+ if (!valid_) {
+ BPLOG(ERROR) << "MinidumpMiscInfo cannot print invalid data";
+ return;
+ }
+
+ printf("MDRawMiscInfo\n");
+ // Print version 1 fields
+ printf(" size_of_info = %d\n", misc_info_.size_of_info);
+ printf(" flags1 = 0x%x\n", misc_info_.flags1);
+ printf(" process_id = ");
+ PrintValueOrInvalid(misc_info_.flags1 & MD_MISCINFO_FLAGS1_PROCESS_ID,
+ kNumberFormatDecimal, misc_info_.process_id);
+ if (misc_info_.flags1 & MD_MISCINFO_FLAGS1_PROCESS_TIMES) {
+ printf(" process_create_time = 0x%x %s\n",
+ misc_info_.process_create_time,
+ TimeTToUTCString(misc_info_.process_create_time).c_str());
+ } else {
+ printf(" process_create_time = (invalid)\n");
+ }
+ printf(" process_user_time = ");
+ PrintValueOrInvalid(misc_info_.flags1 & MD_MISCINFO_FLAGS1_PROCESS_TIMES,
+ kNumberFormatDecimal, misc_info_.process_user_time);
+ printf(" process_kernel_time = ");
+ PrintValueOrInvalid(misc_info_.flags1 & MD_MISCINFO_FLAGS1_PROCESS_TIMES,
+ kNumberFormatDecimal, misc_info_.process_kernel_time);
+ if (misc_info_.size_of_info > MD_MISCINFO_SIZE) {
+ // Print version 2 fields
+ printf(" processor_max_mhz = ");
+ PrintValueOrInvalid(misc_info_.flags1 &
+ MD_MISCINFO_FLAGS1_PROCESSOR_POWER_INFO,
+ kNumberFormatDecimal, misc_info_.processor_max_mhz);
+ printf(" processor_current_mhz = ");
+ PrintValueOrInvalid(misc_info_.flags1 &
+ MD_MISCINFO_FLAGS1_PROCESSOR_POWER_INFO,
+ kNumberFormatDecimal, misc_info_.processor_current_mhz);
+ printf(" processor_mhz_limit = ");
+ PrintValueOrInvalid(misc_info_.flags1 &
+ MD_MISCINFO_FLAGS1_PROCESSOR_POWER_INFO,
+ kNumberFormatDecimal, misc_info_.processor_mhz_limit);
+ printf(" processor_max_idle_state = ");
+ PrintValueOrInvalid(misc_info_.flags1 &
+ MD_MISCINFO_FLAGS1_PROCESSOR_POWER_INFO,
+ kNumberFormatDecimal,
+ misc_info_.processor_max_idle_state);
+ printf(" processor_current_idle_state = ");
+ PrintValueOrInvalid(misc_info_.flags1 &
+ MD_MISCINFO_FLAGS1_PROCESSOR_POWER_INFO,
+ kNumberFormatDecimal,
+ misc_info_.processor_current_idle_state);
+ }
+ if (misc_info_.size_of_info > MD_MISCINFO2_SIZE) {
+ // Print version 3 fields
+ printf(" process_integrity_level = ");
+ PrintValueOrInvalid(misc_info_.flags1 &
+ MD_MISCINFO_FLAGS1_PROCESS_INTEGRITY,
+ kNumberFormatHexadecimal,
+ misc_info_.process_integrity_level);
+ printf(" process_execute_flags = ");
+ PrintValueOrInvalid(misc_info_.flags1 &
+ MD_MISCINFO_FLAGS1_PROCESS_EXECUTE_FLAGS,
+ kNumberFormatHexadecimal,
+ misc_info_.process_execute_flags);
+ printf(" protected_process = ");
+ PrintValueOrInvalid(misc_info_.flags1 &
+ MD_MISCINFO_FLAGS1_PROTECTED_PROCESS,
+ kNumberFormatDecimal, misc_info_.protected_process);
+ printf(" time_zone_id = ");
+ PrintValueOrInvalid(misc_info_.flags1 & MD_MISCINFO_FLAGS1_TIMEZONE,
+ kNumberFormatDecimal, misc_info_.time_zone_id);
+ if (misc_info_.flags1 & MD_MISCINFO_FLAGS1_TIMEZONE) {
+ printf(" time_zone.bias = %d\n",
+ misc_info_.time_zone.bias);
+ printf(" time_zone.standard_name = %s\n", standard_name_.c_str());
+ printf(" time_zone.standard_date = "
+ "%04d-%02d-%02d (%d) %02d:%02d:%02d.%03d\n",
+ misc_info_.time_zone.standard_date.year,
+ misc_info_.time_zone.standard_date.month,
+ misc_info_.time_zone.standard_date.day,
+ misc_info_.time_zone.standard_date.day_of_week,
+ misc_info_.time_zone.standard_date.hour,
+ misc_info_.time_zone.standard_date.minute,
+ misc_info_.time_zone.standard_date.second,
+ misc_info_.time_zone.standard_date.milliseconds);
+ printf(" time_zone.standard_bias = %d\n",
+ misc_info_.time_zone.standard_bias);
+ printf(" time_zone.daylight_name = %s\n", daylight_name_.c_str());
+ printf(" time_zone.daylight_date = "
+ "%04d-%02d-%02d (%d) %02d:%02d:%02d.%03d\n",
+ misc_info_.time_zone.daylight_date.year,
+ misc_info_.time_zone.daylight_date.month,
+ misc_info_.time_zone.daylight_date.day,
+ misc_info_.time_zone.daylight_date.day_of_week,
+ misc_info_.time_zone.daylight_date.hour,
+ misc_info_.time_zone.daylight_date.minute,
+ misc_info_.time_zone.daylight_date.second,
+ misc_info_.time_zone.daylight_date.milliseconds);
+ printf(" time_zone.daylight_bias = %d\n",
+ misc_info_.time_zone.daylight_bias);
+ } else {
+ printf(" time_zone.bias = (invalid)\n");
+ printf(" time_zone.standard_name = (invalid)\n");
+ printf(" time_zone.standard_date = (invalid)\n");
+ printf(" time_zone.standard_bias = (invalid)\n");
+ printf(" time_zone.daylight_name = (invalid)\n");
+ printf(" time_zone.daylight_date = (invalid)\n");
+ printf(" time_zone.daylight_bias = (invalid)\n");
+ }
+ }
+ if (misc_info_.size_of_info > MD_MISCINFO3_SIZE) {
+ // Print version 4 fields
+ if (misc_info_.flags1 & MD_MISCINFO_FLAGS1_BUILDSTRING) {
+ printf(" build_string = %s\n", build_string_.c_str());
+ printf(" dbg_bld_str = %s\n", dbg_bld_str_.c_str());
+ } else {
+ printf(" build_string = (invalid)\n");
+ printf(" dbg_bld_str = (invalid)\n");
+ }
+ }
+ if (misc_info_.size_of_info > MD_MISCINFO4_SIZE) {
+ // Print version 5 fields
+ if (misc_info_.flags1 & MD_MISCINFO_FLAGS1_PROCESS_COOKIE) {
+ printf(" xstate_data.size_of_info = %d\n",
+ misc_info_.xstate_data.size_of_info);
+ printf(" xstate_data.context_size = %d\n",
+ misc_info_.xstate_data.context_size);
+ printf(" xstate_data.enabled_features = 0x%" PRIx64 "\n",
+ misc_info_.xstate_data.enabled_features);
+ for (size_t i = 0; i < MD_MAXIMUM_XSTATE_FEATURES; i++) {
+ if ((misc_info_.xstate_data.enabled_features >> i) & 1) {
+ printf(" xstate_data.features[%02zu] = { %d, %d }\n", i,
+ misc_info_.xstate_data.features[i].offset,
+ misc_info_.xstate_data.features[i].size);
+ }
+ }
+ if (misc_info_.xstate_data.enabled_features == 0) {
+ printf(" xstate_data.features[] = (empty)\n");
+ }
+ printf(" process_cookie = %d\n",
+ misc_info_.process_cookie);
+ } else {
+ printf(" xstate_data.size_of_info = (invalid)\n");
+ printf(" xstate_data.context_size = (invalid)\n");
+ printf(" xstate_data.enabled_features = (invalid)\n");
+ printf(" xstate_data.features[] = (invalid)\n");
+ printf(" process_cookie = (invalid)\n");
+ }
+ }
+ printf("\n");
+}
+
+
+//
+// MinidumpBreakpadInfo
+//
+
+
+MinidumpBreakpadInfo::MinidumpBreakpadInfo(Minidump* minidump)
+ : MinidumpStream(minidump),
+ breakpad_info_() {
+}
+
+
+bool MinidumpBreakpadInfo::Read(uint32_t expected_size) {
+ valid_ = false;
+
+ if (expected_size != sizeof(breakpad_info_)) {
+ BPLOG(ERROR) << "MinidumpBreakpadInfo size mismatch, " << expected_size <<
+ " != " << sizeof(breakpad_info_);
+ return false;
+ }
+
+ if (!minidump_->ReadBytes(&breakpad_info_, sizeof(breakpad_info_))) {
+ BPLOG(ERROR) << "MinidumpBreakpadInfo cannot read Breakpad info";
+ return false;
+ }
+
+ if (minidump_->swap()) {
+ Swap(&breakpad_info_.validity);
+ Swap(&breakpad_info_.dump_thread_id);
+ Swap(&breakpad_info_.requesting_thread_id);
+ }
+
+ valid_ = true;
+ return true;
+}
+
+
+bool MinidumpBreakpadInfo::GetDumpThreadID(uint32_t *thread_id) const {
+ BPLOG_IF(ERROR, !thread_id) << "MinidumpBreakpadInfo::GetDumpThreadID "
+ "requires |thread_id|";
+ assert(thread_id);
+ *thread_id = 0;
+
+ if (!valid_) {
+ BPLOG(ERROR) << "Invalid MinidumpBreakpadInfo for GetDumpThreadID";
+ return false;
+ }
+
+ if (!(breakpad_info_.validity & MD_BREAKPAD_INFO_VALID_DUMP_THREAD_ID)) {
+ BPLOG(INFO) << "MinidumpBreakpadInfo has no dump thread";
+ return false;
+ }
+
+ *thread_id = breakpad_info_.dump_thread_id;
+ return true;
+}
+
+
+bool MinidumpBreakpadInfo::GetRequestingThreadID(uint32_t *thread_id)
+ const {
+ BPLOG_IF(ERROR, !thread_id) << "MinidumpBreakpadInfo::GetRequestingThreadID "
+ "requires |thread_id|";
+ assert(thread_id);
+ *thread_id = 0;
+
+ if (!thread_id || !valid_) {
+ BPLOG(ERROR) << "Invalid MinidumpBreakpadInfo for GetRequestingThreadID";
+ return false;
+ }
+
+ if (!(breakpad_info_.validity &
+ MD_BREAKPAD_INFO_VALID_REQUESTING_THREAD_ID)) {
+ BPLOG(INFO) << "MinidumpBreakpadInfo has no requesting thread";
+ return false;
+ }
+
+ *thread_id = breakpad_info_.requesting_thread_id;
+ return true;
+}
+
+
+void MinidumpBreakpadInfo::Print() {
+ if (!valid_) {
+ BPLOG(ERROR) << "MinidumpBreakpadInfo cannot print invalid data";
+ return;
+ }
+
+ printf("MDRawBreakpadInfo\n");
+ printf(" validity = 0x%x\n", breakpad_info_.validity);
+ printf(" dump_thread_id = ");
+ PrintValueOrInvalid(breakpad_info_.validity &
+ MD_BREAKPAD_INFO_VALID_DUMP_THREAD_ID,
+ kNumberFormatHexadecimal, breakpad_info_.dump_thread_id);
+ printf(" requesting_thread_id = ");
+ PrintValueOrInvalid(breakpad_info_.validity &
+ MD_BREAKPAD_INFO_VALID_REQUESTING_THREAD_ID,
+ kNumberFormatHexadecimal,
+ breakpad_info_.requesting_thread_id);
+
+ printf("\n");
+}
+
+
+//
+// MinidumpMemoryInfo
+//
+
+
+MinidumpMemoryInfo::MinidumpMemoryInfo(Minidump* minidump)
+ : MinidumpObject(minidump),
+ memory_info_() {
+}
+
+
+bool MinidumpMemoryInfo::IsExecutable() const {
+ uint32_t protection =
+ memory_info_.protection & MD_MEMORY_PROTECTION_ACCESS_MASK;
+ return protection == MD_MEMORY_PROTECT_EXECUTE ||
+ protection == MD_MEMORY_PROTECT_EXECUTE_READ ||
+ protection == MD_MEMORY_PROTECT_EXECUTE_READWRITE;
+}
+
+
+bool MinidumpMemoryInfo::IsWritable() const {
+ uint32_t protection =
+ memory_info_.protection & MD_MEMORY_PROTECTION_ACCESS_MASK;
+ return protection == MD_MEMORY_PROTECT_READWRITE ||
+ protection == MD_MEMORY_PROTECT_WRITECOPY ||
+ protection == MD_MEMORY_PROTECT_EXECUTE_READWRITE ||
+ protection == MD_MEMORY_PROTECT_EXECUTE_WRITECOPY;
+}
+
+
+bool MinidumpMemoryInfo::Read() {
+ valid_ = false;
+
+ if (!minidump_->ReadBytes(&memory_info_, sizeof(memory_info_))) {
+ BPLOG(ERROR) << "MinidumpMemoryInfo cannot read memory info";
+ return false;
+ }
+
+ if (minidump_->swap()) {
+ Swap(&memory_info_.base_address);
+ Swap(&memory_info_.allocation_base);
+ Swap(&memory_info_.allocation_protection);
+ Swap(&memory_info_.region_size);
+ Swap(&memory_info_.state);
+ Swap(&memory_info_.protection);
+ Swap(&memory_info_.type);
+ }
+
+ // Check for base + size overflow or undersize.
+ if (memory_info_.region_size == 0 ||
+ memory_info_.region_size > numeric_limits<uint64_t>::max() -
+ memory_info_.base_address) {
+ BPLOG(ERROR) << "MinidumpMemoryInfo has a memory region problem, " <<
+ HexString(memory_info_.base_address) << "+" <<
+ HexString(memory_info_.region_size);
+ return false;
+ }
+
+ valid_ = true;
+ return true;
+}
+
+
+void MinidumpMemoryInfo::Print() {
+ if (!valid_) {
+ BPLOG(ERROR) << "MinidumpMemoryInfo cannot print invalid data";
+ return;
+ }
+
+ printf("MDRawMemoryInfo\n");
+ printf(" base_address = 0x%" PRIx64 "\n",
+ memory_info_.base_address);
+ printf(" allocation_base = 0x%" PRIx64 "\n",
+ memory_info_.allocation_base);
+ printf(" allocation_protection = 0x%x\n",
+ memory_info_.allocation_protection);
+ printf(" region_size = 0x%" PRIx64 "\n", memory_info_.region_size);
+ printf(" state = 0x%x\n", memory_info_.state);
+ printf(" protection = 0x%x\n", memory_info_.protection);
+ printf(" type = 0x%x\n", memory_info_.type);
+}
+
+
+//
+// MinidumpMemoryInfoList
+//
+
+
+MinidumpMemoryInfoList::MinidumpMemoryInfoList(Minidump* minidump)
+ : MinidumpStream(minidump),
+ range_map_(new RangeMap<uint64_t, unsigned int>()),
+ infos_(NULL),
+ info_count_(0) {
+}
+
+
+MinidumpMemoryInfoList::~MinidumpMemoryInfoList() {
+ delete range_map_;
+ delete infos_;
+}
+
+
+bool MinidumpMemoryInfoList::Read(uint32_t expected_size) {
+ // Invalidate cached data.
+ delete infos_;
+ infos_ = NULL;
+ range_map_->Clear();
+ info_count_ = 0;
+
+ valid_ = false;
+
+ MDRawMemoryInfoList header;
+ if (expected_size < sizeof(MDRawMemoryInfoList)) {
+ BPLOG(ERROR) << "MinidumpMemoryInfoList header size mismatch, " <<
+ expected_size << " < " << sizeof(MDRawMemoryInfoList);
+ return false;
+ }
+ if (!minidump_->ReadBytes(&header, sizeof(header))) {
+ BPLOG(ERROR) << "MinidumpMemoryInfoList could not read header";
+ return false;
+ }
+
+ if (minidump_->swap()) {
+ Swap(&header.size_of_header);
+ Swap(&header.size_of_entry);
+ Swap(&header.number_of_entries);
+ }
+
+ // Sanity check that the header is the expected size.
+ // TODO(ted): could possibly handle this more gracefully, assuming
+ // that future versions of the structs would be backwards-compatible.
+ if (header.size_of_header != sizeof(MDRawMemoryInfoList)) {
+ BPLOG(ERROR) << "MinidumpMemoryInfoList header size mismatch, " <<
+ header.size_of_header << " != " <<
+ sizeof(MDRawMemoryInfoList);
+ return false;
+ }
+
+ // Sanity check that the entries are the expected size.
+ if (header.size_of_entry != sizeof(MDRawMemoryInfo)) {
+ BPLOG(ERROR) << "MinidumpMemoryInfoList entry size mismatch, " <<
+ header.size_of_entry << " != " <<
+ sizeof(MDRawMemoryInfo);
+ return false;
+ }
+
+ if (header.number_of_entries >
+ numeric_limits<uint32_t>::max() / sizeof(MDRawMemoryInfo)) {
+ BPLOG(ERROR) << "MinidumpMemoryInfoList info count " <<
+ header.number_of_entries <<
+ " would cause multiplication overflow";
+ return false;
+ }
+
+ if (expected_size != sizeof(MDRawMemoryInfoList) +
+ header.number_of_entries * sizeof(MDRawMemoryInfo)) {
+ BPLOG(ERROR) << "MinidumpMemoryInfoList size mismatch, " << expected_size <<
+ " != " << sizeof(MDRawMemoryInfoList) +
+ header.number_of_entries * sizeof(MDRawMemoryInfo);
+ return false;
+ }
+
+ // Check for data loss when converting header.number_of_entries from
+ // uint64_t into MinidumpMemoryInfos::size_type (uint32_t)
+ MinidumpMemoryInfos::size_type header_number_of_entries =
+ static_cast<unsigned int>(header.number_of_entries);
+ if (static_cast<uint64_t>(header_number_of_entries) !=
+ header.number_of_entries) {
+ BPLOG(ERROR) << "Data loss detected when converting "
+ "the header's number_of_entries";
+ return false;
+ }
+
+ if (header.number_of_entries != 0) {
+ scoped_ptr<MinidumpMemoryInfos> infos(
+ new MinidumpMemoryInfos(header_number_of_entries,
+ MinidumpMemoryInfo(minidump_)));
+
+ for (unsigned int index = 0;
+ index < header.number_of_entries;
+ ++index) {
+ MinidumpMemoryInfo* info = &(*infos)[index];
+
+ // Assume that the file offset is correct after the last read.
+ if (!info->Read()) {
+ BPLOG(ERROR) << "MinidumpMemoryInfoList cannot read info " <<
+ index << "/" << header.number_of_entries;
+ return false;
+ }
+
+ uint64_t base_address = info->GetBase();
+ uint64_t region_size = info->GetSize();
+
+ if (!range_map_->StoreRange(base_address, region_size, index)) {
+ BPLOG(ERROR) << "MinidumpMemoryInfoList could not store"
+ " memory region " <<
+ index << "/" << header.number_of_entries << ", " <<
+ HexString(base_address) << "+" <<
+ HexString(region_size);
+ return false;
+ }
+ }
+
+ infos_ = infos.release();
+ }
+
+ info_count_ = static_cast<uint32_t>(header_number_of_entries);
+
+ valid_ = true;
+ return true;
+}
+
+
+const MinidumpMemoryInfo* MinidumpMemoryInfoList::GetMemoryInfoAtIndex(
+ unsigned int index) const {
+ if (!valid_) {
+ BPLOG(ERROR) << "Invalid MinidumpMemoryInfoList for GetMemoryInfoAtIndex";
+ return NULL;
+ }
+
+ if (index >= info_count_) {
+ BPLOG(ERROR) << "MinidumpMemoryInfoList index out of range: " <<
+ index << "/" << info_count_;
+ return NULL;
+ }
+
+ return &(*infos_)[index];
+}
+
+
+const MinidumpMemoryInfo* MinidumpMemoryInfoList::GetMemoryInfoForAddress(
+ uint64_t address) const {
+ if (!valid_) {
+ BPLOG(ERROR) << "Invalid MinidumpMemoryInfoList for"
+ " GetMemoryInfoForAddress";
+ return NULL;
+ }
+
+ unsigned int info_index;
+ if (!range_map_->RetrieveRange(address, &info_index, NULL /* base */,
+ NULL /* delta */, NULL /* size */)) {
+ BPLOG(INFO) << "MinidumpMemoryInfoList has no memory info at " <<
+ HexString(address);
+ return NULL;
+ }
+
+ return GetMemoryInfoAtIndex(info_index);
+}
+
+
+void MinidumpMemoryInfoList::Print() {
+ if (!valid_) {
+ BPLOG(ERROR) << "MinidumpMemoryInfoList cannot print invalid data";
+ return;
+ }
+
+ printf("MinidumpMemoryInfoList\n");
+ printf(" info_count = %d\n", info_count_);
+ printf("\n");
+
+ for (unsigned int info_index = 0;
+ info_index < info_count_;
+ ++info_index) {
+ printf("info[%d]\n", info_index);
+ (*infos_)[info_index].Print();
+ printf("\n");
+ }
+}
+
+//
+// MinidumpLinuxMaps
+//
+
+MinidumpLinuxMaps::MinidumpLinuxMaps(Minidump *minidump)
+ : MinidumpObject(minidump) {
+}
+
+void MinidumpLinuxMaps::Print() const {
+ if (!valid_) {
+ BPLOG(ERROR) << "MinidumpLinuxMaps cannot print invalid data";
+ return;
+ }
+ std::cout << region_.line << std::endl;
+}
+
+//
+// MinidumpLinuxMapsList
+//
+
+MinidumpLinuxMapsList::MinidumpLinuxMapsList(Minidump *minidump)
+ : MinidumpStream(minidump),
+ maps_(NULL),
+ maps_count_(0) {
+}
+
+MinidumpLinuxMapsList::~MinidumpLinuxMapsList() {
+ if (maps_) {
+ for (unsigned int i = 0; i < maps_->size(); i++) {
+ delete (*maps_)[i];
+ }
+ delete maps_;
+ }
+}
+
+const MinidumpLinuxMaps *MinidumpLinuxMapsList::GetLinuxMapsForAddress(
+ uint64_t address) const {
+ if (!valid_ || (maps_ == NULL)) {
+ BPLOG(ERROR) << "Invalid MinidumpLinuxMapsList for GetLinuxMapsForAddress";
+ return NULL;
+ }
+
+ // Search every memory mapping.
+ for (unsigned int index = 0; index < maps_count_; index++) {
+ // Check if address is within bounds of the current memory region.
+ if ((*maps_)[index]->GetBase() <= address &&
+ (*maps_)[index]->GetBase() + (*maps_)[index]->GetSize() > address) {
+ return (*maps_)[index];
+ }
+ }
+
+ // No mapping encloses the memory address.
+ BPLOG(ERROR) << "MinidumpLinuxMapsList has no mapping at "
+ << HexString(address);
+ return NULL;
+}
+
+const MinidumpLinuxMaps *MinidumpLinuxMapsList::GetLinuxMapsAtIndex(
+ unsigned int index) const {
+ if (!valid_ || (maps_ == NULL)) {
+ BPLOG(ERROR) << "Invalid MinidumpLinuxMapsList for GetLinuxMapsAtIndex";
+ return NULL;
+ }
+
+ // Index out of bounds.
+ if (index >= maps_count_ || (maps_ == NULL)) {
+ BPLOG(ERROR) << "MinidumpLinuxMapsList index of out range: "
+ << index
+ << "/"
+ << maps_count_;
+ return NULL;
+ }
+ return (*maps_)[index];
+}
+
+bool MinidumpLinuxMapsList::Read(uint32_t expected_size) {
+ // Invalidate cached data.
+ if (maps_) {
+ for (unsigned int i = 0; i < maps_->size(); i++) {
+ delete (*maps_)[i];
+ }
+ delete maps_;
+ }
+ maps_ = NULL;
+ maps_count_ = 0;
+
+ valid_ = false;
+
+ // Load and check expected stream length.
+ uint32_t length = 0;
+ if (!minidump_->SeekToStreamType(MD_LINUX_MAPS, &length)) {
+ BPLOG(ERROR) << "MinidumpLinuxMapsList stream type not found";
+ return false;
+ }
+ if (expected_size != length) {
+ BPLOG(ERROR) << "MinidumpLinuxMapsList size mismatch: "
+ << expected_size
+ << " != "
+ << length;
+ return false;
+ }
+
+ // Create a vector to read stream data. The vector needs to have
+ // at least enough capacity to read all the data.
+ vector<char> mapping_bytes(length);
+ if (!minidump_->ReadBytes(&mapping_bytes[0], length)) {
+ BPLOG(ERROR) << "MinidumpLinuxMapsList failed to read bytes";
+ return false;
+ }
+ string map_string(mapping_bytes.begin(), mapping_bytes.end());
+ vector<MappedMemoryRegion> all_regions;
+
+ // Parse string into mapping data.
+ if (!ParseProcMaps(map_string, &all_regions)) {
+ return false;
+ }
+
+ scoped_ptr<MinidumpLinuxMappings> maps(new MinidumpLinuxMappings());
+
+ // Push mapping data into wrapper classes.
+ for (size_t i = 0; i < all_regions.size(); i++) {
+ scoped_ptr<MinidumpLinuxMaps> ele(new MinidumpLinuxMaps(minidump_));
+ ele->region_ = all_regions[i];
+ ele->valid_ = true;
+ maps->push_back(ele.release());
+ }
+
+ // Set instance variables.
+ maps_ = maps.release();
+ maps_count_ = static_cast<uint32_t>(maps_->size());
+ valid_ = true;
+ return true;
+}
+
+void MinidumpLinuxMapsList::Print() const {
+ if (!valid_ || (maps_ == NULL)) {
+ BPLOG(ERROR) << "MinidumpLinuxMapsList cannot print valid data";
+ return;
+ }
+ for (size_t i = 0; i < maps_->size(); i++) {
+ (*maps_)[i]->Print();
+ }
+}
+
+//
+// MinidumpCrashpadInfo
+//
+
+
+MinidumpCrashpadInfo::MinidumpCrashpadInfo(Minidump* minidump)
+ : MinidumpStream(minidump),
+ crashpad_info_(),
+ module_crashpad_info_links_(),
+ module_crashpad_info_(),
+ module_crashpad_info_list_annotations_(),
+ module_crashpad_info_simple_annotations_(),
+ simple_annotations_() {
+}
+
+
+bool MinidumpCrashpadInfo::Read(uint32_t expected_size) {
+ valid_ = false;
+
+ if (expected_size != sizeof(crashpad_info_)) {
+ BPLOG(ERROR) << "MinidumpCrashpadInfo size mismatch, " << expected_size <<
+ " != " << sizeof(crashpad_info_);
+ return false;
+ }
+
+ if (!minidump_->ReadBytes(&crashpad_info_, sizeof(crashpad_info_))) {
+ BPLOG(ERROR) << "MinidumpCrashpadInfo cannot read Crashpad info";
+ return false;
+ }
+
+ if (minidump_->swap()) {
+ Swap(&crashpad_info_.version);
+ Swap(&crashpad_info_.report_id);
+ Swap(&crashpad_info_.client_id);
+ Swap(&crashpad_info_.simple_annotations);
+ Swap(&crashpad_info_.module_list);
+ }
+
+ if (crashpad_info_.simple_annotations.data_size) {
+ if (!minidump_->ReadSimpleStringDictionary(
+ crashpad_info_.simple_annotations.rva,
+ &simple_annotations_)) {
+ BPLOG(ERROR) << "MinidumpCrashpadInfo cannot read simple_annotations";
+ return false;
+ }
+ }
+
+ if (crashpad_info_.module_list.data_size) {
+ if (!minidump_->SeekSet(crashpad_info_.module_list.rva)) {
+ BPLOG(ERROR) << "MinidumpCrashpadInfo cannot seek to module_list";
+ return false;
+ }
+
+ uint32_t count;
+ if (!minidump_->ReadBytes(&count, sizeof(count))) {
+ BPLOG(ERROR) << "MinidumpCrashpadInfo cannot read module_list count";
+ return false;
+ }
+
+ if (minidump_->swap()) {
+ Swap(&count);
+ }
+
+ scoped_array<MDRawModuleCrashpadInfoLink> module_crashpad_info_links(
+ new MDRawModuleCrashpadInfoLink[count]);
+
+ // Read the entire array in one fell swoop, instead of reading one entry
+ // at a time in the loop.
+ if (!minidump_->ReadBytes(
+ &module_crashpad_info_links[0],
+ sizeof(MDRawModuleCrashpadInfoLink) * count)) {
+ BPLOG(ERROR)
+ << "MinidumpCrashpadInfo could not read Crashpad module links";
+ return false;
+ }
+
+ for (uint32_t index = 0; index < count; ++index) {
+ if (minidump_->swap()) {
+ Swap(&module_crashpad_info_links[index].minidump_module_list_index);
+ Swap(&module_crashpad_info_links[index].location);
+ }
+
+ if (!minidump_->SeekSet(module_crashpad_info_links[index].location.rva)) {
+ BPLOG(ERROR)
+ << "MinidumpCrashpadInfo cannot seek to Crashpad module info";
+ return false;
+ }
+
+ MDRawModuleCrashpadInfo module_crashpad_info;
+ if (!minidump_->ReadBytes(&module_crashpad_info,
+ sizeof(module_crashpad_info))) {
+ BPLOG(ERROR) << "MinidumpCrashpadInfo cannot read Crashpad module info";
+ return false;
+ }
+
+ if (minidump_->swap()) {
+ Swap(&module_crashpad_info.version);
+ Swap(&module_crashpad_info.list_annotations);
+ Swap(&module_crashpad_info.simple_annotations);
+ }
+
+ std::vector<std::string> list_annotations;
+ if (module_crashpad_info.list_annotations.data_size) {
+ if (!minidump_->ReadStringList(
+ module_crashpad_info.list_annotations.rva,
+ &list_annotations)) {
+ BPLOG(ERROR) << "MinidumpCrashpadInfo cannot read Crashpad module "
+ "info list annotations";
+ return false;
+ }
+ }
+
+ std::map<std::string, std::string> simple_annotations;
+ if (module_crashpad_info.simple_annotations.data_size) {
+ if (!minidump_->ReadSimpleStringDictionary(
+ module_crashpad_info.simple_annotations.rva,
+ &simple_annotations)) {
+ BPLOG(ERROR) << "MinidumpCrashpadInfo cannot read Crashpad module "
+ "info simple annotations";
+ return false;
+ }
+ }
+
+ module_crashpad_info_links_.push_back(
+ module_crashpad_info_links[index].minidump_module_list_index);
+ module_crashpad_info_.push_back(module_crashpad_info);
+ module_crashpad_info_list_annotations_.push_back(list_annotations);
+ module_crashpad_info_simple_annotations_.push_back(simple_annotations);
+ }
+ }
+
+ valid_ = true;
+ return true;
+}
+
+
+void MinidumpCrashpadInfo::Print() {
+ if (!valid_) {
+ BPLOG(ERROR) << "MinidumpCrashpadInfo cannot print invalid data";
+ return;
+ }
+
+ printf("MDRawCrashpadInfo\n");
+ printf(" version = %d\n", crashpad_info_.version);
+ printf(" report_id = %s\n",
+ MDGUIDToString(crashpad_info_.report_id).c_str());
+ printf(" client_id = %s\n",
+ MDGUIDToString(crashpad_info_.client_id).c_str());
+ for (std::map<std::string, std::string>::const_iterator iterator =
+ simple_annotations_.begin();
+ iterator != simple_annotations_.end();
+ ++iterator) {
+ printf(" simple_annotations[\"%s\"] = %s\n",
+ iterator->first.c_str(), iterator->second.c_str());
+ }
+ for (uint32_t module_index = 0;
+ module_index < module_crashpad_info_links_.size();
+ ++module_index) {
+ printf(" module_list[%d].minidump_module_list_index = %d\n",
+ module_index, module_crashpad_info_links_[module_index]);
+ printf(" module_list[%d].version = %d\n",
+ module_index, module_crashpad_info_[module_index].version);
+ for (uint32_t annotation_index = 0;
+ annotation_index <
+ module_crashpad_info_list_annotations_[module_index].size();
+ ++annotation_index) {
+ printf(" module_list[%d].list_annotations[%d] = %s\n",
+ module_index,
+ annotation_index,
+ module_crashpad_info_list_annotations_
+ [module_index][annotation_index].c_str());
+ }
+ for (std::map<std::string, std::string>::const_iterator iterator =
+ module_crashpad_info_simple_annotations_[module_index].begin();
+ iterator !=
+ module_crashpad_info_simple_annotations_[module_index].end();
+ ++iterator) {
+ printf(" module_list[%d].simple_annotations[\"%s\"] = %s\n",
+ module_index, iterator->first.c_str(), iterator->second.c_str());
+ }
+ }
+
+ printf("\n");
+}
+
+//
+// MinidumpMacCrashInfo
+//
+
+MinidumpMacCrashInfo::MinidumpMacCrashInfo(Minidump* minidump)
+ : MinidumpStream(minidump),
+ description_(),
+ records_() {
+}
+
+bool MinidumpMacCrashInfo::ReadCrashInfoRecord(MDLocationDescriptor location,
+ uint32_t record_start_size) {
+ if (!minidump_->SeekSet(location.rva)) {
+ BPLOG(ERROR) << "ReadCrashInfoRecord could not seek to record";
+ return false;
+ }
+
+ // We may be reading a minidump 1) created by (newer) code that defines more
+ // fields than we do in the fixed-size part of MDRawMacCrashInfoRecord
+ // (before 'data'), or 2) created by (older) code that defines fewer fields.
+ // In the first case we read in the newer fields but ignore them. In the
+ // second case we read in only the older fields, and leave the newer fields
+ // (in 'raw_record_start') set to zero.
+ uint32_t raw_record_size = sizeof(MDRawMacCrashInfoRecord);
+ if (record_start_size > raw_record_size) {
+ raw_record_size = record_start_size;
+ }
+ scoped_ptr< vector<uint8_t> > raw_record(
+ new vector<uint8_t>(raw_record_size));
+ if (!minidump_->ReadBytes(&(*raw_record)[0], record_start_size)) {
+ BPLOG(ERROR) << "ReadCrashInfoRecord could not read " <<
+ record_start_size << " bytes of record";
+ return false;
+ }
+ MDRawMacCrashInfoRecord* raw_record_start =
+ (MDRawMacCrashInfoRecord*) &(*raw_record)[0];
+
+ if (minidump_->swap()) {
+ Swap(&raw_record_start->stream_type);
+ Swap(&raw_record_start->version);
+ Swap(&raw_record_start->thread);
+ Swap(&raw_record_start->dialog_mode);
+ Swap(&raw_record_start->abort_cause);
+ }
+
+ if (raw_record_start->stream_type != MOZ_MACOS_CRASH_INFO_STREAM) {
+ BPLOG(ERROR) << "ReadCrashInfoRecord stream type mismatch, " <<
+ raw_record_start->stream_type << " != " <<
+ MOZ_MACOS_CRASH_INFO_STREAM;
+ return false;
+ }
+
+ uint32_t string_data_size = location.data_size - record_start_size;
+ scoped_ptr< vector<uint8_t> > data(new vector<uint8_t>(string_data_size));
+ if (!minidump_->ReadBytes(&(*data)[0], string_data_size)) {
+ BPLOG(ERROR) << "ReadCrashInfoRecord could not read " <<
+ string_data_size << " bytes of record data";
+ return false;
+ }
+
+ crash_info_record_t record;
+
+ record.version = (unsigned long) raw_record_start->version;
+ record.thread = (unsigned long long) raw_record_start->thread;
+ record.dialog_mode = (unsigned int) raw_record_start->dialog_mode;
+ record.abort_cause = (long long) raw_record_start->abort_cause;
+
+ // Once again, we may be reading a minidump created by newer code that
+ // stores more strings than we expect in (MDRawMacCrashInfoRecord).data,
+ // or one created by older code that contains fewer strings than we
+ // expect. In the first case we ignore the "extra" strings. To deal with
+ // the second case we bail when 'offset >= string_data_size'.
+ const char* string_data = (const char*) &(*data)[0];
+ size_t offset = 0;
+ for (int i = 1; i <= 5; ++i) {
+ switch (i) {
+ case 1:
+ record.module_path.append(string_data);
+ break;
+ case 2:
+ record.message.append(string_data);
+ break;
+ case 3:
+ record.signature_string.append(string_data);
+ break;
+ case 4:
+ record.backtrace.append(string_data);
+ break;
+ case 5:
+ record.message2.append(string_data);
+ break;
+ }
+ size_t char_array_size = strlen(string_data) + 1;
+ offset += char_array_size;
+ if (offset >= string_data_size) {
+ break;
+ }
+ string_data += char_array_size;
+ }
+
+ records_.push_back(record);
+
+ description_.append(" Module \"");
+ description_.append(record.module_path);
+ description_.append("\":\n");
+
+ int num_fields = 6;
+ if (record.version > 4) {
+ num_fields = 7;
+ }
+ for (int i = 1; i <= num_fields; ++i) {
+ switch (i) {
+ case 1:
+ if (!record.message.empty()) {
+ description_.append(" message: \"");
+ description_.append(record.message);
+ description_.append("\"\n");
+ }
+ break;
+ case 2:
+ if (!record.signature_string.empty()) {
+ description_.append(" signature_string: \"");
+ description_.append(record.signature_string);
+ description_.append("\"\n");
+ }
+ break;
+ case 3:
+ if (!record.backtrace.empty()) {
+ description_.append(" backtrace: \"");
+ description_.append(record.backtrace);
+ description_.append("\"\n");
+ }
+ break;
+ case 4:
+ if (!record.message2.empty()) {
+ description_.append(" message2: \"");
+ description_.append(record.message2);
+ description_.append("\"\n");
+ }
+ break;
+ case 5:
+ if (record.thread) {
+ char thread[128];
+ snprintf(thread, sizeof(thread), " thread: 0x%llx\n",
+ record.thread);
+ description_.append(thread);
+ }
+ break;
+ case 6:
+ if (record.dialog_mode) {
+ char dialog_mode[128];
+ snprintf(dialog_mode, sizeof(dialog_mode), " dialog_mode: 0x%x\n",
+ record.dialog_mode);
+ description_.append(dialog_mode);
+ }
+ break;
+ case 7:
+ if (record.abort_cause) {
+ char abort_cause[128];
+ snprintf(abort_cause, sizeof(abort_cause), " abort_cause: %lld\n",
+ record.abort_cause);
+ description_.append(abort_cause);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ return true;
+}
+
+bool MinidumpMacCrashInfo::Read(uint32_t expected_size) {
+ description_.clear();
+ records_.clear();
+ valid_ = false;
+
+ MDRawMacCrashInfo crash_info;
+ if (expected_size != sizeof(crash_info)) {
+ BPLOG(ERROR) << "MinidumpMacCrashInfo size mismatch, " <<
+ expected_size << " != " << sizeof(crash_info);
+ return false;
+ }
+ if (!minidump_->ReadBytes(&crash_info, sizeof(crash_info))) {
+ BPLOG(ERROR) << "MinidumpMacCrashInfo could not read " <<
+ sizeof(crash_info) << " bytes";
+ return false;
+ }
+ if (minidump_->swap()) {
+ Swap(&crash_info.stream_type);
+ Swap(&crash_info.record_count);
+ Swap(&crash_info.record_start_size);
+ for (uint32_t i = 0; i < crash_info.record_count; ++i) {
+ Swap(&crash_info.records[i].data_size);
+ Swap(&crash_info.records[i].rva);
+ }
+ }
+ if (crash_info.stream_type != MOZ_MACOS_CRASH_INFO_STREAM) {
+ BPLOG(ERROR) << "MinidumpMacCrashInfo stream type mismatch, " <<
+ crash_info.stream_type << " != " <<
+ MOZ_MACOS_CRASH_INFO_STREAM;
+ return false;
+ }
+
+ for (uint32_t i = 0; i < crash_info.record_count; ++i) {
+ if (!ReadCrashInfoRecord(crash_info.records[i],
+ crash_info.record_start_size)) {
+ return false;
+ }
+ }
+
+ valid_ = true;
+ return true;
+}
+
+void MinidumpMacCrashInfo::Print() {
+ if (!valid_) {
+ BPLOG(ERROR) << "MinidumpMacCrashInfo cannot print invalid data";
+ return;
+ }
+
+ printf("MinidumpMacCrashInfo:\n\n");
+ printf("%s", description_.c_str());
+}
+
+//
+// Minidump
+//
+
+
+uint32_t Minidump::max_streams_ = 128;
+unsigned int Minidump::max_string_length_ = 1024;
+
+
+Minidump::Minidump(const string& path, bool hexdump, unsigned int hexdump_width)
+ : header_(),
+ directory_(NULL),
+ stream_map_(new MinidumpStreamMap()),
+ path_(path),
+ stream_(NULL),
+ swap_(false),
+ is_big_endian_(false),
+ valid_(false),
+ hexdump_(hexdump),
+ hexdump_width_(hexdump_width) {
+}
+
+Minidump::Minidump(istream& stream)
+ : header_(),
+ directory_(NULL),
+ stream_map_(new MinidumpStreamMap()),
+ path_(),
+ stream_(&stream),
+ swap_(false),
+ is_big_endian_(false),
+ valid_(false),
+ hexdump_(false),
+ hexdump_width_(0) {
+}
+
+Minidump::~Minidump() {
+ if (stream_) {
+ BPLOG(INFO) << "Minidump closing minidump";
+ }
+ if (!path_.empty()) {
+ delete stream_;
+ }
+ delete directory_;
+ delete stream_map_;
+}
+
+
+bool Minidump::Open() {
+ if (stream_ != NULL) {
+ BPLOG(INFO) << "Minidump reopening minidump " << path_;
+
+ // The file is already open. Seek to the beginning, which is the position
+ // the file would be at if it were opened anew.
+ return SeekSet(0);
+ }
+
+ stream_ = new ifstream(path_.c_str(), std::ios::in | std::ios::binary);
+ if (!stream_ || !stream_->good()) {
+ string error_string;
+ int error_code = ErrnoString(&error_string);
+ BPLOG(ERROR) << "Minidump could not open minidump " << path_ <<
+ ", error " << error_code << ": " << error_string;
+ return false;
+ }
+
+ BPLOG(INFO) << "Minidump opened minidump " << path_;
+ return true;
+}
+
+bool Minidump::GetContextCPUFlagsFromSystemInfo(uint32_t *context_cpu_flags) {
+ // Initialize output parameters
+ *context_cpu_flags = 0;
+
+ // Save the current stream position
+ off_t saved_position = Tell();
+ if (saved_position == -1) {
+ // Failed to save the current stream position.
+ // Returns true because the current position of the stream is preserved.
+ return true;
+ }
+
+ const MDRawSystemInfo* system_info =
+ GetSystemInfo() ? GetSystemInfo()->system_info() : NULL;
+
+ if (system_info != NULL) {
+ switch (system_info->processor_architecture) {
+ case MD_CPU_ARCHITECTURE_X86:
+ *context_cpu_flags = MD_CONTEXT_X86;
+ break;
+ case MD_CPU_ARCHITECTURE_MIPS:
+ *context_cpu_flags = MD_CONTEXT_MIPS;
+ break;
+ case MD_CPU_ARCHITECTURE_MIPS64:
+ *context_cpu_flags = MD_CONTEXT_MIPS64;
+ break;
+ case MD_CPU_ARCHITECTURE_ALPHA:
+ *context_cpu_flags = MD_CONTEXT_ALPHA;
+ break;
+ case MD_CPU_ARCHITECTURE_PPC:
+ *context_cpu_flags = MD_CONTEXT_PPC;
+ break;
+ case MD_CPU_ARCHITECTURE_PPC64:
+ *context_cpu_flags = MD_CONTEXT_PPC64;
+ break;
+ case MD_CPU_ARCHITECTURE_SHX:
+ *context_cpu_flags = MD_CONTEXT_SHX;
+ break;
+ case MD_CPU_ARCHITECTURE_ARM:
+ *context_cpu_flags = MD_CONTEXT_ARM;
+ break;
+ case MD_CPU_ARCHITECTURE_ARM64:
+ *context_cpu_flags = MD_CONTEXT_ARM64;
+ break;
+ case MD_CPU_ARCHITECTURE_ARM64_OLD:
+ *context_cpu_flags = MD_CONTEXT_ARM64_OLD;
+ break;
+ case MD_CPU_ARCHITECTURE_IA64:
+ *context_cpu_flags = MD_CONTEXT_IA64;
+ break;
+ case MD_CPU_ARCHITECTURE_ALPHA64:
+ *context_cpu_flags = 0;
+ break;
+ case MD_CPU_ARCHITECTURE_MSIL:
+ *context_cpu_flags = 0;
+ break;
+ case MD_CPU_ARCHITECTURE_AMD64:
+ *context_cpu_flags = MD_CONTEXT_AMD64;
+ break;
+ case MD_CPU_ARCHITECTURE_X86_WIN64:
+ *context_cpu_flags = 0;
+ break;
+ case MD_CPU_ARCHITECTURE_SPARC:
+ *context_cpu_flags = MD_CONTEXT_SPARC;
+ break;
+ case MD_CPU_ARCHITECTURE_UNKNOWN:
+ *context_cpu_flags = 0;
+ break;
+ default:
+ *context_cpu_flags = 0;
+ break;
+ }
+ }
+
+ // Restore position and return
+ return SeekSet(saved_position);
+}
+
+
+bool Minidump::Read() {
+ // Invalidate cached data.
+ delete directory_;
+ directory_ = NULL;
+ stream_map_->clear();
+
+ valid_ = false;
+
+ if (!Open()) {
+ BPLOG(ERROR) << "Minidump cannot open minidump";
+ return false;
+ }
+
+ if (!ReadBytes(&header_, sizeof(MDRawHeader))) {
+ BPLOG(ERROR) << "Minidump cannot read header";
+ return false;
+ }
+
+ if (header_.signature != MD_HEADER_SIGNATURE) {
+ // The file may be byte-swapped. Under the present architecture, these
+ // classes don't know or need to know what CPU (or endianness) the
+ // minidump was produced on in order to parse it. Use the signature as
+ // a byte order marker.
+ uint32_t signature_swapped = header_.signature;
+ Swap(&signature_swapped);
+ if (signature_swapped != MD_HEADER_SIGNATURE) {
+ // This isn't a minidump or a byte-swapped minidump.
+ BPLOG(ERROR) << "Minidump header signature mismatch: (" <<
+ HexString(header_.signature) << ", " <<
+ HexString(signature_swapped) << ") != " <<
+ HexString(MD_HEADER_SIGNATURE);
+ return false;
+ }
+ swap_ = true;
+ } else {
+ // The file is not byte-swapped. Set swap_ false (it may have been true
+ // if the object is being reused?)
+ swap_ = false;
+ }
+
+#if defined(__BIG_ENDIAN__) || \
+ (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
+ is_big_endian_ = !swap_;
+#else
+ is_big_endian_ = swap_;
+#endif
+
+ BPLOG(INFO) << "Minidump " << (swap_ ? "" : "not ") <<
+ "byte-swapping minidump";
+
+ if (swap_) {
+ Swap(&header_.signature);
+ Swap(&header_.version);
+ Swap(&header_.stream_count);
+ Swap(&header_.stream_directory_rva);
+ Swap(&header_.checksum);
+ Swap(&header_.time_date_stamp);
+ Swap(&header_.flags);
+ }
+
+ // Version check. The high 16 bits of header_.version contain something
+ // else "implementation specific."
+ if ((header_.version & 0x0000ffff) != MD_HEADER_VERSION) {
+ BPLOG(ERROR) << "Minidump version mismatch: " <<
+ HexString(header_.version & 0x0000ffff) << " != " <<
+ HexString(MD_HEADER_VERSION);
+ return false;
+ }
+
+ if (!SeekSet(header_.stream_directory_rva)) {
+ BPLOG(ERROR) << "Minidump cannot seek to stream directory";
+ return false;
+ }
+
+ if (header_.stream_count > max_streams_) {
+ BPLOG(ERROR) << "Minidump stream count " << header_.stream_count <<
+ " exceeds maximum " << max_streams_;
+ return false;
+ }
+
+ if (header_.stream_count != 0) {
+ scoped_ptr<MinidumpDirectoryEntries> directory(
+ new MinidumpDirectoryEntries(header_.stream_count));
+
+ // Read the entire array in one fell swoop, instead of reading one entry
+ // at a time in the loop.
+ if (!ReadBytes(&(*directory)[0],
+ sizeof(MDRawDirectory) * header_.stream_count)) {
+ BPLOG(ERROR) << "Minidump cannot read stream directory";
+ return false;
+ }
+
+ for (unsigned int stream_index = 0;
+ stream_index < header_.stream_count;
+ ++stream_index) {
+ MDRawDirectory* directory_entry = &(*directory)[stream_index];
+
+ if (swap_) {
+ Swap(&directory_entry->stream_type);
+ Swap(&directory_entry->location);
+ }
+
+ // Initialize the stream_map_ map, which speeds locating a stream by
+ // type.
+ unsigned int stream_type = directory_entry->stream_type;
+ switch (stream_type) {
+ case MD_THREAD_LIST_STREAM:
+ case MD_MODULE_LIST_STREAM:
+ case MD_MEMORY_LIST_STREAM:
+ case MD_EXCEPTION_STREAM:
+ case MD_SYSTEM_INFO_STREAM:
+ case MD_MISC_INFO_STREAM:
+ case MD_BREAKPAD_INFO_STREAM:
+ case MD_CRASHPAD_INFO_STREAM:
+ case MOZ_MACOS_CRASH_INFO_STREAM: {
+ if (stream_map_->find(stream_type) != stream_map_->end()) {
+ // Another stream with this type was already found. A minidump
+ // file should contain at most one of each of these stream types.
+ BPLOG(ERROR) << "Minidump found multiple streams of type " <<
+ stream_type << ", but can only deal with one";
+ return false;
+ }
+ BP_FALLTHROUGH;
+ }
+
+ default: {
+ // Overwrites for stream types other than those above, but it's
+ // expected to be the user's burden in that case.
+ (*stream_map_)[stream_type].stream_index = stream_index;
+ }
+ }
+ }
+
+ directory_ = directory.release();
+ }
+
+ valid_ = true;
+ return true;
+}
+
+
+MinidumpThreadList* Minidump::GetThreadList() {
+ MinidumpThreadList* thread_list;
+ return GetStream(&thread_list);
+}
+
+
+MinidumpModuleList* Minidump::GetModuleList() {
+ MinidumpModuleList* module_list;
+ return GetStream(&module_list);
+}
+
+
+MinidumpMemoryList* Minidump::GetMemoryList() {
+ MinidumpMemoryList* memory_list;
+ return GetStream(&memory_list);
+}
+
+
+MinidumpException* Minidump::GetException() {
+ MinidumpException* exception;
+ return GetStream(&exception);
+}
+
+MinidumpAssertion* Minidump::GetAssertion() {
+ MinidumpAssertion* assertion;
+ return GetStream(&assertion);
+}
+
+
+MinidumpSystemInfo* Minidump::GetSystemInfo() {
+ MinidumpSystemInfo* system_info;
+ return GetStream(&system_info);
+}
+
+
+MinidumpUnloadedModuleList* Minidump::GetUnloadedModuleList() {
+ MinidumpUnloadedModuleList* unloaded_module_list;
+ return GetStream(&unloaded_module_list);
+}
+
+
+MinidumpMiscInfo* Minidump::GetMiscInfo() {
+ MinidumpMiscInfo* misc_info;
+ return GetStream(&misc_info);
+}
+
+
+MinidumpBreakpadInfo* Minidump::GetBreakpadInfo() {
+ MinidumpBreakpadInfo* breakpad_info;
+ return GetStream(&breakpad_info);
+}
+
+MinidumpMemoryInfoList* Minidump::GetMemoryInfoList() {
+ MinidumpMemoryInfoList* memory_info_list;
+ return GetStream(&memory_info_list);
+}
+
+MinidumpLinuxMapsList *Minidump::GetLinuxMapsList() {
+ MinidumpLinuxMapsList *linux_maps_list;
+ return GetStream(&linux_maps_list);
+}
+
+bool Minidump::IsAndroid() {
+ MDOSPlatform platform;
+ return GetPlatform(&platform) && platform == MD_OS_ANDROID;
+}
+
+bool Minidump::GetPlatform(MDOSPlatform* platform) {
+ // Save the current stream position
+ off_t saved_position = Tell();
+ if (saved_position == -1) {
+ return false;
+ }
+ const MDRawSystemInfo* system_info =
+ GetSystemInfo() ? GetSystemInfo()->system_info() : NULL;
+
+ // Restore position and return
+ if (!SeekSet(saved_position)) {
+ BPLOG(ERROR) << "Couldn't seek back to saved position";
+ return false;
+ }
+
+ if (!system_info) {
+ return false;
+ }
+ *platform = static_cast<MDOSPlatform>(system_info->platform_id);
+ return true;
+}
+
+MinidumpCrashpadInfo* Minidump::GetCrashpadInfo() {
+ MinidumpCrashpadInfo* crashpad_info;
+ return GetStream(&crashpad_info);
+}
+
+MinidumpMacCrashInfo* Minidump::GetMacCrashInfo() {
+ MinidumpMacCrashInfo* mac_crash_info;
+ return GetStream(&mac_crash_info);
+}
+
+MinidumpThreadNamesList* Minidump::GetThreadNamesList() {
+ MinidumpThreadNamesList* thread_names_list;
+ return GetStream(&thread_names_list);
+}
+
+//
+// MinidumpThreadName
+//
+
+
+MinidumpThreadName::MinidumpThreadName(Minidump* minidump)
+ : MinidumpObject(minidump),
+ valid_(false),
+ thread_name_(),
+ name_(NULL) {
+
+}
+
+MinidumpThreadName::~MinidumpThreadName() {
+ ;
+}
+
+void MinidumpThreadName::Print() {
+ if (!valid_) {
+ BPLOG(ERROR) << "MinidumpThreadName cannot print invalid data";
+ return;
+ }
+
+ printf("MDRawThreadName\n");
+ printf(" thread_id = 0x%x\n",
+ thread_name_.thread_id);
+ printf(" rva_of_thread_name = 0x%" PRIx64 "\n",
+ thread_name_.rva_of_thread_name);
+
+ printf(" (name) = \"%s\"\n", name().c_str());
+ printf("\n");
+}
+
+string MinidumpThreadName::name() const {
+ if (!valid_) {
+ BPLOG(ERROR) << "Invalid MinidumpThreadName for name";
+ return "";
+ }
+
+ return *name_;
+}
+
+bool MinidumpThreadName::Read(uint32_t expected_size) {
+
+ delete name_;
+
+ if (expected_size < sizeof(thread_name_)) {
+ BPLOG(ERROR) << "MinidumpThreadName expected size is less than size "
+ << "of struct " << expected_size << " < "
+ << sizeof(thread_name_);
+ return false;
+ }
+
+ if (!minidump_->ReadBytes(&thread_name_, sizeof(thread_name_))) {
+ BPLOG(ERROR) << "MinidumpThreadName cannot read name";
+ return false;
+ }
+
+ if (expected_size > sizeof(thread_name_)) {
+ uint32_t thread_name_bytes_remaining = expected_size - sizeof(thread_name_);
+ off_t pos = minidump_->Tell();
+ if (!minidump_->SeekSet(pos + thread_name_bytes_remaining)) {
+ BPLOG(ERROR) << "MinidumpThreadName unable to seek to end of name";
+ return false;
+ }
+ }
+
+ if (minidump_->swap()) {
+ Swap(&thread_name_.thread_id);
+ uint64_t rva_of_thread_name;
+ memcpy(&rva_of_thread_name, &thread_name_.rva_of_thread_name, sizeof(uint64_t));
+ Swap(&rva_of_thread_name);
+ memcpy(&thread_name_.rva_of_thread_name, &rva_of_thread_name, sizeof(uint64_t));
+ }
+
+ return true;
+}
+
+bool MinidumpThreadName::ReadAuxiliaryData() {
+ // Each thread must have a name string.
+ name_ = minidump_->ReadString(thread_name_.rva_of_thread_name);
+ if (!name_) {
+ BPLOG(ERROR) << "MinidumpThreadName could not read name";
+ valid_ = false;
+ return false;
+ }
+
+ // At this point, we have enough info for the name to be valid.
+ valid_ = true;
+ return true;
+}
+
+//
+// MinidumpThreadNamesList
+//
+
+
+MinidumpThreadNamesList::MinidumpThreadNamesList(Minidump* minidump)
+ : MinidumpStream(minidump),
+ thread_names_(NULL),
+ name_count_(0),
+ valid_(false) {
+ ;
+}
+
+MinidumpThreadNamesList::~MinidumpThreadNamesList() {
+ delete thread_names_;
+}
+
+const string MinidumpThreadNamesList::GetNameForThreadId(uint32_t thread_id) const {
+ if (valid_) {
+ for (unsigned int name_index = 0;
+ name_index < name_count_;
+ ++name_index) {
+ const MinidumpThreadName& thread_name = (*thread_names_)[name_index];
+ if (thread_name.thread_id() == thread_id) {
+ return thread_name.name();
+ }
+ }
+ }
+
+ return "";
+}
+
+void MinidumpThreadNamesList::Print() {
+ if (!valid_) {
+ BPLOG(ERROR) << "MinidumpThreadNamesList cannot print invalid data";
+ return;
+ }
+
+ printf("MinidumpThreadNamesList\n");
+ printf(" name_count = %d\n", name_count_);
+ printf("\n");
+
+ for (unsigned int name_index = 0;
+ name_index < name_count_;
+ ++name_index) {
+ printf("thread_name[%d]\n", name_index);
+
+ (*thread_names_)[name_index].Print();
+ }
+}
+
+bool MinidumpThreadNamesList::Read(uint32_t expected_size) {
+ delete thread_names_;
+ thread_names_ = NULL;
+ name_count_ = 0;
+
+ valid_ = false;
+
+ uint32_t number_of_thread_names;
+ if (!minidump_->ReadBytes(&number_of_thread_names, sizeof(number_of_thread_names))) {
+ BPLOG(ERROR) << "MinidumpThreadNamesList could not read the number of thread names";
+ return false;
+ }
+
+ if (minidump_->swap()) {
+ Swap(&number_of_thread_names);
+ }
+
+ if (expected_size !=
+ sizeof(number_of_thread_names) + (sizeof(MDRawThreadName) * number_of_thread_names)) {
+ BPLOG(ERROR) << "MinidumpThreadNamesList expected_size mismatch " <<
+ expected_size << " != " << sizeof(number_of_thread_names) << " + (" <<
+ sizeof(MDRawThreadName) << " * " << number_of_thread_names << ")";
+ return false;
+ }
+
+ if (number_of_thread_names != 0) {
+ scoped_ptr<MinidumpThreadNames> thread_names(
+ new MinidumpThreadNames(number_of_thread_names,
+ MinidumpThreadName(minidump_)));
+
+ for (unsigned int name_index = 0;
+ name_index < number_of_thread_names;
+ ++name_index) {
+ MinidumpThreadName* thread_name = &(*thread_names)[name_index];
+
+ if (!thread_name->Read(sizeof(MDRawThreadName))) {
+ BPLOG(ERROR) << "MinidumpThreadNamesList could not read name " <<
+ name_index << "/" << number_of_thread_names;
+ return false;
+ }
+ }
+
+ for (unsigned int name_index = 0;
+ name_index < number_of_thread_names;
+ ++name_index) {
+ MinidumpThreadName* thread_name = &(*thread_names)[name_index];
+
+ if (!thread_name->ReadAuxiliaryData()) {
+ BPLOG(ERROR) << "MinidumpThreadNamesList could not read required "
+ "auxiliary data for thread name " <<
+ name_index << "/" << number_of_thread_names;
+ return false;
+ }
+ }
+ thread_names_ = thread_names.release();
+ }
+
+ name_count_ = number_of_thread_names;
+ valid_ = true;
+ return true;
+}
+
+static const char* get_stream_name(uint32_t stream_type) {
+ switch (stream_type) {
+ case MD_UNUSED_STREAM:
+ return "MD_UNUSED_STREAM";
+ case MD_RESERVED_STREAM_0:
+ return "MD_RESERVED_STREAM_0";
+ case MD_RESERVED_STREAM_1:
+ return "MD_RESERVED_STREAM_1";
+ case MD_THREAD_LIST_STREAM:
+ return "MD_THREAD_LIST_STREAM";
+ case MD_MODULE_LIST_STREAM:
+ return "MD_MODULE_LIST_STREAM";
+ case MD_MEMORY_LIST_STREAM:
+ return "MD_MEMORY_LIST_STREAM";
+ case MD_EXCEPTION_STREAM:
+ return "MD_EXCEPTION_STREAM";
+ case MD_SYSTEM_INFO_STREAM:
+ return "MD_SYSTEM_INFO_STREAM";
+ case MD_THREAD_EX_LIST_STREAM:
+ return "MD_THREAD_EX_LIST_STREAM";
+ case MD_MEMORY_64_LIST_STREAM:
+ return "MD_MEMORY_64_LIST_STREAM";
+ case MD_COMMENT_STREAM_A:
+ return "MD_COMMENT_STREAM_A";
+ case MD_COMMENT_STREAM_W:
+ return "MD_COMMENT_STREAM_W";
+ case MD_HANDLE_DATA_STREAM:
+ return "MD_HANDLE_DATA_STREAM";
+ case MD_FUNCTION_TABLE_STREAM:
+ return "MD_FUNCTION_TABLE_STREAM";
+ case MD_UNLOADED_MODULE_LIST_STREAM:
+ return "MD_UNLOADED_MODULE_LIST_STREAM";
+ case MD_MISC_INFO_STREAM:
+ return "MD_MISC_INFO_STREAM";
+ case MD_MEMORY_INFO_LIST_STREAM:
+ return "MD_MEMORY_INFO_LIST_STREAM";
+ case MD_THREAD_INFO_LIST_STREAM:
+ return "MD_THREAD_INFO_LIST_STREAM";
+ case MD_HANDLE_OPERATION_LIST_STREAM:
+ return "MD_HANDLE_OPERATION_LIST_STREAM";
+ case MD_TOKEN_STREAM:
+ return "MD_TOKEN_STREAM";
+ case MD_JAVASCRIPT_DATA_STREAM:
+ return "MD_JAVASCRIPT_DATA_STREAM";
+ case MD_SYSTEM_MEMORY_INFO_STREAM:
+ return "MD_SYSTEM_MEMORY_INFO_STREAM";
+ case MD_PROCESS_VM_COUNTERS_STREAM:
+ return "MD_PROCESS_VM_COUNTERS_STREAM";
+ case MD_IPT_TRACE_STREAM:
+ return "MD_IPT_TRACE_STREAM";
+ case MD_THREAD_NAMES_STREAM:
+ return "MD_THREAD_NAMES_STREAM";
+ case MD_LAST_RESERVED_STREAM:
+ return "MD_LAST_RESERVED_STREAM";
+ case MD_BREAKPAD_INFO_STREAM:
+ return "MD_BREAKPAD_INFO_STREAM";
+ case MD_ASSERTION_INFO_STREAM:
+ return "MD_ASSERTION_INFO_STREAM";
+ case MD_LINUX_CPU_INFO:
+ return "MD_LINUX_CPU_INFO";
+ case MD_LINUX_PROC_STATUS:
+ return "MD_LINUX_PROC_STATUS";
+ case MD_LINUX_LSB_RELEASE:
+ return "MD_LINUX_LSB_RELEASE";
+ case MD_LINUX_CMD_LINE:
+ return "MD_LINUX_CMD_LINE";
+ case MD_LINUX_ENVIRON:
+ return "MD_LINUX_ENVIRON";
+ case MD_LINUX_AUXV:
+ return "MD_LINUX_AUXV";
+ case MD_LINUX_MAPS:
+ return "MD_LINUX_MAPS";
+ case MD_LINUX_DSO_DEBUG:
+ return "MD_LINUX_DSO_DEBUG";
+ case MD_CRASHPAD_INFO_STREAM:
+ return "MD_CRASHPAD_INFO_STREAM";
+ case MOZ_MACOS_CRASH_INFO_STREAM:
+ return "MOZ_MACOS_CRASH_INFO_STREAM";
+ default:
+ return "unknown";
+ }
+}
+
+void Minidump::Print() {
+ if (!valid_) {
+ BPLOG(ERROR) << "Minidump cannot print invalid data";
+ return;
+ }
+
+ printf("MDRawHeader\n");
+ printf(" signature = 0x%x\n", header_.signature);
+ printf(" version = 0x%x\n", header_.version);
+ printf(" stream_count = %d\n", header_.stream_count);
+ printf(" stream_directory_rva = 0x%x\n", header_.stream_directory_rva);
+ printf(" checksum = 0x%x\n", header_.checksum);
+ printf(" time_date_stamp = 0x%x %s\n",
+ header_.time_date_stamp,
+ TimeTToUTCString(header_.time_date_stamp).c_str());
+ printf(" flags = 0x%" PRIx64 "\n", header_.flags);
+ printf("\n");
+
+ for (unsigned int stream_index = 0;
+ stream_index < header_.stream_count;
+ ++stream_index) {
+ MDRawDirectory* directory_entry = &(*directory_)[stream_index];
+
+ printf("mDirectory[%d]\n", stream_index);
+ printf("MDRawDirectory\n");
+ printf(" stream_type = 0x%x (%s)\n", directory_entry->stream_type,
+ get_stream_name(directory_entry->stream_type));
+ printf(" location.data_size = %d\n",
+ directory_entry->location.data_size);
+ printf(" location.rva = 0x%x\n", directory_entry->location.rva);
+ printf("\n");
+ }
+
+ printf("Streams:\n");
+ for (MinidumpStreamMap::const_iterator iterator = stream_map_->begin();
+ iterator != stream_map_->end();
+ ++iterator) {
+ uint32_t stream_type = iterator->first;
+ const MinidumpStreamInfo& info = iterator->second;
+ printf(" stream type 0x%x (%s) at index %d\n", stream_type,
+ get_stream_name(stream_type),
+ info.stream_index);
+ }
+ printf("\n");
+}
+
+
+const MDRawDirectory* Minidump::GetDirectoryEntryAtIndex(unsigned int index)
+ const {
+ if (!valid_) {
+ BPLOG(ERROR) << "Invalid Minidump for GetDirectoryEntryAtIndex";
+ return NULL;
+ }
+
+ if (index >= header_.stream_count) {
+ BPLOG(ERROR) << "Minidump stream directory index out of range: " <<
+ index << "/" << header_.stream_count;
+ return NULL;
+ }
+
+ return &(*directory_)[index];
+}
+
+
+bool Minidump::ReadBytes(void* bytes, size_t count) {
+ // Can't check valid_ because Read needs to call this method before
+ // validity can be determined.
+ if (!stream_) {
+ return false;
+ }
+ stream_->read(static_cast<char*>(bytes), count);
+ std::streamsize bytes_read = stream_->gcount();
+ if (bytes_read == -1) {
+ string error_string;
+ int error_code = ErrnoString(&error_string);
+ BPLOG(ERROR) << "ReadBytes: error " << error_code << ": " << error_string;
+ return false;
+ }
+
+ // Convert to size_t and check for data loss
+ size_t bytes_read_converted = static_cast<size_t>(bytes_read);
+ if (static_cast<std::streamsize>(bytes_read_converted) != bytes_read) {
+ BPLOG(ERROR) << "ReadBytes: conversion data loss detected when converting "
+ << bytes_read << " to " << bytes_read_converted;
+ return false;
+ }
+
+ if (bytes_read_converted != count) {
+ BPLOG(ERROR) << "ReadBytes: read " << bytes_read_converted << "/" << count;
+ return false;
+ }
+
+ return true;
+}
+
+
+bool Minidump::SeekSet(off_t offset) {
+ // Can't check valid_ because Read needs to call this method before
+ // validity can be determined.
+ if (!stream_) {
+ return false;
+ }
+ stream_->seekg(offset, std::ios_base::beg);
+ if (!stream_->good()) {
+ string error_string;
+ int error_code = ErrnoString(&error_string);
+ BPLOG(ERROR) << "SeekSet: error " << error_code << ": " << error_string;
+ return false;
+ }
+ return true;
+}
+
+off_t Minidump::Tell() {
+ if (!valid_ || !stream_) {
+ return (off_t)-1;
+ }
+
+ // Check for conversion data loss
+ std::streamoff std_streamoff = stream_->tellg();
+ off_t rv = static_cast<off_t>(std_streamoff);
+ if (static_cast<std::streamoff>(rv) == std_streamoff) {
+ return rv;
+ } else {
+ BPLOG(ERROR) << "Data loss detected";
+ return (off_t)-1;
+ }
+}
+
+
+string* Minidump::ReadString(off_t offset) {
+ if (!valid_) {
+ BPLOG(ERROR) << "Invalid Minidump for ReadString";
+ return NULL;
+ }
+ if (!SeekSet(offset)) {
+ BPLOG(ERROR) << "ReadString could not seek to string at offset " << offset;
+ return NULL;
+ }
+
+ uint32_t bytes;
+ if (!ReadBytes(&bytes, sizeof(bytes))) {
+ BPLOG(ERROR) << "ReadString could not read string size at offset " <<
+ offset;
+ return NULL;
+ }
+ if (swap_)
+ Swap(&bytes);
+
+ if (bytes % 2 != 0) {
+ BPLOG(ERROR) << "ReadString found odd-sized " << bytes <<
+ "-byte string at offset " << offset;
+ return NULL;
+ }
+ unsigned int utf16_words = bytes / 2;
+
+ if (utf16_words > max_string_length_) {
+ BPLOG(ERROR) << "ReadString string length " << utf16_words <<
+ " exceeds maximum " << max_string_length_ <<
+ " at offset " << offset;
+ return NULL;
+ }
+
+ vector<uint16_t> string_utf16(utf16_words);
+
+ if (utf16_words) {
+ if (!ReadBytes(&string_utf16[0], bytes)) {
+ BPLOG(ERROR) << "ReadString could not read " << bytes <<
+ "-byte string at offset " << offset;
+ return NULL;
+ }
+ }
+
+ return UTF16ToUTF8(string_utf16, swap_);
+}
+
+
+bool Minidump::ReadUTF8String(off_t offset, string* string_utf8) {
+ if (!valid_) {
+ BPLOG(ERROR) << "Invalid Minidump for ReadString";
+ return false;
+ }
+ if (!SeekSet(offset)) {
+ BPLOG(ERROR) << "ReadUTF8String could not seek to string at offset "
+ << offset;
+ return false;
+ }
+
+ uint32_t bytes;
+ if (!ReadBytes(&bytes, sizeof(bytes))) {
+ BPLOG(ERROR) << "ReadUTF8String could not read string size at offset " <<
+ offset;
+ return false;
+ }
+
+ if (swap_) {
+ Swap(&bytes);
+ }
+
+ if (bytes > max_string_length_) {
+ BPLOG(ERROR) << "ReadUTF8String string length " << bytes <<
+ " exceeds maximum " << max_string_length_ <<
+ " at offset " << offset;
+ return false;
+ }
+
+ string_utf8->resize(bytes);
+
+ if (!ReadBytes(&(*string_utf8)[0], bytes)) {
+ BPLOG(ERROR) << "ReadUTF8String could not read " << bytes <<
+ "-byte string at offset " << offset;
+ return false;
+ }
+
+ return true;
+}
+
+
+bool Minidump::ReadStringList(
+ off_t offset,
+ std::vector<std::string>* string_list) {
+ string_list->clear();
+
+ if (!SeekSet(offset)) {
+ BPLOG(ERROR) << "Minidump cannot seek to string_list";
+ return false;
+ }
+
+ uint32_t count;
+ if (!ReadBytes(&count, sizeof(count))) {
+ BPLOG(ERROR) << "Minidump cannot read string_list count";
+ return false;
+ }
+
+ if (swap_) {
+ Swap(&count);
+ }
+
+ scoped_array<MDRVA> rvas(new MDRVA[count]);
+
+ // Read the entire array in one fell swoop, instead of reading one entry
+ // at a time in the loop.
+ if (!ReadBytes(&rvas[0], sizeof(MDRVA) * count)) {
+ BPLOG(ERROR) << "Minidump could not read string_list";
+ return false;
+ }
+
+ for (uint32_t index = 0; index < count; ++index) {
+ if (swap()) {
+ Swap(&rvas[index]);
+ }
+
+ string entry;
+ if (!ReadUTF8String(rvas[index], &entry)) {
+ BPLOG(ERROR) << "Minidump could not read string_list entry";
+ return false;
+ }
+
+ string_list->push_back(entry);
+ }
+
+ return true;
+}
+
+
+bool Minidump::ReadSimpleStringDictionary(
+ off_t offset,
+ std::map<std::string, std::string>* simple_string_dictionary) {
+ simple_string_dictionary->clear();
+
+ if (!SeekSet(offset)) {
+ BPLOG(ERROR) << "Minidump cannot seek to simple_string_dictionary";
+ return false;
+ }
+
+ uint32_t count;
+ if (!ReadBytes(&count, sizeof(count))) {
+ BPLOG(ERROR)
+ << "Minidump cannot read simple_string_dictionary count";
+ return false;
+ }
+
+ if (swap()) {
+ Swap(&count);
+ }
+
+ scoped_array<MDRawSimpleStringDictionaryEntry> entries(
+ new MDRawSimpleStringDictionaryEntry[count]);
+
+ // Read the entire array in one fell swoop, instead of reading one entry
+ // at a time in the loop.
+ if (!ReadBytes(
+ &entries[0],
+ sizeof(MDRawSimpleStringDictionaryEntry) * count)) {
+ BPLOG(ERROR) << "Minidump could not read simple_string_dictionary";
+ return false;
+ }
+
+ for (uint32_t index = 0; index < count; ++index) {
+ if (swap()) {
+ Swap(&entries[index]);
+ }
+
+ string key;
+ if (!ReadUTF8String(entries[index].key, &key)) {
+ BPLOG(ERROR) << "Minidump could not read simple_string_dictionary key";
+ return false;
+ }
+
+ string value;
+ if (!ReadUTF8String(entries[index].value, &value)) {
+ BPLOG(ERROR) << "Minidump could not read simple_string_dictionary value";
+ return false;
+ }
+
+ if (simple_string_dictionary->find(key) !=
+ simple_string_dictionary->end()) {
+ BPLOG(ERROR)
+ << "Minidump: discarding duplicate simple_string_dictionary value "
+ << value << " for key " << key;
+ } else {
+ simple_string_dictionary->insert(std::make_pair(key, value));
+ }
+ }
+
+ return true;
+}
+
+
+bool Minidump::SeekToStreamType(uint32_t stream_type,
+ uint32_t* stream_length) {
+ BPLOG_IF(ERROR, !stream_length) << "Minidump::SeekToStreamType requires "
+ "|stream_length|";
+ assert(stream_length);
+ *stream_length = 0;
+
+ if (!valid_) {
+ BPLOG(ERROR) << "Invalid Mindump for SeekToStreamType";
+ return false;
+ }
+
+ MinidumpStreamMap::const_iterator iterator = stream_map_->find(stream_type);
+ if (iterator == stream_map_->end()) {
+ // This stream type didn't exist in the directory.
+ BPLOG(INFO) << "SeekToStreamType: type " << stream_type << " not present";
+ return false;
+ }
+
+ const MinidumpStreamInfo& info = iterator->second;
+ if (info.stream_index >= header_.stream_count) {
+ BPLOG(ERROR) << "SeekToStreamType: type " << stream_type <<
+ " out of range: " <<
+ info.stream_index << "/" << header_.stream_count;
+ return false;
+ }
+
+ MDRawDirectory* directory_entry = &(*directory_)[info.stream_index];
+ if (!SeekSet(directory_entry->location.rva)) {
+ BPLOG(ERROR) << "SeekToStreamType could not seek to stream type " <<
+ stream_type;
+ return false;
+ }
+
+ *stream_length = directory_entry->location.data_size;
+
+ return true;
+}
+
+
+template<typename T>
+T* Minidump::GetStream(T** stream) {
+ // stream is a garbage parameter that's present only to account for C++'s
+ // inability to overload a method based solely on its return type.
+
+ const uint32_t stream_type = T::kStreamType;
+
+ BPLOG_IF(ERROR, !stream) << "Minidump::GetStream type " << stream_type <<
+ " requires |stream|";
+ assert(stream);
+ *stream = NULL;
+
+ if (!valid_) {
+ BPLOG(ERROR) << "Invalid Minidump for GetStream type " << stream_type;
+ return NULL;
+ }
+
+ MinidumpStreamMap::iterator iterator = stream_map_->find(stream_type);
+ if (iterator == stream_map_->end()) {
+ // This stream type didn't exist in the directory.
+ BPLOG(INFO) << "GetStream: type " << stream_type << " not present";
+ return NULL;
+ }
+
+ // Get a pointer so that the stored stream field can be altered.
+ MinidumpStreamInfo* info = &iterator->second;
+
+ if (info->stream) {
+ // This cast is safe because info.stream is only populated by this
+ // method, and there is a direct correlation between T and stream_type.
+ *stream = static_cast<T*>(info->stream);
+ return *stream;
+ }
+
+ uint32_t stream_length;
+ if (!SeekToStreamType(stream_type, &stream_length)) {
+ BPLOG(ERROR) << "GetStream could not seek to stream type " << stream_type;
+ return NULL;
+ }
+
+ scoped_ptr<T> new_stream(new T(this));
+
+ if (!new_stream->Read(stream_length)) {
+ BPLOG(ERROR) << "GetStream could not read stream type " << stream_type;
+ return NULL;
+ }
+
+ *stream = new_stream.release();
+ info->stream = *stream;
+ return *stream;
+}
+
+} // namespace google_breakpad
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/minidump_dump.cc b/toolkit/crashreporter/google-breakpad/src/processor/minidump_dump.cc
new file mode 100644
index 0000000000..63f25f3800
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/minidump_dump.cc
@@ -0,0 +1,291 @@
+// Copyright (c) 2006, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// minidump_dump.cc: Print the contents of a minidump file in somewhat
+// readable text.
+//
+// Author: Mark Mentovai
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "common/scoped_ptr.h"
+#include "google_breakpad/processor/minidump.h"
+#include "processor/logging.h"
+
+namespace {
+
+using google_breakpad::Minidump;
+using google_breakpad::MinidumpThreadList;
+using google_breakpad::MinidumpModuleList;
+using google_breakpad::MinidumpUnloadedModuleList;
+using google_breakpad::MinidumpMemoryInfoList;
+using google_breakpad::MinidumpMemoryList;
+using google_breakpad::MinidumpException;
+using google_breakpad::MinidumpAssertion;
+using google_breakpad::MinidumpSystemInfo;
+using google_breakpad::MinidumpMiscInfo;
+using google_breakpad::MinidumpBreakpadInfo;
+using google_breakpad::MinidumpCrashpadInfo;
+using google_breakpad::MinidumpThreadNamesList;
+
+struct Options {
+ Options()
+ : minidumpPath(), hexdump(false), hexdump_width(16) {}
+
+ string minidumpPath;
+ bool hexdump;
+ unsigned int hexdump_width;
+};
+
+static void DumpRawStream(Minidump *minidump,
+ uint32_t stream_type,
+ const char *stream_name,
+ int *errors) {
+ uint32_t length = 0;
+ if (!minidump->SeekToStreamType(stream_type, &length)) {
+ return;
+ }
+
+ printf("Stream %s:\n", stream_name);
+
+ if (length == 0) {
+ printf("\n");
+ return;
+ }
+ std::vector<char> contents(length);
+ if (!minidump->ReadBytes(&contents[0], length)) {
+ ++*errors;
+ BPLOG(ERROR) << "minidump.ReadBytes failed";
+ return;
+ }
+ size_t current_offset = 0;
+ while (current_offset < length) {
+ size_t remaining = length - current_offset;
+ // Printf requires an int and direct casting from size_t results
+ // in compatibility warnings.
+ uint32_t int_remaining = remaining;
+ printf("%.*s", int_remaining, &contents[current_offset]);
+ char *next_null = reinterpret_cast<char *>(
+ memchr(&contents[current_offset], 0, remaining));
+ if (next_null == NULL)
+ break;
+ printf("\\0\n");
+ size_t null_offset = next_null - &contents[0];
+ current_offset = null_offset + 1;
+ }
+ printf("\n\n");
+}
+
+static bool PrintMinidumpDump(const Options& options) {
+ Minidump minidump(options.minidumpPath,
+ options.hexdump);
+ if (!minidump.Read()) {
+ BPLOG(ERROR) << "minidump.Read() failed";
+ return false;
+ }
+ minidump.Print();
+
+ int errors = 0;
+
+ MinidumpThreadList *thread_list = minidump.GetThreadList();
+ if (!thread_list) {
+ ++errors;
+ BPLOG(ERROR) << "minidump.GetThreadList() failed";
+ } else {
+ thread_list->Print();
+ }
+
+ // It's useful to be able to see the full list of modules here even if it
+ // would cause minidump_stackwalk to fail.
+ MinidumpModuleList::set_max_modules(UINT32_MAX);
+ MinidumpModuleList *module_list = minidump.GetModuleList();
+ if (!module_list) {
+ ++errors;
+ BPLOG(ERROR) << "minidump.GetModuleList() failed";
+ } else {
+ module_list->Print();
+ }
+
+ MinidumpUnloadedModuleList::set_max_modules(UINT32_MAX);
+ MinidumpUnloadedModuleList *unloaded_module_list = minidump.GetUnloadedModuleList();
+ if (!unloaded_module_list) {
+ ++errors;
+ BPLOG(ERROR) << "minidump.GetUnloadedModuleList() failed";
+ } else {
+ unloaded_module_list->Print();
+ }
+
+ MinidumpMemoryList *memory_list = minidump.GetMemoryList();
+ if (!memory_list) {
+ ++errors;
+ BPLOG(ERROR) << "minidump.GetMemoryList() failed";
+ } else {
+ memory_list->Print();
+ }
+
+ MinidumpException *exception = minidump.GetException();
+ if (!exception) {
+ BPLOG(INFO) << "minidump.GetException() failed";
+ } else {
+ exception->Print();
+ }
+
+ MinidumpAssertion *assertion = minidump.GetAssertion();
+ if (!assertion) {
+ BPLOG(INFO) << "minidump.GetAssertion() failed";
+ } else {
+ assertion->Print();
+ }
+
+ MinidumpSystemInfo *system_info = minidump.GetSystemInfo();
+ if (!system_info) {
+ ++errors;
+ BPLOG(ERROR) << "minidump.GetSystemInfo() failed";
+ } else {
+ system_info->Print();
+ }
+
+ MinidumpMiscInfo *misc_info = minidump.GetMiscInfo();
+ if (!misc_info) {
+ ++errors;
+ BPLOG(ERROR) << "minidump.GetMiscInfo() failed";
+ } else {
+ misc_info->Print();
+ }
+
+ MinidumpBreakpadInfo *breakpad_info = minidump.GetBreakpadInfo();
+ if (!breakpad_info) {
+ // Breakpad info is optional, so don't treat this as an error.
+ BPLOG(INFO) << "minidump.GetBreakpadInfo() failed";
+ } else {
+ breakpad_info->Print();
+ }
+
+ MinidumpMemoryInfoList *memory_info_list = minidump.GetMemoryInfoList();
+ if (!memory_info_list) {
+ ++errors;
+ BPLOG(ERROR) << "minidump.GetMemoryInfoList() failed";
+ } else {
+ memory_info_list->Print();
+ }
+
+ MinidumpCrashpadInfo *crashpad_info = minidump.GetCrashpadInfo();
+ if (crashpad_info) {
+ // Crashpad info is optional, so don't treat absence as an error.
+ crashpad_info->Print();
+ }
+
+ MinidumpThreadNamesList *thread_names_list = minidump.GetThreadNamesList();
+ if (thread_names_list) {
+ thread_names_list->Print();
+ }
+
+ DumpRawStream(&minidump,
+ MD_LINUX_CMD_LINE,
+ "MD_LINUX_CMD_LINE",
+ &errors);
+ DumpRawStream(&minidump,
+ MD_LINUX_ENVIRON,
+ "MD_LINUX_ENVIRON",
+ &errors);
+ DumpRawStream(&minidump,
+ MD_LINUX_LSB_RELEASE,
+ "MD_LINUX_LSB_RELEASE",
+ &errors);
+ DumpRawStream(&minidump,
+ MD_LINUX_PROC_STATUS,
+ "MD_LINUX_PROC_STATUS",
+ &errors);
+ DumpRawStream(&minidump,
+ MD_LINUX_CPU_INFO,
+ "MD_LINUX_CPU_INFO",
+ &errors);
+ DumpRawStream(&minidump,
+ MD_LINUX_MAPS,
+ "MD_LINUX_MAPS",
+ &errors);
+
+ return errors == 0;
+}
+
+//=============================================================================
+static void
+Usage(int argc, char *argv[], bool error) {
+ FILE *fp = error ? stderr : stdout;
+
+ fprintf(fp,
+ "Usage: %s [options...] <minidump>\n"
+ "Dump data in a minidump.\n"
+ "\n"
+ "Options:\n"
+ " <minidump> should be a minidump.\n"
+ " -x:\t Display memory in a hexdump like format\n"
+ " -h:\t Usage\n",
+ argv[0]);
+}
+
+//=============================================================================
+static void
+SetupOptions(int argc, char *argv[], Options *options) {
+ int ch;
+
+ while ((ch = getopt(argc, (char * const *)argv, "xh")) != -1) {
+ switch (ch) {
+ case 'x':
+ options->hexdump = true;
+ break;
+ case 'h':
+ Usage(argc, argv, false);
+ exit(0);
+
+ default:
+ Usage(argc, argv, true);
+ exit(1);
+ break;
+ }
+ }
+
+ if ((argc - optind) != 1) {
+ fprintf(stderr, "%s: Missing minidump file\n", argv[0]);
+ exit(1);
+ }
+
+ options->minidumpPath = argv[optind];
+}
+
+} // namespace
+
+int main(int argc, char *argv[]) {
+ Options options;
+ BPLOG_INIT(&argc, &argv);
+ SetupOptions(argc, argv, &options);
+ return PrintMinidumpDump(options) ? 0 : 1;
+}
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/minidump_dump_test b/toolkit/crashreporter/google-breakpad/src/processor/minidump_dump_test
new file mode 100755
index 0000000000..fb62ace735
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/minidump_dump_test
@@ -0,0 +1,36 @@
+#!/bin/sh
+
+# Copyright (c) 2006, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+testdata_dir=$srcdir/src/processor/testdata
+./src/processor/minidump_dump $testdata_dir/minidump2.dmp | \
+ tr -d '\015' | \
+ diff -u $testdata_dir/minidump2.dump.out -
+exit $?
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/minidump_processor.cc b/toolkit/crashreporter/google-breakpad/src/processor/minidump_processor.cc
new file mode 100644
index 0000000000..bebac3ea48
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/minidump_processor.cc
@@ -0,0 +1,2146 @@
+// 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 "google_breakpad/processor/minidump_processor.h"
+
+#include <assert.h>
+
+#include <string>
+
+#include "common/scoped_ptr.h"
+#include "common/stdio_wrapper.h"
+#include "common/using_std_string.h"
+#include "google_breakpad/processor/call_stack.h"
+#include "google_breakpad/processor/minidump.h"
+#include "google_breakpad/processor/process_state.h"
+#include "google_breakpad/processor/exploitability.h"
+#include "google_breakpad/processor/stack_frame_symbolizer.h"
+#include "processor/logging.h"
+#include "processor/stackwalker_x86.h"
+#include "processor/symbolic_constants_win.h"
+
+namespace google_breakpad {
+
+MinidumpProcessor::MinidumpProcessor(SymbolSupplier *supplier,
+ SourceLineResolverInterface *resolver)
+ : frame_symbolizer_(new StackFrameSymbolizer(supplier, resolver)),
+ own_frame_symbolizer_(true),
+ enable_exploitability_(false),
+ enable_objdump_(false) {
+}
+
+MinidumpProcessor::MinidumpProcessor(SymbolSupplier *supplier,
+ SourceLineResolverInterface *resolver,
+ bool enable_exploitability)
+ : frame_symbolizer_(new StackFrameSymbolizer(supplier, resolver)),
+ own_frame_symbolizer_(true),
+ enable_exploitability_(enable_exploitability),
+ enable_objdump_(false) {
+}
+
+MinidumpProcessor::MinidumpProcessor(StackFrameSymbolizer *frame_symbolizer,
+ bool enable_exploitability)
+ : frame_symbolizer_(frame_symbolizer),
+ own_frame_symbolizer_(false),
+ enable_exploitability_(enable_exploitability),
+ enable_objdump_(false) {
+ assert(frame_symbolizer_);
+}
+
+MinidumpProcessor::~MinidumpProcessor() {
+ if (own_frame_symbolizer_) delete frame_symbolizer_;
+}
+
+ProcessResult MinidumpProcessor::Process(
+ Minidump *dump, ProcessState *process_state) {
+ assert(dump);
+ assert(process_state);
+
+ process_state->Clear();
+
+ const MDRawHeader *header = dump->header();
+ if (!header) {
+ BPLOG(ERROR) << "Minidump " << dump->path() << " has no header";
+ return PROCESS_ERROR_NO_MINIDUMP_HEADER;
+ }
+ process_state->time_date_stamp_ = header->time_date_stamp;
+
+ bool has_process_create_time =
+ GetProcessCreateTime(dump, &process_state->process_create_time_);
+
+ bool has_cpu_info = GetCPUInfo(dump, &process_state->system_info_);
+ bool has_os_info = GetOSInfo(dump, &process_state->system_info_);
+
+ uint32_t dump_thread_id = 0;
+ bool has_dump_thread = false;
+ uint32_t requesting_thread_id = 0;
+ bool has_requesting_thread = false;
+
+ MinidumpBreakpadInfo *breakpad_info = dump->GetBreakpadInfo();
+ if (breakpad_info) {
+ has_dump_thread = breakpad_info->GetDumpThreadID(&dump_thread_id);
+ has_requesting_thread =
+ breakpad_info->GetRequestingThreadID(&requesting_thread_id);
+ }
+
+ MinidumpException *exception = dump->GetException();
+ if (exception) {
+ process_state->crashed_ = true;
+ has_requesting_thread = exception->GetThreadID(&requesting_thread_id);
+
+ process_state->crash_reason_ = GetCrashReason(
+ dump, &process_state->crash_address_);
+
+ process_state->exception_record_.set_code(
+ exception->exception()->exception_record.exception_code,
+ // TODO(ivanpe): Populate description.
+ /* description = */ "");
+ process_state->exception_record_.set_flags(
+ exception->exception()->exception_record.exception_flags,
+ // TODO(ivanpe): Populate description.
+ /* description = */ "");
+ process_state->exception_record_.set_nested_exception_record_address(
+ exception->exception()->exception_record.exception_record);
+ process_state->exception_record_.set_address(process_state->crash_address_);
+ for (uint32_t i = 0;
+ i < exception->exception()->exception_record.number_parameters; i++) {
+ process_state->exception_record_.add_parameter(
+ exception->exception()->exception_record.exception_information[i],
+ // TODO(ivanpe): Populate description.
+ /* description = */ "");
+ }
+ }
+
+ MinidumpMacCrashInfo *crash_info = dump->GetMacCrashInfo();
+ if (crash_info) {
+ process_state->mac_crash_info_ = crash_info->description();
+ process_state->mac_crash_info_records_ = crash_info->records();
+ }
+
+ // This will just return an empty string if it doesn't exist.
+ process_state->assertion_ = GetAssertion(dump);
+
+ MinidumpModuleList *module_list = dump->GetModuleList();
+
+ // Put a copy of the module list into ProcessState object. This is not
+ // necessarily a MinidumpModuleList, but it adheres to the CodeModules
+ // interface, which is all that ProcessState needs to expose.
+ if (module_list) {
+ process_state->modules_ = module_list->Copy();
+ process_state->shrunk_range_modules_ =
+ process_state->modules_->GetShrunkRangeModules();
+ for (unsigned int i = 0;
+ i < process_state->shrunk_range_modules_.size();
+ i++) {
+ linked_ptr<const CodeModule> module =
+ process_state->shrunk_range_modules_[i];
+ BPLOG(INFO) << "The range for module " << module->code_file()
+ << " was shrunk down by " << HexString(
+ module->shrink_down_delta()) << " bytes. ";
+ }
+ }
+
+ MinidumpUnloadedModuleList *unloaded_module_list =
+ dump->GetUnloadedModuleList();
+ if (unloaded_module_list) {
+ process_state->unloaded_modules_ = unloaded_module_list->Copy();
+ }
+
+ MinidumpMemoryList *memory_list = dump->GetMemoryList();
+ if (memory_list) {
+ BPLOG(INFO) << "Found " << memory_list->region_count()
+ << " memory regions.";
+ }
+
+ MinidumpThreadNamesList* thread_names_list = dump->GetThreadNamesList();
+ if (thread_names_list) {
+ BPLOG(INFO) << "Found " << thread_names_list->name_count()
+ << " thread names.";
+ }
+
+ MinidumpThreadList *threads = dump->GetThreadList();
+ if (!threads) {
+ BPLOG(ERROR) << "Minidump " << dump->path() << " has no thread list";
+ return PROCESS_ERROR_NO_THREAD_LIST;
+ }
+
+ BPLOG(INFO) << "Minidump " << dump->path() << " has " <<
+ (has_cpu_info ? "" : "no ") << "CPU info, " <<
+ (has_os_info ? "" : "no ") << "OS info, " <<
+ (breakpad_info != NULL ? "" : "no ") << "Breakpad info, " <<
+ (exception != NULL ? "" : "no ") << "exception, " <<
+ (module_list != NULL ? "" : "no ") << "module list, " <<
+ (threads != NULL ? "" : "no ") << "thread list, " <<
+ (has_dump_thread ? "" : "no ") << "dump thread, " <<
+ (has_requesting_thread ? "" : "no ") << "requesting thread, and " <<
+ (has_process_create_time ? "" : "no ") << "process create time";
+
+ bool interrupted = false;
+ bool found_requesting_thread = false;
+ unsigned int thread_count = threads->thread_count();
+
+ // Reset frame_symbolizer_ at the beginning of stackwalk for each minidump.
+ frame_symbolizer_->Reset();
+
+ for (unsigned int thread_index = 0;
+ thread_index < thread_count;
+ ++thread_index) {
+ char thread_string_buffer[64];
+ snprintf(thread_string_buffer, sizeof(thread_string_buffer), "%d/%d",
+ thread_index, thread_count);
+ string thread_string = dump->path() + ":" + thread_string_buffer;
+
+ MinidumpThread *thread = threads->GetThreadAtIndex(thread_index);
+ if (!thread) {
+ BPLOG(ERROR) << "Could not get thread for " << thread_string;
+ return PROCESS_ERROR_GETTING_THREAD;
+ }
+
+ uint32_t thread_id;
+ if (!thread->GetThreadID(&thread_id)) {
+ BPLOG(ERROR) << "Could not get thread ID for " << thread_string;
+ return PROCESS_ERROR_GETTING_THREAD_ID;
+ }
+
+ thread_string += " id " + HexString(thread_id);
+ BPLOG(INFO) << "Looking at thread " << thread_string;
+
+ // If this thread is the thread that produced the minidump, don't process
+ // it. Because of the problems associated with a thread producing a
+ // dump of itself (when both its context and its stack are in flux),
+ // processing that stack wouldn't provide much useful data.
+ if (has_dump_thread && thread_id == dump_thread_id) {
+ continue;
+ }
+
+ MinidumpContext *context = thread->GetContext();
+
+ if (has_requesting_thread && thread_id == requesting_thread_id) {
+ if (found_requesting_thread) {
+ // There can't be more than one requesting thread.
+ BPLOG(ERROR) << "Duplicate requesting thread: " << thread_string;
+ return PROCESS_ERROR_DUPLICATE_REQUESTING_THREADS;
+ }
+
+ // Use processed_state->threads_.size() instead of thread_index.
+ // thread_index points to the thread index in the minidump, which
+ // might be greater than the thread index in the threads vector if
+ // any of the minidump's threads are skipped and not placed into the
+ // processed threads vector. The thread vector's current size will
+ // be the index of the current thread when it's pushed into the
+ // vector.
+ process_state->requesting_thread_ = process_state->threads_.size();
+
+ found_requesting_thread = true;
+
+ if (process_state->crashed_) {
+ // Use the exception record's context for the crashed thread, instead
+ // of the thread's own context. For the crashed thread, the thread's
+ // own context is the state inside the exception handler. Using it
+ // would not result in the expected stack trace from the time of the
+ // crash. If the exception context is invalid, however, we fall back
+ // on the thread context.
+ MinidumpContext *ctx = exception->GetContext();
+ context = ctx ? ctx : thread->GetContext();
+ }
+ }
+
+ // If the memory region for the stack cannot be read using the RVA stored
+ // in the memory descriptor inside MINIDUMP_THREAD, try to locate and use
+ // a memory region (containing the stack) from the minidump memory list.
+ MinidumpMemoryRegion *thread_memory = thread->GetMemory();
+ if (!thread_memory && memory_list) {
+ uint64_t start_stack_memory_range = thread->GetStartOfStackMemoryRange();
+ if (start_stack_memory_range) {
+ thread_memory = memory_list->GetMemoryRegionForAddress(
+ start_stack_memory_range);
+ }
+ }
+ if (!thread_memory) {
+ BPLOG(ERROR) << "No memory region for " << thread_string;
+ }
+
+ // Use process_state->modules_ instead of module_list, because the
+ // |modules| argument will be used to populate the |module| fields in
+ // the returned StackFrame objects, which will be placed into the
+ // returned ProcessState object. module_list's lifetime is only as
+ // long as the Minidump object: it will be deleted when this function
+ // returns. process_state->modules_ is owned by the ProcessState object
+ // (just like the StackFrame objects), and is much more suitable for this
+ // task.
+ scoped_ptr<Stackwalker> stackwalker(
+ Stackwalker::StackwalkerForCPU(process_state->system_info(),
+ context,
+ thread_memory,
+ process_state->modules_,
+ process_state->unloaded_modules_,
+ frame_symbolizer_));
+
+ scoped_ptr<CallStack> stack(new CallStack());
+ if (stackwalker.get()) {
+ if (!stackwalker->Walk(stack.get(),
+ &process_state->modules_without_symbols_,
+ &process_state->modules_with_corrupt_symbols_)) {
+ BPLOG(INFO) << "Stackwalker interrupt (missing symbols?) at "
+ << thread_string;
+ interrupted = true;
+ }
+ } else {
+ // Threads with missing CPU contexts will hit this, but
+ // don't abort processing the rest of the dump just for
+ // one bad thread.
+ BPLOG(ERROR) << "No stackwalker for " << thread_string;
+ }
+ stack->set_tid(thread_id);
+ stack->set_last_error(thread->GetLastError());
+ if (thread_names_list) {
+ stack->set_name(thread_names_list->GetNameForThreadId(thread_id));
+ }
+ process_state->threads_.push_back(stack.release());
+ process_state->thread_memory_regions_.push_back(thread_memory);
+ }
+
+ if (interrupted) {
+ BPLOG(INFO) << "Processing interrupted for " << dump->path();
+ return PROCESS_SYMBOL_SUPPLIER_INTERRUPTED;
+ }
+
+ // If a requesting thread was indicated, it must be present.
+ if (has_requesting_thread && !found_requesting_thread) {
+ // Don't mark as an error, but invalidate the requesting thread
+ BPLOG(ERROR) << "Minidump indicated requesting thread " <<
+ HexString(requesting_thread_id) << ", not found in " <<
+ dump->path();
+ process_state->requesting_thread_ = -1;
+ }
+
+ // Exploitability defaults to EXPLOITABILITY_NOT_ANALYZED
+ process_state->exploitability_ = EXPLOITABILITY_NOT_ANALYZED;
+
+ // If an exploitability run was requested we perform the platform specific
+ // rating.
+ if (enable_exploitability_) {
+ scoped_ptr<Exploitability> exploitability(
+ Exploitability::ExploitabilityForPlatform(dump,
+ process_state,
+ enable_objdump_));
+ // The engine will be null if the platform is not supported
+ if (exploitability != NULL) {
+ process_state->exploitability_ = exploitability->CheckExploitability();
+ } else {
+ process_state->exploitability_ = EXPLOITABILITY_ERR_NOENGINE;
+ }
+ }
+
+ BPLOG(INFO) << "Processed " << dump->path();
+ return PROCESS_OK;
+}
+
+ProcessResult MinidumpProcessor::Process(
+ const string &minidump_file, ProcessState *process_state) {
+ BPLOG(INFO) << "Processing minidump in file " << minidump_file;
+
+ Minidump dump(minidump_file);
+ if (!dump.Read()) {
+ BPLOG(ERROR) << "Minidump " << dump.path() << " could not be read";
+ return PROCESS_ERROR_MINIDUMP_NOT_FOUND;
+ }
+
+ return Process(&dump, process_state);
+}
+
+// Returns the MDRawSystemInfo from a minidump, or NULL if system info is
+// not available from the minidump. If system_info is non-NULL, it is used
+// to pass back the MinidumpSystemInfo object.
+static const MDRawSystemInfo* GetSystemInfo(Minidump *dump,
+ MinidumpSystemInfo **system_info) {
+ MinidumpSystemInfo *minidump_system_info = dump->GetSystemInfo();
+ if (!minidump_system_info)
+ return NULL;
+
+ if (system_info)
+ *system_info = minidump_system_info;
+
+ return minidump_system_info->system_info();
+}
+
+static uint64_t GetAddressForArchitecture(const MDCPUArchitecture architecture,
+ size_t raw_address)
+{
+ switch (architecture) {
+ case MD_CPU_ARCHITECTURE_X86:
+ case MD_CPU_ARCHITECTURE_MIPS:
+ case MD_CPU_ARCHITECTURE_PPC:
+ case MD_CPU_ARCHITECTURE_SHX:
+ case MD_CPU_ARCHITECTURE_ARM:
+ case MD_CPU_ARCHITECTURE_X86_WIN64:
+ // 32-bit architectures, mask the upper bits.
+ return raw_address & 0xffffffffULL;
+
+ default:
+ // All other architectures either have 64-bit pointers or it's impossible
+ // to tell from the minidump (e.g. MSIL or SPARC) so use 64-bits anyway.
+ return raw_address;
+ }
+}
+
+// Extract CPU info string from ARM-specific MDRawSystemInfo structure.
+// raw_info: pointer to source MDRawSystemInfo.
+// cpu_info: address of target string, cpu info text will be appended to it.
+static void GetARMCpuInfo(const MDRawSystemInfo* raw_info,
+ string* cpu_info) {
+ assert(raw_info != NULL && cpu_info != NULL);
+
+ // Write ARM architecture version.
+ char cpu_string[32];
+ snprintf(cpu_string, sizeof(cpu_string), "ARMv%d",
+ raw_info->processor_level);
+ cpu_info->append(cpu_string);
+
+ // There is no good list of implementer id values, but the following
+ // pages provide some help:
+ // http://comments.gmane.org/gmane.linux.linaro.devel/6903
+ // http://forum.xda-developers.com/archive/index.php/t-480226.html
+ const struct {
+ uint32_t id;
+ const char* name;
+ } vendors[] = {
+ { 0x41, "ARM" },
+ { 0x51, "Qualcomm" },
+ { 0x56, "Marvell" },
+ { 0x69, "Intel/Marvell" },
+ };
+ const struct {
+ uint32_t id;
+ const char* name;
+ } parts[] = {
+ { 0x4100c050, "Cortex-A5" },
+ { 0x4100c080, "Cortex-A8" },
+ { 0x4100c090, "Cortex-A9" },
+ { 0x4100c0f0, "Cortex-A15" },
+ { 0x4100c140, "Cortex-R4" },
+ { 0x4100c150, "Cortex-R5" },
+ { 0x4100b360, "ARM1136" },
+ { 0x4100b560, "ARM1156" },
+ { 0x4100b760, "ARM1176" },
+ { 0x4100b020, "ARM11-MPCore" },
+ { 0x41009260, "ARM926" },
+ { 0x41009460, "ARM946" },
+ { 0x41009660, "ARM966" },
+ { 0x510006f0, "Krait" },
+ { 0x510000f0, "Scorpion" },
+ };
+
+ const struct {
+ uint32_t hwcap;
+ const char* name;
+ } features[] = {
+ { MD_CPU_ARM_ELF_HWCAP_SWP, "swp" },
+ { MD_CPU_ARM_ELF_HWCAP_HALF, "half" },
+ { MD_CPU_ARM_ELF_HWCAP_THUMB, "thumb" },
+ { MD_CPU_ARM_ELF_HWCAP_26BIT, "26bit" },
+ { MD_CPU_ARM_ELF_HWCAP_FAST_MULT, "fastmult" },
+ { MD_CPU_ARM_ELF_HWCAP_FPA, "fpa" },
+ { MD_CPU_ARM_ELF_HWCAP_VFP, "vfpv2" },
+ { MD_CPU_ARM_ELF_HWCAP_EDSP, "edsp" },
+ { MD_CPU_ARM_ELF_HWCAP_JAVA, "java" },
+ { MD_CPU_ARM_ELF_HWCAP_IWMMXT, "iwmmxt" },
+ { MD_CPU_ARM_ELF_HWCAP_CRUNCH, "crunch" },
+ { MD_CPU_ARM_ELF_HWCAP_THUMBEE, "thumbee" },
+ { MD_CPU_ARM_ELF_HWCAP_NEON, "neon" },
+ { MD_CPU_ARM_ELF_HWCAP_VFPv3, "vfpv3" },
+ { MD_CPU_ARM_ELF_HWCAP_VFPv3D16, "vfpv3d16" },
+ { MD_CPU_ARM_ELF_HWCAP_TLS, "tls" },
+ { MD_CPU_ARM_ELF_HWCAP_VFPv4, "vfpv4" },
+ { MD_CPU_ARM_ELF_HWCAP_IDIVA, "idiva" },
+ { MD_CPU_ARM_ELF_HWCAP_IDIVT, "idivt" },
+ };
+
+ uint32_t cpuid = raw_info->cpu.arm_cpu_info.cpuid;
+ if (cpuid != 0) {
+ // Extract vendor name from CPUID
+ const char* vendor = NULL;
+ uint32_t vendor_id = (cpuid >> 24) & 0xff;
+ for (size_t i = 0; i < sizeof(vendors)/sizeof(vendors[0]); ++i) {
+ if (vendors[i].id == vendor_id) {
+ vendor = vendors[i].name;
+ break;
+ }
+ }
+ cpu_info->append(" ");
+ if (vendor) {
+ cpu_info->append(vendor);
+ } else {
+ snprintf(cpu_string, sizeof(cpu_string), "vendor(0x%x)", vendor_id);
+ cpu_info->append(cpu_string);
+ }
+
+ // Extract part name from CPUID
+ uint32_t part_id = (cpuid & 0xff00fff0);
+ const char* part = NULL;
+ for (size_t i = 0; i < sizeof(parts)/sizeof(parts[0]); ++i) {
+ if (parts[i].id == part_id) {
+ part = parts[i].name;
+ break;
+ }
+ }
+ cpu_info->append(" ");
+ if (part != NULL) {
+ cpu_info->append(part);
+ } else {
+ snprintf(cpu_string, sizeof(cpu_string), "part(0x%x)", part_id);
+ cpu_info->append(cpu_string);
+ }
+ }
+ uint32_t elf_hwcaps = raw_info->cpu.arm_cpu_info.elf_hwcaps;
+ if (elf_hwcaps != 0) {
+ cpu_info->append(" features: ");
+ const char* comma = "";
+ for (size_t i = 0; i < sizeof(features)/sizeof(features[0]); ++i) {
+ if (elf_hwcaps & features[i].hwcap) {
+ cpu_info->append(comma);
+ cpu_info->append(features[i].name);
+ comma = ",";
+ }
+ }
+ }
+}
+
+// static
+bool MinidumpProcessor::GetCPUInfo(Minidump *dump, SystemInfo *info) {
+ assert(dump);
+ assert(info);
+
+ info->cpu.clear();
+ info->cpu_info.clear();
+
+ MinidumpSystemInfo *system_info;
+ const MDRawSystemInfo *raw_system_info = GetSystemInfo(dump, &system_info);
+ if (!raw_system_info)
+ return false;
+
+ switch (raw_system_info->processor_architecture) {
+ case MD_CPU_ARCHITECTURE_X86:
+ case MD_CPU_ARCHITECTURE_AMD64: {
+ if (raw_system_info->processor_architecture ==
+ MD_CPU_ARCHITECTURE_X86)
+ info->cpu = "x86";
+ else
+ info->cpu = "amd64";
+
+ const string *cpu_vendor = system_info->GetCPUVendor();
+ if (cpu_vendor) {
+ info->cpu_info = *cpu_vendor;
+ info->cpu_info.append(" ");
+ }
+
+ char x86_info[36];
+ snprintf(x86_info, sizeof(x86_info), "family %u model %u stepping %u",
+ raw_system_info->processor_level,
+ raw_system_info->processor_revision >> 8,
+ raw_system_info->processor_revision & 0xff);
+ info->cpu_info.append(x86_info);
+ break;
+ }
+
+ case MD_CPU_ARCHITECTURE_PPC: {
+ info->cpu = "ppc";
+ break;
+ }
+
+ case MD_CPU_ARCHITECTURE_PPC64: {
+ info->cpu = "ppc64";
+ break;
+ }
+
+ case MD_CPU_ARCHITECTURE_SPARC: {
+ info->cpu = "sparc";
+ break;
+ }
+
+ case MD_CPU_ARCHITECTURE_ARM: {
+ info->cpu = "arm";
+ GetARMCpuInfo(raw_system_info, &info->cpu_info);
+ break;
+ }
+
+ case MD_CPU_ARCHITECTURE_ARM64:
+ case MD_CPU_ARCHITECTURE_ARM64_OLD: {
+ info->cpu = "arm64";
+ break;
+ }
+
+ case MD_CPU_ARCHITECTURE_MIPS: {
+ info->cpu = "mips";
+ break;
+ }
+ case MD_CPU_ARCHITECTURE_MIPS64: {
+ info->cpu = "mips64";
+ break;
+ }
+
+ default: {
+ // Assign the numeric architecture ID into the CPU string.
+ char cpu_string[7];
+ snprintf(cpu_string, sizeof(cpu_string), "0x%04x",
+ raw_system_info->processor_architecture);
+ info->cpu = cpu_string;
+ break;
+ }
+ }
+
+ info->cpu_count = raw_system_info->number_of_processors;
+
+ return true;
+}
+
+// static
+bool MinidumpProcessor::GetOSInfo(Minidump *dump, SystemInfo *info) {
+ assert(dump);
+ assert(info);
+
+ info->os.clear();
+ info->os_short.clear();
+ info->os_version.clear();
+
+ MinidumpSystemInfo *system_info;
+ const MDRawSystemInfo *raw_system_info = GetSystemInfo(dump, &system_info);
+ if (!raw_system_info)
+ return false;
+
+ info->os_short = system_info->GetOS();
+
+ switch (raw_system_info->platform_id) {
+ case MD_OS_WIN32_NT: {
+ info->os = "Windows NT";
+ break;
+ }
+
+ case MD_OS_WIN32_WINDOWS: {
+ info->os = "Windows";
+ break;
+ }
+
+ case MD_OS_MAC_OS_X: {
+ info->os = "Mac OS X";
+ break;
+ }
+
+ case MD_OS_IOS: {
+ info->os = "iOS";
+ break;
+ }
+
+ case MD_OS_LINUX: {
+ info->os = "Linux";
+ break;
+ }
+
+ case MD_OS_SOLARIS: {
+ info->os = "Solaris";
+ break;
+ }
+
+ case MD_OS_ANDROID: {
+ info->os = "Android";
+ break;
+ }
+
+ case MD_OS_PS3: {
+ info->os = "PS3";
+ break;
+ }
+
+ case MD_OS_NACL: {
+ info->os = "NaCl";
+ break;
+ }
+
+ case MD_OS_FUCHSIA: {
+ info->os = "Fuchsia";
+ break;
+ }
+
+ default: {
+ // Assign the numeric platform ID into the OS string.
+ char os_string[11];
+ snprintf(os_string, sizeof(os_string), "0x%08x",
+ raw_system_info->platform_id);
+ info->os = os_string;
+ break;
+ }
+ }
+
+ char os_version_string[33];
+ snprintf(os_version_string, sizeof(os_version_string), "%u.%u.%u",
+ raw_system_info->major_version,
+ raw_system_info->minor_version,
+ raw_system_info->build_number);
+ info->os_version = os_version_string;
+
+ const string *csd_version = system_info->GetCSDVersion();
+ if (csd_version) {
+ info->os_version.append(" ");
+ info->os_version.append(*csd_version);
+ }
+
+ return true;
+}
+
+// static
+bool MinidumpProcessor::GetProcessCreateTime(Minidump* dump,
+ uint32_t* process_create_time) {
+ assert(dump);
+ assert(process_create_time);
+
+ *process_create_time = 0;
+
+ MinidumpMiscInfo* minidump_misc_info = dump->GetMiscInfo();
+ if (!minidump_misc_info) {
+ return false;
+ }
+
+ const MDRawMiscInfo* md_raw_misc_info = minidump_misc_info->misc_info();
+ if (!md_raw_misc_info) {
+ return false;
+ }
+
+ if (!(md_raw_misc_info->flags1 & MD_MISCINFO_FLAGS1_PROCESS_TIMES)) {
+ return false;
+ }
+
+ *process_create_time = md_raw_misc_info->process_create_time;
+ return true;
+}
+
+// static
+string MinidumpProcessor::GetCrashReason(Minidump *dump, uint64_t *address) {
+ MinidumpException *exception = dump->GetException();
+ if (!exception)
+ return "";
+
+ const MDRawExceptionStream *raw_exception = exception->exception();
+ if (!raw_exception)
+ return "";
+
+ if (address)
+ *address = raw_exception->exception_record.exception_address;
+
+ // The reason value is OS-specific and possibly CPU-specific. Set up
+ // sensible numeric defaults for the reason string in case we can't
+ // map the codes to a string (because there's no system info, or because
+ // it's an unrecognized platform, or because it's an unrecognized code.)
+ char reason_string[24];
+ char flags_string[11];
+ uint32_t exception_code = raw_exception->exception_record.exception_code;
+ uint32_t exception_flags = raw_exception->exception_record.exception_flags;
+ snprintf(flags_string, sizeof(flags_string), "0x%08x", exception_flags);
+ snprintf(reason_string, sizeof(reason_string), "0x%08x / %s", exception_code,
+ flags_string);
+ string reason = reason_string;
+
+ const MDRawSystemInfo *raw_system_info = GetSystemInfo(dump, NULL);
+ if (!raw_system_info)
+ return reason;
+
+ switch (raw_system_info->platform_id) {
+ case MD_OS_FUCHSIA: {
+ switch (exception_code) {
+ case MD_EXCEPTION_CODE_FUCHSIA_GENERAL:
+ reason = "GENERAL / ";
+ reason.append(flags_string);
+ break;
+ case MD_EXCEPTION_CODE_FUCHSIA_FATAL_PAGE_FAULT:
+ reason = "FATAL_PAGE_FAULT / ";
+ reason.append(flags_string);
+ break;
+ case MD_EXCEPTION_CODE_FUCHSIA_UNDEFINED_INSTRUCTION:
+ reason = "UNDEFINED_INSTRUCTION / ";
+ reason.append(flags_string);
+ break;
+ case MD_EXCEPTION_CODE_FUCHSIA_SW_BREAKPOINT:
+ reason = "SW_BREAKPOINT / ";
+ reason.append(flags_string);
+ break;
+ case MD_EXCEPTION_CODE_FUCHSIA_HW_BREAKPOINT:
+ reason = "HW_BREAKPOINT / ";
+ reason.append(flags_string);
+ break;
+ case MD_EXCEPTION_CODE_FUCHSIA_UNALIGNED_ACCESS:
+ reason = "UNALIGNED_ACCESS / ";
+ reason.append(flags_string);
+ break;
+ case MD_EXCEPTION_CODE_FUCHSIA_THREAD_STARTING:
+ reason = "THREAD_STARTING / ";
+ reason.append(flags_string);
+ break;
+ case MD_EXCEPTION_CODE_FUCHSIA_THREAD_EXITING:
+ reason = "THREAD_EXITING / ";
+ reason.append(flags_string);
+ break;
+ case MD_EXCEPTION_CODE_FUCHSIA_POLICY_ERROR:
+ reason = "POLICY_ERROR / ";
+ reason.append(flags_string);
+ break;
+ case MD_EXCEPTION_CODE_FUCHSIA_PROCESS_STARTING:
+ reason = "PROCESS_STARTING / ";
+ reason.append(flags_string);
+ break;
+ default:
+ BPLOG(INFO) << "Unknown exception reason " << reason;
+ }
+ break;
+ }
+
+ case MD_OS_MAC_OS_X:
+ case MD_OS_IOS: {
+ switch (exception_code) {
+ case MD_EXCEPTION_MAC_BAD_ACCESS:
+ reason = "EXC_BAD_ACCESS / ";
+ switch (exception_flags) {
+ case MD_EXCEPTION_CODE_MAC_INVALID_ADDRESS:
+ reason.append("KERN_INVALID_ADDRESS");
+ break;
+ case MD_EXCEPTION_CODE_MAC_PROTECTION_FAILURE:
+ reason.append("KERN_PROTECTION_FAILURE");
+ break;
+ case MD_EXCEPTION_CODE_MAC_NO_ACCESS:
+ reason.append("KERN_NO_ACCESS");
+ break;
+ case MD_EXCEPTION_CODE_MAC_MEMORY_FAILURE:
+ reason.append("KERN_MEMORY_FAILURE");
+ break;
+ case MD_EXCEPTION_CODE_MAC_MEMORY_ERROR:
+ reason.append("KERN_MEMORY_ERROR");
+ break;
+ case MD_EXCEPTION_CODE_MAC_CODESIGN_ERROR:
+ reason.append("KERN_CODESIGN_ERROR");
+ break;
+ default:
+ // arm and ppc overlap
+ if (raw_system_info->processor_architecture ==
+ MD_CPU_ARCHITECTURE_ARM ||
+ raw_system_info->processor_architecture ==
+ MD_CPU_ARCHITECTURE_ARM64_OLD) {
+ switch (exception_flags) {
+ case MD_EXCEPTION_CODE_MAC_ARM_DA_ALIGN:
+ reason.append("EXC_ARM_DA_ALIGN");
+ break;
+ case MD_EXCEPTION_CODE_MAC_ARM_DA_DEBUG:
+ reason.append("EXC_ARM_DA_DEBUG");
+ break;
+ default:
+ reason.append(flags_string);
+ BPLOG(INFO) << "Unknown exception reason " << reason;
+ break;
+ }
+ } else if (raw_system_info->processor_architecture ==
+ MD_CPU_ARCHITECTURE_PPC) {
+ switch (exception_flags) {
+ case MD_EXCEPTION_CODE_MAC_PPC_VM_PROT_READ:
+ reason.append("EXC_PPC_VM_PROT_READ");
+ break;
+ case MD_EXCEPTION_CODE_MAC_PPC_BADSPACE:
+ reason.append("EXC_PPC_BADSPACE");
+ break;
+ case MD_EXCEPTION_CODE_MAC_PPC_UNALIGNED:
+ reason.append("EXC_PPC_UNALIGNED");
+ break;
+ default:
+ reason.append(flags_string);
+ BPLOG(INFO) << "Unknown exception reason " << reason;
+ break;
+ }
+ } else if (raw_system_info->processor_architecture ==
+ MD_CPU_ARCHITECTURE_X86 ||
+ raw_system_info->processor_architecture ==
+ MD_CPU_ARCHITECTURE_AMD64) {
+ switch (exception_flags) {
+ case MD_EXCEPTION_CODE_MAC_X86_GENERAL_PROTECTION_FAULT:
+ reason.append("EXC_I386_GPFLT");
+ break;
+ default:
+ reason.append(flags_string);
+ BPLOG(INFO) << "Unknown exception reason " << reason;
+ break;
+ }
+ } else {
+ reason.append(flags_string);
+ BPLOG(INFO) << "Unknown exception reason " << reason;
+ }
+ break;
+ }
+ break;
+ case MD_EXCEPTION_MAC_BAD_INSTRUCTION:
+ reason = "EXC_BAD_INSTRUCTION / ";
+ switch (raw_system_info->processor_architecture) {
+ case MD_CPU_ARCHITECTURE_ARM:
+ case MD_CPU_ARCHITECTURE_ARM64_OLD: {
+ switch (exception_flags) {
+ case MD_EXCEPTION_CODE_MAC_ARM_UNDEFINED:
+ reason.append("EXC_ARM_UNDEFINED");
+ break;
+ default:
+ reason.append(flags_string);
+ BPLOG(INFO) << "Unknown exception reason " << reason;
+ break;
+ }
+ break;
+ }
+ case MD_CPU_ARCHITECTURE_PPC: {
+ switch (exception_flags) {
+ case MD_EXCEPTION_CODE_MAC_PPC_INVALID_SYSCALL:
+ reason.append("EXC_PPC_INVALID_SYSCALL");
+ break;
+ case MD_EXCEPTION_CODE_MAC_PPC_UNIMPLEMENTED_INSTRUCTION:
+ reason.append("EXC_PPC_UNIPL_INST");
+ break;
+ case MD_EXCEPTION_CODE_MAC_PPC_PRIVILEGED_INSTRUCTION:
+ reason.append("EXC_PPC_PRIVINST");
+ break;
+ case MD_EXCEPTION_CODE_MAC_PPC_PRIVILEGED_REGISTER:
+ reason.append("EXC_PPC_PRIVREG");
+ break;
+ case MD_EXCEPTION_CODE_MAC_PPC_TRACE:
+ reason.append("EXC_PPC_TRACE");
+ break;
+ case MD_EXCEPTION_CODE_MAC_PPC_PERFORMANCE_MONITOR:
+ reason.append("EXC_PPC_PERFMON");
+ break;
+ default:
+ reason.append(flags_string);
+ BPLOG(INFO) << "Unknown exception reason " << reason;
+ break;
+ }
+ break;
+ }
+ case MD_CPU_ARCHITECTURE_AMD64:
+ case MD_CPU_ARCHITECTURE_X86: {
+ switch (exception_flags) {
+ case MD_EXCEPTION_CODE_MAC_X86_INVALID_OPERATION:
+ reason.append("EXC_I386_INVOP");
+ break;
+ case MD_EXCEPTION_CODE_MAC_X86_INVALID_TASK_STATE_SEGMENT:
+ reason.append("EXC_I386_INVTSSFLT");
+ break;
+ case MD_EXCEPTION_CODE_MAC_X86_SEGMENT_NOT_PRESENT:
+ reason.append("EXC_I386_SEGNPFLT");
+ break;
+ case MD_EXCEPTION_CODE_MAC_X86_STACK_FAULT:
+ reason.append("EXC_I386_STKFLT");
+ break;
+ case MD_EXCEPTION_CODE_MAC_X86_GENERAL_PROTECTION_FAULT:
+ reason.append("EXC_I386_GPFLT");
+ break;
+ case MD_EXCEPTION_CODE_MAC_X86_ALIGNMENT_FAULT:
+ reason.append("EXC_I386_ALIGNFLT");
+ break;
+ default:
+ reason.append(flags_string);
+ BPLOG(INFO) << "Unknown exception reason " << reason;
+ break;
+ }
+ break;
+ }
+ default:
+ reason.append(flags_string);
+ BPLOG(INFO) << "Unknown exception reason " << reason;
+ break;
+ }
+ break;
+ case MD_EXCEPTION_MAC_ARITHMETIC:
+ reason = "EXC_ARITHMETIC / ";
+ switch (raw_system_info->processor_architecture) {
+ case MD_CPU_ARCHITECTURE_PPC: {
+ switch (exception_flags) {
+ case MD_EXCEPTION_CODE_MAC_PPC_OVERFLOW:
+ reason.append("EXC_PPC_OVERFLOW");
+ break;
+ case MD_EXCEPTION_CODE_MAC_PPC_ZERO_DIVIDE:
+ reason.append("EXC_PPC_ZERO_DIVIDE");
+ break;
+ case MD_EXCEPTION_CODE_MAC_PPC_FLOAT_INEXACT:
+ reason.append("EXC_FLT_INEXACT");
+ break;
+ case MD_EXCEPTION_CODE_MAC_PPC_FLOAT_ZERO_DIVIDE:
+ reason.append("EXC_PPC_FLT_ZERO_DIVIDE");
+ break;
+ case MD_EXCEPTION_CODE_MAC_PPC_FLOAT_UNDERFLOW:
+ reason.append("EXC_PPC_FLT_UNDERFLOW");
+ break;
+ case MD_EXCEPTION_CODE_MAC_PPC_FLOAT_OVERFLOW:
+ reason.append("EXC_PPC_FLT_OVERFLOW");
+ break;
+ case MD_EXCEPTION_CODE_MAC_PPC_FLOAT_NOT_A_NUMBER:
+ reason.append("EXC_PPC_FLT_NOT_A_NUMBER");
+ break;
+ case MD_EXCEPTION_CODE_MAC_PPC_NO_EMULATION:
+ reason.append("EXC_PPC_NOEMULATION");
+ break;
+ case MD_EXCEPTION_CODE_MAC_PPC_ALTIVEC_ASSIST:
+ reason.append("EXC_PPC_ALTIVECASSIST");
+ break;
+ default:
+ reason.append(flags_string);
+ BPLOG(INFO) << "Unknown exception reason " << reason;
+ break;
+ }
+ break;
+ }
+ case MD_CPU_ARCHITECTURE_AMD64:
+ case MD_CPU_ARCHITECTURE_X86: {
+ switch (exception_flags) {
+ case MD_EXCEPTION_CODE_MAC_X86_DIV:
+ reason.append("EXC_I386_DIV");
+ break;
+ case MD_EXCEPTION_CODE_MAC_X86_INTO:
+ reason.append("EXC_I386_INTO");
+ break;
+ case MD_EXCEPTION_CODE_MAC_X86_NOEXT:
+ reason.append("EXC_I386_NOEXT");
+ break;
+ case MD_EXCEPTION_CODE_MAC_X86_EXTOVR:
+ reason.append("EXC_I386_EXTOVR");
+ break;
+ case MD_EXCEPTION_CODE_MAC_X86_EXTERR:
+ reason.append("EXC_I386_EXTERR");
+ break;
+ case MD_EXCEPTION_CODE_MAC_X86_EMERR:
+ reason.append("EXC_I386_EMERR");
+ break;
+ case MD_EXCEPTION_CODE_MAC_X86_BOUND:
+ reason.append("EXC_I386_BOUND");
+ break;
+ case MD_EXCEPTION_CODE_MAC_X86_SSEEXTERR:
+ reason.append("EXC_I386_SSEEXTERR");
+ break;
+ default:
+ reason.append(flags_string);
+ BPLOG(INFO) << "Unknown exception reason " << reason;
+ break;
+ }
+ break;
+ }
+ default:
+ reason.append(flags_string);
+ BPLOG(INFO) << "Unknown exception reason " << reason;
+ break;
+ }
+ break;
+ case MD_EXCEPTION_MAC_EMULATION:
+ reason = "EXC_EMULATION / ";
+ reason.append(flags_string);
+ break;
+ case MD_EXCEPTION_MAC_SOFTWARE:
+ reason = "EXC_SOFTWARE / ";
+ switch (exception_flags) {
+ case MD_EXCEPTION_CODE_MAC_ABORT:
+ reason.append("SIGABRT");
+ break;
+ case MD_EXCEPTION_CODE_MAC_NS_EXCEPTION:
+ reason.append("UNCAUGHT_NS_EXCEPTION");
+ break;
+ // These are ppc only but shouldn't be a problem as they're
+ // unused on x86
+ case MD_EXCEPTION_CODE_MAC_PPC_TRAP:
+ reason.append("EXC_PPC_TRAP");
+ break;
+ case MD_EXCEPTION_CODE_MAC_PPC_MIGRATE:
+ reason.append("EXC_PPC_MIGRATE");
+ break;
+ default:
+ reason.append(flags_string);
+ BPLOG(INFO) << "Unknown exception reason " << reason;
+ break;
+ }
+ break;
+ case MD_EXCEPTION_MAC_BREAKPOINT:
+ reason = "EXC_BREAKPOINT / ";
+ switch (raw_system_info->processor_architecture) {
+ case MD_CPU_ARCHITECTURE_ARM:
+ case MD_CPU_ARCHITECTURE_ARM64_OLD: {
+ switch (exception_flags) {
+ case MD_EXCEPTION_CODE_MAC_ARM_DA_ALIGN:
+ reason.append("EXC_ARM_DA_ALIGN");
+ break;
+ case MD_EXCEPTION_CODE_MAC_ARM_DA_DEBUG:
+ reason.append("EXC_ARM_DA_DEBUG");
+ break;
+ case MD_EXCEPTION_CODE_MAC_ARM_BREAKPOINT:
+ reason.append("EXC_ARM_BREAKPOINT");
+ break;
+ default:
+ reason.append(flags_string);
+ BPLOG(INFO) << "Unknown exception reason " << reason;
+ break;
+ }
+ break;
+ }
+ case MD_CPU_ARCHITECTURE_PPC: {
+ switch (exception_flags) {
+ case MD_EXCEPTION_CODE_MAC_PPC_BREAKPOINT:
+ reason.append("EXC_PPC_BREAKPOINT");
+ break;
+ default:
+ reason.append(flags_string);
+ BPLOG(INFO) << "Unknown exception reason " << reason;
+ break;
+ }
+ break;
+ }
+ case MD_CPU_ARCHITECTURE_AMD64:
+ case MD_CPU_ARCHITECTURE_X86: {
+ switch (exception_flags) {
+ case MD_EXCEPTION_CODE_MAC_X86_SGL:
+ reason.append("EXC_I386_SGL");
+ break;
+ case MD_EXCEPTION_CODE_MAC_X86_BPT:
+ reason.append("EXC_I386_BPT");
+ break;
+ default:
+ reason.append(flags_string);
+ BPLOG(INFO) << "Unknown exception reason " << reason;
+ break;
+ }
+ break;
+ }
+ default:
+ reason.append(flags_string);
+ BPLOG(INFO) << "Unknown exception reason " << reason;
+ break;
+ }
+ break;
+ case MD_EXCEPTION_MAC_SYSCALL:
+ reason = "EXC_SYSCALL / ";
+ reason.append(flags_string);
+ break;
+ case MD_EXCEPTION_MAC_MACH_SYSCALL:
+ reason = "EXC_MACH_SYSCALL / ";
+ reason.append(flags_string);
+ break;
+ case MD_EXCEPTION_MAC_RPC_ALERT:
+ reason = "EXC_RPC_ALERT / ";
+ reason.append(flags_string);
+ break;
+ case MD_EXCEPTION_MAC_RESOURCE:
+ reason = "EXC_RESOURCE / ";
+ {
+ uint32_t type = (exception_flags >> 29) & 0x7ULL;
+ uint32_t flavor = (exception_flags >> 26) & 0x7ULL;
+ char flavor_string[6] = {};
+ switch (type) {
+ case MD_MAC_EXC_RESOURCE_TYPE_CPU:
+ reason.append("RESOURCE_TYPE_CPU / ");
+ switch (flavor) {
+ case MD_MAC_EXC_RESOURCE_FLAVOR_CPU_MONITOR:
+ reason.append("FLAVOR_CPU_MONITOR");
+ break;
+ case MD_MAC_EXC_RESOURCE_FLAVOR_CPU_MONITOR_FATAL:
+ reason.append("FLAVOR_CPU_MONITOR_FATAL");
+ break;
+ default:
+ snprintf(flavor_string, sizeof(flavor_string), "%#3x", flavor);
+ reason.append(flavor_string);
+ break;
+ }
+ break;
+ case MD_MAC_EXC_RESOURCE_TYPE_WAKEUPS:
+ reason.append("RESOURCE_TYPE_WAKEUPS / ");
+ if (flavor == MD_MAC_EXC_RESOURCE_FLAVOR_WAKEUPS_MONITOR) {
+ reason.append("FLAVOR_WAKEUPS_MONITOR");
+ } else {
+ snprintf(flavor_string, sizeof(flavor_string), "%#3x", flavor);
+ reason.append(flavor_string);
+ }
+ break;
+ case MD_MAC_EXC_RESOURCE_TYPE_MEMORY:
+ reason.append("RESOURCE_TYPE_MEMORY / ");
+ if (flavor == MD_MAC_EXC_RESOURCE_FLAVOR_HIGH_WATERMARK) {
+ reason.append("FLAVOR_HIGH_WATERMARK");
+ } else {
+ snprintf(flavor_string, sizeof(flavor_string), "%#3x", flavor);
+ reason.append(flavor_string);
+ }
+ break;
+ case MD_MAC_EXC_RESOURCE_TYPE_IO:
+ reason.append("EXC_RESOURCE_TYPE_IO / ");
+ switch (flavor) {
+ case MD_MAC_EXC_RESOURCE_FLAVOR_IO_PHYSICAL_WRITES:
+ reason.append("FLAVOR_IO_PHYSICAL_WRITES");
+ break;
+ case MD_MAC_EXC_RESOURCE_FLAVOR_IO_LOGICAL_WRITES:
+ reason.append("FLAVOR_IO_LOGICAL_WRITES");
+ break;
+ default:
+ snprintf(flavor_string, sizeof(flavor_string), "%#3x", flavor);
+ reason.append(flavor_string);
+ break;
+ }
+ break;
+ case MD_MAC_EXC_RESOURCE_TYPE_THREADS:
+ reason.append("EXC_RESOURCE_TYPE_THREADS / ");
+ if (flavor == MD_MAC_EXC_RESOURCE_FLAVOR_THREADS_HIGH_WATERMARK) {
+ reason.append("FLAVOR_THREADS_HIGH_WATERMARK");
+ } else {
+ snprintf(flavor_string, sizeof(flavor_string), "%#3x", flavor);
+ reason.append(flavor_string);
+ }
+ break;
+ default:
+ reason.append(flags_string);
+ break;
+ }
+ }
+ break;
+ case MD_EXCEPTION_MAC_GUARD:
+ reason = "EXC_GUARD / ";
+ {
+ uint32_t type = (exception_flags >> 29) & 0x7ULL;
+ uint32_t flavor = exception_flags & 0x1FFFFFFFULL;
+ switch (type) {
+ case MD_MAC_EXC_GUARD_TYPE_NONE:
+ reason.append("GUARD_TYPE_NONE");
+ break;
+ case MD_MAC_EXC_GUARD_TYPE_MACH_PORT:
+ reason.append("GUARD_TYPE_MACH_PORT");
+
+ if (flavor) {
+ std::vector<std::string> flavors;
+
+ if (flavor & MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_DESTROY) {
+ flavors.push_back("GUARD_EXC_DESTROY");
+ }
+
+ if (flavor & MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_MOD_REFS) {
+ flavors.push_back("GUARD_EXC_MOD_REFS");
+ }
+
+ if (flavor & MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_SET_CONTEXT) {
+ flavors.push_back("GUARD_EXC_SET_CONTEXT");
+ }
+
+ if (flavor & MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_SET_CONTEXT) {
+ flavors.push_back("GUARD_EXC_SET_CONTEXT");
+ }
+
+ if (flavor & MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_UNGUARDED) {
+ flavors.push_back("GUARD_EXC_UNGUARDED");
+ }
+
+ if (flavor & MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_INCORRECT_GUARD) {
+ flavors.push_back("GUARD_EXC_INCORRECT_GUARD");
+ }
+
+ if (flavor & MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_IMMOVABLE) {
+ flavors.push_back("GUARD_EXC_IMMOVABLE");
+ }
+
+ if (flavor & MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_STRICT_REPLY) {
+ flavors.push_back("GUARD_EXC_STRICT_REPLY");
+ }
+
+ if (flavor & MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_MSG_FILTERED) {
+ flavors.push_back("GUARD_EXC_MSG_FILTERED");
+ }
+
+ if (flavor & MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_INVALID_RIGHT) {
+ flavors.push_back("GUARD_EXC_INVALID_RIGHT");
+ }
+
+ if (flavor & MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_INVALID_NAME) {
+ flavors.push_back("GUARD_EXC_INVALID_NAME");
+ }
+
+ if (flavor & MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_INVALID_VALUE) {
+ flavors.push_back("GUARD_EXC_INVALID_VALUE");
+ }
+
+ if (flavor & MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_INVALID_ARGUMENT) {
+ flavors.push_back("GUARD_EXC_INVALID_ARGUMENT");
+ }
+
+ if (flavor & MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_RIGHT_EXISTS) {
+ flavors.push_back("GUARD_EXC_RIGHT_EXISTS");
+ }
+
+ if (flavor & MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_KERN_NO_SPACE) {
+ flavors.push_back("GUARD_EXC_KERN_NO_SPACE");
+ }
+
+ if (flavor & MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_KERN_FAILURE) {
+ flavors.push_back("GUARD_EXC_KERN_FAILURE");
+ }
+
+ if (flavor & MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_KERN_RESOURCE) {
+ flavors.push_back("GUARD_EXC_KERN_RESOURCE");
+ }
+
+ if (flavor & MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_SEND_INVALID_REPLY) {
+ flavors.push_back("GUARD_EXC_SEND_INVALID_REPLY");
+ }
+
+ if (flavor & MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_SEND_INVALID_VOUCHER) {
+ flavors.push_back("GUARD_EXC_SEND_INVALID_VOUCHER");
+ }
+
+ if (flavor & MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_SEND_INVALID_RIGHT) {
+ flavors.push_back("GUARD_EXC_SEND_INVALID_RIGHT");
+ }
+
+ if (flavor & MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_RCV_INVALID_NAME) {
+ flavors.push_back("GUARD_EXC_RCV_INVALID_NAME");
+ }
+
+ if (flavor & MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_RCV_GUARDED_DESC) {
+ flavors.push_back("GUARD_EXC_RCV_GUARDED_DESC");
+ }
+
+ if (flavor & MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_MOD_REFS_NON_FATAL) {
+ flavors.push_back("GUARD_EXC_MOD_REFS_NON_FATAL");
+ }
+
+ if (flavor & MD_MAC_EXC_GUARD_MACH_PORT_FLAVOR_GUARD_EXC_IMMOVABLE_NON_FATAL) {
+ flavors.push_back("GUARD_EXC_IMMOVABLE_NON_FATAL");
+ }
+
+ reason.append(" / ");
+ for (size_t i = 0; i < flavors.size(); i++) {
+ if (i > 0) {
+ reason.append(" | ");
+ }
+
+ reason.append(flavors[i]);
+ }
+ }
+
+ break;
+ case MD_MAC_EXC_GUARD_TYPE_FD:
+ reason.append("GUARD_TYPE_FD");
+
+ if (flavor) {
+ std::vector<std::string> flavors;
+
+ if (flavor & MD_MAC_EXC_GUARD_FD_FLAVOR_GUARD_EXC_CLOSE) {
+ flavors.push_back("GUARD_EXC_CLOSE");
+ }
+
+ if (flavor & MD_MAC_EXC_GUARD_FD_FLAVOR_GUARD_EXC_DUP) {
+ flavors.push_back("GUARD_EXC_DUP");
+ }
+
+ if (flavor & MD_MAC_EXC_GUARD_FD_FLAVOR_GUARD_EXC_NOCLOEXEC) {
+ flavors.push_back("GUARD_EXC_NOCLOEXEC");
+ }
+
+ if (flavor & MD_MAC_EXC_GUARD_FD_FLAVOR_GUARD_EXC_SOCKET_IPC) {
+ flavors.push_back("GUARD_EXC_SOCKET_IPC");
+ }
+
+ if (flavor & MD_MAC_EXC_GUARD_FD_FLAVOR_GUARD_EXC_FILEPORT) {
+ flavors.push_back("GUARD_EXC_FILEPORT");
+ }
+
+ if (flavor & MD_MAC_EXC_GUARD_FD_FLAVOR_GUARD_EXC_MISMATCH) {
+ flavors.push_back("GUARD_EXC_MISMATCH");
+ }
+
+ if (flavor & MD_MAC_EXC_GUARD_FD_FLAVOR_GUARD_EXC_WRITE) {
+ flavors.push_back("GUARD_EXC_WRITE");
+ }
+
+ reason.append(" / ");
+ for (size_t i = 0; i < flavors.size(); i++) {
+ if (i > 0) {
+ reason.append(" | ");
+ }
+
+ reason.append(flavors[i]);
+ }
+ }
+
+ break;
+ case MD_MAC_EXC_GUARD_TYPE_USER:
+ reason.append("GUARD_TYPE_USER");
+ break;
+ case MD_MAC_EXC_GUARD_TYPE_VN:
+ reason.append("GUARD_TYPE_VN");
+
+ if (flavor) {
+ std::vector<std::string> flavors;
+
+ if (flavor & MD_MAC_EXC_GUARD_FD_FLAVOR_GUARD_EXC_RENAME_TO) {
+ flavors.push_back("GUARD_EXC_RENAME_TO");
+ }
+
+ if (flavor & MD_MAC_EXC_GUARD_FD_FLAVOR_GUARD_EXC_RENAME_FROM) {
+ flavors.push_back("GUARD_EXC_RENAME_FROM");
+ }
+
+ if (flavor & MD_MAC_EXC_GUARD_FD_FLAVOR_GUARD_EXC_UNLINK) {
+ flavors.push_back("GUARD_EXC_UNLINK");
+ }
+
+ if (flavor & MD_MAC_EXC_GUARD_FD_FLAVOR_GUARD_EXC_WRITE_OTHER) {
+ flavors.push_back("GUARD_EXC_WRITE_OTHER");
+ }
+
+ if (flavor & MD_MAC_EXC_GUARD_FD_FLAVOR_GUARD_EXC_TRUNC_OTHER) {
+ flavors.push_back("GUARD_EXC_TRUNC_OTHER");
+ }
+
+ if (flavor & MD_MAC_EXC_GUARD_FD_FLAVOR_GUARD_EXC_LINK) {
+ flavors.push_back("GUARD_EXC_LINK");
+ }
+
+ if (flavor & MD_MAC_EXC_GUARD_FD_FLAVOR_GUARD_EXC_EXCHDATA) {
+ flavors.push_back("GUARD_EXC_EXCHDATA");
+ }
+
+ reason.append(" / ");
+ for (size_t i = 0; i < flavors.size(); i++) {
+ if (i > 0) {
+ reason.append(" | ");
+ }
+
+ reason.append(flavors[i]);
+ }
+ }
+
+ break;
+ case MD_MAC_EXC_GUARD_TYPE_VIRT_MEMORY:
+ reason.append("GUARD_TYPE_VIRT_MEMORY");
+
+ if (flavor & MD_MAC_EXC_GUARD_VIRT_MEMORY_FLAVOR_GUARD_EXC_DEALLOC_GAP) {
+ reason.append(" / GUARD_EXC_DEALLOC_GAP");
+ }
+
+ break;
+ default:
+ reason.append(flags_string);
+ break;
+ }
+ }
+ break;
+ case MD_EXCEPTION_MAC_SIMULATED:
+ reason = "Simulated Exception";
+ break;
+ }
+ break;
+ }
+
+ case MD_OS_WIN32_NT:
+ case MD_OS_WIN32_WINDOWS: {
+ switch (exception_code) {
+ case MD_EXCEPTION_CODE_WIN_GUARD_PAGE_VIOLATION:
+ reason = "EXCEPTION_GUARD_PAGE";
+ break;
+ case MD_EXCEPTION_CODE_WIN_DATATYPE_MISALIGNMENT:
+ reason = "EXCEPTION_DATATYPE_MISALIGNMENT";
+ break;
+ case MD_EXCEPTION_CODE_WIN_BREAKPOINT:
+ reason = "EXCEPTION_BREAKPOINT";
+ break;
+ case MD_EXCEPTION_CODE_WIN_SINGLE_STEP:
+ reason = "EXCEPTION_SINGLE_STEP";
+ break;
+ case MD_EXCEPTION_CODE_WIN_ACCESS_VIOLATION:
+ // For EXCEPTION_ACCESS_VIOLATION, Windows puts the address that
+ // caused the fault in exception_information[1].
+ // exception_information[0] is 0 if the violation was caused by
+ // an attempt to read data, 1 if it was an attempt to write data,
+ // and 8 if this was a data execution violation.
+ // This information is useful in addition to the code address, which
+ // will be present in the crash thread's instruction field anyway.
+ if (raw_exception->exception_record.number_parameters >= 1) {
+ MDAccessViolationTypeWin av_type =
+ static_cast<MDAccessViolationTypeWin>
+ (raw_exception->exception_record.exception_information[0]);
+ switch (av_type) {
+ case MD_ACCESS_VIOLATION_WIN_READ:
+ reason = "EXCEPTION_ACCESS_VIOLATION_READ";
+ break;
+ case MD_ACCESS_VIOLATION_WIN_WRITE:
+ reason = "EXCEPTION_ACCESS_VIOLATION_WRITE";
+ break;
+ case MD_ACCESS_VIOLATION_WIN_EXEC:
+ reason = "EXCEPTION_ACCESS_VIOLATION_EXEC";
+ break;
+ default:
+ reason = "EXCEPTION_ACCESS_VIOLATION";
+ break;
+ }
+ } else {
+ reason = "EXCEPTION_ACCESS_VIOLATION";
+ }
+ if (address &&
+ raw_exception->exception_record.number_parameters >= 2) {
+ *address =
+ raw_exception->exception_record.exception_information[1];
+ }
+ break;
+ case MD_EXCEPTION_CODE_WIN_IN_PAGE_ERROR:
+ // For EXCEPTION_IN_PAGE_ERROR, Windows puts the address that
+ // caused the fault in exception_information[1].
+ // exception_information[0] is 0 if the violation was caused by
+ // an attempt to read data, 1 if it was an attempt to write data,
+ // and 8 if this was a data execution violation.
+ // exception_information[2] contains the underlying NTSTATUS code,
+ // which is the explanation for why this error occured.
+ // This information is useful in addition to the code address, which
+ // will be present in the crash thread's instruction field anyway.
+ if (raw_exception->exception_record.number_parameters >= 1) {
+ MDInPageErrorTypeWin av_type =
+ static_cast<MDInPageErrorTypeWin>
+ (raw_exception->exception_record.exception_information[0]);
+ switch (av_type) {
+ case MD_IN_PAGE_ERROR_WIN_READ:
+ reason = "EXCEPTION_IN_PAGE_ERROR_READ";
+ break;
+ case MD_IN_PAGE_ERROR_WIN_WRITE:
+ reason = "EXCEPTION_IN_PAGE_ERROR_WRITE";
+ break;
+ case MD_IN_PAGE_ERROR_WIN_EXEC:
+ reason = "EXCEPTION_IN_PAGE_ERROR_EXEC";
+ break;
+ default:
+ reason = "EXCEPTION_IN_PAGE_ERROR";
+ break;
+ }
+ } else {
+ reason = "EXCEPTION_IN_PAGE_ERROR";
+ }
+ if (address &&
+ raw_exception->exception_record.number_parameters >= 2) {
+ *address =
+ raw_exception->exception_record.exception_information[1];
+ }
+ if (raw_exception->exception_record.number_parameters >= 3) {
+ uint32_t ntstatus =
+ static_cast<uint32_t>
+ (raw_exception->exception_record.exception_information[2]);
+ reason.append(" / ");
+ const char* ntstatus_str = NTStatusToString(ntstatus);
+ if (ntstatus_str) {
+ reason.append(ntstatus_str);
+ } else {
+ snprintf(reason_string, sizeof(reason_string), "%#010x", ntstatus);
+ reason.append(reason_string);
+ }
+ }
+ break;
+ case MD_EXCEPTION_CODE_WIN_INVALID_HANDLE:
+ reason = "EXCEPTION_INVALID_HANDLE";
+ break;
+ case MD_EXCEPTION_CODE_WIN_ILLEGAL_INSTRUCTION:
+ reason = "EXCEPTION_ILLEGAL_INSTRUCTION";
+ break;
+ case MD_EXCEPTION_CODE_WIN_NONCONTINUABLE_EXCEPTION:
+ reason = "EXCEPTION_NONCONTINUABLE_EXCEPTION";
+ break;
+ case MD_EXCEPTION_CODE_WIN_INVALID_DISPOSITION:
+ reason = "EXCEPTION_INVALID_DISPOSITION";
+ break;
+ case MD_EXCEPTION_CODE_WIN_ARRAY_BOUNDS_EXCEEDED:
+ reason = "EXCEPTION_ARRAY_BOUNDS_EXCEEDED";
+ break;
+ case MD_EXCEPTION_CODE_WIN_FLOAT_DENORMAL_OPERAND:
+ reason = "EXCEPTION_FLT_DENORMAL_OPERAND";
+ break;
+ case MD_EXCEPTION_CODE_WIN_FLOAT_DIVIDE_BY_ZERO:
+ reason = "EXCEPTION_FLT_DIVIDE_BY_ZERO";
+ break;
+ case MD_EXCEPTION_CODE_WIN_FLOAT_INEXACT_RESULT:
+ reason = "EXCEPTION_FLT_INEXACT_RESULT";
+ break;
+ case MD_EXCEPTION_CODE_WIN_FLOAT_INVALID_OPERATION:
+ reason = "EXCEPTION_FLT_INVALID_OPERATION";
+ break;
+ case MD_EXCEPTION_CODE_WIN_FLOAT_OVERFLOW:
+ reason = "EXCEPTION_FLT_OVERFLOW";
+ break;
+ case MD_EXCEPTION_CODE_WIN_FLOAT_STACK_CHECK:
+ reason = "EXCEPTION_FLT_STACK_CHECK";
+ break;
+ case MD_EXCEPTION_CODE_WIN_FLOAT_UNDERFLOW:
+ reason = "EXCEPTION_FLT_UNDERFLOW";
+ break;
+ case MD_EXCEPTION_CODE_WIN_INTEGER_DIVIDE_BY_ZERO:
+ reason = "EXCEPTION_INT_DIVIDE_BY_ZERO";
+ break;
+ case MD_EXCEPTION_CODE_WIN_INTEGER_OVERFLOW:
+ reason = "EXCEPTION_INT_OVERFLOW";
+ break;
+ case MD_EXCEPTION_CODE_WIN_PRIVILEGED_INSTRUCTION:
+ reason = "EXCEPTION_PRIV_INSTRUCTION";
+ break;
+ case MD_EXCEPTION_CODE_WIN_STACK_OVERFLOW:
+ reason = "EXCEPTION_STACK_OVERFLOW";
+ break;
+ case MD_EXCEPTION_CODE_WIN_BAD_FUNCTION_TABLE:
+ reason = "EXCEPTION_BAD_FUNCTION_TABLE";
+ break;
+ case MD_EXCEPTION_CODE_WIN_POSSIBLE_DEADLOCK:
+ reason = "EXCEPTION_POSSIBLE_DEADLOCK";
+ break;
+ case MD_NTSTATUS_WIN_STATUS_STACK_BUFFER_OVERRUN:
+ reason = "STATUS_STACK_BUFFER_OVERRUN";
+ if (raw_exception->exception_record.number_parameters > 0) {
+ uint32_t fast_fail_code =
+ static_cast<uint32_t>
+ (raw_exception->exception_record.exception_information[0]);
+ char fast_fail_buff[13] = {};
+ const char* fast_fail_string = FastFailToString(fast_fail_code);
+ if (!fast_fail_string) {
+ snprintf(fast_fail_buff, sizeof(fast_fail_buff), "%#010x",
+ fast_fail_code);
+ fast_fail_string = fast_fail_buff;
+ }
+
+ reason.append(" / ");
+ reason.append(fast_fail_string);
+ }
+
+ break;
+ case MD_EXCEPTION_OUT_OF_MEMORY:
+ reason = "Out of Memory";
+ break;
+ case MD_EXCEPTION_CODE_WIN_UNHANDLED_CPP_EXCEPTION:
+ reason = "Unhandled C++ Exception";
+ break;
+ case MD_EXCEPTION_CODE_WIN_SIMULATED:
+ reason = "Simulated Exception";
+ break;
+ default:
+ fprintf(stderr, "exception_code = %u\n", exception_code);
+ const char* exception_str = NTStatusToString(exception_code);
+ fprintf(stderr, "exception_str = %s\n", exception_str);
+ if (exception_str == nullptr) {
+ exception_str = WinErrorToString(exception_code);
+ }
+ if (exception_str != nullptr) {
+ reason = exception_str;
+ }
+ break;
+ }
+ break;
+ }
+
+ case MD_OS_ANDROID:
+ case MD_OS_LINUX: {
+ switch (exception_code) {
+ case MD_EXCEPTION_CODE_LIN_SIGHUP:
+ reason = "SIGHUP";
+ break;
+ case MD_EXCEPTION_CODE_LIN_SIGINT:
+ reason = "SIGINT";
+ break;
+ case MD_EXCEPTION_CODE_LIN_SIGQUIT:
+ reason = "SIGQUIT";
+ break;
+ case MD_EXCEPTION_CODE_LIN_SIGILL:
+ reason = "SIGILL / ";
+ switch (exception_flags) {
+ case MD_EXCEPTION_FLAG_LIN_ILL_ILLOPC:
+ reason.append("ILL_ILLOPC");
+ break;
+ case MD_EXCEPTION_FLAG_LIN_ILL_ILLOPN:
+ reason.append("ILL_ILLOPN");
+ break;
+ case MD_EXCEPTION_FLAG_LIN_ILL_ILLADR:
+ reason.append("ILL_ILLADR");
+ break;
+ case MD_EXCEPTION_FLAG_LIN_ILL_ILLTRP:
+ reason.append("ILL_ILLTRP");
+ break;
+ case MD_EXCEPTION_FLAG_LIN_ILL_PRVOPC:
+ reason.append("ILL_PRVOPC");
+ break;
+ case MD_EXCEPTION_FLAG_LIN_ILL_PRVREG:
+ reason.append("ILL_PRVREG");
+ break;
+ case MD_EXCEPTION_FLAG_LIN_ILL_COPROC:
+ reason.append("ILL_COPROC");
+ break;
+ case MD_EXCEPTION_FLAG_LIN_ILL_BADSTK:
+ reason.append("ILL_BADSTK");
+ break;
+ default:
+ reason.append(flags_string);
+ BPLOG(INFO) << "Unknown exception reason " << reason;
+ break;
+ }
+ break;
+ case MD_EXCEPTION_CODE_LIN_SIGTRAP:
+ reason = "SIGTRAP";
+ break;
+ case MD_EXCEPTION_CODE_LIN_SIGABRT:
+ reason = "SIGABRT";
+ break;
+ case MD_EXCEPTION_CODE_LIN_SIGBUS:
+ reason = "SIGBUS / ";
+ switch (exception_flags) {
+ case MD_EXCEPTION_FLAG_LIN_SI_USER:
+ reason.append("SI_USER");
+ break;
+ case MD_EXCEPTION_FLAG_LIN_SI_KERNEL:
+ reason.append("SI_KERNEL");
+ break;
+ case MD_EXCEPTION_FLAG_LIN_BUS_ADRALN:
+ reason.append("BUS_ADRALN");
+ break;
+ case MD_EXCEPTION_FLAG_LIN_BUS_ADRERR:
+ reason.append("BUS_ADRERR");
+ break;
+ case MD_EXCEPTION_FLAG_LIN_BUS_OBJERR:
+ reason.append("BUS_OBJERR");
+ break;
+ case MD_EXCEPTION_FLAG_LIN_BUS_MCEERR_AR:
+ reason.append("BUS_MCEERR_AR");
+ break;
+ case MD_EXCEPTION_FLAG_LIN_BUS_MCEERR_AO:
+ reason.append("BUS_MCEERR_AO");
+ break;
+ default:
+ reason.append(flags_string);
+ BPLOG(INFO) << "Unknown exception reason " << reason;
+ break;
+ }
+ break;
+ case MD_EXCEPTION_CODE_LIN_SIGFPE:
+ reason = "SIGFPE / ";
+ switch (exception_flags) {
+ case MD_EXCEPTION_FLAG_LIN_FPE_INTDIV:
+ reason.append("FPE_INTDIV");
+ break;
+ case MD_EXCEPTION_FLAG_LIN_FPE_INTOVF:
+ reason.append("FPE_INTOVF");
+ break;
+ case MD_EXCEPTION_FLAG_LIN_FPE_FLTDIV:
+ reason.append("FPE_FLTDIV");
+ break;
+ case MD_EXCEPTION_FLAG_LIN_FPE_FLTOVF:
+ reason.append("FPE_FLTOVF");
+ break;
+ case MD_EXCEPTION_FLAG_LIN_FPE_FLTUND:
+ reason.append("FPE_FLTUND");
+ break;
+ case MD_EXCEPTION_FLAG_LIN_FPE_FLTRES:
+ reason.append("FPE_FLTRES");
+ break;
+ case MD_EXCEPTION_FLAG_LIN_FPE_FLTINV:
+ reason.append("FPE_FLTINV");
+ break;
+ case MD_EXCEPTION_FLAG_LIN_FPE_FLTSUB:
+ reason.append("FPE_FLTSUB");
+ break;
+ default:
+ reason.append(flags_string);
+ BPLOG(INFO) << "Unknown exception reason " << reason;
+ break;
+ }
+ break;
+ case MD_EXCEPTION_CODE_LIN_SIGKILL:
+ reason = "SIGKILL";
+ break;
+ case MD_EXCEPTION_CODE_LIN_SIGUSR1:
+ reason = "SIGUSR1";
+ break;
+ case MD_EXCEPTION_CODE_LIN_SIGSEGV:
+ reason = "SIGSEGV / ";
+ switch (exception_flags) {
+ case MD_EXCEPTION_FLAG_LIN_SI_USER:
+ reason.append("SI_USER");
+ break;
+ case MD_EXCEPTION_FLAG_LIN_SI_KERNEL:
+ reason.append("SI_KERNEL");
+ break;
+ case MD_EXCEPTION_FLAG_LIN_SEGV_MAPERR:
+ reason.append("SEGV_MAPERR");
+ break;
+ case MD_EXCEPTION_FLAG_LIN_SEGV_ACCERR:
+ reason.append("SEGV_ACCERR");
+ break;
+ case MD_EXCEPTION_FLAG_LIN_SEGV_BNDERR:
+ reason.append("SEGV_BNDERR");
+ break;
+ case MD_EXCEPTION_FLAG_LIN_SEGV_PKUERR:
+ reason.append("SEGV_PKUERR");
+ break;
+ default:
+ reason.append(flags_string);
+ BPLOG(INFO) << "Unknown exception reason " << reason;
+ break;
+ }
+ break;
+ case MD_EXCEPTION_CODE_LIN_SIGUSR2:
+ reason = "SIGUSR2";
+ break;
+ case MD_EXCEPTION_CODE_LIN_SIGPIPE:
+ reason = "SIGPIPE";
+ break;
+ case MD_EXCEPTION_CODE_LIN_SIGALRM:
+ reason = "SIGALRM";
+ break;
+ case MD_EXCEPTION_CODE_LIN_SIGTERM:
+ reason = "SIGTERM";
+ break;
+ case MD_EXCEPTION_CODE_LIN_SIGSTKFLT:
+ reason = "SIGSTKFLT";
+ break;
+ case MD_EXCEPTION_CODE_LIN_SIGCHLD:
+ reason = "SIGCHLD";
+ break;
+ case MD_EXCEPTION_CODE_LIN_SIGCONT:
+ reason = "SIGCONT";
+ break;
+ case MD_EXCEPTION_CODE_LIN_SIGSTOP:
+ reason = "SIGSTOP";
+ break;
+ case MD_EXCEPTION_CODE_LIN_SIGTSTP:
+ reason = "SIGTSTP";
+ break;
+ case MD_EXCEPTION_CODE_LIN_SIGTTIN:
+ reason = "SIGTTIN";
+ break;
+ case MD_EXCEPTION_CODE_LIN_SIGTTOU:
+ reason = "SIGTTOU";
+ break;
+ case MD_EXCEPTION_CODE_LIN_SIGURG:
+ reason = "SIGURG";
+ break;
+ case MD_EXCEPTION_CODE_LIN_SIGXCPU:
+ reason = "SIGXCPU";
+ break;
+ case MD_EXCEPTION_CODE_LIN_SIGXFSZ:
+ reason = "SIGXFSZ";
+ break;
+ case MD_EXCEPTION_CODE_LIN_SIGVTALRM:
+ reason = "SIGVTALRM";
+ break;
+ case MD_EXCEPTION_CODE_LIN_SIGPROF:
+ reason = "SIGPROF";
+ break;
+ case MD_EXCEPTION_CODE_LIN_SIGWINCH:
+ reason = "SIGWINCH";
+ break;
+ case MD_EXCEPTION_CODE_LIN_SIGIO:
+ reason = "SIGIO";
+ break;
+ case MD_EXCEPTION_CODE_LIN_SIGPWR:
+ reason = "SIGPWR";
+ break;
+ case MD_EXCEPTION_CODE_LIN_SIGSYS:
+ reason = "SIGSYS";
+ break;
+ case MD_EXCEPTION_CODE_LIN_DUMP_REQUESTED:
+ reason = "DUMP_REQUESTED";
+ break;
+ default:
+ BPLOG(INFO) << "Unknown exception reason " << reason;
+ break;
+ }
+ break;
+ }
+
+ case MD_OS_SOLARIS: {
+ switch (exception_code) {
+ case MD_EXCEPTION_CODE_SOL_SIGHUP:
+ reason = "SIGHUP";
+ break;
+ case MD_EXCEPTION_CODE_SOL_SIGINT:
+ reason = "SIGINT";
+ break;
+ case MD_EXCEPTION_CODE_SOL_SIGQUIT:
+ reason = "SIGQUIT";
+ break;
+ case MD_EXCEPTION_CODE_SOL_SIGILL:
+ reason = "SIGILL";
+ break;
+ case MD_EXCEPTION_CODE_SOL_SIGTRAP:
+ reason = "SIGTRAP";
+ break;
+ case MD_EXCEPTION_CODE_SOL_SIGIOT:
+ reason = "SIGIOT | SIGABRT";
+ break;
+ case MD_EXCEPTION_CODE_SOL_SIGEMT:
+ reason = "SIGEMT";
+ break;
+ case MD_EXCEPTION_CODE_SOL_SIGFPE:
+ reason = "SIGFPE";
+ break;
+ case MD_EXCEPTION_CODE_SOL_SIGKILL:
+ reason = "SIGKILL";
+ break;
+ case MD_EXCEPTION_CODE_SOL_SIGBUS:
+ reason = "SIGBUS";
+ break;
+ case MD_EXCEPTION_CODE_SOL_SIGSEGV:
+ reason = "SIGSEGV";
+ break;
+ case MD_EXCEPTION_CODE_SOL_SIGSYS:
+ reason = "SIGSYS";
+ break;
+ case MD_EXCEPTION_CODE_SOL_SIGPIPE:
+ reason = "SIGPIPE";
+ break;
+ case MD_EXCEPTION_CODE_SOL_SIGALRM:
+ reason = "SIGALRM";
+ break;
+ case MD_EXCEPTION_CODE_SOL_SIGTERM:
+ reason = "SIGTERM";
+ break;
+ case MD_EXCEPTION_CODE_SOL_SIGUSR1:
+ reason = "SIGUSR1";
+ break;
+ case MD_EXCEPTION_CODE_SOL_SIGUSR2:
+ reason = "SIGUSR2";
+ break;
+ case MD_EXCEPTION_CODE_SOL_SIGCLD:
+ reason = "SIGCLD | SIGCHLD";
+ break;
+ case MD_EXCEPTION_CODE_SOL_SIGPWR:
+ reason = "SIGPWR";
+ break;
+ case MD_EXCEPTION_CODE_SOL_SIGWINCH:
+ reason = "SIGWINCH";
+ break;
+ case MD_EXCEPTION_CODE_SOL_SIGURG:
+ reason = "SIGURG";
+ break;
+ case MD_EXCEPTION_CODE_SOL_SIGPOLL:
+ reason = "SIGPOLL | SIGIO";
+ break;
+ case MD_EXCEPTION_CODE_SOL_SIGSTOP:
+ reason = "SIGSTOP";
+ break;
+ case MD_EXCEPTION_CODE_SOL_SIGTSTP:
+ reason = "SIGTSTP";
+ break;
+ case MD_EXCEPTION_CODE_SOL_SIGCONT:
+ reason = "SIGCONT";
+ break;
+ case MD_EXCEPTION_CODE_SOL_SIGTTIN:
+ reason = "SIGTTIN";
+ break;
+ case MD_EXCEPTION_CODE_SOL_SIGTTOU:
+ reason = "SIGTTOU";
+ break;
+ case MD_EXCEPTION_CODE_SOL_SIGVTALRM:
+ reason = "SIGVTALRM";
+ break;
+ case MD_EXCEPTION_CODE_SOL_SIGPROF:
+ reason = "SIGPROF";
+ break;
+ case MD_EXCEPTION_CODE_SOL_SIGXCPU:
+ reason = "SIGXCPU";
+ break;
+ case MD_EXCEPTION_CODE_SOL_SIGXFSZ:
+ reason = "SIGXFSZ";
+ break;
+ case MD_EXCEPTION_CODE_SOL_SIGWAITING:
+ reason = "SIGWAITING";
+ break;
+ case MD_EXCEPTION_CODE_SOL_SIGLWP:
+ reason = "SIGLWP";
+ break;
+ case MD_EXCEPTION_CODE_SOL_SIGFREEZE:
+ reason = "SIGFREEZE";
+ break;
+ case MD_EXCEPTION_CODE_SOL_SIGTHAW:
+ reason = "SIGTHAW";
+ break;
+ case MD_EXCEPTION_CODE_SOL_SIGCANCEL:
+ reason = "SIGCANCEL";
+ break;
+ case MD_EXCEPTION_CODE_SOL_SIGLOST:
+ reason = "SIGLOST";
+ break;
+ case MD_EXCEPTION_CODE_SOL_SIGXRES:
+ reason = "SIGXRES";
+ break;
+ case MD_EXCEPTION_CODE_SOL_SIGJVM1:
+ reason = "SIGJVM1";
+ break;
+ case MD_EXCEPTION_CODE_SOL_SIGJVM2:
+ reason = "SIGJVM2";
+ break;
+ default:
+ BPLOG(INFO) << "Unknown exception reason " << reason;
+ break;
+ }
+ break;
+ }
+
+ case MD_OS_PS3: {
+ switch (exception_code) {
+ case MD_EXCEPTION_CODE_PS3_UNKNOWN:
+ reason = "UNKNOWN";
+ break;
+ case MD_EXCEPTION_CODE_PS3_TRAP_EXCEP:
+ reason = "TRAP_EXCEP";
+ break;
+ case MD_EXCEPTION_CODE_PS3_PRIV_INSTR:
+ reason = "PRIV_INSTR";
+ break;
+ case MD_EXCEPTION_CODE_PS3_ILLEGAL_INSTR:
+ reason = "ILLEGAL_INSTR";
+ break;
+ case MD_EXCEPTION_CODE_PS3_INSTR_STORAGE:
+ reason = "INSTR_STORAGE";
+ break;
+ case MD_EXCEPTION_CODE_PS3_INSTR_SEGMENT:
+ reason = "INSTR_SEGMENT";
+ break;
+ case MD_EXCEPTION_CODE_PS3_DATA_STORAGE:
+ reason = "DATA_STORAGE";
+ break;
+ case MD_EXCEPTION_CODE_PS3_DATA_SEGMENT:
+ reason = "DATA_SEGMENT";
+ break;
+ case MD_EXCEPTION_CODE_PS3_FLOAT_POINT:
+ reason = "FLOAT_POINT";
+ break;
+ case MD_EXCEPTION_CODE_PS3_DABR_MATCH:
+ reason = "DABR_MATCH";
+ break;
+ case MD_EXCEPTION_CODE_PS3_ALIGN_EXCEP:
+ reason = "ALIGN_EXCEP";
+ break;
+ case MD_EXCEPTION_CODE_PS3_MEMORY_ACCESS:
+ reason = "MEMORY_ACCESS";
+ break;
+ case MD_EXCEPTION_CODE_PS3_COPRO_ALIGN:
+ reason = "COPRO_ALIGN";
+ break;
+ case MD_EXCEPTION_CODE_PS3_COPRO_INVALID_COM:
+ reason = "COPRO_INVALID_COM";
+ break;
+ case MD_EXCEPTION_CODE_PS3_COPRO_ERR:
+ reason = "COPRO_ERR";
+ break;
+ case MD_EXCEPTION_CODE_PS3_COPRO_FIR:
+ reason = "COPRO_FIR";
+ break;
+ case MD_EXCEPTION_CODE_PS3_COPRO_DATA_SEGMENT:
+ reason = "COPRO_DATA_SEGMENT";
+ break;
+ case MD_EXCEPTION_CODE_PS3_COPRO_DATA_STORAGE:
+ reason = "COPRO_DATA_STORAGE";
+ break;
+ case MD_EXCEPTION_CODE_PS3_COPRO_STOP_INSTR:
+ reason = "COPRO_STOP_INSTR";
+ break;
+ case MD_EXCEPTION_CODE_PS3_COPRO_HALT_INSTR:
+ reason = "COPRO_HALT_INSTR";
+ break;
+ case MD_EXCEPTION_CODE_PS3_COPRO_HALTINST_UNKNOWN:
+ reason = "COPRO_HALTINSTR_UNKNOWN";
+ break;
+ case MD_EXCEPTION_CODE_PS3_COPRO_MEMORY_ACCESS:
+ reason = "COPRO_MEMORY_ACCESS";
+ break;
+ case MD_EXCEPTION_CODE_PS3_GRAPHIC:
+ reason = "GRAPHIC";
+ break;
+ default:
+ BPLOG(INFO) << "Unknown exception reason "<< reason;
+ break;
+ }
+ break;
+ }
+
+ default: {
+ BPLOG(INFO) << "Unknown exception reason " << reason;
+ break;
+ }
+ }
+
+ if (address) {
+ *address = GetAddressForArchitecture(
+ static_cast<MDCPUArchitecture>(raw_system_info->processor_architecture),
+ *address);
+ }
+
+ return reason;
+}
+
+// static
+string MinidumpProcessor::GetAssertion(Minidump *dump) {
+ MinidumpAssertion *assertion = dump->GetAssertion();
+ if (!assertion)
+ return "";
+
+ const MDRawAssertionInfo *raw_assertion = assertion->assertion();
+ if (!raw_assertion)
+ return "";
+
+ string assertion_string;
+ switch (raw_assertion->type) {
+ case MD_ASSERTION_INFO_TYPE_INVALID_PARAMETER:
+ assertion_string = "Invalid parameter passed to library function";
+ break;
+ case MD_ASSERTION_INFO_TYPE_PURE_VIRTUAL_CALL:
+ assertion_string = "Pure virtual function called";
+ break;
+ default: {
+ char assertion_type[32];
+ snprintf(assertion_type, sizeof(assertion_type),
+ "0x%08x", raw_assertion->type);
+ assertion_string = "Unknown assertion type ";
+ assertion_string += assertion_type;
+ break;
+ }
+ }
+
+ string expression = assertion->expression();
+ if (!expression.empty()) {
+ assertion_string.append(" " + expression);
+ }
+
+ string function = assertion->function();
+ if (!function.empty()) {
+ assertion_string.append(" in function " + function);
+ }
+
+ string file = assertion->file();
+ if (!file.empty()) {
+ assertion_string.append(", in file " + file);
+ }
+
+ if (raw_assertion->line != 0) {
+ char assertion_line[32];
+ snprintf(assertion_line, sizeof(assertion_line), "%u", raw_assertion->line);
+ assertion_string.append(" at line ");
+ assertion_string.append(assertion_line);
+ }
+
+ return assertion_string;
+}
+
+} // namespace google_breakpad
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/minidump_processor_unittest.cc b/toolkit/crashreporter/google-breakpad/src/processor/minidump_processor_unittest.cc
new file mode 100644
index 0000000000..a4ac3685ac
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/minidump_processor_unittest.cc
@@ -0,0 +1,769 @@
+// 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.
+
+// Unit test for MinidumpProcessor. Uses a pre-generated minidump and
+// corresponding symbol file, and checks the stack frames for correctness.
+
+#include <stdlib.h>
+
+#include <string>
+#include <iostream>
+#include <fstream>
+#include <map>
+#include <utility>
+
+#include "breakpad_googletest_includes.h"
+#include "common/scoped_ptr.h"
+#include "common/using_std_string.h"
+#include "google_breakpad/processor/basic_source_line_resolver.h"
+#include "google_breakpad/processor/call_stack.h"
+#include "google_breakpad/processor/code_module.h"
+#include "google_breakpad/processor/code_modules.h"
+#include "google_breakpad/processor/minidump.h"
+#include "google_breakpad/processor/minidump_processor.h"
+#include "google_breakpad/processor/process_state.h"
+#include "google_breakpad/processor/stack_frame.h"
+#include "google_breakpad/processor/symbol_supplier.h"
+#include "processor/logging.h"
+#include "processor/stackwalker_unittest_utils.h"
+
+using std::map;
+
+namespace google_breakpad {
+class MockMinidump : public Minidump {
+ public:
+ MockMinidump() : Minidump("") {
+ }
+
+ MOCK_METHOD0(Read, bool());
+ MOCK_CONST_METHOD0(path, string());
+ MOCK_CONST_METHOD0(header, const MDRawHeader*());
+ MOCK_METHOD0(GetThreadList, MinidumpThreadList*());
+ MOCK_METHOD0(GetSystemInfo, MinidumpSystemInfo*());
+ MOCK_METHOD0(GetMiscInfo, MinidumpMiscInfo*());
+ MOCK_METHOD0(GetBreakpadInfo, MinidumpBreakpadInfo*());
+ MOCK_METHOD0(GetException, MinidumpException*());
+ MOCK_METHOD0(GetAssertion, MinidumpAssertion*());
+ MOCK_METHOD0(GetModuleList, MinidumpModuleList*());
+ MOCK_METHOD0(GetUnloadedModuleList, MinidumpUnloadedModuleList*());
+ MOCK_METHOD0(GetMemoryList, MinidumpMemoryList*());
+};
+
+class MockMinidumpUnloadedModule : public MinidumpUnloadedModule {
+ public:
+ MockMinidumpUnloadedModule() : MinidumpUnloadedModule(NULL) {}
+};
+
+class MockMinidumpUnloadedModuleList : public MinidumpUnloadedModuleList {
+ public:
+ MockMinidumpUnloadedModuleList() : MinidumpUnloadedModuleList(NULL) {}
+
+ ~MockMinidumpUnloadedModuleList() {}
+ MOCK_CONST_METHOD0(Copy, CodeModules*());
+ MOCK_CONST_METHOD1(GetModuleForAddress,
+ const MinidumpUnloadedModule*(uint64_t));
+};
+
+class MockMinidumpThreadList : public MinidumpThreadList {
+ public:
+ MockMinidumpThreadList() : MinidumpThreadList(NULL) {}
+
+ MOCK_CONST_METHOD0(thread_count, unsigned int());
+ MOCK_CONST_METHOD1(GetThreadAtIndex, MinidumpThread*(unsigned int));
+};
+
+class MockMinidumpMemoryList : public MinidumpMemoryList {
+ public:
+ MockMinidumpMemoryList() : MinidumpMemoryList(NULL) {}
+
+ MOCK_METHOD1(GetMemoryRegionForAddress, MinidumpMemoryRegion*(uint64_t));
+};
+
+class MockMinidumpThread : public MinidumpThread {
+ public:
+ MockMinidumpThread() : MinidumpThread(NULL) {}
+
+ MOCK_CONST_METHOD1(GetThreadID, bool(uint32_t*));
+ MOCK_METHOD0(GetContext, MinidumpContext*());
+ MOCK_METHOD0(GetMemory, MinidumpMemoryRegion*());
+ MOCK_CONST_METHOD0(GetStartOfStackMemoryRange, uint64_t());
+};
+
+// This is crappy, but MinidumpProcessor really does want a
+// MinidumpMemoryRegion.
+class MockMinidumpMemoryRegion : public MinidumpMemoryRegion {
+ public:
+ MockMinidumpMemoryRegion(uint64_t base, const string& contents) :
+ MinidumpMemoryRegion(NULL) {
+ region_.Init(base, contents);
+ }
+
+ uint64_t GetBase() const { return region_.GetBase(); }
+ uint32_t GetSize() const { return region_.GetSize(); }
+
+ bool GetMemoryAtAddress(uint64_t address, uint8_t *value) const {
+ return region_.GetMemoryAtAddress(address, value);
+ }
+ bool GetMemoryAtAddress(uint64_t address, uint16_t *value) const {
+ return region_.GetMemoryAtAddress(address, value);
+ }
+ bool GetMemoryAtAddress(uint64_t address, uint32_t *value) const {
+ return region_.GetMemoryAtAddress(address, value);
+ }
+ bool GetMemoryAtAddress(uint64_t address, uint64_t *value) const {
+ return region_.GetMemoryAtAddress(address, value);
+ }
+
+ MockMemoryRegion region_;
+};
+
+// A test miscelaneous info stream, just returns values from the
+// MDRawMiscInfo fed to it.
+class TestMinidumpMiscInfo : public MinidumpMiscInfo {
+ public:
+ explicit TestMinidumpMiscInfo(const MDRawMiscInfo& misc_info) :
+ MinidumpMiscInfo(NULL) {
+ valid_ = true;
+ misc_info_ = misc_info;
+ }
+};
+
+} // namespace google_breakpad
+
+namespace {
+
+using google_breakpad::BasicSourceLineResolver;
+using google_breakpad::CallStack;
+using google_breakpad::CodeModule;
+using google_breakpad::MinidumpContext;
+using google_breakpad::MinidumpMemoryRegion;
+using google_breakpad::MinidumpMiscInfo;
+using google_breakpad::MinidumpProcessor;
+using google_breakpad::MinidumpSystemInfo;
+using google_breakpad::MinidumpThreadList;
+using google_breakpad::MinidumpThread;
+using google_breakpad::MockMinidump;
+using google_breakpad::MockMinidumpMemoryList;
+using google_breakpad::MockMinidumpMemoryRegion;
+using google_breakpad::MockMinidumpThread;
+using google_breakpad::MockMinidumpThreadList;
+using google_breakpad::MockMinidumpUnloadedModule;
+using google_breakpad::MockMinidumpUnloadedModuleList;
+using google_breakpad::ProcessState;
+using google_breakpad::scoped_ptr;
+using google_breakpad::SymbolSupplier;
+using google_breakpad::SystemInfo;
+using ::testing::_;
+using ::testing::AnyNumber;
+using ::testing::DoAll;
+using ::testing::Mock;
+using ::testing::Ne;
+using ::testing::Property;
+using ::testing::Return;
+using ::testing::SetArgumentPointee;
+
+static const char *kSystemInfoOS = "Windows NT";
+static const char *kSystemInfoOSShort = "windows";
+static const char *kSystemInfoOSVersion = "5.1.2600 Service Pack 2";
+static const char *kSystemInfoCPU = "x86";
+static const char *kSystemInfoCPUInfo =
+ "GenuineIntel family 6 model 13 stepping 8";
+
+#define ASSERT_TRUE_ABORT(cond) \
+ if (!(cond)) { \
+ fprintf(stderr, "FAILED: %s at %s:%d\n", #cond, __FILE__, __LINE__); \
+ abort(); \
+ }
+
+#define ASSERT_EQ_ABORT(e1, e2) ASSERT_TRUE_ABORT((e1) == (e2))
+
+static string GetTestDataPath() {
+ char *srcdir = getenv("srcdir");
+
+ return string(srcdir ? srcdir : ".") + "/src/processor/testdata/";
+}
+
+class TestSymbolSupplier : public SymbolSupplier {
+ public:
+ TestSymbolSupplier() : interrupt_(false) {}
+
+ virtual SymbolResult GetSymbolFile(const CodeModule *module,
+ const SystemInfo *system_info,
+ string *symbol_file);
+
+ virtual SymbolResult GetSymbolFile(const CodeModule *module,
+ const SystemInfo *system_info,
+ string *symbol_file,
+ string *symbol_data);
+
+ virtual SymbolResult GetCStringSymbolData(const CodeModule *module,
+ const SystemInfo *system_info,
+ string *symbol_file,
+ char **symbol_data,
+ size_t *symbol_data_size);
+
+ virtual void FreeSymbolData(const CodeModule *module);
+
+ // When set to true, causes the SymbolSupplier to return INTERRUPT
+ void set_interrupt(bool interrupt) { interrupt_ = interrupt; }
+
+ private:
+ bool interrupt_;
+ map<string, char *> memory_buffers_;
+};
+
+SymbolSupplier::SymbolResult TestSymbolSupplier::GetSymbolFile(
+ const CodeModule *module,
+ const SystemInfo *system_info,
+ string *symbol_file) {
+ ASSERT_TRUE_ABORT(module);
+ ASSERT_TRUE_ABORT(system_info);
+ ASSERT_EQ_ABORT(system_info->cpu, kSystemInfoCPU);
+ ASSERT_EQ_ABORT(system_info->cpu_info, kSystemInfoCPUInfo);
+ ASSERT_EQ_ABORT(system_info->os, kSystemInfoOS);
+ ASSERT_EQ_ABORT(system_info->os_short, kSystemInfoOSShort);
+ ASSERT_EQ_ABORT(system_info->os_version, kSystemInfoOSVersion);
+
+ if (interrupt_) {
+ return INTERRUPT;
+ }
+
+ if (module && module->code_file() == "c:\\test_app.exe") {
+ *symbol_file = GetTestDataPath() + "symbols/test_app.pdb/" +
+ module->debug_identifier() + "/test_app.sym";
+ return FOUND;
+ }
+
+ return NOT_FOUND;
+}
+
+SymbolSupplier::SymbolResult TestSymbolSupplier::GetSymbolFile(
+ const CodeModule *module,
+ const SystemInfo *system_info,
+ string *symbol_file,
+ string *symbol_data) {
+ SymbolSupplier::SymbolResult s = GetSymbolFile(module, system_info,
+ symbol_file);
+ if (s == FOUND) {
+ std::ifstream in(symbol_file->c_str());
+ std::getline(in, *symbol_data, string::traits_type::to_char_type(
+ string::traits_type::eof()));
+ in.close();
+ }
+
+ return s;
+}
+
+SymbolSupplier::SymbolResult TestSymbolSupplier::GetCStringSymbolData(
+ const CodeModule *module,
+ const SystemInfo *system_info,
+ string *symbol_file,
+ char **symbol_data,
+ size_t *symbol_data_size) {
+ string symbol_data_string;
+ SymbolSupplier::SymbolResult s = GetSymbolFile(module,
+ system_info,
+ symbol_file,
+ &symbol_data_string);
+ if (s == FOUND) {
+ *symbol_data_size = symbol_data_string.size() + 1;
+ *symbol_data = new char[*symbol_data_size];
+ if (*symbol_data == NULL) {
+ BPLOG(ERROR) << "Memory allocation failed for module: "
+ << module->code_file() << " size: " << *symbol_data_size;
+ return INTERRUPT;
+ }
+ memcpy(*symbol_data, symbol_data_string.c_str(), symbol_data_string.size());
+ (*symbol_data)[symbol_data_string.size()] = '\0';
+ memory_buffers_.insert(make_pair(module->code_file(), *symbol_data));
+ }
+
+ return s;
+}
+
+void TestSymbolSupplier::FreeSymbolData(const CodeModule *module) {
+ map<string, char *>::iterator it = memory_buffers_.find(module->code_file());
+ if (it != memory_buffers_.end()) {
+ delete [] it->second;
+ memory_buffers_.erase(it);
+ }
+}
+
+// A test system info stream, just returns values from the
+// MDRawSystemInfo fed to it.
+class TestMinidumpSystemInfo : public MinidumpSystemInfo {
+ public:
+ explicit TestMinidumpSystemInfo(MDRawSystemInfo info) :
+ MinidumpSystemInfo(NULL) {
+ valid_ = true;
+ system_info_ = info;
+ csd_version_ = new string("");
+ }
+};
+
+// A test minidump context, just returns the MDRawContextX86
+// fed to it.
+class TestMinidumpContext : public MinidumpContext {
+ public:
+ explicit TestMinidumpContext(const MDRawContextX86& context) :
+ MinidumpContext(NULL) {
+ valid_ = true;
+ SetContextX86(new MDRawContextX86(context));
+ SetContextFlags(MD_CONTEXT_X86);
+ }
+};
+
+class MinidumpProcessorTest : public ::testing::Test {
+};
+
+TEST_F(MinidumpProcessorTest, TestUnloadedModules) {
+ MockMinidump dump;
+
+ EXPECT_CALL(dump, path()).WillRepeatedly(Return("mock minidump"));
+ EXPECT_CALL(dump, Read()).WillRepeatedly(Return(true));
+
+ MDRawHeader fake_header;
+ fake_header.time_date_stamp = 0;
+ EXPECT_CALL(dump, header()).WillRepeatedly(Return(&fake_header));
+
+ MDRawSystemInfo raw_system_info;
+ memset(&raw_system_info, 0, sizeof(raw_system_info));
+ raw_system_info.processor_architecture = MD_CPU_ARCHITECTURE_X86;
+ raw_system_info.platform_id = MD_OS_WIN32_NT;
+ TestMinidumpSystemInfo dump_system_info(raw_system_info);
+
+ EXPECT_CALL(dump, GetSystemInfo()).
+ WillRepeatedly(Return(&dump_system_info));
+
+ // No loaded modules
+
+ MockMinidumpUnloadedModuleList unloaded_module_list;
+ EXPECT_CALL(dump, GetUnloadedModuleList()).
+ WillOnce(Return(&unloaded_module_list));
+
+ MockMinidumpMemoryList memory_list;
+ EXPECT_CALL(dump, GetMemoryList()).
+ WillOnce(Return(&memory_list));
+
+ MockMinidumpThreadList thread_list;
+ EXPECT_CALL(dump, GetThreadList()).
+ WillOnce(Return(&thread_list));
+
+ EXPECT_CALL(thread_list, thread_count()).
+ WillRepeatedly(Return(1));
+
+ MockMinidumpThread thread;
+ EXPECT_CALL(thread_list, GetThreadAtIndex(0)).
+ WillOnce(Return(&thread));
+
+ EXPECT_CALL(thread, GetThreadID(_)).
+ WillRepeatedly(DoAll(SetArgumentPointee<0>(1),
+ Return(true)));
+
+ MDRawContextX86 thread_raw_context;
+ memset(&thread_raw_context, 0,
+ sizeof(thread_raw_context));
+ thread_raw_context.context_flags = MD_CONTEXT_X86_FULL;
+ const uint32_t kExpectedEIP = 0xabcd1234;
+ thread_raw_context.eip = kExpectedEIP;
+ TestMinidumpContext thread_context(thread_raw_context);
+ EXPECT_CALL(thread, GetContext()).
+ WillRepeatedly(Return(&thread_context));
+
+ // The memory contents don't really matter here, since it won't be used.
+ MockMinidumpMemoryRegion thread_memory(0x1234, "xxx");
+ EXPECT_CALL(thread, GetMemory()).
+ WillRepeatedly(Return(&thread_memory));
+ EXPECT_CALL(thread, GetStartOfStackMemoryRange()).
+ Times(0);
+ EXPECT_CALL(memory_list, GetMemoryRegionForAddress(_)).
+ Times(0);
+
+ MockMinidumpUnloadedModuleList* unloaded_module_list_copy =
+ new MockMinidumpUnloadedModuleList();
+ EXPECT_CALL(unloaded_module_list, Copy()).
+ WillOnce(Return(unloaded_module_list_copy));
+
+ MockMinidumpUnloadedModule unloaded_module;
+ EXPECT_CALL(*unloaded_module_list_copy, GetModuleForAddress(kExpectedEIP)).
+ WillOnce(Return(&unloaded_module));
+
+ MinidumpProcessor processor(reinterpret_cast<SymbolSupplier*>(NULL), NULL);
+ ProcessState state;
+ EXPECT_EQ(processor.Process(&dump, &state),
+ google_breakpad::PROCESS_OK);
+
+ // The single frame should be populated with the unloaded module.
+ ASSERT_EQ(1U, state.threads()->size());
+ ASSERT_EQ(1U, state.threads()->at(0)->frames()->size());
+ ASSERT_EQ(kExpectedEIP, state.threads()->at(0)->frames()->at(0)->instruction);
+ ASSERT_EQ(&unloaded_module, state.threads()->at(0)->frames()->at(0)->module);
+}
+
+TEST_F(MinidumpProcessorTest, TestCorruptMinidumps) {
+ MockMinidump dump;
+ TestSymbolSupplier supplier;
+ BasicSourceLineResolver resolver;
+ MinidumpProcessor processor(&supplier, &resolver);
+ ProcessState state;
+
+ EXPECT_EQ(processor.Process("nonexistent minidump", &state),
+ google_breakpad::PROCESS_ERROR_MINIDUMP_NOT_FOUND);
+
+ EXPECT_CALL(dump, path()).WillRepeatedly(Return("mock minidump"));
+ EXPECT_CALL(dump, Read()).WillRepeatedly(Return(true));
+
+ MDRawHeader fakeHeader;
+ fakeHeader.time_date_stamp = 0;
+ EXPECT_CALL(dump, header()).
+ WillOnce(Return(reinterpret_cast<MDRawHeader*>(NULL))).
+ WillRepeatedly(Return(&fakeHeader));
+
+ EXPECT_EQ(processor.Process(&dump, &state),
+ google_breakpad::PROCESS_ERROR_NO_MINIDUMP_HEADER);
+
+ EXPECT_CALL(dump, GetThreadList()).
+ WillOnce(Return(reinterpret_cast<MinidumpThreadList*>(NULL)));
+ EXPECT_CALL(dump, GetSystemInfo()).
+ WillRepeatedly(Return(reinterpret_cast<MinidumpSystemInfo*>(NULL)));
+
+ EXPECT_EQ(processor.Process(&dump, &state),
+ google_breakpad::PROCESS_ERROR_NO_THREAD_LIST);
+}
+
+// This test case verifies that the symbol supplier is only consulted
+// once per minidump per module.
+TEST_F(MinidumpProcessorTest, TestSymbolSupplierLookupCounts) {
+ MockSymbolSupplier supplier;
+ BasicSourceLineResolver resolver;
+ MinidumpProcessor processor(&supplier, &resolver);
+
+ string minidump_file = GetTestDataPath() + "minidump2.dmp";
+ ProcessState state;
+ EXPECT_CALL(supplier, GetCStringSymbolData(
+ Property(&google_breakpad::CodeModule::code_file,
+ "c:\\test_app.exe"),
+ _, _, _, _)).WillOnce(Return(SymbolSupplier::NOT_FOUND));
+ EXPECT_CALL(supplier, GetCStringSymbolData(
+ Property(&google_breakpad::CodeModule::code_file,
+ Ne("c:\\test_app.exe")),
+ _, _, _, _)).WillRepeatedly(Return(SymbolSupplier::NOT_FOUND));
+ // Avoid GMOCK WARNING "Uninteresting mock function call - returning
+ // directly" for FreeSymbolData().
+ EXPECT_CALL(supplier, FreeSymbolData(_)).Times(AnyNumber());
+ ASSERT_EQ(processor.Process(minidump_file, &state),
+ google_breakpad::PROCESS_OK);
+
+ ASSERT_TRUE(Mock::VerifyAndClearExpectations(&supplier));
+
+ // We need to verify that across minidumps, the processor will refetch
+ // symbol files, even with the same symbol supplier.
+ EXPECT_CALL(supplier, GetCStringSymbolData(
+ Property(&google_breakpad::CodeModule::code_file,
+ "c:\\test_app.exe"),
+ _, _, _, _)).WillOnce(Return(SymbolSupplier::NOT_FOUND));
+ EXPECT_CALL(supplier, GetCStringSymbolData(
+ Property(&google_breakpad::CodeModule::code_file,
+ Ne("c:\\test_app.exe")),
+ _, _, _, _)).WillRepeatedly(Return(SymbolSupplier::NOT_FOUND));
+ // Avoid GMOCK WARNING "Uninteresting mock function call - returning
+ // directly" for FreeSymbolData().
+ EXPECT_CALL(supplier, FreeSymbolData(_)).Times(AnyNumber());
+ ASSERT_EQ(processor.Process(minidump_file, &state),
+ google_breakpad::PROCESS_OK);
+}
+
+TEST_F(MinidumpProcessorTest, TestBasicProcessing) {
+ TestSymbolSupplier supplier;
+ BasicSourceLineResolver resolver;
+ MinidumpProcessor processor(&supplier, &resolver);
+
+ string minidump_file = GetTestDataPath() + "minidump2.dmp";
+
+ ProcessState state;
+ ASSERT_EQ(processor.Process(minidump_file, &state),
+ google_breakpad::PROCESS_OK);
+ ASSERT_EQ(state.system_info()->os, kSystemInfoOS);
+ ASSERT_EQ(state.system_info()->os_short, kSystemInfoOSShort);
+ ASSERT_EQ(state.system_info()->os_version, kSystemInfoOSVersion);
+ ASSERT_EQ(state.system_info()->cpu, kSystemInfoCPU);
+ ASSERT_EQ(state.system_info()->cpu_info, kSystemInfoCPUInfo);
+ ASSERT_TRUE(state.crashed());
+ ASSERT_EQ(state.crash_reason(), "EXCEPTION_ACCESS_VIOLATION_WRITE");
+ ASSERT_EQ(state.crash_address(), 0x45U);
+ ASSERT_EQ(state.threads()->size(), size_t(1));
+ EXPECT_EQ((*state.threads())[0]->tid(), 3060U);
+ ASSERT_EQ(state.requesting_thread(), 0);
+ EXPECT_EQ(1171480435U, state.time_date_stamp());
+ EXPECT_EQ(1171480435U, state.process_create_time());
+
+ CallStack *stack = state.threads()->at(0);
+ ASSERT_TRUE(stack);
+ ASSERT_EQ(stack->frames()->size(), 4U);
+
+ ASSERT_TRUE(stack->frames()->at(0)->module);
+ ASSERT_EQ(stack->frames()->at(0)->module->base_address(), 0x400000U);
+ ASSERT_EQ(stack->frames()->at(0)->module->code_file(), "c:\\test_app.exe");
+ ASSERT_EQ(stack->frames()->at(0)->function_name,
+ "`anonymous namespace'::CrashFunction");
+ ASSERT_EQ(stack->frames()->at(0)->source_file_name, "c:\\test_app.cc");
+ ASSERT_EQ(stack->frames()->at(0)->source_line, 58);
+
+ ASSERT_TRUE(stack->frames()->at(1)->module);
+ ASSERT_EQ(stack->frames()->at(1)->module->base_address(), 0x400000U);
+ ASSERT_EQ(stack->frames()->at(1)->module->code_file(), "c:\\test_app.exe");
+ ASSERT_EQ(stack->frames()->at(1)->function_name, "main");
+ ASSERT_EQ(stack->frames()->at(1)->source_file_name, "c:\\test_app.cc");
+ ASSERT_EQ(stack->frames()->at(1)->source_line, 65);
+
+ // This comes from the CRT
+ ASSERT_TRUE(stack->frames()->at(2)->module);
+ ASSERT_EQ(stack->frames()->at(2)->module->base_address(), 0x400000U);
+ ASSERT_EQ(stack->frames()->at(2)->module->code_file(), "c:\\test_app.exe");
+ ASSERT_EQ(stack->frames()->at(2)->function_name, "__tmainCRTStartup");
+ ASSERT_EQ(stack->frames()->at(2)->source_file_name,
+ "f:\\sp\\vctools\\crt_bld\\self_x86\\crt\\src\\crt0.c");
+ ASSERT_EQ(stack->frames()->at(2)->source_line, 327);
+
+ // No debug info available for kernel32.dll
+ ASSERT_TRUE(stack->frames()->at(3)->module);
+ ASSERT_EQ(stack->frames()->at(3)->module->base_address(), 0x7c800000U);
+ ASSERT_EQ(stack->frames()->at(3)->module->code_file(),
+ "C:\\WINDOWS\\system32\\kernel32.dll");
+ ASSERT_TRUE(stack->frames()->at(3)->function_name.empty());
+ ASSERT_TRUE(stack->frames()->at(3)->source_file_name.empty());
+ ASSERT_EQ(stack->frames()->at(3)->source_line, 0);
+
+ ASSERT_EQ(state.modules()->module_count(), 13U);
+ ASSERT_TRUE(state.modules()->GetMainModule());
+ ASSERT_EQ(state.modules()->GetMainModule()->code_file(), "c:\\test_app.exe");
+ ASSERT_FALSE(state.modules()->GetModuleForAddress(0));
+ ASSERT_EQ(state.modules()->GetMainModule(),
+ state.modules()->GetModuleForAddress(0x400000));
+ ASSERT_EQ(state.modules()->GetModuleForAddress(0x7c801234)->debug_file(),
+ "kernel32.pdb");
+ ASSERT_EQ(state.modules()->GetModuleForAddress(0x77d43210)->version(),
+ "5.1.2600.2622");
+
+ // Test that disabled exploitability engine defaults to
+ // EXPLOITABILITY_NOT_ANALYZED.
+ ASSERT_EQ(google_breakpad::EXPLOITABILITY_NOT_ANALYZED,
+ state.exploitability());
+
+ // Test that the symbol supplier can interrupt processing
+ state.Clear();
+ supplier.set_interrupt(true);
+ ASSERT_EQ(processor.Process(minidump_file, &state),
+ google_breakpad::PROCESS_SYMBOL_SUPPLIER_INTERRUPTED);
+}
+
+TEST_F(MinidumpProcessorTest, TestThreadMissingMemory) {
+ MockMinidump dump;
+ EXPECT_CALL(dump, path()).WillRepeatedly(Return("mock minidump"));
+ EXPECT_CALL(dump, Read()).WillRepeatedly(Return(true));
+
+ MDRawHeader fake_header;
+ fake_header.time_date_stamp = 0;
+ EXPECT_CALL(dump, header()).WillRepeatedly(Return(&fake_header));
+
+ MDRawSystemInfo raw_system_info;
+ memset(&raw_system_info, 0, sizeof(raw_system_info));
+ raw_system_info.processor_architecture = MD_CPU_ARCHITECTURE_X86;
+ raw_system_info.platform_id = MD_OS_WIN32_NT;
+ TestMinidumpSystemInfo dump_system_info(raw_system_info);
+
+ EXPECT_CALL(dump, GetSystemInfo()).
+ WillRepeatedly(Return(&dump_system_info));
+
+ MockMinidumpThreadList thread_list;
+ EXPECT_CALL(dump, GetThreadList()).
+ WillOnce(Return(&thread_list));
+
+ MockMinidumpMemoryList memory_list;
+ EXPECT_CALL(dump, GetMemoryList()).
+ WillOnce(Return(&memory_list));
+
+ // Return a thread missing stack memory.
+ MockMinidumpThread no_memory_thread;
+ EXPECT_CALL(no_memory_thread, GetThreadID(_)).
+ WillRepeatedly(DoAll(SetArgumentPointee<0>(1),
+ Return(true)));
+ EXPECT_CALL(no_memory_thread, GetMemory()).
+ WillRepeatedly(Return(reinterpret_cast<MinidumpMemoryRegion*>(NULL)));
+
+ const uint64_t kTestStartOfMemoryRange = 0x1234;
+ EXPECT_CALL(no_memory_thread, GetStartOfStackMemoryRange()).
+ WillRepeatedly(Return(kTestStartOfMemoryRange));
+ EXPECT_CALL(memory_list, GetMemoryRegionForAddress(kTestStartOfMemoryRange)).
+ WillRepeatedly(Return(reinterpret_cast<MinidumpMemoryRegion*>(NULL)));
+
+ MDRawContextX86 no_memory_thread_raw_context;
+ memset(&no_memory_thread_raw_context, 0,
+ sizeof(no_memory_thread_raw_context));
+ no_memory_thread_raw_context.context_flags = MD_CONTEXT_X86_FULL;
+ const uint32_t kExpectedEIP = 0xabcd1234;
+ no_memory_thread_raw_context.eip = kExpectedEIP;
+ TestMinidumpContext no_memory_thread_context(no_memory_thread_raw_context);
+ EXPECT_CALL(no_memory_thread, GetContext()).
+ WillRepeatedly(Return(&no_memory_thread_context));
+
+ EXPECT_CALL(thread_list, thread_count()).
+ WillRepeatedly(Return(1));
+ EXPECT_CALL(thread_list, GetThreadAtIndex(0)).
+ WillOnce(Return(&no_memory_thread));
+
+ MinidumpProcessor processor(reinterpret_cast<SymbolSupplier*>(NULL), NULL);
+ ProcessState state;
+ EXPECT_EQ(processor.Process(&dump, &state),
+ google_breakpad::PROCESS_OK);
+
+ // Should have a single thread with a single frame in it.
+ ASSERT_EQ(1U, state.threads()->size());
+ ASSERT_EQ(1U, state.threads()->at(0)->frames()->size());
+ ASSERT_EQ(kExpectedEIP, state.threads()->at(0)->frames()->at(0)->instruction);
+}
+
+TEST_F(MinidumpProcessorTest, GetProcessCreateTime) {
+ const uint32_t kProcessCreateTime = 2000;
+ const uint32_t kTimeDateStamp = 5000;
+ MockMinidump dump;
+ EXPECT_CALL(dump, path()).WillRepeatedly(Return("mock minidump"));
+ EXPECT_CALL(dump, Read()).WillRepeatedly(Return(true));
+
+ // Set time of crash.
+ MDRawHeader fake_header;
+ fake_header.time_date_stamp = kTimeDateStamp;
+ EXPECT_CALL(dump, header()).WillRepeatedly(Return(&fake_header));
+
+ // Set process create time.
+ MDRawMiscInfo raw_misc_info;
+ memset(&raw_misc_info, 0, sizeof(raw_misc_info));
+ raw_misc_info.process_create_time = kProcessCreateTime;
+ raw_misc_info.flags1 |= MD_MISCINFO_FLAGS1_PROCESS_TIMES;
+ google_breakpad::TestMinidumpMiscInfo dump_misc_info(raw_misc_info);
+ EXPECT_CALL(dump, GetMiscInfo()).WillRepeatedly(Return(&dump_misc_info));
+
+ // No threads
+ MockMinidumpThreadList thread_list;
+ EXPECT_CALL(dump, GetThreadList()).WillOnce(Return(&thread_list));
+ EXPECT_CALL(thread_list, thread_count()).WillRepeatedly(Return(0));
+
+ MinidumpProcessor processor(reinterpret_cast<SymbolSupplier*>(NULL), NULL);
+ ProcessState state;
+ EXPECT_EQ(google_breakpad::PROCESS_OK, processor.Process(&dump, &state));
+
+ // Verify the time stamps.
+ ASSERT_EQ(kTimeDateStamp, state.time_date_stamp());
+ ASSERT_EQ(kProcessCreateTime, state.process_create_time());
+}
+
+TEST_F(MinidumpProcessorTest, TestThreadMissingContext) {
+ MockMinidump dump;
+ EXPECT_CALL(dump, path()).WillRepeatedly(Return("mock minidump"));
+ EXPECT_CALL(dump, Read()).WillRepeatedly(Return(true));
+
+ MDRawHeader fake_header;
+ fake_header.time_date_stamp = 0;
+ EXPECT_CALL(dump, header()).WillRepeatedly(Return(&fake_header));
+
+ MDRawSystemInfo raw_system_info;
+ memset(&raw_system_info, 0, sizeof(raw_system_info));
+ raw_system_info.processor_architecture = MD_CPU_ARCHITECTURE_X86;
+ raw_system_info.platform_id = MD_OS_WIN32_NT;
+ TestMinidumpSystemInfo dump_system_info(raw_system_info);
+
+ EXPECT_CALL(dump, GetSystemInfo()).
+ WillRepeatedly(Return(&dump_system_info));
+
+ MockMinidumpThreadList thread_list;
+ EXPECT_CALL(dump, GetThreadList()).
+ WillOnce(Return(&thread_list));
+
+ MockMinidumpMemoryList memory_list;
+ EXPECT_CALL(dump, GetMemoryList()).
+ WillOnce(Return(&memory_list));
+
+ // Return a thread missing a thread context.
+ MockMinidumpThread no_context_thread;
+ EXPECT_CALL(no_context_thread, GetThreadID(_)).
+ WillRepeatedly(DoAll(SetArgumentPointee<0>(1),
+ Return(true)));
+ EXPECT_CALL(no_context_thread, GetContext()).
+ WillRepeatedly(Return(reinterpret_cast<MinidumpContext*>(NULL)));
+
+ // The memory contents don't really matter here, since it won't be used.
+ MockMinidumpMemoryRegion no_context_thread_memory(0x1234, "xxx");
+ EXPECT_CALL(no_context_thread, GetMemory()).
+ WillRepeatedly(Return(&no_context_thread_memory));
+ EXPECT_CALL(no_context_thread, GetStartOfStackMemoryRange()).
+ Times(0);
+ EXPECT_CALL(memory_list, GetMemoryRegionForAddress(_)).
+ Times(0);
+
+ EXPECT_CALL(thread_list, thread_count()).
+ WillRepeatedly(Return(1));
+ EXPECT_CALL(thread_list, GetThreadAtIndex(0)).
+ WillOnce(Return(&no_context_thread));
+
+ MinidumpProcessor processor(reinterpret_cast<SymbolSupplier*>(NULL), NULL);
+ ProcessState state;
+ EXPECT_EQ(processor.Process(&dump, &state),
+ google_breakpad::PROCESS_OK);
+
+ // Should have a single thread with zero frames.
+ ASSERT_EQ(1U, state.threads()->size());
+ ASSERT_EQ(0U, state.threads()->at(0)->frames()->size());
+}
+
+TEST_F(MinidumpProcessorTest, Test32BitCrashingAddress) {
+ TestSymbolSupplier supplier;
+ BasicSourceLineResolver resolver;
+ MinidumpProcessor processor(&supplier, &resolver);
+
+ string minidump_file = GetTestDataPath() + "minidump_32bit_crash_addr.dmp";
+
+ ProcessState state;
+ ASSERT_EQ(processor.Process(minidump_file, &state),
+ google_breakpad::PROCESS_OK);
+ ASSERT_EQ(state.system_info()->os, kSystemInfoOS);
+ ASSERT_EQ(state.system_info()->os_short, kSystemInfoOSShort);
+ ASSERT_EQ(state.system_info()->os_version, kSystemInfoOSVersion);
+ ASSERT_EQ(state.system_info()->cpu, kSystemInfoCPU);
+ ASSERT_EQ(state.system_info()->cpu_info, kSystemInfoCPUInfo);
+ ASSERT_TRUE(state.crashed());
+ ASSERT_EQ(state.crash_reason(), "EXCEPTION_ACCESS_VIOLATION_WRITE");
+ ASSERT_EQ(state.crash_address(), 0x45U);
+}
+
+} // namespace
+
+int main(int argc, char *argv[]) {
+ ::testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/minidump_stackwalk.cc b/toolkit/crashreporter/google-breakpad/src/processor/minidump_stackwalk.cc
new file mode 100644
index 0000000000..acf80972da
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/minidump_stackwalk.cc
@@ -0,0 +1,179 @@
+// Copyright (c) 2010 Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// minidump_stackwalk.cc: Process a minidump with MinidumpProcessor, printing
+// the results, including stack traces.
+//
+// Author: Mark Mentovai
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <limits>
+#include <string>
+#include <vector>
+
+#include "common/path_helper.h"
+#include "common/scoped_ptr.h"
+#include "common/using_std_string.h"
+#include "google_breakpad/processor/basic_source_line_resolver.h"
+#include "google_breakpad/processor/minidump.h"
+#include "google_breakpad/processor/minidump_processor.h"
+#include "google_breakpad/processor/process_state.h"
+#include "processor/logging.h"
+#include "processor/simple_symbol_supplier.h"
+#include "processor/stackwalk_common.h"
+
+
+namespace {
+
+struct Options {
+ bool machine_readable;
+ bool output_stack_contents;
+
+ string minidump_file;
+ std::vector<string> symbol_paths;
+};
+
+using google_breakpad::BasicSourceLineResolver;
+using google_breakpad::Minidump;
+using google_breakpad::MinidumpMemoryList;
+using google_breakpad::MinidumpThreadList;
+using google_breakpad::MinidumpProcessor;
+using google_breakpad::ProcessState;
+using google_breakpad::SimpleSymbolSupplier;
+using google_breakpad::scoped_ptr;
+
+// Processes |options.minidump_file| using MinidumpProcessor.
+// |options.symbol_path|, if non-empty, is the base directory of a
+// symbol storage area, laid out in the format required by
+// SimpleSymbolSupplier. If such a storage area is specified, it is
+// made available for use by the MinidumpProcessor.
+//
+// Returns the value of MinidumpProcessor::Process. If processing succeeds,
+// prints identifying OS and CPU information from the minidump, crash
+// information if the minidump was produced as a result of a crash, and
+// call stacks for each thread contained in the minidump. All information
+// is printed to stdout.
+bool PrintMinidumpProcess(const Options& options) {
+ scoped_ptr<SimpleSymbolSupplier> symbol_supplier;
+ if (!options.symbol_paths.empty()) {
+ // TODO(mmentovai): check existence of symbol_path if specified?
+ symbol_supplier.reset(new SimpleSymbolSupplier(options.symbol_paths));
+ }
+
+ BasicSourceLineResolver resolver;
+ MinidumpProcessor minidump_processor(symbol_supplier.get(), &resolver);
+
+ // Increase the maximum number of threads and regions.
+ MinidumpThreadList::set_max_threads(std::numeric_limits<uint32_t>::max());
+ MinidumpMemoryList::set_max_regions(std::numeric_limits<uint32_t>::max());
+ // Process the minidump.
+ Minidump dump(options.minidump_file);
+ if (!dump.Read()) {
+ BPLOG(ERROR) << "Minidump " << dump.path() << " could not be read";
+ return false;
+ }
+ ProcessState process_state;
+ if (minidump_processor.Process(&dump, &process_state) !=
+ google_breakpad::PROCESS_OK) {
+ BPLOG(ERROR) << "MinidumpProcessor::Process failed";
+ return false;
+ }
+
+ if (options.machine_readable) {
+ PrintProcessStateMachineReadable(process_state);
+ } else {
+ PrintProcessState(process_state, options.output_stack_contents, &resolver);
+ }
+
+ return true;
+}
+
+} // namespace
+
+static void Usage(int argc, const char *argv[], bool error) {
+ fprintf(error ? stderr : stdout,
+ "Usage: %s [options] <minidump-file> [symbol-path ...]\n"
+ "\n"
+ "Output a stack trace for the provided minidump\n"
+ "\n"
+ "Options:\n"
+ "\n"
+ " -m Output in machine-readable format\n"
+ " -s Output stack contents\n",
+ google_breakpad::BaseName(argv[0]).c_str());
+}
+
+static void SetupOptions(int argc, const char *argv[], Options* options) {
+ int ch;
+
+ options->machine_readable = false;
+ options->output_stack_contents = false;
+
+ while ((ch = getopt(argc, (char * const *)argv, "hms")) != -1) {
+ switch (ch) {
+ case 'h':
+ Usage(argc, argv, false);
+ exit(0);
+ break;
+
+ case 'm':
+ options->machine_readable = true;
+ break;
+ case 's':
+ options->output_stack_contents = true;
+ break;
+
+ case '?':
+ Usage(argc, argv, true);
+ exit(1);
+ break;
+ }
+ }
+
+ if ((argc - optind) == 0) {
+ fprintf(stderr, "%s: Missing minidump file\n", argv[0]);
+ Usage(argc, argv, true);
+ exit(1);
+ }
+
+ options->minidump_file = argv[optind];
+
+ for (int argi = optind + 1; argi < argc; ++argi)
+ options->symbol_paths.push_back(argv[argi]);
+}
+
+int main(int argc, const char* argv[]) {
+ Options options;
+ SetupOptions(argc, argv, &options);
+
+ return PrintMinidumpProcess(options) ? 0 : 1;
+}
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/minidump_stackwalk_machine_readable_test b/toolkit/crashreporter/google-breakpad/src/processor/minidump_stackwalk_machine_readable_test
new file mode 100755
index 0000000000..2aadb2412f
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/minidump_stackwalk_machine_readable_test
@@ -0,0 +1,37 @@
+#!/bin/sh
+
+# 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.
+
+testdata_dir=$srcdir/src/processor/testdata
+./src/processor/minidump_stackwalk -m $testdata_dir/minidump2.dmp \
+ $testdata_dir/symbols | \
+ tr -d '\015' | \
+ diff -u $testdata_dir/minidump2.stackwalk.machine_readable.out -
+exit $?
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/minidump_stackwalk_test b/toolkit/crashreporter/google-breakpad/src/processor/minidump_stackwalk_test
new file mode 100755
index 0000000000..f97902791e
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/minidump_stackwalk_test
@@ -0,0 +1,37 @@
+#!/bin/sh
+
+# Copyright (c) 2006, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+testdata_dir=$srcdir/src/processor/testdata
+./src/processor/minidump_stackwalk $testdata_dir/minidump2.dmp \
+ $testdata_dir/symbols | \
+ tr -d '\015' | \
+ diff -u $testdata_dir/minidump2.stackwalk.out -
+exit $?
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/minidump_unittest.cc b/toolkit/crashreporter/google-breakpad/src/processor/minidump_unittest.cc
new file mode 100644
index 0000000000..036d03f116
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/minidump_unittest.cc
@@ -0,0 +1,1628 @@
+// 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 test for Minidump. Uses a pre-generated minidump and
+// verifies that certain streams are correct.
+
+#include <iostream>
+#include <fstream>
+#include <sstream>
+#include <stdlib.h>
+#include <string>
+#include <vector>
+
+#include "breakpad_googletest_includes.h"
+#include "common/using_std_string.h"
+#include "google_breakpad/common/minidump_format.h"
+#include "google_breakpad/processor/minidump.h"
+#include "processor/logging.h"
+#include "processor/synth_minidump.h"
+
+namespace {
+
+using google_breakpad::Minidump;
+using google_breakpad::MinidumpContext;
+using google_breakpad::MinidumpException;
+using google_breakpad::MinidumpMemoryInfo;
+using google_breakpad::MinidumpMemoryInfoList;
+using google_breakpad::MinidumpMemoryList;
+using google_breakpad::MinidumpMemoryRegion;
+using google_breakpad::MinidumpModule;
+using google_breakpad::MinidumpModuleList;
+using google_breakpad::MinidumpSystemInfo;
+using google_breakpad::MinidumpUnloadedModule;
+using google_breakpad::MinidumpUnloadedModuleList;
+using google_breakpad::MinidumpThread;
+using google_breakpad::MinidumpThreadList;
+using google_breakpad::SynthMinidump::Context;
+using google_breakpad::SynthMinidump::Dump;
+using google_breakpad::SynthMinidump::Exception;
+using google_breakpad::SynthMinidump::Memory;
+using google_breakpad::SynthMinidump::Module;
+using google_breakpad::SynthMinidump::UnloadedModule;
+using google_breakpad::SynthMinidump::Section;
+using google_breakpad::SynthMinidump::Stream;
+using google_breakpad::SynthMinidump::String;
+using google_breakpad::SynthMinidump::SystemInfo;
+using google_breakpad::SynthMinidump::Thread;
+using google_breakpad::test_assembler::kBigEndian;
+using google_breakpad::test_assembler::kLittleEndian;
+using std::ifstream;
+using std::istringstream;
+using std::vector;
+using ::testing::Return;
+
+class MinidumpTest : public ::testing::Test {
+public:
+ void SetUp() {
+ minidump_file_ = string(getenv("srcdir") ? getenv("srcdir") : ".") +
+ "/src/processor/testdata/minidump2.dmp";
+ }
+ string minidump_file_;
+};
+
+TEST_F(MinidumpTest, TestMinidumpFromFile) {
+ Minidump minidump(minidump_file_);
+ ASSERT_EQ(minidump.path(), minidump_file_);
+ ASSERT_TRUE(minidump.Read());
+ const MDRawHeader* header = minidump.header();
+ ASSERT_NE(header, (MDRawHeader*)NULL);
+ ASSERT_EQ(header->signature, uint32_t(MD_HEADER_SIGNATURE));
+
+ MinidumpModuleList *md_module_list = minidump.GetModuleList();
+ ASSERT_TRUE(md_module_list != NULL);
+ const MinidumpModule *md_module = md_module_list->GetModuleAtIndex(0);
+ ASSERT_TRUE(md_module != NULL);
+ ASSERT_EQ("c:\\test_app.exe", md_module->code_file());
+ ASSERT_EQ("c:\\test_app.pdb", md_module->debug_file());
+ ASSERT_EQ("45D35F6C2d000", md_module->code_identifier());
+ ASSERT_EQ("5A9832E5287241C1838ED98914E9B7FF1", md_module->debug_identifier());
+}
+
+TEST_F(MinidumpTest, TestMinidumpFromStream) {
+ // read minidump contents into memory, construct a stringstream around them
+ ifstream file_stream(minidump_file_.c_str(), std::ios::in);
+ ASSERT_TRUE(file_stream.good());
+ vector<char> bytes;
+ file_stream.seekg(0, std::ios_base::end);
+ ASSERT_TRUE(file_stream.good());
+ bytes.resize(file_stream.tellg());
+ file_stream.seekg(0, std::ios_base::beg);
+ ASSERT_TRUE(file_stream.good());
+ file_stream.read(&bytes[0], bytes.size());
+ ASSERT_TRUE(file_stream.good());
+ string str(&bytes[0], bytes.size());
+ istringstream stream(str);
+ ASSERT_TRUE(stream.good());
+
+ // now read minidump from stringstream
+ Minidump minidump(stream);
+ ASSERT_EQ(minidump.path(), "");
+ ASSERT_TRUE(minidump.Read());
+ const MDRawHeader* header = minidump.header();
+ ASSERT_NE(header, (MDRawHeader*)NULL);
+ ASSERT_EQ(header->signature, uint32_t(MD_HEADER_SIGNATURE));
+ //TODO: add more checks here
+}
+
+TEST(Dump, ReadBackEmpty) {
+ Dump dump(0);
+ dump.Finish();
+ string contents;
+ ASSERT_TRUE(dump.GetContents(&contents));
+ istringstream stream(contents);
+ Minidump minidump(stream);
+ ASSERT_TRUE(minidump.Read());
+ ASSERT_EQ(0U, minidump.GetDirectoryEntryCount());
+}
+
+TEST(Dump, ReadBackEmptyBigEndian) {
+ Dump big_minidump(0, kBigEndian);
+ big_minidump.Finish();
+ string contents;
+ ASSERT_TRUE(big_minidump.GetContents(&contents));
+ istringstream stream(contents);
+ Minidump minidump(stream);
+ ASSERT_TRUE(minidump.Read());
+ ASSERT_EQ(0U, minidump.GetDirectoryEntryCount());
+}
+
+TEST(Dump, OneStream) {
+ Dump dump(0, kBigEndian);
+ Stream stream(dump, 0xfbb7fa2bU);
+ stream.Append("stream contents");
+ dump.Add(&stream);
+ dump.Finish();
+
+ string contents;
+ ASSERT_TRUE(dump.GetContents(&contents));
+ istringstream minidump_stream(contents);
+ Minidump minidump(minidump_stream);
+ ASSERT_TRUE(minidump.Read());
+ ASSERT_EQ(1U, minidump.GetDirectoryEntryCount());
+
+ const MDRawDirectory *dir = minidump.GetDirectoryEntryAtIndex(0);
+ ASSERT_TRUE(dir != NULL);
+ EXPECT_EQ(0xfbb7fa2bU, dir->stream_type);
+
+ uint32_t stream_length;
+ ASSERT_TRUE(minidump.SeekToStreamType(0xfbb7fa2bU, &stream_length));
+ ASSERT_EQ(15U, stream_length);
+ char stream_contents[15];
+ ASSERT_TRUE(minidump.ReadBytes(stream_contents, sizeof(stream_contents)));
+ EXPECT_EQ(string("stream contents"),
+ string(stream_contents, sizeof(stream_contents)));
+
+ EXPECT_FALSE(minidump.GetThreadList());
+ EXPECT_FALSE(minidump.GetModuleList());
+ EXPECT_FALSE(minidump.GetMemoryList());
+ EXPECT_FALSE(minidump.GetException());
+ EXPECT_FALSE(minidump.GetAssertion());
+ EXPECT_FALSE(minidump.GetSystemInfo());
+ EXPECT_FALSE(minidump.GetMiscInfo());
+ EXPECT_FALSE(minidump.GetBreakpadInfo());
+}
+
+TEST(Dump, OneMemory) {
+ Dump dump(0, kBigEndian);
+ Memory memory(dump, 0x309d68010bd21b2cULL);
+ memory.Append("memory contents");
+ dump.Add(&memory);
+ dump.Finish();
+
+ string contents;
+ ASSERT_TRUE(dump.GetContents(&contents));
+ istringstream minidump_stream(contents);
+ Minidump minidump(minidump_stream);
+ ASSERT_TRUE(minidump.Read());
+ ASSERT_EQ(1U, minidump.GetDirectoryEntryCount());
+
+ const MDRawDirectory *dir = minidump.GetDirectoryEntryAtIndex(0);
+ ASSERT_TRUE(dir != NULL);
+ EXPECT_EQ((uint32_t) MD_MEMORY_LIST_STREAM, dir->stream_type);
+
+ MinidumpMemoryList *memory_list = minidump.GetMemoryList();
+ ASSERT_TRUE(memory_list != NULL);
+ ASSERT_EQ(1U, memory_list->region_count());
+
+ MinidumpMemoryRegion *region1 = memory_list->GetMemoryRegionAtIndex(0);
+ ASSERT_EQ(0x309d68010bd21b2cULL, region1->GetBase());
+ ASSERT_EQ(15U, region1->GetSize());
+ const uint8_t *region1_bytes = region1->GetMemory();
+ ASSERT_TRUE(memcmp("memory contents", region1_bytes, 15) == 0);
+}
+
+// One thread --- and its requisite entourage.
+TEST(Dump, OneThread) {
+ Dump dump(0, kLittleEndian);
+ Memory stack(dump, 0x2326a0fa);
+ stack.Append("stack for thread");
+
+ MDRawContextX86 raw_context;
+ const uint32_t kExpectedEIP = 0x6913f540;
+ raw_context.context_flags = MD_CONTEXT_X86_INTEGER | MD_CONTEXT_X86_CONTROL;
+ raw_context.edi = 0x3ecba80d;
+ raw_context.esi = 0x382583b9;
+ raw_context.ebx = 0x7fccc03f;
+ raw_context.edx = 0xf62f8ec2;
+ raw_context.ecx = 0x46a6a6a8;
+ raw_context.eax = 0x6a5025e2;
+ raw_context.ebp = 0xd9fabb4a;
+ raw_context.eip = kExpectedEIP;
+ raw_context.cs = 0xbffe6eda;
+ raw_context.eflags = 0xb2ce1e2d;
+ raw_context.esp = 0x659caaa4;
+ raw_context.ss = 0x2e951ef7;
+ Context context(dump, raw_context);
+
+ Thread thread(dump, 0xa898f11b, stack, context,
+ 0x9e39439f, 0x4abfc15f, 0xe499898a, 0x0d43e939dcfd0372ULL);
+
+ dump.Add(&stack);
+ dump.Add(&context);
+ dump.Add(&thread);
+ dump.Finish();
+
+ string contents;
+ ASSERT_TRUE(dump.GetContents(&contents));
+
+ istringstream minidump_stream(contents);
+ Minidump minidump(minidump_stream);
+ ASSERT_TRUE(minidump.Read());
+ ASSERT_EQ(2U, minidump.GetDirectoryEntryCount());
+
+ MinidumpMemoryList *md_memory_list = minidump.GetMemoryList();
+ ASSERT_TRUE(md_memory_list != NULL);
+ ASSERT_EQ(1U, md_memory_list->region_count());
+
+ MinidumpMemoryRegion *md_region = md_memory_list->GetMemoryRegionAtIndex(0);
+ ASSERT_EQ(0x2326a0faU, md_region->GetBase());
+ ASSERT_EQ(16U, md_region->GetSize());
+ const uint8_t *region_bytes = md_region->GetMemory();
+ ASSERT_TRUE(memcmp("stack for thread", region_bytes, 16) == 0);
+
+ MinidumpThreadList *thread_list = minidump.GetThreadList();
+ ASSERT_TRUE(thread_list != NULL);
+ ASSERT_EQ(1U, thread_list->thread_count());
+
+ MinidumpThread *md_thread = thread_list->GetThreadAtIndex(0);
+ ASSERT_TRUE(md_thread != NULL);
+ uint32_t thread_id;
+ ASSERT_TRUE(md_thread->GetThreadID(&thread_id));
+ ASSERT_EQ(0xa898f11bU, thread_id);
+ MinidumpMemoryRegion *md_stack = md_thread->GetMemory();
+ ASSERT_TRUE(md_stack != NULL);
+ ASSERT_EQ(0x2326a0faU, md_stack->GetBase());
+ ASSERT_EQ(16U, md_stack->GetSize());
+ const uint8_t *md_stack_bytes = md_stack->GetMemory();
+ ASSERT_TRUE(memcmp("stack for thread", md_stack_bytes, 16) == 0);
+
+ MinidumpContext *md_context = md_thread->GetContext();
+ ASSERT_TRUE(md_context != NULL);
+ ASSERT_EQ((uint32_t) MD_CONTEXT_X86, md_context->GetContextCPU());
+
+ uint64_t eip;
+ ASSERT_TRUE(md_context->GetInstructionPointer(&eip));
+ EXPECT_EQ(kExpectedEIP, eip);
+
+ const MDRawContextX86 *md_raw_context = md_context->GetContextX86();
+ ASSERT_TRUE(md_raw_context != NULL);
+ ASSERT_EQ((uint32_t) (MD_CONTEXT_X86_INTEGER | MD_CONTEXT_X86_CONTROL),
+ (md_raw_context->context_flags
+ & (MD_CONTEXT_X86_INTEGER | MD_CONTEXT_X86_CONTROL)));
+ EXPECT_EQ(0x3ecba80dU, raw_context.edi);
+ EXPECT_EQ(0x382583b9U, raw_context.esi);
+ EXPECT_EQ(0x7fccc03fU, raw_context.ebx);
+ EXPECT_EQ(0xf62f8ec2U, raw_context.edx);
+ EXPECT_EQ(0x46a6a6a8U, raw_context.ecx);
+ EXPECT_EQ(0x6a5025e2U, raw_context.eax);
+ EXPECT_EQ(0xd9fabb4aU, raw_context.ebp);
+ EXPECT_EQ(kExpectedEIP, raw_context.eip);
+ EXPECT_EQ(0xbffe6edaU, raw_context.cs);
+ EXPECT_EQ(0xb2ce1e2dU, raw_context.eflags);
+ EXPECT_EQ(0x659caaa4U, raw_context.esp);
+ EXPECT_EQ(0x2e951ef7U, raw_context.ss);
+}
+
+TEST(Dump, ThreadMissingMemory) {
+ Dump dump(0, kLittleEndian);
+ Memory stack(dump, 0x2326a0fa);
+ // Stack has no contents.
+
+ MDRawContextX86 raw_context;
+ memset(&raw_context, 0, sizeof(raw_context));
+ raw_context.context_flags = MD_CONTEXT_X86_INTEGER | MD_CONTEXT_X86_CONTROL;
+ Context context(dump, raw_context);
+
+ Thread thread(dump, 0xa898f11b, stack, context,
+ 0x9e39439f, 0x4abfc15f, 0xe499898a, 0x0d43e939dcfd0372ULL);
+
+ dump.Add(&stack);
+ dump.Add(&context);
+ dump.Add(&thread);
+ dump.Finish();
+
+ string contents;
+ ASSERT_TRUE(dump.GetContents(&contents));
+
+ istringstream minidump_stream(contents);
+ Minidump minidump(minidump_stream);
+ ASSERT_TRUE(minidump.Read());
+ ASSERT_EQ(2U, minidump.GetDirectoryEntryCount());
+
+ // This should succeed even though the thread has no stack memory.
+ MinidumpThreadList* thread_list = minidump.GetThreadList();
+ ASSERT_TRUE(thread_list != NULL);
+ ASSERT_EQ(1U, thread_list->thread_count());
+
+ MinidumpThread* md_thread = thread_list->GetThreadAtIndex(0);
+ ASSERT_TRUE(md_thread != NULL);
+
+ uint32_t thread_id;
+ ASSERT_TRUE(md_thread->GetThreadID(&thread_id));
+ ASSERT_EQ(0xa898f11bU, thread_id);
+
+ MinidumpContext* md_context = md_thread->GetContext();
+ ASSERT_NE(reinterpret_cast<MinidumpContext*>(NULL), md_context);
+
+ MinidumpMemoryRegion* md_stack = md_thread->GetMemory();
+ ASSERT_EQ(reinterpret_cast<MinidumpMemoryRegion*>(NULL), md_stack);
+}
+
+TEST(Dump, ThreadMissingContext) {
+ Dump dump(0, kLittleEndian);
+ Memory stack(dump, 0x2326a0fa);
+ stack.Append("stack for thread");
+
+ // Context is empty.
+ Context context(dump);
+
+ Thread thread(dump, 0xa898f11b, stack, context,
+ 0x9e39439f, 0x4abfc15f, 0xe499898a, 0x0d43e939dcfd0372ULL);
+
+ dump.Add(&stack);
+ dump.Add(&context);
+ dump.Add(&thread);
+ dump.Finish();
+
+ string contents;
+ ASSERT_TRUE(dump.GetContents(&contents));
+
+ istringstream minidump_stream(contents);
+ Minidump minidump(minidump_stream);
+ ASSERT_TRUE(minidump.Read());
+ ASSERT_EQ(2U, minidump.GetDirectoryEntryCount());
+
+ // This should succeed even though the thread has no stack memory.
+ MinidumpThreadList* thread_list = minidump.GetThreadList();
+ ASSERT_TRUE(thread_list != NULL);
+ ASSERT_EQ(1U, thread_list->thread_count());
+
+ MinidumpThread* md_thread = thread_list->GetThreadAtIndex(0);
+ ASSERT_TRUE(md_thread != NULL);
+
+ uint32_t thread_id;
+ ASSERT_TRUE(md_thread->GetThreadID(&thread_id));
+ ASSERT_EQ(0xa898f11bU, thread_id);
+ MinidumpMemoryRegion* md_stack = md_thread->GetMemory();
+ ASSERT_NE(reinterpret_cast<MinidumpMemoryRegion*>(NULL), md_stack);
+
+ MinidumpContext* md_context = md_thread->GetContext();
+ ASSERT_EQ(reinterpret_cast<MinidumpContext*>(NULL), md_context);
+}
+
+TEST(Dump, OneUnloadedModule) {
+ Dump dump(0, kBigEndian);
+ String module_name(dump, "unloaded module");
+
+ String csd_version(dump, "Windows 9000");
+ SystemInfo system_info(dump, SystemInfo::windows_x86, csd_version);
+
+ UnloadedModule unloaded_module(
+ dump,
+ 0xa90206ca83eb2852ULL,
+ 0xada542bd,
+ module_name,
+ 0x34571371,
+ 0xb1054d2a);
+
+ dump.Add(&unloaded_module);
+ dump.Add(&module_name);
+ dump.Add(&system_info);
+ dump.Add(&csd_version);
+ dump.Finish();
+
+ string contents;
+ ASSERT_TRUE(dump.GetContents(&contents));
+ istringstream minidump_stream(contents);
+ Minidump minidump(minidump_stream);
+ ASSERT_TRUE(minidump.Read());
+ ASSERT_EQ(2U, minidump.GetDirectoryEntryCount());
+
+ const MDRawDirectory *dir = minidump.GetDirectoryEntryAtIndex(1);
+ ASSERT_TRUE(dir != NULL);
+ EXPECT_EQ((uint32_t) MD_UNLOADED_MODULE_LIST_STREAM, dir->stream_type);
+
+ MinidumpUnloadedModuleList *md_unloaded_module_list =
+ minidump.GetUnloadedModuleList();
+ ASSERT_TRUE(md_unloaded_module_list != NULL);
+ ASSERT_EQ(1U, md_unloaded_module_list->module_count());
+
+ const MinidumpUnloadedModule *md_unloaded_module =
+ md_unloaded_module_list->GetModuleAtIndex(0);
+ ASSERT_TRUE(md_unloaded_module != NULL);
+ ASSERT_EQ(0xa90206ca83eb2852ULL, md_unloaded_module->base_address());
+ ASSERT_EQ(0xada542bd, md_unloaded_module->size());
+ ASSERT_EQ("unloaded module", md_unloaded_module->code_file());
+ ASSERT_EQ("", md_unloaded_module->debug_file());
+ // time_date_stamp and size_of_image concatenated
+ ASSERT_EQ("B1054D2Aada542bd", md_unloaded_module->code_identifier());
+ ASSERT_EQ("", md_unloaded_module->debug_identifier());
+
+ const MDRawUnloadedModule *md_raw_unloaded_module =
+ md_unloaded_module->module();
+ ASSERT_TRUE(md_raw_unloaded_module != NULL);
+ ASSERT_EQ(0xb1054d2aU, md_raw_unloaded_module->time_date_stamp);
+ ASSERT_EQ(0x34571371U, md_raw_unloaded_module->checksum);
+}
+
+static const MDVSFixedFileInfo fixed_file_info = {
+ 0xb2fba33a, // signature
+ 0x33d7a728, // struct_version
+ 0x31afcb20, // file_version_hi
+ 0xe51cdab1, // file_version_lo
+ 0xd1ea6907, // product_version_hi
+ 0x03032857, // product_version_lo
+ 0x11bf71d7, // file_flags_mask
+ 0x5fb8cdbf, // file_flags
+ 0xe45d0d5d, // file_os
+ 0x107d9562, // file_type
+ 0x5a8844d4, // file_subtype
+ 0xa8d30b20, // file_date_hi
+ 0x651c3e4e // file_date_lo
+};
+
+TEST(Dump, OneModule) {
+ Dump dump(0, kBigEndian);
+ String module_name(dump, "single module");
+ Section cv_info(dump);
+ cv_info
+ .D32(MD_CVINFOPDB70_SIGNATURE) // signature
+ // signature, a MDGUID
+ .D32(0xabcd1234)
+ .D16(0xf00d)
+ .D16(0xbeef)
+ .Append("\x01\x02\x03\x04\x05\x06\x07\x08")
+ .D32(1) // age
+ .AppendCString("c:\\foo\\file.pdb"); // pdb_file_name
+
+ String csd_version(dump, "Windows 9000");
+ SystemInfo system_info(dump, SystemInfo::windows_x86, csd_version);
+
+ Module module(dump, 0xa90206ca83eb2852ULL, 0xada542bd,
+ module_name,
+ 0xb1054d2a,
+ 0x34571371,
+ fixed_file_info, // from synth_minidump_unittest_data.h
+ &cv_info, nullptr);
+
+ dump.Add(&module);
+ dump.Add(&module_name);
+ dump.Add(&cv_info);
+ dump.Add(&system_info);
+ dump.Add(&csd_version);
+ dump.Finish();
+
+ string contents;
+ ASSERT_TRUE(dump.GetContents(&contents));
+ istringstream minidump_stream(contents);
+ Minidump minidump(minidump_stream);
+ ASSERT_TRUE(minidump.Read());
+ ASSERT_EQ(2U, minidump.GetDirectoryEntryCount());
+
+ const MDRawDirectory *dir = minidump.GetDirectoryEntryAtIndex(1);
+ ASSERT_TRUE(dir != NULL);
+ EXPECT_EQ((uint32_t) MD_MODULE_LIST_STREAM, dir->stream_type);
+
+ MinidumpModuleList *md_module_list = minidump.GetModuleList();
+ ASSERT_TRUE(md_module_list != NULL);
+ ASSERT_EQ(1U, md_module_list->module_count());
+
+ const MinidumpModule *md_module = md_module_list->GetModuleAtIndex(0);
+ ASSERT_TRUE(md_module != NULL);
+ ASSERT_EQ(0xa90206ca83eb2852ULL, md_module->base_address());
+ ASSERT_EQ(0xada542bd, md_module->size());
+ ASSERT_EQ("single module", md_module->code_file());
+ ASSERT_EQ("c:\\foo\\file.pdb", md_module->debug_file());
+ // time_date_stamp and size_of_image concatenated
+ ASSERT_EQ("B1054D2Aada542bd", md_module->code_identifier());
+ ASSERT_EQ("ABCD1234F00DBEEF01020304050607081", md_module->debug_identifier());
+
+ const MDRawModule *md_raw_module = md_module->module();
+ ASSERT_TRUE(md_raw_module != NULL);
+ ASSERT_EQ(0xb1054d2aU, md_raw_module->time_date_stamp);
+ ASSERT_EQ(0x34571371U, md_raw_module->checksum);
+ ASSERT_TRUE(memcmp(&md_raw_module->version_info, &fixed_file_info,
+ sizeof(fixed_file_info)) == 0);
+}
+
+// Test that a module with a MDCVInfoELF CV record is handled properly.
+TEST(Dump, OneModuleCVELF) {
+ Dump dump(0, kLittleEndian);
+ String module_name(dump, "elf module");
+ Section cv_info(dump);
+ cv_info
+ .D32(MD_CVINFOELF_SIGNATURE) // signature
+ // build_id
+ .Append("\x5f\xa9\xcd\xb4\x10\x53\xdf\x1b\x86\xfa\xb7\x33\xb4\xdf"
+ "\x37\x38\xce\xa3\x4a\x87");
+
+ const MDRawSystemInfo linux_x86 = {
+ MD_CPU_ARCHITECTURE_X86, // processor_architecture
+ 6, // processor_level
+ 0xd08, // processor_revision
+ 1, // number_of_processors
+ 0, // product_type
+ 0, // major_version
+ 0, // minor_version
+ 0, // build_number
+ MD_OS_LINUX, // platform_id
+ 0xdeadbeef, // csd_version_rva
+ 0x100, // suite_mask
+ 0, // reserved2
+ { // cpu
+ { // x86_cpu_info
+ { 0x756e6547, 0x49656e69, 0x6c65746e }, // vendor_id
+ 0x6d8, // version_information
+ 0xafe9fbff, // feature_information
+ 0xffffffff // amd_extended_cpu_features
+ }
+ }
+ };
+ String csd_version(dump, "Literally Linux");
+ SystemInfo system_info(dump, linux_x86, csd_version);
+
+ Module module(dump, 0xa90206ca83eb2852ULL, 0xada542bd,
+ module_name,
+ 0xb1054d2a,
+ 0x34571371,
+ fixed_file_info, // from synth_minidump_unittest_data.h
+ &cv_info, nullptr);
+
+ dump.Add(&module);
+ dump.Add(&module_name);
+ dump.Add(&cv_info);
+ dump.Add(&system_info);
+ dump.Add(&csd_version);
+ dump.Finish();
+
+ string contents;
+ ASSERT_TRUE(dump.GetContents(&contents));
+ istringstream minidump_stream(contents);
+ Minidump minidump(minidump_stream);
+ ASSERT_TRUE(minidump.Read());
+
+ MinidumpModuleList *md_module_list = minidump.GetModuleList();
+ ASSERT_TRUE(md_module_list != NULL);
+ ASSERT_EQ(1U, md_module_list->module_count());
+
+ const MinidumpModule *md_module = md_module_list->GetModuleAtIndex(0);
+ ASSERT_TRUE(md_module != NULL);
+ ASSERT_EQ(0xa90206ca83eb2852ULL, md_module->base_address());
+ ASSERT_EQ(0xada542bd, md_module->size());
+ ASSERT_EQ("elf module", md_module->code_file());
+ // debug_file == code_file
+ ASSERT_EQ("elf module", md_module->debug_file());
+ // just the build_id, directly
+ ASSERT_EQ("5fa9cdb41053df1b86fab733b4df3738cea34a87",
+ md_module->code_identifier());
+ // build_id truncted to GUID length and treated as such, with zero
+ // age appended
+ ASSERT_EQ("B4CDA95F53101BDF86FAB733B4DF37380", md_module->debug_identifier());
+
+ const MDRawModule *md_raw_module = md_module->module();
+ ASSERT_TRUE(md_raw_module != NULL);
+ ASSERT_EQ(0xb1054d2aU, md_raw_module->time_date_stamp);
+ ASSERT_EQ(0x34571371U, md_raw_module->checksum);
+ ASSERT_TRUE(memcmp(&md_raw_module->version_info, &fixed_file_info,
+ sizeof(fixed_file_info)) == 0);
+}
+
+// Test that a build_id that's shorter than a GUID is handled properly.
+TEST(Dump, CVELFShort) {
+ Dump dump(0, kLittleEndian);
+ String module_name(dump, "elf module");
+ Section cv_info(dump);
+ cv_info
+ .D32(MD_CVINFOELF_SIGNATURE) // signature
+ // build_id, shorter than a GUID
+ .Append("\x5f\xa9\xcd\xb4");
+
+ const MDRawSystemInfo linux_x86 = {
+ MD_CPU_ARCHITECTURE_X86, // processor_architecture
+ 6, // processor_level
+ 0xd08, // processor_revision
+ 1, // number_of_processors
+ 0, // product_type
+ 0, // major_version
+ 0, // minor_version
+ 0, // build_number
+ MD_OS_LINUX, // platform_id
+ 0xdeadbeef, // csd_version_rva
+ 0x100, // suite_mask
+ 0, // reserved2
+ { // cpu
+ { // x86_cpu_info
+ { 0x756e6547, 0x49656e69, 0x6c65746e }, // vendor_id
+ 0x6d8, // version_information
+ 0xafe9fbff, // feature_information
+ 0xffffffff // amd_extended_cpu_features
+ }
+ }
+ };
+ String csd_version(dump, "Literally Linux");
+ SystemInfo system_info(dump, linux_x86, csd_version);
+
+ Module module(dump, 0xa90206ca83eb2852ULL, 0xada542bd,
+ module_name,
+ 0xb1054d2a,
+ 0x34571371,
+ fixed_file_info, // from synth_minidump_unittest_data.h
+ &cv_info, nullptr);
+
+ dump.Add(&module);
+ dump.Add(&module_name);
+ dump.Add(&cv_info);
+ dump.Add(&system_info);
+ dump.Add(&csd_version);
+ dump.Finish();
+
+ string contents;
+ ASSERT_TRUE(dump.GetContents(&contents));
+ istringstream minidump_stream(contents);
+ Minidump minidump(minidump_stream);
+ ASSERT_TRUE(minidump.Read());
+ ASSERT_EQ(2U, minidump.GetDirectoryEntryCount());
+
+ MinidumpModuleList *md_module_list = minidump.GetModuleList();
+ ASSERT_TRUE(md_module_list != NULL);
+ ASSERT_EQ(1U, md_module_list->module_count());
+
+ const MinidumpModule *md_module = md_module_list->GetModuleAtIndex(0);
+ ASSERT_TRUE(md_module != NULL);
+ // just the build_id, directly
+ ASSERT_EQ("5fa9cdb4", md_module->code_identifier());
+ // build_id expanded to GUID length and treated as such, with zero
+ // age appended
+ ASSERT_EQ("B4CDA95F0000000000000000000000000", md_module->debug_identifier());
+}
+
+// Test that a build_id that's very long is handled properly.
+TEST(Dump, CVELFLong) {
+ Dump dump(0, kLittleEndian);
+ String module_name(dump, "elf module");
+ Section cv_info(dump);
+ cv_info
+ .D32(MD_CVINFOELF_SIGNATURE) // signature
+ // build_id, lots of bytes
+ .Append("\x5f\xa9\xcd\xb4\x10\x53\xdf\x1b\x86\xfa\xb7\x33\xb4\xdf"
+ "\x37\x38\xce\xa3\x4a\x87\x01\x02\x03\x04\x05\x06\x07\x08"
+ "\x09\x0a\x0b\x0c\x0d\x0e\x0f");
+
+
+ const MDRawSystemInfo linux_x86 = {
+ MD_CPU_ARCHITECTURE_X86, // processor_architecture
+ 6, // processor_level
+ 0xd08, // processor_revision
+ 1, // number_of_processors
+ 0, // product_type
+ 0, // major_version
+ 0, // minor_version
+ 0, // build_number
+ MD_OS_LINUX, // platform_id
+ 0xdeadbeef, // csd_version_rva
+ 0x100, // suite_mask
+ 0, // reserved2
+ { // cpu
+ { // x86_cpu_info
+ { 0x756e6547, 0x49656e69, 0x6c65746e }, // vendor_id
+ 0x6d8, // version_information
+ 0xafe9fbff, // feature_information
+ 0xffffffff // amd_extended_cpu_features
+ }
+ }
+ };
+ String csd_version(dump, "Literally Linux");
+ SystemInfo system_info(dump, linux_x86, csd_version);
+
+ Module module(dump, 0xa90206ca83eb2852ULL, 0xada542bd,
+ module_name,
+ 0xb1054d2a,
+ 0x34571371,
+ fixed_file_info, // from synth_minidump_unittest_data.h
+ &cv_info, nullptr);
+
+ dump.Add(&module);
+ dump.Add(&module_name);
+ dump.Add(&cv_info);
+ dump.Add(&system_info);
+ dump.Add(&csd_version);
+ dump.Finish();
+
+ string contents;
+ ASSERT_TRUE(dump.GetContents(&contents));
+ istringstream minidump_stream(contents);
+ Minidump minidump(minidump_stream);
+ ASSERT_TRUE(minidump.Read());
+ ASSERT_EQ(2U, minidump.GetDirectoryEntryCount());
+
+ MinidumpModuleList *md_module_list = minidump.GetModuleList();
+ ASSERT_TRUE(md_module_list != NULL);
+ ASSERT_EQ(1U, md_module_list->module_count());
+
+ const MinidumpModule *md_module = md_module_list->GetModuleAtIndex(0);
+ ASSERT_TRUE(md_module != NULL);
+ // just the build_id, directly
+ ASSERT_EQ(
+ "5fa9cdb41053df1b86fab733b4df3738cea34a870102030405060708090a0b0c0d0e0f",
+ md_module->code_identifier());
+ // build_id truncated to GUID length and treated as such, with zero
+ // age appended.
+ ASSERT_EQ("B4CDA95F53101BDF86FAB733B4DF37380", md_module->debug_identifier());
+}
+
+TEST(Dump, OneSystemInfo) {
+ Dump dump(0, kLittleEndian);
+ String csd_version(dump, "Petulant Pierogi");
+ SystemInfo system_info(dump, SystemInfo::windows_x86, csd_version);
+
+ dump.Add(&system_info);
+ dump.Add(&csd_version);
+ dump.Finish();
+
+ string contents;
+ ASSERT_TRUE(dump.GetContents(&contents));
+ istringstream minidump_stream(contents);
+ Minidump minidump(minidump_stream);
+ ASSERT_TRUE(minidump.Read());
+ ASSERT_EQ(1U, minidump.GetDirectoryEntryCount());
+
+ const MDRawDirectory *dir = minidump.GetDirectoryEntryAtIndex(0);
+ ASSERT_TRUE(dir != NULL);
+ EXPECT_EQ((uint32_t) MD_SYSTEM_INFO_STREAM, dir->stream_type);
+
+ MinidumpSystemInfo *md_system_info = minidump.GetSystemInfo();
+ ASSERT_TRUE(md_system_info != NULL);
+ ASSERT_EQ("windows", md_system_info->GetOS());
+ ASSERT_EQ("x86", md_system_info->GetCPU());
+ ASSERT_EQ("Petulant Pierogi", *md_system_info->GetCSDVersion());
+ ASSERT_EQ("GenuineIntel", *md_system_info->GetCPUVendor());
+}
+
+TEST(Dump, BigDump) {
+ Dump dump(0, kLittleEndian);
+
+ // A SystemInfo stream.
+ String csd_version(dump, "Munificent Macaque");
+ SystemInfo system_info(dump, SystemInfo::windows_x86, csd_version);
+ dump.Add(&csd_version);
+ dump.Add(&system_info);
+
+ // Five threads!
+ Memory stack0(dump, 0x70b9ebfc);
+ stack0.Append("stack for thread zero");
+ MDRawContextX86 raw_context0;
+ raw_context0.context_flags = MD_CONTEXT_X86_INTEGER;
+ raw_context0.eip = 0xaf0709e4;
+ Context context0(dump, raw_context0);
+ Thread thread0(dump, 0xbbef4432, stack0, context0,
+ 0xd0377e7b, 0xdb8eb0cf, 0xd73bc314, 0x09d357bac7f9a163ULL);
+ dump.Add(&stack0);
+ dump.Add(&context0);
+ dump.Add(&thread0);
+
+ Memory stack1(dump, 0xf988cc45);
+ stack1.Append("stack for thread one");
+ MDRawContextX86 raw_context1;
+ raw_context1.context_flags = MD_CONTEXT_X86_INTEGER;
+ raw_context1.eip = 0xe4f56f81;
+ Context context1(dump, raw_context1);
+ Thread thread1(dump, 0x657c3f58, stack1, context1,
+ 0xa68fa182, 0x6f3cf8dd, 0xe3a78ccf, 0x78cc84775e4534bbULL);
+ dump.Add(&stack1);
+ dump.Add(&context1);
+ dump.Add(&thread1);
+
+ Memory stack2(dump, 0xc8a92e7c);
+ stack2.Append("stack for thread two");
+ MDRawContextX86 raw_context2;
+ raw_context2.context_flags = MD_CONTEXT_X86_INTEGER;
+ raw_context2.eip = 0xb336a438;
+ Context context2(dump, raw_context2);
+ Thread thread2(dump, 0xdf4b8a71, stack2, context2,
+ 0x674c26b6, 0x445d7120, 0x7e700c56, 0xd89bf778e7793e17ULL);
+ dump.Add(&stack2);
+ dump.Add(&context2);
+ dump.Add(&thread2);
+
+ Memory stack3(dump, 0x36d08e08);
+ stack3.Append("stack for thread three");
+ MDRawContextX86 raw_context3;
+ raw_context3.context_flags = MD_CONTEXT_X86_INTEGER;
+ raw_context3.eip = 0xdf99a60c;
+ Context context3(dump, raw_context3);
+ Thread thread3(dump, 0x86e6c341, stack3, context3,
+ 0x32dc5c55, 0x17a2aba8, 0xe0cc75e7, 0xa46393994dae83aeULL);
+ dump.Add(&stack3);
+ dump.Add(&context3);
+ dump.Add(&thread3);
+
+ Memory stack4(dump, 0x1e0ab4fa);
+ stack4.Append("stack for thread four");
+ MDRawContextX86 raw_context4;
+ raw_context4.context_flags = MD_CONTEXT_X86_INTEGER;
+ raw_context4.eip = 0xaa646267;
+ Context context4(dump, raw_context4);
+ Thread thread4(dump, 0x261a28d4, stack4, context4,
+ 0x6ebd389e, 0xa0cd4759, 0x30168846, 0x164f650a0cf39d35ULL);
+ dump.Add(&stack4);
+ dump.Add(&context4);
+ dump.Add(&thread4);
+
+ // Three modules!
+ String module1_name(dump, "module one");
+ Module module1(dump, 0xeb77da57b5d4cbdaULL, 0x83cd5a37, module1_name);
+ dump.Add(&module1_name);
+ dump.Add(&module1);
+
+ String module2_name(dump, "module two");
+ Module module2(dump, 0x8675884adfe5ac90ULL, 0xb11e4ea3, module2_name);
+ dump.Add(&module2_name);
+ dump.Add(&module2);
+
+ String module3_name(dump, "module three");
+ Module module3(dump, 0x95fc1544da321b6cULL, 0x7c2bf081, module3_name);
+ dump.Add(&module3_name);
+ dump.Add(&module3);
+
+ // Unloaded modules!
+ uint64_t umodule1_base = 0xeb77da57b5d4cbdaULL;
+ uint32_t umodule1_size = 0x83cd5a37;
+ String umodule1_name(dump, "unloaded module one");
+ UnloadedModule unloaded_module1(dump, umodule1_base, umodule1_size,
+ umodule1_name);
+ dump.Add(&umodule1_name);
+ dump.Add(&unloaded_module1);
+
+ uint64_t umodule2_base = 0xeb77da57b5d4cbdaULL;
+ uint32_t umodule2_size = 0x83cd5a37;
+ String umodule2_name(dump, "unloaded module two");
+ UnloadedModule unloaded_module2(dump, umodule2_base, umodule2_size,
+ umodule2_name);
+ dump.Add(&umodule2_name);
+ dump.Add(&unloaded_module2);
+
+ uint64_t umodule3_base = 0xeb77da5839a20000ULL;
+ uint32_t umodule3_size = 0x83cd5a37;
+ String umodule3_name(dump, "unloaded module three");
+ UnloadedModule unloaded_module3(dump, umodule3_base, umodule3_size,
+ umodule3_name);
+ dump.Add(&umodule3_name);
+ dump.Add(&unloaded_module3);
+
+
+ // Add one more memory region, on top of the five stacks.
+ Memory memory5(dump, 0x61979e828040e564ULL);
+ memory5.Append("contents of memory 5");
+ dump.Add(&memory5);
+
+ dump.Finish();
+
+ string contents;
+ ASSERT_TRUE(dump.GetContents(&contents));
+ istringstream minidump_stream(contents);
+ Minidump minidump(minidump_stream);
+ ASSERT_TRUE(minidump.Read());
+ ASSERT_EQ(5U, minidump.GetDirectoryEntryCount());
+
+ // Check the threads.
+ MinidumpThreadList *thread_list = minidump.GetThreadList();
+ ASSERT_TRUE(thread_list != NULL);
+ ASSERT_EQ(5U, thread_list->thread_count());
+ uint32_t thread_id;
+ ASSERT_TRUE(thread_list->GetThreadAtIndex(0)->GetThreadID(&thread_id));
+ ASSERT_EQ(0xbbef4432U, thread_id);
+ ASSERT_EQ(0x70b9ebfcU,
+ thread_list->GetThreadAtIndex(0)->GetMemory()->GetBase());
+ ASSERT_EQ(0xaf0709e4U,
+ thread_list->GetThreadAtIndex(0)->GetContext()->GetContextX86()
+ ->eip);
+
+ ASSERT_TRUE(thread_list->GetThreadAtIndex(1)->GetThreadID(&thread_id));
+ ASSERT_EQ(0x657c3f58U, thread_id);
+ ASSERT_EQ(0xf988cc45U,
+ thread_list->GetThreadAtIndex(1)->GetMemory()->GetBase());
+ ASSERT_EQ(0xe4f56f81U,
+ thread_list->GetThreadAtIndex(1)->GetContext()->GetContextX86()
+ ->eip);
+
+ ASSERT_TRUE(thread_list->GetThreadAtIndex(2)->GetThreadID(&thread_id));
+ ASSERT_EQ(0xdf4b8a71U, thread_id);
+ ASSERT_EQ(0xc8a92e7cU,
+ thread_list->GetThreadAtIndex(2)->GetMemory()->GetBase());
+ ASSERT_EQ(0xb336a438U,
+ thread_list->GetThreadAtIndex(2)->GetContext()->GetContextX86()
+ ->eip);
+
+ ASSERT_TRUE(thread_list->GetThreadAtIndex(3)->GetThreadID(&thread_id));
+ ASSERT_EQ(0x86e6c341U, thread_id);
+ ASSERT_EQ(0x36d08e08U,
+ thread_list->GetThreadAtIndex(3)->GetMemory()->GetBase());
+ ASSERT_EQ(0xdf99a60cU,
+ thread_list->GetThreadAtIndex(3)->GetContext()->GetContextX86()
+ ->eip);
+
+ ASSERT_TRUE(thread_list->GetThreadAtIndex(4)->GetThreadID(&thread_id));
+ ASSERT_EQ(0x261a28d4U, thread_id);
+ ASSERT_EQ(0x1e0ab4faU,
+ thread_list->GetThreadAtIndex(4)->GetMemory()->GetBase());
+ ASSERT_EQ(0xaa646267U,
+ thread_list->GetThreadAtIndex(4)->GetContext()->GetContextX86()
+ ->eip);
+
+ // Check the modules.
+ MinidumpModuleList *md_module_list = minidump.GetModuleList();
+ ASSERT_TRUE(md_module_list != NULL);
+ ASSERT_EQ(3U, md_module_list->module_count());
+ EXPECT_EQ(0xeb77da57b5d4cbdaULL,
+ md_module_list->GetModuleAtIndex(0)->base_address());
+ EXPECT_EQ(0x8675884adfe5ac90ULL,
+ md_module_list->GetModuleAtIndex(1)->base_address());
+ EXPECT_EQ(0x95fc1544da321b6cULL,
+ md_module_list->GetModuleAtIndex(2)->base_address());
+
+ // Check unloaded modules
+ MinidumpUnloadedModuleList *md_unloaded_module_list =
+ minidump.GetUnloadedModuleList();
+ ASSERT_TRUE(md_unloaded_module_list != NULL);
+ ASSERT_EQ(3U, md_unloaded_module_list->module_count());
+ EXPECT_EQ(umodule1_base,
+ md_unloaded_module_list->GetModuleAtIndex(0)->base_address());
+ EXPECT_EQ(umodule2_base,
+ md_unloaded_module_list->GetModuleAtIndex(1)->base_address());
+ EXPECT_EQ(umodule3_base,
+ md_unloaded_module_list->GetModuleAtIndex(2)->base_address());
+
+ const MinidumpUnloadedModule *umodule =
+ md_unloaded_module_list->GetModuleForAddress(
+ umodule1_base + umodule1_size / 2);
+ EXPECT_EQ(umodule1_base, umodule->base_address());
+
+ umodule = md_unloaded_module_list->GetModuleAtSequence(0);
+ EXPECT_EQ(umodule1_base, umodule->base_address());
+
+ EXPECT_EQ(NULL, md_unloaded_module_list->GetMainModule());
+
+}
+
+TEST(Dump, OneMemoryInfo) {
+ Dump dump(0, kBigEndian);
+ Stream stream(dump, MD_MEMORY_INFO_LIST_STREAM);
+
+ // Add the MDRawMemoryInfoList header.
+ const uint64_t kNumberOfEntries = 1;
+ stream.D32(sizeof(MDRawMemoryInfoList)) // size_of_header
+ .D32(sizeof(MDRawMemoryInfo)) // size_of_entry
+ .D64(kNumberOfEntries); // number_of_entries
+
+
+ // Now add a MDRawMemoryInfo entry.
+ const uint64_t kBaseAddress = 0x1000;
+ const uint64_t kRegionSize = 0x2000;
+ stream.D64(kBaseAddress) // base_address
+ .D64(kBaseAddress) // allocation_base
+ .D32(MD_MEMORY_PROTECT_EXECUTE_READWRITE) // allocation_protection
+ .D32(0) // __alignment1
+ .D64(kRegionSize) // region_size
+ .D32(MD_MEMORY_STATE_COMMIT) // state
+ .D32(MD_MEMORY_PROTECT_EXECUTE_READWRITE) // protection
+ .D32(MD_MEMORY_TYPE_PRIVATE) // type
+ .D32(0); // __alignment2
+
+ dump.Add(&stream);
+ dump.Finish();
+
+ string contents;
+ ASSERT_TRUE(dump.GetContents(&contents));
+ istringstream minidump_stream(contents);
+ Minidump minidump(minidump_stream);
+ ASSERT_TRUE(minidump.Read());
+ ASSERT_EQ(1U, minidump.GetDirectoryEntryCount());
+
+ const MDRawDirectory *dir = minidump.GetDirectoryEntryAtIndex(0);
+ ASSERT_TRUE(dir != NULL);
+ EXPECT_EQ((uint32_t) MD_MEMORY_INFO_LIST_STREAM, dir->stream_type);
+
+ MinidumpMemoryInfoList *info_list = minidump.GetMemoryInfoList();
+ ASSERT_TRUE(info_list != NULL);
+ ASSERT_EQ(1U, info_list->info_count());
+
+ const MinidumpMemoryInfo *info1 = info_list->GetMemoryInfoAtIndex(0);
+ ASSERT_EQ(kBaseAddress, info1->GetBase());
+ ASSERT_EQ(kRegionSize, info1->GetSize());
+ ASSERT_TRUE(info1->IsExecutable());
+ ASSERT_TRUE(info1->IsWritable());
+
+ // Should get back the same memory region here.
+ const MinidumpMemoryInfo *info2 =
+ info_list->GetMemoryInfoForAddress(kBaseAddress + kRegionSize / 2);
+ ASSERT_EQ(kBaseAddress, info2->GetBase());
+ ASSERT_EQ(kRegionSize, info2->GetSize());
+}
+
+TEST(Dump, OneExceptionX86) {
+ Dump dump(0, kLittleEndian);
+
+ MDRawContextX86 raw_context;
+ raw_context.context_flags = MD_CONTEXT_X86_INTEGER | MD_CONTEXT_X86_CONTROL;
+ raw_context.edi = 0x3ecba80d;
+ raw_context.esi = 0x382583b9;
+ raw_context.ebx = 0x7fccc03f;
+ raw_context.edx = 0xf62f8ec2;
+ raw_context.ecx = 0x46a6a6a8;
+ raw_context.eax = 0x6a5025e2;
+ raw_context.ebp = 0xd9fabb4a;
+ raw_context.eip = 0x6913f540;
+ raw_context.cs = 0xbffe6eda;
+ raw_context.eflags = 0xb2ce1e2d;
+ raw_context.esp = 0x659caaa4;
+ raw_context.ss = 0x2e951ef7;
+ Context context(dump, raw_context);
+
+ Exception exception(dump, context,
+ 0x1234abcd, // thread id
+ 0xdcba4321, // exception code
+ 0xf0e0d0c0, // exception flags
+ 0x0919a9b9c9d9e9f9ULL); // exception address
+
+ dump.Add(&context);
+ dump.Add(&exception);
+ dump.Finish();
+
+ string contents;
+ ASSERT_TRUE(dump.GetContents(&contents));
+
+ istringstream minidump_stream(contents);
+ Minidump minidump(minidump_stream);
+ ASSERT_TRUE(minidump.Read());
+ ASSERT_EQ(1U, minidump.GetDirectoryEntryCount());
+
+ MinidumpException *md_exception = minidump.GetException();
+ ASSERT_TRUE(md_exception != NULL);
+
+ uint32_t thread_id;
+ ASSERT_TRUE(md_exception->GetThreadID(&thread_id));
+ ASSERT_EQ(0x1234abcdU, thread_id);
+
+ const MDRawExceptionStream* raw_exception = md_exception->exception();
+ ASSERT_TRUE(raw_exception != NULL);
+ EXPECT_EQ(0xdcba4321, raw_exception->exception_record.exception_code);
+ EXPECT_EQ(0xf0e0d0c0, raw_exception->exception_record.exception_flags);
+ EXPECT_EQ(0x0919a9b9c9d9e9f9ULL,
+ raw_exception->exception_record.exception_address);
+
+ MinidumpContext *md_context = md_exception->GetContext();
+ ASSERT_TRUE(md_context != NULL);
+ ASSERT_EQ((uint32_t) MD_CONTEXT_X86, md_context->GetContextCPU());
+ const MDRawContextX86 *md_raw_context = md_context->GetContextX86();
+ ASSERT_TRUE(md_raw_context != NULL);
+ ASSERT_EQ((uint32_t) (MD_CONTEXT_X86_INTEGER | MD_CONTEXT_X86_CONTROL),
+ (md_raw_context->context_flags
+ & (MD_CONTEXT_X86_INTEGER | MD_CONTEXT_X86_CONTROL)));
+ EXPECT_EQ(0x3ecba80dU, raw_context.edi);
+ EXPECT_EQ(0x382583b9U, raw_context.esi);
+ EXPECT_EQ(0x7fccc03fU, raw_context.ebx);
+ EXPECT_EQ(0xf62f8ec2U, raw_context.edx);
+ EXPECT_EQ(0x46a6a6a8U, raw_context.ecx);
+ EXPECT_EQ(0x6a5025e2U, raw_context.eax);
+ EXPECT_EQ(0xd9fabb4aU, raw_context.ebp);
+ EXPECT_EQ(0x6913f540U, raw_context.eip);
+ EXPECT_EQ(0xbffe6edaU, raw_context.cs);
+ EXPECT_EQ(0xb2ce1e2dU, raw_context.eflags);
+ EXPECT_EQ(0x659caaa4U, raw_context.esp);
+ EXPECT_EQ(0x2e951ef7U, raw_context.ss);
+}
+
+TEST(Dump, OneExceptionX86XState) {
+ Dump dump(0, kLittleEndian);
+
+ MDRawContextX86 raw_context;
+ raw_context.context_flags = MD_CONTEXT_X86_INTEGER |
+ MD_CONTEXT_X86_CONTROL | MD_CONTEXT_X86_XSTATE;
+ raw_context.edi = 0x3ecba80d;
+ raw_context.esi = 0x382583b9;
+ raw_context.ebx = 0x7fccc03f;
+ raw_context.edx = 0xf62f8ec2;
+ raw_context.ecx = 0x46a6a6a8;
+ raw_context.eax = 0x6a5025e2;
+ raw_context.ebp = 0xd9fabb4a;
+ raw_context.eip = 0x6913f540;
+ raw_context.cs = 0xbffe6eda;
+ raw_context.eflags = 0xb2ce1e2d;
+ raw_context.esp = 0x659caaa4;
+ raw_context.ss = 0x2e951ef7;
+ Context context(dump, raw_context);
+
+ Exception exception(dump, context,
+ 0x1234abcd, // thread id
+ 0xdcba4321, // exception code
+ 0xf0e0d0c0, // exception flags
+ 0x0919a9b9c9d9e9f9ULL); // exception address
+
+ dump.Add(&context);
+ dump.Add(&exception);
+ dump.Finish();
+
+ string contents;
+ ASSERT_TRUE(dump.GetContents(&contents));
+
+ istringstream minidump_stream(contents);
+ Minidump minidump(minidump_stream);
+ ASSERT_TRUE(minidump.Read());
+ ASSERT_EQ(1U, minidump.GetDirectoryEntryCount());
+
+ MinidumpException *md_exception = minidump.GetException();
+ ASSERT_TRUE(md_exception != NULL);
+
+ uint32_t thread_id;
+ ASSERT_TRUE(md_exception->GetThreadID(&thread_id));
+ ASSERT_EQ(0x1234abcdU, thread_id);
+
+ const MDRawExceptionStream* raw_exception = md_exception->exception();
+ ASSERT_TRUE(raw_exception != NULL);
+ EXPECT_EQ(0xdcba4321, raw_exception->exception_record.exception_code);
+ EXPECT_EQ(0xf0e0d0c0, raw_exception->exception_record.exception_flags);
+ EXPECT_EQ(0x0919a9b9c9d9e9f9ULL,
+ raw_exception->exception_record.exception_address);
+
+ MinidumpContext *md_context = md_exception->GetContext();
+ ASSERT_TRUE(md_context != NULL);
+ ASSERT_EQ((uint32_t) MD_CONTEXT_X86, md_context->GetContextCPU());
+ const MDRawContextX86 *md_raw_context = md_context->GetContextX86();
+ ASSERT_TRUE(md_raw_context != NULL);
+ ASSERT_EQ((uint32_t) (MD_CONTEXT_X86_INTEGER | MD_CONTEXT_X86_CONTROL),
+ (md_raw_context->context_flags
+ & (MD_CONTEXT_X86_INTEGER | MD_CONTEXT_X86_CONTROL)));
+ EXPECT_EQ(0x3ecba80dU, raw_context.edi);
+ EXPECT_EQ(0x382583b9U, raw_context.esi);
+ EXPECT_EQ(0x7fccc03fU, raw_context.ebx);
+ EXPECT_EQ(0xf62f8ec2U, raw_context.edx);
+ EXPECT_EQ(0x46a6a6a8U, raw_context.ecx);
+ EXPECT_EQ(0x6a5025e2U, raw_context.eax);
+ EXPECT_EQ(0xd9fabb4aU, raw_context.ebp);
+ EXPECT_EQ(0x6913f540U, raw_context.eip);
+ EXPECT_EQ(0xbffe6edaU, raw_context.cs);
+ EXPECT_EQ(0xb2ce1e2dU, raw_context.eflags);
+ EXPECT_EQ(0x659caaa4U, raw_context.esp);
+ EXPECT_EQ(0x2e951ef7U, raw_context.ss);
+}
+
+// Testing that the CPU type can be loaded from a system info stream when
+// the CPU flags are missing from the context_flags of an exception record
+TEST(Dump, OneExceptionX86NoCPUFlags) {
+ Dump dump(0, kLittleEndian);
+
+ MDRawContextX86 raw_context;
+ // Intentionally not setting CPU type in the context_flags
+ raw_context.context_flags = 0;
+ raw_context.edi = 0x3ecba80d;
+ raw_context.esi = 0x382583b9;
+ raw_context.ebx = 0x7fccc03f;
+ raw_context.edx = 0xf62f8ec2;
+ raw_context.ecx = 0x46a6a6a8;
+ raw_context.eax = 0x6a5025e2;
+ raw_context.ebp = 0xd9fabb4a;
+ raw_context.eip = 0x6913f540;
+ raw_context.cs = 0xbffe6eda;
+ raw_context.eflags = 0xb2ce1e2d;
+ raw_context.esp = 0x659caaa4;
+ raw_context.ss = 0x2e951ef7;
+ Context context(dump, raw_context);
+
+ Exception exception(dump, context,
+ 0x1234abcd, // thread id
+ 0xdcba4321, // exception code
+ 0xf0e0d0c0, // exception flags
+ 0x0919a9b9c9d9e9f9ULL); // exception address
+
+ dump.Add(&context);
+ dump.Add(&exception);
+
+ // Add system info. This is needed as an alternative source for CPU type
+ // information. Note, that the CPU flags were intentionally skipped from
+ // the context_flags and this alternative source is required.
+ String csd_version(dump, "Service Pack 2");
+ SystemInfo system_info(dump, SystemInfo::windows_x86, csd_version);
+ dump.Add(&system_info);
+ dump.Add(&csd_version);
+
+ dump.Finish();
+
+ string contents;
+ ASSERT_TRUE(dump.GetContents(&contents));
+
+ istringstream minidump_stream(contents);
+ Minidump minidump(minidump_stream);
+ ASSERT_TRUE(minidump.Read());
+ ASSERT_EQ(2U, minidump.GetDirectoryEntryCount());
+
+ MinidumpException *md_exception = minidump.GetException();
+ ASSERT_TRUE(md_exception != NULL);
+
+ uint32_t thread_id;
+ ASSERT_TRUE(md_exception->GetThreadID(&thread_id));
+ ASSERT_EQ(0x1234abcdU, thread_id);
+
+ const MDRawExceptionStream* raw_exception = md_exception->exception();
+ ASSERT_TRUE(raw_exception != NULL);
+ EXPECT_EQ(0xdcba4321, raw_exception->exception_record.exception_code);
+ EXPECT_EQ(0xf0e0d0c0, raw_exception->exception_record.exception_flags);
+ EXPECT_EQ(0x0919a9b9c9d9e9f9ULL,
+ raw_exception->exception_record.exception_address);
+
+ MinidumpContext *md_context = md_exception->GetContext();
+ ASSERT_TRUE(md_context != NULL);
+
+ ASSERT_EQ((uint32_t) MD_CONTEXT_X86, md_context->GetContextCPU());
+ const MDRawContextX86 *md_raw_context = md_context->GetContextX86();
+ ASSERT_TRUE(md_raw_context != NULL);
+
+ // Even though the CPU flags were missing from the context_flags, the
+ // GetContext call above is expected to load the missing CPU flags from the
+ // system info stream and set the CPU type bits in context_flags.
+ ASSERT_EQ((uint32_t) (MD_CONTEXT_X86), md_raw_context->context_flags);
+
+ EXPECT_EQ(0x3ecba80dU, raw_context.edi);
+ EXPECT_EQ(0x382583b9U, raw_context.esi);
+ EXPECT_EQ(0x7fccc03fU, raw_context.ebx);
+ EXPECT_EQ(0xf62f8ec2U, raw_context.edx);
+ EXPECT_EQ(0x46a6a6a8U, raw_context.ecx);
+ EXPECT_EQ(0x6a5025e2U, raw_context.eax);
+ EXPECT_EQ(0xd9fabb4aU, raw_context.ebp);
+ EXPECT_EQ(0x6913f540U, raw_context.eip);
+ EXPECT_EQ(0xbffe6edaU, raw_context.cs);
+ EXPECT_EQ(0xb2ce1e2dU, raw_context.eflags);
+ EXPECT_EQ(0x659caaa4U, raw_context.esp);
+ EXPECT_EQ(0x2e951ef7U, raw_context.ss);
+}
+
+// This test covers a scenario where a dump contains an exception but the
+// context record of the exception is missing the CPU type information in its
+// context_flags. The dump has no system info stream so it is imposible to
+// deduce the CPU type, hence the context record is unusable.
+TEST(Dump, OneExceptionX86NoCPUFlagsNoSystemInfo) {
+ Dump dump(0, kLittleEndian);
+
+ MDRawContextX86 raw_context;
+ // Intentionally not setting CPU type in the context_flags
+ raw_context.context_flags = 0;
+ raw_context.edi = 0x3ecba80d;
+ raw_context.esi = 0x382583b9;
+ raw_context.ebx = 0x7fccc03f;
+ raw_context.edx = 0xf62f8ec2;
+ raw_context.ecx = 0x46a6a6a8;
+ raw_context.eax = 0x6a5025e2;
+ raw_context.ebp = 0xd9fabb4a;
+ raw_context.eip = 0x6913f540;
+ raw_context.cs = 0xbffe6eda;
+ raw_context.eflags = 0xb2ce1e2d;
+ raw_context.esp = 0x659caaa4;
+ raw_context.ss = 0x2e951ef7;
+ Context context(dump, raw_context);
+
+ Exception exception(dump, context,
+ 0x1234abcd, // thread id
+ 0xdcba4321, // exception code
+ 0xf0e0d0c0, // exception flags
+ 0x0919a9b9c9d9e9f9ULL); // exception address
+
+ dump.Add(&context);
+ dump.Add(&exception);
+ dump.Finish();
+
+ string contents;
+ ASSERT_TRUE(dump.GetContents(&contents));
+
+ istringstream minidump_stream(contents);
+ Minidump minidump(minidump_stream);
+ ASSERT_TRUE(minidump.Read());
+ ASSERT_EQ(1U, minidump.GetDirectoryEntryCount());
+
+ MinidumpException *md_exception = minidump.GetException();
+ ASSERT_TRUE(md_exception != NULL);
+
+ uint32_t thread_id;
+ ASSERT_TRUE(md_exception->GetThreadID(&thread_id));
+ ASSERT_EQ(0x1234abcdU, thread_id);
+
+ const MDRawExceptionStream* raw_exception = md_exception->exception();
+ ASSERT_TRUE(raw_exception != NULL);
+ EXPECT_EQ(0xdcba4321, raw_exception->exception_record.exception_code);
+ EXPECT_EQ(0xf0e0d0c0, raw_exception->exception_record.exception_flags);
+ EXPECT_EQ(0x0919a9b9c9d9e9f9ULL,
+ raw_exception->exception_record.exception_address);
+
+ // The context record of the exception is unusable because the context_flags
+ // don't have CPU type information and at the same time the minidump lacks
+ // system info stream so it is impossible to deduce the CPU type.
+ MinidumpContext *md_context = md_exception->GetContext();
+ ASSERT_EQ(NULL, md_context);
+}
+
+TEST(Dump, OneExceptionARM) {
+ Dump dump(0, kLittleEndian);
+
+ MDRawContextARM raw_context;
+ raw_context.context_flags = MD_CONTEXT_ARM_INTEGER;
+ raw_context.iregs[0] = 0x3ecba80d;
+ raw_context.iregs[1] = 0x382583b9;
+ raw_context.iregs[2] = 0x7fccc03f;
+ raw_context.iregs[3] = 0xf62f8ec2;
+ raw_context.iregs[4] = 0x46a6a6a8;
+ raw_context.iregs[5] = 0x6a5025e2;
+ raw_context.iregs[6] = 0xd9fabb4a;
+ raw_context.iregs[7] = 0x6913f540;
+ raw_context.iregs[8] = 0xbffe6eda;
+ raw_context.iregs[9] = 0xb2ce1e2d;
+ raw_context.iregs[10] = 0x659caaa4;
+ raw_context.iregs[11] = 0xf0e0d0c0;
+ raw_context.iregs[12] = 0xa9b8c7d6;
+ raw_context.iregs[13] = 0x12345678;
+ raw_context.iregs[14] = 0xabcd1234;
+ raw_context.iregs[15] = 0x10203040;
+ raw_context.cpsr = 0x2e951ef7;
+ Context context(dump, raw_context);
+
+ Exception exception(dump, context,
+ 0x1234abcd, // thread id
+ 0xdcba4321, // exception code
+ 0xf0e0d0c0, // exception flags
+ 0x0919a9b9c9d9e9f9ULL); // exception address
+
+ dump.Add(&context);
+ dump.Add(&exception);
+ dump.Finish();
+
+ string contents;
+ ASSERT_TRUE(dump.GetContents(&contents));
+
+ istringstream minidump_stream(contents);
+ Minidump minidump(minidump_stream);
+ ASSERT_TRUE(minidump.Read());
+ ASSERT_EQ(1U, minidump.GetDirectoryEntryCount());
+
+ MinidumpException *md_exception = minidump.GetException();
+ ASSERT_TRUE(md_exception != NULL);
+
+ uint32_t thread_id;
+ ASSERT_TRUE(md_exception->GetThreadID(&thread_id));
+ ASSERT_EQ(0x1234abcdU, thread_id);
+
+ const MDRawExceptionStream* raw_exception = md_exception->exception();
+ ASSERT_TRUE(raw_exception != NULL);
+ EXPECT_EQ(0xdcba4321, raw_exception->exception_record.exception_code);
+ EXPECT_EQ(0xf0e0d0c0, raw_exception->exception_record.exception_flags);
+ EXPECT_EQ(0x0919a9b9c9d9e9f9ULL,
+ raw_exception->exception_record.exception_address);
+
+ MinidumpContext *md_context = md_exception->GetContext();
+ ASSERT_TRUE(md_context != NULL);
+ ASSERT_EQ((uint32_t) MD_CONTEXT_ARM, md_context->GetContextCPU());
+ const MDRawContextARM *md_raw_context = md_context->GetContextARM();
+ ASSERT_TRUE(md_raw_context != NULL);
+ ASSERT_EQ((uint32_t) MD_CONTEXT_ARM_INTEGER,
+ (md_raw_context->context_flags
+ & MD_CONTEXT_ARM_INTEGER));
+ EXPECT_EQ(0x3ecba80dU, raw_context.iregs[0]);
+ EXPECT_EQ(0x382583b9U, raw_context.iregs[1]);
+ EXPECT_EQ(0x7fccc03fU, raw_context.iregs[2]);
+ EXPECT_EQ(0xf62f8ec2U, raw_context.iregs[3]);
+ EXPECT_EQ(0x46a6a6a8U, raw_context.iregs[4]);
+ EXPECT_EQ(0x6a5025e2U, raw_context.iregs[5]);
+ EXPECT_EQ(0xd9fabb4aU, raw_context.iregs[6]);
+ EXPECT_EQ(0x6913f540U, raw_context.iregs[7]);
+ EXPECT_EQ(0xbffe6edaU, raw_context.iregs[8]);
+ EXPECT_EQ(0xb2ce1e2dU, raw_context.iregs[9]);
+ EXPECT_EQ(0x659caaa4U, raw_context.iregs[10]);
+ EXPECT_EQ(0xf0e0d0c0U, raw_context.iregs[11]);
+ EXPECT_EQ(0xa9b8c7d6U, raw_context.iregs[12]);
+ EXPECT_EQ(0x12345678U, raw_context.iregs[13]);
+ EXPECT_EQ(0xabcd1234U, raw_context.iregs[14]);
+ EXPECT_EQ(0x10203040U, raw_context.iregs[15]);
+ EXPECT_EQ(0x2e951ef7U, raw_context.cpsr);
+}
+
+TEST(Dump, OneExceptionARMOldFlags) {
+ Dump dump(0, kLittleEndian);
+
+ MDRawContextARM raw_context;
+ // MD_CONTEXT_ARM_INTEGER, but with _OLD
+ raw_context.context_flags = MD_CONTEXT_ARM_OLD | 0x00000002;
+ raw_context.iregs[0] = 0x3ecba80d;
+ raw_context.iregs[1] = 0x382583b9;
+ raw_context.iregs[2] = 0x7fccc03f;
+ raw_context.iregs[3] = 0xf62f8ec2;
+ raw_context.iregs[4] = 0x46a6a6a8;
+ raw_context.iregs[5] = 0x6a5025e2;
+ raw_context.iregs[6] = 0xd9fabb4a;
+ raw_context.iregs[7] = 0x6913f540;
+ raw_context.iregs[8] = 0xbffe6eda;
+ raw_context.iregs[9] = 0xb2ce1e2d;
+ raw_context.iregs[10] = 0x659caaa4;
+ raw_context.iregs[11] = 0xf0e0d0c0;
+ raw_context.iregs[12] = 0xa9b8c7d6;
+ raw_context.iregs[13] = 0x12345678;
+ raw_context.iregs[14] = 0xabcd1234;
+ raw_context.iregs[15] = 0x10203040;
+ raw_context.cpsr = 0x2e951ef7;
+ Context context(dump, raw_context);
+
+ Exception exception(dump, context,
+ 0x1234abcd, // thread id
+ 0xdcba4321, // exception code
+ 0xf0e0d0c0, // exception flags
+ 0x0919a9b9c9d9e9f9ULL); // exception address
+
+ dump.Add(&context);
+ dump.Add(&exception);
+ dump.Finish();
+
+ string contents;
+ ASSERT_TRUE(dump.GetContents(&contents));
+
+ istringstream minidump_stream(contents);
+ Minidump minidump(minidump_stream);
+ ASSERT_TRUE(minidump.Read());
+ ASSERT_EQ(1U, minidump.GetDirectoryEntryCount());
+
+ MinidumpException *md_exception = minidump.GetException();
+ ASSERT_TRUE(md_exception != NULL);
+
+ uint32_t thread_id;
+ ASSERT_TRUE(md_exception->GetThreadID(&thread_id));
+ ASSERT_EQ(0x1234abcdU, thread_id);
+
+ const MDRawExceptionStream* raw_exception = md_exception->exception();
+ ASSERT_TRUE(raw_exception != NULL);
+ EXPECT_EQ(0xdcba4321, raw_exception->exception_record.exception_code);
+ EXPECT_EQ(0xf0e0d0c0, raw_exception->exception_record.exception_flags);
+ EXPECT_EQ(0x0919a9b9c9d9e9f9ULL,
+ raw_exception->exception_record.exception_address);
+
+ MinidumpContext *md_context = md_exception->GetContext();
+ ASSERT_TRUE(md_context != NULL);
+ ASSERT_EQ((uint32_t) MD_CONTEXT_ARM, md_context->GetContextCPU());
+ const MDRawContextARM *md_raw_context = md_context->GetContextARM();
+ ASSERT_TRUE(md_raw_context != NULL);
+ ASSERT_EQ((uint32_t) MD_CONTEXT_ARM_INTEGER,
+ (md_raw_context->context_flags
+ & MD_CONTEXT_ARM_INTEGER));
+ EXPECT_EQ(0x3ecba80dU, raw_context.iregs[0]);
+ EXPECT_EQ(0x382583b9U, raw_context.iregs[1]);
+ EXPECT_EQ(0x7fccc03fU, raw_context.iregs[2]);
+ EXPECT_EQ(0xf62f8ec2U, raw_context.iregs[3]);
+ EXPECT_EQ(0x46a6a6a8U, raw_context.iregs[4]);
+ EXPECT_EQ(0x6a5025e2U, raw_context.iregs[5]);
+ EXPECT_EQ(0xd9fabb4aU, raw_context.iregs[6]);
+ EXPECT_EQ(0x6913f540U, raw_context.iregs[7]);
+ EXPECT_EQ(0xbffe6edaU, raw_context.iregs[8]);
+ EXPECT_EQ(0xb2ce1e2dU, raw_context.iregs[9]);
+ EXPECT_EQ(0x659caaa4U, raw_context.iregs[10]);
+ EXPECT_EQ(0xf0e0d0c0U, raw_context.iregs[11]);
+ EXPECT_EQ(0xa9b8c7d6U, raw_context.iregs[12]);
+ EXPECT_EQ(0x12345678U, raw_context.iregs[13]);
+ EXPECT_EQ(0xabcd1234U, raw_context.iregs[14]);
+ EXPECT_EQ(0x10203040U, raw_context.iregs[15]);
+ EXPECT_EQ(0x2e951ef7U, raw_context.cpsr);
+}
+
+TEST(Dump, OneExceptionMIPS) {
+ Dump dump(0, kLittleEndian);
+
+ MDRawContextMIPS raw_context;
+ raw_context.context_flags = MD_CONTEXT_MIPS_INTEGER;
+ raw_context.iregs[0] = 0x3ecba80d;
+ raw_context.iregs[1] = 0x382583b9;
+ raw_context.iregs[2] = 0x7fccc03f;
+ raw_context.iregs[3] = 0xf62f8ec2;
+ raw_context.iregs[4] = 0x46a6a6a8;
+ raw_context.iregs[5] = 0x6a5025e2;
+ raw_context.iregs[6] = 0xd9fabb4a;
+ raw_context.iregs[7] = 0x6913f540;
+ raw_context.iregs[8] = 0xbffe6eda;
+ raw_context.iregs[9] = 0xb2ce1e2d;
+ raw_context.iregs[10] = 0x659caaa4;
+ raw_context.iregs[11] = 0xf0e0d0c0;
+ raw_context.iregs[12] = 0xa9b8c7d6;
+ raw_context.iregs[13] = 0x12345678;
+ raw_context.iregs[14] = 0xabcd1234;
+ raw_context.iregs[15] = 0x10203040;
+ raw_context.iregs[16] = 0xa80d3ecb;
+ raw_context.iregs[17] = 0x83b93825;
+ raw_context.iregs[18] = 0xc03f7fcc;
+ raw_context.iregs[19] = 0x8ec2f62f;
+ raw_context.iregs[20] = 0xa6a846a6;
+ raw_context.iregs[21] = 0x25e26a50;
+ raw_context.iregs[22] = 0xbb4ad9fa;
+ raw_context.iregs[23] = 0xf5406913;
+ raw_context.iregs[24] = 0x6edabffe;
+ raw_context.iregs[25] = 0x1e2db2ce;
+ raw_context.iregs[26] = 0xaaa4659c;
+ raw_context.iregs[27] = 0xd0c0f0e0;
+ raw_context.iregs[28] = 0xc7d6a9b8;
+ raw_context.iregs[29] = 0x56781234;
+ raw_context.iregs[30] = 0x1234abcd;
+ raw_context.iregs[31] = 0x30401020;
+
+ Context context(dump, raw_context);
+
+ Exception exception(dump, context,
+ 0x1234abcd, // Thread id.
+ 0xdcba4321, // Exception code.
+ 0xf0e0d0c0, // Exception flags.
+ 0x0919a9b9); // Exception address.
+
+ dump.Add(&context);
+ dump.Add(&exception);
+ dump.Finish();
+
+ string contents;
+ ASSERT_TRUE(dump.GetContents(&contents));
+
+ istringstream minidump_stream(contents);
+ Minidump minidump(minidump_stream);
+ ASSERT_TRUE(minidump.Read());
+ ASSERT_EQ(1U, minidump.GetDirectoryEntryCount());
+
+ MinidumpException *md_exception = minidump.GetException();
+ ASSERT_TRUE(md_exception != NULL);
+
+ uint32_t thread_id;
+ ASSERT_TRUE(md_exception->GetThreadID(&thread_id));
+ ASSERT_EQ(0x1234abcdU, thread_id);
+
+ const MDRawExceptionStream* raw_exception = md_exception->exception();
+ ASSERT_TRUE(raw_exception != NULL);
+ EXPECT_EQ(0xdcba4321, raw_exception->exception_record.exception_code);
+ EXPECT_EQ(0xf0e0d0c0, raw_exception->exception_record.exception_flags);
+ EXPECT_EQ(0x0919a9b9U,
+ raw_exception->exception_record.exception_address);
+
+ MinidumpContext* md_context = md_exception->GetContext();
+ ASSERT_TRUE(md_context != NULL);
+ ASSERT_EQ((uint32_t) MD_CONTEXT_MIPS, md_context->GetContextCPU());
+ const MDRawContextMIPS* md_raw_context = md_context->GetContextMIPS();
+ ASSERT_TRUE(md_raw_context != NULL);
+ ASSERT_EQ((uint32_t) MD_CONTEXT_MIPS_INTEGER,
+ (md_raw_context->context_flags & MD_CONTEXT_MIPS_INTEGER));
+ EXPECT_EQ(0x3ecba80dU, raw_context.iregs[0]);
+ EXPECT_EQ(0x382583b9U, raw_context.iregs[1]);
+ EXPECT_EQ(0x7fccc03fU, raw_context.iregs[2]);
+ EXPECT_EQ(0xf62f8ec2U, raw_context.iregs[3]);
+ EXPECT_EQ(0x46a6a6a8U, raw_context.iregs[4]);
+ EXPECT_EQ(0x6a5025e2U, raw_context.iregs[5]);
+ EXPECT_EQ(0xd9fabb4aU, raw_context.iregs[6]);
+ EXPECT_EQ(0x6913f540U, raw_context.iregs[7]);
+ EXPECT_EQ(0xbffe6edaU, raw_context.iregs[8]);
+ EXPECT_EQ(0xb2ce1e2dU, raw_context.iregs[9]);
+ EXPECT_EQ(0x659caaa4U, raw_context.iregs[10]);
+ EXPECT_EQ(0xf0e0d0c0U, raw_context.iregs[11]);
+ EXPECT_EQ(0xa9b8c7d6U, raw_context.iregs[12]);
+ EXPECT_EQ(0x12345678U, raw_context.iregs[13]);
+ EXPECT_EQ(0xabcd1234U, raw_context.iregs[14]);
+ EXPECT_EQ(0x10203040U, raw_context.iregs[15]);
+ EXPECT_EQ(0xa80d3ecbU, raw_context.iregs[16]);
+ EXPECT_EQ(0x83b93825U, raw_context.iregs[17]);
+ EXPECT_EQ(0xc03f7fccU, raw_context.iregs[18]);
+ EXPECT_EQ(0x8ec2f62fU, raw_context.iregs[19]);
+ EXPECT_EQ(0xa6a846a6U, raw_context.iregs[20]);
+ EXPECT_EQ(0x25e26a50U, raw_context.iregs[21]);
+ EXPECT_EQ(0xbb4ad9faU, raw_context.iregs[22]);
+ EXPECT_EQ(0xf5406913U, raw_context.iregs[23]);
+ EXPECT_EQ(0x6edabffeU, raw_context.iregs[24]);
+ EXPECT_EQ(0x1e2db2ceU, raw_context.iregs[25]);
+ EXPECT_EQ(0xaaa4659cU, raw_context.iregs[26]);
+ EXPECT_EQ(0xd0c0f0e0U, raw_context.iregs[27]);
+ EXPECT_EQ(0xc7d6a9b8U, raw_context.iregs[28]);
+ EXPECT_EQ(0x56781234U, raw_context.iregs[29]);
+ EXPECT_EQ(0x1234abcdU, raw_context.iregs[30]);
+ EXPECT_EQ(0x30401020U, raw_context.iregs[31]);
+}
+
+} // namespace
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/module_comparer.cc b/toolkit/crashreporter/google-breakpad/src/processor/module_comparer.cc
new file mode 100644
index 0000000000..025ab883a3
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/module_comparer.cc
@@ -0,0 +1,302 @@
+// 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.
+//
+// module_comparer.cc: ModuleComparer implementation.
+// See module_comparer.h for documentation.
+//
+// Author: lambxsy@google.com (Siyang Xie)
+
+#include "processor/module_comparer.h"
+
+#include <map>
+#include <string>
+
+#include "common/scoped_ptr.h"
+#include "processor/basic_code_module.h"
+#include "processor/logging.h"
+
+#define ASSERT_TRUE(condition) \
+ if (!(condition)) { \
+ BPLOG(ERROR) << "FAIL: " << #condition << " @ " \
+ << __FILE__ << ":" << __LINE__; \
+ return false; \
+ }
+
+#define ASSERT_FALSE(condition) ASSERT_TRUE(!(condition))
+
+namespace google_breakpad {
+
+bool ModuleComparer::Compare(const string &symbol_data) {
+ scoped_ptr<BasicModule> basic_module(new BasicModule("test_module"));
+ scoped_ptr<FastModule> fast_module(new FastModule("test_module"));
+
+ // Load symbol data into basic_module
+ scoped_array<char> buffer(new char[symbol_data.size() + 1]);
+ memcpy(buffer.get(), symbol_data.c_str(), symbol_data.size());
+ buffer.get()[symbol_data.size()] = '\0';
+ ASSERT_TRUE(basic_module->LoadMapFromMemory(buffer.get(),
+ symbol_data.size() + 1));
+ buffer.reset();
+
+ // Serialize BasicSourceLineResolver::Module.
+ unsigned int serialized_size = 0;
+ scoped_array<char> serialized_data(
+ serializer_.Serialize(*(basic_module.get()), &serialized_size));
+ ASSERT_TRUE(serialized_data.get());
+ BPLOG(INFO) << "Serialized size = " << serialized_size << " Bytes";
+
+ // Load FastSourceLineResolver::Module using serialized data.
+ ASSERT_TRUE(fast_module->LoadMapFromMemory(serialized_data.get(),
+ serialized_size));
+ ASSERT_TRUE(fast_module->IsCorrupt() == basic_module->IsCorrupt());
+
+ // Compare FastSourceLineResolver::Module with
+ // BasicSourceLineResolver::Module.
+ ASSERT_TRUE(CompareModule(basic_module.get(), fast_module.get()));
+
+ return true;
+}
+
+// Traversal the content of module and do comparison
+bool ModuleComparer::CompareModule(const BasicModule *basic_module,
+ const FastModule *fast_module) const {
+ // Compare name_.
+ ASSERT_TRUE(basic_module->name_ == fast_module->name_);
+
+ // Compare files_:
+ {
+ BasicModule::FileMap::const_iterator iter1 = basic_module->files_.begin();
+ FastModule::FileMap::iterator iter2 = fast_module->files_.begin();
+ while (iter1 != basic_module->files_.end()
+ && iter2 != fast_module->files_.end()) {
+ ASSERT_TRUE(iter1->first == iter2.GetKey());
+ string tmp(iter2.GetValuePtr());
+ ASSERT_TRUE(iter1->second == tmp);
+ ++iter1;
+ ++iter2;
+ }
+ ASSERT_TRUE(iter1 == basic_module->files_.end());
+ ASSERT_TRUE(iter2 == fast_module->files_.end());
+ }
+
+ // Compare functions_:
+ {
+ RangeMap<MemAddr, linked_ptr<BasicFunc> >::MapConstIterator iter1;
+ StaticRangeMap<MemAddr, FastFunc>::MapConstIterator iter2;
+ iter1 = basic_module->functions_.map_.begin();
+ iter2 = fast_module->functions_.map_.begin();
+ while (iter1 != basic_module->functions_.map_.end()
+ && iter2 != fast_module->functions_.map_.end()) {
+ ASSERT_TRUE(iter1->first == iter2.GetKey());
+ ASSERT_TRUE(iter1->second.base() == iter2.GetValuePtr()->base());
+ ASSERT_TRUE(CompareFunction(
+ iter1->second.entry().get(), iter2.GetValuePtr()->entryptr()));
+ ++iter1;
+ ++iter2;
+ }
+ ASSERT_TRUE(iter1 == basic_module->functions_.map_.end());
+ ASSERT_TRUE(iter2 == fast_module->functions_.map_.end());
+ }
+
+ // Compare public_symbols_:
+ {
+ AddressMap<MemAddr, linked_ptr<BasicPubSymbol> >::MapConstIterator iter1;
+ StaticAddressMap<MemAddr, FastPubSymbol>::MapConstIterator iter2;
+ iter1 = basic_module->public_symbols_.map_.begin();
+ iter2 = fast_module->public_symbols_.map_.begin();
+ while (iter1 != basic_module->public_symbols_.map_.end()
+ && iter2 != fast_module->public_symbols_.map_.end()) {
+ ASSERT_TRUE(iter1->first == iter2.GetKey());
+ ASSERT_TRUE(ComparePubSymbol(
+ iter1->second.get(), iter2.GetValuePtr()));
+ ++iter1;
+ ++iter2;
+ }
+ ASSERT_TRUE(iter1 == basic_module->public_symbols_.map_.end());
+ ASSERT_TRUE(iter2 == fast_module->public_symbols_.map_.end());
+ }
+
+ // Compare windows_frame_info_[]:
+ for (int i = 0; i < WindowsFrameInfo::STACK_INFO_LAST; ++i) {
+ ASSERT_TRUE(CompareCRM(&(basic_module->windows_frame_info_[i]),
+ &(fast_module->windows_frame_info_[i])));
+ }
+
+ // Compare cfi_initial_rules_:
+ {
+ RangeMap<MemAddr, string>::MapConstIterator iter1;
+ StaticRangeMap<MemAddr, char>::MapConstIterator iter2;
+ iter1 = basic_module->cfi_initial_rules_.map_.begin();
+ iter2 = fast_module->cfi_initial_rules_.map_.begin();
+ while (iter1 != basic_module->cfi_initial_rules_.map_.end()
+ && iter2 != fast_module->cfi_initial_rules_.map_.end()) {
+ ASSERT_TRUE(iter1->first == iter2.GetKey());
+ ASSERT_TRUE(iter1->second.base() == iter2.GetValuePtr()->base());
+ string tmp(iter2.GetValuePtr()->entryptr());
+ ASSERT_TRUE(iter1->second.entry() == tmp);
+ ++iter1;
+ ++iter2;
+ }
+ ASSERT_TRUE(iter1 == basic_module->cfi_initial_rules_.map_.end());
+ ASSERT_TRUE(iter2 == fast_module->cfi_initial_rules_.map_.end());
+ }
+
+ // Compare cfi_delta_rules_:
+ {
+ map<MemAddr, string>::const_iterator iter1;
+ StaticMap<MemAddr, char>::iterator iter2;
+ iter1 = basic_module->cfi_delta_rules_.begin();
+ iter2 = fast_module->cfi_delta_rules_.begin();
+ while (iter1 != basic_module->cfi_delta_rules_.end()
+ && iter2 != fast_module->cfi_delta_rules_.end()) {
+ ASSERT_TRUE(iter1->first == iter2.GetKey());
+ string tmp(iter2.GetValuePtr());
+ ASSERT_TRUE(iter1->second == tmp);
+ ++iter1;
+ ++iter2;
+ }
+ ASSERT_TRUE(iter1 == basic_module->cfi_delta_rules_.end());
+ ASSERT_TRUE(iter2 == fast_module->cfi_delta_rules_.end());
+ }
+
+ return true;
+}
+
+bool ModuleComparer::CompareFunction(const BasicFunc *basic_func,
+ const FastFunc *fast_func_raw) const {
+ FastFunc* fast_func = new FastFunc();
+ fast_func->CopyFrom(fast_func_raw);
+ ASSERT_TRUE(basic_func->name == fast_func->name);
+ ASSERT_TRUE(basic_func->address == fast_func->address);
+ ASSERT_TRUE(basic_func->size == fast_func->size);
+
+ // compare range map of lines:
+ RangeMap<MemAddr, linked_ptr<BasicLine> >::MapConstIterator iter1;
+ StaticRangeMap<MemAddr, FastLine>::MapConstIterator iter2;
+ iter1 = basic_func->lines.map_.begin();
+ iter2 = fast_func->lines.map_.begin();
+ while (iter1 != basic_func->lines.map_.end()
+ && iter2 != fast_func->lines.map_.end()) {
+ ASSERT_TRUE(iter1->first == iter2.GetKey());
+ ASSERT_TRUE(iter1->second.base() == iter2.GetValuePtr()->base());
+ ASSERT_TRUE(CompareLine(iter1->second.entry().get(),
+ iter2.GetValuePtr()->entryptr()));
+ ++iter1;
+ ++iter2;
+ }
+ ASSERT_TRUE(iter1 == basic_func->lines.map_.end());
+ ASSERT_TRUE(iter2 == fast_func->lines.map_.end());
+
+ delete fast_func;
+ return true;
+}
+
+bool ModuleComparer::CompareLine(const BasicLine *basic_line,
+ const FastLine *fast_line_raw) const {
+ FastLine *fast_line = new FastLine;
+ fast_line->CopyFrom(fast_line_raw);
+
+ ASSERT_TRUE(basic_line->address == fast_line->address);
+ ASSERT_TRUE(basic_line->size == fast_line->size);
+ ASSERT_TRUE(basic_line->source_file_id == fast_line->source_file_id);
+ ASSERT_TRUE(basic_line->line == fast_line->line);
+
+ delete fast_line;
+ return true;
+}
+
+bool ModuleComparer::ComparePubSymbol(const BasicPubSymbol* basic_ps,
+ const FastPubSymbol* fastps_raw) const {
+ FastPubSymbol *fast_ps = new FastPubSymbol;
+ fast_ps->CopyFrom(fastps_raw);
+ ASSERT_TRUE(basic_ps->name == fast_ps->name);
+ ASSERT_TRUE(basic_ps->address == fast_ps->address);
+ ASSERT_TRUE(basic_ps->parameter_size == fast_ps->parameter_size);
+ delete fast_ps;
+ return true;
+}
+
+bool ModuleComparer::CompareWFI(const WindowsFrameInfo& wfi1,
+ const WindowsFrameInfo& wfi2) const {
+ ASSERT_TRUE(wfi1.type_ == wfi2.type_);
+ ASSERT_TRUE(wfi1.valid == wfi2.valid);
+ ASSERT_TRUE(wfi1.prolog_size == wfi2.prolog_size);
+ ASSERT_TRUE(wfi1.epilog_size == wfi2.epilog_size);
+ ASSERT_TRUE(wfi1.parameter_size == wfi2.parameter_size);
+ ASSERT_TRUE(wfi1.saved_register_size == wfi2.saved_register_size);
+ ASSERT_TRUE(wfi1.local_size == wfi2.local_size);
+ ASSERT_TRUE(wfi1.max_stack_size == wfi2.max_stack_size);
+ ASSERT_TRUE(wfi1.allocates_base_pointer == wfi2.allocates_base_pointer);
+ ASSERT_TRUE(wfi1.program_string == wfi2.program_string);
+ return true;
+}
+
+// Compare ContainedRangeMap
+bool ModuleComparer::CompareCRM(
+ const ContainedRangeMap<MemAddr, linked_ptr<WFI> >* basic_crm,
+ const StaticContainedRangeMap<MemAddr, char>* fast_crm) const {
+ ASSERT_TRUE(basic_crm->base_ == fast_crm->base_);
+
+ if (!basic_crm->entry_.get() || !fast_crm->entry_ptr_) {
+ // empty entry:
+ ASSERT_TRUE(!basic_crm->entry_.get() && !fast_crm->entry_ptr_);
+ } else {
+ WFI newwfi;
+ newwfi.CopyFrom(fast_resolver_->CopyWFI(fast_crm->entry_ptr_));
+ ASSERT_TRUE(CompareWFI(*(basic_crm->entry_.get()), newwfi));
+ }
+
+ if ((!basic_crm->map_ || basic_crm->map_->empty())
+ || fast_crm->map_.empty()) {
+ ASSERT_TRUE((!basic_crm->map_ || basic_crm->map_->empty())
+ && fast_crm->map_.empty());
+ } else {
+ ContainedRangeMap<MemAddr, linked_ptr<WFI> >::MapConstIterator iter1;
+ StaticContainedRangeMap<MemAddr, char>::MapConstIterator iter2;
+ iter1 = basic_crm->map_->begin();
+ iter2 = fast_crm->map_.begin();
+ while (iter1 != basic_crm->map_->end()
+ && iter2 != fast_crm->map_.end()) {
+ ASSERT_TRUE(iter1->first == iter2.GetKey());
+ StaticContainedRangeMap<MemAddr, char> *child =
+ new StaticContainedRangeMap<MemAddr, char>(
+ reinterpret_cast<const char*>(iter2.GetValuePtr()));
+ ASSERT_TRUE(CompareCRM(iter1->second, child));
+ delete child;
+ ++iter1;
+ ++iter2;
+ }
+ ASSERT_TRUE(iter1 == basic_crm->map_->end());
+ ASSERT_TRUE(iter2 == fast_crm->map_.end());
+ }
+
+ return true;
+}
+
+} // namespace google_breakpad
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/module_comparer.h b/toolkit/crashreporter/google-breakpad/src/processor/module_comparer.h
new file mode 100644
index 0000000000..fcbd51775f
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/module_comparer.h
@@ -0,0 +1,98 @@
+// 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.
+//
+// module_comparer.h: ModuleComparer reads a string format of symbol file, and
+// loads the symbol into both BasicSourceLineResolver::Module and
+// FastSourceLineResolve::Module. It then traverses both Modules and compare
+// the content of data to verify the correctness of new fast module.
+// ModuleCompare class is a tool to verify correctness of a loaded
+// FastSourceLineResolver::Module instance, i.e., in-memory representation of
+// parsed symbol. ModuleComparer class should be used for testing purpose only,
+// e.g., in fast_source_line_resolver_unittest.
+//
+// Author: lambxsy@google.com (Siyang Xie)
+
+#ifndef PROCESSOR_MODULE_COMPARER_H__
+#define PROCESSOR_MODULE_COMPARER_H__
+
+#include <string>
+
+#include "processor/basic_source_line_resolver_types.h"
+#include "processor/fast_source_line_resolver_types.h"
+#include "processor/module_serializer.h"
+#include "processor/windows_frame_info.h"
+
+namespace google_breakpad {
+
+class ModuleComparer {
+ public:
+ ModuleComparer(): fast_resolver_(new FastSourceLineResolver),
+ basic_resolver_(new BasicSourceLineResolver) { }
+ ~ModuleComparer() {
+ delete fast_resolver_;
+ delete basic_resolver_;
+ }
+
+ // BasicSourceLineResolver loads its module using the symbol data,
+ // ModuleSerializer serialize the loaded module into a memory chunk,
+ // FastSourceLineResolver loads its module using the serialized memory chunk,
+ // Then, traverse both modules together and compare underlying data
+ // return true if both modules contain exactly same data.
+ bool Compare(const string &symbol_data);
+
+ private:
+ typedef BasicSourceLineResolver::Module BasicModule;
+ typedef FastSourceLineResolver::Module FastModule;
+ typedef BasicSourceLineResolver::Function BasicFunc;
+ typedef FastSourceLineResolver::Function FastFunc;
+ typedef BasicSourceLineResolver::Line BasicLine;
+ typedef FastSourceLineResolver::Line FastLine;
+ typedef BasicSourceLineResolver::PublicSymbol BasicPubSymbol;
+ typedef FastSourceLineResolver::PublicSymbol FastPubSymbol;
+ typedef WindowsFrameInfo WFI;
+
+ bool CompareModule(const BasicModule *oldmodule,
+ const FastModule *newmodule) const;
+ bool CompareFunction(const BasicFunc *oldfunc, const FastFunc *newfunc) const;
+ bool CompareLine(const BasicLine *oldline, const FastLine *newline) const;
+ bool ComparePubSymbol(const BasicPubSymbol*, const FastPubSymbol*) const;
+ bool CompareWFI(const WindowsFrameInfo&, const WindowsFrameInfo&) const;
+
+ // Compare ContainedRangeMap
+ bool CompareCRM(const ContainedRangeMap<MemAddr, linked_ptr<WFI> >*,
+ const StaticContainedRangeMap<MemAddr, char>*) const;
+
+ FastSourceLineResolver *fast_resolver_;
+ BasicSourceLineResolver *basic_resolver_;
+ ModuleSerializer serializer_;
+};
+
+} // namespace google_breakpad
+
+#endif // PROCESSOR_MODULE_COMPARER_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/module_factory.h b/toolkit/crashreporter/google-breakpad/src/processor/module_factory.h
new file mode 100644
index 0000000000..7aa7caa59d
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/module_factory.h
@@ -0,0 +1,72 @@
+// 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.
+//
+// module_factory.h: ModuleFactory a factory that provides
+// an interface for creating a Module and deferring instantiation to subclasses
+// BasicModuleFactory and FastModuleFactory.
+
+// Author: Siyang Xie (lambxsy@google.com)
+
+#ifndef PROCESSOR_MODULE_FACTORY_H__
+#define PROCESSOR_MODULE_FACTORY_H__
+
+#include "processor/basic_source_line_resolver_types.h"
+#include "processor/fast_source_line_resolver_types.h"
+#include "processor/source_line_resolver_base_types.h"
+
+namespace google_breakpad {
+
+class ModuleFactory {
+ public:
+ virtual ~ModuleFactory() { };
+ virtual SourceLineResolverBase::Module* CreateModule(
+ const string &name) const = 0;
+};
+
+class BasicModuleFactory : public ModuleFactory {
+ public:
+ virtual ~BasicModuleFactory() { }
+ virtual BasicSourceLineResolver::Module* CreateModule(
+ const string &name) const {
+ return new BasicSourceLineResolver::Module(name);
+ }
+};
+
+class FastModuleFactory : public ModuleFactory {
+ public:
+ virtual ~FastModuleFactory() { }
+ virtual FastSourceLineResolver::Module* CreateModule(
+ const string &name) const {
+ return new FastSourceLineResolver::Module(name);
+ }
+};
+
+} // namespace google_breakpad
+
+#endif // PROCESSOR_MODULE_FACTORY_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/module_serializer.cc b/toolkit/crashreporter/google-breakpad/src/processor/module_serializer.cc
new file mode 100644
index 0000000000..6ac60c1fcf
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/module_serializer.cc
@@ -0,0 +1,207 @@
+// 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.
+//
+// module_serializer.cc: ModuleSerializer implementation.
+//
+// See module_serializer.h for documentation.
+//
+// Author: Siyang Xie (lambxsy@google.com)
+
+#include "processor/module_serializer.h"
+
+#include <map>
+#include <string>
+
+#include "processor/basic_code_module.h"
+#include "processor/logging.h"
+
+namespace google_breakpad {
+
+// Definition of static member variable in SimplerSerializer<Funcion>, which
+// is declared in file "simple_serializer-inl.h"
+RangeMapSerializer< MemAddr, linked_ptr<BasicSourceLineResolver::Line> >
+SimpleSerializer<BasicSourceLineResolver::Function>::range_map_serializer_;
+
+size_t ModuleSerializer::SizeOf(const BasicSourceLineResolver::Module &module) {
+ size_t total_size_alloc_ = 0;
+
+ // Size of the "is_corrupt" flag.
+ total_size_alloc_ += SimpleSerializer<bool>::SizeOf(module.is_corrupt_);
+
+ // Compute memory size for each map component in Module class.
+ int map_index = 0;
+ map_sizes_[map_index++] = files_serializer_.SizeOf(module.files_);
+ map_sizes_[map_index++] = functions_serializer_.SizeOf(module.functions_);
+ map_sizes_[map_index++] = pubsym_serializer_.SizeOf(module.public_symbols_);
+ for (int i = 0; i < WindowsFrameInfo::STACK_INFO_LAST; ++i)
+ map_sizes_[map_index++] =
+ wfi_serializer_.SizeOf(&(module.windows_frame_info_[i]));
+ map_sizes_[map_index++] = cfi_init_rules_serializer_.SizeOf(
+ module.cfi_initial_rules_);
+ map_sizes_[map_index++] = cfi_delta_rules_serializer_.SizeOf(
+ module.cfi_delta_rules_);
+
+ // Header size.
+ total_size_alloc_ += kNumberMaps_ * sizeof(uint32_t);
+
+ for (int i = 0; i < kNumberMaps_; ++i) {
+ total_size_alloc_ += map_sizes_[i];
+ }
+
+ // Extra one byte for null terminator for C-string copy safety.
+ total_size_alloc_ += SimpleSerializer<char>::SizeOf(0);
+
+ return total_size_alloc_;
+}
+
+char *ModuleSerializer::Write(const BasicSourceLineResolver::Module &module,
+ char *dest) {
+ // Write the is_corrupt flag.
+ dest = SimpleSerializer<bool>::Write(module.is_corrupt_, dest);
+ // Write header.
+ memcpy(dest, map_sizes_, kNumberMaps_ * sizeof(uint32_t));
+ dest += kNumberMaps_ * sizeof(uint32_t);
+ // Write each map.
+ dest = files_serializer_.Write(module.files_, dest);
+ dest = functions_serializer_.Write(module.functions_, dest);
+ dest = pubsym_serializer_.Write(module.public_symbols_, dest);
+ for (int i = 0; i < WindowsFrameInfo::STACK_INFO_LAST; ++i)
+ dest = wfi_serializer_.Write(&(module.windows_frame_info_[i]), dest);
+ dest = cfi_init_rules_serializer_.Write(module.cfi_initial_rules_, dest);
+ dest = cfi_delta_rules_serializer_.Write(module.cfi_delta_rules_, dest);
+ // Write a null terminator.
+ dest = SimpleSerializer<char>::Write(0, dest);
+ return dest;
+}
+
+char* ModuleSerializer::Serialize(
+ const BasicSourceLineResolver::Module &module, unsigned int *size) {
+ // Compute size of memory to allocate.
+ unsigned int size_to_alloc = SizeOf(module);
+
+ // Allocate memory for serialized data.
+ char *serialized_data = new char[size_to_alloc];
+ if (!serialized_data) {
+ BPLOG(ERROR) << "ModuleSerializer: memory allocation failed, "
+ << "size to alloc: " << size_to_alloc;
+ if (size) *size = 0;
+ return NULL;
+ }
+
+ // Write serialized data to allocated memory chunk.
+ char *end_address = Write(module, serialized_data);
+ // Verify the allocated memory size is equal to the size of data been written.
+ unsigned int size_written =
+ static_cast<unsigned int>(end_address - serialized_data);
+ if (size_to_alloc != size_written) {
+ BPLOG(ERROR) << "size_to_alloc differs from size_written: "
+ << size_to_alloc << " vs " << size_written;
+ }
+
+ // Set size and return the start address of memory chunk.
+ if (size)
+ *size = size_to_alloc;
+ return serialized_data;
+}
+
+bool ModuleSerializer::SerializeModuleAndLoadIntoFastResolver(
+ const BasicSourceLineResolver::ModuleMap::const_iterator &iter,
+ FastSourceLineResolver *fast_resolver) {
+ BPLOG(INFO) << "Converting symbol " << iter->first.c_str();
+
+ // Cast SourceLineResolverBase::Module* to BasicSourceLineResolver::Module*.
+ BasicSourceLineResolver::Module* basic_module =
+ dynamic_cast<BasicSourceLineResolver::Module*>(iter->second);
+
+ unsigned int size = 0;
+ scoped_array<char> symbol_data(Serialize(*basic_module, &size));
+ if (!symbol_data.get()) {
+ BPLOG(ERROR) << "Serialization failed for module: " << basic_module->name_;
+ return false;
+ }
+ BPLOG(INFO) << "Serialized Symbol Size " << size;
+
+ // Copy the data into string.
+ // Must pass string to LoadModuleUsingMapBuffer(), instead of passing char* to
+ // LoadModuleUsingMemoryBuffer(), becaused of data ownership/lifetime issue.
+ string symbol_data_string(symbol_data.get(), size);
+ symbol_data.reset();
+
+ scoped_ptr<CodeModule> code_module(
+ new BasicCodeModule(0, 0, iter->first, "", "", "", ""));
+
+ return fast_resolver->LoadModuleUsingMapBuffer(code_module.get(),
+ symbol_data_string);
+}
+
+void ModuleSerializer::ConvertAllModules(
+ const BasicSourceLineResolver *basic_resolver,
+ FastSourceLineResolver *fast_resolver) {
+ // Check for NULL pointer.
+ if (!basic_resolver || !fast_resolver)
+ return;
+
+ // Traverse module list in basic resolver.
+ BasicSourceLineResolver::ModuleMap::const_iterator iter;
+ iter = basic_resolver->modules_->begin();
+ for (; iter != basic_resolver->modules_->end(); ++iter)
+ SerializeModuleAndLoadIntoFastResolver(iter, fast_resolver);
+}
+
+bool ModuleSerializer::ConvertOneModule(
+ const string &moduleid,
+ const BasicSourceLineResolver *basic_resolver,
+ FastSourceLineResolver *fast_resolver) {
+ // Check for NULL pointer.
+ if (!basic_resolver || !fast_resolver)
+ return false;
+
+ BasicSourceLineResolver::ModuleMap::const_iterator iter;
+ iter = basic_resolver->modules_->find(moduleid);
+ if (iter == basic_resolver->modules_->end())
+ return false;
+
+ return SerializeModuleAndLoadIntoFastResolver(iter, fast_resolver);
+}
+
+char* ModuleSerializer::SerializeSymbolFileData(
+ const string &symbol_data, unsigned int *size) {
+ scoped_ptr<BasicSourceLineResolver::Module> module(
+ new BasicSourceLineResolver::Module("no name"));
+ scoped_array<char> buffer(new char[symbol_data.size() + 1]);
+ memcpy(buffer.get(), symbol_data.c_str(), symbol_data.size());
+ buffer.get()[symbol_data.size()] = '\0';
+ if (!module->LoadMapFromMemory(buffer.get(), symbol_data.size() + 1)) {
+ return NULL;
+ }
+ buffer.reset(NULL);
+ return Serialize(*(module.get()), size);
+}
+
+} // namespace google_breakpad
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/module_serializer.h b/toolkit/crashreporter/google-breakpad/src/processor/module_serializer.h
new file mode 100644
index 0000000000..effb009162
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/module_serializer.h
@@ -0,0 +1,127 @@
+// 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.
+//
+// module_serializer.h: ModuleSerializer serializes a loaded symbol,
+// i.e., a loaded BasicSouceLineResolver::Module instance, into a memory
+// chunk of data. The serialized data can be read and loaded by
+// FastSourceLineResolver without CPU & memory-intensive parsing.
+//
+// Author: Siyang Xie (lambxsy@google.com)
+
+#ifndef PROCESSOR_MODULE_SERIALIZER_H__
+#define PROCESSOR_MODULE_SERIALIZER_H__
+
+#include <map>
+#include <string>
+
+#include "google_breakpad/processor/basic_source_line_resolver.h"
+#include "google_breakpad/processor/fast_source_line_resolver.h"
+#include "processor/basic_source_line_resolver_types.h"
+#include "processor/fast_source_line_resolver_types.h"
+#include "processor/linked_ptr.h"
+#include "processor/map_serializers-inl.h"
+#include "processor/simple_serializer-inl.h"
+#include "processor/windows_frame_info.h"
+
+namespace google_breakpad {
+
+// ModuleSerializer serializes a loaded BasicSourceLineResolver::Module into a
+// chunk of memory data. ModuleSerializer also provides interface to compute
+// memory size of the serialized data, write serialized data directly into
+// memory, convert ASCII format symbol data into serialized binary data, and
+// convert loaded BasicSourceLineResolver::Module into
+// FastSourceLineResolver::Module.
+class ModuleSerializer {
+ public:
+ // Compute the size of memory required to serialize a module. Return the
+ // total size needed for serialization.
+ size_t SizeOf(const BasicSourceLineResolver::Module &module);
+
+ // Write a module into an allocated memory chunk with required size.
+ // Return the "end" of data, i.e., the address after the final byte of data.
+ char* Write(const BasicSourceLineResolver::Module &module, char *dest);
+
+ // Serializes a loaded Module object into a chunk of memory data and returns
+ // the address of memory chunk. If size != NULL, *size is set to the memory
+ // size allocated for the serialized data.
+ // Caller takes the ownership of the memory chunk (allocated on heap), and
+ // owner should call delete [] to free the memory after use.
+ char* Serialize(const BasicSourceLineResolver::Module &module,
+ unsigned int *size = NULL);
+
+ // Given the string format symbol_data, produces a chunk of serialized data.
+ // Caller takes ownership of the serialized data (on heap), and owner should
+ // call delete [] to free the memory after use.
+ char* SerializeSymbolFileData(const string &symbol_data,
+ unsigned int *size = NULL);
+
+ // Serializes one loaded module with given moduleid in the basic source line
+ // resolver, and loads the serialized data into the fast source line resolver.
+ // Return false if the basic source line doesn't have a module with the given
+ // moduleid.
+ bool ConvertOneModule(const string &moduleid,
+ const BasicSourceLineResolver *basic_resolver,
+ FastSourceLineResolver *fast_resolver);
+
+ // Serializes all the loaded modules in a basic source line resolver, and
+ // loads the serialized data into a fast source line resolver.
+ void ConvertAllModules(const BasicSourceLineResolver *basic_resolver,
+ FastSourceLineResolver *fast_resolver);
+
+ private:
+ // Convenient type names.
+ typedef BasicSourceLineResolver::Line Line;
+ typedef BasicSourceLineResolver::Function Function;
+ typedef BasicSourceLineResolver::PublicSymbol PublicSymbol;
+
+ // Internal implementation for ConvertOneModule and ConvertAllModules methods.
+ bool SerializeModuleAndLoadIntoFastResolver(
+ const BasicSourceLineResolver::ModuleMap::const_iterator &iter,
+ FastSourceLineResolver *fast_resolver);
+
+ // Number of Maps that Module class contains.
+ static const int32_t kNumberMaps_ =
+ FastSourceLineResolver::Module::kNumberMaps_;
+
+ // Memory sizes required to serialize map components in Module.
+ uint32_t map_sizes_[kNumberMaps_];
+
+ // Serializers for each individual map component in Module class.
+ StdMapSerializer<int, string> files_serializer_;
+ RangeMapSerializer<MemAddr, linked_ptr<Function> > functions_serializer_;
+ AddressMapSerializer<MemAddr, linked_ptr<PublicSymbol> > pubsym_serializer_;
+ ContainedRangeMapSerializer<MemAddr,
+ linked_ptr<WindowsFrameInfo> > wfi_serializer_;
+ RangeMapSerializer<MemAddr, string> cfi_init_rules_serializer_;
+ StdMapSerializer<MemAddr, string> cfi_delta_rules_serializer_;
+};
+
+} // namespace google_breakpad
+
+#endif // PROCESSOR_MODULE_SERIALIZER_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/moz.build b/toolkit/crashreporter/google-breakpad/src/processor/moz.build
new file mode 100644
index 0000000000..697cbea5f7
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/moz.build
@@ -0,0 +1,76 @@
+# -*- 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/.
+
+SOURCES += [
+ '../third_party/libdisasm/ia32_invariant.c',
+ '../third_party/libdisasm/ia32_reg.c',
+ 'disassembler_x86.cc',
+ 'exploitability_win.cc',
+]
+
+# clang -Wtautological-constant-in-range-compare implicitly enables
+# -Wtautological-value-range-compare, but we need to disable it to avoid
+# Breakpad bug https://bugs.chromium.org/p/google-breakpad/issues/detail?id=859
+if CONFIG["WARNINGS_CFLAGS"] and "-Wtautological-constant-in-range-compare" in CONFIG["WARNINGS_CFLAGS"]:
+ SOURCES['../third_party/libdisasm/ia32_invariant.c'].flags += ["-Wno-tautological-value-range-compare"]
+
+if CONFIG["CC_TYPE"] == "gcc" and int(CONFIG["CC_VERSION"].split(".")[0]) >= 8:
+ SOURCES['../third_party/libdisasm/ia32_reg.c'].flags += ["-Wno-stringop-truncation"]
+
+UNIFIED_SOURCES += [
+ '../third_party/libdisasm/ia32_implicit.c',
+ '../third_party/libdisasm/ia32_insn.c',
+ '../third_party/libdisasm/ia32_modrm.c',
+ '../third_party/libdisasm/ia32_opcode_tables.c',
+ '../third_party/libdisasm/ia32_operand.c',
+ '../third_party/libdisasm/ia32_settings.c',
+ '../third_party/libdisasm/x86_disasm.c',
+ '../third_party/libdisasm/x86_imm.c',
+ '../third_party/libdisasm/x86_insn.c',
+ '../third_party/libdisasm/x86_misc.c',
+ '../third_party/libdisasm/x86_operand_list.c',
+ 'basic_code_modules.cc',
+ 'basic_source_line_resolver.cc',
+ 'call_stack.cc',
+ 'cfi_frame_info.cc',
+ 'convert_old_arm64_context.cc',
+ 'dump_context.cc',
+ 'dump_object.cc',
+ 'exploitability.cc',
+ 'exploitability_linux.cc',
+ 'logging.cc',
+ 'minidump.cc',
+ 'minidump_processor.cc',
+ 'pathname_stripper.cc',
+ 'proc_maps_linux.cc',
+ 'process_state.cc',
+ 'source_line_resolver_base.cc',
+ 'stack_frame_symbolizer.cc',
+ 'stackwalk_common.cc',
+ 'stackwalker.cc',
+ 'stackwalker_amd64.cc',
+ 'stackwalker_arm.cc',
+ 'stackwalker_arm64.cc',
+ 'stackwalker_mips.cc',
+ 'stackwalker_ppc.cc',
+ 'stackwalker_ppc64.cc',
+ 'stackwalker_sparc.cc',
+ 'stackwalker_x86.cc',
+ 'symbolic_constants_win.cc',
+ 'tokenize.cc',
+]
+
+DEFINES['BPLOG_MINIMUM_SEVERITY'] = 'SEVERITY_CRITICAL'
+
+Library('breakpad_processor')
+
+# Don't use the STL wrappers in the crashreporter clients
+DisableStlWrapping()
+
+include('/toolkit/crashreporter/crashreporter.mozbuild')
+
+if CONFIG['CC_TYPE'] == 'clang-cl':
+ AllowCompilerWarnings() # workaround for bug 1090497
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/pathname_stripper.cc b/toolkit/crashreporter/google-breakpad/src/processor/pathname_stripper.cc
new file mode 100644
index 0000000000..839287bdba
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/pathname_stripper.cc
@@ -0,0 +1,56 @@
+// 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.
+
+// pathname_stripper.cc: Manipulates pathnames into their component parts.
+//
+// See pathname_stripper.h for documentation.
+//
+// Author: Mark Mentovai
+
+#include "processor/pathname_stripper.h"
+
+namespace google_breakpad {
+
+// static
+string PathnameStripper::File(const string &path) {
+ string::size_type slash = path.rfind('/');
+ string::size_type backslash = path.rfind('\\');
+
+ string::size_type file_start = 0;
+ if (slash != string::npos &&
+ (backslash == string::npos || slash > backslash)) {
+ file_start = slash + 1;
+ } else if (backslash != string::npos) {
+ file_start = backslash + 1;
+ }
+
+ return path.substr(file_start);
+}
+
+} // namespace google_breakpad
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/pathname_stripper.h b/toolkit/crashreporter/google-breakpad/src/processor/pathname_stripper.h
new file mode 100644
index 0000000000..423ca0d05a
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/pathname_stripper.h
@@ -0,0 +1,53 @@
+// 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.
+
+// pathname_stripper.h: Manipulates pathnames into their component parts.
+//
+// Author: Mark Mentovai
+
+#ifndef PROCESSOR_PATHNAME_STRIPPER_H__
+#define PROCESSOR_PATHNAME_STRIPPER_H__
+
+#include <string>
+
+#include "common/using_std_string.h"
+
+namespace google_breakpad {
+
+class PathnameStripper {
+ public:
+ // Given path, a pathname with components separated by slashes (/) or
+ // backslashes (\), returns the trailing component, without any separator.
+ // If path ends in a separator character, returns an empty string.
+ static string File(const string &path);
+};
+
+} // namespace google_breakpad
+
+#endif // PROCESSOR_PATHNAME_STRIPPER_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/pathname_stripper_unittest.cc b/toolkit/crashreporter/google-breakpad/src/processor/pathname_stripper_unittest.cc
new file mode 100644
index 0000000000..1bff4cb017
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/pathname_stripper_unittest.cc
@@ -0,0 +1,87 @@
+// 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 <stdio.h>
+
+#include "processor/pathname_stripper.h"
+#include "processor/logging.h"
+
+#define ASSERT_TRUE(condition) \
+ if (!(condition)) { \
+ fprintf(stderr, "FAIL: %s @ %s:%d\n", #condition, __FILE__, __LINE__); \
+ return false; \
+ }
+
+#define ASSERT_EQ(e1, e2) ASSERT_TRUE((e1) == (e2))
+
+namespace {
+
+using google_breakpad::PathnameStripper;
+
+static bool RunTests() {
+ ASSERT_EQ(PathnameStripper::File("/dir/file"), "file");
+ ASSERT_EQ(PathnameStripper::File("\\dir\\file"), "file");
+ ASSERT_EQ(PathnameStripper::File("/dir\\file"), "file");
+ ASSERT_EQ(PathnameStripper::File("\\dir/file"), "file");
+ ASSERT_EQ(PathnameStripper::File("dir/file"), "file");
+ ASSERT_EQ(PathnameStripper::File("dir\\file"), "file");
+ ASSERT_EQ(PathnameStripper::File("dir/\\file"), "file");
+ ASSERT_EQ(PathnameStripper::File("dir\\/file"), "file");
+ ASSERT_EQ(PathnameStripper::File("file"), "file");
+ ASSERT_EQ(PathnameStripper::File("dir/"), "");
+ ASSERT_EQ(PathnameStripper::File("dir\\"), "");
+ ASSERT_EQ(PathnameStripper::File("dir/dir/"), "");
+ ASSERT_EQ(PathnameStripper::File("dir\\dir\\"), "");
+ ASSERT_EQ(PathnameStripper::File("dir1/dir2/file"), "file");
+ ASSERT_EQ(PathnameStripper::File("dir1\\dir2\\file"), "file");
+ ASSERT_EQ(PathnameStripper::File("dir1/dir2\\file"), "file");
+ ASSERT_EQ(PathnameStripper::File("dir1\\dir2/file"), "file");
+ ASSERT_EQ(PathnameStripper::File(""), "");
+ ASSERT_EQ(PathnameStripper::File("1"), "1");
+ ASSERT_EQ(PathnameStripper::File("1/2"), "2");
+ ASSERT_EQ(PathnameStripper::File("1\\2"), "2");
+ ASSERT_EQ(PathnameStripper::File("/1/2"), "2");
+ ASSERT_EQ(PathnameStripper::File("\\1\\2"), "2");
+ ASSERT_EQ(PathnameStripper::File("dir//file"), "file");
+ ASSERT_EQ(PathnameStripper::File("dir\\\\file"), "file");
+ ASSERT_EQ(PathnameStripper::File("/dir//file"), "file");
+ ASSERT_EQ(PathnameStripper::File("\\dir\\\\file"), "file");
+ ASSERT_EQ(PathnameStripper::File("c:\\dir\\file"), "file");
+ ASSERT_EQ(PathnameStripper::File("c:\\dir\\file.ext"), "file.ext");
+
+ return true;
+}
+
+} // namespace
+
+int main(int argc, char **argv) {
+ BPLOG_INIT(&argc, &argv);
+
+ return RunTests() ? 0 : 1;
+}
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/postfix_evaluator-inl.h b/toolkit/crashreporter/google-breakpad/src/processor/postfix_evaluator-inl.h
new file mode 100644
index 0000000000..d7dbeac205
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/postfix_evaluator-inl.h
@@ -0,0 +1,363 @@
+// -*- 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.
+
+// postfix_evaluator-inl.h: Postfix (reverse Polish) notation expression
+// evaluator.
+//
+// Documentation in postfix_evaluator.h.
+//
+// Author: Mark Mentovai
+
+#ifndef PROCESSOR_POSTFIX_EVALUATOR_INL_H__
+#define PROCESSOR_POSTFIX_EVALUATOR_INL_H__
+
+#include "processor/postfix_evaluator.h"
+
+#include <stdio.h>
+
+#include <sstream>
+
+#include "google_breakpad/processor/memory_region.h"
+#include "processor/logging.h"
+
+namespace google_breakpad {
+
+using std::istringstream;
+using std::ostringstream;
+
+
+// A small class used in Evaluate to make sure to clean up the stack
+// before returning failure.
+class AutoStackClearer {
+ public:
+ explicit AutoStackClearer(vector<string> *stack) : stack_(stack) {}
+ ~AutoStackClearer() { stack_->clear(); }
+
+ private:
+ vector<string> *stack_;
+};
+
+
+template<typename ValueType>
+bool PostfixEvaluator<ValueType>::EvaluateToken(
+ const string &token,
+ const string &expression,
+ DictionaryValidityType *assigned) {
+ // There are enough binary operations that do exactly the same thing
+ // (other than the specific operation, of course) that it makes sense
+ // to share as much code as possible.
+ enum BinaryOperation {
+ BINARY_OP_NONE = 0,
+ BINARY_OP_ADD,
+ BINARY_OP_SUBTRACT,
+ BINARY_OP_MULTIPLY,
+ BINARY_OP_DIVIDE_QUOTIENT,
+ BINARY_OP_DIVIDE_MODULUS,
+ BINARY_OP_ALIGN
+ };
+
+ BinaryOperation operation = BINARY_OP_NONE;
+ if (token == "+")
+ operation = BINARY_OP_ADD;
+ else if (token == "-")
+ operation = BINARY_OP_SUBTRACT;
+ else if (token == "*")
+ operation = BINARY_OP_MULTIPLY;
+ else if (token == "/")
+ operation = BINARY_OP_DIVIDE_QUOTIENT;
+ else if (token == "%")
+ operation = BINARY_OP_DIVIDE_MODULUS;
+ else if (token == "@")
+ operation = BINARY_OP_ALIGN;
+
+ if (operation != BINARY_OP_NONE) {
+ // Get the operands.
+ ValueType operand1 = ValueType();
+ ValueType operand2 = ValueType();
+ if (!PopValues(&operand1, &operand2)) {
+ BPLOG(ERROR) << "Could not PopValues to get two values for binary "
+ "operation " << token << ": " << expression;
+ return false;
+ }
+
+ // Perform the operation.
+ ValueType result;
+ switch (operation) {
+ case BINARY_OP_ADD:
+ result = operand1 + operand2;
+ break;
+ case BINARY_OP_SUBTRACT:
+ result = operand1 - operand2;
+ break;
+ case BINARY_OP_MULTIPLY:
+ result = operand1 * operand2;
+ break;
+ case BINARY_OP_DIVIDE_QUOTIENT:
+ result = operand1 / operand2;
+ break;
+ case BINARY_OP_DIVIDE_MODULUS:
+ result = operand1 % operand2;
+ break;
+ case BINARY_OP_ALIGN:
+ result =
+ operand1 & (static_cast<ValueType>(-1) ^ (operand2 - 1));
+ break;
+ case BINARY_OP_NONE:
+ // This will not happen, but compilers will want a default or
+ // BINARY_OP_NONE case.
+ BPLOG(ERROR) << "Not reached!";
+ return false;
+ break;
+ }
+
+ // Save the result.
+ PushValue(result);
+ } else if (token == "^") {
+ // ^ for unary dereference. Can't dereference without memory.
+ if (!memory_) {
+ BPLOG(ERROR) << "Attempt to dereference without memory: " <<
+ expression;
+ return false;
+ }
+
+ ValueType address;
+ if (!PopValue(&address)) {
+ BPLOG(ERROR) << "Could not PopValue to get value to derefence: " <<
+ expression;
+ return false;
+ }
+
+ ValueType value;
+ if (!memory_->GetMemoryAtAddress(address, &value)) {
+ BPLOG(ERROR) << "Could not dereference memory at address " <<
+ HexString(address) << ": " << expression;
+ return false;
+ }
+
+ PushValue(value);
+ } else if (token == "=") {
+ // = for assignment.
+ ValueType value;
+ if (!PopValue(&value)) {
+ BPLOG(INFO) << "Could not PopValue to get value to assign: " <<
+ expression;
+ return false;
+ }
+
+ // Assignment is only meaningful when assigning into an identifier.
+ // The identifier must name a variable, not a constant. Variables
+ // begin with '$'.
+ string identifier;
+ if (PopValueOrIdentifier(NULL, &identifier) != POP_RESULT_IDENTIFIER) {
+ BPLOG(ERROR) << "PopValueOrIdentifier returned a value, but an "
+ "identifier is needed to assign " <<
+ HexString(value) << ": " << expression;
+ return false;
+ }
+ if (identifier.empty() || identifier[0] != '$') {
+ BPLOG(ERROR) << "Can't assign " << HexString(value) << " to " <<
+ identifier << ": " << expression;
+ return false;
+ }
+
+ (*dictionary_)[identifier] = value;
+ if (assigned)
+ (*assigned)[identifier] = true;
+ } else {
+ // The token is not an operator, it's a literal value or an identifier.
+ // Push it onto the stack as-is. Use push_back instead of PushValue
+ // because PushValue pushes ValueType as a string, but token is already
+ // a string.
+ stack_.push_back(token);
+ }
+ return true;
+}
+
+template<typename ValueType>
+bool PostfixEvaluator<ValueType>::EvaluateInternal(
+ const string &expression,
+ DictionaryValidityType *assigned) {
+ // Tokenize, splitting on whitespace.
+ istringstream stream(expression);
+ string token;
+ while (stream >> token) {
+ // Normally, tokens are whitespace-separated, but occasionally, the
+ // assignment operator is smashed up against the next token, i.e.
+ // $T0 $ebp 128 + =$eip $T0 4 + ^ =$ebp $T0 ^ =
+ // This has been observed in program strings produced by MSVS 2010 in LTO
+ // mode.
+ if (token.size() > 1 && token[0] == '=') {
+ if (!EvaluateToken("=", expression, assigned)) {
+ return false;
+ }
+
+ if (!EvaluateToken(token.substr(1), expression, assigned)) {
+ return false;
+ }
+ } else if (!EvaluateToken(token, expression, assigned)) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+template<typename ValueType>
+bool PostfixEvaluator<ValueType>::Evaluate(const string &expression,
+ DictionaryValidityType *assigned) {
+ // Ensure that the stack is cleared before returning.
+ AutoStackClearer clearer(&stack_);
+
+ if (!EvaluateInternal(expression, assigned))
+ return false;
+
+ // If there's anything left on the stack, it indicates incomplete execution.
+ // This is a failure case. If the stack is empty, evalution was complete
+ // and successful.
+ if (stack_.empty())
+ return true;
+
+ BPLOG(ERROR) << "Incomplete execution: " << expression;
+ return false;
+}
+
+template<typename ValueType>
+bool PostfixEvaluator<ValueType>::EvaluateForValue(const string &expression,
+ ValueType *result) {
+ // Ensure that the stack is cleared before returning.
+ AutoStackClearer clearer(&stack_);
+
+ if (!EvaluateInternal(expression, NULL))
+ return false;
+
+ // A successful execution should leave exactly one value on the stack.
+ if (stack_.size() != 1) {
+ BPLOG(ERROR) << "Expression yielded bad number of results: "
+ << "'" << expression << "'";
+ return false;
+ }
+
+ return PopValue(result);
+}
+
+template<typename ValueType>
+typename PostfixEvaluator<ValueType>::PopResult
+PostfixEvaluator<ValueType>::PopValueOrIdentifier(
+ ValueType *value, string *identifier) {
+ // There needs to be at least one element on the stack to pop.
+ if (!stack_.size())
+ return POP_RESULT_FAIL;
+
+ string token = stack_.back();
+ stack_.pop_back();
+
+ // First, try to treat the value as a literal. Literals may have leading
+ // '-' sign, and the entire remaining string must be parseable as
+ // ValueType. If this isn't possible, it can't be a literal, so treat it
+ // as an identifier instead.
+ //
+ // Some versions of the libstdc++, the GNU standard C++ library, have
+ // stream extractors for unsigned integer values that permit a leading
+ // '-' sign (6.0.13); others do not (6.0.9). Since we require it, we
+ // handle it explicitly here.
+ istringstream token_stream(token);
+ ValueType literal = ValueType();
+ bool negative;
+ if (token_stream.peek() == '-') {
+ negative = true;
+ token_stream.get();
+ } else {
+ negative = false;
+ }
+ if (token_stream >> literal && token_stream.peek() == EOF) {
+ if (value) {
+ *value = literal;
+ }
+ if (negative)
+ *value = -*value;
+ return POP_RESULT_VALUE;
+ } else {
+ if (identifier) {
+ *identifier = token;
+ }
+ return POP_RESULT_IDENTIFIER;
+ }
+}
+
+
+template<typename ValueType>
+bool PostfixEvaluator<ValueType>::PopValue(ValueType *value) {
+ ValueType literal = ValueType();
+ string token;
+ PopResult result;
+ if ((result = PopValueOrIdentifier(&literal, &token)) == POP_RESULT_FAIL) {
+ return false;
+ } else if (result == POP_RESULT_VALUE) {
+ // This is the easy case.
+ *value = literal;
+ } else { // result == POP_RESULT_IDENTIFIER
+ // There was an identifier at the top of the stack. Resolve it to a
+ // value by looking it up in the dictionary.
+ typename DictionaryType::const_iterator iterator =
+ dictionary_->find(token);
+ if (iterator == dictionary_->end()) {
+ // The identifier wasn't found in the dictionary. Don't imply any
+ // default value, just fail.
+ BPLOG(INFO) << "Identifier " << token << " not in dictionary";
+ return false;
+ }
+
+ *value = iterator->second;
+ }
+
+ return true;
+}
+
+
+template<typename ValueType>
+bool PostfixEvaluator<ValueType>::PopValues(ValueType *value1,
+ ValueType *value2) {
+ return PopValue(value2) && PopValue(value1);
+}
+
+
+template<typename ValueType>
+void PostfixEvaluator<ValueType>::PushValue(const ValueType &value) {
+ ostringstream token_stream;
+ token_stream << value;
+ stack_.push_back(token_stream.str());
+}
+
+
+} // namespace google_breakpad
+
+
+#endif // PROCESSOR_POSTFIX_EVALUATOR_INL_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/postfix_evaluator.h b/toolkit/crashreporter/google-breakpad/src/processor/postfix_evaluator.h
new file mode 100644
index 0000000000..94b66190d5
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/postfix_evaluator.h
@@ -0,0 +1,179 @@
+// -*- 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.
+
+// postfix_evaluator.h: Postfix (reverse Polish) notation expression evaluator.
+//
+// PostfixEvaluator evaluates an expression, using the expression itself
+// in postfix (reverse Polish) notation and a dictionary mapping constants
+// and variables to their values. The evaluator supports standard
+// arithmetic operations, assignment into variables, and when an optional
+// MemoryRange is provided, dereferencing. (Any unary key-to-value operation
+// may be used with a MemoryRange implementation that returns the appropriate
+// values, but PostfixEvaluator was written with dereferencing in mind.)
+//
+// The expression language is simple. Expressions are supplied as strings,
+// with operands and operators delimited by whitespace. Operands may be
+// either literal values suitable for ValueType, or constants or variables,
+// which reference the dictionary. The supported binary operators are +
+// (addition), - (subtraction), * (multiplication), / (quotient of division),
+// % (modulus of division), and @ (data alignment). The alignment operator (@)
+// accepts a value and an alignment size, and produces a result that is a
+// multiple of the alignment size by truncating the input value.
+// The unary ^ (dereference) operator is also provided. These operators
+// allow any operand to be either a literal value, constant, or variable.
+// Assignment (=) of any type of operand into a variable is also supported.
+//
+// The dictionary is provided as a map with string keys. Keys beginning
+// with the '$' character are treated as variables. All other keys are
+// treated as constants. Any results must be assigned into variables in the
+// dictionary. These variables do not need to exist prior to calling
+// Evaluate, unless used in an expression prior to being assigned to. The
+// internal stack state is not made available after evaluation, and any
+// values remaining on the stack are treated as evidence of incomplete
+// execution and cause the evaluator to indicate failure.
+//
+// PostfixEvaluator is intended to support evaluation of "program strings"
+// obtained from MSVC frame data debugging information in pdb files as
+// returned by the DIA APIs.
+//
+// Author: Mark Mentovai
+
+#ifndef PROCESSOR_POSTFIX_EVALUATOR_H__
+#define PROCESSOR_POSTFIX_EVALUATOR_H__
+
+
+#include <map>
+#include <string>
+#include <vector>
+
+#include "common/using_std_string.h"
+
+namespace google_breakpad {
+
+using std::map;
+using std::vector;
+
+class MemoryRegion;
+
+template<typename ValueType>
+class PostfixEvaluator {
+ public:
+ typedef map<string, ValueType> DictionaryType;
+ typedef map<string, bool> DictionaryValidityType;
+
+ // Create a PostfixEvaluator object that may be used (with Evaluate) on
+ // one or more expressions. PostfixEvaluator does not take ownership of
+ // either argument. |memory| may be NULL, in which case dereferencing
+ // (^) will not be supported. |dictionary| may be NULL, but evaluation
+ // will fail in that case unless set_dictionary is used before calling
+ // Evaluate.
+ PostfixEvaluator(DictionaryType *dictionary, const MemoryRegion *memory)
+ : dictionary_(dictionary), memory_(memory), stack_() {}
+
+ // Evaluate the expression, starting with an empty stack. The results of
+ // execution will be stored in one (or more) variables in the dictionary.
+ // Returns false if any failures occur during execution, leaving
+ // variables in the dictionary in an indeterminate state. If assigned is
+ // non-NULL, any keys set in the dictionary as a result of evaluation
+ // will also be set to true in assigned, providing a way to determine if
+ // an expression modifies any of its input variables.
+ bool Evaluate(const string &expression, DictionaryValidityType *assigned);
+
+ // Like Evaluate, but provides the value left on the stack to the
+ // caller. If evaluation succeeds and leaves exactly one value on
+ // the stack, pop that value, store it in *result, and return true.
+ // Otherwise, return false.
+ bool EvaluateForValue(const string &expression, ValueType *result);
+
+ DictionaryType* dictionary() const { return dictionary_; }
+
+ // Reset the dictionary. PostfixEvaluator does not take ownership.
+ void set_dictionary(DictionaryType *dictionary) {dictionary_ = dictionary; }
+
+ private:
+ // Return values for PopValueOrIdentifier
+ enum PopResult {
+ POP_RESULT_FAIL = 0,
+ POP_RESULT_VALUE,
+ POP_RESULT_IDENTIFIER
+ };
+
+ // Retrieves the topmost literal value, constant, or variable from the
+ // stack. Returns POP_RESULT_VALUE if the topmost entry is a literal
+ // value, and sets |value| accordingly. Returns POP_RESULT_IDENTIFIER
+ // if the topmost entry is a constant or variable identifier, and sets
+ // |identifier| accordingly. Returns POP_RESULT_FAIL on failure, such
+ // as when the stack is empty.
+ PopResult PopValueOrIdentifier(ValueType *value, string *identifier);
+
+ // Retrieves the topmost value on the stack. If the topmost entry is
+ // an identifier, the dictionary is queried for the identifier's value.
+ // Returns false on failure, such as when the stack is empty or when
+ // a nonexistent identifier is named.
+ bool PopValue(ValueType *value);
+
+ // Retrieves the top two values on the stack, in the style of PopValue.
+ // value2 is popped before value1, so that value1 corresponds to the
+ // entry that was pushed prior to value2. Returns false on failure.
+ bool PopValues(ValueType *value1, ValueType *value2);
+
+ // Pushes a new value onto the stack.
+ void PushValue(const ValueType &value);
+
+ // Evaluate expression, updating *assigned if it is non-zero. Return
+ // true if evaluation completes successfully. Do not clear the stack
+ // upon successful evaluation.
+ bool EvaluateInternal(const string &expression,
+ DictionaryValidityType *assigned);
+
+ bool EvaluateToken(const string &token,
+ const string &expression,
+ DictionaryValidityType *assigned);
+
+ // The dictionary mapping constant and variable identifiers (strings) to
+ // values. Keys beginning with '$' are treated as variable names, and
+ // PostfixEvaluator is free to create and modify these keys. Weak pointer.
+ DictionaryType *dictionary_;
+
+ // If non-NULL, the MemoryRegion used for dereference (^) operations.
+ // If NULL, dereferencing is unsupported and will fail. Weak pointer.
+ const MemoryRegion *memory_;
+
+ // The stack contains state information as execution progresses. Values
+ // are pushed on to it as the expression string is read and as operations
+ // yield values; values are popped when used as operands to operators.
+ vector<string> stack_;
+};
+
+} // namespace google_breakpad
+
+
+#endif // PROCESSOR_POSTFIX_EVALUATOR_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/postfix_evaluator_unittest.cc b/toolkit/crashreporter/google-breakpad/src/processor/postfix_evaluator_unittest.cc
new file mode 100644
index 0000000000..f118982849
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/postfix_evaluator_unittest.cc
@@ -0,0 +1,403 @@
+// 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.
+
+// postfix_evaluator_unittest.cc: Unit tests for PostfixEvaluator.
+//
+// Author: Mark Mentovai
+
+#include <assert.h>
+#include <stdio.h>
+
+#include <map>
+#include <string>
+
+#include "processor/postfix_evaluator-inl.h"
+
+#include "common/using_std_string.h"
+#include "google_breakpad/common/breakpad_types.h"
+#include "google_breakpad/processor/memory_region.h"
+#include "processor/logging.h"
+
+
+namespace {
+
+
+using std::map;
+using google_breakpad::MemoryRegion;
+using google_breakpad::PostfixEvaluator;
+
+
+// FakeMemoryRegion is used to test PostfixEvaluator's dereference (^)
+// operator. The result of dereferencing a value is one greater than
+// the value.
+class FakeMemoryRegion : public MemoryRegion {
+ public:
+ virtual uint64_t GetBase() const { return 0; }
+ virtual uint32_t GetSize() const { return 0; }
+ virtual bool GetMemoryAtAddress(uint64_t address, uint8_t *value) const {
+ *value = address + 1;
+ return true;
+ }
+ virtual bool GetMemoryAtAddress(uint64_t address, uint16_t *value) const {
+ *value = address + 1;
+ return true;
+ }
+ virtual bool GetMemoryAtAddress(uint64_t address, uint32_t *value) const {
+ *value = address + 1;
+ return true;
+ }
+ virtual bool GetMemoryAtAddress(uint64_t address, uint64_t *value) const {
+ *value = address + 1;
+ return true;
+ }
+ virtual void Print() const {
+ assert(false);
+ }
+};
+
+
+struct EvaluateTest {
+ // Expression passed to PostfixEvaluator::Evaluate.
+ const string expression;
+
+ // True if the expression is expected to be evaluable, false if evaluation
+ // is expected to fail.
+ bool evaluable;
+};
+
+
+struct EvaluateTestSet {
+ // The dictionary used for all tests in the set.
+ PostfixEvaluator<unsigned int>::DictionaryType *dictionary;
+
+ // The list of tests.
+ const EvaluateTest *evaluate_tests;
+
+ // The number of tests.
+ unsigned int evaluate_test_count;
+
+ // Identifiers and their expected values upon completion of the Evaluate
+ // tests in the set.
+ map<string, unsigned int> *validate_data;
+};
+
+
+struct EvaluateForValueTest {
+ // Expression passed to PostfixEvaluator::Evaluate.
+ const string expression;
+
+ // True if the expression is expected to be evaluable, false if evaluation
+ // is expected to fail.
+ bool evaluable;
+
+ // If evaluable, the value we expect it to yield.
+ unsigned int value;
+};
+
+static bool RunTests() {
+ // The first test set checks the basic operations and failure modes.
+ PostfixEvaluator<unsigned int>::DictionaryType dictionary_0;
+ const EvaluateTest evaluate_tests_0[] = {
+ { "$rAdd 2 2 + =", true }, // $rAdd = 2 + 2 = 4
+ { "$rAdd $rAdd 2 + =", true }, // $rAdd = $rAdd + 2 = 6
+ { "$rAdd 2 $rAdd + =", true }, // $rAdd = 2 + $rAdd = 8
+ { "99", false }, // put some junk on the stack...
+ { "$rAdd2 2 2 + =", true }, // ...and make sure things still work
+ { "$rAdd2\t2\n2 + =", true }, // same but with different whitespace
+ { "$rAdd2 2 2 + = ", true }, // trailing whitespace
+ { " $rAdd2 2 2 + =", true }, // leading whitespace
+ { "$rAdd2 2 2 + =", true }, // extra whitespace
+ { "$T0 2 = +", false }, // too few operands for add
+ { "2 + =", false }, // too few operands for add
+ { "2 +", false }, // too few operands for add
+ { "+", false }, // too few operands for add
+ { "^", false }, // too few operands for dereference
+ { "=", false }, // too few operands for assignment
+ { "2 =", false }, // too few operands for assignment
+ { "2 2 + =", false }, // too few operands for assignment
+ { "2 2 =", false }, // can't assign into a literal
+ { "k 2 =", false }, // can't assign into a constant
+ { "2", false }, // leftover data on stack
+ { "2 2 +", false }, // leftover data on stack
+ { "$rAdd", false }, // leftover data on stack
+ { "0 $T1 0 0 + =", false }, // leftover data on stack
+ { "$T2 $T2 2 + =", false }, // can't operate on an undefined value
+ { "$rMul 9 6 * =", true }, // $rMul = 9 * 6 = 54
+ { "$rSub 9 6 - =", true }, // $rSub = 9 - 6 = 3
+ { "$rDivQ 9 6 / =", true }, // $rDivQ = 9 / 6 = 1
+ { "$rDivM 9 6 % =", true }, // $rDivM = 9 % 6 = 3
+ { "$rDeref 9 ^ =", true }, // $rDeref = ^9 = 10 (FakeMemoryRegion)
+ { "$rAlign 36 8 @ =", true }, // $rAlign = 36 @ 8
+ { "$rAdd3 2 2 + =$rMul2 9 6 * =", true } // smashed-equals tokenization
+ };
+ map<string, unsigned int> validate_data_0;
+ validate_data_0["$rAdd"] = 8;
+ validate_data_0["$rAdd2"] = 4;
+ validate_data_0["$rSub"] = 3;
+ validate_data_0["$rMul"] = 54;
+ validate_data_0["$rDivQ"] = 1;
+ validate_data_0["$rDivM"] = 3;
+ validate_data_0["$rDeref"] = 10;
+ validate_data_0["$rAlign"] = 32;
+ validate_data_0["$rAdd3"] = 4;
+ validate_data_0["$rMul2"] = 54;
+
+ // The second test set simulates a couple of MSVC program strings.
+ // The data is fudged a little bit because the tests use FakeMemoryRegion
+ // instead of a real stack snapshot, but the program strings are real and
+ // the implementation doesn't know or care that the data is not real.
+ PostfixEvaluator<unsigned int>::DictionaryType dictionary_1;
+ dictionary_1["$ebp"] = 0xbfff0010;
+ dictionary_1["$eip"] = 0x10000000;
+ dictionary_1["$esp"] = 0xbfff0000;
+ dictionary_1[".cbSavedRegs"] = 4;
+ dictionary_1[".cbParams"] = 4;
+ dictionary_1[".raSearchStart"] = 0xbfff0020;
+ const EvaluateTest evaluate_tests_1[] = {
+ { "$T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = "
+ "$L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + =", true },
+ // Intermediate state: $T0 = 0xbfff0010, $eip = 0xbfff0015,
+ // $ebp = 0xbfff0011, $esp = 0xbfff0018,
+ // $L = 0xbfff000c, $P = 0xbfff001c
+ { "$T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = "
+ "$L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 28 - ^ =",
+ true },
+ // Intermediate state: $T0 = 0xbfff0011, $eip = 0xbfff0016,
+ // $ebp = 0xbfff0012, $esp = 0xbfff0019,
+ // $L = 0xbfff000d, $P = 0xbfff001d,
+ // $ebx = 0xbffefff6
+ { "$T0 $ebp = $T2 $esp = $T1 .raSearchStart = $eip $T1 ^ = $ebp $T0 = "
+ "$esp $T1 4 + = $L $T0 .cbSavedRegs - = $P $T1 4 + .cbParams + = "
+ "$ebx $T0 28 - ^ =",
+ true }
+ };
+ map<string, unsigned int> validate_data_1;
+ validate_data_1["$T0"] = 0xbfff0012;
+ validate_data_1["$T1"] = 0xbfff0020;
+ validate_data_1["$T2"] = 0xbfff0019;
+ validate_data_1["$eip"] = 0xbfff0021;
+ validate_data_1["$ebp"] = 0xbfff0012;
+ validate_data_1["$esp"] = 0xbfff0024;
+ validate_data_1["$L"] = 0xbfff000e;
+ validate_data_1["$P"] = 0xbfff0028;
+ validate_data_1["$ebx"] = 0xbffefff7;
+ validate_data_1[".cbSavedRegs"] = 4;
+ validate_data_1[".cbParams"] = 4;
+
+ EvaluateTestSet evaluate_test_sets[] = {
+ { &dictionary_0, evaluate_tests_0,
+ sizeof(evaluate_tests_0) / sizeof(EvaluateTest), &validate_data_0 },
+ { &dictionary_1, evaluate_tests_1,
+ sizeof(evaluate_tests_1) / sizeof(EvaluateTest), &validate_data_1 },
+ };
+
+ unsigned int evaluate_test_set_count = sizeof(evaluate_test_sets) /
+ sizeof(EvaluateTestSet);
+
+ FakeMemoryRegion fake_memory;
+ PostfixEvaluator<unsigned int> postfix_evaluator =
+ PostfixEvaluator<unsigned int>(NULL, &fake_memory);
+
+ for (unsigned int evaluate_test_set_index = 0;
+ evaluate_test_set_index < evaluate_test_set_count;
+ ++evaluate_test_set_index) {
+ EvaluateTestSet *evaluate_test_set =
+ &evaluate_test_sets[evaluate_test_set_index];
+ const EvaluateTest *evaluate_tests = evaluate_test_set->evaluate_tests;
+ unsigned int evaluate_test_count = evaluate_test_set->evaluate_test_count;
+
+ // The same dictionary will be used for each test in the set. Earlier
+ // tests can affect the state of the dictionary for later tests.
+ postfix_evaluator.set_dictionary(evaluate_test_set->dictionary);
+
+ // Use a new validity dictionary for each test set.
+ PostfixEvaluator<unsigned int>::DictionaryValidityType assigned;
+
+ for (unsigned int evaluate_test_index = 0;
+ evaluate_test_index < evaluate_test_count;
+ ++evaluate_test_index) {
+ const EvaluateTest *evaluate_test = &evaluate_tests[evaluate_test_index];
+
+ // Do the test.
+ bool result = postfix_evaluator.Evaluate(evaluate_test->expression,
+ &assigned);
+ if (result != evaluate_test->evaluable) {
+ fprintf(stderr, "FAIL: evaluate set %d/%d, test %d/%d, "
+ "expression \"%s\", expected %s, observed %s\n",
+ evaluate_test_set_index, evaluate_test_set_count,
+ evaluate_test_index, evaluate_test_count,
+ evaluate_test->expression.c_str(),
+ evaluate_test->evaluable ? "evaluable" : "not evaluable",
+ result ? "evaluted" : "not evaluated");
+ return false;
+ }
+ }
+
+ // Validate the results.
+ for (map<string, unsigned int>::const_iterator validate_iterator =
+ evaluate_test_set->validate_data->begin();
+ validate_iterator != evaluate_test_set->validate_data->end();
+ ++validate_iterator) {
+ const string identifier = validate_iterator->first;
+ unsigned int expected_value = validate_iterator->second;
+
+ map<string, unsigned int>::const_iterator dictionary_iterator =
+ evaluate_test_set->dictionary->find(identifier);
+
+ // The identifier must exist in the dictionary.
+ if (dictionary_iterator == evaluate_test_set->dictionary->end()) {
+ fprintf(stderr, "FAIL: evaluate test set %d/%d, "
+ "validate identifier \"%s\", "
+ "expected %d, observed not found\n",
+ evaluate_test_set_index, evaluate_test_set_count,
+ identifier.c_str(), expected_value);
+ return false;
+ }
+
+ // The value in the dictionary must be the same as the expected value.
+ unsigned int observed_value = dictionary_iterator->second;
+ if (expected_value != observed_value) {
+ fprintf(stderr, "FAIL: evaluate test set %d/%d, "
+ "validate identifier \"%s\", "
+ "expected %d, observed %d\n",
+ evaluate_test_set_index, evaluate_test_set_count,
+ identifier.c_str(), expected_value, observed_value);
+ return false;
+ }
+
+ // The value must be set in the "assigned" dictionary if it was a
+ // variable. It must not have been assigned if it was a constant.
+ bool expected_assigned = identifier[0] == '$';
+ bool observed_assigned = false;
+ PostfixEvaluator<unsigned int>::DictionaryValidityType::const_iterator
+ iterator_assigned = assigned.find(identifier);
+ if (iterator_assigned != assigned.end()) {
+ observed_assigned = iterator_assigned->second;
+ }
+ if (expected_assigned != observed_assigned) {
+ fprintf(stderr, "FAIL: evaluate test set %d/%d, "
+ "validate assignment of \"%s\", "
+ "expected %d, observed %d\n",
+ evaluate_test_set_index, evaluate_test_set_count,
+ identifier.c_str(), expected_assigned, observed_assigned);
+ return false;
+ }
+ }
+ }
+
+ // EvaluateForValue tests.
+ PostfixEvaluator<unsigned int>::DictionaryType dictionary_2;
+ dictionary_2["$ebp"] = 0xbfff0010;
+ dictionary_2["$eip"] = 0x10000000;
+ dictionary_2["$esp"] = 0xbfff0000;
+ dictionary_2[".cbSavedRegs"] = 4;
+ dictionary_2[".cbParams"] = 4;
+ dictionary_2[".raSearchStart"] = 0xbfff0020;
+ const EvaluateForValueTest evaluate_for_value_tests_2[] = {
+ { "28907223", true, 28907223 }, // simple constant
+ { "89854293 40010015 +", true, 89854293 + 40010015 }, // arithmetic
+ { "-870245 8769343 +", true, 7899098 }, // negative constants
+ { "$ebp $esp - $eip +", true, 0x10000010 }, // variable references
+ { "18929794 34015074", false, 0 }, // too many values
+ { "$ebp $ebp 4 - =", false, 0 }, // too few values
+ { "$new $eip = $new", true, 0x10000000 }, // make new variable
+ { "$new 4 +", true, 0x10000004 }, // see prior assignments
+ { ".cfa 42 = 10", false, 0 } // can't set constants
+ };
+ const int evaluate_for_value_tests_2_size
+ = (sizeof (evaluate_for_value_tests_2)
+ / sizeof (evaluate_for_value_tests_2[0]));
+ map<string, unsigned int> validate_data_2;
+ validate_data_2["$eip"] = 0x10000000;
+ validate_data_2["$ebp"] = 0xbfff000c;
+ validate_data_2["$esp"] = 0xbfff0000;
+ validate_data_2["$new"] = 0x10000000;
+ validate_data_2[".cbSavedRegs"] = 4;
+ validate_data_2[".cbParams"] = 4;
+ validate_data_2[".raSearchStart"] = 0xbfff0020;
+
+ postfix_evaluator.set_dictionary(&dictionary_2);
+ for (int i = 0; i < evaluate_for_value_tests_2_size; i++) {
+ const EvaluateForValueTest *test = &evaluate_for_value_tests_2[i];
+ unsigned int result;
+ if (postfix_evaluator.EvaluateForValue(test->expression, &result)
+ != test->evaluable) {
+ fprintf(stderr, "FAIL: evaluate for value test %d, "
+ "expected evaluation to %s, but it %s\n",
+ i, test->evaluable ? "succeed" : "fail",
+ test->evaluable ? "failed" : "succeeded");
+ return false;
+ }
+ if (test->evaluable && result != test->value) {
+ fprintf(stderr, "FAIL: evaluate for value test %d, "
+ "expected value to be 0x%x, but it was 0x%x\n",
+ i, test->value, result);
+ return false;
+ }
+ }
+
+ for (map<string, unsigned int>::iterator v = validate_data_2.begin();
+ v != validate_data_2.end(); v++) {
+ map<string, unsigned int>::iterator a = dictionary_2.find(v->first);
+ if (a == dictionary_2.end()) {
+ fprintf(stderr, "FAIL: evaluate for value dictionary check: "
+ "expected dict[\"%s\"] to be 0x%x, but it was unset\n",
+ v->first.c_str(), v->second);
+ return false;
+ } else if (a->second != v->second) {
+ fprintf(stderr, "FAIL: evaluate for value dictionary check: "
+ "expected dict[\"%s\"] to be 0x%x, but it was 0x%x\n",
+ v->first.c_str(), v->second, a->second);
+ return false;
+ }
+ dictionary_2.erase(a);
+ }
+
+ map<string, unsigned int>::iterator remaining = dictionary_2.begin();
+ if (remaining != dictionary_2.end()) {
+ fprintf(stderr, "FAIL: evaluation of test expressions put unexpected "
+ "values in dictionary:\n");
+ for (; remaining != dictionary_2.end(); remaining++)
+ fprintf(stderr, " dict[\"%s\"] == 0x%x\n",
+ remaining->first.c_str(), remaining->second);
+ return false;
+ }
+
+ return true;
+}
+
+
+} // namespace
+
+
+int main(int argc, char **argv) {
+ BPLOG_INIT(&argc, &argv);
+
+ return RunTests() ? 0 : 1;
+}
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/proc_maps_linux.cc b/toolkit/crashreporter/google-breakpad/src/processor/proc_maps_linux.cc
new file mode 100644
index 0000000000..3c0dea25d2
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/proc_maps_linux.cc
@@ -0,0 +1,106 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef __STDC_FORMAT_MACROS
+#define __STDC_FORMAT_MACROS
+#endif
+
+#include "google_breakpad/processor/proc_maps_linux.h"
+
+#include <fcntl.h>
+#include <inttypes.h>
+#include <stdio.h>
+
+#include "common/using_std_string.h"
+#include "processor/logging.h"
+
+#if defined(OS_ANDROID) && !defined(__LP64__)
+// In 32-bit mode, Bionic's inttypes.h defines PRI/SCNxPTR as an
+// unsigned long int, which is incompatible with Bionic's stdint.h
+// defining uintptr_t as an unsigned int:
+// https://code.google.com/p/android/issues/detail?id=57218
+#undef SCNxPTR
+#define SCNxPTR "x"
+#endif
+
+namespace google_breakpad {
+
+bool ParseProcMaps(const string& input,
+ std::vector<MappedMemoryRegion>* regions_out) {
+ std::vector<MappedMemoryRegion> regions;
+
+ // This isn't async safe nor terribly efficient, but it doesn't need to be at
+ // this point in time.
+
+ // Split the string by newlines.
+ std::vector<string> lines;
+ string l = "";
+ for (size_t i = 0; i < input.size(); i++) {
+ if (input[i] != '\n' && input[i] != '\r') {
+ l.push_back(input[i]);
+ } else if (l.size() > 0) {
+ lines.push_back(l);
+ l.clear();
+ }
+ }
+ if (l.size() > 0) {
+ BPLOG(ERROR) << "Input doesn't end in newline";
+ return false;
+ }
+
+ for (size_t i = 0; i < lines.size(); ++i) {
+ MappedMemoryRegion region;
+ const char* line = lines[i].c_str();
+ char permissions[5] = {'\0'}; // Ensure NUL-terminated string.
+ int path_index = 0;
+
+ // Sample format from man 5 proc:
+ //
+ // address perms offset dev inode pathname
+ // 08048000-08056000 r-xp 00000000 03:0c 64593 /usr/sbin/gpm
+ //
+ // The final %n term captures the offset in the input string, which is used
+ // to determine the path name. It *does not* increment the return value.
+ // Refer to man 3 sscanf for details.
+ if (sscanf(line, "%" SCNx64 "-%" SCNx64 " %4c %" SCNx64" %hhx:%hhx %"
+ SCNd64 " %n", &region.start, &region.end, permissions,
+ &region.offset, &region.major_device, &region.minor_device,
+ &region.inode, &path_index) < 7) {
+ BPLOG(ERROR) << "sscanf failed for line: " << line;
+ return false;
+ }
+
+ region.permissions = 0;
+
+ if (permissions[0] == 'r')
+ region.permissions |= MappedMemoryRegion::READ;
+ else if (permissions[0] != '-')
+ return false;
+
+ if (permissions[1] == 'w')
+ region.permissions |= MappedMemoryRegion::WRITE;
+ else if (permissions[1] != '-')
+ return false;
+
+ if (permissions[2] == 'x')
+ region.permissions |= MappedMemoryRegion::EXECUTE;
+ else if (permissions[2] != '-')
+ return false;
+
+ if (permissions[3] == 'p')
+ region.permissions |= MappedMemoryRegion::PRIVATE;
+ else if (permissions[3] != 's' && permissions[3] != 'S') // Shared memory.
+ return false;
+
+ // Pushing then assigning saves us a string copy.
+ regions.push_back(region);
+ regions.back().path.assign(line + path_index);
+ regions.back().line.assign(line);
+ }
+
+ regions_out->swap(regions);
+ return true;
+}
+
+} // namespace google_breakpad
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/proc_maps_linux_unittest.cc b/toolkit/crashreporter/google-breakpad/src/processor/proc_maps_linux_unittest.cc
new file mode 100644
index 0000000000..466f23455e
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/proc_maps_linux_unittest.cc
@@ -0,0 +1,251 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "breakpad_googletest_includes.h"
+#include "common/using_std_string.h"
+#include "google_breakpad/processor/proc_maps_linux.h"
+
+namespace {
+
+TEST(ProcMapsTest, Empty) {
+ std::vector<google_breakpad::MappedMemoryRegion> regions;
+ EXPECT_TRUE(ParseProcMaps("", &regions));
+ EXPECT_EQ(0u, regions.size());
+}
+
+TEST(ProcMapsTest, NoSpaces) {
+ static const char kNoSpaces[] =
+ "00400000-0040b000 r-xp 00002200 fc:00 794418 /bin/cat\n";
+
+ std::vector<google_breakpad::MappedMemoryRegion> regions;
+ ASSERT_TRUE(ParseProcMaps(kNoSpaces, &regions));
+ ASSERT_EQ(1u, regions.size());
+
+ EXPECT_EQ(0x00400000u, regions[0].start);
+ EXPECT_EQ(0x0040b000u, regions[0].end);
+ EXPECT_EQ(0x00002200u, regions[0].offset);
+ EXPECT_EQ("/bin/cat", regions[0].path);
+}
+
+TEST(ProcMapsTest, Spaces) {
+ static const char kSpaces[] =
+ "00400000-0040b000 r-xp 00002200 fc:00 794418 /bin/space cat\n";
+
+ std::vector<google_breakpad::MappedMemoryRegion> regions;
+ ASSERT_TRUE(ParseProcMaps(kSpaces, &regions));
+ ASSERT_EQ(1u, regions.size());
+
+ EXPECT_EQ(0x00400000u, regions[0].start);
+ EXPECT_EQ(0x0040b000u, regions[0].end);
+ EXPECT_EQ(0x00002200u, regions[0].offset);
+ EXPECT_EQ("/bin/space cat", regions[0].path);
+}
+
+TEST(ProcMapsTest, NoNewline) {
+ static const char kNoSpaces[] =
+ "00400000-0040b000 r-xp 00002200 fc:00 794418 /bin/cat";
+
+ std::vector<google_breakpad::MappedMemoryRegion> regions;
+ ASSERT_FALSE(ParseProcMaps(kNoSpaces, &regions));
+}
+
+TEST(ProcMapsTest, NoPath) {
+ static const char kNoPath[] =
+ "00400000-0040b000 rw-p 00000000 00:00 0 \n";
+
+ std::vector<google_breakpad::MappedMemoryRegion> regions;
+ ASSERT_TRUE(ParseProcMaps(kNoPath, &regions));
+ ASSERT_EQ(1u, regions.size());
+
+ EXPECT_EQ(0x00400000u, regions[0].start);
+ EXPECT_EQ(0x0040b000u, regions[0].end);
+ EXPECT_EQ(0x00000000u, regions[0].offset);
+ EXPECT_EQ("", regions[0].path);
+}
+
+TEST(ProcMapsTest, Heap) {
+ static const char kHeap[] =
+ "022ac000-022cd000 rw-p 00000000 00:00 0 [heap]\n";
+
+ std::vector<google_breakpad::MappedMemoryRegion> regions;
+ ASSERT_TRUE(ParseProcMaps(kHeap, &regions));
+ ASSERT_EQ(1u, regions.size());
+
+ EXPECT_EQ(0x022ac000u, regions[0].start);
+ EXPECT_EQ(0x022cd000u, regions[0].end);
+ EXPECT_EQ(0x00000000u, regions[0].offset);
+ EXPECT_EQ("[heap]", regions[0].path);
+}
+
+#if defined(ARCH_CPU_32_BITS)
+TEST(ProcMapsTest, Stack32) {
+ static const char kStack[] =
+ "beb04000-beb25000 rw-p 00000000 00:00 0 [stack]\n";
+
+ std::vector<google_breakpad::MappedMemoryRegion> regions;
+ ASSERT_TRUE(ParseProcMaps(kStack, &regions));
+ ASSERT_EQ(1u, regions.size());
+
+ EXPECT_EQ(0xbeb04000u, regions[0].start);
+ EXPECT_EQ(0xbeb25000u, regions[0].end);
+ EXPECT_EQ(0x00000000u, regions[0].offset);
+ EXPECT_EQ("[stack]", regions[0].path);
+}
+#elif defined(ARCH_CPU_64_BITS)
+TEST(ProcMapsTest, Stack64) {
+ static const char kStack[] =
+ "7fff69c5b000-7fff69c7d000 rw-p 00000000 00:00 0 [stack]\n";
+
+ std::vector<google_breakpad::MappedMemoryRegion> regions;
+ ASSERT_TRUE(ParseProcMaps(kStack, &regions));
+ ASSERT_EQ(1u, regions.size());
+
+ EXPECT_EQ(0x7fff69c5b000u, regions[0].start);
+ EXPECT_EQ(0x7fff69c7d000u, regions[0].end);
+ EXPECT_EQ(0x00000000u, regions[0].offset);
+ EXPECT_EQ("[stack]", regions[0].path);
+}
+#endif
+
+TEST(ProcMapsTest, Multiple) {
+ static const char kMultiple[] =
+ "00400000-0040b000 r-xp 00000000 fc:00 794418 /bin/cat\n"
+ "0060a000-0060b000 r--p 0000a000 fc:00 794418 /bin/cat\n"
+ "0060b000-0060c000 rw-p 0000b000 fc:00 794418 /bin/cat\n";
+
+ std::vector<google_breakpad::MappedMemoryRegion> regions;
+ ASSERT_TRUE(ParseProcMaps(kMultiple, &regions));
+ ASSERT_EQ(3u, regions.size());
+
+ EXPECT_EQ(0x00400000u, regions[0].start);
+ EXPECT_EQ(0x0040b000u, regions[0].end);
+ EXPECT_EQ(0x00000000u, regions[0].offset);
+ EXPECT_EQ("/bin/cat", regions[0].path);
+
+ EXPECT_EQ(0x0060a000u, regions[1].start);
+ EXPECT_EQ(0x0060b000u, regions[1].end);
+ EXPECT_EQ(0x0000a000u, regions[1].offset);
+ EXPECT_EQ("/bin/cat", regions[1].path);
+
+ EXPECT_EQ(0x0060b000u, regions[2].start);
+ EXPECT_EQ(0x0060c000u, regions[2].end);
+ EXPECT_EQ(0x0000b000u, regions[2].offset);
+ EXPECT_EQ("/bin/cat", regions[2].path);
+}
+
+TEST(ProcMapsTest, Permissions) {
+ static struct {
+ const char* input;
+ uint8_t permissions;
+ } kTestCases[] = {
+ {"00400000-0040b000 ---s 00000000 fc:00 794418 /bin/cat\n", 0},
+ {"00400000-0040b000 ---S 00000000 fc:00 794418 /bin/cat\n", 0},
+ {"00400000-0040b000 r--s 00000000 fc:00 794418 /bin/cat\n",
+ google_breakpad::MappedMemoryRegion::READ},
+ {"00400000-0040b000 -w-s 00000000 fc:00 794418 /bin/cat\n",
+ google_breakpad::MappedMemoryRegion::WRITE},
+ {"00400000-0040b000 --xs 00000000 fc:00 794418 /bin/cat\n",
+ google_breakpad::MappedMemoryRegion::EXECUTE},
+ {"00400000-0040b000 rwxs 00000000 fc:00 794418 /bin/cat\n",
+ google_breakpad::MappedMemoryRegion::READ
+ | google_breakpad::MappedMemoryRegion::WRITE
+ | google_breakpad::MappedMemoryRegion::EXECUTE},
+ {"00400000-0040b000 ---p 00000000 fc:00 794418 /bin/cat\n",
+ google_breakpad::MappedMemoryRegion::PRIVATE},
+ {"00400000-0040b000 r--p 00000000 fc:00 794418 /bin/cat\n",
+ google_breakpad::MappedMemoryRegion::READ
+ | google_breakpad::MappedMemoryRegion::PRIVATE},
+ {"00400000-0040b000 -w-p 00000000 fc:00 794418 /bin/cat\n",
+ google_breakpad::MappedMemoryRegion::WRITE
+ | google_breakpad::MappedMemoryRegion::PRIVATE},
+ {"00400000-0040b000 --xp 00000000 fc:00 794418 /bin/cat\n",
+ google_breakpad::MappedMemoryRegion::EXECUTE
+ | google_breakpad::MappedMemoryRegion::PRIVATE},
+ {"00400000-0040b000 rwxp 00000000 fc:00 794418 /bin/cat\n",
+ google_breakpad::MappedMemoryRegion::READ
+ | google_breakpad::MappedMemoryRegion::WRITE
+ | google_breakpad::MappedMemoryRegion::EXECUTE
+ | google_breakpad::MappedMemoryRegion::PRIVATE},
+ };
+
+ for (size_t i = 0; i < sizeof(kTestCases) / sizeof(kTestCases[0]); ++i) {
+ std::vector<google_breakpad::MappedMemoryRegion> regions;
+ EXPECT_TRUE(ParseProcMaps(kTestCases[i].input, &regions));
+ EXPECT_EQ(1u, regions.size());
+ if (regions.empty())
+ continue;
+ EXPECT_EQ(kTestCases[i].permissions, regions[0].permissions);
+ }
+}
+
+TEST(ProcMapsTest, MissingFields) {
+ static const char* kTestCases[] = {
+ "00400000\n", // Missing end + beyond.
+ "00400000-0040b000\n", // Missing perms + beyond.
+ "00400000-0040b000 r-xp\n", // Missing offset + beyond.
+ "00400000-0040b000 r-xp 00000000\n", // Missing device + beyond.
+ "00400000-0040b000 r-xp 00000000 fc:00\n", // Missing inode + beyond.
+ "00400000-0040b000 00000000 fc:00 794418 /bin/cat\n", // Missing perms.
+ "00400000-0040b000 r-xp fc:00 794418 /bin/cat\n", // Missing offset.
+ "00400000-0040b000 r-xp 00000000 fc:00 /bin/cat\n", // Missing inode.
+ "00400000 r-xp 00000000 fc:00 794418 /bin/cat\n", // Missing end.
+ "-0040b000 r-xp 00000000 fc:00 794418 /bin/cat\n", // Missing start.
+ "00400000-0040b000 r-xp 00000000 794418 /bin/cat\n", // Missing device.
+ };
+
+ for (size_t i = 0; i < sizeof(kTestCases) / sizeof(kTestCases[0]); ++i) {
+ std::vector<google_breakpad::MappedMemoryRegion> regions;
+ EXPECT_FALSE(ParseProcMaps(kTestCases[i], &regions));
+ }
+}
+
+TEST(ProcMapsTest, InvalidInput) {
+ static const char* kTestCases[] = {
+ "thisisal-0040b000 rwxp 00000000 fc:00 794418 /bin/cat\n",
+ "0040000d-linvalid rwxp 00000000 fc:00 794418 /bin/cat\n",
+ "00400000-0040b000 inpu 00000000 fc:00 794418 /bin/cat\n",
+ "00400000-0040b000 rwxp tforproc fc:00 794418 /bin/cat\n",
+ "00400000-0040b000 rwxp 00000000 ma:ps 794418 /bin/cat\n",
+ "00400000-0040b000 rwxp 00000000 fc:00 parse! /bin/cat\n",
+ };
+
+ for (size_t i = 0; i < sizeof(kTestCases) / sizeof(kTestCases[0]); ++i) {
+ std::vector<google_breakpad::MappedMemoryRegion> regions;
+ EXPECT_FALSE(ParseProcMaps(kTestCases[i], &regions));
+ }
+}
+
+TEST(ProcMapsTest, ParseProcMapsEmptyString) {
+ std::vector<google_breakpad::MappedMemoryRegion> regions;
+ EXPECT_TRUE(ParseProcMaps("", &regions));
+ EXPECT_EQ(0ULL, regions.size());
+}
+
+// Testing a couple of remotely possible weird things in the input:
+// - Line ending with \r\n or \n\r.
+// - File name contains quotes.
+// - File name has whitespaces.
+TEST(ProcMapsTest, ParseProcMapsWeirdCorrectInput) {
+ std::vector<google_breakpad::MappedMemoryRegion> regions;
+ const string kContents =
+ "00400000-0040b000 r-xp 00000000 fc:00 2106562 "
+ " /bin/cat\r\n"
+ "7f53b7dad000-7f53b7f62000 r-xp 00000000 fc:00 263011 "
+ " /lib/x86_64-linux-gnu/libc-2.15.so\n\r"
+ "7f53b816d000-7f53b818f000 r-xp 00000000 fc:00 264284 "
+ " /lib/x86_64-linux-gnu/ld-2.15.so\n"
+ "7fff9c7ff000-7fff9c800000 r-xp 00000000 00:00 0 "
+ " \"vd so\"\n"
+ "ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 "
+ " [vsys call]\n";
+ EXPECT_TRUE(ParseProcMaps(kContents, &regions));
+ EXPECT_EQ(5ULL, regions.size());
+ EXPECT_EQ("/bin/cat", regions[0].path);
+ EXPECT_EQ("/lib/x86_64-linux-gnu/libc-2.15.so", regions[1].path);
+ EXPECT_EQ("/lib/x86_64-linux-gnu/ld-2.15.so", regions[2].path);
+ EXPECT_EQ("\"vd so\"", regions[3].path);
+ EXPECT_EQ("[vsys call]", regions[4].path);
+}
+
+} // namespace
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/process_state.cc b/toolkit/crashreporter/google-breakpad/src/processor/process_state.cc
new file mode 100644
index 0000000000..43c4a4b8b0
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/process_state.cc
@@ -0,0 +1,71 @@
+// 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.
+
+// process_state.cc: A snapshot of a process, in a fully-digested state.
+//
+// See process_state.h for documentation.
+//
+// Author: Mark Mentovai
+
+#include "google_breakpad/processor/process_state.h"
+#include "google_breakpad/processor/call_stack.h"
+#include "google_breakpad/processor/code_modules.h"
+
+namespace google_breakpad {
+
+ProcessState::~ProcessState() {
+ Clear();
+}
+
+void ProcessState::Clear() {
+ time_date_stamp_ = 0;
+ process_create_time_ = 0;
+ crashed_ = false;
+ crash_reason_.clear();
+ crash_address_ = 0;
+ assertion_.clear();
+ requesting_thread_ = -1;
+ for (vector<CallStack *>::const_iterator iterator = threads_.begin();
+ iterator != threads_.end();
+ ++iterator) {
+ delete *iterator;
+ }
+ threads_.clear();
+ system_info_.Clear();
+ // modules_without_symbols_ and modules_with_corrupt_symbols_ DO NOT own
+ // the underlying CodeModule pointers. Just clear the vectors.
+ modules_without_symbols_.clear();
+ modules_with_corrupt_symbols_.clear();
+ delete modules_;
+ modules_ = NULL;
+ delete unloaded_modules_;
+ unloaded_modules_ = NULL;
+}
+
+} // namespace google_breakpad
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/processor.gyp b/toolkit/crashreporter/google-breakpad/src/processor/processor.gyp
new file mode 100644
index 0000000000..93896c0e98
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/processor.gyp
@@ -0,0 +1,187 @@
+# 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.
+
+{
+ 'includes': [
+ '../build/common.gypi',
+ 'processor_tools.gypi',
+ ],
+ 'targets': [
+ {
+ 'target_name': 'processor',
+ 'type': 'static_library',
+ 'sources': [
+ 'address_map-inl.h',
+ 'address_map.h',
+ 'basic_code_module.h',
+ 'basic_code_modules.cc',
+ 'basic_code_modules.h',
+ 'basic_source_line_resolver.cc',
+ 'basic_source_line_resolver_types.h',
+ 'call_stack.cc',
+ 'cfi_frame_info-inl.h',
+ 'cfi_frame_info.cc',
+ 'cfi_frame_info.h',
+ 'contained_range_map-inl.h',
+ 'contained_range_map.h',
+ 'convert_old_arm64_context.cc',
+ 'convert_old_arm64_context.h',
+ 'disassembler_x86.cc',
+ 'disassembler_x86.h',
+ 'dump_context.cc',
+ 'dump_object.cc',
+ 'exploitability.cc',
+ 'exploitability_linux.cc',
+ 'exploitability_linux.h',
+ 'exploitability_win.cc',
+ 'exploitability_win.h',
+ 'fast_source_line_resolver.cc',
+ 'fast_source_line_resolver_types.h',
+ 'linked_ptr.h',
+ 'logging.cc',
+ 'logging.h',
+ 'map_serializers-inl.h',
+ 'map_serializers.h',
+ 'microdump_processor.cc',
+ 'minidump.cc',
+ 'minidump_processor.cc',
+ 'module_comparer.cc',
+ 'module_comparer.h',
+ 'module_factory.h',
+ 'module_serializer.cc',
+ 'module_serializer.h',
+ 'pathname_stripper.cc',
+ 'pathname_stripper.h',
+ 'postfix_evaluator-inl.h',
+ 'postfix_evaluator.h',
+ 'proc_maps_linux.cc',
+ 'process_state.cc',
+ 'range_map-inl.h',
+ 'range_map.h',
+ 'simple_serializer-inl.h',
+ 'simple_serializer.h',
+ 'simple_symbol_supplier.cc',
+ 'simple_symbol_supplier.h',
+ 'source_line_resolver_base.cc',
+ 'source_line_resolver_base_types.h',
+ 'stack_frame_cpu.cc',
+ 'stack_frame_symbolizer.cc',
+ 'stackwalk_common.cc',
+ 'stackwalk_common.h',
+ 'stackwalker.cc',
+ 'stackwalker_address_list.cc',
+ 'stackwalker_address_list.h',
+ 'stackwalker_amd64.cc',
+ 'stackwalker_amd64.h',
+ 'stackwalker_arm.cc',
+ 'stackwalker_arm.h',
+ 'stackwalker_arm64.cc',
+ 'stackwalker_arm64.h',
+ 'stackwalker_mips.cc',
+ 'stackwalker_mips.h',
+ 'stackwalker_ppc.cc',
+ 'stackwalker_ppc.h',
+ 'stackwalker_ppc64.cc',
+ 'stackwalker_ppc64.h',
+ 'stackwalker_selftest.cc',
+ 'stackwalker_sparc.cc',
+ 'stackwalker_sparc.h',
+ 'stackwalker_x86.cc',
+ 'stackwalker_x86.h',
+ 'static_address_map-inl.h',
+ 'static_address_map.h',
+ 'static_contained_range_map-inl.h',
+ 'static_contained_range_map.h',
+ 'static_map-inl.h',
+ 'static_map.h',
+ 'static_map_iterator-inl.h',
+ 'static_map_iterator.h',
+ 'static_range_map-inl.h',
+ 'static_range_map.h',
+ 'symbolic_constants_win.cc',
+ 'symbolic_constants_win.h',
+ 'synth_minidump.cc',
+ 'synth_minidump.h',
+ 'tokenize.cc',
+ 'tokenize.h',
+ 'windows_frame_info.h',
+ ],
+ 'include_dirs': [
+ '..',
+ ],
+ 'dependencies': [
+ '../common/common.gyp:common',
+ '../third_party/libdisasm/libdisasm.gyp:libdisasm',
+ ],
+ },
+ {
+ 'target_name': 'processor_unittests',
+ 'type': 'executable',
+ 'sources': [
+ 'address_map_unittest.cc',
+ 'basic_source_line_resolver_unittest.cc',
+ 'cfi_frame_info_unittest.cc',
+ 'contained_range_map_unittest.cc',
+ 'disassembler_x86_unittest.cc',
+ 'exploitability_unittest.cc',
+ 'fast_source_line_resolver_unittest.cc',
+ 'map_serializers_unittest.cc',
+ 'microdump_processor_unittest.cc',
+ 'minidump_processor_unittest.cc',
+ 'minidump_unittest.cc',
+ 'pathname_stripper_unittest.cc',
+ 'postfix_evaluator_unittest.cc',
+ 'range_map_truncate_lower_unittest.cc',
+ 'range_map_truncate_upper_unittest.cc',
+ 'range_map_unittest.cc',
+ 'stackwalker_address_list_unittest.cc',
+ 'stackwalker_amd64_unittest.cc',
+ 'stackwalker_arm64_unittest.cc',
+ 'stackwalker_arm_unittest.cc',
+ 'stackwalker_mips_unittest.cc',
+ 'stackwalker_mips64_unittest.cc',
+ 'stackwalker_unittest_utils.h',
+ 'stackwalker_x86_unittest.cc',
+ 'static_address_map_unittest.cc',
+ 'static_contained_range_map_unittest.cc',
+ 'static_map_unittest.cc',
+ 'static_range_map_unittest.cc',
+ 'synth_minidump_unittest.cc',
+ 'synth_minidump_unittest_data.h',
+ ],
+ 'include_dirs': [
+ '..',
+ ],
+ 'dependencies': [
+ 'processor',
+ '../build/testing.gyp:gmock',
+ '../build/testing.gyp:gtest',
+ ],
+ },
+ ],
+}
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/processor_tools.gypi b/toolkit/crashreporter/google-breakpad/src/processor/processor_tools.gypi
new file mode 100644
index 0000000000..ecb450d602
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/processor_tools.gypi
@@ -0,0 +1,57 @@
+# 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': {
+ 'include_dirs': [
+ '..',
+ ],
+ },
+ 'targets': [
+ {
+ 'target_name': 'minidump_dump',
+ 'type': 'executable',
+ 'sources': [
+ 'minidump_dump.cc',
+ ],
+ 'dependencies': [
+ 'processor',
+ ],
+ },
+ {
+ 'target_name': 'minidump_stackwalk',
+ 'type': 'executable',
+ 'sources': [
+ 'minidump_stackwalk.cc',
+ ],
+ 'dependencies': [
+ 'processor',
+ ],
+ },
+ ],
+}
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/proto/README b/toolkit/crashreporter/google-breakpad/src/processor/proto/README
new file mode 100644
index 0000000000..f9e5a4d301
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/proto/README
@@ -0,0 +1,20 @@
+If you wish to use these protobufs, you must generate their source files
+using protoc from the protobuf project (https://github.com/google/protobuf).
+
+-----
+Troubleshooting for Protobuf:
+
+Install:
+If you are getting permission errors install, make sure you are not trying to
+install from an NFS.
+
+
+Running protoc:
+protoc: error while loading shared libraries: libprotobuf.so.0: cannot open
+shared object file: No such file or directory
+
+The issue is that Ubuntu 8.04 doesn't include /usr/local/lib in
+library paths.
+
+To fix it for your current terminal session, just type in
+export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/proto/process_state.proto b/toolkit/crashreporter/google-breakpad/src/processor/proto/process_state.proto
new file mode 100644
index 0000000000..d3e02dc3f4
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/proto/process_state.proto
@@ -0,0 +1,210 @@
+// 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.
+
+// process_state_proto.proto: A client proto representation of a process,
+// in a fully-digested state.
+//
+// Derived from earlier struct and class based models of a client-side
+// processed minidump found under src/google_breakpad/processor. The
+// file process_state.h holds the top level representation of this model,
+// supported by additional classes. We've added a proto representation
+// to ease serialization and parsing for server-side storage of crash
+// reports processed on the client.
+//
+// Author: Jess Gray
+
+syntax = "proto2";
+
+package google_breakpad;
+
+// A proto representation of a process, in a fully-digested state.
+// See src/google_breakpad/processor/process_state.h
+message ProcessStateProto {
+ // Next value: 14
+
+ // The time-date stamp of the original minidump (time_t format)
+ optional int64 time_date_stamp = 1;
+
+ // The time-date stamp when the process was created (time_t format)
+ optional int64 process_create_time = 13;
+
+ message Crash {
+ // The type of crash. OS- and possibly CPU- specific. For example,
+ // "EXCEPTION_ACCESS_VIOLATION" (Windows), "EXC_BAD_ACCESS /
+ // KERN_INVALID_ADDRESS" (Mac OS X), "SIGSEGV" (other Unix).
+ required string reason = 1;
+
+ // If crash_reason implicates memory, the memory address that caused the
+ // crash. For data access errors, this will be the data address that
+ // caused the fault. For code errors, this will be the address of the
+ // instruction that caused the fault.
+ required int64 address = 2;
+ }
+ optional Crash crash = 2;
+
+
+ // If there was an assertion that was hit, a textual representation
+ // of that assertion, possibly including the file and line at which
+ // it occurred.
+ optional string assertion = 3;
+
+ // The index of the thread that requested a dump be written in the
+ // threads vector. If a dump was produced as a result of a crash, this
+ // will point to the thread that crashed. If the dump was produced as
+ // by user code without crashing, and the dump contains extended Breakpad
+ // information, this will point to the thread that requested the dump.
+ optional int32 requesting_thread = 4;
+
+ message Thread {
+ // Stack for the given thread
+ repeated StackFrame frames = 1;
+ }
+
+ // Stacks for each thread (except possibly the exception handler
+ // thread) at the time of the crash.
+ repeated Thread threads = 5;
+
+ // The modules that were loaded into the process represented by the
+ // ProcessState.
+ repeated CodeModule modules = 6;
+
+ // System Info: OS and CPU
+
+ // A string identifying the operating system, such as "Windows NT",
+ // "Mac OS X", or "Linux". If the information is present in the dump but
+ // its value is unknown, this field will contain a numeric value. If
+ // the information is not present in the dump, this field will be empty.
+ optional string os = 7;
+
+ // A short form of the os string, using lowercase letters and no spaces,
+ // suitable for use in a filesystem. Possible values are "windows",
+ // "mac", and "linux". Empty if the information is not present in the dump
+ // or if the OS given by the dump is unknown. The values stored in this
+ // field should match those used by MinidumpSystemInfo::GetOS.
+ optional string os_short = 8;
+
+ // A string identifying the version of the operating system, such as
+ // "5.1.2600 Service Pack 2" or "10.4.8 8L2127". If the dump does not
+ // contain this information, this field will be empty.
+ optional string os_version = 9;
+
+ // A string identifying the basic CPU family, such as "x86" or "ppc".
+ // If this information is present in the dump but its value is unknown,
+ // this field will contain a numeric value. If the information is not
+ // present in the dump, this field will be empty. The values stored in
+ // this field should match those used by MinidumpSystemInfo::GetCPU.
+ optional string cpu = 10;
+
+ // A string further identifying the specific CPU, such as
+ // "GenuineIntel level 6 model 13 stepping 8". If the information is not
+ // present in the dump, or additional identifying information is not
+ // defined for the CPU family, this field will be empty.
+ optional string cpu_info = 11;
+
+ // The number of processors in the system. Will be greater than one for
+ // multi-core systems.
+ optional int32 cpu_count = 12;
+
+ // Leave the ability to add the raw minidump to this representation
+}
+
+
+// Represents a single frame in a stack
+// See src/google_breakpad/processor/code_module.h
+message StackFrame {
+ // Next value: 8
+
+ // The program counter location as an absolute virtual address. For the
+ // innermost called frame in a stack, this will be an exact program counter
+ // or instruction pointer value. For all other frames, this will be within
+ // the instruction that caused execution to branch to a called function,
+ // but may not necessarily point to the exact beginning of that instruction.
+ required int64 instruction = 1;
+
+ // The module in which the instruction resides.
+ optional CodeModule module = 2;
+
+ // The function name, may be omitted if debug symbols are not available.
+ optional string function_name = 3;
+
+ // The start address of the function, may be omitted if debug symbols
+ // are not available.
+ optional int64 function_base = 4;
+
+ // The source file name, may be omitted if debug symbols are not available.
+ optional string source_file_name = 5;
+
+ // The (1-based) source line number, may be omitted if debug symbols are
+ // not available.
+ optional int32 source_line = 6;
+
+ // The start address of the source line, may be omitted if debug symbols
+ // are not available.
+ optional int64 source_line_base = 7;
+}
+
+
+// Carries information about code modules that are loaded into a process.
+// See src/google_breakpad/processor/code_module.h
+message CodeModule {
+ // Next value: 8
+
+ // The base address of this code module as it was loaded by the process.
+ optional int64 base_address = 1;
+
+ // The size of the code module.
+ optional int64 size = 2;
+
+ // The path or file name that the code module was loaded from.
+ optional string code_file = 3;
+
+ // An identifying string used to discriminate between multiple versions and
+ // builds of the same code module. This may contain a uuid, timestamp,
+ // version number, or any combination of this or other information, in an
+ // implementation-defined format.
+ optional string code_identifier = 4;
+
+ // The filename containing debugging information associated with the code
+ // module. If debugging information is stored in a file separate from the
+ // code module itself (as is the case when .pdb or .dSYM files are used),
+ // this will be different from code_file. If debugging information is
+ // stored in the code module itself (possibly prior to stripping), this
+ // will be the same as code_file.
+ optional string debug_file = 5;
+
+ // An identifying string similar to code_identifier, but identifies a
+ // specific version and build of the associated debug file. This may be
+ // the same as code_identifier when the debug_file and code_file are
+ // identical or when the same identifier is used to identify distinct
+ // debug and code files.
+ optional string debug_identifier = 6;
+
+ // A human-readable representation of the code module's version.
+ optional string version = 7;
+}
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/range_map-inl.h b/toolkit/crashreporter/google-breakpad/src/processor/range_map-inl.h
new file mode 100644
index 0000000000..4d3b0eb96f
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/range_map-inl.h
@@ -0,0 +1,291 @@
+// 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.
+
+// range_map-inl.h: Range map implementation.
+//
+// See range_map.h for documentation.
+//
+// Author: Mark Mentovai
+
+#ifndef PROCESSOR_RANGE_MAP_INL_H__
+#define PROCESSOR_RANGE_MAP_INL_H__
+
+
+#include <assert.h>
+
+#include "processor/range_map.h"
+#include "processor/linked_ptr.h"
+#include "processor/logging.h"
+
+
+namespace google_breakpad {
+
+template<typename AddressType, typename EntryType>
+bool RangeMap<AddressType, EntryType>::StoreRange(const AddressType &base,
+ const AddressType &size,
+ const EntryType &entry) {
+ return StoreRangeInternal(base, 0 /* delta */, size, entry);
+}
+
+template<typename AddressType, typename EntryType>
+bool RangeMap<AddressType, EntryType>::StoreRangeInternal(
+ const AddressType &base, const AddressType &delta,
+ const AddressType &size, const EntryType &entry) {
+ AddressType high = base + (size - 1);
+
+ // Check for undersize or overflow.
+ if (size <= 0 || high < base) {
+ // The processor will hit this case too frequently with common symbol
+ // files in the size == 0 case, which is more suited to a DEBUG channel.
+ // Filter those out since there's no DEBUG channel at the moment.
+ BPLOG_IF(INFO, size != 0) << "StoreRangeInternal failed, "
+ << HexString(base) << "+" << HexString(size)
+ << ", " << HexString(high)
+ << ", delta: " << HexString(delta);
+ return false;
+ }
+
+ // Ensure that this range does not overlap with another one already in the
+ // map.
+ MapConstIterator iterator_base = map_.lower_bound(base);
+ MapConstIterator iterator_high = map_.lower_bound(high);
+
+ if (iterator_base != iterator_high) {
+ // Some other range ends in the space used by this range. It may be
+ // contained within the space used by this range, or it may extend lower.
+ if (merge_strategy_ == MergeRangeStrategy::kTruncateLower) {
+ // kTruncate the range with the lower base address.
+ AddressType other_base = iterator_base->second.base();
+ if (base < other_base) {
+ return StoreRangeInternal(base, delta, other_base - base, entry);
+ } else if (other_base < base) {
+ EntryType other_entry;
+ AddressType other_high, other_size, other_delta;
+ other_high = iterator_base->first;
+ RetrieveRange(other_high, &other_entry, &other_base, &other_delta,
+ &other_size);
+ map_.erase(iterator_base);
+ map_.insert(
+ MapValue(base - 1, Range(other_base, other_delta, other_entry)));
+ return StoreRangeInternal(base, delta, size, entry);
+ } else {
+ return false;
+ }
+ } else if (merge_strategy_ == MergeRangeStrategy::kTruncateUpper) {
+ // Truncate the lower portion of this range.
+ AddressType additional_delta = iterator_base->first - base + 1;
+ return StoreRangeInternal(base + additional_delta,
+ delta + additional_delta,
+ size - additional_delta, entry);
+ } else {
+ // The processor hits this case too frequently with common symbol files.
+ // This is most appropriate for a DEBUG channel, but since none exists
+ // now simply comment out this logging.
+ // AddressType other_base = iterator_base->second.base();
+ // AddressType other_size = iterator_base->first - other_base + 1;
+ // BPLOG(INFO) << "StoreRangeInternal failed, an existing range is "
+ // << "overlapping with the new range: new "
+ // << HexString(base) << "+" << HexString(size)
+ // << ", existing " << HexString(other_base) << "+"
+ // << HexString(other_size);
+ return false;
+ }
+ }
+
+ if (iterator_high != map_.end() && iterator_high->second.base() <= high) {
+ // The range above this one overlaps with this one. It may fully
+ // contain this range, or it may begin within this range and extend
+ // higher.
+ if (merge_strategy_ == MergeRangeStrategy::kTruncateLower) {
+ AddressType other_base = iterator_high->second.base();
+ if (base < other_base) {
+ return StoreRangeInternal(base, delta, other_base - base, entry);
+ } else if (other_base < base) {
+ EntryType other_entry;
+ AddressType other_high, other_size, other_delta;
+ other_high = iterator_high->first;
+ RetrieveRange(other_high, &other_entry, &other_base, &other_delta,
+ &other_size);
+ map_.erase(iterator_high);
+ map_.insert(
+ MapValue(base - 1, Range(other_base, other_delta, other_entry)));
+ return StoreRangeInternal(base, delta, size, entry);
+ } else {
+ return false;
+ }
+ } else if (merge_strategy_ == MergeRangeStrategy::kTruncateUpper &&
+ iterator_high->first > high) {
+ // Shrink the other range down.
+ AddressType other_high = iterator_high->first;
+ AddressType additional_delta = high - iterator_high->second.base() + 1;
+ EntryType other_entry;
+ AddressType other_base = AddressType();
+ AddressType other_size = AddressType();
+ AddressType other_delta = AddressType();
+ RetrieveRange(other_high, &other_entry, &other_base, &other_delta,
+ &other_size);
+ map_.erase(iterator_high);
+ map_.insert(MapValue(other_high,
+ Range(other_base + additional_delta,
+ other_delta + additional_delta, other_entry)));
+ // Retry to store this range.
+ return StoreRangeInternal(base, delta, size, entry);
+ } else {
+ // The processor hits this case too frequently with common symbol files.
+ // This is most appropriate for a DEBUG channel, but since none exists
+ // now simply comment out this logging.
+ //
+ // AddressType other_base = iterator_high->second.base();
+ // AddressType other_size = iterator_high->first - other_base + 1;
+ // BPLOG(INFO) << "StoreRangeInternal failed, an existing range "
+ // << "contains or extends higher than the new range: new "
+ // << HexString(base) << "+" << HexString(size)
+ // << ", existing " << HexString(other_base) << "+"
+ // << HexString(other_size);
+ return false;
+ }
+ }
+
+ // Store the range in the map by its high address, so that lower_bound can
+ // be used to quickly locate a range by address.
+ map_.insert(MapValue(high, Range(base, delta, entry)));
+ return true;
+}
+
+
+template<typename AddressType, typename EntryType>
+bool RangeMap<AddressType, EntryType>::RetrieveRange(
+ const AddressType &address, EntryType *entry, AddressType *entry_base,
+ AddressType *entry_delta, AddressType *entry_size) const {
+ BPLOG_IF(ERROR, !entry) << "RangeMap::RetrieveRange requires |entry|";
+ assert(entry);
+
+ MapConstIterator iterator = map_.lower_bound(address);
+ if (iterator == map_.end())
+ return false;
+
+ // The map is keyed by the high address of each range, so |address| is
+ // guaranteed to be lower than the range's high address. If |range| is
+ // not directly preceded by another range, it's possible for address to
+ // be below the range's low address, though. When that happens, address
+ // references something not within any range, so return false.
+ if (address < iterator->second.base())
+ return false;
+
+ *entry = iterator->second.entry();
+ if (entry_base)
+ *entry_base = iterator->second.base();
+ if (entry_delta)
+ *entry_delta = iterator->second.delta();
+ if (entry_size)
+ *entry_size = iterator->first - iterator->second.base() + 1;
+
+ return true;
+}
+
+
+template<typename AddressType, typename EntryType>
+bool RangeMap<AddressType, EntryType>::RetrieveNearestRange(
+ const AddressType &address, EntryType *entry, AddressType *entry_base,
+ AddressType *entry_delta, AddressType *entry_size) const {
+ BPLOG_IF(ERROR, !entry) << "RangeMap::RetrieveNearestRange requires |entry|";
+ assert(entry);
+
+ // If address is within a range, RetrieveRange can handle it.
+ if (RetrieveRange(address, entry, entry_base, entry_delta, entry_size))
+ return true;
+
+ // upper_bound gives the first element whose key is greater than address,
+ // but we want the first element whose key is less than or equal to address.
+ // Decrement the iterator to get there, but not if the upper_bound already
+ // points to the beginning of the map - in that case, address is lower than
+ // the lowest stored key, so return false.
+ MapConstIterator iterator = map_.upper_bound(address);
+ if (iterator == map_.begin())
+ return false;
+ --iterator;
+
+ *entry = iterator->second.entry();
+ if (entry_base)
+ *entry_base = iterator->second.base();
+ if (entry_delta)
+ *entry_delta = iterator->second.delta();
+ if (entry_size)
+ *entry_size = iterator->first - iterator->second.base() + 1;
+
+ return true;
+}
+
+
+template<typename AddressType, typename EntryType>
+bool RangeMap<AddressType, EntryType>::RetrieveRangeAtIndex(
+ int index, EntryType *entry, AddressType *entry_base,
+ AddressType *entry_delta, AddressType *entry_size) const {
+ BPLOG_IF(ERROR, !entry) << "RangeMap::RetrieveRangeAtIndex requires |entry|";
+ assert(entry);
+
+ if (index >= GetCount()) {
+ BPLOG(ERROR) << "Index out of range: " << index << "/" << GetCount();
+ return false;
+ }
+
+ // Walk through the map. Although it's ordered, it's not a vector, so it
+ // can't be addressed directly by index.
+ MapConstIterator iterator = map_.begin();
+ for (int this_index = 0; this_index < index; ++this_index)
+ ++iterator;
+
+ *entry = iterator->second.entry();
+ if (entry_base)
+ *entry_base = iterator->second.base();
+ if (entry_delta)
+ *entry_delta = iterator->second.delta();
+ if (entry_size)
+ *entry_size = iterator->first - iterator->second.base() + 1;
+
+ return true;
+}
+
+
+template<typename AddressType, typename EntryType>
+int RangeMap<AddressType, EntryType>::GetCount() const {
+ return static_cast<int>(map_.size());
+}
+
+
+template<typename AddressType, typename EntryType>
+void RangeMap<AddressType, EntryType>::Clear() {
+ map_.clear();
+}
+
+
+} // namespace google_breakpad
+
+
+#endif // PROCESSOR_RANGE_MAP_INL_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/range_map.h b/toolkit/crashreporter/google-breakpad/src/processor/range_map.h
new file mode 100644
index 0000000000..33f3297349
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/range_map.h
@@ -0,0 +1,171 @@
+// 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.
+
+// range_map.h: Range maps.
+//
+// A range map associates a range of addresses with a specific object. This
+// is useful when certain objects of variable size are located within an
+// address space. The range map makes it simple to determine which object is
+// associated with a specific address, which may be any address within the
+// range associated with an object.
+//
+// Author: Mark Mentovai
+
+#ifndef PROCESSOR_RANGE_MAP_H__
+#define PROCESSOR_RANGE_MAP_H__
+
+
+#include <map>
+
+
+namespace google_breakpad {
+
+// Forward declarations (for later friend declarations of specialized template).
+template<class, class> class RangeMapSerializer;
+
+// Determines what happens when two ranges overlap.
+enum class MergeRangeStrategy {
+ // When two ranges overlap, the new range fails to be inserted. The default
+ // strategy.
+ kExclusiveRanges,
+
+ // The range with the lower base address will be truncated such that it's
+ // high address is one less than the range above it.
+ kTruncateLower,
+
+ // The range with the greater high address has its range truncated such that
+ // its base address is one higher than the range below it.
+ kTruncateUpper
+};
+
+template<typename AddressType, typename EntryType>
+class RangeMap {
+ public:
+ RangeMap() : merge_strategy_(MergeRangeStrategy::kExclusiveRanges), map_() {}
+
+ void SetMergeStrategy(MergeRangeStrategy strat) { merge_strategy_ = strat; }
+
+ MergeRangeStrategy GetMergeStrategy() const { return merge_strategy_; }
+
+ // Inserts a range into the map. Returns false for a parameter error,
+ // or if the location of the range would conflict with a range already
+ // stored in the map. If enable_shrink_down is true and there is an overlap
+ // between the current range and some other range (already in the map),
+ // shrink down the range which ends at a higher address.
+ bool StoreRange(const AddressType &base, const AddressType &size,
+ const EntryType &entry);
+
+ // Locates the range encompassing the supplied address. If there is no such
+ // range, returns false. entry_base, entry_delta, and entry_size, if
+ // non-NULL, are set to the base, delta, and size of the entry's range.
+ // A positive entry delta (> 0) indicates that there was an overlap and the
+ // entry was shrunk down (original start address was increased by delta).
+ bool RetrieveRange(const AddressType &address, EntryType *entry,
+ AddressType *entry_base, AddressType *entry_delta,
+ AddressType *entry_size) const;
+
+ // Locates the range encompassing the supplied address, if one exists.
+ // If no range encompasses the supplied address, locates the nearest range
+ // to the supplied address that is lower than the address. Returns false
+ // if no range meets these criteria. entry_base, entry_delta, and entry_size,
+ // if non-NULL, are set to the base, delta, and size of the entry's range.
+ // A positive entry delta (> 0) indicates that there was an overlap and the
+ // entry was shrunk down (original start address was increased by delta).
+ bool RetrieveNearestRange(const AddressType &address, EntryType *entry,
+ AddressType *entry_base, AddressType *entry_delta,
+ AddressType *entry_size) const;
+
+ // Treating all ranges as a list ordered by the address spaces that they
+ // occupy, locates the range at the index specified by index. Returns
+ // false if index is larger than the number of ranges stored. entry_base,
+ // entry_delta, and entry_size, if non-NULL, are set to the base, delta, and
+ // size of the entry's range.
+ // A positive entry delta (> 0) indicates that there was an overlap and the
+ // entry was shrunk down (original start address was increased by delta).
+ //
+ // RetrieveRangeAtIndex is not optimized for speedy operation.
+ bool RetrieveRangeAtIndex(int index, EntryType *entry,
+ AddressType *entry_base, AddressType *entry_delta,
+ AddressType *entry_size) const;
+
+ // Returns the number of ranges stored in the RangeMap.
+ int GetCount() const;
+
+ // Empties the range map, restoring it to the state it was when it was
+ // initially created.
+ void Clear();
+
+ private:
+ // Friend declarations.
+ friend class ModuleComparer;
+ friend class RangeMapSerializer<AddressType, EntryType>;
+
+ // Same a StoreRange() with the only exception that the |delta| can be
+ // passed in.
+ bool StoreRangeInternal(const AddressType &base, const AddressType &delta,
+ const AddressType &size, const EntryType &entry);
+
+ class Range {
+ public:
+ Range(const AddressType &base, const AddressType &delta,
+ const EntryType &entry)
+ : base_(base), delta_(delta), entry_(entry) {}
+
+ AddressType base() const { return base_; }
+ AddressType delta() const { return delta_; }
+ EntryType entry() const { return entry_; }
+
+ private:
+ // The base address of the range. The high address does not need to
+ // be stored, because RangeMap uses it as the key to the map.
+ const AddressType base_;
+
+ // The delta when the range is shrunk down.
+ const AddressType delta_;
+
+ // The entry corresponding to a range.
+ const EntryType entry_;
+ };
+
+ // Convenience types.
+ typedef std::map<AddressType, Range> AddressToRangeMap;
+ typedef typename AddressToRangeMap::const_iterator MapConstIterator;
+ typedef typename AddressToRangeMap::value_type MapValue;
+
+ MergeRangeStrategy merge_strategy_;
+
+ // Maps the high address of each range to a EntryType.
+ AddressToRangeMap map_;
+};
+
+
+} // namespace google_breakpad
+
+
+#endif // PROCESSOR_RANGE_MAP_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/range_map_truncate_lower_unittest.cc b/toolkit/crashreporter/google-breakpad/src/processor/range_map_truncate_lower_unittest.cc
new file mode 100644
index 0000000000..a933c956f5
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/range_map_truncate_lower_unittest.cc
@@ -0,0 +1,346 @@
+// Copyright (c) 2019, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
+
+#include <limits.h>
+#include <stdio.h>
+
+#include "processor/range_map-inl.h"
+
+#include "breakpad_googletest_includes.h"
+#include "processor/linked_ptr.h"
+#include "processor/logging.h"
+
+namespace {
+
+using google_breakpad::linked_ptr;
+using google_breakpad::MergeRangeStrategy;
+using google_breakpad::RangeMap;
+
+// A CountedObject holds an int. A global (not thread safe!) count of
+// allocated CountedObjects is maintained to help test memory management.
+class CountedObject {
+ public:
+ explicit CountedObject(int id) : id_(id) { ++count_; }
+ ~CountedObject() { --count_; }
+
+ static int count() { return count_; }
+ int id() const { return id_; }
+
+ private:
+ static int count_;
+ int id_;
+};
+
+int CountedObject::count_;
+
+typedef int AddressType;
+typedef RangeMap<AddressType, linked_ptr<CountedObject>> TestMap;
+
+// Same range cannot be stored wice.
+TEST(RangeMapTruncateLower, SameRange) {
+ TestMap range_map;
+ range_map.SetMergeStrategy(MergeRangeStrategy::kTruncateLower);
+ linked_ptr<CountedObject> object_1(new CountedObject(1));
+ EXPECT_TRUE(
+ range_map.StoreRange(0 /* base address */, 100 /* size */, object_1));
+
+ // Same range cannot be stored wice.
+ linked_ptr<CountedObject> object_2(new CountedObject(2));
+ EXPECT_FALSE(
+ range_map.StoreRange(0 /* base address */, 100 /* size */, object_2));
+}
+
+// If a range is completely contained by another range, then the larger range
+// should be truncated.
+TEST(RangeMapTruncateLower, CompletelyContained) {
+ TestMap range_map;
+ range_map.SetMergeStrategy(MergeRangeStrategy::kTruncateLower);
+ // Larger range is added first.
+ linked_ptr<CountedObject> object_1(new CountedObject(1));
+ EXPECT_TRUE(
+ range_map.StoreRange(0 /* base address */, 100 /* size */, object_1));
+ // Smaller (contained) range is added second.
+ linked_ptr<CountedObject> object_2(new CountedObject(2));
+ EXPECT_TRUE(
+ range_map.StoreRange(10 /* base address */, 80 /* size */, object_2));
+ linked_ptr<CountedObject> object;
+ AddressType retrieved_base = AddressType();
+ AddressType retrieved_delta = AddressType();
+ AddressType retrieved_size = AddressType();
+ // The first range contains the second, so the first range should have been
+ // shrunk to [0, 10]. Range [90, 99] should be free.
+ EXPECT_FALSE(range_map.RetrieveRange(90, &object, &retrieved_base,
+ &retrieved_delta, &retrieved_size));
+ EXPECT_FALSE(range_map.RetrieveRange(99, &object, &retrieved_base,
+ &retrieved_delta, &retrieved_size));
+ EXPECT_TRUE(range_map.RetrieveRange(9, &object, &retrieved_base,
+ &retrieved_delta, &retrieved_size));
+ EXPECT_EQ(1, object->id());
+ EXPECT_EQ(0, retrieved_base);
+ EXPECT_EQ(0, retrieved_delta);
+ EXPECT_EQ(10, retrieved_size);
+ // Validate the properties of the smaller range (should be untouched).
+ EXPECT_TRUE(range_map.RetrieveRange(10, &object, &retrieved_base,
+ &retrieved_delta, &retrieved_size));
+ EXPECT_EQ(2, object->id());
+ EXPECT_EQ(10, retrieved_base);
+ EXPECT_EQ(0, retrieved_delta);
+ EXPECT_EQ(80, retrieved_size);
+}
+
+// Same as the previous test, however the larger range is added second.
+TEST(RangeMapTruncateLower, CompletelyContained_LargerAddedSecond) {
+ TestMap range_map;
+ range_map.SetMergeStrategy(MergeRangeStrategy::kTruncateLower);
+ // Smaller (contained) range is added first.
+ linked_ptr<CountedObject> object_1(new CountedObject(1));
+ EXPECT_TRUE(
+ range_map.StoreRange(10 /* base address */, 80 /* size */, object_1));
+ // Larger range is added second.
+ linked_ptr<CountedObject> object_2(new CountedObject(2));
+ EXPECT_TRUE(
+ range_map.StoreRange(0 /* base address */, 100 /* size */, object_2));
+ linked_ptr<CountedObject> object;
+ AddressType retrieved_base = AddressType();
+ AddressType retrieved_delta = AddressType();
+ AddressType retrieved_size = AddressType();
+ // The second range contains the first, so the second range should have been
+ // truncated to [0, 9]. Range [90, 99] should be free.
+ EXPECT_FALSE(range_map.RetrieveRange(90, &object, &retrieved_base,
+ &retrieved_delta, &retrieved_size));
+ EXPECT_FALSE(range_map.RetrieveRange(99, &object, &retrieved_base,
+ &retrieved_delta, &retrieved_size));
+ EXPECT_TRUE(range_map.RetrieveRange(9, &object, &retrieved_base,
+ &retrieved_delta, &retrieved_size));
+ EXPECT_EQ(2, object->id());
+ EXPECT_EQ(0, retrieved_base);
+ EXPECT_EQ(0, retrieved_delta);
+ EXPECT_EQ(10, retrieved_size);
+ // Validate the properties of the smaller range (should be untouched).
+ EXPECT_TRUE(range_map.RetrieveRange(10, &object, &retrieved_base,
+ &retrieved_delta, &retrieved_size));
+ EXPECT_EQ(1, object->id());
+ EXPECT_EQ(10, retrieved_base);
+ EXPECT_EQ(0, retrieved_delta);
+ EXPECT_EQ(80, retrieved_size);
+}
+
+TEST(RangeMapTruncateLower, PartialOverlap_AtBeginning) {
+ TestMap range_map;
+ range_map.SetMergeStrategy(MergeRangeStrategy::kTruncateLower);
+ linked_ptr<CountedObject> object_1(new CountedObject(1));
+ EXPECT_TRUE(
+ range_map.StoreRange(0 /* base address */, 100 /* size */, object_1));
+
+ // Partial overlap at the beginning of the new range.
+ linked_ptr<CountedObject> object_2(new CountedObject(2));
+ EXPECT_TRUE(
+ range_map.StoreRange(90 /* base address */, 110 /* size */, object_2));
+
+ linked_ptr<CountedObject> object;
+ AddressType retrieved_base = AddressType();
+ AddressType retrieved_delta = AddressType();
+ AddressType retrieved_size = AddressType();
+ // The first range should be truncated, so 99 should address the second range.
+ EXPECT_TRUE(range_map.RetrieveRange(99, &object, &retrieved_base,
+ &retrieved_delta, &retrieved_size));
+ EXPECT_EQ(2, object->id());
+ EXPECT_EQ(90, retrieved_base);
+ EXPECT_EQ(0, retrieved_delta);
+ EXPECT_EQ(110, retrieved_size);
+ // Validate the properties of the truncated range.
+ EXPECT_TRUE(range_map.RetrieveRange(89, &object, &retrieved_base,
+ &retrieved_delta, &retrieved_size));
+ EXPECT_EQ(1, object->id());
+ EXPECT_EQ(0, retrieved_base);
+ EXPECT_EQ(0, retrieved_delta);
+ EXPECT_EQ(90, retrieved_size);
+}
+
+TEST(RangeMapTruncateLower, PartialOverlap_AtEnd) {
+ TestMap range_map;
+ range_map.SetMergeStrategy(MergeRangeStrategy::kTruncateLower);
+ linked_ptr<CountedObject> object_1(new CountedObject(1));
+ EXPECT_TRUE(
+ range_map.StoreRange(50 /* base address */, 50 /* size */, object_1));
+
+ // Partial overlap at the end of the new range.
+ linked_ptr<CountedObject> object_2(new CountedObject(2));
+ EXPECT_TRUE(
+ range_map.StoreRange(0 /* base address */, 70 /* size */, object_2));
+
+ linked_ptr<CountedObject> object;
+ AddressType retrieved_base = AddressType();
+ AddressType retrieved_delta = AddressType();
+ AddressType retrieved_size = AddressType();
+ // The second range should be truncated so 69 addresses the first range.
+ EXPECT_TRUE(range_map.RetrieveRange(69, &object, &retrieved_base,
+ &retrieved_delta, &retrieved_size));
+ EXPECT_EQ(1, object->id());
+ EXPECT_EQ(50, retrieved_base);
+ EXPECT_EQ(0, retrieved_delta);
+ EXPECT_EQ(50, retrieved_size);
+ // Validate the properties of the truncated range.
+ EXPECT_TRUE(range_map.RetrieveRange(49, &object, &retrieved_base,
+ &retrieved_delta, &retrieved_size));
+ EXPECT_EQ(2, object->id());
+ EXPECT_EQ(0, retrieved_base);
+ EXPECT_EQ(0, retrieved_delta);
+ EXPECT_EQ(50, retrieved_size);
+}
+
+// A new range is overlapped at both ends. The new range and the range
+// that overlaps at the beginning should be truncated. The range that overlaps
+// at the end should be left untouched.
+TEST(RangeMapTruncateLower, OverlapAtBothEnds) {
+ TestMap range_map;
+ range_map.SetMergeStrategy(MergeRangeStrategy::kTruncateLower);
+ // This should overlap object_3 at the beginning.
+ linked_ptr<CountedObject> object_1(new CountedObject(1));
+ EXPECT_TRUE(
+ range_map.StoreRange(0 /* base address */, 100 /* size */, object_1));
+
+ // This should overlap object_3 at the end.
+ linked_ptr<CountedObject> object_2(new CountedObject(2));
+ EXPECT_TRUE(
+ range_map.StoreRange(100 /* base address */, 100 /* size */, object_2));
+
+ // This should be overlapped on both ends by object_1 and object_2.
+ linked_ptr<CountedObject> object_3(new CountedObject(3));
+ EXPECT_TRUE(
+ range_map.StoreRange(50 /* base address */, 100 /* size */, object_3));
+
+ linked_ptr<CountedObject> object;
+ AddressType retrieved_base = AddressType();
+ AddressType retrieved_delta = AddressType();
+ AddressType retrieved_size = AddressType();
+ // The first range should be truncated.
+ EXPECT_TRUE(range_map.RetrieveRange(0, &object, &retrieved_base,
+ &retrieved_delta, &retrieved_size));
+ EXPECT_EQ(1, object->id());
+ EXPECT_EQ(0, retrieved_base);
+ EXPECT_EQ(0, retrieved_delta);
+ EXPECT_EQ(50, retrieved_size);
+ // The second range should be intact.
+ EXPECT_TRUE(range_map.RetrieveRange(150, &object, &retrieved_base,
+ &retrieved_delta, &retrieved_size));
+ EXPECT_EQ(2, object->id());
+ EXPECT_EQ(100, retrieved_base);
+ EXPECT_EQ(0, retrieved_delta);
+ EXPECT_EQ(100, retrieved_size);
+ // The third range (in the middle) should be truncated.
+ EXPECT_TRUE(range_map.RetrieveRange(99, &object, &retrieved_base,
+ &retrieved_delta, &retrieved_size));
+ EXPECT_EQ(3, object->id());
+ EXPECT_EQ(50, retrieved_base);
+ EXPECT_EQ(0, retrieved_delta);
+ EXPECT_EQ(50, retrieved_size);
+}
+
+TEST(RangeMapTruncateLower, MultipleConflicts) {
+ TestMap range_map;
+ range_map.SetMergeStrategy(MergeRangeStrategy::kTruncateLower);
+ // This should overlap with object_3.
+ linked_ptr<CountedObject> object_1(new CountedObject(1));
+ EXPECT_TRUE(
+ range_map.StoreRange(10 /* base address */, 90 /* size */, object_1));
+
+ // This should also overlap with object_3 but after object_1.
+ linked_ptr<CountedObject> object_2(new CountedObject(2));
+ EXPECT_TRUE(
+ range_map.StoreRange(100 /* base address */, 100 /* size */, object_2));
+
+ // This should be overlapped on both object_1 and object_2.
+ linked_ptr<CountedObject> object_3(new CountedObject(3));
+ EXPECT_TRUE(
+ range_map.StoreRange(0 /* base address */, 300 /* size */, object_3));
+
+ linked_ptr<CountedObject> object;
+ AddressType retrieved_base = AddressType();
+ AddressType retrieved_delta = AddressType();
+ AddressType retrieved_size = AddressType();
+ // The first range should be intact.
+ EXPECT_TRUE(range_map.RetrieveRange(99, &object, &retrieved_base,
+ &retrieved_delta, &retrieved_size));
+ EXPECT_EQ(1, object->id());
+ EXPECT_EQ(10, retrieved_base);
+ EXPECT_EQ(0, retrieved_delta);
+ EXPECT_EQ(90, retrieved_size);
+ // The second range should be intact.
+ EXPECT_TRUE(range_map.RetrieveRange(199, &object, &retrieved_base,
+ &retrieved_delta, &retrieved_size));
+ EXPECT_EQ(2, object->id());
+ EXPECT_EQ(100, retrieved_base);
+ EXPECT_EQ(0, retrieved_delta);
+ EXPECT_EQ(100, retrieved_size);
+ // The third range should be truncated.
+ EXPECT_TRUE(range_map.RetrieveRange(9, &object, &retrieved_base,
+ &retrieved_delta, &retrieved_size));
+ EXPECT_EQ(3, object->id());
+ EXPECT_EQ(0, retrieved_base);
+ EXPECT_EQ(0, retrieved_delta);
+ EXPECT_EQ(10, retrieved_size);
+}
+
+// Adding two ranges without overlap should succeed and the ranges should
+// be left intact.
+TEST(RangeMapTruncateLower, NoConflicts) {
+ TestMap range_map;
+ range_map.SetMergeStrategy(MergeRangeStrategy::kTruncateLower);
+ // Adding range 1.
+ linked_ptr<CountedObject> object_1(new CountedObject(1));
+ EXPECT_TRUE(
+ range_map.StoreRange(10 /* base address */, 90 /* size */, object_1));
+
+ // Adding range 2 - no overlap with range 1.
+ linked_ptr<CountedObject> object_2(new CountedObject(2));
+ EXPECT_TRUE(
+ range_map.StoreRange(110 /* base address */, 90 /* size */, object_2));
+
+ linked_ptr<CountedObject> object;
+ AddressType retrieved_base = AddressType();
+ AddressType retrieved_delta = AddressType();
+ AddressType retrieved_size = AddressType();
+ // The first range should be intact.
+ EXPECT_TRUE(range_map.RetrieveRange(99, &object, &retrieved_base,
+ &retrieved_delta, &retrieved_size));
+ EXPECT_EQ(1, object->id());
+ EXPECT_EQ(10, retrieved_base);
+ EXPECT_EQ(0, retrieved_delta);
+ EXPECT_EQ(90, retrieved_size);
+ // The second range should be intact.
+ EXPECT_TRUE(range_map.RetrieveRange(199, &object, &retrieved_base,
+ &retrieved_delta, &retrieved_size));
+ EXPECT_EQ(2, object->id());
+ EXPECT_EQ(110, retrieved_base);
+ EXPECT_EQ(0, retrieved_delta);
+ EXPECT_EQ(90, retrieved_size);
+}
+
+} // namespace
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/range_map_truncate_upper_unittest.cc b/toolkit/crashreporter/google-breakpad/src/processor/range_map_truncate_upper_unittest.cc
new file mode 100644
index 0000000000..7e3034f2fc
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/range_map_truncate_upper_unittest.cc
@@ -0,0 +1,354 @@
+// 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
+
+// range_map_shrink_down_unittest.cc: Unit tests for RangeMap that specifically
+// test shrink down when ranges overlap.
+//
+// Author: Ivan Penkov
+
+#include <limits.h>
+#include <stdio.h>
+
+#include "processor/range_map-inl.h"
+
+#include "breakpad_googletest_includes.h"
+#include "processor/linked_ptr.h"
+#include "processor/logging.h"
+
+namespace {
+
+using google_breakpad::linked_ptr;
+using google_breakpad::MergeRangeStrategy;
+using google_breakpad::RangeMap;
+
+// A CountedObject holds an int. A global (not thread safe!) count of
+// allocated CountedObjects is maintained to help test memory management.
+class CountedObject {
+ public:
+ explicit CountedObject(int id) : id_(id) { ++count_; }
+ ~CountedObject() { --count_; }
+
+ static int count() { return count_; }
+ int id() const { return id_; }
+
+ private:
+ static int count_;
+ int id_;
+};
+
+int CountedObject::count_;
+
+typedef int AddressType;
+typedef RangeMap<AddressType, linked_ptr<CountedObject>> TestMap;
+
+// Same range cannot be stored wice.
+TEST(RangeMapTruncateUpper, SameRange) {
+ TestMap range_map;
+ range_map.SetMergeStrategy(MergeRangeStrategy::kTruncateUpper);
+ linked_ptr<CountedObject> object_1(new CountedObject(1));
+ EXPECT_TRUE(range_map.StoreRange(0 /* base address */, 100 /* size */,
+ object_1));
+
+ // Same range cannot be stored wice.
+ linked_ptr<CountedObject> object_2(new CountedObject(2));
+ EXPECT_FALSE(range_map.StoreRange(0 /* base address */, 100 /* size */,
+ object_2));
+}
+
+// If a range is completely contained by another range, then the larger range
+// should be shrinked down.
+TEST(RangeMapTruncateUpper, CompletelyContained) {
+ TestMap range_map;
+ range_map.SetMergeStrategy(MergeRangeStrategy::kTruncateUpper);
+ // Larger range is added first.
+ linked_ptr<CountedObject> object_1(new CountedObject(1));
+ EXPECT_TRUE(range_map.StoreRange(0 /* base address */, 100 /* size */,
+ object_1));
+ // Smaller (contained) range is added second.
+ linked_ptr<CountedObject> object_2(new CountedObject(2));
+ EXPECT_TRUE(range_map.StoreRange(10 /* base address */, 80 /* size */,
+ object_2));
+ linked_ptr<CountedObject> object;
+ AddressType retrieved_base = AddressType();
+ AddressType retrieved_delta = AddressType();
+ AddressType retrieved_size = AddressType();
+ // The first range contains the second, so the first range should have been
+ // shrunk to [90, 99]. Range [0, 9] should be free.
+ EXPECT_FALSE(range_map.RetrieveRange(0, &object, &retrieved_base,
+ &retrieved_delta, &retrieved_size));
+ EXPECT_FALSE(range_map.RetrieveRange(9, &object, &retrieved_base,
+ &retrieved_delta, &retrieved_size));
+ EXPECT_TRUE(range_map.RetrieveRange(90, &object, &retrieved_base,
+ &retrieved_delta, &retrieved_size));
+ EXPECT_EQ(1, object->id());
+ EXPECT_EQ(90, retrieved_base);
+ EXPECT_EQ(90, retrieved_delta);
+ EXPECT_EQ(10, retrieved_size);
+ // Validate the properties of the smaller range (should be untouched).
+ EXPECT_TRUE(range_map.RetrieveRange(10, &object, &retrieved_base,
+ &retrieved_delta, &retrieved_size));
+ EXPECT_EQ(2, object->id());
+ EXPECT_EQ(10, retrieved_base);
+ EXPECT_EQ(0, retrieved_delta);
+ EXPECT_EQ(80, retrieved_size);
+}
+
+// Same as the previous test, however the larger range is added second.
+TEST(RangeMapTruncateUpper, CompletelyContained_LargerAddedSecond) {
+ TestMap range_map;
+ range_map.SetMergeStrategy(MergeRangeStrategy::kTruncateUpper);
+ // Smaller (contained) range is added first.
+ linked_ptr<CountedObject> object_1(new CountedObject(1));
+ EXPECT_TRUE(range_map.StoreRange(10 /* base address */, 80 /* size */,
+ object_1));
+ // Larger range is added second.
+ linked_ptr<CountedObject> object_2(new CountedObject(2));
+ EXPECT_TRUE(range_map.StoreRange(0 /* base address */, 100 /* size */,
+ object_2));
+ linked_ptr<CountedObject> object;
+ AddressType retrieved_base = AddressType();
+ AddressType retrieved_delta = AddressType();
+ AddressType retrieved_size = AddressType();
+ // The second range contains the first, so the second range should have been
+ // shrunk to [90, 99]. Range [0, 9] should be free.
+ EXPECT_FALSE(range_map.RetrieveRange(0, &object, &retrieved_base,
+ &retrieved_delta, &retrieved_size));
+ EXPECT_FALSE(range_map.RetrieveRange(9, &object, &retrieved_base,
+ &retrieved_delta, &retrieved_size));
+ EXPECT_TRUE(range_map.RetrieveRange(90, &object, &retrieved_base,
+ &retrieved_delta, &retrieved_size));
+ EXPECT_EQ(2, object->id());
+ EXPECT_EQ(90, retrieved_base);
+ EXPECT_EQ(90, retrieved_delta);
+ EXPECT_EQ(10, retrieved_size);
+ // Validate the properties of the smaller range (should be untouched).
+ EXPECT_TRUE(range_map.RetrieveRange(10, &object, &retrieved_base,
+ &retrieved_delta, &retrieved_size));
+ EXPECT_EQ(1, object->id());
+ EXPECT_EQ(10, retrieved_base);
+ EXPECT_EQ(0, retrieved_delta);
+ EXPECT_EQ(80, retrieved_size);
+}
+
+TEST(RangeMapTruncateUpper, PartialOverlap_AtBeginning) {
+ TestMap range_map;
+ range_map.SetMergeStrategy(MergeRangeStrategy::kTruncateUpper);
+ linked_ptr<CountedObject> object_1(new CountedObject(1));
+ EXPECT_TRUE(range_map.StoreRange(0 /* base address */, 100 /* size */,
+ object_1));
+
+ // Partial overlap at the beginning of the new range.
+ linked_ptr<CountedObject> object_2(new CountedObject(2));
+ EXPECT_TRUE(range_map.StoreRange(90 /* base address */, 110 /* size */,
+ object_2));
+
+ linked_ptr<CountedObject> object;
+ AddressType retrieved_base = AddressType();
+ AddressType retrieved_delta = AddressType();
+ AddressType retrieved_size = AddressType();
+ // The second range is supposed to be shrunk down so the following address
+ // should resize in the first range.
+ EXPECT_TRUE(range_map.RetrieveRange(99, &object, &retrieved_base,
+ &retrieved_delta, &retrieved_size));
+ EXPECT_EQ(1, object->id());
+ EXPECT_EQ(0, retrieved_base);
+ EXPECT_EQ(0, retrieved_delta);
+ EXPECT_EQ(100, retrieved_size);
+ // Validate the properties of the shrunk down range.
+ EXPECT_TRUE(range_map.RetrieveRange(100, &object, &retrieved_base,
+ &retrieved_delta, &retrieved_size));
+ EXPECT_EQ(2, object->id());
+ EXPECT_EQ(100, retrieved_base);
+ EXPECT_EQ(10, retrieved_delta);
+ EXPECT_EQ(100, retrieved_size);
+}
+
+TEST(RangeMapTruncateUpper, PartialOverlap_AtEnd) {
+ TestMap range_map;
+ range_map.SetMergeStrategy(MergeRangeStrategy::kTruncateUpper);
+ linked_ptr<CountedObject> object_1(new CountedObject(1));
+ EXPECT_TRUE(range_map.StoreRange(50 /* base address */, 50 /* size */,
+ object_1));
+
+ // Partial overlap at the end of the new range.
+ linked_ptr<CountedObject> object_2(new CountedObject(2));
+ EXPECT_TRUE(range_map.StoreRange(0 /* base address */, 70 /* size */,
+ object_2));
+
+ linked_ptr<CountedObject> object;
+ AddressType retrieved_base = AddressType();
+ AddressType retrieved_delta = AddressType();
+ AddressType retrieved_size = AddressType();
+ // The first range is supposed to be shrunk down so the following address
+ // should resize in the first range.
+ EXPECT_TRUE(range_map.RetrieveRange(69, &object, &retrieved_base,
+ &retrieved_delta, &retrieved_size));
+ EXPECT_EQ(2, object->id());
+ EXPECT_EQ(0, retrieved_base);
+ EXPECT_EQ(0, retrieved_delta);
+ EXPECT_EQ(70, retrieved_size);
+ // Validate the properties of the shrunk down range.
+ EXPECT_TRUE(range_map.RetrieveRange(70, &object, &retrieved_base,
+ &retrieved_delta, &retrieved_size));
+ EXPECT_EQ(1, object->id());
+ EXPECT_EQ(70, retrieved_base);
+ EXPECT_EQ(20, retrieved_delta);
+ EXPECT_EQ(30, retrieved_size);
+}
+
+// A new range is overlapped at both ends. The new range and the range
+// that overlaps at the end should be shrink. The range that overlaps at the
+// beginning should be left untouched.
+TEST(RangeMapTruncateUpper, OverlapAtBothEnds) {
+ TestMap range_map;
+ range_map.SetMergeStrategy(MergeRangeStrategy::kTruncateUpper);
+ // This should overlap object_3 at the beginning.
+ linked_ptr<CountedObject> object_1(new CountedObject(1));
+ EXPECT_TRUE(range_map.StoreRange(0 /* base address */, 100 /* size */,
+ object_1));
+
+ // This should overlap object_3 at the end.
+ linked_ptr<CountedObject> object_2(new CountedObject(2));
+ EXPECT_TRUE(range_map.StoreRange(100 /* base address */, 100 /* size */,
+ object_2));
+
+ // This should be overlapped on both ends by object_1 and object_2.
+ linked_ptr<CountedObject> object_3(new CountedObject(3));
+ EXPECT_TRUE(range_map.StoreRange(50 /* base address */, 100 /* size */,
+ object_3));
+
+ linked_ptr<CountedObject> object;
+ AddressType retrieved_base = AddressType();
+ AddressType retrieved_delta = AddressType();
+ AddressType retrieved_size = AddressType();
+ // The first range should be intact.
+ EXPECT_TRUE(range_map.RetrieveRange(0, &object, &retrieved_base,
+ &retrieved_delta, &retrieved_size));
+ EXPECT_EQ(1, object->id());
+ EXPECT_EQ(0, retrieved_base);
+ EXPECT_EQ(0, retrieved_delta);
+ EXPECT_EQ(100, retrieved_size);
+ // The second range should be shrunk down by 50.
+ EXPECT_TRUE(range_map.RetrieveRange(150, &object, &retrieved_base,
+ &retrieved_delta, &retrieved_size));
+ EXPECT_EQ(2, object->id());
+ EXPECT_EQ(150, retrieved_base);
+ EXPECT_EQ(50, retrieved_delta);
+ EXPECT_EQ(50, retrieved_size);
+ // The third range (in the middle) should be shrunk down by 50.
+ EXPECT_TRUE(range_map.RetrieveRange(100, &object, &retrieved_base,
+ &retrieved_delta, &retrieved_size));
+ EXPECT_EQ(3, object->id());
+ EXPECT_EQ(100, retrieved_base);
+ EXPECT_EQ(50, retrieved_delta);
+ EXPECT_EQ(50, retrieved_size);
+}
+
+TEST(RangeMapTruncateUpper, MultipleConflicts) {
+ TestMap range_map;
+ range_map.SetMergeStrategy(MergeRangeStrategy::kTruncateUpper);
+ // This should overlap with object_3.
+ linked_ptr<CountedObject> object_1(new CountedObject(1));
+ EXPECT_TRUE(range_map.StoreRange(10 /* base address */, 90 /* size */,
+ object_1));
+
+ // This should also overlap with object_3 but after object_1.
+ linked_ptr<CountedObject> object_2(new CountedObject(2));
+ EXPECT_TRUE(range_map.StoreRange(100 /* base address */, 100 /* size */,
+ object_2));
+
+ // This should be overlapped on both object_1 and object_2. Since
+ // object_3 ends with the higher address it must be shrunk.
+ linked_ptr<CountedObject> object_3(new CountedObject(3));
+ EXPECT_TRUE(range_map.StoreRange(0 /* base address */, 300 /* size */,
+ object_3));
+
+ linked_ptr<CountedObject> object;
+ AddressType retrieved_base = AddressType();
+ AddressType retrieved_delta = AddressType();
+ AddressType retrieved_size = AddressType();
+ // The first range should be intact.
+ EXPECT_TRUE(range_map.RetrieveRange(99, &object, &retrieved_base,
+ &retrieved_delta, &retrieved_size));
+ EXPECT_EQ(1, object->id());
+ EXPECT_EQ(10, retrieved_base);
+ EXPECT_EQ(0, retrieved_delta);
+ EXPECT_EQ(90, retrieved_size);
+ // The second range should be intact.
+ EXPECT_TRUE(range_map.RetrieveRange(199, &object, &retrieved_base,
+ &retrieved_delta, &retrieved_size));
+ EXPECT_EQ(2, object->id());
+ EXPECT_EQ(100, retrieved_base);
+ EXPECT_EQ(0, retrieved_delta);
+ EXPECT_EQ(100, retrieved_size);
+ // The third range should be shrunk down by 200.
+ EXPECT_TRUE(range_map.RetrieveRange(299, &object, &retrieved_base,
+ &retrieved_delta, &retrieved_size));
+ EXPECT_EQ(3, object->id());
+ EXPECT_EQ(200, retrieved_base);
+ EXPECT_EQ(200, retrieved_delta);
+ EXPECT_EQ(100, retrieved_size);
+}
+
+// Adding two ranges without overlap should succeed and the ranges should
+// be left intact.
+TEST(RangeMapTruncateUpper, NoConflicts) {
+ TestMap range_map;
+ range_map.SetMergeStrategy(MergeRangeStrategy::kTruncateUpper);
+ // Adding range 1.
+ linked_ptr<CountedObject> object_1(new CountedObject(1));
+ EXPECT_TRUE(range_map.StoreRange(10 /* base address */, 90 /* size */,
+ object_1));
+
+ // Adding range 2 - no overlap with range 1.
+ linked_ptr<CountedObject> object_2(new CountedObject(2));
+ EXPECT_TRUE(range_map.StoreRange(110 /* base address */, 90 /* size */,
+ object_2));
+
+ linked_ptr<CountedObject> object;
+ AddressType retrieved_base = AddressType();
+ AddressType retrieved_delta = AddressType();
+ AddressType retrieved_size = AddressType();
+ // The first range should be intact.
+ EXPECT_TRUE(range_map.RetrieveRange(99, &object, &retrieved_base,
+ &retrieved_delta, &retrieved_size));
+ EXPECT_EQ(1, object->id());
+ EXPECT_EQ(10, retrieved_base);
+ EXPECT_EQ(0, retrieved_delta);
+ EXPECT_EQ(90, retrieved_size);
+ // The second range should be intact.
+ EXPECT_TRUE(range_map.RetrieveRange(199, &object, &retrieved_base,
+ &retrieved_delta, &retrieved_size));
+ EXPECT_EQ(2, object->id());
+ EXPECT_EQ(110, retrieved_base);
+ EXPECT_EQ(0, retrieved_delta);
+ EXPECT_EQ(90, retrieved_size);
+}
+
+} // namespace
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/range_map_unittest.cc b/toolkit/crashreporter/google-breakpad/src/processor/range_map_unittest.cc
new file mode 100644
index 0000000000..31b89e5de3
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/range_map_unittest.cc
@@ -0,0 +1,559 @@
+// 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.
+
+// range_map_unittest.cc: Unit tests for RangeMap
+//
+// Author: Mark Mentovai
+
+
+#include <limits.h>
+#include <stdio.h>
+
+#include "processor/range_map-inl.h"
+
+#include "common/scoped_ptr.h"
+#include "processor/linked_ptr.h"
+#include "processor/logging.h"
+
+namespace {
+
+
+using google_breakpad::linked_ptr;
+using google_breakpad::scoped_ptr;
+using google_breakpad::RangeMap;
+
+
+// A CountedObject holds an int. A global (not thread safe!) count of
+// allocated CountedObjects is maintained to help test memory management.
+class CountedObject {
+ public:
+ explicit CountedObject(int id) : id_(id) { ++count_; }
+ ~CountedObject() { --count_; }
+
+ static int count() { return count_; }
+ int id() const { return id_; }
+
+ private:
+ static int count_;
+ int id_;
+};
+
+int CountedObject::count_;
+
+
+typedef int AddressType;
+typedef RangeMap< AddressType, linked_ptr<CountedObject> > TestMap;
+
+
+// RangeTest contains data to use for store and retrieve tests. See
+// RunTests for descriptions of the tests.
+struct RangeTest {
+ // Base address to use for test
+ AddressType address;
+
+ // Size of range to use for test
+ AddressType size;
+
+ // Unique ID of range - unstorable ranges must have unique IDs too
+ int id;
+
+ // Whether this range is expected to be stored successfully or not
+ bool expect_storable;
+};
+
+
+// A RangeTestSet encompasses multiple RangeTests, which are run in
+// sequence on the same RangeMap.
+struct RangeTestSet {
+ // An array of RangeTests
+ const RangeTest *range_tests;
+
+ // The number of tests in the set
+ unsigned int range_test_count;
+};
+
+
+// StoreTest uses the data in a RangeTest and calls StoreRange on the
+// test RangeMap. It returns true if the expected result occurred, and
+// false if something else happened.
+static bool StoreTest(TestMap *range_map, const RangeTest *range_test) {
+ linked_ptr<CountedObject> object(new CountedObject(range_test->id));
+ bool stored = range_map->StoreRange(range_test->address,
+ range_test->size,
+ object);
+
+ if (stored != range_test->expect_storable) {
+ fprintf(stderr, "FAILED: "
+ "StoreRange id %d, expected %s, observed %s\n",
+ range_test->id,
+ range_test->expect_storable ? "storable" : "not storable",
+ stored ? "stored" : "not stored");
+ return false;
+ }
+
+ return true;
+}
+
+
+// RetrieveTest uses the data in RangeTest and calls RetrieveRange on the
+// test RangeMap. If it retrieves the expected value (which can be no
+// map entry at the specified range,) it returns true, otherwise, it returns
+// false. RetrieveTest will check the values around the base address and
+// the high address of a range to guard against off-by-one errors.
+static bool RetrieveTest(TestMap *range_map, const RangeTest *range_test) {
+ for (unsigned int side = 0; side <= 1; ++side) {
+ // When side == 0, check the low side (base address) of each range.
+ // When side == 1, check the high side (base + size) of each range.
+
+ // Check one-less and one-greater than the target address in addition
+ // to the target address itself.
+
+ // If the size of the range is only 1, don't check one greater than
+ // the base or one less than the high - for a successfully stored
+ // range, these tests would erroneously fail because the range is too
+ // small.
+ AddressType low_offset = -1;
+ AddressType high_offset = 1;
+ if (range_test->size == 1) {
+ if (!side) // When checking the low side,
+ high_offset = 0; // don't check one over the target.
+ else // When checking the high side,
+ low_offset = 0; // don't check one under the target.
+ }
+
+ for (AddressType offset = low_offset; offset <= high_offset; ++offset) {
+ AddressType address =
+ offset +
+ (!side ? range_test->address :
+ range_test->address + range_test->size - 1);
+
+ bool expected_result = false; // This is correct for tests not stored.
+ if (range_test->expect_storable) {
+ if (offset == 0) // When checking the target address,
+ expected_result = true; // test should always succeed.
+ else if (offset == -1) // When checking one below the target,
+ expected_result = side; // should fail low and succeed high.
+ else // When checking one above the target,
+ expected_result = !side; // should succeed low and fail high.
+ }
+
+ linked_ptr<CountedObject> object;
+ AddressType retrieved_base = AddressType();
+ AddressType retrieved_size = AddressType();
+ AddressType retrieved_delta = AddressType();
+ bool retrieved = range_map->RetrieveRange(address, &object,
+ &retrieved_base,
+ &retrieved_delta,
+ &retrieved_size);
+
+ bool observed_result = retrieved && object->id() == range_test->id;
+
+ if (observed_result != expected_result) {
+ fprintf(stderr, "FAILED: "
+ "RetrieveRange id %d, side %d, offset %d, "
+ "expected %s, observed %s\n",
+ range_test->id,
+ side,
+ offset,
+ expected_result ? "true" : "false",
+ observed_result ? "true" : "false");
+ return false;
+ }
+
+ // If a range was successfully retrieved, check that the returned
+ // bounds match the range as stored.
+ if (observed_result == true &&
+ (retrieved_base != range_test->address ||
+ retrieved_size != range_test->size)) {
+ fprintf(stderr, "FAILED: "
+ "RetrieveRange id %d, side %d, offset %d, "
+ "expected base/size %d/%d, observed %d/%d\n",
+ range_test->id,
+ side,
+ offset,
+ range_test->address, range_test->size,
+ retrieved_base, retrieved_size);
+ return false;
+ }
+
+ // Now, check RetrieveNearestRange. The nearest range is always
+ // expected to be different from the test range when checking one
+ // less than the low side.
+ bool expected_nearest = range_test->expect_storable;
+ if (!side && offset < 0)
+ expected_nearest = false;
+
+ linked_ptr<CountedObject> nearest_object;
+ AddressType nearest_base = AddressType();
+ AddressType nearest_delta = AddressType();
+ AddressType nearest_size = AddressType();
+ bool retrieved_nearest = range_map->RetrieveNearestRange(address,
+ &nearest_object,
+ &nearest_base,
+ &nearest_delta,
+ &nearest_size);
+
+ // When checking one greater than the high side, RetrieveNearestRange
+ // should usually return the test range. When a different range begins
+ // at that address, though, then RetrieveNearestRange should return the
+ // range at the address instead of the test range.
+ if (side && offset > 0 && nearest_base == address) {
+ expected_nearest = false;
+ }
+
+ bool observed_nearest = retrieved_nearest &&
+ nearest_object->id() == range_test->id;
+
+ if (observed_nearest != expected_nearest) {
+ fprintf(stderr, "FAILED: "
+ "RetrieveNearestRange id %d, side %d, offset %d, "
+ "expected %s, observed %s\n",
+ range_test->id,
+ side,
+ offset,
+ expected_nearest ? "true" : "false",
+ observed_nearest ? "true" : "false");
+ return false;
+ }
+
+ // If a range was successfully retrieved, check that the returned
+ // bounds match the range as stored.
+ if (expected_nearest &&
+ (nearest_base != range_test->address ||
+ nearest_size != range_test->size)) {
+ fprintf(stderr, "FAILED: "
+ "RetrieveNearestRange id %d, side %d, offset %d, "
+ "expected base/size %d/%d, observed %d/%d\n",
+ range_test->id,
+ side,
+ offset,
+ range_test->address, range_test->size,
+ nearest_base, nearest_size);
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+
+// Test RetrieveRangeAtIndex, which is supposed to return objects in order
+// according to their addresses. This test is performed by looping through
+// the map, calling RetrieveRangeAtIndex for all possible indices in sequence,
+// and verifying that each call returns a different object than the previous
+// call, and that ranges are returned with increasing base addresses. Returns
+// false if the test fails.
+static bool RetrieveIndexTest(TestMap *range_map, int set) {
+ linked_ptr<CountedObject> object;
+ CountedObject *last_object = NULL;
+ AddressType last_base = 0;
+
+ int object_count = range_map->GetCount();
+ for (int object_index = 0; object_index < object_count; ++object_index) {
+ AddressType base;
+ if (!range_map->RetrieveRangeAtIndex(object_index, &object, &base,
+ NULL /* delta */, NULL /* size */)) {
+ fprintf(stderr, "FAILED: RetrieveRangeAtIndex set %d index %d, "
+ "expected success, observed failure\n",
+ set, object_index);
+ return false;
+ }
+
+ if (!object.get()) {
+ fprintf(stderr, "FAILED: RetrieveRangeAtIndex set %d index %d, "
+ "expected object, observed NULL\n",
+ set, object_index);
+ return false;
+ }
+
+ // It's impossible to do these comparisons unless there's a previous
+ // object to compare against.
+ if (last_object) {
+ // The object must be different from the last one.
+ if (object->id() == last_object->id()) {
+ fprintf(stderr, "FAILED: RetrieveRangeAtIndex set %d index %d, "
+ "expected different objects, observed same objects (%d)\n",
+ set, object_index, object->id());
+ return false;
+ }
+
+ // Each object must have a base greater than the previous object's base.
+ if (base <= last_base) {
+ fprintf(stderr, "FAILED: RetrieveRangeAtIndex set %d index %d, "
+ "expected different bases, observed same bases (%d)\n",
+ set, object_index, base);
+ return false;
+ }
+ }
+
+ last_object = object.get();
+ last_base = base;
+ }
+
+ // Make sure that RetrieveRangeAtIndex doesn't allow lookups at indices that
+ // are too high.
+ if (range_map->RetrieveRangeAtIndex(object_count, &object, NULL /* base */,
+ NULL /* delta */, NULL /* size */)) {
+ fprintf(stderr, "FAILED: RetrieveRangeAtIndex set %d index %d (too large), "
+ "expected failure, observed success\n",
+ set, object_count);
+ return false;
+ }
+
+ return true;
+}
+
+// Additional RetriveAtIndex test to expose the bug in RetrieveRangeAtIndex().
+// Bug info: RetrieveRangeAtIndex() previously retrieves the high address of
+// entry, however, it is supposed to retrieve the base address of entry as
+// stated in the comment in range_map.h.
+static bool RetriveAtIndexTest2() {
+ scoped_ptr<TestMap> range_map(new TestMap());
+
+ // Store ranges with base address = 2 * object_id:
+ const int range_size = 2;
+ for (int object_id = 0; object_id < 100; ++object_id) {
+ linked_ptr<CountedObject> object(new CountedObject(object_id));
+ int base_address = 2 * object_id;
+ range_map->StoreRange(base_address, range_size, object);
+ }
+
+ linked_ptr<CountedObject> object;
+ int object_count = range_map->GetCount();
+ for (int object_index = 0; object_index < object_count; ++object_index) {
+ AddressType base;
+ if (!range_map->RetrieveRangeAtIndex(object_index, &object, &base,
+ NULL /* delta */, NULL /* size */)) {
+ fprintf(stderr, "FAILED: RetrieveAtIndexTest2 index %d, "
+ "expected success, observed failure\n", object_index);
+ return false;
+ }
+
+ int expected_base = 2 * object->id();
+ if (base != expected_base) {
+ fprintf(stderr, "FAILED: RetriveAtIndexTest2 index %d, "
+ "expected base %d, observed base %d",
+ object_index, expected_base, base);
+ return false;
+ }
+ }
+
+ return true;
+}
+
+
+// RunTests runs a series of test sets.
+static bool RunTests() {
+ // These tests will be run sequentially. The first set of tests exercises
+ // most functions of RangeTest, and verifies all of the bounds-checking.
+ const RangeTest range_tests_0[] = {
+ { INT_MIN, 16, 1, true }, // lowest possible range
+ { -2, 5, 2, true }, // a range through zero
+ { INT_MAX - 9, 11, 3, false }, // tests anti-overflow
+ { INT_MAX - 9, 10, 4, true }, // highest possible range
+ { 5, 0, 5, false }, // tests anti-zero-size
+ { 5, 1, 6, true }, // smallest possible range
+ { -20, 15, 7, true }, // entirely negative
+
+ { 10, 10, 10, true }, // causes the following tests to fail
+ { 9, 10, 11, false }, // one-less base, one-less high
+ { 9, 11, 12, false }, // one-less base, identical high
+ { 9, 12, 13, false }, // completely contains existing
+ { 10, 9, 14, false }, // identical base, one-less high
+ { 10, 10, 15, false }, // exactly identical to existing range
+ { 10, 11, 16, false }, // identical base, one-greater high
+ { 11, 8, 17, false }, // contained completely within
+ { 11, 9, 18, false }, // one-greater base, identical high
+ { 11, 10, 19, false }, // one-greater base, one-greater high
+ { 9, 2, 20, false }, // overlaps bottom by one
+ { 10, 1, 21, false }, // overlaps bottom by one, contained
+ { 19, 1, 22, false }, // overlaps top by one, contained
+ { 19, 2, 23, false }, // overlaps top by one
+
+ { 9, 1, 24, true }, // directly below without overlap
+ { 20, 1, 25, true }, // directly above without overlap
+
+ { 6, 3, 26, true }, // exactly between two ranges, gapless
+ { 7, 3, 27, false }, // tries to span two ranges
+ { 7, 5, 28, false }, // tries to span three ranges
+ { 4, 20, 29, false }, // tries to contain several ranges
+
+ { 30, 50, 30, true },
+ { 90, 25, 31, true },
+ { 35, 65, 32, false }, // tries to span two noncontiguous
+ { 120, 10000, 33, true }, // > 8-bit
+ { 20000, 20000, 34, true }, // > 8-bit
+ { 0x10001, 0x10001, 35, true }, // > 16-bit
+
+ { 27, -1, 36, false } // tests high < base
+ };
+
+ // Attempt to fill the entire space. The entire space must be filled with
+ // three stores because AddressType is signed for these tests, so RangeMap
+ // treats the size as signed and rejects sizes that appear to be negative.
+ // Even if these tests were run as unsigned, two stores would be needed
+ // to fill the space because the entire size of the space could only be
+ // described by using one more bit than would be present in AddressType.
+ const RangeTest range_tests_1[] = {
+ { INT_MIN, INT_MAX, 50, true }, // From INT_MIN to -2, inclusive
+ { -1, 2, 51, true }, // From -1 to 0, inclusive
+ { 1, INT_MAX, 52, true }, // From 1 to INT_MAX, inclusive
+ { INT_MIN, INT_MAX, 53, false }, // Can't fill the space twice
+ { -1, 2, 54, false },
+ { 1, INT_MAX, 55, false },
+ { -3, 6, 56, false }, // -3 to 2, inclusive - spans 3 ranges
+ };
+
+ // A light round of testing to verify that RetrieveRange does the right
+ // the right thing at the extremities of the range when nothing is stored
+ // there. Checks are forced without storing anything at the extremities
+ // by setting size = 0.
+ const RangeTest range_tests_2[] = {
+ { INT_MIN, 0, 100, false }, // makes RetrieveRange check low end
+ { -1, 3, 101, true },
+ { INT_MAX, 0, 102, false }, // makes RetrieveRange check high end
+ };
+
+ // Similar to the previous test set, but with a couple of ranges closer
+ // to the extremities.
+ const RangeTest range_tests_3[] = {
+ { INT_MIN + 1, 1, 110, true },
+ { INT_MAX - 1, 1, 111, true },
+ { INT_MIN, 0, 112, false }, // makes RetrieveRange check low end
+ { INT_MAX, 0, 113, false } // makes RetrieveRange check high end
+ };
+
+ // The range map is cleared between sets of tests listed here.
+ const RangeTestSet range_test_sets[] = {
+ { range_tests_0, sizeof(range_tests_0) / sizeof(RangeTest) },
+ { range_tests_1, sizeof(range_tests_1) / sizeof(RangeTest) },
+ { range_tests_2, sizeof(range_tests_2) / sizeof(RangeTest) },
+ { range_tests_3, sizeof(range_tests_3) / sizeof(RangeTest) },
+ { range_tests_0, sizeof(range_tests_0) / sizeof(RangeTest) } // Run again
+ };
+
+ // Maintain the range map in a pointer so that deletion can be meaningfully
+ // tested.
+ scoped_ptr<TestMap> range_map(new TestMap());
+
+ // Run all of the test sets in sequence.
+ unsigned int range_test_set_count = sizeof(range_test_sets) /
+ sizeof(RangeTestSet);
+ for (unsigned int range_test_set_index = 0;
+ range_test_set_index < range_test_set_count;
+ ++range_test_set_index) {
+ const RangeTest *range_tests =
+ range_test_sets[range_test_set_index].range_tests;
+ unsigned int range_test_count =
+ range_test_sets[range_test_set_index].range_test_count;
+
+ // Run the StoreRange test, which validates StoreRange and initializes
+ // the RangeMap with data for the RetrieveRange test.
+ int stored_count = 0; // The number of ranges successfully stored
+ for (unsigned int range_test_index = 0;
+ range_test_index < range_test_count;
+ ++range_test_index) {
+ const RangeTest *range_test = &range_tests[range_test_index];
+ if (!StoreTest(range_map.get(), range_test))
+ return false;
+
+ if (range_test->expect_storable)
+ ++stored_count;
+ }
+
+ // There should be exactly one CountedObject for everything successfully
+ // stored in the RangeMap.
+ if (CountedObject::count() != stored_count) {
+ fprintf(stderr, "FAILED: "
+ "stored object counts don't match, expected %d, observed %d\n",
+ stored_count,
+ CountedObject::count());
+
+ return false;
+ }
+
+ // The RangeMap's own count of objects should also match.
+ if (range_map->GetCount() != stored_count) {
+ fprintf(stderr, "FAILED: stored object count doesn't match GetCount, "
+ "expected %d, observed %d\n",
+ stored_count, range_map->GetCount());
+
+ return false;
+ }
+
+ // Run the RetrieveRange test
+ for (unsigned int range_test_index = 0;
+ range_test_index < range_test_count;
+ ++range_test_index) {
+ const RangeTest *range_test = &range_tests[range_test_index];
+ if (!RetrieveTest(range_map.get(), range_test))
+ return false;
+ }
+
+ if (!RetrieveIndexTest(range_map.get(), range_test_set_index))
+ return false;
+
+ // Clear the map between test sets. If this is the final test set,
+ // delete the map instead to test destruction.
+ if (range_test_set_index < range_test_set_count - 1)
+ range_map->Clear();
+ else
+ range_map.reset();
+
+ // Test that all stored objects are freed when the RangeMap is cleared
+ // or deleted.
+ if (CountedObject::count() != 0) {
+ fprintf(stderr, "FAILED: "
+ "did not free all objects after %s, %d still allocated\n",
+ range_test_set_index < range_test_set_count - 1 ? "clear"
+ : "delete",
+ CountedObject::count());
+
+ return false;
+ }
+ }
+
+ if (!RetriveAtIndexTest2()) {
+ fprintf(stderr, "FAILED: did not pass RetrieveAtIndexTest2()\n");
+ return false;
+ }
+
+ return true;
+}
+
+
+} // namespace
+
+
+int main(int argc, char **argv) {
+ BPLOG_INIT(&argc, &argv);
+
+ return RunTests() ? 0 : 1;
+}
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/simple_serializer-inl.h b/toolkit/crashreporter/google-breakpad/src/processor/simple_serializer-inl.h
new file mode 100644
index 0000000000..606bb3cead
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/simple_serializer-inl.h
@@ -0,0 +1,260 @@
+// 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.
+//
+// simple_serializer-inl.h: template specializations for following types:
+// bool, const char *(C-string), string,
+// Line, Function, PublicSymbol, WindowsFrameInfo and their linked pointers.
+//
+// See simple_serializer.h for moredocumentation.
+//
+// Author: Siyang Xie (lambxsy@google.com)
+
+#ifndef PROCESSOR_SIMPLE_SERIALIZER_INL_H__
+#define PROCESSOR_SIMPLE_SERIALIZER_INL_H__
+
+#include <string>
+
+#include "processor/simple_serializer.h"
+#include "map_serializers-inl.h"
+
+#include "google_breakpad/processor/basic_source_line_resolver.h"
+#include "processor/basic_source_line_resolver_types.h"
+#include "processor/linked_ptr.h"
+#include "processor/windows_frame_info.h"
+
+namespace google_breakpad {
+
+// Specializations of SimpleSerializer: bool
+template<>
+class SimpleSerializer<bool> {
+ public:
+ static size_t SizeOf(bool boolean) { return 1; }
+
+ static char *Write(bool boolean, char *dest) {
+ *dest = static_cast<char>(boolean? 255 : 0);
+ return ++dest;
+ }
+
+ static const char *Read(const char *source, bool *value) {
+ *value = ((*source) == 0 ? false : true);
+ return ++source;
+ }
+};
+
+// Specializations of SimpleSerializer: string
+template<>
+class SimpleSerializer<string> {
+ public:
+ static size_t SizeOf(const string &str) { return str.size() + 1; }
+
+ static char *Write(const string &str, char *dest) {
+ strcpy(dest, str.c_str());
+ return dest + SizeOf(str);
+ }
+};
+
+// Specializations of SimpleSerializer: C-string
+template<>
+class SimpleSerializer<const char*> {
+ public:
+ static size_t SizeOf(const char *cstring) {
+ return strlen(cstring) + 1;
+ }
+
+ static char *Write(const char *cstring, char *dest) {
+ strcpy(dest, cstring);
+ return dest + SizeOf(cstring);
+ }
+};
+
+// Specializations of SimpleSerializer: Line
+template<>
+class SimpleSerializer<BasicSourceLineResolver::Line> {
+ typedef BasicSourceLineResolver::Line Line;
+ public:
+ static size_t SizeOf(const Line &line) {
+ return SimpleSerializer<MemAddr>::SizeOf(line.address)
+ + SimpleSerializer<MemAddr>::SizeOf(line.size)
+ + SimpleSerializer<int32_t>::SizeOf(line.source_file_id)
+ + SimpleSerializer<int32_t>::SizeOf(line.line);
+ }
+ static char *Write(const Line &line, char *dest) {
+ dest = SimpleSerializer<MemAddr>::Write(line.address, dest);
+ dest = SimpleSerializer<MemAddr>::Write(line.size, dest);
+ dest = SimpleSerializer<int32_t>::Write(line.source_file_id, dest);
+ dest = SimpleSerializer<int32_t>::Write(line.line, dest);
+ return dest;
+ }
+};
+
+// Specializations of SimpleSerializer: PublicSymbol
+template<>
+class SimpleSerializer<BasicSourceLineResolver::PublicSymbol> {
+ typedef BasicSourceLineResolver::PublicSymbol PublicSymbol;
+ public:
+ static size_t SizeOf(const PublicSymbol &pubsymbol) {
+ return SimpleSerializer<string>::SizeOf(pubsymbol.name)
+ + SimpleSerializer<MemAddr>::SizeOf(pubsymbol.address)
+ + SimpleSerializer<int32_t>::SizeOf(pubsymbol.parameter_size);
+ }
+ static char *Write(const PublicSymbol &pubsymbol, char *dest) {
+ dest = SimpleSerializer<string>::Write(pubsymbol.name, dest);
+ dest = SimpleSerializer<MemAddr>::Write(pubsymbol.address, dest);
+ dest = SimpleSerializer<int32_t>::Write(pubsymbol.parameter_size, dest);
+ return dest;
+ }
+};
+
+// Specializations of SimpleSerializer: WindowsFrameInfo
+template<>
+class SimpleSerializer<WindowsFrameInfo> {
+ public:
+ static size_t SizeOf(const WindowsFrameInfo &wfi) {
+ unsigned int size = 0;
+ size += sizeof(int32_t); // wfi.type_
+ size += SimpleSerializer<int32_t>::SizeOf(wfi.valid);
+ size += SimpleSerializer<uint32_t>::SizeOf(wfi.prolog_size);
+ size += SimpleSerializer<uint32_t>::SizeOf(wfi.epilog_size);
+ size += SimpleSerializer<uint32_t>::SizeOf(wfi.parameter_size);
+ size += SimpleSerializer<uint32_t>::SizeOf(wfi.saved_register_size);
+ size += SimpleSerializer<uint32_t>::SizeOf(wfi.local_size);
+ size += SimpleSerializer<uint32_t>::SizeOf(wfi.max_stack_size);
+ size += SimpleSerializer<bool>::SizeOf(wfi.allocates_base_pointer);
+ size += SimpleSerializer<string>::SizeOf(wfi.program_string);
+ return size;
+ }
+ static char *Write(const WindowsFrameInfo &wfi, char *dest) {
+ dest = SimpleSerializer<int32_t>::Write(
+ static_cast<const int32_t>(wfi.type_), dest);
+ dest = SimpleSerializer<int32_t>::Write(wfi.valid, dest);
+ dest = SimpleSerializer<uint32_t>::Write(wfi.prolog_size, dest);
+ dest = SimpleSerializer<uint32_t>::Write(wfi.epilog_size, dest);
+ dest = SimpleSerializer<uint32_t>::Write(wfi.parameter_size, dest);
+ dest = SimpleSerializer<uint32_t>::Write(wfi.saved_register_size, dest);
+ dest = SimpleSerializer<uint32_t>::Write(wfi.local_size, dest);
+ dest = SimpleSerializer<uint32_t>::Write(wfi.max_stack_size, dest);
+ dest = SimpleSerializer<bool>::Write(wfi.allocates_base_pointer, dest);
+ return SimpleSerializer<string>::Write(wfi.program_string, dest);
+ }
+};
+
+// Specializations of SimpleSerializer: Linked_ptr version of
+// Line, Function, PublicSymbol, WindowsFrameInfo.
+template<>
+class SimpleSerializer< linked_ptr<BasicSourceLineResolver::Line> > {
+ typedef BasicSourceLineResolver::Line Line;
+ public:
+ static size_t SizeOf(const linked_ptr<Line> &lineptr) {
+ if (lineptr.get() == NULL) return 0;
+ return SimpleSerializer<Line>::SizeOf(*(lineptr.get()));
+ }
+ static char *Write(const linked_ptr<Line> &lineptr, char *dest) {
+ if (lineptr.get())
+ dest = SimpleSerializer<Line>::Write(*(lineptr.get()), dest);
+ return dest;
+ }
+};
+
+template<>
+class SimpleSerializer<BasicSourceLineResolver::Function> {
+ // Convenient type names.
+ typedef BasicSourceLineResolver::Function Function;
+ typedef BasicSourceLineResolver::Line Line;
+ public:
+ static size_t SizeOf(const Function &func) {
+ unsigned int size = 0;
+ size += SimpleSerializer<string>::SizeOf(func.name);
+ size += SimpleSerializer<MemAddr>::SizeOf(func.address);
+ size += SimpleSerializer<MemAddr>::SizeOf(func.size);
+ size += SimpleSerializer<int32_t>::SizeOf(func.parameter_size);
+ size += range_map_serializer_.SizeOf(func.lines);
+ return size;
+ }
+
+ static char *Write(const Function &func, char *dest) {
+ dest = SimpleSerializer<string>::Write(func.name, dest);
+ dest = SimpleSerializer<MemAddr>::Write(func.address, dest);
+ dest = SimpleSerializer<MemAddr>::Write(func.size, dest);
+ dest = SimpleSerializer<int32_t>::Write(func.parameter_size, dest);
+ dest = range_map_serializer_.Write(func.lines, dest);
+ return dest;
+ }
+ private:
+ // This static member is defined in module_serializer.cc.
+ static RangeMapSerializer< MemAddr, linked_ptr<Line> > range_map_serializer_;
+};
+
+template<>
+class SimpleSerializer< linked_ptr<BasicSourceLineResolver::Function> > {
+ typedef BasicSourceLineResolver::Function Function;
+ public:
+ static size_t SizeOf(const linked_ptr<Function> &func) {
+ if (!func.get()) return 0;
+ return SimpleSerializer<Function>::SizeOf(*(func.get()));
+ }
+
+ static char *Write(const linked_ptr<Function> &func, char *dest) {
+ if (func.get())
+ dest = SimpleSerializer<Function>::Write(*(func.get()), dest);
+ return dest;
+ }
+};
+
+template<>
+class SimpleSerializer< linked_ptr<BasicSourceLineResolver::PublicSymbol> > {
+ typedef BasicSourceLineResolver::PublicSymbol PublicSymbol;
+ public:
+ static size_t SizeOf(const linked_ptr<PublicSymbol> &pubsymbol) {
+ if (pubsymbol.get() == NULL) return 0;
+ return SimpleSerializer<PublicSymbol>::SizeOf(*(pubsymbol.get()));
+ }
+ static char *Write(const linked_ptr<PublicSymbol> &pubsymbol, char *dest) {
+ if (pubsymbol.get())
+ dest = SimpleSerializer<PublicSymbol>::Write(*(pubsymbol.get()), dest);
+ return dest;
+ }
+};
+
+template<>
+class SimpleSerializer< linked_ptr<WindowsFrameInfo> > {
+ public:
+ static size_t SizeOf(const linked_ptr<WindowsFrameInfo> &wfi) {
+ if (wfi.get() == NULL) return 0;
+ return SimpleSerializer<WindowsFrameInfo>::SizeOf(*(wfi.get()));
+ }
+ static char *Write(const linked_ptr<WindowsFrameInfo> &wfi, char *dest) {
+ if (wfi.get())
+ dest = SimpleSerializer<WindowsFrameInfo>::Write(*(wfi.get()), dest);
+ return dest;
+ }
+};
+
+} // namespace google_breakpad
+
+#endif // PROCESSOR_SIMPLE_SERIALIZER_INL_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/simple_serializer.h b/toolkit/crashreporter/google-breakpad/src/processor/simple_serializer.h
new file mode 100644
index 0000000000..275f51ce36
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/simple_serializer.h
@@ -0,0 +1,63 @@
+// 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.
+//
+// simple_serializer.h: SimpleSerializer is a template for calculating size and
+// writing to specific memory location for objects of primitive types, C-style
+// string, string, breakpad types/structs etc.
+// All specializations of SimpleSerializer template are defined in the
+// "simple_serializer-inl.h" file.
+//
+// Author: Siyang Xie (lambxsy@google.com)
+
+#ifndef PROCESSOR_SIMPLE_SERIALIZER_H__
+#define PROCESSOR_SIMPLE_SERIALIZER_H__
+
+#include "google_breakpad/common/breakpad_types.h"
+
+namespace google_breakpad {
+
+typedef uint64_t MemAddr;
+
+// Default implementation of SimpleSerializer template.
+// Specializations are defined in "simple_serializer-inl.h".
+template<class Type> class SimpleSerializer {
+ public:
+ // Calculate and return the size of the 'item'.
+ static size_t SizeOf(const Type &item) { return sizeof(item); }
+ // Write 'item' to memory location 'dest', and return to the "end" address of
+ // data written, i.e., the address after the final byte written.
+ static char *Write(const Type &item, char *dest) {
+ new (dest) Type(item);
+ return dest + SizeOf(item);
+ }
+};
+
+} // namespace google_breakpad
+
+#endif // PROCESSOR_SIMPLE_SERIALIZER_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/simple_symbol_supplier.cc b/toolkit/crashreporter/google-breakpad/src/processor/simple_symbol_supplier.cc
new file mode 100644
index 0000000000..bc5ebb687b
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/simple_symbol_supplier.cc
@@ -0,0 +1,204 @@
+// 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.
+
+// simple_symbol_supplier.cc: A simple SymbolSupplier implementation
+//
+// See simple_symbol_supplier.h for documentation.
+//
+// Author: Mark Mentovai
+
+#include "processor/simple_symbol_supplier.h"
+
+#include <assert.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <algorithm>
+#include <iostream>
+#include <fstream>
+
+#include "common/using_std_string.h"
+#include "google_breakpad/processor/code_module.h"
+#include "google_breakpad/processor/system_info.h"
+#include "processor/logging.h"
+#include "processor/pathname_stripper.h"
+
+namespace google_breakpad {
+
+static bool file_exists(const string &file_name) {
+ struct stat sb;
+ return stat(file_name.c_str(), &sb) == 0;
+}
+
+SymbolSupplier::SymbolResult SimpleSymbolSupplier::GetSymbolFile(
+ const CodeModule *module, const SystemInfo *system_info,
+ string *symbol_file) {
+ BPLOG_IF(ERROR, !symbol_file) << "SimpleSymbolSupplier::GetSymbolFile "
+ "requires |symbol_file|";
+ assert(symbol_file);
+ symbol_file->clear();
+
+ for (unsigned int path_index = 0; path_index < paths_.size(); ++path_index) {
+ SymbolResult result;
+ if ((result = GetSymbolFileAtPathFromRoot(module, system_info,
+ paths_[path_index],
+ symbol_file)) != NOT_FOUND) {
+ return result;
+ }
+ }
+ return NOT_FOUND;
+}
+
+SymbolSupplier::SymbolResult SimpleSymbolSupplier::GetSymbolFile(
+ const CodeModule *module,
+ const SystemInfo *system_info,
+ string *symbol_file,
+ string *symbol_data) {
+ assert(symbol_data);
+ symbol_data->clear();
+
+ SymbolSupplier::SymbolResult s = GetSymbolFile(module, system_info,
+ symbol_file);
+ if (s == FOUND) {
+ std::ifstream in(symbol_file->c_str());
+ std::getline(in, *symbol_data, string::traits_type::to_char_type(
+ string::traits_type::eof()));
+ in.close();
+ }
+ return s;
+}
+
+SymbolSupplier::SymbolResult SimpleSymbolSupplier::GetCStringSymbolData(
+ const CodeModule *module,
+ const SystemInfo *system_info,
+ string *symbol_file,
+ char **symbol_data,
+ size_t *symbol_data_size) {
+ assert(symbol_data);
+ assert(symbol_data_size);
+
+ string symbol_data_string;
+ SymbolSupplier::SymbolResult s =
+ GetSymbolFile(module, system_info, symbol_file, &symbol_data_string);
+
+ if (s == FOUND) {
+ *symbol_data_size = symbol_data_string.size() + 1;
+ *symbol_data = new char[*symbol_data_size];
+ if (*symbol_data == NULL) {
+ BPLOG(ERROR) << "Memory allocation for size " << *symbol_data_size
+ << " failed";
+ return INTERRUPT;
+ }
+ memcpy(*symbol_data, symbol_data_string.c_str(), symbol_data_string.size());
+ (*symbol_data)[symbol_data_string.size()] = '\0';
+ memory_buffers_.insert(make_pair(module->code_file(), *symbol_data));
+ }
+ return s;
+}
+
+void SimpleSymbolSupplier::FreeSymbolData(const CodeModule *module) {
+ if (!module) {
+ BPLOG(INFO) << "Cannot free symbol data buffer for NULL module";
+ return;
+ }
+
+ map<string, char *>::iterator it = memory_buffers_.find(module->code_file());
+ if (it == memory_buffers_.end()) {
+ BPLOG(INFO) << "Cannot find symbol data buffer for module "
+ << module->code_file();
+ return;
+ }
+ delete [] it->second;
+ memory_buffers_.erase(it);
+}
+
+SymbolSupplier::SymbolResult SimpleSymbolSupplier::GetSymbolFileAtPathFromRoot(
+ const CodeModule *module, const SystemInfo *system_info,
+ const string &root_path, string *symbol_file) {
+ BPLOG_IF(ERROR, !symbol_file) << "SimpleSymbolSupplier::GetSymbolFileAtPath "
+ "requires |symbol_file|";
+ assert(symbol_file);
+ symbol_file->clear();
+
+ if (!module)
+ return NOT_FOUND;
+
+ // Start with the base path.
+ string path = root_path;
+
+ // Append the debug (pdb) file name as a directory name.
+ path.append("/");
+ string debug_file_name = PathnameStripper::File(module->debug_file());
+ if (debug_file_name.empty()) {
+ BPLOG(ERROR) << "Can't construct symbol file path without debug_file "
+ "(code_file = " <<
+ PathnameStripper::File(module->code_file()) << ")";
+ return NOT_FOUND;
+ }
+ path.append(debug_file_name);
+
+ // Append the identifier as a directory name.
+ path.append("/");
+ string identifier = module->debug_identifier();
+ if (identifier.empty()) {
+ BPLOG(ERROR) << "Can't construct symbol file path without debug_identifier "
+ "(code_file = " <<
+ PathnameStripper::File(module->code_file()) <<
+ ", debug_file = " << debug_file_name << ")";
+ return NOT_FOUND;
+ }
+ path.append(identifier);
+
+ // Transform the debug file name into one ending in .sym. If the existing
+ // name ends in .pdb, strip the .pdb. Otherwise, add .sym to the non-.pdb
+ // name.
+ path.append("/");
+ string debug_file_extension;
+ if (debug_file_name.size() > 4)
+ debug_file_extension = debug_file_name.substr(debug_file_name.size() - 4);
+ std::transform(debug_file_extension.begin(), debug_file_extension.end(),
+ debug_file_extension.begin(), tolower);
+ if (debug_file_extension == ".pdb") {
+ path.append(debug_file_name.substr(0, debug_file_name.size() - 4));
+ } else {
+ path.append(debug_file_name);
+ }
+ path.append(".sym");
+
+ if (!file_exists(path)) {
+ BPLOG(INFO) << "No symbol file at " << path;
+ return NOT_FOUND;
+ }
+
+ *symbol_file = path;
+ return FOUND;
+}
+
+} // namespace google_breakpad
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/simple_symbol_supplier.h b/toolkit/crashreporter/google-breakpad/src/processor/simple_symbol_supplier.h
new file mode 100644
index 0000000000..0cde85cdcd
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/simple_symbol_supplier.h
@@ -0,0 +1,140 @@
+// 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.
+
+// simple_symbol_supplier.h: A simple SymbolSupplier implementation
+//
+// SimpleSymbolSupplier is a straightforward implementation of SymbolSupplier
+// that stores symbol files in a filesystem tree. A SimpleSymbolSupplier is
+// created with one or more base directories, which are the root paths for all
+// symbol files. Each symbol file contained therein has a directory entry in
+// the base directory with a name identical to the corresponding debugging
+// file (pdb). Within each of these directories, there are subdirectories
+// named for the debugging file's identifier. For recent pdb files, this is
+// a concatenation of the pdb's uuid and age, presented in hexadecimal form,
+// without any dashes or separators. The uuid is in uppercase hexadecimal
+// and the age is in lowercase hexadecimal. Within that subdirectory,
+// SimpleSymbolSupplier expects to find the symbol file, which is named
+// identically to the debug file, but with a .sym extension. If the original
+// debug file had a name ending in .pdb, the .pdb extension will be replaced
+// with .sym. This sample hierarchy is rooted at the "symbols" base
+// directory:
+//
+// symbols
+// symbols/test_app.pdb
+// symbols/test_app.pdb/63FE4780728D49379B9D7BB6460CB42A1
+// symbols/test_app.pdb/63FE4780728D49379B9D7BB6460CB42A1/test_app.sym
+// symbols/kernel32.pdb
+// symbols/kernel32.pdb/BCE8785C57B44245A669896B6A19B9542
+// symbols/kernel32.pdb/BCE8785C57B44245A669896B6A19B9542/kernel32.sym
+//
+// In this case, the uuid of test_app.pdb is
+// 63fe4780-728d-4937-9b9d-7bb6460cb42a and its age is 1.
+//
+// This scheme was chosen to be roughly analogous to the way that
+// symbol files may be accessed from Microsoft Symbol Server. A hierarchy
+// used for Microsoft Symbol Server storage is usable as a hierarchy for
+// SimpleSymbolServer, provided that the pdb files are transformed to dumped
+// format using a tool such as dump_syms, and given a .sym extension.
+//
+// SimpleSymbolSupplier will iterate over all root paths searching for
+// a symbol file existing in that path.
+//
+// SimpleSymbolSupplier supports any debugging file which can be identified
+// by a CodeModule object's debug_file and debug_identifier accessors. The
+// expected ultimate source of these CodeModule objects are MinidumpModule
+// objects; it is this class that is responsible for assigning appropriate
+// values for debug_file and debug_identifier.
+//
+// Author: Mark Mentovai
+
+#ifndef PROCESSOR_SIMPLE_SYMBOL_SUPPLIER_H__
+#define PROCESSOR_SIMPLE_SYMBOL_SUPPLIER_H__
+
+#include <map>
+#include <string>
+#include <vector>
+
+#include "common/using_std_string.h"
+#include "google_breakpad/processor/symbol_supplier.h"
+
+namespace google_breakpad {
+
+using std::map;
+using std::vector;
+
+class CodeModule;
+
+class SimpleSymbolSupplier : public SymbolSupplier {
+ public:
+ // Creates a new SimpleSymbolSupplier, using path as the root path where
+ // symbols are stored.
+ explicit SimpleSymbolSupplier(const string &path) : paths_(1, path) {}
+
+ // Creates a new SimpleSymbolSupplier, using paths as a list of root
+ // paths where symbols may be stored.
+ explicit SimpleSymbolSupplier(const vector<string> &paths) : paths_(paths) {}
+
+ virtual ~SimpleSymbolSupplier() {}
+
+ // Returns the path to the symbol file for the given module. See the
+ // description above.
+ virtual SymbolResult GetSymbolFile(const CodeModule *module,
+ const SystemInfo *system_info,
+ string *symbol_file);
+
+ virtual SymbolResult GetSymbolFile(const CodeModule *module,
+ const SystemInfo *system_info,
+ string *symbol_file,
+ string *symbol_data);
+
+ // Allocates data buffer on heap and writes symbol data into buffer.
+ // Symbol supplier ALWAYS takes ownership of the data buffer.
+ virtual SymbolResult GetCStringSymbolData(const CodeModule *module,
+ const SystemInfo *system_info,
+ string *symbol_file,
+ char **symbol_data,
+ size_t *symbol_data_size);
+
+ // Free the data buffer allocated in the above GetCStringSymbolData();
+ virtual void FreeSymbolData(const CodeModule *module);
+
+ protected:
+ SymbolResult GetSymbolFileAtPathFromRoot(const CodeModule *module,
+ const SystemInfo *system_info,
+ const string &root_path,
+ string *symbol_file);
+
+ private:
+ map<string, char *> memory_buffers_;
+ vector<string> paths_;
+};
+
+} // namespace google_breakpad
+
+#endif // PROCESSOR_SIMPLE_SYMBOL_SUPPLIER_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/source_line_resolver_base.cc b/toolkit/crashreporter/google-breakpad/src/processor/source_line_resolver_base.cc
new file mode 100644
index 0000000000..6eff1f9918
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/source_line_resolver_base.cc
@@ -0,0 +1,341 @@
+// 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.
+//
+// source_line_resolver_base.cc: Implementation of SourceLineResolverBase.
+//
+// See source_line_resolver_base.h and source_line_resolver_base_types.h for
+// more documentation.
+//
+// Author: Siyang Xie (lambxsy@google.com)
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/stat.h>
+
+#include <map>
+#include <utility>
+
+#include "google_breakpad/processor/source_line_resolver_base.h"
+#include "processor/source_line_resolver_base_types.h"
+#include "processor/module_factory.h"
+
+using std::map;
+using std::make_pair;
+
+namespace google_breakpad {
+
+SourceLineResolverBase::SourceLineResolverBase(
+ ModuleFactory *module_factory)
+ : modules_(new ModuleMap),
+ corrupt_modules_(new ModuleSet),
+ memory_buffers_(new MemoryMap),
+ module_factory_(module_factory) {
+}
+
+SourceLineResolverBase::~SourceLineResolverBase() {
+ ModuleMap::iterator it;
+ // Iterate through ModuleMap and delete all loaded modules.
+ for (it = modules_->begin(); it != modules_->end(); ++it) {
+ // Delete individual module.
+ delete it->second;
+ }
+ // Delete the map of modules.
+ delete modules_;
+ modules_ = NULL;
+
+ // Delete the set of corrupt modules.
+ delete corrupt_modules_;
+ corrupt_modules_ = NULL;
+
+ MemoryMap::iterator iter = memory_buffers_->begin();
+ for (; iter != memory_buffers_->end(); ++iter) {
+ delete [] iter->second;
+ }
+ // Delete the map of memory buffers.
+ delete memory_buffers_;
+ memory_buffers_ = NULL;
+
+ delete module_factory_;
+ module_factory_ = NULL;
+}
+
+bool SourceLineResolverBase::ReadSymbolFile(const string &map_file,
+ char **symbol_data,
+ size_t *symbol_data_size) {
+ if (symbol_data == NULL || symbol_data_size == NULL) {
+ BPLOG(ERROR) << "Could not Read file into Null memory pointer";
+ return false;
+ }
+
+ struct stat buf;
+ int error_code = stat(map_file.c_str(), &buf);
+ if (error_code == -1) {
+ string error_string;
+ error_code = ErrnoString(&error_string);
+ BPLOG(ERROR) << "Could not open " << map_file <<
+ ", error " << error_code << ": " << error_string;
+ return false;
+ }
+
+ off_t file_size = buf.st_size;
+
+ // Allocate memory for file contents, plus a null terminator
+ // since we may use strtok() on the contents.
+ *symbol_data_size = file_size + 1;
+ *symbol_data = new char[file_size + 1];
+
+ if (*symbol_data == NULL) {
+ BPLOG(ERROR) << "Could not allocate memory for " << map_file;
+ return false;
+ }
+
+ BPLOG(INFO) << "Opening " << map_file;
+
+ FILE *f = fopen(map_file.c_str(), "rt");
+ if (!f) {
+ string error_string;
+ error_code = ErrnoString(&error_string);
+ BPLOG(ERROR) << "Could not open " << map_file <<
+ ", error " << error_code << ": " << error_string;
+ delete [] (*symbol_data);
+ *symbol_data = NULL;
+ return false;
+ }
+
+ AutoFileCloser closer(f);
+
+ int items_read = 0;
+
+ items_read = fread(*symbol_data, 1, file_size, f);
+
+ if (items_read != file_size) {
+ string error_string;
+ error_code = ErrnoString(&error_string);
+ BPLOG(ERROR) << "Could not slurp " << map_file <<
+ ", error " << error_code << ": " << error_string;
+ delete [] (*symbol_data);
+ *symbol_data = NULL;
+ return false;
+ }
+
+ (*symbol_data)[file_size] = '\0';
+ return true;
+}
+
+bool SourceLineResolverBase::LoadModule(const CodeModule *module,
+ const string &map_file) {
+ if (module == NULL)
+ return false;
+
+ // Make sure we don't already have a module with the given name.
+ if (modules_->find(module->code_file()) != modules_->end()) {
+ BPLOG(INFO) << "Symbols for module " << module->code_file()
+ << " already loaded";
+ return false;
+ }
+
+ BPLOG(INFO) << "Loading symbols for module " << module->code_file()
+ << " from " << map_file;
+
+ char *memory_buffer;
+ size_t memory_buffer_size;
+ if (!ReadSymbolFile(map_file, &memory_buffer, &memory_buffer_size))
+ return false;
+
+ BPLOG(INFO) << "Read symbol file " << map_file << " succeeded";
+
+ bool load_result = LoadModuleUsingMemoryBuffer(module, memory_buffer,
+ memory_buffer_size);
+
+ if (load_result && !ShouldDeleteMemoryBufferAfterLoadModule()) {
+ // memory_buffer has to stay alive as long as the module.
+ memory_buffers_->insert(make_pair(module->code_file(), memory_buffer));
+ } else {
+ delete [] memory_buffer;
+ }
+
+ return load_result;
+}
+
+bool SourceLineResolverBase::LoadModuleUsingMapBuffer(
+ const CodeModule *module, const string &map_buffer) {
+ if (module == NULL)
+ return false;
+
+ // Make sure we don't already have a module with the given name.
+ if (modules_->find(module->code_file()) != modules_->end()) {
+ BPLOG(INFO) << "Symbols for module " << module->code_file()
+ << " already loaded";
+ return false;
+ }
+
+ size_t memory_buffer_size = map_buffer.size() + 1;
+ char *memory_buffer = new char[memory_buffer_size];
+ if (memory_buffer == NULL) {
+ BPLOG(ERROR) << "Could not allocate memory for " << module->code_file();
+ return false;
+ }
+
+ // Can't use strcpy, as the data may contain '\0's before the end.
+ memcpy(memory_buffer, map_buffer.c_str(), map_buffer.size());
+ memory_buffer[map_buffer.size()] = '\0';
+
+ bool load_result = LoadModuleUsingMemoryBuffer(module, memory_buffer,
+ memory_buffer_size);
+
+ if (load_result && !ShouldDeleteMemoryBufferAfterLoadModule()) {
+ // memory_buffer has to stay alive as long as the module.
+ memory_buffers_->insert(make_pair(module->code_file(), memory_buffer));
+ } else {
+ delete [] memory_buffer;
+ }
+
+ return load_result;
+}
+
+bool SourceLineResolverBase::LoadModuleUsingMemoryBuffer(
+ const CodeModule *module,
+ char *memory_buffer,
+ size_t memory_buffer_size) {
+ if (!module)
+ return false;
+
+ // Make sure we don't already have a module with the given name.
+ if (modules_->find(module->code_file()) != modules_->end()) {
+ BPLOG(INFO) << "Symbols for module " << module->code_file()
+ << " already loaded";
+ return false;
+ }
+
+ BPLOG(INFO) << "Loading symbols for module " << module->code_file()
+ << " from memory buffer";
+
+ Module *basic_module = module_factory_->CreateModule(module->code_file());
+
+ // Ownership of memory is NOT transfered to Module::LoadMapFromMemory().
+ if (!basic_module->LoadMapFromMemory(memory_buffer, memory_buffer_size)) {
+ BPLOG(ERROR) << "Too many error while parsing symbol data for module "
+ << module->code_file();
+ // Returning false from here would be an indication that the symbols for
+ // this module are missing which would be wrong. Intentionally fall through
+ // and add the module to both the modules_ and the corrupt_modules_ lists.
+ assert(basic_module->IsCorrupt());
+ }
+
+ modules_->insert(make_pair(module->code_file(), basic_module));
+ if (basic_module->IsCorrupt()) {
+ corrupt_modules_->insert(module->code_file());
+ }
+ return true;
+}
+
+bool SourceLineResolverBase::ShouldDeleteMemoryBufferAfterLoadModule() {
+ return true;
+}
+
+void SourceLineResolverBase::UnloadModule(const CodeModule *code_module) {
+ if (!code_module)
+ return;
+
+ ModuleMap::iterator mod_iter = modules_->find(code_module->code_file());
+ if (mod_iter != modules_->end()) {
+ Module *symbol_module = mod_iter->second;
+ delete symbol_module;
+ corrupt_modules_->erase(mod_iter->first);
+ modules_->erase(mod_iter);
+ }
+
+ if (ShouldDeleteMemoryBufferAfterLoadModule()) {
+ // No-op. Because we never store any memory buffers.
+ } else {
+ // There may be a buffer stored locally, we need to find and delete it.
+ MemoryMap::iterator iter = memory_buffers_->find(code_module->code_file());
+ if (iter != memory_buffers_->end()) {
+ delete [] iter->second;
+ memory_buffers_->erase(iter);
+ }
+ }
+}
+
+bool SourceLineResolverBase::HasModule(const CodeModule *module) {
+ if (!module)
+ return false;
+ return modules_->find(module->code_file()) != modules_->end();
+}
+
+bool SourceLineResolverBase::IsModuleCorrupt(const CodeModule *module) {
+ if (!module)
+ return false;
+ return corrupt_modules_->find(module->code_file()) != corrupt_modules_->end();
+}
+
+void SourceLineResolverBase::FillSourceLineInfo(StackFrame *frame) {
+ if (frame->module) {
+ ModuleMap::const_iterator it = modules_->find(frame->module->code_file());
+ if (it != modules_->end()) {
+ it->second->LookupAddress(frame);
+ }
+ }
+}
+
+WindowsFrameInfo *SourceLineResolverBase::FindWindowsFrameInfo(
+ const StackFrame *frame) {
+ if (frame->module) {
+ ModuleMap::const_iterator it = modules_->find(frame->module->code_file());
+ if (it != modules_->end()) {
+ return it->second->FindWindowsFrameInfo(frame);
+ }
+ }
+ return NULL;
+}
+
+CFIFrameInfo *SourceLineResolverBase::FindCFIFrameInfo(
+ const StackFrame *frame) {
+ if (frame->module) {
+ ModuleMap::const_iterator it = modules_->find(frame->module->code_file());
+ if (it != modules_->end()) {
+ return it->second->FindCFIFrameInfo(frame);
+ }
+ }
+ return NULL;
+}
+
+bool SourceLineResolverBase::CompareString::operator()(
+ const string &s1, const string &s2) const {
+ return strcmp(s1.c_str(), s2.c_str()) < 0;
+}
+
+bool SourceLineResolverBase::Module::ParseCFIRuleSet(
+ const string &rule_set, CFIFrameInfo *frame_info) const {
+ CFIFrameInfoParseHandler handler(frame_info);
+ CFIRuleParser parser(&handler);
+ return parser.Parse(rule_set);
+}
+
+} // namespace google_breakpad
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/source_line_resolver_base_types.h b/toolkit/crashreporter/google-breakpad/src/processor/source_line_resolver_base_types.h
new file mode 100644
index 0000000000..ca744e0015
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/source_line_resolver_base_types.h
@@ -0,0 +1,167 @@
+// 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.
+
+// source_line_resolver_base_types.h: definition of nested classes/structs in
+// SourceLineResolverBase. It moves the definitions out of
+// source_line_resolver_base.cc, so that other classes may have access
+// to these private nested types without including source_line_resolver_base.cc
+// In addition, Module is defined as a pure abstract class to be implemented by
+// each concrete source line resolver class.
+//
+// See source_line_resolver_base.h for more documentation.
+//
+// Author: Siyang Xie (lambxsy@google.com)
+
+#include <stdio.h>
+
+#include <map>
+#include <string>
+
+#include "google_breakpad/common/breakpad_types.h"
+#include "google_breakpad/processor/source_line_resolver_base.h"
+#include "google_breakpad/processor/stack_frame.h"
+#include "processor/cfi_frame_info.h"
+#include "processor/windows_frame_info.h"
+
+#ifndef PROCESSOR_SOURCE_LINE_RESOLVER_BASE_TYPES_H__
+#define PROCESSOR_SOURCE_LINE_RESOLVER_BASE_TYPES_H__
+
+namespace google_breakpad {
+
+class SourceLineResolverBase::AutoFileCloser {
+ public:
+ explicit AutoFileCloser(FILE *file) : file_(file) {}
+ ~AutoFileCloser() {
+ if (file_)
+ fclose(file_);
+ }
+
+ private:
+ FILE *file_;
+};
+
+struct SourceLineResolverBase::Line {
+ Line() { }
+ Line(MemAddr addr, MemAddr code_size, int file_id, int source_line)
+ : address(addr)
+ , size(code_size)
+ , source_file_id(file_id)
+ , line(source_line) { }
+
+ MemAddr address;
+ MemAddr size;
+ int32_t source_file_id;
+ int32_t line;
+};
+
+struct SourceLineResolverBase::Function {
+ Function() { }
+ Function(const string &function_name,
+ MemAddr function_address,
+ MemAddr code_size,
+ int set_parameter_size,
+ bool is_multiple)
+ : name(function_name), address(function_address), size(code_size),
+ parameter_size(set_parameter_size), is_multiple(is_multiple) { }
+
+ string name;
+ MemAddr address;
+ MemAddr size;
+
+ // The size of parameters passed to this function on the stack.
+ int32_t parameter_size;
+
+ // If the function's instructions correspond to multiple symbols.
+ bool is_multiple;
+};
+
+struct SourceLineResolverBase::PublicSymbol {
+ PublicSymbol() { }
+ PublicSymbol(const string& set_name,
+ MemAddr set_address,
+ int set_parameter_size,
+ bool is_multiple)
+ : name(set_name),
+ address(set_address),
+ parameter_size(set_parameter_size),
+ is_multiple(is_multiple) {}
+
+ string name;
+ MemAddr address;
+
+ // If the public symbol is used as a function entry point, parameter_size
+ // is set to the size of the parameters passed to the funciton on the
+ // stack, if known.
+ int32_t parameter_size;
+
+ // If the function's instructions correspond to multiple symbols.
+ bool is_multiple;
+};
+
+class SourceLineResolverBase::Module {
+ public:
+ virtual ~Module() { };
+ // Loads a map from the given buffer in char* type.
+ // Does NOT take ownership of memory_buffer (the caller, source line resolver,
+ // is the owner of memory_buffer).
+ // The passed in |memory buffer| is of size |memory_buffer_size|. If it is
+ // not null terminated, LoadMapFromMemory will null terminate it by modifying
+ // the passed in buffer.
+ virtual bool LoadMapFromMemory(char *memory_buffer,
+ size_t memory_buffer_size) = 0;
+
+ // Tells whether the loaded symbol data is corrupt. Return value is
+ // undefined, if the symbol data hasn't been loaded yet.
+ virtual bool IsCorrupt() const = 0;
+
+ // Looks up the given relative address, and fills the StackFrame struct
+ // with the result.
+ virtual void LookupAddress(StackFrame *frame) const = 0;
+
+ // If Windows stack walking information is available covering ADDRESS,
+ // return a WindowsFrameInfo structure describing it. If the information
+ // is not available, returns NULL. A NULL return value does not indicate
+ // an error. The caller takes ownership of any returned WindowsFrameInfo
+ // object.
+ virtual WindowsFrameInfo *
+ FindWindowsFrameInfo(const StackFrame *frame) const = 0;
+
+ // If CFI stack walking information is available covering ADDRESS,
+ // return a CFIFrameInfo structure describing it. If the information
+ // is not available, return NULL. The caller takes ownership of any
+ // returned CFIFrameInfo object.
+ virtual CFIFrameInfo *FindCFIFrameInfo(const StackFrame *frame) const = 0;
+ protected:
+ virtual bool ParseCFIRuleSet(const string &rule_set,
+ CFIFrameInfo *frame_info) const;
+};
+
+} // namespace google_breakpad
+
+#endif // PROCESSOR_SOURCE_LINE_RESOLVER_BASE_TYPES_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/stack_frame_cpu.cc b/toolkit/crashreporter/google-breakpad/src/processor/stack_frame_cpu.cc
new file mode 100644
index 0000000000..6175dc7f26
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/stack_frame_cpu.cc
@@ -0,0 +1,79 @@
+// 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.
+
+// stack_frame_cpu.h: CPU-specific StackFrame extensions.
+//
+// See google_breakpad/processor/stack_frame_cpu.h for documentation.
+//
+// Author: Colin Blundell
+
+#include "google_breakpad/processor/stack_frame_cpu.h"
+
+namespace google_breakpad {
+
+const uint64_t StackFrameARM64::CONTEXT_VALID_X0;
+const uint64_t StackFrameARM64::CONTEXT_VALID_X1;
+const uint64_t StackFrameARM64::CONTEXT_VALID_X2;
+const uint64_t StackFrameARM64::CONTEXT_VALID_X3;
+const uint64_t StackFrameARM64::CONTEXT_VALID_X4;
+const uint64_t StackFrameARM64::CONTEXT_VALID_X5;
+const uint64_t StackFrameARM64::CONTEXT_VALID_X6;
+const uint64_t StackFrameARM64::CONTEXT_VALID_X7;
+const uint64_t StackFrameARM64::CONTEXT_VALID_X8;
+const uint64_t StackFrameARM64::CONTEXT_VALID_X9;
+const uint64_t StackFrameARM64::CONTEXT_VALID_X10;
+const uint64_t StackFrameARM64::CONTEXT_VALID_X11;
+const uint64_t StackFrameARM64::CONTEXT_VALID_X12;
+const uint64_t StackFrameARM64::CONTEXT_VALID_X13;
+const uint64_t StackFrameARM64::CONTEXT_VALID_X14;
+const uint64_t StackFrameARM64::CONTEXT_VALID_X15;
+const uint64_t StackFrameARM64::CONTEXT_VALID_X16;
+const uint64_t StackFrameARM64::CONTEXT_VALID_X17;
+const uint64_t StackFrameARM64::CONTEXT_VALID_X18;
+const uint64_t StackFrameARM64::CONTEXT_VALID_X19;
+const uint64_t StackFrameARM64::CONTEXT_VALID_X20;
+const uint64_t StackFrameARM64::CONTEXT_VALID_X21;
+const uint64_t StackFrameARM64::CONTEXT_VALID_X22;
+const uint64_t StackFrameARM64::CONTEXT_VALID_X23;
+const uint64_t StackFrameARM64::CONTEXT_VALID_X24;
+const uint64_t StackFrameARM64::CONTEXT_VALID_X25;
+const uint64_t StackFrameARM64::CONTEXT_VALID_X26;
+const uint64_t StackFrameARM64::CONTEXT_VALID_X27;
+const uint64_t StackFrameARM64::CONTEXT_VALID_X28;
+const uint64_t StackFrameARM64::CONTEXT_VALID_X29;
+const uint64_t StackFrameARM64::CONTEXT_VALID_X30;
+const uint64_t StackFrameARM64::CONTEXT_VALID_X31;
+const uint64_t StackFrameARM64::CONTEXT_VALID_X32;
+const uint64_t StackFrameARM64::CONTEXT_VALID_FP;
+const uint64_t StackFrameARM64::CONTEXT_VALID_LR;
+const uint64_t StackFrameARM64::CONTEXT_VALID_SP;
+const uint64_t StackFrameARM64::CONTEXT_VALID_PC;
+const uint64_t StackFrameARM64::CONTEXT_VALID_ALL;
+
+} // namespace google_breakpad
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/stack_frame_symbolizer.cc b/toolkit/crashreporter/google-breakpad/src/processor/stack_frame_symbolizer.cc
new file mode 100644
index 0000000000..504971c17a
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/stack_frame_symbolizer.cc
@@ -0,0 +1,144 @@
+// 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.
+
+// Implementation of StackFrameSymbolizer, which encapsulates the logic of how
+// SourceLineResolverInterface interacts with SymbolSupplier to fill source
+// line information in a stack frame, and also looks up WindowsFrameInfo or
+// CFIFrameInfo for a stack frame.
+
+#include "google_breakpad/processor/stack_frame_symbolizer.h"
+
+#include <assert.h>
+
+#include "common/scoped_ptr.h"
+#include "google_breakpad/processor/code_module.h"
+#include "google_breakpad/processor/code_modules.h"
+#include "google_breakpad/processor/source_line_resolver_interface.h"
+#include "google_breakpad/processor/stack_frame.h"
+#include "google_breakpad/processor/symbol_supplier.h"
+#include "google_breakpad/processor/system_info.h"
+#include "processor/linked_ptr.h"
+#include "processor/logging.h"
+
+namespace google_breakpad {
+
+StackFrameSymbolizer::StackFrameSymbolizer(
+ SymbolSupplier* supplier,
+ SourceLineResolverInterface* resolver) : supplier_(supplier),
+ resolver_(resolver) { }
+
+StackFrameSymbolizer::SymbolizerResult StackFrameSymbolizer::FillSourceLineInfo(
+ const CodeModules* modules,
+ const CodeModules* unloaded_modules,
+ const SystemInfo* system_info,
+ StackFrame* frame) {
+ assert(frame);
+
+ const CodeModule* module = NULL;
+ if (modules) {
+ module = modules->GetModuleForAddress(frame->instruction);
+ }
+ if (!module && unloaded_modules) {
+ module = unloaded_modules->GetModuleForAddress(frame->instruction);
+ }
+
+ if (!module) return kError;
+ frame->module = module;
+
+ if (!resolver_) return kError; // no resolver.
+ // If module is known to have missing symbol file, return.
+ if (no_symbol_modules_.find(module->code_file()) !=
+ no_symbol_modules_.end()) {
+ return kError;
+ }
+
+ // If module is already loaded, go ahead to fill source line info and return.
+ if (resolver_->HasModule(frame->module)) {
+ resolver_->FillSourceLineInfo(frame);
+ return resolver_->IsModuleCorrupt(frame->module) ?
+ kWarningCorruptSymbols : kNoError;
+ }
+
+ // Module needs to fetch symbol file. First check to see if supplier exists.
+ if (!supplier_) {
+ return kError;
+ }
+
+ // Start fetching symbol from supplier.
+ string symbol_file;
+ char* symbol_data = NULL;
+ size_t symbol_data_size;
+ SymbolSupplier::SymbolResult symbol_result = supplier_->GetCStringSymbolData(
+ module, system_info, &symbol_file, &symbol_data, &symbol_data_size);
+
+ switch (symbol_result) {
+ case SymbolSupplier::FOUND: {
+ bool load_success = resolver_->LoadModuleUsingMemoryBuffer(
+ frame->module,
+ symbol_data,
+ symbol_data_size);
+ if (resolver_->ShouldDeleteMemoryBufferAfterLoadModule()) {
+ supplier_->FreeSymbolData(module);
+ }
+
+ if (load_success) {
+ resolver_->FillSourceLineInfo(frame);
+ return resolver_->IsModuleCorrupt(frame->module) ?
+ kWarningCorruptSymbols : kNoError;
+ } else {
+ BPLOG(ERROR) << "Failed to load symbol file in resolver.";
+ no_symbol_modules_.insert(module->code_file());
+ return kError;
+ }
+ }
+
+ case SymbolSupplier::NOT_FOUND:
+ no_symbol_modules_.insert(module->code_file());
+ return kError;
+
+ case SymbolSupplier::INTERRUPT:
+ return kInterrupt;
+
+ default:
+ BPLOG(ERROR) << "Unknown SymbolResult enum: " << symbol_result;
+ return kError;
+ }
+}
+
+WindowsFrameInfo* StackFrameSymbolizer::FindWindowsFrameInfo(
+ const StackFrame* frame) {
+ return resolver_ ? resolver_->FindWindowsFrameInfo(frame) : NULL;
+}
+
+CFIFrameInfo* StackFrameSymbolizer::FindCFIFrameInfo(
+ const StackFrame* frame) {
+ return resolver_ ? resolver_->FindCFIFrameInfo(frame) : NULL;
+}
+
+} // namespace google_breakpad
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/stackwalk_common.cc b/toolkit/crashreporter/google-breakpad/src/processor/stackwalk_common.cc
new file mode 100644
index 0000000000..dc84352b61
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/stackwalk_common.cc
@@ -0,0 +1,1036 @@
+// 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.
+
+// stackwalk_common.cc: Module shared by the {micro,mini}dump_stackwalck
+// executables to print the content of dumps (w/ stack traces) on the console.
+//
+// Author: Mark Mentovai
+
+#include "processor/stackwalk_common.h"
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <string>
+#include <vector>
+
+#include "common/stdio_wrapper.h"
+#include "common/using_std_string.h"
+#include "google_breakpad/processor/call_stack.h"
+#include "google_breakpad/processor/code_module.h"
+#include "google_breakpad/processor/code_modules.h"
+#include "google_breakpad/processor/process_state.h"
+#include "google_breakpad/processor/source_line_resolver_interface.h"
+#include "google_breakpad/processor/stack_frame_cpu.h"
+#include "processor/logging.h"
+#include "processor/pathname_stripper.h"
+
+namespace google_breakpad {
+
+namespace {
+
+using std::vector;
+
+// Separator character for machine readable output.
+static const char kOutputSeparator = '|';
+
+// PrintRegister prints a register's name and value to stdout. It will
+// print four registers on a line. For the first register in a set,
+// pass 0 for |start_col|. For registers in a set, pass the most recent
+// return value of PrintRegister.
+// The caller is responsible for printing the final newline after a set
+// of registers is completely printed, regardless of the number of calls
+// to PrintRegister.
+static const int kMaxWidth = 80; // optimize for an 80-column terminal
+static int PrintRegister(const char *name, uint32_t value, int start_col) {
+ char buffer[64];
+ snprintf(buffer, sizeof(buffer), " %5s = 0x%08x", name, value);
+
+ if (start_col + static_cast<ssize_t>(strlen(buffer)) > kMaxWidth) {
+ start_col = 0;
+ printf("\n ");
+ }
+ fputs(buffer, stdout);
+
+ return start_col + strlen(buffer);
+}
+
+// PrintRegister64 does the same thing, but for 64-bit registers.
+static int PrintRegister64(const char *name, uint64_t value, int start_col) {
+ char buffer[64];
+ snprintf(buffer, sizeof(buffer), " %5s = 0x%016" PRIx64 , name, value);
+
+ if (start_col + static_cast<ssize_t>(strlen(buffer)) > kMaxWidth) {
+ start_col = 0;
+ printf("\n ");
+ }
+ fputs(buffer, stdout);
+
+ return start_col + strlen(buffer);
+}
+
+// StripSeparator takes a string |original| and returns a copy
+// of the string with all occurences of |kOutputSeparator| removed.
+static string StripSeparator(const string &original) {
+ string result = original;
+ string::size_type position = 0;
+ while ((position = result.find(kOutputSeparator, position)) != string::npos) {
+ result.erase(position, 1);
+ }
+ position = 0;
+ while ((position = result.find('\n', position)) != string::npos) {
+ result.erase(position, 1);
+ }
+ return result;
+}
+
+// PrintStackContents prints the stack contents of the current frame to stdout.
+static void PrintStackContents(const string &indent,
+ const StackFrame *frame,
+ const StackFrame *prev_frame,
+ const string &cpu,
+ const MemoryRegion *memory,
+ const CodeModules* modules,
+ SourceLineResolverInterface *resolver) {
+ // Find stack range.
+ int word_length = 0;
+ uint64_t stack_begin = 0, stack_end = 0;
+ if (cpu == "x86") {
+ word_length = 4;
+ const StackFrameX86 *frame_x86 = static_cast<const StackFrameX86*>(frame);
+ const StackFrameX86 *prev_frame_x86 =
+ static_cast<const StackFrameX86*>(prev_frame);
+ if ((frame_x86->context_validity & StackFrameX86::CONTEXT_VALID_ESP) &&
+ (prev_frame_x86->context_validity & StackFrameX86::CONTEXT_VALID_ESP)) {
+ stack_begin = frame_x86->context.esp;
+ stack_end = prev_frame_x86->context.esp;
+ }
+ } else if (cpu == "amd64") {
+ word_length = 8;
+ const StackFrameAMD64 *frame_amd64 =
+ static_cast<const StackFrameAMD64*>(frame);
+ const StackFrameAMD64 *prev_frame_amd64 =
+ static_cast<const StackFrameAMD64*>(prev_frame);
+ if ((frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_RSP) &&
+ (prev_frame_amd64->context_validity &
+ StackFrameAMD64::CONTEXT_VALID_RSP)) {
+ stack_begin = frame_amd64->context.rsp;
+ stack_end = prev_frame_amd64->context.rsp;
+ }
+ } else if (cpu == "arm") {
+ word_length = 4;
+ const StackFrameARM *frame_arm = static_cast<const StackFrameARM*>(frame);
+ const StackFrameARM *prev_frame_arm =
+ static_cast<const StackFrameARM*>(prev_frame);
+ if ((frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_SP) &&
+ (prev_frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_SP)) {
+ stack_begin = frame_arm->context.iregs[13];
+ stack_end = prev_frame_arm->context.iregs[13];
+ }
+ } else if (cpu == "arm64") {
+ word_length = 8;
+ const StackFrameARM64 *frame_arm64 =
+ static_cast<const StackFrameARM64*>(frame);
+ const StackFrameARM64 *prev_frame_arm64 =
+ static_cast<const StackFrameARM64*>(prev_frame);
+ if ((frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_SP) &&
+ (prev_frame_arm64->context_validity &
+ StackFrameARM64::CONTEXT_VALID_SP)) {
+ stack_begin = frame_arm64->context.iregs[31];
+ stack_end = prev_frame_arm64->context.iregs[31];
+ }
+ }
+ if (!word_length || !stack_begin || !stack_end)
+ return;
+
+ // Print stack contents.
+ printf("\n%sStack contents:", indent.c_str());
+ for(uint64_t address = stack_begin; address < stack_end; ) {
+ // Print the start address of this row.
+ if (word_length == 4)
+ printf("\n%s %08x", indent.c_str(), static_cast<uint32_t>(address));
+ else
+ printf("\n%s %016" PRIx64, indent.c_str(), address);
+
+ // Print data in hex.
+ const int kBytesPerRow = 16;
+ string data_as_string;
+ for (int i = 0; i < kBytesPerRow; ++i, ++address) {
+ uint8_t value = 0;
+ if (address < stack_end &&
+ memory->GetMemoryAtAddress(address, &value)) {
+ printf(" %02x", value);
+ data_as_string.push_back(isprint(value) ? value : '.');
+ } else {
+ printf(" ");
+ data_as_string.push_back(' ');
+ }
+ }
+ // Print data as string.
+ printf(" %s", data_as_string.c_str());
+ }
+
+ // Try to find instruction pointers from stack.
+ printf("\n%sPossible instruction pointers:\n", indent.c_str());
+ for (uint64_t address = stack_begin; address < stack_end;
+ address += word_length) {
+ StackFrame pointee_frame;
+
+ // Read a word (possible instruction pointer) from stack.
+ if (word_length == 4) {
+ uint32_t data32 = 0;
+ memory->GetMemoryAtAddress(address, &data32);
+ pointee_frame.instruction = data32;
+ } else {
+ uint64_t data64 = 0;
+ memory->GetMemoryAtAddress(address, &data64);
+ pointee_frame.instruction = data64;
+ }
+ pointee_frame.module =
+ modules->GetModuleForAddress(pointee_frame.instruction);
+
+ // Try to look up the function name.
+ if (pointee_frame.module)
+ resolver->FillSourceLineInfo(&pointee_frame);
+
+ // Print function name.
+ if (!pointee_frame.function_name.empty()) {
+ if (word_length == 4) {
+ printf("%s *(0x%08x) = 0x%08x", indent.c_str(),
+ static_cast<uint32_t>(address),
+ static_cast<uint32_t>(pointee_frame.instruction));
+ } else {
+ printf("%s *(0x%016" PRIx64 ") = 0x%016" PRIx64,
+ indent.c_str(), address, pointee_frame.instruction);
+ }
+ printf(" <%s> [%s : %d + 0x%" PRIx64 "]\n",
+ pointee_frame.function_name.c_str(),
+ PathnameStripper::File(pointee_frame.source_file_name).c_str(),
+ pointee_frame.source_line,
+ pointee_frame.instruction - pointee_frame.source_line_base);
+ }
+ }
+ printf("\n");
+}
+
+// PrintStack prints the call stack in |stack| to stdout, in a reasonably
+// useful form. Module, function, and source file names are displayed if
+// they are available. The code offset to the base code address of the
+// source line, function, or module is printed, preferring them in that
+// order. If no source line, function, or module information is available,
+// an absolute code offset is printed.
+//
+// If |cpu| is a recognized CPU name, relevant register state for each stack
+// frame printed is also output, if available.
+static void PrintStack(const CallStack *stack,
+ const string &cpu,
+ bool output_stack_contents,
+ const MemoryRegion* memory,
+ const CodeModules* modules,
+ SourceLineResolverInterface* resolver) {
+ int frame_count = stack->frames()->size();
+ if (frame_count == 0) {
+ printf(" <no frames>\n");
+ }
+ for (int frame_index = 0; frame_index < frame_count; ++frame_index) {
+ const StackFrame *frame = stack->frames()->at(frame_index);
+ printf("%2d ", frame_index);
+
+ uint64_t instruction_address = frame->ReturnAddress();
+
+ if (frame->module) {
+ printf("%s", PathnameStripper::File(frame->module->code_file()).c_str());
+ if (!frame->function_name.empty()) {
+ printf("!%s", frame->function_name.c_str());
+ if (!frame->source_file_name.empty()) {
+ string source_file = PathnameStripper::File(frame->source_file_name);
+ printf(" [%s : %d + 0x%" PRIx64 "]",
+ source_file.c_str(),
+ frame->source_line,
+ instruction_address - frame->source_line_base);
+ } else {
+ printf(" + 0x%" PRIx64, instruction_address - frame->function_base);
+ }
+ } else {
+ printf(" + 0x%" PRIx64,
+ instruction_address - frame->module->base_address());
+ }
+ } else {
+ printf("0x%" PRIx64, instruction_address);
+ }
+ printf("\n ");
+
+ int sequence = 0;
+ if (cpu == "x86") {
+ const StackFrameX86 *frame_x86 =
+ reinterpret_cast<const StackFrameX86*>(frame);
+
+ if (frame_x86->context_validity & StackFrameX86::CONTEXT_VALID_EIP)
+ sequence = PrintRegister("eip", frame_x86->context.eip, sequence);
+ if (frame_x86->context_validity & StackFrameX86::CONTEXT_VALID_ESP)
+ sequence = PrintRegister("esp", frame_x86->context.esp, sequence);
+ if (frame_x86->context_validity & StackFrameX86::CONTEXT_VALID_EBP)
+ sequence = PrintRegister("ebp", frame_x86->context.ebp, sequence);
+ if (frame_x86->context_validity & StackFrameX86::CONTEXT_VALID_EBX)
+ sequence = PrintRegister("ebx", frame_x86->context.ebx, sequence);
+ if (frame_x86->context_validity & StackFrameX86::CONTEXT_VALID_ESI)
+ sequence = PrintRegister("esi", frame_x86->context.esi, sequence);
+ if (frame_x86->context_validity & StackFrameX86::CONTEXT_VALID_EDI)
+ sequence = PrintRegister("edi", frame_x86->context.edi, sequence);
+ if (frame_x86->context_validity == StackFrameX86::CONTEXT_VALID_ALL) {
+ sequence = PrintRegister("eax", frame_x86->context.eax, sequence);
+ sequence = PrintRegister("ecx", frame_x86->context.ecx, sequence);
+ sequence = PrintRegister("edx", frame_x86->context.edx, sequence);
+ sequence = PrintRegister("efl", frame_x86->context.eflags, sequence);
+ }
+ } else if (cpu == "ppc") {
+ const StackFramePPC *frame_ppc =
+ reinterpret_cast<const StackFramePPC*>(frame);
+
+ if (frame_ppc->context_validity & StackFramePPC::CONTEXT_VALID_SRR0)
+ sequence = PrintRegister("srr0", frame_ppc->context.srr0, sequence);
+ if (frame_ppc->context_validity & StackFramePPC::CONTEXT_VALID_GPR1)
+ sequence = PrintRegister("r1", frame_ppc->context.gpr[1], sequence);
+ } else if (cpu == "amd64") {
+ const StackFrameAMD64 *frame_amd64 =
+ reinterpret_cast<const StackFrameAMD64*>(frame);
+
+ if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_RAX)
+ sequence = PrintRegister64("rax", frame_amd64->context.rax, sequence);
+ if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_RDX)
+ sequence = PrintRegister64("rdx", frame_amd64->context.rdx, sequence);
+ if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_RCX)
+ sequence = PrintRegister64("rcx", frame_amd64->context.rcx, sequence);
+ if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_RBX)
+ sequence = PrintRegister64("rbx", frame_amd64->context.rbx, sequence);
+ if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_RSI)
+ sequence = PrintRegister64("rsi", frame_amd64->context.rsi, sequence);
+ if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_RDI)
+ sequence = PrintRegister64("rdi", frame_amd64->context.rdi, sequence);
+ if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_RBP)
+ sequence = PrintRegister64("rbp", frame_amd64->context.rbp, sequence);
+ if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_RSP)
+ sequence = PrintRegister64("rsp", frame_amd64->context.rsp, sequence);
+ if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_R8)
+ sequence = PrintRegister64("r8", frame_amd64->context.r8, sequence);
+ if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_R9)
+ sequence = PrintRegister64("r9", frame_amd64->context.r9, sequence);
+ if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_R10)
+ sequence = PrintRegister64("r10", frame_amd64->context.r10, sequence);
+ if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_R11)
+ sequence = PrintRegister64("r11", frame_amd64->context.r11, sequence);
+ if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_R12)
+ sequence = PrintRegister64("r12", frame_amd64->context.r12, sequence);
+ if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_R13)
+ sequence = PrintRegister64("r13", frame_amd64->context.r13, sequence);
+ if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_R14)
+ sequence = PrintRegister64("r14", frame_amd64->context.r14, sequence);
+ if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_R15)
+ sequence = PrintRegister64("r15", frame_amd64->context.r15, sequence);
+ if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_RIP)
+ sequence = PrintRegister64("rip", frame_amd64->context.rip, sequence);
+ } else if (cpu == "sparc") {
+ const StackFrameSPARC *frame_sparc =
+ reinterpret_cast<const StackFrameSPARC*>(frame);
+
+ if (frame_sparc->context_validity & StackFrameSPARC::CONTEXT_VALID_SP)
+ sequence = PrintRegister("sp", frame_sparc->context.g_r[14], sequence);
+ if (frame_sparc->context_validity & StackFrameSPARC::CONTEXT_VALID_FP)
+ sequence = PrintRegister("fp", frame_sparc->context.g_r[30], sequence);
+ if (frame_sparc->context_validity & StackFrameSPARC::CONTEXT_VALID_PC)
+ sequence = PrintRegister("pc", frame_sparc->context.pc, sequence);
+ } else if (cpu == "arm") {
+ const StackFrameARM *frame_arm =
+ reinterpret_cast<const StackFrameARM*>(frame);
+
+ // Argument registers (caller-saves), which will likely only be valid
+ // for the youngest frame.
+ if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_R0)
+ sequence = PrintRegister("r0", frame_arm->context.iregs[0], sequence);
+ if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_R1)
+ sequence = PrintRegister("r1", frame_arm->context.iregs[1], sequence);
+ if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_R2)
+ sequence = PrintRegister("r2", frame_arm->context.iregs[2], sequence);
+ if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_R3)
+ sequence = PrintRegister("r3", frame_arm->context.iregs[3], sequence);
+
+ // General-purpose callee-saves registers.
+ if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_R4)
+ sequence = PrintRegister("r4", frame_arm->context.iregs[4], sequence);
+ if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_R5)
+ sequence = PrintRegister("r5", frame_arm->context.iregs[5], sequence);
+ if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_R6)
+ sequence = PrintRegister("r6", frame_arm->context.iregs[6], sequence);
+ if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_R7)
+ sequence = PrintRegister("r7", frame_arm->context.iregs[7], sequence);
+ if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_R8)
+ sequence = PrintRegister("r8", frame_arm->context.iregs[8], sequence);
+ if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_R9)
+ sequence = PrintRegister("r9", frame_arm->context.iregs[9], sequence);
+ if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_R10)
+ sequence = PrintRegister("r10", frame_arm->context.iregs[10], sequence);
+ if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_R12)
+ sequence = PrintRegister("r12", frame_arm->context.iregs[12], sequence);
+
+ // Registers with a dedicated or conventional purpose.
+ if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_FP)
+ sequence = PrintRegister("fp", frame_arm->context.iregs[11], sequence);
+ if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_SP)
+ sequence = PrintRegister("sp", frame_arm->context.iregs[13], sequence);
+ if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_LR)
+ sequence = PrintRegister("lr", frame_arm->context.iregs[14], sequence);
+ if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_PC)
+ sequence = PrintRegister("pc", frame_arm->context.iregs[15], sequence);
+ } else if (cpu == "arm64") {
+ const StackFrameARM64 *frame_arm64 =
+ reinterpret_cast<const StackFrameARM64*>(frame);
+
+ if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X0) {
+ sequence =
+ PrintRegister64("x0", frame_arm64->context.iregs[0], sequence);
+ }
+ if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X1) {
+ sequence =
+ PrintRegister64("x1", frame_arm64->context.iregs[1], sequence);
+ }
+ if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X2) {
+ sequence =
+ PrintRegister64("x2", frame_arm64->context.iregs[2], sequence);
+ }
+ if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X3) {
+ sequence =
+ PrintRegister64("x3", frame_arm64->context.iregs[3], sequence);
+ }
+ if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X4) {
+ sequence =
+ PrintRegister64("x4", frame_arm64->context.iregs[4], sequence);
+ }
+ if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X5) {
+ sequence =
+ PrintRegister64("x5", frame_arm64->context.iregs[5], sequence);
+ }
+ if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X6) {
+ sequence =
+ PrintRegister64("x6", frame_arm64->context.iregs[6], sequence);
+ }
+ if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X7) {
+ sequence =
+ PrintRegister64("x7", frame_arm64->context.iregs[7], sequence);
+ }
+ if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X8) {
+ sequence =
+ PrintRegister64("x8", frame_arm64->context.iregs[8], sequence);
+ }
+ if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X9) {
+ sequence =
+ PrintRegister64("x9", frame_arm64->context.iregs[9], sequence);
+ }
+ if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X10) {
+ sequence =
+ PrintRegister64("x10", frame_arm64->context.iregs[10], sequence);
+ }
+ if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X11) {
+ sequence =
+ PrintRegister64("x11", frame_arm64->context.iregs[11], sequence);
+ }
+ if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X12) {
+ sequence =
+ PrintRegister64("x12", frame_arm64->context.iregs[12], sequence);
+ }
+ if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X13) {
+ sequence =
+ PrintRegister64("x13", frame_arm64->context.iregs[13], sequence);
+ }
+ if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X14) {
+ sequence =
+ PrintRegister64("x14", frame_arm64->context.iregs[14], sequence);
+ }
+ if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X15) {
+ sequence =
+ PrintRegister64("x15", frame_arm64->context.iregs[15], sequence);
+ }
+ if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X16) {
+ sequence =
+ PrintRegister64("x16", frame_arm64->context.iregs[16], sequence);
+ }
+ if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X17) {
+ sequence =
+ PrintRegister64("x17", frame_arm64->context.iregs[17], sequence);
+ }
+ if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X18) {
+ sequence =
+ PrintRegister64("x18", frame_arm64->context.iregs[18], sequence);
+ }
+ if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X19) {
+ sequence =
+ PrintRegister64("x19", frame_arm64->context.iregs[19], sequence);
+ }
+ if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X20) {
+ sequence =
+ PrintRegister64("x20", frame_arm64->context.iregs[20], sequence);
+ }
+ if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X21) {
+ sequence =
+ PrintRegister64("x21", frame_arm64->context.iregs[21], sequence);
+ }
+ if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X22) {
+ sequence =
+ PrintRegister64("x22", frame_arm64->context.iregs[22], sequence);
+ }
+ if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X23) {
+ sequence =
+ PrintRegister64("x23", frame_arm64->context.iregs[23], sequence);
+ }
+ if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X24) {
+ sequence =
+ PrintRegister64("x24", frame_arm64->context.iregs[24], sequence);
+ }
+ if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X25) {
+ sequence =
+ PrintRegister64("x25", frame_arm64->context.iregs[25], sequence);
+ }
+ if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X26) {
+ sequence =
+ PrintRegister64("x26", frame_arm64->context.iregs[26], sequence);
+ }
+ if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X27) {
+ sequence =
+ PrintRegister64("x27", frame_arm64->context.iregs[27], sequence);
+ }
+ if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X28) {
+ sequence =
+ PrintRegister64("x28", frame_arm64->context.iregs[28], sequence);
+ }
+
+ // Registers with a dedicated or conventional purpose.
+ if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_FP) {
+ sequence =
+ PrintRegister64("fp", frame_arm64->context.iregs[29], sequence);
+ }
+ if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_LR) {
+ sequence =
+ PrintRegister64("lr", frame_arm64->context.iregs[30], sequence);
+ }
+ if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_SP) {
+ sequence =
+ PrintRegister64("sp", frame_arm64->context.iregs[31], sequence);
+ }
+ if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_PC) {
+ sequence =
+ PrintRegister64("pc", frame_arm64->context.iregs[32], sequence);
+ }
+ } else if ((cpu == "mips") || (cpu == "mips64")) {
+ const StackFrameMIPS* frame_mips =
+ reinterpret_cast<const StackFrameMIPS*>(frame);
+
+ if (frame_mips->context_validity & StackFrameMIPS::CONTEXT_VALID_GP)
+ sequence = PrintRegister64("gp",
+ frame_mips->context.iregs[MD_CONTEXT_MIPS_REG_GP],
+ sequence);
+ if (frame_mips->context_validity & StackFrameMIPS::CONTEXT_VALID_SP)
+ sequence = PrintRegister64("sp",
+ frame_mips->context.iregs[MD_CONTEXT_MIPS_REG_SP],
+ sequence);
+ if (frame_mips->context_validity & StackFrameMIPS::CONTEXT_VALID_FP)
+ sequence = PrintRegister64("fp",
+ frame_mips->context.iregs[MD_CONTEXT_MIPS_REG_FP],
+ sequence);
+ if (frame_mips->context_validity & StackFrameMIPS::CONTEXT_VALID_RA)
+ sequence = PrintRegister64("ra",
+ frame_mips->context.iregs[MD_CONTEXT_MIPS_REG_RA],
+ sequence);
+ if (frame_mips->context_validity & StackFrameMIPS::CONTEXT_VALID_PC)
+ sequence = PrintRegister64("pc", frame_mips->context.epc, sequence);
+
+ // Save registers s0-s7
+ if (frame_mips->context_validity & StackFrameMIPS::CONTEXT_VALID_S0)
+ sequence = PrintRegister64("s0",
+ frame_mips->context.iregs[MD_CONTEXT_MIPS_REG_S0],
+ sequence);
+ if (frame_mips->context_validity & StackFrameMIPS::CONTEXT_VALID_S1)
+ sequence = PrintRegister64("s1",
+ frame_mips->context.iregs[MD_CONTEXT_MIPS_REG_S1],
+ sequence);
+ if (frame_mips->context_validity & StackFrameMIPS::CONTEXT_VALID_S2)
+ sequence = PrintRegister64("s2",
+ frame_mips->context.iregs[MD_CONTEXT_MIPS_REG_S2],
+ sequence);
+ if (frame_mips->context_validity & StackFrameMIPS::CONTEXT_VALID_S3)
+ sequence = PrintRegister64("s3",
+ frame_mips->context.iregs[MD_CONTEXT_MIPS_REG_S3],
+ sequence);
+ if (frame_mips->context_validity & StackFrameMIPS::CONTEXT_VALID_S4)
+ sequence = PrintRegister64("s4",
+ frame_mips->context.iregs[MD_CONTEXT_MIPS_REG_S4],
+ sequence);
+ if (frame_mips->context_validity & StackFrameMIPS::CONTEXT_VALID_S5)
+ sequence = PrintRegister64("s5",
+ frame_mips->context.iregs[MD_CONTEXT_MIPS_REG_S5],
+ sequence);
+ if (frame_mips->context_validity & StackFrameMIPS::CONTEXT_VALID_S6)
+ sequence = PrintRegister64("s6",
+ frame_mips->context.iregs[MD_CONTEXT_MIPS_REG_S6],
+ sequence);
+ if (frame_mips->context_validity & StackFrameMIPS::CONTEXT_VALID_S7)
+ sequence = PrintRegister64("s7",
+ frame_mips->context.iregs[MD_CONTEXT_MIPS_REG_S7],
+ sequence);
+ }
+ printf("\n Found by: %s\n", frame->trust_description().c_str());
+
+ // Print stack contents.
+ if (output_stack_contents && frame_index + 1 < frame_count) {
+ const string indent(" ");
+ PrintStackContents(indent, frame, stack->frames()->at(frame_index + 1),
+ cpu, memory, modules, resolver);
+ }
+ }
+}
+
+// PrintStackMachineReadable prints the call stack in |stack| to stdout,
+// in the following machine readable pipe-delimited text format:
+// thread number|frame number|module|function|source file|line|offset
+//
+// Module, function, source file, and source line may all be empty
+// depending on availability. The code offset follows the same rules as
+// PrintStack above.
+static void PrintStackMachineReadable(int thread_num, const CallStack *stack) {
+ int frame_count = stack->frames()->size();
+ for (int frame_index = 0; frame_index < frame_count; ++frame_index) {
+ const StackFrame *frame = stack->frames()->at(frame_index);
+ printf("%d%c%d%c", thread_num, kOutputSeparator, frame_index,
+ kOutputSeparator);
+
+ uint64_t instruction_address = frame->ReturnAddress();
+
+ if (frame->module) {
+ assert(!frame->module->code_file().empty());
+ printf("%s", StripSeparator(PathnameStripper::File(
+ frame->module->code_file())).c_str());
+ if (!frame->function_name.empty()) {
+ printf("%c%s", kOutputSeparator,
+ StripSeparator(frame->function_name).c_str());
+ if (!frame->source_file_name.empty()) {
+ printf("%c%s%c%d%c0x%" PRIx64,
+ kOutputSeparator,
+ StripSeparator(frame->source_file_name).c_str(),
+ kOutputSeparator,
+ frame->source_line,
+ kOutputSeparator,
+ instruction_address - frame->source_line_base);
+ } else {
+ printf("%c%c%c0x%" PRIx64,
+ kOutputSeparator, // empty source file
+ kOutputSeparator, // empty source line
+ kOutputSeparator,
+ instruction_address - frame->function_base);
+ }
+ } else {
+ printf("%c%c%c%c0x%" PRIx64,
+ kOutputSeparator, // empty function name
+ kOutputSeparator, // empty source file
+ kOutputSeparator, // empty source line
+ kOutputSeparator,
+ instruction_address - frame->module->base_address());
+ }
+ } else {
+ // the printf before this prints a trailing separator for module name
+ printf("%c%c%c%c0x%" PRIx64,
+ kOutputSeparator, // empty function name
+ kOutputSeparator, // empty source file
+ kOutputSeparator, // empty source line
+ kOutputSeparator,
+ instruction_address);
+ }
+ printf("\n");
+ }
+}
+
+// ContainsModule checks whether a given |module| is in the vector
+// |modules_without_symbols|.
+static bool ContainsModule(
+ const vector<const CodeModule*> *modules,
+ const CodeModule *module) {
+ assert(modules);
+ assert(module);
+ vector<const CodeModule*>::const_iterator iter;
+ for (iter = modules->begin(); iter != modules->end(); ++iter) {
+ if (module->debug_file().compare((*iter)->debug_file()) == 0 &&
+ module->debug_identifier().compare((*iter)->debug_identifier()) == 0) {
+ return true;
+ }
+ }
+ return false;
+}
+
+// PrintModule prints a single |module| to stdout.
+// |modules_without_symbols| should contain the list of modules that were
+// confirmed to be missing their symbols during the stack walk.
+static void PrintModule(
+ const CodeModule *module,
+ const vector<const CodeModule*> *modules_without_symbols,
+ const vector<const CodeModule*> *modules_with_corrupt_symbols,
+ uint64_t main_address) {
+ string symbol_issues;
+ if (ContainsModule(modules_without_symbols, module)) {
+ symbol_issues = " (WARNING: No symbols, " +
+ PathnameStripper::File(module->debug_file()) + ", " +
+ module->debug_identifier() + ")";
+ } else if (ContainsModule(modules_with_corrupt_symbols, module)) {
+ symbol_issues = " (WARNING: Corrupt symbols, " +
+ PathnameStripper::File(module->debug_file()) + ", " +
+ module->debug_identifier() + ")";
+ }
+ uint64_t base_address = module->base_address();
+ printf("0x%08" PRIx64 " - 0x%08" PRIx64 " %s %s%s%s\n",
+ base_address, base_address + module->size() - 1,
+ PathnameStripper::File(module->code_file()).c_str(),
+ module->version().empty() ? "???" : module->version().c_str(),
+ main_address != 0 && base_address == main_address ? " (main)" : "",
+ symbol_issues.c_str());
+}
+
+// PrintModules prints the list of all loaded |modules| to stdout.
+// |modules_without_symbols| should contain the list of modules that were
+// confirmed to be missing their symbols during the stack walk.
+static void PrintModules(
+ const CodeModules *modules,
+ const vector<const CodeModule*> *modules_without_symbols,
+ const vector<const CodeModule*> *modules_with_corrupt_symbols) {
+ if (!modules)
+ return;
+
+ printf("\n");
+ printf("Loaded modules:\n");
+
+ uint64_t main_address = 0;
+ const CodeModule *main_module = modules->GetMainModule();
+ if (main_module) {
+ main_address = main_module->base_address();
+ }
+
+ unsigned int module_count = modules->module_count();
+ for (unsigned int module_sequence = 0;
+ module_sequence < module_count;
+ ++module_sequence) {
+ const CodeModule *module = modules->GetModuleAtSequence(module_sequence);
+ PrintModule(module, modules_without_symbols, modules_with_corrupt_symbols,
+ main_address);
+ }
+}
+
+// PrintModulesMachineReadable outputs a list of loaded modules,
+// one per line, in the following machine-readable pipe-delimited
+// text format:
+// Module|{Module Filename}|{Version}|{Debug Filename}|{Debug Identifier}|
+// {Base Address}|{Max Address}|{Main}
+static void PrintModulesMachineReadable(const CodeModules *modules) {
+ if (!modules)
+ return;
+
+ uint64_t main_address = 0;
+ const CodeModule *main_module = modules->GetMainModule();
+ if (main_module) {
+ main_address = main_module->base_address();
+ }
+
+ unsigned int module_count = modules->module_count();
+ for (unsigned int module_sequence = 0;
+ module_sequence < module_count;
+ ++module_sequence) {
+ const CodeModule *module = modules->GetModuleAtSequence(module_sequence);
+ uint64_t base_address = module->base_address();
+ printf("Module%c%s%c%s%c%s%c%s%c0x%08" PRIx64 "%c0x%08" PRIx64 "%c%d\n",
+ kOutputSeparator,
+ StripSeparator(PathnameStripper::File(module->code_file())).c_str(),
+ kOutputSeparator, StripSeparator(module->version()).c_str(),
+ kOutputSeparator,
+ StripSeparator(PathnameStripper::File(module->debug_file())).c_str(),
+ kOutputSeparator,
+ StripSeparator(module->debug_identifier()).c_str(),
+ kOutputSeparator, base_address,
+ kOutputSeparator, base_address + module->size() - 1,
+ kOutputSeparator,
+ main_module != NULL && base_address == main_address ? 1 : 0);
+ }
+}
+
+// PrintUnloadedModulesMachineReadable outputs a list of loaded modules,
+// one per line, in the following machine-readable pipe-delimited
+// text format:
+// UnloadedModule|{Module Filename}|{Base Address}|{Max Address}|{Main}
+static void PrintUnloadedModulesMachineReadable(const CodeModules* modules) {
+ if (!modules)
+ return;
+
+ uint64_t main_address = 0;
+ const CodeModule* main_module = modules->GetMainModule();
+ if (main_module) {
+ main_address = main_module->base_address();
+ }
+
+ unsigned int module_count = modules->module_count();
+ for (unsigned int module_sequence = 0;
+ module_sequence < module_count;
+ ++module_sequence) {
+ const CodeModule* module = modules->GetModuleAtSequence(module_sequence);
+ uint64_t base_address = module->base_address();
+ printf("UnloadedModule%c%s%c0x%08" PRIx64 "%c0x%08" PRIx64 "%c%d\n",
+ kOutputSeparator,
+ StripSeparator(PathnameStripper::File(module->code_file())).c_str(),
+ kOutputSeparator, base_address,
+ kOutputSeparator, base_address + module->size() - 1,
+ kOutputSeparator,
+ main_module != NULL && base_address == main_address ? 1 : 0);
+ }
+}
+
+} // namespace
+
+void PrintProcessState(const ProcessState& process_state,
+ bool output_stack_contents,
+ SourceLineResolverInterface* resolver) {
+ // Print OS and CPU information.
+ string cpu = process_state.system_info()->cpu;
+ string cpu_info = process_state.system_info()->cpu_info;
+ printf("Operating system: %s\n", process_state.system_info()->os.c_str());
+ printf(" %s\n",
+ process_state.system_info()->os_version.c_str());
+ printf("CPU: %s\n", cpu.c_str());
+ if (!cpu_info.empty()) {
+ // This field is optional.
+ printf(" %s\n", cpu_info.c_str());
+ }
+ printf(" %d CPU%s\n",
+ process_state.system_info()->cpu_count,
+ process_state.system_info()->cpu_count != 1 ? "s" : "");
+ printf("\n");
+
+ // Print GPU information
+ string gl_version = process_state.system_info()->gl_version;
+ string gl_vendor = process_state.system_info()->gl_vendor;
+ string gl_renderer = process_state.system_info()->gl_renderer;
+ printf("GPU:");
+ if (!gl_version.empty() || !gl_vendor.empty() || !gl_renderer.empty()) {
+ printf(" %s\n", gl_version.c_str());
+ printf(" %s\n", gl_vendor.c_str());
+ printf(" %s\n", gl_renderer.c_str());
+ } else {
+ printf(" UNKNOWN\n");
+ }
+ printf("\n");
+
+ // Print crash information.
+ if (process_state.crashed()) {
+ printf("Crash reason: %s\n", process_state.crash_reason().c_str());
+ printf("Crash address: 0x%" PRIx64 "\n", process_state.crash_address());
+ } else {
+ printf("No crash\n");
+ }
+
+ string assertion = process_state.assertion();
+ if (!assertion.empty()) {
+ printf("Assertion: %s\n", assertion.c_str());
+ }
+
+ // Compute process uptime if the process creation and crash times are
+ // available in the dump.
+ if (process_state.time_date_stamp() != 0 &&
+ process_state.process_create_time() != 0 &&
+ process_state.time_date_stamp() >= process_state.process_create_time()) {
+ printf("Process uptime: %d seconds\n",
+ process_state.time_date_stamp() -
+ process_state.process_create_time());
+ } else {
+ printf("Process uptime: not available\n");
+ }
+
+ if (!process_state.mac_crash_info().empty()) {
+ printf("\n");
+ printf("Application-specific information:\n");
+ printf("%s", process_state.mac_crash_info().c_str());
+ }
+
+ // If the thread that requested the dump is known, print it first.
+ int requesting_thread = process_state.requesting_thread();
+ if (requesting_thread != -1) {
+ const CallStack* requesting_thread_callstack =
+ process_state.threads()->at(requesting_thread);
+ printf("\n"
+ "Thread %d tid %u (%s)",
+ requesting_thread,
+ requesting_thread_callstack->tid(),
+ process_state.crashed() ? "crashed" :
+ "requested dump, did not crash");
+ if (!requesting_thread_callstack->name().empty()) {
+ printf(" - %s", requesting_thread_callstack->name().c_str());
+ }
+ PrintStack(requesting_thread_callstack, cpu,
+ output_stack_contents,
+ process_state.thread_memory_regions()->at(requesting_thread),
+ process_state.modules(), resolver);
+ }
+
+ // Print all of the threads in the dump.
+ int thread_count = process_state.threads()->size();
+ for (int thread_index = 0; thread_index < thread_count; ++thread_index) {
+ if (thread_index != requesting_thread) {
+ // Don't print the crash thread again, it was already printed.
+ const CallStack* callstack = process_state.threads()->at(thread_index);
+ printf("\n"
+ "Thread %d tid %u", thread_index, callstack->tid());
+ if (!callstack->name().empty()) {
+ printf(" - %s", callstack->name().c_str());
+ }
+ printf("\n");
+ PrintStack(callstack, cpu,
+ output_stack_contents,
+ process_state.thread_memory_regions()->at(thread_index),
+ process_state.modules(), resolver);
+ }
+ }
+
+ PrintModules(process_state.modules(),
+ process_state.modules_without_symbols(),
+ process_state.modules_with_corrupt_symbols());
+}
+
+void PrintProcessStateMachineReadable(const ProcessState& process_state) {
+ // Print OS and CPU information.
+ // OS|{OS Name}|{OS Version}
+ // CPU|{CPU Name}|{CPU Info}|{Number of CPUs}
+ // GPU|{GPU version}|{GPU vendor}|{GPU renderer}
+ printf("OS%c%s%c%s\n", kOutputSeparator,
+ StripSeparator(process_state.system_info()->os).c_str(),
+ kOutputSeparator,
+ StripSeparator(process_state.system_info()->os_version).c_str());
+ printf("CPU%c%s%c%s%c%d\n", kOutputSeparator,
+ StripSeparator(process_state.system_info()->cpu).c_str(),
+ kOutputSeparator,
+ // this may be empty
+ StripSeparator(process_state.system_info()->cpu_info).c_str(),
+ kOutputSeparator,
+ process_state.system_info()->cpu_count);
+ printf("GPU%c%s%c%s%c%s\n", kOutputSeparator,
+ StripSeparator(process_state.system_info()->gl_version).c_str(),
+ kOutputSeparator,
+ StripSeparator(process_state.system_info()->gl_vendor).c_str(),
+ kOutputSeparator,
+ StripSeparator(process_state.system_info()->gl_renderer).c_str());
+
+ int requesting_thread = process_state.requesting_thread();
+
+ // Print crash information.
+ // Crash|{Crash Reason}|{Crash Address}|{Crashed Thread}
+ printf("Crash%c", kOutputSeparator);
+ if (process_state.crashed()) {
+ printf("%s%c0x%" PRIx64 "%c",
+ StripSeparator(process_state.crash_reason()).c_str(),
+ kOutputSeparator, process_state.crash_address(), kOutputSeparator);
+ } else {
+ // print assertion info, if available, in place of crash reason,
+ // instead of the unhelpful "No crash"
+ string assertion = process_state.assertion();
+ if (!assertion.empty()) {
+ printf("%s%c%c", StripSeparator(assertion).c_str(),
+ kOutputSeparator, kOutputSeparator);
+ } else {
+ printf("No crash%c%c", kOutputSeparator, kOutputSeparator);
+ }
+ }
+
+ if (requesting_thread != -1) {
+ printf("%d\n", requesting_thread);
+ } else {
+ printf("\n");
+ }
+
+ const crash_info_record_t* crash_info_records =
+ process_state.mac_crash_info_records();
+ size_t num_records =
+ process_state.mac_crash_info_records_count();
+ for (size_t i = 0; i < num_records; ++i) {
+ char thread_str[32];
+ if (crash_info_records[i].thread) {
+ snprintf(thread_str, sizeof(thread_str), "0x%llx",
+ crash_info_records[i].thread);
+ } else {
+ strncpy(thread_str, "0", sizeof(thread_str));
+ }
+ char dialog_mode_str[32];
+ if (crash_info_records[i].dialog_mode) {
+ snprintf(dialog_mode_str, sizeof(dialog_mode_str), "0x%x",
+ crash_info_records[i].dialog_mode);
+ } else {
+ strncpy(dialog_mode_str, "0", sizeof(dialog_mode_str));
+ }
+ char abort_cause_str[32];
+ if (crash_info_records[i].abort_cause) {
+ snprintf(abort_cause_str, sizeof(abort_cause_str), "%lld",
+ crash_info_records[i].abort_cause);
+ } else {
+ strncpy(abort_cause_str, "0", sizeof(abort_cause_str));
+ }
+ printf("MacCrashInfo%c%s%c%lu%c%s%c%s%c%s%c%s%c%s%c%s%c%s\n",
+ kOutputSeparator, crash_info_records[i].module_path.c_str(),
+ kOutputSeparator, crash_info_records[i].version,
+ kOutputSeparator, crash_info_records[i].message.c_str(),
+ kOutputSeparator, crash_info_records[i].signature_string.c_str(),
+ kOutputSeparator, crash_info_records[i].backtrace.c_str(),
+ kOutputSeparator, crash_info_records[i].message2.c_str(),
+ kOutputSeparator, thread_str,
+ kOutputSeparator, dialog_mode_str,
+ kOutputSeparator, abort_cause_str);
+ }
+
+ PrintModulesMachineReadable(process_state.modules());
+ PrintUnloadedModulesMachineReadable(process_state.unloaded_modules());
+
+ // blank line to indicate start of threads
+ printf("\n");
+
+ // If the thread that requested the dump is known, print it first.
+ if (requesting_thread != -1) {
+ PrintStackMachineReadable(requesting_thread,
+ process_state.threads()->at(requesting_thread));
+ }
+
+ // Print all of the threads in the dump.
+ int thread_count = process_state.threads()->size();
+ for (int thread_index = 0; thread_index < thread_count; ++thread_index) {
+ if (thread_index != requesting_thread) {
+ // Don't print the crash thread again, it was already printed.
+ PrintStackMachineReadable(thread_index,
+ process_state.threads()->at(thread_index));
+ }
+ }
+}
+
+} // namespace google_breakpad
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/stackwalk_common.h b/toolkit/crashreporter/google-breakpad/src/processor/stackwalk_common.h
new file mode 100644
index 0000000000..a74f7b6da1
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/stackwalk_common.h
@@ -0,0 +1,49 @@
+// 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.
+
+// stackwalk_common.cc: Module shared by the {micro,mini}dump_stackwalck
+// executables to print the content of dumps (w/ stack traces) on the console.
+
+
+#ifndef PROCESSOR_STACKWALK_COMMON_H__
+#define PROCESSOR_STACKWALK_COMMON_H__
+
+namespace google_breakpad {
+
+class ProcessState;
+class SourceLineResolverInterface;
+
+void PrintProcessStateMachineReadable(const ProcessState& process_state);
+void PrintProcessState(const ProcessState& process_state,
+ bool output_stack_contents,
+ SourceLineResolverInterface* resolver);
+
+} // namespace google_breakpad
+
+#endif // PROCESSOR_STACKWALK_COMMON_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/stackwalker.cc b/toolkit/crashreporter/google-breakpad/src/processor/stackwalker.cc
new file mode 100644
index 0000000000..4988ef1eb8
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/stackwalker.cc
@@ -0,0 +1,333 @@
+// 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.
+
+// stackwalker.cc: Generic stackwalker.
+//
+// See stackwalker.h for documentation.
+//
+// Author: Mark Mentovai
+
+#include "google_breakpad/processor/stackwalker.h"
+
+#include <assert.h>
+
+#include "common/scoped_ptr.h"
+#include "google_breakpad/processor/call_stack.h"
+#include "google_breakpad/processor/code_module.h"
+#include "google_breakpad/processor/code_modules.h"
+#include "google_breakpad/processor/dump_context.h"
+#include "google_breakpad/processor/stack_frame.h"
+#include "google_breakpad/processor/stack_frame_symbolizer.h"
+#include "google_breakpad/processor/system_info.h"
+#include "processor/linked_ptr.h"
+#include "processor/logging.h"
+#include "processor/stackwalker_ppc.h"
+#include "processor/stackwalker_ppc64.h"
+#include "processor/stackwalker_sparc.h"
+#include "processor/stackwalker_x86.h"
+#include "processor/stackwalker_amd64.h"
+#include "processor/stackwalker_arm.h"
+#include "processor/stackwalker_arm64.h"
+#include "processor/stackwalker_mips.h"
+
+namespace google_breakpad {
+
+const int Stackwalker::kRASearchWords = 40;
+
+// This default is just a sanity check: a large enough value
+// that allow capturing unbounded recursion traces, yet provide a
+// guardrail against stack walking bugs. The stack walking invariants
+// guarantee that the unwinding process is strictly monotonic and
+// practically bounded by the size of the stack memory range.
+uint32_t Stackwalker::max_frames_ = 1 << 20; // 1M
+bool Stackwalker::max_frames_set_ = false;
+
+uint32_t Stackwalker::max_frames_scanned_ = 1 << 14; // 16k
+
+Stackwalker::Stackwalker(const SystemInfo* system_info,
+ MemoryRegion* memory,
+ const CodeModules* modules,
+ StackFrameSymbolizer* frame_symbolizer)
+ : system_info_(system_info),
+ memory_(memory),
+ modules_(modules),
+ unloaded_modules_(NULL),
+ frame_symbolizer_(frame_symbolizer) {
+ assert(frame_symbolizer_);
+}
+
+void InsertSpecialAttentionModule(
+ StackFrameSymbolizer::SymbolizerResult symbolizer_result,
+ const CodeModule* module,
+ vector<const CodeModule*>* modules) {
+ if (!module) {
+ return;
+ }
+ assert(symbolizer_result == StackFrameSymbolizer::kError ||
+ symbolizer_result == StackFrameSymbolizer::kWarningCorruptSymbols);
+ bool found = false;
+ vector<const CodeModule*>::iterator iter;
+ for (iter = modules->begin(); iter != modules->end(); ++iter) {
+ if (*iter == module) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ BPLOG(INFO) << ((symbolizer_result == StackFrameSymbolizer::kError) ?
+ "Couldn't load symbols for: " :
+ "Detected corrupt symbols for: ")
+ << module->debug_file() << "|" << module->debug_identifier();
+ modules->push_back(module);
+ }
+}
+
+bool Stackwalker::Walk(
+ CallStack* stack,
+ vector<const CodeModule*>* modules_without_symbols,
+ vector<const CodeModule*>* modules_with_corrupt_symbols) {
+ BPLOG_IF(ERROR, !stack) << "Stackwalker::Walk requires |stack|";
+ assert(stack);
+ stack->Clear();
+
+ BPLOG_IF(ERROR, !modules_without_symbols) << "Stackwalker::Walk requires "
+ << "|modules_without_symbols|";
+ BPLOG_IF(ERROR, !modules_without_symbols) << "Stackwalker::Walk requires "
+ << "|modules_with_corrupt_symbols|";
+ assert(modules_without_symbols);
+ assert(modules_with_corrupt_symbols);
+
+ // Begin with the context frame, and keep getting callers until there are
+ // no more.
+
+ // Keep track of the number of scanned or otherwise dubious frames seen
+ // so far, as the caller may have set a limit.
+ uint32_t scanned_frames = 0;
+
+ // Take ownership of the pointer returned by GetContextFrame.
+ scoped_ptr<StackFrame> frame(GetContextFrame());
+
+ while (frame.get()) {
+ // frame already contains a good frame with properly set instruction and
+ // frame_pointer fields. The frame structure comes from either the
+ // context frame (above) or a caller frame (below).
+
+ // Resolve the module information, if a module map was provided.
+ StackFrameSymbolizer::SymbolizerResult symbolizer_result =
+ frame_symbolizer_->FillSourceLineInfo(modules_, unloaded_modules_,
+ system_info_,
+ frame.get());
+ switch (symbolizer_result) {
+ case StackFrameSymbolizer::kInterrupt:
+ BPLOG(INFO) << "Stack walk is interrupted.";
+ return false;
+ break;
+ case StackFrameSymbolizer::kError:
+ InsertSpecialAttentionModule(symbolizer_result, frame->module,
+ modules_without_symbols);
+ break;
+ case StackFrameSymbolizer::kWarningCorruptSymbols:
+ InsertSpecialAttentionModule(symbolizer_result, frame->module,
+ modules_with_corrupt_symbols);
+ break;
+ case StackFrameSymbolizer::kNoError:
+ break;
+ default:
+ assert(false);
+ break;
+ }
+
+ // Keep track of the number of dubious frames so far.
+ switch (frame.get()->trust) {
+ case StackFrame::FRAME_TRUST_NONE:
+ case StackFrame::FRAME_TRUST_SCAN:
+ case StackFrame::FRAME_TRUST_CFI_SCAN:
+ scanned_frames++;
+ break;
+ default:
+ break;
+ }
+
+ // Add the frame to the call stack. Relinquish the ownership claim
+ // over the frame, because the stack now owns it.
+ stack->frames_.push_back(frame.release());
+ if (stack->frames_.size() > max_frames_) {
+ // Only emit an error message in the case where the limit
+ // reached is the default limit, not set by the user.
+ if (!max_frames_set_)
+ BPLOG(ERROR) << "The stack is over " << max_frames_ << " frames.";
+ break;
+ }
+
+ // Get the next frame and take ownership.
+ bool stack_scan_allowed = scanned_frames < max_frames_scanned_;
+ frame.reset(GetCallerFrame(stack, stack_scan_allowed));
+ }
+
+ return true;
+}
+
+// static
+Stackwalker* Stackwalker::StackwalkerForCPU(
+ const SystemInfo* system_info,
+ DumpContext* context,
+ MemoryRegion* memory,
+ const CodeModules* modules,
+ const CodeModules* unloaded_modules,
+ StackFrameSymbolizer* frame_symbolizer) {
+ if (!context) {
+ BPLOG(ERROR) << "Can't choose a stackwalker implementation without context";
+ return NULL;
+ }
+
+ Stackwalker* cpu_stackwalker = NULL;
+
+ uint32_t cpu = context->GetContextCPU();
+ switch (cpu) {
+ case MD_CONTEXT_X86:
+ cpu_stackwalker = new StackwalkerX86(system_info,
+ context->GetContextX86(),
+ memory, modules, frame_symbolizer);
+ break;
+
+ case MD_CONTEXT_PPC:
+ cpu_stackwalker = new StackwalkerPPC(system_info,
+ context->GetContextPPC(),
+ memory, modules, frame_symbolizer);
+ break;
+
+ case MD_CONTEXT_PPC64:
+ cpu_stackwalker = new StackwalkerPPC64(system_info,
+ context->GetContextPPC64(),
+ memory, modules, frame_symbolizer);
+ break;
+
+ case MD_CONTEXT_AMD64:
+ cpu_stackwalker = new StackwalkerAMD64(system_info,
+ context->GetContextAMD64(),
+ memory, modules, frame_symbolizer);
+ break;
+
+ case MD_CONTEXT_SPARC:
+ cpu_stackwalker = new StackwalkerSPARC(system_info,
+ context->GetContextSPARC(),
+ memory, modules, frame_symbolizer);
+ break;
+
+ case MD_CONTEXT_MIPS:
+ case MD_CONTEXT_MIPS64:
+ cpu_stackwalker = new StackwalkerMIPS(system_info,
+ context->GetContextMIPS(),
+ memory, modules, frame_symbolizer);
+ break;
+
+ case MD_CONTEXT_ARM:
+ {
+ int fp_register = -1;
+ if (system_info->os_short == "ios")
+ fp_register = MD_CONTEXT_ARM_REG_IOS_FP;
+ cpu_stackwalker = new StackwalkerARM(system_info,
+ context->GetContextARM(),
+ fp_register, memory, modules,
+ frame_symbolizer);
+ break;
+ }
+
+ case MD_CONTEXT_ARM64:
+ cpu_stackwalker = new StackwalkerARM64(system_info,
+ context->GetContextARM64(),
+ memory, modules,
+ frame_symbolizer);
+ break;
+ }
+
+ BPLOG_IF(ERROR, !cpu_stackwalker) << "Unknown CPU type " << HexString(cpu) <<
+ ", can't choose a stackwalker "
+ "implementation";
+ if (cpu_stackwalker) {
+ cpu_stackwalker->unloaded_modules_ = unloaded_modules;
+ }
+ return cpu_stackwalker;
+}
+
+// CONSIDER: check stack alignment?
+bool Stackwalker::TerminateWalk(uint64_t caller_ip,
+ uint64_t caller_sp,
+ uint64_t callee_sp,
+ bool first_unwind) const {
+ // Treat an instruction address less than 4k as end-of-stack.
+ // (using InstructionAddressSeemsValid() here is very tempting,
+ // but we need to handle JITted code)
+ if (caller_ip < (1 << 12)) {
+ return true;
+ }
+
+ // NOTE: The stack address range is implicitly checked
+ // when the stack memory is accessed.
+
+ // The stack pointer should monotonically increase. For first unwind
+ // we allow caller_sp == callee_sp to account for architectures where
+ // the return address is stored in a register (so it's possible to have
+ // leaf functions which don't move the stack pointer)
+ if (first_unwind ? (caller_sp < callee_sp) : (caller_sp <= callee_sp)) {
+ return true;
+ }
+
+ return false;
+}
+
+bool Stackwalker::InstructionAddressSeemsValid(uint64_t address) const {
+ StackFrame frame;
+ frame.instruction = address;
+ StackFrameSymbolizer::SymbolizerResult symbolizer_result =
+ frame_symbolizer_->FillSourceLineInfo(modules_, unloaded_modules_,
+ system_info_, &frame);
+
+ if (!frame.module) {
+ // not inside any loaded module
+ return false;
+ }
+
+ if (!frame_symbolizer_->HasImplementation()) {
+ // No valid implementation to symbolize stack frame, but the address is
+ // within a known module.
+ return true;
+ }
+
+ if (symbolizer_result != StackFrameSymbolizer::kNoError &&
+ symbolizer_result != StackFrameSymbolizer::kWarningCorruptSymbols) {
+ // Some error occurred during symbolization, but the address is within a
+ // known module
+ return true;
+ }
+
+ return !frame.function_name.empty();
+}
+
+} // namespace google_breakpad
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_address_list.cc b/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_address_list.cc
new file mode 100644
index 0000000000..e81fec282c
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_address_list.cc
@@ -0,0 +1,92 @@
+// 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.
+
+// stackwalker_address_list.cc: a pseudo stack walker.
+//
+// See stackwalker_address_list.h for documentation.
+//
+// Author: Chris Hamilton <chrisha@chromium.org>
+
+#include <assert.h>
+
+#include <vector>
+
+#include "google_breakpad/processor/call_stack.h"
+#include "google_breakpad/processor/memory_region.h"
+#include "google_breakpad/processor/source_line_resolver_interface.h"
+#include "google_breakpad/processor/stack_frame.h"
+#include "processor/logging.h"
+#include "processor/stackwalker_address_list.h"
+
+namespace google_breakpad {
+
+StackwalkerAddressList::StackwalkerAddressList(
+ const uint64_t* frames,
+ size_t frame_count,
+ const CodeModules* modules,
+ StackFrameSymbolizer* frame_symbolizer)
+ : Stackwalker(NULL, NULL, modules, frame_symbolizer),
+ frames_(frames),
+ frame_count_(frame_count) {
+ assert(frames);
+ assert(frame_symbolizer);
+}
+
+StackFrame* StackwalkerAddressList::GetContextFrame() {
+ if (frame_count_ == 0)
+ return NULL;
+
+ StackFrame* frame = new StackFrame();
+ frame->instruction = frames_[0];
+ frame->trust = StackFrame::FRAME_TRUST_PREWALKED;
+ return frame;
+}
+
+StackFrame* StackwalkerAddressList::GetCallerFrame(const CallStack* stack,
+ bool stack_scan_allowed) {
+ if (!stack) {
+ BPLOG(ERROR) << "Can't get caller frame without stack";
+ return NULL;
+ }
+
+ size_t frame_index = stack->frames()->size();
+
+ // There are no more frames to fetch.
+ if (frame_index >= frame_count_)
+ return NULL;
+
+ // All frames have the highest level of trust because they were
+ // explicitly provided.
+ StackFrame* frame = new StackFrame();
+ frame->instruction = frames_[frame_index];
+ frame->trust = StackFrame::FRAME_TRUST_PREWALKED;
+ return frame;
+}
+
+} // namespace google_breakpad
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_address_list.h b/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_address_list.h
new file mode 100644
index 0000000000..0f8c989efd
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_address_list.h
@@ -0,0 +1,72 @@
+// 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.
+
+// stackwalker_address_list.h: a pseudo stackwalker.
+//
+// Doesn't actually walk a stack, rather initializes a CallStack given an
+// explicit list of already walked return addresses.
+//
+// Author: Chris Hamilton <chrisha@chromium.org>
+
+#ifndef PROCESSOR_STACKWALKER_ADDRESS_LIST_H_
+#define PROCESSOR_STACKWALKER_ADDRESS_LIST_H_
+
+#include "common/basictypes.h"
+#include "google_breakpad/common/breakpad_types.h"
+#include "google_breakpad/processor/stackwalker.h"
+
+namespace google_breakpad {
+
+class CodeModules;
+
+class StackwalkerAddressList : public Stackwalker {
+ public:
+ // Initializes this stack walker with an explicit set of frame addresses.
+ // |modules| and |frame_symbolizer| are passed directly through to the base
+ // Stackwalker constructor.
+ StackwalkerAddressList(const uint64_t* frames,
+ size_t frame_count,
+ const CodeModules* modules,
+ StackFrameSymbolizer* frame_symbolizer);
+
+ private:
+ // Implementation of Stackwalker.
+ virtual StackFrame* GetContextFrame();
+ virtual StackFrame* GetCallerFrame(const CallStack* stack,
+ bool stack_scan_allowed);
+
+ const uint64_t* frames_;
+ size_t frame_count_;
+
+ DISALLOW_COPY_AND_ASSIGN(StackwalkerAddressList);
+};
+
+} // namespace google_breakpad
+
+#endif // PROCESSOR_STACKWALKER_ADDRESS_LIST_H_
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_address_list_unittest.cc b/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_address_list_unittest.cc
new file mode 100644
index 0000000000..ab4e9c0880
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_address_list_unittest.cc
@@ -0,0 +1,197 @@
+// 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.
+
+// stackwalker_address_list_unittest.cc: Unit tests for the
+// StackwalkerAddressList class.
+//
+// Author: Chris Hamilton <chrisha@chromium.org>
+
+#include <string>
+#include <vector>
+
+#include "breakpad_googletest_includes.h"
+#include "common/using_std_string.h"
+#include "google_breakpad/common/minidump_format.h"
+#include "google_breakpad/processor/basic_source_line_resolver.h"
+#include "google_breakpad/processor/call_stack.h"
+#include "google_breakpad/processor/code_module.h"
+#include "google_breakpad/processor/source_line_resolver_interface.h"
+#include "google_breakpad/processor/stack_frame.h"
+#include "processor/stackwalker_unittest_utils.h"
+#include "processor/stackwalker_address_list.h"
+
+using google_breakpad::BasicSourceLineResolver;
+using google_breakpad::CallStack;
+using google_breakpad::CodeModule;
+using google_breakpad::StackFrameSymbolizer;
+using google_breakpad::StackFrame;
+using google_breakpad::Stackwalker;
+using google_breakpad::StackwalkerAddressList;
+using std::vector;
+using testing::_;
+using testing::AnyNumber;
+using testing::Return;
+using testing::SetArgumentPointee;
+
+#define arraysize(f) (sizeof(f) / sizeof(*f))
+
+// Addresses and sizes of a couple dummy modules.
+uint64_t kModule1Base = 0x40000000;
+uint64_t kModule1Size = 0x10000;
+uint64_t kModule2Base = 0x50000000;
+uint64_t kModule2Size = 0x10000;
+
+// A handful of addresses that lie within the modules above.
+const uint64_t kDummyFrames[] = {
+ 0x50003000, 0x50002000, 0x50001000, 0x40002000, 0x40001000 };
+
+class StackwalkerAddressListTest : public testing::Test {
+ public:
+ StackwalkerAddressListTest()
+ : // Give the two modules reasonable standard locations and names
+ // for tests to play with.
+ module1(kModule1Base, kModule1Size, "module1", "version1"),
+ module2(kModule2Base, kModule2Size, "module2", "version2") {
+ // Create some modules with some stock debugging information.
+ modules.Add(&module1);
+ modules.Add(&module2);
+
+ // By default, none of the modules have symbol info; call
+ // SetModuleSymbols to override this.
+ EXPECT_CALL(supplier, GetCStringSymbolData(_, _, _, _, _))
+ .WillRepeatedly(Return(MockSymbolSupplier::NOT_FOUND));
+
+ // Avoid GMOCK WARNING "Uninteresting mock function call - returning
+ // directly" for FreeSymbolData().
+ EXPECT_CALL(supplier, FreeSymbolData(_)).Times(AnyNumber());
+ }
+
+ // Set the Breakpad symbol information that supplier should return for
+ // MODULE to INFO.
+ void SetModuleSymbols(MockCodeModule *module, const string &info) {
+ size_t buffer_size;
+ char *buffer = supplier.CopySymbolDataAndOwnTheCopy(info, &buffer_size);
+ EXPECT_CALL(supplier, GetCStringSymbolData(module, NULL, _, _, _))
+ .WillRepeatedly(DoAll(SetArgumentPointee<3>(buffer),
+ SetArgumentPointee<4>(buffer_size),
+ Return(MockSymbolSupplier::FOUND)));
+ }
+
+ void CheckCallStack(const CallStack& call_stack) {
+ const std::vector<StackFrame*>* frames = call_stack.frames();
+ ASSERT_EQ(arraysize(kDummyFrames), frames->size());
+ for (size_t i = 0; i < arraysize(kDummyFrames); ++i) {
+ ASSERT_EQ(kDummyFrames[i], frames->at(i)->instruction);
+ ASSERT_EQ(StackFrame::FRAME_TRUST_PREWALKED, frames->at(i)->trust);
+ }
+ ASSERT_EQ(static_cast<const CodeModule*>(&module2), frames->at(0)->module);
+ ASSERT_EQ(static_cast<const CodeModule*>(&module2), frames->at(1)->module);
+ ASSERT_EQ(static_cast<const CodeModule*>(&module2), frames->at(2)->module);
+ ASSERT_EQ(static_cast<const CodeModule*>(&module1), frames->at(3)->module);
+ ASSERT_EQ(static_cast<const CodeModule*>(&module1), frames->at(4)->module);
+ }
+
+ MockCodeModule module1;
+ MockCodeModule module2;
+ MockCodeModules modules;
+ MockSymbolSupplier supplier;
+ BasicSourceLineResolver resolver;
+};
+
+TEST_F(StackwalkerAddressListTest, ScanWithoutSymbols) {
+ StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
+ StackwalkerAddressList walker(kDummyFrames, arraysize(kDummyFrames),
+ &modules, &frame_symbolizer);
+
+ CallStack call_stack;
+ vector<const CodeModule*> modules_without_symbols;
+ vector<const CodeModule*> modules_with_corrupt_symbols;
+ ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
+ &modules_with_corrupt_symbols));
+
+ // The stack starts in module2, so we expect that to be the first module
+ // found without symbols.
+ ASSERT_EQ(2U, modules_without_symbols.size());
+ ASSERT_EQ("module2", modules_without_symbols[0]->debug_file());
+ ASSERT_EQ("module1", modules_without_symbols[1]->debug_file());
+ ASSERT_EQ(0u, modules_with_corrupt_symbols.size());
+
+ ASSERT_NO_FATAL_FAILURE(CheckCallStack(call_stack));
+}
+
+TEST_F(StackwalkerAddressListTest, ScanWithSymbols) {
+ // File : FILE number(dex) name
+ // Function: FUNC address(hex) size(hex) parameter_size(hex) name
+ // Line : address(hex) size(hex) line(dec) filenum(dec)
+ SetModuleSymbols(&module2,
+ "FILE 1 module2.cc\n"
+ "FUNC 3000 100 10 mod2func3\n"
+ "3000 10 1 1\n"
+ "FUNC 2000 200 10 mod2func2\n"
+ "FUNC 1000 300 10 mod2func1\n");
+ SetModuleSymbols(&module1,
+ "FUNC 2000 200 10 mod1func2\n"
+ "FUNC 1000 300 10 mod1func1\n");
+
+ StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
+ StackwalkerAddressList walker(kDummyFrames, arraysize(kDummyFrames),
+ &modules, &frame_symbolizer);
+
+ CallStack call_stack;
+ vector<const CodeModule*> modules_without_symbols;
+ vector<const CodeModule*> modules_with_corrupt_symbols;
+ ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
+ &modules_with_corrupt_symbols));
+
+ ASSERT_EQ(0u, modules_without_symbols.size());
+ ASSERT_EQ(0u, modules_with_corrupt_symbols.size());
+
+ ASSERT_NO_FATAL_FAILURE(CheckCallStack(call_stack));
+
+ const std::vector<StackFrame*>* frames = call_stack.frames();
+
+ // We have full file/line information for the first function call.
+ ASSERT_EQ("mod2func3", frames->at(0)->function_name);
+ ASSERT_EQ(0x50003000u, frames->at(0)->function_base);
+ ASSERT_EQ("module2.cc", frames->at(0)->source_file_name);
+ ASSERT_EQ(1, frames->at(0)->source_line);
+ ASSERT_EQ(0x50003000u, frames->at(0)->source_line_base);
+
+ ASSERT_EQ("mod2func2", frames->at(1)->function_name);
+ ASSERT_EQ(0x50002000u, frames->at(1)->function_base);
+
+ ASSERT_EQ("mod2func1", frames->at(2)->function_name);
+ ASSERT_EQ(0x50001000u, frames->at(2)->function_base);
+
+ ASSERT_EQ("mod1func2", frames->at(3)->function_name);
+ ASSERT_EQ(0x40002000u, frames->at(3)->function_base);
+
+ ASSERT_EQ("mod1func1", frames->at(4)->function_name);
+ ASSERT_EQ(0x40001000u, frames->at(4)->function_base);
+}
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_amd64.cc b/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_amd64.cc
new file mode 100644
index 0000000000..d5ac6c652e
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_amd64.cc
@@ -0,0 +1,326 @@
+// 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.
+
+// stackwalker_amd64.cc: amd64-specific stackwalker.
+//
+// See stackwalker_amd64.h for documentation.
+//
+// Author: Mark Mentovai, Ted Mielczarek
+
+#include <assert.h>
+
+#include "common/scoped_ptr.h"
+#include "google_breakpad/processor/call_stack.h"
+#include "google_breakpad/processor/memory_region.h"
+#include "google_breakpad/processor/source_line_resolver_interface.h"
+#include "google_breakpad/processor/stack_frame_cpu.h"
+#include "google_breakpad/processor/system_info.h"
+#include "processor/cfi_frame_info.h"
+#include "processor/logging.h"
+#include "processor/stackwalker_amd64.h"
+
+namespace google_breakpad {
+
+
+const StackwalkerAMD64::CFIWalker::RegisterSet
+StackwalkerAMD64::cfi_register_map_[] = {
+ // It may seem like $rip and $rsp are callee-saves, because the callee is
+ // responsible for having them restored upon return. But the callee_saves
+ // flags here really means that the walker should assume they're
+ // unchanged if the CFI doesn't mention them --- clearly wrong for $rip
+ // and $rsp.
+ { "$rax", NULL, false,
+ StackFrameAMD64::CONTEXT_VALID_RAX, &MDRawContextAMD64::rax },
+ { "$rdx", NULL, false,
+ StackFrameAMD64::CONTEXT_VALID_RDX, &MDRawContextAMD64::rdx },
+ { "$rcx", NULL, false,
+ StackFrameAMD64::CONTEXT_VALID_RCX, &MDRawContextAMD64::rcx },
+ { "$rbx", NULL, true,
+ StackFrameAMD64::CONTEXT_VALID_RBX, &MDRawContextAMD64::rbx },
+ { "$rsi", NULL, false,
+ StackFrameAMD64::CONTEXT_VALID_RSI, &MDRawContextAMD64::rsi },
+ { "$rdi", NULL, false,
+ StackFrameAMD64::CONTEXT_VALID_RDI, &MDRawContextAMD64::rdi },
+ { "$rbp", NULL, true,
+ StackFrameAMD64::CONTEXT_VALID_RBP, &MDRawContextAMD64::rbp },
+ { "$rsp", ".cfa", false,
+ StackFrameAMD64::CONTEXT_VALID_RSP, &MDRawContextAMD64::rsp },
+ { "$r8", NULL, false,
+ StackFrameAMD64::CONTEXT_VALID_R8, &MDRawContextAMD64::r8 },
+ { "$r9", NULL, false,
+ StackFrameAMD64::CONTEXT_VALID_R9, &MDRawContextAMD64::r9 },
+ { "$r10", NULL, false,
+ StackFrameAMD64::CONTEXT_VALID_R10, &MDRawContextAMD64::r10 },
+ { "$r11", NULL, false,
+ StackFrameAMD64::CONTEXT_VALID_R11, &MDRawContextAMD64::r11 },
+ { "$r12", NULL, true,
+ StackFrameAMD64::CONTEXT_VALID_R12, &MDRawContextAMD64::r12 },
+ { "$r13", NULL, true,
+ StackFrameAMD64::CONTEXT_VALID_R13, &MDRawContextAMD64::r13 },
+ { "$r14", NULL, true,
+ StackFrameAMD64::CONTEXT_VALID_R14, &MDRawContextAMD64::r14 },
+ { "$r15", NULL, true,
+ StackFrameAMD64::CONTEXT_VALID_R15, &MDRawContextAMD64::r15 },
+ { "$rip", ".ra", false,
+ StackFrameAMD64::CONTEXT_VALID_RIP, &MDRawContextAMD64::rip },
+};
+
+StackwalkerAMD64::StackwalkerAMD64(const SystemInfo* system_info,
+ const MDRawContextAMD64* context,
+ MemoryRegion* memory,
+ const CodeModules* modules,
+ StackFrameSymbolizer* resolver_helper)
+ : Stackwalker(system_info, memory, modules, resolver_helper),
+ context_(context),
+ cfi_walker_(cfi_register_map_,
+ (sizeof(cfi_register_map_) / sizeof(cfi_register_map_[0]))) {
+}
+
+uint64_t StackFrameAMD64::ReturnAddress() const {
+ assert(context_validity & StackFrameAMD64::CONTEXT_VALID_RIP);
+ return context.rip;
+}
+
+StackFrame* StackwalkerAMD64::GetContextFrame() {
+ if (!context_) {
+ BPLOG(ERROR) << "Can't get context frame without context";
+ return NULL;
+ }
+
+ StackFrameAMD64* frame = new StackFrameAMD64();
+
+ // The instruction pointer is stored directly in a register, so pull it
+ // straight out of the CPU context structure.
+ frame->context = *context_;
+ frame->context_validity = StackFrameAMD64::CONTEXT_VALID_ALL;
+ frame->trust = StackFrame::FRAME_TRUST_CONTEXT;
+ frame->instruction = frame->context.rip;
+
+ return frame;
+}
+
+StackFrameAMD64* StackwalkerAMD64::GetCallerByCFIFrameInfo(
+ const vector<StackFrame*> &frames,
+ CFIFrameInfo* cfi_frame_info) {
+ StackFrameAMD64* last_frame = static_cast<StackFrameAMD64*>(frames.back());
+
+ scoped_ptr<StackFrameAMD64> frame(new StackFrameAMD64());
+ if (!cfi_walker_
+ .FindCallerRegisters(*memory_, *cfi_frame_info,
+ last_frame->context, last_frame->context_validity,
+ &frame->context, &frame->context_validity))
+ return NULL;
+
+ // Make sure we recovered all the essentials.
+ static const int essentials = (StackFrameAMD64::CONTEXT_VALID_RIP
+ | StackFrameAMD64::CONTEXT_VALID_RSP);
+ if ((frame->context_validity & essentials) != essentials)
+ return NULL;
+
+ frame->trust = StackFrame::FRAME_TRUST_CFI;
+ return frame.release();
+}
+
+// Returns true if `ptr` is not in x86-64 canonical form.
+// https://en.wikipedia.org/wiki/X86-64#Virtual_address_space_details
+static bool is_non_canonical(uint64_t ptr) {
+ return ptr > 0x7FFFFFFFFFFF && ptr < 0xFFFF800000000000;
+}
+
+StackFrameAMD64* StackwalkerAMD64::GetCallerByFramePointerRecovery(
+ const vector<StackFrame*>& frames) {
+ StackFrameAMD64* last_frame = static_cast<StackFrameAMD64*>(frames.back());
+ uint64_t last_rbp = last_frame->context.rbp;
+
+ // Assume the presence of a frame pointer. This is not mandated by the
+ // AMD64 ABI, c.f. section 3.2.2 footnote 7, though it is typical for
+ // compilers to still preserve the frame pointer and not treat %rbp as a
+ // general purpose register.
+ //
+ // With this assumption, the CALL instruction pushes the return address
+ // onto the stack and sets %rip to the procedure to enter. The procedure
+ // then establishes the stack frame with a prologue that PUSHes the current
+ // %rbp onto the stack, MOVes the current %rsp to %rbp, and then allocates
+ // space for any local variables. Using this procedure linking information,
+ // it is possible to locate frame information for the callee:
+ //
+ // %caller_rsp = *(%callee_rbp + 16)
+ // %caller_rip = *(%callee_rbp + 8)
+ // %caller_rbp = *(%callee_rbp)
+
+ // If rbp is not 8-byte aligned it can't be a frame pointer.
+ if (last_rbp % 8 != 0) {
+ return NULL;
+ }
+
+ uint64_t caller_rip, caller_rbp;
+ if (memory_->GetMemoryAtAddress(last_rbp + 8, &caller_rip) &&
+ memory_->GetMemoryAtAddress(last_rbp, &caller_rbp)) {
+ uint64_t caller_rsp = last_rbp + 16;
+
+ // If the recovered rip is not a canonical address it can't be
+ // the return address, so rbp must not have been a frame pointer.
+ if (is_non_canonical(caller_rip)) {
+ return NULL;
+ }
+
+ // Check that rbp is within the right frame
+ if (caller_rsp <= last_rbp || caller_rbp < caller_rsp) {
+ return NULL;
+ }
+
+ // Sanity check that resulting rbp is still inside stack memory.
+ uint64_t unused;
+ if (!memory_->GetMemoryAtAddress(caller_rbp, &unused)) {
+ return NULL;
+ }
+
+ StackFrameAMD64* frame = new StackFrameAMD64();
+ frame->trust = StackFrame::FRAME_TRUST_FP;
+ frame->context = last_frame->context;
+ frame->context.rip = caller_rip;
+ frame->context.rsp = caller_rsp;
+ frame->context.rbp = caller_rbp;
+ frame->context_validity = StackFrameAMD64::CONTEXT_VALID_RIP |
+ StackFrameAMD64::CONTEXT_VALID_RSP |
+ StackFrameAMD64::CONTEXT_VALID_RBP;
+ return frame;
+ }
+
+ return NULL;
+}
+
+StackFrameAMD64* StackwalkerAMD64::GetCallerByStackScan(
+ const vector<StackFrame*> &frames) {
+ StackFrameAMD64* last_frame = static_cast<StackFrameAMD64*>(frames.back());
+ uint64_t last_rsp = last_frame->context.rsp;
+ uint64_t caller_rip_address, caller_rip;
+
+ if (!ScanForReturnAddress(last_rsp, &caller_rip_address, &caller_rip,
+ frames.size() == 1 /* is_context_frame */)) {
+ // No plausible return address was found.
+ return NULL;
+ }
+
+ // Create a new stack frame (ownership will be transferred to the caller)
+ // and fill it in.
+ StackFrameAMD64* frame = new StackFrameAMD64();
+
+ frame->trust = StackFrame::FRAME_TRUST_SCAN;
+ frame->context = last_frame->context;
+ frame->context.rip = caller_rip;
+ // The caller's %rsp is directly underneath the return address pushed by
+ // the call.
+ frame->context.rsp = caller_rip_address + 8;
+ frame->context_validity = StackFrameAMD64::CONTEXT_VALID_RIP |
+ StackFrameAMD64::CONTEXT_VALID_RSP;
+
+ // Other unwinders give up if they don't have an %rbp value, so see if we
+ // can pass some plausible value on.
+ if (last_frame->context_validity & StackFrameAMD64::CONTEXT_VALID_RBP) {
+ // Functions typically push their caller's %rbp immediately upon entry,
+ // and then set %rbp to point to that. So if the callee's %rbp is
+ // pointing to the first word below the alleged return address, presume
+ // that the caller's %rbp is saved there.
+ if (caller_rip_address - 8 == last_frame->context.rbp) {
+ uint64_t caller_rbp = 0;
+ if (memory_->GetMemoryAtAddress(last_frame->context.rbp, &caller_rbp) &&
+ caller_rbp > caller_rip_address) {
+ frame->context.rbp = caller_rbp;
+ frame->context_validity |= StackFrameAMD64::CONTEXT_VALID_RBP;
+ }
+ } else if (last_frame->context.rbp >= caller_rip_address + 8) {
+ // If the callee's %rbp is plausible as a value for the caller's
+ // %rbp, presume that the callee left it unchanged.
+ frame->context.rbp = last_frame->context.rbp;
+ frame->context_validity |= StackFrameAMD64::CONTEXT_VALID_RBP;
+ }
+ }
+
+ return frame;
+}
+
+StackFrame* StackwalkerAMD64::GetCallerFrame(const CallStack* stack,
+ bool stack_scan_allowed) {
+ if (!memory_ || !stack) {
+ BPLOG(ERROR) << "Can't get caller frame without memory or stack";
+ return NULL;
+ }
+
+ const vector<StackFrame*> &frames = *stack->frames();
+ StackFrameAMD64* last_frame = static_cast<StackFrameAMD64*>(frames.back());
+ scoped_ptr<StackFrameAMD64> new_frame;
+
+ // If we have DWARF CFI information, use it.
+ scoped_ptr<CFIFrameInfo> cfi_frame_info(
+ frame_symbolizer_->FindCFIFrameInfo(last_frame));
+ if (cfi_frame_info.get())
+ new_frame.reset(GetCallerByCFIFrameInfo(frames, cfi_frame_info.get()));
+
+ // If CFI was not available or failed, try using frame pointer recovery.
+ if (!new_frame.get()) {
+ new_frame.reset(GetCallerByFramePointerRecovery(frames));
+ }
+
+ // If all else fails, fall back to stack scanning.
+ if (stack_scan_allowed && !new_frame.get()) {
+ new_frame.reset(GetCallerByStackScan(frames));
+ }
+
+ // If nothing worked, tell the caller.
+ if (!new_frame.get())
+ return NULL;
+
+ if (system_info_->os_short == "nacl") {
+ // Apply constraints from Native Client's x86-64 sandbox. These
+ // registers have the 4GB-aligned sandbox base address (from r15)
+ // added to them, and only the bottom 32 bits are relevant for
+ // stack walking.
+ new_frame->context.rip = static_cast<uint32_t>(new_frame->context.rip);
+ new_frame->context.rsp = static_cast<uint32_t>(new_frame->context.rsp);
+ new_frame->context.rbp = static_cast<uint32_t>(new_frame->context.rbp);
+ }
+
+ // Should we terminate the stack walk? (end-of-stack or broken invariant)
+ if (TerminateWalk(new_frame->context.rip, new_frame->context.rsp,
+ last_frame->context.rsp, frames.size() == 1)) {
+ return NULL;
+ }
+
+ // new_frame->context.rip is the return address, which is the instruction
+ // after the CALL that caused us to arrive at the callee. Set
+ // new_frame->instruction to one less than that, so it points within the
+ // CALL instruction. See StackFrame::instruction for details, and
+ // StackFrameAMD64::ReturnAddress.
+ new_frame->instruction = new_frame->context.rip - 1;
+
+ return new_frame.release();
+}
+
+} // namespace google_breakpad
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_amd64.h b/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_amd64.h
new file mode 100644
index 0000000000..8f3dbd5280
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_amd64.h
@@ -0,0 +1,108 @@
+// 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.
+
+// stackwalker_amd64.h: amd64-specific stackwalker.
+//
+// Provides stack frames given amd64 register context and a memory region
+// corresponding to a amd64 stack.
+//
+// Author: Mark Mentovai, Ted Mielczarek
+
+
+#ifndef PROCESSOR_STACKWALKER_AMD64_H__
+#define PROCESSOR_STACKWALKER_AMD64_H__
+
+#include <vector>
+
+#include "google_breakpad/common/breakpad_types.h"
+#include "google_breakpad/common/minidump_format.h"
+#include "google_breakpad/processor/stackwalker.h"
+#include "google_breakpad/processor/stack_frame_cpu.h"
+#include "processor/cfi_frame_info.h"
+
+namespace google_breakpad {
+
+class CodeModules;
+
+class StackwalkerAMD64 : public Stackwalker {
+ public:
+ // context is a amd64 context object that gives access to amd64-specific
+ // register state corresponding to the innermost called frame to be
+ // included in the stack. The other arguments are passed directly through
+ // to the base Stackwalker constructor.
+ StackwalkerAMD64(const SystemInfo* system_info,
+ const MDRawContextAMD64* context,
+ MemoryRegion* memory,
+ const CodeModules* modules,
+ StackFrameSymbolizer* frame_symbolizer);
+
+ private:
+ // A STACK CFI-driven frame walker for the AMD64
+ typedef SimpleCFIWalker<uint64_t, MDRawContextAMD64> CFIWalker;
+
+ // Implementation of Stackwalker, using amd64 context (stack pointer in %rsp,
+ // stack base in %rbp) and stack conventions (saved stack pointer at 0(%rbp))
+ virtual StackFrame* GetContextFrame();
+ virtual StackFrame* GetCallerFrame(const CallStack* stack,
+ bool stack_scan_allowed);
+
+ // Use cfi_frame_info (derived from STACK CFI records) to construct
+ // the frame that called frames.back(). The caller takes ownership
+ // of the returned frame. Return NULL on failure.
+ StackFrameAMD64* GetCallerByCFIFrameInfo(const vector<StackFrame*> &frames,
+ CFIFrameInfo* cfi_frame_info);
+
+ // Assumes a traditional frame layout where the frame pointer has not been
+ // omitted. The expectation is that caller's %rbp is pushed to the stack
+ // after the return address of the callee, and that the callee's %rsp can
+ // be used to find the pushed %rbp.
+ // Caller owns the returned frame object. Returns NULL on failure.
+ StackFrameAMD64* GetCallerByFramePointerRecovery(
+ const vector<StackFrame*>& frames);
+
+ // Scan the stack for plausible return addresses. The caller takes ownership
+ // of the returned frame. Return NULL on failure.
+ StackFrameAMD64* GetCallerByStackScan(const vector<StackFrame*> &frames);
+
+ // Stores the CPU context corresponding to the innermost stack frame to
+ // be returned by GetContextFrame.
+ const MDRawContextAMD64* context_;
+
+ // Our register map, for cfi_walker_.
+ static const CFIWalker::RegisterSet cfi_register_map_[];
+
+ // Our CFI frame walker.
+ const CFIWalker cfi_walker_;
+};
+
+
+} // namespace google_breakpad
+
+
+#endif // PROCESSOR_STACKWALKER_AMD64_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_amd64_unittest.cc b/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_amd64_unittest.cc
new file mode 100644
index 0000000000..efcd812a35
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_amd64_unittest.cc
@@ -0,0 +1,934 @@
+// 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>
+
+// stackwalker_amd64_unittest.cc: Unit tests for StackwalkerAMD64 class.
+
+#include <string.h>
+#include <string>
+#include <vector>
+
+#include "breakpad_googletest_includes.h"
+#include "common/test_assembler.h"
+#include "common/using_std_string.h"
+#include "google_breakpad/common/minidump_format.h"
+#include "google_breakpad/processor/basic_source_line_resolver.h"
+#include "google_breakpad/processor/call_stack.h"
+#include "google_breakpad/processor/code_module.h"
+#include "google_breakpad/processor/source_line_resolver_interface.h"
+#include "google_breakpad/processor/stack_frame_cpu.h"
+#include "processor/stackwalker_unittest_utils.h"
+#include "processor/stackwalker_amd64.h"
+
+using google_breakpad::BasicSourceLineResolver;
+using google_breakpad::CallStack;
+using google_breakpad::CodeModule;
+using google_breakpad::StackFrameSymbolizer;
+using google_breakpad::StackFrame;
+using google_breakpad::StackFrameAMD64;
+using google_breakpad::Stackwalker;
+using google_breakpad::StackwalkerAMD64;
+using google_breakpad::SystemInfo;
+using google_breakpad::test_assembler::kLittleEndian;
+using google_breakpad::test_assembler::Label;
+using google_breakpad::test_assembler::Section;
+using std::vector;
+using testing::_;
+using testing::AnyNumber;
+using testing::DoAll;
+using testing::Return;
+using testing::SetArgumentPointee;
+using testing::Test;
+
+class StackwalkerAMD64Fixture {
+ public:
+ StackwalkerAMD64Fixture()
+ : stack_section(kLittleEndian),
+ // Give the two modules reasonable standard locations and names
+ // for tests to play with.
+ module1(0x00007400c0000000ULL, 0x10000, "module1", "version1"),
+ module2(0x00007500b0000000ULL, 0x10000, "module2", "version2") {
+ // Identify the system as a Linux system.
+ system_info.os = "Linux";
+ system_info.os_short = "linux";
+ system_info.os_version = "Horrendous Hippo";
+ system_info.cpu = "x86";
+ system_info.cpu_info = "";
+
+ // Put distinctive values in the raw CPU context.
+ BrandContext(&raw_context);
+
+ // Create some modules with some stock debugging information.
+ modules.Add(&module1);
+ modules.Add(&module2);
+
+ // By default, none of the modules have symbol info; call
+ // SetModuleSymbols to override this.
+ EXPECT_CALL(supplier, GetCStringSymbolData(_, _, _, _, _))
+ .WillRepeatedly(Return(MockSymbolSupplier::NOT_FOUND));
+
+ // Avoid GMOCK WARNING "Uninteresting mock function call - returning
+ // directly" for FreeSymbolData().
+ EXPECT_CALL(supplier, FreeSymbolData(_)).Times(AnyNumber());
+
+ // Reset max_frames_scanned since it's static.
+ Stackwalker::set_max_frames_scanned(1024);
+ }
+
+ // Set the Breakpad symbol information that supplier should return for
+ // MODULE to INFO.
+ void SetModuleSymbols(MockCodeModule *module, const string &info) {
+ size_t buffer_size;
+ char *buffer = supplier.CopySymbolDataAndOwnTheCopy(info, &buffer_size);
+ EXPECT_CALL(supplier, GetCStringSymbolData(module, &system_info, _, _, _))
+ .WillRepeatedly(DoAll(SetArgumentPointee<3>(buffer),
+ SetArgumentPointee<4>(buffer_size),
+ Return(MockSymbolSupplier::FOUND)));
+ }
+
+ // Populate stack_region with the contents of stack_section. Use
+ // stack_section.start() as the region's starting address.
+ void RegionFromSection() {
+ string contents;
+ ASSERT_TRUE(stack_section.GetContents(&contents));
+ stack_region.Init(stack_section.start().Value(), contents);
+ }
+
+ // Fill RAW_CONTEXT with pseudo-random data, for round-trip checking.
+ void BrandContext(MDRawContextAMD64 *raw_context) {
+ uint8_t x = 173;
+ for (size_t i = 0; i < sizeof(*raw_context); i++)
+ reinterpret_cast<uint8_t *>(raw_context)[i] = (x += 17);
+ }
+
+ SystemInfo system_info;
+ MDRawContextAMD64 raw_context;
+ Section stack_section;
+ MockMemoryRegion stack_region;
+ MockCodeModule module1;
+ MockCodeModule module2;
+ MockCodeModules modules;
+ MockSymbolSupplier supplier;
+ BasicSourceLineResolver resolver;
+ CallStack call_stack;
+ const vector<StackFrame *> *frames;
+};
+
+class GetContextFrame: public StackwalkerAMD64Fixture, public Test { };
+
+class SanityCheck: public StackwalkerAMD64Fixture, public Test { };
+
+TEST_F(SanityCheck, NoResolver) {
+ // There should be no references to the stack in this walk: we don't
+ // provide any call frame information, so trying to reconstruct the
+ // context frame's caller should fail. So there's no need for us to
+ // provide stack contents.
+ raw_context.rip = 0x00007400c0000200ULL;
+ raw_context.rbp = 0x8000000080000000ULL;
+
+ StackFrameSymbolizer frame_symbolizer(NULL, NULL);
+ StackwalkerAMD64 walker(&system_info, &raw_context, &stack_region, &modules,
+ &frame_symbolizer);
+ // This should succeed even without a resolver or supplier.
+ vector<const CodeModule*> modules_without_symbols;
+ vector<const CodeModule*> modules_with_corrupt_symbols;
+ ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
+ &modules_with_corrupt_symbols));
+ ASSERT_EQ(1U, modules_without_symbols.size());
+ ASSERT_EQ("module1", modules_without_symbols[0]->debug_file());
+ ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
+ frames = call_stack.frames();
+ ASSERT_GE(1U, frames->size());
+ StackFrameAMD64 *frame = static_cast<StackFrameAMD64 *>(frames->at(0));
+ // Check that the values from the original raw context made it
+ // through to the context in the stack frame.
+ EXPECT_EQ(0, memcmp(&raw_context, &frame->context, sizeof(raw_context)));
+}
+
+TEST_F(GetContextFrame, Simple) {
+ // There should be no references to the stack in this walk: we don't
+ // provide any call frame information, so trying to reconstruct the
+ // context frame's caller should fail. So there's no need for us to
+ // provide stack contents.
+ raw_context.rip = 0x00007400c0000200ULL;
+ raw_context.rbp = 0x8000000080000000ULL;
+
+ StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
+ StackwalkerAMD64 walker(&system_info, &raw_context, &stack_region, &modules,
+ &frame_symbolizer);
+ vector<const CodeModule*> modules_without_symbols;
+ vector<const CodeModule*> modules_with_corrupt_symbols;
+ ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
+ &modules_with_corrupt_symbols));
+ ASSERT_EQ(1U, modules_without_symbols.size());
+ ASSERT_EQ("module1", modules_without_symbols[0]->debug_file());
+ ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
+ frames = call_stack.frames();
+ ASSERT_GE(1U, frames->size());
+ StackFrameAMD64 *frame = static_cast<StackFrameAMD64 *>(frames->at(0));
+ // Check that the values from the original raw context made it
+ // through to the context in the stack frame.
+ EXPECT_EQ(0, memcmp(&raw_context, &frame->context, sizeof(raw_context)));
+}
+
+// The stackwalker should be able to produce the context frame even
+// without stack memory present.
+TEST_F(GetContextFrame, NoStackMemory) {
+ raw_context.rip = 0x00007400c0000200ULL;
+ raw_context.rbp = 0x8000000080000000ULL;
+
+ StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
+ StackwalkerAMD64 walker(&system_info, &raw_context, NULL, &modules,
+ &frame_symbolizer);
+ vector<const CodeModule*> modules_without_symbols;
+ vector<const CodeModule*> modules_with_corrupt_symbols;
+ ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
+ &modules_with_corrupt_symbols));
+ ASSERT_EQ(1U, modules_without_symbols.size());
+ ASSERT_EQ("module1", modules_without_symbols[0]->debug_file());
+ ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
+ frames = call_stack.frames();
+ ASSERT_GE(1U, frames->size());
+ StackFrameAMD64 *frame = static_cast<StackFrameAMD64 *>(frames->at(0));
+ // Check that the values from the original raw context made it
+ // through to the context in the stack frame.
+ EXPECT_EQ(0, memcmp(&raw_context, &frame->context, sizeof(raw_context)));
+}
+
+class GetCallerFrame: public StackwalkerAMD64Fixture, public Test { };
+
+TEST_F(GetCallerFrame, ScanWithoutSymbols) {
+ // When the stack walker resorts to scanning the stack,
+ // only addresses located within loaded modules are
+ // considered valid return addresses.
+ // Force scanning through three frames to ensure that the
+ // stack pointer is set properly in scan-recovered frames.
+ stack_section.start() = 0x8000000080000000ULL;
+ uint64_t return_address1 = 0x00007500b0000100ULL;
+ uint64_t return_address2 = 0x00007500b0000900ULL;
+ Label frame1_sp, frame2_sp, frame1_rbp;
+ stack_section
+ // frame 0
+ .Append(16, 0) // space
+
+ .D64(0x00007400b0000000ULL) // junk that's not
+ .D64(0x00007500d0000000ULL) // a return address
+
+ .D64(return_address1) // actual return address
+ // frame 1
+ .Mark(&frame1_sp)
+ .Append(16, 0) // space
+
+ .D64(0x00007400b0000000ULL) // more junk
+ .D64(0x00007500d0000000ULL)
+
+ .Mark(&frame1_rbp)
+ .D64(stack_section.start()) // This is in the right place to be
+ // a saved rbp, but it's bogus, so
+ // we shouldn't report it.
+
+ .D64(return_address2) // actual return address
+ // frame 2
+ .Mark(&frame2_sp)
+ .Append(32, 0); // end of stack
+
+ RegionFromSection();
+
+ raw_context.rip = 0x00007400c0000200ULL;
+ raw_context.rbp = frame1_rbp.Value();
+ raw_context.rsp = stack_section.start().Value();
+
+ StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
+ StackwalkerAMD64 walker(&system_info, &raw_context, &stack_region, &modules,
+ &frame_symbolizer);
+ vector<const CodeModule*> modules_without_symbols;
+ vector<const CodeModule*> modules_with_corrupt_symbols;
+ ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
+ &modules_with_corrupt_symbols));
+ ASSERT_EQ(2U, modules_without_symbols.size());
+ ASSERT_EQ("module1", modules_without_symbols[0]->debug_file());
+ ASSERT_EQ("module2", modules_without_symbols[1]->debug_file());
+ ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
+ frames = call_stack.frames();
+ ASSERT_EQ(3U, frames->size());
+
+ StackFrameAMD64 *frame0 = static_cast<StackFrameAMD64 *>(frames->at(0));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
+ ASSERT_EQ(StackFrameAMD64::CONTEXT_VALID_ALL, frame0->context_validity);
+ EXPECT_EQ(0, memcmp(&raw_context, &frame0->context, sizeof(raw_context)));
+
+ StackFrameAMD64 *frame1 = static_cast<StackFrameAMD64 *>(frames->at(1));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust);
+ ASSERT_EQ((StackFrameAMD64::CONTEXT_VALID_RIP |
+ StackFrameAMD64::CONTEXT_VALID_RSP |
+ StackFrameAMD64::CONTEXT_VALID_RBP),
+ frame1->context_validity);
+ EXPECT_EQ(return_address1, frame1->context.rip);
+ EXPECT_EQ(frame1_sp.Value(), frame1->context.rsp);
+ EXPECT_EQ(frame1_rbp.Value(), frame1->context.rbp);
+
+ StackFrameAMD64 *frame2 = static_cast<StackFrameAMD64 *>(frames->at(2));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame2->trust);
+ ASSERT_EQ((StackFrameAMD64::CONTEXT_VALID_RIP |
+ StackFrameAMD64::CONTEXT_VALID_RSP),
+ frame2->context_validity);
+ EXPECT_EQ(return_address2, frame2->context.rip);
+ EXPECT_EQ(frame2_sp.Value(), frame2->context.rsp);
+}
+
+TEST_F(GetCallerFrame, ScanWithFunctionSymbols) {
+ // During stack scanning, if a potential return address
+ // is located within a loaded module that has symbols,
+ // it is only considered a valid return address if it
+ // lies within a function's bounds.
+ stack_section.start() = 0x8000000080000000ULL;
+ uint64_t return_address = 0x00007500b0000110ULL;
+ Label frame1_sp, frame1_rbp;
+
+ stack_section
+ // frame 0
+ .Append(16, 0) // space
+
+ .D64(0x00007400b0000000ULL) // junk that's not
+ .D64(0x00007500b0000000ULL) // a return address
+
+ .D64(0x00007400c0001000ULL) // a couple of plausible addresses
+ .D64(0x00007500b000aaaaULL) // that are not within functions
+
+ .D64(return_address) // actual return address
+ // frame 1
+ .Mark(&frame1_sp)
+ .Append(32, 0) // end of stack
+ .Mark(&frame1_rbp);
+ RegionFromSection();
+
+ raw_context.rip = 0x00007400c0000200ULL;
+ raw_context.rbp = frame1_rbp.Value();
+ raw_context.rsp = stack_section.start().Value();
+
+ SetModuleSymbols(&module1,
+ // The youngest frame's function.
+ "FUNC 100 400 10 platypus\n");
+ SetModuleSymbols(&module2,
+ // The calling frame's function.
+ "FUNC 100 400 10 echidna\n");
+
+ StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
+ StackwalkerAMD64 walker(&system_info, &raw_context, &stack_region, &modules,
+ &frame_symbolizer);
+ vector<const CodeModule*> modules_without_symbols;
+ vector<const CodeModule*> modules_with_corrupt_symbols;
+ ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
+ &modules_with_corrupt_symbols));
+ ASSERT_EQ(0U, modules_without_symbols.size());
+ ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
+ frames = call_stack.frames();
+ ASSERT_EQ(2U, frames->size());
+
+ StackFrameAMD64 *frame0 = static_cast<StackFrameAMD64 *>(frames->at(0));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
+ ASSERT_EQ(StackFrameAMD64::CONTEXT_VALID_ALL, frame0->context_validity);
+ EXPECT_EQ("platypus", frame0->function_name);
+ EXPECT_EQ(0x00007400c0000100ULL, frame0->function_base);
+
+ StackFrameAMD64 *frame1 = static_cast<StackFrameAMD64 *>(frames->at(1));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust);
+ ASSERT_EQ((StackFrameAMD64::CONTEXT_VALID_RIP |
+ StackFrameAMD64::CONTEXT_VALID_RSP |
+ StackFrameAMD64::CONTEXT_VALID_RBP),
+ frame1->context_validity);
+ EXPECT_EQ(return_address, frame1->context.rip);
+ EXPECT_EQ(frame1_sp.Value(), frame1->context.rsp);
+ EXPECT_EQ(frame1_rbp.Value(), frame1->context.rbp);
+ EXPECT_EQ("echidna", frame1->function_name);
+ EXPECT_EQ(0x00007500b0000100ULL, frame1->function_base);
+}
+
+// StackwalkerAMD64::GetCallerByFramePointerRecovery should never return an
+// instruction pointer of 0 because IP of 0 is an end of stack marker and the
+// stack walk may be terminated prematurely. Instead it should return NULL
+// so that the stack walking code can proceed to stack scanning.
+TEST_F(GetCallerFrame, GetCallerByFramePointerRecovery) {
+ MockCodeModule user32_dll(0x00007ff9cb8a0000ULL, 0x14E000, "user32.dll",
+ "version1");
+ SetModuleSymbols(&user32_dll, // user32.dll
+ "PUBLIC fa60 0 DispatchMessageWorker\n"
+ "PUBLIC fee0 0 UserCallWinProcCheckWow\n"
+ "PUBLIC 1cdb0 0 _fnHkINLPMSG\n"
+ "STACK CFI INIT fa60 340 .cfa: $rsp .ra: .cfa 8 - ^\n"
+ "STACK CFI fa60 .cfa: $rsp 128 +\n"
+ "STACK CFI INIT fee0 49f .cfa: $rsp .ra: .cfa 8 - ^\n"
+ "STACK CFI fee0 .cfa: $rsp 240 +\n"
+ "STACK CFI INIT 1cdb0 9f .cfa: $rsp .ra: .cfa 8 - ^\n"
+ "STACK CFI 1cdb0 .cfa: $rsp 80 +\n");
+
+ // Create some modules with some stock debugging information.
+ MockCodeModules local_modules;
+ local_modules.Add(&user32_dll);
+
+ Label frame0_rsp;
+ Label frame0_rbp;
+ Label frame1_rsp;
+ Label frame2_rsp;
+
+ stack_section.start() = 0x00000099abf0f238ULL;
+ stack_section
+ .Mark(&frame0_rsp)
+ .D64(0x00007ff9cb8b00dcULL)
+ .Mark(&frame1_rsp)
+ .D64(0x0000000000000000ULL)
+ .D64(0x0000000000000001ULL)
+ .D64(0x00000099abf0f308ULL)
+ .D64(0x00007ff9cb8bce3aULL) // Stack residue from execution of
+ // user32!_fnHkINLPMSG+0x8a
+ .D64(0x000000000000c2e0ULL)
+ .D64(0x00000099abf0f328ULL)
+ .D64(0x0000000100000001ULL)
+ .D64(0x0000000000000000ULL)
+ .D64(0x0000000000000000ULL)
+ .D64(0x0000000000000000ULL)
+ .D64(0x0000000000000000ULL)
+ .D64(0x0000000000000000ULL)
+ .D64(0x0000000000000000ULL)
+ .D64(0x00007ff9ccad53e4ULL)
+ .D64(0x0000000000000048ULL)
+ .D64(0x0000000000000001ULL)
+ .D64(0x00000099abf0f5e0ULL)
+ .D64(0x00000099b61f7388ULL)
+ .D64(0x0000000000000030ULL)
+ .D64(0xffffff66540f0a1fULL)
+ .D64(0xffffff6649e08c77ULL)
+ .D64(0x00007ff9cb8affb4ULL) // Return address in
+ // user32!UserCallWinProcCheckWow+0xd4
+ .D64(0x0000000000000000ULL)
+ .D64(0x00000099abf0f368ULL)
+ .D64(0x0000000000000000ULL)
+ .D64(0x0000000000000000ULL)
+ .D64(0x0000000000000000ULL)
+ .D64(0x00000099a8150fd8ULL)
+ .D64(0x00000099abf0f3e8ULL)
+ .D64(0x00007ff9cb8afc07ULL) // Return address in
+ // user32!DispatchMessageWorker+0x1a7
+ .Mark(&frame2_rsp)
+ .Append(256, 0)
+ .Mark(&frame0_rbp) // The following are expected by
+ // GetCallerByFramePointerRecovery.
+ .D64(0xfffffffffffffffeULL) // %caller_rbp = *(%callee_rbp)
+ .D64(0x0000000000000000ULL) // %caller_rip = *(%callee_rbp + 8)
+ .D64(0x00000099a3e31040ULL) // %caller_rsp = *(%callee_rbp + 16)
+ .Append(256, 0);
+
+ RegionFromSection();
+ raw_context.rip = 0x00000099a8150fd8ULL; // IP in context frame is guarbage
+ raw_context.rsp = frame0_rsp.Value();
+ raw_context.rbp = frame0_rbp.Value();
+
+ StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
+ StackwalkerAMD64 walker(&system_info, &raw_context, &stack_region,
+ &local_modules, &frame_symbolizer);
+ vector<const CodeModule*> modules_without_symbols;
+ vector<const CodeModule*> modules_with_corrupt_symbols;
+ ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
+ &modules_with_corrupt_symbols));
+ ASSERT_EQ(0U, modules_without_symbols.size());
+ ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
+ frames = call_stack.frames();
+
+ ASSERT_EQ(3U, frames->size());
+
+ { // To avoid reusing locals by mistake
+ StackFrameAMD64 *frame = static_cast<StackFrameAMD64 *>(frames->at(0));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame->trust);
+ ASSERT_EQ(StackFrameAMD64::CONTEXT_VALID_ALL, frame->context_validity);
+ EXPECT_EQ("", frame->function_name);
+ EXPECT_EQ(0x00000099a8150fd8ULL, frame->instruction);
+ EXPECT_EQ(0x00000099a8150fd8ULL, frame->context.rip);
+ EXPECT_EQ(frame0_rsp.Value(), frame->context.rsp);
+ EXPECT_EQ(frame0_rbp.Value(), frame->context.rbp);
+ }
+
+ { // To avoid reusing locals by mistake
+ StackFrameAMD64 *frame = static_cast<StackFrameAMD64 *>(frames->at(1));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame->trust);
+ ASSERT_EQ((StackFrameAMD64::CONTEXT_VALID_RIP |
+ StackFrameAMD64::CONTEXT_VALID_RSP |
+ StackFrameAMD64::CONTEXT_VALID_RBP),
+ frame->context_validity);
+ EXPECT_EQ("UserCallWinProcCheckWow", frame->function_name);
+ EXPECT_EQ(140710838468828ULL, frame->instruction + 1);
+ EXPECT_EQ(140710838468828ULL, frame->context.rip);
+ EXPECT_EQ(frame1_rsp.Value(), frame->context.rsp);
+ EXPECT_EQ(&user32_dll, frame->module);
+ }
+
+ { // To avoid reusing locals by mistake
+ StackFrameAMD64 *frame = static_cast<StackFrameAMD64 *>(frames->at(2));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame->trust);
+ ASSERT_EQ((StackFrameAMD64::CONTEXT_VALID_RIP |
+ StackFrameAMD64::CONTEXT_VALID_RSP |
+ StackFrameAMD64::CONTEXT_VALID_RBP),
+ frame->context_validity);
+ EXPECT_EQ("DispatchMessageWorker", frame->function_name);
+ EXPECT_EQ(140710838467591ULL, frame->instruction + 1);
+ EXPECT_EQ(140710838467591ULL, frame->context.rip);
+ EXPECT_EQ(frame2_rsp.Value(), frame->context.rsp);
+ EXPECT_EQ(&user32_dll, frame->module);
+ }
+}
+
+// Don't use frame pointer recovery if %rbp is not 8-byte aligned, which
+// indicates that it's not being used as a frame pointer.
+TEST_F(GetCallerFrame, FramePointerNotAligned) {
+ stack_section.start() = 0x8000000080000000ULL;
+ uint64_t return_address1 = 0x00007500b0000100ULL;
+ Label frame0_rbp, not_frame1_rbp, frame1_sp;
+ stack_section
+ // frame 0
+ .Align(8, 0)
+ .Append(2, 0) // mis-align the frame pointer
+ .Mark(&frame0_rbp)
+ .D64(not_frame1_rbp) // not the previous frame pointer
+ .D64(0x00007500b0000a00ULL) // plausible but wrong return address
+ .Align(8, 0)
+ .D64(return_address1) // return address
+ // frame 1
+ .Mark(&frame1_sp)
+ .Mark(&not_frame1_rbp)
+ .Append(32, 0); // end of stack
+
+
+ RegionFromSection();
+
+ raw_context.rip = 0x00007400c0000200ULL;
+ raw_context.rbp = frame0_rbp.Value();
+ raw_context.rsp = stack_section.start().Value();
+
+ StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
+ StackwalkerAMD64 walker(&system_info, &raw_context, &stack_region, &modules,
+ &frame_symbolizer);
+ vector<const CodeModule*> modules_without_symbols;
+ vector<const CodeModule*> modules_with_corrupt_symbols;
+ ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
+ &modules_with_corrupt_symbols));
+ frames = call_stack.frames();
+ ASSERT_EQ(2U, frames->size());
+
+ StackFrameAMD64 *frame0 = static_cast<StackFrameAMD64 *>(frames->at(0));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
+ ASSERT_EQ(StackFrameAMD64::CONTEXT_VALID_ALL, frame0->context_validity);
+ EXPECT_EQ(0, memcmp(&raw_context, &frame0->context, sizeof(raw_context)));
+
+ StackFrameAMD64 *frame1 = static_cast<StackFrameAMD64 *>(frames->at(1));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust);
+ ASSERT_EQ((StackFrameAMD64::CONTEXT_VALID_RIP |
+ StackFrameAMD64::CONTEXT_VALID_RSP),
+ frame1->context_validity);
+ EXPECT_EQ(return_address1, frame1->context.rip);
+ EXPECT_EQ(frame1_sp.Value(), frame1->context.rsp);
+}
+
+// Don't use frame pointer recovery if the recovered %rip is not
+// a canonical x86-64 address.
+TEST_F(GetCallerFrame, NonCanonicalInstructionPointerFromFramePointer) {
+ stack_section.start() = 0x8000000080000000ULL;
+ uint64_t return_address1 = 0x00007500b0000100ULL;
+ Label frame0_rbp, frame1_sp, not_frame1_bp;
+ stack_section
+ // frame 0
+ .Align(8, 0)
+ .Mark(&frame0_rbp)
+ .D64(not_frame1_bp) // some junk on the stack
+ .D64(0xDADADADADADADADA) // not the return address
+ .D64(return_address1) // return address
+ // frame 1
+ .Mark(&frame1_sp)
+ .Append(16, 0)
+ .Mark(&not_frame1_bp)
+ .Append(32, 0); // end of stack
+
+
+ RegionFromSection();
+
+ raw_context.rip = 0x00007400c0000200ULL;
+ raw_context.rbp = frame0_rbp.Value();
+ raw_context.rsp = stack_section.start().Value();
+
+ StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
+ StackwalkerAMD64 walker(&system_info, &raw_context, &stack_region, &modules,
+ &frame_symbolizer);
+ vector<const CodeModule*> modules_without_symbols;
+ vector<const CodeModule*> modules_with_corrupt_symbols;
+ ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
+ &modules_with_corrupt_symbols));
+ frames = call_stack.frames();
+ ASSERT_EQ(2U, frames->size());
+
+ StackFrameAMD64 *frame0 = static_cast<StackFrameAMD64 *>(frames->at(0));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
+ ASSERT_EQ(StackFrameAMD64::CONTEXT_VALID_ALL, frame0->context_validity);
+ EXPECT_EQ(0, memcmp(&raw_context, &frame0->context, sizeof(raw_context)));
+
+ StackFrameAMD64 *frame1 = static_cast<StackFrameAMD64 *>(frames->at(1));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust);
+ ASSERT_EQ((StackFrameAMD64::CONTEXT_VALID_RIP |
+ StackFrameAMD64::CONTEXT_VALID_RSP),
+ frame1->context_validity);
+ EXPECT_EQ(return_address1, frame1->context.rip);
+ EXPECT_EQ(frame1_sp.Value(), frame1->context.rsp);
+}
+
+// Test that set_max_frames_scanned prevents using stack scanning
+// to find caller frames.
+TEST_F(GetCallerFrame, ScanningNotAllowed) {
+ // When the stack walker resorts to scanning the stack,
+ // only addresses located within loaded modules are
+ // considered valid return addresses.
+ stack_section.start() = 0x8000000080000000ULL;
+ uint64_t return_address1 = 0x00007500b0000100ULL;
+ uint64_t return_address2 = 0x00007500b0000900ULL;
+ Label frame1_sp, frame2_sp, frame1_rbp;
+ stack_section
+ // frame 0
+ .Append(16, 0) // space
+
+ .D64(0x00007400b0000000ULL) // junk that's not
+ .D64(0x00007500d0000000ULL) // a return address
+
+ .D64(return_address1) // actual return address
+ // frame 1
+ .Mark(&frame1_sp)
+ .Append(16, 0) // space
+
+ .D64(0x00007400b0000000ULL) // more junk
+ .D64(0x00007500d0000000ULL)
+
+ .Mark(&frame1_rbp)
+ .D64(stack_section.start()) // This is in the right place to be
+ // a saved rbp, but it's bogus, so
+ // we shouldn't report it.
+
+ .D64(return_address2) // actual return address
+ // frame 2
+ .Mark(&frame2_sp)
+ .Append(32, 0); // end of stack
+
+ RegionFromSection();
+
+ raw_context.rip = 0x00007400c0000200ULL;
+ raw_context.rbp = frame1_rbp.Value();
+ raw_context.rsp = stack_section.start().Value();
+
+ StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
+ StackwalkerAMD64 walker(&system_info, &raw_context, &stack_region, &modules,
+ &frame_symbolizer);
+ Stackwalker::set_max_frames_scanned(0);
+
+ vector<const CodeModule*> modules_without_symbols;
+ vector<const CodeModule*> modules_with_corrupt_symbols;
+ ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
+ &modules_with_corrupt_symbols));
+ ASSERT_EQ(1U, modules_without_symbols.size());
+ ASSERT_EQ("module1", modules_without_symbols[0]->debug_file());
+ ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
+ frames = call_stack.frames();
+ ASSERT_EQ(1U, frames->size());
+
+ StackFrameAMD64 *frame0 = static_cast<StackFrameAMD64 *>(frames->at(0));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
+ ASSERT_EQ(StackFrameAMD64::CONTEXT_VALID_ALL, frame0->context_validity);
+ EXPECT_EQ(0, memcmp(&raw_context, &frame0->context, sizeof(raw_context)));
+}
+
+TEST_F(GetCallerFrame, CallerPushedRBP) {
+ // Functions typically push their %rbp upon entry and set %rbp pointing
+ // there. If stackwalking finds a plausible address for the next frame's
+ // %rbp directly below the return address, assume that it is indeed the
+ // next frame's %rbp.
+ stack_section.start() = 0x8000000080000000ULL;
+ uint64_t return_address = 0x00007500b0000110ULL;
+ Label frame0_rbp, frame1_sp, frame1_rbp;
+
+ stack_section
+ // frame 0
+ .Append(16, 0) // space
+
+ .D64(0x00007400b0000000ULL) // junk that's not
+ .D64(0x00007500b0000000ULL) // a return address
+
+ .D64(0x00007400c0001000ULL) // a couple of plausible addresses
+ .D64(0x00007500b000aaaaULL) // that are not within functions
+
+ .Mark(&frame0_rbp)
+ .D64(frame1_rbp) // caller-pushed %rbp
+ .D64(return_address) // actual return address
+ // frame 1
+ .Mark(&frame1_sp)
+ .Append(32, 0) // body of frame1
+ .Mark(&frame1_rbp) // end of stack
+ .D64(0);
+ RegionFromSection();
+
+ raw_context.rip = 0x00007400c0000200ULL;
+ raw_context.rbp = frame0_rbp.Value();
+ raw_context.rsp = stack_section.start().Value();
+
+ SetModuleSymbols(&module1,
+ // The youngest frame's function.
+ "FUNC 100 400 10 sasquatch\n");
+ SetModuleSymbols(&module2,
+ // The calling frame's function.
+ "FUNC 100 400 10 yeti\n");
+
+ StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
+ StackwalkerAMD64 walker(&system_info, &raw_context, &stack_region, &modules,
+ &frame_symbolizer);
+ vector<const CodeModule*> modules_without_symbols;
+ vector<const CodeModule*> modules_with_corrupt_symbols;
+ ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
+ &modules_with_corrupt_symbols));
+ ASSERT_EQ(0U, modules_without_symbols.size());
+ ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
+ frames = call_stack.frames();
+ ASSERT_EQ(2U, frames->size());
+
+ StackFrameAMD64 *frame0 = static_cast<StackFrameAMD64 *>(frames->at(0));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
+ ASSERT_EQ(StackFrameAMD64::CONTEXT_VALID_ALL, frame0->context_validity);
+ EXPECT_EQ(frame0_rbp.Value(), frame0->context.rbp);
+ EXPECT_EQ("sasquatch", frame0->function_name);
+ EXPECT_EQ(0x00007400c0000100ULL, frame0->function_base);
+
+ StackFrameAMD64 *frame1 = static_cast<StackFrameAMD64 *>(frames->at(1));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_FP, frame1->trust);
+ ASSERT_EQ((StackFrameAMD64::CONTEXT_VALID_RIP |
+ StackFrameAMD64::CONTEXT_VALID_RSP |
+ StackFrameAMD64::CONTEXT_VALID_RBP),
+ frame1->context_validity);
+ EXPECT_EQ(return_address, frame1->context.rip);
+ EXPECT_EQ(frame1_sp.Value(), frame1->context.rsp);
+ EXPECT_EQ(frame1_rbp.Value(), frame1->context.rbp);
+ EXPECT_EQ("yeti", frame1->function_name);
+ EXPECT_EQ(0x00007500b0000100ULL, frame1->function_base);
+}
+
+struct CFIFixture: public StackwalkerAMD64Fixture {
+ CFIFixture() {
+ // Provide a bunch of STACK CFI records; we'll walk to the caller
+ // from every point in this series, expecting to find the same set
+ // of register values.
+ SetModuleSymbols(&module1,
+ // The youngest frame's function.
+ "FUNC 4000 1000 10 enchiridion\n"
+ // Initially, just a return address.
+ "STACK CFI INIT 4000 100 .cfa: $rsp 8 + .ra: .cfa 8 - ^\n"
+ // Push %rbx.
+ "STACK CFI 4001 .cfa: $rsp 16 + $rbx: .cfa 16 - ^\n"
+ // Save %r12 in %rbx. Weird, but permitted.
+ "STACK CFI 4002 $r12: $rbx\n"
+ // Allocate frame space, and save %r13.
+ "STACK CFI 4003 .cfa: $rsp 40 + $r13: .cfa 32 - ^\n"
+ // Put the return address in %r13.
+ "STACK CFI 4005 .ra: $r13\n"
+ // Save %rbp, and use it as a frame pointer.
+ "STACK CFI 4006 .cfa: $rbp 16 + $rbp: .cfa 24 - ^\n"
+
+ // The calling function.
+ "FUNC 5000 1000 10 epictetus\n"
+ // Mark it as end of stack.
+ "STACK CFI INIT 5000 1000 .cfa: $rsp .ra 0\n");
+
+ // Provide some distinctive values for the caller's registers.
+ expected.rsp = 0x8000000080000000ULL;
+ expected.rip = 0x00007400c0005510ULL;
+ expected.rbp = 0x68995b1de4700266ULL;
+ expected.rbx = 0x5a5beeb38de23be8ULL;
+ expected.r12 = 0xed1b02e8cc0fc79cULL;
+ expected.r13 = 0x1d20ad8acacbe930ULL;
+ expected.r14 = 0xe94cffc2f7adaa28ULL;
+ expected.r15 = 0xb638d17d8da413b5ULL;
+
+ // By default, registers are unchanged.
+ raw_context = expected;
+ }
+
+ // Walk the stack, using stack_section as the contents of the stack
+ // and raw_context as the current register values. (Set
+ // raw_context.rsp to the stack's starting address.) Expect two
+ // stack frames; in the older frame, expect the callee-saves
+ // registers to have values matching those in 'expected'.
+ void CheckWalk() {
+ RegionFromSection();
+ raw_context.rsp = stack_section.start().Value();
+
+ StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
+ StackwalkerAMD64 walker(&system_info, &raw_context, &stack_region, &modules,
+ &frame_symbolizer);
+ vector<const CodeModule*> modules_without_symbols;
+ vector<const CodeModule*> modules_with_corrupt_symbols;
+ ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
+ &modules_with_corrupt_symbols));
+ ASSERT_EQ(0U, modules_without_symbols.size());
+ ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
+ frames = call_stack.frames();
+ ASSERT_EQ(2U, frames->size());
+
+ StackFrameAMD64 *frame0 = static_cast<StackFrameAMD64 *>(frames->at(0));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
+ ASSERT_EQ(StackFrameAMD64::CONTEXT_VALID_ALL, frame0->context_validity);
+ EXPECT_EQ("enchiridion", frame0->function_name);
+ EXPECT_EQ(0x00007400c0004000ULL, frame0->function_base);
+
+ StackFrameAMD64 *frame1 = static_cast<StackFrameAMD64 *>(frames->at(1));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame1->trust);
+ ASSERT_EQ((StackFrameAMD64::CONTEXT_VALID_RIP |
+ StackFrameAMD64::CONTEXT_VALID_RSP |
+ StackFrameAMD64::CONTEXT_VALID_RBP |
+ StackFrameAMD64::CONTEXT_VALID_RBX |
+ StackFrameAMD64::CONTEXT_VALID_R12 |
+ StackFrameAMD64::CONTEXT_VALID_R13 |
+ StackFrameAMD64::CONTEXT_VALID_R14 |
+ StackFrameAMD64::CONTEXT_VALID_R15),
+ frame1->context_validity);
+ EXPECT_EQ(expected.rip, frame1->context.rip);
+ EXPECT_EQ(expected.rsp, frame1->context.rsp);
+ EXPECT_EQ(expected.rbp, frame1->context.rbp);
+ EXPECT_EQ(expected.rbx, frame1->context.rbx);
+ EXPECT_EQ(expected.r12, frame1->context.r12);
+ EXPECT_EQ(expected.r13, frame1->context.r13);
+ EXPECT_EQ(expected.r14, frame1->context.r14);
+ EXPECT_EQ(expected.r15, frame1->context.r15);
+ EXPECT_EQ("epictetus", frame1->function_name);
+ }
+
+ // The values we expect to find for the caller's registers.
+ MDRawContextAMD64 expected;
+};
+
+class CFI: public CFIFixture, public Test { };
+
+TEST_F(CFI, At4000) {
+ Label frame1_rsp = expected.rsp;
+ stack_section
+ .D64(0x00007400c0005510ULL) // return address
+ .Mark(&frame1_rsp); // This effectively sets stack_section.start().
+ raw_context.rip = 0x00007400c0004000ULL;
+ CheckWalk();
+}
+
+TEST_F(CFI, At4001) {
+ Label frame1_rsp = expected.rsp;
+ stack_section
+ .D64(0x5a5beeb38de23be8ULL) // saved %rbx
+ .D64(0x00007400c0005510ULL) // return address
+ .Mark(&frame1_rsp); // This effectively sets stack_section.start().
+ raw_context.rip = 0x00007400c0004001ULL;
+ raw_context.rbx = 0xbe0487d2f9eafe29ULL; // callee's (distinct) %rbx value
+ CheckWalk();
+}
+
+TEST_F(CFI, At4002) {
+ Label frame1_rsp = expected.rsp;
+ stack_section
+ .D64(0x5a5beeb38de23be8ULL) // saved %rbx
+ .D64(0x00007400c0005510ULL) // return address
+ .Mark(&frame1_rsp); // This effectively sets stack_section.start().
+ raw_context.rip = 0x00007400c0004002ULL;
+ raw_context.rbx = 0xed1b02e8cc0fc79cULL; // saved %r12
+ raw_context.r12 = 0xb0118de918a4bceaULL; // callee's (distinct) %r12 value
+ CheckWalk();
+}
+
+TEST_F(CFI, At4003) {
+ Label frame1_rsp = expected.rsp;
+ stack_section
+ .D64(0x0e023828dffd4d81ULL) // garbage
+ .D64(0x1d20ad8acacbe930ULL) // saved %r13
+ .D64(0x319e68b49e3ace0fULL) // garbage
+ .D64(0x5a5beeb38de23be8ULL) // saved %rbx
+ .D64(0x00007400c0005510ULL) // return address
+ .Mark(&frame1_rsp); // This effectively sets stack_section.start().
+ raw_context.rip = 0x00007400c0004003ULL;
+ raw_context.rbx = 0xed1b02e8cc0fc79cULL; // saved %r12
+ raw_context.r12 = 0x89d04fa804c87a43ULL; // callee's (distinct) %r12
+ raw_context.r13 = 0x5118e02cbdb24b03ULL; // callee's (distinct) %r13
+ CheckWalk();
+}
+
+// The results here should be the same as those at module offset 0x4003.
+TEST_F(CFI, At4004) {
+ Label frame1_rsp = expected.rsp;
+ stack_section
+ .D64(0x0e023828dffd4d81ULL) // garbage
+ .D64(0x1d20ad8acacbe930ULL) // saved %r13
+ .D64(0x319e68b49e3ace0fULL) // garbage
+ .D64(0x5a5beeb38de23be8ULL) // saved %rbx
+ .D64(0x00007400c0005510ULL) // return address
+ .Mark(&frame1_rsp); // This effectively sets stack_section.start().
+ raw_context.rip = 0x00007400c0004004ULL;
+ raw_context.rbx = 0xed1b02e8cc0fc79cULL; // saved %r12
+ raw_context.r12 = 0x89d04fa804c87a43ULL; // callee's (distinct) %r12
+ raw_context.r13 = 0x5118e02cbdb24b03ULL; // callee's (distinct) %r13
+ CheckWalk();
+}
+
+TEST_F(CFI, At4005) {
+ Label frame1_rsp = expected.rsp;
+ stack_section
+ .D64(0x4b516dd035745953ULL) // garbage
+ .D64(0x1d20ad8acacbe930ULL) // saved %r13
+ .D64(0xa6d445e16ae3d872ULL) // garbage
+ .D64(0x5a5beeb38de23be8ULL) // saved %rbx
+ .D64(0xaa95fa054aedfbaeULL) // garbage
+ .Mark(&frame1_rsp); // This effectively sets stack_section.start().
+ raw_context.rip = 0x00007400c0004005ULL;
+ raw_context.rbx = 0xed1b02e8cc0fc79cULL; // saved %r12
+ raw_context.r12 = 0x46b1b8868891b34aULL; // callee's %r12
+ raw_context.r13 = 0x00007400c0005510ULL; // return address
+ CheckWalk();
+}
+
+TEST_F(CFI, At4006) {
+ Label frame0_rbp;
+ Label frame1_rsp = expected.rsp;
+ stack_section
+ .D64(0x043c6dfceb91aa34ULL) // garbage
+ .D64(0x1d20ad8acacbe930ULL) // saved %r13
+ .D64(0x68995b1de4700266ULL) // saved %rbp
+ .Mark(&frame0_rbp) // frame pointer points here
+ .D64(0x5a5beeb38de23be8ULL) // saved %rbx
+ .D64(0xf015ee516ad89eabULL) // garbage
+ .Mark(&frame1_rsp); // This effectively sets stack_section.start().
+ raw_context.rip = 0x00007400c0004006ULL;
+ raw_context.rbp = frame0_rbp.Value();
+ raw_context.rbx = 0xed1b02e8cc0fc79cULL; // saved %r12
+ raw_context.r12 = 0x26e007b341acfebdULL; // callee's %r12
+ raw_context.r13 = 0x00007400c0005510ULL; // return address
+ CheckWalk();
+}
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_arm.cc b/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_arm.cc
new file mode 100644
index 0000000000..1313416f4d
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_arm.cc
@@ -0,0 +1,297 @@
+// 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.
+
+// stackwalker_arm.cc: arm-specific stackwalker.
+//
+// See stackwalker_arm.h for documentation.
+//
+// Author: Mark Mentovai, Ted Mielczarek, Jim Blandy
+
+#include <vector>
+
+#include "common/scoped_ptr.h"
+#include "google_breakpad/processor/call_stack.h"
+#include "google_breakpad/processor/memory_region.h"
+#include "google_breakpad/processor/source_line_resolver_interface.h"
+#include "google_breakpad/processor/stack_frame_cpu.h"
+#include "google_breakpad/processor/system_info.h"
+#include "processor/cfi_frame_info.h"
+#include "processor/logging.h"
+#include "processor/stackwalker_arm.h"
+
+namespace google_breakpad {
+
+
+StackwalkerARM::StackwalkerARM(const SystemInfo* system_info,
+ const MDRawContextARM* context,
+ int fp_register,
+ MemoryRegion* memory,
+ const CodeModules* modules,
+ StackFrameSymbolizer* resolver_helper)
+ : Stackwalker(system_info, memory, modules, resolver_helper),
+ context_(context), fp_register_(fp_register),
+ context_frame_validity_(StackFrameARM::CONTEXT_VALID_ALL) { }
+
+
+StackFrame* StackwalkerARM::GetContextFrame() {
+ if (!context_) {
+ BPLOG(ERROR) << "Can't get context frame without context";
+ return NULL;
+ }
+
+ StackFrameARM* frame = new StackFrameARM();
+
+ // The instruction pointer is stored directly in a register (r15), so pull it
+ // straight out of the CPU context structure.
+ frame->context = *context_;
+ frame->context_validity = context_frame_validity_;
+ frame->trust = StackFrame::FRAME_TRUST_CONTEXT;
+ frame->instruction = frame->context.iregs[MD_CONTEXT_ARM_REG_PC];
+
+ return frame;
+}
+
+StackFrameARM* StackwalkerARM::GetCallerByCFIFrameInfo(
+ const vector<StackFrame*> &frames,
+ CFIFrameInfo* cfi_frame_info) {
+ StackFrameARM* last_frame = static_cast<StackFrameARM*>(frames.back());
+
+ static const char* register_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",
+ NULL
+ };
+
+ // Populate a dictionary with the valid register values in last_frame.
+ CFIFrameInfo::RegisterValueMap<uint32_t> callee_registers;
+ for (int i = 0; register_names[i]; i++)
+ if (last_frame->context_validity & StackFrameARM::RegisterValidFlag(i))
+ callee_registers[register_names[i]] = last_frame->context.iregs[i];
+
+ // Use the STACK CFI data to recover the caller's register values.
+ CFIFrameInfo::RegisterValueMap<uint32_t> caller_registers;
+ if (!cfi_frame_info->FindCallerRegs(callee_registers, *memory_,
+ &caller_registers))
+ return NULL;
+
+ // Construct a new stack frame given the values the CFI recovered.
+ scoped_ptr<StackFrameARM> frame(new StackFrameARM());
+ for (int i = 0; register_names[i]; i++) {
+ CFIFrameInfo::RegisterValueMap<uint32_t>::iterator entry =
+ caller_registers.find(register_names[i]);
+ if (entry != caller_registers.end()) {
+ // We recovered the value of this register; fill the context with the
+ // value from caller_registers.
+ frame->context_validity |= StackFrameARM::RegisterValidFlag(i);
+ frame->context.iregs[i] = entry->second;
+ } else if (4 <= i && i <= 11 && (last_frame->context_validity &
+ StackFrameARM::RegisterValidFlag(i))) {
+ // If the STACK CFI data doesn't mention some callee-saves register, and
+ // it is valid in the callee, assume the callee has not yet changed it.
+ // Registers r4 through r11 are callee-saves, according to the Procedure
+ // Call Standard for the ARM Architecture, which the Linux ABI follows.
+ frame->context_validity |= StackFrameARM::RegisterValidFlag(i);
+ frame->context.iregs[i] = last_frame->context.iregs[i];
+ }
+ }
+ // If the CFI doesn't recover the PC explicitly, then use .ra.
+ if (!(frame->context_validity & StackFrameARM::CONTEXT_VALID_PC)) {
+ CFIFrameInfo::RegisterValueMap<uint32_t>::iterator entry =
+ caller_registers.find(".ra");
+ if (entry != caller_registers.end()) {
+ if (fp_register_ == -1) {
+ frame->context_validity |= StackFrameARM::CONTEXT_VALID_PC;
+ frame->context.iregs[MD_CONTEXT_ARM_REG_PC] = entry->second;
+ } else {
+ // The CFI updated the link register and not the program counter.
+ // Handle getting the program counter from the link register.
+ frame->context_validity |= StackFrameARM::CONTEXT_VALID_PC;
+ frame->context_validity |= StackFrameARM::CONTEXT_VALID_LR;
+ frame->context.iregs[MD_CONTEXT_ARM_REG_LR] = entry->second;
+ frame->context.iregs[MD_CONTEXT_ARM_REG_PC] =
+ last_frame->context.iregs[MD_CONTEXT_ARM_REG_LR];
+ }
+ }
+ }
+ // If the CFI doesn't recover the SP explicitly, then use .cfa.
+ if (!(frame->context_validity & StackFrameARM::CONTEXT_VALID_SP)) {
+ CFIFrameInfo::RegisterValueMap<uint32_t>::iterator entry =
+ caller_registers.find(".cfa");
+ if (entry != caller_registers.end()) {
+ frame->context_validity |= StackFrameARM::CONTEXT_VALID_SP;
+ frame->context.iregs[MD_CONTEXT_ARM_REG_SP] = entry->second;
+ }
+ }
+
+ // If we didn't recover the PC and the SP, then the frame isn't very useful.
+ static const int essentials = (StackFrameARM::CONTEXT_VALID_SP
+ | StackFrameARM::CONTEXT_VALID_PC);
+ if ((frame->context_validity & essentials) != essentials)
+ return NULL;
+
+ frame->trust = StackFrame::FRAME_TRUST_CFI;
+ return frame.release();
+}
+
+StackFrameARM* StackwalkerARM::GetCallerByStackScan(
+ const vector<StackFrame*> &frames) {
+ StackFrameARM* last_frame = static_cast<StackFrameARM*>(frames.back());
+ uint32_t last_sp = last_frame->context.iregs[MD_CONTEXT_ARM_REG_SP];
+ uint32_t caller_sp, caller_pc;
+
+ if (!ScanForReturnAddress(last_sp, &caller_sp, &caller_pc,
+ frames.size() == 1 /* is_context_frame */)) {
+ // No plausible return address was found.
+ return NULL;
+ }
+
+ // ScanForReturnAddress found a reasonable return address. Advance
+ // %sp to the location above the one where the return address was
+ // found.
+ caller_sp += 4;
+
+ // Create a new stack frame (ownership will be transferred to the caller)
+ // and fill it in.
+ StackFrameARM* frame = new StackFrameARM();
+
+ frame->trust = StackFrame::FRAME_TRUST_SCAN;
+ frame->context = last_frame->context;
+ frame->context.iregs[MD_CONTEXT_ARM_REG_PC] = caller_pc;
+ frame->context.iregs[MD_CONTEXT_ARM_REG_SP] = caller_sp;
+ frame->context_validity = StackFrameARM::CONTEXT_VALID_PC |
+ StackFrameARM::CONTEXT_VALID_SP;
+
+ return frame;
+}
+
+StackFrameARM* StackwalkerARM::GetCallerByFramePointer(
+ const vector<StackFrame*> &frames) {
+ StackFrameARM* last_frame = static_cast<StackFrameARM*>(frames.back());
+
+ if (!(last_frame->context_validity &
+ StackFrameARM::RegisterValidFlag(fp_register_))) {
+ return NULL;
+ }
+
+ uint32_t last_fp = last_frame->context.iregs[fp_register_];
+
+ uint32_t caller_fp = 0;
+ if (last_fp && !memory_->GetMemoryAtAddress(last_fp, &caller_fp)) {
+ BPLOG(ERROR) << "Unable to read caller_fp from last_fp: 0x"
+ << std::hex << last_fp;
+ return NULL;
+ }
+
+ uint32_t caller_lr = 0;
+ if (last_fp && !memory_->GetMemoryAtAddress(last_fp + 4, &caller_lr)) {
+ BPLOG(ERROR) << "Unable to read caller_lr from last_fp + 4: 0x"
+ << std::hex << (last_fp + 4);
+ return NULL;
+ }
+
+ uint32_t caller_sp = last_fp ? last_fp + 8 :
+ last_frame->context.iregs[MD_CONTEXT_ARM_REG_SP];
+
+ // Create a new stack frame (ownership will be transferred to the caller)
+ // and fill it in.
+ StackFrameARM* frame = new StackFrameARM();
+
+ frame->trust = StackFrame::FRAME_TRUST_FP;
+ frame->context = last_frame->context;
+ frame->context.iregs[fp_register_] = caller_fp;
+ frame->context.iregs[MD_CONTEXT_ARM_REG_SP] = caller_sp;
+ frame->context.iregs[MD_CONTEXT_ARM_REG_PC] =
+ last_frame->context.iregs[MD_CONTEXT_ARM_REG_LR];
+ frame->context.iregs[MD_CONTEXT_ARM_REG_LR] = caller_lr;
+ frame->context_validity = StackFrameARM::CONTEXT_VALID_PC |
+ StackFrameARM::CONTEXT_VALID_LR |
+ StackFrameARM::RegisterValidFlag(fp_register_) |
+ StackFrameARM::CONTEXT_VALID_SP;
+ return frame;
+}
+
+StackFrame* StackwalkerARM::GetCallerFrame(const CallStack* stack,
+ bool stack_scan_allowed) {
+ if (!memory_ || !stack) {
+ BPLOG(ERROR) << "Can't get caller frame without memory or stack";
+ return NULL;
+ }
+
+ const vector<StackFrame*> &frames = *stack->frames();
+ StackFrameARM* last_frame = static_cast<StackFrameARM*>(frames.back());
+ scoped_ptr<StackFrameARM> frame;
+
+ // See if there is DWARF call frame information covering this address.
+ // TODO(jperaza): Ignore iOS CFI info until it is properly collected.
+ // https://bugs.chromium.org/p/google-breakpad/issues/detail?id=764
+ if (!system_info_ || system_info_->os != "iOS") {
+ scoped_ptr<CFIFrameInfo> cfi_frame_info(
+ frame_symbolizer_->FindCFIFrameInfo(last_frame));
+ if (cfi_frame_info.get())
+ frame.reset(GetCallerByCFIFrameInfo(frames, cfi_frame_info.get()));
+ }
+
+ // If CFI failed, or there wasn't CFI available, fall back
+ // to frame pointer, if this is configured.
+ if (fp_register_ >= 0 && !frame.get())
+ frame.reset(GetCallerByFramePointer(frames));
+
+ // If everuthing failed, fall back to stack scanning.
+ if (stack_scan_allowed && !frame.get())
+ frame.reset(GetCallerByStackScan(frames));
+
+ // If nothing worked, tell the caller.
+ if (!frame.get())
+ return NULL;
+
+ // Should we terminate the stack walk? (end-of-stack or broken invariant)
+ if (TerminateWalk(frame->context.iregs[MD_CONTEXT_ARM_REG_PC],
+ frame->context.iregs[MD_CONTEXT_ARM_REG_SP],
+ last_frame->context.iregs[MD_CONTEXT_ARM_REG_SP],
+ frames.size() == 1)) {
+ return NULL;
+ }
+
+ // The new frame's context's PC is the return address, which is one
+ // instruction past the instruction that caused us to arrive at the
+ // callee. Set new_frame->instruction to one less than the PC. This won't
+ // reference the beginning of the call instruction, but it's at least
+ // within it, which is sufficient to get the source line information to
+ // match up with the line that contains the function call. Callers that
+ // require the exact return address value may access
+ // frame->context.iregs[MD_CONTEXT_ARM_REG_PC].
+ frame->instruction = frame->context.iregs[MD_CONTEXT_ARM_REG_PC] - 2;
+
+ return frame.release();
+}
+
+
+} // namespace google_breakpad
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_arm.h b/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_arm.h
new file mode 100644
index 0000000000..9081a40cd0
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_arm.h
@@ -0,0 +1,107 @@
+// -*- 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.
+
+// stackwalker_arm.h: arm-specific stackwalker.
+//
+// Provides stack frames given arm register context and a memory region
+// corresponding to an arm stack.
+//
+// Author: Mark Mentovai, Ted Mielczarek
+
+
+#ifndef PROCESSOR_STACKWALKER_ARM_H__
+#define PROCESSOR_STACKWALKER_ARM_H__
+
+#include "google_breakpad/common/breakpad_types.h"
+#include "google_breakpad/common/minidump_format.h"
+#include "google_breakpad/processor/stackwalker.h"
+
+namespace google_breakpad {
+
+class CodeModules;
+
+class StackwalkerARM : public Stackwalker {
+ public:
+ // context is an arm context object that gives access to arm-specific
+ // register state corresponding to the innermost called frame to be
+ // included in the stack. The other arguments are passed directly through
+ // to the base Stackwalker constructor.
+ StackwalkerARM(const SystemInfo* system_info,
+ const MDRawContextARM* context,
+ int fp_register,
+ MemoryRegion* memory,
+ const CodeModules* modules,
+ StackFrameSymbolizer* frame_symbolizer);
+
+ // Change the context validity mask of the frame returned by
+ // GetContextFrame to VALID. This is only for use by unit tests; the
+ // default behavior is correct for all application code.
+ void SetContextFrameValidity(int valid) { context_frame_validity_ = valid; }
+
+ private:
+ // Implementation of Stackwalker, using arm context and stack conventions.
+ virtual StackFrame* GetContextFrame();
+ virtual StackFrame* GetCallerFrame(const CallStack* stack,
+ bool stack_scan_allowed);
+
+ // Use cfi_frame_info (derived from STACK CFI records) to construct
+ // the frame that called frames.back(). The caller takes ownership
+ // of the returned frame. Return NULL on failure.
+ StackFrameARM* GetCallerByCFIFrameInfo(const vector<StackFrame*> &frames,
+ CFIFrameInfo* cfi_frame_info);
+
+ // Use the frame pointer. The caller takes ownership of the returned frame.
+ // Return NULL on failure.
+ StackFrameARM* GetCallerByFramePointer(const vector<StackFrame*> &frames);
+
+ // Scan the stack for plausible return addresses. The caller takes ownership
+ // of the returned frame. Return NULL on failure.
+ StackFrameARM* GetCallerByStackScan(const vector<StackFrame*> &frames);
+
+ // Stores the CPU context corresponding to the youngest stack frame, to
+ // be returned by GetContextFrame.
+ const MDRawContextARM* context_;
+
+ // The register to use a as frame pointer. The value is -1 if frame pointer
+ // cannot be used.
+ int fp_register_;
+
+ // Validity mask for youngest stack frame. This is always
+ // CONTEXT_VALID_ALL in real use; it is only changeable for the sake of
+ // unit tests.
+ int context_frame_validity_;
+};
+
+
+} // namespace google_breakpad
+
+
+#endif // PROCESSOR_STACKWALKER_ARM_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_arm64.cc b/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_arm64.cc
new file mode 100644
index 0000000000..3d9232888b
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_arm64.cc
@@ -0,0 +1,351 @@
+// 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.
+
+// stackwalker_arm64.cc: arm64-specific stackwalker.
+//
+// See stackwalker_arm64.h for documentation.
+//
+// Author: Mark Mentovai, Ted Mielczarek, Jim Blandy, Colin Blundell
+
+#include <vector>
+
+#include "common/scoped_ptr.h"
+#include "google_breakpad/processor/call_stack.h"
+#include "google_breakpad/processor/memory_region.h"
+#include "google_breakpad/processor/source_line_resolver_interface.h"
+#include "google_breakpad/processor/stack_frame_cpu.h"
+#include "processor/cfi_frame_info.h"
+#include "processor/logging.h"
+#include "processor/stackwalker_arm64.h"
+
+namespace google_breakpad {
+
+
+StackwalkerARM64::StackwalkerARM64(const SystemInfo* system_info,
+ const MDRawContextARM64* context,
+ MemoryRegion* memory,
+ const CodeModules* modules,
+ StackFrameSymbolizer* resolver_helper)
+ : Stackwalker(system_info, memory, modules, resolver_helper),
+ context_(context),
+ context_frame_validity_(StackFrameARM64::CONTEXT_VALID_ALL),
+ address_range_mask_(0xffffffffffffffff) {
+ if (modules && modules->module_count() > 0) {
+ // ARM64 supports storing pointer authentication codes in the upper bits of
+ // a pointer. Make a best guess at the range of valid addresses based on the
+ // range of loaded modules.
+ const CodeModule *high_module =
+ modules->GetModuleAtSequence(modules->module_count() - 1);
+ uint64_t mask = high_module->base_address() + high_module->size();
+ mask |= mask >> 1;
+ mask |= mask >> 2;
+ mask |= mask >> 4;
+ mask |= mask >> 8;
+ mask |= mask >> 16;
+ mask |= mask >> 32;
+ address_range_mask_ = mask;
+ }
+}
+
+uint64_t StackwalkerARM64::PtrauthStrip(uint64_t ptr) {
+ uint64_t stripped = ptr & address_range_mask_;
+ return modules_ && modules_->GetModuleForAddress(stripped) ? stripped : ptr;
+}
+
+StackFrame* StackwalkerARM64::GetContextFrame() {
+ if (!context_) {
+ BPLOG(ERROR) << "Can't get context frame without context";
+ return NULL;
+ }
+
+ StackFrameARM64* frame = new StackFrameARM64();
+
+ // The instruction pointer is stored directly in a register (x32), so pull it
+ // straight out of the CPU context structure.
+ frame->context = *context_;
+ frame->context_validity = context_frame_validity_;
+ frame->trust = StackFrame::FRAME_TRUST_CONTEXT;
+ frame->instruction = frame->context.iregs[MD_CONTEXT_ARM64_REG_PC];
+ frame->context.iregs[MD_CONTEXT_ARM64_REG_LR] =
+ PtrauthStrip(frame->context.iregs[MD_CONTEXT_ARM64_REG_LR]);
+
+ return frame;
+}
+
+StackFrameARM64* StackwalkerARM64::GetCallerByCFIFrameInfo(
+ const vector<StackFrame*> &frames,
+ CFIFrameInfo* cfi_frame_info) {
+ StackFrameARM64* last_frame = static_cast<StackFrameARM64*>(frames.back());
+
+ static const char* register_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",
+ "pc", NULL
+ };
+
+ // Populate a dictionary with the valid register values in last_frame.
+ CFIFrameInfo::RegisterValueMap<uint64_t> callee_registers;
+ for (int i = 0; register_names[i]; i++) {
+ if (last_frame->context_validity & StackFrameARM64::RegisterValidFlag(i))
+ callee_registers[register_names[i]] = last_frame->context.iregs[i];
+ }
+
+ // Use the STACK CFI data to recover the caller's register values.
+ CFIFrameInfo::RegisterValueMap<uint64_t> caller_registers;
+ if (!cfi_frame_info->FindCallerRegs(callee_registers, *memory_,
+ &caller_registers)) {
+ return NULL;
+ }
+ // Construct a new stack frame given the values the CFI recovered.
+ scoped_ptr<StackFrameARM64> frame(new StackFrameARM64());
+ for (int i = 0; register_names[i]; i++) {
+ CFIFrameInfo::RegisterValueMap<uint64_t>::iterator entry =
+ caller_registers.find(register_names[i]);
+ if (entry != caller_registers.end()) {
+ // We recovered the value of this register; fill the context with the
+ // value from caller_registers.
+ frame->context_validity |= StackFrameARM64::RegisterValidFlag(i);
+ frame->context.iregs[i] = entry->second;
+ } else if (19 <= i && i <= 29 && (last_frame->context_validity &
+ StackFrameARM64::RegisterValidFlag(i))) {
+ // If the STACK CFI data doesn't mention some callee-saves register, and
+ // it is valid in the callee, assume the callee has not yet changed it.
+ // Registers r19 through r29 are callee-saves, according to the Procedure
+ // Call Standard for the ARM AARCH64 Architecture, which the Linux ABI
+ // follows.
+ frame->context_validity |= StackFrameARM64::RegisterValidFlag(i);
+ frame->context.iregs[i] = last_frame->context.iregs[i];
+ }
+ }
+ // If the CFI doesn't recover the PC explicitly, then use .ra.
+ if (!(frame->context_validity & StackFrameARM64::CONTEXT_VALID_PC)) {
+ CFIFrameInfo::RegisterValueMap<uint64_t>::iterator entry =
+ caller_registers.find(".ra");
+ if (entry != caller_registers.end()) {
+ frame->context_validity |= StackFrameARM64::CONTEXT_VALID_PC;
+ frame->context.iregs[MD_CONTEXT_ARM64_REG_PC] = entry->second;
+ }
+ }
+ // If the CFI doesn't recover the SP explicitly, then use .cfa.
+ if (!(frame->context_validity & StackFrameARM64::CONTEXT_VALID_SP)) {
+ CFIFrameInfo::RegisterValueMap<uint64_t>::iterator entry =
+ caller_registers.find(".cfa");
+ if (entry != caller_registers.end()) {
+ frame->context_validity |= StackFrameARM64::CONTEXT_VALID_SP;
+ frame->context.iregs[MD_CONTEXT_ARM64_REG_SP] = entry->second;
+ }
+ }
+
+ // If we didn't recover the PC and the SP, then the frame isn't very useful.
+ static const uint64_t essentials = (StackFrameARM64::CONTEXT_VALID_SP
+ | StackFrameARM64::CONTEXT_VALID_PC);
+ if ((frame->context_validity & essentials) != essentials)
+ return NULL;
+
+ frame->trust = StackFrame::FRAME_TRUST_CFI;
+ return frame.release();
+}
+
+StackFrameARM64* StackwalkerARM64::GetCallerByStackScan(
+ const vector<StackFrame*> &frames) {
+ StackFrameARM64* last_frame = static_cast<StackFrameARM64*>(frames.back());
+ uint64_t last_sp = last_frame->context.iregs[MD_CONTEXT_ARM64_REG_SP];
+ uint64_t caller_sp, caller_pc;
+
+ if (!ScanForReturnAddress(last_sp, &caller_sp, &caller_pc,
+ frames.size() == 1 /* is_context_frame */)) {
+ // No plausible return address was found.
+ return NULL;
+ }
+
+ // ScanForReturnAddress found a reasonable return address. Advance
+ // %sp to the location above the one where the return address was
+ // found.
+ caller_sp += 8;
+
+ // Create a new stack frame (ownership will be transferred to the caller)
+ // and fill it in.
+ StackFrameARM64* frame = new StackFrameARM64();
+
+ frame->trust = StackFrame::FRAME_TRUST_SCAN;
+ frame->context = last_frame->context;
+ frame->context.iregs[MD_CONTEXT_ARM64_REG_PC] = caller_pc;
+ frame->context.iregs[MD_CONTEXT_ARM64_REG_SP] = caller_sp;
+ frame->context_validity = StackFrameARM64::CONTEXT_VALID_PC |
+ StackFrameARM64::CONTEXT_VALID_SP;
+
+ return frame;
+}
+
+StackFrameARM64* StackwalkerARM64::GetCallerByFramePointer(
+ const vector<StackFrame*> &frames) {
+ StackFrameARM64* last_frame = static_cast<StackFrameARM64*>(frames.back());
+ if (!(last_frame->context_validity & StackFrameARM64::CONTEXT_VALID_LR)) {
+ CorrectRegLRByFramePointer(frames, last_frame);
+ }
+
+ uint64_t last_fp = last_frame->context.iregs[MD_CONTEXT_ARM64_REG_FP];
+
+ uint64_t caller_fp = 0;
+ if (last_fp && !memory_->GetMemoryAtAddress(last_fp, &caller_fp)) {
+ BPLOG(ERROR) << "Unable to read caller_fp from last_fp: 0x"
+ << std::hex << last_fp;
+ return NULL;
+ }
+
+ uint64_t caller_lr = 0;
+ if (last_fp && !memory_->GetMemoryAtAddress(last_fp + 8, &caller_lr)) {
+ BPLOG(ERROR) << "Unable to read caller_lr from last_fp + 8: 0x"
+ << std::hex << (last_fp + 8);
+ return NULL;
+ }
+
+ caller_lr = PtrauthStrip(caller_lr);
+
+ uint64_t caller_sp = last_fp ? last_fp + 16 :
+ last_frame->context.iregs[MD_CONTEXT_ARM64_REG_SP];
+
+ // Create a new stack frame (ownership will be transferred to the caller)
+ // and fill it in.
+ StackFrameARM64* frame = new StackFrameARM64();
+
+ frame->trust = StackFrame::FRAME_TRUST_FP;
+ frame->context = last_frame->context;
+ frame->context.iregs[MD_CONTEXT_ARM64_REG_FP] = caller_fp;
+ frame->context.iregs[MD_CONTEXT_ARM64_REG_SP] = caller_sp;
+ frame->context.iregs[MD_CONTEXT_ARM64_REG_PC] =
+ last_frame->context.iregs[MD_CONTEXT_ARM64_REG_LR];
+ frame->context.iregs[MD_CONTEXT_ARM64_REG_LR] = caller_lr;
+ frame->context_validity = StackFrameARM64::CONTEXT_VALID_PC |
+ StackFrameARM64::CONTEXT_VALID_LR |
+ StackFrameARM64::CONTEXT_VALID_FP |
+ StackFrameARM64::CONTEXT_VALID_SP;
+ return frame;
+}
+
+void StackwalkerARM64::CorrectRegLRByFramePointer(
+ const vector<StackFrame*>& frames,
+ StackFrameARM64* last_frame) {
+ // Need at least two frames to correct and
+ // register $FP should always be greater than register $SP.
+ if (frames.size() < 2 || !last_frame ||
+ last_frame->context.iregs[MD_CONTEXT_ARM64_REG_FP] <=
+ last_frame->context.iregs[MD_CONTEXT_ARM64_REG_SP])
+ return;
+
+ StackFrameARM64* last_last_frame =
+ static_cast<StackFrameARM64*>(*(frames.end() - 2));
+ uint64_t last_last_fp =
+ last_last_frame->context.iregs[MD_CONTEXT_ARM64_REG_FP];
+
+ uint64_t last_fp = 0;
+ if (last_last_fp && !memory_->GetMemoryAtAddress(last_last_fp, &last_fp)) {
+ BPLOG(ERROR) << "Unable to read last_fp from last_last_fp: 0x"
+ << std::hex << last_last_fp;
+ return;
+ }
+ // Give up if STACK CFI doesn't agree with frame pointer.
+ if (last_frame->context.iregs[MD_CONTEXT_ARM64_REG_FP] != last_fp)
+ return;
+
+ uint64_t last_lr = 0;
+ if (last_last_fp && !memory_->GetMemoryAtAddress(last_last_fp + 8, &last_lr)) {
+ BPLOG(ERROR) << "Unable to read last_lr from (last_last_fp + 8): 0x"
+ << std::hex << (last_last_fp + 8);
+ return;
+ }
+ last_lr = PtrauthStrip(last_lr);
+
+ last_frame->context.iregs[MD_CONTEXT_ARM64_REG_LR] = last_lr;
+}
+
+bool StackwalkerARM64::ValidInstructionPointerInFrame(const StackFrameARM64& frame) {
+ const uint64_t ip = frame.context.iregs[MD_CONTEXT_ARM64_REG_PC];
+
+ if ((ip < 0x1000) || (ip > 0x000fffffffffffff)) {
+ // The IP points into the first page or above the user space threshold
+ return false;
+ }
+
+ return true;
+}
+
+StackFrame* StackwalkerARM64::GetCallerFrame(const CallStack* stack,
+ bool stack_scan_allowed) {
+ if (!memory_ || !stack) {
+ BPLOG(ERROR) << "Can't get caller frame without memory or stack";
+ return NULL;
+ }
+
+ const vector<StackFrame*> &frames = *stack->frames();
+ StackFrameARM64* last_frame = static_cast<StackFrameARM64*>(frames.back());
+ scoped_ptr<StackFrameARM64> frame;
+
+ // See if there is DWARF call frame information covering this address.
+ scoped_ptr<CFIFrameInfo> cfi_frame_info(
+ frame_symbolizer_->FindCFIFrameInfo(last_frame));
+ if (cfi_frame_info.get())
+ frame.reset(GetCallerByCFIFrameInfo(frames, cfi_frame_info.get()));
+
+ // If CFI failed, or there wasn't CFI available, fall back to frame pointer.
+ if (!frame.get() || !ValidInstructionPointerInFrame(*frame))
+ frame.reset(GetCallerByFramePointer(frames));
+
+ // If everything failed, fall back to stack scanning.
+ if (stack_scan_allowed &&
+ (!frame.get() || !ValidInstructionPointerInFrame(*frame)))
+ frame.reset(GetCallerByStackScan(frames));
+
+ // If nothing worked, tell the caller.
+ if (!frame.get())
+ return NULL;
+
+ // Should we terminate the stack walk? (end-of-stack or broken invariant)
+ if (TerminateWalk(frame->context.iregs[MD_CONTEXT_ARM64_REG_PC],
+ frame->context.iregs[MD_CONTEXT_ARM64_REG_SP],
+ last_frame->context.iregs[MD_CONTEXT_ARM64_REG_SP],
+ frames.size() == 1)) {
+ return NULL;
+ }
+
+ // The new frame's context's PC is the return address, which is one
+ // instruction past the instruction that caused us to arrive at the callee.
+ // ARM64 instructions have a uniform 4-byte encoding, so subtracting 4 off
+ // the return address gets back to the beginning of the call instruction.
+ // Callers that require the exact return address value may access
+ // frame->context.iregs[MD_CONTEXT_ARM64_REG_PC].
+ frame->instruction = frame->context.iregs[MD_CONTEXT_ARM64_REG_PC] - 4;
+
+ return frame.release();
+}
+
+
+} // namespace google_breakpad
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_arm64.h b/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_arm64.h
new file mode 100644
index 0000000000..3f9e4f19c4
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_arm64.h
@@ -0,0 +1,121 @@
+// -*- 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.
+
+// stackwalker_arm64.h: arm64-specific stackwalker.
+//
+// Provides stack frames given arm64 register context and a memory region
+// corresponding to an arm64 stack.
+//
+// Author: Mark Mentovai, Ted Mielczarek, Colin Blundell
+
+
+#ifndef PROCESSOR_STACKWALKER_ARM64_H__
+#define PROCESSOR_STACKWALKER_ARM64_H__
+
+#include "google_breakpad/common/breakpad_types.h"
+#include "google_breakpad/common/minidump_format.h"
+#include "google_breakpad/processor/stackwalker.h"
+
+namespace google_breakpad {
+
+class CodeModules;
+
+class StackwalkerARM64 : public Stackwalker {
+ public:
+ // context is an arm64 context object that gives access to arm64-specific
+ // register state corresponding to the innermost called frame to be
+ // included in the stack. The other arguments are passed directly through
+ // to the base Stackwalker constructor.
+ StackwalkerARM64(const SystemInfo* system_info,
+ const MDRawContextARM64* context,
+ MemoryRegion* memory,
+ const CodeModules* modules,
+ StackFrameSymbolizer* frame_symbolizer);
+
+ // Change the context validity mask of the frame returned by
+ // GetContextFrame to VALID. This is only for use by unit tests; the
+ // default behavior is correct for all application code.
+ void SetContextFrameValidity(uint64_t valid) {
+ context_frame_validity_ = valid;
+ }
+
+ private:
+ // Strip pointer authentication codes from an address.
+ uint64_t PtrauthStrip(uint64_t ptr);
+
+ // Implementation of Stackwalker, using arm64 context and stack conventions.
+ virtual StackFrame* GetContextFrame();
+ virtual StackFrame* GetCallerFrame(const CallStack* stack,
+ bool stack_scan_allowed);
+
+ // Use cfi_frame_info (derived from STACK CFI records) to construct
+ // the frame that called frames.back(). The caller takes ownership
+ // of the returned frame. Return NULL on failure.
+ StackFrameARM64* GetCallerByCFIFrameInfo(const vector<StackFrame*> &frames,
+ CFIFrameInfo* cfi_frame_info);
+
+ // Use the frame pointer. The caller takes ownership of the returned frame.
+ // Return NULL on failure.
+ StackFrameARM64* GetCallerByFramePointer(const vector<StackFrame*> &frames);
+
+ // Scan the stack for plausible return addresses. The caller takes ownership
+ // of the returned frame. Return NULL on failure.
+ StackFrameARM64* GetCallerByStackScan(const vector<StackFrame*> &frames);
+
+ // GetCallerByFramePointer() depends on the previous frame having recovered
+ // x30($LR) which may not have been done when using CFI.
+ // This function recovers $LR in the previous frame by using the frame-pointer
+ // two frames back to read it from the stack.
+ void CorrectRegLRByFramePointer(const vector<StackFrame*>& frames,
+ StackFrameARM64* last_frame);
+
+ // Return true if the instruction pointer points into the first 4KiB of memory
+ bool ValidInstructionPointerInFrame(const StackFrameARM64& frame);
+
+ // Stores the CPU context corresponding to the youngest stack frame, to
+ // be returned by GetContextFrame.
+ const MDRawContextARM64* context_;
+
+ // Validity mask for youngest stack frame. This is always
+ // CONTEXT_VALID_ALL in real use; it is only changeable for the sake of
+ // unit tests.
+ uint64_t context_frame_validity_;
+
+ // A mask of the valid address bits, determined from the address range of
+ // modules_.
+ uint64_t address_range_mask_;
+};
+
+
+} // namespace google_breakpad
+
+
+#endif // PROCESSOR_STACKWALKER_ARM64_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_arm64_unittest.cc b/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_arm64_unittest.cc
new file mode 100644
index 0000000000..d86fa12779
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_arm64_unittest.cc
@@ -0,0 +1,881 @@
+// 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>
+
+// stackwalker_arm64_unittest.cc: Unit tests for StackwalkerARM64 class.
+
+#include <string.h>
+#include <string>
+#include <vector>
+
+#include "breakpad_googletest_includes.h"
+#include "common/test_assembler.h"
+#include "common/using_std_string.h"
+#include "google_breakpad/common/minidump_format.h"
+#include "google_breakpad/processor/basic_source_line_resolver.h"
+#include "google_breakpad/processor/call_stack.h"
+#include "google_breakpad/processor/code_module.h"
+#include "google_breakpad/processor/source_line_resolver_interface.h"
+#include "google_breakpad/processor/stack_frame_cpu.h"
+#include "processor/stackwalker_unittest_utils.h"
+#include "processor/stackwalker_arm64.h"
+#include "processor/windows_frame_info.h"
+
+using google_breakpad::BasicSourceLineResolver;
+using google_breakpad::CallStack;
+using google_breakpad::CodeModule;
+using google_breakpad::StackFrameSymbolizer;
+using google_breakpad::StackFrame;
+using google_breakpad::StackFrameARM64;
+using google_breakpad::Stackwalker;
+using google_breakpad::StackwalkerARM64;
+using google_breakpad::SystemInfo;
+using google_breakpad::WindowsFrameInfo;
+using google_breakpad::test_assembler::kLittleEndian;
+using google_breakpad::test_assembler::Label;
+using google_breakpad::test_assembler::Section;
+using std::vector;
+using testing::_;
+using testing::AnyNumber;
+using testing::DoAll;
+using testing::Return;
+using testing::SetArgumentPointee;
+using testing::Test;
+
+class StackwalkerARM64Fixture {
+ public:
+ StackwalkerARM64Fixture()
+ : stack_section(kLittleEndian),
+ // Give the two modules reasonable standard locations and names
+ // for tests to play with.
+ module1(0x40000000, 0x10000, "module1", "version1"),
+ module2(0x50000000, 0x10000, "module2", "version2") {
+ // Identify the system as an iOS system.
+ system_info.os = "iOS";
+ system_info.os_short = "ios";
+ system_info.cpu = "arm64";
+ system_info.cpu_info = "";
+
+ // Put distinctive values in the raw CPU context.
+ BrandContext(&raw_context);
+
+ // Create some modules with some stock debugging information.
+ modules.Add(&module1);
+ modules.Add(&module2);
+
+ // By default, none of the modules have symbol info; call
+ // SetModuleSymbols to override this.
+ EXPECT_CALL(supplier, GetCStringSymbolData(_, _, _, _, _))
+ .WillRepeatedly(Return(MockSymbolSupplier::NOT_FOUND));
+
+ // Avoid GMOCK WARNING "Uninteresting mock function call - returning
+ // directly" for FreeSymbolData().
+ EXPECT_CALL(supplier, FreeSymbolData(_)).Times(AnyNumber());
+
+ // Reset max_frames_scanned since it's static.
+ Stackwalker::set_max_frames_scanned(1024);
+ }
+
+ // Set the Breakpad symbol information that supplier should return for
+ // MODULE to INFO.
+ void SetModuleSymbols(MockCodeModule *module, const string &info) {
+ size_t buffer_size;
+ char *buffer = supplier.CopySymbolDataAndOwnTheCopy(info, &buffer_size);
+ EXPECT_CALL(supplier, GetCStringSymbolData(module, &system_info, _, _, _))
+ .WillRepeatedly(DoAll(SetArgumentPointee<3>(buffer),
+ SetArgumentPointee<4>(buffer_size),
+ Return(MockSymbolSupplier::FOUND)));
+ }
+
+ // Populate stack_region with the contents of stack_section. Use
+ // stack_section.start() as the region's starting address.
+ void RegionFromSection() {
+ string contents;
+ ASSERT_TRUE(stack_section.GetContents(&contents));
+ stack_region.Init(stack_section.start().Value(), contents);
+ }
+
+ // Fill RAW_CONTEXT with pseudo-random data, for round-trip checking.
+ void BrandContext(MDRawContextARM64 *raw_context) {
+ uint8_t x = 173;
+ for (size_t i = 0; i < sizeof(*raw_context); i++)
+ reinterpret_cast<uint8_t *>(raw_context)[i] = (x += 17);
+ }
+
+ SystemInfo system_info;
+ MDRawContextARM64 raw_context;
+ Section stack_section;
+ MockMemoryRegion stack_region;
+ MockCodeModule module1;
+ MockCodeModule module2;
+ MockCodeModules modules;
+ MockSymbolSupplier supplier;
+ BasicSourceLineResolver resolver;
+ CallStack call_stack;
+ const vector<StackFrame *> *frames;
+};
+
+class SanityCheck: public StackwalkerARM64Fixture, public Test { };
+
+TEST_F(SanityCheck, NoResolver) {
+ // Since the context's frame pointer is garbage, the stack walk will end after
+ // the first frame.
+ StackFrameSymbolizer frame_symbolizer(NULL, NULL);
+ StackwalkerARM64 walker(&system_info, &raw_context, &stack_region, &modules,
+ &frame_symbolizer);
+ // This should succeed even without a resolver or supplier.
+ vector<const CodeModule*> modules_without_symbols;
+ vector<const CodeModule*> modules_with_corrupt_symbols;
+ ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
+ &modules_with_corrupt_symbols));
+ ASSERT_EQ(0U, modules_without_symbols.size());
+ ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
+ frames = call_stack.frames();
+ ASSERT_EQ(1U, frames->size());
+ StackFrameARM64 *frame = static_cast<StackFrameARM64 *>(frames->at(0));
+ // Check that the values from the original raw context made it
+ // through to the context in the stack frame.
+ EXPECT_EQ(0, memcmp(&raw_context, &frame->context, sizeof(raw_context)));
+}
+
+class GetContextFrame: public StackwalkerARM64Fixture, public Test { };
+
+// The stackwalker should be able to produce the context frame even
+// without stack memory present.
+TEST_F(GetContextFrame, NoStackMemory) {
+ StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
+ StackwalkerARM64 walker(&system_info, &raw_context, NULL, &modules,
+ &frame_symbolizer);
+ vector<const CodeModule*> modules_without_symbols;
+ vector<const CodeModule*> modules_with_corrupt_symbols;
+ ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
+ &modules_with_corrupt_symbols));
+ ASSERT_EQ(0U, modules_without_symbols.size());
+ ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
+ frames = call_stack.frames();
+ ASSERT_EQ(1U, frames->size());
+ StackFrameARM64 *frame = static_cast<StackFrameARM64 *>(frames->at(0));
+ // Check that the values from the original raw context made it
+ // through to the context in the stack frame.
+ EXPECT_EQ(0, memcmp(&raw_context, &frame->context, sizeof(raw_context)));
+}
+
+class GetCallerFrame: public StackwalkerARM64Fixture, public Test { };
+
+TEST_F(GetCallerFrame, ScanWithoutSymbols) {
+ // When the stack walker resorts to scanning the stack,
+ // only addresses located within loaded modules are
+ // considered valid return addresses.
+ // Force scanning through three frames to ensure that the
+ // stack pointer is set properly in scan-recovered frames.
+ stack_section.start() = 0x80000000;
+ uint64_t return_address1 = 0x50000100;
+ uint64_t return_address2 = 0x50000900;
+ Label frame1_sp, frame2_sp;
+ stack_section
+ // frame 0
+ .Append(16, 0) // space
+
+ .D64(0x40090000) // junk that's not
+ .D64(0x60000000) // a return address
+
+ .D64(return_address1) // actual return address
+ // frame 1
+ .Mark(&frame1_sp)
+ .Append(16, 0) // space
+
+ .D64(0xF0000000) // more junk
+ .D64(0x0000000D)
+
+ .D64(return_address2) // actual return address
+ // frame 2
+ .Mark(&frame2_sp)
+ .Append(64, 0); // end of stack
+ RegionFromSection();
+
+ raw_context.iregs[MD_CONTEXT_ARM64_REG_PC] = 0x40005510;
+ raw_context.iregs[MD_CONTEXT_ARM64_REG_SP] = stack_section.start().Value();
+
+ StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
+ StackwalkerARM64 walker(&system_info, &raw_context, &stack_region, &modules,
+ &frame_symbolizer);
+ vector<const CodeModule*> modules_without_symbols;
+ vector<const CodeModule*> modules_with_corrupt_symbols;
+ ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
+ &modules_with_corrupt_symbols));
+ ASSERT_EQ(2U, modules_without_symbols.size());
+ ASSERT_EQ("module1", modules_without_symbols[0]->debug_file());
+ ASSERT_EQ("module2", modules_without_symbols[1]->debug_file());
+ ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
+ frames = call_stack.frames();
+ ASSERT_EQ(3U, frames->size());
+
+ StackFrameARM64 *frame0 = static_cast<StackFrameARM64 *>(frames->at(0));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
+ ASSERT_EQ(StackFrameARM64::CONTEXT_VALID_ALL,
+ frame0->context_validity);
+ EXPECT_EQ(0, memcmp(&raw_context, &frame0->context, sizeof(raw_context)));
+
+ StackFrameARM64 *frame1 = static_cast<StackFrameARM64 *>(frames->at(1));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust);
+ ASSERT_EQ((StackFrameARM64::CONTEXT_VALID_PC |
+ StackFrameARM64::CONTEXT_VALID_SP),
+ frame1->context_validity);
+ EXPECT_EQ(return_address1, frame1->context.iregs[MD_CONTEXT_ARM64_REG_PC]);
+ EXPECT_EQ(frame1_sp.Value(), frame1->context.iregs[MD_CONTEXT_ARM64_REG_SP]);
+
+ StackFrameARM64 *frame2 = static_cast<StackFrameARM64 *>(frames->at(2));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame2->trust);
+ ASSERT_EQ((StackFrameARM64::CONTEXT_VALID_PC |
+ StackFrameARM64::CONTEXT_VALID_SP),
+ frame2->context_validity);
+ EXPECT_EQ(return_address2, frame2->context.iregs[MD_CONTEXT_ARM64_REG_PC]);
+ EXPECT_EQ(frame2_sp.Value(), frame2->context.iregs[MD_CONTEXT_ARM64_REG_SP]);
+}
+
+TEST_F(GetCallerFrame, ScanWithFunctionSymbols) {
+ // During stack scanning, if a potential return address
+ // is located within a loaded module that has symbols,
+ // it is only considered a valid return address if it
+ // lies within a function's bounds.
+ stack_section.start() = 0x80000000;
+ uint64_t return_address = 0x50000200;
+ Label frame1_sp;
+
+ stack_section
+ // frame 0
+ .Append(16, 0) // space
+
+ .D64(0x40090000) // junk that's not
+ .D64(0x60000000) // a return address
+
+ .D64(0x40001000) // a couple of plausible addresses
+ .D64(0x5000F000) // that are not within functions
+
+ .D64(return_address) // actual return address
+ // frame 1
+ .Mark(&frame1_sp)
+ .Append(64, 0); // end of stack
+ RegionFromSection();
+
+ raw_context.iregs[MD_CONTEXT_ARM64_REG_PC] = 0x40000200;
+ raw_context.iregs[MD_CONTEXT_ARM64_REG_SP] = stack_section.start().Value();
+
+ SetModuleSymbols(&module1,
+ // The youngest frame's function.
+ "FUNC 100 400 10 monotreme\n");
+ SetModuleSymbols(&module2,
+ // The calling frame's function.
+ "FUNC 100 400 10 marsupial\n");
+
+ StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
+ StackwalkerARM64 walker(&system_info, &raw_context, &stack_region, &modules,
+ &frame_symbolizer);
+ vector<const CodeModule*> modules_without_symbols;
+ vector<const CodeModule*> modules_with_corrupt_symbols;
+ ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
+ &modules_with_corrupt_symbols));
+ ASSERT_EQ(0U, modules_without_symbols.size());
+ ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
+ frames = call_stack.frames();
+ ASSERT_EQ(2U, frames->size());
+
+ StackFrameARM64 *frame0 = static_cast<StackFrameARM64 *>(frames->at(0));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
+ ASSERT_EQ(StackFrameARM64::CONTEXT_VALID_ALL,
+ frame0->context_validity);
+ EXPECT_EQ(0, memcmp(&raw_context, &frame0->context, sizeof(raw_context)));
+ EXPECT_EQ("monotreme", frame0->function_name);
+ EXPECT_EQ(0x40000100ULL, frame0->function_base);
+
+ StackFrameARM64 *frame1 = static_cast<StackFrameARM64 *>(frames->at(1));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust);
+ ASSERT_EQ((StackFrameARM64::CONTEXT_VALID_PC |
+ StackFrameARM64::CONTEXT_VALID_SP),
+ frame1->context_validity);
+ EXPECT_EQ(return_address, frame1->context.iregs[MD_CONTEXT_ARM64_REG_PC]);
+ EXPECT_EQ(frame1_sp.Value(), frame1->context.iregs[MD_CONTEXT_ARM64_REG_SP]);
+ EXPECT_EQ("marsupial", frame1->function_name);
+ EXPECT_EQ(0x50000100ULL, frame1->function_base);
+}
+
+TEST_F(GetCallerFrame, ScanFirstFrame) {
+ // If the stackwalker resorts to stack scanning, it will scan much
+ // farther to find the caller of the context frame.
+ stack_section.start() = 0x80000000;
+ uint64_t return_address1 = 0x50000100;
+ uint64_t return_address2 = 0x50000900;
+ Label frame1_sp, frame2_sp;
+ stack_section
+ // frame 0
+ .Append(32, 0) // space
+
+ .D64(0x40090000) // junk that's not
+ .D64(0x60000000) // a return address
+
+ .Append(96, 0) // more space
+
+ .D64(return_address1) // actual return address
+ // frame 1
+ .Mark(&frame1_sp)
+ .Append(32, 0) // space
+
+ .D64(0xF0000000) // more junk
+ .D64(0x0000000D)
+
+ .Append(336, 0) // more space
+
+ .D64(return_address2) // actual return address
+ // (won't be found)
+ // frame 2
+ .Mark(&frame2_sp)
+ .Append(64, 0); // end of stack
+ RegionFromSection();
+
+ raw_context.iregs[MD_CONTEXT_ARM64_REG_PC] = 0x40005510;
+ raw_context.iregs[MD_CONTEXT_ARM64_REG_SP] = stack_section.start().Value();
+
+ StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
+ StackwalkerARM64 walker(&system_info, &raw_context, &stack_region, &modules,
+ &frame_symbolizer);
+ vector<const CodeModule*> modules_without_symbols;
+ vector<const CodeModule*> modules_with_corrupt_symbols;
+ ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
+ &modules_with_corrupt_symbols));
+ ASSERT_EQ(2U, modules_without_symbols.size());
+ ASSERT_EQ("module1", modules_without_symbols[0]->debug_file());
+ ASSERT_EQ("module2", modules_without_symbols[1]->debug_file());
+ ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
+ frames = call_stack.frames();
+ ASSERT_EQ(2U, frames->size());
+
+ StackFrameARM64 *frame0 = static_cast<StackFrameARM64 *>(frames->at(0));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
+ ASSERT_EQ(StackFrameARM64::CONTEXT_VALID_ALL,
+ frame0->context_validity);
+ EXPECT_EQ(0, memcmp(&raw_context, &frame0->context, sizeof(raw_context)));
+
+ StackFrameARM64 *frame1 = static_cast<StackFrameARM64 *>(frames->at(1));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust);
+ ASSERT_EQ((StackFrameARM64::CONTEXT_VALID_PC |
+ StackFrameARM64::CONTEXT_VALID_SP),
+ frame1->context_validity);
+ EXPECT_EQ(return_address1, frame1->context.iregs[MD_CONTEXT_ARM64_REG_PC]);
+ EXPECT_EQ(frame1_sp.Value(), frame1->context.iregs[MD_CONTEXT_ARM64_REG_SP]);
+}
+
+// Test that set_max_frames_scanned prevents using stack scanning
+// to find caller frames.
+TEST_F(GetCallerFrame, ScanningNotAllowed) {
+ // When the stack walker resorts to scanning the stack,
+ // only addresses located within loaded modules are
+ // considered valid return addresses.
+ stack_section.start() = 0x80000000;
+ uint64_t return_address1 = 0x50000100;
+ uint64_t return_address2 = 0x50000900;
+ Label frame1_sp, frame2_sp;
+ stack_section
+ // frame 0
+ .Append(16, 0) // space
+
+ .D64(0x40090000) // junk that's not
+ .D64(0x60000000) // a return address
+
+ .D64(return_address1) // actual return address
+ // frame 1
+ .Mark(&frame1_sp)
+ .Append(16, 0) // space
+
+ .D64(0xF0000000) // more junk
+ .D64(0x0000000D)
+
+ .D64(return_address2) // actual return address
+ // frame 2
+ .Mark(&frame2_sp)
+ .Append(64, 0); // end of stack
+ RegionFromSection();
+
+ raw_context.iregs[MD_CONTEXT_ARM64_REG_PC] = 0x40005510;
+ raw_context.iregs[MD_CONTEXT_ARM64_REG_SP] = stack_section.start().Value();
+
+ StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
+ StackwalkerARM64 walker(&system_info, &raw_context, &stack_region, &modules,
+ &frame_symbolizer);
+ Stackwalker::set_max_frames_scanned(0);
+
+ vector<const CodeModule*> modules_without_symbols;
+ vector<const CodeModule*> modules_with_corrupt_symbols;
+ ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
+ &modules_with_corrupt_symbols));
+ ASSERT_EQ(1U, modules_without_symbols.size());
+ ASSERT_EQ("module1", modules_without_symbols[0]->debug_file());
+ ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
+ frames = call_stack.frames();
+ ASSERT_EQ(1U, frames->size());
+
+ StackFrameARM64 *frame0 = static_cast<StackFrameARM64 *>(frames->at(0));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
+ ASSERT_EQ(StackFrameARM64::CONTEXT_VALID_ALL,
+ frame0->context_validity);
+ EXPECT_EQ(0, memcmp(&raw_context, &frame0->context, sizeof(raw_context)));
+}
+
+class GetFramesByFramePointer: public StackwalkerARM64Fixture, public Test { };
+
+TEST_F(GetFramesByFramePointer, OnlyFramePointer) {
+ stack_section.start() = 0x80000000;
+ uint64_t return_address1 = 0x50000100;
+ uint64_t return_address2 = 0x50000900;
+ Label frame1_sp, frame2_sp;
+ Label frame1_fp, frame2_fp;
+ stack_section
+ // frame 0
+ .Append(64, 0) // Whatever values on the stack.
+ .D64(0x0000000D) // junk that's not
+ .D64(0xF0000000) // a return address.
+
+ .Mark(&frame1_fp) // Next fp will point to the next value.
+ .D64(frame2_fp) // Save current frame pointer.
+ .D64(return_address2) // Save current link register.
+ .Mark(&frame1_sp)
+
+ // frame 1
+ .Append(64, 0) // Whatever values on the stack.
+ .D64(0x0000000D) // junk that's not
+ .D64(0xF0000000) // a return address.
+
+ .Mark(&frame2_fp)
+ .D64(0)
+ .D64(0)
+ .Mark(&frame2_sp)
+
+ // frame 2
+ .Append(64, 0) // Whatever values on the stack.
+ .D64(0x0000000D) // junk that's not
+ .D64(0xF0000000); // a return address.
+ RegionFromSection();
+
+
+ raw_context.iregs[MD_CONTEXT_ARM64_REG_PC] = 0x40005510;
+ raw_context.iregs[MD_CONTEXT_ARM64_REG_LR] = return_address1;
+ raw_context.iregs[MD_CONTEXT_ARM64_REG_FP] = frame1_fp.Value();
+ raw_context.iregs[MD_CONTEXT_ARM64_REG_SP] = stack_section.start().Value();
+
+ StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
+ StackwalkerARM64 walker(&system_info, &raw_context,
+ &stack_region, &modules, &frame_symbolizer);
+
+ vector<const CodeModule*> modules_without_symbols;
+ vector<const CodeModule*> modules_with_corrupt_symbols;
+ ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
+ &modules_with_corrupt_symbols));
+ ASSERT_EQ(2U, modules_without_symbols.size());
+ ASSERT_EQ("module1", modules_without_symbols[0]->debug_file());
+ ASSERT_EQ("module2", modules_without_symbols[1]->debug_file());
+ ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
+ frames = call_stack.frames();
+ ASSERT_EQ(3U, frames->size());
+
+ StackFrameARM64 *frame0 = static_cast<StackFrameARM64 *>(frames->at(0));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
+ ASSERT_EQ(StackFrameARM64::CONTEXT_VALID_ALL,
+ frame0->context_validity);
+ EXPECT_EQ(0, memcmp(&raw_context, &frame0->context, sizeof(raw_context)));
+
+ StackFrameARM64 *frame1 = static_cast<StackFrameARM64 *>(frames->at(1));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_FP, frame1->trust);
+ ASSERT_EQ((StackFrameARM64::CONTEXT_VALID_PC |
+ StackFrameARM64::CONTEXT_VALID_LR |
+ StackFrameARM64::CONTEXT_VALID_FP |
+ StackFrameARM64::CONTEXT_VALID_SP),
+ frame1->context_validity);
+ EXPECT_EQ(return_address1, frame1->context.iregs[MD_CONTEXT_ARM64_REG_PC]);
+ EXPECT_EQ(return_address2, frame1->context.iregs[MD_CONTEXT_ARM64_REG_LR]);
+ EXPECT_EQ(frame1_sp.Value(), frame1->context.iregs[MD_CONTEXT_ARM64_REG_SP]);
+ EXPECT_EQ(frame2_fp.Value(),
+ frame1->context.iregs[MD_CONTEXT_ARM64_REG_FP]);
+
+ StackFrameARM64 *frame2 = static_cast<StackFrameARM64 *>(frames->at(2));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_FP, frame2->trust);
+ ASSERT_EQ((StackFrameARM64::CONTEXT_VALID_PC |
+ StackFrameARM64::CONTEXT_VALID_LR |
+ StackFrameARM64::CONTEXT_VALID_FP |
+ StackFrameARM64::CONTEXT_VALID_SP),
+ frame2->context_validity);
+ EXPECT_EQ(return_address2, frame2->context.iregs[MD_CONTEXT_ARM64_REG_PC]);
+ EXPECT_EQ(0U, frame2->context.iregs[MD_CONTEXT_ARM64_REG_LR]);
+ EXPECT_EQ(frame2_sp.Value(), frame2->context.iregs[MD_CONTEXT_ARM64_REG_SP]);
+ EXPECT_EQ(0U, frame2->context.iregs[MD_CONTEXT_ARM64_REG_FP]);
+}
+
+struct CFIFixture: public StackwalkerARM64Fixture {
+ CFIFixture() {
+ // Provide a bunch of STACK CFI records; we'll walk to the caller
+ // from every point in this series, expecting to find the same set
+ // of register values.
+ SetModuleSymbols(&module1,
+ // The youngest frame's function.
+ "FUNC 4000 1000 10 enchiridion\n"
+ // Initially, nothing has been pushed on the stack,
+ // and the return address is still in the link
+ // register (x30).
+ "STACK CFI INIT 4000 100 .cfa: sp 0 + .ra: x30\n"
+ // Push x19, x20, the frame pointer and the link register.
+ "STACK CFI 4001 .cfa: sp 32 + .ra: .cfa -8 + ^"
+ " x19: .cfa -32 + ^ x20: .cfa -24 + ^ "
+ " x29: .cfa -16 + ^\n"
+ // Save x19..x22 in x0..x3: verify that we populate
+ // the youngest frame with all the values we have.
+ "STACK CFI 4002 x19: x0 x20: x1 x21: x2 x22: x3\n"
+ // Restore x19..x22. Save the non-callee-saves register x1.
+ "STACK CFI 4003 .cfa: sp 40 + x1: .cfa 40 - ^"
+ " x19: x19 x20: x20 x21: x21 x22: x22\n"
+ // Move the .cfa back eight bytes, to point at the return
+ // address, and restore the sp explicitly.
+ "STACK CFI 4005 .cfa: sp 32 + x1: .cfa 32 - ^"
+ " x29: .cfa 8 - ^ .ra: .cfa ^ sp: .cfa 8 +\n"
+ // Recover the PC explicitly from a new stack slot;
+ // provide garbage for the .ra.
+ "STACK CFI 4006 .cfa: sp 40 + pc: .cfa 40 - ^\n"
+
+ // The calling function.
+ "FUNC 5000 1000 10 epictetus\n"
+ // Mark it as end of stack.
+ "STACK CFI INIT 5000 1000 .cfa: 0 .ra: 0\n"
+
+ // A function whose CFI makes the stack pointer
+ // go backwards.
+ "FUNC 6000 1000 20 palinal\n"
+ "STACK CFI INIT 6000 1000 .cfa: sp 8 - .ra: x30\n"
+
+ // A function with CFI expressions that can't be
+ // evaluated.
+ "FUNC 7000 1000 20 rhetorical\n"
+ "STACK CFI INIT 7000 1000 .cfa: moot .ra: ambiguous\n");
+
+ // Provide some distinctive values for the caller's registers.
+ expected.iregs[MD_CONTEXT_ARM64_REG_PC] = 0x0000000040005510L;
+ expected.iregs[MD_CONTEXT_ARM64_REG_SP] = 0x0000000080000000L;
+ expected.iregs[19] = 0x5e68b5d5b5d55e68L;
+ expected.iregs[20] = 0x34f3ebd1ebd134f3L;
+ expected.iregs[21] = 0x74bca31ea31e74bcL;
+ expected.iregs[22] = 0x16b32dcb2dcb16b3L;
+ expected.iregs[23] = 0x21372ada2ada2137L;
+ expected.iregs[24] = 0x557dbbbbbbbb557dL;
+ expected.iregs[25] = 0x8ca748bf48bf8ca7L;
+ expected.iregs[26] = 0x21f0ab46ab4621f0L;
+ expected.iregs[27] = 0x146732b732b71467L;
+ expected.iregs[28] = 0xa673645fa673645fL;
+ expected.iregs[MD_CONTEXT_ARM64_REG_FP] = 0xe11081128112e110L;
+
+ // Expect CFI to recover all callee-saves registers. Since CFI is the
+ // only stack frame construction technique we have, aside from the
+ // context frame itself, there's no way for us to have a set of valid
+ // registers smaller than this.
+ expected_validity = (StackFrameARM64::CONTEXT_VALID_PC |
+ StackFrameARM64::CONTEXT_VALID_SP |
+ StackFrameARM64::CONTEXT_VALID_X19 |
+ StackFrameARM64::CONTEXT_VALID_X20 |
+ StackFrameARM64::CONTEXT_VALID_X21 |
+ StackFrameARM64::CONTEXT_VALID_X22 |
+ StackFrameARM64::CONTEXT_VALID_X23 |
+ StackFrameARM64::CONTEXT_VALID_X24 |
+ StackFrameARM64::CONTEXT_VALID_X25 |
+ StackFrameARM64::CONTEXT_VALID_X26 |
+ StackFrameARM64::CONTEXT_VALID_X27 |
+ StackFrameARM64::CONTEXT_VALID_X28 |
+ StackFrameARM64::CONTEXT_VALID_FP);
+
+ // By default, context frames provide all registers, as normal.
+ context_frame_validity = StackFrameARM64::CONTEXT_VALID_ALL;
+
+ // By default, registers are unchanged.
+ raw_context = expected;
+ }
+
+ // Walk the stack, using stack_section as the contents of the stack
+ // and raw_context as the current register values. (Set the stack
+ // pointer to the stack's starting address.) Expect two stack
+ // frames; in the older frame, expect the callee-saves registers to
+ // have values matching those in 'expected'.
+ void CheckWalk() {
+ RegionFromSection();
+ raw_context.iregs[MD_CONTEXT_ARM64_REG_SP] = stack_section.start().Value();
+
+ StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
+ StackwalkerARM64 walker(&system_info, &raw_context, &stack_region,
+ &modules, &frame_symbolizer);
+ walker.SetContextFrameValidity(context_frame_validity);
+ vector<const CodeModule*> modules_without_symbols;
+ vector<const CodeModule*> modules_with_corrupt_symbols;
+ ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
+ &modules_with_corrupt_symbols));
+ ASSERT_EQ(0U, modules_without_symbols.size());
+ ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
+ frames = call_stack.frames();
+ ASSERT_EQ(2U, frames->size());
+
+ StackFrameARM64 *frame0 = static_cast<StackFrameARM64 *>(frames->at(0));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
+ ASSERT_EQ(context_frame_validity, frame0->context_validity);
+ EXPECT_EQ("enchiridion", frame0->function_name);
+ EXPECT_EQ(0x0000000040004000UL, frame0->function_base);
+
+ StackFrameARM64 *frame1 = static_cast<StackFrameARM64 *>(frames->at(1));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame1->trust);
+ ASSERT_EQ(expected_validity, frame1->context_validity);
+ if (expected_validity & StackFrameARM64::CONTEXT_VALID_X1)
+ EXPECT_EQ(expected.iregs[1], frame1->context.iregs[1]);
+ if (expected_validity & StackFrameARM64::CONTEXT_VALID_X19)
+ EXPECT_EQ(expected.iregs[19], frame1->context.iregs[19]);
+ if (expected_validity & StackFrameARM64::CONTEXT_VALID_X20)
+ EXPECT_EQ(expected.iregs[20], frame1->context.iregs[20]);
+ if (expected_validity & StackFrameARM64::CONTEXT_VALID_X21)
+ EXPECT_EQ(expected.iregs[21], frame1->context.iregs[21]);
+ if (expected_validity & StackFrameARM64::CONTEXT_VALID_X22)
+ EXPECT_EQ(expected.iregs[22], frame1->context.iregs[22]);
+ if (expected_validity & StackFrameARM64::CONTEXT_VALID_X23)
+ EXPECT_EQ(expected.iregs[23], frame1->context.iregs[23]);
+ if (expected_validity & StackFrameARM64::CONTEXT_VALID_X24)
+ EXPECT_EQ(expected.iregs[24], frame1->context.iregs[24]);
+ if (expected_validity & StackFrameARM64::CONTEXT_VALID_X25)
+ EXPECT_EQ(expected.iregs[25], frame1->context.iregs[25]);
+ if (expected_validity & StackFrameARM64::CONTEXT_VALID_X26)
+ EXPECT_EQ(expected.iregs[26], frame1->context.iregs[26]);
+ if (expected_validity & StackFrameARM64::CONTEXT_VALID_X27)
+ EXPECT_EQ(expected.iregs[27], frame1->context.iregs[27]);
+ if (expected_validity & StackFrameARM64::CONTEXT_VALID_X28)
+ EXPECT_EQ(expected.iregs[28], frame1->context.iregs[28]);
+ if (expected_validity & StackFrameARM64::CONTEXT_VALID_FP)
+ EXPECT_EQ(expected.iregs[MD_CONTEXT_ARM64_REG_FP],
+ frame1->context.iregs[MD_CONTEXT_ARM64_REG_FP]);
+
+ // We would never have gotten a frame in the first place if the SP
+ // and PC weren't valid or ->instruction weren't set.
+ EXPECT_EQ(expected.iregs[MD_CONTEXT_ARM64_REG_SP],
+ frame1->context.iregs[MD_CONTEXT_ARM64_REG_SP]);
+ EXPECT_EQ(expected.iregs[MD_CONTEXT_ARM64_REG_PC],
+ frame1->context.iregs[MD_CONTEXT_ARM64_REG_PC]);
+ EXPECT_EQ(expected.iregs[MD_CONTEXT_ARM64_REG_PC],
+ frame1->instruction + 4);
+ EXPECT_EQ("epictetus", frame1->function_name);
+ }
+
+ // The values we expect to find for the caller's registers.
+ MDRawContextARM64 expected;
+
+ // The validity mask for expected.
+ uint64_t expected_validity;
+
+ // The validity mask to impose on the context frame.
+ uint64_t context_frame_validity;
+};
+
+class CFI: public CFIFixture, public Test { };
+
+TEST_F(CFI, At4000) {
+ stack_section.start() = expected.iregs[MD_CONTEXT_ARM64_REG_SP];
+ raw_context.iregs[MD_CONTEXT_ARM64_REG_PC] = 0x0000000040004000L;
+ raw_context.iregs[MD_CONTEXT_ARM64_REG_LR] = 0x0000000040005510L;
+ CheckWalk();
+}
+
+TEST_F(CFI, At4001) {
+ Label frame1_sp = expected.iregs[MD_CONTEXT_ARM64_REG_SP];
+ stack_section
+ .D64(0x5e68b5d5b5d55e68L) // saved x19
+ .D64(0x34f3ebd1ebd134f3L) // saved x20
+ .D64(0xe11081128112e110L) // saved fp
+ .D64(0x0000000040005510L) // return address
+ .Mark(&frame1_sp); // This effectively sets stack_section.start().
+ raw_context.iregs[MD_CONTEXT_ARM64_REG_PC] = 0x0000000040004001L;
+ // distinct callee x19, x20 and fp
+ raw_context.iregs[19] = 0xadc9f635a635adc9L;
+ raw_context.iregs[20] = 0x623135ac35ac6231L;
+ raw_context.iregs[MD_CONTEXT_ARM64_REG_FP] = 0x5fc4be14be145fc4L;
+ CheckWalk();
+}
+
+// As above, but unwind from a context that has only the PC and SP.
+TEST_F(CFI, At4001LimitedValidity) {
+ Label frame1_sp = expected.iregs[MD_CONTEXT_ARM64_REG_SP];
+ stack_section
+ .D64(0x5e68b5d5b5d55e68L) // saved x19
+ .D64(0x34f3ebd1ebd134f3L) // saved x20
+ .D64(0xe11081128112e110L) // saved fp
+ .D64(0x0000000040005510L) // return address
+ .Mark(&frame1_sp); // This effectively sets stack_section.start().
+ context_frame_validity =
+ StackFrameARM64::CONTEXT_VALID_PC | StackFrameARM64::CONTEXT_VALID_SP;
+ raw_context.iregs[MD_CONTEXT_ARM64_REG_PC] = 0x0000000040004001L;
+ raw_context.iregs[MD_CONTEXT_ARM64_REG_FP] = 0x5fc4be14be145fc4L;
+
+ expected_validity = (StackFrameARM64::CONTEXT_VALID_PC
+ | StackFrameARM64::CONTEXT_VALID_SP
+ | StackFrameARM64::CONTEXT_VALID_FP
+ | StackFrameARM64::CONTEXT_VALID_X19
+ | StackFrameARM64::CONTEXT_VALID_X20);
+ CheckWalk();
+}
+
+TEST_F(CFI, At4002) {
+ Label frame1_sp = expected.iregs[MD_CONTEXT_ARM64_REG_SP];
+ stack_section
+ .D64(0xff3dfb81fb81ff3dL) // no longer saved x19
+ .D64(0x34f3ebd1ebd134f3L) // no longer saved x20
+ .D64(0xe11081128112e110L) // saved fp
+ .D64(0x0000000040005510L) // return address
+ .Mark(&frame1_sp); // This effectively sets stack_section.start().
+ raw_context.iregs[MD_CONTEXT_ARM64_REG_PC] = 0x0000000040004002L;
+ raw_context.iregs[0] = 0x5e68b5d5b5d55e68L; // saved x19
+ raw_context.iregs[1] = 0x34f3ebd1ebd134f3L; // saved x20
+ raw_context.iregs[2] = 0x74bca31ea31e74bcL; // saved x21
+ raw_context.iregs[3] = 0x16b32dcb2dcb16b3L; // saved x22
+ raw_context.iregs[19] = 0xadc9f635a635adc9L; // distinct callee x19
+ raw_context.iregs[20] = 0x623135ac35ac6231L; // distinct callee x20
+ raw_context.iregs[21] = 0xac4543564356ac45L; // distinct callee x21
+ raw_context.iregs[22] = 0x2561562f562f2561L; // distinct callee x22
+ // distinct callee fp
+ raw_context.iregs[MD_CONTEXT_ARM64_REG_FP] = 0x5fc4be14be145fc4L;
+ CheckWalk();
+}
+
+TEST_F(CFI, At4003) {
+ Label frame1_sp = expected.iregs[MD_CONTEXT_ARM64_REG_SP];
+ stack_section
+ .D64(0xdd5a48c848c8dd5aL) // saved x1 (even though it's not callee-saves)
+ .D64(0xff3dfb81fb81ff3dL) // no longer saved x19
+ .D64(0x34f3ebd1ebd134f3L) // no longer saved x20
+ .D64(0xe11081128112e110L) // saved fp
+ .D64(0x0000000040005510L) // return address
+ .Mark(&frame1_sp); // This effectively sets stack_section.start().
+ raw_context.iregs[MD_CONTEXT_ARM64_REG_PC] = 0x0000000040004003L;
+ // distinct callee x1 and fp
+ raw_context.iregs[1] = 0xfb756319fb756319L;
+ raw_context.iregs[MD_CONTEXT_ARM64_REG_FP] = 0x5fc4be14be145fc4L;
+ // caller's x1
+ expected.iregs[1] = 0xdd5a48c848c8dd5aL;
+ expected_validity |= StackFrameARM64::CONTEXT_VALID_X1;
+ CheckWalk();
+}
+
+// We have no new rule at module offset 0x4004, so the results here should
+// be the same as those at module offset 0x4003.
+TEST_F(CFI, At4004) {
+ Label frame1_sp = expected.iregs[MD_CONTEXT_ARM64_REG_SP];
+ stack_section
+ .D64(0xdd5a48c848c8dd5aL) // saved x1 (even though it's not callee-saves)
+ .D64(0xff3dfb81fb81ff3dL) // no longer saved x19
+ .D64(0x34f3ebd1ebd134f3L) // no longer saved x20
+ .D64(0xe11081128112e110L) // saved fp
+ .D64(0x0000000040005510L) // return address
+ .Mark(&frame1_sp); // This effectively sets stack_section.start().
+ raw_context.iregs[MD_CONTEXT_ARM64_REG_PC] = 0x0000000040004004L;
+ // distinct callee x1 and fp
+ raw_context.iregs[1] = 0xfb756319fb756319L;
+ raw_context.iregs[MD_CONTEXT_ARM64_REG_FP] = 0x5fc4be14be145fc4L;
+ // caller's x1
+ expected.iregs[1] = 0xdd5a48c848c8dd5aL;
+ expected_validity |= StackFrameARM64::CONTEXT_VALID_X1;
+ CheckWalk();
+}
+
+// Here we move the .cfa, but provide an explicit rule to recover the SP,
+// so again there should be no change in the registers recovered.
+TEST_F(CFI, At4005) {
+ Label frame1_sp = expected.iregs[MD_CONTEXT_ARM64_REG_SP];
+ stack_section
+ .D64(0xdd5a48c848c8dd5aL) // saved x1 (even though it's not callee-saves)
+ .D64(0xff3dfb81fb81ff3dL) // no longer saved x19
+ .D64(0x34f3ebd1ebd134f3L) // no longer saved x20
+ .D64(0xe11081128112e110L) // saved fp
+ .D64(0x0000000040005510L) // return address
+ .Mark(&frame1_sp); // This effectively sets stack_section.start().
+ raw_context.iregs[MD_CONTEXT_ARM64_REG_PC] = 0x0000000040004005L;
+ raw_context.iregs[1] = 0xfb756319fb756319L; // distinct callee x1
+ expected.iregs[1] = 0xdd5a48c848c8dd5aL; // caller's x1
+ expected_validity |= StackFrameARM64::CONTEXT_VALID_X1;
+ CheckWalk();
+}
+
+// Here we provide an explicit rule for the PC, and have the saved .ra be
+// bogus.
+TEST_F(CFI, At4006) {
+ Label frame1_sp = expected.iregs[MD_CONTEXT_ARM64_REG_SP];
+ stack_section
+ .D64(0x0000000040005510L) // saved pc
+ .D64(0xdd5a48c848c8dd5aL) // saved x1 (even though it's not callee-saves)
+ .D64(0xff3dfb81fb81ff3dL) // no longer saved x19
+ .D64(0x34f3ebd1ebd134f3L) // no longer saved x20
+ .D64(0xe11081128112e110L) // saved fp
+ .D64(0xf8d157835783f8d1L) // .ra rule recovers this, which is garbage
+ .Mark(&frame1_sp); // This effectively sets stack_section.start().
+ raw_context.iregs[MD_CONTEXT_ARM64_REG_PC] = 0x0000000040004006L;
+ raw_context.iregs[1] = 0xfb756319fb756319L; // distinct callee x1
+ expected.iregs[1] = 0xdd5a48c848c8dd5aL; // caller's x1
+ expected_validity |= StackFrameARM64::CONTEXT_VALID_X1;
+ CheckWalk();
+}
+
+// Check that we reject rules that would cause the stack pointer to
+// move in the wrong direction.
+TEST_F(CFI, RejectBackwards) {
+ raw_context.iregs[MD_CONTEXT_ARM64_REG_PC] = 0x0000000040006000L;
+ raw_context.iregs[MD_CONTEXT_ARM64_REG_SP] = 0x0000000080000000L;
+ raw_context.iregs[MD_CONTEXT_ARM64_REG_LR] = 0x0000000040005510L;
+ StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
+ StackwalkerARM64 walker(&system_info, &raw_context, &stack_region, &modules,
+ &frame_symbolizer);
+ vector<const CodeModule*> modules_without_symbols;
+ vector<const CodeModule*> modules_with_corrupt_symbols;
+ ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
+ &modules_with_corrupt_symbols));
+ ASSERT_EQ(0U, modules_without_symbols.size());
+ ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
+ frames = call_stack.frames();
+ ASSERT_EQ(1U, frames->size());
+}
+
+// Check that we reject rules whose expressions' evaluation fails.
+TEST_F(CFI, RejectBadExpressions) {
+ raw_context.iregs[MD_CONTEXT_ARM64_REG_PC] = 0x0000000040007000L;
+ raw_context.iregs[MD_CONTEXT_ARM64_REG_SP] = 0x0000000080000000L;
+ StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
+ StackwalkerARM64 walker(&system_info, &raw_context, &stack_region, &modules,
+ &frame_symbolizer);
+ vector<const CodeModule*> modules_without_symbols;
+ vector<const CodeModule*> modules_with_corrupt_symbols;
+ ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
+ &modules_with_corrupt_symbols));
+ ASSERT_EQ(0U, modules_without_symbols.size());
+ ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
+ frames = call_stack.frames();
+ ASSERT_EQ(1U, frames->size());
+}
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_arm_unittest.cc b/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_arm_unittest.cc
new file mode 100644
index 0000000000..256f7648c4
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_arm_unittest.cc
@@ -0,0 +1,979 @@
+// 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>
+
+// stackwalker_arm_unittest.cc: Unit tests for StackwalkerARM class.
+
+#include <string.h>
+#include <string>
+#include <vector>
+
+#include "breakpad_googletest_includes.h"
+#include "common/test_assembler.h"
+#include "common/using_std_string.h"
+#include "google_breakpad/common/minidump_format.h"
+#include "google_breakpad/processor/basic_source_line_resolver.h"
+#include "google_breakpad/processor/call_stack.h"
+#include "google_breakpad/processor/code_module.h"
+#include "google_breakpad/processor/source_line_resolver_interface.h"
+#include "google_breakpad/processor/stack_frame_cpu.h"
+#include "processor/stackwalker_unittest_utils.h"
+#include "processor/stackwalker_arm.h"
+#include "processor/windows_frame_info.h"
+
+using google_breakpad::BasicSourceLineResolver;
+using google_breakpad::CallStack;
+using google_breakpad::CodeModule;
+using google_breakpad::StackFrameSymbolizer;
+using google_breakpad::StackFrame;
+using google_breakpad::StackFrameARM;
+using google_breakpad::Stackwalker;
+using google_breakpad::StackwalkerARM;
+using google_breakpad::SystemInfo;
+using google_breakpad::WindowsFrameInfo;
+using google_breakpad::test_assembler::kLittleEndian;
+using google_breakpad::test_assembler::Label;
+using google_breakpad::test_assembler::Section;
+using std::vector;
+using testing::_;
+using testing::AnyNumber;
+using testing::DoAll;
+using testing::Return;
+using testing::SetArgumentPointee;
+using testing::Test;
+
+class StackwalkerARMFixture {
+ public:
+ StackwalkerARMFixture()
+ : stack_section(kLittleEndian),
+ // Give the two modules reasonable standard locations and names
+ // for tests to play with.
+ module1(0x40000000, 0x10000, "module1", "version1"),
+ module2(0x50000000, 0x10000, "module2", "version2") {
+ // Identify the system as a Linux system.
+ system_info.os = "Linux";
+ system_info.os_short = "linux";
+ system_info.os_version = "Lugubrious Labrador";
+ system_info.cpu = "arm";
+ system_info.cpu_info = "";
+
+ // Put distinctive values in the raw CPU context.
+ BrandContext(&raw_context);
+
+ // Create some modules with some stock debugging information.
+ modules.Add(&module1);
+ modules.Add(&module2);
+
+ // By default, none of the modules have symbol info; call
+ // SetModuleSymbols to override this.
+ EXPECT_CALL(supplier, GetCStringSymbolData(_, _, _, _, _))
+ .WillRepeatedly(Return(MockSymbolSupplier::NOT_FOUND));
+
+ // Avoid GMOCK WARNING "Uninteresting mock function call - returning
+ // directly" for FreeSymbolData().
+ EXPECT_CALL(supplier, FreeSymbolData(_)).Times(AnyNumber());
+
+ // Reset max_frames_scanned since it's static.
+ Stackwalker::set_max_frames_scanned(1024);
+ }
+
+ // Set the Breakpad symbol information that supplier should return for
+ // MODULE to INFO.
+ void SetModuleSymbols(MockCodeModule *module, const string &info) {
+ size_t buffer_size;
+ char *buffer = supplier.CopySymbolDataAndOwnTheCopy(info, &buffer_size);
+ EXPECT_CALL(supplier, GetCStringSymbolData(module, &system_info, _, _, _))
+ .WillRepeatedly(DoAll(SetArgumentPointee<3>(buffer),
+ SetArgumentPointee<4>(buffer_size),
+ Return(MockSymbolSupplier::FOUND)));
+ }
+
+ // Populate stack_region with the contents of stack_section. Use
+ // stack_section.start() as the region's starting address.
+ void RegionFromSection() {
+ string contents;
+ ASSERT_TRUE(stack_section.GetContents(&contents));
+ stack_region.Init(stack_section.start().Value(), contents);
+ }
+
+ // Fill RAW_CONTEXT with pseudo-random data, for round-trip checking.
+ void BrandContext(MDRawContextARM *raw_context) {
+ uint8_t x = 173;
+ for (size_t i = 0; i < sizeof(*raw_context); i++)
+ reinterpret_cast<uint8_t *>(raw_context)[i] = (x += 17);
+ }
+
+ SystemInfo system_info;
+ MDRawContextARM raw_context;
+ Section stack_section;
+ MockMemoryRegion stack_region;
+ MockCodeModule module1;
+ MockCodeModule module2;
+ MockCodeModules modules;
+ MockSymbolSupplier supplier;
+ BasicSourceLineResolver resolver;
+ CallStack call_stack;
+ const vector<StackFrame *> *frames;
+};
+
+class SanityCheck: public StackwalkerARMFixture, public Test { };
+
+TEST_F(SanityCheck, NoResolver) {
+ // Since we have no call frame information, and all unwinding
+ // requires call frame information, the stack walk will end after
+ // the first frame.
+ StackFrameSymbolizer frame_symbolizer(NULL, NULL);
+ StackwalkerARM walker(&system_info, &raw_context, -1, &stack_region, &modules,
+ &frame_symbolizer);
+ // This should succeed even without a resolver or supplier.
+ vector<const CodeModule*> modules_without_symbols;
+ vector<const CodeModule*> modules_with_corrupt_symbols;
+ ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
+ &modules_with_corrupt_symbols));
+ ASSERT_EQ(0U, modules_without_symbols.size());
+ ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
+ frames = call_stack.frames();
+ ASSERT_EQ(1U, frames->size());
+ StackFrameARM *frame = static_cast<StackFrameARM *>(frames->at(0));
+ // Check that the values from the original raw context made it
+ // through to the context in the stack frame.
+ EXPECT_EQ(0, memcmp(&raw_context, &frame->context, sizeof(raw_context)));
+}
+
+class GetContextFrame: public StackwalkerARMFixture, public Test { };
+
+TEST_F(GetContextFrame, Simple) {
+ // Since we have no call frame information, and all unwinding
+ // requires call frame information, the stack walk will end after
+ // the first frame.
+ StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
+ StackwalkerARM walker(&system_info, &raw_context, -1, &stack_region, &modules,
+ &frame_symbolizer);
+ vector<const CodeModule*> modules_without_symbols;
+ vector<const CodeModule*> modules_with_corrupt_symbols;
+ ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
+ &modules_with_corrupt_symbols));
+ ASSERT_EQ(0U, modules_without_symbols.size());
+ ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
+ frames = call_stack.frames();
+ ASSERT_EQ(1U, frames->size());
+ StackFrameARM *frame = static_cast<StackFrameARM *>(frames->at(0));
+ // Check that the values from the original raw context made it
+ // through to the context in the stack frame.
+ EXPECT_EQ(0, memcmp(&raw_context, &frame->context, sizeof(raw_context)));
+}
+
+// The stackwalker should be able to produce the context frame even
+// without stack memory present.
+TEST_F(GetContextFrame, NoStackMemory) {
+ StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
+ StackwalkerARM walker(&system_info, &raw_context, -1, NULL, &modules,
+ &frame_symbolizer);
+ vector<const CodeModule*> modules_without_symbols;
+ vector<const CodeModule*> modules_with_corrupt_symbols;
+ ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
+ &modules_with_corrupt_symbols));
+ ASSERT_EQ(0U, modules_without_symbols.size());
+ ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
+ frames = call_stack.frames();
+ ASSERT_EQ(1U, frames->size());
+ StackFrameARM *frame = static_cast<StackFrameARM *>(frames->at(0));
+ // Check that the values from the original raw context made it
+ // through to the context in the stack frame.
+ EXPECT_EQ(0, memcmp(&raw_context, &frame->context, sizeof(raw_context)));
+}
+
+class GetCallerFrame: public StackwalkerARMFixture, public Test { };
+
+TEST_F(GetCallerFrame, ScanWithoutSymbols) {
+ // When the stack walker resorts to scanning the stack,
+ // only addresses located within loaded modules are
+ // considered valid return addresses.
+ // Force scanning through three frames to ensure that the
+ // stack pointer is set properly in scan-recovered frames.
+ stack_section.start() = 0x80000000;
+ uint32_t return_address1 = 0x50000100;
+ uint32_t return_address2 = 0x50000900;
+ Label frame1_sp, frame2_sp;
+ stack_section
+ // frame 0
+ .Append(16, 0) // space
+
+ .D32(0x40090000) // junk that's not
+ .D32(0x60000000) // a return address
+
+ .D32(return_address1) // actual return address
+ // frame 1
+ .Mark(&frame1_sp)
+ .Append(16, 0) // space
+
+ .D32(0xF0000000) // more junk
+ .D32(0x0000000D)
+
+ .D32(return_address2) // actual return address
+ // frame 2
+ .Mark(&frame2_sp)
+ .Append(32, 0); // end of stack
+ RegionFromSection();
+
+ raw_context.iregs[MD_CONTEXT_ARM_REG_PC] = 0x40005510;
+ raw_context.iregs[MD_CONTEXT_ARM_REG_SP] = stack_section.start().Value();
+
+ StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
+ StackwalkerARM walker(&system_info, &raw_context, -1, &stack_region, &modules,
+ &frame_symbolizer);
+ vector<const CodeModule*> modules_without_symbols;
+ vector<const CodeModule*> modules_with_corrupt_symbols;
+ ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
+ &modules_with_corrupt_symbols));
+ ASSERT_EQ(2U, modules_without_symbols.size());
+ ASSERT_EQ("module1", modules_without_symbols[0]->debug_file());
+ ASSERT_EQ("module2", modules_without_symbols[1]->debug_file());
+ ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
+ frames = call_stack.frames();
+ ASSERT_EQ(3U, frames->size());
+
+ StackFrameARM *frame0 = static_cast<StackFrameARM *>(frames->at(0));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
+ ASSERT_EQ(StackFrameARM::CONTEXT_VALID_ALL, frame0->context_validity);
+ EXPECT_EQ(0, memcmp(&raw_context, &frame0->context, sizeof(raw_context)));
+
+ StackFrameARM *frame1 = static_cast<StackFrameARM *>(frames->at(1));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust);
+ ASSERT_EQ((StackFrameARM::CONTEXT_VALID_PC |
+ StackFrameARM::CONTEXT_VALID_SP),
+ frame1->context_validity);
+ EXPECT_EQ(return_address1, frame1->context.iregs[MD_CONTEXT_ARM_REG_PC]);
+ EXPECT_EQ(frame1_sp.Value(), frame1->context.iregs[MD_CONTEXT_ARM_REG_SP]);
+
+ StackFrameARM *frame2 = static_cast<StackFrameARM *>(frames->at(2));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame2->trust);
+ ASSERT_EQ((StackFrameARM::CONTEXT_VALID_PC |
+ StackFrameARM::CONTEXT_VALID_SP),
+ frame2->context_validity);
+ EXPECT_EQ(return_address2, frame2->context.iregs[MD_CONTEXT_ARM_REG_PC]);
+ EXPECT_EQ(frame2_sp.Value(), frame2->context.iregs[MD_CONTEXT_ARM_REG_SP]);
+}
+
+TEST_F(GetCallerFrame, ScanWithFunctionSymbols) {
+ // During stack scanning, if a potential return address
+ // is located within a loaded module that has symbols,
+ // it is only considered a valid return address if it
+ // lies within a function's bounds.
+ stack_section.start() = 0x80000000;
+ uint32_t return_address = 0x50000200;
+ Label frame1_sp;
+
+ stack_section
+ // frame 0
+ .Append(16, 0) // space
+
+ .D32(0x40090000) // junk that's not
+ .D32(0x60000000) // a return address
+
+ .D32(0x40001000) // a couple of plausible addresses
+ .D32(0x5000F000) // that are not within functions
+
+ .D32(return_address) // actual return address
+ // frame 1
+ .Mark(&frame1_sp)
+ .Append(32, 0); // end of stack
+ RegionFromSection();
+
+ raw_context.iregs[MD_CONTEXT_ARM_REG_PC] = 0x40000200;
+ raw_context.iregs[MD_CONTEXT_ARM_REG_SP] = stack_section.start().Value();
+
+ SetModuleSymbols(&module1,
+ // The youngest frame's function.
+ "FUNC 100 400 10 monotreme\n");
+ SetModuleSymbols(&module2,
+ // The calling frame's function.
+ "FUNC 100 400 10 marsupial\n");
+
+ StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
+ StackwalkerARM walker(&system_info, &raw_context, -1, &stack_region, &modules,
+ &frame_symbolizer);
+ vector<const CodeModule*> modules_without_symbols;
+ vector<const CodeModule*> modules_with_corrupt_symbols;
+ ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
+ &modules_with_corrupt_symbols));
+ ASSERT_EQ(0U, modules_without_symbols.size());
+ ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
+ frames = call_stack.frames();
+ ASSERT_EQ(2U, frames->size());
+
+ StackFrameARM *frame0 = static_cast<StackFrameARM *>(frames->at(0));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
+ ASSERT_EQ(StackFrameARM::CONTEXT_VALID_ALL, frame0->context_validity);
+ EXPECT_EQ(0, memcmp(&raw_context, &frame0->context, sizeof(raw_context)));
+ EXPECT_EQ("monotreme", frame0->function_name);
+ EXPECT_EQ(0x40000100U, frame0->function_base);
+
+ StackFrameARM *frame1 = static_cast<StackFrameARM *>(frames->at(1));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust);
+ ASSERT_EQ((StackFrameARM::CONTEXT_VALID_PC |
+ StackFrameARM::CONTEXT_VALID_SP),
+ frame1->context_validity);
+ EXPECT_EQ(return_address, frame1->context.iregs[MD_CONTEXT_ARM_REG_PC]);
+ EXPECT_EQ(frame1_sp.Value(), frame1->context.iregs[MD_CONTEXT_ARM_REG_SP]);
+ EXPECT_EQ("marsupial", frame1->function_name);
+ EXPECT_EQ(0x50000100U, frame1->function_base);
+}
+
+TEST_F(GetCallerFrame, ScanFirstFrame) {
+ // If the stackwalker resorts to stack scanning, it will scan much
+ // farther to find the caller of the context frame.
+ stack_section.start() = 0x80000000;
+ uint32_t return_address1 = 0x50000100;
+ uint32_t return_address2 = 0x50000900;
+ Label frame1_sp, frame2_sp;
+ stack_section
+ // frame 0
+ .Append(32, 0) // space
+
+ .D32(0x40090000) // junk that's not
+ .D32(0x60000000) // a return address
+
+ .Append(96, 0) // more space
+
+ .D32(return_address1) // actual return address
+ // frame 1
+ .Mark(&frame1_sp)
+ .Append(32, 0) // space
+
+ .D32(0xF0000000) // more junk
+ .D32(0x0000000D)
+
+ .Append(136, 0) // more space
+
+ .D32(return_address2) // actual return address
+ // (won't be found)
+ // frame 2
+ .Mark(&frame2_sp)
+ .Append(32, 0); // end of stack
+ RegionFromSection();
+
+ raw_context.iregs[MD_CONTEXT_ARM_REG_PC] = 0x40005510;
+ raw_context.iregs[MD_CONTEXT_ARM_REG_SP] = stack_section.start().Value();
+
+ StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
+ StackwalkerARM walker(&system_info, &raw_context, -1, &stack_region, &modules,
+ &frame_symbolizer);
+ vector<const CodeModule*> modules_without_symbols;
+ vector<const CodeModule*> modules_with_corrupt_symbols;
+ ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
+ &modules_with_corrupt_symbols));
+ ASSERT_EQ(2U, modules_without_symbols.size());
+ ASSERT_EQ("module1", modules_without_symbols[0]->debug_file());
+ ASSERT_EQ("module2", modules_without_symbols[1]->debug_file());
+ ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
+ frames = call_stack.frames();
+ ASSERT_EQ(2U, frames->size());
+
+ StackFrameARM *frame0 = static_cast<StackFrameARM *>(frames->at(0));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
+ ASSERT_EQ(StackFrameARM::CONTEXT_VALID_ALL, frame0->context_validity);
+ EXPECT_EQ(0, memcmp(&raw_context, &frame0->context, sizeof(raw_context)));
+
+ StackFrameARM *frame1 = static_cast<StackFrameARM *>(frames->at(1));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust);
+ ASSERT_EQ((StackFrameARM::CONTEXT_VALID_PC |
+ StackFrameARM::CONTEXT_VALID_SP),
+ frame1->context_validity);
+ EXPECT_EQ(return_address1, frame1->context.iregs[MD_CONTEXT_ARM_REG_PC]);
+ EXPECT_EQ(frame1_sp.Value(), frame1->context.iregs[MD_CONTEXT_ARM_REG_SP]);
+}
+
+// Test that set_max_frames_scanned prevents using stack scanning
+// to find caller frames.
+TEST_F(GetCallerFrame, ScanningNotAllowed) {
+ // When the stack walker resorts to scanning the stack,
+ // only addresses located within loaded modules are
+ // considered valid return addresses.
+ stack_section.start() = 0x80000000;
+ uint32_t return_address1 = 0x50000100;
+ uint32_t return_address2 = 0x50000900;
+ Label frame1_sp, frame2_sp;
+ stack_section
+ // frame 0
+ .Append(16, 0) // space
+
+ .D32(0x40090000) // junk that's not
+ .D32(0x60000000) // a return address
+
+ .D32(return_address1) // actual return address
+ // frame 1
+ .Mark(&frame1_sp)
+ .Append(16, 0) // space
+
+ .D32(0xF0000000) // more junk
+ .D32(0x0000000D)
+
+ .D32(return_address2) // actual return address
+ // frame 2
+ .Mark(&frame2_sp)
+ .Append(32, 0); // end of stack
+ RegionFromSection();
+
+ raw_context.iregs[MD_CONTEXT_ARM_REG_PC] = 0x40005510;
+ raw_context.iregs[MD_CONTEXT_ARM_REG_SP] = stack_section.start().Value();
+
+ StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
+ StackwalkerARM walker(&system_info, &raw_context, -1, &stack_region, &modules,
+ &frame_symbolizer);
+ Stackwalker::set_max_frames_scanned(0);
+
+ vector<const CodeModule*> modules_without_symbols;
+ vector<const CodeModule*> modules_with_corrupt_symbols;
+ ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
+ &modules_with_corrupt_symbols));
+ ASSERT_EQ(1U, modules_without_symbols.size());
+ ASSERT_EQ("module1", modules_without_symbols[0]->debug_file());
+ ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
+ frames = call_stack.frames();
+ ASSERT_EQ(1U, frames->size());
+
+ StackFrameARM *frame0 = static_cast<StackFrameARM *>(frames->at(0));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
+ ASSERT_EQ(StackFrameARM::CONTEXT_VALID_ALL, frame0->context_validity);
+ EXPECT_EQ(0, memcmp(&raw_context, &frame0->context, sizeof(raw_context)));
+}
+
+struct CFIFixture: public StackwalkerARMFixture {
+ CFIFixture() {
+ // Provide a bunch of STACK CFI records; we'll walk to the caller
+ // from every point in this series, expecting to find the same set
+ // of register values.
+ SetModuleSymbols(&module1,
+ // The youngest frame's function.
+ "FUNC 4000 1000 10 enchiridion\n"
+ // Initially, nothing has been pushed on the stack,
+ // and the return address is still in the link register.
+ "STACK CFI INIT 4000 100 .cfa: sp .ra: lr\n"
+ // Push r4, the frame pointer, and the link register.
+ "STACK CFI 4001 .cfa: sp 12 + r4: .cfa 12 - ^"
+ " r11: .cfa 8 - ^ .ra: .cfa 4 - ^\n"
+ // Save r4..r7 in r0..r3: verify that we populate
+ // the youngest frame with all the values we have.
+ "STACK CFI 4002 r4: r0 r5: r1 r6: r2 r7: r3\n"
+ // Restore r4..r7. Save the non-callee-saves register r1.
+ "STACK CFI 4003 .cfa: sp 16 + r1: .cfa 16 - ^"
+ " r4: r4 r5: r5 r6: r6 r7: r7\n"
+ // Move the .cfa back four bytes, to point at the return
+ // address, and restore the sp explicitly.
+ "STACK CFI 4005 .cfa: sp 12 + r1: .cfa 12 - ^"
+ " r11: .cfa 4 - ^ .ra: .cfa ^ sp: .cfa 4 +\n"
+ // Recover the PC explicitly from a new stack slot;
+ // provide garbage for the .ra.
+ "STACK CFI 4006 .cfa: sp 16 + pc: .cfa 16 - ^\n"
+
+ // The calling function.
+ "FUNC 5000 1000 10 epictetus\n"
+ // Mark it as end of stack.
+ "STACK CFI INIT 5000 1000 .cfa: 0 .ra: 0\n"
+
+ // A function whose CFI makes the stack pointer
+ // go backwards.
+ "FUNC 6000 1000 20 palinal\n"
+ "STACK CFI INIT 6000 1000 .cfa: sp 4 - .ra: lr\n"
+
+ // A function with CFI expressions that can't be
+ // evaluated.
+ "FUNC 7000 1000 20 rhetorical\n"
+ "STACK CFI INIT 7000 1000 .cfa: moot .ra: ambiguous\n");
+
+ // Provide some distinctive values for the caller's registers.
+ expected.iregs[MD_CONTEXT_ARM_REG_PC] = 0x40005510;
+ expected.iregs[MD_CONTEXT_ARM_REG_SP] = 0x80000000;
+ expected.iregs[4] = 0xb5d55e68;
+ expected.iregs[5] = 0xebd134f3;
+ expected.iregs[6] = 0xa31e74bc;
+ expected.iregs[7] = 0x2dcb16b3;
+ expected.iregs[8] = 0x2ada2137;
+ expected.iregs[9] = 0xbbbb557d;
+ expected.iregs[10] = 0x48bf8ca7;
+ expected.iregs[MD_CONTEXT_ARM_REG_FP] = 0x8112e110;
+
+ // Expect CFI to recover all callee-saves registers. Since CFI is the
+ // only stack frame construction technique we have, aside from the
+ // context frame itself, there's no way for us to have a set of valid
+ // registers smaller than this.
+ expected_validity = (StackFrameARM::CONTEXT_VALID_PC |
+ StackFrameARM::CONTEXT_VALID_SP |
+ StackFrameARM::CONTEXT_VALID_R4 |
+ StackFrameARM::CONTEXT_VALID_R5 |
+ StackFrameARM::CONTEXT_VALID_R6 |
+ StackFrameARM::CONTEXT_VALID_R7 |
+ StackFrameARM::CONTEXT_VALID_R8 |
+ StackFrameARM::CONTEXT_VALID_R9 |
+ StackFrameARM::CONTEXT_VALID_R10 |
+ StackFrameARM::CONTEXT_VALID_FP);
+
+ // By default, context frames provide all registers, as normal.
+ context_frame_validity = StackFrameARM::CONTEXT_VALID_ALL;
+
+ // By default, registers are unchanged.
+ raw_context = expected;
+ }
+
+ // Walk the stack, using stack_section as the contents of the stack
+ // and raw_context as the current register values. (Set the stack
+ // pointer to the stack's starting address.) Expect two stack
+ // frames; in the older frame, expect the callee-saves registers to
+ // have values matching those in 'expected'.
+ void CheckWalk() {
+ RegionFromSection();
+ raw_context.iregs[MD_CONTEXT_ARM_REG_SP] = stack_section.start().Value();
+
+ StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
+ StackwalkerARM walker(&system_info, &raw_context, -1, &stack_region,
+ &modules, &frame_symbolizer);
+ walker.SetContextFrameValidity(context_frame_validity);
+ vector<const CodeModule*> modules_without_symbols;
+ vector<const CodeModule*> modules_with_corrupt_symbols;
+ ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
+ &modules_with_corrupt_symbols));
+ ASSERT_EQ(0U, modules_without_symbols.size());
+ ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
+ frames = call_stack.frames();
+ ASSERT_EQ(2U, frames->size());
+
+ StackFrameARM *frame0 = static_cast<StackFrameARM *>(frames->at(0));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
+ ASSERT_EQ(context_frame_validity, frame0->context_validity);
+ EXPECT_EQ("enchiridion", frame0->function_name);
+ EXPECT_EQ(0x40004000U, frame0->function_base);
+
+ StackFrameARM *frame1 = static_cast<StackFrameARM *>(frames->at(1));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame1->trust);
+ ASSERT_EQ(expected_validity, frame1->context_validity);
+ if (expected_validity & StackFrameARM::CONTEXT_VALID_R1)
+ EXPECT_EQ(expected.iregs[1], frame1->context.iregs[1]);
+ if (expected_validity & StackFrameARM::CONTEXT_VALID_R4)
+ EXPECT_EQ(expected.iregs[4], frame1->context.iregs[4]);
+ if (expected_validity & StackFrameARM::CONTEXT_VALID_R5)
+ EXPECT_EQ(expected.iregs[5], frame1->context.iregs[5]);
+ if (expected_validity & StackFrameARM::CONTEXT_VALID_R6)
+ EXPECT_EQ(expected.iregs[6], frame1->context.iregs[6]);
+ if (expected_validity & StackFrameARM::CONTEXT_VALID_R7)
+ EXPECT_EQ(expected.iregs[7], frame1->context.iregs[7]);
+ if (expected_validity & StackFrameARM::CONTEXT_VALID_R8)
+ EXPECT_EQ(expected.iregs[8], frame1->context.iregs[8]);
+ if (expected_validity & StackFrameARM::CONTEXT_VALID_R9)
+ EXPECT_EQ(expected.iregs[9], frame1->context.iregs[9]);
+ if (expected_validity & StackFrameARM::CONTEXT_VALID_R10)
+ EXPECT_EQ(expected.iregs[10], frame1->context.iregs[10]);
+ if (expected_validity & StackFrameARM::CONTEXT_VALID_FP)
+ EXPECT_EQ(expected.iregs[MD_CONTEXT_ARM_REG_FP],
+ frame1->context.iregs[MD_CONTEXT_ARM_REG_FP]);
+
+ // We would never have gotten a frame in the first place if the SP
+ // and PC weren't valid or ->instruction weren't set.
+ EXPECT_EQ(expected.iregs[MD_CONTEXT_ARM_REG_SP],
+ frame1->context.iregs[MD_CONTEXT_ARM_REG_SP]);
+ EXPECT_EQ(expected.iregs[MD_CONTEXT_ARM_REG_PC],
+ frame1->context.iregs[MD_CONTEXT_ARM_REG_PC]);
+ EXPECT_EQ(expected.iregs[MD_CONTEXT_ARM_REG_PC],
+ frame1->instruction + 2);
+ EXPECT_EQ("epictetus", frame1->function_name);
+ }
+
+ // The values we expect to find for the caller's registers.
+ MDRawContextARM expected;
+
+ // The validity mask for expected.
+ int expected_validity;
+
+ // The validity mask to impose on the context frame.
+ int context_frame_validity;
+};
+
+class CFI: public CFIFixture, public Test { };
+
+TEST_F(CFI, At4000) {
+ stack_section.start() = expected.iregs[MD_CONTEXT_ARM_REG_SP];
+ raw_context.iregs[MD_CONTEXT_ARM_REG_PC] = 0x40004000;
+ raw_context.iregs[MD_CONTEXT_ARM_REG_LR] = 0x40005510;
+ CheckWalk();
+}
+
+TEST_F(CFI, At4001) {
+ Label frame1_sp = expected.iregs[MD_CONTEXT_ARM_REG_SP];
+ stack_section
+ .D32(0xb5d55e68) // saved r4
+ .D32(0x8112e110) // saved fp
+ .D32(0x40005510) // return address
+ .Mark(&frame1_sp); // This effectively sets stack_section.start().
+ raw_context.iregs[MD_CONTEXT_ARM_REG_PC] = 0x40004001;
+ raw_context.iregs[4] = 0x635adc9f; // distinct callee r4
+ raw_context.iregs[MD_CONTEXT_ARM_REG_FP] = 0xbe145fc4; // distinct callee fp
+ CheckWalk();
+}
+
+// As above, but unwind from a context that has only the PC and SP.
+TEST_F(CFI, At4001LimitedValidity) {
+ context_frame_validity =
+ StackFrameARM::CONTEXT_VALID_PC | StackFrameARM::CONTEXT_VALID_SP;
+ raw_context.iregs[MD_CONTEXT_ARM_REG_PC] = 0x40004001;
+ raw_context.iregs[MD_CONTEXT_ARM_REG_FP] = 0xbe145fc4; // distinct callee fp
+ Label frame1_sp = expected.iregs[MD_CONTEXT_ARM_REG_SP];
+ stack_section
+ .D32(0xb5d55e68) // saved r4
+ .D32(0x8112e110) // saved fp
+ .D32(0x40005510) // return address
+ .Mark(&frame1_sp); // This effectively sets stack_section.start().
+ expected_validity = (StackFrameARM::CONTEXT_VALID_PC
+ | StackFrameARM::CONTEXT_VALID_SP
+ | StackFrameARM::CONTEXT_VALID_FP
+ | StackFrameARM::CONTEXT_VALID_R4);
+ CheckWalk();
+}
+
+TEST_F(CFI, At4002) {
+ Label frame1_sp = expected.iregs[MD_CONTEXT_ARM_REG_SP];
+ stack_section
+ .D32(0xfb81ff3d) // no longer saved r4
+ .D32(0x8112e110) // saved fp
+ .D32(0x40005510) // return address
+ .Mark(&frame1_sp); // This effectively sets stack_section.start().
+ raw_context.iregs[MD_CONTEXT_ARM_REG_PC] = 0x40004002;
+ raw_context.iregs[0] = 0xb5d55e68; // saved r4
+ raw_context.iregs[1] = 0xebd134f3; // saved r5
+ raw_context.iregs[2] = 0xa31e74bc; // saved r6
+ raw_context.iregs[3] = 0x2dcb16b3; // saved r7
+ raw_context.iregs[4] = 0xfdd35466; // distinct callee r4
+ raw_context.iregs[5] = 0xf18c946c; // distinct callee r5
+ raw_context.iregs[6] = 0xac2079e8; // distinct callee r6
+ raw_context.iregs[7] = 0xa449829f; // distinct callee r7
+ raw_context.iregs[MD_CONTEXT_ARM_REG_FP] = 0xbe145fc4; // distinct callee fp
+ CheckWalk();
+}
+
+TEST_F(CFI, At4003) {
+ Label frame1_sp = expected.iregs[MD_CONTEXT_ARM_REG_SP];
+ stack_section
+ .D32(0x48c8dd5a) // saved r1 (even though it's not callee-saves)
+ .D32(0xcb78040e) // no longer saved r4
+ .D32(0x8112e110) // saved fp
+ .D32(0x40005510) // return address
+ .Mark(&frame1_sp); // This effectively sets stack_section.start().
+ raw_context.iregs[MD_CONTEXT_ARM_REG_PC] = 0x40004003;
+ raw_context.iregs[1] = 0xfb756319; // distinct callee r1
+ raw_context.iregs[MD_CONTEXT_ARM_REG_FP] = 0x0a2857ea; // distinct callee fp
+ expected.iregs[1] = 0x48c8dd5a; // caller's r1
+ expected_validity |= StackFrameARM::CONTEXT_VALID_R1;
+ CheckWalk();
+}
+
+// We have no new rule at module offset 0x4004, so the results here should
+// be the same as those at module offset 0x4003.
+TEST_F(CFI, At4004) {
+ Label frame1_sp = expected.iregs[MD_CONTEXT_ARM_REG_SP];
+ stack_section
+ .D32(0x48c8dd5a) // saved r1 (even though it's not callee-saves)
+ .D32(0xcb78040e) // no longer saved r4
+ .D32(0x8112e110) // saved fp
+ .D32(0x40005510) // return address
+ .Mark(&frame1_sp); // This effectively sets stack_section.start().
+ raw_context.iregs[MD_CONTEXT_ARM_REG_PC] = 0x40004004;
+ raw_context.iregs[1] = 0xfb756319; // distinct callee r1
+ expected.iregs[1] = 0x48c8dd5a; // caller's r1
+ expected_validity |= StackFrameARM::CONTEXT_VALID_R1;
+ CheckWalk();
+}
+
+// Here we move the .cfa, but provide an explicit rule to recover the SP,
+// so again there should be no change in the registers recovered.
+TEST_F(CFI, At4005) {
+ Label frame1_sp = expected.iregs[MD_CONTEXT_ARM_REG_SP];
+ stack_section
+ .D32(0x48c8dd5a) // saved r1 (even though it's not callee-saves)
+ .D32(0xf013f841) // no longer saved r4
+ .D32(0x8112e110) // saved fp
+ .D32(0x40005510) // return address
+ .Mark(&frame1_sp); // This effectively sets stack_section.start().
+ raw_context.iregs[MD_CONTEXT_ARM_REG_PC] = 0x40004005;
+ raw_context.iregs[1] = 0xfb756319; // distinct callee r1
+ expected.iregs[1] = 0x48c8dd5a; // caller's r1
+ expected_validity |= StackFrameARM::CONTEXT_VALID_R1;
+ CheckWalk();
+}
+
+// Here we provide an explicit rule for the PC, and have the saved .ra be
+// bogus.
+TEST_F(CFI, At4006) {
+ Label frame1_sp = expected.iregs[MD_CONTEXT_ARM_REG_SP];
+ stack_section
+ .D32(0x40005510) // saved pc
+ .D32(0x48c8dd5a) // saved r1 (even though it's not callee-saves)
+ .D32(0xf013f841) // no longer saved r4
+ .D32(0x8112e110) // saved fp
+ .D32(0xf8d15783) // .ra rule recovers this, which is garbage
+ .Mark(&frame1_sp); // This effectively sets stack_section.start().
+ raw_context.iregs[MD_CONTEXT_ARM_REG_PC] = 0x40004006;
+ raw_context.iregs[1] = 0xfb756319; // callee's r1, different from caller's
+ expected.iregs[1] = 0x48c8dd5a; // caller's r1
+ expected_validity |= StackFrameARM::CONTEXT_VALID_R1;
+ CheckWalk();
+}
+
+// Check that we reject rules that would cause the stack pointer to
+// move in the wrong direction.
+TEST_F(CFI, RejectBackwards) {
+ raw_context.iregs[MD_CONTEXT_ARM_REG_PC] = 0x40006000;
+ raw_context.iregs[MD_CONTEXT_ARM_REG_SP] = 0x80000000;
+ raw_context.iregs[MD_CONTEXT_ARM_REG_LR] = 0x40005510;
+ StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
+ StackwalkerARM walker(&system_info, &raw_context, -1, &stack_region, &modules,
+ &frame_symbolizer);
+ vector<const CodeModule*> modules_without_symbols;
+ vector<const CodeModule*> modules_with_corrupt_symbols;
+ ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
+ &modules_with_corrupt_symbols));
+ ASSERT_EQ(0U, modules_without_symbols.size());
+ ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
+ frames = call_stack.frames();
+ ASSERT_EQ(1U, frames->size());
+}
+
+// Check that we reject rules whose expressions' evaluation fails.
+TEST_F(CFI, RejectBadExpressions) {
+ raw_context.iregs[MD_CONTEXT_ARM_REG_PC] = 0x40007000;
+ raw_context.iregs[MD_CONTEXT_ARM_REG_SP] = 0x80000000;
+ StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
+ StackwalkerARM walker(&system_info, &raw_context, -1, &stack_region, &modules,
+ &frame_symbolizer);
+ vector<const CodeModule*> modules_without_symbols;
+ vector<const CodeModule*> modules_with_corrupt_symbols;
+ ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
+ &modules_with_corrupt_symbols));
+ ASSERT_EQ(0U, modules_without_symbols.size());
+ ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
+ frames = call_stack.frames();
+ ASSERT_EQ(1U, frames->size());
+}
+
+class StackwalkerARMFixtureIOS : public StackwalkerARMFixture {
+ public:
+ StackwalkerARMFixtureIOS() {
+ // iOS_test is used instead of iOS because the stackwalker has a check to
+ // avoid using CFI for iOS dumps. This is a workaround for bad CFI being
+ // produced by dump_syms for iOS.
+ // https://bugs.chromium.org/p/google-breakpad/issues/detail?id=764
+ system_info.os = "iOS_test";
+ system_info.os_short = "ios_test";
+ }
+};
+
+class GetFramesByFramePointer: public StackwalkerARMFixtureIOS, public Test { };
+
+TEST_F(GetFramesByFramePointer, OnlyFramePointer) {
+ stack_section.start() = 0x80000000;
+ uint32_t return_address1 = 0x50000100;
+ uint32_t return_address2 = 0x50000900;
+ Label frame1_sp, frame2_sp;
+ Label frame1_fp, frame2_fp;
+ stack_section
+ // frame 0
+ .Append(32, 0) // Whatever values on the stack.
+ .D32(0x0000000D) // junk that's not
+ .D32(0xF0000000) // a return address.
+
+ .Mark(&frame1_fp) // Next fp will point to the next value.
+ .D32(frame2_fp) // Save current frame pointer.
+ .D32(return_address2) // Save current link register.
+ .Mark(&frame1_sp)
+
+ // frame 1
+ .Append(32, 0) // Whatever values on the stack.
+ .D32(0x0000000D) // junk that's not
+ .D32(0xF0000000) // a return address.
+
+ .Mark(&frame2_fp)
+ .D32(0)
+ .D32(0)
+ .Mark(&frame2_sp)
+
+ // frame 2
+ .Append(32, 0) // Whatever values on the stack.
+ .D32(0x0000000D) // junk that's not
+ .D32(0xF0000000); // a return address.
+ RegionFromSection();
+
+
+ raw_context.iregs[MD_CONTEXT_ARM_REG_PC] = 0x40005510;
+ raw_context.iregs[MD_CONTEXT_ARM_REG_LR] = return_address1;
+ raw_context.iregs[MD_CONTEXT_ARM_REG_IOS_FP] = frame1_fp.Value();
+ raw_context.iregs[MD_CONTEXT_ARM_REG_SP] = stack_section.start().Value();
+
+ StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
+ StackwalkerARM walker(&system_info, &raw_context, MD_CONTEXT_ARM_REG_IOS_FP,
+ &stack_region, &modules, &frame_symbolizer);
+
+ vector<const CodeModule*> modules_without_symbols;
+ vector<const CodeModule*> modules_with_corrupt_symbols;
+ ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
+ &modules_with_corrupt_symbols));
+ ASSERT_EQ(2U, modules_without_symbols.size());
+ ASSERT_EQ("module1", modules_without_symbols[0]->debug_file());
+ ASSERT_EQ("module2", modules_without_symbols[1]->debug_file());
+ ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
+ frames = call_stack.frames();
+ ASSERT_EQ(3U, frames->size());
+
+ StackFrameARM *frame0 = static_cast<StackFrameARM *>(frames->at(0));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
+ ASSERT_EQ(StackFrameARM::CONTEXT_VALID_ALL, frame0->context_validity);
+ EXPECT_EQ(0, memcmp(&raw_context, &frame0->context, sizeof(raw_context)));
+
+ StackFrameARM *frame1 = static_cast<StackFrameARM *>(frames->at(1));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_FP, frame1->trust);
+ ASSERT_EQ((StackFrameARM::CONTEXT_VALID_PC |
+ StackFrameARM::CONTEXT_VALID_LR |
+ StackFrameARM::RegisterValidFlag(MD_CONTEXT_ARM_REG_IOS_FP) |
+ StackFrameARM::CONTEXT_VALID_SP),
+ frame1->context_validity);
+ EXPECT_EQ(return_address1, frame1->context.iregs[MD_CONTEXT_ARM_REG_PC]);
+ EXPECT_EQ(return_address2, frame1->context.iregs[MD_CONTEXT_ARM_REG_LR]);
+ EXPECT_EQ(frame1_sp.Value(), frame1->context.iregs[MD_CONTEXT_ARM_REG_SP]);
+ EXPECT_EQ(frame2_fp.Value(),
+ frame1->context.iregs[MD_CONTEXT_ARM_REG_IOS_FP]);
+
+ StackFrameARM *frame2 = static_cast<StackFrameARM *>(frames->at(2));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_FP, frame2->trust);
+ ASSERT_EQ((StackFrameARM::CONTEXT_VALID_PC |
+ StackFrameARM::CONTEXT_VALID_LR |
+ StackFrameARM::RegisterValidFlag(MD_CONTEXT_ARM_REG_IOS_FP) |
+ StackFrameARM::CONTEXT_VALID_SP),
+ frame2->context_validity);
+ EXPECT_EQ(return_address2, frame2->context.iregs[MD_CONTEXT_ARM_REG_PC]);
+ EXPECT_EQ(0U, frame2->context.iregs[MD_CONTEXT_ARM_REG_LR]);
+ EXPECT_EQ(frame2_sp.Value(), frame2->context.iregs[MD_CONTEXT_ARM_REG_SP]);
+ EXPECT_EQ(0U, frame2->context.iregs[MD_CONTEXT_ARM_REG_IOS_FP]);
+}
+
+TEST_F(GetFramesByFramePointer, FramePointerAndCFI) {
+ // Provide the standatd STACK CFI records that is obtained when exmining an
+ // executable produced by XCode.
+ SetModuleSymbols(&module1,
+ // Adding a function in CFI.
+ "FUNC 4000 1000 10 enchiridion\n"
+
+ "STACK CFI INIT 4000 100 .cfa: sp 0 + .ra: lr\n"
+ "STACK CFI 4001 .cfa: sp 8 + .ra: .cfa -4 + ^"
+ " r7: .cfa -8 + ^\n"
+ "STACK CFI 4002 .cfa: r7 8 +\n"
+ );
+
+ stack_section.start() = 0x80000000;
+ uint32_t return_address1 = 0x40004010;
+ uint32_t return_address2 = 0x50000900;
+ Label frame1_sp, frame2_sp;
+ Label frame1_fp, frame2_fp;
+ stack_section
+ // frame 0
+ .Append(32, 0) // Whatever values on the stack.
+ .D32(0x0000000D) // junk that's not
+ .D32(0xF0000000) // a return address.
+
+ .Mark(&frame1_fp) // Next fp will point to the next value.
+ .D32(frame2_fp) // Save current frame pointer.
+ .D32(return_address2) // Save current link register.
+ .Mark(&frame1_sp)
+
+ // frame 1
+ .Append(32, 0) // Whatever values on the stack.
+ .D32(0x0000000D) // junk that's not
+ .D32(0xF0000000) // a return address.
+
+ .Mark(&frame2_fp)
+ .D32(0)
+ .D32(0)
+ .Mark(&frame2_sp)
+
+ // frame 2
+ .Append(32, 0) // Whatever values on the stack.
+ .D32(0x0000000D) // junk that's not
+ .D32(0xF0000000); // a return address.
+ RegionFromSection();
+
+
+ raw_context.iregs[MD_CONTEXT_ARM_REG_PC] = 0x50000400;
+ raw_context.iregs[MD_CONTEXT_ARM_REG_LR] = return_address1;
+ raw_context.iregs[MD_CONTEXT_ARM_REG_IOS_FP] = frame1_fp.Value();
+ raw_context.iregs[MD_CONTEXT_ARM_REG_SP] = stack_section.start().Value();
+
+ StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
+ StackwalkerARM walker(&system_info, &raw_context, MD_CONTEXT_ARM_REG_IOS_FP,
+ &stack_region, &modules, &frame_symbolizer);
+
+ vector<const CodeModule*> modules_without_symbols;
+ vector<const CodeModule*> modules_with_corrupt_symbols;
+ ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
+ &modules_with_corrupt_symbols));
+ ASSERT_EQ(1U, modules_without_symbols.size());
+ ASSERT_EQ("module2", modules_without_symbols[0]->debug_file());
+ ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
+ frames = call_stack.frames();
+ ASSERT_EQ(3U, frames->size());
+
+ StackFrameARM *frame0 = static_cast<StackFrameARM *>(frames->at(0));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
+ ASSERT_EQ(StackFrameARM::CONTEXT_VALID_ALL, frame0->context_validity);
+ EXPECT_EQ(0, memcmp(&raw_context, &frame0->context, sizeof(raw_context)));
+
+ StackFrameARM *frame1 = static_cast<StackFrameARM *>(frames->at(1));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_FP, frame1->trust);
+ ASSERT_EQ((StackFrameARM::CONTEXT_VALID_PC |
+ StackFrameARM::CONTEXT_VALID_LR |
+ StackFrameARM::RegisterValidFlag(MD_CONTEXT_ARM_REG_IOS_FP) |
+ StackFrameARM::CONTEXT_VALID_SP),
+ frame1->context_validity);
+ EXPECT_EQ(return_address1, frame1->context.iregs[MD_CONTEXT_ARM_REG_PC]);
+ EXPECT_EQ(return_address2, frame1->context.iregs[MD_CONTEXT_ARM_REG_LR]);
+ EXPECT_EQ(frame1_sp.Value(), frame1->context.iregs[MD_CONTEXT_ARM_REG_SP]);
+ EXPECT_EQ(frame2_fp.Value(),
+ frame1->context.iregs[MD_CONTEXT_ARM_REG_IOS_FP]);
+ EXPECT_EQ("enchiridion", frame1->function_name);
+ EXPECT_EQ(0x40004000U, frame1->function_base);
+
+
+ StackFrameARM *frame2 = static_cast<StackFrameARM *>(frames->at(2));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame2->trust);
+ ASSERT_EQ((StackFrameARM::CONTEXT_VALID_PC |
+ StackFrameARM::CONTEXT_VALID_LR |
+ StackFrameARM::RegisterValidFlag(MD_CONTEXT_ARM_REG_IOS_FP) |
+ StackFrameARM::CONTEXT_VALID_SP),
+ frame2->context_validity);
+ EXPECT_EQ(return_address2, frame2->context.iregs[MD_CONTEXT_ARM_REG_PC]);
+ EXPECT_EQ(0U, frame2->context.iregs[MD_CONTEXT_ARM_REG_LR]);
+ EXPECT_EQ(frame2_sp.Value(), frame2->context.iregs[MD_CONTEXT_ARM_REG_SP]);
+ EXPECT_EQ(0U, frame2->context.iregs[MD_CONTEXT_ARM_REG_IOS_FP]);
+}
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_mips.cc b/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_mips.cc
new file mode 100644
index 0000000000..c33ecdbe96
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_mips.cc
@@ -0,0 +1,442 @@
+// 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.
+
+// stackwalker_mips.cc: MIPS-specific stackwalker.
+//
+// See stackwalker_mips.h for documentation.
+//
+// Author: Tata Elxsi
+
+#include "common/scoped_ptr.h"
+#include "google_breakpad/processor/call_stack.h"
+#include "google_breakpad/processor/code_modules.h"
+#include "google_breakpad/processor/memory_region.h"
+#include "google_breakpad/processor/source_line_resolver_interface.h"
+#include "google_breakpad/processor/stack_frame_cpu.h"
+#include "processor/cfi_frame_info.h"
+#include "processor/logging.h"
+#include "processor/postfix_evaluator-inl.h"
+#include "processor/stackwalker_mips.h"
+#include "processor/windows_frame_info.h"
+#include "google_breakpad/common/minidump_cpu_mips.h"
+
+namespace google_breakpad {
+
+StackwalkerMIPS::StackwalkerMIPS(const SystemInfo* system_info,
+ const MDRawContextMIPS* context,
+ MemoryRegion* memory,
+ const CodeModules* modules,
+ StackFrameSymbolizer* resolver_helper)
+: Stackwalker(system_info, memory, modules, resolver_helper),
+ context_(context) {
+ if (memory_) {
+ if (context_->context_flags & MD_CONTEXT_MIPS64 ) {
+ if (0xffffffffffffffff - memory_->GetBase() < memory_->GetSize() - 1) {
+ BPLOG(ERROR) << "Memory out of range for stackwalking mips64: "
+ << HexString(memory_->GetBase())
+ << "+"
+ << HexString(memory_->GetSize());
+ memory_ = NULL;
+ }
+ } else {
+ if (0xffffffff - memory_->GetBase() < memory_->GetSize() - 1) {
+ BPLOG(ERROR) << "Memory out of range for stackwalking mips32: "
+ << HexString(memory_->GetBase())
+ << "+"
+ << HexString(memory_->GetSize());
+ memory_ = NULL;
+ }
+ }
+ }
+}
+
+StackFrame* StackwalkerMIPS::GetContextFrame() {
+ if (!context_) {
+ BPLOG(ERROR) << "Can't get context frame without context.";
+ return NULL;
+ }
+
+ StackFrameMIPS* frame = new StackFrameMIPS();
+
+ // The instruction pointer is stored directly in a register, so pull it
+ // straight out of the CPU context structure.
+ frame->context = *context_;
+ frame->context_validity = StackFrameMIPS::CONTEXT_VALID_ALL;
+ frame->trust = StackFrame::FRAME_TRUST_CONTEXT;
+ frame->instruction = frame->context.epc;
+
+ return frame;
+}
+
+// Register names for mips.
+static const char* const kRegisterNames[] = {
+ "$zero", "$at", "$v0", "$v1", "$a0", "$a1", "$a2", "$a3", "$to", "$t1",
+ "$t2", "$t3", "$t4", "$t5", "$t6", "$t7", "$s0", "$s1", "$s2", "$s3",
+ "$s4", "$s5", "$s6", "$s7", "$t8", "$t9", "$k0", "$k1", "$gp", "$sp",
+ "$fp", "$ra", NULL
+ // TODO(gordanac): add float point save registers
+};
+
+StackFrameMIPS* StackwalkerMIPS::GetCallerByCFIFrameInfo(
+ const vector<StackFrame*>& frames,
+ CFIFrameInfo* cfi_frame_info) {
+ StackFrameMIPS* last_frame = static_cast<StackFrameMIPS*>(frames.back());
+
+ if (context_->context_flags & MD_CONTEXT_MIPS) {
+ uint32_t pc = 0;
+
+ // Populate a dictionary with the valid register values in last_frame.
+ CFIFrameInfo::RegisterValueMap<uint32_t> callee_registers;
+ // Use the STACK CFI data to recover the caller's register values.
+ CFIFrameInfo::RegisterValueMap<uint32_t> caller_registers;
+
+ for (int i = 0; kRegisterNames[i]; ++i) {
+ caller_registers[kRegisterNames[i]] = last_frame->context.iregs[i];
+ callee_registers[kRegisterNames[i]] = last_frame->context.iregs[i];
+ }
+
+ if (!cfi_frame_info->FindCallerRegs(callee_registers, *memory_,
+ &caller_registers)) {
+ return NULL;
+ }
+
+ CFIFrameInfo::RegisterValueMap<uint32_t>::const_iterator entry =
+ caller_registers.find(".cfa");
+
+ if (entry != caller_registers.end()) {
+ caller_registers["$sp"] = entry->second;
+ }
+
+ entry = caller_registers.find(".ra");
+ if (entry != caller_registers.end()) {
+ caller_registers["$ra"] = entry->second;
+ pc = entry->second - 2 * sizeof(pc);
+ }
+ caller_registers["$pc"] = pc;
+ // Construct a new stack frame given the values the CFI recovered.
+ scoped_ptr<StackFrameMIPS> frame(new StackFrameMIPS());
+
+ for (int i = 0; kRegisterNames[i]; ++i) {
+ CFIFrameInfo::RegisterValueMap<uint32_t>::const_iterator caller_entry =
+ caller_registers.find(kRegisterNames[i]);
+
+ if (caller_entry != caller_registers.end()) {
+ // The value of this register is recovered; fill the context with the
+ // value from caller_registers.
+ frame->context.iregs[i] = caller_entry->second;
+ frame->context_validity |= StackFrameMIPS::RegisterValidFlag(i);
+ } else if (((i >= INDEX_MIPS_REG_S0 && i <= INDEX_MIPS_REG_S7) ||
+ (i > INDEX_MIPS_REG_GP && i < INDEX_MIPS_REG_RA)) &&
+ (last_frame->context_validity &
+ StackFrameMIPS::RegisterValidFlag(i))) {
+ // If the STACK CFI data doesn't mention some callee-save register, and
+ // it is valid in the callee, assume the callee has not yet changed it.
+ // Calee-save registers according to the MIPS o32 ABI specification are:
+ // $s0 to $s7
+ // $sp, $s8
+ frame->context.iregs[i] = last_frame->context.iregs[i];
+ frame->context_validity |= StackFrameMIPS::RegisterValidFlag(i);
+ }
+ }
+
+ frame->context.epc = caller_registers["$pc"];
+ frame->instruction = caller_registers["$pc"];
+ frame->context_validity |= StackFrameMIPS::CONTEXT_VALID_PC;
+
+ frame->context.iregs[MD_CONTEXT_MIPS_REG_RA] = caller_registers["$ra"];
+ frame->context_validity |= StackFrameMIPS::CONTEXT_VALID_RA;
+
+ frame->trust = StackFrame::FRAME_TRUST_CFI;
+
+ return frame.release();
+ } else {
+ uint64_t pc = 0;
+
+ // Populate a dictionary with the valid register values in last_frame.
+ CFIFrameInfo::RegisterValueMap<uint64_t> callee_registers;
+ // Use the STACK CFI data to recover the caller's register values.
+ CFIFrameInfo::RegisterValueMap<uint64_t> caller_registers;
+
+ for (int i = 0; kRegisterNames[i]; ++i) {
+ caller_registers[kRegisterNames[i]] = last_frame->context.iregs[i];
+ callee_registers[kRegisterNames[i]] = last_frame->context.iregs[i];
+ }
+
+ if (!cfi_frame_info->FindCallerRegs(callee_registers, *memory_,
+ &caller_registers)) {
+ return NULL;
+ }
+
+ CFIFrameInfo::RegisterValueMap<uint64_t>::const_iterator entry =
+ caller_registers.find(".cfa");
+
+ if (entry != caller_registers.end()) {
+ caller_registers["$sp"] = entry->second;
+ }
+
+ entry = caller_registers.find(".ra");
+ if (entry != caller_registers.end()) {
+ caller_registers["$ra"] = entry->second;
+ pc = entry->second - 2 * sizeof(pc);
+ }
+ caller_registers["$pc"] = pc;
+ // Construct a new stack frame given the values the CFI recovered.
+ scoped_ptr<StackFrameMIPS> frame(new StackFrameMIPS());
+
+ for (int i = 0; kRegisterNames[i]; ++i) {
+ CFIFrameInfo::RegisterValueMap<uint64_t>::const_iterator caller_entry =
+ caller_registers.find(kRegisterNames[i]);
+
+ if (caller_entry != caller_registers.end()) {
+ // The value of this register is recovered; fill the context with the
+ // value from caller_registers.
+ frame->context.iregs[i] = caller_entry->second;
+ frame->context_validity |= StackFrameMIPS::RegisterValidFlag(i);
+ } else if (((i >= INDEX_MIPS_REG_S0 && i <= INDEX_MIPS_REG_S7) ||
+ (i >= INDEX_MIPS_REG_GP && i < INDEX_MIPS_REG_RA)) &&
+ (last_frame->context_validity &
+ StackFrameMIPS::RegisterValidFlag(i))) {
+ // If the STACK CFI data doesn't mention some callee-save register, and
+ // it is valid in the callee, assume the callee has not yet changed it.
+ // Calee-save registers according to the MIPS o32 ABI specification are:
+ // $s0 to $s7
+ // $sp, $s8
+ frame->context.iregs[i] = last_frame->context.iregs[i];
+ frame->context_validity |= StackFrameMIPS::RegisterValidFlag(i);
+ }
+ }
+
+ frame->context.epc = caller_registers["$pc"];
+ frame->instruction = caller_registers["$pc"];
+ frame->context_validity |= StackFrameMIPS::CONTEXT_VALID_PC;
+
+ frame->context.iregs[MD_CONTEXT_MIPS_REG_RA] = caller_registers["$ra"];
+ frame->context_validity |= StackFrameMIPS::CONTEXT_VALID_RA;
+
+ frame->trust = StackFrame::FRAME_TRUST_CFI;
+
+ return frame.release();
+ }
+}
+
+StackFrame* StackwalkerMIPS::GetCallerFrame(const CallStack* stack,
+ bool stack_scan_allowed) {
+ if (!memory_ || !stack) {
+ BPLOG(ERROR) << "Can't get caller frame without memory or stack";
+ return NULL;
+ }
+
+ const vector<StackFrame*>& frames = *stack->frames();
+ StackFrameMIPS* last_frame = static_cast<StackFrameMIPS*>(frames.back());
+ scoped_ptr<StackFrameMIPS> new_frame;
+
+ // See if there is DWARF call frame information covering this address.
+ scoped_ptr<CFIFrameInfo> cfi_frame_info(
+ frame_symbolizer_->FindCFIFrameInfo(last_frame));
+ if (cfi_frame_info.get())
+ new_frame.reset(GetCallerByCFIFrameInfo(frames, cfi_frame_info.get()));
+
+ // If caller frame is not found in CFI try analyzing the stack.
+ if (stack_scan_allowed && !new_frame.get()) {
+ new_frame.reset(GetCallerByStackScan(frames));
+ }
+
+ // If nothing worked, tell the caller.
+ if (!new_frame.get()) {
+ return NULL;
+ }
+
+ // Should we terminate the stack walk? (end-of-stack or broken invariant)
+ if (TerminateWalk(new_frame->context.epc,
+ new_frame->context.iregs[MD_CONTEXT_MIPS_REG_SP],
+ last_frame->context.iregs[MD_CONTEXT_MIPS_REG_SP],
+ frames.size() == 1)) {
+ return NULL;
+ }
+
+ return new_frame.release();
+}
+
+StackFrameMIPS* StackwalkerMIPS::GetCallerByStackScan(
+ const vector<StackFrame*>& frames) {
+ const uint32_t kMaxFrameStackSize = 1024;
+ const uint32_t kMinArgsOnStack = 4;
+
+ StackFrameMIPS* last_frame = static_cast<StackFrameMIPS*>(frames.back());
+
+ if (context_->context_flags & MD_CONTEXT_MIPS) {
+ uint32_t last_sp = last_frame->context.iregs[MD_CONTEXT_MIPS_REG_SP];
+ uint32_t caller_pc, caller_sp, caller_fp;
+
+ // Return address cannot be obtained directly.
+ // Force stackwalking.
+
+ // We cannot use frame pointer to get the return address.
+ // We'll scan the stack for a
+ // return address. This can happen if last_frame is executing code
+ // for a module for which we don't have symbols.
+ int count = kMaxFrameStackSize / sizeof(caller_pc);
+
+ if (frames.size() > 1) {
+ // In case of mips32 ABI stack frame of a nonleaf function
+ // must have minimum stack frame assigned for 4 arguments (4 words).
+ // Move stack pointer for 4 words to avoid reporting non-existing frames
+ // for all frames except the topmost one.
+ // There is no way of knowing if topmost frame belongs to a leaf or
+ // a nonleaf function.
+ last_sp += kMinArgsOnStack * sizeof(caller_pc);
+ // Adjust 'count' so that return address is scanned only in limits
+ // of one stack frame.
+ count -= kMinArgsOnStack;
+ }
+
+ do {
+ // Scanning for return address from stack pointer of the last frame.
+ if (!ScanForReturnAddress(last_sp, &caller_sp, &caller_pc, count)) {
+ // If we can't find an instruction pointer even with stack scanning,
+ // give up.
+ BPLOG(ERROR) << " ScanForReturnAddress failed ";
+ return NULL;
+ }
+ // Get $fp stored in the stack frame.
+ if (!memory_->GetMemoryAtAddress(caller_sp - sizeof(caller_pc),
+ &caller_fp)) {
+ BPLOG(INFO) << " GetMemoryAtAddress for fp failed " ;
+ return NULL;
+ }
+
+ count = count - (caller_sp - last_sp) / sizeof(caller_pc);
+ // Now scan the next address in the stack.
+ last_sp = caller_sp + sizeof(caller_pc);
+ } while ((caller_fp - caller_sp >= kMaxFrameStackSize) && count > 0);
+
+ if (!count) {
+ BPLOG(INFO) << " No frame found " ;
+ return NULL;
+ }
+
+ // ScanForReturnAddress found a reasonable return address. Advance
+ // $sp to the location above the one where the return address was
+ // found.
+ caller_sp += sizeof(caller_pc);
+ // caller_pc is actually containing $ra value;
+ // $pc is two instructions before $ra,
+ // so the caller_pc needs to be decremented accordingly.
+ caller_pc -= 2 * sizeof(caller_pc);
+
+ // Create a new stack frame (ownership will be transferred to the caller)
+ // and fill it in.
+ StackFrameMIPS* frame = new StackFrameMIPS();
+ frame->trust = StackFrame::FRAME_TRUST_SCAN;
+ frame->context = last_frame->context;
+ frame->context.epc = caller_pc;
+ frame->context_validity |= StackFrameMIPS::CONTEXT_VALID_PC;
+ frame->instruction = caller_pc;
+
+ frame->context.iregs[MD_CONTEXT_MIPS_REG_SP] = caller_sp;
+ frame->context_validity |= StackFrameMIPS::CONTEXT_VALID_SP;
+ frame->context.iregs[MD_CONTEXT_MIPS_REG_FP] = caller_fp;
+ frame->context_validity |= StackFrameMIPS::CONTEXT_VALID_FP;
+
+ frame->context.iregs[MD_CONTEXT_MIPS_REG_RA] =
+ caller_pc + 2 * sizeof(caller_pc);
+ frame->context_validity |= StackFrameMIPS::CONTEXT_VALID_RA;
+
+ return frame;
+ } else {
+ uint64_t last_sp = last_frame->context.iregs[MD_CONTEXT_MIPS_REG_SP];
+ uint64_t caller_pc, caller_sp, caller_fp;
+
+ // Return address cannot be obtained directly.
+ // Force stackwalking.
+
+ // We cannot use frame pointer to get the return address.
+ // We'll scan the stack for a
+ // return address. This can happen if last_frame is executing code
+ // for a module for which we don't have symbols.
+ int count = kMaxFrameStackSize / sizeof(caller_pc);
+
+ do {
+ // Scanning for return address from stack pointer of the last frame.
+ if (!ScanForReturnAddress(last_sp, &caller_sp, &caller_pc, count)) {
+ // If we can't find an instruction pointer even with stack scanning,
+ // give up.
+ BPLOG(ERROR) << " ScanForReturnAddress failed ";
+ return NULL;
+ }
+ // Get $fp stored in the stack frame.
+ if (!memory_->GetMemoryAtAddress(caller_sp - sizeof(caller_pc),
+ &caller_fp)) {
+ BPLOG(INFO) << " GetMemoryAtAddress for fp failed " ;
+ return NULL;
+ }
+
+ count = count - (caller_sp - last_sp) / sizeof(caller_pc);
+ // Now scan the next address in the stack.
+ last_sp = caller_sp + sizeof(caller_pc);
+ } while ((caller_fp - caller_sp >= kMaxFrameStackSize) && count > 0);
+
+ if (!count) {
+ BPLOG(INFO) << " No frame found " ;
+ return NULL;
+ }
+
+ // ScanForReturnAddress found a reasonable return address. Advance
+ // $sp to the location above the one where the return address was
+ // found.
+ caller_sp += sizeof(caller_pc);
+ // caller_pc is actually containing $ra value;
+ // $pc is two instructions before $ra,
+ // so the caller_pc needs to be decremented accordingly.
+ caller_pc -= 2 * sizeof(caller_pc);
+
+ // Create a new stack frame (ownership will be transferred to the caller)
+ // and fill it in.
+ StackFrameMIPS* frame = new StackFrameMIPS();
+ frame->trust = StackFrame::FRAME_TRUST_SCAN;
+ frame->context = last_frame->context;
+ frame->context.epc = caller_pc;
+ frame->context_validity |= StackFrameMIPS::CONTEXT_VALID_PC;
+ frame->instruction = caller_pc;
+
+ frame->context.iregs[MD_CONTEXT_MIPS_REG_SP] = caller_sp;
+ frame->context_validity |= StackFrameMIPS::CONTEXT_VALID_SP;
+ frame->context.iregs[MD_CONTEXT_MIPS_REG_FP] = caller_fp;
+ frame->context_validity |= StackFrameMIPS::CONTEXT_VALID_FP;
+
+ frame->context.iregs[MD_CONTEXT_MIPS_REG_RA] =
+ caller_pc + 2 * sizeof(caller_pc);
+ frame->context_validity |= StackFrameMIPS::CONTEXT_VALID_RA;
+
+ return frame;
+ }
+}
+
+} // namespace google_breakpad
+
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_mips.h b/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_mips.h
new file mode 100644
index 0000000000..5f97791fb7
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_mips.h
@@ -0,0 +1,85 @@
+// 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.
+
+// stackwalker_mips.h: MIPS-specific stackwalker.
+//
+// Provides stack frames given MIPS register context and a memory region
+// corresponding to a MIPSstack.
+//
+// Author: Tata Elxsi
+
+#ifndef PROCESSOR_STACKWALKER_MIPS_H__
+#define PROCESSOR_STACKWALKER_MIPS_H__
+
+#include "google_breakpad/common/breakpad_types.h"
+#include "google_breakpad/common/minidump_format.h"
+#include "google_breakpad/processor/stackwalker.h"
+#include "google_breakpad/processor/stack_frame_cpu.h"
+#include "processor/cfi_frame_info.h"
+
+namespace google_breakpad {
+
+class CodeModules;
+
+class StackwalkerMIPS : public Stackwalker {
+ public:
+ // Context is a MIPS context object that gives access to mips-specific
+ // register state corresponding to the innermost called frame to be
+ // included in the stack. The other arguments are passed directly
+ // through to the base Stackwalker constructor.
+ StackwalkerMIPS(const SystemInfo* system_info,
+ const MDRawContextMIPS* context,
+ MemoryRegion* memory,
+ const CodeModules* modules,
+ StackFrameSymbolizer* frame_symbolizer);
+
+ private:
+ // Implementation of Stackwalker, using mips context and stack conventions.
+ virtual StackFrame* GetContextFrame();
+ virtual StackFrame* GetCallerFrame(const CallStack* stack,
+ bool stack_scan_allowed);
+
+ // Use cfi_frame_info (derived from STACK CFI records) to construct
+ // the frame that called frames.back(). The caller takes ownership
+ // of the returned frame. Return NULL on failure.
+ StackFrameMIPS* GetCallerByCFIFrameInfo(const vector<StackFrame*>& frames,
+ CFIFrameInfo* cfi_frame_info);
+
+ // Scan the stack for plausible return address and frame pointer pair.
+ // The caller takes ownership of the returned frame. Return NULL on failure.
+ StackFrameMIPS* GetCallerByStackScan(const vector<StackFrame*>& frames);
+
+ // Stores the CPU context corresponding to the innermost stack frame to
+ // be returned by GetContextFrame.
+ const MDRawContextMIPS* context_;
+};
+
+} // namespace google_breakpad
+
+#endif // PROCESSOR_STACKWALKER_MIPS_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_mips64_unittest.cc b/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_mips64_unittest.cc
new file mode 100644
index 0000000000..2a9784bf71
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_mips64_unittest.cc
@@ -0,0 +1,716 @@
+// 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: Veljko Mihailovic <veljko.mihailovic@imgtec.com>
+
+// stackwalker_mips64_unittest.cc: Unit tests for StackwalkerMIPS class for
+// mips64 platforms.
+
+#include <string.h>
+#include <string>
+#include <vector>
+
+#include "breakpad_googletest_includes.h"
+#include "common/test_assembler.h"
+#include "common/using_std_string.h"
+#include "google_breakpad/common/minidump_format.h"
+#include "google_breakpad/processor/basic_source_line_resolver.h"
+#include "google_breakpad/processor/call_stack.h"
+#include "google_breakpad/processor/code_module.h"
+#include "google_breakpad/processor/source_line_resolver_interface.h"
+#include "google_breakpad/processor/stack_frame_cpu.h"
+#include "processor/stackwalker_unittest_utils.h"
+#include "processor/stackwalker_mips.h"
+#include "processor/windows_frame_info.h"
+
+using google_breakpad::BasicSourceLineResolver;
+using google_breakpad::CallStack;
+using google_breakpad::CodeModule;
+using google_breakpad::StackFrameSymbolizer;
+using google_breakpad::StackFrame;
+using google_breakpad::StackFrameMIPS;
+using google_breakpad::Stackwalker;
+using google_breakpad::StackwalkerMIPS;
+using google_breakpad::SystemInfo;
+using google_breakpad::WindowsFrameInfo;
+using google_breakpad::test_assembler::kLittleEndian;
+using google_breakpad::test_assembler::Label;
+using google_breakpad::test_assembler::Section;
+using std::vector;
+using testing::_;
+using testing::AnyNumber;
+using testing::Return;
+using testing::SetArgumentPointee;
+using testing::Test;
+
+class StackwalkerMIPSFixture {
+ public:
+ StackwalkerMIPSFixture()
+ : stack_section(kLittleEndian),
+ // Give the two modules reasonable standard locations and names
+ // for tests to play with.
+ module1(0x00400000, 0x10000, "module1", "version1"),
+ module2(0x00500000, 0x10000, "module2", "version2") {
+ // Identify the system as a Linux system.
+ system_info.os = "Linux";
+ system_info.os_short = "linux";
+ system_info.os_version = "Observant Opossum"; // Jealous Jellyfish
+ system_info.cpu = "mips64";
+ system_info.cpu_info = "";
+
+ // Put distinctive values in the raw CPU context.
+ BrandContext(&raw_context);
+
+ // Create some modules with some stock debugging information.
+ modules.Add(&module1);
+ modules.Add(&module2);
+
+ // By default, none of the modules have symbol info; call
+ // SetModuleSymbols to override this.
+ EXPECT_CALL(supplier, GetCStringSymbolData(_, _, _, _, _))
+ .WillRepeatedly(Return(MockSymbolSupplier::NOT_FOUND));
+
+ // Avoid GMOCK WARNING "Uninteresting mock function call - returning
+ // directly" for FreeSymbolData().
+ EXPECT_CALL(supplier, FreeSymbolData(_)).Times(AnyNumber());
+
+ // Reset max_frames_scanned since it's static.
+ Stackwalker::set_max_frames_scanned(1024);
+ }
+
+ // Set the Breakpad symbol information that supplier should return for
+ // MODULE to INFO.
+ void SetModuleSymbols(MockCodeModule* module, const string& info) {
+ size_t buffer_size;
+ char* buffer = supplier.CopySymbolDataAndOwnTheCopy(info, &buffer_size);
+ EXPECT_CALL(supplier, GetCStringSymbolData(module, &system_info, _, _, _))
+ .WillRepeatedly(DoAll(SetArgumentPointee<3>(buffer),
+ SetArgumentPointee<4>(buffer_size),
+ Return(MockSymbolSupplier::FOUND)));
+ }
+
+ // Populate stack_region with the contents of stack_section. Use
+ // stack_section.start() as the region's starting address.
+ void RegionFromSection() {
+ string contents;
+ ASSERT_TRUE(stack_section.GetContents(&contents));
+ stack_region.Init(stack_section.start().Value(), contents);
+ }
+
+ // Fill RAW_CONTEXT with pseudo-random data, for round-trip checking.
+ void BrandContext(MDRawContextMIPS* raw_context) {
+ uint8_t x = 173;
+ for (size_t i = 0; i < sizeof(*raw_context); ++i)
+ reinterpret_cast<uint8_t*>(raw_context)[i] = (x += 17);
+ }
+
+ SystemInfo system_info;
+ MDRawContextMIPS raw_context;
+ Section stack_section;
+ MockMemoryRegion stack_region;
+ MockCodeModule module1;
+ MockCodeModule module2;
+ MockCodeModules modules;
+ MockSymbolSupplier supplier;
+ BasicSourceLineResolver resolver;
+ CallStack call_stack;
+ const vector<StackFrame*>* frames;
+};
+
+class SanityCheck: public StackwalkerMIPSFixture, public Test { };
+
+TEST_F(SanityCheck, NoResolver) {
+ raw_context.context_flags =
+ raw_context.context_flags | MD_CONTEXT_MIPS64_FULL;
+ stack_section.start() = 0x80000000;
+ stack_section.D64(0).D64(0x0);
+ RegionFromSection();
+ raw_context.epc = 0x00400020;
+ raw_context.iregs[MD_CONTEXT_MIPS_REG_SP] = 0x80000000;
+
+ StackFrameSymbolizer frame_symbolizer(NULL, NULL);
+ StackwalkerMIPS walker(&system_info, &raw_context, &stack_region, &modules,
+ &frame_symbolizer);
+ // This should succeed, even without a resolver or supplier.
+ vector<const CodeModule*> modules_without_symbols;
+ vector<const CodeModule*> modules_with_corrupt_symbols;
+ ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
+ &modules_with_corrupt_symbols));
+ ASSERT_EQ(1U, modules_without_symbols.size());
+ ASSERT_EQ("module1", modules_without_symbols[0]->debug_file());
+ ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
+ frames = call_stack.frames();
+ ASSERT_EQ(1U, frames->size());
+ StackFrameMIPS* frame = static_cast<StackFrameMIPS*>(frames->at(0));
+ // Check that the values from the original raw context made it
+ // through to the context in the stack frame.
+ EXPECT_EQ(0, memcmp(&raw_context, &frame->context, sizeof(raw_context)));
+}
+
+class GetContextFrame: public StackwalkerMIPSFixture, public Test { };
+
+TEST_F(GetContextFrame, Simple) {
+ raw_context.context_flags =
+ raw_context.context_flags | MD_CONTEXT_MIPS64_FULL;
+ stack_section.start() = 0x80000000;
+ stack_section.D64(0).D64(0x0);
+ RegionFromSection();
+ raw_context.epc = 0x00400020;
+ raw_context.iregs[MD_CONTEXT_MIPS_REG_SP] = 0x80000000;
+
+ StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
+ StackwalkerMIPS walker(&system_info, &raw_context, &stack_region, &modules,
+ &frame_symbolizer);
+ vector<const CodeModule*> modules_without_symbols;
+ vector<const CodeModule*> modules_with_corrupt_symbols;
+ ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
+ &modules_with_corrupt_symbols));
+ ASSERT_EQ(1U, modules_without_symbols.size());
+ ASSERT_EQ("module1", modules_without_symbols[0]->debug_file());
+ ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
+ frames = call_stack.frames();
+ StackFrameMIPS* frame = static_cast<StackFrameMIPS*>(frames->at(0));
+ // Check that the values from the original raw context made it
+ // through to the context in the stack frame.
+ EXPECT_EQ(0, memcmp(&raw_context, &frame->context, sizeof(raw_context)));
+}
+
+// The stackwalker should be able to produce the context frame even
+// without stack memory present.
+TEST_F(GetContextFrame, NoStackMemory) {
+ raw_context.context_flags =
+ raw_context.context_flags | MD_CONTEXT_MIPS64_FULL;
+ raw_context.epc = 0x00400020;
+ raw_context.iregs[MD_CONTEXT_MIPS_REG_SP] = 0x80000000;
+
+ StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
+ StackwalkerMIPS walker(&system_info, &raw_context, NULL, &modules,
+ &frame_symbolizer);
+ vector<const CodeModule*> modules_without_symbols;
+ vector<const CodeModule*> modules_with_corrupt_symbols;
+ ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
+ &modules_with_corrupt_symbols));
+ ASSERT_EQ(1U, modules_without_symbols.size());
+ ASSERT_EQ("module1", modules_without_symbols[0]->debug_file());
+ ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
+ frames = call_stack.frames();
+ StackFrameMIPS* frame = static_cast<StackFrameMIPS*>(frames->at(0));
+ // Check that the values from the original raw context made it
+ // through to the context in the stack frame.
+ EXPECT_EQ(0, memcmp(&raw_context, &frame->context, sizeof(raw_context)));
+}
+
+class GetCallerFrame: public StackwalkerMIPSFixture, public Test { };
+
+TEST_F(GetCallerFrame, ScanWithoutSymbols) {
+ raw_context.context_flags =
+ raw_context.context_flags | MD_CONTEXT_MIPS64_FULL;
+ // When the stack walker resorts to scanning the stack,
+ // only addresses located within loaded modules are
+ // considered valid return addresses.
+ // Force scanning through three frames to ensure that the
+ // stack pointer is set properly in scan-recovered frames.
+ stack_section.start() = 0x80000000;
+ uint64_t return_address1 = 0x00400100;
+ uint64_t return_address2 = 0x00400900;
+ Label frame1_sp, frame2_sp;
+ stack_section
+ // frame 0
+ .Append(32, 0) // space
+
+ .D64(0x00490000) // junk that's not
+ .D64(0x00600000) // a return address
+
+ .D64(frame1_sp) // stack pointer
+ .D64(return_address1) // actual return address
+ // frame 1
+ .Mark(&frame1_sp)
+ .Append(32, 0) // space
+
+ .D64(0xF0000000) // more junk
+ .D64(0x0000000D)
+
+ .D64(frame2_sp) // stack pointer
+ .D64(return_address2) // actual return address
+ // frame 2
+ .Mark(&frame2_sp)
+ .Append(64, 0); // end of stack
+ RegionFromSection();
+
+ raw_context.epc = 0x00405510;
+ raw_context.iregs[MD_CONTEXT_MIPS_REG_SP] = stack_section.start().Value();
+ raw_context.iregs[MD_CONTEXT_MIPS_REG_RA] = return_address1;
+
+ StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
+ StackwalkerMIPS walker(&system_info, &raw_context, &stack_region, &modules,
+ &frame_symbolizer);
+ vector<const CodeModule*> modules_without_symbols;
+ vector<const CodeModule*> modules_with_corrupt_symbols;
+ ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
+ &modules_with_corrupt_symbols));
+ ASSERT_EQ(1U, modules_without_symbols.size());
+ ASSERT_EQ("module1", modules_without_symbols[0]->debug_file());
+ ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
+ frames = call_stack.frames();
+ ASSERT_EQ(3U, frames->size());
+
+ StackFrameMIPS* frame0 = static_cast<StackFrameMIPS*>(frames->at(0));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
+ ASSERT_EQ(StackFrameMIPS::CONTEXT_VALID_ALL, frame0->context_validity);
+ EXPECT_EQ(0, memcmp(&raw_context, &frame0->context, sizeof(raw_context)));
+
+ StackFrameMIPS* frame1 = static_cast<StackFrameMIPS*>(frames->at(1));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust);
+ ASSERT_EQ((StackFrameMIPS::CONTEXT_VALID_PC |
+ StackFrameMIPS::CONTEXT_VALID_SP |
+ StackFrameMIPS::CONTEXT_VALID_FP |
+ StackFrameMIPS::CONTEXT_VALID_RA),
+ frame1->context_validity);
+ EXPECT_EQ(return_address1 - 2 * sizeof(return_address1), frame1->context.epc);
+ EXPECT_EQ(frame1_sp.Value(), frame1->context.iregs[MD_CONTEXT_MIPS_REG_SP]);
+
+ StackFrameMIPS* frame2 = static_cast<StackFrameMIPS*>(frames->at(2));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame2->trust);
+ ASSERT_EQ((StackFrameMIPS::CONTEXT_VALID_PC |
+ StackFrameMIPS::CONTEXT_VALID_SP |
+ StackFrameMIPS::CONTEXT_VALID_FP |
+ StackFrameMIPS::CONTEXT_VALID_RA),
+ frame2->context_validity);
+ EXPECT_EQ(return_address2 - 2 * sizeof(return_address2), frame2->context.epc);
+ EXPECT_EQ(frame2_sp.Value(), frame2->context.iregs[MD_CONTEXT_MIPS_REG_SP]);
+}
+
+TEST_F(GetCallerFrame, ScanWithFunctionSymbols) {
+ raw_context.context_flags =
+ raw_context.context_flags | MD_CONTEXT_MIPS64_FULL;
+ // During stack scanning, if a potential return address
+ // is located within a loaded module that has symbols,
+ // it is only considered a valid return address if it
+ // lies within a function's bounds.
+ stack_section.start() = 0x80000000;
+ uint64_t return_address = 0x00500200;
+ Label frame1_sp;
+ stack_section
+ // frame 0
+ .Append(16, 0) // space
+
+ .D64(0x00490000) // junk that's not
+ .D64(0x00600000) // a return address
+
+ .D64(0x00401000) // a couple of plausible addresses
+ .D64(0x0050F000) // that are not within functions
+
+ .D64(frame1_sp) // stack pointer
+ .D64(return_address) // actual return address
+ // frame 1
+ .Mark(&frame1_sp)
+ .Append(64, 0); // end of stack
+ RegionFromSection();
+
+ raw_context.epc = 0x00400200;
+ raw_context.iregs[MD_CONTEXT_MIPS_REG_SP] = stack_section.start().Value();
+ raw_context.iregs[MD_CONTEXT_MIPS_REG_RA] = return_address;
+
+ SetModuleSymbols(&module1,
+ // The youngest frame's function.
+ "FUNC 100 400 10 monotreme\n");
+ SetModuleSymbols(&module2,
+ // The calling frame's function.
+ "FUNC 100 400 10 marsupial\n");
+
+ StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
+ StackwalkerMIPS walker(&system_info, &raw_context, &stack_region, &modules,
+ &frame_symbolizer);
+ vector<const CodeModule*> modules_without_symbols;
+ vector<const CodeModule*> modules_with_corrupt_symbols;
+ ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
+ &modules_with_corrupt_symbols));
+ ASSERT_EQ(0U, modules_without_symbols.size());
+ ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
+ frames = call_stack.frames();
+ ASSERT_EQ(2U, frames->size());
+
+ StackFrameMIPS* frame0 = static_cast<StackFrameMIPS*>(frames->at(0));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
+ ASSERT_EQ(StackFrameMIPS::CONTEXT_VALID_ALL, frame0->context_validity);
+ EXPECT_EQ(0, memcmp(&raw_context, &frame0->context, sizeof(raw_context)));
+ EXPECT_EQ("monotreme", frame0->function_name);
+ EXPECT_EQ(0x00400100U, frame0->function_base);
+
+ StackFrameMIPS* frame1 = static_cast<StackFrameMIPS*>(frames->at(1));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust);
+ ASSERT_EQ((StackFrameMIPS::CONTEXT_VALID_PC |
+ StackFrameMIPS::CONTEXT_VALID_SP |
+ StackFrameMIPS::CONTEXT_VALID_FP |
+ StackFrameMIPS::CONTEXT_VALID_RA),
+ frame1->context_validity);
+ EXPECT_EQ(return_address - 2 * sizeof(return_address), frame1->context.epc);
+ EXPECT_EQ(frame1_sp.Value(), frame1->context.iregs[MD_CONTEXT_MIPS_REG_SP]);
+ EXPECT_EQ("marsupial", frame1->function_name);
+ EXPECT_EQ(0x00500100U, frame1->function_base);
+}
+
+TEST_F(GetCallerFrame, CheckStackFrameSizeLimit) {
+ raw_context.context_flags =
+ raw_context.context_flags | MD_CONTEXT_MIPS64_FULL;
+ // If the stackwalker resorts to stack scanning, it will scan only
+ // 1024 bytes of stack which correspondes to maximum size of stack frame.
+ stack_section.start() = 0x80000000;
+ uint64_t return_address1 = 0x00500100;
+ uint64_t return_address2 = 0x00500900;
+ Label frame1_sp, frame2_sp;
+ stack_section
+ // frame 0
+ .Append(32, 0) // space
+
+ .D64(0x00490000) // junk that's not
+ .D64(0x00600000) // a return address
+
+ .Append(96, 0) // more space
+
+ .D64(frame1_sp) // stack pointer
+ .D64(return_address1) // actual return address
+ // frame 1
+ .Mark(&frame1_sp)
+ .Append(128 * 4, 0) // space
+
+ .D64(0x00F00000) // more junk
+ .D64(0x0000000D)
+
+ .Append(128 * 4, 0) // more space
+
+ .D64(frame2_sp) // stack pointer
+ .D64(return_address2) // actual return address
+ // (won't be found)
+ // frame 2
+ .Mark(&frame2_sp)
+ .Append(64, 0); // end of stack
+ RegionFromSection();
+
+ raw_context.epc = 0x00405510;
+ raw_context.iregs[MD_CONTEXT_MIPS_REG_SP] = stack_section.start().Value();
+ raw_context.iregs[MD_CONTEXT_MIPS_REG_RA] = return_address1;
+
+ StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
+ StackwalkerMIPS walker(&system_info, &raw_context, &stack_region, &modules,
+ &frame_symbolizer);
+ vector<const CodeModule*> modules_without_symbols;
+ vector<const CodeModule*> modules_with_corrupt_symbols;
+ ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
+ &modules_with_corrupt_symbols));
+ ASSERT_EQ(2U, modules_without_symbols.size());
+ ASSERT_EQ("module1", modules_without_symbols[0]->debug_file());
+ ASSERT_EQ("module2", modules_without_symbols[1]->debug_file());
+ ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
+ frames = call_stack.frames();
+ ASSERT_EQ(2U, frames->size());
+
+ StackFrameMIPS* frame0 = static_cast<StackFrameMIPS*>(frames->at(0));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
+ ASSERT_EQ(StackFrameMIPS::CONTEXT_VALID_ALL, frame0->context_validity);
+ EXPECT_EQ(0, memcmp(&raw_context, &frame0->context, sizeof(raw_context)));
+
+ StackFrameMIPS* frame1 = static_cast<StackFrameMIPS*>(frames->at(1));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust);
+ ASSERT_EQ((StackFrameMIPS::CONTEXT_VALID_PC |
+ StackFrameMIPS::CONTEXT_VALID_SP |
+ StackFrameMIPS::CONTEXT_VALID_FP |
+ StackFrameMIPS::CONTEXT_VALID_RA),
+ frame1->context_validity);
+ EXPECT_EQ(return_address1 - 2 * sizeof(return_address1), frame1->context.epc);
+ EXPECT_EQ(frame1_sp.Value(), frame1->context.iregs[MD_CONTEXT_MIPS_REG_SP]);
+}
+
+// Test that set_max_frames_scanned prevents using stack scanning
+// to find caller frames.
+TEST_F(GetCallerFrame, ScanningNotAllowed) {
+ raw_context.context_flags =
+ raw_context.context_flags | MD_CONTEXT_MIPS64_FULL;
+ // When the stack walker resorts to scanning the stack,
+ // only fixed number of frames are allowed to be scanned out from stack
+ stack_section.start() = 0x80000000;
+ uint64_t return_address1 = 0x00500100;
+ uint64_t return_address2 = 0x00500900;
+ Label frame1_sp, frame2_sp;
+ stack_section
+ // frame 0
+ .Append(32, 0) // space
+
+ .D64(0x00490000) // junk that's not
+ .D64(0x00600000) // a return address
+
+ .Append(96, 0) // more space
+
+ .D64(frame1_sp) // stack pointer
+ .D64(return_address1) // actual return address
+ // frame 1
+ .Mark(&frame1_sp)
+ .Append(128 * 4, 0) // space
+
+ .D64(0x00F00000) // more junk
+ .D64(0x0000000D)
+
+ .Append(128 * 4, 0) // more space
+
+ .D64(frame2_sp) // stack pointer
+ .D64(return_address2) // actual return address
+ // (won't be found)
+ // frame 2
+ .Mark(&frame2_sp)
+ .Append(64, 0); // end of stack
+ RegionFromSection();
+
+ raw_context.epc = 0x00405510;
+ raw_context.iregs[MD_CONTEXT_MIPS_REG_SP] = stack_section.start().Value();
+ raw_context.iregs[MD_CONTEXT_MIPS_REG_RA] = return_address1;
+
+ StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
+ StackwalkerMIPS walker(&system_info, &raw_context, &stack_region, &modules,
+ &frame_symbolizer);
+ Stackwalker::set_max_frames_scanned(0);
+
+ vector<const CodeModule*> modules_without_symbols;
+ vector<const CodeModule*> modules_with_corrupt_symbols;
+ ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
+ &modules_with_corrupt_symbols));
+ ASSERT_EQ(1U, modules_without_symbols.size());
+ ASSERT_EQ("module1", modules_without_symbols[0]->debug_file());
+ ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
+ frames = call_stack.frames();
+ ASSERT_EQ(1U, frames->size());
+
+ StackFrameMIPS* frame0 = static_cast<StackFrameMIPS*>(frames->at(0));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
+ ASSERT_EQ(StackFrameMIPS::CONTEXT_VALID_ALL, frame0->context_validity);
+ EXPECT_EQ(0, memcmp(&raw_context, &frame0->context, sizeof(raw_context)));
+}
+
+struct CFIFixture: public StackwalkerMIPSFixture {
+ CFIFixture() {
+ // Provide some STACK CFI records;
+ SetModuleSymbols(&module1,
+ // The youngest frame's function.
+ "FUNC 4000 1000 0 enchiridion\n"
+ // Initially, nothing has been pushed on the stack,
+ // and the return address is still in the $ra register.
+ "STACK CFI INIT 4000 1000 .cfa: $sp 0 + .ra: $ra\n"
+ // Move stack pointer.
+ "STACK CFI 4004 .cfa: $sp 32 +\n"
+ // store $fp and ra
+ "STACK CFI 4008 $fp: .cfa -8 + ^ .ra: .cfa -4 + ^\n"
+ // restore $fp
+ "STACK CFI 400c .cfa: $fp 32 +\n"
+ // restore $sp
+ "STACK CFI 4018 .cfa: $sp 32 +\n"
+
+ "STACK CFI 4020 $fp: $fp .cfa: $sp 0 + .ra: .ra\n"
+
+ // The calling function.
+ "FUNC 5000 1000 0 epictetus\n"
+ // Mark it as end of stack.
+ "STACK CFI INIT 5000 8 .cfa: $sp 0 + .ra: $ra\n"
+
+ // A function whose CFI makes the stack pointer
+ // go backwards.
+ "FUNC 6000 1000 20 palinal\n"
+ "STACK CFI INIT 6000 1000 .cfa: $sp 4 - .ra: $ra\n"
+
+ // A function with CFI expressions that can't be
+ // evaluated.
+ "FUNC 7000 1000 20 rhetorical\n"
+ "STACK CFI INIT 7000 1000 .cfa: moot .ra: ambiguous\n"
+ );
+
+ // Provide some distinctive values for the caller's registers.
+ expected.epc = 0x00405500;
+ expected.iregs[MD_CONTEXT_MIPS_REG_S0] = 0x0;
+ expected.iregs[MD_CONTEXT_MIPS_REG_S1] = 0x1;
+ expected.iregs[MD_CONTEXT_MIPS_REG_S2] = 0x2;
+ expected.iregs[MD_CONTEXT_MIPS_REG_S3] = 0x3;
+ expected.iregs[MD_CONTEXT_MIPS_REG_S4] = 0x4;
+ expected.iregs[MD_CONTEXT_MIPS_REG_S5] = 0x5;
+ expected.iregs[MD_CONTEXT_MIPS_REG_S6] = 0x6;
+ expected.iregs[MD_CONTEXT_MIPS_REG_S7] = 0x7;
+ expected.iregs[MD_CONTEXT_MIPS_REG_SP] = 0x80000000;
+ expected.iregs[MD_CONTEXT_MIPS_REG_FP] = 0x80000000;
+ expected.iregs[MD_CONTEXT_MIPS_REG_RA] = 0x00405510;
+
+ // Expect CFI to recover all callee-save registers. Since CFI is the
+ // only stack frame construction technique we have, aside from the
+ // context frame itself, there's no way for us to have a set of valid
+ // registers smaller than this.
+ expected_validity = (StackFrameMIPS::CONTEXT_VALID_PC |
+ StackFrameMIPS::CONTEXT_VALID_S0 |
+ StackFrameMIPS::CONTEXT_VALID_S1 |
+ StackFrameMIPS::CONTEXT_VALID_S2 |
+ StackFrameMIPS::CONTEXT_VALID_S3 |
+ StackFrameMIPS::CONTEXT_VALID_S4 |
+ StackFrameMIPS::CONTEXT_VALID_S5 |
+ StackFrameMIPS::CONTEXT_VALID_S6 |
+ StackFrameMIPS::CONTEXT_VALID_S7 |
+ StackFrameMIPS::CONTEXT_VALID_SP |
+ StackFrameMIPS::CONTEXT_VALID_FP |
+ StackFrameMIPS::CONTEXT_VALID_GP |
+ StackFrameMIPS::CONTEXT_VALID_RA);
+
+ // By default, context frames provide all registers, as normal.
+ context_frame_validity = StackFrameMIPS::CONTEXT_VALID_ALL;
+
+ // By default, registers are unchanged.
+ raw_context = expected;
+ }
+
+ // Walk the stack, using stack_section as the contents of the stack
+ // and raw_context as the current register values. (Set the stack
+ // pointer to the stack's starting address.) Expect two stack
+ // frames; in the older frame, expect the callee-saves registers to
+ // have values matching those in 'expected'.
+ void CheckWalk() {
+ RegionFromSection();
+ raw_context.iregs[MD_CONTEXT_MIPS_REG_SP] = stack_section.start().Value();
+
+ StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
+ StackwalkerMIPS walker(&system_info, &raw_context, &stack_region,
+ &modules, &frame_symbolizer);
+ vector<const CodeModule*> modules_without_symbols;
+ vector<const CodeModule*> modules_with_corrupt_symbols;
+ ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
+ &modules_with_corrupt_symbols));
+ ASSERT_EQ(0U, modules_without_symbols.size());
+ ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
+ frames = call_stack.frames();
+ ASSERT_EQ(2U, frames->size());
+
+ StackFrameMIPS* frame0 = static_cast<StackFrameMIPS*>(frames->at(0));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
+ ASSERT_EQ(StackFrameMIPS::CONTEXT_VALID_ALL, frame0->context_validity);
+ EXPECT_EQ("enchiridion", frame0->function_name);
+ EXPECT_EQ(0x00404000U, frame0->function_base);
+
+ StackFrameMIPS* frame1 = static_cast<StackFrameMIPS*>(frames->at(1));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame1->trust);
+ ASSERT_EQ(expected_validity, frame1->context_validity);
+ EXPECT_EQ(expected.iregs[MD_CONTEXT_MIPS_REG_S0],
+ frame1->context.iregs[MD_CONTEXT_MIPS_REG_S0]);
+ EXPECT_EQ(expected.iregs[MD_CONTEXT_MIPS_REG_S1],
+ frame1->context.iregs[MD_CONTEXT_MIPS_REG_S1]);
+ EXPECT_EQ(expected.iregs[MD_CONTEXT_MIPS_REG_S2],
+ frame1->context.iregs[MD_CONTEXT_MIPS_REG_S2]);
+ EXPECT_EQ(expected.iregs[MD_CONTEXT_MIPS_REG_S3],
+ frame1->context.iregs[MD_CONTEXT_MIPS_REG_S3]);
+ EXPECT_EQ(expected.iregs[MD_CONTEXT_MIPS_REG_S4],
+ frame1->context.iregs[MD_CONTEXT_MIPS_REG_S4]);
+ EXPECT_EQ(expected.iregs[MD_CONTEXT_MIPS_REG_S5],
+ frame1->context.iregs[MD_CONTEXT_MIPS_REG_S5]);
+ EXPECT_EQ(expected.iregs[MD_CONTEXT_MIPS_REG_S6],
+ frame1->context.iregs[MD_CONTEXT_MIPS_REG_S6]);
+ EXPECT_EQ(expected.iregs[MD_CONTEXT_MIPS_REG_S7],
+ frame1->context.iregs[MD_CONTEXT_MIPS_REG_S7]);
+ EXPECT_EQ(expected.iregs[MD_CONTEXT_MIPS_REG_FP],
+ frame1->context.iregs[MD_CONTEXT_MIPS_REG_FP]);
+ EXPECT_EQ(expected.iregs[MD_CONTEXT_MIPS_REG_RA],
+ frame1->context.iregs[MD_CONTEXT_MIPS_REG_RA]);
+ EXPECT_EQ(expected.iregs[MD_CONTEXT_MIPS_REG_SP],
+ frame1->context.iregs[MD_CONTEXT_MIPS_REG_SP]);
+ EXPECT_EQ(expected.epc, frame1->context.epc);
+ EXPECT_EQ(expected.epc, frame1->instruction);
+ EXPECT_EQ("epictetus", frame1->function_name);
+ EXPECT_EQ(0x00405000U, frame1->function_base);
+ }
+
+ // The values we expect to find for the caller's registers.
+ MDRawContextMIPS expected;
+
+ // The validity mask for expected.
+ int expected_validity;
+
+ // The validity mask to impose on the context frame.
+ int context_frame_validity;
+};
+
+class CFI: public CFIFixture, public Test { };
+
+// TODO(gordanac): add CFI tests
+
+TEST_F(CFI, At4004) {
+ raw_context.context_flags =
+ raw_context.context_flags | MD_CONTEXT_MIPS64_FULL;
+ Label frame1_sp = expected.iregs[MD_CONTEXT_MIPS_REG_SP];
+ stack_section
+ // frame0
+ .Append(16, 0) // space
+ .D64(frame1_sp) // stack pointer
+ .D64(0x00405510) // return address
+ .Mark(&frame1_sp); // This effectively sets stack_section.start().
+ raw_context.epc = 0x00404004;
+ CheckWalk();
+}
+
+// Check that we reject rules that would cause the stack pointer to
+// move in the wrong direction.
+TEST_F(CFI, RejectBackwards) {
+ raw_context.context_flags =
+ raw_context.context_flags | MD_CONTEXT_MIPS64_FULL;
+ raw_context.epc = 0x40005000;
+ raw_context.iregs[MD_CONTEXT_MIPS_REG_SP] = 0x80000000;
+ raw_context.iregs[MD_CONTEXT_MIPS_REG_RA] = 0x00405510;
+
+ StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
+ StackwalkerMIPS walker(&system_info, &raw_context, &stack_region, &modules,
+ &frame_symbolizer);
+ vector<const CodeModule*> modules_without_symbols;
+ vector<const CodeModule*> modules_with_corrupt_symbols;
+ ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
+ &modules_with_corrupt_symbols));
+ ASSERT_EQ(0U, modules_without_symbols.size());
+ ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
+ frames = call_stack.frames();
+ ASSERT_EQ(1U, frames->size());
+}
+
+// Check that we reject rules whose expressions' evaluation fails.
+TEST_F(CFI, RejectBadExpressions) {
+ raw_context.context_flags =
+ raw_context.context_flags | MD_CONTEXT_MIPS64_FULL;
+ raw_context.epc = 0x00407000;
+ raw_context.iregs[MD_CONTEXT_MIPS_REG_SP] = 0x80000000;
+ raw_context.iregs[MD_CONTEXT_MIPS_REG_RA] = 0x00405510;
+
+ StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
+ StackwalkerMIPS walker(&system_info, &raw_context, &stack_region, &modules,
+ &frame_symbolizer);
+ vector<const CodeModule*> modules_without_symbols;
+ vector<const CodeModule*> modules_with_corrupt_symbols;
+ ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
+ &modules_with_corrupt_symbols));
+ ASSERT_EQ(0U, modules_without_symbols.size());
+ ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
+ frames = call_stack.frames();
+ ASSERT_EQ(1U, frames->size());
+}
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_mips_unittest.cc b/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_mips_unittest.cc
new file mode 100644
index 0000000000..a172f17b9d
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_mips_unittest.cc
@@ -0,0 +1,704 @@
+// 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: Gordana Cmiljanovic <gordana.cmiljanovic@imgtec.com>
+
+// stackwalker_mips_unittest.cc: Unit tests for StackwalkerMIPS class.
+
+#include <string.h>
+#include <string>
+#include <vector>
+
+#include "breakpad_googletest_includes.h"
+#include "common/test_assembler.h"
+#include "common/using_std_string.h"
+#include "google_breakpad/common/minidump_format.h"
+#include "google_breakpad/processor/basic_source_line_resolver.h"
+#include "google_breakpad/processor/call_stack.h"
+#include "google_breakpad/processor/code_module.h"
+#include "google_breakpad/processor/source_line_resolver_interface.h"
+#include "google_breakpad/processor/stack_frame_cpu.h"
+#include "processor/stackwalker_unittest_utils.h"
+#include "processor/stackwalker_mips.h"
+#include "processor/windows_frame_info.h"
+
+using google_breakpad::BasicSourceLineResolver;
+using google_breakpad::CallStack;
+using google_breakpad::CodeModule;
+using google_breakpad::StackFrameSymbolizer;
+using google_breakpad::StackFrame;
+using google_breakpad::StackFrameMIPS;
+using google_breakpad::Stackwalker;
+using google_breakpad::StackwalkerMIPS;
+using google_breakpad::SystemInfo;
+using google_breakpad::WindowsFrameInfo;
+using google_breakpad::test_assembler::kLittleEndian;
+using google_breakpad::test_assembler::Label;
+using google_breakpad::test_assembler::Section;
+using std::vector;
+using testing::_;
+using testing::AnyNumber;
+using testing::Return;
+using testing::SetArgumentPointee;
+using testing::Test;
+
+class StackwalkerMIPSFixture {
+ public:
+ StackwalkerMIPSFixture()
+ : stack_section(kLittleEndian),
+ // Give the two modules reasonable standard locations and names
+ // for tests to play with.
+ module1(0x00400000, 0x10000, "module1", "version1"),
+ module2(0x00500000, 0x10000, "module2", "version2") {
+ // Identify the system as a Linux system.
+ system_info.os = "Linux";
+ system_info.os_short = "linux";
+ system_info.os_version = "Observant Opossum"; // Jealous Jellyfish
+ system_info.cpu = "mips";
+ system_info.cpu_info = "";
+
+ // Put distinctive values in the raw CPU context.
+ BrandContext(&raw_context);
+
+ // Create some modules with some stock debugging information.
+ modules.Add(&module1);
+ modules.Add(&module2);
+
+ // By default, none of the modules have symbol info; call
+ // SetModuleSymbols to override this.
+ EXPECT_CALL(supplier, GetCStringSymbolData(_, _, _, _, _))
+ .WillRepeatedly(Return(MockSymbolSupplier::NOT_FOUND));
+
+ // Avoid GMOCK WARNING "Uninteresting mock function call - returning
+ // directly" for FreeSymbolData().
+ EXPECT_CALL(supplier, FreeSymbolData(_)).Times(AnyNumber());
+
+ // Reset max_frames_scanned since it's static.
+ Stackwalker::set_max_frames_scanned(1024);
+ }
+
+ // Set the Breakpad symbol information that supplier should return for
+ // MODULE to INFO.
+ void SetModuleSymbols(MockCodeModule* module, const string& info) {
+ size_t buffer_size;
+ char* buffer = supplier.CopySymbolDataAndOwnTheCopy(info, &buffer_size);
+ EXPECT_CALL(supplier, GetCStringSymbolData(module, &system_info, _, _, _))
+ .WillRepeatedly(DoAll(SetArgumentPointee<3>(buffer),
+ SetArgumentPointee<4>(buffer_size),
+ Return(MockSymbolSupplier::FOUND)));
+ }
+
+ // Populate stack_region with the contents of stack_section. Use
+ // stack_section.start() as the region's starting address.
+ void RegionFromSection() {
+ string contents;
+ ASSERT_TRUE(stack_section.GetContents(&contents));
+ stack_region.Init(stack_section.start().Value(), contents);
+ }
+
+ // Fill RAW_CONTEXT with pseudo-random data, for round-trip checking.
+ void BrandContext(MDRawContextMIPS* raw_context) {
+ uint8_t x = 173;
+ for (size_t i = 0; i < sizeof(*raw_context); ++i)
+ reinterpret_cast<uint8_t*>(raw_context)[i] = (x += 17);
+ }
+
+ SystemInfo system_info;
+ MDRawContextMIPS raw_context;
+ Section stack_section;
+ MockMemoryRegion stack_region;
+ MockCodeModule module1;
+ MockCodeModule module2;
+ MockCodeModules modules;
+ MockSymbolSupplier supplier;
+ BasicSourceLineResolver resolver;
+ CallStack call_stack;
+ const vector<StackFrame*>* frames;
+};
+
+class SanityCheck: public StackwalkerMIPSFixture, public Test { };
+
+TEST_F(SanityCheck, NoResolver) {
+ raw_context.context_flags = raw_context.context_flags | MD_CONTEXT_MIPS_FULL;
+ stack_section.start() = 0x80000000;
+ stack_section.D32(0).D32(0x0);
+ RegionFromSection();
+ raw_context.epc = 0x00400020;
+ raw_context.iregs[MD_CONTEXT_MIPS_REG_SP] = 0x80000000;
+
+ StackFrameSymbolizer frame_symbolizer(NULL, NULL);
+ StackwalkerMIPS walker(&system_info, &raw_context, &stack_region, &modules,
+ &frame_symbolizer);
+ // This should succeed, even without a resolver or supplier.
+ vector<const CodeModule*> modules_without_symbols;
+ vector<const CodeModule*> modules_with_corrupt_symbols;
+ ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
+ &modules_with_corrupt_symbols));
+ ASSERT_EQ(1U, modules_without_symbols.size());
+ ASSERT_EQ("module1", modules_without_symbols[0]->debug_file());
+ ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
+ frames = call_stack.frames();
+ ASSERT_EQ(1U, frames->size());
+ StackFrameMIPS* frame = static_cast<StackFrameMIPS*>(frames->at(0));
+ // Check that the values from the original raw context made it
+ // through to the context in the stack frame.
+ EXPECT_EQ(0, memcmp(&raw_context, &frame->context, sizeof(raw_context)));
+}
+
+class GetContextFrame: public StackwalkerMIPSFixture, public Test { };
+
+TEST_F(GetContextFrame, Simple) {
+ raw_context.context_flags = raw_context.context_flags | MD_CONTEXT_MIPS_FULL;
+ stack_section.start() = 0x80000000;
+ stack_section.D32(0).D32(0x0);
+ RegionFromSection();
+ raw_context.epc = 0x00400020;
+ raw_context.iregs[MD_CONTEXT_MIPS_REG_SP] = 0x80000000;
+
+ StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
+ StackwalkerMIPS walker(&system_info, &raw_context, &stack_region, &modules,
+ &frame_symbolizer);
+ vector<const CodeModule*> modules_without_symbols;
+ vector<const CodeModule*> modules_with_corrupt_symbols;
+ ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
+ &modules_with_corrupt_symbols));
+ ASSERT_EQ(1U, modules_without_symbols.size());
+ ASSERT_EQ("module1", modules_without_symbols[0]->debug_file());
+ ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
+ frames = call_stack.frames();
+ StackFrameMIPS* frame = static_cast<StackFrameMIPS*>(frames->at(0));
+ // Check that the values from the original raw context made it
+ // through to the context in the stack frame.
+ EXPECT_EQ(0, memcmp(&raw_context, &frame->context, sizeof(raw_context)));
+}
+
+// The stackwalker should be able to produce the context frame even
+// without stack memory present.
+TEST_F(GetContextFrame, NoStackMemory) {
+ raw_context.context_flags = raw_context.context_flags | MD_CONTEXT_MIPS_FULL;
+ raw_context.epc = 0x00400020;
+ raw_context.iregs[MD_CONTEXT_MIPS_REG_SP] = 0x80000000;
+
+ StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
+ StackwalkerMIPS walker(&system_info, &raw_context, NULL, &modules,
+ &frame_symbolizer);
+ vector<const CodeModule*> modules_without_symbols;
+ vector<const CodeModule*> modules_with_corrupt_symbols;
+ ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
+ &modules_with_corrupt_symbols));
+ ASSERT_EQ(1U, modules_without_symbols.size());
+ ASSERT_EQ("module1", modules_without_symbols[0]->debug_file());
+ ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
+ frames = call_stack.frames();
+ StackFrameMIPS* frame = static_cast<StackFrameMIPS*>(frames->at(0));
+ // Check that the values from the original raw context made it
+ // through to the context in the stack frame.
+ EXPECT_EQ(0, memcmp(&raw_context, &frame->context, sizeof(raw_context)));
+}
+
+class GetCallerFrame: public StackwalkerMIPSFixture, public Test { };
+
+TEST_F(GetCallerFrame, ScanWithoutSymbols) {
+ raw_context.context_flags = raw_context.context_flags | MD_CONTEXT_MIPS_FULL;
+ // When the stack walker resorts to scanning the stack,
+ // only addresses located within loaded modules are
+ // considered valid return addresses.
+ // Force scanning through three frames to ensure that the
+ // stack pointer is set properly in scan-recovered frames.
+ stack_section.start() = 0x80000000;
+ uint32_t return_address1 = 0x00400100;
+ uint32_t return_address2 = 0x00400900;
+ Label frame1_sp, frame2_sp;
+ stack_section
+ // frame 0
+ .Append(16, 0) // space
+
+ .D32(0x00490000) // junk that's not
+ .D32(0x00600000) // a return address
+
+ .D32(frame1_sp) // stack pointer
+ .D32(return_address1) // actual return address
+ // frame 1
+ .Mark(&frame1_sp)
+ .Append(16, 0) // space
+
+ .D32(0xF0000000) // more junk
+ .D32(0x0000000D)
+
+ .D32(frame2_sp) // stack pointer
+ .D32(return_address2) // actual return address
+ // frame 2
+ .Mark(&frame2_sp)
+ .Append(32, 0); // end of stack
+ RegionFromSection();
+
+ raw_context.epc = 0x00405510;
+ raw_context.iregs[MD_CONTEXT_MIPS_REG_SP] = stack_section.start().Value();
+ raw_context.iregs[MD_CONTEXT_MIPS_REG_RA] = return_address1;
+
+ StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
+ StackwalkerMIPS walker(&system_info, &raw_context, &stack_region, &modules,
+ &frame_symbolizer);
+ vector<const CodeModule*> modules_without_symbols;
+ vector<const CodeModule*> modules_with_corrupt_symbols;
+ ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
+ &modules_with_corrupt_symbols));
+ ASSERT_EQ(1U, modules_without_symbols.size());
+ ASSERT_EQ("module1", modules_without_symbols[0]->debug_file());
+ ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
+ frames = call_stack.frames();
+ ASSERT_EQ(3U, frames->size());
+
+ StackFrameMIPS* frame0 = static_cast<StackFrameMIPS*>(frames->at(0));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
+ ASSERT_EQ(StackFrameMIPS::CONTEXT_VALID_ALL, frame0->context_validity);
+ EXPECT_EQ(0, memcmp(&raw_context, &frame0->context, sizeof(raw_context)));
+
+ StackFrameMIPS* frame1 = static_cast<StackFrameMIPS*>(frames->at(1));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust);
+ ASSERT_EQ((StackFrameMIPS::CONTEXT_VALID_PC |
+ StackFrameMIPS::CONTEXT_VALID_SP |
+ StackFrameMIPS::CONTEXT_VALID_FP |
+ StackFrameMIPS::CONTEXT_VALID_RA),
+ frame1->context_validity);
+ EXPECT_EQ(return_address1 - 2 * sizeof(return_address1), frame1->context.epc);
+ EXPECT_EQ(frame1_sp.Value(), frame1->context.iregs[MD_CONTEXT_MIPS_REG_SP]);
+
+ StackFrameMIPS* frame2 = static_cast<StackFrameMIPS*>(frames->at(2));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame2->trust);
+ ASSERT_EQ((StackFrameMIPS::CONTEXT_VALID_PC |
+ StackFrameMIPS::CONTEXT_VALID_SP |
+ StackFrameMIPS::CONTEXT_VALID_FP |
+ StackFrameMIPS::CONTEXT_VALID_RA),
+ frame2->context_validity);
+ EXPECT_EQ(return_address2 - 2 * sizeof(return_address2), frame2->context.epc);
+ EXPECT_EQ(frame2_sp.Value(), frame2->context.iregs[MD_CONTEXT_MIPS_REG_SP]);
+}
+
+TEST_F(GetCallerFrame, ScanWithFunctionSymbols) {
+ raw_context.context_flags = raw_context.context_flags | MD_CONTEXT_MIPS_FULL;
+ // During stack scanning, if a potential return address
+ // is located within a loaded module that has symbols,
+ // it is only considered a valid return address if it
+ // lies within a function's bounds.
+ stack_section.start() = 0x80000000;
+ uint32_t return_address = 0x00500200;
+ Label frame1_sp;
+ stack_section
+ // frame 0
+ .Append(16, 0) // space
+
+ .D32(0x00490000) // junk that's not
+ .D32(0x00600000) // a return address
+
+ .D32(0x00401000) // a couple of plausible addresses
+ .D32(0x0050F000) // that are not within functions
+
+ .D32(frame1_sp) // stack pointer
+ .D32(return_address) // actual return address
+ // frame 1
+ .Mark(&frame1_sp)
+ .Append(32, 0); // end of stack
+ RegionFromSection();
+
+ raw_context.epc = 0x00400200;
+ raw_context.iregs[MD_CONTEXT_MIPS_REG_SP] = stack_section.start().Value();
+ raw_context.iregs[MD_CONTEXT_MIPS_REG_RA] = return_address;
+
+ SetModuleSymbols(&module1,
+ // The youngest frame's function.
+ "FUNC 100 400 10 monotreme\n");
+ SetModuleSymbols(&module2,
+ // The calling frame's function.
+ "FUNC 100 400 10 marsupial\n");
+
+ StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
+ StackwalkerMIPS walker(&system_info, &raw_context, &stack_region, &modules,
+ &frame_symbolizer);
+ vector<const CodeModule*> modules_without_symbols;
+ vector<const CodeModule*> modules_with_corrupt_symbols;
+ ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
+ &modules_with_corrupt_symbols));
+ ASSERT_EQ(0U, modules_without_symbols.size());
+ ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
+ frames = call_stack.frames();
+ ASSERT_EQ(2U, frames->size());
+
+ StackFrameMIPS* frame0 = static_cast<StackFrameMIPS*>(frames->at(0));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
+ ASSERT_EQ(StackFrameMIPS::CONTEXT_VALID_ALL, frame0->context_validity);
+ EXPECT_EQ(0, memcmp(&raw_context, &frame0->context, sizeof(raw_context)));
+ EXPECT_EQ("monotreme", frame0->function_name);
+ EXPECT_EQ(0x00400100U, frame0->function_base);
+
+ StackFrameMIPS* frame1 = static_cast<StackFrameMIPS*>(frames->at(1));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust);
+ ASSERT_EQ((StackFrameMIPS::CONTEXT_VALID_PC |
+ StackFrameMIPS::CONTEXT_VALID_SP |
+ StackFrameMIPS::CONTEXT_VALID_FP |
+ StackFrameMIPS::CONTEXT_VALID_RA),
+ frame1->context_validity);
+ EXPECT_EQ(return_address - 2 * sizeof(return_address), frame1->context.epc);
+ EXPECT_EQ(frame1_sp.Value(), frame1->context.iregs[MD_CONTEXT_MIPS_REG_SP]);
+ EXPECT_EQ("marsupial", frame1->function_name);
+ EXPECT_EQ(0x00500100U, frame1->function_base);
+}
+
+TEST_F(GetCallerFrame, CheckStackFrameSizeLimit) {
+ raw_context.context_flags = raw_context.context_flags | MD_CONTEXT_MIPS_FULL;
+ // If the stackwalker resorts to stack scanning, it will scan only
+ // 1024 bytes of stack which correspondes to maximum size of stack frame.
+ stack_section.start() = 0x80000000;
+ uint32_t return_address1 = 0x00500100;
+ uint32_t return_address2 = 0x00500900;
+ Label frame1_sp, frame2_sp;
+ stack_section
+ // frame 0
+ .Append(32, 0) // space
+
+ .D32(0x00490000) // junk that's not
+ .D32(0x00600000) // a return address
+
+ .Append(96, 0) // more space
+
+ .D32(frame1_sp) // stack pointer
+ .D32(return_address1) // actual return address
+ // frame 1
+ .Mark(&frame1_sp)
+ .Append(128 * 4, 0) // space
+
+ .D32(0x00F00000) // more junk
+ .D32(0x0000000D)
+
+ .Append(128 * 4, 0) // more space
+
+ .D32(frame2_sp) // stack pointer
+ .D32(return_address2) // actual return address
+ // (won't be found)
+ // frame 2
+ .Mark(&frame2_sp)
+ .Append(32, 0); // end of stack
+ RegionFromSection();
+
+ raw_context.epc = 0x00405510;
+ raw_context.iregs[MD_CONTEXT_MIPS_REG_SP] = stack_section.start().Value();
+ raw_context.iregs[MD_CONTEXT_MIPS_REG_RA] = return_address1;
+
+ StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
+ StackwalkerMIPS walker(&system_info, &raw_context, &stack_region, &modules,
+ &frame_symbolizer);
+ vector<const CodeModule*> modules_without_symbols;
+ vector<const CodeModule*> modules_with_corrupt_symbols;
+ ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
+ &modules_with_corrupt_symbols));
+ ASSERT_EQ(2U, modules_without_symbols.size());
+ ASSERT_EQ("module1", modules_without_symbols[0]->debug_file());
+ ASSERT_EQ("module2", modules_without_symbols[1]->debug_file());
+ ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
+ frames = call_stack.frames();
+ ASSERT_EQ(2U, frames->size());
+
+ StackFrameMIPS* frame0 = static_cast<StackFrameMIPS*>(frames->at(0));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
+ ASSERT_EQ(StackFrameMIPS::CONTEXT_VALID_ALL, frame0->context_validity);
+ EXPECT_EQ(0, memcmp(&raw_context, &frame0->context, sizeof(raw_context)));
+
+ StackFrameMIPS* frame1 = static_cast<StackFrameMIPS*>(frames->at(1));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust);
+ ASSERT_EQ((StackFrameMIPS::CONTEXT_VALID_PC |
+ StackFrameMIPS::CONTEXT_VALID_SP |
+ StackFrameMIPS::CONTEXT_VALID_FP |
+ StackFrameMIPS::CONTEXT_VALID_RA),
+ frame1->context_validity);
+ EXPECT_EQ(return_address1 - 2 * sizeof(return_address1), frame1->context.epc);
+ EXPECT_EQ(frame1_sp.Value(), frame1->context.iregs[MD_CONTEXT_MIPS_REG_SP]);
+}
+
+// Test that set_max_frames_scanned prevents using stack scanning
+// to find caller frames.
+TEST_F(GetCallerFrame, ScanningNotAllowed) {
+ raw_context.context_flags = raw_context.context_flags | MD_CONTEXT_MIPS_FULL;
+ // When the stack walker resorts to scanning the stack,
+ // only fixed number of frames are allowed to be scanned out from stack
+ stack_section.start() = 0x80000000;
+ uint32_t return_address1 = 0x00500100;
+ uint32_t return_address2 = 0x00500900;
+ Label frame1_sp, frame2_sp;
+ stack_section
+ // frame 0
+ .Append(32, 0) // space
+
+ .D32(0x00490000) // junk that's not
+ .D32(0x00600000) // a return address
+
+ .Append(96, 0) // more space
+
+ .D32(frame1_sp) // stack pointer
+ .D32(return_address1) // actual return address
+ // frame 1
+ .Mark(&frame1_sp)
+ .Append(128 * 4, 0) // space
+
+ .D32(0x00F00000) // more junk
+ .D32(0x0000000D)
+
+ .Append(128 * 4, 0) // more space
+
+ .D32(frame2_sp) // stack pointer
+ .D32(return_address2) // actual return address
+ // (won't be found)
+ // frame 2
+ .Mark(&frame2_sp)
+ .Append(32, 0); // end of stack
+ RegionFromSection();
+
+ raw_context.epc = 0x00405510;
+ raw_context.iregs[MD_CONTEXT_MIPS_REG_SP] = stack_section.start().Value();
+ raw_context.iregs[MD_CONTEXT_MIPS_REG_RA] = return_address1;
+
+ StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
+ StackwalkerMIPS walker(&system_info, &raw_context, &stack_region, &modules,
+ &frame_symbolizer);
+ Stackwalker::set_max_frames_scanned(0);
+
+ vector<const CodeModule*> modules_without_symbols;
+ vector<const CodeModule*> modules_with_corrupt_symbols;
+ ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
+ &modules_with_corrupt_symbols));
+ ASSERT_EQ(1U, modules_without_symbols.size());
+ ASSERT_EQ("module1", modules_without_symbols[0]->debug_file());
+ ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
+ frames = call_stack.frames();
+ ASSERT_EQ(1U, frames->size());
+
+ StackFrameMIPS* frame0 = static_cast<StackFrameMIPS*>(frames->at(0));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
+ ASSERT_EQ(StackFrameMIPS::CONTEXT_VALID_ALL, frame0->context_validity);
+ EXPECT_EQ(0, memcmp(&raw_context, &frame0->context, sizeof(raw_context)));
+}
+
+struct CFIFixture: public StackwalkerMIPSFixture {
+ CFIFixture() {
+ // Provide some STACK CFI records;
+ SetModuleSymbols(&module1,
+ // The youngest frame's function.
+ "FUNC 4000 1000 0 enchiridion\n"
+ // Initially, nothing has been pushed on the stack,
+ // and the return address is still in the $ra register.
+ "STACK CFI INIT 4000 1000 .cfa: $sp 0 + .ra: $ra\n"
+ // Move stack pointer.
+ "STACK CFI 4004 .cfa: $sp 32 +\n"
+ // store $fp and ra
+ "STACK CFI 4008 $fp: .cfa -8 + ^ .ra: .cfa -4 + ^\n"
+ // restore $fp
+ "STACK CFI 400c .cfa: $fp 32 +\n"
+ // restore $sp
+ "STACK CFI 4018 .cfa: $sp 32 +\n"
+
+ "STACK CFI 4020 $fp: $fp .cfa: $sp 0 + .ra: .ra\n"
+
+ // The calling function.
+ "FUNC 5000 1000 0 epictetus\n"
+ // Mark it as end of stack.
+ "STACK CFI INIT 5000 8 .cfa: $sp 0 + .ra: $ra\n"
+
+ // A function whose CFI makes the stack pointer
+ // go backwards.
+ "FUNC 6000 1000 20 palinal\n"
+ "STACK CFI INIT 6000 1000 .cfa: $sp 4 - .ra: $ra\n"
+
+ // A function with CFI expressions that can't be
+ // evaluated.
+ "FUNC 7000 1000 20 rhetorical\n"
+ "STACK CFI INIT 7000 1000 .cfa: moot .ra: ambiguous\n"
+ );
+
+ // Provide some distinctive values for the caller's registers.
+ expected.epc = 0x00405508;
+ expected.iregs[MD_CONTEXT_MIPS_REG_S0] = 0x0;
+ expected.iregs[MD_CONTEXT_MIPS_REG_S1] = 0x1;
+ expected.iregs[MD_CONTEXT_MIPS_REG_S2] = 0x2;
+ expected.iregs[MD_CONTEXT_MIPS_REG_S3] = 0x3;
+ expected.iregs[MD_CONTEXT_MIPS_REG_S4] = 0x4;
+ expected.iregs[MD_CONTEXT_MIPS_REG_S5] = 0x5;
+ expected.iregs[MD_CONTEXT_MIPS_REG_S6] = 0x6;
+ expected.iregs[MD_CONTEXT_MIPS_REG_S7] = 0x7;
+ expected.iregs[MD_CONTEXT_MIPS_REG_SP] = 0x80000000;
+ expected.iregs[MD_CONTEXT_MIPS_REG_FP] = 0x80000000;
+ expected.iregs[MD_CONTEXT_MIPS_REG_RA] = 0x00405510;
+
+ // Expect CFI to recover all callee-save registers. Since CFI is the
+ // only stack frame construction technique we have, aside from the
+ // context frame itself, there's no way for us to have a set of valid
+ // registers smaller than this.
+ expected_validity = (StackFrameMIPS::CONTEXT_VALID_PC |
+ StackFrameMIPS::CONTEXT_VALID_S0 |
+ StackFrameMIPS::CONTEXT_VALID_S1 |
+ StackFrameMIPS::CONTEXT_VALID_S2 |
+ StackFrameMIPS::CONTEXT_VALID_S3 |
+ StackFrameMIPS::CONTEXT_VALID_S4 |
+ StackFrameMIPS::CONTEXT_VALID_S5 |
+ StackFrameMIPS::CONTEXT_VALID_S6 |
+ StackFrameMIPS::CONTEXT_VALID_S7 |
+ StackFrameMIPS::CONTEXT_VALID_SP |
+ StackFrameMIPS::CONTEXT_VALID_FP |
+ StackFrameMIPS::CONTEXT_VALID_RA);
+
+ // By default, context frames provide all registers, as normal.
+ context_frame_validity = StackFrameMIPS::CONTEXT_VALID_ALL;
+
+ // By default, registers are unchanged.
+ raw_context = expected;
+ }
+
+ // Walk the stack, using stack_section as the contents of the stack
+ // and raw_context as the current register values. (Set the stack
+ // pointer to the stack's starting address.) Expect two stack
+ // frames; in the older frame, expect the callee-saves registers to
+ // have values matching those in 'expected'.
+ void CheckWalk() {
+ RegionFromSection();
+ raw_context.iregs[MD_CONTEXT_MIPS_REG_SP] = stack_section.start().Value();
+
+ StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
+ StackwalkerMIPS walker(&system_info, &raw_context, &stack_region,
+ &modules, &frame_symbolizer);
+ vector<const CodeModule*> modules_without_symbols;
+ vector<const CodeModule*> modules_with_corrupt_symbols;
+ ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
+ &modules_with_corrupt_symbols));
+ ASSERT_EQ(0U, modules_without_symbols.size());
+ ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
+ frames = call_stack.frames();
+ ASSERT_EQ(2U, frames->size());
+
+ StackFrameMIPS* frame0 = static_cast<StackFrameMIPS*>(frames->at(0));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
+ ASSERT_EQ(StackFrameMIPS::CONTEXT_VALID_ALL, frame0->context_validity);
+ EXPECT_EQ("enchiridion", frame0->function_name);
+ EXPECT_EQ(0x00404000U, frame0->function_base);
+
+ StackFrameMIPS* frame1 = static_cast<StackFrameMIPS*>(frames->at(1));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame1->trust);
+ ASSERT_EQ(expected_validity, frame1->context_validity);
+ EXPECT_EQ(expected.iregs[MD_CONTEXT_MIPS_REG_S0],
+ frame1->context.iregs[MD_CONTEXT_MIPS_REG_S0]);
+ EXPECT_EQ(expected.iregs[MD_CONTEXT_MIPS_REG_S1],
+ frame1->context.iregs[MD_CONTEXT_MIPS_REG_S1]);
+ EXPECT_EQ(expected.iregs[MD_CONTEXT_MIPS_REG_S2],
+ frame1->context.iregs[MD_CONTEXT_MIPS_REG_S2]);
+ EXPECT_EQ(expected.iregs[MD_CONTEXT_MIPS_REG_S3],
+ frame1->context.iregs[MD_CONTEXT_MIPS_REG_S3]);
+ EXPECT_EQ(expected.iregs[MD_CONTEXT_MIPS_REG_S4],
+ frame1->context.iregs[MD_CONTEXT_MIPS_REG_S4]);
+ EXPECT_EQ(expected.iregs[MD_CONTEXT_MIPS_REG_S5],
+ frame1->context.iregs[MD_CONTEXT_MIPS_REG_S5]);
+ EXPECT_EQ(expected.iregs[MD_CONTEXT_MIPS_REG_S6],
+ frame1->context.iregs[MD_CONTEXT_MIPS_REG_S6]);
+ EXPECT_EQ(expected.iregs[MD_CONTEXT_MIPS_REG_S7],
+ frame1->context.iregs[MD_CONTEXT_MIPS_REG_S7]);
+ EXPECT_EQ(expected.iregs[MD_CONTEXT_MIPS_REG_FP],
+ frame1->context.iregs[MD_CONTEXT_MIPS_REG_FP]);
+ EXPECT_EQ(expected.iregs[MD_CONTEXT_MIPS_REG_RA],
+ frame1->context.iregs[MD_CONTEXT_MIPS_REG_RA]);
+ EXPECT_EQ(expected.iregs[MD_CONTEXT_MIPS_REG_SP],
+ frame1->context.iregs[MD_CONTEXT_MIPS_REG_SP]);
+ EXPECT_EQ(expected.epc, frame1->context.epc);
+ EXPECT_EQ(expected.epc, frame1->instruction);
+ EXPECT_EQ("epictetus", frame1->function_name);
+ EXPECT_EQ(0x00405000U, frame1->function_base);
+ }
+
+ // The values we expect to find for the caller's registers.
+ MDRawContextMIPS expected;
+
+ // The validity mask for expected.
+ int expected_validity;
+
+ // The validity mask to impose on the context frame.
+ int context_frame_validity;
+};
+
+class CFI: public CFIFixture, public Test { };
+
+// TODO(gordanac): add CFI tests
+
+TEST_F(CFI, At4004) {
+ raw_context.context_flags = raw_context.context_flags | MD_CONTEXT_MIPS_FULL;
+ Label frame1_sp = expected.iregs[MD_CONTEXT_MIPS_REG_SP];
+ stack_section
+ // frame0
+ .Append(24, 0) // space
+ .D32(frame1_sp) // stack pointer
+ .D32(0x00405510) // return address
+ .Mark(&frame1_sp); // This effectively sets stack_section.start().
+ raw_context.epc = 0x00404004;
+ CheckWalk();
+}
+
+// Check that we reject rules that would cause the stack pointer to
+// move in the wrong direction.
+TEST_F(CFI, RejectBackwards) {
+ raw_context.context_flags = raw_context.context_flags | MD_CONTEXT_MIPS_FULL;
+ raw_context.epc = 0x40005000;
+ raw_context.iregs[MD_CONTEXT_MIPS_REG_SP] = 0x80000000;
+ raw_context.iregs[MD_CONTEXT_MIPS_REG_RA] = 0x00405510;
+
+ StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
+ StackwalkerMIPS walker(&system_info, &raw_context, &stack_region, &modules,
+ &frame_symbolizer);
+ vector<const CodeModule*> modules_without_symbols;
+ vector<const CodeModule*> modules_with_corrupt_symbols;
+ ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
+ &modules_with_corrupt_symbols));
+ ASSERT_EQ(0U, modules_without_symbols.size());
+ ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
+ frames = call_stack.frames();
+ ASSERT_EQ(1U, frames->size());
+}
+
+// Check that we reject rules whose expressions' evaluation fails.
+TEST_F(CFI, RejectBadExpressions) {
+ raw_context.context_flags = raw_context.context_flags | MD_CONTEXT_MIPS_FULL;
+ raw_context.epc = 0x00407000;
+ raw_context.iregs[MD_CONTEXT_MIPS_REG_SP] = 0x80000000;
+ raw_context.iregs[MD_CONTEXT_MIPS_REG_RA] = 0x00405510;
+
+ StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
+ StackwalkerMIPS walker(&system_info, &raw_context, &stack_region, &modules,
+ &frame_symbolizer);
+ vector<const CodeModule*> modules_without_symbols;
+ vector<const CodeModule*> modules_with_corrupt_symbols;
+ ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
+ &modules_with_corrupt_symbols));
+ ASSERT_EQ(0U, modules_without_symbols.size());
+ ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
+ frames = call_stack.frames();
+ ASSERT_EQ(1U, frames->size());
+}
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_ppc.cc b/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_ppc.cc
new file mode 100644
index 0000000000..1e34c38336
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_ppc.cc
@@ -0,0 +1,155 @@
+// 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.
+
+// stackwalker_ppc.cc: ppc-specific stackwalker.
+//
+// See stackwalker_ppc.h for documentation.
+//
+// Author: Mark Mentovai
+
+
+#include "common/scoped_ptr.h"
+#include "processor/stackwalker_ppc.h"
+#include "google_breakpad/processor/call_stack.h"
+#include "google_breakpad/processor/memory_region.h"
+#include "google_breakpad/processor/stack_frame_cpu.h"
+#include "processor/logging.h"
+
+namespace google_breakpad {
+
+
+StackwalkerPPC::StackwalkerPPC(const SystemInfo* system_info,
+ const MDRawContextPPC* context,
+ MemoryRegion* memory,
+ const CodeModules* modules,
+ StackFrameSymbolizer* resolver_helper)
+ : Stackwalker(system_info, memory, modules, resolver_helper),
+ context_(context) {
+ if (memory_ && memory_->GetBase() + memory_->GetSize() - 1 > 0xffffffff) {
+ // This implementation only covers 32-bit ppc CPUs. The limits of the
+ // supplied stack are invalid. Mark memory_ = NULL, which will cause
+ // stackwalking to fail.
+ BPLOG(ERROR) << "Memory out of range for stackwalking: " <<
+ HexString(memory_->GetBase()) << "+" <<
+ HexString(memory_->GetSize());
+ memory_ = NULL;
+ }
+}
+
+
+StackFrame* StackwalkerPPC::GetContextFrame() {
+ if (!context_) {
+ BPLOG(ERROR) << "Can't get context frame without context";
+ return NULL;
+ }
+
+ StackFramePPC* frame = new StackFramePPC();
+
+ // The instruction pointer is stored directly in a register, so pull it
+ // straight out of the CPU context structure.
+ frame->context = *context_;
+ frame->context_validity = StackFramePPC::CONTEXT_VALID_ALL;
+ frame->trust = StackFrame::FRAME_TRUST_CONTEXT;
+ frame->instruction = frame->context.srr0;
+
+ return frame;
+}
+
+
+StackFrame* StackwalkerPPC::GetCallerFrame(const CallStack* stack,
+ bool stack_scan_allowed) {
+ if (!memory_ || !stack) {
+ BPLOG(ERROR) << "Can't get caller frame without memory or stack";
+ return NULL;
+ }
+
+ // The instruction pointers for previous frames are saved on the stack.
+ // The typical ppc calling convention is for the called procedure to store
+ // its return address in the calling procedure's stack frame at 8(%r1),
+ // and to allocate its own stack frame by decrementing %r1 (the stack
+ // pointer) and saving the old value of %r1 at 0(%r1). Because the ppc has
+ // no hardware stack, there is no distinction between the stack pointer and
+ // frame pointer, and what is typically thought of as the frame pointer on
+ // an x86 is usually referred to as the stack pointer on a ppc.
+
+ StackFramePPC* last_frame = static_cast<StackFramePPC*>(
+ stack->frames()->back());
+
+ // A caller frame must reside higher in memory than its callee frames.
+ // Anything else is an error, or an indication that we've reached the
+ // end of the stack.
+ uint32_t stack_pointer;
+ if (!memory_->GetMemoryAtAddress(last_frame->context.gpr[1],
+ &stack_pointer) ||
+ stack_pointer <= last_frame->context.gpr[1]) {
+ return NULL;
+ }
+
+ // Mac OS X/Darwin gives 1 as the return address from the bottom-most
+ // frame in a stack (a thread's entry point). I haven't found any
+ // documentation on this, but 0 or 1 would be bogus return addresses,
+ // so check for them here and return false (end of stack) when they're
+ // hit to avoid having a phantom frame.
+ uint32_t instruction;
+ if (!memory_->GetMemoryAtAddress(stack_pointer + 8, &instruction) ||
+ instruction <= 1) {
+ return NULL;
+ }
+
+ scoped_ptr<StackFramePPC> frame(new StackFramePPC());
+
+ frame->context = last_frame->context;
+ frame->context.srr0 = instruction;
+ frame->context.gpr[1] = stack_pointer;
+ frame->context_validity = StackFramePPC::CONTEXT_VALID_SRR0 |
+ StackFramePPC::CONTEXT_VALID_GPR1;
+ frame->trust = StackFrame::FRAME_TRUST_FP;
+
+ // Should we terminate the stack walk? (end-of-stack or broken invariant)
+ if (TerminateWalk(instruction,
+ stack_pointer,
+ last_frame->context.gpr[1],
+ stack->frames()->size() == 1)) {
+ return NULL;
+ }
+
+ // frame->context.srr0 is the return address, which is one instruction
+ // past the branch that caused us to arrive at the callee. Set
+ // frame_ppc->instruction to four less than that. Since all ppc
+ // instructions are 4 bytes wide, this is the address of the branch
+ // instruction. This allows source line information to match up with the
+ // line that contains a function call. Callers that require the exact
+ // return address value may access the context.srr0 field of StackFramePPC.
+ frame->instruction = frame->context.srr0 - 4;
+
+ return frame.release();
+}
+
+
+} // namespace google_breakpad
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_ppc.h b/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_ppc.h
new file mode 100644
index 0000000000..012e5c32f9
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_ppc.h
@@ -0,0 +1,79 @@
+// 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.
+
+// stackwalker_ppc.h: ppc-specific stackwalker.
+//
+// Provides stack frames given ppc register context and a memory region
+// corresponding to a ppc stack.
+//
+// Author: Mark Mentovai
+
+
+#ifndef PROCESSOR_STACKWALKER_PPC_H__
+#define PROCESSOR_STACKWALKER_PPC_H__
+
+
+#include "google_breakpad/common/breakpad_types.h"
+#include "google_breakpad/common/minidump_format.h"
+#include "google_breakpad/processor/stackwalker.h"
+
+namespace google_breakpad {
+
+class CodeModules;
+
+class StackwalkerPPC : public Stackwalker {
+ public:
+ // context is a ppc context object that gives access to ppc-specific
+ // register state corresponding to the innermost called frame to be
+ // included in the stack. The other arguments are passed directly through
+ // to the base Stackwalker constructor.
+ StackwalkerPPC(const SystemInfo* system_info,
+ const MDRawContextPPC* context,
+ MemoryRegion* memory,
+ const CodeModules* modules,
+ StackFrameSymbolizer* frame_symbolizer);
+
+ private:
+ // Implementation of Stackwalker, using ppc context (stack pointer in %r1,
+ // saved program counter in %srr0) and stack conventions (saved stack
+ // pointer at 0(%r1), return address at 8(0(%r1)).
+ virtual StackFrame* GetContextFrame();
+ virtual StackFrame* GetCallerFrame(const CallStack* stack,
+ bool stack_scan_allowed);
+
+ // Stores the CPU context corresponding to the innermost stack frame to
+ // be returned by GetContextFrame.
+ const MDRawContextPPC* context_;
+};
+
+
+} // namespace google_breakpad
+
+
+#endif // PROCESSOR_STACKWALKER_PPC_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_ppc64.cc b/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_ppc64.cc
new file mode 100644
index 0000000000..fb2bac3c41
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_ppc64.cc
@@ -0,0 +1,146 @@
+// 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.
+
+// stackwalker_ppc64.cc: ppc64-specific stackwalker.
+//
+// See stackwalker_ppc64.h for documentation.
+
+
+#include "common/scoped_ptr.h"
+#include "processor/stackwalker_ppc64.h"
+#include "google_breakpad/processor/call_stack.h"
+#include "google_breakpad/processor/memory_region.h"
+#include "google_breakpad/processor/stack_frame_cpu.h"
+#include "processor/logging.h"
+
+#include <stdio.h>
+
+namespace google_breakpad {
+
+
+StackwalkerPPC64::StackwalkerPPC64(const SystemInfo* system_info,
+ const MDRawContextPPC64* context,
+ MemoryRegion* memory,
+ const CodeModules* modules,
+ StackFrameSymbolizer* resolver_helper)
+ : Stackwalker(system_info, memory, modules, resolver_helper),
+ context_(context) {
+}
+
+
+StackFrame* StackwalkerPPC64::GetContextFrame() {
+ if (!context_) {
+ BPLOG(ERROR) << "Can't get context frame without context";
+ return NULL;
+ }
+
+ StackFramePPC64* frame = new StackFramePPC64();
+
+ // The instruction pointer is stored directly in a register, so pull it
+ // straight out of the CPU context structure.
+ frame->context = *context_;
+ frame->context_validity = StackFramePPC64::CONTEXT_VALID_ALL;
+ frame->trust = StackFrame::FRAME_TRUST_CONTEXT;
+ frame->instruction = frame->context.srr0;
+
+ return frame;
+}
+
+
+StackFrame* StackwalkerPPC64::GetCallerFrame(const CallStack* stack,
+ bool stack_scan_allowed) {
+ if (!memory_ || !stack) {
+ BPLOG(ERROR) << "Can't get caller frame without memory or stack";
+ return NULL;
+ }
+
+ // The instruction pointers for previous frames are saved on the stack.
+ // The typical ppc64 calling convention is for the called procedure to store
+ // its return address in the calling procedure's stack frame at 8(%r1),
+ // and to allocate its own stack frame by decrementing %r1 (the stack
+ // pointer) and saving the old value of %r1 at 0(%r1). Because the ppc64 has
+ // no hardware stack, there is no distinction between the stack pointer and
+ // frame pointer, and what is typically thought of as the frame pointer on
+ // an x86 is usually referred to as the stack pointer on a ppc64.
+
+ StackFramePPC64* last_frame = static_cast<StackFramePPC64*>(
+ stack->frames()->back());
+
+ // A caller frame must reside higher in memory than its callee frames.
+ // Anything else is an error, or an indication that we've reached the
+ // end of the stack.
+ uint64_t stack_pointer;
+ if (!memory_->GetMemoryAtAddress(last_frame->context.gpr[1],
+ &stack_pointer) ||
+ stack_pointer <= last_frame->context.gpr[1]) {
+ return NULL;
+ }
+
+ // Mac OS X/Darwin gives 1 as the return address from the bottom-most
+ // frame in a stack (a thread's entry point). I haven't found any
+ // documentation on this, but 0 or 1 would be bogus return addresses,
+ // so check for them here and return false (end of stack) when they're
+ // hit to avoid having a phantom frame.
+ uint64_t instruction;
+ if (!memory_->GetMemoryAtAddress(stack_pointer + 16, &instruction) ||
+ instruction <= 1) {
+ return NULL;
+ }
+
+ scoped_ptr<StackFramePPC64> frame(new StackFramePPC64());
+
+ frame->context = last_frame->context;
+ frame->context.srr0 = instruction;
+ frame->context.gpr[1] = stack_pointer;
+ frame->context_validity = StackFramePPC64::CONTEXT_VALID_SRR0 |
+ StackFramePPC64::CONTEXT_VALID_GPR1;
+ frame->trust = StackFrame::FRAME_TRUST_FP;
+
+ // Should we terminate the stack walk? (end-of-stack or broken invariant)
+ if (TerminateWalk(instruction,
+ stack_pointer,
+ last_frame->context.gpr[1],
+ stack->frames()->size() == 1)) {
+ return NULL;
+ }
+
+ // frame->context.srr0 is the return address, which is one instruction
+ // past the branch that caused us to arrive at the callee. Set
+ // frame_ppc64->instruction to eight less than that. Since all ppc64
+ // instructions are 8 bytes wide, this is the address of the branch
+ // instruction. This allows source line information to match up with the
+ // line that contains a function call. Callers that require the exact
+ // return address value may access the context.srr0 field of StackFramePPC64.
+ frame->instruction = frame->context.srr0 - 8;
+
+ return frame.release();
+}
+
+
+} // namespace google_breakpad
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_ppc64.h b/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_ppc64.h
new file mode 100644
index 0000000000..a406343af4
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_ppc64.h
@@ -0,0 +1,77 @@
+// 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.
+
+// stackwalker_ppc64.h: ppc-specific stackwalker.
+//
+// Provides stack frames given ppc64 register context and a memory region
+// corresponding to a ppc64 stack.
+
+
+#ifndef PROCESSOR_STACKWALKER_PPC64_H__
+#define PROCESSOR_STACKWALKER_PPC64_H__
+
+
+#include "google_breakpad/common/breakpad_types.h"
+#include "google_breakpad/common/minidump_format.h"
+#include "google_breakpad/processor/stackwalker.h"
+
+namespace google_breakpad {
+
+class CodeModules;
+
+class StackwalkerPPC64 : public Stackwalker {
+ public:
+ // context is a ppc64 context object that gives access to ppc64-specific
+ // register state corresponding to the innermost called frame to be
+ // included in the stack. The other arguments are passed directly through
+ // to the base Stackwalker constructor.
+ StackwalkerPPC64(const SystemInfo* system_info,
+ const MDRawContextPPC64* context,
+ MemoryRegion* memory,
+ const CodeModules* modules,
+ StackFrameSymbolizer* frame_symbolizer);
+
+ private:
+ // Implementation of Stackwalker, using ppc64 context (stack pointer in %r1,
+ // saved program counter in %srr0) and stack conventions (saved stack
+ // pointer at 0(%r1), return address at 8(0(%r1)).
+ virtual StackFrame* GetContextFrame();
+ virtual StackFrame* GetCallerFrame(const CallStack* stack,
+ bool stack_scan_allowed);
+
+ // Stores the CPU context corresponding to the innermost stack frame to
+ // be returned by GetContextFrame.
+ const MDRawContextPPC64* context_;
+};
+
+
+} // namespace google_breakpad
+
+
+#endif // PROCESSOR_STACKWALKER_PPC64_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_selftest.cc b/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_selftest.cc
new file mode 100644
index 0000000000..f692d4c4c0
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_selftest.cc
@@ -0,0 +1,433 @@
+// 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.
+
+// stackwalker_selftest.cc: Tests StackwalkerX86 or StackwalkerPPC using the
+// running process' stack as test data, if running on an x86 or ppc and
+// compiled with gcc. This test is not enabled in the "make check" suite
+// by default, because certain optimizations interfere with its proper
+// operation. To turn it on, configure with --enable-selftest.
+//
+// Optimizations that cause problems:
+// - stack frame reuse. The Recursor function here calls itself with
+// |return Recursor|. When the caller's frame is reused, it will cause
+// CountCallerFrames to correctly return the same number of frames
+// in both the caller and callee. This is considered an unexpected
+// condition in the test, which expects a callee to have one more
+// caller frame in the stack than its caller.
+// - frame pointer omission. Even with a stackwalker that understands
+// this optimization, the code to harness debug information currently
+// only exists to retrieve it from minidumps, not the current process.
+//
+// This test can also serve as a developmental and debugging aid if
+// PRINT_STACKS is defined.
+//
+// Author: Mark Mentovai
+
+#include <assert.h>
+
+#include "processor/logging.h"
+
+#if defined(__i386) && !defined(__i386__)
+#define __i386__
+#endif
+#if defined(__sparc) && !defined(__sparc__)
+#define __sparc__
+#endif
+
+#if (defined(__SUNPRO_CC) || defined(__GNUC__)) && \
+ (defined(__i386__) || defined(__ppc__) || defined(__sparc__))
+
+
+#include <stdio.h>
+
+#include "common/scoped_ptr.h"
+#include "google_breakpad/common/breakpad_types.h"
+#include "google_breakpad/common/minidump_format.h"
+#include "google_breakpad/processor/basic_source_line_resolver.h"
+#include "google_breakpad/processor/call_stack.h"
+#include "google_breakpad/processor/code_module.h"
+#include "google_breakpad/processor/memory_region.h"
+#include "google_breakpad/processor/stack_frame.h"
+#include "google_breakpad/processor/stack_frame_cpu.h"
+
+using google_breakpad::BasicSourceLineResolver;
+using google_breakpad::CallStack;
+using google_breakpad::CodeModule;
+using google_breakpad::MemoryRegion;
+using google_breakpad::scoped_ptr;
+using google_breakpad::StackFrame;
+using google_breakpad::StackFramePPC;
+using google_breakpad::StackFrameX86;
+using google_breakpad::StackFrameSPARC;
+
+#if defined(__i386__)
+#include "processor/stackwalker_x86.h"
+using google_breakpad::StackwalkerX86;
+#elif defined(__ppc__)
+#include "processor/stackwalker_ppc.h"
+using google_breakpad::StackwalkerPPC;
+#elif defined(__sparc__)
+#include "processor/stackwalker_sparc.h"
+using google_breakpad::StackwalkerSPARC;
+#endif // __i386__ || __ppc__ || __sparc__
+
+#define RECURSION_DEPTH 100
+
+
+// A simple MemoryRegion subclass that provides direct access to this
+// process' memory space by pointer.
+class SelfMemoryRegion : public MemoryRegion {
+ public:
+ virtual uint64_t GetBase() const { return 0; }
+ virtual uint32_t GetSize() const { return 0xffffffff; }
+
+ bool GetMemoryAtAddress(uint64_t address, uint8_t* value) const {
+ return GetMemoryAtAddressInternal(address, value); }
+ bool GetMemoryAtAddress(uint64_t address, uint16_t* value) const {
+ return GetMemoryAtAddressInternal(address, value); }
+ bool GetMemoryAtAddress(uint64_t address, uint32_t* value) const {
+ return GetMemoryAtAddressInternal(address, value); }
+ bool GetMemoryAtAddress(uint64_t address, uint64_t* value) const {
+ return GetMemoryAtAddressInternal(address, value); }
+ void Print() const {
+ assert(false);
+ }
+
+ private:
+ template<typename T> bool GetMemoryAtAddressInternal(uint64_t address,
+ T* value) {
+ // Without knowing what addresses are actually mapped, just assume that
+ // everything low is not mapped. This helps the stackwalker catch the
+ // end of a stack when it tries to dereference a null or low pointer
+ // in an attempt to find the caller frame. Other unmapped accesses will
+ // cause the program to crash, but that would properly be a test failure.
+ if (address < 0x100)
+ return false;
+
+ uint8_t* memory = 0;
+ *value = *reinterpret_cast<const T*>(&memory[address]);
+ return true;
+ }
+};
+
+
+#if defined(__GNUC__)
+
+
+#if defined(__i386__)
+
+// GetEBP returns the current value of the %ebp register. Because it's
+// implemented as a function, %ebp itself contains GetEBP's frame pointer
+// and not the caller's frame pointer. Dereference %ebp to obtain the
+// caller's frame pointer, which the compiler-generated preamble stored
+// on the stack (provided frame pointers are not being omitted.) Because
+// this function depends on the compiler-generated preamble, inlining is
+// disabled.
+static uint32_t GetEBP() __attribute__((noinline));
+static uint32_t GetEBP() {
+ uint32_t ebp;
+ __asm__ __volatile__(
+ "movl (%%ebp), %0"
+ : "=a" (ebp)
+ );
+ return ebp;
+}
+
+
+// The caller's %esp is 8 higher than the value of %ebp in this function,
+// assuming that it's not inlined and that the standard prolog is used.
+// The CALL instruction places a 4-byte return address on the stack above
+// the caller's %esp, and this function's prolog will save the caller's %ebp
+// on the stack as well, for another 4 bytes, before storing %esp in %ebp.
+static uint32_t GetESP() __attribute__((noinline));
+static uint32_t GetESP() {
+ uint32_t ebp;
+ __asm__ __volatile__(
+ "movl %%ebp, %0"
+ : "=a" (ebp)
+ );
+ return ebp + 8;
+}
+
+
+// GetEIP returns the instruction pointer identifying the next instruction
+// to execute after GetEIP returns. It obtains this information from the
+// stack, where it was placed by the call instruction that called GetEIP.
+// This function depends on frame pointers not being omitted. It is possible
+// to write a pure asm version of this routine that has no compiler-generated
+// preamble and uses %esp instead of %ebp; that would function in the
+// absence of frame pointers. However, the simpler approach is used here
+// because GetEBP and stackwalking necessarily depends on access to frame
+// pointers. Because this function depends on a call instruction and the
+// compiler-generated preamble, inlining is disabled.
+static uint32_t GetEIP() __attribute__((noinline));
+static uint32_t GetEIP() {
+ uint32_t eip;
+ __asm__ __volatile__(
+ "movl 4(%%ebp), %0"
+ : "=a" (eip)
+ );
+ return eip;
+}
+
+
+#elif defined(__ppc__)
+
+
+// GetSP returns the current value of the %r1 register, which by convention,
+// is the stack pointer on ppc. Because it's implemented as a function,
+// %r1 itself contains GetSP's own stack pointer and not the caller's stack
+// pointer. Dereference %r1 to obtain the caller's stack pointer, which the
+// compiler-generated prolog stored on the stack. Because this function
+// depends on the compiler-generated prolog, inlining is disabled.
+static uint32_t GetSP() __attribute__((noinline));
+static uint32_t GetSP() {
+ uint32_t sp;
+ __asm__ __volatile__(
+ "lwz %0, 0(r1)"
+ : "=r" (sp)
+ );
+ return sp;
+}
+
+
+// GetPC returns the program counter identifying the next instruction to
+// execute after GetPC returns. It obtains this information from the
+// link register, where it was placed by the branch instruction that called
+// GetPC. Because this function depends on the caller's use of a branch
+// instruction, inlining is disabled.
+static uint32_t GetPC() __attribute__((noinline));
+static uint32_t GetPC() {
+ uint32_t lr;
+ __asm__ __volatile__(
+ "mflr %0"
+ : "=r" (lr)
+ );
+ return lr;
+}
+
+
+#elif defined(__sparc__)
+
+
+// GetSP returns the current value of the %sp/%o6/%g_r[14] register, which
+// by convention, is the stack pointer on sparc. Because it's implemented
+// as a function, %sp itself contains GetSP's own stack pointer and not
+// the caller's stack pointer. Dereference to obtain the caller's stack
+// pointer, which the compiler-generated prolog stored on the stack.
+// Because this function depends on the compiler-generated prolog, inlining
+// is disabled.
+static uint32_t GetSP() __attribute__((noinline));
+static uint32_t GetSP() {
+ uint32_t sp;
+ __asm__ __volatile__(
+ "mov %%fp, %0"
+ : "=r" (sp)
+ );
+ return sp;
+}
+
+// GetFP returns the current value of the %fp register. Because it's
+// implemented as a function, %fp itself contains GetFP's frame pointer
+// and not the caller's frame pointer. Dereference %fp to obtain the
+// caller's frame pointer, which the compiler-generated preamble stored
+// on the stack (provided frame pointers are not being omitted.) Because
+// this function depends on the compiler-generated preamble, inlining is
+// disabled.
+static uint32_t GetFP() __attribute__((noinline));
+static uint32_t GetFP() {
+ uint32_t fp;
+ __asm__ __volatile__(
+ "ld [%%fp+56], %0"
+ : "=r" (fp)
+ );
+ return fp;
+}
+
+// GetPC returns the program counter identifying the next instruction to
+// execute after GetPC returns. It obtains this information from the
+// link register, where it was placed by the branch instruction that called
+// GetPC. Because this function depends on the caller's use of a branch
+// instruction, inlining is disabled.
+static uint32_t GetPC() __attribute__((noinline));
+static uint32_t GetPC() {
+ uint32_t pc;
+ __asm__ __volatile__(
+ "mov %%i7, %0"
+ : "=r" (pc)
+ );
+ return pc + 8;
+}
+
+#endif // __i386__ || __ppc__ || __sparc__
+
+#elif defined(__SUNPRO_CC)
+
+#if defined(__i386__)
+extern "C" {
+extern uint32_t GetEIP();
+extern uint32_t GetEBP();
+extern uint32_t GetESP();
+}
+#elif defined(__sparc__)
+extern "C" {
+extern uint32_t GetPC();
+extern uint32_t GetFP();
+extern uint32_t GetSP();
+}
+#endif // __i386__ || __sparc__
+
+#endif // __GNUC__ || __SUNPRO_CC
+
+// CountCallerFrames returns the number of stack frames beneath the function
+// that called CountCallerFrames. Because this function's return value
+// is dependent on the size of the stack beneath it, inlining is disabled,
+// and any function that calls this should not be inlined either.
+#if defined(__GNUC__)
+static unsigned int CountCallerFrames() __attribute__((noinline));
+#elif defined(__SUNPRO_CC)
+static unsigned int CountCallerFrames();
+#endif
+static unsigned int CountCallerFrames() {
+ SelfMemoryRegion memory;
+ BasicSourceLineResolver resolver;
+
+#if defined(__i386__)
+ MDRawContextX86 context = MDRawContextX86();
+ context.eip = GetEIP();
+ context.ebp = GetEBP();
+ context.esp = GetESP();
+
+ StackwalkerX86 stackwalker = StackwalkerX86(NULL, &context, &memory, NULL,
+ NULL, &resolver);
+#elif defined(__ppc__)
+ MDRawContextPPC context = MDRawContextPPC();
+ context.srr0 = GetPC();
+ context.gpr[1] = GetSP();
+
+ StackwalkerPPC stackwalker = StackwalkerPPC(NULL, &context, &memory, NULL,
+ NULL, &resolver);
+#elif defined(__sparc__)
+ MDRawContextSPARC context = MDRawContextSPARC();
+ context.pc = GetPC();
+ context.g_r[14] = GetSP();
+ context.g_r[30] = GetFP();
+
+ StackwalkerSPARC stackwalker = StackwalkerSPARC(NULL, &context, &memory,
+ NULL, NULL, &resolver);
+#endif // __i386__ || __ppc__ || __sparc__
+
+ CallStack stack;
+ vector<const CodeModule*> modules_without_symbols;
+ stackwalker.Walk(&stack, &modules_without_symbols);
+
+#ifdef PRINT_STACKS
+ printf("\n");
+ for (unsigned int frame_index = 0;
+ frame_index < stack.frames()->size();
+ ++frame_index) {
+ StackFrame *frame = stack.frames()->at(frame_index);
+ printf("frame %-3d instruction = 0x%08" PRIx64,
+ frame_index, frame->instruction);
+#if defined(__i386__)
+ StackFrameX86 *frame_x86 = reinterpret_cast<StackFrameX86*>(frame);
+ printf(" esp = 0x%08x ebp = 0x%08x\n",
+ frame_x86->context.esp, frame_x86->context.ebp);
+#elif defined(__ppc__)
+ StackFramePPC *frame_ppc = reinterpret_cast<StackFramePPC*>(frame);
+ printf(" gpr[1] = 0x%08x\n", frame_ppc->context.gpr[1]);
+#elif defined(__sparc__)
+ StackFrameSPARC *frame_sparc = reinterpret_cast<StackFrameSPARC*>(frame);
+ printf(" sp = 0x%08x fp = 0x%08x\n",
+ frame_sparc->context.g_r[14], frame_sparc->context.g_r[30]);
+#endif // __i386__ || __ppc__ || __sparc__
+ }
+#endif // PRINT_STACKS
+
+ // Subtract 1 because the caller wants the number of frames beneath
+ // itself. Because the caller called us, subract two for our frame and its
+ // frame, which are included in stack.size().
+ return stack.frames()->size() - 2;
+}
+
+
+// Recursor verifies that the number stack frames beneath itself is one more
+// than the number of stack frames beneath its parent. When depth frames
+// have been reached, Recursor stops checking and returns success. If the
+// frame count check fails at any depth, Recursor will stop and return false.
+// Because this calls CountCallerFrames, inlining is disabled.
+#if defined(__GNUC__)
+static bool Recursor(unsigned int depth, unsigned int parent_callers)
+ __attribute__((noinline));
+#elif defined(__SUNPRO_CC)
+static bool Recursor(unsigned int depth, unsigned int parent_callers);
+#endif
+static bool Recursor(unsigned int depth, unsigned int parent_callers) {
+ unsigned int callers = CountCallerFrames();
+ if (callers != parent_callers + 1)
+ return false;
+
+ if (depth)
+ return Recursor(depth - 1, callers);
+
+ // depth == 0
+ return true;
+}
+
+
+// Because this calls CountCallerFrames, inlining is disabled - but because
+// it's main (and nobody calls it other than the entry point), it wouldn't
+// be inlined anyway.
+#if defined(__GNUC__)
+int main(int argc, char** argv) __attribute__((noinline));
+#elif defined(__SUNPRO_CC)
+int main(int argc, char** argv);
+#endif
+int main(int argc, char** argv) {
+ BPLOG_INIT(&argc, &argv);
+
+ return Recursor(RECURSION_DEPTH, CountCallerFrames()) ? 0 : 1;
+}
+
+
+#else
+// Not i386 or ppc or sparc? We can only test stacks we know how to walk.
+
+
+int main(int argc, char **argv) {
+ BPLOG_INIT(&argc, &argv);
+
+ // "make check" interprets an exit status of 77 to mean that the test is
+ // not supported.
+ BPLOG(ERROR) << "Selftest not supported here";
+ return 77;
+}
+
+
+#endif // (__GNUC__ || __SUNPRO_CC) && (__i386__ || __ppc__ || __sparc__)
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_selftest_sol.s b/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_selftest_sol.s
new file mode 100644
index 0000000000..648b0499a1
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_selftest_sol.s
@@ -0,0 +1,111 @@
+/* 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.
+ */
+
+/* stackwalker_selftest_sol.s
+ * On Solaris, the recommeded compiler is CC, so we can not use gcc inline
+ * asm, use this method instead.
+ *
+ * How to compile: as -P -L -D_ASM -D_STDC -K PIC -o \
+ * src/processor/stackwalker_selftest_sol.o \
+ * src/processor/stackwalker_selftest_sol.s
+ *
+ * Author: Michael Shang
+ */
+
+#include <sys/asm_linkage.h>
+
+#if defined(__i386)
+
+
+ENTRY(GetEBP)
+ pushl %ebp
+ movl %esp,%ebp
+ subl $0x00000004,%esp
+ movl 0x00000000(%ebp),%eax
+ movl %eax,0xfffffffc(%ebp)
+ movl 0xfffffffc(%ebp),%eax
+ leave
+ ret
+SET_SIZE(GetEBP)
+
+ENTRY(GetEIP)
+ pushl %ebp
+ movl %esp,%ebp
+ subl $0x00000004,%esp
+ movl 0x00000004(%ebp),%eax
+ movl %eax,0xfffffffc(%ebp)
+ movl 0xfffffffc(%ebp),%eax
+ leave
+ ret
+SET_SIZE(GetEIP)
+
+ENTRY(GetESP)
+ pushl %ebp
+ movl %esp,%ebp
+ subl $0x00000004,%esp
+ movl %ebp,%eax
+ movl %eax,0xfffffffc(%ebp)
+ movl 0xfffffffc(%ebp),%eax
+ addl $0x00000008,%eax
+ leave
+ ret
+SET_SIZE(GetESP)
+
+
+#elif defined(__sparc)
+
+
+ENTRY(GetPC)
+ save %sp, -120, %sp
+ mov %i7, %i4
+ inccc 8, %i4
+ mov %i4, %i0
+ ret
+ restore
+SET_SIZE(GetPC)
+
+ENTRY(GetSP)
+ save %sp, -120, %sp
+ mov %fp, %i4
+ mov %i4, %i0
+ ret
+ restore
+SET_SIZE(GetSP)
+
+ENTRY(GetFP)
+ save %sp, -120, %sp
+ ld [%fp + 56], %g1
+ mov %g1, %i0
+ ret
+ restore
+SET_SIZE(GetFP)
+
+
+#endif // __i386 || __sparc
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_sparc.cc b/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_sparc.cc
new file mode 100644
index 0000000000..4de838afec
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_sparc.cc
@@ -0,0 +1,147 @@
+// 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.
+
+// stackwalker_sparc.cc: sparc-specific stackwalker.
+//
+// See stackwalker_sparc.h for documentation.
+//
+// Author: Michael Shang
+
+
+#include "google_breakpad/processor/call_stack.h"
+#include "google_breakpad/processor/memory_region.h"
+#include "google_breakpad/processor/stack_frame_cpu.h"
+#include "processor/logging.h"
+#include "processor/stackwalker_sparc.h"
+
+namespace google_breakpad {
+
+
+StackwalkerSPARC::StackwalkerSPARC(const SystemInfo* system_info,
+ const MDRawContextSPARC* context,
+ MemoryRegion* memory,
+ const CodeModules* modules,
+ StackFrameSymbolizer* resolver_helper)
+ : Stackwalker(system_info, memory, modules, resolver_helper),
+ context_(context) {
+}
+
+
+StackFrame* StackwalkerSPARC::GetContextFrame() {
+ if (!context_) {
+ BPLOG(ERROR) << "Can't get context frame without context";
+ return NULL;
+ }
+
+ StackFrameSPARC* frame = new StackFrameSPARC();
+
+ // The instruction pointer is stored directly in a register, so pull it
+ // straight out of the CPU context structure.
+ frame->context = *context_;
+ frame->context_validity = StackFrameSPARC::CONTEXT_VALID_ALL;
+ frame->trust = StackFrame::FRAME_TRUST_CONTEXT;
+ frame->instruction = frame->context.pc;
+
+ return frame;
+}
+
+
+StackFrame* StackwalkerSPARC::GetCallerFrame(const CallStack* stack,
+ bool stack_scan_allowed) {
+ if (!memory_ || !stack) {
+ BPLOG(ERROR) << "Can't get caller frame without memory or stack";
+ return NULL;
+ }
+
+ StackFrameSPARC* last_frame = static_cast<StackFrameSPARC*>(
+ stack->frames()->back());
+
+ // new: caller
+ // old: callee
+ // %fp, %i6 and g_r[30] is the same, see minidump_format.h
+ // %sp, %o6 and g_r[14] is the same, see minidump_format.h
+ // %sp_new = %fp_old
+ // %fp_new = *(%fp_old + 32 + 32 - 8), where the callee's %i6
+ // %pc_new = *(%fp_old + 32 + 32 - 4) + 8
+ // which is callee's %i7 plus 8
+
+ // A caller frame must reside higher in memory than its callee frames.
+ // Anything else is an error, or an indication that we've reached the
+ // end of the stack.
+ uint64_t stack_pointer = last_frame->context.g_r[30];
+ if (stack_pointer <= last_frame->context.g_r[14]) {
+ return NULL;
+ }
+
+ uint32_t instruction;
+ if (!memory_->GetMemoryAtAddress(stack_pointer + 60,
+ &instruction) || instruction <= 1) {
+ return NULL;
+ }
+
+ uint32_t stack_base;
+ if (!memory_->GetMemoryAtAddress(stack_pointer + 56,
+ &stack_base) || stack_base <= 1) {
+ return NULL;
+ }
+
+ // Should we terminate the stack walk? (end-of-stack or broken invariant)
+ if (TerminateWalk(instruction,
+ stack_pointer,
+ last_frame->context.g_r[14],
+ stack->frames()->size() == 1)) {
+ return NULL;
+ }
+
+ StackFrameSPARC* frame = new StackFrameSPARC();
+
+ frame->context = last_frame->context;
+ frame->context.g_r[14] = stack_pointer;
+ frame->context.g_r[30] = stack_base;
+
+ // frame->context.pc is the return address, which is 2 instruction
+ // past the branch that caused us to arrive at the callee, which are
+ // a CALL instruction then a NOP instruction.
+ // frame_ppc->instruction to 8 less than that. Since all sparc
+ // instructions are 4 bytes wide, this is the address of the branch
+ // instruction. This allows source line information to match up with the
+ // line that contains a function call. Callers that require the exact
+ // return address value may access the %i7/g_r[31] field of StackFrameSPARC.
+ frame->context.pc = instruction + 8;
+ frame->instruction = instruction;
+ frame->context_validity = StackFrameSPARC::CONTEXT_VALID_PC |
+ StackFrameSPARC::CONTEXT_VALID_SP |
+ StackFrameSPARC::CONTEXT_VALID_FP;
+ frame->trust = StackFrame::FRAME_TRUST_FP;
+
+ return frame;
+}
+
+
+} // namespace google_breakpad
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_sparc.h b/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_sparc.h
new file mode 100644
index 0000000000..e8f2a38887
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_sparc.h
@@ -0,0 +1,78 @@
+// 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.
+
+// stackwalker_sparc.h: sparc-specific stackwalker.
+//
+// Provides stack frames given sparc register context and a memory region
+// corresponding to an sparc stack.
+//
+// Author: Michael Shang
+
+
+#ifndef PROCESSOR_STACKWALKER_SPARC_H__
+#define PROCESSOR_STACKWALKER_SPARC_H__
+
+
+#include "google_breakpad/common/breakpad_types.h"
+#include "google_breakpad/common/minidump_format.h"
+#include "google_breakpad/processor/stackwalker.h"
+
+namespace google_breakpad {
+
+class CodeModules;
+
+class StackwalkerSPARC : public Stackwalker {
+ public:
+ // context is a sparc context object that gives access to sparc-specific
+ // register state corresponding to the innermost called frame to be
+ // included in the stack. The other arguments are passed directly through
+ // to the base Stackwalker constructor.
+ StackwalkerSPARC(const SystemInfo* system_info,
+ const MDRawContextSPARC* context,
+ MemoryRegion* memory,
+ const CodeModules* modules,
+ StackFrameSymbolizer* frame_symbolizer);
+
+ private:
+ // Implementation of Stackwalker, using sparc context (%fp, %sp, %pc) and
+ // stack conventions
+ virtual StackFrame* GetContextFrame();
+ virtual StackFrame* GetCallerFrame(const CallStack* stack,
+ bool stack_scan_allowed);
+
+ // Stores the CPU context corresponding to the innermost stack frame to
+ // be returned by GetContextFrame.
+ const MDRawContextSPARC* context_;
+};
+
+
+} // namespace google_breakpad
+
+
+#endif // PROCESSOR_STACKWALKER_SPARC_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_unittest_utils.h b/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_unittest_utils.h
new file mode 100644
index 0000000000..3a92a5ea7a
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_unittest_utils.h
@@ -0,0 +1,220 @@
+// -*- 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>
+
+// Mock classes for writing stackwalker tests, shared amongst architectures.
+
+#ifndef PROCESSOR_STACKWALKER_UNITTEST_UTILS_H_
+#define PROCESSOR_STACKWALKER_UNITTEST_UTILS_H_
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string>
+#include <vector>
+
+#include "common/using_std_string.h"
+#include "google_breakpad/common/breakpad_types.h"
+#include "google_breakpad/processor/code_module.h"
+#include "google_breakpad/processor/code_modules.h"
+#include "google_breakpad/processor/memory_region.h"
+#include "google_breakpad/processor/symbol_supplier.h"
+#include "google_breakpad/processor/system_info.h"
+#include "processor/linked_ptr.h"
+
+class MockMemoryRegion: public google_breakpad::MemoryRegion {
+ public:
+ MockMemoryRegion(): base_address_(0) { }
+
+ // Set this region's address and contents. If we have placed an
+ // instance of this class in a test fixture class, individual tests
+ // can use this to provide the region's contents.
+ void Init(uint64_t base_address, const string &contents) {
+ base_address_ = base_address;
+ contents_ = contents;
+ }
+
+ uint64_t GetBase() const { return base_address_; }
+ uint32_t GetSize() const { return contents_.size(); }
+
+ bool GetMemoryAtAddress(uint64_t address, uint8_t *value) const {
+ return GetMemoryLittleEndian(address, value);
+ }
+ bool GetMemoryAtAddress(uint64_t address, uint16_t *value) const {
+ return GetMemoryLittleEndian(address, value);
+ }
+ bool GetMemoryAtAddress(uint64_t address, uint32_t *value) const {
+ return GetMemoryLittleEndian(address, value);
+ }
+ bool GetMemoryAtAddress(uint64_t address, uint64_t *value) const {
+ return GetMemoryLittleEndian(address, value);
+ }
+ void Print() const {
+ assert(false);
+ }
+
+ private:
+ // Fetch a little-endian value from ADDRESS in contents_ whose size
+ // is BYTES, and store it in *VALUE. Return true on success.
+ template<typename ValueType>
+ bool GetMemoryLittleEndian(uint64_t address, ValueType *value) const {
+ if (address < base_address_ ||
+ address - base_address_ + sizeof(ValueType) > contents_.size())
+ return false;
+ ValueType v = 0;
+ int start = address - base_address_;
+ // The loop condition is odd, but it's correct for size_t.
+ for (size_t i = sizeof(ValueType) - 1; i < sizeof(ValueType); i--)
+ v = (v << 8) | static_cast<unsigned char>(contents_[start + i]);
+ *value = v;
+ return true;
+ }
+
+ uint64_t base_address_;
+ string contents_;
+};
+
+class MockCodeModule: public google_breakpad::CodeModule {
+ public:
+ MockCodeModule(uint64_t base_address, uint64_t size,
+ const string &code_file, const string &version)
+ : base_address_(base_address), size_(size), code_file_(code_file) { }
+
+ uint64_t base_address() const { return base_address_; }
+ uint64_t size() const { return size_; }
+ string code_file() const { return code_file_; }
+ string code_identifier() const { return code_file_; }
+ string debug_file() const { return code_file_; }
+ string debug_identifier() const { return code_file_; }
+ string version() const { return version_; }
+ google_breakpad::CodeModule *Copy() const {
+ abort(); // Tests won't use this.
+ }
+ virtual bool is_unloaded() const { return false; }
+ virtual uint64_t shrink_down_delta() const { return 0; }
+ virtual void SetShrinkDownDelta(uint64_t shrink_down_delta) {}
+
+ private:
+ uint64_t base_address_;
+ uint64_t size_;
+ string code_file_;
+ string version_;
+};
+
+class MockCodeModules: public google_breakpad::CodeModules {
+ public:
+ typedef google_breakpad::CodeModule CodeModule;
+ typedef google_breakpad::CodeModules CodeModules;
+
+ void Add(const MockCodeModule *module) {
+ modules_.push_back(module);
+ }
+
+ unsigned int module_count() const { return modules_.size(); }
+
+ const CodeModule *GetModuleForAddress(uint64_t address) const {
+ for (ModuleVector::const_iterator i = modules_.begin();
+ i != modules_.end(); i++) {
+ const MockCodeModule *module = *i;
+ if (module->base_address() <= address &&
+ address - module->base_address() < module->size())
+ return module;
+ }
+ return NULL;
+ };
+
+ const CodeModule *GetMainModule() const { return modules_[0]; }
+
+ const CodeModule *GetModuleAtSequence(unsigned int sequence) const {
+ return modules_.at(sequence);
+ }
+
+ const CodeModule *GetModuleAtIndex(unsigned int index) const {
+ return modules_.at(index);
+ }
+
+ CodeModules *Copy() const { abort(); } // Tests won't use this
+
+ virtual std::vector<google_breakpad::linked_ptr<const CodeModule> >
+ GetShrunkRangeModules() const {
+ return std::vector<google_breakpad::linked_ptr<const CodeModule> >();
+ }
+
+ private:
+ typedef std::vector<const MockCodeModule *> ModuleVector;
+ ModuleVector modules_;
+};
+
+class MockSymbolSupplier: public google_breakpad::SymbolSupplier {
+ public:
+ typedef google_breakpad::CodeModule CodeModule;
+ typedef google_breakpad::SystemInfo SystemInfo;
+ MOCK_METHOD3(GetSymbolFile, SymbolResult(const CodeModule *module,
+ const SystemInfo *system_info,
+ string *symbol_file));
+ MOCK_METHOD4(GetSymbolFile, SymbolResult(const CodeModule *module,
+ const SystemInfo *system_info,
+ string *symbol_file,
+ string *symbol_data));
+ MOCK_METHOD5(GetCStringSymbolData, SymbolResult(const CodeModule *module,
+ const SystemInfo *system_info,
+ string *symbol_file,
+ char **symbol_data,
+ size_t *symbol_data_size));
+ MOCK_METHOD1(FreeSymbolData, void(const CodeModule *module));
+
+ // Copies the passed string contents into a newly allocated buffer.
+ // The newly allocated buffer will be freed during destruction.
+ char* CopySymbolDataAndOwnTheCopy(const string &info,
+ size_t *symbol_data_size) {
+ *symbol_data_size = info.size() + 1;
+ char *symbol_data = new char[*symbol_data_size];
+ memcpy(symbol_data, info.c_str(), info.size());
+ symbol_data[info.size()] = '\0';
+ symbol_data_to_free_.push_back(symbol_data);
+ return symbol_data;
+ }
+
+ virtual ~MockSymbolSupplier() {
+ for (SymbolDataVector::const_iterator i = symbol_data_to_free_.begin();
+ i != symbol_data_to_free_.end(); i++) {
+ char* symbol_data = *i;
+ delete [] symbol_data;
+ }
+ }
+
+ private:
+ // List of symbol data to be freed upon destruction
+ typedef std::vector<char*> SymbolDataVector;
+ SymbolDataVector symbol_data_to_free_;
+};
+
+#endif // PROCESSOR_STACKWALKER_UNITTEST_UTILS_H_
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_x86.cc b/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_x86.cc
new file mode 100644
index 0000000000..ed2b383d4f
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_x86.cc
@@ -0,0 +1,680 @@
+// 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.
+
+// stackwalker_x86.cc: x86-specific stackwalker.
+//
+// See stackwalker_x86.h for documentation.
+//
+// Author: Mark Mentovai
+
+#include <assert.h>
+#include <string>
+
+#include "common/scoped_ptr.h"
+#include "google_breakpad/processor/call_stack.h"
+#include "google_breakpad/processor/code_modules.h"
+#include "google_breakpad/processor/memory_region.h"
+#include "google_breakpad/processor/source_line_resolver_interface.h"
+#include "google_breakpad/processor/stack_frame_cpu.h"
+#include "processor/logging.h"
+#include "processor/postfix_evaluator-inl.h"
+#include "processor/stackwalker_x86.h"
+#include "processor/windows_frame_info.h"
+#include "processor/cfi_frame_info.h"
+
+namespace google_breakpad {
+
+// Max reasonable size for a single x86 frame is 128 KB. This value is used in
+// a heuristic for recovering of the EBP chain after a scan for return address.
+// This value is based on a stack frame size histogram built for a set of
+// popular third party libraries which suggests that 99.5% of all frames are
+// smaller than 128 KB.
+static const uint32_t kMaxReasonableGapBetweenFrames = 128 * 1024;
+
+const StackwalkerX86::CFIWalker::RegisterSet
+StackwalkerX86::cfi_register_map_[] = {
+ // It may seem like $eip and $esp are callee-saves, because (with Unix or
+ // cdecl calling conventions) the callee is responsible for having them
+ // restored upon return. But the callee_saves flags here really means
+ // that the walker should assume they're unchanged if the CFI doesn't
+ // mention them, which is clearly wrong for $eip and $esp.
+ { "$eip", ".ra", false,
+ StackFrameX86::CONTEXT_VALID_EIP, &MDRawContextX86::eip },
+ { "$esp", ".cfa", false,
+ StackFrameX86::CONTEXT_VALID_ESP, &MDRawContextX86::esp },
+ { "$ebp", NULL, true,
+ StackFrameX86::CONTEXT_VALID_EBP, &MDRawContextX86::ebp },
+ { "$eax", NULL, false,
+ StackFrameX86::CONTEXT_VALID_EAX, &MDRawContextX86::eax },
+ { "$ebx", NULL, true,
+ StackFrameX86::CONTEXT_VALID_EBX, &MDRawContextX86::ebx },
+ { "$ecx", NULL, false,
+ StackFrameX86::CONTEXT_VALID_ECX, &MDRawContextX86::ecx },
+ { "$edx", NULL, false,
+ StackFrameX86::CONTEXT_VALID_EDX, &MDRawContextX86::edx },
+ { "$esi", NULL, true,
+ StackFrameX86::CONTEXT_VALID_ESI, &MDRawContextX86::esi },
+ { "$edi", NULL, true,
+ StackFrameX86::CONTEXT_VALID_EDI, &MDRawContextX86::edi },
+};
+
+StackwalkerX86::StackwalkerX86(const SystemInfo* system_info,
+ const MDRawContextX86* context,
+ MemoryRegion* memory,
+ const CodeModules* modules,
+ StackFrameSymbolizer* resolver_helper)
+ : Stackwalker(system_info, memory, modules, resolver_helper),
+ context_(context),
+ cfi_walker_(cfi_register_map_,
+ (sizeof(cfi_register_map_) / sizeof(cfi_register_map_[0]))) {
+ if (memory_ && memory_->GetBase() + memory_->GetSize() - 1 > 0xffffffff) {
+ // The x86 is a 32-bit CPU, the limits of the supplied stack are invalid.
+ // Mark memory_ = NULL, which will cause stackwalking to fail.
+ BPLOG(ERROR) << "Memory out of range for stackwalking: " <<
+ HexString(memory_->GetBase()) << "+" <<
+ HexString(memory_->GetSize());
+ memory_ = NULL;
+ }
+}
+
+StackFrameX86::~StackFrameX86() {
+ if (windows_frame_info)
+ delete windows_frame_info;
+ windows_frame_info = NULL;
+ if (cfi_frame_info)
+ delete cfi_frame_info;
+ cfi_frame_info = NULL;
+}
+
+uint64_t StackFrameX86::ReturnAddress() const {
+ assert(context_validity & StackFrameX86::CONTEXT_VALID_EIP);
+ return context.eip;
+}
+
+StackFrame* StackwalkerX86::GetContextFrame() {
+ if (!context_) {
+ BPLOG(ERROR) << "Can't get context frame without context";
+ return NULL;
+ }
+
+ StackFrameX86* frame = new StackFrameX86();
+
+ // The instruction pointer is stored directly in a register, so pull it
+ // straight out of the CPU context structure.
+ frame->context = *context_;
+ frame->context_validity = StackFrameX86::CONTEXT_VALID_ALL;
+ frame->trust = StackFrame::FRAME_TRUST_CONTEXT;
+ frame->instruction = frame->context.eip;
+
+ return frame;
+}
+
+StackFrameX86* StackwalkerX86::GetCallerByWindowsFrameInfo(
+ const vector<StackFrame*> &frames,
+ WindowsFrameInfo* last_frame_info,
+ bool stack_scan_allowed) {
+ StackFrame::FrameTrust trust = StackFrame::FRAME_TRUST_NONE;
+
+ StackFrameX86* last_frame = static_cast<StackFrameX86*>(frames.back());
+
+ // Save the stack walking info we found, in case we need it later to
+ // find the callee of the frame we're constructing now.
+ last_frame->windows_frame_info = last_frame_info;
+
+ // This function only covers the full STACK WIN case. If
+ // last_frame_info is VALID_PARAMETER_SIZE-only, then we should
+ // assume the traditional frame format or use some other strategy.
+ if (last_frame_info->valid != WindowsFrameInfo::VALID_ALL)
+ return NULL;
+
+ // This stackwalker sets each frame's %esp to its value immediately prior
+ // to the CALL into the callee. This means that %esp points to the last
+ // callee argument pushed onto the stack, which may not be where %esp points
+ // after the callee returns. Specifically, the value is correct for the
+ // cdecl calling convention, but not other conventions. The cdecl
+ // convention requires a caller to pop its callee's arguments from the
+ // stack after the callee returns. This is usually accomplished by adding
+ // the known size of the arguments to %esp. Other calling conventions,
+ // including stdcall, thiscall, and fastcall, require the callee to pop any
+ // parameters stored on the stack before returning. This is usually
+ // accomplished by using the RET n instruction, which pops n bytes off
+ // the stack after popping the return address.
+ //
+ // Because each frame's %esp will point to a location on the stack after
+ // callee arguments have been PUSHed, when locating things in a stack frame
+ // relative to %esp, the size of the arguments to the callee need to be
+ // taken into account. This seems a little bit unclean, but it's better
+ // than the alternative, which would need to take these same things into
+ // account, but only for cdecl functions. With this implementation, we get
+ // to be agnostic about each function's calling convention. Furthermore,
+ // this is how Windows debugging tools work, so it means that the %esp
+ // values produced by this stackwalker directly correspond to the %esp
+ // values you'll see there.
+ //
+ // If the last frame has no callee (because it's the context frame), just
+ // set the callee parameter size to 0: the stack pointer can't point to
+ // callee arguments because there's no callee. This is correct as long
+ // as the context wasn't captured while arguments were being pushed for
+ // a function call. Note that there may be functions whose parameter sizes
+ // are unknown, 0 is also used in that case. When that happens, it should
+ // be possible to walk to the next frame without reference to %esp.
+
+ uint32_t last_frame_callee_parameter_size = 0;
+ int frames_already_walked = frames.size();
+ if (frames_already_walked >= 2) {
+ const StackFrameX86* last_frame_callee
+ = static_cast<StackFrameX86*>(frames[frames_already_walked - 2]);
+ WindowsFrameInfo* last_frame_callee_info
+ = last_frame_callee->windows_frame_info;
+ if (last_frame_callee_info &&
+ (last_frame_callee_info->valid
+ & WindowsFrameInfo::VALID_PARAMETER_SIZE)) {
+ last_frame_callee_parameter_size =
+ last_frame_callee_info->parameter_size;
+ }
+ }
+
+ // Set up the dictionary for the PostfixEvaluator. %ebp, %esp, and sometimes
+ // %ebx are used in program strings, and their previous values are known, so
+ // set them here.
+ PostfixEvaluator<uint32_t>::DictionaryType dictionary;
+ // Provide the current register values.
+ dictionary["$ebp"] = last_frame->context.ebp;
+ dictionary["$esp"] = last_frame->context.esp;
+ if (last_frame->context_validity & StackFrameX86::CONTEXT_VALID_EBX)
+ dictionary["$ebx"] = last_frame->context.ebx;
+ // Provide constants from the debug info for last_frame and its callee.
+ // .cbCalleeParams is a Breakpad extension that allows us to use the
+ // PostfixEvaluator engine when certain types of debugging information
+ // are present without having to write the constants into the program
+ // string as literals.
+ dictionary[".cbCalleeParams"] = last_frame_callee_parameter_size;
+ dictionary[".cbSavedRegs"] = last_frame_info->saved_register_size;
+ dictionary[".cbLocals"] = last_frame_info->local_size;
+
+ uint32_t raSearchStart = last_frame->context.esp +
+ last_frame_callee_parameter_size +
+ last_frame_info->local_size +
+ last_frame_info->saved_register_size;
+
+ uint32_t raSearchStartOld = raSearchStart;
+ uint32_t found = 0; // dummy value
+ // Scan up to three words above the calculated search value, in case
+ // the stack was aligned to a quadword boundary.
+ //
+ // TODO(ivan.penkov): Consider cleaning up the scan for return address that
+ // follows. The purpose of this scan is to adjust the .raSearchStart
+ // calculation (which is based on register %esp) in the cases where register
+ // %esp may have been aligned (up to a quadword). There are two problems
+ // with this approach:
+ // 1) In practice, 64 byte boundary alignment is seen which clearly can not
+ // be handled by a three word scan.
+ // 2) A search for a return address is "guesswork" by definition because
+ // the results will be different depending on what is left on the stack
+ // from previous executions.
+ // So, basically, the results from this scan should be ignored if other means
+ // for calculation of the value of .raSearchStart are available.
+ if (ScanForReturnAddress(raSearchStart, &raSearchStart, &found, 3) &&
+ last_frame->trust == StackFrame::FRAME_TRUST_CONTEXT &&
+ last_frame->windows_frame_info != NULL &&
+ last_frame_info->type_ == WindowsFrameInfo::STACK_INFO_FPO &&
+ raSearchStartOld == raSearchStart &&
+ found == last_frame->context.eip) {
+ // The context frame represents an FPO-optimized Windows system call.
+ // On the top of the stack we have a pointer to the current instruction.
+ // This means that the callee has returned but the return address is still
+ // on the top of the stack which is very atypical situaltion.
+ // Skip one slot from the stack and do another scan in order to get the
+ // actual return address.
+ raSearchStart += 4;
+ ScanForReturnAddress(raSearchStart, &raSearchStart, &found, 3);
+ }
+
+ dictionary[".cbParams"] = last_frame_info->parameter_size;
+
+ // Decide what type of program string to use. The program string is in
+ // postfix notation and will be passed to PostfixEvaluator::Evaluate.
+ // Given the dictionary and the program string, it is possible to compute
+ // the return address and the values of other registers in the calling
+ // function. Because of bugs described below, the stack may need to be
+ // scanned for these values. The results of program string evaluation
+ // will be used to determine whether to scan for better values.
+ string program_string;
+ bool recover_ebp = true;
+
+ trust = StackFrame::FRAME_TRUST_CFI;
+ if (!last_frame_info->program_string.empty()) {
+ // The FPO data has its own program string, which will tell us how to
+ // get to the caller frame, and may even fill in the values of
+ // nonvolatile registers and provide pointers to local variables and
+ // parameters. In some cases, particularly with program strings that use
+ // .raSearchStart, the stack may need to be scanned afterward.
+ program_string = last_frame_info->program_string;
+ } else if (last_frame_info->allocates_base_pointer) {
+ // The function corresponding to the last frame doesn't use the frame
+ // pointer for conventional purposes, but it does allocate a new
+ // frame pointer and use it for its own purposes. Its callee's
+ // information is still accessed relative to %esp, and the previous
+ // value of %ebp can be recovered from a location in its stack frame,
+ // within the saved-register area.
+ //
+ // Functions that fall into this category use the %ebp register for
+ // a purpose other than the frame pointer. They restore the caller's
+ // %ebp before returning. These functions create their stack frame
+ // after a CALL by decrementing the stack pointer in an amount
+ // sufficient to store local variables, and then PUSHing saved
+ // registers onto the stack. Arguments to a callee function, if any,
+ // are PUSHed after that. Walking up to the caller, therefore,
+ // can be done solely with calculations relative to the stack pointer
+ // (%esp). The return address is recovered from the memory location
+ // above the known sizes of the callee's parameters, saved registers,
+ // and locals. The caller's stack pointer (the value of %esp when
+ // the caller executed CALL) is the location immediately above the
+ // saved return address. The saved value of %ebp to be restored for
+ // the caller is at a known location in the saved-register area of
+ // the stack frame.
+ //
+ // For this type of frame, MSVC 14 (from Visual Studio 8/2005) in
+ // link-time code generation mode (/LTCG and /GL) can generate erroneous
+ // debugging data. The reported size of saved registers can be 0,
+ // which is clearly an error because these frames must, at the very
+ // least, save %ebp. For this reason, in addition to those given above
+ // about the use of .raSearchStart, the stack may need to be scanned
+ // for a better return address and a better frame pointer after the
+ // program string is evaluated.
+ //
+ // %eip_new = *(%esp_old + callee_params + saved_regs + locals)
+ // %ebp_new = *(%esp_old + callee_params + saved_regs - 8)
+ // %esp_new = %esp_old + callee_params + saved_regs + locals + 4
+ program_string = "$eip .raSearchStart ^ = "
+ "$ebp $esp .cbCalleeParams + .cbSavedRegs + 8 - ^ = "
+ "$esp .raSearchStart 4 + =";
+ } else {
+ // The function corresponding to the last frame doesn't use %ebp at
+ // all. The callee frame is located relative to %esp.
+ //
+ // The called procedure's instruction pointer and stack pointer are
+ // recovered in the same way as the case above, except that no
+ // frame pointer (%ebp) is used at all, so it is not saved anywhere
+ // in the callee's stack frame and does not need to be recovered.
+ // Because %ebp wasn't used in the callee, whatever value it has
+ // is the value that it had in the caller, so it can be carried
+ // straight through without bringing its validity into question.
+ //
+ // Because of the use of .raSearchStart, the stack will possibly be
+ // examined to locate a better return address after program string
+ // evaluation. The stack will not be examined to locate a saved
+ // %ebp value, because these frames do not save (or use) %ebp.
+ //
+ // We also propagate %ebx through, as it is commonly unmodifed after
+ // calling simple forwarding functions in ntdll (that are this non-EBP
+ // using type). It's not clear that this is always correct, but it is
+ // important for some functions to get a correct walk.
+ //
+ // %eip_new = *(%esp_old + callee_params + saved_regs + locals)
+ // %esp_new = %esp_old + callee_params + saved_regs + locals + 4
+ // %ebp_new = %ebp_old
+ // %ebx_new = %ebx_old // If available.
+ program_string = "$eip .raSearchStart ^ = "
+ "$esp .raSearchStart 4 + =";
+ if (last_frame->context_validity & StackFrameX86::CONTEXT_VALID_EBX)
+ program_string += " $ebx $ebx =";
+ recover_ebp = false;
+ }
+
+ // Check for alignment operators in the program string. If alignment
+ // operators are found, then current %ebp must be valid and it is the only
+ // reliable data point that can be used for getting to the previous frame.
+ // E.g. the .raSearchStart calculation (above) is based on %esp and since
+ // %esp was aligned in the current frame (which is a lossy operation) the
+ // calculated value of .raSearchStart cannot be correct and should not be
+ // used. Instead .raSearchStart must be calculated based on %ebp.
+ // The code that follows assumes that .raSearchStart is supposed to point
+ // at the saved return address (ebp + 4).
+ // For some more details on this topic, take a look at the following thread:
+ // https://groups.google.com/forum/#!topic/google-breakpad-dev/ZP1FA9B1JjM
+ if ((StackFrameX86::CONTEXT_VALID_EBP & last_frame->context_validity) != 0 &&
+ program_string.find('@') != string::npos) {
+ raSearchStart = last_frame->context.ebp + 4;
+ }
+
+ // The difference between raSearch and raSearchStart is unknown,
+ // but making them the same seems to work well in practice.
+ dictionary[".raSearchStart"] = raSearchStart;
+ dictionary[".raSearch"] = raSearchStart;
+
+ // Now crank it out, making sure that the program string set at least the
+ // two required variables.
+ PostfixEvaluator<uint32_t> evaluator =
+ PostfixEvaluator<uint32_t>(&dictionary, memory_);
+ PostfixEvaluator<uint32_t>::DictionaryValidityType dictionary_validity;
+ if (!evaluator.Evaluate(program_string, &dictionary_validity) ||
+ dictionary_validity.find("$eip") == dictionary_validity.end() ||
+ dictionary_validity.find("$esp") == dictionary_validity.end()) {
+ // Program string evaluation failed. It may be that %eip is not somewhere
+ // with stack frame info, and %ebp is pointing to non-stack memory, so
+ // our evaluation couldn't succeed. We'll scan the stack for a return
+ // address. This can happen if the stack is in a module for which
+ // we don't have symbols, and that module is compiled without a
+ // frame pointer.
+ uint32_t location_start = last_frame->context.esp;
+ uint32_t location, eip;
+ if (!stack_scan_allowed
+ || !ScanForReturnAddress(location_start, &location, &eip,
+ frames.size() == 1 /* is_context_frame */)) {
+ // if we can't find an instruction pointer even with stack scanning,
+ // give up.
+ return NULL;
+ }
+
+ // This seems like a reasonable return address. Since program string
+ // evaluation failed, use it and set %esp to the location above the
+ // one where the return address was found.
+ dictionary["$eip"] = eip;
+ dictionary["$esp"] = location + 4;
+ trust = StackFrame::FRAME_TRUST_SCAN;
+ }
+
+ // Since this stack frame did not use %ebp in a traditional way,
+ // locating the return address isn't entirely deterministic. In that
+ // case, the stack can be scanned to locate the return address.
+ //
+ // However, if program string evaluation resulted in both %eip and
+ // %ebp values of 0, trust that the end of the stack has been
+ // reached and don't scan for anything else.
+ if (dictionary["$eip"] != 0 || dictionary["$ebp"] != 0) {
+ int offset = 0;
+
+ // This scan can only be done if a CodeModules object is available, to
+ // check that candidate return addresses are in fact inside a module.
+ //
+ // TODO(mmentovai): This ignores dynamically-generated code. One possible
+ // solution is to check the minidump's memory map to see if the candidate
+ // %eip value comes from a mapped executable page, although this would
+ // require dumps that contain MINIDUMP_MEMORY_INFO, which the Breakpad
+ // client doesn't currently write (it would need to call MiniDumpWriteDump
+ // with the MiniDumpWithFullMemoryInfo type bit set). Even given this
+ // ability, older OSes (pre-XP SP2) and CPUs (pre-P4) don't enforce
+ // an independent execute privilege on memory pages.
+
+ uint32_t eip = dictionary["$eip"];
+ if (modules_ && !modules_->GetModuleForAddress(eip)) {
+ // The instruction pointer at .raSearchStart was invalid, so start
+ // looking one 32-bit word above that location.
+ uint32_t location_start = dictionary[".raSearchStart"] + 4;
+ uint32_t location;
+ if (stack_scan_allowed
+ && ScanForReturnAddress(location_start, &location, &eip,
+ frames.size() == 1 /* is_context_frame */)) {
+ // This is a better return address that what program string
+ // evaluation found. Use it, and set %esp to the location above the
+ // one where the return address was found.
+ dictionary["$eip"] = eip;
+ dictionary["$esp"] = location + 4;
+ offset = location - location_start;
+ trust = StackFrame::FRAME_TRUST_CFI_SCAN;
+ }
+ }
+
+ if (recover_ebp) {
+ // When trying to recover the previous value of the frame pointer (%ebp),
+ // start looking at the lowest possible address in the saved-register
+ // area, and look at the entire saved register area, increased by the
+ // size of |offset| to account for additional data that may be on the
+ // stack. The scan is performed from the highest possible address to
+ // the lowest, because the expectation is that the function's prolog
+ // would have saved %ebp early.
+ uint32_t ebp = dictionary["$ebp"];
+
+ // When a scan for return address is used, it is possible to skip one or
+ // more frames (when return address is not in a known module). One
+ // indication for skipped frames is when the value of %ebp is lower than
+ // the location of the return address on the stack
+ bool has_skipped_frames =
+ (trust != StackFrame::FRAME_TRUST_CFI && ebp <= raSearchStart + offset);
+
+ uint32_t value; // throwaway variable to check pointer validity
+ if (has_skipped_frames || !memory_->GetMemoryAtAddress(ebp, &value)) {
+ int fp_search_bytes = last_frame_info->saved_register_size + offset;
+ uint32_t location_end = last_frame->context.esp +
+ last_frame_callee_parameter_size;
+
+ for (uint32_t location = location_end + fp_search_bytes;
+ location >= location_end;
+ location -= 4) {
+ if (!memory_->GetMemoryAtAddress(location, &ebp))
+ break;
+
+ if (memory_->GetMemoryAtAddress(ebp, &value)) {
+ // The candidate value is a pointer to the same memory region
+ // (the stack). Prefer it as a recovered %ebp result.
+ dictionary["$ebp"] = ebp;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ // Create a new stack frame (ownership will be transferred to the caller)
+ // and fill it in.
+ StackFrameX86* frame = new StackFrameX86();
+
+ frame->trust = trust;
+ frame->context = last_frame->context;
+ frame->context.eip = dictionary["$eip"];
+ frame->context.esp = dictionary["$esp"];
+ frame->context.ebp = dictionary["$ebp"];
+ frame->context_validity = StackFrameX86::CONTEXT_VALID_EIP |
+ StackFrameX86::CONTEXT_VALID_ESP |
+ StackFrameX86::CONTEXT_VALID_EBP;
+
+ // These are nonvolatile (callee-save) registers, and the program string
+ // may have filled them in.
+ if (dictionary_validity.find("$ebx") != dictionary_validity.end()) {
+ frame->context.ebx = dictionary["$ebx"];
+ frame->context_validity |= StackFrameX86::CONTEXT_VALID_EBX;
+ }
+ if (dictionary_validity.find("$esi") != dictionary_validity.end()) {
+ frame->context.esi = dictionary["$esi"];
+ frame->context_validity |= StackFrameX86::CONTEXT_VALID_ESI;
+ }
+ if (dictionary_validity.find("$edi") != dictionary_validity.end()) {
+ frame->context.edi = dictionary["$edi"];
+ frame->context_validity |= StackFrameX86::CONTEXT_VALID_EDI;
+ }
+
+ return frame;
+}
+
+StackFrameX86* StackwalkerX86::GetCallerByCFIFrameInfo(
+ const vector<StackFrame*> &frames,
+ CFIFrameInfo* cfi_frame_info) {
+ StackFrameX86* last_frame = static_cast<StackFrameX86*>(frames.back());
+ last_frame->cfi_frame_info = cfi_frame_info;
+
+ scoped_ptr<StackFrameX86> frame(new StackFrameX86());
+ if (!cfi_walker_
+ .FindCallerRegisters(*memory_, *cfi_frame_info,
+ last_frame->context, last_frame->context_validity,
+ &frame->context, &frame->context_validity))
+ return NULL;
+
+ // Make sure we recovered all the essentials.
+ static const int essentials = (StackFrameX86::CONTEXT_VALID_EIP
+ | StackFrameX86::CONTEXT_VALID_ESP
+ | StackFrameX86::CONTEXT_VALID_EBP);
+ if ((frame->context_validity & essentials) != essentials)
+ return NULL;
+
+ frame->trust = StackFrame::FRAME_TRUST_CFI;
+
+ return frame.release();
+}
+
+StackFrameX86* StackwalkerX86::GetCallerByEBPAtBase(
+ const vector<StackFrame*> &frames,
+ bool stack_scan_allowed) {
+ StackFrame::FrameTrust trust;
+ StackFrameX86* last_frame = static_cast<StackFrameX86*>(frames.back());
+ uint32_t last_esp = last_frame->context.esp;
+ uint32_t last_ebp = last_frame->context.ebp;
+
+ // Assume that the standard %ebp-using x86 calling convention is in
+ // use.
+ //
+ // The typical x86 calling convention, when frame pointers are present,
+ // is for the calling procedure to use CALL, which pushes the return
+ // address onto the stack and sets the instruction pointer (%eip) to
+ // the entry point of the called routine. The called routine then
+ // PUSHes the calling routine's frame pointer (%ebp) onto the stack
+ // before copying the stack pointer (%esp) to the frame pointer (%ebp).
+ // Therefore, the calling procedure's frame pointer is always available
+ // by dereferencing the called procedure's frame pointer, and the return
+ // address is always available at the memory location immediately above
+ // the address pointed to by the called procedure's frame pointer. The
+ // calling procedure's stack pointer (%esp) is 8 higher than the value
+ // of the called procedure's frame pointer at the time the calling
+ // procedure made the CALL: 4 bytes for the return address pushed by the
+ // CALL itself, and 4 bytes for the callee's PUSH of the caller's frame
+ // pointer.
+ //
+ // %eip_new = *(%ebp_old + 4)
+ // %esp_new = %ebp_old + 8
+ // %ebp_new = *(%ebp_old)
+
+ uint32_t caller_eip, caller_esp, caller_ebp;
+
+ if (memory_->GetMemoryAtAddress(last_ebp + 4, &caller_eip) &&
+ memory_->GetMemoryAtAddress(last_ebp, &caller_ebp)) {
+ caller_esp = last_ebp + 8;
+ trust = StackFrame::FRAME_TRUST_FP;
+ } else {
+ // We couldn't read the memory %ebp refers to. It may be that %ebp
+ // is pointing to non-stack memory. We'll scan the stack for a
+ // return address. This can happen if last_frame is executing code
+ // for a module for which we don't have symbols, and that module
+ // is compiled without a frame pointer.
+ if (!stack_scan_allowed
+ || !ScanForReturnAddress(last_esp, &caller_esp, &caller_eip,
+ frames.size() == 1 /* is_context_frame */)) {
+ // if we can't find an instruction pointer even with stack scanning,
+ // give up.
+ return NULL;
+ }
+
+ // ScanForReturnAddress found a reasonable return address. Advance %esp to
+ // the location immediately above the one where the return address was
+ // found.
+ caller_esp += 4;
+ // Try to restore the %ebp chain. The caller %ebp should be stored at a
+ // location immediately below the one where the return address was found.
+ // A valid caller %ebp must be greater than the address where it is stored
+ // and the gap between the two adjacent frames should be reasonable.
+ uint32_t restored_ebp_chain = caller_esp - 8;
+ if (!memory_->GetMemoryAtAddress(restored_ebp_chain, &caller_ebp) ||
+ caller_ebp <= restored_ebp_chain ||
+ caller_ebp - restored_ebp_chain > kMaxReasonableGapBetweenFrames) {
+ // The restored %ebp chain doesn't appear to be valid.
+ // Assume that %ebp is unchanged.
+ caller_ebp = last_ebp;
+ }
+
+ trust = StackFrame::FRAME_TRUST_SCAN;
+ }
+
+ // Create a new stack frame (ownership will be transferred to the caller)
+ // and fill it in.
+ StackFrameX86* frame = new StackFrameX86();
+
+ frame->trust = trust;
+ frame->context = last_frame->context;
+ frame->context.eip = caller_eip;
+ frame->context.esp = caller_esp;
+ frame->context.ebp = caller_ebp;
+ frame->context_validity = StackFrameX86::CONTEXT_VALID_EIP |
+ StackFrameX86::CONTEXT_VALID_ESP |
+ StackFrameX86::CONTEXT_VALID_EBP;
+
+ return frame;
+}
+
+StackFrame* StackwalkerX86::GetCallerFrame(const CallStack* stack,
+ bool stack_scan_allowed) {
+ if (!memory_ || !stack) {
+ BPLOG(ERROR) << "Can't get caller frame without memory or stack";
+ return NULL;
+ }
+
+ const vector<StackFrame*> &frames = *stack->frames();
+ StackFrameX86* last_frame = static_cast<StackFrameX86*>(frames.back());
+ scoped_ptr<StackFrameX86> new_frame;
+
+ // If the resolver has Windows stack walking information, use that.
+ WindowsFrameInfo* windows_frame_info
+ = frame_symbolizer_->FindWindowsFrameInfo(last_frame);
+ if (windows_frame_info)
+ new_frame.reset(GetCallerByWindowsFrameInfo(frames, windows_frame_info,
+ stack_scan_allowed));
+
+ // If the resolver has DWARF CFI information, use that.
+ if (!new_frame.get()) {
+ CFIFrameInfo* cfi_frame_info =
+ frame_symbolizer_->FindCFIFrameInfo(last_frame);
+ if (cfi_frame_info)
+ new_frame.reset(GetCallerByCFIFrameInfo(frames, cfi_frame_info));
+ }
+
+ // Otherwise, hope that the program was using a traditional frame structure.
+ if (!new_frame.get())
+ new_frame.reset(GetCallerByEBPAtBase(frames, stack_scan_allowed));
+
+ // If nothing worked, tell the caller.
+ if (!new_frame.get())
+ return NULL;
+
+ // Should we terminate the stack walk? (end-of-stack or broken invariant)
+ if (TerminateWalk(new_frame->context.eip,
+ new_frame->context.esp,
+ last_frame->context.esp,
+ frames.size() == 1)) {
+ return NULL;
+ }
+
+ // new_frame->context.eip is the return address, which is the instruction
+ // after the CALL that caused us to arrive at the callee. Set
+ // new_frame->instruction to one less than that, so it points within the
+ // CALL instruction. See StackFrame::instruction for details, and
+ // StackFrameAMD64::ReturnAddress.
+ new_frame->instruction = new_frame->context.eip - 1;
+
+ return new_frame.release();
+}
+
+} // namespace google_breakpad
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_x86.h b/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_x86.h
new file mode 100644
index 0000000000..0659a13bf4
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_x86.h
@@ -0,0 +1,117 @@
+// -*- 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.
+
+// stackwalker_x86.h: x86-specific stackwalker.
+//
+// Provides stack frames given x86 register context and a memory region
+// corresponding to an x86 stack.
+//
+// Author: Mark Mentovai
+
+
+#ifndef PROCESSOR_STACKWALKER_X86_H__
+#define PROCESSOR_STACKWALKER_X86_H__
+
+#include <vector>
+
+#include "google_breakpad/common/breakpad_types.h"
+#include "google_breakpad/common/minidump_format.h"
+#include "google_breakpad/processor/stackwalker.h"
+#include "google_breakpad/processor/stack_frame_cpu.h"
+#include "processor/cfi_frame_info.h"
+
+namespace google_breakpad {
+
+class CodeModules;
+
+
+class StackwalkerX86 : public Stackwalker {
+ public:
+ // context is an x86 context object that gives access to x86-specific
+ // register state corresponding to the innermost called frame to be
+ // included in the stack. The other arguments are passed directly through
+ // to the base Stackwalker constructor.
+ StackwalkerX86(const SystemInfo* system_info,
+ const MDRawContextX86* context,
+ MemoryRegion* memory,
+ const CodeModules* modules,
+ StackFrameSymbolizer* frame_symbolizer);
+
+ private:
+ // A STACK CFI-driven frame walker for the X86.
+ typedef SimpleCFIWalker<uint32_t, MDRawContextX86> CFIWalker;
+
+ // Implementation of Stackwalker, using x86 context (%ebp, %esp, %eip) and
+ // stack conventions (saved %ebp at [%ebp], saved %eip at 4[%ebp], or
+ // alternate conventions as guided by any WindowsFrameInfo available for the
+ // code in question.).
+ virtual StackFrame* GetContextFrame();
+ virtual StackFrame* GetCallerFrame(const CallStack* stack,
+ bool stack_scan_allowed);
+
+ // Use windows_frame_info (derived from STACK WIN and FUNC records)
+ // to construct the frame that called frames.back(). The caller
+ // takes ownership of the returned frame. Return NULL on failure.
+ StackFrameX86* GetCallerByWindowsFrameInfo(
+ const vector<StackFrame*> &frames,
+ WindowsFrameInfo* windows_frame_info,
+ bool stack_scan_allowed);
+
+ // Use cfi_frame_info (derived from STACK CFI records) to construct
+ // the frame that called frames.back(). The caller takes ownership
+ // of the returned frame. Return NULL on failure.
+ StackFrameX86* GetCallerByCFIFrameInfo(const vector<StackFrame*> &frames,
+ CFIFrameInfo* cfi_frame_info);
+
+ // Assuming a traditional frame layout --- where the caller's %ebp
+ // has been pushed just after the return address and the callee's
+ // %ebp points to the saved %ebp --- construct the frame that called
+ // frames.back(). The caller takes ownership of the returned frame.
+ // Return NULL on failure.
+ StackFrameX86* GetCallerByEBPAtBase(const vector<StackFrame*> &frames,
+ bool stack_scan_allowed);
+
+ // Stores the CPU context corresponding to the innermost stack frame to
+ // be returned by GetContextFrame.
+ const MDRawContextX86* context_;
+
+ // Our register map, for cfi_walker_.
+ static const CFIWalker::RegisterSet cfi_register_map_[];
+
+ // Our CFI frame walker.
+ const CFIWalker cfi_walker_;
+};
+
+
+} // namespace google_breakpad
+
+
+#endif // PROCESSOR_STACKWALKER_X86_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_x86_unittest.cc b/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_x86_unittest.cc
new file mode 100644
index 0000000000..359f1c863b
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_x86_unittest.cc
@@ -0,0 +1,2266 @@
+// 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>
+
+// stackwalker_x86_unittest.cc: Unit tests for StackwalkerX86 class.
+
+#include <string>
+#include <vector>
+
+#include "breakpad_googletest_includes.h"
+#include "common/test_assembler.h"
+#include "common/using_std_string.h"
+#include "google_breakpad/common/minidump_format.h"
+#include "google_breakpad/processor/basic_source_line_resolver.h"
+#include "google_breakpad/processor/call_stack.h"
+#include "google_breakpad/processor/code_module.h"
+#include "google_breakpad/processor/source_line_resolver_interface.h"
+#include "google_breakpad/processor/stack_frame_cpu.h"
+#include "processor/stackwalker_unittest_utils.h"
+#include "processor/stackwalker_x86.h"
+#include "processor/windows_frame_info.h"
+
+using google_breakpad::BasicSourceLineResolver;
+using google_breakpad::CallStack;
+using google_breakpad::CodeModule;
+using google_breakpad::StackFrameSymbolizer;
+using google_breakpad::StackFrame;
+using google_breakpad::StackFrameX86;
+using google_breakpad::Stackwalker;
+using google_breakpad::StackwalkerX86;
+using google_breakpad::SystemInfo;
+using google_breakpad::WindowsFrameInfo;
+using google_breakpad::test_assembler::kLittleEndian;
+using google_breakpad::test_assembler::Label;
+using google_breakpad::test_assembler::Section;
+using std::vector;
+using testing::_;
+using testing::AnyNumber;
+using testing::DoAll;
+using testing::Return;
+using testing::SetArgumentPointee;
+using testing::Test;
+
+class StackwalkerX86Fixture {
+ public:
+ StackwalkerX86Fixture()
+ : stack_section(kLittleEndian),
+ // Give the two modules reasonable standard locations and names
+ // for tests to play with.
+ module1(0x40000000, 0x10000, "module1", "version1"),
+ module2(0x50000000, 0x10000, "module2", "version2"),
+ module3(0x771d0000, 0x180000, "module3", "version3"),
+ module4(0x75f90000, 0x46000, "module4", "version4"),
+ module5(0x75730000, 0x110000, "module5", "version5"),
+ module6(0x647f0000, 0x1ba8000, "module6", "version6") {
+ // Identify the system as a Linux system.
+ system_info.os = "Linux";
+ system_info.os_short = "linux";
+ system_info.os_version = "Salacious Skink";
+ system_info.cpu = "x86";
+ system_info.cpu_info = "";
+
+ // Put distinctive values in the raw CPU context.
+ BrandContext(&raw_context);
+
+ // Create some modules with some stock debugging information.
+ modules.Add(&module1);
+ modules.Add(&module2);
+ modules.Add(&module3);
+ modules.Add(&module4);
+ modules.Add(&module5);
+ modules.Add(&module6);
+
+ // By default, none of the modules have symbol info; call
+ // SetModuleSymbols to override this.
+ EXPECT_CALL(supplier, GetCStringSymbolData(_, _, _, _, _))
+ .WillRepeatedly(Return(MockSymbolSupplier::NOT_FOUND));
+
+ // Avoid GMOCK WARNING "Uninteresting mock function call - returning
+ // directly" for FreeSymbolData().
+ EXPECT_CALL(supplier, FreeSymbolData(_)).Times(AnyNumber());
+
+ // Reset max_frames_scanned since it's static.
+ Stackwalker::set_max_frames_scanned(1024);
+ }
+
+ // Set the Breakpad symbol information that supplier should return for
+ // MODULE to INFO.
+ void SetModuleSymbols(MockCodeModule *module, const string &info) {
+ size_t buffer_size;
+ char *buffer = supplier.CopySymbolDataAndOwnTheCopy(info, &buffer_size);
+ EXPECT_CALL(supplier, GetCStringSymbolData(module, &system_info, _, _, _))
+ .WillRepeatedly(DoAll(SetArgumentPointee<3>(buffer),
+ SetArgumentPointee<4>(buffer_size),
+ Return(MockSymbolSupplier::FOUND)));
+ }
+
+ // Populate stack_region with the contents of stack_section. Use
+ // stack_section.start() as the region's starting address.
+ void RegionFromSection() {
+ string contents;
+ ASSERT_TRUE(stack_section.GetContents(&contents));
+ stack_region.Init(stack_section.start().Value(), contents);
+ }
+
+ // Fill RAW_CONTEXT with pseudo-random data, for round-trip checking.
+ void BrandContext(MDRawContextX86 *raw_context) {
+ uint8_t x = 173;
+ for (size_t i = 0; i < sizeof(*raw_context); i++)
+ reinterpret_cast<uint8_t *>(raw_context)[i] = (x += 17);
+ }
+
+ SystemInfo system_info;
+ MDRawContextX86 raw_context;
+ Section stack_section;
+ MockMemoryRegion stack_region;
+ MockCodeModule module1;
+ MockCodeModule module2;
+ MockCodeModule module3;
+ MockCodeModule module4;
+ MockCodeModule module5;
+ MockCodeModule module6;
+ MockCodeModules modules;
+ MockSymbolSupplier supplier;
+ BasicSourceLineResolver resolver;
+ CallStack call_stack;
+ const vector<StackFrame *> *frames;
+};
+
+class SanityCheck: public StackwalkerX86Fixture, public Test { };
+
+TEST_F(SanityCheck, NoResolver) {
+ stack_section.start() = 0x80000000;
+ stack_section.D32(0).D32(0); // end-of-stack marker
+ RegionFromSection();
+ raw_context.eip = 0x40000200;
+ raw_context.ebp = 0x80000000;
+
+ StackFrameSymbolizer frame_symbolizer(NULL, NULL);
+ StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules,
+ &frame_symbolizer);
+ // This should succeed, even without a resolver or supplier.
+ vector<const CodeModule*> modules_without_symbols;
+ vector<const CodeModule*> modules_with_corrupt_symbols;
+ ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
+ &modules_with_corrupt_symbols));
+ ASSERT_EQ(1U, modules_without_symbols.size());
+ ASSERT_EQ("module1", modules_without_symbols[0]->debug_file());
+ ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
+ frames = call_stack.frames();
+ StackFrameX86 *frame = static_cast<StackFrameX86 *>(frames->at(0));
+ // Check that the values from the original raw context made it
+ // through to the context in the stack frame.
+ EXPECT_EQ(0, memcmp(&raw_context, &frame->context, sizeof(raw_context)));
+}
+
+class GetContextFrame: public StackwalkerX86Fixture, public Test { };
+
+TEST_F(GetContextFrame, Simple) {
+ stack_section.start() = 0x80000000;
+ stack_section.D32(0).D32(0); // end-of-stack marker
+ RegionFromSection();
+ raw_context.eip = 0x40000200;
+ raw_context.ebp = 0x80000000;
+
+ StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
+ StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules,
+ &frame_symbolizer);
+ vector<const CodeModule*> modules_without_symbols;
+ vector<const CodeModule*> modules_with_corrupt_symbols;
+ ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
+ &modules_with_corrupt_symbols));
+ ASSERT_EQ(1U, modules_without_symbols.size());
+ ASSERT_EQ("module1", modules_without_symbols[0]->debug_file());
+ ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
+ frames = call_stack.frames();
+ StackFrameX86 *frame = static_cast<StackFrameX86 *>(frames->at(0));
+ // Check that the values from the original raw context made it
+ // through to the context in the stack frame.
+ EXPECT_EQ(0, memcmp(&raw_context, &frame->context, sizeof(raw_context)));
+}
+
+// The stackwalker should be able to produce the context frame even
+// without stack memory present.
+TEST_F(GetContextFrame, NoStackMemory) {
+ raw_context.eip = 0x40000200;
+ raw_context.ebp = 0x80000000;
+
+ StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
+ StackwalkerX86 walker(&system_info, &raw_context, NULL, &modules,
+ &frame_symbolizer);
+ vector<const CodeModule*> modules_without_symbols;
+ vector<const CodeModule*> modules_with_corrupt_symbols;
+ ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
+ &modules_with_corrupt_symbols));
+ ASSERT_EQ(1U, modules_without_symbols.size());
+ ASSERT_EQ("module1", modules_without_symbols[0]->debug_file());
+ ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
+ frames = call_stack.frames();
+ StackFrameX86 *frame = static_cast<StackFrameX86 *>(frames->at(0));
+ // Check that the values from the original raw context made it
+ // through to the context in the stack frame.
+ EXPECT_EQ(0, memcmp(&raw_context, &frame->context, sizeof(raw_context)));
+}
+
+class GetCallerFrame: public StackwalkerX86Fixture, public Test {
+ protected:
+ void IPAddressIsNotInKnownModuleTestImpl(bool has_corrupt_symbols);
+};
+
+// Walk a traditional frame. A traditional frame saves the caller's
+// %ebp just below the return address, and has its own %ebp pointing
+// at the saved %ebp.
+TEST_F(GetCallerFrame, Traditional) {
+ stack_section.start() = 0x80000000;
+ Label frame0_ebp, frame1_ebp;
+ stack_section
+ .Append(12, 0) // frame 0: space
+ .Mark(&frame0_ebp) // frame 0 %ebp points here
+ .D32(frame1_ebp) // frame 0: saved %ebp
+ .D32(0x40008679) // frame 0: return address
+ .Append(8, 0) // frame 1: space
+ .Mark(&frame1_ebp) // frame 1 %ebp points here
+ .D32(0) // frame 1: saved %ebp (stack end)
+ .D32(0); // frame 1: return address (stack end)
+ RegionFromSection();
+ raw_context.eip = 0x4000c7a5;
+ raw_context.esp = stack_section.start().Value();
+ raw_context.ebp = frame0_ebp.Value();
+
+ StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
+ StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules,
+ &frame_symbolizer);
+ vector<const CodeModule*> modules_without_symbols;
+ vector<const CodeModule*> modules_with_corrupt_symbols;
+ ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
+ &modules_with_corrupt_symbols));
+ ASSERT_EQ(1U, modules_without_symbols.size());
+ ASSERT_EQ("module1", modules_without_symbols[0]->debug_file());
+ ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
+ frames = call_stack.frames();
+ ASSERT_EQ(2U, frames->size());
+
+ { // To avoid reusing locals by mistake
+ StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
+ EXPECT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity);
+ EXPECT_EQ(0x4000c7a5U, frame0->instruction);
+ EXPECT_EQ(0x4000c7a5U, frame0->context.eip);
+ EXPECT_EQ(frame0_ebp.Value(), frame0->context.ebp);
+ EXPECT_EQ(NULL, frame0->windows_frame_info);
+ }
+
+ { // To avoid reusing locals by mistake
+ StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_FP, frame1->trust);
+ ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP
+ | StackFrameX86::CONTEXT_VALID_ESP
+ | StackFrameX86::CONTEXT_VALID_EBP),
+ frame1->context_validity);
+ EXPECT_EQ(0x40008679U, frame1->instruction + 1);
+ EXPECT_EQ(0x40008679U, frame1->context.eip);
+ EXPECT_EQ(frame1_ebp.Value(), frame1->context.ebp);
+ EXPECT_EQ(NULL, frame1->windows_frame_info);
+ }
+}
+
+// Walk a traditional frame, but use a bogus %ebp value, forcing a scan
+// of the stack for something that looks like a return address.
+TEST_F(GetCallerFrame, TraditionalScan) {
+ stack_section.start() = 0x80000000;
+ Label frame1_ebp;
+ Label frame1_esp;
+ stack_section
+ // frame 0
+ .D32(0xf065dc76) // locals area:
+ .D32(0x46ee2167) // garbage that doesn't look like
+ .D32(0xbab023ec) // a return address
+ .D32(frame1_ebp) // saved %ebp (%ebp fails to point here, forcing scan)
+ .D32(0x4000129d) // return address
+ // frame 1
+ .Mark(&frame1_esp)
+ .Append(8, 0) // space
+ .Mark(&frame1_ebp) // %ebp points here
+ .D32(0) // saved %ebp (stack end)
+ .D32(0); // return address (stack end)
+
+ RegionFromSection();
+ raw_context.eip = 0x4000f49d;
+ raw_context.esp = stack_section.start().Value();
+ // Make the frame pointer bogus, to make the stackwalker scan the stack
+ // for something that looks like a return address.
+ raw_context.ebp = 0xd43eed6e;
+
+ StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
+ StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules,
+ &frame_symbolizer);
+ vector<const CodeModule*> modules_without_symbols;
+ vector<const CodeModule*> modules_with_corrupt_symbols;
+ ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
+ &modules_with_corrupt_symbols));
+ ASSERT_EQ(1U, modules_without_symbols.size());
+ ASSERT_EQ("module1", modules_without_symbols[0]->debug_file());
+ ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
+ frames = call_stack.frames();
+ ASSERT_EQ(2U, frames->size());
+
+ { // To avoid reusing locals by mistake
+ StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
+ ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity);
+ EXPECT_EQ(0x4000f49dU, frame0->instruction);
+ EXPECT_EQ(0x4000f49dU, frame0->context.eip);
+ EXPECT_EQ(stack_section.start().Value(), frame0->context.esp);
+ EXPECT_EQ(0xd43eed6eU, frame0->context.ebp);
+ EXPECT_EQ(NULL, frame0->windows_frame_info);
+ }
+
+ { // To avoid reusing locals by mistake
+ StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust);
+ ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP
+ | StackFrameX86::CONTEXT_VALID_ESP
+ | StackFrameX86::CONTEXT_VALID_EBP),
+ frame1->context_validity);
+ EXPECT_EQ(0x4000129dU, frame1->instruction + 1);
+ EXPECT_EQ(0x4000129dU, frame1->context.eip);
+ EXPECT_EQ(frame1_esp.Value(), frame1->context.esp);
+ EXPECT_EQ(frame1_ebp.Value(), frame1->context.ebp);
+ EXPECT_EQ(NULL, frame1->windows_frame_info);
+ }
+}
+
+// Force scanning for a return address a long way down the stack
+TEST_F(GetCallerFrame, TraditionalScanLongWay) {
+ stack_section.start() = 0x80000000;
+ Label frame1_ebp;
+ Label frame1_esp;
+ stack_section
+ // frame 0
+ .D32(0xf065dc76) // locals area:
+ .D32(0x46ee2167) // garbage that doesn't look like
+ .D32(0xbab023ec) // a return address
+ .Append(20 * 4, 0) // a bunch of space
+ .D32(frame1_ebp) // saved %ebp (%ebp fails to point here, forcing scan)
+ .D32(0x4000129d) // return address
+ // frame 1
+ .Mark(&frame1_esp)
+ .Append(8, 0) // space
+ .Mark(&frame1_ebp) // %ebp points here
+ .D32(0) // saved %ebp (stack end)
+ .D32(0); // return address (stack end)
+
+ RegionFromSection();
+ raw_context.eip = 0x4000f49d;
+ raw_context.esp = stack_section.start().Value();
+ // Make the frame pointer bogus, to make the stackwalker scan the stack
+ // for something that looks like a return address.
+ raw_context.ebp = 0xd43eed6e;
+
+ StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
+ StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules,
+ &frame_symbolizer);
+ vector<const CodeModule*> modules_without_symbols;
+ vector<const CodeModule*> modules_with_corrupt_symbols;
+ ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
+ &modules_with_corrupt_symbols));
+ ASSERT_EQ(1U, modules_without_symbols.size());
+ ASSERT_EQ("module1", modules_without_symbols[0]->debug_file());
+ ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
+ frames = call_stack.frames();
+ ASSERT_EQ(2U, frames->size());
+
+ { // To avoid reusing locals by mistake
+ StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
+ ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity);
+ EXPECT_EQ(0x4000f49dU, frame0->instruction);
+ EXPECT_EQ(0x4000f49dU, frame0->context.eip);
+ EXPECT_EQ(stack_section.start().Value(), frame0->context.esp);
+ EXPECT_EQ(0xd43eed6eU, frame0->context.ebp);
+ EXPECT_EQ(NULL, frame0->windows_frame_info);
+ }
+
+ { // To avoid reusing locals by mistake
+ StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust);
+ ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP
+ | StackFrameX86::CONTEXT_VALID_ESP
+ | StackFrameX86::CONTEXT_VALID_EBP),
+ frame1->context_validity);
+ EXPECT_EQ(0x4000129dU, frame1->instruction + 1);
+ EXPECT_EQ(0x4000129dU, frame1->context.eip);
+ EXPECT_EQ(frame1_esp.Value(), frame1->context.esp);
+ EXPECT_EQ(frame1_ebp.Value(), frame1->context.ebp);
+ EXPECT_EQ(NULL, frame1->windows_frame_info);
+ }
+}
+
+// Test that set_max_frames_scanned prevents using stack scanning
+// to find caller frames.
+TEST_F(GetCallerFrame, ScanningNotAllowed) {
+ stack_section.start() = 0x80000000;
+ Label frame1_ebp;
+ stack_section
+ // frame 0
+ .D32(0xf065dc76) // locals area:
+ .D32(0x46ee2167) // garbage that doesn't look like
+ .D32(0xbab023ec) // a return address
+ .D32(frame1_ebp) // saved %ebp (%ebp fails to point here, forcing scan)
+ .D32(0x4000129d) // return address
+ // frame 1
+ .Append(8, 0) // space
+ .Mark(&frame1_ebp) // %ebp points here
+ .D32(0) // saved %ebp (stack end)
+ .D32(0); // return address (stack end)
+
+ RegionFromSection();
+ raw_context.eip = 0x4000f49d;
+ raw_context.esp = stack_section.start().Value();
+ // Make the frame pointer bogus, to make the stackwalker scan the stack
+ // for something that looks like a return address.
+ raw_context.ebp = 0xd43eed6e;
+
+ StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
+ StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules,
+ &frame_symbolizer);
+ Stackwalker::set_max_frames_scanned(0);
+
+ vector<const CodeModule*> modules_without_symbols;
+ vector<const CodeModule*> modules_with_corrupt_symbols;
+ ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
+ &modules_with_corrupt_symbols));
+ ASSERT_EQ(1U, modules_without_symbols.size());
+ ASSERT_EQ("module1", modules_without_symbols[0]->debug_file());
+ ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
+ frames = call_stack.frames();
+ ASSERT_EQ(1U, frames->size());
+
+ { // To avoid reusing locals by mistake
+ StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
+ ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity);
+ EXPECT_EQ(0x4000f49dU, frame0->instruction);
+ EXPECT_EQ(0x4000f49dU, frame0->context.eip);
+ EXPECT_EQ(stack_section.start().Value(), frame0->context.esp);
+ EXPECT_EQ(0xd43eed6eU, frame0->context.ebp);
+ EXPECT_EQ(NULL, frame0->windows_frame_info);
+ }
+}
+
+// Use Windows frame data (a "STACK WIN 4" record, from a
+// FrameTypeFrameData DIA record) to walk a stack frame.
+TEST_F(GetCallerFrame, WindowsFrameData) {
+ SetModuleSymbols(&module1,
+ "STACK WIN 4 aa85 176 0 0 4 10 4 0 1"
+ " $T2 $esp .cbSavedRegs + ="
+ " $T0 .raSearchStart ="
+ " $eip $T0 ^ ="
+ " $esp $T0 4 + ="
+ " $ebx $T2 4 - ^ ="
+ " $edi $T2 8 - ^ ="
+ " $esi $T2 12 - ^ ="
+ " $ebp $T2 16 - ^ =\n");
+ Label frame1_esp, frame1_ebp;
+ stack_section.start() = 0x80000000;
+ stack_section
+ // frame 0
+ .D32(frame1_ebp) // saved regs: %ebp
+ .D32(0xa7120d1a) // %esi
+ .D32(0x630891be) // %edi
+ .D32(0x9068a878) // %ebx
+ .D32(0xa08ea45f) // locals: unused
+ .D32(0x40001350) // return address
+ // frame 1
+ .Mark(&frame1_esp)
+ .Append(12, 0) // empty space
+ .Mark(&frame1_ebp)
+ .D32(0) // saved %ebp (stack end)
+ .D32(0); // saved %eip (stack end)
+
+ RegionFromSection();
+ raw_context.eip = 0x4000aa85;
+ raw_context.esp = stack_section.start().Value();
+ raw_context.ebp = 0xf052c1de; // should not be needed to walk frame
+
+ StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
+ StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules,
+ &frame_symbolizer);
+ vector<const CodeModule*> modules_without_symbols;
+ vector<const CodeModule*> modules_with_corrupt_symbols;
+ ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
+ &modules_with_corrupt_symbols));
+ ASSERT_EQ(0U, modules_without_symbols.size());
+ ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
+ frames = call_stack.frames();
+ ASSERT_EQ(2U, frames->size());
+
+ { // To avoid reusing locals by mistake
+ StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
+ ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity);
+ EXPECT_EQ(0x4000aa85U, frame0->instruction);
+ EXPECT_EQ(0x4000aa85U, frame0->context.eip);
+ EXPECT_EQ(stack_section.start().Value(), frame0->context.esp);
+ EXPECT_EQ(0xf052c1deU, frame0->context.ebp);
+ EXPECT_TRUE(frame0->windows_frame_info != NULL);
+ }
+
+ { // To avoid reusing locals by mistake
+ StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame1->trust);
+ ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP
+ | StackFrameX86::CONTEXT_VALID_ESP
+ | StackFrameX86::CONTEXT_VALID_EBP
+ | StackFrameX86::CONTEXT_VALID_EBX
+ | StackFrameX86::CONTEXT_VALID_ESI
+ | StackFrameX86::CONTEXT_VALID_EDI),
+ frame1->context_validity);
+ EXPECT_EQ(0x40001350U, frame1->instruction + 1);
+ EXPECT_EQ(0x40001350U, frame1->context.eip);
+ EXPECT_EQ(frame1_esp.Value(), frame1->context.esp);
+ EXPECT_EQ(frame1_ebp.Value(), frame1->context.ebp);
+ EXPECT_EQ(0x9068a878U, frame1->context.ebx);
+ EXPECT_EQ(0xa7120d1aU, frame1->context.esi);
+ EXPECT_EQ(0x630891beU, frame1->context.edi);
+ EXPECT_EQ(NULL, frame1->windows_frame_info);
+ }
+}
+
+// Use Windows frame data (a "STACK WIN 4" record, from a
+// FrameTypeFrameData DIA record) to walk a stack frame where the stack
+// is aligned and we must search
+TEST_F(GetCallerFrame, WindowsFrameDataAligned) {
+ SetModuleSymbols(&module1,
+ "STACK WIN 4 aa85 176 0 0 4 4 8 0 1"
+ " $T1 .raSearch ="
+ " $T0 $T1 4 - 8 @ ="
+ " $ebp $T1 4 - ^ ="
+ " $eip $T1 ^ ="
+ " $esp $T1 4 + =");
+ Label frame0_esp, frame0_ebp;
+ Label frame1_esp, frame1_ebp;
+ stack_section.start() = 0x80000000;
+ stack_section
+ // frame 0
+ .Mark(&frame0_esp)
+ .D32(0x0ffa0ffa) // unused saved register
+ .D32(0xdeaddead) // locals
+ .D32(0xbeefbeef)
+ .D32(0) // 8-byte alignment
+ .Mark(&frame0_ebp)
+ .D32(frame1_ebp) // saved %ebp
+ .D32(0x5000129d) // return address
+ // frame 1
+ .Mark(&frame1_esp)
+ .D32(0x1) // parameter
+ .Mark(&frame1_ebp)
+ .D32(0) // saved %ebp (stack end)
+ .D32(0); // saved %eip (stack end)
+
+ RegionFromSection();
+ raw_context.eip = 0x4000aa85;
+ raw_context.esp = frame0_esp.Value();
+ raw_context.ebp = frame0_ebp.Value();
+
+ StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
+ StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules,
+ &frame_symbolizer);
+ vector<const CodeModule*> modules_without_symbols;
+ vector<const CodeModule*> modules_with_corrupt_symbols;
+ ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
+ &modules_with_corrupt_symbols));
+ ASSERT_EQ(1U, modules_without_symbols.size());
+ ASSERT_EQ("module2", modules_without_symbols[0]->debug_file());
+ ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
+ frames = call_stack.frames();
+ ASSERT_EQ(2U, frames->size());
+
+ { // To avoid reusing locals by mistake
+ StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
+ ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity);
+ EXPECT_EQ(0x4000aa85U, frame0->instruction);
+ EXPECT_EQ(0x4000aa85U, frame0->context.eip);
+ EXPECT_EQ(frame0_esp.Value(), frame0->context.esp);
+ EXPECT_EQ(frame0_ebp.Value(), frame0->context.ebp);
+ EXPECT_TRUE(frame0->windows_frame_info != NULL);
+ }
+
+ { // To avoid reusing locals by mistake
+ StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame1->trust);
+ ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP
+ | StackFrameX86::CONTEXT_VALID_ESP
+ | StackFrameX86::CONTEXT_VALID_EBP),
+ frame1->context_validity);
+ EXPECT_EQ(0x5000129dU, frame1->instruction + 1);
+ EXPECT_EQ(0x5000129dU, frame1->context.eip);
+ EXPECT_EQ(frame1_esp.Value(), frame1->context.esp);
+ EXPECT_EQ(frame1_ebp.Value(), frame1->context.ebp);
+ EXPECT_EQ(NULL, frame1->windows_frame_info);
+ }
+}
+
+// Use Windows frame data (a "STACK WIN 4" record, from a
+// FrameTypeFrameData DIA record) to walk a frame, and depend on the
+// parameter size from the callee as well.
+TEST_F(GetCallerFrame, WindowsFrameDataParameterSize) {
+ SetModuleSymbols(&module1, "FUNC 1000 100 c module1::wheedle\n");
+ SetModuleSymbols(&module2,
+ // Note bogus parameter size in FUNC record; the stack walker
+ // should prefer the STACK WIN record, and see '4' below.
+ "FUNC aa85 176 beef module2::whine\n"
+ "STACK WIN 4 aa85 176 0 0 4 10 4 0 1"
+ " $T2 $esp .cbLocals + .cbSavedRegs + ="
+ " $T0 .raSearchStart ="
+ " $eip $T0 ^ ="
+ " $esp $T0 4 + ="
+ " $ebp $T0 20 - ^ ="
+ " $ebx $T0 8 - ^ =\n");
+ Label frame0_esp, frame0_ebp;
+ Label frame1_esp;
+ Label frame2_esp, frame2_ebp;
+ stack_section.start() = 0x80000000;
+ stack_section
+ // frame 0, in module1::wheedle. Traditional frame.
+ .Mark(&frame0_esp)
+ .Append(16, 0) // frame space
+ .Mark(&frame0_ebp)
+ .D32(0x6fa902e0) // saved %ebp. Not a frame pointer.
+ .D32(0x5000aa95) // return address, in module2::whine
+ // frame 1, in module2::whine. FrameData frame.
+ .Mark(&frame1_esp)
+ .D32(0xbaa0cb7a) // argument 3 passed to module1::wheedle
+ .D32(0xbdc92f9f) // argument 2
+ .D32(0x0b1d8442) // argument 1
+ .D32(frame2_ebp) // saved %ebp
+ .D32(0xb1b90a15) // unused
+ .D32(0xf18e072d) // unused
+ .D32(0x2558c7f3) // saved %ebx
+ .D32(0x0365e25e) // unused
+ .D32(0x2a179e38) // return address; $T0 points here
+ // frame 2, in no module
+ .Mark(&frame2_esp)
+ .Append(12, 0) // empty space
+ .Mark(&frame2_ebp)
+ .D32(0) // saved %ebp (stack end)
+ .D32(0); // saved %eip (stack end)
+
+ RegionFromSection();
+ raw_context.eip = 0x40001004; // in module1::wheedle
+ raw_context.esp = stack_section.start().Value();
+ raw_context.ebp = frame0_ebp.Value();
+
+ StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
+ StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules,
+ &frame_symbolizer);
+ vector<const CodeModule*> modules_without_symbols;
+ vector<const CodeModule*> modules_with_corrupt_symbols;
+ ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
+ &modules_with_corrupt_symbols));
+ ASSERT_EQ(0U, modules_without_symbols.size());
+ ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
+ frames = call_stack.frames();
+ ASSERT_EQ(3U, frames->size());
+
+ { // To avoid reusing locals by mistake
+ StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
+ ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity);
+ EXPECT_EQ(0x40001004U, frame0->instruction);
+ EXPECT_EQ(0x40001004U, frame0->context.eip);
+ EXPECT_EQ(frame0_esp.Value(), frame0->context.esp);
+ EXPECT_EQ(frame0_ebp.Value(), frame0->context.ebp);
+ EXPECT_EQ(&module1, frame0->module);
+ EXPECT_EQ("module1::wheedle", frame0->function_name);
+ EXPECT_EQ(0x40001000U, frame0->function_base);
+ // The FUNC record for module1::wheedle should have produced a
+ // WindowsFrameInfo structure with only the parameter size valid.
+ ASSERT_TRUE(frame0->windows_frame_info != NULL);
+ EXPECT_EQ(WindowsFrameInfo::VALID_PARAMETER_SIZE,
+ frame0->windows_frame_info->valid);
+ EXPECT_EQ(WindowsFrameInfo::STACK_INFO_UNKNOWN,
+ frame0->windows_frame_info->type_);
+ EXPECT_EQ(12U, frame0->windows_frame_info->parameter_size);
+ }
+
+ { // To avoid reusing locals by mistake
+ StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_FP, frame1->trust);
+ ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP
+ | StackFrameX86::CONTEXT_VALID_ESP
+ | StackFrameX86::CONTEXT_VALID_EBP),
+ frame1->context_validity);
+ EXPECT_EQ(0x5000aa95U, frame1->instruction + 1);
+ EXPECT_EQ(0x5000aa95U, frame1->context.eip);
+ EXPECT_EQ(frame1_esp.Value(), frame1->context.esp);
+ EXPECT_EQ(0x6fa902e0U, frame1->context.ebp);
+ EXPECT_EQ(&module2, frame1->module);
+ EXPECT_EQ("module2::whine", frame1->function_name);
+ EXPECT_EQ(0x5000aa85U, frame1->function_base);
+ ASSERT_TRUE(frame1->windows_frame_info != NULL);
+ EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame1->windows_frame_info->valid);
+ EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FRAME_DATA,
+ frame1->windows_frame_info->type_);
+ // This should not see the 0xbeef parameter size from the FUNC
+ // record, but should instead see the STACK WIN record.
+ EXPECT_EQ(4U, frame1->windows_frame_info->parameter_size);
+ }
+
+ { // To avoid reusing locals by mistake
+ StackFrameX86 *frame2 = static_cast<StackFrameX86 *>(frames->at(2));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame2->trust);
+ ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP
+ | StackFrameX86::CONTEXT_VALID_ESP
+ | StackFrameX86::CONTEXT_VALID_EBP
+ | StackFrameX86::CONTEXT_VALID_EBX),
+ frame2->context_validity);
+ EXPECT_EQ(0x2a179e38U, frame2->instruction + 1);
+ EXPECT_EQ(0x2a179e38U, frame2->context.eip);
+ EXPECT_EQ(frame2_esp.Value(), frame2->context.esp);
+ EXPECT_EQ(frame2_ebp.Value(), frame2->context.ebp);
+ EXPECT_EQ(0x2558c7f3U, frame2->context.ebx);
+ EXPECT_EQ(NULL, frame2->module);
+ EXPECT_EQ(NULL, frame2->windows_frame_info);
+ }
+}
+
+// Use Windows frame data (a "STACK WIN 4" record, from a
+// FrameTypeFrameData DIA record) to walk a stack frame, where the
+// expression fails to yield both an $eip and an $ebp value, and the stack
+// walker must scan.
+TEST_F(GetCallerFrame, WindowsFrameDataScan) {
+ SetModuleSymbols(&module1,
+ "STACK WIN 4 c8c 111 0 0 4 10 4 0 1 bad program string\n");
+ // Mark frame 1's PC as the end of the stack.
+ SetModuleSymbols(&module2,
+ "FUNC 7c38 accf 0 module2::function\n"
+ "STACK WIN 4 7c38 accf 0 0 4 10 4 0 1 $eip 0 = $ebp 0 =\n");
+ Label frame1_esp;
+ stack_section.start() = 0x80000000;
+ stack_section
+ // frame 0
+ .Append(16, 0x2a) // unused, garbage
+ .D32(0x50007ce9) // return address
+ // frame 1
+ .Mark(&frame1_esp)
+ .Append(8, 0); // empty space
+
+ RegionFromSection();
+ raw_context.eip = 0x40000c9c;
+ raw_context.esp = stack_section.start().Value();
+ raw_context.ebp = 0x2ae314cd; // should not be needed to walk frame
+
+ StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
+ StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules,
+ &frame_symbolizer);
+ vector<const CodeModule*> modules_without_symbols;
+ vector<const CodeModule*> modules_with_corrupt_symbols;
+ ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
+ &modules_with_corrupt_symbols));
+ ASSERT_EQ(0U, modules_without_symbols.size());
+ ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
+ frames = call_stack.frames();
+ ASSERT_EQ(2U, frames->size());
+
+ { // To avoid reusing locals by mistake
+ StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
+ ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity);
+ EXPECT_EQ(0x40000c9cU, frame0->instruction);
+ EXPECT_EQ(0x40000c9cU, frame0->context.eip);
+ EXPECT_EQ(stack_section.start().Value(), frame0->context.esp);
+ EXPECT_EQ(0x2ae314cdU, frame0->context.ebp);
+ EXPECT_TRUE(frame0->windows_frame_info != NULL);
+ }
+
+ { // To avoid reusing locals by mistake
+ StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust);
+ // I'd argue that CONTEXT_VALID_EBP shouldn't be here, since the walker
+ // does not actually fetch the EBP after a scan (forcing the next frame
+ // to be scanned as well). But let's grandfather the existing behavior in
+ // for now.
+ ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP
+ | StackFrameX86::CONTEXT_VALID_ESP
+ | StackFrameX86::CONTEXT_VALID_EBP),
+ frame1->context_validity);
+ EXPECT_EQ(0x50007ce9U, frame1->instruction + 1);
+ EXPECT_EQ(0x50007ce9U, frame1->context.eip);
+ EXPECT_EQ(frame1_esp.Value(), frame1->context.esp);
+ EXPECT_TRUE(frame1->windows_frame_info != NULL);
+ }
+}
+
+// Use Windows frame data (a "STACK WIN 4" record, from a
+// FrameTypeFrameData DIA record) to walk a stack frame, where the
+// expression yields an $eip that falls outside of any module, and the
+// stack walker must scan.
+TEST_F(GetCallerFrame, WindowsFrameDataBadEIPScan) {
+ SetModuleSymbols(&module1,
+ "STACK WIN 4 6e6 e7 0 0 0 8 4 0 1"
+ // A traditional frame, actually.
+ " $eip $ebp 4 + ^ = $esp $ebp 8 + = $ebp $ebp ^ =\n");
+ // Mark frame 1's PC as the end of the stack.
+ SetModuleSymbols(&module2,
+ "FUNC cfdb 8406 0 module2::function\n"
+ "STACK WIN 4 cfdb 8406 0 0 0 0 0 0 1 $eip 0 = $ebp 0 =\n");
+ stack_section.start() = 0x80000000;
+
+ // In this stack, the context's %ebp is pointing at the wrong place, so
+ // the stack walker needs to scan to find the return address, and then
+ // scan again to find the caller's saved %ebp.
+ Label frame0_ebp, frame1_ebp, frame1_esp;
+ stack_section
+ // frame 0
+ .Append(8, 0x2a) // garbage
+ .Mark(&frame0_ebp) // frame 0 %ebp points here, but should point
+ // at *** below
+ // The STACK WIN record says that the following two values are
+ // frame 1's saved %ebp and return address, but the %ebp is wrong;
+ // they're garbage. The stack walker will scan for the right values.
+ .D32(0x3d937b2b) // alleged to be frame 1's saved %ebp
+ .D32(0x17847f5b) // alleged to be frame 1's return address
+ .D32(frame1_ebp) // frame 1's real saved %ebp; scan will find
+ .D32(0x2b2b2b2b) // first word of realigned register save area
+ // *** frame 0 %ebp ought to be pointing here
+ .D32(0x2c2c2c2c) // realigned locals area
+ .D32(0x5000d000) // frame 1's real saved %eip; scan will find
+ // Frame 1, in module2::function. The STACK WIN record describes
+ // this as the oldest frame, without referring to its contents, so
+ // we needn't to provide any actual data here.
+ .Mark(&frame1_esp)
+ .Mark(&frame1_ebp) // frame 1 %ebp points here
+ // A dummy value for frame 1's %ebp to point at. The scan recognizes the
+ // saved %ebp because it points to a valid word in the stack memory region.
+ .D32(0x2d2d2d2d);
+
+ RegionFromSection();
+ raw_context.eip = 0x40000700;
+ raw_context.esp = stack_section.start().Value();
+ raw_context.ebp = frame0_ebp.Value();
+
+ StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
+ StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules,
+ &frame_symbolizer);
+ vector<const CodeModule*> modules_without_symbols;
+ vector<const CodeModule*> modules_with_corrupt_symbols;
+ ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
+ &modules_with_corrupt_symbols));
+ ASSERT_EQ(0U, modules_without_symbols.size());
+ ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
+ frames = call_stack.frames();
+ ASSERT_EQ(2U, frames->size());
+
+ { // To avoid reusing locals by mistake
+ StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
+ ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity);
+ EXPECT_EQ(0x40000700U, frame0->instruction);
+ EXPECT_EQ(0x40000700U, frame0->context.eip);
+ EXPECT_EQ(stack_section.start().Value(), frame0->context.esp);
+ EXPECT_EQ(frame0_ebp.Value(), frame0->context.ebp);
+ EXPECT_TRUE(frame0->windows_frame_info != NULL);
+ }
+
+ { // To avoid reusing locals by mistake
+ StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_CFI_SCAN, frame1->trust);
+ // I'd argue that CONTEXT_VALID_EBP shouldn't be here, since the
+ // walker does not actually fetch the EBP after a scan (forcing the
+ // next frame to be scanned as well). But let's grandfather the existing
+ // behavior in for now.
+ ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP
+ | StackFrameX86::CONTEXT_VALID_ESP
+ | StackFrameX86::CONTEXT_VALID_EBP),
+ frame1->context_validity);
+ EXPECT_EQ(0x5000d000U, frame1->instruction + 1);
+ EXPECT_EQ(0x5000d000U, frame1->context.eip);
+ EXPECT_EQ(frame1_esp.Value(), frame1->context.esp);
+ EXPECT_EQ(frame1_ebp.Value(), frame1->context.ebp);
+ EXPECT_TRUE(frame1->windows_frame_info != NULL);
+ }
+}
+
+// Use Windows FrameTypeFPO data to walk a stack frame for a function that
+// does not modify %ebp from the value it had in the caller.
+TEST_F(GetCallerFrame, WindowsFPOUnchangedEBP) {
+ SetModuleSymbols(&module1,
+ // Note bogus parameter size in FUNC record; the walker
+ // should prefer the STACK WIN record, and see the '8' below.
+ "FUNC e8a8 100 feeb module1::discombobulated\n"
+ "STACK WIN 0 e8a8 100 0 0 8 4 10 0 0 0\n");
+ Label frame0_esp;
+ Label frame1_esp, frame1_ebp;
+ stack_section.start() = 0x80000000;
+ stack_section
+ // frame 0, in module1::wheedle. FrameTypeFPO (STACK WIN 0) frame.
+ .Mark(&frame0_esp)
+ // no outgoing parameters; this is the youngest frame.
+ .D32(0x7c521352) // four bytes of saved registers
+ .Append(0x10, 0x42) // local area
+ .D32(0x40009b5b) // return address, in module1, no function
+ // frame 1, in module1, no function.
+ .Mark(&frame1_esp)
+ .D32(0xf60ea7fc) // junk
+ .Mark(&frame1_ebp)
+ .D32(0) // saved %ebp (stack end)
+ .D32(0); // saved %eip (stack end)
+
+ RegionFromSection();
+ raw_context.eip = 0x4000e8b8; // in module1::whine
+ raw_context.esp = stack_section.start().Value();
+ // Frame pointer unchanged from caller.
+ raw_context.ebp = frame1_ebp.Value();
+
+ StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
+ StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules,
+ &frame_symbolizer);
+ vector<const CodeModule*> modules_without_symbols;
+ vector<const CodeModule*> modules_with_corrupt_symbols;
+ ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
+ &modules_with_corrupt_symbols));
+ ASSERT_EQ(0U, modules_without_symbols.size());
+ ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
+ frames = call_stack.frames();
+ ASSERT_EQ(2U, frames->size());
+
+ { // To avoid reusing locals by mistake
+ StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
+ ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity);
+ EXPECT_EQ(0x4000e8b8U, frame0->instruction);
+ EXPECT_EQ(0x4000e8b8U, frame0->context.eip);
+ EXPECT_EQ(frame0_esp.Value(), frame0->context.esp);
+ // unchanged from caller
+ EXPECT_EQ(frame1_ebp.Value(), frame0->context.ebp);
+ EXPECT_EQ(&module1, frame0->module);
+ EXPECT_EQ("module1::discombobulated", frame0->function_name);
+ EXPECT_EQ(0x4000e8a8U, frame0->function_base);
+ // The STACK WIN record for module1::discombobulated should have
+ // produced a fully populated WindowsFrameInfo structure.
+ ASSERT_TRUE(frame0->windows_frame_info != NULL);
+ EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame0->windows_frame_info->valid);
+ EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FPO,
+ frame0->windows_frame_info->type_);
+ EXPECT_EQ(0x10U, frame0->windows_frame_info->local_size);
+ }
+
+ { // To avoid reusing locals by mistake
+ StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame1->trust);
+ ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP
+ | StackFrameX86::CONTEXT_VALID_ESP
+ | StackFrameX86::CONTEXT_VALID_EBP
+ | StackFrameX86::CONTEXT_VALID_EBX),
+ frame1->context_validity);
+ EXPECT_EQ(0x40009b5bU, frame1->instruction + 1);
+ EXPECT_EQ(0x40009b5bU, frame1->context.eip);
+ EXPECT_EQ(frame1_esp.Value(), frame1->context.esp);
+ EXPECT_EQ(frame1_ebp.Value(), frame1->context.ebp);
+ EXPECT_EQ(&module1, frame1->module);
+ EXPECT_EQ("", frame1->function_name);
+ EXPECT_EQ(NULL, frame1->windows_frame_info);
+ }
+}
+
+// Use Windows FrameTypeFPO data to walk a stack frame for a function
+// that uses %ebp for its own purposes, saving the value it had in the
+// caller in the standard place in the saved register area.
+TEST_F(GetCallerFrame, WindowsFPOUsedEBP) {
+ SetModuleSymbols(&module1,
+ // Note bogus parameter size in FUNC record; the walker
+ // should prefer the STACK WIN record, and see the '8' below.
+ "FUNC 9aa8 e6 abbe module1::RaisedByTheAliens\n"
+ "STACK WIN 0 9aa8 e6 a 0 10 8 4 0 0 1\n");
+ Label frame0_esp;
+ Label frame1_esp, frame1_ebp;
+ stack_section.start() = 0x80000000;
+ stack_section
+ // frame 0, in module1::wheedle. FrameTypeFPO (STACK WIN 0) frame.
+ .Mark(&frame0_esp)
+ // no outgoing parameters; this is the youngest frame.
+ .D32(frame1_ebp) // saved register area: saved %ebp
+ .D32(0xb68bd5f9) // saved register area: something else
+ .D32(0xd25d05fc) // local area
+ .D32(0x4000debe) // return address, in module1, no function
+ // frame 1, in module1, no function.
+ .Mark(&frame1_esp)
+ .D32(0xf0c9a974) // junk
+ .Mark(&frame1_ebp)
+ .D32(0) // saved %ebp (stack end)
+ .D32(0); // saved %eip (stack end)
+
+ RegionFromSection();
+ raw_context.eip = 0x40009ab8; // in module1::RaisedByTheAliens
+ raw_context.esp = stack_section.start().Value();
+ // RaisedByTheAliens uses %ebp for its own mysterious purposes.
+ raw_context.ebp = 0xecbdd1a5;
+
+ StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
+ StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules,
+ &frame_symbolizer);
+ vector<const CodeModule*> modules_without_symbols;
+ vector<const CodeModule*> modules_with_corrupt_symbols;
+ ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
+ &modules_with_corrupt_symbols));
+ ASSERT_EQ(0U, modules_without_symbols.size());
+ ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
+ frames = call_stack.frames();
+ ASSERT_EQ(2U, frames->size());
+
+ { // To avoid reusing locals by mistake
+ StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
+ ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity);
+ EXPECT_EQ(0x40009ab8U, frame0->instruction);
+ EXPECT_EQ(0x40009ab8U, frame0->context.eip);
+ EXPECT_EQ(frame0_esp.Value(), frame0->context.esp);
+ EXPECT_EQ(0xecbdd1a5, frame0->context.ebp);
+ EXPECT_EQ(&module1, frame0->module);
+ EXPECT_EQ("module1::RaisedByTheAliens", frame0->function_name);
+ EXPECT_EQ(0x40009aa8U, frame0->function_base);
+ // The STACK WIN record for module1::RaisedByTheAliens should have
+ // produced a fully populated WindowsFrameInfo structure.
+ ASSERT_TRUE(frame0->windows_frame_info != NULL);
+ EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame0->windows_frame_info->valid);
+ EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FPO,
+ frame0->windows_frame_info->type_);
+ EXPECT_EQ("", frame0->windows_frame_info->program_string);
+ EXPECT_TRUE(frame0->windows_frame_info->allocates_base_pointer);
+ }
+
+ { // To avoid reusing locals by mistake
+ StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame1->trust);
+ ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP
+ | StackFrameX86::CONTEXT_VALID_ESP
+ | StackFrameX86::CONTEXT_VALID_EBP),
+ frame1->context_validity);
+ EXPECT_EQ(0x4000debeU, frame1->instruction + 1);
+ EXPECT_EQ(0x4000debeU, frame1->context.eip);
+ EXPECT_EQ(frame1_esp.Value(), frame1->context.esp);
+ EXPECT_EQ(frame1_ebp.Value(), frame1->context.ebp);
+ EXPECT_EQ(&module1, frame1->module);
+ EXPECT_EQ("", frame1->function_name);
+ EXPECT_EQ(NULL, frame1->windows_frame_info);
+ }
+}
+
+// This is a regression test for FPO code that references the initial value of
+// EBX.
+TEST_F(GetCallerFrame, WindowsFPOReferencesEBX) {
+ MockCodeModule ntdll(0x776e0000, 0x142000, "ntdll", "ntdllver");
+ MockCodeModule kernel32(0x77250000, 0xd5000, "kernel32", "kernel32ver");
+ MockCodeModule chrome_child(0x5a710000, 0x2b7c000, "chrome_child",
+ "chrome_childver");
+ MockCodeModules modules;
+ modules.Add(&ntdll);
+ modules.Add(&kernel32);
+ modules.Add(&chrome_child);
+ SetModuleSymbols(&ntdll,
+ "PUBLIC 46bf4 0 KiFastSystemCallRet\n"
+ "STACK WIN 0 46bf4 1 0 0 0 0 0 0 0 0\n"
+
+ "PUBLIC 46550 10 NtWaitForKeyedEvent\n"
+ "STACK WIN 0 46550 f 0 0 10 0 0 0 0 0\n"
+
+ "PUBLIC 4965 10 RtlSleepConditionVariableSRW\n"
+
+ "STACK WIN 4 4965 23 23 0 10 8 38 0 1 $T0 $ebx = "
+ "$eip $T0 4 + ^ = $ebx $T0 ^ = $esp $T0 8 + = "
+ "$ebp $ebp ^ = $L $ebp = $P $T0 8 + .cbParams + =\n"
+
+ "STACK WIN 4 4988 e3 0 0 10 8 38 0 1 $T0 $ebx = "
+ "$eip $T0 4 + ^ = $ebx $T0 ^ = $esp $T0 8 + = "
+ "$ebp $ebp ^ = $L $ebp = $P $T0 8 + .cbParams + =\n"
+
+ "STACK WIN 4 4b2e b 0 0 10 8 38 0 1 $T0 $ebx = "
+ "$eip $T0 4 + ^ = $ebx $T0 ^ = $esp $T0 8 + = "
+ "$ebp $ebp ^ = $L $ebp = $P $T0 8 + .cbParams + =\n");
+
+ SetModuleSymbols(&kernel32,
+ "PUBLIC 3217a 10 SleepConditionVariableSRW\n"
+ "STACK WIN 4 3217a 40 8 0 10 0 8 0 1 $T0 $ebp = $eip $T0 4 "
+ "+ ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs - = "
+ "$P $T0 8 + .cbParams + =\n");
+
+ SetModuleSymbols(&chrome_child,
+ "FUNC 4f4851 20 0 base::ConditionVariable::TimedWait\n");
+
+ stack_section.start() = 0x0026c048;
+ stack_section
+ .D32(0x7772655c)
+ .D32(0x776e4a3f)
+ .D32(0x00000000)
+ .D32(0x0026c070)
+ .D32(0x00000000)
+ .D32(0x00000000)
+ .D32(0x00000001)
+ .D32(0x0026c168)
+ .D32(0x00000000)
+ .D32(0x00000000)
+ .D32(0x00000000)
+ .D32(0x0026c070)
+ .D32(0x00000000)
+ .D32(0x00000000)
+ .D32(0x00000000)
+ .D32(0x0026c164)
+ .D32(0x00be0000)
+ .D32(0x0026fc60)
+ .D32(0x0026c164)
+ .D32(0x00000000)
+ .D32(0xfffffffe)
+ .D32(0x00000000)
+ .D32(0x0026c0d0)
+ .D32(0x7728219e)
+ .D32(0x000003e8)
+ .D32(0x00000000)
+ .D32(0x7728219e)
+ .D32(0x0026c168)
+ .D32(0x0026c164)
+ .D32(0x00000000)
+ .D32(0x00000000)
+ .D32(0x0026c168)
+ .D32(0x000003e8)
+ .D32(0x000003e8)
+ .D32(0x0026c0ec)
+ .D32(0x5ac0486c)
+ .D32(0x0026c168)
+ .D32(0x0026c108)
+ .D32(0x5ac0484c)
+ .D32(0x0026c100)
+ .D32(0x0026c160);
+
+ RegionFromSection();
+ raw_context.eip = 0x77726bf4; // in ntdll!KiFastSystemCallRet
+ raw_context.esp = stack_section.start().Value();
+ raw_context.ebp = 0x26c0a0;
+ raw_context.ebx = 0x26c0ac;
+
+ StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
+ StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules,
+ &frame_symbolizer);
+ vector<const CodeModule *> modules_without_symbols;
+ vector<const CodeModule *> modules_with_corrupt_symbols;
+ ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
+ &modules_with_corrupt_symbols));
+ ASSERT_EQ(0U, modules_without_symbols.size());
+ ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
+ frames = call_stack.frames();
+
+ ASSERT_EQ(5U, frames->size());
+ {
+ const StackFrameX86 &frame = *static_cast<StackFrameX86 *>(frames->at(0));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame.trust);
+ EXPECT_EQ(0x77726bf4U, frame.context.eip);
+ EXPECT_EQ("KiFastSystemCallRet", frame.function_name);
+ }
+ {
+ const StackFrameX86 &frame = *static_cast<StackFrameX86 *>(frames->at(1));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame.trust);
+ EXPECT_EQ(0x7772655cU, frame.context.eip);
+ EXPECT_EQ("NtWaitForKeyedEvent", frame.function_name);
+ }
+ {
+ const StackFrameX86 &frame = *static_cast<StackFrameX86 *>(frames->at(2));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame.trust);
+ EXPECT_EQ(0x776e4a3fU, frame.context.eip);
+ EXPECT_EQ("RtlSleepConditionVariableSRW", frame.function_name);
+ }
+ {
+ const StackFrameX86 &frame = *static_cast<StackFrameX86 *>(frames->at(3));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame.trust);
+ EXPECT_EQ(0x7728219eU, frame.context.eip);
+ EXPECT_EQ("SleepConditionVariableSRW", frame.function_name);
+ }
+ {
+ const StackFrameX86 &frame = *static_cast<StackFrameX86 *>(frames->at(4));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame.trust);
+ EXPECT_EQ(0x5ac0486cU, frame.context.eip);
+ EXPECT_EQ("base::ConditionVariable::TimedWait", frame.function_name);
+ }
+}
+
+// This is a regression unit test which covers a bug which has to do with
+// FPO-optimized Windows system call stubs in the context frame. There is
+// a more recent Windows system call dispatch mechanism which differs from
+// the one which is being tested here. The newer system call dispatch
+// mechanism creates an extra context frame (KiFastSystemCallRet).
+TEST_F(GetCallerFrame, WindowsFPOSystemCall) {
+ SetModuleSymbols(&module3, // ntdll.dll
+ "PUBLIC 1f8ac c ZwWaitForSingleObject\n"
+ "STACK WIN 0 1f8ac 1b 0 0 c 0 0 0 0 0\n");
+ SetModuleSymbols(&module4, // kernelbase.dll
+ "PUBLIC 109f9 c WaitForSingleObjectEx\n"
+ "PUBLIC 36590 0 _except_handler4\n"
+ "STACK WIN 4 109f9 df c 0 c c 48 0 1 $T0 $ebp = $eip "
+ "$T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L "
+ "$T0 .cbSavedRegs - = $P $T0 8 + .cbParams + =\n"
+ "STACK WIN 4 36590 154 17 0 10 0 14 0 1 $T0 $ebp = $eip "
+ "$T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 "
+ ".cbSavedRegs - = $P $T0 8 + .cbParams + =\n");
+ SetModuleSymbols(&module5, // kernel32.dll
+ "PUBLIC 11136 8 WaitForSingleObject\n"
+ "PUBLIC 11151 c WaitForSingleObjectExImplementation\n"
+ "STACK WIN 4 11136 16 5 0 8 0 0 0 1 $T0 $ebp = $eip "
+ "$T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L "
+ "$T0 .cbSavedRegs - = $P $T0 8 + .cbParams + =\n"
+ "STACK WIN 4 11151 7a 5 0 c 0 0 0 1 $T0 $ebp = $eip "
+ "$T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L "
+ "$T0 .cbSavedRegs - = $P $T0 8 + .cbParams + =\n");
+ SetModuleSymbols(&module6, // chrome.dll
+ "FILE 7038 some_file_name.h\n"
+ "FILE 839776 some_file_name.cc\n"
+ "FUNC 217fda 17 4 function_217fda\n"
+ "217fda 4 102 839776\n"
+ "FUNC 217ff1 a 4 function_217ff1\n"
+ "217ff1 0 594 7038\n"
+ "217ff1 a 596 7038\n"
+ "STACK WIN 0 217ff1 a 0 0 4 0 0 0 0 0\n");
+
+ Label frame0_esp, frame1_esp;
+ Label frame1_ebp, frame2_ebp, frame3_ebp;
+ stack_section.start() = 0x002ff290;
+ stack_section
+ .Mark(&frame0_esp)
+ .D32(0x771ef8c1) // EIP in frame 0 (system call)
+ .D32(0x75fa0a91) // return address of frame 0
+ .Mark(&frame1_esp)
+ .D32(0x000017b0) // args to child
+ .D32(0x00000000)
+ .D32(0x002ff2d8)
+ .D32(0x88014a2e)
+ .D32(0x002ff364)
+ .D32(0x000017b0)
+ .D32(0x00000000)
+ .D32(0x00000024)
+ .D32(0x00000001)
+ .D32(0x00000000)
+ .D32(0x00000000)
+ .D32(0x00000000)
+ .D32(0x00000000)
+ .D32(0x00000000)
+ .D32(0x00000000)
+ .D32(0x00000000)
+ .D32(0x9e3b9800)
+ .D32(0xfffffff7)
+ .D32(0x00000000)
+ .D32(0x002ff2a4)
+ .D32(0x64a07ff1) // random value to be confused with a return address
+ .D32(0x002ff8dc)
+ .D32(0x75fc6590) // random value to be confused with a return address
+ .D32(0xfdd2c6ea)
+ .D32(0x00000000)
+ .Mark(&frame1_ebp)
+ .D32(frame2_ebp) // Child EBP
+ .D32(0x75741194) // return address of frame 1
+ .D32(0x000017b0) // args to child
+ .D32(0x0036ee80)
+ .D32(0x00000000)
+ .D32(0x65bc7d14)
+ .Mark(&frame2_ebp)
+ .D32(frame3_ebp) // Child EBP
+ .D32(0x75741148) // return address of frame 2
+ .D32(0x000017b0) // args to child
+ .D32(0x0036ee80)
+ .D32(0x00000000)
+ .Mark(&frame3_ebp)
+ .D32(0) // saved %ebp (stack end)
+ .D32(0); // saved %eip (stack end)
+
+ RegionFromSection();
+ raw_context.eip = 0x771ef8c1; // in ntdll::ZwWaitForSingleObject
+ raw_context.esp = stack_section.start().Value();
+ ASSERT_TRUE(raw_context.esp == frame0_esp.Value());
+ raw_context.ebp = frame1_ebp.Value();
+
+ StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
+ StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules,
+ &frame_symbolizer);
+ vector<const CodeModule*> modules_without_symbols;
+ vector<const CodeModule*> modules_with_corrupt_symbols;
+ ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
+ &modules_with_corrupt_symbols));
+ ASSERT_EQ(0U, modules_without_symbols.size());
+ ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
+ frames = call_stack.frames();
+
+ ASSERT_EQ(4U, frames->size());
+
+ { // To avoid reusing locals by mistake
+ StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
+ ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity);
+ EXPECT_EQ(0x771ef8c1U, frame0->instruction);
+ EXPECT_EQ(0x771ef8c1U, frame0->context.eip);
+ EXPECT_EQ(frame0_esp.Value(), frame0->context.esp);
+ EXPECT_EQ(frame1_ebp.Value(), frame0->context.ebp);
+ EXPECT_EQ(&module3, frame0->module);
+ EXPECT_EQ("ZwWaitForSingleObject", frame0->function_name);
+ // The STACK WIN record for module3!ZwWaitForSingleObject should have
+ // produced a fully populated WindowsFrameInfo structure.
+ ASSERT_TRUE(frame0->windows_frame_info != NULL);
+ EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame0->windows_frame_info->valid);
+ EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FPO,
+ frame0->windows_frame_info->type_);
+ EXPECT_EQ("", frame0->windows_frame_info->program_string);
+ EXPECT_FALSE(frame0->windows_frame_info->allocates_base_pointer);
+ }
+
+ { // To avoid reusing locals by mistake
+ StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame1->trust);
+ ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP
+ | StackFrameX86::CONTEXT_VALID_ESP
+ | StackFrameX86::CONTEXT_VALID_EBP
+ | StackFrameX86::CONTEXT_VALID_EBX),
+ frame1->context_validity);
+ EXPECT_EQ(0x75fa0a91U, frame1->instruction + 1);
+ EXPECT_EQ(0x75fa0a91U, frame1->context.eip);
+ EXPECT_EQ(frame1_esp.Value(), frame1->context.esp);
+ EXPECT_EQ(frame1_ebp.Value(), frame1->context.ebp);
+ EXPECT_EQ(&module4, frame1->module);
+ EXPECT_EQ("WaitForSingleObjectEx", frame1->function_name);
+ // The STACK WIN record for module4!WaitForSingleObjectEx should have
+ // produced a fully populated WindowsFrameInfo structure.
+ ASSERT_TRUE(frame1->windows_frame_info != NULL);
+ EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame1->windows_frame_info->valid);
+ EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FRAME_DATA,
+ frame1->windows_frame_info->type_);
+ EXPECT_EQ("$T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L "
+ "$T0 .cbSavedRegs - = $P $T0 8 + .cbParams + =",
+ frame1->windows_frame_info->program_string);
+ EXPECT_FALSE(frame1->windows_frame_info->allocates_base_pointer);
+ }
+}
+
+// Scan the stack for a better return address and potentially skip frames
+// when the calculated return address is not in a known module. Note, that
+// the span of this scan is somewhat arbitrarily limited to 160 search words
+// for the context frame and 40 search words (pointers) for the other frames:
+// const int kRASearchWords = 40;
+// This means that frames can be skipped only when their size is relatively
+// small: smaller than 4 * kRASearchWords * sizeof(InstructionType)
+TEST_F(GetCallerFrame, ReturnAddressIsNotInKnownModule) {
+ MockCodeModule msvcrt_dll(0x77be0000, 0x58000, "msvcrt.dll", "version1");
+ SetModuleSymbols(&msvcrt_dll, // msvcrt.dll
+ "PUBLIC 38180 0 wcsstr\n"
+ "STACK WIN 4 38180 61 10 0 8 0 0 0 1 $T0 $ebp = $eip $T0 "
+ "4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs "
+ "- = $P $T0 4 + .cbParams + =\n");
+
+ MockCodeModule kernel32_dll(0x7c800000, 0x103000, "kernel32.dll", "version1");
+ SetModuleSymbols(&kernel32_dll, // kernel32.dll
+ "PUBLIC efda 8 FindNextFileW\n"
+ "STACK WIN 4 efda 1bb c 0 8 8 3c 0 1 $T0 $ebp = $eip $T0 "
+ "4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs "
+ "- = $P $T0 4 + .cbParams + =\n");
+
+ MockCodeModule chrome_dll(0x1c30000, 0x28C8000, "chrome.dll", "version1");
+ SetModuleSymbols(&chrome_dll, // chrome.dll
+ "FUNC e3cff 4af 0 file_util::FileEnumerator::Next()\n"
+ "e3cff 1a 711 2505\n"
+ "STACK WIN 4 e3cff 4af 20 0 4 c 94 0 1 $T1 .raSearch = "
+ "$T0 $T1 4 - 8 @ = $ebp $T1 4 - ^ = $eip $T1 ^ = $esp "
+ "$T1 4 + = $20 $T0 152 - ^ = $23 $T0 156 - ^ = $24 "
+ "$T0 160 - ^ =\n");
+
+ // Create some modules with some stock debugging information.
+ MockCodeModules local_modules;
+ local_modules.Add(&msvcrt_dll);
+ local_modules.Add(&kernel32_dll);
+ local_modules.Add(&chrome_dll);
+
+ Label frame0_esp;
+ Label frame0_ebp;
+ Label frame1_ebp;
+ Label frame2_ebp;
+ Label frame3_ebp;
+
+ stack_section.start() = 0x0932f2d0;
+ stack_section
+ .Mark(&frame0_esp)
+ .D32(0x0764e000)
+ .D32(0x0764e068)
+ .Mark(&frame0_ebp)
+ .D32(frame1_ebp) // Child EBP
+ .D32(0x001767a0) // return address of frame 0
+ // Not in known module
+ .D32(0x0764e0c6)
+ .D32(0x001bb1b8)
+ .D32(0x0764e068)
+ .D32(0x00000003)
+ .D32(0x0764e068)
+ .D32(0x00000003)
+ .D32(0x07578828)
+ .D32(0x0764e000)
+ .D32(0x00000000)
+ .D32(0x001c0010)
+ .D32(0x0764e0c6)
+ .Mark(&frame1_ebp)
+ .D32(frame2_ebp) // Child EBP
+ .D32(0x7c80f10f) // return address of frame 1
+ // inside kernel32!FindNextFileW
+ .D32(0x000008f8)
+ .D32(0x00000000)
+ .D32(0x00000000)
+ .D32(0x00000000)
+ .D32(0x0932f34c)
+ .D32(0x0764e000)
+ .D32(0x00001000)
+ .D32(0x00000000)
+ .D32(0x00000001)
+ .D32(0x00000000)
+ .D32(0x00000000)
+ .D32(0x0932f6a8)
+ .D32(0x00000000)
+ .D32(0x0932f6d8)
+ .D32(0x00000000)
+ .D32(0x000000d6)
+ .D32(0x0764e000)
+ .D32(0x7ff9a000)
+ .D32(0x0932f3fc)
+ .D32(0x00000001)
+ .D32(0x00000001)
+ .D32(0x07578828)
+ .D32(0x0000002e)
+ .D32(0x0932f340)
+ .D32(0x0932eef4)
+ .D32(0x0932ffdc)
+ .D32(0x7c839ad8)
+ .D32(0x7c80f0d8)
+ .D32(0x00000000)
+ .Mark(&frame2_ebp)
+ .D32(frame3_ebp) // Child EBP
+ .D32(0x01d13f91) // return address of frame 2
+ // inside chrome_dll!file_util::FileEnumerator::Next
+ .D32(0x07578828)
+ .D32(0x0932f6ac)
+ .D32(0x0932f9c4)
+ .D32(0x0932f9b4)
+ .D32(0x00000000)
+ .D32(0x00000003)
+ .D32(0x0932f978)
+ .D32(0x01094330)
+ .D32(0x00000000)
+ .D32(0x00000001)
+ .D32(0x01094330)
+ .D32(0x00000000)
+ .D32(0x00000000)
+ .D32(0x07f30000)
+ .D32(0x01c3ba17)
+ .D32(0x08bab840)
+ .D32(0x07f31580)
+ .D32(0x00000000)
+ .D32(0x00000007)
+ .D32(0x0932f940)
+ .D32(0x0000002e)
+ .D32(0x0932f40c)
+ .D32(0x01d13b53)
+ .D32(0x0932f958)
+ .D32(0x00000001)
+ .D32(0x00000007)
+ .D32(0x0932f940)
+ .D32(0x0000002e)
+ .D32(0x00000000)
+ .D32(0x0932f6ac)
+ .D32(0x01e13ef0)
+ .D32(0x00000001)
+ .D32(0x00000007)
+ .D32(0x0932f958)
+ .D32(0x08bab840)
+ .D32(0x0932f9b4)
+ .D32(0x00000000)
+ .D32(0x0932f9b4)
+ .D32(0x000000a7)
+ .D32(0x000000a7)
+ .D32(0x0932f998)
+ .D32(0x579627a2)
+ .Mark(&frame3_ebp)
+ .D32(0) // saved %ebp (stack end)
+ .D32(0); // saved %eip (stack end)
+
+ RegionFromSection();
+ raw_context.eip = 0x77c181cd; // inside msvcrt!wcsstr
+ raw_context.esp = frame0_esp.Value();
+ raw_context.ebp = frame0_ebp.Value();
+ // sanity
+ ASSERT_TRUE(raw_context.esp == stack_section.start().Value());
+ ASSERT_TRUE(raw_context.ebp == stack_section.start().Value() + 8);
+
+ StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
+ StackwalkerX86 walker(&system_info, &raw_context, &stack_region,
+ &local_modules, &frame_symbolizer);
+ vector<const CodeModule*> modules_without_symbols;
+ vector<const CodeModule*> modules_with_corrupt_symbols;
+ ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
+ &modules_with_corrupt_symbols));
+ ASSERT_EQ(0U, modules_without_symbols.size());
+ ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
+ frames = call_stack.frames();
+
+ ASSERT_EQ(3U, frames->size());
+
+ { // To avoid reusing locals by mistake
+ StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
+ ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity);
+ EXPECT_EQ(0x77c181cdU, frame0->instruction);
+ EXPECT_EQ(0x77c181cdU, frame0->context.eip);
+ EXPECT_EQ(frame0_esp.Value(), frame0->context.esp);
+ EXPECT_EQ(frame0_ebp.Value(), frame0->context.ebp);
+ EXPECT_EQ(&msvcrt_dll, frame0->module);
+ EXPECT_EQ("wcsstr", frame0->function_name);
+ ASSERT_TRUE(frame0->windows_frame_info != NULL);
+ EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame0->windows_frame_info->valid);
+ EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FRAME_DATA,
+ frame0->windows_frame_info->type_);
+ EXPECT_EQ("$T0 $ebp = $eip $T0 "
+ "4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs "
+ "- = $P $T0 4 + .cbParams + =",
+ frame0->windows_frame_info->program_string);
+ // It has program string, so allocates_base_pointer is not expected
+ EXPECT_FALSE(frame0->windows_frame_info->allocates_base_pointer);
+ }
+
+ { // To avoid reusing locals by mistake
+ StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_CFI_SCAN, frame1->trust);
+ ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP |
+ StackFrameX86::CONTEXT_VALID_ESP |
+ StackFrameX86::CONTEXT_VALID_EBP),
+ frame1->context_validity);
+ EXPECT_EQ(0x7c80f10fU, frame1->instruction + 1);
+ EXPECT_EQ(0x7c80f10fU, frame1->context.eip);
+ // frame 1 was skipped, so intead of frame1_ebp compare with frame2_ebp.
+ EXPECT_EQ(frame2_ebp.Value(), frame1->context.ebp);
+ EXPECT_EQ(&kernel32_dll, frame1->module);
+ EXPECT_EQ("FindNextFileW", frame1->function_name);
+ ASSERT_TRUE(frame1->windows_frame_info != NULL);
+ EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame1->windows_frame_info->valid);
+ EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FRAME_DATA,
+ frame1->windows_frame_info->type_);
+ EXPECT_EQ("$T0 $ebp = $eip $T0 "
+ "4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs "
+ "- = $P $T0 4 + .cbParams + =",
+ frame1->windows_frame_info->program_string);
+ EXPECT_FALSE(frame1->windows_frame_info->allocates_base_pointer);
+ }
+
+ { // To avoid reusing locals by mistake
+ StackFrameX86 *frame2 = static_cast<StackFrameX86 *>(frames->at(2));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame2->trust);
+ ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP |
+ StackFrameX86::CONTEXT_VALID_ESP |
+ StackFrameX86::CONTEXT_VALID_EBP),
+ frame2->context_validity);
+ EXPECT_EQ(0x01d13f91U, frame2->instruction + 1);
+ EXPECT_EQ(0x01d13f91U, frame2->context.eip);
+ // frame 1 was skipped, so intead of frame2_ebp compare with frame3_ebp.
+ EXPECT_EQ(frame3_ebp.Value(), frame2->context.ebp);
+ EXPECT_EQ(&chrome_dll, frame2->module);
+ EXPECT_EQ("file_util::FileEnumerator::Next()", frame2->function_name);
+ ASSERT_TRUE(frame2->windows_frame_info != NULL);
+ EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame2->windows_frame_info->valid);
+ EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FRAME_DATA,
+ frame2->windows_frame_info->type_);
+ EXPECT_EQ("$T1 .raSearch = "
+ "$T0 $T1 4 - 8 @ = $ebp $T1 4 - ^ = $eip $T1 ^ = $esp "
+ "$T1 4 + = $20 $T0 152 - ^ = $23 $T0 156 - ^ = $24 "
+ "$T0 160 - ^ =",
+ frame2->windows_frame_info->program_string);
+ EXPECT_FALSE(frame2->windows_frame_info->allocates_base_pointer);
+ }
+}
+
+// Test the .raSearchStart/.raSearch calculation when alignment operators are
+// used in the program string. The current %ebp must be valid and it is the
+// only reliable data point that can be used for that calculation.
+TEST_F(GetCallerFrame, HandleAlignmentInProgramString) {
+ MockCodeModule chrome_dll(0x59630000, 0x19e3000, "chrome.dll", "version1");
+ SetModuleSymbols(&chrome_dll, // chrome.dll
+ "FUNC 56422 50c 8 base::MessageLoop::RunTask"
+ "(base::PendingTask const &)\n"
+ "56422 e 458 4589\n"
+ "STACK WIN 4 56422 50c 11 0 8 c ac 0 1 $T1 .raSearch = $T0 "
+ "$T1 4 - 8 @ = $ebp $T1 4 - ^ = $eip $T1 ^ = $esp $T1 4 + = "
+ "$20 $T0 176 - ^ = $23 $T0 180 - ^ = $24 $T0 184 - ^ =\n"
+ "FUNC 55d34 34a 0 base::MessageLoop::DoWork()\n"
+ "55d34 11 596 4589\n"
+ "STACK WIN 4 55d34 34a 19 0 0 c 134 0 1 $T1 .raSearch = "
+ "$T0 $T1 4 - 8 @ = $ebp $T1 4 - ^ = $eip $T1 ^ = $esp "
+ "$T1 4 + = $20 $T0 312 - ^ = $23 $T0 316 - ^ = $24 $T0 "
+ "320 - ^ =\n"
+ "FUNC 55c39 fb 0 base::MessagePumpForIO::DoRunLoop()\n"
+ "55c39 d 518 19962\n"
+ "STACK WIN 4 55c39 fb d 0 0 c 34 0 1 $T1 .raSearch = $T0 "
+ "$T1 4 - 64 @ = $ebp $T1 4 - ^ = $eip $T1 ^ = $esp $T1 4 + "
+ "= $20 $T0 56 - ^ = $23 $T0 60 - ^ = $24 $T0 64 - ^ =\n"
+ "FUNC 55bf0 49 4 base::MessagePumpWin::Run(base::"
+ "MessagePump::Delegate *)\n"
+ "55bf0 49 48 4724\n"
+ "STACK WIN 4 55bf0 49 c 0 4 0 10 0 1 $T0 $ebp = $eip $T0 4 "
+ "+ ^ = $ebp $T0 ^ = $esp $T0 8 + =\n"
+ "FUNC 165d de 4 malloc\n"
+ "165d 6 119 54\n"
+ "STACK WIN 4 165d de d 0 4 8 0 0 1 $T1 .raSearch = $T0 "
+ "$T1 4 - 8 @ = $ebp $T1 4 - ^ = $eip $T1 ^ = $esp $T1 4 "
+ "+ = $23 $T0 4 - ^ = $24 $T0 8 - ^ =\n"
+ "FUNC 55ac9 79 0 base::MessageLoop::RunInternal()\n"
+ "55ac9 d 427 4589\n"
+ "STACK WIN 4 55ac9 79 d 0 0 8 10 0 1 $T1 .raSearch = $T0 "
+ "$T1 4 - 8 @ = $ebp $T1 4 - ^ = $eip $T1 ^ = $esp $T1 4 + = "
+ "$23 $T0 20 - ^ = $24 $T0 24 - ^ =\n");
+
+ // Create some modules with some stock debugging information.
+ MockCodeModules local_modules;
+ local_modules.Add(&chrome_dll);
+
+ Label frame0_esp;
+ Label frame0_ebp;
+ Label frame1_esp;
+ Label frame1_ebp;
+ Label frame2_esp;
+ Label frame2_ebp;
+ Label frame3_esp;
+ Label frame3_ebp;
+
+ stack_section.start() = 0x046bfc80;
+ stack_section
+ .D32(0)
+ .Mark(&frame0_esp)
+ .D32(0x01e235a0)
+ .D32(0x00000000)
+ .D32(0x01e9f580)
+ .D32(0x01e9f580)
+ .D32(0x00000020)
+ .D32(0x00000000)
+ .D32(0x00463674)
+ .D32(0x00000020)
+ .D32(0x00000000)
+ .D32(0x046bfcd8)
+ .D32(0x046bfcd8)
+ .D32(0x0001204b)
+ .D32(0x00000000)
+ .D32(0xfdddb523)
+ .D32(0x00000000)
+ .D32(0x00000007)
+ .D32(0x00000040)
+ .D32(0x00000000)
+ .D32(0x59631693) // chrome_59630000!malloc+0x36
+ .D32(0x01e9f580)
+ .D32(0x01e9f580)
+ .D32(0x046bfcf8)
+ .D32(0x77da6704) // ntdll!NtSetIoCompletion+0xc
+ .D32(0x046bfd4c)
+ .D32(0x59685bec) // chrome_59630000!base::MessageLoop::StartHistogrammer..
+ .D32(0x01e235a0)
+
+ .Mark(&frame0_ebp)
+ .D32(frame1_ebp) // Child EBP .D32(0x046bfd0c)
+ .D32(0x59685c2e) // Return address in
+ // chrome_59630000!base::MessagePumpWin::Run+0x3e
+ .Mark(&frame1_esp)
+ .D32(0x01e75a90)
+ .D32(0x046bfd4c)
+ .D32(0x01e75a90)
+ .D32(0x00000000)
+ .D32(0x00000300)
+ .D32(0x00000001)
+
+ .Mark(&frame1_ebp)
+ .D32(frame2_ebp) // Child EBP .D32(0x046bfd30)
+ .D32(0x59685b3c) // Return address in
+ // chrome_59630000!base::MessageLoop::RunInternal+0x73
+ .Mark(&frame2_esp)
+ .D32(0x01e75a90)
+ .D32(0x00000000)
+ .D32(0x046bfd4c)
+ .D32(0x59658123) // chrome_59630000!std::deque..
+ .D32(0x046bfda0)
+ .D32(0x01e79d70)
+ .D32(0x046bfda0)
+
+ .Mark(&frame2_ebp) // .D32(0x046bfd40)
+ .D32(0) // saved %ebp (stack end)
+ .D32(0); // saved %eip (stack end)
+
+ RegionFromSection();
+ raw_context.eip = 0x59685c46; // Context frame in
+ // base::MessagePumpForIO::DoRunLoop
+ raw_context.esp = frame0_esp.Value();
+ raw_context.ebp = frame0_ebp.Value();
+
+ StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
+ StackwalkerX86 walker(&system_info, &raw_context, &stack_region,
+ &local_modules, &frame_symbolizer);
+ vector<const CodeModule*> modules_without_symbols;
+ vector<const CodeModule*> modules_with_corrupt_symbols;
+ ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
+ &modules_with_corrupt_symbols));
+ ASSERT_EQ(0U, modules_without_symbols.size());
+ ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
+ frames = call_stack.frames();
+
+ ASSERT_EQ(3U, frames->size());
+
+ { // To avoid reusing locals by mistake
+ StackFrameX86 *frame = static_cast<StackFrameX86 *>(frames->at(0));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame->trust);
+ ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame->context_validity);
+ EXPECT_EQ("base::MessagePumpForIO::DoRunLoop()", frame->function_name);
+ EXPECT_EQ(0x59685c46U, frame->instruction);
+ EXPECT_EQ(0x59685c46U, frame->context.eip);
+ EXPECT_EQ(frame0_esp.Value(), frame->context.esp);
+ EXPECT_EQ(frame0_ebp.Value(), frame->context.ebp);
+ EXPECT_EQ(&chrome_dll, frame->module);
+ ASSERT_TRUE(frame->windows_frame_info != NULL);
+ EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame->windows_frame_info->valid);
+ EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FRAME_DATA,
+ frame->windows_frame_info->type_);
+ EXPECT_EQ("$T1 .raSearch = $T0 "
+ "$T1 4 - 64 @ = $ebp $T1 4 - ^ = $eip $T1 ^ = $esp $T1 4 + "
+ "= $20 $T0 56 - ^ = $23 $T0 60 - ^ = $24 $T0 64 - ^ =",
+ frame->windows_frame_info->program_string);
+ EXPECT_FALSE(frame->windows_frame_info->allocates_base_pointer);
+ }
+
+ { // To avoid reusing locals by mistake
+ StackFrameX86 *frame = static_cast<StackFrameX86 *>(frames->at(1));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame->trust);
+ ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP |
+ StackFrameX86::CONTEXT_VALID_ESP |
+ StackFrameX86::CONTEXT_VALID_EBP),
+ frame->context_validity);
+ EXPECT_EQ("base::MessagePumpWin::Run(base::MessagePump::Delegate *)",
+ frame->function_name);
+ EXPECT_EQ(1500011566U, frame->instruction + 1);
+ EXPECT_EQ(1500011566U, frame->context.eip);
+ EXPECT_EQ(frame1_esp.Value(), frame->context.esp);
+ EXPECT_EQ(frame1_ebp.Value(), frame->context.ebp);
+ EXPECT_EQ(&chrome_dll, frame->module);
+ ASSERT_TRUE(frame->windows_frame_info != NULL);
+ EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame->windows_frame_info->valid);
+ EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FRAME_DATA,
+ frame->windows_frame_info->type_);
+ EXPECT_EQ("$T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + =",
+ frame->windows_frame_info->program_string);
+ EXPECT_FALSE(frame->windows_frame_info->allocates_base_pointer);
+ }
+
+ { // To avoid reusing locals by mistake
+ StackFrameX86 *frame = static_cast<StackFrameX86 *>(frames->at(2));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame->trust);
+ ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP |
+ StackFrameX86::CONTEXT_VALID_ESP |
+ StackFrameX86::CONTEXT_VALID_EBP),
+ frame->context_validity);
+ EXPECT_EQ("base::MessageLoop::RunInternal()", frame->function_name);
+ EXPECT_EQ(1500011324U, frame->instruction + 1);
+ EXPECT_EQ(1500011324U, frame->context.eip);
+ EXPECT_EQ(frame2_esp.Value(), frame->context.esp);
+ EXPECT_EQ(frame2_ebp.Value(), frame->context.ebp);
+ EXPECT_EQ(&chrome_dll, frame->module);
+ ASSERT_TRUE(frame->windows_frame_info != NULL);
+ EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame->windows_frame_info->valid);
+ EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FRAME_DATA,
+ frame->windows_frame_info->type_);
+ EXPECT_EQ("$T1 .raSearch = $T0 "
+ "$T1 4 - 8 @ = $ebp $T1 4 - ^ = $eip $T1 ^ = $esp $T1 4 + = "
+ "$23 $T0 20 - ^ = $24 $T0 24 - ^ =",
+ frame->windows_frame_info->program_string);
+ EXPECT_FALSE(frame->windows_frame_info->allocates_base_pointer);
+ }
+}
+
+// Scan the stack for a return address and potentially skip frames when the
+// current IP address is not in a known module. Note, that that the span of
+// this scan is limited to 120 search words for the context frame and 30
+// search words (pointers) for the other frames:
+// const int kRASearchWords = 30;
+void GetCallerFrame::IPAddressIsNotInKnownModuleTestImpl(
+ bool has_corrupt_symbols) {
+ MockCodeModule remoting_core_dll(0x54080000, 0x501000, "remoting_core.dll",
+ "version1");
+ string symbols_func_section =
+ "FUNC 137214 17d 10 PK11_Verify\n"
+ "FUNC 15c834 37 14 nsc_ECDSAVerifyStub\n"
+ "FUNC 1611d3 91 14 NSC_Verify\n"
+ "FUNC 162ff7 60 4 sftk_SessionFromHandle\n";
+ string symbols_stack_section =
+ "STACK WIN 4 137214 17d 9 0 10 0 10 0 1 $T0 $ebp = "
+ "$eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + =\n"
+ "STACK WIN 4 15c834 37 6 0 14 0 18 0 1 $T0 $ebp = "
+ "$eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + =\n"
+ "STACK WIN 4 1611d3 91 7 0 14 0 8 0 1 $T0 $ebp = "
+ "$eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + =\n"
+ "STACK WIN 4 162ff7 60 5 0 4 0 0 0 1 $T0 $ebp = "
+ "$eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + =\n";
+
+ string symbols = symbols_func_section;
+ if (has_corrupt_symbols) {
+ symbols.append(string(1, '\0')); // null terminator in the middle
+ symbols.append("\n");
+ symbols.append("FUNC 1234\n" // invalid FUNC records
+ "FUNNC 1234\n"
+ "STACK WIN 4 1234 234 23 " // invalid STACK record
+ "23423423 234 23 234 234 "
+ "234 23 234 23 234 234 "
+ "234 234 234\n");
+ }
+ symbols.append(symbols_stack_section);
+ SetModuleSymbols(&remoting_core_dll, symbols);
+
+ // Create some modules with some stock debugging information.
+ MockCodeModules local_modules;
+ local_modules.Add(&remoting_core_dll);
+
+ Label frame0_esp;
+ Label frame0_ebp;
+ Label frame1_ebp;
+ Label frame1_esp;
+ Label frame2_ebp;
+ Label frame2_esp;
+ Label frame3_ebp;
+ Label frame3_esp;
+ Label bogus_stack_location_1;
+ Label bogus_stack_location_2;
+ Label bogus_stack_location_3;
+
+ stack_section.start() = 0x01a3ea28;
+ stack_section
+ .Mark(&frame0_esp)
+ .D32(bogus_stack_location_2)
+ .D32(bogus_stack_location_1)
+ .D32(0x042478e4)
+ .D32(bogus_stack_location_2)
+ .D32(0x00000000)
+ .D32(0x041f0420)
+ .D32(0x00000000)
+ .D32(0x00000000)
+ .D32(0x00000040)
+ .D32(0x00000001)
+ .D32(0x00b7e0d0)
+ .D32(0x00000000)
+ .D32(0x00000040)
+ .D32(0x00000001)
+ .D32(0x00b7f570)
+ .Mark(&bogus_stack_location_1)
+ .D32(0x00000000)
+ .D32(0x00000040)
+ .D32(0x00000008)
+ .D32(0x04289530)
+ .D32(0x00000000)
+ .D32(0x00000040)
+ .D32(0x00000008)
+ .D32(0x00b7e910)
+ .D32(0x00000000)
+ .D32(0x00000040)
+ .D32(0x00000008)
+ .D32(0x00b7d998)
+ .D32(0x00000000)
+ .D32(0x00000040)
+ .D32(0x00000008)
+ .D32(0x00b7dec0)
+ .Mark(&bogus_stack_location_2)
+ .D32(0x00000000)
+ .D32(0x00000040)
+ .D32(0x00000008)
+ .D32(0x04289428)
+ .D32(0x00000000)
+ .D32(0x00000040)
+ .D32(0x00000008)
+ .D32(0x00b7f258)
+ .Mark(&bogus_stack_location_3)
+ .D32(0x00000000)
+ .D32(0x041f3560)
+ .D32(0x00000041)
+ .D32(0x00000020)
+ .D32(0xffffffff)
+ .Mark(&frame0_ebp)
+ .D32(frame1_ebp) // Child %ebp
+ .D32(0x541dc866) // return address of frame 0
+ // inside remoting_core!nsc_ECDSAVerifyStub+0x32
+ .Mark(&frame1_esp)
+ .D32(0x04247860)
+ .D32(0x01a3eaec)
+ .D32(0x01a3eaf8)
+ .D32(0x541e304f) // remoting_core!sftk_SessionFromHandle+0x58
+ .D32(0x0404c620)
+ .D32(0x00000040)
+ .D32(0x01a3eb2c)
+ .D32(0x01a3ec08)
+ .D32(0x00000014)
+ .Mark(&frame1_ebp)
+ .D32(frame2_ebp) // Child %ebp
+ .D32(0x541e1234) // return address of frame 1
+ // inside remoting_core!NSC_Verify+0x61
+ .Mark(&frame2_esp)
+ .D32(0x04247858)
+ .D32(0x0404c620)
+ .D32(0x00000040)
+ .D32(0x01a3ec08)
+ .D32(0x00000014)
+ .D32(0x01000005)
+ .D32(0x00b2f7a0)
+ .D32(0x041f0420)
+ .D32(0x041f3650)
+ .Mark(&frame2_ebp)
+ .D32(frame3_ebp) // Child %ebp
+ .D32(0x541b734d) // return address of frame 1
+ // inside remoting_core!PK11_Verify+0x139
+ .Mark(&frame3_esp)
+ .D32(0x01000005)
+ .D32(0x01a3ec08)
+ .D32(0x00000014)
+ .D32(0x0404c620)
+ .D32(0x00000040)
+ .D32(0x04073e00)
+ .D32(0x04073e00)
+ .D32(0x04247050)
+ .D32(0x00001041)
+ .D32(0x00000000)
+ .D32(0x00000000)
+ .D32(0x00000000)
+ .Mark(&frame3_ebp)
+ .D32(0) // saved %ebp (stack end)
+ .D32(0); // saved %eip (stack end)
+
+ RegionFromSection();
+ raw_context.eip = 0x4247860; // IP address not in known module
+ raw_context.ebp = 0x5420362d; // bogus
+ raw_context.esp = frame0_esp.Value();
+
+ // sanity
+ ASSERT_TRUE(raw_context.esp == stack_section.start().Value());
+
+ StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
+ StackwalkerX86 walker(&system_info, &raw_context, &stack_region,
+ &local_modules, &frame_symbolizer);
+ vector<const CodeModule*> modules_without_symbols;
+ vector<const CodeModule*> modules_with_corrupt_symbols;
+ ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
+ &modules_with_corrupt_symbols));
+ ASSERT_EQ(0U, modules_without_symbols.size());
+ if (has_corrupt_symbols) {
+ ASSERT_EQ(1U, modules_with_corrupt_symbols.size());
+ ASSERT_EQ("remoting_core.dll",
+ modules_with_corrupt_symbols[0]->debug_file());
+ } else {
+ ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
+ }
+ frames = call_stack.frames();
+
+ ASSERT_EQ(4U, frames->size());
+
+ { // To avoid reusing locals by mistake
+ StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
+ ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity);
+ EXPECT_EQ(raw_context.eip, frame0->context.eip);
+ EXPECT_EQ(raw_context.ebp, frame0->context.ebp);
+ EXPECT_EQ(raw_context.esp, frame0->context.esp);
+ EXPECT_EQ(NULL, frame0->module); // IP not in known module
+ EXPECT_EQ("", frame0->function_name);
+ ASSERT_EQ(NULL, frame0->windows_frame_info);
+ }
+
+ { // To avoid reusing locals by mistake
+ StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust);
+ ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP |
+ StackFrameX86::CONTEXT_VALID_ESP |
+ StackFrameX86::CONTEXT_VALID_EBP),
+ frame1->context_validity);
+ EXPECT_EQ(frame1_ebp.Value(), frame1->context.ebp);
+ EXPECT_EQ(frame1_esp.Value(), frame1->context.esp);
+ EXPECT_EQ(&remoting_core_dll, frame1->module);
+ EXPECT_EQ("nsc_ECDSAVerifyStub", frame1->function_name);
+ ASSERT_TRUE(frame1->windows_frame_info != NULL);
+ EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame1->windows_frame_info->valid);
+ EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FRAME_DATA,
+ frame1->windows_frame_info->type_);
+ EXPECT_EQ("$T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + =",
+ frame1->windows_frame_info->program_string);
+ EXPECT_FALSE(frame1->windows_frame_info->allocates_base_pointer);
+ }
+
+ { // To avoid reusing locals by mistake
+ StackFrameX86 *frame2 = static_cast<StackFrameX86 *>(frames->at(2));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame2->trust);
+ ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP |
+ StackFrameX86::CONTEXT_VALID_ESP |
+ StackFrameX86::CONTEXT_VALID_EBP),
+ frame2->context_validity);
+ EXPECT_EQ(frame2_ebp.Value(), frame2->context.ebp);
+ EXPECT_EQ(frame2_esp.Value(), frame2->context.esp);
+ EXPECT_EQ(&remoting_core_dll, frame2->module);
+ EXPECT_EQ("NSC_Verify", frame2->function_name);
+ ASSERT_TRUE(frame2->windows_frame_info != NULL);
+ EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame2->windows_frame_info->valid);
+ EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FRAME_DATA,
+ frame2->windows_frame_info->type_);
+ EXPECT_EQ("$T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + =",
+ frame2->windows_frame_info->program_string);
+ EXPECT_FALSE(frame2->windows_frame_info->allocates_base_pointer);
+ }
+
+ { // To avoid reusing locals by mistake
+ StackFrameX86 *frame3 = static_cast<StackFrameX86 *>(frames->at(3));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame3->trust);
+ ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP |
+ StackFrameX86::CONTEXT_VALID_ESP |
+ StackFrameX86::CONTEXT_VALID_EBP),
+ frame3->context_validity);
+ EXPECT_EQ(frame3_ebp.Value(), frame3->context.ebp);
+ EXPECT_EQ(frame3_esp.Value(), frame3->context.esp);
+ EXPECT_EQ(&remoting_core_dll, frame3->module);
+ EXPECT_EQ("PK11_Verify", frame3->function_name);
+ ASSERT_TRUE(frame3->windows_frame_info != NULL);
+ EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame3->windows_frame_info->valid);
+ EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FRAME_DATA,
+ frame3->windows_frame_info->type_);
+ EXPECT_EQ("$T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + =",
+ frame3->windows_frame_info->program_string);
+ EXPECT_FALSE(frame3->windows_frame_info->allocates_base_pointer);
+ }
+}
+
+// Runs IPAddressIsNotInKnownModule test with good symbols
+TEST_F(GetCallerFrame, IPAddressIsNotInKnownModule) {
+ IPAddressIsNotInKnownModuleTestImpl(false /* has_corrupt_modules */);
+}
+
+// Runs IPAddressIsNotInKnownModule test with corrupt symbols
+TEST_F(GetCallerFrame, IPAddressIsNotInKnownModule_CorruptSymbols) {
+ IPAddressIsNotInKnownModuleTestImpl(true /* has_corrupt_modules */);
+}
+
+struct CFIFixture: public StackwalkerX86Fixture {
+ CFIFixture() {
+ // Provide a bunch of STACK CFI records; individual tests walk to the
+ // caller from every point in this series, expecting to find the same
+ // set of register values.
+ SetModuleSymbols(&module1,
+ // The youngest frame's function.
+ "FUNC 4000 1000 10 enchiridion\n"
+ // Initially, just a return address.
+ "STACK CFI INIT 4000 100 .cfa: $esp 4 + .ra: .cfa 4 - ^\n"
+ // Push %ebx.
+ "STACK CFI 4001 .cfa: $esp 8 + $ebx: .cfa 8 - ^\n"
+ // Move %esi into %ebx. Weird, but permitted.
+ "STACK CFI 4002 $esi: $ebx\n"
+ // Allocate frame space, and save %edi.
+ "STACK CFI 4003 .cfa: $esp 20 + $edi: .cfa 16 - ^\n"
+ // Put the return address in %edi.
+ "STACK CFI 4005 .ra: $edi\n"
+ // Save %ebp, and use it as a frame pointer.
+ "STACK CFI 4006 .cfa: $ebp 8 + $ebp: .cfa 12 - ^\n"
+
+ // The calling function.
+ "FUNC 5000 1000 10 epictetus\n"
+ // Mark it as end of stack.
+ "STACK CFI INIT 5000 1000 .cfa: $esp .ra 0\n");
+
+ // Provide some distinctive values for the caller's registers.
+ expected.esp = 0x80000000;
+ expected.eip = 0x40005510;
+ expected.ebp = 0xc0d4aab9;
+ expected.ebx = 0x60f20ce6;
+ expected.esi = 0x53d1379d;
+ expected.edi = 0xafbae234;
+
+ // By default, registers are unchanged.
+ raw_context = expected;
+ }
+
+ // Walk the stack, using stack_section as the contents of the stack
+ // and raw_context as the current register values. (Set
+ // raw_context.esp to the stack's starting address.) Expect two
+ // stack frames; in the older frame, expect the callee-saves
+ // registers to have values matching those in 'expected'.
+ void CheckWalk() {
+ RegionFromSection();
+ raw_context.esp = stack_section.start().Value();
+
+ StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
+ StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules,
+ &frame_symbolizer);
+ vector<const CodeModule*> modules_without_symbols;
+ vector<const CodeModule*> modules_with_corrupt_symbols;
+ ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
+ &modules_with_corrupt_symbols));
+ ASSERT_EQ(0U, modules_without_symbols.size());
+ ASSERT_EQ(0U, modules_with_corrupt_symbols.size());
+ frames = call_stack.frames();
+ ASSERT_EQ(2U, frames->size());
+
+ { // To avoid reusing locals by mistake
+ StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
+ ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity);
+ EXPECT_EQ("enchiridion", frame0->function_name);
+ EXPECT_EQ(0x40004000U, frame0->function_base);
+ ASSERT_TRUE(frame0->windows_frame_info != NULL);
+ ASSERT_EQ(WindowsFrameInfo::VALID_PARAMETER_SIZE,
+ frame0->windows_frame_info->valid);
+ ASSERT_TRUE(frame0->cfi_frame_info != NULL);
+ }
+
+ { // To avoid reusing locals by mistake
+ StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1));
+ EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame1->trust);
+ ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP |
+ StackFrameX86::CONTEXT_VALID_ESP |
+ StackFrameX86::CONTEXT_VALID_EBP |
+ StackFrameX86::CONTEXT_VALID_EBX |
+ StackFrameX86::CONTEXT_VALID_ESI |
+ StackFrameX86::CONTEXT_VALID_EDI),
+ frame1->context_validity);
+ EXPECT_EQ(expected.eip, frame1->context.eip);
+ EXPECT_EQ(expected.esp, frame1->context.esp);
+ EXPECT_EQ(expected.ebp, frame1->context.ebp);
+ EXPECT_EQ(expected.ebx, frame1->context.ebx);
+ EXPECT_EQ(expected.esi, frame1->context.esi);
+ EXPECT_EQ(expected.edi, frame1->context.edi);
+ EXPECT_EQ("epictetus", frame1->function_name);
+ }
+ }
+
+ // The values the stack walker should find for the caller's registers.
+ MDRawContextX86 expected;
+};
+
+class CFI: public CFIFixture, public Test { };
+
+TEST_F(CFI, At4000) {
+ Label frame1_esp = expected.esp;
+ stack_section
+ .D32(0x40005510) // return address
+ .Mark(&frame1_esp); // This effectively sets stack_section.start().
+ raw_context.eip = 0x40004000;
+ CheckWalk();
+}
+
+TEST_F(CFI, At4001) {
+ Label frame1_esp = expected.esp;
+ stack_section
+ .D32(0x60f20ce6) // saved %ebx
+ .D32(0x40005510) // return address
+ .Mark(&frame1_esp); // This effectively sets stack_section.start().
+ raw_context.eip = 0x40004001;
+ raw_context.ebx = 0x91aa9a8b; // callee's %ebx value
+ CheckWalk();
+}
+
+TEST_F(CFI, At4002) {
+ Label frame1_esp = expected.esp;
+ stack_section
+ .D32(0x60f20ce6) // saved %ebx
+ .D32(0x40005510) // return address
+ .Mark(&frame1_esp); // This effectively sets stack_section.start().
+ raw_context.eip = 0x40004002;
+ raw_context.ebx = 0x53d1379d; // saved %esi
+ raw_context.esi = 0xa5c790ed; // callee's %esi value
+ CheckWalk();
+}
+
+TEST_F(CFI, At4003) {
+ Label frame1_esp = expected.esp;
+ stack_section
+ .D32(0x56ec3db7) // garbage
+ .D32(0xafbae234) // saved %edi
+ .D32(0x53d67131) // garbage
+ .D32(0x60f20ce6) // saved %ebx
+ .D32(0x40005510) // return address
+ .Mark(&frame1_esp); // This effectively sets stack_section.start().
+ raw_context.eip = 0x40004003;
+ raw_context.ebx = 0x53d1379d; // saved %esi
+ raw_context.esi = 0xa97f229d; // callee's %esi
+ raw_context.edi = 0xb05cc997; // callee's %edi
+ CheckWalk();
+}
+
+// The results here should be the same as those at module offset
+// 0x4003.
+TEST_F(CFI, At4004) {
+ Label frame1_esp = expected.esp;
+ stack_section
+ .D32(0xe29782c2) // garbage
+ .D32(0xafbae234) // saved %edi
+ .D32(0x5ba29ce9) // garbage
+ .D32(0x60f20ce6) // saved %ebx
+ .D32(0x40005510) // return address
+ .Mark(&frame1_esp); // This effectively sets stack_section.start().
+ raw_context.eip = 0x40004004;
+ raw_context.ebx = 0x53d1379d; // saved %esi
+ raw_context.esi = 0x0fb7dc4e; // callee's %esi
+ raw_context.edi = 0x993b4280; // callee's %edi
+ CheckWalk();
+}
+
+TEST_F(CFI, At4005) {
+ Label frame1_esp = expected.esp;
+ stack_section
+ .D32(0xe29782c2) // garbage
+ .D32(0xafbae234) // saved %edi
+ .D32(0x5ba29ce9) // garbage
+ .D32(0x60f20ce6) // saved %ebx
+ .D32(0x8036cc02) // garbage
+ .Mark(&frame1_esp); // This effectively sets stack_section.start().
+ raw_context.eip = 0x40004005;
+ raw_context.ebx = 0x53d1379d; // saved %esi
+ raw_context.esi = 0x0fb7dc4e; // callee's %esi
+ raw_context.edi = 0x40005510; // return address
+ CheckWalk();
+}
+
+TEST_F(CFI, At4006) {
+ Label frame0_ebp;
+ Label frame1_esp = expected.esp;
+ stack_section
+ .D32(0xdcdd25cd) // garbage
+ .D32(0xafbae234) // saved %edi
+ .D32(0xc0d4aab9) // saved %ebp
+ .Mark(&frame0_ebp) // frame pointer points here
+ .D32(0x60f20ce6) // saved %ebx
+ .D32(0x8036cc02) // garbage
+ .Mark(&frame1_esp); // This effectively sets stack_section.start().
+ raw_context.eip = 0x40004006;
+ raw_context.ebp = frame0_ebp.Value();
+ raw_context.ebx = 0x53d1379d; // saved %esi
+ raw_context.esi = 0x743833c9; // callee's %esi
+ raw_context.edi = 0x40005510; // return address
+ CheckWalk();
+}
+
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/static_address_map-inl.h b/toolkit/crashreporter/google-breakpad/src/processor/static_address_map-inl.h
new file mode 100644
index 0000000000..67e07976e0
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/static_address_map-inl.h
@@ -0,0 +1,71 @@
+// 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.
+
+// static_address_map-inl.h: StaticAddressMap implementation.
+//
+// See static_address_map.h for documentation.
+//
+// Author: Siyang Xie (lambxsy@google.com)
+
+#ifndef PROCESSOR_STATIC_ADDRESS_MAP_INL_H__
+#define PROCESSOR_STATIC_ADDRESS_MAP_INL_H__
+
+#include "processor/static_address_map.h"
+
+#include "processor/logging.h"
+
+namespace google_breakpad {
+
+template<typename AddressType, typename EntryType>
+bool StaticAddressMap<AddressType, EntryType>::Retrieve(
+ const AddressType &address,
+ const EntryType *&entry, AddressType *entry_address) const {
+
+ // upper_bound gives the first element whose key is greater than address,
+ // but we want the first element whose key is less than or equal to address.
+ // Decrement the iterator to get there, but not if the upper_bound already
+ // points to the beginning of the map - in that case, address is lower than
+ // the lowest stored key, so return false.
+
+ MapConstIterator iterator = map_.upper_bound(address);
+ if (iterator == map_.begin())
+ return false;
+ --iterator;
+
+ entry = iterator.GetValuePtr();
+ // Make sure AddressType is a copyable basic type
+ if (entry_address)
+ *entry_address = iterator.GetKey();
+
+ return true;
+}
+
+} // namespace google_breakpad
+
+#endif // PROCESSOR_STATIC_ADDRESS_MAP_INL_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/static_address_map.h b/toolkit/crashreporter/google-breakpad/src/processor/static_address_map.h
new file mode 100644
index 0000000000..6bafc66750
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/static_address_map.h
@@ -0,0 +1,78 @@
+// 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.
+
+// static_address_map.h: StaticAddressMap.
+//
+// StaticAddressMap is a wrapper class of StaticMap, just as AddressMap wraps
+// std::map. StaticAddressMap provides read-only Retrieve() operation, similar
+// as AddressMap. However, the difference between StaticAddressMap and
+// AddressMap is that StaticAddressMap does not support dynamic operation
+// Store() due to the static nature of the underlying StaticMap.
+//
+// See address_map.h for reference.
+//
+// Author: Siyang Xie (lambxsy@google.com)
+
+#ifndef PROCESSOR_STATIC_ADDRESS_MAP_H__
+#define PROCESSOR_STATIC_ADDRESS_MAP_H__
+
+#include "processor/static_map-inl.h"
+
+namespace google_breakpad {
+
+// AddressType MUST be a basic type, e.g.: integer types etc
+// EntryType could be a complex type, so we retrieve its pointer instead.
+template<typename AddressType, typename EntryType>
+class StaticAddressMap {
+ public:
+ StaticAddressMap(): map_() { }
+ explicit StaticAddressMap(const char *map_data): map_(map_data) { }
+
+ // Locates the entry stored at the highest address less than or equal to
+ // the address argument. If there is no such range, returns false. The
+ // entry is returned in entry, which is a required argument. If
+ // entry_address is not NULL, it will be set to the address that the entry
+ // was stored at.
+ bool Retrieve(const AddressType &address,
+ const EntryType *&entry, AddressType *entry_address) const;
+
+ private:
+ friend class ModuleComparer;
+ // Convenience types.
+ typedef StaticAddressMap* SelfPtr;
+ typedef StaticMap<AddressType, EntryType> AddressToEntryMap;
+ typedef typename AddressToEntryMap::const_iterator MapConstIterator;
+
+ AddressToEntryMap map_;
+};
+
+} // namespace google_breakpad
+
+#endif // PROCESSOR_STATIC_ADDRESS_MAP_H__
+
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/static_address_map_unittest.cc b/toolkit/crashreporter/google-breakpad/src/processor/static_address_map_unittest.cc
new file mode 100644
index 0000000000..12c735cff0
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/static_address_map_unittest.cc
@@ -0,0 +1,236 @@
+// 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.
+
+// static_address_map_unittest.cc: Unit tests for StaticAddressMap.
+//
+// Author: Siyang Xie (lambxsy@google.com)
+
+#include <climits>
+#include <cstdlib>
+#include <ctime>
+#include <string>
+#include <iostream>
+#include <sstream>
+
+#include "breakpad_googletest_includes.h"
+#include "common/using_std_string.h"
+#include "processor/address_map-inl.h"
+#include "processor/static_address_map-inl.h"
+#include "processor/simple_serializer-inl.h"
+#include "map_serializers-inl.h"
+
+typedef google_breakpad::StaticAddressMap<int, char> TestMap;
+typedef google_breakpad::AddressMap<int, string> AddrMap;
+
+class TestStaticAddressMap : public ::testing::Test {
+ protected:
+ void SetUp() {
+ for (int testcase = 0; testcase < kNumberTestCases; ++testcase) {
+ testdata[testcase] = new int[testsize[testcase]];
+ }
+
+ // Test data set0: NULL (empty map)
+
+ // Test data set1: single element.
+ testdata[1][0] = 10;
+
+ // Test data set2: six elements.
+ const int tempdata[] = {5, 10, 14, 15, 16, 20};
+ for (int i = 0; i < testsize[2]; ++i)
+ testdata[2][i] = tempdata[i];
+
+ // Test data set3:
+ srand(time(NULL));
+ for (int i = 0; i < testsize[3]; ++i)
+ testdata[3][i] = rand();
+
+ // Setup maps.
+ std::stringstream sstream;
+ for (int testcase = 0; testcase < kNumberTestCases; ++testcase) {
+ for (int data_item = 0; data_item < testsize[testcase]; ++data_item) {
+ sstream.clear();
+ sstream << "test " << testdata[testcase][data_item];
+ addr_map[testcase].Store(testdata[testcase][data_item], sstream.str());
+ }
+ map_data[testcase] = serializer.Serialize(addr_map[testcase], NULL);
+ test_map[testcase] = TestMap(map_data[testcase]);
+ }
+ }
+
+ void TearDown() {
+ for (int i = 0; i < kNumberTestCases; ++i) {
+ delete [] map_data[i];
+ delete [] testdata[i];
+ }
+ }
+
+ void CompareRetrieveResult(int testcase, int target) {
+ int address;
+ int address_test;
+ string entry;
+ string entry_test;
+ const char *entry_cstring = NULL;
+ bool found;
+ bool found_test;
+
+ found = addr_map[testcase].Retrieve(target, &entry, &address);
+ found_test =
+ test_map[testcase].Retrieve(target, entry_cstring, &address_test);
+
+ ASSERT_EQ(found, found_test);
+
+ if (found && found_test) {
+ ASSERT_EQ(address, address_test);
+ entry_test = entry_cstring;
+ ASSERT_EQ(entry, entry_test);
+ }
+ }
+
+ void RetrieveTester(int testcase) {
+ int target;
+ target = INT_MIN;
+ CompareRetrieveResult(testcase, target);
+ target = INT_MAX;
+ CompareRetrieveResult(testcase, target);
+
+ srand(time(0));
+ for (int data_item = 0; data_item < testsize[testcase]; ++data_item) {
+ // Retrive (aka, search) for target address and compare results from
+ // AddressMap and StaticAddressMap.
+
+ // First, assign the search target to be one of original testdata that is
+ // known to exist in the map.
+ target = testdata[testcase][data_item];
+ CompareRetrieveResult(testcase, target);
+ // Then, add +2 / -1 bias to target value, in order to test searching for
+ // a target address not stored in the map.
+ target -= 1;
+ CompareRetrieveResult(testcase, target);
+ target += 3;
+ CompareRetrieveResult(testcase, target);
+ // Repeatedly test searching for random target addresses.
+ target = rand();
+ CompareRetrieveResult(testcase, target);
+ }
+ }
+
+ // Test data sets:
+ static const int kNumberTestCases = 4;
+ static const int testsize[];
+ int *testdata[kNumberTestCases];
+
+ AddrMap addr_map[kNumberTestCases];
+ TestMap test_map[kNumberTestCases];
+ char *map_data[kNumberTestCases];
+ google_breakpad::AddressMapSerializer<int, string> serializer;
+};
+
+const int TestStaticAddressMap::testsize[] = {0, 1, 6, 1000};
+
+TEST_F(TestStaticAddressMap, TestEmptyMap) {
+ int testcase = 0;
+ int target;
+ target = INT_MIN;
+ CompareRetrieveResult(testcase, target);
+ target = INT_MAX;
+ CompareRetrieveResult(testcase, target);
+ for (int data_item = 0; data_item < testsize[testcase]; ++data_item) {
+ target = testdata[testcase][data_item];
+ CompareRetrieveResult(testcase, target);
+ target -= 1;
+ CompareRetrieveResult(testcase, target);
+ target += 3;
+ CompareRetrieveResult(testcase, target);
+ target = rand();
+ CompareRetrieveResult(testcase, target);
+ }
+}
+
+TEST_F(TestStaticAddressMap, TestOneElementMap) {
+ int testcase = 1;
+ int target;
+ target = INT_MIN;
+ CompareRetrieveResult(testcase, target);
+ target = INT_MAX;
+ CompareRetrieveResult(testcase, target);
+ for (int data_item = 0; data_item < testsize[testcase]; ++data_item) {
+ target = testdata[testcase][data_item];
+ CompareRetrieveResult(testcase, target);
+ target -= 1;
+ CompareRetrieveResult(testcase, target);
+ target += 3;
+ CompareRetrieveResult(testcase, target);
+ target = rand();
+ CompareRetrieveResult(testcase, target);
+ }
+}
+
+TEST_F(TestStaticAddressMap, TestSixElementsMap) {
+ int testcase = 2;
+ int target;
+ target = INT_MIN;
+ CompareRetrieveResult(testcase, target);
+ target = INT_MAX;
+ CompareRetrieveResult(testcase, target);
+ for (int data_item = 0; data_item < testsize[testcase]; ++data_item) {
+ target = testdata[testcase][data_item];
+ CompareRetrieveResult(testcase, target);
+ target -= 1;
+ CompareRetrieveResult(testcase, target);
+ target += 3;
+ CompareRetrieveResult(testcase, target);
+ target = rand();
+ CompareRetrieveResult(testcase, target);
+ }
+}
+
+TEST_F(TestStaticAddressMap, Test1000RandomElementsMap) {
+ int testcase = 3;
+ int target;
+ target = INT_MIN;
+ CompareRetrieveResult(testcase, target);
+ target = INT_MAX;
+ CompareRetrieveResult(testcase, target);
+ for (int data_item = 0; data_item < testsize[testcase]; ++data_item) {
+ target = testdata[testcase][data_item];
+ CompareRetrieveResult(testcase, target);
+ target -= 1;
+ CompareRetrieveResult(testcase, target);
+ target += 3;
+ CompareRetrieveResult(testcase, target);
+ target = rand();
+ CompareRetrieveResult(testcase, target);
+ }
+}
+
+int main(int argc, char *argv[]) {
+ ::testing::InitGoogleTest(&argc, argv);
+
+ return RUN_ALL_TESTS();
+}
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/static_contained_range_map-inl.h b/toolkit/crashreporter/google-breakpad/src/processor/static_contained_range_map-inl.h
new file mode 100644
index 0000000000..777c762184
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/static_contained_range_map-inl.h
@@ -0,0 +1,92 @@
+// 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.
+
+// static_contained_range_map-inl.h: Hierarchically-organized range map,
+// i.e., StaticContainedRangeMap implementation.
+//
+// See static_contained_range_map.h for documentation.
+//
+// Author: Siyang Xie (lambxsy@google.com)
+
+#ifndef PROCESSOR_STATIC_CONTAINED_RANGE_MAP_INL_H__
+#define PROCESSOR_STATIC_CONTAINED_RANGE_MAP_INL_H__
+
+#include "processor/static_contained_range_map.h"
+#include "processor/logging.h"
+
+namespace google_breakpad {
+
+template<typename AddressType, typename EntryType>
+StaticContainedRangeMap<AddressType, EntryType>::StaticContainedRangeMap(
+ const char *base)
+ : base_(*(reinterpret_cast<const AddressType*>(base))),
+ entry_size_(*(reinterpret_cast<const uint32_t*>(base + sizeof(base_)))),
+ entry_ptr_(reinterpret_cast<const EntryType *>(
+ base + sizeof(base_) + sizeof(entry_size_))),
+ map_(base + sizeof(base_) + sizeof(entry_size_) + entry_size_) {
+ if (entry_size_ == 0)
+ entry_ptr_ = NULL;
+}
+
+
+template<typename AddressType, typename EntryType>
+bool StaticContainedRangeMap<AddressType, EntryType>::RetrieveRange(
+ const AddressType &address, const EntryType *&entry) const {
+
+ // Get an iterator to the child range whose high address is equal to or
+ // greater than the supplied address. If the supplied address is higher
+ // than all of the high addresses in the range, then this range does not
+ // contain a child at address, so return false. If the supplied address
+ // is lower than the base address of the child range, then it is not within
+ // the child range, so return false.
+ MapConstIterator iterator = map_.lower_bound(address);
+
+ if (iterator == map_.end())
+ return false;
+
+ const char *memory_child =
+ reinterpret_cast<const char*>(iterator.GetValuePtr());
+
+ StaticContainedRangeMap child_map(memory_child);
+
+ if (address < child_map.base_)
+ return false;
+
+ // The child in iterator->second contains the specified address. Find out
+ // if it has a more-specific descendant that also contains it. If it does,
+ // it will set |entry| appropriately. If not, set |entry| to the child.
+ if (!child_map.RetrieveRange(address, entry))
+ entry = child_map.entry_ptr_;
+
+ return true;
+}
+
+} // namespace google_breakpad
+
+#endif // PROCESSOR_STATIC_CONTAINED_RANGE_MAP_INL_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/static_contained_range_map.h b/toolkit/crashreporter/google-breakpad/src/processor/static_contained_range_map.h
new file mode 100644
index 0000000000..6a9b8b7b6d
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/static_contained_range_map.h
@@ -0,0 +1,96 @@
+// 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.
+
+// static_contained_range_map.h: StaticContainedRangeMap.
+//
+// StaticContainedRangeMap is similar to ContainedRangeMap. However,
+// StaticContainedRangeMap wraps a StaticMap instead of std::map, and does not
+// support dynamic operations like StoreRange(...).
+// StaticContainedRangeMap provides same RetrieveRange(...) interfaces as
+// ContainedRangeMap.
+//
+// Please see contained_range_map.h for more documentation.
+//
+// Author: Siyang Xie (lambxsy@google.com)
+
+#ifndef PROCESSOR_STATIC_CONTAINED_RANGE_MAP_H__
+#define PROCESSOR_STATIC_CONTAINED_RANGE_MAP_H__
+
+#include "processor/static_map-inl.h"
+
+namespace google_breakpad {
+
+template<typename AddressType, typename EntryType>
+class StaticContainedRangeMap {
+ public:
+ StaticContainedRangeMap(): base_(), entry_size_(), entry_ptr_(), map_() { }
+ explicit StaticContainedRangeMap(const char *base);
+
+ // Retrieves the most specific (smallest) descendant range encompassing
+ // the specified address. This method will only return entries held by
+ // child ranges, and not the entry contained by |this|. This is necessary
+ // to support a sparsely-populated root range. If no descendant range
+ // encompasses the address, returns false.
+ bool RetrieveRange(const AddressType &address, const EntryType *&entry) const;
+
+ private:
+ friend class ModuleComparer;
+ // AddressToRangeMap stores pointers. This makes reparenting simpler in
+ // StoreRange, because it doesn't need to copy entire objects.
+ typedef StaticContainedRangeMap* SelfPtr;
+ typedef
+ StaticMap<AddressType, StaticContainedRangeMap> AddressToRangeMap;
+ typedef typename AddressToRangeMap::const_iterator MapConstIterator;
+
+ // The base address of this range. The high address does not need to
+ // be stored, because it is used as the key to an object in its parent's
+ // map, and all ContainedRangeMaps except for the root range are contained
+ // within maps. The root range does not actually contain an entry, so its
+ // base_ field is meaningless, and the fact that it has no parent and thus
+ // no key is unimportant. For this reason, the base_ field should only be
+ // is accessed on child ContainedRangeMap objects, and never on |this|.
+ AddressType base_;
+
+ // The entry corresponding to this range. The root range does not
+ // actually contain an entry, so its entry_ field is meaningless. For
+ // this reason, the entry_ field should only be accessed on child
+ // ContainedRangeMap objects, and never on |this|.
+ uint32_t entry_size_;
+ const EntryType *entry_ptr_;
+
+ // The map containing child ranges, keyed by each child range's high
+ // address. This is a pointer to avoid allocating map structures for
+ // leaf nodes, where they are not needed.
+ AddressToRangeMap map_;
+};
+
+} // namespace google_breakpad
+
+
+#endif // PROCESSOR_STATIC_CONTAINED_RANGE_MAP_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/static_contained_range_map_unittest.cc b/toolkit/crashreporter/google-breakpad/src/processor/static_contained_range_map_unittest.cc
new file mode 100644
index 0000000000..4ee47578e2
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/static_contained_range_map_unittest.cc
@@ -0,0 +1,320 @@
+// Copyright (c) 2010, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// static_contained_range_map_unittest.cc: Unit tests for
+// StaticContainedRangeMap.
+//
+// Author: Siyang Xie (lambxsy@google.com)
+
+#include "breakpad_googletest_includes.h"
+#include "common/scoped_ptr.h"
+#include "processor/contained_range_map-inl.h"
+#include "processor/static_contained_range_map-inl.h"
+#include "processor/simple_serializer-inl.h"
+#include "processor/map_serializers-inl.h"
+#include "processor/logging.h"
+
+namespace {
+
+typedef google_breakpad::ContainedRangeMap<unsigned int, int> CRMMap;
+typedef google_breakpad::StaticContainedRangeMap<unsigned int, int> TestMap;
+
+// Each element in test_data contains the expected result when calling
+// RetrieveRange on an address.
+const int test_data[] = {
+ 0, // 0
+ 0, // 1
+ 0, // 2
+ 0, // 3
+ 0, // 4
+ 0, // 5
+ 0, // 6
+ 0, // 7
+ 9, // 8
+ 7, // 9
+ 1, // 10
+ 5, // 11
+ 6, // 12
+ 6, // 13
+ 6, // 14
+ 6, // 15
+ 6, // 16
+ 6, // 17
+ 6, // 18
+ 5, // 19
+ 7, // 20
+ 8, // 21
+ 0, // 22
+ 0, // 23
+ 0, // 24
+ 0, // 25
+ 0, // 26
+ 0, // 27
+ 0, // 28
+ 0, // 29
+ 10, // 30
+ 10, // 31
+ 10, // 32
+ 11, // 33
+ 11, // 34
+ 11, // 35
+ 0, // 36
+ 0, // 37
+ 0, // 38
+ 0, // 39
+ 14, // 40
+ 14, // 41
+ 14, // 42
+ 14, // 43
+ 15, // 44
+ 15, // 45
+ 15, // 46
+ 15, // 47
+ 0, // 48
+ 0, // 49
+ 19, // 50
+ 18, // 51
+ 18, // 52
+ 18, // 53
+ 18, // 54
+ 18, // 55
+ 18, // 56
+ 18, // 57
+ 18, // 58
+ 20, // 59
+ 21, // 60
+ 25, // 61
+ 26, // 62
+ 26, // 63
+ 26, // 64
+ 26, // 65
+ 26, // 66
+ 26, // 67
+ 24, // 68
+ 22, // 69
+ 30, // 70
+ 30, // 71
+ 30, // 72
+ 30, // 73
+ 31, // 74
+ 31, // 75
+ 30, // 76
+ 32, // 77
+ 32, // 78
+ 30, // 79
+ 34, // 80
+ 35, // 81
+ 36, // 82
+ 39, // 83
+ 38, // 84
+ 37, // 85
+ 43, // 86
+ 44, // 87
+ 41, // 88
+ 45, // 89
+ 42, // 90
+ 0, // 91
+ 0, // 92
+ 0, // 93
+ 0, // 94
+ 0, // 95
+ 0, // 96
+ 0, // 97
+ 0, // 98
+ 0 // 99
+};
+
+} // namespace
+
+namespace google_breakpad {
+
+class TestStaticCRMMap : public ::testing::Test {
+ protected:
+ void SetUp();
+
+ // A referrence map for testing StaticCRMMap.
+ google_breakpad::ContainedRangeMap<unsigned int, int> crm_map_;
+
+ // Static version of crm_map using serialized data of crm_map.
+ // The goal of testing is to make sure TestMap provides same results for
+ // lookup operation(s) as CRMMap does.
+ google_breakpad::StaticContainedRangeMap<unsigned int, int> test_map_;
+
+ google_breakpad::ContainedRangeMapSerializer<unsigned int, int> serializer_;
+
+ scoped_array<char> serialized_data_;
+};
+
+void TestStaticCRMMap::SetUp() {
+ // First, do the StoreRange tests. This validates the containment
+ // rules.
+ // We confirm the referrence map correctly stores data during setup.
+ ASSERT_TRUE (crm_map_.StoreRange(10, 10, 1));
+ ASSERT_FALSE(crm_map_.StoreRange(10, 10, 2)); // exactly equal to 1
+ ASSERT_FALSE(crm_map_.StoreRange(11, 10, 3)); // begins inside 1 and extends up
+ ASSERT_FALSE(crm_map_.StoreRange( 9, 10, 4)); // begins below 1 and ends inside
+ ASSERT_TRUE (crm_map_.StoreRange(11, 9, 5)); // contained by existing
+ ASSERT_TRUE (crm_map_.StoreRange(12, 7, 6));
+ ASSERT_TRUE (crm_map_.StoreRange( 9, 12, 7)); // contains existing
+ ASSERT_TRUE (crm_map_.StoreRange( 9, 13, 8));
+ ASSERT_TRUE (crm_map_.StoreRange( 8, 14, 9));
+ ASSERT_TRUE (crm_map_.StoreRange(30, 3, 10));
+ ASSERT_TRUE (crm_map_.StoreRange(33, 3, 11));
+ ASSERT_TRUE (crm_map_.StoreRange(30, 6, 12)); // storable but totally masked
+ ASSERT_TRUE (crm_map_.StoreRange(40, 8, 13)); // will be totally masked
+ ASSERT_TRUE (crm_map_.StoreRange(40, 4, 14));
+ ASSERT_TRUE (crm_map_.StoreRange(44, 4, 15));
+ ASSERT_FALSE(crm_map_.StoreRange(32, 10, 16)); // begins in #10, ends in #14
+ ASSERT_FALSE(crm_map_.StoreRange(50, 0, 17)); // zero length
+ ASSERT_TRUE (crm_map_.StoreRange(50, 10, 18));
+ ASSERT_TRUE (crm_map_.StoreRange(50, 1, 19));
+ ASSERT_TRUE (crm_map_.StoreRange(59, 1, 20));
+ ASSERT_TRUE (crm_map_.StoreRange(60, 1, 21));
+ ASSERT_TRUE (crm_map_.StoreRange(69, 1, 22));
+ ASSERT_TRUE (crm_map_.StoreRange(60, 10, 23));
+ ASSERT_TRUE (crm_map_.StoreRange(68, 1, 24));
+ ASSERT_TRUE (crm_map_.StoreRange(61, 1, 25));
+ ASSERT_TRUE (crm_map_.StoreRange(61, 8, 26));
+ ASSERT_FALSE(crm_map_.StoreRange(59, 9, 27));
+ ASSERT_FALSE(crm_map_.StoreRange(59, 10, 28));
+ ASSERT_FALSE(crm_map_.StoreRange(59, 11, 29));
+ ASSERT_TRUE (crm_map_.StoreRange(70, 10, 30));
+ ASSERT_TRUE (crm_map_.StoreRange(74, 2, 31));
+ ASSERT_TRUE (crm_map_.StoreRange(77, 2, 32));
+ ASSERT_FALSE(crm_map_.StoreRange(72, 6, 33));
+ ASSERT_TRUE (crm_map_.StoreRange(80, 3, 34));
+ ASSERT_TRUE (crm_map_.StoreRange(81, 1, 35));
+ ASSERT_TRUE (crm_map_.StoreRange(82, 1, 36));
+ ASSERT_TRUE (crm_map_.StoreRange(83, 3, 37));
+ ASSERT_TRUE (crm_map_.StoreRange(84, 1, 38));
+ ASSERT_TRUE (crm_map_.StoreRange(83, 1, 39));
+ ASSERT_TRUE (crm_map_.StoreRange(86, 5, 40));
+ ASSERT_TRUE (crm_map_.StoreRange(88, 1, 41));
+ ASSERT_TRUE (crm_map_.StoreRange(90, 1, 42));
+ ASSERT_TRUE (crm_map_.StoreRange(86, 1, 43));
+ ASSERT_TRUE (crm_map_.StoreRange(87, 1, 44));
+ ASSERT_TRUE (crm_map_.StoreRange(89, 1, 45));
+ ASSERT_TRUE (crm_map_.StoreRange(87, 4, 46));
+ ASSERT_TRUE (crm_map_.StoreRange(87, 3, 47));
+ ASSERT_FALSE(crm_map_.StoreRange(86, 2, 48));
+
+ // Serialize crm_map to generate serialized data.
+ unsigned int size;
+ serialized_data_.reset(serializer_.Serialize(&crm_map_, &size));
+ BPLOG(INFO) << "Serialized data size: " << size << " Bytes.";
+
+ // Construct test_map_ from serialized data.
+ test_map_ = TestMap(serialized_data_.get());
+}
+
+TEST_F(TestStaticCRMMap, TestEmptyMap) {
+ CRMMap empty_crm_map;
+
+ unsigned int size;
+ scoped_array<char> serialized_data;
+ serialized_data.reset(serializer_.Serialize(&empty_crm_map, &size));
+ scoped_ptr<TestMap> test_map(new TestMap(serialized_data.get()));
+
+ const unsigned int kCorrectSizeForEmptyMap = 16;
+ ASSERT_EQ(kCorrectSizeForEmptyMap, size);
+
+ const int *entry_test;
+ ASSERT_FALSE(test_map->RetrieveRange(-1, entry_test));
+ ASSERT_FALSE(test_map->RetrieveRange(0, entry_test));
+ ASSERT_FALSE(test_map->RetrieveRange(10, entry_test));
+}
+
+TEST_F(TestStaticCRMMap, TestSingleElementMap) {
+ CRMMap crm_map;
+ // Test on one element:
+ int entry = 1;
+ crm_map.StoreRange(10, 10, entry);
+
+ unsigned int size;
+ scoped_array<char> serialized_data;
+ serialized_data.reset(serializer_.Serialize(&crm_map, &size));
+ scoped_ptr<TestMap> test_map(new TestMap(serialized_data.get()));
+
+ const unsigned int kCorrectSizeForSingleElementMap = 40;
+ ASSERT_EQ(kCorrectSizeForSingleElementMap, size);
+
+ const int *entry_test;
+ ASSERT_FALSE(test_map->RetrieveRange(-1, entry_test));
+ ASSERT_FALSE(test_map->RetrieveRange(0, entry_test));
+ ASSERT_TRUE(test_map->RetrieveRange(10, entry_test));
+ ASSERT_EQ(*entry_test, entry);
+ ASSERT_TRUE(test_map->RetrieveRange(13, entry_test));
+ ASSERT_EQ(*entry_test, entry);
+}
+
+TEST_F(TestStaticCRMMap, RunTestData) {
+ unsigned int test_high = sizeof(test_data) / sizeof(test_data[0]);
+
+ // Now, do the RetrieveRange tests. This further validates that the
+ // objects were stored properly and that retrieval returns the correct
+ // object.
+ // If GENERATE_TEST_DATA is defined, instead of the retrieval tests, a
+ // new test_data array will be printed. Exercise caution when doing this.
+ // Be sure to verify the results manually!
+#ifdef GENERATE_TEST_DATA
+ printf(" const int test_data[] = {\n");
+#endif // GENERATE_TEST_DATA
+
+ for (unsigned int address = 0; address < test_high; ++address) {
+ const int *entryptr;
+ int value = 0;
+ if (test_map_.RetrieveRange(address, entryptr))
+ value = *entryptr;
+
+#ifndef GENERATE_TEST_DATA
+ // Don't use ASSERT inside the loop because it won't show the failed
+ // |address|, and the line number will always be the same. That makes
+ // it difficult to figure out which test failed.
+ EXPECT_EQ(value, test_data[address]) << "FAIL: retrieve address "
+ << address;
+#else // !GENERATE_TEST_DATA
+ printf(" %d%c%s // %d\n", value,
+ address == test_high - 1 ? ' ' : ',',
+ value < 10 ? " " : "",
+ address);
+#endif // !GENERATE_TEST_DATA
+ }
+
+#ifdef GENERATE_TEST_DATA
+ printf(" };\n");
+#endif // GENERATE_TEST_DATA
+}
+
+} // namespace google_breakpad
+
+int main(int argc, char *argv[]) {
+ ::testing::InitGoogleTest(&argc, argv);
+
+ return RUN_ALL_TESTS();
+}
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/static_map-inl.h b/toolkit/crashreporter/google-breakpad/src/processor/static_map-inl.h
new file mode 100644
index 0000000000..e6aac6aba4
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/static_map-inl.h
@@ -0,0 +1,176 @@
+// Copyright 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.
+
+// static_map-inl.h: StaticMap implementation.
+//
+// See static_map.h for documentation.
+//
+// Author: Siyang Xie (lambxsy@google.com)
+
+
+#ifndef PROCESSOR_STATIC_MAP_INL_H__
+#define PROCESSOR_STATIC_MAP_INL_H__
+
+#include "processor/static_map.h"
+#include "processor/static_map_iterator-inl.h"
+#include "processor/logging.h"
+
+namespace google_breakpad {
+
+template<typename Key, typename Value, typename Compare>
+StaticMap<Key, Value, Compare>::StaticMap(const char* raw_data)
+ : raw_data_(raw_data),
+ compare_() {
+ // First 4 Bytes store the number of nodes.
+ num_nodes_ = *(reinterpret_cast<const uint32_t*>(raw_data_));
+
+ offsets_ = reinterpret_cast<const uint32_t*>(
+ raw_data_ + sizeof(num_nodes_));
+
+ keys_ = reinterpret_cast<const Key*>(
+ raw_data_ + (1 + num_nodes_) * sizeof(uint32_t));
+}
+
+// find(), lower_bound() and upper_bound() implement binary search algorithm.
+template<typename Key, typename Value, typename Compare>
+StaticMapIterator<Key, Value, Compare>
+StaticMap<Key, Value, Compare>::find(const Key &key) const {
+ int begin = 0;
+ int end = num_nodes_;
+ int middle;
+ int compare_result;
+ while (begin < end) {
+ middle = begin + (end - begin) / 2;
+ compare_result = compare_(key, GetKeyAtIndex(middle));
+ if (compare_result == 0)
+ return IteratorAtIndex(middle);
+ if (compare_result < 0) {
+ end = middle;
+ } else {
+ begin = middle + 1;
+ }
+ }
+ return this->end();
+}
+
+template<typename Key, typename Value, typename Compare>
+StaticMapIterator<Key, Value, Compare>
+StaticMap<Key, Value, Compare>::lower_bound(const Key &key) const {
+ int begin = 0;
+ int end = num_nodes_;
+ int middle;
+ int comp_result;
+ while (begin < end) {
+ middle = begin + (end - begin) / 2;
+ comp_result = compare_(key, GetKeyAtIndex(middle));
+ if (comp_result == 0)
+ return IteratorAtIndex(middle);
+ if (comp_result < 0) {
+ end = middle;
+ } else {
+ begin = middle + 1;
+ }
+ }
+ return IteratorAtIndex(begin);
+}
+
+template<typename Key, typename Value, typename Compare>
+StaticMapIterator<Key, Value, Compare>
+StaticMap<Key, Value, Compare>::upper_bound(const Key &key) const {
+ int begin = 0;
+ int end = num_nodes_;
+ int middle;
+ int compare_result;
+ while (begin < end) {
+ middle = begin + (end - begin) / 2;
+ compare_result = compare_(key, GetKeyAtIndex(middle));
+ if (compare_result == 0)
+ return IteratorAtIndex(middle + 1);
+ if (compare_result < 0) {
+ end = middle;
+ } else {
+ begin = middle + 1;
+ }
+ }
+ return IteratorAtIndex(begin);
+}
+
+template<typename Key, typename Value, typename Compare>
+bool StaticMap<Key, Value, Compare>::ValidateInMemoryStructure() const {
+ // check the number of nodes is non-negative:
+ if (!raw_data_) return false;
+ int32_t num_nodes = *(reinterpret_cast<const int32_t*>(raw_data_));
+ if (num_nodes < 0) {
+ BPLOG(INFO) << "StaticMap check failed: negative number of nodes";
+ return false;
+ }
+
+ int node_index = 0;
+ if (num_nodes_) {
+ uint64_t first_offset = sizeof(int32_t) * (num_nodes_ + 1)
+ + sizeof(Key) * num_nodes_;
+ // Num_nodes_ is too large.
+ if (first_offset > 0xffffffffUL) {
+ BPLOG(INFO) << "StaticMap check failed: size exceeds limit";
+ return false;
+ }
+ if (offsets_[node_index] != static_cast<uint32_t>(first_offset)) {
+ BPLOG(INFO) << "StaticMap check failed: first node offset is incorrect";
+ return false;
+ }
+ }
+
+ for (node_index = 1; node_index < num_nodes_; ++node_index) {
+ // Check offsets[i] is strictly increasing:
+ if (offsets_[node_index] <= offsets_[node_index - 1]) {
+ BPLOG(INFO) << "StaticMap check failed: node offsets non-increasing";
+ return false;
+ }
+ // Check Key[i] is strictly increasing as no duplicate keys are allowed.
+ if (compare_(GetKeyAtIndex(node_index),
+ GetKeyAtIndex(node_index - 1)) <= 0) {
+ BPLOG(INFO) << "StaticMap check failed: node keys non-increasing";
+ return false;
+ }
+ }
+ return true;
+}
+
+template<typename Key, typename Value, typename Compare>
+const Key StaticMap<Key, Value, Compare>::GetKeyAtIndex(int index) const {
+ if (index < 0 || index >= num_nodes_) {
+ BPLOG(ERROR) << "Key index out of range error";
+ // Key type is required to be primitive type. Return 0 if index is invalid.
+ return 0;
+ }
+ return keys_[index];
+}
+
+} // namespace google_breakpad
+
+#endif // PROCESSOR_STATIC_MAP_INL_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/static_map.h b/toolkit/crashreporter/google-breakpad/src/processor/static_map.h
new file mode 100644
index 0000000000..9723ab2a84
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/static_map.h
@@ -0,0 +1,144 @@
+// Copyright 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.
+
+// static_map.h: StaticMap.
+//
+// StaticMap provides lookup interfaces and iterators similar as stl::map's.
+// These lookup operations are purely Read-Only, thus memory
+// allocation & deallocation is mostly avoided (intentionally).
+//
+// The chunk of memory should contain data with pre-defined pattern:
+// **************** header ***************
+// uint32 (4 bytes): number of nodes
+// uint32 (4 bytes): address offset of node1's mapped_value
+// uint32 (4 bytes): address offset of node2's mapped_value
+// ...
+// uint32 (4 bytes): address offset of nodeN's mapped_value
+//
+// ************* Key array ************
+// (X bytes): node1's key
+// (X bytes): node2's key
+// ...
+// (X bytes): nodeN's key
+//
+// ************* Value array **********
+// (? bytes): node1's mapped_value
+// (? bytes): node2's mapped_value
+// ...
+// (? bytes): nodeN's mapped_value
+//
+// REQUIREMENT: Key type MUST be primitive type or pointers so that:
+// X = sizeof(typename Key);
+//
+// Note: since address offset is stored as uint32, user should keep in mind that
+// StaticMap only supports up to 4GB size of memory data.
+
+// Author: Siyang Xie (lambxsy@google.com)
+
+
+#ifndef PROCESSOR_STATIC_MAP_H__
+#define PROCESSOR_STATIC_MAP_H__
+
+#include "processor/static_map_iterator-inl.h"
+
+namespace google_breakpad {
+
+// Default functor to compare keys.
+template<typename Key>
+class DefaultCompare {
+ public:
+ int operator()(const Key &k1, const Key &k2) const {
+ if (k1 < k2) return -1;
+ if (k1 == k2) return 0;
+ return 1;
+ }
+};
+
+template<typename Key, typename Value, typename Compare = DefaultCompare<Key> >
+class StaticMap {
+ public:
+ typedef StaticMapIterator<Key, Value, Compare> iterator;
+ typedef StaticMapIterator<Key, Value, Compare> const_iterator;
+
+ StaticMap() : raw_data_(0),
+ num_nodes_(0),
+ offsets_(0),
+ compare_() { }
+
+ explicit StaticMap(const char* raw_data);
+
+ inline bool empty() const { return num_nodes_ == 0; }
+ inline unsigned int size() const { return num_nodes_; }
+
+ // Return iterators.
+ inline iterator begin() const { return IteratorAtIndex(0); }
+ inline iterator last() const { return IteratorAtIndex(num_nodes_ - 1); }
+ inline iterator end() const { return IteratorAtIndex(num_nodes_); }
+ inline iterator IteratorAtIndex(int index) const {
+ return iterator(raw_data_, index);
+ }
+
+ // Lookup operations.
+ iterator find(const Key &k) const;
+
+ // lower_bound(k) searches in a sorted range for the first element that has a
+ // key not less than the argument k.
+ iterator lower_bound(const Key &k) const;
+
+ // upper_bound(k) searches in a sorted range for the first element that has a
+ // key greater than the argument k.
+ iterator upper_bound(const Key &k) const;
+
+ // Checks if the underlying memory data conforms to the predefined pattern:
+ // first check the number of nodes is non-negative,
+ // then check both offsets and keys are strictly increasing (sorted).
+ bool ValidateInMemoryStructure() const;
+
+ private:
+ const Key GetKeyAtIndex(int i) const;
+
+ // Start address of a raw memory chunk with serialized data.
+ const char* raw_data_;
+
+ // Number of nodes in the static map.
+ int32_t num_nodes_;
+
+ // Array of offset addresses for stored values.
+ // For example:
+ // address_of_i-th_node_value = raw_data_ + offsets_[i]
+ const uint32_t* offsets_;
+
+ // keys_[i] = key of i_th node
+ const Key* keys_;
+
+ Compare compare_;
+};
+
+} // namespace google_breakpad
+
+#endif // PROCESSOR_STATIC_MAP_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/static_map_iterator-inl.h b/toolkit/crashreporter/google-breakpad/src/processor/static_map_iterator-inl.h
new file mode 100644
index 0000000000..7a7db5ad93
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/static_map_iterator-inl.h
@@ -0,0 +1,147 @@
+// Copyright 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.
+
+// static_map_iterator-inl.h: StaticMapIterator implementation.
+//
+// See static_map_iterator.h for documentation.
+//
+// Author: Siyang Xie (lambxsy@google.com)
+
+#ifndef PROCESSOR_STATIC_MAP_ITERATOR_INL_H__
+#define PROCESSOR_STATIC_MAP_ITERATOR_INL_H__
+
+#include "processor/static_map_iterator.h"
+
+#include "processor/logging.h"
+
+namespace google_breakpad {
+
+template<typename Key, typename Value, typename Compare>
+StaticMapIterator<Key, Value, Compare>::StaticMapIterator(const char* base,
+ const int &index):
+ index_(index), base_(base) {
+ // See static_map.h for documentation on
+ // bytes format of serialized StaticMap data.
+ num_nodes_ = *(reinterpret_cast<const int32_t*>(base_));
+ offsets_ = reinterpret_cast<const uint32_t*>(base_ + sizeof(num_nodes_));
+ keys_ = reinterpret_cast<const Key*>(
+ base_ + (1 + num_nodes_) * sizeof(num_nodes_));
+}
+
+// Increment & Decrement operators:
+template<typename Key, typename Value, typename Compare>
+StaticMapIterator<Key, Value, Compare>&
+StaticMapIterator<Key, Value, Compare>::operator++() {
+ if (!IsValid()) {
+ BPLOG(ERROR) << "operator++ on invalid iterator";
+ return *this;
+ }
+ if (++index_ > num_nodes_) index_ = num_nodes_;
+ return *this;
+}
+
+template<typename Key, typename Value, typename Compare>
+StaticMapIterator<Key, Value, Compare>
+StaticMapIterator<Key, Value, Compare>::operator++(int postfix_operator) {
+ if (!IsValid()) {
+ BPLOG(ERROR) << "operator++ on invalid iterator";
+ return *this;
+ }
+ StaticMapIterator<Key, Value, Compare> tmp = *this;
+ if (++index_ > num_nodes_) index_ = num_nodes_;
+ return tmp;
+}
+
+template<typename Key, typename Value, typename Compare>
+StaticMapIterator<Key, Value, Compare>&
+StaticMapIterator<Key, Value, Compare>::operator--() {
+ if (!IsValid()) {
+ BPLOG(ERROR) << "operator++ on invalid iterator";
+ return *this;
+ }
+
+ if (--index_ < 0) index_ = 0;
+ return *this;
+}
+
+template<typename Key, typename Value, typename Compare>
+StaticMapIterator<Key, Value, Compare>
+StaticMapIterator<Key, Value, Compare>::operator--(int postfix_operator) {
+ if (!IsValid()) {
+ BPLOG(ERROR) << "operator++ on invalid iterator";
+ return *this;
+ }
+ StaticMapIterator<Key, Value, Compare> tmp = *this;
+
+ if (--index_ < 0) index_ = 0;
+ return tmp;
+}
+
+template<typename Key, typename Value, typename Compare>
+const Key* StaticMapIterator<Key, Value, Compare>::GetKeyPtr() const {
+ if (!IsValid()) {
+ BPLOG(ERROR) << "call GetKeyPtr() on invalid iterator";
+ return NULL;
+ }
+ return &(keys_[index_]);
+}
+
+template<typename Key, typename Value, typename Compare>
+const char* StaticMapIterator<Key, Value, Compare>::GetValueRawPtr() const {
+ if (!IsValid()) {
+ BPLOG(ERROR) << "call GetValuePtr() on invalid iterator";
+ return NULL;
+ }
+ return base_ + offsets_[index_];
+}
+
+template<typename Key, typename Value, typename Compare>
+bool StaticMapIterator<Key, Value, Compare>::operator==(
+ const StaticMapIterator<Key, Value, Compare>& x) const {
+ return base_ == x.base_ && index_ == x.index_;
+}
+
+template<typename Key, typename Value, typename Compare>
+bool StaticMapIterator<Key, Value, Compare>::operator!=(
+ const StaticMapIterator<Key, Value, Compare>& x) const {
+ // Only need to compare base_ and index_.
+ // Other data members are auxiliary.
+ return base_ != x.base_ || index_ != x.index_;
+}
+
+template<typename Key, typename Value, typename Compare>
+bool StaticMapIterator<Key, Value, Compare>::IsValid() const {
+ if (!base_ || index_ < 0 || index_ > num_nodes_)
+ return false;
+
+ return true;
+}
+
+} // namespace google_breakpad
+
+#endif // PROCESSOR_STATIC_MAP_ITERATOR_INL_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/static_map_iterator.h b/toolkit/crashreporter/google-breakpad/src/processor/static_map_iterator.h
new file mode 100644
index 0000000000..1af8fff454
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/static_map_iterator.h
@@ -0,0 +1,112 @@
+// Copyright 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.
+
+// static_map_iterator.h: StaticMapIterator template class declaration.
+//
+// StaticMapIterator provides increment and decrement operators to iterate
+// through a StaticMap map. It does not provide *, -> operators, user should
+// use GetKeyPtr(), GetKey(), GetValuePtr() interfaces to retrieve data or
+// pointer to data. StaticMapIterator is essentially a const_iterator.
+//
+// Author: Siyang Xie (lambxsy@google.com)
+
+
+#ifndef PROCESSOR_STATIC_MAP_ITERATOR_H__
+#define PROCESSOR_STATIC_MAP_ITERATOR_H__
+
+#include "google_breakpad/common/breakpad_types.h"
+
+namespace google_breakpad {
+
+// Forward declaration.
+template<typename Key, typename Value, typename Compare> class StaticMap;
+
+// StaticMapIterator does not support operator*() or operator->(),
+// User should use GetKey(), GetKeyPtr(), GetValuePtr() instead;
+template<typename Key, typename Value, typename Compare>
+class StaticMapIterator {
+ public:
+ // Constructors.
+ StaticMapIterator(): index_(-1), base_(NULL) { }
+
+ // Increment & Decrement operators:
+ StaticMapIterator& operator++();
+ StaticMapIterator operator++(int post_fix_operator);
+
+ StaticMapIterator& operator--();
+ StaticMapIterator operator--(int post_fix_operator);
+
+ // Interface for retrieving data / pointer to data.
+ const Key* GetKeyPtr() const;
+
+ // Run time error will occur if GetKey() is called on an invalid iterator.
+ inline const Key GetKey() const { return *GetKeyPtr(); }
+
+ // return a raw memory pointer that points to the start address of value.
+ const char* GetValueRawPtr() const;
+
+ // return a reinterpret-casted pointer to the value.
+ inline const Value* GetValuePtr() const {
+ return reinterpret_cast<const Value*>(GetValueRawPtr());
+ }
+
+ bool operator==(const StaticMapIterator& x) const;
+ bool operator!=(const StaticMapIterator& x) const;
+
+ // Check if this iterator is valid.
+ // If iterator is invalid, user is forbidden to use ++/-- operator
+ // or interfaces for retrieving data / pointer to data.
+ bool IsValid() const;
+
+ private:
+ friend class StaticMap<Key, Value, Compare>;
+
+ // Only StaticMap can call this constructor.
+ explicit StaticMapIterator(const char* base, const int32_t &index);
+
+ // Index of node that the iterator is pointing to.
+ int32_t index_;
+
+ // Beginning address of the serialized map data.
+ const char* base_;
+
+ // Number of nodes in the map. Use it to identify end() iterator.
+ int32_t num_nodes_;
+
+ // offsets_ is an array of offset addresses of mapped values.
+ // For example:
+ // address_of_i-th_node_value = base_ + offsets_[i]
+ const uint32_t* offsets_;
+
+ // keys_[i] = key of i_th node.
+ const Key* keys_;
+};
+
+} // namespace google_breakpad
+
+#endif // PROCESSOR_STATIC_MAP_ITERATOR_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/static_map_unittest.cc b/toolkit/crashreporter/google-breakpad/src/processor/static_map_unittest.cc
new file mode 100644
index 0000000000..393d43d5c5
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/static_map_unittest.cc
@@ -0,0 +1,386 @@
+// 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.
+
+// static_map_unittest.cc: Unit tests for StaticMap.
+//
+// Author: Siyang Xie (lambxsy@google.com)
+
+#include <climits>
+#include <map>
+
+#include "breakpad_googletest_includes.h"
+#include "processor/static_map-inl.h"
+
+
+typedef int ValueType;
+typedef int KeyType;
+typedef google_breakpad::StaticMap< KeyType, ValueType > TestMap;
+typedef std::map< KeyType, ValueType > StdMap;
+
+template<typename Key, typename Value>
+class SimpleMapSerializer {
+ public:
+ static char* Serialize(const std::map<Key, Value> &stdmap,
+ unsigned int* size = NULL) {
+ unsigned int size_per_node =
+ sizeof(uint32_t) + sizeof(Key) + sizeof(Value);
+ unsigned int memsize = sizeof(int32_t) + size_per_node * stdmap.size();
+ if (size) *size = memsize;
+
+ // Allocate memory for serialized data:
+ char* mem = reinterpret_cast<char*>(operator new(memsize));
+ char* address = mem;
+
+ // Writer the number of nodes:
+ new (address) uint32_t(static_cast<uint32_t>(stdmap.size()));
+ address += sizeof(uint32_t);
+
+ // Nodes' offset:
+ uint32_t* offsets = reinterpret_cast<uint32_t*>(address);
+ address += sizeof(uint32_t) * stdmap.size();
+
+ // Keys:
+ Key* keys = reinterpret_cast<Key*>(address);
+ address += sizeof(Key) * stdmap.size();
+
+ // Traversing map:
+ typename std::map<Key, Value>::const_iterator iter = stdmap.begin();
+ for (int index = 0; iter != stdmap.end(); ++iter, ++index) {
+ offsets[index] = static_cast<unsigned int>(address - mem);
+ keys[index] = iter->first;
+ new (address) Value(iter->second);
+ address += sizeof(Value);
+ }
+ return mem;
+ }
+};
+
+
+class TestInvalidMap : public ::testing::Test {
+ protected:
+ void SetUp() {
+ memset(data, 0, kMemorySize);
+ }
+
+ // 40 Bytes memory can hold a StaticMap with up to 3 nodes.
+ static const int kMemorySize = 40;
+ char data[kMemorySize];
+ TestMap test_map;
+};
+
+TEST_F(TestInvalidMap, TestNegativeNumberNodes) {
+ memset(data, 0xff, sizeof(uint32_t)); // Set the number of nodes = -1
+ test_map = TestMap(data);
+ ASSERT_FALSE(test_map.ValidateInMemoryStructure());
+}
+
+TEST_F(TestInvalidMap, TestWrongOffsets) {
+ uint32_t* header = reinterpret_cast<uint32_t*>(data);
+ const uint32_t kNumNodes = 2;
+ const uint32_t kHeaderOffset =
+ sizeof(uint32_t) + kNumNodes * (sizeof(uint32_t) + sizeof(KeyType));
+
+ header[0] = kNumNodes;
+ header[1] = kHeaderOffset + 3; // Wrong offset for first node
+ test_map = TestMap(data);
+ ASSERT_FALSE(test_map.ValidateInMemoryStructure());
+
+ header[1] = kHeaderOffset; // Correct offset for first node
+ header[2] = kHeaderOffset - 1; // Wrong offset for second node
+ test_map = TestMap(data);
+ ASSERT_FALSE(test_map.ValidateInMemoryStructure());
+}
+
+TEST_F(TestInvalidMap, TestUnSortedKeys) {
+ uint32_t* header = reinterpret_cast<uint32_t*>(data);
+ const uint32_t kNumNodes = 2;
+ const uint32_t kHeaderOffset =
+ sizeof(uint32_t) + kNumNodes * (sizeof(uint32_t) + sizeof(KeyType));
+ header[0] = kNumNodes;
+ header[1] = kHeaderOffset;
+ header[2] = kHeaderOffset + sizeof(ValueType);
+
+ KeyType* keys = reinterpret_cast<KeyType*>(
+ data + (kNumNodes + 1) * sizeof(uint32_t));
+ // Set keys in non-increasing order.
+ keys[0] = 10;
+ keys[1] = 7;
+ test_map = TestMap(data);
+ ASSERT_FALSE(test_map.ValidateInMemoryStructure());
+}
+
+
+class TestValidMap : public ::testing::Test {
+ protected:
+ void SetUp() {
+ int testcase = 0;
+
+ // Empty map.
+ map_data[testcase] =
+ serializer.Serialize(std_map[testcase], &size[testcase]);
+ test_map[testcase] = TestMap(map_data[testcase]);
+ ++testcase;
+
+ // Single element.
+ std_map[testcase].insert(std::make_pair(2, 8));
+ map_data[testcase] =
+ serializer.Serialize(std_map[testcase], &size[testcase]);
+ test_map[testcase] = TestMap(map_data[testcase]);
+ ++testcase;
+
+ // 100 elements.
+ for (int i = 0; i < 100; ++i)
+ std_map[testcase].insert(std::make_pair(i, 2 * i));
+ map_data[testcase] =
+ serializer.Serialize(std_map[testcase], &size[testcase]);
+ test_map[testcase] = TestMap(map_data[testcase]);
+ ++testcase;
+
+ // 1000 random elements.
+ for (int i = 0; i < 1000; ++i)
+ std_map[testcase].insert(std::make_pair(rand(), rand()));
+ map_data[testcase] =
+ serializer.Serialize(std_map[testcase], &size[testcase]);
+ test_map[testcase] = TestMap(map_data[testcase]);
+
+ // Set correct size of memory allocation for each test case.
+ unsigned int size_per_node =
+ sizeof(uint32_t) + sizeof(KeyType) + sizeof(ValueType);
+ for (testcase = 0; testcase < kNumberTestCases; ++testcase) {
+ correct_size[testcase] =
+ sizeof(uint32_t) + std_map[testcase].size() * size_per_node;
+ }
+ }
+
+ void TearDown() {
+ for (int i = 0;i < kNumberTestCases; ++i)
+ ::operator delete(map_data[i]);
+ }
+
+
+ void IteratorTester(int test_case) {
+ // scan through:
+ iter_test = test_map[test_case].begin();
+ iter_std = std_map[test_case].begin();
+
+ for (; iter_test != test_map[test_case].end() &&
+ iter_std != std_map[test_case].end();
+ ++iter_test, ++iter_std) {
+ ASSERT_EQ(iter_test.GetKey(), iter_std->first);
+ ASSERT_EQ(*(iter_test.GetValuePtr()), iter_std->second);
+ }
+ ASSERT_TRUE(iter_test == test_map[test_case].end()
+ && iter_std == std_map[test_case].end());
+
+ // Boundary testcase.
+ if (!std_map[test_case].empty()) {
+ // rear boundary case:
+ iter_test = test_map[test_case].end();
+ iter_std = std_map[test_case].end();
+ --iter_std;
+ --iter_test;
+ ASSERT_EQ(iter_test.GetKey(), iter_std->first);
+ ASSERT_EQ(*(iter_test.GetValuePtr()), iter_std->second);
+
+ ++iter_test;
+ ++iter_std;
+ ASSERT_TRUE(iter_test == test_map[test_case].end());
+
+ --iter_test;
+ --iter_std;
+ ASSERT_TRUE(iter_test != test_map[test_case].end());
+ ASSERT_TRUE(iter_test == test_map[test_case].last());
+ ASSERT_EQ(iter_test.GetKey(), iter_std->first);
+ ASSERT_EQ(*(iter_test.GetValuePtr()), iter_std->second);
+
+ // front boundary case:
+ iter_test = test_map[test_case].begin();
+ --iter_test;
+ ASSERT_TRUE(iter_test == test_map[test_case].begin());
+ }
+ }
+
+ void CompareLookupResult(int test_case) {
+ bool found1 = (iter_test != test_map[test_case].end());
+ bool found2 = (iter_std != std_map[test_case].end());
+ ASSERT_EQ(found1, found2);
+
+ if (found1 && found2) {
+ ASSERT_EQ(iter_test.GetKey(), iter_std->first);
+ ASSERT_EQ(*(iter_test.GetValuePtr()), iter_std->second);
+ }
+ }
+
+ void FindTester(int test_case, const KeyType &key) {
+ iter_test = test_map[test_case].find(key);
+ iter_std = std_map[test_case].find(key);
+ CompareLookupResult(test_case);
+ }
+
+ void LowerBoundTester(int test_case, const KeyType &key) {
+ iter_test = test_map[test_case].lower_bound(key);
+ iter_std = std_map[test_case].lower_bound(key);
+ CompareLookupResult(test_case);
+ }
+
+ void UpperBoundTester(int test_case, const KeyType &key) {
+ iter_test = test_map[test_case].upper_bound(key);
+ iter_std = std_map[test_case].upper_bound(key);
+ CompareLookupResult(test_case);
+ }
+
+ void LookupTester(int test_case) {
+ StdMap::const_iterator iter;
+ // Test find():
+ for (iter = std_map[test_case].begin();
+ iter != std_map[test_case].end();
+ ++iter) {
+ FindTester(test_case, iter->first);
+ FindTester(test_case, iter->first + 1);
+ FindTester(test_case, iter->first - 1);
+ }
+ FindTester(test_case, INT_MIN);
+ FindTester(test_case, INT_MAX);
+ // random test:
+ for (int i = 0; i < rand()%5000 + 5000; ++i)
+ FindTester(test_case, rand());
+
+ // Test lower_bound():
+ for (iter = std_map[test_case].begin();
+ iter != std_map[test_case].end();
+ ++iter) {
+ LowerBoundTester(test_case, iter->first);
+ LowerBoundTester(test_case, iter->first + 1);
+ LowerBoundTester(test_case, iter->first - 1);
+ }
+ LowerBoundTester(test_case, INT_MIN);
+ LowerBoundTester(test_case, INT_MAX);
+ // random test:
+ for (int i = 0; i < rand()%5000 + 5000; ++i)
+ LowerBoundTester(test_case, rand());
+
+ // Test upper_bound():
+ for (iter = std_map[test_case].begin();
+ iter != std_map[test_case].end();
+ ++iter) {
+ UpperBoundTester(test_case, iter->first);
+ UpperBoundTester(test_case, iter->first + 1);
+ UpperBoundTester(test_case, iter->first - 1);
+ }
+ UpperBoundTester(test_case, INT_MIN);
+ UpperBoundTester(test_case, INT_MAX);
+ // random test:
+ for (int i = 0; i < rand()%5000 + 5000; ++i)
+ UpperBoundTester(test_case, rand());
+ }
+
+ static const int kNumberTestCases = 4;
+ StdMap std_map[kNumberTestCases];
+ TestMap test_map[kNumberTestCases];
+ TestMap::const_iterator iter_test;
+ StdMap::const_iterator iter_std;
+ char* map_data[kNumberTestCases];
+ unsigned int size[kNumberTestCases];
+ unsigned int correct_size[kNumberTestCases];
+ SimpleMapSerializer<KeyType, ValueType> serializer;
+};
+
+TEST_F(TestValidMap, TestEmptyMap) {
+ int test_case = 0;
+ // Assert memory size allocated during serialization is correct.
+ ASSERT_EQ(correct_size[test_case], size[test_case]);
+
+ // Sanity check of serialized data:
+ ASSERT_TRUE(test_map[test_case].ValidateInMemoryStructure());
+ ASSERT_EQ(std_map[test_case].empty(), test_map[test_case].empty());
+ ASSERT_EQ(std_map[test_case].size(), test_map[test_case].size());
+
+ // Test Iterator.
+ IteratorTester(test_case);
+
+ // Test lookup operations.
+ LookupTester(test_case);
+}
+
+TEST_F(TestValidMap, TestSingleElement) {
+ int test_case = 1;
+ // Assert memory size allocated during serialization is correct.
+ ASSERT_EQ(correct_size[test_case], size[test_case]);
+
+ // Sanity check of serialized data:
+ ASSERT_TRUE(test_map[test_case].ValidateInMemoryStructure());
+ ASSERT_EQ(std_map[test_case].empty(), test_map[test_case].empty());
+ ASSERT_EQ(std_map[test_case].size(), test_map[test_case].size());
+
+ // Test Iterator.
+ IteratorTester(test_case);
+
+ // Test lookup operations.
+ LookupTester(test_case);
+}
+
+TEST_F(TestValidMap, Test100Elements) {
+ int test_case = 2;
+ // Assert memory size allocated during serialization is correct.
+ ASSERT_EQ(correct_size[test_case], size[test_case]);
+
+ // Sanity check of serialized data:
+ ASSERT_TRUE(test_map[test_case].ValidateInMemoryStructure());
+ ASSERT_EQ(std_map[test_case].empty(), test_map[test_case].empty());
+ ASSERT_EQ(std_map[test_case].size(), test_map[test_case].size());
+
+ // Test Iterator.
+ IteratorTester(test_case);
+
+ // Test lookup operations.
+ LookupTester(test_case);
+}
+
+TEST_F(TestValidMap, Test1000RandomElements) {
+ int test_case = 3;
+ // Assert memory size allocated during serialization is correct.
+ ASSERT_EQ(correct_size[test_case], size[test_case]);
+
+ // Sanity check of serialized data:
+ ASSERT_TRUE(test_map[test_case].ValidateInMemoryStructure());
+ ASSERT_EQ(std_map[test_case].empty(), test_map[test_case].empty());
+ ASSERT_EQ(std_map[test_case].size(), test_map[test_case].size());
+
+ // Test Iterator.
+ IteratorTester(test_case);
+
+ // Test lookup operations.
+ LookupTester(test_case);
+}
+
+int main(int argc, char *argv[]) {
+ ::testing::InitGoogleTest(&argc, argv);
+
+ return RUN_ALL_TESTS();
+}
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/static_range_map-inl.h b/toolkit/crashreporter/google-breakpad/src/processor/static_range_map-inl.h
new file mode 100644
index 0000000000..f6cef1a9ee
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/static_range_map-inl.h
@@ -0,0 +1,130 @@
+// 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.
+
+// static_range_map-inl.h: StaticRangeMap implementation.
+//
+// See static_range_map.h for documentation.
+//
+// Author: Siyang Xie (lambxsy@google.com)
+
+#ifndef PROCESSOR_STATIC_RANGE_MAP_INL_H__
+#define PROCESSOR_STATIC_RANGE_MAP_INL_H__
+
+#include "processor/static_range_map.h"
+#include "processor/logging.h"
+
+namespace google_breakpad {
+
+template<typename AddressType, typename EntryType>
+bool StaticRangeMap<AddressType, EntryType>::RetrieveRange(
+ const AddressType &address, const EntryType *&entry,
+ AddressType *entry_base, AddressType *entry_size) const {
+ MapConstIterator iterator = map_.lower_bound(address);
+ if (iterator == map_.end())
+ return false;
+
+ // The map is keyed by the high address of each range, so |address| is
+ // guaranteed to be lower than the range's high address. If |range| is
+ // not directly preceded by another range, it's possible for address to
+ // be below the range's low address, though. When that happens, address
+ // references something not within any range, so return false.
+
+ const Range *range = iterator.GetValuePtr();
+
+ // Make sure AddressType and EntryType are copyable basic types
+ // e.g.: integer types, pointers etc
+ if (address < range->base())
+ return false;
+
+ entry = range->entryptr();
+ if (entry_base)
+ *entry_base = range->base();
+ if (entry_size)
+ *entry_size = iterator.GetKey() - range->base() + 1;
+
+ return true;
+}
+
+
+template<typename AddressType, typename EntryType>
+bool StaticRangeMap<AddressType, EntryType>::RetrieveNearestRange(
+ const AddressType &address, const EntryType *&entry,
+ AddressType *entry_base, AddressType *entry_size) const {
+ // If address is within a range, RetrieveRange can handle it.
+ if (RetrieveRange(address, entry, entry_base, entry_size))
+ return true;
+
+ // upper_bound gives the first element whose key is greater than address,
+ // but we want the first element whose key is less than or equal to address.
+ // Decrement the iterator to get there, but not if the upper_bound already
+ // points to the beginning of the map - in that case, address is lower than
+ // the lowest stored key, so return false.
+
+ MapConstIterator iterator = map_.upper_bound(address);
+ if (iterator == map_.begin())
+ return false;
+ --iterator;
+
+ const Range *range = iterator.GetValuePtr();
+ entry = range->entryptr();
+ if (entry_base)
+ *entry_base = range->base();
+ if (entry_size)
+ *entry_size = iterator.GetKey() - range->base() + 1;
+
+ return true;
+}
+
+template<typename AddressType, typename EntryType>
+bool StaticRangeMap<AddressType, EntryType>::RetrieveRangeAtIndex(
+ int index, const EntryType *&entry,
+ AddressType *entry_base, AddressType *entry_size) const {
+
+ if (index >= GetCount()) {
+ BPLOG(ERROR) << "Index out of range: " << index << "/" << GetCount();
+ return false;
+ }
+
+ MapConstIterator iterator = map_.IteratorAtIndex(index);
+
+ const Range *range = iterator.GetValuePtr();
+
+ entry = range->entryptr();
+ if (entry_base)
+ *entry_base = range->base();
+ if (entry_size)
+ *entry_size = iterator.GetKey() - range->base() + 1;
+
+ return true;
+}
+
+} // namespace google_breakpad
+
+
+#endif // PROCESSOR_STATIC_RANGE_MAP_INL_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/static_range_map.h b/toolkit/crashreporter/google-breakpad/src/processor/static_range_map.h
new file mode 100644
index 0000000000..91aabb0324
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/static_range_map.h
@@ -0,0 +1,106 @@
+// 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.
+//
+// static_range_map.h: StaticRangeMap.
+//
+// StaticRangeMap is similar as RangeMap. However, StaticRangeMap wraps a
+// StaticMap instead of std::map, and does not support dynamic operations like
+// StoreRange(...). StaticRangeMap provides same Retrieve*() interfaces as
+// RangeMap. Please see range_map.h for more documentation.
+//
+// Author: Siyang Xie (lambxsy@google.com)
+
+#ifndef PROCESSOR_STATIC_RANGE_MAP_H__
+#define PROCESSOR_STATIC_RANGE_MAP_H__
+
+
+#include "processor/static_map-inl.h"
+
+namespace google_breakpad {
+
+// AddressType is basic type, e.g.: integer types, pointers etc
+// EntryType could be a complex type, so we retrieve its pointer instead.
+template<typename AddressType, typename EntryType>
+class StaticRangeMap {
+ public:
+ StaticRangeMap(): map_() { }
+ explicit StaticRangeMap(const char *memory): map_(memory) { }
+
+ // Locates the range encompassing the supplied address. If there is
+ // no such range, returns false. entry_base and entry_size, if non-NULL,
+ // are set to the base and size of the entry's range.
+ bool RetrieveRange(const AddressType &address, const EntryType *&entry,
+ AddressType *entry_base, AddressType *entry_size) const;
+
+ // Locates the range encompassing the supplied address, if one exists.
+ // If no range encompasses the supplied address, locates the nearest range
+ // to the supplied address that is lower than the address. Returns false
+ // if no range meets these criteria. entry_base and entry_size, if
+ // non-NULL, are set to the base and size of the entry's range.
+ bool RetrieveNearestRange(const AddressType &address, const EntryType *&entry,
+ AddressType *entry_base, AddressType *entry_size)
+ const;
+
+ // Treating all ranges as a list ordered by the address spaces that they
+ // occupy, locates the range at the index specified by index. Returns
+ // false if index is larger than the number of ranges stored. entry_base
+ // and entry_size, if non-NULL, are set to the base and size of the entry's
+ // range.
+ //
+ // RetrieveRangeAtIndex is not optimized for speedy operation.
+ bool RetrieveRangeAtIndex(int index, const EntryType *&entry,
+ AddressType *entry_base, AddressType *entry_size)
+ const;
+
+ // Returns the number of ranges stored in the RangeMap.
+ inline int GetCount() const { return map_.size(); }
+
+ private:
+ friend class ModuleComparer;
+ class Range {
+ public:
+ AddressType base() const {
+ return *(reinterpret_cast<const AddressType*>(this));
+ }
+ const EntryType* entryptr() const {
+ return reinterpret_cast<const EntryType*>(this + sizeof(AddressType));
+ }
+ };
+
+ // Convenience types.
+ typedef StaticRangeMap* SelfPtr;
+ typedef StaticMap<AddressType, Range> AddressToRangeMap;
+ typedef typename AddressToRangeMap::const_iterator MapConstIterator;
+
+ AddressToRangeMap map_;
+};
+
+} // namespace google_breakpad
+
+#endif // PROCESSOR_STATIC_RANGE_MAP_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/static_range_map_unittest.cc b/toolkit/crashreporter/google-breakpad/src/processor/static_range_map_unittest.cc
new file mode 100644
index 0000000000..2821736224
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/static_range_map_unittest.cc
@@ -0,0 +1,421 @@
+// 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.
+
+// static_range_map_unittest.cc: Unit tests for StaticRangeMap.
+//
+// Author: Siyang Xie (lambxsy@google.com)
+
+#include "breakpad_googletest_includes.h"
+#include "common/scoped_ptr.h"
+#include "processor/range_map-inl.h"
+#include "processor/static_range_map-inl.h"
+#include "processor/simple_serializer-inl.h"
+#include "processor/map_serializers-inl.h"
+#include "processor/logging.h"
+
+
+namespace {
+// Types used for testing.
+typedef int AddressType;
+typedef int EntryType;
+typedef google_breakpad::StaticRangeMap< AddressType, EntryType > TestMap;
+typedef google_breakpad::RangeMap< AddressType, EntryType > RMap;
+
+// RangeTest contains data to use for store and retrieve tests. See
+// RunTests for descriptions of the tests.
+struct RangeTest {
+ // Base address to use for test
+ AddressType address;
+
+ // Size of range to use for test
+ AddressType size;
+
+ // Unique ID of range - unstorable ranges must have unique IDs too
+ EntryType id;
+
+ // Whether this range is expected to be stored successfully or not
+ bool expect_storable;
+};
+
+// A RangeTestSet encompasses multiple RangeTests, which are run in
+// sequence on the same RangeMap.
+struct RangeTestSet {
+ // An array of RangeTests
+ const RangeTest* range_tests;
+
+ // The number of tests in the set
+ unsigned int range_test_count;
+};
+
+// These tests will be run sequentially. The first set of tests exercises
+// most functions of RangeTest, and verifies all of the bounds-checking.
+const RangeTest range_tests_0[] = {
+ { INT_MIN, 16, 1, true }, // lowest possible range
+ { -2, 5, 2, true }, // a range through zero
+ { INT_MAX - 9, 11, 3, false }, // tests anti-overflow
+ { INT_MAX - 9, 10, 4, true }, // highest possible range
+ { 5, 0, 5, false }, // tests anti-zero-size
+ { 5, 1, 6, true }, // smallest possible range
+ { -20, 15, 7, true }, // entirely negative
+
+ { 10, 10, 10, true }, // causes the following tests to fail
+ { 9, 10, 11, false }, // one-less base, one-less high
+ { 9, 11, 12, false }, // one-less base, identical high
+ { 9, 12, 13, false }, // completely contains existing
+ { 10, 9, 14, false }, // identical base, one-less high
+ { 10, 10, 15, false }, // exactly identical to existing range
+ { 10, 11, 16, false }, // identical base, one-greater high
+ { 11, 8, 17, false }, // contained completely within
+ { 11, 9, 18, false }, // one-greater base, identical high
+ { 11, 10, 19, false }, // one-greater base, one-greater high
+ { 9, 2, 20, false }, // overlaps bottom by one
+ { 10, 1, 21, false }, // overlaps bottom by one, contained
+ { 19, 1, 22, false }, // overlaps top by one, contained
+ { 19, 2, 23, false }, // overlaps top by one
+
+ { 9, 1, 24, true }, // directly below without overlap
+ { 20, 1, 25, true }, // directly above without overlap
+
+ { 6, 3, 26, true }, // exactly between two ranges, gapless
+ { 7, 3, 27, false }, // tries to span two ranges
+ { 7, 5, 28, false }, // tries to span three ranges
+ { 4, 20, 29, false }, // tries to contain several ranges
+
+ { 30, 50, 30, true },
+ { 90, 25, 31, true },
+ { 35, 65, 32, false }, // tries to span two noncontiguous
+ { 120, 10000, 33, true }, // > 8-bit
+ { 20000, 20000, 34, true }, // > 8-bit
+ { 0x10001, 0x10001, 35, true }, // > 16-bit
+
+ { 27, -1, 36, false } // tests high < base
+};
+
+// Attempt to fill the entire space. The entire space must be filled with
+// three stores because AddressType is signed for these tests, so RangeMap
+// treats the size as signed and rejects sizes that appear to be negative.
+// Even if these tests were run as unsigned, two stores would be needed
+// to fill the space because the entire size of the space could only be
+// described by using one more bit than would be present in AddressType.
+const RangeTest range_tests_1[] = {
+ { INT_MIN, INT_MAX, 50, true }, // From INT_MIN to -2, inclusive
+ { -1, 2, 51, true }, // From -1 to 0, inclusive
+ { 1, INT_MAX, 52, true }, // From 1 to INT_MAX, inclusive
+ { INT_MIN, INT_MAX, 53, false }, // Can't fill the space twice
+ { -1, 2, 54, false },
+ { 1, INT_MAX, 55, false },
+ { -3, 6, 56, false }, // -3 to 2, inclusive - spans 3 ranges
+};
+
+// A light round of testing to verify that RetrieveRange does the right
+// the right thing at the extremities of the range when nothing is stored
+// there. Checks are forced without storing anything at the extremities
+// by setting size = 0.
+const RangeTest range_tests_2[] = {
+ { INT_MIN, 0, 100, false }, // makes RetrieveRange check low end
+ { -1, 3, 101, true },
+ { INT_MAX, 0, 102, false }, // makes RetrieveRange check high end
+};
+
+// Similar to the previous test set, but with a couple of ranges closer
+// to the extremities.
+const RangeTest range_tests_3[] = {
+ { INT_MIN + 1, 1, 110, true },
+ { INT_MAX - 1, 1, 111, true },
+ { INT_MIN, 0, 112, false }, // makes RetrieveRange check low end
+ { INT_MAX, 0, 113, false } // makes RetrieveRange check high end
+};
+
+// The range map is cleared between sets of tests listed here.
+const RangeTestSet range_test_sets[] = {
+ { range_tests_0, sizeof(range_tests_0) / sizeof(RangeTest) },
+ { range_tests_1, sizeof(range_tests_1) / sizeof(RangeTest) },
+ { range_tests_2, sizeof(range_tests_2) / sizeof(RangeTest) },
+ { range_tests_3, sizeof(range_tests_3) / sizeof(RangeTest) },
+ { range_tests_0, sizeof(range_tests_0) / sizeof(RangeTest) } // Run again
+};
+
+} // namespace
+
+namespace google_breakpad {
+class TestStaticRangeMap : public ::testing::Test {
+ protected:
+ void SetUp() {
+ kTestCasesCount_ = sizeof(range_test_sets) / sizeof(RangeTestSet);
+ }
+
+ // StoreTest uses the data in a RangeTest and calls StoreRange on the
+ // test RangeMap. It returns true if the expected result occurred, and
+ // false if something else happened.
+ void StoreTest(RMap* range_map, const RangeTest* range_test);
+
+ // RetrieveTest uses the data in RangeTest and calls RetrieveRange on the
+ // test RangeMap. If it retrieves the expected value (which can be no
+ // map entry at the specified range,) it returns true, otherwise, it returns
+ // false. RetrieveTest will check the values around the base address and
+ // the high address of a range to guard against off-by-one errors.
+ void RetrieveTest(TestMap* range_map, const RangeTest* range_test);
+
+ // Test RetrieveRangeAtIndex, which is supposed to return objects in order
+ // according to their addresses. This test is performed by looping through
+ // the map, calling RetrieveRangeAtIndex for all possible indices in sequence,
+ // and verifying that each call returns a different object than the previous
+ // call, and that ranges are returned with increasing base addresses. Returns
+ // false if the test fails.
+ void RetrieveIndexTest(const TestMap* range_map, int set);
+
+ void RunTestCase(int test_case);
+
+ unsigned int kTestCasesCount_;
+ RangeMapSerializer<AddressType, EntryType> serializer_;
+};
+
+void TestStaticRangeMap::StoreTest(RMap* range_map,
+ const RangeTest* range_test) {
+ bool stored = range_map->StoreRange(range_test->address,
+ range_test->size,
+ range_test->id);
+ EXPECT_EQ(stored, range_test->expect_storable)
+ << "StoreRange id " << range_test->id << "FAILED";
+}
+
+void TestStaticRangeMap::RetrieveTest(TestMap* range_map,
+ const RangeTest* range_test) {
+ for (unsigned int side = 0; side <= 1; ++side) {
+ // When side == 0, check the low side (base address) of each range.
+ // When side == 1, check the high side (base + size) of each range.
+
+ // Check one-less and one-greater than the target address in addition
+ // to the target address itself.
+
+ // If the size of the range is only 1, don't check one greater than
+ // the base or one less than the high - for a successfully stored
+ // range, these tests would erroneously fail because the range is too
+ // small.
+ AddressType low_offset = -1;
+ AddressType high_offset = 1;
+ if (range_test->size == 1) {
+ if (!side) // When checking the low side,
+ high_offset = 0; // don't check one over the target.
+ else // When checking the high side,
+ low_offset = 0; // don't check one under the target.
+ }
+
+ for (AddressType offset = low_offset; offset <= high_offset; ++offset) {
+ AddressType address =
+ offset +
+ (!side ? range_test->address :
+ range_test->address + range_test->size - 1);
+
+ bool expected_result = false; // This is correct for tests not stored.
+ if (range_test->expect_storable) {
+ if (offset == 0) // When checking the target address,
+ expected_result = true; // test should always succeed.
+ else if (offset == -1) // When checking one below the target,
+ expected_result = side; // should fail low and succeed high.
+ else // When checking one above the target,
+ expected_result = !side; // should succeed low and fail high.
+ }
+
+ const EntryType* id;
+ AddressType retrieved_base;
+ AddressType retrieved_size;
+ bool retrieved = range_map->RetrieveRange(address, id,
+ &retrieved_base,
+ &retrieved_size);
+
+ bool observed_result = retrieved && *id == range_test->id;
+ EXPECT_EQ(observed_result, expected_result)
+ << "RetrieveRange id " << range_test->id
+ << ", side " << side << ", offset " << offset << " FAILED.";
+
+ // If a range was successfully retrieved, check that the returned
+ // bounds match the range as stored.
+ if (observed_result == true) {
+ EXPECT_EQ(retrieved_base, range_test->address)
+ << "RetrieveRange id " << range_test->id
+ << ", side " << side << ", offset " << offset << " FAILED.";
+ EXPECT_EQ(retrieved_size, range_test->size)
+ << "RetrieveRange id " << range_test->id
+ << ", side " << side << ", offset " << offset << " FAILED.";
+ }
+
+ // Now, check RetrieveNearestRange. The nearest range is always
+ // expected to be different from the test range when checking one
+ // less than the low side.
+ bool expected_nearest = range_test->expect_storable;
+ if (!side && offset < 0)
+ expected_nearest = false;
+
+ AddressType nearest_base;
+ AddressType nearest_size;
+ bool retrieved_nearest = range_map->RetrieveNearestRange(address,
+ id,
+ &nearest_base,
+ &nearest_size);
+
+ // When checking one greater than the high side, RetrieveNearestRange
+ // should usually return the test range. When a different range begins
+ // at that address, though, then RetrieveNearestRange should return the
+ // range at the address instead of the test range.
+ if (side && offset > 0 && nearest_base == address) {
+ expected_nearest = false;
+ }
+
+ bool observed_nearest = retrieved_nearest &&
+ *id == range_test->id;
+
+ EXPECT_EQ(observed_nearest, expected_nearest)
+ << "RetrieveRange id " << range_test->id
+ << ", side " << side << ", offset " << offset << " FAILED.";
+
+ // If a range was successfully retrieved, check that the returned
+ // bounds match the range as stored.
+ if (expected_nearest ==true) {
+ EXPECT_EQ(nearest_base, range_test->address)
+ << "RetrieveRange id " << range_test->id
+ << ", side " << side << ", offset " << offset << " FAILED.";
+ EXPECT_EQ(nearest_size, range_test->size)
+ << "RetrieveRange id " << range_test->id
+ << ", side " << side << ", offset " << offset << " FAILED.";
+ }
+ }
+ }
+}
+
+void TestStaticRangeMap::RetrieveIndexTest(const TestMap* range_map, int set) {
+ AddressType last_base = 0;
+ const EntryType* last_entry = 0;
+ const EntryType* entry;
+ int object_count = range_map->GetCount();
+ for (int object_index = 0; object_index < object_count; ++object_index) {
+ AddressType base;
+ ASSERT_TRUE(range_map->RetrieveRangeAtIndex(object_index,
+ entry,
+ &base,
+ NULL))
+ << "FAILED: RetrieveRangeAtIndex set " << set
+ << " index " << object_index;
+
+ ASSERT_TRUE(entry) << "FAILED: RetrieveRangeAtIndex set " << set
+ << " index " << object_index;
+
+ // It's impossible to do these comparisons unless there's a previous
+ // object to compare against.
+ if (last_entry) {
+ // The object must be different from the last_entry one.
+ EXPECT_NE(*entry, *last_entry) << "FAILED: RetrieveRangeAtIndex set "
+ << set << " index " << object_index;
+ // Each object must have a base greater than the previous object's base.
+ EXPECT_GT(base, last_base) << "FAILED: RetrieveRangeAtIndex set " << set
+ << " index " << object_index;
+ }
+ last_entry = entry;
+ last_base = base;
+ }
+
+ // Make sure that RetrieveRangeAtIndex doesn't allow lookups at indices that
+ // are too high.
+ ASSERT_FALSE(range_map->RetrieveRangeAtIndex(
+ object_count, entry, NULL, NULL)) << "FAILED: RetrieveRangeAtIndex set "
+ << set << " index " << object_count
+ << " (too large)";
+}
+
+// RunTests runs a series of test sets.
+void TestStaticRangeMap::RunTestCase(int test_case) {
+ // Maintain the range map in a pointer so that deletion can be meaningfully
+ // tested.
+ scoped_ptr<RMap> rmap(new RMap());
+
+ const RangeTest* range_tests = range_test_sets[test_case].range_tests;
+ unsigned int range_test_count = range_test_sets[test_case].range_test_count;
+
+ // Run the StoreRange test, which validates StoreRange and initializes
+ // the RangeMap with data for the RetrieveRange test.
+ int stored_count = 0; // The number of ranges successfully stored
+ for (unsigned int range_test_index = 0;
+ range_test_index < range_test_count;
+ ++range_test_index) {
+ const RangeTest* range_test = &range_tests[range_test_index];
+ StoreTest(rmap.get(), range_test);
+
+ if (range_test->expect_storable)
+ ++stored_count;
+ }
+
+ scoped_array<char> memaddr(serializer_.Serialize(*rmap, NULL));
+ scoped_ptr<TestMap> static_range_map(new TestMap(memaddr.get()));
+
+ // The RangeMap's own count of objects should also match.
+ EXPECT_EQ(static_range_map->GetCount(), stored_count);
+
+ // Run the RetrieveRange test
+ for (unsigned int range_test_index = 0;
+ range_test_index < range_test_count;
+ ++range_test_index) {
+ const RangeTest* range_test = &range_tests[range_test_index];
+ RetrieveTest(static_range_map.get(), range_test);
+ }
+
+ RetrieveIndexTest(static_range_map.get(), test_case);
+}
+
+TEST_F(TestStaticRangeMap, TestCase0) {
+ int test_case = 0;
+ RunTestCase(test_case);
+}
+
+TEST_F(TestStaticRangeMap, TestCase1) {
+ int test_case = 1;
+ RunTestCase(test_case);
+}
+
+TEST_F(TestStaticRangeMap, TestCase2) {
+ int test_case = 2;
+ RunTestCase(test_case);
+}
+
+TEST_F(TestStaticRangeMap, TestCase3) {
+ int test_case = 3;
+ RunTestCase(test_case);
+}
+
+TEST_F(TestStaticRangeMap, RunTestCase0Again) {
+ int test_case = 0;
+ RunTestCase(test_case);
+}
+
+} // namespace google_breakpad
+
+int main(int argc, char *argv[]) {
+ ::testing::InitGoogleTest(&argc, argv);
+
+ return RUN_ALL_TESTS();
+}
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/symbolic_constants_win.cc b/toolkit/crashreporter/google-breakpad/src/processor/symbolic_constants_win.cc
new file mode 100644
index 0000000000..e01a46ab1f
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/symbolic_constants_win.cc
@@ -0,0 +1,10958 @@
+// 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.
+
+// ntstatus_reason_win.h: Windows NTSTATUS code to string.
+//
+// Provides a means to convert NTSTATUS codes to strings.
+//
+// Author: Ben Wagner
+
+#include <algorithm>
+#include <string>
+
+#include "common/stdio_wrapper.h"
+#include "google_breakpad/common/breakpad_types.h"
+#include "google_breakpad/common/minidump_exception_win32.h"
+#include "processor/symbolic_constants_win.h"
+
+namespace google_breakpad {
+
+// The content of this array was created from ntstatus.h in the 10 SDK
+// (version 10.0.19041.0) with
+//
+// egrep '#define [A-Z_0-9]+\s+\(\(NTSTATUS\)0x[048C][0-9A-F]+L\)' ntstatus.h
+// | tr -d '\r'
+// | sed -r 's@#define ([A-Z_0-9]+)\s+\(\(NTSTATUS\)(0x[048C][0-9A-F]+)L\).*@\2 \1@'
+// | sort
+// | sed -r 's@(0x[048C][0-9A-F]+) ([A-Z_0-9]+)@ MD_NTSTATUS_WIN_\2,@'
+//
+// With easy copy to clipboard with
+// | xclip -selection c # on linux
+// | clip # on windows
+// | pbcopy # on mac
+static const uint32_t kNTStatusValues[] = {
+ MD_NTSTATUS_WIN_STATUS_SUCCESS,
+ MD_NTSTATUS_WIN_STATUS_WAIT_0,
+ MD_NTSTATUS_WIN_STATUS_WAIT_1,
+ MD_NTSTATUS_WIN_STATUS_WAIT_2,
+ MD_NTSTATUS_WIN_STATUS_WAIT_3,
+ MD_NTSTATUS_WIN_STATUS_WAIT_63,
+ MD_NTSTATUS_WIN_STATUS_ABANDONED,
+ MD_NTSTATUS_WIN_STATUS_ABANDONED_WAIT_0,
+ MD_NTSTATUS_WIN_STATUS_ABANDONED_WAIT_63,
+ MD_NTSTATUS_WIN_STATUS_USER_APC,
+ MD_NTSTATUS_WIN_STATUS_ALREADY_COMPLETE,
+ MD_NTSTATUS_WIN_STATUS_KERNEL_APC,
+ MD_NTSTATUS_WIN_STATUS_ALERTED,
+ MD_NTSTATUS_WIN_STATUS_TIMEOUT,
+ MD_NTSTATUS_WIN_STATUS_PENDING,
+ MD_NTSTATUS_WIN_STATUS_REPARSE,
+ MD_NTSTATUS_WIN_STATUS_MORE_ENTRIES,
+ MD_NTSTATUS_WIN_STATUS_NOT_ALL_ASSIGNED,
+ MD_NTSTATUS_WIN_STATUS_SOME_NOT_MAPPED,
+ MD_NTSTATUS_WIN_STATUS_OPLOCK_BREAK_IN_PROGRESS,
+ MD_NTSTATUS_WIN_STATUS_VOLUME_MOUNTED,
+ MD_NTSTATUS_WIN_STATUS_RXACT_COMMITTED,
+ MD_NTSTATUS_WIN_STATUS_NOTIFY_CLEANUP,
+ MD_NTSTATUS_WIN_STATUS_NOTIFY_ENUM_DIR,
+ MD_NTSTATUS_WIN_STATUS_NO_QUOTAS_FOR_ACCOUNT,
+ MD_NTSTATUS_WIN_STATUS_PRIMARY_TRANSPORT_CONNECT_FAILED,
+ MD_NTSTATUS_WIN_STATUS_PAGE_FAULT_TRANSITION,
+ MD_NTSTATUS_WIN_STATUS_PAGE_FAULT_DEMAND_ZERO,
+ MD_NTSTATUS_WIN_STATUS_PAGE_FAULT_COPY_ON_WRITE,
+ MD_NTSTATUS_WIN_STATUS_PAGE_FAULT_GUARD_PAGE,
+ MD_NTSTATUS_WIN_STATUS_PAGE_FAULT_PAGING_FILE,
+ MD_NTSTATUS_WIN_STATUS_CACHE_PAGE_LOCKED,
+ MD_NTSTATUS_WIN_STATUS_CRASH_DUMP,
+ MD_NTSTATUS_WIN_STATUS_BUFFER_ALL_ZEROS,
+ MD_NTSTATUS_WIN_STATUS_REPARSE_OBJECT,
+ MD_NTSTATUS_WIN_STATUS_RESOURCE_REQUIREMENTS_CHANGED,
+ MD_NTSTATUS_WIN_STATUS_TRANSLATION_COMPLETE,
+ MD_NTSTATUS_WIN_STATUS_DS_MEMBERSHIP_EVALUATED_LOCALLY,
+ MD_NTSTATUS_WIN_STATUS_NOTHING_TO_TERMINATE,
+ MD_NTSTATUS_WIN_STATUS_PROCESS_NOT_IN_JOB,
+ MD_NTSTATUS_WIN_STATUS_PROCESS_IN_JOB,
+ MD_NTSTATUS_WIN_STATUS_VOLSNAP_HIBERNATE_READY,
+ MD_NTSTATUS_WIN_STATUS_FSFILTER_OP_COMPLETED_SUCCESSFULLY,
+ MD_NTSTATUS_WIN_STATUS_INTERRUPT_VECTOR_ALREADY_CONNECTED,
+ MD_NTSTATUS_WIN_STATUS_INTERRUPT_STILL_CONNECTED,
+ MD_NTSTATUS_WIN_STATUS_PROCESS_CLONED,
+ MD_NTSTATUS_WIN_STATUS_FILE_LOCKED_WITH_ONLY_READERS,
+ MD_NTSTATUS_WIN_STATUS_FILE_LOCKED_WITH_WRITERS,
+ MD_NTSTATUS_WIN_STATUS_VALID_IMAGE_HASH,
+ MD_NTSTATUS_WIN_STATUS_VALID_CATALOG_HASH,
+ MD_NTSTATUS_WIN_STATUS_VALID_STRONG_CODE_HASH,
+ MD_NTSTATUS_WIN_STATUS_GHOSTED,
+ MD_NTSTATUS_WIN_STATUS_DATA_OVERWRITTEN,
+ MD_NTSTATUS_WIN_STATUS_RESOURCEMANAGER_READ_ONLY,
+ MD_NTSTATUS_WIN_STATUS_RING_PREVIOUSLY_EMPTY,
+ MD_NTSTATUS_WIN_STATUS_RING_PREVIOUSLY_FULL,
+ MD_NTSTATUS_WIN_STATUS_RING_PREVIOUSLY_ABOVE_QUOTA,
+ MD_NTSTATUS_WIN_STATUS_RING_NEWLY_EMPTY,
+ MD_NTSTATUS_WIN_STATUS_RING_SIGNAL_OPPOSITE_ENDPOINT,
+ MD_NTSTATUS_WIN_STATUS_OPLOCK_SWITCHED_TO_NEW_HANDLE,
+ MD_NTSTATUS_WIN_STATUS_OPLOCK_HANDLE_CLOSED,
+ MD_NTSTATUS_WIN_STATUS_WAIT_FOR_OPLOCK,
+ MD_NTSTATUS_WIN_STATUS_REPARSE_GLOBAL,
+ MD_NTSTATUS_WIN_DBG_EXCEPTION_HANDLED,
+ MD_NTSTATUS_WIN_DBG_CONTINUE,
+ MD_NTSTATUS_WIN_STATUS_FLT_IO_COMPLETE,
+ MD_NTSTATUS_WIN_STATUS_RTPM_CONTEXT_CONTINUE,
+ MD_NTSTATUS_WIN_STATUS_RTPM_CONTEXT_COMPLETE,
+ MD_NTSTATUS_WIN_STATUS_HV_PENDING_PAGE_REQUESTS,
+ MD_NTSTATUS_WIN_STATUS_SPACES_REPAIRED,
+ MD_NTSTATUS_WIN_STATUS_SPACES_PAUSE,
+ MD_NTSTATUS_WIN_STATUS_SPACES_COMPLETE,
+ MD_NTSTATUS_WIN_STATUS_SPACES_REDIRECT,
+ MD_NTSTATUS_WIN_STATUS_OBJECT_NAME_EXISTS,
+ MD_NTSTATUS_WIN_STATUS_THREAD_WAS_SUSPENDED,
+ MD_NTSTATUS_WIN_STATUS_WORKING_SET_LIMIT_RANGE,
+ MD_NTSTATUS_WIN_STATUS_IMAGE_NOT_AT_BASE,
+ MD_NTSTATUS_WIN_STATUS_RXACT_STATE_CREATED,
+ MD_NTSTATUS_WIN_STATUS_SEGMENT_NOTIFICATION,
+ MD_NTSTATUS_WIN_STATUS_LOCAL_USER_SESSION_KEY,
+ MD_NTSTATUS_WIN_STATUS_BAD_CURRENT_DIRECTORY,
+ MD_NTSTATUS_WIN_STATUS_SERIAL_MORE_WRITES,
+ MD_NTSTATUS_WIN_STATUS_REGISTRY_RECOVERED,
+ MD_NTSTATUS_WIN_STATUS_FT_READ_RECOVERY_FROM_BACKUP,
+ MD_NTSTATUS_WIN_STATUS_FT_WRITE_RECOVERY,
+ MD_NTSTATUS_WIN_STATUS_SERIAL_COUNTER_TIMEOUT,
+ MD_NTSTATUS_WIN_STATUS_NULL_LM_PASSWORD,
+ MD_NTSTATUS_WIN_STATUS_IMAGE_MACHINE_TYPE_MISMATCH,
+ MD_NTSTATUS_WIN_STATUS_RECEIVE_PARTIAL,
+ MD_NTSTATUS_WIN_STATUS_RECEIVE_EXPEDITED,
+ MD_NTSTATUS_WIN_STATUS_RECEIVE_PARTIAL_EXPEDITED,
+ MD_NTSTATUS_WIN_STATUS_EVENT_DONE,
+ MD_NTSTATUS_WIN_STATUS_EVENT_PENDING,
+ MD_NTSTATUS_WIN_STATUS_CHECKING_FILE_SYSTEM,
+ MD_NTSTATUS_WIN_STATUS_FATAL_APP_EXIT,
+ MD_NTSTATUS_WIN_STATUS_PREDEFINED_HANDLE,
+ MD_NTSTATUS_WIN_STATUS_WAS_UNLOCKED,
+ MD_NTSTATUS_WIN_STATUS_SERVICE_NOTIFICATION,
+ MD_NTSTATUS_WIN_STATUS_WAS_LOCKED,
+ MD_NTSTATUS_WIN_STATUS_LOG_HARD_ERROR,
+ MD_NTSTATUS_WIN_STATUS_ALREADY_WIN32,
+ MD_NTSTATUS_WIN_STATUS_WX86_UNSIMULATE,
+ MD_NTSTATUS_WIN_STATUS_WX86_CONTINUE,
+ MD_NTSTATUS_WIN_STATUS_WX86_SINGLE_STEP,
+ MD_NTSTATUS_WIN_STATUS_WX86_BREAKPOINT,
+ MD_NTSTATUS_WIN_STATUS_WX86_EXCEPTION_CONTINUE,
+ MD_NTSTATUS_WIN_STATUS_WX86_EXCEPTION_LASTCHANCE,
+ MD_NTSTATUS_WIN_STATUS_WX86_EXCEPTION_CHAIN,
+ MD_NTSTATUS_WIN_STATUS_IMAGE_MACHINE_TYPE_MISMATCH_EXE,
+ MD_NTSTATUS_WIN_STATUS_NO_YIELD_PERFORMED,
+ MD_NTSTATUS_WIN_STATUS_TIMER_RESUME_IGNORED,
+ MD_NTSTATUS_WIN_STATUS_ARBITRATION_UNHANDLED,
+ MD_NTSTATUS_WIN_STATUS_CARDBUS_NOT_SUPPORTED,
+ MD_NTSTATUS_WIN_STATUS_WX86_CREATEWX86TIB,
+ MD_NTSTATUS_WIN_STATUS_MP_PROCESSOR_MISMATCH,
+ MD_NTSTATUS_WIN_STATUS_HIBERNATED,
+ MD_NTSTATUS_WIN_STATUS_RESUME_HIBERNATION,
+ MD_NTSTATUS_WIN_STATUS_FIRMWARE_UPDATED,
+ MD_NTSTATUS_WIN_STATUS_DRIVERS_LEAKING_LOCKED_PAGES,
+ MD_NTSTATUS_WIN_STATUS_MESSAGE_RETRIEVED,
+ MD_NTSTATUS_WIN_STATUS_SYSTEM_POWERSTATE_TRANSITION,
+ MD_NTSTATUS_WIN_STATUS_ALPC_CHECK_COMPLETION_LIST,
+ MD_NTSTATUS_WIN_STATUS_SYSTEM_POWERSTATE_COMPLEX_TRANSITION,
+ MD_NTSTATUS_WIN_STATUS_ACCESS_AUDIT_BY_POLICY,
+ MD_NTSTATUS_WIN_STATUS_ABANDON_HIBERFILE,
+ MD_NTSTATUS_WIN_STATUS_BIZRULES_NOT_ENABLED,
+ MD_NTSTATUS_WIN_STATUS_FT_READ_FROM_COPY,
+ MD_NTSTATUS_WIN_STATUS_IMAGE_AT_DIFFERENT_BASE,
+ MD_NTSTATUS_WIN_STATUS_PATCH_DEFERRED,
+ MD_NTSTATUS_WIN_STATUS_WAKE_SYSTEM,
+ MD_NTSTATUS_WIN_STATUS_DS_SHUTTING_DOWN,
+ MD_NTSTATUS_WIN_STATUS_DISK_REPAIR_REDIRECTED,
+ MD_NTSTATUS_WIN_STATUS_SERVICES_FAILED_AUTOSTART,
+ MD_NTSTATUS_WIN_DBG_REPLY_LATER,
+ MD_NTSTATUS_WIN_DBG_UNABLE_TO_PROVIDE_HANDLE,
+ MD_NTSTATUS_WIN_DBG_TERMINATE_THREAD,
+ MD_NTSTATUS_WIN_DBG_TERMINATE_PROCESS,
+ MD_NTSTATUS_WIN_DBG_CONTROL_C,
+ MD_NTSTATUS_WIN_DBG_PRINTEXCEPTION_C,
+ MD_NTSTATUS_WIN_DBG_RIPEXCEPTION,
+ MD_NTSTATUS_WIN_DBG_CONTROL_BREAK,
+ MD_NTSTATUS_WIN_DBG_COMMAND_EXCEPTION,
+ MD_NTSTATUS_WIN_DBG_PRINTEXCEPTION_WIDE_C,
+ MD_NTSTATUS_WIN_RPC_NT_UUID_LOCAL_ONLY,
+ MD_NTSTATUS_WIN_RPC_NT_SEND_INCOMPLETE,
+ MD_NTSTATUS_WIN_STATUS_CTX_CDM_CONNECT,
+ MD_NTSTATUS_WIN_STATUS_CTX_CDM_DISCONNECT,
+ MD_NTSTATUS_WIN_STATUS_SXS_RELEASE_ACTIVATION_CONTEXT,
+ MD_NTSTATUS_WIN_STATUS_HEURISTIC_DAMAGE_POSSIBLE,
+ MD_NTSTATUS_WIN_STATUS_RECOVERY_NOT_NEEDED,
+ MD_NTSTATUS_WIN_STATUS_RM_ALREADY_STARTED,
+ MD_NTSTATUS_WIN_STATUS_LOG_NO_RESTART,
+ MD_NTSTATUS_WIN_STATUS_VIDEO_DRIVER_DEBUG_REPORT_REQUEST,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_PARTIAL_DATA_POPULATED,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_SKIP_ALLOCATION_PREPARATION,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_MODE_NOT_PINNED,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_NO_PREFERRED_MODE,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_DATASET_IS_EMPTY,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_NO_MORE_ELEMENTS_IN_DATASET,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_PATH_CONTENT_GEOMETRY_TRANSFORMATION_NOT_PINNED,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_UNKNOWN_CHILD_STATUS,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_LEADLINK_START_DEFERRED,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_POLLING_TOO_FREQUENTLY,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_START_DEFERRED,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_DEPENDABLE_CHILD_STATUS,
+ MD_NTSTATUS_WIN_STATUS_NDIS_INDICATION_REQUIRED,
+ MD_NTSTATUS_WIN_STATUS_PCP_UNSUPPORTED_PSS_SALT,
+ MD_NTSTATUS_WIN_STATUS_GUARD_PAGE_VIOLATION,
+ MD_NTSTATUS_WIN_STATUS_DATATYPE_MISALIGNMENT,
+ MD_NTSTATUS_WIN_STATUS_BREAKPOINT,
+ MD_NTSTATUS_WIN_STATUS_SINGLE_STEP,
+ MD_NTSTATUS_WIN_STATUS_BUFFER_OVERFLOW,
+ MD_NTSTATUS_WIN_STATUS_NO_MORE_FILES,
+ MD_NTSTATUS_WIN_STATUS_WAKE_SYSTEM_DEBUGGER,
+ MD_NTSTATUS_WIN_STATUS_HANDLES_CLOSED,
+ MD_NTSTATUS_WIN_STATUS_NO_INHERITANCE,
+ MD_NTSTATUS_WIN_STATUS_GUID_SUBSTITUTION_MADE,
+ MD_NTSTATUS_WIN_STATUS_PARTIAL_COPY,
+ MD_NTSTATUS_WIN_STATUS_DEVICE_PAPER_EMPTY,
+ MD_NTSTATUS_WIN_STATUS_DEVICE_POWERED_OFF,
+ MD_NTSTATUS_WIN_STATUS_DEVICE_OFF_LINE,
+ MD_NTSTATUS_WIN_STATUS_DEVICE_BUSY,
+ MD_NTSTATUS_WIN_STATUS_NO_MORE_EAS,
+ MD_NTSTATUS_WIN_STATUS_INVALID_EA_NAME,
+ MD_NTSTATUS_WIN_STATUS_EA_LIST_INCONSISTENT,
+ MD_NTSTATUS_WIN_STATUS_INVALID_EA_FLAG,
+ MD_NTSTATUS_WIN_STATUS_VERIFY_REQUIRED,
+ MD_NTSTATUS_WIN_STATUS_EXTRANEOUS_INFORMATION,
+ MD_NTSTATUS_WIN_STATUS_RXACT_COMMIT_NECESSARY,
+ MD_NTSTATUS_WIN_STATUS_NO_MORE_ENTRIES,
+ MD_NTSTATUS_WIN_STATUS_FILEMARK_DETECTED,
+ MD_NTSTATUS_WIN_STATUS_MEDIA_CHANGED,
+ MD_NTSTATUS_WIN_STATUS_BUS_RESET,
+ MD_NTSTATUS_WIN_STATUS_END_OF_MEDIA,
+ MD_NTSTATUS_WIN_STATUS_BEGINNING_OF_MEDIA,
+ MD_NTSTATUS_WIN_STATUS_MEDIA_CHECK,
+ MD_NTSTATUS_WIN_STATUS_SETMARK_DETECTED,
+ MD_NTSTATUS_WIN_STATUS_NO_DATA_DETECTED,
+ MD_NTSTATUS_WIN_STATUS_REDIRECTOR_HAS_OPEN_HANDLES,
+ MD_NTSTATUS_WIN_STATUS_SERVER_HAS_OPEN_HANDLES,
+ MD_NTSTATUS_WIN_STATUS_ALREADY_DISCONNECTED,
+ MD_NTSTATUS_WIN_STATUS_LONGJUMP,
+ MD_NTSTATUS_WIN_STATUS_CLEANER_CARTRIDGE_INSTALLED,
+ MD_NTSTATUS_WIN_STATUS_PLUGPLAY_QUERY_VETOED,
+ MD_NTSTATUS_WIN_STATUS_UNWIND_CONSOLIDATE,
+ MD_NTSTATUS_WIN_STATUS_REGISTRY_HIVE_RECOVERED,
+ MD_NTSTATUS_WIN_STATUS_DLL_MIGHT_BE_INSECURE,
+ MD_NTSTATUS_WIN_STATUS_DLL_MIGHT_BE_INCOMPATIBLE,
+ MD_NTSTATUS_WIN_STATUS_STOPPED_ON_SYMLINK,
+ MD_NTSTATUS_WIN_STATUS_CANNOT_GRANT_REQUESTED_OPLOCK,
+ MD_NTSTATUS_WIN_STATUS_NO_ACE_CONDITION,
+ MD_NTSTATUS_WIN_STATUS_DEVICE_SUPPORT_IN_PROGRESS,
+ MD_NTSTATUS_WIN_STATUS_DEVICE_POWER_CYCLE_REQUIRED,
+ MD_NTSTATUS_WIN_STATUS_NO_WORK_DONE,
+ MD_NTSTATUS_WIN_STATUS_RETURN_ADDRESS_HIJACK_ATTEMPT,
+ MD_NTSTATUS_WIN_STATUS_DEVICE_REQUIRES_CLEANING,
+ MD_NTSTATUS_WIN_STATUS_DEVICE_DOOR_OPEN,
+ MD_NTSTATUS_WIN_STATUS_DATA_LOST_REPAIR,
+ MD_NTSTATUS_WIN_STATUS_GPIO_INTERRUPT_ALREADY_UNMASKED,
+ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_PROPERTY_BLOB_CHECKSUM_MISMATCH,
+ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_PROPERTY_BLOB_TOO_LARGE,
+ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_TOO_MANY_PROPERTY_BLOBS,
+ MD_NTSTATUS_WIN_DBG_EXCEPTION_NOT_HANDLED,
+ MD_NTSTATUS_WIN_STATUS_CLUSTER_NODE_ALREADY_UP,
+ MD_NTSTATUS_WIN_STATUS_CLUSTER_NODE_ALREADY_DOWN,
+ MD_NTSTATUS_WIN_STATUS_CLUSTER_NETWORK_ALREADY_ONLINE,
+ MD_NTSTATUS_WIN_STATUS_CLUSTER_NETWORK_ALREADY_OFFLINE,
+ MD_NTSTATUS_WIN_STATUS_CLUSTER_NODE_ALREADY_MEMBER,
+ MD_NTSTATUS_WIN_STATUS_COULD_NOT_RESIZE_LOG,
+ MD_NTSTATUS_WIN_STATUS_NO_TXF_METADATA,
+ MD_NTSTATUS_WIN_STATUS_CANT_RECOVER_WITH_HANDLE_OPEN,
+ MD_NTSTATUS_WIN_STATUS_TXF_METADATA_ALREADY_PRESENT,
+ MD_NTSTATUS_WIN_STATUS_TRANSACTION_SCOPE_CALLBACKS_NOT_SET,
+ MD_NTSTATUS_WIN_STATUS_VIDEO_HUNG_DISPLAY_DRIVER_THREAD_RECOVERED,
+ MD_NTSTATUS_WIN_STATUS_FLT_BUFFER_TOO_SMALL,
+ MD_NTSTATUS_WIN_STATUS_FVE_PARTIAL_METADATA,
+ MD_NTSTATUS_WIN_STATUS_FVE_TRANSIENT_STATE,
+ MD_NTSTATUS_WIN_STATUS_VID_REMOTE_NODE_PARENT_GPA_PAGES_USED,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_INCOMPLETE_REGENERATION,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_INCOMPLETE_DISK_MIGRATION,
+ MD_NTSTATUS_WIN_STATUS_BCD_NOT_ALL_ENTRIES_IMPORTED,
+ MD_NTSTATUS_WIN_STATUS_BCD_NOT_ALL_ENTRIES_SYNCHRONIZED,
+ MD_NTSTATUS_WIN_STATUS_QUERY_STORAGE_ERROR,
+ MD_NTSTATUS_WIN_STATUS_GDI_HANDLE_LEAK,
+ MD_NTSTATUS_WIN_STATUS_SECUREBOOT_NOT_ENABLED,
+ MD_NTSTATUS_WIN_STATUS_UNSUCCESSFUL,
+ MD_NTSTATUS_WIN_STATUS_NOT_IMPLEMENTED,
+ MD_NTSTATUS_WIN_STATUS_INVALID_INFO_CLASS,
+ MD_NTSTATUS_WIN_STATUS_INFO_LENGTH_MISMATCH,
+ MD_NTSTATUS_WIN_STATUS_ACCESS_VIOLATION,
+ MD_NTSTATUS_WIN_STATUS_IN_PAGE_ERROR,
+ MD_NTSTATUS_WIN_STATUS_PAGEFILE_QUOTA,
+ MD_NTSTATUS_WIN_STATUS_INVALID_HANDLE,
+ MD_NTSTATUS_WIN_STATUS_BAD_INITIAL_STACK,
+ MD_NTSTATUS_WIN_STATUS_BAD_INITIAL_PC,
+ MD_NTSTATUS_WIN_STATUS_INVALID_CID,
+ MD_NTSTATUS_WIN_STATUS_TIMER_NOT_CANCELED,
+ MD_NTSTATUS_WIN_STATUS_INVALID_PARAMETER,
+ MD_NTSTATUS_WIN_STATUS_NO_SUCH_DEVICE,
+ MD_NTSTATUS_WIN_STATUS_NO_SUCH_FILE,
+ MD_NTSTATUS_WIN_STATUS_INVALID_DEVICE_REQUEST,
+ MD_NTSTATUS_WIN_STATUS_END_OF_FILE,
+ MD_NTSTATUS_WIN_STATUS_WRONG_VOLUME,
+ MD_NTSTATUS_WIN_STATUS_NO_MEDIA_IN_DEVICE,
+ MD_NTSTATUS_WIN_STATUS_UNRECOGNIZED_MEDIA,
+ MD_NTSTATUS_WIN_STATUS_NONEXISTENT_SECTOR,
+ MD_NTSTATUS_WIN_STATUS_MORE_PROCESSING_REQUIRED,
+ MD_NTSTATUS_WIN_STATUS_NO_MEMORY,
+ MD_NTSTATUS_WIN_STATUS_CONFLICTING_ADDRESSES,
+ MD_NTSTATUS_WIN_STATUS_NOT_MAPPED_VIEW,
+ MD_NTSTATUS_WIN_STATUS_UNABLE_TO_FREE_VM,
+ MD_NTSTATUS_WIN_STATUS_UNABLE_TO_DELETE_SECTION,
+ MD_NTSTATUS_WIN_STATUS_INVALID_SYSTEM_SERVICE,
+ MD_NTSTATUS_WIN_STATUS_ILLEGAL_INSTRUCTION,
+ MD_NTSTATUS_WIN_STATUS_INVALID_LOCK_SEQUENCE,
+ MD_NTSTATUS_WIN_STATUS_INVALID_VIEW_SIZE,
+ MD_NTSTATUS_WIN_STATUS_INVALID_FILE_FOR_SECTION,
+ MD_NTSTATUS_WIN_STATUS_ALREADY_COMMITTED,
+ MD_NTSTATUS_WIN_STATUS_ACCESS_DENIED,
+ MD_NTSTATUS_WIN_STATUS_BUFFER_TOO_SMALL,
+ MD_NTSTATUS_WIN_STATUS_OBJECT_TYPE_MISMATCH,
+ MD_NTSTATUS_WIN_STATUS_NONCONTINUABLE_EXCEPTION,
+ MD_NTSTATUS_WIN_STATUS_INVALID_DISPOSITION,
+ MD_NTSTATUS_WIN_STATUS_UNWIND,
+ MD_NTSTATUS_WIN_STATUS_BAD_STACK,
+ MD_NTSTATUS_WIN_STATUS_INVALID_UNWIND_TARGET,
+ MD_NTSTATUS_WIN_STATUS_NOT_LOCKED,
+ MD_NTSTATUS_WIN_STATUS_PARITY_ERROR,
+ MD_NTSTATUS_WIN_STATUS_UNABLE_TO_DECOMMIT_VM,
+ MD_NTSTATUS_WIN_STATUS_NOT_COMMITTED,
+ MD_NTSTATUS_WIN_STATUS_INVALID_PORT_ATTRIBUTES,
+ MD_NTSTATUS_WIN_STATUS_PORT_MESSAGE_TOO_LONG,
+ MD_NTSTATUS_WIN_STATUS_INVALID_PARAMETER_MIX,
+ MD_NTSTATUS_WIN_STATUS_INVALID_QUOTA_LOWER,
+ MD_NTSTATUS_WIN_STATUS_DISK_CORRUPT_ERROR,
+ MD_NTSTATUS_WIN_STATUS_OBJECT_NAME_INVALID,
+ MD_NTSTATUS_WIN_STATUS_OBJECT_NAME_NOT_FOUND,
+ MD_NTSTATUS_WIN_STATUS_OBJECT_NAME_COLLISION,
+ MD_NTSTATUS_WIN_STATUS_PORT_DO_NOT_DISTURB,
+ MD_NTSTATUS_WIN_STATUS_PORT_DISCONNECTED,
+ MD_NTSTATUS_WIN_STATUS_DEVICE_ALREADY_ATTACHED,
+ MD_NTSTATUS_WIN_STATUS_OBJECT_PATH_INVALID,
+ MD_NTSTATUS_WIN_STATUS_OBJECT_PATH_NOT_FOUND,
+ MD_NTSTATUS_WIN_STATUS_OBJECT_PATH_SYNTAX_BAD,
+ MD_NTSTATUS_WIN_STATUS_DATA_OVERRUN,
+ MD_NTSTATUS_WIN_STATUS_DATA_LATE_ERROR,
+ MD_NTSTATUS_WIN_STATUS_DATA_ERROR,
+ MD_NTSTATUS_WIN_STATUS_CRC_ERROR,
+ MD_NTSTATUS_WIN_STATUS_SECTION_TOO_BIG,
+ MD_NTSTATUS_WIN_STATUS_PORT_CONNECTION_REFUSED,
+ MD_NTSTATUS_WIN_STATUS_INVALID_PORT_HANDLE,
+ MD_NTSTATUS_WIN_STATUS_SHARING_VIOLATION,
+ MD_NTSTATUS_WIN_STATUS_QUOTA_EXCEEDED,
+ MD_NTSTATUS_WIN_STATUS_INVALID_PAGE_PROTECTION,
+ MD_NTSTATUS_WIN_STATUS_MUTANT_NOT_OWNED,
+ MD_NTSTATUS_WIN_STATUS_SEMAPHORE_LIMIT_EXCEEDED,
+ MD_NTSTATUS_WIN_STATUS_PORT_ALREADY_SET,
+ MD_NTSTATUS_WIN_STATUS_SECTION_NOT_IMAGE,
+ MD_NTSTATUS_WIN_STATUS_SUSPEND_COUNT_EXCEEDED,
+ MD_NTSTATUS_WIN_STATUS_THREAD_IS_TERMINATING,
+ MD_NTSTATUS_WIN_STATUS_BAD_WORKING_SET_LIMIT,
+ MD_NTSTATUS_WIN_STATUS_INCOMPATIBLE_FILE_MAP,
+ MD_NTSTATUS_WIN_STATUS_SECTION_PROTECTION,
+ MD_NTSTATUS_WIN_STATUS_EAS_NOT_SUPPORTED,
+ MD_NTSTATUS_WIN_STATUS_EA_TOO_LARGE,
+ MD_NTSTATUS_WIN_STATUS_NONEXISTENT_EA_ENTRY,
+ MD_NTSTATUS_WIN_STATUS_NO_EAS_ON_FILE,
+ MD_NTSTATUS_WIN_STATUS_EA_CORRUPT_ERROR,
+ MD_NTSTATUS_WIN_STATUS_FILE_LOCK_CONFLICT,
+ MD_NTSTATUS_WIN_STATUS_LOCK_NOT_GRANTED,
+ MD_NTSTATUS_WIN_STATUS_DELETE_PENDING,
+ MD_NTSTATUS_WIN_STATUS_CTL_FILE_NOT_SUPPORTED,
+ MD_NTSTATUS_WIN_STATUS_UNKNOWN_REVISION,
+ MD_NTSTATUS_WIN_STATUS_REVISION_MISMATCH,
+ MD_NTSTATUS_WIN_STATUS_INVALID_OWNER,
+ MD_NTSTATUS_WIN_STATUS_INVALID_PRIMARY_GROUP,
+ MD_NTSTATUS_WIN_STATUS_NO_IMPERSONATION_TOKEN,
+ MD_NTSTATUS_WIN_STATUS_CANT_DISABLE_MANDATORY,
+ MD_NTSTATUS_WIN_STATUS_NO_LOGON_SERVERS,
+ MD_NTSTATUS_WIN_STATUS_NO_SUCH_LOGON_SESSION,
+ MD_NTSTATUS_WIN_STATUS_NO_SUCH_PRIVILEGE,
+ MD_NTSTATUS_WIN_STATUS_PRIVILEGE_NOT_HELD,
+ MD_NTSTATUS_WIN_STATUS_INVALID_ACCOUNT_NAME,
+ MD_NTSTATUS_WIN_STATUS_USER_EXISTS,
+ MD_NTSTATUS_WIN_STATUS_NO_SUCH_USER,
+ MD_NTSTATUS_WIN_STATUS_GROUP_EXISTS,
+ MD_NTSTATUS_WIN_STATUS_NO_SUCH_GROUP,
+ MD_NTSTATUS_WIN_STATUS_MEMBER_IN_GROUP,
+ MD_NTSTATUS_WIN_STATUS_MEMBER_NOT_IN_GROUP,
+ MD_NTSTATUS_WIN_STATUS_LAST_ADMIN,
+ MD_NTSTATUS_WIN_STATUS_WRONG_PASSWORD,
+ MD_NTSTATUS_WIN_STATUS_ILL_FORMED_PASSWORD,
+ MD_NTSTATUS_WIN_STATUS_PASSWORD_RESTRICTION,
+ MD_NTSTATUS_WIN_STATUS_LOGON_FAILURE,
+ MD_NTSTATUS_WIN_STATUS_ACCOUNT_RESTRICTION,
+ MD_NTSTATUS_WIN_STATUS_INVALID_LOGON_HOURS,
+ MD_NTSTATUS_WIN_STATUS_INVALID_WORKSTATION,
+ MD_NTSTATUS_WIN_STATUS_PASSWORD_EXPIRED,
+ MD_NTSTATUS_WIN_STATUS_ACCOUNT_DISABLED,
+ MD_NTSTATUS_WIN_STATUS_NONE_MAPPED,
+ MD_NTSTATUS_WIN_STATUS_TOO_MANY_LUIDS_REQUESTED,
+ MD_NTSTATUS_WIN_STATUS_LUIDS_EXHAUSTED,
+ MD_NTSTATUS_WIN_STATUS_INVALID_SUB_AUTHORITY,
+ MD_NTSTATUS_WIN_STATUS_INVALID_ACL,
+ MD_NTSTATUS_WIN_STATUS_INVALID_SID,
+ MD_NTSTATUS_WIN_STATUS_INVALID_SECURITY_DESCR,
+ MD_NTSTATUS_WIN_STATUS_PROCEDURE_NOT_FOUND,
+ MD_NTSTATUS_WIN_STATUS_INVALID_IMAGE_FORMAT,
+ MD_NTSTATUS_WIN_STATUS_NO_TOKEN,
+ MD_NTSTATUS_WIN_STATUS_BAD_INHERITANCE_ACL,
+ MD_NTSTATUS_WIN_STATUS_RANGE_NOT_LOCKED,
+ MD_NTSTATUS_WIN_STATUS_DISK_FULL,
+ MD_NTSTATUS_WIN_STATUS_SERVER_DISABLED,
+ MD_NTSTATUS_WIN_STATUS_SERVER_NOT_DISABLED,
+ MD_NTSTATUS_WIN_STATUS_TOO_MANY_GUIDS_REQUESTED,
+ MD_NTSTATUS_WIN_STATUS_GUIDS_EXHAUSTED,
+ MD_NTSTATUS_WIN_STATUS_INVALID_ID_AUTHORITY,
+ MD_NTSTATUS_WIN_STATUS_AGENTS_EXHAUSTED,
+ MD_NTSTATUS_WIN_STATUS_INVALID_VOLUME_LABEL,
+ MD_NTSTATUS_WIN_STATUS_SECTION_NOT_EXTENDED,
+ MD_NTSTATUS_WIN_STATUS_NOT_MAPPED_DATA,
+ MD_NTSTATUS_WIN_STATUS_RESOURCE_DATA_NOT_FOUND,
+ MD_NTSTATUS_WIN_STATUS_RESOURCE_TYPE_NOT_FOUND,
+ MD_NTSTATUS_WIN_STATUS_RESOURCE_NAME_NOT_FOUND,
+ MD_NTSTATUS_WIN_STATUS_ARRAY_BOUNDS_EXCEEDED,
+ MD_NTSTATUS_WIN_STATUS_FLOAT_DENORMAL_OPERAND,
+ MD_NTSTATUS_WIN_STATUS_FLOAT_DIVIDE_BY_ZERO,
+ MD_NTSTATUS_WIN_STATUS_FLOAT_INEXACT_RESULT,
+ MD_NTSTATUS_WIN_STATUS_FLOAT_INVALID_OPERATION,
+ MD_NTSTATUS_WIN_STATUS_FLOAT_OVERFLOW,
+ MD_NTSTATUS_WIN_STATUS_FLOAT_STACK_CHECK,
+ MD_NTSTATUS_WIN_STATUS_FLOAT_UNDERFLOW,
+ MD_NTSTATUS_WIN_STATUS_INTEGER_DIVIDE_BY_ZERO,
+ MD_NTSTATUS_WIN_STATUS_INTEGER_OVERFLOW,
+ MD_NTSTATUS_WIN_STATUS_PRIVILEGED_INSTRUCTION,
+ MD_NTSTATUS_WIN_STATUS_TOO_MANY_PAGING_FILES,
+ MD_NTSTATUS_WIN_STATUS_FILE_INVALID,
+ MD_NTSTATUS_WIN_STATUS_ALLOTTED_SPACE_EXCEEDED,
+ MD_NTSTATUS_WIN_STATUS_INSUFFICIENT_RESOURCES,
+ MD_NTSTATUS_WIN_STATUS_DFS_EXIT_PATH_FOUND,
+ MD_NTSTATUS_WIN_STATUS_DEVICE_DATA_ERROR,
+ MD_NTSTATUS_WIN_STATUS_DEVICE_NOT_CONNECTED,
+ MD_NTSTATUS_WIN_STATUS_DEVICE_POWER_FAILURE,
+ MD_NTSTATUS_WIN_STATUS_FREE_VM_NOT_AT_BASE,
+ MD_NTSTATUS_WIN_STATUS_MEMORY_NOT_ALLOCATED,
+ MD_NTSTATUS_WIN_STATUS_WORKING_SET_QUOTA,
+ MD_NTSTATUS_WIN_STATUS_MEDIA_WRITE_PROTECTED,
+ MD_NTSTATUS_WIN_STATUS_DEVICE_NOT_READY,
+ MD_NTSTATUS_WIN_STATUS_INVALID_GROUP_ATTRIBUTES,
+ MD_NTSTATUS_WIN_STATUS_BAD_IMPERSONATION_LEVEL,
+ MD_NTSTATUS_WIN_STATUS_CANT_OPEN_ANONYMOUS,
+ MD_NTSTATUS_WIN_STATUS_BAD_VALIDATION_CLASS,
+ MD_NTSTATUS_WIN_STATUS_BAD_TOKEN_TYPE,
+ MD_NTSTATUS_WIN_STATUS_BAD_MASTER_BOOT_RECORD,
+ MD_NTSTATUS_WIN_STATUS_INSTRUCTION_MISALIGNMENT,
+ MD_NTSTATUS_WIN_STATUS_INSTANCE_NOT_AVAILABLE,
+ MD_NTSTATUS_WIN_STATUS_PIPE_NOT_AVAILABLE,
+ MD_NTSTATUS_WIN_STATUS_INVALID_PIPE_STATE,
+ MD_NTSTATUS_WIN_STATUS_PIPE_BUSY,
+ MD_NTSTATUS_WIN_STATUS_ILLEGAL_FUNCTION,
+ MD_NTSTATUS_WIN_STATUS_PIPE_DISCONNECTED,
+ MD_NTSTATUS_WIN_STATUS_PIPE_CLOSING,
+ MD_NTSTATUS_WIN_STATUS_PIPE_CONNECTED,
+ MD_NTSTATUS_WIN_STATUS_PIPE_LISTENING,
+ MD_NTSTATUS_WIN_STATUS_INVALID_READ_MODE,
+ MD_NTSTATUS_WIN_STATUS_IO_TIMEOUT,
+ MD_NTSTATUS_WIN_STATUS_FILE_FORCED_CLOSED,
+ MD_NTSTATUS_WIN_STATUS_PROFILING_NOT_STARTED,
+ MD_NTSTATUS_WIN_STATUS_PROFILING_NOT_STOPPED,
+ MD_NTSTATUS_WIN_STATUS_COULD_NOT_INTERPRET,
+ MD_NTSTATUS_WIN_STATUS_FILE_IS_A_DIRECTORY,
+ MD_NTSTATUS_WIN_STATUS_NOT_SUPPORTED,
+ MD_NTSTATUS_WIN_STATUS_REMOTE_NOT_LISTENING,
+ MD_NTSTATUS_WIN_STATUS_DUPLICATE_NAME,
+ MD_NTSTATUS_WIN_STATUS_BAD_NETWORK_PATH,
+ MD_NTSTATUS_WIN_STATUS_NETWORK_BUSY,
+ MD_NTSTATUS_WIN_STATUS_DEVICE_DOES_NOT_EXIST,
+ MD_NTSTATUS_WIN_STATUS_TOO_MANY_COMMANDS,
+ MD_NTSTATUS_WIN_STATUS_ADAPTER_HARDWARE_ERROR,
+ MD_NTSTATUS_WIN_STATUS_INVALID_NETWORK_RESPONSE,
+ MD_NTSTATUS_WIN_STATUS_UNEXPECTED_NETWORK_ERROR,
+ MD_NTSTATUS_WIN_STATUS_BAD_REMOTE_ADAPTER,
+ MD_NTSTATUS_WIN_STATUS_PRINT_QUEUE_FULL,
+ MD_NTSTATUS_WIN_STATUS_NO_SPOOL_SPACE,
+ MD_NTSTATUS_WIN_STATUS_PRINT_CANCELLED,
+ MD_NTSTATUS_WIN_STATUS_NETWORK_NAME_DELETED,
+ MD_NTSTATUS_WIN_STATUS_NETWORK_ACCESS_DENIED,
+ MD_NTSTATUS_WIN_STATUS_BAD_DEVICE_TYPE,
+ MD_NTSTATUS_WIN_STATUS_BAD_NETWORK_NAME,
+ MD_NTSTATUS_WIN_STATUS_TOO_MANY_NAMES,
+ MD_NTSTATUS_WIN_STATUS_TOO_MANY_SESSIONS,
+ MD_NTSTATUS_WIN_STATUS_SHARING_PAUSED,
+ MD_NTSTATUS_WIN_STATUS_REQUEST_NOT_ACCEPTED,
+ MD_NTSTATUS_WIN_STATUS_REDIRECTOR_PAUSED,
+ MD_NTSTATUS_WIN_STATUS_NET_WRITE_FAULT,
+ MD_NTSTATUS_WIN_STATUS_PROFILING_AT_LIMIT,
+ MD_NTSTATUS_WIN_STATUS_NOT_SAME_DEVICE,
+ MD_NTSTATUS_WIN_STATUS_FILE_RENAMED,
+ MD_NTSTATUS_WIN_STATUS_VIRTUAL_CIRCUIT_CLOSED,
+ MD_NTSTATUS_WIN_STATUS_NO_SECURITY_ON_OBJECT,
+ MD_NTSTATUS_WIN_STATUS_CANT_WAIT,
+ MD_NTSTATUS_WIN_STATUS_PIPE_EMPTY,
+ MD_NTSTATUS_WIN_STATUS_CANT_ACCESS_DOMAIN_INFO,
+ MD_NTSTATUS_WIN_STATUS_CANT_TERMINATE_SELF,
+ MD_NTSTATUS_WIN_STATUS_INVALID_SERVER_STATE,
+ MD_NTSTATUS_WIN_STATUS_INVALID_DOMAIN_STATE,
+ MD_NTSTATUS_WIN_STATUS_INVALID_DOMAIN_ROLE,
+ MD_NTSTATUS_WIN_STATUS_NO_SUCH_DOMAIN,
+ MD_NTSTATUS_WIN_STATUS_DOMAIN_EXISTS,
+ MD_NTSTATUS_WIN_STATUS_DOMAIN_LIMIT_EXCEEDED,
+ MD_NTSTATUS_WIN_STATUS_OPLOCK_NOT_GRANTED,
+ MD_NTSTATUS_WIN_STATUS_INVALID_OPLOCK_PROTOCOL,
+ MD_NTSTATUS_WIN_STATUS_INTERNAL_DB_CORRUPTION,
+ MD_NTSTATUS_WIN_STATUS_INTERNAL_ERROR,
+ MD_NTSTATUS_WIN_STATUS_GENERIC_NOT_MAPPED,
+ MD_NTSTATUS_WIN_STATUS_BAD_DESCRIPTOR_FORMAT,
+ MD_NTSTATUS_WIN_STATUS_INVALID_USER_BUFFER,
+ MD_NTSTATUS_WIN_STATUS_UNEXPECTED_IO_ERROR,
+ MD_NTSTATUS_WIN_STATUS_UNEXPECTED_MM_CREATE_ERR,
+ MD_NTSTATUS_WIN_STATUS_UNEXPECTED_MM_MAP_ERROR,
+ MD_NTSTATUS_WIN_STATUS_UNEXPECTED_MM_EXTEND_ERR,
+ MD_NTSTATUS_WIN_STATUS_NOT_LOGON_PROCESS,
+ MD_NTSTATUS_WIN_STATUS_LOGON_SESSION_EXISTS,
+ MD_NTSTATUS_WIN_STATUS_INVALID_PARAMETER_1,
+ MD_NTSTATUS_WIN_STATUS_INVALID_PARAMETER_2,
+ MD_NTSTATUS_WIN_STATUS_INVALID_PARAMETER_3,
+ MD_NTSTATUS_WIN_STATUS_INVALID_PARAMETER_4,
+ MD_NTSTATUS_WIN_STATUS_INVALID_PARAMETER_5,
+ MD_NTSTATUS_WIN_STATUS_INVALID_PARAMETER_6,
+ MD_NTSTATUS_WIN_STATUS_INVALID_PARAMETER_7,
+ MD_NTSTATUS_WIN_STATUS_INVALID_PARAMETER_8,
+ MD_NTSTATUS_WIN_STATUS_INVALID_PARAMETER_9,
+ MD_NTSTATUS_WIN_STATUS_INVALID_PARAMETER_10,
+ MD_NTSTATUS_WIN_STATUS_INVALID_PARAMETER_11,
+ MD_NTSTATUS_WIN_STATUS_INVALID_PARAMETER_12,
+ MD_NTSTATUS_WIN_STATUS_REDIRECTOR_NOT_STARTED,
+ MD_NTSTATUS_WIN_STATUS_REDIRECTOR_STARTED,
+ MD_NTSTATUS_WIN_STATUS_STACK_OVERFLOW,
+ MD_NTSTATUS_WIN_STATUS_NO_SUCH_PACKAGE,
+ MD_NTSTATUS_WIN_STATUS_BAD_FUNCTION_TABLE,
+ MD_NTSTATUS_WIN_STATUS_VARIABLE_NOT_FOUND,
+ MD_NTSTATUS_WIN_STATUS_DIRECTORY_NOT_EMPTY,
+ MD_NTSTATUS_WIN_STATUS_FILE_CORRUPT_ERROR,
+ MD_NTSTATUS_WIN_STATUS_NOT_A_DIRECTORY,
+ MD_NTSTATUS_WIN_STATUS_BAD_LOGON_SESSION_STATE,
+ MD_NTSTATUS_WIN_STATUS_LOGON_SESSION_COLLISION,
+ MD_NTSTATUS_WIN_STATUS_NAME_TOO_LONG,
+ MD_NTSTATUS_WIN_STATUS_FILES_OPEN,
+ MD_NTSTATUS_WIN_STATUS_CONNECTION_IN_USE,
+ MD_NTSTATUS_WIN_STATUS_MESSAGE_NOT_FOUND,
+ MD_NTSTATUS_WIN_STATUS_PROCESS_IS_TERMINATING,
+ MD_NTSTATUS_WIN_STATUS_INVALID_LOGON_TYPE,
+ MD_NTSTATUS_WIN_STATUS_NO_GUID_TRANSLATION,
+ MD_NTSTATUS_WIN_STATUS_CANNOT_IMPERSONATE,
+ MD_NTSTATUS_WIN_STATUS_IMAGE_ALREADY_LOADED,
+ MD_NTSTATUS_WIN_STATUS_ABIOS_NOT_PRESENT,
+ MD_NTSTATUS_WIN_STATUS_ABIOS_LID_NOT_EXIST,
+ MD_NTSTATUS_WIN_STATUS_ABIOS_LID_ALREADY_OWNED,
+ MD_NTSTATUS_WIN_STATUS_ABIOS_NOT_LID_OWNER,
+ MD_NTSTATUS_WIN_STATUS_ABIOS_INVALID_COMMAND,
+ MD_NTSTATUS_WIN_STATUS_ABIOS_INVALID_LID,
+ MD_NTSTATUS_WIN_STATUS_ABIOS_SELECTOR_NOT_AVAILABLE,
+ MD_NTSTATUS_WIN_STATUS_ABIOS_INVALID_SELECTOR,
+ MD_NTSTATUS_WIN_STATUS_NO_LDT,
+ MD_NTSTATUS_WIN_STATUS_INVALID_LDT_SIZE,
+ MD_NTSTATUS_WIN_STATUS_INVALID_LDT_OFFSET,
+ MD_NTSTATUS_WIN_STATUS_INVALID_LDT_DESCRIPTOR,
+ MD_NTSTATUS_WIN_STATUS_INVALID_IMAGE_NE_FORMAT,
+ MD_NTSTATUS_WIN_STATUS_RXACT_INVALID_STATE,
+ MD_NTSTATUS_WIN_STATUS_RXACT_COMMIT_FAILURE,
+ MD_NTSTATUS_WIN_STATUS_MAPPED_FILE_SIZE_ZERO,
+ MD_NTSTATUS_WIN_STATUS_TOO_MANY_OPENED_FILES,
+ MD_NTSTATUS_WIN_STATUS_CANCELLED,
+ MD_NTSTATUS_WIN_STATUS_CANNOT_DELETE,
+ MD_NTSTATUS_WIN_STATUS_INVALID_COMPUTER_NAME,
+ MD_NTSTATUS_WIN_STATUS_FILE_DELETED,
+ MD_NTSTATUS_WIN_STATUS_SPECIAL_ACCOUNT,
+ MD_NTSTATUS_WIN_STATUS_SPECIAL_GROUP,
+ MD_NTSTATUS_WIN_STATUS_SPECIAL_USER,
+ MD_NTSTATUS_WIN_STATUS_MEMBERS_PRIMARY_GROUP,
+ MD_NTSTATUS_WIN_STATUS_FILE_CLOSED,
+ MD_NTSTATUS_WIN_STATUS_TOO_MANY_THREADS,
+ MD_NTSTATUS_WIN_STATUS_THREAD_NOT_IN_PROCESS,
+ MD_NTSTATUS_WIN_STATUS_TOKEN_ALREADY_IN_USE,
+ MD_NTSTATUS_WIN_STATUS_PAGEFILE_QUOTA_EXCEEDED,
+ MD_NTSTATUS_WIN_STATUS_COMMITMENT_LIMIT,
+ MD_NTSTATUS_WIN_STATUS_INVALID_IMAGE_LE_FORMAT,
+ MD_NTSTATUS_WIN_STATUS_INVALID_IMAGE_NOT_MZ,
+ MD_NTSTATUS_WIN_STATUS_INVALID_IMAGE_PROTECT,
+ MD_NTSTATUS_WIN_STATUS_INVALID_IMAGE_WIN_16,
+ MD_NTSTATUS_WIN_STATUS_LOGON_SERVER_CONFLICT,
+ MD_NTSTATUS_WIN_STATUS_TIME_DIFFERENCE_AT_DC,
+ MD_NTSTATUS_WIN_STATUS_SYNCHRONIZATION_REQUIRED,
+ MD_NTSTATUS_WIN_STATUS_DLL_NOT_FOUND,
+ MD_NTSTATUS_WIN_STATUS_OPEN_FAILED,
+ MD_NTSTATUS_WIN_STATUS_IO_PRIVILEGE_FAILED,
+ MD_NTSTATUS_WIN_STATUS_ORDINAL_NOT_FOUND,
+ MD_NTSTATUS_WIN_STATUS_ENTRYPOINT_NOT_FOUND,
+ MD_NTSTATUS_WIN_STATUS_CONTROL_C_EXIT,
+ MD_NTSTATUS_WIN_STATUS_LOCAL_DISCONNECT,
+ MD_NTSTATUS_WIN_STATUS_REMOTE_DISCONNECT,
+ MD_NTSTATUS_WIN_STATUS_REMOTE_RESOURCES,
+ MD_NTSTATUS_WIN_STATUS_LINK_FAILED,
+ MD_NTSTATUS_WIN_STATUS_LINK_TIMEOUT,
+ MD_NTSTATUS_WIN_STATUS_INVALID_CONNECTION,
+ MD_NTSTATUS_WIN_STATUS_INVALID_ADDRESS,
+ MD_NTSTATUS_WIN_STATUS_DLL_INIT_FAILED,
+ MD_NTSTATUS_WIN_STATUS_MISSING_SYSTEMFILE,
+ MD_NTSTATUS_WIN_STATUS_UNHANDLED_EXCEPTION,
+ MD_NTSTATUS_WIN_STATUS_APP_INIT_FAILURE,
+ MD_NTSTATUS_WIN_STATUS_PAGEFILE_CREATE_FAILED,
+ MD_NTSTATUS_WIN_STATUS_NO_PAGEFILE,
+ MD_NTSTATUS_WIN_STATUS_INVALID_LEVEL,
+ MD_NTSTATUS_WIN_STATUS_WRONG_PASSWORD_CORE,
+ MD_NTSTATUS_WIN_STATUS_ILLEGAL_FLOAT_CONTEXT,
+ MD_NTSTATUS_WIN_STATUS_PIPE_BROKEN,
+ MD_NTSTATUS_WIN_STATUS_REGISTRY_CORRUPT,
+ MD_NTSTATUS_WIN_STATUS_REGISTRY_IO_FAILED,
+ MD_NTSTATUS_WIN_STATUS_NO_EVENT_PAIR,
+ MD_NTSTATUS_WIN_STATUS_UNRECOGNIZED_VOLUME,
+ MD_NTSTATUS_WIN_STATUS_SERIAL_NO_DEVICE_INITED,
+ MD_NTSTATUS_WIN_STATUS_NO_SUCH_ALIAS,
+ MD_NTSTATUS_WIN_STATUS_MEMBER_NOT_IN_ALIAS,
+ MD_NTSTATUS_WIN_STATUS_MEMBER_IN_ALIAS,
+ MD_NTSTATUS_WIN_STATUS_ALIAS_EXISTS,
+ MD_NTSTATUS_WIN_STATUS_LOGON_NOT_GRANTED,
+ MD_NTSTATUS_WIN_STATUS_TOO_MANY_SECRETS,
+ MD_NTSTATUS_WIN_STATUS_SECRET_TOO_LONG,
+ MD_NTSTATUS_WIN_STATUS_INTERNAL_DB_ERROR,
+ MD_NTSTATUS_WIN_STATUS_FULLSCREEN_MODE,
+ MD_NTSTATUS_WIN_STATUS_TOO_MANY_CONTEXT_IDS,
+ MD_NTSTATUS_WIN_STATUS_LOGON_TYPE_NOT_GRANTED,
+ MD_NTSTATUS_WIN_STATUS_NOT_REGISTRY_FILE,
+ MD_NTSTATUS_WIN_STATUS_NT_CROSS_ENCRYPTION_REQUIRED,
+ MD_NTSTATUS_WIN_STATUS_DOMAIN_CTRLR_CONFIG_ERROR,
+ MD_NTSTATUS_WIN_STATUS_FT_MISSING_MEMBER,
+ MD_NTSTATUS_WIN_STATUS_ILL_FORMED_SERVICE_ENTRY,
+ MD_NTSTATUS_WIN_STATUS_ILLEGAL_CHARACTER,
+ MD_NTSTATUS_WIN_STATUS_UNMAPPABLE_CHARACTER,
+ MD_NTSTATUS_WIN_STATUS_UNDEFINED_CHARACTER,
+ MD_NTSTATUS_WIN_STATUS_FLOPPY_VOLUME,
+ MD_NTSTATUS_WIN_STATUS_FLOPPY_ID_MARK_NOT_FOUND,
+ MD_NTSTATUS_WIN_STATUS_FLOPPY_WRONG_CYLINDER,
+ MD_NTSTATUS_WIN_STATUS_FLOPPY_UNKNOWN_ERROR,
+ MD_NTSTATUS_WIN_STATUS_FLOPPY_BAD_REGISTERS,
+ MD_NTSTATUS_WIN_STATUS_DISK_RECALIBRATE_FAILED,
+ MD_NTSTATUS_WIN_STATUS_DISK_OPERATION_FAILED,
+ MD_NTSTATUS_WIN_STATUS_DISK_RESET_FAILED,
+ MD_NTSTATUS_WIN_STATUS_SHARED_IRQ_BUSY,
+ MD_NTSTATUS_WIN_STATUS_FT_ORPHANING,
+ MD_NTSTATUS_WIN_STATUS_BIOS_FAILED_TO_CONNECT_INTERRUPT,
+ MD_NTSTATUS_WIN_STATUS_PARTITION_FAILURE,
+ MD_NTSTATUS_WIN_STATUS_INVALID_BLOCK_LENGTH,
+ MD_NTSTATUS_WIN_STATUS_DEVICE_NOT_PARTITIONED,
+ MD_NTSTATUS_WIN_STATUS_UNABLE_TO_LOCK_MEDIA,
+ MD_NTSTATUS_WIN_STATUS_UNABLE_TO_UNLOAD_MEDIA,
+ MD_NTSTATUS_WIN_STATUS_EOM_OVERFLOW,
+ MD_NTSTATUS_WIN_STATUS_NO_MEDIA,
+ MD_NTSTATUS_WIN_STATUS_NO_SUCH_MEMBER,
+ MD_NTSTATUS_WIN_STATUS_INVALID_MEMBER,
+ MD_NTSTATUS_WIN_STATUS_KEY_DELETED,
+ MD_NTSTATUS_WIN_STATUS_NO_LOG_SPACE,
+ MD_NTSTATUS_WIN_STATUS_TOO_MANY_SIDS,
+ MD_NTSTATUS_WIN_STATUS_LM_CROSS_ENCRYPTION_REQUIRED,
+ MD_NTSTATUS_WIN_STATUS_KEY_HAS_CHILDREN,
+ MD_NTSTATUS_WIN_STATUS_CHILD_MUST_BE_VOLATILE,
+ MD_NTSTATUS_WIN_STATUS_DEVICE_CONFIGURATION_ERROR,
+ MD_NTSTATUS_WIN_STATUS_DRIVER_INTERNAL_ERROR,
+ MD_NTSTATUS_WIN_STATUS_INVALID_DEVICE_STATE,
+ MD_NTSTATUS_WIN_STATUS_IO_DEVICE_ERROR,
+ MD_NTSTATUS_WIN_STATUS_DEVICE_PROTOCOL_ERROR,
+ MD_NTSTATUS_WIN_STATUS_BACKUP_CONTROLLER,
+ MD_NTSTATUS_WIN_STATUS_LOG_FILE_FULL,
+ MD_NTSTATUS_WIN_STATUS_TOO_LATE,
+ MD_NTSTATUS_WIN_STATUS_NO_TRUST_LSA_SECRET,
+ MD_NTSTATUS_WIN_STATUS_NO_TRUST_SAM_ACCOUNT,
+ MD_NTSTATUS_WIN_STATUS_TRUSTED_DOMAIN_FAILURE,
+ MD_NTSTATUS_WIN_STATUS_TRUSTED_RELATIONSHIP_FAILURE,
+ MD_NTSTATUS_WIN_STATUS_EVENTLOG_FILE_CORRUPT,
+ MD_NTSTATUS_WIN_STATUS_EVENTLOG_CANT_START,
+ MD_NTSTATUS_WIN_STATUS_TRUST_FAILURE,
+ MD_NTSTATUS_WIN_STATUS_MUTANT_LIMIT_EXCEEDED,
+ MD_NTSTATUS_WIN_STATUS_NETLOGON_NOT_STARTED,
+ MD_NTSTATUS_WIN_STATUS_ACCOUNT_EXPIRED,
+ MD_NTSTATUS_WIN_STATUS_POSSIBLE_DEADLOCK,
+ MD_NTSTATUS_WIN_STATUS_NETWORK_CREDENTIAL_CONFLICT,
+ MD_NTSTATUS_WIN_STATUS_REMOTE_SESSION_LIMIT,
+ MD_NTSTATUS_WIN_STATUS_EVENTLOG_FILE_CHANGED,
+ MD_NTSTATUS_WIN_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT,
+ MD_NTSTATUS_WIN_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT,
+ MD_NTSTATUS_WIN_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT,
+ MD_NTSTATUS_WIN_STATUS_DOMAIN_TRUST_INCONSISTENT,
+ MD_NTSTATUS_WIN_STATUS_FS_DRIVER_REQUIRED,
+ MD_NTSTATUS_WIN_STATUS_IMAGE_ALREADY_LOADED_AS_DLL,
+ MD_NTSTATUS_WIN_STATUS_INCOMPATIBLE_WITH_GLOBAL_SHORT_NAME_REGISTRY_SETTING,
+ MD_NTSTATUS_WIN_STATUS_SHORT_NAMES_NOT_ENABLED_ON_VOLUME,
+ MD_NTSTATUS_WIN_STATUS_SECURITY_STREAM_IS_INCONSISTENT,
+ MD_NTSTATUS_WIN_STATUS_INVALID_LOCK_RANGE,
+ MD_NTSTATUS_WIN_STATUS_INVALID_ACE_CONDITION,
+ MD_NTSTATUS_WIN_STATUS_IMAGE_SUBSYSTEM_NOT_PRESENT,
+ MD_NTSTATUS_WIN_STATUS_NOTIFICATION_GUID_ALREADY_DEFINED,
+ MD_NTSTATUS_WIN_STATUS_INVALID_EXCEPTION_HANDLER,
+ MD_NTSTATUS_WIN_STATUS_DUPLICATE_PRIVILEGES,
+ MD_NTSTATUS_WIN_STATUS_NOT_ALLOWED_ON_SYSTEM_FILE,
+ MD_NTSTATUS_WIN_STATUS_REPAIR_NEEDED,
+ MD_NTSTATUS_WIN_STATUS_QUOTA_NOT_ENABLED,
+ MD_NTSTATUS_WIN_STATUS_NO_APPLICATION_PACKAGE,
+ MD_NTSTATUS_WIN_STATUS_FILE_METADATA_OPTIMIZATION_IN_PROGRESS,
+ MD_NTSTATUS_WIN_STATUS_NOT_SAME_OBJECT,
+ MD_NTSTATUS_WIN_STATUS_FATAL_MEMORY_EXHAUSTION,
+ MD_NTSTATUS_WIN_STATUS_ERROR_PROCESS_NOT_IN_JOB,
+ MD_NTSTATUS_WIN_STATUS_CPU_SET_INVALID,
+ MD_NTSTATUS_WIN_STATUS_IO_DEVICE_INVALID_DATA,
+ MD_NTSTATUS_WIN_STATUS_IO_UNALIGNED_WRITE,
+ MD_NTSTATUS_WIN_STATUS_CONTROL_STACK_VIOLATION,
+ MD_NTSTATUS_WIN_STATUS_NETWORK_OPEN_RESTRICTION,
+ MD_NTSTATUS_WIN_STATUS_NO_USER_SESSION_KEY,
+ MD_NTSTATUS_WIN_STATUS_USER_SESSION_DELETED,
+ MD_NTSTATUS_WIN_STATUS_RESOURCE_LANG_NOT_FOUND,
+ MD_NTSTATUS_WIN_STATUS_INSUFF_SERVER_RESOURCES,
+ MD_NTSTATUS_WIN_STATUS_INVALID_BUFFER_SIZE,
+ MD_NTSTATUS_WIN_STATUS_INVALID_ADDRESS_COMPONENT,
+ MD_NTSTATUS_WIN_STATUS_INVALID_ADDRESS_WILDCARD,
+ MD_NTSTATUS_WIN_STATUS_TOO_MANY_ADDRESSES,
+ MD_NTSTATUS_WIN_STATUS_ADDRESS_ALREADY_EXISTS,
+ MD_NTSTATUS_WIN_STATUS_ADDRESS_CLOSED,
+ MD_NTSTATUS_WIN_STATUS_CONNECTION_DISCONNECTED,
+ MD_NTSTATUS_WIN_STATUS_CONNECTION_RESET,
+ MD_NTSTATUS_WIN_STATUS_TOO_MANY_NODES,
+ MD_NTSTATUS_WIN_STATUS_TRANSACTION_ABORTED,
+ MD_NTSTATUS_WIN_STATUS_TRANSACTION_TIMED_OUT,
+ MD_NTSTATUS_WIN_STATUS_TRANSACTION_NO_RELEASE,
+ MD_NTSTATUS_WIN_STATUS_TRANSACTION_NO_MATCH,
+ MD_NTSTATUS_WIN_STATUS_TRANSACTION_RESPONDED,
+ MD_NTSTATUS_WIN_STATUS_TRANSACTION_INVALID_ID,
+ MD_NTSTATUS_WIN_STATUS_TRANSACTION_INVALID_TYPE,
+ MD_NTSTATUS_WIN_STATUS_NOT_SERVER_SESSION,
+ MD_NTSTATUS_WIN_STATUS_NOT_CLIENT_SESSION,
+ MD_NTSTATUS_WIN_STATUS_CANNOT_LOAD_REGISTRY_FILE,
+ MD_NTSTATUS_WIN_STATUS_DEBUG_ATTACH_FAILED,
+ MD_NTSTATUS_WIN_STATUS_SYSTEM_PROCESS_TERMINATED,
+ MD_NTSTATUS_WIN_STATUS_DATA_NOT_ACCEPTED,
+ MD_NTSTATUS_WIN_STATUS_NO_BROWSER_SERVERS_FOUND,
+ MD_NTSTATUS_WIN_STATUS_VDM_HARD_ERROR,
+ MD_NTSTATUS_WIN_STATUS_DRIVER_CANCEL_TIMEOUT,
+ MD_NTSTATUS_WIN_STATUS_REPLY_MESSAGE_MISMATCH,
+ MD_NTSTATUS_WIN_STATUS_MAPPED_ALIGNMENT,
+ MD_NTSTATUS_WIN_STATUS_IMAGE_CHECKSUM_MISMATCH,
+ MD_NTSTATUS_WIN_STATUS_LOST_WRITEBEHIND_DATA,
+ MD_NTSTATUS_WIN_STATUS_CLIENT_SERVER_PARAMETERS_INVALID,
+ MD_NTSTATUS_WIN_STATUS_PASSWORD_MUST_CHANGE,
+ MD_NTSTATUS_WIN_STATUS_NOT_FOUND,
+ MD_NTSTATUS_WIN_STATUS_NOT_TINY_STREAM,
+ MD_NTSTATUS_WIN_STATUS_RECOVERY_FAILURE,
+ MD_NTSTATUS_WIN_STATUS_STACK_OVERFLOW_READ,
+ MD_NTSTATUS_WIN_STATUS_FAIL_CHECK,
+ MD_NTSTATUS_WIN_STATUS_DUPLICATE_OBJECTID,
+ MD_NTSTATUS_WIN_STATUS_OBJECTID_EXISTS,
+ MD_NTSTATUS_WIN_STATUS_CONVERT_TO_LARGE,
+ MD_NTSTATUS_WIN_STATUS_RETRY,
+ MD_NTSTATUS_WIN_STATUS_FOUND_OUT_OF_SCOPE,
+ MD_NTSTATUS_WIN_STATUS_ALLOCATE_BUCKET,
+ MD_NTSTATUS_WIN_STATUS_PROPSET_NOT_FOUND,
+ MD_NTSTATUS_WIN_STATUS_MARSHALL_OVERFLOW,
+ MD_NTSTATUS_WIN_STATUS_INVALID_VARIANT,
+ MD_NTSTATUS_WIN_STATUS_DOMAIN_CONTROLLER_NOT_FOUND,
+ MD_NTSTATUS_WIN_STATUS_ACCOUNT_LOCKED_OUT,
+ MD_NTSTATUS_WIN_STATUS_HANDLE_NOT_CLOSABLE,
+ MD_NTSTATUS_WIN_STATUS_CONNECTION_REFUSED,
+ MD_NTSTATUS_WIN_STATUS_GRACEFUL_DISCONNECT,
+ MD_NTSTATUS_WIN_STATUS_ADDRESS_ALREADY_ASSOCIATED,
+ MD_NTSTATUS_WIN_STATUS_ADDRESS_NOT_ASSOCIATED,
+ MD_NTSTATUS_WIN_STATUS_CONNECTION_INVALID,
+ MD_NTSTATUS_WIN_STATUS_CONNECTION_ACTIVE,
+ MD_NTSTATUS_WIN_STATUS_NETWORK_UNREACHABLE,
+ MD_NTSTATUS_WIN_STATUS_HOST_UNREACHABLE,
+ MD_NTSTATUS_WIN_STATUS_PROTOCOL_UNREACHABLE,
+ MD_NTSTATUS_WIN_STATUS_PORT_UNREACHABLE,
+ MD_NTSTATUS_WIN_STATUS_REQUEST_ABORTED,
+ MD_NTSTATUS_WIN_STATUS_CONNECTION_ABORTED,
+ MD_NTSTATUS_WIN_STATUS_BAD_COMPRESSION_BUFFER,
+ MD_NTSTATUS_WIN_STATUS_USER_MAPPED_FILE,
+ MD_NTSTATUS_WIN_STATUS_AUDIT_FAILED,
+ MD_NTSTATUS_WIN_STATUS_TIMER_RESOLUTION_NOT_SET,
+ MD_NTSTATUS_WIN_STATUS_CONNECTION_COUNT_LIMIT,
+ MD_NTSTATUS_WIN_STATUS_LOGIN_TIME_RESTRICTION,
+ MD_NTSTATUS_WIN_STATUS_LOGIN_WKSTA_RESTRICTION,
+ MD_NTSTATUS_WIN_STATUS_IMAGE_MP_UP_MISMATCH,
+ MD_NTSTATUS_WIN_STATUS_INSUFFICIENT_LOGON_INFO,
+ MD_NTSTATUS_WIN_STATUS_BAD_DLL_ENTRYPOINT,
+ MD_NTSTATUS_WIN_STATUS_BAD_SERVICE_ENTRYPOINT,
+ MD_NTSTATUS_WIN_STATUS_LPC_REPLY_LOST,
+ MD_NTSTATUS_WIN_STATUS_IP_ADDRESS_CONFLICT1,
+ MD_NTSTATUS_WIN_STATUS_IP_ADDRESS_CONFLICT2,
+ MD_NTSTATUS_WIN_STATUS_REGISTRY_QUOTA_LIMIT,
+ MD_NTSTATUS_WIN_STATUS_PATH_NOT_COVERED,
+ MD_NTSTATUS_WIN_STATUS_NO_CALLBACK_ACTIVE,
+ MD_NTSTATUS_WIN_STATUS_LICENSE_QUOTA_EXCEEDED,
+ MD_NTSTATUS_WIN_STATUS_PWD_TOO_SHORT,
+ MD_NTSTATUS_WIN_STATUS_PWD_TOO_RECENT,
+ MD_NTSTATUS_WIN_STATUS_PWD_HISTORY_CONFLICT,
+ MD_NTSTATUS_WIN_STATUS_PLUGPLAY_NO_DEVICE,
+ MD_NTSTATUS_WIN_STATUS_UNSUPPORTED_COMPRESSION,
+ MD_NTSTATUS_WIN_STATUS_INVALID_HW_PROFILE,
+ MD_NTSTATUS_WIN_STATUS_INVALID_PLUGPLAY_DEVICE_PATH,
+ MD_NTSTATUS_WIN_STATUS_DRIVER_ORDINAL_NOT_FOUND,
+ MD_NTSTATUS_WIN_STATUS_DRIVER_ENTRYPOINT_NOT_FOUND,
+ MD_NTSTATUS_WIN_STATUS_RESOURCE_NOT_OWNED,
+ MD_NTSTATUS_WIN_STATUS_TOO_MANY_LINKS,
+ MD_NTSTATUS_WIN_STATUS_QUOTA_LIST_INCONSISTENT,
+ MD_NTSTATUS_WIN_STATUS_FILE_IS_OFFLINE,
+ MD_NTSTATUS_WIN_STATUS_EVALUATION_EXPIRATION,
+ MD_NTSTATUS_WIN_STATUS_ILLEGAL_DLL_RELOCATION,
+ MD_NTSTATUS_WIN_STATUS_LICENSE_VIOLATION,
+ MD_NTSTATUS_WIN_STATUS_DLL_INIT_FAILED_LOGOFF,
+ MD_NTSTATUS_WIN_STATUS_DRIVER_UNABLE_TO_LOAD,
+ MD_NTSTATUS_WIN_STATUS_DFS_UNAVAILABLE,
+ MD_NTSTATUS_WIN_STATUS_VOLUME_DISMOUNTED,
+ MD_NTSTATUS_WIN_STATUS_WX86_INTERNAL_ERROR,
+ MD_NTSTATUS_WIN_STATUS_WX86_FLOAT_STACK_CHECK,
+ MD_NTSTATUS_WIN_STATUS_VALIDATE_CONTINUE,
+ MD_NTSTATUS_WIN_STATUS_NO_MATCH,
+ MD_NTSTATUS_WIN_STATUS_NO_MORE_MATCHES,
+ MD_NTSTATUS_WIN_STATUS_NOT_A_REPARSE_POINT,
+ MD_NTSTATUS_WIN_STATUS_IO_REPARSE_TAG_INVALID,
+ MD_NTSTATUS_WIN_STATUS_IO_REPARSE_TAG_MISMATCH,
+ MD_NTSTATUS_WIN_STATUS_IO_REPARSE_DATA_INVALID,
+ MD_NTSTATUS_WIN_STATUS_IO_REPARSE_TAG_NOT_HANDLED,
+ MD_NTSTATUS_WIN_STATUS_PWD_TOO_LONG,
+ MD_NTSTATUS_WIN_STATUS_STOWED_EXCEPTION,
+ MD_NTSTATUS_WIN_STATUS_CONTEXT_STOWED_EXCEPTION,
+ MD_NTSTATUS_WIN_STATUS_REPARSE_POINT_NOT_RESOLVED,
+ MD_NTSTATUS_WIN_STATUS_DIRECTORY_IS_A_REPARSE_POINT,
+ MD_NTSTATUS_WIN_STATUS_RANGE_LIST_CONFLICT,
+ MD_NTSTATUS_WIN_STATUS_SOURCE_ELEMENT_EMPTY,
+ MD_NTSTATUS_WIN_STATUS_DESTINATION_ELEMENT_FULL,
+ MD_NTSTATUS_WIN_STATUS_ILLEGAL_ELEMENT_ADDRESS,
+ MD_NTSTATUS_WIN_STATUS_MAGAZINE_NOT_PRESENT,
+ MD_NTSTATUS_WIN_STATUS_REINITIALIZATION_NEEDED,
+ MD_NTSTATUS_WIN_STATUS_ENCRYPTION_FAILED,
+ MD_NTSTATUS_WIN_STATUS_DECRYPTION_FAILED,
+ MD_NTSTATUS_WIN_STATUS_RANGE_NOT_FOUND,
+ MD_NTSTATUS_WIN_STATUS_NO_RECOVERY_POLICY,
+ MD_NTSTATUS_WIN_STATUS_NO_EFS,
+ MD_NTSTATUS_WIN_STATUS_WRONG_EFS,
+ MD_NTSTATUS_WIN_STATUS_NO_USER_KEYS,
+ MD_NTSTATUS_WIN_STATUS_FILE_NOT_ENCRYPTED,
+ MD_NTSTATUS_WIN_STATUS_NOT_EXPORT_FORMAT,
+ MD_NTSTATUS_WIN_STATUS_FILE_ENCRYPTED,
+ MD_NTSTATUS_WIN_STATUS_WMI_GUID_NOT_FOUND,
+ MD_NTSTATUS_WIN_STATUS_WMI_INSTANCE_NOT_FOUND,
+ MD_NTSTATUS_WIN_STATUS_WMI_ITEMID_NOT_FOUND,
+ MD_NTSTATUS_WIN_STATUS_WMI_TRY_AGAIN,
+ MD_NTSTATUS_WIN_STATUS_SHARED_POLICY,
+ MD_NTSTATUS_WIN_STATUS_POLICY_OBJECT_NOT_FOUND,
+ MD_NTSTATUS_WIN_STATUS_POLICY_ONLY_IN_DS,
+ MD_NTSTATUS_WIN_STATUS_VOLUME_NOT_UPGRADED,
+ MD_NTSTATUS_WIN_STATUS_REMOTE_STORAGE_NOT_ACTIVE,
+ MD_NTSTATUS_WIN_STATUS_REMOTE_STORAGE_MEDIA_ERROR,
+ MD_NTSTATUS_WIN_STATUS_NO_TRACKING_SERVICE,
+ MD_NTSTATUS_WIN_STATUS_SERVER_SID_MISMATCH,
+ MD_NTSTATUS_WIN_STATUS_DS_NO_ATTRIBUTE_OR_VALUE,
+ MD_NTSTATUS_WIN_STATUS_DS_INVALID_ATTRIBUTE_SYNTAX,
+ MD_NTSTATUS_WIN_STATUS_DS_ATTRIBUTE_TYPE_UNDEFINED,
+ MD_NTSTATUS_WIN_STATUS_DS_ATTRIBUTE_OR_VALUE_EXISTS,
+ MD_NTSTATUS_WIN_STATUS_DS_BUSY,
+ MD_NTSTATUS_WIN_STATUS_DS_UNAVAILABLE,
+ MD_NTSTATUS_WIN_STATUS_DS_NO_RIDS_ALLOCATED,
+ MD_NTSTATUS_WIN_STATUS_DS_NO_MORE_RIDS,
+ MD_NTSTATUS_WIN_STATUS_DS_INCORRECT_ROLE_OWNER,
+ MD_NTSTATUS_WIN_STATUS_DS_RIDMGR_INIT_ERROR,
+ MD_NTSTATUS_WIN_STATUS_DS_OBJ_CLASS_VIOLATION,
+ MD_NTSTATUS_WIN_STATUS_DS_CANT_ON_NON_LEAF,
+ MD_NTSTATUS_WIN_STATUS_DS_CANT_ON_RDN,
+ MD_NTSTATUS_WIN_STATUS_DS_CANT_MOD_OBJ_CLASS,
+ MD_NTSTATUS_WIN_STATUS_DS_CROSS_DOM_MOVE_FAILED,
+ MD_NTSTATUS_WIN_STATUS_DS_GC_NOT_AVAILABLE,
+ MD_NTSTATUS_WIN_STATUS_DIRECTORY_SERVICE_REQUIRED,
+ MD_NTSTATUS_WIN_STATUS_REPARSE_ATTRIBUTE_CONFLICT,
+ MD_NTSTATUS_WIN_STATUS_CANT_ENABLE_DENY_ONLY,
+ MD_NTSTATUS_WIN_STATUS_FLOAT_MULTIPLE_FAULTS,
+ MD_NTSTATUS_WIN_STATUS_FLOAT_MULTIPLE_TRAPS,
+ MD_NTSTATUS_WIN_STATUS_DEVICE_REMOVED,
+ MD_NTSTATUS_WIN_STATUS_JOURNAL_DELETE_IN_PROGRESS,
+ MD_NTSTATUS_WIN_STATUS_JOURNAL_NOT_ACTIVE,
+ MD_NTSTATUS_WIN_STATUS_NOINTERFACE,
+ MD_NTSTATUS_WIN_STATUS_DS_RIDMGR_DISABLED,
+ MD_NTSTATUS_WIN_STATUS_DS_ADMIN_LIMIT_EXCEEDED,
+ MD_NTSTATUS_WIN_STATUS_DRIVER_FAILED_SLEEP,
+ MD_NTSTATUS_WIN_STATUS_MUTUAL_AUTHENTICATION_FAILED,
+ MD_NTSTATUS_WIN_STATUS_CORRUPT_SYSTEM_FILE,
+ MD_NTSTATUS_WIN_STATUS_DATATYPE_MISALIGNMENT_ERROR,
+ MD_NTSTATUS_WIN_STATUS_WMI_READ_ONLY,
+ MD_NTSTATUS_WIN_STATUS_WMI_SET_FAILURE,
+ MD_NTSTATUS_WIN_STATUS_COMMITMENT_MINIMUM,
+ MD_NTSTATUS_WIN_STATUS_REG_NAT_CONSUMPTION,
+ MD_NTSTATUS_WIN_STATUS_TRANSPORT_FULL,
+ MD_NTSTATUS_WIN_STATUS_DS_SAM_INIT_FAILURE,
+ MD_NTSTATUS_WIN_STATUS_ONLY_IF_CONNECTED,
+ MD_NTSTATUS_WIN_STATUS_DS_SENSITIVE_GROUP_VIOLATION,
+ MD_NTSTATUS_WIN_STATUS_PNP_RESTART_ENUMERATION,
+ MD_NTSTATUS_WIN_STATUS_JOURNAL_ENTRY_DELETED,
+ MD_NTSTATUS_WIN_STATUS_DS_CANT_MOD_PRIMARYGROUPID,
+ MD_NTSTATUS_WIN_STATUS_SYSTEM_IMAGE_BAD_SIGNATURE,
+ MD_NTSTATUS_WIN_STATUS_PNP_REBOOT_REQUIRED,
+ MD_NTSTATUS_WIN_STATUS_POWER_STATE_INVALID,
+ MD_NTSTATUS_WIN_STATUS_DS_INVALID_GROUP_TYPE,
+ MD_NTSTATUS_WIN_STATUS_DS_NO_NEST_GLOBALGROUP_IN_MIXEDDOMAIN,
+ MD_NTSTATUS_WIN_STATUS_DS_NO_NEST_LOCALGROUP_IN_MIXEDDOMAIN,
+ MD_NTSTATUS_WIN_STATUS_DS_GLOBAL_CANT_HAVE_LOCAL_MEMBER,
+ MD_NTSTATUS_WIN_STATUS_DS_GLOBAL_CANT_HAVE_UNIVERSAL_MEMBER,
+ MD_NTSTATUS_WIN_STATUS_DS_UNIVERSAL_CANT_HAVE_LOCAL_MEMBER,
+ MD_NTSTATUS_WIN_STATUS_DS_GLOBAL_CANT_HAVE_CROSSDOMAIN_MEMBER,
+ MD_NTSTATUS_WIN_STATUS_DS_LOCAL_CANT_HAVE_CROSSDOMAIN_LOCAL_MEMBER,
+ MD_NTSTATUS_WIN_STATUS_DS_HAVE_PRIMARY_MEMBERS,
+ MD_NTSTATUS_WIN_STATUS_WMI_NOT_SUPPORTED,
+ MD_NTSTATUS_WIN_STATUS_INSUFFICIENT_POWER,
+ MD_NTSTATUS_WIN_STATUS_SAM_NEED_BOOTKEY_PASSWORD,
+ MD_NTSTATUS_WIN_STATUS_SAM_NEED_BOOTKEY_FLOPPY,
+ MD_NTSTATUS_WIN_STATUS_DS_CANT_START,
+ MD_NTSTATUS_WIN_STATUS_DS_INIT_FAILURE,
+ MD_NTSTATUS_WIN_STATUS_SAM_INIT_FAILURE,
+ MD_NTSTATUS_WIN_STATUS_DS_GC_REQUIRED,
+ MD_NTSTATUS_WIN_STATUS_DS_LOCAL_MEMBER_OF_LOCAL_ONLY,
+ MD_NTSTATUS_WIN_STATUS_DS_NO_FPO_IN_UNIVERSAL_GROUPS,
+ MD_NTSTATUS_WIN_STATUS_DS_MACHINE_ACCOUNT_QUOTA_EXCEEDED,
+ MD_NTSTATUS_WIN_STATUS_MULTIPLE_FAULT_VIOLATION,
+ MD_NTSTATUS_WIN_STATUS_CURRENT_DOMAIN_NOT_ALLOWED,
+ MD_NTSTATUS_WIN_STATUS_CANNOT_MAKE,
+ MD_NTSTATUS_WIN_STATUS_SYSTEM_SHUTDOWN,
+ MD_NTSTATUS_WIN_STATUS_DS_INIT_FAILURE_CONSOLE,
+ MD_NTSTATUS_WIN_STATUS_DS_SAM_INIT_FAILURE_CONSOLE,
+ MD_NTSTATUS_WIN_STATUS_UNFINISHED_CONTEXT_DELETED,
+ MD_NTSTATUS_WIN_STATUS_NO_TGT_REPLY,
+ MD_NTSTATUS_WIN_STATUS_OBJECTID_NOT_FOUND,
+ MD_NTSTATUS_WIN_STATUS_NO_IP_ADDRESSES,
+ MD_NTSTATUS_WIN_STATUS_WRONG_CREDENTIAL_HANDLE,
+ MD_NTSTATUS_WIN_STATUS_CRYPTO_SYSTEM_INVALID,
+ MD_NTSTATUS_WIN_STATUS_MAX_REFERRALS_EXCEEDED,
+ MD_NTSTATUS_WIN_STATUS_MUST_BE_KDC,
+ MD_NTSTATUS_WIN_STATUS_STRONG_CRYPTO_NOT_SUPPORTED,
+ MD_NTSTATUS_WIN_STATUS_TOO_MANY_PRINCIPALS,
+ MD_NTSTATUS_WIN_STATUS_NO_PA_DATA,
+ MD_NTSTATUS_WIN_STATUS_PKINIT_NAME_MISMATCH,
+ MD_NTSTATUS_WIN_STATUS_SMARTCARD_LOGON_REQUIRED,
+ MD_NTSTATUS_WIN_STATUS_KDC_INVALID_REQUEST,
+ MD_NTSTATUS_WIN_STATUS_KDC_UNABLE_TO_REFER,
+ MD_NTSTATUS_WIN_STATUS_KDC_UNKNOWN_ETYPE,
+ MD_NTSTATUS_WIN_STATUS_SHUTDOWN_IN_PROGRESS,
+ MD_NTSTATUS_WIN_STATUS_SERVER_SHUTDOWN_IN_PROGRESS,
+ MD_NTSTATUS_WIN_STATUS_NOT_SUPPORTED_ON_SBS,
+ MD_NTSTATUS_WIN_STATUS_WMI_GUID_DISCONNECTED,
+ MD_NTSTATUS_WIN_STATUS_WMI_ALREADY_DISABLED,
+ MD_NTSTATUS_WIN_STATUS_WMI_ALREADY_ENABLED,
+ MD_NTSTATUS_WIN_STATUS_MFT_TOO_FRAGMENTED,
+ MD_NTSTATUS_WIN_STATUS_COPY_PROTECTION_FAILURE,
+ MD_NTSTATUS_WIN_STATUS_CSS_AUTHENTICATION_FAILURE,
+ MD_NTSTATUS_WIN_STATUS_CSS_KEY_NOT_PRESENT,
+ MD_NTSTATUS_WIN_STATUS_CSS_KEY_NOT_ESTABLISHED,
+ MD_NTSTATUS_WIN_STATUS_CSS_SCRAMBLED_SECTOR,
+ MD_NTSTATUS_WIN_STATUS_CSS_REGION_MISMATCH,
+ MD_NTSTATUS_WIN_STATUS_CSS_RESETS_EXHAUSTED,
+ MD_NTSTATUS_WIN_STATUS_PASSWORD_CHANGE_REQUIRED,
+ MD_NTSTATUS_WIN_STATUS_LOST_MODE_LOGON_RESTRICTION,
+ MD_NTSTATUS_WIN_STATUS_PKINIT_FAILURE,
+ MD_NTSTATUS_WIN_STATUS_SMARTCARD_SUBSYSTEM_FAILURE,
+ MD_NTSTATUS_WIN_STATUS_NO_KERB_KEY,
+ MD_NTSTATUS_WIN_STATUS_HOST_DOWN,
+ MD_NTSTATUS_WIN_STATUS_UNSUPPORTED_PREAUTH,
+ MD_NTSTATUS_WIN_STATUS_EFS_ALG_BLOB_TOO_BIG,
+ MD_NTSTATUS_WIN_STATUS_PORT_NOT_SET,
+ MD_NTSTATUS_WIN_STATUS_DEBUGGER_INACTIVE,
+ MD_NTSTATUS_WIN_STATUS_DS_VERSION_CHECK_FAILURE,
+ MD_NTSTATUS_WIN_STATUS_AUDITING_DISABLED,
+ MD_NTSTATUS_WIN_STATUS_PRENT4_MACHINE_ACCOUNT,
+ MD_NTSTATUS_WIN_STATUS_DS_AG_CANT_HAVE_UNIVERSAL_MEMBER,
+ MD_NTSTATUS_WIN_STATUS_INVALID_IMAGE_WIN_32,
+ MD_NTSTATUS_WIN_STATUS_INVALID_IMAGE_WIN_64,
+ MD_NTSTATUS_WIN_STATUS_BAD_BINDINGS,
+ MD_NTSTATUS_WIN_STATUS_NETWORK_SESSION_EXPIRED,
+ MD_NTSTATUS_WIN_STATUS_APPHELP_BLOCK,
+ MD_NTSTATUS_WIN_STATUS_ALL_SIDS_FILTERED,
+ MD_NTSTATUS_WIN_STATUS_NOT_SAFE_MODE_DRIVER,
+ MD_NTSTATUS_WIN_STATUS_ACCESS_DISABLED_BY_POLICY_DEFAULT,
+ MD_NTSTATUS_WIN_STATUS_ACCESS_DISABLED_BY_POLICY_PATH,
+ MD_NTSTATUS_WIN_STATUS_ACCESS_DISABLED_BY_POLICY_PUBLISHER,
+ MD_NTSTATUS_WIN_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER,
+ MD_NTSTATUS_WIN_STATUS_FAILED_DRIVER_ENTRY,
+ MD_NTSTATUS_WIN_STATUS_DEVICE_ENUMERATION_ERROR,
+ MD_NTSTATUS_WIN_STATUS_MOUNT_POINT_NOT_RESOLVED,
+ MD_NTSTATUS_WIN_STATUS_INVALID_DEVICE_OBJECT_PARAMETER,
+ MD_NTSTATUS_WIN_STATUS_MCA_OCCURED,
+ MD_NTSTATUS_WIN_STATUS_DRIVER_BLOCKED_CRITICAL,
+ MD_NTSTATUS_WIN_STATUS_DRIVER_BLOCKED,
+ MD_NTSTATUS_WIN_STATUS_DRIVER_DATABASE_ERROR,
+ MD_NTSTATUS_WIN_STATUS_SYSTEM_HIVE_TOO_LARGE,
+ MD_NTSTATUS_WIN_STATUS_INVALID_IMPORT_OF_NON_DLL,
+ MD_NTSTATUS_WIN_STATUS_NO_SECRETS,
+ MD_NTSTATUS_WIN_STATUS_ACCESS_DISABLED_NO_SAFER_UI_BY_POLICY,
+ MD_NTSTATUS_WIN_STATUS_FAILED_STACK_SWITCH,
+ MD_NTSTATUS_WIN_STATUS_HEAP_CORRUPTION,
+ MD_NTSTATUS_WIN_STATUS_SMARTCARD_WRONG_PIN,
+ MD_NTSTATUS_WIN_STATUS_SMARTCARD_CARD_BLOCKED,
+ MD_NTSTATUS_WIN_STATUS_SMARTCARD_CARD_NOT_AUTHENTICATED,
+ MD_NTSTATUS_WIN_STATUS_SMARTCARD_NO_CARD,
+ MD_NTSTATUS_WIN_STATUS_SMARTCARD_NO_KEY_CONTAINER,
+ MD_NTSTATUS_WIN_STATUS_SMARTCARD_NO_CERTIFICATE,
+ MD_NTSTATUS_WIN_STATUS_SMARTCARD_NO_KEYSET,
+ MD_NTSTATUS_WIN_STATUS_SMARTCARD_IO_ERROR,
+ MD_NTSTATUS_WIN_STATUS_DOWNGRADE_DETECTED,
+ MD_NTSTATUS_WIN_STATUS_SMARTCARD_CERT_REVOKED,
+ MD_NTSTATUS_WIN_STATUS_ISSUING_CA_UNTRUSTED,
+ MD_NTSTATUS_WIN_STATUS_REVOCATION_OFFLINE_C,
+ MD_NTSTATUS_WIN_STATUS_PKINIT_CLIENT_FAILURE,
+ MD_NTSTATUS_WIN_STATUS_SMARTCARD_CERT_EXPIRED,
+ MD_NTSTATUS_WIN_STATUS_DRIVER_FAILED_PRIOR_UNLOAD,
+ MD_NTSTATUS_WIN_STATUS_SMARTCARD_SILENT_CONTEXT,
+ MD_NTSTATUS_WIN_STATUS_PER_USER_TRUST_QUOTA_EXCEEDED,
+ MD_NTSTATUS_WIN_STATUS_ALL_USER_TRUST_QUOTA_EXCEEDED,
+ MD_NTSTATUS_WIN_STATUS_USER_DELETE_TRUST_QUOTA_EXCEEDED,
+ MD_NTSTATUS_WIN_STATUS_DS_NAME_NOT_UNIQUE,
+ MD_NTSTATUS_WIN_STATUS_DS_DUPLICATE_ID_FOUND,
+ MD_NTSTATUS_WIN_STATUS_DS_GROUP_CONVERSION_ERROR,
+ MD_NTSTATUS_WIN_STATUS_VOLSNAP_PREPARE_HIBERNATE,
+ MD_NTSTATUS_WIN_STATUS_USER2USER_REQUIRED,
+ MD_NTSTATUS_WIN_STATUS_STACK_BUFFER_OVERRUN,
+ MD_NTSTATUS_WIN_STATUS_NO_S4U_PROT_SUPPORT,
+ MD_NTSTATUS_WIN_STATUS_CROSSREALM_DELEGATION_FAILURE,
+ MD_NTSTATUS_WIN_STATUS_REVOCATION_OFFLINE_KDC,
+ MD_NTSTATUS_WIN_STATUS_ISSUING_CA_UNTRUSTED_KDC,
+ MD_NTSTATUS_WIN_STATUS_KDC_CERT_EXPIRED,
+ MD_NTSTATUS_WIN_STATUS_KDC_CERT_REVOKED,
+ MD_NTSTATUS_WIN_STATUS_PARAMETER_QUOTA_EXCEEDED,
+ MD_NTSTATUS_WIN_STATUS_HIBERNATION_FAILURE,
+ MD_NTSTATUS_WIN_STATUS_DELAY_LOAD_FAILED,
+ MD_NTSTATUS_WIN_STATUS_AUTHENTICATION_FIREWALL_FAILED,
+ MD_NTSTATUS_WIN_STATUS_VDM_DISALLOWED,
+ MD_NTSTATUS_WIN_STATUS_HUNG_DISPLAY_DRIVER_THREAD,
+ MD_NTSTATUS_WIN_STATUS_INSUFFICIENT_RESOURCE_FOR_SPECIFIED_SHARED_SECTION_SIZE,
+ MD_NTSTATUS_WIN_STATUS_INVALID_CRUNTIME_PARAMETER,
+ MD_NTSTATUS_WIN_STATUS_NTLM_BLOCKED,
+ MD_NTSTATUS_WIN_STATUS_DS_SRC_SID_EXISTS_IN_FOREST,
+ MD_NTSTATUS_WIN_STATUS_DS_DOMAIN_NAME_EXISTS_IN_FOREST,
+ MD_NTSTATUS_WIN_STATUS_DS_FLAT_NAME_EXISTS_IN_FOREST,
+ MD_NTSTATUS_WIN_STATUS_INVALID_USER_PRINCIPAL_NAME,
+ MD_NTSTATUS_WIN_STATUS_FATAL_USER_CALLBACK_EXCEPTION,
+ MD_NTSTATUS_WIN_STATUS_ASSERTION_FAILURE,
+ MD_NTSTATUS_WIN_STATUS_VERIFIER_STOP,
+ MD_NTSTATUS_WIN_STATUS_CALLBACK_POP_STACK,
+ MD_NTSTATUS_WIN_STATUS_INCOMPATIBLE_DRIVER_BLOCKED,
+ MD_NTSTATUS_WIN_STATUS_HIVE_UNLOADED,
+ MD_NTSTATUS_WIN_STATUS_COMPRESSION_DISABLED,
+ MD_NTSTATUS_WIN_STATUS_FILE_SYSTEM_LIMITATION,
+ MD_NTSTATUS_WIN_STATUS_INVALID_IMAGE_HASH,
+ MD_NTSTATUS_WIN_STATUS_NOT_CAPABLE,
+ MD_NTSTATUS_WIN_STATUS_REQUEST_OUT_OF_SEQUENCE,
+ MD_NTSTATUS_WIN_STATUS_IMPLEMENTATION_LIMIT,
+ MD_NTSTATUS_WIN_STATUS_ELEVATION_REQUIRED,
+ MD_NTSTATUS_WIN_STATUS_NO_SECURITY_CONTEXT,
+ MD_NTSTATUS_WIN_STATUS_PKU2U_CERT_FAILURE,
+ MD_NTSTATUS_WIN_STATUS_BEYOND_VDL,
+ MD_NTSTATUS_WIN_STATUS_ENCOUNTERED_WRITE_IN_PROGRESS,
+ MD_NTSTATUS_WIN_STATUS_PTE_CHANGED,
+ MD_NTSTATUS_WIN_STATUS_PURGE_FAILED,
+ MD_NTSTATUS_WIN_STATUS_CRED_REQUIRES_CONFIRMATION,
+ MD_NTSTATUS_WIN_STATUS_CS_ENCRYPTION_INVALID_SERVER_RESPONSE,
+ MD_NTSTATUS_WIN_STATUS_CS_ENCRYPTION_UNSUPPORTED_SERVER,
+ MD_NTSTATUS_WIN_STATUS_CS_ENCRYPTION_EXISTING_ENCRYPTED_FILE,
+ MD_NTSTATUS_WIN_STATUS_CS_ENCRYPTION_NEW_ENCRYPTED_FILE,
+ MD_NTSTATUS_WIN_STATUS_CS_ENCRYPTION_FILE_NOT_CSE,
+ MD_NTSTATUS_WIN_STATUS_INVALID_LABEL,
+ MD_NTSTATUS_WIN_STATUS_DRIVER_PROCESS_TERMINATED,
+ MD_NTSTATUS_WIN_STATUS_AMBIGUOUS_SYSTEM_DEVICE,
+ MD_NTSTATUS_WIN_STATUS_SYSTEM_DEVICE_NOT_FOUND,
+ MD_NTSTATUS_WIN_STATUS_RESTART_BOOT_APPLICATION,
+ MD_NTSTATUS_WIN_STATUS_INSUFFICIENT_NVRAM_RESOURCES,
+ MD_NTSTATUS_WIN_STATUS_INVALID_SESSION,
+ MD_NTSTATUS_WIN_STATUS_THREAD_ALREADY_IN_SESSION,
+ MD_NTSTATUS_WIN_STATUS_THREAD_NOT_IN_SESSION,
+ MD_NTSTATUS_WIN_STATUS_INVALID_WEIGHT,
+ MD_NTSTATUS_WIN_STATUS_REQUEST_PAUSED,
+ MD_NTSTATUS_WIN_STATUS_NO_RANGES_PROCESSED,
+ MD_NTSTATUS_WIN_STATUS_DISK_RESOURCES_EXHAUSTED,
+ MD_NTSTATUS_WIN_STATUS_NEEDS_REMEDIATION,
+ MD_NTSTATUS_WIN_STATUS_DEVICE_FEATURE_NOT_SUPPORTED,
+ MD_NTSTATUS_WIN_STATUS_DEVICE_UNREACHABLE,
+ MD_NTSTATUS_WIN_STATUS_INVALID_TOKEN,
+ MD_NTSTATUS_WIN_STATUS_SERVER_UNAVAILABLE,
+ MD_NTSTATUS_WIN_STATUS_FILE_NOT_AVAILABLE,
+ MD_NTSTATUS_WIN_STATUS_DEVICE_INSUFFICIENT_RESOURCES,
+ MD_NTSTATUS_WIN_STATUS_PACKAGE_UPDATING,
+ MD_NTSTATUS_WIN_STATUS_NOT_READ_FROM_COPY,
+ MD_NTSTATUS_WIN_STATUS_FT_WRITE_FAILURE,
+ MD_NTSTATUS_WIN_STATUS_FT_DI_SCAN_REQUIRED,
+ MD_NTSTATUS_WIN_STATUS_OBJECT_NOT_EXTERNALLY_BACKED,
+ MD_NTSTATUS_WIN_STATUS_EXTERNAL_BACKING_PROVIDER_UNKNOWN,
+ MD_NTSTATUS_WIN_STATUS_COMPRESSION_NOT_BENEFICIAL,
+ MD_NTSTATUS_WIN_STATUS_DATA_CHECKSUM_ERROR,
+ MD_NTSTATUS_WIN_STATUS_INTERMIXED_KERNEL_EA_OPERATION,
+ MD_NTSTATUS_WIN_STATUS_TRIM_READ_ZERO_NOT_SUPPORTED,
+ MD_NTSTATUS_WIN_STATUS_TOO_MANY_SEGMENT_DESCRIPTORS,
+ MD_NTSTATUS_WIN_STATUS_INVALID_OFFSET_ALIGNMENT,
+ MD_NTSTATUS_WIN_STATUS_INVALID_FIELD_IN_PARAMETER_LIST,
+ MD_NTSTATUS_WIN_STATUS_OPERATION_IN_PROGRESS,
+ MD_NTSTATUS_WIN_STATUS_INVALID_INITIATOR_TARGET_PATH,
+ MD_NTSTATUS_WIN_STATUS_SCRUB_DATA_DISABLED,
+ MD_NTSTATUS_WIN_STATUS_NOT_REDUNDANT_STORAGE,
+ MD_NTSTATUS_WIN_STATUS_RESIDENT_FILE_NOT_SUPPORTED,
+ MD_NTSTATUS_WIN_STATUS_COMPRESSED_FILE_NOT_SUPPORTED,
+ MD_NTSTATUS_WIN_STATUS_DIRECTORY_NOT_SUPPORTED,
+ MD_NTSTATUS_WIN_STATUS_IO_OPERATION_TIMEOUT,
+ MD_NTSTATUS_WIN_STATUS_SYSTEM_NEEDS_REMEDIATION,
+ MD_NTSTATUS_WIN_STATUS_APPX_INTEGRITY_FAILURE_CLR_NGEN,
+ MD_NTSTATUS_WIN_STATUS_SHARE_UNAVAILABLE,
+ MD_NTSTATUS_WIN_STATUS_APISET_NOT_HOSTED,
+ MD_NTSTATUS_WIN_STATUS_APISET_NOT_PRESENT,
+ MD_NTSTATUS_WIN_STATUS_DEVICE_HARDWARE_ERROR,
+ MD_NTSTATUS_WIN_STATUS_FIRMWARE_SLOT_INVALID,
+ MD_NTSTATUS_WIN_STATUS_FIRMWARE_IMAGE_INVALID,
+ MD_NTSTATUS_WIN_STATUS_STORAGE_TOPOLOGY_ID_MISMATCH,
+ MD_NTSTATUS_WIN_STATUS_WIM_NOT_BOOTABLE,
+ MD_NTSTATUS_WIN_STATUS_BLOCKED_BY_PARENTAL_CONTROLS,
+ MD_NTSTATUS_WIN_STATUS_NEEDS_REGISTRATION,
+ MD_NTSTATUS_WIN_STATUS_QUOTA_ACTIVITY,
+ MD_NTSTATUS_WIN_STATUS_CALLBACK_INVOKE_INLINE,
+ MD_NTSTATUS_WIN_STATUS_BLOCK_TOO_MANY_REFERENCES,
+ MD_NTSTATUS_WIN_STATUS_MARKED_TO_DISALLOW_WRITES,
+ MD_NTSTATUS_WIN_STATUS_NETWORK_ACCESS_DENIED_EDP,
+ MD_NTSTATUS_WIN_STATUS_ENCLAVE_FAILURE,
+ MD_NTSTATUS_WIN_STATUS_PNP_NO_COMPAT_DRIVERS,
+ MD_NTSTATUS_WIN_STATUS_PNP_DRIVER_PACKAGE_NOT_FOUND,
+ MD_NTSTATUS_WIN_STATUS_PNP_DRIVER_CONFIGURATION_NOT_FOUND,
+ MD_NTSTATUS_WIN_STATUS_PNP_DRIVER_CONFIGURATION_INCOMPLETE,
+ MD_NTSTATUS_WIN_STATUS_PNP_FUNCTION_DRIVER_REQUIRED,
+ MD_NTSTATUS_WIN_STATUS_PNP_DEVICE_CONFIGURATION_PENDING,
+ MD_NTSTATUS_WIN_STATUS_DEVICE_HINT_NAME_BUFFER_TOO_SMALL,
+ MD_NTSTATUS_WIN_STATUS_PACKAGE_NOT_AVAILABLE,
+ MD_NTSTATUS_WIN_STATUS_DEVICE_IN_MAINTENANCE,
+ MD_NTSTATUS_WIN_STATUS_NOT_SUPPORTED_ON_DAX,
+ MD_NTSTATUS_WIN_STATUS_FREE_SPACE_TOO_FRAGMENTED,
+ MD_NTSTATUS_WIN_STATUS_DAX_MAPPING_EXISTS,
+ MD_NTSTATUS_WIN_STATUS_CHILD_PROCESS_BLOCKED,
+ MD_NTSTATUS_WIN_STATUS_STORAGE_LOST_DATA_PERSISTENCE,
+ MD_NTSTATUS_WIN_STATUS_VRF_CFG_AND_IO_ENABLED,
+ MD_NTSTATUS_WIN_STATUS_PARTITION_TERMINATING,
+ MD_NTSTATUS_WIN_STATUS_EXTERNAL_SYSKEY_NOT_SUPPORTED,
+ MD_NTSTATUS_WIN_STATUS_ENCLAVE_VIOLATION,
+ MD_NTSTATUS_WIN_STATUS_FILE_PROTECTED_UNDER_DPL,
+ MD_NTSTATUS_WIN_STATUS_VOLUME_NOT_CLUSTER_ALIGNED,
+ MD_NTSTATUS_WIN_STATUS_NO_PHYSICALLY_ALIGNED_FREE_SPACE_FOUND,
+ MD_NTSTATUS_WIN_STATUS_APPX_FILE_NOT_ENCRYPTED,
+ MD_NTSTATUS_WIN_STATUS_RWRAW_ENCRYPTED_FILE_NOT_ENCRYPTED,
+ MD_NTSTATUS_WIN_STATUS_RWRAW_ENCRYPTED_INVALID_EDATAINFO_FILEOFFSET,
+ MD_NTSTATUS_WIN_STATUS_RWRAW_ENCRYPTED_INVALID_EDATAINFO_FILERANGE,
+ MD_NTSTATUS_WIN_STATUS_RWRAW_ENCRYPTED_INVALID_EDATAINFO_PARAMETER,
+ MD_NTSTATUS_WIN_STATUS_FT_READ_FAILURE,
+ MD_NTSTATUS_WIN_STATUS_PATCH_CONFLICT,
+ MD_NTSTATUS_WIN_STATUS_STORAGE_RESERVE_ID_INVALID,
+ MD_NTSTATUS_WIN_STATUS_STORAGE_RESERVE_DOES_NOT_EXIST,
+ MD_NTSTATUS_WIN_STATUS_STORAGE_RESERVE_ALREADY_EXISTS,
+ MD_NTSTATUS_WIN_STATUS_STORAGE_RESERVE_NOT_EMPTY,
+ MD_NTSTATUS_WIN_STATUS_NOT_A_DAX_VOLUME,
+ MD_NTSTATUS_WIN_STATUS_NOT_DAX_MAPPABLE,
+ MD_NTSTATUS_WIN_STATUS_CASE_DIFFERING_NAMES_IN_DIR,
+ MD_NTSTATUS_WIN_STATUS_FILE_NOT_SUPPORTED,
+ MD_NTSTATUS_WIN_STATUS_NOT_SUPPORTED_WITH_BTT,
+ MD_NTSTATUS_WIN_STATUS_ENCRYPTION_DISABLED,
+ MD_NTSTATUS_WIN_STATUS_ENCRYPTING_METADATA_DISALLOWED,
+ MD_NTSTATUS_WIN_STATUS_CANT_CLEAR_ENCRYPTION_FLAG,
+ MD_NTSTATUS_WIN_STATUS_UNSATISFIED_DEPENDENCIES,
+ MD_NTSTATUS_WIN_STATUS_CASE_SENSITIVE_PATH,
+ MD_NTSTATUS_WIN_STATUS_HAS_SYSTEM_CRITICAL_FILES,
+ MD_NTSTATUS_WIN_STATUS_INVALID_TASK_NAME,
+ MD_NTSTATUS_WIN_STATUS_INVALID_TASK_INDEX,
+ MD_NTSTATUS_WIN_STATUS_THREAD_ALREADY_IN_TASK,
+ MD_NTSTATUS_WIN_STATUS_CALLBACK_BYPASS,
+ MD_NTSTATUS_WIN_STATUS_UNDEFINED_SCOPE,
+ MD_NTSTATUS_WIN_STATUS_INVALID_CAP,
+ MD_NTSTATUS_WIN_STATUS_NOT_GUI_PROCESS,
+ MD_NTSTATUS_WIN_STATUS_DEVICE_HUNG,
+ MD_NTSTATUS_WIN_STATUS_CONTAINER_ASSIGNED,
+ MD_NTSTATUS_WIN_STATUS_JOB_NO_CONTAINER,
+ MD_NTSTATUS_WIN_STATUS_DEVICE_UNRESPONSIVE,
+ MD_NTSTATUS_WIN_STATUS_REPARSE_POINT_ENCOUNTERED,
+ MD_NTSTATUS_WIN_STATUS_ATTRIBUTE_NOT_PRESENT,
+ MD_NTSTATUS_WIN_STATUS_NOT_A_TIERED_VOLUME,
+ MD_NTSTATUS_WIN_STATUS_ALREADY_HAS_STREAM_ID,
+ MD_NTSTATUS_WIN_STATUS_JOB_NOT_EMPTY,
+ MD_NTSTATUS_WIN_STATUS_ALREADY_INITIALIZED,
+ MD_NTSTATUS_WIN_STATUS_ENCLAVE_NOT_TERMINATED,
+ MD_NTSTATUS_WIN_STATUS_ENCLAVE_IS_TERMINATING,
+ MD_NTSTATUS_WIN_STATUS_SMB1_NOT_AVAILABLE,
+ MD_NTSTATUS_WIN_STATUS_SMR_GARBAGE_COLLECTION_REQUIRED,
+ MD_NTSTATUS_WIN_STATUS_INTERRUPTED,
+ MD_NTSTATUS_WIN_STATUS_THREAD_NOT_RUNNING,
+ MD_NTSTATUS_WIN_STATUS_FAIL_FAST_EXCEPTION,
+ MD_NTSTATUS_WIN_STATUS_IMAGE_CERT_REVOKED,
+ MD_NTSTATUS_WIN_STATUS_DYNAMIC_CODE_BLOCKED,
+ MD_NTSTATUS_WIN_STATUS_IMAGE_CERT_EXPIRED,
+ MD_NTSTATUS_WIN_STATUS_STRICT_CFG_VIOLATION,
+ MD_NTSTATUS_WIN_STATUS_SET_CONTEXT_DENIED,
+ MD_NTSTATUS_WIN_STATUS_CROSS_PARTITION_VIOLATION,
+ MD_NTSTATUS_WIN_STATUS_PORT_CLOSED,
+ MD_NTSTATUS_WIN_STATUS_MESSAGE_LOST,
+ MD_NTSTATUS_WIN_STATUS_INVALID_MESSAGE,
+ MD_NTSTATUS_WIN_STATUS_REQUEST_CANCELED,
+ MD_NTSTATUS_WIN_STATUS_RECURSIVE_DISPATCH,
+ MD_NTSTATUS_WIN_STATUS_LPC_RECEIVE_BUFFER_EXPECTED,
+ MD_NTSTATUS_WIN_STATUS_LPC_INVALID_CONNECTION_USAGE,
+ MD_NTSTATUS_WIN_STATUS_LPC_REQUESTS_NOT_ALLOWED,
+ MD_NTSTATUS_WIN_STATUS_RESOURCE_IN_USE,
+ MD_NTSTATUS_WIN_STATUS_HARDWARE_MEMORY_ERROR,
+ MD_NTSTATUS_WIN_STATUS_THREADPOOL_HANDLE_EXCEPTION,
+ MD_NTSTATUS_WIN_STATUS_THREADPOOL_SET_EVENT_ON_COMPLETION_FAILED,
+ MD_NTSTATUS_WIN_STATUS_THREADPOOL_RELEASE_SEMAPHORE_ON_COMPLETION_FAILED,
+ MD_NTSTATUS_WIN_STATUS_THREADPOOL_RELEASE_MUTEX_ON_COMPLETION_FAILED,
+ MD_NTSTATUS_WIN_STATUS_THREADPOOL_FREE_LIBRARY_ON_COMPLETION_FAILED,
+ MD_NTSTATUS_WIN_STATUS_THREADPOOL_RELEASED_DURING_OPERATION,
+ MD_NTSTATUS_WIN_STATUS_CALLBACK_RETURNED_WHILE_IMPERSONATING,
+ MD_NTSTATUS_WIN_STATUS_APC_RETURNED_WHILE_IMPERSONATING,
+ MD_NTSTATUS_WIN_STATUS_PROCESS_IS_PROTECTED,
+ MD_NTSTATUS_WIN_STATUS_MCA_EXCEPTION,
+ MD_NTSTATUS_WIN_STATUS_CERTIFICATE_MAPPING_NOT_UNIQUE,
+ MD_NTSTATUS_WIN_STATUS_SYMLINK_CLASS_DISABLED,
+ MD_NTSTATUS_WIN_STATUS_INVALID_IDN_NORMALIZATION,
+ MD_NTSTATUS_WIN_STATUS_NO_UNICODE_TRANSLATION,
+ MD_NTSTATUS_WIN_STATUS_ALREADY_REGISTERED,
+ MD_NTSTATUS_WIN_STATUS_CONTEXT_MISMATCH,
+ MD_NTSTATUS_WIN_STATUS_PORT_ALREADY_HAS_COMPLETION_LIST,
+ MD_NTSTATUS_WIN_STATUS_CALLBACK_RETURNED_THREAD_PRIORITY,
+ MD_NTSTATUS_WIN_STATUS_INVALID_THREAD,
+ MD_NTSTATUS_WIN_STATUS_CALLBACK_RETURNED_TRANSACTION,
+ MD_NTSTATUS_WIN_STATUS_CALLBACK_RETURNED_LDR_LOCK,
+ MD_NTSTATUS_WIN_STATUS_CALLBACK_RETURNED_LANG,
+ MD_NTSTATUS_WIN_STATUS_CALLBACK_RETURNED_PRI_BACK,
+ MD_NTSTATUS_WIN_STATUS_CALLBACK_RETURNED_THREAD_AFFINITY,
+ MD_NTSTATUS_WIN_STATUS_LPC_HANDLE_COUNT_EXCEEDED,
+ MD_NTSTATUS_WIN_STATUS_EXECUTABLE_MEMORY_WRITE,
+ MD_NTSTATUS_WIN_STATUS_KERNEL_EXECUTABLE_MEMORY_WRITE,
+ MD_NTSTATUS_WIN_STATUS_ATTACHED_EXECUTABLE_MEMORY_WRITE,
+ MD_NTSTATUS_WIN_STATUS_TRIGGERED_EXECUTABLE_MEMORY_WRITE,
+ MD_NTSTATUS_WIN_STATUS_DISK_REPAIR_DISABLED,
+ MD_NTSTATUS_WIN_STATUS_DS_DOMAIN_RENAME_IN_PROGRESS,
+ MD_NTSTATUS_WIN_STATUS_DISK_QUOTA_EXCEEDED,
+ MD_NTSTATUS_WIN_STATUS_CONTENT_BLOCKED,
+ MD_NTSTATUS_WIN_STATUS_BAD_CLUSTERS,
+ MD_NTSTATUS_WIN_STATUS_VOLUME_DIRTY,
+ MD_NTSTATUS_WIN_STATUS_DISK_REPAIR_UNSUCCESSFUL,
+ MD_NTSTATUS_WIN_STATUS_CORRUPT_LOG_OVERFULL,
+ MD_NTSTATUS_WIN_STATUS_CORRUPT_LOG_CORRUPTED,
+ MD_NTSTATUS_WIN_STATUS_CORRUPT_LOG_UNAVAILABLE,
+ MD_NTSTATUS_WIN_STATUS_CORRUPT_LOG_DELETED_FULL,
+ MD_NTSTATUS_WIN_STATUS_CORRUPT_LOG_CLEARED,
+ MD_NTSTATUS_WIN_STATUS_ORPHAN_NAME_EXHAUSTED,
+ MD_NTSTATUS_WIN_STATUS_PROACTIVE_SCAN_IN_PROGRESS,
+ MD_NTSTATUS_WIN_STATUS_ENCRYPTED_IO_NOT_POSSIBLE,
+ MD_NTSTATUS_WIN_STATUS_CORRUPT_LOG_UPLEVEL_RECORDS,
+ MD_NTSTATUS_WIN_STATUS_FILE_CHECKED_OUT,
+ MD_NTSTATUS_WIN_STATUS_CHECKOUT_REQUIRED,
+ MD_NTSTATUS_WIN_STATUS_BAD_FILE_TYPE,
+ MD_NTSTATUS_WIN_STATUS_FILE_TOO_LARGE,
+ MD_NTSTATUS_WIN_STATUS_FORMS_AUTH_REQUIRED,
+ MD_NTSTATUS_WIN_STATUS_VIRUS_INFECTED,
+ MD_NTSTATUS_WIN_STATUS_VIRUS_DELETED,
+ MD_NTSTATUS_WIN_STATUS_BAD_MCFG_TABLE,
+ MD_NTSTATUS_WIN_STATUS_CANNOT_BREAK_OPLOCK,
+ MD_NTSTATUS_WIN_STATUS_BAD_KEY,
+ MD_NTSTATUS_WIN_STATUS_BAD_DATA,
+ MD_NTSTATUS_WIN_STATUS_NO_KEY,
+ MD_NTSTATUS_WIN_STATUS_FILE_HANDLE_REVOKED,
+ MD_NTSTATUS_WIN_STATUS_WOW_ASSERTION,
+ MD_NTSTATUS_WIN_STATUS_INVALID_SIGNATURE,
+ MD_NTSTATUS_WIN_STATUS_HMAC_NOT_SUPPORTED,
+ MD_NTSTATUS_WIN_STATUS_AUTH_TAG_MISMATCH,
+ MD_NTSTATUS_WIN_STATUS_INVALID_STATE_TRANSITION,
+ MD_NTSTATUS_WIN_STATUS_INVALID_KERNEL_INFO_VERSION,
+ MD_NTSTATUS_WIN_STATUS_INVALID_PEP_INFO_VERSION,
+ MD_NTSTATUS_WIN_STATUS_HANDLE_REVOKED,
+ MD_NTSTATUS_WIN_STATUS_EOF_ON_GHOSTED_RANGE,
+ MD_NTSTATUS_WIN_STATUS_CC_NEEDS_CALLBACK_SECTION_DRAIN,
+ MD_NTSTATUS_WIN_STATUS_IPSEC_QUEUE_OVERFLOW,
+ MD_NTSTATUS_WIN_STATUS_ND_QUEUE_OVERFLOW,
+ MD_NTSTATUS_WIN_STATUS_HOPLIMIT_EXCEEDED,
+ MD_NTSTATUS_WIN_STATUS_PROTOCOL_NOT_SUPPORTED,
+ MD_NTSTATUS_WIN_STATUS_FASTPATH_REJECTED,
+ MD_NTSTATUS_WIN_STATUS_LOST_WRITEBEHIND_DATA_NETWORK_DISCONNECTED,
+ MD_NTSTATUS_WIN_STATUS_LOST_WRITEBEHIND_DATA_NETWORK_SERVER_ERROR,
+ MD_NTSTATUS_WIN_STATUS_LOST_WRITEBEHIND_DATA_LOCAL_DISK_ERROR,
+ MD_NTSTATUS_WIN_STATUS_XML_PARSE_ERROR,
+ MD_NTSTATUS_WIN_STATUS_XMLDSIG_ERROR,
+ MD_NTSTATUS_WIN_STATUS_WRONG_COMPARTMENT,
+ MD_NTSTATUS_WIN_STATUS_AUTHIP_FAILURE,
+ MD_NTSTATUS_WIN_STATUS_DS_OID_MAPPED_GROUP_CANT_HAVE_MEMBERS,
+ MD_NTSTATUS_WIN_STATUS_DS_OID_NOT_FOUND,
+ MD_NTSTATUS_WIN_STATUS_INCORRECT_ACCOUNT_TYPE,
+ MD_NTSTATUS_WIN_STATUS_HASH_NOT_SUPPORTED,
+ MD_NTSTATUS_WIN_STATUS_HASH_NOT_PRESENT,
+ MD_NTSTATUS_WIN_STATUS_SECONDARY_IC_PROVIDER_NOT_REGISTERED,
+ MD_NTSTATUS_WIN_STATUS_GPIO_CLIENT_INFORMATION_INVALID,
+ MD_NTSTATUS_WIN_STATUS_GPIO_VERSION_NOT_SUPPORTED,
+ MD_NTSTATUS_WIN_STATUS_GPIO_INVALID_REGISTRATION_PACKET,
+ MD_NTSTATUS_WIN_STATUS_GPIO_OPERATION_DENIED,
+ MD_NTSTATUS_WIN_STATUS_GPIO_INCOMPATIBLE_CONNECT_MODE,
+ MD_NTSTATUS_WIN_STATUS_CANNOT_SWITCH_RUNLEVEL,
+ MD_NTSTATUS_WIN_STATUS_INVALID_RUNLEVEL_SETTING,
+ MD_NTSTATUS_WIN_STATUS_RUNLEVEL_SWITCH_TIMEOUT,
+ MD_NTSTATUS_WIN_STATUS_RUNLEVEL_SWITCH_AGENT_TIMEOUT,
+ MD_NTSTATUS_WIN_STATUS_RUNLEVEL_SWITCH_IN_PROGRESS,
+ MD_NTSTATUS_WIN_STATUS_NOT_APPCONTAINER,
+ MD_NTSTATUS_WIN_STATUS_NOT_SUPPORTED_IN_APPCONTAINER,
+ MD_NTSTATUS_WIN_STATUS_INVALID_PACKAGE_SID_LENGTH,
+ MD_NTSTATUS_WIN_STATUS_LPAC_ACCESS_DENIED,
+ MD_NTSTATUS_WIN_STATUS_ADMINLESS_ACCESS_DENIED,
+ MD_NTSTATUS_WIN_STATUS_APP_DATA_NOT_FOUND,
+ MD_NTSTATUS_WIN_STATUS_APP_DATA_EXPIRED,
+ MD_NTSTATUS_WIN_STATUS_APP_DATA_CORRUPT,
+ MD_NTSTATUS_WIN_STATUS_APP_DATA_LIMIT_EXCEEDED,
+ MD_NTSTATUS_WIN_STATUS_APP_DATA_REBOOT_REQUIRED,
+ MD_NTSTATUS_WIN_STATUS_OFFLOAD_READ_FLT_NOT_SUPPORTED,
+ MD_NTSTATUS_WIN_STATUS_OFFLOAD_WRITE_FLT_NOT_SUPPORTED,
+ MD_NTSTATUS_WIN_STATUS_OFFLOAD_READ_FILE_NOT_SUPPORTED,
+ MD_NTSTATUS_WIN_STATUS_OFFLOAD_WRITE_FILE_NOT_SUPPORTED,
+ MD_NTSTATUS_WIN_STATUS_WOF_WIM_HEADER_CORRUPT,
+ MD_NTSTATUS_WIN_STATUS_WOF_WIM_RESOURCE_TABLE_CORRUPT,
+ MD_NTSTATUS_WIN_STATUS_WOF_FILE_RESOURCE_TABLE_CORRUPT,
+ MD_NTSTATUS_WIN_STATUS_CIMFS_IMAGE_CORRUPT,
+ MD_NTSTATUS_WIN_STATUS_FILE_SYSTEM_VIRTUALIZATION_UNAVAILABLE,
+ MD_NTSTATUS_WIN_STATUS_FILE_SYSTEM_VIRTUALIZATION_METADATA_CORRUPT,
+ MD_NTSTATUS_WIN_STATUS_FILE_SYSTEM_VIRTUALIZATION_BUSY,
+ MD_NTSTATUS_WIN_STATUS_FILE_SYSTEM_VIRTUALIZATION_PROVIDER_UNKNOWN,
+ MD_NTSTATUS_WIN_STATUS_FILE_SYSTEM_VIRTUALIZATION_INVALID_OPERATION,
+ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_SYNC_ROOT_METADATA_CORRUPT,
+ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_PROVIDER_NOT_RUNNING,
+ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_METADATA_CORRUPT,
+ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_METADATA_TOO_LARGE,
+ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_PROPERTY_VERSION_NOT_SUPPORTED,
+ MD_NTSTATUS_WIN_STATUS_NOT_A_CLOUD_FILE,
+ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_NOT_IN_SYNC,
+ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_ALREADY_CONNECTED,
+ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_NOT_SUPPORTED,
+ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_INVALID_REQUEST,
+ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_READ_ONLY_VOLUME,
+ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_CONNECTED_PROVIDER_ONLY,
+ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_VALIDATION_FAILED,
+ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_AUTHENTICATION_FAILED,
+ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_INSUFFICIENT_RESOURCES,
+ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_NETWORK_UNAVAILABLE,
+ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_UNSUCCESSFUL,
+ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_NOT_UNDER_SYNC_ROOT,
+ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_IN_USE,
+ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_PINNED,
+ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_REQUEST_ABORTED,
+ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_PROPERTY_CORRUPT,
+ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_ACCESS_DENIED,
+ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_INCOMPATIBLE_HARDLINKS,
+ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_PROPERTY_LOCK_CONFLICT,
+ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_REQUEST_CANCELED,
+ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_PROVIDER_TERMINATED,
+ MD_NTSTATUS_WIN_STATUS_NOT_A_CLOUD_SYNC_ROOT,
+ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_REQUEST_TIMEOUT,
+ MD_NTSTATUS_WIN_STATUS_CLOUD_FILE_DEHYDRATION_DISALLOWED,
+ MD_NTSTATUS_WIN_STATUS_FILE_SNAP_IN_PROGRESS,
+ MD_NTSTATUS_WIN_STATUS_FILE_SNAP_USER_SECTION_NOT_SUPPORTED,
+ MD_NTSTATUS_WIN_STATUS_FILE_SNAP_MODIFY_NOT_SUPPORTED,
+ MD_NTSTATUS_WIN_STATUS_FILE_SNAP_IO_NOT_COORDINATED,
+ MD_NTSTATUS_WIN_STATUS_FILE_SNAP_UNEXPECTED_ERROR,
+ MD_NTSTATUS_WIN_STATUS_FILE_SNAP_INVALID_PARAMETER,
+ MD_NTSTATUS_WIN_DBG_NO_STATE_CHANGE,
+ MD_NTSTATUS_WIN_DBG_APP_NOT_IDLE,
+ MD_NTSTATUS_WIN_RPC_NT_INVALID_STRING_BINDING,
+ MD_NTSTATUS_WIN_RPC_NT_WRONG_KIND_OF_BINDING,
+ MD_NTSTATUS_WIN_RPC_NT_INVALID_BINDING,
+ MD_NTSTATUS_WIN_RPC_NT_PROTSEQ_NOT_SUPPORTED,
+ MD_NTSTATUS_WIN_RPC_NT_INVALID_RPC_PROTSEQ,
+ MD_NTSTATUS_WIN_RPC_NT_INVALID_STRING_UUID,
+ MD_NTSTATUS_WIN_RPC_NT_INVALID_ENDPOINT_FORMAT,
+ MD_NTSTATUS_WIN_RPC_NT_INVALID_NET_ADDR,
+ MD_NTSTATUS_WIN_RPC_NT_NO_ENDPOINT_FOUND,
+ MD_NTSTATUS_WIN_RPC_NT_INVALID_TIMEOUT,
+ MD_NTSTATUS_WIN_RPC_NT_OBJECT_NOT_FOUND,
+ MD_NTSTATUS_WIN_RPC_NT_ALREADY_REGISTERED,
+ MD_NTSTATUS_WIN_RPC_NT_TYPE_ALREADY_REGISTERED,
+ MD_NTSTATUS_WIN_RPC_NT_ALREADY_LISTENING,
+ MD_NTSTATUS_WIN_RPC_NT_NO_PROTSEQS_REGISTERED,
+ MD_NTSTATUS_WIN_RPC_NT_NOT_LISTENING,
+ MD_NTSTATUS_WIN_RPC_NT_UNKNOWN_MGR_TYPE,
+ MD_NTSTATUS_WIN_RPC_NT_UNKNOWN_IF,
+ MD_NTSTATUS_WIN_RPC_NT_NO_BINDINGS,
+ MD_NTSTATUS_WIN_RPC_NT_NO_PROTSEQS,
+ MD_NTSTATUS_WIN_RPC_NT_CANT_CREATE_ENDPOINT,
+ MD_NTSTATUS_WIN_RPC_NT_OUT_OF_RESOURCES,
+ MD_NTSTATUS_WIN_RPC_NT_SERVER_UNAVAILABLE,
+ MD_NTSTATUS_WIN_RPC_NT_SERVER_TOO_BUSY,
+ MD_NTSTATUS_WIN_RPC_NT_INVALID_NETWORK_OPTIONS,
+ MD_NTSTATUS_WIN_RPC_NT_NO_CALL_ACTIVE,
+ MD_NTSTATUS_WIN_RPC_NT_CALL_FAILED,
+ MD_NTSTATUS_WIN_RPC_NT_CALL_FAILED_DNE,
+ MD_NTSTATUS_WIN_RPC_NT_PROTOCOL_ERROR,
+ MD_NTSTATUS_WIN_RPC_NT_UNSUPPORTED_TRANS_SYN,
+ MD_NTSTATUS_WIN_RPC_NT_UNSUPPORTED_TYPE,
+ MD_NTSTATUS_WIN_RPC_NT_INVALID_TAG,
+ MD_NTSTATUS_WIN_RPC_NT_INVALID_BOUND,
+ MD_NTSTATUS_WIN_RPC_NT_NO_ENTRY_NAME,
+ MD_NTSTATUS_WIN_RPC_NT_INVALID_NAME_SYNTAX,
+ MD_NTSTATUS_WIN_RPC_NT_UNSUPPORTED_NAME_SYNTAX,
+ MD_NTSTATUS_WIN_RPC_NT_UUID_NO_ADDRESS,
+ MD_NTSTATUS_WIN_RPC_NT_DUPLICATE_ENDPOINT,
+ MD_NTSTATUS_WIN_RPC_NT_UNKNOWN_AUTHN_TYPE,
+ MD_NTSTATUS_WIN_RPC_NT_MAX_CALLS_TOO_SMALL,
+ MD_NTSTATUS_WIN_RPC_NT_STRING_TOO_LONG,
+ MD_NTSTATUS_WIN_RPC_NT_PROTSEQ_NOT_FOUND,
+ MD_NTSTATUS_WIN_RPC_NT_PROCNUM_OUT_OF_RANGE,
+ MD_NTSTATUS_WIN_RPC_NT_BINDING_HAS_NO_AUTH,
+ MD_NTSTATUS_WIN_RPC_NT_UNKNOWN_AUTHN_SERVICE,
+ MD_NTSTATUS_WIN_RPC_NT_UNKNOWN_AUTHN_LEVEL,
+ MD_NTSTATUS_WIN_RPC_NT_INVALID_AUTH_IDENTITY,
+ MD_NTSTATUS_WIN_RPC_NT_UNKNOWN_AUTHZ_SERVICE,
+ MD_NTSTATUS_WIN_EPT_NT_INVALID_ENTRY,
+ MD_NTSTATUS_WIN_EPT_NT_CANT_PERFORM_OP,
+ MD_NTSTATUS_WIN_EPT_NT_NOT_REGISTERED,
+ MD_NTSTATUS_WIN_RPC_NT_NOTHING_TO_EXPORT,
+ MD_NTSTATUS_WIN_RPC_NT_INCOMPLETE_NAME,
+ MD_NTSTATUS_WIN_RPC_NT_INVALID_VERS_OPTION,
+ MD_NTSTATUS_WIN_RPC_NT_NO_MORE_MEMBERS,
+ MD_NTSTATUS_WIN_RPC_NT_NOT_ALL_OBJS_UNEXPORTED,
+ MD_NTSTATUS_WIN_RPC_NT_INTERFACE_NOT_FOUND,
+ MD_NTSTATUS_WIN_RPC_NT_ENTRY_ALREADY_EXISTS,
+ MD_NTSTATUS_WIN_RPC_NT_ENTRY_NOT_FOUND,
+ MD_NTSTATUS_WIN_RPC_NT_NAME_SERVICE_UNAVAILABLE,
+ MD_NTSTATUS_WIN_RPC_NT_INVALID_NAF_ID,
+ MD_NTSTATUS_WIN_RPC_NT_CANNOT_SUPPORT,
+ MD_NTSTATUS_WIN_RPC_NT_NO_CONTEXT_AVAILABLE,
+ MD_NTSTATUS_WIN_RPC_NT_INTERNAL_ERROR,
+ MD_NTSTATUS_WIN_RPC_NT_ZERO_DIVIDE,
+ MD_NTSTATUS_WIN_RPC_NT_ADDRESS_ERROR,
+ MD_NTSTATUS_WIN_RPC_NT_FP_DIV_ZERO,
+ MD_NTSTATUS_WIN_RPC_NT_FP_UNDERFLOW,
+ MD_NTSTATUS_WIN_RPC_NT_FP_OVERFLOW,
+ MD_NTSTATUS_WIN_RPC_NT_CALL_IN_PROGRESS,
+ MD_NTSTATUS_WIN_RPC_NT_NO_MORE_BINDINGS,
+ MD_NTSTATUS_WIN_RPC_NT_GROUP_MEMBER_NOT_FOUND,
+ MD_NTSTATUS_WIN_EPT_NT_CANT_CREATE,
+ MD_NTSTATUS_WIN_RPC_NT_INVALID_OBJECT,
+ MD_NTSTATUS_WIN_RPC_NT_NO_INTERFACES,
+ MD_NTSTATUS_WIN_RPC_NT_CALL_CANCELLED,
+ MD_NTSTATUS_WIN_RPC_NT_BINDING_INCOMPLETE,
+ MD_NTSTATUS_WIN_RPC_NT_COMM_FAILURE,
+ MD_NTSTATUS_WIN_RPC_NT_UNSUPPORTED_AUTHN_LEVEL,
+ MD_NTSTATUS_WIN_RPC_NT_NO_PRINC_NAME,
+ MD_NTSTATUS_WIN_RPC_NT_NOT_RPC_ERROR,
+ MD_NTSTATUS_WIN_RPC_NT_SEC_PKG_ERROR,
+ MD_NTSTATUS_WIN_RPC_NT_NOT_CANCELLED,
+ MD_NTSTATUS_WIN_RPC_NT_INVALID_ASYNC_HANDLE,
+ MD_NTSTATUS_WIN_RPC_NT_INVALID_ASYNC_CALL,
+ MD_NTSTATUS_WIN_RPC_NT_PROXY_ACCESS_DENIED,
+ MD_NTSTATUS_WIN_RPC_NT_COOKIE_AUTH_FAILED,
+ MD_NTSTATUS_WIN_RPC_NT_NO_MORE_ENTRIES,
+ MD_NTSTATUS_WIN_RPC_NT_SS_CHAR_TRANS_OPEN_FAIL,
+ MD_NTSTATUS_WIN_RPC_NT_SS_CHAR_TRANS_SHORT_FILE,
+ MD_NTSTATUS_WIN_RPC_NT_SS_IN_NULL_CONTEXT,
+ MD_NTSTATUS_WIN_RPC_NT_SS_CONTEXT_MISMATCH,
+ MD_NTSTATUS_WIN_RPC_NT_SS_CONTEXT_DAMAGED,
+ MD_NTSTATUS_WIN_RPC_NT_SS_HANDLES_MISMATCH,
+ MD_NTSTATUS_WIN_RPC_NT_SS_CANNOT_GET_CALL_HANDLE,
+ MD_NTSTATUS_WIN_RPC_NT_NULL_REF_POINTER,
+ MD_NTSTATUS_WIN_RPC_NT_ENUM_VALUE_OUT_OF_RANGE,
+ MD_NTSTATUS_WIN_RPC_NT_BYTE_COUNT_TOO_SMALL,
+ MD_NTSTATUS_WIN_RPC_NT_BAD_STUB_DATA,
+ MD_NTSTATUS_WIN_RPC_NT_INVALID_ES_ACTION,
+ MD_NTSTATUS_WIN_RPC_NT_WRONG_ES_VERSION,
+ MD_NTSTATUS_WIN_RPC_NT_WRONG_STUB_VERSION,
+ MD_NTSTATUS_WIN_RPC_NT_INVALID_PIPE_OBJECT,
+ MD_NTSTATUS_WIN_RPC_NT_INVALID_PIPE_OPERATION,
+ MD_NTSTATUS_WIN_RPC_NT_WRONG_PIPE_VERSION,
+ MD_NTSTATUS_WIN_RPC_NT_PIPE_CLOSED,
+ MD_NTSTATUS_WIN_RPC_NT_PIPE_DISCIPLINE_ERROR,
+ MD_NTSTATUS_WIN_RPC_NT_PIPE_EMPTY,
+ MD_NTSTATUS_WIN_STATUS_PNP_BAD_MPS_TABLE,
+ MD_NTSTATUS_WIN_STATUS_PNP_TRANSLATION_FAILED,
+ MD_NTSTATUS_WIN_STATUS_PNP_IRQ_TRANSLATION_FAILED,
+ MD_NTSTATUS_WIN_STATUS_PNP_INVALID_ID,
+ MD_NTSTATUS_WIN_STATUS_IO_REISSUE_AS_CACHED,
+ MD_NTSTATUS_WIN_STATUS_CTX_WINSTATION_NAME_INVALID,
+ MD_NTSTATUS_WIN_STATUS_CTX_INVALID_PD,
+ MD_NTSTATUS_WIN_STATUS_CTX_PD_NOT_FOUND,
+ MD_NTSTATUS_WIN_STATUS_CTX_CLOSE_PENDING,
+ MD_NTSTATUS_WIN_STATUS_CTX_NO_OUTBUF,
+ MD_NTSTATUS_WIN_STATUS_CTX_MODEM_INF_NOT_FOUND,
+ MD_NTSTATUS_WIN_STATUS_CTX_INVALID_MODEMNAME,
+ MD_NTSTATUS_WIN_STATUS_CTX_RESPONSE_ERROR,
+ MD_NTSTATUS_WIN_STATUS_CTX_MODEM_RESPONSE_TIMEOUT,
+ MD_NTSTATUS_WIN_STATUS_CTX_MODEM_RESPONSE_NO_CARRIER,
+ MD_NTSTATUS_WIN_STATUS_CTX_MODEM_RESPONSE_NO_DIALTONE,
+ MD_NTSTATUS_WIN_STATUS_CTX_MODEM_RESPONSE_BUSY,
+ MD_NTSTATUS_WIN_STATUS_CTX_MODEM_RESPONSE_VOICE,
+ MD_NTSTATUS_WIN_STATUS_CTX_TD_ERROR,
+ MD_NTSTATUS_WIN_STATUS_CTX_LICENSE_CLIENT_INVALID,
+ MD_NTSTATUS_WIN_STATUS_CTX_LICENSE_NOT_AVAILABLE,
+ MD_NTSTATUS_WIN_STATUS_CTX_LICENSE_EXPIRED,
+ MD_NTSTATUS_WIN_STATUS_CTX_WINSTATION_NOT_FOUND,
+ MD_NTSTATUS_WIN_STATUS_CTX_WINSTATION_NAME_COLLISION,
+ MD_NTSTATUS_WIN_STATUS_CTX_WINSTATION_BUSY,
+ MD_NTSTATUS_WIN_STATUS_CTX_BAD_VIDEO_MODE,
+ MD_NTSTATUS_WIN_STATUS_CTX_GRAPHICS_INVALID,
+ MD_NTSTATUS_WIN_STATUS_CTX_NOT_CONSOLE,
+ MD_NTSTATUS_WIN_STATUS_CTX_CLIENT_QUERY_TIMEOUT,
+ MD_NTSTATUS_WIN_STATUS_CTX_CONSOLE_DISCONNECT,
+ MD_NTSTATUS_WIN_STATUS_CTX_CONSOLE_CONNECT,
+ MD_NTSTATUS_WIN_STATUS_CTX_SHADOW_DENIED,
+ MD_NTSTATUS_WIN_STATUS_CTX_WINSTATION_ACCESS_DENIED,
+ MD_NTSTATUS_WIN_STATUS_CTX_INVALID_WD,
+ MD_NTSTATUS_WIN_STATUS_CTX_WD_NOT_FOUND,
+ MD_NTSTATUS_WIN_STATUS_CTX_SHADOW_INVALID,
+ MD_NTSTATUS_WIN_STATUS_CTX_SHADOW_DISABLED,
+ MD_NTSTATUS_WIN_STATUS_RDP_PROTOCOL_ERROR,
+ MD_NTSTATUS_WIN_STATUS_CTX_CLIENT_LICENSE_NOT_SET,
+ MD_NTSTATUS_WIN_STATUS_CTX_CLIENT_LICENSE_IN_USE,
+ MD_NTSTATUS_WIN_STATUS_CTX_SHADOW_ENDED_BY_MODE_CHANGE,
+ MD_NTSTATUS_WIN_STATUS_CTX_SHADOW_NOT_RUNNING,
+ MD_NTSTATUS_WIN_STATUS_CTX_LOGON_DISABLED,
+ MD_NTSTATUS_WIN_STATUS_CTX_SECURITY_LAYER_ERROR,
+ MD_NTSTATUS_WIN_STATUS_TS_INCOMPATIBLE_SESSIONS,
+ MD_NTSTATUS_WIN_STATUS_TS_VIDEO_SUBSYSTEM_ERROR,
+ MD_NTSTATUS_WIN_STATUS_MUI_FILE_NOT_FOUND,
+ MD_NTSTATUS_WIN_STATUS_MUI_INVALID_FILE,
+ MD_NTSTATUS_WIN_STATUS_MUI_INVALID_RC_CONFIG,
+ MD_NTSTATUS_WIN_STATUS_MUI_INVALID_LOCALE_NAME,
+ MD_NTSTATUS_WIN_STATUS_MUI_INVALID_ULTIMATEFALLBACK_NAME,
+ MD_NTSTATUS_WIN_STATUS_MUI_FILE_NOT_LOADED,
+ MD_NTSTATUS_WIN_STATUS_RESOURCE_ENUM_USER_STOP,
+ MD_NTSTATUS_WIN_STATUS_CLUSTER_INVALID_NODE,
+ MD_NTSTATUS_WIN_STATUS_CLUSTER_NODE_EXISTS,
+ MD_NTSTATUS_WIN_STATUS_CLUSTER_JOIN_IN_PROGRESS,
+ MD_NTSTATUS_WIN_STATUS_CLUSTER_NODE_NOT_FOUND,
+ MD_NTSTATUS_WIN_STATUS_CLUSTER_LOCAL_NODE_NOT_FOUND,
+ MD_NTSTATUS_WIN_STATUS_CLUSTER_NETWORK_EXISTS,
+ MD_NTSTATUS_WIN_STATUS_CLUSTER_NETWORK_NOT_FOUND,
+ MD_NTSTATUS_WIN_STATUS_CLUSTER_NETINTERFACE_EXISTS,
+ MD_NTSTATUS_WIN_STATUS_CLUSTER_NETINTERFACE_NOT_FOUND,
+ MD_NTSTATUS_WIN_STATUS_CLUSTER_INVALID_REQUEST,
+ MD_NTSTATUS_WIN_STATUS_CLUSTER_INVALID_NETWORK_PROVIDER,
+ MD_NTSTATUS_WIN_STATUS_CLUSTER_NODE_DOWN,
+ MD_NTSTATUS_WIN_STATUS_CLUSTER_NODE_UNREACHABLE,
+ MD_NTSTATUS_WIN_STATUS_CLUSTER_NODE_NOT_MEMBER,
+ MD_NTSTATUS_WIN_STATUS_CLUSTER_JOIN_NOT_IN_PROGRESS,
+ MD_NTSTATUS_WIN_STATUS_CLUSTER_INVALID_NETWORK,
+ MD_NTSTATUS_WIN_STATUS_CLUSTER_NO_NET_ADAPTERS,
+ MD_NTSTATUS_WIN_STATUS_CLUSTER_NODE_UP,
+ MD_NTSTATUS_WIN_STATUS_CLUSTER_NODE_PAUSED,
+ MD_NTSTATUS_WIN_STATUS_CLUSTER_NODE_NOT_PAUSED,
+ MD_NTSTATUS_WIN_STATUS_CLUSTER_NO_SECURITY_CONTEXT,
+ MD_NTSTATUS_WIN_STATUS_CLUSTER_NETWORK_NOT_INTERNAL,
+ MD_NTSTATUS_WIN_STATUS_CLUSTER_POISONED,
+ MD_NTSTATUS_WIN_STATUS_CLUSTER_NON_CSV_PATH,
+ MD_NTSTATUS_WIN_STATUS_CLUSTER_CSV_VOLUME_NOT_LOCAL,
+ MD_NTSTATUS_WIN_STATUS_CLUSTER_CSV_READ_OPLOCK_BREAK_IN_PROGRESS,
+ MD_NTSTATUS_WIN_STATUS_CLUSTER_CSV_AUTO_PAUSE_ERROR,
+ MD_NTSTATUS_WIN_STATUS_CLUSTER_CSV_REDIRECTED,
+ MD_NTSTATUS_WIN_STATUS_CLUSTER_CSV_NOT_REDIRECTED,
+ MD_NTSTATUS_WIN_STATUS_CLUSTER_CSV_VOLUME_DRAINING,
+ MD_NTSTATUS_WIN_STATUS_CLUSTER_CSV_SNAPSHOT_CREATION_IN_PROGRESS,
+ MD_NTSTATUS_WIN_STATUS_CLUSTER_CSV_VOLUME_DRAINING_SUCCEEDED_DOWNLEVEL,
+ MD_NTSTATUS_WIN_STATUS_CLUSTER_CSV_NO_SNAPSHOTS,
+ MD_NTSTATUS_WIN_STATUS_CSV_IO_PAUSE_TIMEOUT,
+ MD_NTSTATUS_WIN_STATUS_CLUSTER_CSV_INVALID_HANDLE,
+ MD_NTSTATUS_WIN_STATUS_CLUSTER_CSV_SUPPORTED_ONLY_ON_COORDINATOR,
+ MD_NTSTATUS_WIN_STATUS_CLUSTER_CAM_TICKET_REPLAY_DETECTED,
+ MD_NTSTATUS_WIN_STATUS_ACPI_INVALID_OPCODE,
+ MD_NTSTATUS_WIN_STATUS_ACPI_STACK_OVERFLOW,
+ MD_NTSTATUS_WIN_STATUS_ACPI_ASSERT_FAILED,
+ MD_NTSTATUS_WIN_STATUS_ACPI_INVALID_INDEX,
+ MD_NTSTATUS_WIN_STATUS_ACPI_INVALID_ARGUMENT,
+ MD_NTSTATUS_WIN_STATUS_ACPI_FATAL,
+ MD_NTSTATUS_WIN_STATUS_ACPI_INVALID_SUPERNAME,
+ MD_NTSTATUS_WIN_STATUS_ACPI_INVALID_ARGTYPE,
+ MD_NTSTATUS_WIN_STATUS_ACPI_INVALID_OBJTYPE,
+ MD_NTSTATUS_WIN_STATUS_ACPI_INVALID_TARGETTYPE,
+ MD_NTSTATUS_WIN_STATUS_ACPI_INCORRECT_ARGUMENT_COUNT,
+ MD_NTSTATUS_WIN_STATUS_ACPI_ADDRESS_NOT_MAPPED,
+ MD_NTSTATUS_WIN_STATUS_ACPI_INVALID_EVENTTYPE,
+ MD_NTSTATUS_WIN_STATUS_ACPI_HANDLER_COLLISION,
+ MD_NTSTATUS_WIN_STATUS_ACPI_INVALID_DATA,
+ MD_NTSTATUS_WIN_STATUS_ACPI_INVALID_REGION,
+ MD_NTSTATUS_WIN_STATUS_ACPI_INVALID_ACCESS_SIZE,
+ MD_NTSTATUS_WIN_STATUS_ACPI_ACQUIRE_GLOBAL_LOCK,
+ MD_NTSTATUS_WIN_STATUS_ACPI_ALREADY_INITIALIZED,
+ MD_NTSTATUS_WIN_STATUS_ACPI_NOT_INITIALIZED,
+ MD_NTSTATUS_WIN_STATUS_ACPI_INVALID_MUTEX_LEVEL,
+ MD_NTSTATUS_WIN_STATUS_ACPI_MUTEX_NOT_OWNED,
+ MD_NTSTATUS_WIN_STATUS_ACPI_MUTEX_NOT_OWNER,
+ MD_NTSTATUS_WIN_STATUS_ACPI_RS_ACCESS,
+ MD_NTSTATUS_WIN_STATUS_ACPI_INVALID_TABLE,
+ MD_NTSTATUS_WIN_STATUS_ACPI_REG_HANDLER_FAILED,
+ MD_NTSTATUS_WIN_STATUS_ACPI_POWER_REQUEST_FAILED,
+ MD_NTSTATUS_WIN_STATUS_SXS_SECTION_NOT_FOUND,
+ MD_NTSTATUS_WIN_STATUS_SXS_CANT_GEN_ACTCTX,
+ MD_NTSTATUS_WIN_STATUS_SXS_INVALID_ACTCTXDATA_FORMAT,
+ MD_NTSTATUS_WIN_STATUS_SXS_ASSEMBLY_NOT_FOUND,
+ MD_NTSTATUS_WIN_STATUS_SXS_MANIFEST_FORMAT_ERROR,
+ MD_NTSTATUS_WIN_STATUS_SXS_MANIFEST_PARSE_ERROR,
+ MD_NTSTATUS_WIN_STATUS_SXS_ACTIVATION_CONTEXT_DISABLED,
+ MD_NTSTATUS_WIN_STATUS_SXS_KEY_NOT_FOUND,
+ MD_NTSTATUS_WIN_STATUS_SXS_VERSION_CONFLICT,
+ MD_NTSTATUS_WIN_STATUS_SXS_WRONG_SECTION_TYPE,
+ MD_NTSTATUS_WIN_STATUS_SXS_THREAD_QUERIES_DISABLED,
+ MD_NTSTATUS_WIN_STATUS_SXS_ASSEMBLY_MISSING,
+ MD_NTSTATUS_WIN_STATUS_SXS_PROCESS_DEFAULT_ALREADY_SET,
+ MD_NTSTATUS_WIN_STATUS_SXS_EARLY_DEACTIVATION,
+ MD_NTSTATUS_WIN_STATUS_SXS_INVALID_DEACTIVATION,
+ MD_NTSTATUS_WIN_STATUS_SXS_MULTIPLE_DEACTIVATION,
+ MD_NTSTATUS_WIN_STATUS_SXS_SYSTEM_DEFAULT_ACTIVATION_CONTEXT_EMPTY,
+ MD_NTSTATUS_WIN_STATUS_SXS_PROCESS_TERMINATION_REQUESTED,
+ MD_NTSTATUS_WIN_STATUS_SXS_CORRUPT_ACTIVATION_STACK,
+ MD_NTSTATUS_WIN_STATUS_SXS_CORRUPTION,
+ MD_NTSTATUS_WIN_STATUS_SXS_INVALID_IDENTITY_ATTRIBUTE_VALUE,
+ MD_NTSTATUS_WIN_STATUS_SXS_INVALID_IDENTITY_ATTRIBUTE_NAME,
+ MD_NTSTATUS_WIN_STATUS_SXS_IDENTITY_DUPLICATE_ATTRIBUTE,
+ MD_NTSTATUS_WIN_STATUS_SXS_IDENTITY_PARSE_ERROR,
+ MD_NTSTATUS_WIN_STATUS_SXS_COMPONENT_STORE_CORRUPT,
+ MD_NTSTATUS_WIN_STATUS_SXS_FILE_HASH_MISMATCH,
+ MD_NTSTATUS_WIN_STATUS_SXS_MANIFEST_IDENTITY_SAME_BUT_CONTENTS_DIFFERENT,
+ MD_NTSTATUS_WIN_STATUS_SXS_IDENTITIES_DIFFERENT,
+ MD_NTSTATUS_WIN_STATUS_SXS_ASSEMBLY_IS_NOT_A_DEPLOYMENT,
+ MD_NTSTATUS_WIN_STATUS_SXS_FILE_NOT_PART_OF_ASSEMBLY,
+ MD_NTSTATUS_WIN_STATUS_ADVANCED_INSTALLER_FAILED,
+ MD_NTSTATUS_WIN_STATUS_XML_ENCODING_MISMATCH,
+ MD_NTSTATUS_WIN_STATUS_SXS_MANIFEST_TOO_BIG,
+ MD_NTSTATUS_WIN_STATUS_SXS_SETTING_NOT_REGISTERED,
+ MD_NTSTATUS_WIN_STATUS_SXS_TRANSACTION_CLOSURE_INCOMPLETE,
+ MD_NTSTATUS_WIN_STATUS_SMI_PRIMITIVE_INSTALLER_FAILED,
+ MD_NTSTATUS_WIN_STATUS_GENERIC_COMMAND_FAILED,
+ MD_NTSTATUS_WIN_STATUS_SXS_FILE_HASH_MISSING,
+ MD_NTSTATUS_WIN_STATUS_TRANSACTIONAL_CONFLICT,
+ MD_NTSTATUS_WIN_STATUS_INVALID_TRANSACTION,
+ MD_NTSTATUS_WIN_STATUS_TRANSACTION_NOT_ACTIVE,
+ MD_NTSTATUS_WIN_STATUS_TM_INITIALIZATION_FAILED,
+ MD_NTSTATUS_WIN_STATUS_RM_NOT_ACTIVE,
+ MD_NTSTATUS_WIN_STATUS_RM_METADATA_CORRUPT,
+ MD_NTSTATUS_WIN_STATUS_TRANSACTION_NOT_JOINED,
+ MD_NTSTATUS_WIN_STATUS_DIRECTORY_NOT_RM,
+ MD_NTSTATUS_WIN_STATUS_TRANSACTIONS_UNSUPPORTED_REMOTE,
+ MD_NTSTATUS_WIN_STATUS_LOG_RESIZE_INVALID_SIZE,
+ MD_NTSTATUS_WIN_STATUS_REMOTE_FILE_VERSION_MISMATCH,
+ MD_NTSTATUS_WIN_STATUS_CRM_PROTOCOL_ALREADY_EXISTS,
+ MD_NTSTATUS_WIN_STATUS_TRANSACTION_PROPAGATION_FAILED,
+ MD_NTSTATUS_WIN_STATUS_CRM_PROTOCOL_NOT_FOUND,
+ MD_NTSTATUS_WIN_STATUS_TRANSACTION_SUPERIOR_EXISTS,
+ MD_NTSTATUS_WIN_STATUS_TRANSACTION_REQUEST_NOT_VALID,
+ MD_NTSTATUS_WIN_STATUS_TRANSACTION_NOT_REQUESTED,
+ MD_NTSTATUS_WIN_STATUS_TRANSACTION_ALREADY_ABORTED,
+ MD_NTSTATUS_WIN_STATUS_TRANSACTION_ALREADY_COMMITTED,
+ MD_NTSTATUS_WIN_STATUS_TRANSACTION_INVALID_MARSHALL_BUFFER,
+ MD_NTSTATUS_WIN_STATUS_CURRENT_TRANSACTION_NOT_VALID,
+ MD_NTSTATUS_WIN_STATUS_LOG_GROWTH_FAILED,
+ MD_NTSTATUS_WIN_STATUS_OBJECT_NO_LONGER_EXISTS,
+ MD_NTSTATUS_WIN_STATUS_STREAM_MINIVERSION_NOT_FOUND,
+ MD_NTSTATUS_WIN_STATUS_STREAM_MINIVERSION_NOT_VALID,
+ MD_NTSTATUS_WIN_STATUS_MINIVERSION_INACCESSIBLE_FROM_SPECIFIED_TRANSACTION,
+ MD_NTSTATUS_WIN_STATUS_CANT_OPEN_MINIVERSION_WITH_MODIFY_INTENT,
+ MD_NTSTATUS_WIN_STATUS_CANT_CREATE_MORE_STREAM_MINIVERSIONS,
+ MD_NTSTATUS_WIN_STATUS_HANDLE_NO_LONGER_VALID,
+ MD_NTSTATUS_WIN_STATUS_LOG_CORRUPTION_DETECTED,
+ MD_NTSTATUS_WIN_STATUS_RM_DISCONNECTED,
+ MD_NTSTATUS_WIN_STATUS_ENLISTMENT_NOT_SUPERIOR,
+ MD_NTSTATUS_WIN_STATUS_FILE_IDENTITY_NOT_PERSISTENT,
+ MD_NTSTATUS_WIN_STATUS_CANT_BREAK_TRANSACTIONAL_DEPENDENCY,
+ MD_NTSTATUS_WIN_STATUS_CANT_CROSS_RM_BOUNDARY,
+ MD_NTSTATUS_WIN_STATUS_TXF_DIR_NOT_EMPTY,
+ MD_NTSTATUS_WIN_STATUS_INDOUBT_TRANSACTIONS_EXIST,
+ MD_NTSTATUS_WIN_STATUS_TM_VOLATILE,
+ MD_NTSTATUS_WIN_STATUS_ROLLBACK_TIMER_EXPIRED,
+ MD_NTSTATUS_WIN_STATUS_TXF_ATTRIBUTE_CORRUPT,
+ MD_NTSTATUS_WIN_STATUS_EFS_NOT_ALLOWED_IN_TRANSACTION,
+ MD_NTSTATUS_WIN_STATUS_TRANSACTIONAL_OPEN_NOT_ALLOWED,
+ MD_NTSTATUS_WIN_STATUS_TRANSACTED_MAPPING_UNSUPPORTED_REMOTE,
+ MD_NTSTATUS_WIN_STATUS_TRANSACTION_REQUIRED_PROMOTION,
+ MD_NTSTATUS_WIN_STATUS_CANNOT_EXECUTE_FILE_IN_TRANSACTION,
+ MD_NTSTATUS_WIN_STATUS_TRANSACTIONS_NOT_FROZEN,
+ MD_NTSTATUS_WIN_STATUS_TRANSACTION_FREEZE_IN_PROGRESS,
+ MD_NTSTATUS_WIN_STATUS_NOT_SNAPSHOT_VOLUME,
+ MD_NTSTATUS_WIN_STATUS_NO_SAVEPOINT_WITH_OPEN_FILES,
+ MD_NTSTATUS_WIN_STATUS_SPARSE_NOT_ALLOWED_IN_TRANSACTION,
+ MD_NTSTATUS_WIN_STATUS_TM_IDENTITY_MISMATCH,
+ MD_NTSTATUS_WIN_STATUS_FLOATED_SECTION,
+ MD_NTSTATUS_WIN_STATUS_CANNOT_ACCEPT_TRANSACTED_WORK,
+ MD_NTSTATUS_WIN_STATUS_CANNOT_ABORT_TRANSACTIONS,
+ MD_NTSTATUS_WIN_STATUS_TRANSACTION_NOT_FOUND,
+ MD_NTSTATUS_WIN_STATUS_RESOURCEMANAGER_NOT_FOUND,
+ MD_NTSTATUS_WIN_STATUS_ENLISTMENT_NOT_FOUND,
+ MD_NTSTATUS_WIN_STATUS_TRANSACTIONMANAGER_NOT_FOUND,
+ MD_NTSTATUS_WIN_STATUS_TRANSACTIONMANAGER_NOT_ONLINE,
+ MD_NTSTATUS_WIN_STATUS_TRANSACTIONMANAGER_RECOVERY_NAME_COLLISION,
+ MD_NTSTATUS_WIN_STATUS_TRANSACTION_NOT_ROOT,
+ MD_NTSTATUS_WIN_STATUS_TRANSACTION_OBJECT_EXPIRED,
+ MD_NTSTATUS_WIN_STATUS_COMPRESSION_NOT_ALLOWED_IN_TRANSACTION,
+ MD_NTSTATUS_WIN_STATUS_TRANSACTION_RESPONSE_NOT_ENLISTED,
+ MD_NTSTATUS_WIN_STATUS_TRANSACTION_RECORD_TOO_LONG,
+ MD_NTSTATUS_WIN_STATUS_NO_LINK_TRACKING_IN_TRANSACTION,
+ MD_NTSTATUS_WIN_STATUS_OPERATION_NOT_SUPPORTED_IN_TRANSACTION,
+ MD_NTSTATUS_WIN_STATUS_TRANSACTION_INTEGRITY_VIOLATED,
+ MD_NTSTATUS_WIN_STATUS_TRANSACTIONMANAGER_IDENTITY_MISMATCH,
+ MD_NTSTATUS_WIN_STATUS_RM_CANNOT_BE_FROZEN_FOR_SNAPSHOT,
+ MD_NTSTATUS_WIN_STATUS_TRANSACTION_MUST_WRITETHROUGH,
+ MD_NTSTATUS_WIN_STATUS_TRANSACTION_NO_SUPERIOR,
+ MD_NTSTATUS_WIN_STATUS_EXPIRED_HANDLE,
+ MD_NTSTATUS_WIN_STATUS_TRANSACTION_NOT_ENLISTED,
+ MD_NTSTATUS_WIN_STATUS_LOG_SECTOR_INVALID,
+ MD_NTSTATUS_WIN_STATUS_LOG_SECTOR_PARITY_INVALID,
+ MD_NTSTATUS_WIN_STATUS_LOG_SECTOR_REMAPPED,
+ MD_NTSTATUS_WIN_STATUS_LOG_BLOCK_INCOMPLETE,
+ MD_NTSTATUS_WIN_STATUS_LOG_INVALID_RANGE,
+ MD_NTSTATUS_WIN_STATUS_LOG_BLOCKS_EXHAUSTED,
+ MD_NTSTATUS_WIN_STATUS_LOG_READ_CONTEXT_INVALID,
+ MD_NTSTATUS_WIN_STATUS_LOG_RESTART_INVALID,
+ MD_NTSTATUS_WIN_STATUS_LOG_BLOCK_VERSION,
+ MD_NTSTATUS_WIN_STATUS_LOG_BLOCK_INVALID,
+ MD_NTSTATUS_WIN_STATUS_LOG_READ_MODE_INVALID,
+ MD_NTSTATUS_WIN_STATUS_LOG_METADATA_CORRUPT,
+ MD_NTSTATUS_WIN_STATUS_LOG_METADATA_INVALID,
+ MD_NTSTATUS_WIN_STATUS_LOG_METADATA_INCONSISTENT,
+ MD_NTSTATUS_WIN_STATUS_LOG_RESERVATION_INVALID,
+ MD_NTSTATUS_WIN_STATUS_LOG_CANT_DELETE,
+ MD_NTSTATUS_WIN_STATUS_LOG_CONTAINER_LIMIT_EXCEEDED,
+ MD_NTSTATUS_WIN_STATUS_LOG_START_OF_LOG,
+ MD_NTSTATUS_WIN_STATUS_LOG_POLICY_ALREADY_INSTALLED,
+ MD_NTSTATUS_WIN_STATUS_LOG_POLICY_NOT_INSTALLED,
+ MD_NTSTATUS_WIN_STATUS_LOG_POLICY_INVALID,
+ MD_NTSTATUS_WIN_STATUS_LOG_POLICY_CONFLICT,
+ MD_NTSTATUS_WIN_STATUS_LOG_PINNED_ARCHIVE_TAIL,
+ MD_NTSTATUS_WIN_STATUS_LOG_RECORD_NONEXISTENT,
+ MD_NTSTATUS_WIN_STATUS_LOG_RECORDS_RESERVED_INVALID,
+ MD_NTSTATUS_WIN_STATUS_LOG_SPACE_RESERVED_INVALID,
+ MD_NTSTATUS_WIN_STATUS_LOG_TAIL_INVALID,
+ MD_NTSTATUS_WIN_STATUS_LOG_FULL,
+ MD_NTSTATUS_WIN_STATUS_LOG_MULTIPLEXED,
+ MD_NTSTATUS_WIN_STATUS_LOG_DEDICATED,
+ MD_NTSTATUS_WIN_STATUS_LOG_ARCHIVE_NOT_IN_PROGRESS,
+ MD_NTSTATUS_WIN_STATUS_LOG_ARCHIVE_IN_PROGRESS,
+ MD_NTSTATUS_WIN_STATUS_LOG_EPHEMERAL,
+ MD_NTSTATUS_WIN_STATUS_LOG_NOT_ENOUGH_CONTAINERS,
+ MD_NTSTATUS_WIN_STATUS_LOG_CLIENT_ALREADY_REGISTERED,
+ MD_NTSTATUS_WIN_STATUS_LOG_CLIENT_NOT_REGISTERED,
+ MD_NTSTATUS_WIN_STATUS_LOG_FULL_HANDLER_IN_PROGRESS,
+ MD_NTSTATUS_WIN_STATUS_LOG_CONTAINER_READ_FAILED,
+ MD_NTSTATUS_WIN_STATUS_LOG_CONTAINER_WRITE_FAILED,
+ MD_NTSTATUS_WIN_STATUS_LOG_CONTAINER_OPEN_FAILED,
+ MD_NTSTATUS_WIN_STATUS_LOG_CONTAINER_STATE_INVALID,
+ MD_NTSTATUS_WIN_STATUS_LOG_STATE_INVALID,
+ MD_NTSTATUS_WIN_STATUS_LOG_PINNED,
+ MD_NTSTATUS_WIN_STATUS_LOG_METADATA_FLUSH_FAILED,
+ MD_NTSTATUS_WIN_STATUS_LOG_INCONSISTENT_SECURITY,
+ MD_NTSTATUS_WIN_STATUS_LOG_APPENDED_FLUSH_FAILED,
+ MD_NTSTATUS_WIN_STATUS_LOG_PINNED_RESERVATION,
+ MD_NTSTATUS_WIN_STATUS_VIDEO_HUNG_DISPLAY_DRIVER_THREAD,
+ MD_NTSTATUS_WIN_STATUS_FLT_NO_HANDLER_DEFINED,
+ MD_NTSTATUS_WIN_STATUS_FLT_CONTEXT_ALREADY_DEFINED,
+ MD_NTSTATUS_WIN_STATUS_FLT_INVALID_ASYNCHRONOUS_REQUEST,
+ MD_NTSTATUS_WIN_STATUS_FLT_DISALLOW_FAST_IO,
+ MD_NTSTATUS_WIN_STATUS_FLT_INVALID_NAME_REQUEST,
+ MD_NTSTATUS_WIN_STATUS_FLT_NOT_SAFE_TO_POST_OPERATION,
+ MD_NTSTATUS_WIN_STATUS_FLT_NOT_INITIALIZED,
+ MD_NTSTATUS_WIN_STATUS_FLT_FILTER_NOT_READY,
+ MD_NTSTATUS_WIN_STATUS_FLT_POST_OPERATION_CLEANUP,
+ MD_NTSTATUS_WIN_STATUS_FLT_INTERNAL_ERROR,
+ MD_NTSTATUS_WIN_STATUS_FLT_DELETING_OBJECT,
+ MD_NTSTATUS_WIN_STATUS_FLT_MUST_BE_NONPAGED_POOL,
+ MD_NTSTATUS_WIN_STATUS_FLT_DUPLICATE_ENTRY,
+ MD_NTSTATUS_WIN_STATUS_FLT_CBDQ_DISABLED,
+ MD_NTSTATUS_WIN_STATUS_FLT_DO_NOT_ATTACH,
+ MD_NTSTATUS_WIN_STATUS_FLT_DO_NOT_DETACH,
+ MD_NTSTATUS_WIN_STATUS_FLT_INSTANCE_ALTITUDE_COLLISION,
+ MD_NTSTATUS_WIN_STATUS_FLT_INSTANCE_NAME_COLLISION,
+ MD_NTSTATUS_WIN_STATUS_FLT_FILTER_NOT_FOUND,
+ MD_NTSTATUS_WIN_STATUS_FLT_VOLUME_NOT_FOUND,
+ MD_NTSTATUS_WIN_STATUS_FLT_INSTANCE_NOT_FOUND,
+ MD_NTSTATUS_WIN_STATUS_FLT_CONTEXT_ALLOCATION_NOT_FOUND,
+ MD_NTSTATUS_WIN_STATUS_FLT_INVALID_CONTEXT_REGISTRATION,
+ MD_NTSTATUS_WIN_STATUS_FLT_NAME_CACHE_MISS,
+ MD_NTSTATUS_WIN_STATUS_FLT_NO_DEVICE_OBJECT,
+ MD_NTSTATUS_WIN_STATUS_FLT_VOLUME_ALREADY_MOUNTED,
+ MD_NTSTATUS_WIN_STATUS_FLT_ALREADY_ENLISTED,
+ MD_NTSTATUS_WIN_STATUS_FLT_CONTEXT_ALREADY_LINKED,
+ MD_NTSTATUS_WIN_STATUS_FLT_NO_WAITER_FOR_REPLY,
+ MD_NTSTATUS_WIN_STATUS_FLT_REGISTRATION_BUSY,
+ MD_NTSTATUS_WIN_STATUS_MONITOR_NO_DESCRIPTOR,
+ MD_NTSTATUS_WIN_STATUS_MONITOR_UNKNOWN_DESCRIPTOR_FORMAT,
+ MD_NTSTATUS_WIN_STATUS_MONITOR_INVALID_DESCRIPTOR_CHECKSUM,
+ MD_NTSTATUS_WIN_STATUS_MONITOR_INVALID_STANDARD_TIMING_BLOCK,
+ MD_NTSTATUS_WIN_STATUS_MONITOR_WMI_DATABLOCK_REGISTRATION_FAILED,
+ MD_NTSTATUS_WIN_STATUS_MONITOR_INVALID_SERIAL_NUMBER_MONDSC_BLOCK,
+ MD_NTSTATUS_WIN_STATUS_MONITOR_INVALID_USER_FRIENDLY_MONDSC_BLOCK,
+ MD_NTSTATUS_WIN_STATUS_MONITOR_NO_MORE_DESCRIPTOR_DATA,
+ MD_NTSTATUS_WIN_STATUS_MONITOR_INVALID_DETAILED_TIMING_BLOCK,
+ MD_NTSTATUS_WIN_STATUS_MONITOR_INVALID_MANUFACTURE_DATE,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_NOT_EXCLUSIVE_MODE_OWNER,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_DISPLAY_ADAPTER,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_ADAPTER_WAS_RESET,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_DRIVER_MODEL,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_PRESENT_MODE_CHANGED,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_PRESENT_OCCLUDED,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_PRESENT_DENIED,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_CANNOTCOLORCONVERT,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_DRIVER_MISMATCH,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_PRESENT_REDIRECTION_DISABLED,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_PRESENT_UNOCCLUDED,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_WINDOWDC_NOT_AVAILABLE,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_WINDOWLESS_PRESENT_DISABLED,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_PRESENT_INVALID_WINDOW,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_PRESENT_BUFFER_NOT_BOUND,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_VAIL_STATE_CHANGED,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INDIRECT_DISPLAY_ABANDON_SWAPCHAIN,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INDIRECT_DISPLAY_DEVICE_STOPPED,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_NO_VIDEO_MEMORY,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_CANT_LOCK_MEMORY,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_ALLOCATION_BUSY,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_TOO_MANY_REFERENCES,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_TRY_AGAIN_LATER,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_TRY_AGAIN_NOW,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_ALLOCATION_INVALID,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_UNSWIZZLING_APERTURE_UNAVAILABLE,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_UNSWIZZLING_APERTURE_UNSUPPORTED,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_CANT_EVICT_PINNED_ALLOCATION,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_ALLOCATION_USAGE,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_CANT_RENDER_LOCKED_ALLOCATION,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_ALLOCATION_CLOSED,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_ALLOCATION_INSTANCE,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_ALLOCATION_HANDLE,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_WRONG_ALLOCATION_DEVICE,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_ALLOCATION_CONTENT_LOST,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_GPU_EXCEPTION_ON_DEVICE,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_VIDPN_TOPOLOGY,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_VIDPN_TOPOLOGY_NOT_SUPPORTED,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_VIDPN_TOPOLOGY_CURRENTLY_NOT_SUPPORTED,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_VIDPN,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_SOURCE,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_TARGET,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_VIDPN_MODALITY_NOT_SUPPORTED,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_VIDPN_SOURCEMODESET,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_VIDPN_TARGETMODESET,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_FREQUENCY,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_ACTIVE_REGION,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_TOTAL_REGION,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_SOURCE_MODE,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_TARGET_MODE,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_PINNED_MODE_MUST_REMAIN_IN_SET,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_PATH_ALREADY_IN_TOPOLOGY,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_MODE_ALREADY_IN_MODESET,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_VIDEOPRESENTSOURCESET,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_VIDEOPRESENTTARGETSET,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_SOURCE_ALREADY_IN_SET,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_TARGET_ALREADY_IN_SET,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_VIDPN_PRESENT_PATH,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_NO_RECOMMENDED_VIDPN_TOPOLOGY,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_MONITOR_FREQUENCYRANGESET,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_MONITOR_FREQUENCYRANGE,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_FREQUENCYRANGE_NOT_IN_SET,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_FREQUENCYRANGE_ALREADY_IN_SET,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_STALE_MODESET,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_MONITOR_SOURCEMODESET,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_MONITOR_SOURCE_MODE,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_NO_RECOMMENDED_FUNCTIONAL_VIDPN,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_MODE_ID_MUST_BE_UNIQUE,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_EMPTY_ADAPTER_MONITOR_MODE_SUPPORT_INTERSECTION,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_VIDEO_PRESENT_TARGETS_LESS_THAN_SOURCES,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_PATH_NOT_IN_TOPOLOGY,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_ADAPTER_MUST_HAVE_AT_LEAST_ONE_SOURCE,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_ADAPTER_MUST_HAVE_AT_LEAST_ONE_TARGET,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_MONITORDESCRIPTORSET,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_MONITORDESCRIPTOR,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_MONITORDESCRIPTOR_NOT_IN_SET,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_MONITORDESCRIPTOR_ALREADY_IN_SET,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_MONITORDESCRIPTOR_ID_MUST_BE_UNIQUE,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_VIDPN_TARGET_SUBSET_TYPE,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_RESOURCES_NOT_RELATED,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_SOURCE_ID_MUST_BE_UNIQUE,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_TARGET_ID_MUST_BE_UNIQUE,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_NO_AVAILABLE_VIDPN_TARGET,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_MONITOR_COULD_NOT_BE_ASSOCIATED_WITH_ADAPTER,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_NO_VIDPNMGR,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_NO_ACTIVE_VIDPN,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_STALE_VIDPN_TOPOLOGY,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_MONITOR_NOT_CONNECTED,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_SOURCE_NOT_IN_TOPOLOGY,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_PRIMARYSURFACE_SIZE,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_VISIBLEREGION_SIZE,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_STRIDE,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_PIXELFORMAT,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_COLORBASIS,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_PIXELVALUEACCESSMODE,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_TARGET_NOT_IN_TOPOLOGY,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_NO_DISPLAY_MODE_MANAGEMENT_SUPPORT,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_CANT_ACCESS_ACTIVE_VIDPN,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_PATH_IMPORTANCE_ORDINAL,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_PATH_CONTENT_GEOMETRY_TRANSFORMATION,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_PATH_CONTENT_GEOMETRY_TRANSFORMATION_NOT_SUPPORTED,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_GAMMA_RAMP,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_GAMMA_RAMP_NOT_SUPPORTED,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_MULTISAMPLING_NOT_SUPPORTED,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_MODE_NOT_IN_MODESET,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_VIDPN_TOPOLOGY_RECOMMENDATION_REASON,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_PATH_CONTENT_TYPE,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_COPYPROTECTION_TYPE,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_UNASSIGNED_MODESET_ALREADY_EXISTS,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_SCANLINE_ORDERING,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_TOPOLOGY_CHANGES_NOT_ALLOWED,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_NO_AVAILABLE_IMPORTANCE_ORDINALS,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INCOMPATIBLE_PRIVATE_FORMAT,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_MODE_PRUNING_ALGORITHM,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_MONITOR_CAPABILITY_ORIGIN,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_MONITOR_FREQUENCYRANGE_CONSTRAINT,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_MAX_NUM_PATHS_REACHED,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_CANCEL_VIDPN_TOPOLOGY_AUGMENTATION,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_CLIENT_TYPE,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_CLIENTVIDPN_NOT_SET,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_SPECIFIED_CHILD_ALREADY_CONNECTED,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_CHILD_DESCRIPTOR_NOT_SUPPORTED,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_NOT_A_LINKED_ADAPTER,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_LEADLINK_NOT_ENUMERATED,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_CHAINLINKS_NOT_ENUMERATED,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_ADAPTER_CHAIN_NOT_READY,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_CHAINLINKS_NOT_STARTED,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_CHAINLINKS_NOT_POWERED_ON,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INCONSISTENT_DEVICE_LINK_STATE,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_NOT_POST_DEVICE_DRIVER,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_ADAPTER_ACCESS_NOT_EXCLUDED,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_NOT_SUPPORTED,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_COPP_NOT_SUPPORTED,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_UAB_NOT_SUPPORTED,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_INVALID_ENCRYPTED_PARAMETERS,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_NO_PROTECTED_OUTPUTS_EXIST,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_INTERNAL_ERROR,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_INVALID_HANDLE,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_PVP_INVALID_CERTIFICATE_LENGTH,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_SPANNING_MODE_ENABLED,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_THEATER_MODE_ENABLED,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_PVP_HFS_FAILED,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_INVALID_SRM,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_OUTPUT_DOES_NOT_SUPPORT_HDCP,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_OUTPUT_DOES_NOT_SUPPORT_ACP,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_OUTPUT_DOES_NOT_SUPPORT_CGMSA,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_HDCP_SRM_NEVER_SET,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_RESOLUTION_TOO_HIGH,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_ALL_HDCP_HARDWARE_ALREADY_IN_USE,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_PROTECTED_OUTPUT_NO_LONGER_EXISTS,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_PROTECTED_OUTPUT_DOES_NOT_HAVE_COPP_SEMANTICS,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_INVALID_INFORMATION_REQUEST,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_DRIVER_INTERNAL_ERROR,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_PROTECTED_OUTPUT_DOES_NOT_HAVE_OPM_SEMANTICS,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_SIGNALING_NOT_SUPPORTED,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_INVALID_CONFIGURATION_REQUEST,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_I2C_NOT_SUPPORTED,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_I2C_DEVICE_DOES_NOT_EXIST,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_I2C_ERROR_TRANSMITTING_DATA,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_I2C_ERROR_RECEIVING_DATA,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_DDCCI_VCP_NOT_SUPPORTED,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_DDCCI_INVALID_DATA,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_DDCCI_MONITOR_RETURNED_INVALID_TIMING_STATUS_BYTE,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_DDCCI_INVALID_CAPABILITIES_STRING,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_MCA_INTERNAL_ERROR,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_DDCCI_INVALID_MESSAGE_COMMAND,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_DDCCI_INVALID_MESSAGE_LENGTH,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_DDCCI_INVALID_MESSAGE_CHECKSUM,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_PHYSICAL_MONITOR_HANDLE,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_MONITOR_NO_LONGER_EXISTS,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_ONLY_CONSOLE_SESSION_SUPPORTED,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_NO_DISPLAY_DEVICE_CORRESPONDS_TO_NAME,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_DISPLAY_DEVICE_NOT_ATTACHED_TO_DESKTOP,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_MIRRORING_DEVICES_NOT_SUPPORTED,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_POINTER,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_NO_MONITORS_CORRESPOND_TO_DISPLAY_DEVICE,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_PARAMETER_ARRAY_TOO_SMALL,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_INTERNAL_ERROR,
+ MD_NTSTATUS_WIN_STATUS_GRAPHICS_SESSION_TYPE_CHANGE_IN_PROGRESS,
+ MD_NTSTATUS_WIN_STATUS_FVE_LOCKED_VOLUME,
+ MD_NTSTATUS_WIN_STATUS_FVE_NOT_ENCRYPTED,
+ MD_NTSTATUS_WIN_STATUS_FVE_BAD_INFORMATION,
+ MD_NTSTATUS_WIN_STATUS_FVE_TOO_SMALL,
+ MD_NTSTATUS_WIN_STATUS_FVE_FAILED_WRONG_FS,
+ MD_NTSTATUS_WIN_STATUS_FVE_BAD_PARTITION_SIZE,
+ MD_NTSTATUS_WIN_STATUS_FVE_FS_NOT_EXTENDED,
+ MD_NTSTATUS_WIN_STATUS_FVE_FS_MOUNTED,
+ MD_NTSTATUS_WIN_STATUS_FVE_NO_LICENSE,
+ MD_NTSTATUS_WIN_STATUS_FVE_ACTION_NOT_ALLOWED,
+ MD_NTSTATUS_WIN_STATUS_FVE_BAD_DATA,
+ MD_NTSTATUS_WIN_STATUS_FVE_VOLUME_NOT_BOUND,
+ MD_NTSTATUS_WIN_STATUS_FVE_NOT_DATA_VOLUME,
+ MD_NTSTATUS_WIN_STATUS_FVE_CONV_READ_ERROR,
+ MD_NTSTATUS_WIN_STATUS_FVE_CONV_WRITE_ERROR,
+ MD_NTSTATUS_WIN_STATUS_FVE_OVERLAPPED_UPDATE,
+ MD_NTSTATUS_WIN_STATUS_FVE_FAILED_SECTOR_SIZE,
+ MD_NTSTATUS_WIN_STATUS_FVE_FAILED_AUTHENTICATION,
+ MD_NTSTATUS_WIN_STATUS_FVE_NOT_OS_VOLUME,
+ MD_NTSTATUS_WIN_STATUS_FVE_KEYFILE_NOT_FOUND,
+ MD_NTSTATUS_WIN_STATUS_FVE_KEYFILE_INVALID,
+ MD_NTSTATUS_WIN_STATUS_FVE_KEYFILE_NO_VMK,
+ MD_NTSTATUS_WIN_STATUS_FVE_TPM_DISABLED,
+ MD_NTSTATUS_WIN_STATUS_FVE_TPM_SRK_AUTH_NOT_ZERO,
+ MD_NTSTATUS_WIN_STATUS_FVE_TPM_INVALID_PCR,
+ MD_NTSTATUS_WIN_STATUS_FVE_TPM_NO_VMK,
+ MD_NTSTATUS_WIN_STATUS_FVE_PIN_INVALID,
+ MD_NTSTATUS_WIN_STATUS_FVE_AUTH_INVALID_APPLICATION,
+ MD_NTSTATUS_WIN_STATUS_FVE_AUTH_INVALID_CONFIG,
+ MD_NTSTATUS_WIN_STATUS_FVE_DEBUGGER_ENABLED,
+ MD_NTSTATUS_WIN_STATUS_FVE_DRY_RUN_FAILED,
+ MD_NTSTATUS_WIN_STATUS_FVE_BAD_METADATA_POINTER,
+ MD_NTSTATUS_WIN_STATUS_FVE_OLD_METADATA_COPY,
+ MD_NTSTATUS_WIN_STATUS_FVE_REBOOT_REQUIRED,
+ MD_NTSTATUS_WIN_STATUS_FVE_RAW_ACCESS,
+ MD_NTSTATUS_WIN_STATUS_FVE_RAW_BLOCKED,
+ MD_NTSTATUS_WIN_STATUS_FVE_NO_AUTOUNLOCK_MASTER_KEY,
+ MD_NTSTATUS_WIN_STATUS_FVE_MOR_FAILED,
+ MD_NTSTATUS_WIN_STATUS_FVE_NO_FEATURE_LICENSE,
+ MD_NTSTATUS_WIN_STATUS_FVE_POLICY_USER_DISABLE_RDV_NOT_ALLOWED,
+ MD_NTSTATUS_WIN_STATUS_FVE_CONV_RECOVERY_FAILED,
+ MD_NTSTATUS_WIN_STATUS_FVE_VIRTUALIZED_SPACE_TOO_BIG,
+ MD_NTSTATUS_WIN_STATUS_FVE_INVALID_DATUM_TYPE,
+ MD_NTSTATUS_WIN_STATUS_FVE_VOLUME_TOO_SMALL,
+ MD_NTSTATUS_WIN_STATUS_FVE_ENH_PIN_INVALID,
+ MD_NTSTATUS_WIN_STATUS_FVE_FULL_ENCRYPTION_NOT_ALLOWED_ON_TP_STORAGE,
+ MD_NTSTATUS_WIN_STATUS_FVE_WIPE_NOT_ALLOWED_ON_TP_STORAGE,
+ MD_NTSTATUS_WIN_STATUS_FVE_NOT_ALLOWED_ON_CSV_STACK,
+ MD_NTSTATUS_WIN_STATUS_FVE_NOT_ALLOWED_ON_CLUSTER,
+ MD_NTSTATUS_WIN_STATUS_FVE_NOT_ALLOWED_TO_UPGRADE_WHILE_CONVERTING,
+ MD_NTSTATUS_WIN_STATUS_FVE_WIPE_CANCEL_NOT_APPLICABLE,
+ MD_NTSTATUS_WIN_STATUS_FVE_EDRIVE_DRY_RUN_FAILED,
+ MD_NTSTATUS_WIN_STATUS_FVE_SECUREBOOT_DISABLED,
+ MD_NTSTATUS_WIN_STATUS_FVE_SECUREBOOT_CONFIG_CHANGE,
+ MD_NTSTATUS_WIN_STATUS_FVE_DEVICE_LOCKEDOUT,
+ MD_NTSTATUS_WIN_STATUS_FVE_VOLUME_EXTEND_PREVENTS_EOW_DECRYPT,
+ MD_NTSTATUS_WIN_STATUS_FVE_NOT_DE_VOLUME,
+ MD_NTSTATUS_WIN_STATUS_FVE_PROTECTION_DISABLED,
+ MD_NTSTATUS_WIN_STATUS_FVE_PROTECTION_CANNOT_BE_DISABLED,
+ MD_NTSTATUS_WIN_STATUS_FVE_OSV_KSR_NOT_ALLOWED,
+ MD_NTSTATUS_WIN_STATUS_FWP_CALLOUT_NOT_FOUND,
+ MD_NTSTATUS_WIN_STATUS_FWP_CONDITION_NOT_FOUND,
+ MD_NTSTATUS_WIN_STATUS_FWP_FILTER_NOT_FOUND,
+ MD_NTSTATUS_WIN_STATUS_FWP_LAYER_NOT_FOUND,
+ MD_NTSTATUS_WIN_STATUS_FWP_PROVIDER_NOT_FOUND,
+ MD_NTSTATUS_WIN_STATUS_FWP_PROVIDER_CONTEXT_NOT_FOUND,
+ MD_NTSTATUS_WIN_STATUS_FWP_SUBLAYER_NOT_FOUND,
+ MD_NTSTATUS_WIN_STATUS_FWP_NOT_FOUND,
+ MD_NTSTATUS_WIN_STATUS_FWP_ALREADY_EXISTS,
+ MD_NTSTATUS_WIN_STATUS_FWP_IN_USE,
+ MD_NTSTATUS_WIN_STATUS_FWP_DYNAMIC_SESSION_IN_PROGRESS,
+ MD_NTSTATUS_WIN_STATUS_FWP_WRONG_SESSION,
+ MD_NTSTATUS_WIN_STATUS_FWP_NO_TXN_IN_PROGRESS,
+ MD_NTSTATUS_WIN_STATUS_FWP_TXN_IN_PROGRESS,
+ MD_NTSTATUS_WIN_STATUS_FWP_TXN_ABORTED,
+ MD_NTSTATUS_WIN_STATUS_FWP_SESSION_ABORTED,
+ MD_NTSTATUS_WIN_STATUS_FWP_INCOMPATIBLE_TXN,
+ MD_NTSTATUS_WIN_STATUS_FWP_TIMEOUT,
+ MD_NTSTATUS_WIN_STATUS_FWP_NET_EVENTS_DISABLED,
+ MD_NTSTATUS_WIN_STATUS_FWP_INCOMPATIBLE_LAYER,
+ MD_NTSTATUS_WIN_STATUS_FWP_KM_CLIENTS_ONLY,
+ MD_NTSTATUS_WIN_STATUS_FWP_LIFETIME_MISMATCH,
+ MD_NTSTATUS_WIN_STATUS_FWP_BUILTIN_OBJECT,
+ MD_NTSTATUS_WIN_STATUS_FWP_TOO_MANY_CALLOUTS,
+ MD_NTSTATUS_WIN_STATUS_FWP_NOTIFICATION_DROPPED,
+ MD_NTSTATUS_WIN_STATUS_FWP_TRAFFIC_MISMATCH,
+ MD_NTSTATUS_WIN_STATUS_FWP_INCOMPATIBLE_SA_STATE,
+ MD_NTSTATUS_WIN_STATUS_FWP_NULL_POINTER,
+ MD_NTSTATUS_WIN_STATUS_FWP_INVALID_ENUMERATOR,
+ MD_NTSTATUS_WIN_STATUS_FWP_INVALID_FLAGS,
+ MD_NTSTATUS_WIN_STATUS_FWP_INVALID_NET_MASK,
+ MD_NTSTATUS_WIN_STATUS_FWP_INVALID_RANGE,
+ MD_NTSTATUS_WIN_STATUS_FWP_INVALID_INTERVAL,
+ MD_NTSTATUS_WIN_STATUS_FWP_ZERO_LENGTH_ARRAY,
+ MD_NTSTATUS_WIN_STATUS_FWP_NULL_DISPLAY_NAME,
+ MD_NTSTATUS_WIN_STATUS_FWP_INVALID_ACTION_TYPE,
+ MD_NTSTATUS_WIN_STATUS_FWP_INVALID_WEIGHT,
+ MD_NTSTATUS_WIN_STATUS_FWP_MATCH_TYPE_MISMATCH,
+ MD_NTSTATUS_WIN_STATUS_FWP_TYPE_MISMATCH,
+ MD_NTSTATUS_WIN_STATUS_FWP_OUT_OF_BOUNDS,
+ MD_NTSTATUS_WIN_STATUS_FWP_RESERVED,
+ MD_NTSTATUS_WIN_STATUS_FWP_DUPLICATE_CONDITION,
+ MD_NTSTATUS_WIN_STATUS_FWP_DUPLICATE_KEYMOD,
+ MD_NTSTATUS_WIN_STATUS_FWP_ACTION_INCOMPATIBLE_WITH_LAYER,
+ MD_NTSTATUS_WIN_STATUS_FWP_ACTION_INCOMPATIBLE_WITH_SUBLAYER,
+ MD_NTSTATUS_WIN_STATUS_FWP_CONTEXT_INCOMPATIBLE_WITH_LAYER,
+ MD_NTSTATUS_WIN_STATUS_FWP_CONTEXT_INCOMPATIBLE_WITH_CALLOUT,
+ MD_NTSTATUS_WIN_STATUS_FWP_INCOMPATIBLE_AUTH_METHOD,
+ MD_NTSTATUS_WIN_STATUS_FWP_INCOMPATIBLE_DH_GROUP,
+ MD_NTSTATUS_WIN_STATUS_FWP_EM_NOT_SUPPORTED,
+ MD_NTSTATUS_WIN_STATUS_FWP_NEVER_MATCH,
+ MD_NTSTATUS_WIN_STATUS_FWP_PROVIDER_CONTEXT_MISMATCH,
+ MD_NTSTATUS_WIN_STATUS_FWP_INVALID_PARAMETER,
+ MD_NTSTATUS_WIN_STATUS_FWP_TOO_MANY_SUBLAYERS,
+ MD_NTSTATUS_WIN_STATUS_FWP_CALLOUT_NOTIFICATION_FAILED,
+ MD_NTSTATUS_WIN_STATUS_FWP_INVALID_AUTH_TRANSFORM,
+ MD_NTSTATUS_WIN_STATUS_FWP_INVALID_CIPHER_TRANSFORM,
+ MD_NTSTATUS_WIN_STATUS_FWP_INCOMPATIBLE_CIPHER_TRANSFORM,
+ MD_NTSTATUS_WIN_STATUS_FWP_INVALID_TRANSFORM_COMBINATION,
+ MD_NTSTATUS_WIN_STATUS_FWP_DUPLICATE_AUTH_METHOD,
+ MD_NTSTATUS_WIN_STATUS_FWP_INVALID_TUNNEL_ENDPOINT,
+ MD_NTSTATUS_WIN_STATUS_FWP_L2_DRIVER_NOT_READY,
+ MD_NTSTATUS_WIN_STATUS_FWP_KEY_DICTATOR_ALREADY_REGISTERED,
+ MD_NTSTATUS_WIN_STATUS_FWP_KEY_DICTATION_INVALID_KEYING_MATERIAL,
+ MD_NTSTATUS_WIN_STATUS_FWP_CONNECTIONS_DISABLED,
+ MD_NTSTATUS_WIN_STATUS_FWP_INVALID_DNS_NAME,
+ MD_NTSTATUS_WIN_STATUS_FWP_STILL_ON,
+ MD_NTSTATUS_WIN_STATUS_FWP_IKEEXT_NOT_RUNNING,
+ MD_NTSTATUS_WIN_STATUS_FWP_TCPIP_NOT_READY,
+ MD_NTSTATUS_WIN_STATUS_FWP_INJECT_HANDLE_CLOSING,
+ MD_NTSTATUS_WIN_STATUS_FWP_INJECT_HANDLE_STALE,
+ MD_NTSTATUS_WIN_STATUS_FWP_CANNOT_PEND,
+ MD_NTSTATUS_WIN_STATUS_FWP_DROP_NOICMP,
+ MD_NTSTATUS_WIN_STATUS_NDIS_CLOSING,
+ MD_NTSTATUS_WIN_STATUS_NDIS_BAD_VERSION,
+ MD_NTSTATUS_WIN_STATUS_NDIS_BAD_CHARACTERISTICS,
+ MD_NTSTATUS_WIN_STATUS_NDIS_ADAPTER_NOT_FOUND,
+ MD_NTSTATUS_WIN_STATUS_NDIS_OPEN_FAILED,
+ MD_NTSTATUS_WIN_STATUS_NDIS_DEVICE_FAILED,
+ MD_NTSTATUS_WIN_STATUS_NDIS_MULTICAST_FULL,
+ MD_NTSTATUS_WIN_STATUS_NDIS_MULTICAST_EXISTS,
+ MD_NTSTATUS_WIN_STATUS_NDIS_MULTICAST_NOT_FOUND,
+ MD_NTSTATUS_WIN_STATUS_NDIS_REQUEST_ABORTED,
+ MD_NTSTATUS_WIN_STATUS_NDIS_RESET_IN_PROGRESS,
+ MD_NTSTATUS_WIN_STATUS_NDIS_INVALID_PACKET,
+ MD_NTSTATUS_WIN_STATUS_NDIS_INVALID_DEVICE_REQUEST,
+ MD_NTSTATUS_WIN_STATUS_NDIS_ADAPTER_NOT_READY,
+ MD_NTSTATUS_WIN_STATUS_NDIS_INVALID_LENGTH,
+ MD_NTSTATUS_WIN_STATUS_NDIS_INVALID_DATA,
+ MD_NTSTATUS_WIN_STATUS_NDIS_BUFFER_TOO_SHORT,
+ MD_NTSTATUS_WIN_STATUS_NDIS_INVALID_OID,
+ MD_NTSTATUS_WIN_STATUS_NDIS_ADAPTER_REMOVED,
+ MD_NTSTATUS_WIN_STATUS_NDIS_UNSUPPORTED_MEDIA,
+ MD_NTSTATUS_WIN_STATUS_NDIS_GROUP_ADDRESS_IN_USE,
+ MD_NTSTATUS_WIN_STATUS_NDIS_FILE_NOT_FOUND,
+ MD_NTSTATUS_WIN_STATUS_NDIS_ERROR_READING_FILE,
+ MD_NTSTATUS_WIN_STATUS_NDIS_ALREADY_MAPPED,
+ MD_NTSTATUS_WIN_STATUS_NDIS_RESOURCE_CONFLICT,
+ MD_NTSTATUS_WIN_STATUS_NDIS_MEDIA_DISCONNECTED,
+ MD_NTSTATUS_WIN_STATUS_NDIS_INVALID_ADDRESS,
+ MD_NTSTATUS_WIN_STATUS_NDIS_PAUSED,
+ MD_NTSTATUS_WIN_STATUS_NDIS_INTERFACE_NOT_FOUND,
+ MD_NTSTATUS_WIN_STATUS_NDIS_UNSUPPORTED_REVISION,
+ MD_NTSTATUS_WIN_STATUS_NDIS_INVALID_PORT,
+ MD_NTSTATUS_WIN_STATUS_NDIS_INVALID_PORT_STATE,
+ MD_NTSTATUS_WIN_STATUS_NDIS_LOW_POWER_STATE,
+ MD_NTSTATUS_WIN_STATUS_NDIS_REINIT_REQUIRED,
+ MD_NTSTATUS_WIN_STATUS_NDIS_NO_QUEUES,
+ MD_NTSTATUS_WIN_STATUS_NDIS_NOT_SUPPORTED,
+ MD_NTSTATUS_WIN_STATUS_NDIS_OFFLOAD_POLICY,
+ MD_NTSTATUS_WIN_STATUS_NDIS_OFFLOAD_CONNECTION_REJECTED,
+ MD_NTSTATUS_WIN_STATUS_NDIS_OFFLOAD_PATH_REJECTED,
+ MD_NTSTATUS_WIN_STATUS_NDIS_DOT11_AUTO_CONFIG_ENABLED,
+ MD_NTSTATUS_WIN_STATUS_NDIS_DOT11_MEDIA_IN_USE,
+ MD_NTSTATUS_WIN_STATUS_NDIS_DOT11_POWER_STATE_INVALID,
+ MD_NTSTATUS_WIN_STATUS_NDIS_PM_WOL_PATTERN_LIST_FULL,
+ MD_NTSTATUS_WIN_STATUS_NDIS_PM_PROTOCOL_OFFLOAD_LIST_FULL,
+ MD_NTSTATUS_WIN_STATUS_NDIS_DOT11_AP_CHANNEL_CURRENTLY_NOT_AVAILABLE,
+ MD_NTSTATUS_WIN_STATUS_NDIS_DOT11_AP_BAND_CURRENTLY_NOT_AVAILABLE,
+ MD_NTSTATUS_WIN_STATUS_NDIS_DOT11_AP_CHANNEL_NOT_ALLOWED,
+ MD_NTSTATUS_WIN_STATUS_NDIS_DOT11_AP_BAND_NOT_ALLOWED,
+ MD_NTSTATUS_WIN_STATUS_QUIC_HANDSHAKE_FAILURE,
+ MD_NTSTATUS_WIN_STATUS_QUIC_VER_NEG_FAILURE,
+ MD_NTSTATUS_WIN_STATUS_TPM_ERROR_MASK,
+ MD_NTSTATUS_WIN_STATUS_TPM_AUTHFAIL,
+ MD_NTSTATUS_WIN_STATUS_TPM_BADINDEX,
+ MD_NTSTATUS_WIN_STATUS_TPM_BAD_PARAMETER,
+ MD_NTSTATUS_WIN_STATUS_TPM_AUDITFAILURE,
+ MD_NTSTATUS_WIN_STATUS_TPM_CLEAR_DISABLED,
+ MD_NTSTATUS_WIN_STATUS_TPM_DEACTIVATED,
+ MD_NTSTATUS_WIN_STATUS_TPM_DISABLED,
+ MD_NTSTATUS_WIN_STATUS_TPM_DISABLED_CMD,
+ MD_NTSTATUS_WIN_STATUS_TPM_FAIL,
+ MD_NTSTATUS_WIN_STATUS_TPM_BAD_ORDINAL,
+ MD_NTSTATUS_WIN_STATUS_TPM_INSTALL_DISABLED,
+ MD_NTSTATUS_WIN_STATUS_TPM_INVALID_KEYHANDLE,
+ MD_NTSTATUS_WIN_STATUS_TPM_KEYNOTFOUND,
+ MD_NTSTATUS_WIN_STATUS_TPM_INAPPROPRIATE_ENC,
+ MD_NTSTATUS_WIN_STATUS_TPM_MIGRATEFAIL,
+ MD_NTSTATUS_WIN_STATUS_TPM_INVALID_PCR_INFO,
+ MD_NTSTATUS_WIN_STATUS_TPM_NOSPACE,
+ MD_NTSTATUS_WIN_STATUS_TPM_NOSRK,
+ MD_NTSTATUS_WIN_STATUS_TPM_NOTSEALED_BLOB,
+ MD_NTSTATUS_WIN_STATUS_TPM_OWNER_SET,
+ MD_NTSTATUS_WIN_STATUS_TPM_RESOURCES,
+ MD_NTSTATUS_WIN_STATUS_TPM_SHORTRANDOM,
+ MD_NTSTATUS_WIN_STATUS_TPM_SIZE,
+ MD_NTSTATUS_WIN_STATUS_TPM_WRONGPCRVAL,
+ MD_NTSTATUS_WIN_STATUS_TPM_BAD_PARAM_SIZE,
+ MD_NTSTATUS_WIN_STATUS_TPM_SHA_THREAD,
+ MD_NTSTATUS_WIN_STATUS_TPM_SHA_ERROR,
+ MD_NTSTATUS_WIN_STATUS_TPM_FAILEDSELFTEST,
+ MD_NTSTATUS_WIN_STATUS_TPM_AUTH2FAIL,
+ MD_NTSTATUS_WIN_STATUS_TPM_BADTAG,
+ MD_NTSTATUS_WIN_STATUS_TPM_IOERROR,
+ MD_NTSTATUS_WIN_STATUS_TPM_ENCRYPT_ERROR,
+ MD_NTSTATUS_WIN_STATUS_TPM_DECRYPT_ERROR,
+ MD_NTSTATUS_WIN_STATUS_TPM_INVALID_AUTHHANDLE,
+ MD_NTSTATUS_WIN_STATUS_TPM_NO_ENDORSEMENT,
+ MD_NTSTATUS_WIN_STATUS_TPM_INVALID_KEYUSAGE,
+ MD_NTSTATUS_WIN_STATUS_TPM_WRONG_ENTITYTYPE,
+ MD_NTSTATUS_WIN_STATUS_TPM_INVALID_POSTINIT,
+ MD_NTSTATUS_WIN_STATUS_TPM_INAPPROPRIATE_SIG,
+ MD_NTSTATUS_WIN_STATUS_TPM_BAD_KEY_PROPERTY,
+ MD_NTSTATUS_WIN_STATUS_TPM_BAD_MIGRATION,
+ MD_NTSTATUS_WIN_STATUS_TPM_BAD_SCHEME,
+ MD_NTSTATUS_WIN_STATUS_TPM_BAD_DATASIZE,
+ MD_NTSTATUS_WIN_STATUS_TPM_BAD_MODE,
+ MD_NTSTATUS_WIN_STATUS_TPM_BAD_PRESENCE,
+ MD_NTSTATUS_WIN_STATUS_TPM_BAD_VERSION,
+ MD_NTSTATUS_WIN_STATUS_TPM_NO_WRAP_TRANSPORT,
+ MD_NTSTATUS_WIN_STATUS_TPM_AUDITFAIL_UNSUCCESSFUL,
+ MD_NTSTATUS_WIN_STATUS_TPM_AUDITFAIL_SUCCESSFUL,
+ MD_NTSTATUS_WIN_STATUS_TPM_NOTRESETABLE,
+ MD_NTSTATUS_WIN_STATUS_TPM_NOTLOCAL,
+ MD_NTSTATUS_WIN_STATUS_TPM_BAD_TYPE,
+ MD_NTSTATUS_WIN_STATUS_TPM_INVALID_RESOURCE,
+ MD_NTSTATUS_WIN_STATUS_TPM_NOTFIPS,
+ MD_NTSTATUS_WIN_STATUS_TPM_INVALID_FAMILY,
+ MD_NTSTATUS_WIN_STATUS_TPM_NO_NV_PERMISSION,
+ MD_NTSTATUS_WIN_STATUS_TPM_REQUIRES_SIGN,
+ MD_NTSTATUS_WIN_STATUS_TPM_KEY_NOTSUPPORTED,
+ MD_NTSTATUS_WIN_STATUS_TPM_AUTH_CONFLICT,
+ MD_NTSTATUS_WIN_STATUS_TPM_AREA_LOCKED,
+ MD_NTSTATUS_WIN_STATUS_TPM_BAD_LOCALITY,
+ MD_NTSTATUS_WIN_STATUS_TPM_READ_ONLY,
+ MD_NTSTATUS_WIN_STATUS_TPM_PER_NOWRITE,
+ MD_NTSTATUS_WIN_STATUS_TPM_FAMILYCOUNT,
+ MD_NTSTATUS_WIN_STATUS_TPM_WRITE_LOCKED,
+ MD_NTSTATUS_WIN_STATUS_TPM_BAD_ATTRIBUTES,
+ MD_NTSTATUS_WIN_STATUS_TPM_INVALID_STRUCTURE,
+ MD_NTSTATUS_WIN_STATUS_TPM_KEY_OWNER_CONTROL,
+ MD_NTSTATUS_WIN_STATUS_TPM_BAD_COUNTER,
+ MD_NTSTATUS_WIN_STATUS_TPM_NOT_FULLWRITE,
+ MD_NTSTATUS_WIN_STATUS_TPM_CONTEXT_GAP,
+ MD_NTSTATUS_WIN_STATUS_TPM_MAXNVWRITES,
+ MD_NTSTATUS_WIN_STATUS_TPM_NOOPERATOR,
+ MD_NTSTATUS_WIN_STATUS_TPM_RESOURCEMISSING,
+ MD_NTSTATUS_WIN_STATUS_TPM_DELEGATE_LOCK,
+ MD_NTSTATUS_WIN_STATUS_TPM_DELEGATE_FAMILY,
+ MD_NTSTATUS_WIN_STATUS_TPM_DELEGATE_ADMIN,
+ MD_NTSTATUS_WIN_STATUS_TPM_TRANSPORT_NOTEXCLUSIVE,
+ MD_NTSTATUS_WIN_STATUS_TPM_OWNER_CONTROL,
+ MD_NTSTATUS_WIN_STATUS_TPM_DAA_RESOURCES,
+ MD_NTSTATUS_WIN_STATUS_TPM_DAA_INPUT_DATA0,
+ MD_NTSTATUS_WIN_STATUS_TPM_DAA_INPUT_DATA1,
+ MD_NTSTATUS_WIN_STATUS_TPM_DAA_ISSUER_SETTINGS,
+ MD_NTSTATUS_WIN_STATUS_TPM_DAA_TPM_SETTINGS,
+ MD_NTSTATUS_WIN_STATUS_TPM_DAA_STAGE,
+ MD_NTSTATUS_WIN_STATUS_TPM_DAA_ISSUER_VALIDITY,
+ MD_NTSTATUS_WIN_STATUS_TPM_DAA_WRONG_W,
+ MD_NTSTATUS_WIN_STATUS_TPM_BAD_HANDLE,
+ MD_NTSTATUS_WIN_STATUS_TPM_BAD_DELEGATE,
+ MD_NTSTATUS_WIN_STATUS_TPM_BADCONTEXT,
+ MD_NTSTATUS_WIN_STATUS_TPM_TOOMANYCONTEXTS,
+ MD_NTSTATUS_WIN_STATUS_TPM_MA_TICKET_SIGNATURE,
+ MD_NTSTATUS_WIN_STATUS_TPM_MA_DESTINATION,
+ MD_NTSTATUS_WIN_STATUS_TPM_MA_SOURCE,
+ MD_NTSTATUS_WIN_STATUS_TPM_MA_AUTHORITY,
+ MD_NTSTATUS_WIN_STATUS_TPM_PERMANENTEK,
+ MD_NTSTATUS_WIN_STATUS_TPM_BAD_SIGNATURE,
+ MD_NTSTATUS_WIN_STATUS_TPM_NOCONTEXTSPACE,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_ASYMMETRIC,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_ATTRIBUTES,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_HASH,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_VALUE,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_HIERARCHY,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_KEY_SIZE,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_MGF,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_MODE,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_TYPE,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_HANDLE,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_KDF,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_RANGE,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_AUTH_FAIL,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_NONCE,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_PP,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_SCHEME,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_SIZE,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_SYMMETRIC,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_TAG,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_SELECTOR,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_INSUFFICIENT,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_SIGNATURE,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_KEY,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_POLICY_FAIL,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_INTEGRITY,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_TICKET,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_RESERVED_BITS,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_BAD_AUTH,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_EXPIRED,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_POLICY_CC,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_BINDING,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_CURVE,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_ECC_POINT,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_INITIALIZE,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_FAILURE,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_SEQUENCE,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_PRIVATE,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_HMAC,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_DISABLED,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_EXCLUSIVE,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_ECC_CURVE,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_AUTH_TYPE,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_AUTH_MISSING,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_POLICY,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_PCR,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_PCR_CHANGED,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_UPGRADE,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_TOO_MANY_CONTEXTS,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_AUTH_UNAVAILABLE,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_REBOOT,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_UNBALANCED,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_COMMAND_SIZE,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_COMMAND_CODE,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_AUTHSIZE,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_AUTH_CONTEXT,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_NV_RANGE,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_NV_SIZE,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_NV_LOCKED,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_NV_AUTHORIZATION,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_NV_UNINITIALIZED,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_NV_SPACE,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_NV_DEFINED,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_BAD_CONTEXT,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_CPHASH,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_PARENT,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_NEEDS_TEST,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_NO_RESULT,
+ MD_NTSTATUS_WIN_STATUS_TPM_20_E_SENSITIVE,
+ MD_NTSTATUS_WIN_STATUS_TPM_COMMAND_BLOCKED,
+ MD_NTSTATUS_WIN_STATUS_TPM_INVALID_HANDLE,
+ MD_NTSTATUS_WIN_STATUS_TPM_DUPLICATE_VHANDLE,
+ MD_NTSTATUS_WIN_STATUS_TPM_EMBEDDED_COMMAND_BLOCKED,
+ MD_NTSTATUS_WIN_STATUS_TPM_EMBEDDED_COMMAND_UNSUPPORTED,
+ MD_NTSTATUS_WIN_STATUS_TPM_RETRY,
+ MD_NTSTATUS_WIN_STATUS_TPM_NEEDS_SELFTEST,
+ MD_NTSTATUS_WIN_STATUS_TPM_DOING_SELFTEST,
+ MD_NTSTATUS_WIN_STATUS_TPM_DEFEND_LOCK_RUNNING,
+ MD_NTSTATUS_WIN_STATUS_TPM_COMMAND_CANCELED,
+ MD_NTSTATUS_WIN_STATUS_TPM_TOO_MANY_CONTEXTS,
+ MD_NTSTATUS_WIN_STATUS_TPM_NOT_FOUND,
+ MD_NTSTATUS_WIN_STATUS_TPM_ACCESS_DENIED,
+ MD_NTSTATUS_WIN_STATUS_TPM_INSUFFICIENT_BUFFER,
+ MD_NTSTATUS_WIN_STATUS_TPM_PPI_FUNCTION_UNSUPPORTED,
+ MD_NTSTATUS_WIN_STATUS_PCP_ERROR_MASK,
+ MD_NTSTATUS_WIN_STATUS_PCP_DEVICE_NOT_READY,
+ MD_NTSTATUS_WIN_STATUS_PCP_INVALID_HANDLE,
+ MD_NTSTATUS_WIN_STATUS_PCP_INVALID_PARAMETER,
+ MD_NTSTATUS_WIN_STATUS_PCP_FLAG_NOT_SUPPORTED,
+ MD_NTSTATUS_WIN_STATUS_PCP_NOT_SUPPORTED,
+ MD_NTSTATUS_WIN_STATUS_PCP_BUFFER_TOO_SMALL,
+ MD_NTSTATUS_WIN_STATUS_PCP_INTERNAL_ERROR,
+ MD_NTSTATUS_WIN_STATUS_PCP_AUTHENTICATION_FAILED,
+ MD_NTSTATUS_WIN_STATUS_PCP_AUTHENTICATION_IGNORED,
+ MD_NTSTATUS_WIN_STATUS_PCP_POLICY_NOT_FOUND,
+ MD_NTSTATUS_WIN_STATUS_PCP_PROFILE_NOT_FOUND,
+ MD_NTSTATUS_WIN_STATUS_PCP_VALIDATION_FAILED,
+ MD_NTSTATUS_WIN_STATUS_PCP_DEVICE_NOT_FOUND,
+ MD_NTSTATUS_WIN_STATUS_PCP_WRONG_PARENT,
+ MD_NTSTATUS_WIN_STATUS_PCP_KEY_NOT_LOADED,
+ MD_NTSTATUS_WIN_STATUS_PCP_NO_KEY_CERTIFICATION,
+ MD_NTSTATUS_WIN_STATUS_PCP_KEY_NOT_FINALIZED,
+ MD_NTSTATUS_WIN_STATUS_PCP_ATTESTATION_CHALLENGE_NOT_SET,
+ MD_NTSTATUS_WIN_STATUS_PCP_NOT_PCR_BOUND,
+ MD_NTSTATUS_WIN_STATUS_PCP_KEY_ALREADY_FINALIZED,
+ MD_NTSTATUS_WIN_STATUS_PCP_KEY_USAGE_POLICY_NOT_SUPPORTED,
+ MD_NTSTATUS_WIN_STATUS_PCP_KEY_USAGE_POLICY_INVALID,
+ MD_NTSTATUS_WIN_STATUS_PCP_SOFT_KEY_ERROR,
+ MD_NTSTATUS_WIN_STATUS_PCP_KEY_NOT_AUTHENTICATED,
+ MD_NTSTATUS_WIN_STATUS_PCP_KEY_NOT_AIK,
+ MD_NTSTATUS_WIN_STATUS_PCP_KEY_NOT_SIGNING_KEY,
+ MD_NTSTATUS_WIN_STATUS_PCP_LOCKED_OUT,
+ MD_NTSTATUS_WIN_STATUS_PCP_CLAIM_TYPE_NOT_SUPPORTED,
+ MD_NTSTATUS_WIN_STATUS_PCP_TPM_VERSION_NOT_SUPPORTED,
+ MD_NTSTATUS_WIN_STATUS_PCP_BUFFER_LENGTH_MISMATCH,
+ MD_NTSTATUS_WIN_STATUS_PCP_IFX_RSA_KEY_CREATION_BLOCKED,
+ MD_NTSTATUS_WIN_STATUS_PCP_TICKET_MISSING,
+ MD_NTSTATUS_WIN_STATUS_PCP_RAW_POLICY_NOT_SUPPORTED,
+ MD_NTSTATUS_WIN_STATUS_PCP_KEY_HANDLE_INVALIDATED,
+ MD_NTSTATUS_WIN_STATUS_RTPM_NO_RESULT,
+ MD_NTSTATUS_WIN_STATUS_RTPM_PCR_READ_INCOMPLETE,
+ MD_NTSTATUS_WIN_STATUS_RTPM_INVALID_CONTEXT,
+ MD_NTSTATUS_WIN_STATUS_RTPM_UNSUPPORTED_CMD,
+ MD_NTSTATUS_WIN_STATUS_TPM_ZERO_EXHAUST_ENABLED,
+ MD_NTSTATUS_WIN_STATUS_HV_INVALID_HYPERCALL_CODE,
+ MD_NTSTATUS_WIN_STATUS_HV_INVALID_HYPERCALL_INPUT,
+ MD_NTSTATUS_WIN_STATUS_HV_INVALID_ALIGNMENT,
+ MD_NTSTATUS_WIN_STATUS_HV_INVALID_PARAMETER,
+ MD_NTSTATUS_WIN_STATUS_HV_ACCESS_DENIED,
+ MD_NTSTATUS_WIN_STATUS_HV_INVALID_PARTITION_STATE,
+ MD_NTSTATUS_WIN_STATUS_HV_OPERATION_DENIED,
+ MD_NTSTATUS_WIN_STATUS_HV_UNKNOWN_PROPERTY,
+ MD_NTSTATUS_WIN_STATUS_HV_PROPERTY_VALUE_OUT_OF_RANGE,
+ MD_NTSTATUS_WIN_STATUS_HV_INSUFFICIENT_MEMORY,
+ MD_NTSTATUS_WIN_STATUS_HV_PARTITION_TOO_DEEP,
+ MD_NTSTATUS_WIN_STATUS_HV_INVALID_PARTITION_ID,
+ MD_NTSTATUS_WIN_STATUS_HV_INVALID_VP_INDEX,
+ MD_NTSTATUS_WIN_STATUS_HV_INVALID_PORT_ID,
+ MD_NTSTATUS_WIN_STATUS_HV_INVALID_CONNECTION_ID,
+ MD_NTSTATUS_WIN_STATUS_HV_INSUFFICIENT_BUFFERS,
+ MD_NTSTATUS_WIN_STATUS_HV_NOT_ACKNOWLEDGED,
+ MD_NTSTATUS_WIN_STATUS_HV_INVALID_VP_STATE,
+ MD_NTSTATUS_WIN_STATUS_HV_ACKNOWLEDGED,
+ MD_NTSTATUS_WIN_STATUS_HV_INVALID_SAVE_RESTORE_STATE,
+ MD_NTSTATUS_WIN_STATUS_HV_INVALID_SYNIC_STATE,
+ MD_NTSTATUS_WIN_STATUS_HV_OBJECT_IN_USE,
+ MD_NTSTATUS_WIN_STATUS_HV_INVALID_PROXIMITY_DOMAIN_INFO,
+ MD_NTSTATUS_WIN_STATUS_HV_NO_DATA,
+ MD_NTSTATUS_WIN_STATUS_HV_INACTIVE,
+ MD_NTSTATUS_WIN_STATUS_HV_NO_RESOURCES,
+ MD_NTSTATUS_WIN_STATUS_HV_FEATURE_UNAVAILABLE,
+ MD_NTSTATUS_WIN_STATUS_HV_INSUFFICIENT_BUFFER,
+ MD_NTSTATUS_WIN_STATUS_HV_INSUFFICIENT_DEVICE_DOMAINS,
+ MD_NTSTATUS_WIN_STATUS_HV_CPUID_FEATURE_VALIDATION_ERROR,
+ MD_NTSTATUS_WIN_STATUS_HV_CPUID_XSAVE_FEATURE_VALIDATION_ERROR,
+ MD_NTSTATUS_WIN_STATUS_HV_PROCESSOR_STARTUP_TIMEOUT,
+ MD_NTSTATUS_WIN_STATUS_HV_SMX_ENABLED,
+ MD_NTSTATUS_WIN_STATUS_HV_INVALID_LP_INDEX,
+ MD_NTSTATUS_WIN_STATUS_HV_INVALID_REGISTER_VALUE,
+ MD_NTSTATUS_WIN_STATUS_HV_INVALID_VTL_STATE,
+ MD_NTSTATUS_WIN_STATUS_HV_NX_NOT_DETECTED,
+ MD_NTSTATUS_WIN_STATUS_HV_INVALID_DEVICE_ID,
+ MD_NTSTATUS_WIN_STATUS_HV_INVALID_DEVICE_STATE,
+ MD_NTSTATUS_WIN_STATUS_HV_PAGE_REQUEST_INVALID,
+ MD_NTSTATUS_WIN_STATUS_HV_INVALID_CPU_GROUP_ID,
+ MD_NTSTATUS_WIN_STATUS_HV_INVALID_CPU_GROUP_STATE,
+ MD_NTSTATUS_WIN_STATUS_HV_OPERATION_FAILED,
+ MD_NTSTATUS_WIN_STATUS_HV_NOT_ALLOWED_WITH_NESTED_VIRT_ACTIVE,
+ MD_NTSTATUS_WIN_STATUS_HV_INSUFFICIENT_ROOT_MEMORY,
+ MD_NTSTATUS_WIN_STATUS_HV_EVENT_BUFFER_ALREADY_FREED,
+ MD_NTSTATUS_WIN_STATUS_HV_INSUFFICIENT_CONTIGUOUS_MEMORY,
+ MD_NTSTATUS_WIN_STATUS_HV_NOT_PRESENT,
+ MD_NTSTATUS_WIN_STATUS_IPSEC_BAD_SPI,
+ MD_NTSTATUS_WIN_STATUS_IPSEC_SA_LIFETIME_EXPIRED,
+ MD_NTSTATUS_WIN_STATUS_IPSEC_WRONG_SA,
+ MD_NTSTATUS_WIN_STATUS_IPSEC_REPLAY_CHECK_FAILED,
+ MD_NTSTATUS_WIN_STATUS_IPSEC_INVALID_PACKET,
+ MD_NTSTATUS_WIN_STATUS_IPSEC_INTEGRITY_CHECK_FAILED,
+ MD_NTSTATUS_WIN_STATUS_IPSEC_CLEAR_TEXT_DROP,
+ MD_NTSTATUS_WIN_STATUS_IPSEC_AUTH_FIREWALL_DROP,
+ MD_NTSTATUS_WIN_STATUS_IPSEC_THROTTLE_DROP,
+ MD_NTSTATUS_WIN_STATUS_IPSEC_DOSP_BLOCK,
+ MD_NTSTATUS_WIN_STATUS_IPSEC_DOSP_RECEIVED_MULTICAST,
+ MD_NTSTATUS_WIN_STATUS_IPSEC_DOSP_INVALID_PACKET,
+ MD_NTSTATUS_WIN_STATUS_IPSEC_DOSP_STATE_LOOKUP_FAILED,
+ MD_NTSTATUS_WIN_STATUS_IPSEC_DOSP_MAX_ENTRIES,
+ MD_NTSTATUS_WIN_STATUS_IPSEC_DOSP_KEYMOD_NOT_ALLOWED,
+ MD_NTSTATUS_WIN_STATUS_IPSEC_DOSP_MAX_PER_IP_RATELIMIT_QUEUES,
+ MD_NTSTATUS_WIN_STATUS_VID_DUPLICATE_HANDLER,
+ MD_NTSTATUS_WIN_STATUS_VID_TOO_MANY_HANDLERS,
+ MD_NTSTATUS_WIN_STATUS_VID_QUEUE_FULL,
+ MD_NTSTATUS_WIN_STATUS_VID_HANDLER_NOT_PRESENT,
+ MD_NTSTATUS_WIN_STATUS_VID_INVALID_OBJECT_NAME,
+ MD_NTSTATUS_WIN_STATUS_VID_PARTITION_NAME_TOO_LONG,
+ MD_NTSTATUS_WIN_STATUS_VID_MESSAGE_QUEUE_NAME_TOO_LONG,
+ MD_NTSTATUS_WIN_STATUS_VID_PARTITION_ALREADY_EXISTS,
+ MD_NTSTATUS_WIN_STATUS_VID_PARTITION_DOES_NOT_EXIST,
+ MD_NTSTATUS_WIN_STATUS_VID_PARTITION_NAME_NOT_FOUND,
+ MD_NTSTATUS_WIN_STATUS_VID_MESSAGE_QUEUE_ALREADY_EXISTS,
+ MD_NTSTATUS_WIN_STATUS_VID_EXCEEDED_MBP_ENTRY_MAP_LIMIT,
+ MD_NTSTATUS_WIN_STATUS_VID_MB_STILL_REFERENCED,
+ MD_NTSTATUS_WIN_STATUS_VID_CHILD_GPA_PAGE_SET_CORRUPTED,
+ MD_NTSTATUS_WIN_STATUS_VID_INVALID_NUMA_SETTINGS,
+ MD_NTSTATUS_WIN_STATUS_VID_INVALID_NUMA_NODE_INDEX,
+ MD_NTSTATUS_WIN_STATUS_VID_NOTIFICATION_QUEUE_ALREADY_ASSOCIATED,
+ MD_NTSTATUS_WIN_STATUS_VID_INVALID_MEMORY_BLOCK_HANDLE,
+ MD_NTSTATUS_WIN_STATUS_VID_PAGE_RANGE_OVERFLOW,
+ MD_NTSTATUS_WIN_STATUS_VID_INVALID_MESSAGE_QUEUE_HANDLE,
+ MD_NTSTATUS_WIN_STATUS_VID_INVALID_GPA_RANGE_HANDLE,
+ MD_NTSTATUS_WIN_STATUS_VID_NO_MEMORY_BLOCK_NOTIFICATION_QUEUE,
+ MD_NTSTATUS_WIN_STATUS_VID_MEMORY_BLOCK_LOCK_COUNT_EXCEEDED,
+ MD_NTSTATUS_WIN_STATUS_VID_INVALID_PPM_HANDLE,
+ MD_NTSTATUS_WIN_STATUS_VID_MBPS_ARE_LOCKED,
+ MD_NTSTATUS_WIN_STATUS_VID_MESSAGE_QUEUE_CLOSED,
+ MD_NTSTATUS_WIN_STATUS_VID_VIRTUAL_PROCESSOR_LIMIT_EXCEEDED,
+ MD_NTSTATUS_WIN_STATUS_VID_STOP_PENDING,
+ MD_NTSTATUS_WIN_STATUS_VID_INVALID_PROCESSOR_STATE,
+ MD_NTSTATUS_WIN_STATUS_VID_EXCEEDED_KM_CONTEXT_COUNT_LIMIT,
+ MD_NTSTATUS_WIN_STATUS_VID_KM_INTERFACE_ALREADY_INITIALIZED,
+ MD_NTSTATUS_WIN_STATUS_VID_MB_PROPERTY_ALREADY_SET_RESET,
+ MD_NTSTATUS_WIN_STATUS_VID_MMIO_RANGE_DESTROYED,
+ MD_NTSTATUS_WIN_STATUS_VID_INVALID_CHILD_GPA_PAGE_SET,
+ MD_NTSTATUS_WIN_STATUS_VID_RESERVE_PAGE_SET_IS_BEING_USED,
+ MD_NTSTATUS_WIN_STATUS_VID_RESERVE_PAGE_SET_TOO_SMALL,
+ MD_NTSTATUS_WIN_STATUS_VID_MBP_ALREADY_LOCKED_USING_RESERVED_PAGE,
+ MD_NTSTATUS_WIN_STATUS_VID_MBP_COUNT_EXCEEDED_LIMIT,
+ MD_NTSTATUS_WIN_STATUS_VID_SAVED_STATE_CORRUPT,
+ MD_NTSTATUS_WIN_STATUS_VID_SAVED_STATE_UNRECOGNIZED_ITEM,
+ MD_NTSTATUS_WIN_STATUS_VID_SAVED_STATE_INCOMPATIBLE,
+ MD_NTSTATUS_WIN_STATUS_VID_VTL_ACCESS_DENIED,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_DATABASE_FULL,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_CONFIGURATION_CORRUPTED,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_CONFIGURATION_NOT_IN_SYNC,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_PACK_CONFIG_UPDATE_FAILED,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_CONTAINS_NON_SIMPLE_VOLUME,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_DUPLICATE,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_DYNAMIC,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_ID_INVALID,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_INVALID,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_LAST_VOTER,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_LAYOUT_INVALID,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_LAYOUT_NON_BASIC_BETWEEN_BASIC_PARTITIONS,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_LAYOUT_NOT_CYLINDER_ALIGNED,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_LAYOUT_PARTITIONS_TOO_SMALL,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_LAYOUT_PRIMARY_BETWEEN_LOGICAL_PARTITIONS,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_LAYOUT_TOO_MANY_PARTITIONS,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_MISSING,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_NOT_EMPTY,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_NOT_ENOUGH_SPACE,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_REVECTORING_FAILED,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_SECTOR_SIZE_INVALID,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_SET_NOT_CONTAINED,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_USED_BY_MULTIPLE_MEMBERS,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_USED_BY_MULTIPLE_PLEXES,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_DYNAMIC_DISK_NOT_SUPPORTED,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_EXTENT_ALREADY_USED,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_EXTENT_NOT_CONTIGUOUS,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_EXTENT_NOT_IN_PUBLIC_REGION,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_EXTENT_NOT_SECTOR_ALIGNED,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_EXTENT_OVERLAPS_EBR_PARTITION,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_EXTENT_VOLUME_LENGTHS_DO_NOT_MATCH,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_FAULT_TOLERANT_NOT_SUPPORTED,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_INTERLEAVE_LENGTH_INVALID,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_MAXIMUM_REGISTERED_USERS,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_MEMBER_IN_SYNC,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_MEMBER_INDEX_DUPLICATE,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_MEMBER_INDEX_INVALID,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_MEMBER_MISSING,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_MEMBER_NOT_DETACHED,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_MEMBER_REGENERATING,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_ALL_DISKS_FAILED,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_NO_REGISTERED_USERS,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_NO_SUCH_USER,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_NOTIFICATION_RESET,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_NUMBER_OF_MEMBERS_INVALID,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_NUMBER_OF_PLEXES_INVALID,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_PACK_DUPLICATE,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_PACK_ID_INVALID,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_PACK_INVALID,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_PACK_NAME_INVALID,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_PACK_OFFLINE,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_PACK_HAS_QUORUM,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_PACK_WITHOUT_QUORUM,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_PARTITION_STYLE_INVALID,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_PARTITION_UPDATE_FAILED,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_PLEX_IN_SYNC,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_PLEX_INDEX_DUPLICATE,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_PLEX_INDEX_INVALID,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_PLEX_LAST_ACTIVE,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_PLEX_MISSING,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_PLEX_REGENERATING,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_PLEX_TYPE_INVALID,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_PLEX_NOT_RAID5,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_PLEX_NOT_SIMPLE,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_STRUCTURE_SIZE_INVALID,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_TOO_MANY_NOTIFICATION_REQUESTS,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_TRANSACTION_IN_PROGRESS,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_UNEXPECTED_DISK_LAYOUT_CHANGE,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_VOLUME_CONTAINS_MISSING_DISK,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_VOLUME_ID_INVALID,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_VOLUME_LENGTH_INVALID,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_VOLUME_LENGTH_NOT_SECTOR_SIZE_MULTIPLE,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_VOLUME_NOT_MIRRORED,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_VOLUME_NOT_RETAINED,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_VOLUME_OFFLINE,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_VOLUME_RETAINED,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_NUMBER_OF_EXTENTS_INVALID,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_DIFFERENT_SECTOR_SIZE,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_BAD_BOOT_DISK,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_PACK_CONFIG_OFFLINE,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_PACK_CONFIG_ONLINE,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_NOT_PRIMARY_PACK,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_PACK_LOG_UPDATE_FAILED,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_NUMBER_OF_DISKS_IN_PLEX_INVALID,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_NUMBER_OF_DISKS_IN_MEMBER_INVALID,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_VOLUME_MIRRORED,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_PLEX_NOT_SIMPLE_SPANNED,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_NO_VALID_LOG_COPIES,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_PRIMARY_PACK_PRESENT,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_NUMBER_OF_DISKS_INVALID,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_MIRROR_NOT_SUPPORTED,
+ MD_NTSTATUS_WIN_STATUS_VOLMGR_RAID5_NOT_SUPPORTED,
+ MD_NTSTATUS_WIN_STATUS_BCD_TOO_MANY_ELEMENTS,
+ MD_NTSTATUS_WIN_STATUS_VHD_DRIVE_FOOTER_MISSING,
+ MD_NTSTATUS_WIN_STATUS_VHD_DRIVE_FOOTER_CHECKSUM_MISMATCH,
+ MD_NTSTATUS_WIN_STATUS_VHD_DRIVE_FOOTER_CORRUPT,
+ MD_NTSTATUS_WIN_STATUS_VHD_FORMAT_UNKNOWN,
+ MD_NTSTATUS_WIN_STATUS_VHD_FORMAT_UNSUPPORTED_VERSION,
+ MD_NTSTATUS_WIN_STATUS_VHD_SPARSE_HEADER_CHECKSUM_MISMATCH,
+ MD_NTSTATUS_WIN_STATUS_VHD_SPARSE_HEADER_UNSUPPORTED_VERSION,
+ MD_NTSTATUS_WIN_STATUS_VHD_SPARSE_HEADER_CORRUPT,
+ MD_NTSTATUS_WIN_STATUS_VHD_BLOCK_ALLOCATION_FAILURE,
+ MD_NTSTATUS_WIN_STATUS_VHD_BLOCK_ALLOCATION_TABLE_CORRUPT,
+ MD_NTSTATUS_WIN_STATUS_VHD_INVALID_BLOCK_SIZE,
+ MD_NTSTATUS_WIN_STATUS_VHD_BITMAP_MISMATCH,
+ MD_NTSTATUS_WIN_STATUS_VHD_PARENT_VHD_NOT_FOUND,
+ MD_NTSTATUS_WIN_STATUS_VHD_CHILD_PARENT_ID_MISMATCH,
+ MD_NTSTATUS_WIN_STATUS_VHD_CHILD_PARENT_TIMESTAMP_MISMATCH,
+ MD_NTSTATUS_WIN_STATUS_VHD_METADATA_READ_FAILURE,
+ MD_NTSTATUS_WIN_STATUS_VHD_METADATA_WRITE_FAILURE,
+ MD_NTSTATUS_WIN_STATUS_VHD_INVALID_SIZE,
+ MD_NTSTATUS_WIN_STATUS_VHD_INVALID_FILE_SIZE,
+ MD_NTSTATUS_WIN_STATUS_VIRTDISK_PROVIDER_NOT_FOUND,
+ MD_NTSTATUS_WIN_STATUS_VIRTDISK_NOT_VIRTUAL_DISK,
+ MD_NTSTATUS_WIN_STATUS_VHD_PARENT_VHD_ACCESS_DENIED,
+ MD_NTSTATUS_WIN_STATUS_VHD_CHILD_PARENT_SIZE_MISMATCH,
+ MD_NTSTATUS_WIN_STATUS_VHD_DIFFERENCING_CHAIN_CYCLE_DETECTED,
+ MD_NTSTATUS_WIN_STATUS_VHD_DIFFERENCING_CHAIN_ERROR_IN_PARENT,
+ MD_NTSTATUS_WIN_STATUS_VIRTUAL_DISK_LIMITATION,
+ MD_NTSTATUS_WIN_STATUS_VHD_INVALID_TYPE,
+ MD_NTSTATUS_WIN_STATUS_VHD_INVALID_STATE,
+ MD_NTSTATUS_WIN_STATUS_VIRTDISK_UNSUPPORTED_DISK_SECTOR_SIZE,
+ MD_NTSTATUS_WIN_STATUS_VIRTDISK_DISK_ALREADY_OWNED,
+ MD_NTSTATUS_WIN_STATUS_VIRTDISK_DISK_ONLINE_AND_WRITABLE,
+ MD_NTSTATUS_WIN_STATUS_CTLOG_TRACKING_NOT_INITIALIZED,
+ MD_NTSTATUS_WIN_STATUS_CTLOG_LOGFILE_SIZE_EXCEEDED_MAXSIZE,
+ MD_NTSTATUS_WIN_STATUS_CTLOG_VHD_CHANGED_OFFLINE,
+ MD_NTSTATUS_WIN_STATUS_CTLOG_INVALID_TRACKING_STATE,
+ MD_NTSTATUS_WIN_STATUS_CTLOG_INCONSISTENT_TRACKING_FILE,
+ MD_NTSTATUS_WIN_STATUS_VHD_METADATA_FULL,
+ MD_NTSTATUS_WIN_STATUS_VHD_INVALID_CHANGE_TRACKING_ID,
+ MD_NTSTATUS_WIN_STATUS_VHD_CHANGE_TRACKING_DISABLED,
+ MD_NTSTATUS_WIN_STATUS_VHD_MISSING_CHANGE_TRACKING_INFORMATION,
+ MD_NTSTATUS_WIN_STATUS_VHD_RESIZE_WOULD_TRUNCATE_DATA,
+ MD_NTSTATUS_WIN_STATUS_VHD_COULD_NOT_COMPUTE_MINIMUM_VIRTUAL_SIZE,
+ MD_NTSTATUS_WIN_STATUS_VHD_ALREADY_AT_OR_BELOW_MINIMUM_VIRTUAL_SIZE,
+ MD_NTSTATUS_WIN_STATUS_RKF_KEY_NOT_FOUND,
+ MD_NTSTATUS_WIN_STATUS_RKF_DUPLICATE_KEY,
+ MD_NTSTATUS_WIN_STATUS_RKF_BLOB_FULL,
+ MD_NTSTATUS_WIN_STATUS_RKF_STORE_FULL,
+ MD_NTSTATUS_WIN_STATUS_RKF_FILE_BLOCKED,
+ MD_NTSTATUS_WIN_STATUS_RKF_ACTIVE_KEY,
+ MD_NTSTATUS_WIN_STATUS_RDBSS_RESTART_OPERATION,
+ MD_NTSTATUS_WIN_STATUS_RDBSS_CONTINUE_OPERATION,
+ MD_NTSTATUS_WIN_STATUS_RDBSS_POST_OPERATION,
+ MD_NTSTATUS_WIN_STATUS_RDBSS_RETRY_LOOKUP,
+ MD_NTSTATUS_WIN_STATUS_BTH_ATT_INVALID_HANDLE,
+ MD_NTSTATUS_WIN_STATUS_BTH_ATT_READ_NOT_PERMITTED,
+ MD_NTSTATUS_WIN_STATUS_BTH_ATT_WRITE_NOT_PERMITTED,
+ MD_NTSTATUS_WIN_STATUS_BTH_ATT_INVALID_PDU,
+ MD_NTSTATUS_WIN_STATUS_BTH_ATT_INSUFFICIENT_AUTHENTICATION,
+ MD_NTSTATUS_WIN_STATUS_BTH_ATT_REQUEST_NOT_SUPPORTED,
+ MD_NTSTATUS_WIN_STATUS_BTH_ATT_INVALID_OFFSET,
+ MD_NTSTATUS_WIN_STATUS_BTH_ATT_INSUFFICIENT_AUTHORIZATION,
+ MD_NTSTATUS_WIN_STATUS_BTH_ATT_PREPARE_QUEUE_FULL,
+ MD_NTSTATUS_WIN_STATUS_BTH_ATT_ATTRIBUTE_NOT_FOUND,
+ MD_NTSTATUS_WIN_STATUS_BTH_ATT_ATTRIBUTE_NOT_LONG,
+ MD_NTSTATUS_WIN_STATUS_BTH_ATT_INSUFFICIENT_ENCRYPTION_KEY_SIZE,
+ MD_NTSTATUS_WIN_STATUS_BTH_ATT_INVALID_ATTRIBUTE_VALUE_LENGTH,
+ MD_NTSTATUS_WIN_STATUS_BTH_ATT_UNLIKELY,
+ MD_NTSTATUS_WIN_STATUS_BTH_ATT_INSUFFICIENT_ENCRYPTION,
+ MD_NTSTATUS_WIN_STATUS_BTH_ATT_UNSUPPORTED_GROUP_TYPE,
+ MD_NTSTATUS_WIN_STATUS_BTH_ATT_INSUFFICIENT_RESOURCES,
+ MD_NTSTATUS_WIN_STATUS_BTH_ATT_UNKNOWN_ERROR,
+ MD_NTSTATUS_WIN_STATUS_SECUREBOOT_ROLLBACK_DETECTED,
+ MD_NTSTATUS_WIN_STATUS_SECUREBOOT_POLICY_VIOLATION,
+ MD_NTSTATUS_WIN_STATUS_SECUREBOOT_INVALID_POLICY,
+ MD_NTSTATUS_WIN_STATUS_SECUREBOOT_POLICY_PUBLISHER_NOT_FOUND,
+ MD_NTSTATUS_WIN_STATUS_SECUREBOOT_POLICY_NOT_SIGNED,
+ MD_NTSTATUS_WIN_STATUS_SECUREBOOT_FILE_REPLACED,
+ MD_NTSTATUS_WIN_STATUS_SECUREBOOT_POLICY_NOT_AUTHORIZED,
+ MD_NTSTATUS_WIN_STATUS_SECUREBOOT_POLICY_UNKNOWN,
+ MD_NTSTATUS_WIN_STATUS_SECUREBOOT_POLICY_MISSING_ANTIROLLBACKVERSION,
+ MD_NTSTATUS_WIN_STATUS_SECUREBOOT_PLATFORM_ID_MISMATCH,
+ MD_NTSTATUS_WIN_STATUS_SECUREBOOT_POLICY_ROLLBACK_DETECTED,
+ MD_NTSTATUS_WIN_STATUS_SECUREBOOT_POLICY_UPGRADE_MISMATCH,
+ MD_NTSTATUS_WIN_STATUS_SECUREBOOT_REQUIRED_POLICY_FILE_MISSING,
+ MD_NTSTATUS_WIN_STATUS_SECUREBOOT_NOT_BASE_POLICY,
+ MD_NTSTATUS_WIN_STATUS_SECUREBOOT_NOT_SUPPLEMENTAL_POLICY,
+ MD_NTSTATUS_WIN_STATUS_AUDIO_ENGINE_NODE_NOT_FOUND,
+ MD_NTSTATUS_WIN_STATUS_HDAUDIO_EMPTY_CONNECTION_LIST,
+ MD_NTSTATUS_WIN_STATUS_HDAUDIO_CONNECTION_LIST_NOT_SUPPORTED,
+ MD_NTSTATUS_WIN_STATUS_HDAUDIO_NO_LOGICAL_DEVICES_CREATED,
+ MD_NTSTATUS_WIN_STATUS_HDAUDIO_NULL_LINKED_LIST_ENTRY,
+ MD_NTSTATUS_WIN_STATUS_VSM_NOT_INITIALIZED,
+ MD_NTSTATUS_WIN_STATUS_VSM_DMA_PROTECTION_NOT_IN_USE,
+ MD_NTSTATUS_WIN_STATUS_VOLSNAP_BOOTFILE_NOT_VALID,
+ MD_NTSTATUS_WIN_STATUS_VOLSNAP_ACTIVATION_TIMEOUT,
+ MD_NTSTATUS_WIN_STATUS_IO_PREEMPTED,
+ MD_NTSTATUS_WIN_STATUS_SVHDX_ERROR_STORED,
+ MD_NTSTATUS_WIN_STATUS_SVHDX_ERROR_NOT_AVAILABLE,
+ MD_NTSTATUS_WIN_STATUS_SVHDX_UNIT_ATTENTION_AVAILABLE,
+ MD_NTSTATUS_WIN_STATUS_SVHDX_UNIT_ATTENTION_CAPACITY_DATA_CHANGED,
+ MD_NTSTATUS_WIN_STATUS_SVHDX_UNIT_ATTENTION_RESERVATIONS_PREEMPTED,
+ MD_NTSTATUS_WIN_STATUS_SVHDX_UNIT_ATTENTION_RESERVATIONS_RELEASED,
+ MD_NTSTATUS_WIN_STATUS_SVHDX_UNIT_ATTENTION_REGISTRATIONS_PREEMPTED,
+ MD_NTSTATUS_WIN_STATUS_SVHDX_UNIT_ATTENTION_OPERATING_DEFINITION_CHANGED,
+ MD_NTSTATUS_WIN_STATUS_SVHDX_RESERVATION_CONFLICT,
+ MD_NTSTATUS_WIN_STATUS_SVHDX_WRONG_FILE_TYPE,
+ MD_NTSTATUS_WIN_STATUS_SVHDX_VERSION_MISMATCH,
+ MD_NTSTATUS_WIN_STATUS_VHD_SHARED,
+ MD_NTSTATUS_WIN_STATUS_SVHDX_NO_INITIATOR,
+ MD_NTSTATUS_WIN_STATUS_VHDSET_BACKING_STORAGE_NOT_FOUND,
+ MD_NTSTATUS_WIN_STATUS_SMB_NO_PREAUTH_INTEGRITY_HASH_OVERLAP,
+ MD_NTSTATUS_WIN_STATUS_SMB_BAD_CLUSTER_DIALECT,
+ MD_NTSTATUS_WIN_STATUS_SMB_GUEST_LOGON_BLOCKED,
+ MD_NTSTATUS_WIN_STATUS_SPACES_FAULT_DOMAIN_TYPE_INVALID,
+ MD_NTSTATUS_WIN_STATUS_SPACES_RESILIENCY_TYPE_INVALID,
+ MD_NTSTATUS_WIN_STATUS_SPACES_DRIVE_SECTOR_SIZE_INVALID,
+ MD_NTSTATUS_WIN_STATUS_SPACES_DRIVE_REDUNDANCY_INVALID,
+ MD_NTSTATUS_WIN_STATUS_SPACES_NUMBER_OF_DATA_COPIES_INVALID,
+ MD_NTSTATUS_WIN_STATUS_SPACES_INTERLEAVE_LENGTH_INVALID,
+ MD_NTSTATUS_WIN_STATUS_SPACES_NUMBER_OF_COLUMNS_INVALID,
+ MD_NTSTATUS_WIN_STATUS_SPACES_NOT_ENOUGH_DRIVES,
+ MD_NTSTATUS_WIN_STATUS_SPACES_EXTENDED_ERROR,
+ MD_NTSTATUS_WIN_STATUS_SPACES_PROVISIONING_TYPE_INVALID,
+ MD_NTSTATUS_WIN_STATUS_SPACES_ALLOCATION_SIZE_INVALID,
+ MD_NTSTATUS_WIN_STATUS_SPACES_ENCLOSURE_AWARE_INVALID,
+ MD_NTSTATUS_WIN_STATUS_SPACES_WRITE_CACHE_SIZE_INVALID,
+ MD_NTSTATUS_WIN_STATUS_SPACES_NUMBER_OF_GROUPS_INVALID,
+ MD_NTSTATUS_WIN_STATUS_SPACES_DRIVE_OPERATIONAL_STATE_INVALID,
+ MD_NTSTATUS_WIN_STATUS_SPACES_UPDATE_COLUMN_STATE,
+ MD_NTSTATUS_WIN_STATUS_SPACES_MAP_REQUIRED,
+ MD_NTSTATUS_WIN_STATUS_SPACES_UNSUPPORTED_VERSION,
+ MD_NTSTATUS_WIN_STATUS_SPACES_CORRUPT_METADATA,
+ MD_NTSTATUS_WIN_STATUS_SPACES_DRT_FULL,
+ MD_NTSTATUS_WIN_STATUS_SPACES_INCONSISTENCY,
+ MD_NTSTATUS_WIN_STATUS_SPACES_LOG_NOT_READY,
+ MD_NTSTATUS_WIN_STATUS_SPACES_NO_REDUNDANCY,
+ MD_NTSTATUS_WIN_STATUS_SPACES_DRIVE_NOT_READY,
+ MD_NTSTATUS_WIN_STATUS_SPACES_DRIVE_SPLIT,
+ MD_NTSTATUS_WIN_STATUS_SPACES_DRIVE_LOST_DATA,
+ MD_NTSTATUS_WIN_STATUS_SPACES_ENTRY_INCOMPLETE,
+ MD_NTSTATUS_WIN_STATUS_SPACES_ENTRY_INVALID,
+ MD_NTSTATUS_WIN_STATUS_SPACES_MARK_DIRTY,
+ MD_NTSTATUS_WIN_STATUS_SECCORE_INVALID_COMMAND,
+ MD_NTSTATUS_WIN_STATUS_SYSTEM_INTEGRITY_ROLLBACK_DETECTED,
+ MD_NTSTATUS_WIN_STATUS_SYSTEM_INTEGRITY_POLICY_VIOLATION,
+ MD_NTSTATUS_WIN_STATUS_SYSTEM_INTEGRITY_INVALID_POLICY,
+ MD_NTSTATUS_WIN_STATUS_SYSTEM_INTEGRITY_POLICY_NOT_SIGNED,
+ MD_NTSTATUS_WIN_STATUS_SYSTEM_INTEGRITY_TOO_MANY_POLICIES,
+ MD_NTSTATUS_WIN_STATUS_SYSTEM_INTEGRITY_SUPPLEMENTAL_POLICY_NOT_AUTHORIZED,
+ MD_NTSTATUS_WIN_STATUS_NO_APPLICABLE_APP_LICENSES_FOUND,
+ MD_NTSTATUS_WIN_STATUS_CLIP_LICENSE_NOT_FOUND,
+ MD_NTSTATUS_WIN_STATUS_CLIP_DEVICE_LICENSE_MISSING,
+ MD_NTSTATUS_WIN_STATUS_CLIP_LICENSE_INVALID_SIGNATURE,
+ MD_NTSTATUS_WIN_STATUS_CLIP_KEYHOLDER_LICENSE_MISSING_OR_INVALID,
+ MD_NTSTATUS_WIN_STATUS_CLIP_LICENSE_EXPIRED,
+ MD_NTSTATUS_WIN_STATUS_CLIP_LICENSE_SIGNED_BY_UNKNOWN_SOURCE,
+ MD_NTSTATUS_WIN_STATUS_CLIP_LICENSE_NOT_SIGNED,
+ MD_NTSTATUS_WIN_STATUS_CLIP_LICENSE_HARDWARE_ID_OUT_OF_TOLERANCE,
+ MD_NTSTATUS_WIN_STATUS_CLIP_LICENSE_DEVICE_ID_MISMATCH,
+ MD_NTSTATUS_WIN_STATUS_PLATFORM_MANIFEST_NOT_AUTHORIZED,
+ MD_NTSTATUS_WIN_STATUS_PLATFORM_MANIFEST_INVALID,
+ MD_NTSTATUS_WIN_STATUS_PLATFORM_MANIFEST_FILE_NOT_AUTHORIZED,
+ MD_NTSTATUS_WIN_STATUS_PLATFORM_MANIFEST_CATALOG_NOT_AUTHORIZED,
+ MD_NTSTATUS_WIN_STATUS_PLATFORM_MANIFEST_BINARY_ID_NOT_FOUND,
+ MD_NTSTATUS_WIN_STATUS_PLATFORM_MANIFEST_NOT_ACTIVE,
+ MD_NTSTATUS_WIN_STATUS_PLATFORM_MANIFEST_NOT_SIGNED,
+ MD_NTSTATUS_WIN_STATUS_APPEXEC_CONDITION_NOT_SATISFIED,
+ MD_NTSTATUS_WIN_STATUS_APPEXEC_HANDLE_INVALIDATED,
+ MD_NTSTATUS_WIN_STATUS_APPEXEC_INVALID_HOST_GENERATION,
+ MD_NTSTATUS_WIN_STATUS_APPEXEC_UNEXPECTED_PROCESS_REGISTRATION,
+ MD_NTSTATUS_WIN_STATUS_APPEXEC_INVALID_HOST_STATE,
+ MD_NTSTATUS_WIN_STATUS_APPEXEC_NO_DONOR,
+ MD_NTSTATUS_WIN_STATUS_APPEXEC_HOST_ID_MISMATCH,
+ MD_NTSTATUS_WIN_STATUS_APPEXEC_UNKNOWN_USER,
+};
+
+// The content of this array was created from ntstatus.h in the 10 SDK
+// (version 10.0.19041.0) with
+//
+// egrep '#define [A-Z_0-9]+\s+\(\(NTSTATUS\)0x[048C][0-9A-F]+L\)' ntstatus.h
+// | tr -d '\r'
+// | sed -r 's@#define ([A-Z_0-9]+)\s+\(\(NTSTATUS\)(0x[048C][0-9A-F]+)L\).*@\2 \1@'
+// | sort
+// | sed -r 's@(0x[048C][0-9A-F]+) ([A-Z_0-9]+)@ "\2",@'
+//
+// With easy copy to clipboard with
+// | xclip -selection c # on linux
+// | clip # on windows
+// | pbcopy # on mac
+static const char* kNTStatusStrings[] = {
+ "STATUS_SUCCESS",
+ "STATUS_WAIT_0",
+ "STATUS_WAIT_1",
+ "STATUS_WAIT_2",
+ "STATUS_WAIT_3",
+ "STATUS_WAIT_63",
+ "STATUS_ABANDONED",
+ "STATUS_ABANDONED_WAIT_0",
+ "STATUS_ABANDONED_WAIT_63",
+ "STATUS_USER_APC",
+ "STATUS_ALREADY_COMPLETE",
+ "STATUS_KERNEL_APC",
+ "STATUS_ALERTED",
+ "STATUS_TIMEOUT",
+ "STATUS_PENDING",
+ "STATUS_REPARSE",
+ "STATUS_MORE_ENTRIES",
+ "STATUS_NOT_ALL_ASSIGNED",
+ "STATUS_SOME_NOT_MAPPED",
+ "STATUS_OPLOCK_BREAK_IN_PROGRESS",
+ "STATUS_VOLUME_MOUNTED",
+ "STATUS_RXACT_COMMITTED",
+ "STATUS_NOTIFY_CLEANUP",
+ "STATUS_NOTIFY_ENUM_DIR",
+ "STATUS_NO_QUOTAS_FOR_ACCOUNT",
+ "STATUS_PRIMARY_TRANSPORT_CONNECT_FAILED",
+ "STATUS_PAGE_FAULT_TRANSITION",
+ "STATUS_PAGE_FAULT_DEMAND_ZERO",
+ "STATUS_PAGE_FAULT_COPY_ON_WRITE",
+ "STATUS_PAGE_FAULT_GUARD_PAGE",
+ "STATUS_PAGE_FAULT_PAGING_FILE",
+ "STATUS_CACHE_PAGE_LOCKED",
+ "STATUS_CRASH_DUMP",
+ "STATUS_BUFFER_ALL_ZEROS",
+ "STATUS_REPARSE_OBJECT",
+ "STATUS_RESOURCE_REQUIREMENTS_CHANGED",
+ "STATUS_TRANSLATION_COMPLETE",
+ "STATUS_DS_MEMBERSHIP_EVALUATED_LOCALLY",
+ "STATUS_NOTHING_TO_TERMINATE",
+ "STATUS_PROCESS_NOT_IN_JOB",
+ "STATUS_PROCESS_IN_JOB",
+ "STATUS_VOLSNAP_HIBERNATE_READY",
+ "STATUS_FSFILTER_OP_COMPLETED_SUCCESSFULLY",
+ "STATUS_INTERRUPT_VECTOR_ALREADY_CONNECTED",
+ "STATUS_INTERRUPT_STILL_CONNECTED",
+ "STATUS_PROCESS_CLONED",
+ "STATUS_FILE_LOCKED_WITH_ONLY_READERS",
+ "STATUS_FILE_LOCKED_WITH_WRITERS",
+ "STATUS_VALID_IMAGE_HASH",
+ "STATUS_VALID_CATALOG_HASH",
+ "STATUS_VALID_STRONG_CODE_HASH",
+ "STATUS_GHOSTED",
+ "STATUS_DATA_OVERWRITTEN",
+ "STATUS_RESOURCEMANAGER_READ_ONLY",
+ "STATUS_RING_PREVIOUSLY_EMPTY",
+ "STATUS_RING_PREVIOUSLY_FULL",
+ "STATUS_RING_PREVIOUSLY_ABOVE_QUOTA",
+ "STATUS_RING_NEWLY_EMPTY",
+ "STATUS_RING_SIGNAL_OPPOSITE_ENDPOINT",
+ "STATUS_OPLOCK_SWITCHED_TO_NEW_HANDLE",
+ "STATUS_OPLOCK_HANDLE_CLOSED",
+ "STATUS_WAIT_FOR_OPLOCK",
+ "STATUS_REPARSE_GLOBAL",
+ "DBG_EXCEPTION_HANDLED",
+ "DBG_CONTINUE",
+ "STATUS_FLT_IO_COMPLETE",
+ "STATUS_RTPM_CONTEXT_CONTINUE",
+ "STATUS_RTPM_CONTEXT_COMPLETE",
+ "STATUS_HV_PENDING_PAGE_REQUESTS",
+ "STATUS_SPACES_REPAIRED",
+ "STATUS_SPACES_PAUSE",
+ "STATUS_SPACES_COMPLETE",
+ "STATUS_SPACES_REDIRECT",
+ "STATUS_OBJECT_NAME_EXISTS",
+ "STATUS_THREAD_WAS_SUSPENDED",
+ "STATUS_WORKING_SET_LIMIT_RANGE",
+ "STATUS_IMAGE_NOT_AT_BASE",
+ "STATUS_RXACT_STATE_CREATED",
+ "STATUS_SEGMENT_NOTIFICATION",
+ "STATUS_LOCAL_USER_SESSION_KEY",
+ "STATUS_BAD_CURRENT_DIRECTORY",
+ "STATUS_SERIAL_MORE_WRITES",
+ "STATUS_REGISTRY_RECOVERED",
+ "STATUS_FT_READ_RECOVERY_FROM_BACKUP",
+ "STATUS_FT_WRITE_RECOVERY",
+ "STATUS_SERIAL_COUNTER_TIMEOUT",
+ "STATUS_NULL_LM_PASSWORD",
+ "STATUS_IMAGE_MACHINE_TYPE_MISMATCH",
+ "STATUS_RECEIVE_PARTIAL",
+ "STATUS_RECEIVE_EXPEDITED",
+ "STATUS_RECEIVE_PARTIAL_EXPEDITED",
+ "STATUS_EVENT_DONE",
+ "STATUS_EVENT_PENDING",
+ "STATUS_CHECKING_FILE_SYSTEM",
+ "STATUS_FATAL_APP_EXIT",
+ "STATUS_PREDEFINED_HANDLE",
+ "STATUS_WAS_UNLOCKED",
+ "STATUS_SERVICE_NOTIFICATION",
+ "STATUS_WAS_LOCKED",
+ "STATUS_LOG_HARD_ERROR",
+ "STATUS_ALREADY_WIN32",
+ "STATUS_WX86_UNSIMULATE",
+ "STATUS_WX86_CONTINUE",
+ "STATUS_WX86_SINGLE_STEP",
+ "STATUS_WX86_BREAKPOINT",
+ "STATUS_WX86_EXCEPTION_CONTINUE",
+ "STATUS_WX86_EXCEPTION_LASTCHANCE",
+ "STATUS_WX86_EXCEPTION_CHAIN",
+ "STATUS_IMAGE_MACHINE_TYPE_MISMATCH_EXE",
+ "STATUS_NO_YIELD_PERFORMED",
+ "STATUS_TIMER_RESUME_IGNORED",
+ "STATUS_ARBITRATION_UNHANDLED",
+ "STATUS_CARDBUS_NOT_SUPPORTED",
+ "STATUS_WX86_CREATEWX86TIB",
+ "STATUS_MP_PROCESSOR_MISMATCH",
+ "STATUS_HIBERNATED",
+ "STATUS_RESUME_HIBERNATION",
+ "STATUS_FIRMWARE_UPDATED",
+ "STATUS_DRIVERS_LEAKING_LOCKED_PAGES",
+ "STATUS_MESSAGE_RETRIEVED",
+ "STATUS_SYSTEM_POWERSTATE_TRANSITION",
+ "STATUS_ALPC_CHECK_COMPLETION_LIST",
+ "STATUS_SYSTEM_POWERSTATE_COMPLEX_TRANSITION",
+ "STATUS_ACCESS_AUDIT_BY_POLICY",
+ "STATUS_ABANDON_HIBERFILE",
+ "STATUS_BIZRULES_NOT_ENABLED",
+ "STATUS_FT_READ_FROM_COPY",
+ "STATUS_IMAGE_AT_DIFFERENT_BASE",
+ "STATUS_PATCH_DEFERRED",
+ "STATUS_WAKE_SYSTEM",
+ "STATUS_DS_SHUTTING_DOWN",
+ "STATUS_DISK_REPAIR_REDIRECTED",
+ "STATUS_SERVICES_FAILED_AUTOSTART",
+ "DBG_REPLY_LATER",
+ "DBG_UNABLE_TO_PROVIDE_HANDLE",
+ "DBG_TERMINATE_THREAD",
+ "DBG_TERMINATE_PROCESS",
+ "DBG_CONTROL_C",
+ "DBG_PRINTEXCEPTION_C",
+ "DBG_RIPEXCEPTION",
+ "DBG_CONTROL_BREAK",
+ "DBG_COMMAND_EXCEPTION",
+ "DBG_PRINTEXCEPTION_WIDE_C",
+ "RPC_NT_UUID_LOCAL_ONLY",
+ "RPC_NT_SEND_INCOMPLETE",
+ "STATUS_CTX_CDM_CONNECT",
+ "STATUS_CTX_CDM_DISCONNECT",
+ "STATUS_SXS_RELEASE_ACTIVATION_CONTEXT",
+ "STATUS_HEURISTIC_DAMAGE_POSSIBLE",
+ "STATUS_RECOVERY_NOT_NEEDED",
+ "STATUS_RM_ALREADY_STARTED",
+ "STATUS_LOG_NO_RESTART",
+ "STATUS_VIDEO_DRIVER_DEBUG_REPORT_REQUEST",
+ "STATUS_GRAPHICS_PARTIAL_DATA_POPULATED",
+ "STATUS_GRAPHICS_SKIP_ALLOCATION_PREPARATION",
+ "STATUS_GRAPHICS_MODE_NOT_PINNED",
+ "STATUS_GRAPHICS_NO_PREFERRED_MODE",
+ "STATUS_GRAPHICS_DATASET_IS_EMPTY",
+ "STATUS_GRAPHICS_NO_MORE_ELEMENTS_IN_DATASET",
+ "STATUS_GRAPHICS_PATH_CONTENT_GEOMETRY_TRANSFORMATION_NOT_PINNED",
+ "STATUS_GRAPHICS_UNKNOWN_CHILD_STATUS",
+ "STATUS_GRAPHICS_LEADLINK_START_DEFERRED",
+ "STATUS_GRAPHICS_POLLING_TOO_FREQUENTLY",
+ "STATUS_GRAPHICS_START_DEFERRED",
+ "STATUS_GRAPHICS_DEPENDABLE_CHILD_STATUS",
+ "STATUS_NDIS_INDICATION_REQUIRED",
+ "STATUS_PCP_UNSUPPORTED_PSS_SALT",
+ "STATUS_GUARD_PAGE_VIOLATION",
+ "STATUS_DATATYPE_MISALIGNMENT",
+ "STATUS_BREAKPOINT",
+ "STATUS_SINGLE_STEP",
+ "STATUS_BUFFER_OVERFLOW",
+ "STATUS_NO_MORE_FILES",
+ "STATUS_WAKE_SYSTEM_DEBUGGER",
+ "STATUS_HANDLES_CLOSED",
+ "STATUS_NO_INHERITANCE",
+ "STATUS_GUID_SUBSTITUTION_MADE",
+ "STATUS_PARTIAL_COPY",
+ "STATUS_DEVICE_PAPER_EMPTY",
+ "STATUS_DEVICE_POWERED_OFF",
+ "STATUS_DEVICE_OFF_LINE",
+ "STATUS_DEVICE_BUSY",
+ "STATUS_NO_MORE_EAS",
+ "STATUS_INVALID_EA_NAME",
+ "STATUS_EA_LIST_INCONSISTENT",
+ "STATUS_INVALID_EA_FLAG",
+ "STATUS_VERIFY_REQUIRED",
+ "STATUS_EXTRANEOUS_INFORMATION",
+ "STATUS_RXACT_COMMIT_NECESSARY",
+ "STATUS_NO_MORE_ENTRIES",
+ "STATUS_FILEMARK_DETECTED",
+ "STATUS_MEDIA_CHANGED",
+ "STATUS_BUS_RESET",
+ "STATUS_END_OF_MEDIA",
+ "STATUS_BEGINNING_OF_MEDIA",
+ "STATUS_MEDIA_CHECK",
+ "STATUS_SETMARK_DETECTED",
+ "STATUS_NO_DATA_DETECTED",
+ "STATUS_REDIRECTOR_HAS_OPEN_HANDLES",
+ "STATUS_SERVER_HAS_OPEN_HANDLES",
+ "STATUS_ALREADY_DISCONNECTED",
+ "STATUS_LONGJUMP",
+ "STATUS_CLEANER_CARTRIDGE_INSTALLED",
+ "STATUS_PLUGPLAY_QUERY_VETOED",
+ "STATUS_UNWIND_CONSOLIDATE",
+ "STATUS_REGISTRY_HIVE_RECOVERED",
+ "STATUS_DLL_MIGHT_BE_INSECURE",
+ "STATUS_DLL_MIGHT_BE_INCOMPATIBLE",
+ "STATUS_STOPPED_ON_SYMLINK",
+ "STATUS_CANNOT_GRANT_REQUESTED_OPLOCK",
+ "STATUS_NO_ACE_CONDITION",
+ "STATUS_DEVICE_SUPPORT_IN_PROGRESS",
+ "STATUS_DEVICE_POWER_CYCLE_REQUIRED",
+ "STATUS_NO_WORK_DONE",
+ "STATUS_RETURN_ADDRESS_HIJACK_ATTEMPT",
+ "STATUS_DEVICE_REQUIRES_CLEANING",
+ "STATUS_DEVICE_DOOR_OPEN",
+ "STATUS_DATA_LOST_REPAIR",
+ "STATUS_GPIO_INTERRUPT_ALREADY_UNMASKED",
+ "STATUS_CLOUD_FILE_PROPERTY_BLOB_CHECKSUM_MISMATCH",
+ "STATUS_CLOUD_FILE_PROPERTY_BLOB_TOO_LARGE",
+ "STATUS_CLOUD_FILE_TOO_MANY_PROPERTY_BLOBS",
+ "DBG_EXCEPTION_NOT_HANDLED",
+ "STATUS_CLUSTER_NODE_ALREADY_UP",
+ "STATUS_CLUSTER_NODE_ALREADY_DOWN",
+ "STATUS_CLUSTER_NETWORK_ALREADY_ONLINE",
+ "STATUS_CLUSTER_NETWORK_ALREADY_OFFLINE",
+ "STATUS_CLUSTER_NODE_ALREADY_MEMBER",
+ "STATUS_COULD_NOT_RESIZE_LOG",
+ "STATUS_NO_TXF_METADATA",
+ "STATUS_CANT_RECOVER_WITH_HANDLE_OPEN",
+ "STATUS_TXF_METADATA_ALREADY_PRESENT",
+ "STATUS_TRANSACTION_SCOPE_CALLBACKS_NOT_SET",
+ "STATUS_VIDEO_HUNG_DISPLAY_DRIVER_THREAD_RECOVERED",
+ "STATUS_FLT_BUFFER_TOO_SMALL",
+ "STATUS_FVE_PARTIAL_METADATA",
+ "STATUS_FVE_TRANSIENT_STATE",
+ "STATUS_VID_REMOTE_NODE_PARENT_GPA_PAGES_USED",
+ "STATUS_VOLMGR_INCOMPLETE_REGENERATION",
+ "STATUS_VOLMGR_INCOMPLETE_DISK_MIGRATION",
+ "STATUS_BCD_NOT_ALL_ENTRIES_IMPORTED",
+ "STATUS_BCD_NOT_ALL_ENTRIES_SYNCHRONIZED",
+ "STATUS_QUERY_STORAGE_ERROR",
+ "STATUS_GDI_HANDLE_LEAK",
+ "STATUS_SECUREBOOT_NOT_ENABLED",
+ "STATUS_UNSUCCESSFUL",
+ "STATUS_NOT_IMPLEMENTED",
+ "STATUS_INVALID_INFO_CLASS",
+ "STATUS_INFO_LENGTH_MISMATCH",
+ "STATUS_ACCESS_VIOLATION",
+ "STATUS_IN_PAGE_ERROR",
+ "STATUS_PAGEFILE_QUOTA",
+ "STATUS_INVALID_HANDLE",
+ "STATUS_BAD_INITIAL_STACK",
+ "STATUS_BAD_INITIAL_PC",
+ "STATUS_INVALID_CID",
+ "STATUS_TIMER_NOT_CANCELED",
+ "STATUS_INVALID_PARAMETER",
+ "STATUS_NO_SUCH_DEVICE",
+ "STATUS_NO_SUCH_FILE",
+ "STATUS_INVALID_DEVICE_REQUEST",
+ "STATUS_END_OF_FILE",
+ "STATUS_WRONG_VOLUME",
+ "STATUS_NO_MEDIA_IN_DEVICE",
+ "STATUS_UNRECOGNIZED_MEDIA",
+ "STATUS_NONEXISTENT_SECTOR",
+ "STATUS_MORE_PROCESSING_REQUIRED",
+ "STATUS_NO_MEMORY",
+ "STATUS_CONFLICTING_ADDRESSES",
+ "STATUS_NOT_MAPPED_VIEW",
+ "STATUS_UNABLE_TO_FREE_VM",
+ "STATUS_UNABLE_TO_DELETE_SECTION",
+ "STATUS_INVALID_SYSTEM_SERVICE",
+ "STATUS_ILLEGAL_INSTRUCTION",
+ "STATUS_INVALID_LOCK_SEQUENCE",
+ "STATUS_INVALID_VIEW_SIZE",
+ "STATUS_INVALID_FILE_FOR_SECTION",
+ "STATUS_ALREADY_COMMITTED",
+ "STATUS_ACCESS_DENIED",
+ "STATUS_BUFFER_TOO_SMALL",
+ "STATUS_OBJECT_TYPE_MISMATCH",
+ "STATUS_NONCONTINUABLE_EXCEPTION",
+ "STATUS_INVALID_DISPOSITION",
+ "STATUS_UNWIND",
+ "STATUS_BAD_STACK",
+ "STATUS_INVALID_UNWIND_TARGET",
+ "STATUS_NOT_LOCKED",
+ "STATUS_PARITY_ERROR",
+ "STATUS_UNABLE_TO_DECOMMIT_VM",
+ "STATUS_NOT_COMMITTED",
+ "STATUS_INVALID_PORT_ATTRIBUTES",
+ "STATUS_PORT_MESSAGE_TOO_LONG",
+ "STATUS_INVALID_PARAMETER_MIX",
+ "STATUS_INVALID_QUOTA_LOWER",
+ "STATUS_DISK_CORRUPT_ERROR",
+ "STATUS_OBJECT_NAME_INVALID",
+ "STATUS_OBJECT_NAME_NOT_FOUND",
+ "STATUS_OBJECT_NAME_COLLISION",
+ "STATUS_PORT_DO_NOT_DISTURB",
+ "STATUS_PORT_DISCONNECTED",
+ "STATUS_DEVICE_ALREADY_ATTACHED",
+ "STATUS_OBJECT_PATH_INVALID",
+ "STATUS_OBJECT_PATH_NOT_FOUND",
+ "STATUS_OBJECT_PATH_SYNTAX_BAD",
+ "STATUS_DATA_OVERRUN",
+ "STATUS_DATA_LATE_ERROR",
+ "STATUS_DATA_ERROR",
+ "STATUS_CRC_ERROR",
+ "STATUS_SECTION_TOO_BIG",
+ "STATUS_PORT_CONNECTION_REFUSED",
+ "STATUS_INVALID_PORT_HANDLE",
+ "STATUS_SHARING_VIOLATION",
+ "STATUS_QUOTA_EXCEEDED",
+ "STATUS_INVALID_PAGE_PROTECTION",
+ "STATUS_MUTANT_NOT_OWNED",
+ "STATUS_SEMAPHORE_LIMIT_EXCEEDED",
+ "STATUS_PORT_ALREADY_SET",
+ "STATUS_SECTION_NOT_IMAGE",
+ "STATUS_SUSPEND_COUNT_EXCEEDED",
+ "STATUS_THREAD_IS_TERMINATING",
+ "STATUS_BAD_WORKING_SET_LIMIT",
+ "STATUS_INCOMPATIBLE_FILE_MAP",
+ "STATUS_SECTION_PROTECTION",
+ "STATUS_EAS_NOT_SUPPORTED",
+ "STATUS_EA_TOO_LARGE",
+ "STATUS_NONEXISTENT_EA_ENTRY",
+ "STATUS_NO_EAS_ON_FILE",
+ "STATUS_EA_CORRUPT_ERROR",
+ "STATUS_FILE_LOCK_CONFLICT",
+ "STATUS_LOCK_NOT_GRANTED",
+ "STATUS_DELETE_PENDING",
+ "STATUS_CTL_FILE_NOT_SUPPORTED",
+ "STATUS_UNKNOWN_REVISION",
+ "STATUS_REVISION_MISMATCH",
+ "STATUS_INVALID_OWNER",
+ "STATUS_INVALID_PRIMARY_GROUP",
+ "STATUS_NO_IMPERSONATION_TOKEN",
+ "STATUS_CANT_DISABLE_MANDATORY",
+ "STATUS_NO_LOGON_SERVERS",
+ "STATUS_NO_SUCH_LOGON_SESSION",
+ "STATUS_NO_SUCH_PRIVILEGE",
+ "STATUS_PRIVILEGE_NOT_HELD",
+ "STATUS_INVALID_ACCOUNT_NAME",
+ "STATUS_USER_EXISTS",
+ "STATUS_NO_SUCH_USER",
+ "STATUS_GROUP_EXISTS",
+ "STATUS_NO_SUCH_GROUP",
+ "STATUS_MEMBER_IN_GROUP",
+ "STATUS_MEMBER_NOT_IN_GROUP",
+ "STATUS_LAST_ADMIN",
+ "STATUS_WRONG_PASSWORD",
+ "STATUS_ILL_FORMED_PASSWORD",
+ "STATUS_PASSWORD_RESTRICTION",
+ "STATUS_LOGON_FAILURE",
+ "STATUS_ACCOUNT_RESTRICTION",
+ "STATUS_INVALID_LOGON_HOURS",
+ "STATUS_INVALID_WORKSTATION",
+ "STATUS_PASSWORD_EXPIRED",
+ "STATUS_ACCOUNT_DISABLED",
+ "STATUS_NONE_MAPPED",
+ "STATUS_TOO_MANY_LUIDS_REQUESTED",
+ "STATUS_LUIDS_EXHAUSTED",
+ "STATUS_INVALID_SUB_AUTHORITY",
+ "STATUS_INVALID_ACL",
+ "STATUS_INVALID_SID",
+ "STATUS_INVALID_SECURITY_DESCR",
+ "STATUS_PROCEDURE_NOT_FOUND",
+ "STATUS_INVALID_IMAGE_FORMAT",
+ "STATUS_NO_TOKEN",
+ "STATUS_BAD_INHERITANCE_ACL",
+ "STATUS_RANGE_NOT_LOCKED",
+ "STATUS_DISK_FULL",
+ "STATUS_SERVER_DISABLED",
+ "STATUS_SERVER_NOT_DISABLED",
+ "STATUS_TOO_MANY_GUIDS_REQUESTED",
+ "STATUS_GUIDS_EXHAUSTED",
+ "STATUS_INVALID_ID_AUTHORITY",
+ "STATUS_AGENTS_EXHAUSTED",
+ "STATUS_INVALID_VOLUME_LABEL",
+ "STATUS_SECTION_NOT_EXTENDED",
+ "STATUS_NOT_MAPPED_DATA",
+ "STATUS_RESOURCE_DATA_NOT_FOUND",
+ "STATUS_RESOURCE_TYPE_NOT_FOUND",
+ "STATUS_RESOURCE_NAME_NOT_FOUND",
+ "STATUS_ARRAY_BOUNDS_EXCEEDED",
+ "STATUS_FLOAT_DENORMAL_OPERAND",
+ "STATUS_FLOAT_DIVIDE_BY_ZERO",
+ "STATUS_FLOAT_INEXACT_RESULT",
+ "STATUS_FLOAT_INVALID_OPERATION",
+ "STATUS_FLOAT_OVERFLOW",
+ "STATUS_FLOAT_STACK_CHECK",
+ "STATUS_FLOAT_UNDERFLOW",
+ "STATUS_INTEGER_DIVIDE_BY_ZERO",
+ "STATUS_INTEGER_OVERFLOW",
+ "STATUS_PRIVILEGED_INSTRUCTION",
+ "STATUS_TOO_MANY_PAGING_FILES",
+ "STATUS_FILE_INVALID",
+ "STATUS_ALLOTTED_SPACE_EXCEEDED",
+ "STATUS_INSUFFICIENT_RESOURCES",
+ "STATUS_DFS_EXIT_PATH_FOUND",
+ "STATUS_DEVICE_DATA_ERROR",
+ "STATUS_DEVICE_NOT_CONNECTED",
+ "STATUS_DEVICE_POWER_FAILURE",
+ "STATUS_FREE_VM_NOT_AT_BASE",
+ "STATUS_MEMORY_NOT_ALLOCATED",
+ "STATUS_WORKING_SET_QUOTA",
+ "STATUS_MEDIA_WRITE_PROTECTED",
+ "STATUS_DEVICE_NOT_READY",
+ "STATUS_INVALID_GROUP_ATTRIBUTES",
+ "STATUS_BAD_IMPERSONATION_LEVEL",
+ "STATUS_CANT_OPEN_ANONYMOUS",
+ "STATUS_BAD_VALIDATION_CLASS",
+ "STATUS_BAD_TOKEN_TYPE",
+ "STATUS_BAD_MASTER_BOOT_RECORD",
+ "STATUS_INSTRUCTION_MISALIGNMENT",
+ "STATUS_INSTANCE_NOT_AVAILABLE",
+ "STATUS_PIPE_NOT_AVAILABLE",
+ "STATUS_INVALID_PIPE_STATE",
+ "STATUS_PIPE_BUSY",
+ "STATUS_ILLEGAL_FUNCTION",
+ "STATUS_PIPE_DISCONNECTED",
+ "STATUS_PIPE_CLOSING",
+ "STATUS_PIPE_CONNECTED",
+ "STATUS_PIPE_LISTENING",
+ "STATUS_INVALID_READ_MODE",
+ "STATUS_IO_TIMEOUT",
+ "STATUS_FILE_FORCED_CLOSED",
+ "STATUS_PROFILING_NOT_STARTED",
+ "STATUS_PROFILING_NOT_STOPPED",
+ "STATUS_COULD_NOT_INTERPRET",
+ "STATUS_FILE_IS_A_DIRECTORY",
+ "STATUS_NOT_SUPPORTED",
+ "STATUS_REMOTE_NOT_LISTENING",
+ "STATUS_DUPLICATE_NAME",
+ "STATUS_BAD_NETWORK_PATH",
+ "STATUS_NETWORK_BUSY",
+ "STATUS_DEVICE_DOES_NOT_EXIST",
+ "STATUS_TOO_MANY_COMMANDS",
+ "STATUS_ADAPTER_HARDWARE_ERROR",
+ "STATUS_INVALID_NETWORK_RESPONSE",
+ "STATUS_UNEXPECTED_NETWORK_ERROR",
+ "STATUS_BAD_REMOTE_ADAPTER",
+ "STATUS_PRINT_QUEUE_FULL",
+ "STATUS_NO_SPOOL_SPACE",
+ "STATUS_PRINT_CANCELLED",
+ "STATUS_NETWORK_NAME_DELETED",
+ "STATUS_NETWORK_ACCESS_DENIED",
+ "STATUS_BAD_DEVICE_TYPE",
+ "STATUS_BAD_NETWORK_NAME",
+ "STATUS_TOO_MANY_NAMES",
+ "STATUS_TOO_MANY_SESSIONS",
+ "STATUS_SHARING_PAUSED",
+ "STATUS_REQUEST_NOT_ACCEPTED",
+ "STATUS_REDIRECTOR_PAUSED",
+ "STATUS_NET_WRITE_FAULT",
+ "STATUS_PROFILING_AT_LIMIT",
+ "STATUS_NOT_SAME_DEVICE",
+ "STATUS_FILE_RENAMED",
+ "STATUS_VIRTUAL_CIRCUIT_CLOSED",
+ "STATUS_NO_SECURITY_ON_OBJECT",
+ "STATUS_CANT_WAIT",
+ "STATUS_PIPE_EMPTY",
+ "STATUS_CANT_ACCESS_DOMAIN_INFO",
+ "STATUS_CANT_TERMINATE_SELF",
+ "STATUS_INVALID_SERVER_STATE",
+ "STATUS_INVALID_DOMAIN_STATE",
+ "STATUS_INVALID_DOMAIN_ROLE",
+ "STATUS_NO_SUCH_DOMAIN",
+ "STATUS_DOMAIN_EXISTS",
+ "STATUS_DOMAIN_LIMIT_EXCEEDED",
+ "STATUS_OPLOCK_NOT_GRANTED",
+ "STATUS_INVALID_OPLOCK_PROTOCOL",
+ "STATUS_INTERNAL_DB_CORRUPTION",
+ "STATUS_INTERNAL_ERROR",
+ "STATUS_GENERIC_NOT_MAPPED",
+ "STATUS_BAD_DESCRIPTOR_FORMAT",
+ "STATUS_INVALID_USER_BUFFER",
+ "STATUS_UNEXPECTED_IO_ERROR",
+ "STATUS_UNEXPECTED_MM_CREATE_ERR",
+ "STATUS_UNEXPECTED_MM_MAP_ERROR",
+ "STATUS_UNEXPECTED_MM_EXTEND_ERR",
+ "STATUS_NOT_LOGON_PROCESS",
+ "STATUS_LOGON_SESSION_EXISTS",
+ "STATUS_INVALID_PARAMETER_1",
+ "STATUS_INVALID_PARAMETER_2",
+ "STATUS_INVALID_PARAMETER_3",
+ "STATUS_INVALID_PARAMETER_4",
+ "STATUS_INVALID_PARAMETER_5",
+ "STATUS_INVALID_PARAMETER_6",
+ "STATUS_INVALID_PARAMETER_7",
+ "STATUS_INVALID_PARAMETER_8",
+ "STATUS_INVALID_PARAMETER_9",
+ "STATUS_INVALID_PARAMETER_10",
+ "STATUS_INVALID_PARAMETER_11",
+ "STATUS_INVALID_PARAMETER_12",
+ "STATUS_REDIRECTOR_NOT_STARTED",
+ "STATUS_REDIRECTOR_STARTED",
+ "STATUS_STACK_OVERFLOW",
+ "STATUS_NO_SUCH_PACKAGE",
+ "STATUS_BAD_FUNCTION_TABLE",
+ "STATUS_VARIABLE_NOT_FOUND",
+ "STATUS_DIRECTORY_NOT_EMPTY",
+ "STATUS_FILE_CORRUPT_ERROR",
+ "STATUS_NOT_A_DIRECTORY",
+ "STATUS_BAD_LOGON_SESSION_STATE",
+ "STATUS_LOGON_SESSION_COLLISION",
+ "STATUS_NAME_TOO_LONG",
+ "STATUS_FILES_OPEN",
+ "STATUS_CONNECTION_IN_USE",
+ "STATUS_MESSAGE_NOT_FOUND",
+ "STATUS_PROCESS_IS_TERMINATING",
+ "STATUS_INVALID_LOGON_TYPE",
+ "STATUS_NO_GUID_TRANSLATION",
+ "STATUS_CANNOT_IMPERSONATE",
+ "STATUS_IMAGE_ALREADY_LOADED",
+ "STATUS_ABIOS_NOT_PRESENT",
+ "STATUS_ABIOS_LID_NOT_EXIST",
+ "STATUS_ABIOS_LID_ALREADY_OWNED",
+ "STATUS_ABIOS_NOT_LID_OWNER",
+ "STATUS_ABIOS_INVALID_COMMAND",
+ "STATUS_ABIOS_INVALID_LID",
+ "STATUS_ABIOS_SELECTOR_NOT_AVAILABLE",
+ "STATUS_ABIOS_INVALID_SELECTOR",
+ "STATUS_NO_LDT",
+ "STATUS_INVALID_LDT_SIZE",
+ "STATUS_INVALID_LDT_OFFSET",
+ "STATUS_INVALID_LDT_DESCRIPTOR",
+ "STATUS_INVALID_IMAGE_NE_FORMAT",
+ "STATUS_RXACT_INVALID_STATE",
+ "STATUS_RXACT_COMMIT_FAILURE",
+ "STATUS_MAPPED_FILE_SIZE_ZERO",
+ "STATUS_TOO_MANY_OPENED_FILES",
+ "STATUS_CANCELLED",
+ "STATUS_CANNOT_DELETE",
+ "STATUS_INVALID_COMPUTER_NAME",
+ "STATUS_FILE_DELETED",
+ "STATUS_SPECIAL_ACCOUNT",
+ "STATUS_SPECIAL_GROUP",
+ "STATUS_SPECIAL_USER",
+ "STATUS_MEMBERS_PRIMARY_GROUP",
+ "STATUS_FILE_CLOSED",
+ "STATUS_TOO_MANY_THREADS",
+ "STATUS_THREAD_NOT_IN_PROCESS",
+ "STATUS_TOKEN_ALREADY_IN_USE",
+ "STATUS_PAGEFILE_QUOTA_EXCEEDED",
+ "STATUS_COMMITMENT_LIMIT",
+ "STATUS_INVALID_IMAGE_LE_FORMAT",
+ "STATUS_INVALID_IMAGE_NOT_MZ",
+ "STATUS_INVALID_IMAGE_PROTECT",
+ "STATUS_INVALID_IMAGE_WIN_16",
+ "STATUS_LOGON_SERVER_CONFLICT",
+ "STATUS_TIME_DIFFERENCE_AT_DC",
+ "STATUS_SYNCHRONIZATION_REQUIRED",
+ "STATUS_DLL_NOT_FOUND",
+ "STATUS_OPEN_FAILED",
+ "STATUS_IO_PRIVILEGE_FAILED",
+ "STATUS_ORDINAL_NOT_FOUND",
+ "STATUS_ENTRYPOINT_NOT_FOUND",
+ "STATUS_CONTROL_C_EXIT",
+ "STATUS_LOCAL_DISCONNECT",
+ "STATUS_REMOTE_DISCONNECT",
+ "STATUS_REMOTE_RESOURCES",
+ "STATUS_LINK_FAILED",
+ "STATUS_LINK_TIMEOUT",
+ "STATUS_INVALID_CONNECTION",
+ "STATUS_INVALID_ADDRESS",
+ "STATUS_DLL_INIT_FAILED",
+ "STATUS_MISSING_SYSTEMFILE",
+ "STATUS_UNHANDLED_EXCEPTION",
+ "STATUS_APP_INIT_FAILURE",
+ "STATUS_PAGEFILE_CREATE_FAILED",
+ "STATUS_NO_PAGEFILE",
+ "STATUS_INVALID_LEVEL",
+ "STATUS_WRONG_PASSWORD_CORE",
+ "STATUS_ILLEGAL_FLOAT_CONTEXT",
+ "STATUS_PIPE_BROKEN",
+ "STATUS_REGISTRY_CORRUPT",
+ "STATUS_REGISTRY_IO_FAILED",
+ "STATUS_NO_EVENT_PAIR",
+ "STATUS_UNRECOGNIZED_VOLUME",
+ "STATUS_SERIAL_NO_DEVICE_INITED",
+ "STATUS_NO_SUCH_ALIAS",
+ "STATUS_MEMBER_NOT_IN_ALIAS",
+ "STATUS_MEMBER_IN_ALIAS",
+ "STATUS_ALIAS_EXISTS",
+ "STATUS_LOGON_NOT_GRANTED",
+ "STATUS_TOO_MANY_SECRETS",
+ "STATUS_SECRET_TOO_LONG",
+ "STATUS_INTERNAL_DB_ERROR",
+ "STATUS_FULLSCREEN_MODE",
+ "STATUS_TOO_MANY_CONTEXT_IDS",
+ "STATUS_LOGON_TYPE_NOT_GRANTED",
+ "STATUS_NOT_REGISTRY_FILE",
+ "STATUS_NT_CROSS_ENCRYPTION_REQUIRED",
+ "STATUS_DOMAIN_CTRLR_CONFIG_ERROR",
+ "STATUS_FT_MISSING_MEMBER",
+ "STATUS_ILL_FORMED_SERVICE_ENTRY",
+ "STATUS_ILLEGAL_CHARACTER",
+ "STATUS_UNMAPPABLE_CHARACTER",
+ "STATUS_UNDEFINED_CHARACTER",
+ "STATUS_FLOPPY_VOLUME",
+ "STATUS_FLOPPY_ID_MARK_NOT_FOUND",
+ "STATUS_FLOPPY_WRONG_CYLINDER",
+ "STATUS_FLOPPY_UNKNOWN_ERROR",
+ "STATUS_FLOPPY_BAD_REGISTERS",
+ "STATUS_DISK_RECALIBRATE_FAILED",
+ "STATUS_DISK_OPERATION_FAILED",
+ "STATUS_DISK_RESET_FAILED",
+ "STATUS_SHARED_IRQ_BUSY",
+ "STATUS_FT_ORPHANING",
+ "STATUS_BIOS_FAILED_TO_CONNECT_INTERRUPT",
+ "STATUS_PARTITION_FAILURE",
+ "STATUS_INVALID_BLOCK_LENGTH",
+ "STATUS_DEVICE_NOT_PARTITIONED",
+ "STATUS_UNABLE_TO_LOCK_MEDIA",
+ "STATUS_UNABLE_TO_UNLOAD_MEDIA",
+ "STATUS_EOM_OVERFLOW",
+ "STATUS_NO_MEDIA",
+ "STATUS_NO_SUCH_MEMBER",
+ "STATUS_INVALID_MEMBER",
+ "STATUS_KEY_DELETED",
+ "STATUS_NO_LOG_SPACE",
+ "STATUS_TOO_MANY_SIDS",
+ "STATUS_LM_CROSS_ENCRYPTION_REQUIRED",
+ "STATUS_KEY_HAS_CHILDREN",
+ "STATUS_CHILD_MUST_BE_VOLATILE",
+ "STATUS_DEVICE_CONFIGURATION_ERROR",
+ "STATUS_DRIVER_INTERNAL_ERROR",
+ "STATUS_INVALID_DEVICE_STATE",
+ "STATUS_IO_DEVICE_ERROR",
+ "STATUS_DEVICE_PROTOCOL_ERROR",
+ "STATUS_BACKUP_CONTROLLER",
+ "STATUS_LOG_FILE_FULL",
+ "STATUS_TOO_LATE",
+ "STATUS_NO_TRUST_LSA_SECRET",
+ "STATUS_NO_TRUST_SAM_ACCOUNT",
+ "STATUS_TRUSTED_DOMAIN_FAILURE",
+ "STATUS_TRUSTED_RELATIONSHIP_FAILURE",
+ "STATUS_EVENTLOG_FILE_CORRUPT",
+ "STATUS_EVENTLOG_CANT_START",
+ "STATUS_TRUST_FAILURE",
+ "STATUS_MUTANT_LIMIT_EXCEEDED",
+ "STATUS_NETLOGON_NOT_STARTED",
+ "STATUS_ACCOUNT_EXPIRED",
+ "STATUS_POSSIBLE_DEADLOCK",
+ "STATUS_NETWORK_CREDENTIAL_CONFLICT",
+ "STATUS_REMOTE_SESSION_LIMIT",
+ "STATUS_EVENTLOG_FILE_CHANGED",
+ "STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT",
+ "STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT",
+ "STATUS_NOLOGON_SERVER_TRUST_ACCOUNT",
+ "STATUS_DOMAIN_TRUST_INCONSISTENT",
+ "STATUS_FS_DRIVER_REQUIRED",
+ "STATUS_IMAGE_ALREADY_LOADED_AS_DLL",
+ "STATUS_INCOMPATIBLE_WITH_GLOBAL_SHORT_NAME_REGISTRY_SETTING",
+ "STATUS_SHORT_NAMES_NOT_ENABLED_ON_VOLUME",
+ "STATUS_SECURITY_STREAM_IS_INCONSISTENT",
+ "STATUS_INVALID_LOCK_RANGE",
+ "STATUS_INVALID_ACE_CONDITION",
+ "STATUS_IMAGE_SUBSYSTEM_NOT_PRESENT",
+ "STATUS_NOTIFICATION_GUID_ALREADY_DEFINED",
+ "STATUS_INVALID_EXCEPTION_HANDLER",
+ "STATUS_DUPLICATE_PRIVILEGES",
+ "STATUS_NOT_ALLOWED_ON_SYSTEM_FILE",
+ "STATUS_REPAIR_NEEDED",
+ "STATUS_QUOTA_NOT_ENABLED",
+ "STATUS_NO_APPLICATION_PACKAGE",
+ "STATUS_FILE_METADATA_OPTIMIZATION_IN_PROGRESS",
+ "STATUS_NOT_SAME_OBJECT",
+ "STATUS_FATAL_MEMORY_EXHAUSTION",
+ "STATUS_ERROR_PROCESS_NOT_IN_JOB",
+ "STATUS_CPU_SET_INVALID",
+ "STATUS_IO_DEVICE_INVALID_DATA",
+ "STATUS_IO_UNALIGNED_WRITE",
+ "STATUS_CONTROL_STACK_VIOLATION",
+ "STATUS_NETWORK_OPEN_RESTRICTION",
+ "STATUS_NO_USER_SESSION_KEY",
+ "STATUS_USER_SESSION_DELETED",
+ "STATUS_RESOURCE_LANG_NOT_FOUND",
+ "STATUS_INSUFF_SERVER_RESOURCES",
+ "STATUS_INVALID_BUFFER_SIZE",
+ "STATUS_INVALID_ADDRESS_COMPONENT",
+ "STATUS_INVALID_ADDRESS_WILDCARD",
+ "STATUS_TOO_MANY_ADDRESSES",
+ "STATUS_ADDRESS_ALREADY_EXISTS",
+ "STATUS_ADDRESS_CLOSED",
+ "STATUS_CONNECTION_DISCONNECTED",
+ "STATUS_CONNECTION_RESET",
+ "STATUS_TOO_MANY_NODES",
+ "STATUS_TRANSACTION_ABORTED",
+ "STATUS_TRANSACTION_TIMED_OUT",
+ "STATUS_TRANSACTION_NO_RELEASE",
+ "STATUS_TRANSACTION_NO_MATCH",
+ "STATUS_TRANSACTION_RESPONDED",
+ "STATUS_TRANSACTION_INVALID_ID",
+ "STATUS_TRANSACTION_INVALID_TYPE",
+ "STATUS_NOT_SERVER_SESSION",
+ "STATUS_NOT_CLIENT_SESSION",
+ "STATUS_CANNOT_LOAD_REGISTRY_FILE",
+ "STATUS_DEBUG_ATTACH_FAILED",
+ "STATUS_SYSTEM_PROCESS_TERMINATED",
+ "STATUS_DATA_NOT_ACCEPTED",
+ "STATUS_NO_BROWSER_SERVERS_FOUND",
+ "STATUS_VDM_HARD_ERROR",
+ "STATUS_DRIVER_CANCEL_TIMEOUT",
+ "STATUS_REPLY_MESSAGE_MISMATCH",
+ "STATUS_MAPPED_ALIGNMENT",
+ "STATUS_IMAGE_CHECKSUM_MISMATCH",
+ "STATUS_LOST_WRITEBEHIND_DATA",
+ "STATUS_CLIENT_SERVER_PARAMETERS_INVALID",
+ "STATUS_PASSWORD_MUST_CHANGE",
+ "STATUS_NOT_FOUND",
+ "STATUS_NOT_TINY_STREAM",
+ "STATUS_RECOVERY_FAILURE",
+ "STATUS_STACK_OVERFLOW_READ",
+ "STATUS_FAIL_CHECK",
+ "STATUS_DUPLICATE_OBJECTID",
+ "STATUS_OBJECTID_EXISTS",
+ "STATUS_CONVERT_TO_LARGE",
+ "STATUS_RETRY",
+ "STATUS_FOUND_OUT_OF_SCOPE",
+ "STATUS_ALLOCATE_BUCKET",
+ "STATUS_PROPSET_NOT_FOUND",
+ "STATUS_MARSHALL_OVERFLOW",
+ "STATUS_INVALID_VARIANT",
+ "STATUS_DOMAIN_CONTROLLER_NOT_FOUND",
+ "STATUS_ACCOUNT_LOCKED_OUT",
+ "STATUS_HANDLE_NOT_CLOSABLE",
+ "STATUS_CONNECTION_REFUSED",
+ "STATUS_GRACEFUL_DISCONNECT",
+ "STATUS_ADDRESS_ALREADY_ASSOCIATED",
+ "STATUS_ADDRESS_NOT_ASSOCIATED",
+ "STATUS_CONNECTION_INVALID",
+ "STATUS_CONNECTION_ACTIVE",
+ "STATUS_NETWORK_UNREACHABLE",
+ "STATUS_HOST_UNREACHABLE",
+ "STATUS_PROTOCOL_UNREACHABLE",
+ "STATUS_PORT_UNREACHABLE",
+ "STATUS_REQUEST_ABORTED",
+ "STATUS_CONNECTION_ABORTED",
+ "STATUS_BAD_COMPRESSION_BUFFER",
+ "STATUS_USER_MAPPED_FILE",
+ "STATUS_AUDIT_FAILED",
+ "STATUS_TIMER_RESOLUTION_NOT_SET",
+ "STATUS_CONNECTION_COUNT_LIMIT",
+ "STATUS_LOGIN_TIME_RESTRICTION",
+ "STATUS_LOGIN_WKSTA_RESTRICTION",
+ "STATUS_IMAGE_MP_UP_MISMATCH",
+ "STATUS_INSUFFICIENT_LOGON_INFO",
+ "STATUS_BAD_DLL_ENTRYPOINT",
+ "STATUS_BAD_SERVICE_ENTRYPOINT",
+ "STATUS_LPC_REPLY_LOST",
+ "STATUS_IP_ADDRESS_CONFLICT1",
+ "STATUS_IP_ADDRESS_CONFLICT2",
+ "STATUS_REGISTRY_QUOTA_LIMIT",
+ "STATUS_PATH_NOT_COVERED",
+ "STATUS_NO_CALLBACK_ACTIVE",
+ "STATUS_LICENSE_QUOTA_EXCEEDED",
+ "STATUS_PWD_TOO_SHORT",
+ "STATUS_PWD_TOO_RECENT",
+ "STATUS_PWD_HISTORY_CONFLICT",
+ "STATUS_PLUGPLAY_NO_DEVICE",
+ "STATUS_UNSUPPORTED_COMPRESSION",
+ "STATUS_INVALID_HW_PROFILE",
+ "STATUS_INVALID_PLUGPLAY_DEVICE_PATH",
+ "STATUS_DRIVER_ORDINAL_NOT_FOUND",
+ "STATUS_DRIVER_ENTRYPOINT_NOT_FOUND",
+ "STATUS_RESOURCE_NOT_OWNED",
+ "STATUS_TOO_MANY_LINKS",
+ "STATUS_QUOTA_LIST_INCONSISTENT",
+ "STATUS_FILE_IS_OFFLINE",
+ "STATUS_EVALUATION_EXPIRATION",
+ "STATUS_ILLEGAL_DLL_RELOCATION",
+ "STATUS_LICENSE_VIOLATION",
+ "STATUS_DLL_INIT_FAILED_LOGOFF",
+ "STATUS_DRIVER_UNABLE_TO_LOAD",
+ "STATUS_DFS_UNAVAILABLE",
+ "STATUS_VOLUME_DISMOUNTED",
+ "STATUS_WX86_INTERNAL_ERROR",
+ "STATUS_WX86_FLOAT_STACK_CHECK",
+ "STATUS_VALIDATE_CONTINUE",
+ "STATUS_NO_MATCH",
+ "STATUS_NO_MORE_MATCHES",
+ "STATUS_NOT_A_REPARSE_POINT",
+ "STATUS_IO_REPARSE_TAG_INVALID",
+ "STATUS_IO_REPARSE_TAG_MISMATCH",
+ "STATUS_IO_REPARSE_DATA_INVALID",
+ "STATUS_IO_REPARSE_TAG_NOT_HANDLED",
+ "STATUS_PWD_TOO_LONG",
+ "STATUS_STOWED_EXCEPTION",
+ "STATUS_CONTEXT_STOWED_EXCEPTION",
+ "STATUS_REPARSE_POINT_NOT_RESOLVED",
+ "STATUS_DIRECTORY_IS_A_REPARSE_POINT",
+ "STATUS_RANGE_LIST_CONFLICT",
+ "STATUS_SOURCE_ELEMENT_EMPTY",
+ "STATUS_DESTINATION_ELEMENT_FULL",
+ "STATUS_ILLEGAL_ELEMENT_ADDRESS",
+ "STATUS_MAGAZINE_NOT_PRESENT",
+ "STATUS_REINITIALIZATION_NEEDED",
+ "STATUS_ENCRYPTION_FAILED",
+ "STATUS_DECRYPTION_FAILED",
+ "STATUS_RANGE_NOT_FOUND",
+ "STATUS_NO_RECOVERY_POLICY",
+ "STATUS_NO_EFS",
+ "STATUS_WRONG_EFS",
+ "STATUS_NO_USER_KEYS",
+ "STATUS_FILE_NOT_ENCRYPTED",
+ "STATUS_NOT_EXPORT_FORMAT",
+ "STATUS_FILE_ENCRYPTED",
+ "STATUS_WMI_GUID_NOT_FOUND",
+ "STATUS_WMI_INSTANCE_NOT_FOUND",
+ "STATUS_WMI_ITEMID_NOT_FOUND",
+ "STATUS_WMI_TRY_AGAIN",
+ "STATUS_SHARED_POLICY",
+ "STATUS_POLICY_OBJECT_NOT_FOUND",
+ "STATUS_POLICY_ONLY_IN_DS",
+ "STATUS_VOLUME_NOT_UPGRADED",
+ "STATUS_REMOTE_STORAGE_NOT_ACTIVE",
+ "STATUS_REMOTE_STORAGE_MEDIA_ERROR",
+ "STATUS_NO_TRACKING_SERVICE",
+ "STATUS_SERVER_SID_MISMATCH",
+ "STATUS_DS_NO_ATTRIBUTE_OR_VALUE",
+ "STATUS_DS_INVALID_ATTRIBUTE_SYNTAX",
+ "STATUS_DS_ATTRIBUTE_TYPE_UNDEFINED",
+ "STATUS_DS_ATTRIBUTE_OR_VALUE_EXISTS",
+ "STATUS_DS_BUSY",
+ "STATUS_DS_UNAVAILABLE",
+ "STATUS_DS_NO_RIDS_ALLOCATED",
+ "STATUS_DS_NO_MORE_RIDS",
+ "STATUS_DS_INCORRECT_ROLE_OWNER",
+ "STATUS_DS_RIDMGR_INIT_ERROR",
+ "STATUS_DS_OBJ_CLASS_VIOLATION",
+ "STATUS_DS_CANT_ON_NON_LEAF",
+ "STATUS_DS_CANT_ON_RDN",
+ "STATUS_DS_CANT_MOD_OBJ_CLASS",
+ "STATUS_DS_CROSS_DOM_MOVE_FAILED",
+ "STATUS_DS_GC_NOT_AVAILABLE",
+ "STATUS_DIRECTORY_SERVICE_REQUIRED",
+ "STATUS_REPARSE_ATTRIBUTE_CONFLICT",
+ "STATUS_CANT_ENABLE_DENY_ONLY",
+ "STATUS_FLOAT_MULTIPLE_FAULTS",
+ "STATUS_FLOAT_MULTIPLE_TRAPS",
+ "STATUS_DEVICE_REMOVED",
+ "STATUS_JOURNAL_DELETE_IN_PROGRESS",
+ "STATUS_JOURNAL_NOT_ACTIVE",
+ "STATUS_NOINTERFACE",
+ "STATUS_DS_RIDMGR_DISABLED",
+ "STATUS_DS_ADMIN_LIMIT_EXCEEDED",
+ "STATUS_DRIVER_FAILED_SLEEP",
+ "STATUS_MUTUAL_AUTHENTICATION_FAILED",
+ "STATUS_CORRUPT_SYSTEM_FILE",
+ "STATUS_DATATYPE_MISALIGNMENT_ERROR",
+ "STATUS_WMI_READ_ONLY",
+ "STATUS_WMI_SET_FAILURE",
+ "STATUS_COMMITMENT_MINIMUM",
+ "STATUS_REG_NAT_CONSUMPTION",
+ "STATUS_TRANSPORT_FULL",
+ "STATUS_DS_SAM_INIT_FAILURE",
+ "STATUS_ONLY_IF_CONNECTED",
+ "STATUS_DS_SENSITIVE_GROUP_VIOLATION",
+ "STATUS_PNP_RESTART_ENUMERATION",
+ "STATUS_JOURNAL_ENTRY_DELETED",
+ "STATUS_DS_CANT_MOD_PRIMARYGROUPID",
+ "STATUS_SYSTEM_IMAGE_BAD_SIGNATURE",
+ "STATUS_PNP_REBOOT_REQUIRED",
+ "STATUS_POWER_STATE_INVALID",
+ "STATUS_DS_INVALID_GROUP_TYPE",
+ "STATUS_DS_NO_NEST_GLOBALGROUP_IN_MIXEDDOMAIN",
+ "STATUS_DS_NO_NEST_LOCALGROUP_IN_MIXEDDOMAIN",
+ "STATUS_DS_GLOBAL_CANT_HAVE_LOCAL_MEMBER",
+ "STATUS_DS_GLOBAL_CANT_HAVE_UNIVERSAL_MEMBER",
+ "STATUS_DS_UNIVERSAL_CANT_HAVE_LOCAL_MEMBER",
+ "STATUS_DS_GLOBAL_CANT_HAVE_CROSSDOMAIN_MEMBER",
+ "STATUS_DS_LOCAL_CANT_HAVE_CROSSDOMAIN_LOCAL_MEMBER",
+ "STATUS_DS_HAVE_PRIMARY_MEMBERS",
+ "STATUS_WMI_NOT_SUPPORTED",
+ "STATUS_INSUFFICIENT_POWER",
+ "STATUS_SAM_NEED_BOOTKEY_PASSWORD",
+ "STATUS_SAM_NEED_BOOTKEY_FLOPPY",
+ "STATUS_DS_CANT_START",
+ "STATUS_DS_INIT_FAILURE",
+ "STATUS_SAM_INIT_FAILURE",
+ "STATUS_DS_GC_REQUIRED",
+ "STATUS_DS_LOCAL_MEMBER_OF_LOCAL_ONLY",
+ "STATUS_DS_NO_FPO_IN_UNIVERSAL_GROUPS",
+ "STATUS_DS_MACHINE_ACCOUNT_QUOTA_EXCEEDED",
+ "STATUS_MULTIPLE_FAULT_VIOLATION",
+ "STATUS_CURRENT_DOMAIN_NOT_ALLOWED",
+ "STATUS_CANNOT_MAKE",
+ "STATUS_SYSTEM_SHUTDOWN",
+ "STATUS_DS_INIT_FAILURE_CONSOLE",
+ "STATUS_DS_SAM_INIT_FAILURE_CONSOLE",
+ "STATUS_UNFINISHED_CONTEXT_DELETED",
+ "STATUS_NO_TGT_REPLY",
+ "STATUS_OBJECTID_NOT_FOUND",
+ "STATUS_NO_IP_ADDRESSES",
+ "STATUS_WRONG_CREDENTIAL_HANDLE",
+ "STATUS_CRYPTO_SYSTEM_INVALID",
+ "STATUS_MAX_REFERRALS_EXCEEDED",
+ "STATUS_MUST_BE_KDC",
+ "STATUS_STRONG_CRYPTO_NOT_SUPPORTED",
+ "STATUS_TOO_MANY_PRINCIPALS",
+ "STATUS_NO_PA_DATA",
+ "STATUS_PKINIT_NAME_MISMATCH",
+ "STATUS_SMARTCARD_LOGON_REQUIRED",
+ "STATUS_KDC_INVALID_REQUEST",
+ "STATUS_KDC_UNABLE_TO_REFER",
+ "STATUS_KDC_UNKNOWN_ETYPE",
+ "STATUS_SHUTDOWN_IN_PROGRESS",
+ "STATUS_SERVER_SHUTDOWN_IN_PROGRESS",
+ "STATUS_NOT_SUPPORTED_ON_SBS",
+ "STATUS_WMI_GUID_DISCONNECTED",
+ "STATUS_WMI_ALREADY_DISABLED",
+ "STATUS_WMI_ALREADY_ENABLED",
+ "STATUS_MFT_TOO_FRAGMENTED",
+ "STATUS_COPY_PROTECTION_FAILURE",
+ "STATUS_CSS_AUTHENTICATION_FAILURE",
+ "STATUS_CSS_KEY_NOT_PRESENT",
+ "STATUS_CSS_KEY_NOT_ESTABLISHED",
+ "STATUS_CSS_SCRAMBLED_SECTOR",
+ "STATUS_CSS_REGION_MISMATCH",
+ "STATUS_CSS_RESETS_EXHAUSTED",
+ "STATUS_PASSWORD_CHANGE_REQUIRED",
+ "STATUS_LOST_MODE_LOGON_RESTRICTION",
+ "STATUS_PKINIT_FAILURE",
+ "STATUS_SMARTCARD_SUBSYSTEM_FAILURE",
+ "STATUS_NO_KERB_KEY",
+ "STATUS_HOST_DOWN",
+ "STATUS_UNSUPPORTED_PREAUTH",
+ "STATUS_EFS_ALG_BLOB_TOO_BIG",
+ "STATUS_PORT_NOT_SET",
+ "STATUS_DEBUGGER_INACTIVE",
+ "STATUS_DS_VERSION_CHECK_FAILURE",
+ "STATUS_AUDITING_DISABLED",
+ "STATUS_PRENT4_MACHINE_ACCOUNT",
+ "STATUS_DS_AG_CANT_HAVE_UNIVERSAL_MEMBER",
+ "STATUS_INVALID_IMAGE_WIN_32",
+ "STATUS_INVALID_IMAGE_WIN_64",
+ "STATUS_BAD_BINDINGS",
+ "STATUS_NETWORK_SESSION_EXPIRED",
+ "STATUS_APPHELP_BLOCK",
+ "STATUS_ALL_SIDS_FILTERED",
+ "STATUS_NOT_SAFE_MODE_DRIVER",
+ "STATUS_ACCESS_DISABLED_BY_POLICY_DEFAULT",
+ "STATUS_ACCESS_DISABLED_BY_POLICY_PATH",
+ "STATUS_ACCESS_DISABLED_BY_POLICY_PUBLISHER",
+ "STATUS_ACCESS_DISABLED_BY_POLICY_OTHER",
+ "STATUS_FAILED_DRIVER_ENTRY",
+ "STATUS_DEVICE_ENUMERATION_ERROR",
+ "STATUS_MOUNT_POINT_NOT_RESOLVED",
+ "STATUS_INVALID_DEVICE_OBJECT_PARAMETER",
+ "STATUS_MCA_OCCURED",
+ "STATUS_DRIVER_BLOCKED_CRITICAL",
+ "STATUS_DRIVER_BLOCKED",
+ "STATUS_DRIVER_DATABASE_ERROR",
+ "STATUS_SYSTEM_HIVE_TOO_LARGE",
+ "STATUS_INVALID_IMPORT_OF_NON_DLL",
+ "STATUS_NO_SECRETS",
+ "STATUS_ACCESS_DISABLED_NO_SAFER_UI_BY_POLICY",
+ "STATUS_FAILED_STACK_SWITCH",
+ "STATUS_HEAP_CORRUPTION",
+ "STATUS_SMARTCARD_WRONG_PIN",
+ "STATUS_SMARTCARD_CARD_BLOCKED",
+ "STATUS_SMARTCARD_CARD_NOT_AUTHENTICATED",
+ "STATUS_SMARTCARD_NO_CARD",
+ "STATUS_SMARTCARD_NO_KEY_CONTAINER",
+ "STATUS_SMARTCARD_NO_CERTIFICATE",
+ "STATUS_SMARTCARD_NO_KEYSET",
+ "STATUS_SMARTCARD_IO_ERROR",
+ "STATUS_DOWNGRADE_DETECTED",
+ "STATUS_SMARTCARD_CERT_REVOKED",
+ "STATUS_ISSUING_CA_UNTRUSTED",
+ "STATUS_REVOCATION_OFFLINE_C",
+ "STATUS_PKINIT_CLIENT_FAILURE",
+ "STATUS_SMARTCARD_CERT_EXPIRED",
+ "STATUS_DRIVER_FAILED_PRIOR_UNLOAD",
+ "STATUS_SMARTCARD_SILENT_CONTEXT",
+ "STATUS_PER_USER_TRUST_QUOTA_EXCEEDED",
+ "STATUS_ALL_USER_TRUST_QUOTA_EXCEEDED",
+ "STATUS_USER_DELETE_TRUST_QUOTA_EXCEEDED",
+ "STATUS_DS_NAME_NOT_UNIQUE",
+ "STATUS_DS_DUPLICATE_ID_FOUND",
+ "STATUS_DS_GROUP_CONVERSION_ERROR",
+ "STATUS_VOLSNAP_PREPARE_HIBERNATE",
+ "STATUS_USER2USER_REQUIRED",
+ "STATUS_STACK_BUFFER_OVERRUN",
+ "STATUS_NO_S4U_PROT_SUPPORT",
+ "STATUS_CROSSREALM_DELEGATION_FAILURE",
+ "STATUS_REVOCATION_OFFLINE_KDC",
+ "STATUS_ISSUING_CA_UNTRUSTED_KDC",
+ "STATUS_KDC_CERT_EXPIRED",
+ "STATUS_KDC_CERT_REVOKED",
+ "STATUS_PARAMETER_QUOTA_EXCEEDED",
+ "STATUS_HIBERNATION_FAILURE",
+ "STATUS_DELAY_LOAD_FAILED",
+ "STATUS_AUTHENTICATION_FIREWALL_FAILED",
+ "STATUS_VDM_DISALLOWED",
+ "STATUS_HUNG_DISPLAY_DRIVER_THREAD",
+ "STATUS_INSUFFICIENT_RESOURCE_FOR_SPECIFIED_SHARED_SECTION_SIZE",
+ "STATUS_INVALID_CRUNTIME_PARAMETER",
+ "STATUS_NTLM_BLOCKED",
+ "STATUS_DS_SRC_SID_EXISTS_IN_FOREST",
+ "STATUS_DS_DOMAIN_NAME_EXISTS_IN_FOREST",
+ "STATUS_DS_FLAT_NAME_EXISTS_IN_FOREST",
+ "STATUS_INVALID_USER_PRINCIPAL_NAME",
+ "STATUS_FATAL_USER_CALLBACK_EXCEPTION",
+ "STATUS_ASSERTION_FAILURE",
+ "STATUS_VERIFIER_STOP",
+ "STATUS_CALLBACK_POP_STACK",
+ "STATUS_INCOMPATIBLE_DRIVER_BLOCKED",
+ "STATUS_HIVE_UNLOADED",
+ "STATUS_COMPRESSION_DISABLED",
+ "STATUS_FILE_SYSTEM_LIMITATION",
+ "STATUS_INVALID_IMAGE_HASH",
+ "STATUS_NOT_CAPABLE",
+ "STATUS_REQUEST_OUT_OF_SEQUENCE",
+ "STATUS_IMPLEMENTATION_LIMIT",
+ "STATUS_ELEVATION_REQUIRED",
+ "STATUS_NO_SECURITY_CONTEXT",
+ "STATUS_PKU2U_CERT_FAILURE",
+ "STATUS_BEYOND_VDL",
+ "STATUS_ENCOUNTERED_WRITE_IN_PROGRESS",
+ "STATUS_PTE_CHANGED",
+ "STATUS_PURGE_FAILED",
+ "STATUS_CRED_REQUIRES_CONFIRMATION",
+ "STATUS_CS_ENCRYPTION_INVALID_SERVER_RESPONSE",
+ "STATUS_CS_ENCRYPTION_UNSUPPORTED_SERVER",
+ "STATUS_CS_ENCRYPTION_EXISTING_ENCRYPTED_FILE",
+ "STATUS_CS_ENCRYPTION_NEW_ENCRYPTED_FILE",
+ "STATUS_CS_ENCRYPTION_FILE_NOT_CSE",
+ "STATUS_INVALID_LABEL",
+ "STATUS_DRIVER_PROCESS_TERMINATED",
+ "STATUS_AMBIGUOUS_SYSTEM_DEVICE",
+ "STATUS_SYSTEM_DEVICE_NOT_FOUND",
+ "STATUS_RESTART_BOOT_APPLICATION",
+ "STATUS_INSUFFICIENT_NVRAM_RESOURCES",
+ "STATUS_INVALID_SESSION",
+ "STATUS_THREAD_ALREADY_IN_SESSION",
+ "STATUS_THREAD_NOT_IN_SESSION",
+ "STATUS_INVALID_WEIGHT",
+ "STATUS_REQUEST_PAUSED",
+ "STATUS_NO_RANGES_PROCESSED",
+ "STATUS_DISK_RESOURCES_EXHAUSTED",
+ "STATUS_NEEDS_REMEDIATION",
+ "STATUS_DEVICE_FEATURE_NOT_SUPPORTED",
+ "STATUS_DEVICE_UNREACHABLE",
+ "STATUS_INVALID_TOKEN",
+ "STATUS_SERVER_UNAVAILABLE",
+ "STATUS_FILE_NOT_AVAILABLE",
+ "STATUS_DEVICE_INSUFFICIENT_RESOURCES",
+ "STATUS_PACKAGE_UPDATING",
+ "STATUS_NOT_READ_FROM_COPY",
+ "STATUS_FT_WRITE_FAILURE",
+ "STATUS_FT_DI_SCAN_REQUIRED",
+ "STATUS_OBJECT_NOT_EXTERNALLY_BACKED",
+ "STATUS_EXTERNAL_BACKING_PROVIDER_UNKNOWN",
+ "STATUS_COMPRESSION_NOT_BENEFICIAL",
+ "STATUS_DATA_CHECKSUM_ERROR",
+ "STATUS_INTERMIXED_KERNEL_EA_OPERATION",
+ "STATUS_TRIM_READ_ZERO_NOT_SUPPORTED",
+ "STATUS_TOO_MANY_SEGMENT_DESCRIPTORS",
+ "STATUS_INVALID_OFFSET_ALIGNMENT",
+ "STATUS_INVALID_FIELD_IN_PARAMETER_LIST",
+ "STATUS_OPERATION_IN_PROGRESS",
+ "STATUS_INVALID_INITIATOR_TARGET_PATH",
+ "STATUS_SCRUB_DATA_DISABLED",
+ "STATUS_NOT_REDUNDANT_STORAGE",
+ "STATUS_RESIDENT_FILE_NOT_SUPPORTED",
+ "STATUS_COMPRESSED_FILE_NOT_SUPPORTED",
+ "STATUS_DIRECTORY_NOT_SUPPORTED",
+ "STATUS_IO_OPERATION_TIMEOUT",
+ "STATUS_SYSTEM_NEEDS_REMEDIATION",
+ "STATUS_APPX_INTEGRITY_FAILURE_CLR_NGEN",
+ "STATUS_SHARE_UNAVAILABLE",
+ "STATUS_APISET_NOT_HOSTED",
+ "STATUS_APISET_NOT_PRESENT",
+ "STATUS_DEVICE_HARDWARE_ERROR",
+ "STATUS_FIRMWARE_SLOT_INVALID",
+ "STATUS_FIRMWARE_IMAGE_INVALID",
+ "STATUS_STORAGE_TOPOLOGY_ID_MISMATCH",
+ "STATUS_WIM_NOT_BOOTABLE",
+ "STATUS_BLOCKED_BY_PARENTAL_CONTROLS",
+ "STATUS_NEEDS_REGISTRATION",
+ "STATUS_QUOTA_ACTIVITY",
+ "STATUS_CALLBACK_INVOKE_INLINE",
+ "STATUS_BLOCK_TOO_MANY_REFERENCES",
+ "STATUS_MARKED_TO_DISALLOW_WRITES",
+ "STATUS_NETWORK_ACCESS_DENIED_EDP",
+ "STATUS_ENCLAVE_FAILURE",
+ "STATUS_PNP_NO_COMPAT_DRIVERS",
+ "STATUS_PNP_DRIVER_PACKAGE_NOT_FOUND",
+ "STATUS_PNP_DRIVER_CONFIGURATION_NOT_FOUND",
+ "STATUS_PNP_DRIVER_CONFIGURATION_INCOMPLETE",
+ "STATUS_PNP_FUNCTION_DRIVER_REQUIRED",
+ "STATUS_PNP_DEVICE_CONFIGURATION_PENDING",
+ "STATUS_DEVICE_HINT_NAME_BUFFER_TOO_SMALL",
+ "STATUS_PACKAGE_NOT_AVAILABLE",
+ "STATUS_DEVICE_IN_MAINTENANCE",
+ "STATUS_NOT_SUPPORTED_ON_DAX",
+ "STATUS_FREE_SPACE_TOO_FRAGMENTED",
+ "STATUS_DAX_MAPPING_EXISTS",
+ "STATUS_CHILD_PROCESS_BLOCKED",
+ "STATUS_STORAGE_LOST_DATA_PERSISTENCE",
+ "STATUS_VRF_CFG_AND_IO_ENABLED",
+ "STATUS_PARTITION_TERMINATING",
+ "STATUS_EXTERNAL_SYSKEY_NOT_SUPPORTED",
+ "STATUS_ENCLAVE_VIOLATION",
+ "STATUS_FILE_PROTECTED_UNDER_DPL",
+ "STATUS_VOLUME_NOT_CLUSTER_ALIGNED",
+ "STATUS_NO_PHYSICALLY_ALIGNED_FREE_SPACE_FOUND",
+ "STATUS_APPX_FILE_NOT_ENCRYPTED",
+ "STATUS_RWRAW_ENCRYPTED_FILE_NOT_ENCRYPTED",
+ "STATUS_RWRAW_ENCRYPTED_INVALID_EDATAINFO_FILEOFFSET",
+ "STATUS_RWRAW_ENCRYPTED_INVALID_EDATAINFO_FILERANGE",
+ "STATUS_RWRAW_ENCRYPTED_INVALID_EDATAINFO_PARAMETER",
+ "STATUS_FT_READ_FAILURE",
+ "STATUS_PATCH_CONFLICT",
+ "STATUS_STORAGE_RESERVE_ID_INVALID",
+ "STATUS_STORAGE_RESERVE_DOES_NOT_EXIST",
+ "STATUS_STORAGE_RESERVE_ALREADY_EXISTS",
+ "STATUS_STORAGE_RESERVE_NOT_EMPTY",
+ "STATUS_NOT_A_DAX_VOLUME",
+ "STATUS_NOT_DAX_MAPPABLE",
+ "STATUS_CASE_DIFFERING_NAMES_IN_DIR",
+ "STATUS_FILE_NOT_SUPPORTED",
+ "STATUS_NOT_SUPPORTED_WITH_BTT",
+ "STATUS_ENCRYPTION_DISABLED",
+ "STATUS_ENCRYPTING_METADATA_DISALLOWED",
+ "STATUS_CANT_CLEAR_ENCRYPTION_FLAG",
+ "STATUS_UNSATISFIED_DEPENDENCIES",
+ "STATUS_CASE_SENSITIVE_PATH",
+ "STATUS_HAS_SYSTEM_CRITICAL_FILES",
+ "STATUS_INVALID_TASK_NAME",
+ "STATUS_INVALID_TASK_INDEX",
+ "STATUS_THREAD_ALREADY_IN_TASK",
+ "STATUS_CALLBACK_BYPASS",
+ "STATUS_UNDEFINED_SCOPE",
+ "STATUS_INVALID_CAP",
+ "STATUS_NOT_GUI_PROCESS",
+ "STATUS_DEVICE_HUNG",
+ "STATUS_CONTAINER_ASSIGNED",
+ "STATUS_JOB_NO_CONTAINER",
+ "STATUS_DEVICE_UNRESPONSIVE",
+ "STATUS_REPARSE_POINT_ENCOUNTERED",
+ "STATUS_ATTRIBUTE_NOT_PRESENT",
+ "STATUS_NOT_A_TIERED_VOLUME",
+ "STATUS_ALREADY_HAS_STREAM_ID",
+ "STATUS_JOB_NOT_EMPTY",
+ "STATUS_ALREADY_INITIALIZED",
+ "STATUS_ENCLAVE_NOT_TERMINATED",
+ "STATUS_ENCLAVE_IS_TERMINATING",
+ "STATUS_SMB1_NOT_AVAILABLE",
+ "STATUS_SMR_GARBAGE_COLLECTION_REQUIRED",
+ "STATUS_INTERRUPTED",
+ "STATUS_THREAD_NOT_RUNNING",
+ "STATUS_FAIL_FAST_EXCEPTION",
+ "STATUS_IMAGE_CERT_REVOKED",
+ "STATUS_DYNAMIC_CODE_BLOCKED",
+ "STATUS_IMAGE_CERT_EXPIRED",
+ "STATUS_STRICT_CFG_VIOLATION",
+ "STATUS_SET_CONTEXT_DENIED",
+ "STATUS_CROSS_PARTITION_VIOLATION",
+ "STATUS_PORT_CLOSED",
+ "STATUS_MESSAGE_LOST",
+ "STATUS_INVALID_MESSAGE",
+ "STATUS_REQUEST_CANCELED",
+ "STATUS_RECURSIVE_DISPATCH",
+ "STATUS_LPC_RECEIVE_BUFFER_EXPECTED",
+ "STATUS_LPC_INVALID_CONNECTION_USAGE",
+ "STATUS_LPC_REQUESTS_NOT_ALLOWED",
+ "STATUS_RESOURCE_IN_USE",
+ "STATUS_HARDWARE_MEMORY_ERROR",
+ "STATUS_THREADPOOL_HANDLE_EXCEPTION",
+ "STATUS_THREADPOOL_SET_EVENT_ON_COMPLETION_FAILED",
+ "STATUS_THREADPOOL_RELEASE_SEMAPHORE_ON_COMPLETION_FAILED",
+ "STATUS_THREADPOOL_RELEASE_MUTEX_ON_COMPLETION_FAILED",
+ "STATUS_THREADPOOL_FREE_LIBRARY_ON_COMPLETION_FAILED",
+ "STATUS_THREADPOOL_RELEASED_DURING_OPERATION",
+ "STATUS_CALLBACK_RETURNED_WHILE_IMPERSONATING",
+ "STATUS_APC_RETURNED_WHILE_IMPERSONATING",
+ "STATUS_PROCESS_IS_PROTECTED",
+ "STATUS_MCA_EXCEPTION",
+ "STATUS_CERTIFICATE_MAPPING_NOT_UNIQUE",
+ "STATUS_SYMLINK_CLASS_DISABLED",
+ "STATUS_INVALID_IDN_NORMALIZATION",
+ "STATUS_NO_UNICODE_TRANSLATION",
+ "STATUS_ALREADY_REGISTERED",
+ "STATUS_CONTEXT_MISMATCH",
+ "STATUS_PORT_ALREADY_HAS_COMPLETION_LIST",
+ "STATUS_CALLBACK_RETURNED_THREAD_PRIORITY",
+ "STATUS_INVALID_THREAD",
+ "STATUS_CALLBACK_RETURNED_TRANSACTION",
+ "STATUS_CALLBACK_RETURNED_LDR_LOCK",
+ "STATUS_CALLBACK_RETURNED_LANG",
+ "STATUS_CALLBACK_RETURNED_PRI_BACK",
+ "STATUS_CALLBACK_RETURNED_THREAD_AFFINITY",
+ "STATUS_LPC_HANDLE_COUNT_EXCEEDED",
+ "STATUS_EXECUTABLE_MEMORY_WRITE",
+ "STATUS_KERNEL_EXECUTABLE_MEMORY_WRITE",
+ "STATUS_ATTACHED_EXECUTABLE_MEMORY_WRITE",
+ "STATUS_TRIGGERED_EXECUTABLE_MEMORY_WRITE",
+ "STATUS_DISK_REPAIR_DISABLED",
+ "STATUS_DS_DOMAIN_RENAME_IN_PROGRESS",
+ "STATUS_DISK_QUOTA_EXCEEDED",
+ "STATUS_CONTENT_BLOCKED",
+ "STATUS_BAD_CLUSTERS",
+ "STATUS_VOLUME_DIRTY",
+ "STATUS_DISK_REPAIR_UNSUCCESSFUL",
+ "STATUS_CORRUPT_LOG_OVERFULL",
+ "STATUS_CORRUPT_LOG_CORRUPTED",
+ "STATUS_CORRUPT_LOG_UNAVAILABLE",
+ "STATUS_CORRUPT_LOG_DELETED_FULL",
+ "STATUS_CORRUPT_LOG_CLEARED",
+ "STATUS_ORPHAN_NAME_EXHAUSTED",
+ "STATUS_PROACTIVE_SCAN_IN_PROGRESS",
+ "STATUS_ENCRYPTED_IO_NOT_POSSIBLE",
+ "STATUS_CORRUPT_LOG_UPLEVEL_RECORDS",
+ "STATUS_FILE_CHECKED_OUT",
+ "STATUS_CHECKOUT_REQUIRED",
+ "STATUS_BAD_FILE_TYPE",
+ "STATUS_FILE_TOO_LARGE",
+ "STATUS_FORMS_AUTH_REQUIRED",
+ "STATUS_VIRUS_INFECTED",
+ "STATUS_VIRUS_DELETED",
+ "STATUS_BAD_MCFG_TABLE",
+ "STATUS_CANNOT_BREAK_OPLOCK",
+ "STATUS_BAD_KEY",
+ "STATUS_BAD_DATA",
+ "STATUS_NO_KEY",
+ "STATUS_FILE_HANDLE_REVOKED",
+ "STATUS_WOW_ASSERTION",
+ "STATUS_INVALID_SIGNATURE",
+ "STATUS_HMAC_NOT_SUPPORTED",
+ "STATUS_AUTH_TAG_MISMATCH",
+ "STATUS_INVALID_STATE_TRANSITION",
+ "STATUS_INVALID_KERNEL_INFO_VERSION",
+ "STATUS_INVALID_PEP_INFO_VERSION",
+ "STATUS_HANDLE_REVOKED",
+ "STATUS_EOF_ON_GHOSTED_RANGE",
+ "STATUS_CC_NEEDS_CALLBACK_SECTION_DRAIN",
+ "STATUS_IPSEC_QUEUE_OVERFLOW",
+ "STATUS_ND_QUEUE_OVERFLOW",
+ "STATUS_HOPLIMIT_EXCEEDED",
+ "STATUS_PROTOCOL_NOT_SUPPORTED",
+ "STATUS_FASTPATH_REJECTED",
+ "STATUS_LOST_WRITEBEHIND_DATA_NETWORK_DISCONNECTED",
+ "STATUS_LOST_WRITEBEHIND_DATA_NETWORK_SERVER_ERROR",
+ "STATUS_LOST_WRITEBEHIND_DATA_LOCAL_DISK_ERROR",
+ "STATUS_XML_PARSE_ERROR",
+ "STATUS_XMLDSIG_ERROR",
+ "STATUS_WRONG_COMPARTMENT",
+ "STATUS_AUTHIP_FAILURE",
+ "STATUS_DS_OID_MAPPED_GROUP_CANT_HAVE_MEMBERS",
+ "STATUS_DS_OID_NOT_FOUND",
+ "STATUS_INCORRECT_ACCOUNT_TYPE",
+ "STATUS_HASH_NOT_SUPPORTED",
+ "STATUS_HASH_NOT_PRESENT",
+ "STATUS_SECONDARY_IC_PROVIDER_NOT_REGISTERED",
+ "STATUS_GPIO_CLIENT_INFORMATION_INVALID",
+ "STATUS_GPIO_VERSION_NOT_SUPPORTED",
+ "STATUS_GPIO_INVALID_REGISTRATION_PACKET",
+ "STATUS_GPIO_OPERATION_DENIED",
+ "STATUS_GPIO_INCOMPATIBLE_CONNECT_MODE",
+ "STATUS_CANNOT_SWITCH_RUNLEVEL",
+ "STATUS_INVALID_RUNLEVEL_SETTING",
+ "STATUS_RUNLEVEL_SWITCH_TIMEOUT",
+ "STATUS_RUNLEVEL_SWITCH_AGENT_TIMEOUT",
+ "STATUS_RUNLEVEL_SWITCH_IN_PROGRESS",
+ "STATUS_NOT_APPCONTAINER",
+ "STATUS_NOT_SUPPORTED_IN_APPCONTAINER",
+ "STATUS_INVALID_PACKAGE_SID_LENGTH",
+ "STATUS_LPAC_ACCESS_DENIED",
+ "STATUS_ADMINLESS_ACCESS_DENIED",
+ "STATUS_APP_DATA_NOT_FOUND",
+ "STATUS_APP_DATA_EXPIRED",
+ "STATUS_APP_DATA_CORRUPT",
+ "STATUS_APP_DATA_LIMIT_EXCEEDED",
+ "STATUS_APP_DATA_REBOOT_REQUIRED",
+ "STATUS_OFFLOAD_READ_FLT_NOT_SUPPORTED",
+ "STATUS_OFFLOAD_WRITE_FLT_NOT_SUPPORTED",
+ "STATUS_OFFLOAD_READ_FILE_NOT_SUPPORTED",
+ "STATUS_OFFLOAD_WRITE_FILE_NOT_SUPPORTED",
+ "STATUS_WOF_WIM_HEADER_CORRUPT",
+ "STATUS_WOF_WIM_RESOURCE_TABLE_CORRUPT",
+ "STATUS_WOF_FILE_RESOURCE_TABLE_CORRUPT",
+ "STATUS_CIMFS_IMAGE_CORRUPT",
+ "STATUS_FILE_SYSTEM_VIRTUALIZATION_UNAVAILABLE",
+ "STATUS_FILE_SYSTEM_VIRTUALIZATION_METADATA_CORRUPT",
+ "STATUS_FILE_SYSTEM_VIRTUALIZATION_BUSY",
+ "STATUS_FILE_SYSTEM_VIRTUALIZATION_PROVIDER_UNKNOWN",
+ "STATUS_FILE_SYSTEM_VIRTUALIZATION_INVALID_OPERATION",
+ "STATUS_CLOUD_FILE_SYNC_ROOT_METADATA_CORRUPT",
+ "STATUS_CLOUD_FILE_PROVIDER_NOT_RUNNING",
+ "STATUS_CLOUD_FILE_METADATA_CORRUPT",
+ "STATUS_CLOUD_FILE_METADATA_TOO_LARGE",
+ "STATUS_CLOUD_FILE_PROPERTY_VERSION_NOT_SUPPORTED",
+ "STATUS_NOT_A_CLOUD_FILE",
+ "STATUS_CLOUD_FILE_NOT_IN_SYNC",
+ "STATUS_CLOUD_FILE_ALREADY_CONNECTED",
+ "STATUS_CLOUD_FILE_NOT_SUPPORTED",
+ "STATUS_CLOUD_FILE_INVALID_REQUEST",
+ "STATUS_CLOUD_FILE_READ_ONLY_VOLUME",
+ "STATUS_CLOUD_FILE_CONNECTED_PROVIDER_ONLY",
+ "STATUS_CLOUD_FILE_VALIDATION_FAILED",
+ "STATUS_CLOUD_FILE_AUTHENTICATION_FAILED",
+ "STATUS_CLOUD_FILE_INSUFFICIENT_RESOURCES",
+ "STATUS_CLOUD_FILE_NETWORK_UNAVAILABLE",
+ "STATUS_CLOUD_FILE_UNSUCCESSFUL",
+ "STATUS_CLOUD_FILE_NOT_UNDER_SYNC_ROOT",
+ "STATUS_CLOUD_FILE_IN_USE",
+ "STATUS_CLOUD_FILE_PINNED",
+ "STATUS_CLOUD_FILE_REQUEST_ABORTED",
+ "STATUS_CLOUD_FILE_PROPERTY_CORRUPT",
+ "STATUS_CLOUD_FILE_ACCESS_DENIED",
+ "STATUS_CLOUD_FILE_INCOMPATIBLE_HARDLINKS",
+ "STATUS_CLOUD_FILE_PROPERTY_LOCK_CONFLICT",
+ "STATUS_CLOUD_FILE_REQUEST_CANCELED",
+ "STATUS_CLOUD_FILE_PROVIDER_TERMINATED",
+ "STATUS_NOT_A_CLOUD_SYNC_ROOT",
+ "STATUS_CLOUD_FILE_REQUEST_TIMEOUT",
+ "STATUS_CLOUD_FILE_DEHYDRATION_DISALLOWED",
+ "STATUS_FILE_SNAP_IN_PROGRESS",
+ "STATUS_FILE_SNAP_USER_SECTION_NOT_SUPPORTED",
+ "STATUS_FILE_SNAP_MODIFY_NOT_SUPPORTED",
+ "STATUS_FILE_SNAP_IO_NOT_COORDINATED",
+ "STATUS_FILE_SNAP_UNEXPECTED_ERROR",
+ "STATUS_FILE_SNAP_INVALID_PARAMETER",
+ "DBG_NO_STATE_CHANGE",
+ "DBG_APP_NOT_IDLE",
+ "RPC_NT_INVALID_STRING_BINDING",
+ "RPC_NT_WRONG_KIND_OF_BINDING",
+ "RPC_NT_INVALID_BINDING",
+ "RPC_NT_PROTSEQ_NOT_SUPPORTED",
+ "RPC_NT_INVALID_RPC_PROTSEQ",
+ "RPC_NT_INVALID_STRING_UUID",
+ "RPC_NT_INVALID_ENDPOINT_FORMAT",
+ "RPC_NT_INVALID_NET_ADDR",
+ "RPC_NT_NO_ENDPOINT_FOUND",
+ "RPC_NT_INVALID_TIMEOUT",
+ "RPC_NT_OBJECT_NOT_FOUND",
+ "RPC_NT_ALREADY_REGISTERED",
+ "RPC_NT_TYPE_ALREADY_REGISTERED",
+ "RPC_NT_ALREADY_LISTENING",
+ "RPC_NT_NO_PROTSEQS_REGISTERED",
+ "RPC_NT_NOT_LISTENING",
+ "RPC_NT_UNKNOWN_MGR_TYPE",
+ "RPC_NT_UNKNOWN_IF",
+ "RPC_NT_NO_BINDINGS",
+ "RPC_NT_NO_PROTSEQS",
+ "RPC_NT_CANT_CREATE_ENDPOINT",
+ "RPC_NT_OUT_OF_RESOURCES",
+ "RPC_NT_SERVER_UNAVAILABLE",
+ "RPC_NT_SERVER_TOO_BUSY",
+ "RPC_NT_INVALID_NETWORK_OPTIONS",
+ "RPC_NT_NO_CALL_ACTIVE",
+ "RPC_NT_CALL_FAILED",
+ "RPC_NT_CALL_FAILED_DNE",
+ "RPC_NT_PROTOCOL_ERROR",
+ "RPC_NT_UNSUPPORTED_TRANS_SYN",
+ "RPC_NT_UNSUPPORTED_TYPE",
+ "RPC_NT_INVALID_TAG",
+ "RPC_NT_INVALID_BOUND",
+ "RPC_NT_NO_ENTRY_NAME",
+ "RPC_NT_INVALID_NAME_SYNTAX",
+ "RPC_NT_UNSUPPORTED_NAME_SYNTAX",
+ "RPC_NT_UUID_NO_ADDRESS",
+ "RPC_NT_DUPLICATE_ENDPOINT",
+ "RPC_NT_UNKNOWN_AUTHN_TYPE",
+ "RPC_NT_MAX_CALLS_TOO_SMALL",
+ "RPC_NT_STRING_TOO_LONG",
+ "RPC_NT_PROTSEQ_NOT_FOUND",
+ "RPC_NT_PROCNUM_OUT_OF_RANGE",
+ "RPC_NT_BINDING_HAS_NO_AUTH",
+ "RPC_NT_UNKNOWN_AUTHN_SERVICE",
+ "RPC_NT_UNKNOWN_AUTHN_LEVEL",
+ "RPC_NT_INVALID_AUTH_IDENTITY",
+ "RPC_NT_UNKNOWN_AUTHZ_SERVICE",
+ "EPT_NT_INVALID_ENTRY",
+ "EPT_NT_CANT_PERFORM_OP",
+ "EPT_NT_NOT_REGISTERED",
+ "RPC_NT_NOTHING_TO_EXPORT",
+ "RPC_NT_INCOMPLETE_NAME",
+ "RPC_NT_INVALID_VERS_OPTION",
+ "RPC_NT_NO_MORE_MEMBERS",
+ "RPC_NT_NOT_ALL_OBJS_UNEXPORTED",
+ "RPC_NT_INTERFACE_NOT_FOUND",
+ "RPC_NT_ENTRY_ALREADY_EXISTS",
+ "RPC_NT_ENTRY_NOT_FOUND",
+ "RPC_NT_NAME_SERVICE_UNAVAILABLE",
+ "RPC_NT_INVALID_NAF_ID",
+ "RPC_NT_CANNOT_SUPPORT",
+ "RPC_NT_NO_CONTEXT_AVAILABLE",
+ "RPC_NT_INTERNAL_ERROR",
+ "RPC_NT_ZERO_DIVIDE",
+ "RPC_NT_ADDRESS_ERROR",
+ "RPC_NT_FP_DIV_ZERO",
+ "RPC_NT_FP_UNDERFLOW",
+ "RPC_NT_FP_OVERFLOW",
+ "RPC_NT_CALL_IN_PROGRESS",
+ "RPC_NT_NO_MORE_BINDINGS",
+ "RPC_NT_GROUP_MEMBER_NOT_FOUND",
+ "EPT_NT_CANT_CREATE",
+ "RPC_NT_INVALID_OBJECT",
+ "RPC_NT_NO_INTERFACES",
+ "RPC_NT_CALL_CANCELLED",
+ "RPC_NT_BINDING_INCOMPLETE",
+ "RPC_NT_COMM_FAILURE",
+ "RPC_NT_UNSUPPORTED_AUTHN_LEVEL",
+ "RPC_NT_NO_PRINC_NAME",
+ "RPC_NT_NOT_RPC_ERROR",
+ "RPC_NT_SEC_PKG_ERROR",
+ "RPC_NT_NOT_CANCELLED",
+ "RPC_NT_INVALID_ASYNC_HANDLE",
+ "RPC_NT_INVALID_ASYNC_CALL",
+ "RPC_NT_PROXY_ACCESS_DENIED",
+ "RPC_NT_COOKIE_AUTH_FAILED",
+ "RPC_NT_NO_MORE_ENTRIES",
+ "RPC_NT_SS_CHAR_TRANS_OPEN_FAIL",
+ "RPC_NT_SS_CHAR_TRANS_SHORT_FILE",
+ "RPC_NT_SS_IN_NULL_CONTEXT",
+ "RPC_NT_SS_CONTEXT_MISMATCH",
+ "RPC_NT_SS_CONTEXT_DAMAGED",
+ "RPC_NT_SS_HANDLES_MISMATCH",
+ "RPC_NT_SS_CANNOT_GET_CALL_HANDLE",
+ "RPC_NT_NULL_REF_POINTER",
+ "RPC_NT_ENUM_VALUE_OUT_OF_RANGE",
+ "RPC_NT_BYTE_COUNT_TOO_SMALL",
+ "RPC_NT_BAD_STUB_DATA",
+ "RPC_NT_INVALID_ES_ACTION",
+ "RPC_NT_WRONG_ES_VERSION",
+ "RPC_NT_WRONG_STUB_VERSION",
+ "RPC_NT_INVALID_PIPE_OBJECT",
+ "RPC_NT_INVALID_PIPE_OPERATION",
+ "RPC_NT_WRONG_PIPE_VERSION",
+ "RPC_NT_PIPE_CLOSED",
+ "RPC_NT_PIPE_DISCIPLINE_ERROR",
+ "RPC_NT_PIPE_EMPTY",
+ "STATUS_PNP_BAD_MPS_TABLE",
+ "STATUS_PNP_TRANSLATION_FAILED",
+ "STATUS_PNP_IRQ_TRANSLATION_FAILED",
+ "STATUS_PNP_INVALID_ID",
+ "STATUS_IO_REISSUE_AS_CACHED",
+ "STATUS_CTX_WINSTATION_NAME_INVALID",
+ "STATUS_CTX_INVALID_PD",
+ "STATUS_CTX_PD_NOT_FOUND",
+ "STATUS_CTX_CLOSE_PENDING",
+ "STATUS_CTX_NO_OUTBUF",
+ "STATUS_CTX_MODEM_INF_NOT_FOUND",
+ "STATUS_CTX_INVALID_MODEMNAME",
+ "STATUS_CTX_RESPONSE_ERROR",
+ "STATUS_CTX_MODEM_RESPONSE_TIMEOUT",
+ "STATUS_CTX_MODEM_RESPONSE_NO_CARRIER",
+ "STATUS_CTX_MODEM_RESPONSE_NO_DIALTONE",
+ "STATUS_CTX_MODEM_RESPONSE_BUSY",
+ "STATUS_CTX_MODEM_RESPONSE_VOICE",
+ "STATUS_CTX_TD_ERROR",
+ "STATUS_CTX_LICENSE_CLIENT_INVALID",
+ "STATUS_CTX_LICENSE_NOT_AVAILABLE",
+ "STATUS_CTX_LICENSE_EXPIRED",
+ "STATUS_CTX_WINSTATION_NOT_FOUND",
+ "STATUS_CTX_WINSTATION_NAME_COLLISION",
+ "STATUS_CTX_WINSTATION_BUSY",
+ "STATUS_CTX_BAD_VIDEO_MODE",
+ "STATUS_CTX_GRAPHICS_INVALID",
+ "STATUS_CTX_NOT_CONSOLE",
+ "STATUS_CTX_CLIENT_QUERY_TIMEOUT",
+ "STATUS_CTX_CONSOLE_DISCONNECT",
+ "STATUS_CTX_CONSOLE_CONNECT",
+ "STATUS_CTX_SHADOW_DENIED",
+ "STATUS_CTX_WINSTATION_ACCESS_DENIED",
+ "STATUS_CTX_INVALID_WD",
+ "STATUS_CTX_WD_NOT_FOUND",
+ "STATUS_CTX_SHADOW_INVALID",
+ "STATUS_CTX_SHADOW_DISABLED",
+ "STATUS_RDP_PROTOCOL_ERROR",
+ "STATUS_CTX_CLIENT_LICENSE_NOT_SET",
+ "STATUS_CTX_CLIENT_LICENSE_IN_USE",
+ "STATUS_CTX_SHADOW_ENDED_BY_MODE_CHANGE",
+ "STATUS_CTX_SHADOW_NOT_RUNNING",
+ "STATUS_CTX_LOGON_DISABLED",
+ "STATUS_CTX_SECURITY_LAYER_ERROR",
+ "STATUS_TS_INCOMPATIBLE_SESSIONS",
+ "STATUS_TS_VIDEO_SUBSYSTEM_ERROR",
+ "STATUS_MUI_FILE_NOT_FOUND",
+ "STATUS_MUI_INVALID_FILE",
+ "STATUS_MUI_INVALID_RC_CONFIG",
+ "STATUS_MUI_INVALID_LOCALE_NAME",
+ "STATUS_MUI_INVALID_ULTIMATEFALLBACK_NAME",
+ "STATUS_MUI_FILE_NOT_LOADED",
+ "STATUS_RESOURCE_ENUM_USER_STOP",
+ "STATUS_CLUSTER_INVALID_NODE",
+ "STATUS_CLUSTER_NODE_EXISTS",
+ "STATUS_CLUSTER_JOIN_IN_PROGRESS",
+ "STATUS_CLUSTER_NODE_NOT_FOUND",
+ "STATUS_CLUSTER_LOCAL_NODE_NOT_FOUND",
+ "STATUS_CLUSTER_NETWORK_EXISTS",
+ "STATUS_CLUSTER_NETWORK_NOT_FOUND",
+ "STATUS_CLUSTER_NETINTERFACE_EXISTS",
+ "STATUS_CLUSTER_NETINTERFACE_NOT_FOUND",
+ "STATUS_CLUSTER_INVALID_REQUEST",
+ "STATUS_CLUSTER_INVALID_NETWORK_PROVIDER",
+ "STATUS_CLUSTER_NODE_DOWN",
+ "STATUS_CLUSTER_NODE_UNREACHABLE",
+ "STATUS_CLUSTER_NODE_NOT_MEMBER",
+ "STATUS_CLUSTER_JOIN_NOT_IN_PROGRESS",
+ "STATUS_CLUSTER_INVALID_NETWORK",
+ "STATUS_CLUSTER_NO_NET_ADAPTERS",
+ "STATUS_CLUSTER_NODE_UP",
+ "STATUS_CLUSTER_NODE_PAUSED",
+ "STATUS_CLUSTER_NODE_NOT_PAUSED",
+ "STATUS_CLUSTER_NO_SECURITY_CONTEXT",
+ "STATUS_CLUSTER_NETWORK_NOT_INTERNAL",
+ "STATUS_CLUSTER_POISONED",
+ "STATUS_CLUSTER_NON_CSV_PATH",
+ "STATUS_CLUSTER_CSV_VOLUME_NOT_LOCAL",
+ "STATUS_CLUSTER_CSV_READ_OPLOCK_BREAK_IN_PROGRESS",
+ "STATUS_CLUSTER_CSV_AUTO_PAUSE_ERROR",
+ "STATUS_CLUSTER_CSV_REDIRECTED",
+ "STATUS_CLUSTER_CSV_NOT_REDIRECTED",
+ "STATUS_CLUSTER_CSV_VOLUME_DRAINING",
+ "STATUS_CLUSTER_CSV_SNAPSHOT_CREATION_IN_PROGRESS",
+ "STATUS_CLUSTER_CSV_VOLUME_DRAINING_SUCCEEDED_DOWNLEVEL",
+ "STATUS_CLUSTER_CSV_NO_SNAPSHOTS",
+ "STATUS_CSV_IO_PAUSE_TIMEOUT",
+ "STATUS_CLUSTER_CSV_INVALID_HANDLE",
+ "STATUS_CLUSTER_CSV_SUPPORTED_ONLY_ON_COORDINATOR",
+ "STATUS_CLUSTER_CAM_TICKET_REPLAY_DETECTED",
+ "STATUS_ACPI_INVALID_OPCODE",
+ "STATUS_ACPI_STACK_OVERFLOW",
+ "STATUS_ACPI_ASSERT_FAILED",
+ "STATUS_ACPI_INVALID_INDEX",
+ "STATUS_ACPI_INVALID_ARGUMENT",
+ "STATUS_ACPI_FATAL",
+ "STATUS_ACPI_INVALID_SUPERNAME",
+ "STATUS_ACPI_INVALID_ARGTYPE",
+ "STATUS_ACPI_INVALID_OBJTYPE",
+ "STATUS_ACPI_INVALID_TARGETTYPE",
+ "STATUS_ACPI_INCORRECT_ARGUMENT_COUNT",
+ "STATUS_ACPI_ADDRESS_NOT_MAPPED",
+ "STATUS_ACPI_INVALID_EVENTTYPE",
+ "STATUS_ACPI_HANDLER_COLLISION",
+ "STATUS_ACPI_INVALID_DATA",
+ "STATUS_ACPI_INVALID_REGION",
+ "STATUS_ACPI_INVALID_ACCESS_SIZE",
+ "STATUS_ACPI_ACQUIRE_GLOBAL_LOCK",
+ "STATUS_ACPI_ALREADY_INITIALIZED",
+ "STATUS_ACPI_NOT_INITIALIZED",
+ "STATUS_ACPI_INVALID_MUTEX_LEVEL",
+ "STATUS_ACPI_MUTEX_NOT_OWNED",
+ "STATUS_ACPI_MUTEX_NOT_OWNER",
+ "STATUS_ACPI_RS_ACCESS",
+ "STATUS_ACPI_INVALID_TABLE",
+ "STATUS_ACPI_REG_HANDLER_FAILED",
+ "STATUS_ACPI_POWER_REQUEST_FAILED",
+ "STATUS_SXS_SECTION_NOT_FOUND",
+ "STATUS_SXS_CANT_GEN_ACTCTX",
+ "STATUS_SXS_INVALID_ACTCTXDATA_FORMAT",
+ "STATUS_SXS_ASSEMBLY_NOT_FOUND",
+ "STATUS_SXS_MANIFEST_FORMAT_ERROR",
+ "STATUS_SXS_MANIFEST_PARSE_ERROR",
+ "STATUS_SXS_ACTIVATION_CONTEXT_DISABLED",
+ "STATUS_SXS_KEY_NOT_FOUND",
+ "STATUS_SXS_VERSION_CONFLICT",
+ "STATUS_SXS_WRONG_SECTION_TYPE",
+ "STATUS_SXS_THREAD_QUERIES_DISABLED",
+ "STATUS_SXS_ASSEMBLY_MISSING",
+ "STATUS_SXS_PROCESS_DEFAULT_ALREADY_SET",
+ "STATUS_SXS_EARLY_DEACTIVATION",
+ "STATUS_SXS_INVALID_DEACTIVATION",
+ "STATUS_SXS_MULTIPLE_DEACTIVATION",
+ "STATUS_SXS_SYSTEM_DEFAULT_ACTIVATION_CONTEXT_EMPTY",
+ "STATUS_SXS_PROCESS_TERMINATION_REQUESTED",
+ "STATUS_SXS_CORRUPT_ACTIVATION_STACK",
+ "STATUS_SXS_CORRUPTION",
+ "STATUS_SXS_INVALID_IDENTITY_ATTRIBUTE_VALUE",
+ "STATUS_SXS_INVALID_IDENTITY_ATTRIBUTE_NAME",
+ "STATUS_SXS_IDENTITY_DUPLICATE_ATTRIBUTE",
+ "STATUS_SXS_IDENTITY_PARSE_ERROR",
+ "STATUS_SXS_COMPONENT_STORE_CORRUPT",
+ "STATUS_SXS_FILE_HASH_MISMATCH",
+ "STATUS_SXS_MANIFEST_IDENTITY_SAME_BUT_CONTENTS_DIFFERENT",
+ "STATUS_SXS_IDENTITIES_DIFFERENT",
+ "STATUS_SXS_ASSEMBLY_IS_NOT_A_DEPLOYMENT",
+ "STATUS_SXS_FILE_NOT_PART_OF_ASSEMBLY",
+ "STATUS_ADVANCED_INSTALLER_FAILED",
+ "STATUS_XML_ENCODING_MISMATCH",
+ "STATUS_SXS_MANIFEST_TOO_BIG",
+ "STATUS_SXS_SETTING_NOT_REGISTERED",
+ "STATUS_SXS_TRANSACTION_CLOSURE_INCOMPLETE",
+ "STATUS_SMI_PRIMITIVE_INSTALLER_FAILED",
+ "STATUS_GENERIC_COMMAND_FAILED",
+ "STATUS_SXS_FILE_HASH_MISSING",
+ "STATUS_TRANSACTIONAL_CONFLICT",
+ "STATUS_INVALID_TRANSACTION",
+ "STATUS_TRANSACTION_NOT_ACTIVE",
+ "STATUS_TM_INITIALIZATION_FAILED",
+ "STATUS_RM_NOT_ACTIVE",
+ "STATUS_RM_METADATA_CORRUPT",
+ "STATUS_TRANSACTION_NOT_JOINED",
+ "STATUS_DIRECTORY_NOT_RM",
+ "STATUS_TRANSACTIONS_UNSUPPORTED_REMOTE",
+ "STATUS_LOG_RESIZE_INVALID_SIZE",
+ "STATUS_REMOTE_FILE_VERSION_MISMATCH",
+ "STATUS_CRM_PROTOCOL_ALREADY_EXISTS",
+ "STATUS_TRANSACTION_PROPAGATION_FAILED",
+ "STATUS_CRM_PROTOCOL_NOT_FOUND",
+ "STATUS_TRANSACTION_SUPERIOR_EXISTS",
+ "STATUS_TRANSACTION_REQUEST_NOT_VALID",
+ "STATUS_TRANSACTION_NOT_REQUESTED",
+ "STATUS_TRANSACTION_ALREADY_ABORTED",
+ "STATUS_TRANSACTION_ALREADY_COMMITTED",
+ "STATUS_TRANSACTION_INVALID_MARSHALL_BUFFER",
+ "STATUS_CURRENT_TRANSACTION_NOT_VALID",
+ "STATUS_LOG_GROWTH_FAILED",
+ "STATUS_OBJECT_NO_LONGER_EXISTS",
+ "STATUS_STREAM_MINIVERSION_NOT_FOUND",
+ "STATUS_STREAM_MINIVERSION_NOT_VALID",
+ "STATUS_MINIVERSION_INACCESSIBLE_FROM_SPECIFIED_TRANSACTION",
+ "STATUS_CANT_OPEN_MINIVERSION_WITH_MODIFY_INTENT",
+ "STATUS_CANT_CREATE_MORE_STREAM_MINIVERSIONS",
+ "STATUS_HANDLE_NO_LONGER_VALID",
+ "STATUS_LOG_CORRUPTION_DETECTED",
+ "STATUS_RM_DISCONNECTED",
+ "STATUS_ENLISTMENT_NOT_SUPERIOR",
+ "STATUS_FILE_IDENTITY_NOT_PERSISTENT",
+ "STATUS_CANT_BREAK_TRANSACTIONAL_DEPENDENCY",
+ "STATUS_CANT_CROSS_RM_BOUNDARY",
+ "STATUS_TXF_DIR_NOT_EMPTY",
+ "STATUS_INDOUBT_TRANSACTIONS_EXIST",
+ "STATUS_TM_VOLATILE",
+ "STATUS_ROLLBACK_TIMER_EXPIRED",
+ "STATUS_TXF_ATTRIBUTE_CORRUPT",
+ "STATUS_EFS_NOT_ALLOWED_IN_TRANSACTION",
+ "STATUS_TRANSACTIONAL_OPEN_NOT_ALLOWED",
+ "STATUS_TRANSACTED_MAPPING_UNSUPPORTED_REMOTE",
+ "STATUS_TRANSACTION_REQUIRED_PROMOTION",
+ "STATUS_CANNOT_EXECUTE_FILE_IN_TRANSACTION",
+ "STATUS_TRANSACTIONS_NOT_FROZEN",
+ "STATUS_TRANSACTION_FREEZE_IN_PROGRESS",
+ "STATUS_NOT_SNAPSHOT_VOLUME",
+ "STATUS_NO_SAVEPOINT_WITH_OPEN_FILES",
+ "STATUS_SPARSE_NOT_ALLOWED_IN_TRANSACTION",
+ "STATUS_TM_IDENTITY_MISMATCH",
+ "STATUS_FLOATED_SECTION",
+ "STATUS_CANNOT_ACCEPT_TRANSACTED_WORK",
+ "STATUS_CANNOT_ABORT_TRANSACTIONS",
+ "STATUS_TRANSACTION_NOT_FOUND",
+ "STATUS_RESOURCEMANAGER_NOT_FOUND",
+ "STATUS_ENLISTMENT_NOT_FOUND",
+ "STATUS_TRANSACTIONMANAGER_NOT_FOUND",
+ "STATUS_TRANSACTIONMANAGER_NOT_ONLINE",
+ "STATUS_TRANSACTIONMANAGER_RECOVERY_NAME_COLLISION",
+ "STATUS_TRANSACTION_NOT_ROOT",
+ "STATUS_TRANSACTION_OBJECT_EXPIRED",
+ "STATUS_COMPRESSION_NOT_ALLOWED_IN_TRANSACTION",
+ "STATUS_TRANSACTION_RESPONSE_NOT_ENLISTED",
+ "STATUS_TRANSACTION_RECORD_TOO_LONG",
+ "STATUS_NO_LINK_TRACKING_IN_TRANSACTION",
+ "STATUS_OPERATION_NOT_SUPPORTED_IN_TRANSACTION",
+ "STATUS_TRANSACTION_INTEGRITY_VIOLATED",
+ "STATUS_TRANSACTIONMANAGER_IDENTITY_MISMATCH",
+ "STATUS_RM_CANNOT_BE_FROZEN_FOR_SNAPSHOT",
+ "STATUS_TRANSACTION_MUST_WRITETHROUGH",
+ "STATUS_TRANSACTION_NO_SUPERIOR",
+ "STATUS_EXPIRED_HANDLE",
+ "STATUS_TRANSACTION_NOT_ENLISTED",
+ "STATUS_LOG_SECTOR_INVALID",
+ "STATUS_LOG_SECTOR_PARITY_INVALID",
+ "STATUS_LOG_SECTOR_REMAPPED",
+ "STATUS_LOG_BLOCK_INCOMPLETE",
+ "STATUS_LOG_INVALID_RANGE",
+ "STATUS_LOG_BLOCKS_EXHAUSTED",
+ "STATUS_LOG_READ_CONTEXT_INVALID",
+ "STATUS_LOG_RESTART_INVALID",
+ "STATUS_LOG_BLOCK_VERSION",
+ "STATUS_LOG_BLOCK_INVALID",
+ "STATUS_LOG_READ_MODE_INVALID",
+ "STATUS_LOG_METADATA_CORRUPT",
+ "STATUS_LOG_METADATA_INVALID",
+ "STATUS_LOG_METADATA_INCONSISTENT",
+ "STATUS_LOG_RESERVATION_INVALID",
+ "STATUS_LOG_CANT_DELETE",
+ "STATUS_LOG_CONTAINER_LIMIT_EXCEEDED",
+ "STATUS_LOG_START_OF_LOG",
+ "STATUS_LOG_POLICY_ALREADY_INSTALLED",
+ "STATUS_LOG_POLICY_NOT_INSTALLED",
+ "STATUS_LOG_POLICY_INVALID",
+ "STATUS_LOG_POLICY_CONFLICT",
+ "STATUS_LOG_PINNED_ARCHIVE_TAIL",
+ "STATUS_LOG_RECORD_NONEXISTENT",
+ "STATUS_LOG_RECORDS_RESERVED_INVALID",
+ "STATUS_LOG_SPACE_RESERVED_INVALID",
+ "STATUS_LOG_TAIL_INVALID",
+ "STATUS_LOG_FULL",
+ "STATUS_LOG_MULTIPLEXED",
+ "STATUS_LOG_DEDICATED",
+ "STATUS_LOG_ARCHIVE_NOT_IN_PROGRESS",
+ "STATUS_LOG_ARCHIVE_IN_PROGRESS",
+ "STATUS_LOG_EPHEMERAL",
+ "STATUS_LOG_NOT_ENOUGH_CONTAINERS",
+ "STATUS_LOG_CLIENT_ALREADY_REGISTERED",
+ "STATUS_LOG_CLIENT_NOT_REGISTERED",
+ "STATUS_LOG_FULL_HANDLER_IN_PROGRESS",
+ "STATUS_LOG_CONTAINER_READ_FAILED",
+ "STATUS_LOG_CONTAINER_WRITE_FAILED",
+ "STATUS_LOG_CONTAINER_OPEN_FAILED",
+ "STATUS_LOG_CONTAINER_STATE_INVALID",
+ "STATUS_LOG_STATE_INVALID",
+ "STATUS_LOG_PINNED",
+ "STATUS_LOG_METADATA_FLUSH_FAILED",
+ "STATUS_LOG_INCONSISTENT_SECURITY",
+ "STATUS_LOG_APPENDED_FLUSH_FAILED",
+ "STATUS_LOG_PINNED_RESERVATION",
+ "STATUS_VIDEO_HUNG_DISPLAY_DRIVER_THREAD",
+ "STATUS_FLT_NO_HANDLER_DEFINED",
+ "STATUS_FLT_CONTEXT_ALREADY_DEFINED",
+ "STATUS_FLT_INVALID_ASYNCHRONOUS_REQUEST",
+ "STATUS_FLT_DISALLOW_FAST_IO",
+ "STATUS_FLT_INVALID_NAME_REQUEST",
+ "STATUS_FLT_NOT_SAFE_TO_POST_OPERATION",
+ "STATUS_FLT_NOT_INITIALIZED",
+ "STATUS_FLT_FILTER_NOT_READY",
+ "STATUS_FLT_POST_OPERATION_CLEANUP",
+ "STATUS_FLT_INTERNAL_ERROR",
+ "STATUS_FLT_DELETING_OBJECT",
+ "STATUS_FLT_MUST_BE_NONPAGED_POOL",
+ "STATUS_FLT_DUPLICATE_ENTRY",
+ "STATUS_FLT_CBDQ_DISABLED",
+ "STATUS_FLT_DO_NOT_ATTACH",
+ "STATUS_FLT_DO_NOT_DETACH",
+ "STATUS_FLT_INSTANCE_ALTITUDE_COLLISION",
+ "STATUS_FLT_INSTANCE_NAME_COLLISION",
+ "STATUS_FLT_FILTER_NOT_FOUND",
+ "STATUS_FLT_VOLUME_NOT_FOUND",
+ "STATUS_FLT_INSTANCE_NOT_FOUND",
+ "STATUS_FLT_CONTEXT_ALLOCATION_NOT_FOUND",
+ "STATUS_FLT_INVALID_CONTEXT_REGISTRATION",
+ "STATUS_FLT_NAME_CACHE_MISS",
+ "STATUS_FLT_NO_DEVICE_OBJECT",
+ "STATUS_FLT_VOLUME_ALREADY_MOUNTED",
+ "STATUS_FLT_ALREADY_ENLISTED",
+ "STATUS_FLT_CONTEXT_ALREADY_LINKED",
+ "STATUS_FLT_NO_WAITER_FOR_REPLY",
+ "STATUS_FLT_REGISTRATION_BUSY",
+ "STATUS_MONITOR_NO_DESCRIPTOR",
+ "STATUS_MONITOR_UNKNOWN_DESCRIPTOR_FORMAT",
+ "STATUS_MONITOR_INVALID_DESCRIPTOR_CHECKSUM",
+ "STATUS_MONITOR_INVALID_STANDARD_TIMING_BLOCK",
+ "STATUS_MONITOR_WMI_DATABLOCK_REGISTRATION_FAILED",
+ "STATUS_MONITOR_INVALID_SERIAL_NUMBER_MONDSC_BLOCK",
+ "STATUS_MONITOR_INVALID_USER_FRIENDLY_MONDSC_BLOCK",
+ "STATUS_MONITOR_NO_MORE_DESCRIPTOR_DATA",
+ "STATUS_MONITOR_INVALID_DETAILED_TIMING_BLOCK",
+ "STATUS_MONITOR_INVALID_MANUFACTURE_DATE",
+ "STATUS_GRAPHICS_NOT_EXCLUSIVE_MODE_OWNER",
+ "STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER",
+ "STATUS_GRAPHICS_INVALID_DISPLAY_ADAPTER",
+ "STATUS_GRAPHICS_ADAPTER_WAS_RESET",
+ "STATUS_GRAPHICS_INVALID_DRIVER_MODEL",
+ "STATUS_GRAPHICS_PRESENT_MODE_CHANGED",
+ "STATUS_GRAPHICS_PRESENT_OCCLUDED",
+ "STATUS_GRAPHICS_PRESENT_DENIED",
+ "STATUS_GRAPHICS_CANNOTCOLORCONVERT",
+ "STATUS_GRAPHICS_DRIVER_MISMATCH",
+ "STATUS_GRAPHICS_PRESENT_REDIRECTION_DISABLED",
+ "STATUS_GRAPHICS_PRESENT_UNOCCLUDED",
+ "STATUS_GRAPHICS_WINDOWDC_NOT_AVAILABLE",
+ "STATUS_GRAPHICS_WINDOWLESS_PRESENT_DISABLED",
+ "STATUS_GRAPHICS_PRESENT_INVALID_WINDOW",
+ "STATUS_GRAPHICS_PRESENT_BUFFER_NOT_BOUND",
+ "STATUS_GRAPHICS_VAIL_STATE_CHANGED",
+ "STATUS_GRAPHICS_INDIRECT_DISPLAY_ABANDON_SWAPCHAIN",
+ "STATUS_GRAPHICS_INDIRECT_DISPLAY_DEVICE_STOPPED",
+ "STATUS_GRAPHICS_NO_VIDEO_MEMORY",
+ "STATUS_GRAPHICS_CANT_LOCK_MEMORY",
+ "STATUS_GRAPHICS_ALLOCATION_BUSY",
+ "STATUS_GRAPHICS_TOO_MANY_REFERENCES",
+ "STATUS_GRAPHICS_TRY_AGAIN_LATER",
+ "STATUS_GRAPHICS_TRY_AGAIN_NOW",
+ "STATUS_GRAPHICS_ALLOCATION_INVALID",
+ "STATUS_GRAPHICS_UNSWIZZLING_APERTURE_UNAVAILABLE",
+ "STATUS_GRAPHICS_UNSWIZZLING_APERTURE_UNSUPPORTED",
+ "STATUS_GRAPHICS_CANT_EVICT_PINNED_ALLOCATION",
+ "STATUS_GRAPHICS_INVALID_ALLOCATION_USAGE",
+ "STATUS_GRAPHICS_CANT_RENDER_LOCKED_ALLOCATION",
+ "STATUS_GRAPHICS_ALLOCATION_CLOSED",
+ "STATUS_GRAPHICS_INVALID_ALLOCATION_INSTANCE",
+ "STATUS_GRAPHICS_INVALID_ALLOCATION_HANDLE",
+ "STATUS_GRAPHICS_WRONG_ALLOCATION_DEVICE",
+ "STATUS_GRAPHICS_ALLOCATION_CONTENT_LOST",
+ "STATUS_GRAPHICS_GPU_EXCEPTION_ON_DEVICE",
+ "STATUS_GRAPHICS_INVALID_VIDPN_TOPOLOGY",
+ "STATUS_GRAPHICS_VIDPN_TOPOLOGY_NOT_SUPPORTED",
+ "STATUS_GRAPHICS_VIDPN_TOPOLOGY_CURRENTLY_NOT_SUPPORTED",
+ "STATUS_GRAPHICS_INVALID_VIDPN",
+ "STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_SOURCE",
+ "STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_TARGET",
+ "STATUS_GRAPHICS_VIDPN_MODALITY_NOT_SUPPORTED",
+ "STATUS_GRAPHICS_INVALID_VIDPN_SOURCEMODESET",
+ "STATUS_GRAPHICS_INVALID_VIDPN_TARGETMODESET",
+ "STATUS_GRAPHICS_INVALID_FREQUENCY",
+ "STATUS_GRAPHICS_INVALID_ACTIVE_REGION",
+ "STATUS_GRAPHICS_INVALID_TOTAL_REGION",
+ "STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_SOURCE_MODE",
+ "STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_TARGET_MODE",
+ "STATUS_GRAPHICS_PINNED_MODE_MUST_REMAIN_IN_SET",
+ "STATUS_GRAPHICS_PATH_ALREADY_IN_TOPOLOGY",
+ "STATUS_GRAPHICS_MODE_ALREADY_IN_MODESET",
+ "STATUS_GRAPHICS_INVALID_VIDEOPRESENTSOURCESET",
+ "STATUS_GRAPHICS_INVALID_VIDEOPRESENTTARGETSET",
+ "STATUS_GRAPHICS_SOURCE_ALREADY_IN_SET",
+ "STATUS_GRAPHICS_TARGET_ALREADY_IN_SET",
+ "STATUS_GRAPHICS_INVALID_VIDPN_PRESENT_PATH",
+ "STATUS_GRAPHICS_NO_RECOMMENDED_VIDPN_TOPOLOGY",
+ "STATUS_GRAPHICS_INVALID_MONITOR_FREQUENCYRANGESET",
+ "STATUS_GRAPHICS_INVALID_MONITOR_FREQUENCYRANGE",
+ "STATUS_GRAPHICS_FREQUENCYRANGE_NOT_IN_SET",
+ "STATUS_GRAPHICS_FREQUENCYRANGE_ALREADY_IN_SET",
+ "STATUS_GRAPHICS_STALE_MODESET",
+ "STATUS_GRAPHICS_INVALID_MONITOR_SOURCEMODESET",
+ "STATUS_GRAPHICS_INVALID_MONITOR_SOURCE_MODE",
+ "STATUS_GRAPHICS_NO_RECOMMENDED_FUNCTIONAL_VIDPN",
+ "STATUS_GRAPHICS_MODE_ID_MUST_BE_UNIQUE",
+ "STATUS_GRAPHICS_EMPTY_ADAPTER_MONITOR_MODE_SUPPORT_INTERSECTION",
+ "STATUS_GRAPHICS_VIDEO_PRESENT_TARGETS_LESS_THAN_SOURCES",
+ "STATUS_GRAPHICS_PATH_NOT_IN_TOPOLOGY",
+ "STATUS_GRAPHICS_ADAPTER_MUST_HAVE_AT_LEAST_ONE_SOURCE",
+ "STATUS_GRAPHICS_ADAPTER_MUST_HAVE_AT_LEAST_ONE_TARGET",
+ "STATUS_GRAPHICS_INVALID_MONITORDESCRIPTORSET",
+ "STATUS_GRAPHICS_INVALID_MONITORDESCRIPTOR",
+ "STATUS_GRAPHICS_MONITORDESCRIPTOR_NOT_IN_SET",
+ "STATUS_GRAPHICS_MONITORDESCRIPTOR_ALREADY_IN_SET",
+ "STATUS_GRAPHICS_MONITORDESCRIPTOR_ID_MUST_BE_UNIQUE",
+ "STATUS_GRAPHICS_INVALID_VIDPN_TARGET_SUBSET_TYPE",
+ "STATUS_GRAPHICS_RESOURCES_NOT_RELATED",
+ "STATUS_GRAPHICS_SOURCE_ID_MUST_BE_UNIQUE",
+ "STATUS_GRAPHICS_TARGET_ID_MUST_BE_UNIQUE",
+ "STATUS_GRAPHICS_NO_AVAILABLE_VIDPN_TARGET",
+ "STATUS_GRAPHICS_MONITOR_COULD_NOT_BE_ASSOCIATED_WITH_ADAPTER",
+ "STATUS_GRAPHICS_NO_VIDPNMGR",
+ "STATUS_GRAPHICS_NO_ACTIVE_VIDPN",
+ "STATUS_GRAPHICS_STALE_VIDPN_TOPOLOGY",
+ "STATUS_GRAPHICS_MONITOR_NOT_CONNECTED",
+ "STATUS_GRAPHICS_SOURCE_NOT_IN_TOPOLOGY",
+ "STATUS_GRAPHICS_INVALID_PRIMARYSURFACE_SIZE",
+ "STATUS_GRAPHICS_INVALID_VISIBLEREGION_SIZE",
+ "STATUS_GRAPHICS_INVALID_STRIDE",
+ "STATUS_GRAPHICS_INVALID_PIXELFORMAT",
+ "STATUS_GRAPHICS_INVALID_COLORBASIS",
+ "STATUS_GRAPHICS_INVALID_PIXELVALUEACCESSMODE",
+ "STATUS_GRAPHICS_TARGET_NOT_IN_TOPOLOGY",
+ "STATUS_GRAPHICS_NO_DISPLAY_MODE_MANAGEMENT_SUPPORT",
+ "STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE",
+ "STATUS_GRAPHICS_CANT_ACCESS_ACTIVE_VIDPN",
+ "STATUS_GRAPHICS_INVALID_PATH_IMPORTANCE_ORDINAL",
+ "STATUS_GRAPHICS_INVALID_PATH_CONTENT_GEOMETRY_TRANSFORMATION",
+ "STATUS_GRAPHICS_PATH_CONTENT_GEOMETRY_TRANSFORMATION_NOT_SUPPORTED",
+ "STATUS_GRAPHICS_INVALID_GAMMA_RAMP",
+ "STATUS_GRAPHICS_GAMMA_RAMP_NOT_SUPPORTED",
+ "STATUS_GRAPHICS_MULTISAMPLING_NOT_SUPPORTED",
+ "STATUS_GRAPHICS_MODE_NOT_IN_MODESET",
+ "STATUS_GRAPHICS_INVALID_VIDPN_TOPOLOGY_RECOMMENDATION_REASON",
+ "STATUS_GRAPHICS_INVALID_PATH_CONTENT_TYPE",
+ "STATUS_GRAPHICS_INVALID_COPYPROTECTION_TYPE",
+ "STATUS_GRAPHICS_UNASSIGNED_MODESET_ALREADY_EXISTS",
+ "STATUS_GRAPHICS_INVALID_SCANLINE_ORDERING",
+ "STATUS_GRAPHICS_TOPOLOGY_CHANGES_NOT_ALLOWED",
+ "STATUS_GRAPHICS_NO_AVAILABLE_IMPORTANCE_ORDINALS",
+ "STATUS_GRAPHICS_INCOMPATIBLE_PRIVATE_FORMAT",
+ "STATUS_GRAPHICS_INVALID_MODE_PRUNING_ALGORITHM",
+ "STATUS_GRAPHICS_INVALID_MONITOR_CAPABILITY_ORIGIN",
+ "STATUS_GRAPHICS_INVALID_MONITOR_FREQUENCYRANGE_CONSTRAINT",
+ "STATUS_GRAPHICS_MAX_NUM_PATHS_REACHED",
+ "STATUS_GRAPHICS_CANCEL_VIDPN_TOPOLOGY_AUGMENTATION",
+ "STATUS_GRAPHICS_INVALID_CLIENT_TYPE",
+ "STATUS_GRAPHICS_CLIENTVIDPN_NOT_SET",
+ "STATUS_GRAPHICS_SPECIFIED_CHILD_ALREADY_CONNECTED",
+ "STATUS_GRAPHICS_CHILD_DESCRIPTOR_NOT_SUPPORTED",
+ "STATUS_GRAPHICS_NOT_A_LINKED_ADAPTER",
+ "STATUS_GRAPHICS_LEADLINK_NOT_ENUMERATED",
+ "STATUS_GRAPHICS_CHAINLINKS_NOT_ENUMERATED",
+ "STATUS_GRAPHICS_ADAPTER_CHAIN_NOT_READY",
+ "STATUS_GRAPHICS_CHAINLINKS_NOT_STARTED",
+ "STATUS_GRAPHICS_CHAINLINKS_NOT_POWERED_ON",
+ "STATUS_GRAPHICS_INCONSISTENT_DEVICE_LINK_STATE",
+ "STATUS_GRAPHICS_NOT_POST_DEVICE_DRIVER",
+ "STATUS_GRAPHICS_ADAPTER_ACCESS_NOT_EXCLUDED",
+ "STATUS_GRAPHICS_OPM_NOT_SUPPORTED",
+ "STATUS_GRAPHICS_COPP_NOT_SUPPORTED",
+ "STATUS_GRAPHICS_UAB_NOT_SUPPORTED",
+ "STATUS_GRAPHICS_OPM_INVALID_ENCRYPTED_PARAMETERS",
+ "STATUS_GRAPHICS_OPM_NO_PROTECTED_OUTPUTS_EXIST",
+ "STATUS_GRAPHICS_OPM_INTERNAL_ERROR",
+ "STATUS_GRAPHICS_OPM_INVALID_HANDLE",
+ "STATUS_GRAPHICS_PVP_INVALID_CERTIFICATE_LENGTH",
+ "STATUS_GRAPHICS_OPM_SPANNING_MODE_ENABLED",
+ "STATUS_GRAPHICS_OPM_THEATER_MODE_ENABLED",
+ "STATUS_GRAPHICS_PVP_HFS_FAILED",
+ "STATUS_GRAPHICS_OPM_INVALID_SRM",
+ "STATUS_GRAPHICS_OPM_OUTPUT_DOES_NOT_SUPPORT_HDCP",
+ "STATUS_GRAPHICS_OPM_OUTPUT_DOES_NOT_SUPPORT_ACP",
+ "STATUS_GRAPHICS_OPM_OUTPUT_DOES_NOT_SUPPORT_CGMSA",
+ "STATUS_GRAPHICS_OPM_HDCP_SRM_NEVER_SET",
+ "STATUS_GRAPHICS_OPM_RESOLUTION_TOO_HIGH",
+ "STATUS_GRAPHICS_OPM_ALL_HDCP_HARDWARE_ALREADY_IN_USE",
+ "STATUS_GRAPHICS_OPM_PROTECTED_OUTPUT_NO_LONGER_EXISTS",
+ "STATUS_GRAPHICS_OPM_PROTECTED_OUTPUT_DOES_NOT_HAVE_COPP_SEMANTICS",
+ "STATUS_GRAPHICS_OPM_INVALID_INFORMATION_REQUEST",
+ "STATUS_GRAPHICS_OPM_DRIVER_INTERNAL_ERROR",
+ "STATUS_GRAPHICS_OPM_PROTECTED_OUTPUT_DOES_NOT_HAVE_OPM_SEMANTICS",
+ "STATUS_GRAPHICS_OPM_SIGNALING_NOT_SUPPORTED",
+ "STATUS_GRAPHICS_OPM_INVALID_CONFIGURATION_REQUEST",
+ "STATUS_GRAPHICS_I2C_NOT_SUPPORTED",
+ "STATUS_GRAPHICS_I2C_DEVICE_DOES_NOT_EXIST",
+ "STATUS_GRAPHICS_I2C_ERROR_TRANSMITTING_DATA",
+ "STATUS_GRAPHICS_I2C_ERROR_RECEIVING_DATA",
+ "STATUS_GRAPHICS_DDCCI_VCP_NOT_SUPPORTED",
+ "STATUS_GRAPHICS_DDCCI_INVALID_DATA",
+ "STATUS_GRAPHICS_DDCCI_MONITOR_RETURNED_INVALID_TIMING_STATUS_BYTE",
+ "STATUS_GRAPHICS_DDCCI_INVALID_CAPABILITIES_STRING",
+ "STATUS_GRAPHICS_MCA_INTERNAL_ERROR",
+ "STATUS_GRAPHICS_DDCCI_INVALID_MESSAGE_COMMAND",
+ "STATUS_GRAPHICS_DDCCI_INVALID_MESSAGE_LENGTH",
+ "STATUS_GRAPHICS_DDCCI_INVALID_MESSAGE_CHECKSUM",
+ "STATUS_GRAPHICS_INVALID_PHYSICAL_MONITOR_HANDLE",
+ "STATUS_GRAPHICS_MONITOR_NO_LONGER_EXISTS",
+ "STATUS_GRAPHICS_ONLY_CONSOLE_SESSION_SUPPORTED",
+ "STATUS_GRAPHICS_NO_DISPLAY_DEVICE_CORRESPONDS_TO_NAME",
+ "STATUS_GRAPHICS_DISPLAY_DEVICE_NOT_ATTACHED_TO_DESKTOP",
+ "STATUS_GRAPHICS_MIRRORING_DEVICES_NOT_SUPPORTED",
+ "STATUS_GRAPHICS_INVALID_POINTER",
+ "STATUS_GRAPHICS_NO_MONITORS_CORRESPOND_TO_DISPLAY_DEVICE",
+ "STATUS_GRAPHICS_PARAMETER_ARRAY_TOO_SMALL",
+ "STATUS_GRAPHICS_INTERNAL_ERROR",
+ "STATUS_GRAPHICS_SESSION_TYPE_CHANGE_IN_PROGRESS",
+ "STATUS_FVE_LOCKED_VOLUME",
+ "STATUS_FVE_NOT_ENCRYPTED",
+ "STATUS_FVE_BAD_INFORMATION",
+ "STATUS_FVE_TOO_SMALL",
+ "STATUS_FVE_FAILED_WRONG_FS",
+ "STATUS_FVE_BAD_PARTITION_SIZE",
+ "STATUS_FVE_FS_NOT_EXTENDED",
+ "STATUS_FVE_FS_MOUNTED",
+ "STATUS_FVE_NO_LICENSE",
+ "STATUS_FVE_ACTION_NOT_ALLOWED",
+ "STATUS_FVE_BAD_DATA",
+ "STATUS_FVE_VOLUME_NOT_BOUND",
+ "STATUS_FVE_NOT_DATA_VOLUME",
+ "STATUS_FVE_CONV_READ_ERROR",
+ "STATUS_FVE_CONV_WRITE_ERROR",
+ "STATUS_FVE_OVERLAPPED_UPDATE",
+ "STATUS_FVE_FAILED_SECTOR_SIZE",
+ "STATUS_FVE_FAILED_AUTHENTICATION",
+ "STATUS_FVE_NOT_OS_VOLUME",
+ "STATUS_FVE_KEYFILE_NOT_FOUND",
+ "STATUS_FVE_KEYFILE_INVALID",
+ "STATUS_FVE_KEYFILE_NO_VMK",
+ "STATUS_FVE_TPM_DISABLED",
+ "STATUS_FVE_TPM_SRK_AUTH_NOT_ZERO",
+ "STATUS_FVE_TPM_INVALID_PCR",
+ "STATUS_FVE_TPM_NO_VMK",
+ "STATUS_FVE_PIN_INVALID",
+ "STATUS_FVE_AUTH_INVALID_APPLICATION",
+ "STATUS_FVE_AUTH_INVALID_CONFIG",
+ "STATUS_FVE_DEBUGGER_ENABLED",
+ "STATUS_FVE_DRY_RUN_FAILED",
+ "STATUS_FVE_BAD_METADATA_POINTER",
+ "STATUS_FVE_OLD_METADATA_COPY",
+ "STATUS_FVE_REBOOT_REQUIRED",
+ "STATUS_FVE_RAW_ACCESS",
+ "STATUS_FVE_RAW_BLOCKED",
+ "STATUS_FVE_NO_AUTOUNLOCK_MASTER_KEY",
+ "STATUS_FVE_MOR_FAILED",
+ "STATUS_FVE_NO_FEATURE_LICENSE",
+ "STATUS_FVE_POLICY_USER_DISABLE_RDV_NOT_ALLOWED",
+ "STATUS_FVE_CONV_RECOVERY_FAILED",
+ "STATUS_FVE_VIRTUALIZED_SPACE_TOO_BIG",
+ "STATUS_FVE_INVALID_DATUM_TYPE",
+ "STATUS_FVE_VOLUME_TOO_SMALL",
+ "STATUS_FVE_ENH_PIN_INVALID",
+ "STATUS_FVE_FULL_ENCRYPTION_NOT_ALLOWED_ON_TP_STORAGE",
+ "STATUS_FVE_WIPE_NOT_ALLOWED_ON_TP_STORAGE",
+ "STATUS_FVE_NOT_ALLOWED_ON_CSV_STACK",
+ "STATUS_FVE_NOT_ALLOWED_ON_CLUSTER",
+ "STATUS_FVE_NOT_ALLOWED_TO_UPGRADE_WHILE_CONVERTING",
+ "STATUS_FVE_WIPE_CANCEL_NOT_APPLICABLE",
+ "STATUS_FVE_EDRIVE_DRY_RUN_FAILED",
+ "STATUS_FVE_SECUREBOOT_DISABLED",
+ "STATUS_FVE_SECUREBOOT_CONFIG_CHANGE",
+ "STATUS_FVE_DEVICE_LOCKEDOUT",
+ "STATUS_FVE_VOLUME_EXTEND_PREVENTS_EOW_DECRYPT",
+ "STATUS_FVE_NOT_DE_VOLUME",
+ "STATUS_FVE_PROTECTION_DISABLED",
+ "STATUS_FVE_PROTECTION_CANNOT_BE_DISABLED",
+ "STATUS_FVE_OSV_KSR_NOT_ALLOWED",
+ "STATUS_FWP_CALLOUT_NOT_FOUND",
+ "STATUS_FWP_CONDITION_NOT_FOUND",
+ "STATUS_FWP_FILTER_NOT_FOUND",
+ "STATUS_FWP_LAYER_NOT_FOUND",
+ "STATUS_FWP_PROVIDER_NOT_FOUND",
+ "STATUS_FWP_PROVIDER_CONTEXT_NOT_FOUND",
+ "STATUS_FWP_SUBLAYER_NOT_FOUND",
+ "STATUS_FWP_NOT_FOUND",
+ "STATUS_FWP_ALREADY_EXISTS",
+ "STATUS_FWP_IN_USE",
+ "STATUS_FWP_DYNAMIC_SESSION_IN_PROGRESS",
+ "STATUS_FWP_WRONG_SESSION",
+ "STATUS_FWP_NO_TXN_IN_PROGRESS",
+ "STATUS_FWP_TXN_IN_PROGRESS",
+ "STATUS_FWP_TXN_ABORTED",
+ "STATUS_FWP_SESSION_ABORTED",
+ "STATUS_FWP_INCOMPATIBLE_TXN",
+ "STATUS_FWP_TIMEOUT",
+ "STATUS_FWP_NET_EVENTS_DISABLED",
+ "STATUS_FWP_INCOMPATIBLE_LAYER",
+ "STATUS_FWP_KM_CLIENTS_ONLY",
+ "STATUS_FWP_LIFETIME_MISMATCH",
+ "STATUS_FWP_BUILTIN_OBJECT",
+ "STATUS_FWP_TOO_MANY_CALLOUTS",
+ "STATUS_FWP_NOTIFICATION_DROPPED",
+ "STATUS_FWP_TRAFFIC_MISMATCH",
+ "STATUS_FWP_INCOMPATIBLE_SA_STATE",
+ "STATUS_FWP_NULL_POINTER",
+ "STATUS_FWP_INVALID_ENUMERATOR",
+ "STATUS_FWP_INVALID_FLAGS",
+ "STATUS_FWP_INVALID_NET_MASK",
+ "STATUS_FWP_INVALID_RANGE",
+ "STATUS_FWP_INVALID_INTERVAL",
+ "STATUS_FWP_ZERO_LENGTH_ARRAY",
+ "STATUS_FWP_NULL_DISPLAY_NAME",
+ "STATUS_FWP_INVALID_ACTION_TYPE",
+ "STATUS_FWP_INVALID_WEIGHT",
+ "STATUS_FWP_MATCH_TYPE_MISMATCH",
+ "STATUS_FWP_TYPE_MISMATCH",
+ "STATUS_FWP_OUT_OF_BOUNDS",
+ "STATUS_FWP_RESERVED",
+ "STATUS_FWP_DUPLICATE_CONDITION",
+ "STATUS_FWP_DUPLICATE_KEYMOD",
+ "STATUS_FWP_ACTION_INCOMPATIBLE_WITH_LAYER",
+ "STATUS_FWP_ACTION_INCOMPATIBLE_WITH_SUBLAYER",
+ "STATUS_FWP_CONTEXT_INCOMPATIBLE_WITH_LAYER",
+ "STATUS_FWP_CONTEXT_INCOMPATIBLE_WITH_CALLOUT",
+ "STATUS_FWP_INCOMPATIBLE_AUTH_METHOD",
+ "STATUS_FWP_INCOMPATIBLE_DH_GROUP",
+ "STATUS_FWP_EM_NOT_SUPPORTED",
+ "STATUS_FWP_NEVER_MATCH",
+ "STATUS_FWP_PROVIDER_CONTEXT_MISMATCH",
+ "STATUS_FWP_INVALID_PARAMETER",
+ "STATUS_FWP_TOO_MANY_SUBLAYERS",
+ "STATUS_FWP_CALLOUT_NOTIFICATION_FAILED",
+ "STATUS_FWP_INVALID_AUTH_TRANSFORM",
+ "STATUS_FWP_INVALID_CIPHER_TRANSFORM",
+ "STATUS_FWP_INCOMPATIBLE_CIPHER_TRANSFORM",
+ "STATUS_FWP_INVALID_TRANSFORM_COMBINATION",
+ "STATUS_FWP_DUPLICATE_AUTH_METHOD",
+ "STATUS_FWP_INVALID_TUNNEL_ENDPOINT",
+ "STATUS_FWP_L2_DRIVER_NOT_READY",
+ "STATUS_FWP_KEY_DICTATOR_ALREADY_REGISTERED",
+ "STATUS_FWP_KEY_DICTATION_INVALID_KEYING_MATERIAL",
+ "STATUS_FWP_CONNECTIONS_DISABLED",
+ "STATUS_FWP_INVALID_DNS_NAME",
+ "STATUS_FWP_STILL_ON",
+ "STATUS_FWP_IKEEXT_NOT_RUNNING",
+ "STATUS_FWP_TCPIP_NOT_READY",
+ "STATUS_FWP_INJECT_HANDLE_CLOSING",
+ "STATUS_FWP_INJECT_HANDLE_STALE",
+ "STATUS_FWP_CANNOT_PEND",
+ "STATUS_FWP_DROP_NOICMP",
+ "STATUS_NDIS_CLOSING",
+ "STATUS_NDIS_BAD_VERSION",
+ "STATUS_NDIS_BAD_CHARACTERISTICS",
+ "STATUS_NDIS_ADAPTER_NOT_FOUND",
+ "STATUS_NDIS_OPEN_FAILED",
+ "STATUS_NDIS_DEVICE_FAILED",
+ "STATUS_NDIS_MULTICAST_FULL",
+ "STATUS_NDIS_MULTICAST_EXISTS",
+ "STATUS_NDIS_MULTICAST_NOT_FOUND",
+ "STATUS_NDIS_REQUEST_ABORTED",
+ "STATUS_NDIS_RESET_IN_PROGRESS",
+ "STATUS_NDIS_INVALID_PACKET",
+ "STATUS_NDIS_INVALID_DEVICE_REQUEST",
+ "STATUS_NDIS_ADAPTER_NOT_READY",
+ "STATUS_NDIS_INVALID_LENGTH",
+ "STATUS_NDIS_INVALID_DATA",
+ "STATUS_NDIS_BUFFER_TOO_SHORT",
+ "STATUS_NDIS_INVALID_OID",
+ "STATUS_NDIS_ADAPTER_REMOVED",
+ "STATUS_NDIS_UNSUPPORTED_MEDIA",
+ "STATUS_NDIS_GROUP_ADDRESS_IN_USE",
+ "STATUS_NDIS_FILE_NOT_FOUND",
+ "STATUS_NDIS_ERROR_READING_FILE",
+ "STATUS_NDIS_ALREADY_MAPPED",
+ "STATUS_NDIS_RESOURCE_CONFLICT",
+ "STATUS_NDIS_MEDIA_DISCONNECTED",
+ "STATUS_NDIS_INVALID_ADDRESS",
+ "STATUS_NDIS_PAUSED",
+ "STATUS_NDIS_INTERFACE_NOT_FOUND",
+ "STATUS_NDIS_UNSUPPORTED_REVISION",
+ "STATUS_NDIS_INVALID_PORT",
+ "STATUS_NDIS_INVALID_PORT_STATE",
+ "STATUS_NDIS_LOW_POWER_STATE",
+ "STATUS_NDIS_REINIT_REQUIRED",
+ "STATUS_NDIS_NO_QUEUES",
+ "STATUS_NDIS_NOT_SUPPORTED",
+ "STATUS_NDIS_OFFLOAD_POLICY",
+ "STATUS_NDIS_OFFLOAD_CONNECTION_REJECTED",
+ "STATUS_NDIS_OFFLOAD_PATH_REJECTED",
+ "STATUS_NDIS_DOT11_AUTO_CONFIG_ENABLED",
+ "STATUS_NDIS_DOT11_MEDIA_IN_USE",
+ "STATUS_NDIS_DOT11_POWER_STATE_INVALID",
+ "STATUS_NDIS_PM_WOL_PATTERN_LIST_FULL",
+ "STATUS_NDIS_PM_PROTOCOL_OFFLOAD_LIST_FULL",
+ "STATUS_NDIS_DOT11_AP_CHANNEL_CURRENTLY_NOT_AVAILABLE",
+ "STATUS_NDIS_DOT11_AP_BAND_CURRENTLY_NOT_AVAILABLE",
+ "STATUS_NDIS_DOT11_AP_CHANNEL_NOT_ALLOWED",
+ "STATUS_NDIS_DOT11_AP_BAND_NOT_ALLOWED",
+ "STATUS_QUIC_HANDSHAKE_FAILURE",
+ "STATUS_QUIC_VER_NEG_FAILURE",
+ "STATUS_TPM_ERROR_MASK",
+ "STATUS_TPM_AUTHFAIL",
+ "STATUS_TPM_BADINDEX",
+ "STATUS_TPM_BAD_PARAMETER",
+ "STATUS_TPM_AUDITFAILURE",
+ "STATUS_TPM_CLEAR_DISABLED",
+ "STATUS_TPM_DEACTIVATED",
+ "STATUS_TPM_DISABLED",
+ "STATUS_TPM_DISABLED_CMD",
+ "STATUS_TPM_FAIL",
+ "STATUS_TPM_BAD_ORDINAL",
+ "STATUS_TPM_INSTALL_DISABLED",
+ "STATUS_TPM_INVALID_KEYHANDLE",
+ "STATUS_TPM_KEYNOTFOUND",
+ "STATUS_TPM_INAPPROPRIATE_ENC",
+ "STATUS_TPM_MIGRATEFAIL",
+ "STATUS_TPM_INVALID_PCR_INFO",
+ "STATUS_TPM_NOSPACE",
+ "STATUS_TPM_NOSRK",
+ "STATUS_TPM_NOTSEALED_BLOB",
+ "STATUS_TPM_OWNER_SET",
+ "STATUS_TPM_RESOURCES",
+ "STATUS_TPM_SHORTRANDOM",
+ "STATUS_TPM_SIZE",
+ "STATUS_TPM_WRONGPCRVAL",
+ "STATUS_TPM_BAD_PARAM_SIZE",
+ "STATUS_TPM_SHA_THREAD",
+ "STATUS_TPM_SHA_ERROR",
+ "STATUS_TPM_FAILEDSELFTEST",
+ "STATUS_TPM_AUTH2FAIL",
+ "STATUS_TPM_BADTAG",
+ "STATUS_TPM_IOERROR",
+ "STATUS_TPM_ENCRYPT_ERROR",
+ "STATUS_TPM_DECRYPT_ERROR",
+ "STATUS_TPM_INVALID_AUTHHANDLE",
+ "STATUS_TPM_NO_ENDORSEMENT",
+ "STATUS_TPM_INVALID_KEYUSAGE",
+ "STATUS_TPM_WRONG_ENTITYTYPE",
+ "STATUS_TPM_INVALID_POSTINIT",
+ "STATUS_TPM_INAPPROPRIATE_SIG",
+ "STATUS_TPM_BAD_KEY_PROPERTY",
+ "STATUS_TPM_BAD_MIGRATION",
+ "STATUS_TPM_BAD_SCHEME",
+ "STATUS_TPM_BAD_DATASIZE",
+ "STATUS_TPM_BAD_MODE",
+ "STATUS_TPM_BAD_PRESENCE",
+ "STATUS_TPM_BAD_VERSION",
+ "STATUS_TPM_NO_WRAP_TRANSPORT",
+ "STATUS_TPM_AUDITFAIL_UNSUCCESSFUL",
+ "STATUS_TPM_AUDITFAIL_SUCCESSFUL",
+ "STATUS_TPM_NOTRESETABLE",
+ "STATUS_TPM_NOTLOCAL",
+ "STATUS_TPM_BAD_TYPE",
+ "STATUS_TPM_INVALID_RESOURCE",
+ "STATUS_TPM_NOTFIPS",
+ "STATUS_TPM_INVALID_FAMILY",
+ "STATUS_TPM_NO_NV_PERMISSION",
+ "STATUS_TPM_REQUIRES_SIGN",
+ "STATUS_TPM_KEY_NOTSUPPORTED",
+ "STATUS_TPM_AUTH_CONFLICT",
+ "STATUS_TPM_AREA_LOCKED",
+ "STATUS_TPM_BAD_LOCALITY",
+ "STATUS_TPM_READ_ONLY",
+ "STATUS_TPM_PER_NOWRITE",
+ "STATUS_TPM_FAMILYCOUNT",
+ "STATUS_TPM_WRITE_LOCKED",
+ "STATUS_TPM_BAD_ATTRIBUTES",
+ "STATUS_TPM_INVALID_STRUCTURE",
+ "STATUS_TPM_KEY_OWNER_CONTROL",
+ "STATUS_TPM_BAD_COUNTER",
+ "STATUS_TPM_NOT_FULLWRITE",
+ "STATUS_TPM_CONTEXT_GAP",
+ "STATUS_TPM_MAXNVWRITES",
+ "STATUS_TPM_NOOPERATOR",
+ "STATUS_TPM_RESOURCEMISSING",
+ "STATUS_TPM_DELEGATE_LOCK",
+ "STATUS_TPM_DELEGATE_FAMILY",
+ "STATUS_TPM_DELEGATE_ADMIN",
+ "STATUS_TPM_TRANSPORT_NOTEXCLUSIVE",
+ "STATUS_TPM_OWNER_CONTROL",
+ "STATUS_TPM_DAA_RESOURCES",
+ "STATUS_TPM_DAA_INPUT_DATA0",
+ "STATUS_TPM_DAA_INPUT_DATA1",
+ "STATUS_TPM_DAA_ISSUER_SETTINGS",
+ "STATUS_TPM_DAA_TPM_SETTINGS",
+ "STATUS_TPM_DAA_STAGE",
+ "STATUS_TPM_DAA_ISSUER_VALIDITY",
+ "STATUS_TPM_DAA_WRONG_W",
+ "STATUS_TPM_BAD_HANDLE",
+ "STATUS_TPM_BAD_DELEGATE",
+ "STATUS_TPM_BADCONTEXT",
+ "STATUS_TPM_TOOMANYCONTEXTS",
+ "STATUS_TPM_MA_TICKET_SIGNATURE",
+ "STATUS_TPM_MA_DESTINATION",
+ "STATUS_TPM_MA_SOURCE",
+ "STATUS_TPM_MA_AUTHORITY",
+ "STATUS_TPM_PERMANENTEK",
+ "STATUS_TPM_BAD_SIGNATURE",
+ "STATUS_TPM_NOCONTEXTSPACE",
+ "STATUS_TPM_20_E_ASYMMETRIC",
+ "STATUS_TPM_20_E_ATTRIBUTES",
+ "STATUS_TPM_20_E_HASH",
+ "STATUS_TPM_20_E_VALUE",
+ "STATUS_TPM_20_E_HIERARCHY",
+ "STATUS_TPM_20_E_KEY_SIZE",
+ "STATUS_TPM_20_E_MGF",
+ "STATUS_TPM_20_E_MODE",
+ "STATUS_TPM_20_E_TYPE",
+ "STATUS_TPM_20_E_HANDLE",
+ "STATUS_TPM_20_E_KDF",
+ "STATUS_TPM_20_E_RANGE",
+ "STATUS_TPM_20_E_AUTH_FAIL",
+ "STATUS_TPM_20_E_NONCE",
+ "STATUS_TPM_20_E_PP",
+ "STATUS_TPM_20_E_SCHEME",
+ "STATUS_TPM_20_E_SIZE",
+ "STATUS_TPM_20_E_SYMMETRIC",
+ "STATUS_TPM_20_E_TAG",
+ "STATUS_TPM_20_E_SELECTOR",
+ "STATUS_TPM_20_E_INSUFFICIENT",
+ "STATUS_TPM_20_E_SIGNATURE",
+ "STATUS_TPM_20_E_KEY",
+ "STATUS_TPM_20_E_POLICY_FAIL",
+ "STATUS_TPM_20_E_INTEGRITY",
+ "STATUS_TPM_20_E_TICKET",
+ "STATUS_TPM_20_E_RESERVED_BITS",
+ "STATUS_TPM_20_E_BAD_AUTH",
+ "STATUS_TPM_20_E_EXPIRED",
+ "STATUS_TPM_20_E_POLICY_CC",
+ "STATUS_TPM_20_E_BINDING",
+ "STATUS_TPM_20_E_CURVE",
+ "STATUS_TPM_20_E_ECC_POINT",
+ "STATUS_TPM_20_E_INITIALIZE",
+ "STATUS_TPM_20_E_FAILURE",
+ "STATUS_TPM_20_E_SEQUENCE",
+ "STATUS_TPM_20_E_PRIVATE",
+ "STATUS_TPM_20_E_HMAC",
+ "STATUS_TPM_20_E_DISABLED",
+ "STATUS_TPM_20_E_EXCLUSIVE",
+ "STATUS_TPM_20_E_ECC_CURVE",
+ "STATUS_TPM_20_E_AUTH_TYPE",
+ "STATUS_TPM_20_E_AUTH_MISSING",
+ "STATUS_TPM_20_E_POLICY",
+ "STATUS_TPM_20_E_PCR",
+ "STATUS_TPM_20_E_PCR_CHANGED",
+ "STATUS_TPM_20_E_UPGRADE",
+ "STATUS_TPM_20_E_TOO_MANY_CONTEXTS",
+ "STATUS_TPM_20_E_AUTH_UNAVAILABLE",
+ "STATUS_TPM_20_E_REBOOT",
+ "STATUS_TPM_20_E_UNBALANCED",
+ "STATUS_TPM_20_E_COMMAND_SIZE",
+ "STATUS_TPM_20_E_COMMAND_CODE",
+ "STATUS_TPM_20_E_AUTHSIZE",
+ "STATUS_TPM_20_E_AUTH_CONTEXT",
+ "STATUS_TPM_20_E_NV_RANGE",
+ "STATUS_TPM_20_E_NV_SIZE",
+ "STATUS_TPM_20_E_NV_LOCKED",
+ "STATUS_TPM_20_E_NV_AUTHORIZATION",
+ "STATUS_TPM_20_E_NV_UNINITIALIZED",
+ "STATUS_TPM_20_E_NV_SPACE",
+ "STATUS_TPM_20_E_NV_DEFINED",
+ "STATUS_TPM_20_E_BAD_CONTEXT",
+ "STATUS_TPM_20_E_CPHASH",
+ "STATUS_TPM_20_E_PARENT",
+ "STATUS_TPM_20_E_NEEDS_TEST",
+ "STATUS_TPM_20_E_NO_RESULT",
+ "STATUS_TPM_20_E_SENSITIVE",
+ "STATUS_TPM_COMMAND_BLOCKED",
+ "STATUS_TPM_INVALID_HANDLE",
+ "STATUS_TPM_DUPLICATE_VHANDLE",
+ "STATUS_TPM_EMBEDDED_COMMAND_BLOCKED",
+ "STATUS_TPM_EMBEDDED_COMMAND_UNSUPPORTED",
+ "STATUS_TPM_RETRY",
+ "STATUS_TPM_NEEDS_SELFTEST",
+ "STATUS_TPM_DOING_SELFTEST",
+ "STATUS_TPM_DEFEND_LOCK_RUNNING",
+ "STATUS_TPM_COMMAND_CANCELED",
+ "STATUS_TPM_TOO_MANY_CONTEXTS",
+ "STATUS_TPM_NOT_FOUND",
+ "STATUS_TPM_ACCESS_DENIED",
+ "STATUS_TPM_INSUFFICIENT_BUFFER",
+ "STATUS_TPM_PPI_FUNCTION_UNSUPPORTED",
+ "STATUS_PCP_ERROR_MASK",
+ "STATUS_PCP_DEVICE_NOT_READY",
+ "STATUS_PCP_INVALID_HANDLE",
+ "STATUS_PCP_INVALID_PARAMETER",
+ "STATUS_PCP_FLAG_NOT_SUPPORTED",
+ "STATUS_PCP_NOT_SUPPORTED",
+ "STATUS_PCP_BUFFER_TOO_SMALL",
+ "STATUS_PCP_INTERNAL_ERROR",
+ "STATUS_PCP_AUTHENTICATION_FAILED",
+ "STATUS_PCP_AUTHENTICATION_IGNORED",
+ "STATUS_PCP_POLICY_NOT_FOUND",
+ "STATUS_PCP_PROFILE_NOT_FOUND",
+ "STATUS_PCP_VALIDATION_FAILED",
+ "STATUS_PCP_DEVICE_NOT_FOUND",
+ "STATUS_PCP_WRONG_PARENT",
+ "STATUS_PCP_KEY_NOT_LOADED",
+ "STATUS_PCP_NO_KEY_CERTIFICATION",
+ "STATUS_PCP_KEY_NOT_FINALIZED",
+ "STATUS_PCP_ATTESTATION_CHALLENGE_NOT_SET",
+ "STATUS_PCP_NOT_PCR_BOUND",
+ "STATUS_PCP_KEY_ALREADY_FINALIZED",
+ "STATUS_PCP_KEY_USAGE_POLICY_NOT_SUPPORTED",
+ "STATUS_PCP_KEY_USAGE_POLICY_INVALID",
+ "STATUS_PCP_SOFT_KEY_ERROR",
+ "STATUS_PCP_KEY_NOT_AUTHENTICATED",
+ "STATUS_PCP_KEY_NOT_AIK",
+ "STATUS_PCP_KEY_NOT_SIGNING_KEY",
+ "STATUS_PCP_LOCKED_OUT",
+ "STATUS_PCP_CLAIM_TYPE_NOT_SUPPORTED",
+ "STATUS_PCP_TPM_VERSION_NOT_SUPPORTED",
+ "STATUS_PCP_BUFFER_LENGTH_MISMATCH",
+ "STATUS_PCP_IFX_RSA_KEY_CREATION_BLOCKED",
+ "STATUS_PCP_TICKET_MISSING",
+ "STATUS_PCP_RAW_POLICY_NOT_SUPPORTED",
+ "STATUS_PCP_KEY_HANDLE_INVALIDATED",
+ "STATUS_RTPM_NO_RESULT",
+ "STATUS_RTPM_PCR_READ_INCOMPLETE",
+ "STATUS_RTPM_INVALID_CONTEXT",
+ "STATUS_RTPM_UNSUPPORTED_CMD",
+ "STATUS_TPM_ZERO_EXHAUST_ENABLED",
+ "STATUS_HV_INVALID_HYPERCALL_CODE",
+ "STATUS_HV_INVALID_HYPERCALL_INPUT",
+ "STATUS_HV_INVALID_ALIGNMENT",
+ "STATUS_HV_INVALID_PARAMETER",
+ "STATUS_HV_ACCESS_DENIED",
+ "STATUS_HV_INVALID_PARTITION_STATE",
+ "STATUS_HV_OPERATION_DENIED",
+ "STATUS_HV_UNKNOWN_PROPERTY",
+ "STATUS_HV_PROPERTY_VALUE_OUT_OF_RANGE",
+ "STATUS_HV_INSUFFICIENT_MEMORY",
+ "STATUS_HV_PARTITION_TOO_DEEP",
+ "STATUS_HV_INVALID_PARTITION_ID",
+ "STATUS_HV_INVALID_VP_INDEX",
+ "STATUS_HV_INVALID_PORT_ID",
+ "STATUS_HV_INVALID_CONNECTION_ID",
+ "STATUS_HV_INSUFFICIENT_BUFFERS",
+ "STATUS_HV_NOT_ACKNOWLEDGED",
+ "STATUS_HV_INVALID_VP_STATE",
+ "STATUS_HV_ACKNOWLEDGED",
+ "STATUS_HV_INVALID_SAVE_RESTORE_STATE",
+ "STATUS_HV_INVALID_SYNIC_STATE",
+ "STATUS_HV_OBJECT_IN_USE",
+ "STATUS_HV_INVALID_PROXIMITY_DOMAIN_INFO",
+ "STATUS_HV_NO_DATA",
+ "STATUS_HV_INACTIVE",
+ "STATUS_HV_NO_RESOURCES",
+ "STATUS_HV_FEATURE_UNAVAILABLE",
+ "STATUS_HV_INSUFFICIENT_BUFFER",
+ "STATUS_HV_INSUFFICIENT_DEVICE_DOMAINS",
+ "STATUS_HV_CPUID_FEATURE_VALIDATION_ERROR",
+ "STATUS_HV_CPUID_XSAVE_FEATURE_VALIDATION_ERROR",
+ "STATUS_HV_PROCESSOR_STARTUP_TIMEOUT",
+ "STATUS_HV_SMX_ENABLED",
+ "STATUS_HV_INVALID_LP_INDEX",
+ "STATUS_HV_INVALID_REGISTER_VALUE",
+ "STATUS_HV_INVALID_VTL_STATE",
+ "STATUS_HV_NX_NOT_DETECTED",
+ "STATUS_HV_INVALID_DEVICE_ID",
+ "STATUS_HV_INVALID_DEVICE_STATE",
+ "STATUS_HV_PAGE_REQUEST_INVALID",
+ "STATUS_HV_INVALID_CPU_GROUP_ID",
+ "STATUS_HV_INVALID_CPU_GROUP_STATE",
+ "STATUS_HV_OPERATION_FAILED",
+ "STATUS_HV_NOT_ALLOWED_WITH_NESTED_VIRT_ACTIVE",
+ "STATUS_HV_INSUFFICIENT_ROOT_MEMORY",
+ "STATUS_HV_EVENT_BUFFER_ALREADY_FREED",
+ "STATUS_HV_INSUFFICIENT_CONTIGUOUS_MEMORY",
+ "STATUS_HV_NOT_PRESENT",
+ "STATUS_IPSEC_BAD_SPI",
+ "STATUS_IPSEC_SA_LIFETIME_EXPIRED",
+ "STATUS_IPSEC_WRONG_SA",
+ "STATUS_IPSEC_REPLAY_CHECK_FAILED",
+ "STATUS_IPSEC_INVALID_PACKET",
+ "STATUS_IPSEC_INTEGRITY_CHECK_FAILED",
+ "STATUS_IPSEC_CLEAR_TEXT_DROP",
+ "STATUS_IPSEC_AUTH_FIREWALL_DROP",
+ "STATUS_IPSEC_THROTTLE_DROP",
+ "STATUS_IPSEC_DOSP_BLOCK",
+ "STATUS_IPSEC_DOSP_RECEIVED_MULTICAST",
+ "STATUS_IPSEC_DOSP_INVALID_PACKET",
+ "STATUS_IPSEC_DOSP_STATE_LOOKUP_FAILED",
+ "STATUS_IPSEC_DOSP_MAX_ENTRIES",
+ "STATUS_IPSEC_DOSP_KEYMOD_NOT_ALLOWED",
+ "STATUS_IPSEC_DOSP_MAX_PER_IP_RATELIMIT_QUEUES",
+ "STATUS_VID_DUPLICATE_HANDLER",
+ "STATUS_VID_TOO_MANY_HANDLERS",
+ "STATUS_VID_QUEUE_FULL",
+ "STATUS_VID_HANDLER_NOT_PRESENT",
+ "STATUS_VID_INVALID_OBJECT_NAME",
+ "STATUS_VID_PARTITION_NAME_TOO_LONG",
+ "STATUS_VID_MESSAGE_QUEUE_NAME_TOO_LONG",
+ "STATUS_VID_PARTITION_ALREADY_EXISTS",
+ "STATUS_VID_PARTITION_DOES_NOT_EXIST",
+ "STATUS_VID_PARTITION_NAME_NOT_FOUND",
+ "STATUS_VID_MESSAGE_QUEUE_ALREADY_EXISTS",
+ "STATUS_VID_EXCEEDED_MBP_ENTRY_MAP_LIMIT",
+ "STATUS_VID_MB_STILL_REFERENCED",
+ "STATUS_VID_CHILD_GPA_PAGE_SET_CORRUPTED",
+ "STATUS_VID_INVALID_NUMA_SETTINGS",
+ "STATUS_VID_INVALID_NUMA_NODE_INDEX",
+ "STATUS_VID_NOTIFICATION_QUEUE_ALREADY_ASSOCIATED",
+ "STATUS_VID_INVALID_MEMORY_BLOCK_HANDLE",
+ "STATUS_VID_PAGE_RANGE_OVERFLOW",
+ "STATUS_VID_INVALID_MESSAGE_QUEUE_HANDLE",
+ "STATUS_VID_INVALID_GPA_RANGE_HANDLE",
+ "STATUS_VID_NO_MEMORY_BLOCK_NOTIFICATION_QUEUE",
+ "STATUS_VID_MEMORY_BLOCK_LOCK_COUNT_EXCEEDED",
+ "STATUS_VID_INVALID_PPM_HANDLE",
+ "STATUS_VID_MBPS_ARE_LOCKED",
+ "STATUS_VID_MESSAGE_QUEUE_CLOSED",
+ "STATUS_VID_VIRTUAL_PROCESSOR_LIMIT_EXCEEDED",
+ "STATUS_VID_STOP_PENDING",
+ "STATUS_VID_INVALID_PROCESSOR_STATE",
+ "STATUS_VID_EXCEEDED_KM_CONTEXT_COUNT_LIMIT",
+ "STATUS_VID_KM_INTERFACE_ALREADY_INITIALIZED",
+ "STATUS_VID_MB_PROPERTY_ALREADY_SET_RESET",
+ "STATUS_VID_MMIO_RANGE_DESTROYED",
+ "STATUS_VID_INVALID_CHILD_GPA_PAGE_SET",
+ "STATUS_VID_RESERVE_PAGE_SET_IS_BEING_USED",
+ "STATUS_VID_RESERVE_PAGE_SET_TOO_SMALL",
+ "STATUS_VID_MBP_ALREADY_LOCKED_USING_RESERVED_PAGE",
+ "STATUS_VID_MBP_COUNT_EXCEEDED_LIMIT",
+ "STATUS_VID_SAVED_STATE_CORRUPT",
+ "STATUS_VID_SAVED_STATE_UNRECOGNIZED_ITEM",
+ "STATUS_VID_SAVED_STATE_INCOMPATIBLE",
+ "STATUS_VID_VTL_ACCESS_DENIED",
+ "STATUS_VOLMGR_DATABASE_FULL",
+ "STATUS_VOLMGR_DISK_CONFIGURATION_CORRUPTED",
+ "STATUS_VOLMGR_DISK_CONFIGURATION_NOT_IN_SYNC",
+ "STATUS_VOLMGR_PACK_CONFIG_UPDATE_FAILED",
+ "STATUS_VOLMGR_DISK_CONTAINS_NON_SIMPLE_VOLUME",
+ "STATUS_VOLMGR_DISK_DUPLICATE",
+ "STATUS_VOLMGR_DISK_DYNAMIC",
+ "STATUS_VOLMGR_DISK_ID_INVALID",
+ "STATUS_VOLMGR_DISK_INVALID",
+ "STATUS_VOLMGR_DISK_LAST_VOTER",
+ "STATUS_VOLMGR_DISK_LAYOUT_INVALID",
+ "STATUS_VOLMGR_DISK_LAYOUT_NON_BASIC_BETWEEN_BASIC_PARTITIONS",
+ "STATUS_VOLMGR_DISK_LAYOUT_NOT_CYLINDER_ALIGNED",
+ "STATUS_VOLMGR_DISK_LAYOUT_PARTITIONS_TOO_SMALL",
+ "STATUS_VOLMGR_DISK_LAYOUT_PRIMARY_BETWEEN_LOGICAL_PARTITIONS",
+ "STATUS_VOLMGR_DISK_LAYOUT_TOO_MANY_PARTITIONS",
+ "STATUS_VOLMGR_DISK_MISSING",
+ "STATUS_VOLMGR_DISK_NOT_EMPTY",
+ "STATUS_VOLMGR_DISK_NOT_ENOUGH_SPACE",
+ "STATUS_VOLMGR_DISK_REVECTORING_FAILED",
+ "STATUS_VOLMGR_DISK_SECTOR_SIZE_INVALID",
+ "STATUS_VOLMGR_DISK_SET_NOT_CONTAINED",
+ "STATUS_VOLMGR_DISK_USED_BY_MULTIPLE_MEMBERS",
+ "STATUS_VOLMGR_DISK_USED_BY_MULTIPLE_PLEXES",
+ "STATUS_VOLMGR_DYNAMIC_DISK_NOT_SUPPORTED",
+ "STATUS_VOLMGR_EXTENT_ALREADY_USED",
+ "STATUS_VOLMGR_EXTENT_NOT_CONTIGUOUS",
+ "STATUS_VOLMGR_EXTENT_NOT_IN_PUBLIC_REGION",
+ "STATUS_VOLMGR_EXTENT_NOT_SECTOR_ALIGNED",
+ "STATUS_VOLMGR_EXTENT_OVERLAPS_EBR_PARTITION",
+ "STATUS_VOLMGR_EXTENT_VOLUME_LENGTHS_DO_NOT_MATCH",
+ "STATUS_VOLMGR_FAULT_TOLERANT_NOT_SUPPORTED",
+ "STATUS_VOLMGR_INTERLEAVE_LENGTH_INVALID",
+ "STATUS_VOLMGR_MAXIMUM_REGISTERED_USERS",
+ "STATUS_VOLMGR_MEMBER_IN_SYNC",
+ "STATUS_VOLMGR_MEMBER_INDEX_DUPLICATE",
+ "STATUS_VOLMGR_MEMBER_INDEX_INVALID",
+ "STATUS_VOLMGR_MEMBER_MISSING",
+ "STATUS_VOLMGR_MEMBER_NOT_DETACHED",
+ "STATUS_VOLMGR_MEMBER_REGENERATING",
+ "STATUS_VOLMGR_ALL_DISKS_FAILED",
+ "STATUS_VOLMGR_NO_REGISTERED_USERS",
+ "STATUS_VOLMGR_NO_SUCH_USER",
+ "STATUS_VOLMGR_NOTIFICATION_RESET",
+ "STATUS_VOLMGR_NUMBER_OF_MEMBERS_INVALID",
+ "STATUS_VOLMGR_NUMBER_OF_PLEXES_INVALID",
+ "STATUS_VOLMGR_PACK_DUPLICATE",
+ "STATUS_VOLMGR_PACK_ID_INVALID",
+ "STATUS_VOLMGR_PACK_INVALID",
+ "STATUS_VOLMGR_PACK_NAME_INVALID",
+ "STATUS_VOLMGR_PACK_OFFLINE",
+ "STATUS_VOLMGR_PACK_HAS_QUORUM",
+ "STATUS_VOLMGR_PACK_WITHOUT_QUORUM",
+ "STATUS_VOLMGR_PARTITION_STYLE_INVALID",
+ "STATUS_VOLMGR_PARTITION_UPDATE_FAILED",
+ "STATUS_VOLMGR_PLEX_IN_SYNC",
+ "STATUS_VOLMGR_PLEX_INDEX_DUPLICATE",
+ "STATUS_VOLMGR_PLEX_INDEX_INVALID",
+ "STATUS_VOLMGR_PLEX_LAST_ACTIVE",
+ "STATUS_VOLMGR_PLEX_MISSING",
+ "STATUS_VOLMGR_PLEX_REGENERATING",
+ "STATUS_VOLMGR_PLEX_TYPE_INVALID",
+ "STATUS_VOLMGR_PLEX_NOT_RAID5",
+ "STATUS_VOLMGR_PLEX_NOT_SIMPLE",
+ "STATUS_VOLMGR_STRUCTURE_SIZE_INVALID",
+ "STATUS_VOLMGR_TOO_MANY_NOTIFICATION_REQUESTS",
+ "STATUS_VOLMGR_TRANSACTION_IN_PROGRESS",
+ "STATUS_VOLMGR_UNEXPECTED_DISK_LAYOUT_CHANGE",
+ "STATUS_VOLMGR_VOLUME_CONTAINS_MISSING_DISK",
+ "STATUS_VOLMGR_VOLUME_ID_INVALID",
+ "STATUS_VOLMGR_VOLUME_LENGTH_INVALID",
+ "STATUS_VOLMGR_VOLUME_LENGTH_NOT_SECTOR_SIZE_MULTIPLE",
+ "STATUS_VOLMGR_VOLUME_NOT_MIRRORED",
+ "STATUS_VOLMGR_VOLUME_NOT_RETAINED",
+ "STATUS_VOLMGR_VOLUME_OFFLINE",
+ "STATUS_VOLMGR_VOLUME_RETAINED",
+ "STATUS_VOLMGR_NUMBER_OF_EXTENTS_INVALID",
+ "STATUS_VOLMGR_DIFFERENT_SECTOR_SIZE",
+ "STATUS_VOLMGR_BAD_BOOT_DISK",
+ "STATUS_VOLMGR_PACK_CONFIG_OFFLINE",
+ "STATUS_VOLMGR_PACK_CONFIG_ONLINE",
+ "STATUS_VOLMGR_NOT_PRIMARY_PACK",
+ "STATUS_VOLMGR_PACK_LOG_UPDATE_FAILED",
+ "STATUS_VOLMGR_NUMBER_OF_DISKS_IN_PLEX_INVALID",
+ "STATUS_VOLMGR_NUMBER_OF_DISKS_IN_MEMBER_INVALID",
+ "STATUS_VOLMGR_VOLUME_MIRRORED",
+ "STATUS_VOLMGR_PLEX_NOT_SIMPLE_SPANNED",
+ "STATUS_VOLMGR_NO_VALID_LOG_COPIES",
+ "STATUS_VOLMGR_PRIMARY_PACK_PRESENT",
+ "STATUS_VOLMGR_NUMBER_OF_DISKS_INVALID",
+ "STATUS_VOLMGR_MIRROR_NOT_SUPPORTED",
+ "STATUS_VOLMGR_RAID5_NOT_SUPPORTED",
+ "STATUS_BCD_TOO_MANY_ELEMENTS",
+ "STATUS_VHD_DRIVE_FOOTER_MISSING",
+ "STATUS_VHD_DRIVE_FOOTER_CHECKSUM_MISMATCH",
+ "STATUS_VHD_DRIVE_FOOTER_CORRUPT",
+ "STATUS_VHD_FORMAT_UNKNOWN",
+ "STATUS_VHD_FORMAT_UNSUPPORTED_VERSION",
+ "STATUS_VHD_SPARSE_HEADER_CHECKSUM_MISMATCH",
+ "STATUS_VHD_SPARSE_HEADER_UNSUPPORTED_VERSION",
+ "STATUS_VHD_SPARSE_HEADER_CORRUPT",
+ "STATUS_VHD_BLOCK_ALLOCATION_FAILURE",
+ "STATUS_VHD_BLOCK_ALLOCATION_TABLE_CORRUPT",
+ "STATUS_VHD_INVALID_BLOCK_SIZE",
+ "STATUS_VHD_BITMAP_MISMATCH",
+ "STATUS_VHD_PARENT_VHD_NOT_FOUND",
+ "STATUS_VHD_CHILD_PARENT_ID_MISMATCH",
+ "STATUS_VHD_CHILD_PARENT_TIMESTAMP_MISMATCH",
+ "STATUS_VHD_METADATA_READ_FAILURE",
+ "STATUS_VHD_METADATA_WRITE_FAILURE",
+ "STATUS_VHD_INVALID_SIZE",
+ "STATUS_VHD_INVALID_FILE_SIZE",
+ "STATUS_VIRTDISK_PROVIDER_NOT_FOUND",
+ "STATUS_VIRTDISK_NOT_VIRTUAL_DISK",
+ "STATUS_VHD_PARENT_VHD_ACCESS_DENIED",
+ "STATUS_VHD_CHILD_PARENT_SIZE_MISMATCH",
+ "STATUS_VHD_DIFFERENCING_CHAIN_CYCLE_DETECTED",
+ "STATUS_VHD_DIFFERENCING_CHAIN_ERROR_IN_PARENT",
+ "STATUS_VIRTUAL_DISK_LIMITATION",
+ "STATUS_VHD_INVALID_TYPE",
+ "STATUS_VHD_INVALID_STATE",
+ "STATUS_VIRTDISK_UNSUPPORTED_DISK_SECTOR_SIZE",
+ "STATUS_VIRTDISK_DISK_ALREADY_OWNED",
+ "STATUS_VIRTDISK_DISK_ONLINE_AND_WRITABLE",
+ "STATUS_CTLOG_TRACKING_NOT_INITIALIZED",
+ "STATUS_CTLOG_LOGFILE_SIZE_EXCEEDED_MAXSIZE",
+ "STATUS_CTLOG_VHD_CHANGED_OFFLINE",
+ "STATUS_CTLOG_INVALID_TRACKING_STATE",
+ "STATUS_CTLOG_INCONSISTENT_TRACKING_FILE",
+ "STATUS_VHD_METADATA_FULL",
+ "STATUS_VHD_INVALID_CHANGE_TRACKING_ID",
+ "STATUS_VHD_CHANGE_TRACKING_DISABLED",
+ "STATUS_VHD_MISSING_CHANGE_TRACKING_INFORMATION",
+ "STATUS_VHD_RESIZE_WOULD_TRUNCATE_DATA",
+ "STATUS_VHD_COULD_NOT_COMPUTE_MINIMUM_VIRTUAL_SIZE",
+ "STATUS_VHD_ALREADY_AT_OR_BELOW_MINIMUM_VIRTUAL_SIZE",
+ "STATUS_RKF_KEY_NOT_FOUND",
+ "STATUS_RKF_DUPLICATE_KEY",
+ "STATUS_RKF_BLOB_FULL",
+ "STATUS_RKF_STORE_FULL",
+ "STATUS_RKF_FILE_BLOCKED",
+ "STATUS_RKF_ACTIVE_KEY",
+ "STATUS_RDBSS_RESTART_OPERATION",
+ "STATUS_RDBSS_CONTINUE_OPERATION",
+ "STATUS_RDBSS_POST_OPERATION",
+ "STATUS_RDBSS_RETRY_LOOKUP",
+ "STATUS_BTH_ATT_INVALID_HANDLE",
+ "STATUS_BTH_ATT_READ_NOT_PERMITTED",
+ "STATUS_BTH_ATT_WRITE_NOT_PERMITTED",
+ "STATUS_BTH_ATT_INVALID_PDU",
+ "STATUS_BTH_ATT_INSUFFICIENT_AUTHENTICATION",
+ "STATUS_BTH_ATT_REQUEST_NOT_SUPPORTED",
+ "STATUS_BTH_ATT_INVALID_OFFSET",
+ "STATUS_BTH_ATT_INSUFFICIENT_AUTHORIZATION",
+ "STATUS_BTH_ATT_PREPARE_QUEUE_FULL",
+ "STATUS_BTH_ATT_ATTRIBUTE_NOT_FOUND",
+ "STATUS_BTH_ATT_ATTRIBUTE_NOT_LONG",
+ "STATUS_BTH_ATT_INSUFFICIENT_ENCRYPTION_KEY_SIZE",
+ "STATUS_BTH_ATT_INVALID_ATTRIBUTE_VALUE_LENGTH",
+ "STATUS_BTH_ATT_UNLIKELY",
+ "STATUS_BTH_ATT_INSUFFICIENT_ENCRYPTION",
+ "STATUS_BTH_ATT_UNSUPPORTED_GROUP_TYPE",
+ "STATUS_BTH_ATT_INSUFFICIENT_RESOURCES",
+ "STATUS_BTH_ATT_UNKNOWN_ERROR",
+ "STATUS_SECUREBOOT_ROLLBACK_DETECTED",
+ "STATUS_SECUREBOOT_POLICY_VIOLATION",
+ "STATUS_SECUREBOOT_INVALID_POLICY",
+ "STATUS_SECUREBOOT_POLICY_PUBLISHER_NOT_FOUND",
+ "STATUS_SECUREBOOT_POLICY_NOT_SIGNED",
+ "STATUS_SECUREBOOT_FILE_REPLACED",
+ "STATUS_SECUREBOOT_POLICY_NOT_AUTHORIZED",
+ "STATUS_SECUREBOOT_POLICY_UNKNOWN",
+ "STATUS_SECUREBOOT_POLICY_MISSING_ANTIROLLBACKVERSION",
+ "STATUS_SECUREBOOT_PLATFORM_ID_MISMATCH",
+ "STATUS_SECUREBOOT_POLICY_ROLLBACK_DETECTED",
+ "STATUS_SECUREBOOT_POLICY_UPGRADE_MISMATCH",
+ "STATUS_SECUREBOOT_REQUIRED_POLICY_FILE_MISSING",
+ "STATUS_SECUREBOOT_NOT_BASE_POLICY",
+ "STATUS_SECUREBOOT_NOT_SUPPLEMENTAL_POLICY",
+ "STATUS_AUDIO_ENGINE_NODE_NOT_FOUND",
+ "STATUS_HDAUDIO_EMPTY_CONNECTION_LIST",
+ "STATUS_HDAUDIO_CONNECTION_LIST_NOT_SUPPORTED",
+ "STATUS_HDAUDIO_NO_LOGICAL_DEVICES_CREATED",
+ "STATUS_HDAUDIO_NULL_LINKED_LIST_ENTRY",
+ "STATUS_VSM_NOT_INITIALIZED",
+ "STATUS_VSM_DMA_PROTECTION_NOT_IN_USE",
+ "STATUS_VOLSNAP_BOOTFILE_NOT_VALID",
+ "STATUS_VOLSNAP_ACTIVATION_TIMEOUT",
+ "STATUS_IO_PREEMPTED",
+ "STATUS_SVHDX_ERROR_STORED",
+ "STATUS_SVHDX_ERROR_NOT_AVAILABLE",
+ "STATUS_SVHDX_UNIT_ATTENTION_AVAILABLE",
+ "STATUS_SVHDX_UNIT_ATTENTION_CAPACITY_DATA_CHANGED",
+ "STATUS_SVHDX_UNIT_ATTENTION_RESERVATIONS_PREEMPTED",
+ "STATUS_SVHDX_UNIT_ATTENTION_RESERVATIONS_RELEASED",
+ "STATUS_SVHDX_UNIT_ATTENTION_REGISTRATIONS_PREEMPTED",
+ "STATUS_SVHDX_UNIT_ATTENTION_OPERATING_DEFINITION_CHANGED",
+ "STATUS_SVHDX_RESERVATION_CONFLICT",
+ "STATUS_SVHDX_WRONG_FILE_TYPE",
+ "STATUS_SVHDX_VERSION_MISMATCH",
+ "STATUS_VHD_SHARED",
+ "STATUS_SVHDX_NO_INITIATOR",
+ "STATUS_VHDSET_BACKING_STORAGE_NOT_FOUND",
+ "STATUS_SMB_NO_PREAUTH_INTEGRITY_HASH_OVERLAP",
+ "STATUS_SMB_BAD_CLUSTER_DIALECT",
+ "STATUS_SMB_GUEST_LOGON_BLOCKED",
+ "STATUS_SPACES_FAULT_DOMAIN_TYPE_INVALID",
+ "STATUS_SPACES_RESILIENCY_TYPE_INVALID",
+ "STATUS_SPACES_DRIVE_SECTOR_SIZE_INVALID",
+ "STATUS_SPACES_DRIVE_REDUNDANCY_INVALID",
+ "STATUS_SPACES_NUMBER_OF_DATA_COPIES_INVALID",
+ "STATUS_SPACES_INTERLEAVE_LENGTH_INVALID",
+ "STATUS_SPACES_NUMBER_OF_COLUMNS_INVALID",
+ "STATUS_SPACES_NOT_ENOUGH_DRIVES",
+ "STATUS_SPACES_EXTENDED_ERROR",
+ "STATUS_SPACES_PROVISIONING_TYPE_INVALID",
+ "STATUS_SPACES_ALLOCATION_SIZE_INVALID",
+ "STATUS_SPACES_ENCLOSURE_AWARE_INVALID",
+ "STATUS_SPACES_WRITE_CACHE_SIZE_INVALID",
+ "STATUS_SPACES_NUMBER_OF_GROUPS_INVALID",
+ "STATUS_SPACES_DRIVE_OPERATIONAL_STATE_INVALID",
+ "STATUS_SPACES_UPDATE_COLUMN_STATE",
+ "STATUS_SPACES_MAP_REQUIRED",
+ "STATUS_SPACES_UNSUPPORTED_VERSION",
+ "STATUS_SPACES_CORRUPT_METADATA",
+ "STATUS_SPACES_DRT_FULL",
+ "STATUS_SPACES_INCONSISTENCY",
+ "STATUS_SPACES_LOG_NOT_READY",
+ "STATUS_SPACES_NO_REDUNDANCY",
+ "STATUS_SPACES_DRIVE_NOT_READY",
+ "STATUS_SPACES_DRIVE_SPLIT",
+ "STATUS_SPACES_DRIVE_LOST_DATA",
+ "STATUS_SPACES_ENTRY_INCOMPLETE",
+ "STATUS_SPACES_ENTRY_INVALID",
+ "STATUS_SPACES_MARK_DIRTY",
+ "STATUS_SECCORE_INVALID_COMMAND",
+ "STATUS_SYSTEM_INTEGRITY_ROLLBACK_DETECTED",
+ "STATUS_SYSTEM_INTEGRITY_POLICY_VIOLATION",
+ "STATUS_SYSTEM_INTEGRITY_INVALID_POLICY",
+ "STATUS_SYSTEM_INTEGRITY_POLICY_NOT_SIGNED",
+ "STATUS_SYSTEM_INTEGRITY_TOO_MANY_POLICIES",
+ "STATUS_SYSTEM_INTEGRITY_SUPPLEMENTAL_POLICY_NOT_AUTHORIZED",
+ "STATUS_NO_APPLICABLE_APP_LICENSES_FOUND",
+ "STATUS_CLIP_LICENSE_NOT_FOUND",
+ "STATUS_CLIP_DEVICE_LICENSE_MISSING",
+ "STATUS_CLIP_LICENSE_INVALID_SIGNATURE",
+ "STATUS_CLIP_KEYHOLDER_LICENSE_MISSING_OR_INVALID",
+ "STATUS_CLIP_LICENSE_EXPIRED",
+ "STATUS_CLIP_LICENSE_SIGNED_BY_UNKNOWN_SOURCE",
+ "STATUS_CLIP_LICENSE_NOT_SIGNED",
+ "STATUS_CLIP_LICENSE_HARDWARE_ID_OUT_OF_TOLERANCE",
+ "STATUS_CLIP_LICENSE_DEVICE_ID_MISMATCH",
+ "STATUS_PLATFORM_MANIFEST_NOT_AUTHORIZED",
+ "STATUS_PLATFORM_MANIFEST_INVALID",
+ "STATUS_PLATFORM_MANIFEST_FILE_NOT_AUTHORIZED",
+ "STATUS_PLATFORM_MANIFEST_CATALOG_NOT_AUTHORIZED",
+ "STATUS_PLATFORM_MANIFEST_BINARY_ID_NOT_FOUND",
+ "STATUS_PLATFORM_MANIFEST_NOT_ACTIVE",
+ "STATUS_PLATFORM_MANIFEST_NOT_SIGNED",
+ "STATUS_APPEXEC_CONDITION_NOT_SATISFIED",
+ "STATUS_APPEXEC_HANDLE_INVALIDATED",
+ "STATUS_APPEXEC_INVALID_HOST_GENERATION",
+ "STATUS_APPEXEC_UNEXPECTED_PROCESS_REGISTRATION",
+ "STATUS_APPEXEC_INVALID_HOST_STATE",
+ "STATUS_APPEXEC_NO_DONOR",
+ "STATUS_APPEXEC_HOST_ID_MISMATCH",
+ "STATUS_APPEXEC_UNKNOWN_USER",
+};
+
+const char* NTStatusToString(uint32_t ntstatus) {
+ auto itr = std::find(std::begin(kNTStatusValues),
+ std::end(kNTStatusValues),
+ ntstatus);
+ if (itr == std::end(kNTStatusValues)) {
+ return nullptr;
+ }
+
+ return kNTStatusStrings[itr - std::begin(kNTStatusValues)];
+}
+
+// The content of this array was created from winnt.h in the 10 SDK
+// (version 10.0.19041.0) with the following script:
+//
+// egrep '#define FAST_FAIL_[A-Z_0-9]+\s+[0-9]' winnt.h
+// | tr -d '\r'
+// | sed -r 's@#define FAST_FAIL_([A-Z_0-9]+)\s+([0-9]+).*@\2 \1@'
+// | sed -r 's@([0-9]+) ([A-Z_0-9]+)@ MD_FAST_FAIL_WIN_\2,@'
+// | head -n -1
+static const uint8_t kFastFailValues[] = {
+ MD_FAST_FAIL_WIN_LEGACY_GS_VIOLATION,
+ MD_FAST_FAIL_WIN_VTGUARD_CHECK_FAILURE,
+ MD_FAST_FAIL_WIN_STACK_COOKIE_CHECK_FAILURE,
+ MD_FAST_FAIL_WIN_CORRUPT_LIST_ENTRY,
+ MD_FAST_FAIL_WIN_INCORRECT_STACK,
+ MD_FAST_FAIL_WIN_INVALID_ARG,
+ MD_FAST_FAIL_WIN_GS_COOKIE_INIT,
+ MD_FAST_FAIL_WIN_FATAL_APP_EXIT,
+ MD_FAST_FAIL_WIN_RANGE_CHECK_FAILURE,
+ MD_FAST_FAIL_WIN_UNSAFE_REGISTRY_ACCESS,
+ MD_FAST_FAIL_WIN_GUARD_ICALL_CHECK_FAILURE,
+ MD_FAST_FAIL_WIN_GUARD_WRITE_CHECK_FAILURE,
+ MD_FAST_FAIL_WIN_INVALID_FIBER_SWITCH,
+ MD_FAST_FAIL_WIN_INVALID_SET_OF_CONTEXT,
+ MD_FAST_FAIL_WIN_INVALID_REFERENCE_COUNT,
+ MD_FAST_FAIL_WIN_INVALID_JUMP_BUFFER,
+ MD_FAST_FAIL_WIN_MRDATA_MODIFIED,
+ MD_FAST_FAIL_WIN_CERTIFICATION_FAILURE,
+ MD_FAST_FAIL_WIN_INVALID_EXCEPTION_CHAIN,
+ MD_FAST_FAIL_WIN_CRYPTO_LIBRARY,
+ MD_FAST_FAIL_WIN_INVALID_CALL_IN_DLL_CALLOUT,
+ MD_FAST_FAIL_WIN_INVALID_IMAGE_BASE,
+ MD_FAST_FAIL_WIN_DLOAD_PROTECTION_FAILURE,
+ MD_FAST_FAIL_WIN_UNSAFE_EXTENSION_CALL,
+ MD_FAST_FAIL_WIN_DEPRECATED_SERVICE_INVOKED,
+ MD_FAST_FAIL_WIN_INVALID_BUFFER_ACCESS,
+ MD_FAST_FAIL_WIN_INVALID_BALANCED_TREE,
+ MD_FAST_FAIL_WIN_INVALID_NEXT_THREAD,
+ MD_FAST_FAIL_WIN_GUARD_ICALL_CHECK_SUPPRESSED,
+ MD_FAST_FAIL_WIN_APCS_DISABLED,
+ MD_FAST_FAIL_WIN_INVALID_IDLE_STATE,
+ MD_FAST_FAIL_WIN_MRDATA_PROTECTION_FAILURE,
+ MD_FAST_FAIL_WIN_UNEXPECTED_HEAP_EXCEPTION,
+ MD_FAST_FAIL_WIN_INVALID_LOCK_STATE,
+ MD_FAST_FAIL_WIN_GUARD_JUMPTABLE,
+ MD_FAST_FAIL_WIN_INVALID_LONGJUMP_TARGET,
+ MD_FAST_FAIL_WIN_INVALID_DISPATCH_CONTEXT,
+ MD_FAST_FAIL_WIN_INVALID_THREAD,
+ MD_FAST_FAIL_WIN_INVALID_SYSCALL_NUMBER,
+ MD_FAST_FAIL_WIN_INVALID_FILE_OPERATION,
+ MD_FAST_FAIL_WIN_LPAC_ACCESS_DENIED,
+ MD_FAST_FAIL_WIN_GUARD_SS_FAILURE,
+ MD_FAST_FAIL_WIN_LOADER_CONTINUITY_FAILURE,
+ MD_FAST_FAIL_WIN_GUARD_EXPORT_SUPPRESSION_FAILURE,
+ MD_FAST_FAIL_WIN_INVALID_CONTROL_STACK,
+ MD_FAST_FAIL_WIN_SET_CONTEXT_DENIED,
+ MD_FAST_FAIL_WIN_INVALID_IAT,
+ MD_FAST_FAIL_WIN_HEAP_METADATA_CORRUPTION,
+ MD_FAST_FAIL_WIN_PAYLOAD_RESTRICTION_VIOLATION,
+ MD_FAST_FAIL_WIN_LOW_LABEL_ACCESS_DENIED,
+ MD_FAST_FAIL_WIN_ENCLAVE_CALL_FAILURE,
+ MD_FAST_FAIL_WIN_UNHANDLED_LSS_EXCEPTON,
+ MD_FAST_FAIL_WIN_ADMINLESS_ACCESS_DENIED,
+ MD_FAST_FAIL_WIN_UNEXPECTED_CALL,
+ MD_FAST_FAIL_WIN_CONTROL_INVALID_RETURN_ADDRESS,
+ MD_FAST_FAIL_WIN_UNEXPECTED_HOST_BEHAVIOR,
+ MD_FAST_FAIL_WIN_FLAGS_CORRUPTION,
+ MD_FAST_FAIL_WIN_VEH_CORRUPTION,
+ MD_FAST_FAIL_WIN_ETW_CORRUPTION,
+ MD_FAST_FAIL_WIN_RIO_ABORT,
+ MD_FAST_FAIL_WIN_INVALID_PFN,
+};
+
+// The content of this array was created from winnt.h in the 10 SDK
+// (version 10.0.19041.0) with the following script:
+//
+// egrep '#define FAST_FAIL_[A-Z_0-9]+\s+[0-9]' winnt.h
+// | tr -d '\r'
+// | sed -r 's@#define FAST_FAIL_([A-Z_0-9]+)\s+([0-9]+).*@\2 \1@'
+// | sed -r 's@([0-9]+) ([A-Z_0-9]+)@ "FAST_FAIL_\2",@'
+// | head -n -1
+static const char* kFastFailStrings[] = {
+ "FAST_FAIL_LEGACY_GS_VIOLATION",
+ "FAST_FAIL_VTGUARD_CHECK_FAILURE",
+ "FAST_FAIL_STACK_COOKIE_CHECK_FAILURE",
+ "FAST_FAIL_CORRUPT_LIST_ENTRY",
+ "FAST_FAIL_INCORRECT_STACK",
+ "FAST_FAIL_INVALID_ARG",
+ "FAST_FAIL_GS_COOKIE_INIT",
+ "FAST_FAIL_FATAL_APP_EXIT",
+ "FAST_FAIL_RANGE_CHECK_FAILURE",
+ "FAST_FAIL_UNSAFE_REGISTRY_ACCESS",
+ "FAST_FAIL_GUARD_ICALL_CHECK_FAILURE",
+ "FAST_FAIL_GUARD_WRITE_CHECK_FAILURE",
+ "FAST_FAIL_INVALID_FIBER_SWITCH",
+ "FAST_FAIL_INVALID_SET_OF_CONTEXT",
+ "FAST_FAIL_INVALID_REFERENCE_COUNT",
+ "FAST_FAIL_INVALID_JUMP_BUFFER",
+ "FAST_FAIL_MRDATA_MODIFIED",
+ "FAST_FAIL_CERTIFICATION_FAILURE",
+ "FAST_FAIL_INVALID_EXCEPTION_CHAIN",
+ "FAST_FAIL_CRYPTO_LIBRARY",
+ "FAST_FAIL_INVALID_CALL_IN_DLL_CALLOUT",
+ "FAST_FAIL_INVALID_IMAGE_BASE",
+ "FAST_FAIL_DLOAD_PROTECTION_FAILURE",
+ "FAST_FAIL_UNSAFE_EXTENSION_CALL",
+ "FAST_FAIL_DEPRECATED_SERVICE_INVOKED",
+ "FAST_FAIL_INVALID_BUFFER_ACCESS",
+ "FAST_FAIL_INVALID_BALANCED_TREE",
+ "FAST_FAIL_INVALID_NEXT_THREAD",
+ "FAST_FAIL_GUARD_ICALL_CHECK_SUPPRESSED",
+ "FAST_FAIL_APCS_DISABLED",
+ "FAST_FAIL_INVALID_IDLE_STATE",
+ "FAST_FAIL_MRDATA_PROTECTION_FAILURE",
+ "FAST_FAIL_UNEXPECTED_HEAP_EXCEPTION",
+ "FAST_FAIL_INVALID_LOCK_STATE",
+ "FAST_FAIL_GUARD_JUMPTABLE",
+ "FAST_FAIL_INVALID_LONGJUMP_TARGET",
+ "FAST_FAIL_INVALID_DISPATCH_CONTEXT",
+ "FAST_FAIL_INVALID_THREAD",
+ "FAST_FAIL_INVALID_SYSCALL_NUMBER",
+ "FAST_FAIL_INVALID_FILE_OPERATION",
+ "FAST_FAIL_LPAC_ACCESS_DENIED",
+ "FAST_FAIL_GUARD_SS_FAILURE",
+ "FAST_FAIL_LOADER_CONTINUITY_FAILURE",
+ "FAST_FAIL_GUARD_EXPORT_SUPPRESSION_FAILURE",
+ "FAST_FAIL_INVALID_CONTROL_STACK",
+ "FAST_FAIL_SET_CONTEXT_DENIED",
+ "FAST_FAIL_INVALID_IAT",
+ "FAST_FAIL_HEAP_METADATA_CORRUPTION",
+ "FAST_FAIL_PAYLOAD_RESTRICTION_VIOLATION",
+ "FAST_FAIL_LOW_LABEL_ACCESS_DENIED",
+ "FAST_FAIL_ENCLAVE_CALL_FAILURE",
+ "FAST_FAIL_UNHANDLED_LSS_EXCEPTON",
+ "FAST_FAIL_ADMINLESS_ACCESS_DENIED",
+ "FAST_FAIL_UNEXPECTED_CALL",
+ "FAST_FAIL_CONTROL_INVALID_RETURN_ADDRESS",
+ "FAST_FAIL_UNEXPECTED_HOST_BEHAVIOR",
+ "FAST_FAIL_FLAGS_CORRUPTION",
+ "FAST_FAIL_VEH_CORRUPTION",
+ "FAST_FAIL_ETW_CORRUPTION",
+ "FAST_FAIL_RIO_ABORT",
+ "FAST_FAIL_INVALID_PFN",
+};
+
+const char* FastFailToString(uint32_t fast_fail_code) {
+ auto itr = std::find(std::begin(kFastFailValues),
+ std::end(kFastFailValues),
+ fast_fail_code);
+ if (itr == std::end(kFastFailValues)) {
+ return nullptr;
+ }
+
+ return kFastFailStrings[itr - std::begin(kFastFailValues)];
+}
+
+// The content of this array was created from winerror.h in the 10 SDK
+// (version 10.0.19041.0) with the following script:
+//
+// egrep -o '#define ERROR_[A-Z_0-9]+\s+[0-9]+L' winerror.h
+// | tr -d '\r'
+// | sed -r 's@#define ERROR_([A-Z_0-9]+)\s+([0-9]+)L@\2 \1@'
+// | sort -n
+// | sed -r 's@([0-9]+) ([A-Z_0-9]+)@ MD_ERROR_WIN_\2,@'
+static const uint16_t kWinErrorValues[] = {
+ MD_ERROR_WIN_SUCCESS,
+ MD_ERROR_WIN_INVALID_FUNCTION,
+ MD_ERROR_WIN_FILE_NOT_FOUND,
+ MD_ERROR_WIN_PATH_NOT_FOUND,
+ MD_ERROR_WIN_TOO_MANY_OPEN_FILES,
+ MD_ERROR_WIN_ACCESS_DENIED,
+ MD_ERROR_WIN_INVALID_HANDLE,
+ MD_ERROR_WIN_ARENA_TRASHED,
+ MD_ERROR_WIN_NOT_ENOUGH_MEMORY,
+ MD_ERROR_WIN_INVALID_BLOCK,
+ MD_ERROR_WIN_BAD_ENVIRONMENT,
+ MD_ERROR_WIN_BAD_FORMAT,
+ MD_ERROR_WIN_INVALID_ACCESS,
+ MD_ERROR_WIN_INVALID_DATA,
+ MD_ERROR_WIN_OUTOFMEMORY,
+ MD_ERROR_WIN_INVALID_DRIVE,
+ MD_ERROR_WIN_CURRENT_DIRECTORY,
+ MD_ERROR_WIN_NOT_SAME_DEVICE,
+ MD_ERROR_WIN_NO_MORE_FILES,
+ MD_ERROR_WIN_WRITE_PROTECT,
+ MD_ERROR_WIN_BAD_UNIT,
+ MD_ERROR_WIN_NOT_READY,
+ MD_ERROR_WIN_BAD_COMMAND,
+ MD_ERROR_WIN_CRC,
+ MD_ERROR_WIN_BAD_LENGTH,
+ MD_ERROR_WIN_SEEK,
+ MD_ERROR_WIN_NOT_DOS_DISK,
+ MD_ERROR_WIN_SECTOR_NOT_FOUND,
+ MD_ERROR_WIN_OUT_OF_PAPER,
+ MD_ERROR_WIN_WRITE_FAULT,
+ MD_ERROR_WIN_READ_FAULT,
+ MD_ERROR_WIN_GEN_FAILURE,
+ MD_ERROR_WIN_SHARING_VIOLATION,
+ MD_ERROR_WIN_LOCK_VIOLATION,
+ MD_ERROR_WIN_WRONG_DISK,
+ MD_ERROR_WIN_SHARING_BUFFER_EXCEEDED,
+ MD_ERROR_WIN_HANDLE_EOF,
+ MD_ERROR_WIN_HANDLE_DISK_FULL,
+ MD_ERROR_WIN_NOT_SUPPORTED,
+ MD_ERROR_WIN_REM_NOT_LIST,
+ MD_ERROR_WIN_DUP_NAME,
+ MD_ERROR_WIN_BAD_NETPATH,
+ MD_ERROR_WIN_NETWORK_BUSY,
+ MD_ERROR_WIN_DEV_NOT_EXIST,
+ MD_ERROR_WIN_TOO_MANY_CMDS,
+ MD_ERROR_WIN_ADAP_HDW_ERR,
+ MD_ERROR_WIN_BAD_NET_RESP,
+ MD_ERROR_WIN_UNEXP_NET_ERR,
+ MD_ERROR_WIN_BAD_REM_ADAP,
+ MD_ERROR_WIN_PRINTQ_FULL,
+ MD_ERROR_WIN_NO_SPOOL_SPACE,
+ MD_ERROR_WIN_PRINT_CANCELLED,
+ MD_ERROR_WIN_NETNAME_DELETED,
+ MD_ERROR_WIN_NETWORK_ACCESS_DENIED,
+ MD_ERROR_WIN_BAD_DEV_TYPE,
+ MD_ERROR_WIN_BAD_NET_NAME,
+ MD_ERROR_WIN_TOO_MANY_NAMES,
+ MD_ERROR_WIN_TOO_MANY_SESS,
+ MD_ERROR_WIN_SHARING_PAUSED,
+ MD_ERROR_WIN_REQ_NOT_ACCEP,
+ MD_ERROR_WIN_REDIR_PAUSED,
+ MD_ERROR_WIN_FILE_EXISTS,
+ MD_ERROR_WIN_CANNOT_MAKE,
+ MD_ERROR_WIN_FAIL_I24,
+ MD_ERROR_WIN_OUT_OF_STRUCTURES,
+ MD_ERROR_WIN_ALREADY_ASSIGNED,
+ MD_ERROR_WIN_INVALID_PASSWORD,
+ MD_ERROR_WIN_INVALID_PARAMETER,
+ MD_ERROR_WIN_NET_WRITE_FAULT,
+ MD_ERROR_WIN_NO_PROC_SLOTS,
+ MD_ERROR_WIN_TOO_MANY_SEMAPHORES,
+ MD_ERROR_WIN_EXCL_SEM_ALREADY_OWNED,
+ MD_ERROR_WIN_SEM_IS_SET,
+ MD_ERROR_WIN_TOO_MANY_SEM_REQUESTS,
+ MD_ERROR_WIN_INVALID_AT_INTERRUPT_TIME,
+ MD_ERROR_WIN_SEM_OWNER_DIED,
+ MD_ERROR_WIN_SEM_USER_LIMIT,
+ MD_ERROR_WIN_DISK_CHANGE,
+ MD_ERROR_WIN_DRIVE_LOCKED,
+ MD_ERROR_WIN_BROKEN_PIPE,
+ MD_ERROR_WIN_OPEN_FAILED,
+ MD_ERROR_WIN_BUFFER_OVERFLOW,
+ MD_ERROR_WIN_DISK_FULL,
+ MD_ERROR_WIN_NO_MORE_SEARCH_HANDLES,
+ MD_ERROR_WIN_INVALID_TARGET_HANDLE,
+ MD_ERROR_WIN_INVALID_CATEGORY,
+ MD_ERROR_WIN_INVALID_VERIFY_SWITCH,
+ MD_ERROR_WIN_BAD_DRIVER_LEVEL,
+ MD_ERROR_WIN_CALL_NOT_IMPLEMENTED,
+ MD_ERROR_WIN_SEM_TIMEOUT,
+ MD_ERROR_WIN_INSUFFICIENT_BUFFER,
+ MD_ERROR_WIN_INVALID_NAME,
+ MD_ERROR_WIN_INVALID_LEVEL,
+ MD_ERROR_WIN_NO_VOLUME_LABEL,
+ MD_ERROR_WIN_MOD_NOT_FOUND,
+ MD_ERROR_WIN_PROC_NOT_FOUND,
+ MD_ERROR_WIN_WAIT_NO_CHILDREN,
+ MD_ERROR_WIN_CHILD_NOT_COMPLETE,
+ MD_ERROR_WIN_DIRECT_ACCESS_HANDLE,
+ MD_ERROR_WIN_NEGATIVE_SEEK,
+ MD_ERROR_WIN_SEEK_ON_DEVICE,
+ MD_ERROR_WIN_IS_JOIN_TARGET,
+ MD_ERROR_WIN_IS_JOINED,
+ MD_ERROR_WIN_IS_SUBSTED,
+ MD_ERROR_WIN_NOT_JOINED,
+ MD_ERROR_WIN_NOT_SUBSTED,
+ MD_ERROR_WIN_JOIN_TO_JOIN,
+ MD_ERROR_WIN_SUBST_TO_SUBST,
+ MD_ERROR_WIN_JOIN_TO_SUBST,
+ MD_ERROR_WIN_SUBST_TO_JOIN,
+ MD_ERROR_WIN_BUSY_DRIVE,
+ MD_ERROR_WIN_SAME_DRIVE,
+ MD_ERROR_WIN_DIR_NOT_ROOT,
+ MD_ERROR_WIN_DIR_NOT_EMPTY,
+ MD_ERROR_WIN_IS_SUBST_PATH,
+ MD_ERROR_WIN_IS_JOIN_PATH,
+ MD_ERROR_WIN_PATH_BUSY,
+ MD_ERROR_WIN_IS_SUBST_TARGET,
+ MD_ERROR_WIN_SYSTEM_TRACE,
+ MD_ERROR_WIN_INVALID_EVENT_COUNT,
+ MD_ERROR_WIN_TOO_MANY_MUXWAITERS,
+ MD_ERROR_WIN_INVALID_LIST_FORMAT,
+ MD_ERROR_WIN_LABEL_TOO_LONG,
+ MD_ERROR_WIN_TOO_MANY_TCBS,
+ MD_ERROR_WIN_SIGNAL_REFUSED,
+ MD_ERROR_WIN_DISCARDED,
+ MD_ERROR_WIN_NOT_LOCKED,
+ MD_ERROR_WIN_BAD_THREADID_ADDR,
+ MD_ERROR_WIN_BAD_ARGUMENTS,
+ MD_ERROR_WIN_BAD_PATHNAME,
+ MD_ERROR_WIN_SIGNAL_PENDING,
+ MD_ERROR_WIN_MAX_THRDS_REACHED,
+ MD_ERROR_WIN_LOCK_FAILED,
+ MD_ERROR_WIN_BUSY,
+ MD_ERROR_WIN_DEVICE_SUPPORT_IN_PROGRESS,
+ MD_ERROR_WIN_CANCEL_VIOLATION,
+ MD_ERROR_WIN_ATOMIC_LOCKS_NOT_SUPPORTED,
+ MD_ERROR_WIN_INVALID_SEGMENT_NUMBER,
+ MD_ERROR_WIN_INVALID_ORDINAL,
+ MD_ERROR_WIN_ALREADY_EXISTS,
+ MD_ERROR_WIN_INVALID_FLAG_NUMBER,
+ MD_ERROR_WIN_SEM_NOT_FOUND,
+ MD_ERROR_WIN_INVALID_STARTING_CODESEG,
+ MD_ERROR_WIN_INVALID_STACKSEG,
+ MD_ERROR_WIN_INVALID_MODULETYPE,
+ MD_ERROR_WIN_INVALID_EXE_SIGNATURE,
+ MD_ERROR_WIN_EXE_MARKED_INVALID,
+ MD_ERROR_WIN_BAD_EXE_FORMAT,
+ MD_ERROR_WIN_INVALID_MINALLOCSIZE,
+ MD_ERROR_WIN_DYNLINK_FROM_INVALID_RING,
+ MD_ERROR_WIN_IOPL_NOT_ENABLED,
+ MD_ERROR_WIN_INVALID_SEGDPL,
+ MD_ERROR_WIN_RING2SEG_MUST_BE_MOVABLE,
+ MD_ERROR_WIN_RELOC_CHAIN_XEEDS_SEGLIM,
+ MD_ERROR_WIN_INFLOOP_IN_RELOC_CHAIN,
+ MD_ERROR_WIN_ENVVAR_NOT_FOUND,
+ MD_ERROR_WIN_NO_SIGNAL_SENT,
+ MD_ERROR_WIN_FILENAME_EXCED_RANGE,
+ MD_ERROR_WIN_RING2_STACK_IN_USE,
+ MD_ERROR_WIN_META_EXPANSION_TOO_LONG,
+ MD_ERROR_WIN_INVALID_SIGNAL_NUMBER,
+ MD_ERROR_WIN_THREAD_1_INACTIVE,
+ MD_ERROR_WIN_LOCKED,
+ MD_ERROR_WIN_TOO_MANY_MODULES,
+ MD_ERROR_WIN_NESTING_NOT_ALLOWED,
+ MD_ERROR_WIN_EXE_MACHINE_TYPE_MISMATCH,
+ MD_ERROR_WIN_EXE_CANNOT_MODIFY_SIGNED_BINARY,
+ MD_ERROR_WIN_EXE_CANNOT_MODIFY_STRONG_SIGNED_BINARY,
+ MD_ERROR_WIN_FILE_CHECKED_OUT,
+ MD_ERROR_WIN_CHECKOUT_REQUIRED,
+ MD_ERROR_WIN_BAD_FILE_TYPE,
+ MD_ERROR_WIN_FILE_TOO_LARGE,
+ MD_ERROR_WIN_FORMS_AUTH_REQUIRED,
+ MD_ERROR_WIN_VIRUS_INFECTED,
+ MD_ERROR_WIN_VIRUS_DELETED,
+ MD_ERROR_WIN_PIPE_LOCAL,
+ MD_ERROR_WIN_BAD_PIPE,
+ MD_ERROR_WIN_PIPE_BUSY,
+ MD_ERROR_WIN_NO_DATA,
+ MD_ERROR_WIN_PIPE_NOT_CONNECTED,
+ MD_ERROR_WIN_MORE_DATA,
+ MD_ERROR_WIN_NO_WORK_DONE,
+ MD_ERROR_WIN_VC_DISCONNECTED,
+ MD_ERROR_WIN_INVALID_EA_NAME,
+ MD_ERROR_WIN_EA_LIST_INCONSISTENT,
+ MD_ERROR_WIN_NO_MORE_ITEMS,
+ MD_ERROR_WIN_CANNOT_COPY,
+ MD_ERROR_WIN_DIRECTORY,
+ MD_ERROR_WIN_EAS_DIDNT_FIT,
+ MD_ERROR_WIN_EA_FILE_CORRUPT,
+ MD_ERROR_WIN_EA_TABLE_FULL,
+ MD_ERROR_WIN_INVALID_EA_HANDLE,
+ MD_ERROR_WIN_EAS_NOT_SUPPORTED,
+ MD_ERROR_WIN_NOT_OWNER,
+ MD_ERROR_WIN_TOO_MANY_POSTS,
+ MD_ERROR_WIN_PARTIAL_COPY,
+ MD_ERROR_WIN_OPLOCK_NOT_GRANTED,
+ MD_ERROR_WIN_INVALID_OPLOCK_PROTOCOL,
+ MD_ERROR_WIN_DISK_TOO_FRAGMENTED,
+ MD_ERROR_WIN_DELETE_PENDING,
+ MD_ERROR_WIN_INCOMPATIBLE_WITH_GLOBAL_SHORT_NAME_REGISTRY_SETTING,
+ MD_ERROR_WIN_SHORT_NAMES_NOT_ENABLED_ON_VOLUME,
+ MD_ERROR_WIN_SECURITY_STREAM_IS_INCONSISTENT,
+ MD_ERROR_WIN_INVALID_LOCK_RANGE,
+ MD_ERROR_WIN_IMAGE_SUBSYSTEM_NOT_PRESENT,
+ MD_ERROR_WIN_NOTIFICATION_GUID_ALREADY_DEFINED,
+ MD_ERROR_WIN_INVALID_EXCEPTION_HANDLER,
+ MD_ERROR_WIN_DUPLICATE_PRIVILEGES,
+ MD_ERROR_WIN_NO_RANGES_PROCESSED,
+ MD_ERROR_WIN_NOT_ALLOWED_ON_SYSTEM_FILE,
+ MD_ERROR_WIN_DISK_RESOURCES_EXHAUSTED,
+ MD_ERROR_WIN_INVALID_TOKEN,
+ MD_ERROR_WIN_DEVICE_FEATURE_NOT_SUPPORTED,
+ MD_ERROR_WIN_MR_MID_NOT_FOUND,
+ MD_ERROR_WIN_SCOPE_NOT_FOUND,
+ MD_ERROR_WIN_UNDEFINED_SCOPE,
+ MD_ERROR_WIN_INVALID_CAP,
+ MD_ERROR_WIN_DEVICE_UNREACHABLE,
+ MD_ERROR_WIN_DEVICE_NO_RESOURCES,
+ MD_ERROR_WIN_DATA_CHECKSUM_ERROR,
+ MD_ERROR_WIN_INTERMIXED_KERNEL_EA_OPERATION,
+ MD_ERROR_WIN_FILE_LEVEL_TRIM_NOT_SUPPORTED,
+ MD_ERROR_WIN_OFFSET_ALIGNMENT_VIOLATION,
+ MD_ERROR_WIN_INVALID_FIELD_IN_PARAMETER_LIST,
+ MD_ERROR_WIN_OPERATION_IN_PROGRESS,
+ MD_ERROR_WIN_BAD_DEVICE_PATH,
+ MD_ERROR_WIN_TOO_MANY_DESCRIPTORS,
+ MD_ERROR_WIN_SCRUB_DATA_DISABLED,
+ MD_ERROR_WIN_NOT_REDUNDANT_STORAGE,
+ MD_ERROR_WIN_RESIDENT_FILE_NOT_SUPPORTED,
+ MD_ERROR_WIN_COMPRESSED_FILE_NOT_SUPPORTED,
+ MD_ERROR_WIN_DIRECTORY_NOT_SUPPORTED,
+ MD_ERROR_WIN_NOT_READ_FROM_COPY,
+ MD_ERROR_WIN_FT_WRITE_FAILURE,
+ MD_ERROR_WIN_FT_DI_SCAN_REQUIRED,
+ MD_ERROR_WIN_INVALID_KERNEL_INFO_VERSION,
+ MD_ERROR_WIN_INVALID_PEP_INFO_VERSION,
+ MD_ERROR_WIN_OBJECT_NOT_EXTERNALLY_BACKED,
+ MD_ERROR_WIN_EXTERNAL_BACKING_PROVIDER_UNKNOWN,
+ MD_ERROR_WIN_COMPRESSION_NOT_BENEFICIAL,
+ MD_ERROR_WIN_STORAGE_TOPOLOGY_ID_MISMATCH,
+ MD_ERROR_WIN_BLOCKED_BY_PARENTAL_CONTROLS,
+ MD_ERROR_WIN_BLOCK_TOO_MANY_REFERENCES,
+ MD_ERROR_WIN_MARKED_TO_DISALLOW_WRITES,
+ MD_ERROR_WIN_ENCLAVE_FAILURE,
+ MD_ERROR_WIN_FAIL_NOACTION_REBOOT,
+ MD_ERROR_WIN_FAIL_SHUTDOWN,
+ MD_ERROR_WIN_FAIL_RESTART,
+ MD_ERROR_WIN_MAX_SESSIONS_REACHED,
+ MD_ERROR_WIN_NETWORK_ACCESS_DENIED_EDP,
+ MD_ERROR_WIN_DEVICE_HINT_NAME_BUFFER_TOO_SMALL,
+ MD_ERROR_WIN_EDP_POLICY_DENIES_OPERATION,
+ MD_ERROR_WIN_EDP_DPL_POLICY_CANT_BE_SATISFIED,
+ MD_ERROR_WIN_CLOUD_FILE_SYNC_ROOT_METADATA_CORRUPT,
+ MD_ERROR_WIN_DEVICE_IN_MAINTENANCE,
+ MD_ERROR_WIN_NOT_SUPPORTED_ON_DAX,
+ MD_ERROR_WIN_DAX_MAPPING_EXISTS,
+ MD_ERROR_WIN_CLOUD_FILE_PROVIDER_NOT_RUNNING,
+ MD_ERROR_WIN_CLOUD_FILE_METADATA_CORRUPT,
+ MD_ERROR_WIN_CLOUD_FILE_METADATA_TOO_LARGE,
+ MD_ERROR_WIN_CLOUD_FILE_PROPERTY_BLOB_TOO_LARGE,
+ MD_ERROR_WIN_CLOUD_FILE_PROPERTY_BLOB_CHECKSUM_MISMATCH,
+ MD_ERROR_WIN_CHILD_PROCESS_BLOCKED,
+ MD_ERROR_WIN_STORAGE_LOST_DATA_PERSISTENCE,
+ MD_ERROR_WIN_FILE_SYSTEM_VIRTUALIZATION_UNAVAILABLE,
+ MD_ERROR_WIN_FILE_SYSTEM_VIRTUALIZATION_METADATA_CORRUPT,
+ MD_ERROR_WIN_FILE_SYSTEM_VIRTUALIZATION_BUSY,
+ MD_ERROR_WIN_FILE_SYSTEM_VIRTUALIZATION_PROVIDER_UNKNOWN,
+ MD_ERROR_WIN_GDI_HANDLE_LEAK,
+ MD_ERROR_WIN_CLOUD_FILE_TOO_MANY_PROPERTY_BLOBS,
+ MD_ERROR_WIN_CLOUD_FILE_PROPERTY_VERSION_NOT_SUPPORTED,
+ MD_ERROR_WIN_NOT_A_CLOUD_FILE,
+ MD_ERROR_WIN_CLOUD_FILE_NOT_IN_SYNC,
+ MD_ERROR_WIN_CLOUD_FILE_ALREADY_CONNECTED,
+ MD_ERROR_WIN_CLOUD_FILE_NOT_SUPPORTED,
+ MD_ERROR_WIN_CLOUD_FILE_INVALID_REQUEST,
+ MD_ERROR_WIN_CLOUD_FILE_READ_ONLY_VOLUME,
+ MD_ERROR_WIN_CLOUD_FILE_CONNECTED_PROVIDER_ONLY,
+ MD_ERROR_WIN_CLOUD_FILE_VALIDATION_FAILED,
+ MD_ERROR_WIN_SMB1_NOT_AVAILABLE,
+ MD_ERROR_WIN_FILE_SYSTEM_VIRTUALIZATION_INVALID_OPERATION,
+ MD_ERROR_WIN_CLOUD_FILE_AUTHENTICATION_FAILED,
+ MD_ERROR_WIN_CLOUD_FILE_INSUFFICIENT_RESOURCES,
+ MD_ERROR_WIN_CLOUD_FILE_NETWORK_UNAVAILABLE,
+ MD_ERROR_WIN_CLOUD_FILE_UNSUCCESSFUL,
+ MD_ERROR_WIN_CLOUD_FILE_NOT_UNDER_SYNC_ROOT,
+ MD_ERROR_WIN_CLOUD_FILE_IN_USE,
+ MD_ERROR_WIN_CLOUD_FILE_PINNED,
+ MD_ERROR_WIN_CLOUD_FILE_REQUEST_ABORTED,
+ MD_ERROR_WIN_CLOUD_FILE_PROPERTY_CORRUPT,
+ MD_ERROR_WIN_CLOUD_FILE_ACCESS_DENIED,
+ MD_ERROR_WIN_CLOUD_FILE_INCOMPATIBLE_HARDLINKS,
+ MD_ERROR_WIN_CLOUD_FILE_PROPERTY_LOCK_CONFLICT,
+ MD_ERROR_WIN_CLOUD_FILE_REQUEST_CANCELED,
+ MD_ERROR_WIN_EXTERNAL_SYSKEY_NOT_SUPPORTED,
+ MD_ERROR_WIN_THREAD_MODE_ALREADY_BACKGROUND,
+ MD_ERROR_WIN_THREAD_MODE_NOT_BACKGROUND,
+ MD_ERROR_WIN_PROCESS_MODE_ALREADY_BACKGROUND,
+ MD_ERROR_WIN_PROCESS_MODE_NOT_BACKGROUND,
+ MD_ERROR_WIN_CLOUD_FILE_PROVIDER_TERMINATED,
+ MD_ERROR_WIN_NOT_A_CLOUD_SYNC_ROOT,
+ MD_ERROR_WIN_FILE_PROTECTED_UNDER_DPL,
+ MD_ERROR_WIN_VOLUME_NOT_CLUSTER_ALIGNED,
+ MD_ERROR_WIN_NO_PHYSICALLY_ALIGNED_FREE_SPACE_FOUND,
+ MD_ERROR_WIN_APPX_FILE_NOT_ENCRYPTED,
+ MD_ERROR_WIN_RWRAW_ENCRYPTED_FILE_NOT_ENCRYPTED,
+ MD_ERROR_WIN_RWRAW_ENCRYPTED_INVALID_EDATAINFO_FILEOFFSET,
+ MD_ERROR_WIN_RWRAW_ENCRYPTED_INVALID_EDATAINFO_FILERANGE,
+ MD_ERROR_WIN_RWRAW_ENCRYPTED_INVALID_EDATAINFO_PARAMETER,
+ MD_ERROR_WIN_LINUX_SUBSYSTEM_NOT_PRESENT,
+ MD_ERROR_WIN_FT_READ_FAILURE,
+ MD_ERROR_WIN_STORAGE_RESERVE_ID_INVALID,
+ MD_ERROR_WIN_STORAGE_RESERVE_DOES_NOT_EXIST,
+ MD_ERROR_WIN_STORAGE_RESERVE_ALREADY_EXISTS,
+ MD_ERROR_WIN_STORAGE_RESERVE_NOT_EMPTY,
+ MD_ERROR_WIN_NOT_A_DAX_VOLUME,
+ MD_ERROR_WIN_NOT_DAX_MAPPABLE,
+ MD_ERROR_WIN_TIME_SENSITIVE_THREAD,
+ MD_ERROR_WIN_DPL_NOT_SUPPORTED_FOR_USER,
+ MD_ERROR_WIN_CASE_DIFFERING_NAMES_IN_DIR,
+ MD_ERROR_WIN_FILE_NOT_SUPPORTED,
+ MD_ERROR_WIN_CLOUD_FILE_REQUEST_TIMEOUT,
+ MD_ERROR_WIN_NO_TASK_QUEUE,
+ MD_ERROR_WIN_SRC_SRV_DLL_LOAD_FAILED,
+ MD_ERROR_WIN_NOT_SUPPORTED_WITH_BTT,
+ MD_ERROR_WIN_ENCRYPTION_DISABLED,
+ MD_ERROR_WIN_ENCRYPTING_METADATA_DISALLOWED,
+ MD_ERROR_WIN_CANT_CLEAR_ENCRYPTION_FLAG,
+ MD_ERROR_WIN_NO_SUCH_DEVICE,
+ MD_ERROR_WIN_CLOUD_FILE_DEHYDRATION_DISALLOWED,
+ MD_ERROR_WIN_FILE_SNAP_IN_PROGRESS,
+ MD_ERROR_WIN_FILE_SNAP_USER_SECTION_NOT_SUPPORTED,
+ MD_ERROR_WIN_FILE_SNAP_MODIFY_NOT_SUPPORTED,
+ MD_ERROR_WIN_FILE_SNAP_IO_NOT_COORDINATED,
+ MD_ERROR_WIN_FILE_SNAP_UNEXPECTED_ERROR,
+ MD_ERROR_WIN_FILE_SNAP_INVALID_PARAMETER,
+ MD_ERROR_WIN_UNSATISFIED_DEPENDENCIES,
+ MD_ERROR_WIN_CASE_SENSITIVE_PATH,
+ MD_ERROR_WIN_UNEXPECTED_NTCACHEMANAGER_ERROR,
+ MD_ERROR_WIN_LINUX_SUBSYSTEM_UPDATE_REQUIRED,
+ MD_ERROR_WIN_DLP_POLICY_WARNS_AGAINST_OPERATION,
+ MD_ERROR_WIN_DLP_POLICY_DENIES_OPERATION,
+ MD_ERROR_WIN_DLP_POLICY_SILENTLY_FAIL,
+ MD_ERROR_WIN_CAPAUTHZ_NOT_DEVUNLOCKED,
+ MD_ERROR_WIN_CAPAUTHZ_CHANGE_TYPE,
+ MD_ERROR_WIN_CAPAUTHZ_NOT_PROVISIONED,
+ MD_ERROR_WIN_CAPAUTHZ_NOT_AUTHORIZED,
+ MD_ERROR_WIN_CAPAUTHZ_NO_POLICY,
+ MD_ERROR_WIN_CAPAUTHZ_DB_CORRUPTED,
+ MD_ERROR_WIN_CAPAUTHZ_SCCD_INVALID_CATALOG,
+ MD_ERROR_WIN_CAPAUTHZ_SCCD_NO_AUTH_ENTITY,
+ MD_ERROR_WIN_CAPAUTHZ_SCCD_PARSE_ERROR,
+ MD_ERROR_WIN_CAPAUTHZ_SCCD_DEV_MODE_REQUIRED,
+ MD_ERROR_WIN_CAPAUTHZ_SCCD_NO_CAPABILITY_MATCH,
+ MD_ERROR_WIN_CIMFS_IMAGE_CORRUPT,
+ MD_ERROR_WIN_PNP_QUERY_REMOVE_DEVICE_TIMEOUT,
+ MD_ERROR_WIN_PNP_QUERY_REMOVE_RELATED_DEVICE_TIMEOUT,
+ MD_ERROR_WIN_PNP_QUERY_REMOVE_UNRELATED_DEVICE_TIMEOUT,
+ MD_ERROR_WIN_DEVICE_HARDWARE_ERROR,
+ MD_ERROR_WIN_INVALID_ADDRESS,
+ MD_ERROR_WIN_HAS_SYSTEM_CRITICAL_FILES,
+ MD_ERROR_WIN_USER_PROFILE_LOAD,
+ MD_ERROR_WIN_ARITHMETIC_OVERFLOW,
+ MD_ERROR_WIN_PIPE_CONNECTED,
+ MD_ERROR_WIN_PIPE_LISTENING,
+ MD_ERROR_WIN_VERIFIER_STOP,
+ MD_ERROR_WIN_ABIOS_ERROR,
+ MD_ERROR_WIN_WX86_WARNING,
+ MD_ERROR_WIN_WX86_ERROR,
+ MD_ERROR_WIN_TIMER_NOT_CANCELED,
+ MD_ERROR_WIN_UNWIND,
+ MD_ERROR_WIN_BAD_STACK,
+ MD_ERROR_WIN_INVALID_UNWIND_TARGET,
+ MD_ERROR_WIN_INVALID_PORT_ATTRIBUTES,
+ MD_ERROR_WIN_PORT_MESSAGE_TOO_LONG,
+ MD_ERROR_WIN_INVALID_QUOTA_LOWER,
+ MD_ERROR_WIN_DEVICE_ALREADY_ATTACHED,
+ MD_ERROR_WIN_INSTRUCTION_MISALIGNMENT,
+ MD_ERROR_WIN_PROFILING_NOT_STARTED,
+ MD_ERROR_WIN_PROFILING_NOT_STOPPED,
+ MD_ERROR_WIN_COULD_NOT_INTERPRET,
+ MD_ERROR_WIN_PROFILING_AT_LIMIT,
+ MD_ERROR_WIN_CANT_WAIT,
+ MD_ERROR_WIN_CANT_TERMINATE_SELF,
+ MD_ERROR_WIN_UNEXPECTED_MM_CREATE_ERR,
+ MD_ERROR_WIN_UNEXPECTED_MM_MAP_ERROR,
+ MD_ERROR_WIN_UNEXPECTED_MM_EXTEND_ERR,
+ MD_ERROR_WIN_BAD_FUNCTION_TABLE,
+ MD_ERROR_WIN_NO_GUID_TRANSLATION,
+ MD_ERROR_WIN_INVALID_LDT_SIZE,
+ MD_ERROR_WIN_INVALID_LDT_OFFSET,
+ MD_ERROR_WIN_INVALID_LDT_DESCRIPTOR,
+ MD_ERROR_WIN_TOO_MANY_THREADS,
+ MD_ERROR_WIN_THREAD_NOT_IN_PROCESS,
+ MD_ERROR_WIN_PAGEFILE_QUOTA_EXCEEDED,
+ MD_ERROR_WIN_LOGON_SERVER_CONFLICT,
+ MD_ERROR_WIN_SYNCHRONIZATION_REQUIRED,
+ MD_ERROR_WIN_NET_OPEN_FAILED,
+ MD_ERROR_WIN_IO_PRIVILEGE_FAILED,
+ MD_ERROR_WIN_CONTROL_C_EXIT,
+ MD_ERROR_WIN_MISSING_SYSTEMFILE,
+ MD_ERROR_WIN_UNHANDLED_EXCEPTION,
+ MD_ERROR_WIN_APP_INIT_FAILURE,
+ MD_ERROR_WIN_PAGEFILE_CREATE_FAILED,
+ MD_ERROR_WIN_INVALID_IMAGE_HASH,
+ MD_ERROR_WIN_NO_PAGEFILE,
+ MD_ERROR_WIN_ILLEGAL_FLOAT_CONTEXT,
+ MD_ERROR_WIN_NO_EVENT_PAIR,
+ MD_ERROR_WIN_DOMAIN_CTRLR_CONFIG_ERROR,
+ MD_ERROR_WIN_ILLEGAL_CHARACTER,
+ MD_ERROR_WIN_UNDEFINED_CHARACTER,
+ MD_ERROR_WIN_FLOPPY_VOLUME,
+ MD_ERROR_WIN_BIOS_FAILED_TO_CONNECT_INTERRUPT,
+ MD_ERROR_WIN_BACKUP_CONTROLLER,
+ MD_ERROR_WIN_MUTANT_LIMIT_EXCEEDED,
+ MD_ERROR_WIN_FS_DRIVER_REQUIRED,
+ MD_ERROR_WIN_CANNOT_LOAD_REGISTRY_FILE,
+ MD_ERROR_WIN_DEBUG_ATTACH_FAILED,
+ MD_ERROR_WIN_SYSTEM_PROCESS_TERMINATED,
+ MD_ERROR_WIN_DATA_NOT_ACCEPTED,
+ MD_ERROR_WIN_VDM_HARD_ERROR,
+ MD_ERROR_WIN_DRIVER_CANCEL_TIMEOUT,
+ MD_ERROR_WIN_REPLY_MESSAGE_MISMATCH,
+ MD_ERROR_WIN_LOST_WRITEBEHIND_DATA,
+ MD_ERROR_WIN_CLIENT_SERVER_PARAMETERS_INVALID,
+ MD_ERROR_WIN_NOT_TINY_STREAM,
+ MD_ERROR_WIN_STACK_OVERFLOW_READ,
+ MD_ERROR_WIN_CONVERT_TO_LARGE,
+ MD_ERROR_WIN_FOUND_OUT_OF_SCOPE,
+ MD_ERROR_WIN_ALLOCATE_BUCKET,
+ MD_ERROR_WIN_MARSHALL_OVERFLOW,
+ MD_ERROR_WIN_INVALID_VARIANT,
+ MD_ERROR_WIN_BAD_COMPRESSION_BUFFER,
+ MD_ERROR_WIN_AUDIT_FAILED,
+ MD_ERROR_WIN_TIMER_RESOLUTION_NOT_SET,
+ MD_ERROR_WIN_INSUFFICIENT_LOGON_INFO,
+ MD_ERROR_WIN_BAD_DLL_ENTRYPOINT,
+ MD_ERROR_WIN_BAD_SERVICE_ENTRYPOINT,
+ MD_ERROR_WIN_IP_ADDRESS_CONFLICT1,
+ MD_ERROR_WIN_IP_ADDRESS_CONFLICT2,
+ MD_ERROR_WIN_REGISTRY_QUOTA_LIMIT,
+ MD_ERROR_WIN_NO_CALLBACK_ACTIVE,
+ MD_ERROR_WIN_PWD_TOO_SHORT,
+ MD_ERROR_WIN_PWD_TOO_RECENT,
+ MD_ERROR_WIN_PWD_HISTORY_CONFLICT,
+ MD_ERROR_WIN_UNSUPPORTED_COMPRESSION,
+ MD_ERROR_WIN_INVALID_HW_PROFILE,
+ MD_ERROR_WIN_INVALID_PLUGPLAY_DEVICE_PATH,
+ MD_ERROR_WIN_QUOTA_LIST_INCONSISTENT,
+ MD_ERROR_WIN_EVALUATION_EXPIRATION,
+ MD_ERROR_WIN_ILLEGAL_DLL_RELOCATION,
+ MD_ERROR_WIN_DLL_INIT_FAILED_LOGOFF,
+ MD_ERROR_WIN_VALIDATE_CONTINUE,
+ MD_ERROR_WIN_NO_MORE_MATCHES,
+ MD_ERROR_WIN_RANGE_LIST_CONFLICT,
+ MD_ERROR_WIN_SERVER_SID_MISMATCH,
+ MD_ERROR_WIN_CANT_ENABLE_DENY_ONLY,
+ MD_ERROR_WIN_FLOAT_MULTIPLE_FAULTS,
+ MD_ERROR_WIN_FLOAT_MULTIPLE_TRAPS,
+ MD_ERROR_WIN_NOINTERFACE,
+ MD_ERROR_WIN_DRIVER_FAILED_SLEEP,
+ MD_ERROR_WIN_CORRUPT_SYSTEM_FILE,
+ MD_ERROR_WIN_COMMITMENT_MINIMUM,
+ MD_ERROR_WIN_PNP_RESTART_ENUMERATION,
+ MD_ERROR_WIN_SYSTEM_IMAGE_BAD_SIGNATURE,
+ MD_ERROR_WIN_PNP_REBOOT_REQUIRED,
+ MD_ERROR_WIN_INSUFFICIENT_POWER,
+ MD_ERROR_WIN_MULTIPLE_FAULT_VIOLATION,
+ MD_ERROR_WIN_SYSTEM_SHUTDOWN,
+ MD_ERROR_WIN_PORT_NOT_SET,
+ MD_ERROR_WIN_DS_VERSION_CHECK_FAILURE,
+ MD_ERROR_WIN_RANGE_NOT_FOUND,
+ MD_ERROR_WIN_NOT_SAFE_MODE_DRIVER,
+ MD_ERROR_WIN_FAILED_DRIVER_ENTRY,
+ MD_ERROR_WIN_DEVICE_ENUMERATION_ERROR,
+ MD_ERROR_WIN_MOUNT_POINT_NOT_RESOLVED,
+ MD_ERROR_WIN_INVALID_DEVICE_OBJECT_PARAMETER,
+ MD_ERROR_WIN_MCA_OCCURED,
+ MD_ERROR_WIN_DRIVER_DATABASE_ERROR,
+ MD_ERROR_WIN_SYSTEM_HIVE_TOO_LARGE,
+ MD_ERROR_WIN_DRIVER_FAILED_PRIOR_UNLOAD,
+ MD_ERROR_WIN_VOLSNAP_PREPARE_HIBERNATE,
+ MD_ERROR_WIN_HIBERNATION_FAILURE,
+ MD_ERROR_WIN_PWD_TOO_LONG,
+ MD_ERROR_WIN_FILE_SYSTEM_LIMITATION,
+ MD_ERROR_WIN_ASSERTION_FAILURE,
+ MD_ERROR_WIN_ACPI_ERROR,
+ MD_ERROR_WIN_WOW_ASSERTION,
+ MD_ERROR_WIN_PNP_BAD_MPS_TABLE,
+ MD_ERROR_WIN_PNP_TRANSLATION_FAILED,
+ MD_ERROR_WIN_PNP_IRQ_TRANSLATION_FAILED,
+ MD_ERROR_WIN_PNP_INVALID_ID,
+ MD_ERROR_WIN_WAKE_SYSTEM_DEBUGGER,
+ MD_ERROR_WIN_HANDLES_CLOSED,
+ MD_ERROR_WIN_EXTRANEOUS_INFORMATION,
+ MD_ERROR_WIN_RXACT_COMMIT_NECESSARY,
+ MD_ERROR_WIN_MEDIA_CHECK,
+ MD_ERROR_WIN_GUID_SUBSTITUTION_MADE,
+ MD_ERROR_WIN_STOPPED_ON_SYMLINK,
+ MD_ERROR_WIN_LONGJUMP,
+ MD_ERROR_WIN_PLUGPLAY_QUERY_VETOED,
+ MD_ERROR_WIN_UNWIND_CONSOLIDATE,
+ MD_ERROR_WIN_REGISTRY_HIVE_RECOVERED,
+ MD_ERROR_WIN_DLL_MIGHT_BE_INSECURE,
+ MD_ERROR_WIN_DLL_MIGHT_BE_INCOMPATIBLE,
+ MD_ERROR_WIN_DBG_EXCEPTION_NOT_HANDLED,
+ MD_ERROR_WIN_DBG_REPLY_LATER,
+ MD_ERROR_WIN_DBG_UNABLE_TO_PROVIDE_HANDLE,
+ MD_ERROR_WIN_DBG_TERMINATE_THREAD,
+ MD_ERROR_WIN_DBG_TERMINATE_PROCESS,
+ MD_ERROR_WIN_DBG_CONTROL_C,
+ MD_ERROR_WIN_DBG_PRINTEXCEPTION_C,
+ MD_ERROR_WIN_DBG_RIPEXCEPTION,
+ MD_ERROR_WIN_DBG_CONTROL_BREAK,
+ MD_ERROR_WIN_DBG_COMMAND_EXCEPTION,
+ MD_ERROR_WIN_OBJECT_NAME_EXISTS,
+ MD_ERROR_WIN_THREAD_WAS_SUSPENDED,
+ MD_ERROR_WIN_IMAGE_NOT_AT_BASE,
+ MD_ERROR_WIN_RXACT_STATE_CREATED,
+ MD_ERROR_WIN_SEGMENT_NOTIFICATION,
+ MD_ERROR_WIN_BAD_CURRENT_DIRECTORY,
+ MD_ERROR_WIN_FT_READ_RECOVERY_FROM_BACKUP,
+ MD_ERROR_WIN_FT_WRITE_RECOVERY,
+ MD_ERROR_WIN_IMAGE_MACHINE_TYPE_MISMATCH,
+ MD_ERROR_WIN_RECEIVE_PARTIAL,
+ MD_ERROR_WIN_RECEIVE_EXPEDITED,
+ MD_ERROR_WIN_RECEIVE_PARTIAL_EXPEDITED,
+ MD_ERROR_WIN_EVENT_DONE,
+ MD_ERROR_WIN_EVENT_PENDING,
+ MD_ERROR_WIN_CHECKING_FILE_SYSTEM,
+ MD_ERROR_WIN_FATAL_APP_EXIT,
+ MD_ERROR_WIN_PREDEFINED_HANDLE,
+ MD_ERROR_WIN_WAS_UNLOCKED,
+ MD_ERROR_WIN_SERVICE_NOTIFICATION,
+ MD_ERROR_WIN_WAS_LOCKED,
+ MD_ERROR_WIN_LOG_HARD_ERROR,
+ MD_ERROR_WIN_ALREADY_WIN32,
+ MD_ERROR_WIN_IMAGE_MACHINE_TYPE_MISMATCH_EXE,
+ MD_ERROR_WIN_NO_YIELD_PERFORMED,
+ MD_ERROR_WIN_TIMER_RESUME_IGNORED,
+ MD_ERROR_WIN_ARBITRATION_UNHANDLED,
+ MD_ERROR_WIN_CARDBUS_NOT_SUPPORTED,
+ MD_ERROR_WIN_MP_PROCESSOR_MISMATCH,
+ MD_ERROR_WIN_HIBERNATED,
+ MD_ERROR_WIN_RESUME_HIBERNATION,
+ MD_ERROR_WIN_FIRMWARE_UPDATED,
+ MD_ERROR_WIN_DRIVERS_LEAKING_LOCKED_PAGES,
+ MD_ERROR_WIN_WAKE_SYSTEM,
+ MD_ERROR_WIN_WAIT_1,
+ MD_ERROR_WIN_WAIT_2,
+ MD_ERROR_WIN_WAIT_3,
+ MD_ERROR_WIN_WAIT_63,
+ MD_ERROR_WIN_ABANDONED_WAIT_0,
+ MD_ERROR_WIN_ABANDONED_WAIT_63,
+ MD_ERROR_WIN_USER_APC,
+ MD_ERROR_WIN_KERNEL_APC,
+ MD_ERROR_WIN_ALERTED,
+ MD_ERROR_WIN_ELEVATION_REQUIRED,
+ MD_ERROR_WIN_REPARSE,
+ MD_ERROR_WIN_OPLOCK_BREAK_IN_PROGRESS,
+ MD_ERROR_WIN_VOLUME_MOUNTED,
+ MD_ERROR_WIN_RXACT_COMMITTED,
+ MD_ERROR_WIN_NOTIFY_CLEANUP,
+ MD_ERROR_WIN_PRIMARY_TRANSPORT_CONNECT_FAILED,
+ MD_ERROR_WIN_PAGE_FAULT_TRANSITION,
+ MD_ERROR_WIN_PAGE_FAULT_DEMAND_ZERO,
+ MD_ERROR_WIN_PAGE_FAULT_COPY_ON_WRITE,
+ MD_ERROR_WIN_PAGE_FAULT_GUARD_PAGE,
+ MD_ERROR_WIN_PAGE_FAULT_PAGING_FILE,
+ MD_ERROR_WIN_CACHE_PAGE_LOCKED,
+ MD_ERROR_WIN_CRASH_DUMP,
+ MD_ERROR_WIN_BUFFER_ALL_ZEROS,
+ MD_ERROR_WIN_REPARSE_OBJECT,
+ MD_ERROR_WIN_RESOURCE_REQUIREMENTS_CHANGED,
+ MD_ERROR_WIN_TRANSLATION_COMPLETE,
+ MD_ERROR_WIN_NOTHING_TO_TERMINATE,
+ MD_ERROR_WIN_PROCESS_NOT_IN_JOB,
+ MD_ERROR_WIN_PROCESS_IN_JOB,
+ MD_ERROR_WIN_VOLSNAP_HIBERNATE_READY,
+ MD_ERROR_WIN_FSFILTER_OP_COMPLETED_SUCCESSFULLY,
+ MD_ERROR_WIN_INTERRUPT_VECTOR_ALREADY_CONNECTED,
+ MD_ERROR_WIN_INTERRUPT_STILL_CONNECTED,
+ MD_ERROR_WIN_WAIT_FOR_OPLOCK,
+ MD_ERROR_WIN_DBG_EXCEPTION_HANDLED,
+ MD_ERROR_WIN_DBG_CONTINUE,
+ MD_ERROR_WIN_CALLBACK_POP_STACK,
+ MD_ERROR_WIN_COMPRESSION_DISABLED,
+ MD_ERROR_WIN_CANTFETCHBACKWARDS,
+ MD_ERROR_WIN_CANTSCROLLBACKWARDS,
+ MD_ERROR_WIN_ROWSNOTRELEASED,
+ MD_ERROR_WIN_BAD_ACCESSOR_FLAGS,
+ MD_ERROR_WIN_ERRORS_ENCOUNTERED,
+ MD_ERROR_WIN_NOT_CAPABLE,
+ MD_ERROR_WIN_REQUEST_OUT_OF_SEQUENCE,
+ MD_ERROR_WIN_VERSION_PARSE_ERROR,
+ MD_ERROR_WIN_BADSTARTPOSITION,
+ MD_ERROR_WIN_MEMORY_HARDWARE,
+ MD_ERROR_WIN_DISK_REPAIR_DISABLED,
+ MD_ERROR_WIN_INSUFFICIENT_RESOURCE_FOR_SPECIFIED_SHARED_SECTION_SIZE,
+ MD_ERROR_WIN_SYSTEM_POWERSTATE_TRANSITION,
+ MD_ERROR_WIN_SYSTEM_POWERSTATE_COMPLEX_TRANSITION,
+ MD_ERROR_WIN_MCA_EXCEPTION,
+ MD_ERROR_WIN_ACCESS_AUDIT_BY_POLICY,
+ MD_ERROR_WIN_ACCESS_DISABLED_NO_SAFER_UI_BY_POLICY,
+ MD_ERROR_WIN_ABANDON_HIBERFILE,
+ MD_ERROR_WIN_LOST_WRITEBEHIND_DATA_NETWORK_DISCONNECTED,
+ MD_ERROR_WIN_LOST_WRITEBEHIND_DATA_NETWORK_SERVER_ERROR,
+ MD_ERROR_WIN_LOST_WRITEBEHIND_DATA_LOCAL_DISK_ERROR,
+ MD_ERROR_WIN_BAD_MCFG_TABLE,
+ MD_ERROR_WIN_DISK_REPAIR_REDIRECTED,
+ MD_ERROR_WIN_DISK_REPAIR_UNSUCCESSFUL,
+ MD_ERROR_WIN_CORRUPT_LOG_OVERFULL,
+ MD_ERROR_WIN_CORRUPT_LOG_CORRUPTED,
+ MD_ERROR_WIN_CORRUPT_LOG_UNAVAILABLE,
+ MD_ERROR_WIN_CORRUPT_LOG_DELETED_FULL,
+ MD_ERROR_WIN_CORRUPT_LOG_CLEARED,
+ MD_ERROR_WIN_ORPHAN_NAME_EXHAUSTED,
+ MD_ERROR_WIN_OPLOCK_SWITCHED_TO_NEW_HANDLE,
+ MD_ERROR_WIN_CANNOT_GRANT_REQUESTED_OPLOCK,
+ MD_ERROR_WIN_CANNOT_BREAK_OPLOCK,
+ MD_ERROR_WIN_OPLOCK_HANDLE_CLOSED,
+ MD_ERROR_WIN_NO_ACE_CONDITION,
+ MD_ERROR_WIN_INVALID_ACE_CONDITION,
+ MD_ERROR_WIN_FILE_HANDLE_REVOKED,
+ MD_ERROR_WIN_IMAGE_AT_DIFFERENT_BASE,
+ MD_ERROR_WIN_ENCRYPTED_IO_NOT_POSSIBLE,
+ MD_ERROR_WIN_FILE_METADATA_OPTIMIZATION_IN_PROGRESS,
+ MD_ERROR_WIN_QUOTA_ACTIVITY,
+ MD_ERROR_WIN_HANDLE_REVOKED,
+ MD_ERROR_WIN_CALLBACK_INVOKE_INLINE,
+ MD_ERROR_WIN_CPU_SET_INVALID,
+ MD_ERROR_WIN_ENCLAVE_NOT_TERMINATED,
+ MD_ERROR_WIN_ENCLAVE_VIOLATION,
+ MD_ERROR_WIN_EA_ACCESS_DENIED,
+ MD_ERROR_WIN_OPERATION_ABORTED,
+ MD_ERROR_WIN_IO_INCOMPLETE,
+ MD_ERROR_WIN_IO_PENDING,
+ MD_ERROR_WIN_NOACCESS,
+ MD_ERROR_WIN_SWAPERROR,
+ MD_ERROR_WIN_STACK_OVERFLOW,
+ MD_ERROR_WIN_INVALID_MESSAGE,
+ MD_ERROR_WIN_CAN_NOT_COMPLETE,
+ MD_ERROR_WIN_INVALID_FLAGS,
+ MD_ERROR_WIN_UNRECOGNIZED_VOLUME,
+ MD_ERROR_WIN_FILE_INVALID,
+ MD_ERROR_WIN_FULLSCREEN_MODE,
+ MD_ERROR_WIN_NO_TOKEN,
+ MD_ERROR_WIN_BADDB,
+ MD_ERROR_WIN_BADKEY,
+ MD_ERROR_WIN_CANTOPEN,
+ MD_ERROR_WIN_CANTREAD,
+ MD_ERROR_WIN_CANTWRITE,
+ MD_ERROR_WIN_REGISTRY_RECOVERED,
+ MD_ERROR_WIN_REGISTRY_CORRUPT,
+ MD_ERROR_WIN_REGISTRY_IO_FAILED,
+ MD_ERROR_WIN_NOT_REGISTRY_FILE,
+ MD_ERROR_WIN_KEY_DELETED,
+ MD_ERROR_WIN_NO_LOG_SPACE,
+ MD_ERROR_WIN_KEY_HAS_CHILDREN,
+ MD_ERROR_WIN_CHILD_MUST_BE_VOLATILE,
+ MD_ERROR_WIN_NOTIFY_ENUM_DIR,
+ MD_ERROR_WIN_DEPENDENT_SERVICES_RUNNING,
+ MD_ERROR_WIN_INVALID_SERVICE_CONTROL,
+ MD_ERROR_WIN_SERVICE_REQUEST_TIMEOUT,
+ MD_ERROR_WIN_SERVICE_NO_THREAD,
+ MD_ERROR_WIN_SERVICE_DATABASE_LOCKED,
+ MD_ERROR_WIN_SERVICE_ALREADY_RUNNING,
+ MD_ERROR_WIN_INVALID_SERVICE_ACCOUNT,
+ MD_ERROR_WIN_SERVICE_DISABLED,
+ MD_ERROR_WIN_CIRCULAR_DEPENDENCY,
+ MD_ERROR_WIN_SERVICE_DOES_NOT_EXIST,
+ MD_ERROR_WIN_SERVICE_CANNOT_ACCEPT_CTRL,
+ MD_ERROR_WIN_SERVICE_NOT_ACTIVE,
+ MD_ERROR_WIN_FAILED_SERVICE_CONTROLLER_CONNECT,
+ MD_ERROR_WIN_EXCEPTION_IN_SERVICE,
+ MD_ERROR_WIN_DATABASE_DOES_NOT_EXIST,
+ MD_ERROR_WIN_SERVICE_SPECIFIC_ERROR,
+ MD_ERROR_WIN_PROCESS_ABORTED,
+ MD_ERROR_WIN_SERVICE_DEPENDENCY_FAIL,
+ MD_ERROR_WIN_SERVICE_LOGON_FAILED,
+ MD_ERROR_WIN_SERVICE_START_HANG,
+ MD_ERROR_WIN_INVALID_SERVICE_LOCK,
+ MD_ERROR_WIN_SERVICE_MARKED_FOR_DELETE,
+ MD_ERROR_WIN_SERVICE_EXISTS,
+ MD_ERROR_WIN_ALREADY_RUNNING_LKG,
+ MD_ERROR_WIN_SERVICE_DEPENDENCY_DELETED,
+ MD_ERROR_WIN_BOOT_ALREADY_ACCEPTED,
+ MD_ERROR_WIN_SERVICE_NEVER_STARTED,
+ MD_ERROR_WIN_DUPLICATE_SERVICE_NAME,
+ MD_ERROR_WIN_DIFFERENT_SERVICE_ACCOUNT,
+ MD_ERROR_WIN_CANNOT_DETECT_DRIVER_FAILURE,
+ MD_ERROR_WIN_CANNOT_DETECT_PROCESS_ABORT,
+ MD_ERROR_WIN_NO_RECOVERY_PROGRAM,
+ MD_ERROR_WIN_SERVICE_NOT_IN_EXE,
+ MD_ERROR_WIN_NOT_SAFEBOOT_SERVICE,
+ MD_ERROR_WIN_END_OF_MEDIA,
+ MD_ERROR_WIN_FILEMARK_DETECTED,
+ MD_ERROR_WIN_BEGINNING_OF_MEDIA,
+ MD_ERROR_WIN_SETMARK_DETECTED,
+ MD_ERROR_WIN_NO_DATA_DETECTED,
+ MD_ERROR_WIN_PARTITION_FAILURE,
+ MD_ERROR_WIN_INVALID_BLOCK_LENGTH,
+ MD_ERROR_WIN_DEVICE_NOT_PARTITIONED,
+ MD_ERROR_WIN_UNABLE_TO_LOCK_MEDIA,
+ MD_ERROR_WIN_UNABLE_TO_UNLOAD_MEDIA,
+ MD_ERROR_WIN_MEDIA_CHANGED,
+ MD_ERROR_WIN_BUS_RESET,
+ MD_ERROR_WIN_NO_MEDIA_IN_DRIVE,
+ MD_ERROR_WIN_NO_UNICODE_TRANSLATION,
+ MD_ERROR_WIN_DLL_INIT_FAILED,
+ MD_ERROR_WIN_SHUTDOWN_IN_PROGRESS,
+ MD_ERROR_WIN_NO_SHUTDOWN_IN_PROGRESS,
+ MD_ERROR_WIN_IO_DEVICE,
+ MD_ERROR_WIN_SERIAL_NO_DEVICE,
+ MD_ERROR_WIN_IRQ_BUSY,
+ MD_ERROR_WIN_MORE_WRITES,
+ MD_ERROR_WIN_COUNTER_TIMEOUT,
+ MD_ERROR_WIN_FLOPPY_ID_MARK_NOT_FOUND,
+ MD_ERROR_WIN_FLOPPY_WRONG_CYLINDER,
+ MD_ERROR_WIN_FLOPPY_UNKNOWN_ERROR,
+ MD_ERROR_WIN_FLOPPY_BAD_REGISTERS,
+ MD_ERROR_WIN_DISK_RECALIBRATE_FAILED,
+ MD_ERROR_WIN_DISK_OPERATION_FAILED,
+ MD_ERROR_WIN_DISK_RESET_FAILED,
+ MD_ERROR_WIN_EOM_OVERFLOW,
+ MD_ERROR_WIN_NOT_ENOUGH_SERVER_MEMORY,
+ MD_ERROR_WIN_POSSIBLE_DEADLOCK,
+ MD_ERROR_WIN_MAPPED_ALIGNMENT,
+ MD_ERROR_WIN_SET_POWER_STATE_VETOED,
+ MD_ERROR_WIN_SET_POWER_STATE_FAILED,
+ MD_ERROR_WIN_TOO_MANY_LINKS,
+ MD_ERROR_WIN_OLD_WIN_VERSION,
+ MD_ERROR_WIN_APP_WRONG_OS,
+ MD_ERROR_WIN_SINGLE_INSTANCE_APP,
+ MD_ERROR_WIN_RMODE_APP,
+ MD_ERROR_WIN_INVALID_DLL,
+ MD_ERROR_WIN_NO_ASSOCIATION,
+ MD_ERROR_WIN_DDE_FAIL,
+ MD_ERROR_WIN_DLL_NOT_FOUND,
+ MD_ERROR_WIN_NO_MORE_USER_HANDLES,
+ MD_ERROR_WIN_MESSAGE_SYNC_ONLY,
+ MD_ERROR_WIN_SOURCE_ELEMENT_EMPTY,
+ MD_ERROR_WIN_DESTINATION_ELEMENT_FULL,
+ MD_ERROR_WIN_ILLEGAL_ELEMENT_ADDRESS,
+ MD_ERROR_WIN_MAGAZINE_NOT_PRESENT,
+ MD_ERROR_WIN_DEVICE_REINITIALIZATION_NEEDED,
+ MD_ERROR_WIN_DEVICE_REQUIRES_CLEANING,
+ MD_ERROR_WIN_DEVICE_DOOR_OPEN,
+ MD_ERROR_WIN_DEVICE_NOT_CONNECTED,
+ MD_ERROR_WIN_NOT_FOUND,
+ MD_ERROR_WIN_NO_MATCH,
+ MD_ERROR_WIN_SET_NOT_FOUND,
+ MD_ERROR_WIN_POINT_NOT_FOUND,
+ MD_ERROR_WIN_NO_TRACKING_SERVICE,
+ MD_ERROR_WIN_NO_VOLUME_ID,
+ MD_ERROR_WIN_UNABLE_TO_REMOVE_REPLACED,
+ MD_ERROR_WIN_UNABLE_TO_MOVE_REPLACEMENT,
+ MD_ERROR_WIN_UNABLE_TO_MOVE_REPLACEMENT_2,
+ MD_ERROR_WIN_JOURNAL_DELETE_IN_PROGRESS,
+ MD_ERROR_WIN_JOURNAL_NOT_ACTIVE,
+ MD_ERROR_WIN_POTENTIAL_FILE_FOUND,
+ MD_ERROR_WIN_JOURNAL_ENTRY_DELETED,
+ MD_ERROR_WIN_VRF_CFG_AND_IO_ENABLED,
+ MD_ERROR_WIN_PARTITION_TERMINATING,
+ MD_ERROR_WIN_SHUTDOWN_IS_SCHEDULED,
+ MD_ERROR_WIN_SHUTDOWN_USERS_LOGGED_ON,
+ MD_ERROR_WIN_BAD_DEVICE,
+ MD_ERROR_WIN_CONNECTION_UNAVAIL,
+ MD_ERROR_WIN_DEVICE_ALREADY_REMEMBERED,
+ MD_ERROR_WIN_NO_NET_OR_BAD_PATH,
+ MD_ERROR_WIN_BAD_PROVIDER,
+ MD_ERROR_WIN_CANNOT_OPEN_PROFILE,
+ MD_ERROR_WIN_BAD_PROFILE,
+ MD_ERROR_WIN_NOT_CONTAINER,
+ MD_ERROR_WIN_EXTENDED_ERROR,
+ MD_ERROR_WIN_INVALID_GROUPNAME,
+ MD_ERROR_WIN_INVALID_COMPUTERNAME,
+ MD_ERROR_WIN_INVALID_EVENTNAME,
+ MD_ERROR_WIN_INVALID_DOMAINNAME,
+ MD_ERROR_WIN_INVALID_SERVICENAME,
+ MD_ERROR_WIN_INVALID_NETNAME,
+ MD_ERROR_WIN_INVALID_SHARENAME,
+ MD_ERROR_WIN_INVALID_PASSWORDNAME,
+ MD_ERROR_WIN_INVALID_MESSAGENAME,
+ MD_ERROR_WIN_INVALID_MESSAGEDEST,
+ MD_ERROR_WIN_SESSION_CREDENTIAL_CONFLICT,
+ MD_ERROR_WIN_REMOTE_SESSION_LIMIT_EXCEEDED,
+ MD_ERROR_WIN_DUP_DOMAINNAME,
+ MD_ERROR_WIN_NO_NETWORK,
+ MD_ERROR_WIN_CANCELLED,
+ MD_ERROR_WIN_USER_MAPPED_FILE,
+ MD_ERROR_WIN_CONNECTION_REFUSED,
+ MD_ERROR_WIN_GRACEFUL_DISCONNECT,
+ MD_ERROR_WIN_ADDRESS_ALREADY_ASSOCIATED,
+ MD_ERROR_WIN_ADDRESS_NOT_ASSOCIATED,
+ MD_ERROR_WIN_CONNECTION_INVALID,
+ MD_ERROR_WIN_CONNECTION_ACTIVE,
+ MD_ERROR_WIN_NETWORK_UNREACHABLE,
+ MD_ERROR_WIN_HOST_UNREACHABLE,
+ MD_ERROR_WIN_PROTOCOL_UNREACHABLE,
+ MD_ERROR_WIN_PORT_UNREACHABLE,
+ MD_ERROR_WIN_REQUEST_ABORTED,
+ MD_ERROR_WIN_CONNECTION_ABORTED,
+ MD_ERROR_WIN_RETRY,
+ MD_ERROR_WIN_CONNECTION_COUNT_LIMIT,
+ MD_ERROR_WIN_LOGIN_TIME_RESTRICTION,
+ MD_ERROR_WIN_LOGIN_WKSTA_RESTRICTION,
+ MD_ERROR_WIN_INCORRECT_ADDRESS,
+ MD_ERROR_WIN_ALREADY_REGISTERED,
+ MD_ERROR_WIN_SERVICE_NOT_FOUND,
+ MD_ERROR_WIN_NOT_AUTHENTICATED,
+ MD_ERROR_WIN_NOT_LOGGED_ON,
+ MD_ERROR_WIN_CONTINUE,
+ MD_ERROR_WIN_ALREADY_INITIALIZED,
+ MD_ERROR_WIN_NO_MORE_DEVICES,
+ MD_ERROR_WIN_NO_SUCH_SITE,
+ MD_ERROR_WIN_DOMAIN_CONTROLLER_EXISTS,
+ MD_ERROR_WIN_ONLY_IF_CONNECTED,
+ MD_ERROR_WIN_OVERRIDE_NOCHANGES,
+ MD_ERROR_WIN_BAD_USER_PROFILE,
+ MD_ERROR_WIN_NOT_SUPPORTED_ON_SBS,
+ MD_ERROR_WIN_SERVER_SHUTDOWN_IN_PROGRESS,
+ MD_ERROR_WIN_HOST_DOWN,
+ MD_ERROR_WIN_NON_ACCOUNT_SID,
+ MD_ERROR_WIN_NON_DOMAIN_SID,
+ MD_ERROR_WIN_APPHELP_BLOCK,
+ MD_ERROR_WIN_ACCESS_DISABLED_BY_POLICY,
+ MD_ERROR_WIN_REG_NAT_CONSUMPTION,
+ MD_ERROR_WIN_CSCSHARE_OFFLINE,
+ MD_ERROR_WIN_PKINIT_FAILURE,
+ MD_ERROR_WIN_SMARTCARD_SUBSYSTEM_FAILURE,
+ MD_ERROR_WIN_DOWNGRADE_DETECTED,
+ MD_ERROR_WIN_MACHINE_LOCKED,
+ MD_ERROR_WIN_SMB_GUEST_LOGON_BLOCKED,
+ MD_ERROR_WIN_CALLBACK_SUPPLIED_INVALID_DATA,
+ MD_ERROR_WIN_SYNC_FOREGROUND_REFRESH_REQUIRED,
+ MD_ERROR_WIN_DRIVER_BLOCKED,
+ MD_ERROR_WIN_INVALID_IMPORT_OF_NON_DLL,
+ MD_ERROR_WIN_ACCESS_DISABLED_WEBBLADE,
+ MD_ERROR_WIN_ACCESS_DISABLED_WEBBLADE_TAMPER,
+ MD_ERROR_WIN_RECOVERY_FAILURE,
+ MD_ERROR_WIN_ALREADY_FIBER,
+ MD_ERROR_WIN_ALREADY_THREAD,
+ MD_ERROR_WIN_STACK_BUFFER_OVERRUN,
+ MD_ERROR_WIN_PARAMETER_QUOTA_EXCEEDED,
+ MD_ERROR_WIN_DEBUGGER_INACTIVE,
+ MD_ERROR_WIN_DELAY_LOAD_FAILED,
+ MD_ERROR_WIN_VDM_DISALLOWED,
+ MD_ERROR_WIN_UNIDENTIFIED_ERROR,
+ MD_ERROR_WIN_INVALID_CRUNTIME_PARAMETER,
+ MD_ERROR_WIN_BEYOND_VDL,
+ MD_ERROR_WIN_INCOMPATIBLE_SERVICE_SID_TYPE,
+ MD_ERROR_WIN_DRIVER_PROCESS_TERMINATED,
+ MD_ERROR_WIN_IMPLEMENTATION_LIMIT,
+ MD_ERROR_WIN_PROCESS_IS_PROTECTED,
+ MD_ERROR_WIN_SERVICE_NOTIFY_CLIENT_LAGGING,
+ MD_ERROR_WIN_DISK_QUOTA_EXCEEDED,
+ MD_ERROR_WIN_CONTENT_BLOCKED,
+ MD_ERROR_WIN_INCOMPATIBLE_SERVICE_PRIVILEGE,
+ MD_ERROR_WIN_APP_HANG,
+ MD_ERROR_WIN_INVALID_LABEL,
+ MD_ERROR_WIN_NOT_ALL_ASSIGNED,
+ MD_ERROR_WIN_SOME_NOT_MAPPED,
+ MD_ERROR_WIN_NO_QUOTAS_FOR_ACCOUNT,
+ MD_ERROR_WIN_LOCAL_USER_SESSION_KEY,
+ MD_ERROR_WIN_NULL_LM_PASSWORD,
+ MD_ERROR_WIN_UNKNOWN_REVISION,
+ MD_ERROR_WIN_REVISION_MISMATCH,
+ MD_ERROR_WIN_INVALID_OWNER,
+ MD_ERROR_WIN_INVALID_PRIMARY_GROUP,
+ MD_ERROR_WIN_NO_IMPERSONATION_TOKEN,
+ MD_ERROR_WIN_CANT_DISABLE_MANDATORY,
+ MD_ERROR_WIN_NO_LOGON_SERVERS,
+ MD_ERROR_WIN_NO_SUCH_LOGON_SESSION,
+ MD_ERROR_WIN_NO_SUCH_PRIVILEGE,
+ MD_ERROR_WIN_PRIVILEGE_NOT_HELD,
+ MD_ERROR_WIN_INVALID_ACCOUNT_NAME,
+ MD_ERROR_WIN_USER_EXISTS,
+ MD_ERROR_WIN_NO_SUCH_USER,
+ MD_ERROR_WIN_GROUP_EXISTS,
+ MD_ERROR_WIN_NO_SUCH_GROUP,
+ MD_ERROR_WIN_MEMBER_IN_GROUP,
+ MD_ERROR_WIN_MEMBER_NOT_IN_GROUP,
+ MD_ERROR_WIN_LAST_ADMIN,
+ MD_ERROR_WIN_WRONG_PASSWORD,
+ MD_ERROR_WIN_ILL_FORMED_PASSWORD,
+ MD_ERROR_WIN_PASSWORD_RESTRICTION,
+ MD_ERROR_WIN_LOGON_FAILURE,
+ MD_ERROR_WIN_ACCOUNT_RESTRICTION,
+ MD_ERROR_WIN_INVALID_LOGON_HOURS,
+ MD_ERROR_WIN_INVALID_WORKSTATION,
+ MD_ERROR_WIN_PASSWORD_EXPIRED,
+ MD_ERROR_WIN_ACCOUNT_DISABLED,
+ MD_ERROR_WIN_NONE_MAPPED,
+ MD_ERROR_WIN_TOO_MANY_LUIDS_REQUESTED,
+ MD_ERROR_WIN_LUIDS_EXHAUSTED,
+ MD_ERROR_WIN_INVALID_SUB_AUTHORITY,
+ MD_ERROR_WIN_INVALID_ACL,
+ MD_ERROR_WIN_INVALID_SID,
+ MD_ERROR_WIN_INVALID_SECURITY_DESCR,
+ MD_ERROR_WIN_BAD_INHERITANCE_ACL,
+ MD_ERROR_WIN_SERVER_DISABLED,
+ MD_ERROR_WIN_SERVER_NOT_DISABLED,
+ MD_ERROR_WIN_INVALID_ID_AUTHORITY,
+ MD_ERROR_WIN_ALLOTTED_SPACE_EXCEEDED,
+ MD_ERROR_WIN_INVALID_GROUP_ATTRIBUTES,
+ MD_ERROR_WIN_BAD_IMPERSONATION_LEVEL,
+ MD_ERROR_WIN_CANT_OPEN_ANONYMOUS,
+ MD_ERROR_WIN_BAD_VALIDATION_CLASS,
+ MD_ERROR_WIN_BAD_TOKEN_TYPE,
+ MD_ERROR_WIN_NO_SECURITY_ON_OBJECT,
+ MD_ERROR_WIN_CANT_ACCESS_DOMAIN_INFO,
+ MD_ERROR_WIN_INVALID_SERVER_STATE,
+ MD_ERROR_WIN_INVALID_DOMAIN_STATE,
+ MD_ERROR_WIN_INVALID_DOMAIN_ROLE,
+ MD_ERROR_WIN_NO_SUCH_DOMAIN,
+ MD_ERROR_WIN_DOMAIN_EXISTS,
+ MD_ERROR_WIN_DOMAIN_LIMIT_EXCEEDED,
+ MD_ERROR_WIN_INTERNAL_DB_CORRUPTION,
+ MD_ERROR_WIN_INTERNAL_ERROR,
+ MD_ERROR_WIN_GENERIC_NOT_MAPPED,
+ MD_ERROR_WIN_BAD_DESCRIPTOR_FORMAT,
+ MD_ERROR_WIN_NOT_LOGON_PROCESS,
+ MD_ERROR_WIN_LOGON_SESSION_EXISTS,
+ MD_ERROR_WIN_NO_SUCH_PACKAGE,
+ MD_ERROR_WIN_BAD_LOGON_SESSION_STATE,
+ MD_ERROR_WIN_LOGON_SESSION_COLLISION,
+ MD_ERROR_WIN_INVALID_LOGON_TYPE,
+ MD_ERROR_WIN_CANNOT_IMPERSONATE,
+ MD_ERROR_WIN_RXACT_INVALID_STATE,
+ MD_ERROR_WIN_RXACT_COMMIT_FAILURE,
+ MD_ERROR_WIN_SPECIAL_ACCOUNT,
+ MD_ERROR_WIN_SPECIAL_GROUP,
+ MD_ERROR_WIN_SPECIAL_USER,
+ MD_ERROR_WIN_MEMBERS_PRIMARY_GROUP,
+ MD_ERROR_WIN_TOKEN_ALREADY_IN_USE,
+ MD_ERROR_WIN_NO_SUCH_ALIAS,
+ MD_ERROR_WIN_MEMBER_NOT_IN_ALIAS,
+ MD_ERROR_WIN_MEMBER_IN_ALIAS,
+ MD_ERROR_WIN_ALIAS_EXISTS,
+ MD_ERROR_WIN_LOGON_NOT_GRANTED,
+ MD_ERROR_WIN_TOO_MANY_SECRETS,
+ MD_ERROR_WIN_SECRET_TOO_LONG,
+ MD_ERROR_WIN_INTERNAL_DB_ERROR,
+ MD_ERROR_WIN_TOO_MANY_CONTEXT_IDS,
+ MD_ERROR_WIN_LOGON_TYPE_NOT_GRANTED,
+ MD_ERROR_WIN_NT_CROSS_ENCRYPTION_REQUIRED,
+ MD_ERROR_WIN_NO_SUCH_MEMBER,
+ MD_ERROR_WIN_INVALID_MEMBER,
+ MD_ERROR_WIN_TOO_MANY_SIDS,
+ MD_ERROR_WIN_LM_CROSS_ENCRYPTION_REQUIRED,
+ MD_ERROR_WIN_NO_INHERITANCE,
+ MD_ERROR_WIN_FILE_CORRUPT,
+ MD_ERROR_WIN_DISK_CORRUPT,
+ MD_ERROR_WIN_NO_USER_SESSION_KEY,
+ MD_ERROR_WIN_LICENSE_QUOTA_EXCEEDED,
+ MD_ERROR_WIN_WRONG_TARGET_NAME,
+ MD_ERROR_WIN_MUTUAL_AUTH_FAILED,
+ MD_ERROR_WIN_TIME_SKEW,
+ MD_ERROR_WIN_CURRENT_DOMAIN_NOT_ALLOWED,
+ MD_ERROR_WIN_INVALID_WINDOW_HANDLE,
+ MD_ERROR_WIN_INVALID_MENU_HANDLE,
+ MD_ERROR_WIN_INVALID_CURSOR_HANDLE,
+ MD_ERROR_WIN_INVALID_ACCEL_HANDLE,
+ MD_ERROR_WIN_INVALID_HOOK_HANDLE,
+ MD_ERROR_WIN_INVALID_DWP_HANDLE,
+ MD_ERROR_WIN_TLW_WITH_WSCHILD,
+ MD_ERROR_WIN_CANNOT_FIND_WND_CLASS,
+ MD_ERROR_WIN_WINDOW_OF_OTHER_THREAD,
+ MD_ERROR_WIN_HOTKEY_ALREADY_REGISTERED,
+ MD_ERROR_WIN_CLASS_ALREADY_EXISTS,
+ MD_ERROR_WIN_CLASS_DOES_NOT_EXIST,
+ MD_ERROR_WIN_CLASS_HAS_WINDOWS,
+ MD_ERROR_WIN_INVALID_INDEX,
+ MD_ERROR_WIN_INVALID_ICON_HANDLE,
+ MD_ERROR_WIN_PRIVATE_DIALOG_INDEX,
+ MD_ERROR_WIN_LISTBOX_ID_NOT_FOUND,
+ MD_ERROR_WIN_NO_WILDCARD_CHARACTERS,
+ MD_ERROR_WIN_CLIPBOARD_NOT_OPEN,
+ MD_ERROR_WIN_HOTKEY_NOT_REGISTERED,
+ MD_ERROR_WIN_WINDOW_NOT_DIALOG,
+ MD_ERROR_WIN_CONTROL_ID_NOT_FOUND,
+ MD_ERROR_WIN_INVALID_COMBOBOX_MESSAGE,
+ MD_ERROR_WIN_WINDOW_NOT_COMBOBOX,
+ MD_ERROR_WIN_INVALID_EDIT_HEIGHT,
+ MD_ERROR_WIN_DC_NOT_FOUND,
+ MD_ERROR_WIN_INVALID_HOOK_FILTER,
+ MD_ERROR_WIN_INVALID_FILTER_PROC,
+ MD_ERROR_WIN_HOOK_NEEDS_HMOD,
+ MD_ERROR_WIN_GLOBAL_ONLY_HOOK,
+ MD_ERROR_WIN_JOURNAL_HOOK_SET,
+ MD_ERROR_WIN_HOOK_NOT_INSTALLED,
+ MD_ERROR_WIN_INVALID_LB_MESSAGE,
+ MD_ERROR_WIN_SETCOUNT_ON_BAD_LB,
+ MD_ERROR_WIN_LB_WITHOUT_TABSTOPS,
+ MD_ERROR_WIN_DESTROY_OBJECT_OF_OTHER_THREAD,
+ MD_ERROR_WIN_CHILD_WINDOW_MENU,
+ MD_ERROR_WIN_NO_SYSTEM_MENU,
+ MD_ERROR_WIN_INVALID_MSGBOX_STYLE,
+ MD_ERROR_WIN_INVALID_SPI_VALUE,
+ MD_ERROR_WIN_SCREEN_ALREADY_LOCKED,
+ MD_ERROR_WIN_HWNDS_HAVE_DIFF_PARENT,
+ MD_ERROR_WIN_NOT_CHILD_WINDOW,
+ MD_ERROR_WIN_INVALID_GW_COMMAND,
+ MD_ERROR_WIN_INVALID_THREAD_ID,
+ MD_ERROR_WIN_NON_MDICHILD_WINDOW,
+ MD_ERROR_WIN_POPUP_ALREADY_ACTIVE,
+ MD_ERROR_WIN_NO_SCROLLBARS,
+ MD_ERROR_WIN_INVALID_SCROLLBAR_RANGE,
+ MD_ERROR_WIN_INVALID_SHOWWIN_COMMAND,
+ MD_ERROR_WIN_NO_SYSTEM_RESOURCES,
+ MD_ERROR_WIN_NONPAGED_SYSTEM_RESOURCES,
+ MD_ERROR_WIN_PAGED_SYSTEM_RESOURCES,
+ MD_ERROR_WIN_WORKING_SET_QUOTA,
+ MD_ERROR_WIN_PAGEFILE_QUOTA,
+ MD_ERROR_WIN_COMMITMENT_LIMIT,
+ MD_ERROR_WIN_MENU_ITEM_NOT_FOUND,
+ MD_ERROR_WIN_INVALID_KEYBOARD_HANDLE,
+ MD_ERROR_WIN_HOOK_TYPE_NOT_ALLOWED,
+ MD_ERROR_WIN_REQUIRES_INTERACTIVE_WINDOWSTATION,
+ MD_ERROR_WIN_TIMEOUT,
+ MD_ERROR_WIN_INVALID_MONITOR_HANDLE,
+ MD_ERROR_WIN_INCORRECT_SIZE,
+ MD_ERROR_WIN_SYMLINK_CLASS_DISABLED,
+ MD_ERROR_WIN_SYMLINK_NOT_SUPPORTED,
+ MD_ERROR_WIN_XML_PARSE_ERROR,
+ MD_ERROR_WIN_XMLDSIG_ERROR,
+ MD_ERROR_WIN_RESTART_APPLICATION,
+ MD_ERROR_WIN_WRONG_COMPARTMENT,
+ MD_ERROR_WIN_AUTHIP_FAILURE,
+ MD_ERROR_WIN_NO_NVRAM_RESOURCES,
+ MD_ERROR_WIN_NOT_GUI_PROCESS,
+ MD_ERROR_WIN_EVENTLOG_FILE_CORRUPT,
+ MD_ERROR_WIN_EVENTLOG_CANT_START,
+ MD_ERROR_WIN_LOG_FILE_FULL,
+ MD_ERROR_WIN_EVENTLOG_FILE_CHANGED,
+ MD_ERROR_WIN_CONTAINER_ASSIGNED,
+ MD_ERROR_WIN_JOB_NO_CONTAINER,
+ MD_ERROR_WIN_INVALID_TASK_NAME,
+ MD_ERROR_WIN_INVALID_TASK_INDEX,
+ MD_ERROR_WIN_THREAD_ALREADY_IN_TASK,
+ MD_ERROR_WIN_INSTALL_SERVICE_FAILURE,
+ MD_ERROR_WIN_INSTALL_USEREXIT,
+ MD_ERROR_WIN_INSTALL_FAILURE,
+ MD_ERROR_WIN_INSTALL_SUSPEND,
+ MD_ERROR_WIN_UNKNOWN_PRODUCT,
+ MD_ERROR_WIN_UNKNOWN_FEATURE,
+ MD_ERROR_WIN_UNKNOWN_COMPONENT,
+ MD_ERROR_WIN_UNKNOWN_PROPERTY,
+ MD_ERROR_WIN_INVALID_HANDLE_STATE,
+ MD_ERROR_WIN_BAD_CONFIGURATION,
+ MD_ERROR_WIN_INDEX_ABSENT,
+ MD_ERROR_WIN_INSTALL_SOURCE_ABSENT,
+ MD_ERROR_WIN_INSTALL_PACKAGE_VERSION,
+ MD_ERROR_WIN_PRODUCT_UNINSTALLED,
+ MD_ERROR_WIN_BAD_QUERY_SYNTAX,
+ MD_ERROR_WIN_INVALID_FIELD,
+ MD_ERROR_WIN_DEVICE_REMOVED,
+ MD_ERROR_WIN_INSTALL_ALREADY_RUNNING,
+ MD_ERROR_WIN_INSTALL_PACKAGE_OPEN_FAILED,
+ MD_ERROR_WIN_INSTALL_PACKAGE_INVALID,
+ MD_ERROR_WIN_INSTALL_UI_FAILURE,
+ MD_ERROR_WIN_INSTALL_LOG_FAILURE,
+ MD_ERROR_WIN_INSTALL_LANGUAGE_UNSUPPORTED,
+ MD_ERROR_WIN_INSTALL_TRANSFORM_FAILURE,
+ MD_ERROR_WIN_INSTALL_PACKAGE_REJECTED,
+ MD_ERROR_WIN_FUNCTION_NOT_CALLED,
+ MD_ERROR_WIN_FUNCTION_FAILED,
+ MD_ERROR_WIN_INVALID_TABLE,
+ MD_ERROR_WIN_DATATYPE_MISMATCH,
+ MD_ERROR_WIN_UNSUPPORTED_TYPE,
+ MD_ERROR_WIN_CREATE_FAILED,
+ MD_ERROR_WIN_INSTALL_TEMP_UNWRITABLE,
+ MD_ERROR_WIN_INSTALL_PLATFORM_UNSUPPORTED,
+ MD_ERROR_WIN_INSTALL_NOTUSED,
+ MD_ERROR_WIN_PATCH_PACKAGE_OPEN_FAILED,
+ MD_ERROR_WIN_PATCH_PACKAGE_INVALID,
+ MD_ERROR_WIN_PATCH_PACKAGE_UNSUPPORTED,
+ MD_ERROR_WIN_PRODUCT_VERSION,
+ MD_ERROR_WIN_INVALID_COMMAND_LINE,
+ MD_ERROR_WIN_INSTALL_REMOTE_DISALLOWED,
+ MD_ERROR_WIN_SUCCESS_REBOOT_INITIATED,
+ MD_ERROR_WIN_PATCH_TARGET_NOT_FOUND,
+ MD_ERROR_WIN_PATCH_PACKAGE_REJECTED,
+ MD_ERROR_WIN_INSTALL_TRANSFORM_REJECTED,
+ MD_ERROR_WIN_INSTALL_REMOTE_PROHIBITED,
+ MD_ERROR_WIN_PATCH_REMOVAL_UNSUPPORTED,
+ MD_ERROR_WIN_UNKNOWN_PATCH,
+ MD_ERROR_WIN_PATCH_NO_SEQUENCE,
+ MD_ERROR_WIN_PATCH_REMOVAL_DISALLOWED,
+ MD_ERROR_WIN_INVALID_PATCH_XML,
+ MD_ERROR_WIN_PATCH_MANAGED_ADVERTISED_PRODUCT,
+ MD_ERROR_WIN_INSTALL_SERVICE_SAFEBOOT,
+ MD_ERROR_WIN_FAIL_FAST_EXCEPTION,
+ MD_ERROR_WIN_INSTALL_REJECTED,
+ MD_ERROR_WIN_DYNAMIC_CODE_BLOCKED,
+ MD_ERROR_WIN_NOT_SAME_OBJECT,
+ MD_ERROR_WIN_STRICT_CFG_VIOLATION,
+ MD_ERROR_WIN_SET_CONTEXT_DENIED,
+ MD_ERROR_WIN_CROSS_PARTITION_VIOLATION,
+ MD_ERROR_WIN_RETURN_ADDRESS_HIJACK_ATTEMPT,
+ MD_ERROR_WIN_INVALID_USER_BUFFER,
+ MD_ERROR_WIN_UNRECOGNIZED_MEDIA,
+ MD_ERROR_WIN_NO_TRUST_LSA_SECRET,
+ MD_ERROR_WIN_NO_TRUST_SAM_ACCOUNT,
+ MD_ERROR_WIN_TRUSTED_DOMAIN_FAILURE,
+ MD_ERROR_WIN_TRUSTED_RELATIONSHIP_FAILURE,
+ MD_ERROR_WIN_TRUST_FAILURE,
+ MD_ERROR_WIN_NETLOGON_NOT_STARTED,
+ MD_ERROR_WIN_ACCOUNT_EXPIRED,
+ MD_ERROR_WIN_REDIRECTOR_HAS_OPEN_HANDLES,
+ MD_ERROR_WIN_PRINTER_DRIVER_ALREADY_INSTALLED,
+ MD_ERROR_WIN_UNKNOWN_PORT,
+ MD_ERROR_WIN_UNKNOWN_PRINTER_DRIVER,
+ MD_ERROR_WIN_UNKNOWN_PRINTPROCESSOR,
+ MD_ERROR_WIN_INVALID_SEPARATOR_FILE,
+ MD_ERROR_WIN_INVALID_PRIORITY,
+ MD_ERROR_WIN_INVALID_PRINTER_NAME,
+ MD_ERROR_WIN_PRINTER_ALREADY_EXISTS,
+ MD_ERROR_WIN_INVALID_PRINTER_COMMAND,
+ MD_ERROR_WIN_INVALID_DATATYPE,
+ MD_ERROR_WIN_INVALID_ENVIRONMENT,
+ MD_ERROR_WIN_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT,
+ MD_ERROR_WIN_NOLOGON_WORKSTATION_TRUST_ACCOUNT,
+ MD_ERROR_WIN_NOLOGON_SERVER_TRUST_ACCOUNT,
+ MD_ERROR_WIN_DOMAIN_TRUST_INCONSISTENT,
+ MD_ERROR_WIN_SERVER_HAS_OPEN_HANDLES,
+ MD_ERROR_WIN_RESOURCE_DATA_NOT_FOUND,
+ MD_ERROR_WIN_RESOURCE_TYPE_NOT_FOUND,
+ MD_ERROR_WIN_RESOURCE_NAME_NOT_FOUND,
+ MD_ERROR_WIN_RESOURCE_LANG_NOT_FOUND,
+ MD_ERROR_WIN_NOT_ENOUGH_QUOTA,
+ MD_ERROR_WIN_INVALID_TIME,
+ MD_ERROR_WIN_INVALID_FORM_NAME,
+ MD_ERROR_WIN_INVALID_FORM_SIZE,
+ MD_ERROR_WIN_ALREADY_WAITING,
+ MD_ERROR_WIN_PRINTER_DELETED,
+ MD_ERROR_WIN_INVALID_PRINTER_STATE,
+ MD_ERROR_WIN_PASSWORD_MUST_CHANGE,
+ MD_ERROR_WIN_DOMAIN_CONTROLLER_NOT_FOUND,
+ MD_ERROR_WIN_ACCOUNT_LOCKED_OUT,
+ MD_ERROR_WIN_NO_SITENAME,
+ MD_ERROR_WIN_CANT_ACCESS_FILE,
+ MD_ERROR_WIN_CANT_RESOLVE_FILENAME,
+ MD_ERROR_WIN_KM_DRIVER_BLOCKED,
+ MD_ERROR_WIN_CONTEXT_EXPIRED,
+ MD_ERROR_WIN_PER_USER_TRUST_QUOTA_EXCEEDED,
+ MD_ERROR_WIN_ALL_USER_TRUST_QUOTA_EXCEEDED,
+ MD_ERROR_WIN_USER_DELETE_TRUST_QUOTA_EXCEEDED,
+ MD_ERROR_WIN_AUTHENTICATION_FIREWALL_FAILED,
+ MD_ERROR_WIN_REMOTE_PRINT_CONNECTIONS_BLOCKED,
+ MD_ERROR_WIN_NTLM_BLOCKED,
+ MD_ERROR_WIN_PASSWORD_CHANGE_REQUIRED,
+ MD_ERROR_WIN_LOST_MODE_LOGON_RESTRICTION,
+ MD_ERROR_WIN_INVALID_PIXEL_FORMAT,
+ MD_ERROR_WIN_BAD_DRIVER,
+ MD_ERROR_WIN_INVALID_WINDOW_STYLE,
+ MD_ERROR_WIN_METAFILE_NOT_SUPPORTED,
+ MD_ERROR_WIN_TRANSFORM_NOT_SUPPORTED,
+ MD_ERROR_WIN_CLIPPING_NOT_SUPPORTED,
+ MD_ERROR_WIN_INVALID_CMM,
+ MD_ERROR_WIN_INVALID_PROFILE,
+ MD_ERROR_WIN_TAG_NOT_FOUND,
+ MD_ERROR_WIN_TAG_NOT_PRESENT,
+ MD_ERROR_WIN_DUPLICATE_TAG,
+ MD_ERROR_WIN_PROFILE_NOT_ASSOCIATED_WITH_DEVICE,
+ MD_ERROR_WIN_PROFILE_NOT_FOUND,
+ MD_ERROR_WIN_INVALID_COLORSPACE,
+ MD_ERROR_WIN_ICM_NOT_ENABLED,
+ MD_ERROR_WIN_DELETING_ICM_XFORM,
+ MD_ERROR_WIN_INVALID_TRANSFORM,
+ MD_ERROR_WIN_COLORSPACE_MISMATCH,
+ MD_ERROR_WIN_INVALID_COLORINDEX,
+ MD_ERROR_WIN_PROFILE_DOES_NOT_MATCH_DEVICE,
+ MD_ERROR_WIN_CONNECTED_OTHER_PASSWORD,
+ MD_ERROR_WIN_CONNECTED_OTHER_PASSWORD_DEFAULT,
+ MD_ERROR_WIN_BAD_USERNAME,
+ MD_ERROR_WIN_NOT_CONNECTED,
+ MD_ERROR_WIN_OPEN_FILES,
+ MD_ERROR_WIN_ACTIVE_CONNECTIONS,
+ MD_ERROR_WIN_DEVICE_IN_USE,
+ MD_ERROR_WIN_UNKNOWN_PRINT_MONITOR,
+ MD_ERROR_WIN_PRINTER_DRIVER_IN_USE,
+ MD_ERROR_WIN_SPOOL_FILE_NOT_FOUND,
+ MD_ERROR_WIN_SPL_NO_STARTDOC,
+ MD_ERROR_WIN_SPL_NO_ADDJOB,
+ MD_ERROR_WIN_PRINT_PROCESSOR_ALREADY_INSTALLED,
+ MD_ERROR_WIN_PRINT_MONITOR_ALREADY_INSTALLED,
+ MD_ERROR_WIN_INVALID_PRINT_MONITOR,
+ MD_ERROR_WIN_PRINT_MONITOR_IN_USE,
+ MD_ERROR_WIN_PRINTER_HAS_JOBS_QUEUED,
+ MD_ERROR_WIN_SUCCESS_REBOOT_REQUIRED,
+ MD_ERROR_WIN_SUCCESS_RESTART_REQUIRED,
+ MD_ERROR_WIN_PRINTER_NOT_FOUND,
+ MD_ERROR_WIN_PRINTER_DRIVER_WARNED,
+ MD_ERROR_WIN_PRINTER_DRIVER_BLOCKED,
+ MD_ERROR_WIN_PRINTER_DRIVER_PACKAGE_IN_USE,
+ MD_ERROR_WIN_CORE_DRIVER_PACKAGE_NOT_FOUND,
+ MD_ERROR_WIN_FAIL_REBOOT_REQUIRED,
+ MD_ERROR_WIN_FAIL_REBOOT_INITIATED,
+ MD_ERROR_WIN_PRINTER_DRIVER_DOWNLOAD_NEEDED,
+ MD_ERROR_WIN_PRINT_JOB_RESTART_REQUIRED,
+ MD_ERROR_WIN_INVALID_PRINTER_DRIVER_MANIFEST,
+ MD_ERROR_WIN_PRINTER_NOT_SHAREABLE,
+ MD_ERROR_WIN_REQUEST_PAUSED,
+ MD_ERROR_WIN_APPEXEC_CONDITION_NOT_SATISFIED,
+ MD_ERROR_WIN_APPEXEC_HANDLE_INVALIDATED,
+ MD_ERROR_WIN_APPEXEC_INVALID_HOST_GENERATION,
+ MD_ERROR_WIN_APPEXEC_UNEXPECTED_PROCESS_REGISTRATION,
+ MD_ERROR_WIN_APPEXEC_INVALID_HOST_STATE,
+ MD_ERROR_WIN_APPEXEC_NO_DONOR,
+ MD_ERROR_WIN_APPEXEC_HOST_ID_MISMATCH,
+ MD_ERROR_WIN_APPEXEC_UNKNOWN_USER,
+ MD_ERROR_WIN_IO_REISSUE_AS_CACHED,
+ MD_ERROR_WIN_WINS_INTERNAL,
+ MD_ERROR_WIN_CAN_NOT_DEL_LOCAL_WINS,
+ MD_ERROR_WIN_STATIC_INIT,
+ MD_ERROR_WIN_INC_BACKUP,
+ MD_ERROR_WIN_FULL_BACKUP,
+ MD_ERROR_WIN_REC_NON_EXISTENT,
+ MD_ERROR_WIN_RPL_NOT_ALLOWED,
+ MD_ERROR_WIN_DHCP_ADDRESS_CONFLICT,
+ MD_ERROR_WIN_WMI_GUID_NOT_FOUND,
+ MD_ERROR_WIN_WMI_INSTANCE_NOT_FOUND,
+ MD_ERROR_WIN_WMI_ITEMID_NOT_FOUND,
+ MD_ERROR_WIN_WMI_TRY_AGAIN,
+ MD_ERROR_WIN_WMI_DP_NOT_FOUND,
+ MD_ERROR_WIN_WMI_UNRESOLVED_INSTANCE_REF,
+ MD_ERROR_WIN_WMI_ALREADY_ENABLED,
+ MD_ERROR_WIN_WMI_GUID_DISCONNECTED,
+ MD_ERROR_WIN_WMI_SERVER_UNAVAILABLE,
+ MD_ERROR_WIN_WMI_DP_FAILED,
+ MD_ERROR_WIN_WMI_INVALID_MOF,
+ MD_ERROR_WIN_WMI_INVALID_REGINFO,
+ MD_ERROR_WIN_WMI_ALREADY_DISABLED,
+ MD_ERROR_WIN_WMI_READ_ONLY,
+ MD_ERROR_WIN_WMI_SET_FAILURE,
+ MD_ERROR_WIN_NOT_APPCONTAINER,
+ MD_ERROR_WIN_APPCONTAINER_REQUIRED,
+ MD_ERROR_WIN_NOT_SUPPORTED_IN_APPCONTAINER,
+ MD_ERROR_WIN_INVALID_PACKAGE_SID_LENGTH,
+ MD_ERROR_WIN_INVALID_MEDIA,
+ MD_ERROR_WIN_INVALID_LIBRARY,
+ MD_ERROR_WIN_INVALID_MEDIA_POOL,
+ MD_ERROR_WIN_DRIVE_MEDIA_MISMATCH,
+ MD_ERROR_WIN_MEDIA_OFFLINE,
+ MD_ERROR_WIN_LIBRARY_OFFLINE,
+ MD_ERROR_WIN_EMPTY,
+ MD_ERROR_WIN_NOT_EMPTY,
+ MD_ERROR_WIN_MEDIA_UNAVAILABLE,
+ MD_ERROR_WIN_RESOURCE_DISABLED,
+ MD_ERROR_WIN_INVALID_CLEANER,
+ MD_ERROR_WIN_UNABLE_TO_CLEAN,
+ MD_ERROR_WIN_OBJECT_NOT_FOUND,
+ MD_ERROR_WIN_DATABASE_FAILURE,
+ MD_ERROR_WIN_DATABASE_FULL,
+ MD_ERROR_WIN_MEDIA_INCOMPATIBLE,
+ MD_ERROR_WIN_RESOURCE_NOT_PRESENT,
+ MD_ERROR_WIN_INVALID_OPERATION,
+ MD_ERROR_WIN_MEDIA_NOT_AVAILABLE,
+ MD_ERROR_WIN_DEVICE_NOT_AVAILABLE,
+ MD_ERROR_WIN_REQUEST_REFUSED,
+ MD_ERROR_WIN_INVALID_DRIVE_OBJECT,
+ MD_ERROR_WIN_LIBRARY_FULL,
+ MD_ERROR_WIN_MEDIUM_NOT_ACCESSIBLE,
+ MD_ERROR_WIN_UNABLE_TO_LOAD_MEDIUM,
+ MD_ERROR_WIN_UNABLE_TO_INVENTORY_DRIVE,
+ MD_ERROR_WIN_UNABLE_TO_INVENTORY_SLOT,
+ MD_ERROR_WIN_UNABLE_TO_INVENTORY_TRANSPORT,
+ MD_ERROR_WIN_TRANSPORT_FULL,
+ MD_ERROR_WIN_CONTROLLING_IEPORT,
+ MD_ERROR_WIN_UNABLE_TO_EJECT_MOUNTED_MEDIA,
+ MD_ERROR_WIN_CLEANER_SLOT_SET,
+ MD_ERROR_WIN_CLEANER_SLOT_NOT_SET,
+ MD_ERROR_WIN_CLEANER_CARTRIDGE_SPENT,
+ MD_ERROR_WIN_UNEXPECTED_OMID,
+ MD_ERROR_WIN_CANT_DELETE_LAST_ITEM,
+ MD_ERROR_WIN_MESSAGE_EXCEEDS_MAX_SIZE,
+ MD_ERROR_WIN_VOLUME_CONTAINS_SYS_FILES,
+ MD_ERROR_WIN_INDIGENOUS_TYPE,
+ MD_ERROR_WIN_NO_SUPPORTING_DRIVES,
+ MD_ERROR_WIN_CLEANER_CARTRIDGE_INSTALLED,
+ MD_ERROR_WIN_IEPORT_FULL,
+ MD_ERROR_WIN_FILE_OFFLINE,
+ MD_ERROR_WIN_REMOTE_STORAGE_NOT_ACTIVE,
+ MD_ERROR_WIN_REMOTE_STORAGE_MEDIA_ERROR,
+ MD_ERROR_WIN_NOT_A_REPARSE_POINT,
+ MD_ERROR_WIN_REPARSE_ATTRIBUTE_CONFLICT,
+ MD_ERROR_WIN_INVALID_REPARSE_DATA,
+ MD_ERROR_WIN_REPARSE_TAG_INVALID,
+ MD_ERROR_WIN_REPARSE_TAG_MISMATCH,
+ MD_ERROR_WIN_REPARSE_POINT_ENCOUNTERED,
+ MD_ERROR_WIN_APP_DATA_NOT_FOUND,
+ MD_ERROR_WIN_APP_DATA_EXPIRED,
+ MD_ERROR_WIN_APP_DATA_CORRUPT,
+ MD_ERROR_WIN_APP_DATA_LIMIT_EXCEEDED,
+ MD_ERROR_WIN_APP_DATA_REBOOT_REQUIRED,
+ MD_ERROR_WIN_SECUREBOOT_ROLLBACK_DETECTED,
+ MD_ERROR_WIN_SECUREBOOT_POLICY_VIOLATION,
+ MD_ERROR_WIN_SECUREBOOT_INVALID_POLICY,
+ MD_ERROR_WIN_SECUREBOOT_POLICY_PUBLISHER_NOT_FOUND,
+ MD_ERROR_WIN_SECUREBOOT_POLICY_NOT_SIGNED,
+ MD_ERROR_WIN_SECUREBOOT_NOT_ENABLED,
+ MD_ERROR_WIN_SECUREBOOT_FILE_REPLACED,
+ MD_ERROR_WIN_SECUREBOOT_POLICY_NOT_AUTHORIZED,
+ MD_ERROR_WIN_SECUREBOOT_POLICY_UNKNOWN,
+ MD_ERROR_WIN_SECUREBOOT_POLICY_MISSING_ANTIROLLBACKVERSION,
+ MD_ERROR_WIN_SECUREBOOT_PLATFORM_ID_MISMATCH,
+ MD_ERROR_WIN_SECUREBOOT_POLICY_ROLLBACK_DETECTED,
+ MD_ERROR_WIN_SECUREBOOT_POLICY_UPGRADE_MISMATCH,
+ MD_ERROR_WIN_SECUREBOOT_REQUIRED_POLICY_FILE_MISSING,
+ MD_ERROR_WIN_SECUREBOOT_NOT_BASE_POLICY,
+ MD_ERROR_WIN_SECUREBOOT_NOT_SUPPLEMENTAL_POLICY,
+ MD_ERROR_WIN_OFFLOAD_READ_FLT_NOT_SUPPORTED,
+ MD_ERROR_WIN_OFFLOAD_WRITE_FLT_NOT_SUPPORTED,
+ MD_ERROR_WIN_OFFLOAD_READ_FILE_NOT_SUPPORTED,
+ MD_ERROR_WIN_OFFLOAD_WRITE_FILE_NOT_SUPPORTED,
+ MD_ERROR_WIN_ALREADY_HAS_STREAM_ID,
+ MD_ERROR_WIN_SMR_GARBAGE_COLLECTION_REQUIRED,
+ MD_ERROR_WIN_WOF_WIM_HEADER_CORRUPT,
+ MD_ERROR_WIN_WOF_WIM_RESOURCE_TABLE_CORRUPT,
+ MD_ERROR_WIN_WOF_FILE_RESOURCE_TABLE_CORRUPT,
+ MD_ERROR_WIN_VOLUME_NOT_SIS_ENABLED,
+ MD_ERROR_WIN_SYSTEM_INTEGRITY_ROLLBACK_DETECTED,
+ MD_ERROR_WIN_SYSTEM_INTEGRITY_POLICY_VIOLATION,
+ MD_ERROR_WIN_SYSTEM_INTEGRITY_INVALID_POLICY,
+ MD_ERROR_WIN_SYSTEM_INTEGRITY_POLICY_NOT_SIGNED,
+ MD_ERROR_WIN_SYSTEM_INTEGRITY_TOO_MANY_POLICIES,
+ MD_ERROR_WIN_SYSTEM_INTEGRITY_SUPPLEMENTAL_POLICY_NOT_AUTHORIZED,
+ MD_ERROR_WIN_VSM_NOT_INITIALIZED,
+ MD_ERROR_WIN_VSM_DMA_PROTECTION_NOT_IN_USE,
+ MD_ERROR_WIN_PLATFORM_MANIFEST_NOT_AUTHORIZED,
+ MD_ERROR_WIN_PLATFORM_MANIFEST_INVALID,
+ MD_ERROR_WIN_PLATFORM_MANIFEST_FILE_NOT_AUTHORIZED,
+ MD_ERROR_WIN_PLATFORM_MANIFEST_CATALOG_NOT_AUTHORIZED,
+ MD_ERROR_WIN_PLATFORM_MANIFEST_BINARY_ID_NOT_FOUND,
+ MD_ERROR_WIN_PLATFORM_MANIFEST_NOT_ACTIVE,
+ MD_ERROR_WIN_PLATFORM_MANIFEST_NOT_SIGNED,
+ MD_ERROR_WIN_DEPENDENT_RESOURCE_EXISTS,
+ MD_ERROR_WIN_DEPENDENCY_NOT_FOUND,
+ MD_ERROR_WIN_DEPENDENCY_ALREADY_EXISTS,
+ MD_ERROR_WIN_RESOURCE_NOT_ONLINE,
+ MD_ERROR_WIN_HOST_NODE_NOT_AVAILABLE,
+ MD_ERROR_WIN_RESOURCE_NOT_AVAILABLE,
+ MD_ERROR_WIN_RESOURCE_NOT_FOUND,
+ MD_ERROR_WIN_SHUTDOWN_CLUSTER,
+ MD_ERROR_WIN_CANT_EVICT_ACTIVE_NODE,
+ MD_ERROR_WIN_OBJECT_ALREADY_EXISTS,
+ MD_ERROR_WIN_OBJECT_IN_LIST,
+ MD_ERROR_WIN_GROUP_NOT_AVAILABLE,
+ MD_ERROR_WIN_GROUP_NOT_FOUND,
+ MD_ERROR_WIN_GROUP_NOT_ONLINE,
+ MD_ERROR_WIN_HOST_NODE_NOT_RESOURCE_OWNER,
+ MD_ERROR_WIN_HOST_NODE_NOT_GROUP_OWNER,
+ MD_ERROR_WIN_RESMON_CREATE_FAILED,
+ MD_ERROR_WIN_RESMON_ONLINE_FAILED,
+ MD_ERROR_WIN_RESOURCE_ONLINE,
+ MD_ERROR_WIN_QUORUM_RESOURCE,
+ MD_ERROR_WIN_NOT_QUORUM_CAPABLE,
+ MD_ERROR_WIN_CLUSTER_SHUTTING_DOWN,
+ MD_ERROR_WIN_INVALID_STATE,
+ MD_ERROR_WIN_RESOURCE_PROPERTIES_STORED,
+ MD_ERROR_WIN_NOT_QUORUM_CLASS,
+ MD_ERROR_WIN_CORE_RESOURCE,
+ MD_ERROR_WIN_QUORUM_RESOURCE_ONLINE_FAILED,
+ MD_ERROR_WIN_QUORUMLOG_OPEN_FAILED,
+ MD_ERROR_WIN_CLUSTERLOG_CORRUPT,
+ MD_ERROR_WIN_CLUSTERLOG_RECORD_EXCEEDS_MAXSIZE,
+ MD_ERROR_WIN_CLUSTERLOG_EXCEEDS_MAXSIZE,
+ MD_ERROR_WIN_CLUSTERLOG_CHKPOINT_NOT_FOUND,
+ MD_ERROR_WIN_CLUSTERLOG_NOT_ENOUGH_SPACE,
+ MD_ERROR_WIN_QUORUM_OWNER_ALIVE,
+ MD_ERROR_WIN_NETWORK_NOT_AVAILABLE,
+ MD_ERROR_WIN_NODE_NOT_AVAILABLE,
+ MD_ERROR_WIN_ALL_NODES_NOT_AVAILABLE,
+ MD_ERROR_WIN_RESOURCE_FAILED,
+ MD_ERROR_WIN_CLUSTER_INVALID_NODE,
+ MD_ERROR_WIN_CLUSTER_NODE_EXISTS,
+ MD_ERROR_WIN_CLUSTER_JOIN_IN_PROGRESS,
+ MD_ERROR_WIN_CLUSTER_NODE_NOT_FOUND,
+ MD_ERROR_WIN_CLUSTER_LOCAL_NODE_NOT_FOUND,
+ MD_ERROR_WIN_CLUSTER_NETWORK_EXISTS,
+ MD_ERROR_WIN_CLUSTER_NETWORK_NOT_FOUND,
+ MD_ERROR_WIN_CLUSTER_NETINTERFACE_EXISTS,
+ MD_ERROR_WIN_CLUSTER_NETINTERFACE_NOT_FOUND,
+ MD_ERROR_WIN_CLUSTER_INVALID_REQUEST,
+ MD_ERROR_WIN_CLUSTER_INVALID_NETWORK_PROVIDER,
+ MD_ERROR_WIN_CLUSTER_NODE_DOWN,
+ MD_ERROR_WIN_CLUSTER_NODE_UNREACHABLE,
+ MD_ERROR_WIN_CLUSTER_NODE_NOT_MEMBER,
+ MD_ERROR_WIN_CLUSTER_JOIN_NOT_IN_PROGRESS,
+ MD_ERROR_WIN_CLUSTER_INVALID_NETWORK,
+ MD_ERROR_WIN_CLUSTER_NODE_UP,
+ MD_ERROR_WIN_CLUSTER_IPADDR_IN_USE,
+ MD_ERROR_WIN_CLUSTER_NODE_NOT_PAUSED,
+ MD_ERROR_WIN_CLUSTER_NO_SECURITY_CONTEXT,
+ MD_ERROR_WIN_CLUSTER_NETWORK_NOT_INTERNAL,
+ MD_ERROR_WIN_CLUSTER_NODE_ALREADY_UP,
+ MD_ERROR_WIN_CLUSTER_NODE_ALREADY_DOWN,
+ MD_ERROR_WIN_CLUSTER_NETWORK_ALREADY_ONLINE,
+ MD_ERROR_WIN_CLUSTER_NETWORK_ALREADY_OFFLINE,
+ MD_ERROR_WIN_CLUSTER_NODE_ALREADY_MEMBER,
+ MD_ERROR_WIN_CLUSTER_LAST_INTERNAL_NETWORK,
+ MD_ERROR_WIN_CLUSTER_NETWORK_HAS_DEPENDENTS,
+ MD_ERROR_WIN_INVALID_OPERATION_ON_QUORUM,
+ MD_ERROR_WIN_DEPENDENCY_NOT_ALLOWED,
+ MD_ERROR_WIN_CLUSTER_NODE_PAUSED,
+ MD_ERROR_WIN_NODE_CANT_HOST_RESOURCE,
+ MD_ERROR_WIN_CLUSTER_NODE_NOT_READY,
+ MD_ERROR_WIN_CLUSTER_NODE_SHUTTING_DOWN,
+ MD_ERROR_WIN_CLUSTER_JOIN_ABORTED,
+ MD_ERROR_WIN_CLUSTER_INCOMPATIBLE_VERSIONS,
+ MD_ERROR_WIN_CLUSTER_MAXNUM_OF_RESOURCES_EXCEEDED,
+ MD_ERROR_WIN_CLUSTER_SYSTEM_CONFIG_CHANGED,
+ MD_ERROR_WIN_CLUSTER_RESOURCE_TYPE_NOT_FOUND,
+ MD_ERROR_WIN_CLUSTER_RESTYPE_NOT_SUPPORTED,
+ MD_ERROR_WIN_CLUSTER_RESNAME_NOT_FOUND,
+ MD_ERROR_WIN_CLUSTER_NO_RPC_PACKAGES_REGISTERED,
+ MD_ERROR_WIN_CLUSTER_OWNER_NOT_IN_PREFLIST,
+ MD_ERROR_WIN_CLUSTER_DATABASE_SEQMISMATCH,
+ MD_ERROR_WIN_RESMON_INVALID_STATE,
+ MD_ERROR_WIN_CLUSTER_GUM_NOT_LOCKER,
+ MD_ERROR_WIN_QUORUM_DISK_NOT_FOUND,
+ MD_ERROR_WIN_DATABASE_BACKUP_CORRUPT,
+ MD_ERROR_WIN_CLUSTER_NODE_ALREADY_HAS_DFS_ROOT,
+ MD_ERROR_WIN_RESOURCE_PROPERTY_UNCHANGEABLE,
+ MD_ERROR_WIN_NO_ADMIN_ACCESS_POINT,
+ MD_ERROR_WIN_CLUSTER_MEMBERSHIP_INVALID_STATE,
+ MD_ERROR_WIN_CLUSTER_QUORUMLOG_NOT_FOUND,
+ MD_ERROR_WIN_CLUSTER_MEMBERSHIP_HALT,
+ MD_ERROR_WIN_CLUSTER_INSTANCE_ID_MISMATCH,
+ MD_ERROR_WIN_CLUSTER_NETWORK_NOT_FOUND_FOR_IP,
+ MD_ERROR_WIN_CLUSTER_PROPERTY_DATA_TYPE_MISMATCH,
+ MD_ERROR_WIN_CLUSTER_EVICT_WITHOUT_CLEANUP,
+ MD_ERROR_WIN_CLUSTER_PARAMETER_MISMATCH,
+ MD_ERROR_WIN_NODE_CANNOT_BE_CLUSTERED,
+ MD_ERROR_WIN_CLUSTER_WRONG_OS_VERSION,
+ MD_ERROR_WIN_CLUSTER_CANT_CREATE_DUP_CLUSTER_NAME,
+ MD_ERROR_WIN_CLUSCFG_ALREADY_COMMITTED,
+ MD_ERROR_WIN_CLUSCFG_ROLLBACK_FAILED,
+ MD_ERROR_WIN_CLUSCFG_SYSTEM_DISK_DRIVE_LETTER_CONFLICT,
+ MD_ERROR_WIN_CLUSTER_OLD_VERSION,
+ MD_ERROR_WIN_CLUSTER_MISMATCHED_COMPUTER_ACCT_NAME,
+ MD_ERROR_WIN_CLUSTER_NO_NET_ADAPTERS,
+ MD_ERROR_WIN_CLUSTER_POISONED,
+ MD_ERROR_WIN_CLUSTER_GROUP_MOVING,
+ MD_ERROR_WIN_CLUSTER_RESOURCE_TYPE_BUSY,
+ MD_ERROR_WIN_RESOURCE_CALL_TIMED_OUT,
+ MD_ERROR_WIN_INVALID_CLUSTER_IPV6_ADDRESS,
+ MD_ERROR_WIN_CLUSTER_INTERNAL_INVALID_FUNCTION,
+ MD_ERROR_WIN_CLUSTER_PARAMETER_OUT_OF_BOUNDS,
+ MD_ERROR_WIN_CLUSTER_PARTIAL_SEND,
+ MD_ERROR_WIN_CLUSTER_REGISTRY_INVALID_FUNCTION,
+ MD_ERROR_WIN_CLUSTER_INVALID_STRING_TERMINATION,
+ MD_ERROR_WIN_CLUSTER_INVALID_STRING_FORMAT,
+ MD_ERROR_WIN_CLUSTER_DATABASE_TRANSACTION_IN_PROGRESS,
+ MD_ERROR_WIN_CLUSTER_DATABASE_TRANSACTION_NOT_IN_PROGRESS,
+ MD_ERROR_WIN_CLUSTER_NULL_DATA,
+ MD_ERROR_WIN_CLUSTER_PARTIAL_READ,
+ MD_ERROR_WIN_CLUSTER_PARTIAL_WRITE,
+ MD_ERROR_WIN_CLUSTER_CANT_DESERIALIZE_DATA,
+ MD_ERROR_WIN_DEPENDENT_RESOURCE_PROPERTY_CONFLICT,
+ MD_ERROR_WIN_CLUSTER_NO_QUORUM,
+ MD_ERROR_WIN_CLUSTER_INVALID_IPV6_NETWORK,
+ MD_ERROR_WIN_CLUSTER_INVALID_IPV6_TUNNEL_NETWORK,
+ MD_ERROR_WIN_QUORUM_NOT_ALLOWED_IN_THIS_GROUP,
+ MD_ERROR_WIN_DEPENDENCY_TREE_TOO_COMPLEX,
+ MD_ERROR_WIN_EXCEPTION_IN_RESOURCE_CALL,
+ MD_ERROR_WIN_CLUSTER_RHS_FAILED_INITIALIZATION,
+ MD_ERROR_WIN_CLUSTER_NOT_INSTALLED,
+ MD_ERROR_WIN_CLUSTER_RESOURCES_MUST_BE_ONLINE_ON_THE_SAME_NODE,
+ MD_ERROR_WIN_CLUSTER_MAX_NODES_IN_CLUSTER,
+ MD_ERROR_WIN_CLUSTER_TOO_MANY_NODES,
+ MD_ERROR_WIN_CLUSTER_OBJECT_ALREADY_USED,
+ MD_ERROR_WIN_NONCORE_GROUPS_FOUND,
+ MD_ERROR_WIN_FILE_SHARE_RESOURCE_CONFLICT,
+ MD_ERROR_WIN_CLUSTER_EVICT_INVALID_REQUEST,
+ MD_ERROR_WIN_CLUSTER_SINGLETON_RESOURCE,
+ MD_ERROR_WIN_CLUSTER_GROUP_SINGLETON_RESOURCE,
+ MD_ERROR_WIN_CLUSTER_RESOURCE_PROVIDER_FAILED,
+ MD_ERROR_WIN_CLUSTER_RESOURCE_CONFIGURATION_ERROR,
+ MD_ERROR_WIN_CLUSTER_GROUP_BUSY,
+ MD_ERROR_WIN_CLUSTER_NOT_SHARED_VOLUME,
+ MD_ERROR_WIN_CLUSTER_INVALID_SECURITY_DESCRIPTOR,
+ MD_ERROR_WIN_CLUSTER_SHARED_VOLUMES_IN_USE,
+ MD_ERROR_WIN_CLUSTER_USE_SHARED_VOLUMES_API,
+ MD_ERROR_WIN_CLUSTER_BACKUP_IN_PROGRESS,
+ MD_ERROR_WIN_NON_CSV_PATH,
+ MD_ERROR_WIN_CSV_VOLUME_NOT_LOCAL,
+ MD_ERROR_WIN_CLUSTER_WATCHDOG_TERMINATING,
+ MD_ERROR_WIN_CLUSTER_RESOURCE_VETOED_MOVE_INCOMPATIBLE_NODES,
+ MD_ERROR_WIN_CLUSTER_INVALID_NODE_WEIGHT,
+ MD_ERROR_WIN_CLUSTER_RESOURCE_VETOED_CALL,
+ MD_ERROR_WIN_RESMON_SYSTEM_RESOURCES_LACKING,
+ MD_ERROR_WIN_CLUSTER_RESOURCE_VETOED_MOVE_NOT_ENOUGH_RESOURCES_ON_DESTINATION,
+ MD_ERROR_WIN_CLUSTER_RESOURCE_VETOED_MOVE_NOT_ENOUGH_RESOURCES_ON_SOURCE,
+ MD_ERROR_WIN_CLUSTER_GROUP_QUEUED,
+ MD_ERROR_WIN_CLUSTER_RESOURCE_LOCKED_STATUS,
+ MD_ERROR_WIN_CLUSTER_SHARED_VOLUME_FAILOVER_NOT_ALLOWED,
+ MD_ERROR_WIN_CLUSTER_NODE_DRAIN_IN_PROGRESS,
+ MD_ERROR_WIN_CLUSTER_DISK_NOT_CONNECTED,
+ MD_ERROR_WIN_DISK_NOT_CSV_CAPABLE,
+ MD_ERROR_WIN_RESOURCE_NOT_IN_AVAILABLE_STORAGE,
+ MD_ERROR_WIN_CLUSTER_SHARED_VOLUME_REDIRECTED,
+ MD_ERROR_WIN_CLUSTER_SHARED_VOLUME_NOT_REDIRECTED,
+ MD_ERROR_WIN_CLUSTER_CANNOT_RETURN_PROPERTIES,
+ MD_ERROR_WIN_CLUSTER_RESOURCE_CONTAINS_UNSUPPORTED_DIFF_AREA_FOR_SHARED_VOLUMES,
+ MD_ERROR_WIN_CLUSTER_RESOURCE_IS_IN_MAINTENANCE_MODE,
+ MD_ERROR_WIN_CLUSTER_AFFINITY_CONFLICT,
+ MD_ERROR_WIN_CLUSTER_RESOURCE_IS_REPLICA_VIRTUAL_MACHINE,
+ MD_ERROR_WIN_CLUSTER_UPGRADE_INCOMPATIBLE_VERSIONS,
+ MD_ERROR_WIN_CLUSTER_UPGRADE_FIX_QUORUM_NOT_SUPPORTED,
+ MD_ERROR_WIN_CLUSTER_UPGRADE_RESTART_REQUIRED,
+ MD_ERROR_WIN_CLUSTER_UPGRADE_IN_PROGRESS,
+ MD_ERROR_WIN_CLUSTER_UPGRADE_INCOMPLETE,
+ MD_ERROR_WIN_CLUSTER_NODE_IN_GRACE_PERIOD,
+ MD_ERROR_WIN_CLUSTER_CSV_IO_PAUSE_TIMEOUT,
+ MD_ERROR_WIN_NODE_NOT_ACTIVE_CLUSTER_MEMBER,
+ MD_ERROR_WIN_CLUSTER_RESOURCE_NOT_MONITORED,
+ MD_ERROR_WIN_CLUSTER_RESOURCE_DOES_NOT_SUPPORT_UNMONITORED,
+ MD_ERROR_WIN_CLUSTER_RESOURCE_IS_REPLICATED,
+ MD_ERROR_WIN_CLUSTER_NODE_ISOLATED,
+ MD_ERROR_WIN_CLUSTER_NODE_QUARANTINED,
+ MD_ERROR_WIN_CLUSTER_DATABASE_UPDATE_CONDITION_FAILED,
+ MD_ERROR_WIN_CLUSTER_SPACE_DEGRADED,
+ MD_ERROR_WIN_CLUSTER_TOKEN_DELEGATION_NOT_SUPPORTED,
+ MD_ERROR_WIN_CLUSTER_CSV_INVALID_HANDLE,
+ MD_ERROR_WIN_CLUSTER_CSV_SUPPORTED_ONLY_ON_COORDINATOR,
+ MD_ERROR_WIN_GROUPSET_NOT_AVAILABLE,
+ MD_ERROR_WIN_GROUPSET_NOT_FOUND,
+ MD_ERROR_WIN_GROUPSET_CANT_PROVIDE,
+ MD_ERROR_WIN_CLUSTER_FAULT_DOMAIN_PARENT_NOT_FOUND,
+ MD_ERROR_WIN_CLUSTER_FAULT_DOMAIN_INVALID_HIERARCHY,
+ MD_ERROR_WIN_CLUSTER_FAULT_DOMAIN_FAILED_S2D_VALIDATION,
+ MD_ERROR_WIN_CLUSTER_FAULT_DOMAIN_S2D_CONNECTIVITY_LOSS,
+ MD_ERROR_WIN_CLUSTER_INVALID_INFRASTRUCTURE_FILESERVER_NAME,
+ MD_ERROR_WIN_CLUSTERSET_MANAGEMENT_CLUSTER_UNREACHABLE,
+ MD_ERROR_WIN_ENCRYPTION_FAILED,
+ MD_ERROR_WIN_DECRYPTION_FAILED,
+ MD_ERROR_WIN_FILE_ENCRYPTED,
+ MD_ERROR_WIN_NO_RECOVERY_POLICY,
+ MD_ERROR_WIN_NO_EFS,
+ MD_ERROR_WIN_WRONG_EFS,
+ MD_ERROR_WIN_NO_USER_KEYS,
+ MD_ERROR_WIN_FILE_NOT_ENCRYPTED,
+ MD_ERROR_WIN_NOT_EXPORT_FORMAT,
+ MD_ERROR_WIN_FILE_READ_ONLY,
+ MD_ERROR_WIN_DIR_EFS_DISALLOWED,
+ MD_ERROR_WIN_EFS_SERVER_NOT_TRUSTED,
+ MD_ERROR_WIN_BAD_RECOVERY_POLICY,
+ MD_ERROR_WIN_EFS_ALG_BLOB_TOO_BIG,
+ MD_ERROR_WIN_VOLUME_NOT_SUPPORT_EFS,
+ MD_ERROR_WIN_EFS_DISABLED,
+ MD_ERROR_WIN_EFS_VERSION_NOT_SUPPORT,
+ MD_ERROR_WIN_CS_ENCRYPTION_INVALID_SERVER_RESPONSE,
+ MD_ERROR_WIN_CS_ENCRYPTION_UNSUPPORTED_SERVER,
+ MD_ERROR_WIN_CS_ENCRYPTION_EXISTING_ENCRYPTED_FILE,
+ MD_ERROR_WIN_CS_ENCRYPTION_NEW_ENCRYPTED_FILE,
+ MD_ERROR_WIN_CS_ENCRYPTION_FILE_NOT_CSE,
+ MD_ERROR_WIN_ENCRYPTION_POLICY_DENIES_OPERATION,
+ MD_ERROR_WIN_WIP_ENCRYPTION_FAILED,
+ MD_ERROR_WIN_NO_BROWSER_SERVERS_FOUND,
+ MD_ERROR_WIN_CLUSTER_OBJECT_IS_CLUSTER_SET_VM,
+ MD_ERROR_WIN_LOG_SECTOR_INVALID,
+ MD_ERROR_WIN_LOG_SECTOR_PARITY_INVALID,
+ MD_ERROR_WIN_LOG_SECTOR_REMAPPED,
+ MD_ERROR_WIN_LOG_BLOCK_INCOMPLETE,
+ MD_ERROR_WIN_LOG_INVALID_RANGE,
+ MD_ERROR_WIN_LOG_BLOCKS_EXHAUSTED,
+ MD_ERROR_WIN_LOG_READ_CONTEXT_INVALID,
+ MD_ERROR_WIN_LOG_RESTART_INVALID,
+ MD_ERROR_WIN_LOG_BLOCK_VERSION,
+ MD_ERROR_WIN_LOG_BLOCK_INVALID,
+ MD_ERROR_WIN_LOG_READ_MODE_INVALID,
+ MD_ERROR_WIN_LOG_NO_RESTART,
+ MD_ERROR_WIN_LOG_METADATA_CORRUPT,
+ MD_ERROR_WIN_LOG_METADATA_INVALID,
+ MD_ERROR_WIN_LOG_METADATA_INCONSISTENT,
+ MD_ERROR_WIN_LOG_RESERVATION_INVALID,
+ MD_ERROR_WIN_LOG_CANT_DELETE,
+ MD_ERROR_WIN_LOG_CONTAINER_LIMIT_EXCEEDED,
+ MD_ERROR_WIN_LOG_START_OF_LOG,
+ MD_ERROR_WIN_LOG_POLICY_ALREADY_INSTALLED,
+ MD_ERROR_WIN_LOG_POLICY_NOT_INSTALLED,
+ MD_ERROR_WIN_LOG_POLICY_INVALID,
+ MD_ERROR_WIN_LOG_POLICY_CONFLICT,
+ MD_ERROR_WIN_LOG_PINNED_ARCHIVE_TAIL,
+ MD_ERROR_WIN_LOG_RECORD_NONEXISTENT,
+ MD_ERROR_WIN_LOG_RECORDS_RESERVED_INVALID,
+ MD_ERROR_WIN_LOG_SPACE_RESERVED_INVALID,
+ MD_ERROR_WIN_LOG_TAIL_INVALID,
+ MD_ERROR_WIN_LOG_FULL,
+ MD_ERROR_WIN_COULD_NOT_RESIZE_LOG,
+ MD_ERROR_WIN_LOG_MULTIPLEXED,
+ MD_ERROR_WIN_LOG_DEDICATED,
+ MD_ERROR_WIN_LOG_ARCHIVE_NOT_IN_PROGRESS,
+ MD_ERROR_WIN_LOG_ARCHIVE_IN_PROGRESS,
+ MD_ERROR_WIN_LOG_EPHEMERAL,
+ MD_ERROR_WIN_LOG_NOT_ENOUGH_CONTAINERS,
+ MD_ERROR_WIN_LOG_CLIENT_ALREADY_REGISTERED,
+ MD_ERROR_WIN_LOG_CLIENT_NOT_REGISTERED,
+ MD_ERROR_WIN_LOG_FULL_HANDLER_IN_PROGRESS,
+ MD_ERROR_WIN_LOG_CONTAINER_READ_FAILED,
+ MD_ERROR_WIN_LOG_CONTAINER_WRITE_FAILED,
+ MD_ERROR_WIN_LOG_CONTAINER_OPEN_FAILED,
+ MD_ERROR_WIN_LOG_CONTAINER_STATE_INVALID,
+ MD_ERROR_WIN_LOG_STATE_INVALID,
+ MD_ERROR_WIN_LOG_PINNED,
+ MD_ERROR_WIN_LOG_METADATA_FLUSH_FAILED,
+ MD_ERROR_WIN_LOG_INCONSISTENT_SECURITY,
+ MD_ERROR_WIN_LOG_APPENDED_FLUSH_FAILED,
+ MD_ERROR_WIN_LOG_PINNED_RESERVATION,
+ MD_ERROR_WIN_INVALID_TRANSACTION,
+ MD_ERROR_WIN_TRANSACTION_NOT_ACTIVE,
+ MD_ERROR_WIN_TRANSACTION_REQUEST_NOT_VALID,
+ MD_ERROR_WIN_TRANSACTION_NOT_REQUESTED,
+ MD_ERROR_WIN_TRANSACTION_ALREADY_ABORTED,
+ MD_ERROR_WIN_TRANSACTION_ALREADY_COMMITTED,
+ MD_ERROR_WIN_TM_INITIALIZATION_FAILED,
+ MD_ERROR_WIN_RESOURCEMANAGER_READ_ONLY,
+ MD_ERROR_WIN_TRANSACTION_NOT_JOINED,
+ MD_ERROR_WIN_TRANSACTION_SUPERIOR_EXISTS,
+ MD_ERROR_WIN_CRM_PROTOCOL_ALREADY_EXISTS,
+ MD_ERROR_WIN_TRANSACTION_PROPAGATION_FAILED,
+ MD_ERROR_WIN_CRM_PROTOCOL_NOT_FOUND,
+ MD_ERROR_WIN_TRANSACTION_INVALID_MARSHALL_BUFFER,
+ MD_ERROR_WIN_CURRENT_TRANSACTION_NOT_VALID,
+ MD_ERROR_WIN_TRANSACTION_NOT_FOUND,
+ MD_ERROR_WIN_RESOURCEMANAGER_NOT_FOUND,
+ MD_ERROR_WIN_ENLISTMENT_NOT_FOUND,
+ MD_ERROR_WIN_TRANSACTIONMANAGER_NOT_FOUND,
+ MD_ERROR_WIN_TRANSACTIONMANAGER_NOT_ONLINE,
+ MD_ERROR_WIN_TRANSACTIONMANAGER_RECOVERY_NAME_COLLISION,
+ MD_ERROR_WIN_TRANSACTION_NOT_ROOT,
+ MD_ERROR_WIN_TRANSACTION_OBJECT_EXPIRED,
+ MD_ERROR_WIN_TRANSACTION_RESPONSE_NOT_ENLISTED,
+ MD_ERROR_WIN_TRANSACTION_RECORD_TOO_LONG,
+ MD_ERROR_WIN_IMPLICIT_TRANSACTION_NOT_SUPPORTED,
+ MD_ERROR_WIN_TRANSACTION_INTEGRITY_VIOLATED,
+ MD_ERROR_WIN_TRANSACTIONMANAGER_IDENTITY_MISMATCH,
+ MD_ERROR_WIN_RM_CANNOT_BE_FROZEN_FOR_SNAPSHOT,
+ MD_ERROR_WIN_TRANSACTION_MUST_WRITETHROUGH,
+ MD_ERROR_WIN_TRANSACTION_NO_SUPERIOR,
+ MD_ERROR_WIN_HEURISTIC_DAMAGE_POSSIBLE,
+ MD_ERROR_WIN_TRANSACTIONAL_CONFLICT,
+ MD_ERROR_WIN_RM_NOT_ACTIVE,
+ MD_ERROR_WIN_RM_METADATA_CORRUPT,
+ MD_ERROR_WIN_DIRECTORY_NOT_RM,
+ MD_ERROR_WIN_TRANSACTIONS_UNSUPPORTED_REMOTE,
+ MD_ERROR_WIN_LOG_RESIZE_INVALID_SIZE,
+ MD_ERROR_WIN_OBJECT_NO_LONGER_EXISTS,
+ MD_ERROR_WIN_STREAM_MINIVERSION_NOT_FOUND,
+ MD_ERROR_WIN_STREAM_MINIVERSION_NOT_VALID,
+ MD_ERROR_WIN_MINIVERSION_INACCESSIBLE_FROM_SPECIFIED_TRANSACTION,
+ MD_ERROR_WIN_CANT_OPEN_MINIVERSION_WITH_MODIFY_INTENT,
+ MD_ERROR_WIN_CANT_CREATE_MORE_STREAM_MINIVERSIONS,
+ MD_ERROR_WIN_REMOTE_FILE_VERSION_MISMATCH,
+ MD_ERROR_WIN_HANDLE_NO_LONGER_VALID,
+ MD_ERROR_WIN_NO_TXF_METADATA,
+ MD_ERROR_WIN_LOG_CORRUPTION_DETECTED,
+ MD_ERROR_WIN_CANT_RECOVER_WITH_HANDLE_OPEN,
+ MD_ERROR_WIN_RM_DISCONNECTED,
+ MD_ERROR_WIN_ENLISTMENT_NOT_SUPERIOR,
+ MD_ERROR_WIN_RECOVERY_NOT_NEEDED,
+ MD_ERROR_WIN_RM_ALREADY_STARTED,
+ MD_ERROR_WIN_FILE_IDENTITY_NOT_PERSISTENT,
+ MD_ERROR_WIN_CANT_BREAK_TRANSACTIONAL_DEPENDENCY,
+ MD_ERROR_WIN_CANT_CROSS_RM_BOUNDARY,
+ MD_ERROR_WIN_TXF_DIR_NOT_EMPTY,
+ MD_ERROR_WIN_INDOUBT_TRANSACTIONS_EXIST,
+ MD_ERROR_WIN_TM_VOLATILE,
+ MD_ERROR_WIN_ROLLBACK_TIMER_EXPIRED,
+ MD_ERROR_WIN_TXF_ATTRIBUTE_CORRUPT,
+ MD_ERROR_WIN_EFS_NOT_ALLOWED_IN_TRANSACTION,
+ MD_ERROR_WIN_TRANSACTIONAL_OPEN_NOT_ALLOWED,
+ MD_ERROR_WIN_LOG_GROWTH_FAILED,
+ MD_ERROR_WIN_TRANSACTED_MAPPING_UNSUPPORTED_REMOTE,
+ MD_ERROR_WIN_TXF_METADATA_ALREADY_PRESENT,
+ MD_ERROR_WIN_TRANSACTION_SCOPE_CALLBACKS_NOT_SET,
+ MD_ERROR_WIN_TRANSACTION_REQUIRED_PROMOTION,
+ MD_ERROR_WIN_CANNOT_EXECUTE_FILE_IN_TRANSACTION,
+ MD_ERROR_WIN_TRANSACTIONS_NOT_FROZEN,
+ MD_ERROR_WIN_TRANSACTION_FREEZE_IN_PROGRESS,
+ MD_ERROR_WIN_NOT_SNAPSHOT_VOLUME,
+ MD_ERROR_WIN_NO_SAVEPOINT_WITH_OPEN_FILES,
+ MD_ERROR_WIN_DATA_LOST_REPAIR,
+ MD_ERROR_WIN_SPARSE_NOT_ALLOWED_IN_TRANSACTION,
+ MD_ERROR_WIN_TM_IDENTITY_MISMATCH,
+ MD_ERROR_WIN_FLOATED_SECTION,
+ MD_ERROR_WIN_CANNOT_ACCEPT_TRANSACTED_WORK,
+ MD_ERROR_WIN_CANNOT_ABORT_TRANSACTIONS,
+ MD_ERROR_WIN_BAD_CLUSTERS,
+ MD_ERROR_WIN_COMPRESSION_NOT_ALLOWED_IN_TRANSACTION,
+ MD_ERROR_WIN_VOLUME_DIRTY,
+ MD_ERROR_WIN_NO_LINK_TRACKING_IN_TRANSACTION,
+ MD_ERROR_WIN_OPERATION_NOT_SUPPORTED_IN_TRANSACTION,
+ MD_ERROR_WIN_EXPIRED_HANDLE,
+ MD_ERROR_WIN_TRANSACTION_NOT_ENLISTED,
+ MD_ERROR_WIN_CTX_WINSTATION_NAME_INVALID,
+ MD_ERROR_WIN_CTX_INVALID_PD,
+ MD_ERROR_WIN_CTX_PD_NOT_FOUND,
+ MD_ERROR_WIN_CTX_WD_NOT_FOUND,
+ MD_ERROR_WIN_CTX_CANNOT_MAKE_EVENTLOG_ENTRY,
+ MD_ERROR_WIN_CTX_SERVICE_NAME_COLLISION,
+ MD_ERROR_WIN_CTX_CLOSE_PENDING,
+ MD_ERROR_WIN_CTX_NO_OUTBUF,
+ MD_ERROR_WIN_CTX_MODEM_INF_NOT_FOUND,
+ MD_ERROR_WIN_CTX_INVALID_MODEMNAME,
+ MD_ERROR_WIN_CTX_MODEM_RESPONSE_ERROR,
+ MD_ERROR_WIN_CTX_MODEM_RESPONSE_TIMEOUT,
+ MD_ERROR_WIN_CTX_MODEM_RESPONSE_NO_CARRIER,
+ MD_ERROR_WIN_CTX_MODEM_RESPONSE_NO_DIALTONE,
+ MD_ERROR_WIN_CTX_MODEM_RESPONSE_BUSY,
+ MD_ERROR_WIN_CTX_MODEM_RESPONSE_VOICE,
+ MD_ERROR_WIN_CTX_TD_ERROR,
+ MD_ERROR_WIN_CTX_WINSTATION_NOT_FOUND,
+ MD_ERROR_WIN_CTX_WINSTATION_ALREADY_EXISTS,
+ MD_ERROR_WIN_CTX_WINSTATION_BUSY,
+ MD_ERROR_WIN_CTX_BAD_VIDEO_MODE,
+ MD_ERROR_WIN_CTX_GRAPHICS_INVALID,
+ MD_ERROR_WIN_CTX_LOGON_DISABLED,
+ MD_ERROR_WIN_CTX_NOT_CONSOLE,
+ MD_ERROR_WIN_CTX_CLIENT_QUERY_TIMEOUT,
+ MD_ERROR_WIN_CTX_CONSOLE_DISCONNECT,
+ MD_ERROR_WIN_CTX_CONSOLE_CONNECT,
+ MD_ERROR_WIN_CTX_SHADOW_DENIED,
+ MD_ERROR_WIN_CTX_WINSTATION_ACCESS_DENIED,
+ MD_ERROR_WIN_CTX_INVALID_WD,
+ MD_ERROR_WIN_CTX_SHADOW_INVALID,
+ MD_ERROR_WIN_CTX_SHADOW_DISABLED,
+ MD_ERROR_WIN_CTX_CLIENT_LICENSE_IN_USE,
+ MD_ERROR_WIN_CTX_CLIENT_LICENSE_NOT_SET,
+ MD_ERROR_WIN_CTX_LICENSE_NOT_AVAILABLE,
+ MD_ERROR_WIN_CTX_LICENSE_CLIENT_INVALID,
+ MD_ERROR_WIN_CTX_LICENSE_EXPIRED,
+ MD_ERROR_WIN_CTX_SHADOW_NOT_RUNNING,
+ MD_ERROR_WIN_CTX_SHADOW_ENDED_BY_MODE_CHANGE,
+ MD_ERROR_WIN_ACTIVATION_COUNT_EXCEEDED,
+ MD_ERROR_WIN_CTX_WINSTATIONS_DISABLED,
+ MD_ERROR_WIN_CTX_ENCRYPTION_LEVEL_REQUIRED,
+ MD_ERROR_WIN_CTX_SESSION_IN_USE,
+ MD_ERROR_WIN_CTX_NO_FORCE_LOGOFF,
+ MD_ERROR_WIN_CTX_ACCOUNT_RESTRICTION,
+ MD_ERROR_WIN_RDP_PROTOCOL_ERROR,
+ MD_ERROR_WIN_CTX_CDM_CONNECT,
+ MD_ERROR_WIN_CTX_CDM_DISCONNECT,
+ MD_ERROR_WIN_CTX_SECURITY_LAYER_ERROR,
+ MD_ERROR_WIN_TS_INCOMPATIBLE_SESSIONS,
+ MD_ERROR_WIN_TS_VIDEO_SUBSYSTEM_ERROR,
+ MD_ERROR_WIN_DS_NOT_INSTALLED,
+ MD_ERROR_WIN_DS_MEMBERSHIP_EVALUATED_LOCALLY,
+ MD_ERROR_WIN_DS_NO_ATTRIBUTE_OR_VALUE,
+ MD_ERROR_WIN_DS_INVALID_ATTRIBUTE_SYNTAX,
+ MD_ERROR_WIN_DS_ATTRIBUTE_TYPE_UNDEFINED,
+ MD_ERROR_WIN_DS_ATTRIBUTE_OR_VALUE_EXISTS,
+ MD_ERROR_WIN_DS_BUSY,
+ MD_ERROR_WIN_DS_UNAVAILABLE,
+ MD_ERROR_WIN_DS_NO_RIDS_ALLOCATED,
+ MD_ERROR_WIN_DS_NO_MORE_RIDS,
+ MD_ERROR_WIN_DS_INCORRECT_ROLE_OWNER,
+ MD_ERROR_WIN_DS_RIDMGR_INIT_ERROR,
+ MD_ERROR_WIN_DS_OBJ_CLASS_VIOLATION,
+ MD_ERROR_WIN_DS_CANT_ON_NON_LEAF,
+ MD_ERROR_WIN_DS_CANT_ON_RDN,
+ MD_ERROR_WIN_DS_CANT_MOD_OBJ_CLASS,
+ MD_ERROR_WIN_DS_CROSS_DOM_MOVE_ERROR,
+ MD_ERROR_WIN_DS_GC_NOT_AVAILABLE,
+ MD_ERROR_WIN_SHARED_POLICY,
+ MD_ERROR_WIN_POLICY_OBJECT_NOT_FOUND,
+ MD_ERROR_WIN_POLICY_ONLY_IN_DS,
+ MD_ERROR_WIN_PROMOTION_ACTIVE,
+ MD_ERROR_WIN_NO_PROMOTION_ACTIVE,
+ MD_ERROR_WIN_DS_OPERATIONS_ERROR,
+ MD_ERROR_WIN_DS_PROTOCOL_ERROR,
+ MD_ERROR_WIN_DS_TIMELIMIT_EXCEEDED,
+ MD_ERROR_WIN_DS_SIZELIMIT_EXCEEDED,
+ MD_ERROR_WIN_DS_ADMIN_LIMIT_EXCEEDED,
+ MD_ERROR_WIN_DS_COMPARE_FALSE,
+ MD_ERROR_WIN_DS_COMPARE_TRUE,
+ MD_ERROR_WIN_DS_AUTH_METHOD_NOT_SUPPORTED,
+ MD_ERROR_WIN_DS_STRONG_AUTH_REQUIRED,
+ MD_ERROR_WIN_DS_INAPPROPRIATE_AUTH,
+ MD_ERROR_WIN_DS_AUTH_UNKNOWN,
+ MD_ERROR_WIN_DS_REFERRAL,
+ MD_ERROR_WIN_DS_UNAVAILABLE_CRIT_EXTENSION,
+ MD_ERROR_WIN_DS_CONFIDENTIALITY_REQUIRED,
+ MD_ERROR_WIN_DS_INAPPROPRIATE_MATCHING,
+ MD_ERROR_WIN_DS_CONSTRAINT_VIOLATION,
+ MD_ERROR_WIN_DS_NO_SUCH_OBJECT,
+ MD_ERROR_WIN_DS_ALIAS_PROBLEM,
+ MD_ERROR_WIN_DS_INVALID_DN_SYNTAX,
+ MD_ERROR_WIN_DS_IS_LEAF,
+ MD_ERROR_WIN_DS_ALIAS_DEREF_PROBLEM,
+ MD_ERROR_WIN_DS_UNWILLING_TO_PERFORM,
+ MD_ERROR_WIN_DS_LOOP_DETECT,
+ MD_ERROR_WIN_DS_NAMING_VIOLATION,
+ MD_ERROR_WIN_DS_OBJECT_RESULTS_TOO_LARGE,
+ MD_ERROR_WIN_DS_AFFECTS_MULTIPLE_DSAS,
+ MD_ERROR_WIN_DS_SERVER_DOWN,
+ MD_ERROR_WIN_DS_LOCAL_ERROR,
+ MD_ERROR_WIN_DS_ENCODING_ERROR,
+ MD_ERROR_WIN_DS_DECODING_ERROR,
+ MD_ERROR_WIN_DS_FILTER_UNKNOWN,
+ MD_ERROR_WIN_DS_PARAM_ERROR,
+ MD_ERROR_WIN_DS_NOT_SUPPORTED,
+ MD_ERROR_WIN_DS_NO_RESULTS_RETURNED,
+ MD_ERROR_WIN_DS_CONTROL_NOT_FOUND,
+ MD_ERROR_WIN_DS_CLIENT_LOOP,
+ MD_ERROR_WIN_DS_REFERRAL_LIMIT_EXCEEDED,
+ MD_ERROR_WIN_DS_SORT_CONTROL_MISSING,
+ MD_ERROR_WIN_DS_OFFSET_RANGE_ERROR,
+ MD_ERROR_WIN_DS_RIDMGR_DISABLED,
+ MD_ERROR_WIN_DS_ROOT_MUST_BE_NC,
+ MD_ERROR_WIN_DS_ADD_REPLICA_INHIBITED,
+ MD_ERROR_WIN_DS_ATT_NOT_DEF_IN_SCHEMA,
+ MD_ERROR_WIN_DS_MAX_OBJ_SIZE_EXCEEDED,
+ MD_ERROR_WIN_DS_OBJ_STRING_NAME_EXISTS,
+ MD_ERROR_WIN_DS_NO_RDN_DEFINED_IN_SCHEMA,
+ MD_ERROR_WIN_DS_RDN_DOESNT_MATCH_SCHEMA,
+ MD_ERROR_WIN_DS_NO_REQUESTED_ATTS_FOUND,
+ MD_ERROR_WIN_DS_USER_BUFFER_TO_SMALL,
+ MD_ERROR_WIN_DS_ATT_IS_NOT_ON_OBJ,
+ MD_ERROR_WIN_DS_ILLEGAL_MOD_OPERATION,
+ MD_ERROR_WIN_DS_OBJ_TOO_LARGE,
+ MD_ERROR_WIN_DS_BAD_INSTANCE_TYPE,
+ MD_ERROR_WIN_DS_MASTERDSA_REQUIRED,
+ MD_ERROR_WIN_DS_OBJECT_CLASS_REQUIRED,
+ MD_ERROR_WIN_DS_MISSING_REQUIRED_ATT,
+ MD_ERROR_WIN_DS_ATT_NOT_DEF_FOR_CLASS,
+ MD_ERROR_WIN_DS_ATT_ALREADY_EXISTS,
+ MD_ERROR_WIN_DS_CANT_ADD_ATT_VALUES,
+ MD_ERROR_WIN_DS_SINGLE_VALUE_CONSTRAINT,
+ MD_ERROR_WIN_DS_RANGE_CONSTRAINT,
+ MD_ERROR_WIN_DS_ATT_VAL_ALREADY_EXISTS,
+ MD_ERROR_WIN_DS_CANT_REM_MISSING_ATT,
+ MD_ERROR_WIN_DS_CANT_REM_MISSING_ATT_VAL,
+ MD_ERROR_WIN_DS_ROOT_CANT_BE_SUBREF,
+ MD_ERROR_WIN_DS_NO_CHAINING,
+ MD_ERROR_WIN_DS_NO_CHAINED_EVAL,
+ MD_ERROR_WIN_DS_NO_PARENT_OBJECT,
+ MD_ERROR_WIN_DS_PARENT_IS_AN_ALIAS,
+ MD_ERROR_WIN_DS_CANT_MIX_MASTER_AND_REPS,
+ MD_ERROR_WIN_DS_CHILDREN_EXIST,
+ MD_ERROR_WIN_DS_OBJ_NOT_FOUND,
+ MD_ERROR_WIN_DS_ALIASED_OBJ_MISSING,
+ MD_ERROR_WIN_DS_BAD_NAME_SYNTAX,
+ MD_ERROR_WIN_DS_ALIAS_POINTS_TO_ALIAS,
+ MD_ERROR_WIN_DS_CANT_DEREF_ALIAS,
+ MD_ERROR_WIN_DS_OUT_OF_SCOPE,
+ MD_ERROR_WIN_DS_OBJECT_BEING_REMOVED,
+ MD_ERROR_WIN_DS_CANT_DELETE_DSA_OBJ,
+ MD_ERROR_WIN_DS_GENERIC_ERROR,
+ MD_ERROR_WIN_DS_DSA_MUST_BE_INT_MASTER,
+ MD_ERROR_WIN_DS_CLASS_NOT_DSA,
+ MD_ERROR_WIN_DS_INSUFF_ACCESS_RIGHTS,
+ MD_ERROR_WIN_DS_ILLEGAL_SUPERIOR,
+ MD_ERROR_WIN_DS_ATTRIBUTE_OWNED_BY_SAM,
+ MD_ERROR_WIN_DS_NAME_TOO_MANY_PARTS,
+ MD_ERROR_WIN_DS_NAME_TOO_LONG,
+ MD_ERROR_WIN_DS_NAME_VALUE_TOO_LONG,
+ MD_ERROR_WIN_DS_NAME_UNPARSEABLE,
+ MD_ERROR_WIN_DS_NAME_TYPE_UNKNOWN,
+ MD_ERROR_WIN_DS_NOT_AN_OBJECT,
+ MD_ERROR_WIN_DS_SEC_DESC_TOO_SHORT,
+ MD_ERROR_WIN_DS_SEC_DESC_INVALID,
+ MD_ERROR_WIN_DS_NO_DELETED_NAME,
+ MD_ERROR_WIN_DS_SUBREF_MUST_HAVE_PARENT,
+ MD_ERROR_WIN_DS_NCNAME_MUST_BE_NC,
+ MD_ERROR_WIN_DS_CANT_ADD_SYSTEM_ONLY,
+ MD_ERROR_WIN_DS_CLASS_MUST_BE_CONCRETE,
+ MD_ERROR_WIN_DS_INVALID_DMD,
+ MD_ERROR_WIN_DS_OBJ_GUID_EXISTS,
+ MD_ERROR_WIN_DS_NOT_ON_BACKLINK,
+ MD_ERROR_WIN_DS_NO_CROSSREF_FOR_NC,
+ MD_ERROR_WIN_DS_SHUTTING_DOWN,
+ MD_ERROR_WIN_DS_UNKNOWN_OPERATION,
+ MD_ERROR_WIN_DS_INVALID_ROLE_OWNER,
+ MD_ERROR_WIN_DS_COULDNT_CONTACT_FSMO,
+ MD_ERROR_WIN_DS_CROSS_NC_DN_RENAME,
+ MD_ERROR_WIN_DS_CANT_MOD_SYSTEM_ONLY,
+ MD_ERROR_WIN_DS_REPLICATOR_ONLY,
+ MD_ERROR_WIN_DS_OBJ_CLASS_NOT_DEFINED,
+ MD_ERROR_WIN_DS_OBJ_CLASS_NOT_SUBCLASS,
+ MD_ERROR_WIN_DS_NAME_REFERENCE_INVALID,
+ MD_ERROR_WIN_DS_CROSS_REF_EXISTS,
+ MD_ERROR_WIN_DS_CANT_DEL_MASTER_CROSSREF,
+ MD_ERROR_WIN_DS_SUBTREE_NOTIFY_NOT_NC_HEAD,
+ MD_ERROR_WIN_DS_NOTIFY_FILTER_TOO_COMPLEX,
+ MD_ERROR_WIN_DS_DUP_RDN,
+ MD_ERROR_WIN_DS_DUP_OID,
+ MD_ERROR_WIN_DS_DUP_MAPI_ID,
+ MD_ERROR_WIN_DS_DUP_SCHEMA_ID_GUID,
+ MD_ERROR_WIN_DS_DUP_LDAP_DISPLAY_NAME,
+ MD_ERROR_WIN_DS_SEMANTIC_ATT_TEST,
+ MD_ERROR_WIN_DS_SYNTAX_MISMATCH,
+ MD_ERROR_WIN_DS_EXISTS_IN_MUST_HAVE,
+ MD_ERROR_WIN_DS_EXISTS_IN_MAY_HAVE,
+ MD_ERROR_WIN_DS_NONEXISTENT_MAY_HAVE,
+ MD_ERROR_WIN_DS_NONEXISTENT_MUST_HAVE,
+ MD_ERROR_WIN_DS_AUX_CLS_TEST_FAIL,
+ MD_ERROR_WIN_DS_NONEXISTENT_POSS_SUP,
+ MD_ERROR_WIN_DS_SUB_CLS_TEST_FAIL,
+ MD_ERROR_WIN_DS_BAD_RDN_ATT_ID_SYNTAX,
+ MD_ERROR_WIN_DS_EXISTS_IN_AUX_CLS,
+ MD_ERROR_WIN_DS_EXISTS_IN_SUB_CLS,
+ MD_ERROR_WIN_DS_EXISTS_IN_POSS_SUP,
+ MD_ERROR_WIN_DS_RECALCSCHEMA_FAILED,
+ MD_ERROR_WIN_DS_TREE_DELETE_NOT_FINISHED,
+ MD_ERROR_WIN_DS_CANT_DELETE,
+ MD_ERROR_WIN_DS_ATT_SCHEMA_REQ_ID,
+ MD_ERROR_WIN_DS_BAD_ATT_SCHEMA_SYNTAX,
+ MD_ERROR_WIN_DS_CANT_CACHE_ATT,
+ MD_ERROR_WIN_DS_CANT_CACHE_CLASS,
+ MD_ERROR_WIN_DS_CANT_REMOVE_ATT_CACHE,
+ MD_ERROR_WIN_DS_CANT_REMOVE_CLASS_CACHE,
+ MD_ERROR_WIN_DS_CANT_RETRIEVE_DN,
+ MD_ERROR_WIN_DS_MISSING_SUPREF,
+ MD_ERROR_WIN_DS_CANT_RETRIEVE_INSTANCE,
+ MD_ERROR_WIN_DS_CODE_INCONSISTENCY,
+ MD_ERROR_WIN_DS_DATABASE_ERROR,
+ MD_ERROR_WIN_DS_GOVERNSID_MISSING,
+ MD_ERROR_WIN_DS_MISSING_EXPECTED_ATT,
+ MD_ERROR_WIN_DS_NCNAME_MISSING_CR_REF,
+ MD_ERROR_WIN_DS_SECURITY_CHECKING_ERROR,
+ MD_ERROR_WIN_DS_SCHEMA_NOT_LOADED,
+ MD_ERROR_WIN_DS_SCHEMA_ALLOC_FAILED,
+ MD_ERROR_WIN_DS_ATT_SCHEMA_REQ_SYNTAX,
+ MD_ERROR_WIN_DS_GCVERIFY_ERROR,
+ MD_ERROR_WIN_DS_DRA_SCHEMA_MISMATCH,
+ MD_ERROR_WIN_DS_CANT_FIND_DSA_OBJ,
+ MD_ERROR_WIN_DS_CANT_FIND_EXPECTED_NC,
+ MD_ERROR_WIN_DS_CANT_FIND_NC_IN_CACHE,
+ MD_ERROR_WIN_DS_CANT_RETRIEVE_CHILD,
+ MD_ERROR_WIN_DS_SECURITY_ILLEGAL_MODIFY,
+ MD_ERROR_WIN_DS_CANT_REPLACE_HIDDEN_REC,
+ MD_ERROR_WIN_DS_BAD_HIERARCHY_FILE,
+ MD_ERROR_WIN_DS_BUILD_HIERARCHY_TABLE_FAILED,
+ MD_ERROR_WIN_DS_CONFIG_PARAM_MISSING,
+ MD_ERROR_WIN_DS_COUNTING_AB_INDICES_FAILED,
+ MD_ERROR_WIN_DS_HIERARCHY_TABLE_MALLOC_FAILED,
+ MD_ERROR_WIN_DS_INTERNAL_FAILURE,
+ MD_ERROR_WIN_DS_UNKNOWN_ERROR,
+ MD_ERROR_WIN_DS_ROOT_REQUIRES_CLASS_TOP,
+ MD_ERROR_WIN_DS_REFUSING_FSMO_ROLES,
+ MD_ERROR_WIN_DS_MISSING_FSMO_SETTINGS,
+ MD_ERROR_WIN_DS_UNABLE_TO_SURRENDER_ROLES,
+ MD_ERROR_WIN_DS_DRA_GENERIC,
+ MD_ERROR_WIN_DS_DRA_INVALID_PARAMETER,
+ MD_ERROR_WIN_DS_DRA_BUSY,
+ MD_ERROR_WIN_DS_DRA_BAD_DN,
+ MD_ERROR_WIN_DS_DRA_BAD_NC,
+ MD_ERROR_WIN_DS_DRA_DN_EXISTS,
+ MD_ERROR_WIN_DS_DRA_INTERNAL_ERROR,
+ MD_ERROR_WIN_DS_DRA_INCONSISTENT_DIT,
+ MD_ERROR_WIN_DS_DRA_CONNECTION_FAILED,
+ MD_ERROR_WIN_DS_DRA_BAD_INSTANCE_TYPE,
+ MD_ERROR_WIN_DS_DRA_OUT_OF_MEM,
+ MD_ERROR_WIN_DS_DRA_MAIL_PROBLEM,
+ MD_ERROR_WIN_DS_DRA_REF_ALREADY_EXISTS,
+ MD_ERROR_WIN_DS_DRA_REF_NOT_FOUND,
+ MD_ERROR_WIN_DS_DRA_OBJ_IS_REP_SOURCE,
+ MD_ERROR_WIN_DS_DRA_DB_ERROR,
+ MD_ERROR_WIN_DS_DRA_NO_REPLICA,
+ MD_ERROR_WIN_DS_DRA_ACCESS_DENIED,
+ MD_ERROR_WIN_DS_DRA_NOT_SUPPORTED,
+ MD_ERROR_WIN_DS_DRA_RPC_CANCELLED,
+ MD_ERROR_WIN_DS_DRA_SOURCE_DISABLED,
+ MD_ERROR_WIN_DS_DRA_SINK_DISABLED,
+ MD_ERROR_WIN_DS_DRA_NAME_COLLISION,
+ MD_ERROR_WIN_DS_DRA_SOURCE_REINSTALLED,
+ MD_ERROR_WIN_DS_DRA_MISSING_PARENT,
+ MD_ERROR_WIN_DS_DRA_PREEMPTED,
+ MD_ERROR_WIN_DS_DRA_ABANDON_SYNC,
+ MD_ERROR_WIN_DS_DRA_SHUTDOWN,
+ MD_ERROR_WIN_DS_DRA_INCOMPATIBLE_PARTIAL_SET,
+ MD_ERROR_WIN_DS_DRA_SOURCE_IS_PARTIAL_REPLICA,
+ MD_ERROR_WIN_DS_DRA_EXTN_CONNECTION_FAILED,
+ MD_ERROR_WIN_DS_INSTALL_SCHEMA_MISMATCH,
+ MD_ERROR_WIN_DS_DUP_LINK_ID,
+ MD_ERROR_WIN_DS_NAME_ERROR_RESOLVING,
+ MD_ERROR_WIN_DS_NAME_ERROR_NOT_FOUND,
+ MD_ERROR_WIN_DS_NAME_ERROR_NOT_UNIQUE,
+ MD_ERROR_WIN_DS_NAME_ERROR_NO_MAPPING,
+ MD_ERROR_WIN_DS_NAME_ERROR_DOMAIN_ONLY,
+ MD_ERROR_WIN_DS_NAME_ERROR_NO_SYNTACTICAL_MAPPING,
+ MD_ERROR_WIN_DS_CONSTRUCTED_ATT_MOD,
+ MD_ERROR_WIN_DS_WRONG_OM_OBJ_CLASS,
+ MD_ERROR_WIN_DS_DRA_REPL_PENDING,
+ MD_ERROR_WIN_DS_DS_REQUIRED,
+ MD_ERROR_WIN_DS_INVALID_LDAP_DISPLAY_NAME,
+ MD_ERROR_WIN_DS_NON_BASE_SEARCH,
+ MD_ERROR_WIN_DS_CANT_RETRIEVE_ATTS,
+ MD_ERROR_WIN_DS_BACKLINK_WITHOUT_LINK,
+ MD_ERROR_WIN_DS_EPOCH_MISMATCH,
+ MD_ERROR_WIN_DS_SRC_NAME_MISMATCH,
+ MD_ERROR_WIN_DS_SRC_AND_DST_NC_IDENTICAL,
+ MD_ERROR_WIN_DS_DST_NC_MISMATCH,
+ MD_ERROR_WIN_DS_NOT_AUTHORITIVE_FOR_DST_NC,
+ MD_ERROR_WIN_DS_SRC_GUID_MISMATCH,
+ MD_ERROR_WIN_DS_CANT_MOVE_DELETED_OBJECT,
+ MD_ERROR_WIN_DS_PDC_OPERATION_IN_PROGRESS,
+ MD_ERROR_WIN_DS_CROSS_DOMAIN_CLEANUP_REQD,
+ MD_ERROR_WIN_DS_ILLEGAL_XDOM_MOVE_OPERATION,
+ MD_ERROR_WIN_DS_CANT_WITH_ACCT_GROUP_MEMBERSHPS,
+ MD_ERROR_WIN_DS_NC_MUST_HAVE_NC_PARENT,
+ MD_ERROR_WIN_DS_CR_IMPOSSIBLE_TO_VALIDATE,
+ MD_ERROR_WIN_DS_DST_DOMAIN_NOT_NATIVE,
+ MD_ERROR_WIN_DS_MISSING_INFRASTRUCTURE_CONTAINER,
+ MD_ERROR_WIN_DS_CANT_MOVE_ACCOUNT_GROUP,
+ MD_ERROR_WIN_DS_CANT_MOVE_RESOURCE_GROUP,
+ MD_ERROR_WIN_DS_INVALID_SEARCH_FLAG,
+ MD_ERROR_WIN_DS_NO_TREE_DELETE_ABOVE_NC,
+ MD_ERROR_WIN_DS_COULDNT_LOCK_TREE_FOR_DELETE,
+ MD_ERROR_WIN_DS_COULDNT_IDENTIFY_OBJECTS_FOR_TREE_DELETE,
+ MD_ERROR_WIN_DS_SAM_INIT_FAILURE,
+ MD_ERROR_WIN_DS_SENSITIVE_GROUP_VIOLATION,
+ MD_ERROR_WIN_DS_CANT_MOD_PRIMARYGROUPID,
+ MD_ERROR_WIN_DS_ILLEGAL_BASE_SCHEMA_MOD,
+ MD_ERROR_WIN_DS_NONSAFE_SCHEMA_CHANGE,
+ MD_ERROR_WIN_DS_SCHEMA_UPDATE_DISALLOWED,
+ MD_ERROR_WIN_DS_CANT_CREATE_UNDER_SCHEMA,
+ MD_ERROR_WIN_DS_INSTALL_NO_SRC_SCH_VERSION,
+ MD_ERROR_WIN_DS_INSTALL_NO_SCH_VERSION_IN_INIFILE,
+ MD_ERROR_WIN_DS_INVALID_GROUP_TYPE,
+ MD_ERROR_WIN_DS_NO_NEST_GLOBALGROUP_IN_MIXEDDOMAIN,
+ MD_ERROR_WIN_DS_NO_NEST_LOCALGROUP_IN_MIXEDDOMAIN,
+ MD_ERROR_WIN_DS_GLOBAL_CANT_HAVE_LOCAL_MEMBER,
+ MD_ERROR_WIN_DS_GLOBAL_CANT_HAVE_UNIVERSAL_MEMBER,
+ MD_ERROR_WIN_DS_UNIVERSAL_CANT_HAVE_LOCAL_MEMBER,
+ MD_ERROR_WIN_DS_GLOBAL_CANT_HAVE_CROSSDOMAIN_MEMBER,
+ MD_ERROR_WIN_DS_LOCAL_CANT_HAVE_CROSSDOMAIN_LOCAL_MEMBER,
+ MD_ERROR_WIN_DS_HAVE_PRIMARY_MEMBERS,
+ MD_ERROR_WIN_DS_STRING_SD_CONVERSION_FAILED,
+ MD_ERROR_WIN_DS_NAMING_MASTER_GC,
+ MD_ERROR_WIN_DS_DNS_LOOKUP_FAILURE,
+ MD_ERROR_WIN_DS_COULDNT_UPDATE_SPNS,
+ MD_ERROR_WIN_DS_CANT_RETRIEVE_SD,
+ MD_ERROR_WIN_DS_KEY_NOT_UNIQUE,
+ MD_ERROR_WIN_DS_WRONG_LINKED_ATT_SYNTAX,
+ MD_ERROR_WIN_DS_SAM_NEED_BOOTKEY_PASSWORD,
+ MD_ERROR_WIN_DS_SAM_NEED_BOOTKEY_FLOPPY,
+ MD_ERROR_WIN_DS_CANT_START,
+ MD_ERROR_WIN_DS_INIT_FAILURE,
+ MD_ERROR_WIN_DS_NO_PKT_PRIVACY_ON_CONNECTION,
+ MD_ERROR_WIN_DS_SOURCE_DOMAIN_IN_FOREST,
+ MD_ERROR_WIN_DS_DESTINATION_DOMAIN_NOT_IN_FOREST,
+ MD_ERROR_WIN_DS_DESTINATION_AUDITING_NOT_ENABLED,
+ MD_ERROR_WIN_DS_CANT_FIND_DC_FOR_SRC_DOMAIN,
+ MD_ERROR_WIN_DS_SRC_OBJ_NOT_GROUP_OR_USER,
+ MD_ERROR_WIN_DS_SRC_SID_EXISTS_IN_FOREST,
+ MD_ERROR_WIN_DS_SRC_AND_DST_OBJECT_CLASS_MISMATCH,
+ MD_ERROR_WIN_SAM_INIT_FAILURE,
+ MD_ERROR_WIN_DS_DRA_SCHEMA_INFO_SHIP,
+ MD_ERROR_WIN_DS_DRA_SCHEMA_CONFLICT,
+ MD_ERROR_WIN_DS_DRA_EARLIER_SCHEMA_CONFLICT,
+ MD_ERROR_WIN_DS_DRA_OBJ_NC_MISMATCH,
+ MD_ERROR_WIN_DS_NC_STILL_HAS_DSAS,
+ MD_ERROR_WIN_DS_GC_REQUIRED,
+ MD_ERROR_WIN_DS_LOCAL_MEMBER_OF_LOCAL_ONLY,
+ MD_ERROR_WIN_DS_NO_FPO_IN_UNIVERSAL_GROUPS,
+ MD_ERROR_WIN_DS_CANT_ADD_TO_GC,
+ MD_ERROR_WIN_DS_NO_CHECKPOINT_WITH_PDC,
+ MD_ERROR_WIN_DS_SOURCE_AUDITING_NOT_ENABLED,
+ MD_ERROR_WIN_DS_CANT_CREATE_IN_NONDOMAIN_NC,
+ MD_ERROR_WIN_DS_INVALID_NAME_FOR_SPN,
+ MD_ERROR_WIN_DS_FILTER_USES_CONTRUCTED_ATTRS,
+ MD_ERROR_WIN_DS_UNICODEPWD_NOT_IN_QUOTES,
+ MD_ERROR_WIN_DS_MACHINE_ACCOUNT_QUOTA_EXCEEDED,
+ MD_ERROR_WIN_DS_MUST_BE_RUN_ON_DST_DC,
+ MD_ERROR_WIN_DS_SRC_DC_MUST_BE_SP4_OR_GREATER,
+ MD_ERROR_WIN_DS_CANT_TREE_DELETE_CRITICAL_OBJ,
+ MD_ERROR_WIN_DS_INIT_FAILURE_CONSOLE,
+ MD_ERROR_WIN_DS_SAM_INIT_FAILURE_CONSOLE,
+ MD_ERROR_WIN_DS_FOREST_VERSION_TOO_HIGH,
+ MD_ERROR_WIN_DS_DOMAIN_VERSION_TOO_HIGH,
+ MD_ERROR_WIN_DS_FOREST_VERSION_TOO_LOW,
+ MD_ERROR_WIN_DS_DOMAIN_VERSION_TOO_LOW,
+ MD_ERROR_WIN_DS_INCOMPATIBLE_VERSION,
+ MD_ERROR_WIN_DS_LOW_DSA_VERSION,
+ MD_ERROR_WIN_DS_NO_BEHAVIOR_VERSION_IN_MIXEDDOMAIN,
+ MD_ERROR_WIN_DS_NOT_SUPPORTED_SORT_ORDER,
+ MD_ERROR_WIN_DS_NAME_NOT_UNIQUE,
+ MD_ERROR_WIN_DS_MACHINE_ACCOUNT_CREATED_PRENT4,
+ MD_ERROR_WIN_DS_OUT_OF_VERSION_STORE,
+ MD_ERROR_WIN_DS_INCOMPATIBLE_CONTROLS_USED,
+ MD_ERROR_WIN_DS_NO_REF_DOMAIN,
+ MD_ERROR_WIN_DS_RESERVED_LINK_ID,
+ MD_ERROR_WIN_DS_LINK_ID_NOT_AVAILABLE,
+ MD_ERROR_WIN_DS_AG_CANT_HAVE_UNIVERSAL_MEMBER,
+ MD_ERROR_WIN_DS_MODIFYDN_DISALLOWED_BY_INSTANCE_TYPE,
+ MD_ERROR_WIN_DS_NO_OBJECT_MOVE_IN_SCHEMA_NC,
+ MD_ERROR_WIN_DS_MODIFYDN_DISALLOWED_BY_FLAG,
+ MD_ERROR_WIN_DS_MODIFYDN_WRONG_GRANDPARENT,
+ MD_ERROR_WIN_DS_NAME_ERROR_TRUST_REFERRAL,
+ MD_ERROR_WIN_NOT_SUPPORTED_ON_STANDARD_SERVER,
+ MD_ERROR_WIN_DS_CANT_ACCESS_REMOTE_PART_OF_AD,
+ MD_ERROR_WIN_DS_CR_IMPOSSIBLE_TO_VALIDATE_V2,
+ MD_ERROR_WIN_DS_THREAD_LIMIT_EXCEEDED,
+ MD_ERROR_WIN_DS_NOT_CLOSEST,
+ MD_ERROR_WIN_DS_CANT_DERIVE_SPN_WITHOUT_SERVER_REF,
+ MD_ERROR_WIN_DS_SINGLE_USER_MODE_FAILED,
+ MD_ERROR_WIN_DS_NTDSCRIPT_SYNTAX_ERROR,
+ MD_ERROR_WIN_DS_NTDSCRIPT_PROCESS_ERROR,
+ MD_ERROR_WIN_DS_DIFFERENT_REPL_EPOCHS,
+ MD_ERROR_WIN_DS_DRS_EXTENSIONS_CHANGED,
+ MD_ERROR_WIN_DS_REPLICA_SET_CHANGE_NOT_ALLOWED_ON_DISABLED_CR,
+ MD_ERROR_WIN_DS_NO_MSDS_INTID,
+ MD_ERROR_WIN_DS_DUP_MSDS_INTID,
+ MD_ERROR_WIN_DS_EXISTS_IN_RDNATTID,
+ MD_ERROR_WIN_DS_AUTHORIZATION_FAILED,
+ MD_ERROR_WIN_DS_INVALID_SCRIPT,
+ MD_ERROR_WIN_DS_REMOTE_CROSSREF_OP_FAILED,
+ MD_ERROR_WIN_DS_CROSS_REF_BUSY,
+ MD_ERROR_WIN_DS_CANT_DERIVE_SPN_FOR_DELETED_DOMAIN,
+ MD_ERROR_WIN_DS_CANT_DEMOTE_WITH_WRITEABLE_NC,
+ MD_ERROR_WIN_DS_DUPLICATE_ID_FOUND,
+ MD_ERROR_WIN_DS_INSUFFICIENT_ATTR_TO_CREATE_OBJECT,
+ MD_ERROR_WIN_DS_GROUP_CONVERSION_ERROR,
+ MD_ERROR_WIN_DS_CANT_MOVE_APP_BASIC_GROUP,
+ MD_ERROR_WIN_DS_CANT_MOVE_APP_QUERY_GROUP,
+ MD_ERROR_WIN_DS_ROLE_NOT_VERIFIED,
+ MD_ERROR_WIN_DS_WKO_CONTAINER_CANNOT_BE_SPECIAL,
+ MD_ERROR_WIN_DS_DOMAIN_RENAME_IN_PROGRESS,
+ MD_ERROR_WIN_DS_EXISTING_AD_CHILD_NC,
+ MD_ERROR_WIN_DS_REPL_LIFETIME_EXCEEDED,
+ MD_ERROR_WIN_DS_DISALLOWED_IN_SYSTEM_CONTAINER,
+ MD_ERROR_WIN_DS_LDAP_SEND_QUEUE_FULL,
+ MD_ERROR_WIN_DS_DRA_OUT_SCHEDULE_WINDOW,
+ MD_ERROR_WIN_DS_POLICY_NOT_KNOWN,
+ MD_ERROR_WIN_NO_SITE_SETTINGS_OBJECT,
+ MD_ERROR_WIN_NO_SECRETS,
+ MD_ERROR_WIN_NO_WRITABLE_DC_FOUND,
+ MD_ERROR_WIN_DS_NO_SERVER_OBJECT,
+ MD_ERROR_WIN_DS_NO_NTDSA_OBJECT,
+ MD_ERROR_WIN_DS_NON_ASQ_SEARCH,
+ MD_ERROR_WIN_DS_AUDIT_FAILURE,
+ MD_ERROR_WIN_DS_INVALID_SEARCH_FLAG_SUBTREE,
+ MD_ERROR_WIN_DS_INVALID_SEARCH_FLAG_TUPLE,
+ MD_ERROR_WIN_DS_HIERARCHY_TABLE_TOO_DEEP,
+ MD_ERROR_WIN_DS_DRA_CORRUPT_UTD_VECTOR,
+ MD_ERROR_WIN_DS_DRA_SECRETS_DENIED,
+ MD_ERROR_WIN_DS_RESERVED_MAPI_ID,
+ MD_ERROR_WIN_DS_MAPI_ID_NOT_AVAILABLE,
+ MD_ERROR_WIN_DS_DRA_MISSING_KRBTGT_SECRET,
+ MD_ERROR_WIN_DS_DOMAIN_NAME_EXISTS_IN_FOREST,
+ MD_ERROR_WIN_DS_FLAT_NAME_EXISTS_IN_FOREST,
+ MD_ERROR_WIN_INVALID_USER_PRINCIPAL_NAME,
+ MD_ERROR_WIN_DS_OID_MAPPED_GROUP_CANT_HAVE_MEMBERS,
+ MD_ERROR_WIN_DS_OID_NOT_FOUND,
+ MD_ERROR_WIN_DS_DRA_RECYCLED_TARGET,
+ MD_ERROR_WIN_DS_DISALLOWED_NC_REDIRECT,
+ MD_ERROR_WIN_DS_HIGH_ADLDS_FFL,
+ MD_ERROR_WIN_DS_HIGH_DSA_VERSION,
+ MD_ERROR_WIN_DS_LOW_ADLDS_FFL,
+ MD_ERROR_WIN_DOMAIN_SID_SAME_AS_LOCAL_WORKSTATION,
+ MD_ERROR_WIN_DS_UNDELETE_SAM_VALIDATION_FAILED,
+ MD_ERROR_WIN_INCORRECT_ACCOUNT_TYPE,
+ MD_ERROR_WIN_DS_SPN_VALUE_NOT_UNIQUE_IN_FOREST,
+ MD_ERROR_WIN_DS_UPN_VALUE_NOT_UNIQUE_IN_FOREST,
+ MD_ERROR_WIN_DS_MISSING_FOREST_TRUST,
+ MD_ERROR_WIN_DS_VALUE_KEY_NOT_UNIQUE,
+ MD_ERROR_WIN_IPSEC_QM_POLICY_EXISTS,
+ MD_ERROR_WIN_IPSEC_QM_POLICY_NOT_FOUND,
+ MD_ERROR_WIN_IPSEC_QM_POLICY_IN_USE,
+ MD_ERROR_WIN_IPSEC_MM_POLICY_EXISTS,
+ MD_ERROR_WIN_IPSEC_MM_POLICY_NOT_FOUND,
+ MD_ERROR_WIN_IPSEC_MM_POLICY_IN_USE,
+ MD_ERROR_WIN_IPSEC_MM_FILTER_EXISTS,
+ MD_ERROR_WIN_IPSEC_MM_FILTER_NOT_FOUND,
+ MD_ERROR_WIN_IPSEC_TRANSPORT_FILTER_EXISTS,
+ MD_ERROR_WIN_IPSEC_TRANSPORT_FILTER_NOT_FOUND,
+ MD_ERROR_WIN_IPSEC_MM_AUTH_EXISTS,
+ MD_ERROR_WIN_IPSEC_MM_AUTH_NOT_FOUND,
+ MD_ERROR_WIN_IPSEC_MM_AUTH_IN_USE,
+ MD_ERROR_WIN_IPSEC_DEFAULT_MM_POLICY_NOT_FOUND,
+ MD_ERROR_WIN_IPSEC_DEFAULT_MM_AUTH_NOT_FOUND,
+ MD_ERROR_WIN_IPSEC_DEFAULT_QM_POLICY_NOT_FOUND,
+ MD_ERROR_WIN_IPSEC_TUNNEL_FILTER_EXISTS,
+ MD_ERROR_WIN_IPSEC_TUNNEL_FILTER_NOT_FOUND,
+ MD_ERROR_WIN_IPSEC_MM_FILTER_PENDING_DELETION,
+ MD_ERROR_WIN_IPSEC_TRANSPORT_FILTER_PENDING_DELETION,
+ MD_ERROR_WIN_IPSEC_TUNNEL_FILTER_PENDING_DELETION,
+ MD_ERROR_WIN_IPSEC_MM_POLICY_PENDING_DELETION,
+ MD_ERROR_WIN_IPSEC_MM_AUTH_PENDING_DELETION,
+ MD_ERROR_WIN_IPSEC_QM_POLICY_PENDING_DELETION,
+ MD_ERROR_WIN_IPSEC_IKE_NEG_STATUS_BEGIN,
+ MD_ERROR_WIN_IPSEC_IKE_AUTH_FAIL,
+ MD_ERROR_WIN_IPSEC_IKE_ATTRIB_FAIL,
+ MD_ERROR_WIN_IPSEC_IKE_NEGOTIATION_PENDING,
+ MD_ERROR_WIN_IPSEC_IKE_GENERAL_PROCESSING_ERROR,
+ MD_ERROR_WIN_IPSEC_IKE_TIMED_OUT,
+ MD_ERROR_WIN_IPSEC_IKE_NO_CERT,
+ MD_ERROR_WIN_IPSEC_IKE_SA_DELETED,
+ MD_ERROR_WIN_IPSEC_IKE_SA_REAPED,
+ MD_ERROR_WIN_IPSEC_IKE_MM_ACQUIRE_DROP,
+ MD_ERROR_WIN_IPSEC_IKE_QM_ACQUIRE_DROP,
+ MD_ERROR_WIN_IPSEC_IKE_QUEUE_DROP_MM,
+ MD_ERROR_WIN_IPSEC_IKE_QUEUE_DROP_NO_MM,
+ MD_ERROR_WIN_IPSEC_IKE_DROP_NO_RESPONSE,
+ MD_ERROR_WIN_IPSEC_IKE_MM_DELAY_DROP,
+ MD_ERROR_WIN_IPSEC_IKE_QM_DELAY_DROP,
+ MD_ERROR_WIN_IPSEC_IKE_ERROR,
+ MD_ERROR_WIN_IPSEC_IKE_CRL_FAILED,
+ MD_ERROR_WIN_IPSEC_IKE_INVALID_KEY_USAGE,
+ MD_ERROR_WIN_IPSEC_IKE_INVALID_CERT_TYPE,
+ MD_ERROR_WIN_IPSEC_IKE_NO_PRIVATE_KEY,
+ MD_ERROR_WIN_IPSEC_IKE_SIMULTANEOUS_REKEY,
+ MD_ERROR_WIN_IPSEC_IKE_DH_FAIL,
+ MD_ERROR_WIN_IPSEC_IKE_CRITICAL_PAYLOAD_NOT_RECOGNIZED,
+ MD_ERROR_WIN_IPSEC_IKE_INVALID_HEADER,
+ MD_ERROR_WIN_IPSEC_IKE_NO_POLICY,
+ MD_ERROR_WIN_IPSEC_IKE_INVALID_SIGNATURE,
+ MD_ERROR_WIN_IPSEC_IKE_KERBEROS_ERROR,
+ MD_ERROR_WIN_IPSEC_IKE_NO_PUBLIC_KEY,
+ MD_ERROR_WIN_IPSEC_IKE_PROCESS_ERR,
+ MD_ERROR_WIN_IPSEC_IKE_PROCESS_ERR_SA,
+ MD_ERROR_WIN_IPSEC_IKE_PROCESS_ERR_PROP,
+ MD_ERROR_WIN_IPSEC_IKE_PROCESS_ERR_TRANS,
+ MD_ERROR_WIN_IPSEC_IKE_PROCESS_ERR_KE,
+ MD_ERROR_WIN_IPSEC_IKE_PROCESS_ERR_ID,
+ MD_ERROR_WIN_IPSEC_IKE_PROCESS_ERR_CERT,
+ MD_ERROR_WIN_IPSEC_IKE_PROCESS_ERR_CERT_REQ,
+ MD_ERROR_WIN_IPSEC_IKE_PROCESS_ERR_HASH,
+ MD_ERROR_WIN_IPSEC_IKE_PROCESS_ERR_SIG,
+ MD_ERROR_WIN_IPSEC_IKE_PROCESS_ERR_NONCE,
+ MD_ERROR_WIN_IPSEC_IKE_PROCESS_ERR_NOTIFY,
+ MD_ERROR_WIN_IPSEC_IKE_PROCESS_ERR_DELETE,
+ MD_ERROR_WIN_IPSEC_IKE_PROCESS_ERR_VENDOR,
+ MD_ERROR_WIN_IPSEC_IKE_INVALID_PAYLOAD,
+ MD_ERROR_WIN_IPSEC_IKE_LOAD_SOFT_SA,
+ MD_ERROR_WIN_IPSEC_IKE_SOFT_SA_TORN_DOWN,
+ MD_ERROR_WIN_IPSEC_IKE_INVALID_COOKIE,
+ MD_ERROR_WIN_IPSEC_IKE_NO_PEER_CERT,
+ MD_ERROR_WIN_IPSEC_IKE_PEER_CRL_FAILED,
+ MD_ERROR_WIN_IPSEC_IKE_POLICY_CHANGE,
+ MD_ERROR_WIN_IPSEC_IKE_NO_MM_POLICY,
+ MD_ERROR_WIN_IPSEC_IKE_NOTCBPRIV,
+ MD_ERROR_WIN_IPSEC_IKE_SECLOADFAIL,
+ MD_ERROR_WIN_IPSEC_IKE_FAILSSPINIT,
+ MD_ERROR_WIN_IPSEC_IKE_FAILQUERYSSP,
+ MD_ERROR_WIN_IPSEC_IKE_SRVACQFAIL,
+ MD_ERROR_WIN_IPSEC_IKE_SRVQUERYCRED,
+ MD_ERROR_WIN_IPSEC_IKE_GETSPIFAIL,
+ MD_ERROR_WIN_IPSEC_IKE_INVALID_FILTER,
+ MD_ERROR_WIN_IPSEC_IKE_OUT_OF_MEMORY,
+ MD_ERROR_WIN_IPSEC_IKE_ADD_UPDATE_KEY_FAILED,
+ MD_ERROR_WIN_IPSEC_IKE_INVALID_POLICY,
+ MD_ERROR_WIN_IPSEC_IKE_UNKNOWN_DOI,
+ MD_ERROR_WIN_IPSEC_IKE_INVALID_SITUATION,
+ MD_ERROR_WIN_IPSEC_IKE_DH_FAILURE,
+ MD_ERROR_WIN_IPSEC_IKE_INVALID_GROUP,
+ MD_ERROR_WIN_IPSEC_IKE_ENCRYPT,
+ MD_ERROR_WIN_IPSEC_IKE_DECRYPT,
+ MD_ERROR_WIN_IPSEC_IKE_POLICY_MATCH,
+ MD_ERROR_WIN_IPSEC_IKE_UNSUPPORTED_ID,
+ MD_ERROR_WIN_IPSEC_IKE_INVALID_HASH,
+ MD_ERROR_WIN_IPSEC_IKE_INVALID_HASH_ALG,
+ MD_ERROR_WIN_IPSEC_IKE_INVALID_HASH_SIZE,
+ MD_ERROR_WIN_IPSEC_IKE_INVALID_ENCRYPT_ALG,
+ MD_ERROR_WIN_IPSEC_IKE_INVALID_AUTH_ALG,
+ MD_ERROR_WIN_IPSEC_IKE_INVALID_SIG,
+ MD_ERROR_WIN_IPSEC_IKE_LOAD_FAILED,
+ MD_ERROR_WIN_IPSEC_IKE_RPC_DELETE,
+ MD_ERROR_WIN_IPSEC_IKE_BENIGN_REINIT,
+ MD_ERROR_WIN_IPSEC_IKE_INVALID_RESPONDER_LIFETIME_NOTIFY,
+ MD_ERROR_WIN_IPSEC_IKE_INVALID_MAJOR_VERSION,
+ MD_ERROR_WIN_IPSEC_IKE_INVALID_CERT_KEYLEN,
+ MD_ERROR_WIN_IPSEC_IKE_MM_LIMIT,
+ MD_ERROR_WIN_IPSEC_IKE_NEGOTIATION_DISABLED,
+ MD_ERROR_WIN_IPSEC_IKE_QM_LIMIT,
+ MD_ERROR_WIN_IPSEC_IKE_MM_EXPIRED,
+ MD_ERROR_WIN_IPSEC_IKE_PEER_MM_ASSUMED_INVALID,
+ MD_ERROR_WIN_IPSEC_IKE_CERT_CHAIN_POLICY_MISMATCH,
+ MD_ERROR_WIN_IPSEC_IKE_UNEXPECTED_MESSAGE_ID,
+ MD_ERROR_WIN_IPSEC_IKE_INVALID_AUTH_PAYLOAD,
+ MD_ERROR_WIN_IPSEC_IKE_DOS_COOKIE_SENT,
+ MD_ERROR_WIN_IPSEC_IKE_SHUTTING_DOWN,
+ MD_ERROR_WIN_IPSEC_IKE_CGA_AUTH_FAILED,
+ MD_ERROR_WIN_IPSEC_IKE_PROCESS_ERR_NATOA,
+ MD_ERROR_WIN_IPSEC_IKE_INVALID_MM_FOR_QM,
+ MD_ERROR_WIN_IPSEC_IKE_QM_EXPIRED,
+ MD_ERROR_WIN_IPSEC_IKE_TOO_MANY_FILTERS,
+ MD_ERROR_WIN_IPSEC_IKE_NEG_STATUS_END,
+ MD_ERROR_WIN_IPSEC_IKE_KILL_DUMMY_NAP_TUNNEL,
+ MD_ERROR_WIN_IPSEC_IKE_INNER_IP_ASSIGNMENT_FAILURE,
+ MD_ERROR_WIN_IPSEC_IKE_REQUIRE_CP_PAYLOAD_MISSING,
+ MD_ERROR_WIN_IPSEC_KEY_MODULE_IMPERSONATION_NEGOTIATION_PENDING,
+ MD_ERROR_WIN_IPSEC_IKE_COEXISTENCE_SUPPRESS,
+ MD_ERROR_WIN_IPSEC_IKE_RATELIMIT_DROP,
+ MD_ERROR_WIN_IPSEC_IKE_PEER_DOESNT_SUPPORT_MOBIKE,
+ MD_ERROR_WIN_IPSEC_IKE_AUTHORIZATION_FAILURE,
+ MD_ERROR_WIN_IPSEC_IKE_STRONG_CRED_AUTHORIZATION_FAILURE,
+ MD_ERROR_WIN_IPSEC_IKE_AUTHORIZATION_FAILURE_WITH_OPTIONAL_RETRY,
+ MD_ERROR_WIN_IPSEC_IKE_STRONG_CRED_AUTHORIZATION_AND_CERTMAP_FAILURE,
+ MD_ERROR_WIN_IPSEC_IKE_NEG_STATUS_EXTENDED_END,
+ MD_ERROR_WIN_IPSEC_BAD_SPI,
+ MD_ERROR_WIN_IPSEC_SA_LIFETIME_EXPIRED,
+ MD_ERROR_WIN_IPSEC_WRONG_SA,
+ MD_ERROR_WIN_IPSEC_REPLAY_CHECK_FAILED,
+ MD_ERROR_WIN_IPSEC_INVALID_PACKET,
+ MD_ERROR_WIN_IPSEC_INTEGRITY_CHECK_FAILED,
+ MD_ERROR_WIN_IPSEC_CLEAR_TEXT_DROP,
+ MD_ERROR_WIN_IPSEC_AUTH_FIREWALL_DROP,
+ MD_ERROR_WIN_IPSEC_THROTTLE_DROP,
+ MD_ERROR_WIN_IPSEC_DOSP_BLOCK,
+ MD_ERROR_WIN_IPSEC_DOSP_RECEIVED_MULTICAST,
+ MD_ERROR_WIN_IPSEC_DOSP_INVALID_PACKET,
+ MD_ERROR_WIN_IPSEC_DOSP_STATE_LOOKUP_FAILED,
+ MD_ERROR_WIN_IPSEC_DOSP_MAX_ENTRIES,
+ MD_ERROR_WIN_IPSEC_DOSP_KEYMOD_NOT_ALLOWED,
+ MD_ERROR_WIN_IPSEC_DOSP_NOT_INSTALLED,
+ MD_ERROR_WIN_IPSEC_DOSP_MAX_PER_IP_RATELIMIT_QUEUES,
+ MD_ERROR_WIN_SXS_SECTION_NOT_FOUND,
+ MD_ERROR_WIN_SXS_CANT_GEN_ACTCTX,
+ MD_ERROR_WIN_SXS_INVALID_ACTCTXDATA_FORMAT,
+ MD_ERROR_WIN_SXS_ASSEMBLY_NOT_FOUND,
+ MD_ERROR_WIN_SXS_MANIFEST_FORMAT_ERROR,
+ MD_ERROR_WIN_SXS_MANIFEST_PARSE_ERROR,
+ MD_ERROR_WIN_SXS_ACTIVATION_CONTEXT_DISABLED,
+ MD_ERROR_WIN_SXS_KEY_NOT_FOUND,
+ MD_ERROR_WIN_SXS_VERSION_CONFLICT,
+ MD_ERROR_WIN_SXS_WRONG_SECTION_TYPE,
+ MD_ERROR_WIN_SXS_THREAD_QUERIES_DISABLED,
+ MD_ERROR_WIN_SXS_PROCESS_DEFAULT_ALREADY_SET,
+ MD_ERROR_WIN_SXS_UNKNOWN_ENCODING_GROUP,
+ MD_ERROR_WIN_SXS_UNKNOWN_ENCODING,
+ MD_ERROR_WIN_SXS_INVALID_XML_NAMESPACE_URI,
+ MD_ERROR_WIN_SXS_ROOT_MANIFEST_DEPENDENCY_NOT_INSTALLED,
+ MD_ERROR_WIN_SXS_LEAF_MANIFEST_DEPENDENCY_NOT_INSTALLED,
+ MD_ERROR_WIN_SXS_INVALID_ASSEMBLY_IDENTITY_ATTRIBUTE,
+ MD_ERROR_WIN_SXS_MANIFEST_MISSING_REQUIRED_DEFAULT_NAMESPACE,
+ MD_ERROR_WIN_SXS_MANIFEST_INVALID_REQUIRED_DEFAULT_NAMESPACE,
+ MD_ERROR_WIN_SXS_PRIVATE_MANIFEST_CROSS_PATH_WITH_REPARSE_POINT,
+ MD_ERROR_WIN_SXS_DUPLICATE_DLL_NAME,
+ MD_ERROR_WIN_SXS_DUPLICATE_WINDOWCLASS_NAME,
+ MD_ERROR_WIN_SXS_DUPLICATE_CLSID,
+ MD_ERROR_WIN_SXS_DUPLICATE_IID,
+ MD_ERROR_WIN_SXS_DUPLICATE_TLBID,
+ MD_ERROR_WIN_SXS_DUPLICATE_PROGID,
+ MD_ERROR_WIN_SXS_DUPLICATE_ASSEMBLY_NAME,
+ MD_ERROR_WIN_SXS_FILE_HASH_MISMATCH,
+ MD_ERROR_WIN_SXS_POLICY_PARSE_ERROR,
+ MD_ERROR_WIN_SXS_XML_E_MISSINGQUOTE,
+ MD_ERROR_WIN_SXS_XML_E_COMMENTSYNTAX,
+ MD_ERROR_WIN_SXS_XML_E_BADSTARTNAMECHAR,
+ MD_ERROR_WIN_SXS_XML_E_BADNAMECHAR,
+ MD_ERROR_WIN_SXS_XML_E_BADCHARINSTRING,
+ MD_ERROR_WIN_SXS_XML_E_XMLDECLSYNTAX,
+ MD_ERROR_WIN_SXS_XML_E_BADCHARDATA,
+ MD_ERROR_WIN_SXS_XML_E_MISSINGWHITESPACE,
+ MD_ERROR_WIN_SXS_XML_E_EXPECTINGTAGEND,
+ MD_ERROR_WIN_SXS_XML_E_MISSINGSEMICOLON,
+ MD_ERROR_WIN_SXS_XML_E_UNBALANCEDPAREN,
+ MD_ERROR_WIN_SXS_XML_E_INTERNALERROR,
+ MD_ERROR_WIN_SXS_XML_E_UNEXPECTED_WHITESPACE,
+ MD_ERROR_WIN_SXS_XML_E_INCOMPLETE_ENCODING,
+ MD_ERROR_WIN_SXS_XML_E_MISSING_PAREN,
+ MD_ERROR_WIN_SXS_XML_E_EXPECTINGCLOSEQUOTE,
+ MD_ERROR_WIN_SXS_XML_E_MULTIPLE_COLONS,
+ MD_ERROR_WIN_SXS_XML_E_INVALID_DECIMAL,
+ MD_ERROR_WIN_SXS_XML_E_INVALID_HEXIDECIMAL,
+ MD_ERROR_WIN_SXS_XML_E_INVALID_UNICODE,
+ MD_ERROR_WIN_SXS_XML_E_WHITESPACEORQUESTIONMARK,
+ MD_ERROR_WIN_SXS_XML_E_UNEXPECTEDENDTAG,
+ MD_ERROR_WIN_SXS_XML_E_UNCLOSEDTAG,
+ MD_ERROR_WIN_SXS_XML_E_DUPLICATEATTRIBUTE,
+ MD_ERROR_WIN_SXS_XML_E_MULTIPLEROOTS,
+ MD_ERROR_WIN_SXS_XML_E_INVALIDATROOTLEVEL,
+ MD_ERROR_WIN_SXS_XML_E_BADXMLDECL,
+ MD_ERROR_WIN_SXS_XML_E_MISSINGROOT,
+ MD_ERROR_WIN_SXS_XML_E_UNEXPECTEDEOF,
+ MD_ERROR_WIN_SXS_XML_E_BADPEREFINSUBSET,
+ MD_ERROR_WIN_SXS_XML_E_UNCLOSEDSTARTTAG,
+ MD_ERROR_WIN_SXS_XML_E_UNCLOSEDENDTAG,
+ MD_ERROR_WIN_SXS_XML_E_UNCLOSEDSTRING,
+ MD_ERROR_WIN_SXS_XML_E_UNCLOSEDCOMMENT,
+ MD_ERROR_WIN_SXS_XML_E_UNCLOSEDDECL,
+ MD_ERROR_WIN_SXS_XML_E_UNCLOSEDCDATA,
+ MD_ERROR_WIN_SXS_XML_E_RESERVEDNAMESPACE,
+ MD_ERROR_WIN_SXS_XML_E_INVALIDENCODING,
+ MD_ERROR_WIN_SXS_XML_E_INVALIDSWITCH,
+ MD_ERROR_WIN_SXS_XML_E_BADXMLCASE,
+ MD_ERROR_WIN_SXS_XML_E_INVALID_STANDALONE,
+ MD_ERROR_WIN_SXS_XML_E_UNEXPECTED_STANDALONE,
+ MD_ERROR_WIN_SXS_XML_E_INVALID_VERSION,
+ MD_ERROR_WIN_SXS_XML_E_MISSINGEQUALS,
+ MD_ERROR_WIN_SXS_PROTECTION_RECOVERY_FAILED,
+ MD_ERROR_WIN_SXS_PROTECTION_PUBLIC_KEY_TOO_SHORT,
+ MD_ERROR_WIN_SXS_PROTECTION_CATALOG_NOT_VALID,
+ MD_ERROR_WIN_SXS_UNTRANSLATABLE_HRESULT,
+ MD_ERROR_WIN_SXS_PROTECTION_CATALOG_FILE_MISSING,
+ MD_ERROR_WIN_SXS_MISSING_ASSEMBLY_IDENTITY_ATTRIBUTE,
+ MD_ERROR_WIN_SXS_INVALID_ASSEMBLY_IDENTITY_ATTRIBUTE_NAME,
+ MD_ERROR_WIN_SXS_ASSEMBLY_MISSING,
+ MD_ERROR_WIN_SXS_CORRUPT_ACTIVATION_STACK,
+ MD_ERROR_WIN_SXS_CORRUPTION,
+ MD_ERROR_WIN_SXS_EARLY_DEACTIVATION,
+ MD_ERROR_WIN_SXS_INVALID_DEACTIVATION,
+ MD_ERROR_WIN_SXS_MULTIPLE_DEACTIVATION,
+ MD_ERROR_WIN_SXS_PROCESS_TERMINATION_REQUESTED,
+ MD_ERROR_WIN_SXS_RELEASE_ACTIVATION_CONTEXT,
+ MD_ERROR_WIN_SXS_SYSTEM_DEFAULT_ACTIVATION_CONTEXT_EMPTY,
+ MD_ERROR_WIN_SXS_INVALID_IDENTITY_ATTRIBUTE_VALUE,
+ MD_ERROR_WIN_SXS_INVALID_IDENTITY_ATTRIBUTE_NAME,
+ MD_ERROR_WIN_SXS_IDENTITY_DUPLICATE_ATTRIBUTE,
+ MD_ERROR_WIN_SXS_IDENTITY_PARSE_ERROR,
+ MD_ERROR_WIN_MALFORMED_SUBSTITUTION_STRING,
+ MD_ERROR_WIN_SXS_INCORRECT_PUBLIC_KEY_TOKEN,
+ MD_ERROR_WIN_UNMAPPED_SUBSTITUTION_STRING,
+ MD_ERROR_WIN_SXS_ASSEMBLY_NOT_LOCKED,
+ MD_ERROR_WIN_SXS_COMPONENT_STORE_CORRUPT,
+ MD_ERROR_WIN_ADVANCED_INSTALLER_FAILED,
+ MD_ERROR_WIN_XML_ENCODING_MISMATCH,
+ MD_ERROR_WIN_SXS_MANIFEST_IDENTITY_SAME_BUT_CONTENTS_DIFFERENT,
+ MD_ERROR_WIN_SXS_IDENTITIES_DIFFERENT,
+ MD_ERROR_WIN_SXS_ASSEMBLY_IS_NOT_A_DEPLOYMENT,
+ MD_ERROR_WIN_SXS_FILE_NOT_PART_OF_ASSEMBLY,
+ MD_ERROR_WIN_SXS_MANIFEST_TOO_BIG,
+ MD_ERROR_WIN_SXS_SETTING_NOT_REGISTERED,
+ MD_ERROR_WIN_SXS_TRANSACTION_CLOSURE_INCOMPLETE,
+ MD_ERROR_WIN_SMI_PRIMITIVE_INSTALLER_FAILED,
+ MD_ERROR_WIN_GENERIC_COMMAND_FAILED,
+ MD_ERROR_WIN_SXS_FILE_HASH_MISSING,
+ MD_ERROR_WIN_SXS_DUPLICATE_ACTIVATABLE_CLASS,
+ MD_ERROR_WIN_EVT_INVALID_CHANNEL_PATH,
+ MD_ERROR_WIN_EVT_INVALID_QUERY,
+ MD_ERROR_WIN_EVT_PUBLISHER_METADATA_NOT_FOUND,
+ MD_ERROR_WIN_EVT_EVENT_TEMPLATE_NOT_FOUND,
+ MD_ERROR_WIN_EVT_INVALID_PUBLISHER_NAME,
+ MD_ERROR_WIN_EVT_INVALID_EVENT_DATA,
+ MD_ERROR_WIN_EVT_CHANNEL_NOT_FOUND,
+ MD_ERROR_WIN_EVT_MALFORMED_XML_TEXT,
+ MD_ERROR_WIN_EVT_SUBSCRIPTION_TO_DIRECT_CHANNEL,
+ MD_ERROR_WIN_EVT_CONFIGURATION_ERROR,
+ MD_ERROR_WIN_EVT_QUERY_RESULT_STALE,
+ MD_ERROR_WIN_EVT_QUERY_RESULT_INVALID_POSITION,
+ MD_ERROR_WIN_EVT_NON_VALIDATING_MSXML,
+ MD_ERROR_WIN_EVT_FILTER_ALREADYSCOPED,
+ MD_ERROR_WIN_EVT_FILTER_NOTELTSET,
+ MD_ERROR_WIN_EVT_FILTER_INVARG,
+ MD_ERROR_WIN_EVT_FILTER_INVTEST,
+ MD_ERROR_WIN_EVT_FILTER_INVTYPE,
+ MD_ERROR_WIN_EVT_FILTER_PARSEERR,
+ MD_ERROR_WIN_EVT_FILTER_UNSUPPORTEDOP,
+ MD_ERROR_WIN_EVT_FILTER_UNEXPECTEDTOKEN,
+ MD_ERROR_WIN_EVT_INVALID_OPERATION_OVER_ENABLED_DIRECT_CHANNEL,
+ MD_ERROR_WIN_EVT_INVALID_CHANNEL_PROPERTY_VALUE,
+ MD_ERROR_WIN_EVT_INVALID_PUBLISHER_PROPERTY_VALUE,
+ MD_ERROR_WIN_EVT_CHANNEL_CANNOT_ACTIVATE,
+ MD_ERROR_WIN_EVT_FILTER_TOO_COMPLEX,
+ MD_ERROR_WIN_EVT_MESSAGE_NOT_FOUND,
+ MD_ERROR_WIN_EVT_MESSAGE_ID_NOT_FOUND,
+ MD_ERROR_WIN_EVT_UNRESOLVED_VALUE_INSERT,
+ MD_ERROR_WIN_EVT_UNRESOLVED_PARAMETER_INSERT,
+ MD_ERROR_WIN_EVT_MAX_INSERTS_REACHED,
+ MD_ERROR_WIN_EVT_EVENT_DEFINITION_NOT_FOUND,
+ MD_ERROR_WIN_EVT_MESSAGE_LOCALE_NOT_FOUND,
+ MD_ERROR_WIN_EVT_VERSION_TOO_OLD,
+ MD_ERROR_WIN_EVT_VERSION_TOO_NEW,
+ MD_ERROR_WIN_EVT_CANNOT_OPEN_CHANNEL_OF_QUERY,
+ MD_ERROR_WIN_EVT_PUBLISHER_DISABLED,
+ MD_ERROR_WIN_EVT_FILTER_OUT_OF_RANGE,
+ MD_ERROR_WIN_EC_SUBSCRIPTION_CANNOT_ACTIVATE,
+ MD_ERROR_WIN_EC_LOG_DISABLED,
+ MD_ERROR_WIN_EC_CIRCULAR_FORWARDING,
+ MD_ERROR_WIN_EC_CREDSTORE_FULL,
+ MD_ERROR_WIN_EC_CRED_NOT_FOUND,
+ MD_ERROR_WIN_EC_NO_ACTIVE_CHANNEL,
+ MD_ERROR_WIN_MUI_FILE_NOT_FOUND,
+ MD_ERROR_WIN_MUI_INVALID_FILE,
+ MD_ERROR_WIN_MUI_INVALID_RC_CONFIG,
+ MD_ERROR_WIN_MUI_INVALID_LOCALE_NAME,
+ MD_ERROR_WIN_MUI_INVALID_ULTIMATEFALLBACK_NAME,
+ MD_ERROR_WIN_MUI_FILE_NOT_LOADED,
+ MD_ERROR_WIN_RESOURCE_ENUM_USER_STOP,
+ MD_ERROR_WIN_MUI_INTLSETTINGS_UILANG_NOT_INSTALLED,
+ MD_ERROR_WIN_MUI_INTLSETTINGS_INVALID_LOCALE_NAME,
+ MD_ERROR_WIN_MRM_RUNTIME_NO_DEFAULT_OR_NEUTRAL_RESOURCE,
+ MD_ERROR_WIN_MRM_INVALID_PRICONFIG,
+ MD_ERROR_WIN_MRM_INVALID_FILE_TYPE,
+ MD_ERROR_WIN_MRM_UNKNOWN_QUALIFIER,
+ MD_ERROR_WIN_MRM_INVALID_QUALIFIER_VALUE,
+ MD_ERROR_WIN_MRM_NO_CANDIDATE,
+ MD_ERROR_WIN_MRM_NO_MATCH_OR_DEFAULT_CANDIDATE,
+ MD_ERROR_WIN_MRM_RESOURCE_TYPE_MISMATCH,
+ MD_ERROR_WIN_MRM_DUPLICATE_MAP_NAME,
+ MD_ERROR_WIN_MRM_DUPLICATE_ENTRY,
+ MD_ERROR_WIN_MRM_INVALID_RESOURCE_IDENTIFIER,
+ MD_ERROR_WIN_MRM_FILEPATH_TOO_LONG,
+ MD_ERROR_WIN_MRM_UNSUPPORTED_DIRECTORY_TYPE,
+ MD_ERROR_WIN_MRM_INVALID_PRI_FILE,
+ MD_ERROR_WIN_MRM_NAMED_RESOURCE_NOT_FOUND,
+ MD_ERROR_WIN_MRM_MAP_NOT_FOUND,
+ MD_ERROR_WIN_MRM_UNSUPPORTED_PROFILE_TYPE,
+ MD_ERROR_WIN_MRM_INVALID_QUALIFIER_OPERATOR,
+ MD_ERROR_WIN_MRM_INDETERMINATE_QUALIFIER_VALUE,
+ MD_ERROR_WIN_MRM_AUTOMERGE_ENABLED,
+ MD_ERROR_WIN_MRM_TOO_MANY_RESOURCES,
+ MD_ERROR_WIN_MRM_UNSUPPORTED_FILE_TYPE_FOR_MERGE,
+ MD_ERROR_WIN_MRM_UNSUPPORTED_FILE_TYPE_FOR_LOAD_UNLOAD_PRI_FILE,
+ MD_ERROR_WIN_MRM_NO_CURRENT_VIEW_ON_THREAD,
+ MD_ERROR_WIN_DIFFERENT_PROFILE_RESOURCE_MANAGER_EXIST,
+ MD_ERROR_WIN_OPERATION_NOT_ALLOWED_FROM_SYSTEM_COMPONENT,
+ MD_ERROR_WIN_MRM_DIRECT_REF_TO_NON_DEFAULT_RESOURCE,
+ MD_ERROR_WIN_MRM_GENERATION_COUNT_MISMATCH,
+ MD_ERROR_WIN_PRI_MERGE_VERSION_MISMATCH,
+ MD_ERROR_WIN_PRI_MERGE_MISSING_SCHEMA,
+ MD_ERROR_WIN_PRI_MERGE_LOAD_FILE_FAILED,
+ MD_ERROR_WIN_PRI_MERGE_ADD_FILE_FAILED,
+ MD_ERROR_WIN_PRI_MERGE_WRITE_FILE_FAILED,
+ MD_ERROR_WIN_PRI_MERGE_MULTIPLE_PACKAGE_FAMILIES_NOT_ALLOWED,
+ MD_ERROR_WIN_PRI_MERGE_MULTIPLE_MAIN_PACKAGES_NOT_ALLOWED,
+ MD_ERROR_WIN_PRI_MERGE_BUNDLE_PACKAGES_NOT_ALLOWED,
+ MD_ERROR_WIN_PRI_MERGE_MAIN_PACKAGE_REQUIRED,
+ MD_ERROR_WIN_PRI_MERGE_RESOURCE_PACKAGE_REQUIRED,
+ MD_ERROR_WIN_PRI_MERGE_INVALID_FILE_NAME,
+ MD_ERROR_WIN_MRM_PACKAGE_NOT_FOUND,
+ MD_ERROR_WIN_MRM_MISSING_DEFAULT_LANGUAGE,
+ MD_ERROR_WIN_MCA_INVALID_CAPABILITIES_STRING,
+ MD_ERROR_WIN_MCA_INVALID_VCP_VERSION,
+ MD_ERROR_WIN_MCA_MONITOR_VIOLATES_MCCS_SPECIFICATION,
+ MD_ERROR_WIN_MCA_MCCS_VERSION_MISMATCH,
+ MD_ERROR_WIN_MCA_UNSUPPORTED_MCCS_VERSION,
+ MD_ERROR_WIN_MCA_INTERNAL_ERROR,
+ MD_ERROR_WIN_MCA_INVALID_TECHNOLOGY_TYPE_RETURNED,
+ MD_ERROR_WIN_MCA_UNSUPPORTED_COLOR_TEMPERATURE,
+ MD_ERROR_WIN_AMBIGUOUS_SYSTEM_DEVICE,
+ MD_ERROR_WIN_SYSTEM_DEVICE_NOT_FOUND,
+ MD_ERROR_WIN_HASH_NOT_SUPPORTED,
+ MD_ERROR_WIN_HASH_NOT_PRESENT,
+ MD_ERROR_WIN_SECONDARY_IC_PROVIDER_NOT_REGISTERED,
+ MD_ERROR_WIN_GPIO_CLIENT_INFORMATION_INVALID,
+ MD_ERROR_WIN_GPIO_VERSION_NOT_SUPPORTED,
+ MD_ERROR_WIN_GPIO_INVALID_REGISTRATION_PACKET,
+ MD_ERROR_WIN_GPIO_OPERATION_DENIED,
+ MD_ERROR_WIN_GPIO_INCOMPATIBLE_CONNECT_MODE,
+ MD_ERROR_WIN_GPIO_INTERRUPT_ALREADY_UNMASKED,
+ MD_ERROR_WIN_CANNOT_SWITCH_RUNLEVEL,
+ MD_ERROR_WIN_INVALID_RUNLEVEL_SETTING,
+ MD_ERROR_WIN_RUNLEVEL_SWITCH_TIMEOUT,
+ MD_ERROR_WIN_RUNLEVEL_SWITCH_AGENT_TIMEOUT,
+ MD_ERROR_WIN_RUNLEVEL_SWITCH_IN_PROGRESS,
+ MD_ERROR_WIN_SERVICES_FAILED_AUTOSTART,
+ MD_ERROR_WIN_COM_TASK_STOP_PENDING,
+ MD_ERROR_WIN_INSTALL_OPEN_PACKAGE_FAILED,
+ MD_ERROR_WIN_INSTALL_PACKAGE_NOT_FOUND,
+ MD_ERROR_WIN_INSTALL_INVALID_PACKAGE,
+ MD_ERROR_WIN_INSTALL_RESOLVE_DEPENDENCY_FAILED,
+ MD_ERROR_WIN_INSTALL_OUT_OF_DISK_SPACE,
+ MD_ERROR_WIN_INSTALL_NETWORK_FAILURE,
+ MD_ERROR_WIN_INSTALL_REGISTRATION_FAILURE,
+ MD_ERROR_WIN_INSTALL_DEREGISTRATION_FAILURE,
+ MD_ERROR_WIN_INSTALL_CANCEL,
+ MD_ERROR_WIN_INSTALL_FAILED,
+ MD_ERROR_WIN_REMOVE_FAILED,
+ MD_ERROR_WIN_PACKAGE_ALREADY_EXISTS,
+ MD_ERROR_WIN_NEEDS_REMEDIATION,
+ MD_ERROR_WIN_INSTALL_PREREQUISITE_FAILED,
+ MD_ERROR_WIN_PACKAGE_REPOSITORY_CORRUPTED,
+ MD_ERROR_WIN_INSTALL_POLICY_FAILURE,
+ MD_ERROR_WIN_PACKAGE_UPDATING,
+ MD_ERROR_WIN_DEPLOYMENT_BLOCKED_BY_POLICY,
+ MD_ERROR_WIN_PACKAGES_IN_USE,
+ MD_ERROR_WIN_RECOVERY_FILE_CORRUPT,
+ MD_ERROR_WIN_INVALID_STAGED_SIGNATURE,
+ MD_ERROR_WIN_DELETING_EXISTING_APPLICATIONDATA_STORE_FAILED,
+ MD_ERROR_WIN_INSTALL_PACKAGE_DOWNGRADE,
+ MD_ERROR_WIN_SYSTEM_NEEDS_REMEDIATION,
+ MD_ERROR_WIN_APPX_INTEGRITY_FAILURE_CLR_NGEN,
+ MD_ERROR_WIN_RESILIENCY_FILE_CORRUPT,
+ MD_ERROR_WIN_INSTALL_FIREWALL_SERVICE_NOT_RUNNING,
+ MD_ERROR_WIN_PACKAGE_MOVE_FAILED,
+ MD_ERROR_WIN_INSTALL_VOLUME_NOT_EMPTY,
+ MD_ERROR_WIN_INSTALL_VOLUME_OFFLINE,
+ MD_ERROR_WIN_INSTALL_VOLUME_CORRUPT,
+ MD_ERROR_WIN_NEEDS_REGISTRATION,
+ MD_ERROR_WIN_INSTALL_WRONG_PROCESSOR_ARCHITECTURE,
+ MD_ERROR_WIN_DEV_SIDELOAD_LIMIT_EXCEEDED,
+ MD_ERROR_WIN_INSTALL_OPTIONAL_PACKAGE_REQUIRES_MAIN_PACKAGE,
+ MD_ERROR_WIN_PACKAGE_NOT_SUPPORTED_ON_FILESYSTEM,
+ MD_ERROR_WIN_PACKAGE_MOVE_BLOCKED_BY_STREAMING,
+ MD_ERROR_WIN_INSTALL_OPTIONAL_PACKAGE_APPLICATIONID_NOT_UNIQUE,
+ MD_ERROR_WIN_PACKAGE_STAGING_ONHOLD,
+ MD_ERROR_WIN_INSTALL_INVALID_RELATED_SET_UPDATE,
+ MD_ERROR_WIN_INSTALL_OPTIONAL_PACKAGE_REQUIRES_MAIN_PACKAGE_FULLTRUST_CAPABILITY,
+ MD_ERROR_WIN_DEPLOYMENT_BLOCKED_BY_USER_LOG_OFF,
+ MD_ERROR_WIN_PROVISION_OPTIONAL_PACKAGE_REQUIRES_MAIN_PACKAGE_PROVISIONED,
+ MD_ERROR_WIN_PACKAGES_REPUTATION_CHECK_FAILED,
+ MD_ERROR_WIN_PACKAGES_REPUTATION_CHECK_TIMEDOUT,
+ MD_ERROR_WIN_DEPLOYMENT_OPTION_NOT_SUPPORTED,
+ MD_ERROR_WIN_APPINSTALLER_ACTIVATION_BLOCKED,
+ MD_ERROR_WIN_REGISTRATION_FROM_REMOTE_DRIVE_NOT_SUPPORTED,
+ MD_ERROR_WIN_APPX_RAW_DATA_WRITE_FAILED,
+ MD_ERROR_WIN_DEPLOYMENT_BLOCKED_BY_VOLUME_POLICY_PACKAGE,
+ MD_ERROR_WIN_DEPLOYMENT_BLOCKED_BY_VOLUME_POLICY_MACHINE,
+ MD_ERROR_WIN_DEPLOYMENT_BLOCKED_BY_PROFILE_POLICY,
+ MD_ERROR_WIN_DEPLOYMENT_FAILED_CONFLICTING_MUTABLE_PACKAGE_DIRECTORY,
+ MD_ERROR_WIN_SINGLETON_RESOURCE_INSTALLED_IN_ACTIVE_USER,
+ MD_ERROR_WIN_DIFFERENT_VERSION_OF_PACKAGED_SERVICE_INSTALLED,
+ MD_ERROR_WIN_SERVICE_EXISTS_AS_NON_PACKAGED_SERVICE,
+ MD_ERROR_WIN_PACKAGED_SERVICE_REQUIRES_ADMIN_PRIVILEGES,
+ MD_ERROR_WIN_REDIRECTION_TO_DEFAULT_ACCOUNT_NOT_ALLOWED,
+ MD_ERROR_WIN_PACKAGE_LACKS_CAPABILITY_TO_DEPLOY_ON_HOST,
+ MD_ERROR_WIN_UNSIGNED_PACKAGE_INVALID_CONTENT,
+ MD_ERROR_WIN_UNSIGNED_PACKAGE_INVALID_PUBLISHER_NAMESPACE,
+ MD_ERROR_WIN_SIGNED_PACKAGE_INVALID_PUBLISHER_NAMESPACE,
+ MD_ERROR_WIN_PACKAGE_EXTERNAL_LOCATION_NOT_ALLOWED,
+ MD_ERROR_WIN_INSTALL_FULLTRUST_HOSTRUNTIME_REQUIRES_MAIN_PACKAGE_FULLTRUST_CAPABILITY,
+ MD_ERROR_WIN_STATE_LOAD_STORE_FAILED,
+ MD_ERROR_WIN_STATE_GET_VERSION_FAILED,
+ MD_ERROR_WIN_STATE_SET_VERSION_FAILED,
+ MD_ERROR_WIN_STATE_STRUCTURED_RESET_FAILED,
+ MD_ERROR_WIN_STATE_OPEN_CONTAINER_FAILED,
+ MD_ERROR_WIN_STATE_CREATE_CONTAINER_FAILED,
+ MD_ERROR_WIN_STATE_DELETE_CONTAINER_FAILED,
+ MD_ERROR_WIN_STATE_READ_SETTING_FAILED,
+ MD_ERROR_WIN_STATE_WRITE_SETTING_FAILED,
+ MD_ERROR_WIN_STATE_DELETE_SETTING_FAILED,
+ MD_ERROR_WIN_STATE_QUERY_SETTING_FAILED,
+ MD_ERROR_WIN_STATE_READ_COMPOSITE_SETTING_FAILED,
+ MD_ERROR_WIN_STATE_WRITE_COMPOSITE_SETTING_FAILED,
+ MD_ERROR_WIN_STATE_ENUMERATE_CONTAINER_FAILED,
+ MD_ERROR_WIN_STATE_ENUMERATE_SETTINGS_FAILED,
+ MD_ERROR_WIN_STATE_COMPOSITE_SETTING_VALUE_SIZE_LIMIT_EXCEEDED,
+ MD_ERROR_WIN_STATE_SETTING_VALUE_SIZE_LIMIT_EXCEEDED,
+ MD_ERROR_WIN_STATE_SETTING_NAME_SIZE_LIMIT_EXCEEDED,
+ MD_ERROR_WIN_STATE_CONTAINER_NAME_SIZE_LIMIT_EXCEEDED,
+ MD_ERROR_WIN_API_UNAVAILABLE,
+};
+
+// The content of this array was created from winerror.h in the 10 SDK
+// (version 10.0.19041.0) with the following script:
+//
+// egrep -o '#define ERROR_[A-Z_0-9]+\s+[0-9]+L' winerror.h
+// | tr -d '\r'
+// | sed -r 's@#define (ERROR_[A-Z_0-9]+)\s+([0-9]+)L@\2 \1@'
+// | sort -n | sed -r 's@([0-9]+) ([A-Z_0-9]+)@ "\2",@'
+static const char* kWinErrorStrings[] = {
+ "ERROR_SUCCESS",
+ "ERROR_INVALID_FUNCTION",
+ "ERROR_FILE_NOT_FOUND",
+ "ERROR_PATH_NOT_FOUND",
+ "ERROR_TOO_MANY_OPEN_FILES",
+ "ERROR_ACCESS_DENIED",
+ "ERROR_INVALID_HANDLE",
+ "ERROR_ARENA_TRASHED",
+ "ERROR_NOT_ENOUGH_MEMORY",
+ "ERROR_INVALID_BLOCK",
+ "ERROR_BAD_ENVIRONMENT",
+ "ERROR_BAD_FORMAT",
+ "ERROR_INVALID_ACCESS",
+ "ERROR_INVALID_DATA",
+ "ERROR_OUTOFMEMORY",
+ "ERROR_INVALID_DRIVE",
+ "ERROR_CURRENT_DIRECTORY",
+ "ERROR_NOT_SAME_DEVICE",
+ "ERROR_NO_MORE_FILES",
+ "ERROR_WRITE_PROTECT",
+ "ERROR_BAD_UNIT",
+ "ERROR_NOT_READY",
+ "ERROR_BAD_COMMAND",
+ "ERROR_CRC",
+ "ERROR_BAD_LENGTH",
+ "ERROR_SEEK",
+ "ERROR_NOT_DOS_DISK",
+ "ERROR_SECTOR_NOT_FOUND",
+ "ERROR_OUT_OF_PAPER",
+ "ERROR_WRITE_FAULT",
+ "ERROR_READ_FAULT",
+ "ERROR_GEN_FAILURE",
+ "ERROR_SHARING_VIOLATION",
+ "ERROR_LOCK_VIOLATION",
+ "ERROR_WRONG_DISK",
+ "ERROR_SHARING_BUFFER_EXCEEDED",
+ "ERROR_HANDLE_EOF",
+ "ERROR_HANDLE_DISK_FULL",
+ "ERROR_NOT_SUPPORTED",
+ "ERROR_REM_NOT_LIST",
+ "ERROR_DUP_NAME",
+ "ERROR_BAD_NETPATH",
+ "ERROR_NETWORK_BUSY",
+ "ERROR_DEV_NOT_EXIST",
+ "ERROR_TOO_MANY_CMDS",
+ "ERROR_ADAP_HDW_ERR",
+ "ERROR_BAD_NET_RESP",
+ "ERROR_UNEXP_NET_ERR",
+ "ERROR_BAD_REM_ADAP",
+ "ERROR_PRINTQ_FULL",
+ "ERROR_NO_SPOOL_SPACE",
+ "ERROR_PRINT_CANCELLED",
+ "ERROR_NETNAME_DELETED",
+ "ERROR_NETWORK_ACCESS_DENIED",
+ "ERROR_BAD_DEV_TYPE",
+ "ERROR_BAD_NET_NAME",
+ "ERROR_TOO_MANY_NAMES",
+ "ERROR_TOO_MANY_SESS",
+ "ERROR_SHARING_PAUSED",
+ "ERROR_REQ_NOT_ACCEP",
+ "ERROR_REDIR_PAUSED",
+ "ERROR_FILE_EXISTS",
+ "ERROR_CANNOT_MAKE",
+ "ERROR_FAIL_I24",
+ "ERROR_OUT_OF_STRUCTURES",
+ "ERROR_ALREADY_ASSIGNED",
+ "ERROR_INVALID_PASSWORD",
+ "ERROR_INVALID_PARAMETER",
+ "ERROR_NET_WRITE_FAULT",
+ "ERROR_NO_PROC_SLOTS",
+ "ERROR_TOO_MANY_SEMAPHORES",
+ "ERROR_EXCL_SEM_ALREADY_OWNED",
+ "ERROR_SEM_IS_SET",
+ "ERROR_TOO_MANY_SEM_REQUESTS",
+ "ERROR_INVALID_AT_INTERRUPT_TIME",
+ "ERROR_SEM_OWNER_DIED",
+ "ERROR_SEM_USER_LIMIT",
+ "ERROR_DISK_CHANGE",
+ "ERROR_DRIVE_LOCKED",
+ "ERROR_BROKEN_PIPE",
+ "ERROR_OPEN_FAILED",
+ "ERROR_BUFFER_OVERFLOW",
+ "ERROR_DISK_FULL",
+ "ERROR_NO_MORE_SEARCH_HANDLES",
+ "ERROR_INVALID_TARGET_HANDLE",
+ "ERROR_INVALID_CATEGORY",
+ "ERROR_INVALID_VERIFY_SWITCH",
+ "ERROR_BAD_DRIVER_LEVEL",
+ "ERROR_CALL_NOT_IMPLEMENTED",
+ "ERROR_SEM_TIMEOUT",
+ "ERROR_INSUFFICIENT_BUFFER",
+ "ERROR_INVALID_NAME",
+ "ERROR_INVALID_LEVEL",
+ "ERROR_NO_VOLUME_LABEL",
+ "ERROR_MOD_NOT_FOUND",
+ "ERROR_PROC_NOT_FOUND",
+ "ERROR_WAIT_NO_CHILDREN",
+ "ERROR_CHILD_NOT_COMPLETE",
+ "ERROR_DIRECT_ACCESS_HANDLE",
+ "ERROR_NEGATIVE_SEEK",
+ "ERROR_SEEK_ON_DEVICE",
+ "ERROR_IS_JOIN_TARGET",
+ "ERROR_IS_JOINED",
+ "ERROR_IS_SUBSTED",
+ "ERROR_NOT_JOINED",
+ "ERROR_NOT_SUBSTED",
+ "ERROR_JOIN_TO_JOIN",
+ "ERROR_SUBST_TO_SUBST",
+ "ERROR_JOIN_TO_SUBST",
+ "ERROR_SUBST_TO_JOIN",
+ "ERROR_BUSY_DRIVE",
+ "ERROR_SAME_DRIVE",
+ "ERROR_DIR_NOT_ROOT",
+ "ERROR_DIR_NOT_EMPTY",
+ "ERROR_IS_SUBST_PATH",
+ "ERROR_IS_JOIN_PATH",
+ "ERROR_PATH_BUSY",
+ "ERROR_IS_SUBST_TARGET",
+ "ERROR_SYSTEM_TRACE",
+ "ERROR_INVALID_EVENT_COUNT",
+ "ERROR_TOO_MANY_MUXWAITERS",
+ "ERROR_INVALID_LIST_FORMAT",
+ "ERROR_LABEL_TOO_LONG",
+ "ERROR_TOO_MANY_TCBS",
+ "ERROR_SIGNAL_REFUSED",
+ "ERROR_DISCARDED",
+ "ERROR_NOT_LOCKED",
+ "ERROR_BAD_THREADID_ADDR",
+ "ERROR_BAD_ARGUMENTS",
+ "ERROR_BAD_PATHNAME",
+ "ERROR_SIGNAL_PENDING",
+ "ERROR_MAX_THRDS_REACHED",
+ "ERROR_LOCK_FAILED",
+ "ERROR_BUSY",
+ "ERROR_DEVICE_SUPPORT_IN_PROGRESS",
+ "ERROR_CANCEL_VIOLATION",
+ "ERROR_ATOMIC_LOCKS_NOT_SUPPORTED",
+ "ERROR_INVALID_SEGMENT_NUMBER",
+ "ERROR_INVALID_ORDINAL",
+ "ERROR_ALREADY_EXISTS",
+ "ERROR_INVALID_FLAG_NUMBER",
+ "ERROR_SEM_NOT_FOUND",
+ "ERROR_INVALID_STARTING_CODESEG",
+ "ERROR_INVALID_STACKSEG",
+ "ERROR_INVALID_MODULETYPE",
+ "ERROR_INVALID_EXE_SIGNATURE",
+ "ERROR_EXE_MARKED_INVALID",
+ "ERROR_BAD_EXE_FORMAT",
+ "ERROR_INVALID_MINALLOCSIZE",
+ "ERROR_DYNLINK_FROM_INVALID_RING",
+ "ERROR_IOPL_NOT_ENABLED",
+ "ERROR_INVALID_SEGDPL",
+ "ERROR_RING2SEG_MUST_BE_MOVABLE",
+ "ERROR_RELOC_CHAIN_XEEDS_SEGLIM",
+ "ERROR_INFLOOP_IN_RELOC_CHAIN",
+ "ERROR_ENVVAR_NOT_FOUND",
+ "ERROR_NO_SIGNAL_SENT",
+ "ERROR_FILENAME_EXCED_RANGE",
+ "ERROR_RING2_STACK_IN_USE",
+ "ERROR_META_EXPANSION_TOO_LONG",
+ "ERROR_INVALID_SIGNAL_NUMBER",
+ "ERROR_THREAD_1_INACTIVE",
+ "ERROR_LOCKED",
+ "ERROR_TOO_MANY_MODULES",
+ "ERROR_NESTING_NOT_ALLOWED",
+ "ERROR_EXE_MACHINE_TYPE_MISMATCH",
+ "ERROR_EXE_CANNOT_MODIFY_SIGNED_BINARY",
+ "ERROR_EXE_CANNOT_MODIFY_STRONG_SIGNED_BINARY",
+ "ERROR_FILE_CHECKED_OUT",
+ "ERROR_CHECKOUT_REQUIRED",
+ "ERROR_BAD_FILE_TYPE",
+ "ERROR_FILE_TOO_LARGE",
+ "ERROR_FORMS_AUTH_REQUIRED",
+ "ERROR_VIRUS_INFECTED",
+ "ERROR_VIRUS_DELETED",
+ "ERROR_PIPE_LOCAL",
+ "ERROR_BAD_PIPE",
+ "ERROR_PIPE_BUSY",
+ "ERROR_NO_DATA",
+ "ERROR_PIPE_NOT_CONNECTED",
+ "ERROR_MORE_DATA",
+ "ERROR_NO_WORK_DONE",
+ "ERROR_VC_DISCONNECTED",
+ "ERROR_INVALID_EA_NAME",
+ "ERROR_EA_LIST_INCONSISTENT",
+ "ERROR_NO_MORE_ITEMS",
+ "ERROR_CANNOT_COPY",
+ "ERROR_DIRECTORY",
+ "ERROR_EAS_DIDNT_FIT",
+ "ERROR_EA_FILE_CORRUPT",
+ "ERROR_EA_TABLE_FULL",
+ "ERROR_INVALID_EA_HANDLE",
+ "ERROR_EAS_NOT_SUPPORTED",
+ "ERROR_NOT_OWNER",
+ "ERROR_TOO_MANY_POSTS",
+ "ERROR_PARTIAL_COPY",
+ "ERROR_OPLOCK_NOT_GRANTED",
+ "ERROR_INVALID_OPLOCK_PROTOCOL",
+ "ERROR_DISK_TOO_FRAGMENTED",
+ "ERROR_DELETE_PENDING",
+ "ERROR_INCOMPATIBLE_WITH_GLOBAL_SHORT_NAME_REGISTRY_SETTING",
+ "ERROR_SHORT_NAMES_NOT_ENABLED_ON_VOLUME",
+ "ERROR_SECURITY_STREAM_IS_INCONSISTENT",
+ "ERROR_INVALID_LOCK_RANGE",
+ "ERROR_IMAGE_SUBSYSTEM_NOT_PRESENT",
+ "ERROR_NOTIFICATION_GUID_ALREADY_DEFINED",
+ "ERROR_INVALID_EXCEPTION_HANDLER",
+ "ERROR_DUPLICATE_PRIVILEGES",
+ "ERROR_NO_RANGES_PROCESSED",
+ "ERROR_NOT_ALLOWED_ON_SYSTEM_FILE",
+ "ERROR_DISK_RESOURCES_EXHAUSTED",
+ "ERROR_INVALID_TOKEN",
+ "ERROR_DEVICE_FEATURE_NOT_SUPPORTED",
+ "ERROR_MR_MID_NOT_FOUND",
+ "ERROR_SCOPE_NOT_FOUND",
+ "ERROR_UNDEFINED_SCOPE",
+ "ERROR_INVALID_CAP",
+ "ERROR_DEVICE_UNREACHABLE",
+ "ERROR_DEVICE_NO_RESOURCES",
+ "ERROR_DATA_CHECKSUM_ERROR",
+ "ERROR_INTERMIXED_KERNEL_EA_OPERATION",
+ "ERROR_FILE_LEVEL_TRIM_NOT_SUPPORTED",
+ "ERROR_OFFSET_ALIGNMENT_VIOLATION",
+ "ERROR_INVALID_FIELD_IN_PARAMETER_LIST",
+ "ERROR_OPERATION_IN_PROGRESS",
+ "ERROR_BAD_DEVICE_PATH",
+ "ERROR_TOO_MANY_DESCRIPTORS",
+ "ERROR_SCRUB_DATA_DISABLED",
+ "ERROR_NOT_REDUNDANT_STORAGE",
+ "ERROR_RESIDENT_FILE_NOT_SUPPORTED",
+ "ERROR_COMPRESSED_FILE_NOT_SUPPORTED",
+ "ERROR_DIRECTORY_NOT_SUPPORTED",
+ "ERROR_NOT_READ_FROM_COPY",
+ "ERROR_FT_WRITE_FAILURE",
+ "ERROR_FT_DI_SCAN_REQUIRED",
+ "ERROR_INVALID_KERNEL_INFO_VERSION",
+ "ERROR_INVALID_PEP_INFO_VERSION",
+ "ERROR_OBJECT_NOT_EXTERNALLY_BACKED",
+ "ERROR_EXTERNAL_BACKING_PROVIDER_UNKNOWN",
+ "ERROR_COMPRESSION_NOT_BENEFICIAL",
+ "ERROR_STORAGE_TOPOLOGY_ID_MISMATCH",
+ "ERROR_BLOCKED_BY_PARENTAL_CONTROLS",
+ "ERROR_BLOCK_TOO_MANY_REFERENCES",
+ "ERROR_MARKED_TO_DISALLOW_WRITES",
+ "ERROR_ENCLAVE_FAILURE",
+ "ERROR_FAIL_NOACTION_REBOOT",
+ "ERROR_FAIL_SHUTDOWN",
+ "ERROR_FAIL_RESTART",
+ "ERROR_MAX_SESSIONS_REACHED",
+ "ERROR_NETWORK_ACCESS_DENIED_EDP",
+ "ERROR_DEVICE_HINT_NAME_BUFFER_TOO_SMALL",
+ "ERROR_EDP_POLICY_DENIES_OPERATION",
+ "ERROR_EDP_DPL_POLICY_CANT_BE_SATISFIED",
+ "ERROR_CLOUD_FILE_SYNC_ROOT_METADATA_CORRUPT",
+ "ERROR_DEVICE_IN_MAINTENANCE",
+ "ERROR_NOT_SUPPORTED_ON_DAX",
+ "ERROR_DAX_MAPPING_EXISTS",
+ "ERROR_CLOUD_FILE_PROVIDER_NOT_RUNNING",
+ "ERROR_CLOUD_FILE_METADATA_CORRUPT",
+ "ERROR_CLOUD_FILE_METADATA_TOO_LARGE",
+ "ERROR_CLOUD_FILE_PROPERTY_BLOB_TOO_LARGE",
+ "ERROR_CLOUD_FILE_PROPERTY_BLOB_CHECKSUM_MISMATCH",
+ "ERROR_CHILD_PROCESS_BLOCKED",
+ "ERROR_STORAGE_LOST_DATA_PERSISTENCE",
+ "ERROR_FILE_SYSTEM_VIRTUALIZATION_UNAVAILABLE",
+ "ERROR_FILE_SYSTEM_VIRTUALIZATION_METADATA_CORRUPT",
+ "ERROR_FILE_SYSTEM_VIRTUALIZATION_BUSY",
+ "ERROR_FILE_SYSTEM_VIRTUALIZATION_PROVIDER_UNKNOWN",
+ "ERROR_GDI_HANDLE_LEAK",
+ "ERROR_CLOUD_FILE_TOO_MANY_PROPERTY_BLOBS",
+ "ERROR_CLOUD_FILE_PROPERTY_VERSION_NOT_SUPPORTED",
+ "ERROR_NOT_A_CLOUD_FILE",
+ "ERROR_CLOUD_FILE_NOT_IN_SYNC",
+ "ERROR_CLOUD_FILE_ALREADY_CONNECTED",
+ "ERROR_CLOUD_FILE_NOT_SUPPORTED",
+ "ERROR_CLOUD_FILE_INVALID_REQUEST",
+ "ERROR_CLOUD_FILE_READ_ONLY_VOLUME",
+ "ERROR_CLOUD_FILE_CONNECTED_PROVIDER_ONLY",
+ "ERROR_CLOUD_FILE_VALIDATION_FAILED",
+ "ERROR_SMB1_NOT_AVAILABLE",
+ "ERROR_FILE_SYSTEM_VIRTUALIZATION_INVALID_OPERATION",
+ "ERROR_CLOUD_FILE_AUTHENTICATION_FAILED",
+ "ERROR_CLOUD_FILE_INSUFFICIENT_RESOURCES",
+ "ERROR_CLOUD_FILE_NETWORK_UNAVAILABLE",
+ "ERROR_CLOUD_FILE_UNSUCCESSFUL",
+ "ERROR_CLOUD_FILE_NOT_UNDER_SYNC_ROOT",
+ "ERROR_CLOUD_FILE_IN_USE",
+ "ERROR_CLOUD_FILE_PINNED",
+ "ERROR_CLOUD_FILE_REQUEST_ABORTED",
+ "ERROR_CLOUD_FILE_PROPERTY_CORRUPT",
+ "ERROR_CLOUD_FILE_ACCESS_DENIED",
+ "ERROR_CLOUD_FILE_INCOMPATIBLE_HARDLINKS",
+ "ERROR_CLOUD_FILE_PROPERTY_LOCK_CONFLICT",
+ "ERROR_CLOUD_FILE_REQUEST_CANCELED",
+ "ERROR_EXTERNAL_SYSKEY_NOT_SUPPORTED",
+ "ERROR_THREAD_MODE_ALREADY_BACKGROUND",
+ "ERROR_THREAD_MODE_NOT_BACKGROUND",
+ "ERROR_PROCESS_MODE_ALREADY_BACKGROUND",
+ "ERROR_PROCESS_MODE_NOT_BACKGROUND",
+ "ERROR_CLOUD_FILE_PROVIDER_TERMINATED",
+ "ERROR_NOT_A_CLOUD_SYNC_ROOT",
+ "ERROR_FILE_PROTECTED_UNDER_DPL",
+ "ERROR_VOLUME_NOT_CLUSTER_ALIGNED",
+ "ERROR_NO_PHYSICALLY_ALIGNED_FREE_SPACE_FOUND",
+ "ERROR_APPX_FILE_NOT_ENCRYPTED",
+ "ERROR_RWRAW_ENCRYPTED_FILE_NOT_ENCRYPTED",
+ "ERROR_RWRAW_ENCRYPTED_INVALID_EDATAINFO_FILEOFFSET",
+ "ERROR_RWRAW_ENCRYPTED_INVALID_EDATAINFO_FILERANGE",
+ "ERROR_RWRAW_ENCRYPTED_INVALID_EDATAINFO_PARAMETER",
+ "ERROR_LINUX_SUBSYSTEM_NOT_PRESENT",
+ "ERROR_FT_READ_FAILURE",
+ "ERROR_STORAGE_RESERVE_ID_INVALID",
+ "ERROR_STORAGE_RESERVE_DOES_NOT_EXIST",
+ "ERROR_STORAGE_RESERVE_ALREADY_EXISTS",
+ "ERROR_STORAGE_RESERVE_NOT_EMPTY",
+ "ERROR_NOT_A_DAX_VOLUME",
+ "ERROR_NOT_DAX_MAPPABLE",
+ "ERROR_TIME_SENSITIVE_THREAD",
+ "ERROR_DPL_NOT_SUPPORTED_FOR_USER",
+ "ERROR_CASE_DIFFERING_NAMES_IN_DIR",
+ "ERROR_FILE_NOT_SUPPORTED",
+ "ERROR_CLOUD_FILE_REQUEST_TIMEOUT",
+ "ERROR_NO_TASK_QUEUE",
+ "ERROR_SRC_SRV_DLL_LOAD_FAILED",
+ "ERROR_NOT_SUPPORTED_WITH_BTT",
+ "ERROR_ENCRYPTION_DISABLED",
+ "ERROR_ENCRYPTING_METADATA_DISALLOWED",
+ "ERROR_CANT_CLEAR_ENCRYPTION_FLAG",
+ "ERROR_NO_SUCH_DEVICE",
+ "ERROR_CLOUD_FILE_DEHYDRATION_DISALLOWED",
+ "ERROR_FILE_SNAP_IN_PROGRESS",
+ "ERROR_FILE_SNAP_USER_SECTION_NOT_SUPPORTED",
+ "ERROR_FILE_SNAP_MODIFY_NOT_SUPPORTED",
+ "ERROR_FILE_SNAP_IO_NOT_COORDINATED",
+ "ERROR_FILE_SNAP_UNEXPECTED_ERROR",
+ "ERROR_FILE_SNAP_INVALID_PARAMETER",
+ "ERROR_UNSATISFIED_DEPENDENCIES",
+ "ERROR_CASE_SENSITIVE_PATH",
+ "ERROR_UNEXPECTED_NTCACHEMANAGER_ERROR",
+ "ERROR_LINUX_SUBSYSTEM_UPDATE_REQUIRED",
+ "ERROR_DLP_POLICY_WARNS_AGAINST_OPERATION",
+ "ERROR_DLP_POLICY_DENIES_OPERATION",
+ "ERROR_DLP_POLICY_SILENTLY_FAIL",
+ "ERROR_CAPAUTHZ_NOT_DEVUNLOCKED",
+ "ERROR_CAPAUTHZ_CHANGE_TYPE",
+ "ERROR_CAPAUTHZ_NOT_PROVISIONED",
+ "ERROR_CAPAUTHZ_NOT_AUTHORIZED",
+ "ERROR_CAPAUTHZ_NO_POLICY",
+ "ERROR_CAPAUTHZ_DB_CORRUPTED",
+ "ERROR_CAPAUTHZ_SCCD_INVALID_CATALOG",
+ "ERROR_CAPAUTHZ_SCCD_NO_AUTH_ENTITY",
+ "ERROR_CAPAUTHZ_SCCD_PARSE_ERROR",
+ "ERROR_CAPAUTHZ_SCCD_DEV_MODE_REQUIRED",
+ "ERROR_CAPAUTHZ_SCCD_NO_CAPABILITY_MATCH",
+ "ERROR_CIMFS_IMAGE_CORRUPT",
+ "ERROR_PNP_QUERY_REMOVE_DEVICE_TIMEOUT",
+ "ERROR_PNP_QUERY_REMOVE_RELATED_DEVICE_TIMEOUT",
+ "ERROR_PNP_QUERY_REMOVE_UNRELATED_DEVICE_TIMEOUT",
+ "ERROR_DEVICE_HARDWARE_ERROR",
+ "ERROR_INVALID_ADDRESS",
+ "ERROR_HAS_SYSTEM_CRITICAL_FILES",
+ "ERROR_USER_PROFILE_LOAD",
+ "ERROR_ARITHMETIC_OVERFLOW",
+ "ERROR_PIPE_CONNECTED",
+ "ERROR_PIPE_LISTENING",
+ "ERROR_VERIFIER_STOP",
+ "ERROR_ABIOS_ERROR",
+ "ERROR_WX86_WARNING",
+ "ERROR_WX86_ERROR",
+ "ERROR_TIMER_NOT_CANCELED",
+ "ERROR_UNWIND",
+ "ERROR_BAD_STACK",
+ "ERROR_INVALID_UNWIND_TARGET",
+ "ERROR_INVALID_PORT_ATTRIBUTES",
+ "ERROR_PORT_MESSAGE_TOO_LONG",
+ "ERROR_INVALID_QUOTA_LOWER",
+ "ERROR_DEVICE_ALREADY_ATTACHED",
+ "ERROR_INSTRUCTION_MISALIGNMENT",
+ "ERROR_PROFILING_NOT_STARTED",
+ "ERROR_PROFILING_NOT_STOPPED",
+ "ERROR_COULD_NOT_INTERPRET",
+ "ERROR_PROFILING_AT_LIMIT",
+ "ERROR_CANT_WAIT",
+ "ERROR_CANT_TERMINATE_SELF",
+ "ERROR_UNEXPECTED_MM_CREATE_ERR",
+ "ERROR_UNEXPECTED_MM_MAP_ERROR",
+ "ERROR_UNEXPECTED_MM_EXTEND_ERR",
+ "ERROR_BAD_FUNCTION_TABLE",
+ "ERROR_NO_GUID_TRANSLATION",
+ "ERROR_INVALID_LDT_SIZE",
+ "ERROR_INVALID_LDT_OFFSET",
+ "ERROR_INVALID_LDT_DESCRIPTOR",
+ "ERROR_TOO_MANY_THREADS",
+ "ERROR_THREAD_NOT_IN_PROCESS",
+ "ERROR_PAGEFILE_QUOTA_EXCEEDED",
+ "ERROR_LOGON_SERVER_CONFLICT",
+ "ERROR_SYNCHRONIZATION_REQUIRED",
+ "ERROR_NET_OPEN_FAILED",
+ "ERROR_IO_PRIVILEGE_FAILED",
+ "ERROR_CONTROL_C_EXIT",
+ "ERROR_MISSING_SYSTEMFILE",
+ "ERROR_UNHANDLED_EXCEPTION",
+ "ERROR_APP_INIT_FAILURE",
+ "ERROR_PAGEFILE_CREATE_FAILED",
+ "ERROR_INVALID_IMAGE_HASH",
+ "ERROR_NO_PAGEFILE",
+ "ERROR_ILLEGAL_FLOAT_CONTEXT",
+ "ERROR_NO_EVENT_PAIR",
+ "ERROR_DOMAIN_CTRLR_CONFIG_ERROR",
+ "ERROR_ILLEGAL_CHARACTER",
+ "ERROR_UNDEFINED_CHARACTER",
+ "ERROR_FLOPPY_VOLUME",
+ "ERROR_BIOS_FAILED_TO_CONNECT_INTERRUPT",
+ "ERROR_BACKUP_CONTROLLER",
+ "ERROR_MUTANT_LIMIT_EXCEEDED",
+ "ERROR_FS_DRIVER_REQUIRED",
+ "ERROR_CANNOT_LOAD_REGISTRY_FILE",
+ "ERROR_DEBUG_ATTACH_FAILED",
+ "ERROR_SYSTEM_PROCESS_TERMINATED",
+ "ERROR_DATA_NOT_ACCEPTED",
+ "ERROR_VDM_HARD_ERROR",
+ "ERROR_DRIVER_CANCEL_TIMEOUT",
+ "ERROR_REPLY_MESSAGE_MISMATCH",
+ "ERROR_LOST_WRITEBEHIND_DATA",
+ "ERROR_CLIENT_SERVER_PARAMETERS_INVALID",
+ "ERROR_NOT_TINY_STREAM",
+ "ERROR_STACK_OVERFLOW_READ",
+ "ERROR_CONVERT_TO_LARGE",
+ "ERROR_FOUND_OUT_OF_SCOPE",
+ "ERROR_ALLOCATE_BUCKET",
+ "ERROR_MARSHALL_OVERFLOW",
+ "ERROR_INVALID_VARIANT",
+ "ERROR_BAD_COMPRESSION_BUFFER",
+ "ERROR_AUDIT_FAILED",
+ "ERROR_TIMER_RESOLUTION_NOT_SET",
+ "ERROR_INSUFFICIENT_LOGON_INFO",
+ "ERROR_BAD_DLL_ENTRYPOINT",
+ "ERROR_BAD_SERVICE_ENTRYPOINT",
+ "ERROR_IP_ADDRESS_CONFLICT1",
+ "ERROR_IP_ADDRESS_CONFLICT2",
+ "ERROR_REGISTRY_QUOTA_LIMIT",
+ "ERROR_NO_CALLBACK_ACTIVE",
+ "ERROR_PWD_TOO_SHORT",
+ "ERROR_PWD_TOO_RECENT",
+ "ERROR_PWD_HISTORY_CONFLICT",
+ "ERROR_UNSUPPORTED_COMPRESSION",
+ "ERROR_INVALID_HW_PROFILE",
+ "ERROR_INVALID_PLUGPLAY_DEVICE_PATH",
+ "ERROR_QUOTA_LIST_INCONSISTENT",
+ "ERROR_EVALUATION_EXPIRATION",
+ "ERROR_ILLEGAL_DLL_RELOCATION",
+ "ERROR_DLL_INIT_FAILED_LOGOFF",
+ "ERROR_VALIDATE_CONTINUE",
+ "ERROR_NO_MORE_MATCHES",
+ "ERROR_RANGE_LIST_CONFLICT",
+ "ERROR_SERVER_SID_MISMATCH",
+ "ERROR_CANT_ENABLE_DENY_ONLY",
+ "ERROR_FLOAT_MULTIPLE_FAULTS",
+ "ERROR_FLOAT_MULTIPLE_TRAPS",
+ "ERROR_NOINTERFACE",
+ "ERROR_DRIVER_FAILED_SLEEP",
+ "ERROR_CORRUPT_SYSTEM_FILE",
+ "ERROR_COMMITMENT_MINIMUM",
+ "ERROR_PNP_RESTART_ENUMERATION",
+ "ERROR_SYSTEM_IMAGE_BAD_SIGNATURE",
+ "ERROR_PNP_REBOOT_REQUIRED",
+ "ERROR_INSUFFICIENT_POWER",
+ "ERROR_MULTIPLE_FAULT_VIOLATION",
+ "ERROR_SYSTEM_SHUTDOWN",
+ "ERROR_PORT_NOT_SET",
+ "ERROR_DS_VERSION_CHECK_FAILURE",
+ "ERROR_RANGE_NOT_FOUND",
+ "ERROR_NOT_SAFE_MODE_DRIVER",
+ "ERROR_FAILED_DRIVER_ENTRY",
+ "ERROR_DEVICE_ENUMERATION_ERROR",
+ "ERROR_MOUNT_POINT_NOT_RESOLVED",
+ "ERROR_INVALID_DEVICE_OBJECT_PARAMETER",
+ "ERROR_MCA_OCCURED",
+ "ERROR_DRIVER_DATABASE_ERROR",
+ "ERROR_SYSTEM_HIVE_TOO_LARGE",
+ "ERROR_DRIVER_FAILED_PRIOR_UNLOAD",
+ "ERROR_VOLSNAP_PREPARE_HIBERNATE",
+ "ERROR_HIBERNATION_FAILURE",
+ "ERROR_PWD_TOO_LONG",
+ "ERROR_FILE_SYSTEM_LIMITATION",
+ "ERROR_ASSERTION_FAILURE",
+ "ERROR_ACPI_ERROR",
+ "ERROR_WOW_ASSERTION",
+ "ERROR_PNP_BAD_MPS_TABLE",
+ "ERROR_PNP_TRANSLATION_FAILED",
+ "ERROR_PNP_IRQ_TRANSLATION_FAILED",
+ "ERROR_PNP_INVALID_ID",
+ "ERROR_WAKE_SYSTEM_DEBUGGER",
+ "ERROR_HANDLES_CLOSED",
+ "ERROR_EXTRANEOUS_INFORMATION",
+ "ERROR_RXACT_COMMIT_NECESSARY",
+ "ERROR_MEDIA_CHECK",
+ "ERROR_GUID_SUBSTITUTION_MADE",
+ "ERROR_STOPPED_ON_SYMLINK",
+ "ERROR_LONGJUMP",
+ "ERROR_PLUGPLAY_QUERY_VETOED",
+ "ERROR_UNWIND_CONSOLIDATE",
+ "ERROR_REGISTRY_HIVE_RECOVERED",
+ "ERROR_DLL_MIGHT_BE_INSECURE",
+ "ERROR_DLL_MIGHT_BE_INCOMPATIBLE",
+ "ERROR_DBG_EXCEPTION_NOT_HANDLED",
+ "ERROR_DBG_REPLY_LATER",
+ "ERROR_DBG_UNABLE_TO_PROVIDE_HANDLE",
+ "ERROR_DBG_TERMINATE_THREAD",
+ "ERROR_DBG_TERMINATE_PROCESS",
+ "ERROR_DBG_CONTROL_C",
+ "ERROR_DBG_PRINTEXCEPTION_C",
+ "ERROR_DBG_RIPEXCEPTION",
+ "ERROR_DBG_CONTROL_BREAK",
+ "ERROR_DBG_COMMAND_EXCEPTION",
+ "ERROR_OBJECT_NAME_EXISTS",
+ "ERROR_THREAD_WAS_SUSPENDED",
+ "ERROR_IMAGE_NOT_AT_BASE",
+ "ERROR_RXACT_STATE_CREATED",
+ "ERROR_SEGMENT_NOTIFICATION",
+ "ERROR_BAD_CURRENT_DIRECTORY",
+ "ERROR_FT_READ_RECOVERY_FROM_BACKUP",
+ "ERROR_FT_WRITE_RECOVERY",
+ "ERROR_IMAGE_MACHINE_TYPE_MISMATCH",
+ "ERROR_RECEIVE_PARTIAL",
+ "ERROR_RECEIVE_EXPEDITED",
+ "ERROR_RECEIVE_PARTIAL_EXPEDITED",
+ "ERROR_EVENT_DONE",
+ "ERROR_EVENT_PENDING",
+ "ERROR_CHECKING_FILE_SYSTEM",
+ "ERROR_FATAL_APP_EXIT",
+ "ERROR_PREDEFINED_HANDLE",
+ "ERROR_WAS_UNLOCKED",
+ "ERROR_SERVICE_NOTIFICATION",
+ "ERROR_WAS_LOCKED",
+ "ERROR_LOG_HARD_ERROR",
+ "ERROR_ALREADY_WIN32",
+ "ERROR_IMAGE_MACHINE_TYPE_MISMATCH_EXE",
+ "ERROR_NO_YIELD_PERFORMED",
+ "ERROR_TIMER_RESUME_IGNORED",
+ "ERROR_ARBITRATION_UNHANDLED",
+ "ERROR_CARDBUS_NOT_SUPPORTED",
+ "ERROR_MP_PROCESSOR_MISMATCH",
+ "ERROR_HIBERNATED",
+ "ERROR_RESUME_HIBERNATION",
+ "ERROR_FIRMWARE_UPDATED",
+ "ERROR_DRIVERS_LEAKING_LOCKED_PAGES",
+ "ERROR_WAKE_SYSTEM",
+ "ERROR_WAIT_1",
+ "ERROR_WAIT_2",
+ "ERROR_WAIT_3",
+ "ERROR_WAIT_63",
+ "ERROR_ABANDONED_WAIT_0",
+ "ERROR_ABANDONED_WAIT_63",
+ "ERROR_USER_APC",
+ "ERROR_KERNEL_APC",
+ "ERROR_ALERTED",
+ "ERROR_ELEVATION_REQUIRED",
+ "ERROR_REPARSE",
+ "ERROR_OPLOCK_BREAK_IN_PROGRESS",
+ "ERROR_VOLUME_MOUNTED",
+ "ERROR_RXACT_COMMITTED",
+ "ERROR_NOTIFY_CLEANUP",
+ "ERROR_PRIMARY_TRANSPORT_CONNECT_FAILED",
+ "ERROR_PAGE_FAULT_TRANSITION",
+ "ERROR_PAGE_FAULT_DEMAND_ZERO",
+ "ERROR_PAGE_FAULT_COPY_ON_WRITE",
+ "ERROR_PAGE_FAULT_GUARD_PAGE",
+ "ERROR_PAGE_FAULT_PAGING_FILE",
+ "ERROR_CACHE_PAGE_LOCKED",
+ "ERROR_CRASH_DUMP",
+ "ERROR_BUFFER_ALL_ZEROS",
+ "ERROR_REPARSE_OBJECT",
+ "ERROR_RESOURCE_REQUIREMENTS_CHANGED",
+ "ERROR_TRANSLATION_COMPLETE",
+ "ERROR_NOTHING_TO_TERMINATE",
+ "ERROR_PROCESS_NOT_IN_JOB",
+ "ERROR_PROCESS_IN_JOB",
+ "ERROR_VOLSNAP_HIBERNATE_READY",
+ "ERROR_FSFILTER_OP_COMPLETED_SUCCESSFULLY",
+ "ERROR_INTERRUPT_VECTOR_ALREADY_CONNECTED",
+ "ERROR_INTERRUPT_STILL_CONNECTED",
+ "ERROR_WAIT_FOR_OPLOCK",
+ "ERROR_DBG_EXCEPTION_HANDLED",
+ "ERROR_DBG_CONTINUE",
+ "ERROR_CALLBACK_POP_STACK",
+ "ERROR_COMPRESSION_DISABLED",
+ "ERROR_CANTFETCHBACKWARDS",
+ "ERROR_CANTSCROLLBACKWARDS",
+ "ERROR_ROWSNOTRELEASED",
+ "ERROR_BAD_ACCESSOR_FLAGS",
+ "ERROR_ERRORS_ENCOUNTERED",
+ "ERROR_NOT_CAPABLE",
+ "ERROR_REQUEST_OUT_OF_SEQUENCE",
+ "ERROR_VERSION_PARSE_ERROR",
+ "ERROR_BADSTARTPOSITION",
+ "ERROR_MEMORY_HARDWARE",
+ "ERROR_DISK_REPAIR_DISABLED",
+ "ERROR_INSUFFICIENT_RESOURCE_FOR_SPECIFIED_SHARED_SECTION_SIZE",
+ "ERROR_SYSTEM_POWERSTATE_TRANSITION",
+ "ERROR_SYSTEM_POWERSTATE_COMPLEX_TRANSITION",
+ "ERROR_MCA_EXCEPTION",
+ "ERROR_ACCESS_AUDIT_BY_POLICY",
+ "ERROR_ACCESS_DISABLED_NO_SAFER_UI_BY_POLICY",
+ "ERROR_ABANDON_HIBERFILE",
+ "ERROR_LOST_WRITEBEHIND_DATA_NETWORK_DISCONNECTED",
+ "ERROR_LOST_WRITEBEHIND_DATA_NETWORK_SERVER_ERROR",
+ "ERROR_LOST_WRITEBEHIND_DATA_LOCAL_DISK_ERROR",
+ "ERROR_BAD_MCFG_TABLE",
+ "ERROR_DISK_REPAIR_REDIRECTED",
+ "ERROR_DISK_REPAIR_UNSUCCESSFUL",
+ "ERROR_CORRUPT_LOG_OVERFULL",
+ "ERROR_CORRUPT_LOG_CORRUPTED",
+ "ERROR_CORRUPT_LOG_UNAVAILABLE",
+ "ERROR_CORRUPT_LOG_DELETED_FULL",
+ "ERROR_CORRUPT_LOG_CLEARED",
+ "ERROR_ORPHAN_NAME_EXHAUSTED",
+ "ERROR_OPLOCK_SWITCHED_TO_NEW_HANDLE",
+ "ERROR_CANNOT_GRANT_REQUESTED_OPLOCK",
+ "ERROR_CANNOT_BREAK_OPLOCK",
+ "ERROR_OPLOCK_HANDLE_CLOSED",
+ "ERROR_NO_ACE_CONDITION",
+ "ERROR_INVALID_ACE_CONDITION",
+ "ERROR_FILE_HANDLE_REVOKED",
+ "ERROR_IMAGE_AT_DIFFERENT_BASE",
+ "ERROR_ENCRYPTED_IO_NOT_POSSIBLE",
+ "ERROR_FILE_METADATA_OPTIMIZATION_IN_PROGRESS",
+ "ERROR_QUOTA_ACTIVITY",
+ "ERROR_HANDLE_REVOKED",
+ "ERROR_CALLBACK_INVOKE_INLINE",
+ "ERROR_CPU_SET_INVALID",
+ "ERROR_ENCLAVE_NOT_TERMINATED",
+ "ERROR_ENCLAVE_VIOLATION",
+ "ERROR_EA_ACCESS_DENIED",
+ "ERROR_OPERATION_ABORTED",
+ "ERROR_IO_INCOMPLETE",
+ "ERROR_IO_PENDING",
+ "ERROR_NOACCESS",
+ "ERROR_SWAPERROR",
+ "ERROR_STACK_OVERFLOW",
+ "ERROR_INVALID_MESSAGE",
+ "ERROR_CAN_NOT_COMPLETE",
+ "ERROR_INVALID_FLAGS",
+ "ERROR_UNRECOGNIZED_VOLUME",
+ "ERROR_FILE_INVALID",
+ "ERROR_FULLSCREEN_MODE",
+ "ERROR_NO_TOKEN",
+ "ERROR_BADDB",
+ "ERROR_BADKEY",
+ "ERROR_CANTOPEN",
+ "ERROR_CANTREAD",
+ "ERROR_CANTWRITE",
+ "ERROR_REGISTRY_RECOVERED",
+ "ERROR_REGISTRY_CORRUPT",
+ "ERROR_REGISTRY_IO_FAILED",
+ "ERROR_NOT_REGISTRY_FILE",
+ "ERROR_KEY_DELETED",
+ "ERROR_NO_LOG_SPACE",
+ "ERROR_KEY_HAS_CHILDREN",
+ "ERROR_CHILD_MUST_BE_VOLATILE",
+ "ERROR_NOTIFY_ENUM_DIR",
+ "ERROR_DEPENDENT_SERVICES_RUNNING",
+ "ERROR_INVALID_SERVICE_CONTROL",
+ "ERROR_SERVICE_REQUEST_TIMEOUT",
+ "ERROR_SERVICE_NO_THREAD",
+ "ERROR_SERVICE_DATABASE_LOCKED",
+ "ERROR_SERVICE_ALREADY_RUNNING",
+ "ERROR_INVALID_SERVICE_ACCOUNT",
+ "ERROR_SERVICE_DISABLED",
+ "ERROR_CIRCULAR_DEPENDENCY",
+ "ERROR_SERVICE_DOES_NOT_EXIST",
+ "ERROR_SERVICE_CANNOT_ACCEPT_CTRL",
+ "ERROR_SERVICE_NOT_ACTIVE",
+ "ERROR_FAILED_SERVICE_CONTROLLER_CONNECT",
+ "ERROR_EXCEPTION_IN_SERVICE",
+ "ERROR_DATABASE_DOES_NOT_EXIST",
+ "ERROR_SERVICE_SPECIFIC_ERROR",
+ "ERROR_PROCESS_ABORTED",
+ "ERROR_SERVICE_DEPENDENCY_FAIL",
+ "ERROR_SERVICE_LOGON_FAILED",
+ "ERROR_SERVICE_START_HANG",
+ "ERROR_INVALID_SERVICE_LOCK",
+ "ERROR_SERVICE_MARKED_FOR_DELETE",
+ "ERROR_SERVICE_EXISTS",
+ "ERROR_ALREADY_RUNNING_LKG",
+ "ERROR_SERVICE_DEPENDENCY_DELETED",
+ "ERROR_BOOT_ALREADY_ACCEPTED",
+ "ERROR_SERVICE_NEVER_STARTED",
+ "ERROR_DUPLICATE_SERVICE_NAME",
+ "ERROR_DIFFERENT_SERVICE_ACCOUNT",
+ "ERROR_CANNOT_DETECT_DRIVER_FAILURE",
+ "ERROR_CANNOT_DETECT_PROCESS_ABORT",
+ "ERROR_NO_RECOVERY_PROGRAM",
+ "ERROR_SERVICE_NOT_IN_EXE",
+ "ERROR_NOT_SAFEBOOT_SERVICE",
+ "ERROR_END_OF_MEDIA",
+ "ERROR_FILEMARK_DETECTED",
+ "ERROR_BEGINNING_OF_MEDIA",
+ "ERROR_SETMARK_DETECTED",
+ "ERROR_NO_DATA_DETECTED",
+ "ERROR_PARTITION_FAILURE",
+ "ERROR_INVALID_BLOCK_LENGTH",
+ "ERROR_DEVICE_NOT_PARTITIONED",
+ "ERROR_UNABLE_TO_LOCK_MEDIA",
+ "ERROR_UNABLE_TO_UNLOAD_MEDIA",
+ "ERROR_MEDIA_CHANGED",
+ "ERROR_BUS_RESET",
+ "ERROR_NO_MEDIA_IN_DRIVE",
+ "ERROR_NO_UNICODE_TRANSLATION",
+ "ERROR_DLL_INIT_FAILED",
+ "ERROR_SHUTDOWN_IN_PROGRESS",
+ "ERROR_NO_SHUTDOWN_IN_PROGRESS",
+ "ERROR_IO_DEVICE",
+ "ERROR_SERIAL_NO_DEVICE",
+ "ERROR_IRQ_BUSY",
+ "ERROR_MORE_WRITES",
+ "ERROR_COUNTER_TIMEOUT",
+ "ERROR_FLOPPY_ID_MARK_NOT_FOUND",
+ "ERROR_FLOPPY_WRONG_CYLINDER",
+ "ERROR_FLOPPY_UNKNOWN_ERROR",
+ "ERROR_FLOPPY_BAD_REGISTERS",
+ "ERROR_DISK_RECALIBRATE_FAILED",
+ "ERROR_DISK_OPERATION_FAILED",
+ "ERROR_DISK_RESET_FAILED",
+ "ERROR_EOM_OVERFLOW",
+ "ERROR_NOT_ENOUGH_SERVER_MEMORY",
+ "ERROR_POSSIBLE_DEADLOCK",
+ "ERROR_MAPPED_ALIGNMENT",
+ "ERROR_SET_POWER_STATE_VETOED",
+ "ERROR_SET_POWER_STATE_FAILED",
+ "ERROR_TOO_MANY_LINKS",
+ "ERROR_OLD_WIN_VERSION",
+ "ERROR_APP_WRONG_OS",
+ "ERROR_SINGLE_INSTANCE_APP",
+ "ERROR_RMODE_APP",
+ "ERROR_INVALID_DLL",
+ "ERROR_NO_ASSOCIATION",
+ "ERROR_DDE_FAIL",
+ "ERROR_DLL_NOT_FOUND",
+ "ERROR_NO_MORE_USER_HANDLES",
+ "ERROR_MESSAGE_SYNC_ONLY",
+ "ERROR_SOURCE_ELEMENT_EMPTY",
+ "ERROR_DESTINATION_ELEMENT_FULL",
+ "ERROR_ILLEGAL_ELEMENT_ADDRESS",
+ "ERROR_MAGAZINE_NOT_PRESENT",
+ "ERROR_DEVICE_REINITIALIZATION_NEEDED",
+ "ERROR_DEVICE_REQUIRES_CLEANING",
+ "ERROR_DEVICE_DOOR_OPEN",
+ "ERROR_DEVICE_NOT_CONNECTED",
+ "ERROR_NOT_FOUND",
+ "ERROR_NO_MATCH",
+ "ERROR_SET_NOT_FOUND",
+ "ERROR_POINT_NOT_FOUND",
+ "ERROR_NO_TRACKING_SERVICE",
+ "ERROR_NO_VOLUME_ID",
+ "ERROR_UNABLE_TO_REMOVE_REPLACED",
+ "ERROR_UNABLE_TO_MOVE_REPLACEMENT",
+ "ERROR_UNABLE_TO_MOVE_REPLACEMENT_2",
+ "ERROR_JOURNAL_DELETE_IN_PROGRESS",
+ "ERROR_JOURNAL_NOT_ACTIVE",
+ "ERROR_POTENTIAL_FILE_FOUND",
+ "ERROR_JOURNAL_ENTRY_DELETED",
+ "ERROR_VRF_CFG_AND_IO_ENABLED",
+ "ERROR_PARTITION_TERMINATING",
+ "ERROR_SHUTDOWN_IS_SCHEDULED",
+ "ERROR_SHUTDOWN_USERS_LOGGED_ON",
+ "ERROR_BAD_DEVICE",
+ "ERROR_CONNECTION_UNAVAIL",
+ "ERROR_DEVICE_ALREADY_REMEMBERED",
+ "ERROR_NO_NET_OR_BAD_PATH",
+ "ERROR_BAD_PROVIDER",
+ "ERROR_CANNOT_OPEN_PROFILE",
+ "ERROR_BAD_PROFILE",
+ "ERROR_NOT_CONTAINER",
+ "ERROR_EXTENDED_ERROR",
+ "ERROR_INVALID_GROUPNAME",
+ "ERROR_INVALID_COMPUTERNAME",
+ "ERROR_INVALID_EVENTNAME",
+ "ERROR_INVALID_DOMAINNAME",
+ "ERROR_INVALID_SERVICENAME",
+ "ERROR_INVALID_NETNAME",
+ "ERROR_INVALID_SHARENAME",
+ "ERROR_INVALID_PASSWORDNAME",
+ "ERROR_INVALID_MESSAGENAME",
+ "ERROR_INVALID_MESSAGEDEST",
+ "ERROR_SESSION_CREDENTIAL_CONFLICT",
+ "ERROR_REMOTE_SESSION_LIMIT_EXCEEDED",
+ "ERROR_DUP_DOMAINNAME",
+ "ERROR_NO_NETWORK",
+ "ERROR_CANCELLED",
+ "ERROR_USER_MAPPED_FILE",
+ "ERROR_CONNECTION_REFUSED",
+ "ERROR_GRACEFUL_DISCONNECT",
+ "ERROR_ADDRESS_ALREADY_ASSOCIATED",
+ "ERROR_ADDRESS_NOT_ASSOCIATED",
+ "ERROR_CONNECTION_INVALID",
+ "ERROR_CONNECTION_ACTIVE",
+ "ERROR_NETWORK_UNREACHABLE",
+ "ERROR_HOST_UNREACHABLE",
+ "ERROR_PROTOCOL_UNREACHABLE",
+ "ERROR_PORT_UNREACHABLE",
+ "ERROR_REQUEST_ABORTED",
+ "ERROR_CONNECTION_ABORTED",
+ "ERROR_RETRY",
+ "ERROR_CONNECTION_COUNT_LIMIT",
+ "ERROR_LOGIN_TIME_RESTRICTION",
+ "ERROR_LOGIN_WKSTA_RESTRICTION",
+ "ERROR_INCORRECT_ADDRESS",
+ "ERROR_ALREADY_REGISTERED",
+ "ERROR_SERVICE_NOT_FOUND",
+ "ERROR_NOT_AUTHENTICATED",
+ "ERROR_NOT_LOGGED_ON",
+ "ERROR_CONTINUE",
+ "ERROR_ALREADY_INITIALIZED",
+ "ERROR_NO_MORE_DEVICES",
+ "ERROR_NO_SUCH_SITE",
+ "ERROR_DOMAIN_CONTROLLER_EXISTS",
+ "ERROR_ONLY_IF_CONNECTED",
+ "ERROR_OVERRIDE_NOCHANGES",
+ "ERROR_BAD_USER_PROFILE",
+ "ERROR_NOT_SUPPORTED_ON_SBS",
+ "ERROR_SERVER_SHUTDOWN_IN_PROGRESS",
+ "ERROR_HOST_DOWN",
+ "ERROR_NON_ACCOUNT_SID",
+ "ERROR_NON_DOMAIN_SID",
+ "ERROR_APPHELP_BLOCK",
+ "ERROR_ACCESS_DISABLED_BY_POLICY",
+ "ERROR_REG_NAT_CONSUMPTION",
+ "ERROR_CSCSHARE_OFFLINE",
+ "ERROR_PKINIT_FAILURE",
+ "ERROR_SMARTCARD_SUBSYSTEM_FAILURE",
+ "ERROR_DOWNGRADE_DETECTED",
+ "ERROR_MACHINE_LOCKED",
+ "ERROR_SMB_GUEST_LOGON_BLOCKED",
+ "ERROR_CALLBACK_SUPPLIED_INVALID_DATA",
+ "ERROR_SYNC_FOREGROUND_REFRESH_REQUIRED",
+ "ERROR_DRIVER_BLOCKED",
+ "ERROR_INVALID_IMPORT_OF_NON_DLL",
+ "ERROR_ACCESS_DISABLED_WEBBLADE",
+ "ERROR_ACCESS_DISABLED_WEBBLADE_TAMPER",
+ "ERROR_RECOVERY_FAILURE",
+ "ERROR_ALREADY_FIBER",
+ "ERROR_ALREADY_THREAD",
+ "ERROR_STACK_BUFFER_OVERRUN",
+ "ERROR_PARAMETER_QUOTA_EXCEEDED",
+ "ERROR_DEBUGGER_INACTIVE",
+ "ERROR_DELAY_LOAD_FAILED",
+ "ERROR_VDM_DISALLOWED",
+ "ERROR_UNIDENTIFIED_ERROR",
+ "ERROR_INVALID_CRUNTIME_PARAMETER",
+ "ERROR_BEYOND_VDL",
+ "ERROR_INCOMPATIBLE_SERVICE_SID_TYPE",
+ "ERROR_DRIVER_PROCESS_TERMINATED",
+ "ERROR_IMPLEMENTATION_LIMIT",
+ "ERROR_PROCESS_IS_PROTECTED",
+ "ERROR_SERVICE_NOTIFY_CLIENT_LAGGING",
+ "ERROR_DISK_QUOTA_EXCEEDED",
+ "ERROR_CONTENT_BLOCKED",
+ "ERROR_INCOMPATIBLE_SERVICE_PRIVILEGE",
+ "ERROR_APP_HANG",
+ "ERROR_INVALID_LABEL",
+ "ERROR_NOT_ALL_ASSIGNED",
+ "ERROR_SOME_NOT_MAPPED",
+ "ERROR_NO_QUOTAS_FOR_ACCOUNT",
+ "ERROR_LOCAL_USER_SESSION_KEY",
+ "ERROR_NULL_LM_PASSWORD",
+ "ERROR_UNKNOWN_REVISION",
+ "ERROR_REVISION_MISMATCH",
+ "ERROR_INVALID_OWNER",
+ "ERROR_INVALID_PRIMARY_GROUP",
+ "ERROR_NO_IMPERSONATION_TOKEN",
+ "ERROR_CANT_DISABLE_MANDATORY",
+ "ERROR_NO_LOGON_SERVERS",
+ "ERROR_NO_SUCH_LOGON_SESSION",
+ "ERROR_NO_SUCH_PRIVILEGE",
+ "ERROR_PRIVILEGE_NOT_HELD",
+ "ERROR_INVALID_ACCOUNT_NAME",
+ "ERROR_USER_EXISTS",
+ "ERROR_NO_SUCH_USER",
+ "ERROR_GROUP_EXISTS",
+ "ERROR_NO_SUCH_GROUP",
+ "ERROR_MEMBER_IN_GROUP",
+ "ERROR_MEMBER_NOT_IN_GROUP",
+ "ERROR_LAST_ADMIN",
+ "ERROR_WRONG_PASSWORD",
+ "ERROR_ILL_FORMED_PASSWORD",
+ "ERROR_PASSWORD_RESTRICTION",
+ "ERROR_LOGON_FAILURE",
+ "ERROR_ACCOUNT_RESTRICTION",
+ "ERROR_INVALID_LOGON_HOURS",
+ "ERROR_INVALID_WORKSTATION",
+ "ERROR_PASSWORD_EXPIRED",
+ "ERROR_ACCOUNT_DISABLED",
+ "ERROR_NONE_MAPPED",
+ "ERROR_TOO_MANY_LUIDS_REQUESTED",
+ "ERROR_LUIDS_EXHAUSTED",
+ "ERROR_INVALID_SUB_AUTHORITY",
+ "ERROR_INVALID_ACL",
+ "ERROR_INVALID_SID",
+ "ERROR_INVALID_SECURITY_DESCR",
+ "ERROR_BAD_INHERITANCE_ACL",
+ "ERROR_SERVER_DISABLED",
+ "ERROR_SERVER_NOT_DISABLED",
+ "ERROR_INVALID_ID_AUTHORITY",
+ "ERROR_ALLOTTED_SPACE_EXCEEDED",
+ "ERROR_INVALID_GROUP_ATTRIBUTES",
+ "ERROR_BAD_IMPERSONATION_LEVEL",
+ "ERROR_CANT_OPEN_ANONYMOUS",
+ "ERROR_BAD_VALIDATION_CLASS",
+ "ERROR_BAD_TOKEN_TYPE",
+ "ERROR_NO_SECURITY_ON_OBJECT",
+ "ERROR_CANT_ACCESS_DOMAIN_INFO",
+ "ERROR_INVALID_SERVER_STATE",
+ "ERROR_INVALID_DOMAIN_STATE",
+ "ERROR_INVALID_DOMAIN_ROLE",
+ "ERROR_NO_SUCH_DOMAIN",
+ "ERROR_DOMAIN_EXISTS",
+ "ERROR_DOMAIN_LIMIT_EXCEEDED",
+ "ERROR_INTERNAL_DB_CORRUPTION",
+ "ERROR_INTERNAL_ERROR",
+ "ERROR_GENERIC_NOT_MAPPED",
+ "ERROR_BAD_DESCRIPTOR_FORMAT",
+ "ERROR_NOT_LOGON_PROCESS",
+ "ERROR_LOGON_SESSION_EXISTS",
+ "ERROR_NO_SUCH_PACKAGE",
+ "ERROR_BAD_LOGON_SESSION_STATE",
+ "ERROR_LOGON_SESSION_COLLISION",
+ "ERROR_INVALID_LOGON_TYPE",
+ "ERROR_CANNOT_IMPERSONATE",
+ "ERROR_RXACT_INVALID_STATE",
+ "ERROR_RXACT_COMMIT_FAILURE",
+ "ERROR_SPECIAL_ACCOUNT",
+ "ERROR_SPECIAL_GROUP",
+ "ERROR_SPECIAL_USER",
+ "ERROR_MEMBERS_PRIMARY_GROUP",
+ "ERROR_TOKEN_ALREADY_IN_USE",
+ "ERROR_NO_SUCH_ALIAS",
+ "ERROR_MEMBER_NOT_IN_ALIAS",
+ "ERROR_MEMBER_IN_ALIAS",
+ "ERROR_ALIAS_EXISTS",
+ "ERROR_LOGON_NOT_GRANTED",
+ "ERROR_TOO_MANY_SECRETS",
+ "ERROR_SECRET_TOO_LONG",
+ "ERROR_INTERNAL_DB_ERROR",
+ "ERROR_TOO_MANY_CONTEXT_IDS",
+ "ERROR_LOGON_TYPE_NOT_GRANTED",
+ "ERROR_NT_CROSS_ENCRYPTION_REQUIRED",
+ "ERROR_NO_SUCH_MEMBER",
+ "ERROR_INVALID_MEMBER",
+ "ERROR_TOO_MANY_SIDS",
+ "ERROR_LM_CROSS_ENCRYPTION_REQUIRED",
+ "ERROR_NO_INHERITANCE",
+ "ERROR_FILE_CORRUPT",
+ "ERROR_DISK_CORRUPT",
+ "ERROR_NO_USER_SESSION_KEY",
+ "ERROR_LICENSE_QUOTA_EXCEEDED",
+ "ERROR_WRONG_TARGET_NAME",
+ "ERROR_MUTUAL_AUTH_FAILED",
+ "ERROR_TIME_SKEW",
+ "ERROR_CURRENT_DOMAIN_NOT_ALLOWED",
+ "ERROR_INVALID_WINDOW_HANDLE",
+ "ERROR_INVALID_MENU_HANDLE",
+ "ERROR_INVALID_CURSOR_HANDLE",
+ "ERROR_INVALID_ACCEL_HANDLE",
+ "ERROR_INVALID_HOOK_HANDLE",
+ "ERROR_INVALID_DWP_HANDLE",
+ "ERROR_TLW_WITH_WSCHILD",
+ "ERROR_CANNOT_FIND_WND_CLASS",
+ "ERROR_WINDOW_OF_OTHER_THREAD",
+ "ERROR_HOTKEY_ALREADY_REGISTERED",
+ "ERROR_CLASS_ALREADY_EXISTS",
+ "ERROR_CLASS_DOES_NOT_EXIST",
+ "ERROR_CLASS_HAS_WINDOWS",
+ "ERROR_INVALID_INDEX",
+ "ERROR_INVALID_ICON_HANDLE",
+ "ERROR_PRIVATE_DIALOG_INDEX",
+ "ERROR_LISTBOX_ID_NOT_FOUND",
+ "ERROR_NO_WILDCARD_CHARACTERS",
+ "ERROR_CLIPBOARD_NOT_OPEN",
+ "ERROR_HOTKEY_NOT_REGISTERED",
+ "ERROR_WINDOW_NOT_DIALOG",
+ "ERROR_CONTROL_ID_NOT_FOUND",
+ "ERROR_INVALID_COMBOBOX_MESSAGE",
+ "ERROR_WINDOW_NOT_COMBOBOX",
+ "ERROR_INVALID_EDIT_HEIGHT",
+ "ERROR_DC_NOT_FOUND",
+ "ERROR_INVALID_HOOK_FILTER",
+ "ERROR_INVALID_FILTER_PROC",
+ "ERROR_HOOK_NEEDS_HMOD",
+ "ERROR_GLOBAL_ONLY_HOOK",
+ "ERROR_JOURNAL_HOOK_SET",
+ "ERROR_HOOK_NOT_INSTALLED",
+ "ERROR_INVALID_LB_MESSAGE",
+ "ERROR_SETCOUNT_ON_BAD_LB",
+ "ERROR_LB_WITHOUT_TABSTOPS",
+ "ERROR_DESTROY_OBJECT_OF_OTHER_THREAD",
+ "ERROR_CHILD_WINDOW_MENU",
+ "ERROR_NO_SYSTEM_MENU",
+ "ERROR_INVALID_MSGBOX_STYLE",
+ "ERROR_INVALID_SPI_VALUE",
+ "ERROR_SCREEN_ALREADY_LOCKED",
+ "ERROR_HWNDS_HAVE_DIFF_PARENT",
+ "ERROR_NOT_CHILD_WINDOW",
+ "ERROR_INVALID_GW_COMMAND",
+ "ERROR_INVALID_THREAD_ID",
+ "ERROR_NON_MDICHILD_WINDOW",
+ "ERROR_POPUP_ALREADY_ACTIVE",
+ "ERROR_NO_SCROLLBARS",
+ "ERROR_INVALID_SCROLLBAR_RANGE",
+ "ERROR_INVALID_SHOWWIN_COMMAND",
+ "ERROR_NO_SYSTEM_RESOURCES",
+ "ERROR_NONPAGED_SYSTEM_RESOURCES",
+ "ERROR_PAGED_SYSTEM_RESOURCES",
+ "ERROR_WORKING_SET_QUOTA",
+ "ERROR_PAGEFILE_QUOTA",
+ "ERROR_COMMITMENT_LIMIT",
+ "ERROR_MENU_ITEM_NOT_FOUND",
+ "ERROR_INVALID_KEYBOARD_HANDLE",
+ "ERROR_HOOK_TYPE_NOT_ALLOWED",
+ "ERROR_REQUIRES_INTERACTIVE_WINDOWSTATION",
+ "ERROR_TIMEOUT",
+ "ERROR_INVALID_MONITOR_HANDLE",
+ "ERROR_INCORRECT_SIZE",
+ "ERROR_SYMLINK_CLASS_DISABLED",
+ "ERROR_SYMLINK_NOT_SUPPORTED",
+ "ERROR_XML_PARSE_ERROR",
+ "ERROR_XMLDSIG_ERROR",
+ "ERROR_RESTART_APPLICATION",
+ "ERROR_WRONG_COMPARTMENT",
+ "ERROR_AUTHIP_FAILURE",
+ "ERROR_NO_NVRAM_RESOURCES",
+ "ERROR_NOT_GUI_PROCESS",
+ "ERROR_EVENTLOG_FILE_CORRUPT",
+ "ERROR_EVENTLOG_CANT_START",
+ "ERROR_LOG_FILE_FULL",
+ "ERROR_EVENTLOG_FILE_CHANGED",
+ "ERROR_CONTAINER_ASSIGNED",
+ "ERROR_JOB_NO_CONTAINER",
+ "ERROR_INVALID_TASK_NAME",
+ "ERROR_INVALID_TASK_INDEX",
+ "ERROR_THREAD_ALREADY_IN_TASK",
+ "ERROR_INSTALL_SERVICE_FAILURE",
+ "ERROR_INSTALL_USEREXIT",
+ "ERROR_INSTALL_FAILURE",
+ "ERROR_INSTALL_SUSPEND",
+ "ERROR_UNKNOWN_PRODUCT",
+ "ERROR_UNKNOWN_FEATURE",
+ "ERROR_UNKNOWN_COMPONENT",
+ "ERROR_UNKNOWN_PROPERTY",
+ "ERROR_INVALID_HANDLE_STATE",
+ "ERROR_BAD_CONFIGURATION",
+ "ERROR_INDEX_ABSENT",
+ "ERROR_INSTALL_SOURCE_ABSENT",
+ "ERROR_INSTALL_PACKAGE_VERSION",
+ "ERROR_PRODUCT_UNINSTALLED",
+ "ERROR_BAD_QUERY_SYNTAX",
+ "ERROR_INVALID_FIELD",
+ "ERROR_DEVICE_REMOVED",
+ "ERROR_INSTALL_ALREADY_RUNNING",
+ "ERROR_INSTALL_PACKAGE_OPEN_FAILED",
+ "ERROR_INSTALL_PACKAGE_INVALID",
+ "ERROR_INSTALL_UI_FAILURE",
+ "ERROR_INSTALL_LOG_FAILURE",
+ "ERROR_INSTALL_LANGUAGE_UNSUPPORTED",
+ "ERROR_INSTALL_TRANSFORM_FAILURE",
+ "ERROR_INSTALL_PACKAGE_REJECTED",
+ "ERROR_FUNCTION_NOT_CALLED",
+ "ERROR_FUNCTION_FAILED",
+ "ERROR_INVALID_TABLE",
+ "ERROR_DATATYPE_MISMATCH",
+ "ERROR_UNSUPPORTED_TYPE",
+ "ERROR_CREATE_FAILED",
+ "ERROR_INSTALL_TEMP_UNWRITABLE",
+ "ERROR_INSTALL_PLATFORM_UNSUPPORTED",
+ "ERROR_INSTALL_NOTUSED",
+ "ERROR_PATCH_PACKAGE_OPEN_FAILED",
+ "ERROR_PATCH_PACKAGE_INVALID",
+ "ERROR_PATCH_PACKAGE_UNSUPPORTED",
+ "ERROR_PRODUCT_VERSION",
+ "ERROR_INVALID_COMMAND_LINE",
+ "ERROR_INSTALL_REMOTE_DISALLOWED",
+ "ERROR_SUCCESS_REBOOT_INITIATED",
+ "ERROR_PATCH_TARGET_NOT_FOUND",
+ "ERROR_PATCH_PACKAGE_REJECTED",
+ "ERROR_INSTALL_TRANSFORM_REJECTED",
+ "ERROR_INSTALL_REMOTE_PROHIBITED",
+ "ERROR_PATCH_REMOVAL_UNSUPPORTED",
+ "ERROR_UNKNOWN_PATCH",
+ "ERROR_PATCH_NO_SEQUENCE",
+ "ERROR_PATCH_REMOVAL_DISALLOWED",
+ "ERROR_INVALID_PATCH_XML",
+ "ERROR_PATCH_MANAGED_ADVERTISED_PRODUCT",
+ "ERROR_INSTALL_SERVICE_SAFEBOOT",
+ "ERROR_FAIL_FAST_EXCEPTION",
+ "ERROR_INSTALL_REJECTED",
+ "ERROR_DYNAMIC_CODE_BLOCKED",
+ "ERROR_NOT_SAME_OBJECT",
+ "ERROR_STRICT_CFG_VIOLATION",
+ "ERROR_SET_CONTEXT_DENIED",
+ "ERROR_CROSS_PARTITION_VIOLATION",
+ "ERROR_RETURN_ADDRESS_HIJACK_ATTEMPT",
+ "ERROR_INVALID_USER_BUFFER",
+ "ERROR_UNRECOGNIZED_MEDIA",
+ "ERROR_NO_TRUST_LSA_SECRET",
+ "ERROR_NO_TRUST_SAM_ACCOUNT",
+ "ERROR_TRUSTED_DOMAIN_FAILURE",
+ "ERROR_TRUSTED_RELATIONSHIP_FAILURE",
+ "ERROR_TRUST_FAILURE",
+ "ERROR_NETLOGON_NOT_STARTED",
+ "ERROR_ACCOUNT_EXPIRED",
+ "ERROR_REDIRECTOR_HAS_OPEN_HANDLES",
+ "ERROR_PRINTER_DRIVER_ALREADY_INSTALLED",
+ "ERROR_UNKNOWN_PORT",
+ "ERROR_UNKNOWN_PRINTER_DRIVER",
+ "ERROR_UNKNOWN_PRINTPROCESSOR",
+ "ERROR_INVALID_SEPARATOR_FILE",
+ "ERROR_INVALID_PRIORITY",
+ "ERROR_INVALID_PRINTER_NAME",
+ "ERROR_PRINTER_ALREADY_EXISTS",
+ "ERROR_INVALID_PRINTER_COMMAND",
+ "ERROR_INVALID_DATATYPE",
+ "ERROR_INVALID_ENVIRONMENT",
+ "ERROR_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT",
+ "ERROR_NOLOGON_WORKSTATION_TRUST_ACCOUNT",
+ "ERROR_NOLOGON_SERVER_TRUST_ACCOUNT",
+ "ERROR_DOMAIN_TRUST_INCONSISTENT",
+ "ERROR_SERVER_HAS_OPEN_HANDLES",
+ "ERROR_RESOURCE_DATA_NOT_FOUND",
+ "ERROR_RESOURCE_TYPE_NOT_FOUND",
+ "ERROR_RESOURCE_NAME_NOT_FOUND",
+ "ERROR_RESOURCE_LANG_NOT_FOUND",
+ "ERROR_NOT_ENOUGH_QUOTA",
+ "ERROR_INVALID_TIME",
+ "ERROR_INVALID_FORM_NAME",
+ "ERROR_INVALID_FORM_SIZE",
+ "ERROR_ALREADY_WAITING",
+ "ERROR_PRINTER_DELETED",
+ "ERROR_INVALID_PRINTER_STATE",
+ "ERROR_PASSWORD_MUST_CHANGE",
+ "ERROR_DOMAIN_CONTROLLER_NOT_FOUND",
+ "ERROR_ACCOUNT_LOCKED_OUT",
+ "ERROR_NO_SITENAME",
+ "ERROR_CANT_ACCESS_FILE",
+ "ERROR_CANT_RESOLVE_FILENAME",
+ "ERROR_KM_DRIVER_BLOCKED",
+ "ERROR_CONTEXT_EXPIRED",
+ "ERROR_PER_USER_TRUST_QUOTA_EXCEEDED",
+ "ERROR_ALL_USER_TRUST_QUOTA_EXCEEDED",
+ "ERROR_USER_DELETE_TRUST_QUOTA_EXCEEDED",
+ "ERROR_AUTHENTICATION_FIREWALL_FAILED",
+ "ERROR_REMOTE_PRINT_CONNECTIONS_BLOCKED",
+ "ERROR_NTLM_BLOCKED",
+ "ERROR_PASSWORD_CHANGE_REQUIRED",
+ "ERROR_LOST_MODE_LOGON_RESTRICTION",
+ "ERROR_INVALID_PIXEL_FORMAT",
+ "ERROR_BAD_DRIVER",
+ "ERROR_INVALID_WINDOW_STYLE",
+ "ERROR_METAFILE_NOT_SUPPORTED",
+ "ERROR_TRANSFORM_NOT_SUPPORTED",
+ "ERROR_CLIPPING_NOT_SUPPORTED",
+ "ERROR_INVALID_CMM",
+ "ERROR_INVALID_PROFILE",
+ "ERROR_TAG_NOT_FOUND",
+ "ERROR_TAG_NOT_PRESENT",
+ "ERROR_DUPLICATE_TAG",
+ "ERROR_PROFILE_NOT_ASSOCIATED_WITH_DEVICE",
+ "ERROR_PROFILE_NOT_FOUND",
+ "ERROR_INVALID_COLORSPACE",
+ "ERROR_ICM_NOT_ENABLED",
+ "ERROR_DELETING_ICM_XFORM",
+ "ERROR_INVALID_TRANSFORM",
+ "ERROR_COLORSPACE_MISMATCH",
+ "ERROR_INVALID_COLORINDEX",
+ "ERROR_PROFILE_DOES_NOT_MATCH_DEVICE",
+ "ERROR_CONNECTED_OTHER_PASSWORD",
+ "ERROR_CONNECTED_OTHER_PASSWORD_DEFAULT",
+ "ERROR_BAD_USERNAME",
+ "ERROR_NOT_CONNECTED",
+ "ERROR_OPEN_FILES",
+ "ERROR_ACTIVE_CONNECTIONS",
+ "ERROR_DEVICE_IN_USE",
+ "ERROR_UNKNOWN_PRINT_MONITOR",
+ "ERROR_PRINTER_DRIVER_IN_USE",
+ "ERROR_SPOOL_FILE_NOT_FOUND",
+ "ERROR_SPL_NO_STARTDOC",
+ "ERROR_SPL_NO_ADDJOB",
+ "ERROR_PRINT_PROCESSOR_ALREADY_INSTALLED",
+ "ERROR_PRINT_MONITOR_ALREADY_INSTALLED",
+ "ERROR_INVALID_PRINT_MONITOR",
+ "ERROR_PRINT_MONITOR_IN_USE",
+ "ERROR_PRINTER_HAS_JOBS_QUEUED",
+ "ERROR_SUCCESS_REBOOT_REQUIRED",
+ "ERROR_SUCCESS_RESTART_REQUIRED",
+ "ERROR_PRINTER_NOT_FOUND",
+ "ERROR_PRINTER_DRIVER_WARNED",
+ "ERROR_PRINTER_DRIVER_BLOCKED",
+ "ERROR_PRINTER_DRIVER_PACKAGE_IN_USE",
+ "ERROR_CORE_DRIVER_PACKAGE_NOT_FOUND",
+ "ERROR_FAIL_REBOOT_REQUIRED",
+ "ERROR_FAIL_REBOOT_INITIATED",
+ "ERROR_PRINTER_DRIVER_DOWNLOAD_NEEDED",
+ "ERROR_PRINT_JOB_RESTART_REQUIRED",
+ "ERROR_INVALID_PRINTER_DRIVER_MANIFEST",
+ "ERROR_PRINTER_NOT_SHAREABLE",
+ "ERROR_REQUEST_PAUSED",
+ "ERROR_APPEXEC_CONDITION_NOT_SATISFIED",
+ "ERROR_APPEXEC_HANDLE_INVALIDATED",
+ "ERROR_APPEXEC_INVALID_HOST_GENERATION",
+ "ERROR_APPEXEC_UNEXPECTED_PROCESS_REGISTRATION",
+ "ERROR_APPEXEC_INVALID_HOST_STATE",
+ "ERROR_APPEXEC_NO_DONOR",
+ "ERROR_APPEXEC_HOST_ID_MISMATCH",
+ "ERROR_APPEXEC_UNKNOWN_USER",
+ "ERROR_IO_REISSUE_AS_CACHED",
+ "ERROR_WINS_INTERNAL",
+ "ERROR_CAN_NOT_DEL_LOCAL_WINS",
+ "ERROR_STATIC_INIT",
+ "ERROR_INC_BACKUP",
+ "ERROR_FULL_BACKUP",
+ "ERROR_REC_NON_EXISTENT",
+ "ERROR_RPL_NOT_ALLOWED",
+ "ERROR_DHCP_ADDRESS_CONFLICT",
+ "ERROR_WMI_GUID_NOT_FOUND",
+ "ERROR_WMI_INSTANCE_NOT_FOUND",
+ "ERROR_WMI_ITEMID_NOT_FOUND",
+ "ERROR_WMI_TRY_AGAIN",
+ "ERROR_WMI_DP_NOT_FOUND",
+ "ERROR_WMI_UNRESOLVED_INSTANCE_REF",
+ "ERROR_WMI_ALREADY_ENABLED",
+ "ERROR_WMI_GUID_DISCONNECTED",
+ "ERROR_WMI_SERVER_UNAVAILABLE",
+ "ERROR_WMI_DP_FAILED",
+ "ERROR_WMI_INVALID_MOF",
+ "ERROR_WMI_INVALID_REGINFO",
+ "ERROR_WMI_ALREADY_DISABLED",
+ "ERROR_WMI_READ_ONLY",
+ "ERROR_WMI_SET_FAILURE",
+ "ERROR_NOT_APPCONTAINER",
+ "ERROR_APPCONTAINER_REQUIRED",
+ "ERROR_NOT_SUPPORTED_IN_APPCONTAINER",
+ "ERROR_INVALID_PACKAGE_SID_LENGTH",
+ "ERROR_INVALID_MEDIA",
+ "ERROR_INVALID_LIBRARY",
+ "ERROR_INVALID_MEDIA_POOL",
+ "ERROR_DRIVE_MEDIA_MISMATCH",
+ "ERROR_MEDIA_OFFLINE",
+ "ERROR_LIBRARY_OFFLINE",
+ "ERROR_EMPTY",
+ "ERROR_NOT_EMPTY",
+ "ERROR_MEDIA_UNAVAILABLE",
+ "ERROR_RESOURCE_DISABLED",
+ "ERROR_INVALID_CLEANER",
+ "ERROR_UNABLE_TO_CLEAN",
+ "ERROR_OBJECT_NOT_FOUND",
+ "ERROR_DATABASE_FAILURE",
+ "ERROR_DATABASE_FULL",
+ "ERROR_MEDIA_INCOMPATIBLE",
+ "ERROR_RESOURCE_NOT_PRESENT",
+ "ERROR_INVALID_OPERATION",
+ "ERROR_MEDIA_NOT_AVAILABLE",
+ "ERROR_DEVICE_NOT_AVAILABLE",
+ "ERROR_REQUEST_REFUSED",
+ "ERROR_INVALID_DRIVE_OBJECT",
+ "ERROR_LIBRARY_FULL",
+ "ERROR_MEDIUM_NOT_ACCESSIBLE",
+ "ERROR_UNABLE_TO_LOAD_MEDIUM",
+ "ERROR_UNABLE_TO_INVENTORY_DRIVE",
+ "ERROR_UNABLE_TO_INVENTORY_SLOT",
+ "ERROR_UNABLE_TO_INVENTORY_TRANSPORT",
+ "ERROR_TRANSPORT_FULL",
+ "ERROR_CONTROLLING_IEPORT",
+ "ERROR_UNABLE_TO_EJECT_MOUNTED_MEDIA",
+ "ERROR_CLEANER_SLOT_SET",
+ "ERROR_CLEANER_SLOT_NOT_SET",
+ "ERROR_CLEANER_CARTRIDGE_SPENT",
+ "ERROR_UNEXPECTED_OMID",
+ "ERROR_CANT_DELETE_LAST_ITEM",
+ "ERROR_MESSAGE_EXCEEDS_MAX_SIZE",
+ "ERROR_VOLUME_CONTAINS_SYS_FILES",
+ "ERROR_INDIGENOUS_TYPE",
+ "ERROR_NO_SUPPORTING_DRIVES",
+ "ERROR_CLEANER_CARTRIDGE_INSTALLED",
+ "ERROR_IEPORT_FULL",
+ "ERROR_FILE_OFFLINE",
+ "ERROR_REMOTE_STORAGE_NOT_ACTIVE",
+ "ERROR_REMOTE_STORAGE_MEDIA_ERROR",
+ "ERROR_NOT_A_REPARSE_POINT",
+ "ERROR_REPARSE_ATTRIBUTE_CONFLICT",
+ "ERROR_INVALID_REPARSE_DATA",
+ "ERROR_REPARSE_TAG_INVALID",
+ "ERROR_REPARSE_TAG_MISMATCH",
+ "ERROR_REPARSE_POINT_ENCOUNTERED",
+ "ERROR_APP_DATA_NOT_FOUND",
+ "ERROR_APP_DATA_EXPIRED",
+ "ERROR_APP_DATA_CORRUPT",
+ "ERROR_APP_DATA_LIMIT_EXCEEDED",
+ "ERROR_APP_DATA_REBOOT_REQUIRED",
+ "ERROR_SECUREBOOT_ROLLBACK_DETECTED",
+ "ERROR_SECUREBOOT_POLICY_VIOLATION",
+ "ERROR_SECUREBOOT_INVALID_POLICY",
+ "ERROR_SECUREBOOT_POLICY_PUBLISHER_NOT_FOUND",
+ "ERROR_SECUREBOOT_POLICY_NOT_SIGNED",
+ "ERROR_SECUREBOOT_NOT_ENABLED",
+ "ERROR_SECUREBOOT_FILE_REPLACED",
+ "ERROR_SECUREBOOT_POLICY_NOT_AUTHORIZED",
+ "ERROR_SECUREBOOT_POLICY_UNKNOWN",
+ "ERROR_SECUREBOOT_POLICY_MISSING_ANTIROLLBACKVERSION",
+ "ERROR_SECUREBOOT_PLATFORM_ID_MISMATCH",
+ "ERROR_SECUREBOOT_POLICY_ROLLBACK_DETECTED",
+ "ERROR_SECUREBOOT_POLICY_UPGRADE_MISMATCH",
+ "ERROR_SECUREBOOT_REQUIRED_POLICY_FILE_MISSING",
+ "ERROR_SECUREBOOT_NOT_BASE_POLICY",
+ "ERROR_SECUREBOOT_NOT_SUPPLEMENTAL_POLICY",
+ "ERROR_OFFLOAD_READ_FLT_NOT_SUPPORTED",
+ "ERROR_OFFLOAD_WRITE_FLT_NOT_SUPPORTED",
+ "ERROR_OFFLOAD_READ_FILE_NOT_SUPPORTED",
+ "ERROR_OFFLOAD_WRITE_FILE_NOT_SUPPORTED",
+ "ERROR_ALREADY_HAS_STREAM_ID",
+ "ERROR_SMR_GARBAGE_COLLECTION_REQUIRED",
+ "ERROR_WOF_WIM_HEADER_CORRUPT",
+ "ERROR_WOF_WIM_RESOURCE_TABLE_CORRUPT",
+ "ERROR_WOF_FILE_RESOURCE_TABLE_CORRUPT",
+ "ERROR_VOLUME_NOT_SIS_ENABLED",
+ "ERROR_SYSTEM_INTEGRITY_ROLLBACK_DETECTED",
+ "ERROR_SYSTEM_INTEGRITY_POLICY_VIOLATION",
+ "ERROR_SYSTEM_INTEGRITY_INVALID_POLICY",
+ "ERROR_SYSTEM_INTEGRITY_POLICY_NOT_SIGNED",
+ "ERROR_SYSTEM_INTEGRITY_TOO_MANY_POLICIES",
+ "ERROR_SYSTEM_INTEGRITY_SUPPLEMENTAL_POLICY_NOT_AUTHORIZED",
+ "ERROR_VSM_NOT_INITIALIZED",
+ "ERROR_VSM_DMA_PROTECTION_NOT_IN_USE",
+ "ERROR_PLATFORM_MANIFEST_NOT_AUTHORIZED",
+ "ERROR_PLATFORM_MANIFEST_INVALID",
+ "ERROR_PLATFORM_MANIFEST_FILE_NOT_AUTHORIZED",
+ "ERROR_PLATFORM_MANIFEST_CATALOG_NOT_AUTHORIZED",
+ "ERROR_PLATFORM_MANIFEST_BINARY_ID_NOT_FOUND",
+ "ERROR_PLATFORM_MANIFEST_NOT_ACTIVE",
+ "ERROR_PLATFORM_MANIFEST_NOT_SIGNED",
+ "ERROR_DEPENDENT_RESOURCE_EXISTS",
+ "ERROR_DEPENDENCY_NOT_FOUND",
+ "ERROR_DEPENDENCY_ALREADY_EXISTS",
+ "ERROR_RESOURCE_NOT_ONLINE",
+ "ERROR_HOST_NODE_NOT_AVAILABLE",
+ "ERROR_RESOURCE_NOT_AVAILABLE",
+ "ERROR_RESOURCE_NOT_FOUND",
+ "ERROR_SHUTDOWN_CLUSTER",
+ "ERROR_CANT_EVICT_ACTIVE_NODE",
+ "ERROR_OBJECT_ALREADY_EXISTS",
+ "ERROR_OBJECT_IN_LIST",
+ "ERROR_GROUP_NOT_AVAILABLE",
+ "ERROR_GROUP_NOT_FOUND",
+ "ERROR_GROUP_NOT_ONLINE",
+ "ERROR_HOST_NODE_NOT_RESOURCE_OWNER",
+ "ERROR_HOST_NODE_NOT_GROUP_OWNER",
+ "ERROR_RESMON_CREATE_FAILED",
+ "ERROR_RESMON_ONLINE_FAILED",
+ "ERROR_RESOURCE_ONLINE",
+ "ERROR_QUORUM_RESOURCE",
+ "ERROR_NOT_QUORUM_CAPABLE",
+ "ERROR_CLUSTER_SHUTTING_DOWN",
+ "ERROR_INVALID_STATE",
+ "ERROR_RESOURCE_PROPERTIES_STORED",
+ "ERROR_NOT_QUORUM_CLASS",
+ "ERROR_CORE_RESOURCE",
+ "ERROR_QUORUM_RESOURCE_ONLINE_FAILED",
+ "ERROR_QUORUMLOG_OPEN_FAILED",
+ "ERROR_CLUSTERLOG_CORRUPT",
+ "ERROR_CLUSTERLOG_RECORD_EXCEEDS_MAXSIZE",
+ "ERROR_CLUSTERLOG_EXCEEDS_MAXSIZE",
+ "ERROR_CLUSTERLOG_CHKPOINT_NOT_FOUND",
+ "ERROR_CLUSTERLOG_NOT_ENOUGH_SPACE",
+ "ERROR_QUORUM_OWNER_ALIVE",
+ "ERROR_NETWORK_NOT_AVAILABLE",
+ "ERROR_NODE_NOT_AVAILABLE",
+ "ERROR_ALL_NODES_NOT_AVAILABLE",
+ "ERROR_RESOURCE_FAILED",
+ "ERROR_CLUSTER_INVALID_NODE",
+ "ERROR_CLUSTER_NODE_EXISTS",
+ "ERROR_CLUSTER_JOIN_IN_PROGRESS",
+ "ERROR_CLUSTER_NODE_NOT_FOUND",
+ "ERROR_CLUSTER_LOCAL_NODE_NOT_FOUND",
+ "ERROR_CLUSTER_NETWORK_EXISTS",
+ "ERROR_CLUSTER_NETWORK_NOT_FOUND",
+ "ERROR_CLUSTER_NETINTERFACE_EXISTS",
+ "ERROR_CLUSTER_NETINTERFACE_NOT_FOUND",
+ "ERROR_CLUSTER_INVALID_REQUEST",
+ "ERROR_CLUSTER_INVALID_NETWORK_PROVIDER",
+ "ERROR_CLUSTER_NODE_DOWN",
+ "ERROR_CLUSTER_NODE_UNREACHABLE",
+ "ERROR_CLUSTER_NODE_NOT_MEMBER",
+ "ERROR_CLUSTER_JOIN_NOT_IN_PROGRESS",
+ "ERROR_CLUSTER_INVALID_NETWORK",
+ "ERROR_CLUSTER_NODE_UP",
+ "ERROR_CLUSTER_IPADDR_IN_USE",
+ "ERROR_CLUSTER_NODE_NOT_PAUSED",
+ "ERROR_CLUSTER_NO_SECURITY_CONTEXT",
+ "ERROR_CLUSTER_NETWORK_NOT_INTERNAL",
+ "ERROR_CLUSTER_NODE_ALREADY_UP",
+ "ERROR_CLUSTER_NODE_ALREADY_DOWN",
+ "ERROR_CLUSTER_NETWORK_ALREADY_ONLINE",
+ "ERROR_CLUSTER_NETWORK_ALREADY_OFFLINE",
+ "ERROR_CLUSTER_NODE_ALREADY_MEMBER",
+ "ERROR_CLUSTER_LAST_INTERNAL_NETWORK",
+ "ERROR_CLUSTER_NETWORK_HAS_DEPENDENTS",
+ "ERROR_INVALID_OPERATION_ON_QUORUM",
+ "ERROR_DEPENDENCY_NOT_ALLOWED",
+ "ERROR_CLUSTER_NODE_PAUSED",
+ "ERROR_NODE_CANT_HOST_RESOURCE",
+ "ERROR_CLUSTER_NODE_NOT_READY",
+ "ERROR_CLUSTER_NODE_SHUTTING_DOWN",
+ "ERROR_CLUSTER_JOIN_ABORTED",
+ "ERROR_CLUSTER_INCOMPATIBLE_VERSIONS",
+ "ERROR_CLUSTER_MAXNUM_OF_RESOURCES_EXCEEDED",
+ "ERROR_CLUSTER_SYSTEM_CONFIG_CHANGED",
+ "ERROR_CLUSTER_RESOURCE_TYPE_NOT_FOUND",
+ "ERROR_CLUSTER_RESTYPE_NOT_SUPPORTED",
+ "ERROR_CLUSTER_RESNAME_NOT_FOUND",
+ "ERROR_CLUSTER_NO_RPC_PACKAGES_REGISTERED",
+ "ERROR_CLUSTER_OWNER_NOT_IN_PREFLIST",
+ "ERROR_CLUSTER_DATABASE_SEQMISMATCH",
+ "ERROR_RESMON_INVALID_STATE",
+ "ERROR_CLUSTER_GUM_NOT_LOCKER",
+ "ERROR_QUORUM_DISK_NOT_FOUND",
+ "ERROR_DATABASE_BACKUP_CORRUPT",
+ "ERROR_CLUSTER_NODE_ALREADY_HAS_DFS_ROOT",
+ "ERROR_RESOURCE_PROPERTY_UNCHANGEABLE",
+ "ERROR_NO_ADMIN_ACCESS_POINT",
+ "ERROR_CLUSTER_MEMBERSHIP_INVALID_STATE",
+ "ERROR_CLUSTER_QUORUMLOG_NOT_FOUND",
+ "ERROR_CLUSTER_MEMBERSHIP_HALT",
+ "ERROR_CLUSTER_INSTANCE_ID_MISMATCH",
+ "ERROR_CLUSTER_NETWORK_NOT_FOUND_FOR_IP",
+ "ERROR_CLUSTER_PROPERTY_DATA_TYPE_MISMATCH",
+ "ERROR_CLUSTER_EVICT_WITHOUT_CLEANUP",
+ "ERROR_CLUSTER_PARAMETER_MISMATCH",
+ "ERROR_NODE_CANNOT_BE_CLUSTERED",
+ "ERROR_CLUSTER_WRONG_OS_VERSION",
+ "ERROR_CLUSTER_CANT_CREATE_DUP_CLUSTER_NAME",
+ "ERROR_CLUSCFG_ALREADY_COMMITTED",
+ "ERROR_CLUSCFG_ROLLBACK_FAILED",
+ "ERROR_CLUSCFG_SYSTEM_DISK_DRIVE_LETTER_CONFLICT",
+ "ERROR_CLUSTER_OLD_VERSION",
+ "ERROR_CLUSTER_MISMATCHED_COMPUTER_ACCT_NAME",
+ "ERROR_CLUSTER_NO_NET_ADAPTERS",
+ "ERROR_CLUSTER_POISONED",
+ "ERROR_CLUSTER_GROUP_MOVING",
+ "ERROR_CLUSTER_RESOURCE_TYPE_BUSY",
+ "ERROR_RESOURCE_CALL_TIMED_OUT",
+ "ERROR_INVALID_CLUSTER_IPV6_ADDRESS",
+ "ERROR_CLUSTER_INTERNAL_INVALID_FUNCTION",
+ "ERROR_CLUSTER_PARAMETER_OUT_OF_BOUNDS",
+ "ERROR_CLUSTER_PARTIAL_SEND",
+ "ERROR_CLUSTER_REGISTRY_INVALID_FUNCTION",
+ "ERROR_CLUSTER_INVALID_STRING_TERMINATION",
+ "ERROR_CLUSTER_INVALID_STRING_FORMAT",
+ "ERROR_CLUSTER_DATABASE_TRANSACTION_IN_PROGRESS",
+ "ERROR_CLUSTER_DATABASE_TRANSACTION_NOT_IN_PROGRESS",
+ "ERROR_CLUSTER_NULL_DATA",
+ "ERROR_CLUSTER_PARTIAL_READ",
+ "ERROR_CLUSTER_PARTIAL_WRITE",
+ "ERROR_CLUSTER_CANT_DESERIALIZE_DATA",
+ "ERROR_DEPENDENT_RESOURCE_PROPERTY_CONFLICT",
+ "ERROR_CLUSTER_NO_QUORUM",
+ "ERROR_CLUSTER_INVALID_IPV6_NETWORK",
+ "ERROR_CLUSTER_INVALID_IPV6_TUNNEL_NETWORK",
+ "ERROR_QUORUM_NOT_ALLOWED_IN_THIS_GROUP",
+ "ERROR_DEPENDENCY_TREE_TOO_COMPLEX",
+ "ERROR_EXCEPTION_IN_RESOURCE_CALL",
+ "ERROR_CLUSTER_RHS_FAILED_INITIALIZATION",
+ "ERROR_CLUSTER_NOT_INSTALLED",
+ "ERROR_CLUSTER_RESOURCES_MUST_BE_ONLINE_ON_THE_SAME_NODE",
+ "ERROR_CLUSTER_MAX_NODES_IN_CLUSTER",
+ "ERROR_CLUSTER_TOO_MANY_NODES",
+ "ERROR_CLUSTER_OBJECT_ALREADY_USED",
+ "ERROR_NONCORE_GROUPS_FOUND",
+ "ERROR_FILE_SHARE_RESOURCE_CONFLICT",
+ "ERROR_CLUSTER_EVICT_INVALID_REQUEST",
+ "ERROR_CLUSTER_SINGLETON_RESOURCE",
+ "ERROR_CLUSTER_GROUP_SINGLETON_RESOURCE",
+ "ERROR_CLUSTER_RESOURCE_PROVIDER_FAILED",
+ "ERROR_CLUSTER_RESOURCE_CONFIGURATION_ERROR",
+ "ERROR_CLUSTER_GROUP_BUSY",
+ "ERROR_CLUSTER_NOT_SHARED_VOLUME",
+ "ERROR_CLUSTER_INVALID_SECURITY_DESCRIPTOR",
+ "ERROR_CLUSTER_SHARED_VOLUMES_IN_USE",
+ "ERROR_CLUSTER_USE_SHARED_VOLUMES_API",
+ "ERROR_CLUSTER_BACKUP_IN_PROGRESS",
+ "ERROR_NON_CSV_PATH",
+ "ERROR_CSV_VOLUME_NOT_LOCAL",
+ "ERROR_CLUSTER_WATCHDOG_TERMINATING",
+ "ERROR_CLUSTER_RESOURCE_VETOED_MOVE_INCOMPATIBLE_NODES",
+ "ERROR_CLUSTER_INVALID_NODE_WEIGHT",
+ "ERROR_CLUSTER_RESOURCE_VETOED_CALL",
+ "ERROR_RESMON_SYSTEM_RESOURCES_LACKING",
+ "ERROR_CLUSTER_RESOURCE_VETOED_MOVE_NOT_ENOUGH_RESOURCES_ON_DESTINATION",
+ "ERROR_CLUSTER_RESOURCE_VETOED_MOVE_NOT_ENOUGH_RESOURCES_ON_SOURCE",
+ "ERROR_CLUSTER_GROUP_QUEUED",
+ "ERROR_CLUSTER_RESOURCE_LOCKED_STATUS",
+ "ERROR_CLUSTER_SHARED_VOLUME_FAILOVER_NOT_ALLOWED",
+ "ERROR_CLUSTER_NODE_DRAIN_IN_PROGRESS",
+ "ERROR_CLUSTER_DISK_NOT_CONNECTED",
+ "ERROR_DISK_NOT_CSV_CAPABLE",
+ "ERROR_RESOURCE_NOT_IN_AVAILABLE_STORAGE",
+ "ERROR_CLUSTER_SHARED_VOLUME_REDIRECTED",
+ "ERROR_CLUSTER_SHARED_VOLUME_NOT_REDIRECTED",
+ "ERROR_CLUSTER_CANNOT_RETURN_PROPERTIES",
+ "ERROR_CLUSTER_RESOURCE_CONTAINS_UNSUPPORTED_DIFF_AREA_FOR_SHARED_VOLUMES",
+ "ERROR_CLUSTER_RESOURCE_IS_IN_MAINTENANCE_MODE",
+ "ERROR_CLUSTER_AFFINITY_CONFLICT",
+ "ERROR_CLUSTER_RESOURCE_IS_REPLICA_VIRTUAL_MACHINE",
+ "ERROR_CLUSTER_UPGRADE_INCOMPATIBLE_VERSIONS",
+ "ERROR_CLUSTER_UPGRADE_FIX_QUORUM_NOT_SUPPORTED",
+ "ERROR_CLUSTER_UPGRADE_RESTART_REQUIRED",
+ "ERROR_CLUSTER_UPGRADE_IN_PROGRESS",
+ "ERROR_CLUSTER_UPGRADE_INCOMPLETE",
+ "ERROR_CLUSTER_NODE_IN_GRACE_PERIOD",
+ "ERROR_CLUSTER_CSV_IO_PAUSE_TIMEOUT",
+ "ERROR_NODE_NOT_ACTIVE_CLUSTER_MEMBER",
+ "ERROR_CLUSTER_RESOURCE_NOT_MONITORED",
+ "ERROR_CLUSTER_RESOURCE_DOES_NOT_SUPPORT_UNMONITORED",
+ "ERROR_CLUSTER_RESOURCE_IS_REPLICATED",
+ "ERROR_CLUSTER_NODE_ISOLATED",
+ "ERROR_CLUSTER_NODE_QUARANTINED",
+ "ERROR_CLUSTER_DATABASE_UPDATE_CONDITION_FAILED",
+ "ERROR_CLUSTER_SPACE_DEGRADED",
+ "ERROR_CLUSTER_TOKEN_DELEGATION_NOT_SUPPORTED",
+ "ERROR_CLUSTER_CSV_INVALID_HANDLE",
+ "ERROR_CLUSTER_CSV_SUPPORTED_ONLY_ON_COORDINATOR",
+ "ERROR_GROUPSET_NOT_AVAILABLE",
+ "ERROR_GROUPSET_NOT_FOUND",
+ "ERROR_GROUPSET_CANT_PROVIDE",
+ "ERROR_CLUSTER_FAULT_DOMAIN_PARENT_NOT_FOUND",
+ "ERROR_CLUSTER_FAULT_DOMAIN_INVALID_HIERARCHY",
+ "ERROR_CLUSTER_FAULT_DOMAIN_FAILED_S2D_VALIDATION",
+ "ERROR_CLUSTER_FAULT_DOMAIN_S2D_CONNECTIVITY_LOSS",
+ "ERROR_CLUSTER_INVALID_INFRASTRUCTURE_FILESERVER_NAME",
+ "ERROR_CLUSTERSET_MANAGEMENT_CLUSTER_UNREACHABLE",
+ "ERROR_ENCRYPTION_FAILED",
+ "ERROR_DECRYPTION_FAILED",
+ "ERROR_FILE_ENCRYPTED",
+ "ERROR_NO_RECOVERY_POLICY",
+ "ERROR_NO_EFS",
+ "ERROR_WRONG_EFS",
+ "ERROR_NO_USER_KEYS",
+ "ERROR_FILE_NOT_ENCRYPTED",
+ "ERROR_NOT_EXPORT_FORMAT",
+ "ERROR_FILE_READ_ONLY",
+ "ERROR_DIR_EFS_DISALLOWED",
+ "ERROR_EFS_SERVER_NOT_TRUSTED",
+ "ERROR_BAD_RECOVERY_POLICY",
+ "ERROR_EFS_ALG_BLOB_TOO_BIG",
+ "ERROR_VOLUME_NOT_SUPPORT_EFS",
+ "ERROR_EFS_DISABLED",
+ "ERROR_EFS_VERSION_NOT_SUPPORT",
+ "ERROR_CS_ENCRYPTION_INVALID_SERVER_RESPONSE",
+ "ERROR_CS_ENCRYPTION_UNSUPPORTED_SERVER",
+ "ERROR_CS_ENCRYPTION_EXISTING_ENCRYPTED_FILE",
+ "ERROR_CS_ENCRYPTION_NEW_ENCRYPTED_FILE",
+ "ERROR_CS_ENCRYPTION_FILE_NOT_CSE",
+ "ERROR_ENCRYPTION_POLICY_DENIES_OPERATION",
+ "ERROR_WIP_ENCRYPTION_FAILED",
+ "ERROR_NO_BROWSER_SERVERS_FOUND",
+ "ERROR_CLUSTER_OBJECT_IS_CLUSTER_SET_VM",
+ "ERROR_LOG_SECTOR_INVALID",
+ "ERROR_LOG_SECTOR_PARITY_INVALID",
+ "ERROR_LOG_SECTOR_REMAPPED",
+ "ERROR_LOG_BLOCK_INCOMPLETE",
+ "ERROR_LOG_INVALID_RANGE",
+ "ERROR_LOG_BLOCKS_EXHAUSTED",
+ "ERROR_LOG_READ_CONTEXT_INVALID",
+ "ERROR_LOG_RESTART_INVALID",
+ "ERROR_LOG_BLOCK_VERSION",
+ "ERROR_LOG_BLOCK_INVALID",
+ "ERROR_LOG_READ_MODE_INVALID",
+ "ERROR_LOG_NO_RESTART",
+ "ERROR_LOG_METADATA_CORRUPT",
+ "ERROR_LOG_METADATA_INVALID",
+ "ERROR_LOG_METADATA_INCONSISTENT",
+ "ERROR_LOG_RESERVATION_INVALID",
+ "ERROR_LOG_CANT_DELETE",
+ "ERROR_LOG_CONTAINER_LIMIT_EXCEEDED",
+ "ERROR_LOG_START_OF_LOG",
+ "ERROR_LOG_POLICY_ALREADY_INSTALLED",
+ "ERROR_LOG_POLICY_NOT_INSTALLED",
+ "ERROR_LOG_POLICY_INVALID",
+ "ERROR_LOG_POLICY_CONFLICT",
+ "ERROR_LOG_PINNED_ARCHIVE_TAIL",
+ "ERROR_LOG_RECORD_NONEXISTENT",
+ "ERROR_LOG_RECORDS_RESERVED_INVALID",
+ "ERROR_LOG_SPACE_RESERVED_INVALID",
+ "ERROR_LOG_TAIL_INVALID",
+ "ERROR_LOG_FULL",
+ "ERROR_COULD_NOT_RESIZE_LOG",
+ "ERROR_LOG_MULTIPLEXED",
+ "ERROR_LOG_DEDICATED",
+ "ERROR_LOG_ARCHIVE_NOT_IN_PROGRESS",
+ "ERROR_LOG_ARCHIVE_IN_PROGRESS",
+ "ERROR_LOG_EPHEMERAL",
+ "ERROR_LOG_NOT_ENOUGH_CONTAINERS",
+ "ERROR_LOG_CLIENT_ALREADY_REGISTERED",
+ "ERROR_LOG_CLIENT_NOT_REGISTERED",
+ "ERROR_LOG_FULL_HANDLER_IN_PROGRESS",
+ "ERROR_LOG_CONTAINER_READ_FAILED",
+ "ERROR_LOG_CONTAINER_WRITE_FAILED",
+ "ERROR_LOG_CONTAINER_OPEN_FAILED",
+ "ERROR_LOG_CONTAINER_STATE_INVALID",
+ "ERROR_LOG_STATE_INVALID",
+ "ERROR_LOG_PINNED",
+ "ERROR_LOG_METADATA_FLUSH_FAILED",
+ "ERROR_LOG_INCONSISTENT_SECURITY",
+ "ERROR_LOG_APPENDED_FLUSH_FAILED",
+ "ERROR_LOG_PINNED_RESERVATION",
+ "ERROR_INVALID_TRANSACTION",
+ "ERROR_TRANSACTION_NOT_ACTIVE",
+ "ERROR_TRANSACTION_REQUEST_NOT_VALID",
+ "ERROR_TRANSACTION_NOT_REQUESTED",
+ "ERROR_TRANSACTION_ALREADY_ABORTED",
+ "ERROR_TRANSACTION_ALREADY_COMMITTED",
+ "ERROR_TM_INITIALIZATION_FAILED",
+ "ERROR_RESOURCEMANAGER_READ_ONLY",
+ "ERROR_TRANSACTION_NOT_JOINED",
+ "ERROR_TRANSACTION_SUPERIOR_EXISTS",
+ "ERROR_CRM_PROTOCOL_ALREADY_EXISTS",
+ "ERROR_TRANSACTION_PROPAGATION_FAILED",
+ "ERROR_CRM_PROTOCOL_NOT_FOUND",
+ "ERROR_TRANSACTION_INVALID_MARSHALL_BUFFER",
+ "ERROR_CURRENT_TRANSACTION_NOT_VALID",
+ "ERROR_TRANSACTION_NOT_FOUND",
+ "ERROR_RESOURCEMANAGER_NOT_FOUND",
+ "ERROR_ENLISTMENT_NOT_FOUND",
+ "ERROR_TRANSACTIONMANAGER_NOT_FOUND",
+ "ERROR_TRANSACTIONMANAGER_NOT_ONLINE",
+ "ERROR_TRANSACTIONMANAGER_RECOVERY_NAME_COLLISION",
+ "ERROR_TRANSACTION_NOT_ROOT",
+ "ERROR_TRANSACTION_OBJECT_EXPIRED",
+ "ERROR_TRANSACTION_RESPONSE_NOT_ENLISTED",
+ "ERROR_TRANSACTION_RECORD_TOO_LONG",
+ "ERROR_IMPLICIT_TRANSACTION_NOT_SUPPORTED",
+ "ERROR_TRANSACTION_INTEGRITY_VIOLATED",
+ "ERROR_TRANSACTIONMANAGER_IDENTITY_MISMATCH",
+ "ERROR_RM_CANNOT_BE_FROZEN_FOR_SNAPSHOT",
+ "ERROR_TRANSACTION_MUST_WRITETHROUGH",
+ "ERROR_TRANSACTION_NO_SUPERIOR",
+ "ERROR_HEURISTIC_DAMAGE_POSSIBLE",
+ "ERROR_TRANSACTIONAL_CONFLICT",
+ "ERROR_RM_NOT_ACTIVE",
+ "ERROR_RM_METADATA_CORRUPT",
+ "ERROR_DIRECTORY_NOT_RM",
+ "ERROR_TRANSACTIONS_UNSUPPORTED_REMOTE",
+ "ERROR_LOG_RESIZE_INVALID_SIZE",
+ "ERROR_OBJECT_NO_LONGER_EXISTS",
+ "ERROR_STREAM_MINIVERSION_NOT_FOUND",
+ "ERROR_STREAM_MINIVERSION_NOT_VALID",
+ "ERROR_MINIVERSION_INACCESSIBLE_FROM_SPECIFIED_TRANSACTION",
+ "ERROR_CANT_OPEN_MINIVERSION_WITH_MODIFY_INTENT",
+ "ERROR_CANT_CREATE_MORE_STREAM_MINIVERSIONS",
+ "ERROR_REMOTE_FILE_VERSION_MISMATCH",
+ "ERROR_HANDLE_NO_LONGER_VALID",
+ "ERROR_NO_TXF_METADATA",
+ "ERROR_LOG_CORRUPTION_DETECTED",
+ "ERROR_CANT_RECOVER_WITH_HANDLE_OPEN",
+ "ERROR_RM_DISCONNECTED",
+ "ERROR_ENLISTMENT_NOT_SUPERIOR",
+ "ERROR_RECOVERY_NOT_NEEDED",
+ "ERROR_RM_ALREADY_STARTED",
+ "ERROR_FILE_IDENTITY_NOT_PERSISTENT",
+ "ERROR_CANT_BREAK_TRANSACTIONAL_DEPENDENCY",
+ "ERROR_CANT_CROSS_RM_BOUNDARY",
+ "ERROR_TXF_DIR_NOT_EMPTY",
+ "ERROR_INDOUBT_TRANSACTIONS_EXIST",
+ "ERROR_TM_VOLATILE",
+ "ERROR_ROLLBACK_TIMER_EXPIRED",
+ "ERROR_TXF_ATTRIBUTE_CORRUPT",
+ "ERROR_EFS_NOT_ALLOWED_IN_TRANSACTION",
+ "ERROR_TRANSACTIONAL_OPEN_NOT_ALLOWED",
+ "ERROR_LOG_GROWTH_FAILED",
+ "ERROR_TRANSACTED_MAPPING_UNSUPPORTED_REMOTE",
+ "ERROR_TXF_METADATA_ALREADY_PRESENT",
+ "ERROR_TRANSACTION_SCOPE_CALLBACKS_NOT_SET",
+ "ERROR_TRANSACTION_REQUIRED_PROMOTION",
+ "ERROR_CANNOT_EXECUTE_FILE_IN_TRANSACTION",
+ "ERROR_TRANSACTIONS_NOT_FROZEN",
+ "ERROR_TRANSACTION_FREEZE_IN_PROGRESS",
+ "ERROR_NOT_SNAPSHOT_VOLUME",
+ "ERROR_NO_SAVEPOINT_WITH_OPEN_FILES",
+ "ERROR_DATA_LOST_REPAIR",
+ "ERROR_SPARSE_NOT_ALLOWED_IN_TRANSACTION",
+ "ERROR_TM_IDENTITY_MISMATCH",
+ "ERROR_FLOATED_SECTION",
+ "ERROR_CANNOT_ACCEPT_TRANSACTED_WORK",
+ "ERROR_CANNOT_ABORT_TRANSACTIONS",
+ "ERROR_BAD_CLUSTERS",
+ "ERROR_COMPRESSION_NOT_ALLOWED_IN_TRANSACTION",
+ "ERROR_VOLUME_DIRTY",
+ "ERROR_NO_LINK_TRACKING_IN_TRANSACTION",
+ "ERROR_OPERATION_NOT_SUPPORTED_IN_TRANSACTION",
+ "ERROR_EXPIRED_HANDLE",
+ "ERROR_TRANSACTION_NOT_ENLISTED",
+ "ERROR_CTX_WINSTATION_NAME_INVALID",
+ "ERROR_CTX_INVALID_PD",
+ "ERROR_CTX_PD_NOT_FOUND",
+ "ERROR_CTX_WD_NOT_FOUND",
+ "ERROR_CTX_CANNOT_MAKE_EVENTLOG_ENTRY",
+ "ERROR_CTX_SERVICE_NAME_COLLISION",
+ "ERROR_CTX_CLOSE_PENDING",
+ "ERROR_CTX_NO_OUTBUF",
+ "ERROR_CTX_MODEM_INF_NOT_FOUND",
+ "ERROR_CTX_INVALID_MODEMNAME",
+ "ERROR_CTX_MODEM_RESPONSE_ERROR",
+ "ERROR_CTX_MODEM_RESPONSE_TIMEOUT",
+ "ERROR_CTX_MODEM_RESPONSE_NO_CARRIER",
+ "ERROR_CTX_MODEM_RESPONSE_NO_DIALTONE",
+ "ERROR_CTX_MODEM_RESPONSE_BUSY",
+ "ERROR_CTX_MODEM_RESPONSE_VOICE",
+ "ERROR_CTX_TD_ERROR",
+ "ERROR_CTX_WINSTATION_NOT_FOUND",
+ "ERROR_CTX_WINSTATION_ALREADY_EXISTS",
+ "ERROR_CTX_WINSTATION_BUSY",
+ "ERROR_CTX_BAD_VIDEO_MODE",
+ "ERROR_CTX_GRAPHICS_INVALID",
+ "ERROR_CTX_LOGON_DISABLED",
+ "ERROR_CTX_NOT_CONSOLE",
+ "ERROR_CTX_CLIENT_QUERY_TIMEOUT",
+ "ERROR_CTX_CONSOLE_DISCONNECT",
+ "ERROR_CTX_CONSOLE_CONNECT",
+ "ERROR_CTX_SHADOW_DENIED",
+ "ERROR_CTX_WINSTATION_ACCESS_DENIED",
+ "ERROR_CTX_INVALID_WD",
+ "ERROR_CTX_SHADOW_INVALID",
+ "ERROR_CTX_SHADOW_DISABLED",
+ "ERROR_CTX_CLIENT_LICENSE_IN_USE",
+ "ERROR_CTX_CLIENT_LICENSE_NOT_SET",
+ "ERROR_CTX_LICENSE_NOT_AVAILABLE",
+ "ERROR_CTX_LICENSE_CLIENT_INVALID",
+ "ERROR_CTX_LICENSE_EXPIRED",
+ "ERROR_CTX_SHADOW_NOT_RUNNING",
+ "ERROR_CTX_SHADOW_ENDED_BY_MODE_CHANGE",
+ "ERROR_ACTIVATION_COUNT_EXCEEDED",
+ "ERROR_CTX_WINSTATIONS_DISABLED",
+ "ERROR_CTX_ENCRYPTION_LEVEL_REQUIRED",
+ "ERROR_CTX_SESSION_IN_USE",
+ "ERROR_CTX_NO_FORCE_LOGOFF",
+ "ERROR_CTX_ACCOUNT_RESTRICTION",
+ "ERROR_RDP_PROTOCOL_ERROR",
+ "ERROR_CTX_CDM_CONNECT",
+ "ERROR_CTX_CDM_DISCONNECT",
+ "ERROR_CTX_SECURITY_LAYER_ERROR",
+ "ERROR_TS_INCOMPATIBLE_SESSIONS",
+ "ERROR_TS_VIDEO_SUBSYSTEM_ERROR",
+ "ERROR_DS_NOT_INSTALLED",
+ "ERROR_DS_MEMBERSHIP_EVALUATED_LOCALLY",
+ "ERROR_DS_NO_ATTRIBUTE_OR_VALUE",
+ "ERROR_DS_INVALID_ATTRIBUTE_SYNTAX",
+ "ERROR_DS_ATTRIBUTE_TYPE_UNDEFINED",
+ "ERROR_DS_ATTRIBUTE_OR_VALUE_EXISTS",
+ "ERROR_DS_BUSY",
+ "ERROR_DS_UNAVAILABLE",
+ "ERROR_DS_NO_RIDS_ALLOCATED",
+ "ERROR_DS_NO_MORE_RIDS",
+ "ERROR_DS_INCORRECT_ROLE_OWNER",
+ "ERROR_DS_RIDMGR_INIT_ERROR",
+ "ERROR_DS_OBJ_CLASS_VIOLATION",
+ "ERROR_DS_CANT_ON_NON_LEAF",
+ "ERROR_DS_CANT_ON_RDN",
+ "ERROR_DS_CANT_MOD_OBJ_CLASS",
+ "ERROR_DS_CROSS_DOM_MOVE_ERROR",
+ "ERROR_DS_GC_NOT_AVAILABLE",
+ "ERROR_SHARED_POLICY",
+ "ERROR_POLICY_OBJECT_NOT_FOUND",
+ "ERROR_POLICY_ONLY_IN_DS",
+ "ERROR_PROMOTION_ACTIVE",
+ "ERROR_NO_PROMOTION_ACTIVE",
+ "ERROR_DS_OPERATIONS_ERROR",
+ "ERROR_DS_PROTOCOL_ERROR",
+ "ERROR_DS_TIMELIMIT_EXCEEDED",
+ "ERROR_DS_SIZELIMIT_EXCEEDED",
+ "ERROR_DS_ADMIN_LIMIT_EXCEEDED",
+ "ERROR_DS_COMPARE_FALSE",
+ "ERROR_DS_COMPARE_TRUE",
+ "ERROR_DS_AUTH_METHOD_NOT_SUPPORTED",
+ "ERROR_DS_STRONG_AUTH_REQUIRED",
+ "ERROR_DS_INAPPROPRIATE_AUTH",
+ "ERROR_DS_AUTH_UNKNOWN",
+ "ERROR_DS_REFERRAL",
+ "ERROR_DS_UNAVAILABLE_CRIT_EXTENSION",
+ "ERROR_DS_CONFIDENTIALITY_REQUIRED",
+ "ERROR_DS_INAPPROPRIATE_MATCHING",
+ "ERROR_DS_CONSTRAINT_VIOLATION",
+ "ERROR_DS_NO_SUCH_OBJECT",
+ "ERROR_DS_ALIAS_PROBLEM",
+ "ERROR_DS_INVALID_DN_SYNTAX",
+ "ERROR_DS_IS_LEAF",
+ "ERROR_DS_ALIAS_DEREF_PROBLEM",
+ "ERROR_DS_UNWILLING_TO_PERFORM",
+ "ERROR_DS_LOOP_DETECT",
+ "ERROR_DS_NAMING_VIOLATION",
+ "ERROR_DS_OBJECT_RESULTS_TOO_LARGE",
+ "ERROR_DS_AFFECTS_MULTIPLE_DSAS",
+ "ERROR_DS_SERVER_DOWN",
+ "ERROR_DS_LOCAL_ERROR",
+ "ERROR_DS_ENCODING_ERROR",
+ "ERROR_DS_DECODING_ERROR",
+ "ERROR_DS_FILTER_UNKNOWN",
+ "ERROR_DS_PARAM_ERROR",
+ "ERROR_DS_NOT_SUPPORTED",
+ "ERROR_DS_NO_RESULTS_RETURNED",
+ "ERROR_DS_CONTROL_NOT_FOUND",
+ "ERROR_DS_CLIENT_LOOP",
+ "ERROR_DS_REFERRAL_LIMIT_EXCEEDED",
+ "ERROR_DS_SORT_CONTROL_MISSING",
+ "ERROR_DS_OFFSET_RANGE_ERROR",
+ "ERROR_DS_RIDMGR_DISABLED",
+ "ERROR_DS_ROOT_MUST_BE_NC",
+ "ERROR_DS_ADD_REPLICA_INHIBITED",
+ "ERROR_DS_ATT_NOT_DEF_IN_SCHEMA",
+ "ERROR_DS_MAX_OBJ_SIZE_EXCEEDED",
+ "ERROR_DS_OBJ_STRING_NAME_EXISTS",
+ "ERROR_DS_NO_RDN_DEFINED_IN_SCHEMA",
+ "ERROR_DS_RDN_DOESNT_MATCH_SCHEMA",
+ "ERROR_DS_NO_REQUESTED_ATTS_FOUND",
+ "ERROR_DS_USER_BUFFER_TO_SMALL",
+ "ERROR_DS_ATT_IS_NOT_ON_OBJ",
+ "ERROR_DS_ILLEGAL_MOD_OPERATION",
+ "ERROR_DS_OBJ_TOO_LARGE",
+ "ERROR_DS_BAD_INSTANCE_TYPE",
+ "ERROR_DS_MASTERDSA_REQUIRED",
+ "ERROR_DS_OBJECT_CLASS_REQUIRED",
+ "ERROR_DS_MISSING_REQUIRED_ATT",
+ "ERROR_DS_ATT_NOT_DEF_FOR_CLASS",
+ "ERROR_DS_ATT_ALREADY_EXISTS",
+ "ERROR_DS_CANT_ADD_ATT_VALUES",
+ "ERROR_DS_SINGLE_VALUE_CONSTRAINT",
+ "ERROR_DS_RANGE_CONSTRAINT",
+ "ERROR_DS_ATT_VAL_ALREADY_EXISTS",
+ "ERROR_DS_CANT_REM_MISSING_ATT",
+ "ERROR_DS_CANT_REM_MISSING_ATT_VAL",
+ "ERROR_DS_ROOT_CANT_BE_SUBREF",
+ "ERROR_DS_NO_CHAINING",
+ "ERROR_DS_NO_CHAINED_EVAL",
+ "ERROR_DS_NO_PARENT_OBJECT",
+ "ERROR_DS_PARENT_IS_AN_ALIAS",
+ "ERROR_DS_CANT_MIX_MASTER_AND_REPS",
+ "ERROR_DS_CHILDREN_EXIST",
+ "ERROR_DS_OBJ_NOT_FOUND",
+ "ERROR_DS_ALIASED_OBJ_MISSING",
+ "ERROR_DS_BAD_NAME_SYNTAX",
+ "ERROR_DS_ALIAS_POINTS_TO_ALIAS",
+ "ERROR_DS_CANT_DEREF_ALIAS",
+ "ERROR_DS_OUT_OF_SCOPE",
+ "ERROR_DS_OBJECT_BEING_REMOVED",
+ "ERROR_DS_CANT_DELETE_DSA_OBJ",
+ "ERROR_DS_GENERIC_ERROR",
+ "ERROR_DS_DSA_MUST_BE_INT_MASTER",
+ "ERROR_DS_CLASS_NOT_DSA",
+ "ERROR_DS_INSUFF_ACCESS_RIGHTS",
+ "ERROR_DS_ILLEGAL_SUPERIOR",
+ "ERROR_DS_ATTRIBUTE_OWNED_BY_SAM",
+ "ERROR_DS_NAME_TOO_MANY_PARTS",
+ "ERROR_DS_NAME_TOO_LONG",
+ "ERROR_DS_NAME_VALUE_TOO_LONG",
+ "ERROR_DS_NAME_UNPARSEABLE",
+ "ERROR_DS_NAME_TYPE_UNKNOWN",
+ "ERROR_DS_NOT_AN_OBJECT",
+ "ERROR_DS_SEC_DESC_TOO_SHORT",
+ "ERROR_DS_SEC_DESC_INVALID",
+ "ERROR_DS_NO_DELETED_NAME",
+ "ERROR_DS_SUBREF_MUST_HAVE_PARENT",
+ "ERROR_DS_NCNAME_MUST_BE_NC",
+ "ERROR_DS_CANT_ADD_SYSTEM_ONLY",
+ "ERROR_DS_CLASS_MUST_BE_CONCRETE",
+ "ERROR_DS_INVALID_DMD",
+ "ERROR_DS_OBJ_GUID_EXISTS",
+ "ERROR_DS_NOT_ON_BACKLINK",
+ "ERROR_DS_NO_CROSSREF_FOR_NC",
+ "ERROR_DS_SHUTTING_DOWN",
+ "ERROR_DS_UNKNOWN_OPERATION",
+ "ERROR_DS_INVALID_ROLE_OWNER",
+ "ERROR_DS_COULDNT_CONTACT_FSMO",
+ "ERROR_DS_CROSS_NC_DN_RENAME",
+ "ERROR_DS_CANT_MOD_SYSTEM_ONLY",
+ "ERROR_DS_REPLICATOR_ONLY",
+ "ERROR_DS_OBJ_CLASS_NOT_DEFINED",
+ "ERROR_DS_OBJ_CLASS_NOT_SUBCLASS",
+ "ERROR_DS_NAME_REFERENCE_INVALID",
+ "ERROR_DS_CROSS_REF_EXISTS",
+ "ERROR_DS_CANT_DEL_MASTER_CROSSREF",
+ "ERROR_DS_SUBTREE_NOTIFY_NOT_NC_HEAD",
+ "ERROR_DS_NOTIFY_FILTER_TOO_COMPLEX",
+ "ERROR_DS_DUP_RDN",
+ "ERROR_DS_DUP_OID",
+ "ERROR_DS_DUP_MAPI_ID",
+ "ERROR_DS_DUP_SCHEMA_ID_GUID",
+ "ERROR_DS_DUP_LDAP_DISPLAY_NAME",
+ "ERROR_DS_SEMANTIC_ATT_TEST",
+ "ERROR_DS_SYNTAX_MISMATCH",
+ "ERROR_DS_EXISTS_IN_MUST_HAVE",
+ "ERROR_DS_EXISTS_IN_MAY_HAVE",
+ "ERROR_DS_NONEXISTENT_MAY_HAVE",
+ "ERROR_DS_NONEXISTENT_MUST_HAVE",
+ "ERROR_DS_AUX_CLS_TEST_FAIL",
+ "ERROR_DS_NONEXISTENT_POSS_SUP",
+ "ERROR_DS_SUB_CLS_TEST_FAIL",
+ "ERROR_DS_BAD_RDN_ATT_ID_SYNTAX",
+ "ERROR_DS_EXISTS_IN_AUX_CLS",
+ "ERROR_DS_EXISTS_IN_SUB_CLS",
+ "ERROR_DS_EXISTS_IN_POSS_SUP",
+ "ERROR_DS_RECALCSCHEMA_FAILED",
+ "ERROR_DS_TREE_DELETE_NOT_FINISHED",
+ "ERROR_DS_CANT_DELETE",
+ "ERROR_DS_ATT_SCHEMA_REQ_ID",
+ "ERROR_DS_BAD_ATT_SCHEMA_SYNTAX",
+ "ERROR_DS_CANT_CACHE_ATT",
+ "ERROR_DS_CANT_CACHE_CLASS",
+ "ERROR_DS_CANT_REMOVE_ATT_CACHE",
+ "ERROR_DS_CANT_REMOVE_CLASS_CACHE",
+ "ERROR_DS_CANT_RETRIEVE_DN",
+ "ERROR_DS_MISSING_SUPREF",
+ "ERROR_DS_CANT_RETRIEVE_INSTANCE",
+ "ERROR_DS_CODE_INCONSISTENCY",
+ "ERROR_DS_DATABASE_ERROR",
+ "ERROR_DS_GOVERNSID_MISSING",
+ "ERROR_DS_MISSING_EXPECTED_ATT",
+ "ERROR_DS_NCNAME_MISSING_CR_REF",
+ "ERROR_DS_SECURITY_CHECKING_ERROR",
+ "ERROR_DS_SCHEMA_NOT_LOADED",
+ "ERROR_DS_SCHEMA_ALLOC_FAILED",
+ "ERROR_DS_ATT_SCHEMA_REQ_SYNTAX",
+ "ERROR_DS_GCVERIFY_ERROR",
+ "ERROR_DS_DRA_SCHEMA_MISMATCH",
+ "ERROR_DS_CANT_FIND_DSA_OBJ",
+ "ERROR_DS_CANT_FIND_EXPECTED_NC",
+ "ERROR_DS_CANT_FIND_NC_IN_CACHE",
+ "ERROR_DS_CANT_RETRIEVE_CHILD",
+ "ERROR_DS_SECURITY_ILLEGAL_MODIFY",
+ "ERROR_DS_CANT_REPLACE_HIDDEN_REC",
+ "ERROR_DS_BAD_HIERARCHY_FILE",
+ "ERROR_DS_BUILD_HIERARCHY_TABLE_FAILED",
+ "ERROR_DS_CONFIG_PARAM_MISSING",
+ "ERROR_DS_COUNTING_AB_INDICES_FAILED",
+ "ERROR_DS_HIERARCHY_TABLE_MALLOC_FAILED",
+ "ERROR_DS_INTERNAL_FAILURE",
+ "ERROR_DS_UNKNOWN_ERROR",
+ "ERROR_DS_ROOT_REQUIRES_CLASS_TOP",
+ "ERROR_DS_REFUSING_FSMO_ROLES",
+ "ERROR_DS_MISSING_FSMO_SETTINGS",
+ "ERROR_DS_UNABLE_TO_SURRENDER_ROLES",
+ "ERROR_DS_DRA_GENERIC",
+ "ERROR_DS_DRA_INVALID_PARAMETER",
+ "ERROR_DS_DRA_BUSY",
+ "ERROR_DS_DRA_BAD_DN",
+ "ERROR_DS_DRA_BAD_NC",
+ "ERROR_DS_DRA_DN_EXISTS",
+ "ERROR_DS_DRA_INTERNAL_ERROR",
+ "ERROR_DS_DRA_INCONSISTENT_DIT",
+ "ERROR_DS_DRA_CONNECTION_FAILED",
+ "ERROR_DS_DRA_BAD_INSTANCE_TYPE",
+ "ERROR_DS_DRA_OUT_OF_MEM",
+ "ERROR_DS_DRA_MAIL_PROBLEM",
+ "ERROR_DS_DRA_REF_ALREADY_EXISTS",
+ "ERROR_DS_DRA_REF_NOT_FOUND",
+ "ERROR_DS_DRA_OBJ_IS_REP_SOURCE",
+ "ERROR_DS_DRA_DB_ERROR",
+ "ERROR_DS_DRA_NO_REPLICA",
+ "ERROR_DS_DRA_ACCESS_DENIED",
+ "ERROR_DS_DRA_NOT_SUPPORTED",
+ "ERROR_DS_DRA_RPC_CANCELLED",
+ "ERROR_DS_DRA_SOURCE_DISABLED",
+ "ERROR_DS_DRA_SINK_DISABLED",
+ "ERROR_DS_DRA_NAME_COLLISION",
+ "ERROR_DS_DRA_SOURCE_REINSTALLED",
+ "ERROR_DS_DRA_MISSING_PARENT",
+ "ERROR_DS_DRA_PREEMPTED",
+ "ERROR_DS_DRA_ABANDON_SYNC",
+ "ERROR_DS_DRA_SHUTDOWN",
+ "ERROR_DS_DRA_INCOMPATIBLE_PARTIAL_SET",
+ "ERROR_DS_DRA_SOURCE_IS_PARTIAL_REPLICA",
+ "ERROR_DS_DRA_EXTN_CONNECTION_FAILED",
+ "ERROR_DS_INSTALL_SCHEMA_MISMATCH",
+ "ERROR_DS_DUP_LINK_ID",
+ "ERROR_DS_NAME_ERROR_RESOLVING",
+ "ERROR_DS_NAME_ERROR_NOT_FOUND",
+ "ERROR_DS_NAME_ERROR_NOT_UNIQUE",
+ "ERROR_DS_NAME_ERROR_NO_MAPPING",
+ "ERROR_DS_NAME_ERROR_DOMAIN_ONLY",
+ "ERROR_DS_NAME_ERROR_NO_SYNTACTICAL_MAPPING",
+ "ERROR_DS_CONSTRUCTED_ATT_MOD",
+ "ERROR_DS_WRONG_OM_OBJ_CLASS",
+ "ERROR_DS_DRA_REPL_PENDING",
+ "ERROR_DS_DS_REQUIRED",
+ "ERROR_DS_INVALID_LDAP_DISPLAY_NAME",
+ "ERROR_DS_NON_BASE_SEARCH",
+ "ERROR_DS_CANT_RETRIEVE_ATTS",
+ "ERROR_DS_BACKLINK_WITHOUT_LINK",
+ "ERROR_DS_EPOCH_MISMATCH",
+ "ERROR_DS_SRC_NAME_MISMATCH",
+ "ERROR_DS_SRC_AND_DST_NC_IDENTICAL",
+ "ERROR_DS_DST_NC_MISMATCH",
+ "ERROR_DS_NOT_AUTHORITIVE_FOR_DST_NC",
+ "ERROR_DS_SRC_GUID_MISMATCH",
+ "ERROR_DS_CANT_MOVE_DELETED_OBJECT",
+ "ERROR_DS_PDC_OPERATION_IN_PROGRESS",
+ "ERROR_DS_CROSS_DOMAIN_CLEANUP_REQD",
+ "ERROR_DS_ILLEGAL_XDOM_MOVE_OPERATION",
+ "ERROR_DS_CANT_WITH_ACCT_GROUP_MEMBERSHPS",
+ "ERROR_DS_NC_MUST_HAVE_NC_PARENT",
+ "ERROR_DS_CR_IMPOSSIBLE_TO_VALIDATE",
+ "ERROR_DS_DST_DOMAIN_NOT_NATIVE",
+ "ERROR_DS_MISSING_INFRASTRUCTURE_CONTAINER",
+ "ERROR_DS_CANT_MOVE_ACCOUNT_GROUP",
+ "ERROR_DS_CANT_MOVE_RESOURCE_GROUP",
+ "ERROR_DS_INVALID_SEARCH_FLAG",
+ "ERROR_DS_NO_TREE_DELETE_ABOVE_NC",
+ "ERROR_DS_COULDNT_LOCK_TREE_FOR_DELETE",
+ "ERROR_DS_COULDNT_IDENTIFY_OBJECTS_FOR_TREE_DELETE",
+ "ERROR_DS_SAM_INIT_FAILURE",
+ "ERROR_DS_SENSITIVE_GROUP_VIOLATION",
+ "ERROR_DS_CANT_MOD_PRIMARYGROUPID",
+ "ERROR_DS_ILLEGAL_BASE_SCHEMA_MOD",
+ "ERROR_DS_NONSAFE_SCHEMA_CHANGE",
+ "ERROR_DS_SCHEMA_UPDATE_DISALLOWED",
+ "ERROR_DS_CANT_CREATE_UNDER_SCHEMA",
+ "ERROR_DS_INSTALL_NO_SRC_SCH_VERSION",
+ "ERROR_DS_INSTALL_NO_SCH_VERSION_IN_INIFILE",
+ "ERROR_DS_INVALID_GROUP_TYPE",
+ "ERROR_DS_NO_NEST_GLOBALGROUP_IN_MIXEDDOMAIN",
+ "ERROR_DS_NO_NEST_LOCALGROUP_IN_MIXEDDOMAIN",
+ "ERROR_DS_GLOBAL_CANT_HAVE_LOCAL_MEMBER",
+ "ERROR_DS_GLOBAL_CANT_HAVE_UNIVERSAL_MEMBER",
+ "ERROR_DS_UNIVERSAL_CANT_HAVE_LOCAL_MEMBER",
+ "ERROR_DS_GLOBAL_CANT_HAVE_CROSSDOMAIN_MEMBER",
+ "ERROR_DS_LOCAL_CANT_HAVE_CROSSDOMAIN_LOCAL_MEMBER",
+ "ERROR_DS_HAVE_PRIMARY_MEMBERS",
+ "ERROR_DS_STRING_SD_CONVERSION_FAILED",
+ "ERROR_DS_NAMING_MASTER_GC",
+ "ERROR_DS_DNS_LOOKUP_FAILURE",
+ "ERROR_DS_COULDNT_UPDATE_SPNS",
+ "ERROR_DS_CANT_RETRIEVE_SD",
+ "ERROR_DS_KEY_NOT_UNIQUE",
+ "ERROR_DS_WRONG_LINKED_ATT_SYNTAX",
+ "ERROR_DS_SAM_NEED_BOOTKEY_PASSWORD",
+ "ERROR_DS_SAM_NEED_BOOTKEY_FLOPPY",
+ "ERROR_DS_CANT_START",
+ "ERROR_DS_INIT_FAILURE",
+ "ERROR_DS_NO_PKT_PRIVACY_ON_CONNECTION",
+ "ERROR_DS_SOURCE_DOMAIN_IN_FOREST",
+ "ERROR_DS_DESTINATION_DOMAIN_NOT_IN_FOREST",
+ "ERROR_DS_DESTINATION_AUDITING_NOT_ENABLED",
+ "ERROR_DS_CANT_FIND_DC_FOR_SRC_DOMAIN",
+ "ERROR_DS_SRC_OBJ_NOT_GROUP_OR_USER",
+ "ERROR_DS_SRC_SID_EXISTS_IN_FOREST",
+ "ERROR_DS_SRC_AND_DST_OBJECT_CLASS_MISMATCH",
+ "ERROR_SAM_INIT_FAILURE",
+ "ERROR_DS_DRA_SCHEMA_INFO_SHIP",
+ "ERROR_DS_DRA_SCHEMA_CONFLICT",
+ "ERROR_DS_DRA_EARLIER_SCHEMA_CONFLICT",
+ "ERROR_DS_DRA_OBJ_NC_MISMATCH",
+ "ERROR_DS_NC_STILL_HAS_DSAS",
+ "ERROR_DS_GC_REQUIRED",
+ "ERROR_DS_LOCAL_MEMBER_OF_LOCAL_ONLY",
+ "ERROR_DS_NO_FPO_IN_UNIVERSAL_GROUPS",
+ "ERROR_DS_CANT_ADD_TO_GC",
+ "ERROR_DS_NO_CHECKPOINT_WITH_PDC",
+ "ERROR_DS_SOURCE_AUDITING_NOT_ENABLED",
+ "ERROR_DS_CANT_CREATE_IN_NONDOMAIN_NC",
+ "ERROR_DS_INVALID_NAME_FOR_SPN",
+ "ERROR_DS_FILTER_USES_CONTRUCTED_ATTRS",
+ "ERROR_DS_UNICODEPWD_NOT_IN_QUOTES",
+ "ERROR_DS_MACHINE_ACCOUNT_QUOTA_EXCEEDED",
+ "ERROR_DS_MUST_BE_RUN_ON_DST_DC",
+ "ERROR_DS_SRC_DC_MUST_BE_SP4_OR_GREATER",
+ "ERROR_DS_CANT_TREE_DELETE_CRITICAL_OBJ",
+ "ERROR_DS_INIT_FAILURE_CONSOLE",
+ "ERROR_DS_SAM_INIT_FAILURE_CONSOLE",
+ "ERROR_DS_FOREST_VERSION_TOO_HIGH",
+ "ERROR_DS_DOMAIN_VERSION_TOO_HIGH",
+ "ERROR_DS_FOREST_VERSION_TOO_LOW",
+ "ERROR_DS_DOMAIN_VERSION_TOO_LOW",
+ "ERROR_DS_INCOMPATIBLE_VERSION",
+ "ERROR_DS_LOW_DSA_VERSION",
+ "ERROR_DS_NO_BEHAVIOR_VERSION_IN_MIXEDDOMAIN",
+ "ERROR_DS_NOT_SUPPORTED_SORT_ORDER",
+ "ERROR_DS_NAME_NOT_UNIQUE",
+ "ERROR_DS_MACHINE_ACCOUNT_CREATED_PRENT4",
+ "ERROR_DS_OUT_OF_VERSION_STORE",
+ "ERROR_DS_INCOMPATIBLE_CONTROLS_USED",
+ "ERROR_DS_NO_REF_DOMAIN",
+ "ERROR_DS_RESERVED_LINK_ID",
+ "ERROR_DS_LINK_ID_NOT_AVAILABLE",
+ "ERROR_DS_AG_CANT_HAVE_UNIVERSAL_MEMBER",
+ "ERROR_DS_MODIFYDN_DISALLOWED_BY_INSTANCE_TYPE",
+ "ERROR_DS_NO_OBJECT_MOVE_IN_SCHEMA_NC",
+ "ERROR_DS_MODIFYDN_DISALLOWED_BY_FLAG",
+ "ERROR_DS_MODIFYDN_WRONG_GRANDPARENT",
+ "ERROR_DS_NAME_ERROR_TRUST_REFERRAL",
+ "ERROR_NOT_SUPPORTED_ON_STANDARD_SERVER",
+ "ERROR_DS_CANT_ACCESS_REMOTE_PART_OF_AD",
+ "ERROR_DS_CR_IMPOSSIBLE_TO_VALIDATE_V2",
+ "ERROR_DS_THREAD_LIMIT_EXCEEDED",
+ "ERROR_DS_NOT_CLOSEST",
+ "ERROR_DS_CANT_DERIVE_SPN_WITHOUT_SERVER_REF",
+ "ERROR_DS_SINGLE_USER_MODE_FAILED",
+ "ERROR_DS_NTDSCRIPT_SYNTAX_ERROR",
+ "ERROR_DS_NTDSCRIPT_PROCESS_ERROR",
+ "ERROR_DS_DIFFERENT_REPL_EPOCHS",
+ "ERROR_DS_DRS_EXTENSIONS_CHANGED",
+ "ERROR_DS_REPLICA_SET_CHANGE_NOT_ALLOWED_ON_DISABLED_CR",
+ "ERROR_DS_NO_MSDS_INTID",
+ "ERROR_DS_DUP_MSDS_INTID",
+ "ERROR_DS_EXISTS_IN_RDNATTID",
+ "ERROR_DS_AUTHORIZATION_FAILED",
+ "ERROR_DS_INVALID_SCRIPT",
+ "ERROR_DS_REMOTE_CROSSREF_OP_FAILED",
+ "ERROR_DS_CROSS_REF_BUSY",
+ "ERROR_DS_CANT_DERIVE_SPN_FOR_DELETED_DOMAIN",
+ "ERROR_DS_CANT_DEMOTE_WITH_WRITEABLE_NC",
+ "ERROR_DS_DUPLICATE_ID_FOUND",
+ "ERROR_DS_INSUFFICIENT_ATTR_TO_CREATE_OBJECT",
+ "ERROR_DS_GROUP_CONVERSION_ERROR",
+ "ERROR_DS_CANT_MOVE_APP_BASIC_GROUP",
+ "ERROR_DS_CANT_MOVE_APP_QUERY_GROUP",
+ "ERROR_DS_ROLE_NOT_VERIFIED",
+ "ERROR_DS_WKO_CONTAINER_CANNOT_BE_SPECIAL",
+ "ERROR_DS_DOMAIN_RENAME_IN_PROGRESS",
+ "ERROR_DS_EXISTING_AD_CHILD_NC",
+ "ERROR_DS_REPL_LIFETIME_EXCEEDED",
+ "ERROR_DS_DISALLOWED_IN_SYSTEM_CONTAINER",
+ "ERROR_DS_LDAP_SEND_QUEUE_FULL",
+ "ERROR_DS_DRA_OUT_SCHEDULE_WINDOW",
+ "ERROR_DS_POLICY_NOT_KNOWN",
+ "ERROR_NO_SITE_SETTINGS_OBJECT",
+ "ERROR_NO_SECRETS",
+ "ERROR_NO_WRITABLE_DC_FOUND",
+ "ERROR_DS_NO_SERVER_OBJECT",
+ "ERROR_DS_NO_NTDSA_OBJECT",
+ "ERROR_DS_NON_ASQ_SEARCH",
+ "ERROR_DS_AUDIT_FAILURE",
+ "ERROR_DS_INVALID_SEARCH_FLAG_SUBTREE",
+ "ERROR_DS_INVALID_SEARCH_FLAG_TUPLE",
+ "ERROR_DS_HIERARCHY_TABLE_TOO_DEEP",
+ "ERROR_DS_DRA_CORRUPT_UTD_VECTOR",
+ "ERROR_DS_DRA_SECRETS_DENIED",
+ "ERROR_DS_RESERVED_MAPI_ID",
+ "ERROR_DS_MAPI_ID_NOT_AVAILABLE",
+ "ERROR_DS_DRA_MISSING_KRBTGT_SECRET",
+ "ERROR_DS_DOMAIN_NAME_EXISTS_IN_FOREST",
+ "ERROR_DS_FLAT_NAME_EXISTS_IN_FOREST",
+ "ERROR_INVALID_USER_PRINCIPAL_NAME",
+ "ERROR_DS_OID_MAPPED_GROUP_CANT_HAVE_MEMBERS",
+ "ERROR_DS_OID_NOT_FOUND",
+ "ERROR_DS_DRA_RECYCLED_TARGET",
+ "ERROR_DS_DISALLOWED_NC_REDIRECT",
+ "ERROR_DS_HIGH_ADLDS_FFL",
+ "ERROR_DS_HIGH_DSA_VERSION",
+ "ERROR_DS_LOW_ADLDS_FFL",
+ "ERROR_DOMAIN_SID_SAME_AS_LOCAL_WORKSTATION",
+ "ERROR_DS_UNDELETE_SAM_VALIDATION_FAILED",
+ "ERROR_INCORRECT_ACCOUNT_TYPE",
+ "ERROR_DS_SPN_VALUE_NOT_UNIQUE_IN_FOREST",
+ "ERROR_DS_UPN_VALUE_NOT_UNIQUE_IN_FOREST",
+ "ERROR_DS_MISSING_FOREST_TRUST",
+ "ERROR_DS_VALUE_KEY_NOT_UNIQUE",
+ "ERROR_IPSEC_QM_POLICY_EXISTS",
+ "ERROR_IPSEC_QM_POLICY_NOT_FOUND",
+ "ERROR_IPSEC_QM_POLICY_IN_USE",
+ "ERROR_IPSEC_MM_POLICY_EXISTS",
+ "ERROR_IPSEC_MM_POLICY_NOT_FOUND",
+ "ERROR_IPSEC_MM_POLICY_IN_USE",
+ "ERROR_IPSEC_MM_FILTER_EXISTS",
+ "ERROR_IPSEC_MM_FILTER_NOT_FOUND",
+ "ERROR_IPSEC_TRANSPORT_FILTER_EXISTS",
+ "ERROR_IPSEC_TRANSPORT_FILTER_NOT_FOUND",
+ "ERROR_IPSEC_MM_AUTH_EXISTS",
+ "ERROR_IPSEC_MM_AUTH_NOT_FOUND",
+ "ERROR_IPSEC_MM_AUTH_IN_USE",
+ "ERROR_IPSEC_DEFAULT_MM_POLICY_NOT_FOUND",
+ "ERROR_IPSEC_DEFAULT_MM_AUTH_NOT_FOUND",
+ "ERROR_IPSEC_DEFAULT_QM_POLICY_NOT_FOUND",
+ "ERROR_IPSEC_TUNNEL_FILTER_EXISTS",
+ "ERROR_IPSEC_TUNNEL_FILTER_NOT_FOUND",
+ "ERROR_IPSEC_MM_FILTER_PENDING_DELETION",
+ "ERROR_IPSEC_TRANSPORT_FILTER_PENDING_DELETION",
+ "ERROR_IPSEC_TUNNEL_FILTER_PENDING_DELETION",
+ "ERROR_IPSEC_MM_POLICY_PENDING_DELETION",
+ "ERROR_IPSEC_MM_AUTH_PENDING_DELETION",
+ "ERROR_IPSEC_QM_POLICY_PENDING_DELETION",
+ "ERROR_IPSEC_IKE_NEG_STATUS_BEGIN",
+ "ERROR_IPSEC_IKE_AUTH_FAIL",
+ "ERROR_IPSEC_IKE_ATTRIB_FAIL",
+ "ERROR_IPSEC_IKE_NEGOTIATION_PENDING",
+ "ERROR_IPSEC_IKE_GENERAL_PROCESSING_ERROR",
+ "ERROR_IPSEC_IKE_TIMED_OUT",
+ "ERROR_IPSEC_IKE_NO_CERT",
+ "ERROR_IPSEC_IKE_SA_DELETED",
+ "ERROR_IPSEC_IKE_SA_REAPED",
+ "ERROR_IPSEC_IKE_MM_ACQUIRE_DROP",
+ "ERROR_IPSEC_IKE_QM_ACQUIRE_DROP",
+ "ERROR_IPSEC_IKE_QUEUE_DROP_MM",
+ "ERROR_IPSEC_IKE_QUEUE_DROP_NO_MM",
+ "ERROR_IPSEC_IKE_DROP_NO_RESPONSE",
+ "ERROR_IPSEC_IKE_MM_DELAY_DROP",
+ "ERROR_IPSEC_IKE_QM_DELAY_DROP",
+ "ERROR_IPSEC_IKE_ERROR",
+ "ERROR_IPSEC_IKE_CRL_FAILED",
+ "ERROR_IPSEC_IKE_INVALID_KEY_USAGE",
+ "ERROR_IPSEC_IKE_INVALID_CERT_TYPE",
+ "ERROR_IPSEC_IKE_NO_PRIVATE_KEY",
+ "ERROR_IPSEC_IKE_SIMULTANEOUS_REKEY",
+ "ERROR_IPSEC_IKE_DH_FAIL",
+ "ERROR_IPSEC_IKE_CRITICAL_PAYLOAD_NOT_RECOGNIZED",
+ "ERROR_IPSEC_IKE_INVALID_HEADER",
+ "ERROR_IPSEC_IKE_NO_POLICY",
+ "ERROR_IPSEC_IKE_INVALID_SIGNATURE",
+ "ERROR_IPSEC_IKE_KERBEROS_ERROR",
+ "ERROR_IPSEC_IKE_NO_PUBLIC_KEY",
+ "ERROR_IPSEC_IKE_PROCESS_ERR",
+ "ERROR_IPSEC_IKE_PROCESS_ERR_SA",
+ "ERROR_IPSEC_IKE_PROCESS_ERR_PROP",
+ "ERROR_IPSEC_IKE_PROCESS_ERR_TRANS",
+ "ERROR_IPSEC_IKE_PROCESS_ERR_KE",
+ "ERROR_IPSEC_IKE_PROCESS_ERR_ID",
+ "ERROR_IPSEC_IKE_PROCESS_ERR_CERT",
+ "ERROR_IPSEC_IKE_PROCESS_ERR_CERT_REQ",
+ "ERROR_IPSEC_IKE_PROCESS_ERR_HASH",
+ "ERROR_IPSEC_IKE_PROCESS_ERR_SIG",
+ "ERROR_IPSEC_IKE_PROCESS_ERR_NONCE",
+ "ERROR_IPSEC_IKE_PROCESS_ERR_NOTIFY",
+ "ERROR_IPSEC_IKE_PROCESS_ERR_DELETE",
+ "ERROR_IPSEC_IKE_PROCESS_ERR_VENDOR",
+ "ERROR_IPSEC_IKE_INVALID_PAYLOAD",
+ "ERROR_IPSEC_IKE_LOAD_SOFT_SA",
+ "ERROR_IPSEC_IKE_SOFT_SA_TORN_DOWN",
+ "ERROR_IPSEC_IKE_INVALID_COOKIE",
+ "ERROR_IPSEC_IKE_NO_PEER_CERT",
+ "ERROR_IPSEC_IKE_PEER_CRL_FAILED",
+ "ERROR_IPSEC_IKE_POLICY_CHANGE",
+ "ERROR_IPSEC_IKE_NO_MM_POLICY",
+ "ERROR_IPSEC_IKE_NOTCBPRIV",
+ "ERROR_IPSEC_IKE_SECLOADFAIL",
+ "ERROR_IPSEC_IKE_FAILSSPINIT",
+ "ERROR_IPSEC_IKE_FAILQUERYSSP",
+ "ERROR_IPSEC_IKE_SRVACQFAIL",
+ "ERROR_IPSEC_IKE_SRVQUERYCRED",
+ "ERROR_IPSEC_IKE_GETSPIFAIL",
+ "ERROR_IPSEC_IKE_INVALID_FILTER",
+ "ERROR_IPSEC_IKE_OUT_OF_MEMORY",
+ "ERROR_IPSEC_IKE_ADD_UPDATE_KEY_FAILED",
+ "ERROR_IPSEC_IKE_INVALID_POLICY",
+ "ERROR_IPSEC_IKE_UNKNOWN_DOI",
+ "ERROR_IPSEC_IKE_INVALID_SITUATION",
+ "ERROR_IPSEC_IKE_DH_FAILURE",
+ "ERROR_IPSEC_IKE_INVALID_GROUP",
+ "ERROR_IPSEC_IKE_ENCRYPT",
+ "ERROR_IPSEC_IKE_DECRYPT",
+ "ERROR_IPSEC_IKE_POLICY_MATCH",
+ "ERROR_IPSEC_IKE_UNSUPPORTED_ID",
+ "ERROR_IPSEC_IKE_INVALID_HASH",
+ "ERROR_IPSEC_IKE_INVALID_HASH_ALG",
+ "ERROR_IPSEC_IKE_INVALID_HASH_SIZE",
+ "ERROR_IPSEC_IKE_INVALID_ENCRYPT_ALG",
+ "ERROR_IPSEC_IKE_INVALID_AUTH_ALG",
+ "ERROR_IPSEC_IKE_INVALID_SIG",
+ "ERROR_IPSEC_IKE_LOAD_FAILED",
+ "ERROR_IPSEC_IKE_RPC_DELETE",
+ "ERROR_IPSEC_IKE_BENIGN_REINIT",
+ "ERROR_IPSEC_IKE_INVALID_RESPONDER_LIFETIME_NOTIFY",
+ "ERROR_IPSEC_IKE_INVALID_MAJOR_VERSION",
+ "ERROR_IPSEC_IKE_INVALID_CERT_KEYLEN",
+ "ERROR_IPSEC_IKE_MM_LIMIT",
+ "ERROR_IPSEC_IKE_NEGOTIATION_DISABLED",
+ "ERROR_IPSEC_IKE_QM_LIMIT",
+ "ERROR_IPSEC_IKE_MM_EXPIRED",
+ "ERROR_IPSEC_IKE_PEER_MM_ASSUMED_INVALID",
+ "ERROR_IPSEC_IKE_CERT_CHAIN_POLICY_MISMATCH",
+ "ERROR_IPSEC_IKE_UNEXPECTED_MESSAGE_ID",
+ "ERROR_IPSEC_IKE_INVALID_AUTH_PAYLOAD",
+ "ERROR_IPSEC_IKE_DOS_COOKIE_SENT",
+ "ERROR_IPSEC_IKE_SHUTTING_DOWN",
+ "ERROR_IPSEC_IKE_CGA_AUTH_FAILED",
+ "ERROR_IPSEC_IKE_PROCESS_ERR_NATOA",
+ "ERROR_IPSEC_IKE_INVALID_MM_FOR_QM",
+ "ERROR_IPSEC_IKE_QM_EXPIRED",
+ "ERROR_IPSEC_IKE_TOO_MANY_FILTERS",
+ "ERROR_IPSEC_IKE_NEG_STATUS_END",
+ "ERROR_IPSEC_IKE_KILL_DUMMY_NAP_TUNNEL",
+ "ERROR_IPSEC_IKE_INNER_IP_ASSIGNMENT_FAILURE",
+ "ERROR_IPSEC_IKE_REQUIRE_CP_PAYLOAD_MISSING",
+ "ERROR_IPSEC_KEY_MODULE_IMPERSONATION_NEGOTIATION_PENDING",
+ "ERROR_IPSEC_IKE_COEXISTENCE_SUPPRESS",
+ "ERROR_IPSEC_IKE_RATELIMIT_DROP",
+ "ERROR_IPSEC_IKE_PEER_DOESNT_SUPPORT_MOBIKE",
+ "ERROR_IPSEC_IKE_AUTHORIZATION_FAILURE",
+ "ERROR_IPSEC_IKE_STRONG_CRED_AUTHORIZATION_FAILURE",
+ "ERROR_IPSEC_IKE_AUTHORIZATION_FAILURE_WITH_OPTIONAL_RETRY",
+ "ERROR_IPSEC_IKE_STRONG_CRED_AUTHORIZATION_AND_CERTMAP_FAILURE",
+ "ERROR_IPSEC_IKE_NEG_STATUS_EXTENDED_END",
+ "ERROR_IPSEC_BAD_SPI",
+ "ERROR_IPSEC_SA_LIFETIME_EXPIRED",
+ "ERROR_IPSEC_WRONG_SA",
+ "ERROR_IPSEC_REPLAY_CHECK_FAILED",
+ "ERROR_IPSEC_INVALID_PACKET",
+ "ERROR_IPSEC_INTEGRITY_CHECK_FAILED",
+ "ERROR_IPSEC_CLEAR_TEXT_DROP",
+ "ERROR_IPSEC_AUTH_FIREWALL_DROP",
+ "ERROR_IPSEC_THROTTLE_DROP",
+ "ERROR_IPSEC_DOSP_BLOCK",
+ "ERROR_IPSEC_DOSP_RECEIVED_MULTICAST",
+ "ERROR_IPSEC_DOSP_INVALID_PACKET",
+ "ERROR_IPSEC_DOSP_STATE_LOOKUP_FAILED",
+ "ERROR_IPSEC_DOSP_MAX_ENTRIES",
+ "ERROR_IPSEC_DOSP_KEYMOD_NOT_ALLOWED",
+ "ERROR_IPSEC_DOSP_NOT_INSTALLED",
+ "ERROR_IPSEC_DOSP_MAX_PER_IP_RATELIMIT_QUEUES",
+ "ERROR_SXS_SECTION_NOT_FOUND",
+ "ERROR_SXS_CANT_GEN_ACTCTX",
+ "ERROR_SXS_INVALID_ACTCTXDATA_FORMAT",
+ "ERROR_SXS_ASSEMBLY_NOT_FOUND",
+ "ERROR_SXS_MANIFEST_FORMAT_ERROR",
+ "ERROR_SXS_MANIFEST_PARSE_ERROR",
+ "ERROR_SXS_ACTIVATION_CONTEXT_DISABLED",
+ "ERROR_SXS_KEY_NOT_FOUND",
+ "ERROR_SXS_VERSION_CONFLICT",
+ "ERROR_SXS_WRONG_SECTION_TYPE",
+ "ERROR_SXS_THREAD_QUERIES_DISABLED",
+ "ERROR_SXS_PROCESS_DEFAULT_ALREADY_SET",
+ "ERROR_SXS_UNKNOWN_ENCODING_GROUP",
+ "ERROR_SXS_UNKNOWN_ENCODING",
+ "ERROR_SXS_INVALID_XML_NAMESPACE_URI",
+ "ERROR_SXS_ROOT_MANIFEST_DEPENDENCY_NOT_INSTALLED",
+ "ERROR_SXS_LEAF_MANIFEST_DEPENDENCY_NOT_INSTALLED",
+ "ERROR_SXS_INVALID_ASSEMBLY_IDENTITY_ATTRIBUTE",
+ "ERROR_SXS_MANIFEST_MISSING_REQUIRED_DEFAULT_NAMESPACE",
+ "ERROR_SXS_MANIFEST_INVALID_REQUIRED_DEFAULT_NAMESPACE",
+ "ERROR_SXS_PRIVATE_MANIFEST_CROSS_PATH_WITH_REPARSE_POINT",
+ "ERROR_SXS_DUPLICATE_DLL_NAME",
+ "ERROR_SXS_DUPLICATE_WINDOWCLASS_NAME",
+ "ERROR_SXS_DUPLICATE_CLSID",
+ "ERROR_SXS_DUPLICATE_IID",
+ "ERROR_SXS_DUPLICATE_TLBID",
+ "ERROR_SXS_DUPLICATE_PROGID",
+ "ERROR_SXS_DUPLICATE_ASSEMBLY_NAME",
+ "ERROR_SXS_FILE_HASH_MISMATCH",
+ "ERROR_SXS_POLICY_PARSE_ERROR",
+ "ERROR_SXS_XML_E_MISSINGQUOTE",
+ "ERROR_SXS_XML_E_COMMENTSYNTAX",
+ "ERROR_SXS_XML_E_BADSTARTNAMECHAR",
+ "ERROR_SXS_XML_E_BADNAMECHAR",
+ "ERROR_SXS_XML_E_BADCHARINSTRING",
+ "ERROR_SXS_XML_E_XMLDECLSYNTAX",
+ "ERROR_SXS_XML_E_BADCHARDATA",
+ "ERROR_SXS_XML_E_MISSINGWHITESPACE",
+ "ERROR_SXS_XML_E_EXPECTINGTAGEND",
+ "ERROR_SXS_XML_E_MISSINGSEMICOLON",
+ "ERROR_SXS_XML_E_UNBALANCEDPAREN",
+ "ERROR_SXS_XML_E_INTERNALERROR",
+ "ERROR_SXS_XML_E_UNEXPECTED_WHITESPACE",
+ "ERROR_SXS_XML_E_INCOMPLETE_ENCODING",
+ "ERROR_SXS_XML_E_MISSING_PAREN",
+ "ERROR_SXS_XML_E_EXPECTINGCLOSEQUOTE",
+ "ERROR_SXS_XML_E_MULTIPLE_COLONS",
+ "ERROR_SXS_XML_E_INVALID_DECIMAL",
+ "ERROR_SXS_XML_E_INVALID_HEXIDECIMAL",
+ "ERROR_SXS_XML_E_INVALID_UNICODE",
+ "ERROR_SXS_XML_E_WHITESPACEORQUESTIONMARK",
+ "ERROR_SXS_XML_E_UNEXPECTEDENDTAG",
+ "ERROR_SXS_XML_E_UNCLOSEDTAG",
+ "ERROR_SXS_XML_E_DUPLICATEATTRIBUTE",
+ "ERROR_SXS_XML_E_MULTIPLEROOTS",
+ "ERROR_SXS_XML_E_INVALIDATROOTLEVEL",
+ "ERROR_SXS_XML_E_BADXMLDECL",
+ "ERROR_SXS_XML_E_MISSINGROOT",
+ "ERROR_SXS_XML_E_UNEXPECTEDEOF",
+ "ERROR_SXS_XML_E_BADPEREFINSUBSET",
+ "ERROR_SXS_XML_E_UNCLOSEDSTARTTAG",
+ "ERROR_SXS_XML_E_UNCLOSEDENDTAG",
+ "ERROR_SXS_XML_E_UNCLOSEDSTRING",
+ "ERROR_SXS_XML_E_UNCLOSEDCOMMENT",
+ "ERROR_SXS_XML_E_UNCLOSEDDECL",
+ "ERROR_SXS_XML_E_UNCLOSEDCDATA",
+ "ERROR_SXS_XML_E_RESERVEDNAMESPACE",
+ "ERROR_SXS_XML_E_INVALIDENCODING",
+ "ERROR_SXS_XML_E_INVALIDSWITCH",
+ "ERROR_SXS_XML_E_BADXMLCASE",
+ "ERROR_SXS_XML_E_INVALID_STANDALONE",
+ "ERROR_SXS_XML_E_UNEXPECTED_STANDALONE",
+ "ERROR_SXS_XML_E_INVALID_VERSION",
+ "ERROR_SXS_XML_E_MISSINGEQUALS",
+ "ERROR_SXS_PROTECTION_RECOVERY_FAILED",
+ "ERROR_SXS_PROTECTION_PUBLIC_KEY_TOO_SHORT",
+ "ERROR_SXS_PROTECTION_CATALOG_NOT_VALID",
+ "ERROR_SXS_UNTRANSLATABLE_HRESULT",
+ "ERROR_SXS_PROTECTION_CATALOG_FILE_MISSING",
+ "ERROR_SXS_MISSING_ASSEMBLY_IDENTITY_ATTRIBUTE",
+ "ERROR_SXS_INVALID_ASSEMBLY_IDENTITY_ATTRIBUTE_NAME",
+ "ERROR_SXS_ASSEMBLY_MISSING",
+ "ERROR_SXS_CORRUPT_ACTIVATION_STACK",
+ "ERROR_SXS_CORRUPTION",
+ "ERROR_SXS_EARLY_DEACTIVATION",
+ "ERROR_SXS_INVALID_DEACTIVATION",
+ "ERROR_SXS_MULTIPLE_DEACTIVATION",
+ "ERROR_SXS_PROCESS_TERMINATION_REQUESTED",
+ "ERROR_SXS_RELEASE_ACTIVATION_CONTEXT",
+ "ERROR_SXS_SYSTEM_DEFAULT_ACTIVATION_CONTEXT_EMPTY",
+ "ERROR_SXS_INVALID_IDENTITY_ATTRIBUTE_VALUE",
+ "ERROR_SXS_INVALID_IDENTITY_ATTRIBUTE_NAME",
+ "ERROR_SXS_IDENTITY_DUPLICATE_ATTRIBUTE",
+ "ERROR_SXS_IDENTITY_PARSE_ERROR",
+ "ERROR_MALFORMED_SUBSTITUTION_STRING",
+ "ERROR_SXS_INCORRECT_PUBLIC_KEY_TOKEN",
+ "ERROR_UNMAPPED_SUBSTITUTION_STRING",
+ "ERROR_SXS_ASSEMBLY_NOT_LOCKED",
+ "ERROR_SXS_COMPONENT_STORE_CORRUPT",
+ "ERROR_ADVANCED_INSTALLER_FAILED",
+ "ERROR_XML_ENCODING_MISMATCH",
+ "ERROR_SXS_MANIFEST_IDENTITY_SAME_BUT_CONTENTS_DIFFERENT",
+ "ERROR_SXS_IDENTITIES_DIFFERENT",
+ "ERROR_SXS_ASSEMBLY_IS_NOT_A_DEPLOYMENT",
+ "ERROR_SXS_FILE_NOT_PART_OF_ASSEMBLY",
+ "ERROR_SXS_MANIFEST_TOO_BIG",
+ "ERROR_SXS_SETTING_NOT_REGISTERED",
+ "ERROR_SXS_TRANSACTION_CLOSURE_INCOMPLETE",
+ "ERROR_SMI_PRIMITIVE_INSTALLER_FAILED",
+ "ERROR_GENERIC_COMMAND_FAILED",
+ "ERROR_SXS_FILE_HASH_MISSING",
+ "ERROR_SXS_DUPLICATE_ACTIVATABLE_CLASS",
+ "ERROR_EVT_INVALID_CHANNEL_PATH",
+ "ERROR_EVT_INVALID_QUERY",
+ "ERROR_EVT_PUBLISHER_METADATA_NOT_FOUND",
+ "ERROR_EVT_EVENT_TEMPLATE_NOT_FOUND",
+ "ERROR_EVT_INVALID_PUBLISHER_NAME",
+ "ERROR_EVT_INVALID_EVENT_DATA",
+ "ERROR_EVT_CHANNEL_NOT_FOUND",
+ "ERROR_EVT_MALFORMED_XML_TEXT",
+ "ERROR_EVT_SUBSCRIPTION_TO_DIRECT_CHANNEL",
+ "ERROR_EVT_CONFIGURATION_ERROR",
+ "ERROR_EVT_QUERY_RESULT_STALE",
+ "ERROR_EVT_QUERY_RESULT_INVALID_POSITION",
+ "ERROR_EVT_NON_VALIDATING_MSXML",
+ "ERROR_EVT_FILTER_ALREADYSCOPED",
+ "ERROR_EVT_FILTER_NOTELTSET",
+ "ERROR_EVT_FILTER_INVARG",
+ "ERROR_EVT_FILTER_INVTEST",
+ "ERROR_EVT_FILTER_INVTYPE",
+ "ERROR_EVT_FILTER_PARSEERR",
+ "ERROR_EVT_FILTER_UNSUPPORTEDOP",
+ "ERROR_EVT_FILTER_UNEXPECTEDTOKEN",
+ "ERROR_EVT_INVALID_OPERATION_OVER_ENABLED_DIRECT_CHANNEL",
+ "ERROR_EVT_INVALID_CHANNEL_PROPERTY_VALUE",
+ "ERROR_EVT_INVALID_PUBLISHER_PROPERTY_VALUE",
+ "ERROR_EVT_CHANNEL_CANNOT_ACTIVATE",
+ "ERROR_EVT_FILTER_TOO_COMPLEX",
+ "ERROR_EVT_MESSAGE_NOT_FOUND",
+ "ERROR_EVT_MESSAGE_ID_NOT_FOUND",
+ "ERROR_EVT_UNRESOLVED_VALUE_INSERT",
+ "ERROR_EVT_UNRESOLVED_PARAMETER_INSERT",
+ "ERROR_EVT_MAX_INSERTS_REACHED",
+ "ERROR_EVT_EVENT_DEFINITION_NOT_FOUND",
+ "ERROR_EVT_MESSAGE_LOCALE_NOT_FOUND",
+ "ERROR_EVT_VERSION_TOO_OLD",
+ "ERROR_EVT_VERSION_TOO_NEW",
+ "ERROR_EVT_CANNOT_OPEN_CHANNEL_OF_QUERY",
+ "ERROR_EVT_PUBLISHER_DISABLED",
+ "ERROR_EVT_FILTER_OUT_OF_RANGE",
+ "ERROR_EC_SUBSCRIPTION_CANNOT_ACTIVATE",
+ "ERROR_EC_LOG_DISABLED",
+ "ERROR_EC_CIRCULAR_FORWARDING",
+ "ERROR_EC_CREDSTORE_FULL",
+ "ERROR_EC_CRED_NOT_FOUND",
+ "ERROR_EC_NO_ACTIVE_CHANNEL",
+ "ERROR_MUI_FILE_NOT_FOUND",
+ "ERROR_MUI_INVALID_FILE",
+ "ERROR_MUI_INVALID_RC_CONFIG",
+ "ERROR_MUI_INVALID_LOCALE_NAME",
+ "ERROR_MUI_INVALID_ULTIMATEFALLBACK_NAME",
+ "ERROR_MUI_FILE_NOT_LOADED",
+ "ERROR_RESOURCE_ENUM_USER_STOP",
+ "ERROR_MUI_INTLSETTINGS_UILANG_NOT_INSTALLED",
+ "ERROR_MUI_INTLSETTINGS_INVALID_LOCALE_NAME",
+ "ERROR_MRM_RUNTIME_NO_DEFAULT_OR_NEUTRAL_RESOURCE",
+ "ERROR_MRM_INVALID_PRICONFIG",
+ "ERROR_MRM_INVALID_FILE_TYPE",
+ "ERROR_MRM_UNKNOWN_QUALIFIER",
+ "ERROR_MRM_INVALID_QUALIFIER_VALUE",
+ "ERROR_MRM_NO_CANDIDATE",
+ "ERROR_MRM_NO_MATCH_OR_DEFAULT_CANDIDATE",
+ "ERROR_MRM_RESOURCE_TYPE_MISMATCH",
+ "ERROR_MRM_DUPLICATE_MAP_NAME",
+ "ERROR_MRM_DUPLICATE_ENTRY",
+ "ERROR_MRM_INVALID_RESOURCE_IDENTIFIER",
+ "ERROR_MRM_FILEPATH_TOO_LONG",
+ "ERROR_MRM_UNSUPPORTED_DIRECTORY_TYPE",
+ "ERROR_MRM_INVALID_PRI_FILE",
+ "ERROR_MRM_NAMED_RESOURCE_NOT_FOUND",
+ "ERROR_MRM_MAP_NOT_FOUND",
+ "ERROR_MRM_UNSUPPORTED_PROFILE_TYPE",
+ "ERROR_MRM_INVALID_QUALIFIER_OPERATOR",
+ "ERROR_MRM_INDETERMINATE_QUALIFIER_VALUE",
+ "ERROR_MRM_AUTOMERGE_ENABLED",
+ "ERROR_MRM_TOO_MANY_RESOURCES",
+ "ERROR_MRM_UNSUPPORTED_FILE_TYPE_FOR_MERGE",
+ "ERROR_MRM_UNSUPPORTED_FILE_TYPE_FOR_LOAD_UNLOAD_PRI_FILE",
+ "ERROR_MRM_NO_CURRENT_VIEW_ON_THREAD",
+ "ERROR_DIFFERENT_PROFILE_RESOURCE_MANAGER_EXIST",
+ "ERROR_OPERATION_NOT_ALLOWED_FROM_SYSTEM_COMPONENT",
+ "ERROR_MRM_DIRECT_REF_TO_NON_DEFAULT_RESOURCE",
+ "ERROR_MRM_GENERATION_COUNT_MISMATCH",
+ "ERROR_PRI_MERGE_VERSION_MISMATCH",
+ "ERROR_PRI_MERGE_MISSING_SCHEMA",
+ "ERROR_PRI_MERGE_LOAD_FILE_FAILED",
+ "ERROR_PRI_MERGE_ADD_FILE_FAILED",
+ "ERROR_PRI_MERGE_WRITE_FILE_FAILED",
+ "ERROR_PRI_MERGE_MULTIPLE_PACKAGE_FAMILIES_NOT_ALLOWED",
+ "ERROR_PRI_MERGE_MULTIPLE_MAIN_PACKAGES_NOT_ALLOWED",
+ "ERROR_PRI_MERGE_BUNDLE_PACKAGES_NOT_ALLOWED",
+ "ERROR_PRI_MERGE_MAIN_PACKAGE_REQUIRED",
+ "ERROR_PRI_MERGE_RESOURCE_PACKAGE_REQUIRED",
+ "ERROR_PRI_MERGE_INVALID_FILE_NAME",
+ "ERROR_MRM_PACKAGE_NOT_FOUND",
+ "ERROR_MRM_MISSING_DEFAULT_LANGUAGE",
+ "ERROR_MCA_INVALID_CAPABILITIES_STRING",
+ "ERROR_MCA_INVALID_VCP_VERSION",
+ "ERROR_MCA_MONITOR_VIOLATES_MCCS_SPECIFICATION",
+ "ERROR_MCA_MCCS_VERSION_MISMATCH",
+ "ERROR_MCA_UNSUPPORTED_MCCS_VERSION",
+ "ERROR_MCA_INTERNAL_ERROR",
+ "ERROR_MCA_INVALID_TECHNOLOGY_TYPE_RETURNED",
+ "ERROR_MCA_UNSUPPORTED_COLOR_TEMPERATURE",
+ "ERROR_AMBIGUOUS_SYSTEM_DEVICE",
+ "ERROR_SYSTEM_DEVICE_NOT_FOUND",
+ "ERROR_HASH_NOT_SUPPORTED",
+ "ERROR_HASH_NOT_PRESENT",
+ "ERROR_SECONDARY_IC_PROVIDER_NOT_REGISTERED",
+ "ERROR_GPIO_CLIENT_INFORMATION_INVALID",
+ "ERROR_GPIO_VERSION_NOT_SUPPORTED",
+ "ERROR_GPIO_INVALID_REGISTRATION_PACKET",
+ "ERROR_GPIO_OPERATION_DENIED",
+ "ERROR_GPIO_INCOMPATIBLE_CONNECT_MODE",
+ "ERROR_GPIO_INTERRUPT_ALREADY_UNMASKED",
+ "ERROR_CANNOT_SWITCH_RUNLEVEL",
+ "ERROR_INVALID_RUNLEVEL_SETTING",
+ "ERROR_RUNLEVEL_SWITCH_TIMEOUT",
+ "ERROR_RUNLEVEL_SWITCH_AGENT_TIMEOUT",
+ "ERROR_RUNLEVEL_SWITCH_IN_PROGRESS",
+ "ERROR_SERVICES_FAILED_AUTOSTART",
+ "ERROR_COM_TASK_STOP_PENDING",
+ "ERROR_INSTALL_OPEN_PACKAGE_FAILED",
+ "ERROR_INSTALL_PACKAGE_NOT_FOUND",
+ "ERROR_INSTALL_INVALID_PACKAGE",
+ "ERROR_INSTALL_RESOLVE_DEPENDENCY_FAILED",
+ "ERROR_INSTALL_OUT_OF_DISK_SPACE",
+ "ERROR_INSTALL_NETWORK_FAILURE",
+ "ERROR_INSTALL_REGISTRATION_FAILURE",
+ "ERROR_INSTALL_DEREGISTRATION_FAILURE",
+ "ERROR_INSTALL_CANCEL",
+ "ERROR_INSTALL_FAILED",
+ "ERROR_REMOVE_FAILED",
+ "ERROR_PACKAGE_ALREADY_EXISTS",
+ "ERROR_NEEDS_REMEDIATION",
+ "ERROR_INSTALL_PREREQUISITE_FAILED",
+ "ERROR_PACKAGE_REPOSITORY_CORRUPTED",
+ "ERROR_INSTALL_POLICY_FAILURE",
+ "ERROR_PACKAGE_UPDATING",
+ "ERROR_DEPLOYMENT_BLOCKED_BY_POLICY",
+ "ERROR_PACKAGES_IN_USE",
+ "ERROR_RECOVERY_FILE_CORRUPT",
+ "ERROR_INVALID_STAGED_SIGNATURE",
+ "ERROR_DELETING_EXISTING_APPLICATIONDATA_STORE_FAILED",
+ "ERROR_INSTALL_PACKAGE_DOWNGRADE",
+ "ERROR_SYSTEM_NEEDS_REMEDIATION",
+ "ERROR_APPX_INTEGRITY_FAILURE_CLR_NGEN",
+ "ERROR_RESILIENCY_FILE_CORRUPT",
+ "ERROR_INSTALL_FIREWALL_SERVICE_NOT_RUNNING",
+ "ERROR_PACKAGE_MOVE_FAILED",
+ "ERROR_INSTALL_VOLUME_NOT_EMPTY",
+ "ERROR_INSTALL_VOLUME_OFFLINE",
+ "ERROR_INSTALL_VOLUME_CORRUPT",
+ "ERROR_NEEDS_REGISTRATION",
+ "ERROR_INSTALL_WRONG_PROCESSOR_ARCHITECTURE",
+ "ERROR_DEV_SIDELOAD_LIMIT_EXCEEDED",
+ "ERROR_INSTALL_OPTIONAL_PACKAGE_REQUIRES_MAIN_PACKAGE",
+ "ERROR_PACKAGE_NOT_SUPPORTED_ON_FILESYSTEM",
+ "ERROR_PACKAGE_MOVE_BLOCKED_BY_STREAMING",
+ "ERROR_INSTALL_OPTIONAL_PACKAGE_APPLICATIONID_NOT_UNIQUE",
+ "ERROR_PACKAGE_STAGING_ONHOLD",
+ "ERROR_INSTALL_INVALID_RELATED_SET_UPDATE",
+ "ERROR_INSTALL_OPTIONAL_PACKAGE_REQUIRES_MAIN_PACKAGE_FULLTRUST_CAPABILITY",
+ "ERROR_DEPLOYMENT_BLOCKED_BY_USER_LOG_OFF",
+ "ERROR_PROVISION_OPTIONAL_PACKAGE_REQUIRES_MAIN_PACKAGE_PROVISIONED",
+ "ERROR_PACKAGES_REPUTATION_CHECK_FAILED",
+ "ERROR_PACKAGES_REPUTATION_CHECK_TIMEDOUT",
+ "ERROR_DEPLOYMENT_OPTION_NOT_SUPPORTED",
+ "ERROR_APPINSTALLER_ACTIVATION_BLOCKED",
+ "ERROR_REGISTRATION_FROM_REMOTE_DRIVE_NOT_SUPPORTED",
+ "ERROR_APPX_RAW_DATA_WRITE_FAILED",
+ "ERROR_DEPLOYMENT_BLOCKED_BY_VOLUME_POLICY_PACKAGE",
+ "ERROR_DEPLOYMENT_BLOCKED_BY_VOLUME_POLICY_MACHINE",
+ "ERROR_DEPLOYMENT_BLOCKED_BY_PROFILE_POLICY",
+ "ERROR_DEPLOYMENT_FAILED_CONFLICTING_MUTABLE_PACKAGE_DIRECTORY",
+ "ERROR_SINGLETON_RESOURCE_INSTALLED_IN_ACTIVE_USER",
+ "ERROR_DIFFERENT_VERSION_OF_PACKAGED_SERVICE_INSTALLED",
+ "ERROR_SERVICE_EXISTS_AS_NON_PACKAGED_SERVICE",
+ "ERROR_PACKAGED_SERVICE_REQUIRES_ADMIN_PRIVILEGES",
+ "ERROR_REDIRECTION_TO_DEFAULT_ACCOUNT_NOT_ALLOWED",
+ "ERROR_PACKAGE_LACKS_CAPABILITY_TO_DEPLOY_ON_HOST",
+ "ERROR_UNSIGNED_PACKAGE_INVALID_CONTENT",
+ "ERROR_UNSIGNED_PACKAGE_INVALID_PUBLISHER_NAMESPACE",
+ "ERROR_SIGNED_PACKAGE_INVALID_PUBLISHER_NAMESPACE",
+ "ERROR_PACKAGE_EXTERNAL_LOCATION_NOT_ALLOWED",
+ "ERROR_INSTALL_FULLTRUST_HOSTRUNTIME_REQUIRES_MAIN_PACKAGE_FULLTRUST_CAPABILITY",
+ "ERROR_STATE_LOAD_STORE_FAILED",
+ "ERROR_STATE_GET_VERSION_FAILED",
+ "ERROR_STATE_SET_VERSION_FAILED",
+ "ERROR_STATE_STRUCTURED_RESET_FAILED",
+ "ERROR_STATE_OPEN_CONTAINER_FAILED",
+ "ERROR_STATE_CREATE_CONTAINER_FAILED",
+ "ERROR_STATE_DELETE_CONTAINER_FAILED",
+ "ERROR_STATE_READ_SETTING_FAILED",
+ "ERROR_STATE_WRITE_SETTING_FAILED",
+ "ERROR_STATE_DELETE_SETTING_FAILED",
+ "ERROR_STATE_QUERY_SETTING_FAILED",
+ "ERROR_STATE_READ_COMPOSITE_SETTING_FAILED",
+ "ERROR_STATE_WRITE_COMPOSITE_SETTING_FAILED",
+ "ERROR_STATE_ENUMERATE_CONTAINER_FAILED",
+ "ERROR_STATE_ENUMERATE_SETTINGS_FAILED",
+ "ERROR_STATE_COMPOSITE_SETTING_VALUE_SIZE_LIMIT_EXCEEDED",
+ "ERROR_STATE_SETTING_VALUE_SIZE_LIMIT_EXCEEDED",
+ "ERROR_STATE_SETTING_NAME_SIZE_LIMIT_EXCEEDED",
+ "ERROR_STATE_CONTAINER_NAME_SIZE_LIMIT_EXCEEDED",
+ "ERROR_API_UNAVAILABLE",
+};
+
+const char* WinErrorToString(uint16_t error) {
+ auto itr = std::find(std::begin(kWinErrorValues),
+ std::end(kWinErrorValues),
+ error);
+ if (itr == std::end(kWinErrorValues)) {
+ return nullptr;
+ }
+
+ return kWinErrorStrings[itr - std::begin(kWinErrorValues)];
+}
+
+} // namespace google_breakpad
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/symbolic_constants_win.h b/toolkit/crashreporter/google-breakpad/src/processor/symbolic_constants_win.h
new file mode 100644
index 0000000000..5b7152679b
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/symbolic_constants_win.h
@@ -0,0 +1,61 @@
+// 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.
+
+// ntstatus_reason_win.h: Windows NTSTATUS code to string.
+//
+// Provides a means to convert NTSTATUS codes to strings.
+//
+// Author: Ben Wagner
+
+#ifndef GOOGLE_BREAKPAD_PROCESSOR_SYMBOLIC_CONSTANTS_WIN_H_
+#define GOOGLE_BREAKPAD_PROCESSOR_SYMBOLIC_CONSTANTS_WIN_H_
+
+#include <stdint.h>
+#include <string>
+
+#include "common/using_std_string.h"
+#include "google_breakpad/common/breakpad_types.h"
+
+namespace google_breakpad {
+
+/* Converts an NTSTATUS code to its string representation. Returns nullptr if
+ * no entry corresponds to the code. */
+const char* NTStatusToString(uint32_t ntstatus);
+
+/* Converts a FAST_FAIL code to its string representation. Returns nullptr if
+ * no entry corresponds to the code. */
+const char* FastFailToString(uint32_t fast_fail_code);
+
+/* Converts an ERROR code to its string representation. Returns nullptr if
+ * no entry corresponds to the code. */
+const char* WinErrorToString(uint16_t error);
+
+} // namespace google_breakpad
+
+#endif // GOOGLE_BREAKPAD_PROCESSOR_SYMBOLIC_CONSTANTS_WIN_H_
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/synth_minidump.cc b/toolkit/crashreporter/google-breakpad/src/processor/synth_minidump.cc
new file mode 100644
index 0000000000..aa86d248ae
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/synth_minidump.cc
@@ -0,0 +1,421 @@
+// 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>
+
+// synth_minidump.cc: Implementation of SynthMinidump. See synth_minidump.h
+
+#include "processor/synth_minidump.h"
+
+namespace google_breakpad {
+
+namespace SynthMinidump {
+
+Section::Section(const Dump &dump)
+ : test_assembler::Section(dump.endianness()) { }
+
+void Section::CiteLocationIn(test_assembler::Section *section) const {
+ (*section).D32(size_).D32(file_offset_);
+}
+
+void Stream::CiteStreamIn(test_assembler::Section *section) const {
+ section->D32(type_);
+ CiteLocationIn(section);
+}
+
+SystemInfo::SystemInfo(const Dump &dump,
+ const MDRawSystemInfo &system_info,
+ const String &csd_version)
+ : Stream(dump, MD_SYSTEM_INFO_STREAM) {
+ D16(system_info.processor_architecture);
+ D16(system_info.processor_level);
+ D16(system_info.processor_revision);
+ D8(system_info.number_of_processors);
+ D8(system_info.product_type);
+ D32(system_info.major_version);
+ D32(system_info.minor_version);
+ D32(system_info.build_number);
+ D32(system_info.platform_id);
+ csd_version.CiteStringIn(this);
+ D16(system_info.suite_mask);
+ D16(system_info.reserved2); // Well, why not?
+
+ // MDCPUInformation cpu;
+ if (system_info.processor_architecture == MD_CPU_ARCHITECTURE_X86) {
+ D32(system_info.cpu.x86_cpu_info.vendor_id[0]);
+ D32(system_info.cpu.x86_cpu_info.vendor_id[1]);
+ D32(system_info.cpu.x86_cpu_info.vendor_id[2]);
+ D32(system_info.cpu.x86_cpu_info.version_information);
+ D32(system_info.cpu.x86_cpu_info.feature_information);
+ D32(system_info.cpu.x86_cpu_info.amd_extended_cpu_features);
+ } else if (system_info.processor_architecture == MD_CPU_ARCHITECTURE_ARM) {
+ D32(system_info.cpu.arm_cpu_info.cpuid);
+ D32(system_info.cpu.arm_cpu_info.elf_hwcaps);
+ } else {
+ D64(system_info.cpu.other_cpu_info.processor_features[0]);
+ D64(system_info.cpu.other_cpu_info.processor_features[1]);
+ }
+}
+
+const MDRawSystemInfo SystemInfo::windows_x86 = {
+ MD_CPU_ARCHITECTURE_X86, // processor_architecture
+ 6, // processor_level
+ 0xd08, // processor_revision
+ 1, // number_of_processors
+ 1, // product_type
+ 5, // major_version
+ 1, // minor_version
+ 2600, // build_number
+ 2, // platform_id
+ 0xdeadbeef, // csd_version_rva
+ 0x100, // suite_mask
+ 0, // reserved2
+ { // cpu
+ { // x86_cpu_info
+ { 0x756e6547, 0x49656e69, 0x6c65746e }, // vendor_id
+ 0x6d8, // version_information
+ 0xafe9fbff, // feature_information
+ 0xffffffff // amd_extended_cpu_features
+ }
+ }
+};
+
+const string SystemInfo::windows_x86_csd_version = "Service Pack 2";
+
+String::String(const Dump &dump, const string &contents) : Section(dump) {
+ D32(contents.size() * 2);
+ for (string::const_iterator i = contents.begin(); i != contents.end(); i++)
+ D16(*i);
+}
+
+void String::CiteStringIn(test_assembler::Section *section) const {
+ section->D32(file_offset_);
+}
+
+void Memory::CiteMemoryIn(test_assembler::Section *section) const {
+ section->D64(address_);
+ CiteLocationIn(section);
+}
+
+Context::Context(const Dump &dump, const MDRawContextX86 &context)
+ : Section(dump) {
+ // The caller should have properly set the CPU type flag.
+ // The high 24 bits identify the CPU. Note that context records with no CPU
+ // type information can be valid (e.g. produced by ::RtlCaptureContext).
+ assert(((context.context_flags & MD_CONTEXT_CPU_MASK) == 0) ||
+ (context.context_flags & MD_CONTEXT_X86));
+ // It doesn't make sense to store x86 registers in big-endian form.
+ assert(dump.endianness() == kLittleEndian);
+ D32(context.context_flags);
+ D32(context.dr0);
+ D32(context.dr1);
+ D32(context.dr2);
+ D32(context.dr3);
+ D32(context.dr6);
+ D32(context.dr7);
+ D32(context.float_save.control_word);
+ D32(context.float_save.status_word);
+ D32(context.float_save.tag_word);
+ D32(context.float_save.error_offset);
+ D32(context.float_save.error_selector);
+ D32(context.float_save.data_offset);
+ D32(context.float_save.data_selector);
+ // context.float_save.register_area[] contains 8-bit quantities and
+ // does not need to be swapped.
+ Append(context.float_save.register_area,
+ sizeof(context.float_save.register_area));
+ D32(context.float_save.cr0_npx_state);
+ D32(context.gs);
+ D32(context.fs);
+ D32(context.es);
+ D32(context.ds);
+ D32(context.edi);
+ D32(context.esi);
+ D32(context.ebx);
+ D32(context.edx);
+ D32(context.ecx);
+ D32(context.eax);
+ D32(context.ebp);
+ D32(context.eip);
+ D32(context.cs);
+ D32(context.eflags);
+ D32(context.esp);
+ D32(context.ss);
+ // context.extended_registers[] contains 8-bit quantities and does
+ // not need to be swapped.
+ Append(context.extended_registers, sizeof(context.extended_registers));
+ assert(Size() == sizeof(MDRawContextX86));
+}
+
+Context::Context(const Dump &dump, const MDRawContextARM &context)
+ : Section(dump) {
+ // The caller should have properly set the CPU type flag.
+ assert((context.context_flags & MD_CONTEXT_ARM) ||
+ (context.context_flags & MD_CONTEXT_ARM_OLD));
+ // It doesn't make sense to store ARM registers in big-endian form.
+ assert(dump.endianness() == kLittleEndian);
+ D32(context.context_flags);
+ for (int i = 0; i < MD_CONTEXT_ARM_GPR_COUNT; ++i)
+ D32(context.iregs[i]);
+ D32(context.cpsr);
+ D64(context.float_save.fpscr);
+ for (int i = 0; i < MD_FLOATINGSAVEAREA_ARM_FPR_COUNT; ++i)
+ D64(context.float_save.regs[i]);
+ for (int i = 0; i < MD_FLOATINGSAVEAREA_ARM_FPEXTRA_COUNT; ++i)
+ D32(context.float_save.extra[i]);
+ assert(Size() == sizeof(MDRawContextARM));
+}
+
+Context::Context(const Dump &dump, const MDRawContextMIPS &context)
+ : Section(dump) {
+ // The caller should have properly set the CPU type flag.
+ assert(context.context_flags & MD_CONTEXT_MIPS);
+ D32(context.context_flags);
+ D32(context._pad0);
+
+ for (int i = 0; i < MD_CONTEXT_MIPS_GPR_COUNT; ++i)
+ D64(context.iregs[i]);
+
+ D64(context.mdhi);
+ D64(context.mdlo);
+
+ for (int i = 0; i < MD_CONTEXT_MIPS_DSP_COUNT; ++i)
+ D32(context.hi[i]);
+
+ for (int i = 0; i < MD_CONTEXT_MIPS_DSP_COUNT; ++i)
+ D32(context.lo[i]);
+
+ D32(context.dsp_control);
+ D32(context._pad1);
+
+ D64(context.epc);
+ D64(context.badvaddr);
+ D32(context.status);
+ D32(context.cause);
+
+ for (int i = 0; i < MD_FLOATINGSAVEAREA_MIPS_FPR_COUNT; ++i)
+ D64(context.float_save.regs[i]);
+
+ D32(context.float_save.fpcsr);
+ D32(context.float_save.fir);
+
+ assert(Size() == sizeof(MDRawContextMIPS));
+}
+
+Thread::Thread(const Dump &dump,
+ uint32_t thread_id, const Memory &stack, const Context &context,
+ uint32_t suspend_count, uint32_t priority_class,
+ uint32_t priority, uint64_t teb) : Section(dump) {
+ D32(thread_id);
+ D32(suspend_count);
+ D32(priority_class);
+ D32(priority);
+ D64(teb);
+ stack.CiteMemoryIn(this);
+ context.CiteLocationIn(this);
+ assert(Size() == sizeof(MDRawThread));
+}
+
+Module::Module(const Dump &dump,
+ uint64_t base_of_image,
+ uint32_t size_of_image,
+ const String &name,
+ uint32_t time_date_stamp,
+ uint32_t checksum,
+ const MDVSFixedFileInfo &version_info,
+ const Section *cv_record,
+ const Section *misc_record) : Section(dump) {
+ D64(base_of_image);
+ D32(size_of_image);
+ D32(checksum);
+ D32(time_date_stamp);
+ name.CiteStringIn(this);
+ D32(version_info.signature);
+ D32(version_info.struct_version);
+ D32(version_info.file_version_hi);
+ D32(version_info.file_version_lo);
+ D32(version_info.product_version_hi);
+ D32(version_info.product_version_lo);
+ D32(version_info.file_flags_mask);
+ D32(version_info.file_flags);
+ D32(version_info.file_os);
+ D32(version_info.file_type);
+ D32(version_info.file_subtype);
+ D32(version_info.file_date_hi);
+ D32(version_info.file_date_lo);
+ if (cv_record)
+ cv_record->CiteLocationIn(this);
+ else
+ D32(0).D32(0);
+ if (misc_record)
+ misc_record->CiteLocationIn(this);
+ else
+ D32(0).D32(0);
+ D64(0).D64(0);
+}
+
+const MDVSFixedFileInfo Module::stock_version_info = {
+ MD_VSFIXEDFILEINFO_SIGNATURE, // signature
+ MD_VSFIXEDFILEINFO_VERSION, // struct_version
+ 0x11111111, // file_version_hi
+ 0x22222222, // file_version_lo
+ 0x33333333, // product_version_hi
+ 0x44444444, // product_version_lo
+ MD_VSFIXEDFILEINFO_FILE_FLAGS_DEBUG, // file_flags_mask
+ MD_VSFIXEDFILEINFO_FILE_FLAGS_DEBUG, // file_flags
+ MD_VSFIXEDFILEINFO_FILE_OS_NT | MD_VSFIXEDFILEINFO_FILE_OS__WINDOWS32,
+ // file_os
+ MD_VSFIXEDFILEINFO_FILE_TYPE_APP, // file_type
+ MD_VSFIXEDFILEINFO_FILE_SUBTYPE_UNKNOWN, // file_subtype
+ 0, // file_date_hi
+ 0 // file_date_lo
+};
+
+UnloadedModule::UnloadedModule(const Dump &dump,
+ uint64_t base_of_image,
+ uint32_t size_of_image,
+ const String &name,
+ uint32_t checksum,
+ uint32_t time_date_stamp) : Section(dump) {
+ D64(base_of_image);
+ D32(size_of_image);
+ D32(checksum);
+ D32(time_date_stamp);
+ name.CiteStringIn(this);
+}
+
+UnloadedModuleList::UnloadedModuleList(const Dump &dump, uint32_t type)
+ : List<UnloadedModule>(dump, type, false) {
+ D32(sizeof(MDRawUnloadedModuleList));
+ D32(sizeof(MDRawUnloadedModule));
+ D32(count_label_);
+}
+
+Exception::Exception(const Dump &dump,
+ const Context &context,
+ uint32_t thread_id,
+ uint32_t exception_code,
+ uint32_t exception_flags,
+ uint64_t exception_address)
+ : Stream(dump, MD_EXCEPTION_STREAM) {
+ D32(thread_id);
+ D32(0); // __align
+ D32(exception_code);
+ D32(exception_flags);
+ D64(0); // exception_record
+ D64(exception_address);
+ D32(0); // number_parameters
+ D32(0); // __align
+ for (int i = 0; i < MD_EXCEPTION_MAXIMUM_PARAMETERS; ++i)
+ D64(0); // exception_information
+ context.CiteLocationIn(this);
+ assert(Size() == sizeof(MDRawExceptionStream));
+}
+
+Dump::Dump(uint64_t flags,
+ Endianness endianness,
+ uint32_t version,
+ uint32_t date_time_stamp)
+ : test_assembler::Section(endianness),
+ file_start_(0),
+ stream_directory_(*this),
+ stream_count_(0),
+ thread_list_(*this, MD_THREAD_LIST_STREAM),
+ module_list_(*this, MD_MODULE_LIST_STREAM),
+ unloaded_module_list_(*this, MD_UNLOADED_MODULE_LIST_STREAM),
+ memory_list_(*this, MD_MEMORY_LIST_STREAM)
+ {
+ D32(MD_HEADER_SIGNATURE);
+ D32(version);
+ D32(stream_count_label_);
+ D32(stream_directory_rva_);
+ D32(0);
+ D32(date_time_stamp);
+ D64(flags);
+ assert(Size() == sizeof(MDRawHeader));
+}
+
+Dump &Dump::Add(SynthMinidump::Section *section) {
+ section->Finish(file_start_ + Size());
+ Append(*section);
+ return *this;
+}
+
+Dump &Dump::Add(Stream *stream) {
+ Add(static_cast<SynthMinidump::Section *>(stream));
+ stream->CiteStreamIn(&stream_directory_);
+ stream_count_++;
+ return *this;
+}
+
+Dump &Dump::Add(Memory *memory) {
+ // Add the memory contents themselves to the file.
+ Add(static_cast<SynthMinidump::Section *>(memory));
+
+ // The memory list is a list of MDMemoryDescriptors, not of actual
+ // memory elements. Produce a descriptor, and add that to the list.
+ SynthMinidump::Section descriptor(*this);
+ memory->CiteMemoryIn(&descriptor);
+ memory_list_.Add(&descriptor);
+ return *this;
+}
+
+Dump &Dump::Add(Thread *thread) {
+ thread_list_.Add(thread);
+ return *this;
+}
+
+Dump &Dump::Add(Module *module) {
+ module_list_.Add(module);
+ return *this;
+}
+
+Dump &Dump::Add(UnloadedModule *unloaded_module) {
+ unloaded_module_list_.Add(unloaded_module);
+ return *this;
+}
+
+void Dump::Finish() {
+ if (!thread_list_.Empty()) Add(&thread_list_);
+ if (!module_list_.Empty()) Add(&module_list_);
+ if (!unloaded_module_list_.Empty()) Add(&unloaded_module_list_);
+ if (!memory_list_.Empty()) Add(&memory_list_);
+
+ // Create the stream directory. We don't use
+ // stream_directory_.Finish here, because the stream directory isn't
+ // cited using a location descriptor; rather, the Minidump header
+ // has the stream count and MDRVA.
+ stream_count_label_ = stream_count_;
+ stream_directory_rva_ = file_start_ + Size();
+ Append(static_cast<test_assembler::Section &>(stream_directory_));
+}
+
+} // namespace SynthMinidump
+
+} // namespace google_breakpad
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/synth_minidump.h b/toolkit/crashreporter/google-breakpad/src/processor/synth_minidump.h
new file mode 100644
index 0000000000..8f49cfff22
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/synth_minidump.h
@@ -0,0 +1,398 @@
+// -*- 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>
+
+// synth_minidump.h: Interface to SynthMinidump: fake minidump generator.
+//
+// We treat a minidump file as the concatenation of a bunch of
+// test_assembler::Sections. The file header, stream directory,
+// streams, memory regions, strings, and so on --- each is a Section
+// that eventually gets appended to the minidump. Dump, Memory,
+// Context, Thread, and so on all inherit from test_assembler::Section.
+// For example:
+//
+// using google_breakpad::test_assembler::kLittleEndian;
+// using google_breakpad::SynthMinidump::Context;
+// using google_breakpad::SynthMinidump::Dump;
+// using google_breakpad::SynthMinidump::Memory;
+// using google_breakpad::SynthMinidump::Thread;
+//
+// Dump minidump(MD_NORMAL, kLittleEndian);
+//
+// Memory stack1(minidump, 0x569eb0a9);
+// ... build contents of stack1 with test_assembler::Section functions ...
+//
+// MDRawContextX86 x86_context1;
+// x86_context1.context_flags = MD_CONTEXT_X86;
+// x86_context1.eip = 0x7c90eb94;
+// x86_context1.esp = 0x569eb0a9;
+// x86_context1.ebp = x86_context1.esp + something appropriate;
+// Context context1(minidump, x86_context1);
+//
+// Thread thread1(minidump, 0xe4a4821d, stack1, context1);
+//
+// minidump.Add(&stack1);
+// minidump.Add(&context1);
+// minidump.Add(&thread1);
+// minidump.Finish();
+//
+// string contents;
+// EXPECT_TRUE(minidump.GetContents(&contents));
+// // contents now holds the bytes of a minidump file
+//
+// Because the test_assembler classes let us write Label references to
+// sections before the Labels' values are known, this gives us
+// flexibility in how we put the dump together: minidump pieces can
+// hold the file offsets of other minidump pieces before the
+// referents' positions have been decided. As long as everything has
+// been placed by the time we call dump.GetContents to obtain the
+// bytes, all the Labels' values will be known, and everything will
+// get patched up appropriately.
+//
+// The dump.Add(thing) functions append THINGS's contents to the
+// minidump, but they also do two other things:
+//
+// - dump.Add(thing) invokes thing->Finish, which tells *thing the
+// offset within the file at which it was placed, and allows *thing
+// to do any final content generation.
+//
+// - If THING is something which should receive an entry in some sort
+// of list or directory, then dump.Add(THING) automatically creates
+// the appropriate directory or list entry. Streams must appear in
+// the stream directory; memory ranges should be listed in the
+// memory list; threads should be placed in the thread list; and so
+// on.
+//
+// By convention, Section subclass constructors that take references
+// to other Sections do not take care of 'Add'ing their arguments to
+// the dump. For example, although the Thread constructor takes
+// references to a Memory and a Context, it does not add them to the
+// dump on the caller's behalf. Rather, the caller is responsible for
+// 'Add'ing every section they create. This allows Sections to be
+// cited from more than one place; for example, Memory ranges are
+// cited both from Thread objects (as their stack contents) and by the
+// memory list stream.
+//
+// If you forget to Add some Section, the Dump::GetContents call will
+// fail, as the test_assembler::Labels used to cite the Section's
+// contents from elsewhere will still be undefined.
+#ifndef PROCESSOR_SYNTH_MINIDUMP_H_
+#define PROCESSOR_SYNTH_MINIDUMP_H_
+
+#include <assert.h>
+
+#include <iostream>
+#include <string>
+
+#include "common/test_assembler.h"
+#include "common/using_std_string.h"
+#include "google_breakpad/common/breakpad_types.h"
+#include "google_breakpad/common/minidump_format.h"
+
+namespace google_breakpad {
+
+namespace SynthMinidump {
+
+using test_assembler::Endianness;
+using test_assembler::kBigEndian;
+using test_assembler::kLittleEndian;
+using test_assembler::kUnsetEndian;
+using test_assembler::Label;
+
+class Dump;
+class Memory;
+class String;
+
+// A test_assembler::Section which will be appended to a minidump.
+class Section: public test_assembler::Section {
+ public:
+ explicit Section(const Dump &dump);
+
+ // Append an MDLocationDescriptor referring to this section to SECTION.
+ // If 'this' is NULL, append a descriptor with a zero length and MDRVA.
+ //
+ // (I couldn't find the language in the C++ standard that says that
+ // invoking member functions of a NULL pointer to a class type is
+ // bad, if such language exists. Having this function handle NULL
+ // 'this' is convenient, but if it causes trouble, it's not hard to
+ // do differently.)
+ void CiteLocationIn(test_assembler::Section *section) const;
+
+ // Note that this section's contents are complete, and that it has
+ // been placed in the minidump file at OFFSET. The 'Add' member
+ // functions call the Finish member function of the object being
+ // added for you; if you are 'Add'ing this section, you needn't Finish it.
+ virtual void Finish(const Label &offset) {
+ file_offset_ = offset; size_ = Size();
+ }
+
+ protected:
+ // This section's size and offset within the minidump file.
+ Label file_offset_, size_;
+};
+
+// A stream within a minidump file. 'Add'ing a stream to a minidump
+// creates an entry for it in the minidump's stream directory.
+class Stream: public Section {
+ public:
+ // Create a stream of type TYPE. You can append whatever contents
+ // you like to this stream using the test_assembler::Section methods.
+ Stream(const Dump &dump, uint32_t type) : Section(dump), type_(type) { }
+
+ // Append an MDRawDirectory referring to this stream to SECTION.
+ void CiteStreamIn(test_assembler::Section *section) const;
+
+ private:
+ // The type of this stream.
+ uint32_t type_;
+};
+
+class SystemInfo: public Stream {
+ public:
+ // Create an MD_SYSTEM_INFO_STREAM stream belonging to DUMP holding
+ // an MDRawSystem info structure initialized with the values from
+ // SYSTEM_INFO, except that the csd_version field is replaced with
+ // the file offset of the string CSD_VERSION, which can be 'Add'ed
+ // to the dump at the desired location.
+ //
+ // Remember that you are still responsible for 'Add'ing CSD_VERSION
+ // to the dump yourself.
+ SystemInfo(const Dump &dump,
+ const MDRawSystemInfo &system_info,
+ const String &csd_version);
+
+ // Stock MDRawSystemInfo information and associated strings, for
+ // writing tests.
+ static const MDRawSystemInfo windows_x86;
+ static const string windows_x86_csd_version;
+};
+
+// An MDString: a string preceded by a 32-bit length.
+class String: public Section {
+ public:
+ String(const Dump &dump, const string &value);
+
+ // Append an MDRVA referring to this string to SECTION.
+ void CiteStringIn(test_assembler::Section *section) const;
+};
+
+// A range of memory contents. 'Add'ing a memory range to a minidump
+// creates n entry for it in the minidump's memory list. By
+// convention, the 'start', 'Here', and 'Mark' member functions refer
+// to memory addresses.
+class Memory: public Section {
+ public:
+ Memory(const Dump &dump, uint64_t address)
+ : Section(dump), address_(address) { start() = address; }
+
+ // Append an MDMemoryDescriptor referring to this memory range to SECTION.
+ void CiteMemoryIn(test_assembler::Section *section) const;
+
+ private:
+ // The process address from which these memory contents were taken.
+ // Shouldn't this be a Label?
+ uint64_t address_;
+};
+
+class Context: public Section {
+ public:
+ // Create a context belonging to DUMP whose contents are a copy of CONTEXT.
+ Context(const Dump &dump, const MDRawContextX86 &context);
+ Context(const Dump &dump, const MDRawContextARM &context);
+ Context(const Dump &dump, const MDRawContextMIPS &context);
+ // Add an empty context to the dump.
+ Context(const Dump &dump) : Section(dump) {}
+ // Add constructors for other architectures here. Remember to byteswap.
+};
+
+class Thread: public Section {
+ public:
+ // Create a thread belonging to DUMP with the given values, citing
+ // STACK and CONTEXT (which you must Add to the dump separately).
+ Thread(const Dump &dump,
+ uint32_t thread_id,
+ const Memory &stack,
+ const Context &context,
+ uint32_t suspend_count = 0,
+ uint32_t priority_class = 0,
+ uint32_t priority = 0,
+ uint64_t teb = 0);
+};
+
+class Module: public Section {
+ public:
+ // Create a module with the given values. Note that CV_RECORD and
+ // MISC_RECORD can be NULL, in which case the corresponding location
+ // descriptior in the minidump will have a length of zero.
+ Module(const Dump &dump,
+ uint64_t base_of_image,
+ uint32_t size_of_image,
+ const String &name,
+ uint32_t time_date_stamp = 1262805309,
+ uint32_t checksum = 0,
+ const MDVSFixedFileInfo &version_info = Module::stock_version_info,
+ const Section *cv_record = NULL,
+ const Section *misc_record = NULL);
+
+ private:
+ // A standard MDVSFixedFileInfo structure to use as a default for
+ // minidumps. There's no reason to make users write out all this crap
+ // over and over.
+ static const MDVSFixedFileInfo stock_version_info;
+};
+
+class UnloadedModule: public Section {
+ public:
+ UnloadedModule(const Dump &dump,
+ uint64_t base_of_image,
+ uint32_t size_of_image,
+ const String &name,
+ uint32_t checksum = 0,
+ uint32_t time_date_stamp = 1262805309);
+};
+
+class Exception : public Stream {
+public:
+ Exception(const Dump &dump,
+ const Context &context,
+ uint32_t thread_id = 0,
+ uint32_t exception_code = 0,
+ uint32_t exception_flags = 0,
+ uint64_t exception_address = 0);
+};
+
+// A list of entries starting with a 32-bit count, like a memory list
+// or a thread list.
+template<typename Element>
+class List: public Stream {
+ public:
+ List(const Dump &dump, uint32_t type) : Stream(dump, type), count_(0) {
+ D32(count_label_);
+ }
+
+ // Add ELEMENT to this list.
+ void Add(Element *element) {
+ element->Finish(file_offset_ + Size());
+ Append(*element);
+ count_++;
+ }
+
+ // Return true if this List is empty, false otherwise.
+ bool Empty() { return count_ == 0; }
+
+ // Finish up the contents of this section, mark it as having been
+ // placed at OFFSET.
+ virtual void Finish(const Label &offset) {
+ Stream::Finish(offset);
+ count_label_ = count_;
+ }
+
+ private:
+ size_t count_;
+
+ protected:
+ // This constructor allows derived lists to specify their own layout
+ // rather than starting with count as specified in the public constructor.
+ List(const Dump &dump, uint32_t type, bool) : Stream(dump, type), count_(0) {}
+
+ Label count_label_;
+};
+
+class UnloadedModuleList : public List<UnloadedModule> {
+ public:
+ UnloadedModuleList(const Dump &dump, uint32_t type);
+};
+
+class Dump: public test_assembler::Section {
+ public:
+
+ // Create a test_assembler::Section containing a minidump file whose
+ // header uses the given values. ENDIANNESS determines the
+ // endianness of the signature; we set this section's default
+ // endianness by this.
+ Dump(uint64_t flags,
+ Endianness endianness = kLittleEndian,
+ uint32_t version = MD_HEADER_VERSION,
+ uint32_t date_time_stamp = 1262805309);
+
+ // The following functions call OBJECT->Finish(), and append the
+ // contents of OBJECT to this minidump. They also record OBJECT in
+ // whatever directory or list is appropriate for its type. The
+ // stream directory, memory list, thread list, and module list are
+ // accumulated this way.
+ Dump &Add(SynthMinidump::Section *object); // simply append data
+ Dump &Add(Stream *object); // append, record in stream directory
+ Dump &Add(Memory *object); // append, record in memory list
+ Dump &Add(Thread *object); // append, record in thread list
+ Dump &Add(Module *object); // append, record in module list
+ Dump &Add(UnloadedModule *object); // append, record in unloaded module list
+
+ // Complete the construction of the minidump, given the Add calls
+ // we've seen up to this point. After this call, this Dump's
+ // contents are complete, all labels should be defined if everything
+ // Cited has been Added, and you may call GetContents on it.
+ void Finish();
+
+ private:
+ // A label representing the start of the minidump file.
+ Label file_start_;
+
+ // The stream directory. We construct this incrementally from
+ // Add(Stream *) calls.
+ SynthMinidump::Section stream_directory_; // The directory's contents.
+ size_t stream_count_; // The number of streams so far.
+ Label stream_count_label_; // Cited in file header.
+ Label stream_directory_rva_; // The directory's file offset.
+
+ // This minidump's thread list. We construct this incrementally from
+ // Add(Thread *) calls.
+ List<Thread> thread_list_;
+
+ // This minidump's module list. We construct this incrementally from
+ // Add(Module *) calls.
+ List<Module> module_list_;
+
+ // This minidump's unloaded module list. We construct this incrementally from
+ // Add(UnloadedModule *) calls.
+ UnloadedModuleList unloaded_module_list_;
+
+ // This minidump's memory list. We construct this incrementally from
+ // Add(Memory *) calls. This is actually a list of MDMemoryDescriptors,
+ // not memory ranges --- thus the odd type.
+ List<SynthMinidump::Section> memory_list_;
+};
+
+} // namespace SynthMinidump
+
+} // namespace google_breakpad
+
+#endif // PROCESSOR_SYNTH_MINIDUMP_H_
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/synth_minidump_unittest.cc b/toolkit/crashreporter/google-breakpad/src/processor/synth_minidump_unittest.cc
new file mode 100644
index 0000000000..8835b44933
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/synth_minidump_unittest.cc
@@ -0,0 +1,336 @@
+// 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>
+
+// synth_minidump_unittest.cc: Unit tests for google_breakpad::SynthMinidump
+// classes.
+
+#include <sstream>
+#include <string>
+
+#include "breakpad_googletest_includes.h"
+#include "common/using_std_string.h"
+#include "google_breakpad/common/minidump_format.h"
+#include "processor/synth_minidump.h"
+#include "processor/synth_minidump_unittest_data.h"
+
+using google_breakpad::SynthMinidump::Context;
+using google_breakpad::SynthMinidump::Dump;
+using google_breakpad::SynthMinidump::Exception;
+using google_breakpad::SynthMinidump::List;
+using google_breakpad::SynthMinidump::Memory;
+using google_breakpad::SynthMinidump::Module;
+using google_breakpad::SynthMinidump::Section;
+using google_breakpad::SynthMinidump::Stream;
+using google_breakpad::SynthMinidump::String;
+using google_breakpad::SynthMinidump::SystemInfo;
+using google_breakpad::test_assembler::kBigEndian;
+using google_breakpad::test_assembler::kLittleEndian;
+using google_breakpad::test_assembler::Label;
+
+TEST(Section, Simple) {
+ Dump dump(0);
+ Section section(dump);
+ section.L32(0x12345678);
+ section.Finish(0);
+ string contents;
+ ASSERT_TRUE(section.GetContents(&contents));
+ EXPECT_EQ(string("\x78\x56\x34\x12", 4), contents);
+}
+
+TEST(Section, CiteLocationIn) {
+ Dump dump(0, kBigEndian);
+ Section section1(dump), section2(dump);
+ section1.Append("order");
+ section2.Append("mayhem");
+ section2.Finish(0x32287ec2);
+ section2.CiteLocationIn(&section1);
+ string contents;
+ ASSERT_TRUE(section1.GetContents(&contents));
+ string expected("order\0\0\0\x06\x32\x28\x7e\xc2", 13);
+ EXPECT_EQ(expected, contents);
+}
+
+TEST(Stream, CiteStreamIn) {
+ Dump dump(0, kLittleEndian);
+ Stream stream(dump, 0x40cae2b3);
+ Section section(dump);
+ stream.Append("stream contents");
+ section.Append("section contents");
+ stream.Finish(0x41424344);
+ stream.CiteStreamIn(&section);
+ string contents;
+ ASSERT_TRUE(section.GetContents(&contents));
+ string expected("section contents"
+ "\xb3\xe2\xca\x40"
+ "\x0f\0\0\0"
+ "\x44\x43\x42\x41",
+ 16 + 4 + 4 + 4);
+ EXPECT_EQ(expected, contents);
+}
+
+TEST(Memory, CiteMemoryIn) {
+ Dump dump(0, kBigEndian);
+ Memory memory(dump, 0x76d010874ab019f9ULL);
+ Section section(dump);
+ memory.Append("memory contents");
+ section.Append("section contents");
+ memory.Finish(0x51525354);
+ memory.CiteMemoryIn(&section);
+ string contents;
+ ASSERT_TRUE(section.GetContents(&contents));
+ string expected("section contents"
+ "\x76\xd0\x10\x87\x4a\xb0\x19\xf9"
+ "\0\0\0\x0f"
+ "\x51\x52\x53\x54",
+ 16 + 8 + 4 + 4);
+ EXPECT_EQ(contents, expected);
+}
+
+TEST(Memory, Here) {
+ Dump dump(0, kBigEndian);
+ Memory memory(dump, 0x89979731eb060ed4ULL);
+ memory.Append(1729, 42);
+ Label l = memory.Here();
+ ASSERT_EQ(0x89979731eb060ed4ULL + 1729, l.Value());
+}
+
+TEST(Context, X86) {
+ Dump dump(0, kLittleEndian);
+ assert(x86_raw_context.context_flags & MD_CONTEXT_X86);
+ Context context(dump, x86_raw_context);
+ string contents;
+ ASSERT_TRUE(context.GetContents(&contents));
+ EXPECT_EQ(sizeof(x86_expected_contents), contents.size());
+ EXPECT_TRUE(memcmp(contents.data(), x86_expected_contents, contents.size())
+ == 0);
+}
+
+TEST(Context, ARM) {
+ Dump dump(0, kLittleEndian);
+ assert(arm_raw_context.context_flags & MD_CONTEXT_ARM);
+ Context context(dump, arm_raw_context);
+ string contents;
+ ASSERT_TRUE(context.GetContents(&contents));
+ EXPECT_EQ(sizeof(arm_expected_contents), contents.size());
+ EXPECT_TRUE(memcmp(contents.data(), arm_expected_contents, contents.size())
+ == 0);
+}
+
+TEST(ContextDeathTest, X86BadFlags) {
+ Dump dump(0, kLittleEndian);
+ MDRawContextX86 raw;
+ raw.context_flags = MD_CONTEXT_AMD64;
+ ASSERT_DEATH(Context context(dump, raw);,
+ "context\\.context_flags & (0x[0-9a-f]+|MD_CONTEXT_X86)");
+}
+
+TEST(ContextDeathTest, X86BadEndianness) {
+ Dump dump(0, kBigEndian);
+ MDRawContextX86 raw;
+ raw.context_flags = MD_CONTEXT_X86;
+ ASSERT_DEATH(Context context(dump, raw);,
+ "dump\\.endianness\\(\\) == kLittleEndian");
+}
+
+TEST(Thread, Simple) {
+ Dump dump(0, kLittleEndian);
+ Context context(dump, x86_raw_context);
+ context.Finish(0x8665da0c);
+ Memory stack(dump, 0xaad55a93cc3c0efcULL);
+ stack.Append("stack contents");
+ stack.Finish(0xe08cdbd1);
+ google_breakpad::SynthMinidump::Thread thread(
+ dump, 0x3d7ec360, stack, context,
+ 0x3593f44d, // suspend count
+ 0xab352b82, // priority class
+ 0x2753d838, // priority
+ 0xeb2de4be3f29e3e9ULL); // thread environment block
+ string contents;
+ ASSERT_TRUE(thread.GetContents(&contents));
+ static const uint8_t expected_bytes[] = {
+ 0x60, 0xc3, 0x7e, 0x3d, // thread id
+ 0x4d, 0xf4, 0x93, 0x35, // suspend count
+ 0x82, 0x2b, 0x35, 0xab, // priority class
+ 0x38, 0xd8, 0x53, 0x27, // priority
+ 0xe9, 0xe3, 0x29, 0x3f, 0xbe, 0xe4, 0x2d, 0xeb, // thread environment block
+ 0xfc, 0x0e, 0x3c, 0xcc, 0x93, 0x5a, 0xd5, 0xaa, // stack address
+ 0x0e, 0x00, 0x00, 0x00, // stack size
+ 0xd1, 0xdb, 0x8c, 0xe0, // stack MDRVA
+ 0xcc, 0x02, 0x00, 0x00, // context size
+ 0x0c, 0xda, 0x65, 0x86 // context MDRVA
+ };
+ EXPECT_EQ(sizeof(expected_bytes), contents.size());
+ EXPECT_TRUE(memcmp(contents.data(), expected_bytes, contents.size()) == 0);
+}
+
+TEST(Exception, Simple) {
+ Dump dump(0, kLittleEndian);
+ Context context(dump, x86_raw_context);
+ context.Finish(0x8665da0c);
+
+ Exception exception(dump, context,
+ 0x1234abcd, // thread id
+ 0xdcba4321, // exception code
+ 0xf0e0d0c0, // exception flags
+ 0x0919a9b9c9d9e9f9ULL); // exception address
+ string contents;
+ ASSERT_TRUE(exception.GetContents(&contents));
+ static const uint8_t expected_bytes[] = {
+ 0xcd, 0xab, 0x34, 0x12, // thread id
+ 0x00, 0x00, 0x00, 0x00, // __align
+ 0x21, 0x43, 0xba, 0xdc, // exception code
+ 0xc0, 0xd0, 0xe0, 0xf0, // exception flags
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // exception record
+ 0xf9, 0xe9, 0xd9, 0xc9, 0xb9, 0xa9, 0x19, 0x09, // exception address
+ 0x00, 0x00, 0x00, 0x00, // number parameters
+ 0x00, 0x00, 0x00, 0x00, // __align
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // exception_information
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // exception_information
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // exception_information
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // exception_information
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // exception_information
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // exception_information
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // exception_information
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // exception_information
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // exception_information
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // exception_information
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // exception_information
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // exception_information
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // exception_information
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // exception_information
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // exception_information
+ 0xcc, 0x02, 0x00, 0x00, // context size
+ 0x0c, 0xda, 0x65, 0x86 // context MDRVA
+ };
+ EXPECT_EQ(sizeof(expected_bytes), contents.size());
+ EXPECT_TRUE(memcmp(contents.data(), expected_bytes, contents.size()) == 0);
+}
+
+TEST(String, Simple) {
+ Dump dump(0, kBigEndian);
+ String s(dump, "All mimsy were the borogoves");
+ string contents;
+ ASSERT_TRUE(s.GetContents(&contents));
+ static const char expected[] =
+ "\x00\x00\x00\x38\0A\0l\0l\0 \0m\0i\0m\0s\0y\0 \0w\0e\0r\0e"
+ "\0 \0t\0h\0e\0 \0b\0o\0r\0o\0g\0o\0v\0e\0s";
+ string expected_string(expected, sizeof(expected) - 1);
+ EXPECT_EQ(expected_string, contents);
+}
+
+TEST(String, CiteStringIn) {
+ Dump dump(0, kLittleEndian);
+ String s(dump, "and the mome wraths outgrabe");
+ Section section(dump);
+ section.Append("initial");
+ s.CiteStringIn(&section);
+ s.Finish(0xdc2bb469);
+ string contents;
+ ASSERT_TRUE(section.GetContents(&contents));
+ EXPECT_EQ(string("initial\x69\xb4\x2b\xdc", 7 + 4), contents);
+}
+
+TEST(List, Empty) {
+ Dump dump(0, kBigEndian);
+ List<Section> list(dump, 0x2442779c);
+ EXPECT_TRUE(list.Empty());
+ list.Finish(0x84e09808);
+ string contents;
+ ASSERT_TRUE(list.GetContents(&contents));
+ EXPECT_EQ(string("\0\0\0\0", 4), contents);
+}
+
+TEST(List, Two) {
+ Dump dump(0, kBigEndian);
+ List<Section> list(dump, 0x26c9f498);
+ Section section1(dump);
+ section1.Append("section one contents");
+ EXPECT_TRUE(list.Empty());
+ list.Add(&section1);
+ EXPECT_FALSE(list.Empty());
+ Section section2(dump);
+ section2.Append("section two contents");
+ list.Add(&section2);
+ list.Finish(0x1e5bb60e);
+ string contents;
+ ASSERT_TRUE(list.GetContents(&contents));
+ EXPECT_EQ(string("\0\0\0\x02section one contentssection two contents", 44),
+ contents);
+}
+
+TEST(Dump, Header) {
+ Dump dump(0x9f738b33685cc84cULL, kLittleEndian, 0xb3817faf, 0x2c741c0a);
+ dump.Finish();
+ string contents;
+ ASSERT_TRUE(dump.GetContents(&contents));
+ ASSERT_EQ(string("\x4d\x44\x4d\x50" // signature
+ "\xaf\x7f\x81\xb3" // version
+ "\0\0\0\0" // stream count
+ "\x20\0\0\0" // directory RVA (could be anything)
+ "\0\0\0\0" // checksum
+ "\x0a\x1c\x74\x2c" // time_date_stamp
+ "\x4c\xc8\x5c\x68\x33\x8b\x73\x9f", // flags
+ 32),
+ contents);
+}
+
+TEST(Dump, HeaderBigEndian) {
+ Dump dump(0x206ce3cc6fb8e0f0ULL, kBigEndian, 0x161693e2, 0x35667744);
+ dump.Finish();
+ string contents;
+ ASSERT_TRUE(dump.GetContents(&contents));
+ ASSERT_EQ(string("\x50\x4d\x44\x4d" // signature
+ "\x16\x16\x93\xe2" // version
+ "\0\0\0\0" // stream count
+ "\0\0\0\x20" // directory RVA (could be anything)
+ "\0\0\0\0" // checksum
+ "\x35\x66\x77\x44" // time_date_stamp
+ "\x20\x6c\xe3\xcc\x6f\xb8\xe0\xf0", // flags
+ 32),
+ contents);
+}
+
+TEST(Dump, OneSection) {
+ Dump dump(0, kLittleEndian);
+ Section section(dump);
+ section.Append("section contents");
+ dump.Add(&section);
+ dump.Finish();
+ string dump_contents;
+ // Just check for undefined labels; don't worry about the contents.
+ ASSERT_TRUE(dump.GetContents(&dump_contents));
+
+ Section referencing_section(dump);
+ section.CiteLocationIn(&referencing_section);
+ string contents;
+ ASSERT_TRUE(referencing_section.GetContents(&contents));
+ ASSERT_EQ(string("\x10\0\0\0\x20\0\0\0", 8), contents);
+}
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/synth_minidump_unittest_data.h b/toolkit/crashreporter/google-breakpad/src/processor/synth_minidump_unittest_data.h
new file mode 100644
index 0000000000..3403372e6c
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/synth_minidump_unittest_data.h
@@ -0,0 +1,418 @@
+// -*- mode: C++ -*-
+
+// Not copyrightable: random test data.
+// synth_minidump_unittest_data.h: verbose test data for SynthMinidump tests.
+
+#ifndef PROCESSOR_SYNTH_MINIDUMP_UNITTEST_DATA_H_
+#define PROCESSOR_SYNTH_MINIDUMP_UNITTEST_DATA_H_
+
+#include "google_breakpad/common/minidump_format.h"
+
+static const MDRawContextX86 x86_raw_context = {
+ 0xded5d71b, // context_flags
+ 0x9fdb432e, // dr0
+ 0x26b7a81a, // dr1
+ 0xcac7e348, // dr2
+ 0xcf99ec09, // dr3
+ 0x7dc8c2cd, // dr6
+ 0x21deb880, // dr7
+
+ // float_save
+ {
+ 0x8a5d2bb0, // control_word
+ 0x0286c4c9, // status_word
+ 0xf1feea21, // tag_word
+ 0xb2d40576, // error_offset
+ 0x48146cde, // error_selector
+ 0x983f9b21, // data_offset
+ 0x475be12c, // data_selector
+
+ // register_area
+ {
+ 0xd9, 0x04, 0x20, 0x6b, 0x88, 0x3a, 0x3f, 0xd5,
+ 0x59, 0x7a, 0xa9, 0xeb, 0xd0, 0x5c, 0xdf, 0xfe,
+ 0xad, 0xdd, 0x4a, 0x8b, 0x10, 0xcc, 0x9a, 0x33,
+ 0xcb, 0xb6, 0xf7, 0x86, 0xcd, 0x69, 0x25, 0xae,
+ 0x25, 0xe5, 0x7a, 0xa1, 0x8f, 0xb2, 0x84, 0xd9,
+ 0xf7, 0x2d, 0x8a, 0xa1, 0x80, 0x81, 0x7f, 0x67,
+ 0x07, 0xa8, 0x23, 0xf1, 0x8c, 0xdc, 0xd8, 0x04,
+ 0x8b, 0x9d, 0xb1, 0xcd, 0x61, 0x0c, 0x9c, 0x69,
+ 0xc7, 0x8d, 0x17, 0xb6, 0xe5, 0x0b, 0x94, 0xf7,
+ 0x78, 0x9b, 0x63, 0x49, 0xba, 0xfc, 0x08, 0x4d
+ },
+
+ 0x84c53a90, // cr0_npx_state
+ },
+
+ 0x79f71e76, // gs
+ 0x8107bd25, // fs
+ 0x452d2921, // es
+ 0x87ec2875, // ds
+ 0xf8bb73f5, // edi
+ 0xa63ebb88, // esi
+ 0x95d35ebe, // ebx
+ 0x17aa2456, // edx
+ 0x135fa208, // ecx
+ 0x500615e6, // eax
+ 0x66d14205, // ebp
+ 0x000719a5, // eip
+ 0x477b481b, // cs
+ 0x8684dfba, // eflags
+ 0xe33ccddf, // esp
+ 0xc0e65d33, // ss
+
+ // extended_registers
+ {
+ 0x68, 0x63, 0xdf, 0x50, 0xf7, 0x3b, 0xe8, 0xe5,
+ 0xcb, 0xd6, 0x66, 0x60, 0xe5, 0xa3, 0x58, 0xb3,
+ 0x6f, 0x34, 0xca, 0x02, 0x9b, 0x5f, 0xd0, 0x41,
+ 0xbd, 0xc5, 0x2d, 0xf8, 0xff, 0x15, 0xa2, 0xd0,
+ 0xe3, 0x2b, 0x3b, 0x8a, 0x9f, 0xc3, 0x9e, 0x28,
+ 0x0a, 0xc2, 0xac, 0x3b, 0x67, 0x37, 0x01, 0xfd,
+ 0xc3, 0xaf, 0x60, 0xf6, 0x2c, 0x4f, 0xa9, 0x52,
+ 0x92, 0xe5, 0x28, 0xde, 0x34, 0xb6, 0x2e, 0x44,
+ 0x15, 0xa4, 0xb6, 0xe4, 0xc9, 0x1a, 0x14, 0xb9,
+ 0x51, 0x33, 0x3c, 0xe0, 0xc7, 0x94, 0xf0, 0xf7,
+ 0x78, 0xdd, 0xe5, 0xca, 0xb7, 0xa6, 0xe0, 0x14,
+ 0xa6, 0x03, 0xab, 0x77, 0xad, 0xbd, 0xd2, 0x53,
+ 0x3d, 0x07, 0xe7, 0xaf, 0x90, 0x44, 0x71, 0xbe,
+ 0x0c, 0xdf, 0x2b, 0x97, 0x40, 0x48, 0xd5, 0xf9,
+ 0x62, 0x03, 0x91, 0x84, 0xd6, 0xdd, 0x29, 0x97,
+ 0x35, 0x02, 0xfb, 0x59, 0x97, 0xb0, 0xec, 0xa9,
+ 0x39, 0x6f, 0x81, 0x71, 0x2a, 0xf0, 0xe7, 0x2c,
+ 0x4e, 0x93, 0x90, 0xcb, 0x67, 0x69, 0xde, 0xd7,
+ 0x68, 0x3b, 0x0f, 0x69, 0xa8, 0xf4, 0xa8, 0x83,
+ 0x42, 0x80, 0x47, 0x65, 0x7a, 0xc9, 0x19, 0x5d,
+ 0xcb, 0x43, 0xa5, 0xff, 0xf8, 0x9e, 0x62, 0xf4,
+ 0xe2, 0x6c, 0xcc, 0x17, 0x55, 0x7c, 0x0d, 0x5c,
+ 0x8d, 0x16, 0x01, 0xd7, 0x3a, 0x0c, 0xf4, 0x7f,
+ 0x71, 0xdc, 0x48, 0xe9, 0x4b, 0xfe, 0x1a, 0xd0,
+ 0x04, 0x15, 0x33, 0xec, 0x78, 0xc6, 0x7e, 0xde,
+ 0x7c, 0x23, 0x18, 0x8d, 0x8f, 0xc2, 0x74, 0xc1,
+ 0x48, 0xcd, 0x5d, 0xee, 0xee, 0x81, 0x9e, 0x49,
+ 0x47, 0x8a, 0xf8, 0x61, 0xa3, 0x9c, 0x81, 0x96,
+ 0xbe, 0x2b, 0x5e, 0xbc, 0xcd, 0x34, 0x0a, 0x2a,
+ 0x3b, 0x8b, 0x7d, 0xa1, 0xf2, 0x8d, 0xb4, 0x51,
+ 0x9e, 0x14, 0x78, 0xa3, 0x58, 0x65, 0x2d, 0xd6,
+ 0x50, 0x40, 0x36, 0x32, 0x31, 0xd4, 0x3e, 0xc2,
+ 0xe0, 0x87, 0x1c, 0x05, 0x95, 0x80, 0x84, 0x24,
+ 0x08, 0x6f, 0x5b, 0xc7, 0xe1, 0x1d, 0xd5, 0xa3,
+ 0x94, 0x44, 0xa1, 0x7c, 0xd8, 0x4b, 0x86, 0xd2,
+ 0xc6, 0xa9, 0xf3, 0xe2, 0x4d, 0x6e, 0x1f, 0x0e,
+ 0xf2, 0xf5, 0x71, 0xf9, 0x71, 0x05, 0x24, 0xc9,
+ 0xc1, 0xe8, 0x91, 0x42, 0x61, 0x86, 0x57, 0x68,
+ 0xd9, 0xc9, 0x1d, 0xd5, 0x5a, 0xe9, 0xba, 0xe6,
+ 0x15, 0x8f, 0x87, 0xbd, 0x62, 0x56, 0xed, 0xda,
+ 0xc2, 0xa5, 0xd5, 0x39, 0xac, 0x05, 0x10, 0x14,
+ 0x4a, 0xe7, 0xe7, 0x3c, 0x3f, 0xb7, 0xbb, 0xed,
+ 0x01, 0x6e, 0xcd, 0xee, 0x81, 0xb4, 0x62, 0xf4,
+ 0x62, 0x16, 0xff, 0x20, 0xb4, 0xf0, 0xbc, 0xff,
+ 0x7d, 0xd9, 0xcf, 0x95, 0x30, 0x27, 0xe0, 0x2f,
+ 0x98, 0x53, 0x80, 0x15, 0x13, 0xef, 0x44, 0x58,
+ 0x12, 0x16, 0xdb, 0x11, 0xef, 0x73, 0x51, 0xcd,
+ 0x42, 0x3f, 0x98, 0x6c, 0xc9, 0x68, 0xc3, 0xf4,
+ 0x5b, 0x0f, 0x5d, 0x77, 0xed, 0xdf, 0x0f, 0xff,
+ 0xb8, 0x69, 0x98, 0x50, 0x77, 0x7a, 0xe8, 0x90,
+ 0x27, 0x46, 0x10, 0xd2, 0xb5, 0x00, 0x3b, 0x36,
+ 0x43, 0x6d, 0x67, 0x41, 0x20, 0x3a, 0x32, 0xe0,
+ 0x2e, 0x5a, 0xfb, 0x4e, 0x4f, 0xa4, 0xf7, 0xc2,
+ 0xe6, 0x81, 0x1a, 0x51, 0xa8, 0x7c, 0xd4, 0x60,
+ 0x7c, 0x45, 0xe2, 0xba, 0x5b, 0x42, 0xf3, 0xbf,
+ 0x28, 0xaa, 0xf2, 0x90, 0xe4, 0x94, 0xdd, 0xaa,
+ 0x22, 0xd3, 0x71, 0x33, 0xa1, 0x01, 0x43, 0x0e,
+ 0xfa, 0x46, 0xd2, 0x6e, 0x55, 0x5e, 0x49, 0xeb,
+ 0x94, 0xf0, 0xb0, 0xb1, 0x2e, 0xf2, 0x3d, 0x6c,
+ 0x00, 0x5e, 0x01, 0x56, 0x3b, 0xfd, 0x5b, 0xa1,
+ 0x2f, 0x63, 0x1d, 0xbf, 0xf9, 0xd8, 0x13, 0xf7,
+ 0x4d, 0xb7, 0x1e, 0x3d, 0x98, 0xd2, 0xee, 0xb8,
+ 0x48, 0xc8, 0x5b, 0x91, 0x0f, 0x54, 0x9e, 0x26,
+ 0xb2, 0xc7, 0x3a, 0x6c, 0x8a, 0x35, 0xe1, 0xba
+ }
+};
+
+static const uint8_t x86_expected_contents[] = {
+ 0x1b, 0xd7, 0xd5, 0xde,
+ 0x2e, 0x43, 0xdb, 0x9f,
+ 0x1a, 0xa8, 0xb7, 0x26,
+ 0x48, 0xe3, 0xc7, 0xca,
+ 0x09, 0xec, 0x99, 0xcf,
+ 0xcd, 0xc2, 0xc8, 0x7d,
+ 0x80, 0xb8, 0xde, 0x21,
+ 0xb0, 0x2b, 0x5d, 0x8a,
+ 0xc9, 0xc4, 0x86, 0x02,
+ 0x21, 0xea, 0xfe, 0xf1,
+ 0x76, 0x05, 0xd4, 0xb2,
+ 0xde, 0x6c, 0x14, 0x48,
+ 0x21, 0x9b, 0x3f, 0x98,
+ 0x2c, 0xe1, 0x5b, 0x47,
+
+ // float_save.register_area --- unswapped
+ 0xd9, 0x04, 0x20, 0x6b, 0x88, 0x3a, 0x3f, 0xd5,
+ 0x59, 0x7a, 0xa9, 0xeb, 0xd0, 0x5c, 0xdf, 0xfe,
+ 0xad, 0xdd, 0x4a, 0x8b, 0x10, 0xcc, 0x9a, 0x33,
+ 0xcb, 0xb6, 0xf7, 0x86, 0xcd, 0x69, 0x25, 0xae,
+ 0x25, 0xe5, 0x7a, 0xa1, 0x8f, 0xb2, 0x84, 0xd9,
+ 0xf7, 0x2d, 0x8a, 0xa1, 0x80, 0x81, 0x7f, 0x67,
+ 0x07, 0xa8, 0x23, 0xf1, 0x8c, 0xdc, 0xd8, 0x04,
+ 0x8b, 0x9d, 0xb1, 0xcd, 0x61, 0x0c, 0x9c, 0x69,
+ 0xc7, 0x8d, 0x17, 0xb6, 0xe5, 0x0b, 0x94, 0xf7,
+ 0x78, 0x9b, 0x63, 0x49, 0xba, 0xfc, 0x08, 0x4d,
+
+ 0x90, 0x3a, 0xc5, 0x84,
+ 0x76, 0x1e, 0xf7, 0x79,
+ 0x25, 0xbd, 0x07, 0x81,
+ 0x21, 0x29, 0x2d, 0x45,
+ 0x75, 0x28, 0xec, 0x87,
+ 0xf5, 0x73, 0xbb, 0xf8,
+ 0x88, 0xbb, 0x3e, 0xa6,
+ 0xbe, 0x5e, 0xd3, 0x95,
+ 0x56, 0x24, 0xaa, 0x17,
+ 0x08, 0xa2, 0x5f, 0x13,
+ 0xe6, 0x15, 0x06, 0x50,
+ 0x05, 0x42, 0xd1, 0x66,
+ 0xa5, 0x19, 0x07, 0x00,
+ 0x1b, 0x48, 0x7b, 0x47,
+ 0xba, 0xdf, 0x84, 0x86,
+ 0xdf, 0xcd, 0x3c, 0xe3,
+ 0x33, 0x5d, 0xe6, 0xc0,
+
+ // extended_registers --- unswapped
+ 0x68, 0x63, 0xdf, 0x50, 0xf7, 0x3b, 0xe8, 0xe5,
+ 0xcb, 0xd6, 0x66, 0x60, 0xe5, 0xa3, 0x58, 0xb3,
+ 0x6f, 0x34, 0xca, 0x02, 0x9b, 0x5f, 0xd0, 0x41,
+ 0xbd, 0xc5, 0x2d, 0xf8, 0xff, 0x15, 0xa2, 0xd0,
+ 0xe3, 0x2b, 0x3b, 0x8a, 0x9f, 0xc3, 0x9e, 0x28,
+ 0x0a, 0xc2, 0xac, 0x3b, 0x67, 0x37, 0x01, 0xfd,
+ 0xc3, 0xaf, 0x60, 0xf6, 0x2c, 0x4f, 0xa9, 0x52,
+ 0x92, 0xe5, 0x28, 0xde, 0x34, 0xb6, 0x2e, 0x44,
+ 0x15, 0xa4, 0xb6, 0xe4, 0xc9, 0x1a, 0x14, 0xb9,
+ 0x51, 0x33, 0x3c, 0xe0, 0xc7, 0x94, 0xf0, 0xf7,
+ 0x78, 0xdd, 0xe5, 0xca, 0xb7, 0xa6, 0xe0, 0x14,
+ 0xa6, 0x03, 0xab, 0x77, 0xad, 0xbd, 0xd2, 0x53,
+ 0x3d, 0x07, 0xe7, 0xaf, 0x90, 0x44, 0x71, 0xbe,
+ 0x0c, 0xdf, 0x2b, 0x97, 0x40, 0x48, 0xd5, 0xf9,
+ 0x62, 0x03, 0x91, 0x84, 0xd6, 0xdd, 0x29, 0x97,
+ 0x35, 0x02, 0xfb, 0x59, 0x97, 0xb0, 0xec, 0xa9,
+ 0x39, 0x6f, 0x81, 0x71, 0x2a, 0xf0, 0xe7, 0x2c,
+ 0x4e, 0x93, 0x90, 0xcb, 0x67, 0x69, 0xde, 0xd7,
+ 0x68, 0x3b, 0x0f, 0x69, 0xa8, 0xf4, 0xa8, 0x83,
+ 0x42, 0x80, 0x47, 0x65, 0x7a, 0xc9, 0x19, 0x5d,
+ 0xcb, 0x43, 0xa5, 0xff, 0xf8, 0x9e, 0x62, 0xf4,
+ 0xe2, 0x6c, 0xcc, 0x17, 0x55, 0x7c, 0x0d, 0x5c,
+ 0x8d, 0x16, 0x01, 0xd7, 0x3a, 0x0c, 0xf4, 0x7f,
+ 0x71, 0xdc, 0x48, 0xe9, 0x4b, 0xfe, 0x1a, 0xd0,
+ 0x04, 0x15, 0x33, 0xec, 0x78, 0xc6, 0x7e, 0xde,
+ 0x7c, 0x23, 0x18, 0x8d, 0x8f, 0xc2, 0x74, 0xc1,
+ 0x48, 0xcd, 0x5d, 0xee, 0xee, 0x81, 0x9e, 0x49,
+ 0x47, 0x8a, 0xf8, 0x61, 0xa3, 0x9c, 0x81, 0x96,
+ 0xbe, 0x2b, 0x5e, 0xbc, 0xcd, 0x34, 0x0a, 0x2a,
+ 0x3b, 0x8b, 0x7d, 0xa1, 0xf2, 0x8d, 0xb4, 0x51,
+ 0x9e, 0x14, 0x78, 0xa3, 0x58, 0x65, 0x2d, 0xd6,
+ 0x50, 0x40, 0x36, 0x32, 0x31, 0xd4, 0x3e, 0xc2,
+ 0xe0, 0x87, 0x1c, 0x05, 0x95, 0x80, 0x84, 0x24,
+ 0x08, 0x6f, 0x5b, 0xc7, 0xe1, 0x1d, 0xd5, 0xa3,
+ 0x94, 0x44, 0xa1, 0x7c, 0xd8, 0x4b, 0x86, 0xd2,
+ 0xc6, 0xa9, 0xf3, 0xe2, 0x4d, 0x6e, 0x1f, 0x0e,
+ 0xf2, 0xf5, 0x71, 0xf9, 0x71, 0x05, 0x24, 0xc9,
+ 0xc1, 0xe8, 0x91, 0x42, 0x61, 0x86, 0x57, 0x68,
+ 0xd9, 0xc9, 0x1d, 0xd5, 0x5a, 0xe9, 0xba, 0xe6,
+ 0x15, 0x8f, 0x87, 0xbd, 0x62, 0x56, 0xed, 0xda,
+ 0xc2, 0xa5, 0xd5, 0x39, 0xac, 0x05, 0x10, 0x14,
+ 0x4a, 0xe7, 0xe7, 0x3c, 0x3f, 0xb7, 0xbb, 0xed,
+ 0x01, 0x6e, 0xcd, 0xee, 0x81, 0xb4, 0x62, 0xf4,
+ 0x62, 0x16, 0xff, 0x20, 0xb4, 0xf0, 0xbc, 0xff,
+ 0x7d, 0xd9, 0xcf, 0x95, 0x30, 0x27, 0xe0, 0x2f,
+ 0x98, 0x53, 0x80, 0x15, 0x13, 0xef, 0x44, 0x58,
+ 0x12, 0x16, 0xdb, 0x11, 0xef, 0x73, 0x51, 0xcd,
+ 0x42, 0x3f, 0x98, 0x6c, 0xc9, 0x68, 0xc3, 0xf4,
+ 0x5b, 0x0f, 0x5d, 0x77, 0xed, 0xdf, 0x0f, 0xff,
+ 0xb8, 0x69, 0x98, 0x50, 0x77, 0x7a, 0xe8, 0x90,
+ 0x27, 0x46, 0x10, 0xd2, 0xb5, 0x00, 0x3b, 0x36,
+ 0x43, 0x6d, 0x67, 0x41, 0x20, 0x3a, 0x32, 0xe0,
+ 0x2e, 0x5a, 0xfb, 0x4e, 0x4f, 0xa4, 0xf7, 0xc2,
+ 0xe6, 0x81, 0x1a, 0x51, 0xa8, 0x7c, 0xd4, 0x60,
+ 0x7c, 0x45, 0xe2, 0xba, 0x5b, 0x42, 0xf3, 0xbf,
+ 0x28, 0xaa, 0xf2, 0x90, 0xe4, 0x94, 0xdd, 0xaa,
+ 0x22, 0xd3, 0x71, 0x33, 0xa1, 0x01, 0x43, 0x0e,
+ 0xfa, 0x46, 0xd2, 0x6e, 0x55, 0x5e, 0x49, 0xeb,
+ 0x94, 0xf0, 0xb0, 0xb1, 0x2e, 0xf2, 0x3d, 0x6c,
+ 0x00, 0x5e, 0x01, 0x56, 0x3b, 0xfd, 0x5b, 0xa1,
+ 0x2f, 0x63, 0x1d, 0xbf, 0xf9, 0xd8, 0x13, 0xf7,
+ 0x4d, 0xb7, 0x1e, 0x3d, 0x98, 0xd2, 0xee, 0xb8,
+ 0x48, 0xc8, 0x5b, 0x91, 0x0f, 0x54, 0x9e, 0x26,
+ 0xb2, 0xc7, 0x3a, 0x6c, 0x8a, 0x35, 0xe1, 0xba
+};
+
+static const MDRawContextARM arm_raw_context = {
+ // context_flags
+ 0x591b9e6a,
+ // iregs
+ {
+ 0xa21594de,
+ 0x820d8a25,
+ 0xc4e133b2,
+ 0x173a1c02,
+ 0x105fb175,
+ 0xe871793f,
+ 0x5def70b3,
+ 0xcee3a623,
+ 0x7b3aa9b8,
+ 0x52518537,
+ 0x627012c5,
+ 0x22723dcc,
+ 0x16fcc971,
+ 0x20988bcb,
+ 0xf1ab806b,
+ 0x99d5fc03,
+ },
+ // cpsr
+ 0xb70df511,
+ // float_save
+ {
+ // fpscr
+ 0xa1e1f7ce1077e6b5ULL,
+ // regs
+ {
+ 0xbcb8d002eed7fbdeULL,
+ 0x4dd26a43b96ae97fULL,
+ 0x8eec22db8b31741cULL,
+ 0xfd634bd7c5ad66a0ULL,
+ 0x1681da0daeb3debeULL,
+ 0x474a32bdf72d0b71ULL,
+ 0xcaf464f8b1044834ULL,
+ 0xcaa6592ae5c7582aULL,
+ 0x4ee46889d877c3dbULL,
+ 0xf8930cf301645cf5ULL,
+ 0x4da7e9ebba27f7c7ULL,
+ 0x69a7b02761944da3ULL,
+ 0x2cda2b2e78195c06ULL,
+ 0x66b227ab9b460a42ULL,
+ 0x7e77e49e52ee0849ULL,
+ 0xd62cd9663e76f255ULL,
+ 0xe9370f082451514bULL,
+ 0x50a1c674dd1b6029ULL,
+ 0x405db4575829eac4ULL,
+ 0x67b948764649eee7ULL,
+ 0x93731885419229d4ULL,
+ 0xdb0338bad72a4ce7ULL,
+ 0xa0a451f996fca4c8ULL,
+ 0xb4508ea668400a45ULL,
+ 0xbff28c5c7a142423ULL,
+ 0x4f31b42b96f3a431ULL,
+ 0x2ce6789d4ea1ff37ULL,
+ 0xfa150b52e4f82a3cULL,
+ 0xe9ec40449e6ed4f3ULL,
+ 0x5ceca87836fe2251ULL,
+ 0x66f50de463ee238cULL,
+ 0x42823efcd59ab511ULL,
+ },
+ // extra
+ {
+ 0xe9e14cd2,
+ 0x865bb640,
+ 0x9f3f0b3e,
+ 0x94a71c52,
+ 0x3c012f19,
+ 0x6436637c,
+ 0x46ccedcb,
+ 0x7b341be7,
+ }
+ }
+};
+
+static const uint8_t arm_expected_contents[] = {
+ 0x6a, 0x9e, 0x1b, 0x59,
+ 0xde, 0x94, 0x15, 0xa2,
+ 0x25, 0x8a, 0x0d, 0x82,
+ 0xb2, 0x33, 0xe1, 0xc4,
+ 0x02, 0x1c, 0x3a, 0x17,
+ 0x75, 0xb1, 0x5f, 0x10,
+ 0x3f, 0x79, 0x71, 0xe8,
+ 0xb3, 0x70, 0xef, 0x5d,
+ 0x23, 0xa6, 0xe3, 0xce,
+ 0xb8, 0xa9, 0x3a, 0x7b,
+ 0x37, 0x85, 0x51, 0x52,
+ 0xc5, 0x12, 0x70, 0x62,
+ 0xcc, 0x3d, 0x72, 0x22,
+ 0x71, 0xc9, 0xfc, 0x16,
+ 0xcb, 0x8b, 0x98, 0x20,
+ 0x6b, 0x80, 0xab, 0xf1,
+ 0x03, 0xfc, 0xd5, 0x99,
+ 0x11, 0xf5, 0x0d, 0xb7,
+ 0xb5, 0xe6, 0x77, 0x10,
+ 0xce, 0xf7, 0xe1, 0xa1,
+ 0xde, 0xfb, 0xd7, 0xee,
+ 0x02, 0xd0, 0xb8, 0xbc,
+ 0x7f, 0xe9, 0x6a, 0xb9,
+ 0x43, 0x6a, 0xd2, 0x4d,
+ 0x1c, 0x74, 0x31, 0x8b,
+ 0xdb, 0x22, 0xec, 0x8e,
+ 0xa0, 0x66, 0xad, 0xc5,
+ 0xd7, 0x4b, 0x63, 0xfd,
+ 0xbe, 0xde, 0xb3, 0xae,
+ 0x0d, 0xda, 0x81, 0x16,
+ 0x71, 0x0b, 0x2d, 0xf7,
+ 0xbd, 0x32, 0x4a, 0x47,
+ 0x34, 0x48, 0x04, 0xb1,
+ 0xf8, 0x64, 0xf4, 0xca,
+ 0x2a, 0x58, 0xc7, 0xe5,
+ 0x2a, 0x59, 0xa6, 0xca,
+ 0xdb, 0xc3, 0x77, 0xd8,
+ 0x89, 0x68, 0xe4, 0x4e,
+ 0xf5, 0x5c, 0x64, 0x01,
+ 0xf3, 0x0c, 0x93, 0xf8,
+ 0xc7, 0xf7, 0x27, 0xba,
+ 0xeb, 0xe9, 0xa7, 0x4d,
+ 0xa3, 0x4d, 0x94, 0x61,
+ 0x27, 0xb0, 0xa7, 0x69,
+ 0x06, 0x5c, 0x19, 0x78,
+ 0x2e, 0x2b, 0xda, 0x2c,
+ 0x42, 0x0a, 0x46, 0x9b,
+ 0xab, 0x27, 0xb2, 0x66,
+ 0x49, 0x08, 0xee, 0x52,
+ 0x9e, 0xe4, 0x77, 0x7e,
+ 0x55, 0xf2, 0x76, 0x3e,
+ 0x66, 0xd9, 0x2c, 0xd6,
+ 0x4b, 0x51, 0x51, 0x24,
+ 0x08, 0x0f, 0x37, 0xe9,
+ 0x29, 0x60, 0x1b, 0xdd,
+ 0x74, 0xc6, 0xa1, 0x50,
+ 0xc4, 0xea, 0x29, 0x58,
+ 0x57, 0xb4, 0x5d, 0x40,
+ 0xe7, 0xee, 0x49, 0x46,
+ 0x76, 0x48, 0xb9, 0x67,
+ 0xd4, 0x29, 0x92, 0x41,
+ 0x85, 0x18, 0x73, 0x93,
+ 0xe7, 0x4c, 0x2a, 0xd7,
+ 0xba, 0x38, 0x03, 0xdb,
+ 0xc8, 0xa4, 0xfc, 0x96,
+ 0xf9, 0x51, 0xa4, 0xa0,
+ 0x45, 0x0a, 0x40, 0x68,
+ 0xa6, 0x8e, 0x50, 0xb4,
+ 0x23, 0x24, 0x14, 0x7a,
+ 0x5c, 0x8c, 0xf2, 0xbf,
+ 0x31, 0xa4, 0xf3, 0x96,
+ 0x2b, 0xb4, 0x31, 0x4f,
+ 0x37, 0xff, 0xa1, 0x4e,
+ 0x9d, 0x78, 0xe6, 0x2c,
+ 0x3c, 0x2a, 0xf8, 0xe4,
+ 0x52, 0x0b, 0x15, 0xfa,
+ 0xf3, 0xd4, 0x6e, 0x9e,
+ 0x44, 0x40, 0xec, 0xe9,
+ 0x51, 0x22, 0xfe, 0x36,
+ 0x78, 0xa8, 0xec, 0x5c,
+ 0x8c, 0x23, 0xee, 0x63,
+ 0xe4, 0x0d, 0xf5, 0x66,
+ 0x11, 0xb5, 0x9a, 0xd5,
+ 0xfc, 0x3e, 0x82, 0x42,
+ 0xd2, 0x4c, 0xe1, 0xe9,
+ 0x40, 0xb6, 0x5b, 0x86,
+ 0x3e, 0x0b, 0x3f, 0x9f,
+ 0x52, 0x1c, 0xa7, 0x94,
+ 0x19, 0x2f, 0x01, 0x3c,
+ 0x7c, 0x63, 0x36, 0x64,
+ 0xcb, 0xed, 0xcc, 0x46,
+ 0xe7, 0x1b, 0x34, 0x7b
+};
+
+#endif // PROCESSOR_SYNTH_MINIDUMP_UNITTEST_DATA_H_
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/tokenize.cc b/toolkit/crashreporter/google-breakpad/src/processor/tokenize.cc
new file mode 100644
index 0000000000..8fce87a224
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/tokenize.cc
@@ -0,0 +1,79 @@
+// 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 <string.h>
+
+#include <string>
+#include <vector>
+
+#include "common/using_std_string.h"
+
+namespace google_breakpad {
+
+#ifdef _MSC_VER
+#define strtok_r strtok_s
+#endif
+
+using std::vector;
+
+bool Tokenize(char *line,
+ const char *separators,
+ int max_tokens,
+ vector<char*> *tokens) {
+ tokens->clear();
+ tokens->reserve(max_tokens);
+
+ int remaining = max_tokens;
+
+ // Split tokens on the separator character.
+ // strip them out before exhausting max_tokens.
+ char *save_ptr;
+ char *token = strtok_r(line, separators, &save_ptr);
+ while (token && --remaining > 0) {
+ tokens->push_back(token);
+ if (remaining > 1)
+ token = strtok_r(NULL, separators, &save_ptr);
+ }
+
+ // If there's anything left, just add it as a single token.
+ if (remaining == 0 && (token = strtok_r(NULL, "\r\n", &save_ptr))) {
+ tokens->push_back(token);
+ }
+
+ return tokens->size() == static_cast<unsigned int>(max_tokens);
+}
+
+void StringToVector(const string &str, vector<char> &vec) {
+ vec.resize(str.length() + 1);
+ std::copy(str.begin(), str.end(),
+ vec.begin());
+ vec[str.length()] = '\0';
+}
+
+} // namespace google_breakpad
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/tokenize.h b/toolkit/crashreporter/google-breakpad/src/processor/tokenize.h
new file mode 100644
index 0000000000..9ff571d5c5
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/tokenize.h
@@ -0,0 +1,63 @@
+// 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.
+//
+// Implements a Tokenize function for splitting up strings.
+
+#ifndef GOOGLE_BREAKPAD_PROCESSOR_TOKENIZE_H_
+#define GOOGLE_BREAKPAD_PROCESSOR_TOKENIZE_H_
+
+#include <string>
+#include <vector>
+
+#include "common/using_std_string.h"
+
+namespace google_breakpad {
+
+// Splits line into at most max_tokens tokens, separated by any of the
+// characters in separators and placing them in the tokens vector.
+// line is a 0-terminated string that optionally ends with a newline
+// character or combination, which will be removed.
+// If more tokens than max_tokens are present, the final token is placed
+// into the vector without splitting it up at all. This modifies line as
+// a side effect. Returns true if exactly max_tokens tokens are returned,
+// and false if fewer are returned. This is not considered a failure of
+// Tokenize, but may be treated as a failure if the caller expects an
+// exact, as opposed to maximum, number of tokens.
+
+bool Tokenize(char *line,
+ const char *separators,
+ int max_tokens,
+ std::vector<char*> *tokens);
+// For convenience, since you need a char* to pass to Tokenize.
+// You can call StringToVector on a string, and use &vec[0].
+void StringToVector(const string &str, std::vector<char> &vec);
+
+} // namespace google_breakpad
+
+#endif // GOOGLE_BREAKPAD_PROCESSOR_TOKENIZE_H_
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/windows_frame_info.h b/toolkit/crashreporter/google-breakpad/src/processor/windows_frame_info.h
new file mode 100644
index 0000000000..f96e0a438c
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/processor/windows_frame_info.h
@@ -0,0 +1,209 @@
+// Copyright (c) 2006, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// windows_frame_info.h: Holds debugging information about a stack frame.
+//
+// This structure is specific to Windows debugging information obtained
+// from pdb files using the DIA API.
+//
+// Author: Mark Mentovai
+
+
+#ifndef PROCESSOR_WINDOWS_FRAME_INFO_H__
+#define PROCESSOR_WINDOWS_FRAME_INFO_H__
+
+#include <string.h>
+#include <stdlib.h>
+
+#include <string>
+#include <vector>
+
+#include "common/using_std_string.h"
+#include "google_breakpad/common/breakpad_types.h"
+#include "processor/logging.h"
+#include "processor/tokenize.h"
+
+namespace google_breakpad {
+
+#ifdef _WIN32
+#define strtoull _strtoui64
+#endif
+
+struct WindowsFrameInfo {
+ public:
+ enum Validity {
+ VALID_NONE = 0,
+ VALID_PARAMETER_SIZE = 1,
+ VALID_ALL = -1
+ };
+
+ // The types for stack_info_. This is equivalent to MS DIA's
+ // StackFrameTypeEnum. Each identifies a different type of frame
+ // information, although all are represented in the symbol file in the
+ // same format. These are used as indices to the stack_info_ array.
+ enum StackInfoTypes {
+ STACK_INFO_FPO = 0,
+ STACK_INFO_TRAP, // not used here
+ STACK_INFO_TSS, // not used here
+ STACK_INFO_STANDARD,
+ STACK_INFO_FRAME_DATA,
+ STACK_INFO_LAST, // must be the last sequentially-numbered item
+ STACK_INFO_UNKNOWN = -1
+ };
+
+ WindowsFrameInfo() : type_(STACK_INFO_UNKNOWN),
+ valid(VALID_NONE),
+ prolog_size(0),
+ epilog_size(0),
+ parameter_size(0),
+ saved_register_size(0),
+ local_size(0),
+ max_stack_size(0),
+ allocates_base_pointer(0),
+ program_string() {}
+
+ WindowsFrameInfo(StackInfoTypes type,
+ uint32_t set_prolog_size,
+ uint32_t set_epilog_size,
+ uint32_t set_parameter_size,
+ uint32_t set_saved_register_size,
+ uint32_t set_local_size,
+ uint32_t set_max_stack_size,
+ int set_allocates_base_pointer,
+ const string set_program_string)
+ : type_(type),
+ valid(VALID_ALL),
+ prolog_size(set_prolog_size),
+ epilog_size(set_epilog_size),
+ parameter_size(set_parameter_size),
+ saved_register_size(set_saved_register_size),
+ local_size(set_local_size),
+ max_stack_size(set_max_stack_size),
+ allocates_base_pointer(set_allocates_base_pointer),
+ program_string(set_program_string) {}
+
+ // Parse a textual serialization of a WindowsFrameInfo object from
+ // a string. Returns NULL if parsing fails, or a new object
+ // otherwise. type, rva and code_size are present in the STACK line,
+ // but not the StackFrameInfo structure, so return them as outparams.
+ static WindowsFrameInfo *ParseFromString(const string string,
+ int &type,
+ uint64_t &rva,
+ uint64_t &code_size) {
+ // The format of a STACK WIN record is documented at:
+ //
+ // https://chromium.googlesource.com/breakpad/breakpad/+/master/docs/symbol_files.md
+
+ std::vector<char> buffer;
+ StringToVector(string, buffer);
+ std::vector<char*> tokens;
+ if (!Tokenize(&buffer[0], " \r\n", 11, &tokens))
+ return NULL;
+
+ type = strtol(tokens[0], NULL, 16);
+ if (type < 0 || type > STACK_INFO_LAST - 1)
+ return NULL;
+
+ rva = strtoull(tokens[1], NULL, 16);
+ code_size = strtoull(tokens[2], NULL, 16);
+ uint32_t prolog_size = strtoul(tokens[3], NULL, 16);
+ uint32_t epilog_size = strtoul(tokens[4], NULL, 16);
+ uint32_t parameter_size = strtoul(tokens[5], NULL, 16);
+ uint32_t saved_register_size = strtoul(tokens[6], NULL, 16);
+ uint32_t local_size = strtoul(tokens[7], NULL, 16);
+ uint32_t max_stack_size = strtoul(tokens[8], NULL, 16);
+ int has_program_string = strtoul(tokens[9], NULL, 16);
+
+ const char *program_string = "";
+ int allocates_base_pointer = 0;
+ if (has_program_string) {
+ program_string = tokens[10];
+ } else {
+ allocates_base_pointer = strtoul(tokens[10], NULL, 16);
+ }
+
+ return new WindowsFrameInfo(static_cast<StackInfoTypes>(type),
+ prolog_size,
+ epilog_size,
+ parameter_size,
+ saved_register_size,
+ local_size,
+ max_stack_size,
+ allocates_base_pointer,
+ program_string);
+ }
+
+ // CopyFrom makes "this" WindowsFrameInfo object identical to "that".
+ void CopyFrom(const WindowsFrameInfo &that) {
+ type_ = that.type_;
+ valid = that.valid;
+ prolog_size = that.prolog_size;
+ epilog_size = that.epilog_size;
+ parameter_size = that.parameter_size;
+ saved_register_size = that.saved_register_size;
+ local_size = that.local_size;
+ max_stack_size = that.max_stack_size;
+ allocates_base_pointer = that.allocates_base_pointer;
+ program_string = that.program_string;
+ }
+
+ // Clears the WindowsFrameInfo object so that users will see it as though
+ // it contains no information.
+ void Clear() {
+ type_ = STACK_INFO_UNKNOWN;
+ valid = VALID_NONE;
+ program_string.erase();
+ }
+
+ StackInfoTypes type_;
+
+ // Identifies which fields in the structure are valid. This is of
+ // type Validity, but it is defined as an int because it's not
+ // possible to OR values into an enumerated type. Users must check
+ // this field before using any other.
+ int valid;
+
+ // These values come from IDiaFrameData.
+ uint32_t prolog_size;
+ uint32_t epilog_size;
+ uint32_t parameter_size;
+ uint32_t saved_register_size;
+ uint32_t local_size;
+ uint32_t max_stack_size;
+
+ // Only one of allocates_base_pointer or program_string will be valid.
+ // If program_string is empty, use allocates_base_pointer.
+ bool allocates_base_pointer;
+ string program_string;
+};
+
+} // namespace google_breakpad
+
+
+#endif // PROCESSOR_WINDOWS_FRAME_INFO_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/third_party/curl/COPYING b/toolkit/crashreporter/google-breakpad/src/third_party/curl/COPYING
new file mode 100644
index 0000000000..3528bd7566
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/third_party/curl/COPYING
@@ -0,0 +1,22 @@
+COPYRIGHT AND PERMISSION NOTICE
+
+Copyright (c) 1996 - 2019, Daniel Stenberg, <daniel@haxx.se>, and many
+contributors, see the THANKS file.
+
+All rights reserved.
+
+Permission to use, copy, modify, and distribute this software for any purpose
+with or without fee is hereby granted, provided that the above copyright
+notice and this permission notice appear in all copies.
+
+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 OF THIRD PARTY RIGHTS. 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.
+
+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 this Software without prior written authorization of the copyright holder.
diff --git a/toolkit/crashreporter/google-breakpad/src/third_party/curl/curl.h b/toolkit/crashreporter/google-breakpad/src/third_party/curl/curl.h
new file mode 100644
index 0000000000..86a24184aa
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/third_party/curl/curl.h
@@ -0,0 +1,2864 @@
+#ifndef __CURL_CURL_H
+#define __CURL_CURL_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/*
+ * If you have libcurl problems, all docs and details are found here:
+ * https://curl.haxx.se/libcurl/
+ *
+ * curl-library mailing list subscription and unsubscription web interface:
+ * https://cool.haxx.se/mailman/listinfo/curl-library/
+ */
+
+#ifdef CURL_NO_OLDIES
+#define CURL_STRICTER
+#endif
+
+#include "curlver.h" /* libcurl version defines */
+#include "system.h" /* determine things run-time */
+
+/*
+ * Define WIN32 when build target is Win32 API
+ */
+
+#if (defined(_WIN32) || defined(__WIN32__)) && \
+ !defined(WIN32) && !defined(__SYMBIAN32__)
+#define WIN32
+#endif
+
+#include <stdio.h>
+#include <limits.h>
+
+#if defined(__FreeBSD__) && (__FreeBSD__ >= 2)
+/* Needed for __FreeBSD_version symbol definition */
+#include <osreldate.h>
+#endif
+
+/* The include stuff here below is mainly for time_t! */
+#include <sys/types.h>
+#include <time.h>
+
+#if defined(WIN32) && !defined(_WIN32_WCE) && !defined(__CYGWIN__)
+#if !(defined(_WINSOCKAPI_) || defined(_WINSOCK_H) || \
+ defined(__LWIP_OPT_H__) || defined(LWIP_HDR_OPT_H))
+/* The check above prevents the winsock2 inclusion if winsock.h already was
+ included, since they can't co-exist without problems */
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#endif
+#endif
+
+/* HP-UX systems version 9, 10 and 11 lack sys/select.h and so does oldish
+ libc5-based Linux systems. Only include it on systems that are known to
+ require it! */
+#if defined(_AIX) || defined(__NOVELL_LIBC__) || defined(__NetBSD__) || \
+ defined(__minix) || defined(__SYMBIAN32__) || defined(__INTEGRITY) || \
+ defined(ANDROID) || defined(__ANDROID__) || defined(__OpenBSD__) || \
+ defined(__CYGWIN__) || \
+ (defined(__FreeBSD_version) && (__FreeBSD_version < 800000))
+#include <sys/select.h>
+#endif
+
+#if !defined(WIN32) && !defined(_WIN32_WCE)
+#include <sys/socket.h>
+#endif
+
+#if !defined(WIN32) && !defined(__WATCOMC__) && !defined(__VXWORKS__)
+#include <sys/time.h>
+#endif
+
+#ifdef __BEOS__
+#include <support/SupportDefs.h>
+#endif
+
+/* Compatibility for non-Clang compilers */
+#ifndef __has_declspec_attribute
+# define __has_declspec_attribute(x) 0
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined(BUILDING_LIBCURL) || defined(CURL_STRICTER)
+typedef struct Curl_easy CURL;
+typedef struct Curl_share CURLSH;
+#else
+typedef void CURL;
+typedef void CURLSH;
+#endif
+
+/*
+ * libcurl external API function linkage decorations.
+ */
+
+#ifdef CURL_STATICLIB
+# define CURL_EXTERN
+#elif defined(WIN32) || defined(_WIN32) || defined(__SYMBIAN32__) || \
+ (__has_declspec_attribute(dllexport) && \
+ __has_declspec_attribute(dllimport))
+# if defined(BUILDING_LIBCURL)
+# define CURL_EXTERN __declspec(dllexport)
+# else
+# define CURL_EXTERN __declspec(dllimport)
+# endif
+#elif defined(BUILDING_LIBCURL) && defined(CURL_HIDDEN_SYMBOLS)
+# define CURL_EXTERN CURL_EXTERN_SYMBOL
+#else
+# define CURL_EXTERN
+#endif
+
+#ifndef curl_socket_typedef
+/* socket typedef */
+#if defined(WIN32) && !defined(__LWIP_OPT_H__) && !defined(LWIP_HDR_OPT_H)
+typedef SOCKET curl_socket_t;
+#define CURL_SOCKET_BAD INVALID_SOCKET
+#else
+typedef int curl_socket_t;
+#define CURL_SOCKET_BAD -1
+#endif
+#define curl_socket_typedef
+#endif /* curl_socket_typedef */
+
+/* enum for the different supported SSL backends */
+typedef enum {
+ CURLSSLBACKEND_NONE = 0,
+ CURLSSLBACKEND_OPENSSL = 1,
+ CURLSSLBACKEND_GNUTLS = 2,
+ CURLSSLBACKEND_NSS = 3,
+ CURLSSLBACKEND_OBSOLETE4 = 4, /* Was QSOSSL. */
+ CURLSSLBACKEND_GSKIT = 5,
+ CURLSSLBACKEND_POLARSSL = 6,
+ CURLSSLBACKEND_WOLFSSL = 7,
+ CURLSSLBACKEND_SCHANNEL = 8,
+ CURLSSLBACKEND_SECURETRANSPORT = 9,
+ CURLSSLBACKEND_AXTLS = 10, /* never used since 7.63.0 */
+ CURLSSLBACKEND_MBEDTLS = 11,
+ CURLSSLBACKEND_MESALINK = 12
+} curl_sslbackend;
+
+/* aliases for library clones and renames */
+#define CURLSSLBACKEND_LIBRESSL CURLSSLBACKEND_OPENSSL
+#define CURLSSLBACKEND_BORINGSSL CURLSSLBACKEND_OPENSSL
+
+/* deprecated names: */
+#define CURLSSLBACKEND_CYASSL CURLSSLBACKEND_WOLFSSL
+#define CURLSSLBACKEND_DARWINSSL CURLSSLBACKEND_SECURETRANSPORT
+
+struct curl_httppost {
+ struct curl_httppost *next; /* next entry in the list */
+ char *name; /* pointer to allocated name */
+ long namelength; /* length of name length */
+ char *contents; /* pointer to allocated data contents */
+ long contentslength; /* length of contents field, see also
+ CURL_HTTPPOST_LARGE */
+ char *buffer; /* pointer to allocated buffer contents */
+ long bufferlength; /* length of buffer field */
+ char *contenttype; /* Content-Type */
+ struct curl_slist *contentheader; /* list of extra headers for this form */
+ struct curl_httppost *more; /* if one field name has more than one
+ file, this link should link to following
+ files */
+ long flags; /* as defined below */
+
+/* specified content is a file name */
+#define CURL_HTTPPOST_FILENAME (1<<0)
+/* specified content is a file name */
+#define CURL_HTTPPOST_READFILE (1<<1)
+/* name is only stored pointer do not free in formfree */
+#define CURL_HTTPPOST_PTRNAME (1<<2)
+/* contents is only stored pointer do not free in formfree */
+#define CURL_HTTPPOST_PTRCONTENTS (1<<3)
+/* upload file from buffer */
+#define CURL_HTTPPOST_BUFFER (1<<4)
+/* upload file from pointer contents */
+#define CURL_HTTPPOST_PTRBUFFER (1<<5)
+/* upload file contents by using the regular read callback to get the data and
+ pass the given pointer as custom pointer */
+#define CURL_HTTPPOST_CALLBACK (1<<6)
+/* use size in 'contentlen', added in 7.46.0 */
+#define CURL_HTTPPOST_LARGE (1<<7)
+
+ char *showfilename; /* The file name to show. If not set, the
+ actual file name will be used (if this
+ is a file part) */
+ void *userp; /* custom pointer used for
+ HTTPPOST_CALLBACK posts */
+ curl_off_t contentlen; /* alternative length of contents
+ field. Used if CURL_HTTPPOST_LARGE is
+ set. Added in 7.46.0 */
+};
+
+/* This is the CURLOPT_PROGRESSFUNCTION callback proto. It is now considered
+ deprecated but was the only choice up until 7.31.0 */
+typedef int (*curl_progress_callback)(void *clientp,
+ double dltotal,
+ double dlnow,
+ double ultotal,
+ double ulnow);
+
+/* This is the CURLOPT_XFERINFOFUNCTION callback proto. It was introduced in
+ 7.32.0, it avoids floating point and provides more detailed information. */
+typedef int (*curl_xferinfo_callback)(void *clientp,
+ curl_off_t dltotal,
+ curl_off_t dlnow,
+ curl_off_t ultotal,
+ curl_off_t ulnow);
+
+#ifndef CURL_MAX_READ_SIZE
+ /* The maximum receive buffer size configurable via CURLOPT_BUFFERSIZE. */
+#define CURL_MAX_READ_SIZE 524288
+#endif
+
+#ifndef CURL_MAX_WRITE_SIZE
+ /* Tests have proven that 20K is a very bad buffer size for uploads on
+ Windows, while 16K for some odd reason performed a lot better.
+ We do the ifndef check to allow this value to easier be changed at build
+ time for those who feel adventurous. The practical minimum is about
+ 400 bytes since libcurl uses a buffer of this size as a scratch area
+ (unrelated to network send operations). */
+#define CURL_MAX_WRITE_SIZE 16384
+#endif
+
+#ifndef CURL_MAX_HTTP_HEADER
+/* The only reason to have a max limit for this is to avoid the risk of a bad
+ server feeding libcurl with a never-ending header that will cause reallocs
+ infinitely */
+#define CURL_MAX_HTTP_HEADER (100*1024)
+#endif
+
+/* This is a magic return code for the write callback that, when returned,
+ will signal libcurl to pause receiving on the current transfer. */
+#define CURL_WRITEFUNC_PAUSE 0x10000001
+
+typedef size_t (*curl_write_callback)(char *buffer,
+ size_t size,
+ size_t nitems,
+ void *outstream);
+
+/* This callback will be called when a new resolver request is made */
+typedef int (*curl_resolver_start_callback)(void *resolver_state,
+ void *reserved, void *userdata);
+
+/* enumeration of file types */
+typedef enum {
+ CURLFILETYPE_FILE = 0,
+ CURLFILETYPE_DIRECTORY,
+ CURLFILETYPE_SYMLINK,
+ CURLFILETYPE_DEVICE_BLOCK,
+ CURLFILETYPE_DEVICE_CHAR,
+ CURLFILETYPE_NAMEDPIPE,
+ CURLFILETYPE_SOCKET,
+ CURLFILETYPE_DOOR, /* is possible only on Sun Solaris now */
+
+ CURLFILETYPE_UNKNOWN /* should never occur */
+} curlfiletype;
+
+#define CURLFINFOFLAG_KNOWN_FILENAME (1<<0)
+#define CURLFINFOFLAG_KNOWN_FILETYPE (1<<1)
+#define CURLFINFOFLAG_KNOWN_TIME (1<<2)
+#define CURLFINFOFLAG_KNOWN_PERM (1<<3)
+#define CURLFINFOFLAG_KNOWN_UID (1<<4)
+#define CURLFINFOFLAG_KNOWN_GID (1<<5)
+#define CURLFINFOFLAG_KNOWN_SIZE (1<<6)
+#define CURLFINFOFLAG_KNOWN_HLINKCOUNT (1<<7)
+
+/* Content of this structure depends on information which is known and is
+ achievable (e.g. by FTP LIST parsing). Please see the url_easy_setopt(3) man
+ page for callbacks returning this structure -- some fields are mandatory,
+ some others are optional. The FLAG field has special meaning. */
+struct curl_fileinfo {
+ char *filename;
+ curlfiletype filetype;
+ time_t time;
+ unsigned int perm;
+ int uid;
+ int gid;
+ curl_off_t size;
+ long int hardlinks;
+
+ struct {
+ /* If some of these fields is not NULL, it is a pointer to b_data. */
+ char *time;
+ char *perm;
+ char *user;
+ char *group;
+ char *target; /* pointer to the target filename of a symlink */
+ } strings;
+
+ unsigned int flags;
+
+ /* used internally */
+ char *b_data;
+ size_t b_size;
+ size_t b_used;
+};
+
+/* return codes for CURLOPT_CHUNK_BGN_FUNCTION */
+#define CURL_CHUNK_BGN_FUNC_OK 0
+#define CURL_CHUNK_BGN_FUNC_FAIL 1 /* tell the lib to end the task */
+#define CURL_CHUNK_BGN_FUNC_SKIP 2 /* skip this chunk over */
+
+/* if splitting of data transfer is enabled, this callback is called before
+ download of an individual chunk started. Note that parameter "remains" works
+ only for FTP wildcard downloading (for now), otherwise is not used */
+typedef long (*curl_chunk_bgn_callback)(const void *transfer_info,
+ void *ptr,
+ int remains);
+
+/* return codes for CURLOPT_CHUNK_END_FUNCTION */
+#define CURL_CHUNK_END_FUNC_OK 0
+#define CURL_CHUNK_END_FUNC_FAIL 1 /* tell the lib to end the task */
+
+/* If splitting of data transfer is enabled this callback is called after
+ download of an individual chunk finished.
+ Note! After this callback was set then it have to be called FOR ALL chunks.
+ Even if downloading of this chunk was skipped in CHUNK_BGN_FUNC.
+ This is the reason why we don't need "transfer_info" parameter in this
+ callback and we are not interested in "remains" parameter too. */
+typedef long (*curl_chunk_end_callback)(void *ptr);
+
+/* return codes for FNMATCHFUNCTION */
+#define CURL_FNMATCHFUNC_MATCH 0 /* string corresponds to the pattern */
+#define CURL_FNMATCHFUNC_NOMATCH 1 /* pattern doesn't match the string */
+#define CURL_FNMATCHFUNC_FAIL 2 /* an error occurred */
+
+/* callback type for wildcard downloading pattern matching. If the
+ string matches the pattern, return CURL_FNMATCHFUNC_MATCH value, etc. */
+typedef int (*curl_fnmatch_callback)(void *ptr,
+ const char *pattern,
+ const char *string);
+
+/* These are the return codes for the seek callbacks */
+#define CURL_SEEKFUNC_OK 0
+#define CURL_SEEKFUNC_FAIL 1 /* fail the entire transfer */
+#define CURL_SEEKFUNC_CANTSEEK 2 /* tell libcurl seeking can't be done, so
+ libcurl might try other means instead */
+typedef int (*curl_seek_callback)(void *instream,
+ curl_off_t offset,
+ int origin); /* 'whence' */
+
+/* This is a return code for the read callback that, when returned, will
+ signal libcurl to immediately abort the current transfer. */
+#define CURL_READFUNC_ABORT 0x10000000
+/* This is a return code for the read callback that, when returned, will
+ signal libcurl to pause sending data on the current transfer. */
+#define CURL_READFUNC_PAUSE 0x10000001
+
+/* Return code for when the trailing headers' callback has terminated
+ without any errors*/
+#define CURL_TRAILERFUNC_OK 0
+/* Return code for when was an error in the trailing header's list and we
+ want to abort the request */
+#define CURL_TRAILERFUNC_ABORT 1
+
+typedef size_t (*curl_read_callback)(char *buffer,
+ size_t size,
+ size_t nitems,
+ void *instream);
+
+typedef int (*curl_trailer_callback)(struct curl_slist **list,
+ void *userdata);
+
+typedef enum {
+ CURLSOCKTYPE_IPCXN, /* socket created for a specific IP connection */
+ CURLSOCKTYPE_ACCEPT, /* socket created by accept() call */
+ CURLSOCKTYPE_LAST /* never use */
+} curlsocktype;
+
+/* The return code from the sockopt_callback can signal information back
+ to libcurl: */
+#define CURL_SOCKOPT_OK 0
+#define CURL_SOCKOPT_ERROR 1 /* causes libcurl to abort and return
+ CURLE_ABORTED_BY_CALLBACK */
+#define CURL_SOCKOPT_ALREADY_CONNECTED 2
+
+typedef int (*curl_sockopt_callback)(void *clientp,
+ curl_socket_t curlfd,
+ curlsocktype purpose);
+
+struct curl_sockaddr {
+ int family;
+ int socktype;
+ int protocol;
+ unsigned int addrlen; /* addrlen was a socklen_t type before 7.18.0 but it
+ turned really ugly and painful on the systems that
+ lack this type */
+ struct sockaddr addr;
+};
+
+typedef curl_socket_t
+(*curl_opensocket_callback)(void *clientp,
+ curlsocktype purpose,
+ struct curl_sockaddr *address);
+
+typedef int
+(*curl_closesocket_callback)(void *clientp, curl_socket_t item);
+
+typedef enum {
+ CURLIOE_OK, /* I/O operation successful */
+ CURLIOE_UNKNOWNCMD, /* command was unknown to callback */
+ CURLIOE_FAILRESTART, /* failed to restart the read */
+ CURLIOE_LAST /* never use */
+} curlioerr;
+
+typedef enum {
+ CURLIOCMD_NOP, /* no operation */
+ CURLIOCMD_RESTARTREAD, /* restart the read stream from start */
+ CURLIOCMD_LAST /* never use */
+} curliocmd;
+
+typedef curlioerr (*curl_ioctl_callback)(CURL *handle,
+ int cmd,
+ void *clientp);
+
+#ifndef CURL_DID_MEMORY_FUNC_TYPEDEFS
+/*
+ * The following typedef's are signatures of malloc, free, realloc, strdup and
+ * calloc respectively. Function pointers of these types can be passed to the
+ * curl_global_init_mem() function to set user defined memory management
+ * callback routines.
+ */
+typedef void *(*curl_malloc_callback)(size_t size);
+typedef void (*curl_free_callback)(void *ptr);
+typedef void *(*curl_realloc_callback)(void *ptr, size_t size);
+typedef char *(*curl_strdup_callback)(const char *str);
+typedef void *(*curl_calloc_callback)(size_t nmemb, size_t size);
+
+#define CURL_DID_MEMORY_FUNC_TYPEDEFS
+#endif
+
+/* the kind of data that is passed to information_callback*/
+typedef enum {
+ CURLINFO_TEXT = 0,
+ CURLINFO_HEADER_IN, /* 1 */
+ CURLINFO_HEADER_OUT, /* 2 */
+ CURLINFO_DATA_IN, /* 3 */
+ CURLINFO_DATA_OUT, /* 4 */
+ CURLINFO_SSL_DATA_IN, /* 5 */
+ CURLINFO_SSL_DATA_OUT, /* 6 */
+ CURLINFO_END
+} curl_infotype;
+
+typedef int (*curl_debug_callback)
+ (CURL *handle, /* the handle/transfer this concerns */
+ curl_infotype type, /* what kind of data */
+ char *data, /* points to the data */
+ size_t size, /* size of the data pointed to */
+ void *userptr); /* whatever the user please */
+
+/* All possible error codes from all sorts of curl functions. Future versions
+ may return other values, stay prepared.
+
+ Always add new return codes last. Never *EVER* remove any. The return
+ codes must remain the same!
+ */
+
+typedef enum {
+ CURLE_OK = 0,
+ CURLE_UNSUPPORTED_PROTOCOL, /* 1 */
+ CURLE_FAILED_INIT, /* 2 */
+ CURLE_URL_MALFORMAT, /* 3 */
+ CURLE_NOT_BUILT_IN, /* 4 - [was obsoleted in August 2007 for
+ 7.17.0, reused in April 2011 for 7.21.5] */
+ CURLE_COULDNT_RESOLVE_PROXY, /* 5 */
+ CURLE_COULDNT_RESOLVE_HOST, /* 6 */
+ CURLE_COULDNT_CONNECT, /* 7 */
+ CURLE_WEIRD_SERVER_REPLY, /* 8 */
+ CURLE_REMOTE_ACCESS_DENIED, /* 9 a service was denied by the server
+ due to lack of access - when login fails
+ this is not returned. */
+ CURLE_FTP_ACCEPT_FAILED, /* 10 - [was obsoleted in April 2006 for
+ 7.15.4, reused in Dec 2011 for 7.24.0]*/
+ CURLE_FTP_WEIRD_PASS_REPLY, /* 11 */
+ CURLE_FTP_ACCEPT_TIMEOUT, /* 12 - timeout occurred accepting server
+ [was obsoleted in August 2007 for 7.17.0,
+ reused in Dec 2011 for 7.24.0]*/
+ CURLE_FTP_WEIRD_PASV_REPLY, /* 13 */
+ CURLE_FTP_WEIRD_227_FORMAT, /* 14 */
+ CURLE_FTP_CANT_GET_HOST, /* 15 */
+ CURLE_HTTP2, /* 16 - A problem in the http2 framing layer.
+ [was obsoleted in August 2007 for 7.17.0,
+ reused in July 2014 for 7.38.0] */
+ CURLE_FTP_COULDNT_SET_TYPE, /* 17 */
+ CURLE_PARTIAL_FILE, /* 18 */
+ CURLE_FTP_COULDNT_RETR_FILE, /* 19 */
+ CURLE_OBSOLETE20, /* 20 - NOT USED */
+ CURLE_QUOTE_ERROR, /* 21 - quote command failure */
+ CURLE_HTTP_RETURNED_ERROR, /* 22 */
+ CURLE_WRITE_ERROR, /* 23 */
+ CURLE_OBSOLETE24, /* 24 - NOT USED */
+ CURLE_UPLOAD_FAILED, /* 25 - failed upload "command" */
+ CURLE_READ_ERROR, /* 26 - couldn't open/read from file */
+ CURLE_OUT_OF_MEMORY, /* 27 */
+ /* Note: CURLE_OUT_OF_MEMORY may sometimes indicate a conversion error
+ instead of a memory allocation error if CURL_DOES_CONVERSIONS
+ is defined
+ */
+ CURLE_OPERATION_TIMEDOUT, /* 28 - the timeout time was reached */
+ CURLE_OBSOLETE29, /* 29 - NOT USED */
+ CURLE_FTP_PORT_FAILED, /* 30 - FTP PORT operation failed */
+ CURLE_FTP_COULDNT_USE_REST, /* 31 - the REST command failed */
+ CURLE_OBSOLETE32, /* 32 - NOT USED */
+ CURLE_RANGE_ERROR, /* 33 - RANGE "command" didn't work */
+ CURLE_HTTP_POST_ERROR, /* 34 */
+ CURLE_SSL_CONNECT_ERROR, /* 35 - wrong when connecting with SSL */
+ CURLE_BAD_DOWNLOAD_RESUME, /* 36 - couldn't resume download */
+ CURLE_FILE_COULDNT_READ_FILE, /* 37 */
+ CURLE_LDAP_CANNOT_BIND, /* 38 */
+ CURLE_LDAP_SEARCH_FAILED, /* 39 */
+ CURLE_OBSOLETE40, /* 40 - NOT USED */
+ CURLE_FUNCTION_NOT_FOUND, /* 41 - NOT USED starting with 7.53.0 */
+ CURLE_ABORTED_BY_CALLBACK, /* 42 */
+ CURLE_BAD_FUNCTION_ARGUMENT, /* 43 */
+ CURLE_OBSOLETE44, /* 44 - NOT USED */
+ CURLE_INTERFACE_FAILED, /* 45 - CURLOPT_INTERFACE failed */
+ CURLE_OBSOLETE46, /* 46 - NOT USED */
+ CURLE_TOO_MANY_REDIRECTS, /* 47 - catch endless re-direct loops */
+ CURLE_UNKNOWN_OPTION, /* 48 - User specified an unknown option */
+ CURLE_TELNET_OPTION_SYNTAX, /* 49 - Malformed telnet option */
+ CURLE_OBSOLETE50, /* 50 - NOT USED */
+ CURLE_OBSOLETE51, /* 51 - NOT USED */
+ CURLE_GOT_NOTHING, /* 52 - when this is a specific error */
+ CURLE_SSL_ENGINE_NOTFOUND, /* 53 - SSL crypto engine not found */
+ CURLE_SSL_ENGINE_SETFAILED, /* 54 - can not set SSL crypto engine as
+ default */
+ CURLE_SEND_ERROR, /* 55 - failed sending network data */
+ CURLE_RECV_ERROR, /* 56 - failure in receiving network data */
+ CURLE_OBSOLETE57, /* 57 - NOT IN USE */
+ CURLE_SSL_CERTPROBLEM, /* 58 - problem with the local certificate */
+ CURLE_SSL_CIPHER, /* 59 - couldn't use specified cipher */
+ CURLE_PEER_FAILED_VERIFICATION, /* 60 - peer's certificate or fingerprint
+ wasn't verified fine */
+ CURLE_BAD_CONTENT_ENCODING, /* 61 - Unrecognized/bad encoding */
+ CURLE_LDAP_INVALID_URL, /* 62 - Invalid LDAP URL */
+ CURLE_FILESIZE_EXCEEDED, /* 63 - Maximum file size exceeded */
+ CURLE_USE_SSL_FAILED, /* 64 - Requested FTP SSL level failed */
+ CURLE_SEND_FAIL_REWIND, /* 65 - Sending the data requires a rewind
+ that failed */
+ CURLE_SSL_ENGINE_INITFAILED, /* 66 - failed to initialise ENGINE */
+ CURLE_LOGIN_DENIED, /* 67 - user, password or similar was not
+ accepted and we failed to login */
+ CURLE_TFTP_NOTFOUND, /* 68 - file not found on server */
+ CURLE_TFTP_PERM, /* 69 - permission problem on server */
+ CURLE_REMOTE_DISK_FULL, /* 70 - out of disk space on server */
+ CURLE_TFTP_ILLEGAL, /* 71 - Illegal TFTP operation */
+ CURLE_TFTP_UNKNOWNID, /* 72 - Unknown transfer ID */
+ CURLE_REMOTE_FILE_EXISTS, /* 73 - File already exists */
+ CURLE_TFTP_NOSUCHUSER, /* 74 - No such user */
+ CURLE_CONV_FAILED, /* 75 - conversion failed */
+ CURLE_CONV_REQD, /* 76 - caller must register conversion
+ callbacks using curl_easy_setopt options
+ CURLOPT_CONV_FROM_NETWORK_FUNCTION,
+ CURLOPT_CONV_TO_NETWORK_FUNCTION, and
+ CURLOPT_CONV_FROM_UTF8_FUNCTION */
+ CURLE_SSL_CACERT_BADFILE, /* 77 - could not load CACERT file, missing
+ or wrong format */
+ CURLE_REMOTE_FILE_NOT_FOUND, /* 78 - remote file not found */
+ CURLE_SSH, /* 79 - error from the SSH layer, somewhat
+ generic so the error message will be of
+ interest when this has happened */
+
+ CURLE_SSL_SHUTDOWN_FAILED, /* 80 - Failed to shut down the SSL
+ connection */
+ CURLE_AGAIN, /* 81 - socket is not ready for send/recv,
+ wait till it's ready and try again (Added
+ in 7.18.2) */
+ CURLE_SSL_CRL_BADFILE, /* 82 - could not load CRL file, missing or
+ wrong format (Added in 7.19.0) */
+ CURLE_SSL_ISSUER_ERROR, /* 83 - Issuer check failed. (Added in
+ 7.19.0) */
+ CURLE_FTP_PRET_FAILED, /* 84 - a PRET command failed */
+ CURLE_RTSP_CSEQ_ERROR, /* 85 - mismatch of RTSP CSeq numbers */
+ CURLE_RTSP_SESSION_ERROR, /* 86 - mismatch of RTSP Session Ids */
+ CURLE_FTP_BAD_FILE_LIST, /* 87 - unable to parse FTP file list */
+ CURLE_CHUNK_FAILED, /* 88 - chunk callback reported error */
+ CURLE_NO_CONNECTION_AVAILABLE, /* 89 - No connection available, the
+ session will be queued */
+ CURLE_SSL_PINNEDPUBKEYNOTMATCH, /* 90 - specified pinned public key did not
+ match */
+ CURLE_SSL_INVALIDCERTSTATUS, /* 91 - invalid certificate status */
+ CURLE_HTTP2_STREAM, /* 92 - stream error in HTTP/2 framing layer
+ */
+ CURLE_RECURSIVE_API_CALL, /* 93 - an api function was called from
+ inside a callback */
+ CURL_LAST /* never use! */
+} CURLcode;
+
+#ifndef CURL_NO_OLDIES /* define this to test if your app builds with all
+ the obsolete stuff removed! */
+
+/* Previously obsolete error code re-used in 7.38.0 */
+#define CURLE_OBSOLETE16 CURLE_HTTP2
+
+/* Previously obsolete error codes re-used in 7.24.0 */
+#define CURLE_OBSOLETE10 CURLE_FTP_ACCEPT_FAILED
+#define CURLE_OBSOLETE12 CURLE_FTP_ACCEPT_TIMEOUT
+
+/* compatibility with older names */
+#define CURLOPT_ENCODING CURLOPT_ACCEPT_ENCODING
+#define CURLE_FTP_WEIRD_SERVER_REPLY CURLE_WEIRD_SERVER_REPLY
+
+/* The following were added in 7.62.0 */
+#define CURLE_SSL_CACERT CURLE_PEER_FAILED_VERIFICATION
+
+/* The following were added in 7.21.5, April 2011 */
+#define CURLE_UNKNOWN_TELNET_OPTION CURLE_UNKNOWN_OPTION
+
+/* The following were added in 7.17.1 */
+/* These are scheduled to disappear by 2009 */
+#define CURLE_SSL_PEER_CERTIFICATE CURLE_PEER_FAILED_VERIFICATION
+
+/* The following were added in 7.17.0 */
+/* These are scheduled to disappear by 2009 */
+#define CURLE_OBSOLETE CURLE_OBSOLETE50 /* no one should be using this! */
+#define CURLE_BAD_PASSWORD_ENTERED CURLE_OBSOLETE46
+#define CURLE_BAD_CALLING_ORDER CURLE_OBSOLETE44
+#define CURLE_FTP_USER_PASSWORD_INCORRECT CURLE_OBSOLETE10
+#define CURLE_FTP_CANT_RECONNECT CURLE_OBSOLETE16
+#define CURLE_FTP_COULDNT_GET_SIZE CURLE_OBSOLETE32
+#define CURLE_FTP_COULDNT_SET_ASCII CURLE_OBSOLETE29
+#define CURLE_FTP_WEIRD_USER_REPLY CURLE_OBSOLETE12
+#define CURLE_FTP_WRITE_ERROR CURLE_OBSOLETE20
+#define CURLE_LIBRARY_NOT_FOUND CURLE_OBSOLETE40
+#define CURLE_MALFORMAT_USER CURLE_OBSOLETE24
+#define CURLE_SHARE_IN_USE CURLE_OBSOLETE57
+#define CURLE_URL_MALFORMAT_USER CURLE_NOT_BUILT_IN
+
+#define CURLE_FTP_ACCESS_DENIED CURLE_REMOTE_ACCESS_DENIED
+#define CURLE_FTP_COULDNT_SET_BINARY CURLE_FTP_COULDNT_SET_TYPE
+#define CURLE_FTP_QUOTE_ERROR CURLE_QUOTE_ERROR
+#define CURLE_TFTP_DISKFULL CURLE_REMOTE_DISK_FULL
+#define CURLE_TFTP_EXISTS CURLE_REMOTE_FILE_EXISTS
+#define CURLE_HTTP_RANGE_ERROR CURLE_RANGE_ERROR
+#define CURLE_FTP_SSL_FAILED CURLE_USE_SSL_FAILED
+
+/* The following were added earlier */
+
+#define CURLE_OPERATION_TIMEOUTED CURLE_OPERATION_TIMEDOUT
+
+#define CURLE_HTTP_NOT_FOUND CURLE_HTTP_RETURNED_ERROR
+#define CURLE_HTTP_PORT_FAILED CURLE_INTERFACE_FAILED
+#define CURLE_FTP_COULDNT_STOR_FILE CURLE_UPLOAD_FAILED
+
+#define CURLE_FTP_PARTIAL_FILE CURLE_PARTIAL_FILE
+#define CURLE_FTP_BAD_DOWNLOAD_RESUME CURLE_BAD_DOWNLOAD_RESUME
+
+/* This was the error code 50 in 7.7.3 and a few earlier versions, this
+ is no longer used by libcurl but is instead #defined here only to not
+ make programs break */
+#define CURLE_ALREADY_COMPLETE 99999
+
+/* Provide defines for really old option names */
+#define CURLOPT_FILE CURLOPT_WRITEDATA /* name changed in 7.9.7 */
+#define CURLOPT_INFILE CURLOPT_READDATA /* name changed in 7.9.7 */
+#define CURLOPT_WRITEHEADER CURLOPT_HEADERDATA
+
+/* Since long deprecated options with no code in the lib that does anything
+ with them. */
+#define CURLOPT_WRITEINFO CURLOPT_OBSOLETE40
+#define CURLOPT_CLOSEPOLICY CURLOPT_OBSOLETE72
+
+#endif /*!CURL_NO_OLDIES*/
+
+/* This prototype applies to all conversion callbacks */
+typedef CURLcode (*curl_conv_callback)(char *buffer, size_t length);
+
+typedef CURLcode (*curl_ssl_ctx_callback)(CURL *curl, /* easy handle */
+ void *ssl_ctx, /* actually an
+ OpenSSL SSL_CTX */
+ void *userptr);
+
+typedef enum {
+ CURLPROXY_HTTP = 0, /* added in 7.10, new in 7.19.4 default is to use
+ CONNECT HTTP/1.1 */
+ CURLPROXY_HTTP_1_0 = 1, /* added in 7.19.4, force to use CONNECT
+ HTTP/1.0 */
+ CURLPROXY_HTTPS = 2, /* added in 7.52.0 */
+ CURLPROXY_SOCKS4 = 4, /* support added in 7.15.2, enum existed already
+ in 7.10 */
+ CURLPROXY_SOCKS5 = 5, /* added in 7.10 */
+ CURLPROXY_SOCKS4A = 6, /* added in 7.18.0 */
+ CURLPROXY_SOCKS5_HOSTNAME = 7 /* Use the SOCKS5 protocol but pass along the
+ host name rather than the IP address. added
+ in 7.18.0 */
+} curl_proxytype; /* this enum was added in 7.10 */
+
+/*
+ * Bitmasks for CURLOPT_HTTPAUTH and CURLOPT_PROXYAUTH options:
+ *
+ * CURLAUTH_NONE - No HTTP authentication
+ * CURLAUTH_BASIC - HTTP Basic authentication (default)
+ * CURLAUTH_DIGEST - HTTP Digest authentication
+ * CURLAUTH_NEGOTIATE - HTTP Negotiate (SPNEGO) authentication
+ * CURLAUTH_GSSNEGOTIATE - Alias for CURLAUTH_NEGOTIATE (deprecated)
+ * CURLAUTH_NTLM - HTTP NTLM authentication
+ * CURLAUTH_DIGEST_IE - HTTP Digest authentication with IE flavour
+ * CURLAUTH_NTLM_WB - HTTP NTLM authentication delegated to winbind helper
+ * CURLAUTH_BEARER - HTTP Bearer token authentication
+ * CURLAUTH_ONLY - Use together with a single other type to force no
+ * authentication or just that single type
+ * CURLAUTH_ANY - All fine types set
+ * CURLAUTH_ANYSAFE - All fine types except Basic
+ */
+
+#define CURLAUTH_NONE ((unsigned long)0)
+#define CURLAUTH_BASIC (((unsigned long)1)<<0)
+#define CURLAUTH_DIGEST (((unsigned long)1)<<1)
+#define CURLAUTH_NEGOTIATE (((unsigned long)1)<<2)
+/* Deprecated since the advent of CURLAUTH_NEGOTIATE */
+#define CURLAUTH_GSSNEGOTIATE CURLAUTH_NEGOTIATE
+/* Used for CURLOPT_SOCKS5_AUTH to stay terminologically correct */
+#define CURLAUTH_GSSAPI CURLAUTH_NEGOTIATE
+#define CURLAUTH_NTLM (((unsigned long)1)<<3)
+#define CURLAUTH_DIGEST_IE (((unsigned long)1)<<4)
+#define CURLAUTH_NTLM_WB (((unsigned long)1)<<5)
+#define CURLAUTH_BEARER (((unsigned long)1)<<6)
+#define CURLAUTH_ONLY (((unsigned long)1)<<31)
+#define CURLAUTH_ANY (~CURLAUTH_DIGEST_IE)
+#define CURLAUTH_ANYSAFE (~(CURLAUTH_BASIC|CURLAUTH_DIGEST_IE))
+
+#define CURLSSH_AUTH_ANY ~0 /* all types supported by the server */
+#define CURLSSH_AUTH_NONE 0 /* none allowed, silly but complete */
+#define CURLSSH_AUTH_PUBLICKEY (1<<0) /* public/private key files */
+#define CURLSSH_AUTH_PASSWORD (1<<1) /* password */
+#define CURLSSH_AUTH_HOST (1<<2) /* host key files */
+#define CURLSSH_AUTH_KEYBOARD (1<<3) /* keyboard interactive */
+#define CURLSSH_AUTH_AGENT (1<<4) /* agent (ssh-agent, pageant...) */
+#define CURLSSH_AUTH_GSSAPI (1<<5) /* gssapi (kerberos, ...) */
+#define CURLSSH_AUTH_DEFAULT CURLSSH_AUTH_ANY
+
+#define CURLGSSAPI_DELEGATION_NONE 0 /* no delegation (default) */
+#define CURLGSSAPI_DELEGATION_POLICY_FLAG (1<<0) /* if permitted by policy */
+#define CURLGSSAPI_DELEGATION_FLAG (1<<1) /* delegate always */
+
+#define CURL_ERROR_SIZE 256
+
+enum curl_khtype {
+ CURLKHTYPE_UNKNOWN,
+ CURLKHTYPE_RSA1,
+ CURLKHTYPE_RSA,
+ CURLKHTYPE_DSS,
+ CURLKHTYPE_ECDSA,
+ CURLKHTYPE_ED25519
+};
+
+struct curl_khkey {
+ const char *key; /* points to a zero-terminated string encoded with base64
+ if len is zero, otherwise to the "raw" data */
+ size_t len;
+ enum curl_khtype keytype;
+};
+
+/* this is the set of return values expected from the curl_sshkeycallback
+ callback */
+enum curl_khstat {
+ CURLKHSTAT_FINE_ADD_TO_FILE,
+ CURLKHSTAT_FINE,
+ CURLKHSTAT_REJECT, /* reject the connection, return an error */
+ CURLKHSTAT_DEFER, /* do not accept it, but we can't answer right now so
+ this causes a CURLE_DEFER error but otherwise the
+ connection will be left intact etc */
+ CURLKHSTAT_LAST /* not for use, only a marker for last-in-list */
+};
+
+/* this is the set of status codes pass in to the callback */
+enum curl_khmatch {
+ CURLKHMATCH_OK, /* match */
+ CURLKHMATCH_MISMATCH, /* host found, key mismatch! */
+ CURLKHMATCH_MISSING, /* no matching host/key found */
+ CURLKHMATCH_LAST /* not for use, only a marker for last-in-list */
+};
+
+typedef int
+ (*curl_sshkeycallback) (CURL *easy, /* easy handle */
+ const struct curl_khkey *knownkey, /* known */
+ const struct curl_khkey *foundkey, /* found */
+ enum curl_khmatch, /* libcurl's view on the keys */
+ void *clientp); /* custom pointer passed from app */
+
+/* parameter for the CURLOPT_USE_SSL option */
+typedef enum {
+ CURLUSESSL_NONE, /* do not attempt to use SSL */
+ CURLUSESSL_TRY, /* try using SSL, proceed anyway otherwise */
+ CURLUSESSL_CONTROL, /* SSL for the control connection or fail */
+ CURLUSESSL_ALL, /* SSL for all communication or fail */
+ CURLUSESSL_LAST /* not an option, never use */
+} curl_usessl;
+
+/* Definition of bits for the CURLOPT_SSL_OPTIONS argument: */
+
+/* - ALLOW_BEAST tells libcurl to allow the BEAST SSL vulnerability in the
+ name of improving interoperability with older servers. Some SSL libraries
+ have introduced work-arounds for this flaw but those work-arounds sometimes
+ make the SSL communication fail. To regain functionality with those broken
+ servers, a user can this way allow the vulnerability back. */
+#define CURLSSLOPT_ALLOW_BEAST (1<<0)
+
+/* - NO_REVOKE tells libcurl to disable certificate revocation checks for those
+ SSL backends where such behavior is present. */
+#define CURLSSLOPT_NO_REVOKE (1<<1)
+
+/* The default connection attempt delay in milliseconds for happy eyeballs.
+ CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS.3 and happy-eyeballs-timeout-ms.d document
+ this value, keep them in sync. */
+#define CURL_HET_DEFAULT 200L
+
+/* The default connection upkeep interval in milliseconds. */
+#define CURL_UPKEEP_INTERVAL_DEFAULT 60000L
+
+#ifndef CURL_NO_OLDIES /* define this to test if your app builds with all
+ the obsolete stuff removed! */
+
+/* Backwards compatibility with older names */
+/* These are scheduled to disappear by 2009 */
+
+#define CURLFTPSSL_NONE CURLUSESSL_NONE
+#define CURLFTPSSL_TRY CURLUSESSL_TRY
+#define CURLFTPSSL_CONTROL CURLUSESSL_CONTROL
+#define CURLFTPSSL_ALL CURLUSESSL_ALL
+#define CURLFTPSSL_LAST CURLUSESSL_LAST
+#define curl_ftpssl curl_usessl
+#endif /*!CURL_NO_OLDIES*/
+
+/* parameter for the CURLOPT_FTP_SSL_CCC option */
+typedef enum {
+ CURLFTPSSL_CCC_NONE, /* do not send CCC */
+ CURLFTPSSL_CCC_PASSIVE, /* Let the server initiate the shutdown */
+ CURLFTPSSL_CCC_ACTIVE, /* Initiate the shutdown */
+ CURLFTPSSL_CCC_LAST /* not an option, never use */
+} curl_ftpccc;
+
+/* parameter for the CURLOPT_FTPSSLAUTH option */
+typedef enum {
+ CURLFTPAUTH_DEFAULT, /* let libcurl decide */
+ CURLFTPAUTH_SSL, /* use "AUTH SSL" */
+ CURLFTPAUTH_TLS, /* use "AUTH TLS" */
+ CURLFTPAUTH_LAST /* not an option, never use */
+} curl_ftpauth;
+
+/* parameter for the CURLOPT_FTP_CREATE_MISSING_DIRS option */
+typedef enum {
+ CURLFTP_CREATE_DIR_NONE, /* do NOT create missing dirs! */
+ CURLFTP_CREATE_DIR, /* (FTP/SFTP) if CWD fails, try MKD and then CWD
+ again if MKD succeeded, for SFTP this does
+ similar magic */
+ CURLFTP_CREATE_DIR_RETRY, /* (FTP only) if CWD fails, try MKD and then CWD
+ again even if MKD failed! */
+ CURLFTP_CREATE_DIR_LAST /* not an option, never use */
+} curl_ftpcreatedir;
+
+/* parameter for the CURLOPT_FTP_FILEMETHOD option */
+typedef enum {
+ CURLFTPMETHOD_DEFAULT, /* let libcurl pick */
+ CURLFTPMETHOD_MULTICWD, /* single CWD operation for each path part */
+ CURLFTPMETHOD_NOCWD, /* no CWD at all */
+ CURLFTPMETHOD_SINGLECWD, /* one CWD to full dir, then work on file */
+ CURLFTPMETHOD_LAST /* not an option, never use */
+} curl_ftpmethod;
+
+/* bitmask defines for CURLOPT_HEADEROPT */
+#define CURLHEADER_UNIFIED 0
+#define CURLHEADER_SEPARATE (1<<0)
+
+/* CURLALTSVC_* are bits for the CURLOPT_ALTSVC_CTRL option */
+#define CURLALTSVC_IMMEDIATELY (1<<0)
+#define CURLALTSVC_ALTUSED (1<<1)
+#define CURLALTSVC_READONLYFILE (1<<2)
+#define CURLALTSVC_H1 (1<<3)
+#define CURLALTSVC_H2 (1<<4)
+#define CURLALTSVC_H3 (1<<5)
+
+/* CURLPROTO_ defines are for the CURLOPT_*PROTOCOLS options */
+#define CURLPROTO_HTTP (1<<0)
+#define CURLPROTO_HTTPS (1<<1)
+#define CURLPROTO_FTP (1<<2)
+#define CURLPROTO_FTPS (1<<3)
+#define CURLPROTO_SCP (1<<4)
+#define CURLPROTO_SFTP (1<<5)
+#define CURLPROTO_TELNET (1<<6)
+#define CURLPROTO_LDAP (1<<7)
+#define CURLPROTO_LDAPS (1<<8)
+#define CURLPROTO_DICT (1<<9)
+#define CURLPROTO_FILE (1<<10)
+#define CURLPROTO_TFTP (1<<11)
+#define CURLPROTO_IMAP (1<<12)
+#define CURLPROTO_IMAPS (1<<13)
+#define CURLPROTO_POP3 (1<<14)
+#define CURLPROTO_POP3S (1<<15)
+#define CURLPROTO_SMTP (1<<16)
+#define CURLPROTO_SMTPS (1<<17)
+#define CURLPROTO_RTSP (1<<18)
+#define CURLPROTO_RTMP (1<<19)
+#define CURLPROTO_RTMPT (1<<20)
+#define CURLPROTO_RTMPE (1<<21)
+#define CURLPROTO_RTMPTE (1<<22)
+#define CURLPROTO_RTMPS (1<<23)
+#define CURLPROTO_RTMPTS (1<<24)
+#define CURLPROTO_GOPHER (1<<25)
+#define CURLPROTO_SMB (1<<26)
+#define CURLPROTO_SMBS (1<<27)
+#define CURLPROTO_ALL (~0) /* enable everything */
+
+/* long may be 32 or 64 bits, but we should never depend on anything else
+ but 32 */
+#define CURLOPTTYPE_LONG 0
+#define CURLOPTTYPE_OBJECTPOINT 10000
+#define CURLOPTTYPE_STRINGPOINT 10000
+#define CURLOPTTYPE_FUNCTIONPOINT 20000
+#define CURLOPTTYPE_OFF_T 30000
+
+/* *STRINGPOINT is an alias for OBJECTPOINT to allow tools to extract the
+ string options from the header file */
+
+/* name is uppercase CURLOPT_<name>,
+ type is one of the defined CURLOPTTYPE_<type>
+ number is unique identifier */
+#ifdef CINIT
+#undef CINIT
+#endif
+
+#ifdef CURL_ISOCPP
+#define CINIT(na,t,nu) CURLOPT_ ## na = CURLOPTTYPE_ ## t + nu
+#else
+/* The macro "##" is ISO C, we assume pre-ISO C doesn't support it. */
+#define LONG CURLOPTTYPE_LONG
+#define OBJECTPOINT CURLOPTTYPE_OBJECTPOINT
+#define STRINGPOINT CURLOPTTYPE_OBJECTPOINT
+#define FUNCTIONPOINT CURLOPTTYPE_FUNCTIONPOINT
+#define OFF_T CURLOPTTYPE_OFF_T
+#define CINIT(name,type,number) CURLOPT_/**/name = type + number
+#endif
+
+/*
+ * This macro-mania below setups the CURLOPT_[what] enum, to be used with
+ * curl_easy_setopt(). The first argument in the CINIT() macro is the [what]
+ * word.
+ */
+
+typedef enum {
+ /* This is the FILE * or void * the regular output should be written to. */
+ CINIT(WRITEDATA, OBJECTPOINT, 1),
+
+ /* The full URL to get/put */
+ CINIT(URL, STRINGPOINT, 2),
+
+ /* Port number to connect to, if other than default. */
+ CINIT(PORT, LONG, 3),
+
+ /* Name of proxy to use. */
+ CINIT(PROXY, STRINGPOINT, 4),
+
+ /* "user:password;options" to use when fetching. */
+ CINIT(USERPWD, STRINGPOINT, 5),
+
+ /* "user:password" to use with proxy. */
+ CINIT(PROXYUSERPWD, STRINGPOINT, 6),
+
+ /* Range to get, specified as an ASCII string. */
+ CINIT(RANGE, STRINGPOINT, 7),
+
+ /* not used */
+
+ /* Specified file stream to upload from (use as input): */
+ CINIT(READDATA, OBJECTPOINT, 9),
+
+ /* Buffer to receive error messages in, must be at least CURL_ERROR_SIZE
+ * bytes big. */
+ CINIT(ERRORBUFFER, OBJECTPOINT, 10),
+
+ /* Function that will be called to store the output (instead of fwrite). The
+ * parameters will use fwrite() syntax, make sure to follow them. */
+ CINIT(WRITEFUNCTION, FUNCTIONPOINT, 11),
+
+ /* Function that will be called to read the input (instead of fread). The
+ * parameters will use fread() syntax, make sure to follow them. */
+ CINIT(READFUNCTION, FUNCTIONPOINT, 12),
+
+ /* Time-out the read operation after this amount of seconds */
+ CINIT(TIMEOUT, LONG, 13),
+
+ /* If the CURLOPT_INFILE is used, this can be used to inform libcurl about
+ * how large the file being sent really is. That allows better error
+ * checking and better verifies that the upload was successful. -1 means
+ * unknown size.
+ *
+ * For large file support, there is also a _LARGE version of the key
+ * which takes an off_t type, allowing platforms with larger off_t
+ * sizes to handle larger files. See below for INFILESIZE_LARGE.
+ */
+ CINIT(INFILESIZE, LONG, 14),
+
+ /* POST static input fields. */
+ CINIT(POSTFIELDS, OBJECTPOINT, 15),
+
+ /* Set the referrer page (needed by some CGIs) */
+ CINIT(REFERER, STRINGPOINT, 16),
+
+ /* Set the FTP PORT string (interface name, named or numerical IP address)
+ Use i.e '-' to use default address. */
+ CINIT(FTPPORT, STRINGPOINT, 17),
+
+ /* Set the User-Agent string (examined by some CGIs) */
+ CINIT(USERAGENT, STRINGPOINT, 18),
+
+ /* If the download receives less than "low speed limit" bytes/second
+ * during "low speed time" seconds, the operations is aborted.
+ * You could i.e if you have a pretty high speed connection, abort if
+ * it is less than 2000 bytes/sec during 20 seconds.
+ */
+
+ /* Set the "low speed limit" */
+ CINIT(LOW_SPEED_LIMIT, LONG, 19),
+
+ /* Set the "low speed time" */
+ CINIT(LOW_SPEED_TIME, LONG, 20),
+
+ /* Set the continuation offset.
+ *
+ * Note there is also a _LARGE version of this key which uses
+ * off_t types, allowing for large file offsets on platforms which
+ * use larger-than-32-bit off_t's. Look below for RESUME_FROM_LARGE.
+ */
+ CINIT(RESUME_FROM, LONG, 21),
+
+ /* Set cookie in request: */
+ CINIT(COOKIE, STRINGPOINT, 22),
+
+ /* This points to a linked list of headers, struct curl_slist kind. This
+ list is also used for RTSP (in spite of its name) */
+ CINIT(HTTPHEADER, OBJECTPOINT, 23),
+
+ /* This points to a linked list of post entries, struct curl_httppost */
+ CINIT(HTTPPOST, OBJECTPOINT, 24),
+
+ /* name of the file keeping your private SSL-certificate */
+ CINIT(SSLCERT, STRINGPOINT, 25),
+
+ /* password for the SSL or SSH private key */
+ CINIT(KEYPASSWD, STRINGPOINT, 26),
+
+ /* send TYPE parameter? */
+ CINIT(CRLF, LONG, 27),
+
+ /* send linked-list of QUOTE commands */
+ CINIT(QUOTE, OBJECTPOINT, 28),
+
+ /* send FILE * or void * to store headers to, if you use a callback it
+ is simply passed to the callback unmodified */
+ CINIT(HEADERDATA, OBJECTPOINT, 29),
+
+ /* point to a file to read the initial cookies from, also enables
+ "cookie awareness" */
+ CINIT(COOKIEFILE, STRINGPOINT, 31),
+
+ /* What version to specifically try to use.
+ See CURL_SSLVERSION defines below. */
+ CINIT(SSLVERSION, LONG, 32),
+
+ /* What kind of HTTP time condition to use, see defines */
+ CINIT(TIMECONDITION, LONG, 33),
+
+ /* Time to use with the above condition. Specified in number of seconds
+ since 1 Jan 1970 */
+ CINIT(TIMEVALUE, LONG, 34),
+
+ /* 35 = OBSOLETE */
+
+ /* Custom request, for customizing the get command like
+ HTTP: DELETE, TRACE and others
+ FTP: to use a different list command
+ */
+ CINIT(CUSTOMREQUEST, STRINGPOINT, 36),
+
+ /* FILE handle to use instead of stderr */
+ CINIT(STDERR, OBJECTPOINT, 37),
+
+ /* 38 is not used */
+
+ /* send linked-list of post-transfer QUOTE commands */
+ CINIT(POSTQUOTE, OBJECTPOINT, 39),
+
+ CINIT(OBSOLETE40, OBJECTPOINT, 40), /* OBSOLETE, do not use! */
+
+ CINIT(VERBOSE, LONG, 41), /* talk a lot */
+ CINIT(HEADER, LONG, 42), /* throw the header out too */
+ CINIT(NOPROGRESS, LONG, 43), /* shut off the progress meter */
+ CINIT(NOBODY, LONG, 44), /* use HEAD to get http document */
+ CINIT(FAILONERROR, LONG, 45), /* no output on http error codes >= 400 */
+ CINIT(UPLOAD, LONG, 46), /* this is an upload */
+ CINIT(POST, LONG, 47), /* HTTP POST method */
+ CINIT(DIRLISTONLY, LONG, 48), /* bare names when listing directories */
+
+ CINIT(APPEND, LONG, 50), /* Append instead of overwrite on upload! */
+
+ /* Specify whether to read the user+password from the .netrc or the URL.
+ * This must be one of the CURL_NETRC_* enums below. */
+ CINIT(NETRC, LONG, 51),
+
+ CINIT(FOLLOWLOCATION, LONG, 52), /* use Location: Luke! */
+
+ CINIT(TRANSFERTEXT, LONG, 53), /* transfer data in text/ASCII format */
+ CINIT(PUT, LONG, 54), /* HTTP PUT */
+
+ /* 55 = OBSOLETE */
+
+ /* DEPRECATED
+ * Function that will be called instead of the internal progress display
+ * function. This function should be defined as the curl_progress_callback
+ * prototype defines. */
+ CINIT(PROGRESSFUNCTION, FUNCTIONPOINT, 56),
+
+ /* Data passed to the CURLOPT_PROGRESSFUNCTION and CURLOPT_XFERINFOFUNCTION
+ callbacks */
+ CINIT(PROGRESSDATA, OBJECTPOINT, 57),
+#define CURLOPT_XFERINFODATA CURLOPT_PROGRESSDATA
+
+ /* We want the referrer field set automatically when following locations */
+ CINIT(AUTOREFERER, LONG, 58),
+
+ /* Port of the proxy, can be set in the proxy string as well with:
+ "[host]:[port]" */
+ CINIT(PROXYPORT, LONG, 59),
+
+ /* size of the POST input data, if strlen() is not good to use */
+ CINIT(POSTFIELDSIZE, LONG, 60),
+
+ /* tunnel non-http operations through a HTTP proxy */
+ CINIT(HTTPPROXYTUNNEL, LONG, 61),
+
+ /* Set the interface string to use as outgoing network interface */
+ CINIT(INTERFACE, STRINGPOINT, 62),
+
+ /* Set the krb4/5 security level, this also enables krb4/5 awareness. This
+ * is a string, 'clear', 'safe', 'confidential' or 'private'. If the string
+ * is set but doesn't match one of these, 'private' will be used. */
+ CINIT(KRBLEVEL, STRINGPOINT, 63),
+
+ /* Set if we should verify the peer in ssl handshake, set 1 to verify. */
+ CINIT(SSL_VERIFYPEER, LONG, 64),
+
+ /* The CApath or CAfile used to validate the peer certificate
+ this option is used only if SSL_VERIFYPEER is true */
+ CINIT(CAINFO, STRINGPOINT, 65),
+
+ /* 66 = OBSOLETE */
+ /* 67 = OBSOLETE */
+
+ /* Maximum number of http redirects to follow */
+ CINIT(MAXREDIRS, LONG, 68),
+
+ /* Pass a long set to 1 to get the date of the requested document (if
+ possible)! Pass a zero to shut it off. */
+ CINIT(FILETIME, LONG, 69),
+
+ /* This points to a linked list of telnet options */
+ CINIT(TELNETOPTIONS, OBJECTPOINT, 70),
+
+ /* Max amount of cached alive connections */
+ CINIT(MAXCONNECTS, LONG, 71),
+
+ CINIT(OBSOLETE72, LONG, 72), /* OBSOLETE, do not use! */
+
+ /* 73 = OBSOLETE */
+
+ /* Set to explicitly use a new connection for the upcoming transfer.
+ Do not use this unless you're absolutely sure of this, as it makes the
+ operation slower and is less friendly for the network. */
+ CINIT(FRESH_CONNECT, LONG, 74),
+
+ /* Set to explicitly forbid the upcoming transfer's connection to be re-used
+ when done. Do not use this unless you're absolutely sure of this, as it
+ makes the operation slower and is less friendly for the network. */
+ CINIT(FORBID_REUSE, LONG, 75),
+
+ /* Set to a file name that contains random data for libcurl to use to
+ seed the random engine when doing SSL connects. */
+ CINIT(RANDOM_FILE, STRINGPOINT, 76),
+
+ /* Set to the Entropy Gathering Daemon socket pathname */
+ CINIT(EGDSOCKET, STRINGPOINT, 77),
+
+ /* Time-out connect operations after this amount of seconds, if connects are
+ OK within this time, then fine... This only aborts the connect phase. */
+ CINIT(CONNECTTIMEOUT, LONG, 78),
+
+ /* Function that will be called to store headers (instead of fwrite). The
+ * parameters will use fwrite() syntax, make sure to follow them. */
+ CINIT(HEADERFUNCTION, FUNCTIONPOINT, 79),
+
+ /* Set this to force the HTTP request to get back to GET. Only really usable
+ if POST, PUT or a custom request have been used first.
+ */
+ CINIT(HTTPGET, LONG, 80),
+
+ /* Set if we should verify the Common name from the peer certificate in ssl
+ * handshake, set 1 to check existence, 2 to ensure that it matches the
+ * provided hostname. */
+ CINIT(SSL_VERIFYHOST, LONG, 81),
+
+ /* Specify which file name to write all known cookies in after completed
+ operation. Set file name to "-" (dash) to make it go to stdout. */
+ CINIT(COOKIEJAR, STRINGPOINT, 82),
+
+ /* Specify which SSL ciphers to use */
+ CINIT(SSL_CIPHER_LIST, STRINGPOINT, 83),
+
+ /* Specify which HTTP version to use! This must be set to one of the
+ CURL_HTTP_VERSION* enums set below. */
+ CINIT(HTTP_VERSION, LONG, 84),
+
+ /* Specifically switch on or off the FTP engine's use of the EPSV command. By
+ default, that one will always be attempted before the more traditional
+ PASV command. */
+ CINIT(FTP_USE_EPSV, LONG, 85),
+
+ /* type of the file keeping your SSL-certificate ("DER", "PEM", "ENG") */
+ CINIT(SSLCERTTYPE, STRINGPOINT, 86),
+
+ /* name of the file keeping your private SSL-key */
+ CINIT(SSLKEY, STRINGPOINT, 87),
+
+ /* type of the file keeping your private SSL-key ("DER", "PEM", "ENG") */
+ CINIT(SSLKEYTYPE, STRINGPOINT, 88),
+
+ /* crypto engine for the SSL-sub system */
+ CINIT(SSLENGINE, STRINGPOINT, 89),
+
+ /* set the crypto engine for the SSL-sub system as default
+ the param has no meaning...
+ */
+ CINIT(SSLENGINE_DEFAULT, LONG, 90),
+
+ /* Non-zero value means to use the global dns cache */
+ CINIT(DNS_USE_GLOBAL_CACHE, LONG, 91), /* DEPRECATED, do not use! */
+
+ /* DNS cache timeout */
+ CINIT(DNS_CACHE_TIMEOUT, LONG, 92),
+
+ /* send linked-list of pre-transfer QUOTE commands */
+ CINIT(PREQUOTE, OBJECTPOINT, 93),
+
+ /* set the debug function */
+ CINIT(DEBUGFUNCTION, FUNCTIONPOINT, 94),
+
+ /* set the data for the debug function */
+ CINIT(DEBUGDATA, OBJECTPOINT, 95),
+
+ /* mark this as start of a cookie session */
+ CINIT(COOKIESESSION, LONG, 96),
+
+ /* The CApath directory used to validate the peer certificate
+ this option is used only if SSL_VERIFYPEER is true */
+ CINIT(CAPATH, STRINGPOINT, 97),
+
+ /* Instruct libcurl to use a smaller receive buffer */
+ CINIT(BUFFERSIZE, LONG, 98),
+
+ /* Instruct libcurl to not use any signal/alarm handlers, even when using
+ timeouts. This option is useful for multi-threaded applications.
+ See libcurl-the-guide for more background information. */
+ CINIT(NOSIGNAL, LONG, 99),
+
+ /* Provide a CURLShare for mutexing non-ts data */
+ CINIT(SHARE, OBJECTPOINT, 100),
+
+ /* indicates type of proxy. accepted values are CURLPROXY_HTTP (default),
+ CURLPROXY_HTTPS, CURLPROXY_SOCKS4, CURLPROXY_SOCKS4A and
+ CURLPROXY_SOCKS5. */
+ CINIT(PROXYTYPE, LONG, 101),
+
+ /* Set the Accept-Encoding string. Use this to tell a server you would like
+ the response to be compressed. Before 7.21.6, this was known as
+ CURLOPT_ENCODING */
+ CINIT(ACCEPT_ENCODING, STRINGPOINT, 102),
+
+ /* Set pointer to private data */
+ CINIT(PRIVATE, OBJECTPOINT, 103),
+
+ /* Set aliases for HTTP 200 in the HTTP Response header */
+ CINIT(HTTP200ALIASES, OBJECTPOINT, 104),
+
+ /* Continue to send authentication (user+password) when following locations,
+ even when hostname changed. This can potentially send off the name
+ and password to whatever host the server decides. */
+ CINIT(UNRESTRICTED_AUTH, LONG, 105),
+
+ /* Specifically switch on or off the FTP engine's use of the EPRT command (
+ it also disables the LPRT attempt). By default, those ones will always be
+ attempted before the good old traditional PORT command. */
+ CINIT(FTP_USE_EPRT, LONG, 106),
+
+ /* Set this to a bitmask value to enable the particular authentications
+ methods you like. Use this in combination with CURLOPT_USERPWD.
+ Note that setting multiple bits may cause extra network round-trips. */
+ CINIT(HTTPAUTH, LONG, 107),
+
+ /* Set the ssl context callback function, currently only for OpenSSL ssl_ctx
+ in second argument. The function must be matching the
+ curl_ssl_ctx_callback proto. */
+ CINIT(SSL_CTX_FUNCTION, FUNCTIONPOINT, 108),
+
+ /* Set the userdata for the ssl context callback function's third
+ argument */
+ CINIT(SSL_CTX_DATA, OBJECTPOINT, 109),
+
+ /* FTP Option that causes missing dirs to be created on the remote server.
+ In 7.19.4 we introduced the convenience enums for this option using the
+ CURLFTP_CREATE_DIR prefix.
+ */
+ CINIT(FTP_CREATE_MISSING_DIRS, LONG, 110),
+
+ /* Set this to a bitmask value to enable the particular authentications
+ methods you like. Use this in combination with CURLOPT_PROXYUSERPWD.
+ Note that setting multiple bits may cause extra network round-trips. */
+ CINIT(PROXYAUTH, LONG, 111),
+
+ /* FTP option that changes the timeout, in seconds, associated with
+ getting a response. This is different from transfer timeout time and
+ essentially places a demand on the FTP server to acknowledge commands
+ in a timely manner. */
+ CINIT(FTP_RESPONSE_TIMEOUT, LONG, 112),
+#define CURLOPT_SERVER_RESPONSE_TIMEOUT CURLOPT_FTP_RESPONSE_TIMEOUT
+
+ /* Set this option to one of the CURL_IPRESOLVE_* defines (see below) to
+ tell libcurl to resolve names to those IP versions only. This only has
+ affect on systems with support for more than one, i.e IPv4 _and_ IPv6. */
+ CINIT(IPRESOLVE, LONG, 113),
+
+ /* Set this option to limit the size of a file that will be downloaded from
+ an HTTP or FTP server.
+
+ Note there is also _LARGE version which adds large file support for
+ platforms which have larger off_t sizes. See MAXFILESIZE_LARGE below. */
+ CINIT(MAXFILESIZE, LONG, 114),
+
+ /* See the comment for INFILESIZE above, but in short, specifies
+ * the size of the file being uploaded. -1 means unknown.
+ */
+ CINIT(INFILESIZE_LARGE, OFF_T, 115),
+
+ /* Sets the continuation offset. There is also a LONG version of this;
+ * look above for RESUME_FROM.
+ */
+ CINIT(RESUME_FROM_LARGE, OFF_T, 116),
+
+ /* Sets the maximum size of data that will be downloaded from
+ * an HTTP or FTP server. See MAXFILESIZE above for the LONG version.
+ */
+ CINIT(MAXFILESIZE_LARGE, OFF_T, 117),
+
+ /* Set this option to the file name of your .netrc file you want libcurl
+ to parse (using the CURLOPT_NETRC option). If not set, libcurl will do
+ a poor attempt to find the user's home directory and check for a .netrc
+ file in there. */
+ CINIT(NETRC_FILE, STRINGPOINT, 118),
+
+ /* Enable SSL/TLS for FTP, pick one of:
+ CURLUSESSL_TRY - try using SSL, proceed anyway otherwise
+ CURLUSESSL_CONTROL - SSL for the control connection or fail
+ CURLUSESSL_ALL - SSL for all communication or fail
+ */
+ CINIT(USE_SSL, LONG, 119),
+
+ /* The _LARGE version of the standard POSTFIELDSIZE option */
+ CINIT(POSTFIELDSIZE_LARGE, OFF_T, 120),
+
+ /* Enable/disable the TCP Nagle algorithm */
+ CINIT(TCP_NODELAY, LONG, 121),
+
+ /* 122 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */
+ /* 123 OBSOLETE. Gone in 7.16.0 */
+ /* 124 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */
+ /* 125 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */
+ /* 126 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */
+ /* 127 OBSOLETE. Gone in 7.16.0 */
+ /* 128 OBSOLETE. Gone in 7.16.0 */
+
+ /* When FTP over SSL/TLS is selected (with CURLOPT_USE_SSL), this option
+ can be used to change libcurl's default action which is to first try
+ "AUTH SSL" and then "AUTH TLS" in this order, and proceed when a OK
+ response has been received.
+
+ Available parameters are:
+ CURLFTPAUTH_DEFAULT - let libcurl decide
+ CURLFTPAUTH_SSL - try "AUTH SSL" first, then TLS
+ CURLFTPAUTH_TLS - try "AUTH TLS" first, then SSL
+ */
+ CINIT(FTPSSLAUTH, LONG, 129),
+
+ CINIT(IOCTLFUNCTION, FUNCTIONPOINT, 130),
+ CINIT(IOCTLDATA, OBJECTPOINT, 131),
+
+ /* 132 OBSOLETE. Gone in 7.16.0 */
+ /* 133 OBSOLETE. Gone in 7.16.0 */
+
+ /* zero terminated string for pass on to the FTP server when asked for
+ "account" info */
+ CINIT(FTP_ACCOUNT, STRINGPOINT, 134),
+
+ /* feed cookie into cookie engine */
+ CINIT(COOKIELIST, STRINGPOINT, 135),
+
+ /* ignore Content-Length */
+ CINIT(IGNORE_CONTENT_LENGTH, LONG, 136),
+
+ /* Set to non-zero to skip the IP address received in a 227 PASV FTP server
+ response. Typically used for FTP-SSL purposes but is not restricted to
+ that. libcurl will then instead use the same IP address it used for the
+ control connection. */
+ CINIT(FTP_SKIP_PASV_IP, LONG, 137),
+
+ /* Select "file method" to use when doing FTP, see the curl_ftpmethod
+ above. */
+ CINIT(FTP_FILEMETHOD, LONG, 138),
+
+ /* Local port number to bind the socket to */
+ CINIT(LOCALPORT, LONG, 139),
+
+ /* Number of ports to try, including the first one set with LOCALPORT.
+ Thus, setting it to 1 will make no additional attempts but the first.
+ */
+ CINIT(LOCALPORTRANGE, LONG, 140),
+
+ /* no transfer, set up connection and let application use the socket by
+ extracting it with CURLINFO_LASTSOCKET */
+ CINIT(CONNECT_ONLY, LONG, 141),
+
+ /* Function that will be called to convert from the
+ network encoding (instead of using the iconv calls in libcurl) */
+ CINIT(CONV_FROM_NETWORK_FUNCTION, FUNCTIONPOINT, 142),
+
+ /* Function that will be called to convert to the
+ network encoding (instead of using the iconv calls in libcurl) */
+ CINIT(CONV_TO_NETWORK_FUNCTION, FUNCTIONPOINT, 143),
+
+ /* Function that will be called to convert from UTF8
+ (instead of using the iconv calls in libcurl)
+ Note that this is used only for SSL certificate processing */
+ CINIT(CONV_FROM_UTF8_FUNCTION, FUNCTIONPOINT, 144),
+
+ /* if the connection proceeds too quickly then need to slow it down */
+ /* limit-rate: maximum number of bytes per second to send or receive */
+ CINIT(MAX_SEND_SPEED_LARGE, OFF_T, 145),
+ CINIT(MAX_RECV_SPEED_LARGE, OFF_T, 146),
+
+ /* Pointer to command string to send if USER/PASS fails. */
+ CINIT(FTP_ALTERNATIVE_TO_USER, STRINGPOINT, 147),
+
+ /* callback function for setting socket options */
+ CINIT(SOCKOPTFUNCTION, FUNCTIONPOINT, 148),
+ CINIT(SOCKOPTDATA, OBJECTPOINT, 149),
+
+ /* set to 0 to disable session ID re-use for this transfer, default is
+ enabled (== 1) */
+ CINIT(SSL_SESSIONID_CACHE, LONG, 150),
+
+ /* allowed SSH authentication methods */
+ CINIT(SSH_AUTH_TYPES, LONG, 151),
+
+ /* Used by scp/sftp to do public/private key authentication */
+ CINIT(SSH_PUBLIC_KEYFILE, STRINGPOINT, 152),
+ CINIT(SSH_PRIVATE_KEYFILE, STRINGPOINT, 153),
+
+ /* Send CCC (Clear Command Channel) after authentication */
+ CINIT(FTP_SSL_CCC, LONG, 154),
+
+ /* Same as TIMEOUT and CONNECTTIMEOUT, but with ms resolution */
+ CINIT(TIMEOUT_MS, LONG, 155),
+ CINIT(CONNECTTIMEOUT_MS, LONG, 156),
+
+ /* set to zero to disable the libcurl's decoding and thus pass the raw body
+ data to the application even when it is encoded/compressed */
+ CINIT(HTTP_TRANSFER_DECODING, LONG, 157),
+ CINIT(HTTP_CONTENT_DECODING, LONG, 158),
+
+ /* Permission used when creating new files and directories on the remote
+ server for protocols that support it, SFTP/SCP/FILE */
+ CINIT(NEW_FILE_PERMS, LONG, 159),
+ CINIT(NEW_DIRECTORY_PERMS, LONG, 160),
+
+ /* Set the behaviour of POST when redirecting. Values must be set to one
+ of CURL_REDIR* defines below. This used to be called CURLOPT_POST301 */
+ CINIT(POSTREDIR, LONG, 161),
+
+ /* used by scp/sftp to verify the host's public key */
+ CINIT(SSH_HOST_PUBLIC_KEY_MD5, STRINGPOINT, 162),
+
+ /* Callback function for opening socket (instead of socket(2)). Optionally,
+ callback is able change the address or refuse to connect returning
+ CURL_SOCKET_BAD. The callback should have type
+ curl_opensocket_callback */
+ CINIT(OPENSOCKETFUNCTION, FUNCTIONPOINT, 163),
+ CINIT(OPENSOCKETDATA, OBJECTPOINT, 164),
+
+ /* POST volatile input fields. */
+ CINIT(COPYPOSTFIELDS, OBJECTPOINT, 165),
+
+ /* set transfer mode (;type=<a|i>) when doing FTP via an HTTP proxy */
+ CINIT(PROXY_TRANSFER_MODE, LONG, 166),
+
+ /* Callback function for seeking in the input stream */
+ CINIT(SEEKFUNCTION, FUNCTIONPOINT, 167),
+ CINIT(SEEKDATA, OBJECTPOINT, 168),
+
+ /* CRL file */
+ CINIT(CRLFILE, STRINGPOINT, 169),
+
+ /* Issuer certificate */
+ CINIT(ISSUERCERT, STRINGPOINT, 170),
+
+ /* (IPv6) Address scope */
+ CINIT(ADDRESS_SCOPE, LONG, 171),
+
+ /* Collect certificate chain info and allow it to get retrievable with
+ CURLINFO_CERTINFO after the transfer is complete. */
+ CINIT(CERTINFO, LONG, 172),
+
+ /* "name" and "pwd" to use when fetching. */
+ CINIT(USERNAME, STRINGPOINT, 173),
+ CINIT(PASSWORD, STRINGPOINT, 174),
+
+ /* "name" and "pwd" to use with Proxy when fetching. */
+ CINIT(PROXYUSERNAME, STRINGPOINT, 175),
+ CINIT(PROXYPASSWORD, STRINGPOINT, 176),
+
+ /* Comma separated list of hostnames defining no-proxy zones. These should
+ match both hostnames directly, and hostnames within a domain. For
+ example, local.com will match local.com and www.local.com, but NOT
+ notlocal.com or www.notlocal.com. For compatibility with other
+ implementations of this, .local.com will be considered to be the same as
+ local.com. A single * is the only valid wildcard, and effectively
+ disables the use of proxy. */
+ CINIT(NOPROXY, STRINGPOINT, 177),
+
+ /* block size for TFTP transfers */
+ CINIT(TFTP_BLKSIZE, LONG, 178),
+
+ /* Socks Service */
+ CINIT(SOCKS5_GSSAPI_SERVICE, STRINGPOINT, 179), /* DEPRECATED, do not use! */
+
+ /* Socks Service */
+ CINIT(SOCKS5_GSSAPI_NEC, LONG, 180),
+
+ /* set the bitmask for the protocols that are allowed to be used for the
+ transfer, which thus helps the app which takes URLs from users or other
+ external inputs and want to restrict what protocol(s) to deal
+ with. Defaults to CURLPROTO_ALL. */
+ CINIT(PROTOCOLS, LONG, 181),
+
+ /* set the bitmask for the protocols that libcurl is allowed to follow to,
+ as a subset of the CURLOPT_PROTOCOLS ones. That means the protocol needs
+ to be set in both bitmasks to be allowed to get redirected to. Defaults
+ to all protocols except FILE and SCP. */
+ CINIT(REDIR_PROTOCOLS, LONG, 182),
+
+ /* set the SSH knownhost file name to use */
+ CINIT(SSH_KNOWNHOSTS, STRINGPOINT, 183),
+
+ /* set the SSH host key callback, must point to a curl_sshkeycallback
+ function */
+ CINIT(SSH_KEYFUNCTION, FUNCTIONPOINT, 184),
+
+ /* set the SSH host key callback custom pointer */
+ CINIT(SSH_KEYDATA, OBJECTPOINT, 185),
+
+ /* set the SMTP mail originator */
+ CINIT(MAIL_FROM, STRINGPOINT, 186),
+
+ /* set the list of SMTP mail receiver(s) */
+ CINIT(MAIL_RCPT, OBJECTPOINT, 187),
+
+ /* FTP: send PRET before PASV */
+ CINIT(FTP_USE_PRET, LONG, 188),
+
+ /* RTSP request method (OPTIONS, SETUP, PLAY, etc...) */
+ CINIT(RTSP_REQUEST, LONG, 189),
+
+ /* The RTSP session identifier */
+ CINIT(RTSP_SESSION_ID, STRINGPOINT, 190),
+
+ /* The RTSP stream URI */
+ CINIT(RTSP_STREAM_URI, STRINGPOINT, 191),
+
+ /* The Transport: header to use in RTSP requests */
+ CINIT(RTSP_TRANSPORT, STRINGPOINT, 192),
+
+ /* Manually initialize the client RTSP CSeq for this handle */
+ CINIT(RTSP_CLIENT_CSEQ, LONG, 193),
+
+ /* Manually initialize the server RTSP CSeq for this handle */
+ CINIT(RTSP_SERVER_CSEQ, LONG, 194),
+
+ /* The stream to pass to INTERLEAVEFUNCTION. */
+ CINIT(INTERLEAVEDATA, OBJECTPOINT, 195),
+
+ /* Let the application define a custom write method for RTP data */
+ CINIT(INTERLEAVEFUNCTION, FUNCTIONPOINT, 196),
+
+ /* Turn on wildcard matching */
+ CINIT(WILDCARDMATCH, LONG, 197),
+
+ /* Directory matching callback called before downloading of an
+ individual file (chunk) started */
+ CINIT(CHUNK_BGN_FUNCTION, FUNCTIONPOINT, 198),
+
+ /* Directory matching callback called after the file (chunk)
+ was downloaded, or skipped */
+ CINIT(CHUNK_END_FUNCTION, FUNCTIONPOINT, 199),
+
+ /* Change match (fnmatch-like) callback for wildcard matching */
+ CINIT(FNMATCH_FUNCTION, FUNCTIONPOINT, 200),
+
+ /* Let the application define custom chunk data pointer */
+ CINIT(CHUNK_DATA, OBJECTPOINT, 201),
+
+ /* FNMATCH_FUNCTION user pointer */
+ CINIT(FNMATCH_DATA, OBJECTPOINT, 202),
+
+ /* send linked-list of name:port:address sets */
+ CINIT(RESOLVE, OBJECTPOINT, 203),
+
+ /* Set a username for authenticated TLS */
+ CINIT(TLSAUTH_USERNAME, STRINGPOINT, 204),
+
+ /* Set a password for authenticated TLS */
+ CINIT(TLSAUTH_PASSWORD, STRINGPOINT, 205),
+
+ /* Set authentication type for authenticated TLS */
+ CINIT(TLSAUTH_TYPE, STRINGPOINT, 206),
+
+ /* Set to 1 to enable the "TE:" header in HTTP requests to ask for
+ compressed transfer-encoded responses. Set to 0 to disable the use of TE:
+ in outgoing requests. The current default is 0, but it might change in a
+ future libcurl release.
+
+ libcurl will ask for the compressed methods it knows of, and if that
+ isn't any, it will not ask for transfer-encoding at all even if this
+ option is set to 1.
+
+ */
+ CINIT(TRANSFER_ENCODING, LONG, 207),
+
+ /* Callback function for closing socket (instead of close(2)). The callback
+ should have type curl_closesocket_callback */
+ CINIT(CLOSESOCKETFUNCTION, FUNCTIONPOINT, 208),
+ CINIT(CLOSESOCKETDATA, OBJECTPOINT, 209),
+
+ /* allow GSSAPI credential delegation */
+ CINIT(GSSAPI_DELEGATION, LONG, 210),
+
+ /* Set the name servers to use for DNS resolution */
+ CINIT(DNS_SERVERS, STRINGPOINT, 211),
+
+ /* Time-out accept operations (currently for FTP only) after this amount
+ of milliseconds. */
+ CINIT(ACCEPTTIMEOUT_MS, LONG, 212),
+
+ /* Set TCP keepalive */
+ CINIT(TCP_KEEPALIVE, LONG, 213),
+
+ /* non-universal keepalive knobs (Linux, AIX, HP-UX, more) */
+ CINIT(TCP_KEEPIDLE, LONG, 214),
+ CINIT(TCP_KEEPINTVL, LONG, 215),
+
+ /* Enable/disable specific SSL features with a bitmask, see CURLSSLOPT_* */
+ CINIT(SSL_OPTIONS, LONG, 216),
+
+ /* Set the SMTP auth originator */
+ CINIT(MAIL_AUTH, STRINGPOINT, 217),
+
+ /* Enable/disable SASL initial response */
+ CINIT(SASL_IR, LONG, 218),
+
+ /* Function that will be called instead of the internal progress display
+ * function. This function should be defined as the curl_xferinfo_callback
+ * prototype defines. (Deprecates CURLOPT_PROGRESSFUNCTION) */
+ CINIT(XFERINFOFUNCTION, FUNCTIONPOINT, 219),
+
+ /* The XOAUTH2 bearer token */
+ CINIT(XOAUTH2_BEARER, STRINGPOINT, 220),
+
+ /* Set the interface string to use as outgoing network
+ * interface for DNS requests.
+ * Only supported by the c-ares DNS backend */
+ CINIT(DNS_INTERFACE, STRINGPOINT, 221),
+
+ /* Set the local IPv4 address to use for outgoing DNS requests.
+ * Only supported by the c-ares DNS backend */
+ CINIT(DNS_LOCAL_IP4, STRINGPOINT, 222),
+
+ /* Set the local IPv6 address to use for outgoing DNS requests.
+ * Only supported by the c-ares DNS backend */
+ CINIT(DNS_LOCAL_IP6, STRINGPOINT, 223),
+
+ /* Set authentication options directly */
+ CINIT(LOGIN_OPTIONS, STRINGPOINT, 224),
+
+ /* Enable/disable TLS NPN extension (http2 over ssl might fail without) */
+ CINIT(SSL_ENABLE_NPN, LONG, 225),
+
+ /* Enable/disable TLS ALPN extension (http2 over ssl might fail without) */
+ CINIT(SSL_ENABLE_ALPN, LONG, 226),
+
+ /* Time to wait for a response to a HTTP request containing an
+ * Expect: 100-continue header before sending the data anyway. */
+ CINIT(EXPECT_100_TIMEOUT_MS, LONG, 227),
+
+ /* This points to a linked list of headers used for proxy requests only,
+ struct curl_slist kind */
+ CINIT(PROXYHEADER, OBJECTPOINT, 228),
+
+ /* Pass in a bitmask of "header options" */
+ CINIT(HEADEROPT, LONG, 229),
+
+ /* The public key in DER form used to validate the peer public key
+ this option is used only if SSL_VERIFYPEER is true */
+ CINIT(PINNEDPUBLICKEY, STRINGPOINT, 230),
+
+ /* Path to Unix domain socket */
+ CINIT(UNIX_SOCKET_PATH, STRINGPOINT, 231),
+
+ /* Set if we should verify the certificate status. */
+ CINIT(SSL_VERIFYSTATUS, LONG, 232),
+
+ /* Set if we should enable TLS false start. */
+ CINIT(SSL_FALSESTART, LONG, 233),
+
+ /* Do not squash dot-dot sequences */
+ CINIT(PATH_AS_IS, LONG, 234),
+
+ /* Proxy Service Name */
+ CINIT(PROXY_SERVICE_NAME, STRINGPOINT, 235),
+
+ /* Service Name */
+ CINIT(SERVICE_NAME, STRINGPOINT, 236),
+
+ /* Wait/don't wait for pipe/mutex to clarify */
+ CINIT(PIPEWAIT, LONG, 237),
+
+ /* Set the protocol used when curl is given a URL without a protocol */
+ CINIT(DEFAULT_PROTOCOL, STRINGPOINT, 238),
+
+ /* Set stream weight, 1 - 256 (default is 16) */
+ CINIT(STREAM_WEIGHT, LONG, 239),
+
+ /* Set stream dependency on another CURL handle */
+ CINIT(STREAM_DEPENDS, OBJECTPOINT, 240),
+
+ /* Set E-xclusive stream dependency on another CURL handle */
+ CINIT(STREAM_DEPENDS_E, OBJECTPOINT, 241),
+
+ /* Do not send any tftp option requests to the server */
+ CINIT(TFTP_NO_OPTIONS, LONG, 242),
+
+ /* Linked-list of host:port:connect-to-host:connect-to-port,
+ overrides the URL's host:port (only for the network layer) */
+ CINIT(CONNECT_TO, OBJECTPOINT, 243),
+
+ /* Set TCP Fast Open */
+ CINIT(TCP_FASTOPEN, LONG, 244),
+
+ /* Continue to send data if the server responds early with an
+ * HTTP status code >= 300 */
+ CINIT(KEEP_SENDING_ON_ERROR, LONG, 245),
+
+ /* The CApath or CAfile used to validate the proxy certificate
+ this option is used only if PROXY_SSL_VERIFYPEER is true */
+ CINIT(PROXY_CAINFO, STRINGPOINT, 246),
+
+ /* The CApath directory used to validate the proxy certificate
+ this option is used only if PROXY_SSL_VERIFYPEER is true */
+ CINIT(PROXY_CAPATH, STRINGPOINT, 247),
+
+ /* Set if we should verify the proxy in ssl handshake,
+ set 1 to verify. */
+ CINIT(PROXY_SSL_VERIFYPEER, LONG, 248),
+
+ /* Set if we should verify the Common name from the proxy certificate in ssl
+ * handshake, set 1 to check existence, 2 to ensure that it matches
+ * the provided hostname. */
+ CINIT(PROXY_SSL_VERIFYHOST, LONG, 249),
+
+ /* What version to specifically try to use for proxy.
+ See CURL_SSLVERSION defines below. */
+ CINIT(PROXY_SSLVERSION, LONG, 250),
+
+ /* Set a username for authenticated TLS for proxy */
+ CINIT(PROXY_TLSAUTH_USERNAME, STRINGPOINT, 251),
+
+ /* Set a password for authenticated TLS for proxy */
+ CINIT(PROXY_TLSAUTH_PASSWORD, STRINGPOINT, 252),
+
+ /* Set authentication type for authenticated TLS for proxy */
+ CINIT(PROXY_TLSAUTH_TYPE, STRINGPOINT, 253),
+
+ /* name of the file keeping your private SSL-certificate for proxy */
+ CINIT(PROXY_SSLCERT, STRINGPOINT, 254),
+
+ /* type of the file keeping your SSL-certificate ("DER", "PEM", "ENG") for
+ proxy */
+ CINIT(PROXY_SSLCERTTYPE, STRINGPOINT, 255),
+
+ /* name of the file keeping your private SSL-key for proxy */
+ CINIT(PROXY_SSLKEY, STRINGPOINT, 256),
+
+ /* type of the file keeping your private SSL-key ("DER", "PEM", "ENG") for
+ proxy */
+ CINIT(PROXY_SSLKEYTYPE, STRINGPOINT, 257),
+
+ /* password for the SSL private key for proxy */
+ CINIT(PROXY_KEYPASSWD, STRINGPOINT, 258),
+
+ /* Specify which SSL ciphers to use for proxy */
+ CINIT(PROXY_SSL_CIPHER_LIST, STRINGPOINT, 259),
+
+ /* CRL file for proxy */
+ CINIT(PROXY_CRLFILE, STRINGPOINT, 260),
+
+ /* Enable/disable specific SSL features with a bitmask for proxy, see
+ CURLSSLOPT_* */
+ CINIT(PROXY_SSL_OPTIONS, LONG, 261),
+
+ /* Name of pre proxy to use. */
+ CINIT(PRE_PROXY, STRINGPOINT, 262),
+
+ /* The public key in DER form used to validate the proxy public key
+ this option is used only if PROXY_SSL_VERIFYPEER is true */
+ CINIT(PROXY_PINNEDPUBLICKEY, STRINGPOINT, 263),
+
+ /* Path to an abstract Unix domain socket */
+ CINIT(ABSTRACT_UNIX_SOCKET, STRINGPOINT, 264),
+
+ /* Suppress proxy CONNECT response headers from user callbacks */
+ CINIT(SUPPRESS_CONNECT_HEADERS, LONG, 265),
+
+ /* The request target, instead of extracted from the URL */
+ CINIT(REQUEST_TARGET, STRINGPOINT, 266),
+
+ /* bitmask of allowed auth methods for connections to SOCKS5 proxies */
+ CINIT(SOCKS5_AUTH, LONG, 267),
+
+ /* Enable/disable SSH compression */
+ CINIT(SSH_COMPRESSION, LONG, 268),
+
+ /* Post MIME data. */
+ CINIT(MIMEPOST, OBJECTPOINT, 269),
+
+ /* Time to use with the CURLOPT_TIMECONDITION. Specified in number of
+ seconds since 1 Jan 1970. */
+ CINIT(TIMEVALUE_LARGE, OFF_T, 270),
+
+ /* Head start in milliseconds to give happy eyeballs. */
+ CINIT(HAPPY_EYEBALLS_TIMEOUT_MS, LONG, 271),
+
+ /* Function that will be called before a resolver request is made */
+ CINIT(RESOLVER_START_FUNCTION, FUNCTIONPOINT, 272),
+
+ /* User data to pass to the resolver start callback. */
+ CINIT(RESOLVER_START_DATA, OBJECTPOINT, 273),
+
+ /* send HAProxy PROXY protocol header? */
+ CINIT(HAPROXYPROTOCOL, LONG, 274),
+
+ /* shuffle addresses before use when DNS returns multiple */
+ CINIT(DNS_SHUFFLE_ADDRESSES, LONG, 275),
+
+ /* Specify which TLS 1.3 ciphers suites to use */
+ CINIT(TLS13_CIPHERS, STRINGPOINT, 276),
+ CINIT(PROXY_TLS13_CIPHERS, STRINGPOINT, 277),
+
+ /* Disallow specifying username/login in URL. */
+ CINIT(DISALLOW_USERNAME_IN_URL, LONG, 278),
+
+ /* DNS-over-HTTPS URL */
+ CINIT(DOH_URL, STRINGPOINT, 279),
+
+ /* Preferred buffer size to use for uploads */
+ CINIT(UPLOAD_BUFFERSIZE, LONG, 280),
+
+ /* Time in ms between connection upkeep calls for long-lived connections. */
+ CINIT(UPKEEP_INTERVAL_MS, LONG, 281),
+
+ /* Specify URL using CURL URL API. */
+ CINIT(CURLU, OBJECTPOINT, 282),
+
+ /* add trailing data just after no more data is available */
+ CINIT(TRAILERFUNCTION, FUNCTIONPOINT, 283),
+
+ /* pointer to be passed to HTTP_TRAILER_FUNCTION */
+ CINIT(TRAILERDATA, OBJECTPOINT, 284),
+
+ /* set this to 1L to allow HTTP/0.9 responses or 0L to disallow */
+ CINIT(HTTP09_ALLOWED, LONG, 285),
+
+ /* alt-svc control bitmask */
+ CINIT(ALTSVC_CTRL, LONG, 286),
+
+ /* alt-svc cache file name to possibly read from/write to */
+ CINIT(ALTSVC, STRINGPOINT, 287),
+
+ CURLOPT_LASTENTRY /* the last unused */
+} CURLoption;
+
+#ifndef CURL_NO_OLDIES /* define this to test if your app builds with all
+ the obsolete stuff removed! */
+
+/* Backwards compatibility with older names */
+/* These are scheduled to disappear by 2011 */
+
+/* This was added in version 7.19.1 */
+#define CURLOPT_POST301 CURLOPT_POSTREDIR
+
+/* These are scheduled to disappear by 2009 */
+
+/* The following were added in 7.17.0 */
+#define CURLOPT_SSLKEYPASSWD CURLOPT_KEYPASSWD
+#define CURLOPT_FTPAPPEND CURLOPT_APPEND
+#define CURLOPT_FTPLISTONLY CURLOPT_DIRLISTONLY
+#define CURLOPT_FTP_SSL CURLOPT_USE_SSL
+
+/* The following were added earlier */
+
+#define CURLOPT_SSLCERTPASSWD CURLOPT_KEYPASSWD
+#define CURLOPT_KRB4LEVEL CURLOPT_KRBLEVEL
+
+#else
+/* This is set if CURL_NO_OLDIES is defined at compile-time */
+#undef CURLOPT_DNS_USE_GLOBAL_CACHE /* soon obsolete */
+#endif
+
+
+ /* Below here follows defines for the CURLOPT_IPRESOLVE option. If a host
+ name resolves addresses using more than one IP protocol version, this
+ option might be handy to force libcurl to use a specific IP version. */
+#define CURL_IPRESOLVE_WHATEVER 0 /* default, resolves addresses to all IP
+ versions that your system allows */
+#define CURL_IPRESOLVE_V4 1 /* resolve to IPv4 addresses */
+#define CURL_IPRESOLVE_V6 2 /* resolve to IPv6 addresses */
+
+ /* three convenient "aliases" that follow the name scheme better */
+#define CURLOPT_RTSPHEADER CURLOPT_HTTPHEADER
+
+ /* These enums are for use with the CURLOPT_HTTP_VERSION option. */
+enum {
+ CURL_HTTP_VERSION_NONE, /* setting this means we don't care, and that we'd
+ like the library to choose the best possible
+ for us! */
+ CURL_HTTP_VERSION_1_0, /* please use HTTP 1.0 in the request */
+ CURL_HTTP_VERSION_1_1, /* please use HTTP 1.1 in the request */
+ CURL_HTTP_VERSION_2_0, /* please use HTTP 2 in the request */
+ CURL_HTTP_VERSION_2TLS, /* use version 2 for HTTPS, version 1.1 for HTTP */
+ CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE, /* please use HTTP 2 without HTTP/1.1
+ Upgrade */
+
+ CURL_HTTP_VERSION_LAST /* *ILLEGAL* http version */
+};
+
+/* Convenience definition simple because the name of the version is HTTP/2 and
+ not 2.0. The 2_0 version of the enum name was set while the version was
+ still planned to be 2.0 and we stick to it for compatibility. */
+#define CURL_HTTP_VERSION_2 CURL_HTTP_VERSION_2_0
+
+/*
+ * Public API enums for RTSP requests
+ */
+enum {
+ CURL_RTSPREQ_NONE, /* first in list */
+ CURL_RTSPREQ_OPTIONS,
+ CURL_RTSPREQ_DESCRIBE,
+ CURL_RTSPREQ_ANNOUNCE,
+ CURL_RTSPREQ_SETUP,
+ CURL_RTSPREQ_PLAY,
+ CURL_RTSPREQ_PAUSE,
+ CURL_RTSPREQ_TEARDOWN,
+ CURL_RTSPREQ_GET_PARAMETER,
+ CURL_RTSPREQ_SET_PARAMETER,
+ CURL_RTSPREQ_RECORD,
+ CURL_RTSPREQ_RECEIVE,
+ CURL_RTSPREQ_LAST /* last in list */
+};
+
+ /* These enums are for use with the CURLOPT_NETRC option. */
+enum CURL_NETRC_OPTION {
+ CURL_NETRC_IGNORED, /* The .netrc will never be read.
+ * This is the default. */
+ CURL_NETRC_OPTIONAL, /* A user:password in the URL will be preferred
+ * to one in the .netrc. */
+ CURL_NETRC_REQUIRED, /* A user:password in the URL will be ignored.
+ * Unless one is set programmatically, the .netrc
+ * will be queried. */
+ CURL_NETRC_LAST
+};
+
+enum {
+ CURL_SSLVERSION_DEFAULT,
+ CURL_SSLVERSION_TLSv1, /* TLS 1.x */
+ CURL_SSLVERSION_SSLv2,
+ CURL_SSLVERSION_SSLv3,
+ CURL_SSLVERSION_TLSv1_0,
+ CURL_SSLVERSION_TLSv1_1,
+ CURL_SSLVERSION_TLSv1_2,
+ CURL_SSLVERSION_TLSv1_3,
+
+ CURL_SSLVERSION_LAST /* never use, keep last */
+};
+
+enum {
+ CURL_SSLVERSION_MAX_NONE = 0,
+ CURL_SSLVERSION_MAX_DEFAULT = (CURL_SSLVERSION_TLSv1 << 16),
+ CURL_SSLVERSION_MAX_TLSv1_0 = (CURL_SSLVERSION_TLSv1_0 << 16),
+ CURL_SSLVERSION_MAX_TLSv1_1 = (CURL_SSLVERSION_TLSv1_1 << 16),
+ CURL_SSLVERSION_MAX_TLSv1_2 = (CURL_SSLVERSION_TLSv1_2 << 16),
+ CURL_SSLVERSION_MAX_TLSv1_3 = (CURL_SSLVERSION_TLSv1_3 << 16),
+
+ /* never use, keep last */
+ CURL_SSLVERSION_MAX_LAST = (CURL_SSLVERSION_LAST << 16)
+};
+
+enum CURL_TLSAUTH {
+ CURL_TLSAUTH_NONE,
+ CURL_TLSAUTH_SRP,
+ CURL_TLSAUTH_LAST /* never use, keep last */
+};
+
+/* symbols to use with CURLOPT_POSTREDIR.
+ CURL_REDIR_POST_301, CURL_REDIR_POST_302 and CURL_REDIR_POST_303
+ can be bitwise ORed so that CURL_REDIR_POST_301 | CURL_REDIR_POST_302
+ | CURL_REDIR_POST_303 == CURL_REDIR_POST_ALL */
+
+#define CURL_REDIR_GET_ALL 0
+#define CURL_REDIR_POST_301 1
+#define CURL_REDIR_POST_302 2
+#define CURL_REDIR_POST_303 4
+#define CURL_REDIR_POST_ALL \
+ (CURL_REDIR_POST_301|CURL_REDIR_POST_302|CURL_REDIR_POST_303)
+
+typedef enum {
+ CURL_TIMECOND_NONE,
+
+ CURL_TIMECOND_IFMODSINCE,
+ CURL_TIMECOND_IFUNMODSINCE,
+ CURL_TIMECOND_LASTMOD,
+
+ CURL_TIMECOND_LAST
+} curl_TimeCond;
+
+/* Special size_t value signaling a zero-terminated string. */
+#define CURL_ZERO_TERMINATED ((size_t) -1)
+
+/* curl_strequal() and curl_strnequal() are subject for removal in a future
+ release */
+CURL_EXTERN int curl_strequal(const char *s1, const char *s2);
+CURL_EXTERN int curl_strnequal(const char *s1, const char *s2, size_t n);
+
+/* Mime/form handling support. */
+typedef struct curl_mime_s curl_mime; /* Mime context. */
+typedef struct curl_mimepart_s curl_mimepart; /* Mime part context. */
+
+/*
+ * NAME curl_mime_init()
+ *
+ * DESCRIPTION
+ *
+ * Create a mime context and return its handle. The easy parameter is the
+ * target handle.
+ */
+CURL_EXTERN curl_mime *curl_mime_init(CURL *easy);
+
+/*
+ * NAME curl_mime_free()
+ *
+ * DESCRIPTION
+ *
+ * release a mime handle and its substructures.
+ */
+CURL_EXTERN void curl_mime_free(curl_mime *mime);
+
+/*
+ * NAME curl_mime_addpart()
+ *
+ * DESCRIPTION
+ *
+ * Append a new empty part to the given mime context and return a handle to
+ * the created part.
+ */
+CURL_EXTERN curl_mimepart *curl_mime_addpart(curl_mime *mime);
+
+/*
+ * NAME curl_mime_name()
+ *
+ * DESCRIPTION
+ *
+ * Set mime/form part name.
+ */
+CURL_EXTERN CURLcode curl_mime_name(curl_mimepart *part, const char *name);
+
+/*
+ * NAME curl_mime_filename()
+ *
+ * DESCRIPTION
+ *
+ * Set mime part remote file name.
+ */
+CURL_EXTERN CURLcode curl_mime_filename(curl_mimepart *part,
+ const char *filename);
+
+/*
+ * NAME curl_mime_type()
+ *
+ * DESCRIPTION
+ *
+ * Set mime part type.
+ */
+CURL_EXTERN CURLcode curl_mime_type(curl_mimepart *part, const char *mimetype);
+
+/*
+ * NAME curl_mime_encoder()
+ *
+ * DESCRIPTION
+ *
+ * Set mime data transfer encoder.
+ */
+CURL_EXTERN CURLcode curl_mime_encoder(curl_mimepart *part,
+ const char *encoding);
+
+/*
+ * NAME curl_mime_data()
+ *
+ * DESCRIPTION
+ *
+ * Set mime part data source from memory data,
+ */
+CURL_EXTERN CURLcode curl_mime_data(curl_mimepart *part,
+ const char *data, size_t datasize);
+
+/*
+ * NAME curl_mime_filedata()
+ *
+ * DESCRIPTION
+ *
+ * Set mime part data source from named file.
+ */
+CURL_EXTERN CURLcode curl_mime_filedata(curl_mimepart *part,
+ const char *filename);
+
+/*
+ * NAME curl_mime_data_cb()
+ *
+ * DESCRIPTION
+ *
+ * Set mime part data source from callback function.
+ */
+CURL_EXTERN CURLcode curl_mime_data_cb(curl_mimepart *part,
+ curl_off_t datasize,
+ curl_read_callback readfunc,
+ curl_seek_callback seekfunc,
+ curl_free_callback freefunc,
+ void *arg);
+
+/*
+ * NAME curl_mime_subparts()
+ *
+ * DESCRIPTION
+ *
+ * Set mime part data source from subparts.
+ */
+CURL_EXTERN CURLcode curl_mime_subparts(curl_mimepart *part,
+ curl_mime *subparts);
+/*
+ * NAME curl_mime_headers()
+ *
+ * DESCRIPTION
+ *
+ * Set mime part headers.
+ */
+CURL_EXTERN CURLcode curl_mime_headers(curl_mimepart *part,
+ struct curl_slist *headers,
+ int take_ownership);
+
+/* Old form API. */
+/* name is uppercase CURLFORM_<name> */
+#ifdef CFINIT
+#undef CFINIT
+#endif
+
+#ifdef CURL_ISOCPP
+#define CFINIT(name) CURLFORM_ ## name
+#else
+/* The macro "##" is ISO C, we assume pre-ISO C doesn't support it. */
+#define CFINIT(name) CURLFORM_/**/name
+#endif
+
+typedef enum {
+ CFINIT(NOTHING), /********* the first one is unused ************/
+
+ /* */
+ CFINIT(COPYNAME),
+ CFINIT(PTRNAME),
+ CFINIT(NAMELENGTH),
+ CFINIT(COPYCONTENTS),
+ CFINIT(PTRCONTENTS),
+ CFINIT(CONTENTSLENGTH),
+ CFINIT(FILECONTENT),
+ CFINIT(ARRAY),
+ CFINIT(OBSOLETE),
+ CFINIT(FILE),
+
+ CFINIT(BUFFER),
+ CFINIT(BUFFERPTR),
+ CFINIT(BUFFERLENGTH),
+
+ CFINIT(CONTENTTYPE),
+ CFINIT(CONTENTHEADER),
+ CFINIT(FILENAME),
+ CFINIT(END),
+ CFINIT(OBSOLETE2),
+
+ CFINIT(STREAM),
+ CFINIT(CONTENTLEN), /* added in 7.46.0, provide a curl_off_t length */
+
+ CURLFORM_LASTENTRY /* the last unused */
+} CURLformoption;
+
+#undef CFINIT /* done */
+
+/* structure to be used as parameter for CURLFORM_ARRAY */
+struct curl_forms {
+ CURLformoption option;
+ const char *value;
+};
+
+/* use this for multipart formpost building */
+/* Returns code for curl_formadd()
+ *
+ * Returns:
+ * CURL_FORMADD_OK on success
+ * CURL_FORMADD_MEMORY if the FormInfo allocation fails
+ * CURL_FORMADD_OPTION_TWICE if one option is given twice for one Form
+ * CURL_FORMADD_NULL if a null pointer was given for a char
+ * CURL_FORMADD_MEMORY if the allocation of a FormInfo struct failed
+ * CURL_FORMADD_UNKNOWN_OPTION if an unknown option was used
+ * CURL_FORMADD_INCOMPLETE if the some FormInfo is not complete (or error)
+ * CURL_FORMADD_MEMORY if a curl_httppost struct cannot be allocated
+ * CURL_FORMADD_MEMORY if some allocation for string copying failed.
+ * CURL_FORMADD_ILLEGAL_ARRAY if an illegal option is used in an array
+ *
+ ***************************************************************************/
+typedef enum {
+ CURL_FORMADD_OK, /* first, no error */
+
+ CURL_FORMADD_MEMORY,
+ CURL_FORMADD_OPTION_TWICE,
+ CURL_FORMADD_NULL,
+ CURL_FORMADD_UNKNOWN_OPTION,
+ CURL_FORMADD_INCOMPLETE,
+ CURL_FORMADD_ILLEGAL_ARRAY,
+ CURL_FORMADD_DISABLED, /* libcurl was built with this disabled */
+
+ CURL_FORMADD_LAST /* last */
+} CURLFORMcode;
+
+/*
+ * NAME curl_formadd()
+ *
+ * DESCRIPTION
+ *
+ * Pretty advanced function for building multi-part formposts. Each invoke
+ * adds one part that together construct a full post. Then use
+ * CURLOPT_HTTPPOST to send it off to libcurl.
+ */
+CURL_EXTERN CURLFORMcode curl_formadd(struct curl_httppost **httppost,
+ struct curl_httppost **last_post,
+ ...);
+
+/*
+ * callback function for curl_formget()
+ * The void *arg pointer will be the one passed as second argument to
+ * curl_formget().
+ * The character buffer passed to it must not be freed.
+ * Should return the buffer length passed to it as the argument "len" on
+ * success.
+ */
+typedef size_t (*curl_formget_callback)(void *arg, const char *buf,
+ size_t len);
+
+/*
+ * NAME curl_formget()
+ *
+ * DESCRIPTION
+ *
+ * Serialize a curl_httppost struct built with curl_formadd().
+ * Accepts a void pointer as second argument which will be passed to
+ * the curl_formget_callback function.
+ * Returns 0 on success.
+ */
+CURL_EXTERN int curl_formget(struct curl_httppost *form, void *arg,
+ curl_formget_callback append);
+/*
+ * NAME curl_formfree()
+ *
+ * DESCRIPTION
+ *
+ * Free a multipart formpost previously built with curl_formadd().
+ */
+CURL_EXTERN void curl_formfree(struct curl_httppost *form);
+
+/*
+ * NAME curl_getenv()
+ *
+ * DESCRIPTION
+ *
+ * Returns a malloc()'ed string that MUST be curl_free()ed after usage is
+ * complete. DEPRECATED - see lib/README.curlx
+ */
+CURL_EXTERN char *curl_getenv(const char *variable);
+
+/*
+ * NAME curl_version()
+ *
+ * DESCRIPTION
+ *
+ * Returns a static ascii string of the libcurl version.
+ */
+CURL_EXTERN char *curl_version(void);
+
+/*
+ * NAME curl_easy_escape()
+ *
+ * DESCRIPTION
+ *
+ * Escapes URL strings (converts all letters consider illegal in URLs to their
+ * %XX versions). This function returns a new allocated string or NULL if an
+ * error occurred.
+ */
+CURL_EXTERN char *curl_easy_escape(CURL *handle,
+ const char *string,
+ int length);
+
+/* the previous version: */
+CURL_EXTERN char *curl_escape(const char *string,
+ int length);
+
+
+/*
+ * NAME curl_easy_unescape()
+ *
+ * DESCRIPTION
+ *
+ * Unescapes URL encoding in strings (converts all %XX codes to their 8bit
+ * versions). This function returns a new allocated string or NULL if an error
+ * occurred.
+ * Conversion Note: On non-ASCII platforms the ASCII %XX codes are
+ * converted into the host encoding.
+ */
+CURL_EXTERN char *curl_easy_unescape(CURL *handle,
+ const char *string,
+ int length,
+ int *outlength);
+
+/* the previous version */
+CURL_EXTERN char *curl_unescape(const char *string,
+ int length);
+
+/*
+ * NAME curl_free()
+ *
+ * DESCRIPTION
+ *
+ * Provided for de-allocation in the same translation unit that did the
+ * allocation. Added in libcurl 7.10
+ */
+CURL_EXTERN void curl_free(void *p);
+
+/*
+ * NAME curl_global_init()
+ *
+ * DESCRIPTION
+ *
+ * curl_global_init() should be invoked exactly once for each application that
+ * uses libcurl and before any call of other libcurl functions.
+ *
+ * This function is not thread-safe!
+ */
+CURL_EXTERN CURLcode curl_global_init(long flags);
+
+/*
+ * NAME curl_global_init_mem()
+ *
+ * DESCRIPTION
+ *
+ * curl_global_init() or curl_global_init_mem() should be invoked exactly once
+ * for each application that uses libcurl. This function can be used to
+ * initialize libcurl and set user defined memory management callback
+ * functions. Users can implement memory management routines to check for
+ * memory leaks, check for mis-use of the curl library etc. User registered
+ * callback routines with be invoked by this library instead of the system
+ * memory management routines like malloc, free etc.
+ */
+CURL_EXTERN CURLcode curl_global_init_mem(long flags,
+ curl_malloc_callback m,
+ curl_free_callback f,
+ curl_realloc_callback r,
+ curl_strdup_callback s,
+ curl_calloc_callback c);
+
+/*
+ * NAME curl_global_cleanup()
+ *
+ * DESCRIPTION
+ *
+ * curl_global_cleanup() should be invoked exactly once for each application
+ * that uses libcurl
+ */
+CURL_EXTERN void curl_global_cleanup(void);
+
+/* linked-list structure for the CURLOPT_QUOTE option (and other) */
+struct curl_slist {
+ char *data;
+ struct curl_slist *next;
+};
+
+/*
+ * NAME curl_global_sslset()
+ *
+ * DESCRIPTION
+ *
+ * When built with multiple SSL backends, curl_global_sslset() allows to
+ * choose one. This function can only be called once, and it must be called
+ * *before* curl_global_init().
+ *
+ * The backend can be identified by the id (e.g. CURLSSLBACKEND_OPENSSL). The
+ * backend can also be specified via the name parameter (passing -1 as id).
+ * If both id and name are specified, the name will be ignored. If neither id
+ * nor name are specified, the function will fail with
+ * CURLSSLSET_UNKNOWN_BACKEND and set the "avail" pointer to the
+ * NULL-terminated list of available backends.
+ *
+ * Upon success, the function returns CURLSSLSET_OK.
+ *
+ * If the specified SSL backend is not available, the function returns
+ * CURLSSLSET_UNKNOWN_BACKEND and sets the "avail" pointer to a NULL-terminated
+ * list of available SSL backends.
+ *
+ * The SSL backend can be set only once. If it has already been set, a
+ * subsequent attempt to change it will result in a CURLSSLSET_TOO_LATE.
+ */
+
+typedef struct {
+ curl_sslbackend id;
+ const char *name;
+} curl_ssl_backend;
+
+typedef enum {
+ CURLSSLSET_OK = 0,
+ CURLSSLSET_UNKNOWN_BACKEND,
+ CURLSSLSET_TOO_LATE,
+ CURLSSLSET_NO_BACKENDS /* libcurl was built without any SSL support */
+} CURLsslset;
+
+CURL_EXTERN CURLsslset curl_global_sslset(curl_sslbackend id, const char *name,
+ const curl_ssl_backend ***avail);
+
+/*
+ * NAME curl_slist_append()
+ *
+ * DESCRIPTION
+ *
+ * Appends a string to a linked list. If no list exists, it will be created
+ * first. Returns the new list, after appending.
+ */
+CURL_EXTERN struct curl_slist *curl_slist_append(struct curl_slist *,
+ const char *);
+
+/*
+ * NAME curl_slist_free_all()
+ *
+ * DESCRIPTION
+ *
+ * free a previously built curl_slist.
+ */
+CURL_EXTERN void curl_slist_free_all(struct curl_slist *);
+
+/*
+ * NAME curl_getdate()
+ *
+ * DESCRIPTION
+ *
+ * Returns the time, in seconds since 1 Jan 1970 of the time string given in
+ * the first argument. The time argument in the second parameter is unused
+ * and should be set to NULL.
+ */
+CURL_EXTERN time_t curl_getdate(const char *p, const time_t *unused);
+
+/* info about the certificate chain, only for OpenSSL builds. Asked
+ for with CURLOPT_CERTINFO / CURLINFO_CERTINFO */
+struct curl_certinfo {
+ int num_of_certs; /* number of certificates with information */
+ struct curl_slist **certinfo; /* for each index in this array, there's a
+ linked list with textual information in the
+ format "name: value" */
+};
+
+/* Information about the SSL library used and the respective internal SSL
+ handle, which can be used to obtain further information regarding the
+ connection. Asked for with CURLINFO_TLS_SSL_PTR or CURLINFO_TLS_SESSION. */
+struct curl_tlssessioninfo {
+ curl_sslbackend backend;
+ void *internals;
+};
+
+#define CURLINFO_STRING 0x100000
+#define CURLINFO_LONG 0x200000
+#define CURLINFO_DOUBLE 0x300000
+#define CURLINFO_SLIST 0x400000
+#define CURLINFO_PTR 0x400000 /* same as SLIST */
+#define CURLINFO_SOCKET 0x500000
+#define CURLINFO_OFF_T 0x600000
+#define CURLINFO_MASK 0x0fffff
+#define CURLINFO_TYPEMASK 0xf00000
+
+typedef enum {
+ CURLINFO_NONE, /* first, never use this */
+ CURLINFO_EFFECTIVE_URL = CURLINFO_STRING + 1,
+ CURLINFO_RESPONSE_CODE = CURLINFO_LONG + 2,
+ CURLINFO_TOTAL_TIME = CURLINFO_DOUBLE + 3,
+ CURLINFO_NAMELOOKUP_TIME = CURLINFO_DOUBLE + 4,
+ CURLINFO_CONNECT_TIME = CURLINFO_DOUBLE + 5,
+ CURLINFO_PRETRANSFER_TIME = CURLINFO_DOUBLE + 6,
+ CURLINFO_SIZE_UPLOAD = CURLINFO_DOUBLE + 7,
+ CURLINFO_SIZE_UPLOAD_T = CURLINFO_OFF_T + 7,
+ CURLINFO_SIZE_DOWNLOAD = CURLINFO_DOUBLE + 8,
+ CURLINFO_SIZE_DOWNLOAD_T = CURLINFO_OFF_T + 8,
+ CURLINFO_SPEED_DOWNLOAD = CURLINFO_DOUBLE + 9,
+ CURLINFO_SPEED_DOWNLOAD_T = CURLINFO_OFF_T + 9,
+ CURLINFO_SPEED_UPLOAD = CURLINFO_DOUBLE + 10,
+ CURLINFO_SPEED_UPLOAD_T = CURLINFO_OFF_T + 10,
+ CURLINFO_HEADER_SIZE = CURLINFO_LONG + 11,
+ CURLINFO_REQUEST_SIZE = CURLINFO_LONG + 12,
+ CURLINFO_SSL_VERIFYRESULT = CURLINFO_LONG + 13,
+ CURLINFO_FILETIME = CURLINFO_LONG + 14,
+ CURLINFO_FILETIME_T = CURLINFO_OFF_T + 14,
+ CURLINFO_CONTENT_LENGTH_DOWNLOAD = CURLINFO_DOUBLE + 15,
+ CURLINFO_CONTENT_LENGTH_DOWNLOAD_T = CURLINFO_OFF_T + 15,
+ CURLINFO_CONTENT_LENGTH_UPLOAD = CURLINFO_DOUBLE + 16,
+ CURLINFO_CONTENT_LENGTH_UPLOAD_T = CURLINFO_OFF_T + 16,
+ CURLINFO_STARTTRANSFER_TIME = CURLINFO_DOUBLE + 17,
+ CURLINFO_CONTENT_TYPE = CURLINFO_STRING + 18,
+ CURLINFO_REDIRECT_TIME = CURLINFO_DOUBLE + 19,
+ CURLINFO_REDIRECT_COUNT = CURLINFO_LONG + 20,
+ CURLINFO_PRIVATE = CURLINFO_STRING + 21,
+ CURLINFO_HTTP_CONNECTCODE = CURLINFO_LONG + 22,
+ CURLINFO_HTTPAUTH_AVAIL = CURLINFO_LONG + 23,
+ CURLINFO_PROXYAUTH_AVAIL = CURLINFO_LONG + 24,
+ CURLINFO_OS_ERRNO = CURLINFO_LONG + 25,
+ CURLINFO_NUM_CONNECTS = CURLINFO_LONG + 26,
+ CURLINFO_SSL_ENGINES = CURLINFO_SLIST + 27,
+ CURLINFO_COOKIELIST = CURLINFO_SLIST + 28,
+ CURLINFO_LASTSOCKET = CURLINFO_LONG + 29,
+ CURLINFO_FTP_ENTRY_PATH = CURLINFO_STRING + 30,
+ CURLINFO_REDIRECT_URL = CURLINFO_STRING + 31,
+ CURLINFO_PRIMARY_IP = CURLINFO_STRING + 32,
+ CURLINFO_APPCONNECT_TIME = CURLINFO_DOUBLE + 33,
+ CURLINFO_CERTINFO = CURLINFO_PTR + 34,
+ CURLINFO_CONDITION_UNMET = CURLINFO_LONG + 35,
+ CURLINFO_RTSP_SESSION_ID = CURLINFO_STRING + 36,
+ CURLINFO_RTSP_CLIENT_CSEQ = CURLINFO_LONG + 37,
+ CURLINFO_RTSP_SERVER_CSEQ = CURLINFO_LONG + 38,
+ CURLINFO_RTSP_CSEQ_RECV = CURLINFO_LONG + 39,
+ CURLINFO_PRIMARY_PORT = CURLINFO_LONG + 40,
+ CURLINFO_LOCAL_IP = CURLINFO_STRING + 41,
+ CURLINFO_LOCAL_PORT = CURLINFO_LONG + 42,
+ CURLINFO_TLS_SESSION = CURLINFO_PTR + 43,
+ CURLINFO_ACTIVESOCKET = CURLINFO_SOCKET + 44,
+ CURLINFO_TLS_SSL_PTR = CURLINFO_PTR + 45,
+ CURLINFO_HTTP_VERSION = CURLINFO_LONG + 46,
+ CURLINFO_PROXY_SSL_VERIFYRESULT = CURLINFO_LONG + 47,
+ CURLINFO_PROTOCOL = CURLINFO_LONG + 48,
+ CURLINFO_SCHEME = CURLINFO_STRING + 49,
+ /* Fill in new entries below here! */
+
+ /* Preferably these would be defined conditionally based on the
+ sizeof curl_off_t being 64-bits */
+ CURLINFO_TOTAL_TIME_T = CURLINFO_OFF_T + 50,
+ CURLINFO_NAMELOOKUP_TIME_T = CURLINFO_OFF_T + 51,
+ CURLINFO_CONNECT_TIME_T = CURLINFO_OFF_T + 52,
+ CURLINFO_PRETRANSFER_TIME_T = CURLINFO_OFF_T + 53,
+ CURLINFO_STARTTRANSFER_TIME_T = CURLINFO_OFF_T + 54,
+ CURLINFO_REDIRECT_TIME_T = CURLINFO_OFF_T + 55,
+ CURLINFO_APPCONNECT_TIME_T = CURLINFO_OFF_T + 56,
+
+ CURLINFO_LASTONE = 56
+} CURLINFO;
+
+/* CURLINFO_RESPONSE_CODE is the new name for the option previously known as
+ CURLINFO_HTTP_CODE */
+#define CURLINFO_HTTP_CODE CURLINFO_RESPONSE_CODE
+
+typedef enum {
+ CURLCLOSEPOLICY_NONE, /* first, never use this */
+
+ CURLCLOSEPOLICY_OLDEST,
+ CURLCLOSEPOLICY_LEAST_RECENTLY_USED,
+ CURLCLOSEPOLICY_LEAST_TRAFFIC,
+ CURLCLOSEPOLICY_SLOWEST,
+ CURLCLOSEPOLICY_CALLBACK,
+
+ CURLCLOSEPOLICY_LAST /* last, never use this */
+} curl_closepolicy;
+
+#define CURL_GLOBAL_SSL (1<<0) /* no purpose since since 7.57.0 */
+#define CURL_GLOBAL_WIN32 (1<<1)
+#define CURL_GLOBAL_ALL (CURL_GLOBAL_SSL|CURL_GLOBAL_WIN32)
+#define CURL_GLOBAL_NOTHING 0
+#define CURL_GLOBAL_DEFAULT CURL_GLOBAL_ALL
+#define CURL_GLOBAL_ACK_EINTR (1<<2)
+
+
+/*****************************************************************************
+ * Setup defines, protos etc for the sharing stuff.
+ */
+
+/* Different data locks for a single share */
+typedef enum {
+ CURL_LOCK_DATA_NONE = 0,
+ /* CURL_LOCK_DATA_SHARE is used internally to say that
+ * the locking is just made to change the internal state of the share
+ * itself.
+ */
+ CURL_LOCK_DATA_SHARE,
+ CURL_LOCK_DATA_COOKIE,
+ CURL_LOCK_DATA_DNS,
+ CURL_LOCK_DATA_SSL_SESSION,
+ CURL_LOCK_DATA_CONNECT,
+ CURL_LOCK_DATA_PSL,
+ CURL_LOCK_DATA_LAST
+} curl_lock_data;
+
+/* Different lock access types */
+typedef enum {
+ CURL_LOCK_ACCESS_NONE = 0, /* unspecified action */
+ CURL_LOCK_ACCESS_SHARED = 1, /* for read perhaps */
+ CURL_LOCK_ACCESS_SINGLE = 2, /* for write perhaps */
+ CURL_LOCK_ACCESS_LAST /* never use */
+} curl_lock_access;
+
+typedef void (*curl_lock_function)(CURL *handle,
+ curl_lock_data data,
+ curl_lock_access locktype,
+ void *userptr);
+typedef void (*curl_unlock_function)(CURL *handle,
+ curl_lock_data data,
+ void *userptr);
+
+
+typedef enum {
+ CURLSHE_OK, /* all is fine */
+ CURLSHE_BAD_OPTION, /* 1 */
+ CURLSHE_IN_USE, /* 2 */
+ CURLSHE_INVALID, /* 3 */
+ CURLSHE_NOMEM, /* 4 out of memory */
+ CURLSHE_NOT_BUILT_IN, /* 5 feature not present in lib */
+ CURLSHE_LAST /* never use */
+} CURLSHcode;
+
+typedef enum {
+ CURLSHOPT_NONE, /* don't use */
+ CURLSHOPT_SHARE, /* specify a data type to share */
+ CURLSHOPT_UNSHARE, /* specify which data type to stop sharing */
+ CURLSHOPT_LOCKFUNC, /* pass in a 'curl_lock_function' pointer */
+ CURLSHOPT_UNLOCKFUNC, /* pass in a 'curl_unlock_function' pointer */
+ CURLSHOPT_USERDATA, /* pass in a user data pointer used in the lock/unlock
+ callback functions */
+ CURLSHOPT_LAST /* never use */
+} CURLSHoption;
+
+CURL_EXTERN CURLSH *curl_share_init(void);
+CURL_EXTERN CURLSHcode curl_share_setopt(CURLSH *, CURLSHoption option, ...);
+CURL_EXTERN CURLSHcode curl_share_cleanup(CURLSH *);
+
+/****************************************************************************
+ * Structures for querying information about the curl library at runtime.
+ */
+
+typedef enum {
+ CURLVERSION_FIRST,
+ CURLVERSION_SECOND,
+ CURLVERSION_THIRD,
+ CURLVERSION_FOURTH,
+ CURLVERSION_FIFTH,
+ CURLVERSION_LAST /* never actually use this */
+} CURLversion;
+
+/* The 'CURLVERSION_NOW' is the symbolic name meant to be used by
+ basically all programs ever that want to get version information. It is
+ meant to be a built-in version number for what kind of struct the caller
+ expects. If the struct ever changes, we redefine the NOW to another enum
+ from above. */
+#define CURLVERSION_NOW CURLVERSION_FIFTH
+
+typedef struct {
+ CURLversion age; /* age of the returned struct */
+ const char *version; /* LIBCURL_VERSION */
+ unsigned int version_num; /* LIBCURL_VERSION_NUM */
+ const char *host; /* OS/host/cpu/machine when configured */
+ int features; /* bitmask, see defines below */
+ const char *ssl_version; /* human readable string */
+ long ssl_version_num; /* not used anymore, always 0 */
+ const char *libz_version; /* human readable string */
+ /* protocols is terminated by an entry with a NULL protoname */
+ const char * const *protocols;
+
+ /* The fields below this were added in CURLVERSION_SECOND */
+ const char *ares;
+ int ares_num;
+
+ /* This field was added in CURLVERSION_THIRD */
+ const char *libidn;
+
+ /* These field were added in CURLVERSION_FOURTH */
+
+ /* Same as '_libiconv_version' if built with HAVE_ICONV */
+ int iconv_ver_num;
+
+ const char *libssh_version; /* human readable string */
+
+ /* These fields were added in CURLVERSION_FIFTH */
+
+ unsigned int brotli_ver_num; /* Numeric Brotli version
+ (MAJOR << 24) | (MINOR << 12) | PATCH */
+ const char *brotli_version; /* human readable string. */
+
+} curl_version_info_data;
+
+#define CURL_VERSION_IPV6 (1<<0) /* IPv6-enabled */
+#define CURL_VERSION_KERBEROS4 (1<<1) /* Kerberos V4 auth is supported
+ (deprecated) */
+#define CURL_VERSION_SSL (1<<2) /* SSL options are present */
+#define CURL_VERSION_LIBZ (1<<3) /* libz features are present */
+#define CURL_VERSION_NTLM (1<<4) /* NTLM auth is supported */
+#define CURL_VERSION_GSSNEGOTIATE (1<<5) /* Negotiate auth is supported
+ (deprecated) */
+#define CURL_VERSION_DEBUG (1<<6) /* Built with debug capabilities */
+#define CURL_VERSION_ASYNCHDNS (1<<7) /* Asynchronous DNS resolves */
+#define CURL_VERSION_SPNEGO (1<<8) /* SPNEGO auth is supported */
+#define CURL_VERSION_LARGEFILE (1<<9) /* Supports files larger than 2GB */
+#define CURL_VERSION_IDN (1<<10) /* Internationized Domain Names are
+ supported */
+#define CURL_VERSION_SSPI (1<<11) /* Built against Windows SSPI */
+#define CURL_VERSION_CONV (1<<12) /* Character conversions supported */
+#define CURL_VERSION_CURLDEBUG (1<<13) /* Debug memory tracking supported */
+#define CURL_VERSION_TLSAUTH_SRP (1<<14) /* TLS-SRP auth is supported */
+#define CURL_VERSION_NTLM_WB (1<<15) /* NTLM delegation to winbind helper
+ is supported */
+#define CURL_VERSION_HTTP2 (1<<16) /* HTTP2 support built-in */
+#define CURL_VERSION_GSSAPI (1<<17) /* Built against a GSS-API library */
+#define CURL_VERSION_KERBEROS5 (1<<18) /* Kerberos V5 auth is supported */
+#define CURL_VERSION_UNIX_SOCKETS (1<<19) /* Unix domain sockets support */
+#define CURL_VERSION_PSL (1<<20) /* Mozilla's Public Suffix List, used
+ for cookie domain verification */
+#define CURL_VERSION_HTTPS_PROXY (1<<21) /* HTTPS-proxy support built-in */
+#define CURL_VERSION_MULTI_SSL (1<<22) /* Multiple SSL backends available */
+#define CURL_VERSION_BROTLI (1<<23) /* Brotli features are present. */
+#define CURL_VERSION_ALTSVC (1<<24) /* Alt-Svc handling built-in */
+
+ /*
+ * NAME curl_version_info()
+ *
+ * DESCRIPTION
+ *
+ * This function returns a pointer to a static copy of the version info
+ * struct. See above.
+ */
+CURL_EXTERN curl_version_info_data *curl_version_info(CURLversion);
+
+/*
+ * NAME curl_easy_strerror()
+ *
+ * DESCRIPTION
+ *
+ * The curl_easy_strerror function may be used to turn a CURLcode value
+ * into the equivalent human readable error string. This is useful
+ * for printing meaningful error messages.
+ */
+CURL_EXTERN const char *curl_easy_strerror(CURLcode);
+
+/*
+ * NAME curl_share_strerror()
+ *
+ * DESCRIPTION
+ *
+ * The curl_share_strerror function may be used to turn a CURLSHcode value
+ * into the equivalent human readable error string. This is useful
+ * for printing meaningful error messages.
+ */
+CURL_EXTERN const char *curl_share_strerror(CURLSHcode);
+
+/*
+ * NAME curl_easy_pause()
+ *
+ * DESCRIPTION
+ *
+ * The curl_easy_pause function pauses or unpauses transfers. Select the new
+ * state by setting the bitmask, use the convenience defines below.
+ *
+ */
+CURL_EXTERN CURLcode curl_easy_pause(CURL *handle, int bitmask);
+
+#define CURLPAUSE_RECV (1<<0)
+#define CURLPAUSE_RECV_CONT (0)
+
+#define CURLPAUSE_SEND (1<<2)
+#define CURLPAUSE_SEND_CONT (0)
+
+#define CURLPAUSE_ALL (CURLPAUSE_RECV|CURLPAUSE_SEND)
+#define CURLPAUSE_CONT (CURLPAUSE_RECV_CONT|CURLPAUSE_SEND_CONT)
+
+#ifdef __cplusplus
+}
+#endif
+
+/* unfortunately, the easy.h and multi.h include files need options and info
+ stuff before they can be included! */
+#include "easy.h" /* nothing in curl is fun without the easy stuff */
+#include "multi.h"
+#include "urlapi.h"
+
+/* the typechecker doesn't work in C++ (yet) */
+#if defined(__GNUC__) && defined(__GNUC_MINOR__) && \
+ ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)) && \
+ !defined(__cplusplus) && !defined(CURL_DISABLE_TYPECHECK)
+#include "typecheck-gcc.h"
+#else
+#if defined(__STDC__) && (__STDC__ >= 1)
+/* This preprocessor magic that replaces a call with the exact same call is
+ only done to make sure application authors pass exactly three arguments
+ to these functions. */
+#define curl_easy_setopt(handle,opt,param) curl_easy_setopt(handle,opt,param)
+#define curl_easy_getinfo(handle,info,arg) curl_easy_getinfo(handle,info,arg)
+#define curl_share_setopt(share,opt,param) curl_share_setopt(share,opt,param)
+#define curl_multi_setopt(handle,opt,param) curl_multi_setopt(handle,opt,param)
+#endif /* __STDC__ >= 1 */
+#endif /* gcc >= 4.3 && !__cplusplus */
+
+#endif /* __CURL_CURL_H */
diff --git a/toolkit/crashreporter/google-breakpad/src/third_party/curl/curlver.h b/toolkit/crashreporter/google-breakpad/src/third_party/curl/curlver.h
new file mode 100644
index 0000000000..479cd8e6cd
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/third_party/curl/curlver.h
@@ -0,0 +1,77 @@
+#ifndef __CURL_CURLVER_H
+#define __CURL_CURLVER_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/* This header file contains nothing but libcurl version info, generated by
+ a script at release-time. This was made its own header file in 7.11.2 */
+
+/* This is the global package copyright */
+#define LIBCURL_COPYRIGHT "1996 - 2019 Daniel Stenberg, <daniel@haxx.se>."
+
+/* This is the version number of the libcurl package from which this header
+ file origins: */
+#define LIBCURL_VERSION "7.64.1-DEV"
+
+/* The numeric version number is also available "in parts" by using these
+ defines: */
+#define LIBCURL_VERSION_MAJOR 7
+#define LIBCURL_VERSION_MINOR 64
+#define LIBCURL_VERSION_PATCH 1
+
+/* This is the numeric version of the libcurl version number, meant for easier
+ parsing and comparions by programs. The LIBCURL_VERSION_NUM define will
+ always follow this syntax:
+
+ 0xXXYYZZ
+
+ Where XX, YY and ZZ are the main version, release and patch numbers in
+ hexadecimal (using 8 bits each). All three numbers are always represented
+ using two digits. 1.2 would appear as "0x010200" while version 9.11.7
+ appears as "0x090b07".
+
+ This 6-digit (24 bits) hexadecimal number does not show pre-release number,
+ and it is always a greater number in a more recent release. It makes
+ comparisons with greater than and less than work.
+
+ Note: This define is the full hex number and _does not_ use the
+ CURL_VERSION_BITS() macro since curl's own configure script greps for it
+ and needs it to contain the full number.
+*/
+#define LIBCURL_VERSION_NUM 0x074001
+
+/*
+ * This is the date and time when the full source package was created. The
+ * timestamp is not stored in git, as the timestamp is properly set in the
+ * tarballs by the maketgz script.
+ *
+ * The format of the date follows this template:
+ *
+ * "2007-11-23"
+ */
+#define LIBCURL_TIMESTAMP "[unreleased]"
+
+#define CURL_VERSION_BITS(x,y,z) ((x)<<16|(y)<<8|z)
+#define CURL_AT_LEAST_VERSION(x,y,z) \
+ (LIBCURL_VERSION_NUM >= CURL_VERSION_BITS(x, y, z))
+
+#endif /* __CURL_CURLVER_H */
diff --git a/toolkit/crashreporter/google-breakpad/src/third_party/curl/easy.h b/toolkit/crashreporter/google-breakpad/src/third_party/curl/easy.h
new file mode 100644
index 0000000000..f42a8a9692
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/third_party/curl/easy.h
@@ -0,0 +1,112 @@
+#ifndef __CURL_EASY_H
+#define __CURL_EASY_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+CURL_EXTERN CURL *curl_easy_init(void);
+CURL_EXTERN CURLcode curl_easy_setopt(CURL *curl, CURLoption option, ...);
+CURL_EXTERN CURLcode curl_easy_perform(CURL *curl);
+CURL_EXTERN void curl_easy_cleanup(CURL *curl);
+
+/*
+ * NAME curl_easy_getinfo()
+ *
+ * DESCRIPTION
+ *
+ * Request internal information from the curl session with this function. The
+ * third argument MUST be a pointer to a long, a pointer to a char * or a
+ * pointer to a double (as the documentation describes elsewhere). The data
+ * pointed to will be filled in accordingly and can be relied upon only if the
+ * function returns CURLE_OK. This function is intended to get used *AFTER* a
+ * performed transfer, all results from this function are undefined until the
+ * transfer is completed.
+ */
+CURL_EXTERN CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ...);
+
+
+/*
+ * NAME curl_easy_duphandle()
+ *
+ * DESCRIPTION
+ *
+ * Creates a new curl session handle with the same options set for the handle
+ * passed in. Duplicating a handle could only be a matter of cloning data and
+ * options, internal state info and things like persistent connections cannot
+ * be transferred. It is useful in multithreaded applications when you can run
+ * curl_easy_duphandle() for each new thread to avoid a series of identical
+ * curl_easy_setopt() invokes in every thread.
+ */
+CURL_EXTERN CURL *curl_easy_duphandle(CURL *curl);
+
+/*
+ * NAME curl_easy_reset()
+ *
+ * DESCRIPTION
+ *
+ * Re-initializes a CURL handle to the default values. This puts back the
+ * handle to the same state as it was in when it was just created.
+ *
+ * It does keep: live connections, the Session ID cache, the DNS cache and the
+ * cookies.
+ */
+CURL_EXTERN void curl_easy_reset(CURL *curl);
+
+/*
+ * NAME curl_easy_recv()
+ *
+ * DESCRIPTION
+ *
+ * Receives data from the connected socket. Use after successful
+ * curl_easy_perform() with CURLOPT_CONNECT_ONLY option.
+ */
+CURL_EXTERN CURLcode curl_easy_recv(CURL *curl, void *buffer, size_t buflen,
+ size_t *n);
+
+/*
+ * NAME curl_easy_send()
+ *
+ * DESCRIPTION
+ *
+ * Sends data over the connected socket. Use after successful
+ * curl_easy_perform() with CURLOPT_CONNECT_ONLY option.
+ */
+CURL_EXTERN CURLcode curl_easy_send(CURL *curl, const void *buffer,
+ size_t buflen, size_t *n);
+
+
+/*
+ * NAME curl_easy_upkeep()
+ *
+ * DESCRIPTION
+ *
+ * Performs connection upkeep for the given session handle.
+ */
+CURL_EXTERN CURLcode curl_easy_upkeep(CURL *curl);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/toolkit/crashreporter/google-breakpad/src/third_party/curl/multi.h b/toolkit/crashreporter/google-breakpad/src/third_party/curl/multi.h
new file mode 100644
index 0000000000..b19dbaf791
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/third_party/curl/multi.h
@@ -0,0 +1,441 @@
+#ifndef __CURL_MULTI_H
+#define __CURL_MULTI_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+/*
+ This is an "external" header file. Don't give away any internals here!
+
+ GOALS
+
+ o Enable a "pull" interface. The application that uses libcurl decides where
+ and when to ask libcurl to get/send data.
+
+ o Enable multiple simultaneous transfers in the same thread without making it
+ complicated for the application.
+
+ o Enable the application to select() on its own file descriptors and curl's
+ file descriptors simultaneous easily.
+
+*/
+
+/*
+ * This header file should not really need to include "curl.h" since curl.h
+ * itself includes this file and we expect user applications to do #include
+ * <curl/curl.h> without the need for especially including multi.h.
+ *
+ * For some reason we added this include here at one point, and rather than to
+ * break existing (wrongly written) libcurl applications, we leave it as-is
+ * but with this warning attached.
+ */
+#include "curl.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined(BUILDING_LIBCURL) || defined(CURL_STRICTER)
+typedef struct Curl_multi CURLM;
+#else
+typedef void CURLM;
+#endif
+
+typedef enum {
+ CURLM_CALL_MULTI_PERFORM = -1, /* please call curl_multi_perform() or
+ curl_multi_socket*() soon */
+ CURLM_OK,
+ CURLM_BAD_HANDLE, /* the passed-in handle is not a valid CURLM handle */
+ CURLM_BAD_EASY_HANDLE, /* an easy handle was not good/valid */
+ CURLM_OUT_OF_MEMORY, /* if you ever get this, you're in deep sh*t */
+ CURLM_INTERNAL_ERROR, /* this is a libcurl bug */
+ CURLM_BAD_SOCKET, /* the passed in socket argument did not match */
+ CURLM_UNKNOWN_OPTION, /* curl_multi_setopt() with unsupported option */
+ CURLM_ADDED_ALREADY, /* an easy handle already added to a multi handle was
+ attempted to get added - again */
+ CURLM_RECURSIVE_API_CALL, /* an api function was called from inside a
+ callback */
+ CURLM_LAST
+} CURLMcode;
+
+/* just to make code nicer when using curl_multi_socket() you can now check
+ for CURLM_CALL_MULTI_SOCKET too in the same style it works for
+ curl_multi_perform() and CURLM_CALL_MULTI_PERFORM */
+#define CURLM_CALL_MULTI_SOCKET CURLM_CALL_MULTI_PERFORM
+
+/* bitmask bits for CURLMOPT_PIPELINING */
+#define CURLPIPE_NOTHING 0L
+#define CURLPIPE_HTTP1 1L
+#define CURLPIPE_MULTIPLEX 2L
+
+typedef enum {
+ CURLMSG_NONE, /* first, not used */
+ CURLMSG_DONE, /* This easy handle has completed. 'result' contains
+ the CURLcode of the transfer */
+ CURLMSG_LAST /* last, not used */
+} CURLMSG;
+
+struct CURLMsg {
+ CURLMSG msg; /* what this message means */
+ CURL *easy_handle; /* the handle it concerns */
+ union {
+ void *whatever; /* message-specific data */
+ CURLcode result; /* return code for transfer */
+ } data;
+};
+typedef struct CURLMsg CURLMsg;
+
+/* Based on poll(2) structure and values.
+ * We don't use pollfd and POLL* constants explicitly
+ * to cover platforms without poll(). */
+#define CURL_WAIT_POLLIN 0x0001
+#define CURL_WAIT_POLLPRI 0x0002
+#define CURL_WAIT_POLLOUT 0x0004
+
+struct curl_waitfd {
+ curl_socket_t fd;
+ short events;
+ short revents; /* not supported yet */
+};
+
+/*
+ * Name: curl_multi_init()
+ *
+ * Desc: inititalize multi-style curl usage
+ *
+ * Returns: a new CURLM handle to use in all 'curl_multi' functions.
+ */
+CURL_EXTERN CURLM *curl_multi_init(void);
+
+/*
+ * Name: curl_multi_add_handle()
+ *
+ * Desc: add a standard curl handle to the multi stack
+ *
+ * Returns: CURLMcode type, general multi error code.
+ */
+CURL_EXTERN CURLMcode curl_multi_add_handle(CURLM *multi_handle,
+ CURL *curl_handle);
+
+ /*
+ * Name: curl_multi_remove_handle()
+ *
+ * Desc: removes a curl handle from the multi stack again
+ *
+ * Returns: CURLMcode type, general multi error code.
+ */
+CURL_EXTERN CURLMcode curl_multi_remove_handle(CURLM *multi_handle,
+ CURL *curl_handle);
+
+ /*
+ * Name: curl_multi_fdset()
+ *
+ * Desc: Ask curl for its fd_set sets. The app can use these to select() or
+ * poll() on. We want curl_multi_perform() called as soon as one of
+ * them are ready.
+ *
+ * Returns: CURLMcode type, general multi error code.
+ */
+CURL_EXTERN CURLMcode curl_multi_fdset(CURLM *multi_handle,
+ fd_set *read_fd_set,
+ fd_set *write_fd_set,
+ fd_set *exc_fd_set,
+ int *max_fd);
+
+/*
+ * Name: curl_multi_wait()
+ *
+ * Desc: Poll on all fds within a CURLM set as well as any
+ * additional fds passed to the function.
+ *
+ * Returns: CURLMcode type, general multi error code.
+ */
+CURL_EXTERN CURLMcode curl_multi_wait(CURLM *multi_handle,
+ struct curl_waitfd extra_fds[],
+ unsigned int extra_nfds,
+ int timeout_ms,
+ int *ret);
+
+ /*
+ * Name: curl_multi_perform()
+ *
+ * Desc: When the app thinks there's data available for curl it calls this
+ * function to read/write whatever there is right now. This returns
+ * as soon as the reads and writes are done. This function does not
+ * require that there actually is data available for reading or that
+ * data can be written, it can be called just in case. It returns
+ * the number of handles that still transfer data in the second
+ * argument's integer-pointer.
+ *
+ * Returns: CURLMcode type, general multi error code. *NOTE* that this only
+ * returns errors etc regarding the whole multi stack. There might
+ * still have occurred problems on individual transfers even when
+ * this returns OK.
+ */
+CURL_EXTERN CURLMcode curl_multi_perform(CURLM *multi_handle,
+ int *running_handles);
+
+ /*
+ * Name: curl_multi_cleanup()
+ *
+ * Desc: Cleans up and removes a whole multi stack. It does not free or
+ * touch any individual easy handles in any way. We need to define
+ * in what state those handles will be if this function is called
+ * in the middle of a transfer.
+ *
+ * Returns: CURLMcode type, general multi error code.
+ */
+CURL_EXTERN CURLMcode curl_multi_cleanup(CURLM *multi_handle);
+
+/*
+ * Name: curl_multi_info_read()
+ *
+ * Desc: Ask the multi handle if there's any messages/informationals from
+ * the individual transfers. Messages include informationals such as
+ * error code from the transfer or just the fact that a transfer is
+ * completed. More details on these should be written down as well.
+ *
+ * Repeated calls to this function will return a new struct each
+ * time, until a special "end of msgs" struct is returned as a signal
+ * that there is no more to get at this point.
+ *
+ * The data the returned pointer points to will not survive calling
+ * curl_multi_cleanup().
+ *
+ * The 'CURLMsg' struct is meant to be very simple and only contain
+ * very basic information. If more involved information is wanted,
+ * we will provide the particular "transfer handle" in that struct
+ * and that should/could/would be used in subsequent
+ * curl_easy_getinfo() calls (or similar). The point being that we
+ * must never expose complex structs to applications, as then we'll
+ * undoubtably get backwards compatibility problems in the future.
+ *
+ * Returns: A pointer to a filled-in struct, or NULL if it failed or ran out
+ * of structs. It also writes the number of messages left in the
+ * queue (after this read) in the integer the second argument points
+ * to.
+ */
+CURL_EXTERN CURLMsg *curl_multi_info_read(CURLM *multi_handle,
+ int *msgs_in_queue);
+
+/*
+ * Name: curl_multi_strerror()
+ *
+ * Desc: The curl_multi_strerror function may be used to turn a CURLMcode
+ * value into the equivalent human readable error string. This is
+ * useful for printing meaningful error messages.
+ *
+ * Returns: A pointer to a zero-terminated error message.
+ */
+CURL_EXTERN const char *curl_multi_strerror(CURLMcode);
+
+/*
+ * Name: curl_multi_socket() and
+ * curl_multi_socket_all()
+ *
+ * Desc: An alternative version of curl_multi_perform() that allows the
+ * application to pass in one of the file descriptors that have been
+ * detected to have "action" on them and let libcurl perform.
+ * See man page for details.
+ */
+#define CURL_POLL_NONE 0
+#define CURL_POLL_IN 1
+#define CURL_POLL_OUT 2
+#define CURL_POLL_INOUT 3
+#define CURL_POLL_REMOVE 4
+
+#define CURL_SOCKET_TIMEOUT CURL_SOCKET_BAD
+
+#define CURL_CSELECT_IN 0x01
+#define CURL_CSELECT_OUT 0x02
+#define CURL_CSELECT_ERR 0x04
+
+typedef int (*curl_socket_callback)(CURL *easy, /* easy handle */
+ curl_socket_t s, /* socket */
+ int what, /* see above */
+ void *userp, /* private callback
+ pointer */
+ void *socketp); /* private socket
+ pointer */
+/*
+ * Name: curl_multi_timer_callback
+ *
+ * Desc: Called by libcurl whenever the library detects a change in the
+ * maximum number of milliseconds the app is allowed to wait before
+ * curl_multi_socket() or curl_multi_perform() must be called
+ * (to allow libcurl's timed events to take place).
+ *
+ * Returns: The callback should return zero.
+ */
+typedef int (*curl_multi_timer_callback)(CURLM *multi, /* multi handle */
+ long timeout_ms, /* see above */
+ void *userp); /* private callback
+ pointer */
+
+CURL_EXTERN CURLMcode curl_multi_socket(CURLM *multi_handle, curl_socket_t s,
+ int *running_handles);
+
+CURL_EXTERN CURLMcode curl_multi_socket_action(CURLM *multi_handle,
+ curl_socket_t s,
+ int ev_bitmask,
+ int *running_handles);
+
+CURL_EXTERN CURLMcode curl_multi_socket_all(CURLM *multi_handle,
+ int *running_handles);
+
+#ifndef CURL_ALLOW_OLD_MULTI_SOCKET
+/* This macro below was added in 7.16.3 to push users who recompile to use
+ the new curl_multi_socket_action() instead of the old curl_multi_socket()
+*/
+#define curl_multi_socket(x,y,z) curl_multi_socket_action(x,y,0,z)
+#endif
+
+/*
+ * Name: curl_multi_timeout()
+ *
+ * Desc: Returns the maximum number of milliseconds the app is allowed to
+ * wait before curl_multi_socket() or curl_multi_perform() must be
+ * called (to allow libcurl's timed events to take place).
+ *
+ * Returns: CURLM error code.
+ */
+CURL_EXTERN CURLMcode curl_multi_timeout(CURLM *multi_handle,
+ long *milliseconds);
+
+#undef CINIT /* re-using the same name as in curl.h */
+
+#ifdef CURL_ISOCPP
+#define CINIT(name,type,num) CURLMOPT_ ## name = CURLOPTTYPE_ ## type + num
+#else
+/* The macro "##" is ISO C, we assume pre-ISO C doesn't support it. */
+#define LONG CURLOPTTYPE_LONG
+#define OBJECTPOINT CURLOPTTYPE_OBJECTPOINT
+#define FUNCTIONPOINT CURLOPTTYPE_FUNCTIONPOINT
+#define OFF_T CURLOPTTYPE_OFF_T
+#define CINIT(name,type,number) CURLMOPT_/**/name = type + number
+#endif
+
+typedef enum {
+ /* This is the socket callback function pointer */
+ CINIT(SOCKETFUNCTION, FUNCTIONPOINT, 1),
+
+ /* This is the argument passed to the socket callback */
+ CINIT(SOCKETDATA, OBJECTPOINT, 2),
+
+ /* set to 1 to enable pipelining for this multi handle */
+ CINIT(PIPELINING, LONG, 3),
+
+ /* This is the timer callback function pointer */
+ CINIT(TIMERFUNCTION, FUNCTIONPOINT, 4),
+
+ /* This is the argument passed to the timer callback */
+ CINIT(TIMERDATA, OBJECTPOINT, 5),
+
+ /* maximum number of entries in the connection cache */
+ CINIT(MAXCONNECTS, LONG, 6),
+
+ /* maximum number of (pipelining) connections to one host */
+ CINIT(MAX_HOST_CONNECTIONS, LONG, 7),
+
+ /* maximum number of requests in a pipeline */
+ CINIT(MAX_PIPELINE_LENGTH, LONG, 8),
+
+ /* a connection with a content-length longer than this
+ will not be considered for pipelining */
+ CINIT(CONTENT_LENGTH_PENALTY_SIZE, OFF_T, 9),
+
+ /* a connection with a chunk length longer than this
+ will not be considered for pipelining */
+ CINIT(CHUNK_LENGTH_PENALTY_SIZE, OFF_T, 10),
+
+ /* a list of site names(+port) that are blacklisted from
+ pipelining */
+ CINIT(PIPELINING_SITE_BL, OBJECTPOINT, 11),
+
+ /* a list of server types that are blacklisted from
+ pipelining */
+ CINIT(PIPELINING_SERVER_BL, OBJECTPOINT, 12),
+
+ /* maximum number of open connections in total */
+ CINIT(MAX_TOTAL_CONNECTIONS, LONG, 13),
+
+ /* This is the server push callback function pointer */
+ CINIT(PUSHFUNCTION, FUNCTIONPOINT, 14),
+
+ /* This is the argument passed to the server push callback */
+ CINIT(PUSHDATA, OBJECTPOINT, 15),
+
+ CURLMOPT_LASTENTRY /* the last unused */
+} CURLMoption;
+
+
+/*
+ * Name: curl_multi_setopt()
+ *
+ * Desc: Sets options for the multi handle.
+ *
+ * Returns: CURLM error code.
+ */
+CURL_EXTERN CURLMcode curl_multi_setopt(CURLM *multi_handle,
+ CURLMoption option, ...);
+
+
+/*
+ * Name: curl_multi_assign()
+ *
+ * Desc: This function sets an association in the multi handle between the
+ * given socket and a private pointer of the application. This is
+ * (only) useful for curl_multi_socket uses.
+ *
+ * Returns: CURLM error code.
+ */
+CURL_EXTERN CURLMcode curl_multi_assign(CURLM *multi_handle,
+ curl_socket_t sockfd, void *sockp);
+
+
+/*
+ * Name: curl_push_callback
+ *
+ * Desc: This callback gets called when a new stream is being pushed by the
+ * server. It approves or denies the new stream.
+ *
+ * Returns: CURL_PUSH_OK or CURL_PUSH_DENY.
+ */
+#define CURL_PUSH_OK 0
+#define CURL_PUSH_DENY 1
+
+struct curl_pushheaders; /* forward declaration only */
+
+CURL_EXTERN char *curl_pushheader_bynum(struct curl_pushheaders *h,
+ size_t num);
+CURL_EXTERN char *curl_pushheader_byname(struct curl_pushheaders *h,
+ const char *name);
+
+typedef int (*curl_push_callback)(CURL *parent,
+ CURL *easy,
+ size_t num_headers,
+ struct curl_pushheaders *headers,
+ void *userp);
+
+#ifdef __cplusplus
+} /* end of extern "C" */
+#endif
+
+#endif
diff --git a/toolkit/crashreporter/google-breakpad/src/third_party/curl/system.h b/toolkit/crashreporter/google-breakpad/src/third_party/curl/system.h
new file mode 100644
index 0000000000..1e555ec19e
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/third_party/curl/system.h
@@ -0,0 +1,493 @@
+#ifndef __CURL_SYSTEM_H
+#define __CURL_SYSTEM_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/*
+ * Try to keep one section per platform, compiler and architecture, otherwise,
+ * if an existing section is reused for a different one and later on the
+ * original is adjusted, probably the piggybacking one can be adversely
+ * changed.
+ *
+ * In order to differentiate between platforms/compilers/architectures use
+ * only compiler built in predefined preprocessor symbols.
+ *
+ * curl_off_t
+ * ----------
+ *
+ * For any given platform/compiler curl_off_t must be typedef'ed to a 64-bit
+ * wide signed integral data type. The width of this data type must remain
+ * constant and independent of any possible large file support settings.
+ *
+ * As an exception to the above, curl_off_t shall be typedef'ed to a 32-bit
+ * wide signed integral data type if there is no 64-bit type.
+ *
+ * As a general rule, curl_off_t shall not be mapped to off_t. This rule shall
+ * only be violated if off_t is the only 64-bit data type available and the
+ * size of off_t is independent of large file support settings. Keep your
+ * build on the safe side avoiding an off_t gating. If you have a 64-bit
+ * off_t then take for sure that another 64-bit data type exists, dig deeper
+ * and you will find it.
+ *
+ */
+
+#if defined(__DJGPP__) || defined(__GO32__)
+# if defined(__DJGPP__) && (__DJGPP__ > 1)
+# define CURL_TYPEOF_CURL_OFF_T long long
+# define CURL_FORMAT_CURL_OFF_T "lld"
+# define CURL_FORMAT_CURL_OFF_TU "llu"
+# define CURL_SUFFIX_CURL_OFF_T LL
+# define CURL_SUFFIX_CURL_OFF_TU ULL
+# else
+# define CURL_TYPEOF_CURL_OFF_T long
+# define CURL_FORMAT_CURL_OFF_T "ld"
+# define CURL_FORMAT_CURL_OFF_TU "lu"
+# define CURL_SUFFIX_CURL_OFF_T L
+# define CURL_SUFFIX_CURL_OFF_TU UL
+# endif
+# define CURL_TYPEOF_CURL_SOCKLEN_T int
+
+#elif defined(__SALFORDC__)
+# define CURL_TYPEOF_CURL_OFF_T long
+# define CURL_FORMAT_CURL_OFF_T "ld"
+# define CURL_FORMAT_CURL_OFF_TU "lu"
+# define CURL_SUFFIX_CURL_OFF_T L
+# define CURL_SUFFIX_CURL_OFF_TU UL
+# define CURL_TYPEOF_CURL_SOCKLEN_T int
+
+#elif defined(__BORLANDC__)
+# if (__BORLANDC__ < 0x520)
+# define CURL_TYPEOF_CURL_OFF_T long
+# define CURL_FORMAT_CURL_OFF_T "ld"
+# define CURL_FORMAT_CURL_OFF_TU "lu"
+# define CURL_SUFFIX_CURL_OFF_T L
+# define CURL_SUFFIX_CURL_OFF_TU UL
+# else
+# define CURL_TYPEOF_CURL_OFF_T __int64
+# define CURL_FORMAT_CURL_OFF_T "I64d"
+# define CURL_FORMAT_CURL_OFF_TU "I64u"
+# define CURL_SUFFIX_CURL_OFF_T i64
+# define CURL_SUFFIX_CURL_OFF_TU ui64
+# endif
+# define CURL_TYPEOF_CURL_SOCKLEN_T int
+
+#elif defined(__TURBOC__)
+# define CURL_TYPEOF_CURL_OFF_T long
+# define CURL_FORMAT_CURL_OFF_T "ld"
+# define CURL_FORMAT_CURL_OFF_TU "lu"
+# define CURL_SUFFIX_CURL_OFF_T L
+# define CURL_SUFFIX_CURL_OFF_TU UL
+# define CURL_TYPEOF_CURL_SOCKLEN_T int
+
+#elif defined(__WATCOMC__)
+# if defined(__386__)
+# define CURL_TYPEOF_CURL_OFF_T __int64
+# define CURL_FORMAT_CURL_OFF_T "I64d"
+# define CURL_FORMAT_CURL_OFF_TU "I64u"
+# define CURL_SUFFIX_CURL_OFF_T i64
+# define CURL_SUFFIX_CURL_OFF_TU ui64
+# else
+# define CURL_TYPEOF_CURL_OFF_T long
+# define CURL_FORMAT_CURL_OFF_T "ld"
+# define CURL_FORMAT_CURL_OFF_TU "lu"
+# define CURL_SUFFIX_CURL_OFF_T L
+# define CURL_SUFFIX_CURL_OFF_TU UL
+# endif
+# define CURL_TYPEOF_CURL_SOCKLEN_T int
+
+#elif defined(__POCC__)
+# if (__POCC__ < 280)
+# define CURL_TYPEOF_CURL_OFF_T long
+# define CURL_FORMAT_CURL_OFF_T "ld"
+# define CURL_FORMAT_CURL_OFF_TU "lu"
+# define CURL_SUFFIX_CURL_OFF_T L
+# define CURL_SUFFIX_CURL_OFF_TU UL
+# elif defined(_MSC_VER)
+# define CURL_TYPEOF_CURL_OFF_T __int64
+# define CURL_FORMAT_CURL_OFF_T "I64d"
+# define CURL_FORMAT_CURL_OFF_TU "I64u"
+# define CURL_SUFFIX_CURL_OFF_T i64
+# define CURL_SUFFIX_CURL_OFF_TU ui64
+# else
+# define CURL_TYPEOF_CURL_OFF_T long long
+# define CURL_FORMAT_CURL_OFF_T "lld"
+# define CURL_FORMAT_CURL_OFF_TU "llu"
+# define CURL_SUFFIX_CURL_OFF_T LL
+# define CURL_SUFFIX_CURL_OFF_TU ULL
+# endif
+# define CURL_TYPEOF_CURL_SOCKLEN_T int
+
+#elif defined(__LCC__)
+# define CURL_TYPEOF_CURL_OFF_T long
+# define CURL_FORMAT_CURL_OFF_T "ld"
+# define CURL_FORMAT_CURL_OFF_TU "lu"
+# define CURL_SUFFIX_CURL_OFF_T L
+# define CURL_SUFFIX_CURL_OFF_TU UL
+# define CURL_TYPEOF_CURL_SOCKLEN_T int
+
+#elif defined(__SYMBIAN32__)
+# if defined(__EABI__) /* Treat all ARM compilers equally */
+# define CURL_TYPEOF_CURL_OFF_T long long
+# define CURL_FORMAT_CURL_OFF_T "lld"
+# define CURL_FORMAT_CURL_OFF_TU "llu"
+# define CURL_SUFFIX_CURL_OFF_T LL
+# define CURL_SUFFIX_CURL_OFF_TU ULL
+# elif defined(__CW32__)
+# pragma longlong on
+# define CURL_TYPEOF_CURL_OFF_T long long
+# define CURL_FORMAT_CURL_OFF_T "lld"
+# define CURL_FORMAT_CURL_OFF_TU "llu"
+# define CURL_SUFFIX_CURL_OFF_T LL
+# define CURL_SUFFIX_CURL_OFF_TU ULL
+# elif defined(__VC32__)
+# define CURL_TYPEOF_CURL_OFF_T __int64
+# define CURL_FORMAT_CURL_OFF_T "lld"
+# define CURL_FORMAT_CURL_OFF_TU "llu"
+# define CURL_SUFFIX_CURL_OFF_T LL
+# define CURL_SUFFIX_CURL_OFF_TU ULL
+# endif
+# define CURL_TYPEOF_CURL_SOCKLEN_T unsigned int
+
+#elif defined(__MWERKS__)
+# define CURL_TYPEOF_CURL_OFF_T long long
+# define CURL_FORMAT_CURL_OFF_T "lld"
+# define CURL_FORMAT_CURL_OFF_TU "llu"
+# define CURL_SUFFIX_CURL_OFF_T LL
+# define CURL_SUFFIX_CURL_OFF_TU ULL
+# define CURL_TYPEOF_CURL_SOCKLEN_T int
+
+#elif defined(_WIN32_WCE)
+# define CURL_TYPEOF_CURL_OFF_T __int64
+# define CURL_FORMAT_CURL_OFF_T "I64d"
+# define CURL_FORMAT_CURL_OFF_TU "I64u"
+# define CURL_SUFFIX_CURL_OFF_T i64
+# define CURL_SUFFIX_CURL_OFF_TU ui64
+# define CURL_TYPEOF_CURL_SOCKLEN_T int
+
+#elif defined(__MINGW32__)
+# define CURL_TYPEOF_CURL_OFF_T long long
+# define CURL_FORMAT_CURL_OFF_T "I64d"
+# define CURL_FORMAT_CURL_OFF_TU "I64u"
+# define CURL_SUFFIX_CURL_OFF_T LL
+# define CURL_SUFFIX_CURL_OFF_TU ULL
+# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
+# define CURL_PULL_SYS_TYPES_H 1
+# define CURL_PULL_WS2TCPIP_H 1
+
+#elif defined(__VMS)
+# if defined(__VAX)
+# define CURL_TYPEOF_CURL_OFF_T long
+# define CURL_FORMAT_CURL_OFF_T "ld"
+# define CURL_FORMAT_CURL_OFF_TU "lu"
+# define CURL_SUFFIX_CURL_OFF_T L
+# define CURL_SUFFIX_CURL_OFF_TU UL
+# else
+# define CURL_TYPEOF_CURL_OFF_T long long
+# define CURL_FORMAT_CURL_OFF_T "lld"
+# define CURL_FORMAT_CURL_OFF_TU "llu"
+# define CURL_SUFFIX_CURL_OFF_T LL
+# define CURL_SUFFIX_CURL_OFF_TU ULL
+# endif
+# define CURL_TYPEOF_CURL_SOCKLEN_T unsigned int
+
+#elif defined(__OS400__)
+# if defined(__ILEC400__)
+# define CURL_TYPEOF_CURL_OFF_T long long
+# define CURL_FORMAT_CURL_OFF_T "lld"
+# define CURL_FORMAT_CURL_OFF_TU "llu"
+# define CURL_SUFFIX_CURL_OFF_T LL
+# define CURL_SUFFIX_CURL_OFF_TU ULL
+# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
+# define CURL_PULL_SYS_TYPES_H 1
+# define CURL_PULL_SYS_SOCKET_H 1
+# endif
+
+#elif defined(__MVS__)
+# if defined(__IBMC__) || defined(__IBMCPP__)
+# if defined(_ILP32)
+# elif defined(_LP64)
+# endif
+# if defined(_LONG_LONG)
+# define CURL_TYPEOF_CURL_OFF_T long long
+# define CURL_FORMAT_CURL_OFF_T "lld"
+# define CURL_FORMAT_CURL_OFF_TU "llu"
+# define CURL_SUFFIX_CURL_OFF_T LL
+# define CURL_SUFFIX_CURL_OFF_TU ULL
+# elif defined(_LP64)
+# define CURL_TYPEOF_CURL_OFF_T long
+# define CURL_FORMAT_CURL_OFF_T "ld"
+# define CURL_FORMAT_CURL_OFF_TU "lu"
+# define CURL_SUFFIX_CURL_OFF_T L
+# define CURL_SUFFIX_CURL_OFF_TU UL
+# else
+# define CURL_TYPEOF_CURL_OFF_T long
+# define CURL_FORMAT_CURL_OFF_T "ld"
+# define CURL_FORMAT_CURL_OFF_TU "lu"
+# define CURL_SUFFIX_CURL_OFF_T L
+# define CURL_SUFFIX_CURL_OFF_TU UL
+# endif
+# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
+# define CURL_PULL_SYS_TYPES_H 1
+# define CURL_PULL_SYS_SOCKET_H 1
+# endif
+
+#elif defined(__370__)
+# if defined(__IBMC__) || defined(__IBMCPP__)
+# if defined(_ILP32)
+# elif defined(_LP64)
+# endif
+# if defined(_LONG_LONG)
+# define CURL_TYPEOF_CURL_OFF_T long long
+# define CURL_FORMAT_CURL_OFF_T "lld"
+# define CURL_FORMAT_CURL_OFF_TU "llu"
+# define CURL_SUFFIX_CURL_OFF_T LL
+# define CURL_SUFFIX_CURL_OFF_TU ULL
+# elif defined(_LP64)
+# define CURL_TYPEOF_CURL_OFF_T long
+# define CURL_FORMAT_CURL_OFF_T "ld"
+# define CURL_FORMAT_CURL_OFF_TU "lu"
+# define CURL_SUFFIX_CURL_OFF_T L
+# define CURL_SUFFIX_CURL_OFF_TU UL
+# else
+# define CURL_TYPEOF_CURL_OFF_T long
+# define CURL_FORMAT_CURL_OFF_T "ld"
+# define CURL_FORMAT_CURL_OFF_TU "lu"
+# define CURL_SUFFIX_CURL_OFF_T L
+# define CURL_SUFFIX_CURL_OFF_TU UL
+# endif
+# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
+# define CURL_PULL_SYS_TYPES_H 1
+# define CURL_PULL_SYS_SOCKET_H 1
+# endif
+
+#elif defined(TPF)
+# define CURL_TYPEOF_CURL_OFF_T long
+# define CURL_FORMAT_CURL_OFF_T "ld"
+# define CURL_FORMAT_CURL_OFF_TU "lu"
+# define CURL_SUFFIX_CURL_OFF_T L
+# define CURL_SUFFIX_CURL_OFF_TU UL
+# define CURL_TYPEOF_CURL_SOCKLEN_T int
+
+#elif defined(__TINYC__) /* also known as tcc */
+
+# define CURL_TYPEOF_CURL_OFF_T long long
+# define CURL_FORMAT_CURL_OFF_T "lld"
+# define CURL_FORMAT_CURL_OFF_TU "llu"
+# define CURL_SUFFIX_CURL_OFF_T LL
+# define CURL_SUFFIX_CURL_OFF_TU ULL
+# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
+# define CURL_PULL_SYS_TYPES_H 1
+# define CURL_PULL_SYS_SOCKET_H 1
+
+#elif defined(__SUNPRO_C) || defined(__SUNPRO_CC) /* Oracle Solaris Studio */
+# if !defined(__LP64) && (defined(__ILP32) || \
+ defined(__i386) || \
+ defined(__sparcv8) || \
+ defined(__sparcv8plus))
+# define CURL_TYPEOF_CURL_OFF_T long long
+# define CURL_FORMAT_CURL_OFF_T "lld"
+# define CURL_FORMAT_CURL_OFF_TU "llu"
+# define CURL_SUFFIX_CURL_OFF_T LL
+# define CURL_SUFFIX_CURL_OFF_TU ULL
+# elif defined(__LP64) || \
+ defined(__amd64) || defined(__sparcv9)
+# define CURL_TYPEOF_CURL_OFF_T long
+# define CURL_FORMAT_CURL_OFF_T "ld"
+# define CURL_FORMAT_CURL_OFF_TU "lu"
+# define CURL_SUFFIX_CURL_OFF_T L
+# define CURL_SUFFIX_CURL_OFF_TU UL
+# endif
+# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
+# define CURL_PULL_SYS_TYPES_H 1
+# define CURL_PULL_SYS_SOCKET_H 1
+
+#elif defined(__xlc__) /* IBM xlc compiler */
+# if !defined(_LP64)
+# define CURL_TYPEOF_CURL_OFF_T long long
+# define CURL_FORMAT_CURL_OFF_T "lld"
+# define CURL_FORMAT_CURL_OFF_TU "llu"
+# define CURL_SUFFIX_CURL_OFF_T LL
+# define CURL_SUFFIX_CURL_OFF_TU ULL
+# else
+# define CURL_TYPEOF_CURL_OFF_T long
+# define CURL_FORMAT_CURL_OFF_T "ld"
+# define CURL_FORMAT_CURL_OFF_TU "lu"
+# define CURL_SUFFIX_CURL_OFF_T L
+# define CURL_SUFFIX_CURL_OFF_TU UL
+# endif
+# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
+# define CURL_PULL_SYS_TYPES_H 1
+# define CURL_PULL_SYS_SOCKET_H 1
+
+/* ===================================== */
+/* KEEP MSVC THE PENULTIMATE ENTRY */
+/* ===================================== */
+
+#elif defined(_MSC_VER)
+# if (_MSC_VER >= 900) && (_INTEGRAL_MAX_BITS >= 64)
+# define CURL_TYPEOF_CURL_OFF_T __int64
+# define CURL_FORMAT_CURL_OFF_T "I64d"
+# define CURL_FORMAT_CURL_OFF_TU "I64u"
+# define CURL_SUFFIX_CURL_OFF_T i64
+# define CURL_SUFFIX_CURL_OFF_TU ui64
+# else
+# define CURL_TYPEOF_CURL_OFF_T long
+# define CURL_FORMAT_CURL_OFF_T "ld"
+# define CURL_FORMAT_CURL_OFF_TU "lu"
+# define CURL_SUFFIX_CURL_OFF_T L
+# define CURL_SUFFIX_CURL_OFF_TU UL
+# endif
+# define CURL_TYPEOF_CURL_SOCKLEN_T int
+
+/* ===================================== */
+/* KEEP GENERIC GCC THE LAST ENTRY */
+/* ===================================== */
+
+#elif defined(__GNUC__) && !defined(_SCO_DS)
+# if !defined(__LP64__) && \
+ (defined(__ILP32__) || defined(__i386__) || defined(__hppa__) || \
+ defined(__ppc__) || defined(__powerpc__) || defined(__arm__) || \
+ defined(__sparc__) || defined(__mips__) || defined(__sh__) || \
+ defined(__XTENSA__) || \
+ (defined(__SIZEOF_LONG__) && __SIZEOF_LONG__ == 4) || \
+ (defined(__LONG_MAX__) && __LONG_MAX__ == 2147483647L))
+# define CURL_TYPEOF_CURL_OFF_T long long
+# define CURL_FORMAT_CURL_OFF_T "lld"
+# define CURL_FORMAT_CURL_OFF_TU "llu"
+# define CURL_SUFFIX_CURL_OFF_T LL
+# define CURL_SUFFIX_CURL_OFF_TU ULL
+# elif defined(__LP64__) || \
+ defined(__x86_64__) || defined(__ppc64__) || defined(__sparc64__) || \
+ (defined(__SIZEOF_LONG__) && __SIZEOF_LONG__ == 8) || \
+ (defined(__LONG_MAX__) && __LONG_MAX__ == 9223372036854775807L)
+# define CURL_TYPEOF_CURL_OFF_T long
+# define CURL_FORMAT_CURL_OFF_T "ld"
+# define CURL_FORMAT_CURL_OFF_TU "lu"
+# define CURL_SUFFIX_CURL_OFF_T L
+# define CURL_SUFFIX_CURL_OFF_TU UL
+# endif
+# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
+# define CURL_PULL_SYS_TYPES_H 1
+# define CURL_PULL_SYS_SOCKET_H 1
+
+#else
+/* generic "safe guess" on old 32 bit style */
+# define CURL_TYPEOF_CURL_OFF_T long
+# define CURL_FORMAT_CURL_OFF_T "ld"
+# define CURL_FORMAT_CURL_OFF_TU "lu"
+# define CURL_SUFFIX_CURL_OFF_T L
+# define CURL_SUFFIX_CURL_OFF_TU UL
+# define CURL_TYPEOF_CURL_SOCKLEN_T int
+#endif
+
+#ifdef _AIX
+/* AIX needs <sys/poll.h> */
+#define CURL_PULL_SYS_POLL_H
+#endif
+
+
+/* CURL_PULL_WS2TCPIP_H is defined above when inclusion of header file */
+/* ws2tcpip.h is required here to properly make type definitions below. */
+#ifdef CURL_PULL_WS2TCPIP_H
+# include <winsock2.h>
+# include <windows.h>
+# include <ws2tcpip.h>
+#endif
+
+/* CURL_PULL_SYS_TYPES_H is defined above when inclusion of header file */
+/* sys/types.h is required here to properly make type definitions below. */
+#ifdef CURL_PULL_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+/* CURL_PULL_SYS_SOCKET_H is defined above when inclusion of header file */
+/* sys/socket.h is required here to properly make type definitions below. */
+#ifdef CURL_PULL_SYS_SOCKET_H
+# include <sys/socket.h>
+#endif
+
+/* CURL_PULL_SYS_POLL_H is defined above when inclusion of header file */
+/* sys/poll.h is required here to properly make type definitions below. */
+#ifdef CURL_PULL_SYS_POLL_H
+# include <sys/poll.h>
+#endif
+
+/* Data type definition of curl_socklen_t. */
+#ifdef CURL_TYPEOF_CURL_SOCKLEN_T
+ typedef CURL_TYPEOF_CURL_SOCKLEN_T curl_socklen_t;
+#endif
+
+/* Data type definition of curl_off_t. */
+
+#ifdef CURL_TYPEOF_CURL_OFF_T
+ typedef CURL_TYPEOF_CURL_OFF_T curl_off_t;
+#endif
+
+/*
+ * CURL_ISOCPP and CURL_OFF_T_C definitions are done here in order to allow
+ * these to be visible and exported by the external libcurl interface API,
+ * while also making them visible to the library internals, simply including
+ * curl_setup.h, without actually needing to include curl.h internally.
+ * If some day this section would grow big enough, all this should be moved
+ * to its own header file.
+ */
+
+/*
+ * Figure out if we can use the ## preprocessor operator, which is supported
+ * by ISO/ANSI C and C++. Some compilers support it without setting __STDC__
+ * or __cplusplus so we need to carefully check for them too.
+ */
+
+#if defined(__STDC__) || defined(_MSC_VER) || defined(__cplusplus) || \
+ defined(__HP_aCC) || defined(__BORLANDC__) || defined(__LCC__) || \
+ defined(__POCC__) || defined(__SALFORDC__) || defined(__HIGHC__) || \
+ defined(__ILEC400__)
+ /* This compiler is believed to have an ISO compatible preprocessor */
+#define CURL_ISOCPP
+#else
+ /* This compiler is believed NOT to have an ISO compatible preprocessor */
+#undef CURL_ISOCPP
+#endif
+
+/*
+ * Macros for minimum-width signed and unsigned curl_off_t integer constants.
+ */
+
+#if defined(__BORLANDC__) && (__BORLANDC__ == 0x0551)
+# define __CURL_OFF_T_C_HLPR2(x) x
+# define __CURL_OFF_T_C_HLPR1(x) __CURL_OFF_T_C_HLPR2(x)
+# define CURL_OFF_T_C(Val) __CURL_OFF_T_C_HLPR1(Val) ## \
+ __CURL_OFF_T_C_HLPR1(CURL_SUFFIX_CURL_OFF_T)
+# define CURL_OFF_TU_C(Val) __CURL_OFF_T_C_HLPR1(Val) ## \
+ __CURL_OFF_T_C_HLPR1(CURL_SUFFIX_CURL_OFF_TU)
+#else
+# ifdef CURL_ISOCPP
+# define __CURL_OFF_T_C_HLPR2(Val,Suffix) Val ## Suffix
+# else
+# define __CURL_OFF_T_C_HLPR2(Val,Suffix) Val/**/Suffix
+# endif
+# define __CURL_OFF_T_C_HLPR1(Val,Suffix) __CURL_OFF_T_C_HLPR2(Val,Suffix)
+# define CURL_OFF_T_C(Val) __CURL_OFF_T_C_HLPR1(Val,CURL_SUFFIX_CURL_OFF_T)
+# define CURL_OFF_TU_C(Val) __CURL_OFF_T_C_HLPR1(Val,CURL_SUFFIX_CURL_OFF_TU)
+#endif
+
+#endif /* __CURL_SYSTEM_H */
diff --git a/toolkit/crashreporter/google-breakpad/src/third_party/curl/typecheck-gcc.h b/toolkit/crashreporter/google-breakpad/src/third_party/curl/typecheck-gcc.h
new file mode 100644
index 0000000000..8018ea37fe
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/third_party/curl/typecheck-gcc.h
@@ -0,0 +1,700 @@
+#ifndef __CURL_TYPECHECK_GCC_H
+#define __CURL_TYPECHECK_GCC_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+/* wraps curl_easy_setopt() with typechecking */
+
+/* To add a new kind of warning, add an
+ * if(_curl_is_sometype_option(_curl_opt))
+ * if(!_curl_is_sometype(value))
+ * _curl_easy_setopt_err_sometype();
+ * block and define _curl_is_sometype_option, _curl_is_sometype and
+ * _curl_easy_setopt_err_sometype below
+ *
+ * NOTE: We use two nested 'if' statements here instead of the && operator, in
+ * order to work around gcc bug #32061. It affects only gcc 4.3.x/4.4.x
+ * when compiling with -Wlogical-op.
+ *
+ * To add an option that uses the same type as an existing option, you'll just
+ * need to extend the appropriate _curl_*_option macro
+ */
+#define curl_easy_setopt(handle, option, value) \
+__extension__ ({ \
+ __typeof__(option) _curl_opt = option; \
+ if(__builtin_constant_p(_curl_opt)) { \
+ if(_curl_is_long_option(_curl_opt)) \
+ if(!_curl_is_long(value)) \
+ _curl_easy_setopt_err_long(); \
+ if(_curl_is_off_t_option(_curl_opt)) \
+ if(!_curl_is_off_t(value)) \
+ _curl_easy_setopt_err_curl_off_t(); \
+ if(_curl_is_string_option(_curl_opt)) \
+ if(!_curl_is_string(value)) \
+ _curl_easy_setopt_err_string(); \
+ if(_curl_is_write_cb_option(_curl_opt)) \
+ if(!_curl_is_write_cb(value)) \
+ _curl_easy_setopt_err_write_callback(); \
+ if((_curl_opt) == CURLOPT_RESOLVER_START_FUNCTION) \
+ if(!_curl_is_resolver_start_callback(value)) \
+ _curl_easy_setopt_err_resolver_start_callback(); \
+ if((_curl_opt) == CURLOPT_READFUNCTION) \
+ if(!_curl_is_read_cb(value)) \
+ _curl_easy_setopt_err_read_cb(); \
+ if((_curl_opt) == CURLOPT_IOCTLFUNCTION) \
+ if(!_curl_is_ioctl_cb(value)) \
+ _curl_easy_setopt_err_ioctl_cb(); \
+ if((_curl_opt) == CURLOPT_SOCKOPTFUNCTION) \
+ if(!_curl_is_sockopt_cb(value)) \
+ _curl_easy_setopt_err_sockopt_cb(); \
+ if((_curl_opt) == CURLOPT_OPENSOCKETFUNCTION) \
+ if(!_curl_is_opensocket_cb(value)) \
+ _curl_easy_setopt_err_opensocket_cb(); \
+ if((_curl_opt) == CURLOPT_PROGRESSFUNCTION) \
+ if(!_curl_is_progress_cb(value)) \
+ _curl_easy_setopt_err_progress_cb(); \
+ if((_curl_opt) == CURLOPT_DEBUGFUNCTION) \
+ if(!_curl_is_debug_cb(value)) \
+ _curl_easy_setopt_err_debug_cb(); \
+ if((_curl_opt) == CURLOPT_SSL_CTX_FUNCTION) \
+ if(!_curl_is_ssl_ctx_cb(value)) \
+ _curl_easy_setopt_err_ssl_ctx_cb(); \
+ if(_curl_is_conv_cb_option(_curl_opt)) \
+ if(!_curl_is_conv_cb(value)) \
+ _curl_easy_setopt_err_conv_cb(); \
+ if((_curl_opt) == CURLOPT_SEEKFUNCTION) \
+ if(!_curl_is_seek_cb(value)) \
+ _curl_easy_setopt_err_seek_cb(); \
+ if(_curl_is_cb_data_option(_curl_opt)) \
+ if(!_curl_is_cb_data(value)) \
+ _curl_easy_setopt_err_cb_data(); \
+ if((_curl_opt) == CURLOPT_ERRORBUFFER) \
+ if(!_curl_is_error_buffer(value)) \
+ _curl_easy_setopt_err_error_buffer(); \
+ if((_curl_opt) == CURLOPT_STDERR) \
+ if(!_curl_is_FILE(value)) \
+ _curl_easy_setopt_err_FILE(); \
+ if(_curl_is_postfields_option(_curl_opt)) \
+ if(!_curl_is_postfields(value)) \
+ _curl_easy_setopt_err_postfields(); \
+ if((_curl_opt) == CURLOPT_HTTPPOST) \
+ if(!_curl_is_arr((value), struct curl_httppost)) \
+ _curl_easy_setopt_err_curl_httpost(); \
+ if((_curl_opt) == CURLOPT_MIMEPOST) \
+ if(!_curl_is_ptr((value), curl_mime)) \
+ _curl_easy_setopt_err_curl_mimepost(); \
+ if(_curl_is_slist_option(_curl_opt)) \
+ if(!_curl_is_arr((value), struct curl_slist)) \
+ _curl_easy_setopt_err_curl_slist(); \
+ if((_curl_opt) == CURLOPT_SHARE) \
+ if(!_curl_is_ptr((value), CURLSH)) \
+ _curl_easy_setopt_err_CURLSH(); \
+ } \
+ curl_easy_setopt(handle, _curl_opt, value); \
+})
+
+/* wraps curl_easy_getinfo() with typechecking */
+/* FIXME: don't allow const pointers */
+#define curl_easy_getinfo(handle, info, arg) \
+__extension__ ({ \
+ __typeof__(info) _curl_info = info; \
+ if(__builtin_constant_p(_curl_info)) { \
+ if(_curl_is_string_info(_curl_info)) \
+ if(!_curl_is_arr((arg), char *)) \
+ _curl_easy_getinfo_err_string(); \
+ if(_curl_is_long_info(_curl_info)) \
+ if(!_curl_is_arr((arg), long)) \
+ _curl_easy_getinfo_err_long(); \
+ if(_curl_is_double_info(_curl_info)) \
+ if(!_curl_is_arr((arg), double)) \
+ _curl_easy_getinfo_err_double(); \
+ if(_curl_is_slist_info(_curl_info)) \
+ if(!_curl_is_arr((arg), struct curl_slist *)) \
+ _curl_easy_getinfo_err_curl_slist(); \
+ if(_curl_is_tlssessioninfo_info(_curl_info)) \
+ if(!_curl_is_arr((arg), struct curl_tlssessioninfo *)) \
+ _curl_easy_getinfo_err_curl_tlssesssioninfo(); \
+ if(_curl_is_certinfo_info(_curl_info)) \
+ if(!_curl_is_arr((arg), struct curl_certinfo *)) \
+ _curl_easy_getinfo_err_curl_certinfo(); \
+ if(_curl_is_socket_info(_curl_info)) \
+ if(!_curl_is_arr((arg), curl_socket_t)) \
+ _curl_easy_getinfo_err_curl_socket(); \
+ if(_curl_is_off_t_info(_curl_info)) \
+ if(!_curl_is_arr((arg), curl_off_t)) \
+ _curl_easy_getinfo_err_curl_off_t(); \
+ } \
+ curl_easy_getinfo(handle, _curl_info, arg); \
+})
+
+/* TODO: typechecking for curl_share_setopt() and curl_multi_setopt(),
+ * for now just make sure that the functions are called with three
+ * arguments
+ */
+#define curl_share_setopt(share,opt,param) curl_share_setopt(share,opt,param)
+#define curl_multi_setopt(handle,opt,param) curl_multi_setopt(handle,opt,param)
+
+
+/* the actual warnings, triggered by calling the _curl_easy_setopt_err*
+ * functions */
+
+/* To define a new warning, use _CURL_WARNING(identifier, "message") */
+#define _CURL_WARNING(id, message) \
+ static void __attribute__((__warning__(message))) \
+ __attribute__((__unused__)) __attribute__((__noinline__)) \
+ id(void) { __asm__(""); }
+
+_CURL_WARNING(_curl_easy_setopt_err_long,
+ "curl_easy_setopt expects a long argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_curl_off_t,
+ "curl_easy_setopt expects a curl_off_t argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_string,
+ "curl_easy_setopt expects a "
+ "string ('char *' or char[]) argument for this option"
+ )
+_CURL_WARNING(_curl_easy_setopt_err_write_callback,
+ "curl_easy_setopt expects a curl_write_callback argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_resolver_start_callback,
+ "curl_easy_setopt expects a "
+ "curl_resolver_start_callback argument for this option"
+ )
+_CURL_WARNING(_curl_easy_setopt_err_read_cb,
+ "curl_easy_setopt expects a curl_read_callback argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_ioctl_cb,
+ "curl_easy_setopt expects a curl_ioctl_callback argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_sockopt_cb,
+ "curl_easy_setopt expects a curl_sockopt_callback argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_opensocket_cb,
+ "curl_easy_setopt expects a "
+ "curl_opensocket_callback argument for this option"
+ )
+_CURL_WARNING(_curl_easy_setopt_err_progress_cb,
+ "curl_easy_setopt expects a curl_progress_callback argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_debug_cb,
+ "curl_easy_setopt expects a curl_debug_callback argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_ssl_ctx_cb,
+ "curl_easy_setopt expects a curl_ssl_ctx_callback argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_conv_cb,
+ "curl_easy_setopt expects a curl_conv_callback argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_seek_cb,
+ "curl_easy_setopt expects a curl_seek_callback argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_cb_data,
+ "curl_easy_setopt expects a "
+ "private data pointer as argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_error_buffer,
+ "curl_easy_setopt expects a "
+ "char buffer of CURL_ERROR_SIZE as argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_FILE,
+ "curl_easy_setopt expects a 'FILE *' argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_postfields,
+ "curl_easy_setopt expects a 'void *' or 'char *' argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_curl_httpost,
+ "curl_easy_setopt expects a 'struct curl_httppost *' "
+ "argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_curl_mimepost,
+ "curl_easy_setopt expects a 'curl_mime *' "
+ "argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_curl_slist,
+ "curl_easy_setopt expects a 'struct curl_slist *' argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_CURLSH,
+ "curl_easy_setopt expects a CURLSH* argument for this option")
+
+_CURL_WARNING(_curl_easy_getinfo_err_string,
+ "curl_easy_getinfo expects a pointer to 'char *' for this info")
+_CURL_WARNING(_curl_easy_getinfo_err_long,
+ "curl_easy_getinfo expects a pointer to long for this info")
+_CURL_WARNING(_curl_easy_getinfo_err_double,
+ "curl_easy_getinfo expects a pointer to double for this info")
+_CURL_WARNING(_curl_easy_getinfo_err_curl_slist,
+ "curl_easy_getinfo expects a pointer to 'struct curl_slist *' for this info")
+_CURL_WARNING(_curl_easy_getinfo_err_curl_tlssesssioninfo,
+ "curl_easy_getinfo expects a pointer to "
+ "'struct curl_tlssessioninfo *' for this info")
+_CURL_WARNING(_curl_easy_getinfo_err_curl_certinfo,
+ "curl_easy_getinfo expects a pointer to "
+ "'struct curl_certinfo *' for this info")
+_CURL_WARNING(_curl_easy_getinfo_err_curl_socket,
+ "curl_easy_getinfo expects a pointer to curl_socket_t for this info")
+_CURL_WARNING(_curl_easy_getinfo_err_curl_off_t,
+ "curl_easy_getinfo expects a pointer to curl_off_t for this info")
+
+/* groups of curl_easy_setops options that take the same type of argument */
+
+/* To add a new option to one of the groups, just add
+ * (option) == CURLOPT_SOMETHING
+ * to the or-expression. If the option takes a long or curl_off_t, you don't
+ * have to do anything
+ */
+
+/* evaluates to true if option takes a long argument */
+#define _curl_is_long_option(option) \
+ (0 < (option) && (option) < CURLOPTTYPE_OBJECTPOINT)
+
+#define _curl_is_off_t_option(option) \
+ ((option) > CURLOPTTYPE_OFF_T)
+
+/* evaluates to true if option takes a char* argument */
+#define _curl_is_string_option(option) \
+ ((option) == CURLOPT_ABSTRACT_UNIX_SOCKET || \
+ (option) == CURLOPT_ACCEPT_ENCODING || \
+ (option) == CURLOPT_ALTSVC || \
+ (option) == CURLOPT_CAINFO || \
+ (option) == CURLOPT_CAPATH || \
+ (option) == CURLOPT_COOKIE || \
+ (option) == CURLOPT_COOKIEFILE || \
+ (option) == CURLOPT_COOKIEJAR || \
+ (option) == CURLOPT_COOKIELIST || \
+ (option) == CURLOPT_CRLFILE || \
+ (option) == CURLOPT_CUSTOMREQUEST || \
+ (option) == CURLOPT_DEFAULT_PROTOCOL || \
+ (option) == CURLOPT_DNS_INTERFACE || \
+ (option) == CURLOPT_DNS_LOCAL_IP4 || \
+ (option) == CURLOPT_DNS_LOCAL_IP6 || \
+ (option) == CURLOPT_DNS_SERVERS || \
+ (option) == CURLOPT_DOH_URL || \
+ (option) == CURLOPT_EGDSOCKET || \
+ (option) == CURLOPT_FTPPORT || \
+ (option) == CURLOPT_FTP_ACCOUNT || \
+ (option) == CURLOPT_FTP_ALTERNATIVE_TO_USER || \
+ (option) == CURLOPT_INTERFACE || \
+ (option) == CURLOPT_ISSUERCERT || \
+ (option) == CURLOPT_KEYPASSWD || \
+ (option) == CURLOPT_KRBLEVEL || \
+ (option) == CURLOPT_LOGIN_OPTIONS || \
+ (option) == CURLOPT_MAIL_AUTH || \
+ (option) == CURLOPT_MAIL_FROM || \
+ (option) == CURLOPT_NETRC_FILE || \
+ (option) == CURLOPT_NOPROXY || \
+ (option) == CURLOPT_PASSWORD || \
+ (option) == CURLOPT_PINNEDPUBLICKEY || \
+ (option) == CURLOPT_PRE_PROXY || \
+ (option) == CURLOPT_PROXY || \
+ (option) == CURLOPT_PROXYPASSWORD || \
+ (option) == CURLOPT_PROXYUSERNAME || \
+ (option) == CURLOPT_PROXYUSERPWD || \
+ (option) == CURLOPT_PROXY_CAINFO || \
+ (option) == CURLOPT_PROXY_CAPATH || \
+ (option) == CURLOPT_PROXY_CRLFILE || \
+ (option) == CURLOPT_PROXY_KEYPASSWD || \
+ (option) == CURLOPT_PROXY_PINNEDPUBLICKEY || \
+ (option) == CURLOPT_PROXY_SERVICE_NAME || \
+ (option) == CURLOPT_PROXY_SSLCERT || \
+ (option) == CURLOPT_PROXY_SSLCERTTYPE || \
+ (option) == CURLOPT_PROXY_SSLKEY || \
+ (option) == CURLOPT_PROXY_SSLKEYTYPE || \
+ (option) == CURLOPT_PROXY_SSL_CIPHER_LIST || \
+ (option) == CURLOPT_PROXY_TLSAUTH_PASSWORD || \
+ (option) == CURLOPT_PROXY_TLSAUTH_USERNAME || \
+ (option) == CURLOPT_PROXY_TLSAUTH_TYPE || \
+ (option) == CURLOPT_RANDOM_FILE || \
+ (option) == CURLOPT_RANGE || \
+ (option) == CURLOPT_REFERER || \
+ (option) == CURLOPT_RTSP_SESSION_ID || \
+ (option) == CURLOPT_RTSP_STREAM_URI || \
+ (option) == CURLOPT_RTSP_TRANSPORT || \
+ (option) == CURLOPT_SERVICE_NAME || \
+ (option) == CURLOPT_SOCKS5_GSSAPI_SERVICE || \
+ (option) == CURLOPT_SSH_HOST_PUBLIC_KEY_MD5 || \
+ (option) == CURLOPT_SSH_KNOWNHOSTS || \
+ (option) == CURLOPT_SSH_PRIVATE_KEYFILE || \
+ (option) == CURLOPT_SSH_PUBLIC_KEYFILE || \
+ (option) == CURLOPT_SSLCERT || \
+ (option) == CURLOPT_SSLCERTTYPE || \
+ (option) == CURLOPT_SSLENGINE || \
+ (option) == CURLOPT_SSLKEY || \
+ (option) == CURLOPT_SSLKEYTYPE || \
+ (option) == CURLOPT_SSL_CIPHER_LIST || \
+ (option) == CURLOPT_TLSAUTH_PASSWORD || \
+ (option) == CURLOPT_TLSAUTH_TYPE || \
+ (option) == CURLOPT_TLSAUTH_USERNAME || \
+ (option) == CURLOPT_UNIX_SOCKET_PATH || \
+ (option) == CURLOPT_URL || \
+ (option) == CURLOPT_USERAGENT || \
+ (option) == CURLOPT_USERNAME || \
+ (option) == CURLOPT_USERPWD || \
+ (option) == CURLOPT_XOAUTH2_BEARER || \
+ 0)
+
+/* evaluates to true if option takes a curl_write_callback argument */
+#define _curl_is_write_cb_option(option) \
+ ((option) == CURLOPT_HEADERFUNCTION || \
+ (option) == CURLOPT_WRITEFUNCTION)
+
+/* evaluates to true if option takes a curl_conv_callback argument */
+#define _curl_is_conv_cb_option(option) \
+ ((option) == CURLOPT_CONV_TO_NETWORK_FUNCTION || \
+ (option) == CURLOPT_CONV_FROM_NETWORK_FUNCTION || \
+ (option) == CURLOPT_CONV_FROM_UTF8_FUNCTION)
+
+/* evaluates to true if option takes a data argument to pass to a callback */
+#define _curl_is_cb_data_option(option) \
+ ((option) == CURLOPT_CHUNK_DATA || \
+ (option) == CURLOPT_CLOSESOCKETDATA || \
+ (option) == CURLOPT_DEBUGDATA || \
+ (option) == CURLOPT_FNMATCH_DATA || \
+ (option) == CURLOPT_HEADERDATA || \
+ (option) == CURLOPT_INTERLEAVEDATA || \
+ (option) == CURLOPT_IOCTLDATA || \
+ (option) == CURLOPT_OPENSOCKETDATA || \
+ (option) == CURLOPT_PRIVATE || \
+ (option) == CURLOPT_PROGRESSDATA || \
+ (option) == CURLOPT_READDATA || \
+ (option) == CURLOPT_SEEKDATA || \
+ (option) == CURLOPT_SOCKOPTDATA || \
+ (option) == CURLOPT_SSH_KEYDATA || \
+ (option) == CURLOPT_SSL_CTX_DATA || \
+ (option) == CURLOPT_WRITEDATA || \
+ (option) == CURLOPT_RESOLVER_START_DATA || \
+ (option) == CURLOPT_CURLU || \
+ 0)
+
+/* evaluates to true if option takes a POST data argument (void* or char*) */
+#define _curl_is_postfields_option(option) \
+ ((option) == CURLOPT_POSTFIELDS || \
+ (option) == CURLOPT_COPYPOSTFIELDS || \
+ 0)
+
+/* evaluates to true if option takes a struct curl_slist * argument */
+#define _curl_is_slist_option(option) \
+ ((option) == CURLOPT_HTTP200ALIASES || \
+ (option) == CURLOPT_HTTPHEADER || \
+ (option) == CURLOPT_MAIL_RCPT || \
+ (option) == CURLOPT_POSTQUOTE || \
+ (option) == CURLOPT_PREQUOTE || \
+ (option) == CURLOPT_PROXYHEADER || \
+ (option) == CURLOPT_QUOTE || \
+ (option) == CURLOPT_RESOLVE || \
+ (option) == CURLOPT_TELNETOPTIONS || \
+ 0)
+
+/* groups of curl_easy_getinfo infos that take the same type of argument */
+
+/* evaluates to true if info expects a pointer to char * argument */
+#define _curl_is_string_info(info) \
+ (CURLINFO_STRING < (info) && (info) < CURLINFO_LONG)
+
+/* evaluates to true if info expects a pointer to long argument */
+#define _curl_is_long_info(info) \
+ (CURLINFO_LONG < (info) && (info) < CURLINFO_DOUBLE)
+
+/* evaluates to true if info expects a pointer to double argument */
+#define _curl_is_double_info(info) \
+ (CURLINFO_DOUBLE < (info) && (info) < CURLINFO_SLIST)
+
+/* true if info expects a pointer to struct curl_slist * argument */
+#define _curl_is_slist_info(info) \
+ (((info) == CURLINFO_SSL_ENGINES) || ((info) == CURLINFO_COOKIELIST))
+
+/* true if info expects a pointer to struct curl_tlssessioninfo * argument */
+#define _curl_is_tlssessioninfo_info(info) \
+ (((info) == CURLINFO_TLS_SSL_PTR) || ((info) == CURLINFO_TLS_SESSION))
+
+/* true if info expects a pointer to struct curl_certinfo * argument */
+#define _curl_is_certinfo_info(info) ((info) == CURLINFO_CERTINFO)
+
+/* true if info expects a pointer to struct curl_socket_t argument */
+#define _curl_is_socket_info(info) \
+ (CURLINFO_SOCKET < (info) && (info) < CURLINFO_OFF_T)
+
+/* true if info expects a pointer to curl_off_t argument */
+#define _curl_is_off_t_info(info) \
+ (CURLINFO_OFF_T < (info))
+
+
+/* typecheck helpers -- check whether given expression has requested type*/
+
+/* For pointers, you can use the _curl_is_ptr/_curl_is_arr macros,
+ * otherwise define a new macro. Search for __builtin_types_compatible_p
+ * in the GCC manual.
+ * NOTE: these macros MUST NOT EVALUATE their arguments! The argument is
+ * the actual expression passed to the curl_easy_setopt macro. This
+ * means that you can only apply the sizeof and __typeof__ operators, no
+ * == or whatsoever.
+ */
+
+/* XXX: should evaluate to true if expr is a pointer */
+#define _curl_is_any_ptr(expr) \
+ (sizeof(expr) == sizeof(void *))
+
+/* evaluates to true if expr is NULL */
+/* XXX: must not evaluate expr, so this check is not accurate */
+#define _curl_is_NULL(expr) \
+ (__builtin_types_compatible_p(__typeof__(expr), __typeof__(NULL)))
+
+/* evaluates to true if expr is type*, const type* or NULL */
+#define _curl_is_ptr(expr, type) \
+ (_curl_is_NULL(expr) || \
+ __builtin_types_compatible_p(__typeof__(expr), type *) || \
+ __builtin_types_compatible_p(__typeof__(expr), const type *))
+
+/* evaluates to true if expr is one of type[], type*, NULL or const type* */
+#define _curl_is_arr(expr, type) \
+ (_curl_is_ptr((expr), type) || \
+ __builtin_types_compatible_p(__typeof__(expr), type []))
+
+/* evaluates to true if expr is a string */
+#define _curl_is_string(expr) \
+ (_curl_is_arr((expr), char) || \
+ _curl_is_arr((expr), signed char) || \
+ _curl_is_arr((expr), unsigned char))
+
+/* evaluates to true if expr is a long (no matter the signedness)
+ * XXX: for now, int is also accepted (and therefore short and char, which
+ * are promoted to int when passed to a variadic function) */
+#define _curl_is_long(expr) \
+ (__builtin_types_compatible_p(__typeof__(expr), long) || \
+ __builtin_types_compatible_p(__typeof__(expr), signed long) || \
+ __builtin_types_compatible_p(__typeof__(expr), unsigned long) || \
+ __builtin_types_compatible_p(__typeof__(expr), int) || \
+ __builtin_types_compatible_p(__typeof__(expr), signed int) || \
+ __builtin_types_compatible_p(__typeof__(expr), unsigned int) || \
+ __builtin_types_compatible_p(__typeof__(expr), short) || \
+ __builtin_types_compatible_p(__typeof__(expr), signed short) || \
+ __builtin_types_compatible_p(__typeof__(expr), unsigned short) || \
+ __builtin_types_compatible_p(__typeof__(expr), char) || \
+ __builtin_types_compatible_p(__typeof__(expr), signed char) || \
+ __builtin_types_compatible_p(__typeof__(expr), unsigned char))
+
+/* evaluates to true if expr is of type curl_off_t */
+#define _curl_is_off_t(expr) \
+ (__builtin_types_compatible_p(__typeof__(expr), curl_off_t))
+
+/* evaluates to true if expr is abuffer suitable for CURLOPT_ERRORBUFFER */
+/* XXX: also check size of an char[] array? */
+#define _curl_is_error_buffer(expr) \
+ (_curl_is_NULL(expr) || \
+ __builtin_types_compatible_p(__typeof__(expr), char *) || \
+ __builtin_types_compatible_p(__typeof__(expr), char[]))
+
+/* evaluates to true if expr is of type (const) void* or (const) FILE* */
+#if 0
+#define _curl_is_cb_data(expr) \
+ (_curl_is_ptr((expr), void) || \
+ _curl_is_ptr((expr), FILE))
+#else /* be less strict */
+#define _curl_is_cb_data(expr) \
+ _curl_is_any_ptr(expr)
+#endif
+
+/* evaluates to true if expr is of type FILE* */
+#define _curl_is_FILE(expr) \
+ (_curl_is_NULL(expr) || \
+ (__builtin_types_compatible_p(__typeof__(expr), FILE *)))
+
+/* evaluates to true if expr can be passed as POST data (void* or char*) */
+#define _curl_is_postfields(expr) \
+ (_curl_is_ptr((expr), void) || \
+ _curl_is_arr((expr), char) || \
+ _curl_is_arr((expr), unsigned char))
+
+/* FIXME: the whole callback checking is messy...
+ * The idea is to tolerate char vs. void and const vs. not const
+ * pointers in arguments at least
+ */
+/* helper: __builtin_types_compatible_p distinguishes between functions and
+ * function pointers, hide it */
+#define _curl_callback_compatible(func, type) \
+ (__builtin_types_compatible_p(__typeof__(func), type) || \
+ __builtin_types_compatible_p(__typeof__(func) *, type))
+
+/* evaluates to true if expr is of type curl_resolver_start_callback */
+#define _curl_is_resolver_start_callback(expr) \
+ (_curl_is_NULL(expr) || \
+ _curl_callback_compatible((expr), curl_resolver_start_callback))
+
+/* evaluates to true if expr is of type curl_read_callback or "similar" */
+#define _curl_is_read_cb(expr) \
+ (_curl_is_NULL(expr) || \
+ _curl_callback_compatible((expr), __typeof__(fread) *) || \
+ _curl_callback_compatible((expr), curl_read_callback) || \
+ _curl_callback_compatible((expr), _curl_read_callback1) || \
+ _curl_callback_compatible((expr), _curl_read_callback2) || \
+ _curl_callback_compatible((expr), _curl_read_callback3) || \
+ _curl_callback_compatible((expr), _curl_read_callback4) || \
+ _curl_callback_compatible((expr), _curl_read_callback5) || \
+ _curl_callback_compatible((expr), _curl_read_callback6))
+typedef size_t (*_curl_read_callback1)(char *, size_t, size_t, void *);
+typedef size_t (*_curl_read_callback2)(char *, size_t, size_t, const void *);
+typedef size_t (*_curl_read_callback3)(char *, size_t, size_t, FILE *);
+typedef size_t (*_curl_read_callback4)(void *, size_t, size_t, void *);
+typedef size_t (*_curl_read_callback5)(void *, size_t, size_t, const void *);
+typedef size_t (*_curl_read_callback6)(void *, size_t, size_t, FILE *);
+
+/* evaluates to true if expr is of type curl_write_callback or "similar" */
+#define _curl_is_write_cb(expr) \
+ (_curl_is_read_cb(expr) || \
+ _curl_callback_compatible((expr), __typeof__(fwrite) *) || \
+ _curl_callback_compatible((expr), curl_write_callback) || \
+ _curl_callback_compatible((expr), _curl_write_callback1) || \
+ _curl_callback_compatible((expr), _curl_write_callback2) || \
+ _curl_callback_compatible((expr), _curl_write_callback3) || \
+ _curl_callback_compatible((expr), _curl_write_callback4) || \
+ _curl_callback_compatible((expr), _curl_write_callback5) || \
+ _curl_callback_compatible((expr), _curl_write_callback6))
+typedef size_t (*_curl_write_callback1)(const char *, size_t, size_t, void *);
+typedef size_t (*_curl_write_callback2)(const char *, size_t, size_t,
+ const void *);
+typedef size_t (*_curl_write_callback3)(const char *, size_t, size_t, FILE *);
+typedef size_t (*_curl_write_callback4)(const void *, size_t, size_t, void *);
+typedef size_t (*_curl_write_callback5)(const void *, size_t, size_t,
+ const void *);
+typedef size_t (*_curl_write_callback6)(const void *, size_t, size_t, FILE *);
+
+/* evaluates to true if expr is of type curl_ioctl_callback or "similar" */
+#define _curl_is_ioctl_cb(expr) \
+ (_curl_is_NULL(expr) || \
+ _curl_callback_compatible((expr), curl_ioctl_callback) || \
+ _curl_callback_compatible((expr), _curl_ioctl_callback1) || \
+ _curl_callback_compatible((expr), _curl_ioctl_callback2) || \
+ _curl_callback_compatible((expr), _curl_ioctl_callback3) || \
+ _curl_callback_compatible((expr), _curl_ioctl_callback4))
+typedef curlioerr (*_curl_ioctl_callback1)(CURL *, int, void *);
+typedef curlioerr (*_curl_ioctl_callback2)(CURL *, int, const void *);
+typedef curlioerr (*_curl_ioctl_callback3)(CURL *, curliocmd, void *);
+typedef curlioerr (*_curl_ioctl_callback4)(CURL *, curliocmd, const void *);
+
+/* evaluates to true if expr is of type curl_sockopt_callback or "similar" */
+#define _curl_is_sockopt_cb(expr) \
+ (_curl_is_NULL(expr) || \
+ _curl_callback_compatible((expr), curl_sockopt_callback) || \
+ _curl_callback_compatible((expr), _curl_sockopt_callback1) || \
+ _curl_callback_compatible((expr), _curl_sockopt_callback2))
+typedef int (*_curl_sockopt_callback1)(void *, curl_socket_t, curlsocktype);
+typedef int (*_curl_sockopt_callback2)(const void *, curl_socket_t,
+ curlsocktype);
+
+/* evaluates to true if expr is of type curl_opensocket_callback or
+ "similar" */
+#define _curl_is_opensocket_cb(expr) \
+ (_curl_is_NULL(expr) || \
+ _curl_callback_compatible((expr), curl_opensocket_callback) || \
+ _curl_callback_compatible((expr), _curl_opensocket_callback1) || \
+ _curl_callback_compatible((expr), _curl_opensocket_callback2) || \
+ _curl_callback_compatible((expr), _curl_opensocket_callback3) || \
+ _curl_callback_compatible((expr), _curl_opensocket_callback4))
+typedef curl_socket_t (*_curl_opensocket_callback1)
+ (void *, curlsocktype, struct curl_sockaddr *);
+typedef curl_socket_t (*_curl_opensocket_callback2)
+ (void *, curlsocktype, const struct curl_sockaddr *);
+typedef curl_socket_t (*_curl_opensocket_callback3)
+ (const void *, curlsocktype, struct curl_sockaddr *);
+typedef curl_socket_t (*_curl_opensocket_callback4)
+ (const void *, curlsocktype, const struct curl_sockaddr *);
+
+/* evaluates to true if expr is of type curl_progress_callback or "similar" */
+#define _curl_is_progress_cb(expr) \
+ (_curl_is_NULL(expr) || \
+ _curl_callback_compatible((expr), curl_progress_callback) || \
+ _curl_callback_compatible((expr), _curl_progress_callback1) || \
+ _curl_callback_compatible((expr), _curl_progress_callback2))
+typedef int (*_curl_progress_callback1)(void *,
+ double, double, double, double);
+typedef int (*_curl_progress_callback2)(const void *,
+ double, double, double, double);
+
+/* evaluates to true if expr is of type curl_debug_callback or "similar" */
+#define _curl_is_debug_cb(expr) \
+ (_curl_is_NULL(expr) || \
+ _curl_callback_compatible((expr), curl_debug_callback) || \
+ _curl_callback_compatible((expr), _curl_debug_callback1) || \
+ _curl_callback_compatible((expr), _curl_debug_callback2) || \
+ _curl_callback_compatible((expr), _curl_debug_callback3) || \
+ _curl_callback_compatible((expr), _curl_debug_callback4) || \
+ _curl_callback_compatible((expr), _curl_debug_callback5) || \
+ _curl_callback_compatible((expr), _curl_debug_callback6) || \
+ _curl_callback_compatible((expr), _curl_debug_callback7) || \
+ _curl_callback_compatible((expr), _curl_debug_callback8))
+typedef int (*_curl_debug_callback1) (CURL *,
+ curl_infotype, char *, size_t, void *);
+typedef int (*_curl_debug_callback2) (CURL *,
+ curl_infotype, char *, size_t, const void *);
+typedef int (*_curl_debug_callback3) (CURL *,
+ curl_infotype, const char *, size_t, void *);
+typedef int (*_curl_debug_callback4) (CURL *,
+ curl_infotype, const char *, size_t, const void *);
+typedef int (*_curl_debug_callback5) (CURL *,
+ curl_infotype, unsigned char *, size_t, void *);
+typedef int (*_curl_debug_callback6) (CURL *,
+ curl_infotype, unsigned char *, size_t, const void *);
+typedef int (*_curl_debug_callback7) (CURL *,
+ curl_infotype, const unsigned char *, size_t, void *);
+typedef int (*_curl_debug_callback8) (CURL *,
+ curl_infotype, const unsigned char *, size_t, const void *);
+
+/* evaluates to true if expr is of type curl_ssl_ctx_callback or "similar" */
+/* this is getting even messier... */
+#define _curl_is_ssl_ctx_cb(expr) \
+ (_curl_is_NULL(expr) || \
+ _curl_callback_compatible((expr), curl_ssl_ctx_callback) || \
+ _curl_callback_compatible((expr), _curl_ssl_ctx_callback1) || \
+ _curl_callback_compatible((expr), _curl_ssl_ctx_callback2) || \
+ _curl_callback_compatible((expr), _curl_ssl_ctx_callback3) || \
+ _curl_callback_compatible((expr), _curl_ssl_ctx_callback4) || \
+ _curl_callback_compatible((expr), _curl_ssl_ctx_callback5) || \
+ _curl_callback_compatible((expr), _curl_ssl_ctx_callback6) || \
+ _curl_callback_compatible((expr), _curl_ssl_ctx_callback7) || \
+ _curl_callback_compatible((expr), _curl_ssl_ctx_callback8))
+typedef CURLcode (*_curl_ssl_ctx_callback1)(CURL *, void *, void *);
+typedef CURLcode (*_curl_ssl_ctx_callback2)(CURL *, void *, const void *);
+typedef CURLcode (*_curl_ssl_ctx_callback3)(CURL *, const void *, void *);
+typedef CURLcode (*_curl_ssl_ctx_callback4)(CURL *, const void *,
+ const void *);
+#ifdef HEADER_SSL_H
+/* hack: if we included OpenSSL's ssl.h, we know about SSL_CTX
+ * this will of course break if we're included before OpenSSL headers...
+ */
+typedef CURLcode (*_curl_ssl_ctx_callback5)(CURL *, SSL_CTX, void *);
+typedef CURLcode (*_curl_ssl_ctx_callback6)(CURL *, SSL_CTX, const void *);
+typedef CURLcode (*_curl_ssl_ctx_callback7)(CURL *, const SSL_CTX, void *);
+typedef CURLcode (*_curl_ssl_ctx_callback8)(CURL *, const SSL_CTX,
+ const void *);
+#else
+typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback5;
+typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback6;
+typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback7;
+typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback8;
+#endif
+
+/* evaluates to true if expr is of type curl_conv_callback or "similar" */
+#define _curl_is_conv_cb(expr) \
+ (_curl_is_NULL(expr) || \
+ _curl_callback_compatible((expr), curl_conv_callback) || \
+ _curl_callback_compatible((expr), _curl_conv_callback1) || \
+ _curl_callback_compatible((expr), _curl_conv_callback2) || \
+ _curl_callback_compatible((expr), _curl_conv_callback3) || \
+ _curl_callback_compatible((expr), _curl_conv_callback4))
+typedef CURLcode (*_curl_conv_callback1)(char *, size_t length);
+typedef CURLcode (*_curl_conv_callback2)(const char *, size_t length);
+typedef CURLcode (*_curl_conv_callback3)(void *, size_t length);
+typedef CURLcode (*_curl_conv_callback4)(const void *, size_t length);
+
+/* evaluates to true if expr is of type curl_seek_callback or "similar" */
+#define _curl_is_seek_cb(expr) \
+ (_curl_is_NULL(expr) || \
+ _curl_callback_compatible((expr), curl_seek_callback) || \
+ _curl_callback_compatible((expr), _curl_seek_callback1) || \
+ _curl_callback_compatible((expr), _curl_seek_callback2))
+typedef CURLcode (*_curl_seek_callback1)(void *, curl_off_t, int);
+typedef CURLcode (*_curl_seek_callback2)(const void *, curl_off_t, int);
+
+
+#endif /* __CURL_TYPECHECK_GCC_H */
diff --git a/toolkit/crashreporter/google-breakpad/src/third_party/curl/urlapi.h b/toolkit/crashreporter/google-breakpad/src/third_party/curl/urlapi.h
new file mode 100644
index 0000000000..850faa97a5
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/third_party/curl/urlapi.h
@@ -0,0 +1,122 @@
+#ifndef __CURL_URLAPI_H
+#define __CURL_URLAPI_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2018 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* the error codes for the URL API */
+typedef enum {
+ CURLUE_OK,
+ CURLUE_BAD_HANDLE, /* 1 */
+ CURLUE_BAD_PARTPOINTER, /* 2 */
+ CURLUE_MALFORMED_INPUT, /* 3 */
+ CURLUE_BAD_PORT_NUMBER, /* 4 */
+ CURLUE_UNSUPPORTED_SCHEME, /* 5 */
+ CURLUE_URLDECODE, /* 6 */
+ CURLUE_OUT_OF_MEMORY, /* 7 */
+ CURLUE_USER_NOT_ALLOWED, /* 8 */
+ CURLUE_UNKNOWN_PART, /* 9 */
+ CURLUE_NO_SCHEME, /* 10 */
+ CURLUE_NO_USER, /* 11 */
+ CURLUE_NO_PASSWORD, /* 12 */
+ CURLUE_NO_OPTIONS, /* 13 */
+ CURLUE_NO_HOST, /* 14 */
+ CURLUE_NO_PORT, /* 15 */
+ CURLUE_NO_QUERY, /* 16 */
+ CURLUE_NO_FRAGMENT /* 17 */
+} CURLUcode;
+
+typedef enum {
+ CURLUPART_URL,
+ CURLUPART_SCHEME,
+ CURLUPART_USER,
+ CURLUPART_PASSWORD,
+ CURLUPART_OPTIONS,
+ CURLUPART_HOST,
+ CURLUPART_PORT,
+ CURLUPART_PATH,
+ CURLUPART_QUERY,
+ CURLUPART_FRAGMENT
+} CURLUPart;
+
+#define CURLU_DEFAULT_PORT (1<<0) /* return default port number */
+#define CURLU_NO_DEFAULT_PORT (1<<1) /* act as if no port number was set,
+ if the port number matches the
+ default for the scheme */
+#define CURLU_DEFAULT_SCHEME (1<<2) /* return default scheme if
+ missing */
+#define CURLU_NON_SUPPORT_SCHEME (1<<3) /* allow non-supported scheme */
+#define CURLU_PATH_AS_IS (1<<4) /* leave dot sequences */
+#define CURLU_DISALLOW_USER (1<<5) /* no user+password allowed */
+#define CURLU_URLDECODE (1<<6) /* URL decode on get */
+#define CURLU_URLENCODE (1<<7) /* URL encode on set */
+#define CURLU_APPENDQUERY (1<<8) /* append a form style part */
+#define CURLU_GUESS_SCHEME (1<<9) /* legacy curl-style guessing */
+
+typedef struct Curl_URL CURLU;
+
+/*
+ * curl_url() creates a new CURLU handle and returns a pointer to it.
+ * Must be freed with curl_url_cleanup().
+ */
+CURL_EXTERN CURLU *curl_url(void);
+
+/*
+ * curl_url_cleanup() frees the CURLU handle and related resources used for
+ * the URL parsing. It will not free strings previously returned with the URL
+ * API.
+ */
+CURL_EXTERN void curl_url_cleanup(CURLU *handle);
+
+/*
+ * curl_url_dup() duplicates a CURLU handle and returns a new copy. The new
+ * handle must also be freed with curl_url_cleanup().
+ */
+CURL_EXTERN CURLU *curl_url_dup(CURLU *in);
+
+/*
+ * curl_url_get() extracts a specific part of the URL from a CURLU
+ * handle. Returns error code. The returned pointer MUST be freed with
+ * curl_free() afterwards.
+ */
+CURL_EXTERN CURLUcode curl_url_get(CURLU *handle, CURLUPart what,
+ char **part, unsigned int flags);
+
+/*
+ * curl_url_set() sets a specific part of the URL in a CURLU handle. Returns
+ * error code. The passed in string will be copied. Passing a NULL instead of
+ * a part string, clears that part.
+ */
+CURL_EXTERN CURLUcode curl_url_set(CURLU *handle, CURLUPart what,
+ const char *part, unsigned int flags);
+
+
+#ifdef __cplusplus
+} /* end of extern "C" */
+#endif
+
+#endif
diff --git a/toolkit/crashreporter/google-breakpad/src/third_party/glog/Makefile.in b/toolkit/crashreporter/google-breakpad/src/third_party/glog/Makefile.in
new file mode 100644
index 0000000000..731e82f995
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/third_party/glog/Makefile.in
@@ -0,0 +1,1553 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+
+
+
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+
+# These are good warnings to turn on by default
+@GCC_TRUE@am__append_1 = -Wall -Wwrite-strings -Woverloaded-virtual -Wno-sign-compare
+
+# These are x86-specific, having to do with frame-pointers
+@ENABLE_FRAME_POINTERS_TRUE@@X86_64_TRUE@am__append_2 = -fno-omit-frame-pointer
+@ENABLE_FRAME_POINTERS_FALSE@@X86_64_TRUE@am__append_3 = -DNO_FRAME_POINTER
+TESTS = logging_unittest$(EXEEXT) demangle_unittest$(EXEEXT) \
+ stacktrace_unittest$(EXEEXT) symbolize_unittest$(EXEEXT) \
+ stl_logging_unittest$(EXEEXT) utilities_unittest$(EXEEXT) \
+ $(am__EXEEXT_1)
+@HAVE_GMOCK_TRUE@am__append_4 = mock_log_test
+noinst_PROGRAMS = $(am__EXEEXT_2) $(am__EXEEXT_3)
+subdir = .
+DIST_COMMON = README $(am__configure_deps) $(dist_doc_DATA) \
+ $(gloginclude_HEADERS) $(noinst_HEADERS) $(srcdir)/Makefile.am \
+ $(srcdir)/Makefile.in $(srcdir)/libglog.pc.in \
+ $(top_srcdir)/configure $(top_srcdir)/src/config.h.in \
+ $(top_srcdir)/src/glog/logging.h.in \
+ $(top_srcdir)/src/glog/raw_logging.h.in \
+ $(top_srcdir)/src/glog/stl_logging.h.in \
+ $(top_srcdir)/src/glog/vlog_is_on.h.in AUTHORS COPYING \
+ ChangeLog INSTALL NEWS compile config.guess config.sub depcomp \
+ install-sh ltmain.sh missing mkinstalldirs
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_have_attribute.m4 \
+ $(top_srcdir)/m4/ac_have_builtin_expect.m4 \
+ $(top_srcdir)/m4/ac_have_sync_val_compare_and_swap.m4 \
+ $(top_srcdir)/m4/ac_rwlock.m4 $(top_srcdir)/m4/acx_pthread.m4 \
+ $(top_srcdir)/m4/google_namespace.m4 \
+ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
+ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
+ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/namespaces.m4 \
+ $(top_srcdir)/m4/pc_from_ucontext.m4 \
+ $(top_srcdir)/m4/stl_namespace.m4 \
+ $(top_srcdir)/m4/using_operator.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
+ configure.lineno config.status.lineno
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/src/config.h
+CONFIG_CLEAN_FILES = src/glog/logging.h src/glog/raw_logging.h \
+ src/glog/vlog_is_on.h src/glog/stl_logging.h libglog.pc
+CONFIG_CLEAN_VPATH_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(docdir)" \
+ "$(DESTDIR)$(pkgconfigdir)" "$(DESTDIR)$(glogincludedir)" \
+ "$(DESTDIR)$(glogincludedir)"
+LTLIBRARIES = $(lib_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1)
+libglog_la_DEPENDENCIES = $(am__DEPENDENCIES_2)
+am__objects_1 =
+am_libglog_la_OBJECTS = $(am__objects_1) libglog_la-logging.lo \
+ libglog_la-raw_logging.lo libglog_la-vlog_is_on.lo \
+ libglog_la-utilities.lo libglog_la-demangle.lo \
+ libglog_la-symbolize.lo libglog_la-signalhandler.lo
+nodist_libglog_la_OBJECTS = $(am__objects_1)
+libglog_la_OBJECTS = $(am_libglog_la_OBJECTS) \
+ $(nodist_libglog_la_OBJECTS)
+libglog_la_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(libglog_la_CXXFLAGS) \
+ $(CXXFLAGS) $(libglog_la_LDFLAGS) $(LDFLAGS) -o $@
+@HAVE_GMOCK_TRUE@am__EXEEXT_1 = mock_log_test$(EXEEXT)
+am__EXEEXT_2 = logging_unittest$(EXEEXT) demangle_unittest$(EXEEXT) \
+ stacktrace_unittest$(EXEEXT) symbolize_unittest$(EXEEXT) \
+ stl_logging_unittest$(EXEEXT) utilities_unittest$(EXEEXT) \
+ $(am__EXEEXT_1)
+am__EXEEXT_3 = logging_striptest0$(EXEEXT) logging_striptest2$(EXEEXT) \
+ logging_striptest10$(EXEEXT) signalhandler_unittest$(EXEEXT)
+PROGRAMS = $(noinst_PROGRAMS)
+am_demangle_unittest_OBJECTS = $(am__objects_1) \
+ demangle_unittest-demangle_unittest.$(OBJEXT)
+nodist_demangle_unittest_OBJECTS = $(am__objects_1)
+demangle_unittest_OBJECTS = $(am_demangle_unittest_OBJECTS) \
+ $(nodist_demangle_unittest_OBJECTS)
+demangle_unittest_DEPENDENCIES = libglog.la $(am__DEPENDENCIES_2) \
+ $(am__DEPENDENCIES_2)
+demangle_unittest_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CXXLD) \
+ $(demangle_unittest_CXXFLAGS) $(CXXFLAGS) \
+ $(demangle_unittest_LDFLAGS) $(LDFLAGS) -o $@
+am_logging_striptest0_OBJECTS = $(am__objects_1) \
+ logging_striptest0-logging_striptest_main.$(OBJEXT)
+nodist_logging_striptest0_OBJECTS = $(am__objects_1)
+logging_striptest0_OBJECTS = $(am_logging_striptest0_OBJECTS) \
+ $(nodist_logging_striptest0_OBJECTS)
+logging_striptest0_DEPENDENCIES = libglog.la $(am__DEPENDENCIES_2)
+logging_striptest0_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CXXLD) \
+ $(logging_striptest0_CXXFLAGS) $(CXXFLAGS) \
+ $(logging_striptest0_LDFLAGS) $(LDFLAGS) -o $@
+am_logging_striptest10_OBJECTS = $(am__objects_1) \
+ logging_striptest10-logging_striptest10.$(OBJEXT)
+nodist_logging_striptest10_OBJECTS = $(am__objects_1)
+logging_striptest10_OBJECTS = $(am_logging_striptest10_OBJECTS) \
+ $(nodist_logging_striptest10_OBJECTS)
+logging_striptest10_DEPENDENCIES = libglog.la $(am__DEPENDENCIES_2)
+logging_striptest10_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CXXLD) \
+ $(logging_striptest10_CXXFLAGS) $(CXXFLAGS) \
+ $(logging_striptest10_LDFLAGS) $(LDFLAGS) -o $@
+am_logging_striptest2_OBJECTS = $(am__objects_1) \
+ logging_striptest2-logging_striptest2.$(OBJEXT)
+nodist_logging_striptest2_OBJECTS = $(am__objects_1)
+logging_striptest2_OBJECTS = $(am_logging_striptest2_OBJECTS) \
+ $(nodist_logging_striptest2_OBJECTS)
+logging_striptest2_DEPENDENCIES = libglog.la $(am__DEPENDENCIES_2)
+logging_striptest2_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CXXLD) \
+ $(logging_striptest2_CXXFLAGS) $(CXXFLAGS) \
+ $(logging_striptest2_LDFLAGS) $(LDFLAGS) -o $@
+am_logging_unittest_OBJECTS = $(am__objects_1) \
+ logging_unittest-logging_unittest.$(OBJEXT)
+nodist_logging_unittest_OBJECTS = $(am__objects_1)
+logging_unittest_OBJECTS = $(am_logging_unittest_OBJECTS) \
+ $(nodist_logging_unittest_OBJECTS)
+logging_unittest_DEPENDENCIES = libglog.la $(am__DEPENDENCIES_2) \
+ $(am__DEPENDENCIES_2)
+logging_unittest_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CXXLD) \
+ $(logging_unittest_CXXFLAGS) $(CXXFLAGS) \
+ $(logging_unittest_LDFLAGS) $(LDFLAGS) -o $@
+am__mock_log_test_SOURCES_DIST = src/glog/log_severity.h \
+ src/mock-log_test.cc
+@HAVE_GMOCK_TRUE@am_mock_log_test_OBJECTS = $(am__objects_1) \
+@HAVE_GMOCK_TRUE@ mock_log_test-mock-log_test.$(OBJEXT)
+@HAVE_GMOCK_TRUE@nodist_mock_log_test_OBJECTS = $(am__objects_1)
+mock_log_test_OBJECTS = $(am_mock_log_test_OBJECTS) \
+ $(nodist_mock_log_test_OBJECTS)
+@HAVE_GMOCK_TRUE@mock_log_test_DEPENDENCIES = libglog.la \
+@HAVE_GMOCK_TRUE@ $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_2)
+mock_log_test_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(mock_log_test_CXXFLAGS) \
+ $(CXXFLAGS) $(mock_log_test_LDFLAGS) $(LDFLAGS) -o $@
+am_signalhandler_unittest_OBJECTS = $(am__objects_1) \
+ signalhandler_unittest-signalhandler_unittest.$(OBJEXT)
+nodist_signalhandler_unittest_OBJECTS = $(am__objects_1)
+signalhandler_unittest_OBJECTS = $(am_signalhandler_unittest_OBJECTS) \
+ $(nodist_signalhandler_unittest_OBJECTS)
+signalhandler_unittest_DEPENDENCIES = libglog.la $(am__DEPENDENCIES_2) \
+ $(am__DEPENDENCIES_2)
+signalhandler_unittest_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CXXLD) \
+ $(signalhandler_unittest_CXXFLAGS) $(CXXFLAGS) \
+ $(signalhandler_unittest_LDFLAGS) $(LDFLAGS) -o $@
+am_stacktrace_unittest_OBJECTS = $(am__objects_1) \
+ stacktrace_unittest-stacktrace_unittest.$(OBJEXT)
+nodist_stacktrace_unittest_OBJECTS = $(am__objects_1)
+stacktrace_unittest_OBJECTS = $(am_stacktrace_unittest_OBJECTS) \
+ $(nodist_stacktrace_unittest_OBJECTS)
+stacktrace_unittest_DEPENDENCIES = libglog.la $(am__DEPENDENCIES_2)
+stacktrace_unittest_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CXXLD) \
+ $(stacktrace_unittest_CXXFLAGS) $(CXXFLAGS) \
+ $(stacktrace_unittest_LDFLAGS) $(LDFLAGS) -o $@
+am_stl_logging_unittest_OBJECTS = $(am__objects_1) \
+ stl_logging_unittest-stl_logging_unittest.$(OBJEXT)
+nodist_stl_logging_unittest_OBJECTS = $(am__objects_1)
+stl_logging_unittest_OBJECTS = $(am_stl_logging_unittest_OBJECTS) \
+ $(nodist_stl_logging_unittest_OBJECTS)
+stl_logging_unittest_DEPENDENCIES = libglog.la $(am__DEPENDENCIES_2) \
+ $(am__DEPENDENCIES_2)
+stl_logging_unittest_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CXXLD) \
+ $(stl_logging_unittest_CXXFLAGS) $(CXXFLAGS) \
+ $(stl_logging_unittest_LDFLAGS) $(LDFLAGS) -o $@
+am_symbolize_unittest_OBJECTS = $(am__objects_1) \
+ symbolize_unittest-symbolize_unittest.$(OBJEXT)
+nodist_symbolize_unittest_OBJECTS = $(am__objects_1)
+symbolize_unittest_OBJECTS = $(am_symbolize_unittest_OBJECTS) \
+ $(nodist_symbolize_unittest_OBJECTS)
+symbolize_unittest_DEPENDENCIES = libglog.la $(am__DEPENDENCIES_2) \
+ $(am__DEPENDENCIES_2)
+symbolize_unittest_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CXXLD) \
+ $(symbolize_unittest_CXXFLAGS) $(CXXFLAGS) \
+ $(symbolize_unittest_LDFLAGS) $(LDFLAGS) -o $@
+am_utilities_unittest_OBJECTS = $(am__objects_1) \
+ utilities_unittest-utilities_unittest.$(OBJEXT)
+nodist_utilities_unittest_OBJECTS = $(am__objects_1)
+utilities_unittest_OBJECTS = $(am_utilities_unittest_OBJECTS) \
+ $(nodist_utilities_unittest_OBJECTS)
+utilities_unittest_DEPENDENCIES = libglog.la $(am__DEPENDENCIES_2) \
+ $(am__DEPENDENCIES_2)
+utilities_unittest_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CXXLD) \
+ $(utilities_unittest_CXXFLAGS) $(CXXFLAGS) \
+ $(utilities_unittest_LDFLAGS) $(LDFLAGS) -o $@
+SCRIPTS = $(noinst_SCRIPTS)
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/src
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+LTCXXCOMPILE = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLD = $(CXX)
+CXXLINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(libglog_la_SOURCES) $(nodist_libglog_la_SOURCES) \
+ $(demangle_unittest_SOURCES) \
+ $(nodist_demangle_unittest_SOURCES) \
+ $(logging_striptest0_SOURCES) \
+ $(nodist_logging_striptest0_SOURCES) \
+ $(logging_striptest10_SOURCES) \
+ $(nodist_logging_striptest10_SOURCES) \
+ $(logging_striptest2_SOURCES) \
+ $(nodist_logging_striptest2_SOURCES) \
+ $(logging_unittest_SOURCES) $(nodist_logging_unittest_SOURCES) \
+ $(mock_log_test_SOURCES) $(nodist_mock_log_test_SOURCES) \
+ $(signalhandler_unittest_SOURCES) \
+ $(nodist_signalhandler_unittest_SOURCES) \
+ $(stacktrace_unittest_SOURCES) \
+ $(nodist_stacktrace_unittest_SOURCES) \
+ $(stl_logging_unittest_SOURCES) \
+ $(nodist_stl_logging_unittest_SOURCES) \
+ $(symbolize_unittest_SOURCES) \
+ $(nodist_symbolize_unittest_SOURCES) \
+ $(utilities_unittest_SOURCES) \
+ $(nodist_utilities_unittest_SOURCES)
+DIST_SOURCES = $(libglog_la_SOURCES) $(demangle_unittest_SOURCES) \
+ $(logging_striptest0_SOURCES) $(logging_striptest10_SOURCES) \
+ $(logging_striptest2_SOURCES) $(logging_unittest_SOURCES) \
+ $(am__mock_log_test_SOURCES_DIST) \
+ $(signalhandler_unittest_SOURCES) \
+ $(stacktrace_unittest_SOURCES) $(stl_logging_unittest_SOURCES) \
+ $(symbolize_unittest_SOURCES) $(utilities_unittest_SOURCES)
+DATA = $(dist_doc_DATA) $(pkgconfig_DATA)
+HEADERS = $(gloginclude_HEADERS) $(nodist_gloginclude_HEADERS) \
+ $(noinst_HEADERS)
+ETAGS = etags
+CTAGS = ctags
+am__tty_colors = \
+red=; grn=; lgn=; blu=; std=
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+distdir = $(PACKAGE)-$(VERSION)
+top_distdir = $(distdir)
+am__remove_distdir = \
+ { test ! -d "$(distdir)" \
+ || { find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \
+ && rm -fr "$(distdir)"; }; }
+DIST_ARCHIVES = $(distdir).tar.gz
+GZIP_ENV = --best
+distuninstallcheck_listfiles = find . -type f -print
+distcleancheck_listfiles = find . -type f -print
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GFLAGS_CFLAGS = @GFLAGS_CFLAGS@
+GFLAGS_LIBS = @GFLAGS_LIBS@
+GMOCK_CFLAGS = @GMOCK_CFLAGS@
+GMOCK_CONFIG = @GMOCK_CONFIG@
+GMOCK_LIBS = @GMOCK_LIBS@
+GREP = @GREP@
+GTEST_CFLAGS = @GTEST_CFLAGS@
+GTEST_CONFIG = @GTEST_CONFIG@
+GTEST_LIBS = @GTEST_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIBTOOL_DEPS = @LIBTOOL_DEPS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PTHREAD_CC = @PTHREAD_CC@
+PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
+PTHREAD_LIBS = @PTHREAD_LIBS@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+UNWIND_LIBS = @UNWIND_LIBS@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+ac_cv___attribute___noreturn = @ac_cv___attribute___noreturn@
+ac_cv___attribute___printf_4_5 = @ac_cv___attribute___printf_4_5@
+ac_cv_cxx_using_operator = @ac_cv_cxx_using_operator@
+ac_cv_have___builtin_expect = @ac_cv_have___builtin_expect@
+ac_cv_have___uint16 = @ac_cv_have___uint16@
+ac_cv_have_inttypes_h = @ac_cv_have_inttypes_h@
+ac_cv_have_libgflags = @ac_cv_have_libgflags@
+ac_cv_have_stdint_h = @ac_cv_have_stdint_h@
+ac_cv_have_systypes_h = @ac_cv_have_systypes_h@
+ac_cv_have_u_int16_t = @ac_cv_have_u_int16_t@
+ac_cv_have_uint16_t = @ac_cv_have_uint16_t@
+ac_cv_have_unistd_h = @ac_cv_have_unistd_h@
+ac_google_end_namespace = @ac_google_end_namespace@
+ac_google_namespace = @ac_google_namespace@
+ac_google_start_namespace = @ac_google_start_namespace@
+acx_pthread_config = @acx_pthread_config@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = $(prefix)/share/doc/$(PACKAGE)-$(VERSION)
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+
+# Make sure that when we re-make ./configure, we get the macros we need
+ACLOCAL_AMFLAGS = -I m4
+
+# This is so we can #include <glog/foo>
+AM_CPPFLAGS = -I$(top_srcdir)/src
+
+# This is mostly based on configure options
+AM_CXXFLAGS = $(am__append_1) $(am__append_2) $(am__append_3)
+glogincludedir = $(includedir)/glog
+gloginclude_HEADERS = src/glog/log_severity.h
+nodist_gloginclude_HEADERS = src/glog/logging.h src/glog/raw_logging.h src/glog/vlog_is_on.h src/glog/stl_logging.h
+noinst_HEADERS = src/glog/logging.h.in src/glog/raw_logging.h.in src/glog/vlog_is_on.h.in src/glog/stl_logging.h.in
+dist_doc_DATA = AUTHORS COPYING ChangeLog INSTALL NEWS README README.windows \
+ doc/designstyle.css doc/glog.html
+
+lib_LTLIBRARIES = libglog.la
+
+# The libraries libglog depends on.
+COMMON_LIBS = $(PTHREAD_LIBS) $(GFLAGS_LIBS) $(UNWIND_LIBS)
+# Compile switches for our unittest.
+TEST_CFLAGS = $(GTEST_CFLAGS) $(GMOCK_CFLAGS) $(GFLAGS_CFLAGS) $(AM_CXXFLAGS)
+# Libraries for our unittest.
+TEST_LIBS = $(GTEST_LIBS) $(GMOCK_LIBS) $(GFLAGS_LIBS)
+TESTS_ENVIRONMENT =
+check_SCRIPTS = logging_striplog_test_sh demangle_unittest_sh \
+ signalhandler_unittest_sh
+# Every time you add a unittest to check_SCRIPTS, add it here too
+noinst_SCRIPTS = src/logging_striplog_test.sh src/demangle_unittest.sh \
+ src/signalhandler_unittest.sh
+# Binaries used for script-based unittests.
+TEST_BINARIES = logging_striptest0 logging_striptest2 \
+ logging_striptest10 signalhandler_unittest
+logging_unittest_SOURCES = $(gloginclude_HEADERS) \
+ src/logging_unittest.cc \
+ src/config_for_unittests.h \
+ src/mock-log.h
+
+nodist_logging_unittest_SOURCES = $(nodist_gloginclude_HEADERS)
+logging_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(TEST_CFLAGS)
+logging_unittest_LDFLAGS = $(PTHREAD_CFLAGS)
+logging_unittest_LDADD = libglog.la $(COMMON_LIBS) $(TEST_LIBS)
+logging_striptest0_SOURCES = $(gloginclude_HEADERS) \
+ src/logging_striptest_main.cc
+
+nodist_logging_striptest0_SOURCES = $(nodist_gloginclude_HEADERS)
+logging_striptest0_CXXFLAGS = $(PTHREAD_CFLAGS) $(TEST_CFLAGS)
+logging_striptest0_LDFLAGS = $(PTHREAD_CFLAGS)
+logging_striptest0_LDADD = libglog.la $(COMMON_LIBS)
+logging_striptest2_SOURCES = $(gloginclude_HEADERS) \
+ src/logging_striptest2.cc
+
+nodist_logging_striptest2_SOURCES = $(nodist_gloginclude_HEADERS)
+logging_striptest2_CXXFLAGS = $(PTHREAD_CFLAGS) $(TEST_CFLAGS)
+logging_striptest2_LDFLAGS = $(PTHREAD_CFLAGS)
+logging_striptest2_LDADD = libglog.la $(COMMON_LIBS)
+logging_striptest10_SOURCES = $(gloginclude_HEADERS) \
+ src/logging_striptest10.cc
+
+nodist_logging_striptest10_SOURCES = $(nodist_gloginclude_HEADERS)
+logging_striptest10_CXXFLAGS = $(PTHREAD_CFLAGS) $(TEST_CFLAGS)
+logging_striptest10_LDFLAGS = $(PTHREAD_CFLAGS)
+logging_striptest10_LDADD = libglog.la $(COMMON_LIBS)
+demangle_unittest_SOURCES = $(gloginclude_HEADERS) \
+ src/demangle_unittest.cc
+
+nodist_demangle_unittest_SOURCES = $(nodist_gloginclude_HEADERS)
+demangle_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(TEST_CFLAGS)
+demangle_unittest_LDFLAGS = $(PTHREAD_CFLAGS)
+demangle_unittest_LDADD = libglog.la $(COMMON_LIBS) $(TEST_LIBS)
+stacktrace_unittest_SOURCES = $(gloginclude_HEADERS) \
+ src/stacktrace_unittest.cc
+
+nodist_stacktrace_unittest_SOURCES = $(nodist_gloginclude_HEADERS)
+stacktrace_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(TEST_CFLAGS)
+stacktrace_unittest_LDFLAGS = $(PTHREAD_CFLAGS)
+stacktrace_unittest_LDADD = libglog.la $(COMMON_LIBS)
+symbolize_unittest_SOURCES = $(gloginclude_HEADERS) \
+ src/symbolize_unittest.cc
+
+nodist_symbolize_unittest_SOURCES = $(nodist_gloginclude_HEADERS)
+symbolize_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(TEST_CFLAGS)
+symbolize_unittest_LDFLAGS = $(PTHREAD_CFLAGS)
+symbolize_unittest_LDADD = libglog.la $(COMMON_LIBS) $(TEST_LIBS)
+stl_logging_unittest_SOURCES = $(gloginclude_HEADERS) \
+ src/stl_logging_unittest.cc
+
+nodist_stl_logging_unittest_SOURCES = $(nodist_gloginclude_HEADERS)
+stl_logging_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(TEST_CFLAGS)
+stl_logging_unittest_LDFLAGS = $(PTHREAD_CFLAGS)
+stl_logging_unittest_LDADD = libglog.la $(COMMON_LIBS) $(TEST_LIBS)
+signalhandler_unittest_SOURCES = $(gloginclude_HEADERS) \
+ src/signalhandler_unittest.cc
+
+nodist_signalhandler_unittest_SOURCES = $(nodist_gloginclude_HEADERS)
+signalhandler_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(TEST_CFLAGS)
+signalhandler_unittest_LDFLAGS = $(PTHREAD_CFLAGS)
+signalhandler_unittest_LDADD = libglog.la $(COMMON_LIBS) $(TEST_LIBS)
+utilities_unittest_SOURCES = $(gloginclude_HEADERS) \
+ src/utilities_unittest.cc
+
+nodist_utilities_unittest_SOURCES = $(nodist_gloginclude_HEADERS)
+utilities_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(TEST_CFLAGS)
+utilities_unittest_LDFLAGS = $(PTHREAD_CFLAGS)
+utilities_unittest_LDADD = libglog.la $(COMMON_LIBS) $(TEST_LIBS)
+@HAVE_GMOCK_TRUE@mock_log_test_SOURCES = $(gloginclude_HEADERS) \
+@HAVE_GMOCK_TRUE@ src/mock-log_test.cc
+
+@HAVE_GMOCK_TRUE@nodist_mock_log_test_SOURCES = $(nodist_gloginclude_HEADERS)
+@HAVE_GMOCK_TRUE@mock_log_test_CXXFLAGS = $(PTHREAD_CFLAGS) $(TEST_CFLAGS)
+@HAVE_GMOCK_TRUE@mock_log_test_LDFLAGS = $(PTHREAD_CFLAGS)
+@HAVE_GMOCK_TRUE@mock_log_test_LDADD = libglog.la $(COMMON_LIBS) $(TEST_LIBS)
+libglog_la_SOURCES = $(gloginclude_HEADERS) \
+ src/logging.cc src/raw_logging.cc src/vlog_is_on.cc \
+ src/utilities.cc src/utilities.h \
+ src/demangle.cc src/demangle.h \
+ src/stacktrace.h \
+ src/stacktrace_generic-inl.h \
+ src/stacktrace_libunwind-inl.h \
+ src/stacktrace_powerpc-inl.h \
+ src/stacktrace_x86-inl.h \
+ src/stacktrace_x86_64-inl.h \
+ src/symbolize.cc src/symbolize.h \
+ src/signalhandler.cc \
+ src/base/mutex.h src/base/googleinit.h \
+ src/base/commandlineflags.h src/googletest.h
+
+nodist_libglog_la_SOURCES = $(nodist_gloginclude_HEADERS)
+libglog_la_CXXFLAGS = $(PTRHEAD_CFLAGS) $(GFLAGS_CFLAGS) $(AM_CXXFLAGS) -DNDEBUG
+libglog_la_LDFLAGS = $(PTRHEAD_CFLAGS) $(GFLAGS_LDFLAGS)
+libglog_la_LIBADD = $(COMMON_LIBS)
+WINDOWS_PROJECTS = google-glog.sln vsprojects/libglog/libglog.vcproj \
+ vsprojects/logging_unittest/logging_unittest.vcproj \
+ vsprojects/libglog_static/libglog_static.vcproj \
+ vsprojects/logging_unittest_static/logging_unittest_static.vcproj
+EXTRA_DIST = packages/rpm.sh packages/rpm/rpm.spec packages/deb.sh packages/deb \
+ $(SCRIPTS) src/logging_unittest.err src/demangle_unittest.txt \
+ src/windows/config.h src/windows/port.h src/windows/port.cc \
+ src/windows/preprocess.sh \
+ src/windows/glog/log_severity.h src/windows/glog/logging.h \
+ src/windows/glog/raw_logging.h src/windows/glog/stl_logging.h \
+ src/windows/glog/vlog_is_on.h \
+ $(WINDOWS_PROJECTS)
+
+CLEANFILES = core demangle.dm demangle.nm signalhandler.out* \
+ signalhandler_unittest.*.log.INFO.*
+
+
+# Add pkgconfig file
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = libglog.pc
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .cc .lo .o .obj
+am--refresh:
+ @:
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ echo ' cd $(srcdir) && $(AUTOMAKE) --gnu'; \
+ $(am__cd) $(srcdir) && $(AUTOMAKE) --gnu \
+ && exit 0; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ echo ' $(SHELL) ./config.status'; \
+ $(SHELL) ./config.status;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ $(SHELL) ./config.status --recheck
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ $(am__cd) $(srcdir) && $(AUTOCONF)
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)
+$(am__aclocal_m4_deps):
+
+src/config.h: src/stamp-h1
+ @if test ! -f $@; then \
+ rm -f src/stamp-h1; \
+ $(MAKE) $(AM_MAKEFLAGS) src/stamp-h1; \
+ else :; fi
+
+src/stamp-h1: $(top_srcdir)/src/config.h.in $(top_builddir)/config.status
+ @rm -f src/stamp-h1
+ cd $(top_builddir) && $(SHELL) ./config.status src/config.h
+$(top_srcdir)/src/config.h.in: $(am__configure_deps)
+ ($(am__cd) $(top_srcdir) && $(AUTOHEADER))
+ rm -f src/stamp-h1
+ touch $@
+
+distclean-hdr:
+ -rm -f src/config.h src/stamp-h1
+src/glog/logging.h: $(top_builddir)/config.status $(top_srcdir)/src/glog/logging.h.in
+ cd $(top_builddir) && $(SHELL) ./config.status $@
+src/glog/raw_logging.h: $(top_builddir)/config.status $(top_srcdir)/src/glog/raw_logging.h.in
+ cd $(top_builddir) && $(SHELL) ./config.status $@
+src/glog/vlog_is_on.h: $(top_builddir)/config.status $(top_srcdir)/src/glog/vlog_is_on.h.in
+ cd $(top_builddir) && $(SHELL) ./config.status $@
+src/glog/stl_logging.h: $(top_builddir)/config.status $(top_srcdir)/src/glog/stl_logging.h.in
+ cd $(top_builddir) && $(SHELL) ./config.status $@
+libglog.pc: $(top_builddir)/config.status $(srcdir)/libglog.pc.in
+ cd $(top_builddir) && $(SHELL) ./config.status $@
+install-libLTLIBRARIES: $(lib_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)"
+ @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \
+ }
+
+uninstall-libLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
+ for p in $$list; do \
+ $(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \
+ done
+
+clean-libLTLIBRARIES:
+ -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
+ @list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libglog.la: $(libglog_la_OBJECTS) $(libglog_la_DEPENDENCIES)
+ $(libglog_la_LINK) -rpath $(libdir) $(libglog_la_OBJECTS) $(libglog_la_LIBADD) $(LIBS)
+
+clean-noinstPROGRAMS:
+ @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \
+ echo " rm -f" $$list; \
+ rm -f $$list || exit $$?; \
+ test -n "$(EXEEXT)" || exit 0; \
+ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f" $$list; \
+ rm -f $$list
+demangle_unittest$(EXEEXT): $(demangle_unittest_OBJECTS) $(demangle_unittest_DEPENDENCIES)
+ @rm -f demangle_unittest$(EXEEXT)
+ $(demangle_unittest_LINK) $(demangle_unittest_OBJECTS) $(demangle_unittest_LDADD) $(LIBS)
+logging_striptest0$(EXEEXT): $(logging_striptest0_OBJECTS) $(logging_striptest0_DEPENDENCIES)
+ @rm -f logging_striptest0$(EXEEXT)
+ $(logging_striptest0_LINK) $(logging_striptest0_OBJECTS) $(logging_striptest0_LDADD) $(LIBS)
+logging_striptest10$(EXEEXT): $(logging_striptest10_OBJECTS) $(logging_striptest10_DEPENDENCIES)
+ @rm -f logging_striptest10$(EXEEXT)
+ $(logging_striptest10_LINK) $(logging_striptest10_OBJECTS) $(logging_striptest10_LDADD) $(LIBS)
+logging_striptest2$(EXEEXT): $(logging_striptest2_OBJECTS) $(logging_striptest2_DEPENDENCIES)
+ @rm -f logging_striptest2$(EXEEXT)
+ $(logging_striptest2_LINK) $(logging_striptest2_OBJECTS) $(logging_striptest2_LDADD) $(LIBS)
+logging_unittest$(EXEEXT): $(logging_unittest_OBJECTS) $(logging_unittest_DEPENDENCIES)
+ @rm -f logging_unittest$(EXEEXT)
+ $(logging_unittest_LINK) $(logging_unittest_OBJECTS) $(logging_unittest_LDADD) $(LIBS)
+mock_log_test$(EXEEXT): $(mock_log_test_OBJECTS) $(mock_log_test_DEPENDENCIES)
+ @rm -f mock_log_test$(EXEEXT)
+ $(mock_log_test_LINK) $(mock_log_test_OBJECTS) $(mock_log_test_LDADD) $(LIBS)
+signalhandler_unittest$(EXEEXT): $(signalhandler_unittest_OBJECTS) $(signalhandler_unittest_DEPENDENCIES)
+ @rm -f signalhandler_unittest$(EXEEXT)
+ $(signalhandler_unittest_LINK) $(signalhandler_unittest_OBJECTS) $(signalhandler_unittest_LDADD) $(LIBS)
+stacktrace_unittest$(EXEEXT): $(stacktrace_unittest_OBJECTS) $(stacktrace_unittest_DEPENDENCIES)
+ @rm -f stacktrace_unittest$(EXEEXT)
+ $(stacktrace_unittest_LINK) $(stacktrace_unittest_OBJECTS) $(stacktrace_unittest_LDADD) $(LIBS)
+stl_logging_unittest$(EXEEXT): $(stl_logging_unittest_OBJECTS) $(stl_logging_unittest_DEPENDENCIES)
+ @rm -f stl_logging_unittest$(EXEEXT)
+ $(stl_logging_unittest_LINK) $(stl_logging_unittest_OBJECTS) $(stl_logging_unittest_LDADD) $(LIBS)
+symbolize_unittest$(EXEEXT): $(symbolize_unittest_OBJECTS) $(symbolize_unittest_DEPENDENCIES)
+ @rm -f symbolize_unittest$(EXEEXT)
+ $(symbolize_unittest_LINK) $(symbolize_unittest_OBJECTS) $(symbolize_unittest_LDADD) $(LIBS)
+utilities_unittest$(EXEEXT): $(utilities_unittest_OBJECTS) $(utilities_unittest_DEPENDENCIES)
+ @rm -f utilities_unittest$(EXEEXT)
+ $(utilities_unittest_LINK) $(utilities_unittest_OBJECTS) $(utilities_unittest_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/demangle_unittest-demangle_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglog_la-demangle.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglog_la-logging.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglog_la-raw_logging.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglog_la-signalhandler.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglog_la-symbolize.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglog_la-utilities.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglog_la-vlog_is_on.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/logging_striptest0-logging_striptest_main.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/logging_striptest10-logging_striptest10.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/logging_striptest2-logging_striptest2.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/logging_unittest-logging_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mock_log_test-mock-log_test.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/signalhandler_unittest-signalhandler_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stacktrace_unittest-stacktrace_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stl_logging_unittest-stl_logging_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/symbolize_unittest-symbolize_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/utilities_unittest-utilities_unittest.Po@am__quote@
+
+.cc.o:
+@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $<
+
+.cc.obj:
+@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.cc.lo:
+@am__fastdepCXX_TRUE@ $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LTCXXCOMPILE) -c -o $@ $<
+
+libglog_la-logging.lo: src/logging.cc
+@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libglog_la_CXXFLAGS) $(CXXFLAGS) -MT libglog_la-logging.lo -MD -MP -MF $(DEPDIR)/libglog_la-logging.Tpo -c -o libglog_la-logging.lo `test -f 'src/logging.cc' || echo '$(srcdir)/'`src/logging.cc
+@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/libglog_la-logging.Tpo $(DEPDIR)/libglog_la-logging.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/logging.cc' object='libglog_la-logging.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libglog_la_CXXFLAGS) $(CXXFLAGS) -c -o libglog_la-logging.lo `test -f 'src/logging.cc' || echo '$(srcdir)/'`src/logging.cc
+
+libglog_la-raw_logging.lo: src/raw_logging.cc
+@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libglog_la_CXXFLAGS) $(CXXFLAGS) -MT libglog_la-raw_logging.lo -MD -MP -MF $(DEPDIR)/libglog_la-raw_logging.Tpo -c -o libglog_la-raw_logging.lo `test -f 'src/raw_logging.cc' || echo '$(srcdir)/'`src/raw_logging.cc
+@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/libglog_la-raw_logging.Tpo $(DEPDIR)/libglog_la-raw_logging.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/raw_logging.cc' object='libglog_la-raw_logging.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libglog_la_CXXFLAGS) $(CXXFLAGS) -c -o libglog_la-raw_logging.lo `test -f 'src/raw_logging.cc' || echo '$(srcdir)/'`src/raw_logging.cc
+
+libglog_la-vlog_is_on.lo: src/vlog_is_on.cc
+@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libglog_la_CXXFLAGS) $(CXXFLAGS) -MT libglog_la-vlog_is_on.lo -MD -MP -MF $(DEPDIR)/libglog_la-vlog_is_on.Tpo -c -o libglog_la-vlog_is_on.lo `test -f 'src/vlog_is_on.cc' || echo '$(srcdir)/'`src/vlog_is_on.cc
+@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/libglog_la-vlog_is_on.Tpo $(DEPDIR)/libglog_la-vlog_is_on.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/vlog_is_on.cc' object='libglog_la-vlog_is_on.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libglog_la_CXXFLAGS) $(CXXFLAGS) -c -o libglog_la-vlog_is_on.lo `test -f 'src/vlog_is_on.cc' || echo '$(srcdir)/'`src/vlog_is_on.cc
+
+libglog_la-utilities.lo: src/utilities.cc
+@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libglog_la_CXXFLAGS) $(CXXFLAGS) -MT libglog_la-utilities.lo -MD -MP -MF $(DEPDIR)/libglog_la-utilities.Tpo -c -o libglog_la-utilities.lo `test -f 'src/utilities.cc' || echo '$(srcdir)/'`src/utilities.cc
+@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/libglog_la-utilities.Tpo $(DEPDIR)/libglog_la-utilities.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/utilities.cc' object='libglog_la-utilities.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libglog_la_CXXFLAGS) $(CXXFLAGS) -c -o libglog_la-utilities.lo `test -f 'src/utilities.cc' || echo '$(srcdir)/'`src/utilities.cc
+
+libglog_la-demangle.lo: src/demangle.cc
+@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libglog_la_CXXFLAGS) $(CXXFLAGS) -MT libglog_la-demangle.lo -MD -MP -MF $(DEPDIR)/libglog_la-demangle.Tpo -c -o libglog_la-demangle.lo `test -f 'src/demangle.cc' || echo '$(srcdir)/'`src/demangle.cc
+@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/libglog_la-demangle.Tpo $(DEPDIR)/libglog_la-demangle.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/demangle.cc' object='libglog_la-demangle.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libglog_la_CXXFLAGS) $(CXXFLAGS) -c -o libglog_la-demangle.lo `test -f 'src/demangle.cc' || echo '$(srcdir)/'`src/demangle.cc
+
+libglog_la-symbolize.lo: src/symbolize.cc
+@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libglog_la_CXXFLAGS) $(CXXFLAGS) -MT libglog_la-symbolize.lo -MD -MP -MF $(DEPDIR)/libglog_la-symbolize.Tpo -c -o libglog_la-symbolize.lo `test -f 'src/symbolize.cc' || echo '$(srcdir)/'`src/symbolize.cc
+@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/libglog_la-symbolize.Tpo $(DEPDIR)/libglog_la-symbolize.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/symbolize.cc' object='libglog_la-symbolize.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libglog_la_CXXFLAGS) $(CXXFLAGS) -c -o libglog_la-symbolize.lo `test -f 'src/symbolize.cc' || echo '$(srcdir)/'`src/symbolize.cc
+
+libglog_la-signalhandler.lo: src/signalhandler.cc
+@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libglog_la_CXXFLAGS) $(CXXFLAGS) -MT libglog_la-signalhandler.lo -MD -MP -MF $(DEPDIR)/libglog_la-signalhandler.Tpo -c -o libglog_la-signalhandler.lo `test -f 'src/signalhandler.cc' || echo '$(srcdir)/'`src/signalhandler.cc
+@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/libglog_la-signalhandler.Tpo $(DEPDIR)/libglog_la-signalhandler.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/signalhandler.cc' object='libglog_la-signalhandler.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libglog_la_CXXFLAGS) $(CXXFLAGS) -c -o libglog_la-signalhandler.lo `test -f 'src/signalhandler.cc' || echo '$(srcdir)/'`src/signalhandler.cc
+
+demangle_unittest-demangle_unittest.o: src/demangle_unittest.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(demangle_unittest_CXXFLAGS) $(CXXFLAGS) -MT demangle_unittest-demangle_unittest.o -MD -MP -MF $(DEPDIR)/demangle_unittest-demangle_unittest.Tpo -c -o demangle_unittest-demangle_unittest.o `test -f 'src/demangle_unittest.cc' || echo '$(srcdir)/'`src/demangle_unittest.cc
+@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/demangle_unittest-demangle_unittest.Tpo $(DEPDIR)/demangle_unittest-demangle_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/demangle_unittest.cc' object='demangle_unittest-demangle_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(demangle_unittest_CXXFLAGS) $(CXXFLAGS) -c -o demangle_unittest-demangle_unittest.o `test -f 'src/demangle_unittest.cc' || echo '$(srcdir)/'`src/demangle_unittest.cc
+
+demangle_unittest-demangle_unittest.obj: src/demangle_unittest.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(demangle_unittest_CXXFLAGS) $(CXXFLAGS) -MT demangle_unittest-demangle_unittest.obj -MD -MP -MF $(DEPDIR)/demangle_unittest-demangle_unittest.Tpo -c -o demangle_unittest-demangle_unittest.obj `if test -f 'src/demangle_unittest.cc'; then $(CYGPATH_W) 'src/demangle_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/demangle_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/demangle_unittest-demangle_unittest.Tpo $(DEPDIR)/demangle_unittest-demangle_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/demangle_unittest.cc' object='demangle_unittest-demangle_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(demangle_unittest_CXXFLAGS) $(CXXFLAGS) -c -o demangle_unittest-demangle_unittest.obj `if test -f 'src/demangle_unittest.cc'; then $(CYGPATH_W) 'src/demangle_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/demangle_unittest.cc'; fi`
+
+logging_striptest0-logging_striptest_main.o: src/logging_striptest_main.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(logging_striptest0_CXXFLAGS) $(CXXFLAGS) -MT logging_striptest0-logging_striptest_main.o -MD -MP -MF $(DEPDIR)/logging_striptest0-logging_striptest_main.Tpo -c -o logging_striptest0-logging_striptest_main.o `test -f 'src/logging_striptest_main.cc' || echo '$(srcdir)/'`src/logging_striptest_main.cc
+@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/logging_striptest0-logging_striptest_main.Tpo $(DEPDIR)/logging_striptest0-logging_striptest_main.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/logging_striptest_main.cc' object='logging_striptest0-logging_striptest_main.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(logging_striptest0_CXXFLAGS) $(CXXFLAGS) -c -o logging_striptest0-logging_striptest_main.o `test -f 'src/logging_striptest_main.cc' || echo '$(srcdir)/'`src/logging_striptest_main.cc
+
+logging_striptest0-logging_striptest_main.obj: src/logging_striptest_main.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(logging_striptest0_CXXFLAGS) $(CXXFLAGS) -MT logging_striptest0-logging_striptest_main.obj -MD -MP -MF $(DEPDIR)/logging_striptest0-logging_striptest_main.Tpo -c -o logging_striptest0-logging_striptest_main.obj `if test -f 'src/logging_striptest_main.cc'; then $(CYGPATH_W) 'src/logging_striptest_main.cc'; else $(CYGPATH_W) '$(srcdir)/src/logging_striptest_main.cc'; fi`
+@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/logging_striptest0-logging_striptest_main.Tpo $(DEPDIR)/logging_striptest0-logging_striptest_main.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/logging_striptest_main.cc' object='logging_striptest0-logging_striptest_main.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(logging_striptest0_CXXFLAGS) $(CXXFLAGS) -c -o logging_striptest0-logging_striptest_main.obj `if test -f 'src/logging_striptest_main.cc'; then $(CYGPATH_W) 'src/logging_striptest_main.cc'; else $(CYGPATH_W) '$(srcdir)/src/logging_striptest_main.cc'; fi`
+
+logging_striptest10-logging_striptest10.o: src/logging_striptest10.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(logging_striptest10_CXXFLAGS) $(CXXFLAGS) -MT logging_striptest10-logging_striptest10.o -MD -MP -MF $(DEPDIR)/logging_striptest10-logging_striptest10.Tpo -c -o logging_striptest10-logging_striptest10.o `test -f 'src/logging_striptest10.cc' || echo '$(srcdir)/'`src/logging_striptest10.cc
+@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/logging_striptest10-logging_striptest10.Tpo $(DEPDIR)/logging_striptest10-logging_striptest10.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/logging_striptest10.cc' object='logging_striptest10-logging_striptest10.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(logging_striptest10_CXXFLAGS) $(CXXFLAGS) -c -o logging_striptest10-logging_striptest10.o `test -f 'src/logging_striptest10.cc' || echo '$(srcdir)/'`src/logging_striptest10.cc
+
+logging_striptest10-logging_striptest10.obj: src/logging_striptest10.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(logging_striptest10_CXXFLAGS) $(CXXFLAGS) -MT logging_striptest10-logging_striptest10.obj -MD -MP -MF $(DEPDIR)/logging_striptest10-logging_striptest10.Tpo -c -o logging_striptest10-logging_striptest10.obj `if test -f 'src/logging_striptest10.cc'; then $(CYGPATH_W) 'src/logging_striptest10.cc'; else $(CYGPATH_W) '$(srcdir)/src/logging_striptest10.cc'; fi`
+@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/logging_striptest10-logging_striptest10.Tpo $(DEPDIR)/logging_striptest10-logging_striptest10.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/logging_striptest10.cc' object='logging_striptest10-logging_striptest10.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(logging_striptest10_CXXFLAGS) $(CXXFLAGS) -c -o logging_striptest10-logging_striptest10.obj `if test -f 'src/logging_striptest10.cc'; then $(CYGPATH_W) 'src/logging_striptest10.cc'; else $(CYGPATH_W) '$(srcdir)/src/logging_striptest10.cc'; fi`
+
+logging_striptest2-logging_striptest2.o: src/logging_striptest2.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(logging_striptest2_CXXFLAGS) $(CXXFLAGS) -MT logging_striptest2-logging_striptest2.o -MD -MP -MF $(DEPDIR)/logging_striptest2-logging_striptest2.Tpo -c -o logging_striptest2-logging_striptest2.o `test -f 'src/logging_striptest2.cc' || echo '$(srcdir)/'`src/logging_striptest2.cc
+@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/logging_striptest2-logging_striptest2.Tpo $(DEPDIR)/logging_striptest2-logging_striptest2.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/logging_striptest2.cc' object='logging_striptest2-logging_striptest2.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(logging_striptest2_CXXFLAGS) $(CXXFLAGS) -c -o logging_striptest2-logging_striptest2.o `test -f 'src/logging_striptest2.cc' || echo '$(srcdir)/'`src/logging_striptest2.cc
+
+logging_striptest2-logging_striptest2.obj: src/logging_striptest2.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(logging_striptest2_CXXFLAGS) $(CXXFLAGS) -MT logging_striptest2-logging_striptest2.obj -MD -MP -MF $(DEPDIR)/logging_striptest2-logging_striptest2.Tpo -c -o logging_striptest2-logging_striptest2.obj `if test -f 'src/logging_striptest2.cc'; then $(CYGPATH_W) 'src/logging_striptest2.cc'; else $(CYGPATH_W) '$(srcdir)/src/logging_striptest2.cc'; fi`
+@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/logging_striptest2-logging_striptest2.Tpo $(DEPDIR)/logging_striptest2-logging_striptest2.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/logging_striptest2.cc' object='logging_striptest2-logging_striptest2.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(logging_striptest2_CXXFLAGS) $(CXXFLAGS) -c -o logging_striptest2-logging_striptest2.obj `if test -f 'src/logging_striptest2.cc'; then $(CYGPATH_W) 'src/logging_striptest2.cc'; else $(CYGPATH_W) '$(srcdir)/src/logging_striptest2.cc'; fi`
+
+logging_unittest-logging_unittest.o: src/logging_unittest.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(logging_unittest_CXXFLAGS) $(CXXFLAGS) -MT logging_unittest-logging_unittest.o -MD -MP -MF $(DEPDIR)/logging_unittest-logging_unittest.Tpo -c -o logging_unittest-logging_unittest.o `test -f 'src/logging_unittest.cc' || echo '$(srcdir)/'`src/logging_unittest.cc
+@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/logging_unittest-logging_unittest.Tpo $(DEPDIR)/logging_unittest-logging_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/logging_unittest.cc' object='logging_unittest-logging_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(logging_unittest_CXXFLAGS) $(CXXFLAGS) -c -o logging_unittest-logging_unittest.o `test -f 'src/logging_unittest.cc' || echo '$(srcdir)/'`src/logging_unittest.cc
+
+logging_unittest-logging_unittest.obj: src/logging_unittest.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(logging_unittest_CXXFLAGS) $(CXXFLAGS) -MT logging_unittest-logging_unittest.obj -MD -MP -MF $(DEPDIR)/logging_unittest-logging_unittest.Tpo -c -o logging_unittest-logging_unittest.obj `if test -f 'src/logging_unittest.cc'; then $(CYGPATH_W) 'src/logging_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/logging_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/logging_unittest-logging_unittest.Tpo $(DEPDIR)/logging_unittest-logging_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/logging_unittest.cc' object='logging_unittest-logging_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(logging_unittest_CXXFLAGS) $(CXXFLAGS) -c -o logging_unittest-logging_unittest.obj `if test -f 'src/logging_unittest.cc'; then $(CYGPATH_W) 'src/logging_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/logging_unittest.cc'; fi`
+
+mock_log_test-mock-log_test.o: src/mock-log_test.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(mock_log_test_CXXFLAGS) $(CXXFLAGS) -MT mock_log_test-mock-log_test.o -MD -MP -MF $(DEPDIR)/mock_log_test-mock-log_test.Tpo -c -o mock_log_test-mock-log_test.o `test -f 'src/mock-log_test.cc' || echo '$(srcdir)/'`src/mock-log_test.cc
+@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/mock_log_test-mock-log_test.Tpo $(DEPDIR)/mock_log_test-mock-log_test.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/mock-log_test.cc' object='mock_log_test-mock-log_test.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(mock_log_test_CXXFLAGS) $(CXXFLAGS) -c -o mock_log_test-mock-log_test.o `test -f 'src/mock-log_test.cc' || echo '$(srcdir)/'`src/mock-log_test.cc
+
+mock_log_test-mock-log_test.obj: src/mock-log_test.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(mock_log_test_CXXFLAGS) $(CXXFLAGS) -MT mock_log_test-mock-log_test.obj -MD -MP -MF $(DEPDIR)/mock_log_test-mock-log_test.Tpo -c -o mock_log_test-mock-log_test.obj `if test -f 'src/mock-log_test.cc'; then $(CYGPATH_W) 'src/mock-log_test.cc'; else $(CYGPATH_W) '$(srcdir)/src/mock-log_test.cc'; fi`
+@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/mock_log_test-mock-log_test.Tpo $(DEPDIR)/mock_log_test-mock-log_test.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/mock-log_test.cc' object='mock_log_test-mock-log_test.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(mock_log_test_CXXFLAGS) $(CXXFLAGS) -c -o mock_log_test-mock-log_test.obj `if test -f 'src/mock-log_test.cc'; then $(CYGPATH_W) 'src/mock-log_test.cc'; else $(CYGPATH_W) '$(srcdir)/src/mock-log_test.cc'; fi`
+
+signalhandler_unittest-signalhandler_unittest.o: src/signalhandler_unittest.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(signalhandler_unittest_CXXFLAGS) $(CXXFLAGS) -MT signalhandler_unittest-signalhandler_unittest.o -MD -MP -MF $(DEPDIR)/signalhandler_unittest-signalhandler_unittest.Tpo -c -o signalhandler_unittest-signalhandler_unittest.o `test -f 'src/signalhandler_unittest.cc' || echo '$(srcdir)/'`src/signalhandler_unittest.cc
+@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/signalhandler_unittest-signalhandler_unittest.Tpo $(DEPDIR)/signalhandler_unittest-signalhandler_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/signalhandler_unittest.cc' object='signalhandler_unittest-signalhandler_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(signalhandler_unittest_CXXFLAGS) $(CXXFLAGS) -c -o signalhandler_unittest-signalhandler_unittest.o `test -f 'src/signalhandler_unittest.cc' || echo '$(srcdir)/'`src/signalhandler_unittest.cc
+
+signalhandler_unittest-signalhandler_unittest.obj: src/signalhandler_unittest.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(signalhandler_unittest_CXXFLAGS) $(CXXFLAGS) -MT signalhandler_unittest-signalhandler_unittest.obj -MD -MP -MF $(DEPDIR)/signalhandler_unittest-signalhandler_unittest.Tpo -c -o signalhandler_unittest-signalhandler_unittest.obj `if test -f 'src/signalhandler_unittest.cc'; then $(CYGPATH_W) 'src/signalhandler_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/signalhandler_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/signalhandler_unittest-signalhandler_unittest.Tpo $(DEPDIR)/signalhandler_unittest-signalhandler_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/signalhandler_unittest.cc' object='signalhandler_unittest-signalhandler_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(signalhandler_unittest_CXXFLAGS) $(CXXFLAGS) -c -o signalhandler_unittest-signalhandler_unittest.obj `if test -f 'src/signalhandler_unittest.cc'; then $(CYGPATH_W) 'src/signalhandler_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/signalhandler_unittest.cc'; fi`
+
+stacktrace_unittest-stacktrace_unittest.o: src/stacktrace_unittest.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stacktrace_unittest_CXXFLAGS) $(CXXFLAGS) -MT stacktrace_unittest-stacktrace_unittest.o -MD -MP -MF $(DEPDIR)/stacktrace_unittest-stacktrace_unittest.Tpo -c -o stacktrace_unittest-stacktrace_unittest.o `test -f 'src/stacktrace_unittest.cc' || echo '$(srcdir)/'`src/stacktrace_unittest.cc
+@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/stacktrace_unittest-stacktrace_unittest.Tpo $(DEPDIR)/stacktrace_unittest-stacktrace_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/stacktrace_unittest.cc' object='stacktrace_unittest-stacktrace_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stacktrace_unittest_CXXFLAGS) $(CXXFLAGS) -c -o stacktrace_unittest-stacktrace_unittest.o `test -f 'src/stacktrace_unittest.cc' || echo '$(srcdir)/'`src/stacktrace_unittest.cc
+
+stacktrace_unittest-stacktrace_unittest.obj: src/stacktrace_unittest.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stacktrace_unittest_CXXFLAGS) $(CXXFLAGS) -MT stacktrace_unittest-stacktrace_unittest.obj -MD -MP -MF $(DEPDIR)/stacktrace_unittest-stacktrace_unittest.Tpo -c -o stacktrace_unittest-stacktrace_unittest.obj `if test -f 'src/stacktrace_unittest.cc'; then $(CYGPATH_W) 'src/stacktrace_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/stacktrace_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/stacktrace_unittest-stacktrace_unittest.Tpo $(DEPDIR)/stacktrace_unittest-stacktrace_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/stacktrace_unittest.cc' object='stacktrace_unittest-stacktrace_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stacktrace_unittest_CXXFLAGS) $(CXXFLAGS) -c -o stacktrace_unittest-stacktrace_unittest.obj `if test -f 'src/stacktrace_unittest.cc'; then $(CYGPATH_W) 'src/stacktrace_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/stacktrace_unittest.cc'; fi`
+
+stl_logging_unittest-stl_logging_unittest.o: src/stl_logging_unittest.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stl_logging_unittest_CXXFLAGS) $(CXXFLAGS) -MT stl_logging_unittest-stl_logging_unittest.o -MD -MP -MF $(DEPDIR)/stl_logging_unittest-stl_logging_unittest.Tpo -c -o stl_logging_unittest-stl_logging_unittest.o `test -f 'src/stl_logging_unittest.cc' || echo '$(srcdir)/'`src/stl_logging_unittest.cc
+@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/stl_logging_unittest-stl_logging_unittest.Tpo $(DEPDIR)/stl_logging_unittest-stl_logging_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/stl_logging_unittest.cc' object='stl_logging_unittest-stl_logging_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stl_logging_unittest_CXXFLAGS) $(CXXFLAGS) -c -o stl_logging_unittest-stl_logging_unittest.o `test -f 'src/stl_logging_unittest.cc' || echo '$(srcdir)/'`src/stl_logging_unittest.cc
+
+stl_logging_unittest-stl_logging_unittest.obj: src/stl_logging_unittest.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stl_logging_unittest_CXXFLAGS) $(CXXFLAGS) -MT stl_logging_unittest-stl_logging_unittest.obj -MD -MP -MF $(DEPDIR)/stl_logging_unittest-stl_logging_unittest.Tpo -c -o stl_logging_unittest-stl_logging_unittest.obj `if test -f 'src/stl_logging_unittest.cc'; then $(CYGPATH_W) 'src/stl_logging_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/stl_logging_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/stl_logging_unittest-stl_logging_unittest.Tpo $(DEPDIR)/stl_logging_unittest-stl_logging_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/stl_logging_unittest.cc' object='stl_logging_unittest-stl_logging_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stl_logging_unittest_CXXFLAGS) $(CXXFLAGS) -c -o stl_logging_unittest-stl_logging_unittest.obj `if test -f 'src/stl_logging_unittest.cc'; then $(CYGPATH_W) 'src/stl_logging_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/stl_logging_unittest.cc'; fi`
+
+symbolize_unittest-symbolize_unittest.o: src/symbolize_unittest.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(symbolize_unittest_CXXFLAGS) $(CXXFLAGS) -MT symbolize_unittest-symbolize_unittest.o -MD -MP -MF $(DEPDIR)/symbolize_unittest-symbolize_unittest.Tpo -c -o symbolize_unittest-symbolize_unittest.o `test -f 'src/symbolize_unittest.cc' || echo '$(srcdir)/'`src/symbolize_unittest.cc
+@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/symbolize_unittest-symbolize_unittest.Tpo $(DEPDIR)/symbolize_unittest-symbolize_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/symbolize_unittest.cc' object='symbolize_unittest-symbolize_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(symbolize_unittest_CXXFLAGS) $(CXXFLAGS) -c -o symbolize_unittest-symbolize_unittest.o `test -f 'src/symbolize_unittest.cc' || echo '$(srcdir)/'`src/symbolize_unittest.cc
+
+symbolize_unittest-symbolize_unittest.obj: src/symbolize_unittest.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(symbolize_unittest_CXXFLAGS) $(CXXFLAGS) -MT symbolize_unittest-symbolize_unittest.obj -MD -MP -MF $(DEPDIR)/symbolize_unittest-symbolize_unittest.Tpo -c -o symbolize_unittest-symbolize_unittest.obj `if test -f 'src/symbolize_unittest.cc'; then $(CYGPATH_W) 'src/symbolize_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/symbolize_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/symbolize_unittest-symbolize_unittest.Tpo $(DEPDIR)/symbolize_unittest-symbolize_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/symbolize_unittest.cc' object='symbolize_unittest-symbolize_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(symbolize_unittest_CXXFLAGS) $(CXXFLAGS) -c -o symbolize_unittest-symbolize_unittest.obj `if test -f 'src/symbolize_unittest.cc'; then $(CYGPATH_W) 'src/symbolize_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/symbolize_unittest.cc'; fi`
+
+utilities_unittest-utilities_unittest.o: src/utilities_unittest.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(utilities_unittest_CXXFLAGS) $(CXXFLAGS) -MT utilities_unittest-utilities_unittest.o -MD -MP -MF $(DEPDIR)/utilities_unittest-utilities_unittest.Tpo -c -o utilities_unittest-utilities_unittest.o `test -f 'src/utilities_unittest.cc' || echo '$(srcdir)/'`src/utilities_unittest.cc
+@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/utilities_unittest-utilities_unittest.Tpo $(DEPDIR)/utilities_unittest-utilities_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/utilities_unittest.cc' object='utilities_unittest-utilities_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(utilities_unittest_CXXFLAGS) $(CXXFLAGS) -c -o utilities_unittest-utilities_unittest.o `test -f 'src/utilities_unittest.cc' || echo '$(srcdir)/'`src/utilities_unittest.cc
+
+utilities_unittest-utilities_unittest.obj: src/utilities_unittest.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(utilities_unittest_CXXFLAGS) $(CXXFLAGS) -MT utilities_unittest-utilities_unittest.obj -MD -MP -MF $(DEPDIR)/utilities_unittest-utilities_unittest.Tpo -c -o utilities_unittest-utilities_unittest.obj `if test -f 'src/utilities_unittest.cc'; then $(CYGPATH_W) 'src/utilities_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/utilities_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/utilities_unittest-utilities_unittest.Tpo $(DEPDIR)/utilities_unittest-utilities_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/utilities_unittest.cc' object='utilities_unittest-utilities_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(utilities_unittest_CXXFLAGS) $(CXXFLAGS) -c -o utilities_unittest-utilities_unittest.obj `if test -f 'src/utilities_unittest.cc'; then $(CYGPATH_W) 'src/utilities_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/utilities_unittest.cc'; fi`
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+distclean-libtool:
+ -rm -f libtool config.lt
+install-dist_docDATA: $(dist_doc_DATA)
+ @$(NORMAL_INSTALL)
+ test -z "$(docdir)" || $(MKDIR_P) "$(DESTDIR)$(docdir)"
+ @list='$(dist_doc_DATA)'; test -n "$(docdir)" || list=; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(docdir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(docdir)" || exit $$?; \
+ done
+
+uninstall-dist_docDATA:
+ @$(NORMAL_UNINSTALL)
+ @list='$(dist_doc_DATA)'; test -n "$(docdir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ test -n "$$files" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(docdir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(docdir)" && rm -f $$files
+install-pkgconfigDATA: $(pkgconfig_DATA)
+ @$(NORMAL_INSTALL)
+ test -z "$(pkgconfigdir)" || $(MKDIR_P) "$(DESTDIR)$(pkgconfigdir)"
+ @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgconfigdir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgconfigdir)" || exit $$?; \
+ done
+
+uninstall-pkgconfigDATA:
+ @$(NORMAL_UNINSTALL)
+ @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ test -n "$$files" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(pkgconfigdir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(pkgconfigdir)" && rm -f $$files
+install-glogincludeHEADERS: $(gloginclude_HEADERS)
+ @$(NORMAL_INSTALL)
+ test -z "$(glogincludedir)" || $(MKDIR_P) "$(DESTDIR)$(glogincludedir)"
+ @list='$(gloginclude_HEADERS)'; test -n "$(glogincludedir)" || list=; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(glogincludedir)'"; \
+ $(INSTALL_HEADER) $$files "$(DESTDIR)$(glogincludedir)" || exit $$?; \
+ done
+
+uninstall-glogincludeHEADERS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(gloginclude_HEADERS)'; test -n "$(glogincludedir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ test -n "$$files" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(glogincludedir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(glogincludedir)" && rm -f $$files
+install-nodist_glogincludeHEADERS: $(nodist_gloginclude_HEADERS)
+ @$(NORMAL_INSTALL)
+ test -z "$(glogincludedir)" || $(MKDIR_P) "$(DESTDIR)$(glogincludedir)"
+ @list='$(nodist_gloginclude_HEADERS)'; test -n "$(glogincludedir)" || list=; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(glogincludedir)'"; \
+ $(INSTALL_HEADER) $$files "$(DESTDIR)$(glogincludedir)" || exit $$?; \
+ done
+
+uninstall-nodist_glogincludeHEADERS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(nodist_gloginclude_HEADERS)'; test -n "$(glogincludedir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ test -n "$$files" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(glogincludedir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(glogincludedir)" && rm -f $$files
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+check-TESTS: $(TESTS)
+ @failed=0; all=0; xfail=0; xpass=0; skip=0; \
+ srcdir=$(srcdir); export srcdir; \
+ list=' $(TESTS) '; \
+ $(am__tty_colors); \
+ if test -n "$$list"; then \
+ for tst in $$list; do \
+ if test -f ./$$tst; then dir=./; \
+ elif test -f $$tst; then dir=; \
+ else dir="$(srcdir)/"; fi; \
+ if $(TESTS_ENVIRONMENT) $${dir}$$tst; then \
+ all=`expr $$all + 1`; \
+ case " $(XFAIL_TESTS) " in \
+ *[\ \ ]$$tst[\ \ ]*) \
+ xpass=`expr $$xpass + 1`; \
+ failed=`expr $$failed + 1`; \
+ col=$$red; res=XPASS; \
+ ;; \
+ *) \
+ col=$$grn; res=PASS; \
+ ;; \
+ esac; \
+ elif test $$? -ne 77; then \
+ all=`expr $$all + 1`; \
+ case " $(XFAIL_TESTS) " in \
+ *[\ \ ]$$tst[\ \ ]*) \
+ xfail=`expr $$xfail + 1`; \
+ col=$$lgn; res=XFAIL; \
+ ;; \
+ *) \
+ failed=`expr $$failed + 1`; \
+ col=$$red; res=FAIL; \
+ ;; \
+ esac; \
+ else \
+ skip=`expr $$skip + 1`; \
+ col=$$blu; res=SKIP; \
+ fi; \
+ echo "$${col}$$res$${std}: $$tst"; \
+ done; \
+ if test "$$all" -eq 1; then \
+ tests="test"; \
+ All=""; \
+ else \
+ tests="tests"; \
+ All="All "; \
+ fi; \
+ if test "$$failed" -eq 0; then \
+ if test "$$xfail" -eq 0; then \
+ banner="$$All$$all $$tests passed"; \
+ else \
+ if test "$$xfail" -eq 1; then failures=failure; else failures=failures; fi; \
+ banner="$$All$$all $$tests behaved as expected ($$xfail expected $$failures)"; \
+ fi; \
+ else \
+ if test "$$xpass" -eq 0; then \
+ banner="$$failed of $$all $$tests failed"; \
+ else \
+ if test "$$xpass" -eq 1; then passes=pass; else passes=passes; fi; \
+ banner="$$failed of $$all $$tests did not behave as expected ($$xpass unexpected $$passes)"; \
+ fi; \
+ fi; \
+ dashes="$$banner"; \
+ skipped=""; \
+ if test "$$skip" -ne 0; then \
+ if test "$$skip" -eq 1; then \
+ skipped="($$skip test was not run)"; \
+ else \
+ skipped="($$skip tests were not run)"; \
+ fi; \
+ test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \
+ dashes="$$skipped"; \
+ fi; \
+ report=""; \
+ if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \
+ report="Please report to $(PACKAGE_BUGREPORT)"; \
+ test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \
+ dashes="$$report"; \
+ fi; \
+ dashes=`echo "$$dashes" | sed s/./=/g`; \
+ if test "$$failed" -eq 0; then \
+ echo "$$grn$$dashes"; \
+ else \
+ echo "$$red$$dashes"; \
+ fi; \
+ echo "$$banner"; \
+ test -z "$$skipped" || echo "$$skipped"; \
+ test -z "$$report" || echo "$$report"; \
+ echo "$$dashes$$std"; \
+ test "$$failed" -eq 0; \
+ else :; fi
+
+distdir: $(DISTFILES)
+ $(am__remove_distdir)
+ test -d "$(distdir)" || mkdir "$(distdir)"
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+ $(MAKE) $(AM_MAKEFLAGS) \
+ top_distdir="$(top_distdir)" distdir="$(distdir)" \
+ dist-hook
+ -test -n "$(am__skip_mode_fix)" \
+ || find "$(distdir)" -type d ! -perm -755 \
+ -exec chmod u+rwx,go+rx {} \; -o \
+ ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \
+ ! -type d ! -perm -400 -exec chmod a+r {} \; -o \
+ ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \
+ || chmod -R a+r "$(distdir)"
+dist-gzip: distdir
+ tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
+ $(am__remove_distdir)
+
+dist-bzip2: distdir
+ tardir=$(distdir) && $(am__tar) | bzip2 -9 -c >$(distdir).tar.bz2
+ $(am__remove_distdir)
+
+dist-lzma: distdir
+ tardir=$(distdir) && $(am__tar) | lzma -9 -c >$(distdir).tar.lzma
+ $(am__remove_distdir)
+
+dist-xz: distdir
+ tardir=$(distdir) && $(am__tar) | xz -c >$(distdir).tar.xz
+ $(am__remove_distdir)
+
+dist-tarZ: distdir
+ tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z
+ $(am__remove_distdir)
+
+dist-shar: distdir
+ shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz
+ $(am__remove_distdir)
+
+dist-zip: distdir
+ -rm -f $(distdir).zip
+ zip -rq $(distdir).zip $(distdir)
+ $(am__remove_distdir)
+
+dist dist-all: distdir
+ tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
+ $(am__remove_distdir)
+
+# This target untars the dist file and tries a VPATH configuration. Then
+# it guarantees that the distribution is self-contained by making another
+# tarfile.
+distcheck: dist
+ case '$(DIST_ARCHIVES)' in \
+ *.tar.gz*) \
+ GZIP=$(GZIP_ENV) gzip -dc $(distdir).tar.gz | $(am__untar) ;;\
+ *.tar.bz2*) \
+ bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\
+ *.tar.lzma*) \
+ lzma -dc $(distdir).tar.lzma | $(am__untar) ;;\
+ *.tar.xz*) \
+ xz -dc $(distdir).tar.xz | $(am__untar) ;;\
+ *.tar.Z*) \
+ uncompress -c $(distdir).tar.Z | $(am__untar) ;;\
+ *.shar.gz*) \
+ GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\
+ *.zip*) \
+ unzip $(distdir).zip ;;\
+ esac
+ chmod -R a-w $(distdir); chmod a+w $(distdir)
+ mkdir $(distdir)/_build
+ mkdir $(distdir)/_inst
+ chmod a-w $(distdir)
+ test -d $(distdir)/_build || exit 0; \
+ dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \
+ && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \
+ && am__cwd=`pwd` \
+ && $(am__cd) $(distdir)/_build \
+ && ../configure --srcdir=.. --prefix="$$dc_install_base" \
+ $(DISTCHECK_CONFIGURE_FLAGS) \
+ && $(MAKE) $(AM_MAKEFLAGS) \
+ && $(MAKE) $(AM_MAKEFLAGS) dvi \
+ && $(MAKE) $(AM_MAKEFLAGS) check \
+ && $(MAKE) $(AM_MAKEFLAGS) install \
+ && $(MAKE) $(AM_MAKEFLAGS) installcheck \
+ && $(MAKE) $(AM_MAKEFLAGS) uninstall \
+ && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \
+ distuninstallcheck \
+ && chmod -R a-w "$$dc_install_base" \
+ && ({ \
+ (cd ../.. && umask 077 && mkdir "$$dc_destdir") \
+ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \
+ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \
+ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \
+ distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \
+ } || { rm -rf "$$dc_destdir"; exit 1; }) \
+ && rm -rf "$$dc_destdir" \
+ && $(MAKE) $(AM_MAKEFLAGS) dist \
+ && rm -rf $(DIST_ARCHIVES) \
+ && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \
+ && cd "$$am__cwd" \
+ || exit 1
+ $(am__remove_distdir)
+ @(echo "$(distdir) archives ready for distribution: "; \
+ list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \
+ sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x'
+distuninstallcheck:
+ @$(am__cd) '$(distuninstallcheck_dir)' \
+ && test `$(distuninstallcheck_listfiles) | wc -l` -le 1 \
+ || { echo "ERROR: files left after uninstall:" ; \
+ if test -n "$(DESTDIR)"; then \
+ echo " (check DESTDIR support)"; \
+ fi ; \
+ $(distuninstallcheck_listfiles) ; \
+ exit 1; } >&2
+distcleancheck: distclean
+ @if test '$(srcdir)' = . ; then \
+ echo "ERROR: distcleancheck can only run from a VPATH build" ; \
+ exit 1 ; \
+ fi
+ @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \
+ || { echo "ERROR: files left in build directory after distclean:" ; \
+ $(distcleancheck_listfiles) ; \
+ exit 1; } >&2
+check-am: all-am
+ $(MAKE) $(AM_MAKEFLAGS) $(check_SCRIPTS)
+ $(MAKE) $(AM_MAKEFLAGS) check-TESTS
+check: check-am
+all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(SCRIPTS) $(DATA) \
+ $(HEADERS)
+installdirs:
+ for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(docdir)" "$(DESTDIR)$(pkgconfigdir)" "$(DESTDIR)$(glogincludedir)" "$(DESTDIR)$(glogincludedir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \
+ clean-noinstPROGRAMS mostlyclean-am
+
+distclean: distclean-am
+ -rm -f $(am__CONFIG_DISTCLEAN_FILES)
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-hdr distclean-libtool distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-dist_docDATA install-glogincludeHEADERS \
+ install-nodist_glogincludeHEADERS install-pkgconfigDATA
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am: install-libLTLIBRARIES
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -f $(am__CONFIG_DISTCLEAN_FILES)
+ -rm -rf $(top_srcdir)/autom4te.cache
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-dist_docDATA uninstall-glogincludeHEADERS \
+ uninstall-libLTLIBRARIES uninstall-nodist_glogincludeHEADERS \
+ uninstall-pkgconfigDATA
+
+.MAKE: check-am install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am am--refresh check check-TESTS check-am \
+ clean clean-generic clean-libLTLIBRARIES clean-libtool \
+ clean-noinstPROGRAMS ctags dist dist-all dist-bzip2 dist-gzip \
+ dist-hook dist-lzma dist-shar dist-tarZ dist-xz dist-zip \
+ distcheck distclean distclean-compile distclean-generic \
+ distclean-hdr distclean-libtool distclean-tags distcleancheck \
+ distdir distuninstallcheck dvi dvi-am html html-am info \
+ info-am install install-am install-data install-data-am \
+ install-dist_docDATA install-dvi install-dvi-am install-exec \
+ install-exec-am install-glogincludeHEADERS install-html \
+ install-html-am install-info install-info-am \
+ install-libLTLIBRARIES install-man \
+ install-nodist_glogincludeHEADERS install-pdf install-pdf-am \
+ install-pkgconfigDATA install-ps install-ps-am install-strip \
+ installcheck installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ tags uninstall uninstall-am uninstall-dist_docDATA \
+ uninstall-glogincludeHEADERS uninstall-libLTLIBRARIES \
+ uninstall-nodist_glogincludeHEADERS uninstall-pkgconfigDATA
+
+@ENABLE_FRAME_POINTERS_FALSE@@X86_64_TRUE@ # TODO(csilvers): check if -fomit-frame-pointer might be in $(CXXFLAGS),
+@ENABLE_FRAME_POINTERS_FALSE@@X86_64_TRUE@ # before setting this.
+logging_striplog_test_sh: logging_striptest0 logging_striptest2 logging_striptest10
+ $(top_srcdir)/src/logging_striplog_test.sh
+demangle_unittest_sh: demangle_unittest
+ $(builddir)/demangle_unittest # force to create lt-demangle_unittest
+ $(top_srcdir)/src/demangle_unittest.sh
+signalhandler_unittest_sh: signalhandler_unittest
+ $(builddir)/signalhandler_unittest # force to create lt-signalhandler_unittest
+ $(top_srcdir)/src/signalhandler_unittest.sh
+
+rpm: dist-gzip packages/rpm.sh packages/rpm/rpm.spec
+ @cd packages && ./rpm.sh ${PACKAGE} ${VERSION}
+
+deb: dist-gzip packages/deb.sh packages/deb/*
+ @cd packages && ./deb.sh ${PACKAGE} ${VERSION}
+
+# Windows wants write permission to .vcproj files and maybe even sln files.
+dist-hook:
+ test -e "$(distdir)/vsprojects" \
+ && chmod -R u+w $(distdir)/*.sln $(distdir)/vsprojects/
+
+libtool: $(LIBTOOL_DEPS)
+ $(SHELL) ./config.status --recheck
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/LICENSE b/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/LICENSE
new file mode 100644
index 0000000000..c5638285a9
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/LICENSE
@@ -0,0 +1,137 @@
+
+
+
+
+ The "Clarified Artistic License"
+
+ Preamble
+
+The intent of this document is to state the conditions under which a
+Package may be copied, such that the Copyright Holder maintains some
+semblance of artistic control over the development of the package,
+while giving the users of the package the right to use and distribute
+the Package in a more-or-less customary fashion, plus the right to make
+reasonable modifications.
+
+Definitions:
+
+ "Package" refers to the collection of files distributed by the
+ Copyright Holder, and derivatives of that collection of files
+ created through textual modification.
+
+ "Standard Version" refers to such a Package if it has not been
+ modified, or has been modified in accordance with the wishes
+ of the Copyright Holder as specified below.
+
+ "Copyright Holder" is whoever is named in the copyright or
+ copyrights for the package.
+
+ "You" is you, if you're thinking about copying or distributing
+ this Package.
+
+ "Distribution fee" is a fee you charge for providing a copy of this
+ Package to another party.
+
+ "Freely Available" means that no fee is charged for the right to use
+ the item, though there may be fees involved in handling the item.
+
+1. You may make and give away verbatim copies of the source form of the
+Standard Version of this Package without restriction, provided that you
+duplicate all of the original copyright notices and associated disclaimers.
+
+2. You may apply bug fixes, portability fixes and other modifications
+derived from the Public Domain, or those made Freely Available, or from
+the Copyright Holder. A Package modified in such a way shall still be
+considered the Standard Version.
+
+3. You may otherwise modify your copy of this Package in any way, provided
+that you insert a prominent notice in each changed file stating how and
+when you changed that file, and provided that you do at least ONE of the
+following:
+
+ a) place your modifications in the Public Domain or otherwise make them
+ Freely Available, such as by posting said modifications to Usenet or
+ an equivalent medium, or placing the modifications on a major archive
+ site allowing unrestricted access to them, or by allowing the Copyright
+ Holder to include your modifications in the Standard Version of the
+ Package.
+
+ b) use the modified Package only within your corporation or organization.
+
+ c) rename any non-standard executables so the names do not conflict
+ with standard executables, which must also be provided, and provide
+ a separate manual page for each non-standard executable that clearly
+ documents how it differs from the Standard Version.
+
+ d) make other distribution arrangements with the Copyright Holder.
+
+ e) permit and encourge anyone who receives a copy of the modified Package
+ permission to make your modifications Freely Available in some specific
+ way.
+
+4. You may distribute the programs of this Package in object code or
+executable form, provided that you do at least ONE of the following:
+
+ a) distribute a Standard Version of the executables and library files,
+ together with instructions (in the manual page or equivalent) on where
+ to get the Standard Version.
+
+ b) accompany the distribution with the machine-readable source of
+ the Package with your modifications.
+
+ c) give non-standard executables non-standard names, and clearly
+ document the differences in manual pages (or equivalent), together
+ with instructions on where to get the Standard Version.
+
+ d) make other distribution arrangements with the Copyright Holder.
+
+ e) offer the machine-readable source of the Package, with your
+ modifications, by mail order.
+
+5. You may charge a distribution fee for any distribution of this Package.
+If you offer support for this Package, you may charge any fee you choose
+for that support. You may not charge a license fee for the right to use
+this Package itself. You may distribute this Package in aggregate with
+other (possibly commercial and possibly nonfree) programs as part of a
+larger (possibly commercial and possibly nonfree) software distribution,
+and charge license fees for other parts of that software distribution,
+provided that you do not advertise this Package as a product of your own.
+If the Package includes an interpreter, You may embed this Package's
+interpreter within an executable of yours (by linking); this shall be
+construed as a mere form of aggregation, provided that the complete
+Standard Version of the interpreter is so embedded.
+
+6. The scripts and library files supplied as input to or produced as
+output from the programs of this Package do not automatically fall
+under the copyright of this Package, but belong to whoever generated
+them, and may be sold commercially, and may be aggregated with this
+Package. If such scripts or library files are aggregated with this
+Package via the so-called "undump" or "unexec" methods of producing a
+binary executable image, then distribution of such an image shall
+neither be construed as a distribution of this Package nor shall it
+fall under the restrictions of Paragraphs 3 and 4, provided that you do
+not represent such an executable image as a Standard Version of this
+Package.
+
+7. C subroutines (or comparably compiled subroutines in other
+languages) supplied by you and linked into this Package in order to
+emulate subroutines and variables of the language defined by this
+Package shall not be considered part of this Package, but are the
+equivalent of input as in Paragraph 6, provided these subroutines do
+not change the language in any way that would cause it to fail the
+regression tests for the language.
+
+8. Aggregation of the Standard Version of the Package with a commercial
+distribution is always permitted provided that the use of this Package is
+embedded; that is, when no overt attempt is made to make this Package's
+interfaces visible to the end user of the commercial distribution.
+Such use shall not be construed as a distribution of this Package.
+
+9. The name of the Copyright Holder may not be used to endorse or promote
+products derived from this software without specific prior written permission.
+
+10. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+
+ The End
diff --git a/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/Makefile.am b/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/Makefile.am
new file mode 100644
index 0000000000..bd3129e1ad
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/Makefile.am
@@ -0,0 +1,43 @@
+include_HEADERS = libdis.h
+lib_LTLIBRARIES = libdisasm.la
+libdisasm_la_SOURCES = \
+ ia32_implicit.c \
+ ia32_implicit.h \
+ ia32_insn.c \
+ ia32_insn.h \
+ ia32_invariant.c \
+ ia32_invariant.h \
+ ia32_modrm.c \
+ ia32_modrm.h \
+ ia32_opcode_tables.c \
+ ia32_opcode_tables.h \
+ ia32_operand.c \
+ ia32_operand.h \
+ ia32_reg.c \
+ ia32_reg.h \
+ ia32_settings.c \
+ ia32_settings.h \
+ libdis.h \
+ qword.h \
+ x86_disasm.c \
+ x86_format.c \
+ x86_imm.c \
+ x86_imm.h \
+ x86_insn.c \
+ x86_misc.c \
+ x86_operand_list.c \
+ x86_operand_list.h
+
+# Cheat to get non-autoconf swig into tarball,
+# even if it doesn't build by default.
+EXTRA_DIST = \
+swig/Makefile \
+swig/libdisasm.i \
+swig/libdisasm_oop.i \
+swig/python/Makefile-swig \
+swig/perl/Makefile-swig \
+swig/perl/Makefile.PL \
+swig/ruby/Makefile-swig \
+swig/ruby/extconf.rb \
+swig/tcl/Makefile-swig \
+swig/README
diff --git a/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/README.breakpad b/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/README.breakpad
new file mode 100644
index 0000000000..a345411401
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/README.breakpad
@@ -0,0 +1,9 @@
+Name: libdisasm
+URL: https://sourceforge.net/projects/bastard/files/libdisasm/0.23/libdisasm-0.23.tar.gz/download
+Version: 0.23
+License: Clarified-Artistic
+License File: LICENSE
+
+Description:
+This contains a copy of libdisasm. It is no longer under development upstream,
+so we keep a copy here to maintain fixes ourselves.
diff --git a/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/TODO b/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/TODO
new file mode 100644
index 0000000000..148addf9b8
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/TODO
@@ -0,0 +1,43 @@
+x86_format.c
+------------
+intel: jmpf -> jmp, callf -> call
+att: jmpf -> ljmp, callf -> lcall
+
+opcode table
+------------
+finish typing instructions
+fix flag clear/set/toggle types
+
+ix64 stuff
+----------
+document output file formats in web page
+features doc: register aliases, implicit operands, stack mods,
+ring0 flags, eflags, cpu model/isa
+
+ia32_handle_* implementation
+
+fix operand 0F C2
+CMPPS
+
+* sysenter, sysexit as CALL types -- preceded by MSR writes
+* SYSENTER/SYSEXIT stack : overwrites SS, ESP
+* stos, cmps, scas, movs, ins, outs, lods -> OP_PTR
+* OP_SIZE in implicit operands
+* use OP_SIZE to choose reg sizes!
+
+DONE?? :
+implicit operands: provide action ?
+e.g. add/inc for stach, write, etc
+replace table numbers in opcodes.dat with
+#defines for table names
+
+replace 0 with INSN_INVALID [or maybe FF for imnvalid and 00 for Not Applicable */
+no wait that is only for prefix tables -- n/p
+
+if ( prefx) only use if insn != invalid
+
+these should cover all the wacky disasm exceptions
+
+for the rep one we can chet, match only a 0x90
+
+todo: privilege | ring
diff --git a/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/ia32_implicit.c b/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/ia32_implicit.c
new file mode 100644
index 0000000000..8b075d2ee0
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/ia32_implicit.c
@@ -0,0 +1,422 @@
+#include <stdlib.h>
+
+#include "ia32_implicit.h"
+#include "ia32_insn.h"
+#include "ia32_reg.h"
+#include "x86_operand_list.h"
+
+/* Conventions: Register operands which are aliases of another register
+ * operand (e.g. AX in one operand and AL in another) assume that the
+ * operands are different registers and that alias tracking will resolve
+ * data flow. This means that something like
+ * mov ax, al
+ * would have 'write only' access for AX and 'read only' access for AL,
+ * even though both AL and AX are read and written */
+typedef struct {
+ uint32_t type;
+ uint32_t operand;
+} op_implicit_list_t;
+
+static op_implicit_list_t list_aaa[] =
+ /* 37 : AAA : rw AL */
+ /* 3F : AAS : rw AL */
+ {{ OP_R | OP_W, REG_BYTE_OFFSET }, {0}}; /* aaa */
+
+static op_implicit_list_t list_aad[] =
+ /* D5 0A, D5 (ib) : AAD : rw AX */
+ /* D4 0A, D4 (ib) : AAM : rw AX */
+ {{ OP_R | OP_W, REG_WORD_OFFSET }, {0}}; /* aad */
+
+static op_implicit_list_t list_call[] =
+ /* E8, FF, 9A, FF : CALL : rw ESP, rw EIP */
+ /* C2, C3, CA, CB : RET : rw ESP, rw EIP */
+ {{ OP_R | OP_W, REG_EIP_INDEX },
+ { OP_R | OP_W, REG_ESP_INDEX }, {0}}; /* call, ret */
+
+static op_implicit_list_t list_cbw[] =
+ /* 98 : CBW : r AL, rw AX */
+ {{ OP_R | OP_W, REG_WORD_OFFSET },
+ { OP_R, REG_BYTE_OFFSET}, {0}}; /* cbw */
+
+static op_implicit_list_t list_cwde[] =
+ /* 98 : CWDE : r AX, rw EAX */
+ {{ OP_R | OP_W, REG_DWORD_OFFSET },
+ { OP_R, REG_WORD_OFFSET }, {0}}; /* cwde */
+
+static op_implicit_list_t list_clts[] =
+ /* 0F 06 : CLTS : rw CR0 */
+ {{ OP_R | OP_W, REG_CTRL_OFFSET}, {0}}; /* clts */
+
+static op_implicit_list_t list_cmpxchg[] =
+ /* 0F B0 : CMPXCHG : rw AL */
+ {{ OP_R | OP_W, REG_BYTE_OFFSET }, {0}}; /* cmpxchg */
+
+static op_implicit_list_t list_cmpxchgb[] =
+ /* 0F B1 : CMPXCHG : rw EAX */
+ {{ OP_R | OP_W, REG_DWORD_OFFSET }, {0}}; /* cmpxchg */
+
+static op_implicit_list_t list_cmpxchg8b[] =
+ /* 0F C7 : CMPXCHG8B : rw EDX, rw EAX, r ECX, r EBX */
+ {{ OP_R | OP_W, REG_DWORD_OFFSET },
+ { OP_R | OP_W, REG_DWORD_OFFSET + 2 },
+ { OP_R, REG_DWORD_OFFSET + 1 },
+ { OP_R, REG_DWORD_OFFSET + 3 }, {0}}; /* cmpxchg8b */
+
+static op_implicit_list_t list_cpuid[] =
+ /* 0F A2 : CPUID : rw EAX, w EBX, w ECX, w EDX */
+ {{ OP_R | OP_W, REG_DWORD_OFFSET },
+ { OP_W, REG_DWORD_OFFSET + 1 },
+ { OP_W, REG_DWORD_OFFSET + 2 },
+ { OP_W, REG_DWORD_OFFSET + 3 }, {0}}; /* cpuid */
+
+static op_implicit_list_t list_cwd[] =
+ /* 99 : CWD/CWQ : rw EAX, w EDX */
+ {{ OP_R | OP_W, REG_DWORD_OFFSET },
+ { OP_W, REG_DWORD_OFFSET + 2 }, {0}}; /* cwd */
+
+static op_implicit_list_t list_daa[] =
+ /* 27 : DAA : rw AL */
+ /* 2F : DAS : rw AL */
+ {{ OP_R | OP_W, REG_BYTE_OFFSET }, {0}}; /* daa */
+
+static op_implicit_list_t list_idiv[] =
+ /* F6 : DIV, IDIV : r AX, w AL, w AH */
+ /* FIXED: first op was EAX, not Aw. TODO: verify! */
+ {{ OP_R, REG_WORD_OFFSET },
+ { OP_W, REG_BYTE_OFFSET },
+ { OP_W, REG_BYTE_OFFSET + 4 }, {0}}; /* div */
+
+static op_implicit_list_t list_div[] =
+ /* F7 : DIV, IDIV : rw EDX, rw EAX */
+ {{ OP_R | OP_W, REG_DWORD_OFFSET + 2 },
+ { OP_R | OP_W, REG_DWORD_OFFSET }, {0}}; /* div */
+
+static op_implicit_list_t list_enter[] =
+ /* C8 : ENTER : rw ESP w EBP */
+ {{ OP_R | OP_W, REG_DWORD_OFFSET + 4 },
+ { OP_R, REG_DWORD_OFFSET + 5 }, {0}}; /* enter */
+
+static op_implicit_list_t list_f2xm1[] =
+ /* D9 F0 : F2XM1 : rw ST(0) */
+ /* D9 E1 : FABS : rw ST(0) */
+ /* D9 E0 : FCHS : rw ST(0) */
+ /* D9 FF : FCOS : rw ST(0)*/
+ /* D8, DA : FDIV : rw ST(0) */
+ /* D8, DA : FDIVR : rw ST(0) */
+ /* D9 F2 : FPTAN : rw ST(0) */
+ /* D9 FC : FRNDINT : rw ST(0) */
+ /* D9 FB : FSINCOS : rw ST(0) */
+ /* D9 FE : FSIN : rw ST(0) */
+ /* D9 FA : FSQRT : rw ST(0) */
+ /* D9 F4 : FXTRACT : rw ST(0) */
+ {{ OP_R | OP_W, REG_FPU_OFFSET }, {0}}; /* f2xm1 */
+
+static op_implicit_list_t list_fcom[] =
+ /* D8, DC, DE D9 : FCOM : r ST(0) */
+ /* DE, DA : FICOM : r ST(0) */
+ /* DF, D8 : FIST : r ST(0) */
+ /* D9 E4 : FTST : r ST(0) */
+ /* D9 E5 : FXAM : r ST(0) */
+ {{ OP_R, REG_FPU_OFFSET }, {0}}; /* fcom */
+
+static op_implicit_list_t list_fpatan[] =
+ /* D9 F3 : FPATAN : r ST(0), rw ST(1) */
+ {{ OP_R, REG_FPU_OFFSET }, {0}}; /* fpatan */
+
+static op_implicit_list_t list_fprem[] =
+ /* D9 F8, D9 F5 : FPREM : rw ST(0) r ST(1) */
+ /* D9 FD : FSCALE : rw ST(0), r ST(1) */
+ {{ OP_R | OP_W, REG_FPU_OFFSET },
+ { OP_R, REG_FPU_OFFSET + 1 }, {0}}; /* fprem */
+
+static op_implicit_list_t list_faddp[] =
+ /* DE C1 : FADDP : r ST(0), rw ST(1) */
+ /* DE E9 : FSUBP : r ST(0), rw ST(1) */
+ /* D9 F1 : FYL2X : r ST(0), rw ST(1) */
+ /* D9 F9 : FYL2XP1 : r ST(0), rw ST(1) */
+ {{ OP_R, REG_FPU_OFFSET },
+ { OP_R | OP_W, REG_FPU_OFFSET + 1 }, {0}}; /* faddp */
+
+static op_implicit_list_t list_fucompp[] =
+ /* DA E9 : FUCOMPP : r ST(0), r ST(1) */
+ {{ OP_R, REG_FPU_OFFSET },
+ { OP_R, REG_FPU_OFFSET + 1 }, {0}}; /* fucompp */
+
+static op_implicit_list_t list_imul[] =
+ /* F6 : IMUL : r AL, w AX */
+ /* F6 : MUL : r AL, w AX */
+ {{ OP_R, REG_BYTE_OFFSET },
+ { OP_W, REG_WORD_OFFSET }, {0}}; /* imul */
+
+static op_implicit_list_t list_mul[] =
+ /* F7 : IMUL : rw EAX, w EDX */
+ /* F7 : MUL : rw EAX, w EDX */
+ {{ OP_R | OP_W, REG_DWORD_OFFSET },
+ { OP_W, REG_DWORD_OFFSET + 2 }, {0}}; /* imul */
+
+static op_implicit_list_t list_lahf[] =
+ /* 9F : LAHF : r EFLAGS, w AH */
+ {{ OP_R, REG_FLAGS_INDEX },
+ { OP_W, REG_BYTE_OFFSET + 4 }, {0}}; /* lahf */
+
+static op_implicit_list_t list_ldmxcsr[] =
+ /* 0F AE : LDMXCSR : w MXCSR SSE Control Status Reg */
+ {{ OP_W, REG_MXCSG_INDEX }, {0}}; /* ldmxcsr */
+
+static op_implicit_list_t list_leave[] =
+ /* C9 : LEAVE : rw ESP, w EBP */
+ {{ OP_R | OP_W, REG_ESP_INDEX },
+ { OP_W, REG_DWORD_OFFSET + 5 }, {0}}; /* leave */
+
+static op_implicit_list_t list_lgdt[] =
+ /* 0F 01 : LGDT : w GDTR */
+ {{ OP_W, REG_GDTR_INDEX }, {0}}; /* lgdt */
+
+static op_implicit_list_t list_lidt[] =
+ /* 0F 01 : LIDT : w IDTR */
+ {{ OP_W, REG_IDTR_INDEX }, {0}}; /* lidt */
+
+static op_implicit_list_t list_lldt[] =
+ /* 0F 00 : LLDT : w LDTR */
+ {{ OP_W, REG_LDTR_INDEX }, {0}}; /* lldt */
+
+static op_implicit_list_t list_lmsw[] =
+ /* 0F 01 : LMSW : w CR0 */
+ {{ OP_W, REG_CTRL_OFFSET }, {0}}; /* lmsw */
+
+static op_implicit_list_t list_loop[] =
+ /* E0, E1, E2 : LOOP : rw ECX */
+ {{ OP_R | OP_W, REG_DWORD_OFFSET + 1 }, {0}};/* loop */
+
+static op_implicit_list_t list_ltr[] =
+ /* 0F 00 : LTR : w Task Register */
+ {{ OP_W, REG_TR_INDEX }, {0}}; /* ltr */
+
+static op_implicit_list_t list_pop[] =
+ /* 8F, 58, 1F, 07, 17, 0F A1, 0F A9 : POP : rw ESP */
+ /* FF, 50, 6A, 68, 0E, 16, 1E, 06, 0F A0, 0F A8 : PUSH : rw ESP */
+ {{ OP_R | OP_W, REG_ESP_INDEX }, {0}}; /* pop, push */
+
+static op_implicit_list_t list_popad[] =
+ /* 61 : POPAD : rw esp, w edi esi ebp ebx edx ecx eax */
+ {{ OP_R | OP_W, REG_ESP_INDEX },
+ { OP_W, REG_DWORD_OFFSET + 7 },
+ { OP_W, REG_DWORD_OFFSET + 6 },
+ { OP_W, REG_DWORD_OFFSET + 5 },
+ { OP_W, REG_DWORD_OFFSET + 3 },
+ { OP_W, REG_DWORD_OFFSET + 2 },
+ { OP_W, REG_DWORD_OFFSET + 1 },
+ { OP_W, REG_DWORD_OFFSET }, {0}}; /* popad */
+
+static op_implicit_list_t list_popfd[] =
+ /* 9D : POPFD : rw esp, w eflags */
+ {{ OP_R | OP_W, REG_ESP_INDEX },
+ { OP_W, REG_FLAGS_INDEX }, {0}}; /* popfd */
+
+static op_implicit_list_t list_pushad[] =
+ /* FF, 50, 6A, 68, 0E, 16, 1E, 06, 0F A0, 0F A8 : PUSH : rw ESP */
+ /* 60 : PUSHAD : rw esp, r eax ecx edx ebx esp ebp esi edi */
+ {{ OP_R | OP_W, REG_ESP_INDEX },
+ { OP_R, REG_DWORD_OFFSET },
+ { OP_R, REG_DWORD_OFFSET + 1 },
+ { OP_R, REG_DWORD_OFFSET + 2 },
+ { OP_R, REG_DWORD_OFFSET + 3 },
+ { OP_R, REG_DWORD_OFFSET + 5 },
+ { OP_R, REG_DWORD_OFFSET + 6 },
+ { OP_R, REG_DWORD_OFFSET + 7 }, {0}}; /* pushad */
+
+static op_implicit_list_t list_pushfd[] =
+ /* 9C : PUSHFD : rw esp, r eflags */
+ {{ OP_R | OP_W, REG_ESP_INDEX },
+ { OP_R, REG_FLAGS_INDEX }, {0}}; /* pushfd */
+
+static op_implicit_list_t list_rdmsr[] =
+ /* 0F 32 : RDMSR : r ECX, w EDX, w EAX */
+ {{ OP_R, REG_DWORD_OFFSET + 1 },
+ { OP_W, REG_DWORD_OFFSET + 2 },
+ { OP_W, REG_DWORD_OFFSET }, {0}}; /* rdmsr */
+
+static op_implicit_list_t list_rdpmc[] =
+ /* 0F 33 : RDPMC : r ECX, w EDX, w EAX */
+ {{ OP_R, REG_DWORD_OFFSET + 1 },
+ { OP_W, REG_DWORD_OFFSET + 2 },
+ { OP_W, REG_DWORD_OFFSET }, {0}}; /* rdpmc */
+
+static op_implicit_list_t list_rdtsc[] =
+ /* 0F 31 : RDTSC : rw EDX, rw EAX */
+ {{ OP_R | OP_W, REG_DWORD_OFFSET + 2 },
+ { OP_R | OP_W, REG_DWORD_OFFSET }, {0}}; /* rdtsc */
+
+static op_implicit_list_t list_rep[] =
+ /* F3, F2 ... : REP : rw ECX */
+ {{ OP_R | OP_W, REG_DWORD_OFFSET + 1 }, {0}};/* rep */
+
+static op_implicit_list_t list_rsm[] =
+ /* 0F AA : RSM : r CR4, r CR0 */
+ {{ OP_R, REG_CTRL_OFFSET + 4 },
+ { OP_R, REG_CTRL_OFFSET }, {0}}; /* rsm */
+
+static op_implicit_list_t list_sahf[] =
+ /* 9E : SAHF : r ah, rw eflags (set SF ZF AF PF CF) */
+ {{ OP_R, REG_DWORD_OFFSET }, {0}}; /* sahf */
+
+static op_implicit_list_t list_sgdt[] =
+ /* 0F : SGDT : r gdtr */
+ /* TODO: finish this! */
+ {{ OP_R, REG_DWORD_OFFSET }, {0}}; /* sgdt */
+
+static op_implicit_list_t list_sidt[] =
+ /* 0F : SIDT : r idtr */
+ /* TODO: finish this! */
+ {{ OP_R, REG_DWORD_OFFSET }, {0}}; /* sidt */
+
+static op_implicit_list_t list_sldt[] =
+ /* 0F : SLDT : r ldtr */
+ /* TODO: finish this! */
+ {{ OP_R, REG_DWORD_OFFSET }, {0}}; /* sldt */
+
+static op_implicit_list_t list_smsw[] =
+ /* 0F : SMSW : r CR0 */
+ /* TODO: finish this! */
+ {{ OP_R, REG_DWORD_OFFSET }, {0}}; /* smsw */
+
+static op_implicit_list_t list_stmxcsr[] =
+ /* 0F AE : STMXCSR : r MXCSR */
+ /* TODO: finish this! */
+ {{ OP_R, REG_DWORD_OFFSET }, {0}}; /* stmxcsr */
+
+static op_implicit_list_t list_str[] =
+ /* 0F 00 : STR : r TR (task register) */
+ /* TODO: finish this! */
+ {{ OP_R, REG_DWORD_OFFSET }, {0}}; /* str */
+
+static op_implicit_list_t list_sysenter[] =
+ /* 0F 34 : SYSENTER : w cs, w eip, w ss, w esp, r CR0, w eflags
+ * r sysenter_cs_msr, sysenter_esp_msr, sysenter_eip_msr */
+ /* TODO: finish this! */
+ {{ OP_R, REG_DWORD_OFFSET }, {0}}; /* sysenter */
+
+static op_implicit_list_t list_sysexit[] =
+ /* 0F 35 : SYSEXIT : r edx, r ecx, w cs, w eip, w ss, w esp
+ * r sysenter_cs_msr */
+ /* TODO: finish this! */
+ {{ OP_R, REG_DWORD_OFFSET }, {0}}; /* sysexit */
+
+static op_implicit_list_t list_wrmsr[] =
+ /* 0F 30 : WRMST : r edx, r eax, r ecx */
+ /* TODO: finish this! */
+ {{ OP_R, REG_DWORD_OFFSET }, {0}}; /* wrmsr */
+
+static op_implicit_list_t list_xlat[] =
+ /* D7 : XLAT : rw al r ebx (ptr) */
+ /* TODO: finish this! */
+ {{ OP_R, REG_DWORD_OFFSET }, {0}}; /* xlat */
+/* TODO:
+ * monitor 0f 01 c8 eax OP_R ecx OP_R edx OP_R
+ * mwait 0f 01 c9 eax OP_R ecx OP_R
+ */
+static op_implicit_list_t list_monitor[] =
+ {{ OP_R, REG_DWORD_OFFSET }, {0}}; /* monitor */
+static op_implicit_list_t list_mwait[] =
+ {{ OP_R, REG_DWORD_OFFSET }, {0}}; /* mwait */
+
+op_implicit_list_t *op_implicit_list[] = {
+ /* This is a list of implicit operands which are read/written by
+ * various x86 instructions. Note that modifications to the stack
+ * register are mentioned here, but that additional information on
+ * the effect an instruction has on the stack is contained in the
+ * x86_insn_t 'stack_mod' and 'stack_mod_val' fields. Use of the
+ * eflags register, i.e. setting, clearing, and testing flags, is
+ * not recorded here but rather in the flags_set and flags_tested
+ * fields of the x86_insn_t.*/
+ NULL,
+ list_aaa, list_aad, list_call, list_cbw, /* 1 - 4 */
+ list_cwde, list_clts, list_cmpxchg, list_cmpxchgb, /* 5 - 8 */
+ list_cmpxchg8b, list_cpuid, list_cwd, list_daa, /* 9 - 12 */
+ list_idiv, list_div, list_enter, list_f2xm1, /* 13 - 16 */
+ list_fcom, list_fpatan, list_fprem, list_faddp, /* 17 - 20 */
+ list_fucompp, list_imul, list_mul, list_lahf, /* 21 - 24 */
+ list_ldmxcsr, list_leave, list_lgdt, list_lidt, /* 25 - 28 */
+ list_lldt, list_lmsw, list_loop, list_ltr, /* 29 - 32 */
+ list_pop, list_popad, list_popfd, list_pushad, /* 33 - 36 */
+ list_pushfd, list_rdmsr, list_rdpmc, list_rdtsc, /* 37 - 40 */
+ /* NOTE: 'REP' is a hack since it is a prefix: if its position
+ * in the table changes, then change IDX_IMPLICIT_REP in the .h */
+ list_rep, list_rsm, list_sahf, list_sgdt, /* 41 - 44 */
+ list_sidt, list_sldt, list_smsw, list_stmxcsr, /* 45 - 48 */
+ list_str, list_sysenter, list_sysexit, list_wrmsr, /* 49 - 52 */
+ list_xlat, list_monitor, list_mwait, /* 53 - 55*/
+ NULL /* end of list */
+ };
+
+#define LAST_IMPL_IDX 55
+
+static void handle_impl_reg( x86_op_t *op, uint32_t val ) {
+ x86_reg_t *reg = &op->data.reg;
+ op->type = op_register;
+ ia32_handle_register( reg, (unsigned int) val );
+ switch (reg->size) {
+ case 1:
+ op->datatype = op_byte; break;
+ case 2:
+ op->datatype = op_word; break;
+ case 4:
+ op->datatype = op_dword; break;
+ case 8:
+ op->datatype = op_qword; break;
+ case 10:
+ op->datatype = op_extreal; break;
+ case 16:
+ op->datatype = op_dqword; break;
+ }
+ return;
+}
+
+/* 'impl_idx' is the value from the opcode table: between 1 and LAST_IMPL_IDX */
+/* returns number of operands added */
+unsigned int ia32_insn_implicit_ops( x86_insn_t *insn, unsigned int impl_idx ) {
+ op_implicit_list_t *list;
+ x86_op_t *op;
+ unsigned int num = 0;
+
+ if (! impl_idx || impl_idx > LAST_IMPL_IDX ) {
+ return 0;
+ }
+
+ for ( list = op_implicit_list[impl_idx]; list->type; list++, num++ ) {
+ enum x86_op_access access = (enum x86_op_access) OP_PERM(list->type);
+ enum x86_op_flags flags = (enum x86_op_flags) (OP_FLAGS(list->type) >> 12);
+
+ op = NULL;
+ /* In some cases (MUL), EAX is an implicit operand hardcoded in
+ * the instruction without being explicitly listed in assembly.
+ * For this situation, find the hardcoded operand and add the
+ * implied flag rather than adding a new implicit operand. */
+ x86_oplist_t * existing;
+ if (ia32_true_register_id(list->operand) == REG_DWORD_OFFSET) {
+ for ( existing = insn->operands; existing; existing = existing->next ) {
+ if (existing->op.type == op_register &&
+ existing->op.data.reg.id == list->operand) {
+ op = &existing->op;
+ break;
+ }
+ }
+ }
+ if (!op) {
+ op = x86_operand_new( insn );
+ /* all implicit operands are registers */
+ handle_impl_reg( op, list->operand );
+ /* decrement the 'explicit count' incremented by default in
+ * x86_operand_new */
+ insn->explicit_count = insn->explicit_count -1;
+ }
+ if (!op) {
+ return num; /* gah! return early */
+ }
+ op->access |= access;
+ op->flags |= flags;
+ op->flags |= op_implied;
+ }
+
+ return num;
+}
diff --git a/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/ia32_implicit.h b/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/ia32_implicit.h
new file mode 100644
index 0000000000..0002b28b9b
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/ia32_implicit.h
@@ -0,0 +1,13 @@
+#ifndef IA32_IMPLICIT_H
+#define IA32_IMPLICIT_H
+
+#include "libdis.h"
+
+/* OK, this is a hack to deal with prefixes having implicit operands...
+ * thought I had removed all the old hackishness ;( */
+
+#define IDX_IMPLICIT_REP 41 /* change this if the table changes! */
+
+unsigned int ia32_insn_implicit_ops( x86_insn_t *insn, unsigned int impl_idx );
+
+#endif
diff --git a/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/ia32_insn.c b/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/ia32_insn.c
new file mode 100644
index 0000000000..cc277608bf
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/ia32_insn.c
@@ -0,0 +1,623 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "qword.h"
+
+#include "ia32_insn.h"
+#include "ia32_opcode_tables.h"
+
+#include "ia32_reg.h"
+#include "ia32_operand.h"
+#include "ia32_implicit.h"
+#include "ia32_settings.h"
+
+#include "libdis.h"
+
+extern ia32_table_desc_t ia32_tables[];
+extern ia32_settings_t ia32_settings;
+
+#define IS_SP( op ) (op->type == op_register && \
+ (op->data.reg.id == REG_ESP_INDEX || \
+ op->data.reg.alias == REG_ESP_INDEX) )
+#define IS_IMM( op ) (op->type == op_immediate )
+
+#ifdef WIN32
+# define INLINE
+#else
+# define INLINE inline
+#endif
+
+/* for calculating stack modification based on an operand */
+static INLINE int32_t long_from_operand( x86_op_t *op ) {
+
+ if (! IS_IMM(op) ) {
+ return 0L;
+ }
+
+ switch ( op->datatype ) {
+ case op_byte:
+ return (int32_t) op->data.sbyte;
+ case op_word:
+ return (int32_t) op->data.sword;
+ case op_qword:
+ return (int32_t) op->data.sqword;
+ case op_dword:
+ return op->data.sdword;
+ default:
+ /* these are not used in stack insn */
+ break;
+ }
+
+ return 0L;
+}
+
+
+/* determine what this insn does to the stack */
+static void ia32_stack_mod(x86_insn_t *insn) {
+ x86_op_t *dest, *src = NULL;
+
+ if (! insn || ! insn->operands ) {
+ return;
+ }
+
+ dest = &insn->operands->op;
+ if ( dest ) {
+ src = &insn->operands->next->op;
+ }
+
+ insn->stack_mod = 0;
+ insn->stack_mod_val = 0;
+
+ switch ( insn->type ) {
+ case insn_call:
+ case insn_callcc:
+ insn->stack_mod = 1;
+ insn->stack_mod_val = insn->addr_size * -1;
+ break;
+ case insn_push:
+ insn->stack_mod = 1;
+ insn->stack_mod_val = insn->addr_size * -1;
+ break;
+ case insn_return:
+ insn->stack_mod = 1;
+ insn->stack_mod_val = insn->addr_size;
+ case insn_int: case insn_intcc:
+ case insn_iret:
+ break;
+ case insn_pop:
+ insn->stack_mod = 1;
+ if (! IS_SP( dest ) ) {
+ insn->stack_mod_val = insn->op_size;
+ } /* else we don't know the stack change in a pop esp */
+ break;
+ case insn_enter:
+ insn->stack_mod = 1;
+ insn->stack_mod_val = 0; /* TODO : FIX */
+ break;
+ case insn_leave:
+ insn->stack_mod = 1;
+ insn->stack_mod_val = 0; /* TODO : FIX */
+ break;
+ case insn_pushregs:
+ insn->stack_mod = 1;
+ insn->stack_mod_val = 0; /* TODO : FIX */
+ break;
+ case insn_popregs:
+ insn->stack_mod = 1;
+ insn->stack_mod_val = 0; /* TODO : FIX */
+ break;
+ case insn_pushflags:
+ insn->stack_mod = 1;
+ insn->stack_mod_val = 0; /* TODO : FIX */
+ break;
+ case insn_popflags:
+ insn->stack_mod = 1;
+ insn->stack_mod_val = 0; /* TODO : FIX */
+ break;
+ case insn_add:
+ if ( IS_SP( dest ) ) {
+ insn->stack_mod = 1;
+ insn->stack_mod_val = long_from_operand( src );
+ }
+ break;
+ case insn_sub:
+ if ( IS_SP( dest ) ) {
+ insn->stack_mod = 1;
+ insn->stack_mod_val = long_from_operand( src );
+ insn->stack_mod_val *= -1;
+ }
+ break;
+ case insn_inc:
+ if ( IS_SP( dest ) ) {
+ insn->stack_mod = 1;
+ insn->stack_mod_val = 1;
+ }
+ break;
+ case insn_dec:
+ if ( IS_SP( dest ) ) {
+ insn->stack_mod = 1;
+ insn->stack_mod_val = 1;
+ }
+ break;
+ case insn_mov: case insn_movcc:
+ case insn_xchg: case insn_xchgcc:
+ case insn_mul: case insn_div:
+ case insn_shl: case insn_shr:
+ case insn_rol: case insn_ror:
+ case insn_and: case insn_or:
+ case insn_not: case insn_neg:
+ case insn_xor:
+ if ( IS_SP( dest ) ) {
+ insn->stack_mod = 1;
+ }
+ break;
+ default:
+ break;
+ }
+ if (! strcmp("enter", insn->mnemonic) ) {
+ insn->stack_mod = 1;
+ } else if (! strcmp("leave", insn->mnemonic) ) {
+ insn->stack_mod = 1;
+ }
+
+ /* for mov, etc we return 0 -- unknown stack mod */
+
+ return;
+}
+
+/* get the cpu details for this insn from cpu flags int */
+static void ia32_handle_cpu( x86_insn_t *insn, unsigned int cpu ) {
+ insn->cpu = (enum x86_insn_cpu) CPU_MODEL(cpu);
+ insn->isa = (enum x86_insn_isa) (ISA_SUBSET(cpu)) >> 16;
+ return;
+}
+
+/* handle mnemonic type and group */
+static void ia32_handle_mnemtype(x86_insn_t *insn, unsigned int mnemtype) {
+ unsigned int type = mnemtype & ~INS_FLAG_MASK;
+ insn->group = (enum x86_insn_group) (INS_GROUP(type)) >> 12;
+ insn->type = (enum x86_insn_type) INS_TYPE(type);
+
+ return;
+}
+
+static void ia32_handle_notes(x86_insn_t *insn, unsigned int notes) {
+ insn->note = (enum x86_insn_note) notes;
+ return;
+}
+
+static void ia32_handle_eflags( x86_insn_t *insn, unsigned int eflags) {
+ unsigned int flags;
+
+ /* handle flags effected */
+ flags = INS_FLAGS_TEST(eflags);
+ /* handle weird OR cases */
+ /* these are either JLE (ZF | SF<>OF) or JBE (CF | ZF) */
+ if (flags & INS_TEST_OR) {
+ flags &= ~INS_TEST_OR;
+ if ( flags & INS_TEST_ZERO ) {
+ flags &= ~INS_TEST_ZERO;
+ if ( flags & INS_TEST_CARRY ) {
+ flags &= ~INS_TEST_CARRY ;
+ flags |= (int)insn_carry_or_zero_set;
+ } else if ( flags & INS_TEST_SFNEOF ) {
+ flags &= ~INS_TEST_SFNEOF;
+ flags |= (int)insn_zero_set_or_sign_ne_oflow;
+ }
+ }
+ }
+ insn->flags_tested = (enum x86_flag_status) flags;
+
+ insn->flags_set = (enum x86_flag_status) INS_FLAGS_SET(eflags) >> 16;
+
+ return;
+}
+
+static void ia32_handle_prefix( x86_insn_t *insn, unsigned int prefixes ) {
+
+ insn->prefix = (enum x86_insn_prefix) prefixes & PREFIX_MASK; // >> 20;
+ if (! (insn->prefix & PREFIX_PRINT_MASK) ) {
+ /* no printable prefixes */
+ insn->prefix = insn_no_prefix;
+ }
+
+ /* concat all prefix strings */
+ if ( (unsigned int)insn->prefix & PREFIX_LOCK ) {
+ strncat(insn->prefix_string, "lock ", 32 -
+ strlen(insn->prefix_string));
+ }
+
+ if ( (unsigned int)insn->prefix & PREFIX_REPNZ ) {
+ strncat(insn->prefix_string, "repnz ", 32 -
+ strlen(insn->prefix_string));
+ } else if ( (unsigned int)insn->prefix & PREFIX_REPZ ) {
+ strncat(insn->prefix_string, "repz ", 32 -
+ strlen(insn->prefix_string));
+ }
+
+ return;
+}
+
+
+static void reg_32_to_16( x86_op_t *op, x86_insn_t *insn, void *arg ) {
+
+ /* if this is a 32-bit register and it is a general register ... */
+ if ( op->type == op_register && op->data.reg.size == 4 &&
+ (op->data.reg.type & reg_gen) ) {
+ /* WORD registers are 8 indices off from DWORD registers */
+ ia32_handle_register( &(op->data.reg),
+ op->data.reg.id + 8 );
+ }
+}
+
+static void handle_insn_metadata( x86_insn_t *insn, ia32_insn_t *raw_insn ) {
+ ia32_handle_mnemtype( insn, raw_insn->mnem_flag );
+ ia32_handle_notes( insn, raw_insn->notes );
+ ia32_handle_eflags( insn, raw_insn->flags_effected );
+ ia32_handle_cpu( insn, raw_insn->cpu );
+ ia32_stack_mod( insn );
+}
+
+static size_t ia32_decode_insn( unsigned char *buf, size_t buf_len,
+ ia32_insn_t *raw_insn, x86_insn_t *insn,
+ unsigned int prefixes ) {
+ size_t size, op_size;
+ unsigned char modrm;
+
+ /* this should never happen, but just in case... */
+ if ( raw_insn->mnem_flag == INS_INVALID ) {
+ return 0;
+ }
+
+ if (ia32_settings.options & opt_16_bit) {
+ insn->op_size = ( prefixes & PREFIX_OP_SIZE ) ? 4 : 2;
+ insn->addr_size = ( prefixes & PREFIX_ADDR_SIZE ) ? 4 : 2;
+ } else {
+ insn->op_size = ( prefixes & PREFIX_OP_SIZE ) ? 2 : 4;
+ insn->addr_size = ( prefixes & PREFIX_ADDR_SIZE ) ? 2 : 4;
+ }
+
+
+ /* ++++ 1. Copy mnemonic and mnemonic-flags to CODE struct */
+ if ((ia32_settings.options & opt_att_mnemonics) && raw_insn->mnemonic_att[0]) {
+ strncpy( insn->mnemonic, raw_insn->mnemonic_att, 16 );
+ }
+ else {
+ strncpy( insn->mnemonic, raw_insn->mnemonic, 16 );
+ }
+ ia32_handle_prefix( insn, prefixes );
+
+ handle_insn_metadata( insn, raw_insn );
+
+ /* prefetch the next byte in case it is a modr/m byte -- saves
+ * worrying about whether the 'mod/rm' operand or the 'reg' operand
+ * occurs first */
+ modrm = GET_BYTE( buf, buf_len );
+
+ /* ++++ 2. Decode Explicit Operands */
+ /* Intel uses up to 3 explicit operands in its instructions;
+ * the first is 'dest', the second is 'src', and the third
+ * is an additional source value (usually an immediate value,
+ * e.g. in the MUL instructions). These three explicit operands
+ * are encoded in the opcode tables, even if they are not used
+ * by the instruction. Additional implicit operands are stored
+ * in a supplemental table and are handled later. */
+
+ op_size = ia32_decode_operand( buf, buf_len, insn, raw_insn->dest,
+ raw_insn->dest_flag, prefixes, modrm );
+ /* advance buffer, increase size if necessary */
+ buf += op_size;
+ buf_len -= op_size;
+ size = op_size;
+
+ op_size = ia32_decode_operand( buf, buf_len, insn, raw_insn->src,
+ raw_insn->src_flag, prefixes, modrm );
+ buf += op_size;
+ buf_len -= op_size;
+ size += op_size;
+
+ op_size = ia32_decode_operand( buf, buf_len, insn, raw_insn->aux,
+ raw_insn->aux_flag, prefixes, modrm );
+ size += op_size;
+
+
+ /* ++++ 3. Decode Implicit Operands */
+ /* apply implicit operands */
+ ia32_insn_implicit_ops( insn, raw_insn->implicit_ops );
+ /* we have one small inelegant hack here, to deal with
+ * the two prefixes that have implicit operands. If Intel
+ * adds more, we'll change the algorithm to suit :) */
+ if ( (prefixes & PREFIX_REPZ) || (prefixes & PREFIX_REPNZ) ) {
+ ia32_insn_implicit_ops( insn, IDX_IMPLICIT_REP );
+ }
+
+
+ /* 16-bit hack: foreach operand, if 32-bit reg, make 16-bit reg */
+ if ( insn->op_size == 2 ) {
+ x86_operand_foreach( insn, reg_32_to_16, NULL, op_any );
+ }
+
+ return size;
+}
+
+
+/* convenience routine */
+#define USES_MOD_RM(flag) \
+ (flag == ADDRMETH_E || flag == ADDRMETH_M || flag == ADDRMETH_Q || \
+ flag == ADDRMETH_W || flag == ADDRMETH_R)
+
+static int uses_modrm_flag( unsigned int flag ) {
+ unsigned int meth;
+ if ( flag == ARG_NONE ) {
+ return 0;
+ }
+ meth = (flag & ADDRMETH_MASK);
+ if ( USES_MOD_RM(meth) ) {
+ return 1;
+ }
+
+ return 0;
+}
+
+/* This routine performs the actual byte-by-byte opcode table lookup.
+ * Originally it was pretty simple: get a byte, adjust it to a proper
+ * index into the table, then check the table row at that index to
+ * determine what to do next. But is anything that simple with Intel?
+ * This is now a huge, convoluted mess, mostly of bitter comments. */
+/* buf: pointer to next byte to read from stream
+ * buf_len: length of buf
+ * table: index of table to use for lookups
+ * raw_insn: output pointer that receives opcode definition
+ * prefixes: output integer that is encoded with prefixes in insn
+ * returns : number of bytes consumed from stream during lookup */
+size_t ia32_table_lookup( unsigned char *buf, size_t buf_len,
+ unsigned int table, ia32_insn_t **raw_insn,
+ unsigned int *prefixes ) {
+ unsigned char *next, op = buf[0]; /* byte value -- 'opcode' */
+ size_t size = 1, sub_size = 0, next_len;
+ ia32_table_desc_t *table_desc;
+ unsigned int subtable, prefix = 0, recurse_table = 0;
+
+ table_desc = &ia32_tables[table];
+
+ op = GET_BYTE( buf, buf_len );
+
+ if ( table_desc->type == tbl_fpu && op > table_desc->maxlim) {
+ /* one of the fucking FPU tables out of the 00-BH range */
+ /* OK,. this is a bit of a hack -- the proper way would
+ * have been to use subtables in the 00-BF FPU opcode tables,
+ * but that is rather wasteful of space... */
+ table_desc = &ia32_tables[table +1];
+ }
+
+ /* PERFORM TABLE LOOKUP */
+
+ /* ModR/M trick: shift extension bits into lowest bits of byte */
+ /* Note: non-ModR/M tables have a shift value of 0 */
+ op >>= table_desc->shift;
+
+ /* ModR/M trick: mask out high bits to turn extension into an index */
+ /* Note: non-ModR/M tables have a mask value of 0xFF */
+ op &= table_desc->mask;
+
+
+ /* Sparse table trick: check that byte is <= max value */
+ /* Note: full (256-entry) tables have a maxlim of 155 */
+ if ( op > table_desc->maxlim ) {
+ /* this is a partial table, truncated at the tail,
+ and op is out of range! */
+ return INVALID_INSN;
+ }
+
+ /* Sparse table trick: check that byte is >= min value */
+ /* Note: full (256-entry) tables have a minlim of 0 */
+ if ( table_desc->minlim > op ) {
+ /* this is a partial table, truncated at the head,
+ and op is out of range! */
+ return INVALID_INSN;
+ }
+ /* adjust op to be an offset from table index 0 */
+ op -= table_desc->minlim;
+
+ /* Yay! 'op' is now fully adjusted to be an index into 'table' */
+ *raw_insn = &(table_desc->table[op]);
+ //printf("BYTE %X TABLE %d OP %X\n", buf[0], table, op );
+
+ if ( (*raw_insn)->mnem_flag & INS_FLAG_PREFIX ) {
+ prefix = (*raw_insn)->mnem_flag & PREFIX_MASK;
+ }
+
+
+ /* handle escape to a multibyte/coproc/extension/etc table */
+ /* NOTE: if insn is a prefix and has a subtable, then we
+ * only recurse if this is the first prefix byte --
+ * that is, if *prefixes is 0.
+ * NOTE also that suffix tables are handled later */
+ subtable = (*raw_insn)->table;
+
+ if ( subtable && ia32_tables[subtable].type != tbl_suffix &&
+ (! prefix || ! *prefixes) ) {
+
+ if ( ia32_tables[subtable].type == tbl_ext_ext ||
+ ia32_tables[subtable].type == tbl_fpu_ext ) {
+ /* opcode extension: reuse current byte in buffer */
+ next = buf;
+ next_len = buf_len;
+ } else {
+ /* "normal" opcode: advance to next byte in buffer */
+ if ( buf_len > 1 ) {
+ next = &buf[1];
+ next_len = buf_len - 1;
+ }
+ else {
+ // buffer is truncated
+ return INVALID_INSN;
+ }
+ }
+ /* we encountered a multibyte opcode: recurse using the
+ * table specified in the opcode definition */
+ sub_size = ia32_table_lookup( next, next_len, subtable,
+ raw_insn, prefixes );
+
+ /* SSE/prefix hack: if the original opcode def was a
+ * prefix that specified a subtable, and the subtable
+ * lookup returned a valid insn, then we have encountered
+ * an SSE opcode definition; otherwise, we pretend we
+ * never did the subtable lookup, and deal with the
+ * prefix normally later */
+ if ( prefix && ( sub_size == INVALID_INSN ||
+ INS_TYPE((*raw_insn)->mnem_flag) == INS_INVALID ) ) {
+ /* this is a prefix, not an SSE insn :
+ * lookup next byte in main table,
+ * subsize will be reset during the
+ * main table lookup */
+ recurse_table = 1;
+ } else {
+ /* this is either a subtable (two-byte) insn
+ * or an invalid insn: either way, set prefix
+ * to NULL and end the opcode lookup */
+ prefix = 0;
+ // short-circuit lookup on invalid insn
+ if (sub_size == INVALID_INSN) return INVALID_INSN;
+ }
+ } else if ( prefix ) {
+ recurse_table = 1;
+ }
+
+ /* by default, we assume that we have the opcode definition,
+ * and there is no need to recurse on the same table, but
+ * if we do then a prefix was encountered... */
+ if ( recurse_table ) {
+ /* this must have been a prefix: use the same table for
+ * lookup of the next byte */
+ sub_size = ia32_table_lookup( &buf[1], buf_len - 1, table,
+ raw_insn, prefixes );
+
+ // short-circuit lookup on invalid insn
+ if (sub_size == INVALID_INSN) return INVALID_INSN;
+
+ /* a bit of a hack for branch hints */
+ if ( prefix & BRANCH_HINT_MASK ) {
+ if ( INS_GROUP((*raw_insn)->mnem_flag) == INS_EXEC ) {
+ /* segment override prefixes are invalid for
+ * all branch instructions, so delete them */
+ prefix &= ~PREFIX_REG_MASK;
+ } else {
+ prefix &= ~BRANCH_HINT_MASK;
+ }
+ }
+
+ /* apply prefix to instruction */
+
+ /* TODO: implement something enforcing prefix groups */
+ (*prefixes) |= prefix;
+ }
+
+ /* if this lookup was in a ModR/M table, then an opcode byte is
+ * NOT consumed: subtract accordingly. NOTE that if none of the
+ * operands used the ModR/M, then we need to consume the byte
+ * here, but ONLY in the 'top-level' opcode extension table */
+
+ if ( table_desc->type == tbl_ext_ext ) {
+ /* extensions-to-extensions never consume a byte */
+ --size;
+ } else if ( (table_desc->type == tbl_extension ||
+ table_desc->type == tbl_fpu ||
+ table_desc->type == tbl_fpu_ext ) &&
+ /* extensions that have an operand encoded in ModR/M
+ * never consume a byte */
+ (uses_modrm_flag((*raw_insn)->dest_flag) ||
+ uses_modrm_flag((*raw_insn)->src_flag) ) ) {
+ --size;
+ }
+
+ size += sub_size;
+
+ return size;
+}
+
+static size_t handle_insn_suffix( unsigned char *buf, size_t buf_len,
+ ia32_insn_t *raw_insn, x86_insn_t * insn ) {
+ ia32_insn_t *sfx_insn;
+ size_t size;
+ unsigned int prefixes = 0;
+
+ size = ia32_table_lookup( buf, buf_len, raw_insn->table, &sfx_insn,
+ &prefixes );
+ if (size == INVALID_INSN || sfx_insn->mnem_flag == INS_INVALID ) {
+ return 0;
+ }
+
+ strncpy( insn->mnemonic, sfx_insn->mnemonic, 16 );
+ handle_insn_metadata( insn, sfx_insn );
+
+ return 1;
+}
+
+/* invalid instructions are handled by returning 0 [error] from the
+ * function, setting the size of the insn to 1 byte, and copying
+ * the byte at the start of the invalid insn into the x86_insn_t.
+ * if the caller is saving the x86_insn_t for invalid instructions,
+ * instead of discarding them, this will maintain a consistent
+ * address space in the x86_insn_ts */
+
+/* this function is called by the controlling disassembler, so its name and
+ * calling convention cannot be changed */
+/* buf points to the loc of the current opcode (start of the
+ * instruction) in the instruction stream. The instruction
+ * stream is assumed to be a buffer of bytes read directly
+ * from the file for the purpose of disassembly; a mem-mapped
+ * file is ideal for * this.
+ * insn points to a code structure to be filled by instr_decode
+ * returns the size of the decoded instruction in bytes */
+size_t ia32_disasm_addr( unsigned char * buf, size_t buf_len,
+ x86_insn_t *insn ) {
+ ia32_insn_t *raw_insn = NULL;
+ unsigned int prefixes = 0;
+ size_t size, sfx_size;
+
+ if ( (ia32_settings.options & opt_ignore_nulls) && buf_len > 3 &&
+ !buf[0] && !buf[1] && !buf[2] && !buf[3]) {
+ /* IF IGNORE_NULLS is set AND
+ * first 4 bytes in the intruction stream are NULL
+ * THEN return 0 (END_OF_DISASSEMBLY) */
+ /* TODO: set errno */
+ MAKE_INVALID( insn, buf );
+ return 0; /* 4 00 bytes in a row? This isn't code! */
+ }
+
+ /* Perform recursive table lookup starting with main table (0) */
+ size = ia32_table_lookup(buf, buf_len, idx_Main, &raw_insn, &prefixes);
+ if ( size == INVALID_INSN || size > buf_len || raw_insn->mnem_flag == INS_INVALID ) {
+ MAKE_INVALID( insn, buf );
+ /* TODO: set errno */
+ return 0;
+ }
+
+ /* We now have the opcode itself figured out: we can decode
+ * the rest of the instruction. */
+ size += ia32_decode_insn( &buf[size], buf_len - size, raw_insn, insn,
+ prefixes );
+ if ( raw_insn->mnem_flag & INS_FLAG_SUFFIX ) {
+ /* AMD 3DNow! suffix -- get proper operand type here */
+ sfx_size = handle_insn_suffix( &buf[size], buf_len - size,
+ raw_insn, insn );
+ if (! sfx_size ) {
+ /* TODO: set errno */
+ MAKE_INVALID( insn, buf );
+ return 0;
+ }
+
+ size += sfx_size;
+ }
+
+ if (! size ) {
+ /* invalid insn */
+ MAKE_INVALID( insn, buf );
+ return 0;
+ }
+
+
+ insn->size = size;
+ return size; /* return size of instruction in bytes */
+}
diff --git a/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/ia32_insn.h b/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/ia32_insn.h
new file mode 100644
index 0000000000..d3f36c3b20
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/ia32_insn.h
@@ -0,0 +1,506 @@
+#ifndef IA32_INSN_H
+#define IA32_INSN_H
+/* this file contains the structure of opcode definitions and the
+ * constants they use */
+
+#include <sys/types.h>
+#include "libdis.h"
+
+
+#define GET_BYTE( buf, buf_len ) buf_len ? *buf : 0
+
+#define OP_SIZE_16 1
+#define OP_SIZE_32 2
+#define ADDR_SIZE_16 4
+#define ADDR_SIZE_32 8
+
+#define MAX_INSTRUCTION_SIZE 20
+
+/* invalid instructions are handled by returning 0 [error] from the
+ * function, setting the size of the insn to 1 byte, and copying
+ * the byte at the start of the invalid insn into the x86_insn_t.
+ * if the caller is saving the x86_insn_t for invalid instructions,
+ * instead of discarding them, this will maintain a consistent
+ * address space in the x86_insn_ts */
+
+#define INVALID_INSN ((size_t) -1) /* return value for invalid insn */
+#define MAKE_INVALID( i, buf ) \
+ strcpy( i->mnemonic, "invalid" ); \
+ x86_oplist_free( i ); \
+ i->size = 1; \
+ i->group = insn_none; \
+ i->type = insn_invalid; \
+ memcpy( i->bytes, buf, 1 );
+
+
+size_t ia32_disasm_addr( unsigned char * buf, size_t buf_len,
+ x86_insn_t *insn);
+
+
+/* --------------------------------------------------------- Table Lookup */
+/* IA32 Instruction defintion for ia32_opcodes.c */
+typedef struct {
+ unsigned int table; /* escape to this sub-table */
+ unsigned int mnem_flag; /* Flags referring to mnemonic */
+ unsigned int notes; /* Notes for this instruction */
+ unsigned int dest_flag, src_flag, aux_flag; /* and for specific operands */
+ unsigned int cpu; /* minimumCPU [AND with clocks?? */
+ char mnemonic[16]; /* buffers for building instruction */
+ char mnemonic_att[16]; /* at&t style mnemonic name */
+ int32_t dest;
+ int32_t src;
+ int32_t aux;
+ unsigned int flags_effected;
+ unsigned int implicit_ops; /* implicit operands */
+} ia32_insn_t;
+
+
+
+/* --------------------------------------------------------- Prefixes */
+/* Prefix Flags */
+/* Prefixes, same order as in the manual */
+/* had to reverse the values of the first three as they were entered into
+ * libdis.h incorrectly. */
+#define PREFIX_LOCK 0x0004
+#define PREFIX_REPNZ 0x0002
+#define PREFIX_REPZ 0x0001
+#define PREFIX_OP_SIZE 0x0010
+#define PREFIX_ADDR_SIZE 0x0020
+#define PREFIX_CS 0x0100
+#define PREFIX_SS 0x0200
+#define PREFIX_DS 0x0300
+#define PREFIX_ES 0x0400
+#define PREFIX_FS 0x0500
+#define PREFIX_GS 0x0600
+#define PREFIX_TAKEN 0x1000 /* branch taken */
+#define PREFIX_NOTTAKEN 0x2000 /* branch not taken */
+#define PREFIX_REG_MASK 0x0F00
+#define BRANCH_HINT_MASK 0x3000
+#define PREFIX_PRINT_MASK 0x000F /* printable prefixes */
+#define PREFIX_MASK 0xFFFF
+
+/* ---------------------------------------------------------- CPU Type */
+
+#define cpu_8086 0x0001
+#define cpu_80286 0x0002
+#define cpu_80386 0x0003
+#define cpu_80387 0x0004 /* originally these were a co-proc */
+#define cpu_80486 0x0005
+#define cpu_PENTIUM 0x0006
+#define cpu_PENTPRO 0x0007
+#define cpu_PENTIUM2 0x0008
+#define cpu_PENTIUM3 0x0009
+#define cpu_PENTIUM4 0x000A
+#define cpu_K6 0x0010
+#define cpu_K7 0x0020
+#define cpu_ATHLON 0x0030
+#define CPU_MODEL_MASK 0xFFFF
+#define CPU_MODEL(cpu) (cpu & CPU_MODEL_MASK)
+/* intel instruction subsets */
+#define isa_GP 0x10000 /* General Purpose Instructions */
+#define isa_FPU 0x20000 /* FPU instructions */
+#define isa_FPUMGT 0x30000 /* FPU/SIMD Management */
+#define isa_MMX 0x40000 /* MMX */
+#define isa_SSE1 0x50000 /* SSE */
+#define isa_SSE2 0x60000 /* SSE 2 */
+#define isa_SSE3 0x70000 /* SSE 3 */
+#define isa_3DNOW 0x80000 /* AMD 3d Now */
+#define isa_SYS 0x90000 /* System Instructions */
+#define ISA_SUBSET_MASK 0xFFFF0000
+#define ISA_SUBSET(isa) (isa & ISA_SUBSET_MASK)
+
+
+/* ------------------------------------------------------ Operand Decoding */
+#define ARG_NONE 0
+
+/* Using a mask allows us to store info such as OP_SIGNED in the
+ * operand flags field */
+#define OPFLAGS_MASK 0x0000FFFF
+
+/* Operand Addressing Methods, per intel manual */
+#define ADDRMETH_MASK 0x00FF0000
+
+/* note: for instructions with implied operands, use no ADDRMETH */
+#define ADDRMETH_A 0x00010000
+#define ADDRMETH_C 0x00020000
+#define ADDRMETH_D 0x00030000
+#define ADDRMETH_E 0x00040000
+#define ADDRMETH_F 0x00050000
+#define ADDRMETH_G 0x00060000
+#define ADDRMETH_I 0x00070000
+#define ADDRMETH_J 0x00080000
+#define ADDRMETH_M 0x00090000
+#define ADDRMETH_O 0x000A0000
+#define ADDRMETH_P 0x000B0000
+#define ADDRMETH_Q 0x000C0000
+#define ADDRMETH_R 0x000D0000
+#define ADDRMETH_S 0x000E0000
+#define ADDRMETH_T 0x000F0000
+#define ADDRMETH_V 0x00100000
+#define ADDRMETH_W 0x00110000
+#define ADDRMETH_X 0x00120000
+#define ADDRMETH_Y 0x00130000
+#define ADDRMETH_RR 0x00140000 /* gen reg hard-coded in opcode */
+#define ADDRMETH_RS 0x00150000 /* seg reg hard-coded in opcode */
+#define ADDRMETH_RT 0x00160000 /* test reg hard-coded in opcode */
+#define ADDRMETH_RF 0x00170000 /* fpu reg hard-coded in opcode */
+#define ADDRMETH_II 0x00180000 /* immediate hard-coded in opcode */
+#define ADDRMETH_PP 0x00190000 /* mm reg ONLY in modr/m field */
+#define ADDRMETH_VV 0x001A0000 /* xmm reg ONLY in mod/rm field */
+
+/* Operand Types, per intel manual */
+#define OPTYPE_MASK 0xFF000000
+
+#define OPTYPE_a 0x01000000 /* BOUND: h:h or w:w */
+#define OPTYPE_b 0x02000000 /* byte */
+#define OPTYPE_c 0x03000000 /* byte or word */
+#define OPTYPE_d 0x04000000 /* word */
+#define OPTYPE_dq 0x05000000 /* qword */
+#define OPTYPE_p 0x06000000 /* 16:16 or 16:32 pointer */
+#define OPTYPE_pi 0x07000000 /* dword MMX reg */
+#define OPTYPE_ps 0x08000000 /* 128-bit single fp */
+#define OPTYPE_q 0x09000000 /* dword */
+#define OPTYPE_s 0x0A000000 /* 6-byte descriptor */
+#define OPTYPE_ss 0x0B000000 /* scalar of 128-bit single fp */
+#define OPTYPE_si 0x0C000000 /* word general register */
+#define OPTYPE_v 0x0D000000 /* hword or word */
+#define OPTYPE_w 0x0E000000 /* hword */
+#define OPTYPE_m 0x0F000000 /* to handle LEA */
+#define OPTYPE_none 0xFF000000 /* no valid operand size, INVLPG */
+
+/* custom ones for FPU instructions */
+#define OPTYPE_fs 0x10000000 /* pointer to single-real*/
+#define OPTYPE_fd 0x20000000 /* pointer to double real */
+#define OPTYPE_fe 0x30000000 /* pointer to extended real */
+#define OPTYPE_fb 0x40000000 /* pointer to packed BCD */
+#define OPTYPE_fv 0x50000000 /* pointer to FPU env: 14|28-bytes */
+#define OPTYPE_ft 0x60000000 /* pointer to FPU state: 94|108-bytes */
+#define OPTYPE_fx 0x70000000 /* pointer to FPU regs: 512 bites */
+#define OPTYPE_fp 0x80000000 /* general fpu register: dbl ext */
+
+/* SSE2 operand types */
+#define OPTYPE_sd 0x90000000 /* scalar of 128-bit double fp */
+#define OPTYPE_pd 0xA0000000 /* 128-bit double fp */
+
+
+
+/* ---------------------------------------------- Opcode Table Descriptions */
+/* the table type describes how to handle byte/size increments before
+ * and after lookup. Some tables re-use the current byte, others
+ * consume a byte only if the ModR/M encodes no operands, etc */
+enum ia32_tbl_type_id {
+ tbl_opcode = 0, /* standard opcode table: no surprises */
+ tbl_prefix, /* Prefix Override, e.g. 66/F2/F3 */
+ tbl_suffix, /* 3D Now style */
+ tbl_extension, /* ModR/M extension: 00-FF -> 00-07 */
+ tbl_ext_ext, /* extension of modr/m using R/M field */
+ tbl_fpu, /* fpu table: 00-BF -> 00-0F */
+ tbl_fpu_ext /* fpu extension : C0-FF -> 00-1F */
+ };
+
+/* How it works:
+ * Bytes are 'consumed' if the next table lookup requires that the byte
+ * pointer be advanced in the instruction stream. 'Does not consume' means
+ * that, when the lookup function recurses, the same byte it re-used in the
+ * new table. It also means that size is not decremented, for example when
+ * a ModR/M byte is used. Note that tbl_extension (ModR/M) instructions that
+ * do not increase the size of an insn with their operands have a forced
+ 3 size increase in the lookup algo. Weird, yes, confusing, yes, welcome
+ * to the Intel ISA. Another note: tbl_prefix is used as an override, so an
+ * empty insn in a prefix table causes the instruction in the original table
+ * to be used, rather than an invalid insn being generated.
+ * tbl_opcode uses current byte and consumes it
+ * tbl_prefix uses current byte but does not consume it
+ * tbl_suffix uses and consumes last byte in insn
+ * tbl_extension uses current byte but does not consume it
+ * tbl_ext_ext uses current byte but does not consume it
+ * tbl_fpu uses current byte and consumes it
+ * tbl_fpu_ext uses current byte but does not consume it
+ */
+
+/* Convenience struct for opcode tables : these will be stored in a
+ * 'table of tables' so we can use a table index instead of a pointer */
+typedef struct { /* Assembly instruction tables */
+ ia32_insn_t *table; /* Pointer to table of instruction encodings */
+ enum ia32_tbl_type_id type;
+ unsigned char shift; /* amount to shift modrm byte */
+ unsigned char mask; /* bit mask for look up */
+ unsigned char minlim,maxlim; /* limits on min/max entries. */
+} ia32_table_desc_t;
+
+
+/* ---------------------------------------------- 'Cooked' Operand Type Info */
+/* Permissions: */
+#define OP_R 0x001 /* operand is READ */
+#define OP_W 0x002 /* operand is WRITTEN */
+#define OP_RW 0x003 /* (OP_R|OP_W): convenience macro */
+#define OP_X 0x004 /* operand is EXECUTED */
+
+#define OP_PERM_MASK 0x0000007 /* perms are NOT mutually exclusive */
+#define OP_PERM( type ) (type & OP_PERM_MASK)
+
+/* Flags */
+#define OP_SIGNED 0x010 /* operand is signed */
+
+#define OP_FLAG_MASK 0x0F0 /* mods are NOT mutually exclusive */
+#define OP_FLAGS( type ) (type & OP_FLAG_MASK)
+
+#define OP_REG_MASK 0x0000FFFF /* lower WORD is register ID */
+#define OP_REGTBL_MASK 0xFFFF0000 /* higher word is register type [gen/dbg] */
+#define OP_REGID( type ) (type & OP_REG_MASK)
+#define OP_REGTYPE( type ) (type & OP_REGTBL_MASK)
+
+/* ------------------------------------------'Cooked' Instruction Type Info */
+/* high-bit opcode types/insn meta-types */
+#define INS_FLAG_PREFIX 0x10000000 /* insn is a prefix */
+#define INS_FLAG_SUFFIX 0x20000000 /* followed by a suffix byte */
+#define INS_FLAG_MASK 0xFF000000
+
+/* insn notes */
+#define INS_NOTE_RING0 0x00000001 /* insn is privileged */
+#define INS_NOTE_SMM 0x00000002 /* Sys Mgt Mode only */
+#define INS_NOTE_SERIAL 0x00000004 /* serializes */
+#define INS_NOTE_NONSWAP 0x00000008 /* insn is not swapped in att format */ // could be separate field?
+#define INS_NOTE_NOSUFFIX 0x00000010 /* insn has no size suffix in att format */ // could be separate field?
+//#define INS_NOTE_NMI
+
+#define INS_INVALID 0
+
+/* instruction groups */
+#define INS_EXEC 0x1000
+#define INS_ARITH 0x2000
+#define INS_LOGIC 0x3000
+#define INS_STACK 0x4000
+#define INS_COND 0x5000
+#define INS_LOAD 0x6000
+#define INS_ARRAY 0x7000
+#define INS_BIT 0x8000
+#define INS_FLAG 0x9000
+#define INS_FPU 0xA000
+#define INS_TRAPS 0xD000
+#define INS_SYSTEM 0xE000
+#define INS_OTHER 0xF000
+
+#define INS_GROUP_MASK 0xF000
+#define INS_GROUP( type ) ( type & INS_GROUP_MASK )
+
+/* INS_EXEC group */
+#define INS_BRANCH (INS_EXEC | 0x01) /* Unconditional branch */
+#define INS_BRANCHCC (INS_EXEC | 0x02) /* Conditional branch */
+#define INS_CALL (INS_EXEC | 0x03) /* Jump to subroutine */
+#define INS_CALLCC (INS_EXEC | 0x04) /* Jump to subroutine */
+#define INS_RET (INS_EXEC | 0x05) /* Return from subroutine */
+
+/* INS_ARITH group */
+#define INS_ADD (INS_ARITH | 0x01)
+#define INS_SUB (INS_ARITH | 0x02)
+#define INS_MUL (INS_ARITH | 0x03)
+#define INS_DIV (INS_ARITH | 0x04)
+#define INS_INC (INS_ARITH | 0x05) /* increment */
+#define INS_DEC (INS_ARITH | 0x06) /* decrement */
+#define INS_SHL (INS_ARITH | 0x07) /* shift right */
+#define INS_SHR (INS_ARITH | 0x08) /* shift left */
+#define INS_ROL (INS_ARITH | 0x09) /* rotate left */
+#define INS_ROR (INS_ARITH | 0x0A) /* rotate right */
+#define INS_MIN (INS_ARITH | 0x0B) /* min func */
+#define INS_MAX (INS_ARITH | 0x0C) /* max func */
+#define INS_AVG (INS_ARITH | 0x0D) /* avg func */
+#define INS_FLR (INS_ARITH | 0x0E) /* floor func */
+#define INS_CEIL (INS_ARITH | 0x0F) /* ceiling func */
+
+/* INS_LOGIC group */
+#define INS_AND (INS_LOGIC | 0x01)
+#define INS_OR (INS_LOGIC | 0x02)
+#define INS_XOR (INS_LOGIC | 0x03)
+#define INS_NOT (INS_LOGIC | 0x04)
+#define INS_NEG (INS_LOGIC | 0x05)
+#define INS_NAND (INS_LOGIC | 0x06)
+
+/* INS_STACK group */
+#define INS_PUSH (INS_STACK | 0x01)
+#define INS_POP (INS_STACK | 0x02)
+#define INS_PUSHREGS (INS_STACK | 0x03) /* push register context */
+#define INS_POPREGS (INS_STACK | 0x04) /* pop register context */
+#define INS_PUSHFLAGS (INS_STACK | 0x05) /* push all flags */
+#define INS_POPFLAGS (INS_STACK | 0x06) /* pop all flags */
+#define INS_ENTER (INS_STACK | 0x07) /* enter stack frame */
+#define INS_LEAVE (INS_STACK | 0x08) /* leave stack frame */
+
+/* INS_COND group */
+#define INS_TEST (INS_COND | 0x01)
+#define INS_CMP (INS_COND | 0x02)
+
+/* INS_LOAD group */
+#define INS_MOV (INS_LOAD | 0x01)
+#define INS_MOVCC (INS_LOAD | 0x02)
+#define INS_XCHG (INS_LOAD | 0x03)
+#define INS_XCHGCC (INS_LOAD | 0x04)
+#define INS_CONV (INS_LOAD | 0x05) /* move and convert type */
+
+/* INS_ARRAY group */
+#define INS_STRCMP (INS_ARRAY | 0x01)
+#define INS_STRLOAD (INS_ARRAY | 0x02)
+#define INS_STRMOV (INS_ARRAY | 0x03)
+#define INS_STRSTOR (INS_ARRAY | 0x04)
+#define INS_XLAT (INS_ARRAY | 0x05)
+
+/* INS_BIT group */
+#define INS_BITTEST (INS_BIT | 0x01)
+#define INS_BITSET (INS_BIT | 0x02)
+#define INS_BITCLR (INS_BIT | 0x03)
+
+/* INS_FLAG group */
+#define INS_CLEARCF (INS_FLAG | 0x01) /* clear Carry flag */
+#define INS_CLEARZF (INS_FLAG | 0x02) /* clear Zero flag */
+#define INS_CLEAROF (INS_FLAG | 0x03) /* clear Overflow flag */
+#define INS_CLEARDF (INS_FLAG | 0x04) /* clear Direction flag */
+#define INS_CLEARSF (INS_FLAG | 0x05) /* clear Sign flag */
+#define INS_CLEARPF (INS_FLAG | 0x06) /* clear Parity flag */
+#define INS_SETCF (INS_FLAG | 0x07)
+#define INS_SETZF (INS_FLAG | 0x08)
+#define INS_SETOF (INS_FLAG | 0x09)
+#define INS_SETDF (INS_FLAG | 0x0A)
+#define INS_SETSF (INS_FLAG | 0x0B)
+#define INS_SETPF (INS_FLAG | 0x0C)
+#define INS_TOGCF (INS_FLAG | 0x10) /* toggle */
+#define INS_TOGZF (INS_FLAG | 0x20)
+#define INS_TOGOF (INS_FLAG | 0x30)
+#define INS_TOGDF (INS_FLAG | 0x40)
+#define INS_TOGSF (INS_FLAG | 0x50)
+#define INS_TOGPF (INS_FLAG | 0x60)
+
+/* INS_FPU */
+#define INS_FMOV (INS_FPU | 0x1)
+#define INS_FMOVCC (INS_FPU | 0x2)
+#define INS_FNEG (INS_FPU | 0x3)
+#define INS_FABS (INS_FPU | 0x4)
+#define INS_FADD (INS_FPU | 0x5)
+#define INS_FSUB (INS_FPU | 0x6)
+#define INS_FMUL (INS_FPU | 0x7)
+#define INS_FDIV (INS_FPU | 0x8)
+#define INS_FSQRT (INS_FPU | 0x9)
+#define INS_FCMP (INS_FPU | 0xA)
+#define INS_FCOS (INS_FPU | 0xC) /* cosine */
+#define INS_FLDPI (INS_FPU | 0xD) /* load pi */
+#define INS_FLDZ (INS_FPU | 0xE) /* load 0 */
+#define INS_FTAN (INS_FPU | 0xF) /* tanget */
+#define INS_FSINE (INS_FPU | 0x10) /* sine */
+#define INS_FSYS (INS_FPU | 0x20) /* misc */
+
+/* INS_TRAP */
+#define INS_TRAP (INS_TRAPS | 0x01) /* generate trap */
+#define INS_TRAPCC (INS_TRAPS | 0x02) /* conditional trap gen */
+#define INS_TRET (INS_TRAPS | 0x03) /* return from trap */
+#define INS_BOUNDS (INS_TRAPS | 0x04) /* gen bounds trap */
+#define INS_DEBUG (INS_TRAPS | 0x05) /* gen breakpoint trap */
+#define INS_TRACE (INS_TRAPS | 0x06) /* gen single step trap */
+#define INS_INVALIDOP (INS_TRAPS | 0x07) /* gen invalid insn */
+#define INS_OFLOW (INS_TRAPS | 0x08) /* gen overflow trap */
+#define INS_ICEBP (INS_TRAPS | 0x09) /* ICE breakpoint */
+
+/* INS_SYSTEM */
+#define INS_HALT (INS_SYSTEM | 0x01) /* halt machine */
+#define INS_IN (INS_SYSTEM | 0x02) /* input form port */
+#define INS_OUT (INS_SYSTEM | 0x03) /* output to port */
+#define INS_CPUID (INS_SYSTEM | 0x04) /* identify cpu */
+
+/* INS_OTHER */
+#define INS_NOP (INS_OTHER | 0x01)
+#define INS_BCDCONV (INS_OTHER | 0x02) /* convert to/from BCD */
+#define INS_SZCONV (INS_OTHER | 0x03) /* convert size of operand */
+#define INS_SALC (INS_OTHER | 0x04) /* set %al on carry */
+#define INS_UNKNOWN (INS_OTHER | 0x05)
+
+
+#define INS_TYPE_MASK 0xFFFF
+#define INS_TYPE( type ) ( type & INS_TYPE_MASK )
+
+ /* flags effected by instruction */
+#define INS_TEST_CARRY 0x01 /* carry */
+#define INS_TEST_ZERO 0x02 /* zero/equal */
+#define INS_TEST_OFLOW 0x04 /* overflow */
+#define INS_TEST_DIR 0x08 /* direction */
+#define INS_TEST_SIGN 0x10 /* negative */
+#define INS_TEST_PARITY 0x20 /* parity */
+#define INS_TEST_OR 0x40 /* used in jle */
+#define INS_TEST_NCARRY 0x100 /* ! carry */
+#define INS_TEST_NZERO 0x200 /* ! zero */
+#define INS_TEST_NOFLOW 0x400 /* ! oflow */
+#define INS_TEST_NDIR 0x800 /* ! dir */
+#define INS_TEST_NSIGN 0x100 /* ! sign */
+#define INS_TEST_NPARITY 0x2000 /* ! parity */
+/* SF == OF */
+#define INS_TEST_SFEQOF 0x4000
+/* SF != OF */
+#define INS_TEST_SFNEOF 0x8000
+
+#define INS_TEST_ALL INS_TEST_CARRY | INS_TEST_ZERO | \
+ INS_TEST_OFLOW | INS_TEST_SIGN | \
+ INS_TEST_PARITY
+
+#define INS_SET_CARRY 0x010000 /* carry */
+#define INS_SET_ZERO 0x020000 /* zero/equal */
+#define INS_SET_OFLOW 0x040000 /* overflow */
+#define INS_SET_DIR 0x080000 /* direction */
+#define INS_SET_SIGN 0x100000 /* negative */
+#define INS_SET_PARITY 0x200000 /* parity */
+#define INS_SET_NCARRY 0x1000000
+#define INS_SET_NZERO 0x2000000
+#define INS_SET_NOFLOW 0x4000000
+#define INS_SET_NDIR 0x8000000
+#define INS_SET_NSIGN 0x10000000
+#define INS_SET_NPARITY 0x20000000
+#define INS_SET_SFEQOF 0x40000000
+#define INS_SET_SFNEOF 0x80000000
+
+#define INS_SET_ALL INS_SET_CARRY | INS_SET_ZERO | \
+ INS_SET_OFLOW | INS_SET_SIGN | \
+ INS_SET_PARITY
+
+#define INS_TEST_MASK 0x0000FFFF
+#define INS_FLAGS_TEST(x) (x & INS_TEST_MASK)
+#define INS_SET_MASK 0xFFFF0000
+#define INS_FLAGS_SET(x) (x & INS_SET_MASK)
+
+#if 0
+/* TODO: actually start using these */
+#define X86_PAIR_NP 1 /* not pairable; execs in U */
+#define X86_PAIR_PU 2 /* pairable in U pipe */
+#define X86_PAIR_PV 3 /* pairable in V pipe */
+#define X86_PAIR_UV 4 /* pairable in UV pipe */
+#define X86_PAIR_FX 5 /* pairable with FXCH */
+
+#define X86_EXEC_PORT_0 1
+#define X86_EXEC_PORT_1 2
+#define X86_EXEC_PORT_2 4
+#define X86_EXEC_PORT_3 8
+#define X86_EXEC_PORT_4 16
+
+#define X86_EXEC_UNITS
+
+typedef struct { /* representation of an insn during decoding */
+ uint32_t flags; /* runtime settings */
+ /* instruction prefixes and other foolishness */
+ uint32_t prefix; /* encoding of prefix */
+ char prefix_str[16]; /* mnemonics for prefix */
+ uint32_t branch_hint; /* gah! */
+ unsigned int cpu_ver; /* TODO: cpu version */
+ unsigned int clocks; /* TODO: clock cycles: min/max */
+ unsigned char last_prefix;
+ /* runtime intruction decoding helpers */
+ unsigned char mode; /* 16, 32, 64 */
+ unsigned char gen_regs; /* offset of default general reg set */
+ unsigned char sz_operand; /* operand size for insn */
+ unsigned char sz_address; /* address size for insn */
+ unsigned char uops; /* uops per insn */
+ unsigned char pairing; /* np,pu,pv.lv */
+ unsigned char exec_unit;
+ unsigned char exec_port;
+ unsigned char latency;
+} ia32_info_t;
+#define MODE_32 0 /* default */
+#define MODE_16 1
+#define MODE_64 2
+#endif
+
+#endif
diff --git a/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/ia32_invariant.c b/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/ia32_invariant.c
new file mode 100644
index 0000000000..68ec153d27
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/ia32_invariant.c
@@ -0,0 +1,313 @@
+#include <stdlib.h>
+#include <string.h>
+
+#include "ia32_invariant.h"
+#include "ia32_insn.h"
+#include "ia32_settings.h"
+
+extern ia32_table_desc_t *ia32_tables;
+extern ia32_settings_t ia32_settings;
+
+extern size_t ia32_table_lookup( unsigned char *buf, size_t buf_len,
+ unsigned int table, ia32_insn_t **raw_insn,
+ unsigned int *prefixes );
+
+
+/* -------------------------------- ModR/M, SIB */
+/* Convenience flags */
+#define MODRM_EA 1 /* ModR/M is an effective addr */
+#define MODRM_reg 2 /* ModR/M is a register */
+
+/* ModR/M flags */
+#define MODRM_RM_SIB 0x04 /* R/M == 100 */
+#define MODRM_RM_NOREG 0x05 /* R/B == 101 */
+/* if (MODRM.MOD_NODISP && MODRM.RM_NOREG) then just disp32 */
+#define MODRM_MOD_NODISP 0x00 /* mod == 00 */
+#define MODRM_MOD_DISP8 0x01 /* mod == 01 */
+#define MODRM_MOD_DISP32 0x02 /* mod == 10 */
+#define MODRM_MOD_NOEA 0x03 /* mod == 11 */
+/* 16-bit modrm flags */
+#define MOD16_MOD_NODISP 0
+#define MOD16_MOD_DISP8 1
+#define MOD16_MOD_DISP16 2
+#define MOD16_MOD_REG 3
+
+#define MOD16_RM_BXSI 0
+#define MOD16_RM_BXDI 1
+#define MOD16_RM_BPSI 2
+#define MOD16_RM_BPDI 3
+#define MOD16_RM_SI 4
+#define MOD16_RM_DI 5
+#define MOD16_RM_BP 6
+#define MOD16_RM_BX 7
+
+/* SIB flags */
+#define SIB_INDEX_NONE 0x04
+#define SIB_BASE_EBP 0x05
+#define SIB_SCALE_NOBASE 0x00
+
+/* Convenience struct for modR/M bitfield */
+struct modRM_byte {
+ unsigned int mod : 2;
+ unsigned int reg : 3;
+ unsigned int rm : 3;
+};
+
+/* Convenience struct for SIB bitfield */
+struct SIB_byte {
+ unsigned int scale : 2;
+ unsigned int index : 3;
+ unsigned int base : 3;
+};
+
+#ifdef WIN32
+static void byte_decode(unsigned char b, struct modRM_byte *modrm) {
+#else
+static inline void byte_decode(unsigned char b, struct modRM_byte *modrm) {
+#endif
+ /* generic bitfield-packing routine */
+
+ modrm->mod = b >> 6; /* top 2 bits */
+ modrm->reg = (b & 56) >> 3; /* middle 3 bits */
+ modrm->rm = b & 7; /* bottom 3 bits */
+}
+static int ia32_invariant_modrm( unsigned char *in, unsigned char *out,
+ unsigned int mode_16, x86_invariant_op_t *op) {
+ struct modRM_byte modrm;
+ struct SIB_byte sib;
+ unsigned char *c, *cin;
+ unsigned short *s;
+ unsigned int *i;
+ int size = 0; /* modrm byte is already counted */
+
+
+ byte_decode(*in, &modrm); /* get bitfields */
+
+ out[0] = in[0]; /* save modrm byte */
+ cin = &in[1];
+ c = &out[1];
+ s = (unsigned short *)&out[1];
+ i = (unsigned int *)&out[1];
+
+ op->type = op_expression;
+ op->flags |= op_pointer;
+ if ( ! mode_16 && modrm.rm == MODRM_RM_SIB &&
+ modrm.mod != MODRM_MOD_NOEA ) {
+ size ++;
+ byte_decode(*cin, (struct modRM_byte *)(void*)&sib);
+
+ out[1] = in[1]; /* save sib byte */
+ cin = &in[2];
+ c = &out[2];
+ s = (unsigned short *)&out[2];
+ i = (unsigned int *)&out[2];
+
+ if ( sib.base == SIB_BASE_EBP && ! modrm.mod ) {
+ /* disp 32 is variant! */
+ memset( i, X86_WILDCARD_BYTE, 4 );
+ size += 4;
+ }
+ }
+
+ if (! modrm.mod && modrm.rm == 101) {
+ if ( mode_16 ) { /* straight RVA in disp */
+ memset( s, X86_WILDCARD_BYTE, 2 );
+ size += 2;
+ } else {
+ memset( i, X86_WILDCARD_BYTE, 2 );
+ size += 4;
+ }
+ } else if (modrm.mod && modrm.mod < 3) {
+ if (modrm.mod == MODRM_MOD_DISP8) { /* offset in disp */
+ *c = *cin;
+ size += 1;
+ } else if ( mode_16 ) {
+ *s = (* ((unsigned short *) cin));
+ size += 2;
+ } else {
+ *i = (*((unsigned int *) cin));
+ size += 4;
+ }
+ } else if ( modrm.mod == 3 ) {
+ op->type = op_register;
+ op->flags &= ~op_pointer;
+ }
+
+ return (size);
+}
+
+
+static int ia32_decode_invariant( unsigned char *buf, size_t buf_len,
+ ia32_insn_t *t, unsigned char *out,
+ unsigned int prefixes, x86_invariant_t *inv) {
+
+ unsigned int addr_size, op_size, mode_16;
+ unsigned int op_flags[3] = { t->dest_flag, t->src_flag, t->aux_flag };
+ int x, type, bytes = 0, size = 0, modrm = 0;
+
+ /* set addressing mode */
+ if (ia32_settings.options & opt_16_bit) {
+ op_size = ( prefixes & PREFIX_OP_SIZE ) ? 4 : 2;
+ addr_size = ( prefixes & PREFIX_ADDR_SIZE ) ? 4 : 2;
+ mode_16 = ( prefixes & PREFIX_ADDR_SIZE ) ? 0 : 1;
+ } else {
+ op_size = ( prefixes & PREFIX_OP_SIZE ) ? 2 : 4;
+ addr_size = ( prefixes & PREFIX_ADDR_SIZE ) ? 2 : 4;
+ mode_16 = ( prefixes & PREFIX_ADDR_SIZE ) ? 1 : 0;
+ }
+
+ for (x = 0; x < 3; x++) {
+ inv->operands[x].access = (enum x86_op_access)
+ OP_PERM(op_flags[x]);
+ inv->operands[x].flags = (enum x86_op_flags)
+ (OP_FLAGS(op_flags[x]) >> 12);
+
+ switch (op_flags[x] & OPTYPE_MASK) {
+ case OPTYPE_c:
+ size = (op_size == 4) ? 2 : 1;
+ break;
+ case OPTYPE_a: case OPTYPE_v:
+ size = (op_size == 4) ? 4 : 2;
+ break;
+ case OPTYPE_p:
+ size = (op_size == 4) ? 6 : 4;
+ break;
+ case OPTYPE_b:
+ size = 1;
+ break;
+ case OPTYPE_w:
+ size = 2;
+ break;
+ case OPTYPE_d: case OPTYPE_fs: case OPTYPE_fd:
+ case OPTYPE_fe: case OPTYPE_fb: case OPTYPE_fv:
+ case OPTYPE_si: case OPTYPE_fx:
+ size = 4;
+ break;
+ case OPTYPE_s:
+ size = 6;
+ break;
+ case OPTYPE_q: case OPTYPE_pi:
+ size = 8;
+ break;
+ case OPTYPE_dq: case OPTYPE_ps: case OPTYPE_ss:
+ case OPTYPE_pd: case OPTYPE_sd:
+ size = 16;
+ break;
+ case OPTYPE_m:
+ size = (addr_size == 4) ? 4 : 2;
+ break;
+ default:
+ break;
+ }
+
+ type = op_flags[x] & ADDRMETH_MASK;
+ switch (type) {
+ case ADDRMETH_E: case ADDRMETH_M: case ADDRMETH_Q:
+ case ADDRMETH_R: case ADDRMETH_W:
+ modrm = 1;
+ bytes += ia32_invariant_modrm( buf, out,
+ mode_16, &inv->operands[x]);
+ break;
+ case ADDRMETH_C: case ADDRMETH_D: case ADDRMETH_G:
+ case ADDRMETH_P: case ADDRMETH_S: case ADDRMETH_T:
+ case ADDRMETH_V:
+ inv->operands[x].type = op_register;
+ modrm = 1;
+ break;
+ case ADDRMETH_A: case ADDRMETH_O:
+ /* pad with xF4's */
+ memset( &out[bytes + modrm], X86_WILDCARD_BYTE,
+ size );
+ bytes += size;
+ inv->operands[x].type = op_offset;
+ if ( type == ADDRMETH_O ) {
+ inv->operands[x].flags |= op_signed |
+ op_pointer;
+ }
+ break;
+ case ADDRMETH_I: case ADDRMETH_J:
+ /* grab imm value */
+ if ((op_flags[x] & OPTYPE_MASK) == OPTYPE_v) {
+ /* assume this is an address */
+ memset( &out[bytes + modrm],
+ X86_WILDCARD_BYTE, size );
+ } else {
+ memcpy( &out[bytes + modrm],
+ &buf[bytes + modrm], size );
+ }
+
+ bytes += size;
+ if ( type == ADDRMETH_J ) {
+ if ( size == 1 ) {
+ inv->operands[x].type =
+ op_relative_near;
+ } else {
+ inv->operands[x].type =
+ op_relative_far;
+ }
+ inv->operands[x].flags |= op_signed;
+ } else {
+ inv->operands[x].type = op_immediate;
+ }
+ break;
+ case ADDRMETH_F:
+ inv->operands[x].type = op_register;
+ break;
+ case ADDRMETH_X:
+ inv->operands[x].flags |= op_signed |
+ op_pointer | op_ds_seg | op_string;
+ break;
+ case ADDRMETH_Y:
+ inv->operands[x].flags |= op_signed |
+ op_pointer | op_es_seg | op_string;
+ break;
+ case ADDRMETH_RR:
+ inv->operands[x].type = op_register;
+ break;
+ case ADDRMETH_II:
+ inv->operands[x].type = op_immediate;
+ break;
+ default:
+ inv->operands[x].type = op_unused;
+ break;
+ }
+ }
+
+ return (bytes + modrm);
+}
+
+size_t ia32_disasm_invariant( unsigned char * buf, size_t buf_len,
+ x86_invariant_t *inv ) {
+ ia32_insn_t *raw_insn = NULL;
+ unsigned int prefixes;
+ unsigned int type;
+ size_t size;
+
+ /* Perform recursive table lookup starting with main table (0) */
+ size = ia32_table_lookup( buf, buf_len, 0, &raw_insn, &prefixes );
+ if ( size == INVALID_INSN || size > buf_len ) {
+ /* TODO: set errno */
+ return 0;
+ }
+
+ /* copy opcode bytes to buffer */
+ memcpy( inv->bytes, buf, size );
+
+ /* set mnemonic type and group */
+ type = raw_insn->mnem_flag & ~INS_FLAG_MASK;
+ inv->group = (enum x86_insn_group) (INS_GROUP(type)) >> 12;
+ inv->type = (enum x86_insn_type) INS_TYPE(type);
+
+ /* handle operands */
+ size += ia32_decode_invariant( buf + size, buf_len - size, raw_insn,
+ &buf[size - 1], prefixes, inv );
+
+ inv->size = size;
+
+ return size; /* return size of instruction in bytes */
+}
+
+size_t ia32_disasm_size( unsigned char *buf, size_t buf_len ) {
+ x86_invariant_t inv = { {0} };
+ return( ia32_disasm_invariant( buf, buf_len, &inv ) );
+}
diff --git a/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/ia32_invariant.h b/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/ia32_invariant.h
new file mode 100644
index 0000000000..e1cea60e9d
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/ia32_invariant.h
@@ -0,0 +1,11 @@
+#ifndef IA32_INVARIANT_H
+#define IA32_INVARIANT_H
+
+#include "libdis.h"
+
+size_t ia32_disasm_invariant( unsigned char *buf, size_t buf_len,
+ x86_invariant_t *inv);
+
+size_t ia32_disasm_size( unsigned char *buf, size_t buf_len );
+
+#endif
diff --git a/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/ia32_modrm.c b/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/ia32_modrm.c
new file mode 100644
index 0000000000..b0fe2ed3d3
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/ia32_modrm.c
@@ -0,0 +1,310 @@
+#include "ia32_modrm.h"
+#include "ia32_reg.h"
+#include "x86_imm.h"
+
+/* NOTE: when decoding ModR/M and SIB, we have to add 1 to all register
+ * values obtained from decoding the ModR/M or SIB byte, since they
+ * are encoded with eAX = 0 and the tables in ia32_reg.c use eAX = 1.
+ * ADDENDUM: this is only the case when the register value is used
+ * directly as an index into the register table, not when it is added to
+ * a genregs offset. */
+
+/* -------------------------------- ModR/M, SIB */
+/* ModR/M flags */
+#define MODRM_RM_SIB 0x04 /* R/M == 100 */
+#define MODRM_RM_NOREG 0x05 /* R/B == 101 */
+
+/* if (MODRM.MOD_NODISP && MODRM.RM_NOREG) then just disp32 */
+#define MODRM_MOD_NODISP 0x00 /* mod == 00 */
+#define MODRM_MOD_DISP8 0x01 /* mod == 01 */
+#define MODRM_MOD_DISP32 0x02 /* mod == 10 */
+#define MODRM_MOD_NOEA 0x03 /* mod == 11 */
+
+/* 16-bit modrm flags */
+#define MOD16_MOD_NODISP 0
+#define MOD16_MOD_DISP8 1
+#define MOD16_MOD_DISP16 2
+#define MOD16_MOD_REG 3
+
+#define MOD16_RM_BXSI 0
+#define MOD16_RM_BXDI 1
+#define MOD16_RM_BPSI 2
+#define MOD16_RM_BPDI 3
+#define MOD16_RM_SI 4
+#define MOD16_RM_DI 5
+#define MOD16_RM_BP 6
+#define MOD16_RM_BX 7
+
+/* SIB flags */
+#define SIB_INDEX_NONE 0x04
+#define SIB_BASE_EBP 0x05
+#define SIB_SCALE_NOBASE 0x00
+
+/* Convenience struct for modR/M bitfield */
+struct modRM_byte {
+ unsigned int mod : 2;
+ unsigned int reg : 3;
+ unsigned int rm : 3;
+};
+
+/* Convenience struct for SIB bitfield */
+struct SIB_byte {
+ unsigned int scale : 2;
+ unsigned int index : 3;
+ unsigned int base : 3;
+};
+
+
+#if 0
+int modrm_rm[] = {0,1,2,3,MODRM_RM_SIB,MODRM_MOD_DISP32,6,7};
+int modrm_reg[] = {0, 1, 2, 3, 4, 5, 6, 7};
+int modrm_mod[] = {0, MODRM_MOD_DISP8, MODRM_MOD_DISP32, MODRM_MOD_NOEA};
+int sib_scl[] = {0, 2, 4, 8};
+int sib_idx[] = {0, 1, 2, 3, SIB_INDEX_NONE, 5, 6, 7 };
+int sib_bas[] = {0, 1, 2, 3, 4, SIB_SCALE_NOBASE, 6, 7 };
+#endif
+
+/* this is needed to replace x86_imm_signsized() which does not sign-extend
+ * to dest */
+static unsigned int imm32_signsized( unsigned char *buf, size_t buf_len,
+ int32_t *dest, unsigned int size ) {
+ if ( size > buf_len ) {
+ return 0;
+ }
+
+ switch (size) {
+ case 1:
+ *dest = *((signed char *) buf);
+ break;
+ case 2:
+ *dest = *((signed short *) buf);
+ break;
+ case 4:
+ default:
+ *dest = *((signed int *) buf);
+ break;
+ }
+
+ return size;
+}
+
+
+
+static void byte_decode(unsigned char b, struct modRM_byte *modrm) {
+ /* generic bitfield-packing routine */
+
+ modrm->mod = b >> 6; /* top 2 bits */
+ modrm->reg = (b & 56) >> 3; /* middle 3 bits */
+ modrm->rm = b & 7; /* bottom 3 bits */
+}
+
+
+static size_t sib_decode( unsigned char *buf, size_t buf_len, x86_ea_t *ea,
+ unsigned int mod ) {
+ /* set Address Expression fields (scale, index, base, disp)
+ * according to the contents of the SIB byte.
+ * b points to the SIB byte in the instruction-stream buffer; the
+ * byte after b[0] is therefore the byte after the SIB
+ * returns number of bytes 'used', including the SIB byte */
+ size_t size = 1; /* start at 1 for SIB byte */
+ struct SIB_byte sib;
+
+ if ( buf_len < 1 ) {
+ return 0;
+ }
+
+ byte_decode( *buf, (struct modRM_byte *)(void*)&sib ); /* get bit-fields */
+
+ if ( sib.base == SIB_BASE_EBP && ! mod ) { /* if base == 101 (ebp) */
+ /* IF BASE == EBP, deal with exception */
+ /* IF (ModR/M did not create a Disp */
+ /* ... create a 32-bit Displacement */
+ imm32_signsized( &buf[1], buf_len, &ea->disp, sizeof(int32_t));
+ ea->disp_size = sizeof(int32_t);
+ ea->disp_sign = (ea->disp < 0) ? 1 : 0;
+ size += 4; /* add sizeof disp to count */
+
+ } else {
+ /* ELSE BASE refers to a General Register */
+ ia32_handle_register( &ea->base, sib.base + 1 );
+ }
+
+ /* set scale to 1, 2, 4, 8 */
+ ea->scale = 1 << sib.scale;
+
+ if (sib.index != SIB_INDEX_NONE) {
+ /* IF INDEX is not 'ESP' (100) */
+ ia32_handle_register( &ea->index, sib.index + 1 );
+ }
+
+ return (size); /* return number of bytes processed */
+}
+
+static size_t modrm_decode16( unsigned char *buf, unsigned int buf_len,
+ x86_op_t *op, struct modRM_byte *modrm ) {
+ /* 16-bit mode: hackish, but not as hackish as 32-bit mode ;) */
+ size_t size = 1; /* # of bytes decoded [1 for modR/M byte] */
+ x86_ea_t * ea = &op->data.expression;
+
+ switch( modrm->rm ) {
+ case MOD16_RM_BXSI:
+ ia32_handle_register(&ea->base, REG_WORD_OFFSET + 3);
+ ia32_handle_register(&ea->index, REG_WORD_OFFSET + 6);
+ break;
+ case MOD16_RM_BXDI:
+ ia32_handle_register(&ea->base, REG_WORD_OFFSET + 3);
+ ia32_handle_register(&ea->index, REG_WORD_OFFSET + 7);
+ case MOD16_RM_BPSI:
+ op->flags |= op_ss_seg;
+ ia32_handle_register(&ea->base, REG_WORD_OFFSET + 5);
+ ia32_handle_register(&ea->index, REG_WORD_OFFSET + 6);
+ break;
+ case MOD16_RM_BPDI:
+ op->flags |= op_ss_seg;
+ ia32_handle_register(&ea->base, REG_WORD_OFFSET + 5);
+ ia32_handle_register(&ea->index, REG_WORD_OFFSET + 7);
+ break;
+ case MOD16_RM_SI:
+ ia32_handle_register(&ea->base, REG_WORD_OFFSET + 6);
+ break;
+ case MOD16_RM_DI:
+ ia32_handle_register(&ea->base, REG_WORD_OFFSET + 7);
+ break;
+ case MOD16_RM_BP:
+ if ( modrm->mod != MOD16_MOD_NODISP ) {
+ op->flags |= op_ss_seg;
+ ia32_handle_register(&ea->base,
+ REG_WORD_OFFSET + 5);
+ }
+ break;
+ case MOD16_RM_BX:
+ ia32_handle_register(&ea->base, REG_WORD_OFFSET + 3);
+ break;
+ }
+
+ /* move to byte after ModR/M */
+ ++buf;
+ --buf_len;
+
+ if ( modrm->mod == MOD16_MOD_DISP8 ) {
+ imm32_signsized( buf, buf_len, &ea->disp, sizeof(char) );
+ ea->disp_sign = (ea->disp < 0) ? 1 : 0;
+ ea->disp_size = sizeof(char);
+ size += sizeof(char);
+ } else if ( modrm->mod == MOD16_MOD_DISP16 ) {
+ imm32_signsized( buf, buf_len, &ea->disp, sizeof(short) );
+ ea->disp_sign = (ea->disp < 0) ? 1 : 0;
+ ea->disp_size = sizeof(short);
+ size += sizeof(short);
+ }
+
+ return size;
+}
+
+/* TODO : Mark index modes
+ Use addressing mode flags to imply arrays (index), structure (disp),
+ two-dimensional arrays [disp + index], classes [ea reg], and so on.
+*/
+size_t ia32_modrm_decode( unsigned char *buf, unsigned int buf_len,
+ x86_op_t *op, x86_insn_t *insn, size_t gen_regs ) {
+ /* create address expression and/or fill operand based on value of
+ * ModR/M byte. Calls sib_decode as appropriate.
+ * flags specifies whether Reg or mod+R/M fields are being decoded
+ * returns the number of bytes in the instruction, including modR/M */
+ struct modRM_byte modrm;
+ size_t size = 1; /* # of bytes decoded [1 for modR/M byte] */
+ x86_ea_t * ea;
+
+
+ byte_decode(*buf, &modrm); /* get bitfields */
+
+ /* first, handle the case where the mod field is a register only */
+ if ( modrm.mod == MODRM_MOD_NOEA ) {
+ op->type = op_register;
+ ia32_handle_register(&op->data.reg, modrm.rm + gen_regs);
+ /* increase insn size by 1 for modrm byte */
+ return 1;
+ }
+
+ /* then deal with cases where there is an effective address */
+ ea = &op->data.expression;
+ op->type = op_expression;
+ op->flags |= op_pointer;
+
+ if ( insn->addr_size == 2 ) {
+ /* gah! 16 bit mode! */
+ return modrm_decode16( buf, buf_len, op, &modrm);
+ }
+
+ /* move to byte after ModR/M */
+ ++buf;
+ --buf_len;
+
+ if (modrm.mod == MODRM_MOD_NODISP) { /* if mod == 00 */
+
+ /* IF MOD == No displacement, just Indirect Register */
+ if (modrm.rm == MODRM_RM_NOREG) { /* if r/m == 101 */
+ /* IF RM == No Register, just Displacement */
+ /* This is an Intel Moronic Exception TM */
+ imm32_signsized( buf, buf_len, &ea->disp,
+ sizeof(int32_t) );
+ ea->disp_size = sizeof(int32_t);
+ ea->disp_sign = (ea->disp < 0) ? 1 : 0;
+ size += 4; /* add sizeof disp to count */
+
+ } else if (modrm.rm == MODRM_RM_SIB) { /* if r/m == 100 */
+ /* ELSE IF an SIB byte is present */
+ /* TODO: check for 0 retval */
+ size += sib_decode( buf, buf_len, ea, modrm.mod);
+ /* move to byte after SIB for displacement */
+ ++buf;
+ --buf_len;
+ } else { /* modR/M specifies base register */
+ /* ELSE RM encodes a general register */
+ ia32_handle_register( &ea->base, modrm.rm + 1 );
+ }
+ } else { /* mod is 01 or 10 */
+ if (modrm.rm == MODRM_RM_SIB) { /* rm == 100 */
+ /* IF base is an AddrExpr specified by an SIB byte */
+ /* TODO: check for 0 retval */
+ size += sib_decode( buf, buf_len, ea, modrm.mod);
+ /* move to byte after SIB for displacement */
+ ++buf;
+ --buf_len;
+ } else {
+ /* ELSE base is a general register */
+ ia32_handle_register( &ea->base, modrm.rm + 1 );
+ }
+
+ /* ELSE mod + r/m specify a disp##[base] or disp##(SIB) */
+ if (modrm.mod == MODRM_MOD_DISP8) { /* mod == 01 */
+ /* If this is an 8-bit displacement */
+ imm32_signsized( buf, buf_len, &ea->disp,
+ sizeof(char));
+ ea->disp_size = sizeof(char);
+ ea->disp_sign = (ea->disp < 0) ? 1 : 0;
+ size += 1; /* add sizeof disp to count */
+
+ } else {
+ /* Displacement is dependent on address size */
+ imm32_signsized( buf, buf_len, &ea->disp,
+ insn->addr_size);
+ ea->disp_size = insn->addr_size;
+ ea->disp_sign = (ea->disp < 0) ? 1 : 0;
+ size += 4;
+ }
+ }
+
+ return size; /* number of bytes found in instruction */
+}
+
+void ia32_reg_decode( unsigned char byte, x86_op_t *op, size_t gen_regs ) {
+ struct modRM_byte modrm;
+ byte_decode( byte, &modrm ); /* get bitfields */
+
+ /* set operand to register ID */
+ op->type = op_register;
+ ia32_handle_register(&op->data.reg, modrm.reg + gen_regs);
+
+ return;
+}
diff --git a/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/ia32_modrm.h b/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/ia32_modrm.h
new file mode 100644
index 0000000000..765cb0833b
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/ia32_modrm.h
@@ -0,0 +1,13 @@
+#ifndef IA32_MODRM_H
+#define IA32_MODRM_H
+
+#include "libdis.h"
+#include "ia32_insn.h"
+
+size_t ia32_modrm_decode( unsigned char *buf, unsigned int buf_len,
+ x86_op_t *op, x86_insn_t *insn,
+ size_t gen_regs );
+
+void ia32_reg_decode( unsigned char byte, x86_op_t *op, size_t gen_regs );
+
+#endif
diff --git a/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/ia32_opcode_tables.c b/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/ia32_opcode_tables.c
new file mode 100644
index 0000000000..ef97c7a351
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/ia32_opcode_tables.c
@@ -0,0 +1,2939 @@
+#include "ia32_insn.h"
+
+#include "ia32_reg.h"
+
+#include "ia32_opcode_tables.h"
+
+static ia32_insn_t tbl_Main[] = { /* One-byte Opcodes */
+ { 0, INS_ADD, 0, ADDRMETH_E | OPTYPE_b | OP_W | OP_R, ADDRMETH_G | OPTYPE_b | OP_R, ARG_NONE, cpu_80386 | isa_GP, "add", "", 0, 0, 0, INS_SET_ALL, 0 },
+ { 0, INS_ADD, 0, ADDRMETH_E | OPTYPE_v | OP_W | OP_R, ADDRMETH_G | OPTYPE_v | OP_R, ARG_NONE, cpu_80386 | isa_GP, "add", "", 0, 0, 0, INS_SET_ALL, 0 },
+ { 0, INS_ADD, 0, ADDRMETH_G | OPTYPE_b | OP_W | OP_R, ADDRMETH_E | OPTYPE_b | OP_R, ARG_NONE, cpu_80386 | isa_GP, "add", "", 0, 0, 0, INS_SET_ALL, 0 },
+ { 0, INS_ADD, 0, ADDRMETH_G | OPTYPE_v | OP_W | OP_R, ADDRMETH_E | OPTYPE_v | OP_R, ARG_NONE, cpu_80386 | isa_GP, "add", "", 0, 0, 0, INS_SET_ALL, 0 },
+ { 0, INS_ADD, 0, ADDRMETH_RR | OPTYPE_b | OP_W | OP_R, ADDRMETH_I | OPTYPE_b | OP_SIGNED | OP_R, ARG_NONE, cpu_80386 | isa_GP, "add", "", 0, 0, 0, INS_SET_ALL, 0 },
+ { 0, INS_ADD, 0, ADDRMETH_RR | OPTYPE_v | OP_W | OP_R, ADDRMETH_I | OPTYPE_v | OP_SIGNED | OP_R, ARG_NONE, cpu_80386 | isa_GP, "add", "", 0, 0, 0, INS_SET_ALL, 0 },
+ { 0, INS_PUSH, 0, ADDRMETH_RS | OPTYPE_w | OP_R, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "push", "", 0, 0, 0, 0 , 33 },
+ { 0, INS_POP, 0, ADDRMETH_RS | OPTYPE_w | OP_W, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "pop", "", 0, 0, 0, 0 , 33 },
+ { 0, INS_OR, 0, ADDRMETH_E | OPTYPE_b | OP_W | OP_R, ADDRMETH_G | OPTYPE_b | OP_R, ARG_NONE, cpu_80386 | isa_GP, "or", "", 0, 0, 0, INS_SET_ALL, 0 },
+ { 0, INS_OR, 0, ADDRMETH_E | OPTYPE_v | OP_W | OP_R, ADDRMETH_G | OPTYPE_v | OP_R, ARG_NONE, cpu_80386 | isa_GP, "or", "", 0, 0, 0, INS_SET_ALL, 0 },
+ { 0, INS_OR, 0, ADDRMETH_G | OPTYPE_b | OP_W | OP_R, ADDRMETH_E | OPTYPE_b | OP_R, ARG_NONE, cpu_80386 | isa_GP, "or", "", 0, 0, 0, INS_SET_ALL, 0 },
+ { 0, INS_OR, 0, ADDRMETH_G | OPTYPE_v | OP_W | OP_R, ADDRMETH_E | OPTYPE_v | OP_R, ARG_NONE, cpu_80386 | isa_GP, "or", "", 0, 0, 0, INS_SET_ALL, 0 },
+ { 0, INS_OR, 0, ADDRMETH_RR | OPTYPE_b | OP_W | OP_R, ADDRMETH_I | OPTYPE_b | OP_R, ARG_NONE, cpu_80386 | isa_GP, "or", "", 0, 0, 0, INS_SET_ALL, 0 },
+ { 0, INS_OR, 0, ADDRMETH_RR | OPTYPE_v | OP_W | OP_R, ADDRMETH_I | OPTYPE_v | OP_R, ARG_NONE, cpu_80386 | isa_GP, "or", "", 0, 0, 0, INS_SET_ALL, 0 },
+ { 0, INS_PUSH, 0, ADDRMETH_RS | OPTYPE_w | OP_R, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "push", "", 1, 0, 0, 0 , 33 },
+ { idx_0F, 0, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "", "", 0, 0, 0, 0 , 0 },
+/* 0x10 */
+ { 0, INS_ADD, 0, ADDRMETH_E | OPTYPE_b | OP_W | OP_R, ADDRMETH_G | OPTYPE_b | OP_R, ARG_NONE, cpu_80386 | isa_GP, "adc", "", 0, 0, 0, INS_SET_ALL|INS_TEST_CARRY, 0 },
+ { 0, INS_ADD, 0, ADDRMETH_E | OPTYPE_v | OP_W | OP_R, ADDRMETH_G | OPTYPE_v | OP_R, ARG_NONE, cpu_80386 | isa_GP, "adc", "", 0, 0, 0, INS_SET_ALL|INS_TEST_CARRY, 0 },
+ { 0, INS_ADD, 0, ADDRMETH_G | OPTYPE_b | OP_W | OP_R, ADDRMETH_E | OPTYPE_b | OP_R, ARG_NONE, cpu_80386 | isa_GP, "adc", "", 0, 0, 0, INS_SET_ALL|INS_TEST_CARRY, 0 },
+ { 0, INS_ADD, 0, ADDRMETH_G | OPTYPE_v | OP_W | OP_R, ADDRMETH_E | OPTYPE_v | OP_R, ARG_NONE, cpu_80386 | isa_GP, "adc", "", 0, 0, 0, INS_SET_ALL|INS_TEST_CARRY, 0 },
+ { 0, INS_ADD, 0, ADDRMETH_RR | OPTYPE_b | OP_W | OP_R, ADDRMETH_I | OPTYPE_b | OP_SIGNED | OP_R, ARG_NONE, cpu_80386 | isa_GP, "adc", "", 0, 0, 0, INS_SET_ALL|INS_TEST_CARRY, 0 },
+ { 0, INS_ADD, 0, ADDRMETH_RR | OPTYPE_v | OP_W | OP_R, ADDRMETH_I | OPTYPE_v | OP_SIGNED | OP_R, ARG_NONE, cpu_80386 | isa_GP, "adc", "", 0, 0, 0, INS_SET_ALL|INS_TEST_CARRY, 0 },
+ { 0, INS_PUSH, 0, ADDRMETH_RS | OPTYPE_w | OP_R, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "push", "", 2, 0, 0, 0 , 33 },
+ { 0, INS_POP, 0, ADDRMETH_RS | OPTYPE_w | OP_W, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "pop", "", 2, 0, 0, 0 , 33 },
+ { 0, INS_SUB, 0, ADDRMETH_E | OPTYPE_b | OP_SIGNED | OP_W | OP_R, ADDRMETH_G | OPTYPE_b | OP_SIGNED | OP_R, ARG_NONE, cpu_80386 | isa_GP, "sbb", "", 0, 0, 0, INS_SET_ALL|INS_TEST_CARRY, 0 },
+ { 0, INS_SUB, 0, ADDRMETH_E | OPTYPE_v | OP_SIGNED | OP_W | OP_R, ADDRMETH_G | OPTYPE_v | OP_SIGNED | OP_R, ARG_NONE, cpu_80386 | isa_GP, "sbb", "", 0, 0, 0, INS_SET_ALL|INS_TEST_CARRY, 0 },
+ { 0, INS_SUB, 0, ADDRMETH_G | OPTYPE_b | OP_W | OP_SIGNED | OP_R, ADDRMETH_E | OPTYPE_b | OP_SIGNED | OP_R, ARG_NONE, cpu_80386 | isa_GP, "sbb", "", 0, 0, 0, INS_SET_ALL|INS_TEST_CARRY, 0 },
+ { 0, INS_SUB, 0, ADDRMETH_G | OPTYPE_v | OP_SIGNED | OP_W | OP_R, ADDRMETH_E | OPTYPE_v | OP_SIGNED | OP_R, ARG_NONE, cpu_80386 | isa_GP, "sbb", "", 0, 0, 0, INS_SET_ALL|INS_TEST_CARRY, 0 },
+ { 0, INS_SUB, 0, ADDRMETH_RR | OPTYPE_b | OP_SIGNED | OP_W | OP_R, ADDRMETH_I | OPTYPE_b | OP_SIGNED | OP_R, ARG_NONE, cpu_80386 | isa_GP, "sbb", "", 0, 0, 0, INS_SET_ALL|INS_TEST_CARRY, 0 },
+ { 0, INS_SUB, 0, ADDRMETH_RR | OPTYPE_v | OP_SIGNED | OP_W | OP_R, ADDRMETH_I | OPTYPE_v | OP_SIGNED | OP_R, ARG_NONE, cpu_80386 | isa_GP, "sbb", "", 0, 0, 0, INS_SET_ALL|INS_TEST_CARRY, 0 },
+ { 0, INS_PUSH, 0, ADDRMETH_RS | OPTYPE_w | OP_R, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "push", "", 3, 0, 0, 0 , 33 },
+ { 0, INS_POP, 0, ADDRMETH_RS | OPTYPE_w | OP_W, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "pop", "", 3, 0, 0, 0 , 33 },
+/* 0x20 */
+ { 0, INS_AND, 0, ADDRMETH_E | OPTYPE_b | OP_W | OP_R, ADDRMETH_G | OPTYPE_b | OP_R, ARG_NONE, cpu_80386 | isa_GP, "and", "", 0, 0, 0, INS_SET_ALL, 0 },
+ { 0, INS_AND, 0, ADDRMETH_E | OPTYPE_v | OP_W | OP_R, ADDRMETH_G | OPTYPE_v | OP_R, ARG_NONE, cpu_80386 | isa_GP, "and", "", 0, 0, 0, INS_SET_ALL, 0 },
+ { 0, INS_AND, 0, ADDRMETH_G | OPTYPE_b | OP_W | OP_R, ADDRMETH_E | OPTYPE_b | OP_R, ARG_NONE, cpu_80386 | isa_GP, "and", "", 0, 0, 0, INS_SET_ALL, 0 },
+ { 0, INS_AND, 0, ADDRMETH_G | OPTYPE_v | OP_W | OP_R, ADDRMETH_E | OPTYPE_v | OP_R, ARG_NONE, cpu_80386 | isa_GP, "and", "", 0, 0, 0, INS_SET_ALL, 0 },
+ { 0, INS_AND, 0, ADDRMETH_RR | OPTYPE_b | OP_W | OP_R, ADDRMETH_I | OPTYPE_b | OP_SIGNED | OP_R, ARG_NONE, cpu_80386 | isa_GP, "and", "", 0, 0, 0, INS_SET_ALL, 0 },
+ { 0, INS_AND, 0, ADDRMETH_RR | OPTYPE_v | OP_W | OP_R, ADDRMETH_I | OPTYPE_v | OP_R, ARG_NONE, cpu_80386 | isa_GP, "and", "", 0, 0, 0, INS_SET_ALL, 0 },
+ { 0, INS_FLAG_PREFIX | PREFIX_ES, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_BCDCONV, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "daa", "", 0, 0, 0, INS_SET_SIGN|INS_SET_ZERO|INS_SET_CARRY|INS_SET_PARITY|INS_TEST_CARRY, 12 },
+ { 0, INS_SUB, 0, ADDRMETH_E | OPTYPE_b | OP_SIGNED | OP_W | OP_R, ADDRMETH_G | OPTYPE_b | OP_SIGNED | OP_R, ARG_NONE, cpu_80386 | isa_GP, "sub", "", 0, 0, 0, INS_SET_ALL, 0 },
+ { 0, INS_SUB, 0, ADDRMETH_E | OPTYPE_v | OP_SIGNED | OP_W | OP_R, ADDRMETH_G | OPTYPE_v | OP_SIGNED | OP_R, ARG_NONE, cpu_80386 | isa_GP, "sub", "", 0, 0, 0, INS_SET_ALL, 0 },
+ { 0, INS_SUB, 0, ADDRMETH_G | OPTYPE_b | OP_SIGNED | OP_W | OP_R, ADDRMETH_E | OPTYPE_b | OP_SIGNED | OP_R, ARG_NONE, cpu_80386 | isa_GP, "sub", "", 0, 0, 0, INS_SET_ALL, 0 },
+ { 0, INS_SUB, 0, ADDRMETH_G | OPTYPE_v | OP_SIGNED | OP_W | OP_R, ADDRMETH_E | OPTYPE_v | OP_SIGNED | OP_R, ARG_NONE, cpu_80386 | isa_GP, "sub", "", 0, 0, 0, INS_SET_ALL, 0 },
+ { 0, INS_SUB, 0, ADDRMETH_RR | OPTYPE_b | OP_SIGNED | OP_W | OP_R, ADDRMETH_I | OPTYPE_b | OP_SIGNED | OP_R, ARG_NONE, cpu_80386 | isa_GP, "sub", "", 0, 0, 0, INS_SET_ALL, 0 },
+ { 0, INS_SUB, 0, ADDRMETH_RR | OPTYPE_v | OP_SIGNED | OP_W | OP_R, ADDRMETH_I | OPTYPE_v | OP_SIGNED | OP_R, ARG_NONE, cpu_80386 | isa_GP, "sub", "", 0, 0, 0, INS_SET_ALL, 0 },
+ { 0, INS_FLAG_PREFIX | PREFIX_CS | PREFIX_NOTTAKEN, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_BCDCONV, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "das", "", 0, 0, 0, INS_SET_SIGN|INS_SET_ZERO|INS_SET_CARRY|INS_SET_PARITY|INS_TEST_CARRY, 0 },
+/* 0x30 */
+ { 0, INS_XOR, 0, ADDRMETH_E | OPTYPE_b | OP_W | OP_R, ADDRMETH_G | OPTYPE_b | OP_R, ARG_NONE, cpu_80386 | isa_GP, "xor", "", 0, 0, 0, INS_SET_ALL, 0 },
+ { 0, INS_XOR, 0, ADDRMETH_E | OPTYPE_v | OP_W | OP_R, ADDRMETH_G | OPTYPE_v | OP_R, ARG_NONE, cpu_80386 | isa_GP, "xor", "", 0, 0, 0, INS_SET_ALL, 0 },
+ { 0, INS_XOR, 0, ADDRMETH_G | OPTYPE_b | OP_W | OP_R, ADDRMETH_E | OPTYPE_b | OP_R, ARG_NONE, cpu_80386 | isa_GP, "xor", "", 0, 0, 0, INS_SET_ALL, 0 },
+ { 0, INS_XOR, 0, ADDRMETH_G | OPTYPE_v | OP_W | OP_R, ADDRMETH_E | OPTYPE_v | OP_R, ARG_NONE, cpu_80386 | isa_GP, "xor", "", 0, 0, 0, INS_SET_ALL, 0 },
+ { 0, INS_XOR, 0, ADDRMETH_RR | OPTYPE_b | OP_W | OP_R, ADDRMETH_I | OPTYPE_b | OP_R, ARG_NONE, cpu_80386 | isa_GP, "xor", "", 0, 0, 0, INS_SET_ALL, 0 },
+ { 0, INS_XOR, 0, ADDRMETH_RR | OPTYPE_v | OP_W | OP_R, ADDRMETH_I | OPTYPE_v | OP_R, ARG_NONE, cpu_80386 | isa_GP, "xor", "", 0, 0, 0, INS_SET_ALL, 0 },
+ { 0, INS_FLAG_PREFIX | PREFIX_SS, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_BCDCONV, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "aaa", "", 0, 0, 0, INS_SET_CARRY, 1 },
+ { 0, INS_CMP, 0, ADDRMETH_E | OPTYPE_b | OP_R, ADDRMETH_G | OPTYPE_b | OP_R, ARG_NONE, cpu_80386 | isa_GP, "cmp", "", 0, 0, 0, INS_SET_ALL, 0 },
+ { 0, INS_CMP, 0, ADDRMETH_E | OPTYPE_v | OP_R, ADDRMETH_G | OPTYPE_v | OP_R, ARG_NONE, cpu_80386 | isa_GP, "cmp", "", 0, 0, 0, INS_SET_ALL, 0 },
+ { 0, INS_CMP, 0, ADDRMETH_G | OPTYPE_b | OP_R, ADDRMETH_E | OPTYPE_b | OP_R, ARG_NONE, cpu_80386 | isa_GP, "cmp", "", 0, 0, 0, INS_SET_ALL, 0 },
+ { 0, INS_CMP, 0, ADDRMETH_G | OPTYPE_v | OP_R, ADDRMETH_E | OPTYPE_v | OP_R, ARG_NONE, cpu_80386 | isa_GP, "cmp", "", 0, 0, 0, INS_SET_ALL, 0 },
+ { 0, INS_CMP, 0, ADDRMETH_RR | OPTYPE_b | OP_R, ADDRMETH_I | OPTYPE_b | OP_SIGNED | OP_R, ARG_NONE, cpu_80386 | isa_GP, "cmp", "", 0, 0, 0, INS_SET_ALL, 0 },
+ { 0, INS_CMP, 0, ADDRMETH_RR | OPTYPE_v | OP_R, ADDRMETH_I | OPTYPE_v | OP_SIGNED | OP_R, ARG_NONE, cpu_80386 | isa_GP, "cmp", "", 0, 0, 0, INS_SET_ALL, 0 },
+ { 0, INS_FLAG_PREFIX | PREFIX_DS | PREFIX_TAKEN, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_BCDCONV, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "aas", "", 0, 0, 0, INS_SET_CARRY, 0 },
+/* 0x40 */
+ { 0, INS_INC, 0, ADDRMETH_RR | OPTYPE_v | OP_R | OP_W, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "inc", "", 0, 0, 0, INS_SET_OFLOW|INS_SET_SIGN|INS_SET_ZERO|INS_SET_PARITY, 0 },
+ { 0, INS_INC, 0, ADDRMETH_RR | OPTYPE_v | OP_R | OP_W, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "inc", "", 1, 0, 0, INS_SET_OFLOW|INS_SET_SIGN|INS_SET_ZERO|INS_SET_PARITY, 0 },
+ { 0, INS_INC, 0, ADDRMETH_RR | OPTYPE_v | OP_R | OP_W, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "inc", "", 2, 0, 0, INS_SET_OFLOW|INS_SET_SIGN|INS_SET_ZERO|INS_SET_PARITY, 0 },
+ { 0, INS_INC, 0, ADDRMETH_RR | OPTYPE_v | OP_R | OP_W, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "inc", "", 3, 0, 0, INS_SET_OFLOW|INS_SET_SIGN|INS_SET_ZERO|INS_SET_PARITY, 0 },
+ { 0, INS_INC, 0, ADDRMETH_RR | OPTYPE_v | OP_R | OP_W, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "inc", "", 4, 0, 0, INS_SET_OFLOW|INS_SET_SIGN|INS_SET_ZERO|INS_SET_PARITY, 0 },
+ { 0, INS_INC, 0, ADDRMETH_RR | OPTYPE_v | OP_R | OP_W, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "inc", "", 5, 0, 0, INS_SET_OFLOW|INS_SET_SIGN|INS_SET_ZERO|INS_SET_PARITY, 0 },
+ { 0, INS_INC, 0, ADDRMETH_RR | OPTYPE_v | OP_R | OP_W, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "inc", "", 6, 0, 0, INS_SET_OFLOW|INS_SET_SIGN|INS_SET_ZERO|INS_SET_PARITY, 0 },
+ { 0, INS_INC, 0, ADDRMETH_RR | OPTYPE_v | OP_R | OP_W, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "inc", "", 7, 0, 0, INS_SET_OFLOW|INS_SET_SIGN|INS_SET_ZERO|INS_SET_PARITY, 0 },
+ { 0, INS_DEC, 0, ADDRMETH_RR | OPTYPE_v | OP_W | OP_R, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "dec", "", 0, 0, 0, INS_SET_OFLOW|INS_SET_SIGN|INS_SET_ZERO|INS_SET_PARITY, 0 },
+ { 0, INS_DEC, 0, ADDRMETH_RR | OPTYPE_v | OP_W | OP_R, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "dec", "", 1, 0, 0, INS_SET_OFLOW|INS_SET_SIGN|INS_SET_ZERO|INS_SET_PARITY, 0 },
+ { 0, INS_DEC, 0, ADDRMETH_RR | OPTYPE_v | OP_W | OP_R, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "dec", "", 2, 0, 0, INS_SET_OFLOW|INS_SET_SIGN|INS_SET_ZERO|INS_SET_PARITY, 0 },
+ { 0, INS_DEC, 0, ADDRMETH_RR | OPTYPE_v | OP_W | OP_R, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "dec", "", 3, 0, 0, INS_SET_OFLOW|INS_SET_SIGN|INS_SET_ZERO|INS_SET_PARITY, 0 },
+ { 0, INS_DEC, 0, ADDRMETH_RR | OPTYPE_v | OP_W | OP_R, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "dec", "", 4, 0, 0, INS_SET_OFLOW|INS_SET_SIGN|INS_SET_ZERO|INS_SET_PARITY, 0 },
+ { 0, INS_DEC, 0, ADDRMETH_RR | OPTYPE_v | OP_W | OP_R, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "dec", "", 5, 0, 0, INS_SET_OFLOW|INS_SET_SIGN|INS_SET_ZERO|INS_SET_PARITY, 0 },
+ { 0, INS_DEC, 0, ADDRMETH_RR | OPTYPE_v | OP_W | OP_R, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "dec", "", 6, 0, 0, INS_SET_OFLOW|INS_SET_SIGN|INS_SET_ZERO|INS_SET_PARITY, 0 },
+ { 0, INS_DEC, 0, ADDRMETH_RR | OPTYPE_v | OP_W | OP_R, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "dec", "", 7, 0, 0, INS_SET_OFLOW|INS_SET_SIGN|INS_SET_ZERO|INS_SET_PARITY, 0 },
+/* 0x50 */
+ { 0, INS_PUSH, 0, ADDRMETH_RR | OPTYPE_v | OP_R, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "push", "", 0, 0, 0, 0 , 33 },
+ { 0, INS_PUSH, 0, ADDRMETH_RR | OPTYPE_v | OP_R, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "push", "", 1, 0, 0, 0 , 33 },
+ { 0, INS_PUSH, 0, ADDRMETH_RR | OPTYPE_v | OP_R, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "push", "", 2, 0, 0, 0 , 33 },
+ { 0, INS_PUSH, 0, ADDRMETH_RR | OPTYPE_v | OP_R, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "push", "", 3, 0, 0, 0 , 33 },
+ { 0, INS_PUSH, 0, ADDRMETH_RR | OPTYPE_v | OP_R, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "push", "", 4, 0, 0, 0 , 33 },
+ { 0, INS_PUSH, 0, ADDRMETH_RR | OPTYPE_v | OP_R, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "push", "", 5, 0, 0, 0 , 33 },
+ { 0, INS_PUSH, 0, ADDRMETH_RR | OPTYPE_v | OP_R, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "push", "", 6, 0, 0, 0 , 33 },
+ { 0, INS_PUSH, 0, ADDRMETH_RR | OPTYPE_v | OP_R, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "push", "", 7, 0, 0, 0 , 33 },
+ { 0, INS_POP, 0, ADDRMETH_RR | OPTYPE_v | OP_W, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "pop", "", 0, 0, 0, 0 , 33 },
+ { 0, INS_POP, 0, ADDRMETH_RR | OPTYPE_v | OP_W, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "pop", "", 1, 0, 0, 0 , 33 },
+ { 0, INS_POP, 0, ADDRMETH_RR | OPTYPE_v | OP_W, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "pop", "", 2, 0, 0, 0 , 33 },
+ { 0, INS_POP, 0, ADDRMETH_RR | OPTYPE_v | OP_W, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "pop", "", 3, 0, 0, 0 , 33 },
+ { 0, INS_POP, 0, ADDRMETH_RR | OPTYPE_v | OP_W, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "pop", "", 4, 0, 0, 0 , 33 },
+ { 0, INS_POP, 0, ADDRMETH_RR | OPTYPE_v | OP_W, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "pop", "", 5, 0, 0, 0 , 33 },
+ { 0, INS_POP, 0, ADDRMETH_RR | OPTYPE_v | OP_W, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "pop", "", 6, 0, 0, 0 , 33 },
+ { 0, INS_POP, 0, ADDRMETH_RR | OPTYPE_v | OP_W, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "pop", "", 7, 0, 0, 0 , 33 },
+/* 0x60 */
+ { 0, INS_PUSHREGS, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "pusha", "", 0, 0, 0, 0 , 36 },
+ { 0, INS_POPREGS, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "popa", "", 0, 0, 0, 0 , 34 },
+ { 0, INS_BOUNDS, INS_NOTE_NONSWAP, ADDRMETH_G | OPTYPE_v | OP_R, ADDRMETH_M | OPTYPE_a | OP_SIGNED | OP_R, ARG_NONE, cpu_80386 | isa_GP, "bound", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_SYSTEM, 0, ADDRMETH_E | OPTYPE_w | OP_R | OP_W, ADDRMETH_G | OPTYPE_w | OP_R, ARG_NONE, cpu_80386 | isa_GP, "arpl", "", 0, 0, 0, INS_SET_ZERO, 0 },
+ { 0, INS_FLAG_PREFIX | PREFIX_FS, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_FLAG_PREFIX | PREFIX_GS, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "", "", 0, 0, 0, 0 , 0 },
+ { idx_66, INS_FLAG_PREFIX | PREFIX_OP_SIZE, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_FLAG_PREFIX | PREFIX_ADDR_SIZE, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_PUSH, 0, ADDRMETH_I | OPTYPE_v | OP_R, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "push", "", 0, 0, 0, 0 , 33 },
+ { 0, INS_MUL, 0, ADDRMETH_G | OPTYPE_v | OP_SIGNED | OP_R | OP_W, ADDRMETH_E | OPTYPE_v | OP_SIGNED | OP_R, ADDRMETH_I | OPTYPE_v | OP_SIGNED | OP_R, cpu_80386 | isa_GP, "imul", "", 0, 0, 0, INS_SET_OFLOW|INS_SET_CARRY, 0 },
+ { 0, INS_PUSH, 0, ADDRMETH_I | OPTYPE_b | OP_SIGNED | OP_R, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "push", "", 0, 0, 0, 0 , 33 },
+ { 0, INS_MUL, 0, ADDRMETH_G | OPTYPE_v | OP_SIGNED | OP_R | OP_W, ADDRMETH_E | OPTYPE_v | OP_SIGNED | OP_R, ADDRMETH_I | OPTYPE_b | OP_SIGNED | OP_R, cpu_80386 | isa_GP, "imul", "", 0, 0, 0, INS_SET_OFLOW|INS_SET_CARRY, 0 },
+ { 0, INS_IN, 0, ADDRMETH_Y | OPTYPE_b | OP_W, ADDRMETH_RR | OPTYPE_b | OP_R, ARG_NONE, cpu_80386 | isa_GP, "ins", "", 0, 2, 0, 0 , 0 },
+ { 0, INS_IN, 0, ADDRMETH_Y | OPTYPE_v | OP_W, ADDRMETH_RR | OPTYPE_v | OP_R, ARG_NONE, cpu_80386 | isa_GP, "ins", "", 0, 2, 0, 0 , 0 },
+ { 0, INS_OUT, 0, ADDRMETH_RR | OPTYPE_b | OP_R, ADDRMETH_X | OPTYPE_b | OP_R, ARG_NONE, cpu_80386 | isa_GP, "outs", "", 2, 0, 0, 0 , 0 },
+ { 0, INS_OUT, 0, ADDRMETH_RR | OPTYPE_v | OP_R, ADDRMETH_X | OPTYPE_v | OP_R, ARG_NONE, cpu_80386 | isa_GP, "outs", "", 2, 0, 0, 0 , 0 },
+/* 0x70 */
+ { 0, INS_BRANCHCC, 0, ADDRMETH_J | OPTYPE_b | OP_X, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "jo", "", 0, 0, 0, INS_TEST_OFLOW, 0 },
+ { 0, INS_BRANCHCC, 0, ADDRMETH_J | OPTYPE_b | OP_X, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "jno", "", 0, 0, 0, INS_TEST_NOFLOW, 0 },
+ { 0, INS_BRANCHCC, 0, ADDRMETH_J | OPTYPE_b | OP_X, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "jc", "", 0, 0, 0, INS_TEST_CARRY, 0 },
+ { 0, INS_BRANCHCC, 0, ADDRMETH_J | OPTYPE_b | OP_X, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "jnc", "", 0, 0, 0, INS_TEST_NCARRY, 0 },
+ { 0, INS_BRANCHCC, 0, ADDRMETH_J | OPTYPE_b | OP_X, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "jz", "", 0, 0, 0, INS_TEST_ZERO, 0 },
+ { 0, INS_BRANCHCC, 0, ADDRMETH_J | OPTYPE_b | OP_X, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "jnz", "", 0, 0, 0, INS_TEST_NZERO, 0 },
+ { 0, INS_BRANCHCC, 0, ADDRMETH_J | OPTYPE_b | OP_X, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "jbe", "", 0, 0, 0, INS_TEST_CARRY|INS_TEST_OR|INS_TEST_ZERO, 0 },
+ { 0, INS_BRANCHCC, 0, ADDRMETH_J | OPTYPE_b | OP_X, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "ja", "", 0, 0, 0, INS_TEST_NCARRY|INS_TEST_NZERO, 0 },
+ { 0, INS_BRANCHCC, 0, ADDRMETH_J | OPTYPE_b | OP_X, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "js", "", 0, 0, 0, INS_TEST_SIGN, 0 },
+ { 0, INS_BRANCHCC, 0, ADDRMETH_J | OPTYPE_b | OP_X, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "jns", "", 0, 0, 0, INS_TEST_NSIGN, 0 },
+ { 0, INS_BRANCHCC, 0, ADDRMETH_J | OPTYPE_b | OP_X, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "jpe", "", 0, 0, 0, INS_TEST_PARITY, 0 },
+ { 0, INS_BRANCHCC, 0, ADDRMETH_J | OPTYPE_b | OP_X, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "jpo", "", 0, 0, 0, INS_TEST_NPARITY, 0 },
+ { 0, INS_BRANCHCC, 0, ADDRMETH_J | OPTYPE_b | OP_X, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "jl", "", 0, 0, 0, INS_TEST_SFNEOF, 0 },
+ { 0, INS_BRANCHCC, 0, ADDRMETH_J | OPTYPE_b | OP_X, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "jge", "", 0, 0, 0, INS_TEST_SFEQOF, 0 },
+ { 0, INS_BRANCHCC, 0, ADDRMETH_J | OPTYPE_b | OP_X, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "jle", "", 0, 0, 0, INS_TEST_ZERO|INS_TEST_OR|INS_TEST_SFNEOF, 0 },
+ { 0, INS_BRANCHCC, 0, ADDRMETH_J | OPTYPE_b | OP_X, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "jg", "", 0, 0, 0, INS_TEST_NZERO|INS_TEST_SFEQOF, 0 },
+/* 0x80 */
+ { idx_80, 0, 0, ADDRMETH_E | OPTYPE_b, ADDRMETH_I | OPTYPE_b, ARG_NONE, cpu_80386 | isa_GP, "", "", 0, 0, 0, 0 , 0 },
+ { idx_81, 0, 0, ADDRMETH_E | OPTYPE_v, ADDRMETH_I | OPTYPE_v, ARG_NONE, cpu_80386 | isa_GP, "", "", 0, 0, 0, 0 , 0 },
+ { idx_82, 0, 0, ADDRMETH_E | OPTYPE_b, ADDRMETH_I | OPTYPE_b, ARG_NONE, cpu_80386 | isa_GP, "", "", 0, 0, 0, 0 , 0 },
+ { idx_83, 0, 0, ADDRMETH_E | OPTYPE_v, ADDRMETH_I | OPTYPE_b, ARG_NONE, cpu_80386 | isa_GP, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_TEST, 0, ADDRMETH_E | OPTYPE_b | OP_R, ADDRMETH_G | OPTYPE_b | OP_R, ARG_NONE, cpu_80386 | isa_GP, "test", "", 0, 0, 0, INS_SET_ALL, 0 },
+ { 0, INS_TEST, 0, ADDRMETH_E | OPTYPE_v | OP_R, ADDRMETH_G | OPTYPE_v | OP_R, ARG_NONE, cpu_80386 | isa_GP, "test", "", 0, 0, 0, INS_SET_ALL, 0 },
+ { 0, INS_XCHG, 0, ADDRMETH_E | OPTYPE_b | OP_W | OP_R, ADDRMETH_G | OPTYPE_b | OP_W | OP_R, ARG_NONE, cpu_80386 | isa_GP, "xchg", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_XCHG, 0, ADDRMETH_E | OPTYPE_v | OP_W | OP_R, ADDRMETH_G | OPTYPE_v | OP_W | OP_R, ARG_NONE, cpu_80386 | isa_GP, "xchg", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_MOV, 0, ADDRMETH_E | OPTYPE_b | OP_W, ADDRMETH_G | OPTYPE_b | OP_R, ARG_NONE, cpu_80386 | isa_GP, "mov", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_MOV, 0, ADDRMETH_E | OPTYPE_v | OP_W, ADDRMETH_G | OPTYPE_v | OP_R, ARG_NONE, cpu_80386 | isa_GP, "mov", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_MOV, 0, ADDRMETH_G | OPTYPE_b | OP_W, ADDRMETH_E | OPTYPE_b | OP_R, ARG_NONE, cpu_80386 | isa_GP, "mov", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_MOV, 0, ADDRMETH_G | OPTYPE_v | OP_W, ADDRMETH_E | OPTYPE_v | OP_R, ARG_NONE, cpu_80386 | isa_GP, "mov", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_MOV, 0, ADDRMETH_E | OPTYPE_w | OP_W, ADDRMETH_S | OPTYPE_w | OP_R, ARG_NONE, cpu_80386 | isa_GP, "mov", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_MOV, 0, ADDRMETH_G | OPTYPE_v | OP_W, ADDRMETH_M | OPTYPE_m | OP_R, ARG_NONE, cpu_80386 | isa_GP, "lea", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_MOV, 0, ADDRMETH_S | OPTYPE_w | OP_W, ADDRMETH_E | OPTYPE_w | OP_R, ARG_NONE, cpu_80386 | isa_GP, "mov", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_POP, 0, ADDRMETH_E | OPTYPE_v | OP_W, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "pop", "", 0, 0, 0, 0 , 33 },
+/* 0x90 */
+ { 0, INS_NOP, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "nop", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_XCHG, 0, ADDRMETH_RR | OPTYPE_v | OP_W | OP_R, ADDRMETH_RR | OPTYPE_v | OP_W | OP_R, ARG_NONE, cpu_80386 | isa_GP, "xchg", "", 0, 1, 0, 0 , 0 },
+ { 0, INS_XCHG, 0, ADDRMETH_RR | OPTYPE_v | OP_W | OP_R, ADDRMETH_RR | OPTYPE_v | OP_W | OP_R, ARG_NONE, cpu_80386 | isa_GP, "xchg", "", 0, 2, 0, 0 , 0 },
+ { 0, INS_XCHG, 0, ADDRMETH_RR | OPTYPE_v | OP_W | OP_R, ADDRMETH_RR | OPTYPE_v | OP_W | OP_R, ARG_NONE, cpu_80386 | isa_GP, "xchg", "", 0, 3, 0, 0 , 0 },
+ { 0, INS_XCHG, 0, ADDRMETH_RR | OPTYPE_v | OP_W | OP_R, ADDRMETH_RR | OPTYPE_v | OP_W | OP_R, ARG_NONE, cpu_80386 | isa_GP, "xchg", "", 0, 4, 0, 0 , 0 },
+ { 0, INS_XCHG, 0, ADDRMETH_RR | OPTYPE_v | OP_W | OP_R, ADDRMETH_RR | OPTYPE_v | OP_W | OP_R, ARG_NONE, cpu_80386 | isa_GP, "xchg", "", 0, 5, 0, 0 , 0 },
+ { 0, INS_XCHG, 0, ADDRMETH_RR | OPTYPE_v | OP_W | OP_R, ADDRMETH_RR | OPTYPE_v | OP_W | OP_R, ARG_NONE, cpu_80386 | isa_GP, "xchg", "", 0, 6, 0, 0 , 0 },
+ { 0, INS_XCHG, 0, ADDRMETH_RR | OPTYPE_v | OP_W | OP_R, ADDRMETH_RR | OPTYPE_v | OP_W | OP_R, ARG_NONE, cpu_80386 | isa_GP, "xchg", "", 0, 7, 0, 0 , 0 },
+ { 0, INS_SZCONV, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "cwde", "", 0, 0, 0, 0 , 5 },
+ { 0, INS_SZCONV, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "cdq", "", 0, 0, 0, 0 , 11 },
+ { 0, INS_CALL, 0, ADDRMETH_A | OPTYPE_p | OP_X, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "callf", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_SYSTEM, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "wait", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_PUSHFLAGS, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "pushf", "", 0, 0, 0, 0 , 37 },
+ { 0, INS_POPFLAGS, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "popf", "", 0, 0, 0, 0 , 35 },
+ { 0, INS_MOV, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "sahf", "", 0, 0, 0, INS_SET_SIGN|INS_SET_ZERO|INS_SET_PARITY|INS_SET_CARRY, 43 },
+ { 0, INS_MOV, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "lahf", "", 0, 0, 0, 0 , 24 },
+/* 0xa0 */
+ { 0, INS_MOV, 0, ADDRMETH_RR | OPTYPE_b | OP_W, ADDRMETH_O | OPTYPE_b | OP_R, ARG_NONE, cpu_80386 | isa_GP, "mov", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_MOV, 0, ADDRMETH_RR | OPTYPE_v | OP_W, ADDRMETH_O | OPTYPE_v | OP_R, ARG_NONE, cpu_80386 | isa_GP, "mov", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_MOV, 0, ADDRMETH_O | OPTYPE_b | OP_W, ADDRMETH_RR | OPTYPE_b | OP_R, ARG_NONE, cpu_80386 | isa_GP, "mov", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_MOV, 0, ADDRMETH_O | OPTYPE_v | OP_W, ADDRMETH_RR | OPTYPE_v | OP_R, ARG_NONE, cpu_80386 | isa_GP, "mov", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_STRMOV, 0, ADDRMETH_Y | OPTYPE_b | OP_W, ADDRMETH_X | OPTYPE_b | OP_R, ARG_NONE, cpu_80386 | isa_GP, "movs", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_STRMOV, 0, ADDRMETH_Y | OPTYPE_v | OP_W, ADDRMETH_X | OPTYPE_v | OP_R, ARG_NONE, cpu_80386 | isa_GP, "movs", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_STRCMP, 0, ADDRMETH_Y | OPTYPE_b | OP_R, ADDRMETH_X | OPTYPE_b | OP_R, ARG_NONE, cpu_80386 | isa_GP, "cmps", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_STRCMP, 0, ADDRMETH_X | OPTYPE_v | OP_R, ADDRMETH_Y | OPTYPE_v | OP_R, ARG_NONE, cpu_80386 | isa_GP, "cmps", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_TEST, 0, ADDRMETH_RR | OPTYPE_b | OP_R, ADDRMETH_I | OPTYPE_b | OP_R, ARG_NONE, cpu_80386 | isa_GP, "test", "", 0, 0, 0, INS_SET_ALL, 0 },
+ { 0, INS_TEST, 0, ADDRMETH_RR | OPTYPE_v | OP_R, ADDRMETH_I | OPTYPE_v | OP_R, ARG_NONE, cpu_80386 | isa_GP, "test", "", 0, 0, 0, INS_SET_ALL, 0 },
+ { 0, INS_STRSTOR, 0, ADDRMETH_Y | OPTYPE_b | OP_W, ADDRMETH_RR | OPTYPE_b | OP_R, ARG_NONE, cpu_80386 | isa_GP, "stos", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_STRSTOR, 0, ADDRMETH_Y | OPTYPE_v | OP_W, ADDRMETH_RR | OPTYPE_v |OP_R, ARG_NONE, cpu_80386 | isa_GP, "stos", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_STRLOAD, 0, ADDRMETH_RR | OPTYPE_b | OP_W, ADDRMETH_X| OPTYPE_b | OP_R, ARG_NONE, cpu_80386 | isa_GP, "lods", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_STRLOAD, 0, ADDRMETH_RR | OPTYPE_v | OP_W, ADDRMETH_X| OPTYPE_v | OP_R, ARG_NONE, cpu_80386 | isa_GP, "lods", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_STRCMP, 0, ADDRMETH_RR | OPTYPE_b | OP_R, ADDRMETH_Y | OPTYPE_b | OP_R, ARG_NONE, cpu_80386 | isa_GP, "scas", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_STRCMP, 0, ADDRMETH_RR | OPTYPE_v | OP_R, ADDRMETH_Y | OPTYPE_v | OP_R, ARG_NONE, cpu_80386 | isa_GP, "scas", "", 0, 0, 0, 0 , 0 },
+/* 0xb0 */
+ { 0, INS_MOV, 0, ADDRMETH_RR | OPTYPE_b | OP_W, ADDRMETH_I | OPTYPE_b | OP_R, ARG_NONE, cpu_80386 | isa_GP, "mov", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_MOV, 0, ADDRMETH_RR | OPTYPE_b | OP_W, ADDRMETH_I | OPTYPE_b | OP_R, ARG_NONE, cpu_80386 | isa_GP, "mov", "", 1, 0, 0, 0 , 0 },
+ { 0, INS_MOV, 0, ADDRMETH_RR | OPTYPE_b | OP_W, ADDRMETH_I | OPTYPE_b | OP_R, ARG_NONE, cpu_80386 | isa_GP, "mov", "", 2, 0, 0, 0 , 0 },
+ { 0, INS_MOV, 0, ADDRMETH_RR | OPTYPE_b | OP_W, ADDRMETH_I | OPTYPE_b | OP_R, ARG_NONE, cpu_80386 | isa_GP, "mov", "", 3, 0, 0, 0 , 0 },
+ { 0, INS_MOV, 0, ADDRMETH_RR | OPTYPE_b | OP_W, ADDRMETH_I | OPTYPE_b | OP_R, ARG_NONE, cpu_80386 | isa_GP, "mov", "", 4, 0, 0, 0 , 0 },
+ { 0, INS_MOV, 0, ADDRMETH_RR | OPTYPE_b | OP_W, ADDRMETH_I | OPTYPE_b | OP_R, ARG_NONE, cpu_80386 | isa_GP, "mov", "", 5, 0, 0, 0 , 0 },
+ { 0, INS_MOV, 0, ADDRMETH_RR | OPTYPE_b | OP_W, ADDRMETH_I | OPTYPE_b | OP_R, ARG_NONE, cpu_80386 | isa_GP, "mov", "", 6, 0, 0, 0 , 0 },
+ { 0, INS_MOV, 0, ADDRMETH_RR | OPTYPE_b | OP_W, ADDRMETH_I | OPTYPE_b | OP_R, ARG_NONE, cpu_80386 | isa_GP, "mov", "", 7, 0, 0, 0 , 0 },
+ { 0, INS_MOV, 0, ADDRMETH_RR | OPTYPE_v | OP_W, ADDRMETH_I | OPTYPE_v | OP_R, ARG_NONE, cpu_80386 | isa_GP, "mov", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_MOV, 0, ADDRMETH_RR | OPTYPE_v | OP_W, ADDRMETH_I | OPTYPE_v | OP_R, ARG_NONE, cpu_80386 | isa_GP, "mov", "", 1, 0, 0, 0 , 0 },
+ { 0, INS_MOV, 0, ADDRMETH_RR | OPTYPE_v | OP_W, ADDRMETH_I | OPTYPE_v | OP_R, ARG_NONE, cpu_80386 | isa_GP, "mov", "", 2, 0, 0, 0 , 0 },
+ { 0, INS_MOV, 0, ADDRMETH_RR | OPTYPE_v | OP_W, ADDRMETH_I | OPTYPE_v | OP_R, ARG_NONE, cpu_80386 | isa_GP, "mov", "", 3, 0, 0, 0 , 0 },
+ { 0, INS_MOV, 0, ADDRMETH_RR | OPTYPE_v | OP_W, ADDRMETH_I | OPTYPE_v | OP_R, ARG_NONE, cpu_80386 | isa_GP, "mov", "", 4, 0, 0, 0 , 0 },
+ { 0, INS_MOV, 0, ADDRMETH_RR | OPTYPE_v | OP_W, ADDRMETH_I | OPTYPE_v | OP_R, ARG_NONE, cpu_80386 | isa_GP, "mov", "", 5, 0, 0, 0 , 0 },
+ { 0, INS_MOV, 0, ADDRMETH_RR | OPTYPE_v | OP_W, ADDRMETH_I | OPTYPE_v | OP_R, ARG_NONE, cpu_80386 | isa_GP, "mov", "", 6, 0, 0, 0 , 0 },
+ { 0, INS_MOV, 0, ADDRMETH_RR | OPTYPE_v | OP_W, ADDRMETH_I | OPTYPE_v | OP_R, ARG_NONE, cpu_80386 | isa_GP, "mov", "", 7, 0, 0, 0 , 0 },
+/* 0xc0 */
+ { idx_C0, 0, 0, ADDRMETH_E | OPTYPE_b, ADDRMETH_I | OPTYPE_b, ARG_NONE, cpu_80386 | isa_GP, "", "", 0, 0, 0, 0 , 0 },
+ { idx_C1, 0, 0, ADDRMETH_E | OPTYPE_v, ADDRMETH_I | OPTYPE_b, ARG_NONE, cpu_80386 | isa_GP, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_RET, 0, ADDRMETH_I | OPTYPE_w | OP_R, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "ret", "", 0, 0, 0, 0 , 3 },
+ { 0, INS_RET, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "ret", "", 0, 0, 0, 0 , 3 },
+ { 0, INS_MOV, 0, ADDRMETH_G | OPTYPE_v | OP_W, ADDRMETH_M | OPTYPE_p | OP_R, ARG_NONE, cpu_80386 | isa_GP, "les", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_MOV, 0, ADDRMETH_G | OPTYPE_v | OP_W, ADDRMETH_M | OPTYPE_p | OP_R, ARG_NONE, cpu_80386 | isa_GP, "lds", "", 0, 0, 0, 0 , 0 },
+ { idx_C6, 0, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "", "", 0, 0, 0, 0 , 0 },
+ { idx_C7, 0, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_ENTER, INS_NOTE_NONSWAP, ADDRMETH_I | OPTYPE_w | OP_R, ADDRMETH_I | OPTYPE_b | OP_R, ARG_NONE, cpu_80386 | isa_GP, "enter", "", 0, 0, 0, 0 , 15 },
+ { 0, INS_LEAVE, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "leave", "", 0, 0, 0, 0 , 26 },
+ { 0, INS_RET, 0, ADDRMETH_I | OPTYPE_w | OP_R, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "retf", "lret", 0, 0, 0, 0 , 3 },
+ { 0, INS_RET, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "retf", "lret", 0, 0, 0, 0 , 3 },
+ { 0, INS_DEBUG, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "int3", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_TRAP, 0, ADDRMETH_I | OPTYPE_b | OP_R, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "int", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_OFLOW, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "into", "", 0, 0, 0, INS_TEST_OFLOW, 0 },
+ { 0, INS_TRET, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "iret", "", 0, 0, 0, INS_SET_ALL|INS_SET_DIR, 0 },
+/* 0xd0 */
+ { idx_D0, 0, 0, ADDRMETH_E | OPTYPE_b, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "", "", 0, 1, 0, 0 , 0 },
+ { idx_D1, 0, 0, ADDRMETH_E | OPTYPE_v, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "", "", 0, 1, 0, 0 , 0 },
+ { idx_D2, 0, 0, ADDRMETH_E | OPTYPE_b, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "", "", 0, 1, 0, 0 , 0 },
+ { idx_D3, 0, 0, ADDRMETH_E | OPTYPE_v, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "", "", 0, 1, 0, 0 , 0 },
+ { 0, INS_BCDCONV, 0, ADDRMETH_I | OPTYPE_b | OP_R, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "aam", "", 0, 0, 0, INS_SET_SIGN|INS_SET_ZERO|INS_SET_PARITY, 0 },
+ { 0, INS_BCDCONV, 0, ADDRMETH_I | OPTYPE_b | OP_R, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "aad", "", 0, 0, 0, INS_SET_SIGN|INS_SET_ZERO|INS_SET_PARITY, 2 },
+ { 0, INS_SALC, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "salc", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_XLAT, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "xlat", "", 0, 0, 0, 0 , 53 },
+ { idx_D8, 0, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "", "", 0, 0, 0, 0 , 0 },
+ { idx_D9, 0, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "", "", 0, 0, 0, 0 , 0 },
+ { idx_DA, 0, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "", "", 0, 0, 0, 0 , 0 },
+ { idx_DB, 0, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "", "", 0, 0, 0, 0 , 0 },
+ { idx_DC, 0, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "", "", 0, 0, 0, 0 , 0 },
+ { idx_DD, 0, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "", "", 0, 0, 0, 0 , 0 },
+ { idx_DE, 0, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "", "", 0, 0, 0, 0 , 0 },
+ { idx_DF, 0, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "", "", 0, 0, 0, 0 , 0 },
+/* 0xe0 */
+ { 0, INS_BRANCHCC, 0, ADDRMETH_J | OPTYPE_b | OP_X, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "loopnz", "", 0, 0, 0, INS_TEST_NZERO, 31 },
+ { 0, INS_BRANCHCC, 0, ADDRMETH_J | OPTYPE_b | OP_X, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "loopz", "", 0, 0, 0, INS_TEST_ZERO, 31 },
+ { 0, INS_BRANCHCC, 0, ADDRMETH_J | OPTYPE_b | OP_X, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "loop", "", 0, 0, 0, 0 , 31 },
+ { 0, INS_BRANCHCC, 0, ADDRMETH_J | OPTYPE_b | OP_X, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "jcxz", "", 0, 0, 0, 0 , 31 },
+ { 0, INS_IN, 0, ADDRMETH_RR | OPTYPE_b | OP_W, ADDRMETH_I | OPTYPE_b | OP_R, ARG_NONE, cpu_80386 | isa_GP, "in", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_IN, 0, ADDRMETH_RR | OPTYPE_b | OP_W, ADDRMETH_I | OPTYPE_b | OP_R, ARG_NONE, cpu_80386 | isa_GP, "in", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_OUT, 0, ADDRMETH_I | OPTYPE_b | OP_R, ADDRMETH_RR | OPTYPE_b | OP_R, ARG_NONE, cpu_80386 | isa_GP, "out", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_OUT, 0, ADDRMETH_I | OPTYPE_b | OP_R, ADDRMETH_RR | OPTYPE_b | OP_R, ARG_NONE, cpu_80386 | isa_GP, "out", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_CALL, 0, ADDRMETH_J | OPTYPE_v | OP_X | OP_SIGNED, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "call", "", 0, 0, 0, 0 , 3 },
+ { 0, INS_BRANCH, 0, ADDRMETH_J | OPTYPE_v | OP_X | OP_SIGNED, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "jmp", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_BRANCH, 0, ADDRMETH_A | OPTYPE_p | OP_X, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "jmp", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_BRANCH, 0, ADDRMETH_J | OPTYPE_b | OP_X | OP_SIGNED, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "jmp", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_IN, 0, ADDRMETH_RR | OPTYPE_b| OP_W, ADDRMETH_RR | OPTYPE_w| OP_R, ARG_NONE, cpu_80386 | isa_GP, "in", "", 0, 2, 0, 0 , 0 },
+ { 0, INS_IN, 0, ADDRMETH_RR | OPTYPE_v | OP_W, ADDRMETH_RR | OPTYPE_w| OP_R, ARG_NONE, cpu_80386 | isa_GP, "in", "", 0, 2, 0, 0 , 0 },
+ { 0, INS_OUT, 0, ADDRMETH_RR | OPTYPE_w| OP_R, ADDRMETH_RR | OPTYPE_b| OP_R, ARG_NONE, cpu_80386 | isa_GP, "out", "", 2, 0, 0, 0 , 0 },
+ { 0, INS_OUT, 0, ADDRMETH_RR | OPTYPE_w| OP_R, ADDRMETH_RR | OPTYPE_v| OP_R, ARG_NONE, cpu_80386 | isa_GP, "out", "", 2, 0, 0, 0 , 0 },
+/* 0xf0 */
+ { 0, INS_FLAG_PREFIX | PREFIX_LOCK, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_ICEBP, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "icebp", "", 0, 0, 0, 0 , 0 },
+ { idx_F2, INS_FLAG_PREFIX | PREFIX_REPNZ, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "", "", 0, 0, 0, 0 , 0 },
+ { idx_F3, INS_FLAG_PREFIX | PREFIX_REPZ, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_HALT, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "hlt", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_TOGCF, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "cmc", "", 0, 0, 0, INS_SET_CARRY, 0 },
+ { idx_F6, 0, 0, ADDRMETH_E | OPTYPE_b, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "", "", 0, 0, 0, 0 , 0 },
+ { idx_F7, 0, 0, ADDRMETH_E | OPTYPE_v, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_CLEARCF, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "clc", "", 0, 0, 0, INS_SET_NCARRY, 0 },
+ { 0, INS_SETCF, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "stc", "", 0, 0, 0, INS_SET_CARRY, 0 },
+ { 0, INS_SYSTEM, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "cli", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_SYSTEM, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "sti", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_CLEARDF, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "cld", "", 0, 0, 0, INS_SET_NDIR, 0 },
+ { 0, INS_SETDF, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "std", "", 0, 0, 0, INS_SET_DIR, 0 },
+ { idx_FE, 0, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "", "", 0, 0, 0, 0 , 0 },
+ { idx_FF, 0, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "", "", 0, 0, 0, 0 , 0 }
+};
+
+
+static ia32_insn_t tbl_66[] = { /* SIMD 66 one-byte Opcodes */
+ { idx_660F, 0, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "", "", 0, 0, 0, 0 , 0 }
+};
+
+
+static ia32_insn_t tbl_F2[] = { /* SIMD F2 one-byte Opcodes */
+ { idx_F20F, 0, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "", "", 0, 0, 0, 0 , 0 }
+};
+
+
+static ia32_insn_t tbl_F3[] = { /* SIMD F3 one-byte Opcodes */
+ { idx_F30F, 0, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_SYSTEM, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "pause", "", 0, 0, 0, 0, 0 }
+};
+
+
+static ia32_insn_t tbl_0F[] = { /* Two-byte Opcodes */
+ { idx_0F00, 0, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "", "", 0, 0, 0, 0 , 0 },
+ { idx_0F01, 0, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_SYSTEM, 0, ADDRMETH_G | OPTYPE_v | OP_W, ADDRMETH_E | OPTYPE_w | OP_R, ARG_NONE, cpu_80386 | isa_GP, "lar", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_SYSTEM, 0, ADDRMETH_G | OPTYPE_v | OP_W, ADDRMETH_E | OPTYPE_w | OP_R, ARG_NONE, cpu_80386 | isa_GP, "lsl", "", 0, 0, 0, INS_SET_ZERO, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_SYSTEM, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "clts", "", 0, 0, 0, 0 , 6 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_SYSTEM, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80486 | isa_GP, "invd", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_SYSTEM, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80486 | isa_GP, "wbinvd", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_UNKNOWN, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTPRO | isa_GP, "ud2", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_SYSTEM, 0, ADDRMETH_M | OPTYPE_b | OP_R, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "prefetch", "", 0, 0, 0, 0, 0 },
+ { 0, INS_SYSTEM, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "femms", "", 0, 0, 0, 0, 0 },
+ { idx_0F0F, INS_FLAG_SUFFIX, 0, ADDRMETH_P | OPTYPE_pi | OP_R | OP_W, ADDRMETH_Q | OPTYPE_q |OP_R, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_MOV, 0, ADDRMETH_V | OPTYPE_ps | OP_W, ADDRMETH_W | OPTYPE_ps | OP_R, ARG_NONE, cpu_PENTIUM2 | isa_GP, "movups", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_MOV, 0, ADDRMETH_W | OPTYPE_ps | OP_W, ADDRMETH_V | OPTYPE_ps | OP_R, ARG_NONE, cpu_PENTIUM2 | isa_GP, "movups", "", 0, 0, 0, 0 , 0 },
+ { idx_0F12, 0, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_MOV, INS_NOTE_NOSUFFIX, ADDRMETH_V | OPTYPE_q | OP_W, ADDRMETH_W | OPTYPE_q | OP_R, ARG_NONE, cpu_PENTIUM2 | isa_GP, "movlps", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_OTHER, 0, ADDRMETH_V | OPTYPE_ps | OP_W, ADDRMETH_W | OPTYPE_q | OP_R, ARG_NONE, cpu_PENTIUM2 | isa_GP, "unpcklps", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_OTHER, 0, ADDRMETH_V | OPTYPE_ps | OP_W, ADDRMETH_W | OPTYPE_q | OP_R, ARG_NONE, cpu_PENTIUM2 | isa_GP, "unpckhps", "", 0, 0, 0, 0 , 0 },
+ { idx_0F16, 0, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_OTHER, 0, ADDRMETH_W | OPTYPE_q | OP_W, ADDRMETH_V | OPTYPE_q | OP_R, ARG_NONE, cpu_PENTIUM2 | isa_GP, "movhps", "", 0, 0, 0, 0 , 0 },
+ { idx_0F18, 0, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_MOV, 0, ADDRMETH_R | OPTYPE_d | OP_W, ADDRMETH_C | OPTYPE_d | OP_R, ARG_NONE, cpu_80386 | isa_GP, "mov", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_MOV, 0, ADDRMETH_R | OPTYPE_d | OP_W, ADDRMETH_D | OPTYPE_d | OP_R, ARG_NONE, cpu_80386 | isa_GP, "mov", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_MOV, 0, ADDRMETH_C | OPTYPE_d | OP_W, ADDRMETH_R | OPTYPE_d | OP_R, ARG_NONE, cpu_80386 | isa_GP, "mov", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_MOV, 0, ADDRMETH_D | OPTYPE_d | OP_W, ADDRMETH_R | OPTYPE_d | OP_R, ARG_NONE, cpu_80386 | isa_GP, "mov", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_MOV, 0, ADDRMETH_R | OPTYPE_d | OP_W, ADDRMETH_T | OPTYPE_d | OP_R, ARG_NONE, cpu_80386 | isa_GP, "mov", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_MOV, 0, ADDRMETH_T | OPTYPE_d | OP_W, ADDRMETH_R | OPTYPE_d | OP_R, ARG_NONE, cpu_80386 | isa_GP, "mov", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_MOV, 0, ADDRMETH_V | OPTYPE_ps | OP_W, ADDRMETH_W | OPTYPE_ps | OP_R, ARG_NONE, cpu_PENTIUM2 | isa_GP, "movaps", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_MOV, 0, ADDRMETH_W | OPTYPE_ps | OP_W, ADDRMETH_V | OPTYPE_ps | OP_R, ARG_NONE, cpu_PENTIUM2 | isa_GP, "movaps", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_MOV, 0, ADDRMETH_V | OPTYPE_ps | OP_W, ADDRMETH_Q | OPTYPE_q | OP_R, ARG_NONE, cpu_PENTIUM2 | isa_GP, "cvtpi2ps", "", 0, 0, 0, 0, 0 },
+ { 0, INS_MOV, 0, ADDRMETH_W | OPTYPE_ps | OP_W, ADDRMETH_V | OPTYPE_ps | OP_R, ARG_NONE, cpu_PENTIUM2 | isa_GP, "movntps", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_MOV, 0, ADDRMETH_P | OPTYPE_q | OP_W, ADDRMETH_W | OPTYPE_q | OP_R, ARG_NONE, cpu_PENTIUM2 | isa_GP, "cvttps2pi", "", 0, 0, 0, 0, 0 },
+ { 0, INS_MOV, 0, ADDRMETH_P | OPTYPE_q | OP_W , ADDRMETH_W | OPTYPE_q | OP_R, ARG_NONE, cpu_PENTIUM2 | isa_GP, "cvtps2pi", "", 0, 0, 0, 0, 0 },
+ { 0, INS_OTHER, 0, ADDRMETH_V | OPTYPE_ss | OP_W, ADDRMETH_W | OPTYPE_ss | OP_R, ARG_NONE, cpu_PENTIUM2 | isa_GP, "ucomiss", "", 0, 0, 0, INS_SET_ALL, 0 },
+ { 0, INS_OTHER, 0, ADDRMETH_V | OPTYPE_ps | OP_W, ADDRMETH_W | OPTYPE_ss | OP_W, ARG_NONE, cpu_PENTIUM2 | isa_GP, "comiss", "", 0, 0, 0, INS_SET_ALL, 0 },
+ { 0, INS_SYSTEM, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM | isa_GP, "wrmsr", "", 0, 0, 0, 0 , 52 },
+ { 0, INS_SYSTEM, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM | isa_GP, "rdtsc", "", 0, 0, 0, 0 , 40 },
+ { 0, INS_SYSTEM, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM | isa_GP, "rdmsr", "", 0, 0, 0, 0 , 38 },
+ { 0, INS_SYSTEM, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTPRO | isa_GP, "rdpmc", "", 0, 0, 0, 0 , 39 },
+ { 0, INS_SYSTEM, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM2 | isa_GP, "sysenter", "", 0, 0, 0, 0 , 50 },
+ { 0, INS_SYSTEM, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM2 | isa_GP, "sysexit", "", 0, 0, 0, 0 , 51 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_MOVCC, 0, ADDRMETH_G | OPTYPE_v | OP_W, ADDRMETH_E | OPTYPE_v | OP_R, ARG_NONE, cpu_PENTPRO | isa_GP, "cmovo", "", 0, 0, 0, INS_TEST_OFLOW, 0 },
+ { 0, INS_MOVCC, 0, ADDRMETH_G | OPTYPE_v | OP_W, ADDRMETH_E | OPTYPE_v | OP_R, ARG_NONE, cpu_PENTPRO | isa_GP, "cmovno", "", 0, 0, 0, INS_TEST_NOFLOW, 0 },
+ { 0, INS_MOVCC, 0, ADDRMETH_G | OPTYPE_v | OP_W, ADDRMETH_E | OPTYPE_v | OP_R, ARG_NONE, cpu_PENTPRO | isa_GP, "cmovc", "", 0, 0, 0, INS_TEST_CARRY, 0 },
+ { 0, INS_MOVCC, 0, ADDRMETH_G | OPTYPE_v | OP_W, ADDRMETH_E | OPTYPE_v | OP_R, ARG_NONE, cpu_PENTPRO | isa_GP, "cmovnc", "", 0, 0, 0, INS_TEST_NCARRY, 0 },
+ { 0, INS_MOVCC, 0, ADDRMETH_G | OPTYPE_v | OP_W, ADDRMETH_E | OPTYPE_v | OP_R, ARG_NONE, cpu_PENTPRO | isa_GP, "cmovz", "", 0, 0, 0, INS_TEST_ZERO, 0 },
+ { 0, INS_MOVCC, 0, ADDRMETH_G | OPTYPE_v | OP_W, ADDRMETH_E | OPTYPE_v | OP_R, ARG_NONE, cpu_PENTPRO | isa_GP, "cmovnz", "", 0, 0, 0, INS_TEST_NZERO, 0 },
+ { 0, INS_MOVCC, 0, ADDRMETH_G | OPTYPE_v | OP_W, ADDRMETH_E | OPTYPE_v | OP_R, ARG_NONE, cpu_PENTPRO | isa_GP, "cmovbe", "", 0, 0, 0, INS_TEST_CARRY|INS_TEST_OR|INS_TEST_ZERO, 0 },
+ { 0, INS_MOVCC, 0, ADDRMETH_G | OPTYPE_v | OP_W, ADDRMETH_E | OPTYPE_v | OP_R, ARG_NONE, cpu_PENTPRO | isa_GP, "cmova", "", 0, 0, 0, INS_TEST_NZERO|INS_TEST_NCARRY, 0 },
+ { 0, INS_MOVCC, 0, ADDRMETH_G | OPTYPE_v | OP_W, ADDRMETH_E | OPTYPE_v | OP_R, ARG_NONE, cpu_PENTPRO | isa_GP, "cmovs", "", 0, 0, 0, INS_TEST_SIGN, 0 },
+ { 0, INS_MOVCC, 0, ADDRMETH_G | OPTYPE_v | OP_W, ADDRMETH_E | OPTYPE_v | OP_R, ARG_NONE, cpu_PENTPRO | isa_GP, "cmovns", "", 0, 0, 0, INS_TEST_NSIGN, 0 },
+ { 0, INS_MOVCC, 0, ADDRMETH_G | OPTYPE_v | OP_W, ADDRMETH_E | OPTYPE_v | OP_R, ARG_NONE, cpu_PENTPRO | isa_GP, "cmovp", "", 0, 0, 0, INS_TEST_PARITY, 0 },
+ { 0, INS_MOVCC, 0, ADDRMETH_G | OPTYPE_v | OP_W, ADDRMETH_E | OPTYPE_v | OP_R, ARG_NONE, cpu_PENTPRO | isa_GP, "cmovnp", "", 0, 0, 0, INS_TEST_NPARITY, 0 },
+ { 0, INS_MOVCC, 0, ADDRMETH_G | OPTYPE_v | OP_W, ADDRMETH_E | OPTYPE_v | OP_R, ARG_NONE, cpu_PENTPRO | isa_GP, "cmovl", "", 0, 0, 0, INS_TEST_SFNEOF, 0 },
+ { 0, INS_MOVCC, 0, ADDRMETH_G | OPTYPE_v | OP_W, ADDRMETH_E | OPTYPE_v | OP_R, ARG_NONE, cpu_PENTPRO | isa_GP, "cmovge", "", 0, 0, 0, INS_TEST_SFEQOF, 0 },
+ { 0, INS_MOVCC, 0, ADDRMETH_G | OPTYPE_v | OP_W, ADDRMETH_E | OPTYPE_v | OP_R, ARG_NONE, cpu_PENTPRO | isa_GP, "cmovle", "", 0, 0, 0, INS_TEST_ZERO|INS_TEST_OR|INS_TEST_SFNEOF, 0 },
+ { 0, INS_MOVCC, 0, ADDRMETH_G | OPTYPE_v | OP_W, ADDRMETH_E | OPTYPE_v | OP_R, ARG_NONE, cpu_PENTPRO | isa_GP, "cmovg", "", 0, 0, 0, INS_TEST_NZERO|INS_TEST_SFEQOF, 0 },
+ { 0, INS_MOV, 0, ADDRMETH_G | OPTYPE_d | OP_W, ADDRMETH_W | OPTYPE_ps | OP_R, ARG_NONE, cpu_PENTIUM2 | isa_GP, "movmskps", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_ARITH, 0, ADDRMETH_V | OPTYPE_ps | OP_W, ADDRMETH_W | OPTYPE_ps | OP_R, ARG_NONE, cpu_PENTIUM2 | isa_GP, "sqrtps", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_ARITH, 0, ADDRMETH_V | OPTYPE_ps | OP_W, ADDRMETH_W | OPTYPE_ps | OP_R, ARG_NONE, cpu_PENTIUM2 | isa_GP, "rsqrtps", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_OTHER, 0, ADDRMETH_V | OPTYPE_ps | OP_W, ADDRMETH_W | OPTYPE_ps | OP_R, ARG_NONE, cpu_PENTIUM2 | isa_GP, "rcpps", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_AND, 0, ADDRMETH_V | OPTYPE_ps | OP_W, ADDRMETH_W | OPTYPE_ps | OP_R, ARG_NONE, cpu_PENTIUM2 | isa_GP, "andps", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_AND, 0, ADDRMETH_V | OPTYPE_ps | OP_W, ADDRMETH_W | OPTYPE_ps | OP_R, ARG_NONE, cpu_PENTIUM2 | isa_GP, "andnps", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_OR, 0, ADDRMETH_V | OPTYPE_ps | OP_W, ADDRMETH_W | OPTYPE_ps | OP_R, ARG_NONE, cpu_PENTIUM2 | isa_GP, "orps", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_XOR, 0, ADDRMETH_V | OPTYPE_ps | OP_W, ADDRMETH_W | OPTYPE_ps | OP_R, ARG_NONE, cpu_PENTIUM2 | isa_GP, "xorps", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_ADD, 0, ADDRMETH_V | OPTYPE_ps | OP_W, ADDRMETH_W | OPTYPE_ps | OP_R, ARG_NONE, cpu_PENTIUM2 | isa_GP, "addps", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_MUL, 0, ADDRMETH_V | OPTYPE_ps | OP_R, ADDRMETH_W | OPTYPE_ps | OP_R, ARG_NONE, cpu_PENTIUM2 | isa_GP, "mulps", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_MOV, 0, ADDRMETH_V | OPTYPE_pd, ADDRMETH_W | OPTYPE_q, ARG_NONE, cpu_PENTIUM4 | isa_GP, "cvtps2pd", "", 0, 0, 0, 0, 0 },
+ { 0, INS_MOV, 0, ADDRMETH_V | OPTYPE_ps | OP_W, ADDRMETH_W | OPTYPE_dq | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "cvtdq2ps", "", 0, 0, 0, 0, 0 },
+ { 0, INS_SUB, 0, ADDRMETH_V | OPTYPE_ps | OP_W, ADDRMETH_W | OPTYPE_ps | OP_R, ARG_NONE, cpu_PENTIUM2 | isa_GP, "subps", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_ARITH, 0, ADDRMETH_V | OPTYPE_ps | OP_W, ADDRMETH_W | OPTYPE_ps | OP_R, ARG_NONE, cpu_PENTIUM2 | isa_GP, "minps", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_DIV, 0, ADDRMETH_V | OPTYPE_ps | OP_W, ADDRMETH_W | OPTYPE_ps | OP_R, ARG_NONE, cpu_PENTIUM2 | isa_GP, "divps", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_ARITH, 0, ADDRMETH_V | OPTYPE_ps | OP_W, ADDRMETH_W | OPTYPE_ps | OP_R, ARG_NONE, cpu_PENTIUM2 | isa_GP, "maxps", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_OTHER, 0, ADDRMETH_P | OPTYPE_q | OP_W, ADDRMETH_Q | OPTYPE_d | OP_R, ARG_NONE, cpu_PENTIUM | isa_MMX, "punpcklbw", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_OTHER, 0, ADDRMETH_P | OPTYPE_q | OP_W, ADDRMETH_Q | OPTYPE_d | OP_R, ARG_NONE, cpu_PENTIUM | isa_MMX, "punpcklwd", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_OTHER, 0, ADDRMETH_P | OPTYPE_q | OP_W, ADDRMETH_Q | OPTYPE_d | OP_R, ARG_NONE, cpu_PENTIUM | isa_MMX, "punpckldq", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_OTHER, 0, ADDRMETH_P | OPTYPE_q | OP_W, ADDRMETH_Q | OPTYPE_d | OP_R, ARG_NONE, cpu_PENTIUM | isa_MMX, "packsswb", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_OTHER, 0, ADDRMETH_P | OPTYPE_q | OP_W, ADDRMETH_Q | OPTYPE_d | OP_R, ARG_NONE, cpu_PENTIUM | isa_MMX, "pcmpgtb", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_OTHER, 0, ADDRMETH_P | OPTYPE_q | OP_W, ADDRMETH_Q | OPTYPE_d | OP_R, ARG_NONE, cpu_PENTIUM | isa_MMX, "pcmpgtw", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_OTHER, 0, ADDRMETH_P | OPTYPE_q | OP_W, ADDRMETH_Q | OPTYPE_d | OP_R, ARG_NONE, cpu_PENTIUM | isa_MMX, "pcmpgtd", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_OTHER, 0, ADDRMETH_P | OPTYPE_q | OP_W, ADDRMETH_Q | OPTYPE_d | OP_R, ARG_NONE, cpu_PENTIUM | isa_MMX, "packuswb", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_OTHER, 0, ADDRMETH_P | OPTYPE_q | OP_W, ADDRMETH_Q | OPTYPE_d | OP_R, ARG_NONE, cpu_PENTIUM | isa_MMX, "punpckhbw", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_OTHER, 0, ADDRMETH_P | OPTYPE_q | OP_W, ADDRMETH_Q | OPTYPE_d | OP_R, ARG_NONE, cpu_PENTIUM | isa_MMX, "punpckhwd", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_OTHER, 0, ADDRMETH_P | OPTYPE_q | OP_W, ADDRMETH_Q | OPTYPE_d | OP_R, ARG_NONE, cpu_PENTIUM | isa_MMX, "punpckhdq", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_OTHER, 0, ADDRMETH_P | OPTYPE_q | OP_W, ADDRMETH_Q | OPTYPE_d | OP_R, ARG_NONE, cpu_PENTIUM | isa_MMX, "packssdw", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_MOV, 0, ADDRMETH_P | OPTYPE_d | OP_W, ADDRMETH_E | OPTYPE_d | OP_R, ARG_NONE, cpu_PENTIUM | isa_MMX, "movd", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_MOV, 0, ADDRMETH_P | OPTYPE_q | OP_W, ADDRMETH_Q | OPTYPE_q | OP_R, ARG_NONE, cpu_PENTIUM | isa_MMX, "movq", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_MOV, 0, ADDRMETH_P | OPTYPE_q | OP_W, ADDRMETH_Q | OPTYPE_q | OP_R, ADDRMETH_I | OPTYPE_b | OP_R, cpu_PENTIUM2 | isa_GP, "pshufw", "", 0, 0, 0, 0, 0 },
+ { idx_0F71, 0, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM | isa_MMX, "", "", 0, 0, 0, 0 , 0 },
+ { idx_0F72, 0, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM | isa_MMX, "", "", 0, 0, 0, 0 , 0 },
+ { idx_0F73, 0, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM | isa_MMX, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_OTHER, 0, ADDRMETH_P | OPTYPE_q | OP_W, ADDRMETH_Q | OPTYPE_q | OP_R, ARG_NONE, cpu_PENTIUM | isa_MMX, "pcmpeqb", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_CMP, 0, ADDRMETH_P | OPTYPE_q | OP_W, ADDRMETH_Q | OPTYPE_q | OP_R, ARG_NONE, cpu_PENTIUM | isa_MMX, "pcmpeqw", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_CMP, 0, ADDRMETH_P | OPTYPE_q | OP_W, ADDRMETH_Q | OPTYPE_q | OP_R, ARG_NONE, cpu_PENTIUM | isa_MMX, "pcmpeqd", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_OTHER, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM | isa_MMX, "emms", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_MOV, 0, ADDRMETH_E | OPTYPE_d | OP_W, ADDRMETH_P | OPTYPE_d | OP_R, ARG_NONE, cpu_PENTIUM | isa_MMX, "movd", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_MOV, 0, ADDRMETH_Q | OPTYPE_q | OP_W, ADDRMETH_P | OPTYPE_q | OP_R, ARG_NONE, cpu_PENTIUM | isa_MMX, "movq", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_BRANCHCC, 0, ADDRMETH_J | OPTYPE_v | OP_X | OP_SIGNED, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "jo", "", 0, 0, 0, INS_TEST_OFLOW, 0 },
+ { 0, INS_BRANCHCC, 0, ADDRMETH_J | OPTYPE_v | OP_X | OP_SIGNED, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "jno", "", 0, 0, 0, INS_TEST_NOFLOW, 0 },
+ { 0, INS_BRANCHCC, 0, ADDRMETH_J | OPTYPE_v | OP_X | OP_SIGNED, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "jc", "", 0, 0, 0, INS_TEST_CARRY, 0 },
+ { 0, INS_BRANCHCC, 0, ADDRMETH_J | OPTYPE_v | OP_X | OP_SIGNED, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "jnc", "", 0, 0, 0, INS_TEST_NCARRY, 0 },
+ { 0, INS_BRANCHCC, 0, ADDRMETH_J | OPTYPE_v | OP_X | OP_SIGNED, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "jz", "", 0, 0, 0, INS_TEST_ZERO, 0 },
+ { 0, INS_BRANCHCC, 0, ADDRMETH_J | OPTYPE_v | OP_X | OP_SIGNED, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "jnz", "", 0, 0, 0, INS_TEST_NZERO, 0 },
+ { 0, INS_BRANCHCC, 0, ADDRMETH_J | OPTYPE_v | OP_X | OP_SIGNED, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "jbe", "", 0, 0, 0, INS_TEST_CARRY|INS_TEST_OR|INS_TEST_ZERO, 0 },
+ { 0, INS_BRANCHCC, 0, ADDRMETH_J | OPTYPE_v | OP_X | OP_SIGNED, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "ja", "", 0, 0, 0, INS_TEST_NCARRY|INS_TEST_NZERO, 0 },
+ { 0, INS_BRANCHCC, 0, ADDRMETH_J | OPTYPE_v | OP_X | OP_SIGNED, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "js", "", 0, 0, 0, INS_TEST_SIGN, 0 },
+ { 0, INS_BRANCHCC, 0, ADDRMETH_J | OPTYPE_v | OP_X | OP_SIGNED, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "jns", "", 0, 0, 0, INS_TEST_NSIGN, 0 },
+ { 0, INS_BRANCHCC, 0, ADDRMETH_J | OPTYPE_v | OP_X | OP_SIGNED, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "jpe", "", 0, 0, 0, INS_TEST_PARITY, 0 },
+ { 0, INS_BRANCHCC, 0, ADDRMETH_J | OPTYPE_v | OP_X | OP_SIGNED, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "jpo", "", 0, 0, 0, INS_TEST_NPARITY, 0 },
+ { 0, INS_BRANCHCC, 0, ADDRMETH_J | OPTYPE_v | OP_X | OP_SIGNED, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "jl", "", 0, 0, 0, INS_TEST_SFNEOF, 0 },
+ { 0, INS_BRANCHCC, 0, ADDRMETH_J | OPTYPE_v | OP_X | OP_SIGNED, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "jge", "", 0, 0, 0, INS_TEST_SFEQOF, 0 },
+ { 0, INS_BRANCHCC, 0, ADDRMETH_J | OPTYPE_v | OP_X | OP_SIGNED, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "jle", "", 0, 0, 0, INS_TEST_ZERO|INS_TEST_OR|INS_TEST_SFNEOF, 0 },
+ { 0, INS_BRANCHCC, 0, ADDRMETH_J | OPTYPE_v | OP_X | OP_SIGNED, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "jg", "", 0, 0, 0, INS_TEST_NZERO|INS_TEST_SFEQOF, 0 },
+ { 0, INS_MOVCC, 0, ADDRMETH_E | OPTYPE_b | OP_W, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "seto", "", 0, 0, 0, INS_TEST_OFLOW, 0 },
+ { 0, INS_MOVCC, 0, ADDRMETH_E | OPTYPE_b | OP_W, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "setno", "", 0, 0, 0, INS_TEST_OFLOW, 0 },
+ { 0, INS_MOVCC, 0, ADDRMETH_E | OPTYPE_b | OP_W, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "setc", "", 0, 0, 0, INS_TEST_CARRY, 0 },
+ { 0, INS_MOVCC, 0, ADDRMETH_E | OPTYPE_b | OP_W, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "setnc", "", 0, 0, 0, INS_TEST_NCARRY, 0 },
+ { 0, INS_MOVCC, 0, ADDRMETH_E | OPTYPE_b | OP_W, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "setz", "", 0, 0, 0, INS_TEST_ZERO, 0 },
+ { 0, INS_MOVCC, 0, ADDRMETH_E | OPTYPE_b | OP_W, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "setnz", "", 0, 0, 0, INS_TEST_NZERO, 0 },
+ { 0, INS_MOVCC, 0, ADDRMETH_E | OPTYPE_b | OP_W, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "setbe", "", 0, 0, 0, INS_TEST_CARRY|INS_TEST_OR|INS_TEST_ZERO, 0 },
+ { 0, INS_MOVCC, 0, ADDRMETH_E | OPTYPE_b | OP_W, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "seta", "", 0, 0, 0, INS_TEST_NCARRY|INS_TEST_NZERO, 0 },
+ { 0, INS_MOVCC, 0, ADDRMETH_E | OPTYPE_b | OP_W, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "sets", "", 0, 0, 0, INS_TEST_SIGN, 0 },
+ { 0, INS_MOVCC, 0, ADDRMETH_E | OPTYPE_b | OP_W, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "setns", "", 0, 0, 0, INS_TEST_NSIGN, 0 },
+ { 0, INS_MOVCC, 0, ADDRMETH_E | OPTYPE_b | OP_W, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "setpe", "", 0, 0, 0, INS_TEST_PARITY, 0 },
+ { 0, INS_MOVCC, 0, ADDRMETH_E | OPTYPE_b | OP_W, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "setpo", "", 0, 0, 0, INS_TEST_NPARITY, 0 },
+ { 0, INS_MOVCC, 0, ADDRMETH_E | OPTYPE_b | OP_W, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "setl", "", 0, 0, 0, INS_TEST_SFNEOF, 0 },
+ { 0, INS_MOVCC, 0, ADDRMETH_E | OPTYPE_b | OP_W, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "setge", "", 0, 0, 0, INS_TEST_SFEQOF, 0 },
+ { 0, INS_MOVCC, 0, ADDRMETH_E | OPTYPE_b | OP_W, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "setle", "", 0, 0, 0, INS_TEST_ZERO|INS_TEST_OR|INS_TEST_SFNEOF, 0 },
+ { 0, INS_MOVCC, 0, ADDRMETH_E | OPTYPE_b | OP_W, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "setg", "", 0, 0, 0, INS_TEST_NZERO|INS_TEST_SFEQOF, 0 },
+ { 0, INS_PUSH, 0, ADDRMETH_RS | OPTYPE_w | OP_R, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "push", "", 4, 0, 0, 0 , 33 },
+ { 0, INS_POP, 0, ADDRMETH_RS | OPTYPE_w | OP_W, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "pop", "", 4, 0, 0, 0 , 33 },
+ { 0, INS_CPUID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM | isa_GP, "cpuid", "", 0, 0, 0, 0 , 10 },
+ { 0, INS_BITTEST, 0, ADDRMETH_E | OPTYPE_v | OP_R, ADDRMETH_G | OPTYPE_v | OP_R, ARG_NONE, cpu_80386 | isa_GP, "bt", "", 0, 0, 0, INS_SET_CARRY, 0 },
+ { 0, INS_SHL, 0, ADDRMETH_E | OPTYPE_v | OP_W | OP_R, ADDRMETH_G | OPTYPE_v | OP_R, ADDRMETH_I | OPTYPE_b | OP_R, cpu_80386 | isa_GP, "shld", "", 0, 0, 0, INS_SET_SIGN|INS_SET_ZERO|INS_SET_PARITY|INS_SET_CARRY, 0 },
+ //{ 0, INS_SHL, 0, ADDRMETH_E | OPTYPE_v | OP_W | OP_R, ADDRMETH_G | OPTYPE_v | OP_R, ADDRMETH_I | OP_R | OPTYPE_b | ADDRMETH_RR, cpu_80386 | isa_GP, "shld", "", 0, 0, 1, INS_SET_SIGN|INS_SET_ZERO|INS_SET_PARITY|INS_SET_CARRY, 0 },
+ { 0, INS_SHL, 0, ADDRMETH_E | OPTYPE_v | OP_W | OP_R, ADDRMETH_G | OPTYPE_v | OP_R, ADDRMETH_RR | OP_R | OPTYPE_b, cpu_80386 | isa_GP, "shld", "", 0, 0, 1, INS_SET_SIGN|INS_SET_ZERO|INS_SET_PARITY|INS_SET_CARRY, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_PUSH, 0, ADDRMETH_RS | OPTYPE_w | OP_R, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "push", "", 5, 0, 0, 0 , 33 },
+ { 0, INS_POP, 0, ADDRMETH_RS | OPTYPE_w | OP_W, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "pop", "", 5, 0, 0, 0 , 33 },
+ { 0, INS_SYSTEM, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "rsm", "", 0, 0, 0, INS_SET_ALL|INS_SET_DIR, 42 },
+ { 0, INS_BITTEST, 0, ADDRMETH_E | OPTYPE_v | OP_R, ADDRMETH_G | OPTYPE_v | OP_R, ARG_NONE, cpu_80386 | isa_GP, "bts", "", 0, 0, 0, INS_SET_CARRY, 0 },
+ { 0, INS_SHR, 0, ADDRMETH_E | OPTYPE_v | OP_W | OP_R, ADDRMETH_G | OPTYPE_v | OP_R, ADDRMETH_I | OPTYPE_b | OP_R, cpu_80386 | isa_GP, "shrd", "", 0, 0, 0, INS_SET_SIGN|INS_SET_ZERO|INS_SET_PARITY|INS_SET_CARRY, 0 },
+ { 0, INS_SHR, 0, ADDRMETH_E | OPTYPE_v | OP_W | OP_R, ADDRMETH_G | OPTYPE_v | OP_R, ADDRMETH_RR | OP_R | OPTYPE_b , cpu_80386 | isa_GP, "shrd", "", 0, 0, 1, INS_SET_SIGN|INS_SET_ZERO|INS_SET_PARITY|INS_SET_CARRY, 0 },
+ { idx_0FAE, 0, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM2 | isa_GP, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_MUL, 0, ADDRMETH_G | OPTYPE_v | OP_SIGNED | OP_R | OP_W, ADDRMETH_E | OPTYPE_v | OP_SIGNED | OP_R, ARG_NONE, cpu_80386 | isa_GP, "imul", "", 0, 0, 0, INS_SET_OFLOW|INS_SET_CARRY, },
+ { 0, INS_XCHGCC, 0, ADDRMETH_E | OPTYPE_b | OP_W | OP_R, ADDRMETH_G | OPTYPE_b | OP_W, ARG_NONE, cpu_80486 | isa_GP, "cmpxchg", "", 0, 0, 0, INS_SET_ALL, 8 },
+ { 0, INS_XCHGCC, 0, ADDRMETH_E | OPTYPE_v | OP_W | OP_R, ADDRMETH_G | OPTYPE_v | OP_W, ARG_NONE, cpu_80486 | isa_GP, "cmpxchg", "", 0, 0, 0, INS_SET_ALL, 7 },
+ { 0, INS_MOV, 0, ADDRMETH_G | OPTYPE_v | OP_W, ADDRMETH_M | OPTYPE_p | OP_W, ARG_NONE, cpu_80386 | isa_GP, "lss", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_BITTEST, 0, ADDRMETH_E | OPTYPE_v | OP_R, ADDRMETH_G | OPTYPE_v | OP_R, ARG_NONE, cpu_80386 | isa_GP, "btr", "", 0, 0, 0, INS_SET_CARRY, 0 },
+ { 0, INS_MOV, 0, ADDRMETH_G | OPTYPE_v | OP_W, ADDRMETH_M | OPTYPE_p | OP_W, ARG_NONE, cpu_80386 | isa_GP, "lfs", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_MOV, 0, ADDRMETH_G | OPTYPE_v | OP_W, ADDRMETH_M | OPTYPE_p | OP_W, ARG_NONE, cpu_80386 | isa_GP, "lgs", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_MOV, 0, ADDRMETH_G | OPTYPE_v | OP_W, ADDRMETH_E | OPTYPE_b | OP_R, ARG_NONE, cpu_80386 | isa_GP, "movzx", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_MOV, 0, ADDRMETH_G | OPTYPE_v | OP_W, ADDRMETH_E | OPTYPE_w | OP_R, ARG_NONE, cpu_80386 | isa_GP, "movzx", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_UNKNOWN, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "ud1", "", 0, 0, 0, 0 , 0 },
+ { idx_0FBA, 0, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_BITTEST, 0, ADDRMETH_E | OPTYPE_v | OP_R, ADDRMETH_G | OPTYPE_v | OP_R, ARG_NONE, cpu_80386 | isa_GP, "btc", "", 0, 0, 0, INS_SET_CARRY, 0 },
+ { 0, INS_BITTEST, 0, ADDRMETH_G | OPTYPE_v | OP_R | OP_W, ADDRMETH_E | OPTYPE_v | OP_R, ARG_NONE, cpu_80386 | isa_GP, "bsf", "", 0, 0, 0, INS_SET_ZERO, 0 },
+ { 0, INS_BITTEST, 0, ADDRMETH_G | OPTYPE_v | OP_R | OP_W, ADDRMETH_E | OPTYPE_v | OP_R, ARG_NONE, cpu_80386 | isa_GP, "bsr", "", 0, 0, 0, INS_SET_ZERO, 0 },
+ { 0, INS_MOV, 0, ADDRMETH_G | OPTYPE_v | OP_W, ADDRMETH_E | OPTYPE_b | OP_R, ARG_NONE, cpu_80386 | isa_GP, "movsx", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_MOV, 0, ADDRMETH_G | OPTYPE_v | OP_W, ADDRMETH_E | OPTYPE_w | OP_R, ARG_NONE, cpu_80386 | isa_GP, "movsx", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_ADD, 0, ADDRMETH_E | OPTYPE_b | OP_W | OP_R, ADDRMETH_G | OPTYPE_b | OP_W, ARG_NONE, cpu_80486 | isa_GP, "xadd", "", 0, 0, 0, INS_SET_ALL, 0 },
+ { 0, INS_ADD, 0, ADDRMETH_E | OPTYPE_v | OP_W | OP_R, ADDRMETH_G | OPTYPE_v | OP_W, ARG_NONE, cpu_80486 | isa_GP, "xadd", "", 0, 0, 0, INS_SET_ALL, 0 },
+ { 0, INS_CMP, 0, ADDRMETH_V | OPTYPE_ps | OP_R, ADDRMETH_W | OPTYPE_ps | OP_R, ADDRMETH_I | OPTYPE_b | OP_R, cpu_PENTIUM4 | isa_GP, "cmpps", "", 0, 0, 0, 0, 0 },
+ { 0, INS_MOV, 0, ADDRMETH_M | OPTYPE_d | OP_W, ADDRMETH_G | OPTYPE_d | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "movnti", "", 0, 0, 0, 0, 0 },
+ { 0, INS_OTHER, 0, ADDRMETH_P | OPTYPE_q | OP_W, ADDRMETH_E | OPTYPE_d | OP_R, ADDRMETH_I | OPTYPE_b | OP_R, cpu_PENTIUM2 | isa_GP, "pinsrw", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_OTHER, 0, ADDRMETH_G | OPTYPE_d | OP_W, ADDRMETH_Q | OPTYPE_q | OP_R, ADDRMETH_I | OPTYPE_b | OP_R, cpu_PENTIUM2 | isa_GP, "pextrw", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_OTHER, 0, ADDRMETH_V | OPTYPE_ps | OP_W, ADDRMETH_W | OPTYPE_ps | OP_R, ADDRMETH_I | OPTYPE_b | OP_R, cpu_PENTIUM2 | isa_GP, "shufps", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_XCHGCC, 0, ADDRMETH_M | OPTYPE_q | OP_R | OP_W, ARG_NONE, ARG_NONE, cpu_PENTIUM | isa_GP, "cmpxchg8b", "", 0, 0, 0, 0, 9 },
+ { 0, INS_XCHG, 0, ADDRMETH_RR | OPTYPE_d | OP_W | OP_R, ARG_NONE, ARG_NONE, cpu_80486 | isa_GP, "bswap", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_XCHG, 0, ADDRMETH_RR | OPTYPE_d | OP_W | OP_R, ARG_NONE, ARG_NONE, cpu_80486 | isa_GP, "bswap", "", 1, 0, 0, 0 , 0 },
+ { 0, INS_XCHG, 0, ADDRMETH_RR | OPTYPE_d | OP_W | OP_R, ARG_NONE, ARG_NONE, cpu_80486 | isa_GP, "bswap", "", 2, 0, 0, 0 , 0 },
+ { 0, INS_XCHG, 0, ADDRMETH_RR | OPTYPE_d | OP_W | OP_R, ARG_NONE, ARG_NONE, cpu_80486 | isa_GP, "bswap", "", 3, 0, 0, 0 , 0 },
+ { 0, INS_XCHG, 0, ADDRMETH_RR | OPTYPE_d | OP_W | OP_R, ARG_NONE, ARG_NONE, cpu_80486 | isa_GP, "bswap", "", 4, 0, 0, 0 , 0 },
+ { 0, INS_XCHG, 0, ADDRMETH_RR | OPTYPE_d | OP_W | OP_R, ARG_NONE, ARG_NONE, cpu_80486 | isa_GP, "bswap", "", 5, 0, 0, 0 , 0 },
+ { 0, INS_XCHG, 0, ADDRMETH_RR | OPTYPE_d | OP_W | OP_R, ARG_NONE, ARG_NONE, cpu_80486 | isa_GP, "bswap", "", 6, 0, 0, 0 , 0 },
+ { 0, INS_XCHG, 0, ADDRMETH_RR | OPTYPE_d | OP_W | OP_R, ARG_NONE, ARG_NONE, cpu_80486 | isa_GP, "bswap", "", 7, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_OTHER, 0, ADDRMETH_P | OPTYPE_q | OP_W, ADDRMETH_Q | OPTYPE_q | OP_R, ARG_NONE, cpu_PENTIUM | isa_MMX, "psrlw", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_OTHER, 0, ADDRMETH_P | OPTYPE_q | OP_W, ADDRMETH_Q | OPTYPE_q | OP_R, ARG_NONE, cpu_PENTIUM | isa_MMX, "psrld", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_OTHER, 0, ADDRMETH_P | OPTYPE_q | OP_W, ADDRMETH_Q | OPTYPE_q | OP_R, ARG_NONE, cpu_PENTIUM | isa_MMX, "psrlq", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_ADD, 0, ADDRMETH_P | OPTYPE_q | OP_R | OP_W, ADDRMETH_Q | OPTYPE_q | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "paddq", "", 0, 0, 0, 0, 0 },
+ { 0, INS_OTHER, 0, ADDRMETH_P | OPTYPE_q | OP_W, ADDRMETH_Q | OPTYPE_q | OP_R, ARG_NONE, cpu_PENTIUM | isa_MMX, "pmullw", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_OTHER, 0, ADDRMETH_G | OPTYPE_d | OP_W, ADDRMETH_Q | OPTYPE_q | OP_R, ARG_NONE, cpu_PENTIUM2 | isa_GP, "pmovmskb", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_OTHER, 0, ADDRMETH_P | OPTYPE_q | OP_W, ADDRMETH_Q | OPTYPE_q | OP_R, ARG_NONE, cpu_PENTIUM | isa_MMX, "psubusb", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_OTHER, 0, ADDRMETH_P | OPTYPE_q | OP_W, ADDRMETH_Q | OPTYPE_q | OP_R, ARG_NONE, cpu_PENTIUM | isa_MMX, "psubusw", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_OTHER, 0, ADDRMETH_P | OPTYPE_q | OP_W, ADDRMETH_Q | OPTYPE_q | OP_R, ARG_NONE, cpu_PENTIUM2 | isa_GP, "pminub", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_AND, 0, ADDRMETH_P | OPTYPE_q | OP_W, ADDRMETH_Q | OPTYPE_q | OP_R, ARG_NONE, cpu_PENTIUM | isa_MMX, "pand", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_ADD, 0, ADDRMETH_P | OPTYPE_q | OP_W, ADDRMETH_Q | OPTYPE_q | OP_R, ARG_NONE, cpu_PENTIUM | isa_MMX, "paddusb", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_ADD, 0, ADDRMETH_P | OPTYPE_q | OP_W, ADDRMETH_Q | OPTYPE_q | OP_R, ARG_NONE, cpu_PENTIUM | isa_MMX, "paddusw", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_ARITH, 0, ADDRMETH_P | OPTYPE_q | OP_W, ADDRMETH_Q | OPTYPE_q | OP_R, ARG_NONE, cpu_PENTIUM2 | isa_GP, "pmaxub", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_AND, 0, ADDRMETH_P | OPTYPE_q | OP_W, ADDRMETH_Q | OPTYPE_q | OP_R, ARG_NONE, cpu_PENTIUM | isa_MMX, "pandn", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_OTHER, 0, ADDRMETH_P | OPTYPE_q | OP_W, ADDRMETH_Q | OPTYPE_q | OP_R, ARG_NONE, cpu_PENTIUM2 | isa_GP, "pavgb", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_OTHER, 0, ADDRMETH_P | OPTYPE_q | OP_W, ADDRMETH_Q | OPTYPE_q | OP_R, ARG_NONE, cpu_PENTIUM | isa_MMX, "psraw", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_OTHER, 0, ADDRMETH_P | OPTYPE_q | OP_W, ADDRMETH_Q | OPTYPE_q | OP_R, ARG_NONE, cpu_PENTIUM | isa_MMX, "psrad", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_OTHER, 0, ADDRMETH_P | OPTYPE_q | OP_W, ADDRMETH_Q | OPTYPE_q | OP_R, ARG_NONE, cpu_PENTIUM2 | isa_GP, "pavgw", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_MUL, 0, ADDRMETH_P | OPTYPE_q | OP_W, ADDRMETH_Q | OPTYPE_q | OP_R, ARG_NONE, cpu_PENTIUM2 | isa_GP, "pmulhuw", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_MUL, 0, ADDRMETH_P | OPTYPE_q | OP_W, ADDRMETH_Q | OPTYPE_q | OP_R, ARG_NONE, cpu_PENTIUM | isa_MMX, "pmulhw", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_MOV, INS_NOTE_NOSUFFIX, ADDRMETH_W | OPTYPE_q | OP_W, ADDRMETH_V | OPTYPE_q | OP_R, ARG_NONE, cpu_PENTIUM2 | isa_GP, "movntq", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_SUB, 0, ADDRMETH_P | OPTYPE_q | OP_W, ADDRMETH_Q | OPTYPE_q | OP_R, ARG_NONE, cpu_PENTIUM | isa_MMX, "psubsb", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_SUB, 0, ADDRMETH_P | OPTYPE_q | OP_W, ADDRMETH_Q | OPTYPE_q | OP_R, ARG_NONE, cpu_PENTIUM | isa_MMX, "psubsw", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_ARITH, 0, ADDRMETH_P | OPTYPE_q | OP_W, ADDRMETH_Q | OPTYPE_q | OP_R, ARG_NONE, cpu_PENTIUM2 | isa_GP, "pminsw", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_OR, 0, ADDRMETH_P | OPTYPE_q | OP_W, ADDRMETH_Q | OPTYPE_q | OP_R, ARG_NONE, cpu_PENTIUM | isa_MMX, "por", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_ADD, 0, ADDRMETH_P | OPTYPE_q | OP_W, ADDRMETH_Q | OPTYPE_q | OP_R, ARG_NONE, cpu_PENTIUM | isa_MMX, "paddsb", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_ADD, 0, ADDRMETH_P | OPTYPE_q | OP_W, ADDRMETH_Q | OPTYPE_q | OP_R, ARG_NONE, cpu_PENTIUM | isa_MMX, "paddsw", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_ARITH, 0, ADDRMETH_P | OPTYPE_q | OP_W, ADDRMETH_Q | OPTYPE_q | OP_R, ARG_NONE, cpu_PENTIUM2 | isa_GP, "pmaxsw", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_XOR, 0, ADDRMETH_P | OPTYPE_q | OP_W, ADDRMETH_Q | OPTYPE_q | OP_R, ARG_NONE, cpu_PENTIUM | isa_MMX, "pxor", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_OTHER, 0, ADDRMETH_P | OPTYPE_q | OP_W, ADDRMETH_Q | OPTYPE_q | OP_R, ARG_NONE, cpu_PENTIUM | isa_MMX, "psllw", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_OTHER, 0, ADDRMETH_P | OPTYPE_q | OP_W, ADDRMETH_Q | OPTYPE_q | OP_R, ARG_NONE, cpu_PENTIUM | isa_MMX, "pslld", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_OTHER, 0, ADDRMETH_P | OPTYPE_q | OP_W, ADDRMETH_Q | OPTYPE_q | OP_R, ARG_NONE, cpu_PENTIUM | isa_MMX, "psllq", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_MUL, 0, ADDRMETH_P | OPTYPE_q | OP_R | OP_W, ADDRMETH_Q | OPTYPE_q | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "pmuludq", "", 0, 0, 0, 0, 0 },
+ { 0, INS_ADD, 0, ADDRMETH_P | OPTYPE_q | OP_W, ADDRMETH_Q | OPTYPE_q | OP_R, ARG_NONE, cpu_PENTIUM | isa_MMX, "pmaddwd", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_OTHER, 0, ADDRMETH_P | OPTYPE_q | OP_W, ADDRMETH_Q | OPTYPE_q | OP_R, ARG_NONE, cpu_PENTIUM2 | isa_GP, "psadbw", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_MOV, 0, ADDRMETH_P | OPTYPE_pi | OP_W, ADDRMETH_Q | OPTYPE_pi | OP_R, ARG_NONE, cpu_PENTIUM2 | isa_GP, "maskmovq", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_SUB, 0, ADDRMETH_P | OPTYPE_q | OP_W, ADDRMETH_Q | OPTYPE_q | OP_R, ARG_NONE, cpu_PENTIUM | isa_MMX, "psubb", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_SUB, 0, ADDRMETH_P | OPTYPE_q | OP_W, ADDRMETH_Q | OPTYPE_q | OP_R, ARG_NONE, cpu_PENTIUM | isa_MMX, "psubw", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_SUB, 0, ADDRMETH_P | OPTYPE_q | OP_W, ADDRMETH_Q | OPTYPE_q | OP_R, ARG_NONE, cpu_PENTIUM | isa_MMX, "psubd", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_SUB, 0, ADDRMETH_P | OPTYPE_q | OP_R | OP_W, ADDRMETH_Q | OPTYPE_q | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "psubq", "", 0, 0, 0, 0, 0 },
+ { 0, INS_ADD, 0, ADDRMETH_P | OPTYPE_q | OP_W, ADDRMETH_Q | OPTYPE_q | OP_R, ARG_NONE, cpu_PENTIUM | isa_MMX, "paddb", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_ADD, 0, ADDRMETH_P | OPTYPE_q | OP_W, ADDRMETH_Q | OPTYPE_q | OP_R, ARG_NONE, cpu_PENTIUM | isa_MMX, "paddw", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_ADD, 0, ADDRMETH_P | OPTYPE_q | OP_W, ADDRMETH_Q | OPTYPE_q | OP_R, ARG_NONE, cpu_PENTIUM | isa_MMX, "paddd", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 }
+};
+
+
+static ia32_insn_t tbl_660F[] = { /* SIMD 66 Two-byte Opcodes */
+ { 0, INS_MOV, 0, ADDRMETH_V | OPTYPE_pd | OP_R, ADDRMETH_W | OPTYPE_pd | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "movupd", "", 0, 0, 0, 0, 0 },
+ { 0, INS_MOV, 0, ADDRMETH_W | OPTYPE_pd | OP_R, ADDRMETH_V | OPTYPE_pd | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "movupd", "", 0, 0, 0, 0, 0 },
+ { 0, INS_MOV, INS_NOTE_NOSUFFIX, ADDRMETH_V | OPTYPE_q | OP_R, ADDRMETH_M | OPTYPE_q | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "movlpd", "", 0, 0, 0, 0, 0 },
+ { 0, INS_MOV, INS_NOTE_NOSUFFIX, ADDRMETH_M | OPTYPE_q | OP_R, ADDRMETH_V | OPTYPE_q | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "movlpd", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_pd | OP_R, ADDRMETH_W | OPTYPE_pd | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "unpcklpd", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_pd | OP_R, ADDRMETH_W | OPTYPE_pd | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "unpckhpd", "", 0, 0, 0, 0, 0 },
+ { 0, INS_MOV, INS_NOTE_NOSUFFIX, ADDRMETH_V | OPTYPE_q | OP_R, ADDRMETH_M | OPTYPE_q | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "movhpd", "", 0, 0, 0, 0, 0 },
+ { 0, INS_MOV, INS_NOTE_NOSUFFIX, ADDRMETH_M | OPTYPE_q | OP_R, ADDRMETH_V | OPTYPE_pd | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "movhpd", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_MOV, 0, ADDRMETH_V | OPTYPE_pd | OP_R, ADDRMETH_W | OPTYPE_pd | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "movapd", "", 0, 0, 0, 0, 0 },
+ { 0, INS_MOV, 0, ADDRMETH_W | OPTYPE_pd | OP_R, ADDRMETH_V | OPTYPE_pd | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "movapd", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_pd | OP_R, ADDRMETH_Q | OPTYPE_q | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "cvtpi2pd", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_M | OPTYPE_pd | OP_R, ADDRMETH_V | OPTYPE_pd | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "movntpd", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_P | OPTYPE_q | OP_R, ADDRMETH_W | OPTYPE_pd | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "cvttpd2pi", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_P | OPTYPE_q | OP_R, ADDRMETH_W | OPTYPE_pd | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "cvtpd2pi", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_sd | OP_R, ADDRMETH_W | OPTYPE_sd | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "ucomisd", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_sd | OP_R, ADDRMETH_W | OPTYPE_sd | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "comisd", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_G | OPTYPE_d | OP_R, ADDRMETH_W | OPTYPE_pd | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "movmskpd", "", 0, 0, 0, 0, 0 },
+ { 0, INS_FSQRT, 0, ADDRMETH_V | OPTYPE_pd | OP_R, ADDRMETH_W | OPTYPE_pd | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "sqrtpd", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_AND, 0, ADDRMETH_V | OPTYPE_pd | OP_R, ADDRMETH_W | OPTYPE_pd | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "andpd", "", 0, 0, 0, 0, 0 },
+ { 0, INS_AND, 0, ADDRMETH_V | OPTYPE_pd | OP_R, ADDRMETH_W | OPTYPE_pd | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "andnpd", "", 0, 0, 0, 0, 0 },
+ { 0, INS_OR, 0, ADDRMETH_V | OPTYPE_pd | OP_R, ADDRMETH_W | OPTYPE_pd | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "orpd", "", 0, 0, 0, 0, 0 },
+ { 0, INS_XOR, 0, ADDRMETH_V | OPTYPE_pd | OP_R, ADDRMETH_W | OPTYPE_pd | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "xorpd", "", 0, 0, 0, 0, 0 },
+ { 0, INS_ADD, 0, ADDRMETH_V | OPTYPE_pd | OP_R, ADDRMETH_W | OPTYPE_pd | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "addpd", "", 0, 0, 0, 0, 0 },
+ { 0, INS_MUL, 0, ADDRMETH_V | OPTYPE_pd | OP_R, ADDRMETH_W | OPTYPE_pd | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "mulpd", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_ps | OP_R, ADDRMETH_W | OPTYPE_pd | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "cvtpd2ps", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_dq | OP_R, ADDRMETH_W | OPTYPE_ps | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "cvtps2dq", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_pd | OP_R, ADDRMETH_W | OPTYPE_pd | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "subpd", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_pd | OP_R, ADDRMETH_W | OPTYPE_pd | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "minpd", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_pd | OP_R, ADDRMETH_W | OPTYPE_pd | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "divpd", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_pd | OP_R, ADDRMETH_W | OPTYPE_pd | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "maxpd", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_dq | OP_R, ADDRMETH_W | OPTYPE_dq | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "punpcklbw", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_dq | OP_R, ADDRMETH_W | OPTYPE_dq | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "punpcklwd", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_dq | OP_R, ADDRMETH_W | OPTYPE_dq | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "punpckldq", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_dq | OP_R, ADDRMETH_W | OPTYPE_dq | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "packsswb", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_dq | OP_R, ADDRMETH_W | OPTYPE_dq | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "pcmpgtb", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_dq | OP_R, ADDRMETH_W | OPTYPE_dq | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "pcmpgtw", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_dq | OP_R, ADDRMETH_W | OPTYPE_dq | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "pcmpgtd", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_dq | OP_R, ADDRMETH_W | OPTYPE_dq | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "packuswb", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_dq | OP_R, ADDRMETH_W | OPTYPE_dq | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "punpckhbw", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_dq | OP_R, ADDRMETH_W | OPTYPE_dq | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "punpckhwd", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_dq | OP_R, ADDRMETH_W | OPTYPE_dq | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "punpckhdq", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_dq | OP_R, ADDRMETH_W | OPTYPE_dq | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "packssdw", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_dq | OP_R, ADDRMETH_W | OPTYPE_dq | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "punpcklqdq", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_dq | OP_R, ADDRMETH_W | OPTYPE_dq | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "punpckhqdq", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_d | OP_R, ADDRMETH_E | OPTYPE_d | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "movd", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_dq | OP_R, ADDRMETH_W | OPTYPE_dq | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "movdqa", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_dq | OP_R, ADDRMETH_W | OPTYPE_dq | OP_R, ADDRMETH_I | OPTYPE_b | OP_R, cpu_PENTIUM4 | isa_GP, "pshufd", "", 0, 0, 0, 0, 0 },
+ { idx_660F71, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { idx_660F72, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { idx_660F73, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_dq | OP_R, ADDRMETH_W | OPTYPE_dq | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "pcmpeqb", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_dq | OP_R, ADDRMETH_W | OPTYPE_dq | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "pcmpeqw", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_dq | OP_R, ADDRMETH_W | OPTYPE_dq | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "pcmpeqd", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_pd | OP_R, ADDRMETH_W | OPTYPE_pd | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "haddpd", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_pd | OP_R, ADDRMETH_W | OPTYPE_pd | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "hsubpd", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_E | OPTYPE_d | OP_R, ADDRMETH_V | OPTYPE_d | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "movd", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_W | OPTYPE_dq | OP_R, ADDRMETH_V | OPTYPE_dq | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "movdqa", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_pd | OP_R, ADDRMETH_W | OPTYPE_pd | OP_R, ADDRMETH_I | OPTYPE_b | OP_R, cpu_PENTIUM4 | isa_GP, "cmppd", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_w | OP_R, ADDRMETH_E | OPTYPE_d | OP_R, ADDRMETH_I | OPTYPE_b | OP_R, cpu_PENTIUM4 | isa_GP, "pinsrw", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_G | OPTYPE_d | OP_R, ADDRMETH_W | OPTYPE_w | OP_R, ADDRMETH_I | OPTYPE_b | OP_R, cpu_PENTIUM4 | isa_GP, "pextrw", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_pd | OP_R, ADDRMETH_W | OPTYPE_pd | OP_R, ADDRMETH_I | OPTYPE_b | OP_R, cpu_PENTIUM4 | isa_GP, "shufpd", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_pd | OP_R, ADDRMETH_W | OPTYPE_pd | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "addsubpd", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_dq | OP_R, ADDRMETH_W | OPTYPE_dq | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "psrlw", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_dq | OP_R, ADDRMETH_W | OPTYPE_dq | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "psrld", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_dq | OP_R, ADDRMETH_W | OPTYPE_dq | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "psrlq", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_dq | OP_R, ADDRMETH_W | OPTYPE_dq | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "paddq", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_dq | OP_R, ADDRMETH_W | OPTYPE_dq | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "pmullw", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_W | OPTYPE_q | OP_R, ADDRMETH_V | OPTYPE_q | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "movq", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_G | OPTYPE_d | OP_R, ADDRMETH_W | OPTYPE_dq | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "pmovmskb", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_dq | OP_R, ADDRMETH_W | OPTYPE_dq | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "psubusb", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_dq | OP_R, ADDRMETH_W | OPTYPE_dq | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "psubusw", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_dq | OP_R, ADDRMETH_W | OPTYPE_dq | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "pminub", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_dq | OP_R, ADDRMETH_W | OPTYPE_dq | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "pand", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_dq | OP_R, ADDRMETH_W | OPTYPE_dq | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "paddusb", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_dq | OP_R, ADDRMETH_W | OPTYPE_dq | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "paddusw", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_dq | OP_R, ADDRMETH_W | OPTYPE_dq | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "pmaxub", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_dq | OP_R, ADDRMETH_W | OPTYPE_dq | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "pandn", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_dq | OP_R, ADDRMETH_W | OPTYPE_dq | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "pavgb", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_dq | OP_R, ADDRMETH_W | OPTYPE_dq | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "psraw", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_dq | OP_R, ADDRMETH_W | OPTYPE_dq | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "psrad", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_dq | OP_R, ADDRMETH_W | OPTYPE_dq | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "pavgw", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_dq | OP_R, ADDRMETH_W | OPTYPE_dq | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "pmulhuw", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_dq | OP_R, ADDRMETH_W | OPTYPE_dq | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "pmulhw", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_dq | OP_R, ADDRMETH_W | OPTYPE_pd | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "cvttpd2dq", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_M | OPTYPE_dq | OP_R, ADDRMETH_V | OPTYPE_dq | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "movntdq", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_dq | OP_R, ADDRMETH_W | OPTYPE_dq | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "psubsb", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_dq | OP_R, ADDRMETH_W | OPTYPE_dq | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "psubsw", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_dq | OP_R, ADDRMETH_W | OPTYPE_dq | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "pminsw", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_dq | OP_R, ADDRMETH_W | OPTYPE_dq | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "por", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_dq | OP_R, ADDRMETH_W | OPTYPE_dq | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "paddsb", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_dq | OP_R, ADDRMETH_W | OPTYPE_dq | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "paddsw", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_dq | OP_R, ADDRMETH_W | OPTYPE_dq | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "pmaxsw", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_dq | OP_R, ADDRMETH_W | OPTYPE_dq | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "pxor", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_dq | OP_R, ADDRMETH_W | OPTYPE_dq | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "psllw", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_dq | OP_R, ADDRMETH_W | OPTYPE_dq | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "pslld", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_dq | OP_R, ADDRMETH_W | OPTYPE_dq | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "psllq", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_dq | OP_R, ADDRMETH_W | OPTYPE_dq | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "pmuludq", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_dq | OP_R, ADDRMETH_W | OPTYPE_dq | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "pmaddwd", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_dq | OP_R, ADDRMETH_W | OPTYPE_dq | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "psadbw", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_dq | OP_R, ADDRMETH_W | OPTYPE_dq | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "maskmovdqu", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_dq | OP_R, ADDRMETH_W | OPTYPE_dq | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "psubb", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_dq | OP_R, ADDRMETH_W | OPTYPE_dq | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "psubw", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_dq | OP_R, ADDRMETH_W | OPTYPE_dq | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "psubd", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_dq | OP_R, ADDRMETH_W | OPTYPE_dq | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "psubq", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_dq | OP_R, ADDRMETH_W | OPTYPE_dq | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "paddb", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_dq | OP_R, ADDRMETH_W | OPTYPE_dq | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "paddw", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_dq | OP_R, ADDRMETH_W | OPTYPE_dq | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "paddd", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 }
+};
+
+
+static ia32_insn_t tbl_F20F[] = { /* SIMD F2 Two-byte Opcodes */
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_sd | OP_R, ADDRMETH_W | OPTYPE_sd | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "movsd", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_W | OPTYPE_sd | OP_R, ADDRMETH_V | OPTYPE_sd | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "movsd", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_q | OP_R, ADDRMETH_W | OPTYPE_q | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "movddup", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_sd | OP_R, ADDRMETH_E | OPTYPE_d | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "cvtsi2sd", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_G | OPTYPE_d | OP_R, ADDRMETH_W | OPTYPE_sd | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "cvttsd2si", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_G | OPTYPE_d | OP_R, ADDRMETH_W | OPTYPE_sd | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "cvtsd2si", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_sd | OP_R, ADDRMETH_W | OPTYPE_sd | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "sqrtsd", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_sd | OP_R, ADDRMETH_W | OPTYPE_sd | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "addsd", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_sd | OP_R, ADDRMETH_W | OPTYPE_sd | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "mulsd", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_ss | OP_R, ADDRMETH_W | OPTYPE_sd | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "cvtsd2ss", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_sd | OP_R, ADDRMETH_W | OPTYPE_sd | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "subsd", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_sd | OP_R, ADDRMETH_W | OPTYPE_sd | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "minsd", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_sd | OP_R, ADDRMETH_W | OPTYPE_sd | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "divsd", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_sd | OP_R, ADDRMETH_W | OPTYPE_sd | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "maxsd", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_dq | OP_R, ADDRMETH_W | OPTYPE_dq | OP_R, ADDRMETH_I | OPTYPE_b | OP_R, cpu_PENTIUM4 | isa_GP, "pshuflw", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_ps | OP_R, ADDRMETH_W | OPTYPE_ps | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "haddps", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_ps | OP_R, ADDRMETH_W | OPTYPE_ps | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "hsubps", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_sd | OP_R, ADDRMETH_W | OPTYPE_sd | OP_R, ADDRMETH_I | OPTYPE_b | OP_R, cpu_PENTIUM4 | isa_GP, "cmpsd", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_ps | OP_R, ADDRMETH_W | OPTYPE_ps | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "addsubps", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_P | OPTYPE_q | OP_R, ADDRMETH_W | OPTYPE_q | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "movdq2q", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_dq | OP_R, ADDRMETH_W | OPTYPE_pd | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "cvtpd2dq", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_dq | OP_R, ADDRMETH_M | OPTYPE_dq | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "lddqu", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 }
+};
+
+
+static ia32_insn_t tbl_F30F[] = { /* SIMD F3 Two-byte Opcodes */
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_ss | OP_R, ADDRMETH_W | OPTYPE_ss | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "movss", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_W | OPTYPE_ss | OP_R, ADDRMETH_V | OPTYPE_ss | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "movss", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_ps | OP_R, ADDRMETH_W | OPTYPE_ps | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "movsldup", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_ps | OP_R, ADDRMETH_W | OPTYPE_ps | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "movshdup", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_ss | OP_R, ADDRMETH_E | OPTYPE_d | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "cvtsi2ss", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_G | OPTYPE_d | OP_R, ADDRMETH_W | OPTYPE_ss | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "cvttss2si", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_G | OPTYPE_d | OP_R, ADDRMETH_W | OPTYPE_ss | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "cvtss2si", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_ss | OP_R, ADDRMETH_W | OPTYPE_ss | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "sqrtss", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_ss | OP_R, ADDRMETH_W | OPTYPE_ss | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "rsqrtss", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_ss | OP_R, ADDRMETH_W | OPTYPE_ss | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "rcpss", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_ss | OP_R, ADDRMETH_W | OPTYPE_ss | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "addss", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_ss | OP_R, ADDRMETH_W | OPTYPE_ss | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "mulss", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_sd | OP_R, ADDRMETH_W | OPTYPE_ss | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "cvtss2sd", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_dq | OP_R, ADDRMETH_W | OPTYPE_ps | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "cvttps2dq", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_ss | OP_R, ADDRMETH_W | OPTYPE_ss | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "subss", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_ss | OP_R, ADDRMETH_W | OPTYPE_ss | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "minss", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_ss | OP_R, ADDRMETH_W | OPTYPE_ss | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "divss", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_ss | OP_R, ADDRMETH_W | OPTYPE_ss | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "maxss", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_dq | OP_R, ADDRMETH_W | OPTYPE_dq | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "movdqu", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_dq | OP_R, ADDRMETH_W | OPTYPE_dq | OP_R, ADDRMETH_I | OPTYPE_b | OP_R, cpu_PENTIUM4 | isa_GP, "pshufhw", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_q | OP_R, ADDRMETH_W | OPTYPE_q | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "movq", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_W | OPTYPE_dq | OP_R, ADDRMETH_V | OPTYPE_dq | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "movdqu", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_ss | OP_R, ADDRMETH_W | OPTYPE_ss | OP_R, ADDRMETH_I | OPTYPE_b | OP_R, cpu_PENTIUM4 | isa_GP, "cmpss", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_dq | OP_R, ADDRMETH_Q | OPTYPE_q | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "movq2dq", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_UNKNOWN, 0, ADDRMETH_V | OPTYPE_pd | OP_R, ADDRMETH_W | OPTYPE_q | OP_R, ARG_NONE, cpu_PENTIUM4 | isa_GP, "cvtdq2pd", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "", "", 0, 0, 0, 0, 0 }
+};
+
+
+static ia32_insn_t tbl_0F00[] = { /* Group 6 */
+ { 0, INS_SYSTEM, 0, ADDRMETH_E | OPTYPE_w | OP_R, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "sldt", "", 0, 0, 0, 0 , 46 },
+ { 0, INS_SYSTEM, 0, ADDRMETH_E | OPTYPE_w | OP_W, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "str", "", 0, 0, 0, 0 , 49 },
+ { 0, INS_SYSTEM, 0, ADDRMETH_E | OPTYPE_w | OP_W, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "lldt", "", 0, 0, 0, 0 , 29 },
+ { 0, INS_SYSTEM, 0, ADDRMETH_E | OPTYPE_w | OP_W, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "ltr", "", 0, 0, 0, 0 , 32 },
+ { 0, INS_SYSTEM, 0, ADDRMETH_E | OPTYPE_w | OP_R, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "verr", "", 0, 0, 0, INS_SET_ZERO, 0 },
+ { 0, INS_SYSTEM, 0, ADDRMETH_E | OPTYPE_w | OP_R, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "verw", "", 0, 0, 0, INS_SET_ZERO, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 }
+};
+
+
+static ia32_insn_t tbl_0F01[] = { /* Group 7 */
+ { 0, INS_SYSTEM, 0, ADDRMETH_M | OPTYPE_s | OP_R, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "sgdt", "", 0, 0, 0, 0 , 44 },
+ { 0, INS_SYSTEM, 0, ADDRMETH_M | OPTYPE_s | OP_R, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "sidt", "", 0, 0, 0, 0 , 45 },
+ { 0, INS_SYSTEM, 0, ADDRMETH_M | OPTYPE_s | OP_W, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "lgdt", "", 0, 0, 0, 0 , 27 },
+ { 0, INS_SYSTEM, 0, ADDRMETH_M | OPTYPE_s | OP_W, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "lidt", "", 0, 0, 0, 0 , 28 },
+ { 0, INS_SYSTEM, 0, ADDRMETH_E | OPTYPE_w | OP_W, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "smsw", "", 0, 0, 0, 0 , 47 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_SYSTEM, 0, ADDRMETH_E | OPTYPE_w | OP_W, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "lmsw", "", 0, 0, 0, 0 , 30 },
+ { 0, INS_SYSTEM, 0, ADDRMETH_M | OPTYPE_none | OP_R, ARG_NONE, ARG_NONE, cpu_80486 | isa_GP, "invlpg", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_SYSTEM, 0, ADDRMETH_M | OPTYPE_s | OP_R, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "sgdt", "", 0, 0, 0, 0 , 44 },
+ { 0, INS_SYSTEM, 0, ADDRMETH_M | OPTYPE_s | OP_R, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "sidt", "", 0, 0, 0, 0 , 45 },
+ { 0, INS_SYSTEM, 0, ADDRMETH_M | OPTYPE_s | OP_W, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "lgdt", "", 0, 0, 0, 0 , 27 },
+ { 0, INS_SYSTEM, 0, ADDRMETH_M | OPTYPE_s | OP_W, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "lidt", "", 0, 0, 0, 0 , 28 },
+ { 0, INS_SYSTEM, 0, ADDRMETH_E | OPTYPE_w | OP_W, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "smsw", "", 0, 0, 0, 0 , 47 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_SYSTEM, 0, ADDRMETH_E | OPTYPE_w | OP_W, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "lmsw", "", 0, 0, 0, 0 , 30 },
+ { 0, INS_SYSTEM, 0, ADDRMETH_M | OPTYPE_none | OP_R, ARG_NONE, ARG_NONE, cpu_80486 | isa_GP, "invlpg", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_SYSTEM, 0, ADDRMETH_M | OPTYPE_s | OP_R, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "sgdt", "", 0, 0, 0, 0 , 44 },
+ { 0, INS_SYSTEM, 0, ADDRMETH_M | OPTYPE_s | OP_R, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "sidt", "", 0, 0, 0, 0 , 45 },
+ { 0, INS_SYSTEM, 0, ADDRMETH_M | OPTYPE_s | OP_W, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "lgdt", "", 0, 0, 0, 0 , 27 },
+ { 0, INS_SYSTEM, 0, ADDRMETH_M | OPTYPE_s | OP_W, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "lidt", "", 0, 0, 0, 0 , 28 },
+ { 0, INS_SYSTEM, 0, ADDRMETH_E | OPTYPE_w | OP_W, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "smsw", "", 0, 0, 0, 0 , 47 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_SYSTEM, 0, ADDRMETH_E | OPTYPE_w | OP_W, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "lmsw", "", 0, 0, 0, 0 , 30 },
+ { 0, INS_SYSTEM, 0, ADDRMETH_M | OPTYPE_none | OP_R, ARG_NONE, ARG_NONE, cpu_80486 | isa_GP, "invlpg", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { idx_0F0111, 0, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_SYSTEM, 0, ADDRMETH_E | OPTYPE_w | OP_W, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "smsw", "", 0, 0, 0, 0 , 47 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_SYSTEM, 0, ADDRMETH_E | OPTYPE_w | OP_W, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "lmsw", "", 0, 0, 0, 0 , 30 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 }
+};
+
+
+static ia32_insn_t tbl_0F0111[] = { /* Monitor/MWait opcode */
+ { 0, INS_SYSTEM, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "monitor", "", 0, 0, 0, 0, 54 },
+ { 0, INS_SYSTEM, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "mwait", "", 0, 0, 0, 0, 55 }
+};
+
+
+static ia32_insn_t tbl_0F12[] = { /* Movlps Opcode */
+ { 0, INS_MOV, INS_NOTE_NOSUFFIX, ADDRMETH_V | OPTYPE_q | OP_W, ADDRMETH_M | OPTYPE_q | OP_R, ARG_NONE, cpu_PENTIUM2 | isa_GP, "movlps", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_MOV, INS_NOTE_NOSUFFIX, ADDRMETH_V | OPTYPE_q | OP_W, ADDRMETH_M | OPTYPE_q | OP_R, ARG_NONE, cpu_PENTIUM2 | isa_GP, "movlps", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_MOV, INS_NOTE_NOSUFFIX, ADDRMETH_V | OPTYPE_q | OP_W, ADDRMETH_M | OPTYPE_q | OP_R, ARG_NONE, cpu_PENTIUM2 | isa_GP, "movlps", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_MOV, 0, ADDRMETH_V | OPTYPE_ps | OP_R | OP_W, ADDRMETH_W | OPTYPE_ps | OP_R , ARG_NONE, cpu_PENTIUM4 | isa_GP, "movhlps", "", 0, 0, 0, 0, 0 }
+};
+
+
+static ia32_insn_t tbl_0F16[] = { /* Movhps Opcode */
+ { 0, INS_OTHER, 0, ADDRMETH_V | OPTYPE_q | OP_W, ADDRMETH_M | OPTYPE_q | OP_R, ARG_NONE, cpu_PENTIUM2 | isa_GP, "movhps", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_OTHER, 0, ADDRMETH_V | OPTYPE_q | OP_W, ADDRMETH_M | OPTYPE_q | OP_R, ARG_NONE, cpu_PENTIUM2 | isa_GP, "movhps", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_OTHER, 0, ADDRMETH_V | OPTYPE_q | OP_W, ADDRMETH_M | OPTYPE_q | OP_R, ARG_NONE, cpu_PENTIUM2 | isa_GP, "movhps", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_MOV, 0, ADDRMETH_V | OPTYPE_ps | OP_R | OP_W, ADDRMETH_W | OPTYPE_ps | OP_R , ARG_NONE, cpu_PENTIUM4 | isa_GP, "movlhps", "", 0, 0, 0, 0, 0 }
+};
+
+
+static ia32_insn_t tbl_0F18[] = { /* Group 16 */
+ { 0, INS_SYSTEM, 0, OP_W | OPTYPE_b | ADDRMETH_M, ARG_NONE, ARG_NONE, cpu_PENTIUM2 | isa_GP, "prefetchnta", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_SYSTEM, 0, ADDRMETH_RT | OPTYPE_d | OP_W, ARG_NONE, ARG_NONE, cpu_PENTIUM2 | isa_GP, "prefetcht0", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_SYSTEM, 0, ADDRMETH_RT | OPTYPE_d | OP_W, ARG_NONE, ARG_NONE, cpu_PENTIUM2 | isa_GP, "prefetcht1", "", 1, 0, 0, 0 , 0 },
+ { 0, INS_SYSTEM, 0, ADDRMETH_RT | OPTYPE_d | OP_W, ARG_NONE, ARG_NONE, cpu_PENTIUM2 | isa_GP, "prefetcht2", "", 2, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_SYSTEM, 0, OP_W | OPTYPE_b | ADDRMETH_M, ARG_NONE, ARG_NONE, cpu_PENTIUM2 | isa_GP, "prefetchnta", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_SYSTEM, 0, ADDRMETH_RT | OPTYPE_d | OP_W, ARG_NONE, ARG_NONE, cpu_PENTIUM2 | isa_GP, "prefetcht0", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_SYSTEM, 0, ADDRMETH_RT | OPTYPE_d | OP_W, ARG_NONE, ARG_NONE, cpu_PENTIUM2 | isa_GP, "prefetcht1", "", 1, 0, 0, 0 , 0 },
+ { 0, INS_SYSTEM, 0, ADDRMETH_RT | OPTYPE_d | OP_W, ARG_NONE, ARG_NONE, cpu_PENTIUM2 | isa_GP, "prefetcht2", "", 2, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_SYSTEM, 0, OP_W | OPTYPE_b | ADDRMETH_M, ARG_NONE, ARG_NONE, cpu_PENTIUM2 | isa_GP, "prefetchnta", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_SYSTEM, 0, ADDRMETH_RT | OPTYPE_d | OP_W, ARG_NONE, ARG_NONE, cpu_PENTIUM2 | isa_GP, "prefetcht0", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_SYSTEM, 0, ADDRMETH_RT | OPTYPE_d | OP_W, ARG_NONE, ARG_NONE, cpu_PENTIUM2 | isa_GP, "prefetcht1", "", 1, 0, 0, 0 , 0 },
+ { 0, INS_SYSTEM, 0, ADDRMETH_RT | OPTYPE_d | OP_W, ARG_NONE, ARG_NONE, cpu_PENTIUM2 | isa_GP, "prefetcht2", "", 2, 0, 0, 0 , 0 }
+};
+
+
+static ia32_insn_t tbl_0F71[] = { /* Group 12 */
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_OTHER, 0, ADDRMETH_P | OPTYPE_q | OP_W, ADDRMETH_I | OPTYPE_b | OP_R, ARG_NONE, cpu_PENTIUM | isa_MMX, "psrlw", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_OTHER, 0, ADDRMETH_P | OPTYPE_q | OP_W, ADDRMETH_I | OPTYPE_b | OP_R, ARG_NONE, cpu_PENTIUM | isa_MMX, "psraw", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_OTHER, 0, ADDRMETH_P | OPTYPE_q | OP_W, ADDRMETH_I | OPTYPE_b | OP_R, ARG_NONE, cpu_PENTIUM | isa_MMX, "psllw", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 }
+};
+
+
+static ia32_insn_t tbl_660F71[] = { /* Group 12 SSE */
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_OTHER, 0, ADDRMETH_P | OPTYPE_dq | OP_W, ADDRMETH_I | OPTYPE_b | OP_R, ARG_NONE, cpu_PENTIUM | isa_MMX, "psrlw", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_OTHER, 0, ADDRMETH_P | OPTYPE_dq | OP_W, ADDRMETH_I | OPTYPE_b | OP_R, ARG_NONE, cpu_PENTIUM | isa_MMX, "psraw", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_OTHER, 0, ADDRMETH_P | OPTYPE_dq | OP_W, ADDRMETH_I | OPTYPE_b | OP_R, ARG_NONE, cpu_PENTIUM | isa_MMX, "psllw", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 }
+};
+
+
+static ia32_insn_t tbl_0F72[] = { /* Group 13 */
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_OTHER, 0, ADDRMETH_P | OPTYPE_q | OP_W, ADDRMETH_I | OPTYPE_b | OP_R, ARG_NONE, cpu_PENTIUM | isa_MMX, "psrld", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_OTHER, 0, ADDRMETH_P | OPTYPE_q | OP_W, ADDRMETH_I | OPTYPE_b | OP_R, ARG_NONE, cpu_PENTIUM | isa_MMX, "psrad", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_OTHER, 0, ADDRMETH_P | OPTYPE_q | OP_W, ADDRMETH_I | OPTYPE_b | OP_R, ARG_NONE, cpu_PENTIUM | isa_MMX, "pslld", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 }
+};
+
+
+static ia32_insn_t tbl_660F72[] = { /* Group 13 SSE */
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_OTHER, 0, ADDRMETH_W | OPTYPE_dq | OP_W, ADDRMETH_I | OPTYPE_b | OP_R, ARG_NONE, cpu_PENTIUM | isa_MMX, "psrld", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_OTHER, 0, ADDRMETH_W | OPTYPE_dq | OP_W, ADDRMETH_I | OPTYPE_b | OP_R, ARG_NONE, cpu_PENTIUM | isa_MMX, "psrad", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_OTHER, 0, ADDRMETH_W | OPTYPE_dq | OP_W, ADDRMETH_I | OPTYPE_b | OP_R, ARG_NONE, cpu_PENTIUM | isa_MMX, "pslld", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 }
+};
+
+
+static ia32_insn_t tbl_0F73[] = { /* Group 14 */
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_OTHER, 0, ADDRMETH_P | OPTYPE_q | OP_W, ADDRMETH_I | OPTYPE_b | OP_R, ARG_NONE, cpu_PENTIUM | isa_MMX, "psrlq", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_OTHER, 0, ADDRMETH_P | OPTYPE_q | OP_W, ADDRMETH_I | OPTYPE_b | OP_R, ARG_NONE, cpu_PENTIUM | isa_MMX, "psllq", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 }
+};
+
+
+static ia32_insn_t tbl_660F73[] = { /* Group 14 SSE */
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_OTHER, 0, ADDRMETH_W | OPTYPE_dq | OP_W, ADDRMETH_I | OPTYPE_b | OP_R, ARG_NONE, cpu_PENTIUM | isa_MMX, "psrlq", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_OTHER, 0, ADDRMETH_W | OPTYPE_dq | OP_W, ADDRMETH_I | OPTYPE_b | OP_R, ARG_NONE, cpu_PENTIUM | isa_MMX, "psrldq", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_OTHER, 0, ADDRMETH_W | OPTYPE_dq | OP_W, ADDRMETH_I | OPTYPE_b | OP_R, ARG_NONE, cpu_PENTIUM | isa_MMX, "psllq", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_OTHER, 0, ADDRMETH_W | OPTYPE_dq | OP_W, ADDRMETH_I | OPTYPE_b | OP_R, ARG_NONE, cpu_PENTIUM | isa_MMX, "pslldq", "", 0, 0, 0, 0 , 0 }
+};
+
+
+static ia32_insn_t tbl_0FAE[] = { /* Group 15 */
+ { 0, INS_FPU, 0, ADDRMETH_E | OPTYPE_fx | OP_W, ARG_NONE, ARG_NONE, cpu_PENTIUM | isa_MMX, "fxsave", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_E | OPTYPE_fx | OP_R, ARG_NONE, ARG_NONE, cpu_PENTIUM | isa_MMX, "fxrstor", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_SYSTEM, 0, ADDRMETH_E | OPTYPE_d | OP_R, ARG_NONE, ARG_NONE, cpu_PENTIUM2, "ldmxcsr", "", 0, 0, 0, 0 , 25 },
+ { 0, INS_SYSTEM, 0, ADDRMETH_E | OPTYPE_d | OP_W, ARG_NONE, ARG_NONE, cpu_PENTIUM2, "stmxcsr", "", 0, 0, 0 , 0, 48 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_SYSTEM, 0, ADDRMETH_M | OPTYPE_b | OP_R, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "clflush", "", 0, 0, 0, 0, 0 },
+ { 0, INS_FPU, 0, ADDRMETH_E | OPTYPE_fx | OP_W, ARG_NONE, ARG_NONE, cpu_PENTIUM | isa_MMX, "fxsave", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_E | OPTYPE_fx | OP_R, ARG_NONE, ARG_NONE, cpu_PENTIUM | isa_MMX, "fxrstor", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_SYSTEM, 0, ADDRMETH_E | OPTYPE_d | OP_R, ARG_NONE, ARG_NONE, cpu_PENTIUM2, "ldmxcsr", "", 0, 0, 0, 0 , 25 },
+ { 0, INS_SYSTEM, 0, ADDRMETH_E | OPTYPE_d | OP_W, ARG_NONE, ARG_NONE, cpu_PENTIUM2, "stmxcsr", "", 0, 0, 0 , 0, 48 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_SYSTEM, 0, ADDRMETH_M | OPTYPE_b | OP_R, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "clflush", "", 0, 0, 0, 0, 0 },
+ { 0, INS_FPU, 0, ADDRMETH_E | OPTYPE_fx | OP_W, ARG_NONE, ARG_NONE, cpu_PENTIUM | isa_MMX, "fxsave", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_E | OPTYPE_fx | OP_R, ARG_NONE, ARG_NONE, cpu_PENTIUM | isa_MMX, "fxrstor", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_SYSTEM, 0, ADDRMETH_E | OPTYPE_d | OP_R, ARG_NONE, ARG_NONE, cpu_PENTIUM2, "ldmxcsr", "", 0, 0, 0, 0 , 25 },
+ { 0, INS_SYSTEM, 0, ADDRMETH_E | OPTYPE_d | OP_W, ARG_NONE, ARG_NONE, cpu_PENTIUM2, "stmxcsr", "", 0, 0, 0 , 0, 48 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_SYSTEM, 0, ADDRMETH_M | OPTYPE_b | OP_R, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "clflush", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_SYSTEM, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "lfence", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_SYSTEM, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "mfence", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_SYSTEM, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "sfence", "", 0, 0, 0, 0 , 0 }
+};
+
+
+static ia32_insn_t tbl_0FBA[] = { /* Group 8 */
+ { 0, INS_BITTEST, 0, ADDRMETH_E | OPTYPE_v | OP_R, ADDRMETH_I | OPTYPE_b | OP_R, ARG_NONE, cpu_80386 | isa_GP, "bt", "", 0, 0, 0, INS_SET_CARRY, 0 },
+ { 0, INS_BITTEST, 0, ADDRMETH_E | OPTYPE_v | OP_R, ADDRMETH_I | OPTYPE_b | OP_R, ARG_NONE, cpu_80386 | isa_GP, "bts", "", 0, 0, 0, INS_SET_CARRY, 0 },
+ { 0, INS_BITTEST, 0, ADDRMETH_E | OPTYPE_v | OP_R, ADDRMETH_I | OPTYPE_b | OP_R, ARG_NONE, cpu_80386 | isa_GP, "btr", "", 0, 0, 0, INS_SET_CARRY, 0 },
+ { 0, INS_BITTEST, 0, ADDRMETH_E | OPTYPE_v | OP_R, ADDRMETH_I | OPTYPE_b | OP_R, ARG_NONE, cpu_80386 | isa_GP, "btc", "", 0, 0, 0 , INS_SET_CARRY, 0 }
+};
+
+
+static ia32_insn_t tbl_0FC7[] = { /* Group 9 */
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_XCHGCC, 0, ADDRMETH_M | OPTYPE_q | OP_W, ARG_NONE, ARG_NONE, cpu_PENTIUM | isa_GP, "cmpxch8b", "", 0, 0, 0 , 0 , 9 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_XCHGCC, 0, ADDRMETH_M | OPTYPE_q | OP_W, ARG_NONE, ARG_NONE, cpu_PENTIUM | isa_GP, "cmpxch8b", "", 0, 0, 0 , 0 , 9 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_XCHGCC, 0, ADDRMETH_M | OPTYPE_q | OP_W, ARG_NONE, ARG_NONE, cpu_PENTIUM | isa_GP, "cmpxch8b", "", 0, 0, 0 , 0 , 9 }
+};
+
+
+static ia32_insn_t tbl_0FB9[] = { /* Group 10 */
+ { 0, INS_SYSTEM, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, "fxsave", "", 0, 0, 0, 0 , 0 }
+};
+
+
+static ia32_insn_t tbl_C6[] = { /* Group 11a */
+ { 0, INS_MOV, 0, ADDRMETH_E | OPTYPE_b | OP_W, ADDRMETH_I | OPTYPE_b | OP_R, ARG_NONE, cpu_80386 | isa_GP, "mov", "", 0, 0, 0, 0 , 0 }
+};
+
+
+static ia32_insn_t tbl_C7[] = { /* Group 11b */
+ { 0, INS_MOV, 0, ADDRMETH_E | OPTYPE_v | OP_W, ADDRMETH_I | OPTYPE_v | OP_R, ARG_NONE, cpu_80386 | isa_GP, "mov", "", 0, 0, 0, 0 , 0 }
+};
+
+
+static ia32_insn_t tbl_80[] = { /* Group 1a */
+ { 0, INS_ADD, 0, ADDRMETH_E | OPTYPE_b | OP_W | OP_R, ADDRMETH_I | OPTYPE_b | OP_SIGNED | OP_R, ARG_NONE, cpu_80386 | isa_GP, "add", "", 0, 0, 0, INS_SET_ALL, 0 },
+ { 0, INS_OR, 0, ADDRMETH_E | OPTYPE_b | OP_W | OP_R, ADDRMETH_I | OPTYPE_b | OP_R, ARG_NONE, cpu_80386 | isa_GP, "or", "", 0, 0, 0, INS_SET_ALL, 0 },
+ { 0, INS_ADD, 0, ADDRMETH_E | OPTYPE_b | OP_W | OP_R, ADDRMETH_I | OPTYPE_b | OP_SIGNED | OP_R, ARG_NONE, cpu_80386 | isa_GP, "adc", "", 0, 0, 0, INS_SET_ALL|INS_TEST_CARRY, 0 },
+ { 0, INS_SUB, 0, ADDRMETH_E | OPTYPE_b | OP_SIGNED | OP_W | OP_R, ADDRMETH_I | OPTYPE_b | OP_SIGNED | OP_R, ARG_NONE, cpu_80386 | isa_GP, "sbb", "", 0, 0, 0, INS_SET_ALL|INS_TEST_CARRY, 0 },
+ { 0, INS_AND, 0, ADDRMETH_E | OPTYPE_b | OP_W | OP_R, ADDRMETH_I | OPTYPE_b | OP_R, ARG_NONE, cpu_80386 | isa_GP, "and", "", 0, 0, 0, INS_SET_ALL, 0 },
+ { 0, INS_SUB, 0, ADDRMETH_E | OPTYPE_b | OP_SIGNED | OP_W | OP_R, ADDRMETH_I | OPTYPE_b | OP_SIGNED | OP_R, ARG_NONE, cpu_80386 | isa_GP, "sub", "", 0, 0, 0, INS_SET_ALL, 0 },
+ { 0, INS_XOR, 0, ADDRMETH_E | OPTYPE_b | OP_W | OP_R, ADDRMETH_I | OPTYPE_b | OP_R, ARG_NONE, cpu_80386 | isa_GP, "xor", "", 0, 0, 0, INS_SET_ALL, 0 },
+ { 0, INS_CMP, 0, ADDRMETH_E | OPTYPE_b | OP_R, ADDRMETH_I | OPTYPE_b | OP_SIGNED | OP_R, ARG_NONE, cpu_80386 | isa_GP, "cmp", "", 0, 0, 0 , INS_SET_ALL, 0 }
+};
+
+
+static ia32_insn_t tbl_81[] = { /* Group 1b */
+ { 0, INS_ADD, 0, ADDRMETH_E | OPTYPE_v | OP_W | OP_R, ADDRMETH_I | OPTYPE_v | OP_SIGNED | OP_R, ARG_NONE, cpu_80386 | isa_GP, "add", "", 0, 0, 0, INS_SET_ALL, 0 },
+ { 0, INS_OR, 0, ADDRMETH_E | OPTYPE_v | OP_W | OP_R, ADDRMETH_I | OPTYPE_v | OP_R, ARG_NONE, cpu_80386 | isa_GP, "or", "", 0, 0, 0, INS_SET_ALL, 0 },
+ { 0, INS_ADD, 0, ADDRMETH_E | OPTYPE_v | OP_W | OP_R, ADDRMETH_I | OPTYPE_v | OP_SIGNED | OP_R, ARG_NONE, cpu_80386 | isa_GP, "adc", "", 0, 0, 0, INS_SET_ALL|INS_TEST_CARRY, 0 },
+ { 0, INS_SUB, 0, ADDRMETH_E | OPTYPE_v | OP_SIGNED | OP_W | OP_R, ADDRMETH_I | OPTYPE_v | OP_SIGNED | OP_R, ARG_NONE, cpu_80386 | isa_GP, "sbb", "", 0, 0, 0, INS_SET_ALL|INS_TEST_CARRY, 0 },
+ { 0, INS_AND, 0, ADDRMETH_E | OPTYPE_v | OP_W | OP_R, ADDRMETH_I | OPTYPE_v | OP_R, ARG_NONE, cpu_80386 | isa_GP, "and", "", 0, 0, 0, INS_SET_ALL, 0 },
+ { 0, INS_SUB, 0, ADDRMETH_E | OPTYPE_v | OP_SIGNED | OP_W | OP_R, ADDRMETH_I | OPTYPE_v | OP_SIGNED | OP_R, ARG_NONE, cpu_80386 | isa_GP, "sub", "", 0, 0, 0, INS_SET_ALL, 0 },
+ { 0, INS_XOR, 0, ADDRMETH_E | OPTYPE_v | OP_W | OP_R, ADDRMETH_I | OPTYPE_v | OP_R, ARG_NONE, cpu_80386 | isa_GP, "xor", "", 0, 0, 0, INS_SET_ALL, 0 },
+ { 0, INS_CMP, 0, ADDRMETH_E | OPTYPE_v | OP_R, ADDRMETH_I | OPTYPE_v | OP_SIGNED | OP_R, ARG_NONE, cpu_80386 | isa_GP, "cmp", "", 0, 0, 0 , INS_SET_ALL, 0 }
+};
+
+
+static ia32_insn_t tbl_82[] = { /* Group 1c */
+ { 0, INS_ADD, 0, ADDRMETH_E | OPTYPE_b | OP_W | OP_R, ADDRMETH_I | OPTYPE_b | OP_SIGNED | OP_R, ARG_NONE, cpu_80386 | isa_GP, "add", "", 0, 0, 0, INS_SET_ALL, 0 },
+ { 0, INS_OR, 0, ADDRMETH_E | OPTYPE_b | OP_W | OP_R, ADDRMETH_I | OPTYPE_b | OP_R, ARG_NONE, cpu_80386 | isa_GP, "or", "", 0, 0, 0, INS_SET_ALL, 0 },
+ { 0, INS_ADD, 0, ADDRMETH_E | OPTYPE_b | OP_W | OP_R, ADDRMETH_I | OPTYPE_b | OP_SIGNED | OP_R, ARG_NONE, cpu_80386 | isa_GP, "adc", "", 0, 0, 0, INS_SET_ALL|INS_TEST_CARRY, 0 },
+ { 0, INS_SUB, 0, ADDRMETH_E | OPTYPE_b | OP_SIGNED | OP_W | OP_R, ADDRMETH_I | OPTYPE_b | OP_SIGNED | OP_R, ARG_NONE, cpu_80386 | isa_GP, "sbb", "", 0, 0, 0, INS_SET_ALL|INS_TEST_CARRY, 0 },
+ { 0, INS_AND, 0, ADDRMETH_E | OPTYPE_b | OP_W | OP_R, ADDRMETH_I | OPTYPE_b | OP_R, ARG_NONE, cpu_80386 | isa_GP, "and", "", 0, 0, 0, INS_SET_ALL, 0 },
+ { 0, INS_SUB, 0, ADDRMETH_E | OPTYPE_b | OP_SIGNED | OP_W | OP_R, ADDRMETH_I | OPTYPE_b | OP_SIGNED | OP_R, ARG_NONE, cpu_80386 | isa_GP, "sub", "", 0, 0, 0, INS_SET_ALL, 0 },
+ { 0, INS_XOR, 0, ADDRMETH_E | OPTYPE_b | OP_W | OP_R, ADDRMETH_I | OPTYPE_b | OP_R, ARG_NONE, cpu_80386 | isa_GP, "xor", "", 0, 0, 0, INS_SET_ALL, 0 },
+ { 0, INS_CMP, 0, ADDRMETH_E | OPTYPE_b | OP_R, ADDRMETH_I | OPTYPE_b | OP_SIGNED | OP_R, ARG_NONE, cpu_80386 | isa_GP, "cmp", "", 0, 0, 0 , INS_SET_ALL, 0 }
+};
+
+
+static ia32_insn_t tbl_83[] = { /* Group 1d */
+ { 0, INS_ADD, 0, ADDRMETH_E | OPTYPE_v | OP_W | OP_R, ADDRMETH_I | OPTYPE_b | OP_SIGNED | OP_R, ARG_NONE, cpu_80386 | isa_GP, "add", "", 0, 0, 0, INS_SET_ALL, 0 },
+ { 0, INS_OR, 0, ADDRMETH_E | OPTYPE_v | OP_W | OP_R, ADDRMETH_I | OPTYPE_b | OP_SIGNED | OP_R, ARG_NONE, cpu_80386 | isa_GP, "or", "", 0, 0, 0, INS_SET_ALL, 0 },
+ { 0, INS_ADD, 0, ADDRMETH_E | OPTYPE_v | OP_W | OP_R, ADDRMETH_I | OPTYPE_b | OP_SIGNED | OP_R, ARG_NONE, cpu_80386 | isa_GP, "adc", "", 0, 0, 0, INS_SET_ALL|INS_TEST_CARRY, 0 },
+ { 0, INS_SUB, 0, ADDRMETH_E | OPTYPE_v | OP_SIGNED | OP_W | OP_R, ADDRMETH_I | OPTYPE_b | OP_SIGNED | OP_R, ARG_NONE, cpu_80386 | isa_GP, "sbb", "", 0, 0, 0, INS_SET_ALL|INS_TEST_CARRY, 0 },
+ { 0, INS_AND, 0, ADDRMETH_E | OPTYPE_v | OP_W | OP_R, ADDRMETH_I | OPTYPE_b | OP_SIGNED | OP_R, ARG_NONE, cpu_80386 | isa_GP, "and", "", 0, 0, 0, INS_SET_ALL, 0 },
+ { 0, INS_SUB, 0, ADDRMETH_E | OPTYPE_v | OP_SIGNED | OP_W | OP_R, ADDRMETH_I | OPTYPE_b | OP_SIGNED | OP_R, ARG_NONE, cpu_80386 | isa_GP, "sub", "", 0, 0, 0, INS_SET_ALL, 0 },
+ { 0, INS_XOR, 0, ADDRMETH_E | OPTYPE_v | OP_W | OP_R, ADDRMETH_I | OPTYPE_b | OP_SIGNED | OP_R, ARG_NONE, cpu_80386 | isa_GP, "xor", "", 0, 0, 0, INS_SET_ALL, 0 },
+ { 0, INS_CMP, 0, ADDRMETH_E | OPTYPE_v | OP_R, ADDRMETH_I | OPTYPE_b | OP_SIGNED | OP_R, ARG_NONE, cpu_80386 | isa_GP, "cmp", "", 0, 0, 0 , INS_SET_ALL, 0 }
+};
+
+
+static ia32_insn_t tbl_C0[] = { /* Group 2a */
+ { 0, INS_ROL, 0, ADDRMETH_E | OPTYPE_b | OP_W | OP_R, ADDRMETH_I | OPTYPE_b | OP_R, ARG_NONE, cpu_80386 | isa_GP, "rol", "", 0, 0, 0, INS_SET_CARRY|INS_SET_OFLOW, 0 },
+ { 0, INS_ROR, 0, ADDRMETH_E | OPTYPE_b | OP_W | OP_R, ADDRMETH_I | OPTYPE_b | OP_R, ARG_NONE, cpu_80386 | isa_GP, "ror", "", 0, 0, 0, INS_SET_CARRY|INS_SET_OFLOW, 0 },
+ { 0, INS_ROL, 0, ADDRMETH_E | OPTYPE_b | OP_W | OP_R, ADDRMETH_I | OPTYPE_b | OP_R, ARG_NONE, cpu_80386 | isa_GP, "rcl", "", 0, 0, 0, INS_SET_CARRY|INS_SET_OFLOW|INS_TEST_CARRY, 0 },
+ { 0, INS_ROR, 0, ADDRMETH_E | OPTYPE_b | OP_W | OP_R, ADDRMETH_I | OPTYPE_b | OP_R, ARG_NONE, cpu_80386 | isa_GP, "rcr", "", 0, 0, 0, INS_SET_CARRY|INS_SET_OFLOW|INS_TEST_CARRY, 0 },
+ { 0, INS_SHL, 0, ADDRMETH_E | OPTYPE_b | OP_W | OP_R, ADDRMETH_I | OPTYPE_b | OP_R, ARG_NONE, cpu_80386 | isa_GP, "shl", "", 0, 0, 0, INS_SET_ALL, 0 },
+ { 0, INS_SHR, 0, ADDRMETH_E | OPTYPE_b | OP_W | OP_R, ADDRMETH_I | OPTYPE_b | OP_R, ARG_NONE, cpu_80386 | isa_GP, "shr", "", 0, 0, 0, INS_SET_ALL, 0 },
+ { 0, INS_SHL, 0, ADDRMETH_E | OPTYPE_b | OP_W | OP_R, ADDRMETH_I | OPTYPE_b | OP_R, ARG_NONE, cpu_80386 | isa_GP, "sal", "", 0, 0, 0, INS_SET_ALL, 0 },
+ { 0, INS_SHR, 0, ADDRMETH_E | OPTYPE_b | OP_W | OP_R, ADDRMETH_I | OPTYPE_b | OP_R, ARG_NONE, cpu_80386 | isa_GP, "sar", "", 0, 0, 0 , INS_SET_ALL, 0 }
+};
+
+
+static ia32_insn_t tbl_C1[] = { /* Group 2b */
+ { 0, INS_ROL, 0, ADDRMETH_E | OPTYPE_v | OP_W | OP_R, ADDRMETH_I | OPTYPE_b | OP_R, ARG_NONE, cpu_80386 | isa_GP, "rol", "", 0, 0, 0, INS_SET_CARRY|INS_SET_OFLOW, 0 },
+ { 0, INS_ROR, 0, ADDRMETH_E | OPTYPE_v | OP_W | OP_R, ADDRMETH_I | OPTYPE_b | OP_R, ARG_NONE, cpu_80386 | isa_GP, "ror", "", 0, 0, 0, INS_SET_CARRY|INS_SET_OFLOW, 0 },
+ { 0, INS_ROL, 0, ADDRMETH_E | OPTYPE_v | OP_W | OP_R, ADDRMETH_I | OPTYPE_b | OP_R, ARG_NONE, cpu_80386 | isa_GP, "rcl", "", 0, 0, 0, INS_SET_CARRY|INS_SET_OFLOW|INS_TEST_CARRY, 0 },
+ { 0, INS_ROR, 0, ADDRMETH_E | OPTYPE_v | OP_W | OP_R, ADDRMETH_I | OPTYPE_b | OP_R, ARG_NONE, cpu_80386 | isa_GP, "rcr", "", 0, 0, 0, INS_SET_CARRY|INS_SET_OFLOW|INS_TEST_CARRY, 0 },
+ { 0, INS_SHL, 0, ADDRMETH_E | OPTYPE_v | OP_W | OP_R, ADDRMETH_I | OPTYPE_b | OP_R, ARG_NONE, cpu_80386 | isa_GP, "shl", "", 0, 0, 0, INS_SET_ALL, 0 },
+ { 0, INS_SHR, 0, ADDRMETH_E | OPTYPE_v | OP_W | OP_R, ADDRMETH_I | OPTYPE_b | OP_R, ARG_NONE, cpu_80386 | isa_GP, "shr", "", 0, 0, 0, INS_SET_ALL, 0 },
+ { 0, INS_SHL, 0, ADDRMETH_E | OPTYPE_v | OP_W | OP_R, ADDRMETH_I | OPTYPE_b | OP_R, ARG_NONE, cpu_80386 | isa_GP, "sal", "", 0, 0, 0, INS_SET_ALL, 0 },
+ { 0, INS_SHR, 0, ADDRMETH_E | OPTYPE_v | OP_W | OP_R, ADDRMETH_I | OPTYPE_b | OP_R, ARG_NONE, cpu_80386 | isa_GP, "sar", "", 0, 0, 0 , INS_SET_ALL, 0 }
+};
+
+
+static ia32_insn_t tbl_D0[] = { /* Group 2c */
+ { 0, INS_ROL, 0, ADDRMETH_E | OPTYPE_b | OP_W | OP_R, ADDRMETH_II | OPTYPE_b | OP_R, ARG_NONE, cpu_80386 | isa_GP, "rol", "", 0, 1, 0, INS_SET_CARRY|INS_SET_OFLOW, 0 },
+ { 0, INS_ROR, 0, ADDRMETH_E | OPTYPE_b | OP_W | OP_R, ADDRMETH_II | OPTYPE_b | OP_R, ARG_NONE, cpu_80386 | isa_GP, "ror", "", 0, 1, 0, INS_SET_CARRY|INS_SET_OFLOW, 0 },
+ { 0, INS_ROL, 0, ADDRMETH_E | OPTYPE_b | OP_W | OP_R, ADDRMETH_II | OPTYPE_b | OP_R, ARG_NONE, cpu_80386 | isa_GP, "rcl", "", 0, 1, 0, INS_SET_CARRY|INS_SET_OFLOW|INS_TEST_CARRY, 0 },
+ { 0, INS_ROR, 0, ADDRMETH_E | OPTYPE_b | OP_W | OP_R, ADDRMETH_II | OPTYPE_b | OP_R, ARG_NONE, cpu_80386 | isa_GP, "rcr", "", 0, 1, 0, INS_SET_CARRY|INS_SET_OFLOW|INS_TEST_CARRY, 0 },
+ { 0, INS_SHL, 0, ADDRMETH_E | OPTYPE_b | OP_W | OP_R, ADDRMETH_II | OPTYPE_b | OP_R, ARG_NONE, cpu_80386 | isa_GP, "shl", "", 0, 1, 0, INS_SET_ALL, 0 },
+ { 0, INS_SHR, 0, ADDRMETH_E | OPTYPE_b | OP_W | OP_R, ADDRMETH_II | OPTYPE_b | OP_R, ARG_NONE, cpu_80386 | isa_GP, "shr", "", 0, 1, 0, INS_SET_ALL, 0 },
+ { 0, INS_SHL, 0, ADDRMETH_E | OPTYPE_b | OP_W | OP_R, ADDRMETH_II | OPTYPE_b | OP_R, ARG_NONE, cpu_80386 | isa_GP, "sal", "", 0, 1, 0, INS_SET_ALL, 0 },
+ { 0, INS_SHR, 0, ADDRMETH_E | OPTYPE_b | OP_W | OP_R, ADDRMETH_II | OPTYPE_b | OP_R, ARG_NONE, cpu_80386 | isa_GP, "sar", "", 0, 1, 0 , INS_SET_ALL, 0 }
+};
+
+
+static ia32_insn_t tbl_D1[] = { /* Group 2d */
+ { 0, INS_ROL, 0, ADDRMETH_E | OPTYPE_v | OP_W | OP_R, ADDRMETH_II | OPTYPE_v | OP_R, ARG_NONE, cpu_80386 | isa_GP, "rol", "", 0, 1, 0, INS_SET_CARRY|INS_SET_OFLOW, 0 },
+ { 0, INS_ROR, 0, ADDRMETH_E | OPTYPE_v | OP_W | OP_R, ADDRMETH_II | OPTYPE_v | OP_R, ARG_NONE, cpu_80386 | isa_GP, "ror", "", 0, 1, 0, INS_SET_CARRY|INS_SET_OFLOW, 0 },
+ { 0, INS_ROL, 0, ADDRMETH_E | OPTYPE_v | OP_W | OP_R, ADDRMETH_II | OPTYPE_v | OP_R, ARG_NONE, cpu_80386 | isa_GP, "rcl", "", 0, 1, 0, INS_SET_CARRY|INS_SET_OFLOW|INS_TEST_CARRY, 0 },
+ { 0, INS_ROR, 0, ADDRMETH_E | OPTYPE_v | OP_W | OP_R, ADDRMETH_II | OPTYPE_v | OP_R, ARG_NONE, cpu_80386 | isa_GP, "rcr", "", 0, 1, 0, INS_SET_CARRY|INS_SET_OFLOW|INS_TEST_CARRY, 0 },
+ { 0, INS_SHL, 0, ADDRMETH_E | OPTYPE_v | OP_W | OP_R, ADDRMETH_II | OPTYPE_v | OP_R, ARG_NONE, cpu_80386 | isa_GP, "shl", "", 0, 1, 0, INS_SET_ALL, 0 },
+ { 0, INS_SHR, 0, ADDRMETH_E | OPTYPE_v | OP_W | OP_R, ADDRMETH_II | OPTYPE_v | OP_R, ARG_NONE, cpu_80386 | isa_GP, "shr", "", 0, 1, 0, INS_SET_ALL, 0 },
+ { 0, INS_SHL, 0, ADDRMETH_E | OPTYPE_v | OP_W | OP_R, ADDRMETH_II | OPTYPE_v | OP_R, ARG_NONE, cpu_80386 | isa_GP, "sal", "", 0, 1, 0, INS_SET_ALL, 0 },
+ { 0, INS_SHR, 0, ADDRMETH_E | OPTYPE_v | OP_W | OP_R, ADDRMETH_II | OPTYPE_v | OP_R, ARG_NONE, cpu_80386 | isa_GP, "sar", "", 0, 1, 0 , INS_SET_ALL, 0 }
+};
+
+
+static ia32_insn_t tbl_D2[] = { /* Group 2e */
+ { 0, INS_ROL, 0, ADDRMETH_E | OPTYPE_b | OP_W | OP_R, ADDRMETH_RR | OPTYPE_b | OP_R, ARG_NONE, cpu_80386 | isa_GP, "rol", "", 0, 1, 0, INS_SET_CARRY|INS_SET_OFLOW, 0 },
+ { 0, INS_ROR, 0, ADDRMETH_E | OPTYPE_b | OP_W | OP_R, ADDRMETH_RR | OPTYPE_b | OP_R, ARG_NONE, cpu_80386 | isa_GP, "ror", "", 0, 1, 0, INS_SET_CARRY|INS_SET_OFLOW, 0 },
+ { 0, INS_ROL, 0, ADDRMETH_E | OPTYPE_b | OP_W | OP_R, ADDRMETH_RR | OPTYPE_b | OP_R, ARG_NONE, cpu_80386 | isa_GP, "rcl", "", 0, 1, 0, INS_SET_CARRY|INS_SET_OFLOW|INS_TEST_CARRY, 0 },
+ { 0, INS_ROR, 0, ADDRMETH_E | OPTYPE_b | OP_W | OP_R, ADDRMETH_RR | OPTYPE_b | OP_R, ARG_NONE, cpu_80386 | isa_GP, "rcr", "", 0, 1, 0, INS_SET_CARRY|INS_SET_OFLOW|INS_TEST_CARRY, 0 },
+ { 0, INS_SHL, 0, ADDRMETH_E | OPTYPE_b | OP_W | OP_R, ADDRMETH_RR | OPTYPE_b | OP_R, ARG_NONE, cpu_80386 | isa_GP, "shl", "", 0, 1, 0, INS_SET_ALL, 0 },
+ { 0, INS_SHR, 0, ADDRMETH_E | OPTYPE_b | OP_W | OP_R, ADDRMETH_RR | OPTYPE_b | OP_R, ARG_NONE, cpu_80386 | isa_GP, "shr", "", 0, 1, 0, INS_SET_ALL, 0 },
+ { 0, INS_SHL, 0, ADDRMETH_E | OPTYPE_b | OP_W | OP_R, ADDRMETH_RR | OPTYPE_b | OP_R, ARG_NONE, cpu_80386 | isa_GP, "sal", "", 0, 1, 0, INS_SET_ALL, 0 },
+ { 0, INS_SHR, 0, ADDRMETH_E | OPTYPE_b | OP_W | OP_R, ADDRMETH_RR | OPTYPE_b | OP_R, ARG_NONE, cpu_80386 | isa_GP, "sar", "", 0, 1, 0 , INS_SET_ALL, 0 }
+};
+
+
+static ia32_insn_t tbl_D3[] = { /* Group 2f */
+ { 0, INS_ROL, 0, ADDRMETH_E | OPTYPE_v | OP_W | OP_R, ADDRMETH_RR | OPTYPE_b | OP_R, ARG_NONE, cpu_80386 | isa_GP, "rol", "", 0, 1, 0, INS_SET_CARRY|INS_SET_OFLOW, 0 },
+ { 0, INS_ROR, 0, ADDRMETH_E | OPTYPE_v | OP_W | OP_R, ADDRMETH_RR | OPTYPE_b | OP_R, ARG_NONE, cpu_80386 | isa_GP, "ror", "", 0, 1, 0, INS_SET_CARRY|INS_SET_OFLOW, 0 },
+ { 0, INS_ROL, 0, ADDRMETH_E | OPTYPE_v | OP_W | OP_R, ADDRMETH_RR | OPTYPE_b | OP_R, ARG_NONE, cpu_80386 | isa_GP, "rcl", "", 0, 1, 0, INS_SET_CARRY|INS_SET_OFLOW|INS_TEST_CARRY, 0 },
+ { 0, INS_ROR, 0, ADDRMETH_E | OPTYPE_v | OP_W | OP_R, ADDRMETH_RR | OPTYPE_b | OP_R, ARG_NONE, cpu_80386 | isa_GP, "rcr", "", 0, 1, 0, INS_SET_CARRY|INS_SET_OFLOW|INS_TEST_CARRY, 0 },
+ { 0, INS_SHL, 0, ADDRMETH_E | OPTYPE_v | OP_W | OP_R, ADDRMETH_RR | OPTYPE_b | OP_R, ARG_NONE, cpu_80386 | isa_GP, "shl", "", 0, 1, 0, INS_SET_ALL, 0 },
+ { 0, INS_SHR, 0, ADDRMETH_E | OPTYPE_v | OP_W | OP_R, ADDRMETH_RR | OPTYPE_b | OP_R, ARG_NONE, cpu_80386 | isa_GP, "shr", "", 0, 1, 0, INS_SET_ALL, 0 },
+ { 0, INS_SHL, 0, ADDRMETH_E | OPTYPE_v | OP_W | OP_R, ADDRMETH_RR | OPTYPE_b | OP_R, ARG_NONE, cpu_80386 | isa_GP, "sal", "", 0, 1, 0, INS_SET_ALL, 0 },
+ { 0, INS_SHR, 0, ADDRMETH_E | OPTYPE_v | OP_W | OP_R, ADDRMETH_RR | OPTYPE_b | OP_R, ARG_NONE, cpu_80386 | isa_GP, "sar", "", 0, 1, 0 , INS_SET_ALL, 0 }
+};
+
+
+static ia32_insn_t tbl_F6[] = { /* Group 3a */
+ { 0, INS_TEST, 0, ADDRMETH_E | OPTYPE_b | OP_R, ADDRMETH_I | OPTYPE_b | OP_SIGNED | OP_R, ARG_NONE, cpu_80386 | isa_GP, "test", "", 0, 0, 0, INS_SET_ALL, 0 },
+ { 0, INS_TEST, 0, ADDRMETH_E | OPTYPE_b | OP_R, ADDRMETH_I | OPTYPE_b | OP_SIGNED | OP_R, ARG_NONE, cpu_80386 | isa_GP, "test", "", 0, 0, 0, INS_SET_ALL, 0 },
+ { 0, INS_NOT, 0, ADDRMETH_E | OPTYPE_b | OP_W | OP_R, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "not", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_NEG, 0, ADDRMETH_E | OPTYPE_b | OP_W | OP_R, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "neg", "", 0, 0, 0, INS_SET_ALL, 0 },
+ { 0, INS_MUL, 0, OPTYPE_b | ADDRMETH_RR | OP_W | OP_R, ADDRMETH_E | OPTYPE_b | OP_R, ARG_NONE, cpu_80386 | isa_GP, "mul", "", 0, 0, 0, INS_SET_OFLOW|INS_SET_CARRY, 22 },
+ { 0, INS_MUL, 0, OPTYPE_b | ADDRMETH_RR | OP_W | OP_SIGNED | OP_R, ADDRMETH_E | OPTYPE_b | OP_SIGNED | OP_R, ARG_NONE, cpu_80386 | isa_GP, "imul", "", 0, 0, 0, INS_SET_OFLOW|INS_SET_CARRY, 22 },
+ { 0, INS_DIV, 0, ADDRMETH_RR | OPTYPE_b | OP_W | OP_R, ADDRMETH_E | OPTYPE_b | OP_R, ARG_NONE, cpu_80386 | isa_GP, "div", "", 0, 0, 0, 0 , 13 },
+ { 0, INS_DIV, 0, ADDRMETH_RR | OPTYPE_b | OP_W | OP_R, ADDRMETH_E | OPTYPE_b | OP_R, ARG_NONE, cpu_80386 | isa_GP, "idiv", "", 0, 0, 0 , 0 , 13 }
+};
+
+
+static ia32_insn_t tbl_F7[] = { /* Group 3b */
+ { 0, INS_TEST, 0, ADDRMETH_E | OPTYPE_v | OP_R, ADDRMETH_I | OPTYPE_v | OP_SIGNED | OP_R, ARG_NONE, cpu_80386 | isa_GP, "test", "", 0, 0, 0, INS_SET_ALL, 0 },
+ { 0, INS_TEST, 0, ADDRMETH_E | OPTYPE_v | OP_R, ADDRMETH_I | OPTYPE_v | OP_SIGNED | OP_R, ARG_NONE, cpu_80386 | isa_GP, "test", "", 0, 0, 0, INS_SET_ALL, 0 },
+ { 0, INS_NOT, 0, ADDRMETH_E | OPTYPE_v | OP_W | OP_R, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "not", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_NEG, 0, ADDRMETH_E | OPTYPE_v | OP_W | OP_R, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "neg", "", 0, 0, 0, INS_SET_ALL, 0 },
+ { 0, INS_MUL, 0, ADDRMETH_RR | OPTYPE_v | OP_W | OP_R, ADDRMETH_E | OPTYPE_v | OP_R, ARG_NONE, cpu_80386 | isa_GP, "mul", "", 0, 0, 0, INS_SET_OFLOW|INS_SET_CARRY, 23 },
+ { 0, INS_MUL, 0, ADDRMETH_RR | OPTYPE_v | OP_SIGNED | OP_W | OP_R, ADDRMETH_E | OPTYPE_v | OP_SIGNED | OP_R, ARG_NONE, cpu_80386 | isa_GP, "imul", "", 0, 0, 0, INS_SET_OFLOW|INS_SET_CARRY, 23 },
+ { 0, INS_DIV, 0, ADDRMETH_RR | OPTYPE_v | OP_W | OP_R, ADDRMETH_E | OPTYPE_v | OP_R, ARG_NONE, cpu_80386 | isa_GP, "div", "", 0, 0, 0, 0 , 14 },
+ { 0, INS_DIV, 0, ADDRMETH_RR | OPTYPE_v | OP_W | OP_R, ADDRMETH_E | OPTYPE_v | OP_R, ARG_NONE, cpu_80386 | isa_GP, "idiv", "", 0, 0, 0, 0 , 14 }
+};
+
+
+static ia32_insn_t tbl_FE[] = { /* Group 4 */
+ { 0, INS_INC, 0, ADDRMETH_E | OPTYPE_b | OP_W | OP_R, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "inc", "", 0, 0, 0, INS_SET_OFLOW|INS_SET_SIGN|INS_SET_ZERO|INS_SET_PARITY, 0 },
+ { 0, INS_DEC, 0, ADDRMETH_E | OPTYPE_b | OP_W | OP_R, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "dec", "", 0, 0, 0 , INS_SET_OFLOW|INS_SET_SIGN|INS_SET_ZERO|INS_SET_PARITY, 0 }
+};
+
+
+static ia32_insn_t tbl_FF[] = { /* Group 5 */
+ { 0, INS_INC, 0, ADDRMETH_E | OPTYPE_v | OP_W | OP_R, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "inc", "", 0, 0, 0, INS_SET_OFLOW|INS_SET_SIGN|INS_SET_ZERO|INS_SET_PARITY, 0 },
+ { 0, INS_DEC, 0, ADDRMETH_E | OPTYPE_v | OP_W | OP_R, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "dec", "", 0, 0, 0, INS_SET_OFLOW|INS_SET_SIGN|INS_SET_ZERO|INS_SET_PARITY, 0 },
+ { 0, INS_CALL, 0, ADDRMETH_E | OPTYPE_v | OP_X, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "call", "", 0, 0, 0, 0 , 3 },
+ { 0, INS_CALL, 0, ADDRMETH_M | OPTYPE_p | OP_X, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "call", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_BRANCH, 0, ADDRMETH_E | OPTYPE_v | OP_X, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "jmp", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_BRANCH, 0, ADDRMETH_M | OPTYPE_p | OP_X, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "jmp", "", 0, 0, 0, 0 , 0 },
+ { 0, INS_PUSH, 0, ADDRMETH_E | OPTYPE_v | OP_R, ARG_NONE, ARG_NONE, cpu_80386 | isa_GP, "push", "", 0, 0, 0, 0 , 33 }
+};
+
+
+static ia32_insn_t tbl_D8[] = { /* FPU D8 */
+ { 0, INS_FPU, 0, ADDRMETH_M|OPTYPE_fs|OP_W, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "fadd", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_M|OPTYPE_fs|OP_W, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "fmul", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_M|OPTYPE_fs|OP_W, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "fcom", "", 0, 0, 0 , INS_SET_ZERO|INS_SET_PARITY|INS_SET_CARRY, 17 },
+ { 0, INS_FPU, 0, ADDRMETH_M|OPTYPE_fs|OP_W, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "fcomp", "", 0, 0, 0 , INS_SET_ZERO|INS_SET_PARITY|INS_SET_CARRY, 0 },
+ { 0, INS_FPU, 0, ADDRMETH_M|OPTYPE_fs|OP_W, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "fsub", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_M|OPTYPE_fs|OP_W, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "fsubr", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_M|OPTYPE_fs|OP_W, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "fdiv", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_M|OPTYPE_fs|OP_W, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "fdivr", "", 0, 0, 0 , 0 , 0 }
+};
+
+
+static ia32_insn_t tbl_D8C0[] = { /* FPU D8 C0 */
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fadd", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fadd", "", 0, 1, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fadd", "", 0, 2, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fadd", "", 0, 3, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fadd", "", 0, 4, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fadd", "", 0, 5, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fadd", "", 0, 6, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fadd", "", 0, 7, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fmul", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fmul", "", 0, 1, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fmul", "", 0, 2, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fmul", "", 0, 3, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fmul", "", 0, 4, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fmul", "", 0, 5, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fmul", "", 0, 6, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fmul", "", 0, 7, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fcom", "", 0, 0, 0 , INS_SET_ZERO|INS_SET_PARITY|INS_SET_CARRY, 17 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fcom", "", 0, 1, 0 , INS_SET_ZERO|INS_SET_PARITY|INS_SET_CARRY, 17 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fcom", "", 0, 2, 0 , INS_SET_ZERO|INS_SET_PARITY|INS_SET_CARRY, 17 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fcom", "", 0, 3, 0 , INS_SET_ZERO|INS_SET_PARITY|INS_SET_CARRY, 17 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fcom", "", 0, 4, 0 , INS_SET_ZERO|INS_SET_PARITY|INS_SET_CARRY, 17 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fcom", "", 0, 5, 0 , INS_SET_ZERO|INS_SET_PARITY|INS_SET_CARRY, 17 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fcom", "", 0, 6, 0 , INS_SET_ZERO|INS_SET_PARITY|INS_SET_CARRY, 17 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fcom", "", 0, 7, 0 , INS_SET_ZERO|INS_SET_PARITY|INS_SET_CARRY, 17 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fcomp", "", 0, 0, 0 , INS_SET_ZERO|INS_SET_PARITY|INS_SET_CARRY, 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fcomp", "", 0, 1, 0 , INS_SET_ZERO|INS_SET_PARITY|INS_SET_CARRY, 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fcomp", "", 0, 2, 0 , INS_SET_ZERO|INS_SET_PARITY|INS_SET_CARRY, 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fcomp", "", 0, 3, 0 , INS_SET_ZERO|INS_SET_PARITY|INS_SET_CARRY, 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fcomp", "", 0, 4, 0 , INS_SET_ZERO|INS_SET_PARITY|INS_SET_CARRY, 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fcomp", "", 0, 5, 0 , INS_SET_ZERO|INS_SET_PARITY|INS_SET_CARRY, 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fcomp", "", 0, 6, 0 , INS_SET_ZERO|INS_SET_PARITY|INS_SET_CARRY, 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fcomp", "", 0, 7, 0 , INS_SET_ZERO|INS_SET_PARITY|INS_SET_CARRY, 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fsub", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fsub", "", 0, 1, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fsub", "", 0, 2, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fsub", "", 0, 3, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fsub", "", 0, 4, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fsub", "", 0, 5, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fsub", "", 0, 6, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fsub", "", 0, 7, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fsubr", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fsubr", "", 0, 1, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fsubr", "", 0, 2, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fsubr", "", 0, 3, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fsubr", "", 0, 4, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fsubr", "", 0, 5, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fsubr", "", 0, 6, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fsubr", "", 0, 7, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fdiv", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fdiv", "", 0, 1, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fdiv", "", 0, 2, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fdiv", "", 0, 3, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fdiv", "", 0, 4, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fdiv", "", 0, 5, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fdiv", "", 0, 6, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fdiv", "", 0, 7, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fdivr", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fdivr", "", 0, 1, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fdivr", "", 0, 2, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fdivr", "", 0, 3, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fdivr", "", 0, 4, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fdivr", "", 0, 5, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fdivr", "", 0, 6, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fdivr", "", 0, 7, 0 , 0 , 0 }
+};
+
+
+static ia32_insn_t tbl_D9[] = { /* FPU D9 */
+ { 0, INS_FPU, 0, ADDRMETH_M|OPTYPE_fs|OP_W, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "fld", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_M|OPTYPE_fs|OP_W, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "fst", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_M|OPTYPE_fs|OP_W, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "fstp", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_M|OPTYPE_fv|OP_W, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "fldenv", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_M|OPTYPE_w|OP_W, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "fldcw", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_M|OPTYPE_fv|OP_W, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "fnstenv", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_M|OPTYPE_w|OP_W, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "fnstcw", "", 0, 0, 0 , 0 , 0 }
+};
+
+
+static ia32_insn_t tbl_D9C0[] = { /* FPU D9 C0 */
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fld", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fld", "", 0, 1, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fld", "", 0, 2, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fld", "", 0, 3, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fld", "", 0, 4, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fld", "", 0, 5, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fld", "", 0, 6, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fld", "", 0, 7, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fxch", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fxch", "", 0, 1, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fxch", "", 0, 2, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fxch", "", 0, 3, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fxch", "", 0, 4, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fxch", "", 0, 5, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fxch", "", 0, 6, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fxch", "", 0, 7, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "fnop", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "fchs", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "fabs", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "ftst", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "fxam", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "fld1", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "fldl2t", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "fldl2e", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "fldpi", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "fldlg2", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "fldln2", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "fldz", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "f2xm1", "", 0, 0, 0 , 0 , 16 },
+ { 0, INS_FPU, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "fyl2x", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "fptan", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "fpatan", "", 0, 0, 0 , 0 , 18 },
+ { 0, INS_FPU, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "fxtract", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "fprem1", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "fdecstp", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "fincstp", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "fprem", "", 0, 0, 0 , 0 , 19 },
+ { 0, INS_FPU, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "fyl2xp1", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "fsqrt", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "fsincos", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "frndint", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "fscale", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "fsin", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "fcos", "", 0, 0, 0 , 0 , 0 }
+};
+
+
+static ia32_insn_t tbl_DA[] = { /* FPU DA */
+ { 0, INS_FPU, 0, ADDRMETH_M|OPTYPE_d|OP_W, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "fiadd", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_M|OPTYPE_d|OP_W, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "fimul", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_M|OPTYPE_d|OP_W, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "ficom", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_M|OPTYPE_d|OP_W, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "ficomp", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_M|OPTYPE_d|OP_W, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "fisub", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_M|OPTYPE_d|OP_W, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "fisubr", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_M|OPTYPE_d|OP_W, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "fidiv", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_M|OPTYPE_d|OP_W, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "fidivr", "", 0, 0, 0 , 0 , 0 }
+};
+
+
+static ia32_insn_t tbl_DAC0[] = { /* FPU DA C0 */
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_PENTPRO | isa_GP, "fcmovb", "", 0, 0, 0 , INS_TEST_CARRY, 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_PENTPRO | isa_GP, "fcmovb", "", 0, 1, 0 , INS_TEST_CARRY, 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_PENTPRO | isa_GP, "fcmovb", "", 0, 2, 0 , INS_TEST_CARRY, 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_PENTPRO | isa_GP, "fcmovb", "", 0, 3, 0 , INS_TEST_CARRY, 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_PENTPRO | isa_GP, "fcmovb", "", 0, 4, 0 , INS_TEST_CARRY, 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_PENTPRO | isa_GP, "fcmovb", "", 0, 5, 0 , INS_TEST_CARRY, 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_PENTPRO | isa_GP, "fcmovb", "", 0, 6, 0 , INS_TEST_CARRY, 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_PENTPRO | isa_GP, "fcmovb", "", 0, 7, 0 , INS_TEST_CARRY, 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_PENTPRO | isa_GP, "fcmove", "", 0, 0, 0 , INS_TEST_ZERO, 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_PENTPRO | isa_GP, "fcmove", "", 0, 1, 0 , INS_TEST_ZERO, 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_PENTPRO | isa_GP, "fcmove", "", 0, 2, 0 , INS_TEST_ZERO, 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_PENTPRO | isa_GP, "fcmove", "", 0, 3, 0 , INS_TEST_ZERO, 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_PENTPRO | isa_GP, "fcmove", "", 0, 4, 0 , INS_TEST_ZERO, 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_PENTPRO | isa_GP, "fcmove", "", 0, 5, 0 , INS_TEST_ZERO, 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_PENTPRO | isa_GP, "fcmove", "", 0, 6, 0 , INS_TEST_ZERO, 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_PENTPRO | isa_GP, "fcmove", "", 0, 7, 0 , INS_TEST_ZERO, 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_PENTPRO | isa_GP, "fcmovbe", "", 0, 0, 0 , INS_TEST_CARRY|INS_TEST_OR|INS_TEST_ZERO, 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_PENTPRO | isa_GP, "fcmovbe", "", 0, 1, 0 , INS_TEST_CARRY|INS_TEST_OR|INS_TEST_ZERO, 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_PENTPRO | isa_GP, "fcmovbe", "", 0, 2, 0 , INS_TEST_CARRY|INS_TEST_OR|INS_TEST_ZERO, 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_PENTPRO | isa_GP, "fcmovbe", "", 0, 3, 0 , INS_TEST_CARRY|INS_TEST_OR|INS_TEST_ZERO, 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_PENTPRO | isa_GP, "fcmovbe", "", 0, 4, 0 , INS_TEST_CARRY|INS_TEST_OR|INS_TEST_ZERO, 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_PENTPRO | isa_GP, "fcmovbe", "", 0, 5, 0 , INS_TEST_CARRY|INS_TEST_OR|INS_TEST_ZERO, 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_PENTPRO | isa_GP, "fcmovbe", "", 0, 6, 0 , INS_TEST_CARRY|INS_TEST_OR|INS_TEST_ZERO, 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_PENTPRO | isa_GP, "fcmovbe", "", 0, 7, 0 , INS_TEST_CARRY|INS_TEST_OR|INS_TEST_ZERO, 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_PENTPRO | isa_GP, "fcmovu", "", 0, 0, 0 , INS_TEST_PARITY, 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_PENTPRO | isa_GP, "fcmovu", "", 0, 1, 0 , INS_TEST_PARITY, 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_PENTPRO | isa_GP, "fcmovu", "", 0, 2, 0 , INS_TEST_PARITY, 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_PENTPRO | isa_GP, "fcmovu", "", 0, 3, 0 , INS_TEST_PARITY, 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_PENTPRO | isa_GP, "fcmovu", "", 0, 4, 0 , INS_TEST_PARITY, 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_PENTPRO | isa_GP, "fcmovu", "", 0, 5, 0 , INS_TEST_PARITY, 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_PENTPRO | isa_GP, "fcmovu", "", 0, 6, 0 , INS_TEST_PARITY, 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_PENTPRO | isa_GP, "fcmovu", "", 0, 7, 0 , INS_TEST_PARITY, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "fucompp", "", 0, 0, 0 , 0 , 21 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 }
+};
+
+
+static ia32_insn_t tbl_DB[] = { /* FPU DB */
+ { 0, INS_FPU, 0, ADDRMETH_M|OPTYPE_d|OP_W, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "fild", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_M|OPTYPE_d|OP_W, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "fisttp", "", 0, 0, 0, 0, 0 },
+ { 0, INS_FPU, 0, ADDRMETH_M|OPTYPE_d|OP_W, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "fist", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_M|OPTYPE_d|OP_W, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "fistp", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_M|OPTYPE_fe|OP_W, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "fld", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_M|OPTYPE_fe|OP_W, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "fstp", "", 0, 0, 0 , 0 , 0 }
+};
+
+
+static ia32_insn_t tbl_DBC0[] = { /* FPU DB C0 */
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fcmovnb", "", 0, 0, 0 , INS_TEST_NCARRY, 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fcmovnb", "", 0, 1, 0 , INS_TEST_NCARRY, 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fcmovnb", "", 0, 2, 0 , INS_TEST_NCARRY, 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fcmovnb", "", 0, 3, 0 , INS_TEST_NCARRY, 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fcmovnb", "", 0, 4, 0 , INS_TEST_NCARRY, 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fcmovnb", "", 0, 5, 0 , INS_TEST_NCARRY, 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fcmovnb", "", 0, 6, 0 , INS_TEST_NCARRY, 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fcmovnb", "", 0, 7, 0 , INS_TEST_NCARRY, 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fcmovne", "", 0, 0, 0 , INS_TEST_NZERO, 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fcmovne", "", 0, 1, 0 , INS_TEST_NZERO, 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fcmovne", "", 0, 2, 0 , INS_TEST_NZERO, 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fcmovne", "", 0, 3, 0 , INS_TEST_NZERO, 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fcmovne", "", 0, 4, 0 , INS_TEST_NZERO, 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fcmovne", "", 0, 5, 0 , INS_TEST_NZERO, 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fcmovne", "", 0, 6, 0 , INS_TEST_NZERO, 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fcmovne", "", 0, 7, 0 , INS_TEST_NZERO, 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fcmovnbe", "", 0, 0, 0 , INS_TEST_NCARRY|INS_TEST_NZERO, 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fcmovnbe", "", 0, 1, 0 , INS_TEST_NCARRY|INS_TEST_NZERO, 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fcmovnbe", "", 0, 2, 0 , INS_TEST_NCARRY|INS_TEST_NZERO, 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fcmovnbe", "", 0, 3, 0 , INS_TEST_NCARRY|INS_TEST_NZERO, 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fcmovnbe", "", 0, 4, 0 , INS_TEST_NCARRY|INS_TEST_NZERO, 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fcmovnbe", "", 0, 5, 0 , INS_TEST_NCARRY|INS_TEST_NZERO, 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fcmovnbe", "", 0, 6, 0 , INS_TEST_NCARRY|INS_TEST_NZERO, 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fcmovnbe", "", 0, 7, 0 , INS_TEST_NCARRY|INS_TEST_NZERO, 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fcmovnu", "", 0, 0, 0 , INS_TEST_NPARITY, 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fcmovnu", "", 0, 1, 0 , INS_TEST_NPARITY, 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fcmovnu", "", 0, 2, 0 , INS_TEST_NPARITY, 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fcmovnu", "", 0, 3, 0 , INS_TEST_NPARITY, 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fcmovnu", "", 0, 4, 0 , INS_TEST_NPARITY, 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fcmovnu", "", 0, 5, 0 , INS_TEST_NPARITY, 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fcmovnu", "", 0, 6, 0 , INS_TEST_NPARITY, 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fcmovnu", "", 0, 7, 0 , INS_TEST_NPARITY, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "fnclex", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "fninit", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fucomi", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fucomi", "", 0, 1, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fucomi", "", 0, 2, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fucomi", "", 0, 3, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fucomi", "", 0, 4, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fucomi", "", 0, 5, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fucomi", "", 0, 6, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fucomi", "", 0, 7, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_PENTPRO | isa_GP, "fcomi", "", 0, 0, 0 , INS_SET_ZERO|INS_SET_PARITY|INS_SET_CARRY, 0, },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_PENTPRO | isa_GP, "fcomi", "", 0, 1, 0 , INS_SET_ZERO|INS_SET_PARITY|INS_SET_CARRY, 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_PENTPRO | isa_GP, "fcomi", "", 0, 2, 0 , INS_SET_ZERO|INS_SET_PARITY|INS_SET_CARRY, 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_PENTPRO | isa_GP, "fcomi", "", 0, 3, 0 , INS_SET_ZERO|INS_SET_PARITY|INS_SET_CARRY, 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_PENTPRO | isa_GP, "fcomi", "", 0, 4, 0 , INS_SET_ZERO|INS_SET_PARITY|INS_SET_CARRY, 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_PENTPRO | isa_GP, "fcomi", "", 0, 5, 0 , INS_SET_ZERO|INS_SET_PARITY|INS_SET_CARRY, 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_PENTPRO | isa_GP, "fcomi", "", 0, 6, 0 , INS_SET_ZERO|INS_SET_PARITY|INS_SET_CARRY, 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_PENTPRO | isa_GP, "fcomi", "", 0, 7, 0 , INS_SET_ZERO|INS_SET_PARITY|INS_SET_CARRY, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 }
+};
+
+
+static ia32_insn_t tbl_DC[] = { /* FPU DC */
+ { 0, INS_FPU, 0, ADDRMETH_M|OPTYPE_fd|OP_W, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "fadd", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_M|OPTYPE_fd|OP_W, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "fmul", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_M|OPTYPE_fd|OP_W, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "fcom", "", 0, 0, 0 , INS_SET_ZERO|INS_SET_PARITY|INS_SET_CARRY, 17 },
+ { 0, INS_FPU, 0, ADDRMETH_M|OPTYPE_fd|OP_W, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "fcomp", "", 0, 0, 0 , INS_SET_ZERO|INS_SET_PARITY|INS_SET_CARRY, 0 },
+ { 0, INS_FPU, 0, ADDRMETH_M|OPTYPE_fd|OP_W, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "fsub", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_M|OPTYPE_fd|OP_W, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "fsubr", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_M|OPTYPE_fd|OP_W, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "fdiv", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_M|OPTYPE_fd|OP_W, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "fdivr", "", 0, 0, 0, 0 , 0 }
+};
+
+
+static ia32_insn_t tbl_DCC0[] = { /* FPU DC C0 */
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fadd", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fadd", "", 1, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fadd", "", 2, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fadd", "", 3, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fadd", "", 4, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fadd", "", 5, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fadd", "", 6, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fadd", "", 7, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fmul", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fmul", "", 1, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fmul", "", 2, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fmul", "", 3, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fmul", "", 4, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fmul", "", 5, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fmul", "", 6, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fmul", "", 7, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fsubr", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fsubr", "", 1, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fsubr", "", 2, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fsubr", "", 3, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fsubr", "", 4, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fsubr", "", 5, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fsubr", "", 6, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fsubr", "", 7, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fsub", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fsub", "", 1, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fsub", "", 2, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fsub", "", 3, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fsub", "", 4, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fsub", "", 5, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fsub", "", 6, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fsub", "", 7, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fdivr", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fdivr", "", 1, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fdivr", "", 2, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fdivr", "", 3, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fdivr", "", 4, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fdivr", "", 5, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fdivr", "", 6, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fdivr", "", 7, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fdiv", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fdiv", "", 1, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fdiv", "", 2, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fdiv", "", 3, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fdiv", "", 4, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fdiv", "", 5, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fdiv", "", 6, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fdiv", "", 7, 0, 0 , 0 , 0 }
+};
+
+
+static ia32_insn_t tbl_DD[] = { /* FPU DD */
+ { 0, INS_FPU, 0, ADDRMETH_M|OPTYPE_fd|OP_W, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "fld", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_M|OPTYPE_q|OP_W, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "fisttp", "", 0, 0, 0, 0, 0 },
+ { 0, INS_FPU, 0, ADDRMETH_M|OPTYPE_fd|OP_W, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "fst", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_M|OPTYPE_fd|OP_W, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "fstp", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_M|OPTYPE_ft|OP_W, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "frstor", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_M|OPTYPE_ft|OP_W, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "fnsave", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_M|OPTYPE_w|OP_W, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "fnstsw", "", 0, 0, 0 , 0 , 0 }
+};
+
+
+static ia32_insn_t tbl_DDC0[] = { /* FPU DD C0 */
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "ffree", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "ffree", "", 1, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "ffree", "", 2, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "ffree", "", 3, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "ffree", "", 4, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "ffree", "", 5, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "ffree", "", 6, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "ffree", "", 7, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "fst", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "fst", "", 1, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "fst", "", 2, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "fst", "", 3, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "fst", "", 4, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "fst", "", 5, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "fst", "", 6, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "fst", "", 7, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "fstp", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "fstp", "", 1, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "fstp", "", 2, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "fstp", "", 3, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "fstp", "", 4, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "fstp", "", 5, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "fstp", "", 6, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "fstp", "", 7, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fucom", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fucom", "", 1, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fucom", "", 2, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fucom", "", 3, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fucom", "", 4, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fucom", "", 5, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fucom", "", 6, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fucom", "", 7, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fucomp", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fucomp", "", 1, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fucomp", "", 2, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fucomp", "", 3, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fucomp", "", 4, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fucomp", "", 5, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fucomp", "", 6, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fucomp", "", 7, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 }
+};
+
+
+static ia32_insn_t tbl_DE[] = { /* FPU DE */
+ { 0, INS_FPU, 0, ADDRMETH_M|OPTYPE_w|OP_W, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "fiadd", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_M|OPTYPE_w|OP_W, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "fimul", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_M|OPTYPE_w|OP_W, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "ficom", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_M|OPTYPE_w|OP_W, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "ficomp", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_M|OPTYPE_w|OP_W, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "fisub", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_M|OPTYPE_w|OP_W, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "fisubr", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_M|OPTYPE_w|OP_W, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "fidiv", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_M|OPTYPE_w|OP_W, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "fidivr", "", 0, 0, 0, 0 , 0 }
+};
+
+
+static ia32_insn_t tbl_DEC0[] = { /* FPU DE C0 */
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "faddp", "", 0, 0, 0 , 0 , 20 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "faddp", "", 1, 0, 0 , 0 , 20 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "faddp", "", 2, 0, 0 , 0 , 20 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "faddp", "", 3, 0, 0 , 0 , 20 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "faddp", "", 4, 0, 0 , 0 , 20 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "faddp", "", 5, 0, 0 , 0 , 20 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "faddp", "", 6, 0, 0 , 0 , 20 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "faddp", "", 7, 0, 0 , 0 , 20 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fmulp", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fmulp", "", 1, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fmulp", "", 2, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fmulp", "", 3, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fmulp", "", 4, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fmulp", "", 5, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fmulp", "", 6, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fmulp", "", 7, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "fcompp", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fsubrp", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fsubrp", "", 1, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fsubrp", "", 2, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fsubrp", "", 3, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fsubrp", "", 4, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fsubrp", "", 5, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fsubrp", "", 6, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fsubrp", "", 7, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fsubp", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fsubp", "", 1, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fsubp", "", 2, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fsubp", "", 3, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fsubp", "", 4, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fsubp", "", 5, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fsubp", "", 6, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fsubp", "", 7, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fdivrp", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fdivrp", "", 1, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fdivrp", "", 2, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fdivrp", "", 3, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fdivrp", "", 4, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fdivrp", "", 5, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fdivrp", "", 6, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fdivrp", "", 7, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fdivp", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fdivp", "", 1, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fdivp", "", 2, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fdivp", "", 3, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fdivp", "", 4, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fdivp", "", 5, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fdivp", "", 6, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fdivp", "", 7, 0, 0 , 0 , 0 }
+};
+
+
+static ia32_insn_t tbl_DF[] = { /* FPU DF */
+ { 0, INS_FPU, 0, ADDRMETH_M|OPTYPE_w|OP_W, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "fild", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_M|OPTYPE_w|OP_W, ARG_NONE, ARG_NONE, cpu_PENTIUM4 | isa_GP, "fisttp", "", 0, 0, 0, 0, 0 },
+ { 0, INS_FPU, 0, ADDRMETH_M|OPTYPE_w|OP_W, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "fist", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_M|OPTYPE_w|OP_W, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "fistp", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_M|OPTYPE_fb|OP_W, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "fbld", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_M|OPTYPE_q|OP_W, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "fild", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_M|OPTYPE_fb|OP_W, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "fbstp", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_M|OPTYPE_q|OP_W, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "fistp", "", 0, 0, 0 , 0 , 0 }
+};
+
+
+static ia32_insn_t tbl_DFC0[] = { /* FPU DF C0 */
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RR | OPTYPE_w | OP_R, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "fnstsw", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fucomip", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fucomip", "", 0, 1, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fucomip", "", 0, 2, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fucomip", "", 0, 3, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fucomip", "", 0, 4, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fucomip", "", 0, 5, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fucomip", "", 0, 6, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fucomip", "", 0, 7, 0 , 0 , 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fcomip", "", 0, 0, 0 , INS_SET_ZERO|INS_SET_PARITY|INS_SET_CARRY, 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fcomip", "", 0, 1, 0 , INS_SET_ZERO|INS_SET_PARITY|INS_SET_CARRY, 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fcomip", "", 0, 2, 0 , INS_SET_ZERO|INS_SET_PARITY|INS_SET_CARRY, 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fcomip", "", 0, 3, 0 , INS_SET_ZERO|INS_SET_PARITY|INS_SET_CARRY, 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fcomip", "", 0, 4, 0 , INS_SET_ZERO|INS_SET_PARITY|INS_SET_CARRY, 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fcomip", "", 0, 5, 0 , INS_SET_ZERO|INS_SET_PARITY|INS_SET_CARRY, 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fcomip", "", 0, 6, 0 , INS_SET_ZERO|INS_SET_PARITY|INS_SET_CARRY, 0 },
+ { 0, INS_FPU, 0, ADDRMETH_RF | OPTYPE_fp | OP_W, ADDRMETH_RF | OPTYPE_fp | OP_R, ARG_NONE, cpu_80387 | isa_FPU, "fcomip", "", 0, 7, 0 , INS_SET_ZERO|INS_SET_PARITY|INS_SET_CARRY, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_80387 | isa_FPU, "", "", 0, 0, 0 , 0 , 0 }
+};
+
+
+static ia32_insn_t tbl_0F0F[] = { /* 3D Now! 0F Suffix */
+ /* 00 */ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_CONV, 0, ADDRMETH_P | OPTYPE_pi | OP_R | OP_W, ADDRMETH_Q | OPTYPE_q |OP_R, ARG_NONE, cpu_K6 | isa_3DNOW, "pi2fd", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ /* 10 */ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_CONV, 0, ADDRMETH_P | OPTYPE_pi | OP_R | OP_W, ADDRMETH_Q | OPTYPE_q |OP_R, ARG_NONE, cpu_K6 | isa_3DNOW, "pf2id", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ /* 20 */ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ /* 30 */ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ /* 40 */ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ /* 50 */ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ /* 60 */ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ /* 70 */ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ /* 80 */ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_CMP, 0, ADDRMETH_P | OPTYPE_pi | OP_R | OP_W, ADDRMETH_Q | OPTYPE_q |OP_R, ARG_NONE, cpu_K6 | isa_3DNOW, "pfcmpge", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_MIN, 0, ADDRMETH_P | OPTYPE_pi | OP_R | OP_W, ADDRMETH_Q | OPTYPE_q |OP_R, ARG_NONE, cpu_K6 | isa_3DNOW, "pfmin", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_ARITH, 0, ADDRMETH_P | OPTYPE_pi | OP_R | OP_W, ADDRMETH_Q | OPTYPE_q |OP_R, ARG_NONE, cpu_K6 | isa_3DNOW, "pfrcp", "", 0, 0, 0, 0, 0 },
+ { 0, INS_ARITH, 0, ADDRMETH_P | OPTYPE_pi | OP_R | OP_W, ADDRMETH_Q | OPTYPE_q |OP_R, ARG_NONE, cpu_K6 | isa_3DNOW, "pfrsqrt", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_SUB, 0, ADDRMETH_P | OPTYPE_pi | OP_R | OP_W, ADDRMETH_Q | OPTYPE_q |OP_R, ARG_NONE, cpu_K6 | isa_3DNOW, "pfsub", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_ADD, 0, ADDRMETH_P | OPTYPE_pi | OP_R | OP_W, ADDRMETH_Q | OPTYPE_q |OP_R, ARG_NONE, cpu_K6 | isa_3DNOW, "pfadd", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_CMP, 0, ADDRMETH_P | OPTYPE_pi | OP_R | OP_W, ADDRMETH_Q | OPTYPE_q |OP_R, ARG_NONE, cpu_K6 | isa_3DNOW, "pfcmpgt", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_MAX, 0, ADDRMETH_P | OPTYPE_pi | OP_R | OP_W, ADDRMETH_Q | OPTYPE_q |OP_R, ARG_NONE, cpu_K6 | isa_3DNOW, "pfmax", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_ARITH, 0, ADDRMETH_P | OPTYPE_pi | OP_R | OP_W, ADDRMETH_Q | OPTYPE_q |OP_R, ARG_NONE, cpu_K6 | isa_3DNOW, "pfrcpit1", "", 0, 0, 0, 0, 0 },
+ { 0, INS_ARITH, 0, ADDRMETH_P | OPTYPE_pi | OP_R | OP_W, ADDRMETH_Q | OPTYPE_q |OP_R, ARG_NONE, cpu_K6 | isa_3DNOW, "pfrsqit1", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_SUB, 0, ADDRMETH_P | OPTYPE_pi | OP_R | OP_W, ADDRMETH_Q | OPTYPE_q |OP_R, ARG_NONE, cpu_K6 | isa_3DNOW, "pfsubr", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_ADD, 0, ADDRMETH_P | OPTYPE_pi | OP_R | OP_W, ADDRMETH_Q | OPTYPE_q |OP_R, ARG_NONE, cpu_K6 | isa_3DNOW, "pfacc", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_CMP, 0, ADDRMETH_P | OPTYPE_pi | OP_R | OP_W, ADDRMETH_Q | OPTYPE_q |OP_R, ARG_NONE, cpu_K6 | isa_3DNOW, "pfcmpeq", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_MUL, 0, ADDRMETH_P | OPTYPE_pi | OP_R | OP_W, ADDRMETH_Q | OPTYPE_q |OP_R, ARG_NONE, cpu_K6 | isa_3DNOW, "pfmul", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_ARITH, 0, ADDRMETH_P | OPTYPE_pi | OP_R | OP_W, ADDRMETH_Q | OPTYPE_q |OP_R, ARG_NONE, cpu_K6 | isa_3DNOW, "pfrcpit2", "", 0, 0, 0, 0, 0 },
+ { 0, INS_MUL, 0, ADDRMETH_P | OPTYPE_pi | OP_R | OP_W, ADDRMETH_Q | OPTYPE_q |OP_R, ARG_NONE, cpu_K6 | isa_3DNOW, "pmulhrw", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_INVALID, 0, ARG_NONE, ARG_NONE, ARG_NONE, cpu_K6 | isa_3DNOW, "", "", 0, 0, 0, 0, 0 },
+ { 0, INS_AVG, 0, ADDRMETH_P | OPTYPE_pi | OP_R | OP_W, ADDRMETH_Q | OPTYPE_q |OP_R, ARG_NONE, cpu_K6 | isa_3DNOW, "pavgusb", "", 0, 0, 0, 0, 0 }
+};
+
+
+
+/* ================== Table of Opcode Tables ================== */
+ia32_table_desc_t ia32_tables[] = {
+ /* table, prefix table, type, shift, mask, min, max */
+ { tbl_Main, tbl_opcode, 0x00, 0xFF, 0x00, 0xFF },
+ { tbl_66, tbl_prefix, 0x00, 0xFF, 0x0F, 0x0F },
+ { tbl_F2, tbl_prefix, 0x00, 0xFF, 0x0F, 0x0F },
+ { tbl_F3, tbl_prefix, 0x00, 0xFF, 0x0F, 0x90 },
+ { tbl_0F, tbl_opcode, 0x00, 0xFF, 0x00, 0xFF },
+ /* 5 */
+ { tbl_660F, tbl_prefix, 0x00, 0xFF, 0x10, 0xFF },
+ { tbl_F20F, tbl_prefix, 0x00, 0xFF, 0x10, 0xFF },
+ { tbl_F30F, tbl_prefix, 0x00, 0xFF, 0x10, 0xFF },
+ { tbl_0F00, tbl_extension, 0x03, 0x07, 0x00, 0x07 },
+ { tbl_0F01, tbl_extension, 0x03, 0x1F, 0x00, 0x1F },
+ /* 10 */
+ { tbl_0F0111, tbl_ext_ext, 0x00, 0x01, 0x00, 0x01 },
+ { tbl_0F12, tbl_extension, 0x06, 0x03, 0x00, 0x03 },
+ { tbl_0F16, tbl_extension, 0x06, 0x03, 0x00, 0x03 },
+ { tbl_0F18, tbl_extension, 0x03, 0x1F, 0x00, 0x13 },
+ { tbl_0F71, tbl_extension, 0x03, 0x1F, 0x00, 0x1F },
+ /* 15 */
+ { tbl_660F71, tbl_extension, 0x03, 0x1F, 0x00, 0x1F },
+ { tbl_0F72, tbl_extension, 0x03, 0x1F, 0x00, 0x1F },
+ { tbl_660F72, tbl_extension, 0x03, 0x1F, 0x00, 0x1F },
+ { tbl_0F73, tbl_extension, 0x00, 0x00, 0x00, 0x00 },
+ { tbl_660F73, tbl_extension, 0x03, 0x1F, 0x00, 0x1F },
+ /* 20 */
+ { tbl_0FAE, tbl_extension, 0x03, 0x1F, 0x00, 0x1F },
+ { tbl_0FBA, tbl_extension, 0x03, 0x07, 0x04, 0x07 },
+ { tbl_0FC7, tbl_extension, 0x03, 0x1F, 0x00, 0x11 },
+ { tbl_0FB9, tbl_extension, 0x03, 0x07, 0x00, 0x00 },
+ { tbl_C6, tbl_extension, 0x03, 0x07, 0x00, 0x00 },
+ /* 25 */
+ { tbl_C7, tbl_extension, 0x03, 0x07, 0x00, 0x00 },
+ { tbl_80, tbl_extension, 0x03, 0x07, 0x00, 0x07 },
+ { tbl_81, tbl_extension, 0x03, 0x07, 0x00, 0x07 },
+ { tbl_82, tbl_extension, 0x03, 0x07, 0x00, 0x07 },
+ { tbl_83, tbl_extension, 0x03, 0x07, 0x00, 0x07 },
+ /* 30 */
+ { tbl_C0, tbl_extension, 0x03, 0x07, 0x00, 0x07 },
+ { tbl_C1, tbl_extension, 0x03, 0x07, 0x00, 0x07 },
+ { tbl_D0, tbl_extension, 0x03, 0x07, 0x00, 0x07 },
+ { tbl_D1, tbl_extension, 0x03, 0x07, 0x00, 0x07 },
+ { tbl_D2, tbl_extension, 0x03, 0x07, 0x00, 0x07 },
+ /* 35 */
+ { tbl_D3, tbl_extension, 0x03, 0x07, 0x00, 0x07 },
+ { tbl_F6, tbl_extension, 0x03, 0x07, 0x00, 0x07 },
+ { tbl_F7, tbl_extension, 0x03, 0x07, 0x00, 0x07 },
+ { tbl_FE, tbl_extension, 0x03, 0x07, 0x00, 0x01 },
+ { tbl_FF, tbl_extension, 0x03, 0x07, 0x00, 0x06 },
+ /* 40 */
+ { tbl_D8, tbl_fpu, 0x03, 0x07, 0x00, 0xBF },
+ { tbl_D8C0, tbl_fpu_ext, 0x00, 0xFF, 0xC0, 0xFF },
+ { tbl_D9, tbl_fpu, 0x03, 0x07, 0x00, 0xBF },
+ { tbl_D9C0, tbl_fpu_ext, 0x00, 0xFF, 0xC0, 0xFF },
+ { tbl_DA, tbl_fpu, 0x03, 0x07, 0x00, 0xBF },
+ /* 45 */
+ { tbl_DAC0, tbl_fpu_ext, 0x00, 0xFF, 0xC0, 0xFF },
+ { tbl_DB, tbl_fpu, 0x03, 0x07, 0x00, 0xBF },
+ { tbl_DBC0, tbl_fpu_ext, 0x00, 0xFF, 0xC0, 0xFF },
+ { tbl_DC, tbl_fpu, 0x03, 0x07, 0x00, 0xBF },
+ { tbl_DCC0, tbl_fpu_ext, 0x00, 0xFF, 0xC0, 0xFF },
+ /* 50 */
+ { tbl_DD, tbl_fpu, 0x03, 0x07, 0x00, 0xBF },
+ { tbl_DDC0, tbl_fpu_ext, 0x00, 0xFF, 0xC0, 0xFF },
+ { tbl_DE, tbl_fpu, 0x03, 0x07, 0x00, 0xBF },
+ { tbl_DEC0, tbl_fpu_ext, 0x00, 0xFF, 0xC0, 0xFF },
+ { tbl_DF, tbl_fpu, 0x03, 0x07, 0x00, 0xBF },
+ /* 55 */
+ { tbl_DFC0, tbl_fpu_ext, 0x00, 0xFF, 0xC0, 0xFF },
+ { tbl_0F0F, tbl_suffix, 0x00, 0xFF, 0x00, 0xBF }
+};
+/* ia32_opcode_tables.h */
+/* Table index constants:
+#define idx_Main 0
+#define idx_66 1
+#define idx_F2 2
+#define idx_F3 3
+#define idx_0F 4
+#define idx_660F 5
+#define idx_F20F 6
+#define idx_F30F 7
+#define idx_0F00 8
+#define idx_0F01 9
+#define idx_0F0111 10
+#define idx_0F12 11
+#define idx_0F16 12
+#define idx_0F18 13
+#define idx_0F71 14
+#define idx_660F71 15
+#define idx_0F72 16
+#define idx_660F72 17
+#define idx_0F73 18
+#define idx_660F73 19
+#define idx_0FAE 20
+#define idx_0FBA 21
+#define idx_0FC7 22
+#define idx_0FB9 23
+#define idx_C6 24
+#define idx_C7 25
+#define idx_80 26
+#define idx_81 27
+#define idx_82 28
+#define idx_83 29
+#define idx_C0 30
+#define idx_C1 31
+#define idx_D0 32
+#define idx_D1 33
+#define idx_D2 34
+#define idx_D3 35
+#define idx_F6 36
+#define idx_F7 37
+#define idx_FE 38
+#define idx_FF 39
+#define idx_D8 40
+#define idx_D8C0 41
+#define idx_D9 42
+#define idx_D9C0 43
+#define idx_DA 44
+#define idx_DAC0 45
+#define idx_DB 46
+#define idx_DBC0 47
+#define idx_DC 48
+#define idx_DCC0 49
+#define idx_DD 50
+#define idx_DDC0 51
+#define idx_DE 52
+#define idx_DEC0 53
+#define idx_DF 54
+#define idx_DFC0 55
+#define idx_0F0F 56
+*/
diff --git a/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/ia32_opcode_tables.h b/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/ia32_opcode_tables.h
new file mode 100644
index 0000000000..bbd4fae9ab
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/ia32_opcode_tables.h
@@ -0,0 +1,57 @@
+#define idx_Main 0
+#define idx_66 1
+#define idx_F2 2
+#define idx_F3 3
+#define idx_0F 4
+#define idx_660F 5
+#define idx_F20F 6
+#define idx_F30F 7
+#define idx_0F00 8
+#define idx_0F01 9
+#define idx_0F0111 10
+#define idx_0F12 11
+#define idx_0F16 12
+#define idx_0F18 13
+#define idx_0F71 14
+#define idx_660F71 15
+#define idx_0F72 16
+#define idx_660F72 17
+#define idx_0F73 18
+#define idx_660F73 19
+#define idx_0FAE 20
+#define idx_0FBA 21
+#define idx_0FC7 22
+#define idx_0FB9 23
+#define idx_C6 24
+#define idx_C7 25
+#define idx_80 26
+#define idx_81 27
+#define idx_82 28
+#define idx_83 29
+#define idx_C0 30
+#define idx_C1 31
+#define idx_D0 32
+#define idx_D1 33
+#define idx_D2 34
+#define idx_D3 35
+#define idx_F6 36
+#define idx_F7 37
+#define idx_FE 38
+#define idx_FF 39
+#define idx_D8 40
+#define idx_D8C0 41
+#define idx_D9 42
+#define idx_D9C0 43
+#define idx_DA 44
+#define idx_DAC0 45
+#define idx_DB 46
+#define idx_DBC0 47
+#define idx_DC 48
+#define idx_DCC0 49
+#define idx_DD 50
+#define idx_DDC0 51
+#define idx_DE 52
+#define idx_DEC0 53
+#define idx_DF 54
+#define idx_DFC0 55
+#define idx_0F0F 56
diff --git a/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/ia32_operand.c b/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/ia32_operand.c
new file mode 100644
index 0000000000..8e7f16a0c0
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/ia32_operand.c
@@ -0,0 +1,425 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "libdis.h"
+#include "ia32_insn.h"
+#include "ia32_operand.h"
+#include "ia32_modrm.h"
+#include "ia32_reg.h"
+#include "x86_imm.h"
+#include "x86_operand_list.h"
+
+
+
+/* apply segment override to memory operand in insn */
+static void apply_seg( x86_op_t *op, unsigned int prefixes ) {
+ if (! prefixes ) return;
+
+ /* apply overrides from prefix */
+ switch ( prefixes & PREFIX_REG_MASK ) {
+ case PREFIX_CS:
+ op->flags |= op_cs_seg; break;
+ case PREFIX_SS:
+ op->flags |= op_ss_seg; break;
+ case PREFIX_DS:
+ op->flags |= op_ds_seg; break;
+ case PREFIX_ES:
+ op->flags |= op_es_seg; break;
+ case PREFIX_FS:
+ op->flags |= op_fs_seg; break;
+ case PREFIX_GS:
+ op->flags |= op_gs_seg; break;
+ }
+
+ return;
+}
+
+static size_t decode_operand_value( unsigned char *buf, size_t buf_len,
+ x86_op_t *op, x86_insn_t *insn,
+ unsigned int addr_meth, size_t op_size,
+ unsigned int op_value, unsigned char modrm,
+ size_t gen_regs ) {
+ size_t size = 0;
+
+ /* ++ Do Operand Addressing Method / Decode operand ++ */
+ switch (addr_meth) {
+ /* This sets the operand Size based on the Intel Opcode Map
+ * (Vol 2, Appendix A). Letter encodings are from section
+ * A.1.1, 'Codes for Addressing Method' */
+
+ /* ---------------------- Addressing Method -------------- */
+ /* Note that decoding mod ModR/M operand adjusts the size of
+ * the instruction, but decoding the reg operand does not.
+ * This should not cause any problems, as every 'reg' operand
+ * has an associated 'mod' operand.
+ * Goddamn-Intel-Note:
+ * Some Intel addressing methods [M, R] specify that modR/M
+ * byte may only refer to a memory address/may only refer to
+ * a register -- however Intel provides no clues on what to do
+ * if, say, the modR/M for an M opcode decodes to a register
+ * rather than a memory address ... returning 0 is out of the
+ * question, as this would be an Immediate or a RelOffset, so
+ * instead these modR/Ms are decoded with total disregard to
+ * the M, R constraints. */
+
+ /* MODRM -- mod operand. sets size to at least 1! */
+ case ADDRMETH_E: /* ModR/M present, Gen reg or memory */
+ size = ia32_modrm_decode( buf, buf_len, op, insn,
+ gen_regs );
+ break;
+ case ADDRMETH_M: /* ModR/M only refers to memory */
+ size = ia32_modrm_decode( buf, buf_len, op, insn,
+ gen_regs );
+ break;
+ case ADDRMETH_Q: /* ModR/M present, MMX or Memory */
+ size = ia32_modrm_decode( buf, buf_len, op, insn,
+ REG_MMX_OFFSET );
+ break;
+ case ADDRMETH_R: /* ModR/M mod == gen reg */
+ size = ia32_modrm_decode( buf, buf_len, op, insn,
+ gen_regs );
+ break;
+ case ADDRMETH_W: /* ModR/M present, mem or SIMD reg */
+ size = ia32_modrm_decode( buf, buf_len, op, insn,
+ REG_SIMD_OFFSET );
+ break;
+
+ /* MODRM -- reg operand. does not effect size! */
+ case ADDRMETH_C: /* ModR/M reg == control reg */
+ ia32_reg_decode( modrm, op, REG_CTRL_OFFSET );
+ break;
+ case ADDRMETH_D: /* ModR/M reg == debug reg */
+ ia32_reg_decode( modrm, op, REG_DEBUG_OFFSET );
+ break;
+ case ADDRMETH_G: /* ModR/M reg == gen-purpose reg */
+ ia32_reg_decode( modrm, op, gen_regs );
+ break;
+ case ADDRMETH_P: /* ModR/M reg == qword MMX reg */
+ ia32_reg_decode( modrm, op, REG_MMX_OFFSET );
+ break;
+ case ADDRMETH_S: /* ModR/M reg == segment reg */
+ ia32_reg_decode( modrm, op, REG_SEG_OFFSET );
+ break;
+ case ADDRMETH_T: /* ModR/M reg == test reg */
+ ia32_reg_decode( modrm, op, REG_TEST_OFFSET );
+ break;
+ case ADDRMETH_V: /* ModR/M reg == SIMD reg */
+ ia32_reg_decode( modrm, op, REG_SIMD_OFFSET );
+ break;
+
+ /* No MODRM : note these set operand type explicitly */
+ case ADDRMETH_A: /* No modR/M -- direct addr */
+ op->type = op_absolute;
+
+ /* segment:offset address used in far calls */
+ x86_imm_sized( buf, buf_len,
+ &op->data.absolute.segment, 2 );
+ if ( insn->addr_size == 4 ) {
+ x86_imm_sized( buf, buf_len,
+ &op->data.absolute.offset.off32, 4 );
+ size = 6;
+ } else {
+ x86_imm_sized( buf, buf_len,
+ &op->data.absolute.offset.off16, 2 );
+ size = 4;
+ }
+
+ break;
+ case ADDRMETH_I: /* Immediate val */
+ op->type = op_immediate;
+ /* if it ever becomes legal to have imm as dest and
+ * there is a src ModR/M operand, we are screwed! */
+ if ( op->flags & op_signed ) {
+ x86_imm_signsized(buf, buf_len, &op->data.byte,
+ op_size);
+ } else {
+ x86_imm_sized(buf, buf_len, &op->data.byte,
+ op_size);
+ }
+ size = op_size;
+ break;
+ case ADDRMETH_J: /* Rel offset to add to IP [jmp] */
+ /* this fills op->data.near_offset or
+ op->data.far_offset depending on the size of
+ the operand */
+ op->flags |= op_signed;
+ if ( op_size == 1 ) {
+ /* one-byte near offset */
+ op->type = op_relative_near;
+ x86_imm_signsized(buf, buf_len,
+ &op->data.relative_near, 1);
+ } else {
+ /* far offset...is this truly signed? */
+ op->type = op_relative_far;
+ x86_imm_signsized(buf, buf_len,
+ &op->data.relative_far, op_size );
+ }
+ size = op_size;
+ break;
+ case ADDRMETH_O: /* No ModR/M; op is word/dword offset */
+ /* NOTE: these are actually RVAs not offsets to seg!! */
+ /* note bene: 'O' ADDR_METH uses addr_size to
+ determine operand size */
+ op->type = op_offset;
+ op->flags |= op_pointer;
+ x86_imm_sized( buf, buf_len, &op->data.offset,
+ insn->addr_size );
+
+ size = insn->addr_size;
+ break;
+
+ /* Hard-coded: these are specified in the insn definition */
+ case ADDRMETH_F: /* EFLAGS register */
+ op->type = op_register;
+ op->flags |= op_hardcode;
+ ia32_handle_register( &op->data.reg, REG_FLAGS_INDEX );
+ break;
+ case ADDRMETH_X: /* Memory addressed by DS:SI [string] */
+ op->type = op_expression;
+ op->flags |= op_hardcode;
+ op->flags |= op_ds_seg | op_pointer | op_string;
+ ia32_handle_register( &op->data.expression.base,
+ REG_DWORD_OFFSET + 6 );
+ break;
+ case ADDRMETH_Y: /* Memory addressed by ES:DI [string] */
+ op->type = op_expression;
+ op->flags |= op_hardcode;
+ op->flags |= op_es_seg | op_pointer | op_string;
+ ia32_handle_register( &op->data.expression.base,
+ REG_DWORD_OFFSET + 7 );
+ break;
+ case ADDRMETH_RR: /* Gen Register hard-coded in opcode */
+ op->type = op_register;
+ op->flags |= op_hardcode;
+ ia32_handle_register( &op->data.reg,
+ op_value + gen_regs );
+ break;
+ case ADDRMETH_RS: /* Seg Register hard-coded in opcode */
+ op->type = op_register;
+ op->flags |= op_hardcode;
+ ia32_handle_register( &op->data.reg,
+ op_value + REG_SEG_OFFSET );
+ break;
+ case ADDRMETH_RF: /* FPU Register hard-coded in opcode */
+ op->type = op_register;
+ op->flags |= op_hardcode;
+ ia32_handle_register( &op->data.reg,
+ op_value + REG_FPU_OFFSET );
+ break;
+ case ADDRMETH_RT: /* TST Register hard-coded in opcode */
+ op->type = op_register;
+ op->flags |= op_hardcode;
+ ia32_handle_register( &op->data.reg,
+ op_value + REG_TEST_OFFSET );
+ break;
+ case ADDRMETH_II: /* Immediate hard-coded in opcode */
+ op->type = op_immediate;
+ op->data.dword = op_value;
+ op->flags |= op_hardcode;
+ break;
+
+ case 0: /* Operand is not used */
+ default:
+ /* ignore -- operand not used in this insn */
+ op->type = op_unused; /* this shouldn't happen! */
+ break;
+ }
+
+ return size;
+}
+
+static size_t decode_operand_size( unsigned int op_type, x86_insn_t *insn,
+ x86_op_t *op ){
+ size_t size;
+
+ /* ++ Do Operand Type ++ */
+ switch (op_type) {
+ /* This sets the operand Size based on the Intel Opcode Map
+ * (Vol 2, Appendix A). Letter encodings are from section
+ * A.1.2, 'Codes for Operand Type' */
+ /* NOTE: in this routines, 'size' refers to the size
+ * of the operand in the raw (encoded) instruction;
+ * 'datatype' stores the actual size and datatype
+ * of the operand */
+
+ /* ------------------------ Operand Type ----------------- */
+ case OPTYPE_c: /* byte or word [op size attr] */
+ size = (insn->op_size == 4) ? 2 : 1;
+ op->datatype = (size == 4) ? op_word : op_byte;
+ break;
+ case OPTYPE_a: /* 2 word or 2 dword [op size attr] */
+ /* pointer to a 16:16 or 32:32 BOUNDS operand */
+ size = (insn->op_size == 4) ? 8 : 4;
+ op->datatype = (size == 4) ? op_bounds32 : op_bounds16;
+ break;
+ case OPTYPE_v: /* word or dword [op size attr] */
+ size = (insn->op_size == 4) ? 4 : 2;
+ op->datatype = (size == 4) ? op_dword : op_word;
+ break;
+ case OPTYPE_p: /* 32/48-bit ptr [op size attr] */
+ /* technically these flags are not accurate: the
+ * value s a 16:16 pointer or a 16:32 pointer, where
+ * the first '16' is a segment */
+ size = (insn->addr_size == 4) ? 6 : 4;
+ op->datatype = (size == 4) ? op_descr32 : op_descr16;
+ break;
+ case OPTYPE_b: /* byte, ignore op-size */
+ size = 1;
+ op->datatype = op_byte;
+ break;
+ case OPTYPE_w: /* word, ignore op-size */
+ size = 2;
+ op->datatype = op_word;
+ break;
+ case OPTYPE_d: /* dword , ignore op-size */
+ size = 4;
+ op->datatype = op_dword;
+ break;
+ case OPTYPE_s: /* 6-byte psuedo-descriptor */
+ /* ptr to 6-byte value which is 32:16 in 32-bit
+ * mode, or 8:24:16 in 16-bit mode. The high byte
+ * is ignored in 16-bit mode. */
+ size = 6;
+ op->datatype = (insn->addr_size == 4) ?
+ op_pdescr32 : op_pdescr16;
+ break;
+ case OPTYPE_q: /* qword, ignore op-size */
+ size = 8;
+ op->datatype = op_qword;
+ break;
+ case OPTYPE_dq: /* d-qword, ignore op-size */
+ size = 16;
+ op->datatype = op_dqword;
+ break;
+ case OPTYPE_ps: /* 128-bit FP data */
+ size = 16;
+ /* really this is 4 packed SP FP values */
+ op->datatype = op_ssimd;
+ break;
+ case OPTYPE_pd: /* 128-bit FP data */
+ size = 16;
+ /* really this is 2 packed DP FP values */
+ op->datatype = op_dsimd;
+ break;
+ case OPTYPE_ss: /* Scalar elem of 128-bit FP data */
+ size = 16;
+ /* this only looks at the low dword (4 bytes)
+ * of the xmmm register passed as a param.
+ * This is a 16-byte register where only 4 bytes
+ * are used in the insn. Painful, ain't it? */
+ op->datatype = op_sssimd;
+ break;
+ case OPTYPE_sd: /* Scalar elem of 128-bit FP data */
+ size = 16;
+ /* this only looks at the low qword (8 bytes)
+ * of the xmmm register passed as a param.
+ * This is a 16-byte register where only 8 bytes
+ * are used in the insn. Painful, again... */
+ op->datatype = op_sdsimd;
+ break;
+ case OPTYPE_pi: /* qword mmx register */
+ size = 8;
+ op->datatype = op_qword;
+ break;
+ case OPTYPE_si: /* dword integer register */
+ size = 4;
+ op->datatype = op_dword;
+ break;
+ case OPTYPE_fs: /* single-real */
+ size = 4;
+ op->datatype = op_sreal;
+ break;
+ case OPTYPE_fd: /* double real */
+ size = 8;
+ op->datatype = op_dreal;
+ break;
+ case OPTYPE_fe: /* extended real */
+ size = 10;
+ op->datatype = op_extreal;
+ break;
+ case OPTYPE_fb: /* packed BCD */
+ size = 10;
+ op->datatype = op_bcd;
+ break;
+ case OPTYPE_fv: /* pointer to FPU env: 14 or 28-bytes */
+ size = (insn->addr_size == 4)? 28 : 14;
+ op->datatype = (size == 28)? op_fpuenv32: op_fpuenv16;
+ break;
+ case OPTYPE_ft: /* pointer to FPU env: 94 or 108 bytes */
+ size = (insn->addr_size == 4)? 108 : 94;
+ op->datatype = (size == 108)?
+ op_fpustate32: op_fpustate16;
+ break;
+ case OPTYPE_fx: /* 512-byte register stack */
+ size = 512;
+ op->datatype = op_fpregset;
+ break;
+ case OPTYPE_fp: /* floating point register */
+ size = 10; /* double extended precision */
+ op->datatype = op_fpreg;
+ break;
+ case OPTYPE_m: /* fake operand type used for "lea Gv, M" */
+ size = insn->addr_size;
+ op->datatype = (size == 4) ? op_dword : op_word;
+ break;
+ case OPTYPE_none: /* handle weird instructions that have no encoding but use a dword datatype, like invlpg */
+ size = 0;
+ op->datatype = op_none;
+ break;
+ case 0:
+ default:
+ size = insn->op_size;
+ op->datatype = (size == 4) ? op_dword : op_word;
+ break;
+ }
+ return size;
+}
+
+size_t ia32_decode_operand( unsigned char *buf, size_t buf_len,
+ x86_insn_t *insn, unsigned int raw_op,
+ unsigned int raw_flags, unsigned int prefixes,
+ unsigned char modrm ) {
+ unsigned int addr_meth, op_type, op_size, gen_regs;
+ x86_op_t *op;
+ size_t size;
+
+ /* ++ Yank optype and addr mode out of operand flags */
+ addr_meth = raw_flags & ADDRMETH_MASK;
+ op_type = raw_flags & OPTYPE_MASK;
+
+ if ( raw_flags == ARG_NONE ) {
+ /* operand is not used in this instruction */
+ return 0;
+ }
+
+ /* allocate a new operand */
+ op = x86_operand_new( insn );
+
+ /* ++ Copy flags from opcode table to x86_insn_t */
+ op->access = (enum x86_op_access) OP_PERM(raw_flags);
+ op->flags = (enum x86_op_flags) (OP_FLAGS(raw_flags) >> 12);
+
+ /* Get size (for decoding) and datatype of operand */
+ op_size = decode_operand_size(op_type, insn, op);
+
+ /* override default register set based on Operand Type */
+ /* this allows mixing of 8, 16, and 32 bit regs in insn */
+ if (op_size == 1) {
+ gen_regs = REG_BYTE_OFFSET;
+ } else if (op_size == 2) {
+ gen_regs = REG_WORD_OFFSET;
+ } else {
+ gen_regs = REG_DWORD_OFFSET;
+ }
+
+ size = decode_operand_value( buf, buf_len, op, insn, addr_meth,
+ op_size, raw_op, modrm, gen_regs );
+
+ /* if operand is an address, apply any segment override prefixes */
+ if ( op->type == op_expression || op->type == op_offset ) {
+ apply_seg(op, prefixes);
+ }
+
+ return size; /* return number of bytes in instruction */
+}
diff --git a/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/ia32_operand.h b/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/ia32_operand.h
new file mode 100644
index 0000000000..08c3074cd7
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/ia32_operand.h
@@ -0,0 +1,11 @@
+#ifndef IA32_OPERAND_H
+#define IA32_OPERAND_H
+
+#include "libdis.h"
+#include "ia32_insn.h"
+
+size_t ia32_decode_operand( unsigned char *buf, size_t buf_len,
+ x86_insn_t *insn, unsigned int raw_op,
+ unsigned int raw_flags, unsigned int prefixes,
+ unsigned char modrm );
+#endif
diff --git a/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/ia32_reg.c b/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/ia32_reg.c
new file mode 100644
index 0000000000..f270c1f346
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/ia32_reg.c
@@ -0,0 +1,234 @@
+#include <stdlib.h>
+#include <string.h>
+
+#include "ia32_reg.h"
+#include "ia32_insn.h"
+
+#define NUM_X86_REGS 92
+
+/* register sizes */
+#define REG_DWORD_SIZE 4
+#define REG_WORD_SIZE 2
+#define REG_BYTE_SIZE 1
+#define REG_MMX_SIZE 8
+#define REG_SIMD_SIZE 16
+#define REG_DEBUG_SIZE 4
+#define REG_CTRL_SIZE 4
+#define REG_TEST_SIZE 4
+#define REG_SEG_SIZE 2
+#define REG_FPU_SIZE 10
+#define REG_FLAGS_SIZE 4
+#define REG_FPCTRL_SIZE 2
+#define REG_FPSTATUS_SIZE 2
+#define REG_FPTAG_SIZE 2
+#define REG_EIP_SIZE 4
+#define REG_IP_SIZE 2
+
+/* REGISTER ALIAS TABLE:
+ *
+ * NOTE: the MMX register mapping is fixed to the physical registers
+ * used by the FPU. The floating FP stack does not effect the location
+ * of the MMX registers, so this aliasing is not 100% accurate.
+ * */
+static struct {
+ unsigned char alias; /* id of register this is an alias for */
+ unsigned char shift; /* # of bits register must be shifted */
+} ia32_reg_aliases[] = {
+ { 0,0 },
+ { REG_DWORD_OFFSET, 0 }, /* al : 1 */
+ { REG_DWORD_OFFSET, 8 }, /* ah : 2 */
+ { REG_DWORD_OFFSET, 0 }, /* ax : 3 */
+ { REG_DWORD_OFFSET + 1, 0 }, /* cl : 4 */
+ { REG_DWORD_OFFSET + 1, 8 }, /* ch : 5 */
+ { REG_DWORD_OFFSET + 1, 0 }, /* cx : 6 */
+ { REG_DWORD_OFFSET + 2, 0 }, /* dl : 7 */
+ { REG_DWORD_OFFSET + 2, 8 }, /* dh : 8 */
+ { REG_DWORD_OFFSET + 2, 0 }, /* dx : 9 */
+ { REG_DWORD_OFFSET + 3, 0 }, /* bl : 10 */
+ { REG_DWORD_OFFSET + 3, 8 }, /* bh : 11 */
+ { REG_DWORD_OFFSET + 3, 0 }, /* bx : 12 */
+ { REG_DWORD_OFFSET + 4, 0 }, /* sp : 13 */
+ { REG_DWORD_OFFSET + 5, 0 }, /* bp : 14 */
+ { REG_DWORD_OFFSET + 6, 0 }, /* si : 15 */
+ { REG_DWORD_OFFSET + 7, 0 }, /* di : 16 */
+ { REG_EIP_INDEX, 0 }, /* ip : 17 */
+ { REG_FPU_OFFSET, 0 }, /* mm0 : 18 */
+ { REG_FPU_OFFSET + 1, 0 }, /* mm1 : 19 */
+ { REG_FPU_OFFSET + 2, 0 }, /* mm2 : 20 */
+ { REG_FPU_OFFSET + 3, 0 }, /* mm3 : 21 */
+ { REG_FPU_OFFSET + 4, 0 }, /* mm4 : 22 */
+ { REG_FPU_OFFSET + 5, 0 }, /* mm5 : 23 */
+ { REG_FPU_OFFSET + 6, 0 }, /* mm6 : 24 */
+ { REG_FPU_OFFSET + 7, 0 } /* mm7 : 25 */
+ };
+
+/* REGISTER TABLE: size, type, and name of every register in the
+ * CPU. Does not include MSRs since the are, after all,
+ * model specific. */
+static struct {
+ unsigned int size;
+ enum x86_reg_type type;
+ unsigned int alias;
+ char mnemonic[8];
+} ia32_reg_table[NUM_X86_REGS + 2] = {
+ { 0, 0, 0, "" },
+ /* REG_DWORD_OFFSET */
+ { REG_DWORD_SIZE, reg_gen | reg_ret, 0, "eax" },
+ { REG_DWORD_SIZE, reg_gen | reg_count, 0, "ecx" },
+ { REG_DWORD_SIZE, reg_gen, 0, "edx" },
+ { REG_DWORD_SIZE, reg_gen, 0, "ebx" },
+ /* REG_ESP_INDEX */
+ { REG_DWORD_SIZE, reg_gen | reg_sp, 0, "esp" },
+ { REG_DWORD_SIZE, reg_gen | reg_fp, 0, "ebp" },
+ { REG_DWORD_SIZE, reg_gen | reg_src, 0, "esi" },
+ { REG_DWORD_SIZE, reg_gen | reg_dest, 0, "edi" },
+ /* REG_WORD_OFFSET */
+ { REG_WORD_SIZE, reg_gen | reg_ret, 3, "ax" },
+ { REG_WORD_SIZE, reg_gen | reg_count, 6, "cx" },
+ { REG_WORD_SIZE, reg_gen, 9, "dx" },
+ { REG_WORD_SIZE, reg_gen, 12, "bx" },
+ { REG_WORD_SIZE, reg_gen | reg_sp, 13, "sp" },
+ { REG_WORD_SIZE, reg_gen | reg_fp, 14, "bp" },
+ { REG_WORD_SIZE, reg_gen | reg_src, 15, "si" },
+ { REG_WORD_SIZE, reg_gen | reg_dest, 16, "di" },
+ /* REG_BYTE_OFFSET */
+ { REG_BYTE_SIZE, reg_gen, 1, "al" },
+ { REG_BYTE_SIZE, reg_gen, 4, "cl" },
+ { REG_BYTE_SIZE, reg_gen, 7, "dl" },
+ { REG_BYTE_SIZE, reg_gen, 10, "bl" },
+ { REG_BYTE_SIZE, reg_gen, 2, "ah" },
+ { REG_BYTE_SIZE, reg_gen, 5, "ch" },
+ { REG_BYTE_SIZE, reg_gen, 8, "dh" },
+ { REG_BYTE_SIZE, reg_gen, 11, "bh" },
+ /* REG_MMX_OFFSET */
+ { REG_MMX_SIZE, reg_simd, 18, "mm0" },
+ { REG_MMX_SIZE, reg_simd, 19, "mm1" },
+ { REG_MMX_SIZE, reg_simd, 20, "mm2" },
+ { REG_MMX_SIZE, reg_simd, 21, "mm3" },
+ { REG_MMX_SIZE, reg_simd, 22, "mm4" },
+ { REG_MMX_SIZE, reg_simd, 23, "mm5" },
+ { REG_MMX_SIZE, reg_simd, 24, "mm6" },
+ { REG_MMX_SIZE, reg_simd, 25, "mm7" },
+ /* REG_SIMD_OFFSET */
+ { REG_SIMD_SIZE, reg_simd, 0, "xmm0" },
+ { REG_SIMD_SIZE, reg_simd, 0, "xmm1" },
+ { REG_SIMD_SIZE, reg_simd, 0, "xmm2" },
+ { REG_SIMD_SIZE, reg_simd, 0, "xmm3" },
+ { REG_SIMD_SIZE, reg_simd, 0, "xmm4" },
+ { REG_SIMD_SIZE, reg_simd, 0, "xmm5" },
+ { REG_SIMD_SIZE, reg_simd, 0, "xmm6" },
+ { REG_SIMD_SIZE, reg_simd, 0, "xmm7" },
+ /* REG_DEBUG_OFFSET */
+ { REG_DEBUG_SIZE, reg_sys, 0, "dr0" },
+ { REG_DEBUG_SIZE, reg_sys, 0, "dr1" },
+ { REG_DEBUG_SIZE, reg_sys, 0, "dr2" },
+ { REG_DEBUG_SIZE, reg_sys, 0, "dr3" },
+ { REG_DEBUG_SIZE, reg_sys, 0, "dr4" },
+ { REG_DEBUG_SIZE, reg_sys, 0, "dr5" },
+ { REG_DEBUG_SIZE, reg_sys, 0, "dr6" },
+ { REG_DEBUG_SIZE, reg_sys, 0, "dr7" },
+ /* REG_CTRL_OFFSET */
+ { REG_CTRL_SIZE, reg_sys, 0, "cr0" },
+ { REG_CTRL_SIZE, reg_sys, 0, "cr1" },
+ { REG_CTRL_SIZE, reg_sys, 0, "cr2" },
+ { REG_CTRL_SIZE, reg_sys, 0, "cr3" },
+ { REG_CTRL_SIZE, reg_sys, 0, "cr4" },
+ { REG_CTRL_SIZE, reg_sys, 0, "cr5" },
+ { REG_CTRL_SIZE, reg_sys, 0, "cr6" },
+ { REG_CTRL_SIZE, reg_sys, 0, "cr7" },
+ /* REG_TEST_OFFSET */
+ { REG_TEST_SIZE, reg_sys, 0, "tr0" },
+ { REG_TEST_SIZE, reg_sys, 0, "tr1" },
+ { REG_TEST_SIZE, reg_sys, 0, "tr2" },
+ { REG_TEST_SIZE, reg_sys, 0, "tr3" },
+ { REG_TEST_SIZE, reg_sys, 0, "tr4" },
+ { REG_TEST_SIZE, reg_sys, 0, "tr5" },
+ { REG_TEST_SIZE, reg_sys, 0, "tr6" },
+ { REG_TEST_SIZE, reg_sys, 0, "tr7" },
+ /* REG_SEG_OFFSET */
+ { REG_SEG_SIZE, reg_seg, 0, "es" },
+ { REG_SEG_SIZE, reg_seg, 0, "cs" },
+ { REG_SEG_SIZE, reg_seg, 0, "ss" },
+ { REG_SEG_SIZE, reg_seg, 0, "ds" },
+ { REG_SEG_SIZE, reg_seg, 0, "fs" },
+ { REG_SEG_SIZE, reg_seg, 0, "gs" },
+ /* REG_LDTR_INDEX */
+ { REG_DWORD_SIZE, reg_sys, 0, "ldtr" },
+ /* REG_GDTR_INDEX */
+ { REG_DWORD_SIZE, reg_sys, 0, "gdtr" },
+ /* REG_FPU_OFFSET */
+ { REG_FPU_SIZE, reg_fpu, 0, "st(0)" },
+ { REG_FPU_SIZE, reg_fpu, 0, "st(1)" },
+ { REG_FPU_SIZE, reg_fpu, 0, "st(2)" },
+ { REG_FPU_SIZE, reg_fpu, 0, "st(3)" },
+ { REG_FPU_SIZE, reg_fpu, 0, "st(4)" },
+ { REG_FPU_SIZE, reg_fpu, 0, "st(5)" },
+ { REG_FPU_SIZE, reg_fpu, 0, "st(6)" },
+ { REG_FPU_SIZE, reg_fpu, 0, "st(7)" },
+ /* REG_FLAGS_INDEX : 81 */
+ { REG_FLAGS_SIZE, reg_cond, 0, "eflags" },
+ /* REG_FPCTRL_INDEX : 82*/
+ { REG_FPCTRL_SIZE, reg_fpu | reg_sys, 0, "fpctrl" },
+ /* REG_FPSTATUS_INDEX : 83*/
+ { REG_FPSTATUS_SIZE, reg_fpu | reg_sys, 0, "fpstat" },
+ /* REG_FPTAG_INDEX : 84 */
+ { REG_FPTAG_SIZE, reg_fpu | reg_sys, 0, "fptag" },
+ /* REG_EIP_INDEX : 85 */
+ { REG_EIP_SIZE, reg_pc, 0, "eip" },
+ /* REG_IP_INDEX : 86 */
+ { REG_IP_SIZE, reg_pc, 17, "ip" },
+ /* REG_IDTR_INDEX : 87 */
+ { REG_DWORD_SIZE, reg_sys, 0, "idtr" },
+ /* REG_MXCSG_INDEX : SSE Control Reg : 88 */
+ { REG_DWORD_SIZE, reg_sys | reg_simd, 0, "mxcsr" },
+ /* REG_TR_INDEX : Task Register : 89 */
+ { 16 + 64, reg_sys, 0, "tr" },
+ /* REG_CSMSR_INDEX : SYSENTER_CS_MSR : 90 */
+ { REG_DWORD_SIZE, reg_sys, 0, "cs_msr" },
+ /* REG_ESPMSR_INDEX : SYSENTER_ESP_MSR : 91 */
+ { REG_DWORD_SIZE, reg_sys, 0, "esp_msr" },
+ /* REG_EIPMSR_INDEX : SYSENTER_EIP_MSR : 92 */
+ { REG_DWORD_SIZE, reg_sys, 0, "eip_msr" },
+ { 0 }
+ };
+
+
+static size_t sz_regtable = NUM_X86_REGS + 1;
+
+
+void ia32_handle_register( x86_reg_t *reg, size_t id ) {
+ unsigned int alias;
+ if (! id || id > sz_regtable ) {
+ return;
+ }
+
+ memset( reg, 0, sizeof(x86_reg_t) );
+
+ strncpy( reg->name, ia32_reg_table[id].mnemonic, MAX_REGNAME );
+
+ reg->type = ia32_reg_table[id].type;
+ reg->size = ia32_reg_table[id].size;
+
+ alias = ia32_reg_table[id].alias;
+ if ( alias ) {
+ reg->alias = ia32_reg_aliases[alias].alias;
+ reg->shift = ia32_reg_aliases[alias].shift;
+ }
+ reg->id = id;
+
+ return;
+}
+
+size_t ia32_true_register_id( size_t id ) {
+ size_t reg;
+
+ if (! id || id > sz_regtable ) {
+ return 0;
+ }
+
+ reg = id;
+ if (ia32_reg_table[reg].alias) {
+ reg = ia32_reg_aliases[ia32_reg_table[reg].alias].alias;
+ }
+ return reg;
+}
diff --git a/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/ia32_reg.h b/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/ia32_reg.h
new file mode 100644
index 0000000000..fbbc77a178
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/ia32_reg.h
@@ -0,0 +1,41 @@
+#ifndef IA32_REG_H
+#define IA32_REG_H
+
+#include <sys/types.h> /* for size_t */
+#include "libdis.h" /* for x86_reg_t */
+
+/* NOTE these are used in opcode tables for hard-coded registers */
+#define REG_DWORD_OFFSET 1 /* 0 + 1 */
+#define REG_ECX_INDEX 2 /* 0 + 1 + 1 */
+#define REG_ESP_INDEX 5 /* 0 + 4 + 1 */
+#define REG_EBP_INDEX 6 /* 0 + 5 + 1 */
+#define REG_ESI_INDEX 7 /* 0 + 6 + 1 */
+#define REG_EDI_INDEX 8 /* 0 + 7 + 1 */
+#define REG_WORD_OFFSET 9 /* 1 * 8 + 1 */
+#define REG_BYTE_OFFSET 17 /* 2 * 8 + 1 */
+#define REG_MMX_OFFSET 25 /* 3 * 8 + 1 */
+#define REG_SIMD_OFFSET 33 /* 4 * 8 + 1 */
+#define REG_DEBUG_OFFSET 41 /* 5 * 8 + 1 */
+#define REG_CTRL_OFFSET 49 /* 6 * 8 + 1 */
+#define REG_TEST_OFFSET 57 /* 7 * 8 + 1 */
+#define REG_SEG_OFFSET 65 /* 8 * 8 + 1 */
+#define REG_LDTR_INDEX 71 /* 8 * 8 + 1 + 1 */
+#define REG_GDTR_INDEX 72 /* 8 * 8 + 2 + 1 */
+#define REG_FPU_OFFSET 73 /* 9 * 8 + 1 */
+#define REG_FLAGS_INDEX 81 /* 10 * 8 + 1 */
+#define REG_FPCTRL_INDEX 82 /* 10 * 8 + 1 + 1 */
+#define REG_FPSTATUS_INDEX 83 /* 10 * 8 + 2 + 1 */
+#define REG_FPTAG_INDEX 84 /* 10 * 8 + 3 + 1 */
+#define REG_EIP_INDEX 85 /* 10 * 8 + 4 + 1 */
+#define REG_IP_INDEX 86 /* 10 * 8 + 5 + 1 */
+#define REG_IDTR_INDEX 87 /* 10 * 8 + 6 + 1 */
+#define REG_MXCSG_INDEX 88 /* 10 * 8 + 7 + 1 */
+#define REG_TR_INDEX 89 /* 10 * 8 + 8 + 1 */
+#define REG_CSMSR_INDEX 90 /* 10 * 8 + 9 + 1 */
+#define REG_ESPMSR_INDEX 91 /* 10 * 8 + 10 + 1 */
+#define REG_EIPMSR_INDEX 92 /* 10 * 8 + 11 + 1 */
+
+void ia32_handle_register( x86_reg_t *reg, size_t id );
+size_t ia32_true_register_id( size_t id );
+
+#endif
diff --git a/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/ia32_settings.c b/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/ia32_settings.c
new file mode 100644
index 0000000000..b578e34488
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/ia32_settings.c
@@ -0,0 +1,13 @@
+#include "libdis.h"
+#include "ia32_settings.h"
+#include "ia32_reg.h"
+#include "ia32_insn.h"
+
+ia32_settings_t ia32_settings = {
+ 1, 0xF4,
+ MAX_INSTRUCTION_SIZE,
+ 4, 4, 8, 4, 8,
+ REG_ESP_INDEX, REG_EBP_INDEX, REG_EIP_INDEX, REG_FLAGS_INDEX,
+ REG_DWORD_OFFSET, REG_SEG_OFFSET, REG_FPU_OFFSET,
+ opt_none
+};
diff --git a/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/ia32_settings.h b/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/ia32_settings.h
new file mode 100644
index 0000000000..769c0e9fa0
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/ia32_settings.h
@@ -0,0 +1,27 @@
+#ifndef IA32_SETTINGS_H
+#define IA32_SETTINGS_H
+
+#include "libdis.h"
+
+typedef struct {
+ /* options */
+ unsigned char endian, /* 0 = big, 1 = little */
+ wc_byte, /* wildcard byte */
+ max_insn, /* max insn size */
+ sz_addr, /* default address size */
+ sz_oper, /* default operand size */
+ sz_byte, /* # bits in byte */
+ sz_word, /* # bytes in machine word */
+ sz_dword; /* # bytes in machine dword */
+ unsigned int id_sp_reg, /* id of stack pointer */
+ id_fp_reg, /* id of frame pointer */
+ id_ip_reg, /* id of instruction pointer */
+ id_flag_reg, /* id of flags register */
+ offset_gen_regs, /* start of general regs */
+ offset_seg_regs, /* start of segment regs */
+ offset_fpu_regs; /* start of floating point regs */
+ /* user-controlled settings */
+ enum x86_options options;
+} ia32_settings_t;
+
+#endif
diff --git a/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/libdis.h b/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/libdis.h
new file mode 100644
index 0000000000..83a88612a3
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/libdis.h
@@ -0,0 +1,832 @@
+#ifndef LIBDISASM_H
+#define LIBDISASM_H
+
+#include <stdint.h>
+
+/* 'NEW" types
+ * __________________________________________________________________________*/
+#ifndef LIBDISASM_QWORD_H /* do not interfere with qword.h */
+ #define LIBDISASM_QWORD_H
+ #ifdef _MSC_VER
+ typedef __int64 qword_t;
+ #else
+ typedef int64_t qword_t;
+ #endif
+#endif
+
+#include <sys/types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* 'NEW" x86 API
+ * __________________________________________________________________________*/
+
+
+/* ========================================= Error Reporting */
+/* REPORT CODES
+ * These are passed to a reporter function passed at initialization.
+ * Each code determines the type of the argument passed to the reporter;
+ * this allows the report to recover from errors, or just log them.
+ */
+enum x86_report_codes {
+ report_disasm_bounds, /* RVA OUT OF BOUNDS : The disassembler could
+ not disassemble the supplied RVA as it is
+ out of the range of the buffer. The
+ application should store the address and
+ attempt to determine what section of the
+ binary it is in, then disassemble the
+ address from the bytes in that section.
+ data: uint32_t rva */
+ report_insn_bounds, /* INSTRUCTION OUT OF BOUNDS: The disassembler
+ could not disassemble the instruction as
+ the instruction would require bytes beyond
+ the end of the current buffer. This usually
+ indicated garbage bytes at the end of a
+ buffer, or an incorrectly-sized buffer.
+ data: uint32_t rva */
+ report_invalid_insn, /* INVALID INSTRUCTION: The disassembler could
+ not disassemble the instruction as it has an
+ invalid combination of opcodes and operands.
+ This will stop automated disassembly; the
+ application can restart the disassembly
+ after the invalid instruction.
+ data: uint32_t rva */
+ report_unknown
+};
+
+/* 'arg' is optional arbitrary data provided by the code passing the
+ * callback -- for example, it could be 'this' or 'self' in OOP code.
+ * 'code' is provided by libdisasm, it is one of the above
+ * 'data' is provided by libdisasm and is context-specific, per the enums */
+typedef void (*DISASM_REPORTER)( enum x86_report_codes code,
+ void *data, void *arg );
+
+
+/* x86_report_error : Call the register reporter to report an error */
+void x86_report_error( enum x86_report_codes code, void *data );
+
+/* ========================================= Libdisasm Management Routines */
+enum x86_options { /* these can be ORed together */
+ opt_none= 0,
+ opt_ignore_nulls=1, /* ignore sequences of > 4 NULL bytes */
+ opt_16_bit=2, /* 16-bit/DOS disassembly */
+ opt_att_mnemonics=4, /* use AT&T syntax names for alternate opcode mnemonics */
+};
+
+/* management routines */
+/* 'arg' is caller-specific data which is passed as the first argument
+ * to the reporter callback routine */
+int x86_init( enum x86_options options, DISASM_REPORTER reporter, void *arg);
+void x86_set_reporter( DISASM_REPORTER reporter, void *arg);
+void x86_set_options( enum x86_options options );
+enum x86_options x86_get_options( void );
+int x86_cleanup(void);
+
+
+/* ========================================= Instruction Representation */
+/* these defines are only intended for use in the array decl's */
+#define MAX_REGNAME 8
+
+#define MAX_PREFIX_STR 32
+#define MAX_MNEM_STR 16
+#define MAX_INSN_SIZE 20 /* same as in i386.h */
+#define MAX_OP_STRING 32 /* max possible operand size in string form */
+#define MAX_OP_RAW_STRING 64 /* max possible operand size in raw form */
+#define MAX_OP_XML_STRING 256 /* max possible operand size in xml form */
+#define MAX_NUM_OPERANDS 8 /* max # implicit and explicit operands */
+/* in these, the '2 *' is arbitrary: the max # of operands should require
+ * more space than the rest of the insn */
+#define MAX_INSN_STRING 512 /* 2 * 8 * MAX_OP_STRING */
+#define MAX_INSN_RAW_STRING 1024 /* 2 * 8 * MAX_OP_RAW_STRING */
+#define MAX_INSN_XML_STRING 4096 /* 2 * 8 * MAX_OP_XML_STRING */
+
+enum x86_reg_type { /* NOTE: these may be ORed together */
+ reg_gen = 0x00001, /* general purpose */
+ reg_in = 0x00002, /* incoming args, ala RISC */
+ reg_out = 0x00004, /* args to calls, ala RISC */
+ reg_local = 0x00008, /* local vars, ala RISC */
+ reg_fpu = 0x00010, /* FPU data register */
+ reg_seg = 0x00020, /* segment register */
+ reg_simd = 0x00040, /* SIMD/MMX reg */
+ reg_sys = 0x00080, /* restricted/system register */
+ reg_sp = 0x00100, /* stack pointer */
+ reg_fp = 0x00200, /* frame pointer */
+ reg_pc = 0x00400, /* program counter */
+ reg_retaddr = 0x00800, /* return addr for func */
+ reg_cond = 0x01000, /* condition code / flags */
+ reg_zero = 0x02000, /* zero register, ala RISC */
+ reg_ret = 0x04000, /* return value */
+ reg_src = 0x10000, /* array/rep source */
+ reg_dest = 0x20000, /* array/rep destination */
+ reg_count = 0x40000 /* array/rep/loop counter */
+};
+
+/* x86_reg_t : an X86 CPU register */
+typedef struct {
+ char name[MAX_REGNAME];
+ enum x86_reg_type type; /* what register is used for */
+ unsigned int size; /* size of register in bytes */
+ unsigned int id; /* register ID #, for quick compares */
+ unsigned int alias; /* ID of reg this is an alias for */
+ unsigned int shift; /* amount to shift aliased reg by */
+} x86_reg_t;
+
+/* x86_ea_t : an X86 effective address (address expression) */
+typedef struct {
+ unsigned int scale; /* scale factor */
+ x86_reg_t index, base; /* index, base registers */
+ int32_t disp; /* displacement */
+ char disp_sign; /* is negative? 1/0 */
+ char disp_size; /* 0, 1, 2, 4 */
+} x86_ea_t;
+
+/* x86_absolute_t : an X86 segment:offset address (descriptor) */
+typedef struct {
+ unsigned short segment; /* loaded directly into CS */
+ union {
+ unsigned short off16; /* loaded directly into IP */
+ uint32_t off32; /* loaded directly into EIP */
+ } offset;
+} x86_absolute_t;
+
+enum x86_op_type { /* mutually exclusive */
+ op_unused = 0, /* empty/unused operand: should never occur */
+ op_register = 1, /* CPU register */
+ op_immediate = 2, /* Immediate Value */
+ op_relative_near = 3, /* Relative offset from IP */
+ op_relative_far = 4, /* Relative offset from IP */
+ op_absolute = 5, /* Absolute address (ptr16:32) */
+ op_expression = 6, /* Address expression (scale/index/base/disp) */
+ op_offset = 7, /* Offset from start of segment (m32) */
+ op_unknown
+};
+
+#define x86_optype_is_address( optype ) \
+ ( optype == op_absolute || optype == op_offset )
+#define x86_optype_is_relative( optype ) \
+ ( optype == op_relative_near || optype == op_relative_far )
+#define x86_optype_is_memory( optype ) \
+ ( optype > op_immediate && optype < op_unknown )
+
+enum x86_op_datatype { /* these use Intel's lame terminology */
+ op_byte = 1, /* 1 byte integer */
+ op_word = 2, /* 2 byte integer */
+ op_dword = 3, /* 4 byte integer */
+ op_qword = 4, /* 8 byte integer */
+ op_dqword = 5, /* 16 byte integer */
+ op_sreal = 6, /* 4 byte real (single real) */
+ op_dreal = 7, /* 8 byte real (double real) */
+ op_extreal = 8, /* 10 byte real (extended real) */
+ op_bcd = 9, /* 10 byte binary-coded decimal */
+ op_ssimd = 10, /* 16 byte : 4 packed single FP (SIMD, MMX) */
+ op_dsimd = 11, /* 16 byte : 2 packed double FP (SIMD, MMX) */
+ op_sssimd = 12, /* 4 byte : scalar single FP (SIMD, MMX) */
+ op_sdsimd = 13, /* 8 byte : scalar double FP (SIMD, MMX) */
+ op_descr32 = 14, /* 6 byte Intel descriptor 2:4 */
+ op_descr16 = 15, /* 4 byte Intel descriptor 2:2 */
+ op_pdescr32 = 16, /* 6 byte Intel pseudo-descriptor 32:16 */
+ op_pdescr16 = 17, /* 6 byte Intel pseudo-descriptor 8:24:16 */
+ op_bounds16 = 18, /* signed 16:16 lower:upper bounds */
+ op_bounds32 = 19, /* signed 32:32 lower:upper bounds */
+ op_fpuenv16 = 20, /* 14 byte FPU control/environment data */
+ op_fpuenv32 = 21, /* 28 byte FPU control/environment data */
+ op_fpustate16 = 22, /* 94 byte FPU state (env & reg stack) */
+ op_fpustate32 = 23, /* 108 byte FPU state (env & reg stack) */
+ op_fpregset = 24, /* 512 bytes: register set */
+ op_fpreg = 25, /* FPU register */
+ op_none = 0xFF, /* operand without a datatype (INVLPG) */
+};
+
+enum x86_op_access { /* ORed together */
+ op_read = 1,
+ op_write = 2,
+ op_execute = 4
+};
+
+enum x86_op_flags { /* ORed together, but segs are mutually exclusive */
+ op_signed = 1, /* signed integer */
+ op_string = 2, /* possible string or array */
+ op_constant = 4, /* symbolic constant */
+ op_pointer = 8, /* operand points to a memory address */
+ op_sysref = 0x010, /* operand is a syscall number */
+ op_implied = 0x020, /* operand is implicit in the insn */
+ op_hardcode = 0x40, /* operand is hardcoded in insn definition */
+ /* NOTE: an 'implied' operand is one which can be considered a side
+ * effect of the insn, e.g. %esp being modified by PUSH or POP. A
+ * 'hard-coded' operand is one which is specified in the instruction
+ * definition, e.g. %es:%edi in MOVSB or 1 in ROL Eb, 1. The difference
+ * is that hard-coded operands are printed by disassemblers and are
+ * required to re-assemble, while implicit operands are invisible. */
+ op_es_seg = 0x100, /* ES segment override */
+ op_cs_seg = 0x200, /* CS segment override */
+ op_ss_seg = 0x300, /* SS segment override */
+ op_ds_seg = 0x400, /* DS segment override */
+ op_fs_seg = 0x500, /* FS segment override */
+ op_gs_seg = 0x600 /* GS segment override */
+};
+
+/* x86_op_t : an X86 instruction operand */
+typedef struct {
+ enum x86_op_type type; /* operand type */
+ enum x86_op_datatype datatype; /* operand size */
+ enum x86_op_access access; /* operand access [RWX] */
+ enum x86_op_flags flags; /* misc flags */
+ union {
+ /* sizeof will have to work on these union members! */
+ /* immediate values */
+ char sbyte;
+ short sword;
+ int32_t sdword;
+ qword_t sqword;
+ unsigned char byte;
+ unsigned short word;
+ uint32_t dword;
+ qword_t qword;
+ float sreal;
+ double dreal;
+ /* misc large/non-native types */
+ unsigned char extreal[10];
+ unsigned char bcd[10];
+ qword_t dqword[2];
+ unsigned char simd[16];
+ unsigned char fpuenv[28];
+ /* offset from segment */
+ uint32_t offset;
+ /* ID of CPU register */
+ x86_reg_t reg;
+ /* offsets from current insn */
+ char relative_near;
+ int32_t relative_far;
+ /* segment:offset */
+ x86_absolute_t absolute;
+ /* effective address [expression] */
+ x86_ea_t expression;
+ } data;
+ /* this is needed to make formatting operands more sane */
+ void * insn; /* pointer to x86_insn_t owning operand */
+} x86_op_t;
+
+/* Linked list of x86_op_t; provided for manual traversal of the operand
+ * list in an insn. Users wishing to add operands to this list, e.g. to add
+ * implicit operands, should use x86_operand_new in x86_operand_list.h */
+typedef struct x86_operand_list {
+ x86_op_t op;
+ struct x86_operand_list *next;
+} x86_oplist_t;
+
+enum x86_insn_group {
+ insn_none = 0, /* invalid instruction */
+ insn_controlflow = 1,
+ insn_arithmetic = 2,
+ insn_logic = 3,
+ insn_stack = 4,
+ insn_comparison = 5,
+ insn_move = 6,
+ insn_string = 7,
+ insn_bit_manip = 8,
+ insn_flag_manip = 9,
+ insn_fpu = 10,
+ insn_interrupt = 13,
+ insn_system = 14,
+ insn_other = 15
+};
+
+enum x86_insn_type {
+ insn_invalid = 0, /* invalid instruction */
+ /* insn_controlflow */
+ insn_jmp = 0x1001,
+ insn_jcc = 0x1002,
+ insn_call = 0x1003,
+ insn_callcc = 0x1004,
+ insn_return = 0x1005,
+ /* insn_arithmetic */
+ insn_add = 0x2001,
+ insn_sub = 0x2002,
+ insn_mul = 0x2003,
+ insn_div = 0x2004,
+ insn_inc = 0x2005,
+ insn_dec = 0x2006,
+ insn_shl = 0x2007,
+ insn_shr = 0x2008,
+ insn_rol = 0x2009,
+ insn_ror = 0x200A,
+ /* insn_logic */
+ insn_and = 0x3001,
+ insn_or = 0x3002,
+ insn_xor = 0x3003,
+ insn_not = 0x3004,
+ insn_neg = 0x3005,
+ /* insn_stack */
+ insn_push = 0x4001,
+ insn_pop = 0x4002,
+ insn_pushregs = 0x4003,
+ insn_popregs = 0x4004,
+ insn_pushflags = 0x4005,
+ insn_popflags = 0x4006,
+ insn_enter = 0x4007,
+ insn_leave = 0x4008,
+ /* insn_comparison */
+ insn_test = 0x5001,
+ insn_cmp = 0x5002,
+ /* insn_move */
+ insn_mov = 0x6001, /* move */
+ insn_movcc = 0x6002, /* conditional move */
+ insn_xchg = 0x6003, /* exchange */
+ insn_xchgcc = 0x6004, /* conditional exchange */
+ /* insn_string */
+ insn_strcmp = 0x7001,
+ insn_strload = 0x7002,
+ insn_strmov = 0x7003,
+ insn_strstore = 0x7004,
+ insn_translate = 0x7005, /* xlat */
+ /* insn_bit_manip */
+ insn_bittest = 0x8001,
+ insn_bitset = 0x8002,
+ insn_bitclear = 0x8003,
+ /* insn_flag_manip */
+ insn_clear_carry = 0x9001,
+ insn_clear_zero = 0x9002,
+ insn_clear_oflow = 0x9003,
+ insn_clear_dir = 0x9004,
+ insn_clear_sign = 0x9005,
+ insn_clear_parity = 0x9006,
+ insn_set_carry = 0x9007,
+ insn_set_zero = 0x9008,
+ insn_set_oflow = 0x9009,
+ insn_set_dir = 0x900A,
+ insn_set_sign = 0x900B,
+ insn_set_parity = 0x900C,
+ insn_tog_carry = 0x9010,
+ insn_tog_zero = 0x9020,
+ insn_tog_oflow = 0x9030,
+ insn_tog_dir = 0x9040,
+ insn_tog_sign = 0x9050,
+ insn_tog_parity = 0x9060,
+ /* insn_fpu */
+ insn_fmov = 0xA001,
+ insn_fmovcc = 0xA002,
+ insn_fneg = 0xA003,
+ insn_fabs = 0xA004,
+ insn_fadd = 0xA005,
+ insn_fsub = 0xA006,
+ insn_fmul = 0xA007,
+ insn_fdiv = 0xA008,
+ insn_fsqrt = 0xA009,
+ insn_fcmp = 0xA00A,
+ insn_fcos = 0xA00C,
+ insn_fldpi = 0xA00D,
+ insn_fldz = 0xA00E,
+ insn_ftan = 0xA00F,
+ insn_fsine = 0xA010,
+ insn_fsys = 0xA020,
+ /* insn_interrupt */
+ insn_int = 0xD001,
+ insn_intcc = 0xD002, /* not present in x86 ISA */
+ insn_iret = 0xD003,
+ insn_bound = 0xD004,
+ insn_debug = 0xD005,
+ insn_trace = 0xD006,
+ insn_invalid_op = 0xD007,
+ insn_oflow = 0xD008,
+ /* insn_system */
+ insn_halt = 0xE001,
+ insn_in = 0xE002, /* input from port/bus */
+ insn_out = 0xE003, /* output to port/bus */
+ insn_cpuid = 0xE004,
+ /* insn_other */
+ insn_nop = 0xF001,
+ insn_bcdconv = 0xF002, /* convert to or from BCD */
+ insn_szconv = 0xF003 /* change size of operand */
+};
+
+/* These flags specify special characteristics of the instruction, such as
+ * whether the inatruction is privileged or whether it serializes the
+ * pipeline.
+ * NOTE : These may not be accurate for all instructions; updates to the
+ * opcode tables have not been completed. */
+enum x86_insn_note {
+ insn_note_ring0 = 1, /* Only available in ring 0 */
+ insn_note_smm = 2, /* "" in System Management Mode */
+ insn_note_serial = 4, /* Serializing instruction */
+ insn_note_nonswap = 8, /* Does not swap arguments in att-style formatting */
+ insn_note_nosuffix = 16, /* Does not have size suffix in att-style formatting */
+};
+
+/* This specifies what effects the instruction has on the %eflags register */
+enum x86_flag_status {
+ insn_carry_set = 0x1, /* CF */
+ insn_zero_set = 0x2, /* ZF */
+ insn_oflow_set = 0x4, /* OF */
+ insn_dir_set = 0x8, /* DF */
+ insn_sign_set = 0x10, /* SF */
+ insn_parity_set = 0x20, /* PF */
+ insn_carry_or_zero_set = 0x40,
+ insn_zero_set_or_sign_ne_oflow = 0x80,
+ insn_carry_clear = 0x100,
+ insn_zero_clear = 0x200,
+ insn_oflow_clear = 0x400,
+ insn_dir_clear = 0x800,
+ insn_sign_clear = 0x1000,
+ insn_parity_clear = 0x2000,
+ insn_sign_eq_oflow = 0x4000,
+ insn_sign_ne_oflow = 0x8000
+};
+
+/* The CPU model in which the insturction first appeared; this can be used
+ * to mask out instructions appearing in earlier or later models or to
+ * check the portability of a binary.
+ * NOTE : These may not be accurate for all instructions; updates to the
+ * opcode tables have not been completed. */
+enum x86_insn_cpu {
+ cpu_8086 = 1, /* Intel */
+ cpu_80286 = 2,
+ cpu_80386 = 3,
+ cpu_80387 = 4,
+ cpu_80486 = 5,
+ cpu_pentium = 6,
+ cpu_pentiumpro = 7,
+ cpu_pentium2 = 8,
+ cpu_pentium3 = 9,
+ cpu_pentium4 = 10,
+ cpu_k6 = 16, /* AMD */
+ cpu_k7 = 32,
+ cpu_athlon = 48
+};
+
+/* CPU ISA subsets: These are derived from the Instruction Groups in
+ * Intel Vol 1 Chapter 5; they represent subsets of the IA32 ISA but
+ * do not reflect the 'type' of the instruction in the same way that
+ * x86_insn_group does. In short, these are AMD/Intel's somewhat useless
+ * designations.
+ * NOTE : These may not be accurate for all instructions; updates to the
+ * opcode tables have not been completed. */
+enum x86_insn_isa {
+ isa_gp = 1, /* general purpose */
+ isa_fp = 2, /* floating point */
+ isa_fpumgt = 3, /* FPU/SIMD management */
+ isa_mmx = 4, /* Intel MMX */
+ isa_sse1 = 5, /* Intel SSE SIMD */
+ isa_sse2 = 6, /* Intel SSE2 SIMD */
+ isa_sse3 = 7, /* Intel SSE3 SIMD */
+ isa_3dnow = 8, /* AMD 3DNow! SIMD */
+ isa_sys = 9 /* system instructions */
+};
+
+enum x86_insn_prefix {
+ insn_no_prefix = 0,
+ insn_rep_zero = 1, /* REPZ and REPE */
+ insn_rep_notzero = 2, /* REPNZ and REPNZ */
+ insn_lock = 4 /* LOCK: */
+};
+
+/* TODO: maybe provide insn_new/free(), and have disasm return new insn_t */
+/* x86_insn_t : an X86 instruction */
+typedef struct {
+ /* information about the instruction */
+ uint32_t addr; /* load address */
+ uint32_t offset; /* offset into file/buffer */
+ enum x86_insn_group group; /* meta-type, e.g. INS_EXEC */
+ enum x86_insn_type type; /* type, e.g. INS_BRANCH */
+ enum x86_insn_note note; /* note, e.g. RING0 */
+ unsigned char bytes[MAX_INSN_SIZE];
+ unsigned char size; /* size of insn in bytes */
+ /* 16/32-bit mode settings */
+ unsigned char addr_size; /* default address size : 2 or 4 */
+ unsigned char op_size; /* default operand size : 2 or 4 */
+ /* CPU/instruction set */
+ enum x86_insn_cpu cpu;
+ enum x86_insn_isa isa;
+ /* flags */
+ enum x86_flag_status flags_set; /* flags set or tested by insn */
+ enum x86_flag_status flags_tested;
+ /* stack */
+ unsigned char stack_mod; /* 0 or 1 : is the stack modified? */
+ int32_t stack_mod_val; /* val stack is modified by if known */
+
+ /* the instruction proper */
+ enum x86_insn_prefix prefix; /* prefixes ORed together */
+ char prefix_string[MAX_PREFIX_STR]; /* prefixes [might be truncated] */
+ char mnemonic[MAX_MNEM_STR];
+ x86_oplist_t *operands; /* list of explicit/implicit operands */
+ size_t operand_count; /* total number of operands */
+ size_t explicit_count; /* number of explicit operands */
+ /* convenience fields for user */
+ void *block; /* code block containing this insn */
+ void *function; /* function containing this insn */
+ int tag; /* tag the insn as seen/processed */
+} x86_insn_t;
+
+
+/* returns 0 if an instruction is invalid, 1 if valid */
+int x86_insn_is_valid( x86_insn_t *insn );
+
+/* DISASSEMBLY ROUTINES
+ * Canonical order of arguments is
+ * (buf, buf_len, buf_rva, offset, len, insn, func, arg, resolve_func)
+ * ...but of course all of these are not used at the same time.
+ */
+
+
+/* Function prototype for caller-supplied callback routine
+ * These callbacks are intended to process 'insn' further, e.g. by
+ * adding it to a linked list, database, etc */
+typedef void (*DISASM_CALLBACK)( x86_insn_t *insn, void * arg );
+
+/* Function prototype for caller-supplied address resolver.
+ * This routine is used to determine the rva to disassemble next, given
+ * the 'dest' operand of a jump/call. This allows the caller to resolve
+ * jump/call targets stored in a register or on the stack, and also allows
+ * the caller to prevent endless loops by checking if an address has
+ * already been disassembled. If an address cannot be resolved from the
+ * operand, or if the address has already been disassembled, this routine
+ * should return -1; in all other cases the RVA to be disassembled next
+ * should be returned. */
+typedef int32_t (*DISASM_RESOLVER)( x86_op_t *op, x86_insn_t * current_insn,
+ void *arg );
+
+
+/* x86_disasm: Disassemble a single instruction from a buffer of bytes.
+ * Returns size of instruction in bytes.
+ * Caller is responsible for calling x86_oplist_free() on
+ * a reused "insn" to avoid leaking memory when calling this
+ * function repeatedly.
+ * buf : Buffer of bytes to disassemble
+ * buf_len : Length of the buffer
+ * buf_rva : Load address of the start of the buffer
+ * offset : Offset in buffer to disassemble
+ * insn : Structure to fill with disassembled instruction
+ */
+unsigned int x86_disasm( unsigned char *buf, unsigned int buf_len,
+ uint32_t buf_rva, unsigned int offset,
+ x86_insn_t * insn );
+
+/* x86_disasm_range: Sequential disassembly of a range of bytes in a buffer,
+ * invoking a callback function each time an instruction
+ * is successfully disassembled. The 'range' refers to the
+ * bytes between 'offset' and 'offset + len' in the buffer;
+ * 'len' is assumed to be less than the length of the buffer.
+ * Returns number of instructions processed.
+ * buf : Buffer of bytes to disassemble (e.g. .text section)
+ * buf_rva : Load address of buffer (e.g. ELF Virtual Address)
+ * offset : Offset in buffer to start disassembly at
+ * len : Number of bytes to disassemble
+ * func : Callback function to invoke (may be NULL)
+ * arg : Arbitrary data to pass to callback (may be NULL)
+ */
+unsigned int x86_disasm_range( unsigned char *buf, uint32_t buf_rva,
+ unsigned int offset, unsigned int len,
+ DISASM_CALLBACK func, void *arg );
+
+/* x86_disasm_forward: Flow-of-execution disassembly of the bytes in a buffer,
+ * invoking a callback function each time an instruction
+ * is successfully disassembled.
+ * buf : Buffer to disassemble (e.g. .text section)
+ * buf_len : Number of bytes in buffer
+ * buf_rva : Load address of buffer (e.g. ELF Virtual Address)
+ * offset : Offset in buffer to start disassembly at (e.g. entry point)
+ * func : Callback function to invoke (may be NULL)
+ * arg : Arbitrary data to pass to callback (may be NULL)
+ * resolver: Caller-supplied address resolver. If no resolver is
+ * supplied, a default internal one is used -- however the
+ * internal resolver does NOT catch loops and could end up
+ * disassembling forever..
+ * r_arg : Arbitrary data to pass to resolver (may be NULL)
+ */
+unsigned int x86_disasm_forward( unsigned char *buf, unsigned int buf_len,
+ uint32_t buf_rva, unsigned int offset,
+ DISASM_CALLBACK func, void *arg,
+ DISASM_RESOLVER resolver, void *r_arg );
+
+/* Instruction operands: these are stored as a list of explicit and
+ * implicit operands. It is recommended that the 'foreach' routines
+ * be used to when examining operands for purposes of data flow analysis */
+
+/* Operand FOREACH callback: 'arg' is an abritrary parameter passed to the
+ * foreach routine, 'insn' is the x86_insn_t whose operands are being
+ * iterated over, and 'op' is the current x86_op_t */
+typedef void (*x86_operand_fn)(x86_op_t *op, x86_insn_t *insn, void *arg);
+
+/* FOREACH types: these are used to limit the foreach results to
+ * operands which match a certain "type" (implicit or explicit)
+ * or which are accessed in certain ways (e.g. read or write). Note
+ * that this operates on the operand list of single instruction, so
+ * specifying the 'real' operand type (register, memory, etc) is not
+ * useful. Note also that by definition Execute Access implies Read
+ * Access and implies Not Write Access.
+ * The "type" (implicit or explicit) and the access method can
+ * be ORed together, e.g. op_wo | op_explicit */
+enum x86_op_foreach_type {
+ op_any = 0, /* ALL operands (explicit, implicit, rwx) */
+ op_dest = 1, /* operands with Write access */
+ op_src = 2, /* operands with Read access */
+ op_ro = 3, /* operands with Read but not Write access */
+ op_wo = 4, /* operands with Write but not Read access */
+ op_xo = 5, /* operands with Execute access */
+ op_rw = 6, /* operands with Read AND Write access */
+ op_implicit = 0x10, /* operands that are implied by the opcode */
+ op_explicit = 0x20 /* operands that are not side-effects */
+};
+
+
+/* free the operand list associated with an instruction -- useful for
+ * preventing memory leaks when free()ing an x86_insn_t */
+void x86_oplist_free( x86_insn_t *insn );
+
+/* Operand foreach: invokes 'func' with 'insn' and 'arg' as arguments. The
+ * 'type' parameter is used to select only operands matching specific
+ * criteria. */
+int x86_operand_foreach( x86_insn_t *insn, x86_operand_fn func, void *arg,
+ enum x86_op_foreach_type type);
+
+/* convenience routine: returns count of operands matching 'type' */
+size_t x86_operand_count( x86_insn_t *insn, enum x86_op_foreach_type type );
+
+/* accessor functions for the operands */
+x86_op_t * x86_operand_1st( x86_insn_t *insn );
+x86_op_t * x86_operand_2nd( x86_insn_t *insn );
+x86_op_t * x86_operand_3rd( x86_insn_t *insn );
+
+/* these allow libdisasm 2.0 accessor functions to still be used */
+#define x86_get_dest_operand( insn ) x86_operand_1st( insn )
+#define x86_get_src_operand( insn ) x86_operand_2nd( insn )
+#define x86_get_imm_operand( insn ) x86_operand_3rd( insn )
+
+/* get size of operand data in bytes */
+unsigned int x86_operand_size( x86_op_t *op );
+
+/* Operand Convenience Routines: the following three routines are common
+ * operations on operands, intended to ease the burden of the programmer. */
+
+/* Get Address: return the value of an offset operand, or the offset of
+ * a segment:offset absolute address */
+uint32_t x86_get_address( x86_insn_t *insn );
+
+/* Get Relative Offset: return as a sign-extended int32_t the near or far
+ * relative offset operand, or 0 if there is none. There can be only one
+ * relaive offset operand in an instruction. */
+int32_t x86_get_rel_offset( x86_insn_t *insn );
+
+/* Get Branch Target: return the x86_op_t containing the target of
+ * a jump or call operand, or NULL if there is no branch target.
+ * Internally, a 'branch target' is defined as any operand with
+ * Execute Access set. There can be only one branch target per instruction. */
+x86_op_t * x86_get_branch_target( x86_insn_t *insn );
+
+/* Get Immediate: return the x86_op_t containing the immediate operand
+ * for this instruction, or NULL if there is no immediate operand. There
+ * can be only one immediate operand per instruction */
+x86_op_t * x86_get_imm( x86_insn_t *insn );
+
+/* Get Raw Immediate Data: returns a pointer to the immediate data encoded
+ * in the instruction. This is useful for large data types [>32 bits] currently
+ * not supported by libdisasm, or for determining if the disassembler
+ * screwed up the conversion of the immediate data. Note that 'imm' in this
+ * context refers to immediate data encoded at the end of an instruction as
+ * detailed in the Intel Manual Vol II Chapter 2; it does not refer to the
+ * 'op_imm' operand (the third operand in instructions like 'mul' */
+unsigned char * x86_get_raw_imm( x86_insn_t *insn );
+
+
+/* More accessor fuctions, this time for user-defined info... */
+/* set the address (usually RVA) of the insn */
+void x86_set_insn_addr( x86_insn_t *insn, uint32_t addr );
+
+/* set the offset (usually offset into file) of the insn */
+void x86_set_insn_offset( x86_insn_t *insn, unsigned int offset );
+
+/* set a pointer to the function owning the instruction. The
+ * type of 'func' is user-defined; libdisasm does not use the func field. */
+void x86_set_insn_function( x86_insn_t *insn, void * func );
+
+/* set a pointer to the block of code owning the instruction. The
+ * type of 'block' is user-defined; libdisasm does not use the block field. */
+void x86_set_insn_block( x86_insn_t *insn, void * block );
+
+/* instruction tagging: these routines allow the programmer to mark
+ * instructions as "seen" in a DFS, for example. libdisasm does not use
+ * the tag field.*/
+/* set insn->tag to 1 */
+void x86_tag_insn( x86_insn_t *insn );
+/* set insn->tag to 0 */
+void x86_untag_insn( x86_insn_t *insn );
+/* return insn->tag */
+int x86_insn_is_tagged( x86_insn_t *insn );
+
+
+/* Disassembly formats:
+ * AT&T is standard AS/GAS-style: "mnemonic\tsrc, dest, imm"
+ * Intel is standard MASM/NASM/TASM: "mnemonic\tdest,src, imm"
+ * Native is tab-delimited: "RVA\tbytes\tmnemonic\tdest\tsrc\timm"
+ * XML is your typical <insn> ... </insn>
+ * Raw is addr|offset|size|bytes|prefix... see libdisasm_formats.7
+ */
+enum x86_asm_format {
+ unknown_syntax = 0, /* never use! */
+ native_syntax, /* header: 35 bytes */
+ intel_syntax, /* header: 23 bytes */
+ att_syntax, /* header: 23 bytes */
+ xml_syntax, /* header: 679 bytes */
+ raw_syntax /* header: 172 bytes */
+};
+
+/* format (sprintf) an operand into 'buf' using specified syntax */
+int x86_format_operand(x86_op_t *op, char *buf, int len,
+ enum x86_asm_format format);
+
+/* format (sprintf) an instruction mnemonic into 'buf' using specified syntax */
+int x86_format_mnemonic(x86_insn_t *insn, char *buf, int len,
+ enum x86_asm_format format);
+
+/* format (sprintf) an instruction into 'buf' using specified syntax;
+ * this includes formatting all operands */
+int x86_format_insn(x86_insn_t *insn, char *buf, int len, enum x86_asm_format);
+
+/* fill 'buf' with a description of the format's syntax */
+int x86_format_header( char *buf, int len, enum x86_asm_format format);
+
+/* Endianness of an x86 CPU : 0 is big, 1 is little; always returns 1 */
+unsigned int x86_endian(void);
+
+/* Default address and operand size in bytes */
+unsigned int x86_addr_size(void);
+unsigned int x86_op_size(void);
+
+/* Size of a machine word in bytes */
+unsigned int x86_word_size(void);
+
+/* maximum size of a code instruction */
+#define x86_max_inst_size(x) x86_max_insn_size(x)
+unsigned int x86_max_insn_size(void);
+
+/* register IDs of Stack, Frame, Instruction pointer and Flags register */
+unsigned int x86_sp_reg(void);
+unsigned int x86_fp_reg(void);
+unsigned int x86_ip_reg(void);
+unsigned int x86_flag_reg(void);
+
+/* fill 'reg' struct with details of register 'id' */
+void x86_reg_from_id( unsigned int id, x86_reg_t * reg );
+
+/* convenience macro demonstrating how to get an aliased register; proto is
+ * void x86_get_aliased_reg( x86_reg_t *alias_reg, x86_reg_t *output_reg )
+ * where 'alias_reg' is a reg operand and 'output_reg' is filled with the
+ * register that the operand is an alias for */
+#define x86_get_aliased_reg( alias_reg, output_reg ) \
+ x86_reg_from_id( alias_reg->alias, output_reg )
+
+
+/* ================================== Invariant Instruction Representation */
+/* Invariant instructions are used for generating binary signatures;
+ * the instruction is modified so that all variant bytes in an instruction
+ * are replaced with a wildcard byte.
+ *
+ * A 'variant byte' is one that is expected to be modified by either the
+ * static or the dynamic linker: for example, an address encoded in an
+ * instruction.
+ *
+ * By comparing the invariant representation of one instruction [or of a
+ * sequence of instructions] with the invariant representation of another,
+ * one determine whether the two invariant representations are from the same
+ * relocatable object [.o] file. Thus one can use binary signatures [which
+ * are just sequences of invariant instruction representations] to look for
+ * library routines which have been statically-linked into a binary.
+ *
+ * The invariant routines are faster and smaller than the disassembly
+ * routines; they can be used to determine the size of an instruction
+ * without all of the overhead of a full instruction disassembly.
+ */
+
+/* This byte is used to replace variant bytes */
+#define X86_WILDCARD_BYTE 0xF4
+
+typedef struct {
+ enum x86_op_type type; /* operand type */
+ enum x86_op_datatype datatype; /* operand size */
+ enum x86_op_access access; /* operand access [RWX] */
+ enum x86_op_flags flags; /* misc flags */
+} x86_invariant_op_t;
+
+typedef struct {
+ unsigned char bytes[64]; /* invariant representation */
+ unsigned int size; /* number of bytes in insn */
+ enum x86_insn_group group; /* meta-type, e.g. INS_EXEC */
+ enum x86_insn_type type; /* type, e.g. INS_BRANCH */
+ x86_invariant_op_t operands[3]; /* operands: dest, src, imm */
+} x86_invariant_t;
+
+
+/* return a version of the instruction with the variant bytes masked out */
+size_t x86_invariant_disasm( unsigned char *buf, int buf_len,
+ x86_invariant_t *inv );
+/* return the size in bytes of the intruction pointed to by 'buf';
+ * this used x86_invariant_disasm since it faster than x86_disasm */
+size_t x86_size_disasm( unsigned char *buf, unsigned int buf_len );
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif
diff --git a/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/libdisasm.gyp b/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/libdisasm.gyp
new file mode 100644
index 0000000000..5c8dc45867
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/libdisasm.gyp
@@ -0,0 +1,67 @@
+# 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.
+
+{
+ 'includes': [
+ '../../build/common.gypi',
+ ],
+ 'targets': [
+ {
+ 'target_name': 'libdisasm',
+ 'type': 'static_library',
+ 'sources': [
+ 'ia32_implicit.c',
+ 'ia32_implicit.h',
+ 'ia32_insn.c',
+ 'ia32_insn.h',
+ 'ia32_invariant.c',
+ 'ia32_invariant.h',
+ 'ia32_modrm.c',
+ 'ia32_modrm.h',
+ 'ia32_opcode_tables.c',
+ 'ia32_opcode_tables.h',
+ 'ia32_operand.c',
+ 'ia32_operand.h',
+ 'ia32_reg.c',
+ 'ia32_reg.h',
+ 'ia32_settings.c',
+ 'ia32_settings.h',
+ 'libdis.h',
+ 'qword.h',
+ 'x86_disasm.c',
+ 'x86_format.c',
+ 'x86_imm.c',
+ 'x86_imm.h',
+ 'x86_insn.c',
+ 'x86_misc.c',
+ 'x86_operand_list.c',
+ 'x86_operand_list.h',
+ ],
+ },
+ ],
+}
diff --git a/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/qword.h b/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/qword.h
new file mode 100644
index 0000000000..5f0e803c93
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/qword.h
@@ -0,0 +1,14 @@
+#ifndef LIBDISASM_QWORD_H
+#define LIBDISASM_QWORD_H
+
+#include <stdint.h>
+
+/* platform independent data types */
+
+#ifdef _MSC_VER
+ typedef __int64 qword_t;
+#else
+ typedef int64_t qword_t;
+#endif
+
+#endif
diff --git a/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/swig/Makefile b/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/swig/Makefile
new file mode 100644
index 0000000000..44ef486b6a
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/swig/Makefile
@@ -0,0 +1,70 @@
+# change these values if you need to
+SWIG = swig # apt-get install swig !
+GCC = gcc
+
+CC_FLAGS = -c -fPIC
+LD_FLAGS = -shared -L../.. -ldisasm
+
+BASE_NAME = x86disasm
+
+export INTERFACE_FILE BASE_NAME SWIG GCC CC_FLAGS LD_FLAGS
+
+#====================================================
+# TARGETS
+
+all: swig
+dummy: swig swig-python swig-ruby swig-perl swig-tcl install uninstall clean
+
+swig: swig-python swig-perl
+# swig-rub swig-tcl
+
+swig-python:
+ cd python && make -f Makefile-swig
+
+swig-ruby:
+ cd ruby && make -f Makefile-swig
+
+swig-perl:
+ cd perl && make -f Makefile-swig
+
+swig-tcl:
+ cd tcl && make -f Makefile-swig
+
+# ==================================================================
+install: install-python install-perl
+# install-ruby install-tcl
+
+install-python:
+ cd python && sudo make -f Makefile-swig install
+
+install-ruby:
+ cd ruby && sudo make -f Makefile-swig install
+
+install-perl:
+ cd perl && sudo make -f Makefile-swig install
+
+install-tcl:
+ cd tcl && sudo make -f Makefile-swig install
+
+# ==================================================================
+uninstall: uninstall-python
+#uninstall-ruby uninstall-perl uninstall-tcl
+
+uninstall-python:
+ cd python && sudo make -f Makefile-swig uninstall
+
+uninstall-ruby:
+ cd ruby && sudo make -f Makefile-swig uninstall
+
+uninstall-perl:
+ cd perl && sudo make -f Makefile-swig uninstall
+
+uninstall-tcl:
+ cd tcl && sudo make -f Makefile-swig uninstall
+
+# ==================================================================
+clean:
+ cd python && make -f Makefile-swig clean
+ cd ruby && make -f Makefile-swig clean
+ cd perl && make -f Makefile-swig clean
+ cd tcl && make -f Makefile-swig clean
diff --git a/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/swig/README b/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/swig/README
new file mode 100644
index 0000000000..a9fa79ec2c
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/swig/README
@@ -0,0 +1,128 @@
+ Libdisasm SWIG README
+
+The SWIG utility (www.swig.org) can be used to generate
+
+
+Building SWIG Modules
+---------------------
+
+ make
+ make install
+
+Make and Install both build Python, Perl, Ruby, and Tcl modules. If you
+do not have one of these languages installed, comment out the relevant
+target in the main Makefile.
+
+Install uses 'sudo' to put files in the correct locations; if you
+do not have sudo installed, change the install targets.
+
+The Module API
+--------------
+
+The OOP API
+-----------
+
+
+The Python Module
+-----------------
+
+To test that the module loads:
+
+ bash# python
+ >>> import x86disasm
+ >>> x86disasm.version_string()
+ '0.21-pre'
+ >>>^D
+ bash#
+
+ >>> import x86disasm
+ >>> import array
+ >>> disasm = x86disasm.X86_Disasm( )
+ >>> tgt = open( "/tmp/a.out", "rb" )
+ >>> tgt.seek( 0, 2 )
+ >>> size = tgt.tell()
+ >>> tgt.seek( 0, 0 )
+ >>> buf = array.array( 'B' )
+ >>> buf.fromfile( tgt, size )
+ >>> tgt.close()
+ >>> data = x86disasm.byteArray( size )
+ >>> for i in range( size ):
+ ... data[i] = buf.pop(0)
+ ...
+ >>> del buf
+ >>> del tgt
+ >>> insn = disasm.disasm( data, size - 1, 0, 0 )
+ >>> insn.format( x86disasm.att_syntax )
+ 'jg\t0x00000047'
+ >>> insn.format( x86disasm.raw_syntax )
+ '0x00000000|0x00000000|2|7F 45 |||controlflow|jcc|jg|80386|General Purpose|||zero_clear sign_eq_oflow |0|0|relative|sbyte|00000047|'
+ >>> ops = insn.operand_list()
+ >>> node = ops.first()
+ >>> while node is not None:
+ ... s = node.op.format(x86disasm.raw_syntax)
+ ... print s
+ ... node = ops.next()
+ ...
+ relative|sbyte|00000047|
+
+
+
+
+
+
+The Perl Module
+---------------
+
+To test that the module loads:
+
+ bash# perl
+ use x86disasm;
+ print x86disasm::version_string() . "\n";
+ ^D
+ 0.21-pre
+ bash#
+
+The Ruby Module
+---------------
+
+To test that the module loads:
+
+ bash# irb
+ irb(main):001:0> require 'x86disasm'
+ => true
+ irb(main):002:0> X86disasm.version_string()
+ => "0.21-pre"
+ irb(main):003:0> x = X86disasm::X86_Disasm.new
+ => #<X86disasm::X86_Disasm:0xb7d624a4>
+ irb(main):004:0> x.max_register_string()
+ => 8
+ irb(main):003:0> ^D
+ bash#
+
+The Tcl Module
+---------------
+
+To test that the module loads:
+
+ bash# tclsh
+ % load /usr/lib/tcl8.3/x86disasm.so X86disasm
+ % version_string
+ 0.21-pre
+ % ^D
+ bash#
+
+ % x86_init 0 NULL NULL
+ OR
+ % x86disasm dis
+ _486b0708_p_x86disasm
+ % puts "[dis cget -last_error]"
+ 0
+
+
+
+
+The Interface Files
+-------------------
+
+ libdisasm.i -- interface file without shadow classes
+ libdisasm_oop.i -- interface file with shadow classes
diff --git a/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/swig/libdisasm.i b/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/swig/libdisasm.i
new file mode 100644
index 0000000000..ec12041755
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/swig/libdisasm.i
@@ -0,0 +1,508 @@
+%module x86disasm
+%{
+#include "../../libdis.h"
+#include "../../../config.h"
+%}
+
+%rename(version_string) x86_version_string;
+%include "../../libdis.h"
+#include "../../../config.h"
+
+%inline %{
+ const char * x86_version_string( void ) {
+ return PACKAGE_VERSION;
+ }
+%}
+
+%rename(report_codes) x86_report_codes;
+%rename(report_error) x86_report_error;
+%rename(options) x86_options;
+%rename(init) x86_init;
+%rename(set_reporter) x86_set_reporter;
+%rename(set_options) x86_set_options;
+%rename(options) x86_get_options;
+%rename(cleanup) x86_cleanup;
+%rename(reg_type) x86_reg_type;
+%rename(reg) x86_reg_t;
+%rename(eaddr) x86_ea_t;
+%rename(op_type) x86_op_type;
+%rename(optype_is_address) x86_optype_is_address;
+%rename(optype_is_relative) x86_optype_is_relative;
+%rename(op_datatype) x86_op_datatype;
+%rename(op_access) x86_op_access;
+%rename(op_flags) x86_op_flags;
+%rename(operand) x86_op_t;
+%rename(insn_group) x86_insn_group;
+%rename(insn_type) x86_insn_type;
+%rename(insn_note) x86_insn_note ;
+%rename(flag_status) x86_flag_status;
+%rename(insn_cpu) x86_insn_cpu ;
+%rename(insn_isa) x86_insn_isa ;
+%rename(insn_prefix) x86_insn_prefix ;
+%rename(insn) x86_insn_t;
+%rename(insn_is_valid) x86_insn_is_valid;
+%rename(i_disasm) x86_disasm;
+%rename(i_disasm_range) x86_disasm_range;
+%rename(i_disasm_forward) x86_disasm_forward;
+%rename(insn_operand_count) x86_operand_count;
+%rename(insn_operand_1st) x86_operand_1st;
+%rename(insn_operand_2nd) x86_operand_2nd;
+%rename(insn_operand_3rd) x86_operand_3rd;
+%rename(insn_dest_operand) x86_get_dest_operand;
+%rename(insn_src_operand) x86_get_src_operand;
+%rename(insn_imm_operand) x86_get_imm_operand;
+%rename(operand_size) x86_operand_size;
+%rename(insn_rel_offset) x86_get_rel_offset;
+%rename(insn_branch_target) x86_get_branch_target;
+%rename(insn_imm) x86_get_imm;
+%rename(insn_raw_imm) x86_get_raw_imm;
+%rename(insn_set_addr) x86_set_insn_addr;
+%rename(insn_set_offset) x86_set_insn_offset;
+%rename(insn_set_function) x86_set_insn_function;
+%rename(insn_set_block) x86_set_insn_block;
+%rename(insn_tag) x86_tag_insn;
+%rename(insn_untag) x86_untag_insn;
+%rename(insn_is_tagged) x86_insn_is_tagged;
+%rename(asm_format) x86_asm_format;
+%rename(operand_format) x86_format_operand;
+%rename(insn_format_mnemonic) x86_format_mnemonic;
+%rename(insn_format) x86_format_insn;
+%rename(header_format) x86_format_header;
+%rename(endian) x86_endian;
+%rename(size_default_address) x86_addr_size;
+%rename(size_default_operand) x86_op_size;
+%rename(size_machine_word) x86_word_size;
+%rename(size_max_insn) x86_max_insn_size;
+%rename(reg_sp) x86_sp_reg;
+%rename(reg_fp) x86_fp_reg;
+%rename(reg_ip) x86_ip_reg;
+%rename(reg_from_id) x86_reg_from_id;
+%rename(reg_from_alias) x86_get_aliased_reg;
+%rename(invariant_op) x86_invariant_op_t;
+%rename(invariant) x86_invariant_t;
+%rename(disasm_invariant) x86_invariant_disasm;
+%rename(disasm_size) x86_size_disasm;
+
+%include "carrays.i"
+
+%array_class( unsigned char, byteArray );
+
+
+%apply (unsigned char *STRING, int LENGTH) {
+ (unsigned char *buf, size_t buf_len)
+};
+
+
+%newobject x86_op_copy;
+%inline %{
+ x86_op_t * x86_op_copy( x86_op_t * src ) {
+ x86_op_t *op;
+
+ if (! src ) {
+ return NULL;
+ }
+
+ op = (x86_op_t *) calloc( sizeof(x86_op_t), 1 );
+ if ( op ) {
+ memcpy( op, src, sizeof(x86_op_t) );
+ }
+
+ return op;
+ }
+
+ typedef struct x86_op_list_node {
+ x86_op_t *op;
+ struct x86_op_list_node *next, *prev;
+ } x86_op_list_node;
+
+ typedef struct x86_op_list {
+ size_t count;
+ x86_op_list_node *head, *tail, *curr;
+ } x86_op_list;
+
+ x86_op_list * x86_op_list_new () {
+ x86_op_list *list = (x86_op_list *)
+ calloc( sizeof(x86_op_list), 1 );
+ list->count = 0;
+ return list;
+ }
+
+ void x86_op_list_free(x86_op_list *list) {
+ x86_op_list_node *node, *next;
+
+ node = list->head;
+ while ( node ) {
+ next = node->next;
+ /* free( node->insn ); */
+ free( node );
+ node = next;
+ }
+
+ free( list );
+ }
+
+ x86_op_list_node * x86_op_list_first(x86_op_list *list) {
+ return list->head;
+ }
+
+ x86_op_list_node * x86_op_list_last(x86_op_list *list) {
+ return list->tail;
+ }
+
+ x86_op_list_node * x86_op_list_next(x86_op_list *list) {
+ if (! list->curr ) {
+ list->curr = list->head;
+ return list->head;
+ }
+
+ list->curr = list->curr->next;
+ return list->curr;
+ }
+
+ x86_op_list_node * x86_op_list_prev(x86_op_list *list) {
+ if (! list->curr ) {
+ list->curr = list->tail;
+ return list->tail;
+ }
+
+ list->curr = list->curr->prev;
+ return list->curr;
+ }
+
+%}
+
+%newobject x86_op_list_append;
+
+%inline %{
+ void x86_op_list_append( x86_op_list * list, x86_op_t *op ) {
+ x86_op_list_node *node = (x86_op_list_node *)
+ calloc( sizeof(x86_op_list_node) , 1 );
+ if (! node ) {
+ return;
+ }
+
+ list->count++;
+ if ( ! list->tail ) {
+ list->head = list->tail = node;
+ } else {
+ list->tail->next = node;
+ node->prev = list->tail;
+ list->tail = node;
+ }
+
+ node->op = x86_op_copy( op );
+ }
+
+ x86_oplist_t * x86_op_list_node_copy( x86_oplist_t * list ) {
+ x86_oplist_t *ptr;
+ ptr = (x86_oplist_t *) calloc( sizeof(x86_oplist_t), 1 );
+ if ( ptr ) {
+ memcpy( &ptr->op, &list->op, sizeof(x86_op_t) );
+ }
+
+ return ptr;
+ }
+
+ x86_insn_t * x86_insn_new() {
+ x86_insn_t *insn = (x86_insn_t *)
+ calloc( sizeof(x86_insn_t), 1 );
+ return insn;
+ }
+
+ void x86_insn_free( x86_insn_t *insn ) {
+ x86_oplist_free( insn );
+ free( insn );
+ }
+%}
+
+%newobject x86_insn_copy;
+
+%inline %{
+ x86_insn_t * x86_insn_copy( x86_insn_t *src) {
+ x86_oplist_t *ptr, *list, *last = NULL;
+ x86_insn_t *insn = (x86_insn_t *)
+ calloc( sizeof(x86_insn_t), 1 );
+
+ if ( insn ) {
+ memcpy( insn, src, sizeof(x86_insn_t) );
+ insn->operands = NULL;
+ insn->block = NULL;
+ insn->function = NULL;
+
+ /* copy operand list */
+ for ( list = src->operands; list; list = list->next ) {
+ ptr = x86_op_list_node_copy( list );
+
+ if (! ptr ) {
+ continue;
+ }
+
+ if ( insn->operands ) {
+ last->next = ptr;
+ } else {
+ insn->operands = ptr;
+ }
+ last = ptr;
+ }
+ }
+
+ return insn;
+ }
+
+ x86_op_list * x86_insn_op_list( x86_insn_t *insn ) {
+ x86_oplist_t *list = insn->operands;
+ x86_op_list *op_list = x86_op_list_new();
+
+ for ( list = insn->operands; list; list = list->next ) {
+ x86_op_list_append( op_list, &list->op );
+ }
+
+ return op_list;
+ }
+
+ typedef struct x86_insn_list_node {
+ x86_insn_t *insn;
+ struct x86_insn_list_node *next, *prev;
+ } x86_insn_list_node;
+
+ typedef struct x86_insn_list {
+ size_t count;
+ x86_insn_list_node *head, *tail, *curr;
+ } x86_insn_list;
+
+%}
+
+%newobject x86_insn_list_new;
+
+%inline %{
+ x86_insn_list * x86_insn_list_new () {
+ x86_insn_list *list = (x86_insn_list *)
+ calloc( sizeof(x86_insn_list), 1 );
+ list->count = 0;
+ return list;
+ }
+
+ void x86_insn_list_free( x86_insn_list * list ) {
+ x86_insn_list_node *node, *next;
+
+ if (! list ) {
+ return;
+ }
+
+ node = list->head;
+ while ( node ) {
+ next = node->next;
+ /* free( node->insn ); */
+ free( node );
+ node = next;
+ }
+
+ free( list );
+ }
+
+ x86_insn_list_node * x86_insn_list_first( x86_insn_list *list ) {
+ if (! list ) {
+ return NULL;
+ }
+ return list->head;
+ }
+
+ x86_insn_list_node * x86_insn_list_last( x86_insn_list *list ) {
+ if (! list ) {
+ return NULL;
+ }
+ return list->tail;
+ }
+
+ x86_insn_list_node * x86_insn_list_next( x86_insn_list *list ) {
+ if (! list ) {
+ return NULL;
+ }
+ if (! list->curr ) {
+ list->curr = list->head;
+ return list->head;
+ }
+
+ list->curr = list->curr->next;
+ return list->curr;
+ }
+
+ x86_insn_list_node * x86_insn_list_prev( x86_insn_list *list ) {
+ if (! list ) {
+ return NULL;
+ }
+ if (! list->curr ) {
+ list->curr = list->tail;
+ return list->tail;
+ }
+
+ list->curr = list->curr->prev;
+ return list->curr;
+ }
+
+%}
+
+%newobject x86_insn_list_append;
+
+%inline %{
+ void x86_insn_list_append( x86_insn_list *list, x86_insn_t *insn ) {
+ x86_insn_list_node *node;
+ if (! list ) {
+ return;
+ }
+
+ node = (x86_insn_list_node *)
+ calloc( sizeof(x86_insn_list_node) , 1 );
+
+ if (! node ) {
+ return;
+ }
+
+ list->count++;
+ if ( ! list->tail ) {
+ list->head = list->tail = node;
+ } else {
+ list->tail->next = node;
+ node->prev = list->tail;
+ list->tail = node;
+ }
+
+ node->insn = x86_insn_copy( insn );
+ }
+
+ typedef struct {
+ enum x86_report_codes last_error;
+ void * last_error_data;
+ void * disasm_callback;
+ void * disasm_resolver;
+ } x86disasm;
+
+ void x86_default_reporter( enum x86_report_codes code,
+ void *data, void *arg ) {
+ x86disasm *dis = (x86disasm *) arg;
+ if ( dis ) {
+ dis->last_error = code;
+ dis->last_error_data = data;
+ }
+ }
+
+ void x86_default_callback( x86_insn_t *insn, void *arg ) {
+ x86_insn_list *list = (x86_insn_list *) arg;
+ if ( list ) {
+ x86_insn_list_append( list, insn );
+ }
+ }
+
+ /* TODO: resolver stack, maybe a callback */
+ long x86_default_resolver( x86_op_t *op, x86_insn_t *insn, void *arg ) {
+ x86disasm *dis = (x86disasm *) arg;
+ if ( dis ) {
+ //return dis->resolver( op, insn );
+ return 0;
+ }
+
+ return 0;
+ }
+
+
+%}
+
+%newobject x86disasm_new;
+
+%inline %{
+ x86disasm * x86disasm_new ( enum x86_options options ) {
+ x86disasm * dis = (x86disasm *)
+ calloc( sizeof( x86disasm ), 1 );
+ x86_init( options, x86_default_reporter, dis );
+ return dis;
+ }
+
+ void x86disasm_free( x86disasm * dis ) {
+ x86_cleanup();
+ free( dis );
+ }
+%}
+
+%newobject x86_disasm;
+
+%inline %{
+ x86_insn_t * disasm( unsigned char *buf, size_t buf_len,
+ unsigned long buf_rva, unsigned int offset ) {
+ x86_insn_t *insn = calloc( sizeof( x86_insn_t ), 1 );
+ x86_disasm( buf, buf_len, buf_rva, offset, insn );
+ return insn;
+ }
+
+ int disasm_range( unsigned char *buf, size_t buf_len,
+ unsigned long buf_rva, unsigned int offset,
+ unsigned int len ) {
+
+ x86_insn_list *list = x86_insn_list_new();
+
+ if ( len > buf_len ) {
+ len = buf_len;
+ }
+
+ return x86_disasm_range( buf, buf_rva, offset, len,
+ x86_default_callback, list );
+ }
+
+ int disasm_forward( unsigned char *buf, size_t buf_len,
+ unsigned long buf_rva, unsigned int offset ) {
+ x86_insn_list *list = x86_insn_list_new();
+
+ /* use default resolver: damn SWIG callbacks! */
+ return x86_disasm_forward( buf, buf_len, buf_rva, offset,
+ x86_default_callback, list,
+ x86_default_resolver, NULL );
+ }
+
+ size_t disasm_invariant( unsigned char *buf, size_t buf_len,
+ x86_invariant_t *inv ) {
+ return x86_invariant_disasm( buf, buf_len, inv );
+ }
+
+ size_t disasm_size( unsigned char *buf, size_t buf_len ) {
+ return x86_size_disasm( buf, buf_len );
+ }
+
+ int x86_max_operand_string( enum x86_asm_format format ) {
+ switch ( format ) {
+ case xml_syntax:
+ return MAX_OP_XML_STRING;
+ break;
+ case raw_syntax:
+ return MAX_OP_RAW_STRING;
+ break;
+ case native_syntax:
+ case intel_syntax:
+ case att_syntax:
+ case unknown_syntax:
+ default:
+ return MAX_OP_STRING;
+ break;
+ }
+ }
+
+
+ int x86_max_insn_string( enum x86_asm_format format ) {
+ switch ( format ) {
+ case xml_syntax:
+ return MAX_INSN_XML_STRING;
+ break;
+ case raw_syntax:
+ return MAX_INSN_RAW_STRING;
+ break;
+ case native_syntax:
+ case intel_syntax:
+ case att_syntax:
+ case unknown_syntax:
+ default:
+ return MAX_INSN_STRING;
+ break;
+ }
+ }
+
+ int x86_max_num_operands( ) { return MAX_NUM_OPERANDS; }
+%}
+
diff --git a/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/swig/libdisasm_oop.i b/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/swig/libdisasm_oop.i
new file mode 100644
index 0000000000..973a47e27b
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/swig/libdisasm_oop.i
@@ -0,0 +1,1114 @@
+%module x86disasm
+%{
+#ifdef _MSC_VER
+ typedef __int64 qword;
+#else
+ typedef long long qword;
+#endif
+
+#include <sys/types.h>
+
+#define MAX_REGNAME 8
+#define MAX_PREFIX_STR 32
+#define MAX_MNEM_STR 16
+#define MAX_INSN_SIZE 20
+#define MAX_OP_STRING 32
+#define MAX_OP_RAW_STRING 64
+#define MAX_OP_XML_STRING 256
+#define MAX_NUM_OPERANDS 8
+#define MAX_INSN_STRING 512
+#define MAX_INSN_RAW_STRING 1024
+#define MAX_INSN_XML_STRING 4096
+
+#include "../../../config.h"
+
+
+const char * version_string( void ) {
+ return PACKAGE_VERSION;
+}
+
+%}
+
+const char * version_string( void );
+
+%rename(X86_Register) x86_reg_t;
+%rename(X86_EAddr) x86_ea_t;
+%rename(X86_Operand) x86_op_t;
+//%rename(X86_OpList) x86_oplist_t;
+%rename(X86_Insn) x86_insn_t;
+%rename(X86_InvOperand) x86_invariant_op_t;
+%rename(X86_Invariant) x86_invariant_t;
+
+%include "carrays.i"
+
+%array_class( unsigned char, byteArray );
+
+
+%apply (unsigned char *STRING, int LENGTH) {
+ (unsigned char *buf, size_t buf_len)
+};
+
+
+%inline %{
+
+
+enum x86_asm_format {
+ unknown_syntax = 0, /* never use! */
+ native_syntax, /* header: 35 bytes */
+ intel_syntax, /* header: 23 bytes */
+ att_syntax, /* header: 23 bytes */
+ xml_syntax, /* header: 679 bytes */
+ raw_syntax /* header: 172 bytes */
+};
+%}
+
+/* ================================================================== */
+/* operand class */
+%inline %{
+ enum x86_reg_type {
+ reg_gen = 0x00001, reg_in = 0x00002,
+ reg_out = 0x00004, reg_local = 0x00008,
+ reg_fpu = 0x00010, reg_seg = 0x00020,
+ reg_simd = 0x00040, reg_sys = 0x00080,
+ reg_sp = 0x00100, reg_fp = 0x00200,
+ reg_pc = 0x00400, reg_retaddr = 0x00800,
+ reg_cond = 0x01000, reg_zero = 0x02000,
+ reg_ret = 0x04000, reg_src = 0x10000,
+ reg_dest = 0x20000, reg_count = 0x40000
+ };
+
+ typedef struct {
+ char name[MAX_REGNAME];
+ enum x86_reg_type type;
+ unsigned int size;
+ unsigned int id;
+ unsigned int alias;
+ unsigned int shift;
+ } x86_reg_t;
+
+ void x86_reg_from_id( unsigned int id, x86_reg_t * reg );
+
+ typedef struct {
+ unsigned int scale;
+ x86_reg_t index, base;
+ long disp;
+ char disp_sign;
+ char disp_size;
+ } x86_ea_t;
+
+ enum x86_op_type {
+ op_unused = 0,
+ op_register = 1,
+ op_immediate = 2,
+ op_relative_near = 3,
+ op_relative_far = 4,
+ op_absolute = 5,
+ op_expression = 6,
+ op_offset = 7,
+ op_unknown
+ };
+
+ enum x86_op_datatype {
+ op_byte = 1, op_word = 2,
+ op_dword = 3, op_qword = 4,
+ op_dqword = 5, op_sreal = 6,
+ op_dreal = 7, op_extreal = 8,
+ op_bcd = 9, op_ssimd = 10,
+ op_dsimd = 11, op_sssimd = 12,
+ op_sdsimd = 13, op_descr32 = 14,
+ op_descr16 = 15, op_pdescr32 = 16,
+ op_pdescr16 = 17, op_fpuenv = 18,
+ op_fpregset = 19,
+ };
+
+ enum x86_op_access {
+ op_read = 1,
+ op_write = 2,
+ op_execute = 4
+ };
+
+ enum x86_op_flags {
+ op_signed = 1, op_string = 2,
+ op_constant = 4, op_pointer = 8,
+ op_sysref = 0x010, op_implied = 0x020,
+ op_hardcode = 0x40, op_es_seg = 0x100,
+ op_cs_seg = 0x200, op_ss_seg = 0x300,
+ op_ds_seg = 0x400, op_fs_seg = 0x500,
+ op_gs_seg = 0x600
+ };
+
+ typedef struct {
+ enum x86_op_type type;
+ enum x86_op_datatype datatype;
+ enum x86_op_access access;
+ enum x86_op_flags flags;
+ union {
+ char sbyte;
+ short sword;
+ long sdword;
+ qword sqword;
+ unsigned char byte;
+ unsigned short word;
+ unsigned long dword;
+ qword qword;
+ float sreal;
+ double dreal;
+ unsigned char extreal[10];
+ unsigned char bcd[10];
+ qword dqword[2];
+ unsigned char simd[16];
+ unsigned char fpuenv[28];
+ void * address;
+ unsigned long offset;
+ x86_reg_t reg;
+ char relative_near;
+ long relative_far;
+ x86_ea_t expression;
+ } data;
+ void * insn;
+ } x86_op_t;
+
+ unsigned int x86_operand_size( x86_op_t *op );
+
+ int x86_format_operand(x86_op_t *op, char *buf, int len,
+ enum x86_asm_format format);
+%}
+
+%extend x86_reg_t{
+ x86_reg_t * aliased_reg( ) {
+ x86_reg_t * reg = (x86_reg_t * )
+ calloc( sizeof(x86_reg_t), 1 );
+ x86_reg_from_id( self->id, reg );
+ return reg;
+ }
+}
+
+%extend x86_op_t{
+ size_t size() {
+ return x86_operand_size( self );
+ }
+ char * format( enum x86_asm_format format ) {
+ char *buf, *str;
+ size_t len;
+
+ switch ( format ) {
+ case xml_syntax:
+ len = MAX_OP_XML_STRING;
+ break;
+ case raw_syntax:
+ len = MAX_OP_RAW_STRING;
+ break;
+ case native_syntax:
+ case intel_syntax:
+ case att_syntax:
+ case unknown_syntax:
+ default:
+ len = MAX_OP_STRING;
+ break;
+ }
+
+ buf = (char * ) calloc( len + 1, 1 );
+ x86_format_operand( self, buf, len, format );
+
+ /* drop buffer down to a reasonable size */
+ str = strdup( buf );
+ free(buf);
+ return str;
+ }
+
+ int is_address( ) {
+ if ( self->type == op_absolute ||
+ self->type == op_offset ) {
+ return 1;
+ }
+
+ return 0;
+ }
+
+ int is_relative( ) {
+ if ( self->type == op_relative_near ||
+ self->type == op_relative_far ) {
+ return 1;
+ }
+
+ return 0;
+ }
+
+ %newobject copy;
+ x86_op_t * copy() {
+ x86_op_t *op = (x86_op_t *) calloc( sizeof(x86_op_t), 1 );
+
+ if ( op ) {
+ memcpy( op, self, sizeof(x86_op_t) );
+ }
+
+ return op;
+ }
+}
+
+/* ================================================================== */
+/* operand list class */
+%inline %{
+ typedef struct X86_OpListNode {
+ x86_op_t *op;
+ struct X86_OpListNode *next, *prev;
+ } X86_OpListNode;
+
+ typedef struct X86_OpList {
+ size_t count;
+ X86_OpListNode *head, *tail, *curr;
+ } X86_OpList;
+%}
+
+%extend X86_OpList {
+ X86_OpList () {
+ X86_OpList *list = (X86_OpList *)
+ calloc( sizeof(X86_OpList), 1 );
+ list->count = 0;
+ return list;
+ }
+
+ ~X86_OpList() {
+ X86_OpListNode *node, *next;
+
+ node = self->head;
+ while ( node ) {
+ next = node->next;
+ /* free( node->insn ); */
+ free( node );
+ node = next;
+ }
+
+ free( self );
+ }
+
+ X86_OpListNode * first() {
+ self->curr = self->head;
+ return self->head;
+ }
+
+ X86_OpListNode * last() {
+ self->curr = self->tail;
+ return self->tail;
+ }
+
+ X86_OpListNode * next() {
+ if (! self->curr ) {
+ self->curr = self->head;
+ return self->head;
+ }
+
+ self->curr = self->curr->next;
+ return self->curr;
+ }
+
+ X86_OpListNode * prev() {
+ if (! self->curr ) {
+ self->curr = self->tail;
+ return self->tail;
+ }
+
+ self->curr = self->curr->prev;
+ return self->curr;
+ }
+
+ %newobject append;
+ void append( x86_op_t *op ) {
+ X86_OpListNode *node = (X86_OpListNode *)
+ calloc( sizeof(X86_OpListNode) , 1 );
+ if (! node ) {
+ return;
+ }
+
+ self->count++;
+ if ( ! self->tail ) {
+ self->head = self->tail = node;
+ } else {
+ self->tail->next = node;
+ node->prev = self->tail;
+ self->tail = node;
+ }
+
+ node->op = x86_op_t_copy( op );
+ }
+}
+
+%inline %{
+ typedef struct x86_operand_list {
+ x86_op_t op;
+ struct x86_operand_list *next;
+ } x86_oplist_t;
+%}
+
+%extend x86_oplist_t {
+ %newobject x86_oplist_node_copy;
+}
+
+/* ================================================================== */
+/* instruction class */
+%inline %{
+ x86_oplist_t * x86_oplist_node_copy( x86_oplist_t * list ) {
+ x86_oplist_t *ptr;
+ ptr = (x86_oplist_t *) calloc( sizeof(x86_oplist_t), 1 );
+ if ( ptr ) {
+ memcpy( &ptr->op, &list->op, sizeof(x86_op_t) );
+ }
+
+ return ptr;
+ }
+
+ enum x86_insn_group {
+ insn_none = 0, insn_controlflow = 1,
+ insn_arithmetic = 2, insn_logic = 3,
+ insn_stack = 4, insn_comparison = 5,
+ insn_move = 6, insn_string = 7,
+ insn_bit_manip = 8, insn_flag_manip = 9,
+ insn_fpu = 10, insn_interrupt = 13,
+ insn_system = 14, insn_other = 15
+ };
+
+ enum x86_insn_type {
+ insn_invalid = 0, insn_jmp = 0x1001,
+ insn_jcc = 0x1002, insn_call = 0x1003,
+ insn_callcc = 0x1004, insn_return = 0x1005,
+ insn_add = 0x2001, insn_sub = 0x2002,
+ insn_mul = 0x2003, insn_div = 0x2004,
+ insn_inc = 0x2005, insn_dec = 0x2006,
+ insn_shl = 0x2007, insn_shr = 0x2008,
+ insn_rol = 0x2009, insn_ror = 0x200A,
+ insn_and = 0x3001, insn_or = 0x3002,
+ insn_xor = 0x3003, insn_not = 0x3004,
+ insn_neg = 0x3005, insn_push = 0x4001,
+ insn_pop = 0x4002, insn_pushregs = 0x4003,
+ insn_popregs = 0x4004, insn_pushflags = 0x4005,
+ insn_popflags = 0x4006, insn_enter = 0x4007,
+ insn_leave = 0x4008, insn_test = 0x5001,
+ insn_cmp = 0x5002, insn_mov = 0x6001,
+ insn_movcc = 0x6002, insn_xchg = 0x6003,
+ insn_xchgcc = 0x6004, insn_strcmp = 0x7001,
+ insn_strload = 0x7002, insn_strmov = 0x7003,
+ insn_strstore = 0x7004, insn_translate = 0x7005,
+ insn_bittest = 0x8001, insn_bitset = 0x8002,
+ insn_bitclear = 0x8003, insn_clear_carry = 0x9001,
+ insn_clear_zero = 0x9002, insn_clear_oflow = 0x9003,
+ insn_clear_dir = 0x9004, insn_clear_sign = 0x9005,
+ insn_clear_parity = 0x9006, insn_set_carry = 0x9007,
+ insn_set_zero = 0x9008, insn_set_oflow = 0x9009,
+ insn_set_dir = 0x900A, insn_set_sign = 0x900B,
+ insn_set_parity = 0x900C, insn_tog_carry = 0x9010,
+ insn_tog_zero = 0x9020, insn_tog_oflow = 0x9030,
+ insn_tog_dir = 0x9040, insn_tog_sign = 0x9050,
+ insn_tog_parity = 0x9060, insn_fmov = 0xA001,
+ insn_fmovcc = 0xA002, insn_fneg = 0xA003,
+ insn_fabs = 0xA004, insn_fadd = 0xA005,
+ insn_fsub = 0xA006, insn_fmul = 0xA007,
+ insn_fdiv = 0xA008, insn_fsqrt = 0xA009,
+ insn_fcmp = 0xA00A, insn_fcos = 0xA00C,
+ insn_fldpi = 0xA00D, insn_fldz = 0xA00E,
+ insn_ftan = 0xA00F, insn_fsine = 0xA010,
+ insn_fsys = 0xA020, insn_int = 0xD001,
+ insn_intcc = 0xD002, insn_iret = 0xD003,
+ insn_bound = 0xD004, insn_debug = 0xD005,
+ insn_trace = 0xD006, insn_invalid_op = 0xD007,
+ insn_oflow = 0xD008, insn_halt = 0xE001,
+ insn_in = 0xE002, insn_out = 0xE003,
+ insn_cpuid = 0xE004, insn_nop = 0xF001,
+ insn_bcdconv = 0xF002, insn_szconv = 0xF003
+ };
+
+ enum x86_insn_note {
+ insn_note_ring0 = 1,
+ insn_note_smm = 2,
+ insn_note_serial = 4
+ };
+
+ enum x86_flag_status {
+ insn_carry_set = 0x1,
+ insn_zero_set = 0x2,
+ insn_oflow_set = 0x4,
+ insn_dir_set = 0x8,
+ insn_sign_set = 0x10,
+ insn_parity_set = 0x20,
+ insn_carry_or_zero_set = 0x40,
+ insn_zero_set_or_sign_ne_oflow = 0x80,
+ insn_carry_clear = 0x100,
+ insn_zero_clear = 0x200,
+ insn_oflow_clear = 0x400,
+ insn_dir_clear = 0x800,
+ insn_sign_clear = 0x1000,
+ insn_parity_clear = 0x2000,
+ insn_sign_eq_oflow = 0x4000,
+ insn_sign_ne_oflow = 0x8000
+ };
+
+ enum x86_insn_cpu {
+ cpu_8086 = 1, cpu_80286 = 2,
+ cpu_80386 = 3, cpu_80387 = 4,
+ cpu_80486 = 5, cpu_pentium = 6,
+ cpu_pentiumpro = 7, cpu_pentium2 = 8,
+ cpu_pentium3 = 9, cpu_pentium4 = 10,
+ cpu_k6 = 16, cpu_k7 = 32,
+ cpu_athlon = 48
+ };
+
+ enum x86_insn_isa {
+ isa_gp = 1, isa_fp = 2,
+ isa_fpumgt = 3, isa_mmx = 4,
+ isa_sse1 = 5, isa_sse2 = 6,
+ isa_sse3 = 7, isa_3dnow = 8,
+ isa_sys = 9
+ };
+
+ enum x86_insn_prefix {
+ insn_no_prefix = 0,
+ insn_rep_zero = 1,
+ insn_rep_notzero = 2,
+ insn_lock = 4
+ };
+
+
+ typedef struct {
+ unsigned long addr;
+ unsigned long offset;
+ enum x86_insn_group group;
+ enum x86_insn_type type;
+ enum x86_insn_note note;
+ unsigned char bytes[MAX_INSN_SIZE];
+ unsigned char size;
+ unsigned char addr_size;
+ unsigned char op_size;
+ enum x86_insn_cpu cpu;
+ enum x86_insn_isa isa;
+ enum x86_flag_status flags_set;
+ enum x86_flag_status flags_tested;
+ unsigned char stack_mod;
+ long stack_mod_val;
+ enum x86_insn_prefix prefix;
+ char prefix_string[MAX_PREFIX_STR];
+ char mnemonic[MAX_MNEM_STR];
+ x86_oplist_t *operands;
+ size_t operand_count;
+ size_t explicit_count;
+ void *block;
+ void *function;
+ int tag;
+ } x86_insn_t;
+
+ typedef void (*x86_operand_fn)(x86_op_t *op, x86_insn_t *insn,
+ void *arg);
+
+ enum x86_op_foreach_type {
+ op_any = 0,
+ op_dest = 1,
+ op_src = 2,
+ op_ro = 3,
+ op_wo = 4,
+ op_xo = 5,
+ op_rw = 6,
+ op_implicit = 0x10,
+ op_explicit = 0x20
+ };
+
+ size_t x86_operand_count( x86_insn_t *insn,
+ enum x86_op_foreach_type type );
+ x86_op_t * x86_operand_1st( x86_insn_t *insn );
+ x86_op_t * x86_operand_2nd( x86_insn_t *insn );
+ x86_op_t * x86_operand_3rd( x86_insn_t *insn );
+ long x86_get_rel_offset( x86_insn_t *insn );
+ x86_op_t * x86_get_branch_target( x86_insn_t *insn );
+ x86_op_t * x86_get_imm( x86_insn_t *insn );
+ unsigned char * x86_get_raw_imm( x86_insn_t *insn );
+ void x86_set_insn_addr( x86_insn_t *insn, unsigned long addr );
+ int x86_format_mnemonic(x86_insn_t *insn, char *buf, int len,
+ enum x86_asm_format format);
+ int x86_format_insn(x86_insn_t *insn, char *buf, int len,
+ enum x86_asm_format);
+ void x86_oplist_free( x86_insn_t *insn );
+ int x86_insn_is_valid( x86_insn_t *insn );
+%}
+
+%extend x86_insn_t {
+ x86_insn_t() {
+ x86_insn_t *insn = (x86_insn_t *)
+ calloc( sizeof(x86_insn_t), 1 );
+ return insn;
+ }
+ ~x86_insn_t() {
+ x86_oplist_free( self );
+ free( self );
+ }
+
+ int is_valid( ) {
+ return x86_insn_is_valid( self );
+ }
+
+ x86_op_t * operand_1st() {
+ return x86_operand_1st( self );
+ }
+
+ x86_op_t * operand_2nd() {
+ return x86_operand_2nd( self );
+ }
+
+ x86_op_t * operand_3rd() {
+ return x86_operand_3rd( self );
+ }
+
+ x86_op_t * operand_dest() {
+ return x86_operand_1st( self );
+ }
+
+ x86_op_t * operand_src() {
+ return x86_operand_2nd( self );
+ }
+
+ size_t num_operands( enum x86_op_foreach_type type ) {
+ return x86_operand_count( self, type );
+ }
+
+ long rel_offset() {
+ return x86_get_rel_offset( self );
+ }
+
+ x86_op_t * branch_target() {
+ return x86_get_branch_target( self );
+ }
+
+ x86_op_t * imm() {
+ return x86_get_imm( self );
+ }
+
+ unsigned char * raw_imm() {
+ return x86_get_raw_imm( self );
+ }
+
+ %newobject format;
+ char * format( enum x86_asm_format format ) {
+ char *buf, *str;
+ size_t len;
+
+ switch ( format ) {
+ case xml_syntax:
+ len = MAX_INSN_XML_STRING;
+ break;
+ case raw_syntax:
+ len = MAX_INSN_RAW_STRING;
+ break;
+ case native_syntax:
+ case intel_syntax:
+ case att_syntax:
+ case unknown_syntax:
+ default:
+ len = MAX_INSN_STRING;
+ break;
+ }
+
+ buf = (char * ) calloc( len + 1, 1 );
+ x86_format_insn( self, buf, len, format );
+
+ /* drop buffer down to a reasonable size */
+ str = strdup( buf );
+ free(buf);
+ return str;
+ }
+
+ %newobject format_mnemonic;
+ char * format_mnemonic( enum x86_asm_format format ) {
+ char *buf, *str;
+ size_t len = MAX_MNEM_STR + MAX_PREFIX_STR + 4;
+
+ buf = (char * ) calloc( len, 1 );
+ x86_format_mnemonic( self, buf, len, format );
+
+ /* drop buffer down to a reasonable size */
+ str = strdup( buf );
+ free(buf);
+
+ return str;
+ }
+
+ %newobject copy;
+ x86_insn_t * copy() {
+ x86_oplist_t *ptr, *list, *last = NULL;
+ x86_insn_t *insn = (x86_insn_t *)
+ calloc( sizeof(x86_insn_t), 1 );
+
+ if ( insn ) {
+ memcpy( insn, self, sizeof(x86_insn_t) );
+ insn->operands = NULL;
+ insn->block = NULL;
+ insn->function = NULL;
+
+ /* copy operand list */
+ for ( list = self->operands; list; list = list->next ) {
+ ptr = x86_oplist_node_copy( list );
+
+ if (! ptr ) {
+ continue;
+ }
+
+ if ( insn->operands ) {
+ last->next = ptr;
+ } else {
+ insn->operands = ptr;
+ }
+ last = ptr;
+ }
+ }
+
+ return insn;
+ }
+
+ X86_OpList * operand_list( ) {
+ x86_oplist_t *list = self->operands;
+ X86_OpList *op_list = new_X86_OpList();
+
+ for ( list = self->operands; list; list = list->next ) {
+ X86_OpList_append( op_list, &list->op );
+ }
+
+ return op_list;
+ }
+}
+
+/* ================================================================== */
+/* invariant instruction class */
+%inline %{
+ #define X86_WILDCARD_BYTE 0xF4
+
+ typedef struct {
+ enum x86_op_type type;
+ enum x86_op_datatype datatype;
+ enum x86_op_access access;
+ enum x86_op_flags flags;
+ } x86_invariant_op_t;
+
+ typedef struct {
+ unsigned char bytes[64];
+ unsigned int size;
+ enum x86_insn_group group;
+ enum x86_insn_type type;
+ x86_invariant_op_t operands[3];
+ } x86_invariant_t;
+%}
+
+%extend x86_invariant_t {
+
+ x86_invariant_t() {
+ x86_invariant_t *inv = (x86_invariant_t *)
+ calloc( sizeof(x86_invariant_t), 1 );
+ return inv;
+ }
+
+ ~x86_invariant_t() {
+ free( self );
+ }
+}
+
+/* ================================================================== */
+/* instruction list class */
+%inline %{
+ typedef struct X86_InsnListNode {
+ x86_insn_t *insn;
+ struct X86_InsnListNode *next, *prev;
+ } X86_InsnListNode;
+
+ typedef struct X86_InsnList {
+ size_t count;
+ X86_InsnListNode *head, *tail, *curr;
+ } X86_InsnList;
+%}
+
+%extend X86_InsnList {
+ X86_InsnList () {
+ X86_InsnList *list = (X86_InsnList *)
+ calloc( sizeof(X86_InsnList), 1 );
+ list->count = 0;
+ return list;
+ }
+
+ ~X86_InsnList() {
+ X86_InsnListNode *node, *next;
+
+ node = self->head;
+ while ( node ) {
+ next = node->next;
+ /* free( node->insn ); */
+ free( node );
+ node = next;
+ }
+
+ free( self );
+ }
+
+ X86_InsnListNode * first() { return self->head; }
+
+ X86_InsnListNode * last() { return self->tail; }
+
+ X86_InsnListNode * next() {
+ if (! self->curr ) {
+ self->curr = self->head;
+ return self->head;
+ }
+
+ self->curr = self->curr->next;
+ return self->curr;
+ }
+
+ X86_InsnListNode * prev() {
+ if (! self->curr ) {
+ self->curr = self->tail;
+ return self->tail;
+ }
+
+ self->curr = self->curr->prev;
+ return self->curr;
+ }
+
+ %newobject append;
+ void append( x86_insn_t *insn ) {
+ X86_InsnListNode *node = (X86_InsnListNode *)
+ calloc( sizeof(X86_InsnListNode) , 1 );
+ if (! node ) {
+ return;
+ }
+
+ self->count++;
+ if ( ! self->tail ) {
+ self->head = self->tail = node;
+ } else {
+ self->tail->next = node;
+ node->prev = self->tail;
+ self->tail = node;
+ }
+
+ node->insn = x86_insn_t_copy( insn );
+ }
+}
+
+/* ================================================================== */
+/* address table class */
+/* slight TODO */
+
+/* ================================================================== */
+/* Main disassembler class */
+%inline %{
+
+ enum x86_options {
+ opt_none= 0,
+ opt_ignore_nulls=1,
+ opt_16_bit=2
+ };
+ enum x86_report_codes {
+ report_disasm_bounds,
+ report_insn_bounds,
+ report_invalid_insn,
+ report_unknown
+ };
+
+
+ typedef struct {
+ enum x86_report_codes last_error;
+ void * last_error_data;
+ void * disasm_callback;
+ void * disasm_resolver;
+ } X86_Disasm;
+
+ typedef void (*DISASM_REPORTER)( enum x86_report_codes code,
+ void *data, void *arg );
+ typedef void (*DISASM_CALLBACK)( x86_insn_t *insn, void * arg );
+ typedef long (*DISASM_RESOLVER)( x86_op_t *op,
+ x86_insn_t * current_insn,
+ void *arg );
+
+ void x86_report_error( enum x86_report_codes code, void *data );
+ int x86_init( enum x86_options options, DISASM_REPORTER reporter,
+ void *arg);
+ void x86_set_reporter( DISASM_REPORTER reporter, void *arg);
+ void x86_set_options( enum x86_options options );
+ enum x86_options x86_get_options( void );
+ int x86_cleanup(void);
+ int x86_format_header( char *buf, int len, enum x86_asm_format format);
+ unsigned int x86_endian(void);
+ unsigned int x86_addr_size(void);
+ unsigned int x86_op_size(void);
+ unsigned int x86_word_size(void);
+ unsigned int x86_max_insn_size(void);
+ unsigned int x86_sp_reg(void);
+ unsigned int x86_fp_reg(void);
+ unsigned int x86_ip_reg(void);
+ size_t x86_invariant_disasm( unsigned char *buf, int buf_len,
+ x86_invariant_t *inv );
+ size_t x86_size_disasm( unsigned char *buf, unsigned int buf_len );
+ int x86_disasm( unsigned char *buf, unsigned int buf_len,
+ unsigned long buf_rva, unsigned int offset,
+ x86_insn_t * insn );
+ int x86_disasm_range( unsigned char *buf, unsigned long buf_rva,
+ unsigned int offset, unsigned int len,
+ DISASM_CALLBACK func, void *arg );
+ int x86_disasm_forward( unsigned char *buf, unsigned int buf_len,
+ unsigned long buf_rva, unsigned int offset,
+ DISASM_CALLBACK func, void *arg,
+ DISASM_RESOLVER resolver, void *r_arg );
+
+ void x86_default_reporter( enum x86_report_codes code,
+ void *data, void *arg ) {
+ X86_Disasm *dis = (X86_Disasm *) arg;
+ if ( dis ) {
+ dis->last_error = code;
+ dis->last_error_data = data;
+ }
+ }
+
+ void x86_default_callback( x86_insn_t *insn, void *arg ) {
+ X86_InsnList *list = (X86_InsnList *) arg;
+ if ( list ) {
+ X86_InsnList_append( list, insn );
+ }
+ }
+
+ /* TODO: resolver stack, maybe a callback */
+ long x86_default_resolver( x86_op_t *op, x86_insn_t *insn, void *arg ) {
+ X86_Disasm *dis = (X86_Disasm *) arg;
+ if ( dis ) {
+ //return dis->resolver( op, insn );
+ return 0;
+ }
+
+ return 0;
+ }
+
+%}
+
+%extend X86_Disasm {
+
+ X86_Disasm( ) {
+ X86_Disasm * dis = (X86_Disasm *)
+ calloc( sizeof( X86_Disasm ), 1 );
+ x86_init( opt_none, x86_default_reporter, dis );
+ return dis;
+ }
+
+ X86_Disasm( enum x86_options options ) {
+ X86_Disasm * dis = (X86_Disasm *)
+ calloc( sizeof( X86_Disasm ), 1 );
+ x86_init( options, x86_default_reporter, dis );
+ return dis;
+ }
+
+ X86_Disasm( enum x86_options options, DISASM_REPORTER reporter ) {
+ X86_Disasm * dis = (X86_Disasm *)
+ calloc( sizeof( X86_Disasm ), 1 );
+ x86_init( options, reporter, NULL );
+ return dis;
+ }
+
+ X86_Disasm( enum x86_options options, DISASM_REPORTER reporter,
+ void * arg ) {
+ X86_Disasm * dis = (X86_Disasm *)
+ calloc( sizeof( X86_Disasm ), 1 );
+ x86_init( options, reporter, arg );
+ return dis;
+ }
+
+ ~X86_Disasm() {
+ x86_cleanup();
+ free( self );
+ }
+
+ void set_options( enum x86_options options ) {
+ return x86_set_options( options );
+ }
+
+ enum x86_options options() {
+ return x86_get_options();
+ }
+
+ void set_callback( void * callback ) {
+ self->disasm_callback = callback;
+ }
+
+ void set_resolver( void * callback ) {
+ self->disasm_resolver = callback;
+ }
+
+ void report_error( enum x86_report_codes code ) {
+ x86_report_error( code, NULL );
+ }
+
+ %newobject disasm;
+ x86_insn_t * disasm( unsigned char *buf, size_t buf_len,
+ unsigned long buf_rva, unsigned int offset ) {
+ x86_insn_t *insn = calloc( sizeof( x86_insn_t ), 1 );
+ x86_disasm( buf, buf_len, buf_rva, offset, insn );
+ return insn;
+ }
+
+ int disasm_range( unsigned char *buf, size_t buf_len,
+ unsigned long buf_rva, unsigned int offset,
+ unsigned int len ) {
+
+ X86_InsnList *list = new_X86_InsnList();
+
+ if ( len > buf_len ) {
+ len = buf_len;
+ }
+
+ return x86_disasm_range( buf, buf_rva, offset, len,
+ x86_default_callback, list );
+ }
+
+ int disasm_forward( unsigned char *buf, size_t buf_len,
+ unsigned long buf_rva, unsigned int offset ) {
+ X86_InsnList *list = new_X86_InsnList();
+
+ /* use default resolver: damn SWIG callbacks! */
+ return x86_disasm_forward( buf, buf_len, buf_rva, offset,
+ x86_default_callback, list,
+ x86_default_resolver, NULL );
+ }
+
+ size_t disasm_invariant( unsigned char *buf, size_t buf_len,
+ x86_invariant_t *inv ) {
+ return x86_invariant_disasm( buf, buf_len, inv );
+ }
+
+ size_t disasm_size( unsigned char *buf, size_t buf_len ) {
+ return x86_size_disasm( buf, buf_len );
+ }
+
+ %newobject format_header;
+ char * format_header( enum x86_asm_format format) {
+ char *buf, *str;
+ size_t len;
+
+ switch ( format ) {
+ /* these were obtained from x86_format.c */
+ case xml_syntax:
+ len = 679; break;
+ case raw_syntax:
+ len = 172; break;
+ case native_syntax:
+ len = 35; break;
+ case intel_syntax:
+ len = 23; break;
+ case att_syntax:
+ len = 23; break;
+ case unknown_syntax:
+ default:
+ len = 23; break;
+ }
+
+ buf = (char * ) calloc( len + 1, 1 );
+ x86_format_header( buf, len, format );
+
+ return buf;
+ }
+
+ unsigned int endian() {
+ return x86_endian();
+ }
+
+ unsigned int addr_size() {
+ return x86_addr_size();
+ }
+
+ unsigned int op_size() {
+ return x86_op_size();
+ }
+
+ unsigned int word_size() {
+ return x86_word_size();
+ }
+
+ unsigned int max_insn_size() {
+ return x86_max_insn_size();
+ }
+
+ unsigned int sp_reg() {
+ return x86_sp_reg();
+ }
+
+ unsigned int fp_reg() {
+ return x86_fp_reg();
+ }
+
+ unsigned int ip_reg() {
+ return x86_ip_reg();
+ }
+
+ %newobject reg_from_id;
+ x86_reg_t * reg_from_id( unsigned int id ) {
+ x86_reg_t * reg = calloc( sizeof(x86_reg_t), 1 );
+ x86_reg_from_id( id, reg );
+ return reg;
+ }
+
+ unsigned char wildcard_byte() { return X86_WILDCARD_BYTE; }
+
+ int max_register_string() { return MAX_REGNAME; }
+
+ int max_prefix_string() { return MAX_PREFIX_STR; }
+
+ int max_mnemonic_string() { return MAX_MNEM_STR; }
+
+ int max_operand_string( enum x86_asm_format format ) {
+ switch ( format ) {
+ case xml_syntax:
+ return MAX_OP_XML_STRING;
+ break;
+ case raw_syntax:
+ return MAX_OP_RAW_STRING;
+ break;
+ case native_syntax:
+ case intel_syntax:
+ case att_syntax:
+ case unknown_syntax:
+ default:
+ return MAX_OP_STRING;
+ break;
+ }
+ }
+
+
+ int max_insn_string( enum x86_asm_format format ) {
+ switch ( format ) {
+ case xml_syntax:
+ return MAX_INSN_XML_STRING;
+ break;
+ case raw_syntax:
+ return MAX_INSN_RAW_STRING;
+ break;
+ case native_syntax:
+ case intel_syntax:
+ case att_syntax:
+ case unknown_syntax:
+ default:
+ return MAX_INSN_STRING;
+ break;
+ }
+ }
+
+ int max_num_operands( ) { return MAX_NUM_OPERANDS; }
+}
+
+/* python callback, per the manual */
+/*%typemap(python,in) PyObject *pyfunc {
+ if (!PyCallable_Check($source)) {
+ PyErr_SetString(PyExc_TypeError, "Need a callable object!");
+ return NULL;
+ }
+ $target = $source;
+}*/
+
+/* python FILE * callback, per the manual */
+/*
+%typemap(python,in) FILE * {
+ if (!PyFile_Check($source)) {
+ PyErr_SetString(PyExc_TypeError, "Need a file!");
+ return NULL;
+ }
+ $target = PyFile_AsFile($source);
+}*/
+
+
diff --git a/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/swig/perl/Makefile-swig b/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/swig/perl/Makefile-swig
new file mode 100644
index 0000000000..9f3a645733
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/swig/perl/Makefile-swig
@@ -0,0 +1,65 @@
+ifndef BASE_NAME
+BASE_NAME = x86disasm
+endif
+
+ifndef SWIG
+SWIG = swig # apt-get install swig !
+endif
+
+ifndef GCC
+GCC = gcc
+endif
+
+ifndef CC_FLAGS
+CC_FLAGS = -c -fPIC
+endif
+
+ifndef LD_FLAGS
+LD_FLAGS = -shared -L.. -ldisasm
+endif
+
+INTERFACE_FILE = libdisasm_oop.i
+
+SWIG_INTERFACE = ../$(INTERFACE_FILE)
+
+# PERL rules
+PERL_MOD = blib/arch/auto/$(BASE_NAME)/$(BASE_NAME).so
+PERL_SHADOW = $(BASE_NAME)_wrap.c
+PERL_SWIG = $(BASE_NAME).pl
+PERL_OBJ = $(BASE_NAME)_wrap.o
+PERL_INC = `perl -e 'use Config; print $$Config{archlib};'`/CORE
+PERL_CC_FLAGS = `perl -e 'use Config; print $$Config{ccflags};'`
+
+#====================================================
+# TARGETS
+
+all: swig-perl
+
+dummy: swig-perl install uninstall clean
+
+swig-perl: $(PERL_MOD)
+
+$(PERL_MOD): $(PERL_OBJ)
+ perl Makefile.PL
+ make
+ #$(GCC) $(LD_FLAGS) $(PERL_OBJ) -o $@
+
+$(PERL_OBJ): $(PERL_SHADOW)
+ $(GCC) $(CC_FLAGS) $(PERL_CC_FLAGS) -I$(PERL_INC) -o $@ $<
+
+$(PERL_SHADOW): $(SWIG_INTERFACE)
+ swig -perl -shadow -o $(PERL_SHADOW) -outdir . $<
+
+# ==================================================================
+install: $(PERL_MOD)
+ make install
+
+# ==================================================================
+uninstall:
+
+# ==================================================================
+clean:
+ rm $(PERL_MOD) $(PERL_OBJ)
+ rm $(PERL_SHADOW)
+ rm -rf Makefile blib pm_to_blib
+
diff --git a/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/swig/perl/Makefile.PL b/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/swig/perl/Makefile.PL
new file mode 100644
index 0000000000..6e625df182
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/swig/perl/Makefile.PL
@@ -0,0 +1,7 @@
+use ExtUtils::MakeMaker;
+
+WriteMakefile(
+ 'NAME' => 'x86disasm',
+ 'LIBS' => ['-ldisasm'],
+ 'OBJECT' => 'x86disasm_wrap.o'
+);
diff --git a/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/swig/python/Makefile-swig b/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/swig/python/Makefile-swig
new file mode 100644
index 0000000000..544681a13a
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/swig/python/Makefile-swig
@@ -0,0 +1,64 @@
+ifndef BASE_NAME
+BASE_NAME = x86disasm
+endif
+
+ifndef SWIG
+SWIG = swig # apt-get install swig !
+endif
+
+ifndef GCC
+GCC = gcc
+endif
+
+ifndef CC_FLAGS
+CC_FLAGS = -c -fPIC
+endif
+
+ifndef LD_FLAGS
+LD_FLAGS = -shared -L.. -ldisasm
+endif
+
+INTERFACE_FILE = libdisasm_oop.i
+
+SWIG_INTERFACE = ../$(INTERFACE_FILE)
+
+# PYTHON rules
+PYTHON_MOD = $(BASE_NAME)-python.so
+PYTHON_SHADOW = $(BASE_NAME)_wrap.c
+PYTHON_SWIG = $(BASE_NAME).py
+PYTHON_OBJ = $(BASE_NAME)_wrap.o
+PYTHON_INC = `/bin/echo -e 'import sys\nprint sys.prefix + "/include/python" + sys.version[:3]' | python`
+PYTHON_LIB = `/bin/echo -e 'import sys\nprint sys.prefix + "/lib/python" + sys.version[:3]' | python`
+PYTHON_DEST = $(PYTHON_LIB)/lib-dynload/_$(BASE_NAME).so
+
+#====================================================
+# TARGETS
+
+all: swig-python
+
+dummy: swig-python install uninstall clean
+
+swig-python: $(PYTHON_MOD)
+
+$(PYTHON_MOD): $(PYTHON_OBJ)
+ $(GCC) $(LD_FLAGS) $(PYTHON_OBJ) -o $@
+
+$(PYTHON_OBJ): $(PYTHON_SHADOW)
+ $(GCC) $(CC_FLAGS) -I$(PYTHON_INC) -I.. -o $@ $<
+
+$(PYTHON_SHADOW): $(SWIG_INTERFACE)
+ swig -python -shadow -o $(PYTHON_SHADOW) -outdir . $<
+
+# ==================================================================
+install: $(PYTHON_MOD)
+ sudo cp $(PYTHON_MOD) $(PYTHON_DEST)
+ sudo cp $(PYTHON_SWIG) $(PYTHON_LIB)
+
+# ==================================================================
+uninstall:
+
+# ==================================================================
+clean:
+ rm $(PYTHON_MOD) $(PYTHON_SWIG) $(PYTHON_OBJ)
+ rm $(PYTHON_SHADOW)
+
diff --git a/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/swig/ruby/Makefile-swig b/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/swig/ruby/Makefile-swig
new file mode 100644
index 0000000000..ee4800232c
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/swig/ruby/Makefile-swig
@@ -0,0 +1,68 @@
+ifndef BASE_NAME
+BASE_NAME = x86disasm
+endif
+
+ifndef SWIG
+SWIG = swig # apt-get install swig !
+endif
+
+ifndef GCC
+GCC = gcc
+endif
+
+ifndef CC_FLAGS
+CC_FLAGS = -c -fPIC
+endif
+
+ifndef LD_FLAGS
+LD_FLAGS = -shared -L../.. -ldisasm
+endif
+
+LIBDISASM_DIR = ../..
+
+INTERFACE_FILE = libdisasm_oop.i
+
+SWIG_INTERFACE = ../$(INTERFACE_FILE)
+
+# RUBY rules
+RUBY_MAKEFILE = Makefile
+RUBY_MOD = $(BASE_NAME).so
+RUBY_SHADOW = $(BASE_NAME)_wrap.c
+#RUBY_SWIG = $(BASE_NAME).rb
+RUBY_OBJ = $(BASE_NAME)_wrap.o
+RUBY_INC = `ruby -e 'puts $$:.join("\n")' | tail -2 | head -1`
+#RUBY_LIB =
+#RUBY_DEST =
+
+#====================================================
+# TARGETS
+
+all: swig-ruby
+
+dummy: swig-ruby install uninstall clean
+
+swig-ruby: $(RUBY_MOD)
+
+$(RUBY_MOD): $(RUBY_MAKEFILE)
+ make
+
+$(RUBY_MAKEFILE): $(RUBY_OBJ)
+ ruby extconf.rb
+
+$(RUBY_OBJ):$(RUBY_SHADOW)
+ $(GCC) $(CC_FLAGS) -I$(RUBY_INC) -I.. -o $@ $<
+
+$(RUBY_SHADOW): $(SWIG_INTERFACE)
+ swig -ruby -o $(RUBY_SHADOW) -outdir . $<
+
+# ==================================================================
+install: $(RUBY_MOD)
+ make install
+
+# ==================================================================
+uninstall:
+
+# ==================================================================
+clean:
+ make clean || true
+ rm $(RUBY_SHADOW) $(RUBY_MAKEFILE) $(RUBY_MOD) $(RUBY_OBJ)
diff --git a/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/swig/ruby/extconf.rb b/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/swig/ruby/extconf.rb
new file mode 100644
index 0000000000..4e74326435
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/swig/ruby/extconf.rb
@@ -0,0 +1,4 @@
+require 'mkmf'
+find_library('disasm', 'x86_init', "/usr/local/lib", "../..")
+create_makefile('x86disasm')
+
diff --git a/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/swig/tcl/Makefile-swig b/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/swig/tcl/Makefile-swig
new file mode 100644
index 0000000000..5145a82935
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/swig/tcl/Makefile-swig
@@ -0,0 +1,63 @@
+ifndef BASE_NAME
+BASE_NAME = x86disasm
+endif
+
+ifndef SWIG
+SWIG = swig # apt-get install swig !
+endif
+
+ifndef GCC
+GCC = gcc
+endif
+
+ifndef CC_FLAGS
+CC_FLAGS = -c -fPIC
+endif
+
+ifndef LD_FLAGS
+LD_FLAGS = -shared -L../.. -ldisasm
+endif
+
+INTERFACE_FILE = libdisasm.i
+
+SWIG_INTERFACE = ../$(INTERFACE_FILE)
+
+# TCL rules
+TCL_VERSION = 8.3
+TCL_MOD = $(BASE_NAME)-tcl.so
+TCL_SHADOW = $(BASE_NAME)_wrap.c
+TCL_OBJ = $(BASE_NAME)_wrap.o
+TCL_INC = /usr/include/tcl$(TCL_VERSION)
+TCL_LIB = /usr/lib/tcl$(TCL_VERSION)
+TCL_DEST = $(TCL_LIB)/$(BASE_NAME).so
+
+#====================================================
+# TARGETS
+
+all: swig-tcl
+
+dummy: swig-tcl install uninstall clean
+
+swig-tcl: $(TCL_MOD)
+
+$(TCL_MOD): $(TCL_OBJ)
+ $(GCC) $(LD_FLAGS) $(TCL_OBJ) -o $@
+
+$(TCL_OBJ): $(TCL_SHADOW)
+ $(GCC) $(CC_FLAGS) -I$(TCL_INC) -I.. -o $@ $<
+
+$(TCL_SHADOW): $(SWIG_INTERFACE)
+ swig -tcl -o $(TCL_SHADOW) -outdir . $<
+
+# ==================================================================
+install: $(TCL_MOD)
+ sudo cp $(TCL_MOD) $(TCL_DEST)
+
+# ==================================================================
+uninstall:
+
+# ==================================================================
+clean:
+ rm $(TCL_MOD) $(TCL_SWIG) $(TCL_OBJ)
+ rm $(TCL_SHADOW)
+
diff --git a/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/x86_disasm.c b/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/x86_disasm.c
new file mode 100644
index 0000000000..1b82f4e667
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/x86_disasm.c
@@ -0,0 +1,210 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "libdis.h"
+#include "ia32_insn.h"
+#include "ia32_invariant.h"
+#include "x86_operand_list.h"
+
+
+#ifdef _MSC_VER
+ #define snprintf _snprintf
+ #define inline __inline
+#endif
+
+unsigned int x86_disasm( unsigned char *buf, unsigned int buf_len,
+ uint32_t buf_rva, unsigned int offset,
+ x86_insn_t *insn ){
+ int len, size;
+ unsigned char bytes[MAX_INSTRUCTION_SIZE];
+
+ if ( ! buf || ! insn || ! buf_len ) {
+ /* caller screwed up somehow */
+ return 0;
+ }
+
+
+ /* ensure we are all NULLed up */
+ memset( insn, 0, sizeof(x86_insn_t) );
+ insn->addr = buf_rva + offset;
+ insn->offset = offset;
+ /* default to invalid insn */
+ insn->type = insn_invalid;
+ insn->group = insn_none;
+
+ if ( offset >= buf_len ) {
+ /* another caller screwup ;) */
+ x86_report_error(report_disasm_bounds, (void*)(long)(buf_rva+offset));
+ return 0;
+ }
+
+ len = buf_len - offset;
+
+ /* copy enough bytes for disassembly into buffer : this
+ * helps prevent buffer overruns at the end of a file */
+ memset( bytes, 0, MAX_INSTRUCTION_SIZE );
+ memcpy( bytes, &buf[offset], (len < MAX_INSTRUCTION_SIZE) ? len :
+ MAX_INSTRUCTION_SIZE );
+
+ /* actually do the disassembly */
+ /* TODO: allow switching when more disassemblers are added */
+ size = ia32_disasm_addr( bytes, len, insn);
+
+ /* check and see if we had an invalid instruction */
+ if (! size ) {
+ x86_report_error(report_invalid_insn, (void*)(long)(buf_rva+offset));
+ return 0;
+ }
+
+ /* check if we overran the end of the buffer */
+ if ( size > len ) {
+ x86_report_error( report_insn_bounds, (void*)(long)(buf_rva + offset));
+ MAKE_INVALID( insn, bytes );
+ return 0;
+ }
+
+ /* fill bytes field of insn */
+ memcpy( insn->bytes, bytes, size );
+
+ return size;
+}
+
+unsigned int x86_disasm_range( unsigned char *buf, uint32_t buf_rva,
+ unsigned int offset, unsigned int len,
+ DISASM_CALLBACK func, void *arg ) {
+ x86_insn_t insn;
+ unsigned int buf_len, size, count = 0, bytes = 0;
+
+ /* buf_len is implied by the arguments */
+ buf_len = len + offset;
+
+ while ( bytes < len ) {
+ size = x86_disasm( buf, buf_len, buf_rva, offset + bytes,
+ &insn );
+ if ( size ) {
+ /* invoke callback if it exists */
+ if ( func ) {
+ (*func)( &insn, arg );
+ }
+ bytes += size;
+ count ++;
+ } else {
+ /* error */
+ bytes++; /* try next byte */
+ }
+
+ x86_oplist_free( &insn );
+ }
+
+ return( count );
+}
+
+static inline int follow_insn_dest( x86_insn_t *insn ) {
+ if ( insn->type == insn_jmp || insn->type == insn_jcc ||
+ insn->type == insn_call || insn->type == insn_callcc ) {
+ return(1);
+ }
+ return(0);
+}
+
+static inline int insn_doesnt_return( x86_insn_t *insn ) {
+ return( (insn->type == insn_jmp || insn->type == insn_return) ? 1: 0 );
+}
+
+static int32_t internal_resolver( x86_op_t *op, x86_insn_t *insn ){
+ int32_t next_addr = -1;
+ if ( x86_optype_is_address(op->type) ) {
+ next_addr = op->data.sdword;
+ } else if ( op->type == op_relative_near ) {
+ next_addr = insn->addr + insn->size + op->data.relative_near;
+ } else if ( op->type == op_relative_far ) {
+ next_addr = insn->addr + insn->size + op->data.relative_far;
+ }
+ return( next_addr );
+}
+
+unsigned int x86_disasm_forward( unsigned char *buf, unsigned int buf_len,
+ uint32_t buf_rva, unsigned int offset,
+ DISASM_CALLBACK func, void *arg,
+ DISASM_RESOLVER resolver, void *r_arg ){
+ x86_insn_t insn;
+ x86_op_t *op;
+ int32_t next_addr;
+ uint32_t next_offset;
+ unsigned int size, count = 0, bytes = 0, cont = 1;
+
+ while ( cont && bytes < buf_len ) {
+ size = x86_disasm( buf, buf_len, buf_rva, offset + bytes,
+ &insn );
+
+ if ( size ) {
+ /* invoke callback if it exists */
+ if ( func ) {
+ (*func)( &insn, arg );
+ }
+ bytes += size;
+ count ++;
+ } else {
+ /* error */
+ bytes++; /* try next byte */
+ }
+
+ if ( follow_insn_dest(&insn) ) {
+ op = x86_get_dest_operand( &insn );
+ next_addr = -1;
+
+ /* if caller supplied a resolver, use it to determine
+ * the address to disassemble */
+ if ( resolver ) {
+ next_addr = resolver(op, &insn, r_arg);
+ } else {
+ next_addr = internal_resolver(op, &insn);
+ }
+
+ if (next_addr != -1 ) {
+ next_offset = next_addr - buf_rva;
+ /* if offset is in this buffer... */
+ if ( (uint32_t)next_addr >= buf_rva &&
+ next_offset < buf_len ) {
+ /* go ahead and disassemble */
+ count += x86_disasm_forward( buf,
+ buf_len,
+ buf_rva,
+ next_offset,
+ func, arg,
+ resolver, r_arg );
+ } else {
+ /* report unresolved address */
+ x86_report_error( report_disasm_bounds,
+ (void*)(long)next_addr );
+ }
+ }
+ } /* end follow_insn */
+
+ if ( insn_doesnt_return(&insn) ) {
+ /* stop disassembling */
+ cont = 0;
+ }
+
+ x86_oplist_free( &insn );
+ }
+ return( count );
+}
+
+/* invariant instruction representation */
+size_t x86_invariant_disasm( unsigned char *buf, int buf_len,
+ x86_invariant_t *inv ){
+ if (! buf || ! buf_len || ! inv ) {
+ return(0);
+ }
+
+ return ia32_disasm_invariant(buf, buf_len, inv);
+}
+size_t x86_size_disasm( unsigned char *buf, unsigned int buf_len ) {
+ if (! buf || ! buf_len ) {
+ return(0);
+ }
+
+ return ia32_disasm_size(buf, buf_len);
+}
diff --git a/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/x86_format.c b/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/x86_format.c
new file mode 100644
index 0000000000..0ec960dc8f
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/x86_format.c
@@ -0,0 +1,1430 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "libdis.h"
+#include <inttypes.h>
+
+#ifdef _MSC_VER
+ #define snprintf _snprintf
+ #define inline __inline
+#endif
+
+
+/*
+ * concatenation macros. STRNCATF concatenates a format string, buf
+ * only with one argument.
+ */
+#define STRNCAT( buf, str, len ) do { \
+ int _i = strlen(str), _blen = strlen(buf), _len = len - 1; \
+ if ( len ) { \
+ strncat( buf, str, _len ); \
+ if ( _len <= _i ) { \
+ buf[_blen+_len] = '\0'; \
+ len = 0; \
+ } else { \
+ len -= _i; \
+ } \
+ } \
+} while( 0 )
+
+#define STRNCATF( buf, fmt, data, len ) do { \
+ char _tmp[MAX_OP_STRING]; \
+ \
+ snprintf( _tmp, sizeof _tmp, fmt, data ); \
+ STRNCAT( buf, _tmp, len ); \
+} while( 0 )
+
+
+#define PRINT_DISPLACEMENT( ea ) do { \
+ if ( ea->disp_size && ea->disp ) { \
+ if ( ea->disp_sign ) { \
+ STRNCATF( buf, "-0x%" PRIX32, -ea->disp, len ); \
+ } else { \
+ STRNCATF( buf, "0x%" PRIX32, ea->disp, len ); \
+ } \
+ } \
+} while( 0 )
+
+static const char *prefix_strings[] = {
+ "", /* no prefix */
+ "repz ", /* the trailing spaces make it easy to prepend to mnemonic */
+ "repnz ",
+ "lock ",
+ "branch delay " /* unused in x86 */
+};
+
+static int format_insn_prefix_str( enum x86_insn_prefix prefix, char *buf,
+ int len ) {
+
+ int len_orig = len;
+
+ /* concat all prefix strings */
+ if ( prefix & 1 ) { STRNCAT( buf, prefix_strings[1], len ); }
+ if ( prefix & 2 ) { STRNCAT( buf, prefix_strings[2], len ); }
+ if ( prefix & 4 ) { STRNCAT( buf, prefix_strings[3], len ); }
+ if ( prefix & 8 ) { STRNCAT( buf, prefix_strings[4], len ); }
+
+ /* return the number of characters added */
+ return (len_orig - len);
+}
+
+/*
+ * sprint's an operand's data to string str.
+ */
+static void get_operand_data_str( x86_op_t *op, char *str, int len ){
+
+ if ( op->flags & op_signed ) {
+ switch ( op->datatype ) {
+ case op_byte:
+ snprintf( str, len, "%" PRId8, op->data.sbyte );
+ return;
+ case op_word:
+ snprintf( str, len, "%" PRId16, op->data.sword );
+ return;
+ case op_qword:
+ snprintf( str, len, "%" PRId64, op->data.sqword );
+ return;
+ default:
+ snprintf( str, len, "%" PRId32, op->data.sdword );
+ return;
+ }
+ }
+
+ //else
+ switch ( op->datatype ) {
+ case op_byte:
+ snprintf( str, len, "0x%02" PRIX8, op->data.byte );
+ return;
+ case op_word:
+ snprintf( str, len, "0x%04" PRIX16, op->data.word );
+ return;
+ case op_qword:
+ snprintf( str, len, "0x%08" PRIX64,op->data.sqword );
+ return;
+ default:
+ snprintf( str, len, "0x%08" PRIX32, op->data.dword );
+ return;
+ }
+}
+
+/*
+ * sprints register types to a string. the register types can be ORed
+ * together.
+ */
+static void get_operand_regtype_str( int regtype, char *str, int len )
+{
+ static struct {
+ const char *name;
+ int value;
+ } operand_regtypes[] = {
+ {"reg_gen" , 0x00001},
+ {"reg_in" , 0x00002},
+ {"reg_out" , 0x00004},
+ {"reg_local" , 0x00008},
+ {"reg_fpu" , 0x00010},
+ {"reg_seg" , 0x00020},
+ {"reg_simd" , 0x00040},
+ {"reg_sys" , 0x00080},
+ {"reg_sp" , 0x00100},
+ {"reg_fp" , 0x00200},
+ {"reg_pc" , 0x00400},
+ {"reg_retaddr", 0x00800},
+ {"reg_cond" , 0x01000},
+ {"reg_zero" , 0x02000},
+ {"reg_ret" , 0x04000},
+ {"reg_src" , 0x10000},
+ {"reg_dest" , 0x20000},
+ {"reg_count" , 0x40000},
+ {NULL, 0}, //end
+ };
+
+ unsigned int i;
+
+ memset( str, 0, len );
+
+ //go thru every type in the enum
+ for ( i = 0; operand_regtypes[i].name; i++ ) {
+ //skip if type is not set
+ if(! (regtype & operand_regtypes[i].value) )
+ continue;
+
+ //not the first time around
+ if( str[0] ) {
+ STRNCAT( str, " ", len );
+ }
+
+ STRNCAT(str, operand_regtypes[i].name, len );
+ }
+}
+
+static int format_expr( x86_ea_t *ea, char *buf, int len,
+ enum x86_asm_format format ) {
+ char str[MAX_OP_STRING];
+
+ if ( format == att_syntax ) {
+ if (ea->base.name[0] || ea->index.name[0] || ea->scale) {
+ PRINT_DISPLACEMENT(ea);
+ STRNCAT( buf, "(", len );
+
+ if ( ea->base.name[0]) {
+ STRNCATF( buf, "%%%s", ea->base.name, len );
+ }
+ if ( ea->index.name[0]) {
+ STRNCATF( buf, ",%%%s", ea->index.name, len );
+ if ( ea->scale > 1 ) {
+ STRNCATF( buf, ",%d", ea->scale, len );
+ }
+ }
+ /* handle the syntactic exception */
+ if ( ! ea->base.name[0] &&
+ ! ea->index.name[0] ) {
+ STRNCATF( buf, ",%d", ea->scale, len );
+ }
+
+ STRNCAT( buf, ")", len );
+ } else
+ STRNCATF( buf, "0x%" PRIX32, ea->disp, len );
+
+ } else if ( format == xml_syntax ){
+
+ if ( ea->base.name[0]) {
+ STRNCAT (buf, "\t\t\t<base>\n", len);
+
+ get_operand_regtype_str (ea->base.type, str,
+ sizeof str);
+ STRNCAT (buf, "\t\t\t\t<register ", len);
+ STRNCATF (buf, "name=\"%s\" ", ea->base.name, len);
+ STRNCATF (buf, "type=\"%s\" ", str, len);
+ STRNCATF (buf, "size=%d/>\n", ea->base.size, len);
+
+ STRNCAT (buf, "\t\t\t</base>\n", len);
+ }
+
+ if ( ea->index.name[0]) {
+ STRNCAT (buf, "\t\t\t<index>\n", len);
+
+ get_operand_regtype_str (ea->index.type, str,
+ sizeof str);
+
+ STRNCAT (buf, "\t\t\t\t<register ", len);
+ STRNCATF (buf, "name=\"%s\" ", ea->index.name, len);
+ STRNCATF (buf, "type=\"%s\" ", str, len);
+ STRNCATF (buf, "size=%d/>\n", ea->index.size, len);
+
+ STRNCAT (buf, "\t\t\t</index>\n", len);
+ }
+
+ //scale
+ STRNCAT (buf, "\t\t\t<scale>\n", len);
+ STRNCAT (buf, "\t\t\t\t<immediate ", len);
+ STRNCATF (buf, "value=\"%d\"/>\n", ea->scale, len);
+ STRNCAT (buf, "\t\t\t</scale>\n", len);
+
+ if ( ea->disp_size ) {
+
+ STRNCAT (buf, "\t\t\t<displacement>\n", len);
+
+ if ( ea->disp_size > 1 && ! ea->disp_sign ) {
+ STRNCAT (buf, "\t\t\t\t<address ", len);
+ STRNCATF (buf, "value=\"0x%" PRIX32 "\"/>\n", ea->disp,
+ len);
+ } else {
+ STRNCAT (buf, "\t\t\t\t<immediate ", len);
+ STRNCATF (buf, "value=%" PRId32 "/>\n", ea->disp, len);
+ }
+
+ STRNCAT (buf, "\t\t\t</displacement>\n", len);
+ }
+
+ } else if ( format == raw_syntax ) {
+
+ PRINT_DISPLACEMENT(ea);
+ STRNCAT( buf, "(", len );
+
+ STRNCATF( buf, "%s,", ea->base.name, len );
+ STRNCATF( buf, "%s,", ea->index.name, len );
+ STRNCATF( buf, "%d", ea->scale, len );
+ STRNCAT( buf, ")", len );
+
+ } else {
+
+ STRNCAT( buf, "[", len );
+
+ if ( ea->base.name[0] ) {
+ STRNCAT( buf, ea->base.name, len );
+ if ( ea->index.name[0] ||
+ (ea->disp_size && ! ea->disp_sign) ) {
+ STRNCAT( buf, "+", len );
+ }
+ }
+ if ( ea->index.name[0] ) {
+ STRNCAT( buf, ea->index.name, len );
+ if ( ea->scale > 1 )
+ {
+ STRNCATF( buf, "*%" PRId32, ea->scale, len );
+ }
+ if ( ea->disp_size && ! ea->disp_sign )
+ {
+ STRNCAT( buf, "+", len );
+ }
+ }
+
+ if ( ea->disp_size || (! ea->index.name[0] &&
+ ! ea->base.name[0] ) )
+ {
+ PRINT_DISPLACEMENT(ea);
+ }
+
+ STRNCAT( buf, "]", len );
+ }
+
+ return( strlen(buf) );
+}
+
+static int format_seg( x86_op_t *op, char *buf, int len,
+ enum x86_asm_format format ) {
+ int len_orig = len;
+ const char *reg = "";
+
+ if (! op || ! buf || ! len || ! op->flags) {
+ return(0);
+ }
+ if ( op->type != op_offset && op->type != op_expression ){
+ return(0);
+ }
+ if (! ((int) op->flags & 0xF00) ) {
+ return(0);
+ }
+
+ switch (op->flags & 0xF00) {
+ case op_es_seg: reg = "es"; break;
+ case op_cs_seg: reg = "cs"; break;
+ case op_ss_seg: reg = "ss"; break;
+ case op_ds_seg: reg = "ds"; break;
+ case op_fs_seg: reg = "fs"; break;
+ case op_gs_seg: reg = "gs"; break;
+ default:
+ break;
+ }
+
+ if (! reg[0] ) {
+ return( 0 );
+ }
+
+ switch( format ) {
+ case xml_syntax:
+ STRNCAT( buf, "\t\t\t<segment ", len );
+ STRNCATF( buf, "value=\"%s\"/>\n", reg, len );
+ break;
+ case att_syntax:
+ STRNCATF( buf, "%%%s:", reg, len );
+ break;
+
+ default:
+ STRNCATF( buf, "%s:", reg, len );
+ break;
+ }
+
+ return( len_orig - len ); /* return length of appended string */
+}
+
+static const char *get_operand_datatype_str( x86_op_t *op ){
+
+ static const char *types[] = {
+ "sbyte", /* 0 */
+ "sword",
+ "sqword",
+ "sdword",
+ "sdqword", /* 4 */
+ "byte",
+ "word",
+ "qword",
+ "dword", /* 8 */
+ "dqword",
+ "sreal",
+ "dreal",
+ "extreal", /* 12 */
+ "bcd",
+ "ssimd",
+ "dsimd",
+ "sssimd", /* 16 */
+ "sdsimd",
+ "descr32",
+ "descr16",
+ "pdescr32", /* 20 */
+ "pdescr16",
+ "bounds16",
+ "bounds32",
+ "fpu_env16",
+ "fpu_env32", /* 25 */
+ "fpu_state16",
+ "fpu_state32",
+ "fp_reg_set"
+ };
+
+ /* handle signed values first */
+ if ( op->flags & op_signed ) {
+ switch (op->datatype) {
+ case op_byte: return types[0];
+ case op_word: return types[1];
+ case op_qword: return types[2];
+ case op_dqword: return types[4];
+ default: return types[3];
+ }
+ }
+
+ switch (op->datatype) {
+ case op_byte: return types[5];
+ case op_word: return types[6];
+ case op_qword: return types[7];
+ case op_dqword: return types[9];
+ case op_sreal: return types[10];
+ case op_dreal: return types[11];
+ case op_extreal: return types[12];
+ case op_bcd: return types[13];
+ case op_ssimd: return types[14];
+ case op_dsimd: return types[15];
+ case op_sssimd: return types[16];
+ case op_sdsimd: return types[17];
+ case op_descr32: return types[18];
+ case op_descr16: return types[19];
+ case op_pdescr32: return types[20];
+ case op_pdescr16: return types[21];
+ case op_bounds16: return types[22];
+ case op_bounds32: return types[23];
+ case op_fpustate16: return types[24];
+ case op_fpustate32: return types[25];
+ case op_fpuenv16: return types[26];
+ case op_fpuenv32: return types[27];
+ case op_fpregset: return types[28];
+ default: return types[8];
+ }
+}
+
+static int format_insn_eflags_str( enum x86_flag_status flags, char *buf,
+ int len) {
+
+ static struct {
+ const char *name;
+ int value;
+ } insn_flags[] = {
+ { "carry_set ", 0x0001 },
+ { "zero_set ", 0x0002 },
+ { "oflow_set ", 0x0004 },
+ { "dir_set ", 0x0008 },
+ { "sign_set ", 0x0010 },
+ { "parity_set ", 0x0020 },
+ { "carry_or_zero_set ", 0x0040 },
+ { "zero_set_or_sign_ne_oflow ", 0x0080 },
+ { "carry_clear ", 0x0100 },
+ { "zero_clear ", 0x0200 },
+ { "oflow_clear ", 0x0400 },
+ { "dir_clear ", 0x0800 },
+ { "sign_clear ", 0x1000 },
+ { "parity_clear ", 0x2000 },
+ { "sign_eq_oflow ", 0x4000 },
+ { "sign_ne_oflow ", 0x8000 },
+ { NULL, 0x0000 }, //end
+ };
+
+ unsigned int i;
+ int len_orig = len;
+
+ for (i = 0; insn_flags[i].name; i++) {
+ if (! (flags & insn_flags[i].value) )
+ continue;
+
+ STRNCAT( buf, insn_flags[i].name, len );
+ }
+
+ return( len_orig - len );
+}
+
+static const char *get_insn_group_str( enum x86_insn_group gp ) {
+
+ static const char *types[] = {
+ "", // 0
+ "controlflow",// 1
+ "arithmetic", // 2
+ "logic", // 3
+ "stack", // 4
+ "comparison", // 5
+ "move", // 6
+ "string", // 7
+ "bit_manip", // 8
+ "flag_manip", // 9
+ "fpu", // 10
+ "", // 11
+ "", // 12
+ "interrupt", // 13
+ "system", // 14
+ "other", // 15
+ };
+
+ if ( gp > sizeof (types)/sizeof(types[0]) )
+ return "";
+
+ return types[gp];
+}
+
+static const char *get_insn_type_str( enum x86_insn_type type ) {
+
+ static struct {
+ const char *name;
+ int value;
+ } types[] = {
+ /* insn_controlflow */
+ { "jmp", 0x1001 },
+ { "jcc", 0x1002 },
+ { "call", 0x1003 },
+ { "callcc", 0x1004 },
+ { "return", 0x1005 },
+ { "loop", 0x1006 },
+ /* insn_arithmetic */
+ { "add", 0x2001 },
+ { "sub", 0x2002 },
+ { "mul", 0x2003 },
+ { "div", 0x2004 },
+ { "inc", 0x2005 },
+ { "dec", 0x2006 },
+ { "shl", 0x2007 },
+ { "shr", 0x2008 },
+ { "rol", 0x2009 },
+ { "ror", 0x200A },
+ /* insn_logic */
+ { "and", 0x3001 },
+ { "or", 0x3002 },
+ { "xor", 0x3003 },
+ { "not", 0x3004 },
+ { "neg", 0x3005 },
+ /* insn_stack */
+ { "push", 0x4001 },
+ { "pop", 0x4002 },
+ { "pushregs", 0x4003 },
+ { "popregs", 0x4004 },
+ { "pushflags", 0x4005 },
+ { "popflags", 0x4006 },
+ { "enter", 0x4007 },
+ { "leave", 0x4008 },
+ /* insn_comparison */
+ { "test", 0x5001 },
+ { "cmp", 0x5002 },
+ /* insn_move */
+ { "mov", 0x6001 }, /* move */
+ { "movcc", 0x6002 }, /* conditional move */
+ { "xchg", 0x6003 }, /* exchange */
+ { "xchgcc", 0x6004 }, /* conditional exchange */
+ /* insn_string */
+ { "strcmp", 0x7001 },
+ { "strload", 0x7002 },
+ { "strmov", 0x7003 },
+ { "strstore", 0x7004 },
+ { "translate", 0x7005 }, /* xlat */
+ /* insn_bit_manip */
+ { "bittest", 0x8001 },
+ { "bitset", 0x8002 },
+ { "bitclear", 0x8003 },
+ /* insn_flag_manip */
+ { "clear_carry", 0x9001 },
+ { "clear_zero", 0x9002 },
+ { "clear_oflow", 0x9003 },
+ { "clear_dir", 0x9004 },
+ { "clear_sign", 0x9005 },
+ { "clear_parity", 0x9006 },
+ { "set_carry", 0x9007 },
+ { "set_zero", 0x9008 },
+ { "set_oflow", 0x9009 },
+ { "set_dir", 0x900A },
+ { "set_sign", 0x900B },
+ { "set_parity", 0x900C },
+ { "tog_carry", 0x9010 },
+ { "tog_zero", 0x9020 },
+ { "tog_oflow", 0x9030 },
+ { "tog_dir", 0x9040 },
+ { "tog_sign", 0x9050 },
+ { "tog_parity", 0x9060 },
+ /* insn_fpu */
+ { "fmov", 0xA001 },
+ { "fmovcc", 0xA002 },
+ { "fneg", 0xA003 },
+ { "fabs", 0xA004 },
+ { "fadd", 0xA005 },
+ { "fsub", 0xA006 },
+ { "fmul", 0xA007 },
+ { "fdiv", 0xA008 },
+ { "fsqrt", 0xA009 },
+ { "fcmp", 0xA00A },
+ { "fcos", 0xA00C },
+ { "fldpi", 0xA00D },
+ { "fldz", 0xA00E },
+ { "ftan", 0xA00F },
+ { "fsine", 0xA010 },
+ { "fsys", 0xA020 },
+ /* insn_interrupt */
+ { "int", 0xD001 },
+ { "intcc", 0xD002 }, /* not present in x86 ISA */
+ { "iret", 0xD003 },
+ { "bound", 0xD004 },
+ { "debug", 0xD005 },
+ { "trace", 0xD006 },
+ { "invalid_op", 0xD007 },
+ { "oflow", 0xD008 },
+ /* insn_system */
+ { "halt", 0xE001 },
+ { "in", 0xE002 }, /* input from port/bus */
+ { "out", 0xE003 }, /* output to port/bus */
+ { "cpuid", 0xE004 },
+ /* insn_other */
+ { "nop", 0xF001 },
+ { "bcdconv", 0xF002 }, /* convert to or from BCD */
+ { "szconv", 0xF003 }, /* change size of operand */
+ { NULL, 0 }, //end
+ };
+
+ unsigned int i;
+
+ //go thru every type in the enum
+ for ( i = 0; types[i].name; i++ ) {
+ if ( types[i].value == type )
+ return types[i].name;
+ }
+
+ return "";
+}
+
+static const char *get_insn_cpu_str( enum x86_insn_cpu cpu ) {
+ static const char *intel[] = {
+ "", // 0
+ "8086", // 1
+ "80286", // 2
+ "80386", // 3
+ "80387", // 4
+ "80486", // 5
+ "Pentium", // 6
+ "Pentium Pro", // 7
+ "Pentium 2", // 8
+ "Pentium 3", // 9
+ "Pentium 4" // 10
+ };
+
+ if ( cpu < sizeof(intel)/sizeof(intel[0]) ) {
+ return intel[cpu];
+ } else if ( cpu == 16 ) {
+ return "K6";
+ } else if ( cpu == 32 ) {
+ return "K7";
+ } else if ( cpu == 48 ) {
+ return "Athlon";
+ }
+
+ return "";
+}
+
+static const char *get_insn_isa_str( enum x86_insn_isa isa ) {
+ static const char *subset[] = {
+ NULL, // 0
+ "General Purpose", // 1
+ "Floating Point", // 2
+ "FPU Management", // 3
+ "MMX", // 4
+ "SSE", // 5
+ "SSE2", // 6
+ "SSE3", // 7
+ "3DNow!", // 8
+ "System" // 9
+ };
+
+ if ( isa > sizeof (subset)/sizeof(subset[0]) ) {
+ return "";
+ }
+
+ return subset[isa];
+}
+
+static int format_operand_att( x86_op_t *op, x86_insn_t *insn, char *buf,
+ int len){
+
+ char str[MAX_OP_STRING];
+
+ memset (str, 0, sizeof str);
+
+ switch ( op->type ) {
+ case op_register:
+ STRNCATF( buf, "%%%s", op->data.reg.name, len );
+ break;
+
+ case op_immediate:
+ get_operand_data_str( op, str, sizeof str );
+ STRNCATF( buf, "$%s", str, len );
+ break;
+
+ case op_relative_near:
+ STRNCATF( buf, "0x%08X",
+ (unsigned int)(op->data.sbyte +
+ insn->addr + insn->size), len );
+ break;
+
+ case op_relative_far:
+ if (op->datatype == op_word) {
+ STRNCATF( buf, "0x%08X",
+ (unsigned int)(op->data.sword +
+ insn->addr + insn->size), len );
+ } else {
+ STRNCATF( buf, "0x%08X",
+ (unsigned int)(op->data.sdword +
+ insn->addr + insn->size), len );
+ }
+ break;
+
+ case op_absolute:
+ /* ATT uses the syntax $section, $offset */
+ STRNCATF( buf, "$0x%04" PRIX16 ", ", op->data.absolute.segment,
+ len );
+ if (op->datatype == op_descr16) {
+ STRNCATF( buf, "$0x%04" PRIX16,
+ op->data.absolute.offset.off16, len );
+ } else {
+ STRNCATF( buf, "$0x%08" PRIX32,
+ op->data.absolute.offset.off32, len );
+ }
+ break;
+ case op_offset:
+ /* ATT requires a '*' before JMP/CALL ops */
+ if (insn->type == insn_jmp || insn->type == insn_call)
+ STRNCAT( buf, "*", len );
+
+ len -= format_seg( op, buf, len, att_syntax );
+ STRNCATF( buf, "0x%08" PRIX32, op->data.sdword, len );
+ break;
+
+ case op_expression:
+ /* ATT requires a '*' before JMP/CALL ops */
+ if (insn->type == insn_jmp || insn->type == insn_call)
+ STRNCAT( buf, "*", len );
+
+ len -= format_seg( op, buf, len, att_syntax );
+ len -= format_expr( &op->data.expression, buf, len,
+ att_syntax );
+ break;
+ case op_unused:
+ case op_unknown:
+ /* return 0-truncated buffer */
+ break;
+ }
+
+ return ( strlen( buf ) );
+}
+
+static int format_operand_native( x86_op_t *op, x86_insn_t *insn, char *buf,
+ int len){
+
+ char str[MAX_OP_STRING];
+
+ switch (op->type) {
+ case op_register:
+ STRNCAT( buf, op->data.reg.name, len );
+ break;
+
+ case op_immediate:
+ get_operand_data_str( op, str, sizeof str );
+ STRNCAT( buf, str, len );
+ break;
+
+ case op_relative_near:
+ STRNCATF( buf, "0x%08" PRIX32,
+ (unsigned int)(op->data.sbyte +
+ insn->addr + insn->size), len );
+ break;
+
+ case op_relative_far:
+ if ( op->datatype == op_word ) {
+ STRNCATF( buf, "0x%08" PRIX32,
+ (unsigned int)(op->data.sword +
+ insn->addr + insn->size), len );
+ break;
+ } else {
+ STRNCATF( buf, "0x%08" PRIX32, op->data.sdword +
+ insn->addr + insn->size, len );
+ }
+ break;
+
+ case op_absolute:
+ STRNCATF( buf, "$0x%04" PRIX16 ":", op->data.absolute.segment,
+ len );
+ if (op->datatype == op_descr16) {
+ STRNCATF( buf, "0x%04" PRIX16,
+ op->data.absolute.offset.off16, len );
+ } else {
+ STRNCATF( buf, "0x%08" PRIX32,
+ op->data.absolute.offset.off32, len );
+ }
+ break;
+
+ case op_offset:
+ len -= format_seg( op, buf, len, native_syntax );
+ STRNCATF( buf, "[0x%08" PRIX32 "]", op->data.sdword, len );
+ break;
+
+ case op_expression:
+ len -= format_seg( op, buf, len, native_syntax );
+ len -= format_expr( &op->data.expression, buf, len,
+ native_syntax );
+ break;
+ case op_unused:
+ case op_unknown:
+ /* return 0-truncated buffer */
+ break;
+ }
+
+ return( strlen( buf ) );
+}
+
+static int format_operand_xml( x86_op_t *op, x86_insn_t *insn, char *buf,
+ int len){
+
+ char str[MAX_OP_STRING] = "\0";
+
+ switch (op->type) {
+ case op_register:
+
+ get_operand_regtype_str( op->data.reg.type, str,
+ sizeof str );
+
+ STRNCAT( buf, "\t\t<register ", len );
+ STRNCATF( buf, "name=\"%s\" ", op->data.reg.name, len );
+ STRNCATF( buf, "type=\"%s\" ", str, len );
+ STRNCATF( buf, "size=%d/>\n", op->data.reg.size, len );
+ break;
+
+ case op_immediate:
+
+ get_operand_data_str( op, str, sizeof str );
+
+ STRNCAT( buf, "\t\t<immediate ", len );
+ STRNCATF( buf, "type=\"%s\" ",
+ get_operand_datatype_str (op), len );
+ STRNCATF( buf, "value=\"%s\"/>\n", str, len );
+ break;
+
+ case op_relative_near:
+ STRNCAT( buf, "\t\t<relative_offset ", len );
+
+ STRNCATF( buf, "value=\"0x%08" PRIX32 "\"/>\n",
+ (unsigned int)(op->data.sbyte +
+ insn->addr + insn->size), len );
+ break;
+
+ case op_relative_far:
+ STRNCAT( buf, "\t\t<relative_offset ", len );
+
+ if (op->datatype == op_word) {
+ STRNCATF( buf, "value=\"0x%08" PRIX32 "\"/>\n",
+ (unsigned int)(op->data.sword +
+ insn->addr + insn->size), len);
+ break;
+ } else {
+
+ STRNCATF( buf, "value=\"0x%08" PRIX32 "\"/>\n",
+ op->data.sdword + insn->addr + insn->size,
+ len );
+ }
+ break;
+
+ case op_absolute:
+
+ STRNCATF( buf,
+ "\t\t<absolute_address segment=\"0x%04" PRIX16 "\"",
+ op->data.absolute.segment, len );
+
+ if (op->datatype == op_descr16) {
+ STRNCATF( buf, "offset=\"0x%04" PRIX16 "\">",
+ op->data.absolute.offset.off16, len );
+ } else {
+ STRNCATF( buf, "offset=\"0x%08" PRIX32 "\">",
+ op->data.absolute.offset.off32, len );
+ }
+
+ STRNCAT( buf, "\t\t</absolute_address>\n", len );
+ break;
+
+ case op_expression:
+
+
+ STRNCAT( buf, "\t\t<address_expression>\n", len );
+
+ len -= format_seg( op, buf, len, xml_syntax );
+ len -= format_expr( &op->data.expression, buf, len,
+ xml_syntax );
+
+ STRNCAT( buf, "\t\t</address_expression>\n", len );
+ break;
+
+ case op_offset:
+
+ STRNCAT( buf, "\t\t<segment_offset>\n", len );
+
+ len -= format_seg( op, buf, len, xml_syntax );
+
+ STRNCAT( buf, "\t\t\t<address ", len);
+ STRNCATF( buf, "value=\"0x%08" PRIX32 "\"/>\n",
+ op->data.sdword, len );
+ STRNCAT( buf, "\t\t</segment_offset>\n", len );
+ break;
+
+ case op_unused:
+ case op_unknown:
+ /* return 0-truncated buffer */
+ break;
+ }
+
+ return( strlen( buf ) );
+}
+
+static int format_operand_raw( x86_op_t *op, x86_insn_t *insn, char *buf,
+ int len){
+
+ char str[MAX_OP_RAW_STRING];
+ const char *datatype = get_operand_datatype_str(op);
+
+ switch (op->type) {
+ case op_register:
+
+ get_operand_regtype_str( op->data.reg.type, str,
+ sizeof str );
+
+ STRNCAT( buf, "reg|", len );
+ STRNCATF( buf, "%s|", datatype, len );
+ STRNCATF( buf, "%s:", op->data.reg.name, len );
+ STRNCATF( buf, "%s:", str, len );
+ STRNCATF( buf, "%d|", op->data.reg.size, len );
+ break;
+
+ case op_immediate:
+
+ get_operand_data_str( op, str, sizeof str );
+
+ STRNCAT( buf, "immediate|", len );
+ STRNCATF( buf, "%s|", datatype, len );
+ STRNCATF( buf, "%s|", str, len );
+ break;
+
+ case op_relative_near:
+ /* NOTE: in raw format, we print the
+ * relative offset, not the actual
+ * address of the jump target */
+
+ STRNCAT( buf, "relative|", len );
+ STRNCATF( buf, "%s|", datatype, len );
+ STRNCATF( buf, "%" PRId8 "|", op->data.sbyte, len );
+ break;
+
+ case op_relative_far:
+
+ STRNCAT( buf, "relative|", len );
+ STRNCATF( buf, "%s|", datatype, len );
+
+ if (op->datatype == op_word) {
+ STRNCATF( buf, "%" PRId16 "|", op->data.sword, len);
+ break;
+ } else {
+ STRNCATF( buf, "%" PRId32 "|", op->data.sdword, len );
+ }
+ break;
+
+ case op_absolute:
+
+ STRNCAT( buf, "absolute_address|", len );
+ STRNCATF( buf, "%s|", datatype, len );
+
+ STRNCATF( buf, "$0x%04" PRIX16 ":", op->data.absolute.segment,
+ len );
+ if (op->datatype == op_descr16) {
+ STRNCATF( buf, "0x%04" PRIX16 "|",
+ op->data.absolute.offset.off16, len );
+ } else {
+ STRNCATF( buf, "0x%08" PRIX32 "|",
+ op->data.absolute.offset.off32, len );
+ }
+
+ break;
+
+ case op_expression:
+
+ STRNCAT( buf, "address_expression|", len );
+ STRNCATF( buf, "%s|", datatype, len );
+
+ len -= format_seg( op, buf, len, native_syntax );
+ len -= format_expr( &op->data.expression, buf, len,
+ raw_syntax );
+
+ STRNCAT( buf, "|", len );
+ break;
+
+ case op_offset:
+
+ STRNCAT( buf, "segment_offset|", len );
+ STRNCATF( buf, "%s|", datatype, len );
+
+ len -= format_seg( op, buf, len, xml_syntax );
+
+ STRNCATF( buf, "%08" PRIX32 "|", op->data.sdword, len );
+ break;
+
+ case op_unused:
+ case op_unknown:
+ /* return 0-truncated buffer */
+ break;
+ }
+
+ return( strlen( buf ) );
+}
+
+int x86_format_operand( x86_op_t *op, char *buf, int len,
+ enum x86_asm_format format ){
+ x86_insn_t *insn;
+
+ if ( ! op || ! buf || len < 1 ) {
+ return(0);
+ }
+
+ /* insn is stored in x86_op_t since .21-pre3 */
+ insn = (x86_insn_t *) op->insn;
+
+ memset( buf, 0, len );
+
+ switch ( format ) {
+ case att_syntax:
+ return format_operand_att( op, insn, buf, len );
+ case xml_syntax:
+ return format_operand_xml( op, insn, buf, len );
+ case raw_syntax:
+ return format_operand_raw( op, insn, buf, len );
+ case native_syntax:
+ case intel_syntax:
+ default:
+ return format_operand_native( op, insn, buf, len );
+ }
+}
+
+#define is_imm_jmp(op) (op->type == op_absolute || \
+ op->type == op_immediate || \
+ op->type == op_offset)
+#define is_memory_op(op) (op->type == op_absolute || \
+ op->type == op_expression || \
+ op->type == op_offset)
+
+static int format_att_mnemonic( x86_insn_t *insn, char *buf, int len) {
+ int size = 0;
+ const char *suffix;
+
+ if (! insn || ! buf || ! len )
+ return(0);
+
+ memset( buf, 0, len );
+
+ /* do long jump/call prefix */
+ if ( insn->type == insn_jmp || insn->type == insn_call ) {
+ if (! is_imm_jmp( x86_operand_1st(insn) ) ||
+ (x86_operand_1st(insn))->datatype != op_byte ) {
+ /* far jump/call, use "l" prefix */
+ STRNCAT( buf, "l", len );
+ }
+ STRNCAT( buf, insn->mnemonic, len );
+
+ return ( strlen( buf ) );
+ }
+
+ /* do mnemonic */
+ STRNCAT( buf, insn->mnemonic, len );
+
+ /* do suffixes for memory operands */
+ if (!(insn->note & insn_note_nosuffix) &&
+ (insn->group == insn_arithmetic ||
+ insn->group == insn_logic ||
+ insn->group == insn_move ||
+ insn->group == insn_stack ||
+ insn->group == insn_string ||
+ insn->group == insn_comparison ||
+ insn->type == insn_in ||
+ insn->type == insn_out
+ )) {
+ if ( x86_operand_count( insn, op_explicit ) > 0 &&
+ is_memory_op( x86_operand_1st(insn) ) ){
+ size = x86_operand_size( x86_operand_1st( insn ) );
+ } else if ( x86_operand_count( insn, op_explicit ) > 1 &&
+ is_memory_op( x86_operand_2nd(insn) ) ){
+ size = x86_operand_size( x86_operand_2nd( insn ) );
+ }
+ }
+
+ if ( size == 1 ) suffix = "b";
+ else if ( size == 2 ) suffix = "w";
+ else if ( size == 4 ) suffix = "l";
+ else if ( size == 8 ) suffix = "q";
+ else suffix = "";
+
+ STRNCAT( buf, suffix, len );
+ return ( strlen( buf ) );
+}
+
+int x86_format_mnemonic(x86_insn_t *insn, char *buf, int len,
+ enum x86_asm_format format){
+ char str[MAX_OP_STRING];
+
+ memset( buf, 0, len );
+ STRNCAT( buf, insn->prefix_string, len );
+ if ( format == att_syntax ) {
+ format_att_mnemonic( insn, str, sizeof str );
+ STRNCAT( buf, str, len );
+ } else {
+ STRNCAT( buf, insn->mnemonic, len );
+ }
+
+ return( strlen( buf ) );
+}
+
+struct op_string { char *buf; size_t len; };
+
+static void format_op_raw( x86_op_t *op, x86_insn_t *insn, void *arg ) {
+ struct op_string * opstr = (struct op_string *) arg;
+
+ format_operand_raw(op, insn, opstr->buf, opstr->len);
+}
+
+static int format_insn_note(x86_insn_t *insn, char *buf, int len){
+ char note[32] = {0};
+ int len_orig = len, note_len = 32;
+
+ if ( insn->note & insn_note_ring0 ) {
+ STRNCATF( note, "%s", "Ring0 ", note_len );
+ }
+ if ( insn->note & insn_note_smm ) {
+ STRNCATF( note, "%s", "SMM ", note_len );
+ }
+ if ( insn->note & insn_note_serial ) {
+ STRNCATF(note, "%s", "Serialize ", note_len );
+ }
+ STRNCATF( buf, "%s|", note, len );
+
+ return( len_orig - len );
+}
+
+static int format_raw_insn( x86_insn_t *insn, char *buf, int len ){
+ struct op_string opstr = { buf, len };
+ int i;
+
+ /* RAW style:
+ * ADDRESS|OFFSET|SIZE|BYTES|
+ * PREFIX|PREFIX_STRING|GROUP|TYPE|NOTES|
+ * MNEMONIC|CPU|ISA|FLAGS_SET|FLAGS_TESTED|
+ * STACK_MOD|STACK_MOD_VAL
+ * [|OP_TYPE|OP_DATATYPE|OP_ACCESS|OP_FLAGS|OP]*
+ *
+ * Register values are encoded as:
+ * NAME:TYPE:SIZE
+ *
+ * Effective addresses are encoded as:
+ * disp(base_reg,index_reg,scale)
+ */
+ STRNCATF( buf, "0x%08" PRIX32 "|", insn->addr , len );
+ STRNCATF( buf, "0x%08" PRIX32 "|", insn->offset, len );
+ STRNCATF( buf, "%d|" , insn->size , len );
+
+ /* print bytes */
+ for ( i = 0; i < insn->size; i++ ) {
+ STRNCATF( buf, "%02X ", insn->bytes[i], len );
+ }
+ STRNCAT( buf, "|", len );
+
+ len -= format_insn_prefix_str( insn->prefix, buf, len );
+ STRNCATF( buf, "|%s|", insn->prefix_string , len );
+ STRNCATF( buf, "%s|", get_insn_group_str( insn->group ), len );
+ STRNCATF( buf, "%s|", get_insn_type_str( insn->type ) , len );
+ STRNCATF( buf, "%s|", insn->mnemonic , len );
+ STRNCATF( buf, "%s|", get_insn_cpu_str( insn->cpu ) , len );
+ STRNCATF( buf, "%s|", get_insn_isa_str( insn->isa ) , len );
+
+ /* insn note */
+ len -= format_insn_note( insn, buf, len );
+
+ len -= format_insn_eflags_str( insn->flags_set, buf, len );
+ STRNCAT( buf, "|", len );
+ len -= format_insn_eflags_str( insn->flags_tested, buf, len );
+ STRNCAT( buf, "|", len );
+ STRNCATF( buf, "%d|", insn->stack_mod, len );
+ STRNCATF( buf, "%" PRId32 "|", insn->stack_mod_val, len );
+
+ opstr.len = len;
+ x86_operand_foreach( insn, format_op_raw, &opstr, op_any );
+
+ return( strlen (buf) );
+}
+
+static int format_xml_insn( x86_insn_t *insn, char *buf, int len ) {
+ char str[MAX_OP_XML_STRING];
+ int i;
+
+ STRNCAT( buf, "<x86_insn>\n", len );
+
+ STRNCATF( buf, "\t<address rva=\"0x%08" PRIX32 "\" ", insn->addr, len );
+ STRNCATF( buf, "offset=\"0x%08" PRIX32 "\" ", insn->offset, len );
+ STRNCATF( buf, "size=%d bytes=\"", insn->size, len );
+
+ for ( i = 0; i < insn->size; i++ ) {
+ STRNCATF( buf, "%02X ", insn->bytes[i], len );
+ }
+ STRNCAT( buf, "\"/>\n", len );
+
+ STRNCAT( buf, "\t<prefix type=\"", len );
+ len -= format_insn_prefix_str( insn->prefix, buf, len );
+ STRNCATF( buf, "\" string=\"%s\"/>\n", insn->prefix_string, len );
+
+ STRNCATF( buf, "\t<mnemonic group=\"%s\" ",
+ get_insn_group_str (insn->group), len );
+ STRNCATF( buf, "type=\"%s\" ", get_insn_type_str (insn->type), len );
+ STRNCATF( buf, "string=\"%s\"/>\n", insn->mnemonic, len );
+
+ STRNCAT( buf, "\t<flags type=set>\n", len );
+ STRNCAT( buf, "\t\t<flag name=\"", len );
+ len -= format_insn_eflags_str( insn->flags_set, buf, len );
+ STRNCAT( buf, "\"/>\n\t</flags>\n", len );
+
+
+ STRNCAT( buf, "\t<flags type=tested>\n", len );
+ STRNCAT( buf, "\t\t<flag name=\"", len );
+ len -= format_insn_eflags_str( insn->flags_tested, buf, len );
+ STRNCAT( buf, "\"/>\n\t</flags>\n", len );
+
+ if ( x86_operand_1st( insn ) ) {
+ x86_format_operand( x86_operand_1st(insn), str,
+ sizeof str, xml_syntax);
+ STRNCAT( buf, "\t<operand name=dest>\n", len );
+ STRNCAT( buf, str, len );
+ STRNCAT( buf, "\t</operand>\n", len );
+ }
+
+ if ( x86_operand_2nd( insn ) ) {
+ x86_format_operand( x86_operand_2nd( insn ), str,
+ sizeof str, xml_syntax);
+ STRNCAT( buf, "\t<operand name=src>\n", len );
+ STRNCAT( buf, str, len );
+ STRNCAT( buf, "\t</operand>\n", len );
+ }
+
+ if ( x86_operand_3rd( insn ) ) {
+ x86_format_operand( x86_operand_3rd(insn), str,
+ sizeof str, xml_syntax);
+ STRNCAT( buf, "\t<operand name=imm>\n", len );
+ STRNCAT( buf, str, len );
+ STRNCAT( buf, "\t</operand>\n", len );
+ }
+
+ STRNCAT( buf, "</x86_insn>\n", len );
+
+ return strlen (buf);
+}
+
+int x86_format_header( char *buf, int len, enum x86_asm_format format ) {
+ switch (format) {
+ case att_syntax:
+ snprintf( buf, len, "MNEMONIC\tSRC, DEST, IMM" );
+ break;
+ case intel_syntax:
+ snprintf( buf, len, "MNEMONIC\tDEST, SRC, IMM" );
+ break;
+ case native_syntax:
+ snprintf( buf, len, "ADDRESS\tBYTES\tMNEMONIC\t"
+ "DEST\tSRC\tIMM" );
+ break;
+ case raw_syntax:
+ snprintf( buf, len, "ADDRESS|OFFSET|SIZE|BYTES|"
+ "PREFIX|PREFIX_STRING|GROUP|TYPE|NOTES|"
+ "MNEMONIC|CPU|ISA|FLAGS_SET|FLAGS_TESTED|"
+ "STACK_MOD|STACK_MOD_VAL"
+ "[|OP_TYPE|OP_DATATYPE|OP_ACCESS|OP_FLAGS|OP]*"
+ );
+ break;
+ case xml_syntax:
+ snprintf( buf, len,
+ "<x86_insn>"
+ "<address rva= offset= size= bytes=/>"
+ "<prefix type= string=/>"
+ "<mnemonic group= type= string= "
+ "cpu= isa= note= />"
+ "<flags type=set>"
+ "<flag name=>"
+ "</flags>"
+ "<stack_mod val= >"
+ "<flags type=tested>"
+ "<flag name=>"
+ "</flags>"
+ "<operand name=>"
+ "<register name= type= size=/>"
+ "<immediate type= value=/>"
+ "<relative_offset value=/>"
+ "<absolute_address value=>"
+ "<segment value=/>"
+ "</absolute_address>"
+ "<address_expression>"
+ "<segment value=/>"
+ "<base>"
+ "<register name= type= size=/>"
+ "</base>"
+ "<index>"
+ "<register name= type= size=/>"
+ "</index>"
+ "<scale>"
+ "<immediate value=/>"
+ "</scale>"
+ "<displacement>"
+ "<immediate value=/>"
+ "<address value=/>"
+ "</displacement>"
+ "</address_expression>"
+ "<segment_offset>"
+ "<address value=/>"
+ "</segment_offset>"
+ "</operand>"
+ "</x86_insn>"
+ );
+ break;
+ case unknown_syntax:
+ if ( len ) {
+ buf[0] = '\0';
+ }
+ break;
+ }
+
+ return( strlen(buf) );
+}
+
+int x86_format_insn( x86_insn_t *insn, char *buf, int len,
+ enum x86_asm_format format ){
+ char str[MAX_OP_STRING];
+ x86_op_t *src, *dst;
+ int i;
+
+ memset(buf, 0, len);
+ if ( format == intel_syntax ) {
+ /* INTEL STYLE: mnemonic dest, src, imm */
+ STRNCAT( buf, insn->prefix_string, len );
+ STRNCAT( buf, insn->mnemonic, len );
+ STRNCAT( buf, "\t", len );
+
+ /* dest */
+ if ( (dst = x86_operand_1st( insn )) && !(dst->flags & op_implied) ) {
+ x86_format_operand( dst, str, MAX_OP_STRING, format);
+ STRNCAT( buf, str, len );
+ }
+
+ /* src */
+ if ( (src = x86_operand_2nd( insn )) ) {
+ if ( !(dst->flags & op_implied) ) {
+ STRNCAT( buf, ", ", len );
+ }
+ x86_format_operand( src, str, MAX_OP_STRING, format);
+ STRNCAT( buf, str, len );
+ }
+
+ /* imm */
+ if ( x86_operand_3rd( insn )) {
+ STRNCAT( buf, ", ", len );
+ x86_format_operand( x86_operand_3rd( insn ),
+ str, MAX_OP_STRING, format);
+ STRNCAT( buf, str, len );
+ }
+
+ } else if ( format == att_syntax ) {
+ /* ATT STYLE: mnemonic src, dest, imm */
+ STRNCAT( buf, insn->prefix_string, len );
+ format_att_mnemonic(insn, str, MAX_OP_STRING);
+ STRNCATF( buf, "%s\t", str, len);
+
+
+ /* not sure which is correct? sometimes GNU as requires
+ * an imm as the first operand, sometimes as the third... */
+ /* imm */
+ if ( x86_operand_3rd( insn ) ) {
+ x86_format_operand(x86_operand_3rd( insn ),
+ str, MAX_OP_STRING, format);
+ STRNCAT( buf, str, len );
+ /* there is always 'dest' operand if there is 'src' */
+ STRNCAT( buf, ", ", len );
+ }
+
+ if ( (insn->note & insn_note_nonswap ) == 0 ) {
+ /* regular AT&T style swap */
+ src = x86_operand_2nd( insn );
+ dst = x86_operand_1st( insn );
+ }
+ else {
+ /* special-case instructions */
+ src = x86_operand_1st( insn );
+ dst = x86_operand_2nd( insn );
+ }
+
+ /* src */
+ if ( src ) {
+ x86_format_operand(src, str, MAX_OP_STRING, format);
+ STRNCAT( buf, str, len );
+ /* there is always 'dest' operand if there is 'src' */
+ if ( dst && !(dst->flags & op_implied) ) {
+ STRNCAT( buf, ", ", len );
+ }
+ }
+
+ /* dest */
+ if ( dst && !(dst->flags & op_implied) ) {
+ x86_format_operand( dst, str, MAX_OP_STRING, format);
+ STRNCAT( buf, str, len );
+ }
+
+
+ } else if ( format == raw_syntax ) {
+ format_raw_insn( insn, buf, len );
+ } else if ( format == xml_syntax ) {
+ format_xml_insn( insn, buf, len );
+ } else { /* default to native */
+ /* NATIVE style: RVA\tBYTES\tMNEMONIC\tOPERANDS */
+ /* print address */
+ STRNCATF( buf, "%08" PRIX32 "\t", insn->addr, len );
+
+ /* print bytes */
+ for ( i = 0; i < insn->size; i++ ) {
+ STRNCATF( buf, "%02X ", insn->bytes[i], len );
+ }
+
+ STRNCAT( buf, "\t", len );
+
+ /* print mnemonic */
+ STRNCAT( buf, insn->prefix_string, len );
+ STRNCAT( buf, insn->mnemonic, len );
+ STRNCAT( buf, "\t", len );
+
+ /* print operands */
+ /* dest */
+ if ( x86_operand_1st( insn ) ) {
+ x86_format_operand( x86_operand_1st( insn ),
+ str, MAX_OP_STRING, format);
+ STRNCATF( buf, "%s\t", str, len );
+ }
+
+ /* src */
+ if ( x86_operand_2nd( insn ) ) {
+ x86_format_operand(x86_operand_2nd( insn ),
+ str, MAX_OP_STRING, format);
+ STRNCATF( buf, "%s\t", str, len );
+ }
+
+ /* imm */
+ if ( x86_operand_3rd( insn )) {
+ x86_format_operand( x86_operand_3rd( insn ),
+ str, MAX_OP_STRING, format);
+ STRNCAT( buf, str, len );
+ }
+ }
+
+ return( strlen( buf ) );
+}
+
diff --git a/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/x86_imm.c b/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/x86_imm.c
new file mode 100644
index 0000000000..cd59bfc9ab
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/x86_imm.c
@@ -0,0 +1,70 @@
+#include "qword.h"
+#include "x86_imm.h"
+
+#include <stdio.h>
+
+unsigned int x86_imm_signsized( unsigned char * buf, size_t buf_len,
+ void *dest, unsigned int size ) {
+ signed char *cp = (signed char *) dest;
+ signed short *sp = (signed short *) dest;
+ int32_t *lp = (int32_t *) dest;
+ qword_t *qp = (qword_t *) dest;
+
+ if ( size > buf_len ) {
+ return 0;
+ }
+
+ /* Copy 'size' bytes from *buf to *op
+ * return number of bytes copied */
+ switch (size) {
+ case 1: /* BYTE */
+ *cp = *((signed char *) buf);
+ break;
+ case 2: /* WORD */
+ *sp = *((signed short *) buf);
+ break;
+ case 6:
+ case 8: /* QWORD */
+ *qp = *((qword_t *) buf);
+ break;
+ case 4: /* DWORD */
+ default:
+ *lp = *((int32_t *) buf);
+ break;
+ }
+ return (size);
+}
+
+unsigned int x86_imm_sized( unsigned char * buf, size_t buf_len, void *dest,
+ unsigned int size ) {
+ unsigned char *cp = (unsigned char *) dest;
+ unsigned short *sp = (unsigned short *) dest;
+ uint32_t *lp = (uint32_t *) dest;
+ qword_t *qp = (qword_t *) dest;
+
+ if ( size > buf_len ) {
+ return 0;
+ }
+
+ /* Copy 'size' bytes from *buf to *op
+ * return number of bytes copied */
+ switch (size) {
+ case 1: /* BYTE */
+ *cp = *((unsigned char *) buf);
+ break;
+ case 2: /* WORD */
+ *sp = *((unsigned short *) buf);
+ break;
+ case 6:
+ case 8: /* QWORD */
+ *qp = *((qword_t *) buf);
+ break;
+ case 4: /* DWORD */
+ default:
+ *lp = *((uint32_t *) buf);
+ break;
+ }
+
+ return (size);
+}
+
diff --git a/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/x86_imm.h b/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/x86_imm.h
new file mode 100644
index 0000000000..fa35ff2de4
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/x86_imm.h
@@ -0,0 +1,18 @@
+#ifndef x86_IMM_H
+#define x86_IMM_H
+
+#include "./qword.h"
+#include <sys/types.h>
+
+#ifdef WIN32
+#include <windows.h>
+#endif
+
+/* these are in the global x86 namespace but are not a part of the
+ * official API */
+unsigned int x86_imm_sized( unsigned char *buf, size_t buf_len, void *dest,
+ unsigned int size );
+
+unsigned int x86_imm_signsized( unsigned char *buf, size_t buf_len, void *dest,
+ unsigned int size );
+#endif
diff --git a/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/x86_insn.c b/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/x86_insn.c
new file mode 100644
index 0000000000..5649b89fb8
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/x86_insn.c
@@ -0,0 +1,182 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "libdis.h"
+
+#ifdef _MSC_VER
+ #define snprintf _snprintf
+ #define inline __inline
+#endif
+
+int x86_insn_is_valid( x86_insn_t *insn ) {
+ if ( insn && insn->type != insn_invalid && insn->size > 0 ) {
+ return 1;
+ }
+
+ return 0;
+}
+
+uint32_t x86_get_address( x86_insn_t *insn ) {
+ x86_oplist_t *op_lst;
+ if (! insn || ! insn->operands ) {
+ return 0;
+ }
+
+ for (op_lst = insn->operands; op_lst; op_lst = op_lst->next ) {
+ if ( op_lst->op.type == op_offset ) {
+ return op_lst->op.data.offset;
+ } else if ( op_lst->op.type == op_absolute ) {
+ if ( op_lst->op.datatype == op_descr16 ) {
+ return (uint32_t)
+ op_lst->op.data.absolute.offset.off16;
+ }
+ return op_lst->op.data.absolute.offset.off32;
+ }
+ }
+
+ return 0;
+}
+
+int32_t x86_get_rel_offset( x86_insn_t *insn ) {
+ x86_oplist_t *op_lst;
+ if (! insn || ! insn->operands ) {
+ return 0;
+ }
+
+ for (op_lst = insn->operands; op_lst; op_lst = op_lst->next ) {
+ if ( op_lst->op.type == op_relative_near ) {
+ return (int32_t) op_lst->op.data.relative_near;
+ } else if ( op_lst->op.type == op_relative_far ) {
+ return op_lst->op.data.relative_far;
+ }
+ }
+
+ return 0;
+}
+
+x86_op_t * x86_get_branch_target( x86_insn_t *insn ) {
+ x86_oplist_t *op_lst;
+ if (! insn || ! insn->operands ) {
+ return NULL;
+ }
+
+ for (op_lst = insn->operands; op_lst; op_lst = op_lst->next ) {
+ if ( op_lst->op.access & op_execute ) {
+ return &(op_lst->op);
+ }
+ }
+
+ return NULL;
+}
+x86_op_t * x86_get_imm( x86_insn_t *insn ) {
+ x86_oplist_t *op_lst;
+ if (! insn || ! insn->operands ) {
+ return NULL;
+ }
+
+ for (op_lst = insn->operands; op_lst; op_lst = op_lst->next ) {
+ if ( op_lst->op.type == op_immediate ) {
+ return &(op_lst->op);
+ }
+ }
+
+ return NULL;
+}
+
+#define IS_PROPER_IMM( x ) \
+ x->op.type == op_immediate && ! (x->op.flags & op_hardcode)
+
+
+/* if there is an immediate value in the instruction, return a pointer to
+ * it */
+unsigned char * x86_get_raw_imm( x86_insn_t *insn ) {
+ int size, offset;
+ x86_op_t *op = NULL;
+
+ if (! insn || ! insn->operands ) {
+ return(NULL);
+ }
+
+ /* a bit inelegant, but oh well... */
+ if ( IS_PROPER_IMM( insn->operands ) ) {
+ op = &insn->operands->op;
+ } else if ( insn->operands->next ) {
+ if ( IS_PROPER_IMM( insn->operands->next ) ) {
+ op = &insn->operands->next->op;
+ } else if ( insn->operands->next->next &&
+ IS_PROPER_IMM( insn->operands->next->next ) ) {
+ op = &insn->operands->next->next->op;
+ }
+ }
+
+ if (! op ) {
+ return( NULL );
+ }
+
+ /* immediate data is at the end of the insn */
+ size = x86_operand_size( op );
+ offset = insn->size - size;
+ return( &insn->bytes[offset] );
+}
+
+
+unsigned int x86_operand_size( x86_op_t *op ) {
+ switch (op->datatype ) {
+ case op_byte: return 1;
+ case op_word: return 2;
+ case op_dword: return 4;
+ case op_qword: return 8;
+ case op_dqword: return 16;
+ case op_sreal: return 4;
+ case op_dreal: return 8;
+ case op_extreal: return 10;
+ case op_bcd: return 10;
+ case op_ssimd: return 16;
+ case op_dsimd: return 16;
+ case op_sssimd: return 4;
+ case op_sdsimd: return 8;
+ case op_descr32: return 6;
+ case op_descr16: return 4;
+ case op_pdescr32: return 6;
+ case op_pdescr16: return 6;
+ case op_bounds16: return 4;
+ case op_bounds32: return 8;
+ case op_fpuenv16: return 14;
+ case op_fpuenv32: return 28;
+ case op_fpustate16: return 94;
+ case op_fpustate32: return 108;
+ case op_fpregset: return 512;
+ case op_fpreg: return 10;
+ case op_none: return 0;
+ }
+ return(4); /* default size */
+}
+
+void x86_set_insn_addr( x86_insn_t *insn, uint32_t addr ) {
+ if ( insn ) insn->addr = addr;
+}
+
+void x86_set_insn_offset( x86_insn_t *insn, unsigned int offset ){
+ if ( insn ) insn->offset = offset;
+}
+
+void x86_set_insn_function( x86_insn_t *insn, void * func ){
+ if ( insn ) insn->function = func;
+}
+
+void x86_set_insn_block( x86_insn_t *insn, void * block ){
+ if ( insn ) insn->block = block;
+}
+
+void x86_tag_insn( x86_insn_t *insn ){
+ if ( insn ) insn->tag = 1;
+}
+
+void x86_untag_insn( x86_insn_t *insn ){
+ if ( insn ) insn->tag = 0;
+}
+
+int x86_insn_is_tagged( x86_insn_t *insn ){
+ return insn->tag;
+}
+
diff --git a/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/x86_misc.c b/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/x86_misc.c
new file mode 100644
index 0000000000..3d2dd0ae8b
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/x86_misc.c
@@ -0,0 +1,71 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "libdis.h"
+#include "ia32_insn.h"
+#include "ia32_reg.h" /* for ia32_reg wrapper */
+#include "ia32_settings.h"
+extern ia32_settings_t ia32_settings;
+
+#ifdef _MSC_VER
+ #define snprintf _snprintf
+ #define inline __inline
+#endif
+
+
+/* =========================================================== INIT/TERM */
+static DISASM_REPORTER __x86_reporter_func = NULL;
+static void * __x86_reporter_arg = NULL;
+
+int x86_init( enum x86_options options, DISASM_REPORTER reporter, void * arg )
+{
+ ia32_settings.options = options;
+ __x86_reporter_func = reporter;
+ __x86_reporter_arg = arg;
+
+ return 1;
+}
+
+void x86_set_reporter( DISASM_REPORTER reporter, void * arg ) {
+ __x86_reporter_func = reporter;
+ __x86_reporter_arg = arg;
+}
+
+void x86_set_options( enum x86_options options ){
+ ia32_settings.options = options;
+}
+
+enum x86_options x86_get_options( void ) {
+ return ia32_settings.options;
+}
+
+int x86_cleanup( void )
+{
+ return 1;
+}
+
+/* =========================================================== ERRORS */
+void x86_report_error( enum x86_report_codes code, void *data ) {
+ if ( __x86_reporter_func ) {
+ (*__x86_reporter_func)(code, data, __x86_reporter_arg);
+ }
+}
+
+
+/* =========================================================== MISC */
+unsigned int x86_endian(void) { return ia32_settings.endian; }
+unsigned int x86_addr_size(void) { return ia32_settings.sz_addr; }
+unsigned int x86_op_size(void) { return ia32_settings.sz_oper; }
+unsigned int x86_word_size(void) { return ia32_settings.sz_word; }
+unsigned int x86_max_insn_size(void) { return ia32_settings.max_insn; }
+unsigned int x86_sp_reg(void) { return ia32_settings.id_sp_reg; }
+unsigned int x86_fp_reg(void) { return ia32_settings.id_fp_reg; }
+unsigned int x86_ip_reg(void) { return ia32_settings.id_ip_reg; }
+unsigned int x86_flag_reg(void) { return ia32_settings.id_flag_reg; }
+
+/* wrapper function to hide the IA32 register fn */
+void x86_reg_from_id( unsigned int id, x86_reg_t * reg ) {
+ ia32_handle_register( reg, id );
+ return;
+}
diff --git a/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/x86_operand_list.c b/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/x86_operand_list.c
new file mode 100644
index 0000000000..95409e0698
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/x86_operand_list.c
@@ -0,0 +1,191 @@
+#include <stdlib.h>
+#include "libdis.h"
+
+
+static void x86_oplist_append( x86_insn_t *insn, x86_oplist_t *op ) {
+ x86_oplist_t *list;
+
+ if (! insn ) {
+ return;
+ }
+
+ list = insn->operands;
+ if (! list ) {
+ insn->operand_count = 1;
+ /* Note that we have no way of knowing if this is an
+ * exlicit operand or not, since the caller fills
+ * the x86_op_t after we return. We increase the
+ * explicit count automatically, and ia32_insn_implicit_ops
+ * decrements it */
+ insn->explicit_count = 1;
+ insn->operands = op;
+ return;
+ }
+
+ /* get to end of list */
+ for ( ; list->next; list = list->next )
+ ;
+
+ insn->operand_count = insn->operand_count + 1;
+ insn->explicit_count = insn->explicit_count + 1;
+ list->next = op;
+
+ return;
+}
+
+x86_op_t * x86_operand_new( x86_insn_t *insn ) {
+ x86_oplist_t *op;
+
+ if (! insn ) {
+ return(NULL);
+ }
+ op = calloc( sizeof(x86_oplist_t), 1 );
+ op->op.insn = insn;
+ x86_oplist_append( insn, op );
+ return( &(op->op) );
+}
+
+void x86_oplist_free( x86_insn_t *insn ) {
+ x86_oplist_t *op, *list;
+
+ if (! insn ) {
+ return;
+ }
+
+ for ( list = insn->operands; list; ) {
+ op = list;
+ list = list->next;
+ free(op);
+ }
+
+ insn->operands = NULL;
+ insn->operand_count = 0;
+ insn->explicit_count = 0;
+
+ return;
+}
+
+/* ================================================== LIBDISASM API */
+/* these could probably just be #defines, but that means exposing the
+ enum... yet one more confusing thing in the API */
+int x86_operand_foreach( x86_insn_t *insn, x86_operand_fn func, void *arg,
+ enum x86_op_foreach_type type ){
+ x86_oplist_t *list;
+ char explicit = 1, implicit = 1;
+
+ if (! insn || ! func ) {
+ return 0;
+ }
+
+ /* note: explicit and implicit can be ORed together to
+ * allow an "all" limited by access type, even though the
+ * user is stupid to do this since it is default behavior :) */
+ if ( (type & op_explicit) && ! (type & op_implicit) ) {
+ implicit = 0;
+ }
+ if ( (type & op_implicit) && ! (type & op_explicit) ) {
+ explicit = 0;
+ }
+
+ type = type & 0x0F; /* mask out explicit/implicit operands */
+
+ for ( list = insn->operands; list; list = list->next ) {
+ if (! implicit && (list->op.flags & op_implied) ) {
+ /* operand is implicit */
+ continue;
+ }
+
+ if (! explicit && ! (list->op.flags & op_implied) ) {
+ /* operand is not implicit */
+ continue;
+ }
+
+ switch ( type ) {
+ case op_any:
+ break;
+ case op_dest:
+ if (! (list->op.access & op_write) ) {
+ continue;
+ }
+ break;
+ case op_src:
+ if (! (list->op.access & op_read) ) {
+ continue;
+ }
+ break;
+ case op_ro:
+ if (! (list->op.access & op_read) ||
+ (list->op.access & op_write ) ) {
+ continue;
+ }
+ break;
+ case op_wo:
+ if (! (list->op.access & op_write) ||
+ (list->op.access & op_read ) ) {
+ continue;
+ }
+ break;
+ case op_xo:
+ if (! (list->op.access & op_execute) ) {
+ continue;
+ }
+ break;
+ case op_rw:
+ if (! (list->op.access & op_write) ||
+ ! (list->op.access & op_read ) ) {
+ continue;
+ }
+ break;
+ case op_implicit: case op_explicit: /* make gcc happy */
+ break;
+ }
+ /* any non-continue ends up here: invoke the callback */
+ (*func)( &list->op, insn, arg );
+ }
+
+ return 1;
+}
+
+static void count_operand( x86_op_t *op, x86_insn_t *insn, void *arg ) {
+ size_t * count = (size_t *) arg;
+ *count = *count + 1;
+}
+
+size_t x86_operand_count( x86_insn_t *insn, enum x86_op_foreach_type type ) {
+ size_t count = 0;
+
+ /* save us a list traversal for common counts... */
+ if ( type == op_any ) {
+ return insn->operand_count;
+ } else if ( type == op_explicit ) {
+ return insn->explicit_count;
+ }
+
+ x86_operand_foreach( insn, count_operand, &count, type );
+ return count;
+}
+
+/* accessor functions */
+x86_op_t * x86_operand_1st( x86_insn_t *insn ) {
+ if (! insn->explicit_count ) {
+ return NULL;
+ }
+
+ return &(insn->operands->op);
+}
+
+x86_op_t * x86_operand_2nd( x86_insn_t *insn ) {
+ if ( insn->explicit_count < 2 ) {
+ return NULL;
+ }
+
+ return &(insn->operands->next->op);
+}
+
+x86_op_t * x86_operand_3rd( x86_insn_t *insn ) {
+ if ( insn->explicit_count < 3 ) {
+ return NULL;
+ }
+
+ return &(insn->operands->next->next->op);
+}
diff --git a/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/x86_operand_list.h b/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/x86_operand_list.h
new file mode 100644
index 0000000000..53668658ec
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/x86_operand_list.h
@@ -0,0 +1,8 @@
+#ifndef X86_OPERAND_LIST_H
+#define X86_OPERAND_LIST_H
+#include "libdis.h"
+
+
+x86_op_t * x86_operand_new( x86_insn_t *insn );
+
+#endif
diff --git a/toolkit/crashreporter/google-breakpad/src/third_party/lss/.gitignore b/toolkit/crashreporter/google-breakpad/src/third_party/lss/.gitignore
new file mode 100644
index 0000000000..4032eb05cb
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/third_party/lss/.gitignore
@@ -0,0 +1,3 @@
+*.o
+
+core
diff --git a/toolkit/crashreporter/google-breakpad/src/third_party/lss/README.md b/toolkit/crashreporter/google-breakpad/src/third_party/lss/README.md
new file mode 100644
index 0000000000..70cbc85311
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/third_party/lss/README.md
@@ -0,0 +1,137 @@
+# Linux Syscall Support (LSS)
+
+Every so often, projects need to directly embed Linux system calls instead of
+calling the implementations in the system runtime library.
+
+This project provides a header file that can be included into your application
+whenever you need to make direct system calls.
+
+The goal is to provide an API that generally mirrors the standard C library
+while still making direct syscalls. We try to hide some of the differences
+between arches when reasonably feasible. e.g. Newer architectures no longer
+provide an `open` syscall, but do provide `openat`. We will still expose a
+`sys_open` helper by default that calls into `openat` instead.
+
+We explicitly do not expose the raw syscall ABI including all of its historical
+warts to the user. We want people to be able to easily make a syscall, not have
+to worry that on some arches size args are swapped or they are shifted.
+
+Please be sure to review the Caveats section below however.
+
+## How to include linux\_syscall\_support.h in your project
+
+You can either copy the file into your project, or preferably, you can set up
+Git submodules to automatically pull from our source repository.
+
+## Supported targets
+
+The following architectures/ABIs have been tested (at some point) and should
+generally work. If you don't see your combo listed here, please double check
+the header itself as this list might be out of date.
+
+* x86 32-bit (i.e. i386, i486, i586, i686, Intel, AMD, etc...)
+* [x86_64 64-bit](https://en.wikipedia.org/wiki/X86-64) (i.e. x86-64, amd64, etc...)
+* [x32 32-bit](https://sites.google.com/site/x32abi/)
+* [ARM 32-bit](https://en.wikipedia.org/wiki/ARM_architecture) OABI
+* [ARM 32-bit](https://en.wikipedia.org/wiki/ARM_architecture) EABI (i.e. armv6, armv7, etc...)
+* AARCH64 64-bit (i.e. arm64, armv8, etc...)
+* PowerPC 32-bit (i.e. ppc, ppc32, etc...)
+* MIPS 32-bit o32 ABI
+* MIPS 32-bit n32 ABI
+* MIPS 64-bit n64 ABI
+
+## API
+
+By default, you can just add a `sys_` prefix to any function you want to call.
+So if you want to call `open(...)`, use `sys_open(...)` instead.
+
+### Knobs
+
+The linux\_syscall\_support.h header provides many knobs for you to control
+the exported API. These are all documented in the top of the header in a big
+comment block, so refer to that instead.
+
+## Caveats
+
+### ABI differences
+
+Some functions that the standard C library exposes use a different ABI than
+what the Linux kernel uses. Care must be taken when making syscalls directly
+that you use the right structure and flags. e.g. Most C libraries define a
+`struct stat` (commonly in `sys/stat.h` or `bits/stat.h`) that is different
+from the `struct stat` the kernel uses (commonly in `asm/stat.h`). If you use
+the wrong structure layout, then you can see errors like memory corruption or
+weird/shifted values. If you plan on making syscalls directly, you should
+focus on headers that are available under the `linux/` and `asm/` namespaces.
+
+Note: LSS provides structs for most of these cases. For `sys_stat()`, it
+provides `struct kernel_stat` for you to use.
+
+### Transparent backwards compatibility with older kernels
+
+While some C libraries (notably, glibc) take care to fallback to older syscalls
+when running on older kernels, there is no such support in LSS. If you plan on
+trying to run on older kernels, you will need to handle errors yourself (e.g.
+`ENOSYS` when using a too new syscall).
+
+Remember that this can happen with new flag bits too. e.g. The `O_CLOEXEC`
+flag was added to many syscalls, but if you try to run use it on older kernels,
+it will fail with `EINVAL`. In that case, you must handle the fallback logic
+yourself.
+
+### Variable arguments (varargs)
+
+We do not support vararg type functions. e.g. While the standard `open()`
+function can accept 2 or 3 arguments (with the mode field being optional),
+the `sys_open()` function always requires 3 arguments.
+
+## Bug reports & feature requests
+
+If you wish to report a problem or request a feature, please file them in our
+[bug tracker](https://bugs.chromium.org/p/linux-syscall-support/issues/).
+
+Please do not post patches to the tracker. Instead, see below for how to send
+patches to us directly.
+
+While we welcome feature requests, please keep in mind that it is unlikely that
+anyone will find time to implement them for you. Sending patches is strongly
+preferred and will often move things much faster.
+
+## Projects that use LSS
+
+* [Chromium](https://www.chromium.org/)
+* [Breakpad](https://chromium.googlesource.com/breakpad/breakpad)
+* [Native Client](https://developer.chrome.com/native-client), in nacl\_bootstrap.c
+
+## How to get an LSS change committed
+
+### Review
+
+You get your change reviewed, you can upload it to
+[Gerrit](https://chromium-review.googlesource.com/q/project:linux-syscall-support+status:open)
+using `git cl upload` from
+[Chromium's depot-tools](https://commondatastorage.googleapis.com/chrome-infra-docs/flat/depot_tools/docs/html/depot_tools_tutorial.html).
+
+### Testing
+
+Tests are found in the [tests/](./tests/) subdirectory. It does not (yet) offer
+100% coverage, but should grow over time.
+
+New commits that update/change/add syscall wrappers should include tests for
+them too. Consult the [test documentation](./tests/README.md) for more details.
+
+To run, just run `make` inside the tests directory. It will compile & execute
+the tests locally.
+
+There is some limited cross-compile coverage available if you run `make cross`.
+It only compiles things (does not execute at all).
+
+### Rolling into Chromium
+
+If you commit a change to LSS, please also commit a Chromium change to update
+`lss_revision` in
+[Chromium's DEPS](https://chromium.googlesource.com/chromium/src/+/master/DEPS)
+file.
+
+This ensures that the LSS change gets tested, so that people who commit later
+LSS changes don't run into problems with updating `lss_revision`.
diff --git a/toolkit/crashreporter/google-breakpad/src/third_party/lss/codereview.settings b/toolkit/crashreporter/google-breakpad/src/third_party/lss/codereview.settings
new file mode 100644
index 0000000000..b5082e8d30
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/third_party/lss/codereview.settings
@@ -0,0 +1,5 @@
+# This file is used by git cl to get repository specific information.
+CC_LIST: chromium-reviews@chromium.org,mseaborn@chromium.org
+CODE_REVIEW_SERVER: codereview.chromium.org
+GERRIT_HOST: True
+VIEW_VC: https://chromium.googlesource.com/linux-syscall-support/+/
diff --git a/toolkit/crashreporter/google-breakpad/src/third_party/lss/linux_syscall_support.h b/toolkit/crashreporter/google-breakpad/src/third_party/lss/linux_syscall_support.h
new file mode 100644
index 0000000000..1abe0ba5b0
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/third_party/lss/linux_syscall_support.h
@@ -0,0 +1,4553 @@
+/* Copyright (c) 2005-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: Markus Gutschke
+ */
+
+/* This file includes Linux-specific support functions common to the
+ * coredumper and the thread lister; primarily, this is a collection
+ * of direct system calls, and a couple of symbols missing from
+ * standard header files.
+ * There are a few options that the including file can set to control
+ * the behavior of this file:
+ *
+ * SYS_CPLUSPLUS:
+ * The entire header file will normally be wrapped in 'extern "C" { }",
+ * making it suitable for compilation as both C and C++ source. If you
+ * do not want to do this, you can set the SYS_CPLUSPLUS macro to inhibit
+ * the wrapping. N.B. doing so will suppress inclusion of all prerequisite
+ * system header files, too. It is the caller's responsibility to provide
+ * the necessary definitions.
+ *
+ * SYS_ERRNO:
+ * All system calls will update "errno" unless overriden by setting the
+ * SYS_ERRNO macro prior to including this file. SYS_ERRNO should be
+ * an l-value.
+ *
+ * SYS_INLINE:
+ * New symbols will be defined "static inline", unless overridden by
+ * the SYS_INLINE macro.
+ *
+ * SYS_LINUX_SYSCALL_SUPPORT_H
+ * This macro is used to avoid multiple inclusions of this header file.
+ * If you need to include this file more than once, make sure to
+ * unset SYS_LINUX_SYSCALL_SUPPORT_H before each inclusion.
+ *
+ * SYS_PREFIX:
+ * New system calls will have a prefix of "sys_" unless overridden by
+ * the SYS_PREFIX macro. Valid values for this macro are [0..9] which
+ * results in prefixes "sys[0..9]_". It is also possible to set this
+ * macro to -1, which avoids all prefixes.
+ *
+ * SYS_SYSCALL_ENTRYPOINT:
+ * Some applications (such as sandboxes that filter system calls), need
+ * to be able to run custom-code each time a system call is made. If this
+ * macro is defined, it expands to the name of a "common" symbol. If
+ * this symbol is assigned a non-NULL pointer value, it is used as the
+ * address of the system call entrypoint.
+ * A pointer to this symbol can be obtained by calling
+ * get_syscall_entrypoint()
+ *
+ * This file defines a few internal symbols that all start with "LSS_".
+ * Do not access these symbols from outside this file. They are not part
+ * of the supported API.
+ */
+#ifndef SYS_LINUX_SYSCALL_SUPPORT_H
+#define SYS_LINUX_SYSCALL_SUPPORT_H
+
+/* We currently only support x86-32, x86-64, ARM, MIPS, PPC, s390 and s390x
+ * on Linux.
+ * Porting to other related platforms should not be difficult.
+ */
+#if (defined(__i386__) || defined(__x86_64__) || defined(__ARM_ARCH_3__) || \
+ defined(__mips__) || defined(__PPC__) || defined(__ARM_EABI__) || \
+ defined(__aarch64__) || defined(__s390__)) \
+ && (defined(__linux) || defined(__ANDROID__))
+
+#ifndef SYS_CPLUSPLUS
+#ifdef __cplusplus
+/* Some system header files in older versions of gcc neglect to properly
+ * handle being included from C++. As it appears to be harmless to have
+ * multiple nested 'extern "C"' blocks, just add another one here.
+ */
+extern "C" {
+#endif
+
+#include <errno.h>
+#include <fcntl.h>
+#include <sched.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+#include <sys/ptrace.h>
+#include <sys/resource.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/syscall.h>
+#include <unistd.h>
+#include <linux/unistd.h>
+#include <endian.h>
+
+#ifdef __mips__
+/* Include definitions of the ABI currently in use. */
+#ifdef __ANDROID__
+/* Android doesn't have sgidefs.h, but does have asm/sgidefs.h,
+ * which has the definitions we need.
+ */
+#include <asm/sgidefs.h>
+#else
+#include <sgidefs.h>
+#endif
+#endif
+#endif
+
+/* Some libcs, for example Android NDK and musl, #define these
+ * macros as aliases to their non-64 counterparts. To avoid naming
+ * conflict, remove them.
+ *
+ * These are restored by the corresponding #pragma pop_macro near
+ * the end of this file.
+ */
+#pragma push_macro("stat64")
+#pragma push_macro("fstat64")
+#pragma push_macro("lstat64")
+#pragma push_macro("pread64")
+#pragma push_macro("pwrite64")
+#pragma push_macro("getdents64")
+#undef stat64
+#undef fstat64
+#undef lstat64
+#undef pread64
+#undef pwrite64
+#undef getdents64
+
+#if defined(__ANDROID__) && defined(__x86_64__)
+// A number of x86_64 syscalls are blocked by seccomp on recent Android;
+// undefine them so that modern alternatives will be used instead where
+// possible.
+// The alternative syscalls have been sanity checked against linux-3.4+;
+// older versions might not work.
+# undef __NR_getdents
+# undef __NR_dup2
+# undef __NR_fork
+# undef __NR_getpgrp
+# undef __NR_open
+# undef __NR_poll
+# undef __NR_readlink
+# undef __NR_stat
+# undef __NR_unlink
+# undef __NR_pipe
+#endif
+
+#if defined(__ANDROID__)
+// waitpid is blocked by seccomp on all architectures on recent Android.
+# undef __NR_waitpid
+#endif
+
+/* As glibc often provides subtly incompatible data structures (and implicit
+ * wrapper functions that convert them), we provide our own kernel data
+ * structures for use by the system calls.
+ * These structures have been developed by using Linux 2.6.23 headers for
+ * reference. Note though, we do not care about exact API compatibility
+ * with the kernel, and in fact the kernel often does not have a single
+ * API that works across architectures. Instead, we try to mimic the glibc
+ * API where reasonable, and only guarantee ABI compatibility with the
+ * kernel headers.
+ * Most notably, here are a few changes that were made to the structures
+ * defined by kernel headers:
+ *
+ * - we only define structures, but not symbolic names for kernel data
+ * types. For the latter, we directly use the native C datatype
+ * (i.e. "unsigned" instead of "mode_t").
+ * - in a few cases, it is possible to define identical structures for
+ * both 32bit (e.g. i386) and 64bit (e.g. x86-64) platforms by
+ * standardizing on the 64bit version of the data types. In particular,
+ * this means that we use "unsigned" where the 32bit headers say
+ * "unsigned long".
+ * - overall, we try to minimize the number of cases where we need to
+ * conditionally define different structures.
+ * - the "struct kernel_sigaction" class of structures have been
+ * modified to more closely mimic glibc's API by introducing an
+ * anonymous union for the function pointer.
+ * - a small number of field names had to have an underscore appended to
+ * them, because glibc defines a global macro by the same name.
+ */
+
+/* include/linux/dirent.h */
+struct kernel_dirent64 {
+ unsigned long long d_ino;
+ long long d_off;
+ unsigned short d_reclen;
+ unsigned char d_type;
+ char d_name[256];
+};
+
+/* include/linux/dirent.h */
+#if !defined(__NR_getdents)
+// when getdents is not available, getdents64 is used for both.
+#define kernel_dirent kernel_dirent64
+#else
+struct kernel_dirent {
+ long d_ino;
+ long d_off;
+ unsigned short d_reclen;
+ char d_name[256];
+};
+#endif
+
+/* include/linux/uio.h */
+struct kernel_iovec {
+ void *iov_base;
+ unsigned long iov_len;
+};
+
+/* include/linux/socket.h */
+struct kernel_msghdr {
+ void *msg_name;
+ int msg_namelen;
+ struct kernel_iovec*msg_iov;
+ unsigned long msg_iovlen;
+ void *msg_control;
+ unsigned long msg_controllen;
+ unsigned msg_flags;
+};
+
+/* include/asm-generic/poll.h */
+struct kernel_pollfd {
+ int fd;
+ short events;
+ short revents;
+};
+
+/* include/linux/resource.h */
+struct kernel_rlimit {
+ unsigned long rlim_cur;
+ unsigned long rlim_max;
+};
+
+/* include/linux/time.h */
+struct kernel_timespec {
+ long tv_sec;
+ long tv_nsec;
+};
+
+/* include/linux/time.h */
+struct kernel_timeval {
+ long tv_sec;
+ long tv_usec;
+};
+
+/* include/linux/resource.h */
+struct kernel_rusage {
+ struct kernel_timeval ru_utime;
+ struct kernel_timeval ru_stime;
+ long ru_maxrss;
+ long ru_ixrss;
+ long ru_idrss;
+ long ru_isrss;
+ long ru_minflt;
+ long ru_majflt;
+ long ru_nswap;
+ long ru_inblock;
+ long ru_oublock;
+ long ru_msgsnd;
+ long ru_msgrcv;
+ long ru_nsignals;
+ long ru_nvcsw;
+ long ru_nivcsw;
+};
+
+#if defined(__i386__) || defined(__ARM_EABI__) || defined(__ARM_ARCH_3__) \
+ || defined(__PPC__) || (defined(__s390__) && !defined(__s390x__))
+
+/* include/asm-{arm,i386,mips,ppc}/signal.h */
+struct kernel_old_sigaction {
+ union {
+ void (*sa_handler_)(int);
+ void (*sa_sigaction_)(int, siginfo_t *, void *);
+ };
+ unsigned long sa_mask;
+ unsigned long sa_flags;
+ void (*sa_restorer)(void);
+} __attribute__((packed,aligned(4)));
+#elif (defined(__mips__) && _MIPS_SIM == _MIPS_SIM_ABI32)
+ #define kernel_old_sigaction kernel_sigaction
+#elif defined(__aarch64__)
+ // No kernel_old_sigaction defined for arm64.
+#endif
+
+/* Some kernel functions (e.g. sigaction() in 2.6.23) require that the
+ * exactly match the size of the signal set, even though the API was
+ * intended to be extensible. We define our own KERNEL_NSIG to deal with
+ * this.
+ * Please note that glibc provides signals [1.._NSIG-1], whereas the
+ * kernel (and this header) provides the range [1..KERNEL_NSIG]. The
+ * actual number of signals is obviously the same, but the constants
+ * differ by one.
+ */
+#ifdef __mips__
+#define KERNEL_NSIG 128
+#else
+#define KERNEL_NSIG 64
+#endif
+
+/* include/asm-{arm,aarch64,i386,mips,x86_64}/signal.h */
+struct kernel_sigset_t {
+ unsigned long sig[(KERNEL_NSIG + 8*sizeof(unsigned long) - 1)/
+ (8*sizeof(unsigned long))];
+};
+
+/* include/asm-{arm,i386,mips,x86_64,ppc}/signal.h */
+struct kernel_sigaction {
+#ifdef __mips__
+ unsigned long sa_flags;
+ union {
+ void (*sa_handler_)(int);
+ void (*sa_sigaction_)(int, siginfo_t *, void *);
+ };
+ struct kernel_sigset_t sa_mask;
+#else
+ union {
+ void (*sa_handler_)(int);
+ void (*sa_sigaction_)(int, siginfo_t *, void *);
+ };
+ unsigned long sa_flags;
+ void (*sa_restorer)(void);
+ struct kernel_sigset_t sa_mask;
+#endif
+};
+
+/* include/linux/socket.h */
+struct kernel_sockaddr {
+ unsigned short sa_family;
+ char sa_data[14];
+};
+
+/* include/asm-{arm,aarch64,i386,mips,ppc,s390}/stat.h */
+#ifdef __mips__
+#if _MIPS_SIM == _MIPS_SIM_ABI64
+struct kernel_stat {
+#else
+struct kernel_stat64 {
+#endif
+ unsigned st_dev;
+ unsigned __pad0[3];
+ unsigned long long st_ino;
+ unsigned st_mode;
+ unsigned st_nlink;
+ unsigned st_uid;
+ unsigned st_gid;
+ unsigned st_rdev;
+ unsigned __pad1[3];
+ long long st_size;
+ unsigned st_atime_;
+ unsigned st_atime_nsec_;
+ unsigned st_mtime_;
+ unsigned st_mtime_nsec_;
+ unsigned st_ctime_;
+ unsigned st_ctime_nsec_;
+ unsigned st_blksize;
+ unsigned __pad2;
+ unsigned long long st_blocks;
+};
+#elif defined __PPC__
+struct kernel_stat64 {
+ unsigned long long st_dev;
+ unsigned long long st_ino;
+ unsigned st_mode;
+ unsigned st_nlink;
+ unsigned st_uid;
+ unsigned st_gid;
+ unsigned long long st_rdev;
+ unsigned short int __pad2;
+ long long st_size;
+ long st_blksize;
+ long long st_blocks;
+ long st_atime_;
+ unsigned long st_atime_nsec_;
+ long st_mtime_;
+ unsigned long st_mtime_nsec_;
+ long st_ctime_;
+ unsigned long st_ctime_nsec_;
+ unsigned long __unused4;
+ unsigned long __unused5;
+};
+#else
+struct kernel_stat64 {
+ unsigned long long st_dev;
+ unsigned char __pad0[4];
+ unsigned __st_ino;
+ unsigned st_mode;
+ unsigned st_nlink;
+ unsigned st_uid;
+ unsigned st_gid;
+ unsigned long long st_rdev;
+ unsigned char __pad3[4];
+ long long st_size;
+ unsigned st_blksize;
+ unsigned long long st_blocks;
+ unsigned st_atime_;
+ unsigned st_atime_nsec_;
+ unsigned st_mtime_;
+ unsigned st_mtime_nsec_;
+ unsigned st_ctime_;
+ unsigned st_ctime_nsec_;
+ unsigned long long st_ino;
+};
+#endif
+
+/* include/asm-{arm,aarch64,i386,mips,x86_64,ppc,s390}/stat.h */
+#if defined(__i386__) || defined(__ARM_ARCH_3__) || defined(__ARM_EABI__)
+struct kernel_stat {
+ /* The kernel headers suggest that st_dev and st_rdev should be 32bit
+ * quantities encoding 12bit major and 20bit minor numbers in an interleaved
+ * format. In reality, we do not see useful data in the top bits. So,
+ * we'll leave the padding in here, until we find a better solution.
+ */
+ unsigned short st_dev;
+ short pad1;
+ unsigned st_ino;
+ unsigned short st_mode;
+ unsigned short st_nlink;
+ unsigned short st_uid;
+ unsigned short st_gid;
+ unsigned short st_rdev;
+ short pad2;
+ unsigned st_size;
+ unsigned st_blksize;
+ unsigned st_blocks;
+ unsigned st_atime_;
+ unsigned st_atime_nsec_;
+ unsigned st_mtime_;
+ unsigned st_mtime_nsec_;
+ unsigned st_ctime_;
+ unsigned st_ctime_nsec_;
+ unsigned __unused4;
+ unsigned __unused5;
+};
+#elif defined(__x86_64__)
+struct kernel_stat {
+ uint64_t st_dev;
+ uint64_t st_ino;
+ uint64_t st_nlink;
+ unsigned st_mode;
+ unsigned st_uid;
+ unsigned st_gid;
+ unsigned __pad0;
+ uint64_t st_rdev;
+ int64_t st_size;
+ int64_t st_blksize;
+ int64_t st_blocks;
+ uint64_t st_atime_;
+ uint64_t st_atime_nsec_;
+ uint64_t st_mtime_;
+ uint64_t st_mtime_nsec_;
+ uint64_t st_ctime_;
+ uint64_t st_ctime_nsec_;
+ int64_t __unused4[3];
+};
+#elif defined(__PPC__)
+struct kernel_stat {
+ unsigned st_dev;
+ unsigned long st_ino; // ino_t
+ unsigned long st_mode; // mode_t
+ unsigned short st_nlink; // nlink_t
+ unsigned st_uid; // uid_t
+ unsigned st_gid; // gid_t
+ unsigned st_rdev;
+ long st_size; // off_t
+ unsigned long st_blksize;
+ unsigned long st_blocks;
+ unsigned long st_atime_;
+ unsigned long st_atime_nsec_;
+ unsigned long st_mtime_;
+ unsigned long st_mtime_nsec_;
+ unsigned long st_ctime_;
+ unsigned long st_ctime_nsec_;
+ unsigned long __unused4;
+ unsigned long __unused5;
+};
+#elif (defined(__mips__) && _MIPS_SIM != _MIPS_SIM_ABI64)
+struct kernel_stat {
+ unsigned st_dev;
+ int st_pad1[3];
+ unsigned st_ino;
+ unsigned st_mode;
+ unsigned st_nlink;
+ unsigned st_uid;
+ unsigned st_gid;
+ unsigned st_rdev;
+ int st_pad2[2];
+ long st_size;
+ int st_pad3;
+ long st_atime_;
+ long st_atime_nsec_;
+ long st_mtime_;
+ long st_mtime_nsec_;
+ long st_ctime_;
+ long st_ctime_nsec_;
+ int st_blksize;
+ int st_blocks;
+ int st_pad4[14];
+};
+#elif defined(__aarch64__)
+struct kernel_stat {
+ unsigned long st_dev;
+ unsigned long st_ino;
+ unsigned int st_mode;
+ unsigned int st_nlink;
+ unsigned int st_uid;
+ unsigned int st_gid;
+ unsigned long st_rdev;
+ unsigned long __pad1;
+ long st_size;
+ int st_blksize;
+ int __pad2;
+ long st_blocks;
+ long st_atime_;
+ unsigned long st_atime_nsec_;
+ long st_mtime_;
+ unsigned long st_mtime_nsec_;
+ long st_ctime_;
+ unsigned long st_ctime_nsec_;
+ unsigned int __unused4;
+ unsigned int __unused5;
+};
+#elif defined(__s390x__)
+struct kernel_stat {
+ unsigned long st_dev;
+ unsigned long st_ino;
+ unsigned long st_nlink;
+ unsigned int st_mode;
+ unsigned int st_uid;
+ unsigned int st_gid;
+ unsigned int __pad1;
+ unsigned long st_rdev;
+ unsigned long st_size;
+ unsigned long st_atime_;
+ unsigned long st_atime_nsec_;
+ unsigned long st_mtime_;
+ unsigned long st_mtime_nsec_;
+ unsigned long st_ctime_;
+ unsigned long st_ctime_nsec_;
+ unsigned long st_blksize;
+ long st_blocks;
+ unsigned long __unused[3];
+};
+#elif defined(__s390__)
+struct kernel_stat {
+ unsigned short st_dev;
+ unsigned short __pad1;
+ unsigned long st_ino;
+ unsigned short st_mode;
+ unsigned short st_nlink;
+ unsigned short st_uid;
+ unsigned short st_gid;
+ unsigned short st_rdev;
+ unsigned short __pad2;
+ unsigned long st_size;
+ unsigned long st_blksize;
+ unsigned long st_blocks;
+ unsigned long st_atime_;
+ unsigned long st_atime_nsec_;
+ unsigned long st_mtime_;
+ unsigned long st_mtime_nsec_;
+ unsigned long st_ctime_;
+ unsigned long st_ctime_nsec_;
+ unsigned long __unused4;
+ unsigned long __unused5;
+};
+#endif
+
+/* include/asm-{arm,aarch64,i386,mips,x86_64,ppc,s390}/statfs.h */
+#ifdef __mips__
+#if _MIPS_SIM != _MIPS_SIM_ABI64
+struct kernel_statfs64 {
+ unsigned long f_type;
+ unsigned long f_bsize;
+ unsigned long f_frsize;
+ unsigned long __pad;
+ unsigned long long f_blocks;
+ unsigned long long f_bfree;
+ unsigned long long f_files;
+ unsigned long long f_ffree;
+ unsigned long long f_bavail;
+ struct { int val[2]; } f_fsid;
+ unsigned long f_namelen;
+ unsigned long f_spare[6];
+};
+#endif
+#elif defined(__s390__)
+/* See also arch/s390/include/asm/compat.h */
+struct kernel_statfs64 {
+ unsigned int f_type;
+ unsigned int f_bsize;
+ unsigned long long f_blocks;
+ unsigned long long f_bfree;
+ unsigned long long f_bavail;
+ unsigned long long f_files;
+ unsigned long long f_ffree;
+ struct { int val[2]; } f_fsid;
+ unsigned int f_namelen;
+ unsigned int f_frsize;
+ unsigned int f_flags;
+ unsigned int f_spare[4];
+};
+#elif !defined(__x86_64__)
+struct kernel_statfs64 {
+ unsigned long f_type;
+ unsigned long f_bsize;
+ unsigned long long f_blocks;
+ unsigned long long f_bfree;
+ unsigned long long f_bavail;
+ unsigned long long f_files;
+ unsigned long long f_ffree;
+ struct { int val[2]; } f_fsid;
+ unsigned long f_namelen;
+ unsigned long f_frsize;
+ unsigned long f_spare[5];
+};
+#endif
+
+/* include/asm-{arm,i386,mips,x86_64,ppc,generic,s390}/statfs.h */
+#ifdef __mips__
+struct kernel_statfs {
+ long f_type;
+ long f_bsize;
+ long f_frsize;
+ long f_blocks;
+ long f_bfree;
+ long f_files;
+ long f_ffree;
+ long f_bavail;
+ struct { int val[2]; } f_fsid;
+ long f_namelen;
+ long f_spare[6];
+};
+#elif defined(__x86_64__)
+struct kernel_statfs {
+ /* x86_64 actually defines all these fields as signed, whereas all other */
+ /* platforms define them as unsigned. Leaving them at unsigned should not */
+ /* cause any problems. Make sure these are 64-bit even on x32. */
+ uint64_t f_type;
+ uint64_t f_bsize;
+ uint64_t f_blocks;
+ uint64_t f_bfree;
+ uint64_t f_bavail;
+ uint64_t f_files;
+ uint64_t f_ffree;
+ struct { int val[2]; } f_fsid;
+ uint64_t f_namelen;
+ uint64_t f_frsize;
+ uint64_t f_spare[5];
+};
+#elif defined(__s390__)
+struct kernel_statfs {
+ unsigned int f_type;
+ unsigned int f_bsize;
+ unsigned long f_blocks;
+ unsigned long f_bfree;
+ unsigned long f_bavail;
+ unsigned long f_files;
+ unsigned long f_ffree;
+ struct { int val[2]; } f_fsid;
+ unsigned int f_namelen;
+ unsigned int f_frsize;
+ unsigned int f_flags;
+ unsigned int f_spare[4];
+};
+#else
+struct kernel_statfs {
+ unsigned long f_type;
+ unsigned long f_bsize;
+ unsigned long f_blocks;
+ unsigned long f_bfree;
+ unsigned long f_bavail;
+ unsigned long f_files;
+ unsigned long f_ffree;
+ struct { int val[2]; } f_fsid;
+ unsigned long f_namelen;
+ unsigned long f_frsize;
+ unsigned long f_spare[5];
+};
+#endif
+
+
+/* Definitions missing from the standard header files */
+#ifndef O_DIRECTORY
+#if defined(__ARM_ARCH_3__) || defined(__ARM_EABI__) || defined(__aarch64__)
+#define O_DIRECTORY 0040000
+#else
+#define O_DIRECTORY 0200000
+#endif
+#endif
+#ifndef NT_PRXFPREG
+#define NT_PRXFPREG 0x46e62b7f
+#endif
+#ifndef PTRACE_GETFPXREGS
+#define PTRACE_GETFPXREGS ((enum __ptrace_request)18)
+#endif
+#ifndef PR_GET_DUMPABLE
+#define PR_GET_DUMPABLE 3
+#endif
+#ifndef PR_SET_DUMPABLE
+#define PR_SET_DUMPABLE 4
+#endif
+#ifndef PR_GET_SECCOMP
+#define PR_GET_SECCOMP 21
+#endif
+#ifndef PR_SET_SECCOMP
+#define PR_SET_SECCOMP 22
+#endif
+#ifndef AT_FDCWD
+#define AT_FDCWD (-100)
+#endif
+#ifndef AT_SYMLINK_NOFOLLOW
+#define AT_SYMLINK_NOFOLLOW 0x100
+#endif
+#ifndef AT_REMOVEDIR
+#define AT_REMOVEDIR 0x200
+#endif
+#ifndef MREMAP_FIXED
+#define MREMAP_FIXED 2
+#endif
+#ifndef SA_RESTORER
+#define SA_RESTORER 0x04000000
+#endif
+#ifndef CPUCLOCK_PROF
+#define CPUCLOCK_PROF 0
+#endif
+#ifndef CPUCLOCK_VIRT
+#define CPUCLOCK_VIRT 1
+#endif
+#ifndef CPUCLOCK_SCHED
+#define CPUCLOCK_SCHED 2
+#endif
+#ifndef CPUCLOCK_PERTHREAD_MASK
+#define CPUCLOCK_PERTHREAD_MASK 4
+#endif
+#ifndef MAKE_PROCESS_CPUCLOCK
+#define MAKE_PROCESS_CPUCLOCK(pid, clock) \
+ ((int)(~(unsigned)(pid) << 3) | (int)(clock))
+#endif
+#ifndef MAKE_THREAD_CPUCLOCK
+#define MAKE_THREAD_CPUCLOCK(tid, clock) \
+ ((int)(~(unsigned)(tid) << 3) | \
+ (int)((clock) | CPUCLOCK_PERTHREAD_MASK))
+#endif
+
+#ifndef FUTEX_WAIT
+#define FUTEX_WAIT 0
+#endif
+#ifndef FUTEX_WAKE
+#define FUTEX_WAKE 1
+#endif
+#ifndef FUTEX_FD
+#define FUTEX_FD 2
+#endif
+#ifndef FUTEX_REQUEUE
+#define FUTEX_REQUEUE 3
+#endif
+#ifndef FUTEX_CMP_REQUEUE
+#define FUTEX_CMP_REQUEUE 4
+#endif
+#ifndef FUTEX_WAKE_OP
+#define FUTEX_WAKE_OP 5
+#endif
+#ifndef FUTEX_LOCK_PI
+#define FUTEX_LOCK_PI 6
+#endif
+#ifndef FUTEX_UNLOCK_PI
+#define FUTEX_UNLOCK_PI 7
+#endif
+#ifndef FUTEX_TRYLOCK_PI
+#define FUTEX_TRYLOCK_PI 8
+#endif
+#ifndef FUTEX_PRIVATE_FLAG
+#define FUTEX_PRIVATE_FLAG 128
+#endif
+#ifndef FUTEX_CMD_MASK
+#define FUTEX_CMD_MASK ~FUTEX_PRIVATE_FLAG
+#endif
+#ifndef FUTEX_WAIT_PRIVATE
+#define FUTEX_WAIT_PRIVATE (FUTEX_WAIT | FUTEX_PRIVATE_FLAG)
+#endif
+#ifndef FUTEX_WAKE_PRIVATE
+#define FUTEX_WAKE_PRIVATE (FUTEX_WAKE | FUTEX_PRIVATE_FLAG)
+#endif
+#ifndef FUTEX_REQUEUE_PRIVATE
+#define FUTEX_REQUEUE_PRIVATE (FUTEX_REQUEUE | FUTEX_PRIVATE_FLAG)
+#endif
+#ifndef FUTEX_CMP_REQUEUE_PRIVATE
+#define FUTEX_CMP_REQUEUE_PRIVATE (FUTEX_CMP_REQUEUE | FUTEX_PRIVATE_FLAG)
+#endif
+#ifndef FUTEX_WAKE_OP_PRIVATE
+#define FUTEX_WAKE_OP_PRIVATE (FUTEX_WAKE_OP | FUTEX_PRIVATE_FLAG)
+#endif
+#ifndef FUTEX_LOCK_PI_PRIVATE
+#define FUTEX_LOCK_PI_PRIVATE (FUTEX_LOCK_PI | FUTEX_PRIVATE_FLAG)
+#endif
+#ifndef FUTEX_UNLOCK_PI_PRIVATE
+#define FUTEX_UNLOCK_PI_PRIVATE (FUTEX_UNLOCK_PI | FUTEX_PRIVATE_FLAG)
+#endif
+#ifndef FUTEX_TRYLOCK_PI_PRIVATE
+#define FUTEX_TRYLOCK_PI_PRIVATE (FUTEX_TRYLOCK_PI | FUTEX_PRIVATE_FLAG)
+#endif
+
+
+#if defined(__x86_64__)
+#ifndef ARCH_SET_GS
+#define ARCH_SET_GS 0x1001
+#endif
+#ifndef ARCH_GET_GS
+#define ARCH_GET_GS 0x1004
+#endif
+#endif
+
+#if defined(__i386__)
+#ifndef __NR_quotactl
+#define __NR_quotactl 131
+#endif
+#ifndef __NR_setresuid
+#define __NR_setresuid 164
+#define __NR_getresuid 165
+#define __NR_setresgid 170
+#define __NR_getresgid 171
+#endif
+#ifndef __NR_rt_sigaction
+#define __NR_rt_sigreturn 173
+#define __NR_rt_sigaction 174
+#define __NR_rt_sigprocmask 175
+#define __NR_rt_sigpending 176
+#define __NR_rt_sigsuspend 179
+#endif
+#ifndef __NR_pread64
+#define __NR_pread64 180
+#endif
+#ifndef __NR_pwrite64
+#define __NR_pwrite64 181
+#endif
+#ifndef __NR_ugetrlimit
+#define __NR_ugetrlimit 191
+#endif
+#ifndef __NR_stat64
+#define __NR_stat64 195
+#endif
+#ifndef __NR_fstat64
+#define __NR_fstat64 197
+#endif
+#ifndef __NR_setresuid32
+#define __NR_setresuid32 208
+#define __NR_getresuid32 209
+#define __NR_setresgid32 210
+#define __NR_getresgid32 211
+#endif
+#ifndef __NR_setfsuid32
+#define __NR_setfsuid32 215
+#define __NR_setfsgid32 216
+#endif
+#ifndef __NR_getdents64
+#define __NR_getdents64 220
+#endif
+#ifndef __NR_gettid
+#define __NR_gettid 224
+#endif
+#ifndef __NR_readahead
+#define __NR_readahead 225
+#endif
+#ifndef __NR_setxattr
+#define __NR_setxattr 226
+#endif
+#ifndef __NR_lsetxattr
+#define __NR_lsetxattr 227
+#endif
+#ifndef __NR_getxattr
+#define __NR_getxattr 229
+#endif
+#ifndef __NR_lgetxattr
+#define __NR_lgetxattr 230
+#endif
+#ifndef __NR_listxattr
+#define __NR_listxattr 232
+#endif
+#ifndef __NR_llistxattr
+#define __NR_llistxattr 233
+#endif
+#ifndef __NR_tkill
+#define __NR_tkill 238
+#endif
+#ifndef __NR_futex
+#define __NR_futex 240
+#endif
+#ifndef __NR_sched_setaffinity
+#define __NR_sched_setaffinity 241
+#define __NR_sched_getaffinity 242
+#endif
+#ifndef __NR_set_tid_address
+#define __NR_set_tid_address 258
+#endif
+#ifndef __NR_clock_gettime
+#define __NR_clock_gettime 265
+#endif
+#ifndef __NR_clock_getres
+#define __NR_clock_getres 266
+#endif
+#ifndef __NR_statfs64
+#define __NR_statfs64 268
+#endif
+#ifndef __NR_fstatfs64
+#define __NR_fstatfs64 269
+#endif
+#ifndef __NR_fadvise64_64
+#define __NR_fadvise64_64 272
+#endif
+#ifndef __NR_ioprio_set
+#define __NR_ioprio_set 289
+#endif
+#ifndef __NR_ioprio_get
+#define __NR_ioprio_get 290
+#endif
+#ifndef __NR_openat
+#define __NR_openat 295
+#endif
+#ifndef __NR_fstatat64
+#define __NR_fstatat64 300
+#endif
+#ifndef __NR_unlinkat
+#define __NR_unlinkat 301
+#endif
+#ifndef __NR_move_pages
+#define __NR_move_pages 317
+#endif
+#ifndef __NR_getcpu
+#define __NR_getcpu 318
+#endif
+#ifndef __NR_fallocate
+#define __NR_fallocate 324
+#endif
+/* End of i386 definitions */
+#elif defined(__ARM_ARCH_3__) || defined(__ARM_EABI__)
+#ifndef __NR_setresuid
+#define __NR_setresuid (__NR_SYSCALL_BASE + 164)
+#define __NR_getresuid (__NR_SYSCALL_BASE + 165)
+#define __NR_setresgid (__NR_SYSCALL_BASE + 170)
+#define __NR_getresgid (__NR_SYSCALL_BASE + 171)
+#endif
+#ifndef __NR_rt_sigaction
+#define __NR_rt_sigreturn (__NR_SYSCALL_BASE + 173)
+#define __NR_rt_sigaction (__NR_SYSCALL_BASE + 174)
+#define __NR_rt_sigprocmask (__NR_SYSCALL_BASE + 175)
+#define __NR_rt_sigpending (__NR_SYSCALL_BASE + 176)
+#define __NR_rt_sigsuspend (__NR_SYSCALL_BASE + 179)
+#endif
+#ifndef __NR_pread64
+#define __NR_pread64 (__NR_SYSCALL_BASE + 180)
+#endif
+#ifndef __NR_pwrite64
+#define __NR_pwrite64 (__NR_SYSCALL_BASE + 181)
+#endif
+#ifndef __NR_ugetrlimit
+#define __NR_ugetrlimit (__NR_SYSCALL_BASE + 191)
+#endif
+#ifndef __NR_stat64
+#define __NR_stat64 (__NR_SYSCALL_BASE + 195)
+#endif
+#ifndef __NR_fstat64
+#define __NR_fstat64 (__NR_SYSCALL_BASE + 197)
+#endif
+#ifndef __NR_setresuid32
+#define __NR_setresuid32 (__NR_SYSCALL_BASE + 208)
+#define __NR_getresuid32 (__NR_SYSCALL_BASE + 209)
+#define __NR_setresgid32 (__NR_SYSCALL_BASE + 210)
+#define __NR_getresgid32 (__NR_SYSCALL_BASE + 211)
+#endif
+#ifndef __NR_setfsuid32
+#define __NR_setfsuid32 (__NR_SYSCALL_BASE + 215)
+#define __NR_setfsgid32 (__NR_SYSCALL_BASE + 216)
+#endif
+#ifndef __NR_getdents64
+#define __NR_getdents64 (__NR_SYSCALL_BASE + 217)
+#endif
+#ifndef __NR_gettid
+#define __NR_gettid (__NR_SYSCALL_BASE + 224)
+#endif
+#ifndef __NR_readahead
+#define __NR_readahead (__NR_SYSCALL_BASE + 225)
+#endif
+#ifndef __NR_setxattr
+#define __NR_setxattr (__NR_SYSCALL_BASE + 226)
+#endif
+#ifndef __NR_lsetxattr
+#define __NR_lsetxattr (__NR_SYSCALL_BASE + 227)
+#endif
+#ifndef __NR_getxattr
+#define __NR_getxattr (__NR_SYSCALL_BASE + 229)
+#endif
+#ifndef __NR_lgetxattr
+#define __NR_lgetxattr (__NR_SYSCALL_BASE + 230)
+#endif
+#ifndef __NR_listxattr
+#define __NR_listxattr (__NR_SYSCALL_BASE + 232)
+#endif
+#ifndef __NR_llistxattr
+#define __NR_llistxattr (__NR_SYSCALL_BASE + 233)
+#endif
+#ifndef __NR_tkill
+#define __NR_tkill (__NR_SYSCALL_BASE + 238)
+#endif
+#ifndef __NR_futex
+#define __NR_futex (__NR_SYSCALL_BASE + 240)
+#endif
+#ifndef __NR_sched_setaffinity
+#define __NR_sched_setaffinity (__NR_SYSCALL_BASE + 241)
+#define __NR_sched_getaffinity (__NR_SYSCALL_BASE + 242)
+#endif
+#ifndef __NR_set_tid_address
+#define __NR_set_tid_address (__NR_SYSCALL_BASE + 256)
+#endif
+#ifndef __NR_clock_gettime
+#define __NR_clock_gettime (__NR_SYSCALL_BASE + 263)
+#endif
+#ifndef __NR_clock_getres
+#define __NR_clock_getres (__NR_SYSCALL_BASE + 264)
+#endif
+#ifndef __NR_statfs64
+#define __NR_statfs64 (__NR_SYSCALL_BASE + 266)
+#endif
+#ifndef __NR_fstatfs64
+#define __NR_fstatfs64 (__NR_SYSCALL_BASE + 267)
+#endif
+#ifndef __NR_ioprio_set
+#define __NR_ioprio_set (__NR_SYSCALL_BASE + 314)
+#endif
+#ifndef __NR_ioprio_get
+#define __NR_ioprio_get (__NR_SYSCALL_BASE + 315)
+#endif
+#ifndef __NR_move_pages
+#define __NR_move_pages (__NR_SYSCALL_BASE + 344)
+#endif
+#ifndef __NR_getcpu
+#define __NR_getcpu (__NR_SYSCALL_BASE + 345)
+#endif
+/* End of ARM 3/EABI definitions */
+#elif defined(__aarch64__)
+#ifndef __NR_setxattr
+#define __NR_setxattr 5
+#endif
+#ifndef __NR_lsetxattr
+#define __NR_lsetxattr 6
+#endif
+#ifndef __NR_getxattr
+#define __NR_getxattr 8
+#endif
+#ifndef __NR_lgetxattr
+#define __NR_lgetxattr 9
+#endif
+#ifndef __NR_listxattr
+#define __NR_listxattr 11
+#endif
+#ifndef __NR_llistxattr
+#define __NR_llistxattr 12
+#endif
+#ifndef __NR_ioprio_set
+#define __NR_ioprio_set 30
+#endif
+#ifndef __NR_ioprio_get
+#define __NR_ioprio_get 31
+#endif
+#ifndef __NR_unlinkat
+#define __NR_unlinkat 35
+#endif
+#ifndef __NR_fallocate
+#define __NR_fallocate 47
+#endif
+#ifndef __NR_openat
+#define __NR_openat 56
+#endif
+#ifndef __NR_quotactl
+#define __NR_quotactl 60
+#endif
+#ifndef __NR_getdents64
+#define __NR_getdents64 61
+#endif
+#ifndef __NR_getdents
+// when getdents is not available, getdents64 is used for both.
+#define __NR_getdents __NR_getdents64
+#endif
+#ifndef __NR_pread64
+#define __NR_pread64 67
+#endif
+#ifndef __NR_pwrite64
+#define __NR_pwrite64 68
+#endif
+#ifndef __NR_ppoll
+#define __NR_ppoll 73
+#endif
+#ifndef __NR_readlinkat
+#define __NR_readlinkat 78
+#endif
+#ifndef __NR_newfstatat
+#define __NR_newfstatat 79
+#endif
+#ifndef __NR_set_tid_address
+#define __NR_set_tid_address 96
+#endif
+#ifndef __NR_futex
+#define __NR_futex 98
+#endif
+#ifndef __NR_clock_gettime
+#define __NR_clock_gettime 113
+#endif
+#ifndef __NR_clock_getres
+#define __NR_clock_getres 114
+#endif
+#ifndef __NR_sched_setaffinity
+#define __NR_sched_setaffinity 122
+#define __NR_sched_getaffinity 123
+#endif
+#ifndef __NR_tkill
+#define __NR_tkill 130
+#endif
+#ifndef __NR_setresuid
+#define __NR_setresuid 147
+#define __NR_getresuid 148
+#define __NR_setresgid 149
+#define __NR_getresgid 150
+#endif
+#ifndef __NR_gettid
+#define __NR_gettid 178
+#endif
+#ifndef __NR_readahead
+#define __NR_readahead 213
+#endif
+#ifndef __NR_fadvise64
+#define __NR_fadvise64 223
+#endif
+#ifndef __NR_move_pages
+#define __NR_move_pages 239
+#endif
+/* End of aarch64 definitions */
+#elif defined(__x86_64__)
+#ifndef __NR_pread64
+#define __NR_pread64 17
+#endif
+#ifndef __NR_pwrite64
+#define __NR_pwrite64 18
+#endif
+#ifndef __NR_setresuid
+#define __NR_setresuid 117
+#define __NR_getresuid 118
+#define __NR_setresgid 119
+#define __NR_getresgid 120
+#endif
+#ifndef __NR_quotactl
+#define __NR_quotactl 179
+#endif
+#ifndef __NR_gettid
+#define __NR_gettid 186
+#endif
+#ifndef __NR_readahead
+#define __NR_readahead 187
+#endif
+#ifndef __NR_setxattr
+#define __NR_setxattr 188
+#endif
+#ifndef __NR_lsetxattr
+#define __NR_lsetxattr 189
+#endif
+#ifndef __NR_getxattr
+#define __NR_getxattr 191
+#endif
+#ifndef __NR_lgetxattr
+#define __NR_lgetxattr 192
+#endif
+#ifndef __NR_listxattr
+#define __NR_listxattr 194
+#endif
+#ifndef __NR_llistxattr
+#define __NR_llistxattr 195
+#endif
+#ifndef __NR_tkill
+#define __NR_tkill 200
+#endif
+#ifndef __NR_futex
+#define __NR_futex 202
+#endif
+#ifndef __NR_sched_setaffinity
+#define __NR_sched_setaffinity 203
+#define __NR_sched_getaffinity 204
+#endif
+#ifndef __NR_getdents64
+#define __NR_getdents64 217
+#endif
+#ifndef __NR_getdents
+// when getdents is not available, getdents64 is used for both.
+#define __NR_getdents __NR_getdents64
+#endif
+#ifndef __NR_set_tid_address
+#define __NR_set_tid_address 218
+#endif
+#ifndef __NR_fadvise64
+#define __NR_fadvise64 221
+#endif
+#ifndef __NR_clock_gettime
+#define __NR_clock_gettime 228
+#endif
+#ifndef __NR_clock_getres
+#define __NR_clock_getres 229
+#endif
+#ifndef __NR_ioprio_set
+#define __NR_ioprio_set 251
+#endif
+#ifndef __NR_ioprio_get
+#define __NR_ioprio_get 252
+#endif
+#ifndef __NR_openat
+#define __NR_openat 257
+#endif
+#ifndef __NR_newfstatat
+#define __NR_newfstatat 262
+#endif
+#ifndef __NR_unlinkat
+#define __NR_unlinkat 263
+#endif
+#ifndef __NR_move_pages
+#define __NR_move_pages 279
+#endif
+#ifndef __NR_fallocate
+#define __NR_fallocate 285
+#endif
+/* End of x86-64 definitions */
+#elif defined(__mips__)
+#if _MIPS_SIM == _MIPS_SIM_ABI32
+#ifndef __NR_setresuid
+#define __NR_setresuid (__NR_Linux + 185)
+#define __NR_getresuid (__NR_Linux + 186)
+#define __NR_setresgid (__NR_Linux + 190)
+#define __NR_getresgid (__NR_Linux + 191)
+#endif
+#ifndef __NR_rt_sigaction
+#define __NR_rt_sigreturn (__NR_Linux + 193)
+#define __NR_rt_sigaction (__NR_Linux + 194)
+#define __NR_rt_sigprocmask (__NR_Linux + 195)
+#define __NR_rt_sigpending (__NR_Linux + 196)
+#define __NR_rt_sigsuspend (__NR_Linux + 199)
+#endif
+#ifndef __NR_pread64
+#define __NR_pread64 (__NR_Linux + 200)
+#endif
+#ifndef __NR_pwrite64
+#define __NR_pwrite64 (__NR_Linux + 201)
+#endif
+#ifndef __NR_stat64
+#define __NR_stat64 (__NR_Linux + 213)
+#endif
+#ifndef __NR_fstat64
+#define __NR_fstat64 (__NR_Linux + 215)
+#endif
+#ifndef __NR_getdents64
+#define __NR_getdents64 (__NR_Linux + 219)
+#endif
+#ifndef __NR_gettid
+#define __NR_gettid (__NR_Linux + 222)
+#endif
+#ifndef __NR_readahead
+#define __NR_readahead (__NR_Linux + 223)
+#endif
+#ifndef __NR_setxattr
+#define __NR_setxattr (__NR_Linux + 224)
+#endif
+#ifndef __NR_lsetxattr
+#define __NR_lsetxattr (__NR_Linux + 225)
+#endif
+#ifndef __NR_getxattr
+#define __NR_getxattr (__NR_Linux + 227)
+#endif
+#ifndef __NR_lgetxattr
+#define __NR_lgetxattr (__NR_Linux + 228)
+#endif
+#ifndef __NR_listxattr
+#define __NR_listxattr (__NR_Linux + 230)
+#endif
+#ifndef __NR_llistxattr
+#define __NR_llistxattr (__NR_Linux + 231)
+#endif
+#ifndef __NR_tkill
+#define __NR_tkill (__NR_Linux + 236)
+#endif
+#ifndef __NR_futex
+#define __NR_futex (__NR_Linux + 238)
+#endif
+#ifndef __NR_sched_setaffinity
+#define __NR_sched_setaffinity (__NR_Linux + 239)
+#define __NR_sched_getaffinity (__NR_Linux + 240)
+#endif
+#ifndef __NR_set_tid_address
+#define __NR_set_tid_address (__NR_Linux + 252)
+#endif
+#ifndef __NR_statfs64
+#define __NR_statfs64 (__NR_Linux + 255)
+#endif
+#ifndef __NR_fstatfs64
+#define __NR_fstatfs64 (__NR_Linux + 256)
+#endif
+#ifndef __NR_clock_gettime
+#define __NR_clock_gettime (__NR_Linux + 263)
+#endif
+#ifndef __NR_clock_getres
+#define __NR_clock_getres (__NR_Linux + 264)
+#endif
+#ifndef __NR_openat
+#define __NR_openat (__NR_Linux + 288)
+#endif
+#ifndef __NR_fstatat
+#define __NR_fstatat (__NR_Linux + 293)
+#endif
+#ifndef __NR_unlinkat
+#define __NR_unlinkat (__NR_Linux + 294)
+#endif
+#ifndef __NR_move_pages
+#define __NR_move_pages (__NR_Linux + 308)
+#endif
+#ifndef __NR_getcpu
+#define __NR_getcpu (__NR_Linux + 312)
+#endif
+#ifndef __NR_ioprio_set
+#define __NR_ioprio_set (__NR_Linux + 314)
+#endif
+#ifndef __NR_ioprio_get
+#define __NR_ioprio_get (__NR_Linux + 315)
+#endif
+/* End of MIPS (old 32bit API) definitions */
+#elif _MIPS_SIM == _MIPS_SIM_ABI64
+#ifndef __NR_pread64
+#define __NR_pread64 (__NR_Linux + 16)
+#endif
+#ifndef __NR_pwrite64
+#define __NR_pwrite64 (__NR_Linux + 17)
+#endif
+#ifndef __NR_setresuid
+#define __NR_setresuid (__NR_Linux + 115)
+#define __NR_getresuid (__NR_Linux + 116)
+#define __NR_setresgid (__NR_Linux + 117)
+#define __NR_getresgid (__NR_Linux + 118)
+#endif
+#ifndef __NR_gettid
+#define __NR_gettid (__NR_Linux + 178)
+#endif
+#ifndef __NR_readahead
+#define __NR_readahead (__NR_Linux + 179)
+#endif
+#ifndef __NR_setxattr
+#define __NR_setxattr (__NR_Linux + 180)
+#endif
+#ifndef __NR_lsetxattr
+#define __NR_lsetxattr (__NR_Linux + 181)
+#endif
+#ifndef __NR_getxattr
+#define __NR_getxattr (__NR_Linux + 183)
+#endif
+#ifndef __NR_lgetxattr
+#define __NR_lgetxattr (__NR_Linux + 184)
+#endif
+#ifndef __NR_listxattr
+#define __NR_listxattr (__NR_Linux + 186)
+#endif
+#ifndef __NR_llistxattr
+#define __NR_llistxattr (__NR_Linux + 187)
+#endif
+#ifndef __NR_tkill
+#define __NR_tkill (__NR_Linux + 192)
+#endif
+#ifndef __NR_futex
+#define __NR_futex (__NR_Linux + 194)
+#endif
+#ifndef __NR_sched_setaffinity
+#define __NR_sched_setaffinity (__NR_Linux + 195)
+#define __NR_sched_getaffinity (__NR_Linux + 196)
+#endif
+#ifndef __NR_set_tid_address
+#define __NR_set_tid_address (__NR_Linux + 212)
+#endif
+#ifndef __NR_clock_gettime
+#define __NR_clock_gettime (__NR_Linux + 222)
+#endif
+#ifndef __NR_clock_getres
+#define __NR_clock_getres (__NR_Linux + 223)
+#endif
+#ifndef __NR_openat
+#define __NR_openat (__NR_Linux + 247)
+#endif
+#ifndef __NR_fstatat
+#define __NR_fstatat (__NR_Linux + 252)
+#endif
+#ifndef __NR_unlinkat
+#define __NR_unlinkat (__NR_Linux + 253)
+#endif
+#ifndef __NR_move_pages
+#define __NR_move_pages (__NR_Linux + 267)
+#endif
+#ifndef __NR_getcpu
+#define __NR_getcpu (__NR_Linux + 271)
+#endif
+#ifndef __NR_ioprio_set
+#define __NR_ioprio_set (__NR_Linux + 273)
+#endif
+#ifndef __NR_ioprio_get
+#define __NR_ioprio_get (__NR_Linux + 274)
+#endif
+/* End of MIPS (64bit API) definitions */
+#else
+#ifndef __NR_setresuid
+#define __NR_setresuid (__NR_Linux + 115)
+#define __NR_getresuid (__NR_Linux + 116)
+#define __NR_setresgid (__NR_Linux + 117)
+#define __NR_getresgid (__NR_Linux + 118)
+#endif
+#ifndef __NR_gettid
+#define __NR_gettid (__NR_Linux + 178)
+#endif
+#ifndef __NR_readahead
+#define __NR_readahead (__NR_Linux + 179)
+#endif
+#ifndef __NR_setxattr
+#define __NR_setxattr (__NR_Linux + 180)
+#endif
+#ifndef __NR_lsetxattr
+#define __NR_lsetxattr (__NR_Linux + 181)
+#endif
+#ifndef __NR_getxattr
+#define __NR_getxattr (__NR_Linux + 183)
+#endif
+#ifndef __NR_lgetxattr
+#define __NR_lgetxattr (__NR_Linux + 184)
+#endif
+#ifndef __NR_listxattr
+#define __NR_listxattr (__NR_Linux + 186)
+#endif
+#ifndef __NR_llistxattr
+#define __NR_llistxattr (__NR_Linux + 187)
+#endif
+#ifndef __NR_tkill
+#define __NR_tkill (__NR_Linux + 192)
+#endif
+#ifndef __NR_futex
+#define __NR_futex (__NR_Linux + 194)
+#endif
+#ifndef __NR_sched_setaffinity
+#define __NR_sched_setaffinity (__NR_Linux + 195)
+#define __NR_sched_getaffinity (__NR_Linux + 196)
+#endif
+#ifndef __NR_set_tid_address
+#define __NR_set_tid_address (__NR_Linux + 213)
+#endif
+#ifndef __NR_statfs64
+#define __NR_statfs64 (__NR_Linux + 217)
+#endif
+#ifndef __NR_fstatfs64
+#define __NR_fstatfs64 (__NR_Linux + 218)
+#endif
+#ifndef __NR_clock_gettime
+#define __NR_clock_gettime (__NR_Linux + 226)
+#endif
+#ifndef __NR_clock_getres
+#define __NR_clock_getres (__NR_Linux + 227)
+#endif
+#ifndef __NR_openat
+#define __NR_openat (__NR_Linux + 251)
+#endif
+#ifndef __NR_fstatat
+#define __NR_fstatat (__NR_Linux + 256)
+#endif
+#ifndef __NR_unlinkat
+#define __NR_unlinkat (__NR_Linux + 257)
+#endif
+#ifndef __NR_move_pages
+#define __NR_move_pages (__NR_Linux + 271)
+#endif
+#ifndef __NR_getcpu
+#define __NR_getcpu (__NR_Linux + 275)
+#endif
+#ifndef __NR_ioprio_set
+#define __NR_ioprio_set (__NR_Linux + 277)
+#endif
+#ifndef __NR_ioprio_get
+#define __NR_ioprio_get (__NR_Linux + 278)
+#endif
+/* End of MIPS (new 32bit API) definitions */
+#endif
+/* End of MIPS definitions */
+#elif defined(__PPC__)
+#ifndef __NR_setfsuid
+#define __NR_setfsuid 138
+#define __NR_setfsgid 139
+#endif
+#ifndef __NR_setresuid
+#define __NR_setresuid 164
+#define __NR_getresuid 165
+#define __NR_setresgid 169
+#define __NR_getresgid 170
+#endif
+#ifndef __NR_rt_sigaction
+#define __NR_rt_sigreturn 172
+#define __NR_rt_sigaction 173
+#define __NR_rt_sigprocmask 174
+#define __NR_rt_sigpending 175
+#define __NR_rt_sigsuspend 178
+#endif
+#ifndef __NR_pread64
+#define __NR_pread64 179
+#endif
+#ifndef __NR_pwrite64
+#define __NR_pwrite64 180
+#endif
+#ifndef __NR_ugetrlimit
+#define __NR_ugetrlimit 190
+#endif
+#ifndef __NR_readahead
+#define __NR_readahead 191
+#endif
+#ifndef __NR_stat64
+#define __NR_stat64 195
+#endif
+#ifndef __NR_fstat64
+#define __NR_fstat64 197
+#endif
+#ifndef __NR_getdents64
+#define __NR_getdents64 202
+#endif
+#ifndef __NR_gettid
+#define __NR_gettid 207
+#endif
+#ifndef __NR_tkill
+#define __NR_tkill 208
+#endif
+#ifndef __NR_setxattr
+#define __NR_setxattr 209
+#endif
+#ifndef __NR_lsetxattr
+#define __NR_lsetxattr 210
+#endif
+#ifndef __NR_getxattr
+#define __NR_getxattr 212
+#endif
+#ifndef __NR_lgetxattr
+#define __NR_lgetxattr 213
+#endif
+#ifndef __NR_listxattr
+#define __NR_listxattr 215
+#endif
+#ifndef __NR_llistxattr
+#define __NR_llistxattr 216
+#endif
+#ifndef __NR_futex
+#define __NR_futex 221
+#endif
+#ifndef __NR_sched_setaffinity
+#define __NR_sched_setaffinity 222
+#define __NR_sched_getaffinity 223
+#endif
+#ifndef __NR_set_tid_address
+#define __NR_set_tid_address 232
+#endif
+#ifndef __NR_clock_gettime
+#define __NR_clock_gettime 246
+#endif
+#ifndef __NR_clock_getres
+#define __NR_clock_getres 247
+#endif
+#ifndef __NR_statfs64
+#define __NR_statfs64 252
+#endif
+#ifndef __NR_fstatfs64
+#define __NR_fstatfs64 253
+#endif
+#ifndef __NR_fadvise64_64
+#define __NR_fadvise64_64 254
+#endif
+#ifndef __NR_ioprio_set
+#define __NR_ioprio_set 273
+#endif
+#ifndef __NR_ioprio_get
+#define __NR_ioprio_get 274
+#endif
+#ifndef __NR_openat
+#define __NR_openat 286
+#endif
+#ifndef __NR_fstatat64
+#define __NR_fstatat64 291
+#endif
+#ifndef __NR_unlinkat
+#define __NR_unlinkat 292
+#endif
+#ifndef __NR_move_pages
+#define __NR_move_pages 301
+#endif
+#ifndef __NR_getcpu
+#define __NR_getcpu 302
+#endif
+/* End of powerpc defininitions */
+#elif defined(__s390__)
+#ifndef __NR_quotactl
+#define __NR_quotactl 131
+#endif
+#ifndef __NR_rt_sigreturn
+#define __NR_rt_sigreturn 173
+#endif
+#ifndef __NR_rt_sigaction
+#define __NR_rt_sigaction 174
+#endif
+#ifndef __NR_rt_sigprocmask
+#define __NR_rt_sigprocmask 175
+#endif
+#ifndef __NR_rt_sigpending
+#define __NR_rt_sigpending 176
+#endif
+#ifndef __NR_rt_sigsuspend
+#define __NR_rt_sigsuspend 179
+#endif
+#ifndef __NR_pread64
+#define __NR_pread64 180
+#endif
+#ifndef __NR_pwrite64
+#define __NR_pwrite64 181
+#endif
+#ifndef __NR_getdents64
+#define __NR_getdents64 220
+#endif
+#ifndef __NR_readahead
+#define __NR_readahead 222
+#endif
+#ifndef __NR_setxattr
+#define __NR_setxattr 224
+#endif
+#ifndef __NR_lsetxattr
+#define __NR_lsetxattr 225
+#endif
+#ifndef __NR_getxattr
+#define __NR_getxattr 227
+#endif
+#ifndef __NR_lgetxattr
+#define __NR_lgetxattr 228
+#endif
+#ifndef __NR_listxattr
+#define __NR_listxattr 230
+#endif
+#ifndef __NR_llistxattr
+#define __NR_llistxattr 231
+#endif
+#ifndef __NR_gettid
+#define __NR_gettid 236
+#endif
+#ifndef __NR_tkill
+#define __NR_tkill 237
+#endif
+#ifndef __NR_futex
+#define __NR_futex 238
+#endif
+#ifndef __NR_sched_setaffinity
+#define __NR_sched_setaffinity 239
+#endif
+#ifndef __NR_sched_getaffinity
+#define __NR_sched_getaffinity 240
+#endif
+#ifndef __NR_set_tid_address
+#define __NR_set_tid_address 252
+#endif
+#ifndef __NR_clock_gettime
+#define __NR_clock_gettime 260
+#endif
+#ifndef __NR_clock_getres
+#define __NR_clock_getres 261
+#endif
+#ifndef __NR_statfs64
+#define __NR_statfs64 265
+#endif
+#ifndef __NR_fstatfs64
+#define __NR_fstatfs64 266
+#endif
+#ifndef __NR_ioprio_set
+#define __NR_ioprio_set 282
+#endif
+#ifndef __NR_ioprio_get
+#define __NR_ioprio_get 283
+#endif
+#ifndef __NR_openat
+#define __NR_openat 288
+#endif
+#ifndef __NR_unlinkat
+#define __NR_unlinkat 294
+#endif
+#ifndef __NR_move_pages
+#define __NR_move_pages 310
+#endif
+#ifndef __NR_getcpu
+#define __NR_getcpu 311
+#endif
+#ifndef __NR_fallocate
+#define __NR_fallocate 314
+#endif
+/* Some syscalls are named/numbered differently between s390 and s390x. */
+#ifdef __s390x__
+# ifndef __NR_getrlimit
+# define __NR_getrlimit 191
+# endif
+# ifndef __NR_setresuid
+# define __NR_setresuid 208
+# endif
+# ifndef __NR_getresuid
+# define __NR_getresuid 209
+# endif
+# ifndef __NR_setresgid
+# define __NR_setresgid 210
+# endif
+# ifndef __NR_getresgid
+# define __NR_getresgid 211
+# endif
+# ifndef __NR_setfsuid
+# define __NR_setfsuid 215
+# endif
+# ifndef __NR_setfsgid
+# define __NR_setfsgid 216
+# endif
+# ifndef __NR_fadvise64
+# define __NR_fadvise64 253
+# endif
+# ifndef __NR_newfstatat
+# define __NR_newfstatat 293
+# endif
+#else /* __s390x__ */
+# ifndef __NR_getrlimit
+# define __NR_getrlimit 76
+# endif
+# ifndef __NR_setfsuid
+# define __NR_setfsuid 138
+# endif
+# ifndef __NR_setfsgid
+# define __NR_setfsgid 139
+# endif
+# ifndef __NR_setresuid
+# define __NR_setresuid 164
+# endif
+# ifndef __NR_getresuid
+# define __NR_getresuid 165
+# endif
+# ifndef __NR_setresgid
+# define __NR_setresgid 170
+# endif
+# ifndef __NR_getresgid
+# define __NR_getresgid 171
+# endif
+# ifndef __NR_ugetrlimit
+# define __NR_ugetrlimit 191
+# endif
+# ifndef __NR_mmap2
+# define __NR_mmap2 192
+# endif
+# ifndef __NR_setresuid32
+# define __NR_setresuid32 208
+# endif
+# ifndef __NR_getresuid32
+# define __NR_getresuid32 209
+# endif
+# ifndef __NR_setresgid32
+# define __NR_setresgid32 210
+# endif
+# ifndef __NR_getresgid32
+# define __NR_getresgid32 211
+# endif
+# ifndef __NR_setfsuid32
+# define __NR_setfsuid32 215
+# endif
+# ifndef __NR_setfsgid32
+# define __NR_setfsgid32 216
+# endif
+# ifndef __NR_fadvise64_64
+# define __NR_fadvise64_64 264
+# endif
+# ifndef __NR_fstatat64
+# define __NR_fstatat64 293
+# endif
+#endif /* __s390__ */
+/* End of s390/s390x definitions */
+#endif
+
+
+/* After forking, we must make sure to only call system calls. */
+#if defined(__BOUNDED_POINTERS__)
+ #error "Need to port invocations of syscalls for bounded ptrs"
+#else
+ /* The core dumper and the thread lister get executed after threads
+ * have been suspended. As a consequence, we cannot call any functions
+ * that acquire locks. Unfortunately, libc wraps most system calls
+ * (e.g. in order to implement pthread_atfork, and to make calls
+ * cancellable), which means we cannot call these functions. Instead,
+ * we have to call syscall() directly.
+ */
+ #undef LSS_ERRNO
+ #ifdef SYS_ERRNO
+ /* Allow the including file to override the location of errno. This can
+ * be useful when using clone() with the CLONE_VM option.
+ */
+ #define LSS_ERRNO SYS_ERRNO
+ #else
+ #define LSS_ERRNO errno
+ #endif
+
+ #undef LSS_INLINE
+ #ifdef SYS_INLINE
+ #define LSS_INLINE SYS_INLINE
+ #else
+ #define LSS_INLINE static inline
+ #endif
+
+ /* Allow the including file to override the prefix used for all new
+ * system calls. By default, it will be set to "sys_".
+ */
+ #undef LSS_NAME
+ #ifndef SYS_PREFIX
+ #define LSS_NAME(name) sys_##name
+ #elif defined(SYS_PREFIX) && SYS_PREFIX < 0
+ #define LSS_NAME(name) name
+ #elif defined(SYS_PREFIX) && SYS_PREFIX == 0
+ #define LSS_NAME(name) sys0_##name
+ #elif defined(SYS_PREFIX) && SYS_PREFIX == 1
+ #define LSS_NAME(name) sys1_##name
+ #elif defined(SYS_PREFIX) && SYS_PREFIX == 2
+ #define LSS_NAME(name) sys2_##name
+ #elif defined(SYS_PREFIX) && SYS_PREFIX == 3
+ #define LSS_NAME(name) sys3_##name
+ #elif defined(SYS_PREFIX) && SYS_PREFIX == 4
+ #define LSS_NAME(name) sys4_##name
+ #elif defined(SYS_PREFIX) && SYS_PREFIX == 5
+ #define LSS_NAME(name) sys5_##name
+ #elif defined(SYS_PREFIX) && SYS_PREFIX == 6
+ #define LSS_NAME(name) sys6_##name
+ #elif defined(SYS_PREFIX) && SYS_PREFIX == 7
+ #define LSS_NAME(name) sys7_##name
+ #elif defined(SYS_PREFIX) && SYS_PREFIX == 8
+ #define LSS_NAME(name) sys8_##name
+ #elif defined(SYS_PREFIX) && SYS_PREFIX == 9
+ #define LSS_NAME(name) sys9_##name
+ #endif
+
+ #undef LSS_RETURN
+ #if (defined(__i386__) || defined(__x86_64__) || defined(__ARM_ARCH_3__) \
+ || defined(__ARM_EABI__) || defined(__aarch64__) || defined(__s390__))
+ /* Failing system calls return a negative result in the range of
+ * -1..-4095. These are "errno" values with the sign inverted.
+ */
+ #define LSS_RETURN(type, res) \
+ do { \
+ if ((unsigned long)(res) >= (unsigned long)(-4095)) { \
+ LSS_ERRNO = -(res); \
+ res = -1; \
+ } \
+ return (type) (res); \
+ } while (0)
+ #elif defined(__mips__)
+ /* On MIPS, failing system calls return -1, and set errno in a
+ * separate CPU register.
+ */
+ #define LSS_RETURN(type, res, err) \
+ do { \
+ if (err) { \
+ unsigned long __errnovalue = (res); \
+ LSS_ERRNO = __errnovalue; \
+ res = -1; \
+ } \
+ return (type) (res); \
+ } while (0)
+ #elif defined(__PPC__)
+ /* On PPC, failing system calls return -1, and set errno in a
+ * separate CPU register. See linux/unistd.h.
+ */
+ #define LSS_RETURN(type, res, err) \
+ do { \
+ if (err & 0x10000000 ) { \
+ LSS_ERRNO = (res); \
+ res = -1; \
+ } \
+ return (type) (res); \
+ } while (0)
+ #endif
+ #if defined(__i386__)
+ /* In PIC mode (e.g. when building shared libraries), gcc for i386
+ * reserves ebx. Unfortunately, most distribution ship with implementations
+ * of _syscallX() which clobber ebx.
+ * Also, most definitions of _syscallX() neglect to mark "memory" as being
+ * clobbered. This causes problems with compilers, that do a better job
+ * at optimizing across __asm__ calls.
+ * So, we just have to redefine all of the _syscallX() macros.
+ */
+ #undef LSS_ENTRYPOINT
+ #ifdef SYS_SYSCALL_ENTRYPOINT
+ static inline void (**LSS_NAME(get_syscall_entrypoint)(void))(void) {
+ void (**entrypoint)(void);
+ asm volatile(".bss\n"
+ ".align 8\n"
+ ".globl " SYS_SYSCALL_ENTRYPOINT "\n"
+ ".common " SYS_SYSCALL_ENTRYPOINT ",8,8\n"
+ ".previous\n"
+ /* This logically does 'lea "SYS_SYSCALL_ENTRYPOINT", %0' */
+ "call 0f\n"
+ "0:pop %0\n"
+ "add $_GLOBAL_OFFSET_TABLE_+[.-0b], %0\n"
+ "mov " SYS_SYSCALL_ENTRYPOINT "@GOT(%0), %0\n"
+ : "=r"(entrypoint));
+ return entrypoint;
+ }
+
+ #define LSS_ENTRYPOINT ".bss\n" \
+ ".align 8\n" \
+ ".globl " SYS_SYSCALL_ENTRYPOINT "\n" \
+ ".common " SYS_SYSCALL_ENTRYPOINT ",8,8\n" \
+ ".previous\n" \
+ /* Check the SYS_SYSCALL_ENTRYPOINT vector */ \
+ "push %%eax\n" \
+ "call 10000f\n" \
+ "10000:pop %%eax\n" \
+ "add $_GLOBAL_OFFSET_TABLE_+[.-10000b], %%eax\n" \
+ "mov " SYS_SYSCALL_ENTRYPOINT \
+ "@GOT(%%eax), %%eax\n" \
+ "mov 0(%%eax), %%eax\n" \
+ "test %%eax, %%eax\n" \
+ "jz 10002f\n" \
+ "push %%eax\n" \
+ "call 10001f\n" \
+ "10001:pop %%eax\n" \
+ "add $(10003f-10001b), %%eax\n" \
+ "xchg 4(%%esp), %%eax\n" \
+ "ret\n" \
+ "10002:pop %%eax\n" \
+ "int $0x80\n" \
+ "10003:\n"
+ #else
+ #define LSS_ENTRYPOINT "int $0x80\n"
+ #endif
+ #undef LSS_BODY
+ #define LSS_BODY(type,args...) \
+ long __res; \
+ __asm__ __volatile__("push %%ebx\n" \
+ "movl %2,%%ebx\n" \
+ LSS_ENTRYPOINT \
+ "pop %%ebx" \
+ args \
+ : "esp", "memory"); \
+ LSS_RETURN(type,__res)
+ #undef _syscall0
+ #define _syscall0(type,name) \
+ type LSS_NAME(name)(void) { \
+ long __res; \
+ __asm__ volatile(LSS_ENTRYPOINT \
+ : "=a" (__res) \
+ : "0" (__NR_##name) \
+ : "memory"); \
+ LSS_RETURN(type,__res); \
+ }
+ #undef _syscall1
+ #define _syscall1(type,name,type1,arg1) \
+ type LSS_NAME(name)(type1 arg1) { \
+ LSS_BODY(type, \
+ : "=a" (__res) \
+ : "0" (__NR_##name), "ri" ((long)(arg1))); \
+ }
+ #undef _syscall2
+ #define _syscall2(type,name,type1,arg1,type2,arg2) \
+ type LSS_NAME(name)(type1 arg1,type2 arg2) { \
+ LSS_BODY(type, \
+ : "=a" (__res) \
+ : "0" (__NR_##name),"ri" ((long)(arg1)), "c" ((long)(arg2))); \
+ }
+ #undef _syscall3
+ #define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \
+ type LSS_NAME(name)(type1 arg1,type2 arg2,type3 arg3) { \
+ LSS_BODY(type, \
+ : "=a" (__res) \
+ : "0" (__NR_##name), "ri" ((long)(arg1)), "c" ((long)(arg2)), \
+ "d" ((long)(arg3))); \
+ }
+ #undef _syscall4
+ #define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
+ type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4) { \
+ LSS_BODY(type, \
+ : "=a" (__res) \
+ : "0" (__NR_##name), "ri" ((long)(arg1)), "c" ((long)(arg2)), \
+ "d" ((long)(arg3)),"S" ((long)(arg4))); \
+ }
+ #undef _syscall5
+ #define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
+ type5,arg5) \
+ type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \
+ type5 arg5) { \
+ long __res; \
+ __asm__ __volatile__("push %%ebx\n" \
+ "movl %2,%%ebx\n" \
+ "movl %1,%%eax\n" \
+ LSS_ENTRYPOINT \
+ "pop %%ebx" \
+ : "=a" (__res) \
+ : "i" (__NR_##name), "ri" ((long)(arg1)), \
+ "c" ((long)(arg2)), "d" ((long)(arg3)), \
+ "S" ((long)(arg4)), "D" ((long)(arg5)) \
+ : "esp", "memory"); \
+ LSS_RETURN(type,__res); \
+ }
+ #undef _syscall6
+ #define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
+ type5,arg5,type6,arg6) \
+ type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \
+ type5 arg5, type6 arg6) { \
+ long __res; \
+ struct { long __a1; long __a6; } __s = { (long)arg1, (long) arg6 }; \
+ __asm__ __volatile__("push %%ebp\n" \
+ "push %%ebx\n" \
+ "movl 4(%2),%%ebp\n" \
+ "movl 0(%2), %%ebx\n" \
+ "movl %1,%%eax\n" \
+ LSS_ENTRYPOINT \
+ "pop %%ebx\n" \
+ "pop %%ebp" \
+ : "=a" (__res) \
+ : "i" (__NR_##name), "0" ((long)(&__s)), \
+ "c" ((long)(arg2)), "d" ((long)(arg3)), \
+ "S" ((long)(arg4)), "D" ((long)(arg5)) \
+ : "esp", "memory"); \
+ LSS_RETURN(type,__res); \
+ }
+ LSS_INLINE int LSS_NAME(clone)(int (*fn)(void *), void *child_stack,
+ int flags, void *arg, int *parent_tidptr,
+ void *newtls, int *child_tidptr) {
+ long __res;
+ __asm__ __volatile__(/* if (fn == NULL)
+ * return -EINVAL;
+ */
+ "movl %3,%%ecx\n"
+ "jecxz 1f\n"
+
+ /* if (child_stack == NULL)
+ * return -EINVAL;
+ */
+ "movl %4,%%ecx\n"
+ "jecxz 1f\n"
+
+ /* Set up alignment of the child stack:
+ * child_stack = (child_stack & ~0xF) - 20;
+ */
+ "andl $-16,%%ecx\n"
+ "subl $20,%%ecx\n"
+
+ /* Push "arg" and "fn" onto the stack that will be
+ * used by the child.
+ */
+ "movl %6,%%eax\n"
+ "movl %%eax,4(%%ecx)\n"
+ "movl %3,%%eax\n"
+ "movl %%eax,(%%ecx)\n"
+
+ /* %eax = syscall(%eax = __NR_clone,
+ * %ebx = flags,
+ * %ecx = child_stack,
+ * %edx = parent_tidptr,
+ * %esi = newtls,
+ * %edi = child_tidptr)
+ * Also, make sure that %ebx gets preserved as it is
+ * used in PIC mode.
+ */
+ "movl %8,%%esi\n"
+ "movl %7,%%edx\n"
+ "movl %5,%%eax\n"
+ "movl %9,%%edi\n"
+ "pushl %%ebx\n"
+ "movl %%eax,%%ebx\n"
+ "movl %2,%%eax\n"
+ LSS_ENTRYPOINT
+
+ /* In the parent: restore %ebx
+ * In the child: move "fn" into %ebx
+ */
+ "popl %%ebx\n"
+
+ /* if (%eax != 0)
+ * return %eax;
+ */
+ "test %%eax,%%eax\n"
+ "jnz 1f\n"
+
+ /* In the child, now. Terminate frame pointer chain.
+ */
+ "movl $0,%%ebp\n"
+
+ /* Call "fn". "arg" is already on the stack.
+ */
+ "call *%%ebx\n"
+
+ /* Call _exit(%ebx). Unfortunately older versions
+ * of gcc restrict the number of arguments that can
+ * be passed to asm(). So, we need to hard-code the
+ * system call number.
+ */
+ "movl %%eax,%%ebx\n"
+ "movl $1,%%eax\n"
+ LSS_ENTRYPOINT
+
+ /* Return to parent.
+ */
+ "1:\n"
+ : "=a" (__res)
+ : "0"(-EINVAL), "i"(__NR_clone),
+ "m"(fn), "m"(child_stack), "m"(flags), "m"(arg),
+ "m"(parent_tidptr), "m"(newtls), "m"(child_tidptr)
+ : "esp", "memory", "ecx", "edx", "esi", "edi");
+ LSS_RETURN(int, __res);
+ }
+
+ LSS_INLINE _syscall1(int, set_thread_area, void *, u)
+ LSS_INLINE _syscall1(int, get_thread_area, void *, u)
+
+ LSS_INLINE void (*LSS_NAME(restore_rt)(void))(void) {
+ /* On i386, the kernel does not know how to return from a signal
+ * handler. Instead, it relies on user space to provide a
+ * restorer function that calls the {rt_,}sigreturn() system call.
+ * Unfortunately, we cannot just reference the glibc version of this
+ * function, as glibc goes out of its way to make it inaccessible.
+ */
+ void (*res)(void);
+ __asm__ __volatile__("call 2f\n"
+ "0:.align 16\n"
+ "1:movl %1,%%eax\n"
+ LSS_ENTRYPOINT
+ "2:popl %0\n"
+ "addl $(1b-0b),%0\n"
+ : "=a" (res)
+ : "i" (__NR_rt_sigreturn));
+ return res;
+ }
+ LSS_INLINE void (*LSS_NAME(restore)(void))(void) {
+ /* On i386, the kernel does not know how to return from a signal
+ * handler. Instead, it relies on user space to provide a
+ * restorer function that calls the {rt_,}sigreturn() system call.
+ * Unfortunately, we cannot just reference the glibc version of this
+ * function, as glibc goes out of its way to make it inaccessible.
+ */
+ void (*res)(void);
+ __asm__ __volatile__("call 2f\n"
+ "0:.align 16\n"
+ "1:pop %%eax\n"
+ "movl %1,%%eax\n"
+ LSS_ENTRYPOINT
+ "2:popl %0\n"
+ "addl $(1b-0b),%0\n"
+ : "=a" (res)
+ : "i" (__NR_sigreturn));
+ return res;
+ }
+ #elif defined(__x86_64__)
+ /* There are no known problems with any of the _syscallX() macros
+ * currently shipping for x86_64, but we still need to be able to define
+ * our own version so that we can override the location of the errno
+ * location (e.g. when using the clone() system call with the CLONE_VM
+ * option).
+ */
+ #undef LSS_ENTRYPOINT
+ #ifdef SYS_SYSCALL_ENTRYPOINT
+ static inline void (**LSS_NAME(get_syscall_entrypoint)(void))(void) {
+ void (**entrypoint)(void);
+ asm volatile(".bss\n"
+ ".align 8\n"
+ ".globl " SYS_SYSCALL_ENTRYPOINT "\n"
+ ".common " SYS_SYSCALL_ENTRYPOINT ",8,8\n"
+ ".previous\n"
+ "mov " SYS_SYSCALL_ENTRYPOINT "@GOTPCREL(%%rip), %0\n"
+ : "=r"(entrypoint));
+ return entrypoint;
+ }
+
+ #define LSS_ENTRYPOINT \
+ ".bss\n" \
+ ".align 8\n" \
+ ".globl " SYS_SYSCALL_ENTRYPOINT "\n" \
+ ".common " SYS_SYSCALL_ENTRYPOINT ",8,8\n" \
+ ".previous\n" \
+ "mov " SYS_SYSCALL_ENTRYPOINT "@GOTPCREL(%%rip), %%rcx\n" \
+ "mov 0(%%rcx), %%rcx\n" \
+ "test %%rcx, %%rcx\n" \
+ "jz 10001f\n" \
+ "call *%%rcx\n" \
+ "jmp 10002f\n" \
+ "10001:syscall\n" \
+ "10002:\n"
+
+ #else
+ #define LSS_ENTRYPOINT "syscall\n"
+ #endif
+
+ /* The x32 ABI has 32 bit longs, but the syscall interface is 64 bit.
+ * We need to explicitly cast to an unsigned 64 bit type to avoid implicit
+ * sign extension. We can't cast pointers directly because those are
+ * 32 bits, and gcc will dump ugly warnings about casting from a pointer
+ * to an integer of a different size.
+ */
+ #undef LSS_SYSCALL_ARG
+ #define LSS_SYSCALL_ARG(a) ((uint64_t)(uintptr_t)(a))
+ #undef _LSS_RETURN
+ #define _LSS_RETURN(type, res, cast) \
+ do { \
+ if ((uint64_t)(res) >= (uint64_t)(-4095)) { \
+ LSS_ERRNO = -(res); \
+ res = -1; \
+ } \
+ return (type)(cast)(res); \
+ } while (0)
+ #undef LSS_RETURN
+ #define LSS_RETURN(type, res) _LSS_RETURN(type, res, uintptr_t)
+
+ #undef _LSS_BODY
+ #define _LSS_BODY(nr, type, name, cast, ...) \
+ long long __res; \
+ __asm__ __volatile__(LSS_BODY_ASM##nr LSS_ENTRYPOINT \
+ : "=a" (__res) \
+ : "0" (__NR_##name) LSS_BODY_ARG##nr(__VA_ARGS__) \
+ : LSS_BODY_CLOBBER##nr "r11", "rcx", "memory"); \
+ _LSS_RETURN(type, __res, cast)
+ #undef LSS_BODY
+ #define LSS_BODY(nr, type, name, args...) \
+ _LSS_BODY(nr, type, name, uintptr_t, ## args)
+
+ #undef LSS_BODY_ASM0
+ #undef LSS_BODY_ASM1
+ #undef LSS_BODY_ASM2
+ #undef LSS_BODY_ASM3
+ #undef LSS_BODY_ASM4
+ #undef LSS_BODY_ASM5
+ #undef LSS_BODY_ASM6
+ #define LSS_BODY_ASM0
+ #define LSS_BODY_ASM1 LSS_BODY_ASM0
+ #define LSS_BODY_ASM2 LSS_BODY_ASM1
+ #define LSS_BODY_ASM3 LSS_BODY_ASM2
+ #define LSS_BODY_ASM4 LSS_BODY_ASM3 "movq %5,%%r10;"
+ #define LSS_BODY_ASM5 LSS_BODY_ASM4 "movq %6,%%r8;"
+ #define LSS_BODY_ASM6 LSS_BODY_ASM5 "movq %7,%%r9;"
+
+ #undef LSS_BODY_CLOBBER0
+ #undef LSS_BODY_CLOBBER1
+ #undef LSS_BODY_CLOBBER2
+ #undef LSS_BODY_CLOBBER3
+ #undef LSS_BODY_CLOBBER4
+ #undef LSS_BODY_CLOBBER5
+ #undef LSS_BODY_CLOBBER6
+ #define LSS_BODY_CLOBBER0
+ #define LSS_BODY_CLOBBER1 LSS_BODY_CLOBBER0
+ #define LSS_BODY_CLOBBER2 LSS_BODY_CLOBBER1
+ #define LSS_BODY_CLOBBER3 LSS_BODY_CLOBBER2
+ #define LSS_BODY_CLOBBER4 LSS_BODY_CLOBBER3 "r10",
+ #define LSS_BODY_CLOBBER5 LSS_BODY_CLOBBER4 "r8",
+ #define LSS_BODY_CLOBBER6 LSS_BODY_CLOBBER5 "r9",
+
+ #undef LSS_BODY_ARG0
+ #undef LSS_BODY_ARG1
+ #undef LSS_BODY_ARG2
+ #undef LSS_BODY_ARG3
+ #undef LSS_BODY_ARG4
+ #undef LSS_BODY_ARG5
+ #undef LSS_BODY_ARG6
+ #define LSS_BODY_ARG0()
+ #define LSS_BODY_ARG1(arg1) \
+ LSS_BODY_ARG0(), "D" (arg1)
+ #define LSS_BODY_ARG2(arg1, arg2) \
+ LSS_BODY_ARG1(arg1), "S" (arg2)
+ #define LSS_BODY_ARG3(arg1, arg2, arg3) \
+ LSS_BODY_ARG2(arg1, arg2), "d" (arg3)
+ #define LSS_BODY_ARG4(arg1, arg2, arg3, arg4) \
+ LSS_BODY_ARG3(arg1, arg2, arg3), "r" (arg4)
+ #define LSS_BODY_ARG5(arg1, arg2, arg3, arg4, arg5) \
+ LSS_BODY_ARG4(arg1, arg2, arg3, arg4), "r" (arg5)
+ #define LSS_BODY_ARG6(arg1, arg2, arg3, arg4, arg5, arg6) \
+ LSS_BODY_ARG5(arg1, arg2, arg3, arg4, arg5), "r" (arg6)
+
+ #undef _syscall0
+ #define _syscall0(type,name) \
+ type LSS_NAME(name)(void) { \
+ LSS_BODY(0, type, name); \
+ }
+ #undef _syscall1
+ #define _syscall1(type,name,type1,arg1) \
+ type LSS_NAME(name)(type1 arg1) { \
+ LSS_BODY(1, type, name, LSS_SYSCALL_ARG(arg1)); \
+ }
+ #undef _syscall2
+ #define _syscall2(type,name,type1,arg1,type2,arg2) \
+ type LSS_NAME(name)(type1 arg1, type2 arg2) { \
+ LSS_BODY(2, type, name, LSS_SYSCALL_ARG(arg1), LSS_SYSCALL_ARG(arg2));\
+ }
+ #undef _syscall3
+ #define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \
+ type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3) { \
+ LSS_BODY(3, type, name, LSS_SYSCALL_ARG(arg1), LSS_SYSCALL_ARG(arg2), \
+ LSS_SYSCALL_ARG(arg3)); \
+ }
+ #undef _syscall4
+ #define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
+ type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4) { \
+ LSS_BODY(4, type, name, LSS_SYSCALL_ARG(arg1), LSS_SYSCALL_ARG(arg2), \
+ LSS_SYSCALL_ARG(arg3), LSS_SYSCALL_ARG(arg4));\
+ }
+ #undef _syscall5
+ #define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
+ type5,arg5) \
+ type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \
+ type5 arg5) { \
+ LSS_BODY(5, type, name, LSS_SYSCALL_ARG(arg1), LSS_SYSCALL_ARG(arg2), \
+ LSS_SYSCALL_ARG(arg3), LSS_SYSCALL_ARG(arg4), \
+ LSS_SYSCALL_ARG(arg5)); \
+ }
+ #undef _syscall6
+ #define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
+ type5,arg5,type6,arg6) \
+ type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \
+ type5 arg5, type6 arg6) { \
+ LSS_BODY(6, type, name, LSS_SYSCALL_ARG(arg1), LSS_SYSCALL_ARG(arg2), \
+ LSS_SYSCALL_ARG(arg3), LSS_SYSCALL_ARG(arg4), \
+ LSS_SYSCALL_ARG(arg5), LSS_SYSCALL_ARG(arg6));\
+ }
+ LSS_INLINE int LSS_NAME(clone)(int (*fn)(void *), void *child_stack,
+ int flags, void *arg, int *parent_tidptr,
+ void *newtls, int *child_tidptr) {
+ long long __res;
+ {
+ __asm__ __volatile__(/* if (fn == NULL)
+ * return -EINVAL;
+ */
+ "testq %4,%4\n"
+ "jz 1f\n"
+
+ /* if (child_stack == NULL)
+ * return -EINVAL;
+ */
+ "testq %5,%5\n"
+ "jz 1f\n"
+
+ /* childstack -= 2*sizeof(void *);
+ */
+ "subq $16,%5\n"
+
+ /* Push "arg" and "fn" onto the stack that will be
+ * used by the child.
+ */
+ "movq %7,8(%5)\n"
+ "movq %4,0(%5)\n"
+
+ /* %rax = syscall(%rax = __NR_clone,
+ * %rdi = flags,
+ * %rsi = child_stack,
+ * %rdx = parent_tidptr,
+ * %r8 = new_tls,
+ * %r10 = child_tidptr)
+ */
+ "movq %2,%%rax\n"
+ "movq %9,%%r8\n"
+ "movq %10,%%r10\n"
+ LSS_ENTRYPOINT
+
+ /* if (%rax != 0)
+ * return;
+ */
+ "testq %%rax,%%rax\n"
+ "jnz 1f\n"
+
+ /* In the child. Terminate frame pointer chain.
+ */
+ "xorq %%rbp,%%rbp\n"
+
+ /* Call "fn(arg)".
+ */
+ "popq %%rax\n"
+ "popq %%rdi\n"
+ "call *%%rax\n"
+
+ /* Call _exit(%ebx).
+ */
+ "movq %%rax,%%rdi\n"
+ "movq %3,%%rax\n"
+ LSS_ENTRYPOINT
+
+ /* Return to parent.
+ */
+ "1:\n"
+ : "=a" (__res)
+ : "0"(-EINVAL), "i"(__NR_clone), "i"(__NR_exit),
+ "r"(LSS_SYSCALL_ARG(fn)),
+ "S"(LSS_SYSCALL_ARG(child_stack)),
+ "D"(LSS_SYSCALL_ARG(flags)),
+ "r"(LSS_SYSCALL_ARG(arg)),
+ "d"(LSS_SYSCALL_ARG(parent_tidptr)),
+ "r"(LSS_SYSCALL_ARG(newtls)),
+ "r"(LSS_SYSCALL_ARG(child_tidptr))
+ : "memory", "r8", "r10", "r11", "rcx");
+ }
+ LSS_RETURN(int, __res);
+ }
+ LSS_INLINE _syscall2(int, arch_prctl, int, c, void *, a)
+
+ LSS_INLINE void (*LSS_NAME(restore_rt)(void))(void) {
+ /* On x86-64, the kernel does not know how to return from
+ * a signal handler. Instead, it relies on user space to provide a
+ * restorer function that calls the rt_sigreturn() system call.
+ * Unfortunately, we cannot just reference the glibc version of this
+ * function, as glibc goes out of its way to make it inaccessible.
+ */
+ long long res;
+ __asm__ __volatile__("jmp 2f\n"
+ ".align 16\n"
+ "1:movq %1,%%rax\n"
+ LSS_ENTRYPOINT
+ "2:leaq 1b(%%rip),%0\n"
+ : "=r" (res)
+ : "i" (__NR_rt_sigreturn));
+ return (void (*)(void))(uintptr_t)res;
+ }
+ #elif defined(__ARM_ARCH_3__)
+ /* Most definitions of _syscallX() neglect to mark "memory" as being
+ * clobbered. This causes problems with compilers, that do a better job
+ * at optimizing across __asm__ calls.
+ * So, we just have to redefine all of the _syscallX() macros.
+ */
+ #undef LSS_REG
+ #define LSS_REG(r,a) register long __r##r __asm__("r"#r) = (long)a
+ #undef LSS_BODY
+ #define LSS_BODY(type,name,args...) \
+ register long __res_r0 __asm__("r0"); \
+ long __res; \
+ __asm__ __volatile__ (__syscall(name) \
+ : "=r"(__res_r0) : args : "lr", "memory"); \
+ __res = __res_r0; \
+ LSS_RETURN(type, __res)
+ #undef _syscall0
+ #define _syscall0(type, name) \
+ type LSS_NAME(name)(void) { \
+ LSS_BODY(type, name); \
+ }
+ #undef _syscall1
+ #define _syscall1(type, name, type1, arg1) \
+ type LSS_NAME(name)(type1 arg1) { \
+ LSS_REG(0, arg1); LSS_BODY(type, name, "r"(__r0)); \
+ }
+ #undef _syscall2
+ #define _syscall2(type, name, type1, arg1, type2, arg2) \
+ type LSS_NAME(name)(type1 arg1, type2 arg2) { \
+ LSS_REG(0, arg1); LSS_REG(1, arg2); \
+ LSS_BODY(type, name, "r"(__r0), "r"(__r1)); \
+ }
+ #undef _syscall3
+ #define _syscall3(type, name, type1, arg1, type2, arg2, type3, arg3) \
+ type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3) { \
+ LSS_REG(0, arg1); LSS_REG(1, arg2); LSS_REG(2, arg3); \
+ LSS_BODY(type, name, "r"(__r0), "r"(__r1), "r"(__r2)); \
+ }
+ #undef _syscall4
+ #define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
+ type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4) { \
+ LSS_REG(0, arg1); LSS_REG(1, arg2); LSS_REG(2, arg3); \
+ LSS_REG(3, arg4); \
+ LSS_BODY(type, name, "r"(__r0), "r"(__r1), "r"(__r2), "r"(__r3)); \
+ }
+ #undef _syscall5
+ #define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
+ type5,arg5) \
+ type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \
+ type5 arg5) { \
+ LSS_REG(0, arg1); LSS_REG(1, arg2); LSS_REG(2, arg3); \
+ LSS_REG(3, arg4); LSS_REG(4, arg5); \
+ LSS_BODY(type, name, "r"(__r0), "r"(__r1), "r"(__r2), "r"(__r3), \
+ "r"(__r4)); \
+ }
+ #undef _syscall6
+ #define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
+ type5,arg5,type6,arg6) \
+ type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \
+ type5 arg5, type6 arg6) { \
+ LSS_REG(0, arg1); LSS_REG(1, arg2); LSS_REG(2, arg3); \
+ LSS_REG(3, arg4); LSS_REG(4, arg5); LSS_REG(5, arg6); \
+ LSS_BODY(type, name, "r"(__r0), "r"(__r1), "r"(__r2), "r"(__r3), \
+ "r"(__r4), "r"(__r5)); \
+ }
+ LSS_INLINE int LSS_NAME(clone)(int (*fn)(void *), void *child_stack,
+ int flags, void *arg, int *parent_tidptr,
+ void *newtls, int *child_tidptr) {
+ long __res;
+ {
+ register int __flags __asm__("r0") = flags;
+ register void *__stack __asm__("r1") = child_stack;
+ register void *__ptid __asm__("r2") = parent_tidptr;
+ register void *__tls __asm__("r3") = newtls;
+ register int *__ctid __asm__("r4") = child_tidptr;
+ __asm__ __volatile__(/* if (fn == NULL || child_stack == NULL)
+ * return -EINVAL;
+ */
+ "cmp %2,#0\n"
+ "cmpne %3,#0\n"
+ "moveq %0,%1\n"
+ "beq 1f\n"
+
+ /* Push "arg" and "fn" onto the stack that will be
+ * used by the child.
+ */
+ "str %5,[%3,#-4]!\n"
+ "str %2,[%3,#-4]!\n"
+
+ /* %r0 = syscall(%r0 = flags,
+ * %r1 = child_stack,
+ * %r2 = parent_tidptr,
+ * %r3 = newtls,
+ * %r4 = child_tidptr)
+ */
+ __syscall(clone)"\n"
+
+ /* if (%r0 != 0)
+ * return %r0;
+ */
+ "movs %0,r0\n"
+ "bne 1f\n"
+
+ /* In the child, now. Call "fn(arg)".
+ */
+ "ldr r0,[sp, #4]\n"
+ "mov lr,pc\n"
+ "ldr pc,[sp]\n"
+
+ /* Call _exit(%r0).
+ */
+ __syscall(exit)"\n"
+ "1:\n"
+ : "=r" (__res)
+ : "i"(-EINVAL),
+ "r"(fn), "r"(__stack), "r"(__flags), "r"(arg),
+ "r"(__ptid), "r"(__tls), "r"(__ctid)
+ : "cc", "lr", "memory");
+ }
+ LSS_RETURN(int, __res);
+ }
+ #elif defined(__ARM_EABI__)
+ /* Most definitions of _syscallX() neglect to mark "memory" as being
+ * clobbered. This causes problems with compilers, that do a better job
+ * at optimizing across __asm__ calls.
+ * So, we just have to redefine all fo the _syscallX() macros.
+ */
+ #undef LSS_REG
+ #define LSS_REG(r,a) register long __r##r __asm__("r"#r) = (long)a
+ #undef LSS_BODY
+ #define LSS_BODY(type,name,args...) \
+ register long __res_r0 __asm__("r0"); \
+ long __res; \
+ __asm__ __volatile__ ("push {r7}\n" \
+ "mov r7, %1\n" \
+ "swi 0x0\n" \
+ "pop {r7}\n" \
+ : "=r"(__res_r0) \
+ : "i"(__NR_##name) , ## args \
+ : "lr", "memory"); \
+ __res = __res_r0; \
+ LSS_RETURN(type, __res)
+ #undef _syscall0
+ #define _syscall0(type, name) \
+ type LSS_NAME(name)(void) { \
+ LSS_BODY(type, name); \
+ }
+ #undef _syscall1
+ #define _syscall1(type, name, type1, arg1) \
+ type LSS_NAME(name)(type1 arg1) { \
+ LSS_REG(0, arg1); LSS_BODY(type, name, "r"(__r0)); \
+ }
+ #undef _syscall2
+ #define _syscall2(type, name, type1, arg1, type2, arg2) \
+ type LSS_NAME(name)(type1 arg1, type2 arg2) { \
+ LSS_REG(0, arg1); LSS_REG(1, arg2); \
+ LSS_BODY(type, name, "r"(__r0), "r"(__r1)); \
+ }
+ #undef _syscall3
+ #define _syscall3(type, name, type1, arg1, type2, arg2, type3, arg3) \
+ type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3) { \
+ LSS_REG(0, arg1); LSS_REG(1, arg2); LSS_REG(2, arg3); \
+ LSS_BODY(type, name, "r"(__r0), "r"(__r1), "r"(__r2)); \
+ }
+ #undef _syscall4
+ #define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
+ type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4) { \
+ LSS_REG(0, arg1); LSS_REG(1, arg2); LSS_REG(2, arg3); \
+ LSS_REG(3, arg4); \
+ LSS_BODY(type, name, "r"(__r0), "r"(__r1), "r"(__r2), "r"(__r3)); \
+ }
+ #undef _syscall5
+ #define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
+ type5,arg5) \
+ type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \
+ type5 arg5) { \
+ LSS_REG(0, arg1); LSS_REG(1, arg2); LSS_REG(2, arg3); \
+ LSS_REG(3, arg4); LSS_REG(4, arg5); \
+ LSS_BODY(type, name, "r"(__r0), "r"(__r1), "r"(__r2), "r"(__r3), \
+ "r"(__r4)); \
+ }
+ #undef _syscall6
+ #define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
+ type5,arg5,type6,arg6) \
+ type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \
+ type5 arg5, type6 arg6) { \
+ LSS_REG(0, arg1); LSS_REG(1, arg2); LSS_REG(2, arg3); \
+ LSS_REG(3, arg4); LSS_REG(4, arg5); LSS_REG(5, arg6); \
+ LSS_BODY(type, name, "r"(__r0), "r"(__r1), "r"(__r2), "r"(__r3), \
+ "r"(__r4), "r"(__r5)); \
+ }
+ LSS_INLINE int LSS_NAME(clone)(int (*fn)(void *), void *child_stack,
+ int flags, void *arg, int *parent_tidptr,
+ void *newtls, int *child_tidptr) {
+ long __res;
+ if (fn == NULL || child_stack == NULL) {
+ __res = -EINVAL;
+ LSS_RETURN(int, __res);
+ }
+
+ /* Push "arg" and "fn" onto the stack that will be
+ * used by the child.
+ */
+ {
+ uintptr_t* cstack = (uintptr_t*)child_stack - 2;
+ cstack[0] = (uintptr_t)fn;
+ cstack[1] = (uintptr_t)arg;
+ child_stack = cstack;
+ }
+ {
+ register int __flags __asm__("r0") = flags;
+ register void *__stack __asm__("r1") = child_stack;
+ register void *__ptid __asm__("r2") = parent_tidptr;
+ register void *__tls __asm__("r3") = newtls;
+ register int *__ctid __asm__("r4") = child_tidptr;
+ __asm__ __volatile__(
+#ifdef __thumb2__
+ "push {r7}\n"
+#endif
+ /* %r0 = syscall(%r0 = flags,
+ * %r1 = child_stack,
+ * %r2 = parent_tidptr,
+ * %r3 = newtls,
+ * %r4 = child_tidptr)
+ */
+ "mov r7, %6\n"
+ "swi 0x0\n"
+
+ /* if (%r0 != 0)
+ * return %r0;
+ */
+ "cmp r0, #0\n"
+ "bne 1f\n"
+
+ /* In the child, now. Call "fn(arg)".
+ */
+ "ldr r0,[sp, #4]\n"
+
+ "ldr lr,[sp]\n"
+ "blx lr\n"
+
+ /* Call _exit(%r0).
+ */
+ "mov r7, %7\n"
+ "swi 0x0\n"
+ /* Unreachable */
+ "bkpt #0\n"
+ "1:\n"
+#ifdef __thumb2__
+ "pop {r7}\n"
+#endif
+ "movs %0,r0\n"
+ : "=r"(__res)
+ : "r"(__stack), "r"(__flags), "r"(__ptid), "r"(__tls), "r"(__ctid),
+ "i"(__NR_clone), "i"(__NR_exit)
+ : "cc", "lr", "memory"
+#ifndef __thumb2__
+ , "r7"
+#endif
+ );
+ }
+ LSS_RETURN(int, __res);
+ }
+ #elif defined(__aarch64__)
+ /* Most definitions of _syscallX() neglect to mark "memory" as being
+ * clobbered. This causes problems with compilers, that do a better job
+ * at optimizing across __asm__ calls.
+ * So, we just have to redefine all of the _syscallX() macros.
+ */
+ #undef LSS_REG
+ #define LSS_REG(r,a) register int64_t __r##r __asm__("x"#r) = (int64_t)a
+ #undef LSS_BODY
+ #define LSS_BODY(type,name,args...) \
+ register int64_t __res_x0 __asm__("x0"); \
+ int64_t __res; \
+ __asm__ __volatile__ ("mov x8, %1\n" \
+ "svc 0x0\n" \
+ : "=r"(__res_x0) \
+ : "i"(__NR_##name) , ## args \
+ : "x8", "memory"); \
+ __res = __res_x0; \
+ LSS_RETURN(type, __res)
+ #undef _syscall0
+ #define _syscall0(type, name) \
+ type LSS_NAME(name)(void) { \
+ LSS_BODY(type, name); \
+ }
+ #undef _syscall1
+ #define _syscall1(type, name, type1, arg1) \
+ type LSS_NAME(name)(type1 arg1) { \
+ LSS_REG(0, arg1); LSS_BODY(type, name, "r"(__r0)); \
+ }
+ #undef _syscall2
+ #define _syscall2(type, name, type1, arg1, type2, arg2) \
+ type LSS_NAME(name)(type1 arg1, type2 arg2) { \
+ LSS_REG(0, arg1); LSS_REG(1, arg2); \
+ LSS_BODY(type, name, "r"(__r0), "r"(__r1)); \
+ }
+ #undef _syscall3
+ #define _syscall3(type, name, type1, arg1, type2, arg2, type3, arg3) \
+ type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3) { \
+ LSS_REG(0, arg1); LSS_REG(1, arg2); LSS_REG(2, arg3); \
+ LSS_BODY(type, name, "r"(__r0), "r"(__r1), "r"(__r2)); \
+ }
+ #undef _syscall4
+ #define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
+ type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4) { \
+ LSS_REG(0, arg1); LSS_REG(1, arg2); LSS_REG(2, arg3); \
+ LSS_REG(3, arg4); \
+ LSS_BODY(type, name, "r"(__r0), "r"(__r1), "r"(__r2), "r"(__r3)); \
+ }
+ #undef _syscall5
+ #define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
+ type5,arg5) \
+ type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \
+ type5 arg5) { \
+ LSS_REG(0, arg1); LSS_REG(1, arg2); LSS_REG(2, arg3); \
+ LSS_REG(3, arg4); LSS_REG(4, arg5); \
+ LSS_BODY(type, name, "r"(__r0), "r"(__r1), "r"(__r2), "r"(__r3), \
+ "r"(__r4)); \
+ }
+ #undef _syscall6
+ #define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
+ type5,arg5,type6,arg6) \
+ type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \
+ type5 arg5, type6 arg6) { \
+ LSS_REG(0, arg1); LSS_REG(1, arg2); LSS_REG(2, arg3); \
+ LSS_REG(3, arg4); LSS_REG(4, arg5); LSS_REG(5, arg6); \
+ LSS_BODY(type, name, "r"(__r0), "r"(__r1), "r"(__r2), "r"(__r3), \
+ "r"(__r4), "r"(__r5)); \
+ }
+
+ LSS_INLINE int LSS_NAME(clone)(int (*fn)(void *), void *child_stack,
+ int flags, void *arg, int *parent_tidptr,
+ void *newtls, int *child_tidptr) {
+ int64_t __res;
+ {
+ register uint64_t __flags __asm__("x0") = flags;
+ register void *__stack __asm__("x1") = child_stack;
+ register void *__ptid __asm__("x2") = parent_tidptr;
+ register void *__tls __asm__("x3") = newtls;
+ register int *__ctid __asm__("x4") = child_tidptr;
+ __asm__ __volatile__(/* Push "arg" and "fn" onto the stack that will be
+ * used by the child.
+ */
+ "stp %1, %4, [%2, #-16]!\n"
+
+ /* %x0 = syscall(%x0 = flags,
+ * %x1 = child_stack,
+ * %x2 = parent_tidptr,
+ * %x3 = newtls,
+ * %x4 = child_tidptr)
+ */
+ "mov x8, %8\n"
+ "svc 0x0\n"
+
+ /* if (%r0 != 0)
+ * return %r0;
+ */
+ "mov %0, x0\n"
+ "cbnz x0, 1f\n"
+
+ /* In the child, now. Call "fn(arg)".
+ */
+ "ldp x1, x0, [sp], #16\n"
+ "blr x1\n"
+
+ /* Call _exit(%r0).
+ */
+ "mov x8, %9\n"
+ "svc 0x0\n"
+ "1:\n"
+ : "=r" (__res)
+ : "r"(fn), "r"(__stack), "r"(__flags), "r"(arg),
+ "r"(__ptid), "r"(__tls), "r"(__ctid),
+ "i"(__NR_clone), "i"(__NR_exit)
+ : "cc", "x8", "memory");
+ }
+ LSS_RETURN(int, __res);
+ }
+ #elif defined(__mips__)
+ #undef LSS_REG
+ #define LSS_REG(r,a) register unsigned long __r##r __asm__("$"#r) = \
+ (unsigned long)(a)
+ #undef LSS_BODY
+ #undef LSS_SYSCALL_CLOBBERS
+ #if _MIPS_SIM == _MIPS_SIM_ABI32
+ #define LSS_SYSCALL_CLOBBERS "$1", "$3", "$8", "$9", "$10", \
+ "$11", "$12", "$13", "$14", "$15", \
+ "$24", "$25", "hi", "lo", "memory"
+ #else
+ #define LSS_SYSCALL_CLOBBERS "$1", "$3", "$10", "$11", "$12", \
+ "$13", "$14", "$15", "$24", "$25", \
+ "hi", "lo", "memory"
+ #endif
+ #define LSS_BODY(type,name,r7,...) \
+ register unsigned long __v0 __asm__("$2") = __NR_##name; \
+ __asm__ __volatile__ ("syscall\n" \
+ : "=r"(__v0), r7 (__r7) \
+ : "0"(__v0), ##__VA_ARGS__ \
+ : LSS_SYSCALL_CLOBBERS); \
+ LSS_RETURN(type, __v0, __r7)
+ #undef _syscall0
+ #define _syscall0(type, name) \
+ type LSS_NAME(name)(void) { \
+ register unsigned long __r7 __asm__("$7"); \
+ LSS_BODY(type, name, "=r"); \
+ }
+ #undef _syscall1
+ #define _syscall1(type, name, type1, arg1) \
+ type LSS_NAME(name)(type1 arg1) { \
+ register unsigned long __r7 __asm__("$7"); \
+ LSS_REG(4, arg1); LSS_BODY(type, name, "=r", "r"(__r4)); \
+ }
+ #undef _syscall2
+ #define _syscall2(type, name, type1, arg1, type2, arg2) \
+ type LSS_NAME(name)(type1 arg1, type2 arg2) { \
+ register unsigned long __r7 __asm__("$7"); \
+ LSS_REG(4, arg1); LSS_REG(5, arg2); \
+ LSS_BODY(type, name, "=r", "r"(__r4), "r"(__r5)); \
+ }
+ #undef _syscall3
+ #define _syscall3(type, name, type1, arg1, type2, arg2, type3, arg3) \
+ type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3) { \
+ register unsigned long __r7 __asm__("$7"); \
+ LSS_REG(4, arg1); LSS_REG(5, arg2); LSS_REG(6, arg3); \
+ LSS_BODY(type, name, "=r", "r"(__r4), "r"(__r5), "r"(__r6)); \
+ }
+ #undef _syscall4
+ #define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
+ type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4) { \
+ LSS_REG(4, arg1); LSS_REG(5, arg2); LSS_REG(6, arg3); \
+ LSS_REG(7, arg4); \
+ LSS_BODY(type, name, "+r", "r"(__r4), "r"(__r5), "r"(__r6)); \
+ }
+ #undef _syscall5
+ #if _MIPS_SIM == _MIPS_SIM_ABI32
+ /* The old 32bit MIPS system call API passes the fifth and sixth argument
+ * on the stack, whereas the new APIs use registers "r8" and "r9".
+ */
+ #define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
+ type5,arg5) \
+ type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \
+ type5 arg5) { \
+ LSS_REG(4, arg1); LSS_REG(5, arg2); LSS_REG(6, arg3); \
+ LSS_REG(7, arg4); \
+ register unsigned long __v0 __asm__("$2") = __NR_##name; \
+ __asm__ __volatile__ (".set noreorder\n" \
+ "subu $29, 32\n" \
+ "sw %5, 16($29)\n" \
+ "syscall\n" \
+ "addiu $29, 32\n" \
+ ".set reorder\n" \
+ : "+r"(__v0), "+r" (__r7) \
+ : "r"(__r4), "r"(__r5), \
+ "r"(__r6), "r" ((unsigned long)arg5) \
+ : "$8", "$9", "$10", "$11", "$12", \
+ "$13", "$14", "$15", "$24", "$25", \
+ "memory"); \
+ LSS_RETURN(type, __v0, __r7); \
+ }
+ #else
+ #define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
+ type5,arg5) \
+ type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \
+ type5 arg5) { \
+ LSS_REG(4, arg1); LSS_REG(5, arg2); LSS_REG(6, arg3); \
+ LSS_REG(7, arg4); LSS_REG(8, arg5); \
+ LSS_BODY(type, name, "+r", "r"(__r4), "r"(__r5), "r"(__r6), \
+ "r"(__r8)); \
+ }
+ #endif
+ #undef _syscall6
+ #if _MIPS_SIM == _MIPS_SIM_ABI32
+ /* The old 32bit MIPS system call API passes the fifth and sixth argument
+ * on the stack, whereas the new APIs use registers "r8" and "r9".
+ */
+ #define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
+ type5,arg5,type6,arg6) \
+ type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \
+ type5 arg5, type6 arg6) { \
+ LSS_REG(4, arg1); LSS_REG(5, arg2); LSS_REG(6, arg3); \
+ LSS_REG(7, arg4); \
+ register unsigned long __v0 __asm__("$2") = __NR_##name; \
+ __asm__ __volatile__ (".set noreorder\n" \
+ "subu $29, 32\n" \
+ "sw %5, 16($29)\n" \
+ "sw %6, 20($29)\n" \
+ "syscall\n" \
+ "addiu $29, 32\n" \
+ ".set reorder\n" \
+ : "+r"(__v0), "+r" (__r7) \
+ : "r"(__r4), "r"(__r5), \
+ "r"(__r6), "r" ((unsigned long)arg5), \
+ "r" ((unsigned long)arg6) \
+ : "$8", "$9", "$10", "$11", "$12", \
+ "$13", "$14", "$15", "$24", "$25", \
+ "memory"); \
+ LSS_RETURN(type, __v0, __r7); \
+ }
+ #else
+ #define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
+ type5,arg5,type6,arg6) \
+ type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \
+ type5 arg5,type6 arg6) { \
+ LSS_REG(4, arg1); LSS_REG(5, arg2); LSS_REG(6, arg3); \
+ LSS_REG(7, arg4); LSS_REG(8, arg5); LSS_REG(9, arg6); \
+ LSS_BODY(type, name, "+r", "r"(__r4), "r"(__r5), "r"(__r6), \
+ "r"(__r8), "r"(__r9)); \
+ }
+ #endif
+ LSS_INLINE int LSS_NAME(clone)(int (*fn)(void *), void *child_stack,
+ int flags, void *arg, int *parent_tidptr,
+ void *newtls, int *child_tidptr) {
+ register unsigned long __v0 __asm__("$2") = -EINVAL;
+ register unsigned long __r7 __asm__("$7") = (unsigned long)newtls;
+ {
+ register int __flags __asm__("$4") = flags;
+ register void *__stack __asm__("$5") = child_stack;
+ register void *__ptid __asm__("$6") = parent_tidptr;
+ register int *__ctid __asm__("$8") = child_tidptr;
+ __asm__ __volatile__(
+ #if _MIPS_SIM == _MIPS_SIM_ABI32 && _MIPS_SZPTR == 32
+ "subu $29,24\n"
+ #elif _MIPS_SIM == _MIPS_SIM_NABI32
+ "sub $29,16\n"
+ #else
+ "dsubu $29,16\n"
+ #endif
+
+ /* if (fn == NULL || child_stack == NULL)
+ * return -EINVAL;
+ */
+ "beqz %4,1f\n"
+ "beqz %5,1f\n"
+
+ /* Push "arg" and "fn" onto the stack that will be
+ * used by the child.
+ */
+ #if _MIPS_SIM == _MIPS_SIM_ABI32 && _MIPS_SZPTR == 32
+ "subu %5,32\n"
+ "sw %4,0(%5)\n"
+ "sw %7,4(%5)\n"
+ #elif _MIPS_SIM == _MIPS_SIM_NABI32
+ "sub %5,32\n"
+ "sw %4,0(%5)\n"
+ "sw %7,8(%5)\n"
+ #else
+ "dsubu %5,32\n"
+ "sd %4,0(%5)\n"
+ "sd %7,8(%5)\n"
+ #endif
+
+ /* $7 = syscall($4 = flags,
+ * $5 = child_stack,
+ * $6 = parent_tidptr,
+ * $7 = newtls,
+ * $8 = child_tidptr)
+ */
+ "li $2,%2\n"
+ "syscall\n"
+
+ /* if ($7 != 0)
+ * return $2;
+ */
+ "bnez $7,1f\n"
+ "bnez $2,1f\n"
+
+ /* In the child, now. Call "fn(arg)".
+ */
+ #if _MIPS_SIM == _MIPS_SIM_ABI32 && _MIPS_SZPTR == 32
+ "lw $25,0($29)\n"
+ "lw $4,4($29)\n"
+ #elif _MIPS_SIM == _MIPS_SIM_NABI32
+ "lw $25,0($29)\n"
+ "lw $4,8($29)\n"
+ #else
+ "ld $25,0($29)\n"
+ "ld $4,8($29)\n"
+ #endif
+ "jalr $25\n"
+
+ /* Call _exit($2)
+ */
+ "move $4,$2\n"
+ "li $2,%3\n"
+ "syscall\n"
+
+ "1:\n"
+ #if _MIPS_SIM == _MIPS_SIM_ABI32 && _MIPS_SZPTR == 32
+ "addu $29, 24\n"
+ #elif _MIPS_SIM == _MIPS_SIM_NABI32
+ "add $29, 16\n"
+ #else
+ "daddu $29,16\n"
+ #endif
+ : "+r" (__v0), "+r" (__r7)
+ : "i"(__NR_clone), "i"(__NR_exit), "r"(fn),
+ "r"(__stack), "r"(__flags), "r"(arg),
+ "r"(__ptid), "r"(__ctid)
+ : "$9", "$10", "$11", "$12", "$13", "$14", "$15",
+ "$24", "$25", "memory");
+ }
+ LSS_RETURN(int, __v0, __r7);
+ }
+ #elif defined (__PPC__)
+ #undef LSS_LOADARGS_0
+ #define LSS_LOADARGS_0(name, dummy...) \
+ __sc_0 = __NR_##name
+ #undef LSS_LOADARGS_1
+ #define LSS_LOADARGS_1(name, arg1) \
+ LSS_LOADARGS_0(name); \
+ __sc_3 = (unsigned long) (arg1)
+ #undef LSS_LOADARGS_2
+ #define LSS_LOADARGS_2(name, arg1, arg2) \
+ LSS_LOADARGS_1(name, arg1); \
+ __sc_4 = (unsigned long) (arg2)
+ #undef LSS_LOADARGS_3
+ #define LSS_LOADARGS_3(name, arg1, arg2, arg3) \
+ LSS_LOADARGS_2(name, arg1, arg2); \
+ __sc_5 = (unsigned long) (arg3)
+ #undef LSS_LOADARGS_4
+ #define LSS_LOADARGS_4(name, arg1, arg2, arg3, arg4) \
+ LSS_LOADARGS_3(name, arg1, arg2, arg3); \
+ __sc_6 = (unsigned long) (arg4)
+ #undef LSS_LOADARGS_5
+ #define LSS_LOADARGS_5(name, arg1, arg2, arg3, arg4, arg5) \
+ LSS_LOADARGS_4(name, arg1, arg2, arg3, arg4); \
+ __sc_7 = (unsigned long) (arg5)
+ #undef LSS_LOADARGS_6
+ #define LSS_LOADARGS_6(name, arg1, arg2, arg3, arg4, arg5, arg6) \
+ LSS_LOADARGS_5(name, arg1, arg2, arg3, arg4, arg5); \
+ __sc_8 = (unsigned long) (arg6)
+ #undef LSS_ASMINPUT_0
+ #define LSS_ASMINPUT_0 "0" (__sc_0)
+ #undef LSS_ASMINPUT_1
+ #define LSS_ASMINPUT_1 LSS_ASMINPUT_0, "1" (__sc_3)
+ #undef LSS_ASMINPUT_2
+ #define LSS_ASMINPUT_2 LSS_ASMINPUT_1, "2" (__sc_4)
+ #undef LSS_ASMINPUT_3
+ #define LSS_ASMINPUT_3 LSS_ASMINPUT_2, "3" (__sc_5)
+ #undef LSS_ASMINPUT_4
+ #define LSS_ASMINPUT_4 LSS_ASMINPUT_3, "4" (__sc_6)
+ #undef LSS_ASMINPUT_5
+ #define LSS_ASMINPUT_5 LSS_ASMINPUT_4, "5" (__sc_7)
+ #undef LSS_ASMINPUT_6
+ #define LSS_ASMINPUT_6 LSS_ASMINPUT_5, "6" (__sc_8)
+ #undef LSS_BODY
+ #define LSS_BODY(nr, type, name, args...) \
+ long __sc_ret, __sc_err; \
+ { \
+ register unsigned long __sc_0 __asm__ ("r0"); \
+ register unsigned long __sc_3 __asm__ ("r3"); \
+ register unsigned long __sc_4 __asm__ ("r4"); \
+ register unsigned long __sc_5 __asm__ ("r5"); \
+ register unsigned long __sc_6 __asm__ ("r6"); \
+ register unsigned long __sc_7 __asm__ ("r7"); \
+ register unsigned long __sc_8 __asm__ ("r8"); \
+ \
+ LSS_LOADARGS_##nr(name, args); \
+ __asm__ __volatile__ \
+ ("sc\n\t" \
+ "mfcr %0" \
+ : "=&r" (__sc_0), \
+ "=&r" (__sc_3), "=&r" (__sc_4), \
+ "=&r" (__sc_5), "=&r" (__sc_6), \
+ "=&r" (__sc_7), "=&r" (__sc_8) \
+ : LSS_ASMINPUT_##nr \
+ : "cr0", "ctr", "memory", \
+ "r9", "r10", "r11", "r12"); \
+ __sc_ret = __sc_3; \
+ __sc_err = __sc_0; \
+ } \
+ LSS_RETURN(type, __sc_ret, __sc_err)
+ #undef _syscall0
+ #define _syscall0(type, name) \
+ type LSS_NAME(name)(void) { \
+ LSS_BODY(0, type, name); \
+ }
+ #undef _syscall1
+ #define _syscall1(type, name, type1, arg1) \
+ type LSS_NAME(name)(type1 arg1) { \
+ LSS_BODY(1, type, name, arg1); \
+ }
+ #undef _syscall2
+ #define _syscall2(type, name, type1, arg1, type2, arg2) \
+ type LSS_NAME(name)(type1 arg1, type2 arg2) { \
+ LSS_BODY(2, type, name, arg1, arg2); \
+ }
+ #undef _syscall3
+ #define _syscall3(type, name, type1, arg1, type2, arg2, type3, arg3) \
+ type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3) { \
+ LSS_BODY(3, type, name, arg1, arg2, arg3); \
+ }
+ #undef _syscall4
+ #define _syscall4(type, name, type1, arg1, type2, arg2, type3, arg3, \
+ type4, arg4) \
+ type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4) { \
+ LSS_BODY(4, type, name, arg1, arg2, arg3, arg4); \
+ }
+ #undef _syscall5
+ #define _syscall5(type, name, type1, arg1, type2, arg2, type3, arg3, \
+ type4, arg4, type5, arg5) \
+ type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \
+ type5 arg5) { \
+ LSS_BODY(5, type, name, arg1, arg2, arg3, arg4, arg5); \
+ }
+ #undef _syscall6
+ #define _syscall6(type, name, type1, arg1, type2, arg2, type3, arg3, \
+ type4, arg4, type5, arg5, type6, arg6) \
+ type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \
+ type5 arg5, type6 arg6) { \
+ LSS_BODY(6, type, name, arg1, arg2, arg3, arg4, arg5, arg6); \
+ }
+ /* clone function adapted from glibc 2.3.6 clone.S */
+ /* TODO(csilvers): consider wrapping some args up in a struct, like we
+ * do for i386's _syscall6, so we can compile successfully on gcc 2.95
+ */
+ LSS_INLINE int LSS_NAME(clone)(int (*fn)(void *), void *child_stack,
+ int flags, void *arg, int *parent_tidptr,
+ void *newtls, int *child_tidptr) {
+ long __ret, __err;
+ {
+ register int (*__fn)(void *) __asm__ ("r8") = fn;
+ register void *__cstack __asm__ ("r4") = child_stack;
+ register int __flags __asm__ ("r3") = flags;
+ register void * __arg __asm__ ("r9") = arg;
+ register int * __ptidptr __asm__ ("r5") = parent_tidptr;
+ register void * __newtls __asm__ ("r6") = newtls;
+ register int * __ctidptr __asm__ ("r7") = child_tidptr;
+ __asm__ __volatile__(
+ /* check for fn == NULL
+ * and child_stack == NULL
+ */
+ "cmpwi cr0, %6, 0\n\t"
+ "cmpwi cr1, %7, 0\n\t"
+ "cror cr0*4+eq, cr1*4+eq, cr0*4+eq\n\t"
+ "beq- cr0, 1f\n\t"
+
+ /* set up stack frame for child */
+ "clrrwi %7, %7, 4\n\t"
+ "li 0, 0\n\t"
+ "stwu 0, -16(%7)\n\t"
+
+ /* fn, arg, child_stack are saved across the syscall: r28-30 */
+ "mr 28, %6\n\t"
+ "mr 29, %7\n\t"
+ "mr 27, %9\n\t"
+
+ /* syscall */
+ "li 0, %4\n\t"
+ /* flags already in r3
+ * child_stack already in r4
+ * ptidptr already in r5
+ * newtls already in r6
+ * ctidptr already in r7
+ */
+ "sc\n\t"
+
+ /* Test if syscall was successful */
+ "cmpwi cr1, 3, 0\n\t"
+ "crandc cr1*4+eq, cr1*4+eq, cr0*4+so\n\t"
+ "bne- cr1, 1f\n\t"
+
+ /* Do the function call */
+ "mtctr 28\n\t"
+ "mr 3, 27\n\t"
+ "bctrl\n\t"
+
+ /* Call _exit(r3) */
+ "li 0, %5\n\t"
+ "sc\n\t"
+
+ /* Return to parent */
+ "1:\n"
+ "mfcr %1\n\t"
+ "mr %0, 3\n\t"
+ : "=r" (__ret), "=r" (__err)
+ : "0" (-1), "1" (EINVAL),
+ "i" (__NR_clone), "i" (__NR_exit),
+ "r" (__fn), "r" (__cstack), "r" (__flags),
+ "r" (__arg), "r" (__ptidptr), "r" (__newtls),
+ "r" (__ctidptr)
+ : "cr0", "cr1", "memory", "ctr",
+ "r0", "r29", "r27", "r28");
+ }
+ LSS_RETURN(int, __ret, __err);
+ }
+ #elif defined(__s390__)
+ #undef LSS_REG
+ #define LSS_REG(r, a) register unsigned long __r##r __asm__("r"#r) = (unsigned long) a
+ #undef LSS_BODY
+ #define LSS_BODY(type, name, args...) \
+ register unsigned long __nr __asm__("r1") \
+ = (unsigned long)(__NR_##name); \
+ register long __res_r2 __asm__("r2"); \
+ long __res; \
+ __asm__ __volatile__ \
+ ("svc 0\n\t" \
+ : "=d"(__res_r2) \
+ : "d"(__nr), ## args \
+ : "memory"); \
+ __res = __res_r2; \
+ LSS_RETURN(type, __res)
+ #undef _syscall0
+ #define _syscall0(type, name) \
+ type LSS_NAME(name)(void) { \
+ LSS_BODY(type, name); \
+ }
+ #undef _syscall1
+ #define _syscall1(type, name, type1, arg1) \
+ type LSS_NAME(name)(type1 arg1) { \
+ LSS_REG(2, arg1); \
+ LSS_BODY(type, name, "0"(__r2)); \
+ }
+ #undef _syscall2
+ #define _syscall2(type, name, type1, arg1, type2, arg2) \
+ type LSS_NAME(name)(type1 arg1, type2 arg2) { \
+ LSS_REG(2, arg1); LSS_REG(3, arg2); \
+ LSS_BODY(type, name, "0"(__r2), "d"(__r3)); \
+ }
+ #undef _syscall3
+ #define _syscall3(type, name, type1, arg1, type2, arg2, type3, arg3) \
+ type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3) { \
+ LSS_REG(2, arg1); LSS_REG(3, arg2); LSS_REG(4, arg3); \
+ LSS_BODY(type, name, "0"(__r2), "d"(__r3), "d"(__r4)); \
+ }
+ #undef _syscall4
+ #define _syscall4(type, name, type1, arg1, type2, arg2, type3, arg3, \
+ type4, arg4) \
+ type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, \
+ type4 arg4) { \
+ LSS_REG(2, arg1); LSS_REG(3, arg2); LSS_REG(4, arg3); \
+ LSS_REG(5, arg4); \
+ LSS_BODY(type, name, "0"(__r2), "d"(__r3), "d"(__r4), \
+ "d"(__r5)); \
+ }
+ #undef _syscall5
+ #define _syscall5(type, name, type1, arg1, type2, arg2, type3, arg3, \
+ type4, arg4, type5, arg5) \
+ type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, \
+ type4 arg4, type5 arg5) { \
+ LSS_REG(2, arg1); LSS_REG(3, arg2); LSS_REG(4, arg3); \
+ LSS_REG(5, arg4); LSS_REG(6, arg5); \
+ LSS_BODY(type, name, "0"(__r2), "d"(__r3), "d"(__r4), \
+ "d"(__r5), "d"(__r6)); \
+ }
+ #undef _syscall6
+ #define _syscall6(type, name, type1, arg1, type2, arg2, type3, arg3, \
+ type4, arg4, type5, arg5, type6, arg6) \
+ type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, \
+ type4 arg4, type5 arg5, type6 arg6) { \
+ LSS_REG(2, arg1); LSS_REG(3, arg2); LSS_REG(4, arg3); \
+ LSS_REG(5, arg4); LSS_REG(6, arg5); LSS_REG(7, arg6); \
+ LSS_BODY(type, name, "0"(__r2), "d"(__r3), "d"(__r4), \
+ "d"(__r5), "d"(__r6), "d"(__r7)); \
+ }
+ LSS_INLINE int LSS_NAME(clone)(int (*fn)(void *), void *child_stack,
+ int flags, void *arg, int *parent_tidptr,
+ void *newtls, int *child_tidptr) {
+ long __ret;
+ {
+ register int (*__fn)(void *) __asm__ ("r1") = fn;
+ register void *__cstack __asm__ ("r2") = child_stack;
+ register int __flags __asm__ ("r3") = flags;
+ register void *__arg __asm__ ("r0") = arg;
+ register int *__ptidptr __asm__ ("r4") = parent_tidptr;
+ register void *__newtls __asm__ ("r6") = newtls;
+ register int *__ctidptr __asm__ ("r5") = child_tidptr;
+ __asm__ __volatile__ (
+ #ifndef __s390x__
+ /* arg already in r0 */
+ "ltr %4, %4\n\t" /* check fn, which is already in r1 */
+ "jz 1f\n\t" /* NULL function pointer, return -EINVAL */
+ "ltr %5, %5\n\t" /* check child_stack, which is already in r2 */
+ "jz 1f\n\t" /* NULL stack pointer, return -EINVAL */
+ /* flags already in r3 */
+ /* parent_tidptr already in r4 */
+ /* child_tidptr already in r5 */
+ /* newtls already in r6 */
+ "svc %2\n\t" /* invoke clone syscall */
+ "ltr %0,%%r2\n\t" /* load return code into __ret and test */
+ "jnz 1f\n\t" /* return to parent if non-zero */
+ /* start child thread */
+ "lr %%r2, %7\n\t" /* set first parameter to void *arg */
+ "ahi %%r15, -96\n\t" /* make room on the stack for the save area */
+ "xc 0(4,%%r15), 0(%%r15)\n\t"
+ "basr %%r14, %4\n\t" /* jump to fn */
+ "svc %3\n" /* invoke exit syscall */
+ "1:\n"
+ #else
+ /* arg already in r0 */
+ "ltgr %4, %4\n\t" /* check fn, which is already in r1 */
+ "jz 1f\n\t" /* NULL function pointer, return -EINVAL */
+ "ltgr %5, %5\n\t" /* check child_stack, which is already in r2 */
+ "jz 1f\n\t" /* NULL stack pointer, return -EINVAL */
+ /* flags already in r3 */
+ /* parent_tidptr already in r4 */
+ /* child_tidptr already in r5 */
+ /* newtls already in r6 */
+ "svc %2\n\t" /* invoke clone syscall */
+ "ltgr %0, %%r2\n\t" /* load return code into __ret and test */
+ "jnz 1f\n\t" /* return to parent if non-zero */
+ /* start child thread */
+ "lgr %%r2, %7\n\t" /* set first parameter to void *arg */
+ "aghi %%r15, -160\n\t" /* make room on the stack for the save area */
+ "xc 0(8,%%r15), 0(%%r15)\n\t"
+ "basr %%r14, %4\n\t" /* jump to fn */
+ "svc %3\n" /* invoke exit syscall */
+ "1:\n"
+ #endif
+ : "=r" (__ret)
+ : "0" (-EINVAL), "i" (__NR_clone), "i" (__NR_exit),
+ "d" (__fn), "d" (__cstack), "d" (__flags), "d" (__arg),
+ "d" (__ptidptr), "d" (__newtls), "d" (__ctidptr)
+ : "cc", "r14", "memory"
+ );
+ }
+ LSS_RETURN(int, __ret);
+ }
+ #endif
+ #define __NR__exit __NR_exit
+ #define __NR__gettid __NR_gettid
+ #define __NR__mremap __NR_mremap
+ LSS_INLINE _syscall1(void *, brk, void *, e)
+ LSS_INLINE _syscall1(int, chdir, const char *,p)
+ LSS_INLINE _syscall1(int, close, int, f)
+ LSS_INLINE _syscall2(int, clock_getres, int, c,
+ struct kernel_timespec*, t)
+ LSS_INLINE _syscall2(int, clock_gettime, int, c,
+ struct kernel_timespec*, t)
+ LSS_INLINE _syscall1(int, dup, int, f)
+ #if defined(__NR_dup2)
+ // dup2 is polyfilled below when not available.
+ LSS_INLINE _syscall2(int, dup2, int, s,
+ int, d)
+ #endif
+ #if defined(__NR_dup3)
+ LSS_INLINE _syscall3(int, dup3, int, s, int, d, int, f)
+ #endif
+ LSS_INLINE _syscall3(int, execve, const char*, f,
+ const char*const*,a,const char*const*, e)
+ LSS_INLINE _syscall1(int, _exit, int, e)
+ LSS_INLINE _syscall1(int, exit_group, int, e)
+ LSS_INLINE _syscall3(int, fcntl, int, f,
+ int, c, long, a)
+ #if defined(__NR_fork)
+ // fork is polyfilled below when not available.
+ LSS_INLINE _syscall0(pid_t, fork)
+ #endif
+ LSS_INLINE _syscall2(int, fstat, int, f,
+ struct kernel_stat*, b)
+ LSS_INLINE _syscall2(int, fstatfs, int, f,
+ struct kernel_statfs*, b)
+ #if defined(__x86_64__)
+ /* Need to make sure off_t isn't truncated to 32-bits under x32. */
+ LSS_INLINE int LSS_NAME(ftruncate)(int f, off_t l) {
+ LSS_BODY(2, int, ftruncate, LSS_SYSCALL_ARG(f), (uint64_t)(l));
+ }
+ #else
+ LSS_INLINE _syscall2(int, ftruncate, int, f,
+ off_t, l)
+ #endif
+ LSS_INLINE _syscall6(int, futex, int*, u,
+ int, o, int, v,
+ struct kernel_timespec*, t,
+ int*, u2, int, v2)
+ LSS_INLINE _syscall3(int, getdents, int, f,
+ struct kernel_dirent*, d, int, c)
+ LSS_INLINE _syscall3(int, getdents64, int, f,
+ struct kernel_dirent64*, d, int, c)
+ LSS_INLINE _syscall0(gid_t, getegid)
+ LSS_INLINE _syscall0(uid_t, geteuid)
+ #if defined(__NR_getpgrp)
+ LSS_INLINE _syscall0(pid_t, getpgrp)
+ #endif
+ LSS_INLINE _syscall0(pid_t, getpid)
+ LSS_INLINE _syscall0(pid_t, getppid)
+ LSS_INLINE _syscall2(int, getpriority, int, a,
+ int, b)
+ LSS_INLINE _syscall3(int, getresgid, gid_t *, r,
+ gid_t *, e, gid_t *, s)
+ LSS_INLINE _syscall3(int, getresuid, uid_t *, r,
+ uid_t *, e, uid_t *, s)
+#if !defined(__ARM_EABI__)
+ LSS_INLINE _syscall2(int, getrlimit, int, r,
+ struct kernel_rlimit*, l)
+#endif
+ LSS_INLINE _syscall1(pid_t, getsid, pid_t, p)
+ LSS_INLINE _syscall0(pid_t, _gettid)
+ LSS_INLINE _syscall2(pid_t, gettimeofday, struct kernel_timeval*, t,
+ void*, tz)
+ LSS_INLINE _syscall5(int, setxattr, const char *,p,
+ const char *, n, const void *,v,
+ size_t, s, int, f)
+ LSS_INLINE _syscall5(int, lsetxattr, const char *,p,
+ const char *, n, const void *,v,
+ size_t, s, int, f)
+ LSS_INLINE _syscall4(ssize_t, getxattr, const char *,p,
+ const char *, n, void *, v, size_t, s)
+ LSS_INLINE _syscall4(ssize_t, lgetxattr, const char *,p,
+ const char *, n, void *, v, size_t, s)
+ LSS_INLINE _syscall3(ssize_t, listxattr, const char *,p,
+ char *, l, size_t, s)
+ LSS_INLINE _syscall3(ssize_t, llistxattr, const char *,p,
+ char *, l, size_t, s)
+ LSS_INLINE _syscall3(int, ioctl, int, d,
+ int, r, void *, a)
+ LSS_INLINE _syscall2(int, ioprio_get, int, which,
+ int, who)
+ LSS_INLINE _syscall3(int, ioprio_set, int, which,
+ int, who, int, ioprio)
+ LSS_INLINE _syscall2(int, kill, pid_t, p,
+ int, s)
+ #if defined(__x86_64__)
+ /* Need to make sure off_t isn't truncated to 32-bits under x32. */
+ LSS_INLINE off_t LSS_NAME(lseek)(int f, off_t o, int w) {
+ _LSS_BODY(3, off_t, lseek, off_t, LSS_SYSCALL_ARG(f), (uint64_t)(o),
+ LSS_SYSCALL_ARG(w));
+ }
+ #else
+ LSS_INLINE _syscall3(off_t, lseek, int, f,
+ off_t, o, int, w)
+ #endif
+ LSS_INLINE _syscall2(int, munmap, void*, s,
+ size_t, l)
+ LSS_INLINE _syscall6(long, move_pages, pid_t, p,
+ unsigned long, n, void **,g, int *, d,
+ int *, s, int, f)
+ LSS_INLINE _syscall3(int, mprotect, const void *,a,
+ size_t, l, int, p)
+ LSS_INLINE _syscall5(void*, _mremap, void*, o,
+ size_t, os, size_t, ns,
+ unsigned long, f, void *, a)
+ #if defined(__NR_open)
+ // open is polyfilled below when not available.
+ LSS_INLINE _syscall3(int, open, const char*, p,
+ int, f, int, m)
+ #endif
+ #if defined(__NR_poll)
+ // poll is polyfilled below when not available.
+ LSS_INLINE _syscall3(int, poll, struct kernel_pollfd*, u,
+ unsigned int, n, int, t)
+ #endif
+ #if defined(__NR_ppoll)
+ LSS_INLINE _syscall5(int, ppoll, struct kernel_pollfd *, u,
+ unsigned int, n, const struct kernel_timespec *, t,
+ const struct kernel_sigset_t *, sigmask, size_t, s)
+ #endif
+ LSS_INLINE _syscall5(int, prctl, int, option,
+ unsigned long, arg2,
+ unsigned long, arg3,
+ unsigned long, arg4,
+ unsigned long, arg5)
+ LSS_INLINE _syscall4(long, ptrace, int, r,
+ pid_t, p, void *, a, void *, d)
+ #if defined(__NR_quotactl)
+ // Defined on x86_64 / i386 only
+ LSS_INLINE _syscall4(int, quotactl, int, cmd, const char *, special,
+ int, id, caddr_t, addr)
+ #endif
+ LSS_INLINE _syscall3(ssize_t, read, int, f,
+ void *, b, size_t, c)
+ #if defined(__NR_readlink)
+ // readlink is polyfilled below when not available.
+ LSS_INLINE _syscall3(int, readlink, const char*, p,
+ char*, b, size_t, s)
+ #endif
+ #if defined(__NR_readlinkat)
+ LSS_INLINE _syscall4(int, readlinkat, int, d, const char *, p, char *, b,
+ size_t, s)
+ #endif
+ LSS_INLINE _syscall4(int, rt_sigaction, int, s,
+ const struct kernel_sigaction*, a,
+ struct kernel_sigaction*, o, size_t, c)
+ LSS_INLINE _syscall2(int, rt_sigpending, struct kernel_sigset_t *, s,
+ size_t, c)
+ LSS_INLINE _syscall4(int, rt_sigprocmask, int, h,
+ const struct kernel_sigset_t*, s,
+ struct kernel_sigset_t*, o, size_t, c)
+ LSS_INLINE _syscall2(int, rt_sigsuspend,
+ const struct kernel_sigset_t*, s, size_t, c)
+ LSS_INLINE _syscall4(int, rt_sigtimedwait, const struct kernel_sigset_t*, s,
+ siginfo_t*, i, const struct timespec*, t, size_t, c)
+ LSS_INLINE _syscall3(int, sched_getaffinity,pid_t, p,
+ unsigned int, l, unsigned long *, m)
+ LSS_INLINE _syscall3(int, sched_setaffinity,pid_t, p,
+ unsigned int, l, unsigned long *, m)
+ LSS_INLINE _syscall0(int, sched_yield)
+ LSS_INLINE _syscall1(long, set_tid_address, int *, t)
+ LSS_INLINE _syscall1(int, setfsgid, gid_t, g)
+ LSS_INLINE _syscall1(int, setfsuid, uid_t, u)
+ LSS_INLINE _syscall1(int, setuid, uid_t, u)
+ LSS_INLINE _syscall1(int, setgid, gid_t, g)
+ LSS_INLINE _syscall2(int, setpgid, pid_t, p,
+ pid_t, g)
+ LSS_INLINE _syscall3(int, setpriority, int, a,
+ int, b, int, p)
+ LSS_INLINE _syscall3(int, setresgid, gid_t, r,
+ gid_t, e, gid_t, s)
+ LSS_INLINE _syscall3(int, setresuid, uid_t, r,
+ uid_t, e, uid_t, s)
+ LSS_INLINE _syscall2(int, setrlimit, int, r,
+ const struct kernel_rlimit*, l)
+ LSS_INLINE _syscall0(pid_t, setsid)
+ LSS_INLINE _syscall2(int, sigaltstack, const stack_t*, s,
+ const stack_t*, o)
+ #if defined(__NR_sigreturn)
+ LSS_INLINE _syscall1(int, sigreturn, unsigned long, u)
+ #endif
+ #if defined(__NR_stat)
+ // stat is polyfilled below when not available.
+ LSS_INLINE _syscall2(int, stat, const char*, f,
+ struct kernel_stat*, b)
+ #endif
+ LSS_INLINE _syscall2(int, statfs, const char*, f,
+ struct kernel_statfs*, b)
+ LSS_INLINE _syscall3(int, tgkill, pid_t, p,
+ pid_t, t, int, s)
+ LSS_INLINE _syscall2(int, tkill, pid_t, p,
+ int, s)
+ #if defined(__NR_unlink)
+ // unlink is polyfilled below when not available.
+ LSS_INLINE _syscall1(int, unlink, const char*, f)
+ #endif
+ LSS_INLINE _syscall3(ssize_t, write, int, f,
+ const void *, b, size_t, c)
+ LSS_INLINE _syscall3(ssize_t, writev, int, f,
+ const struct kernel_iovec*, v, size_t, c)
+ #if defined(__NR_getcpu)
+ LSS_INLINE _syscall3(long, getcpu, unsigned *, cpu,
+ unsigned *, node, void *, unused)
+ #endif
+ #if defined(__x86_64__) || \
+ (defined(__mips__) && _MIPS_SIM != _MIPS_SIM_ABI32)
+ LSS_INLINE _syscall3(int, recvmsg, int, s,
+ struct kernel_msghdr*, m, int, f)
+ LSS_INLINE _syscall3(int, sendmsg, int, s,
+ const struct kernel_msghdr*, m, int, f)
+ LSS_INLINE _syscall6(int, sendto, int, s,
+ const void*, m, size_t, l,
+ int, f,
+ const struct kernel_sockaddr*, a, int, t)
+ LSS_INLINE _syscall2(int, shutdown, int, s,
+ int, h)
+ LSS_INLINE _syscall3(int, socket, int, d,
+ int, t, int, p)
+ LSS_INLINE _syscall4(int, socketpair, int, d,
+ int, t, int, p, int*, s)
+ #endif
+ #if defined(__NR_fadvise64)
+ #if defined(__x86_64__)
+ /* Need to make sure loff_t isn't truncated to 32-bits under x32. */
+ LSS_INLINE int LSS_NAME(fadvise64)(int fd, loff_t offset, loff_t len,
+ int advice) {
+ LSS_BODY(4, int, fadvise64, LSS_SYSCALL_ARG(fd), (uint64_t)(offset),
+ (uint64_t)(len), LSS_SYSCALL_ARG(advice));
+ }
+ #else
+ LSS_INLINE _syscall4(int, fadvise64,
+ int, fd, loff_t, offset, loff_t, len, int, advice)
+ #endif
+ #elif defined(__i386__)
+ #define __NR__fadvise64_64 __NR_fadvise64_64
+ LSS_INLINE _syscall6(int, _fadvise64_64, int, fd,
+ unsigned, offset_lo, unsigned, offset_hi,
+ unsigned, len_lo, unsigned, len_hi,
+ int, advice)
+
+ LSS_INLINE int LSS_NAME(fadvise64)(int fd, loff_t offset,
+ loff_t len, int advice) {
+ return LSS_NAME(_fadvise64_64)(fd,
+ (unsigned)offset, (unsigned)(offset >>32),
+ (unsigned)len, (unsigned)(len >> 32),
+ advice);
+ }
+
+ #elif defined(__s390__) && !defined(__s390x__)
+ #define __NR__fadvise64_64 __NR_fadvise64_64
+ struct kernel_fadvise64_64_args {
+ int fd;
+ long long offset;
+ long long len;
+ int advice;
+ };
+
+ LSS_INLINE _syscall1(int, _fadvise64_64,
+ struct kernel_fadvise64_64_args *args)
+
+ LSS_INLINE int LSS_NAME(fadvise64)(int fd, loff_t offset,
+ loff_t len, int advice) {
+ struct kernel_fadvise64_64_args args = { fd, offset, len, advice };
+ return LSS_NAME(_fadvise64_64)(&args);
+ }
+ #endif
+ #if defined(__NR_fallocate)
+ #if defined(__x86_64__)
+ /* Need to make sure loff_t isn't truncated to 32-bits under x32. */
+ LSS_INLINE int LSS_NAME(fallocate)(int f, int mode, loff_t offset,
+ loff_t len) {
+ LSS_BODY(4, int, fallocate, LSS_SYSCALL_ARG(f), LSS_SYSCALL_ARG(mode),
+ (uint64_t)(offset), (uint64_t)(len));
+ }
+ #elif (defined(__i386__) || (defined(__s390__) && !defined(__s390x__)) \
+ || defined(__ARM_ARCH_3__) || defined(__ARM_EABI__) \
+ || (defined(__mips__) && _MIPS_SIM == _MIPS_SIM_ABI32) \
+ || defined(__PPC__))
+ #define __NR__fallocate __NR_fallocate
+ LSS_INLINE _syscall6(int, _fallocate, int, fd,
+ int, mode,
+ unsigned, offset_lo, unsigned, offset_hi,
+ unsigned, len_lo, unsigned, len_hi)
+
+ LSS_INLINE int LSS_NAME(fallocate)(int fd, int mode,
+ loff_t offset, loff_t len) {
+ union { loff_t off; unsigned w[2]; } o = { offset }, l = { len };
+ return LSS_NAME(_fallocate)(fd, mode, o.w[0], o.w[1], l.w[0], l.w[1]);
+ }
+ #else
+ LSS_INLINE _syscall4(int, fallocate,
+ int, f, int, mode, loff_t, offset, loff_t, len)
+ #endif
+ #endif
+ #if defined(__NR_newfstatat)
+ LSS_INLINE _syscall4(int, newfstatat, int, d,
+ const char *, p,
+ struct kernel_stat*, b, int, f)
+ #endif
+ #if defined(__x86_64__) || defined(__s390x__)
+ LSS_INLINE int LSS_NAME(getresgid32)(gid_t *rgid,
+ gid_t *egid,
+ gid_t *sgid) {
+ return LSS_NAME(getresgid)(rgid, egid, sgid);
+ }
+
+ LSS_INLINE int LSS_NAME(getresuid32)(uid_t *ruid,
+ uid_t *euid,
+ uid_t *suid) {
+ return LSS_NAME(getresuid)(ruid, euid, suid);
+ }
+
+ LSS_INLINE int LSS_NAME(setfsgid32)(gid_t gid) {
+ return LSS_NAME(setfsgid)(gid);
+ }
+
+ LSS_INLINE int LSS_NAME(setfsuid32)(uid_t uid) {
+ return LSS_NAME(setfsuid)(uid);
+ }
+
+ LSS_INLINE int LSS_NAME(setresgid32)(gid_t rgid, gid_t egid, gid_t sgid) {
+ return LSS_NAME(setresgid)(rgid, egid, sgid);
+ }
+
+ LSS_INLINE int LSS_NAME(setresuid32)(uid_t ruid, uid_t euid, uid_t suid) {
+ return LSS_NAME(setresuid)(ruid, euid, suid);
+ }
+
+ LSS_INLINE int LSS_NAME(sigaction)(int signum,
+ const struct kernel_sigaction *act,
+ struct kernel_sigaction *oldact) {
+ #if defined(__x86_64__)
+ /* On x86_64, the kernel requires us to always set our own
+ * SA_RESTORER in order to be able to return from a signal handler.
+ * This function must have a "magic" signature that the "gdb"
+ * (and maybe the kernel?) can recognize.
+ */
+ if (act != NULL && !(act->sa_flags & SA_RESTORER)) {
+ struct kernel_sigaction a = *act;
+ a.sa_flags |= SA_RESTORER;
+ a.sa_restorer = LSS_NAME(restore_rt)();
+ return LSS_NAME(rt_sigaction)(signum, &a, oldact,
+ (KERNEL_NSIG+7)/8);
+ } else
+ #endif
+ return LSS_NAME(rt_sigaction)(signum, act, oldact,
+ (KERNEL_NSIG+7)/8);
+ }
+
+ LSS_INLINE int LSS_NAME(sigpending)(struct kernel_sigset_t *set) {
+ return LSS_NAME(rt_sigpending)(set, (KERNEL_NSIG+7)/8);
+ }
+
+ LSS_INLINE int LSS_NAME(sigsuspend)(const struct kernel_sigset_t *set) {
+ return LSS_NAME(rt_sigsuspend)(set, (KERNEL_NSIG+7)/8);
+ }
+ #endif
+ #if defined(__NR_rt_sigprocmask)
+ LSS_INLINE int LSS_NAME(sigprocmask)(int how,
+ const struct kernel_sigset_t *set,
+ struct kernel_sigset_t *oldset) {
+ return LSS_NAME(rt_sigprocmask)(how, set, oldset, (KERNEL_NSIG+7)/8);
+ }
+ #endif
+ #if defined(__NR_rt_sigtimedwait)
+ LSS_INLINE int LSS_NAME(sigtimedwait)(const struct kernel_sigset_t *set,
+ siginfo_t *info,
+ const struct timespec *timeout) {
+ return LSS_NAME(rt_sigtimedwait)(set, info, timeout, (KERNEL_NSIG+7)/8);
+ }
+ #endif
+ #if defined(__NR_wait4)
+ LSS_INLINE _syscall4(pid_t, wait4, pid_t, p,
+ int*, s, int, o,
+ struct kernel_rusage*, r)
+ #endif
+ #if defined(__NR_openat)
+ LSS_INLINE _syscall4(int, openat, int, d, const char *, p, int, f, int, m)
+ #endif
+ #if defined(__NR_unlinkat)
+ LSS_INLINE _syscall3(int, unlinkat, int, d, const char *, p, int, f)
+ #endif
+ #if defined(__i386__) || defined(__ARM_ARCH_3__) || defined(__ARM_EABI__) || \
+ (defined(__s390__) && !defined(__s390x__))
+ #define __NR__getresgid32 __NR_getresgid32
+ #define __NR__getresuid32 __NR_getresuid32
+ #define __NR__setfsgid32 __NR_setfsgid32
+ #define __NR__setfsuid32 __NR_setfsuid32
+ #define __NR__setresgid32 __NR_setresgid32
+ #define __NR__setresuid32 __NR_setresuid32
+#if defined(__ARM_EABI__)
+ LSS_INLINE _syscall2(int, ugetrlimit, int, r,
+ struct kernel_rlimit*, l)
+#endif
+ LSS_INLINE _syscall3(int, _getresgid32, gid_t *, r,
+ gid_t *, e, gid_t *, s)
+ LSS_INLINE _syscall3(int, _getresuid32, uid_t *, r,
+ uid_t *, e, uid_t *, s)
+ LSS_INLINE _syscall1(int, _setfsgid32, gid_t, f)
+ LSS_INLINE _syscall1(int, _setfsuid32, uid_t, f)
+ LSS_INLINE _syscall3(int, _setresgid32, gid_t, r,
+ gid_t, e, gid_t, s)
+ LSS_INLINE _syscall3(int, _setresuid32, uid_t, r,
+ uid_t, e, uid_t, s)
+
+ LSS_INLINE int LSS_NAME(getresgid32)(gid_t *rgid,
+ gid_t *egid,
+ gid_t *sgid) {
+ int rc;
+ if ((rc = LSS_NAME(_getresgid32)(rgid, egid, sgid)) < 0 &&
+ LSS_ERRNO == ENOSYS) {
+ if ((rgid == NULL) || (egid == NULL) || (sgid == NULL)) {
+ return EFAULT;
+ }
+ // Clear the high bits first, since getresgid only sets 16 bits
+ *rgid = *egid = *sgid = 0;
+ rc = LSS_NAME(getresgid)(rgid, egid, sgid);
+ }
+ return rc;
+ }
+
+ LSS_INLINE int LSS_NAME(getresuid32)(uid_t *ruid,
+ uid_t *euid,
+ uid_t *suid) {
+ int rc;
+ if ((rc = LSS_NAME(_getresuid32)(ruid, euid, suid)) < 0 &&
+ LSS_ERRNO == ENOSYS) {
+ if ((ruid == NULL) || (euid == NULL) || (suid == NULL)) {
+ return EFAULT;
+ }
+ // Clear the high bits first, since getresuid only sets 16 bits
+ *ruid = *euid = *suid = 0;
+ rc = LSS_NAME(getresuid)(ruid, euid, suid);
+ }
+ return rc;
+ }
+
+ LSS_INLINE int LSS_NAME(setfsgid32)(gid_t gid) {
+ int rc;
+ if ((rc = LSS_NAME(_setfsgid32)(gid)) < 0 &&
+ LSS_ERRNO == ENOSYS) {
+ if ((unsigned int)gid & ~0xFFFFu) {
+ rc = EINVAL;
+ } else {
+ rc = LSS_NAME(setfsgid)(gid);
+ }
+ }
+ return rc;
+ }
+
+ LSS_INLINE int LSS_NAME(setfsuid32)(uid_t uid) {
+ int rc;
+ if ((rc = LSS_NAME(_setfsuid32)(uid)) < 0 &&
+ LSS_ERRNO == ENOSYS) {
+ if ((unsigned int)uid & ~0xFFFFu) {
+ rc = EINVAL;
+ } else {
+ rc = LSS_NAME(setfsuid)(uid);
+ }
+ }
+ return rc;
+ }
+
+ LSS_INLINE int LSS_NAME(setresgid32)(gid_t rgid, gid_t egid, gid_t sgid) {
+ int rc;
+ if ((rc = LSS_NAME(_setresgid32)(rgid, egid, sgid)) < 0 &&
+ LSS_ERRNO == ENOSYS) {
+ if ((unsigned int)rgid & ~0xFFFFu ||
+ (unsigned int)egid & ~0xFFFFu ||
+ (unsigned int)sgid & ~0xFFFFu) {
+ rc = EINVAL;
+ } else {
+ rc = LSS_NAME(setresgid)(rgid, egid, sgid);
+ }
+ }
+ return rc;
+ }
+
+ LSS_INLINE int LSS_NAME(setresuid32)(uid_t ruid, uid_t euid, uid_t suid) {
+ int rc;
+ if ((rc = LSS_NAME(_setresuid32)(ruid, euid, suid)) < 0 &&
+ LSS_ERRNO == ENOSYS) {
+ if ((unsigned int)ruid & ~0xFFFFu ||
+ (unsigned int)euid & ~0xFFFFu ||
+ (unsigned int)suid & ~0xFFFFu) {
+ rc = EINVAL;
+ } else {
+ rc = LSS_NAME(setresuid)(ruid, euid, suid);
+ }
+ }
+ return rc;
+ }
+ #endif
+ LSS_INLINE int LSS_NAME(sigemptyset)(struct kernel_sigset_t *set) {
+ memset(&set->sig, 0, sizeof(set->sig));
+ return 0;
+ }
+
+ LSS_INLINE int LSS_NAME(sigfillset)(struct kernel_sigset_t *set) {
+ memset(&set->sig, -1, sizeof(set->sig));
+ return 0;
+ }
+
+ LSS_INLINE int LSS_NAME(sigaddset)(struct kernel_sigset_t *set,
+ int signum) {
+ if (signum < 1 || signum > (int)(8*sizeof(set->sig))) {
+ LSS_ERRNO = EINVAL;
+ return -1;
+ } else {
+ set->sig[(signum - 1)/(8*sizeof(set->sig[0]))]
+ |= 1UL << ((signum - 1) % (8*sizeof(set->sig[0])));
+ return 0;
+ }
+ }
+
+ LSS_INLINE int LSS_NAME(sigdelset)(struct kernel_sigset_t *set,
+ int signum) {
+ if (signum < 1 || signum > (int)(8*sizeof(set->sig))) {
+ LSS_ERRNO = EINVAL;
+ return -1;
+ } else {
+ set->sig[(signum - 1)/(8*sizeof(set->sig[0]))]
+ &= ~(1UL << ((signum - 1) % (8*sizeof(set->sig[0]))));
+ return 0;
+ }
+ }
+
+ LSS_INLINE int LSS_NAME(sigismember)(struct kernel_sigset_t *set,
+ int signum) {
+ if (signum < 1 || signum > (int)(8*sizeof(set->sig))) {
+ LSS_ERRNO = EINVAL;
+ return -1;
+ } else {
+ return !!(set->sig[(signum - 1)/(8*sizeof(set->sig[0]))] &
+ (1UL << ((signum - 1) % (8*sizeof(set->sig[0])))));
+ }
+ }
+ #if defined(__i386__) || \
+ defined(__ARM_ARCH_3__) || defined(__ARM_EABI__) || \
+ (defined(__mips__) && _MIPS_SIM == _MIPS_SIM_ABI32) || \
+ defined(__PPC__) || \
+ (defined(__s390__) && !defined(__s390x__))
+ #define __NR__sigaction __NR_sigaction
+ #define __NR__sigpending __NR_sigpending
+ #define __NR__sigsuspend __NR_sigsuspend
+ #define __NR__socketcall __NR_socketcall
+ LSS_INLINE _syscall2(int, fstat64, int, f,
+ struct kernel_stat64 *, b)
+ LSS_INLINE _syscall5(int, _llseek, uint, fd,
+ unsigned long, hi, unsigned long, lo,
+ loff_t *, res, uint, wh)
+#if defined(__s390__) && !defined(__s390x__)
+ /* On s390, mmap2() arguments are passed in memory. */
+ LSS_INLINE void* LSS_NAME(_mmap2)(void *s, size_t l, int p, int f, int d,
+ off_t o) {
+ unsigned long buf[6] = { (unsigned long) s, (unsigned long) l,
+ (unsigned long) p, (unsigned long) f,
+ (unsigned long) d, (unsigned long) o };
+ LSS_REG(2, buf);
+ LSS_BODY(void*, mmap2, "0"(__r2));
+ }
+#else
+ #define __NR__mmap2 __NR_mmap2
+ LSS_INLINE _syscall6(void*, _mmap2, void*, s,
+ size_t, l, int, p,
+ int, f, int, d,
+ off_t, o)
+#endif
+ LSS_INLINE _syscall3(int, _sigaction, int, s,
+ const struct kernel_old_sigaction*, a,
+ struct kernel_old_sigaction*, o)
+ LSS_INLINE _syscall1(int, _sigpending, unsigned long*, s)
+ #ifdef __PPC__
+ LSS_INLINE _syscall1(int, _sigsuspend, unsigned long, s)
+ #else
+ LSS_INLINE _syscall3(int, _sigsuspend, const void*, a,
+ int, b,
+ unsigned long, s)
+ #endif
+ LSS_INLINE _syscall2(int, stat64, const char *, p,
+ struct kernel_stat64 *, b)
+
+ LSS_INLINE int LSS_NAME(sigaction)(int signum,
+ const struct kernel_sigaction *act,
+ struct kernel_sigaction *oldact) {
+ int old_errno = LSS_ERRNO;
+ int rc;
+ struct kernel_sigaction a;
+ if (act != NULL) {
+ a = *act;
+ #ifdef __i386__
+ /* On i386, the kernel requires us to always set our own
+ * SA_RESTORER when using realtime signals. Otherwise, it does not
+ * know how to return from a signal handler. This function must have
+ * a "magic" signature that the "gdb" (and maybe the kernel?) can
+ * recognize.
+ * Apparently, a SA_RESTORER is implicitly set by the kernel, when
+ * using non-realtime signals.
+ *
+ * TODO: Test whether ARM needs a restorer
+ */
+ if (!(a.sa_flags & SA_RESTORER)) {
+ a.sa_flags |= SA_RESTORER;
+ a.sa_restorer = (a.sa_flags & SA_SIGINFO)
+ ? LSS_NAME(restore_rt)() : LSS_NAME(restore)();
+ }
+ #endif
+ }
+ rc = LSS_NAME(rt_sigaction)(signum, act ? &a : act, oldact,
+ (KERNEL_NSIG+7)/8);
+ if (rc < 0 && LSS_ERRNO == ENOSYS) {
+ struct kernel_old_sigaction oa, ooa, *ptr_a = &oa, *ptr_oa = &ooa;
+ if (!act) {
+ ptr_a = NULL;
+ } else {
+ oa.sa_handler_ = act->sa_handler_;
+ memcpy(&oa.sa_mask, &act->sa_mask, sizeof(oa.sa_mask));
+ #ifndef __mips__
+ oa.sa_restorer = act->sa_restorer;
+ #endif
+ oa.sa_flags = act->sa_flags;
+ }
+ if (!oldact) {
+ ptr_oa = NULL;
+ }
+ LSS_ERRNO = old_errno;
+ rc = LSS_NAME(_sigaction)(signum, ptr_a, ptr_oa);
+ if (rc == 0 && oldact) {
+ if (act) {
+ memcpy(oldact, act, sizeof(*act));
+ } else {
+ memset(oldact, 0, sizeof(*oldact));
+ }
+ oldact->sa_handler_ = ptr_oa->sa_handler_;
+ oldact->sa_flags = ptr_oa->sa_flags;
+ memcpy(&oldact->sa_mask, &ptr_oa->sa_mask, sizeof(ptr_oa->sa_mask));
+ #ifndef __mips__
+ oldact->sa_restorer = ptr_oa->sa_restorer;
+ #endif
+ }
+ }
+ return rc;
+ }
+
+ LSS_INLINE int LSS_NAME(sigpending)(struct kernel_sigset_t *set) {
+ int old_errno = LSS_ERRNO;
+ int rc = LSS_NAME(rt_sigpending)(set, (KERNEL_NSIG+7)/8);
+ if (rc < 0 && LSS_ERRNO == ENOSYS) {
+ LSS_ERRNO = old_errno;
+ LSS_NAME(sigemptyset)(set);
+ rc = LSS_NAME(_sigpending)(&set->sig[0]);
+ }
+ return rc;
+ }
+
+ LSS_INLINE int LSS_NAME(sigsuspend)(const struct kernel_sigset_t *set) {
+ int olderrno = LSS_ERRNO;
+ int rc = LSS_NAME(rt_sigsuspend)(set, (KERNEL_NSIG+7)/8);
+ if (rc < 0 && LSS_ERRNO == ENOSYS) {
+ LSS_ERRNO = olderrno;
+ rc = LSS_NAME(_sigsuspend)(
+ #ifndef __PPC__
+ set, 0,
+ #endif
+ set->sig[0]);
+ }
+ return rc;
+ }
+ #endif
+ #if defined(__i386__) || \
+ defined(__ARM_ARCH_3__) || defined(__ARM_EABI__) || \
+ (defined(__mips__) && _MIPS_SIM == _MIPS_SIM_ABI32) || \
+ defined(__PPC__) || \
+ (defined(__s390__) && !defined(__s390x__))
+ /* On these architectures, implement mmap() with mmap2(). */
+ LSS_INLINE void* LSS_NAME(mmap)(void *s, size_t l, int p, int f, int d,
+ int64_t o) {
+ if (o % 4096) {
+ LSS_ERRNO = EINVAL;
+ return (void *) -1;
+ }
+ return LSS_NAME(_mmap2)(s, l, p, f, d, (o / 4096));
+ }
+ #elif defined(__s390x__)
+ /* On s390x, mmap() arguments are passed in memory. */
+ LSS_INLINE void* LSS_NAME(mmap)(void *s, size_t l, int p, int f, int d,
+ int64_t o) {
+ unsigned long buf[6] = { (unsigned long) s, (unsigned long) l,
+ (unsigned long) p, (unsigned long) f,
+ (unsigned long) d, (unsigned long) o };
+ LSS_REG(2, buf);
+ LSS_BODY(void*, mmap, "0"(__r2));
+ }
+ #elif defined(__x86_64__)
+ /* Need to make sure __off64_t isn't truncated to 32-bits under x32. */
+ LSS_INLINE void* LSS_NAME(mmap)(void *s, size_t l, int p, int f, int d,
+ int64_t o) {
+ LSS_BODY(6, void*, mmap, LSS_SYSCALL_ARG(s), LSS_SYSCALL_ARG(l),
+ LSS_SYSCALL_ARG(p), LSS_SYSCALL_ARG(f),
+ LSS_SYSCALL_ARG(d), (uint64_t)(o));
+ }
+ #else
+ /* Remaining 64-bit architectures. */
+ LSS_INLINE _syscall6(void*, mmap, void*, addr, size_t, length, int, prot,
+ int, flags, int, fd, int64_t, offset)
+ #endif
+ #if defined(__PPC__)
+ #undef LSS_SC_LOADARGS_0
+ #define LSS_SC_LOADARGS_0(dummy...)
+ #undef LSS_SC_LOADARGS_1
+ #define LSS_SC_LOADARGS_1(arg1) \
+ __sc_4 = (unsigned long) (arg1)
+ #undef LSS_SC_LOADARGS_2
+ #define LSS_SC_LOADARGS_2(arg1, arg2) \
+ LSS_SC_LOADARGS_1(arg1); \
+ __sc_5 = (unsigned long) (arg2)
+ #undef LSS_SC_LOADARGS_3
+ #define LSS_SC_LOADARGS_3(arg1, arg2, arg3) \
+ LSS_SC_LOADARGS_2(arg1, arg2); \
+ __sc_6 = (unsigned long) (arg3)
+ #undef LSS_SC_LOADARGS_4
+ #define LSS_SC_LOADARGS_4(arg1, arg2, arg3, arg4) \
+ LSS_SC_LOADARGS_3(arg1, arg2, arg3); \
+ __sc_7 = (unsigned long) (arg4)
+ #undef LSS_SC_LOADARGS_5
+ #define LSS_SC_LOADARGS_5(arg1, arg2, arg3, arg4, arg5) \
+ LSS_SC_LOADARGS_4(arg1, arg2, arg3, arg4); \
+ __sc_8 = (unsigned long) (arg5)
+ #undef LSS_SC_BODY
+ #define LSS_SC_BODY(nr, type, opt, args...) \
+ long __sc_ret, __sc_err; \
+ { \
+ register unsigned long __sc_0 __asm__ ("r0") = __NR_socketcall; \
+ register unsigned long __sc_3 __asm__ ("r3") = opt; \
+ register unsigned long __sc_4 __asm__ ("r4"); \
+ register unsigned long __sc_5 __asm__ ("r5"); \
+ register unsigned long __sc_6 __asm__ ("r6"); \
+ register unsigned long __sc_7 __asm__ ("r7"); \
+ register unsigned long __sc_8 __asm__ ("r8"); \
+ LSS_SC_LOADARGS_##nr(args); \
+ __asm__ __volatile__ \
+ ("stwu 1, -48(1)\n\t" \
+ "stw 4, 20(1)\n\t" \
+ "stw 5, 24(1)\n\t" \
+ "stw 6, 28(1)\n\t" \
+ "stw 7, 32(1)\n\t" \
+ "stw 8, 36(1)\n\t" \
+ "addi 4, 1, 20\n\t" \
+ "sc\n\t" \
+ "mfcr %0" \
+ : "=&r" (__sc_0), \
+ "=&r" (__sc_3), "=&r" (__sc_4), \
+ "=&r" (__sc_5), "=&r" (__sc_6), \
+ "=&r" (__sc_7), "=&r" (__sc_8) \
+ : LSS_ASMINPUT_##nr \
+ : "cr0", "ctr", "memory"); \
+ __sc_ret = __sc_3; \
+ __sc_err = __sc_0; \
+ } \
+ LSS_RETURN(type, __sc_ret, __sc_err)
+
+ LSS_INLINE ssize_t LSS_NAME(recvmsg)(int s,struct kernel_msghdr *msg,
+ int flags){
+ LSS_SC_BODY(3, ssize_t, 17, s, msg, flags);
+ }
+
+ LSS_INLINE ssize_t LSS_NAME(sendmsg)(int s,
+ const struct kernel_msghdr *msg,
+ int flags) {
+ LSS_SC_BODY(3, ssize_t, 16, s, msg, flags);
+ }
+
+ // TODO(csilvers): why is this ifdef'ed out?
+#if 0
+ LSS_INLINE ssize_t LSS_NAME(sendto)(int s, const void *buf, size_t len,
+ int flags,
+ const struct kernel_sockaddr *to,
+ unsigned int tolen) {
+ LSS_BODY(6, ssize_t, 11, s, buf, len, flags, to, tolen);
+ }
+#endif
+
+ LSS_INLINE int LSS_NAME(shutdown)(int s, int how) {
+ LSS_SC_BODY(2, int, 13, s, how);
+ }
+
+ LSS_INLINE int LSS_NAME(socket)(int domain, int type, int protocol) {
+ LSS_SC_BODY(3, int, 1, domain, type, protocol);
+ }
+
+ LSS_INLINE int LSS_NAME(socketpair)(int d, int type, int protocol,
+ int sv[2]) {
+ LSS_SC_BODY(4, int, 8, d, type, protocol, sv);
+ }
+ #endif
+ #if defined(__ARM_EABI__) || defined (__aarch64__)
+ LSS_INLINE _syscall3(ssize_t, recvmsg, int, s, struct kernel_msghdr*, msg,
+ int, flags)
+ LSS_INLINE _syscall3(ssize_t, sendmsg, int, s, const struct kernel_msghdr*,
+ msg, int, flags)
+ LSS_INLINE _syscall6(ssize_t, sendto, int, s, const void*, buf, size_t,len,
+ int, flags, const struct kernel_sockaddr*, to,
+ unsigned int, tolen)
+ LSS_INLINE _syscall2(int, shutdown, int, s, int, how)
+ LSS_INLINE _syscall3(int, socket, int, domain, int, type, int, protocol)
+ LSS_INLINE _syscall4(int, socketpair, int, d, int, type, int, protocol,
+ int*, sv)
+ #endif
+ #if defined(__i386__) || defined(__ARM_ARCH_3__) || \
+ (defined(__mips__) && _MIPS_SIM == _MIPS_SIM_ABI32) || \
+ defined(__s390__)
+ #define __NR__socketcall __NR_socketcall
+ LSS_INLINE _syscall2(int, _socketcall, int, c,
+ va_list, a)
+ LSS_INLINE int LSS_NAME(socketcall)(int op, ...) {
+ int rc;
+ va_list ap;
+ va_start(ap, op);
+ rc = LSS_NAME(_socketcall)(op, ap);
+ va_end(ap);
+ return rc;
+ }
+
+ LSS_INLINE ssize_t LSS_NAME(recvmsg)(int s,struct kernel_msghdr *msg,
+ int flags){
+ return (ssize_t)LSS_NAME(socketcall)(17, s, msg, flags);
+ }
+
+ LSS_INLINE ssize_t LSS_NAME(sendmsg)(int s,
+ const struct kernel_msghdr *msg,
+ int flags) {
+ return (ssize_t)LSS_NAME(socketcall)(16, s, msg, flags);
+ }
+
+ LSS_INLINE ssize_t LSS_NAME(sendto)(int s, const void *buf, size_t len,
+ int flags,
+ const struct kernel_sockaddr *to,
+ unsigned int tolen) {
+ return (ssize_t)LSS_NAME(socketcall)(11, s, buf, len, flags, to, tolen);
+ }
+
+ LSS_INLINE int LSS_NAME(shutdown)(int s, int how) {
+ return LSS_NAME(socketcall)(13, s, how);
+ }
+
+ LSS_INLINE int LSS_NAME(socket)(int domain, int type, int protocol) {
+ return LSS_NAME(socketcall)(1, domain, type, protocol);
+ }
+
+ LSS_INLINE int LSS_NAME(socketpair)(int d, int type, int protocol,
+ int sv[2]) {
+ return LSS_NAME(socketcall)(8, d, type, protocol, sv);
+ }
+ #endif
+ #if defined(__NR_fstatat64)
+ LSS_INLINE _syscall4(int, fstatat64, int, d,
+ const char *, p,
+ struct kernel_stat64 *, b, int, f)
+ #endif
+ #if defined(__NR_waitpid)
+ // waitpid is polyfilled below when not available.
+ LSS_INLINE _syscall3(pid_t, waitpid, pid_t, p,
+ int*, s, int, o)
+ #endif
+ #if defined(__mips__)
+ /* sys_pipe() on MIPS has non-standard calling conventions, as it returns
+ * both file handles through CPU registers.
+ */
+ LSS_INLINE int LSS_NAME(pipe)(int *p) {
+ register unsigned long __v0 __asm__("$2") = __NR_pipe;
+ register unsigned long __v1 __asm__("$3");
+ register unsigned long __r7 __asm__("$7");
+ __asm__ __volatile__ ("syscall\n"
+ : "=r"(__v0), "=r"(__v1), "=r" (__r7)
+ : "0"(__v0)
+ : "$8", "$9", "$10", "$11", "$12",
+ "$13", "$14", "$15", "$24", "$25", "memory");
+ if (__r7) {
+ unsigned long __errnovalue = __v0;
+ LSS_ERRNO = __errnovalue;
+ return -1;
+ } else {
+ p[0] = __v0;
+ p[1] = __v1;
+ return 0;
+ }
+ }
+ #elif defined(__NR_pipe)
+ // pipe is polyfilled below when not available.
+ LSS_INLINE _syscall1(int, pipe, int *, p)
+ #endif
+ #if defined(__NR_pipe2)
+ LSS_INLINE _syscall2(int, pipe2, int *, pipefd, int, flags)
+ #endif
+ /* TODO(csilvers): see if ppc can/should support this as well */
+ #if defined(__i386__) || defined(__ARM_ARCH_3__) || \
+ defined(__ARM_EABI__) || \
+ (defined(__mips__) && _MIPS_SIM != _MIPS_SIM_ABI64) || \
+ (defined(__s390__) && !defined(__s390x__))
+ #define __NR__statfs64 __NR_statfs64
+ #define __NR__fstatfs64 __NR_fstatfs64
+ LSS_INLINE _syscall3(int, _statfs64, const char*, p,
+ size_t, s,struct kernel_statfs64*, b)
+ LSS_INLINE _syscall3(int, _fstatfs64, int, f,
+ size_t, s,struct kernel_statfs64*, b)
+ LSS_INLINE int LSS_NAME(statfs64)(const char *p,
+ struct kernel_statfs64 *b) {
+ return LSS_NAME(_statfs64)(p, sizeof(*b), b);
+ }
+ LSS_INLINE int LSS_NAME(fstatfs64)(int f,struct kernel_statfs64 *b) {
+ return LSS_NAME(_fstatfs64)(f, sizeof(*b), b);
+ }
+ #endif
+
+ LSS_INLINE int LSS_NAME(execv)(const char *path, const char *const argv[]) {
+ extern char **environ;
+ return LSS_NAME(execve)(path, argv, (const char *const *)environ);
+ }
+
+ LSS_INLINE pid_t LSS_NAME(gettid)(void) {
+ pid_t tid = LSS_NAME(_gettid)();
+ if (tid != -1) {
+ return tid;
+ }
+ return LSS_NAME(getpid)();
+ }
+
+ LSS_INLINE void *LSS_NAME(mremap)(void *old_address, size_t old_size,
+ size_t new_size, int flags, ...) {
+ va_list ap;
+ void *new_address, *rc;
+ va_start(ap, flags);
+ new_address = va_arg(ap, void *);
+ rc = LSS_NAME(_mremap)(old_address, old_size, new_size,
+ flags, new_address);
+ va_end(ap);
+ return rc;
+ }
+
+ LSS_INLINE int LSS_NAME(ptrace_detach)(pid_t pid) {
+ /* PTRACE_DETACH can sometimes forget to wake up the tracee and it
+ * then sends job control signals to the real parent, rather than to
+ * the tracer. We reduce the risk of this happening by starting a
+ * whole new time slice, and then quickly sending a SIGCONT signal
+ * right after detaching from the tracee.
+ *
+ * We use tkill to ensure that we only issue a wakeup for the thread being
+ * detached. Large multi threaded apps can take a long time in the kernel
+ * processing SIGCONT.
+ */
+ int rc, err;
+ LSS_NAME(sched_yield)();
+ rc = LSS_NAME(ptrace)(PTRACE_DETACH, pid, (void *)0, (void *)0);
+ err = LSS_ERRNO;
+ LSS_NAME(tkill)(pid, SIGCONT);
+ /* Old systems don't have tkill */
+ if (LSS_ERRNO == ENOSYS)
+ LSS_NAME(kill)(pid, SIGCONT);
+ LSS_ERRNO = err;
+ return rc;
+ }
+
+ LSS_INLINE int LSS_NAME(raise)(int sig) {
+ return LSS_NAME(kill)(LSS_NAME(getpid)(), sig);
+ }
+
+ LSS_INLINE int LSS_NAME(setpgrp)(void) {
+ return LSS_NAME(setpgid)(0, 0);
+ }
+
+ #if defined(__x86_64__)
+ /* Need to make sure loff_t isn't truncated to 32-bits under x32. */
+ LSS_INLINE ssize_t LSS_NAME(pread64)(int f, void *b, size_t c, loff_t o) {
+ LSS_BODY(4, ssize_t, pread64, LSS_SYSCALL_ARG(f), LSS_SYSCALL_ARG(b),
+ LSS_SYSCALL_ARG(c), (uint64_t)(o));
+ }
+
+ LSS_INLINE ssize_t LSS_NAME(pwrite64)(int f, const void *b, size_t c,
+ loff_t o) {
+ LSS_BODY(4, ssize_t, pwrite64, LSS_SYSCALL_ARG(f), LSS_SYSCALL_ARG(b),
+ LSS_SYSCALL_ARG(c), (uint64_t)(o));
+ }
+
+ LSS_INLINE int LSS_NAME(readahead)(int f, loff_t o, unsigned c) {
+ LSS_BODY(3, int, readahead, LSS_SYSCALL_ARG(f), (uint64_t)(o),
+ LSS_SYSCALL_ARG(c));
+ }
+ #elif defined(__mips__) && _MIPS_SIM == _MIPS_SIM_ABI64
+ LSS_INLINE _syscall4(ssize_t, pread64, int, f,
+ void *, b, size_t, c,
+ loff_t, o)
+ LSS_INLINE _syscall4(ssize_t, pwrite64, int, f,
+ const void *, b, size_t, c,
+ loff_t, o)
+ LSS_INLINE _syscall3(int, readahead, int, f,
+ loff_t, o, unsigned, c)
+ #else
+ #define __NR__pread64 __NR_pread64
+ #define __NR__pwrite64 __NR_pwrite64
+ #define __NR__readahead __NR_readahead
+ #if defined(__ARM_EABI__) || defined(__mips__)
+ /* On ARM and MIPS, a 64-bit parameter has to be in an even-odd register
+ * pair. Hence these calls ignore their fourth argument (r3) so that their
+ * fifth and sixth make such a pair (r4,r5).
+ */
+ #define LSS_LLARG_PAD 0,
+ LSS_INLINE _syscall6(ssize_t, _pread64, int, f,
+ void *, b, size_t, c,
+ unsigned, skip, unsigned, o1, unsigned, o2)
+ LSS_INLINE _syscall6(ssize_t, _pwrite64, int, f,
+ const void *, b, size_t, c,
+ unsigned, skip, unsigned, o1, unsigned, o2)
+ LSS_INLINE _syscall5(int, _readahead, int, f,
+ unsigned, skip,
+ unsigned, o1, unsigned, o2, size_t, c)
+ #else
+ #define LSS_LLARG_PAD
+ LSS_INLINE _syscall5(ssize_t, _pread64, int, f,
+ void *, b, size_t, c, unsigned, o1,
+ unsigned, o2)
+ LSS_INLINE _syscall5(ssize_t, _pwrite64, int, f,
+ const void *, b, size_t, c, unsigned, o1,
+ long, o2)
+ LSS_INLINE _syscall4(int, _readahead, int, f,
+ unsigned, o1, unsigned, o2, size_t, c)
+ #endif
+ /* We force 64bit-wide parameters onto the stack, then access each
+ * 32-bit component individually. This guarantees that we build the
+ * correct parameters independent of the native byte-order of the
+ * underlying architecture.
+ */
+ LSS_INLINE ssize_t LSS_NAME(pread64)(int fd, void *buf, size_t count,
+ loff_t off) {
+ union { loff_t off; unsigned arg[2]; } o = { off };
+ return LSS_NAME(_pread64)(fd, buf, count,
+ LSS_LLARG_PAD o.arg[0], o.arg[1]);
+ }
+ LSS_INLINE ssize_t LSS_NAME(pwrite64)(int fd, const void *buf,
+ size_t count, loff_t off) {
+ union { loff_t off; unsigned arg[2]; } o = { off };
+ return LSS_NAME(_pwrite64)(fd, buf, count,
+ LSS_LLARG_PAD o.arg[0], o.arg[1]);
+ }
+ LSS_INLINE int LSS_NAME(readahead)(int fd, loff_t off, int len) {
+ union { loff_t off; unsigned arg[2]; } o = { off };
+ return LSS_NAME(_readahead)(fd, LSS_LLARG_PAD o.arg[0], o.arg[1], len);
+ }
+ #endif
+#endif
+
+/*
+ * Polyfills for deprecated syscalls.
+ */
+
+#if !defined(__NR_dup2)
+ LSS_INLINE int LSS_NAME(dup2)(int s, int d) {
+ return LSS_NAME(dup3)(s, d, 0);
+ }
+#endif
+
+#if !defined(__NR_open)
+ LSS_INLINE int LSS_NAME(open)(const char *pathname, int flags, int mode) {
+ return LSS_NAME(openat)(AT_FDCWD, pathname, flags, mode);
+ }
+#endif
+
+#if !defined(__NR_unlink)
+ LSS_INLINE int LSS_NAME(unlink)(const char *pathname) {
+ return LSS_NAME(unlinkat)(AT_FDCWD, pathname, 0);
+ }
+#endif
+
+#if !defined(__NR_readlink)
+ LSS_INLINE int LSS_NAME(readlink)(const char *pathname, char *buffer,
+ size_t size) {
+ return LSS_NAME(readlinkat)(AT_FDCWD, pathname, buffer, size);
+ }
+#endif
+
+#if !defined(__NR_pipe)
+ LSS_INLINE int LSS_NAME(pipe)(int *pipefd) {
+ return LSS_NAME(pipe2)(pipefd, 0);
+ }
+#endif
+
+#if !defined(__NR_poll)
+ LSS_INLINE int LSS_NAME(poll)(struct kernel_pollfd *fds, unsigned int nfds,
+ int timeout) {
+ struct kernel_timespec timeout_ts;
+ struct kernel_timespec *timeout_ts_p = NULL;
+
+ if (timeout >= 0) {
+ timeout_ts.tv_sec = timeout / 1000;
+ timeout_ts.tv_nsec = (timeout % 1000) * 1000000;
+ timeout_ts_p = &timeout_ts;
+ }
+ return LSS_NAME(ppoll)(fds, nfds, timeout_ts_p, NULL, 0);
+ }
+#endif
+
+#if !defined(__NR_stat)
+ LSS_INLINE int LSS_NAME(stat)(const char *pathname,
+ struct kernel_stat *buf) {
+ return LSS_NAME(newfstatat)(AT_FDCWD, pathname, buf, 0);
+ }
+#endif
+
+#if !defined(__NR_waitpid)
+ LSS_INLINE pid_t LSS_NAME(waitpid)(pid_t pid, int *status, int options) {
+ return LSS_NAME(wait4)(pid, status, options, 0);
+ }
+#endif
+
+#if !defined(__NR_fork)
+// TODO: define this in an arch-independant way instead of inlining the clone
+// syscall body.
+
+# if defined(__aarch64__)
+ LSS_INLINE pid_t LSS_NAME(fork)(void) {
+ // No fork syscall on aarch64 - implement by means of the clone syscall.
+ // Note that this does not reset glibc's cached view of the PID/TID, so
+ // some glibc interfaces might go wrong in the forked subprocess.
+ int flags = SIGCHLD;
+ void *child_stack = NULL;
+ void *parent_tidptr = NULL;
+ void *newtls = NULL;
+ void *child_tidptr = NULL;
+
+ LSS_REG(0, flags);
+ LSS_REG(1, child_stack);
+ LSS_REG(2, parent_tidptr);
+ LSS_REG(3, newtls);
+ LSS_REG(4, child_tidptr);
+ LSS_BODY(pid_t, clone, "r"(__r0), "r"(__r1), "r"(__r2), "r"(__r3),
+ "r"(__r4));
+ }
+# elif defined(__x86_64__)
+ LSS_INLINE pid_t LSS_NAME(fork)(void) {
+ // Android disallows the fork syscall on x86_64 - implement by means of the
+ // clone syscall as above for aarch64.
+ int flags = SIGCHLD;
+ void *child_stack = NULL;
+ void *parent_tidptr = NULL;
+ void *newtls = NULL;
+ void *child_tidptr = NULL;
+
+ LSS_BODY(5, pid_t, clone, LSS_SYSCALL_ARG(flags),
+ LSS_SYSCALL_ARG(child_stack), LSS_SYSCALL_ARG(parent_tidptr),
+ LSS_SYSCALL_ARG(newtls), LSS_SYSCALL_ARG(child_tidptr));
+ }
+# else
+# error missing fork polyfill for this architecture
+# endif
+#endif
+
+/* These restore the original values of these macros saved by the
+ * corresponding #pragma push_macro near the top of this file. */
+#pragma pop_macro("stat64")
+#pragma pop_macro("fstat64")
+#pragma pop_macro("lstat64")
+#pragma pop_macro("pread64")
+#pragma pop_macro("pwrite64")
+#pragma pop_macro("getdents64")
+
+#if defined(__cplusplus) && !defined(SYS_CPLUSPLUS)
+}
+#endif
+
+#elif defined(__FreeBSD__)
+
+#include <unistd.h>
+#include <sys/stat.h>
+
+#define sys_readlink readlink
+
+#define sys_open open
+#define sys_close close
+#define sys_fstat fstat
+#define sys_fstat64 fstat
+#define kernel_stat stat
+#define kernel_stat64 stat
+#define sys_mmap mmap
+#define sys_munmap munmap
+
+#endif
+
+#endif
diff --git a/toolkit/crashreporter/google-breakpad/src/third_party/lss/tests/.gitignore b/toolkit/crashreporter/google-breakpad/src/third_party/lss/tests/.gitignore
new file mode 100644
index 0000000000..89c5d3c934
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/third_party/lss/tests/.gitignore
@@ -0,0 +1,4 @@
+/*_test
+
+# Some tests create temp files.
+/tempfile.*
diff --git a/toolkit/crashreporter/google-breakpad/src/third_party/lss/tests/Makefile b/toolkit/crashreporter/google-breakpad/src/third_party/lss/tests/Makefile
new file mode 100644
index 0000000000..5e37345f15
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/third_party/lss/tests/Makefile
@@ -0,0 +1,131 @@
+# Copyright 2018, 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.
+
+top_srcdir ?= ..
+
+DEF_FLAGS = -g -pipe
+DEF_WFLAGS = -Wall
+CFLAGS ?= $(DEF_FLAGS)
+CXXFLAGS ?= $(DEF_FLAGS)
+CFLAGS += $(DEF_WFLAGS) -Wstrict-prototypes
+CXXFLAGS += $(DEF_WFLAGS)
+CPPFLAGS += -I$(top_srcdir)
+# We use static linking here so that if people run through qemu/etc... by hand,
+# it's a lot easier to run/debug. Same for strace output.
+LDFLAGS += -static
+
+TESTS = \
+ fallocate \
+ sigtimedwait \
+ unlink \
+
+all: check
+
+%_test: %.c test_skel.h $(top_srcdir)/linux_syscall_support.h
+ $(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) -o $@ $<
+
+%_test: %.cc test_skel.h $(top_srcdir)/linux_syscall_support.h
+ $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(LDFLAGS) -o $@ $<
+
+%_run: %_test
+ @t=$(@:_run=_test); \
+ echo "./$$t"; \
+ if ! env -i ./$$t; then \
+ env -i strace -f -v ./$$t; \
+ echo "TRY: gdb -q -ex r -ex bt ./$$t"; \
+ exit 1; \
+ fi
+
+ALL_TEST_TARGETS = $(TESTS:=_test)
+compile_tests: $(ALL_TEST_TARGETS)
+
+ALL_RUN_TARGETS = $(TESTS:=_run)
+check: $(ALL_RUN_TARGETS)
+
+# The "tempfile" targets are the names we use with temp files.
+# Clean them out in case some tests crashed in the middle.
+clean:
+ rm -f *~ *.o tempfile.* a.out core $(ALL_TEST_TARGETS)
+
+.SUFFIXES:
+.PHONY: all check clean compile_tests
+.SECONDARY: $(ALL_TEST_TARGETS)
+
+# Try to cross-compile the tests for all our supported arches. We test with
+# both gcc and clang. We don't support execution (yet?), but just compiling
+# & linking helps catch common bugs.
+.PHONY: cross compile_cross
+cross_compile:
+ @echo "Running: $(MAKE) $@ CC='$(CC)' CXX='$(CXX)'"; \
+ if (echo '#include <stdio.h>' | $(CC) -x c -c -o /dev/null -) 2>/dev/null; then \
+ $(MAKE) -s clean; \
+ $(MAKE) -k --no-print-directory compile_tests; \
+ else \
+ echo "Skipping $(CC) test: not installed"; \
+ fi; \
+ echo
+
+# The names here are a best effort. Not easy to probe for.
+cross:
+ @for cc in \
+ "x86_64-pc-linux-gnu-gcc" \
+ "i686-pc-linux-gnu-gcc" \
+ "x86_64-pc-linux-gnu-gcc -mx32" \
+ "armv7a-unknown-linux-gnueabi-gcc -marm -mhard-float" \
+ "armv7a-unknown-linux-gnueabi-gcc -mthumb -mhard-float" \
+ "powerpc-unknown-linux-gnu-gcc" \
+ "aarch64-unknown-linux-gnu-gcc" \
+ "mips64-unknown-linux-gnu-gcc -mabi=64" \
+ "mips64-unknown-linux-gnu-gcc -mabi=32" \
+ "mips64-unknown-linux-gnu-gcc -mabi=n32" \
+ "s390-ibm-linux-gnu-gcc" \
+ "s390x-ibm-linux-gnu-gcc" \
+ ; do \
+ cxx=`echo "$$cc" | sed 's:-gcc:-g++:'`; \
+ $(MAKE) --no-print-directory CC="$$cc" CXX="$$cxx" cross_compile; \
+ \
+ sysroot=`$$cc --print-sysroot 2>/dev/null`; \
+ gccdir=`$$cc -print-file-name=libgcc.a 2>/dev/null`; \
+ gccdir=`dirname "$$gccdir"`; \
+ : Skip building for clang for mips/o32 and s390/31-bit until it works.; \
+ case $$cc in \
+ mips64*-mabi=32) continue;; \
+ s390-*) continue;; \
+ esac; \
+ set -- $$cc; \
+ tuple=$${1%-gcc}; \
+ shift; \
+ cc="clang -target $$tuple $$*"; \
+ : Assume the build system is x86_64 based, so ignore the sysroot.; \
+ case $$tuple in \
+ x86_64*) ;; \
+ *) cc="$$cc --sysroot $$sysroot -B$$gccdir -L$$gccdir";; \
+ esac; \
+ cxx=`echo "$$cc" | sed 's:^clang:clang++:'`; \
+ $(MAKE) --no-print-directory CC="$$cc" CXX="$$cxx" cross_compile; \
+ done
diff --git a/toolkit/crashreporter/google-breakpad/src/third_party/lss/tests/README.md b/toolkit/crashreporter/google-breakpad/src/third_party/lss/tests/README.md
new file mode 100644
index 0000000000..45af3c37ed
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/third_party/lss/tests/README.md
@@ -0,0 +1,52 @@
+# LSS Tests
+
+## Source Layout
+
+The general layout of the tests:
+* [test_skel.h]: Test helpers for common checks/etc...
+* xxx.c: Unittest for the xxx syscall (e.g. `open.c`).
+* [Makefile]: New tests should be registered in the `TESTS` variable.
+
+## Test Guidelines
+
+The unittest itself generally follows the conventions:
+* Written in C (unless a very specific language behavior is needed).
+* You should only need to `#include "test_skel.h"`. For new system headers, try
+ to add them here rather than copying to exact unittest (if possible).
+ It might slow compilation down slightly, but makes the code easier to manage.
+ Make sure it is included first.
+* Use `assert()` on everything to check return values.
+* Use `sys_xxx()` to access the syscall via LSS (compared to `xxx()` which tends
+ to come from the C library).
+* If you need a tempfile, use `tempfile.XXXXXX` for templates with helpers like
+ `mkstemp`. Try to clean them up when you're done with them.
+ These will be created in the cwd, but that's fine.
+* Don't worry about trying to verify the kernel/C library API and various edge
+ cases. The goal of LSS is to make sure that we pass args along correctly to
+ the syscall only.
+* Make sure to leave comments in the test so it's clear what behavior you're
+ trying to verify (and how).
+
+Feel free to extend [test_skel.h] with more helpers if they're useful to more
+than one test.
+
+If you're looking for a simple example, start with [unlink.c](./unlink.c).
+You should be able to copy this over and replace the content of `main()`.
+
+## Running The Tests
+
+Simply run `make`. This will compile & execute all the tests on your local
+system. A standard `make clean` will clean up all the objects.
+
+If you need to debug something, then the programs are simply named `xxx_test`
+and can easily be thrown into `gdb ./xxx_test`.
+
+We have rudimentary cross-compile testing via gcc and clang. Try running
+`make cross` -- for any toolchains you don't have available, it should skip
+things automatically. This only verifies the compilation & linking stages
+though.
+
+The cross-compilers can be created using <http://crosstool-ng.github.io/>.
+
+[Makefile]: ./Makefile
+[test_skel.h]: ./test_skel.h
diff --git a/toolkit/crashreporter/google-breakpad/src/third_party/lss/tests/fallocate.c b/toolkit/crashreporter/google-breakpad/src/third_party/lss/tests/fallocate.c
new file mode 100644
index 0000000000..c156e58986
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/third_party/lss/tests/fallocate.c
@@ -0,0 +1,67 @@
+/* Copyright 2019, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "test_skel.h"
+
+int main(int argc, char *argv[]) {
+ int fd = 0, mode = 0;
+ loff_t offset = 0, len = 0;
+
+ // Bad file descriptor.
+ fd = -1;
+ assert(sys_fallocate(fd, mode, offset, len) == -1);
+ assert(errno == EBADF);
+
+ char filename[] = "tempfile.XXXXXX";
+ fd = mkstemp(filename);
+ assert(fd >= 0);
+
+ // Invalid len.
+ assert(sys_fallocate(fd, mode, offset, len) == -1);
+ assert(errno == EINVAL);
+
+ // Small offset and length succeeds.
+ len = 4096;
+ assert(sys_fallocate(fd, mode, offset, len) == 0);
+
+ // Large offset succeeds and isn't truncated.
+ offset = 1llu + UINT32_MAX;
+ assert(sys_fallocate(fd, mode , offset, len) == 0);
+
+#if defined(__NR_fstat64)
+ struct kernel_stat64 st;
+ assert(sys_fstat64(fd, &st) == 0);
+#else
+ struct kernel_stat st;
+ assert(sys_fstat(fd, &st) == 0);
+#endif
+ assert(st.st_size == offset + len);
+
+ return 0;
+}
diff --git a/toolkit/crashreporter/google-breakpad/src/third_party/lss/tests/sigtimedwait.c b/toolkit/crashreporter/google-breakpad/src/third_party/lss/tests/sigtimedwait.c
new file mode 100644
index 0000000000..ee2f740fe4
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/third_party/lss/tests/sigtimedwait.c
@@ -0,0 +1,58 @@
+/* Copyright 2019, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "test_skel.h"
+
+int main(int argc, char *argv[]) {
+
+ struct kernel_sigset_t sigset = {};
+ siginfo_t siginfo = {};
+ struct timespec timeout = {};
+
+ // Invalid timeouts.
+ timeout.tv_sec = -1;
+ assert(sys_sigtimedwait(&sigset, &siginfo, &timeout) == -1);
+ assert(errno == EINVAL);
+
+ // Expired timeouts.
+ timeout.tv_sec = 0;
+ assert(sys_sigtimedwait(&sigset, &siginfo, &timeout) == -1);
+ assert(errno == EAGAIN);
+
+ // Success.
+ const int kTestSignal = SIGCONT;
+ assert(sys_sigemptyset(&sigset) == 0);
+ assert(sys_sigaddset(&sigset, kTestSignal) == 0);
+ assert(sys_sigprocmask(SIG_BLOCK, &sigset, NULL) == 0);
+ assert(raise(kTestSignal) == 0);
+ assert(sys_sigtimedwait(&sigset, &siginfo, &timeout) == kTestSignal);
+ assert(siginfo.si_signo == kTestSignal);
+
+ return 0;
+}
diff --git a/toolkit/crashreporter/google-breakpad/src/third_party/lss/tests/test_skel.h b/toolkit/crashreporter/google-breakpad/src/third_party/lss/tests/test_skel.h
new file mode 100644
index 0000000000..9ff0eb3711
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/third_party/lss/tests/test_skel.h
@@ -0,0 +1,70 @@
+/* Copyright 2018, 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.
+ */
+
+/*
+ * Make sure it's defined before including anything else. A number of syscalls
+ * are GNU extensions and rely on being exported by glibc.
+ */
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+/*
+ * Make sure the assert checks aren't removed as all the unittests are based
+ * on them.
+ */
+#undef NDEBUG
+
+#include <assert.h>
+#include <fcntl.h>
+#include <sched.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/mman.h>
+#include <sys/prctl.h>
+#include <sys/stat.h>
+#include <sys/vfs.h>
+#include <sys/wait.h>
+
+#include <linux/capability.h>
+
+#include "linux_syscall_support.h"
+
+void assert_buffers_eq_len(const void *buf1, const void *buf2, size_t len) {
+ const uint8_t *u8_1 = (const uint8_t *)buf1;
+ const uint8_t *u8_2 = (const uint8_t *)buf2;
+ size_t i;
+
+ for (i = 0; i < len; ++i) {
+ if (u8_1[i] != u8_2[i])
+ printf("offset %zu: %02x != %02x\n", i, u8_1[i], u8_2[i]);
+ }
+}
+#define assert_buffers_eq(obj1, obj2) assert_buffers_eq_len(obj1, obj2, sizeof(*obj1))
diff --git a/toolkit/crashreporter/google-breakpad/src/third_party/lss/tests/unlink.c b/toolkit/crashreporter/google-breakpad/src/third_party/lss/tests/unlink.c
new file mode 100644
index 0000000000..70c8bc9a5e
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/third_party/lss/tests/unlink.c
@@ -0,0 +1,48 @@
+/* Copyright 2018, 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 "test_skel.h"
+
+int main(int argc, char *argv[]) {
+ // Get a unique path to play with.
+ char foo[] = "tempfile.XXXXXX";
+ int fd = mkstemp(foo);
+ assert(fd != -1);
+
+ // Make sure it exists.
+ assert(access(foo, F_OK) == 0);
+
+ // Then delete it.
+ assert(sys_unlink(foo) == 0);
+
+ // Make sure it's gone.
+ assert(access(foo, F_OK) != 0);
+
+ return 0;
+}
diff --git a/toolkit/crashreporter/google-breakpad/src/third_party/mac_headers/README b/toolkit/crashreporter/google-breakpad/src/third_party/mac_headers/README
new file mode 100644
index 0000000000..c681bb3d65
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/third_party/mac_headers/README
@@ -0,0 +1,2 @@
+These headers were copied from the Mac OS X 10.7 SDK to enable building
+the Mac dump_syms code that processes Mach-O files on Linux.
diff --git a/toolkit/crashreporter/google-breakpad/src/third_party/mac_headers/architecture/byte_order.h b/toolkit/crashreporter/google-breakpad/src/third_party/mac_headers/architecture/byte_order.h
new file mode 100644
index 0000000000..b772d9f38e
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/third_party/mac_headers/architecture/byte_order.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 1999-2008 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1992 NeXT Computer, Inc.
+ *
+ * Byte ordering conversion.
+ *
+ */
+/* This file mostly left blank */
+
+#ifndef _ARCHITECTURE_BYTE_ORDER_H_
+#define _ARCHITECTURE_BYTE_ORDER_H_
+
+/*
+ * Identify the byte order
+ * of the current host.
+ */
+
+enum NXByteOrder {
+ NX_UnknownByteOrder,
+ NX_LittleEndian,
+ NX_BigEndian
+};
+
+#endif /* _ARCHITECTURE_BYTE_ORDER_H_ */
diff --git a/toolkit/crashreporter/google-breakpad/src/third_party/mac_headers/i386/_types.h b/toolkit/crashreporter/google-breakpad/src/third_party/mac_headers/i386/_types.h
new file mode 100644
index 0000000000..2ed7fd6759
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/third_party/mac_headers/i386/_types.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ *
+ * Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
+ */
+#ifndef _BSD_I386__TYPES_H_
+#define _BSD_I386__TYPES_H_
+
+typedef long __darwin_intptr_t;
+typedef unsigned int __darwin_natural_t;
+
+#endif /* _BSD_I386__TYPES_H_ */
diff --git a/toolkit/crashreporter/google-breakpad/src/third_party/mac_headers/mach-o/arch.h b/toolkit/crashreporter/google-breakpad/src/third_party/mac_headers/mach-o/arch.h
new file mode 100644
index 0000000000..526c10fc84
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/third_party/mac_headers/mach-o/arch.h
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+#ifndef _MACH_O_ARCH_H_
+#define _MACH_O_ARCH_H_
+/*
+ * Copyright (c) 1997 Apple Computer, Inc.
+ *
+ * Functions that deal with information about architectures.
+ *
+ */
+
+#include <stdint.h>
+#include <mach/machine.h>
+#include <architecture/byte_order.h>
+
+/* The NXArchInfo structs contain the architectures symbolic name
+ * (such as "ppc"), its CPU type and CPU subtype as defined in
+ * mach/machine.h, the byte order for the architecture, and a
+ * describing string (such as "PowerPC").
+ * There will both be entries for specific CPUs (such as ppc604e) as
+ * well as generic "family" entries (such as ppc).
+ */
+typedef struct {
+ const char *name;
+ cpu_type_t cputype;
+ cpu_subtype_t cpusubtype;
+ enum NXByteOrder byteorder;
+ const char *description;
+} NXArchInfo;
+
+#if __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/* NXGetAllArchInfos() returns a pointer to an array of all known
+ * NXArchInfo structures. The last NXArchInfo is marked by a NULL name.
+ */
+extern const NXArchInfo *NXGetAllArchInfos(void);
+
+/* NXGetLocalArchInfo() returns the NXArchInfo for the local host, or NULL
+ * if none is known.
+ */
+extern const NXArchInfo *NXGetLocalArchInfo(void);
+
+/* NXGetArchInfoFromName() and NXGetArchInfoFromCpuType() return the
+ * NXArchInfo from the architecture's name or cputype/cpusubtype
+ * combination. A cpusubtype of CPU_SUBTYPE_MULTIPLE can be used
+ * to request the most general NXArchInfo known for the given cputype.
+ * NULL is returned if no matching NXArchInfo can be found.
+ */
+extern const NXArchInfo *NXGetArchInfoFromName(const char *name);
+extern const NXArchInfo *NXGetArchInfoFromCpuType(cpu_type_t cputype,
+ cpu_subtype_t cpusubtype);
+
+/* NXFindBestFatArch() is passed a cputype and cpusubtype and a set of
+ * fat_arch structs and selects the best one that matches (if any) and returns
+ * a pointer to that fat_arch struct (or NULL). The fat_arch structs must be
+ * in the host byte order and correct such that the fat_archs really points to
+ * enough memory for nfat_arch structs. It is possible that this routine could
+ * fail if new cputypes or cpusubtypes are added and an old version of this
+ * routine is used. But if there is an exact match between the cputype and
+ * cpusubtype and one of the fat_arch structs this routine will always succeed.
+ */
+extern struct fat_arch *NXFindBestFatArch(cpu_type_t cputype,
+ cpu_subtype_t cpusubtype,
+ struct fat_arch *fat_archs,
+ uint32_t nfat_archs);
+
+/* NXCombineCpuSubtypes() returns the resulting cpusubtype when combining two
+ * different cpusubtypes for the specified cputype. If the two cpusubtypes
+ * can't be combined (the specific subtypes are mutually exclusive) -1 is
+ * returned indicating it is an error to combine them. This can also fail and
+ * return -1 if new cputypes or cpusubtypes are added and an old version of
+ * this routine is used. But if the cpusubtypes are the same they can always
+ * be combined and this routine will return the cpusubtype pass in.
+ */
+extern cpu_subtype_t NXCombineCpuSubtypes(cpu_type_t cputype,
+ cpu_subtype_t cpusubtype1,
+ cpu_subtype_t cpusubtype2);
+
+#if __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* _MACH_O_ARCH_H_ */
diff --git a/toolkit/crashreporter/google-breakpad/src/third_party/mac_headers/mach-o/fat.h b/toolkit/crashreporter/google-breakpad/src/third_party/mac_headers/mach-o/fat.h
new file mode 100644
index 0000000000..e2bcf433d5
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/third_party/mac_headers/mach-o/fat.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+#ifndef _MACH_O_FAT_H_
+#define _MACH_O_FAT_H_
+/*
+ * This header file describes the structures of the file format for "fat"
+ * architecture specific file (wrapper design). At the begining of the file
+ * there is one fat_header structure followed by a number of fat_arch
+ * structures. For each architecture in the file, specified by a pair of
+ * cputype and cpusubtype, the fat_header describes the file offset, file
+ * size and alignment in the file of the architecture specific member.
+ * The padded bytes in the file to place each member on it's specific alignment
+ * are defined to be read as zeros and can be left as "holes" if the file system
+ * can support them as long as they read as zeros.
+ *
+ * All structures defined here are always written and read to/from disk
+ * in big-endian order.
+ */
+
+/*
+ * <mach/machine.h> is needed here for the cpu_type_t and cpu_subtype_t types
+ * and contains the constants for the possible values of these types.
+ */
+#include <stdint.h>
+#include <mach/machine.h>
+#include <architecture/byte_order.h>
+
+#define FAT_MAGIC 0xcafebabe
+#define FAT_CIGAM 0xbebafeca /* NXSwapLong(FAT_MAGIC) */
+
+struct fat_header {
+ uint32_t magic; /* FAT_MAGIC */
+ uint32_t nfat_arch; /* number of structs that follow */
+};
+
+struct fat_arch {
+ cpu_type_t cputype; /* cpu specifier (int) */
+ cpu_subtype_t cpusubtype; /* machine specifier (int) */
+ uint32_t offset; /* file offset to this object file */
+ uint32_t size; /* size of this object file */
+ uint32_t align; /* alignment as a power of 2 */
+};
+
+#endif /* _MACH_O_FAT_H_ */
diff --git a/toolkit/crashreporter/google-breakpad/src/third_party/mac_headers/mach-o/loader.h b/toolkit/crashreporter/google-breakpad/src/third_party/mac_headers/mach-o/loader.h
new file mode 100644
index 0000000000..ff18e29c73
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/third_party/mac_headers/mach-o/loader.h
@@ -0,0 +1,1402 @@
+/*
+ * Copyright (c) 1999-2010 Apple Inc. All Rights Reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+#ifndef _MACHO_LOADER_H_
+#define _MACHO_LOADER_H_
+
+/*
+ * This file describes the format of mach object files.
+ */
+#include <stdint.h>
+
+/*
+ * <mach/machine.h> is needed here for the cpu_type_t and cpu_subtype_t types
+ * and contains the constants for the possible values of these types.
+ */
+#include <mach/machine.h>
+
+/*
+ * <mach/vm_prot.h> is needed here for the vm_prot_t type and contains the
+ * constants that are or'ed together for the possible values of this type.
+ */
+#include <mach/vm_prot.h>
+
+/*
+ * <machine/thread_status.h> is expected to define the flavors of the thread
+ * states and the structures of those flavors for each machine.
+ */
+#include <mach/machine/thread_status.h>
+#include <architecture/byte_order.h>
+
+/*
+ * The 32-bit mach header appears at the very beginning of the object file for
+ * 32-bit architectures.
+ */
+struct mach_header {
+ uint32_t magic; /* mach magic number identifier */
+ cpu_type_t cputype; /* cpu specifier */
+ cpu_subtype_t cpusubtype; /* machine specifier */
+ uint32_t filetype; /* type of file */
+ uint32_t ncmds; /* number of load commands */
+ uint32_t sizeofcmds; /* the size of all the load commands */
+ uint32_t flags; /* flags */
+};
+
+/* Constant for the magic field of the mach_header (32-bit architectures) */
+#define MH_MAGIC 0xfeedface /* the mach magic number */
+#define MH_CIGAM 0xcefaedfe /* NXSwapInt(MH_MAGIC) */
+
+/*
+ * The 64-bit mach header appears at the very beginning of object files for
+ * 64-bit architectures.
+ */
+struct mach_header_64 {
+ uint32_t magic; /* mach magic number identifier */
+ cpu_type_t cputype; /* cpu specifier */
+ cpu_subtype_t cpusubtype; /* machine specifier */
+ uint32_t filetype; /* type of file */
+ uint32_t ncmds; /* number of load commands */
+ uint32_t sizeofcmds; /* the size of all the load commands */
+ uint32_t flags; /* flags */
+ uint32_t reserved; /* reserved */
+};
+
+/* Constant for the magic field of the mach_header_64 (64-bit architectures) */
+#define MH_MAGIC_64 0xfeedfacf /* the 64-bit mach magic number */
+#define MH_CIGAM_64 0xcffaedfe /* NXSwapInt(MH_MAGIC_64) */
+
+/*
+ * The layout of the file depends on the filetype. For all but the MH_OBJECT
+ * file type the segments are padded out and aligned on a segment alignment
+ * boundary for efficient demand pageing. The MH_EXECUTE, MH_FVMLIB, MH_DYLIB,
+ * MH_DYLINKER and MH_BUNDLE file types also have the headers included as part
+ * of their first segment.
+ *
+ * The file type MH_OBJECT is a compact format intended as output of the
+ * assembler and input (and possibly output) of the link editor (the .o
+ * format). All sections are in one unnamed segment with no segment padding.
+ * This format is used as an executable format when the file is so small the
+ * segment padding greatly increases its size.
+ *
+ * The file type MH_PRELOAD is an executable format intended for things that
+ * are not executed under the kernel (proms, stand alones, kernels, etc). The
+ * format can be executed under the kernel but may demand paged it and not
+ * preload it before execution.
+ *
+ * A core file is in MH_CORE format and can be any in an arbritray legal
+ * Mach-O file.
+ *
+ * Constants for the filetype field of the mach_header
+ */
+#define MH_OBJECT 0x1 /* relocatable object file */
+#define MH_EXECUTE 0x2 /* demand paged executable file */
+#define MH_FVMLIB 0x3 /* fixed VM shared library file */
+#define MH_CORE 0x4 /* core file */
+#define MH_PRELOAD 0x5 /* preloaded executable file */
+#define MH_DYLIB 0x6 /* dynamically bound shared library */
+#define MH_DYLINKER 0x7 /* dynamic link editor */
+#define MH_BUNDLE 0x8 /* dynamically bound bundle file */
+#define MH_DYLIB_STUB 0x9 /* shared library stub for static */
+ /* linking only, no section contents */
+#define MH_DSYM 0xa /* companion file with only debug */
+ /* sections */
+#define MH_KEXT_BUNDLE 0xb /* x86_64 kexts */
+
+/* Constants for the flags field of the mach_header */
+#define MH_NOUNDEFS 0x1 /* the object file has no undefined
+ references */
+#define MH_INCRLINK 0x2 /* the object file is the output of an
+ incremental link against a base file
+ and can't be link edited again */
+#define MH_DYLDLINK 0x4 /* the object file is input for the
+ dynamic linker and can't be staticly
+ link edited again */
+#define MH_BINDATLOAD 0x8 /* the object file's undefined
+ references are bound by the dynamic
+ linker when loaded. */
+#define MH_PREBOUND 0x10 /* the file has its dynamic undefined
+ references prebound. */
+#define MH_SPLIT_SEGS 0x20 /* the file has its read-only and
+ read-write segments split */
+#define MH_LAZY_INIT 0x40 /* the shared library init routine is
+ to be run lazily via catching memory
+ faults to its writeable segments
+ (obsolete) */
+#define MH_TWOLEVEL 0x80 /* the image is using two-level name
+ space bindings */
+#define MH_FORCE_FLAT 0x100 /* the executable is forcing all images
+ to use flat name space bindings */
+#define MH_NOMULTIDEFS 0x200 /* this umbrella guarantees no multiple
+ defintions of symbols in its
+ sub-images so the two-level namespace
+ hints can always be used. */
+#define MH_NOFIXPREBINDING 0x400 /* do not have dyld notify the
+ prebinding agent about this
+ executable */
+#define MH_PREBINDABLE 0x800 /* the binary is not prebound but can
+ have its prebinding redone. only used
+ when MH_PREBOUND is not set. */
+#define MH_ALLMODSBOUND 0x1000 /* indicates that this binary binds to
+ all two-level namespace modules of
+ its dependent libraries. only used
+ when MH_PREBINDABLE and MH_TWOLEVEL
+ are both set. */
+#define MH_SUBSECTIONS_VIA_SYMBOLS 0x2000/* safe to divide up the sections into
+ sub-sections via symbols for dead
+ code stripping */
+#define MH_CANONICAL 0x4000 /* the binary has been canonicalized
+ via the unprebind operation */
+#define MH_WEAK_DEFINES 0x8000 /* the final linked image contains
+ external weak symbols */
+#define MH_BINDS_TO_WEAK 0x10000 /* the final linked image uses
+ weak symbols */
+
+#define MH_ALLOW_STACK_EXECUTION 0x20000/* When this bit is set, all stacks
+ in the task will be given stack
+ execution privilege. Only used in
+ MH_EXECUTE filetypes. */
+#define MH_ROOT_SAFE 0x40000 /* When this bit is set, the binary
+ declares it is safe for use in
+ processes with uid zero */
+
+#define MH_SETUID_SAFE 0x80000 /* When this bit is set, the binary
+ declares it is safe for use in
+ processes when issetugid() is true */
+
+#define MH_NO_REEXPORTED_DYLIBS 0x100000 /* When this bit is set on a dylib,
+ the static linker does not need to
+ examine dependent dylibs to see
+ if any are re-exported */
+#define MH_PIE 0x200000 /* When this bit is set, the OS will
+ load the main executable at a
+ random address. Only used in
+ MH_EXECUTE filetypes. */
+#define MH_DEAD_STRIPPABLE_DYLIB 0x400000 /* Only for use on dylibs. When
+ linking against a dylib that
+ has this bit set, the static linker
+ will automatically not create a
+ LC_LOAD_DYLIB load command to the
+ dylib if no symbols are being
+ referenced from the dylib. */
+#define MH_HAS_TLV_DESCRIPTORS 0x800000 /* Contains a section of type
+ S_THREAD_LOCAL_VARIABLES */
+
+#define MH_NO_HEAP_EXECUTION 0x1000000 /* When this bit is set, the OS will
+ run the main executable with
+ a non-executable heap even on
+ platforms (e.g. i386) that don't
+ require it. Only used in MH_EXECUTE
+ filetypes. */
+
+/*
+ * The load commands directly follow the mach_header. The total size of all
+ * of the commands is given by the sizeofcmds field in the mach_header. All
+ * load commands must have as their first two fields cmd and cmdsize. The cmd
+ * field is filled in with a constant for that command type. Each command type
+ * has a structure specifically for it. The cmdsize field is the size in bytes
+ * of the particular load command structure plus anything that follows it that
+ * is a part of the load command (i.e. section structures, strings, etc.). To
+ * advance to the next load command the cmdsize can be added to the offset or
+ * pointer of the current load command. The cmdsize for 32-bit architectures
+ * MUST be a multiple of 4 bytes and for 64-bit architectures MUST be a multiple
+ * of 8 bytes (these are forever the maximum alignment of any load commands).
+ * The padded bytes must be zero. All tables in the object file must also
+ * follow these rules so the file can be memory mapped. Otherwise the pointers
+ * to these tables will not work well or at all on some machines. With all
+ * padding zeroed like objects will compare byte for byte.
+ */
+struct load_command {
+ uint32_t cmd; /* type of load command */
+ uint32_t cmdsize; /* total size of command in bytes */
+};
+
+/*
+ * After MacOS X 10.1 when a new load command is added that is required to be
+ * understood by the dynamic linker for the image to execute properly the
+ * LC_REQ_DYLD bit will be or'ed into the load command constant. If the dynamic
+ * linker sees such a load command it it does not understand will issue a
+ * "unknown load command required for execution" error and refuse to use the
+ * image. Other load commands without this bit that are not understood will
+ * simply be ignored.
+ */
+#define LC_REQ_DYLD 0x80000000
+
+/* Constants for the cmd field of all load commands, the type */
+#define LC_SEGMENT 0x1 /* segment of this file to be mapped */
+#define LC_SYMTAB 0x2 /* link-edit stab symbol table info */
+#define LC_SYMSEG 0x3 /* link-edit gdb symbol table info (obsolete) */
+#define LC_THREAD 0x4 /* thread */
+#define LC_UNIXTHREAD 0x5 /* unix thread (includes a stack) */
+#define LC_LOADFVMLIB 0x6 /* load a specified fixed VM shared library */
+#define LC_IDFVMLIB 0x7 /* fixed VM shared library identification */
+#define LC_IDENT 0x8 /* object identification info (obsolete) */
+#define LC_FVMFILE 0x9 /* fixed VM file inclusion (internal use) */
+#define LC_PREPAGE 0xa /* prepage command (internal use) */
+#define LC_DYSYMTAB 0xb /* dynamic link-edit symbol table info */
+#define LC_LOAD_DYLIB 0xc /* load a dynamically linked shared library */
+#define LC_ID_DYLIB 0xd /* dynamically linked shared lib ident */
+#define LC_LOAD_DYLINKER 0xe /* load a dynamic linker */
+#define LC_ID_DYLINKER 0xf /* dynamic linker identification */
+#define LC_PREBOUND_DYLIB 0x10 /* modules prebound for a dynamically */
+ /* linked shared library */
+#define LC_ROUTINES 0x11 /* image routines */
+#define LC_SUB_FRAMEWORK 0x12 /* sub framework */
+#define LC_SUB_UMBRELLA 0x13 /* sub umbrella */
+#define LC_SUB_CLIENT 0x14 /* sub client */
+#define LC_SUB_LIBRARY 0x15 /* sub library */
+#define LC_TWOLEVEL_HINTS 0x16 /* two-level namespace lookup hints */
+#define LC_PREBIND_CKSUM 0x17 /* prebind checksum */
+
+/*
+ * load a dynamically linked shared library that is allowed to be missing
+ * (all symbols are weak imported).
+ */
+#define LC_LOAD_WEAK_DYLIB (0x18 | LC_REQ_DYLD)
+
+#define LC_SEGMENT_64 0x19 /* 64-bit segment of this file to be
+ mapped */
+#define LC_ROUTINES_64 0x1a /* 64-bit image routines */
+#define LC_UUID 0x1b /* the uuid */
+#define LC_RPATH (0x1c | LC_REQ_DYLD) /* runpath additions */
+#define LC_CODE_SIGNATURE 0x1d /* local of code signature */
+#define LC_SEGMENT_SPLIT_INFO 0x1e /* local of info to split segments */
+#define LC_REEXPORT_DYLIB (0x1f | LC_REQ_DYLD) /* load and re-export dylib */
+#define LC_LAZY_LOAD_DYLIB 0x20 /* delay load of dylib until first use */
+#define LC_ENCRYPTION_INFO 0x21 /* encrypted segment information */
+#define LC_DYLD_INFO 0x22 /* compressed dyld information */
+#define LC_DYLD_INFO_ONLY (0x22|LC_REQ_DYLD) /* compressed dyld information only */
+#define LC_LOAD_UPWARD_DYLIB (0x23 | LC_REQ_DYLD) /* load upward dylib */
+#define LC_VERSION_MIN_MACOSX 0x24 /* build for MacOSX min OS version */
+#define LC_VERSION_MIN_IPHONEOS 0x25 /* build for iPhoneOS min OS version */
+#define LC_FUNCTION_STARTS 0x26 /* compressed table of function start addresses */
+#define LC_DYLD_ENVIRONMENT 0x27 /* string for dyld to treat
+ like environment variable */
+
+/*
+ * A variable length string in a load command is represented by an lc_str
+ * union. The strings are stored just after the load command structure and
+ * the offset is from the start of the load command structure. The size
+ * of the string is reflected in the cmdsize field of the load command.
+ * Once again any padded bytes to bring the cmdsize field to a multiple
+ * of 4 bytes must be zero.
+ */
+union lc_str {
+ uint32_t offset; /* offset to the string */
+#ifndef __LP64__
+ char *ptr; /* pointer to the string */
+#endif
+};
+
+/*
+ * The segment load command indicates that a part of this file is to be
+ * mapped into the task's address space. The size of this segment in memory,
+ * vmsize, maybe equal to or larger than the amount to map from this file,
+ * filesize. The file is mapped starting at fileoff to the beginning of
+ * the segment in memory, vmaddr. The rest of the memory of the segment,
+ * if any, is allocated zero fill on demand. The segment's maximum virtual
+ * memory protection and initial virtual memory protection are specified
+ * by the maxprot and initprot fields. If the segment has sections then the
+ * section structures directly follow the segment command and their size is
+ * reflected in cmdsize.
+ */
+struct segment_command { /* for 32-bit architectures */
+ uint32_t cmd; /* LC_SEGMENT */
+ uint32_t cmdsize; /* includes sizeof section structs */
+ char segname[16]; /* segment name */
+ uint32_t vmaddr; /* memory address of this segment */
+ uint32_t vmsize; /* memory size of this segment */
+ uint32_t fileoff; /* file offset of this segment */
+ uint32_t filesize; /* amount to map from the file */
+ vm_prot_t maxprot; /* maximum VM protection */
+ vm_prot_t initprot; /* initial VM protection */
+ uint32_t nsects; /* number of sections in segment */
+ uint32_t flags; /* flags */
+};
+
+/*
+ * The 64-bit segment load command indicates that a part of this file is to be
+ * mapped into a 64-bit task's address space. If the 64-bit segment has
+ * sections then section_64 structures directly follow the 64-bit segment
+ * command and their size is reflected in cmdsize.
+ */
+struct segment_command_64 { /* for 64-bit architectures */
+ uint32_t cmd; /* LC_SEGMENT_64 */
+ uint32_t cmdsize; /* includes sizeof section_64 structs */
+ char segname[16]; /* segment name */
+ uint64_t vmaddr; /* memory address of this segment */
+ uint64_t vmsize; /* memory size of this segment */
+ uint64_t fileoff; /* file offset of this segment */
+ uint64_t filesize; /* amount to map from the file */
+ vm_prot_t maxprot; /* maximum VM protection */
+ vm_prot_t initprot; /* initial VM protection */
+ uint32_t nsects; /* number of sections in segment */
+ uint32_t flags; /* flags */
+};
+
+/* Constants for the flags field of the segment_command */
+#define SG_HIGHVM 0x1 /* the file contents for this segment is for
+ the high part of the VM space, the low part
+ is zero filled (for stacks in core files) */
+#define SG_FVMLIB 0x2 /* this segment is the VM that is allocated by
+ a fixed VM library, for overlap checking in
+ the link editor */
+#define SG_NORELOC 0x4 /* this segment has nothing that was relocated
+ in it and nothing relocated to it, that is
+ it maybe safely replaced without relocation*/
+#define SG_PROTECTED_VERSION_1 0x8 /* This segment is protected. If the
+ segment starts at file offset 0, the
+ first page of the segment is not
+ protected. All other pages of the
+ segment are protected. */
+
+/*
+ * A segment is made up of zero or more sections. Non-MH_OBJECT files have
+ * all of their segments with the proper sections in each, and padded to the
+ * specified segment alignment when produced by the link editor. The first
+ * segment of a MH_EXECUTE and MH_FVMLIB format file contains the mach_header
+ * and load commands of the object file before its first section. The zero
+ * fill sections are always last in their segment (in all formats). This
+ * allows the zeroed segment padding to be mapped into memory where zero fill
+ * sections might be. The gigabyte zero fill sections, those with the section
+ * type S_GB_ZEROFILL, can only be in a segment with sections of this type.
+ * These segments are then placed after all other segments.
+ *
+ * The MH_OBJECT format has all of its sections in one segment for
+ * compactness. There is no padding to a specified segment boundary and the
+ * mach_header and load commands are not part of the segment.
+ *
+ * Sections with the same section name, sectname, going into the same segment,
+ * segname, are combined by the link editor. The resulting section is aligned
+ * to the maximum alignment of the combined sections and is the new section's
+ * alignment. The combined sections are aligned to their original alignment in
+ * the combined section. Any padded bytes to get the specified alignment are
+ * zeroed.
+ *
+ * The format of the relocation entries referenced by the reloff and nreloc
+ * fields of the section structure for mach object files is described in the
+ * header file <reloc.h>.
+ */
+struct section { /* for 32-bit architectures */
+ char sectname[16]; /* name of this section */
+ char segname[16]; /* segment this section goes in */
+ uint32_t addr; /* memory address of this section */
+ uint32_t size; /* size in bytes of this section */
+ uint32_t offset; /* file offset of this section */
+ uint32_t align; /* section alignment (power of 2) */
+ uint32_t reloff; /* file offset of relocation entries */
+ uint32_t nreloc; /* number of relocation entries */
+ uint32_t flags; /* flags (section type and attributes)*/
+ uint32_t reserved1; /* reserved (for offset or index) */
+ uint32_t reserved2; /* reserved (for count or sizeof) */
+};
+
+struct section_64 { /* for 64-bit architectures */
+ char sectname[16]; /* name of this section */
+ char segname[16]; /* segment this section goes in */
+ uint64_t addr; /* memory address of this section */
+ uint64_t size; /* size in bytes of this section */
+ uint32_t offset; /* file offset of this section */
+ uint32_t align; /* section alignment (power of 2) */
+ uint32_t reloff; /* file offset of relocation entries */
+ uint32_t nreloc; /* number of relocation entries */
+ uint32_t flags; /* flags (section type and attributes)*/
+ uint32_t reserved1; /* reserved (for offset or index) */
+ uint32_t reserved2; /* reserved (for count or sizeof) */
+ uint32_t reserved3; /* reserved */
+};
+
+/*
+ * The flags field of a section structure is separated into two parts a section
+ * type and section attributes. The section types are mutually exclusive (it
+ * can only have one type) but the section attributes are not (it may have more
+ * than one attribute).
+ */
+#define SECTION_TYPE 0x000000ff /* 256 section types */
+#define SECTION_ATTRIBUTES 0xffffff00 /* 24 section attributes */
+
+/* Constants for the type of a section */
+#define S_REGULAR 0x0 /* regular section */
+#define S_ZEROFILL 0x1 /* zero fill on demand section */
+#define S_CSTRING_LITERALS 0x2 /* section with only literal C strings*/
+#define S_4BYTE_LITERALS 0x3 /* section with only 4 byte literals */
+#define S_8BYTE_LITERALS 0x4 /* section with only 8 byte literals */
+#define S_LITERAL_POINTERS 0x5 /* section with only pointers to */
+ /* literals */
+/*
+ * For the two types of symbol pointers sections and the symbol stubs section
+ * they have indirect symbol table entries. For each of the entries in the
+ * section the indirect symbol table entries, in corresponding order in the
+ * indirect symbol table, start at the index stored in the reserved1 field
+ * of the section structure. Since the indirect symbol table entries
+ * correspond to the entries in the section the number of indirect symbol table
+ * entries is inferred from the size of the section divided by the size of the
+ * entries in the section. For symbol pointers sections the size of the entries
+ * in the section is 4 bytes and for symbol stubs sections the byte size of the
+ * stubs is stored in the reserved2 field of the section structure.
+ */
+#define S_NON_LAZY_SYMBOL_POINTERS 0x6 /* section with only non-lazy
+ symbol pointers */
+#define S_LAZY_SYMBOL_POINTERS 0x7 /* section with only lazy symbol
+ pointers */
+#define S_SYMBOL_STUBS 0x8 /* section with only symbol
+ stubs, byte size of stub in
+ the reserved2 field */
+#define S_MOD_INIT_FUNC_POINTERS 0x9 /* section with only function
+ pointers for initialization*/
+#define S_MOD_TERM_FUNC_POINTERS 0xa /* section with only function
+ pointers for termination */
+#define S_COALESCED 0xb /* section contains symbols that
+ are to be coalesced */
+#define S_GB_ZEROFILL 0xc /* zero fill on demand section
+ (that can be larger than 4
+ gigabytes) */
+#define S_INTERPOSING 0xd /* section with only pairs of
+ function pointers for
+ interposing */
+#define S_16BYTE_LITERALS 0xe /* section with only 16 byte
+ literals */
+#define S_DTRACE_DOF 0xf /* section contains
+ DTrace Object Format */
+#define S_LAZY_DYLIB_SYMBOL_POINTERS 0x10 /* section with only lazy
+ symbol pointers to lazy
+ loaded dylibs */
+/*
+ * Section types to support thread local variables
+ */
+#define S_THREAD_LOCAL_REGULAR 0x11 /* template of initial
+ values for TLVs */
+#define S_THREAD_LOCAL_ZEROFILL 0x12 /* template of initial
+ values for TLVs */
+#define S_THREAD_LOCAL_VARIABLES 0x13 /* TLV descriptors */
+#define S_THREAD_LOCAL_VARIABLE_POINTERS 0x14 /* pointers to TLV
+ descriptors */
+#define S_THREAD_LOCAL_INIT_FUNCTION_POINTERS 0x15 /* functions to call
+ to initialize TLV
+ values */
+
+/*
+ * Constants for the section attributes part of the flags field of a section
+ * structure.
+ */
+#define SECTION_ATTRIBUTES_USR 0xff000000 /* User setable attributes */
+#define S_ATTR_PURE_INSTRUCTIONS 0x80000000 /* section contains only true
+ machine instructions */
+#define S_ATTR_NO_TOC 0x40000000 /* section contains coalesced
+ symbols that are not to be
+ in a ranlib table of
+ contents */
+#define S_ATTR_STRIP_STATIC_SYMS 0x20000000 /* ok to strip static symbols
+ in this section in files
+ with the MH_DYLDLINK flag */
+#define S_ATTR_NO_DEAD_STRIP 0x10000000 /* no dead stripping */
+#define S_ATTR_LIVE_SUPPORT 0x08000000 /* blocks are live if they
+ reference live blocks */
+#define S_ATTR_SELF_MODIFYING_CODE 0x04000000 /* Used with i386 code stubs
+ written on by dyld */
+/*
+ * If a segment contains any sections marked with S_ATTR_DEBUG then all
+ * sections in that segment must have this attribute. No section other than
+ * a section marked with this attribute may reference the contents of this
+ * section. A section with this attribute may contain no symbols and must have
+ * a section type S_REGULAR. The static linker will not copy section contents
+ * from sections with this attribute into its output file. These sections
+ * generally contain DWARF debugging info.
+ */
+#define S_ATTR_DEBUG 0x02000000 /* a debug section */
+#define SECTION_ATTRIBUTES_SYS 0x00ffff00 /* system setable attributes */
+#define S_ATTR_SOME_INSTRUCTIONS 0x00000400 /* section contains some
+ machine instructions */
+#define S_ATTR_EXT_RELOC 0x00000200 /* section has external
+ relocation entries */
+#define S_ATTR_LOC_RELOC 0x00000100 /* section has local
+ relocation entries */
+
+
+/*
+ * The names of segments and sections in them are mostly meaningless to the
+ * link-editor. But there are few things to support traditional UNIX
+ * executables that require the link-editor and assembler to use some names
+ * agreed upon by convention.
+ *
+ * The initial protection of the "__TEXT" segment has write protection turned
+ * off (not writeable).
+ *
+ * The link-editor will allocate common symbols at the end of the "__common"
+ * section in the "__DATA" segment. It will create the section and segment
+ * if needed.
+ */
+
+/* The currently known segment names and the section names in those segments */
+
+#define SEG_PAGEZERO "__PAGEZERO" /* the pagezero segment which has no */
+ /* protections and catches NULL */
+ /* references for MH_EXECUTE files */
+
+
+#define SEG_TEXT "__TEXT" /* the tradition UNIX text segment */
+#define SECT_TEXT "__text" /* the real text part of the text */
+ /* section no headers, and no padding */
+#define SECT_FVMLIB_INIT0 "__fvmlib_init0" /* the fvmlib initialization */
+ /* section */
+#define SECT_FVMLIB_INIT1 "__fvmlib_init1" /* the section following the */
+ /* fvmlib initialization */
+ /* section */
+
+#define SEG_DATA "__DATA" /* the tradition UNIX data segment */
+#define SECT_DATA "__data" /* the real initialized data section */
+ /* no padding, no bss overlap */
+#define SECT_BSS "__bss" /* the real uninitialized data section*/
+ /* no padding */
+#define SECT_COMMON "__common" /* the section common symbols are */
+ /* allocated in by the link editor */
+
+#define SEG_OBJC "__OBJC" /* objective-C runtime segment */
+#define SECT_OBJC_SYMBOLS "__symbol_table" /* symbol table */
+#define SECT_OBJC_MODULES "__module_info" /* module information */
+#define SECT_OBJC_STRINGS "__selector_strs" /* string table */
+#define SECT_OBJC_REFS "__selector_refs" /* string table */
+
+#define SEG_ICON "__ICON" /* the icon segment */
+#define SECT_ICON_HEADER "__header" /* the icon headers */
+#define SECT_ICON_TIFF "__tiff" /* the icons in tiff format */
+
+#define SEG_LINKEDIT "__LINKEDIT" /* the segment containing all structs */
+ /* created and maintained by the link */
+ /* editor. Created with -seglinkedit */
+ /* option to ld(1) for MH_EXECUTE and */
+ /* FVMLIB file types only */
+
+#define SEG_UNIXSTACK "__UNIXSTACK" /* the unix stack segment */
+
+#define SEG_IMPORT "__IMPORT" /* the segment for the self (dyld) */
+ /* modifing code stubs that has read, */
+ /* write and execute permissions */
+
+/*
+ * Fixed virtual memory shared libraries are identified by two things. The
+ * target pathname (the name of the library as found for execution), and the
+ * minor version number. The address of where the headers are loaded is in
+ * header_addr. (THIS IS OBSOLETE and no longer supported).
+ */
+struct fvmlib {
+ union lc_str name; /* library's target pathname */
+ uint32_t minor_version; /* library's minor version number */
+ uint32_t header_addr; /* library's header address */
+};
+
+/*
+ * A fixed virtual shared library (filetype == MH_FVMLIB in the mach header)
+ * contains a fvmlib_command (cmd == LC_IDFVMLIB) to identify the library.
+ * An object that uses a fixed virtual shared library also contains a
+ * fvmlib_command (cmd == LC_LOADFVMLIB) for each library it uses.
+ * (THIS IS OBSOLETE and no longer supported).
+ */
+struct fvmlib_command {
+ uint32_t cmd; /* LC_IDFVMLIB or LC_LOADFVMLIB */
+ uint32_t cmdsize; /* includes pathname string */
+ struct fvmlib fvmlib; /* the library identification */
+};
+
+/*
+ * Dynamicly linked shared libraries are identified by two things. The
+ * pathname (the name of the library as found for execution), and the
+ * compatibility version number. The pathname must match and the compatibility
+ * number in the user of the library must be greater than or equal to the
+ * library being used. The time stamp is used to record the time a library was
+ * built and copied into user so it can be use to determined if the library used
+ * at runtime is exactly the same as used to built the program.
+ */
+struct dylib {
+ union lc_str name; /* library's path name */
+ uint32_t timestamp; /* library's build time stamp */
+ uint32_t current_version; /* library's current version number */
+ uint32_t compatibility_version; /* library's compatibility vers number*/
+};
+
+/*
+ * A dynamically linked shared library (filetype == MH_DYLIB in the mach header)
+ * contains a dylib_command (cmd == LC_ID_DYLIB) to identify the library.
+ * An object that uses a dynamically linked shared library also contains a
+ * dylib_command (cmd == LC_LOAD_DYLIB, LC_LOAD_WEAK_DYLIB, or
+ * LC_REEXPORT_DYLIB) for each library it uses.
+ */
+struct dylib_command {
+ uint32_t cmd; /* LC_ID_DYLIB, LC_LOAD_{,WEAK_}DYLIB,
+ LC_REEXPORT_DYLIB */
+ uint32_t cmdsize; /* includes pathname string */
+ struct dylib dylib; /* the library identification */
+};
+
+/*
+ * A dynamically linked shared library may be a subframework of an umbrella
+ * framework. If so it will be linked with "-umbrella umbrella_name" where
+ * Where "umbrella_name" is the name of the umbrella framework. A subframework
+ * can only be linked against by its umbrella framework or other subframeworks
+ * that are part of the same umbrella framework. Otherwise the static link
+ * editor produces an error and states to link against the umbrella framework.
+ * The name of the umbrella framework for subframeworks is recorded in the
+ * following structure.
+ */
+struct sub_framework_command {
+ uint32_t cmd; /* LC_SUB_FRAMEWORK */
+ uint32_t cmdsize; /* includes umbrella string */
+ union lc_str umbrella; /* the umbrella framework name */
+};
+
+/*
+ * For dynamically linked shared libraries that are subframework of an umbrella
+ * framework they can allow clients other than the umbrella framework or other
+ * subframeworks in the same umbrella framework. To do this the subframework
+ * is built with "-allowable_client client_name" and an LC_SUB_CLIENT load
+ * command is created for each -allowable_client flag. The client_name is
+ * usually a framework name. It can also be a name used for bundles clients
+ * where the bundle is built with "-client_name client_name".
+ */
+struct sub_client_command {
+ uint32_t cmd; /* LC_SUB_CLIENT */
+ uint32_t cmdsize; /* includes client string */
+ union lc_str client; /* the client name */
+};
+
+/*
+ * A dynamically linked shared library may be a sub_umbrella of an umbrella
+ * framework. If so it will be linked with "-sub_umbrella umbrella_name" where
+ * Where "umbrella_name" is the name of the sub_umbrella framework. When
+ * staticly linking when -twolevel_namespace is in effect a twolevel namespace
+ * umbrella framework will only cause its subframeworks and those frameworks
+ * listed as sub_umbrella frameworks to be implicited linked in. Any other
+ * dependent dynamic libraries will not be linked it when -twolevel_namespace
+ * is in effect. The primary library recorded by the static linker when
+ * resolving a symbol in these libraries will be the umbrella framework.
+ * Zero or more sub_umbrella frameworks may be use by an umbrella framework.
+ * The name of a sub_umbrella framework is recorded in the following structure.
+ */
+struct sub_umbrella_command {
+ uint32_t cmd; /* LC_SUB_UMBRELLA */
+ uint32_t cmdsize; /* includes sub_umbrella string */
+ union lc_str sub_umbrella; /* the sub_umbrella framework name */
+};
+
+/*
+ * A dynamically linked shared library may be a sub_library of another shared
+ * library. If so it will be linked with "-sub_library library_name" where
+ * Where "library_name" is the name of the sub_library shared library. When
+ * staticly linking when -twolevel_namespace is in effect a twolevel namespace
+ * shared library will only cause its subframeworks and those frameworks
+ * listed as sub_umbrella frameworks and libraries listed as sub_libraries to
+ * be implicited linked in. Any other dependent dynamic libraries will not be
+ * linked it when -twolevel_namespace is in effect. The primary library
+ * recorded by the static linker when resolving a symbol in these libraries
+ * will be the umbrella framework (or dynamic library). Zero or more sub_library
+ * shared libraries may be use by an umbrella framework or (or dynamic library).
+ * The name of a sub_library framework is recorded in the following structure.
+ * For example /usr/lib/libobjc_profile.A.dylib would be recorded as "libobjc".
+ */
+struct sub_library_command {
+ uint32_t cmd; /* LC_SUB_LIBRARY */
+ uint32_t cmdsize; /* includes sub_library string */
+ union lc_str sub_library; /* the sub_library name */
+};
+
+/*
+ * A program (filetype == MH_EXECUTE) that is
+ * prebound to its dynamic libraries has one of these for each library that
+ * the static linker used in prebinding. It contains a bit vector for the
+ * modules in the library. The bits indicate which modules are bound (1) and
+ * which are not (0) from the library. The bit for module 0 is the low bit
+ * of the first byte. So the bit for the Nth module is:
+ * (linked_modules[N/8] >> N%8) & 1
+ */
+struct prebound_dylib_command {
+ uint32_t cmd; /* LC_PREBOUND_DYLIB */
+ uint32_t cmdsize; /* includes strings */
+ union lc_str name; /* library's path name */
+ uint32_t nmodules; /* number of modules in library */
+ union lc_str linked_modules; /* bit vector of linked modules */
+};
+
+/*
+ * A program that uses a dynamic linker contains a dylinker_command to identify
+ * the name of the dynamic linker (LC_LOAD_DYLINKER). And a dynamic linker
+ * contains a dylinker_command to identify the dynamic linker (LC_ID_DYLINKER).
+ * A file can have at most one of these.
+ * This struct is also used for the LC_DYLD_ENVIRONMENT load command and
+ * contains string for dyld to treat like environment variable.
+ */
+struct dylinker_command {
+ uint32_t cmd; /* LC_ID_DYLINKER, LC_LOAD_DYLINKER or
+ LC_DYLD_ENVIRONMENT */
+ uint32_t cmdsize; /* includes pathname string */
+ union lc_str name; /* dynamic linker's path name */
+};
+
+/*
+ * Thread commands contain machine-specific data structures suitable for
+ * use in the thread state primitives. The machine specific data structures
+ * follow the struct thread_command as follows.
+ * Each flavor of machine specific data structure is preceded by an unsigned
+ * long constant for the flavor of that data structure, an uint32_t
+ * that is the count of longs of the size of the state data structure and then
+ * the state data structure follows. This triple may be repeated for many
+ * flavors. The constants for the flavors, counts and state data structure
+ * definitions are expected to be in the header file <machine/thread_status.h>.
+ * These machine specific data structures sizes must be multiples of
+ * 4 bytes The cmdsize reflects the total size of the thread_command
+ * and all of the sizes of the constants for the flavors, counts and state
+ * data structures.
+ *
+ * For executable objects that are unix processes there will be one
+ * thread_command (cmd == LC_UNIXTHREAD) created for it by the link-editor.
+ * This is the same as a LC_THREAD, except that a stack is automatically
+ * created (based on the shell's limit for the stack size). Command arguments
+ * and environment variables are copied onto that stack.
+ */
+struct thread_command {
+ uint32_t cmd; /* LC_THREAD or LC_UNIXTHREAD */
+ uint32_t cmdsize; /* total size of this command */
+ /* uint32_t flavor flavor of thread state */
+ /* uint32_t count count of longs in thread state */
+ /* struct XXX_thread_state state thread state for this flavor */
+ /* ... */
+};
+
+/*
+ * The routines command contains the address of the dynamic shared library
+ * initialization routine and an index into the module table for the module
+ * that defines the routine. Before any modules are used from the library the
+ * dynamic linker fully binds the module that defines the initialization routine
+ * and then calls it. This gets called before any module initialization
+ * routines (used for C++ static constructors) in the library.
+ */
+struct routines_command { /* for 32-bit architectures */
+ uint32_t cmd; /* LC_ROUTINES */
+ uint32_t cmdsize; /* total size of this command */
+ uint32_t init_address; /* address of initialization routine */
+ uint32_t init_module; /* index into the module table that */
+ /* the init routine is defined in */
+ uint32_t reserved1;
+ uint32_t reserved2;
+ uint32_t reserved3;
+ uint32_t reserved4;
+ uint32_t reserved5;
+ uint32_t reserved6;
+};
+
+/*
+ * The 64-bit routines command. Same use as above.
+ */
+struct routines_command_64 { /* for 64-bit architectures */
+ uint32_t cmd; /* LC_ROUTINES_64 */
+ uint32_t cmdsize; /* total size of this command */
+ uint64_t init_address; /* address of initialization routine */
+ uint64_t init_module; /* index into the module table that */
+ /* the init routine is defined in */
+ uint64_t reserved1;
+ uint64_t reserved2;
+ uint64_t reserved3;
+ uint64_t reserved4;
+ uint64_t reserved5;
+ uint64_t reserved6;
+};
+
+/*
+ * The symtab_command contains the offsets and sizes of the link-edit 4.3BSD
+ * "stab" style symbol table information as described in the header files
+ * <nlist.h> and <stab.h>.
+ */
+struct symtab_command {
+ uint32_t cmd; /* LC_SYMTAB */
+ uint32_t cmdsize; /* sizeof(struct symtab_command) */
+ uint32_t symoff; /* symbol table offset */
+ uint32_t nsyms; /* number of symbol table entries */
+ uint32_t stroff; /* string table offset */
+ uint32_t strsize; /* string table size in bytes */
+};
+
+/*
+ * This is the second set of the symbolic information which is used to support
+ * the data structures for the dynamically link editor.
+ *
+ * The original set of symbolic information in the symtab_command which contains
+ * the symbol and string tables must also be present when this load command is
+ * present. When this load command is present the symbol table is organized
+ * into three groups of symbols:
+ * local symbols (static and debugging symbols) - grouped by module
+ * defined external symbols - grouped by module (sorted by name if not lib)
+ * undefined external symbols (sorted by name if MH_BINDATLOAD is not set,
+ * and in order the were seen by the static
+ * linker if MH_BINDATLOAD is set)
+ * In this load command there are offsets and counts to each of the three groups
+ * of symbols.
+ *
+ * This load command contains a the offsets and sizes of the following new
+ * symbolic information tables:
+ * table of contents
+ * module table
+ * reference symbol table
+ * indirect symbol table
+ * The first three tables above (the table of contents, module table and
+ * reference symbol table) are only present if the file is a dynamically linked
+ * shared library. For executable and object modules, which are files
+ * containing only one module, the information that would be in these three
+ * tables is determined as follows:
+ * table of contents - the defined external symbols are sorted by name
+ * module table - the file contains only one module so everything in the
+ * file is part of the module.
+ * reference symbol table - is the defined and undefined external symbols
+ *
+ * For dynamically linked shared library files this load command also contains
+ * offsets and sizes to the pool of relocation entries for all sections
+ * separated into two groups:
+ * external relocation entries
+ * local relocation entries
+ * For executable and object modules the relocation entries continue to hang
+ * off the section structures.
+ */
+struct dysymtab_command {
+ uint32_t cmd; /* LC_DYSYMTAB */
+ uint32_t cmdsize; /* sizeof(struct dysymtab_command) */
+
+ /*
+ * The symbols indicated by symoff and nsyms of the LC_SYMTAB load command
+ * are grouped into the following three groups:
+ * local symbols (further grouped by the module they are from)
+ * defined external symbols (further grouped by the module they are from)
+ * undefined symbols
+ *
+ * The local symbols are used only for debugging. The dynamic binding
+ * process may have to use them to indicate to the debugger the local
+ * symbols for a module that is being bound.
+ *
+ * The last two groups are used by the dynamic binding process to do the
+ * binding (indirectly through the module table and the reference symbol
+ * table when this is a dynamically linked shared library file).
+ */
+ uint32_t ilocalsym; /* index to local symbols */
+ uint32_t nlocalsym; /* number of local symbols */
+
+ uint32_t iextdefsym;/* index to externally defined symbols */
+ uint32_t nextdefsym;/* number of externally defined symbols */
+
+ uint32_t iundefsym; /* index to undefined symbols */
+ uint32_t nundefsym; /* number of undefined symbols */
+
+ /*
+ * For the for the dynamic binding process to find which module a symbol
+ * is defined in the table of contents is used (analogous to the ranlib
+ * structure in an archive) which maps defined external symbols to modules
+ * they are defined in. This exists only in a dynamically linked shared
+ * library file. For executable and object modules the defined external
+ * symbols are sorted by name and is use as the table of contents.
+ */
+ uint32_t tocoff; /* file offset to table of contents */
+ uint32_t ntoc; /* number of entries in table of contents */
+
+ /*
+ * To support dynamic binding of "modules" (whole object files) the symbol
+ * table must reflect the modules that the file was created from. This is
+ * done by having a module table that has indexes and counts into the merged
+ * tables for each module. The module structure that these two entries
+ * refer to is described below. This exists only in a dynamically linked
+ * shared library file. For executable and object modules the file only
+ * contains one module so everything in the file belongs to the module.
+ */
+ uint32_t modtaboff; /* file offset to module table */
+ uint32_t nmodtab; /* number of module table entries */
+
+ /*
+ * To support dynamic module binding the module structure for each module
+ * indicates the external references (defined and undefined) each module
+ * makes. For each module there is an offset and a count into the
+ * reference symbol table for the symbols that the module references.
+ * This exists only in a dynamically linked shared library file. For
+ * executable and object modules the defined external symbols and the
+ * undefined external symbols indicates the external references.
+ */
+ uint32_t extrefsymoff; /* offset to referenced symbol table */
+ uint32_t nextrefsyms; /* number of referenced symbol table entries */
+
+ /*
+ * The sections that contain "symbol pointers" and "routine stubs" have
+ * indexes and (implied counts based on the size of the section and fixed
+ * size of the entry) into the "indirect symbol" table for each pointer
+ * and stub. For every section of these two types the index into the
+ * indirect symbol table is stored in the section header in the field
+ * reserved1. An indirect symbol table entry is simply a 32bit index into
+ * the symbol table to the symbol that the pointer or stub is referring to.
+ * The indirect symbol table is ordered to match the entries in the section.
+ */
+ uint32_t indirectsymoff; /* file offset to the indirect symbol table */
+ uint32_t nindirectsyms; /* number of indirect symbol table entries */
+
+ /*
+ * To support relocating an individual module in a library file quickly the
+ * external relocation entries for each module in the library need to be
+ * accessed efficiently. Since the relocation entries can't be accessed
+ * through the section headers for a library file they are separated into
+ * groups of local and external entries further grouped by module. In this
+ * case the presents of this load command who's extreloff, nextrel,
+ * locreloff and nlocrel fields are non-zero indicates that the relocation
+ * entries of non-merged sections are not referenced through the section
+ * structures (and the reloff and nreloc fields in the section headers are
+ * set to zero).
+ *
+ * Since the relocation entries are not accessed through the section headers
+ * this requires the r_address field to be something other than a section
+ * offset to identify the item to be relocated. In this case r_address is
+ * set to the offset from the vmaddr of the first LC_SEGMENT command.
+ * For MH_SPLIT_SEGS images r_address is set to the the offset from the
+ * vmaddr of the first read-write LC_SEGMENT command.
+ *
+ * The relocation entries are grouped by module and the module table
+ * entries have indexes and counts into them for the group of external
+ * relocation entries for that the module.
+ *
+ * For sections that are merged across modules there must not be any
+ * remaining external relocation entries for them (for merged sections
+ * remaining relocation entries must be local).
+ */
+ uint32_t extreloff; /* offset to external relocation entries */
+ uint32_t nextrel; /* number of external relocation entries */
+
+ /*
+ * All the local relocation entries are grouped together (they are not
+ * grouped by their module since they are only used if the object is moved
+ * from it staticly link edited address).
+ */
+ uint32_t locreloff; /* offset to local relocation entries */
+ uint32_t nlocrel; /* number of local relocation entries */
+
+};
+
+/*
+ * An indirect symbol table entry is simply a 32bit index into the symbol table
+ * to the symbol that the pointer or stub is refering to. Unless it is for a
+ * non-lazy symbol pointer section for a defined symbol which strip(1) as
+ * removed. In which case it has the value INDIRECT_SYMBOL_LOCAL. If the
+ * symbol was also absolute INDIRECT_SYMBOL_ABS is or'ed with that.
+ */
+#define INDIRECT_SYMBOL_LOCAL 0x80000000
+#define INDIRECT_SYMBOL_ABS 0x40000000
+
+
+/* a table of contents entry */
+struct dylib_table_of_contents {
+ uint32_t symbol_index; /* the defined external symbol
+ (index into the symbol table) */
+ uint32_t module_index; /* index into the module table this symbol
+ is defined in */
+};
+
+/* a module table entry */
+struct dylib_module {
+ uint32_t module_name; /* the module name (index into string table) */
+
+ uint32_t iextdefsym; /* index into externally defined symbols */
+ uint32_t nextdefsym; /* number of externally defined symbols */
+ uint32_t irefsym; /* index into reference symbol table */
+ uint32_t nrefsym; /* number of reference symbol table entries */
+ uint32_t ilocalsym; /* index into symbols for local symbols */
+ uint32_t nlocalsym; /* number of local symbols */
+
+ uint32_t iextrel; /* index into external relocation entries */
+ uint32_t nextrel; /* number of external relocation entries */
+
+ uint32_t iinit_iterm; /* low 16 bits are the index into the init
+ section, high 16 bits are the index into
+ the term section */
+ uint32_t ninit_nterm; /* low 16 bits are the number of init section
+ entries, high 16 bits are the number of
+ term section entries */
+
+ uint32_t /* for this module address of the start of */
+ objc_module_info_addr; /* the (__OBJC,__module_info) section */
+ uint32_t /* for this module size of */
+ objc_module_info_size; /* the (__OBJC,__module_info) section */
+};
+
+/* a 64-bit module table entry */
+struct dylib_module_64 {
+ uint32_t module_name; /* the module name (index into string table) */
+
+ uint32_t iextdefsym; /* index into externally defined symbols */
+ uint32_t nextdefsym; /* number of externally defined symbols */
+ uint32_t irefsym; /* index into reference symbol table */
+ uint32_t nrefsym; /* number of reference symbol table entries */
+ uint32_t ilocalsym; /* index into symbols for local symbols */
+ uint32_t nlocalsym; /* number of local symbols */
+
+ uint32_t iextrel; /* index into external relocation entries */
+ uint32_t nextrel; /* number of external relocation entries */
+
+ uint32_t iinit_iterm; /* low 16 bits are the index into the init
+ section, high 16 bits are the index into
+ the term section */
+ uint32_t ninit_nterm; /* low 16 bits are the number of init section
+ entries, high 16 bits are the number of
+ term section entries */
+
+ uint32_t /* for this module size of */
+ objc_module_info_size; /* the (__OBJC,__module_info) section */
+ uint64_t /* for this module address of the start of */
+ objc_module_info_addr; /* the (__OBJC,__module_info) section */
+};
+
+/*
+ * The entries in the reference symbol table are used when loading the module
+ * (both by the static and dynamic link editors) and if the module is unloaded
+ * or replaced. Therefore all external symbols (defined and undefined) are
+ * listed in the module's reference table. The flags describe the type of
+ * reference that is being made. The constants for the flags are defined in
+ * <mach-o/nlist.h> as they are also used for symbol table entries.
+ */
+struct dylib_reference {
+ uint32_t isym:24, /* index into the symbol table */
+ flags:8; /* flags to indicate the type of reference */
+};
+
+/*
+ * The twolevel_hints_command contains the offset and number of hints in the
+ * two-level namespace lookup hints table.
+ */
+struct twolevel_hints_command {
+ uint32_t cmd; /* LC_TWOLEVEL_HINTS */
+ uint32_t cmdsize; /* sizeof(struct twolevel_hints_command) */
+ uint32_t offset; /* offset to the hint table */
+ uint32_t nhints; /* number of hints in the hint table */
+};
+
+/*
+ * The entries in the two-level namespace lookup hints table are twolevel_hint
+ * structs. These provide hints to the dynamic link editor where to start
+ * looking for an undefined symbol in a two-level namespace image. The
+ * isub_image field is an index into the sub-images (sub-frameworks and
+ * sub-umbrellas list) that made up the two-level image that the undefined
+ * symbol was found in when it was built by the static link editor. If
+ * isub-image is 0 the the symbol is expected to be defined in library and not
+ * in the sub-images. If isub-image is non-zero it is an index into the array
+ * of sub-images for the umbrella with the first index in the sub-images being
+ * 1. The array of sub-images is the ordered list of sub-images of the umbrella
+ * that would be searched for a symbol that has the umbrella recorded as its
+ * primary library. The table of contents index is an index into the
+ * library's table of contents. This is used as the starting point of the
+ * binary search or a directed linear search.
+ */
+struct twolevel_hint {
+ uint32_t
+ isub_image:8, /* index into the sub images */
+ itoc:24; /* index into the table of contents */
+};
+
+/*
+ * The prebind_cksum_command contains the value of the original check sum for
+ * prebound files or zero. When a prebound file is first created or modified
+ * for other than updating its prebinding information the value of the check sum
+ * is set to zero. When the file has it prebinding re-done and if the value of
+ * the check sum is zero the original check sum is calculated and stored in
+ * cksum field of this load command in the output file. If when the prebinding
+ * is re-done and the cksum field is non-zero it is left unchanged from the
+ * input file.
+ */
+struct prebind_cksum_command {
+ uint32_t cmd; /* LC_PREBIND_CKSUM */
+ uint32_t cmdsize; /* sizeof(struct prebind_cksum_command) */
+ uint32_t cksum; /* the check sum or zero */
+};
+
+/*
+ * The uuid load command contains a single 128-bit unique random number that
+ * identifies an object produced by the static link editor.
+ */
+struct uuid_command {
+ uint32_t cmd; /* LC_UUID */
+ uint32_t cmdsize; /* sizeof(struct uuid_command) */
+ uint8_t uuid[16]; /* the 128-bit uuid */
+};
+
+/*
+ * The rpath_command contains a path which at runtime should be added to
+ * the current run path used to find @rpath prefixed dylibs.
+ */
+struct rpath_command {
+ uint32_t cmd; /* LC_RPATH */
+ uint32_t cmdsize; /* includes string */
+ union lc_str path; /* path to add to run path */
+};
+
+/*
+ * The linkedit_data_command contains the offsets and sizes of a blob
+ * of data in the __LINKEDIT segment.
+ */
+struct linkedit_data_command {
+ uint32_t cmd; /* LC_CODE_SIGNATURE, LC_SEGMENT_SPLIT_INFO,
+ or LC_FUNCTION_STARTS */
+ uint32_t cmdsize; /* sizeof(struct linkedit_data_command) */
+ uint32_t dataoff; /* file offset of data in __LINKEDIT segment */
+ uint32_t datasize; /* file size of data in __LINKEDIT segment */
+};
+
+/*
+ * The encryption_info_command contains the file offset and size of an
+ * of an encrypted segment.
+ */
+struct encryption_info_command {
+ uint32_t cmd; /* LC_ENCRYPTION_INFO */
+ uint32_t cmdsize; /* sizeof(struct encryption_info_command) */
+ uint32_t cryptoff; /* file offset of encrypted range */
+ uint32_t cryptsize; /* file size of encrypted range */
+ uint32_t cryptid; /* which enryption system,
+ 0 means not-encrypted yet */
+};
+
+/*
+ * The version_min_command contains the min OS version on which this
+ * binary was built to run.
+ */
+struct version_min_command {
+ uint32_t cmd; /* LC_VERSION_MIN_MACOSX or
+ LC_VERSION_MIN_IPHONEOS */
+ uint32_t cmdsize; /* sizeof(struct min_version_command) */
+ uint32_t version; /* X.Y.Z is encoded in nibbles xxxx.yy.zz */
+ uint32_t reserved; /* zero */
+};
+
+/*
+ * The dyld_info_command contains the file offsets and sizes of
+ * the new compressed form of the information dyld needs to
+ * load the image. This information is used by dyld on Mac OS X
+ * 10.6 and later. All information pointed to by this command
+ * is encoded using byte streams, so no endian swapping is needed
+ * to interpret it.
+ */
+struct dyld_info_command {
+ uint32_t cmd; /* LC_DYLD_INFO or LC_DYLD_INFO_ONLY */
+ uint32_t cmdsize; /* sizeof(struct dyld_info_command) */
+
+ /*
+ * Dyld rebases an image whenever dyld loads it at an address different
+ * from its preferred address. The rebase information is a stream
+ * of byte sized opcodes whose symbolic names start with REBASE_OPCODE_.
+ * Conceptually the rebase information is a table of tuples:
+ * <seg-index, seg-offset, type>
+ * The opcodes are a compressed way to encode the table by only
+ * encoding when a column changes. In addition simple patterns
+ * like "every n'th offset for m times" can be encoded in a few
+ * bytes.
+ */
+ uint32_t rebase_off; /* file offset to rebase info */
+ uint32_t rebase_size; /* size of rebase info */
+
+ /*
+ * Dyld binds an image during the loading process, if the image
+ * requires any pointers to be initialized to symbols in other images.
+ * The bind information is a stream of byte sized
+ * opcodes whose symbolic names start with BIND_OPCODE_.
+ * Conceptually the bind information is a table of tuples:
+ * <seg-index, seg-offset, type, symbol-library-ordinal, symbol-name, addend>
+ * The opcodes are a compressed way to encode the table by only
+ * encoding when a column changes. In addition simple patterns
+ * like for runs of pointers initialzed to the same value can be
+ * encoded in a few bytes.
+ */
+ uint32_t bind_off; /* file offset to binding info */
+ uint32_t bind_size; /* size of binding info */
+
+ /*
+ * Some C++ programs require dyld to unique symbols so that all
+ * images in the process use the same copy of some code/data.
+ * This step is done after binding. The content of the weak_bind
+ * info is an opcode stream like the bind_info. But it is sorted
+ * alphabetically by symbol name. This enable dyld to walk
+ * all images with weak binding information in order and look
+ * for collisions. If there are no collisions, dyld does
+ * no updating. That means that some fixups are also encoded
+ * in the bind_info. For instance, all calls to "operator new"
+ * are first bound to libstdc++.dylib using the information
+ * in bind_info. Then if some image overrides operator new
+ * that is detected when the weak_bind information is processed
+ * and the call to operator new is then rebound.
+ */
+ uint32_t weak_bind_off; /* file offset to weak binding info */
+ uint32_t weak_bind_size; /* size of weak binding info */
+
+ /*
+ * Some uses of external symbols do not need to be bound immediately.
+ * Instead they can be lazily bound on first use. The lazy_bind
+ * are contains a stream of BIND opcodes to bind all lazy symbols.
+ * Normal use is that dyld ignores the lazy_bind section when
+ * loading an image. Instead the static linker arranged for the
+ * lazy pointer to initially point to a helper function which
+ * pushes the offset into the lazy_bind area for the symbol
+ * needing to be bound, then jumps to dyld which simply adds
+ * the offset to lazy_bind_off to get the information on what
+ * to bind.
+ */
+ uint32_t lazy_bind_off; /* file offset to lazy binding info */
+ uint32_t lazy_bind_size; /* size of lazy binding infs */
+
+ /*
+ * The symbols exported by a dylib are encoded in a trie. This
+ * is a compact representation that factors out common prefixes.
+ * It also reduces LINKEDIT pages in RAM because it encodes all
+ * information (name, address, flags) in one small, contiguous range.
+ * The export area is a stream of nodes. The first node sequentially
+ * is the start node for the trie.
+ *
+ * Nodes for a symbol start with a uleb128 that is the length of
+ * the exported symbol information for the string so far.
+ * If there is no exported symbol, the node starts with a zero byte.
+ * If there is exported info, it follows the length. First is
+ * a uleb128 containing flags. Normally, it is followed by a
+ * uleb128 encoded offset which is location of the content named
+ * by the symbol from the mach_header for the image. If the flags
+ * is EXPORT_SYMBOL_FLAGS_REEXPORT, then following the flags is
+ * a uleb128 encoded library ordinal, then a zero terminated
+ * UTF8 string. If the string is zero length, then the symbol
+ * is re-export from the specified dylib with the same name.
+ *
+ * After the optional exported symbol information is a byte of
+ * how many edges (0-255) that this node has leaving it,
+ * followed by each edge.
+ * Each edge is a zero terminated UTF8 of the addition chars
+ * in the symbol, followed by a uleb128 offset for the node that
+ * edge points to.
+ *
+ */
+ uint32_t export_off; /* file offset to lazy binding info */
+ uint32_t export_size; /* size of lazy binding infs */
+};
+
+/*
+ * The following are used to encode rebasing information
+ */
+#define REBASE_TYPE_POINTER 1
+#define REBASE_TYPE_TEXT_ABSOLUTE32 2
+#define REBASE_TYPE_TEXT_PCREL32 3
+
+#define REBASE_OPCODE_MASK 0xF0
+#define REBASE_IMMEDIATE_MASK 0x0F
+#define REBASE_OPCODE_DONE 0x00
+#define REBASE_OPCODE_SET_TYPE_IMM 0x10
+#define REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB 0x20
+#define REBASE_OPCODE_ADD_ADDR_ULEB 0x30
+#define REBASE_OPCODE_ADD_ADDR_IMM_SCALED 0x40
+#define REBASE_OPCODE_DO_REBASE_IMM_TIMES 0x50
+#define REBASE_OPCODE_DO_REBASE_ULEB_TIMES 0x60
+#define REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB 0x70
+#define REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB 0x80
+
+
+/*
+ * The following are used to encode binding information
+ */
+#define BIND_TYPE_POINTER 1
+#define BIND_TYPE_TEXT_ABSOLUTE32 2
+#define BIND_TYPE_TEXT_PCREL32 3
+
+#define BIND_SPECIAL_DYLIB_SELF 0
+#define BIND_SPECIAL_DYLIB_MAIN_EXECUTABLE -1
+#define BIND_SPECIAL_DYLIB_FLAT_LOOKUP -2
+
+#define BIND_SYMBOL_FLAGS_WEAK_IMPORT 0x1
+#define BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION 0x8
+
+#define BIND_OPCODE_MASK 0xF0
+#define BIND_IMMEDIATE_MASK 0x0F
+#define BIND_OPCODE_DONE 0x00
+#define BIND_OPCODE_SET_DYLIB_ORDINAL_IMM 0x10
+#define BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB 0x20
+#define BIND_OPCODE_SET_DYLIB_SPECIAL_IMM 0x30
+#define BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM 0x40
+#define BIND_OPCODE_SET_TYPE_IMM 0x50
+#define BIND_OPCODE_SET_ADDEND_SLEB 0x60
+#define BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB 0x70
+#define BIND_OPCODE_ADD_ADDR_ULEB 0x80
+#define BIND_OPCODE_DO_BIND 0x90
+#define BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB 0xA0
+#define BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED 0xB0
+#define BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB 0xC0
+
+
+/*
+ * The following are used on the flags byte of a terminal node
+ * in the export information.
+ */
+#define EXPORT_SYMBOL_FLAGS_KIND_MASK 0x03
+#define EXPORT_SYMBOL_FLAGS_KIND_REGULAR 0x00
+#define EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL 0x01
+#define EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION 0x04
+#define EXPORT_SYMBOL_FLAGS_REEXPORT 0x08
+#define EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER 0x10
+
+/*
+ * The symseg_command contains the offset and size of the GNU style
+ * symbol table information as described in the header file <symseg.h>.
+ * The symbol roots of the symbol segments must also be aligned properly
+ * in the file. So the requirement of keeping the offsets aligned to a
+ * multiple of a 4 bytes translates to the length field of the symbol
+ * roots also being a multiple of a long. Also the padding must again be
+ * zeroed. (THIS IS OBSOLETE and no longer supported).
+ */
+struct symseg_command {
+ uint32_t cmd; /* LC_SYMSEG */
+ uint32_t cmdsize; /* sizeof(struct symseg_command) */
+ uint32_t offset; /* symbol segment offset */
+ uint32_t size; /* symbol segment size in bytes */
+};
+
+/*
+ * The ident_command contains a free format string table following the
+ * ident_command structure. The strings are null terminated and the size of
+ * the command is padded out with zero bytes to a multiple of 4 bytes/
+ * (THIS IS OBSOLETE and no longer supported).
+ */
+struct ident_command {
+ uint32_t cmd; /* LC_IDENT */
+ uint32_t cmdsize; /* strings that follow this command */
+};
+
+/*
+ * The fvmfile_command contains a reference to a file to be loaded at the
+ * specified virtual address. (Presently, this command is reserved for
+ * internal use. The kernel ignores this command when loading a program into
+ * memory).
+ */
+struct fvmfile_command {
+ uint32_t cmd; /* LC_FVMFILE */
+ uint32_t cmdsize; /* includes pathname string */
+ union lc_str name; /* files pathname */
+ uint32_t header_addr; /* files virtual address */
+};
+
+/*
+ * Sections of type S_THREAD_LOCAL_VARIABLES contain an array
+ * of tlv_descriptor structures.
+ */
+struct tlv_descriptor
+{
+ void* (*thunk)(struct tlv_descriptor*);
+ unsigned long key;
+ unsigned long offset;
+};
+
+#endif /* _MACHO_LOADER_H_ */
diff --git a/toolkit/crashreporter/google-breakpad/src/third_party/mac_headers/mach-o/nlist.h b/toolkit/crashreporter/google-breakpad/src/third_party/mac_headers/mach-o/nlist.h
new file mode 100644
index 0000000000..1c1941012e
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/third_party/mac_headers/mach-o/nlist.h
@@ -0,0 +1,312 @@
+/*
+ * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+#ifndef _MACHO_NLIST_H_
+#define _MACHO_NLIST_H_
+/* $NetBSD: nlist.h,v 1.5 1994/10/26 00:56:11 cgd Exp $ */
+
+/*-
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ * (c) UNIX System Laboratories, Inc.
+ * All or some portions of this file are derived from material licensed
+ * to the University of California by American Telephone and Telegraph
+ * Co. or Unix System Laboratories, Inc. and are reproduced herein with
+ * the permission of UNIX System Laboratories, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)nlist.h 8.2 (Berkeley) 1/21/94
+ */
+#include <stdint.h>
+
+/*
+ * Format of a symbol table entry of a Mach-O file for 32-bit architectures.
+ * Modified from the BSD format. The modifications from the original format
+ * were changing n_other (an unused field) to n_sect and the addition of the
+ * N_SECT type. These modifications are required to support symbols in a larger
+ * number of sections not just the three sections (text, data and bss) in a BSD
+ * file.
+ */
+struct nlist {
+ union {
+#ifndef __LP64__
+ char *n_name; /* for use when in-core */
+#endif
+ int32_t n_strx; /* index into the string table */
+ } n_un;
+ uint8_t n_type; /* type flag, see below */
+ uint8_t n_sect; /* section number or NO_SECT */
+ int16_t n_desc; /* see <mach-o/stab.h> */
+ uint32_t n_value; /* value of this symbol (or stab offset) */
+};
+
+/*
+ * This is the symbol table entry structure for 64-bit architectures.
+ */
+struct nlist_64 {
+ union {
+ uint32_t n_strx; /* index into the string table */
+ } n_un;
+ uint8_t n_type; /* type flag, see below */
+ uint8_t n_sect; /* section number or NO_SECT */
+ uint16_t n_desc; /* see <mach-o/stab.h> */
+ uint64_t n_value; /* value of this symbol (or stab offset) */
+};
+
+/*
+ * Symbols with a index into the string table of zero (n_un.n_strx == 0) are
+ * defined to have a null, "", name. Therefore all string indexes to non null
+ * names must not have a zero string index. This is bit historical information
+ * that has never been well documented.
+ */
+
+/*
+ * The n_type field really contains four fields:
+ * unsigned char N_STAB:3,
+ * N_PEXT:1,
+ * N_TYPE:3,
+ * N_EXT:1;
+ * which are used via the following masks.
+ */
+#define N_STAB 0xe0 /* if any of these bits set, a symbolic debugging entry */
+#define N_PEXT 0x10 /* private external symbol bit */
+#define N_TYPE 0x0e /* mask for the type bits */
+#define N_EXT 0x01 /* external symbol bit, set for external symbols */
+
+/*
+ * Only symbolic debugging entries have some of the N_STAB bits set and if any
+ * of these bits are set then it is a symbolic debugging entry (a stab). In
+ * which case then the values of the n_type field (the entire field) are given
+ * in <mach-o/stab.h>
+ */
+
+/*
+ * Values for N_TYPE bits of the n_type field.
+ */
+#define N_UNDF 0x0 /* undefined, n_sect == NO_SECT */
+#define N_ABS 0x2 /* absolute, n_sect == NO_SECT */
+#define N_SECT 0xe /* defined in section number n_sect */
+#define N_PBUD 0xc /* prebound undefined (defined in a dylib) */
+#define N_INDR 0xa /* indirect */
+
+/*
+ * If the type is N_INDR then the symbol is defined to be the same as another
+ * symbol. In this case the n_value field is an index into the string table
+ * of the other symbol's name. When the other symbol is defined then they both
+ * take on the defined type and value.
+ */
+
+/*
+ * If the type is N_SECT then the n_sect field contains an ordinal of the
+ * section the symbol is defined in. The sections are numbered from 1 and
+ * refer to sections in order they appear in the load commands for the file
+ * they are in. This means the same ordinal may very well refer to different
+ * sections in different files.
+ *
+ * The n_value field for all symbol table entries (including N_STAB's) gets
+ * updated by the link editor based on the value of it's n_sect field and where
+ * the section n_sect references gets relocated. If the value of the n_sect
+ * field is NO_SECT then it's n_value field is not changed by the link editor.
+ */
+#define NO_SECT 0 /* symbol is not in any section */
+#define MAX_SECT 255 /* 1 thru 255 inclusive */
+
+/*
+ * Common symbols are represented by undefined (N_UNDF) external (N_EXT) types
+ * who's values (n_value) are non-zero. In which case the value of the n_value
+ * field is the size (in bytes) of the common symbol. The n_sect field is set
+ * to NO_SECT. The alignment of a common symbol may be set as a power of 2
+ * between 2^1 and 2^15 as part of the n_desc field using the macros below. If
+ * the alignment is not set (a value of zero) then natural alignment based on
+ * the size is used.
+ */
+#define GET_COMM_ALIGN(n_desc) (((n_desc) >> 8) & 0x0f)
+#define SET_COMM_ALIGN(n_desc,align) \
+ (n_desc) = (((n_desc) & 0xf0ff) | (((align) & 0x0f) << 8))
+
+/*
+ * To support the lazy binding of undefined symbols in the dynamic link-editor,
+ * the undefined symbols in the symbol table (the nlist structures) are marked
+ * with the indication if the undefined reference is a lazy reference or
+ * non-lazy reference. If both a non-lazy reference and a lazy reference is
+ * made to the same symbol the non-lazy reference takes precedence. A reference
+ * is lazy only when all references to that symbol are made through a symbol
+ * pointer in a lazy symbol pointer section.
+ *
+ * The implementation of marking nlist structures in the symbol table for
+ * undefined symbols will be to use some of the bits of the n_desc field as a
+ * reference type. The mask REFERENCE_TYPE will be applied to the n_desc field
+ * of an nlist structure for an undefined symbol to determine the type of
+ * undefined reference (lazy or non-lazy).
+ *
+ * The constants for the REFERENCE FLAGS are propagated to the reference table
+ * in a shared library file. In that case the constant for a defined symbol,
+ * REFERENCE_FLAG_DEFINED, is also used.
+ */
+/* Reference type bits of the n_desc field of undefined symbols */
+#define REFERENCE_TYPE 0x7
+/* types of references */
+#define REFERENCE_FLAG_UNDEFINED_NON_LAZY 0
+#define REFERENCE_FLAG_UNDEFINED_LAZY 1
+#define REFERENCE_FLAG_DEFINED 2
+#define REFERENCE_FLAG_PRIVATE_DEFINED 3
+#define REFERENCE_FLAG_PRIVATE_UNDEFINED_NON_LAZY 4
+#define REFERENCE_FLAG_PRIVATE_UNDEFINED_LAZY 5
+
+/*
+ * To simplify stripping of objects that use are used with the dynamic link
+ * editor, the static link editor marks the symbols defined an object that are
+ * referenced by a dynamicly bound object (dynamic shared libraries, bundles).
+ * With this marking strip knows not to strip these symbols.
+ */
+#define REFERENCED_DYNAMICALLY 0x0010
+
+/*
+ * For images created by the static link editor with the -twolevel_namespace
+ * option in effect the flags field of the mach header is marked with
+ * MH_TWOLEVEL. And the binding of the undefined references of the image are
+ * determined by the static link editor. Which library an undefined symbol is
+ * bound to is recorded by the static linker in the high 8 bits of the n_desc
+ * field using the SET_LIBRARY_ORDINAL macro below. The ordinal recorded
+ * references the libraries listed in the Mach-O's LC_LOAD_DYLIB,
+ * LC_LOAD_WEAK_DYLIB, LC_REEXPORT_DYLIB, LC_LOAD_UPWARD_DYLIB, and
+ * LC_LAZY_LOAD_DYLIB, etc. load commands in the order they appear in the
+ * headers. The library ordinals start from 1.
+ * For a dynamic library that is built as a two-level namespace image the
+ * undefined references from module defined in another use the same nlist struct
+ * an in that case SELF_LIBRARY_ORDINAL is used as the library ordinal. For
+ * defined symbols in all images they also must have the library ordinal set to
+ * SELF_LIBRARY_ORDINAL. The EXECUTABLE_ORDINAL refers to the executable
+ * image for references from plugins that refer to the executable that loads
+ * them.
+ *
+ * The DYNAMIC_LOOKUP_ORDINAL is for undefined symbols in a two-level namespace
+ * image that are looked up by the dynamic linker with flat namespace semantics.
+ * This ordinal was added as a feature in Mac OS X 10.3 by reducing the
+ * value of MAX_LIBRARY_ORDINAL by one. So it is legal for existing binaries
+ * or binaries built with older tools to have 0xfe (254) dynamic libraries. In
+ * this case the ordinal value 0xfe (254) must be treated as a library ordinal
+ * for compatibility.
+ */
+#define GET_LIBRARY_ORDINAL(n_desc) (((n_desc) >> 8) & 0xff)
+#define SET_LIBRARY_ORDINAL(n_desc,ordinal) \
+ (n_desc) = (((n_desc) & 0x00ff) | (((ordinal) & 0xff) << 8))
+#define SELF_LIBRARY_ORDINAL 0x0
+#define MAX_LIBRARY_ORDINAL 0xfd
+#define DYNAMIC_LOOKUP_ORDINAL 0xfe
+#define EXECUTABLE_ORDINAL 0xff
+
+/*
+ * The bit 0x0020 of the n_desc field is used for two non-overlapping purposes
+ * and has two different symbolic names, N_NO_DEAD_STRIP and N_DESC_DISCARDED.
+ */
+
+/*
+ * The N_NO_DEAD_STRIP bit of the n_desc field only ever appears in a
+ * relocatable .o file (MH_OBJECT filetype). And is used to indicate to the
+ * static link editor it is never to dead strip the symbol.
+ */
+#define N_NO_DEAD_STRIP 0x0020 /* symbol is not to be dead stripped */
+
+/*
+ * The N_DESC_DISCARDED bit of the n_desc field never appears in linked image.
+ * But is used in very rare cases by the dynamic link editor to mark an in
+ * memory symbol as discared and longer used for linking.
+ */
+#define N_DESC_DISCARDED 0x0020 /* symbol is discarded */
+
+/*
+ * The N_WEAK_REF bit of the n_desc field indicates to the dynamic linker that
+ * the undefined symbol is allowed to be missing and is to have the address of
+ * zero when missing.
+ */
+#define N_WEAK_REF 0x0040 /* symbol is weak referenced */
+
+/*
+ * The N_WEAK_DEF bit of the n_desc field indicates to the static and dynamic
+ * linkers that the symbol definition is weak, allowing a non-weak symbol to
+ * also be used which causes the weak definition to be discared. Currently this
+ * is only supported for symbols in coalesed sections.
+ */
+#define N_WEAK_DEF 0x0080 /* coalesed symbol is a weak definition */
+
+/*
+ * The N_REF_TO_WEAK bit of the n_desc field indicates to the dynamic linker
+ * that the undefined symbol should be resolved using flat namespace searching.
+ */
+#define N_REF_TO_WEAK 0x0080 /* reference to a weak symbol */
+
+/*
+ * The N_ARM_THUMB_DEF bit of the n_desc field indicates that the symbol is
+ * a defintion of a Thumb function.
+ */
+#define N_ARM_THUMB_DEF 0x0008 /* symbol is a Thumb function (ARM) */
+
+/*
+ * The N_SYMBOL_RESOLVER bit of the n_desc field indicates that the
+ * that the function is actually a resolver function and should
+ * be called to get the address of the real function to use.
+ * This bit is only available in .o files (MH_OBJECT filetype)
+ */
+#define N_SYMBOL_RESOLVER 0x0100
+
+#ifndef __STRICT_BSD__
+#if __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+/*
+ * The function nlist(3) from the C library.
+ */
+extern int nlist (const char *filename, struct nlist *list);
+#if __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* __STRICT_BSD__ */
+
+#endif /* _MACHO_LIST_H_ */
diff --git a/toolkit/crashreporter/google-breakpad/src/third_party/mac_headers/mach/boolean.h b/toolkit/crashreporter/google-breakpad/src/third_party/mac_headers/mach/boolean.h
new file mode 100644
index 0000000000..641c3962d9
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/third_party/mac_headers/mach/boolean.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ *
+ * Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
+ */
+/*
+ * @OSF_COPYRIGHT@
+ */
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ */
+/*
+ * File: mach/boolean.h
+ *
+ * Boolean data type.
+ *
+ */
+
+#ifndef _MACH_BOOLEAN_H_
+#define _MACH_BOOLEAN_H_
+
+/*
+ * Pick up "boolean_t" type definition
+ */
+
+#ifndef ASSEMBLER
+#include <mach/machine/boolean.h>
+#endif /* ASSEMBLER */
+
+/*
+ * Define TRUE and FALSE if not defined.
+ */
+
+#ifndef TRUE
+#define TRUE 1
+#endif /* TRUE */
+
+#ifndef FALSE
+#define FALSE 0
+#endif /* FALSE */
+
+#endif /* _MACH_BOOLEAN_H_ */
diff --git a/toolkit/crashreporter/google-breakpad/src/third_party/mac_headers/mach/i386/boolean.h b/toolkit/crashreporter/google-breakpad/src/third_party/mac_headers/mach/i386/boolean.h
new file mode 100644
index 0000000000..100f7e7b51
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/third_party/mac_headers/mach/i386/boolean.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2000-2006 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ *
+ * Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
+ */
+/*
+ * @OSF_COPYRIGHT@
+ */
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990,1989 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ */
+
+/*
+ * File: boolean.h
+ *
+ * Boolean type, for I386.
+ */
+
+#ifndef _MACH_I386_BOOLEAN_H_
+#define _MACH_I386_BOOLEAN_H_
+
+#if defined(__x86_64__) && !defined(KERNEL)
+typedef unsigned int boolean_t;
+#else
+typedef int boolean_t;
+#endif
+
+#endif /* _MACH_I386_BOOLEAN_H_ */
diff --git a/toolkit/crashreporter/google-breakpad/src/third_party/mac_headers/mach/i386/vm_param.h b/toolkit/crashreporter/google-breakpad/src/third_party/mac_headers/mach/i386/vm_param.h
new file mode 100644
index 0000000000..edcb83496b
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/third_party/mac_headers/mach/i386/vm_param.h
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 2000-2006 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ *
+ * Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
+ */
+/*
+ * @OSF_COPYRIGHT@
+ */
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990,1989,1988 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+
+/*
+ * Copyright (c) 1994 The University of Utah and
+ * the Computer Systems Laboratory at the University of Utah (CSL).
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify and distribute this software is hereby
+ * granted provided that (1) source code retains these copyright, permission,
+ * and disclaimer notices, and (2) redistributions including binaries
+ * reproduce the notices in supporting documentation, and (3) all advertising
+ * materials mentioning features or use of this software display the following
+ * acknowledgement: ``This product includes software developed by the
+ * Computer Systems Laboratory at the University of Utah.''
+ *
+ * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS
+ * IS" CONDITION. THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF
+ * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * CSL requests users of this software to return to csl-dist@cs.utah.edu any
+ * improvements that they make and grant CSL redistribution rights.
+ *
+ */
+
+/*
+ * File: vm_param.h
+ * Author: Avadis Tevanian, Jr.
+ * Date: 1985
+ *
+ * I386 machine dependent virtual memory parameters.
+ * Most of the declarations are preceeded by I386_ (or i386_)
+ * which is OK because only I386 specific code will be using
+ * them.
+ */
+
+#ifndef _MACH_I386_VM_PARAM_H_
+#define _MACH_I386_VM_PARAM_H_
+
+#define BYTE_SIZE 8 /* byte size in bits */
+
+#define I386_PGBYTES 4096 /* bytes per 80386 page */
+#define I386_PGSHIFT 12 /* bitshift for pages */
+
+#define PAGE_SIZE I386_PGBYTES
+#define PAGE_SHIFT I386_PGSHIFT
+#define PAGE_MASK (PAGE_SIZE - 1)
+
+#define I386_LPGBYTES 2*1024*1024 /* bytes per large page */
+#define I386_LPGSHIFT 21 /* bitshift for large pages */
+#define I386_LPGMASK (I386_LPGBYTES-1)
+
+/*
+ * Convert bytes to pages and convert pages to bytes.
+ * No rounding is used.
+ */
+
+#define i386_btop(x) ((ppnum_t)((x) >> I386_PGSHIFT))
+#define machine_btop(x) i386_btop(x)
+#define i386_ptob(x) (((pmap_paddr_t)(x)) << I386_PGSHIFT)
+
+/*
+ * Round off or truncate to the nearest page. These will work
+ * for either addresses or counts. (i.e. 1 byte rounds to 1 page
+ * bytes.
+ */
+
+#define i386_round_page(x) ((((pmap_paddr_t)(x)) + I386_PGBYTES - 1) & \
+ ~(I386_PGBYTES-1))
+#define i386_trunc_page(x) (((pmap_paddr_t)(x)) & ~(I386_PGBYTES-1))
+
+
+
+#define VM_MIN_ADDRESS64 ((user_addr_t) 0x0000000000000000ULL)
+/*
+ * default top of user stack... it grows down from here
+ */
+#define VM_USRSTACK64 ((user_addr_t) 0x00007FFF5FC00000ULL)
+#define VM_DYLD64 ((user_addr_t) 0x00007FFF5FC00000ULL)
+#define VM_LIB64_SHR_DATA ((user_addr_t) 0x00007FFF60000000ULL)
+#define VM_LIB64_SHR_TEXT ((user_addr_t) 0x00007FFF80000000ULL)
+/*
+ * the end of the usable user address space , for now about 47 bits.
+ * the 64 bit commpage is past the end of this
+ */
+#define VM_MAX_PAGE_ADDRESS ((user_addr_t) 0x00007FFFFFE00000ULL)
+/*
+ * canonical end of user address space for limits checking
+ */
+#define VM_MAX_USER_PAGE_ADDRESS ((user_addr_t)0x00007FFFFFFFF000ULL)
+
+
+/* system-wide values */
+#define MACH_VM_MIN_ADDRESS ((mach_vm_offset_t) 0)
+#define MACH_VM_MAX_ADDRESS ((mach_vm_offset_t) VM_MAX_PAGE_ADDRESS)
+
+/* process-relative values (all 32-bit legacy only for now) */
+#define VM_MIN_ADDRESS ((vm_offset_t) 0)
+#define VM_USRSTACK32 ((vm_offset_t) 0xC0000000)
+#define VM_MAX_ADDRESS ((vm_offset_t) 0xFFE00000)
+
+
+
+#endif /* _MACH_I386_VM_PARAM_H_ */
diff --git a/toolkit/crashreporter/google-breakpad/src/third_party/mac_headers/mach/i386/vm_types.h b/toolkit/crashreporter/google-breakpad/src/third_party/mac_headers/mach/i386/vm_types.h
new file mode 100644
index 0000000000..2c38fa2d70
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/third_party/mac_headers/mach/i386/vm_types.h
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2000-2006 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ *
+ * Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
+ */
+/*
+ * @OSF_COPYRIGHT@
+ */
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990,1989,1988 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ */
+
+/*
+ * File: vm_types.h
+ * Author: Avadis Tevanian, Jr.
+ * Date: 1985
+ *
+ * Header file for VM data types. I386 version.
+ */
+
+#ifndef _MACH_I386_VM_TYPES_H_
+#define _MACH_I386_VM_TYPES_H_
+
+#ifndef ASSEMBLER
+
+#include <i386/_types.h>
+#include <mach/i386/vm_param.h>
+#include <stdint.h>
+
+/*
+ * natural_t and integer_t are Mach's legacy types for machine-
+ * independent integer types (unsigned, and signed, respectively).
+ * Their original purpose was to define other types in a machine/
+ * compiler independent way.
+ *
+ * They also had an implicit "same size as pointer" characteristic
+ * to them (i.e. Mach's traditional types are very ILP32 or ILP64
+ * centric). We support x86 ABIs that do not follow either of
+ * these models (specifically LP64). Therefore, we had to make a
+ * choice between making these types scale with pointers or stay
+ * tied to integers. Because their use is predominantly tied to
+ * to the size of an integer, we are keeping that association and
+ * breaking free from pointer size guarantees.
+ *
+ * New use of these types is discouraged.
+ */
+typedef __darwin_natural_t natural_t;
+typedef int integer_t;
+
+/*
+ * A vm_offset_t is a type-neutral pointer,
+ * e.g. an offset into a virtual memory space.
+ */
+#ifdef __LP64__
+typedef uintptr_t vm_offset_t;
+#else /* __LP64__ */
+typedef natural_t vm_offset_t;
+#endif /* __LP64__ */
+
+/*
+ * A vm_size_t is the proper type for e.g.
+ * expressing the difference between two
+ * vm_offset_t entities.
+ */
+#ifdef __LP64__
+typedef uintptr_t vm_size_t;
+#else /* __LP64__ */
+typedef natural_t vm_size_t;
+#endif /* __LP64__ */
+
+/*
+ * This new type is independent of a particular vm map's
+ * implementation size - and represents appropriate types
+ * for all possible maps. This is used for interfaces
+ * where the size of the map is not known - or we don't
+ * want to have to distinguish.
+ */
+typedef uint64_t mach_vm_address_t;
+typedef uint64_t mach_vm_offset_t;
+typedef uint64_t mach_vm_size_t;
+
+typedef uint64_t vm_map_offset_t;
+typedef uint64_t vm_map_address_t;
+typedef uint64_t vm_map_size_t;
+
+
+#endif /* ASSEMBLER */
+
+/*
+ * If composing messages by hand (please do not)
+ */
+#define MACH_MSG_TYPE_INTEGER_T MACH_MSG_TYPE_INTEGER_32
+
+#endif /* _MACH_I386_VM_TYPES_H_ */
diff --git a/toolkit/crashreporter/google-breakpad/src/third_party/mac_headers/mach/machine.h b/toolkit/crashreporter/google-breakpad/src/third_party/mac_headers/mach/machine.h
new file mode 100644
index 0000000000..5bb21e48be
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/third_party/mac_headers/mach/machine.h
@@ -0,0 +1,347 @@
+/*
+ * Copyright (c) 2000-2007 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ *
+ * Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
+ */
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/* File: machine.h
+ * Author: Avadis Tevanian, Jr.
+ * Date: 1986
+ *
+ * Machine independent machine abstraction.
+ */
+
+#ifndef _MACH_MACHINE_H_
+#define _MACH_MACHINE_H_
+
+#include <stdint.h>
+#include <mach/machine/vm_types.h>
+#include <mach/boolean.h>
+
+typedef integer_t cpu_type_t;
+typedef integer_t cpu_subtype_t;
+typedef integer_t cpu_threadtype_t;
+
+#define CPU_STATE_MAX 4
+
+#define CPU_STATE_USER 0
+#define CPU_STATE_SYSTEM 1
+#define CPU_STATE_IDLE 2
+#define CPU_STATE_NICE 3
+
+
+
+/*
+ * Capability bits used in the definition of cpu_type.
+ */
+#define CPU_ARCH_MASK 0xff000000 /* mask for architecture bits */
+#define CPU_ARCH_ABI64 0x01000000 /* 64 bit ABI */
+
+/*
+ * Machine types known by all.
+ */
+
+#define CPU_TYPE_ANY ((cpu_type_t) -1)
+
+#define CPU_TYPE_VAX ((cpu_type_t) 1)
+/* skip ((cpu_type_t) 2) */
+/* skip ((cpu_type_t) 3) */
+/* skip ((cpu_type_t) 4) */
+/* skip ((cpu_type_t) 5) */
+#define CPU_TYPE_MC680x0 ((cpu_type_t) 6)
+#define CPU_TYPE_X86 ((cpu_type_t) 7)
+#define CPU_TYPE_I386 CPU_TYPE_X86 /* compatibility */
+#define CPU_TYPE_X86_64 (CPU_TYPE_X86 | CPU_ARCH_ABI64)
+
+/* skip CPU_TYPE_MIPS ((cpu_type_t) 8) */
+/* skip ((cpu_type_t) 9) */
+#define CPU_TYPE_MC98000 ((cpu_type_t) 10)
+#define CPU_TYPE_HPPA ((cpu_type_t) 11)
+#define CPU_TYPE_ARM ((cpu_type_t) 12)
+#define CPU_TYPE_MC88000 ((cpu_type_t) 13)
+#define CPU_TYPE_SPARC ((cpu_type_t) 14)
+#define CPU_TYPE_I860 ((cpu_type_t) 15)
+/* skip CPU_TYPE_ALPHA ((cpu_type_t) 16) */
+/* skip ((cpu_type_t) 17) */
+#define CPU_TYPE_POWERPC ((cpu_type_t) 18)
+#define CPU_TYPE_POWERPC64 (CPU_TYPE_POWERPC | CPU_ARCH_ABI64)
+
+/*
+ * Machine subtypes (these are defined here, instead of in a machine
+ * dependent directory, so that any program can get all definitions
+ * regardless of where is it compiled).
+ */
+
+/*
+ * Capability bits used in the definition of cpu_subtype.
+ */
+#define CPU_SUBTYPE_MASK 0xff000000 /* mask for feature flags */
+#define CPU_SUBTYPE_LIB64 0x80000000 /* 64 bit libraries */
+
+
+/*
+ * Object files that are hand-crafted to run on any
+ * implementation of an architecture are tagged with
+ * CPU_SUBTYPE_MULTIPLE. This functions essentially the same as
+ * the "ALL" subtype of an architecture except that it allows us
+ * to easily find object files that may need to be modified
+ * whenever a new implementation of an architecture comes out.
+ *
+ * It is the responsibility of the implementor to make sure the
+ * software handles unsupported implementations elegantly.
+ */
+#define CPU_SUBTYPE_MULTIPLE ((cpu_subtype_t) -1)
+#define CPU_SUBTYPE_LITTLE_ENDIAN ((cpu_subtype_t) 0)
+#define CPU_SUBTYPE_BIG_ENDIAN ((cpu_subtype_t) 1)
+
+/*
+ * Machine threadtypes.
+ * This is none - not defined - for most machine types/subtypes.
+ */
+#define CPU_THREADTYPE_NONE ((cpu_threadtype_t) 0)
+
+/*
+ * VAX subtypes (these do *not* necessary conform to the actual cpu
+ * ID assigned by DEC available via the SID register).
+ */
+
+#define CPU_SUBTYPE_VAX_ALL ((cpu_subtype_t) 0)
+#define CPU_SUBTYPE_VAX780 ((cpu_subtype_t) 1)
+#define CPU_SUBTYPE_VAX785 ((cpu_subtype_t) 2)
+#define CPU_SUBTYPE_VAX750 ((cpu_subtype_t) 3)
+#define CPU_SUBTYPE_VAX730 ((cpu_subtype_t) 4)
+#define CPU_SUBTYPE_UVAXI ((cpu_subtype_t) 5)
+#define CPU_SUBTYPE_UVAXII ((cpu_subtype_t) 6)
+#define CPU_SUBTYPE_VAX8200 ((cpu_subtype_t) 7)
+#define CPU_SUBTYPE_VAX8500 ((cpu_subtype_t) 8)
+#define CPU_SUBTYPE_VAX8600 ((cpu_subtype_t) 9)
+#define CPU_SUBTYPE_VAX8650 ((cpu_subtype_t) 10)
+#define CPU_SUBTYPE_VAX8800 ((cpu_subtype_t) 11)
+#define CPU_SUBTYPE_UVAXIII ((cpu_subtype_t) 12)
+
+/*
+ * 680x0 subtypes
+ *
+ * The subtype definitions here are unusual for historical reasons.
+ * NeXT used to consider 68030 code as generic 68000 code. For
+ * backwards compatability:
+ *
+ * CPU_SUBTYPE_MC68030 symbol has been preserved for source code
+ * compatability.
+ *
+ * CPU_SUBTYPE_MC680x0_ALL has been defined to be the same
+ * subtype as CPU_SUBTYPE_MC68030 for binary comatability.
+ *
+ * CPU_SUBTYPE_MC68030_ONLY has been added to allow new object
+ * files to be tagged as containing 68030-specific instructions.
+ */
+
+#define CPU_SUBTYPE_MC680x0_ALL ((cpu_subtype_t) 1)
+#define CPU_SUBTYPE_MC68030 ((cpu_subtype_t) 1) /* compat */
+#define CPU_SUBTYPE_MC68040 ((cpu_subtype_t) 2)
+#define CPU_SUBTYPE_MC68030_ONLY ((cpu_subtype_t) 3)
+
+/*
+ * I386 subtypes
+ */
+
+#define CPU_SUBTYPE_INTEL(f, m) ((cpu_subtype_t) (f) + ((m) << 4))
+
+#define CPU_SUBTYPE_I386_ALL CPU_SUBTYPE_INTEL(3, 0)
+#define CPU_SUBTYPE_386 CPU_SUBTYPE_INTEL(3, 0)
+#define CPU_SUBTYPE_486 CPU_SUBTYPE_INTEL(4, 0)
+#define CPU_SUBTYPE_486SX CPU_SUBTYPE_INTEL(4, 8) // 8 << 4 = 128
+#define CPU_SUBTYPE_586 CPU_SUBTYPE_INTEL(5, 0)
+#define CPU_SUBTYPE_PENT CPU_SUBTYPE_INTEL(5, 0)
+#define CPU_SUBTYPE_PENTPRO CPU_SUBTYPE_INTEL(6, 1)
+#define CPU_SUBTYPE_PENTII_M3 CPU_SUBTYPE_INTEL(6, 3)
+#define CPU_SUBTYPE_PENTII_M5 CPU_SUBTYPE_INTEL(6, 5)
+#define CPU_SUBTYPE_CELERON CPU_SUBTYPE_INTEL(7, 6)
+#define CPU_SUBTYPE_CELERON_MOBILE CPU_SUBTYPE_INTEL(7, 7)
+#define CPU_SUBTYPE_PENTIUM_3 CPU_SUBTYPE_INTEL(8, 0)
+#define CPU_SUBTYPE_PENTIUM_3_M CPU_SUBTYPE_INTEL(8, 1)
+#define CPU_SUBTYPE_PENTIUM_3_XEON CPU_SUBTYPE_INTEL(8, 2)
+#define CPU_SUBTYPE_PENTIUM_M CPU_SUBTYPE_INTEL(9, 0)
+#define CPU_SUBTYPE_PENTIUM_4 CPU_SUBTYPE_INTEL(10, 0)
+#define CPU_SUBTYPE_PENTIUM_4_M CPU_SUBTYPE_INTEL(10, 1)
+#define CPU_SUBTYPE_ITANIUM CPU_SUBTYPE_INTEL(11, 0)
+#define CPU_SUBTYPE_ITANIUM_2 CPU_SUBTYPE_INTEL(11, 1)
+#define CPU_SUBTYPE_XEON CPU_SUBTYPE_INTEL(12, 0)
+#define CPU_SUBTYPE_XEON_MP CPU_SUBTYPE_INTEL(12, 1)
+
+#define CPU_SUBTYPE_INTEL_FAMILY(x) ((x) & 15)
+#define CPU_SUBTYPE_INTEL_FAMILY_MAX 15
+
+#define CPU_SUBTYPE_INTEL_MODEL(x) ((x) >> 4)
+#define CPU_SUBTYPE_INTEL_MODEL_ALL 0
+
+/*
+ * X86 subtypes.
+ */
+
+#define CPU_SUBTYPE_X86_ALL ((cpu_subtype_t)3)
+#define CPU_SUBTYPE_X86_64_ALL ((cpu_subtype_t)3)
+#define CPU_SUBTYPE_X86_ARCH1 ((cpu_subtype_t)4)
+#define CPU_SUBTYPE_X86_64_H ((cpu_subtype_t)8) /* Haswell feature subset */
+
+
+#define CPU_THREADTYPE_INTEL_HTT ((cpu_threadtype_t) 1)
+
+/*
+ * Mips subtypes.
+ */
+
+#define CPU_SUBTYPE_MIPS_ALL ((cpu_subtype_t) 0)
+#define CPU_SUBTYPE_MIPS_R2300 ((cpu_subtype_t) 1)
+#define CPU_SUBTYPE_MIPS_R2600 ((cpu_subtype_t) 2)
+#define CPU_SUBTYPE_MIPS_R2800 ((cpu_subtype_t) 3)
+#define CPU_SUBTYPE_MIPS_R2000a ((cpu_subtype_t) 4) /* pmax */
+#define CPU_SUBTYPE_MIPS_R2000 ((cpu_subtype_t) 5)
+#define CPU_SUBTYPE_MIPS_R3000a ((cpu_subtype_t) 6) /* 3max */
+#define CPU_SUBTYPE_MIPS_R3000 ((cpu_subtype_t) 7)
+
+/*
+ * MC98000 (PowerPC) subtypes
+ */
+#define CPU_SUBTYPE_MC98000_ALL ((cpu_subtype_t) 0)
+#define CPU_SUBTYPE_MC98601 ((cpu_subtype_t) 1)
+
+/*
+ * HPPA subtypes for Hewlett-Packard HP-PA family of
+ * risc processors. Port by NeXT to 700 series.
+ */
+
+#define CPU_SUBTYPE_HPPA_ALL ((cpu_subtype_t) 0)
+#define CPU_SUBTYPE_HPPA_7100 ((cpu_subtype_t) 0) /* compat */
+#define CPU_SUBTYPE_HPPA_7100LC ((cpu_subtype_t) 1)
+
+/*
+ * MC88000 subtypes.
+ */
+#define CPU_SUBTYPE_MC88000_ALL ((cpu_subtype_t) 0)
+#define CPU_SUBTYPE_MC88100 ((cpu_subtype_t) 1)
+#define CPU_SUBTYPE_MC88110 ((cpu_subtype_t) 2)
+
+/*
+ * SPARC subtypes
+ */
+#define CPU_SUBTYPE_SPARC_ALL ((cpu_subtype_t) 0)
+
+/*
+ * I860 subtypes
+ */
+#define CPU_SUBTYPE_I860_ALL ((cpu_subtype_t) 0)
+#define CPU_SUBTYPE_I860_860 ((cpu_subtype_t) 1)
+
+/*
+ * PowerPC subtypes
+ */
+#define CPU_SUBTYPE_POWERPC_ALL ((cpu_subtype_t) 0)
+#define CPU_SUBTYPE_POWERPC_601 ((cpu_subtype_t) 1)
+#define CPU_SUBTYPE_POWERPC_602 ((cpu_subtype_t) 2)
+#define CPU_SUBTYPE_POWERPC_603 ((cpu_subtype_t) 3)
+#define CPU_SUBTYPE_POWERPC_603e ((cpu_subtype_t) 4)
+#define CPU_SUBTYPE_POWERPC_603ev ((cpu_subtype_t) 5)
+#define CPU_SUBTYPE_POWERPC_604 ((cpu_subtype_t) 6)
+#define CPU_SUBTYPE_POWERPC_604e ((cpu_subtype_t) 7)
+#define CPU_SUBTYPE_POWERPC_620 ((cpu_subtype_t) 8)
+#define CPU_SUBTYPE_POWERPC_750 ((cpu_subtype_t) 9)
+#define CPU_SUBTYPE_POWERPC_7400 ((cpu_subtype_t) 10)
+#define CPU_SUBTYPE_POWERPC_7450 ((cpu_subtype_t) 11)
+#define CPU_SUBTYPE_POWERPC_970 ((cpu_subtype_t) 100)
+
+/*
+ * ARM subtypes
+ */
+#define CPU_SUBTYPE_ARM_ALL ((cpu_subtype_t) 0)
+#define CPU_SUBTYPE_ARM_V4T ((cpu_subtype_t) 5)
+#define CPU_SUBTYPE_ARM_V6 ((cpu_subtype_t) 6)
+#define CPU_SUBTYPE_ARM_V5TEJ ((cpu_subtype_t) 7)
+#define CPU_SUBTYPE_ARM_XSCALE ((cpu_subtype_t) 8)
+#define CPU_SUBTYPE_ARM_V7 ((cpu_subtype_t) 9)
+
+/*
+ * CPU families (sysctl hw.cpufamily)
+ *
+ * These are meant to identify the CPU's marketing name - an
+ * application can map these to (possibly) localized strings.
+ * NB: the encodings of the CPU families are intentionally arbitrary.
+ * There is no ordering, and you should never try to deduce whether
+ * or not some feature is available based on the family.
+ * Use feature flags (eg, hw.optional.altivec) to test for optional
+ * functionality.
+ */
+#define CPUFAMILY_UNKNOWN 0
+#define CPUFAMILY_POWERPC_G3 0xcee41549
+#define CPUFAMILY_POWERPC_G4 0x77c184ae
+#define CPUFAMILY_POWERPC_G5 0xed76d8aa
+#define CPUFAMILY_INTEL_6_13 0xaa33392b
+#define CPUFAMILY_INTEL_YONAH 0x73d67300
+#define CPUFAMILY_INTEL_MEROM 0x426f69ef
+#define CPUFAMILY_INTEL_PENRYN 0x78ea4fbc
+#define CPUFAMILY_INTEL_NEHALEM 0x6b5a4cd2
+#define CPUFAMILY_INTEL_WESTMERE 0x573b5eec
+#define CPUFAMILY_INTEL_SANDYBRIDGE 0x5490b78c
+#define CPUFAMILY_ARM_9 0xe73283ae
+#define CPUFAMILY_ARM_11 0x8ff620d8
+#define CPUFAMILY_ARM_XSCALE 0x53b005f5
+#define CPUFAMILY_ARM_13 0x0cc90e64
+#define CPUFAMILY_ARM_14 0x96077ef1
+
+/* The following synonyms are deprecated: */
+#define CPUFAMILY_INTEL_6_14 CPUFAMILY_INTEL_YONAH
+#define CPUFAMILY_INTEL_6_15 CPUFAMILY_INTEL_MEROM
+#define CPUFAMILY_INTEL_6_23 CPUFAMILY_INTEL_PENRYN
+#define CPUFAMILY_INTEL_6_26 CPUFAMILY_INTEL_NEHALEM
+
+#define CPUFAMILY_INTEL_CORE CPUFAMILY_INTEL_YONAH
+#define CPUFAMILY_INTEL_CORE2 CPUFAMILY_INTEL_MEROM
+
+
+#endif /* _MACH_MACHINE_H_ */
diff --git a/toolkit/crashreporter/google-breakpad/src/third_party/mac_headers/mach/machine/boolean.h b/toolkit/crashreporter/google-breakpad/src/third_party/mac_headers/mach/machine/boolean.h
new file mode 100644
index 0000000000..ffdc2390a8
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/third_party/mac_headers/mach/machine/boolean.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2000-2007 Apple Inc. All rights reserved.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ *
+ * Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
+ */
+
+#ifndef _MACH_MACHINE_BOOLEAN_H_
+#define _MACH_MACHINE_BOOLEAN_H_
+
+#if defined (__i386__) || defined(__x86_64__)
+#include "mach/i386/boolean.h"
+#elif defined (__arm__)
+#include "mach/arm/boolean.h"
+#else
+#error architecture not supported
+#endif
+
+#endif /* _MACH_MACHINE_BOOLEAN_H_ */
diff --git a/toolkit/crashreporter/google-breakpad/src/third_party/mac_headers/mach/machine/thread_state.h b/toolkit/crashreporter/google-breakpad/src/third_party/mac_headers/mach/machine/thread_state.h
new file mode 100644
index 0000000000..1547acac76
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/third_party/mac_headers/mach/machine/thread_state.h
@@ -0,0 +1,9 @@
+/*
+ * This file is a stub with the bare minimum needed to make things work.
+ */
+#ifndef _MACH_MACHINE_THREAD_STATE_H_
+#define _MACH_MACHINE_THREAD_STATE_H_
+
+#define THREAD_STATE_MAX 1
+
+#endif /* _MACH_MACHINE_THREAD_STATE_H_ */
diff --git a/toolkit/crashreporter/google-breakpad/src/third_party/mac_headers/mach/machine/thread_status.h b/toolkit/crashreporter/google-breakpad/src/third_party/mac_headers/mach/machine/thread_status.h
new file mode 100644
index 0000000000..d1ab56ad58
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/third_party/mac_headers/mach/machine/thread_status.h
@@ -0,0 +1 @@
+/* This file intentionally left blank */
diff --git a/toolkit/crashreporter/google-breakpad/src/third_party/mac_headers/mach/machine/vm_types.h b/toolkit/crashreporter/google-breakpad/src/third_party/mac_headers/mach/machine/vm_types.h
new file mode 100644
index 0000000000..8ccd24be53
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/third_party/mac_headers/mach/machine/vm_types.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2000-2007 Apple Inc. All rights reserved.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ *
+ * Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
+ */
+
+#ifndef _MACH_MACHINE_VM_TYPES_H_
+#define _MACH_MACHINE_VM_TYPES_H_
+
+#if defined (__i386__) || defined(__x86_64__)
+#include "mach/i386/vm_types.h"
+#elif defined (__arm__)
+#include "mach/arm/vm_types.h"
+#else
+#error architecture not supported
+#endif
+
+#endif /* _MACH_MACHINE_VM_TYPES_H_ */
diff --git a/toolkit/crashreporter/google-breakpad/src/third_party/mac_headers/mach/thread_status.h b/toolkit/crashreporter/google-breakpad/src/third_party/mac_headers/mach/thread_status.h
new file mode 100644
index 0000000000..aead09bf97
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/third_party/mac_headers/mach/thread_status.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ *
+ * Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
+ */
+/*
+ * @OSF_COPYRIGHT@
+ */
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990,1989,1988 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ */
+/*
+ * File: mach/thread_status.h
+ * Author: Avadis Tevanian, Jr.
+ *
+ * This file contains the structure definitions for the user-visible
+ * thread state. This thread state is examined with the thread_get_state
+ * kernel call and may be changed with the thread_set_state kernel call.
+ *
+ */
+
+#ifndef _MACH_THREAD_STATUS_H_
+#define _MACH_THREAD_STATUS_H_
+
+/*
+ * The actual structure that comprises the thread state is defined
+ * in the machine dependent module.
+ */
+#include <mach/machine/vm_types.h>
+#include <mach/machine/thread_status.h>
+#include <mach/machine/thread_state.h>
+
+/*
+ * Generic definition for machine-dependent thread status.
+ */
+
+typedef natural_t *thread_state_t; /* Variable-length array */
+
+/* THREAD_STATE_MAX is now defined in <mach/machine/thread_state.h> */
+typedef natural_t thread_state_data_t[THREAD_STATE_MAX];
+
+#define THREAD_STATE_FLAVOR_LIST 0 /* List of valid flavors */
+#define THREAD_STATE_FLAVOR_LIST_NEW 128
+
+typedef int thread_state_flavor_t;
+typedef thread_state_flavor_t *thread_state_flavor_array_t;
+
+#endif /* _MACH_THREAD_STATUS_H_ */
diff --git a/toolkit/crashreporter/google-breakpad/src/third_party/mac_headers/mach/vm_prot.h b/toolkit/crashreporter/google-breakpad/src/third_party/mac_headers/mach/vm_prot.h
new file mode 100644
index 0000000000..07c2114e5c
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/third_party/mac_headers/mach/vm_prot.h
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ *
+ * Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
+ */
+/*
+ * @OSF_COPYRIGHT@
+ */
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ */
+/*
+ * File: mach/vm_prot.h
+ * Author: Avadis Tevanian, Jr., Michael Wayne Young
+ *
+ * Virtual memory protection definitions.
+ *
+ */
+
+#ifndef _MACH_VM_PROT_H_
+#define _MACH_VM_PROT_H_
+
+/*
+ * Types defined:
+ *
+ * vm_prot_t VM protection values.
+ */
+
+typedef int vm_prot_t;
+
+/*
+ * Protection values, defined as bits within the vm_prot_t type
+ */
+
+#define VM_PROT_NONE ((vm_prot_t) 0x00)
+
+#define VM_PROT_READ ((vm_prot_t) 0x01) /* read permission */
+#define VM_PROT_WRITE ((vm_prot_t) 0x02) /* write permission */
+#define VM_PROT_EXECUTE ((vm_prot_t) 0x04) /* execute permission */
+
+/*
+ * The default protection for newly-created virtual memory
+ */
+
+#define VM_PROT_DEFAULT (VM_PROT_READ|VM_PROT_WRITE)
+
+/*
+ * The maximum privileges possible, for parameter checking.
+ */
+
+#define VM_PROT_ALL (VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE)
+
+/*
+ * An invalid protection value.
+ * Used only by memory_object_lock_request to indicate no change
+ * to page locks. Using -1 here is a bad idea because it
+ * looks like VM_PROT_ALL and then some.
+ */
+
+#define VM_PROT_NO_CHANGE ((vm_prot_t) 0x08)
+
+/*
+ * When a caller finds that he cannot obtain write permission on a
+ * mapped entry, the following flag can be used. The entry will
+ * be made "needs copy" effectively copying the object (using COW),
+ * and write permission will be added to the maximum protections
+ * for the associated entry.
+ */
+
+#define VM_PROT_COPY ((vm_prot_t) 0x10)
+
+
+/*
+ * Another invalid protection value.
+ * Used only by memory_object_data_request upon an object
+ * which has specified a copy_call copy strategy. It is used
+ * when the kernel wants a page belonging to a copy of the
+ * object, and is only asking the object as a result of
+ * following a shadow chain. This solves the race between pages
+ * being pushed up by the memory manager and the kernel
+ * walking down the shadow chain.
+ */
+
+#define VM_PROT_WANTS_COPY ((vm_prot_t) 0x10)
+
+
+/*
+ * Another invalid protection value.
+ * Indicates that the other protection bits are to be applied as a mask
+ * against the actual protection bits of the map entry.
+ */
+#define VM_PROT_IS_MASK ((vm_prot_t) 0x40)
+
+#endif /* _MACH_VM_PROT_H_ */
diff --git a/toolkit/crashreporter/google-breakpad/src/third_party/musl/COPYRIGHT b/toolkit/crashreporter/google-breakpad/src/third_party/musl/COPYRIGHT
new file mode 100644
index 0000000000..f0ee3b78d8
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/third_party/musl/COPYRIGHT
@@ -0,0 +1,163 @@
+musl as a whole is licensed under the following standard MIT license:
+
+----------------------------------------------------------------------
+Copyright © 2005-2014 Rich Felker, et al.
+
+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.
+----------------------------------------------------------------------
+
+Authors/contributors include:
+
+Alex Dowad
+Alexander Monakov
+Anthony G. Basile
+Arvid Picciani
+Bobby Bingham
+Boris Brezillon
+Brent Cook
+Chris Spiegel
+Clément Vasseur
+Daniel Micay
+Denys Vlasenko
+Emil Renner Berthing
+Felix Fietkau
+Felix Janda
+Gianluca Anzolin
+Hauke Mehrtens
+Hiltjo Posthuma
+Isaac Dunham
+Jaydeep Patil
+Jens Gustedt
+Jeremy Huntwork
+Jo-Philipp Wich
+Joakim Sindholt
+John Spencer
+Josiah Worcester
+Justin Cormack
+Khem Raj
+Kylie McClain
+Luca Barbato
+Luka Perkov
+M Farkas-Dyck (Strake)
+Mahesh Bodapati
+Michael Forney
+Natanael Copa
+Nicholas J. Kain
+orc
+Pascal Cuoq
+Petr Hosek
+Pierre Carrier
+Rich Felker
+Richard Pennington
+Shiz
+sin
+Solar Designer
+Stefan Kristiansson
+Szabolcs Nagy
+Timo Teräs
+Trutz Behn
+Valentin Ochs
+William Haddon
+
+Portions of this software are derived from third-party works licensed
+under terms compatible with the above MIT license:
+
+The TRE regular expression implementation (src/regex/reg* and
+src/regex/tre*) is Copyright © 2001-2008 Ville Laurikari and licensed
+under a 2-clause BSD license (license text in the source files). The
+included version has been heavily modified by Rich Felker in 2012, in
+the interests of size, simplicity, and namespace cleanliness.
+
+Much of the math library code (src/math/* and src/complex/*) is
+Copyright © 1993,2004 Sun Microsystems or
+Copyright © 2003-2011 David Schultz or
+Copyright © 2003-2009 Steven G. Kargl or
+Copyright © 2003-2009 Bruce D. Evans or
+Copyright © 2008 Stephen L. Moshier
+and labelled as such in comments in the individual source files. All
+have been licensed under extremely permissive terms.
+
+The ARM memcpy code (src/string/arm/memcpy_el.S) is Copyright © 2008
+The Android Open Source Project and is licensed under a two-clause BSD
+license. It was taken from Bionic libc, used on Android.
+
+The implementation of DES for crypt (src/crypt/crypt_des.c) is
+Copyright © 1994 David Burren. It is licensed under a BSD license.
+
+The implementation of blowfish crypt (src/crypt/crypt_blowfish.c) was
+originally written by Solar Designer and placed into the public
+domain. The code also comes with a fallback permissive license for use
+in jurisdictions that may not recognize the public domain.
+
+The smoothsort implementation (src/stdlib/qsort.c) is Copyright © 2011
+Valentin Ochs and is licensed under an MIT-style license.
+
+The BSD PRNG implementation (src/prng/random.c) and XSI search API
+(src/search/*.c) functions are Copyright © 2011 Szabolcs Nagy and
+licensed under following terms: "Permission to use, copy, modify,
+and/or distribute this code for any purpose with or without fee is
+hereby granted. There is no warranty."
+
+The x86_64 port was written by Nicholas J. Kain and is licensed under
+the standard MIT terms.
+
+The mips and microblaze ports were originally written by Richard
+Pennington for use in the ellcc project. The original code was adapted
+by Rich Felker for build system and code conventions during upstream
+integration. It is licensed under the standard MIT terms.
+
+The mips64 port was contributed by Imagination Technologies and is
+licensed under the standard MIT terms.
+
+The powerpc port was also originally written by Richard Pennington,
+and later supplemented and integrated by John Spencer. It is licensed
+under the standard MIT terms.
+
+All other files which have no copyright comments are original works
+produced specifically for use as part of this library, written either
+by Rich Felker, the main author of the library, or by one or more
+contibutors listed above. Details on authorship of individual files
+can be found in the git version control history of the project. The
+omission of copyright and license comments in each file is in the
+interest of source tree size.
+
+In addition, permission is hereby granted for all public header files
+(include/* and arch/*/bits/*) and crt files intended to be linked into
+applications (crt/*, ldso/dlstart.c, and arch/*/crt_arch.h) to omit
+the copyright notice and permission notice otherwise required by the
+license, and to use these files without any requirement of
+attribution. These files include substantial contributions from:
+
+Bobby Bingham
+John Spencer
+Nicholas J. Kain
+Rich Felker
+Richard Pennington
+Stefan Kristiansson
+Szabolcs Nagy
+
+all of whom have explicitly granted such permission.
+
+This file previously contained text expressing a belief that most of
+the files covered by the above exception were sufficiently trivial not
+to be subject to copyright, resulting in confusion over whether it
+negated the permissions granted in the license. In the spirit of
+permissive licensing, and of not having licensing issues being an
+obstacle to adoption, that text has been removed.
diff --git a/toolkit/crashreporter/google-breakpad/src/third_party/musl/README b/toolkit/crashreporter/google-breakpad/src/third_party/musl/README
new file mode 100644
index 0000000000..a30eb11275
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/third_party/musl/README
@@ -0,0 +1,23 @@
+
+ musl libc
+
+musl, pronounced like the word "mussel", is an MIT-licensed
+implementation of the standard C library targetting the Linux syscall
+API, suitable for use in a wide range of deployment environments. musl
+offers efficient static and dynamic linking support, lightweight code
+and low runtime overhead, strong fail-safe guarantees under correct
+usage, and correctness in the sense of standards conformance and
+safety. musl is built on the principle that these goals are best
+achieved through simple code that is easy to understand and maintain.
+
+The 1.1 release series for musl features coverage for all interfaces
+defined in ISO C99 and POSIX 2008 base, along with a number of
+non-standardized interfaces for compatibility with Linux, BSD, and
+glibc functionality.
+
+For basic installation instructions, see the included INSTALL file.
+Information on full musl-targeted compiler toolchains, system
+bootstrapping, and Linux distributions built on musl can be found on
+the project website:
+
+ http://www.musl-libc.org/
diff --git a/toolkit/crashreporter/google-breakpad/src/third_party/musl/README.breakpad b/toolkit/crashreporter/google-breakpad/src/third_party/musl/README.breakpad
new file mode 100644
index 0000000000..f500c4359e
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/third_party/musl/README.breakpad
@@ -0,0 +1,3 @@
+This directory contains the elf header from
+https://git.musl-libc.org/cgit/musl/tree/
+that is required to get ELF working in dump_syms on Mac OS X.
diff --git a/toolkit/crashreporter/google-breakpad/src/third_party/musl/VERSION b/toolkit/crashreporter/google-breakpad/src/third_party/musl/VERSION
new file mode 100644
index 0000000000..e9bc14996e
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/third_party/musl/VERSION
@@ -0,0 +1 @@
+1.1.14
diff --git a/toolkit/crashreporter/google-breakpad/src/third_party/musl/include/elf.h b/toolkit/crashreporter/google-breakpad/src/third_party/musl/include/elf.h
new file mode 100644
index 0000000000..aad522e484
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/third_party/musl/include/elf.h
@@ -0,0 +1,3234 @@
+#ifndef _ELF_H
+#define _ELF_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+
+typedef uint16_t Elf32_Half;
+typedef uint16_t Elf64_Half;
+
+typedef uint32_t Elf32_Word;
+typedef int32_t Elf32_Sword;
+typedef uint32_t Elf64_Word;
+typedef int32_t Elf64_Sword;
+
+typedef uint64_t Elf32_Xword;
+typedef int64_t Elf32_Sxword;
+typedef uint64_t Elf64_Xword;
+typedef int64_t Elf64_Sxword;
+
+typedef uint32_t Elf32_Addr;
+typedef uint64_t Elf64_Addr;
+
+typedef uint32_t Elf32_Off;
+typedef uint64_t Elf64_Off;
+
+typedef uint16_t Elf32_Section;
+typedef uint16_t Elf64_Section;
+
+typedef Elf32_Half Elf32_Versym;
+typedef Elf64_Half Elf64_Versym;
+
+#define EI_NIDENT (16)
+
+typedef struct {
+ unsigned char e_ident[EI_NIDENT];
+ Elf32_Half e_type;
+ Elf32_Half e_machine;
+ Elf32_Word e_version;
+ Elf32_Addr e_entry;
+ Elf32_Off e_phoff;
+ Elf32_Off e_shoff;
+ Elf32_Word e_flags;
+ Elf32_Half e_ehsize;
+ Elf32_Half e_phentsize;
+ Elf32_Half e_phnum;
+ Elf32_Half e_shentsize;
+ Elf32_Half e_shnum;
+ Elf32_Half e_shstrndx;
+} Elf32_Ehdr;
+
+typedef struct {
+ unsigned char e_ident[EI_NIDENT];
+ Elf64_Half e_type;
+ Elf64_Half e_machine;
+ Elf64_Word e_version;
+ Elf64_Addr e_entry;
+ Elf64_Off e_phoff;
+ Elf64_Off e_shoff;
+ Elf64_Word e_flags;
+ Elf64_Half e_ehsize;
+ Elf64_Half e_phentsize;
+ Elf64_Half e_phnum;
+ Elf64_Half e_shentsize;
+ Elf64_Half e_shnum;
+ Elf64_Half e_shstrndx;
+} Elf64_Ehdr;
+
+#define EI_MAG0 0
+#define ELFMAG0 0x7f
+
+#define EI_MAG1 1
+#define ELFMAG1 'E'
+
+#define EI_MAG2 2
+#define ELFMAG2 'L'
+
+#define EI_MAG3 3
+#define ELFMAG3 'F'
+
+
+#define ELFMAG "\177ELF"
+#define SELFMAG 4
+
+#define EI_CLASS 4
+#define ELFCLASSNONE 0
+#define ELFCLASS32 1
+#define ELFCLASS64 2
+#define ELFCLASSNUM 3
+
+#define EI_DATA 5
+#define ELFDATANONE 0
+#define ELFDATA2LSB 1
+#define ELFDATA2MSB 2
+#define ELFDATANUM 3
+
+#define EI_VERSION 6
+
+
+#define EI_OSABI 7
+#define ELFOSABI_NONE 0
+#define ELFOSABI_SYSV 0
+#define ELFOSABI_HPUX 1
+#define ELFOSABI_NETBSD 2
+#define ELFOSABI_LINUX 3
+#define ELFOSABI_GNU 3
+#define ELFOSABI_SOLARIS 6
+#define ELFOSABI_AIX 7
+#define ELFOSABI_IRIX 8
+#define ELFOSABI_FREEBSD 9
+#define ELFOSABI_TRU64 10
+#define ELFOSABI_MODESTO 11
+#define ELFOSABI_OPENBSD 12
+#define ELFOSABI_ARM 97
+#define ELFOSABI_STANDALONE 255
+
+#define EI_ABIVERSION 8
+
+#define EI_PAD 9
+
+
+
+#define ET_NONE 0
+#define ET_REL 1
+#define ET_EXEC 2
+#define ET_DYN 3
+#define ET_CORE 4
+#define ET_NUM 5
+#define ET_LOOS 0xfe00
+#define ET_HIOS 0xfeff
+#define ET_LOPROC 0xff00
+#define ET_HIPROC 0xffff
+
+
+
+#define EM_NONE 0
+#define EM_M32 1
+#define EM_SPARC 2
+#define EM_386 3
+#define EM_68K 4
+#define EM_88K 5
+#define EM_860 7
+#define EM_MIPS 8
+#define EM_S370 9
+#define EM_MIPS_RS3_LE 10
+
+#define EM_PARISC 15
+#define EM_VPP500 17
+#define EM_SPARC32PLUS 18
+#define EM_960 19
+#define EM_PPC 20
+#define EM_PPC64 21
+#define EM_S390 22
+
+#define EM_V800 36
+#define EM_FR20 37
+#define EM_RH32 38
+#define EM_RCE 39
+#define EM_ARM 40
+#define EM_FAKE_ALPHA 41
+#define EM_SH 42
+#define EM_SPARCV9 43
+#define EM_TRICORE 44
+#define EM_ARC 45
+#define EM_H8_300 46
+#define EM_H8_300H 47
+#define EM_H8S 48
+#define EM_H8_500 49
+#define EM_IA_64 50
+#define EM_MIPS_X 51
+#define EM_COLDFIRE 52
+#define EM_68HC12 53
+#define EM_MMA 54
+#define EM_PCP 55
+#define EM_NCPU 56
+#define EM_NDR1 57
+#define EM_STARCORE 58
+#define EM_ME16 59
+#define EM_ST100 60
+#define EM_TINYJ 61
+#define EM_X86_64 62
+#define EM_PDSP 63
+
+#define EM_FX66 66
+#define EM_ST9PLUS 67
+#define EM_ST7 68
+#define EM_68HC16 69
+#define EM_68HC11 70
+#define EM_68HC08 71
+#define EM_68HC05 72
+#define EM_SVX 73
+#define EM_ST19 74
+#define EM_VAX 75
+#define EM_CRIS 76
+#define EM_JAVELIN 77
+#define EM_FIREPATH 78
+#define EM_ZSP 79
+#define EM_MMIX 80
+#define EM_HUANY 81
+#define EM_PRISM 82
+#define EM_AVR 83
+#define EM_FR30 84
+#define EM_D10V 85
+#define EM_D30V 86
+#define EM_V850 87
+#define EM_M32R 88
+#define EM_MN10300 89
+#define EM_MN10200 90
+#define EM_PJ 91
+#define EM_OR1K 92
+#define EM_OPENRISC 92
+#define EM_ARC_A5 93
+#define EM_ARC_COMPACT 93
+#define EM_XTENSA 94
+#define EM_VIDEOCORE 95
+#define EM_TMM_GPP 96
+#define EM_NS32K 97
+#define EM_TPC 98
+#define EM_SNP1K 99
+#define EM_ST200 100
+#define EM_IP2K 101
+#define EM_MAX 102
+#define EM_CR 103
+#define EM_F2MC16 104
+#define EM_MSP430 105
+#define EM_BLACKFIN 106
+#define EM_SE_C33 107
+#define EM_SEP 108
+#define EM_ARCA 109
+#define EM_UNICORE 110
+#define EM_EXCESS 111
+#define EM_DXP 112
+#define EM_ALTERA_NIOS2 113
+#define EM_CRX 114
+#define EM_XGATE 115
+#define EM_C166 116
+#define EM_M16C 117
+#define EM_DSPIC30F 118
+#define EM_CE 119
+#define EM_M32C 120
+#define EM_TSK3000 131
+#define EM_RS08 132
+#define EM_SHARC 133
+#define EM_ECOG2 134
+#define EM_SCORE7 135
+#define EM_DSP24 136
+#define EM_VIDEOCORE3 137
+#define EM_LATTICEMICO32 138
+#define EM_SE_C17 139
+#define EM_TI_C6000 140
+#define EM_TI_C2000 141
+#define EM_TI_C5500 142
+#define EM_TI_ARP32 143
+#define EM_TI_PRU 144
+#define EM_MMDSP_PLUS 160
+#define EM_CYPRESS_M8C 161
+#define EM_R32C 162
+#define EM_TRIMEDIA 163
+#define EM_QDSP6 164
+#define EM_8051 165
+#define EM_STXP7X 166
+#define EM_NDS32 167
+#define EM_ECOG1X 168
+#define EM_MAXQ30 169
+#define EM_XIMO16 170
+#define EM_MANIK 171
+#define EM_CRAYNV2 172
+#define EM_RX 173
+#define EM_METAG 174
+#define EM_MCST_ELBRUS 175
+#define EM_ECOG16 176
+#define EM_CR16 177
+#define EM_ETPU 178
+#define EM_SLE9X 179
+#define EM_L10M 180
+#define EM_K10M 181
+#define EM_AARCH64 183
+#define EM_AVR32 185
+#define EM_STM8 186
+#define EM_TILE64 187
+#define EM_TILEPRO 188
+#define EM_MICROBLAZE 189
+#define EM_CUDA 190
+#define EM_TILEGX 191
+#define EM_CLOUDSHIELD 192
+#define EM_COREA_1ST 193
+#define EM_COREA_2ND 194
+#define EM_ARC_COMPACT2 195
+#define EM_OPEN8 196
+#define EM_RL78 197
+#define EM_VIDEOCORE5 198
+#define EM_78KOR 199
+#define EM_56800EX 200
+#define EM_BA1 201
+#define EM_BA2 202
+#define EM_XCORE 203
+#define EM_MCHP_PIC 204
+#define EM_KM32 210
+#define EM_KMX32 211
+#define EM_EMX16 212
+#define EM_EMX8 213
+#define EM_KVARC 214
+#define EM_CDP 215
+#define EM_COGE 216
+#define EM_COOL 217
+#define EM_NORC 218
+#define EM_CSR_KALIMBA 219
+#define EM_Z80 220
+#define EM_VISIUM 221
+#define EM_FT32 222
+#define EM_MOXIE 223
+#define EM_AMDGPU 224
+#define EM_RISCV 243
+#define EM_BPF 247
+#define EM_CSKY 252
+#define EM_NUM 253
+
+#define EM_ALPHA 0x9026
+
+#define EV_NONE 0
+#define EV_CURRENT 1
+#define EV_NUM 2
+
+typedef struct {
+ Elf32_Word sh_name;
+ Elf32_Word sh_type;
+ Elf32_Word sh_flags;
+ Elf32_Addr sh_addr;
+ Elf32_Off sh_offset;
+ Elf32_Word sh_size;
+ Elf32_Word sh_link;
+ Elf32_Word sh_info;
+ Elf32_Word sh_addralign;
+ Elf32_Word sh_entsize;
+} Elf32_Shdr;
+
+typedef struct {
+ Elf64_Word sh_name;
+ Elf64_Word sh_type;
+ Elf64_Xword sh_flags;
+ Elf64_Addr sh_addr;
+ Elf64_Off sh_offset;
+ Elf64_Xword sh_size;
+ Elf64_Word sh_link;
+ Elf64_Word sh_info;
+ Elf64_Xword sh_addralign;
+ Elf64_Xword sh_entsize;
+} Elf64_Shdr;
+
+
+
+#define SHN_UNDEF 0
+#define SHN_LORESERVE 0xff00
+#define SHN_LOPROC 0xff00
+#define SHN_BEFORE 0xff00
+
+#define SHN_AFTER 0xff01
+
+#define SHN_HIPROC 0xff1f
+#define SHN_LOOS 0xff20
+#define SHN_HIOS 0xff3f
+#define SHN_ABS 0xfff1
+#define SHN_COMMON 0xfff2
+#define SHN_XINDEX 0xffff
+#define SHN_HIRESERVE 0xffff
+
+
+
+#define SHT_NULL 0
+#define SHT_PROGBITS 1
+#define SHT_SYMTAB 2
+#define SHT_STRTAB 3
+#define SHT_RELA 4
+#define SHT_HASH 5
+#define SHT_DYNAMIC 6
+#define SHT_NOTE 7
+#define SHT_NOBITS 8
+#define SHT_REL 9
+#define SHT_SHLIB 10
+#define SHT_DYNSYM 11
+#define SHT_INIT_ARRAY 14
+#define SHT_FINI_ARRAY 15
+#define SHT_PREINIT_ARRAY 16
+#define SHT_GROUP 17
+#define SHT_SYMTAB_SHNDX 18
+#define SHT_NUM 19
+#define SHT_LOOS 0x60000000
+#define SHT_GNU_ATTRIBUTES 0x6ffffff5
+#define SHT_GNU_HASH 0x6ffffff6
+#define SHT_GNU_LIBLIST 0x6ffffff7
+#define SHT_CHECKSUM 0x6ffffff8
+#define SHT_LOSUNW 0x6ffffffa
+#define SHT_SUNW_move 0x6ffffffa
+#define SHT_SUNW_COMDAT 0x6ffffffb
+#define SHT_SUNW_syminfo 0x6ffffffc
+#define SHT_GNU_verdef 0x6ffffffd
+#define SHT_GNU_verneed 0x6ffffffe
+#define SHT_GNU_versym 0x6fffffff
+#define SHT_HISUNW 0x6fffffff
+#define SHT_HIOS 0x6fffffff
+#define SHT_LOPROC 0x70000000
+#define SHT_HIPROC 0x7fffffff
+#define SHT_LOUSER 0x80000000
+#define SHT_HIUSER 0x8fffffff
+
+#define SHF_WRITE (1 << 0)
+#define SHF_ALLOC (1 << 1)
+#define SHF_EXECINSTR (1 << 2)
+#define SHF_MERGE (1 << 4)
+#define SHF_STRINGS (1 << 5)
+#define SHF_INFO_LINK (1 << 6)
+#define SHF_LINK_ORDER (1 << 7)
+#define SHF_OS_NONCONFORMING (1 << 8)
+
+#define SHF_GROUP (1 << 9)
+#define SHF_TLS (1 << 10)
+#define SHF_COMPRESSED (1 << 11)
+#define SHF_MASKOS 0x0ff00000
+#define SHF_MASKPROC 0xf0000000
+#define SHF_ORDERED (1 << 30)
+#define SHF_EXCLUDE (1U << 31)
+
+typedef struct {
+ Elf32_Word ch_type;
+ Elf32_Word ch_size;
+ Elf32_Word ch_addralign;
+} Elf32_Chdr;
+
+typedef struct {
+ Elf64_Word ch_type;
+ Elf64_Word ch_reserved;
+ Elf64_Xword ch_size;
+ Elf64_Xword ch_addralign;
+} Elf64_Chdr;
+
+#define ELFCOMPRESS_ZLIB 1
+#define ELFCOMPRESS_LOOS 0x60000000
+#define ELFCOMPRESS_HIOS 0x6fffffff
+#define ELFCOMPRESS_LOPROC 0x70000000
+#define ELFCOMPRESS_HIPROC 0x7fffffff
+
+
+#define GRP_COMDAT 0x1
+
+typedef struct {
+ Elf32_Word st_name;
+ Elf32_Addr st_value;
+ Elf32_Word st_size;
+ unsigned char st_info;
+ unsigned char st_other;
+ Elf32_Section st_shndx;
+} Elf32_Sym;
+
+typedef struct {
+ Elf64_Word st_name;
+ unsigned char st_info;
+ unsigned char st_other;
+ Elf64_Section st_shndx;
+ Elf64_Addr st_value;
+ Elf64_Xword st_size;
+} Elf64_Sym;
+
+typedef struct {
+ Elf32_Half si_boundto;
+ Elf32_Half si_flags;
+} Elf32_Syminfo;
+
+typedef struct {
+ Elf64_Half si_boundto;
+ Elf64_Half si_flags;
+} Elf64_Syminfo;
+
+#define SYMINFO_BT_SELF 0xffff
+#define SYMINFO_BT_PARENT 0xfffe
+#define SYMINFO_BT_LOWRESERVE 0xff00
+
+#define SYMINFO_FLG_DIRECT 0x0001
+#define SYMINFO_FLG_PASSTHRU 0x0002
+#define SYMINFO_FLG_COPY 0x0004
+#define SYMINFO_FLG_LAZYLOAD 0x0008
+
+#define SYMINFO_NONE 0
+#define SYMINFO_CURRENT 1
+#define SYMINFO_NUM 2
+
+#define ELF32_ST_BIND(val) (((unsigned char) (val)) >> 4)
+#define ELF32_ST_TYPE(val) ((val) & 0xf)
+#define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
+
+#define ELF64_ST_BIND(val) ELF32_ST_BIND (val)
+#define ELF64_ST_TYPE(val) ELF32_ST_TYPE (val)
+#define ELF64_ST_INFO(bind, type) ELF32_ST_INFO ((bind), (type))
+
+#define STB_LOCAL 0
+#define STB_GLOBAL 1
+#define STB_WEAK 2
+#define STB_NUM 3
+#define STB_LOOS 10
+#define STB_GNU_UNIQUE 10
+#define STB_HIOS 12
+#define STB_LOPROC 13
+#define STB_HIPROC 15
+
+#define STT_NOTYPE 0
+#define STT_OBJECT 1
+#define STT_FUNC 2
+#define STT_SECTION 3
+#define STT_FILE 4
+#define STT_COMMON 5
+#define STT_TLS 6
+#define STT_NUM 7
+#define STT_LOOS 10
+#define STT_GNU_IFUNC 10
+#define STT_HIOS 12
+#define STT_LOPROC 13
+#define STT_HIPROC 15
+
+#define STN_UNDEF 0
+
+#define ELF32_ST_VISIBILITY(o) ((o) & 0x03)
+#define ELF64_ST_VISIBILITY(o) ELF32_ST_VISIBILITY (o)
+
+#define STV_DEFAULT 0
+#define STV_INTERNAL 1
+#define STV_HIDDEN 2
+#define STV_PROTECTED 3
+
+
+
+
+typedef struct {
+ Elf32_Addr r_offset;
+ Elf32_Word r_info;
+} Elf32_Rel;
+
+typedef struct {
+ Elf64_Addr r_offset;
+ Elf64_Xword r_info;
+} Elf64_Rel;
+
+
+
+typedef struct {
+ Elf32_Addr r_offset;
+ Elf32_Word r_info;
+ Elf32_Sword r_addend;
+} Elf32_Rela;
+
+typedef struct {
+ Elf64_Addr r_offset;
+ Elf64_Xword r_info;
+ Elf64_Sxword r_addend;
+} Elf64_Rela;
+
+
+
+#define ELF32_R_SYM(val) ((val) >> 8)
+#define ELF32_R_TYPE(val) ((val) & 0xff)
+#define ELF32_R_INFO(sym, type) (((sym) << 8) + ((type) & 0xff))
+
+#define ELF64_R_SYM(i) ((i) >> 32)
+#define ELF64_R_TYPE(i) ((i) & 0xffffffff)
+#define ELF64_R_INFO(sym,type) ((((Elf64_Xword) (sym)) << 32) + (type))
+
+
+
+typedef struct {
+ Elf32_Word p_type;
+ Elf32_Off p_offset;
+ Elf32_Addr p_vaddr;
+ Elf32_Addr p_paddr;
+ Elf32_Word p_filesz;
+ Elf32_Word p_memsz;
+ Elf32_Word p_flags;
+ Elf32_Word p_align;
+} Elf32_Phdr;
+
+typedef struct {
+ Elf64_Word p_type;
+ Elf64_Word p_flags;
+ Elf64_Off p_offset;
+ Elf64_Addr p_vaddr;
+ Elf64_Addr p_paddr;
+ Elf64_Xword p_filesz;
+ Elf64_Xword p_memsz;
+ Elf64_Xword p_align;
+} Elf64_Phdr;
+
+
+
+#define PT_NULL 0
+#define PT_LOAD 1
+#define PT_DYNAMIC 2
+#define PT_INTERP 3
+#define PT_NOTE 4
+#define PT_SHLIB 5
+#define PT_PHDR 6
+#define PT_TLS 7
+#define PT_NUM 8
+#define PT_LOOS 0x60000000
+#define PT_GNU_EH_FRAME 0x6474e550
+#define PT_GNU_STACK 0x6474e551
+#define PT_GNU_RELRO 0x6474e552
+#define PT_LOSUNW 0x6ffffffa
+#define PT_SUNWBSS 0x6ffffffa
+#define PT_SUNWSTACK 0x6ffffffb
+#define PT_HISUNW 0x6fffffff
+#define PT_HIOS 0x6fffffff
+#define PT_LOPROC 0x70000000
+#define PT_HIPROC 0x7fffffff
+
+
+#define PN_XNUM 0xffff
+
+
+#define PF_X (1 << 0)
+#define PF_W (1 << 1)
+#define PF_R (1 << 2)
+#define PF_MASKOS 0x0ff00000
+#define PF_MASKPROC 0xf0000000
+
+
+
+#define NT_PRSTATUS 1
+#define NT_PRFPREG 2
+#define NT_FPREGSET 2
+#define NT_PRPSINFO 3
+#define NT_PRXREG 4
+#define NT_TASKSTRUCT 4
+#define NT_PLATFORM 5
+#define NT_AUXV 6
+#define NT_GWINDOWS 7
+#define NT_ASRS 8
+#define NT_PSTATUS 10
+#define NT_PSINFO 13
+#define NT_PRCRED 14
+#define NT_UTSNAME 15
+#define NT_LWPSTATUS 16
+#define NT_LWPSINFO 17
+#define NT_PRFPXREG 20
+#define NT_SIGINFO 0x53494749
+#define NT_FILE 0x46494c45
+#define NT_PRXFPREG 0x46e62b7f
+#define NT_PPC_VMX 0x100
+#define NT_PPC_SPE 0x101
+#define NT_PPC_VSX 0x102
+#define NT_PPC_TAR 0x103
+#define NT_PPC_PPR 0x104
+#define NT_PPC_DSCR 0x105
+#define NT_PPC_EBB 0x106
+#define NT_PPC_PMU 0x107
+#define NT_PPC_TM_CGPR 0x108
+#define NT_PPC_TM_CFPR 0x109
+#define NT_PPC_TM_CVMX 0x10a
+#define NT_PPC_TM_CVSX 0x10b
+#define NT_PPC_TM_SPR 0x10c
+#define NT_PPC_TM_CTAR 0x10d
+#define NT_PPC_TM_CPPR 0x10e
+#define NT_PPC_TM_CDSCR 0x10f
+#define NT_386_TLS 0x200
+#define NT_386_IOPERM 0x201
+#define NT_X86_XSTATE 0x202
+#define NT_S390_HIGH_GPRS 0x300
+#define NT_S390_TIMER 0x301
+#define NT_S390_TODCMP 0x302
+#define NT_S390_TODPREG 0x303
+#define NT_S390_CTRS 0x304
+#define NT_S390_PREFIX 0x305
+#define NT_S390_LAST_BREAK 0x306
+#define NT_S390_SYSTEM_CALL 0x307
+#define NT_S390_TDB 0x308
+#define NT_S390_VXRS_LOW 0x309
+#define NT_S390_VXRS_HIGH 0x30a
+#define NT_S390_GS_CB 0x30b
+#define NT_S390_GS_BC 0x30c
+#define NT_S390_RI_CB 0x30d
+#define NT_ARM_VFP 0x400
+#define NT_ARM_TLS 0x401
+#define NT_ARM_HW_BREAK 0x402
+#define NT_ARM_HW_WATCH 0x403
+#define NT_ARM_SYSTEM_CALL 0x404
+#define NT_ARM_SVE 0x405
+#define NT_ARM_PAC_MASK 0x406
+#define NT_METAG_CBUF 0x500
+#define NT_METAG_RPIPE 0x501
+#define NT_METAG_TLS 0x502
+#define NT_ARC_V2 0x600
+#define NT_VMCOREDD 0x700
+#define NT_MIPS_DSP 0x800
+#define NT_MIPS_FP_MODE 0x801
+#define NT_MIPS_MSA 0x802
+#define NT_VERSION 1
+
+
+
+
+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;
+
+
+
+#define DT_NULL 0
+#define DT_NEEDED 1
+#define DT_PLTRELSZ 2
+#define DT_PLTGOT 3
+#define DT_HASH 4
+#define DT_STRTAB 5
+#define DT_SYMTAB 6
+#define DT_RELA 7
+#define DT_RELASZ 8
+#define DT_RELAENT 9
+#define DT_STRSZ 10
+#define DT_SYMENT 11
+#define DT_INIT 12
+#define DT_FINI 13
+#define DT_SONAME 14
+#define DT_RPATH 15
+#define DT_SYMBOLIC 16
+#define DT_REL 17
+#define DT_RELSZ 18
+#define DT_RELENT 19
+#define DT_PLTREL 20
+#define DT_DEBUG 21
+#define DT_TEXTREL 22
+#define DT_JMPREL 23
+#define DT_BIND_NOW 24
+#define DT_INIT_ARRAY 25
+#define DT_FINI_ARRAY 26
+#define DT_INIT_ARRAYSZ 27
+#define DT_FINI_ARRAYSZ 28
+#define DT_RUNPATH 29
+#define DT_FLAGS 30
+#define DT_ENCODING 32
+#define DT_PREINIT_ARRAY 32
+#define DT_PREINIT_ARRAYSZ 33
+#define DT_SYMTAB_SHNDX 34
+#define DT_NUM 35
+#define DT_LOOS 0x6000000d
+#define DT_HIOS 0x6ffff000
+#define DT_LOPROC 0x70000000
+#define DT_HIPROC 0x7fffffff
+#define DT_PROCNUM DT_MIPS_NUM
+
+#define DT_VALRNGLO 0x6ffffd00
+#define DT_GNU_PRELINKED 0x6ffffdf5
+#define DT_GNU_CONFLICTSZ 0x6ffffdf6
+#define DT_GNU_LIBLISTSZ 0x6ffffdf7
+#define DT_CHECKSUM 0x6ffffdf8
+#define DT_PLTPADSZ 0x6ffffdf9
+#define DT_MOVEENT 0x6ffffdfa
+#define DT_MOVESZ 0x6ffffdfb
+#define DT_FEATURE_1 0x6ffffdfc
+#define DT_POSFLAG_1 0x6ffffdfd
+
+#define DT_SYMINSZ 0x6ffffdfe
+#define DT_SYMINENT 0x6ffffdff
+#define DT_VALRNGHI 0x6ffffdff
+#define DT_VALTAGIDX(tag) (DT_VALRNGHI - (tag))
+#define DT_VALNUM 12
+
+#define DT_ADDRRNGLO 0x6ffffe00
+#define DT_GNU_HASH 0x6ffffef5
+#define DT_TLSDESC_PLT 0x6ffffef6
+#define DT_TLSDESC_GOT 0x6ffffef7
+#define DT_GNU_CONFLICT 0x6ffffef8
+#define DT_GNU_LIBLIST 0x6ffffef9
+#define DT_CONFIG 0x6ffffefa
+#define DT_DEPAUDIT 0x6ffffefb
+#define DT_AUDIT 0x6ffffefc
+#define DT_PLTPAD 0x6ffffefd
+#define DT_MOVETAB 0x6ffffefe
+#define DT_SYMINFO 0x6ffffeff
+#define DT_ADDRRNGHI 0x6ffffeff
+#define DT_ADDRTAGIDX(tag) (DT_ADDRRNGHI - (tag))
+#define DT_ADDRNUM 11
+
+
+
+#define DT_VERSYM 0x6ffffff0
+
+#define DT_RELACOUNT 0x6ffffff9
+#define DT_RELCOUNT 0x6ffffffa
+
+
+#define DT_FLAGS_1 0x6ffffffb
+#define DT_VERDEF 0x6ffffffc
+
+#define DT_VERDEFNUM 0x6ffffffd
+#define DT_VERNEED 0x6ffffffe
+
+#define DT_VERNEEDNUM 0x6fffffff
+#define DT_VERSIONTAGIDX(tag) (DT_VERNEEDNUM - (tag))
+#define DT_VERSIONTAGNUM 16
+
+
+
+#define DT_AUXILIARY 0x7ffffffd
+#define DT_FILTER 0x7fffffff
+#define DT_EXTRATAGIDX(tag) ((Elf32_Word)-((Elf32_Sword) (tag) <<1>>1)-1)
+#define DT_EXTRANUM 3
+
+
+#define DF_ORIGIN 0x00000001
+#define DF_SYMBOLIC 0x00000002
+#define DF_TEXTREL 0x00000004
+#define DF_BIND_NOW 0x00000008
+#define DF_STATIC_TLS 0x00000010
+
+
+
+#define DF_1_NOW 0x00000001
+#define DF_1_GLOBAL 0x00000002
+#define DF_1_GROUP 0x00000004
+#define DF_1_NODELETE 0x00000008
+#define DF_1_LOADFLTR 0x00000010
+#define DF_1_INITFIRST 0x00000020
+#define DF_1_NOOPEN 0x00000040
+#define DF_1_ORIGIN 0x00000080
+#define DF_1_DIRECT 0x00000100
+#define DF_1_TRANS 0x00000200
+#define DF_1_INTERPOSE 0x00000400
+#define DF_1_NODEFLIB 0x00000800
+#define DF_1_NODUMP 0x00001000
+#define DF_1_CONFALT 0x00002000
+#define DF_1_ENDFILTEE 0x00004000
+#define DF_1_DISPRELDNE 0x00008000
+#define DF_1_DISPRELPND 0x00010000
+#define DF_1_NODIRECT 0x00020000
+#define DF_1_IGNMULDEF 0x00040000
+#define DF_1_NOKSYMS 0x00080000
+#define DF_1_NOHDR 0x00100000
+#define DF_1_EDITED 0x00200000
+#define DF_1_NORELOC 0x00400000
+#define DF_1_SYMINTPOSE 0x00800000
+#define DF_1_GLOBAUDIT 0x01000000
+#define DF_1_SINGLETON 0x02000000
+#define DF_1_STUB 0x04000000
+#define DF_1_PIE 0x08000000
+
+#define DTF_1_PARINIT 0x00000001
+#define DTF_1_CONFEXP 0x00000002
+
+
+#define DF_P1_LAZYLOAD 0x00000001
+#define DF_P1_GROUPPERM 0x00000002
+
+
+
+
+typedef struct {
+ Elf32_Half vd_version;
+ Elf32_Half vd_flags;
+ Elf32_Half vd_ndx;
+ Elf32_Half vd_cnt;
+ Elf32_Word vd_hash;
+ Elf32_Word vd_aux;
+ Elf32_Word vd_next;
+} Elf32_Verdef;
+
+typedef struct {
+ Elf64_Half vd_version;
+ Elf64_Half vd_flags;
+ Elf64_Half vd_ndx;
+ Elf64_Half vd_cnt;
+ Elf64_Word vd_hash;
+ Elf64_Word vd_aux;
+ Elf64_Word vd_next;
+} Elf64_Verdef;
+
+
+
+#define VER_DEF_NONE 0
+#define VER_DEF_CURRENT 1
+#define VER_DEF_NUM 2
+
+
+#define VER_FLG_BASE 0x1
+#define VER_FLG_WEAK 0x2
+
+
+#define VER_NDX_LOCAL 0
+#define VER_NDX_GLOBAL 1
+#define VER_NDX_LORESERVE 0xff00
+#define VER_NDX_ELIMINATE 0xff01
+
+
+
+typedef struct {
+ Elf32_Word vda_name;
+ Elf32_Word vda_next;
+} Elf32_Verdaux;
+
+typedef struct {
+ Elf64_Word vda_name;
+ Elf64_Word vda_next;
+} Elf64_Verdaux;
+
+
+
+
+typedef struct {
+ Elf32_Half vn_version;
+ Elf32_Half vn_cnt;
+ Elf32_Word vn_file;
+ Elf32_Word vn_aux;
+ Elf32_Word vn_next;
+} Elf32_Verneed;
+
+typedef struct {
+ Elf64_Half vn_version;
+ Elf64_Half vn_cnt;
+ Elf64_Word vn_file;
+ Elf64_Word vn_aux;
+ Elf64_Word vn_next;
+} Elf64_Verneed;
+
+
+
+#define VER_NEED_NONE 0
+#define VER_NEED_CURRENT 1
+#define VER_NEED_NUM 2
+
+
+
+typedef struct {
+ Elf32_Word vna_hash;
+ Elf32_Half vna_flags;
+ Elf32_Half vna_other;
+ Elf32_Word vna_name;
+ Elf32_Word vna_next;
+} Elf32_Vernaux;
+
+typedef struct {
+ Elf64_Word vna_hash;
+ Elf64_Half vna_flags;
+ Elf64_Half vna_other;
+ Elf64_Word vna_name;
+ Elf64_Word vna_next;
+} Elf64_Vernaux;
+
+
+
+#define VER_FLG_WEAK 0x2
+
+
+
+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;
+
+
+
+#define AT_NULL 0
+#define AT_IGNORE 1
+#define AT_EXECFD 2
+#define AT_PHDR 3
+#define AT_PHENT 4
+#define AT_PHNUM 5
+#define AT_PAGESZ 6
+#define AT_BASE 7
+#define AT_FLAGS 8
+#define AT_ENTRY 9
+#define AT_NOTELF 10
+#define AT_UID 11
+#define AT_EUID 12
+#define AT_GID 13
+#define AT_EGID 14
+#define AT_CLKTCK 17
+
+
+#define AT_PLATFORM 15
+#define AT_HWCAP 16
+
+
+
+
+#define AT_FPUCW 18
+
+
+#define AT_DCACHEBSIZE 19
+#define AT_ICACHEBSIZE 20
+#define AT_UCACHEBSIZE 21
+
+
+
+#define AT_IGNOREPPC 22
+
+#define AT_SECURE 23
+
+#define AT_BASE_PLATFORM 24
+
+#define AT_RANDOM 25
+
+#define AT_HWCAP2 26
+
+#define AT_EXECFN 31
+
+
+
+#define AT_SYSINFO 32
+#define AT_SYSINFO_EHDR 33
+
+
+
+#define AT_L1I_CACHESHAPE 34
+#define AT_L1D_CACHESHAPE 35
+#define AT_L2_CACHESHAPE 36
+#define AT_L3_CACHESHAPE 37
+
+#define AT_L1I_CACHESIZE 40
+#define AT_L1I_CACHEGEOMETRY 41
+#define AT_L1D_CACHESIZE 42
+#define AT_L1D_CACHEGEOMETRY 43
+#define AT_L2_CACHESIZE 44
+#define AT_L2_CACHEGEOMETRY 45
+#define AT_L3_CACHESIZE 46
+#define AT_L3_CACHEGEOMETRY 47
+
+#define AT_MINSIGSTKSZ 51
+
+
+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;
+
+
+
+
+#define ELF_NOTE_SOLARIS "SUNW Solaris"
+
+
+#define ELF_NOTE_GNU "GNU"
+
+
+
+
+
+#define ELF_NOTE_PAGESIZE_HINT 1
+
+
+#define NT_GNU_ABI_TAG 1
+#define ELF_NOTE_ABI NT_GNU_ABI_TAG
+
+
+
+#define ELF_NOTE_OS_LINUX 0
+#define ELF_NOTE_OS_GNU 1
+#define ELF_NOTE_OS_SOLARIS2 2
+#define ELF_NOTE_OS_FREEBSD 3
+
+#define NT_GNU_BUILD_ID 3
+#define NT_GNU_GOLD_VERSION 4
+
+
+
+typedef struct {
+ Elf32_Xword m_value;
+ Elf32_Word m_info;
+ Elf32_Word m_poffset;
+ Elf32_Half m_repeat;
+ Elf32_Half m_stride;
+} Elf32_Move;
+
+typedef struct {
+ Elf64_Xword m_value;
+ Elf64_Xword m_info;
+ Elf64_Xword m_poffset;
+ Elf64_Half m_repeat;
+ Elf64_Half m_stride;
+} Elf64_Move;
+
+
+#define ELF32_M_SYM(info) ((info) >> 8)
+#define ELF32_M_SIZE(info) ((unsigned char) (info))
+#define ELF32_M_INFO(sym, size) (((sym) << 8) + (unsigned char) (size))
+
+#define ELF64_M_SYM(info) ELF32_M_SYM (info)
+#define ELF64_M_SIZE(info) ELF32_M_SIZE (info)
+#define ELF64_M_INFO(sym, size) ELF32_M_INFO (sym, size)
+
+#define EF_CPU32 0x00810000
+
+#define R_68K_NONE 0
+#define R_68K_32 1
+#define R_68K_16 2
+#define R_68K_8 3
+#define R_68K_PC32 4
+#define R_68K_PC16 5
+#define R_68K_PC8 6
+#define R_68K_GOT32 7
+#define R_68K_GOT16 8
+#define R_68K_GOT8 9
+#define R_68K_GOT32O 10
+#define R_68K_GOT16O 11
+#define R_68K_GOT8O 12
+#define R_68K_PLT32 13
+#define R_68K_PLT16 14
+#define R_68K_PLT8 15
+#define R_68K_PLT32O 16
+#define R_68K_PLT16O 17
+#define R_68K_PLT8O 18
+#define R_68K_COPY 19
+#define R_68K_GLOB_DAT 20
+#define R_68K_JMP_SLOT 21
+#define R_68K_RELATIVE 22
+#define R_68K_TLS_GD32 25
+#define R_68K_TLS_GD16 26
+#define R_68K_TLS_GD8 27
+#define R_68K_TLS_LDM32 28
+#define R_68K_TLS_LDM16 29
+#define R_68K_TLS_LDM8 30
+#define R_68K_TLS_LDO32 31
+#define R_68K_TLS_LDO16 32
+#define R_68K_TLS_LDO8 33
+#define R_68K_TLS_IE32 34
+#define R_68K_TLS_IE16 35
+#define R_68K_TLS_IE8 36
+#define R_68K_TLS_LE32 37
+#define R_68K_TLS_LE16 38
+#define R_68K_TLS_LE8 39
+#define R_68K_TLS_DTPMOD32 40
+#define R_68K_TLS_DTPREL32 41
+#define R_68K_TLS_TPREL32 42
+#define R_68K_NUM 43
+
+#define R_386_NONE 0
+#define R_386_32 1
+#define R_386_PC32 2
+#define R_386_GOT32 3
+#define R_386_PLT32 4
+#define R_386_COPY 5
+#define R_386_GLOB_DAT 6
+#define R_386_JMP_SLOT 7
+#define R_386_RELATIVE 8
+#define R_386_GOTOFF 9
+#define R_386_GOTPC 10
+#define R_386_32PLT 11
+#define R_386_TLS_TPOFF 14
+#define R_386_TLS_IE 15
+#define R_386_TLS_GOTIE 16
+#define R_386_TLS_LE 17
+#define R_386_TLS_GD 18
+#define R_386_TLS_LDM 19
+#define R_386_16 20
+#define R_386_PC16 21
+#define R_386_8 22
+#define R_386_PC8 23
+#define R_386_TLS_GD_32 24
+#define R_386_TLS_GD_PUSH 25
+#define R_386_TLS_GD_CALL 26
+#define R_386_TLS_GD_POP 27
+#define R_386_TLS_LDM_32 28
+#define R_386_TLS_LDM_PUSH 29
+#define R_386_TLS_LDM_CALL 30
+#define R_386_TLS_LDM_POP 31
+#define R_386_TLS_LDO_32 32
+#define R_386_TLS_IE_32 33
+#define R_386_TLS_LE_32 34
+#define R_386_TLS_DTPMOD32 35
+#define R_386_TLS_DTPOFF32 36
+#define R_386_TLS_TPOFF32 37
+#define R_386_SIZE32 38
+#define R_386_TLS_GOTDESC 39
+#define R_386_TLS_DESC_CALL 40
+#define R_386_TLS_DESC 41
+#define R_386_IRELATIVE 42
+#define R_386_GOT32X 43
+#define R_386_NUM 44
+
+
+
+
+
+#define STT_SPARC_REGISTER 13
+
+
+
+#define EF_SPARCV9_MM 3
+#define EF_SPARCV9_TSO 0
+#define EF_SPARCV9_PSO 1
+#define EF_SPARCV9_RMO 2
+#define EF_SPARC_LEDATA 0x800000
+#define EF_SPARC_EXT_MASK 0xFFFF00
+#define EF_SPARC_32PLUS 0x000100
+#define EF_SPARC_SUN_US1 0x000200
+#define EF_SPARC_HAL_R1 0x000400
+#define EF_SPARC_SUN_US3 0x000800
+
+
+
+#define R_SPARC_NONE 0
+#define R_SPARC_8 1
+#define R_SPARC_16 2
+#define R_SPARC_32 3
+#define R_SPARC_DISP8 4
+#define R_SPARC_DISP16 5
+#define R_SPARC_DISP32 6
+#define R_SPARC_WDISP30 7
+#define R_SPARC_WDISP22 8
+#define R_SPARC_HI22 9
+#define R_SPARC_22 10
+#define R_SPARC_13 11
+#define R_SPARC_LO10 12
+#define R_SPARC_GOT10 13
+#define R_SPARC_GOT13 14
+#define R_SPARC_GOT22 15
+#define R_SPARC_PC10 16
+#define R_SPARC_PC22 17
+#define R_SPARC_WPLT30 18
+#define R_SPARC_COPY 19
+#define R_SPARC_GLOB_DAT 20
+#define R_SPARC_JMP_SLOT 21
+#define R_SPARC_RELATIVE 22
+#define R_SPARC_UA32 23
+
+
+
+#define R_SPARC_PLT32 24
+#define R_SPARC_HIPLT22 25
+#define R_SPARC_LOPLT10 26
+#define R_SPARC_PCPLT32 27
+#define R_SPARC_PCPLT22 28
+#define R_SPARC_PCPLT10 29
+#define R_SPARC_10 30
+#define R_SPARC_11 31
+#define R_SPARC_64 32
+#define R_SPARC_OLO10 33
+#define R_SPARC_HH22 34
+#define R_SPARC_HM10 35
+#define R_SPARC_LM22 36
+#define R_SPARC_PC_HH22 37
+#define R_SPARC_PC_HM10 38
+#define R_SPARC_PC_LM22 39
+#define R_SPARC_WDISP16 40
+#define R_SPARC_WDISP19 41
+#define R_SPARC_GLOB_JMP 42
+#define R_SPARC_7 43
+#define R_SPARC_5 44
+#define R_SPARC_6 45
+#define R_SPARC_DISP64 46
+#define R_SPARC_PLT64 47
+#define R_SPARC_HIX22 48
+#define R_SPARC_LOX10 49
+#define R_SPARC_H44 50
+#define R_SPARC_M44 51
+#define R_SPARC_L44 52
+#define R_SPARC_REGISTER 53
+#define R_SPARC_UA64 54
+#define R_SPARC_UA16 55
+#define R_SPARC_TLS_GD_HI22 56
+#define R_SPARC_TLS_GD_LO10 57
+#define R_SPARC_TLS_GD_ADD 58
+#define R_SPARC_TLS_GD_CALL 59
+#define R_SPARC_TLS_LDM_HI22 60
+#define R_SPARC_TLS_LDM_LO10 61
+#define R_SPARC_TLS_LDM_ADD 62
+#define R_SPARC_TLS_LDM_CALL 63
+#define R_SPARC_TLS_LDO_HIX22 64
+#define R_SPARC_TLS_LDO_LOX10 65
+#define R_SPARC_TLS_LDO_ADD 66
+#define R_SPARC_TLS_IE_HI22 67
+#define R_SPARC_TLS_IE_LO10 68
+#define R_SPARC_TLS_IE_LD 69
+#define R_SPARC_TLS_IE_LDX 70
+#define R_SPARC_TLS_IE_ADD 71
+#define R_SPARC_TLS_LE_HIX22 72
+#define R_SPARC_TLS_LE_LOX10 73
+#define R_SPARC_TLS_DTPMOD32 74
+#define R_SPARC_TLS_DTPMOD64 75
+#define R_SPARC_TLS_DTPOFF32 76
+#define R_SPARC_TLS_DTPOFF64 77
+#define R_SPARC_TLS_TPOFF32 78
+#define R_SPARC_TLS_TPOFF64 79
+#define R_SPARC_GOTDATA_HIX22 80
+#define R_SPARC_GOTDATA_LOX10 81
+#define R_SPARC_GOTDATA_OP_HIX22 82
+#define R_SPARC_GOTDATA_OP_LOX10 83
+#define R_SPARC_GOTDATA_OP 84
+#define R_SPARC_H34 85
+#define R_SPARC_SIZE32 86
+#define R_SPARC_SIZE64 87
+#define R_SPARC_GNU_VTINHERIT 250
+#define R_SPARC_GNU_VTENTRY 251
+#define R_SPARC_REV32 252
+
+#define R_SPARC_NUM 253
+
+
+
+#define DT_SPARC_REGISTER 0x70000001
+#define DT_SPARC_NUM 2
+
+
+#define EF_MIPS_NOREORDER 1
+#define EF_MIPS_PIC 2
+#define EF_MIPS_CPIC 4
+#define EF_MIPS_XGOT 8
+#define EF_MIPS_64BIT_WHIRL 16
+#define EF_MIPS_ABI2 32
+#define EF_MIPS_ABI_ON32 64
+#define EF_MIPS_FP64 512
+#define EF_MIPS_NAN2008 1024
+#define EF_MIPS_ARCH 0xf0000000
+
+
+
+#define EF_MIPS_ARCH_1 0x00000000
+#define EF_MIPS_ARCH_2 0x10000000
+#define EF_MIPS_ARCH_3 0x20000000
+#define EF_MIPS_ARCH_4 0x30000000
+#define EF_MIPS_ARCH_5 0x40000000
+#define EF_MIPS_ARCH_32 0x50000000
+#define EF_MIPS_ARCH_64 0x60000000
+#define EF_MIPS_ARCH_32R2 0x70000000
+#define EF_MIPS_ARCH_64R2 0x80000000
+
+
+#define E_MIPS_ARCH_1 0x00000000
+#define E_MIPS_ARCH_2 0x10000000
+#define E_MIPS_ARCH_3 0x20000000
+#define E_MIPS_ARCH_4 0x30000000
+#define E_MIPS_ARCH_5 0x40000000
+#define E_MIPS_ARCH_32 0x50000000
+#define E_MIPS_ARCH_64 0x60000000
+
+
+
+#define SHN_MIPS_ACOMMON 0xff00
+#define SHN_MIPS_TEXT 0xff01
+#define SHN_MIPS_DATA 0xff02
+#define SHN_MIPS_SCOMMON 0xff03
+#define SHN_MIPS_SUNDEFINED 0xff04
+
+
+
+#define SHT_MIPS_LIBLIST 0x70000000
+#define SHT_MIPS_MSYM 0x70000001
+#define SHT_MIPS_CONFLICT 0x70000002
+#define SHT_MIPS_GPTAB 0x70000003
+#define SHT_MIPS_UCODE 0x70000004
+#define SHT_MIPS_DEBUG 0x70000005
+#define SHT_MIPS_REGINFO 0x70000006
+#define SHT_MIPS_PACKAGE 0x70000007
+#define SHT_MIPS_PACKSYM 0x70000008
+#define SHT_MIPS_RELD 0x70000009
+#define SHT_MIPS_IFACE 0x7000000b
+#define SHT_MIPS_CONTENT 0x7000000c
+#define SHT_MIPS_OPTIONS 0x7000000d
+#define SHT_MIPS_SHDR 0x70000010
+#define SHT_MIPS_FDESC 0x70000011
+#define SHT_MIPS_EXTSYM 0x70000012
+#define SHT_MIPS_DENSE 0x70000013
+#define SHT_MIPS_PDESC 0x70000014
+#define SHT_MIPS_LOCSYM 0x70000015
+#define SHT_MIPS_AUXSYM 0x70000016
+#define SHT_MIPS_OPTSYM 0x70000017
+#define SHT_MIPS_LOCSTR 0x70000018
+#define SHT_MIPS_LINE 0x70000019
+#define SHT_MIPS_RFDESC 0x7000001a
+#define SHT_MIPS_DELTASYM 0x7000001b
+#define SHT_MIPS_DELTAINST 0x7000001c
+#define SHT_MIPS_DELTACLASS 0x7000001d
+#define SHT_MIPS_DWARF 0x7000001e
+#define SHT_MIPS_DELTADECL 0x7000001f
+#define SHT_MIPS_SYMBOL_LIB 0x70000020
+#define SHT_MIPS_EVENTS 0x70000021
+#define SHT_MIPS_TRANSLATE 0x70000022
+#define SHT_MIPS_PIXIE 0x70000023
+#define SHT_MIPS_XLATE 0x70000024
+#define SHT_MIPS_XLATE_DEBUG 0x70000025
+#define SHT_MIPS_WHIRL 0x70000026
+#define SHT_MIPS_EH_REGION 0x70000027
+#define SHT_MIPS_XLATE_OLD 0x70000028
+#define SHT_MIPS_PDR_EXCEPTION 0x70000029
+
+
+
+#define SHF_MIPS_GPREL 0x10000000
+#define SHF_MIPS_MERGE 0x20000000
+#define SHF_MIPS_ADDR 0x40000000
+#define SHF_MIPS_STRINGS 0x80000000
+#define SHF_MIPS_NOSTRIP 0x08000000
+#define SHF_MIPS_LOCAL 0x04000000
+#define SHF_MIPS_NAMES 0x02000000
+#define SHF_MIPS_NODUPE 0x01000000
+
+
+
+
+
+#define STO_MIPS_DEFAULT 0x0
+#define STO_MIPS_INTERNAL 0x1
+#define STO_MIPS_HIDDEN 0x2
+#define STO_MIPS_PROTECTED 0x3
+#define STO_MIPS_PLT 0x8
+#define STO_MIPS_SC_ALIGN_UNUSED 0xff
+
+
+#define STB_MIPS_SPLIT_COMMON 13
+
+
+
+typedef union {
+ struct {
+ Elf32_Word gt_current_g_value;
+ Elf32_Word gt_unused;
+ } gt_header;
+ struct {
+ Elf32_Word gt_g_value;
+ Elf32_Word gt_bytes;
+ } gt_entry;
+} Elf32_gptab;
+
+
+
+typedef struct {
+ Elf32_Word ri_gprmask;
+ Elf32_Word ri_cprmask[4];
+ Elf32_Sword ri_gp_value;
+} Elf32_RegInfo;
+
+
+
+typedef struct {
+ unsigned char kind;
+
+ unsigned char size;
+ Elf32_Section section;
+
+ Elf32_Word info;
+} Elf_Options;
+
+
+
+#define ODK_NULL 0
+#define ODK_REGINFO 1
+#define ODK_EXCEPTIONS 2
+#define ODK_PAD 3
+#define ODK_HWPATCH 4
+#define ODK_FILL 5
+#define ODK_TAGS 6
+#define ODK_HWAND 7
+#define ODK_HWOR 8
+
+
+
+#define OEX_FPU_MIN 0x1f
+#define OEX_FPU_MAX 0x1f00
+#define OEX_PAGE0 0x10000
+#define OEX_SMM 0x20000
+#define OEX_FPDBUG 0x40000
+#define OEX_PRECISEFP OEX_FPDBUG
+#define OEX_DISMISS 0x80000
+
+#define OEX_FPU_INVAL 0x10
+#define OEX_FPU_DIV0 0x08
+#define OEX_FPU_OFLO 0x04
+#define OEX_FPU_UFLO 0x02
+#define OEX_FPU_INEX 0x01
+
+
+
+#define OHW_R4KEOP 0x1
+#define OHW_R8KPFETCH 0x2
+#define OHW_R5KEOP 0x4
+#define OHW_R5KCVTL 0x8
+
+#define OPAD_PREFIX 0x1
+#define OPAD_POSTFIX 0x2
+#define OPAD_SYMBOL 0x4
+
+
+
+typedef struct {
+ Elf32_Word hwp_flags1;
+ Elf32_Word hwp_flags2;
+} Elf_Options_Hw;
+
+
+
+#define OHWA0_R4KEOP_CHECKED 0x00000001
+#define OHWA1_R4KEOP_CLEAN 0x00000002
+
+
+
+#define R_MIPS_NONE 0
+#define R_MIPS_16 1
+#define R_MIPS_32 2
+#define R_MIPS_REL32 3
+#define R_MIPS_26 4
+#define R_MIPS_HI16 5
+#define R_MIPS_LO16 6
+#define R_MIPS_GPREL16 7
+#define R_MIPS_LITERAL 8
+#define R_MIPS_GOT16 9
+#define R_MIPS_PC16 10
+#define R_MIPS_CALL16 11
+#define R_MIPS_GPREL32 12
+
+#define R_MIPS_SHIFT5 16
+#define R_MIPS_SHIFT6 17
+#define R_MIPS_64 18
+#define R_MIPS_GOT_DISP 19
+#define R_MIPS_GOT_PAGE 20
+#define R_MIPS_GOT_OFST 21
+#define R_MIPS_GOT_HI16 22
+#define R_MIPS_GOT_LO16 23
+#define R_MIPS_SUB 24
+#define R_MIPS_INSERT_A 25
+#define R_MIPS_INSERT_B 26
+#define R_MIPS_DELETE 27
+#define R_MIPS_HIGHER 28
+#define R_MIPS_HIGHEST 29
+#define R_MIPS_CALL_HI16 30
+#define R_MIPS_CALL_LO16 31
+#define R_MIPS_SCN_DISP 32
+#define R_MIPS_REL16 33
+#define R_MIPS_ADD_IMMEDIATE 34
+#define R_MIPS_PJUMP 35
+#define R_MIPS_RELGOT 36
+#define R_MIPS_JALR 37
+#define R_MIPS_TLS_DTPMOD32 38
+#define R_MIPS_TLS_DTPREL32 39
+#define R_MIPS_TLS_DTPMOD64 40
+#define R_MIPS_TLS_DTPREL64 41
+#define R_MIPS_TLS_GD 42
+#define R_MIPS_TLS_LDM 43
+#define R_MIPS_TLS_DTPREL_HI16 44
+#define R_MIPS_TLS_DTPREL_LO16 45
+#define R_MIPS_TLS_GOTTPREL 46
+#define R_MIPS_TLS_TPREL32 47
+#define R_MIPS_TLS_TPREL64 48
+#define R_MIPS_TLS_TPREL_HI16 49
+#define R_MIPS_TLS_TPREL_LO16 50
+#define R_MIPS_GLOB_DAT 51
+#define R_MIPS_COPY 126
+#define R_MIPS_JUMP_SLOT 127
+
+#define R_MIPS_NUM 128
+
+
+
+#define PT_MIPS_REGINFO 0x70000000
+#define PT_MIPS_RTPROC 0x70000001
+#define PT_MIPS_OPTIONS 0x70000002
+#define PT_MIPS_ABIFLAGS 0x70000003
+
+
+
+#define PF_MIPS_LOCAL 0x10000000
+
+
+
+#define DT_MIPS_RLD_VERSION 0x70000001
+#define DT_MIPS_TIME_STAMP 0x70000002
+#define DT_MIPS_ICHECKSUM 0x70000003
+#define DT_MIPS_IVERSION 0x70000004
+#define DT_MIPS_FLAGS 0x70000005
+#define DT_MIPS_BASE_ADDRESS 0x70000006
+#define DT_MIPS_MSYM 0x70000007
+#define DT_MIPS_CONFLICT 0x70000008
+#define DT_MIPS_LIBLIST 0x70000009
+#define DT_MIPS_LOCAL_GOTNO 0x7000000a
+#define DT_MIPS_CONFLICTNO 0x7000000b
+#define DT_MIPS_LIBLISTNO 0x70000010
+#define DT_MIPS_SYMTABNO 0x70000011
+#define DT_MIPS_UNREFEXTNO 0x70000012
+#define DT_MIPS_GOTSYM 0x70000013
+#define DT_MIPS_HIPAGENO 0x70000014
+#define DT_MIPS_RLD_MAP 0x70000016
+#define DT_MIPS_DELTA_CLASS 0x70000017
+#define DT_MIPS_DELTA_CLASS_NO 0x70000018
+
+#define DT_MIPS_DELTA_INSTANCE 0x70000019
+#define DT_MIPS_DELTA_INSTANCE_NO 0x7000001a
+
+#define DT_MIPS_DELTA_RELOC 0x7000001b
+#define DT_MIPS_DELTA_RELOC_NO 0x7000001c
+
+#define DT_MIPS_DELTA_SYM 0x7000001d
+
+#define DT_MIPS_DELTA_SYM_NO 0x7000001e
+
+#define DT_MIPS_DELTA_CLASSSYM 0x70000020
+
+#define DT_MIPS_DELTA_CLASSSYM_NO 0x70000021
+
+#define DT_MIPS_CXX_FLAGS 0x70000022
+#define DT_MIPS_PIXIE_INIT 0x70000023
+#define DT_MIPS_SYMBOL_LIB 0x70000024
+#define DT_MIPS_LOCALPAGE_GOTIDX 0x70000025
+#define DT_MIPS_LOCAL_GOTIDX 0x70000026
+#define DT_MIPS_HIDDEN_GOTIDX 0x70000027
+#define DT_MIPS_PROTECTED_GOTIDX 0x70000028
+#define DT_MIPS_OPTIONS 0x70000029
+#define DT_MIPS_INTERFACE 0x7000002a
+#define DT_MIPS_DYNSTR_ALIGN 0x7000002b
+#define DT_MIPS_INTERFACE_SIZE 0x7000002c
+#define DT_MIPS_RLD_TEXT_RESOLVE_ADDR 0x7000002d
+
+#define DT_MIPS_PERF_SUFFIX 0x7000002e
+
+#define DT_MIPS_COMPACT_SIZE 0x7000002f
+#define DT_MIPS_GP_VALUE 0x70000030
+#define DT_MIPS_AUX_DYNAMIC 0x70000031
+
+#define DT_MIPS_PLTGOT 0x70000032
+
+#define DT_MIPS_RWPLT 0x70000034
+#define DT_MIPS_RLD_MAP_REL 0x70000035
+#define DT_MIPS_NUM 0x36
+
+
+
+#define RHF_NONE 0
+#define RHF_QUICKSTART (1 << 0)
+#define RHF_NOTPOT (1 << 1)
+#define RHF_NO_LIBRARY_REPLACEMENT (1 << 2)
+#define RHF_NO_MOVE (1 << 3)
+#define RHF_SGI_ONLY (1 << 4)
+#define RHF_GUARANTEE_INIT (1 << 5)
+#define RHF_DELTA_C_PLUS_PLUS (1 << 6)
+#define RHF_GUARANTEE_START_INIT (1 << 7)
+#define RHF_PIXIE (1 << 8)
+#define RHF_DEFAULT_DELAY_LOAD (1 << 9)
+#define RHF_REQUICKSTART (1 << 10)
+#define RHF_REQUICKSTARTED (1 << 11)
+#define RHF_CORD (1 << 12)
+#define RHF_NO_UNRES_UNDEF (1 << 13)
+#define RHF_RLD_ORDER_SAFE (1 << 14)
+
+
+
+typedef struct {
+ Elf32_Word l_name;
+ Elf32_Word l_time_stamp;
+ Elf32_Word l_checksum;
+ Elf32_Word l_version;
+ Elf32_Word l_flags;
+} Elf32_Lib;
+
+typedef struct {
+ Elf64_Word l_name;
+ Elf64_Word l_time_stamp;
+ Elf64_Word l_checksum;
+ Elf64_Word l_version;
+ Elf64_Word l_flags;
+} Elf64_Lib;
+
+
+
+
+#define LL_NONE 0
+#define LL_EXACT_MATCH (1 << 0)
+#define LL_IGNORE_INT_VER (1 << 1)
+#define LL_REQUIRE_MINOR (1 << 2)
+#define LL_EXPORTS (1 << 3)
+#define LL_DELAY_LOAD (1 << 4)
+#define LL_DELTA (1 << 5)
+
+
+
+typedef Elf32_Addr Elf32_Conflict;
+
+typedef struct {
+ Elf32_Half version;
+ unsigned char isa_level;
+ unsigned char isa_rev;
+ unsigned char gpr_size;
+ unsigned char cpr1_size;
+ unsigned char cpr2_size;
+ unsigned char fp_abi;
+ Elf32_Word isa_ext;
+ Elf32_Word ases;
+ Elf32_Word flags1;
+ Elf32_Word flags2;
+} Elf_MIPS_ABIFlags_v0;
+
+#define MIPS_AFL_REG_NONE 0x00
+#define MIPS_AFL_REG_32 0x01
+#define MIPS_AFL_REG_64 0x02
+#define MIPS_AFL_REG_128 0x03
+
+#define MIPS_AFL_ASE_DSP 0x00000001
+#define MIPS_AFL_ASE_DSPR2 0x00000002
+#define MIPS_AFL_ASE_EVA 0x00000004
+#define MIPS_AFL_ASE_MCU 0x00000008
+#define MIPS_AFL_ASE_MDMX 0x00000010
+#define MIPS_AFL_ASE_MIPS3D 0x00000020
+#define MIPS_AFL_ASE_MT 0x00000040
+#define MIPS_AFL_ASE_SMARTMIPS 0x00000080
+#define MIPS_AFL_ASE_VIRT 0x00000100
+#define MIPS_AFL_ASE_MSA 0x00000200
+#define MIPS_AFL_ASE_MIPS16 0x00000400
+#define MIPS_AFL_ASE_MICROMIPS 0x00000800
+#define MIPS_AFL_ASE_XPA 0x00001000
+#define MIPS_AFL_ASE_MASK 0x00001fff
+
+#define MIPS_AFL_EXT_XLR 1
+#define MIPS_AFL_EXT_OCTEON2 2
+#define MIPS_AFL_EXT_OCTEONP 3
+#define MIPS_AFL_EXT_LOONGSON_3A 4
+#define MIPS_AFL_EXT_OCTEON 5
+#define MIPS_AFL_EXT_5900 6
+#define MIPS_AFL_EXT_4650 7
+#define MIPS_AFL_EXT_4010 8
+#define MIPS_AFL_EXT_4100 9
+#define MIPS_AFL_EXT_3900 10
+#define MIPS_AFL_EXT_10000 11
+#define MIPS_AFL_EXT_SB1 12
+#define MIPS_AFL_EXT_4111 13
+#define MIPS_AFL_EXT_4120 14
+#define MIPS_AFL_EXT_5400 15
+#define MIPS_AFL_EXT_5500 16
+#define MIPS_AFL_EXT_LOONGSON_2E 17
+#define MIPS_AFL_EXT_LOONGSON_2F 18
+
+#define MIPS_AFL_FLAGS1_ODDSPREG 1
+
+enum
+{
+ Val_GNU_MIPS_ABI_FP_ANY = 0,
+ Val_GNU_MIPS_ABI_FP_DOUBLE = 1,
+ Val_GNU_MIPS_ABI_FP_SINGLE = 2,
+ Val_GNU_MIPS_ABI_FP_SOFT = 3,
+ Val_GNU_MIPS_ABI_FP_OLD_64 = 4,
+ Val_GNU_MIPS_ABI_FP_XX = 5,
+ Val_GNU_MIPS_ABI_FP_64 = 6,
+ Val_GNU_MIPS_ABI_FP_64A = 7,
+ Val_GNU_MIPS_ABI_FP_MAX = 7
+};
+
+
+
+
+#define EF_PARISC_TRAPNIL 0x00010000
+#define EF_PARISC_EXT 0x00020000
+#define EF_PARISC_LSB 0x00040000
+#define EF_PARISC_WIDE 0x00080000
+#define EF_PARISC_NO_KABP 0x00100000
+
+#define EF_PARISC_LAZYSWAP 0x00400000
+#define EF_PARISC_ARCH 0x0000ffff
+
+
+
+#define EFA_PARISC_1_0 0x020b
+#define EFA_PARISC_1_1 0x0210
+#define EFA_PARISC_2_0 0x0214
+
+
+
+#define SHN_PARISC_ANSI_COMMON 0xff00
+
+#define SHN_PARISC_HUGE_COMMON 0xff01
+
+
+
+#define SHT_PARISC_EXT 0x70000000
+#define SHT_PARISC_UNWIND 0x70000001
+#define SHT_PARISC_DOC 0x70000002
+
+
+
+#define SHF_PARISC_SHORT 0x20000000
+#define SHF_PARISC_HUGE 0x40000000
+#define SHF_PARISC_SBP 0x80000000
+
+
+
+#define STT_PARISC_MILLICODE 13
+
+#define STT_HP_OPAQUE (STT_LOOS + 0x1)
+#define STT_HP_STUB (STT_LOOS + 0x2)
+
+
+
+#define R_PARISC_NONE 0
+#define R_PARISC_DIR32 1
+#define R_PARISC_DIR21L 2
+#define R_PARISC_DIR17R 3
+#define R_PARISC_DIR17F 4
+#define R_PARISC_DIR14R 6
+#define R_PARISC_PCREL32 9
+#define R_PARISC_PCREL21L 10
+#define R_PARISC_PCREL17R 11
+#define R_PARISC_PCREL17F 12
+#define R_PARISC_PCREL14R 14
+#define R_PARISC_DPREL21L 18
+#define R_PARISC_DPREL14R 22
+#define R_PARISC_GPREL21L 26
+#define R_PARISC_GPREL14R 30
+#define R_PARISC_LTOFF21L 34
+#define R_PARISC_LTOFF14R 38
+#define R_PARISC_SECREL32 41
+#define R_PARISC_SEGBASE 48
+#define R_PARISC_SEGREL32 49
+#define R_PARISC_PLTOFF21L 50
+#define R_PARISC_PLTOFF14R 54
+#define R_PARISC_LTOFF_FPTR32 57
+#define R_PARISC_LTOFF_FPTR21L 58
+#define R_PARISC_LTOFF_FPTR14R 62
+#define R_PARISC_FPTR64 64
+#define R_PARISC_PLABEL32 65
+#define R_PARISC_PLABEL21L 66
+#define R_PARISC_PLABEL14R 70
+#define R_PARISC_PCREL64 72
+#define R_PARISC_PCREL22F 74
+#define R_PARISC_PCREL14WR 75
+#define R_PARISC_PCREL14DR 76
+#define R_PARISC_PCREL16F 77
+#define R_PARISC_PCREL16WF 78
+#define R_PARISC_PCREL16DF 79
+#define R_PARISC_DIR64 80
+#define R_PARISC_DIR14WR 83
+#define R_PARISC_DIR14DR 84
+#define R_PARISC_DIR16F 85
+#define R_PARISC_DIR16WF 86
+#define R_PARISC_DIR16DF 87
+#define R_PARISC_GPREL64 88
+#define R_PARISC_GPREL14WR 91
+#define R_PARISC_GPREL14DR 92
+#define R_PARISC_GPREL16F 93
+#define R_PARISC_GPREL16WF 94
+#define R_PARISC_GPREL16DF 95
+#define R_PARISC_LTOFF64 96
+#define R_PARISC_LTOFF14WR 99
+#define R_PARISC_LTOFF14DR 100
+#define R_PARISC_LTOFF16F 101
+#define R_PARISC_LTOFF16WF 102
+#define R_PARISC_LTOFF16DF 103
+#define R_PARISC_SECREL64 104
+#define R_PARISC_SEGREL64 112
+#define R_PARISC_PLTOFF14WR 115
+#define R_PARISC_PLTOFF14DR 116
+#define R_PARISC_PLTOFF16F 117
+#define R_PARISC_PLTOFF16WF 118
+#define R_PARISC_PLTOFF16DF 119
+#define R_PARISC_LTOFF_FPTR64 120
+#define R_PARISC_LTOFF_FPTR14WR 123
+#define R_PARISC_LTOFF_FPTR14DR 124
+#define R_PARISC_LTOFF_FPTR16F 125
+#define R_PARISC_LTOFF_FPTR16WF 126
+#define R_PARISC_LTOFF_FPTR16DF 127
+#define R_PARISC_LORESERVE 128
+#define R_PARISC_COPY 128
+#define R_PARISC_IPLT 129
+#define R_PARISC_EPLT 130
+#define R_PARISC_TPREL32 153
+#define R_PARISC_TPREL21L 154
+#define R_PARISC_TPREL14R 158
+#define R_PARISC_LTOFF_TP21L 162
+#define R_PARISC_LTOFF_TP14R 166
+#define R_PARISC_LTOFF_TP14F 167
+#define R_PARISC_TPREL64 216
+#define R_PARISC_TPREL14WR 219
+#define R_PARISC_TPREL14DR 220
+#define R_PARISC_TPREL16F 221
+#define R_PARISC_TPREL16WF 222
+#define R_PARISC_TPREL16DF 223
+#define R_PARISC_LTOFF_TP64 224
+#define R_PARISC_LTOFF_TP14WR 227
+#define R_PARISC_LTOFF_TP14DR 228
+#define R_PARISC_LTOFF_TP16F 229
+#define R_PARISC_LTOFF_TP16WF 230
+#define R_PARISC_LTOFF_TP16DF 231
+#define R_PARISC_GNU_VTENTRY 232
+#define R_PARISC_GNU_VTINHERIT 233
+#define R_PARISC_TLS_GD21L 234
+#define R_PARISC_TLS_GD14R 235
+#define R_PARISC_TLS_GDCALL 236
+#define R_PARISC_TLS_LDM21L 237
+#define R_PARISC_TLS_LDM14R 238
+#define R_PARISC_TLS_LDMCALL 239
+#define R_PARISC_TLS_LDO21L 240
+#define R_PARISC_TLS_LDO14R 241
+#define R_PARISC_TLS_DTPMOD32 242
+#define R_PARISC_TLS_DTPMOD64 243
+#define R_PARISC_TLS_DTPOFF32 244
+#define R_PARISC_TLS_DTPOFF64 245
+#define R_PARISC_TLS_LE21L R_PARISC_TPREL21L
+#define R_PARISC_TLS_LE14R R_PARISC_TPREL14R
+#define R_PARISC_TLS_IE21L R_PARISC_LTOFF_TP21L
+#define R_PARISC_TLS_IE14R R_PARISC_LTOFF_TP14R
+#define R_PARISC_TLS_TPREL32 R_PARISC_TPREL32
+#define R_PARISC_TLS_TPREL64 R_PARISC_TPREL64
+#define R_PARISC_HIRESERVE 255
+
+
+
+#define PT_HP_TLS (PT_LOOS + 0x0)
+#define PT_HP_CORE_NONE (PT_LOOS + 0x1)
+#define PT_HP_CORE_VERSION (PT_LOOS + 0x2)
+#define PT_HP_CORE_KERNEL (PT_LOOS + 0x3)
+#define PT_HP_CORE_COMM (PT_LOOS + 0x4)
+#define PT_HP_CORE_PROC (PT_LOOS + 0x5)
+#define PT_HP_CORE_LOADABLE (PT_LOOS + 0x6)
+#define PT_HP_CORE_STACK (PT_LOOS + 0x7)
+#define PT_HP_CORE_SHM (PT_LOOS + 0x8)
+#define PT_HP_CORE_MMF (PT_LOOS + 0x9)
+#define PT_HP_PARALLEL (PT_LOOS + 0x10)
+#define PT_HP_FASTBIND (PT_LOOS + 0x11)
+#define PT_HP_OPT_ANNOT (PT_LOOS + 0x12)
+#define PT_HP_HSL_ANNOT (PT_LOOS + 0x13)
+#define PT_HP_STACK (PT_LOOS + 0x14)
+
+#define PT_PARISC_ARCHEXT 0x70000000
+#define PT_PARISC_UNWIND 0x70000001
+
+
+
+#define PF_PARISC_SBP 0x08000000
+
+#define PF_HP_PAGE_SIZE 0x00100000
+#define PF_HP_FAR_SHARED 0x00200000
+#define PF_HP_NEAR_SHARED 0x00400000
+#define PF_HP_CODE 0x01000000
+#define PF_HP_MODIFY 0x02000000
+#define PF_HP_LAZYSWAP 0x04000000
+#define PF_HP_SBP 0x08000000
+
+
+
+
+
+
+#define EF_ALPHA_32BIT 1
+#define EF_ALPHA_CANRELAX 2
+
+
+
+
+#define SHT_ALPHA_DEBUG 0x70000001
+#define SHT_ALPHA_REGINFO 0x70000002
+
+
+
+#define SHF_ALPHA_GPREL 0x10000000
+
+
+#define STO_ALPHA_NOPV 0x80
+#define STO_ALPHA_STD_GPLOAD 0x88
+
+
+
+#define R_ALPHA_NONE 0
+#define R_ALPHA_REFLONG 1
+#define R_ALPHA_REFQUAD 2
+#define R_ALPHA_GPREL32 3
+#define R_ALPHA_LITERAL 4
+#define R_ALPHA_LITUSE 5
+#define R_ALPHA_GPDISP 6
+#define R_ALPHA_BRADDR 7
+#define R_ALPHA_HINT 8
+#define R_ALPHA_SREL16 9
+#define R_ALPHA_SREL32 10
+#define R_ALPHA_SREL64 11
+#define R_ALPHA_GPRELHIGH 17
+#define R_ALPHA_GPRELLOW 18
+#define R_ALPHA_GPREL16 19
+#define R_ALPHA_COPY 24
+#define R_ALPHA_GLOB_DAT 25
+#define R_ALPHA_JMP_SLOT 26
+#define R_ALPHA_RELATIVE 27
+#define R_ALPHA_TLS_GD_HI 28
+#define R_ALPHA_TLSGD 29
+#define R_ALPHA_TLS_LDM 30
+#define R_ALPHA_DTPMOD64 31
+#define R_ALPHA_GOTDTPREL 32
+#define R_ALPHA_DTPREL64 33
+#define R_ALPHA_DTPRELHI 34
+#define R_ALPHA_DTPRELLO 35
+#define R_ALPHA_DTPREL16 36
+#define R_ALPHA_GOTTPREL 37
+#define R_ALPHA_TPREL64 38
+#define R_ALPHA_TPRELHI 39
+#define R_ALPHA_TPRELLO 40
+#define R_ALPHA_TPREL16 41
+
+#define R_ALPHA_NUM 46
+
+
+#define LITUSE_ALPHA_ADDR 0
+#define LITUSE_ALPHA_BASE 1
+#define LITUSE_ALPHA_BYTOFF 2
+#define LITUSE_ALPHA_JSR 3
+#define LITUSE_ALPHA_TLS_GD 4
+#define LITUSE_ALPHA_TLS_LDM 5
+
+
+#define DT_ALPHA_PLTRO (DT_LOPROC + 0)
+#define DT_ALPHA_NUM 1
+
+
+
+
+#define EF_PPC_EMB 0x80000000
+
+
+#define EF_PPC_RELOCATABLE 0x00010000
+#define EF_PPC_RELOCATABLE_LIB 0x00008000
+
+
+
+#define R_PPC_NONE 0
+#define R_PPC_ADDR32 1
+#define R_PPC_ADDR24 2
+#define R_PPC_ADDR16 3
+#define R_PPC_ADDR16_LO 4
+#define R_PPC_ADDR16_HI 5
+#define R_PPC_ADDR16_HA 6
+#define R_PPC_ADDR14 7
+#define R_PPC_ADDR14_BRTAKEN 8
+#define R_PPC_ADDR14_BRNTAKEN 9
+#define R_PPC_REL24 10
+#define R_PPC_REL14 11
+#define R_PPC_REL14_BRTAKEN 12
+#define R_PPC_REL14_BRNTAKEN 13
+#define R_PPC_GOT16 14
+#define R_PPC_GOT16_LO 15
+#define R_PPC_GOT16_HI 16
+#define R_PPC_GOT16_HA 17
+#define R_PPC_PLTREL24 18
+#define R_PPC_COPY 19
+#define R_PPC_GLOB_DAT 20
+#define R_PPC_JMP_SLOT 21
+#define R_PPC_RELATIVE 22
+#define R_PPC_LOCAL24PC 23
+#define R_PPC_UADDR32 24
+#define R_PPC_UADDR16 25
+#define R_PPC_REL32 26
+#define R_PPC_PLT32 27
+#define R_PPC_PLTREL32 28
+#define R_PPC_PLT16_LO 29
+#define R_PPC_PLT16_HI 30
+#define R_PPC_PLT16_HA 31
+#define R_PPC_SDAREL16 32
+#define R_PPC_SECTOFF 33
+#define R_PPC_SECTOFF_LO 34
+#define R_PPC_SECTOFF_HI 35
+#define R_PPC_SECTOFF_HA 36
+
+
+#define R_PPC_TLS 67
+#define R_PPC_DTPMOD32 68
+#define R_PPC_TPREL16 69
+#define R_PPC_TPREL16_LO 70
+#define R_PPC_TPREL16_HI 71
+#define R_PPC_TPREL16_HA 72
+#define R_PPC_TPREL32 73
+#define R_PPC_DTPREL16 74
+#define R_PPC_DTPREL16_LO 75
+#define R_PPC_DTPREL16_HI 76
+#define R_PPC_DTPREL16_HA 77
+#define R_PPC_DTPREL32 78
+#define R_PPC_GOT_TLSGD16 79
+#define R_PPC_GOT_TLSGD16_LO 80
+#define R_PPC_GOT_TLSGD16_HI 81
+#define R_PPC_GOT_TLSGD16_HA 82
+#define R_PPC_GOT_TLSLD16 83
+#define R_PPC_GOT_TLSLD16_LO 84
+#define R_PPC_GOT_TLSLD16_HI 85
+#define R_PPC_GOT_TLSLD16_HA 86
+#define R_PPC_GOT_TPREL16 87
+#define R_PPC_GOT_TPREL16_LO 88
+#define R_PPC_GOT_TPREL16_HI 89
+#define R_PPC_GOT_TPREL16_HA 90
+#define R_PPC_GOT_DTPREL16 91
+#define R_PPC_GOT_DTPREL16_LO 92
+#define R_PPC_GOT_DTPREL16_HI 93
+#define R_PPC_GOT_DTPREL16_HA 94
+#define R_PPC_TLSGD 95
+#define R_PPC_TLSLD 96
+
+
+#define R_PPC_EMB_NADDR32 101
+#define R_PPC_EMB_NADDR16 102
+#define R_PPC_EMB_NADDR16_LO 103
+#define R_PPC_EMB_NADDR16_HI 104
+#define R_PPC_EMB_NADDR16_HA 105
+#define R_PPC_EMB_SDAI16 106
+#define R_PPC_EMB_SDA2I16 107
+#define R_PPC_EMB_SDA2REL 108
+#define R_PPC_EMB_SDA21 109
+#define R_PPC_EMB_MRKREF 110
+#define R_PPC_EMB_RELSEC16 111
+#define R_PPC_EMB_RELST_LO 112
+#define R_PPC_EMB_RELST_HI 113
+#define R_PPC_EMB_RELST_HA 114
+#define R_PPC_EMB_BIT_FLD 115
+#define R_PPC_EMB_RELSDA 116
+
+
+#define R_PPC_DIAB_SDA21_LO 180
+#define R_PPC_DIAB_SDA21_HI 181
+#define R_PPC_DIAB_SDA21_HA 182
+#define R_PPC_DIAB_RELSDA_LO 183
+#define R_PPC_DIAB_RELSDA_HI 184
+#define R_PPC_DIAB_RELSDA_HA 185
+
+
+#define R_PPC_IRELATIVE 248
+
+
+#define R_PPC_REL16 249
+#define R_PPC_REL16_LO 250
+#define R_PPC_REL16_HI 251
+#define R_PPC_REL16_HA 252
+
+
+
+#define R_PPC_TOC16 255
+
+
+#define DT_PPC_GOT (DT_LOPROC + 0)
+#define DT_PPC_OPT (DT_LOPROC + 1)
+#define DT_PPC_NUM 2
+
+#define PPC_OPT_TLS 1
+
+
+#define R_PPC64_NONE R_PPC_NONE
+#define R_PPC64_ADDR32 R_PPC_ADDR32
+#define R_PPC64_ADDR24 R_PPC_ADDR24
+#define R_PPC64_ADDR16 R_PPC_ADDR16
+#define R_PPC64_ADDR16_LO R_PPC_ADDR16_LO
+#define R_PPC64_ADDR16_HI R_PPC_ADDR16_HI
+#define R_PPC64_ADDR16_HA R_PPC_ADDR16_HA
+#define R_PPC64_ADDR14 R_PPC_ADDR14
+#define R_PPC64_ADDR14_BRTAKEN R_PPC_ADDR14_BRTAKEN
+#define R_PPC64_ADDR14_BRNTAKEN R_PPC_ADDR14_BRNTAKEN
+#define R_PPC64_REL24 R_PPC_REL24
+#define R_PPC64_REL14 R_PPC_REL14
+#define R_PPC64_REL14_BRTAKEN R_PPC_REL14_BRTAKEN
+#define R_PPC64_REL14_BRNTAKEN R_PPC_REL14_BRNTAKEN
+#define R_PPC64_GOT16 R_PPC_GOT16
+#define R_PPC64_GOT16_LO R_PPC_GOT16_LO
+#define R_PPC64_GOT16_HI R_PPC_GOT16_HI
+#define R_PPC64_GOT16_HA R_PPC_GOT16_HA
+
+#define R_PPC64_COPY R_PPC_COPY
+#define R_PPC64_GLOB_DAT R_PPC_GLOB_DAT
+#define R_PPC64_JMP_SLOT R_PPC_JMP_SLOT
+#define R_PPC64_RELATIVE R_PPC_RELATIVE
+
+#define R_PPC64_UADDR32 R_PPC_UADDR32
+#define R_PPC64_UADDR16 R_PPC_UADDR16
+#define R_PPC64_REL32 R_PPC_REL32
+#define R_PPC64_PLT32 R_PPC_PLT32
+#define R_PPC64_PLTREL32 R_PPC_PLTREL32
+#define R_PPC64_PLT16_LO R_PPC_PLT16_LO
+#define R_PPC64_PLT16_HI R_PPC_PLT16_HI
+#define R_PPC64_PLT16_HA R_PPC_PLT16_HA
+
+#define R_PPC64_SECTOFF R_PPC_SECTOFF
+#define R_PPC64_SECTOFF_LO R_PPC_SECTOFF_LO
+#define R_PPC64_SECTOFF_HI R_PPC_SECTOFF_HI
+#define R_PPC64_SECTOFF_HA R_PPC_SECTOFF_HA
+#define R_PPC64_ADDR30 37
+#define R_PPC64_ADDR64 38
+#define R_PPC64_ADDR16_HIGHER 39
+#define R_PPC64_ADDR16_HIGHERA 40
+#define R_PPC64_ADDR16_HIGHEST 41
+#define R_PPC64_ADDR16_HIGHESTA 42
+#define R_PPC64_UADDR64 43
+#define R_PPC64_REL64 44
+#define R_PPC64_PLT64 45
+#define R_PPC64_PLTREL64 46
+#define R_PPC64_TOC16 47
+#define R_PPC64_TOC16_LO 48
+#define R_PPC64_TOC16_HI 49
+#define R_PPC64_TOC16_HA 50
+#define R_PPC64_TOC 51
+#define R_PPC64_PLTGOT16 52
+#define R_PPC64_PLTGOT16_LO 53
+#define R_PPC64_PLTGOT16_HI 54
+#define R_PPC64_PLTGOT16_HA 55
+
+#define R_PPC64_ADDR16_DS 56
+#define R_PPC64_ADDR16_LO_DS 57
+#define R_PPC64_GOT16_DS 58
+#define R_PPC64_GOT16_LO_DS 59
+#define R_PPC64_PLT16_LO_DS 60
+#define R_PPC64_SECTOFF_DS 61
+#define R_PPC64_SECTOFF_LO_DS 62
+#define R_PPC64_TOC16_DS 63
+#define R_PPC64_TOC16_LO_DS 64
+#define R_PPC64_PLTGOT16_DS 65
+#define R_PPC64_PLTGOT16_LO_DS 66
+
+
+#define R_PPC64_TLS 67
+#define R_PPC64_DTPMOD64 68
+#define R_PPC64_TPREL16 69
+#define R_PPC64_TPREL16_LO 70
+#define R_PPC64_TPREL16_HI 71
+#define R_PPC64_TPREL16_HA 72
+#define R_PPC64_TPREL64 73
+#define R_PPC64_DTPREL16 74
+#define R_PPC64_DTPREL16_LO 75
+#define R_PPC64_DTPREL16_HI 76
+#define R_PPC64_DTPREL16_HA 77
+#define R_PPC64_DTPREL64 78
+#define R_PPC64_GOT_TLSGD16 79
+#define R_PPC64_GOT_TLSGD16_LO 80
+#define R_PPC64_GOT_TLSGD16_HI 81
+#define R_PPC64_GOT_TLSGD16_HA 82
+#define R_PPC64_GOT_TLSLD16 83
+#define R_PPC64_GOT_TLSLD16_LO 84
+#define R_PPC64_GOT_TLSLD16_HI 85
+#define R_PPC64_GOT_TLSLD16_HA 86
+#define R_PPC64_GOT_TPREL16_DS 87
+#define R_PPC64_GOT_TPREL16_LO_DS 88
+#define R_PPC64_GOT_TPREL16_HI 89
+#define R_PPC64_GOT_TPREL16_HA 90
+#define R_PPC64_GOT_DTPREL16_DS 91
+#define R_PPC64_GOT_DTPREL16_LO_DS 92
+#define R_PPC64_GOT_DTPREL16_HI 93
+#define R_PPC64_GOT_DTPREL16_HA 94
+#define R_PPC64_TPREL16_DS 95
+#define R_PPC64_TPREL16_LO_DS 96
+#define R_PPC64_TPREL16_HIGHER 97
+#define R_PPC64_TPREL16_HIGHERA 98
+#define R_PPC64_TPREL16_HIGHEST 99
+#define R_PPC64_TPREL16_HIGHESTA 100
+#define R_PPC64_DTPREL16_DS 101
+#define R_PPC64_DTPREL16_LO_DS 102
+#define R_PPC64_DTPREL16_HIGHER 103
+#define R_PPC64_DTPREL16_HIGHERA 104
+#define R_PPC64_DTPREL16_HIGHEST 105
+#define R_PPC64_DTPREL16_HIGHESTA 106
+#define R_PPC64_TLSGD 107
+#define R_PPC64_TLSLD 108
+#define R_PPC64_TOCSAVE 109
+#define R_PPC64_ADDR16_HIGH 110
+#define R_PPC64_ADDR16_HIGHA 111
+#define R_PPC64_TPREL16_HIGH 112
+#define R_PPC64_TPREL16_HIGHA 113
+#define R_PPC64_DTPREL16_HIGH 114
+#define R_PPC64_DTPREL16_HIGHA 115
+
+
+#define R_PPC64_JMP_IREL 247
+#define R_PPC64_IRELATIVE 248
+#define R_PPC64_REL16 249
+#define R_PPC64_REL16_LO 250
+#define R_PPC64_REL16_HI 251
+#define R_PPC64_REL16_HA 252
+
+#define EF_PPC64_ABI 3
+
+#define DT_PPC64_GLINK (DT_LOPROC + 0)
+#define DT_PPC64_OPD (DT_LOPROC + 1)
+#define DT_PPC64_OPDSZ (DT_LOPROC + 2)
+#define DT_PPC64_OPT (DT_LOPROC + 3)
+#define DT_PPC64_NUM 4
+
+#define PPC64_OPT_TLS 1
+#define PPC64_OPT_MULTI_TOC 2
+#define PPC64_OPT_LOCALENTRY 4
+
+#define STO_PPC64_LOCAL_BIT 5
+#define STO_PPC64_LOCAL_MASK 0xe0
+#define PPC64_LOCAL_ENTRY_OFFSET(x) (1 << (((x)&0xe0)>>5) & 0xfc)
+
+
+#define EF_ARM_RELEXEC 0x01
+#define EF_ARM_HASENTRY 0x02
+#define EF_ARM_INTERWORK 0x04
+#define EF_ARM_APCS_26 0x08
+#define EF_ARM_APCS_FLOAT 0x10
+#define EF_ARM_PIC 0x20
+#define EF_ARM_ALIGN8 0x40
+#define EF_ARM_NEW_ABI 0x80
+#define EF_ARM_OLD_ABI 0x100
+#define EF_ARM_SOFT_FLOAT 0x200
+#define EF_ARM_VFP_FLOAT 0x400
+#define EF_ARM_MAVERICK_FLOAT 0x800
+
+#define EF_ARM_ABI_FLOAT_SOFT 0x200
+#define EF_ARM_ABI_FLOAT_HARD 0x400
+
+
+#define EF_ARM_SYMSARESORTED 0x04
+#define EF_ARM_DYNSYMSUSESEGIDX 0x08
+#define EF_ARM_MAPSYMSFIRST 0x10
+#define EF_ARM_EABIMASK 0XFF000000
+
+
+#define EF_ARM_BE8 0x00800000
+#define EF_ARM_LE8 0x00400000
+
+#define EF_ARM_EABI_VERSION(flags) ((flags) & EF_ARM_EABIMASK)
+#define EF_ARM_EABI_UNKNOWN 0x00000000
+#define EF_ARM_EABI_VER1 0x01000000
+#define EF_ARM_EABI_VER2 0x02000000
+#define EF_ARM_EABI_VER3 0x03000000
+#define EF_ARM_EABI_VER4 0x04000000
+#define EF_ARM_EABI_VER5 0x05000000
+
+
+#define STT_ARM_TFUNC STT_LOPROC
+#define STT_ARM_16BIT STT_HIPROC
+
+
+#define SHF_ARM_ENTRYSECT 0x10000000
+#define SHF_ARM_COMDEF 0x80000000
+
+
+
+#define PF_ARM_SB 0x10000000
+
+#define PF_ARM_PI 0x20000000
+#define PF_ARM_ABS 0x40000000
+
+
+#define PT_ARM_EXIDX (PT_LOPROC + 1)
+
+
+#define SHT_ARM_EXIDX (SHT_LOPROC + 1)
+#define SHT_ARM_PREEMPTMAP (SHT_LOPROC + 2)
+#define SHT_ARM_ATTRIBUTES (SHT_LOPROC + 3)
+
+#define R_AARCH64_NONE 0
+#define R_AARCH64_P32_ABS32 1
+#define R_AARCH64_P32_COPY 180
+#define R_AARCH64_P32_GLOB_DAT 181
+#define R_AARCH64_P32_JUMP_SLOT 182
+#define R_AARCH64_P32_RELATIVE 183
+#define R_AARCH64_P32_TLS_DTPMOD 184
+#define R_AARCH64_P32_TLS_DTPREL 185
+#define R_AARCH64_P32_TLS_TPREL 186
+#define R_AARCH64_P32_TLSDESC 187
+#define R_AARCH64_P32_IRELATIVE 188
+#define R_AARCH64_ABS64 257
+#define R_AARCH64_ABS32 258
+#define R_AARCH64_ABS16 259
+#define R_AARCH64_PREL64 260
+#define R_AARCH64_PREL32 261
+#define R_AARCH64_PREL16 262
+#define R_AARCH64_MOVW_UABS_G0 263
+#define R_AARCH64_MOVW_UABS_G0_NC 264
+#define R_AARCH64_MOVW_UABS_G1 265
+#define R_AARCH64_MOVW_UABS_G1_NC 266
+#define R_AARCH64_MOVW_UABS_G2 267
+#define R_AARCH64_MOVW_UABS_G2_NC 268
+#define R_AARCH64_MOVW_UABS_G3 269
+#define R_AARCH64_MOVW_SABS_G0 270
+#define R_AARCH64_MOVW_SABS_G1 271
+#define R_AARCH64_MOVW_SABS_G2 272
+#define R_AARCH64_LD_PREL_LO19 273
+#define R_AARCH64_ADR_PREL_LO21 274
+#define R_AARCH64_ADR_PREL_PG_HI21 275
+#define R_AARCH64_ADR_PREL_PG_HI21_NC 276
+#define R_AARCH64_ADD_ABS_LO12_NC 277
+#define R_AARCH64_LDST8_ABS_LO12_NC 278
+#define R_AARCH64_TSTBR14 279
+#define R_AARCH64_CONDBR19 280
+#define R_AARCH64_JUMP26 282
+#define R_AARCH64_CALL26 283
+#define R_AARCH64_LDST16_ABS_LO12_NC 284
+#define R_AARCH64_LDST32_ABS_LO12_NC 285
+#define R_AARCH64_LDST64_ABS_LO12_NC 286
+#define R_AARCH64_MOVW_PREL_G0 287
+#define R_AARCH64_MOVW_PREL_G0_NC 288
+#define R_AARCH64_MOVW_PREL_G1 289
+#define R_AARCH64_MOVW_PREL_G1_NC 290
+#define R_AARCH64_MOVW_PREL_G2 291
+#define R_AARCH64_MOVW_PREL_G2_NC 292
+#define R_AARCH64_MOVW_PREL_G3 293
+#define R_AARCH64_LDST128_ABS_LO12_NC 299
+#define R_AARCH64_MOVW_GOTOFF_G0 300
+#define R_AARCH64_MOVW_GOTOFF_G0_NC 301
+#define R_AARCH64_MOVW_GOTOFF_G1 302
+#define R_AARCH64_MOVW_GOTOFF_G1_NC 303
+#define R_AARCH64_MOVW_GOTOFF_G2 304
+#define R_AARCH64_MOVW_GOTOFF_G2_NC 305
+#define R_AARCH64_MOVW_GOTOFF_G3 306
+#define R_AARCH64_GOTREL64 307
+#define R_AARCH64_GOTREL32 308
+#define R_AARCH64_GOT_LD_PREL19 309
+#define R_AARCH64_LD64_GOTOFF_LO15 310
+#define R_AARCH64_ADR_GOT_PAGE 311
+#define R_AARCH64_LD64_GOT_LO12_NC 312
+#define R_AARCH64_LD64_GOTPAGE_LO15 313
+#define R_AARCH64_TLSGD_ADR_PREL21 512
+#define R_AARCH64_TLSGD_ADR_PAGE21 513
+#define R_AARCH64_TLSGD_ADD_LO12_NC 514
+#define R_AARCH64_TLSGD_MOVW_G1 515
+#define R_AARCH64_TLSGD_MOVW_G0_NC 516
+#define R_AARCH64_TLSLD_ADR_PREL21 517
+#define R_AARCH64_TLSLD_ADR_PAGE21 518
+#define R_AARCH64_TLSLD_ADD_LO12_NC 519
+#define R_AARCH64_TLSLD_MOVW_G1 520
+#define R_AARCH64_TLSLD_MOVW_G0_NC 521
+#define R_AARCH64_TLSLD_LD_PREL19 522
+#define R_AARCH64_TLSLD_MOVW_DTPREL_G2 523
+#define R_AARCH64_TLSLD_MOVW_DTPREL_G1 524
+#define R_AARCH64_TLSLD_MOVW_DTPREL_G1_NC 525
+#define R_AARCH64_TLSLD_MOVW_DTPREL_G0 526
+#define R_AARCH64_TLSLD_MOVW_DTPREL_G0_NC 527
+#define R_AARCH64_TLSLD_ADD_DTPREL_HI12 528
+#define R_AARCH64_TLSLD_ADD_DTPREL_LO12 529
+#define R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC 530
+#define R_AARCH64_TLSLD_LDST8_DTPREL_LO12 531
+#define R_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC 532
+#define R_AARCH64_TLSLD_LDST16_DTPREL_LO12 533
+#define R_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC 534
+#define R_AARCH64_TLSLD_LDST32_DTPREL_LO12 535
+#define R_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC 536
+#define R_AARCH64_TLSLD_LDST64_DTPREL_LO12 537
+#define R_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC 538
+#define R_AARCH64_TLSIE_MOVW_GOTTPREL_G1 539
+#define R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC 540
+#define R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21 541
+#define R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC 542
+#define R_AARCH64_TLSIE_LD_GOTTPREL_PREL19 543
+#define R_AARCH64_TLSLE_MOVW_TPREL_G2 544
+#define R_AARCH64_TLSLE_MOVW_TPREL_G1 545
+#define R_AARCH64_TLSLE_MOVW_TPREL_G1_NC 546
+#define R_AARCH64_TLSLE_MOVW_TPREL_G0 547
+#define R_AARCH64_TLSLE_MOVW_TPREL_G0_NC 548
+#define R_AARCH64_TLSLE_ADD_TPREL_HI12 549
+#define R_AARCH64_TLSLE_ADD_TPREL_LO12 550
+#define R_AARCH64_TLSLE_ADD_TPREL_LO12_NC 551
+#define R_AARCH64_TLSLE_LDST8_TPREL_LO12 552
+#define R_AARCH64_TLSLE_LDST8_TPREL_LO12_NC 553
+#define R_AARCH64_TLSLE_LDST16_TPREL_LO12 554
+#define R_AARCH64_TLSLE_LDST16_TPREL_LO12_NC 555
+#define R_AARCH64_TLSLE_LDST32_TPREL_LO12 556
+#define R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC 557
+#define R_AARCH64_TLSLE_LDST64_TPREL_LO12 558
+#define R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC 559
+#define R_AARCH64_TLSDESC_LD_PREL19 560
+#define R_AARCH64_TLSDESC_ADR_PREL21 561
+#define R_AARCH64_TLSDESC_ADR_PAGE21 562
+#define R_AARCH64_TLSDESC_LD64_LO12 563
+#define R_AARCH64_TLSDESC_ADD_LO12 564
+#define R_AARCH64_TLSDESC_OFF_G1 565
+#define R_AARCH64_TLSDESC_OFF_G0_NC 566
+#define R_AARCH64_TLSDESC_LDR 567
+#define R_AARCH64_TLSDESC_ADD 568
+#define R_AARCH64_TLSDESC_CALL 569
+#define R_AARCH64_TLSLE_LDST128_TPREL_LO12 570
+#define R_AARCH64_TLSLE_LDST128_TPREL_LO12_NC 571
+#define R_AARCH64_TLSLD_LDST128_DTPREL_LO12 572
+#define R_AARCH64_TLSLD_LDST128_DTPREL_LO12_NC 573
+#define R_AARCH64_COPY 1024
+#define R_AARCH64_GLOB_DAT 1025
+#define R_AARCH64_JUMP_SLOT 1026
+#define R_AARCH64_RELATIVE 1027
+#define R_AARCH64_TLS_DTPMOD 1028
+#define R_AARCH64_TLS_DTPMOD64 1028
+#define R_AARCH64_TLS_DTPREL 1029
+#define R_AARCH64_TLS_DTPREL64 1029
+#define R_AARCH64_TLS_TPREL 1030
+#define R_AARCH64_TLS_TPREL64 1030
+#define R_AARCH64_TLSDESC 1031
+
+
+#define R_ARM_NONE 0
+#define R_ARM_PC24 1
+#define R_ARM_ABS32 2
+#define R_ARM_REL32 3
+#define R_ARM_PC13 4
+#define R_ARM_ABS16 5
+#define R_ARM_ABS12 6
+#define R_ARM_THM_ABS5 7
+#define R_ARM_ABS8 8
+#define R_ARM_SBREL32 9
+#define R_ARM_THM_PC22 10
+#define R_ARM_THM_PC8 11
+#define R_ARM_AMP_VCALL9 12
+#define R_ARM_TLS_DESC 13
+#define R_ARM_THM_SWI8 14
+#define R_ARM_XPC25 15
+#define R_ARM_THM_XPC22 16
+#define R_ARM_TLS_DTPMOD32 17
+#define R_ARM_TLS_DTPOFF32 18
+#define R_ARM_TLS_TPOFF32 19
+#define R_ARM_COPY 20
+#define R_ARM_GLOB_DAT 21
+#define R_ARM_JUMP_SLOT 22
+#define R_ARM_RELATIVE 23
+#define R_ARM_GOTOFF 24
+#define R_ARM_GOTPC 25
+#define R_ARM_GOT32 26
+#define R_ARM_PLT32 27
+#define R_ARM_CALL 28
+#define R_ARM_JUMP24 29
+#define R_ARM_THM_JUMP24 30
+#define R_ARM_BASE_ABS 31
+#define R_ARM_ALU_PCREL_7_0 32
+#define R_ARM_ALU_PCREL_15_8 33
+#define R_ARM_ALU_PCREL_23_15 34
+#define R_ARM_LDR_SBREL_11_0 35
+#define R_ARM_ALU_SBREL_19_12 36
+#define R_ARM_ALU_SBREL_27_20 37
+#define R_ARM_TARGET1 38
+#define R_ARM_SBREL31 39
+#define R_ARM_V4BX 40
+#define R_ARM_TARGET2 41
+#define R_ARM_PREL31 42
+#define R_ARM_MOVW_ABS_NC 43
+#define R_ARM_MOVT_ABS 44
+#define R_ARM_MOVW_PREL_NC 45
+#define R_ARM_MOVT_PREL 46
+#define R_ARM_THM_MOVW_ABS_NC 47
+#define R_ARM_THM_MOVT_ABS 48
+#define R_ARM_THM_MOVW_PREL_NC 49
+#define R_ARM_THM_MOVT_PREL 50
+#define R_ARM_THM_JUMP19 51
+#define R_ARM_THM_JUMP6 52
+#define R_ARM_THM_ALU_PREL_11_0 53
+#define R_ARM_THM_PC12 54
+#define R_ARM_ABS32_NOI 55
+#define R_ARM_REL32_NOI 56
+#define R_ARM_ALU_PC_G0_NC 57
+#define R_ARM_ALU_PC_G0 58
+#define R_ARM_ALU_PC_G1_NC 59
+#define R_ARM_ALU_PC_G1 60
+#define R_ARM_ALU_PC_G2 61
+#define R_ARM_LDR_PC_G1 62
+#define R_ARM_LDR_PC_G2 63
+#define R_ARM_LDRS_PC_G0 64
+#define R_ARM_LDRS_PC_G1 65
+#define R_ARM_LDRS_PC_G2 66
+#define R_ARM_LDC_PC_G0 67
+#define R_ARM_LDC_PC_G1 68
+#define R_ARM_LDC_PC_G2 69
+#define R_ARM_ALU_SB_G0_NC 70
+#define R_ARM_ALU_SB_G0 71
+#define R_ARM_ALU_SB_G1_NC 72
+#define R_ARM_ALU_SB_G1 73
+#define R_ARM_ALU_SB_G2 74
+#define R_ARM_LDR_SB_G0 75
+#define R_ARM_LDR_SB_G1 76
+#define R_ARM_LDR_SB_G2 77
+#define R_ARM_LDRS_SB_G0 78
+#define R_ARM_LDRS_SB_G1 79
+#define R_ARM_LDRS_SB_G2 80
+#define R_ARM_LDC_SB_G0 81
+#define R_ARM_LDC_SB_G1 82
+#define R_ARM_LDC_SB_G2 83
+#define R_ARM_MOVW_BREL_NC 84
+#define R_ARM_MOVT_BREL 85
+#define R_ARM_MOVW_BREL 86
+#define R_ARM_THM_MOVW_BREL_NC 87
+#define R_ARM_THM_MOVT_BREL 88
+#define R_ARM_THM_MOVW_BREL 89
+#define R_ARM_TLS_GOTDESC 90
+#define R_ARM_TLS_CALL 91
+#define R_ARM_TLS_DESCSEQ 92
+#define R_ARM_THM_TLS_CALL 93
+#define R_ARM_PLT32_ABS 94
+#define R_ARM_GOT_ABS 95
+#define R_ARM_GOT_PREL 96
+#define R_ARM_GOT_BREL12 97
+#define R_ARM_GOTOFF12 98
+#define R_ARM_GOTRELAX 99
+#define R_ARM_GNU_VTENTRY 100
+#define R_ARM_GNU_VTINHERIT 101
+#define R_ARM_THM_PC11 102
+#define R_ARM_THM_PC9 103
+#define R_ARM_TLS_GD32 104
+
+#define R_ARM_TLS_LDM32 105
+
+#define R_ARM_TLS_LDO32 106
+
+#define R_ARM_TLS_IE32 107
+
+#define R_ARM_TLS_LE32 108
+#define R_ARM_TLS_LDO12 109
+#define R_ARM_TLS_LE12 110
+#define R_ARM_TLS_IE12GP 111
+#define R_ARM_ME_TOO 128
+#define R_ARM_THM_TLS_DESCSEQ 129
+#define R_ARM_THM_TLS_DESCSEQ16 129
+#define R_ARM_THM_TLS_DESCSEQ32 130
+#define R_ARM_THM_GOT_BREL12 131
+#define R_ARM_IRELATIVE 160
+#define R_ARM_RXPC25 249
+#define R_ARM_RSBREL32 250
+#define R_ARM_THM_RPC22 251
+#define R_ARM_RREL32 252
+#define R_ARM_RABS22 253
+#define R_ARM_RPC24 254
+#define R_ARM_RBASE 255
+
+#define R_ARM_NUM 256
+
+
+#define R_CKCORE_NONE 0
+#define R_CKCORE_ADDR32 1
+#define R_CKCORE_PCRELIMM8BY4 2
+#define R_CKCORE_PCRELIMM11BY2 3
+#define R_CKCORE_PCREL32 5
+#define R_CKCORE_PCRELJSR_IMM11BY2 6
+#define R_CKCORE_RELATIVE 9
+#define R_CKCORE_COPY 10
+#define R_CKCORE_GLOB_DAT 11
+#define R_CKCORE_JUMP_SLOT 12
+#define R_CKCORE_GOTOFF 13
+#define R_CKCORE_GOTPC 14
+#define R_CKCORE_GOT32 15
+#define R_CKCORE_PLT32 16
+#define R_CKCORE_ADDRGOT 17
+#define R_CKCORE_ADDRPLT 18
+#define R_CKCORE_PCREL_IMM26BY2 19
+#define R_CKCORE_PCREL_IMM16BY2 20
+#define R_CKCORE_PCREL_IMM16BY4 21
+#define R_CKCORE_PCREL_IMM10BY2 22
+#define R_CKCORE_PCREL_IMM10BY4 23
+#define R_CKCORE_ADDR_HI16 24
+#define R_CKCORE_ADDR_LO16 25
+#define R_CKCORE_GOTPC_HI16 26
+#define R_CKCORE_GOTPC_LO16 27
+#define R_CKCORE_GOTOFF_HI16 28
+#define R_CKCORE_GOTOFF_LO16 29
+#define R_CKCORE_GOT12 30
+#define R_CKCORE_GOT_HI16 31
+#define R_CKCORE_GOT_LO16 32
+#define R_CKCORE_PLT12 33
+#define R_CKCORE_PLT_HI16 34
+#define R_CKCORE_PLT_LO16 35
+#define R_CKCORE_ADDRGOT_HI16 36
+#define R_CKCORE_ADDRGOT_LO16 37
+#define R_CKCORE_ADDRPLT_HI16 38
+#define R_CKCORE_ADDRPLT_LO16 39
+#define R_CKCORE_PCREL_JSR_IMM26BY2 40
+#define R_CKCORE_TOFFSET_LO16 41
+#define R_CKCORE_DOFFSET_LO16 42
+#define R_CKCORE_PCREL_IMM18BY2 43
+#define R_CKCORE_DOFFSET_IMM18 44
+#define R_CKCORE_DOFFSET_IMM18BY2 45
+#define R_CKCORE_DOFFSET_IMM18BY4 46
+#define R_CKCORE_GOT_IMM18BY4 48
+#define R_CKCORE_PLT_IMM18BY4 49
+#define R_CKCORE_PCREL_IMM7BY4 50
+#define R_CKCORE_TLS_LE32 51
+#define R_CKCORE_TLS_IE32 52
+#define R_CKCORE_TLS_GD32 53
+#define R_CKCORE_TLS_LDM32 54
+#define R_CKCORE_TLS_LDO32 55
+#define R_CKCORE_TLS_DTPMOD32 56
+#define R_CKCORE_TLS_DTPOFF32 57
+#define R_CKCORE_TLS_TPOFF32 58
+
+
+#define EF_IA_64_MASKOS 0x0000000f
+#define EF_IA_64_ABI64 0x00000010
+#define EF_IA_64_ARCH 0xff000000
+
+
+#define PT_IA_64_ARCHEXT (PT_LOPROC + 0)
+#define PT_IA_64_UNWIND (PT_LOPROC + 1)
+#define PT_IA_64_HP_OPT_ANOT (PT_LOOS + 0x12)
+#define PT_IA_64_HP_HSL_ANOT (PT_LOOS + 0x13)
+#define PT_IA_64_HP_STACK (PT_LOOS + 0x14)
+
+
+#define PF_IA_64_NORECOV 0x80000000
+
+
+#define SHT_IA_64_EXT (SHT_LOPROC + 0)
+#define SHT_IA_64_UNWIND (SHT_LOPROC + 1)
+
+
+#define SHF_IA_64_SHORT 0x10000000
+#define SHF_IA_64_NORECOV 0x20000000
+
+
+#define DT_IA_64_PLT_RESERVE (DT_LOPROC + 0)
+#define DT_IA_64_NUM 1
+
+
+#define R_IA64_NONE 0x00
+#define R_IA64_IMM14 0x21
+#define R_IA64_IMM22 0x22
+#define R_IA64_IMM64 0x23
+#define R_IA64_DIR32MSB 0x24
+#define R_IA64_DIR32LSB 0x25
+#define R_IA64_DIR64MSB 0x26
+#define R_IA64_DIR64LSB 0x27
+#define R_IA64_GPREL22 0x2a
+#define R_IA64_GPREL64I 0x2b
+#define R_IA64_GPREL32MSB 0x2c
+#define R_IA64_GPREL32LSB 0x2d
+#define R_IA64_GPREL64MSB 0x2e
+#define R_IA64_GPREL64LSB 0x2f
+#define R_IA64_LTOFF22 0x32
+#define R_IA64_LTOFF64I 0x33
+#define R_IA64_PLTOFF22 0x3a
+#define R_IA64_PLTOFF64I 0x3b
+#define R_IA64_PLTOFF64MSB 0x3e
+#define R_IA64_PLTOFF64LSB 0x3f
+#define R_IA64_FPTR64I 0x43
+#define R_IA64_FPTR32MSB 0x44
+#define R_IA64_FPTR32LSB 0x45
+#define R_IA64_FPTR64MSB 0x46
+#define R_IA64_FPTR64LSB 0x47
+#define R_IA64_PCREL60B 0x48
+#define R_IA64_PCREL21B 0x49
+#define R_IA64_PCREL21M 0x4a
+#define R_IA64_PCREL21F 0x4b
+#define R_IA64_PCREL32MSB 0x4c
+#define R_IA64_PCREL32LSB 0x4d
+#define R_IA64_PCREL64MSB 0x4e
+#define R_IA64_PCREL64LSB 0x4f
+#define R_IA64_LTOFF_FPTR22 0x52
+#define R_IA64_LTOFF_FPTR64I 0x53
+#define R_IA64_LTOFF_FPTR32MSB 0x54
+#define R_IA64_LTOFF_FPTR32LSB 0x55
+#define R_IA64_LTOFF_FPTR64MSB 0x56
+#define R_IA64_LTOFF_FPTR64LSB 0x57
+#define R_IA64_SEGREL32MSB 0x5c
+#define R_IA64_SEGREL32LSB 0x5d
+#define R_IA64_SEGREL64MSB 0x5e
+#define R_IA64_SEGREL64LSB 0x5f
+#define R_IA64_SECREL32MSB 0x64
+#define R_IA64_SECREL32LSB 0x65
+#define R_IA64_SECREL64MSB 0x66
+#define R_IA64_SECREL64LSB 0x67
+#define R_IA64_REL32MSB 0x6c
+#define R_IA64_REL32LSB 0x6d
+#define R_IA64_REL64MSB 0x6e
+#define R_IA64_REL64LSB 0x6f
+#define R_IA64_LTV32MSB 0x74
+#define R_IA64_LTV32LSB 0x75
+#define R_IA64_LTV64MSB 0x76
+#define R_IA64_LTV64LSB 0x77
+#define R_IA64_PCREL21BI 0x79
+#define R_IA64_PCREL22 0x7a
+#define R_IA64_PCREL64I 0x7b
+#define R_IA64_IPLTMSB 0x80
+#define R_IA64_IPLTLSB 0x81
+#define R_IA64_COPY 0x84
+#define R_IA64_SUB 0x85
+#define R_IA64_LTOFF22X 0x86
+#define R_IA64_LDXMOV 0x87
+#define R_IA64_TPREL14 0x91
+#define R_IA64_TPREL22 0x92
+#define R_IA64_TPREL64I 0x93
+#define R_IA64_TPREL64MSB 0x96
+#define R_IA64_TPREL64LSB 0x97
+#define R_IA64_LTOFF_TPREL22 0x9a
+#define R_IA64_DTPMOD64MSB 0xa6
+#define R_IA64_DTPMOD64LSB 0xa7
+#define R_IA64_LTOFF_DTPMOD22 0xaa
+#define R_IA64_DTPREL14 0xb1
+#define R_IA64_DTPREL22 0xb2
+#define R_IA64_DTPREL64I 0xb3
+#define R_IA64_DTPREL32MSB 0xb4
+#define R_IA64_DTPREL32LSB 0xb5
+#define R_IA64_DTPREL64MSB 0xb6
+#define R_IA64_DTPREL64LSB 0xb7
+#define R_IA64_LTOFF_DTPREL22 0xba
+
+
+#define EF_SH_MACH_MASK 0x1f
+#define EF_SH_UNKNOWN 0x0
+#define EF_SH1 0x1
+#define EF_SH2 0x2
+#define EF_SH3 0x3
+#define EF_SH_DSP 0x4
+#define EF_SH3_DSP 0x5
+#define EF_SH4AL_DSP 0x6
+#define EF_SH3E 0x8
+#define EF_SH4 0x9
+#define EF_SH2E 0xb
+#define EF_SH4A 0xc
+#define EF_SH2A 0xd
+#define EF_SH4_NOFPU 0x10
+#define EF_SH4A_NOFPU 0x11
+#define EF_SH4_NOMMU_NOFPU 0x12
+#define EF_SH2A_NOFPU 0x13
+#define EF_SH3_NOMMU 0x14
+#define EF_SH2A_SH4_NOFPU 0x15
+#define EF_SH2A_SH3_NOFPU 0x16
+#define EF_SH2A_SH4 0x17
+#define EF_SH2A_SH3E 0x18
+
+#define R_SH_NONE 0
+#define R_SH_DIR32 1
+#define R_SH_REL32 2
+#define R_SH_DIR8WPN 3
+#define R_SH_IND12W 4
+#define R_SH_DIR8WPL 5
+#define R_SH_DIR8WPZ 6
+#define R_SH_DIR8BP 7
+#define R_SH_DIR8W 8
+#define R_SH_DIR8L 9
+#define R_SH_SWITCH16 25
+#define R_SH_SWITCH32 26
+#define R_SH_USES 27
+#define R_SH_COUNT 28
+#define R_SH_ALIGN 29
+#define R_SH_CODE 30
+#define R_SH_DATA 31
+#define R_SH_LABEL 32
+#define R_SH_SWITCH8 33
+#define R_SH_GNU_VTINHERIT 34
+#define R_SH_GNU_VTENTRY 35
+#define R_SH_TLS_GD_32 144
+#define R_SH_TLS_LD_32 145
+#define R_SH_TLS_LDO_32 146
+#define R_SH_TLS_IE_32 147
+#define R_SH_TLS_LE_32 148
+#define R_SH_TLS_DTPMOD32 149
+#define R_SH_TLS_DTPOFF32 150
+#define R_SH_TLS_TPOFF32 151
+#define R_SH_GOT32 160
+#define R_SH_PLT32 161
+#define R_SH_COPY 162
+#define R_SH_GLOB_DAT 163
+#define R_SH_JMP_SLOT 164
+#define R_SH_RELATIVE 165
+#define R_SH_GOTOFF 166
+#define R_SH_GOTPC 167
+#define R_SH_GOT20 201
+#define R_SH_GOTOFF20 202
+#define R_SH_GOTFUNCDESC 203
+#define R_SH_GOTFUNCDEST20 204
+#define R_SH_GOTOFFFUNCDESC 205
+#define R_SH_GOTOFFFUNCDEST20 206
+#define R_SH_FUNCDESC 207
+#define R_SH_FUNCDESC_VALUE 208
+
+#define R_SH_NUM 256
+
+
+
+#define R_390_NONE 0
+#define R_390_8 1
+#define R_390_12 2
+#define R_390_16 3
+#define R_390_32 4
+#define R_390_PC32 5
+#define R_390_GOT12 6
+#define R_390_GOT32 7
+#define R_390_PLT32 8
+#define R_390_COPY 9
+#define R_390_GLOB_DAT 10
+#define R_390_JMP_SLOT 11
+#define R_390_RELATIVE 12
+#define R_390_GOTOFF32 13
+#define R_390_GOTPC 14
+#define R_390_GOT16 15
+#define R_390_PC16 16
+#define R_390_PC16DBL 17
+#define R_390_PLT16DBL 18
+#define R_390_PC32DBL 19
+#define R_390_PLT32DBL 20
+#define R_390_GOTPCDBL 21
+#define R_390_64 22
+#define R_390_PC64 23
+#define R_390_GOT64 24
+#define R_390_PLT64 25
+#define R_390_GOTENT 26
+#define R_390_GOTOFF16 27
+#define R_390_GOTOFF64 28
+#define R_390_GOTPLT12 29
+#define R_390_GOTPLT16 30
+#define R_390_GOTPLT32 31
+#define R_390_GOTPLT64 32
+#define R_390_GOTPLTENT 33
+#define R_390_PLTOFF16 34
+#define R_390_PLTOFF32 35
+#define R_390_PLTOFF64 36
+#define R_390_TLS_LOAD 37
+#define R_390_TLS_GDCALL 38
+
+#define R_390_TLS_LDCALL 39
+
+#define R_390_TLS_GD32 40
+
+#define R_390_TLS_GD64 41
+
+#define R_390_TLS_GOTIE12 42
+
+#define R_390_TLS_GOTIE32 43
+
+#define R_390_TLS_GOTIE64 44
+
+#define R_390_TLS_LDM32 45
+
+#define R_390_TLS_LDM64 46
+
+#define R_390_TLS_IE32 47
+
+#define R_390_TLS_IE64 48
+
+#define R_390_TLS_IEENT 49
+
+#define R_390_TLS_LE32 50
+
+#define R_390_TLS_LE64 51
+
+#define R_390_TLS_LDO32 52
+
+#define R_390_TLS_LDO64 53
+
+#define R_390_TLS_DTPMOD 54
+#define R_390_TLS_DTPOFF 55
+#define R_390_TLS_TPOFF 56
+
+#define R_390_20 57
+#define R_390_GOT20 58
+#define R_390_GOTPLT20 59
+#define R_390_TLS_GOTIE20 60
+
+
+#define R_390_NUM 61
+
+
+
+#define R_CRIS_NONE 0
+#define R_CRIS_8 1
+#define R_CRIS_16 2
+#define R_CRIS_32 3
+#define R_CRIS_8_PCREL 4
+#define R_CRIS_16_PCREL 5
+#define R_CRIS_32_PCREL 6
+#define R_CRIS_GNU_VTINHERIT 7
+#define R_CRIS_GNU_VTENTRY 8
+#define R_CRIS_COPY 9
+#define R_CRIS_GLOB_DAT 10
+#define R_CRIS_JUMP_SLOT 11
+#define R_CRIS_RELATIVE 12
+#define R_CRIS_16_GOT 13
+#define R_CRIS_32_GOT 14
+#define R_CRIS_16_GOTPLT 15
+#define R_CRIS_32_GOTPLT 16
+#define R_CRIS_32_GOTREL 17
+#define R_CRIS_32_PLT_GOTREL 18
+#define R_CRIS_32_PLT_PCREL 19
+
+#define R_CRIS_NUM 20
+
+
+
+#define R_X86_64_NONE 0
+#define R_X86_64_64 1
+#define R_X86_64_PC32 2
+#define R_X86_64_GOT32 3
+#define R_X86_64_PLT32 4
+#define R_X86_64_COPY 5
+#define R_X86_64_GLOB_DAT 6
+#define R_X86_64_JUMP_SLOT 7
+#define R_X86_64_RELATIVE 8
+#define R_X86_64_GOTPCREL 9
+
+#define R_X86_64_32 10
+#define R_X86_64_32S 11
+#define R_X86_64_16 12
+#define R_X86_64_PC16 13
+#define R_X86_64_8 14
+#define R_X86_64_PC8 15
+#define R_X86_64_DTPMOD64 16
+#define R_X86_64_DTPOFF64 17
+#define R_X86_64_TPOFF64 18
+#define R_X86_64_TLSGD 19
+
+#define R_X86_64_TLSLD 20
+
+#define R_X86_64_DTPOFF32 21
+#define R_X86_64_GOTTPOFF 22
+
+#define R_X86_64_TPOFF32 23
+#define R_X86_64_PC64 24
+#define R_X86_64_GOTOFF64 25
+#define R_X86_64_GOTPC32 26
+#define R_X86_64_GOT64 27
+#define R_X86_64_GOTPCREL64 28
+#define R_X86_64_GOTPC64 29
+#define R_X86_64_GOTPLT64 30
+#define R_X86_64_PLTOFF64 31
+#define R_X86_64_SIZE32 32
+#define R_X86_64_SIZE64 33
+
+#define R_X86_64_GOTPC32_TLSDESC 34
+#define R_X86_64_TLSDESC_CALL 35
+
+#define R_X86_64_TLSDESC 36
+#define R_X86_64_IRELATIVE 37
+#define R_X86_64_RELATIVE64 38
+#define R_X86_64_GOTPCRELX 41
+#define R_X86_64_REX_GOTPCRELX 42
+#define R_X86_64_NUM 43
+
+
+
+#define R_MN10300_NONE 0
+#define R_MN10300_32 1
+#define R_MN10300_16 2
+#define R_MN10300_8 3
+#define R_MN10300_PCREL32 4
+#define R_MN10300_PCREL16 5
+#define R_MN10300_PCREL8 6
+#define R_MN10300_GNU_VTINHERIT 7
+#define R_MN10300_GNU_VTENTRY 8
+#define R_MN10300_24 9
+#define R_MN10300_GOTPC32 10
+#define R_MN10300_GOTPC16 11
+#define R_MN10300_GOTOFF32 12
+#define R_MN10300_GOTOFF24 13
+#define R_MN10300_GOTOFF16 14
+#define R_MN10300_PLT32 15
+#define R_MN10300_PLT16 16
+#define R_MN10300_GOT32 17
+#define R_MN10300_GOT24 18
+#define R_MN10300_GOT16 19
+#define R_MN10300_COPY 20
+#define R_MN10300_GLOB_DAT 21
+#define R_MN10300_JMP_SLOT 22
+#define R_MN10300_RELATIVE 23
+
+#define R_MN10300_NUM 24
+
+
+
+#define R_M32R_NONE 0
+#define R_M32R_16 1
+#define R_M32R_32 2
+#define R_M32R_24 3
+#define R_M32R_10_PCREL 4
+#define R_M32R_18_PCREL 5
+#define R_M32R_26_PCREL 6
+#define R_M32R_HI16_ULO 7
+#define R_M32R_HI16_SLO 8
+#define R_M32R_LO16 9
+#define R_M32R_SDA16 10
+#define R_M32R_GNU_VTINHERIT 11
+#define R_M32R_GNU_VTENTRY 12
+
+#define R_M32R_16_RELA 33
+#define R_M32R_32_RELA 34
+#define R_M32R_24_RELA 35
+#define R_M32R_10_PCREL_RELA 36
+#define R_M32R_18_PCREL_RELA 37
+#define R_M32R_26_PCREL_RELA 38
+#define R_M32R_HI16_ULO_RELA 39
+#define R_M32R_HI16_SLO_RELA 40
+#define R_M32R_LO16_RELA 41
+#define R_M32R_SDA16_RELA 42
+#define R_M32R_RELA_GNU_VTINHERIT 43
+#define R_M32R_RELA_GNU_VTENTRY 44
+#define R_M32R_REL32 45
+
+#define R_M32R_GOT24 48
+#define R_M32R_26_PLTREL 49
+#define R_M32R_COPY 50
+#define R_M32R_GLOB_DAT 51
+#define R_M32R_JMP_SLOT 52
+#define R_M32R_RELATIVE 53
+#define R_M32R_GOTOFF 54
+#define R_M32R_GOTPC24 55
+#define R_M32R_GOT16_HI_ULO 56
+
+#define R_M32R_GOT16_HI_SLO 57
+
+#define R_M32R_GOT16_LO 58
+#define R_M32R_GOTPC_HI_ULO 59
+
+#define R_M32R_GOTPC_HI_SLO 60
+
+#define R_M32R_GOTPC_LO 61
+
+#define R_M32R_GOTOFF_HI_ULO 62
+
+#define R_M32R_GOTOFF_HI_SLO 63
+
+#define R_M32R_GOTOFF_LO 64
+#define R_M32R_NUM 256
+
+#define R_MICROBLAZE_NONE 0
+#define R_MICROBLAZE_32 1
+#define R_MICROBLAZE_32_PCREL 2
+#define R_MICROBLAZE_64_PCREL 3
+#define R_MICROBLAZE_32_PCREL_LO 4
+#define R_MICROBLAZE_64 5
+#define R_MICROBLAZE_32_LO 6
+#define R_MICROBLAZE_SRO32 7
+#define R_MICROBLAZE_SRW32 8
+#define R_MICROBLAZE_64_NONE 9
+#define R_MICROBLAZE_32_SYM_OP_SYM 10
+#define R_MICROBLAZE_GNU_VTINHERIT 11
+#define R_MICROBLAZE_GNU_VTENTRY 12
+#define R_MICROBLAZE_GOTPC_64 13
+#define R_MICROBLAZE_GOT_64 14
+#define R_MICROBLAZE_PLT_64 15
+#define R_MICROBLAZE_REL 16
+#define R_MICROBLAZE_JUMP_SLOT 17
+#define R_MICROBLAZE_GLOB_DAT 18
+#define R_MICROBLAZE_GOTOFF_64 19
+#define R_MICROBLAZE_GOTOFF_32 20
+#define R_MICROBLAZE_COPY 21
+#define R_MICROBLAZE_TLS 22
+#define R_MICROBLAZE_TLSGD 23
+#define R_MICROBLAZE_TLSLD 24
+#define R_MICROBLAZE_TLSDTPMOD32 25
+#define R_MICROBLAZE_TLSDTPREL32 26
+#define R_MICROBLAZE_TLSDTPREL64 27
+#define R_MICROBLAZE_TLSGOTTPREL32 28
+#define R_MICROBLAZE_TLSTPREL32 29
+
+#define DT_NIOS2_GP 0x70000002
+
+#define R_NIOS2_NONE 0
+#define R_NIOS2_S16 1
+#define R_NIOS2_U16 2
+#define R_NIOS2_PCREL16 3
+#define R_NIOS2_CALL26 4
+#define R_NIOS2_IMM5 5
+#define R_NIOS2_CACHE_OPX 6
+#define R_NIOS2_IMM6 7
+#define R_NIOS2_IMM8 8
+#define R_NIOS2_HI16 9
+#define R_NIOS2_LO16 10
+#define R_NIOS2_HIADJ16 11
+#define R_NIOS2_BFD_RELOC_32 12
+#define R_NIOS2_BFD_RELOC_16 13
+#define R_NIOS2_BFD_RELOC_8 14
+#define R_NIOS2_GPREL 15
+#define R_NIOS2_GNU_VTINHERIT 16
+#define R_NIOS2_GNU_VTENTRY 17
+#define R_NIOS2_UJMP 18
+#define R_NIOS2_CJMP 19
+#define R_NIOS2_CALLR 20
+#define R_NIOS2_ALIGN 21
+#define R_NIOS2_GOT16 22
+#define R_NIOS2_CALL16 23
+#define R_NIOS2_GOTOFF_LO 24
+#define R_NIOS2_GOTOFF_HA 25
+#define R_NIOS2_PCREL_LO 26
+#define R_NIOS2_PCREL_HA 27
+#define R_NIOS2_TLS_GD16 28
+#define R_NIOS2_TLS_LDM16 29
+#define R_NIOS2_TLS_LDO16 30
+#define R_NIOS2_TLS_IE16 31
+#define R_NIOS2_TLS_LE16 32
+#define R_NIOS2_TLS_DTPMOD 33
+#define R_NIOS2_TLS_DTPREL 34
+#define R_NIOS2_TLS_TPREL 35
+#define R_NIOS2_COPY 36
+#define R_NIOS2_GLOB_DAT 37
+#define R_NIOS2_JUMP_SLOT 38
+#define R_NIOS2_RELATIVE 39
+#define R_NIOS2_GOTOFF 40
+#define R_NIOS2_CALL26_NOAT 41
+#define R_NIOS2_GOT_LO 42
+#define R_NIOS2_GOT_HA 43
+#define R_NIOS2_CALL_LO 44
+#define R_NIOS2_CALL_HA 45
+
+#define R_OR1K_NONE 0
+#define R_OR1K_32 1
+#define R_OR1K_16 2
+#define R_OR1K_8 3
+#define R_OR1K_LO_16_IN_INSN 4
+#define R_OR1K_HI_16_IN_INSN 5
+#define R_OR1K_INSN_REL_26 6
+#define R_OR1K_GNU_VTENTRY 7
+#define R_OR1K_GNU_VTINHERIT 8
+#define R_OR1K_32_PCREL 9
+#define R_OR1K_16_PCREL 10
+#define R_OR1K_8_PCREL 11
+#define R_OR1K_GOTPC_HI16 12
+#define R_OR1K_GOTPC_LO16 13
+#define R_OR1K_GOT16 14
+#define R_OR1K_PLT26 15
+#define R_OR1K_GOTOFF_HI16 16
+#define R_OR1K_GOTOFF_LO16 17
+#define R_OR1K_COPY 18
+#define R_OR1K_GLOB_DAT 19
+#define R_OR1K_JMP_SLOT 20
+#define R_OR1K_RELATIVE 21
+#define R_OR1K_TLS_GD_HI16 22
+#define R_OR1K_TLS_GD_LO16 23
+#define R_OR1K_TLS_LDM_HI16 24
+#define R_OR1K_TLS_LDM_LO16 25
+#define R_OR1K_TLS_LDO_HI16 26
+#define R_OR1K_TLS_LDO_LO16 27
+#define R_OR1K_TLS_IE_HI16 28
+#define R_OR1K_TLS_IE_LO16 29
+#define R_OR1K_TLS_LE_HI16 30
+#define R_OR1K_TLS_LE_LO16 31
+#define R_OR1K_TLS_TPOFF 32
+#define R_OR1K_TLS_DTPOFF 33
+#define R_OR1K_TLS_DTPMOD 34
+
+#define R_BPF_NONE 0
+#define R_BPF_MAP_FD 1
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/linux/core2md/core2md.cc b/toolkit/crashreporter/google-breakpad/src/tools/linux/core2md/core2md.cc
new file mode 100644
index 0000000000..c3a9da3988
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/linux/core2md/core2md.cc
@@ -0,0 +1,72 @@
+// 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.
+
+// core2md.cc: A utility to convert an ELF core file to a minidump file.
+
+#include <stdio.h>
+
+#include "client/linux/minidump_writer/minidump_writer.h"
+#include "client/linux/minidump_writer/linux_core_dumper.h"
+
+using google_breakpad::AppMemoryList;
+using google_breakpad::MappingList;
+using google_breakpad::LinuxCoreDumper;
+
+static int ShowUsage(const char* argv0) {
+ fprintf(stderr, "Usage: %s <core file> <procfs dir> <output>\n", argv0);
+ return 1;
+}
+
+bool WriteMinidumpFromCore(const char* filename,
+ const char* core_path,
+ const char* procfs_override) {
+ MappingList mappings;
+ AppMemoryList memory_list;
+ LinuxCoreDumper dumper(0, core_path, procfs_override);
+ return google_breakpad::WriteMinidump(filename, mappings, memory_list,
+ &dumper);
+}
+
+int main(int argc, char *argv[]) {
+ if (argc != 4) {
+ return ShowUsage(argv[0]);
+ }
+
+ const char* core_file = argv[1];
+ const char* procfs_dir = argv[2];
+ const char* minidump_file = argv[3];
+ if (!WriteMinidumpFromCore(minidump_file,
+ core_file,
+ procfs_dir)) {
+ perror("core2md: Unable to generate minidump");
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/linux/dump_syms/dump_syms.cc b/toolkit/crashreporter/google-breakpad/src/tools/linux/dump_syms/dump_syms.cc
new file mode 100644
index 0000000000..ebdf23146c
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/linux/dump_syms/dump_syms.cc
@@ -0,0 +1,137 @@
+// 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.
+
+#include <paths.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include <cstring>
+#include <iostream>
+#include <string>
+#include <vector>
+
+#include "common/linux/dump_symbols.h"
+
+using google_breakpad::WriteSymbolFile;
+using google_breakpad::WriteSymbolFileHeader;
+
+int usage(const char* self) {
+ fprintf(stderr, "Usage: %s [OPTION] <binary-with-debugging-info> "
+ "[directories-for-debug-file]\n\n", self);
+ fprintf(stderr, "Options:\n");
+ fprintf(stderr, " -i: Output module header information only.\n");
+ fprintf(stderr, " -c Do not generate CFI section\n");
+ fprintf(stderr, " -r Do not handle inter-compilation "
+ "unit references\n");
+ fprintf(stderr, " -v Print all warnings to stderr\n");
+ fprintf(stderr, " -n <name> Use specified name for name of the object\n");
+ fprintf(stderr, " -o <os> Use specified name for the "
+ "operating system\n");
+ return 1;
+}
+
+int main(int argc, char **argv) {
+ if (argc < 2)
+ return usage(argv[0]);
+ bool header_only = false;
+ bool cfi = true;
+ bool handle_inter_cu_refs = true;
+ bool log_to_stderr = false;
+ std::string obj_name;
+ const char* obj_os = "Linux";
+ int arg_index = 1;
+ while (arg_index < argc && strlen(argv[arg_index]) > 0 &&
+ argv[arg_index][0] == '-') {
+ if (strcmp("-i", argv[arg_index]) == 0) {
+ header_only = true;
+ } else if (strcmp("-c", argv[arg_index]) == 0) {
+ cfi = false;
+ } else if (strcmp("-r", argv[arg_index]) == 0) {
+ handle_inter_cu_refs = false;
+ } else if (strcmp("-v", argv[arg_index]) == 0) {
+ log_to_stderr = true;
+ } else if (strcmp("-n", argv[arg_index]) == 0) {
+ if (arg_index + 1 >= argc) {
+ fprintf(stderr, "Missing argument to -n\n");
+ return usage(argv[0]);
+ }
+ obj_name = argv[arg_index + 1];
+ ++arg_index;
+ } else if (strcmp("-o", argv[arg_index]) == 0) {
+ if (arg_index + 1 >= argc) {
+ fprintf(stderr, "Missing argument to -o\n");
+ return usage(argv[0]);
+ }
+ obj_os = argv[arg_index + 1];
+ ++arg_index;
+ } else {
+ printf("2.4 %s\n", argv[arg_index]);
+ return usage(argv[0]);
+ }
+ ++arg_index;
+ }
+ if (arg_index == argc)
+ return usage(argv[0]);
+ // Save stderr so it can be used below.
+ FILE* saved_stderr = fdopen(dup(fileno(stderr)), "w");
+ if (!log_to_stderr) {
+ if (freopen(_PATH_DEVNULL, "w", stderr)) {
+ // If it fails, not a lot we can (or should) do.
+ // Add this brace section to silence gcc warnings.
+ }
+ }
+ const char* binary;
+ std::vector<string> debug_dirs;
+ binary = argv[arg_index];
+ for (int debug_dir_index = arg_index + 1;
+ debug_dir_index < argc;
+ ++debug_dir_index) {
+ debug_dirs.push_back(argv[debug_dir_index]);
+ }
+
+ if (obj_name.empty())
+ obj_name = binary;
+
+ if (header_only) {
+ if (!WriteSymbolFileHeader(binary, obj_name, obj_os, std::cout)) {
+ fprintf(saved_stderr, "Failed to process file.\n");
+ return 1;
+ }
+ } else {
+ SymbolData symbol_data = cfi ? ALL_SYMBOL_DATA : NO_CFI;
+ google_breakpad::DumpOptions options(symbol_data, handle_inter_cu_refs);
+ if (!WriteSymbolFile(binary, obj_name, obj_os, debug_dirs, options,
+ std::cout)) {
+ fprintf(saved_stderr, "Failed to write symbol file.\n");
+ return 1;
+ }
+ }
+
+ return 0;
+}
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/linux/md2core/minidump-2-core.cc b/toolkit/crashreporter/google-breakpad/src/tools/linux/md2core/minidump-2-core.cc
new file mode 100644
index 0000000000..a60be32354
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/linux/md2core/minidump-2-core.cc
@@ -0,0 +1,1428 @@
+// 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.
+
+// Converts a minidump file to a core file which gdb can read.
+// Large parts lifted from the userspace core dumper:
+// http://code.google.com/p/google-coredumper/
+
+#include <elf.h>
+#include <errno.h>
+#include <limits.h>
+#include <link.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/user.h>
+#include <unistd.h>
+
+#include <map>
+#include <string>
+#include <vector>
+
+#include "common/linux/memory_mapped_file.h"
+#include "common/minidump_type_helper.h"
+#include "common/path_helper.h"
+#include "common/scoped_ptr.h"
+#include "common/using_std_string.h"
+#include "google_breakpad/common/breakpad_types.h"
+#include "google_breakpad/common/minidump_format.h"
+#include "third_party/lss/linux_syscall_support.h"
+#include "tools/linux/md2core/minidump_memory_range.h"
+
+#if ULONG_MAX == 0xffffffffffffffff
+ #define ELF_CLASS ELFCLASS64
+#else
+ #define ELF_CLASS ELFCLASS32
+#endif
+#define Ehdr ElfW(Ehdr)
+#define Phdr ElfW(Phdr)
+#define Shdr ElfW(Shdr)
+#define Nhdr ElfW(Nhdr)
+#define auxv_t ElfW(auxv_t)
+
+
+#if defined(__x86_64__)
+ #define ELF_ARCH EM_X86_64
+#elif defined(__i386__)
+ #define ELF_ARCH EM_386
+#elif defined(__arm__)
+ #define ELF_ARCH EM_ARM
+#elif defined(__mips__)
+ #define ELF_ARCH EM_MIPS
+#elif defined(__aarch64__)
+ #define ELF_ARCH EM_AARCH64
+#endif
+
+#if defined(__arm__)
+// GLibc/ARM and Android/ARM both use 'user_regs' for the structure type
+// containing core registers, while they use 'user_regs_struct' on other
+// architectures. This file-local typedef simplifies the source code.
+typedef user_regs user_regs_struct;
+#elif defined (__mips__)
+// This file-local typedef simplifies the source code.
+typedef gregset_t user_regs_struct;
+#endif
+
+using google_breakpad::MDTypeHelper;
+using google_breakpad::MemoryMappedFile;
+using google_breakpad::MinidumpMemoryRange;
+
+typedef MDTypeHelper<sizeof(ElfW(Addr))>::MDRawDebug MDRawDebug;
+typedef MDTypeHelper<sizeof(ElfW(Addr))>::MDRawLinkMap MDRawLinkMap;
+
+static const MDRVA kInvalidMDRVA = static_cast<MDRVA>(-1);
+
+struct Options {
+ string minidump_path;
+ bool verbose;
+ int out_fd;
+ bool use_filename;
+ bool inc_guid;
+ string so_basedir;
+};
+
+static void
+Usage(int argc, const char* argv[]) {
+ fprintf(stderr,
+ "Usage: %s [options] <minidump file>\n"
+ "\n"
+ "Convert a minidump file into a core file (often for use by gdb).\n"
+ "\n"
+ "The shared library list will by default have filenames as the runtime expects.\n"
+ "There are many flags to control the output names though to make it easier to\n"
+ "integrate with your debug environment (e.g. gdb).\n"
+ " Default: /lib64/libpthread.so.0\n"
+ " -f: /lib64/libpthread-2.19.so\n"
+ " -i: /lib64/<module id>-libpthread.so.0\n"
+ " -f -i: /lib64/<module id>-libpthread-2.19.so\n"
+ " -S /foo/: /foo/libpthread.so.0\n"
+ "\n"
+ "Options:\n"
+ " -v Enable verbose output\n"
+ " -o <file> Write coredump to specified file (otherwise use stdout).\n"
+ " -f Use the filename rather than the soname in the sharedlib list.\n"
+ " The soname is what the runtime system uses, but the filename is\n"
+ " how it's stored on disk.\n"
+ " -i Prefix sharedlib names with ID (when available). This makes it\n"
+ " easier to have a single directory full of symbols.\n"
+ " -S <dir> Set soname base directory. This will force all debug/symbol\n"
+ " lookups to be done in this directory rather than the filesystem\n"
+ " layout as it exists in the crashing image. This path should end\n"
+ " with a slash if it's a directory. e.g. /var/lib/breakpad/\n"
+ "", google_breakpad::BaseName(argv[0]).c_str());
+}
+
+static void
+SetupOptions(int argc, const char* argv[], Options* options) {
+ extern int optind;
+ int ch;
+ const char* output_file = NULL;
+
+ // Initialize the options struct as needed.
+ options->verbose = false;
+ options->use_filename = false;
+ options->inc_guid = false;
+
+ while ((ch = getopt(argc, (char * const *)argv, "fhio:S:v")) != -1) {
+ switch (ch) {
+ case 'h':
+ Usage(argc, argv);
+ exit(0);
+ break;
+ case '?':
+ Usage(argc, argv);
+ exit(1);
+ break;
+
+ case 'f':
+ options->use_filename = true;
+ break;
+ case 'i':
+ options->inc_guid = true;
+ break;
+ case 'o':
+ output_file = optarg;
+ break;
+ case 'S':
+ options->so_basedir = optarg;
+ break;
+ case 'v':
+ options->verbose = true;
+ break;
+ }
+ }
+
+ if ((argc - optind) != 1) {
+ fprintf(stderr, "%s: Missing minidump file\n", argv[0]);
+ Usage(argc, argv);
+ exit(1);
+ }
+
+ if (output_file == NULL || !strcmp(output_file, "-")) {
+ options->out_fd = STDOUT_FILENO;
+ } else {
+ options->out_fd = open(output_file, O_WRONLY|O_CREAT|O_TRUNC, 0664);
+ if (options->out_fd == -1) {
+ fprintf(stderr, "%s: could not open output %s: %s\n", argv[0],
+ output_file, strerror(errno));
+ exit(1);
+ }
+ }
+
+ options->minidump_path = argv[optind];
+}
+
+// Write all of the given buffer, handling short writes and EINTR. Return true
+// iff successful.
+static bool
+writea(int fd, const void* idata, size_t length) {
+ const uint8_t* data = (const uint8_t*) idata;
+
+ size_t done = 0;
+ while (done < length) {
+ ssize_t r;
+ do {
+ r = write(fd, data + done, length - done);
+ } while (r == -1 && errno == EINTR);
+
+ if (r < 1)
+ return false;
+ done += r;
+ }
+
+ return true;
+}
+
+/* Dynamically determines the byte sex of the system. Returns non-zero
+ * for big-endian machines.
+ */
+static inline int sex() {
+ int probe = 1;
+ return !*(char *)&probe;
+}
+
+typedef struct elf_timeval { /* Time value with microsecond resolution */
+ long tv_sec; /* Seconds */
+ long tv_usec; /* Microseconds */
+} elf_timeval;
+
+typedef struct _elf_siginfo { /* Information about signal (unused) */
+ int32_t si_signo; /* Signal number */
+ int32_t si_code; /* Extra code */
+ int32_t si_errno; /* Errno */
+} _elf_siginfo;
+
+typedef struct prstatus { /* Information about thread; includes CPU reg*/
+ _elf_siginfo pr_info; /* Info associated with signal */
+ uint16_t pr_cursig; /* Current signal */
+ unsigned long pr_sigpend; /* Set of pending signals */
+ unsigned long pr_sighold; /* Set of held signals */
+ pid_t pr_pid; /* Process ID */
+ pid_t pr_ppid; /* Parent's process ID */
+ pid_t pr_pgrp; /* Group ID */
+ pid_t pr_sid; /* Session ID */
+ elf_timeval pr_utime; /* User time */
+ elf_timeval pr_stime; /* System time */
+ elf_timeval pr_cutime; /* Cumulative user time */
+ elf_timeval pr_cstime; /* Cumulative system time */
+ user_regs_struct pr_reg; /* CPU registers */
+ uint32_t pr_fpvalid; /* True if math co-processor being used */
+} prstatus;
+
+typedef struct prpsinfo { /* Information about process */
+ unsigned char pr_state; /* Numeric process state */
+ char pr_sname; /* Char for pr_state */
+ unsigned char pr_zomb; /* Zombie */
+ signed char pr_nice; /* Nice val */
+ unsigned long pr_flag; /* Flags */
+#if defined(__x86_64__) || defined(__mips__)
+ uint32_t pr_uid; /* User ID */
+ uint32_t pr_gid; /* Group ID */
+#else
+ uint16_t pr_uid; /* User ID */
+ uint16_t pr_gid; /* Group ID */
+#endif
+ pid_t pr_pid; /* Process ID */
+ pid_t pr_ppid; /* Parent's process ID */
+ pid_t pr_pgrp; /* Group ID */
+ pid_t pr_sid; /* Session ID */
+ char pr_fname[16]; /* Filename of executable */
+ char pr_psargs[80]; /* Initial part of arg list */
+} prpsinfo;
+
+// We parse the minidump file and keep the parsed information in this structure
+struct CrashedProcess {
+ CrashedProcess()
+ : crashing_tid(-1),
+ auxv(NULL),
+ auxv_length(0) {
+ memset(&prps, 0, sizeof(prps));
+ prps.pr_sname = 'R';
+ memset(&debug, 0, sizeof(debug));
+ }
+
+ struct Mapping {
+ Mapping()
+ : permissions(0xFFFFFFFF),
+ start_address(0),
+ end_address(0),
+ offset(0) {
+ }
+
+ uint32_t permissions;
+ uint64_t start_address, end_address, offset;
+ // The name we write out to the core.
+ string filename;
+ string data;
+ };
+ std::map<uint64_t, Mapping> mappings;
+
+ pid_t crashing_tid;
+ int fatal_signal;
+
+ struct Thread {
+ pid_t tid;
+#if defined(__mips__)
+ mcontext_t mcontext;
+#else
+ user_regs_struct regs;
+#endif
+#if defined(__i386__) || defined(__x86_64__)
+ user_fpregs_struct fpregs;
+#endif
+#if defined(__i386__)
+ user_fpxregs_struct fpxregs;
+#endif
+#if defined(__aarch64__)
+ user_fpsimd_struct fpregs;
+#endif
+ uintptr_t stack_addr;
+ const uint8_t* stack;
+ size_t stack_length;
+ };
+ std::vector<Thread> threads;
+
+ const uint8_t* auxv;
+ size_t auxv_length;
+
+ prpsinfo prps;
+
+ // The GUID/filename from MD_MODULE_LIST_STREAM entries.
+ // We gather them for merging later on into the list of maps.
+ struct Signature {
+ char guid[40];
+ string filename;
+ };
+ std::map<uintptr_t, Signature> signatures;
+
+ string dynamic_data;
+ MDRawDebug debug;
+ std::vector<MDRawLinkMap> link_map;
+};
+
+#if defined(__i386__)
+static uint32_t
+U32(const uint8_t* data) {
+ uint32_t v;
+ memcpy(&v, data, sizeof(v));
+ return v;
+}
+
+static uint16_t
+U16(const uint8_t* data) {
+ uint16_t v;
+ memcpy(&v, data, sizeof(v));
+ return v;
+}
+
+static void
+ParseThreadRegisters(CrashedProcess::Thread* thread,
+ const MinidumpMemoryRange& range) {
+ const MDRawContextX86* rawregs = range.GetData<MDRawContextX86>(0);
+
+ thread->regs.ebx = rawregs->ebx;
+ thread->regs.ecx = rawregs->ecx;
+ thread->regs.edx = rawregs->edx;
+ thread->regs.esi = rawregs->esi;
+ thread->regs.edi = rawregs->edi;
+ thread->regs.ebp = rawregs->ebp;
+ thread->regs.eax = rawregs->eax;
+ thread->regs.xds = rawregs->ds;
+ thread->regs.xes = rawregs->es;
+ thread->regs.xfs = rawregs->fs;
+ thread->regs.xgs = rawregs->gs;
+ thread->regs.orig_eax = rawregs->eax;
+ thread->regs.eip = rawregs->eip;
+ thread->regs.xcs = rawregs->cs;
+ thread->regs.eflags = rawregs->eflags;
+ thread->regs.esp = rawregs->esp;
+ thread->regs.xss = rawregs->ss;
+
+ thread->fpregs.cwd = rawregs->float_save.control_word;
+ thread->fpregs.swd = rawregs->float_save.status_word;
+ thread->fpregs.twd = rawregs->float_save.tag_word;
+ thread->fpregs.fip = rawregs->float_save.error_offset;
+ thread->fpregs.fcs = rawregs->float_save.error_selector;
+ thread->fpregs.foo = rawregs->float_save.data_offset;
+ thread->fpregs.fos = rawregs->float_save.data_selector;
+ memcpy(thread->fpregs.st_space, rawregs->float_save.register_area,
+ 10 * 8);
+
+ thread->fpxregs.cwd = rawregs->float_save.control_word;
+ thread->fpxregs.swd = rawregs->float_save.status_word;
+ thread->fpxregs.twd = rawregs->float_save.tag_word;
+ thread->fpxregs.fop = U16(rawregs->extended_registers + 6);
+ thread->fpxregs.fip = U16(rawregs->extended_registers + 8);
+ thread->fpxregs.fcs = U16(rawregs->extended_registers + 12);
+ thread->fpxregs.foo = U16(rawregs->extended_registers + 16);
+ thread->fpxregs.fos = U16(rawregs->extended_registers + 20);
+ thread->fpxregs.mxcsr = U32(rawregs->extended_registers + 24);
+ memcpy(thread->fpxregs.st_space, rawregs->extended_registers + 32, 128);
+ memcpy(thread->fpxregs.xmm_space, rawregs->extended_registers + 160, 128);
+}
+#elif defined(__x86_64__)
+static void
+ParseThreadRegisters(CrashedProcess::Thread* thread,
+ const MinidumpMemoryRange& range) {
+ const MDRawContextAMD64* rawregs = range.GetData<MDRawContextAMD64>(0);
+
+ thread->regs.r15 = rawregs->r15;
+ thread->regs.r14 = rawregs->r14;
+ thread->regs.r13 = rawregs->r13;
+ thread->regs.r12 = rawregs->r12;
+ thread->regs.rbp = rawregs->rbp;
+ thread->regs.rbx = rawregs->rbx;
+ thread->regs.r11 = rawregs->r11;
+ thread->regs.r10 = rawregs->r10;
+ thread->regs.r9 = rawregs->r9;
+ thread->regs.r8 = rawregs->r8;
+ thread->regs.rax = rawregs->rax;
+ thread->regs.rcx = rawregs->rcx;
+ thread->regs.rdx = rawregs->rdx;
+ thread->regs.rsi = rawregs->rsi;
+ thread->regs.rdi = rawregs->rdi;
+ thread->regs.orig_rax = rawregs->rax;
+ thread->regs.rip = rawregs->rip;
+ thread->regs.cs = rawregs->cs;
+ thread->regs.eflags = rawregs->eflags;
+ thread->regs.rsp = rawregs->rsp;
+ thread->regs.ss = rawregs->ss;
+ thread->regs.fs_base = 0;
+ thread->regs.gs_base = 0;
+ thread->regs.ds = rawregs->ds;
+ thread->regs.es = rawregs->es;
+ thread->regs.fs = rawregs->fs;
+ thread->regs.gs = rawregs->gs;
+
+ thread->fpregs.cwd = rawregs->flt_save.control_word;
+ thread->fpregs.swd = rawregs->flt_save.status_word;
+ thread->fpregs.ftw = rawregs->flt_save.tag_word;
+ thread->fpregs.fop = rawregs->flt_save.error_opcode;
+ thread->fpregs.rip = rawregs->flt_save.error_offset;
+ thread->fpregs.rdp = rawregs->flt_save.data_offset;
+ thread->fpregs.mxcsr = rawregs->flt_save.mx_csr;
+ thread->fpregs.mxcr_mask = rawregs->flt_save.mx_csr_mask;
+ memcpy(thread->fpregs.st_space, rawregs->flt_save.float_registers, 8 * 16);
+ memcpy(thread->fpregs.xmm_space, rawregs->flt_save.xmm_registers, 16 * 16);
+}
+#elif defined(__arm__)
+static void
+ParseThreadRegisters(CrashedProcess::Thread* thread,
+ const MinidumpMemoryRange& range) {
+ const MDRawContextARM* rawregs = range.GetData<MDRawContextARM>(0);
+
+ thread->regs.uregs[0] = rawregs->iregs[0];
+ thread->regs.uregs[1] = rawregs->iregs[1];
+ thread->regs.uregs[2] = rawregs->iregs[2];
+ thread->regs.uregs[3] = rawregs->iregs[3];
+ thread->regs.uregs[4] = rawregs->iregs[4];
+ thread->regs.uregs[5] = rawregs->iregs[5];
+ thread->regs.uregs[6] = rawregs->iregs[6];
+ thread->regs.uregs[7] = rawregs->iregs[7];
+ thread->regs.uregs[8] = rawregs->iregs[8];
+ thread->regs.uregs[9] = rawregs->iregs[9];
+ thread->regs.uregs[10] = rawregs->iregs[10];
+ thread->regs.uregs[11] = rawregs->iregs[11];
+ thread->regs.uregs[12] = rawregs->iregs[12];
+ thread->regs.uregs[13] = rawregs->iregs[13];
+ thread->regs.uregs[14] = rawregs->iregs[14];
+ thread->regs.uregs[15] = rawregs->iregs[15];
+
+ thread->regs.uregs[16] = rawregs->cpsr;
+ thread->regs.uregs[17] = 0; // what is ORIG_r0 exactly?
+}
+#elif defined(__aarch64__)
+static void
+ParseThreadRegisters(CrashedProcess::Thread* thread,
+ const MinidumpMemoryRange& range) {
+#define COPY_REGS(rawregs) \
+ do { \
+ for (int i = 0; i < 31; ++i) \
+ thread->regs.regs[i] = rawregs->iregs[i]; \
+ thread->regs.sp = rawregs->iregs[MD_CONTEXT_ARM64_REG_SP]; \
+ thread->regs.pc = rawregs->iregs[MD_CONTEXT_ARM64_REG_PC]; \
+ thread->regs.pstate = rawregs->cpsr; \
+ \
+ memcpy(thread->fpregs.vregs, rawregs->float_save.regs, 8 * 32); \
+ thread->fpregs.fpsr = rawregs->float_save.fpsr; \
+ thread->fpregs.fpcr = rawregs->float_save.fpcr; \
+ } while (false)
+
+ if (range.length() == sizeof(MDRawContextARM64_Old)) {
+ const MDRawContextARM64_Old* rawregs =
+ range.GetData<MDRawContextARM64_Old>(0);
+ COPY_REGS(rawregs);
+ } else {
+ const MDRawContextARM64* rawregs = range.GetData<MDRawContextARM64>(0);
+ COPY_REGS(rawregs);
+ }
+#undef COPY_REGS
+}
+#elif defined(__mips__)
+static void
+ParseThreadRegisters(CrashedProcess::Thread* thread,
+ const MinidumpMemoryRange& range) {
+ const MDRawContextMIPS* rawregs = range.GetData<MDRawContextMIPS>(0);
+
+ for (int i = 0; i < MD_CONTEXT_MIPS_GPR_COUNT; ++i)
+ thread->mcontext.gregs[i] = rawregs->iregs[i];
+
+ thread->mcontext.pc = rawregs->epc;
+
+ thread->mcontext.mdlo = rawregs->mdlo;
+ thread->mcontext.mdhi = rawregs->mdhi;
+
+ thread->mcontext.hi1 = rawregs->hi[0];
+ thread->mcontext.lo1 = rawregs->lo[0];
+ thread->mcontext.hi2 = rawregs->hi[1];
+ thread->mcontext.lo2 = rawregs->lo[1];
+ thread->mcontext.hi3 = rawregs->hi[2];
+ thread->mcontext.lo3 = rawregs->lo[2];
+
+ for (int i = 0; i < MD_FLOATINGSAVEAREA_MIPS_FPR_COUNT; ++i) {
+ thread->mcontext.fpregs.fp_r.fp_fregs[i]._fp_fregs =
+ rawregs->float_save.regs[i];
+ }
+
+ thread->mcontext.fpc_csr = rawregs->float_save.fpcsr;
+#if _MIPS_SIM == _ABIO32
+ thread->mcontext.fpc_eir = rawregs->float_save.fir;
+#endif
+}
+#else
+#error "This code has not been ported to your platform yet"
+#endif
+
+static void
+ParseThreadList(const Options& options, CrashedProcess* crashinfo,
+ const MinidumpMemoryRange& range,
+ const MinidumpMemoryRange& full_file) {
+ const uint32_t num_threads = *range.GetData<uint32_t>(0);
+ if (options.verbose) {
+ fprintf(stderr,
+ "MD_THREAD_LIST_STREAM:\n"
+ "Found %d threads\n"
+ "\n\n",
+ num_threads);
+ }
+ for (unsigned i = 0; i < num_threads; ++i) {
+ CrashedProcess::Thread thread;
+ memset(&thread, 0, sizeof(thread));
+ const MDRawThread* rawthread =
+ range.GetArrayElement<MDRawThread>(sizeof(uint32_t), i);
+ thread.tid = rawthread->thread_id;
+ thread.stack_addr = rawthread->stack.start_of_memory_range;
+ MinidumpMemoryRange stack_range =
+ full_file.Subrange(rawthread->stack.memory);
+ thread.stack = stack_range.data();
+ thread.stack_length = rawthread->stack.memory.data_size;
+
+ ParseThreadRegisters(&thread,
+ full_file.Subrange(rawthread->thread_context));
+
+ crashinfo->threads.push_back(thread);
+ }
+}
+
+static void
+ParseSystemInfo(const Options& options, CrashedProcess* crashinfo,
+ const MinidumpMemoryRange& range,
+ const MinidumpMemoryRange& full_file) {
+ const MDRawSystemInfo* sysinfo = range.GetData<MDRawSystemInfo>(0);
+ if (!sysinfo) {
+ fprintf(stderr, "Failed to access MD_SYSTEM_INFO_STREAM\n");
+ exit(1);
+ }
+#if defined(__i386__)
+ if (sysinfo->processor_architecture != MD_CPU_ARCHITECTURE_X86) {
+ fprintf(stderr,
+ "This version of minidump-2-core only supports x86 (32bit)%s.\n",
+ sysinfo->processor_architecture == MD_CPU_ARCHITECTURE_AMD64 ?
+ ",\nbut the minidump file is from a 64bit machine" : "");
+ exit(1);
+ }
+#elif defined(__x86_64__)
+ if (sysinfo->processor_architecture != MD_CPU_ARCHITECTURE_AMD64) {
+ fprintf(stderr,
+ "This version of minidump-2-core only supports x86 (64bit)%s.\n",
+ sysinfo->processor_architecture == MD_CPU_ARCHITECTURE_X86 ?
+ ",\nbut the minidump file is from a 32bit machine" : "");
+ exit(1);
+ }
+#elif defined(__arm__)
+ if (sysinfo->processor_architecture != MD_CPU_ARCHITECTURE_ARM) {
+ fprintf(stderr,
+ "This version of minidump-2-core only supports ARM (32bit).\n");
+ exit(1);
+ }
+#elif defined(__aarch64__)
+ if (sysinfo->processor_architecture != MD_CPU_ARCHITECTURE_ARM64_OLD) {
+ fprintf(stderr,
+ "This version of minidump-2-core only supports ARM (64bit).\n");
+ exit(1);
+ }
+#elif defined(__mips__)
+# if _MIPS_SIM == _ABIO32
+ if (sysinfo->processor_architecture != MD_CPU_ARCHITECTURE_MIPS) {
+ fprintf(stderr,
+ "This version of minidump-2-core only supports mips o32 (32bit).\n");
+ exit(1);
+ }
+# elif _MIPS_SIM == _ABI64
+ if (sysinfo->processor_architecture != MD_CPU_ARCHITECTURE_MIPS64) {
+ fprintf(stderr,
+ "This version of minidump-2-core only supports mips n64 (64bit).\n");
+ exit(1);
+ }
+# else
+# error "This mips ABI is currently not supported (n32)"
+# endif
+#else
+#error "This code has not been ported to your platform yet"
+#endif
+ if (!strstr(full_file.GetAsciiMDString(sysinfo->csd_version_rva).c_str(),
+ "Linux") &&
+ sysinfo->platform_id != MD_OS_NACL) {
+ fprintf(stderr, "This minidump was not generated by Linux or NaCl.\n");
+ exit(1);
+ }
+
+ if (options.verbose) {
+ fprintf(stderr,
+ "MD_SYSTEM_INFO_STREAM:\n"
+ "Architecture: %s\n"
+ "Number of processors: %d\n"
+ "Processor level: %d\n"
+ "Processor model: %d\n"
+ "Processor stepping: %d\n",
+ sysinfo->processor_architecture == MD_CPU_ARCHITECTURE_X86
+ ? "i386"
+ : sysinfo->processor_architecture == MD_CPU_ARCHITECTURE_AMD64
+ ? "x86-64"
+ : sysinfo->processor_architecture == MD_CPU_ARCHITECTURE_ARM
+ ? "ARM"
+ : sysinfo->processor_architecture == MD_CPU_ARCHITECTURE_MIPS
+ ? "MIPS"
+ : sysinfo->processor_architecture == MD_CPU_ARCHITECTURE_MIPS64
+ ? "MIPS64"
+ : "???",
+ sysinfo->number_of_processors,
+ sysinfo->processor_level,
+ sysinfo->processor_revision >> 8,
+ sysinfo->processor_revision & 0xFF);
+ if (sysinfo->processor_architecture == MD_CPU_ARCHITECTURE_X86 ||
+ sysinfo->processor_architecture == MD_CPU_ARCHITECTURE_AMD64) {
+ fputs("Vendor id: ", stderr);
+ const char *nul =
+ (const char *)memchr(sysinfo->cpu.x86_cpu_info.vendor_id, 0,
+ sizeof(sysinfo->cpu.x86_cpu_info.vendor_id));
+ fwrite(sysinfo->cpu.x86_cpu_info.vendor_id,
+ nul ? nul - (const char *)&sysinfo->cpu.x86_cpu_info.vendor_id[0]
+ : sizeof(sysinfo->cpu.x86_cpu_info.vendor_id), 1, stderr);
+ fputs("\n", stderr);
+ }
+ fprintf(stderr, "OS: %s\n",
+ full_file.GetAsciiMDString(sysinfo->csd_version_rva).c_str());
+ fputs("\n\n", stderr);
+ }
+}
+
+static void
+ParseCPUInfo(const Options& options, CrashedProcess* crashinfo,
+ const MinidumpMemoryRange& range) {
+ if (options.verbose) {
+ fputs("MD_LINUX_CPU_INFO:\n", stderr);
+ fwrite(range.data(), range.length(), 1, stderr);
+ fputs("\n\n\n", stderr);
+ }
+}
+
+static void
+ParseProcessStatus(const Options& options, CrashedProcess* crashinfo,
+ const MinidumpMemoryRange& range) {
+ if (options.verbose) {
+ fputs("MD_LINUX_PROC_STATUS:\n", stderr);
+ fwrite(range.data(), range.length(), 1, stderr);
+ fputs("\n\n", stderr);
+ }
+}
+
+static void
+ParseLSBRelease(const Options& options, CrashedProcess* crashinfo,
+ const MinidumpMemoryRange& range) {
+ if (options.verbose) {
+ fputs("MD_LINUX_LSB_RELEASE:\n", stderr);
+ fwrite(range.data(), range.length(), 1, stderr);
+ fputs("\n\n", stderr);
+ }
+}
+
+static void
+ParseMaps(const Options& options, CrashedProcess* crashinfo,
+ const MinidumpMemoryRange& range) {
+ if (options.verbose) {
+ fputs("MD_LINUX_MAPS:\n", stderr);
+ fwrite(range.data(), range.length(), 1, stderr);
+ }
+ for (const uint8_t* ptr = range.data();
+ ptr < range.data() + range.length();) {
+ const uint8_t* eol = (uint8_t*)memchr(ptr, '\n',
+ range.data() + range.length() - ptr);
+ string line((const char*)ptr,
+ eol ? eol - ptr : range.data() + range.length() - ptr);
+ ptr = eol ? eol + 1 : range.data() + range.length();
+ unsigned long long start, stop, offset;
+ char* permissions = NULL;
+ char* filename = NULL;
+ sscanf(line.c_str(), "%llx-%llx %m[-rwxp] %llx %*[:0-9a-f] %*d %ms",
+ &start, &stop, &permissions, &offset, &filename);
+ if (filename && *filename == '/') {
+ CrashedProcess::Mapping mapping;
+ mapping.permissions = 0;
+ if (strchr(permissions, 'r')) {
+ mapping.permissions |= PF_R;
+ }
+ if (strchr(permissions, 'w')) {
+ mapping.permissions |= PF_W;
+ }
+ if (strchr(permissions, 'x')) {
+ mapping.permissions |= PF_X;
+ }
+ mapping.start_address = start;
+ mapping.end_address = stop;
+ mapping.offset = offset;
+ if (filename) {
+ mapping.filename = filename;
+ }
+ crashinfo->mappings[mapping.start_address] = mapping;
+ }
+ free(permissions);
+ free(filename);
+ }
+ if (options.verbose) {
+ fputs("\n\n\n", stderr);
+ }
+}
+
+static void
+ParseEnvironment(const Options& options, CrashedProcess* crashinfo,
+ const MinidumpMemoryRange& range) {
+ if (options.verbose) {
+ fputs("MD_LINUX_ENVIRON:\n", stderr);
+ char* env = new char[range.length()];
+ memcpy(env, range.data(), range.length());
+ int nul_count = 0;
+ for (char *ptr = env;;) {
+ ptr = (char *)memchr(ptr, '\000', range.length() - (ptr - env));
+ if (!ptr) {
+ break;
+ }
+ if (ptr > env && ptr[-1] == '\n') {
+ if (++nul_count > 5) {
+ // Some versions of Chrome try to rewrite the process' command line
+ // in a way that causes the environment to be corrupted. Afterwards,
+ // part of the environment will contain the trailing bit of the
+ // command line. The rest of the environment will be filled with
+ // NUL bytes.
+ // We detect this corruption by counting the number of consecutive
+ // NUL bytes. Normally, we would not expect any consecutive NUL
+ // bytes. But we are conservative and only suppress printing of
+ // the environment if we see at least five consecutive NULs.
+ fputs("Environment has been corrupted; no data available", stderr);
+ goto env_corrupted;
+ }
+ } else {
+ nul_count = 0;
+ }
+ *ptr = '\n';
+ }
+ fwrite(env, range.length(), 1, stderr);
+ env_corrupted:
+ delete[] env;
+ fputs("\n\n\n", stderr);
+ }
+}
+
+static void
+ParseAuxVector(const Options& options, CrashedProcess* crashinfo,
+ const MinidumpMemoryRange& range) {
+ // Some versions of Chrome erroneously used the MD_LINUX_AUXV stream value
+ // when dumping /proc/$x/maps
+ if (range.length() > 17) {
+ // The AUXV vector contains binary data, whereas the maps always begin
+ // with an 8+ digit hex address followed by a hyphen and another 8+ digit
+ // address.
+ char addresses[18];
+ memcpy(addresses, range.data(), 17);
+ addresses[17] = '\000';
+ if (strspn(addresses, "0123456789abcdef-") == 17) {
+ ParseMaps(options, crashinfo, range);
+ return;
+ }
+ }
+
+ crashinfo->auxv = range.data();
+ crashinfo->auxv_length = range.length();
+}
+
+static void
+ParseCmdLine(const Options& options, CrashedProcess* crashinfo,
+ const MinidumpMemoryRange& range) {
+ // The command line is supposed to use NUL bytes to separate arguments.
+ // As Chrome rewrites its own command line and (incorrectly) substitutes
+ // spaces, this is often not the case in our minidump files.
+ const char* cmdline = (const char*) range.data();
+ if (options.verbose) {
+ fputs("MD_LINUX_CMD_LINE:\n", stderr);
+ unsigned i = 0;
+ for (; i < range.length() && cmdline[i] && cmdline[i] != ' '; ++i) { }
+ fputs("argv[0] = \"", stderr);
+ fwrite(cmdline, i, 1, stderr);
+ fputs("\"\n", stderr);
+ for (unsigned j = ++i, argc = 1; j < range.length(); ++j) {
+ if (!cmdline[j] || cmdline[j] == ' ') {
+ fprintf(stderr, "argv[%d] = \"", argc++);
+ fwrite(cmdline + i, j - i, 1, stderr);
+ fputs("\"\n", stderr);
+ i = j + 1;
+ }
+ }
+ fputs("\n\n", stderr);
+ }
+
+ const char *binary_name = cmdline;
+ for (size_t i = 0; i < range.length(); ++i) {
+ if (cmdline[i] == '/') {
+ binary_name = cmdline + i + 1;
+ } else if (cmdline[i] == 0 || cmdline[i] == ' ') {
+ static const size_t fname_len = sizeof(crashinfo->prps.pr_fname) - 1;
+ static const size_t args_len = sizeof(crashinfo->prps.pr_psargs) - 1;
+ memset(crashinfo->prps.pr_fname, 0, fname_len + 1);
+ memset(crashinfo->prps.pr_psargs, 0, args_len + 1);
+ unsigned len = cmdline + i - binary_name;
+ memcpy(crashinfo->prps.pr_fname, binary_name,
+ len > fname_len ? fname_len : len);
+
+ len = range.length() > args_len ? args_len : range.length();
+ memcpy(crashinfo->prps.pr_psargs, cmdline, len);
+ for (unsigned j = 0; j < len; ++j) {
+ if (crashinfo->prps.pr_psargs[j] == 0)
+ crashinfo->prps.pr_psargs[j] = ' ';
+ }
+ break;
+ }
+ }
+}
+
+static void
+ParseDSODebugInfo(const Options& options, CrashedProcess* crashinfo,
+ const MinidumpMemoryRange& range,
+ const MinidumpMemoryRange& full_file) {
+ const MDRawDebug* debug = range.GetData<MDRawDebug>(0);
+ if (!debug) {
+ return;
+ }
+ if (options.verbose) {
+ fprintf(stderr,
+ "MD_LINUX_DSO_DEBUG:\n"
+ "Version: %d\n"
+ "Number of DSOs: %d\n"
+ "Brk handler: 0x%" PRIx64 "\n"
+ "Dynamic loader at: 0x%" PRIx64 "\n"
+ "_DYNAMIC: 0x%" PRIx64 "\n",
+ debug->version,
+ debug->dso_count,
+ static_cast<uint64_t>(debug->brk),
+ static_cast<uint64_t>(debug->ldbase),
+ static_cast<uint64_t>(debug->dynamic));
+ }
+ crashinfo->debug = *debug;
+ if (range.length() > sizeof(MDRawDebug)) {
+ char* dynamic_data = (char*)range.data() + sizeof(MDRawDebug);
+ crashinfo->dynamic_data.assign(dynamic_data,
+ range.length() - sizeof(MDRawDebug));
+ }
+ if (debug->map != kInvalidMDRVA) {
+ for (unsigned int i = 0; i < debug->dso_count; ++i) {
+ const MDRawLinkMap* link_map =
+ full_file.GetArrayElement<MDRawLinkMap>(debug->map, i);
+ if (link_map) {
+ if (options.verbose) {
+ fprintf(stderr,
+ "#%03d: %" PRIx64 ", %" PRIx64 ", \"%s\"\n",
+ i, static_cast<uint64_t>(link_map->addr),
+ static_cast<uint64_t>(link_map->ld),
+ full_file.GetAsciiMDString(link_map->name).c_str());
+ }
+ crashinfo->link_map.push_back(*link_map);
+ }
+ }
+ }
+ if (options.verbose) {
+ fputs("\n\n", stderr);
+ }
+}
+
+static void
+ParseExceptionStream(const Options& options, CrashedProcess* crashinfo,
+ const MinidumpMemoryRange& range) {
+ const MDRawExceptionStream* exp = range.GetData<MDRawExceptionStream>(0);
+ crashinfo->crashing_tid = exp->thread_id;
+ crashinfo->fatal_signal = (int) exp->exception_record.exception_code;
+}
+
+static bool
+WriteThread(const Options& options, const CrashedProcess::Thread& thread,
+ int fatal_signal) {
+ struct prstatus pr;
+ memset(&pr, 0, sizeof(pr));
+
+ pr.pr_info.si_signo = fatal_signal;
+ pr.pr_cursig = fatal_signal;
+ pr.pr_pid = thread.tid;
+#if defined(__mips__)
+ memcpy(&pr.pr_reg, &thread.mcontext.gregs, sizeof(user_regs_struct));
+#else
+ memcpy(&pr.pr_reg, &thread.regs, sizeof(user_regs_struct));
+#endif
+
+ Nhdr nhdr;
+ memset(&nhdr, 0, sizeof(nhdr));
+ nhdr.n_namesz = 5;
+ nhdr.n_descsz = sizeof(struct prstatus);
+ nhdr.n_type = NT_PRSTATUS;
+ if (!writea(options.out_fd, &nhdr, sizeof(nhdr)) ||
+ !writea(options.out_fd, "CORE\0\0\0\0", 8) ||
+ !writea(options.out_fd, &pr, sizeof(struct prstatus))) {
+ return false;
+ }
+
+#if defined(__i386__) || defined(__x86_64__)
+ nhdr.n_descsz = sizeof(user_fpregs_struct);
+ nhdr.n_type = NT_FPREGSET;
+ if (!writea(options.out_fd, &nhdr, sizeof(nhdr)) ||
+ !writea(options.out_fd, "CORE\0\0\0\0", 8) ||
+ !writea(options.out_fd, &thread.fpregs, sizeof(user_fpregs_struct))) {
+ return false;
+ }
+#endif
+
+#if defined(__i386__)
+ nhdr.n_descsz = sizeof(user_fpxregs_struct);
+ nhdr.n_type = NT_PRXFPREG;
+ if (!writea(options.out_fd, &nhdr, sizeof(nhdr)) ||
+ !writea(options.out_fd, "LINUX\0\0\0", 8) ||
+ !writea(options.out_fd, &thread.fpxregs, sizeof(user_fpxregs_struct))) {
+ return false;
+ }
+#endif
+
+ return true;
+}
+
+static void
+ParseModuleStream(const Options& options, CrashedProcess* crashinfo,
+ const MinidumpMemoryRange& range,
+ const MinidumpMemoryRange& full_file) {
+ if (options.verbose) {
+ fputs("MD_MODULE_LIST_STREAM:\n", stderr);
+ }
+ const uint32_t num_mappings = *range.GetData<uint32_t>(0);
+ for (unsigned i = 0; i < num_mappings; ++i) {
+ CrashedProcess::Mapping mapping;
+ const MDRawModule* rawmodule = reinterpret_cast<const MDRawModule*>(
+ range.GetArrayElement(sizeof(uint32_t), MD_MODULE_SIZE, i));
+ mapping.start_address = rawmodule->base_of_image;
+ mapping.end_address = rawmodule->size_of_image + rawmodule->base_of_image;
+
+ if (crashinfo->mappings.find(mapping.start_address) ==
+ crashinfo->mappings.end()) {
+ // We prefer data from MD_LINUX_MAPS over MD_MODULE_LIST_STREAM, as
+ // the former is a strict superset of the latter.
+ crashinfo->mappings[mapping.start_address] = mapping;
+ }
+
+ const MDCVInfoPDB70* record = reinterpret_cast<const MDCVInfoPDB70*>(
+ full_file.GetData(rawmodule->cv_record.rva, MDCVInfoPDB70_minsize));
+ char guid[40];
+ sprintf(guid, "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
+ record->signature.data1, record->signature.data2,
+ record->signature.data3,
+ record->signature.data4[0], record->signature.data4[1],
+ record->signature.data4[2], record->signature.data4[3],
+ record->signature.data4[4], record->signature.data4[5],
+ record->signature.data4[6], record->signature.data4[7]);
+
+ string filename = full_file.GetAsciiMDString(rawmodule->module_name_rva);
+
+ CrashedProcess::Signature signature;
+ strcpy(signature.guid, guid);
+ signature.filename = filename;
+ crashinfo->signatures[rawmodule->base_of_image] = signature;
+
+ if (options.verbose) {
+ fprintf(stderr, "0x%" PRIx64 "-0x%" PRIx64 ", ChkSum: 0x%08X, GUID: %s, "
+ " \"%s\"\n",
+ rawmodule->base_of_image,
+ rawmodule->base_of_image + rawmodule->size_of_image,
+ rawmodule->checksum, guid, filename.c_str());
+ }
+ }
+ if (options.verbose) {
+ fputs("\n\n", stderr);
+ }
+}
+
+static void
+AddDataToMapping(CrashedProcess* crashinfo, const string& data,
+ uintptr_t addr) {
+ for (std::map<uint64_t, CrashedProcess::Mapping>::iterator
+ iter = crashinfo->mappings.begin();
+ iter != crashinfo->mappings.end();
+ ++iter) {
+ if (addr >= iter->second.start_address &&
+ addr < iter->second.end_address) {
+ CrashedProcess::Mapping mapping = iter->second;
+ if ((addr & ~4095) != iter->second.start_address) {
+ // If there are memory pages in the mapping prior to where the
+ // data starts, truncate the existing mapping so that it ends with
+ // the page immediately preceding the data region.
+ iter->second.end_address = addr & ~4095;
+ if (!mapping.filename.empty()) {
+ // "mapping" is a copy of "iter->second". We are splitting the
+ // existing mapping into two separate ones when we write the data
+ // to the core file. The first one does not have any associated
+ // data in the core file, the second one is backed by data that is
+ // included with the core file.
+ // If this mapping wasn't supposed to be anonymous, then we also
+ // have to update the file offset upon splitting the mapping.
+ mapping.offset += iter->second.end_address -
+ iter->second.start_address;
+ }
+ }
+ // Create a new mapping that contains the data contents. We often
+ // limit the amount of data that is actually written to the core
+ // file. But it is OK if the mapping itself extends past the end of
+ // the data.
+ mapping.start_address = addr & ~4095;
+ mapping.data.assign(addr & 4095, 0).append(data);
+ mapping.data.append(-mapping.data.size() & 4095, 0);
+ crashinfo->mappings[mapping.start_address] = mapping;
+ return;
+ }
+ }
+ // Didn't find a suitable existing mapping for the data. Create a new one.
+ CrashedProcess::Mapping mapping;
+ mapping.permissions = PF_R | PF_W;
+ mapping.start_address = addr & ~4095;
+ mapping.end_address =
+ (addr + data.size() + 4095) & ~4095;
+ mapping.data.assign(addr & 4095, 0).append(data);
+ mapping.data.append(-mapping.data.size() & 4095, 0);
+ crashinfo->mappings[mapping.start_address] = mapping;
+}
+
+static void
+AugmentMappings(const Options& options, CrashedProcess* crashinfo,
+ const MinidumpMemoryRange& full_file) {
+ // For each thread, find the memory mapping that matches the thread's stack.
+ // Then adjust the mapping to include the stack dump.
+ for (unsigned i = 0; i < crashinfo->threads.size(); ++i) {
+ const CrashedProcess::Thread& thread = crashinfo->threads[i];
+ AddDataToMapping(crashinfo,
+ string((char *)thread.stack, thread.stack_length),
+ thread.stack_addr);
+ }
+
+ // Create a new link map with information about DSOs. We move this map to
+ // the beginning of the address space, as this area should always be
+ // available.
+ static const uintptr_t start_addr = 4096;
+ string data;
+ struct r_debug debug = { 0 };
+ debug.r_version = crashinfo->debug.version;
+ debug.r_brk = (ElfW(Addr))crashinfo->debug.brk;
+ debug.r_state = r_debug::RT_CONSISTENT;
+ debug.r_ldbase = (ElfW(Addr))crashinfo->debug.ldbase;
+ debug.r_map = crashinfo->debug.dso_count > 0 ?
+ (struct link_map*)(start_addr + sizeof(debug)) : 0;
+ data.append((char*)&debug, sizeof(debug));
+
+ struct link_map* prev = 0;
+ for (std::vector<MDRawLinkMap>::iterator iter = crashinfo->link_map.begin();
+ iter != crashinfo->link_map.end();
+ ++iter) {
+ struct link_map link_map = { 0 };
+ link_map.l_addr = (ElfW(Addr))iter->addr;
+ link_map.l_name = (char*)(start_addr + data.size() + sizeof(link_map));
+ link_map.l_ld = (ElfW(Dyn)*)iter->ld;
+ link_map.l_prev = prev;
+ prev = (struct link_map*)(start_addr + data.size());
+ string filename = full_file.GetAsciiMDString(iter->name);
+
+ // Look up signature for this filename. If available, change filename
+ // to point to GUID, instead.
+ std::map<uintptr_t, CrashedProcess::Signature>::const_iterator sig =
+ crashinfo->signatures.find((uintptr_t)iter->addr);
+ if (sig != crashinfo->signatures.end()) {
+ // At this point, we have:
+ // old_filename: The path as found via SONAME (e.g. /lib/libpthread.so.0).
+ // sig_filename: The path on disk (e.g. /lib/libpthread-2.19.so).
+ const char* guid = sig->second.guid;
+ string sig_filename = sig->second.filename;
+ string old_filename = filename.empty() ? sig_filename : filename;
+ string new_filename;
+
+ // First set up the leading path. We assume dirname always ends with a
+ // trailing slash (as needed), so we won't be appending one manually.
+ if (options.so_basedir.empty()) {
+ string dirname;
+ if (options.use_filename) {
+ dirname = sig_filename;
+ } else {
+ dirname = old_filename;
+ }
+ size_t slash = dirname.find_last_of('/');
+ if (slash != string::npos) {
+ new_filename = dirname.substr(0, slash + 1);
+ }
+ } else {
+ new_filename = options.so_basedir;
+ }
+
+ // Insert the module ID if requested.
+ if (options.inc_guid &&
+ strcmp(guid, "00000000-0000-0000-0000-000000000000") != 0) {
+ new_filename += guid;
+ new_filename += "-";
+ }
+
+ // Decide whether we use the filename or the SONAME (where the SONAME tends
+ // to be a symlink to the actual file).
+ new_filename += google_breakpad::BaseName(
+ options.use_filename ? sig_filename : old_filename);
+
+ if (filename != new_filename) {
+ if (options.verbose) {
+ fprintf(stderr, "0x%" PRIx64": rewriting mapping \"%s\" to \"%s\"\n",
+ static_cast<uint64_t>(link_map.l_addr),
+ filename.c_str(), new_filename.c_str());
+ }
+ filename = new_filename;
+ }
+ }
+
+ if (std::distance(iter, crashinfo->link_map.end()) == 1) {
+ link_map.l_next = 0;
+ } else {
+ link_map.l_next = (struct link_map*)(start_addr + data.size() +
+ sizeof(link_map) +
+ ((filename.size() + 8) & ~7));
+ }
+ data.append((char*)&link_map, sizeof(link_map));
+ data.append(filename);
+ data.append(8 - (filename.size() & 7), 0);
+ }
+ AddDataToMapping(crashinfo, data, start_addr);
+
+ // Map the page containing the _DYNAMIC array
+ if (!crashinfo->dynamic_data.empty()) {
+ // Make _DYNAMIC DT_DEBUG entry point to our link map
+ for (int i = 0;; ++i) {
+ ElfW(Dyn) dyn;
+ if ((i+1)*sizeof(dyn) > crashinfo->dynamic_data.length()) {
+ no_dt_debug:
+ if (options.verbose) {
+ fprintf(stderr, "No DT_DEBUG entry found\n");
+ }
+ return;
+ }
+ memcpy(&dyn, crashinfo->dynamic_data.c_str() + i*sizeof(dyn),
+ sizeof(dyn));
+ if (dyn.d_tag == DT_DEBUG) {
+ crashinfo->dynamic_data.replace(i*sizeof(dyn) +
+ offsetof(ElfW(Dyn), d_un.d_ptr),
+ sizeof(start_addr),
+ (char*)&start_addr, sizeof(start_addr));
+ break;
+ } else if (dyn.d_tag == DT_NULL) {
+ goto no_dt_debug;
+ }
+ }
+ AddDataToMapping(crashinfo, crashinfo->dynamic_data,
+ (uintptr_t)crashinfo->debug.dynamic);
+ }
+}
+
+int
+main(int argc, const char* argv[]) {
+ Options options;
+ SetupOptions(argc, argv, &options);
+
+ MemoryMappedFile mapped_file(options.minidump_path.c_str(), 0);
+ if (!mapped_file.data()) {
+ fprintf(stderr, "Failed to mmap dump file: %s: %s\n",
+ options.minidump_path.c_str(), strerror(errno));
+ return 1;
+ }
+
+ MinidumpMemoryRange dump(mapped_file.data(), mapped_file.size());
+
+ const MDRawHeader* header = dump.GetData<MDRawHeader>(0);
+
+ CrashedProcess crashinfo;
+
+ // Always check the system info first, as that allows us to tell whether
+ // this is a minidump file that is compatible with our converter.
+ bool ok = false;
+ for (unsigned i = 0; i < header->stream_count; ++i) {
+ const MDRawDirectory* dirent =
+ dump.GetArrayElement<MDRawDirectory>(header->stream_directory_rva, i);
+ switch (dirent->stream_type) {
+ case MD_SYSTEM_INFO_STREAM:
+ ParseSystemInfo(options, &crashinfo, dump.Subrange(dirent->location),
+ dump);
+ ok = true;
+ break;
+ default:
+ break;
+ }
+ }
+ if (!ok) {
+ fprintf(stderr, "Cannot determine input file format.\n");
+ exit(1);
+ }
+
+ for (unsigned i = 0; i < header->stream_count; ++i) {
+ const MDRawDirectory* dirent =
+ dump.GetArrayElement<MDRawDirectory>(header->stream_directory_rva, i);
+ switch (dirent->stream_type) {
+ case MD_THREAD_LIST_STREAM:
+ ParseThreadList(options, &crashinfo, dump.Subrange(dirent->location),
+ dump);
+ break;
+ case MD_LINUX_CPU_INFO:
+ ParseCPUInfo(options, &crashinfo, dump.Subrange(dirent->location));
+ break;
+ case MD_LINUX_PROC_STATUS:
+ ParseProcessStatus(options, &crashinfo,
+ dump.Subrange(dirent->location));
+ break;
+ case MD_LINUX_LSB_RELEASE:
+ ParseLSBRelease(options, &crashinfo, dump.Subrange(dirent->location));
+ break;
+ case MD_LINUX_ENVIRON:
+ ParseEnvironment(options, &crashinfo, dump.Subrange(dirent->location));
+ break;
+ case MD_LINUX_MAPS:
+ ParseMaps(options, &crashinfo, dump.Subrange(dirent->location));
+ break;
+ case MD_LINUX_AUXV:
+ ParseAuxVector(options, &crashinfo, dump.Subrange(dirent->location));
+ break;
+ case MD_LINUX_CMD_LINE:
+ ParseCmdLine(options, &crashinfo, dump.Subrange(dirent->location));
+ break;
+ case MD_LINUX_DSO_DEBUG:
+ ParseDSODebugInfo(options, &crashinfo, dump.Subrange(dirent->location),
+ dump);
+ break;
+ case MD_EXCEPTION_STREAM:
+ ParseExceptionStream(options, &crashinfo,
+ dump.Subrange(dirent->location));
+ break;
+ case MD_MODULE_LIST_STREAM:
+ ParseModuleStream(options, &crashinfo, dump.Subrange(dirent->location),
+ dump);
+ break;
+ default:
+ if (options.verbose)
+ fprintf(stderr, "Skipping %x\n", dirent->stream_type);
+ }
+ }
+
+ AugmentMappings(options, &crashinfo, dump);
+
+ // Write the ELF header. The file will look like:
+ // ELF header
+ // Phdr for the PT_NOTE
+ // Phdr for each of the thread stacks
+ // PT_NOTE
+ // each of the thread stacks
+ Ehdr ehdr;
+ memset(&ehdr, 0, sizeof(Ehdr));
+ ehdr.e_ident[0] = ELFMAG0;
+ ehdr.e_ident[1] = ELFMAG1;
+ ehdr.e_ident[2] = ELFMAG2;
+ ehdr.e_ident[3] = ELFMAG3;
+ ehdr.e_ident[4] = ELF_CLASS;
+ ehdr.e_ident[5] = sex() ? ELFDATA2MSB : ELFDATA2LSB;
+ ehdr.e_ident[6] = EV_CURRENT;
+ ehdr.e_type = ET_CORE;
+ ehdr.e_machine = ELF_ARCH;
+ ehdr.e_version = EV_CURRENT;
+ ehdr.e_phoff = sizeof(Ehdr);
+ ehdr.e_ehsize = sizeof(Ehdr);
+ ehdr.e_phentsize= sizeof(Phdr);
+ ehdr.e_phnum = 1 + // PT_NOTE
+ crashinfo.mappings.size(); // memory mappings
+ ehdr.e_shentsize= sizeof(Shdr);
+ if (!writea(options.out_fd, &ehdr, sizeof(Ehdr)))
+ return 1;
+
+ size_t offset = sizeof(Ehdr) + ehdr.e_phnum * sizeof(Phdr);
+ size_t filesz = sizeof(Nhdr) + 8 + sizeof(prpsinfo) +
+ // sizeof(Nhdr) + 8 + sizeof(user) +
+ sizeof(Nhdr) + 8 + crashinfo.auxv_length +
+ crashinfo.threads.size() * (
+ (sizeof(Nhdr) + 8 + sizeof(prstatus))
+#if defined(__i386__) || defined(__x86_64__)
+ + sizeof(Nhdr) + 8 + sizeof(user_fpregs_struct)
+#endif
+#if defined(__i386__)
+ + sizeof(Nhdr) + 8 + sizeof(user_fpxregs_struct)
+#endif
+ );
+
+ Phdr phdr;
+ memset(&phdr, 0, sizeof(Phdr));
+ phdr.p_type = PT_NOTE;
+ phdr.p_offset = offset;
+ phdr.p_filesz = filesz;
+ if (!writea(options.out_fd, &phdr, sizeof(phdr)))
+ return 1;
+
+ phdr.p_type = PT_LOAD;
+ phdr.p_align = 4096;
+ size_t note_align = phdr.p_align - ((offset+filesz) % phdr.p_align);
+ if (note_align == phdr.p_align)
+ note_align = 0;
+ offset += note_align;
+
+ for (std::map<uint64_t, CrashedProcess::Mapping>::const_iterator iter =
+ crashinfo.mappings.begin();
+ iter != crashinfo.mappings.end(); ++iter) {
+ const CrashedProcess::Mapping& mapping = iter->second;
+ if (mapping.permissions == 0xFFFFFFFF) {
+ // This is a map that we found in MD_MODULE_LIST_STREAM (as opposed to
+ // MD_LINUX_MAPS). It lacks some of the information that we would like
+ // to include.
+ phdr.p_flags = PF_R;
+ } else {
+ phdr.p_flags = mapping.permissions;
+ }
+ phdr.p_vaddr = mapping.start_address;
+ phdr.p_memsz = mapping.end_address - mapping.start_address;
+ if (mapping.data.size()) {
+ offset += filesz;
+ filesz = mapping.data.size();
+ phdr.p_filesz = mapping.data.size();
+ phdr.p_offset = offset;
+ } else {
+ phdr.p_filesz = 0;
+ phdr.p_offset = 0;
+ }
+ if (!writea(options.out_fd, &phdr, sizeof(phdr)))
+ return 1;
+ }
+
+ Nhdr nhdr;
+ memset(&nhdr, 0, sizeof(nhdr));
+ nhdr.n_namesz = 5;
+ nhdr.n_descsz = sizeof(prpsinfo);
+ nhdr.n_type = NT_PRPSINFO;
+ if (!writea(options.out_fd, &nhdr, sizeof(nhdr)) ||
+ !writea(options.out_fd, "CORE\0\0\0\0", 8) ||
+ !writea(options.out_fd, &crashinfo.prps, sizeof(prpsinfo))) {
+ return 1;
+ }
+
+ nhdr.n_descsz = crashinfo.auxv_length;
+ nhdr.n_type = NT_AUXV;
+ if (!writea(options.out_fd, &nhdr, sizeof(nhdr)) ||
+ !writea(options.out_fd, "CORE\0\0\0\0", 8) ||
+ !writea(options.out_fd, crashinfo.auxv, crashinfo.auxv_length)) {
+ return 1;
+ }
+
+ for (unsigned i = 0; i < crashinfo.threads.size(); ++i) {
+ if (crashinfo.threads[i].tid == crashinfo.crashing_tid) {
+ WriteThread(options, crashinfo.threads[i], crashinfo.fatal_signal);
+ break;
+ }
+ }
+
+ for (unsigned i = 0; i < crashinfo.threads.size(); ++i) {
+ if (crashinfo.threads[i].tid != crashinfo.crashing_tid)
+ WriteThread(options, crashinfo.threads[i], 0);
+ }
+
+ if (note_align) {
+ google_breakpad::scoped_array<char> scratch(new char[note_align]);
+ memset(scratch.get(), 0, note_align);
+ if (!writea(options.out_fd, scratch.get(), note_align))
+ return 1;
+ }
+
+ for (std::map<uint64_t, CrashedProcess::Mapping>::const_iterator iter =
+ crashinfo.mappings.begin();
+ iter != crashinfo.mappings.end(); ++iter) {
+ const CrashedProcess::Mapping& mapping = iter->second;
+ if (mapping.data.size()) {
+ if (!writea(options.out_fd, mapping.data.c_str(), mapping.data.size()))
+ return 1;
+ }
+ }
+
+ if (options.out_fd != STDOUT_FILENO) {
+ close(options.out_fd);
+ }
+
+ return 0;
+}
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/linux/md2core/minidump_memory_range.h b/toolkit/crashreporter/google-breakpad/src/tools/linux/md2core/minidump_memory_range.h
new file mode 100644
index 0000000000..a793e2cfb9
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/linux/md2core/minidump_memory_range.h
@@ -0,0 +1,89 @@
+// 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.
+
+// minidump_memory_range.h: Define the google_breakpad::MinidumpMemoryRange
+// class, which adds methods for handling minidump specific data structures
+// on top of google_breakpad::MemoryRange. See common/memory_range.h for
+// more details on MemoryRange.
+
+#ifndef TOOLS_LINUX_MD2CORE_MINIDUMP_MEMORY_RANGE_H_
+#define TOOLS_LINUX_MD2CORE_MINIDUMP_MEMORY_RANGE_H_
+
+#include <string>
+
+#include "common/memory_range.h"
+#include "google_breakpad/common/minidump_format.h"
+
+namespace google_breakpad {
+
+// A derived class of MemoryRange with added methods for handling minidump
+// specific data structures. To avoid virtual functions, it is not designed
+// to be used polymorphically.
+class MinidumpMemoryRange : public MemoryRange {
+ public:
+ MinidumpMemoryRange() {}
+
+ MinidumpMemoryRange(const void* data, size_t length)
+ : MemoryRange(data, length) {}
+
+ // Returns a subrange of |length| bytes at |offset| bytes of this memory
+ // range, or an empty range if the subrange is out of bounds.
+ // This methods overrides the base implemementation in order to return
+ // an instance of MinidumpMemoryRange instead of MemoryRange.
+ MinidumpMemoryRange Subrange(size_t sub_offset, size_t sub_length) const {
+ if (Covers(sub_offset, sub_length))
+ return MinidumpMemoryRange(data() + sub_offset, sub_length);
+ return MinidumpMemoryRange();
+ }
+
+ // Returns a subrange that covers the offset and length specified by
+ // |location|, or an empty range if the subrange is out of bounds.
+ MinidumpMemoryRange Subrange(const MDLocationDescriptor& location) const {
+ return MinidumpMemoryRange::Subrange(location.rva, location.data_size);
+ }
+
+ // Gets a STL string from a MDString at |sub_offset| bytes of this memory
+ // range. This method only works correctly for ASCII characters and does
+ // not convert between UTF-16 and UTF-8.
+ const std::string GetAsciiMDString(size_t sub_offset) const {
+ std::string str;
+ const MDString* md_str = GetData<MDString>(sub_offset);
+ if (md_str) {
+ const uint16_t* buffer = &md_str->buffer[0];
+ for (uint32_t i = 0; i < md_str->length && buffer[i]; ++i) {
+ str.push_back(buffer[i]);
+ }
+ }
+ return str;
+ }
+};
+
+} // namespace google_breakpad
+
+#endif // TOOLS_LINUX_MD2CORE_MINIDUMP_MEMORY_RANGE_H_
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/linux/md2core/minidump_memory_range_unittest.cc b/toolkit/crashreporter/google-breakpad/src/tools/linux/md2core/minidump_memory_range_unittest.cc
new file mode 100644
index 0000000000..fe4ded83dc
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/linux/md2core/minidump_memory_range_unittest.cc
@@ -0,0 +1,258 @@
+// 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.
+
+// minidump_memory_range_unittest.cc:
+// Unit tests for google_breakpad::MinidumpMemoryRange.
+
+#include "breakpad_googletest_includes.h"
+#include "tools/linux/md2core/minidump_memory_range.h"
+
+using google_breakpad::MinidumpMemoryRange;
+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(MinidumpMemoryRangeTest, DefaultConstructor) {
+ MinidumpMemoryRange range;
+ EXPECT_EQ(NULL, range.data());
+ EXPECT_EQ(0U, range.length());
+}
+
+TEST(MinidumpMemoryRangeTest, ConstructorWithDataAndLength) {
+ MinidumpMemoryRange range(kBuffer, kBufferSize);
+ EXPECT_EQ(kBufferPointer, range.data());
+ EXPECT_EQ(kBufferSize, range.length());
+}
+
+TEST(MinidumpMemoryRangeTest, Reset) {
+ MinidumpMemoryRange 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(MinidumpMemoryRangeTest, Set) {
+ MinidumpMemoryRange 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(MinidumpMemoryRangeTest, SubrangeOfEmptyMemoryRange) {
+ MinidumpMemoryRange range;
+ MinidumpMemoryRange subrange = range.Subrange(0, 10);
+ EXPECT_EQ(NULL, subrange.data());
+ EXPECT_EQ(0U, subrange.length());
+}
+
+TEST(MinidumpMemoryRangeTest, SubrangeAndGetData) {
+ MinidumpMemoryRange 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);
+
+ MinidumpMemoryRange 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(MinidumpMemoryRangeTest, SubrangeWithMDLocationDescriptor) {
+ MinidumpMemoryRange 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);
+
+ MDLocationDescriptor location;
+ location.rva = sub_offset;
+ location.data_size = sub_length;
+ MinidumpMemoryRange subrange = range.Subrange(location);
+ 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(MinidumpMemoryRangeTest, GetDataWithTemplateType) {
+ MinidumpMemoryRange 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(MinidumpMemoryRangeTest, GetArrayElement) {
+ MinidumpMemoryRange 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(MinidumpMemoryRangeTest, GetArrayElmentWithTemplateType) {
+ MinidumpMemoryRange 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);
+}
+
+TEST(MinidumpMemoryRangeTest, GetAsciiMDString) {
+ uint8_t buffer[100] = { 0 };
+
+ MDString* md_str = reinterpret_cast<MDString*>(buffer);
+ md_str->length = 4;
+ md_str->buffer[0] = 'T';
+ md_str->buffer[1] = 'e';
+ md_str->buffer[2] = 's';
+ md_str->buffer[3] = 't';
+ md_str->buffer[4] = '\0';
+
+ size_t str2_offset =
+ sizeof(MDString) + (md_str->length + 1) * sizeof(uint16_t);
+
+ md_str = reinterpret_cast<MDString*>(buffer + str2_offset);
+ md_str->length = 9; // Test length larger than actual string
+ md_str->buffer[0] = 'S';
+ md_str->buffer[1] = 't';
+ md_str->buffer[2] = 'r';
+ md_str->buffer[3] = 'i';
+ md_str->buffer[4] = 'n';
+ md_str->buffer[5] = 'g';
+ md_str->buffer[6] = '\0';
+ md_str->buffer[7] = '1';
+ md_str->buffer[8] = '2';
+
+ MinidumpMemoryRange range(buffer, sizeof(buffer));
+ EXPECT_EQ("Test", range.GetAsciiMDString(0));
+ EXPECT_EQ("String", range.GetAsciiMDString(str2_offset));
+
+ // Test out-of-bounds cases.
+ EXPECT_EQ("", range.GetAsciiMDString(
+ sizeof(buffer) - sizeof(MDString) + 1));
+ EXPECT_EQ("", range.GetAsciiMDString(sizeof(buffer)));
+}
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/linux/symupload/minidump_upload.cc b/toolkit/crashreporter/google-breakpad/src/tools/linux/symupload/minidump_upload.cc
new file mode 100644
index 0000000000..19f17450a1
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/linux/symupload/minidump_upload.cc
@@ -0,0 +1,153 @@
+// Copyright (c) 2006, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// minidump_upload.cc: Upload a minidump to a HTTP server.
+// The upload is sent as a multipart/form-data POST request with
+// the following parameters:
+// prod: the product name
+// ver: the product version
+// symbol_file: the breakpad format symbol file
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <string>
+
+#include "common/linux/http_upload.h"
+#include "common/using_std_string.h"
+
+using google_breakpad::HTTPUpload;
+
+struct Options {
+ string minidumpPath;
+ string uploadURLStr;
+ string product;
+ string version;
+ string proxy;
+ string proxy_user_pwd;
+ bool success;
+};
+
+//=============================================================================
+static void Start(Options *options) {
+ std::map<string, string> parameters;
+ // Add parameters
+ parameters["prod"] = options->product;
+ parameters["ver"] = options->version;
+
+ std::map<string, string> files;
+ files["upload_file_minidump"] = options->minidumpPath;
+
+ // Send it
+ string response, error;
+ bool success = HTTPUpload::SendRequest(options->uploadURLStr,
+ parameters,
+ files,
+ options->proxy,
+ options->proxy_user_pwd,
+ "",
+ &response,
+ NULL,
+ &error);
+
+ if (success) {
+ printf("Successfully sent the minidump file.\n");
+ } else {
+ printf("Failed to send minidump: %s\n", error.c_str());
+ }
+ printf("Response:\n");
+ printf("%s\n", response.c_str());
+ options->success = success;
+}
+
+//=============================================================================
+static void
+Usage(int argc, const char *argv[]) {
+ fprintf(stderr, "Submit minidump information.\n");
+ fprintf(stderr, "Usage: %s [options...] -p <product> -v <version> <minidump> "
+ "<upload-URL>\n", argv[0]);
+ fprintf(stderr, "Options:\n");
+ fprintf(stderr, "<minidump> should be a minidump.\n");
+ fprintf(stderr, "<upload-URL> is the destination for the upload\n");
+
+ fprintf(stderr, "-p:\t <product> Product name\n");
+ fprintf(stderr, "-v:\t <version> Product version\n");
+ fprintf(stderr, "-x:\t <host[:port]> Use HTTP proxy on given port\n");
+ fprintf(stderr, "-u:\t <user[:password]> Set proxy user and password\n");
+ fprintf(stderr, "-h:\t Usage\n");
+ fprintf(stderr, "-?:\t Usage\n");
+}
+
+//=============================================================================
+static void
+SetupOptions(int argc, const char *argv[], Options *options) {
+ extern int optind;
+ int ch;
+
+ while ((ch = getopt(argc, (char * const *)argv, "p:u:v:x:h?")) != -1) {
+ switch (ch) {
+ case 'p':
+ options->product = optarg;
+ break;
+ case 'u':
+ options->proxy_user_pwd = optarg;
+ break;
+ case 'v':
+ options->version = optarg;
+ break;
+ case 'x':
+ options->proxy = optarg;
+ break;
+
+ default:
+ fprintf(stderr, "Invalid option '%c'\n", ch);
+ Usage(argc, argv);
+ exit(1);
+ break;
+ }
+ }
+
+ if ((argc - optind) != 2) {
+ fprintf(stderr, "%s: Missing symbols file and/or upload-URL\n", argv[0]);
+ Usage(argc, argv);
+ exit(1);
+ }
+
+ options->minidumpPath = argv[optind];
+ options->uploadURLStr = argv[optind + 1];
+}
+
+//=============================================================================
+int main(int argc, const char* argv[]) {
+ Options options;
+ SetupOptions(argc, argv, &options);
+ Start(&options);
+ return options.success ? 0 : 1;
+}
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/linux/symupload/sym_upload.cc b/toolkit/crashreporter/google-breakpad/src/tools/linux/symupload/sym_upload.cc
new file mode 100644
index 0000000000..f155eb9552
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/linux/symupload/sym_upload.cc
@@ -0,0 +1,210 @@
+// 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.
+
+// symupload.cc: Upload a symbol file to a HTTP server. The upload is sent as
+// a multipart/form-data POST request with the following parameters:
+// code_file: the basename of the module, e.g. "app"
+// debug_file: the basename of the debugging file, e.g. "app"
+// debug_identifier: the debug file's identifier, usually consisting of
+// the guid and age embedded in the pdb, e.g.
+// "11111111BBBB3333DDDD555555555555F"
+// version: the file version of the module, e.g. "1.2.3.4"
+// os: the operating system that the module was built for
+// cpu: the CPU that the module was built for
+// symbol_file: the contents of the breakpad-format symbol file
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <locale>
+
+#include "common/linux/symbol_upload.h"
+
+using google_breakpad::sym_upload::UploadProtocol;
+using google_breakpad::sym_upload::Options;
+
+static void StrToUpper(std::string* str) {
+ if (str == nullptr) {
+ fprintf(stderr, "nullptr passed to StrToUpper.\n");
+ exit(1);
+ }
+ for (size_t i = 0; i < str->length(); i++) {
+ (*str)[i] = std::toupper((*str)[i], std::locale::classic());
+ }
+}
+
+//=============================================================================
+static void
+Usage(int argc, const char *argv[]) {
+ fprintf(stderr, "Submit symbol information.\n");
+ fprintf(stderr, "Usage: %s [options...] <symbol-file> <upload-URL>\n",
+ argv[0]);
+ fprintf(stderr, "Options:\n");
+ fprintf(stderr, "<symbol-file> should be created by using the dump_syms"
+ "tool.\n");
+ fprintf(stderr, "<upload-URL> is the destination for the upload\n");
+ fprintf(stderr, "-p:\t <protocol> One of ['sym-upload-v1',"
+ " 'sym-upload-v2'], defaults to 'sym-upload-v1'.\n");
+ fprintf(stderr, "-v:\t Version information (e.g., 1.2.3.4)\n");
+ fprintf(stderr, "-x:\t <host[:port]> Use HTTP proxy on given port\n");
+ fprintf(stderr, "-u:\t <user[:password]> Set proxy user and password\n");
+ fprintf(stderr, "-h:\t Usage\n");
+ fprintf(stderr, "-?:\t Usage\n");
+ fprintf(stderr, "\n");
+ fprintf(stderr, "These options only work with 'sym-upload-v2' protocol:\n");
+ fprintf(stderr, "-k:\t <API-key> A secret used to authenticate with the"
+ " API.\n");
+ fprintf(stderr, "-f:\t Force symbol upload if already exists.\n");
+ fprintf(stderr, "-t:\t <symbol-type> Explicitly set symbol upload type ("
+ "default is 'breakpad').\n"
+ "\t One of ['breakpad', 'elf', 'pe', 'macho', 'debug_only', 'dwp', "
+ "'dsym', 'pdb'].\n"
+ "\t Note: When this flag is set to anything other than 'breakpad', then "
+ "the '-c' and '-i' flags must also be set.\n");
+ fprintf(stderr, "-c:\t <code-file> Explicitly set 'code_file' for symbol "
+ "upload (basename of executable).\n");
+ fprintf(stderr, "-i:\t <debug-id> Explicitly set 'debug_id' for symbol "
+ "upload (typically build ID of executable).\n");
+ fprintf(stderr, "\n");
+ fprintf(stderr, "Examples:\n");
+ fprintf(stderr, " With 'sym-upload-v1':\n");
+ fprintf(stderr, " %s path/to/symbol_file http://myuploadserver\n",
+ argv[0]);
+ fprintf(stderr, " With 'sym-upload-v2':\n");
+ fprintf(stderr, " [Defaulting to symbol type 'BREAKPAD']\n");
+ fprintf(stderr, " %s -p sym-upload-v2 -k mysecret123! "
+ "path/to/symbol_file http://myuploadserver\n", argv[0]);
+ fprintf(stderr, " [Explicitly set symbol type to 'elf']\n");
+ fprintf(stderr, " %s -p sym-upload-v2 -k mysecret123! -t elf "
+ "-c app -i 11111111BBBB3333DDDD555555555555F "
+ "path/to/symbol_file http://myuploadserver\n", argv[0]);
+}
+
+//=============================================================================
+static void
+SetupOptions(int argc, const char *argv[], Options *options) {
+ extern int optind;
+ int ch;
+ constexpr char flag_pattern[] = "u:v:x:p:k:t:c:i:hf?";
+
+ while ((ch = getopt(argc, (char * const *)argv, flag_pattern)) != -1) {
+ switch (ch) {
+ case 'h':
+ case '?':
+ Usage(argc, argv);
+ exit(0);
+ break;
+ case 'u':
+ options->proxy_user_pwd = optarg;
+ break;
+ case 'v':
+ options->version = optarg;
+ break;
+ case 'x':
+ options->proxy = optarg;
+ break;
+ case 'p':
+ if (strcmp(optarg, "sym-upload-v2") == 0) {
+ options->upload_protocol = UploadProtocol::SYM_UPLOAD_V2;
+ } else if (strcmp(optarg, "sym-upload-v1") == 0) {
+ options->upload_protocol = UploadProtocol::SYM_UPLOAD_V1;
+ } else {
+ fprintf(stderr, "Invalid protocol '%s'\n", optarg);
+ Usage(argc, argv);
+ exit(1);
+ }
+ break;
+ case 'k':
+ options->api_key = optarg;
+ break;
+ case 't': {
+ // This is really an enum, so treat as upper-case for consistency with
+ // enum naming convention on server-side.
+ options->type = optarg;
+ StrToUpper(&(options->type));
+ break;
+ }
+ case 'c':
+ options->code_file = optarg;
+ break;
+ case 'i':
+ options->debug_id = optarg;
+ break;
+ case 'f':
+ options->force = true;
+ break;
+
+ default:
+ fprintf(stderr, "Invalid option '%c'\n", ch);
+ Usage(argc, argv);
+ exit(1);
+ break;
+ }
+ }
+
+ if ((argc - optind) != 2) {
+ fprintf(stderr, "%s: Missing symbols file and/or upload-URL\n", argv[0]);
+ Usage(argc, argv);
+ exit(1);
+ }
+
+ bool is_breakpad_upload = options->type.empty() ||
+ options->type == google_breakpad::sym_upload::kBreakpadSymbolType;
+ bool has_code_file = !options->code_file.empty();
+ bool has_debug_id = !options->debug_id.empty();
+ if (is_breakpad_upload && (has_code_file || has_debug_id)) {
+ fprintf(stderr, "\n");
+ fprintf(stderr, "%s: -c and -i should only be specified for non-breakpad "
+ "symbol upload types.\n", argv[0]);
+ fprintf(stderr, "\n");
+ Usage(argc, argv);
+ exit(1);
+ }
+ if (!is_breakpad_upload && (!has_code_file || !has_debug_id)) {
+ fprintf(stderr, "\n");
+ fprintf(stderr, "%s: -c and -i must be specified for non-breakpad "
+ "symbol upload types.\n", argv[0]);
+ fprintf(stderr, "\n");
+ Usage(argc, argv);
+ exit(1);
+ }
+
+ options->symbolsPath = argv[optind];
+ options->uploadURLStr = argv[optind + 1];
+}
+
+//=============================================================================
+int main(int argc, const char* argv[]) {
+ Options options;
+ SetupOptions(argc, argv, &options);
+ google_breakpad::sym_upload::Start(&options);
+ return options.success ? 0 : 1;
+}
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/linux/tools_linux.gypi b/toolkit/crashreporter/google-breakpad/src/tools/linux/tools_linux.gypi
new file mode 100644
index 0000000000..020e4c1c71
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/linux/tools_linux.gypi
@@ -0,0 +1,83 @@
+# 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': {
+ 'include_dirs': [
+ '../..',
+ ],
+ },
+ 'targets': [
+ {
+ 'target_name': 'dump_syms',
+ 'type': 'executable',
+ 'sources': [
+ 'dump_syms/dump_syms.cc',
+ ],
+ 'dependencies': [
+ '../common/common.gyp:common',
+ ],
+ },
+ {
+ 'target_name': 'md2core',
+ 'type': 'executable',
+ 'sources': [
+ 'md2core/minidump-2-core.cc',
+ 'md2core/minidump_memory_range.h',
+ ],
+ 'dependencies': [
+ '../common/common.gyp:common',
+ ],
+ },
+ {
+ 'target_name': 'minidump_upload',
+ 'type': 'executable',
+ 'sources': [
+ 'symupload/minidump_upload.cc',
+ ],
+ 'dependencies': [
+ '../common/common.gyp:common',
+ ],
+ },
+ {
+ 'target_name': 'symupload',
+ 'type': 'executable',
+ 'sources': [
+ 'symupload/sym_upload.cc',
+ ],
+ 'link_settings': {
+ 'libraries': [
+ '-ldl',
+ ],
+ },
+ 'dependencies': [
+ '../common/common.gyp:common',
+ ],
+ },
+ ],
+}
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/mac/crash_report/crash_report.mm b/toolkit/crashreporter/google-breakpad/src/tools/mac/crash_report/crash_report.mm
new file mode 100644
index 0000000000..f68200c7c9
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/mac/crash_report/crash_report.mm
@@ -0,0 +1,408 @@
+// Copyright (c) 2010 Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// crash_report.mm: Convert the contents of a minidump into a format that
+// looks more like Apple's CrashReporter format
+
+#include <unistd.h>
+
+#include <mach/machine.h>
+#include <mach-o/arch.h>
+
+#include <string>
+
+#include <Foundation/Foundation.h>
+
+#include "common/scoped_ptr.h"
+#include "google_breakpad/processor/basic_source_line_resolver.h"
+#include "google_breakpad/processor/call_stack.h"
+#include "google_breakpad/processor/code_module.h"
+#include "google_breakpad/processor/minidump.h"
+#include "google_breakpad/processor/minidump_processor.h"
+#include "google_breakpad/processor/process_state.h"
+#include "google_breakpad/processor/stack_frame_cpu.h"
+#include "google_breakpad/processor/system_info.h"
+#include "processor/pathname_stripper.h"
+#include "processor/simple_symbol_supplier.h"
+
+#include "on_demand_symbol_supplier.h"
+
+using std::string;
+
+using google_breakpad::BasicSourceLineResolver;
+using google_breakpad::CallStack;
+using google_breakpad::CodeModule;
+using google_breakpad::CodeModules;
+using google_breakpad::Minidump;
+using google_breakpad::MinidumpProcessor;
+using google_breakpad::OnDemandSymbolSupplier;
+using google_breakpad::PathnameStripper;
+using google_breakpad::ProcessState;
+using google_breakpad::scoped_ptr;
+using google_breakpad::StackFrame;
+using google_breakpad::StackFramePPC;
+using google_breakpad::StackFrameX86;
+using google_breakpad::SystemInfo;
+
+typedef struct {
+ NSString *minidumpPath;
+ NSString *searchDir;
+ NSString *symbolSearchDir;
+ BOOL printThreadMemory;
+} Options;
+
+//=============================================================================
+static int PrintRegister(const char *name, u_int32_t value, int sequence) {
+ if (sequence % 4 == 0) {
+ printf("\n");
+ }
+ printf("%6s = 0x%08x ", name, value);
+ return ++sequence;
+}
+
+//=============================================================================
+static void PrintStack(const CallStack *stack, const string &cpu) {
+ size_t frame_count = stack->frames()->size();
+ char buffer[1024];
+ for (size_t frame_index = 0; frame_index < frame_count; ++frame_index) {
+ const StackFrame *frame = stack->frames()->at(frame_index);
+ const CodeModule *module = frame->module;
+ printf("%2zu ", frame_index);
+
+ if (module) {
+ // Module name (20 chars max)
+ strcpy(buffer, PathnameStripper::File(module->code_file()).c_str());
+ int maxStr = 20;
+ buffer[maxStr] = 0;
+ printf("%-*s", maxStr, buffer);
+
+ strcpy(buffer, module->version().c_str());
+ buffer[maxStr] = 0;
+
+ printf("%-*s",maxStr, buffer);
+
+ u_int64_t instruction = frame->instruction;
+
+ // PPC only: Adjust the instruction to match that of Crash reporter. The
+ // instruction listed is actually the return address. See the detailed
+ // comments in stackwalker_ppc.cc for more information.
+ if (cpu == "ppc" && frame_index)
+ instruction += 4;
+
+ printf(" 0x%08llx ", instruction);
+
+ // Function name
+ if (!frame->function_name.empty()) {
+ printf("%s", frame->function_name.c_str());
+ if (!frame->source_file_name.empty()) {
+ string source_file = PathnameStripper::File(frame->source_file_name);
+ printf(" + 0x%llx (%s:%d)",
+ instruction - frame->source_line_base,
+ source_file.c_str(), frame->source_line);
+ } else {
+ printf(" + 0x%llx", instruction - frame->function_base);
+ }
+ }
+ }
+ printf("\n");
+ }
+}
+
+//=============================================================================
+static void PrintRegisters(const CallStack *stack, const string &cpu) {
+ int sequence = 0;
+ const StackFrame *frame = stack->frames()->at(0);
+ if (cpu == "x86") {
+ const StackFrameX86 *frame_x86 =
+ reinterpret_cast<const StackFrameX86*>(frame);
+
+ if (frame_x86->context_validity & StackFrameX86::CONTEXT_VALID_EIP)
+ sequence = PrintRegister("eip", frame_x86->context.eip, sequence);
+ if (frame_x86->context_validity & StackFrameX86::CONTEXT_VALID_ESP)
+ sequence = PrintRegister("esp", frame_x86->context.esp, sequence);
+ if (frame_x86->context_validity & StackFrameX86::CONTEXT_VALID_EBP)
+ sequence = PrintRegister("ebp", frame_x86->context.ebp, sequence);
+ if (frame_x86->context_validity & StackFrameX86::CONTEXT_VALID_EBX)
+ sequence = PrintRegister("ebx", frame_x86->context.ebx, sequence);
+ if (frame_x86->context_validity & StackFrameX86::CONTEXT_VALID_ESI)
+ sequence = PrintRegister("esi", frame_x86->context.esi, sequence);
+ if (frame_x86->context_validity & StackFrameX86::CONTEXT_VALID_EDI)
+ sequence = PrintRegister("edi", frame_x86->context.edi, sequence);
+ if (frame_x86->context_validity == StackFrameX86::CONTEXT_VALID_ALL) {
+ sequence = PrintRegister("eax", frame_x86->context.eax, sequence);
+ sequence = PrintRegister("ecx", frame_x86->context.ecx, sequence);
+ sequence = PrintRegister("edx", frame_x86->context.edx, sequence);
+ sequence = PrintRegister("efl", frame_x86->context.eflags, sequence);
+ }
+ } else if (cpu == "ppc") {
+ const StackFramePPC *frame_ppc =
+ reinterpret_cast<const StackFramePPC*>(frame);
+
+ if ((frame_ppc->context_validity & StackFramePPC::CONTEXT_VALID_ALL) ==
+ StackFramePPC::CONTEXT_VALID_ALL) {
+ sequence = PrintRegister("srr0", frame_ppc->context.srr0, sequence);
+ sequence = PrintRegister("srr1", frame_ppc->context.srr1, sequence);
+ sequence = PrintRegister("cr", frame_ppc->context.cr, sequence);
+ sequence = PrintRegister("xer", frame_ppc->context.xer, sequence);
+ sequence = PrintRegister("lr", frame_ppc->context.lr, sequence);
+ sequence = PrintRegister("ctr", frame_ppc->context.ctr, sequence);
+ sequence = PrintRegister("mq", frame_ppc->context.mq, sequence);
+ sequence = PrintRegister("vrsave", frame_ppc->context.vrsave, sequence);
+
+ sequence = 0;
+ char buffer[5];
+ for (int i = 0; i < MD_CONTEXT_PPC_GPR_COUNT; ++i) {
+ sprintf(buffer, "r%d", i);
+ sequence = PrintRegister(buffer, frame_ppc->context.gpr[i], sequence);
+ }
+ } else {
+ if (frame_ppc->context_validity & StackFramePPC::CONTEXT_VALID_SRR0)
+ sequence = PrintRegister("srr0", frame_ppc->context.srr0, sequence);
+ if (frame_ppc->context_validity & StackFramePPC::CONTEXT_VALID_GPR1)
+ sequence = PrintRegister("r1", frame_ppc->context.gpr[1], sequence);
+ }
+ }
+
+ printf("\n");
+}
+
+static void PrintModules(const CodeModules *modules) {
+ if (!modules)
+ return;
+
+ printf("\n");
+ printf("Loaded modules:\n");
+
+ u_int64_t main_address = 0;
+ const CodeModule *main_module = modules->GetMainModule();
+ if (main_module) {
+ main_address = main_module->base_address();
+ }
+
+ unsigned int module_count = modules->module_count();
+ for (unsigned int module_sequence = 0;
+ module_sequence < module_count;
+ ++module_sequence) {
+ const CodeModule *module = modules->GetModuleAtSequence(module_sequence);
+ assert(module);
+ u_int64_t base_address = module->base_address();
+ printf("0x%08llx - 0x%08llx %s %s%s %s\n",
+ base_address, base_address + module->size() - 1,
+ PathnameStripper::File(module->code_file()).c_str(),
+ module->version().empty() ? "???" : module->version().c_str(),
+ main_module != NULL && base_address == main_address ?
+ " (main)" : "",
+ module->code_file().c_str());
+ }
+}
+
+static void ProcessSingleReport(Options *options, NSString *file_path) {
+ string minidump_file([file_path fileSystemRepresentation]);
+ BasicSourceLineResolver resolver;
+ string search_dir = options->searchDir ?
+ [options->searchDir fileSystemRepresentation] : "";
+ string symbol_search_dir = options->symbolSearchDir ?
+ [options->symbolSearchDir fileSystemRepresentation] : "";
+ scoped_ptr<OnDemandSymbolSupplier> symbol_supplier(
+ new OnDemandSymbolSupplier(search_dir, symbol_search_dir));
+ scoped_ptr<MinidumpProcessor>
+ minidump_processor(new MinidumpProcessor(symbol_supplier.get(), &resolver));
+ ProcessState process_state;
+ scoped_ptr<Minidump> dump(new google_breakpad::Minidump(minidump_file));
+
+ if (!dump->Read()) {
+ fprintf(stderr, "Minidump %s could not be read\n", dump->path().c_str());
+ return;
+ }
+ if (minidump_processor->Process(dump.get(), &process_state) !=
+ google_breakpad::PROCESS_OK) {
+ fprintf(stderr, "MinidumpProcessor::Process failed\n");
+ return;
+ }
+
+ const SystemInfo *system_info = process_state.system_info();
+ string cpu = system_info->cpu;
+
+ // Convert the time to a string
+ u_int32_t time_date_stamp = process_state.time_date_stamp();
+ struct tm timestruct;
+ gmtime_r(reinterpret_cast<time_t*>(&time_date_stamp), &timestruct);
+ char timestr[20];
+ strftime(timestr, 20, "%Y-%m-%d %H:%M:%S", &timestruct);
+ printf("Date: %s GMT\n", timestr);
+
+ printf("Operating system: %s (%s)\n", system_info->os.c_str(),
+ system_info->os_version.c_str());
+ printf("Architecture: %s\n", cpu.c_str());
+
+ if (process_state.crashed()) {
+ printf("Crash reason: %s\n", process_state.crash_reason().c_str());
+ printf("Crash address: 0x%llx\n", process_state.crash_address());
+ } else {
+ printf("No crash\n");
+ }
+
+ int requesting_thread = process_state.requesting_thread();
+ if (requesting_thread != -1) {
+ printf("\n");
+ printf("Thread %d (%s)\n",
+ requesting_thread,
+ process_state.crashed() ? "crashed" :
+ "requested dump, did not crash");
+ PrintStack(process_state.threads()->at(requesting_thread), cpu);
+ }
+
+ // Print all of the threads in the dump.
+ int thread_count = static_cast<int>(process_state.threads()->size());
+ const std::vector<google_breakpad::MemoryRegion*>
+ *thread_memory_regions = process_state.thread_memory_regions();
+
+ for (int thread_index = 0; thread_index < thread_count; ++thread_index) {
+ if (thread_index != requesting_thread) {
+ // Don't print the crash thread again, it was already printed.
+ printf("\n");
+ printf("Thread %d\n", thread_index);
+ PrintStack(process_state.threads()->at(thread_index), cpu);
+ google_breakpad::MemoryRegion *thread_stack_bytes =
+ thread_memory_regions->at(thread_index);
+ if (options->printThreadMemory) {
+ thread_stack_bytes->Print();
+ }
+ }
+ }
+
+ // Print the crashed registers
+ if (requesting_thread != -1) {
+ printf("\nThread %d:", requesting_thread);
+ PrintRegisters(process_state.threads()->at(requesting_thread), cpu);
+ }
+
+ // Print information about modules
+ PrintModules(process_state.modules());
+}
+
+//=============================================================================
+static void Start(Options *options) {
+ NSFileManager *manager = [NSFileManager defaultManager];
+ NSString *minidump_path = options->minidumpPath;
+ BOOL is_dir = NO;
+ BOOL file_exists = [manager fileExistsAtPath:minidump_path
+ isDirectory:&is_dir];
+ if (file_exists && is_dir) {
+ NSDirectoryEnumerator *enumerator =
+ [manager enumeratorAtPath:minidump_path];
+ NSString *current_file = nil;
+ while ((current_file = [enumerator nextObject])) {
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ if ([[current_file pathExtension] isEqualTo:@"dmp"]) {
+ printf("Attempting to process report: %s\n",
+ [current_file cStringUsingEncoding:NSASCIIStringEncoding]);
+ NSString *full_path =
+ [minidump_path stringByAppendingPathComponent:current_file];
+ ProcessSingleReport(options, full_path);
+ }
+ [pool release];
+ }
+ } else if (file_exists) {
+ ProcessSingleReport(options, minidump_path);
+ }
+}
+
+//=============================================================================
+static void Usage(int argc, const char *argv[]) {
+ fprintf(stderr, "Convert a minidump to a crash report. Breakpad symbol "
+ "files will be used (or created if missing) in /tmp.\n"
+ "If a symbol-file-search-dir is specified, any symbol "
+ "files in it will be used instead of being loaded from "
+ "modules on disk.\n"
+ "If modules cannot be found at the paths stored in the "
+ "minidump file, they will be searched for at "
+ "<module-search-dir>/<path-in-minidump-file>.\n");
+ fprintf(stderr, "Usage: %s [-s module-search-dir] [-S symbol-file-search-dir] "
+ "minidump-file\n", argv[0]);
+ fprintf(stderr, "\t-s: Specify a search directory to use for missing modules\n"
+ "\t-S: Specify a search directory to use for symbol files\n"
+ "\t-t: Print thread stack memory in hex\n"
+ "\t-h: Usage\n"
+ "\t-?: Usage\n");
+}
+
+//=============================================================================
+static void SetupOptions(int argc, const char *argv[], Options *options) {
+ extern int optind;
+ char ch;
+
+ while ((ch = getopt(argc, (char * const *)argv, "S:s:ht?")) != -1) {
+ switch (ch) {
+ case 's':
+ options->searchDir = [[NSFileManager defaultManager]
+ stringWithFileSystemRepresentation:optarg
+ length:strlen(optarg)];
+ break;
+
+ case 'S':
+ options->symbolSearchDir = [[NSFileManager defaultManager]
+ stringWithFileSystemRepresentation:optarg
+ length:strlen(optarg)];
+ break;
+
+ case 't':
+ options->printThreadMemory = YES;
+ break;
+ case 'h':
+ case '?':
+ Usage(argc, argv);
+ exit(1);
+ break;
+ }
+ }
+
+ if ((argc - optind) != 1) {
+ fprintf(stderr, "%s: Missing minidump file\n", argv[0]);
+ Usage(argc, argv);
+ exit(1);
+ }
+
+ options->minidumpPath = [[NSFileManager defaultManager]
+ stringWithFileSystemRepresentation:argv[optind]
+ length:strlen(argv[optind])];
+}
+
+//=============================================================================
+int main (int argc, const char * argv[]) {
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ Options options;
+
+ bzero(&options, sizeof(Options));
+ SetupOptions(argc, argv, &options);
+ Start(&options);
+ [pool release];
+
+ return 0;
+}
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/mac/crash_report/crash_report.xcodeproj/project.pbxproj b/toolkit/crashreporter/google-breakpad/src/tools/mac/crash_report/crash_report.xcodeproj/project.pbxproj
new file mode 100644
index 0000000000..33204f7e2e
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/mac/crash_report/crash_report.xcodeproj/project.pbxproj
@@ -0,0 +1,618 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 45;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ 162F64FE161C5ECB00CD68D5 /* arch_utilities.cc in Sources */ = {isa = PBXBuildFile; fileRef = 162F64FC161C5ECB00CD68D5 /* arch_utilities.cc */; };
+ 4214B800211109A600B769FA /* convert_old_arm64_context.cc in Sources */ = {isa = PBXBuildFile; fileRef = 4214B7FE211109A600B769FA /* convert_old_arm64_context.cc */; };
+ 4247E6402110D5A500482558 /* path_helper.cc in Sources */ = {isa = PBXBuildFile; fileRef = 4247E63F2110D5A500482558 /* path_helper.cc */; };
+ 4D2C721B126F9ACC00B43EAF /* source_line_resolver_base.cc in Sources */ = {isa = PBXBuildFile; fileRef = 4D2C721A126F9ACC00B43EAF /* source_line_resolver_base.cc */; };
+ 4D2C721F126F9ADE00B43EAF /* exploitability.cc in Sources */ = {isa = PBXBuildFile; fileRef = 4D2C721E126F9ADE00B43EAF /* exploitability.cc */; };
+ 4D2C7223126F9AF900B43EAF /* exploitability_win.cc in Sources */ = {isa = PBXBuildFile; fileRef = 4D2C7222126F9AF900B43EAF /* exploitability_win.cc */; };
+ 4D2C7227126F9B0F00B43EAF /* disassembler_x86.cc in Sources */ = {isa = PBXBuildFile; fileRef = 4D2C7226126F9B0F00B43EAF /* disassembler_x86.cc */; };
+ 4D2C722B126F9B5A00B43EAF /* x86_disasm.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D2C722A126F9B5A00B43EAF /* x86_disasm.c */; };
+ 4D2C722D126F9B6E00B43EAF /* x86_misc.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D2C722C126F9B6E00B43EAF /* x86_misc.c */; };
+ 4D2C722F126F9B8300B43EAF /* x86_operand_list.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D2C722E126F9B8300B43EAF /* x86_operand_list.c */; };
+ 4D2C7233126F9BB000B43EAF /* ia32_invariant.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D2C7232126F9BB000B43EAF /* ia32_invariant.c */; settings = {COMPILER_FLAGS = "-Wno-error"; }; };
+ 4D2C7235126F9BC200B43EAF /* ia32_settings.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D2C7234126F9BC200B43EAF /* ia32_settings.c */; };
+ 4D2C7246126F9C0B00B43EAF /* ia32_insn.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D2C7245126F9C0B00B43EAF /* ia32_insn.c */; };
+ 4D2C724A126F9C2300B43EAF /* ia32_opcode_tables.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D2C7249126F9C2300B43EAF /* ia32_opcode_tables.c */; settings = {COMPILER_FLAGS = "-Wno-error"; }; };
+ 4D2C724C126F9C3800B43EAF /* ia32_implicit.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D2C724B126F9C3800B43EAF /* ia32_implicit.c */; settings = {COMPILER_FLAGS = "-Wno-error"; }; };
+ 4D2C724E126F9C4D00B43EAF /* ia32_reg.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D2C724D126F9C4D00B43EAF /* ia32_reg.c */; settings = {COMPILER_FLAGS = "-Wno-error"; }; };
+ 4D2C725B126F9C8000B43EAF /* ia32_operand.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D2C725A126F9C8000B43EAF /* ia32_operand.c */; };
+ 4D2C725D126F9C9200B43EAF /* x86_insn.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D2C725C126F9C9200B43EAF /* x86_insn.c */; };
+ 4D2C7264126F9CBB00B43EAF /* ia32_modrm.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D2C7261126F9CBB00B43EAF /* ia32_modrm.c */; };
+ 4D2C726D126F9CDC00B43EAF /* x86_imm.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D2C7263126F9CBB00B43EAF /* x86_imm.c */; };
+ 4D72CA5713DFBA84006CABE3 /* md5.cc in Sources */ = {isa = PBXBuildFile; fileRef = 4D72CA5613DFBA84006CABE3 /* md5.cc */; };
+ 557800400BE1F28500EC23E0 /* macho_utilities.cc in Sources */ = {isa = PBXBuildFile; fileRef = 5578003E0BE1F28500EC23E0 /* macho_utilities.cc */; };
+ 8B31FF2A11F0C62700FCF3E4 /* dwarf_cfi_to_module.cc in Sources */ = {isa = PBXBuildFile; fileRef = 8B31FF2411F0C62700FCF3E4 /* dwarf_cfi_to_module.cc */; };
+ 8B31FF2B11F0C62700FCF3E4 /* dwarf_cu_to_module.cc in Sources */ = {isa = PBXBuildFile; fileRef = 8B31FF2611F0C62700FCF3E4 /* dwarf_cu_to_module.cc */; };
+ 8B31FF2C11F0C62700FCF3E4 /* dwarf_line_to_module.cc in Sources */ = {isa = PBXBuildFile; fileRef = 8B31FF2811F0C62700FCF3E4 /* dwarf_line_to_module.cc */; };
+ 8B31FF4111F0C64400FCF3E4 /* stabs_reader.cc in Sources */ = {isa = PBXBuildFile; fileRef = 8B31FF3D11F0C64400FCF3E4 /* stabs_reader.cc */; };
+ 8B31FF4211F0C64400FCF3E4 /* stabs_to_module.cc in Sources */ = {isa = PBXBuildFile; fileRef = 8B31FF3F11F0C64400FCF3E4 /* stabs_to_module.cc */; };
+ 8B31FF7411F0C6E000FCF3E4 /* macho_reader.cc in Sources */ = {isa = PBXBuildFile; fileRef = 8B31FF7211F0C6E000FCF3E4 /* macho_reader.cc */; };
+ 8B31FF8811F0C6FB00FCF3E4 /* language.cc in Sources */ = {isa = PBXBuildFile; fileRef = 8B31FF8411F0C6FB00FCF3E4 /* language.cc */; };
+ 8B31FF8911F0C6FB00FCF3E4 /* module.cc in Sources */ = {isa = PBXBuildFile; fileRef = 8B31FF8611F0C6FB00FCF3E4 /* module.cc */; };
+ 8B31FFC511F0C8AB00FCF3E4 /* dwarf2diehandler.cc in Sources */ = {isa = PBXBuildFile; fileRef = 8B31FFC311F0C8AB00FCF3E4 /* dwarf2diehandler.cc */; };
+ 8B40BDC00C0638E4009535AF /* logging.cc in Sources */ = {isa = PBXBuildFile; fileRef = 8B40BDBF0C0638E4009535AF /* logging.cc */; };
+ 8DD76F9A0486AA7600D96B5E /* crash_report.mm in Sources */ = {isa = PBXBuildFile; fileRef = 08FB7796FE84155DC02AAC07 /* crash_report.mm */; settings = {ATTRIBUTES = (); }; };
+ 8DD76F9C0486AA7600D96B5E /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 08FB779EFE84155DC02AAC07 /* Foundation.framework */; };
+ 9B35FEEA0B26761C008DE8C7 /* basic_code_modules.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9B35FEE70B26761C008DE8C7 /* basic_code_modules.cc */; };
+ 9B3904990B2E52FD0059FABE /* basic_source_line_resolver.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9B3904980B2E52FD0059FABE /* basic_source_line_resolver.cc */; };
+ 9BDF172C0B1B8B2400F8391B /* call_stack.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9BDF172A0B1B8B2400F8391B /* call_stack.cc */; };
+ 9BDF172D0B1B8B2400F8391B /* minidump_processor.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9BDF172B0B1B8B2400F8391B /* minidump_processor.cc */; };
+ 9BDF17410B1B8B9A00F8391B /* minidump.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9BDF173F0B1B8B9A00F8391B /* minidump.cc */; };
+ 9BDF17540B1B8BF900F8391B /* stackwalker_ppc.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9BDF17510B1B8BF900F8391B /* stackwalker_ppc.cc */; };
+ 9BDF17550B1B8BF900F8391B /* stackwalker_x86.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9BDF17520B1B8BF900F8391B /* stackwalker_x86.cc */; };
+ 9BDF17560B1B8BF900F8391B /* stackwalker.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9BDF17530B1B8BF900F8391B /* stackwalker.cc */; };
+ 9BDF175D0B1B8C1B00F8391B /* process_state.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9BDF175B0B1B8C1B00F8391B /* process_state.cc */; };
+ 9BDF176E0B1B8CB100F8391B /* on_demand_symbol_supplier.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9BDF176C0B1B8CB100F8391B /* on_demand_symbol_supplier.mm */; };
+ 9BDF1A280B1BD58200F8391B /* pathname_stripper.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9BDF1A270B1BD58200F8391B /* pathname_stripper.cc */; };
+ 9BDF21A70B1E825400F8391B /* dump_syms.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9BDF192E0B1BC15D00F8391B /* dump_syms.cc */; };
+ 9BE650B20B52FE3000611104 /* file_id.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9BE650AC0B52FE3000611104 /* file_id.cc */; };
+ 9BE650B40B52FE3000611104 /* macho_id.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9BE650AE0B52FE3000611104 /* macho_id.cc */; };
+ 9BE650B60B52FE3000611104 /* macho_walker.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9BE650B00B52FE3000611104 /* macho_walker.cc */; };
+ D2A5DD4D1188651100081F03 /* cfi_frame_info.cc in Sources */ = {isa = PBXBuildFile; fileRef = D2A5DD4C1188651100081F03 /* cfi_frame_info.cc */; };
+ D2A5DD631188658B00081F03 /* tokenize.cc in Sources */ = {isa = PBXBuildFile; fileRef = D2A5DD621188658B00081F03 /* tokenize.cc */; };
+ F407DC48185773C10064622B /* exploitability_linux.cc in Sources */ = {isa = PBXBuildFile; fileRef = F407DC40185773C10064622B /* exploitability_linux.cc */; };
+ F407DC49185773C10064622B /* stack_frame_symbolizer.cc in Sources */ = {isa = PBXBuildFile; fileRef = F407DC41185773C10064622B /* stack_frame_symbolizer.cc */; };
+ F407DC4A185773C10064622B /* stackwalker_arm64.cc in Sources */ = {isa = PBXBuildFile; fileRef = F407DC42185773C10064622B /* stackwalker_arm64.cc */; };
+ F407DC4B185773C10064622B /* stackwalker_mips.cc in Sources */ = {isa = PBXBuildFile; fileRef = F407DC44185773C10064622B /* stackwalker_mips.cc */; };
+ F407DC4C185773C10064622B /* stackwalker_ppc64.cc in Sources */ = {isa = PBXBuildFile; fileRef = F407DC46185773C10064622B /* stackwalker_ppc64.cc */; };
+ F44DDD8719C85CD50047280E /* dump_context.cc in Sources */ = {isa = PBXBuildFile; fileRef = F44DDD8419C85CD50047280E /* dump_context.cc */; };
+ F44DDD8819C85CD50047280E /* dump_object.cc in Sources */ = {isa = PBXBuildFile; fileRef = F44DDD8519C85CD50047280E /* dump_object.cc */; };
+ F44DDD8919C85CD50047280E /* microdump_processor.cc in Sources */ = {isa = PBXBuildFile; fileRef = F44DDD8619C85CD50047280E /* microdump_processor.cc */; };
+ F47180561D745DEF0032F208 /* elf_reader.cc in Sources */ = {isa = PBXBuildFile; fileRef = F47180541D745DEF0032F208 /* elf_reader.cc */; };
+ F47180581D7467630032F208 /* proc_maps_linux.cc in Sources */ = {isa = PBXBuildFile; fileRef = F47180571D7467630032F208 /* proc_maps_linux.cc */; };
+ F471805A1D7468A40032F208 /* symbolic_constants_win.cc in Sources */ = {isa = PBXBuildFile; fileRef = F47180591D7468A40032F208 /* symbolic_constants_win.cc */; };
+ F4D43B2F1A38490700C290B2 /* microdump.cc in Sources */ = {isa = PBXBuildFile; fileRef = F4D43B2E1A38490700C290B2 /* microdump.cc */; };
+ F9C7ECE50E8ABCA600E953AD /* bytereader.cc in Sources */ = {isa = PBXBuildFile; fileRef = F9C7ECE20E8ABCA600E953AD /* bytereader.cc */; };
+ F9C7ECE60E8ABCA600E953AD /* dwarf2reader.cc in Sources */ = {isa = PBXBuildFile; fileRef = F9C7ECE30E8ABCA600E953AD /* dwarf2reader.cc */; };
+ F9C7ECE70E8ABCA600E953AD /* functioninfo.cc in Sources */ = {isa = PBXBuildFile; fileRef = F9C7ECE40E8ABCA600E953AD /* functioninfo.cc */; };
+ F9F0706710FBC02D0037B88B /* stackwalker_arm.cc in Sources */ = {isa = PBXBuildFile; fileRef = F9F0706510FBC02D0037B88B /* stackwalker_arm.cc */; };
+ FD6625CD0CF4D45C004AC844 /* stackwalker_amd64.cc in Sources */ = {isa = PBXBuildFile; fileRef = FD6625C40CF4D438004AC844 /* stackwalker_amd64.cc */; };
+ FD8EDEAE0CADDAD400A5EDF1 /* stackwalker_sparc.cc in Sources */ = {isa = PBXBuildFile; fileRef = FD8EDEAC0CADDAD400A5EDF1 /* stackwalker_sparc.cc */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXFileReference section */
+ 08FB7796FE84155DC02AAC07 /* crash_report.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = crash_report.mm; sourceTree = "<group>"; };
+ 08FB779EFE84155DC02AAC07 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
+ 162F64FC161C5ECB00CD68D5 /* arch_utilities.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = arch_utilities.cc; path = ../../../common/mac/arch_utilities.cc; sourceTree = "<group>"; };
+ 162F64FD161C5ECB00CD68D5 /* arch_utilities.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = arch_utilities.h; path = ../../../common/mac/arch_utilities.h; sourceTree = "<group>"; };
+ 4214B7FE211109A600B769FA /* convert_old_arm64_context.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = convert_old_arm64_context.cc; path = ../../../processor/convert_old_arm64_context.cc; sourceTree = "<group>"; };
+ 4214B7FF211109A600B769FA /* convert_old_arm64_context.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = convert_old_arm64_context.h; path = ../../../processor/convert_old_arm64_context.h; sourceTree = "<group>"; };
+ 4247E63E2110D5A500482558 /* path_helper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = path_helper.h; path = ../../../common/path_helper.h; sourceTree = "<group>"; };
+ 4247E63F2110D5A500482558 /* path_helper.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = path_helper.cc; path = ../../../common/path_helper.cc; sourceTree = "<group>"; };
+ 4D2C721A126F9ACC00B43EAF /* source_line_resolver_base.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = source_line_resolver_base.cc; path = ../../../processor/source_line_resolver_base.cc; sourceTree = SOURCE_ROOT; };
+ 4D2C721E126F9ADE00B43EAF /* exploitability.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = exploitability.cc; path = ../../../processor/exploitability.cc; sourceTree = SOURCE_ROOT; };
+ 4D2C7222126F9AF900B43EAF /* exploitability_win.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = exploitability_win.cc; path = ../../../processor/exploitability_win.cc; sourceTree = SOURCE_ROOT; };
+ 4D2C7226126F9B0F00B43EAF /* disassembler_x86.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = disassembler_x86.cc; path = ../../../processor/disassembler_x86.cc; sourceTree = SOURCE_ROOT; };
+ 4D2C722A126F9B5A00B43EAF /* x86_disasm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = x86_disasm.c; path = ../../../third_party/libdisasm/x86_disasm.c; sourceTree = SOURCE_ROOT; };
+ 4D2C722C126F9B6E00B43EAF /* x86_misc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = x86_misc.c; path = ../../../third_party/libdisasm/x86_misc.c; sourceTree = SOURCE_ROOT; };
+ 4D2C722E126F9B8300B43EAF /* x86_operand_list.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = x86_operand_list.c; path = ../../../third_party/libdisasm/x86_operand_list.c; sourceTree = SOURCE_ROOT; };
+ 4D2C7232126F9BB000B43EAF /* ia32_invariant.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = ia32_invariant.c; path = ../../../third_party/libdisasm/ia32_invariant.c; sourceTree = SOURCE_ROOT; };
+ 4D2C7234126F9BC200B43EAF /* ia32_settings.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = ia32_settings.c; path = ../../../third_party/libdisasm/ia32_settings.c; sourceTree = SOURCE_ROOT; };
+ 4D2C7245126F9C0B00B43EAF /* ia32_insn.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = ia32_insn.c; path = ../../../third_party/libdisasm/ia32_insn.c; sourceTree = SOURCE_ROOT; };
+ 4D2C7249126F9C2300B43EAF /* ia32_opcode_tables.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = ia32_opcode_tables.c; path = ../../../third_party/libdisasm/ia32_opcode_tables.c; sourceTree = SOURCE_ROOT; };
+ 4D2C724B126F9C3800B43EAF /* ia32_implicit.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = ia32_implicit.c; path = ../../../third_party/libdisasm/ia32_implicit.c; sourceTree = SOURCE_ROOT; };
+ 4D2C724D126F9C4D00B43EAF /* ia32_reg.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = ia32_reg.c; path = ../../../third_party/libdisasm/ia32_reg.c; sourceTree = SOURCE_ROOT; };
+ 4D2C725A126F9C8000B43EAF /* ia32_operand.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = ia32_operand.c; path = ../../../third_party/libdisasm/ia32_operand.c; sourceTree = SOURCE_ROOT; };
+ 4D2C725C126F9C9200B43EAF /* x86_insn.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = x86_insn.c; path = ../../../third_party/libdisasm/x86_insn.c; sourceTree = SOURCE_ROOT; };
+ 4D2C7261126F9CBB00B43EAF /* ia32_modrm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = ia32_modrm.c; path = ../../../third_party/libdisasm/ia32_modrm.c; sourceTree = SOURCE_ROOT; };
+ 4D2C7263126F9CBB00B43EAF /* x86_imm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = x86_imm.c; path = ../../../third_party/libdisasm/x86_imm.c; sourceTree = SOURCE_ROOT; };
+ 4D72CA5613DFBA84006CABE3 /* md5.cc */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = md5.cc; path = ../../../common/md5.cc; sourceTree = SOURCE_ROOT; };
+ 5578003E0BE1F28500EC23E0 /* macho_utilities.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = macho_utilities.cc; path = ../../../common/mac/macho_utilities.cc; sourceTree = SOURCE_ROOT; };
+ 5578003F0BE1F28500EC23E0 /* macho_utilities.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = macho_utilities.h; path = ../../../common/mac/macho_utilities.h; sourceTree = SOURCE_ROOT; };
+ 8B31025311F0D2D400FCF3E4 /* Breakpad.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Breakpad.xcconfig; path = ../../../common/mac/Breakpad.xcconfig; sourceTree = SOURCE_ROOT; };
+ 8B3102DA11F0D65600FCF3E4 /* BreakpadDebug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = BreakpadDebug.xcconfig; path = ../../../common/mac/BreakpadDebug.xcconfig; sourceTree = SOURCE_ROOT; };
+ 8B3102DB11F0D65600FCF3E4 /* BreakpadRelease.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = BreakpadRelease.xcconfig; path = ../../../common/mac/BreakpadRelease.xcconfig; sourceTree = SOURCE_ROOT; };
+ 8B31FF2411F0C62700FCF3E4 /* dwarf_cfi_to_module.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = dwarf_cfi_to_module.cc; path = ../../../common/dwarf_cfi_to_module.cc; sourceTree = SOURCE_ROOT; };
+ 8B31FF2511F0C62700FCF3E4 /* dwarf_cfi_to_module.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dwarf_cfi_to_module.h; path = ../../../common/dwarf_cfi_to_module.h; sourceTree = SOURCE_ROOT; };
+ 8B31FF2611F0C62700FCF3E4 /* dwarf_cu_to_module.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = dwarf_cu_to_module.cc; path = ../../../common/dwarf_cu_to_module.cc; sourceTree = SOURCE_ROOT; };
+ 8B31FF2711F0C62700FCF3E4 /* dwarf_cu_to_module.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dwarf_cu_to_module.h; path = ../../../common/dwarf_cu_to_module.h; sourceTree = SOURCE_ROOT; };
+ 8B31FF2811F0C62700FCF3E4 /* dwarf_line_to_module.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = dwarf_line_to_module.cc; path = ../../../common/dwarf_line_to_module.cc; sourceTree = SOURCE_ROOT; };
+ 8B31FF2911F0C62700FCF3E4 /* dwarf_line_to_module.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dwarf_line_to_module.h; path = ../../../common/dwarf_line_to_module.h; sourceTree = SOURCE_ROOT; };
+ 8B31FF3D11F0C64400FCF3E4 /* stabs_reader.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = stabs_reader.cc; path = ../../../common/stabs_reader.cc; sourceTree = SOURCE_ROOT; };
+ 8B31FF3E11F0C64400FCF3E4 /* stabs_reader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = stabs_reader.h; path = ../../../common/stabs_reader.h; sourceTree = SOURCE_ROOT; };
+ 8B31FF3F11F0C64400FCF3E4 /* stabs_to_module.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = stabs_to_module.cc; path = ../../../common/stabs_to_module.cc; sourceTree = SOURCE_ROOT; };
+ 8B31FF4011F0C64400FCF3E4 /* stabs_to_module.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = stabs_to_module.h; path = ../../../common/stabs_to_module.h; sourceTree = SOURCE_ROOT; };
+ 8B31FF7211F0C6E000FCF3E4 /* macho_reader.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = macho_reader.cc; path = ../../../common/mac/macho_reader.cc; sourceTree = SOURCE_ROOT; };
+ 8B31FF7311F0C6E000FCF3E4 /* macho_reader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = macho_reader.h; path = ../../../common/mac/macho_reader.h; sourceTree = SOURCE_ROOT; };
+ 8B31FF8411F0C6FB00FCF3E4 /* language.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = language.cc; path = ../../../common/language.cc; sourceTree = SOURCE_ROOT; };
+ 8B31FF8511F0C6FB00FCF3E4 /* language.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = language.h; path = ../../../common/language.h; sourceTree = SOURCE_ROOT; };
+ 8B31FF8611F0C6FB00FCF3E4 /* module.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = module.cc; path = ../../../common/module.cc; sourceTree = SOURCE_ROOT; };
+ 8B31FF8711F0C6FB00FCF3E4 /* module.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = module.h; path = ../../../common/module.h; sourceTree = SOURCE_ROOT; };
+ 8B31FFC311F0C8AB00FCF3E4 /* dwarf2diehandler.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = dwarf2diehandler.cc; path = ../../../common/dwarf/dwarf2diehandler.cc; sourceTree = SOURCE_ROOT; };
+ 8B31FFC411F0C8AB00FCF3E4 /* dwarf2diehandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dwarf2diehandler.h; path = ../../../common/dwarf/dwarf2diehandler.h; sourceTree = SOURCE_ROOT; };
+ 8B40BDBF0C0638E4009535AF /* logging.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = logging.cc; path = ../../../processor/logging.cc; sourceTree = SOURCE_ROOT; };
+ 8DD76FA10486AA7600D96B5E /* crash_report */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = crash_report; sourceTree = BUILT_PRODUCTS_DIR; };
+ 9B35FEE20B2675F9008DE8C7 /* code_module.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = code_module.h; path = ../../../google_breakpad/processor/code_module.h; sourceTree = SOURCE_ROOT; };
+ 9B35FEE30B2675F9008DE8C7 /* code_modules.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = code_modules.h; path = ../../../google_breakpad/processor/code_modules.h; sourceTree = SOURCE_ROOT; };
+ 9B35FEE60B26761C008DE8C7 /* basic_code_module.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = basic_code_module.h; path = ../../../processor/basic_code_module.h; sourceTree = SOURCE_ROOT; };
+ 9B35FEE70B26761C008DE8C7 /* basic_code_modules.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = basic_code_modules.cc; path = ../../../processor/basic_code_modules.cc; sourceTree = SOURCE_ROOT; };
+ 9B35FEE80B26761C008DE8C7 /* basic_code_modules.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = basic_code_modules.h; path = ../../../processor/basic_code_modules.h; sourceTree = SOURCE_ROOT; };
+ 9B3904940B2E52D90059FABE /* basic_source_line_resolver.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = basic_source_line_resolver.h; sourceTree = "<group>"; };
+ 9B3904950B2E52D90059FABE /* source_line_resolver_interface.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = source_line_resolver_interface.h; sourceTree = "<group>"; };
+ 9B3904980B2E52FD0059FABE /* basic_source_line_resolver.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = basic_source_line_resolver.cc; path = ../../../processor/basic_source_line_resolver.cc; sourceTree = SOURCE_ROOT; };
+ 9B44619D0B66C66B00BBB817 /* system_info.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = system_info.h; sourceTree = "<group>"; };
+ 9BDF16F90B1B8ACD00F8391B /* breakpad_types.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = breakpad_types.h; sourceTree = "<group>"; };
+ 9BDF16FA0B1B8ACD00F8391B /* minidump_format.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = minidump_format.h; sourceTree = "<group>"; };
+ 9BDF16FC0B1B8ACD00F8391B /* call_stack.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = call_stack.h; sourceTree = "<group>"; };
+ 9BDF16FD0B1B8ACD00F8391B /* memory_region.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = memory_region.h; sourceTree = "<group>"; };
+ 9BDF16FE0B1B8ACD00F8391B /* minidump.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = minidump.h; sourceTree = "<group>"; };
+ 9BDF16FF0B1B8ACD00F8391B /* minidump_processor.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = minidump_processor.h; sourceTree = "<group>"; };
+ 9BDF17000B1B8ACD00F8391B /* process_state.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = process_state.h; sourceTree = "<group>"; };
+ 9BDF17010B1B8ACD00F8391B /* stack_frame.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = stack_frame.h; sourceTree = "<group>"; };
+ 9BDF17020B1B8ACD00F8391B /* stack_frame_cpu.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = stack_frame_cpu.h; sourceTree = "<group>"; };
+ 9BDF17030B1B8ACD00F8391B /* stackwalker.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = stackwalker.h; sourceTree = "<group>"; };
+ 9BDF17040B1B8ACD00F8391B /* symbol_supplier.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = symbol_supplier.h; sourceTree = "<group>"; };
+ 9BDF172A0B1B8B2400F8391B /* call_stack.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = call_stack.cc; path = ../../../processor/call_stack.cc; sourceTree = SOURCE_ROOT; };
+ 9BDF172B0B1B8B2400F8391B /* minidump_processor.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = minidump_processor.cc; path = ../../../processor/minidump_processor.cc; sourceTree = SOURCE_ROOT; };
+ 9BDF173F0B1B8B9A00F8391B /* minidump.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = minidump.cc; path = ../../../processor/minidump.cc; sourceTree = SOURCE_ROOT; };
+ 9BDF17510B1B8BF900F8391B /* stackwalker_ppc.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = stackwalker_ppc.cc; path = ../../../processor/stackwalker_ppc.cc; sourceTree = SOURCE_ROOT; };
+ 9BDF17520B1B8BF900F8391B /* stackwalker_x86.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = stackwalker_x86.cc; path = ../../../processor/stackwalker_x86.cc; sourceTree = SOURCE_ROOT; };
+ 9BDF17530B1B8BF900F8391B /* stackwalker.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = stackwalker.cc; path = ../../../processor/stackwalker.cc; sourceTree = SOURCE_ROOT; };
+ 9BDF175B0B1B8C1B00F8391B /* process_state.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = process_state.cc; path = ../../../processor/process_state.cc; sourceTree = SOURCE_ROOT; };
+ 9BDF176B0B1B8CB100F8391B /* on_demand_symbol_supplier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = on_demand_symbol_supplier.h; sourceTree = "<group>"; };
+ 9BDF176C0B1B8CB100F8391B /* on_demand_symbol_supplier.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = on_demand_symbol_supplier.mm; sourceTree = "<group>"; };
+ 9BDF192D0B1BC15D00F8391B /* dump_syms.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = dump_syms.h; path = ../../../common/mac/dump_syms.h; sourceTree = SOURCE_ROOT; };
+ 9BDF192E0B1BC15D00F8391B /* dump_syms.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.objcpp; name = dump_syms.cc; path = ../../../common/mac/dump_syms.cc; sourceTree = SOURCE_ROOT; };
+ 9BDF1A270B1BD58200F8391B /* pathname_stripper.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = pathname_stripper.cc; path = ../../../processor/pathname_stripper.cc; sourceTree = SOURCE_ROOT; };
+ 9BDF1A7A0B1BE30100F8391B /* range_map-inl.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = "range_map-inl.h"; path = "../../../processor/range_map-inl.h"; sourceTree = SOURCE_ROOT; };
+ 9BDF1A7B0B1BE30100F8391B /* range_map.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = range_map.h; path = ../../../processor/range_map.h; sourceTree = SOURCE_ROOT; };
+ 9BDF1AFA0B1BEB6300F8391B /* address_map-inl.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = "address_map-inl.h"; path = "../../../processor/address_map-inl.h"; sourceTree = SOURCE_ROOT; };
+ 9BDF1AFB0B1BEB6300F8391B /* address_map.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = address_map.h; path = ../../../processor/address_map.h; sourceTree = SOURCE_ROOT; };
+ 9BE650AC0B52FE3000611104 /* file_id.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = file_id.cc; path = ../../../common/mac/file_id.cc; sourceTree = SOURCE_ROOT; };
+ 9BE650AD0B52FE3000611104 /* file_id.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = file_id.h; path = ../../../common/mac/file_id.h; sourceTree = SOURCE_ROOT; };
+ 9BE650AE0B52FE3000611104 /* macho_id.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = macho_id.cc; path = ../../../common/mac/macho_id.cc; sourceTree = SOURCE_ROOT; };
+ 9BE650AF0B52FE3000611104 /* macho_id.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = macho_id.h; path = ../../../common/mac/macho_id.h; sourceTree = SOURCE_ROOT; };
+ 9BE650B00B52FE3000611104 /* macho_walker.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = macho_walker.cc; path = ../../../common/mac/macho_walker.cc; sourceTree = SOURCE_ROOT; };
+ 9BE650B10B52FE3000611104 /* macho_walker.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = macho_walker.h; path = ../../../common/mac/macho_walker.h; sourceTree = SOURCE_ROOT; };
+ D2A5DD4C1188651100081F03 /* cfi_frame_info.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = cfi_frame_info.cc; path = ../../../processor/cfi_frame_info.cc; sourceTree = SOURCE_ROOT; };
+ D2A5DD621188658B00081F03 /* tokenize.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = tokenize.cc; path = ../../../processor/tokenize.cc; sourceTree = SOURCE_ROOT; };
+ F407DC40185773C10064622B /* exploitability_linux.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = exploitability_linux.cc; path = ../../../processor/exploitability_linux.cc; sourceTree = "<group>"; };
+ F407DC41185773C10064622B /* stack_frame_symbolizer.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = stack_frame_symbolizer.cc; path = ../../../processor/stack_frame_symbolizer.cc; sourceTree = "<group>"; };
+ F407DC42185773C10064622B /* stackwalker_arm64.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = stackwalker_arm64.cc; path = ../../../processor/stackwalker_arm64.cc; sourceTree = "<group>"; };
+ F407DC43185773C10064622B /* stackwalker_arm64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = stackwalker_arm64.h; path = ../../../processor/stackwalker_arm64.h; sourceTree = "<group>"; };
+ F407DC44185773C10064622B /* stackwalker_mips.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = stackwalker_mips.cc; path = ../../../processor/stackwalker_mips.cc; sourceTree = "<group>"; };
+ F407DC45185773C10064622B /* stackwalker_mips.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = stackwalker_mips.h; path = ../../../processor/stackwalker_mips.h; sourceTree = "<group>"; };
+ F407DC46185773C10064622B /* stackwalker_ppc64.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = stackwalker_ppc64.cc; path = ../../../processor/stackwalker_ppc64.cc; sourceTree = "<group>"; };
+ F407DC47185773C10064622B /* stackwalker_ppc64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = stackwalker_ppc64.h; path = ../../../processor/stackwalker_ppc64.h; sourceTree = "<group>"; };
+ F44DDD8419C85CD50047280E /* dump_context.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = dump_context.cc; path = ../../../processor/dump_context.cc; sourceTree = "<group>"; };
+ F44DDD8519C85CD50047280E /* dump_object.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = dump_object.cc; path = ../../../processor/dump_object.cc; sourceTree = "<group>"; };
+ F44DDD8619C85CD50047280E /* microdump_processor.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = microdump_processor.cc; path = ../../../processor/microdump_processor.cc; sourceTree = "<group>"; };
+ F44DDD8A19C85CFB0047280E /* dump_context.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = dump_context.h; path = ../../../google_breakpad/processor/dump_context.h; sourceTree = "<group>"; };
+ F44DDD8B19C85CFB0047280E /* dump_object.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = dump_object.h; path = ../../../google_breakpad/processor/dump_object.h; sourceTree = "<group>"; };
+ F44DDD8C19C85CFC0047280E /* microdump_processor.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = microdump_processor.h; path = ../../../google_breakpad/processor/microdump_processor.h; sourceTree = "<group>"; };
+ F44DDD8D19C85CFC0047280E /* process_result.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = process_result.h; path = ../../../google_breakpad/processor/process_result.h; sourceTree = "<group>"; };
+ F47180541D745DEF0032F208 /* elf_reader.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = elf_reader.cc; path = ../../../common/dwarf/elf_reader.cc; sourceTree = "<group>"; };
+ F47180551D745DEF0032F208 /* elf_reader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = elf_reader.h; path = ../../../common/dwarf/elf_reader.h; sourceTree = "<group>"; };
+ F47180571D7467630032F208 /* proc_maps_linux.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = proc_maps_linux.cc; path = ../../../processor/proc_maps_linux.cc; sourceTree = "<group>"; };
+ F47180591D7468A40032F208 /* symbolic_constants_win.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = symbolic_constants_win.cc; path = ../../../processor/symbolic_constants_win.cc; sourceTree = "<group>"; };
+ F4D43B2E1A38490700C290B2 /* microdump.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = microdump.cc; path = ../../../processor/microdump.cc; sourceTree = "<group>"; };
+ F4D43B301A38492000C290B2 /* microdump.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = microdump.h; path = ../../../google_breakpad/processor/microdump.h; sourceTree = "<group>"; };
+ F9C7ECE20E8ABCA600E953AD /* bytereader.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = bytereader.cc; path = ../../../common/dwarf/bytereader.cc; sourceTree = SOURCE_ROOT; };
+ F9C7ECE30E8ABCA600E953AD /* dwarf2reader.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = dwarf2reader.cc; path = ../../../common/dwarf/dwarf2reader.cc; sourceTree = SOURCE_ROOT; };
+ F9C7ECE40E8ABCA600E953AD /* functioninfo.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = functioninfo.cc; path = ../../../common/dwarf/functioninfo.cc; sourceTree = SOURCE_ROOT; };
+ F9F0706510FBC02D0037B88B /* stackwalker_arm.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = stackwalker_arm.cc; path = ../../../processor/stackwalker_arm.cc; sourceTree = SOURCE_ROOT; };
+ F9F0706610FBC02D0037B88B /* stackwalker_arm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = stackwalker_arm.h; path = ../../../processor/stackwalker_arm.h; sourceTree = SOURCE_ROOT; };
+ FD6625C40CF4D438004AC844 /* stackwalker_amd64.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = stackwalker_amd64.cc; path = ../../../processor/stackwalker_amd64.cc; sourceTree = SOURCE_ROOT; };
+ FD6625C50CF4D438004AC844 /* stackwalker_amd64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = stackwalker_amd64.h; path = ../../../processor/stackwalker_amd64.h; sourceTree = SOURCE_ROOT; };
+ FD8EDEAC0CADDAD400A5EDF1 /* stackwalker_sparc.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = stackwalker_sparc.cc; path = ../../../processor/stackwalker_sparc.cc; sourceTree = SOURCE_ROOT; };
+ FD8EDEAD0CADDAD400A5EDF1 /* stackwalker_sparc.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = stackwalker_sparc.h; path = ../../../processor/stackwalker_sparc.h; sourceTree = SOURCE_ROOT; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ 8DD76F9B0486AA7600D96B5E /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 8DD76F9C0486AA7600D96B5E /* Foundation.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 08FB7794FE84155DC02AAC07 /* crash_report */ = {
+ isa = PBXGroup;
+ children = (
+ 4214B7FE211109A600B769FA /* convert_old_arm64_context.cc */,
+ 4214B7FF211109A600B769FA /* convert_old_arm64_context.h */,
+ 4247E63F2110D5A500482558 /* path_helper.cc */,
+ 4247E63E2110D5A500482558 /* path_helper.h */,
+ 8B31025311F0D2D400FCF3E4 /* Breakpad.xcconfig */,
+ 8B3102DA11F0D65600FCF3E4 /* BreakpadDebug.xcconfig */,
+ 8B3102DB11F0D65600FCF3E4 /* BreakpadRelease.xcconfig */,
+ F9C7ECE10E8ABC7F00E953AD /* DWARF */,
+ 162F64FC161C5ECB00CD68D5 /* arch_utilities.cc */,
+ 162F64FD161C5ECB00CD68D5 /* arch_utilities.h */,
+ 5578003E0BE1F28500EC23E0 /* macho_utilities.cc */,
+ 5578003F0BE1F28500EC23E0 /* macho_utilities.h */,
+ 8B31FF7211F0C6E000FCF3E4 /* macho_reader.cc */,
+ 8B31FF7311F0C6E000FCF3E4 /* macho_reader.h */,
+ 9BDF192D0B1BC15D00F8391B /* dump_syms.h */,
+ 9BDF192E0B1BC15D00F8391B /* dump_syms.cc */,
+ 08FB7796FE84155DC02AAC07 /* crash_report.mm */,
+ F44DDD8D19C85CFC0047280E /* process_result.h */,
+ 9BDF176B0B1B8CB100F8391B /* on_demand_symbol_supplier.h */,
+ F44DDD8419C85CD50047280E /* dump_context.cc */,
+ F44DDD8A19C85CFB0047280E /* dump_context.h */,
+ F44DDD8519C85CD50047280E /* dump_object.cc */,
+ F44DDD8B19C85CFB0047280E /* dump_object.h */,
+ F4D43B2E1A38490700C290B2 /* microdump.cc */,
+ F4D43B301A38492000C290B2 /* microdump.h */,
+ F44DDD8619C85CD50047280E /* microdump_processor.cc */,
+ F44DDD8C19C85CFC0047280E /* microdump_processor.h */,
+ 9BDF176C0B1B8CB100F8391B /* on_demand_symbol_supplier.mm */,
+ 8B31FF2411F0C62700FCF3E4 /* dwarf_cfi_to_module.cc */,
+ 8B31FF2511F0C62700FCF3E4 /* dwarf_cfi_to_module.h */,
+ 8B31FF2611F0C62700FCF3E4 /* dwarf_cu_to_module.cc */,
+ 8B31FF2711F0C62700FCF3E4 /* dwarf_cu_to_module.h */,
+ 8B31FF2811F0C62700FCF3E4 /* dwarf_line_to_module.cc */,
+ 8B31FF2911F0C62700FCF3E4 /* dwarf_line_to_module.h */,
+ 8B31FF3D11F0C64400FCF3E4 /* stabs_reader.cc */,
+ 8B31FF3E11F0C64400FCF3E4 /* stabs_reader.h */,
+ 8B31FF3F11F0C64400FCF3E4 /* stabs_to_module.cc */,
+ 8B31FF4011F0C64400FCF3E4 /* stabs_to_module.h */,
+ 8B31FF8411F0C6FB00FCF3E4 /* language.cc */,
+ 8B31FF8511F0C6FB00FCF3E4 /* language.h */,
+ 4D72CA5613DFBA84006CABE3 /* md5.cc */,
+ 8B31FF8611F0C6FB00FCF3E4 /* module.cc */,
+ 8B31FF8711F0C6FB00FCF3E4 /* module.h */,
+ 08FB7795FE84155DC02AAC07 /* breakpad */,
+ 4D2C726E126F9CE200B43EAF /* libdisasm */,
+ 08FB779DFE84155DC02AAC07 /* External Frameworks and Libraries */,
+ 1AB674ADFE9D54B511CA2CBB /* Products */,
+ );
+ name = crash_report;
+ sourceTree = "<group>";
+ };
+ 08FB7795FE84155DC02AAC07 /* breakpad */ = {
+ isa = PBXGroup;
+ children = (
+ 9BE650AB0B52FE1A00611104 /* common */,
+ 9BDF17280B1B8B0200F8391B /* processor */,
+ 9BDF16F70B1B8ACD00F8391B /* google_breakpad */,
+ );
+ name = breakpad;
+ sourceTree = "<group>";
+ };
+ 08FB779DFE84155DC02AAC07 /* External Frameworks and Libraries */ = {
+ isa = PBXGroup;
+ children = (
+ 08FB779EFE84155DC02AAC07 /* Foundation.framework */,
+ );
+ name = "External Frameworks and Libraries";
+ sourceTree = "<group>";
+ };
+ 1AB674ADFE9D54B511CA2CBB /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 8DD76FA10486AA7600D96B5E /* crash_report */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+ 4D2C726E126F9CE200B43EAF /* libdisasm */ = {
+ isa = PBXGroup;
+ children = (
+ 4D2C7226126F9B0F00B43EAF /* disassembler_x86.cc */,
+ 4D2C724B126F9C3800B43EAF /* ia32_implicit.c */,
+ 4D2C7245126F9C0B00B43EAF /* ia32_insn.c */,
+ 4D2C7232126F9BB000B43EAF /* ia32_invariant.c */,
+ 4D2C7261126F9CBB00B43EAF /* ia32_modrm.c */,
+ 4D2C7249126F9C2300B43EAF /* ia32_opcode_tables.c */,
+ 4D2C725A126F9C8000B43EAF /* ia32_operand.c */,
+ 4D2C724D126F9C4D00B43EAF /* ia32_reg.c */,
+ 4D2C7234126F9BC200B43EAF /* ia32_settings.c */,
+ 4D2C722A126F9B5A00B43EAF /* x86_disasm.c */,
+ 4D2C7263126F9CBB00B43EAF /* x86_imm.c */,
+ 4D2C725C126F9C9200B43EAF /* x86_insn.c */,
+ 4D2C722C126F9B6E00B43EAF /* x86_misc.c */,
+ 4D2C722E126F9B8300B43EAF /* x86_operand_list.c */,
+ );
+ name = libdisasm;
+ sourceTree = "<group>";
+ };
+ 9BDF16F70B1B8ACD00F8391B /* google_breakpad */ = {
+ isa = PBXGroup;
+ children = (
+ 9BDF16F80B1B8ACD00F8391B /* common */,
+ 9BDF16FB0B1B8ACD00F8391B /* processor */,
+ );
+ name = google_breakpad;
+ path = ../../../google_breakpad;
+ sourceTree = SOURCE_ROOT;
+ };
+ 9BDF16F80B1B8ACD00F8391B /* common */ = {
+ isa = PBXGroup;
+ children = (
+ 9BDF16F90B1B8ACD00F8391B /* breakpad_types.h */,
+ 9BDF16FA0B1B8ACD00F8391B /* minidump_format.h */,
+ );
+ path = common;
+ sourceTree = "<group>";
+ };
+ 9BDF16FB0B1B8ACD00F8391B /* processor */ = {
+ isa = PBXGroup;
+ children = (
+ 9B3904940B2E52D90059FABE /* basic_source_line_resolver.h */,
+ 9BDF16FC0B1B8ACD00F8391B /* call_stack.h */,
+ 9B35FEE20B2675F9008DE8C7 /* code_module.h */,
+ 9B35FEE30B2675F9008DE8C7 /* code_modules.h */,
+ 9BDF16FD0B1B8ACD00F8391B /* memory_region.h */,
+ 9BDF16FE0B1B8ACD00F8391B /* minidump.h */,
+ 9BDF16FF0B1B8ACD00F8391B /* minidump_processor.h */,
+ 9BDF17000B1B8ACD00F8391B /* process_state.h */,
+ 9B3904950B2E52D90059FABE /* source_line_resolver_interface.h */,
+ 9BDF17010B1B8ACD00F8391B /* stack_frame.h */,
+ 9BDF17020B1B8ACD00F8391B /* stack_frame_cpu.h */,
+ 9BDF17030B1B8ACD00F8391B /* stackwalker.h */,
+ 9BDF17040B1B8ACD00F8391B /* symbol_supplier.h */,
+ 9B44619D0B66C66B00BBB817 /* system_info.h */,
+ );
+ path = processor;
+ sourceTree = "<group>";
+ };
+ 9BDF17280B1B8B0200F8391B /* processor */ = {
+ isa = PBXGroup;
+ children = (
+ 4D2C7222126F9AF900B43EAF /* exploitability_win.cc */,
+ F407DC40185773C10064622B /* exploitability_linux.cc */,
+ F407DC41185773C10064622B /* stack_frame_symbolizer.cc */,
+ F407DC42185773C10064622B /* stackwalker_arm64.cc */,
+ F407DC43185773C10064622B /* stackwalker_arm64.h */,
+ F407DC44185773C10064622B /* stackwalker_mips.cc */,
+ F407DC45185773C10064622B /* stackwalker_mips.h */,
+ F407DC46185773C10064622B /* stackwalker_ppc64.cc */,
+ F407DC47185773C10064622B /* stackwalker_ppc64.h */,
+ 4D2C721E126F9ADE00B43EAF /* exploitability.cc */,
+ 4D2C721A126F9ACC00B43EAF /* source_line_resolver_base.cc */,
+ D2A5DD621188658B00081F03 /* tokenize.cc */,
+ D2A5DD4C1188651100081F03 /* cfi_frame_info.cc */,
+ F9F0706510FBC02D0037B88B /* stackwalker_arm.cc */,
+ F9F0706610FBC02D0037B88B /* stackwalker_arm.h */,
+ 9B3904980B2E52FD0059FABE /* basic_source_line_resolver.cc */,
+ 9BDF1AFA0B1BEB6300F8391B /* address_map-inl.h */,
+ 9BDF1AFB0B1BEB6300F8391B /* address_map.h */,
+ 9B35FEE60B26761C008DE8C7 /* basic_code_module.h */,
+ 9B35FEE70B26761C008DE8C7 /* basic_code_modules.cc */,
+ 9B35FEE80B26761C008DE8C7 /* basic_code_modules.h */,
+ 9BDF172A0B1B8B2400F8391B /* call_stack.cc */,
+ 8B40BDBF0C0638E4009535AF /* logging.cc */,
+ 9BDF173F0B1B8B9A00F8391B /* minidump.cc */,
+ 9BDF172B0B1B8B2400F8391B /* minidump_processor.cc */,
+ 9BDF1A270B1BD58200F8391B /* pathname_stripper.cc */,
+ F47180571D7467630032F208 /* proc_maps_linux.cc */,
+ 9BDF175B0B1B8C1B00F8391B /* process_state.cc */,
+ 9BDF1A7A0B1BE30100F8391B /* range_map-inl.h */,
+ 9BDF1A7B0B1BE30100F8391B /* range_map.h */,
+ 9BDF17530B1B8BF900F8391B /* stackwalker.cc */,
+ 9BDF17510B1B8BF900F8391B /* stackwalker_ppc.cc */,
+ 9BDF17520B1B8BF900F8391B /* stackwalker_x86.cc */,
+ FD8EDEAC0CADDAD400A5EDF1 /* stackwalker_sparc.cc */,
+ FD8EDEAD0CADDAD400A5EDF1 /* stackwalker_sparc.h */,
+ FD6625C40CF4D438004AC844 /* stackwalker_amd64.cc */,
+ FD6625C50CF4D438004AC844 /* stackwalker_amd64.h */,
+ F47180591D7468A40032F208 /* symbolic_constants_win.cc */,
+ );
+ name = processor;
+ sourceTree = "<group>";
+ };
+ 9BE650AB0B52FE1A00611104 /* common */ = {
+ isa = PBXGroup;
+ children = (
+ 9BE650AC0B52FE3000611104 /* file_id.cc */,
+ 9BE650AD0B52FE3000611104 /* file_id.h */,
+ 9BE650AE0B52FE3000611104 /* macho_id.cc */,
+ 9BE650AF0B52FE3000611104 /* macho_id.h */,
+ 9BE650B00B52FE3000611104 /* macho_walker.cc */,
+ 9BE650B10B52FE3000611104 /* macho_walker.h */,
+ );
+ name = common;
+ sourceTree = "<group>";
+ };
+ F9C7ECE10E8ABC7F00E953AD /* DWARF */ = {
+ isa = PBXGroup;
+ children = (
+ F9C7ECE20E8ABCA600E953AD /* bytereader.cc */,
+ F9C7ECE30E8ABCA600E953AD /* dwarf2reader.cc */,
+ 8B31FFC311F0C8AB00FCF3E4 /* dwarf2diehandler.cc */,
+ 8B31FFC411F0C8AB00FCF3E4 /* dwarf2diehandler.h */,
+ F47180541D745DEF0032F208 /* elf_reader.cc */,
+ F47180551D745DEF0032F208 /* elf_reader.h */,
+ F9C7ECE40E8ABCA600E953AD /* functioninfo.cc */,
+ );
+ name = DWARF;
+ sourceTree = "<group>";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+ 8DD76F960486AA7600D96B5E /* crash_report */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 1DEB927408733DD40010E9CD /* Build configuration list for PBXNativeTarget "crash_report" */;
+ buildPhases = (
+ 8DD76F990486AA7600D96B5E /* Sources */,
+ 8DD76F9B0486AA7600D96B5E /* Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = crash_report;
+ productInstallPath = "$(HOME)/bin";
+ productName = crash_report;
+ productReference = 8DD76FA10486AA7600D96B5E /* crash_report */;
+ productType = "com.apple.product-type.tool";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 08FB7793FE84155DC02AAC07 /* Project object */ = {
+ isa = PBXProject;
+ attributes = {
+ };
+ buildConfigurationList = 1DEB927808733DD40010E9CD /* Build configuration list for PBXProject "crash_report" */;
+ compatibilityVersion = "Xcode 3.1";
+ developmentRegion = en;
+ hasScannedForEncodings = 1;
+ knownRegions = (
+ English,
+ Japanese,
+ French,
+ German,
+ );
+ mainGroup = 08FB7794FE84155DC02AAC07 /* crash_report */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ 8DD76F960486AA7600D96B5E /* crash_report */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXSourcesBuildPhase section */
+ 8DD76F990486AA7600D96B5E /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 162F64FE161C5ECB00CD68D5 /* arch_utilities.cc in Sources */,
+ 8DD76F9A0486AA7600D96B5E /* crash_report.mm in Sources */,
+ F47180581D7467630032F208 /* proc_maps_linux.cc in Sources */,
+ 9BDF172C0B1B8B2400F8391B /* call_stack.cc in Sources */,
+ 9BDF172D0B1B8B2400F8391B /* minidump_processor.cc in Sources */,
+ 9BDF17410B1B8B9A00F8391B /* minidump.cc in Sources */,
+ F44DDD8719C85CD50047280E /* dump_context.cc in Sources */,
+ 9BDF17540B1B8BF900F8391B /* stackwalker_ppc.cc in Sources */,
+ 9BDF17550B1B8BF900F8391B /* stackwalker_x86.cc in Sources */,
+ 9BDF17560B1B8BF900F8391B /* stackwalker.cc in Sources */,
+ 9BDF175D0B1B8C1B00F8391B /* process_state.cc in Sources */,
+ F47180561D745DEF0032F208 /* elf_reader.cc in Sources */,
+ 9BDF176E0B1B8CB100F8391B /* on_demand_symbol_supplier.mm in Sources */,
+ 9BDF1A280B1BD58200F8391B /* pathname_stripper.cc in Sources */,
+ 9BDF21A70B1E825400F8391B /* dump_syms.cc in Sources */,
+ 9B35FEEA0B26761C008DE8C7 /* basic_code_modules.cc in Sources */,
+ 9B3904990B2E52FD0059FABE /* basic_source_line_resolver.cc in Sources */,
+ 9BE650B20B52FE3000611104 /* file_id.cc in Sources */,
+ 9BE650B40B52FE3000611104 /* macho_id.cc in Sources */,
+ 9BE650B60B52FE3000611104 /* macho_walker.cc in Sources */,
+ 557800400BE1F28500EC23E0 /* macho_utilities.cc in Sources */,
+ 8B40BDC00C0638E4009535AF /* logging.cc in Sources */,
+ FD8EDEAE0CADDAD400A5EDF1 /* stackwalker_sparc.cc in Sources */,
+ FD6625CD0CF4D45C004AC844 /* stackwalker_amd64.cc in Sources */,
+ F9C7ECE50E8ABCA600E953AD /* bytereader.cc in Sources */,
+ F9C7ECE60E8ABCA600E953AD /* dwarf2reader.cc in Sources */,
+ F9C7ECE70E8ABCA600E953AD /* functioninfo.cc in Sources */,
+ F9F0706710FBC02D0037B88B /* stackwalker_arm.cc in Sources */,
+ D2A5DD4D1188651100081F03 /* cfi_frame_info.cc in Sources */,
+ D2A5DD631188658B00081F03 /* tokenize.cc in Sources */,
+ 8B31FF2A11F0C62700FCF3E4 /* dwarf_cfi_to_module.cc in Sources */,
+ F4D43B2F1A38490700C290B2 /* microdump.cc in Sources */,
+ 8B31FF2B11F0C62700FCF3E4 /* dwarf_cu_to_module.cc in Sources */,
+ F44DDD8819C85CD50047280E /* dump_object.cc in Sources */,
+ 8B31FF2C11F0C62700FCF3E4 /* dwarf_line_to_module.cc in Sources */,
+ 8B31FF4111F0C64400FCF3E4 /* stabs_reader.cc in Sources */,
+ 8B31FF4211F0C64400FCF3E4 /* stabs_to_module.cc in Sources */,
+ 8B31FF7411F0C6E000FCF3E4 /* macho_reader.cc in Sources */,
+ 8B31FF8811F0C6FB00FCF3E4 /* language.cc in Sources */,
+ 8B31FF8911F0C6FB00FCF3E4 /* module.cc in Sources */,
+ 8B31FFC511F0C8AB00FCF3E4 /* dwarf2diehandler.cc in Sources */,
+ F407DC49185773C10064622B /* stack_frame_symbolizer.cc in Sources */,
+ F471805A1D7468A40032F208 /* symbolic_constants_win.cc in Sources */,
+ 4D2C721B126F9ACC00B43EAF /* source_line_resolver_base.cc in Sources */,
+ 4D2C721F126F9ADE00B43EAF /* exploitability.cc in Sources */,
+ 4D2C7223126F9AF900B43EAF /* exploitability_win.cc in Sources */,
+ 4D2C7227126F9B0F00B43EAF /* disassembler_x86.cc in Sources */,
+ F407DC48185773C10064622B /* exploitability_linux.cc in Sources */,
+ 4214B800211109A600B769FA /* convert_old_arm64_context.cc in Sources */,
+ 4D2C722B126F9B5A00B43EAF /* x86_disasm.c in Sources */,
+ 4D2C722D126F9B6E00B43EAF /* x86_misc.c in Sources */,
+ 4D2C722F126F9B8300B43EAF /* x86_operand_list.c in Sources */,
+ F407DC4A185773C10064622B /* stackwalker_arm64.cc in Sources */,
+ 4D2C7233126F9BB000B43EAF /* ia32_invariant.c in Sources */,
+ 4D2C7235126F9BC200B43EAF /* ia32_settings.c in Sources */,
+ 4D2C7246126F9C0B00B43EAF /* ia32_insn.c in Sources */,
+ 4D2C724A126F9C2300B43EAF /* ia32_opcode_tables.c in Sources */,
+ 4D2C724C126F9C3800B43EAF /* ia32_implicit.c in Sources */,
+ 4247E6402110D5A500482558 /* path_helper.cc in Sources */,
+ F44DDD8919C85CD50047280E /* microdump_processor.cc in Sources */,
+ 4D2C724E126F9C4D00B43EAF /* ia32_reg.c in Sources */,
+ 4D2C725B126F9C8000B43EAF /* ia32_operand.c in Sources */,
+ F407DC4C185773C10064622B /* stackwalker_ppc64.cc in Sources */,
+ 4D2C725D126F9C9200B43EAF /* x86_insn.c in Sources */,
+ 4D2C7264126F9CBB00B43EAF /* ia32_modrm.c in Sources */,
+ F407DC4B185773C10064622B /* stackwalker_mips.cc in Sources */,
+ 4D2C726D126F9CDC00B43EAF /* x86_imm.c in Sources */,
+ 4D72CA5713DFBA84006CABE3 /* md5.cc in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin XCBuildConfiguration section */
+ 1DEB927508733DD40010E9CD /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CLANG_CXX_LANGUAGE_STANDARD = "c++0x";
+ HEADER_SEARCH_PATHS = ../../../../src;
+ PRODUCT_NAME = crash_report;
+ };
+ name = Debug;
+ };
+ 1DEB927608733DD40010E9CD /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CLANG_CXX_LANGUAGE_STANDARD = "c++0x";
+ HEADER_SEARCH_PATHS = ../../../../src;
+ PRODUCT_NAME = crash_report;
+ };
+ name = Release;
+ };
+ 1DEB927908733DD40010E9CD /* Debug */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 8B3102DA11F0D65600FCF3E4 /* BreakpadDebug.xcconfig */;
+ buildSettings = {
+ GCC_PREPROCESSOR_DEFINITIONS = HAVE_MACH_O_NLIST_H;
+ GCC_TREAT_WARNINGS_AS_ERRORS = NO;
+ };
+ name = Debug;
+ };
+ 1DEB927A08733DD40010E9CD /* Release */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 8B3102DB11F0D65600FCF3E4 /* BreakpadRelease.xcconfig */;
+ buildSettings = {
+ GCC_PREPROCESSOR_DEFINITIONS = HAVE_MACH_O_NLIST_H;
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ 1DEB927408733DD40010E9CD /* Build configuration list for PBXNativeTarget "crash_report" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 1DEB927508733DD40010E9CD /* Debug */,
+ 1DEB927608733DD40010E9CD /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 1DEB927808733DD40010E9CD /* Build configuration list for PBXProject "crash_report" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 1DEB927908733DD40010E9CD /* Debug */,
+ 1DEB927A08733DD40010E9CD /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = 08FB7793FE84155DC02AAC07 /* Project object */;
+}
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/mac/crash_report/on_demand_symbol_supplier.h b/toolkit/crashreporter/google-breakpad/src/tools/mac/crash_report/on_demand_symbol_supplier.h
new file mode 100644
index 0000000000..3fbe108ebd
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/mac/crash_report/on_demand_symbol_supplier.h
@@ -0,0 +1,111 @@
+// 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.
+
+// on_demand_symbol_supplier.h: Provides a Symbol Supplier that will create
+// a breakpad symbol file on demand.
+
+#ifndef TOOLS_MAC_CRASH_REPORT_ON_DEMAND_SYMBOL_SUPPLIER_H__
+#define TOOLS_MAC_CRASH_REPORT_ON_DEMAND_SYMBOL_SUPPLIER_H__
+
+#include <map>
+#include <string>
+#include "google_breakpad/processor/symbol_supplier.h"
+
+namespace google_breakpad {
+
+using std::map;
+using std::string;
+class MinidumpModule;
+
+class OnDemandSymbolSupplier : public SymbolSupplier {
+ public:
+ // |search_dir| is the directory to search for alternative symbols with
+ // the same name as the module in the minidump
+ OnDemandSymbolSupplier(const string &search_dir,
+ const string &symbol_search_dir);
+ virtual ~OnDemandSymbolSupplier() {}
+
+ // Returns the path to the symbol file for the given module.
+ virtual SymbolResult GetSymbolFile(const CodeModule *module,
+ const SystemInfo *system_info,
+ string *symbol_file);
+
+ // Returns the path to the symbol file for the given module.
+ virtual SymbolResult GetSymbolFile(const CodeModule *module,
+ const SystemInfo *system_info,
+ string *symbol_file,
+ string *symbol_data);
+ // Allocates data buffer on heap, and takes the ownership of
+ // the data buffer.
+ virtual SymbolResult GetCStringSymbolData(const CodeModule *module,
+ const SystemInfo *system_info,
+ string *symbol_file,
+ char **symbol_data,
+ size_t *symbol_data_size);
+
+ // Delete the data buffer allocated for module in GetCStringSymbolData().
+ virtual void FreeSymbolData(const CodeModule *module);
+
+ protected:
+ // Search directory
+ string search_dir_;
+ string symbol_search_dir_;
+
+ // When we create a symbol file for a module, save the name of the module
+ // and the path to that module's symbol file.
+ map<string, string> module_file_map_;
+
+ // Map of allocated data buffers, keyed by module->code_file().
+ map<string, char *> memory_buffers_;
+
+ // Return the name for |module| This will be the value used as the key
+ // to the |module_file_map_|.
+ string GetNameForModule(const CodeModule *module);
+
+ // Find the module on local system. If the module resides in a different
+ // location than the full path in the minidump, this will be the location
+ // used.
+ string GetLocalModulePath(const CodeModule *module);
+
+ // Return the full path for |module|.
+ string GetModulePath(const CodeModule *module);
+
+ // Return the path to the symbol file for |module|. If an empty string is
+ // returned, then |module| doesn't have a symbol file.
+ string GetModuleSymbolFile(const CodeModule *module);
+
+ // Generate the breakpad symbol file for |module|. Return true if successful.
+ // File is generated in /tmp.
+ bool GenerateSymbolFile(const CodeModule *module,
+ const SystemInfo *system_info);
+};
+
+} // namespace google_breakpad
+
+#endif // TOOLS_MAC_CRASH_REPORT_ON_DEMAND_SYMBOL_SUPPLIER_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/mac/crash_report/on_demand_symbol_supplier.mm b/toolkit/crashreporter/google-breakpad/src/tools/mac/crash_report/on_demand_symbol_supplier.mm
new file mode 100644
index 0000000000..1955d2667b
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/mac/crash_report/on_demand_symbol_supplier.mm
@@ -0,0 +1,314 @@
+// 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 <Foundation/Foundation.h>
+#include <sys/stat.h>
+#include <map>
+#include <string>
+#include <iostream>
+#include <fstream>
+#include <utility>
+
+#include "google_breakpad/processor/basic_source_line_resolver.h"
+#include "google_breakpad/processor/minidump.h"
+#include "google_breakpad/processor/system_info.h"
+#include "processor/pathname_stripper.h"
+
+#include "on_demand_symbol_supplier.h"
+#include "common/mac/dump_syms.h"
+
+using std::map;
+using std::string;
+
+using google_breakpad::OnDemandSymbolSupplier;
+using google_breakpad::PathnameStripper;
+using google_breakpad::SymbolSupplier;
+using google_breakpad::SystemInfo;
+
+OnDemandSymbolSupplier::OnDemandSymbolSupplier(const string &search_dir,
+ const string &symbol_search_dir)
+ : search_dir_(search_dir) {
+ NSFileManager *mgr = [NSFileManager defaultManager];
+ size_t length = symbol_search_dir.length();
+ if (length) {
+ // Load all sym files in symbol_search_dir into our module_file_map
+ // A symbol file always starts with a line like this:
+ // MODULE mac x86 BBF0A8F9BEADDD2048E6464001CA193F0 GoogleDesktopDaemon
+ // or
+ // MODULE mac ppc BBF0A8F9BEADDD2048E6464001CA193F0 GoogleDesktopDaemon
+ const char *symbolSearchStr = symbol_search_dir.c_str();
+ NSString *symbolSearchPath =
+ [mgr stringWithFileSystemRepresentation:symbolSearchStr
+ length:strlen(symbolSearchStr)];
+ NSDirectoryEnumerator *dirEnum = [mgr enumeratorAtPath:symbolSearchPath];
+ NSString *fileName;
+ NSCharacterSet *hexSet =
+ [NSCharacterSet characterSetWithCharactersInString:@"0123456789ABCDEF"];
+ NSCharacterSet *newlineSet =
+ [NSCharacterSet characterSetWithCharactersInString:@"\r\n"];
+ while ((fileName = [dirEnum nextObject])) {
+ // Check to see what type of file we have
+ NSDictionary *attrib = [dirEnum fileAttributes];
+ NSString *fileType = [attrib objectForKey:NSFileType];
+ if ([fileType isEqualToString:NSFileTypeDirectory]) {
+ // Skip subdirectories
+ [dirEnum skipDescendents];
+ } else {
+ NSString *filePath = [symbolSearchPath stringByAppendingPathComponent:fileName];
+ NSString *dataStr = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:NULL];
+ if (dataStr) {
+ // Check file to see if it is of appropriate type, and grab module
+ // name.
+ NSScanner *scanner = [NSScanner scannerWithString:dataStr];
+ BOOL goodScan = [scanner scanString:@"MODULE mac " intoString:nil];
+ if (goodScan) {
+ goodScan = ([scanner scanString:@"x86 " intoString:nil] ||
+ [scanner scanString:@"x86_64 " intoString:nil] ||
+ [scanner scanString:@"ppc " intoString:nil]);
+ if (goodScan) {
+ NSString *moduleID;
+ goodScan = [scanner scanCharactersFromSet:hexSet
+ intoString:&moduleID];
+ if (goodScan) {
+ // Module IDs are always 33 chars long
+ goodScan = [moduleID length] == 33;
+ if (goodScan) {
+ NSString *moduleName;
+ goodScan = [scanner scanUpToCharactersFromSet:newlineSet
+ intoString:&moduleName];
+ if (goodScan) {
+ goodScan = [moduleName length] > 0;
+ if (goodScan) {
+ const char *moduleNameStr = [moduleName UTF8String];
+ const char *filePathStr = [filePath fileSystemRepresentation];
+ // Map our file
+ module_file_map_[moduleNameStr] = filePathStr;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+SymbolSupplier::SymbolResult
+OnDemandSymbolSupplier::GetSymbolFile(const CodeModule *module,
+ const SystemInfo *system_info,
+ string *symbol_file) {
+ string path(GetModuleSymbolFile(module));
+
+ if (path.empty()) {
+ if (!GenerateSymbolFile(module, system_info))
+ return NOT_FOUND;
+
+ path = GetModuleSymbolFile(module);
+ }
+
+ if (path.empty())
+ return NOT_FOUND;
+
+ *symbol_file = path;
+ return FOUND;
+}
+
+SymbolSupplier::SymbolResult
+OnDemandSymbolSupplier::GetSymbolFile(const CodeModule *module,
+ const SystemInfo *system_info,
+ string *symbol_file,
+ string *symbol_data) {
+ SymbolSupplier::SymbolResult s = GetSymbolFile(module,
+ system_info,
+ symbol_file);
+
+
+ if (s == FOUND) {
+ std::ifstream in(symbol_file->c_str());
+ getline(in, *symbol_data, std::string::traits_type::to_char_type(
+ std::string::traits_type::eof()));
+ in.close();
+ }
+
+ return s;
+}
+
+SymbolSupplier::SymbolResult
+OnDemandSymbolSupplier::GetCStringSymbolData(const CodeModule *module,
+ const SystemInfo *system_info,
+ string *symbol_file,
+ char **symbol_data,
+ size_t *symbol_data_size) {
+ std::string symbol_data_string;
+ SymbolSupplier::SymbolResult result = GetSymbolFile(module,
+ system_info,
+ symbol_file,
+ &symbol_data_string);
+ if (result == FOUND) {
+ *symbol_data_size = symbol_data_string.size() + 1;
+ *symbol_data = new char[*symbol_data_size];
+ if (*symbol_data == NULL) {
+ // Should return INTERRUPT on memory allocation failure.
+ return INTERRUPT;
+ }
+ memcpy(*symbol_data, symbol_data_string.c_str(), symbol_data_string.size());
+ (*symbol_data)[symbol_data_string.size()] = '\0';
+ memory_buffers_.insert(make_pair(module->code_file(), *symbol_data));
+ }
+ return result;
+}
+
+void OnDemandSymbolSupplier::FreeSymbolData(const CodeModule *module) {
+ map<string, char *>::iterator it = memory_buffers_.find(module->code_file());
+ if (it != memory_buffers_.end()) {
+ delete [] it->second;
+ memory_buffers_.erase(it);
+ }
+}
+
+string OnDemandSymbolSupplier::GetLocalModulePath(const CodeModule *module) {
+ NSFileManager *mgr = [NSFileManager defaultManager];
+ const char *moduleStr = module->code_file().c_str();
+ NSString *modulePath =
+ [mgr stringWithFileSystemRepresentation:moduleStr length:strlen(moduleStr)];
+ const char *searchStr = search_dir_.c_str();
+ NSString *searchDir =
+ [mgr stringWithFileSystemRepresentation:searchStr length:strlen(searchStr)];
+
+ if ([mgr fileExistsAtPath:modulePath])
+ return module->code_file();
+
+ // If the module is not found, try to start appending the components to the
+ // search string and stop if a file (not dir) is found or all components
+ // have been appended
+ NSArray *pathComponents = [modulePath componentsSeparatedByString:@"/"];
+ size_t count = [pathComponents count];
+ NSMutableString *path = [NSMutableString string];
+
+ for (size_t i = 0; i < count; ++i) {
+ [path setString:searchDir];
+
+ for (size_t j = 0; j < i + 1; ++j) {
+ size_t idx = count - 1 - i + j;
+ [path appendFormat:@"/%@", [pathComponents objectAtIndex:idx]];
+ }
+
+ BOOL isDir;
+ if ([mgr fileExistsAtPath:path isDirectory:&isDir] && (!isDir)) {
+ return [path fileSystemRepresentation];
+ }
+ }
+
+ return "";
+}
+
+string OnDemandSymbolSupplier::GetModulePath(const CodeModule *module) {
+ return module->code_file();
+}
+
+string OnDemandSymbolSupplier::GetNameForModule(const CodeModule *module) {
+ return PathnameStripper::File(module->code_file());
+}
+
+string OnDemandSymbolSupplier::GetModuleSymbolFile(const CodeModule *module) {
+ string name(GetNameForModule(module));
+ map<string, string>::iterator result = module_file_map_.find(name);
+
+ return (result == module_file_map_.end()) ? "" : (*result).second;
+}
+
+static float GetFileModificationTime(const char *path) {
+ float result = 0;
+ struct stat file_stat;
+ if (stat(path, &file_stat) == 0)
+ result = (float)file_stat.st_mtimespec.tv_sec +
+ (float)file_stat.st_mtimespec.tv_nsec / 1.0e9f;
+
+ return result;
+}
+
+bool OnDemandSymbolSupplier::GenerateSymbolFile(const CodeModule *module,
+ const SystemInfo *system_info) {
+ bool result = true;
+ string name = GetNameForModule(module);
+ string module_path = GetLocalModulePath(module);
+ NSString *symbol_path = [NSString stringWithFormat:@"/tmp/%s.%s.sym",
+ name.c_str(), system_info->cpu.c_str()];
+
+ if (module_path.empty())
+ return false;
+
+ // Check if there's already a symbol file cached. Ensure that the file is
+ // newer than the module. Otherwise, generate a new one.
+ BOOL generate_file = YES;
+ if ([[NSFileManager defaultManager] fileExistsAtPath:symbol_path]) {
+ // Check if the module file is newer than the saved symbols
+ float cache_time =
+ GetFileModificationTime([symbol_path fileSystemRepresentation]);
+ float module_time =
+ GetFileModificationTime(module_path.c_str());
+
+ if (cache_time > module_time)
+ generate_file = NO;
+ }
+
+ if (generate_file) {
+ DumpSymbols dump(ALL_SYMBOL_DATA, false);
+ if (dump.Read(module_path)) {
+ // What Breakpad calls "x86" should be given to the system as "i386".
+ std::string architecture;
+ if (system_info->cpu.compare("x86") == 0) {
+ architecture = "i386";
+ } else {
+ architecture = system_info->cpu;
+ }
+
+ if (dump.SetArchitecture(architecture)) {
+ std::fstream file([symbol_path fileSystemRepresentation],
+ std::ios_base::out | std::ios_base::trunc);
+ dump.WriteSymbolFile(file);
+ } else {
+ printf("Architecture %s not available for %s\n",
+ system_info->cpu.c_str(), name.c_str());
+ result = false;
+ }
+ } else {
+ printf("Unable to open %s\n", module_path.c_str());
+ result = false;
+ }
+ }
+
+ // Add the mapping
+ if (result)
+ module_file_map_[name] = [symbol_path fileSystemRepresentation];
+
+ return result;
+}
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/mac/dump_syms/dump_syms.xcodeproj/project.pbxproj b/toolkit/crashreporter/google-breakpad/src/tools/mac/dump_syms/dump_syms.xcodeproj/project.pbxproj
new file mode 100644
index 0000000000..5b644e24c8
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/mac/dump_syms/dump_syms.xcodeproj/project.pbxproj
@@ -0,0 +1,1857 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 45;
+ objects = {
+
+/* Begin PBXAggregateTarget section */
+ B88FAFC9116BDCAD00407530 /* all_unittests */ = {
+ isa = PBXAggregateTarget;
+ buildConfigurationList = B88FAFCC116BDCCC00407530 /* Build configuration list for PBXAggregateTarget "all_unittests" */;
+ buildPhases = (
+ B88FB094116CE73E00407530 /* ShellScript */,
+ );
+ dependencies = (
+ B88FB15B116CF53E00407530 /* PBXTargetDependency */,
+ B88FAFCF116BDD7000407530 /* PBXTargetDependency */,
+ B88FB01D116BDF9800407530 /* PBXTargetDependency */,
+ B88FB167116CF54B00407530 /* PBXTargetDependency */,
+ B88FAFD1116BDD7000407530 /* PBXTargetDependency */,
+ B88FB165116CF54B00407530 /* PBXTargetDependency */,
+ B88FB161116CF54B00407530 /* PBXTargetDependency */,
+ B88FB15F116CF54B00407530 /* PBXTargetDependency */,
+ B88FB15D116CF54B00407530 /* PBXTargetDependency */,
+ B84A9201116CF7D2006C210E /* PBXTargetDependency */,
+ B88FB0C8116CEB4A00407530 /* PBXTargetDependency */,
+ 8B31051511F100CF00FCF3E4 /* PBXTargetDependency */,
+ );
+ name = all_unittests;
+ productName = all_unittests;
+ };
+/* End PBXAggregateTarget section */
+
+/* Begin PBXBuildFile section */
+ 162F64FA161C591500CD68D5 /* arch_utilities.cc in Sources */ = {isa = PBXBuildFile; fileRef = 162F64F8161C591500CD68D5 /* arch_utilities.cc */; };
+ 162F6500161C5F2200CD68D5 /* arch_utilities.cc in Sources */ = {isa = PBXBuildFile; fileRef = 162F64F8161C591500CD68D5 /* arch_utilities.cc */; };
+ 4247E63D2110D4B200482558 /* path_helper.cc in Sources */ = {isa = PBXBuildFile; fileRef = EB06C7511FEBC515000214D9 /* path_helper.cc */; };
+ 4262382721AC496F00E5A3A6 /* dwarf_range_list_handler.cc in Sources */ = {isa = PBXBuildFile; fileRef = 4262382521AC496F00E5A3A6 /* dwarf_range_list_handler.cc */; };
+ 4262382821AC49A000E5A3A6 /* dwarf_range_list_handler.h in Sources */ = {isa = PBXBuildFile; fileRef = 4262382621AC496F00E5A3A6 /* dwarf_range_list_handler.h */; };
+ 4D72CAF513DFBAC2006CABE3 /* md5.cc in Sources */ = {isa = PBXBuildFile; fileRef = 4D72CAF413DFBAC2006CABE3 /* md5.cc */; };
+ 8BCAAA4C1CE3A7980046090B /* elf_reader.cc in Sources */ = {isa = PBXBuildFile; fileRef = 8BCAAA4A1CE3A7980046090B /* elf_reader.cc */; };
+ 8BCAAA4D1CE3B1260046090B /* elf_reader.cc in Sources */ = {isa = PBXBuildFile; fileRef = 8BCAAA4A1CE3A7980046090B /* elf_reader.cc */; };
+ B84A91F8116CF78F006C210E /* libgtestmockall.a in Frameworks */ = {isa = PBXBuildFile; fileRef = B88FB024116BDFFF00407530 /* libgtestmockall.a */; };
+ B84A91FB116CF7AF006C210E /* module.cc in Sources */ = {isa = PBXBuildFile; fileRef = B88FAE241166603300407530 /* module.cc */; };
+ B84A91FC116CF7AF006C210E /* stabs_to_module.cc in Sources */ = {isa = PBXBuildFile; fileRef = B88FAE3C11666C8900407530 /* stabs_to_module.cc */; };
+ B84A91FD116CF7AF006C210E /* stabs_to_module_unittest.cc in Sources */ = {isa = PBXBuildFile; fileRef = B88FB0D8116CEC0600407530 /* stabs_to_module_unittest.cc */; };
+ B88FAE1911665FE400407530 /* dwarf2diehandler.cc in Sources */ = {isa = PBXBuildFile; fileRef = B88FAE1711665FE400407530 /* dwarf2diehandler.cc */; };
+ B88FAE261166603300407530 /* dwarf_cu_to_module.cc in Sources */ = {isa = PBXBuildFile; fileRef = B88FAE1E1166603300407530 /* dwarf_cu_to_module.cc */; };
+ B88FAE271166603300407530 /* dwarf_line_to_module.cc in Sources */ = {isa = PBXBuildFile; fileRef = B88FAE201166603300407530 /* dwarf_line_to_module.cc */; };
+ B88FAE281166603300407530 /* language.cc in Sources */ = {isa = PBXBuildFile; fileRef = B88FAE221166603300407530 /* language.cc */; };
+ B88FAE291166603300407530 /* module.cc in Sources */ = {isa = PBXBuildFile; fileRef = B88FAE241166603300407530 /* module.cc */; };
+ B88FAE2C1166606200407530 /* macho_reader.cc in Sources */ = {isa = PBXBuildFile; fileRef = B89E0E6E1166571D00DD08C9 /* macho_reader.cc */; };
+ B88FAE351166673E00407530 /* dwarf_cfi_to_module.cc in Sources */ = {isa = PBXBuildFile; fileRef = B88FAE331166673E00407530 /* dwarf_cfi_to_module.cc */; };
+ B88FAE3B11666C6F00407530 /* stabs_reader.cc in Sources */ = {isa = PBXBuildFile; fileRef = B88FAE3911666C6F00407530 /* stabs_reader.cc */; };
+ B88FAE3E11666C8900407530 /* stabs_to_module.cc in Sources */ = {isa = PBXBuildFile; fileRef = B88FAE3C11666C8900407530 /* stabs_to_module.cc */; };
+ B88FAF37116A595400407530 /* cfi_assembler.cc in Sources */ = {isa = PBXBuildFile; fileRef = B88FAF34116A595400407530 /* cfi_assembler.cc */; };
+ B88FAF38116A595400407530 /* dwarf2reader_cfi_unittest.cc in Sources */ = {isa = PBXBuildFile; fileRef = B88FAF36116A595400407530 /* dwarf2reader_cfi_unittest.cc */; };
+ B88FAF3F116A5A2E00407530 /* dwarf2reader.cc in Sources */ = {isa = PBXBuildFile; fileRef = F95B422F0E0E22D100DBDE83 /* dwarf2reader.cc */; };
+ B88FAF40116A5A2E00407530 /* bytereader.cc in Sources */ = {isa = PBXBuildFile; fileRef = F95B422C0E0E22D100DBDE83 /* bytereader.cc */; };
+ B88FB00F116BDEA700407530 /* stabs_reader_unittest.cc in Sources */ = {isa = PBXBuildFile; fileRef = B88FB003116BDE7200407530 /* stabs_reader_unittest.cc */; };
+ B88FB010116BDEA700407530 /* stabs_reader.cc in Sources */ = {isa = PBXBuildFile; fileRef = B88FAE3911666C6F00407530 /* stabs_reader.cc */; };
+ B88FB028116BE03100407530 /* test_assembler.cc in Sources */ = {isa = PBXBuildFile; fileRef = B88FAE0911665B5700407530 /* test_assembler.cc */; };
+ B88FB029116BE03100407530 /* gmock-all.cc in Sources */ = {isa = PBXBuildFile; fileRef = B89E0EA311665AEA00DD08C9 /* gmock-all.cc */; };
+ B88FB02A116BE03100407530 /* gtest_main.cc in Sources */ = {isa = PBXBuildFile; fileRef = B89E0E9F11665AC300DD08C9 /* gtest_main.cc */; };
+ B88FB02B116BE03100407530 /* gtest-all.cc in Sources */ = {isa = PBXBuildFile; fileRef = B89E0EA011665AC300DD08C9 /* gtest-all.cc */; };
+ B88FB03F116BE24200407530 /* libgtestmockall.a in Frameworks */ = {isa = PBXBuildFile; fileRef = B88FB024116BDFFF00407530 /* libgtestmockall.a */; };
+ B88FB042116BE3C400407530 /* libgtestmockall.a in Frameworks */ = {isa = PBXBuildFile; fileRef = B88FB024116BDFFF00407530 /* libgtestmockall.a */; };
+ B88FB057116C0CDE00407530 /* libgtestmockall.a in Frameworks */ = {isa = PBXBuildFile; fileRef = B88FB024116BDFFF00407530 /* libgtestmockall.a */; };
+ B88FB0BD116CEAE000407530 /* module_unittest.cc in Sources */ = {isa = PBXBuildFile; fileRef = B88FB0B5116CEA8A00407530 /* module_unittest.cc */; };
+ B88FB0C1116CEB0600407530 /* libgtestmockall.a in Frameworks */ = {isa = PBXBuildFile; fileRef = B88FB024116BDFFF00407530 /* libgtestmockall.a */; };
+ B88FB0C4116CEB4100407530 /* module.cc in Sources */ = {isa = PBXBuildFile; fileRef = B88FAE241166603300407530 /* module.cc */; };
+ B88FB0E3116CEEB000407530 /* libgtestmockall.a in Frameworks */ = {isa = PBXBuildFile; fileRef = B88FB024116BDFFF00407530 /* libgtestmockall.a */; };
+ B88FB0E5116CEED300407530 /* dwarf2diehandler.cc in Sources */ = {isa = PBXBuildFile; fileRef = B88FAE1711665FE400407530 /* dwarf2diehandler.cc */; };
+ B88FB0E6116CEED300407530 /* dwarf2diehandler_unittest.cc in Sources */ = {isa = PBXBuildFile; fileRef = B88FB0DB116CEC5800407530 /* dwarf2diehandler_unittest.cc */; };
+ B88FB0F6116CEF2000407530 /* libgtestmockall.a in Frameworks */ = {isa = PBXBuildFile; fileRef = B88FB024116BDFFF00407530 /* libgtestmockall.a */; };
+ B88FB0FA116CF00E00407530 /* dwarf_line_to_module.cc in Sources */ = {isa = PBXBuildFile; fileRef = B88FAE201166603300407530 /* dwarf_line_to_module.cc */; };
+ B88FB0FB116CF00E00407530 /* dwarf_line_to_module_unittest.cc in Sources */ = {isa = PBXBuildFile; fileRef = B88FB0D7116CEC0600407530 /* dwarf_line_to_module_unittest.cc */; };
+ B88FB0FE116CF02400407530 /* module.cc in Sources */ = {isa = PBXBuildFile; fileRef = B88FAE241166603300407530 /* module.cc */; };
+ B88FB10E116CF08100407530 /* libgtestmockall.a in Frameworks */ = {isa = PBXBuildFile; fileRef = B88FB024116BDFFF00407530 /* libgtestmockall.a */; };
+ B88FB112116CF1F000407530 /* dwarf_cu_to_module.cc in Sources */ = {isa = PBXBuildFile; fileRef = B88FAE1E1166603300407530 /* dwarf_cu_to_module.cc */; };
+ B88FB113116CF1F000407530 /* dwarf_cu_to_module_unittest.cc in Sources */ = {isa = PBXBuildFile; fileRef = B88FB0D6116CEC0600407530 /* dwarf_cu_to_module_unittest.cc */; };
+ B88FB114116CF1F000407530 /* language.cc in Sources */ = {isa = PBXBuildFile; fileRef = B88FAE221166603300407530 /* language.cc */; };
+ B88FB115116CF1F000407530 /* module.cc in Sources */ = {isa = PBXBuildFile; fileRef = B88FAE241166603300407530 /* module.cc */; };
+ B88FB123116CF28500407530 /* libgtestmockall.a in Frameworks */ = {isa = PBXBuildFile; fileRef = B88FB024116BDFFF00407530 /* libgtestmockall.a */; };
+ B88FB129116CF2DD00407530 /* module.cc in Sources */ = {isa = PBXBuildFile; fileRef = B88FAE241166603300407530 /* module.cc */; };
+ B88FB12A116CF2DD00407530 /* dwarf_cfi_to_module.cc in Sources */ = {isa = PBXBuildFile; fileRef = B88FAE331166673E00407530 /* dwarf_cfi_to_module.cc */; };
+ B88FB12B116CF2DD00407530 /* dwarf_cfi_to_module_unittest.cc in Sources */ = {isa = PBXBuildFile; fileRef = B88FB0D5116CEC0600407530 /* dwarf_cfi_to_module_unittest.cc */; };
+ B88FB139116CF31600407530 /* libgtestmockall.a in Frameworks */ = {isa = PBXBuildFile; fileRef = B88FB024116BDFFF00407530 /* libgtestmockall.a */; };
+ B88FB13D116CF38300407530 /* cfi_assembler.cc in Sources */ = {isa = PBXBuildFile; fileRef = B88FAF34116A595400407530 /* cfi_assembler.cc */; };
+ B88FB13E116CF38300407530 /* bytereader.cc in Sources */ = {isa = PBXBuildFile; fileRef = F95B422C0E0E22D100DBDE83 /* bytereader.cc */; };
+ B88FB13F116CF38300407530 /* bytereader_unittest.cc in Sources */ = {isa = PBXBuildFile; fileRef = B88FB0DA116CEC5800407530 /* bytereader_unittest.cc */; };
+ B88FB14F116CF4AE00407530 /* libgtestmockall.a in Frameworks */ = {isa = PBXBuildFile; fileRef = B88FB024116BDFFF00407530 /* libgtestmockall.a */; };
+ B88FB152116CF4D300407530 /* byte_cursor_unittest.cc in Sources */ = {isa = PBXBuildFile; fileRef = B88FB0D4116CEC0600407530 /* byte_cursor_unittest.cc */; };
+ B89E0E781166576C00DD08C9 /* macho_reader.cc in Sources */ = {isa = PBXBuildFile; fileRef = B89E0E6E1166571D00DD08C9 /* macho_reader.cc */; };
+ B89E0E7A1166576C00DD08C9 /* macho_dump.cc in Sources */ = {isa = PBXBuildFile; fileRef = B89E0E701166573700DD08C9 /* macho_dump.cc */; };
+ B89E0E9911665A7200DD08C9 /* macho_reader_unittest.cc in Sources */ = {isa = PBXBuildFile; fileRef = B89E0E6D1166571D00DD08C9 /* macho_reader_unittest.cc */; };
+ B89E0E9A11665A7200DD08C9 /* macho_reader.cc in Sources */ = {isa = PBXBuildFile; fileRef = B89E0E6E1166571D00DD08C9 /* macho_reader.cc */; };
+ B8C5B5171166534700D34F4E /* dwarf2reader.cc in Sources */ = {isa = PBXBuildFile; fileRef = F95B422F0E0E22D100DBDE83 /* dwarf2reader.cc */; };
+ B8C5B5181166534700D34F4E /* bytereader.cc in Sources */ = {isa = PBXBuildFile; fileRef = F95B422C0E0E22D100DBDE83 /* bytereader.cc */; };
+ B8C5B5191166534700D34F4E /* macho_utilities.cc in Sources */ = {isa = PBXBuildFile; fileRef = 557800890BE1F3AB00EC23E0 /* macho_utilities.cc */; };
+ B8C5B51A1166534700D34F4E /* file_id.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9BE650410B52F6D800611104 /* file_id.cc */; };
+ B8C5B51B1166534700D34F4E /* macho_id.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9BE650430B52F6D800611104 /* macho_id.cc */; };
+ B8C5B51C1166534700D34F4E /* macho_walker.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9BE650450B52F6D800611104 /* macho_walker.cc */; };
+ B8C5B51D1166534700D34F4E /* dump_syms.cc in Sources */ = {isa = PBXBuildFile; fileRef = 08FB7796FE84155DC02AAC07 /* dump_syms.cc */; };
+ B8C5B51E1166534700D34F4E /* dump_syms_tool.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9BDF186E0B1BB43700F8391B /* dump_syms_tool.cc */; };
+ B8C5B523116653BA00D34F4E /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 08FB779EFE84155DC02AAC07 /* Foundation.framework */; };
+ D21F97D711CBA12300239E38 /* test_assembler_unittest.cc in Sources */ = {isa = PBXBuildFile; fileRef = B88FB0D9116CEC0600407530 /* test_assembler_unittest.cc */; };
+ D21F97D811CBA13D00239E38 /* libgtestmockall.a in Frameworks */ = {isa = PBXBuildFile; fileRef = B88FB024116BDFFF00407530 /* libgtestmockall.a */; };
+ D21F97E911CBA1FF00239E38 /* test_assembler.cc in Sources */ = {isa = PBXBuildFile; fileRef = B88FAE0911665B5700407530 /* test_assembler.cc */; };
+ EB06C7531FEBC516000214D9 /* path_helper.cc in Sources */ = {isa = PBXBuildFile; fileRef = EB06C7511FEBC515000214D9 /* path_helper.cc */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXContainerItemProxy section */
+ 8B31051411F100CF00FCF3E4 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = D21F97D111CBA0F200239E38;
+ remoteInfo = test_assembler_unittest;
+ };
+ B84A91F9116CF796006C210E /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = B88FB023116BDFFF00407530;
+ remoteInfo = gtestmockall;
+ };
+ B84A9200116CF7D2006C210E /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = B84A91F3116CF784006C210E;
+ remoteInfo = stabs_to_module_unittest;
+ };
+ B88FAFCE116BDD7000407530 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = B89E0E9411665A6400DD08C9;
+ remoteInfo = macho_reader_unittest;
+ };
+ B88FAFD0116BDD7000407530 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = B88FAF2E116A591D00407530;
+ remoteInfo = dwarf2reader_cfi_unittest;
+ };
+ B88FB01C116BDF9800407530 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = B88FB006116BDE8300407530;
+ remoteInfo = stabs_reader_unittest;
+ };
+ B88FB039116BE17E00407530 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = B88FB023116BDFFF00407530;
+ remoteInfo = gtestmockall;
+ };
+ B88FB087116CE6D800407530 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = B88FB023116BDFFF00407530;
+ remoteInfo = gtestmockall;
+ };
+ B88FB08F116CE71000407530 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = B88FB023116BDFFF00407530;
+ remoteInfo = gtestmockall;
+ };
+ B88FB0BF116CEAFE00407530 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = B88FB023116BDFFF00407530;
+ remoteInfo = gtestmockall;
+ };
+ B88FB0C7116CEB4A00407530 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = B88FB0B8116CEABF00407530;
+ remoteInfo = module_unittest;
+ };
+ B88FB0E7116CEEDA00407530 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = B88FB023116BDFFF00407530;
+ remoteInfo = gtestmockall;
+ };
+ B88FB0F7116CEF2E00407530 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = B88FB023116BDFFF00407530;
+ remoteInfo = gtestmockall;
+ };
+ B88FB10F116CF08A00407530 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = B88FB023116BDFFF00407530;
+ remoteInfo = gtestmockall;
+ };
+ B88FB124116CF29E00407530 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = B88FB023116BDFFF00407530;
+ remoteInfo = gtestmockall;
+ };
+ B88FB13B116CF35C00407530 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = B88FB023116BDFFF00407530;
+ remoteInfo = gtestmockall;
+ };
+ B88FB150116CF4C100407530 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = B88FB023116BDFFF00407530;
+ remoteInfo = gtestmockall;
+ };
+ B88FB15A116CF53E00407530 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = B88FB14A116CF4A700407530;
+ remoteInfo = byte_cursor_unittest;
+ };
+ B88FB15C116CF54B00407530 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = B88FB11E116CF27F00407530;
+ remoteInfo = dwarf_cfi_to_module_unittest;
+ };
+ B88FB15E116CF54B00407530 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = B88FB0F1116CEF1900407530;
+ remoteInfo = dwarf_line_to_module_unittest;
+ };
+ B88FB160116CF54B00407530 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = B88FB109116CF07900407530;
+ remoteInfo = dwarf_cu_to_module_unittest;
+ };
+ B88FB164116CF54B00407530 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = B88FB0DE116CEEA800407530;
+ remoteInfo = dwarf2diehandler_unittest;
+ };
+ B88FB166116CF54B00407530 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = B88FB134116CF30F00407530;
+ remoteInfo = bytereader_unittest;
+ };
+/* End PBXContainerItemProxy section */
+
+/* Begin PBXFileReference section */
+ 08FB7796FE84155DC02AAC07 /* dump_syms.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = dump_syms.cc; path = ../../../common/mac/dump_syms.cc; sourceTree = "<group>"; };
+ 08FB779EFE84155DC02AAC07 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
+ 162F64F8161C591500CD68D5 /* arch_utilities.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = arch_utilities.cc; path = ../../../common/mac/arch_utilities.cc; sourceTree = "<group>"; };
+ 162F64F9161C591500CD68D5 /* arch_utilities.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = arch_utilities.h; path = ../../../common/mac/arch_utilities.h; sourceTree = "<group>"; };
+ 4262382521AC496F00E5A3A6 /* dwarf_range_list_handler.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = dwarf_range_list_handler.cc; path = ../../../common/dwarf_range_list_handler.cc; sourceTree = "<group>"; };
+ 4262382621AC496F00E5A3A6 /* dwarf_range_list_handler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dwarf_range_list_handler.h; path = ../../../common/dwarf_range_list_handler.h; sourceTree = "<group>"; };
+ 4D72CAF413DFBAC2006CABE3 /* md5.cc */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = md5.cc; path = ../../../common/md5.cc; sourceTree = SOURCE_ROOT; };
+ 557800890BE1F3AB00EC23E0 /* macho_utilities.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = macho_utilities.cc; path = ../../../common/mac/macho_utilities.cc; sourceTree = SOURCE_ROOT; };
+ 5578008A0BE1F3AB00EC23E0 /* macho_utilities.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = macho_utilities.h; path = ../../../common/mac/macho_utilities.h; sourceTree = SOURCE_ROOT; };
+ 8B31023E11F0CF1C00FCF3E4 /* Breakpad.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Breakpad.xcconfig; path = ../../../common/mac/Breakpad.xcconfig; sourceTree = SOURCE_ROOT; };
+ 8B3102D411F0D60300FCF3E4 /* BreakpadDebug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = BreakpadDebug.xcconfig; path = ../../../common/mac/BreakpadDebug.xcconfig; sourceTree = SOURCE_ROOT; };
+ 8B3102D511F0D60300FCF3E4 /* BreakpadRelease.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = BreakpadRelease.xcconfig; path = ../../../common/mac/BreakpadRelease.xcconfig; sourceTree = SOURCE_ROOT; };
+ 8BCAAA4A1CE3A7980046090B /* elf_reader.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = elf_reader.cc; path = ../../../common/dwarf/elf_reader.cc; sourceTree = "<group>"; };
+ 8BCAAA4B1CE3A7980046090B /* elf_reader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = elf_reader.h; path = ../../../common/dwarf/elf_reader.h; sourceTree = "<group>"; };
+ 9BDF186D0B1BB43700F8391B /* dump_syms.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dump_syms.h; path = ../../../common/mac/dump_syms.h; sourceTree = "<group>"; };
+ 9BDF186E0B1BB43700F8391B /* dump_syms_tool.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = dump_syms_tool.cc; sourceTree = "<group>"; };
+ 9BE650410B52F6D800611104 /* file_id.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = file_id.cc; path = ../../../common/mac/file_id.cc; sourceTree = SOURCE_ROOT; };
+ 9BE650420B52F6D800611104 /* file_id.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = file_id.h; path = ../../../common/mac/file_id.h; sourceTree = SOURCE_ROOT; };
+ 9BE650430B52F6D800611104 /* macho_id.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = macho_id.cc; path = ../../../common/mac/macho_id.cc; sourceTree = SOURCE_ROOT; };
+ 9BE650440B52F6D800611104 /* macho_id.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = macho_id.h; path = ../../../common/mac/macho_id.h; sourceTree = SOURCE_ROOT; };
+ 9BE650450B52F6D800611104 /* macho_walker.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = macho_walker.cc; path = ../../../common/mac/macho_walker.cc; sourceTree = SOURCE_ROOT; };
+ 9BE650460B52F6D800611104 /* macho_walker.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = macho_walker.h; path = ../../../common/mac/macho_walker.h; sourceTree = SOURCE_ROOT; };
+ B84A91F4116CF784006C210E /* stabs_to_module_unittest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = stabs_to_module_unittest; sourceTree = BUILT_PRODUCTS_DIR; };
+ B88FAE0911665B5700407530 /* test_assembler.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = test_assembler.cc; path = ../../../common/test_assembler.cc; sourceTree = SOURCE_ROOT; };
+ B88FAE0A11665B5700407530 /* test_assembler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = test_assembler.h; path = ../../../common/test_assembler.h; sourceTree = SOURCE_ROOT; };
+ B88FAE1711665FE400407530 /* dwarf2diehandler.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = dwarf2diehandler.cc; path = ../../../common/dwarf/dwarf2diehandler.cc; sourceTree = SOURCE_ROOT; };
+ B88FAE1811665FE400407530 /* dwarf2diehandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dwarf2diehandler.h; path = ../../../common/dwarf/dwarf2diehandler.h; sourceTree = SOURCE_ROOT; };
+ B88FAE1D1166603300407530 /* byte_cursor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = byte_cursor.h; path = ../../../common/byte_cursor.h; sourceTree = SOURCE_ROOT; };
+ B88FAE1E1166603300407530 /* dwarf_cu_to_module.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = dwarf_cu_to_module.cc; path = ../../../common/dwarf_cu_to_module.cc; sourceTree = SOURCE_ROOT; };
+ B88FAE1F1166603300407530 /* dwarf_cu_to_module.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dwarf_cu_to_module.h; path = ../../../common/dwarf_cu_to_module.h; sourceTree = SOURCE_ROOT; };
+ B88FAE201166603300407530 /* dwarf_line_to_module.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = dwarf_line_to_module.cc; path = ../../../common/dwarf_line_to_module.cc; sourceTree = SOURCE_ROOT; };
+ B88FAE211166603300407530 /* dwarf_line_to_module.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dwarf_line_to_module.h; path = ../../../common/dwarf_line_to_module.h; sourceTree = SOURCE_ROOT; };
+ B88FAE221166603300407530 /* language.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = language.cc; path = ../../../common/language.cc; sourceTree = SOURCE_ROOT; };
+ B88FAE231166603300407530 /* language.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = language.h; path = ../../../common/language.h; sourceTree = SOURCE_ROOT; };
+ B88FAE241166603300407530 /* module.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = module.cc; path = ../../../common/module.cc; sourceTree = SOURCE_ROOT; };
+ B88FAE251166603300407530 /* module.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = module.h; path = ../../../common/module.h; sourceTree = SOURCE_ROOT; };
+ B88FAE331166673E00407530 /* dwarf_cfi_to_module.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = dwarf_cfi_to_module.cc; path = ../../../common/dwarf_cfi_to_module.cc; sourceTree = SOURCE_ROOT; };
+ B88FAE341166673E00407530 /* dwarf_cfi_to_module.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dwarf_cfi_to_module.h; path = ../../../common/dwarf_cfi_to_module.h; sourceTree = SOURCE_ROOT; };
+ B88FAE3911666C6F00407530 /* stabs_reader.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = stabs_reader.cc; path = ../../../common/stabs_reader.cc; sourceTree = SOURCE_ROOT; };
+ B88FAE3A11666C6F00407530 /* stabs_reader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = stabs_reader.h; path = ../../../common/stabs_reader.h; sourceTree = SOURCE_ROOT; };
+ B88FAE3C11666C8900407530 /* stabs_to_module.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = stabs_to_module.cc; path = ../../../common/stabs_to_module.cc; sourceTree = SOURCE_ROOT; };
+ B88FAE3D11666C8900407530 /* stabs_to_module.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = stabs_to_module.h; path = ../../../common/stabs_to_module.h; sourceTree = SOURCE_ROOT; };
+ B88FAF2F116A591E00407530 /* dwarf2reader_cfi_unittest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = dwarf2reader_cfi_unittest; sourceTree = BUILT_PRODUCTS_DIR; };
+ B88FAF34116A595400407530 /* cfi_assembler.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = cfi_assembler.cc; path = ../../../common/dwarf/cfi_assembler.cc; sourceTree = SOURCE_ROOT; };
+ B88FAF35116A595400407530 /* cfi_assembler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = cfi_assembler.h; path = ../../../common/dwarf/cfi_assembler.h; sourceTree = SOURCE_ROOT; };
+ B88FAF36116A595400407530 /* dwarf2reader_cfi_unittest.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = dwarf2reader_cfi_unittest.cc; path = ../../../common/dwarf/dwarf2reader_cfi_unittest.cc; sourceTree = SOURCE_ROOT; };
+ B88FB003116BDE7200407530 /* stabs_reader_unittest.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = stabs_reader_unittest.cc; path = ../../../common/stabs_reader_unittest.cc; sourceTree = SOURCE_ROOT; };
+ B88FB007116BDE8300407530 /* stabs_reader_unittest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = stabs_reader_unittest; sourceTree = BUILT_PRODUCTS_DIR; };
+ B88FB024116BDFFF00407530 /* libgtestmockall.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libgtestmockall.a; sourceTree = BUILT_PRODUCTS_DIR; };
+ B88FB0B5116CEA8A00407530 /* module_unittest.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = module_unittest.cc; path = ../../../common/module_unittest.cc; sourceTree = SOURCE_ROOT; };
+ B88FB0B9116CEABF00407530 /* module_unittest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = module_unittest; sourceTree = BUILT_PRODUCTS_DIR; };
+ B88FB0D4116CEC0600407530 /* byte_cursor_unittest.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = byte_cursor_unittest.cc; path = ../../../common/byte_cursor_unittest.cc; sourceTree = SOURCE_ROOT; };
+ B88FB0D5116CEC0600407530 /* dwarf_cfi_to_module_unittest.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = dwarf_cfi_to_module_unittest.cc; path = ../../../common/dwarf_cfi_to_module_unittest.cc; sourceTree = SOURCE_ROOT; };
+ B88FB0D6116CEC0600407530 /* dwarf_cu_to_module_unittest.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = dwarf_cu_to_module_unittest.cc; path = ../../../common/dwarf_cu_to_module_unittest.cc; sourceTree = SOURCE_ROOT; };
+ B88FB0D7116CEC0600407530 /* dwarf_line_to_module_unittest.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = dwarf_line_to_module_unittest.cc; path = ../../../common/dwarf_line_to_module_unittest.cc; sourceTree = SOURCE_ROOT; };
+ B88FB0D8116CEC0600407530 /* stabs_to_module_unittest.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = stabs_to_module_unittest.cc; path = ../../../common/stabs_to_module_unittest.cc; sourceTree = SOURCE_ROOT; };
+ B88FB0D9116CEC0600407530 /* test_assembler_unittest.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = test_assembler_unittest.cc; path = ../../../common/test_assembler_unittest.cc; sourceTree = SOURCE_ROOT; };
+ B88FB0DA116CEC5800407530 /* bytereader_unittest.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = bytereader_unittest.cc; path = ../../../common/dwarf/bytereader_unittest.cc; sourceTree = SOURCE_ROOT; };
+ B88FB0DB116CEC5800407530 /* dwarf2diehandler_unittest.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = dwarf2diehandler_unittest.cc; path = ../../../common/dwarf/dwarf2diehandler_unittest.cc; sourceTree = SOURCE_ROOT; };
+ B88FB0DF116CEEA800407530 /* dwarf2diehandler_unittest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = dwarf2diehandler_unittest; sourceTree = BUILT_PRODUCTS_DIR; };
+ B88FB0F2116CEF1900407530 /* dwarf_line_to_module_unittest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = dwarf_line_to_module_unittest; sourceTree = BUILT_PRODUCTS_DIR; };
+ B88FB10A116CF07900407530 /* dwarf_cu_to_module_unittest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = dwarf_cu_to_module_unittest; sourceTree = BUILT_PRODUCTS_DIR; };
+ B88FB11F116CF27F00407530 /* dwarf_cfi_to_module_unittest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = dwarf_cfi_to_module_unittest; sourceTree = BUILT_PRODUCTS_DIR; };
+ B88FB135116CF30F00407530 /* bytereader_unittest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = bytereader_unittest; sourceTree = BUILT_PRODUCTS_DIR; };
+ B88FB14B116CF4A700407530 /* byte_cursor_unittest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = byte_cursor_unittest; sourceTree = BUILT_PRODUCTS_DIR; };
+ B89E0E6D1166571D00DD08C9 /* macho_reader_unittest.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = macho_reader_unittest.cc; path = ../../../common/mac/macho_reader_unittest.cc; sourceTree = SOURCE_ROOT; };
+ B89E0E6E1166571D00DD08C9 /* macho_reader.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = macho_reader.cc; path = ../../../common/mac/macho_reader.cc; sourceTree = SOURCE_ROOT; };
+ B89E0E6F1166571D00DD08C9 /* macho_reader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = macho_reader.h; path = ../../../common/mac/macho_reader.h; sourceTree = SOURCE_ROOT; };
+ B89E0E701166573700DD08C9 /* macho_dump.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = macho_dump.cc; sourceTree = "<group>"; };
+ B89E0E741166575200DD08C9 /* macho_dump */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = macho_dump; sourceTree = BUILT_PRODUCTS_DIR; };
+ B89E0E9511665A6400DD08C9 /* macho_reader_unittest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = macho_reader_unittest; sourceTree = BUILT_PRODUCTS_DIR; };
+ B89E0E9F11665AC300DD08C9 /* gtest_main.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = gtest_main.cc; path = ../../../testing/googletest/src/gtest_main.cc; sourceTree = SOURCE_ROOT; };
+ B89E0EA011665AC300DD08C9 /* gtest-all.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "gtest-all.cc"; path = "../../../testing/googletest/src/gtest-all.cc"; sourceTree = SOURCE_ROOT; };
+ B89E0EA311665AEA00DD08C9 /* gmock-all.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "gmock-all.cc"; path = "../../../testing/googlemock/src/gmock-all.cc"; sourceTree = SOURCE_ROOT; };
+ B8C5B5111166531A00D34F4E /* dump_syms */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = dump_syms; sourceTree = BUILT_PRODUCTS_DIR; };
+ B8E8CA0C1156C854009E61B2 /* byteswap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = byteswap.h; path = ../../../common/mac/byteswap.h; sourceTree = SOURCE_ROOT; };
+ D21F97D211CBA0F200239E38 /* test_assembler_unittest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = test_assembler_unittest; sourceTree = BUILT_PRODUCTS_DIR; };
+ EB06C7511FEBC515000214D9 /* path_helper.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = path_helper.cc; path = ../../../common/path_helper.cc; sourceTree = "<group>"; };
+ EB06C7521FEBC516000214D9 /* path_helper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = path_helper.h; path = ../../../common/path_helper.h; sourceTree = "<group>"; };
+ F95B422B0E0E22D100DBDE83 /* bytereader-inl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "bytereader-inl.h"; path = "../../../common/dwarf/bytereader-inl.h"; sourceTree = SOURCE_ROOT; };
+ F95B422C0E0E22D100DBDE83 /* bytereader.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = bytereader.cc; path = ../../../common/dwarf/bytereader.cc; sourceTree = SOURCE_ROOT; };
+ F95B422D0E0E22D100DBDE83 /* bytereader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = bytereader.h; path = ../../../common/dwarf/bytereader.h; sourceTree = SOURCE_ROOT; };
+ F95B422E0E0E22D100DBDE83 /* dwarf2enums.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dwarf2enums.h; path = ../../../common/dwarf/dwarf2enums.h; sourceTree = SOURCE_ROOT; };
+ F95B422F0E0E22D100DBDE83 /* dwarf2reader.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = dwarf2reader.cc; path = ../../../common/dwarf/dwarf2reader.cc; sourceTree = SOURCE_ROOT; };
+ F95B42300E0E22D100DBDE83 /* dwarf2reader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dwarf2reader.h; path = ../../../common/dwarf/dwarf2reader.h; sourceTree = SOURCE_ROOT; };
+ F95B42310E0E22D100DBDE83 /* line_state_machine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = line_state_machine.h; path = ../../../common/dwarf/line_state_machine.h; sourceTree = SOURCE_ROOT; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ B84A91F2116CF784006C210E /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ B84A91F8116CF78F006C210E /* libgtestmockall.a in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ B88FAF2D116A591D00407530 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ B88FB042116BE3C400407530 /* libgtestmockall.a in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ B88FB005116BDE8300407530 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ B88FB03F116BE24200407530 /* libgtestmockall.a in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ B88FB022116BDFFF00407530 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ B88FB0B7116CEABF00407530 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ B88FB0C1116CEB0600407530 /* libgtestmockall.a in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ B88FB0DD116CEEA800407530 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ B88FB0E3116CEEB000407530 /* libgtestmockall.a in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ B88FB0F0116CEF1900407530 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ B88FB0F6116CEF2000407530 /* libgtestmockall.a in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ B88FB108116CF07900407530 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ B88FB10E116CF08100407530 /* libgtestmockall.a in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ B88FB11D116CF27F00407530 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ B88FB123116CF28500407530 /* libgtestmockall.a in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ B88FB133116CF30F00407530 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ B88FB139116CF31600407530 /* libgtestmockall.a in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ B88FB149116CF4A700407530 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ B88FB14F116CF4AE00407530 /* libgtestmockall.a in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ B89E0E721166575200DD08C9 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ B89E0E9311665A6400DD08C9 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ B88FB057116C0CDE00407530 /* libgtestmockall.a in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ B8C5B50F1166531A00D34F4E /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ B8C5B523116653BA00D34F4E /* Foundation.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ D21F97D011CBA0F200239E38 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ D21F97D811CBA13D00239E38 /* libgtestmockall.a in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 08FB7794FE84155DC02AAC07 /* dump_syms */ = {
+ isa = PBXGroup;
+ children = (
+ 8B31023E11F0CF1C00FCF3E4 /* Breakpad.xcconfig */,
+ 8B3102D411F0D60300FCF3E4 /* BreakpadDebug.xcconfig */,
+ 8B3102D511F0D60300FCF3E4 /* BreakpadRelease.xcconfig */,
+ B89E0E9D11665A9500DD08C9 /* TESTING */,
+ F9F5344B0E7C8FFC0012363F /* DWARF */,
+ B89E0E6C1166569700DD08C9 /* MACHO */,
+ B88FAE3811666A1700407530 /* STABS */,
+ B88FAE1C11665FFD00407530 /* MODULE */,
+ 162F64F8161C591500CD68D5 /* arch_utilities.cc */,
+ 162F64F9161C591500CD68D5 /* arch_utilities.h */,
+ B88FAE1D1166603300407530 /* byte_cursor.h */,
+ B88FB0D4116CEC0600407530 /* byte_cursor_unittest.cc */,
+ B8E8CA0C1156C854009E61B2 /* byteswap.h */,
+ 9BE650410B52F6D800611104 /* file_id.cc */,
+ 9BE650420B52F6D800611104 /* file_id.h */,
+ 9BDF186D0B1BB43700F8391B /* dump_syms.h */,
+ 08FB7796FE84155DC02AAC07 /* dump_syms.cc */,
+ 9BDF186E0B1BB43700F8391B /* dump_syms_tool.cc */,
+ B89E0E701166573700DD08C9 /* macho_dump.cc */,
+ 4D72CAF413DFBAC2006CABE3 /* md5.cc */,
+ EB06C7511FEBC515000214D9 /* path_helper.cc */,
+ EB06C7521FEBC516000214D9 /* path_helper.h */,
+ 08FB779DFE84155DC02AAC07 /* External Frameworks and Libraries */,
+ 1AB674ADFE9D54B511CA2CBB /* Products */,
+ );
+ name = dump_syms;
+ sourceTree = "<group>";
+ };
+ 08FB779DFE84155DC02AAC07 /* External Frameworks and Libraries */ = {
+ isa = PBXGroup;
+ children = (
+ 08FB779EFE84155DC02AAC07 /* Foundation.framework */,
+ );
+ name = "External Frameworks and Libraries";
+ sourceTree = "<group>";
+ };
+ 1AB674ADFE9D54B511CA2CBB /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ B8C5B5111166531A00D34F4E /* dump_syms */,
+ B89E0E741166575200DD08C9 /* macho_dump */,
+ B89E0E9511665A6400DD08C9 /* macho_reader_unittest */,
+ B88FAF2F116A591E00407530 /* dwarf2reader_cfi_unittest */,
+ B88FB007116BDE8300407530 /* stabs_reader_unittest */,
+ B88FB024116BDFFF00407530 /* libgtestmockall.a */,
+ B88FB0B9116CEABF00407530 /* module_unittest */,
+ B88FB0DF116CEEA800407530 /* dwarf2diehandler_unittest */,
+ B88FB0F2116CEF1900407530 /* dwarf_line_to_module_unittest */,
+ B88FB10A116CF07900407530 /* dwarf_cu_to_module_unittest */,
+ B88FB11F116CF27F00407530 /* dwarf_cfi_to_module_unittest */,
+ B88FB135116CF30F00407530 /* bytereader_unittest */,
+ B88FB14B116CF4A700407530 /* byte_cursor_unittest */,
+ B84A91F4116CF784006C210E /* stabs_to_module_unittest */,
+ D21F97D211CBA0F200239E38 /* test_assembler_unittest */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+ B88FAE1C11665FFD00407530 /* MODULE */ = {
+ isa = PBXGroup;
+ children = (
+ B88FAE1E1166603300407530 /* dwarf_cu_to_module.cc */,
+ B88FAE1F1166603300407530 /* dwarf_cu_to_module.h */,
+ B88FB0D6116CEC0600407530 /* dwarf_cu_to_module_unittest.cc */,
+ B88FAE201166603300407530 /* dwarf_line_to_module.cc */,
+ B88FAE211166603300407530 /* dwarf_line_to_module.h */,
+ B88FB0D7116CEC0600407530 /* dwarf_line_to_module_unittest.cc */,
+ B88FAE221166603300407530 /* language.cc */,
+ B88FAE231166603300407530 /* language.h */,
+ B88FAE241166603300407530 /* module.cc */,
+ B88FAE251166603300407530 /* module.h */,
+ B88FB0B5116CEA8A00407530 /* module_unittest.cc */,
+ B88FAE331166673E00407530 /* dwarf_cfi_to_module.cc */,
+ B88FAE341166673E00407530 /* dwarf_cfi_to_module.h */,
+ B88FB0D5116CEC0600407530 /* dwarf_cfi_to_module_unittest.cc */,
+ B88FAE3C11666C8900407530 /* stabs_to_module.cc */,
+ B88FAE3D11666C8900407530 /* stabs_to_module.h */,
+ B88FB0D8116CEC0600407530 /* stabs_to_module_unittest.cc */,
+ );
+ name = MODULE;
+ sourceTree = "<group>";
+ };
+ B88FAE3811666A1700407530 /* STABS */ = {
+ isa = PBXGroup;
+ children = (
+ B88FB003116BDE7200407530 /* stabs_reader_unittest.cc */,
+ B88FAE3911666C6F00407530 /* stabs_reader.cc */,
+ B88FAE3A11666C6F00407530 /* stabs_reader.h */,
+ );
+ name = STABS;
+ sourceTree = "<group>";
+ };
+ B89E0E6C1166569700DD08C9 /* MACHO */ = {
+ isa = PBXGroup;
+ children = (
+ B89E0E6D1166571D00DD08C9 /* macho_reader_unittest.cc */,
+ B89E0E6E1166571D00DD08C9 /* macho_reader.cc */,
+ B89E0E6F1166571D00DD08C9 /* macho_reader.h */,
+ 557800890BE1F3AB00EC23E0 /* macho_utilities.cc */,
+ 5578008A0BE1F3AB00EC23E0 /* macho_utilities.h */,
+ 9BE650430B52F6D800611104 /* macho_id.cc */,
+ 9BE650440B52F6D800611104 /* macho_id.h */,
+ 9BE650450B52F6D800611104 /* macho_walker.cc */,
+ 9BE650460B52F6D800611104 /* macho_walker.h */,
+ );
+ name = MACHO;
+ sourceTree = "<group>";
+ };
+ B89E0E9D11665A9500DD08C9 /* TESTING */ = {
+ isa = PBXGroup;
+ children = (
+ B88FAE0911665B5700407530 /* test_assembler.cc */,
+ B88FAE0A11665B5700407530 /* test_assembler.h */,
+ B88FB0D9116CEC0600407530 /* test_assembler_unittest.cc */,
+ B89E0EA311665AEA00DD08C9 /* gmock-all.cc */,
+ B89E0E9F11665AC300DD08C9 /* gtest_main.cc */,
+ B89E0EA011665AC300DD08C9 /* gtest-all.cc */,
+ );
+ name = TESTING;
+ sourceTree = "<group>";
+ };
+ F9F5344B0E7C8FFC0012363F /* DWARF */ = {
+ isa = PBXGroup;
+ children = (
+ B88FAF34116A595400407530 /* cfi_assembler.cc */,
+ B88FAF35116A595400407530 /* cfi_assembler.h */,
+ F95B422E0E0E22D100DBDE83 /* dwarf2enums.h */,
+ F95B422F0E0E22D100DBDE83 /* dwarf2reader.cc */,
+ 4262382521AC496F00E5A3A6 /* dwarf_range_list_handler.cc */,
+ 4262382621AC496F00E5A3A6 /* dwarf_range_list_handler.h */,
+ F95B42300E0E22D100DBDE83 /* dwarf2reader.h */,
+ B88FAF36116A595400407530 /* dwarf2reader_cfi_unittest.cc */,
+ F95B422D0E0E22D100DBDE83 /* bytereader.h */,
+ F95B422B0E0E22D100DBDE83 /* bytereader-inl.h */,
+ F95B422C0E0E22D100DBDE83 /* bytereader.cc */,
+ B88FB0DA116CEC5800407530 /* bytereader_unittest.cc */,
+ F95B42310E0E22D100DBDE83 /* line_state_machine.h */,
+ B88FAE1711665FE400407530 /* dwarf2diehandler.cc */,
+ B88FAE1811665FE400407530 /* dwarf2diehandler.h */,
+ B88FB0DB116CEC5800407530 /* dwarf2diehandler_unittest.cc */,
+ 8BCAAA4A1CE3A7980046090B /* elf_reader.cc */,
+ 8BCAAA4B1CE3A7980046090B /* elf_reader.h */,
+ );
+ name = DWARF;
+ sourceTree = "<group>";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXHeadersBuildPhase section */
+ B88FB020116BDFFF00407530 /* Headers */ = {
+ isa = PBXHeadersBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXHeadersBuildPhase section */
+
+/* Begin PBXNativeTarget section */
+ B84A91F3116CF784006C210E /* stabs_to_module_unittest */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = B84A9202116CF7F0006C210E /* Build configuration list for PBXNativeTarget "stabs_to_module_unittest" */;
+ buildPhases = (
+ B84A91F1116CF784006C210E /* Sources */,
+ B84A91F2116CF784006C210E /* Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ B84A91FA116CF796006C210E /* PBXTargetDependency */,
+ );
+ name = stabs_to_module_unittest;
+ productName = stabs_to_module_unittest;
+ productReference = B84A91F4116CF784006C210E /* stabs_to_module_unittest */;
+ productType = "com.apple.product-type.tool";
+ };
+ B88FAF2E116A591D00407530 /* dwarf2reader_cfi_unittest */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = B88FAF33116A594800407530 /* Build configuration list for PBXNativeTarget "dwarf2reader_cfi_unittest" */;
+ buildPhases = (
+ B88FAF2C116A591D00407530 /* Sources */,
+ B88FAF2D116A591D00407530 /* Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ B88FB03A116BE17E00407530 /* PBXTargetDependency */,
+ );
+ name = dwarf2reader_cfi_unittest;
+ productName = dwarf2reader_cfi_unittest;
+ productReference = B88FAF2F116A591E00407530 /* dwarf2reader_cfi_unittest */;
+ productType = "com.apple.product-type.tool";
+ };
+ B88FB006116BDE8300407530 /* stabs_reader_unittest */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = B88FB013116BDEC800407530 /* Build configuration list for PBXNativeTarget "stabs_reader_unittest" */;
+ buildPhases = (
+ B88FB004116BDE8300407530 /* Sources */,
+ B88FB005116BDE8300407530 /* Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ B88FB088116CE6D800407530 /* PBXTargetDependency */,
+ );
+ name = stabs_reader_unittest;
+ productName = stabs_reader_unittest;
+ productReference = B88FB007116BDE8300407530 /* stabs_reader_unittest */;
+ productType = "com.apple.product-type.tool";
+ };
+ B88FB023116BDFFF00407530 /* gtestmockall */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = B88FB027116BE02900407530 /* Build configuration list for PBXNativeTarget "gtestmockall" */;
+ buildPhases = (
+ B88FB020116BDFFF00407530 /* Headers */,
+ B88FB021116BDFFF00407530 /* Sources */,
+ B88FB022116BDFFF00407530 /* Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = gtestmockall;
+ productName = gtestmockall;
+ productReference = B88FB024116BDFFF00407530 /* libgtestmockall.a */;
+ productType = "com.apple.product-type.library.static";
+ };
+ B88FB0B8116CEABF00407530 /* module_unittest */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = B88FB0BE116CEAFE00407530 /* Build configuration list for PBXNativeTarget "module_unittest" */;
+ buildPhases = (
+ B88FB0B6116CEABF00407530 /* Sources */,
+ B88FB0B7116CEABF00407530 /* Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ B88FB0C0116CEAFE00407530 /* PBXTargetDependency */,
+ );
+ name = module_unittest;
+ productName = module_unittest;
+ productReference = B88FB0B9116CEABF00407530 /* module_unittest */;
+ productType = "com.apple.product-type.tool";
+ };
+ B88FB0DE116CEEA800407530 /* dwarf2diehandler_unittest */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = B88FB0E4116CEECE00407530 /* Build configuration list for PBXNativeTarget "dwarf2diehandler_unittest" */;
+ buildPhases = (
+ B88FB0DC116CEEA800407530 /* Sources */,
+ B88FB0DD116CEEA800407530 /* Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ B88FB0E8116CEEDA00407530 /* PBXTargetDependency */,
+ );
+ name = dwarf2diehandler_unittest;
+ productName = dwarf2diehandler_unittest;
+ productReference = B88FB0DF116CEEA800407530 /* dwarf2diehandler_unittest */;
+ productType = "com.apple.product-type.tool";
+ };
+ B88FB0F1116CEF1900407530 /* dwarf_line_to_module_unittest */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = B88FB0F9116CEF9800407530 /* Build configuration list for PBXNativeTarget "dwarf_line_to_module_unittest" */;
+ buildPhases = (
+ B88FB0EF116CEF1900407530 /* Sources */,
+ B88FB0F0116CEF1900407530 /* Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ B88FB0F8116CEF2E00407530 /* PBXTargetDependency */,
+ );
+ name = dwarf_line_to_module_unittest;
+ productName = dwarf_line_to_module_unittest;
+ productReference = B88FB0F2116CEF1900407530 /* dwarf_line_to_module_unittest */;
+ productType = "com.apple.product-type.tool";
+ };
+ B88FB109116CF07900407530 /* dwarf_cu_to_module_unittest */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = B88FB111116CF0A800407530 /* Build configuration list for PBXNativeTarget "dwarf_cu_to_module_unittest" */;
+ buildPhases = (
+ B88FB107116CF07900407530 /* Sources */,
+ B88FB108116CF07900407530 /* Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ B88FB110116CF08A00407530 /* PBXTargetDependency */,
+ );
+ name = dwarf_cu_to_module_unittest;
+ productName = dwarf_cu_to_module_unittest;
+ productReference = B88FB10A116CF07900407530 /* dwarf_cu_to_module_unittest */;
+ productType = "com.apple.product-type.tool";
+ };
+ B88FB11E116CF27F00407530 /* dwarf_cfi_to_module_unittest */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = B88FB128116CF2C800407530 /* Build configuration list for PBXNativeTarget "dwarf_cfi_to_module_unittest" */;
+ buildPhases = (
+ B88FB11C116CF27F00407530 /* Sources */,
+ B88FB11D116CF27F00407530 /* Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ B88FB125116CF29E00407530 /* PBXTargetDependency */,
+ );
+ name = dwarf_cfi_to_module_unittest;
+ productName = dwarf_cfi_to_module_unittest;
+ productReference = B88FB11F116CF27F00407530 /* dwarf_cfi_to_module_unittest */;
+ productType = "com.apple.product-type.tool";
+ };
+ B88FB134116CF30F00407530 /* bytereader_unittest */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = B88FB13A116CF33400407530 /* Build configuration list for PBXNativeTarget "bytereader_unittest" */;
+ buildPhases = (
+ B88FB132116CF30F00407530 /* Sources */,
+ B88FB133116CF30F00407530 /* Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ B88FB13C116CF35C00407530 /* PBXTargetDependency */,
+ );
+ name = bytereader_unittest;
+ productName = bytereader_unittest;
+ productReference = B88FB135116CF30F00407530 /* bytereader_unittest */;
+ productType = "com.apple.product-type.tool";
+ };
+ B88FB14A116CF4A700407530 /* byte_cursor_unittest */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = B88FB159116CF4F900407530 /* Build configuration list for PBXNativeTarget "byte_cursor_unittest" */;
+ buildPhases = (
+ B88FB148116CF4A700407530 /* Sources */,
+ B88FB149116CF4A700407530 /* Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ B88FB151116CF4C100407530 /* PBXTargetDependency */,
+ );
+ name = byte_cursor_unittest;
+ productName = byte_cursor_unittest;
+ productReference = B88FB14B116CF4A700407530 /* byte_cursor_unittest */;
+ productType = "com.apple.product-type.tool";
+ };
+ B89E0E731166575200DD08C9 /* macho_dump */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = B89E0E7F116657A100DD08C9 /* Build configuration list for PBXNativeTarget "macho_dump" */;
+ buildPhases = (
+ B89E0E711166575200DD08C9 /* Sources */,
+ B89E0E721166575200DD08C9 /* Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = macho_dump;
+ productName = macho_dump;
+ productReference = B89E0E741166575200DD08C9 /* macho_dump */;
+ productType = "com.apple.product-type.tool";
+ };
+ B89E0E9411665A6400DD08C9 /* macho_reader_unittest */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = B89E0E9E11665A9600DD08C9 /* Build configuration list for PBXNativeTarget "macho_reader_unittest" */;
+ buildPhases = (
+ B89E0E9211665A6400DD08C9 /* Sources */,
+ B89E0E9311665A6400DD08C9 /* Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ B88FB090116CE71000407530 /* PBXTargetDependency */,
+ );
+ name = macho_reader_unittest;
+ productName = macho_reader_unittest;
+ productReference = B89E0E9511665A6400DD08C9 /* macho_reader_unittest */;
+ productType = "com.apple.product-type.tool";
+ };
+ B8C5B5101166531A00D34F4E /* dump_syms */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = B8C5B5151166533900D34F4E /* Build configuration list for PBXNativeTarget "dump_syms" */;
+ buildPhases = (
+ B8C5B50E1166531A00D34F4E /* Sources */,
+ B8C5B50F1166531A00D34F4E /* Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = dump_syms;
+ productName = dump_syms;
+ productReference = B8C5B5111166531A00D34F4E /* dump_syms */;
+ productType = "com.apple.product-type.tool";
+ };
+ D21F97D111CBA0F200239E38 /* test_assembler_unittest */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = D21F97D611CBA11000239E38 /* Build configuration list for PBXNativeTarget "test_assembler_unittest" */;
+ buildPhases = (
+ D21F97CF11CBA0F200239E38 /* Sources */,
+ D21F97D011CBA0F200239E38 /* Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = test_assembler_unittest;
+ productName = test_assembler_unittest;
+ productReference = D21F97D211CBA0F200239E38 /* test_assembler_unittest */;
+ productType = "com.apple.product-type.tool";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 08FB7793FE84155DC02AAC07 /* Project object */ = {
+ isa = PBXProject;
+ attributes = {
+ };
+ buildConfigurationList = 1DEB927808733DD40010E9CD /* Build configuration list for PBXProject "dump_syms" */;
+ compatibilityVersion = "Xcode 3.1";
+ developmentRegion = English;
+ hasScannedForEncodings = 1;
+ knownRegions = (
+ English,
+ Japanese,
+ French,
+ German,
+ );
+ mainGroup = 08FB7794FE84155DC02AAC07 /* dump_syms */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ B8C5B5101166531A00D34F4E /* dump_syms */,
+ B89E0E731166575200DD08C9 /* macho_dump */,
+ B88FB023116BDFFF00407530 /* gtestmockall */,
+ B88FB14A116CF4A700407530 /* byte_cursor_unittest */,
+ B89E0E9411665A6400DD08C9 /* macho_reader_unittest */,
+ B88FB006116BDE8300407530 /* stabs_reader_unittest */,
+ B88FB134116CF30F00407530 /* bytereader_unittest */,
+ B88FAF2E116A591D00407530 /* dwarf2reader_cfi_unittest */,
+ B88FB0DE116CEEA800407530 /* dwarf2diehandler_unittest */,
+ B88FB109116CF07900407530 /* dwarf_cu_to_module_unittest */,
+ B88FB0F1116CEF1900407530 /* dwarf_line_to_module_unittest */,
+ B88FB11E116CF27F00407530 /* dwarf_cfi_to_module_unittest */,
+ B84A91F3116CF784006C210E /* stabs_to_module_unittest */,
+ B88FB0B8116CEABF00407530 /* module_unittest */,
+ B88FAFC9116BDCAD00407530 /* all_unittests */,
+ D21F97D111CBA0F200239E38 /* test_assembler_unittest */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXShellScriptBuildPhase section */
+ B88FB094116CE73E00407530 /* ShellScript */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputPaths = (
+ );
+ outputPaths = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "set -eu\n\ncd $BUILT_PRODUCTS_DIR\npwd\n\n./byte_cursor_unittest\n./macho_reader_unittest\n./stabs_reader_unittest\n./bytereader_unittest\n./dwarf2reader_cfi_unittest\n./dwarf2diehandler_unittest\n./dwarf_cu_to_module_unittest\n./dwarf_line_to_module_unittest\n./dwarf_cfi_to_module_unittest\n./stabs_to_module_unittest\n./module_unittest\n./test_assembler_unittest\n\necho \"Expect two warnings from the following tests:\"\necho \" Errors.BadFileNumber\"\necho \" Errors.BadDirectoryNumber\"\necho \"The proper behavior of these tests is to print text that XCode confuses with compiler warnings.\"\n";
+ };
+/* End PBXShellScriptBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ B84A91F1116CF784006C210E /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ B84A91FB116CF7AF006C210E /* module.cc in Sources */,
+ B84A91FC116CF7AF006C210E /* stabs_to_module.cc in Sources */,
+ B84A91FD116CF7AF006C210E /* stabs_to_module_unittest.cc in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ B88FAF2C116A591D00407530 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ B88FAF38116A595400407530 /* dwarf2reader_cfi_unittest.cc in Sources */,
+ B88FAF3F116A5A2E00407530 /* dwarf2reader.cc in Sources */,
+ 8BCAAA4D1CE3B1260046090B /* elf_reader.cc in Sources */,
+ B88FAF40116A5A2E00407530 /* bytereader.cc in Sources */,
+ B88FAF37116A595400407530 /* cfi_assembler.cc in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ B88FB004116BDE8300407530 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ B88FB00F116BDEA700407530 /* stabs_reader_unittest.cc in Sources */,
+ B88FB010116BDEA700407530 /* stabs_reader.cc in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ B88FB021116BDFFF00407530 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ B88FB028116BE03100407530 /* test_assembler.cc in Sources */,
+ B88FB029116BE03100407530 /* gmock-all.cc in Sources */,
+ B88FB02A116BE03100407530 /* gtest_main.cc in Sources */,
+ B88FB02B116BE03100407530 /* gtest-all.cc in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ B88FB0B6116CEABF00407530 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ B88FB0BD116CEAE000407530 /* module_unittest.cc in Sources */,
+ B88FB0C4116CEB4100407530 /* module.cc in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ B88FB0DC116CEEA800407530 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ B88FB0E5116CEED300407530 /* dwarf2diehandler.cc in Sources */,
+ B88FB0E6116CEED300407530 /* dwarf2diehandler_unittest.cc in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ B88FB0EF116CEF1900407530 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ B88FB0FA116CF00E00407530 /* dwarf_line_to_module.cc in Sources */,
+ B88FB0FE116CF02400407530 /* module.cc in Sources */,
+ B88FB0FB116CF00E00407530 /* dwarf_line_to_module_unittest.cc in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ B88FB107116CF07900407530 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ B88FB112116CF1F000407530 /* dwarf_cu_to_module.cc in Sources */,
+ B88FB113116CF1F000407530 /* dwarf_cu_to_module_unittest.cc in Sources */,
+ B88FB114116CF1F000407530 /* language.cc in Sources */,
+ B88FB115116CF1F000407530 /* module.cc in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ B88FB11C116CF27F00407530 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ B88FB129116CF2DD00407530 /* module.cc in Sources */,
+ B88FB12A116CF2DD00407530 /* dwarf_cfi_to_module.cc in Sources */,
+ B88FB12B116CF2DD00407530 /* dwarf_cfi_to_module_unittest.cc in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ B88FB132116CF30F00407530 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ B88FB13D116CF38300407530 /* cfi_assembler.cc in Sources */,
+ B88FB13E116CF38300407530 /* bytereader.cc in Sources */,
+ B88FB13F116CF38300407530 /* bytereader_unittest.cc in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ B88FB148116CF4A700407530 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ B88FB152116CF4D300407530 /* byte_cursor_unittest.cc in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ B89E0E711166575200DD08C9 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 4247E63D2110D4B200482558 /* path_helper.cc in Sources */,
+ 162F6500161C5F2200CD68D5 /* arch_utilities.cc in Sources */,
+ B89E0E781166576C00DD08C9 /* macho_reader.cc in Sources */,
+ B89E0E7A1166576C00DD08C9 /* macho_dump.cc in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ B89E0E9211665A6400DD08C9 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ B89E0E9911665A7200DD08C9 /* macho_reader_unittest.cc in Sources */,
+ B89E0E9A11665A7200DD08C9 /* macho_reader.cc in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ B8C5B50E1166531A00D34F4E /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 4262382821AC49A000E5A3A6 /* dwarf_range_list_handler.h in Sources */,
+ 162F64FA161C591500CD68D5 /* arch_utilities.cc in Sources */,
+ B88FAE2C1166606200407530 /* macho_reader.cc in Sources */,
+ 8BCAAA4C1CE3A7980046090B /* elf_reader.cc in Sources */,
+ B8C5B5171166534700D34F4E /* dwarf2reader.cc in Sources */,
+ EB06C7531FEBC516000214D9 /* path_helper.cc in Sources */,
+ B8C5B5181166534700D34F4E /* bytereader.cc in Sources */,
+ B8C5B5191166534700D34F4E /* macho_utilities.cc in Sources */,
+ B8C5B51A1166534700D34F4E /* file_id.cc in Sources */,
+ B8C5B51B1166534700D34F4E /* macho_id.cc in Sources */,
+ B8C5B51C1166534700D34F4E /* macho_walker.cc in Sources */,
+ B8C5B51D1166534700D34F4E /* dump_syms.cc in Sources */,
+ B8C5B51E1166534700D34F4E /* dump_syms_tool.cc in Sources */,
+ B88FAE1911665FE400407530 /* dwarf2diehandler.cc in Sources */,
+ B88FAE261166603300407530 /* dwarf_cu_to_module.cc in Sources */,
+ B88FAE271166603300407530 /* dwarf_line_to_module.cc in Sources */,
+ 4262382721AC496F00E5A3A6 /* dwarf_range_list_handler.cc in Sources */,
+ B88FAE281166603300407530 /* language.cc in Sources */,
+ B88FAE291166603300407530 /* module.cc in Sources */,
+ B88FAE351166673E00407530 /* dwarf_cfi_to_module.cc in Sources */,
+ B88FAE3B11666C6F00407530 /* stabs_reader.cc in Sources */,
+ B88FAE3E11666C8900407530 /* stabs_to_module.cc in Sources */,
+ 4D72CAF513DFBAC2006CABE3 /* md5.cc in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ D21F97CF11CBA0F200239E38 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ D21F97E911CBA1FF00239E38 /* test_assembler.cc in Sources */,
+ D21F97D711CBA12300239E38 /* test_assembler_unittest.cc in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXTargetDependency section */
+ 8B31051511F100CF00FCF3E4 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = D21F97D111CBA0F200239E38 /* test_assembler_unittest */;
+ targetProxy = 8B31051411F100CF00FCF3E4 /* PBXContainerItemProxy */;
+ };
+ B84A91FA116CF796006C210E /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = B88FB023116BDFFF00407530 /* gtestmockall */;
+ targetProxy = B84A91F9116CF796006C210E /* PBXContainerItemProxy */;
+ };
+ B84A9201116CF7D2006C210E /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = B84A91F3116CF784006C210E /* stabs_to_module_unittest */;
+ targetProxy = B84A9200116CF7D2006C210E /* PBXContainerItemProxy */;
+ };
+ B88FAFCF116BDD7000407530 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = B89E0E9411665A6400DD08C9 /* macho_reader_unittest */;
+ targetProxy = B88FAFCE116BDD7000407530 /* PBXContainerItemProxy */;
+ };
+ B88FAFD1116BDD7000407530 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = B88FAF2E116A591D00407530 /* dwarf2reader_cfi_unittest */;
+ targetProxy = B88FAFD0116BDD7000407530 /* PBXContainerItemProxy */;
+ };
+ B88FB01D116BDF9800407530 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = B88FB006116BDE8300407530 /* stabs_reader_unittest */;
+ targetProxy = B88FB01C116BDF9800407530 /* PBXContainerItemProxy */;
+ };
+ B88FB03A116BE17E00407530 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = B88FB023116BDFFF00407530 /* gtestmockall */;
+ targetProxy = B88FB039116BE17E00407530 /* PBXContainerItemProxy */;
+ };
+ B88FB088116CE6D800407530 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = B88FB023116BDFFF00407530 /* gtestmockall */;
+ targetProxy = B88FB087116CE6D800407530 /* PBXContainerItemProxy */;
+ };
+ B88FB090116CE71000407530 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = B88FB023116BDFFF00407530 /* gtestmockall */;
+ targetProxy = B88FB08F116CE71000407530 /* PBXContainerItemProxy */;
+ };
+ B88FB0C0116CEAFE00407530 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = B88FB023116BDFFF00407530 /* gtestmockall */;
+ targetProxy = B88FB0BF116CEAFE00407530 /* PBXContainerItemProxy */;
+ };
+ B88FB0C8116CEB4A00407530 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = B88FB0B8116CEABF00407530 /* module_unittest */;
+ targetProxy = B88FB0C7116CEB4A00407530 /* PBXContainerItemProxy */;
+ };
+ B88FB0E8116CEEDA00407530 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = B88FB023116BDFFF00407530 /* gtestmockall */;
+ targetProxy = B88FB0E7116CEEDA00407530 /* PBXContainerItemProxy */;
+ };
+ B88FB0F8116CEF2E00407530 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = B88FB023116BDFFF00407530 /* gtestmockall */;
+ targetProxy = B88FB0F7116CEF2E00407530 /* PBXContainerItemProxy */;
+ };
+ B88FB110116CF08A00407530 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = B88FB023116BDFFF00407530 /* gtestmockall */;
+ targetProxy = B88FB10F116CF08A00407530 /* PBXContainerItemProxy */;
+ };
+ B88FB125116CF29E00407530 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = B88FB023116BDFFF00407530 /* gtestmockall */;
+ targetProxy = B88FB124116CF29E00407530 /* PBXContainerItemProxy */;
+ };
+ B88FB13C116CF35C00407530 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = B88FB023116BDFFF00407530 /* gtestmockall */;
+ targetProxy = B88FB13B116CF35C00407530 /* PBXContainerItemProxy */;
+ };
+ B88FB151116CF4C100407530 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = B88FB023116BDFFF00407530 /* gtestmockall */;
+ targetProxy = B88FB150116CF4C100407530 /* PBXContainerItemProxy */;
+ };
+ B88FB15B116CF53E00407530 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = B88FB14A116CF4A700407530 /* byte_cursor_unittest */;
+ targetProxy = B88FB15A116CF53E00407530 /* PBXContainerItemProxy */;
+ };
+ B88FB15D116CF54B00407530 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = B88FB11E116CF27F00407530 /* dwarf_cfi_to_module_unittest */;
+ targetProxy = B88FB15C116CF54B00407530 /* PBXContainerItemProxy */;
+ };
+ B88FB15F116CF54B00407530 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = B88FB0F1116CEF1900407530 /* dwarf_line_to_module_unittest */;
+ targetProxy = B88FB15E116CF54B00407530 /* PBXContainerItemProxy */;
+ };
+ B88FB161116CF54B00407530 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = B88FB109116CF07900407530 /* dwarf_cu_to_module_unittest */;
+ targetProxy = B88FB160116CF54B00407530 /* PBXContainerItemProxy */;
+ };
+ B88FB165116CF54B00407530 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = B88FB0DE116CEEA800407530 /* dwarf2diehandler_unittest */;
+ targetProxy = B88FB164116CF54B00407530 /* PBXContainerItemProxy */;
+ };
+ B88FB167116CF54B00407530 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = B88FB134116CF30F00407530 /* bytereader_unittest */;
+ targetProxy = B88FB166116CF54B00407530 /* PBXContainerItemProxy */;
+ };
+/* End PBXTargetDependency section */
+
+/* Begin XCBuildConfiguration section */
+ 1DEB927908733DD40010E9CD /* Debug */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 8B3102D411F0D60300FCF3E4 /* BreakpadDebug.xcconfig */;
+ buildSettings = {
+ CLANG_CXX_LANGUAGE_STANDARD = "c++0x";
+ HEADER_SEARCH_PATHS = (
+ ../../..,
+ ../../../common/mac/include/,
+ ../../../third_party/musl/include/,
+ );
+ };
+ name = Debug;
+ };
+ 1DEB927A08733DD40010E9CD /* Release */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 8B3102D511F0D60300FCF3E4 /* BreakpadRelease.xcconfig */;
+ buildSettings = {
+ CLANG_CXX_LANGUAGE_STANDARD = "c++0x";
+ HEADER_SEARCH_PATHS = (
+ ../../..,
+ ../../../common/mac/include/,
+ ../../../third_party/musl/include/,
+ );
+ };
+ name = Release;
+ };
+ B84A91F6116CF784006C210E /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ HEADER_SEARCH_PATHS = (
+ $inherited,
+ ../../../testing/googlemock,
+ ../../../testing/googlemock/include,
+ ../../../testing/googletest,
+ ../../../testing/googletest/include,
+ );
+ PRODUCT_NAME = stabs_to_module_unittest;
+ };
+ name = Debug;
+ };
+ B84A91F7116CF784006C210E /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ HEADER_SEARCH_PATHS = (
+ $inherited,
+ ../../../testing/googlemock,
+ ../../../testing/googlemock/include,
+ ../../../testing/googletest,
+ ../../../testing/googletest/include,
+ );
+ PRODUCT_NAME = stabs_to_module_unittest;
+ };
+ name = Release;
+ };
+ B88FAF31116A591F00407530 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ HEADER_SEARCH_PATHS = (
+ $inherited,
+ ../../../testing/googlemock,
+ ../../../testing/googlemock/include,
+ ../../../testing/googletest,
+ ../../../testing/googletest/include,
+ );
+ LIBRARY_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_1)",
+ );
+ LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_1 = "\"$(SRCROOT)/build/Debug\"";
+ PRODUCT_NAME = dwarf2reader_cfi_unittest;
+ };
+ name = Debug;
+ };
+ B88FAF32116A591F00407530 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ HEADER_SEARCH_PATHS = (
+ $inherited,
+ ../../../testing/googlemock,
+ ../../../testing/googlemock/include,
+ ../../../testing/googletest,
+ ../../../testing/googletest/include,
+ );
+ LIBRARY_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_1)",
+ );
+ LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_1 = "\"$(SRCROOT)/build/Debug\"";
+ PRODUCT_NAME = dwarf2reader_cfi_unittest;
+ };
+ name = Release;
+ };
+ B88FAFCA116BDCAD00407530 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = all_unittests;
+ };
+ name = Debug;
+ };
+ B88FAFCB116BDCAD00407530 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = all_unittests;
+ };
+ name = Release;
+ };
+ B88FB009116BDE8400407530 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ GCC_PREPROCESSOR_DEFINITIONS = HAVE_MACH_O_NLIST_H;
+ HEADER_SEARCH_PATHS = (
+ $inherited,
+ ../../../testing/googlemock,
+ ../../../testing/googlemock/include,
+ ../../../testing/googletest,
+ ../../../testing/googletest/include,
+ );
+ PRODUCT_NAME = stabs_reader_unittest;
+ };
+ name = Debug;
+ };
+ B88FB00A116BDE8400407530 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ GCC_PREPROCESSOR_DEFINITIONS = HAVE_MACH_O_NLIST_H;
+ HEADER_SEARCH_PATHS = (
+ $inherited,
+ ../../../testing/googlemock,
+ ../../../testing/googlemock/include,
+ ../../../testing/googletest,
+ ../../../testing/googletest/include,
+ );
+ PRODUCT_NAME = stabs_reader_unittest;
+ };
+ name = Release;
+ };
+ B88FB025116BE00100407530 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ HEADER_SEARCH_PATHS = (
+ $inherited,
+ ../../../testing/googlemock,
+ ../../../testing/googlemock/include,
+ ../../../testing/googletest,
+ ../../../testing/googletest/include,
+ );
+ PRODUCT_NAME = gtestmockall;
+ };
+ name = Debug;
+ };
+ B88FB026116BE00100407530 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ HEADER_SEARCH_PATHS = (
+ $inherited,
+ ../../../testing/googlemock,
+ ../../../testing/googlemock/include,
+ ../../../testing/googletest,
+ ../../../testing/googletest/include,
+ );
+ PRODUCT_NAME = gtestmockall;
+ };
+ name = Release;
+ };
+ B88FB0BB116CEAC000407530 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ HEADER_SEARCH_PATHS = (
+ $inherited,
+ ../../../testing/googlemock,
+ ../../../testing/googlemock/include,
+ ../../../testing/googletest,
+ ../../../testing/googletest/include,
+ );
+ PRODUCT_NAME = module_unittest;
+ };
+ name = Debug;
+ };
+ B88FB0BC116CEAC000407530 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ HEADER_SEARCH_PATHS = (
+ $inherited,
+ ../../../testing/googlemock,
+ ../../../testing/googlemock/include,
+ ../../../testing/googletest,
+ ../../../testing/googletest/include,
+ );
+ PRODUCT_NAME = module_unittest;
+ };
+ name = Release;
+ };
+ B88FB0E1116CEEA800407530 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ HEADER_SEARCH_PATHS = (
+ $inherited,
+ ../../../testing/googlemock,
+ ../../../testing/googlemock/include,
+ ../../../testing/googletest,
+ ../../../testing/googletest/include,
+ );
+ PRODUCT_NAME = dwarf2diehandler_unittest;
+ };
+ name = Debug;
+ };
+ B88FB0E2116CEEA800407530 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ HEADER_SEARCH_PATHS = (
+ $inherited,
+ ../../../testing/googlemock,
+ ../../../testing/googlemock/include,
+ ../../../testing/googletest,
+ ../../../testing/googletest/include,
+ );
+ PRODUCT_NAME = dwarf2diehandler_unittest;
+ };
+ name = Release;
+ };
+ B88FB0F4116CEF1900407530 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ HEADER_SEARCH_PATHS = (
+ $inherited,
+ ../../../testing/googlemock,
+ ../../../testing/googlemock/include,
+ ../../../testing/googletest,
+ ../../../testing/googletest/include,
+ );
+ PRODUCT_NAME = dwarf_line_to_module_unittest;
+ };
+ name = Debug;
+ };
+ B88FB0F5116CEF1900407530 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ HEADER_SEARCH_PATHS = (
+ $inherited,
+ ../../../testing/googlemock,
+ ../../../testing/googlemock/include,
+ ../../../testing/googletest,
+ ../../../testing/googletest/include,
+ );
+ PRODUCT_NAME = dwarf_line_to_module_unittest;
+ };
+ name = Release;
+ };
+ B88FB10C116CF07A00407530 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ HEADER_SEARCH_PATHS = (
+ $inherited,
+ ../../../testing/googlemock,
+ ../../../testing/googlemock/include,
+ ../../../testing/googletest,
+ ../../../testing/googletest/include,
+ );
+ PRODUCT_NAME = dwarf_cu_to_module_unittest;
+ };
+ name = Debug;
+ };
+ B88FB10D116CF07A00407530 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ HEADER_SEARCH_PATHS = (
+ $inherited,
+ ../../../testing/googlemock,
+ ../../../testing/googlemock/include,
+ ../../../testing/googletest,
+ ../../../testing/googletest/include,
+ );
+ PRODUCT_NAME = dwarf_cu_to_module_unittest;
+ };
+ name = Release;
+ };
+ B88FB121116CF28000407530 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ HEADER_SEARCH_PATHS = (
+ $inherited,
+ ../../../testing/googlemock,
+ ../../../testing/googlemock/include,
+ ../../../testing/googletest,
+ ../../../testing/googletest/include,
+ );
+ PRODUCT_NAME = dwarf_cfi_to_module_unittest;
+ };
+ name = Debug;
+ };
+ B88FB122116CF28000407530 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ HEADER_SEARCH_PATHS = (
+ $inherited,
+ ../../../testing/googlemock,
+ ../../../testing/googlemock/include,
+ ../../../testing/googletest,
+ ../../../testing/googletest/include,
+ );
+ PRODUCT_NAME = dwarf_cfi_to_module_unittest;
+ };
+ name = Release;
+ };
+ B88FB137116CF30F00407530 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ HEADER_SEARCH_PATHS = (
+ $inherited,
+ ../../../testing/googlemock,
+ ../../../testing/googlemock/include,
+ ../../../testing/googletest,
+ ../../../testing/googletest/include,
+ );
+ PRODUCT_NAME = bytereader_unittest;
+ };
+ name = Debug;
+ };
+ B88FB138116CF30F00407530 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ HEADER_SEARCH_PATHS = (
+ $inherited,
+ ../../../testing/googlemock,
+ ../../../testing/googlemock/include,
+ ../../../testing/googletest,
+ ../../../testing/googletest/include,
+ );
+ PRODUCT_NAME = bytereader_unittest;
+ };
+ name = Release;
+ };
+ B88FB14D116CF4A800407530 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ HEADER_SEARCH_PATHS = (
+ $inherited,
+ ../../../testing/googletest,
+ ../../../testing/googletest/include,
+ ../../../testing/googlemock,
+ ../../../testing/googlemock/include,
+ );
+ PRODUCT_NAME = byte_cursor_unittest;
+ };
+ name = Debug;
+ };
+ B88FB14E116CF4A800407530 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ HEADER_SEARCH_PATHS = (
+ $inherited,
+ ../../../testing/googletest,
+ ../../../testing/googletest/include,
+ ../../../testing/googlemock,
+ ../../../testing/googlemock/include,
+ );
+ PRODUCT_NAME = byte_cursor_unittest;
+ };
+ name = Release;
+ };
+ B89E0E761166575300DD08C9 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = macho_dump;
+ };
+ name = Debug;
+ };
+ B89E0E771166575300DD08C9 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = macho_dump;
+ };
+ name = Release;
+ };
+ B89E0E9711665A6400DD08C9 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ HEADER_SEARCH_PATHS = (
+ $inherited,
+ ../../../testing/googletest,
+ ../../../testing/googletest/include,
+ ../../../testing/googlemock,
+ ../../../testing/googlemock/include,
+ );
+ PRODUCT_NAME = macho_reader_unittest;
+ };
+ name = Debug;
+ };
+ B89E0E9811665A6400DD08C9 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ HEADER_SEARCH_PATHS = (
+ $inherited,
+ ../../../testing/googletest,
+ ../../../testing/googletest/include,
+ ../../../testing/googlemock,
+ ../../../testing/googlemock/include,
+ );
+ PRODUCT_NAME = macho_reader_unittest;
+ };
+ name = Release;
+ };
+ B8C5B5131166531B00D34F4E /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ GCC_PREPROCESSOR_DEFINITIONS = HAVE_MACH_O_NLIST_H;
+ GCC_VERSION = "";
+ PRODUCT_NAME = dump_syms;
+ };
+ name = Debug;
+ };
+ B8C5B5141166531B00D34F4E /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ GCC_PREPROCESSOR_DEFINITIONS = HAVE_MACH_O_NLIST_H;
+ GCC_VERSION = "";
+ PRODUCT_NAME = dump_syms;
+ };
+ name = Release;
+ };
+ D21F97D411CBA0F200239E38 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ HEADER_SEARCH_PATHS = (
+ $inherited,
+ ../../../testing/googletest,
+ ../../../testing/googletest/include,
+ ../../../testing/googlemock,
+ ../../../testing/googlemock/include,
+ );
+ PRODUCT_NAME = test_assembler_unittest;
+ };
+ name = Debug;
+ };
+ D21F97D511CBA0F200239E38 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ HEADER_SEARCH_PATHS = (
+ $inherited,
+ ../../../testing/googletest,
+ ../../../testing/googletest/include,
+ ../../../testing/googlemock,
+ ../../../testing/googlemock/include,
+ );
+ PRODUCT_NAME = test_assembler_unittest;
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ 1DEB927808733DD40010E9CD /* Build configuration list for PBXProject "dump_syms" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 1DEB927908733DD40010E9CD /* Debug */,
+ 1DEB927A08733DD40010E9CD /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ B84A9202116CF7F0006C210E /* Build configuration list for PBXNativeTarget "stabs_to_module_unittest" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ B84A91F6116CF784006C210E /* Debug */,
+ B84A91F7116CF784006C210E /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ B88FAF33116A594800407530 /* Build configuration list for PBXNativeTarget "dwarf2reader_cfi_unittest" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ B88FAF31116A591F00407530 /* Debug */,
+ B88FAF32116A591F00407530 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ B88FAFCC116BDCCC00407530 /* Build configuration list for PBXAggregateTarget "all_unittests" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ B88FAFCA116BDCAD00407530 /* Debug */,
+ B88FAFCB116BDCAD00407530 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ B88FB013116BDEC800407530 /* Build configuration list for PBXNativeTarget "stabs_reader_unittest" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ B88FB009116BDE8400407530 /* Debug */,
+ B88FB00A116BDE8400407530 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ B88FB027116BE02900407530 /* Build configuration list for PBXNativeTarget "gtestmockall" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ B88FB025116BE00100407530 /* Debug */,
+ B88FB026116BE00100407530 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ B88FB0BE116CEAFE00407530 /* Build configuration list for PBXNativeTarget "module_unittest" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ B88FB0BB116CEAC000407530 /* Debug */,
+ B88FB0BC116CEAC000407530 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ B88FB0E4116CEECE00407530 /* Build configuration list for PBXNativeTarget "dwarf2diehandler_unittest" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ B88FB0E1116CEEA800407530 /* Debug */,
+ B88FB0E2116CEEA800407530 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ B88FB0F9116CEF9800407530 /* Build configuration list for PBXNativeTarget "dwarf_line_to_module_unittest" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ B88FB0F4116CEF1900407530 /* Debug */,
+ B88FB0F5116CEF1900407530 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ B88FB111116CF0A800407530 /* Build configuration list for PBXNativeTarget "dwarf_cu_to_module_unittest" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ B88FB10C116CF07A00407530 /* Debug */,
+ B88FB10D116CF07A00407530 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ B88FB128116CF2C800407530 /* Build configuration list for PBXNativeTarget "dwarf_cfi_to_module_unittest" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ B88FB121116CF28000407530 /* Debug */,
+ B88FB122116CF28000407530 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ B88FB13A116CF33400407530 /* Build configuration list for PBXNativeTarget "bytereader_unittest" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ B88FB137116CF30F00407530 /* Debug */,
+ B88FB138116CF30F00407530 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ B88FB159116CF4F900407530 /* Build configuration list for PBXNativeTarget "byte_cursor_unittest" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ B88FB14D116CF4A800407530 /* Debug */,
+ B88FB14E116CF4A800407530 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ B89E0E7F116657A100DD08C9 /* Build configuration list for PBXNativeTarget "macho_dump" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ B89E0E761166575300DD08C9 /* Debug */,
+ B89E0E771166575300DD08C9 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ B89E0E9E11665A9600DD08C9 /* Build configuration list for PBXNativeTarget "macho_reader_unittest" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ B89E0E9711665A6400DD08C9 /* Debug */,
+ B89E0E9811665A6400DD08C9 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ B8C5B5151166533900D34F4E /* Build configuration list for PBXNativeTarget "dump_syms" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ B8C5B5131166531B00D34F4E /* Debug */,
+ B8C5B5141166531B00D34F4E /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ D21F97D611CBA11000239E38 /* Build configuration list for PBXNativeTarget "test_assembler_unittest" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ D21F97D411CBA0F200239E38 /* Debug */,
+ D21F97D511CBA0F200239E38 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = 08FB7793FE84155DC02AAC07 /* Project object */;
+}
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/mac/dump_syms/dump_syms_tool.cc b/toolkit/crashreporter/google-breakpad/src/tools/mac/dump_syms/dump_syms_tool.cc
new file mode 100644
index 0000000000..6f68457b4c
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/mac/dump_syms/dump_syms_tool.cc
@@ -0,0 +1,264 @@
+// -*- 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_syms_tool.cc: Command line tool that uses the DumpSymbols class.
+// TODO(waylonis): accept stdin
+
+#include <mach-o/arch.h>
+#include <unistd.h>
+
+#include <algorithm>
+#include <iostream>
+#include <vector>
+
+#include "common/mac/dump_syms.h"
+#include "common/mac/arch_utilities.h"
+#include "common/mac/macho_utilities.h"
+#include "common/scoped_ptr.h"
+
+using google_breakpad::DumpSymbols;
+using google_breakpad::Module;
+using google_breakpad::scoped_ptr;
+using std::vector;
+
+struct Options {
+ Options()
+ : srcPath(), dsymPath(), arch(), header_only(false),
+ cfi(true), handle_inter_cu_refs(true) {}
+
+ string srcPath;
+ string dsymPath;
+ const NXArchInfo *arch;
+ bool header_only;
+ bool cfi;
+ bool handle_inter_cu_refs;
+};
+
+static bool StackFrameEntryComparator(const Module::StackFrameEntry* a,
+ const Module::StackFrameEntry* b) {
+ return a->address < b->address;
+}
+
+// Copy the CFI data from |from_module| into |to_module|, for any non-
+// overlapping ranges.
+static void CopyCFIDataBetweenModules(Module* to_module,
+ const Module* from_module) {
+ typedef vector<Module::StackFrameEntry*>::const_iterator Iterator;
+
+ // Get the CFI data from both the source and destination modules and ensure
+ // it is sorted by start address.
+ vector<Module::StackFrameEntry*> from_data;
+ from_module->GetStackFrameEntries(&from_data);
+ std::sort(from_data.begin(), from_data.end(), &StackFrameEntryComparator);
+
+ vector<Module::StackFrameEntry*> to_data;
+ to_module->GetStackFrameEntries(&to_data);
+ std::sort(to_data.begin(), to_data.end(), &StackFrameEntryComparator);
+
+ Iterator to_it = to_data.begin();
+
+ for (Iterator it = from_data.begin(); it != from_data.end(); ++it) {
+ Module::StackFrameEntry* from_entry = *it;
+ Module::Address from_entry_end = from_entry->address + from_entry->size;
+
+ // Find the first CFI record in the |to_module| that does not have an
+ // address less than the entry to be copied.
+ while (to_it != to_data.end()) {
+ if (from_entry->address > (*to_it)->address)
+ ++to_it;
+ else
+ break;
+ }
+
+ // If the entry does not overlap, then it is safe to copy to |to_module|.
+ if (to_it == to_data.end() || (from_entry->address < (*to_it)->address &&
+ from_entry_end < (*to_it)->address)) {
+ to_module->AddStackFrameEntry(new Module::StackFrameEntry(*from_entry));
+ }
+ }
+}
+
+static bool Start(const Options &options) {
+ SymbolData symbol_data = options.cfi ? ALL_SYMBOL_DATA : NO_CFI;
+ DumpSymbols dump_symbols(symbol_data, options.handle_inter_cu_refs);
+
+ // For x86_64 binaries, the CFI data is in the __TEXT,__eh_frame of the
+ // Mach-O file, which is not copied into the dSYM. Whereas in i386, the CFI
+ // data is in the __DWARF,__debug_frame section, which is moved into the
+ // dSYM. Therefore, to get x86_64 CFI data, dump_syms needs to look at both
+ // the dSYM and the Mach-O file. If both paths are present and CFI was
+ // requested, then consider the Module as "split" and dump all the debug data
+ // from the primary debug info file, the dSYM, and then dump additional CFI
+ // data from the source Mach-O file.
+ bool split_module =
+ !options.dsymPath.empty() && !options.srcPath.empty() && options.cfi;
+ const string& primary_file =
+ split_module ? options.dsymPath : options.srcPath;
+
+ if (!dump_symbols.Read(primary_file))
+ return false;
+
+ if (options.arch) {
+ if (!dump_symbols.SetArchitecture(options.arch->cputype,
+ options.arch->cpusubtype)) {
+ fprintf(stderr, "%s: no architecture '%s' is present in file.\n",
+ primary_file.c_str(), options.arch->name);
+ size_t available_size;
+ const SuperFatArch *available =
+ dump_symbols.AvailableArchitectures(&available_size);
+ if (available_size == 1)
+ fprintf(stderr, "the file's architecture is: ");
+ else
+ fprintf(stderr, "architectures present in the file are:\n");
+ for (size_t i = 0; i < available_size; i++) {
+ const SuperFatArch *arch = &available[i];
+ const NXArchInfo *arch_info =
+ google_breakpad::BreakpadGetArchInfoFromCpuType(
+ arch->cputype, arch->cpusubtype);
+ if (arch_info)
+ fprintf(stderr, "%s (%s)\n", arch_info->name, arch_info->description);
+ else
+ fprintf(stderr, "unrecognized cpu type 0x%x, subtype 0x%x\n",
+ arch->cputype, arch->cpusubtype);
+ }
+ return false;
+ }
+ }
+
+ if (options.header_only)
+ return dump_symbols.WriteSymbolFileHeader(std::cout);
+
+ // Read the primary file into a Breakpad Module.
+ Module* module = NULL;
+ if (!dump_symbols.ReadSymbolData(&module))
+ return false;
+ scoped_ptr<Module> scoped_module(module);
+
+ // If this is a split module, read the secondary Mach-O file, from which the
+ // CFI data will be extracted.
+ if (split_module && primary_file == options.dsymPath) {
+ if (!dump_symbols.Read(options.srcPath))
+ return false;
+
+ Module* cfi_module = NULL;
+ if (!dump_symbols.ReadSymbolData(&cfi_module))
+ return false;
+ scoped_ptr<Module> scoped_cfi_module(cfi_module);
+
+ // Ensure that the modules are for the same debug code file.
+ if (cfi_module->name() != module->name() ||
+ cfi_module->os() != module->os() ||
+ cfi_module->architecture() != module->architecture() ||
+ cfi_module->identifier() != module->identifier()) {
+ fprintf(stderr, "Cannot generate a symbol file from split sources that do"
+ " not match.\n");
+ return false;
+ }
+
+ CopyCFIDataBetweenModules(module, cfi_module);
+ }
+
+ return module->Write(std::cout, symbol_data);
+}
+
+//=============================================================================
+static void Usage(int argc, const char *argv[]) {
+ fprintf(stderr, "Output a Breakpad symbol file from a Mach-o file.\n");
+ fprintf(stderr, "Usage: %s [-a ARCHITECTURE] [-c] [-g dSYM path] "
+ "<Mach-o file>\n", argv[0]);
+ fprintf(stderr, "\t-i: Output module header information only.\n");
+ fprintf(stderr, "\t-a: Architecture type [default: native, or whatever is\n");
+ fprintf(stderr, "\t in the file, if it contains only one architecture]\n");
+ fprintf(stderr, "\t-g: Debug symbol file (dSYM) to dump in addition to the "
+ "Mach-o file\n");
+ fprintf(stderr, "\t-c: Do not generate CFI section\n");
+ fprintf(stderr, "\t-r: Do not handle inter-compilation unit references\n");
+ fprintf(stderr, "\t-h: Usage\n");
+ fprintf(stderr, "\t-?: Usage\n");
+}
+
+//=============================================================================
+static void SetupOptions(int argc, const char *argv[], Options *options) {
+ extern int optind;
+ signed char ch;
+
+ while ((ch = getopt(argc, (char * const *)argv, "ia:g:chr?")) != -1) {
+ switch (ch) {
+ case 'i':
+ options->header_only = true;
+ break;
+ case 'a': {
+ const NXArchInfo *arch_info =
+ google_breakpad::BreakpadGetArchInfoFromName(optarg);
+ if (!arch_info) {
+ fprintf(stderr, "%s: Invalid architecture: %s\n", argv[0], optarg);
+ Usage(argc, argv);
+ exit(1);
+ }
+ options->arch = arch_info;
+ break;
+ }
+ case 'g':
+ options->dsymPath = optarg;
+ break;
+ case 'c':
+ options->cfi = false;
+ break;
+ case 'r':
+ options->handle_inter_cu_refs = false;
+ break;
+ case '?':
+ case 'h':
+ Usage(argc, argv);
+ exit(0);
+ break;
+ }
+ }
+
+ if ((argc - optind) != 1) {
+ fprintf(stderr, "Must specify Mach-o file\n");
+ Usage(argc, argv);
+ exit(1);
+ }
+
+ options->srcPath = argv[optind];
+}
+
+//=============================================================================
+int main (int argc, const char * argv[]) {
+ Options options;
+ bool result;
+
+ SetupOptions(argc, argv, &options);
+ result = Start(options);
+
+ return !result;
+}
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/mac/dump_syms/macho_dump.cc b/toolkit/crashreporter/google-breakpad/src/tools/mac/dump_syms/macho_dump.cc
new file mode 100644
index 0000000000..6e784ca709
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/mac/dump_syms/macho_dump.cc
@@ -0,0 +1,203 @@
+// 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_dump.cc: Dump the contents of a Mach-O file. This is mostly
+// a test program for the Mach_O::FatReader and Mach_O::Reader classes.
+
+#include <errno.h>
+#include <fcntl.h>
+#include <mach-o/arch.h>
+#include <sys/mman.h>
+#include <stdint.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <sstream>
+#include <string>
+#include <vector>
+
+#include "common/byte_cursor.h"
+#include "common/mac/arch_utilities.h"
+#include "common/mac/macho_reader.h"
+#include "common/path_helper.h"
+
+using google_breakpad::ByteBuffer;
+using std::ostringstream;
+using std::string;
+using std::vector;
+
+namespace {
+namespace mach_o = google_breakpad::mach_o;
+
+string program_name;
+
+int check_syscall(int result, const char *operation, const char *filename) {
+ if (result < 0) {
+ fprintf(stderr, "%s: %s '%s': %s\n",
+ program_name.c_str(), operation,
+ filename, strerror(errno));
+ exit(1);
+ }
+ return result;
+}
+
+class DumpSection: public mach_o::Reader::SectionHandler {
+ public:
+ DumpSection() : index_(0) { }
+ bool HandleSection(const mach_o::Section &section) {
+ printf(" section %d '%s' in segment '%s'\n"
+ " address: 0x%llx\n"
+ " alignment: 1 << %d B\n"
+ " flags: %d\n"
+ " size: %ld\n",
+ index_++, section.section_name.c_str(), section.segment_name.c_str(),
+ section.address, section.align,
+ mach_o::SectionFlags(section.flags),
+ section.contents.Size());
+ return true;
+ }
+
+ private:
+ int index_;
+};
+
+class DumpCommand: public mach_o::Reader::LoadCommandHandler {
+ public:
+ DumpCommand(mach_o::Reader *reader) : reader_(reader), index_(0) { }
+ bool UnknownCommand(mach_o::LoadCommandType type,
+ const ByteBuffer &contents) {
+ printf(" load command %d: %d", index_++, type);
+ return true;
+ }
+ bool SegmentCommand(const mach_o::Segment &segment) {
+ printf(" load command %d: %s-bit segment '%s'\n"
+ " address: 0x%llx\n"
+ " memory size: 0x%llx\n"
+ " maximum protection: 0x%x\n"
+ " initial protection: 0x%x\n"
+ " flags: %d\n"
+ " section_list size: %ld B\n",
+ index_++, (segment.bits_64 ? "64" : "32"), segment.name.c_str(),
+ segment.vmaddr, segment.vmsize, segment.maxprot,
+ segment.initprot, mach_o::SegmentFlags(segment.flags),
+ segment.section_list.Size());
+
+ DumpSection dump_section;
+ return reader_->WalkSegmentSections(segment, &dump_section);
+ }
+ private:
+ mach_o::Reader *reader_;
+ int index_;
+};
+
+void DumpFile(const char *filename) {
+ int fd = check_syscall(open(filename, O_RDONLY), "opening", filename);
+ struct stat attributes;
+ check_syscall(fstat(fd, &attributes),
+ "getting file attributes for", filename);
+ void *mapping = mmap(NULL, attributes.st_size, PROT_READ,
+ MAP_PRIVATE, fd, 0);
+ close(fd);
+ check_syscall(mapping == (void *)-1 ? -1 : 0,
+ "mapping contents of", filename);
+
+ mach_o::FatReader::Reporter fat_reporter(filename);
+ mach_o::FatReader fat_reader(&fat_reporter);
+ if (!fat_reader.Read(reinterpret_cast<uint8_t *>(mapping),
+ attributes.st_size)) {
+ exit(1);
+ }
+ printf("filename: %s\n", filename);
+ size_t object_files_size;
+ const SuperFatArch* super_fat_object_files =
+ fat_reader.object_files(&object_files_size);
+ struct fat_arch *object_files;
+ if (!super_fat_object_files->ConvertToFatArch(object_files)) {
+ exit(1);
+ }
+ printf(" object file count: %ld\n", object_files_size);
+ for (size_t i = 0; i < object_files_size; i++) {
+ const struct fat_arch &file = object_files[i];
+ const NXArchInfo *fat_arch_info =
+ google_breakpad::BreakpadGetArchInfoFromCpuType(
+ file.cputype, file.cpusubtype);
+ printf("\n object file %ld:\n"
+ " fat header:\n:"
+ " CPU type: %s (%s)\n"
+ " size: %d B\n"
+ " alignment: 1<<%d B\n",
+ i, fat_arch_info->name, fat_arch_info->description,
+ file.size, file.align);
+
+ ostringstream name;
+ name << filename;
+ if (object_files_size > 1)
+ name << ", object file #" << i;
+ ByteBuffer file_contents(reinterpret_cast<uint8_t *>(mapping)
+ + file.offset, file.size);
+ mach_o::Reader::Reporter reporter(name.str());
+ mach_o::Reader reader(&reporter);
+ if (!reader.Read(file_contents, file.cputype, file.cpusubtype)) {
+ exit(1);
+ }
+
+ const NXArchInfo *macho_arch_info =
+ NXGetArchInfoFromCpuType(reader.cpu_type(),
+ reader.cpu_subtype());
+ printf(" Mach-O header:\n"
+ " word size: %s\n"
+ " CPU type: %s (%s)\n"
+ " File type: %d\n"
+ " flags: %x\n",
+ (reader.bits_64() ? "64 bits" : "32 bits"),
+ macho_arch_info->name, macho_arch_info->description,
+ reader.file_type(), reader.flags());
+
+ DumpCommand dump_command(&reader);
+ reader.WalkLoadCommands(&dump_command);
+ }
+ munmap(mapping, attributes.st_size);
+}
+
+} // namespace
+
+int main(int argc, char **argv) {
+ program_name = google_breakpad::BaseName(argv[0]);
+ if (argc == 1) {
+ fprintf(stderr, "Usage: %s FILE ...\n"
+ "Dump the contents of the Mach-O or fat binary files "
+ "'FILE ...'.\n", program_name.c_str());
+ }
+ for (int i = 1; i < argc; i++) {
+ DumpFile(argv[i]);
+ }
+}
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/mac/symupload/minidump_upload.m b/toolkit/crashreporter/google-breakpad/src/tools/mac/symupload/minidump_upload.m
new file mode 100644
index 0000000000..741ad765e5
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/mac/symupload/minidump_upload.m
@@ -0,0 +1,135 @@
+// Copyright (c) 2006, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// minidump_upload.m: Upload a minidump to a HTTP server. The upload is sent as
+// a multipart/form-data POST request with the following parameters:
+// prod: the product name
+// ver: the product version
+// symbol_file: the breakpad format symbol file
+
+#import <unistd.h>
+
+#import <Foundation/Foundation.h>
+
+#import "common/mac/HTTPMultipartUpload.h"
+
+typedef struct {
+ NSString *minidumpPath;
+ NSString *uploadURLStr;
+ NSString *product;
+ NSString *version;
+ BOOL success;
+} Options;
+
+//=============================================================================
+static void Start(Options *options) {
+ NSURL *url = [NSURL URLWithString:options->uploadURLStr];
+ HTTPMultipartUpload *ul = [[HTTPMultipartUpload alloc] initWithURL:url];
+ NSMutableDictionary *parameters = [NSMutableDictionary dictionary];
+
+ // Add parameters
+ [parameters setObject:options->product forKey:@"prod"];
+ [parameters setObject:options->version forKey:@"ver"];
+ [ul setParameters:parameters];
+
+ // Add file
+ [ul addFileAtPath:options->minidumpPath name:@"upload_file_minidump"];
+
+ // Send it
+ NSError *error = nil;
+ NSData *data = [ul send:&error];
+ NSString *result = [[NSString alloc] initWithData:data
+ encoding:NSUTF8StringEncoding];
+
+ NSLog(@"Send: %@", error ? [error description] : @"No Error");
+ NSLog(@"Response: %ld", (long)[[ul response] statusCode]);
+ NSLog(@"Result: %lu bytes\n%@", (unsigned long)[data length], result);
+
+ [result release];
+ [ul release];
+ options->success = !error;
+}
+
+//=============================================================================
+static void
+Usage(int argc, const char *argv[]) {
+ fprintf(stderr, "Submit minidump information.\n");
+ fprintf(stderr, "Usage: %s -p <product> -v <version> <minidump> "
+ "<upload-URL>\n", argv[0]);
+ fprintf(stderr, "<minidump> should be a minidump.\n");
+ fprintf(stderr, "<upload-URL> is the destination for the upload\n");
+
+ fprintf(stderr, "\t-h: Usage\n");
+ fprintf(stderr, "\t-?: Usage\n");
+}
+
+//=============================================================================
+static void
+SetupOptions(int argc, const char *argv[], Options *options) {
+ extern int optind;
+ char ch;
+
+ while ((ch = getopt(argc, (char * const *)argv, "p:v:h?")) != -1) {
+ switch (ch) {
+ case 'p':
+ options->product = [NSString stringWithUTF8String:optarg];
+ break;
+ case 'v':
+ options->version = [NSString stringWithUTF8String:optarg];
+ break;
+
+ default:
+ Usage(argc, argv);
+ exit(0);
+ break;
+ }
+ }
+
+ if ((argc - optind) != 2) {
+ fprintf(stderr, "%s: Missing symbols file and/or upload-URL\n", argv[0]);
+ Usage(argc, argv);
+ exit(1);
+ }
+
+ options->minidumpPath = [NSString stringWithUTF8String:argv[optind]];
+ options->uploadURLStr = [NSString stringWithUTF8String:argv[optind + 1]];
+}
+
+//=============================================================================
+int main (int argc, const char * argv[]) {
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ Options options;
+
+ bzero(&options, sizeof(Options));
+ SetupOptions(argc, argv, &options);
+ Start(&options);
+
+ [pool release];
+ return options.success ? 0 : 1;
+}
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/mac/symupload/symupload.m b/toolkit/crashreporter/google-breakpad/src/tools/mac/symupload/symupload.m
new file mode 100644
index 0000000000..a7cce7b00c
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/mac/symupload/symupload.m
@@ -0,0 +1,204 @@
+// 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.
+
+// symupload.m: Upload a symbol file to a HTTP server. The upload is sent as
+// a multipart/form-data POST request with the following parameters:
+// code_file: the basename of the module, e.g. "app"
+// debug_file: the basename of the debugging file, e.g. "app"
+// debug_identifier: the debug file's identifier, usually consisting of
+// the guid and age embedded in the pdb, e.g.
+// "11111111BBBB3333DDDD555555555555F"
+// os: the operating system that the module was built for
+// cpu: the CPU that the module was built for (x86 or ppc)
+// symbol_file: the contents of the breakpad-format symbol file
+
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <Foundation/Foundation.h>
+#include "HTTPMultipartUpload.h"
+
+typedef struct {
+ NSString *symbolsPath;
+ NSString *uploadURLStr;
+ BOOL success;
+} Options;
+
+//=============================================================================
+static NSArray *ModuleDataForSymbolFile(NSString *file) {
+ NSFileHandle *fh = [NSFileHandle fileHandleForReadingAtPath:file];
+ NSData *data = [fh readDataOfLength:1024];
+ NSString *str = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
+ NSScanner *scanner = [NSScanner scannerWithString:str];
+ NSString *line;
+ NSMutableArray *parts = nil;
+ const int MODULE_ID_INDEX = 3;
+
+ if ([scanner scanUpToString:@"\n" intoString:&line]) {
+ parts = [[NSMutableArray alloc] init];
+ NSScanner *moduleInfoScanner = [NSScanner scannerWithString:line];
+ NSString *moduleInfo;
+ // Get everything BEFORE the module name. None of these properties
+ // can have spaces.
+ for (int i = 0; i <= MODULE_ID_INDEX; i++) {
+ [moduleInfoScanner scanUpToString:@" " intoString:&moduleInfo];
+ [parts addObject:moduleInfo];
+ }
+
+ // Now get the module name. This can have a space so we scan to
+ // the end of the line.
+ [moduleInfoScanner scanUpToString:@"\n" intoString:&moduleInfo];
+ [parts addObject:moduleInfo];
+ }
+
+ [str release];
+
+ return parts;
+}
+
+//=============================================================================
+static void Start(Options *options) {
+ NSURL *url = [NSURL URLWithString:options->uploadURLStr];
+ HTTPMultipartUpload *ul = [[HTTPMultipartUpload alloc] initWithURL:url];
+ NSMutableDictionary *parameters = [NSMutableDictionary dictionary];
+ NSArray *moduleParts = ModuleDataForSymbolFile(options->symbolsPath);
+ NSMutableString *compactedID =
+ [NSMutableString stringWithString:[moduleParts objectAtIndex:3]];
+ [compactedID replaceOccurrencesOfString:@"-" withString:@"" options:0
+ range:NSMakeRange(0, [compactedID length])];
+
+ // Add parameters
+ [parameters setObject:compactedID forKey:@"debug_identifier"];
+
+ // MODULE <os> <cpu> <uuid> <module-name>
+ // 0 1 2 3 4
+ [parameters setObject:[moduleParts objectAtIndex:1] forKey:@"os"];
+ [parameters setObject:[moduleParts objectAtIndex:2] forKey:@"cpu"];
+ [parameters setObject:[moduleParts objectAtIndex:4] forKey:@"debug_file"];
+ [parameters setObject:[moduleParts objectAtIndex:4] forKey:@"code_file"];
+ [ul setParameters:parameters];
+
+ NSArray *keys = [parameters allKeys];
+ int count = [keys count];
+ for (int i = 0; i < count; ++i) {
+ NSString *key = [keys objectAtIndex:i];
+ NSString *value = [parameters objectForKey:key];
+ fprintf(stdout, "'%s' = '%s'\n", [key UTF8String],
+ [value UTF8String]);
+ }
+
+ // Add file
+ [ul addFileAtPath:options->symbolsPath name:@"symbol_file"];
+
+ // Send it
+ NSError *error = nil;
+ NSData *data = [ul send:&error];
+ NSString *result = [[NSString alloc] initWithData:data
+ encoding:NSUTF8StringEncoding];
+ int status = [[ul response] statusCode];
+
+ fprintf(stdout, "Send: %s\n", error ? [[error description] UTF8String] :
+ "No Error");
+ fprintf(stdout, "Response: %d\n", status);
+ fprintf(stdout, "Result: %lu bytes\n%s\n",
+ (unsigned long)[data length], [result UTF8String]);
+
+ [result release];
+ [ul release];
+ options->success = !error && status==200;
+}
+
+//=============================================================================
+static void
+Usage(int argc, const char *argv[]) {
+ fprintf(stderr, "Submit symbol information.\n");
+ fprintf(stderr, "Usage: %s <symbols> <upload-URL>\n", argv[0]);
+ fprintf(stderr, "<symbols> should be created by using the dump_syms tool.\n");
+ fprintf(stderr, "<upload-URL> is the destination for the upload\n");
+ fprintf(stderr, "\t-h: Usage\n");
+ fprintf(stderr, "\t-?: Usage\n");
+}
+
+//=============================================================================
+static void
+SetupOptions(int argc, const char *argv[], Options *options) {
+ extern int optind;
+ char ch;
+
+ while ((ch = getopt(argc, (char * const *)argv, "h?")) != -1) {
+ switch (ch) {
+ default:
+ Usage(argc, argv);
+ exit(0);
+ break;
+ }
+ }
+
+ if ((argc - optind) != 2) {
+ fprintf(stderr, "%s: Missing symbols file and/or upload-URL\n", argv[0]);
+ Usage(argc, argv);
+ exit(1);
+ }
+
+ int fd = open(argv[optind], O_RDONLY);
+ if (fd < 0) {
+ fprintf(stderr, "%s: %s: %s\n", argv[0], argv[optind], strerror(errno));
+ exit(1);
+ }
+
+ struct stat statbuf;
+ if (fstat(fd, &statbuf) < 0) {
+ fprintf(stderr, "%s: %s: %s\n", argv[0], argv[optind], strerror(errno));
+ close(fd);
+ exit(1);
+ }
+ close(fd);
+
+ if (!S_ISREG(statbuf.st_mode)) {
+ fprintf(stderr, "%s: %s: not a regular file\n", argv[0], argv[optind]);
+ exit(1);
+ }
+
+ options->symbolsPath = [NSString stringWithUTF8String:argv[optind]];
+ options->uploadURLStr = [NSString stringWithUTF8String:argv[optind + 1]];
+}
+
+//=============================================================================
+int main (int argc, const char * argv[]) {
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ Options options;
+
+ bzero(&options, sizeof(Options));
+ SetupOptions(argc, argv, &options);
+ Start(&options);
+
+ [pool release];
+ return options.success ? 0 : 1;
+}
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/mac/symupload/symupload.xcodeproj/project.pbxproj b/toolkit/crashreporter/google-breakpad/src/tools/mac/symupload/symupload.xcodeproj/project.pbxproj
new file mode 100644
index 0000000000..a6a78dc5f3
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/mac/symupload/symupload.xcodeproj/project.pbxproj
@@ -0,0 +1,254 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 45;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ 8B31022C11F0CEBD00FCF3E4 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 08FB779EFE84155DC02AAC07 /* Foundation.framework */; };
+ 8DD76F9A0486AA7600D96B5E /* symupload.m in Sources */ = {isa = PBXBuildFile; fileRef = 08FB7796FE84155DC02AAC07 /* symupload.m */; settings = {ATTRIBUTES = (); }; };
+ 8DD76F9C0486AA7600D96B5E /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 08FB779EFE84155DC02AAC07 /* Foundation.framework */; };
+ 9BC1D49E0B37427A00F2A2B4 /* minidump_upload.m in Sources */ = {isa = PBXBuildFile; fileRef = 9BD836000B0544BA0055103E /* minidump_upload.m */; };
+ 9BD8336A0B03E4080055103E /* HTTPMultipartUpload.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 9BD833680B03E4080055103E /* HTTPMultipartUpload.h */; };
+ 9BD8336B0B03E4080055103E /* HTTPMultipartUpload.m in Sources */ = {isa = PBXBuildFile; fileRef = 9BD833690B03E4080055103E /* HTTPMultipartUpload.m */; };
+ 9BD836180B0549F70055103E /* HTTPMultipartUpload.m in Sources */ = {isa = PBXBuildFile; fileRef = 9BD833690B03E4080055103E /* HTTPMultipartUpload.m */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXCopyFilesBuildPhase section */
+ 8DD76F9E0486AA7600D96B5E /* CopyFiles */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 8;
+ dstPath = /usr/share/man/man1/;
+ dstSubfolderSpec = 0;
+ files = (
+ 9BD8336A0B03E4080055103E /* HTTPMultipartUpload.h in CopyFiles */,
+ );
+ runOnlyForDeploymentPostprocessing = 1;
+ };
+/* End PBXCopyFilesBuildPhase section */
+
+/* Begin PBXFileReference section */
+ 08FB7796FE84155DC02AAC07 /* symupload.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = symupload.m; sourceTree = "<group>"; };
+ 08FB779EFE84155DC02AAC07 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
+ 8B31022B11F0CE6900FCF3E4 /* Breakpad.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Breakpad.xcconfig; path = ../../../common/mac/Breakpad.xcconfig; sourceTree = SOURCE_ROOT; };
+ 8B3102B611F0D5CE00FCF3E4 /* BreakpadDebug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = BreakpadDebug.xcconfig; path = ../../../common/mac/BreakpadDebug.xcconfig; sourceTree = SOURCE_ROOT; };
+ 8B3102B711F0D5CE00FCF3E4 /* BreakpadRelease.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = BreakpadRelease.xcconfig; path = ../../../common/mac/BreakpadRelease.xcconfig; sourceTree = SOURCE_ROOT; };
+ 8DD76FA10486AA7600D96B5E /* symupload */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = symupload; sourceTree = BUILT_PRODUCTS_DIR; };
+ 9BD833680B03E4080055103E /* HTTPMultipartUpload.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HTTPMultipartUpload.h; path = ../../../common/mac/HTTPMultipartUpload.h; sourceTree = "<group>"; };
+ 9BD833690B03E4080055103E /* HTTPMultipartUpload.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = HTTPMultipartUpload.m; path = ../../../common/mac/HTTPMultipartUpload.m; sourceTree = "<group>"; };
+ 9BD835FB0B0544950055103E /* minidump_upload */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = minidump_upload; sourceTree = BUILT_PRODUCTS_DIR; };
+ 9BD836000B0544BA0055103E /* minidump_upload.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = minidump_upload.m; sourceTree = "<group>"; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ 8DD76F9B0486AA7600D96B5E /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 8DD76F9C0486AA7600D96B5E /* Foundation.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 9BD835F90B0544950055103E /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 8B31022C11F0CEBD00FCF3E4 /* Foundation.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 08FB7794FE84155DC02AAC07 /* symupload */ = {
+ isa = PBXGroup;
+ children = (
+ 8B31022B11F0CE6900FCF3E4 /* Breakpad.xcconfig */,
+ 8B3102B611F0D5CE00FCF3E4 /* BreakpadDebug.xcconfig */,
+ 8B3102B711F0D5CE00FCF3E4 /* BreakpadRelease.xcconfig */,
+ 08FB7796FE84155DC02AAC07 /* symupload.m */,
+ 9BD836000B0544BA0055103E /* minidump_upload.m */,
+ 9BD833680B03E4080055103E /* HTTPMultipartUpload.h */,
+ 9BD833690B03E4080055103E /* HTTPMultipartUpload.m */,
+ 08FB779DFE84155DC02AAC07 /* External Frameworks and Libraries */,
+ 1AB674ADFE9D54B511CA2CBB /* Products */,
+ );
+ name = symupload;
+ sourceTree = "<group>";
+ };
+ 08FB779DFE84155DC02AAC07 /* External Frameworks and Libraries */ = {
+ isa = PBXGroup;
+ children = (
+ 08FB779EFE84155DC02AAC07 /* Foundation.framework */,
+ );
+ name = "External Frameworks and Libraries";
+ sourceTree = "<group>";
+ };
+ 1AB674ADFE9D54B511CA2CBB /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 8DD76FA10486AA7600D96B5E /* symupload */,
+ 9BD835FB0B0544950055103E /* minidump_upload */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+ 8DD76F960486AA7600D96B5E /* symupload */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 1DEB927408733DD40010E9CD /* Build configuration list for PBXNativeTarget "symupload" */;
+ buildPhases = (
+ 8DD76F990486AA7600D96B5E /* Sources */,
+ 8DD76F9B0486AA7600D96B5E /* Frameworks */,
+ 8DD76F9E0486AA7600D96B5E /* CopyFiles */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = symupload;
+ productInstallPath = "$(HOME)/bin";
+ productName = symupload;
+ productReference = 8DD76FA10486AA7600D96B5E /* symupload */;
+ productType = "com.apple.product-type.tool";
+ };
+ 9BD835FA0B0544950055103E /* minidump_upload */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 9BD836020B0544BB0055103E /* Build configuration list for PBXNativeTarget "minidump_upload" */;
+ buildPhases = (
+ 9BD835F80B0544950055103E /* Sources */,
+ 9BD835F90B0544950055103E /* Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = minidump_upload;
+ productName = minidump_upload;
+ productReference = 9BD835FB0B0544950055103E /* minidump_upload */;
+ productType = "com.apple.product-type.tool";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 08FB7793FE84155DC02AAC07 /* Project object */ = {
+ isa = PBXProject;
+ buildConfigurationList = 1DEB927808733DD40010E9CD /* Build configuration list for PBXProject "symupload" */;
+ compatibilityVersion = "Xcode 3.1";
+ hasScannedForEncodings = 1;
+ mainGroup = 08FB7794FE84155DC02AAC07 /* symupload */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ 8DD76F960486AA7600D96B5E /* symupload */,
+ 9BD835FA0B0544950055103E /* minidump_upload */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXSourcesBuildPhase section */
+ 8DD76F990486AA7600D96B5E /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 8DD76F9A0486AA7600D96B5E /* symupload.m in Sources */,
+ 9BD8336B0B03E4080055103E /* HTTPMultipartUpload.m in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 9BD835F80B0544950055103E /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 9BD836180B0549F70055103E /* HTTPMultipartUpload.m in Sources */,
+ 9BC1D49E0B37427A00F2A2B4 /* minidump_upload.m in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin XCBuildConfiguration section */
+ 1DEB927508733DD40010E9CD /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ HEADER_SEARCH_PATHS = ../../..;
+ PRODUCT_NAME = symupload;
+ };
+ name = Debug;
+ };
+ 1DEB927608733DD40010E9CD /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ HEADER_SEARCH_PATHS = ../../..;
+ PRODUCT_NAME = symupload;
+ };
+ name = Release;
+ };
+ 1DEB927908733DD40010E9CD /* Debug */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 8B3102B611F0D5CE00FCF3E4 /* BreakpadDebug.xcconfig */;
+ buildSettings = {
+ };
+ name = Debug;
+ };
+ 1DEB927A08733DD40010E9CD /* Release */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 8B3102B711F0D5CE00FCF3E4 /* BreakpadRelease.xcconfig */;
+ buildSettings = {
+ };
+ name = Release;
+ };
+ 9BD836030B0544BB0055103E /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ HEADER_SEARCH_PATHS = ../../..;
+ PRODUCT_NAME = minidump_upload;
+ };
+ name = Debug;
+ };
+ 9BD836040B0544BB0055103E /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ HEADER_SEARCH_PATHS = ../../..;
+ PRODUCT_NAME = minidump_upload;
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ 1DEB927408733DD40010E9CD /* Build configuration list for PBXNativeTarget "symupload" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 1DEB927508733DD40010E9CD /* Debug */,
+ 1DEB927608733DD40010E9CD /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 1DEB927808733DD40010E9CD /* Build configuration list for PBXProject "symupload" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 1DEB927908733DD40010E9CD /* Debug */,
+ 1DEB927A08733DD40010E9CD /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 9BD836020B0544BB0055103E /* Build configuration list for PBXNativeTarget "minidump_upload" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 9BD836030B0544BB0055103E /* Debug */,
+ 9BD836040B0544BB0055103E /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = 08FB7793FE84155DC02AAC07 /* Project object */;
+}
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/mac/tools_mac.gypi b/toolkit/crashreporter/google-breakpad/src/tools/mac/tools_mac.gypi
new file mode 100644
index 0000000000..7457573b4b
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/mac/tools_mac.gypi
@@ -0,0 +1,116 @@
+# 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': {
+ 'include_dirs': [
+ '../..',
+ ],
+ },
+ 'targets': [
+ {
+ 'target_name': 'crash_report',
+ 'type': 'executable',
+ 'sources': [
+ 'crash_report/crash_report.mm',
+ 'crash_report/on_demand_symbol_supplier.h',
+ 'crash_report/on_demand_symbol_supplier.mm',
+ ],
+ 'link_settings': {
+ 'libraries': [
+ '$(SDKROOT)/System/Library/Frameworks/Foundation.framework',
+ ],
+ },
+ 'dependencies': [
+ '../common/common.gyp:common',
+ '../processor/processor.gyp:processor',
+ ],
+ },
+ {
+ 'target_name': 'dump_syms',
+ 'type': 'executable',
+ 'sources': [
+ 'dump_syms/dump_syms_tool.cc',
+ ],
+ 'link_settings': {
+ 'libraries': [
+ '$(SDKROOT)/System/Library/Frameworks/Foundation.framework',
+ ],
+ },
+ 'dependencies': [
+ '../common/common.gyp:common',
+ ],
+ },
+ {
+ 'target_name': 'macho_dump',
+ 'type': 'executable',
+ 'sources': [
+ 'dump_syms/macho_dump.cc',
+ ],
+ 'dependencies': [
+ '../common/common.gyp:common',
+ ],
+ },
+ {
+ 'target_name': 'minidump_upload',
+ 'type': 'executable',
+ 'sources': [
+ 'symupload/minidump_upload.m',
+ ],
+ 'include_dirs': [
+ '../../common/mac',
+ ],
+ 'link_settings': {
+ 'libraries': [
+ '$(SDKROOT)/System/Library/Frameworks/Foundation.framework',
+ ],
+ },
+ 'dependencies': [
+ '../common/common.gyp:common',
+ ],
+ },
+ {
+ 'target_name': 'symupload',
+ 'type': 'executable',
+ 'sources': [
+ 'symupload/symupload.m',
+ ],
+ 'include_dirs': [
+ '../../common/mac',
+ ],
+ 'link_settings': {
+ 'libraries': [
+ '$(SDKROOT)/System/Library/Frameworks/Foundation.framework',
+ ],
+ },
+ 'dependencies': [
+ '../common/common.gyp:common',
+ ],
+ },
+ ],
+}
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/mac/upload_system_symbols/arch_constants.h b/toolkit/crashreporter/google-breakpad/src/tools/mac/upload_system_symbols/arch_constants.h
new file mode 100644
index 0000000000..e12e53e229
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/mac/upload_system_symbols/arch_constants.h
@@ -0,0 +1,67 @@
+/* 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 <mach-o/arch.h>
+#include <mach-o/loader.h>
+#include <mach/machine.h>
+
+// Go/Cgo does not support #define constants, so turn them into symbols
+// that are reachable from Go.
+
+#ifndef CPU_TYPE_ARM64
+#define CPU_TYPE_ARM64 (CPU_TYPE_ARM | CPU_ARCH_ABI64)
+#endif
+
+#ifndef CPU_SUBTYPE_ARM64_ALL
+#define CPU_SUBTYPE_ARM64_ALL 0
+#endif
+
+#ifndef CPU_SUBTYPE_ARM64_E
+#define CPU_SUBTYPE_ARM64_E 2
+#endif
+
+const cpu_type_t kCPU_TYPE_ARM = CPU_TYPE_ARM;
+const cpu_type_t kCPU_TYPE_ARM64 = CPU_TYPE_ARM64;
+
+const cpu_subtype_t kCPU_SUBTYPE_ARM64_ALL = CPU_SUBTYPE_ARM64_ALL;
+const cpu_subtype_t kCPU_SUBTYPE_ARM64_E = CPU_SUBTYPE_ARM64_E;
+const cpu_subtype_t kCPU_SUBTYPE_ARM_V7S = CPU_SUBTYPE_ARM_V7S;
+
+const char* GetNXArchInfoName(cpu_type_t cpu_type, cpu_subtype_t cpu_subtype) {
+ const NXArchInfo* arch_info = NXGetArchInfoFromCpuType(cpu_type, cpu_subtype);
+ if (!arch_info)
+ return 0;
+ return arch_info->name;
+}
+
+const uint32_t kMachHeaderFtypeDylib = MH_DYLIB;
+const uint32_t kMachHeaderFtypeBundle = MH_BUNDLE;
+const uint32_t kMachHeaderFtypeExe = MH_EXECUTE;
+const uint32_t kMachHeaderFtypeDylinker = MH_DYLINKER;
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/mac/upload_system_symbols/arch_reader.go b/toolkit/crashreporter/google-breakpad/src/tools/mac/upload_system_symbols/arch_reader.go
new file mode 100644
index 0000000000..ed98fa60f4
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/mac/upload_system_symbols/arch_reader.go
@@ -0,0 +1,69 @@
+/* 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.
+*/
+
+package main
+
+import (
+ "debug/macho"
+)
+
+/*
+#include "arch_constants.h"
+*/
+import "C"
+
+// getArchStringFromHeader takes a MachO FileHeader and returns a string that
+// represents the CPU type and subtype.
+// This function is a Go version of src/common/mac/arch_utilities.cc:BreakpadGetArchInfoFromCpuType().
+func getArchStringFromHeader(header macho.FileHeader) string {
+ // TODO(rsesek): As of 10.9.4, OS X doesn't list these in /usr/include/mach/machine.h.
+ if header.Cpu == C.kCPU_TYPE_ARM64 && header.SubCpu == C.kCPU_SUBTYPE_ARM64_ALL {
+ return "arm64"
+ }
+ if header.Cpu == C.kCPU_TYPE_ARM64 && header.SubCpu == C.kCPU_SUBTYPE_ARM64_E {
+ return "arm64e"
+ }
+ if header.Cpu == C.kCPU_TYPE_ARM && header.SubCpu == C.kCPU_SUBTYPE_ARM_V7S {
+ return "armv7s"
+ }
+
+ cstr := C.GetNXArchInfoName(C.cpu_type_t(header.Cpu), C.cpu_subtype_t(header.SubCpu))
+ if cstr == nil {
+ return ""
+ }
+ return C.GoString(cstr)
+}
+
+const (
+ MachODylib macho.Type = C.kMachHeaderFtypeDylib
+ MachOBundle = C.kMachHeaderFtypeBundle
+ MachOExe = C.kMachHeaderFtypeExe
+ MachODylinker = C.kMachHeaderFtypeDylinker
+)
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/mac/upload_system_symbols/upload_system_symbols.go b/toolkit/crashreporter/google-breakpad/src/tools/mac/upload_system_symbols/upload_system_symbols.go
new file mode 100644
index 0000000000..05a7764abf
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/mac/upload_system_symbols/upload_system_symbols.go
@@ -0,0 +1,432 @@
+/* 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.
+*/
+
+/*
+Tool upload_system_symbols generates and uploads Breakpad symbol files for OS X system libraries.
+
+This tool shells out to the dump_syms and symupload Breakpad tools. In its default mode, this
+will find all dynamic libraries on the system, run dump_syms to create the Breakpad symbol files,
+and then upload them to Google's crash infrastructure.
+
+The tool can also be used to only dump libraries or upload from a directory. See -help for more
+information.
+
+Both i386 and x86_64 architectures will be dumped and uploaded.
+*/
+package main
+
+import (
+ "debug/macho"
+ "flag"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "log"
+ "os"
+ "os/exec"
+ "path"
+ "regexp"
+ "strings"
+ "sync"
+ "time"
+)
+
+var (
+ breakpadTools = flag.String("breakpad-tools", "out/Release/", "Path to the Breakpad tools directory, containing dump_syms and symupload.")
+ uploadOnlyPath = flag.String("upload-from", "", "Upload a directory of symbol files that has been dumped independently.")
+ dumpOnlyPath = flag.String("dump-to", "", "Dump the symbols to the specified directory, but do not upload them.")
+ systemRoot = flag.String("system-root", "", "Path to the root of the Mac OS X system whose symbols will be dumped.")
+ dumpArchitecture = flag.String("arch", "", "The CPU architecture for which symbols should be dumped. If not specified, dumps all architectures.")
+)
+
+var (
+ // pathsToScan are the subpaths in the systemRoot that should be scanned for shared libraries.
+ pathsToScan = []string{
+ "/System/Library/Components",
+ "/System/Library/Frameworks",
+ "/System/Library/PrivateFrameworks",
+ "/usr/lib",
+ }
+
+ // optionalPathsToScan is just like pathsToScan, but the paths are permitted to be absent.
+ optionalPathsToScan = []string{
+ // Gone in 10.15.
+ "/Library/QuickTime",
+ }
+
+ // uploadServers are the list of servers to which symbols should be uploaded.
+ uploadServers = []string{
+ "https://clients2.google.com/cr/symbol",
+ "https://clients2.google.com/cr/staging_symbol",
+ }
+
+ // blacklistRegexps match paths that should be excluded from dumping.
+ blacklistRegexps = []*regexp.Regexp{
+ regexp.MustCompile(`/System/Library/Frameworks/Python\.framework/`),
+ regexp.MustCompile(`/System/Library/Frameworks/Ruby\.framework/`),
+ regexp.MustCompile(`_profile\.dylib$`),
+ regexp.MustCompile(`_debug\.dylib$`),
+ regexp.MustCompile(`\.a$`),
+ regexp.MustCompile(`\.dat$`),
+ }
+)
+
+func main() {
+ flag.Parse()
+ log.SetFlags(0)
+
+ var uq *UploadQueue
+
+ if *uploadOnlyPath != "" {
+ // -upload-from specified, so handle that case early.
+ uq = StartUploadQueue()
+ uploadFromDirectory(*uploadOnlyPath, uq)
+ uq.Wait()
+ return
+ }
+
+ if *systemRoot == "" {
+ log.Fatal("Need a -system-root to dump symbols for")
+ }
+
+ if *dumpOnlyPath != "" {
+ // -dump-to specified, so make sure that the path is a directory.
+ if fi, err := os.Stat(*dumpOnlyPath); err != nil {
+ log.Fatalf("-dump-to location: %v", err)
+ } else if !fi.IsDir() {
+ log.Fatal("-dump-to location is not a directory")
+ }
+ }
+
+ dumpPath := *dumpOnlyPath
+ if *dumpOnlyPath == "" {
+ // If -dump-to was not specified, then run the upload pipeline and create
+ // a temporary dump output directory.
+ uq = StartUploadQueue()
+
+ if p, err := ioutil.TempDir("", "upload_system_symbols"); err != nil {
+ log.Fatalf("Failed to create temporary directory: %v", err)
+ } else {
+ dumpPath = p
+ defer os.RemoveAll(p)
+ }
+ }
+
+ dq := StartDumpQueue(*systemRoot, dumpPath, uq)
+ dq.Wait()
+ if uq != nil {
+ uq.Wait()
+ }
+}
+
+type WorkerPool struct {
+ wg sync.WaitGroup
+}
+
+// StartWorkerPool will launch numWorkers goroutines all running workerFunc.
+// When workerFunc exits, the goroutine will terminate.
+func StartWorkerPool(numWorkers int, workerFunc func()) *WorkerPool {
+ p := new(WorkerPool)
+ for i := 0; i < numWorkers; i++ {
+ p.wg.Add(1)
+ go func() {
+ workerFunc()
+ p.wg.Done()
+ }()
+ }
+ return p
+}
+
+// Wait for all the workers in the pool to complete the workerFunc.
+func (p *WorkerPool) Wait() {
+ p.wg.Wait()
+}
+
+type UploadQueue struct {
+ *WorkerPool
+ queue chan string
+}
+
+// StartUploadQueue creates a new worker pool and queue, to which paths to
+// Breakpad symbol files may be sent for uploading.
+func StartUploadQueue() *UploadQueue {
+ uq := &UploadQueue{
+ queue: make(chan string, 10),
+ }
+ uq.WorkerPool = StartWorkerPool(5, uq.worker)
+ return uq
+}
+
+// Upload enqueues the contents of filepath to be uploaded.
+func (uq *UploadQueue) Upload(filepath string) {
+ uq.queue <- filepath
+}
+
+// Done tells the queue that no more files need to be uploaded. This must be
+// called before WorkerPool.Wait.
+func (uq *UploadQueue) Done() {
+ close(uq.queue)
+}
+
+func (uq *UploadQueue) worker() {
+ symUpload := path.Join(*breakpadTools, "symupload")
+
+ for symfile := range uq.queue {
+ for _, server := range uploadServers {
+ for i := 0; i < 3; i++ { // Give each upload 3 attempts to succeed.
+ cmd := exec.Command(symUpload, symfile, server)
+ if output, err := cmd.Output(); err == nil {
+ // Success. No retry needed.
+ fmt.Printf("Uploaded %s to %s\n", symfile, server)
+ break
+ } else {
+ log.Printf("Error running symupload(%s, %s), attempt %d: %v: %s\n", symfile, server, i, err, output)
+ time.Sleep(1 * time.Second)
+ }
+ }
+ }
+ }
+}
+
+type DumpQueue struct {
+ *WorkerPool
+ dumpPath string
+ queue chan dumpRequest
+ uq *UploadQueue
+}
+
+type dumpRequest struct {
+ path string
+ arch string
+}
+
+// StartDumpQueue creates a new worker pool to find all the Mach-O libraries in
+// root and dump their symbols to dumpPath. If an UploadQueue is passed, the
+// path to the symbol file will be enqueued there, too.
+func StartDumpQueue(root, dumpPath string, uq *UploadQueue) *DumpQueue {
+ dq := &DumpQueue{
+ dumpPath: dumpPath,
+ queue: make(chan dumpRequest),
+ uq: uq,
+ }
+ dq.WorkerPool = StartWorkerPool(12, dq.worker)
+
+ findLibsInRoot(root, dq)
+
+ return dq
+}
+
+// DumpSymbols enqueues the filepath to have its symbols dumped in the specified
+// architecture.
+func (dq *DumpQueue) DumpSymbols(filepath string, arch string) {
+ dq.queue <- dumpRequest{
+ path: filepath,
+ arch: arch,
+ }
+}
+
+func (dq *DumpQueue) Wait() {
+ dq.WorkerPool.Wait()
+ if dq.uq != nil {
+ dq.uq.Done()
+ }
+}
+
+func (dq *DumpQueue) done() {
+ close(dq.queue)
+}
+
+func (dq *DumpQueue) worker() {
+ dumpSyms := path.Join(*breakpadTools, "dump_syms")
+
+ for req := range dq.queue {
+ filebase := path.Join(dq.dumpPath, strings.Replace(req.path, "/", "_", -1))
+ symfile := fmt.Sprintf("%s_%s.sym", filebase, req.arch)
+ f, err := os.Create(symfile)
+ if err != nil {
+ log.Fatalf("Error creating symbol file: %v", err)
+ }
+
+ cmd := exec.Command(dumpSyms, "-a", req.arch, req.path)
+ cmd.Stdout = f
+ err = cmd.Run()
+ f.Close()
+
+ if err != nil {
+ os.Remove(symfile)
+ log.Printf("Error running dump_syms(%s, %s): %v\n", req.arch, req.path, err)
+ } else if dq.uq != nil {
+ dq.uq.Upload(symfile)
+ }
+ }
+}
+
+// uploadFromDirectory handles the upload-only case and merely uploads all files in
+// a directory.
+func uploadFromDirectory(directory string, uq *UploadQueue) {
+ d, err := os.Open(directory)
+ if err != nil {
+ log.Fatalf("Could not open directory to upload: %v", err)
+ }
+ defer d.Close()
+
+ entries, err := d.Readdirnames(0)
+ if err != nil {
+ log.Fatalf("Could not read directory: %v", err)
+ }
+
+ for _, entry := range entries {
+ uq.Upload(path.Join(directory, entry))
+ }
+
+ uq.Done()
+}
+
+// findQueue is an implementation detail of the DumpQueue that finds all the
+// Mach-O files and their architectures.
+type findQueue struct {
+ *WorkerPool
+ queue chan string
+ dq *DumpQueue
+}
+
+// findLibsInRoot looks in all the pathsToScan in the root and manages the
+// interaction between findQueue and DumpQueue.
+func findLibsInRoot(root string, dq *DumpQueue) {
+ fq := &findQueue{
+ queue: make(chan string, 10),
+ dq: dq,
+ }
+ fq.WorkerPool = StartWorkerPool(12, fq.worker)
+
+ for _, p := range pathsToScan {
+ fq.findLibsInPath(path.Join(root, p), true)
+ }
+
+ for _, p := range optionalPathsToScan {
+ fq.findLibsInPath(path.Join(root, p), false)
+ }
+
+ close(fq.queue)
+ fq.Wait()
+ dq.done()
+}
+
+// findLibsInPath recursively walks the directory tree, sending file paths to
+// test for being Mach-O to the findQueue.
+func (fq *findQueue) findLibsInPath(loc string, mustExist bool) {
+ d, err := os.Open(loc)
+ if err != nil {
+ if !mustExist && os.IsNotExist(err) {
+ return
+ }
+ log.Fatalf("Could not open %s: %v", loc, err)
+ }
+ defer d.Close()
+
+ for {
+ fis, err := d.Readdir(100)
+ if err != nil && err != io.EOF {
+ log.Fatalf("Error reading directory %s: %v", loc, err)
+ }
+
+ for _, fi := range fis {
+ fp := path.Join(loc, fi.Name())
+ if fi.IsDir() {
+ fq.findLibsInPath(fp, true)
+ continue
+ } else if fi.Mode()&os.ModeSymlink != 0 {
+ continue
+ }
+
+ // Test the blacklist in the worker to not slow down this main loop.
+
+ fq.queue <- fp
+ }
+
+ if err == io.EOF {
+ break
+ }
+ }
+}
+
+func (fq *findQueue) worker() {
+ for fp := range fq.queue {
+ blacklisted := false
+ for _, re := range blacklistRegexps {
+ blacklisted = blacklisted || re.MatchString(fp)
+ }
+ if blacklisted {
+ continue
+ }
+
+ f, err := os.Open(fp)
+ if err != nil {
+ log.Printf("%s: %v", fp, err)
+ continue
+ }
+
+ fatFile, err := macho.NewFatFile(f)
+ if err == nil {
+ // The file is fat, so dump its architectures.
+ for _, fatArch := range fatFile.Arches {
+ fq.dumpMachOFile(fp, fatArch.File)
+ }
+ fatFile.Close()
+ } else if err == macho.ErrNotFat {
+ // The file isn't fat but may still be MachO.
+ thinFile, err := macho.NewFile(f)
+ if err != nil {
+ log.Printf("%s: %v", fp, err)
+ continue
+ }
+ fq.dumpMachOFile(fp, thinFile)
+ thinFile.Close()
+ } else {
+ f.Close()
+ }
+ }
+}
+
+func (fq *findQueue) dumpMachOFile(fp string, image *macho.File) {
+ if image.Type != MachODylib && image.Type != MachOBundle && image.Type != MachODylinker {
+ return
+ }
+
+ arch := getArchStringFromHeader(image.FileHeader)
+ if arch == "" {
+ // Don't know about this architecture type.
+ return
+ }
+
+ if (*dumpArchitecture != "" && *dumpArchitecture == arch) || *dumpArchitecture == "" {
+ fq.dq.DumpSymbols(fp, arch)
+ }
+}
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/python/deps-to-manifest.py b/toolkit/crashreporter/google-breakpad/src/tools/python/deps-to-manifest.py
new file mode 100755
index 0000000000..b456285431
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/python/deps-to-manifest.py
@@ -0,0 +1,167 @@
+#!/usr/bin/python
+# Copyright 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.
+
+"""Convert gclient's DEPS file to repo's manifest xml file."""
+
+from __future__ import print_function
+
+import argparse
+import os
+import sys
+
+
+REMOTES = {
+ 'chromium': 'https://chromium.googlesource.com/',
+ 'github': 'https://github.com/',
+}
+REVIEWS = {
+ 'chromium': 'https://chromium-review.googlesource.com',
+}
+
+MANIFEST_HEAD = """<?xml version='1.0' encoding='UTF-8'?>
+<!-- AUTOGENERATED BY %(prog)s; DO NOT EDIT -->
+<manifest>
+
+ <default revision='refs/heads/master'
+ remote='chromium'
+ sync-c='true'
+ sync-j='8' />
+"""
+
+MANIFEST_REMOTE = """
+ <remote name='%(name)s'
+ fetch='%(fetch)s'
+ review='%(review)s' />
+"""
+
+MANIFEST_PROJECT = """
+ <project path='%(path)s'
+ name='%(name)s'
+ revision='%(revision)s'
+ remote='%(remote)s' />
+"""
+
+MANIFEST_TAIL = """
+</manifest>
+"""
+
+
+def ConvertDepsToManifest(deps, manifest):
+ """Convert the |deps| file to the |manifest|."""
+ # Load the DEPS file data.
+ ctx = {}
+ execfile(deps, ctx)
+
+ new_contents = ''
+
+ # Write out the common header.
+ data = {
+ 'prog': os.path.basename(__file__),
+ }
+ new_contents += MANIFEST_HEAD % data
+
+ # Write out the <remote> sections.
+ for name, fetch in REMOTES.items():
+ data = {
+ 'name': name,
+ 'fetch': fetch,
+ 'review': REVIEWS.get(name, ''),
+ }
+ new_contents += MANIFEST_REMOTE % data
+
+ # Write out the main repo itself.
+ data = {
+ 'path': 'src',
+ 'name': 'breakpad/breakpad',
+ 'revision': 'refs/heads/master',
+ 'remote': 'chromium',
+ }
+ new_contents += MANIFEST_PROJECT % data
+
+ # Write out the <project> sections.
+ for path, url in ctx['deps'].items():
+ for name, fetch in REMOTES.items():
+ if url.startswith(fetch):
+ remote = name
+ break
+ else:
+ raise ValueError('Unknown DEPS remote: %s: %s' % (path, url))
+
+ # The DEPS url will look like:
+ # https://chromium.googlesource.com/external/gyp/@e8ab0833a42691cd2
+ remote_path, rev = url.split('@')
+ remote_path = remote_path[len(fetch):]
+
+ # If it's not a revision, assume it's a tag. Repo wants full ref names.
+ if len(rev) != 40:
+ rev = 'refs/tags/%s' % rev
+
+ data = {
+ 'path': path,
+ 'name': remote_path,
+ 'revision': rev,
+ 'remote': remote,
+ }
+ new_contents += MANIFEST_PROJECT % data
+
+ # Write out the common footer.
+ new_contents += MANIFEST_TAIL
+
+ # See if the manifest has actually changed contents to avoid thrashing.
+ try:
+ old_contents = open(manifest).read()
+ except IOError:
+ # In case the file doesn't exist yet.
+ old_contents = ''
+ if old_contents != new_contents:
+ print('Updating %s due to changed %s' % (manifest, deps))
+ with open(manifest, 'w') as fp:
+ fp.write(new_contents)
+
+
+def GetParser():
+ """Return a CLI parser."""
+ parser = argparse.ArgumentParser(description=__doc__)
+ parser.add_argument('deps',
+ help='The DEPS file to convert')
+ parser.add_argument('manifest',
+ help='The manifest xml to generate')
+ return parser
+
+
+def main(argv):
+ """The main func!"""
+ parser = GetParser()
+ opts = parser.parse_args(argv)
+ ConvertDepsToManifest(opts.deps, opts.manifest)
+
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv[1:]))
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/python/filter_syms.py b/toolkit/crashreporter/google-breakpad/src/tools/python/filter_syms.py
new file mode 100644
index 0000000000..abddf7893e
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/python/filter_syms.py
@@ -0,0 +1,204 @@
+#!/usr/bin/env python
+# 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.
+
+"""Normalizes and de-duplicates paths within Breakpad symbol files.
+
+When using DWARF for storing debug symbols, some file information will be
+stored relative to the current working directory of the current compilation
+unit, and may be further relativized based upon how the file was #included.
+
+This helper can be used to parse the Breakpad symbol file generated from such
+DWARF files and normalize and de-duplicate the FILE records found within,
+updating any references to the FILE records in the other record types.
+"""
+
+import macpath
+import ntpath
+import optparse
+import os
+import posixpath
+import sys
+
+class BreakpadParseError(Exception):
+ """Unsupported Breakpad symbol record exception class."""
+ pass
+
+class SymbolFileParser(object):
+ """Parser for Breakpad symbol files.
+
+ The format of these files is documented at
+ https://chromium.googlesource.com/breakpad/breakpad/+/master/docs/symbol_files.md
+ """
+
+ def __init__(self, input_stream, output_stream, ignored_prefixes=None,
+ path_handler=os.path):
+ """Inits a SymbolFileParser to read symbol records from |input_stream| and
+ write the processed output to |output_stream|.
+
+ |ignored_prefixes| contains a list of optional path prefixes that
+ should be stripped from the final, normalized path outputs.
+
+ For example, if the Breakpad symbol file had all paths starting with a
+ common prefix, such as:
+ FILE 1 /b/build/src/foo.cc
+ FILE 2 /b/build/src/bar.cc
+ Then adding "/b/build/src" as an ignored prefix would result in an output
+ file that contained:
+ FILE 1 foo.cc
+ FILE 2 bar.cc
+
+ Note that |ignored_prefixes| does not necessarily contain file system
+ paths, as the contents of the DWARF DW_AT_comp_dir attribute is dependent
+ upon the host system and compiler, and may contain additional information
+ such as hostname or compiler version.
+ """
+
+ self.unique_files = {}
+ self.duplicate_files = {}
+ self.input_stream = input_stream
+ self.output_stream = output_stream
+ self.ignored_prefixes = ignored_prefixes or []
+ self.path_handler = path_handler
+
+ def Process(self):
+ """Processes the Breakpad symbol file."""
+ for line in self.input_stream:
+ parsed = self._ParseRecord(line.rstrip())
+ if parsed:
+ self.output_stream.write(parsed + '\n')
+
+ def _ParseRecord(self, record):
+ """Parses a single Breakpad symbol record - a single line from the symbol
+ file.
+
+ Returns:
+ The modified string to write to the output file, or None if no line
+ should be written.
+ """
+ record_type = record.partition(' ')[0]
+ if record_type == 'FILE':
+ return self._ParseFileRecord(record)
+ elif self._IsLineRecord(record_type):
+ return self._ParseLineRecord(record)
+ else:
+ # Simply pass the record through unaltered.
+ return record
+
+ def _NormalizePath(self, path):
+ """Normalizes a file path to its canonical form.
+
+ As this may not execute on the machine or file system originally
+ responsible for compilation, it may be necessary to further correct paths
+ for symlinks, junctions, or other such file system indirections.
+
+ Returns:
+ A unique, canonical representation for the the file path.
+ """
+ return self.path_handler.normpath(path)
+
+ def _AdjustPath(self, path):
+ """Adjusts the supplied path after performing path de-duplication.
+
+ This may be used to perform secondary adjustments, such as removing a
+ common prefix, such as "/D/build", or replacing the file system path with
+ information from the version control system.
+
+ Returns:
+ The actual path to use when writing the FILE record.
+ """
+ return path[len(filter(path.startswith,
+ self.ignored_prefixes + [''])[0]):]
+
+ def _ParseFileRecord(self, file_record):
+ """Parses and corrects a FILE record."""
+ file_info = file_record[5:].split(' ', 3)
+ if len(file_info) > 2:
+ raise BreakpadParseError('Unsupported FILE record: ' + file_record)
+ file_index = int(file_info[0])
+ file_name = self._NormalizePath(file_info[1])
+ existing_file_index = self.unique_files.get(file_name)
+ if existing_file_index is None:
+ self.unique_files[file_name] = file_index
+ file_info[1] = self._AdjustPath(file_name)
+ return 'FILE ' + ' '.join(file_info)
+ else:
+ self.duplicate_files[file_index] = existing_file_index
+ return None
+
+ def _IsLineRecord(self, record_type):
+ """Determines if the current record type is a Line record"""
+ try:
+ line = int(record_type, 16)
+ except (ValueError, TypeError):
+ return False
+ return True
+
+ def _ParseLineRecord(self, line_record):
+ """Parses and corrects a Line record."""
+ line_info = line_record.split(' ', 5)
+ if len(line_info) > 4:
+ raise BreakpadParseError('Unsupported Line record: ' + line_record)
+ file_index = int(line_info[3])
+ line_info[3] = str(self.duplicate_files.get(file_index, file_index))
+ return ' '.join(line_info)
+
+def main():
+ option_parser = optparse.OptionParser()
+ option_parser.add_option("-p", "--prefix",
+ action="append", dest="prefixes", type="string",
+ default=[],
+ help="A path prefix that should be removed from "
+ "all FILE lines. May be repeated to specify "
+ "multiple prefixes.")
+ option_parser.add_option("-t", "--path_type",
+ action="store", type="choice", dest="path_handler",
+ choices=['win32', 'posix'],
+ help="Indicates how file paths should be "
+ "interpreted. The default is to treat paths "
+ "the same as the OS running Python (eg: "
+ "os.path)")
+ options, args = option_parser.parse_args()
+ if args:
+ option_parser.error('Unknown argument: %s' % args)
+
+ path_handler = { 'win32': ntpath,
+ 'posix': posixpath }.get(options.path_handler, os.path)
+ try:
+ symbol_parser = SymbolFileParser(sys.stdin, sys.stdout, options.prefixes,
+ path_handler)
+ symbol_parser.Process()
+ except BreakpadParseError, e:
+ print >> sys.stderr, 'Got an error while processing symbol file'
+ print >> sys.stderr, str(e)
+ return 1
+ return 0
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/python/tests/filter_syms_unittest.py b/toolkit/crashreporter/google-breakpad/src/tools/python/tests/filter_syms_unittest.py
new file mode 100644
index 0000000000..b111f34983
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/python/tests/filter_syms_unittest.py
@@ -0,0 +1,138 @@
+#!/usr/bin/env python
+# 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.
+
+"""Unit tests for filter_syms.py"""
+
+import cStringIO
+import ntpath
+import os
+import StringIO
+import sys
+import unittest
+
+ROOT_DIR = os.path.dirname(os.path.abspath(__file__))
+sys.path.insert(0, os.path.join(ROOT_DIR, '..'))
+
+# In root
+import filter_syms
+
+class FilterSysmsTest(unittest.TestCase):
+ def assertParsed(self, input_data, ignored_prefixes, expected):
+ input_io = cStringIO.StringIO(input_data)
+ output_io = cStringIO.StringIO()
+ parser = filter_syms.SymbolFileParser(input_io, output_io,
+ ignored_prefixes, ntpath)
+ parser.Process()
+ self.assertEqual(output_io.getvalue(), expected)
+
+ def testDuplicateFiles(self):
+ """Tests that duplicate files in FILE records are correctly removed and
+ that Line records are updated."""
+
+ INPUT = \
+"""MODULE windows x86 111111111111111111111111111111111 module1.pdb
+INFO CODE_ID FFFFFFFF module1.exe
+FILE 1 foo/../file1_1.cc
+FILE 2 bar/../file1_1.cc
+FILE 3 baz/../file1_1.cc
+FUNC 1000 c 0 Function1_1
+1000 8 45 2
+1008 4 46 3
+100c 4 44 1
+"""
+ EXPECTED_OUTPUT = \
+"""MODULE windows x86 111111111111111111111111111111111 module1.pdb
+INFO CODE_ID FFFFFFFF module1.exe
+FILE 1 file1_1.cc
+FUNC 1000 c 0 Function1_1
+1000 8 45 1
+1008 4 46 1
+100c 4 44 1
+"""
+ self.assertParsed(INPUT, [], EXPECTED_OUTPUT)
+
+ def testIgnoredPrefix(self):
+ """Tests that prefixes in FILE records are correctly removed."""
+
+ INPUT = \
+"""MODULE windows x86 111111111111111111111111111111111 module1.pdb
+INFO CODE_ID FFFFFFFF module1.exe
+FILE 1 /src/build/foo/../file1_1.cc
+FILE 2 /src/build/bar/../file1_2.cc
+FILE 3 /src/build/baz/../file1_2.cc
+FUNC 1000 c 0 Function1_1
+1000 8 45 2
+1008 4 46 3
+100c 4 44 1
+"""
+ EXPECTED_OUTPUT = \
+"""MODULE windows x86 111111111111111111111111111111111 module1.pdb
+INFO CODE_ID FFFFFFFF module1.exe
+FILE 1 file1_1.cc
+FILE 2 file1_2.cc
+FUNC 1000 c 0 Function1_1
+1000 8 45 2
+1008 4 46 2
+100c 4 44 1
+"""
+ IGNORED_PREFIXES = ['\\src\\build\\']
+ self.assertParsed(INPUT, IGNORED_PREFIXES, EXPECTED_OUTPUT)
+
+ def testIgnoredPrefixesDuplicateFiles(self):
+ """Tests that de-duplication of FILE records happens BEFORE prefixes
+ are removed."""
+
+ INPUT = \
+"""MODULE windows x86 111111111111111111111111111111111 module1.pdb
+INFO CODE_ID FFFFFFFF module1.exe
+FILE 1 /src/build/foo/../file1_1.cc
+FILE 2 /src/build/bar/../file1_2.cc
+FILE 3 D:/src/build2/baz/../file1_2.cc
+FUNC 1000 c 0 Function1_1
+1000 8 45 2
+1008 4 46 3
+100c 4 44 1
+"""
+ EXPECTED_OUTPUT = \
+"""MODULE windows x86 111111111111111111111111111111111 module1.pdb
+INFO CODE_ID FFFFFFFF module1.exe
+FILE 1 file1_1.cc
+FILE 2 file1_2.cc
+FILE 3 file1_2.cc
+FUNC 1000 c 0 Function1_1
+1000 8 45 2
+1008 4 46 3
+100c 4 44 1
+"""
+ IGNORED_PREFIXES = ['\\src\\build\\', 'D:\\src\\build2\\']
+ self.assertParsed(INPUT, IGNORED_PREFIXES, EXPECTED_OUTPUT)
+
+if __name__ == '__main__':
+ unittest.main() \ No newline at end of file
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/solaris/dump_syms/Makefile b/toolkit/crashreporter/google-breakpad/src/tools/solaris/dump_syms/Makefile
new file mode 100644
index 0000000000..ff77105c61
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/solaris/dump_syms/Makefile
@@ -0,0 +1,64 @@
+# 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
+
+CXX=CC
+CC=cc
+
+CXXFLAGS=-g -xs -xdebugformat=stabs -I../../.. -I../../../common/solaris -lelf -ldemangle -D_REENTRANT
+
+.PHONY:all clean
+
+BIN=dump_syms
+
+all:$(BIN)
+
+DUMP_OBJ=dump_symbols.o guid_creator.o dump_syms.o file_id.o md5.o
+
+dump_syms:$(DUMP_OBJ)
+ $(CXX) $(CXXFLAGS) -o $@ $^
+
+dump_symbols.o:../../../common/solaris/dump_symbols.cc
+ $(CXX) $(CXXFLAGS) -c $^
+
+guid_creator.o:../../../common/solaris/guid_creator.cc
+ $(CXX) $(CXXFLAGS) -c $^
+
+file_id.o:../../../common/solaris/file_id.cc
+ $(CXX) $(CXXFLAGS) -c $^
+
+md5.o:../../../common/md5.cc
+ $(CXX) $(CXXFLAGS) -c $^
+
+test:all
+ ./run_regtest.sh
+
+clean:
+ rm -f $(BIN) $(DUMP_OBJ)
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/solaris/dump_syms/Makefile.in b/toolkit/crashreporter/google-breakpad/src/tools/solaris/dump_syms/Makefile.in
new file mode 100644
index 0000000000..7bef51e078
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/solaris/dump_syms/Makefile.in
@@ -0,0 +1,5 @@
+# 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/.
+
+HOST_LDFLAGS += -lelf -ldemangle
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/solaris/dump_syms/dump_syms.cc b/toolkit/crashreporter/google-breakpad/src/tools/solaris/dump_syms/dump_syms.cc
new file mode 100644
index 0000000000..54cea57e75
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/solaris/dump_syms/dump_syms.cc
@@ -0,0 +1,54 @@
+// 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 <string>
+#include <cstdio>
+
+#include "common/solaris/dump_symbols.h"
+
+using namespace google_breakpad;
+
+int main(int argc, char **argv) {
+ if (argc != 2) {
+ fprintf(stderr, "Usage: %s <binary-with-stab-symbol>\n", argv[0]);
+ return 1;
+ }
+
+ const char *binary = argv[1];
+
+ DumpSymbols dumper;
+ if (!dumper.WriteSymbolFile(binary, fileno(stdout))) {
+ fprintf(stderr, "Failed to write symbol file.\n");
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/solaris/dump_syms/run_regtest.sh b/toolkit/crashreporter/google-breakpad/src/tools/solaris/dump_syms/run_regtest.sh
new file mode 100644
index 0000000000..ffb3433067
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/solaris/dump_syms/run_regtest.sh
@@ -0,0 +1,51 @@
+#!/bin/sh
+
+# 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_syms testdata/dump_syms_regtest.o > testdata/dump_syms_regtest.new
+status=$?
+
+if [ $status -ne 0 ] ; then
+ echo "FAIL, dump_syms failed"
+ exit $status
+fi
+
+diff -u testdata/dump_syms_regtest.new testdata/dump_syms_regtest.sym > \
+ testdata/dump_syms_regtest.diff
+status=$?
+
+if [ $status -eq 0 ] ; then
+ rm testdata/dump_syms_regtest.diff testdata/dump_syms_regtest.new
+ echo "PASS"
+else
+ echo "FAIL, see testdata/dump_syms_regtest.[new|diff]"
+fi
+
+exit $status
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/solaris/dump_syms/testdata/dump_syms_regtest.cc b/toolkit/crashreporter/google-breakpad/src/tools/solaris/dump_syms/testdata/dump_syms_regtest.cc
new file mode 100644
index 0000000000..e617a23b81
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/solaris/dump_syms/testdata/dump_syms_regtest.cc
@@ -0,0 +1,64 @@
+// 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_syms dump_syms_regtest.pdb > dump_syms_regtest.sym
+
+namespace google_breakpad {
+
+class C {
+ public:
+ C() : member_(1) {}
+ virtual ~C() {}
+
+ void set_member(int value) { member_ = value; }
+ int member() const { return member_; }
+
+ void f() { member_ = g(); }
+ virtual int g() { return 2; }
+ static char* h(const C &that) { return 0; }
+
+ private:
+ int member_;
+};
+
+static int i() {
+ return 3;
+}
+
+} // namespace google_breakpad
+
+int main(int argc, char **argv) {
+ google_breakpad::C object;
+ object.set_member(google_breakpad::i());
+ object.f();
+ int value = object.g();
+ char *nothing = object.h(object);
+
+ return 0;
+}
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/solaris/dump_syms/testdata/dump_syms_regtest.o b/toolkit/crashreporter/google-breakpad/src/tools/solaris/dump_syms/testdata/dump_syms_regtest.o
new file mode 100644
index 0000000000..a1c61b2dfd
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/solaris/dump_syms/testdata/dump_syms_regtest.o
Binary files differ
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/solaris/dump_syms/testdata/dump_syms_regtest.stabs b/toolkit/crashreporter/google-breakpad/src/tools/solaris/dump_syms/testdata/dump_syms_regtest.stabs
new file mode 100644
index 0000000000..c5f93ef78c
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/solaris/dump_syms/testdata/dump_syms_regtest.stabs
@@ -0,0 +1,129 @@
+
+
+Debugging Stab table -- 104 entries
+
+ 0: .stabs "dump_syms_regtest.cc",N_UNDF,0x0,0x67,0x71c
+ 1: .stabs "/export/home/alfred/cvs/breakpad/google-breakpad20070927/src/tools/solaris/dump_syms/testdata/",N_SO,0x0,0x0,0x0
+ 2: .stabs "dump_syms_regtest.cc",N_SO,0x0,0x4,0x0
+ 3: .stabs "",N_OBJ,0x0,0x0,0x0
+ 4: .stabs "",N_OBJ,0x0,0x0,0x0
+ 5: .stabs "V=9.0;DBG_GEN=5.0.8;dm;cd;backend;ptf;ptx;ptk;s;g;R=5.8<<Sun C++ 5.8 Patch 121018-07 2006/11/01 (ccfe)>>;G=.XAB6Z2hOiL$Gl1b.;A=2",N_OPT,0x0,0x0,0x46fcb88e
+ 6: .stabs "dump_syms_regtest.cc",N_SOL,0x0,0x0,0x0
+ 7: .stabs "char:t(0,1)=bsc1;0;8",N_ISYM,0x0,0x0,0x0
+ 8: .stabs "short:t(0,2)=bs2;0;16",N_ISYM,0x0,0x0,0x0
+ 9: .stabs "int:t(0,3)=bs4;0;32",N_ISYM,0x0,0x0,0x0
+ 10: .stabs "long:t(0,4)=bs4;0;32",N_ISYM,0x0,0x0,0x0
+ 11: .stabs "long long:t(0,5)=bs8;0;64",N_ISYM,0x0,0x0,0x0
+ 12: .stabs "unsigned char:t(0,6)=buc1;0;8",N_ISYM,0x0,0x0,0x0
+ 13: .stabs "unsigned short:t(0,7)=bu2;0;16",N_ISYM,0x0,0x0,0x0
+ 14: .stabs "unsigned:t(0,8)=bu4;0;32",N_ISYM,0x0,0x0,0x0
+ 15: .stabs "unsigned long:t(0,9)=bu4;0;32",N_ISYM,0x0,0x0,0x0
+ 16: .stabs "unsigned long long:t(0,10)=bu8;0;64",N_ISYM,0x0,0x0,0x0
+ 17: .stabs "signed char:t(0,11)=bsc1;0;8",N_ISYM,0x0,0x0,0x0
+ 18: .stabs "wchar_t:t(0,12)=buc4;0;32",N_ISYM,0x0,0x0,0x0
+ 19: .stabs "void:t(0,13)=bs0;0;0",N_ISYM,0x0,0x0,0x0
+ 20: .stabs "float:t(0,14)=R1;4",N_ISYM,0x0,0x0,0x0
+ 21: .stabs "double:t(0,15)=R2;8",N_ISYM,0x0,0x0,0x0
+ 22: .stabs "long double:t(0,16)=R6;12",N_ISYM,0x0,0x0,0x0
+ 23: .stabs "...:t(0,17)=buv4;0;32",N_ISYM,0x0,0x0,0x0
+ 24: .stabs "bool:t(0,18)=bub1;0;8",N_ISYM,0x0,0x0,0x0
+ 25: .stabs "__1nPgoogle_breakpad_:T(0,19)=Yn0google_breakpad;",N_ISYM,0x0,0x0,0x0
+ 26: .stabs "nBC(0,19):U(0,20)",N_ESYM,0x0,0x0,0x0
+ 27: .stabs "nBC(0,19):T(0,20)=Yc8C;;AcHmember_:(0,3),32,32;;Cc2t6M_v K2c2T6M_v CcKset_member6Mi_v CcGmember6kM_i CcBf6M_v K3cBg6M_i GcBh6Frk1_pc;;;2 0;;;;110;",N_ESYM,0x0,0x8,0x0
+ 28: .stabs "main:F(0,3);(0,3);(0,21)=*(0,22)=*(0,1)",N_FUN,0x0,0x38,0x0
+ 29: .stabs "main",N_MAIN,0x0,0x0,0x0
+ 30: .stabs "argc:p(0,3)",N_PSYM,0x0,0x4,0x8
+ 31: .stabs "argv:p(0,21)",N_PSYM,0x0,0x4,0xc
+ 32: .stabn N_LBRAC,0x0,0x1,0x12
+ 33: .stabs "object:(0,20)",N_LSYM,0x0,0x8,0xfffffff4
+ 34: .stabs "value:(0,3)",N_LSYM,0x0,0x4,0xfffffff0
+ 35: .stabs "nothing:(0,22)",N_LSYM,0x0,0x4,0xffffffec
+ 36: .stabn N_SLINE,0x0,0x39,0x12
+ 37: .stabs "object:2",N_CONSTRUCT,0x0,0xc,0x12
+ 38: .stabn N_SLINE,0x2,0x3a,0x1e
+ 39: .stabn N_SLINE,0x0,0x3b,0x36
+ 40: .stabn N_SLINE,0x0,0x3c,0x42
+ 41: .stabn N_SLINE,0x0,0x3d,0x57
+ 42: .stabn N_SLINE,0x0,0x3f,0x6c
+ 43: .stabs "2:0",N_DESTRUCT,0x0,0xc,0x73
+ 44: .stabn N_SLINE,0xfffffffe,0x40,0x9c
+ 45: .stabn N_RBRAC,0x0,0x1,0x9c
+ 46: .stabs "__1cPgoogle_breakpadBi6F_i_:f(0,3)",N_FUN,0x0,0x32,0x0
+ 47: .stabn N_LBRAC,0x0,0x1,0x6
+ 48: .stabn N_SLINE,0x0,0x33,0x6
+ 49: .stabn N_SLINE,0x0,0x34,0x10
+ 50: .stabn N_RBRAC,0x0,0x1,0x10
+ 51: .stabs "__1cPgoogle_breakpadBC2t6M_v_:F(0,13);(0,23)=*(0,20)",N_FUN,0x0,0x24,0x0
+ 52: .stabs "this:p(0,23)",N_PSYM,0x0,0x4,0x8
+ 53: .stabn N_LBRAC,0x0,0x1,0x3
+ 54: .stabn N_SLINE,0x0,0x24,0x25
+ 55: .stabn N_RBRAC,0x0,0x1,0x25
+ 56: .stabs "__1cPgoogle_breakpadBC2T6M_v_:F(0,13);(0,23)",N_FUN,0x0,0x25,0x0
+ 57: .stabs "this:p(0,23)",N_PSYM,0x0,0x4,0x8
+ 58: .stabn N_LBRAC,0x0,0x1,0x3
+ 59: .stabn N_SLINE,0x0,0x25,0x3
+ 60: .stabn N_RBRAC,0x0,0x1,0x3
+ 61: .stabs "__1cPgoogle_breakpadBCKset_member6Mi_v_:F(0,13);(0,23);(0,3)",N_FUN,0x0,0x27,0x0
+ 62: .stabs "this:p(0,23)",N_PSYM,0x0,0x4,0x8
+ 63: .stabs "value:p(0,3)",N_PSYM,0x0,0x4,0xc
+ 64: .stabn N_LBRAC,0x0,0x1,0x3
+ 65: .stabn N_SLINE,0x0,0x27,0x3
+ 66: .stabn N_SLINE,0x0,0x27,0xc
+ 67: .stabn N_RBRAC,0x0,0x1,0xc
+ 68: .stabs "__1cPgoogle_breakpadBCBf6M_v_:F(0,13);(0,23)",N_FUN,0x0,0x2a,0x0
+ 69: .stabs "this:p(0,23)",N_PSYM,0x0,0x4,0x8
+ 70: .stabn N_LBRAC,0x0,0x1,0x3
+ 71: .stabn N_SLINE,0x0,0x2a,0x3
+ 72: .stabn N_SLINE,0x0,0x2a,0x1d
+ 73: .stabn N_RBRAC,0x0,0x1,0x1d
+ 74: .stabs "__1cPgoogle_breakpadBCBg6M_i_:F(0,3);(0,23)",N_FUN,0x0,0x2b,0x0
+ 75: .stabs "this:p(0,23)",N_PSYM,0x0,0x4,0x8
+ 76: .stabn N_LBRAC,0x0,0x1,0x6
+ 77: .stabn N_SLINE,0x0,0x2b,0x6
+ 78: .stabn N_SLINE,0x0,0x2b,0x10
+ 79: .stabn N_RBRAC,0x0,0x1,0x10
+ 80: .stabs "__1cPgoogle_breakpadBCBh6Frk1_pc_:F(0,22);(0,24)=&(0,25)=k(0,20)",N_FUN,0x0,0x2c,0x0
+ 81: .stabs "that:p(0,24)",N_PSYM,0x0,0x4,0x8
+ 82: .stabn N_LBRAC,0x0,0x1,0x6
+ 83: .stabn N_SLINE,0x0,0x2c,0x6
+ 84: .stabn N_SLINE,0x0,0x2c,0x10
+ 85: .stabn N_RBRAC,0x0,0x1,0x10
+ 86: .stabs "__1cPgoogle_breakpadBC2T5B6M_v_:F(0,13);(0,23)",N_FUN,0x0,0x25,0x0
+ 87: .stabs "this:p(0,23)",N_PSYM,0x0,0x4,0x8
+ 88: .stabn N_LBRAC,0x0,0x1,0x3
+ 89: .stabn N_SLINE,0x0,0x25,0xf
+ 90: .stabn N_RBRAC,0x0,0x1,0xf
+ 91: .stabs "__SLIP.DELETER__A:f(0,13);(0,23);(0,3)",N_FUN,0x0,0x25,0x0
+ 92: .stabs "this:p(0,23)",N_PSYM,0x0,0x4,0x8
+ 93: .stabs "delete:p(0,3)",N_PSYM,0x0,0x4,0xc
+ 94: .stabn N_LBRAC,0x0,0x1,0x3
+ 95: .stabn N_LBRAC,0x0,0x2,0x3
+ 96: .stabn N_RBRAC,0x0,0x2,0x28
+ 97: .stabn N_RBRAC,0x0,0x1,0x28
+ 98: .stabs "true:l(0,18);1",N_LSYM,0x0,0x4,0x0
+ 99: .stabs "false:l(0,18);0",N_LSYM,0x0,0x4,0x0
+ 100: .stabs "__1c2k6Fpv_v_:P(0,13);(0,26)=*(0,13)",N_FUN,0x0,0x0,0x0
+ 101: .stabs "__1cPgoogle_breakpadBC2t5B6M_v_:F__1cPgoogle_breakpadBC2t6M_v_",N_ALIAS,0x0,0x0,0x0
+ 102: .stabs "cbD__RTTI__1nPgoogle_breakpadBC_(0,19):YR(0,20)",N_LSYM,0x0,0x0,0x0
+ 103: .stabn N_ENDM,0x0,0x0,0x0
+
+
+Index Stab table -- 17 entries
+
+ 0: .stabs "dump_syms_regtest.cc",N_UNDF,0x0,0x10,0x3b1
+ 1: .stabs "/export/home/alfred/cvs/breakpad/google-breakpad20070927/src/tools/solaris/dump_syms/testdata/",N_SO,0x0,0x0,0x0
+ 2: .stabs "dump_syms_regtest.cc",N_SO,0x0,0x4,0x0
+ 3: .stabs "/export/home/alfred/cvs/breakpad/google-breakpad20070927/src/tools/solaris/dump_syms/testdata",N_OBJ,0x0,0x0,0x0
+ 4: .stabs "dump_syms_regtest.o",N_OBJ,0x0,0x0,0x0
+ 5: .stabs "V=9.0;DBG_GEN=5.0.8;dm;cd;backend;ptf;ptx;ptk;s;g;R=5.8<<Sun C++ 5.8 Patch 121018-07 2006/11/01 (ccfe)>>;G=.XAB6Z2hOiL$Gl1b.;A=2",N_OPT,0x0,0x0,0x46fcb88e
+ 6: .stabs "/export/home/alfred/cvs/breakpad/google-breakpad20070927/src/tools/solaris/dump_syms/testdata/; /ws/on10-tools-prc/SUNWspro/SS11/prod/bin/CC -g -xs -xdebugformat=stabs -I../../.. -I../../../common/solaris -D_REENTRANT -xs dump_syms_regtest.cc -Qoption ccfe -prefix -Qoption ccfe .XAB6Z2hOiL\$Gl1b.",N_CMDLINE,0x0,0x0,0x0
+ 7: .stabs "__1nPgoogle_breakpadBC_:U",N_ESYM,0x0,0x0,0x0
+ 8: .stabs "main",N_MAIN,0x0,0x0,0x0
+ 9: .stabs "main",N_FUN,0x0,0x0,0x0
+ 10: .stabs "__1cPgoogle_breakpadBC2t6M_v_",N_FUN,0x0,0x0,0x0
+ 11: .stabs "__1cPgoogle_breakpadBC2T6M_v_",N_FUN,0x0,0x0,0x0
+ 12: .stabs "__1cPgoogle_breakpadBCKset_member6Mi_v_",N_FUN,0x0,0x0,0x0
+ 13: .stabs "__1cPgoogle_breakpadBCBf6M_v_",N_FUN,0x0,0x0,0x0
+ 14: .stabs "__1cPgoogle_breakpadBCBg6M_i_",N_FUN,0x0,0x0,0x0
+ 15: .stabs "__1cPgoogle_breakpadBCBh6Frk1_pc_",N_FUN,0x0,0x0,0x0
+ 16: .stabs "__1cPgoogle_breakpadBC2T5B6M_v_",N_FUN,0x0,0x0,0x0
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/solaris/dump_syms/testdata/dump_syms_regtest.sym b/toolkit/crashreporter/google-breakpad/src/tools/solaris/dump_syms/testdata/dump_syms_regtest.sym
new file mode 100644
index 0000000000..44d3c5391c
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/solaris/dump_syms/testdata/dump_syms_regtest.sym
@@ -0,0 +1,33 @@
+MODULE solaris x86 3DC8191474338D8587339B5FB3E2C62A0 dump_syms_regtest.o
+FILE 0 dump_syms_regtest.cc
+FUNC 0 156 0 main
+12 18 57 0
+1e 12 58 0
+36 24 59 0
+42 12 60 0
+57 21 61 0
+6c 21 63 0
+9c 48 64 0
+FUNC 0 16 0 int google_breakpad::i()
+6 6 51 0
+10 10 52 0
+FUNC 0 37 0 google_breakpad::C::C()
+25 37 36 0
+FUNC 0 3 0 google_breakpad::C::~C()
+3 3 37 0
+FUNC 0 12 0 void google_breakpad::C::set_member(int)
+3 3 39 0
+c 9 39 0
+FUNC 0 29 0 void google_breakpad::C::f()
+3 3 42 0
+1d 26 42 0
+FUNC 0 16 0 int google_breakpad::C::g()
+6 6 43 0
+10 10 43 0
+FUNC 0 16 0 char*google_breakpad::C::h(const google_breakpad::C&)
+6 6 44 0
+10 10 44 0
+FUNC 0 15 0 google_breakpad::C::~C #Nvariant 1()
+f 15 37 0
+FUNC 0 0 0 __SLIP.DELETER__A
+FUNC 0 0 0 void operator delete(void*)
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/tools.gyp b/toolkit/crashreporter/google-breakpad/src/tools/tools.gyp
new file mode 100644
index 0000000000..e6a4210fec
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/tools.gyp
@@ -0,0 +1,38 @@
+# 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.
+
+{
+ 'conditions': [
+ ['OS=="mac"', {
+ 'includes': ['mac/tools_mac.gypi'],
+ }],
+ ['OS=="linux"', {
+ 'includes': ['linux/tools_linux.gypi'],
+ }],
+ ],
+}
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/windows/binaries/dump_syms.exe b/toolkit/crashreporter/google-breakpad/src/tools/windows/binaries/dump_syms.exe
new file mode 100644
index 0000000000..3a2dfd8e50
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/windows/binaries/dump_syms.exe
Binary files differ
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/windows/binaries/symupload.exe b/toolkit/crashreporter/google-breakpad/src/tools/windows/binaries/symupload.exe
new file mode 100644
index 0000000000..09d2a55b5c
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/windows/binaries/symupload.exe
Binary files differ
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/windows/converter/ms_symbol_server_converter.cc b/toolkit/crashreporter/google-breakpad/src/tools/windows/converter/ms_symbol_server_converter.cc
new file mode 100644
index 0000000000..2b40faeeb5
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/windows/converter/ms_symbol_server_converter.cc
@@ -0,0 +1,752 @@
+// Copyright (c) 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// ms_symbol_server_converter.cc: Obtain symbol files from a Microsoft
+// symbol server, and convert them to Breakpad's dumped format.
+//
+// See ms_symbol_server_converter.h for documentation.
+//
+// Author: Mark Mentovai
+
+#include <windows.h>
+#include <dbghelp.h>
+#include <pathcch.h>
+
+#include <cassert>
+#include <cstdio>
+
+#include "tools/windows/converter/ms_symbol_server_converter.h"
+#include "common/windows/pdb_source_line_writer.h"
+#include "common/windows/pe_source_line_writer.h"
+#include "common/windows/string_utils-inl.h"
+
+// SYMOPT_NO_PROMPTS is not defined in earlier platform SDKs. Define it
+// in that case, in the event that this code is used with a newer version
+// of DbgHelp at runtime that recognizes the option. The presence of this
+// bit in the symbol options should not harm earlier versions of DbgHelp.
+#ifndef SYMOPT_NO_PROMPTS
+#define SYMOPT_NO_PROMPTS 0x00080000
+#endif // SYMOPT_NO_PROMPTS
+
+namespace {
+
+std::wstring GetExeDirectory() {
+ wchar_t directory[MAX_PATH];
+
+ // Get path to this process exe.
+ DWORD result = GetModuleFileName(/*hModule=*/nullptr, directory, MAX_PATH);
+ if (result <= 0 || result == MAX_PATH) {
+ fprintf(stderr,
+ "GetExeDirectory: failed to get path to process exe.\n");
+ return L"";
+ }
+ HRESULT hr = PathCchRemoveFileSpec(directory, result + 1);
+ if (hr != S_OK) {
+ fprintf(stderr,
+ "GetExeDirectory: failed to remove basename from path '%ls'.\n",
+ directory);
+ return L"";
+ }
+
+ return std::wstring(directory);
+}
+
+} // namespace
+
+namespace google_breakpad {
+
+// Use sscanf_s if it is available, to quench the warning about scanf being
+// deprecated. Use scanf where sscanf_is not available. Note that the
+// parameters passed to sscanf and sscanf_s are only compatible as long as
+// fields of type c, C, s, S, and [ are not used.
+#if _MSC_VER >= 1400 // MSVC 2005/8
+#define SSCANF sscanf_s
+#else // _MSC_VER >= 1400
+#define SSCANF sscanf
+#endif // _MSC_VER >= 1400
+
+bool GUIDOrSignatureIdentifier::InitializeFromString(
+ const string &identifier) {
+ type_ = TYPE_NONE;
+
+ size_t length = identifier.length();
+
+ if (length > 32 && length <= 40) {
+ // GUID
+ if (SSCANF(identifier.c_str(),
+ "%08X%04hX%04hX%02hhX%02hhX%02hhX%02hhX%02hhX%02hhX%02hhX%02hhX%X",
+ &guid_.Data1, &guid_.Data2, &guid_.Data3,
+ &guid_.Data4[0], &guid_.Data4[1],
+ &guid_.Data4[2], &guid_.Data4[3],
+ &guid_.Data4[4], &guid_.Data4[5],
+ &guid_.Data4[6], &guid_.Data4[7],
+ &age_) != 12) {
+ return false;
+ }
+
+ type_ = TYPE_GUID;
+ } else if (length > 8 && length <= 15) {
+ // Signature
+ if (SSCANF(identifier.c_str(), "%08X%x", &signature_, &age_) != 2) {
+ return false;
+ }
+
+ type_ = TYPE_SIGNATURE;
+ } else {
+ return false;
+ }
+
+ return true;
+}
+
+#undef SSCANF
+
+MSSymbolServerConverter::MSSymbolServerConverter(
+ const string &local_cache, const vector<string> &symbol_servers)
+ : symbol_path_(),
+ fail_dns_(false),
+ fail_timeout_(false),
+ fail_not_found_(false) {
+ // Setting local_cache can be done without verifying that it exists because
+ // SymSrv will create it if it is missing - any creation failures will occur
+ // at that time, so there's nothing to check here, making it safe to
+ // assign this in the constructor.
+
+ assert(symbol_servers.size() > 0);
+
+#if !defined(NDEBUG)
+ // These are characters that are interpreted as having special meanings in
+ // symbol_path_.
+ const char kInvalidCharacters[] = "*;";
+ assert(local_cache.find_first_of(kInvalidCharacters) == string::npos);
+#endif // !defined(NDEBUG)
+
+ for (vector<string>::const_iterator symbol_server = symbol_servers.begin();
+ symbol_server != symbol_servers.end();
+ ++symbol_server) {
+ // The symbol path format is explained by
+ // http://msdn.microsoft.com/library/en-us/debug/base/using_symsrv.asp .
+ // "srv*" is the same as "symsrv*symsrv.dll*", which means that
+ // symsrv.dll is to be responsible for locating symbols. symsrv.dll
+ // interprets the rest of the string as a series of symbol stores separated
+ // by '*'. "srv*local_cache*symbol_server" means to check local_cache
+ // first for the symbol file, and if it is not found there, to check
+ // symbol_server. Symbol files found on the symbol server will be placed
+ // in the local cache, decompressed.
+ //
+ // Multiple specifications in this format may be presented, separated by
+ // semicolons.
+
+ assert((*symbol_server).find_first_of(kInvalidCharacters) == string::npos);
+ symbol_path_ += "srv*" + local_cache + "*" + *symbol_server + ";";
+ }
+
+ // Strip the trailing semicolon.
+ symbol_path_.erase(symbol_path_.length() - 1);
+}
+
+// A stack-based class that manages SymInitialize and SymCleanup calls.
+class AutoSymSrv {
+ public:
+ AutoSymSrv() : initialized_(false) {}
+
+ ~AutoSymSrv() {
+ if (!Cleanup()) {
+ // Print the error message here, because destructors have no return
+ // value.
+ fprintf(stderr, "~AutoSymSrv: SymCleanup: error %lu\n", GetLastError());
+ }
+ }
+
+ bool Initialize(HANDLE process, char *path, bool invade_process) {
+ process_ = process;
+
+ // TODO(nbilling): Figure out why dbghelp.dll is being loaded from
+ // system32/SysWOW64 before exe folder.
+
+ // Attempt to locate and load dbghelp.dll beside the process exe. This is
+ // somewhat of a workaround to loader delay load behavior that is occurring
+ // when we call into symsrv APIs. dbghelp.dll must be loaded from beside
+ // the process exe so that we are guaranteed to find symsrv.dll alongside
+ // dbghelp.dll (a security requirement of dbghelp.dll) and so that the
+ // symsrv.dll file that is loaded has a symsrv.yes file alongside it (a
+ // requirement of symsrv.dll when accessing Microsoft-owned symbol
+ // servers).
+ // 'static local' because we don't care about the value but we need the
+ // initialization to happen exactly once.
+ static HMODULE dbghelp_module = [] () -> HMODULE {
+ std::wstring exe_directory = GetExeDirectory();
+ if (exe_directory.empty()) {
+ return nullptr;
+ }
+ std::wstring dbghelp_path = exe_directory + L"\\dbghelp.dll";
+ return LoadLibrary(dbghelp_path.c_str());
+ }();
+ if (dbghelp_module == nullptr) {
+ fprintf(stderr,
+ "AutoSymSrv::Initialize: failed to load dbghelp.dll beside exe.");
+ return false;
+ }
+
+ initialized_ = SymInitialize(process, path, invade_process) == TRUE;
+ return initialized_;
+ }
+
+ bool Cleanup() {
+ if (initialized_) {
+ if (SymCleanup(process_)) {
+ initialized_ = false;
+ return true;
+ }
+ return false;
+ }
+
+ return true;
+ }
+
+ private:
+ HANDLE process_;
+ bool initialized_;
+};
+
+// A stack-based class that "owns" a pathname and deletes it when destroyed,
+// unless told not to by having its Release() method called. Early deletions
+// are supported by calling Delete().
+class AutoDeleter {
+ public:
+ explicit AutoDeleter(const string &path) : path_(path) {}
+
+ ~AutoDeleter() {
+ int error;
+ if ((error = Delete()) != 0) {
+ // Print the error message here, because destructors have no return
+ // value.
+ fprintf(stderr, "~AutoDeleter: Delete: error %d for %s\n",
+ error, path_.c_str());
+ }
+ }
+
+ int Delete() {
+ if (path_.empty())
+ return 0;
+
+ int error = remove(path_.c_str());
+ Release();
+ return error;
+ }
+
+ void Release() {
+ path_.clear();
+ }
+
+ private:
+ string path_;
+};
+
+MSSymbolServerConverter::LocateResult
+MSSymbolServerConverter::LocateFile(const string &debug_or_code_file,
+ const string &debug_or_code_id,
+ const string &version,
+ string *file_name) {
+ assert(file_name);
+ file_name->clear();
+
+ GUIDOrSignatureIdentifier identifier;
+ if (!identifier.InitializeFromString(debug_or_code_id)) {
+ fprintf(stderr,
+ "LocateFile: Unparseable identifier for %s %s %s\n",
+ debug_or_code_file.c_str(),
+ debug_or_code_id.c_str(),
+ version.c_str());
+ return LOCATE_FAILURE;
+ }
+
+ HANDLE process = GetCurrentProcess(); // CloseHandle is not needed.
+ AutoSymSrv symsrv;
+ if (!symsrv.Initialize(process,
+ const_cast<char *>(symbol_path_.c_str()),
+ false)) {
+ fprintf(stderr, "LocateFile: SymInitialize: error %lu for %s %s %s\n",
+ GetLastError(),
+ debug_or_code_file.c_str(),
+ debug_or_code_id.c_str(),
+ version.c_str());
+ return LOCATE_FAILURE;
+ }
+
+ if (!SymRegisterCallback64(process, SymCallback,
+ reinterpret_cast<ULONG64>(this))) {
+ fprintf(stderr,
+ "LocateFile: SymRegisterCallback64: error %lu for %s %s %s\n",
+ GetLastError(),
+ debug_or_code_file.c_str(),
+ debug_or_code_id.c_str(),
+ version.c_str());
+ return LOCATE_FAILURE;
+ }
+
+ // SYMOPT_DEBUG arranges for SymCallback to be called with additional
+ // debugging information. This is used to determine the nature of failures.
+ DWORD options = SymGetOptions() | SYMOPT_DEBUG | SYMOPT_NO_PROMPTS |
+ SYMOPT_FAIL_CRITICAL_ERRORS | SYMOPT_SECURE;
+ SymSetOptions(options);
+
+ // SymCallback will set these as needed inisde the SymFindFileInPath call.
+ fail_dns_ = false;
+ fail_timeout_ = false;
+ fail_not_found_ = false;
+
+ // Do the lookup.
+ char path[MAX_PATH];
+ if (!SymFindFileInPath(
+ process, NULL,
+ const_cast<char *>(debug_or_code_file.c_str()),
+ const_cast<void *>(identifier.guid_or_signature_pointer()),
+ identifier.age(), 0,
+ identifier.type() == GUIDOrSignatureIdentifier::TYPE_GUID ?
+ SSRVOPT_GUIDPTR : SSRVOPT_DWORDPTR,
+ path, SymFindFileInPathCallback, this)) {
+ DWORD error = GetLastError();
+ if (error == ERROR_FILE_NOT_FOUND) {
+ // This can be returned for a number of reasons. Use the crumbs
+ // collected by SymCallback to determine which one is relevant.
+
+ // These errors are possibly transient.
+ if (fail_dns_ || fail_timeout_) {
+ return LOCATE_RETRY;
+ }
+
+ // This is an authoritiative file-not-found message.
+ if (fail_not_found_) {
+ fprintf(stderr,
+ "LocateFile: SymFindFileInPath: LOCATE_NOT_FOUND error "
+ "for %s %s %s\n",
+ debug_or_code_file.c_str(),
+ debug_or_code_id.c_str(),
+ version.c_str());
+ return LOCATE_NOT_FOUND;
+ }
+
+ // If the error is FILE_NOT_FOUND but none of the known error
+ // conditions are matched, fall through to LOCATE_FAILURE.
+ }
+
+ fprintf(stderr,
+ "LocateFile: SymFindFileInPath: error %lu for %s %s %s\n",
+ error,
+ debug_or_code_file.c_str(),
+ debug_or_code_id.c_str(),
+ version.c_str());
+ return LOCATE_FAILURE;
+ }
+
+ // Making sure path is null-terminated.
+ path[MAX_PATH - 1] = '\0';
+
+ // The AutoDeleter ensures that the file is only kept when returning
+ // LOCATE_SUCCESS.
+ AutoDeleter deleter(path);
+
+ // Do the cleanup here even though it will happen when symsrv goes out of
+ // scope, to allow it to influence the return value.
+ if (!symsrv.Cleanup()) {
+ fprintf(stderr, "LocateFile: SymCleanup: error %lu for %s %s %s\n",
+ GetLastError(),
+ debug_or_code_file.c_str(),
+ debug_or_code_id.c_str(),
+ version.c_str());
+ return LOCATE_FAILURE;
+ }
+
+ deleter.Release();
+
+ printf("Downloaded: %s\n", path);
+ *file_name = path;
+ return LOCATE_SUCCESS;
+}
+
+
+MSSymbolServerConverter::LocateResult
+MSSymbolServerConverter::LocatePEFile(const MissingSymbolInfo &missing,
+ string *pe_file) {
+ return LocateFile(missing.code_file, missing.code_identifier,
+ missing.version, pe_file);
+}
+
+MSSymbolServerConverter::LocateResult
+MSSymbolServerConverter::LocateSymbolFile(const MissingSymbolInfo &missing,
+ string *symbol_file) {
+ return LocateFile(missing.debug_file, missing.debug_identifier,
+ missing.version, symbol_file);
+}
+
+
+// static
+BOOL CALLBACK MSSymbolServerConverter::SymCallback(HANDLE process,
+ ULONG action,
+ ULONG64 data,
+ ULONG64 context) {
+ MSSymbolServerConverter *self =
+ reinterpret_cast<MSSymbolServerConverter *>(context);
+
+ switch (action) {
+ case CBA_EVENT: {
+ IMAGEHLP_CBA_EVENT *cba_event =
+ reinterpret_cast<IMAGEHLP_CBA_EVENT *>(data);
+
+ // Put the string into a string object to be able to use string::find
+ // for substring matching. This is important because the not-found
+ // message does not use the entire string but is appended to the URL
+ // that SymSrv attempted to retrieve.
+ string desc(cba_event->desc);
+
+ // desc_action maps strings (in desc) to boolean pointers that are to
+ // be set to true if the string matches.
+ struct desc_action {
+ const char *desc; // The substring to match.
+ bool *action; // On match, this pointer will be set to true.
+ };
+
+ static const desc_action desc_actions[] = {
+ // When a DNS error occurs, it could be indiciative of network
+ // problems.
+ { "SYMSRV: The server name or address could not be resolved\n",
+ &self->fail_dns_ },
+
+ // This message is produced if no connection is opened.
+ { "SYMSRV: A connection with the server could not be established\n",
+ &self->fail_timeout_ },
+
+ // This message is produced if a connection is established but the
+ // server fails to respond to the HTTP request.
+ { "SYMSRV: The operation timed out\n",
+ &self->fail_timeout_ },
+
+ // This message is produced when the requested file is not found,
+ // even if one or more of the above messages are also produced.
+ // It's trapped to distinguish between not-found and unknown-failure
+ // conditions. Note that this message will not be produced if a
+ // connection is established and the server begins to respond to the
+ // HTTP request but does not finish transmitting the file.
+ { " not found\n",
+ &self->fail_not_found_ }
+ };
+
+ for (int desc_action_index = 0;
+ desc_action_index <
+ static_cast<int>(sizeof(desc_actions) / sizeof(desc_action));
+ ++desc_action_index) {
+ if (desc.find(desc_actions[desc_action_index].desc) != string::npos) {
+ *(desc_actions[desc_action_index].action) = true;
+ break;
+ }
+ }
+
+ break;
+ }
+ }
+
+ // This function is a mere fly on the wall. Treat everything as unhandled.
+ return FALSE;
+}
+
+// static
+BOOL CALLBACK MSSymbolServerConverter::SymFindFileInPathCallback(
+ const char *filename, void *context) {
+ // FALSE ends the search, indicating that the located symbol file is
+ // satisfactory.
+ return FALSE;
+}
+
+MSSymbolServerConverter::LocateResult
+MSSymbolServerConverter::LocateAndConvertSymbolFile(
+ const MissingSymbolInfo &missing,
+ bool keep_symbol_file,
+ bool keep_pe_file,
+ string *converted_symbol_file,
+ string *symbol_file,
+ string *out_pe_file) {
+ assert(converted_symbol_file);
+ converted_symbol_file->clear();
+ if (symbol_file) {
+ symbol_file->clear();
+ }
+
+ string pdb_file;
+ LocateResult result = LocateSymbolFile(missing, &pdb_file);
+ if (result != LOCATE_SUCCESS) {
+ fprintf(stderr, "Fallback to PE-only symbol generation for: %s\n",
+ missing.debug_file.c_str());
+ return LocateAndConvertPEFile(missing, keep_pe_file, converted_symbol_file,
+ out_pe_file);
+ }
+
+ if (symbol_file && keep_symbol_file) {
+ *symbol_file = pdb_file;
+ }
+
+ // The conversion of a symbol file for a Windows 64-bit module requires
+ // loading of the executable file. If there is no executable file, convert
+ // using only the PDB file. Without an executable file, the conversion will
+ // fail for 64-bit modules but it should succeed for 32-bit modules.
+ string pe_file;
+ result = LocatePEFile(missing, &pe_file);
+ if (result != LOCATE_SUCCESS) {
+ fprintf(stderr, "WARNING: Could not download: %s\n", pe_file.c_str());
+ }
+
+ if (out_pe_file && keep_pe_file) {
+ *out_pe_file = pe_file;
+ }
+
+ // Conversion may fail because the file is corrupt. If a broken file is
+ // kept in the local cache, LocateSymbolFile will not hit the network again
+ // to attempt to locate it. To guard against problems like this, the
+ // symbol file in the local cache will be removed if conversion fails.
+ AutoDeleter pdb_deleter(pdb_file);
+ AutoDeleter pe_deleter(pe_file);
+
+ // Be sure that it's a .pdb file, since we'll be replacing .pdb with .sym
+ // for the converted file's name.
+ string pdb_extension = pdb_file.substr(pdb_file.length() - 4);
+ // strcasecmp is called _stricmp here.
+ if (_stricmp(pdb_extension.c_str(), ".pdb") != 0) {
+ fprintf(stderr, "LocateAndConvertSymbolFile: "
+ "no .pdb extension for %s %s %s %s\n",
+ missing.debug_file.c_str(),
+ missing.debug_identifier.c_str(),
+ missing.version.c_str(),
+ pdb_file.c_str());
+ return LOCATE_FAILURE;
+ }
+
+ PDBSourceLineWriter writer;
+ wstring pe_file_w;
+ if (!WindowsStringUtils::safe_mbstowcs(pe_file, &pe_file_w)) {
+ fprintf(stderr,
+ "LocateAndConvertSymbolFile: "
+ "WindowsStringUtils::safe_mbstowcs failed for %s\n",
+ pe_file.c_str());
+ return LOCATE_FAILURE;
+ }
+ wstring pdb_file_w;
+ if (!WindowsStringUtils::safe_mbstowcs(pdb_file, &pdb_file_w)) {
+ fprintf(stderr,
+ "LocateAndConvertSymbolFile: "
+ "WindowsStringUtils::safe_mbstowcs failed for %ws\n",
+ pdb_file_w.c_str());
+ return LOCATE_FAILURE;
+ }
+ if (!writer.Open(pdb_file_w, PDBSourceLineWriter::PDB_FILE)) {
+ fprintf(stderr,
+ "ERROR: PDBSourceLineWriter::Open failed for %s %s %s %ws\n",
+ missing.debug_file.c_str(), missing.debug_identifier.c_str(),
+ missing.version.c_str(), pdb_file_w.c_str());
+ return LOCATE_FAILURE;
+ }
+ if (!writer.SetCodeFile(pe_file_w)) {
+ fprintf(stderr,
+ "ERROR: PDBSourceLineWriter::SetCodeFile failed for %s %s %s %ws\n",
+ missing.debug_file.c_str(), missing.debug_identifier.c_str(),
+ missing.version.c_str(), pe_file_w.c_str());
+ return LOCATE_FAILURE;
+ }
+
+ *converted_symbol_file = pdb_file.substr(0, pdb_file.length() - 4) + ".sym";
+
+ FILE *converted_output = NULL;
+#if _MSC_VER >= 1400 // MSVC 2005/8
+ errno_t err;
+ if ((err = fopen_s(&converted_output, converted_symbol_file->c_str(), "w"))
+ != 0) {
+#else // _MSC_VER >= 1400
+ // fopen_s and errno_t were introduced in MSVC8. Use fopen for earlier
+ // environments. Don't use fopen with MSVC8 and later, because it's
+ // deprecated. fopen does not provide reliable error codes, so just use
+ // -1 in the event of a failure.
+ int err;
+ if (!(converted_output = fopen(converted_symbol_file->c_str(), "w"))) {
+ err = -1;
+#endif // _MSC_VER >= 1400
+ fprintf(stderr, "LocateAndConvertSymbolFile: "
+ "fopen_s: error %d for %s %s %s %s\n",
+ err,
+ missing.debug_file.c_str(),
+ missing.debug_identifier.c_str(),
+ missing.version.c_str(),
+ converted_symbol_file->c_str());
+ return LOCATE_FAILURE;
+ }
+
+ AutoDeleter sym_deleter(*converted_symbol_file);
+
+ bool success = writer.WriteSymbols(converted_output);
+ fclose(converted_output);
+
+ if (!success) {
+ fprintf(stderr, "LocateAndConvertSymbolFile: "
+ "PDBSourceLineWriter::WriteMap failed for %s %s %s %s\n",
+ missing.debug_file.c_str(),
+ missing.debug_identifier.c_str(),
+ missing.version.c_str(),
+ pdb_file.c_str());
+ return LOCATE_FAILURE;
+ }
+
+ if (keep_symbol_file) {
+ pdb_deleter.Release();
+ }
+
+ if (keep_pe_file) {
+ pe_deleter.Release();
+ }
+
+ sym_deleter.Release();
+
+ return LOCATE_SUCCESS;
+}
+
+MSSymbolServerConverter::LocateResult
+MSSymbolServerConverter::LocateAndConvertPEFile(
+ const MissingSymbolInfo &missing,
+ bool keep_pe_file,
+ string *converted_symbol_file,
+ string *out_pe_file) {
+ assert(converted_symbol_file);
+ converted_symbol_file->clear();
+
+ string pe_file;
+ MSSymbolServerConverter::LocateResult result = LocatePEFile(missing,
+ &pe_file);
+ if (result != LOCATE_SUCCESS) {
+ fprintf(stderr, "WARNING: Could not download: %s\n", pe_file.c_str());
+ return result;
+ }
+
+ if (out_pe_file && keep_pe_file) {
+ *out_pe_file = pe_file;
+ }
+
+ // Conversion may fail because the file is corrupt. If a broken file is
+ // kept in the local cache, LocatePEFile will not hit the network again
+ // to attempt to locate it. To guard against problems like this, the
+ // PE file in the local cache will be removed if conversion fails.
+ AutoDeleter pe_deleter(pe_file);
+
+ // Be sure that it's a .exe or .dll file, since we'll be replacing extension
+ // with .sym for the converted file's name.
+ string pe_extension = pe_file.substr(pe_file.length() - 4);
+ // strcasecmp is called _stricmp here.
+ if (_stricmp(pe_extension.c_str(), ".exe") != 0 &&
+ _stricmp(pe_extension.c_str(), ".dll") != 0) {
+ fprintf(stderr, "LocateAndConvertPEFile: "
+ "no .dll/.exe extension for %s %s %s %s\n",
+ missing.debug_file.c_str(),
+ missing.debug_identifier.c_str(),
+ missing.version.c_str(),
+ pe_file.c_str());
+ return LOCATE_FAILURE;
+ }
+
+ *converted_symbol_file = pe_file.substr(0, pe_file.length() - 4) + ".sym";
+
+ FILE *converted_output = NULL;
+#if _MSC_VER >= 1400 // MSVC 2005/8
+ errno_t err;
+ if ((err = fopen_s(&converted_output, converted_symbol_file->c_str(), "w"))
+ != 0) {
+#else // _MSC_VER >= 1400
+ // fopen_s and errno_t were introduced in MSVC8. Use fopen for earlier
+ // environments. Don't use fopen with MSVC8 and later, because it's
+ // deprecated. fopen does not provide reliable error codes, so just use
+ // -1 in the event of a failure.
+ int err;
+ if (!(converted_output = fopen(converted_symbol_file->c_str(), "w"))) {
+ err = -1;
+#endif // _MSC_VER >= 1400
+ fprintf(stderr, "LocateAndConvertPEFile: "
+ "fopen_s: error %d for %s %s %s %s\n",
+ err,
+ missing.debug_file.c_str(),
+ missing.debug_identifier.c_str(),
+ missing.version.c_str(),
+ converted_symbol_file->c_str());
+ return LOCATE_FAILURE;
+ }
+ AutoDeleter sym_deleter(*converted_symbol_file);
+
+ wstring pe_file_w;
+ if (!WindowsStringUtils::safe_mbstowcs(pe_file, &pe_file_w)) {
+ fprintf(stderr,
+ "LocateAndConvertPEFile: "
+ "WindowsStringUtils::safe_mbstowcs failed for %s\n",
+ pe_file.c_str());
+ return LOCATE_FAILURE;
+ }
+ PESourceLineWriter writer(pe_file_w);
+ PDBModuleInfo module_info;
+ if (!writer.GetModuleInfo(&module_info)) {
+ fprintf(stderr, "LocateAndConvertPEFile: "
+ "PESourceLineWriter::GetModuleInfo failed for %s %s %s %s\n",
+ missing.debug_file.c_str(),
+ missing.debug_identifier.c_str(),
+ missing.version.c_str(),
+ pe_file.c_str());
+ return LOCATE_FAILURE;
+ }
+ if (module_info.cpu.compare(L"x86_64") != 0) {
+ // This module is not x64 so we cannot generate Breakpad symbols from the
+ // PE alone. Don't delete PE-- no need to retry download.
+ pe_deleter.Release();
+ return LOCATE_FAILURE;
+ }
+
+ bool success = writer.WriteSymbols(converted_output);
+ fclose(converted_output);
+
+ if (!success) {
+ fprintf(stderr, "LocateAndConvertPEFile: "
+ "PESourceLineWriter::WriteMap failed for %s %s %s %s\n",
+ missing.debug_file.c_str(),
+ missing.debug_identifier.c_str(),
+ missing.version.c_str(),
+ pe_file.c_str());
+ return LOCATE_FAILURE;
+ }
+
+ if (keep_pe_file) {
+ pe_deleter.Release();
+ }
+
+ sym_deleter.Release();
+
+ return LOCATE_SUCCESS;
+}
+
+} // namespace google_breakpad
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/windows/converter/ms_symbol_server_converter.gyp b/toolkit/crashreporter/google-breakpad/src/tools/windows/converter/ms_symbol_server_converter.gyp
new file mode 100644
index 0000000000..57ec790686
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/windows/converter/ms_symbol_server_converter.gyp
@@ -0,0 +1,46 @@
+# Copyright 2013 Google Inc. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+{
+ 'includes': [
+ '../../../build/common.gypi',
+ ],
+ 'targets': [
+ {
+ 'target_name': 'ms_symbol_server_converter',
+ 'type': 'static_library',
+ 'msvs_guid': '1463C4CD-23FC-4DE9-BFDE-283338200157',
+ 'sources': [
+ 'ms_symbol_server_converter.cc',
+ ],
+ 'dependencies': [
+ '../../../common/windows/common_windows.gyp:common_windows_lib',
+ ],
+ },
+ ],
+}
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/windows/converter/ms_symbol_server_converter.h b/toolkit/crashreporter/google-breakpad/src/tools/windows/converter/ms_symbol_server_converter.h
new file mode 100644
index 0000000000..401f7c3443
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/windows/converter/ms_symbol_server_converter.h
@@ -0,0 +1,235 @@
+// Copyright (c) 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// ms_symbol_server_converter.h: Obtain symbol files from a Microsoft
+// symbol server, and convert them to Breakpad's dumped format.
+//
+// At runtime, MSSymbolServerConverter and code that it calls depend on being
+// able to locate suitable versions of dbghelp.dll and symsrv.dll. For best
+// results, place these files in the same directory as the executable.
+// dbghelp.dll and symsrv.dll as supplied with Debugging Tools for Windows are
+// both redistributable, as indicated by the package's redist.txt file.
+//
+// When connecting to Microsoft's symbol server at
+// http://msdl.microsoft.com/download/symbols/, which provides access to
+// symbols for the operating system itself, symsrv.dll requires agreement to
+// Microsoft's "Terms of Use for Microsoft Symbols and Binaries." Because this
+// library places the symbol engine into a promptless mode, the dialog with the
+// terms will not appear, and use of Microsoft's symbol server will not be
+// possible. To indicate agreement to the terms, create a file called
+// symsrv.yes in the same directory as symsrv.dll. (Note that symsrv.dll will
+// also recognize a symsrv.no file as indicating that you do not accept the
+// terms; the .yes file takes priority over the .no file.) The terms of use
+// are contained within symsrv.dll; they were formerly available online at
+// http://www.microsoft.com/whdc/devtools/debugging/symsrvTOU2.mspx , but
+// do not appear to be available online any longer as of January, 2007. It is
+// possible to view the terms from within WinDbg (Debugging Tools for Windows)
+// by removing any symsrv.yes and symsrv.no files from WinDbg's directory,
+// setting the symbol path to include Microsoft's symbol server (.sympath), and
+// attempting to load symbols from their server (.reload).
+//
+// This code has been tested with dbghelp.dll 6.5.3.7 and symsrv.dll 6.5.3.8,
+// included with Microsoft Visual Studio 8 in Common7/IDE. This has also been
+// tested with dbghelp.dll and symsrv.dll versions 6.6.7.5 and 6.12.2.633,
+// included with the same versions of Debugging Tools for Windows, available at
+// http://www.microsoft.com/whdc/devtools/debugging/ .
+//
+// Author: Mark Mentovai
+
+#ifndef TOOLS_WINDOWS_MS_SYMBOL_SERVER_CONVERTER_H_
+#define TOOLS_WINDOWS_MS_SYMBOL_SERVER_CONVERTER_H_
+
+#include <windows.h>
+
+#include <string>
+#include <vector>
+
+namespace google_breakpad {
+
+using std::string;
+using std::vector;
+
+// MissingSymbolInfo contains the subset of the information in the processor's
+// CodeModule structure relevant to obtaining a missing symbol file. Only
+// debug_file and debug_identifier are relevant in actually obtaining the
+// missing file; the other fields are for convenience.
+struct MissingSymbolInfo {
+ string code_file;
+ string code_identifier;
+ string debug_file;
+ string debug_identifier;
+ string version;
+};
+
+class GUIDOrSignatureIdentifier {
+ public:
+ enum GUIDOrSignatureType {
+ TYPE_NONE = 0,
+ TYPE_GUID,
+ TYPE_SIGNATURE
+ };
+
+ GUIDOrSignatureIdentifier() : type_(TYPE_NONE) {}
+
+ // Converts |identifier|, a debug_identifier-formatted string, into its
+ // component fields: either a GUID and age, or signature and age. If
+ // successful, sets the relevant fields in the object, including the type
+ // field, and returns true. On error, returns false.
+ bool InitializeFromString(const string &identifier);
+
+ GUIDOrSignatureType type() const { return type_; }
+ GUID guid() const { return guid_; }
+ DWORD signature() const { return signature_; }
+ int age() const { return age_; }
+ const void *guid_or_signature_pointer() const { return &guid_; }
+
+ private:
+ GUIDOrSignatureType type_;
+
+ // An identifier contains either a 128-bit uuid or a 32-bit signature.
+ union {
+ GUID guid_;
+ DWORD signature_;
+ };
+
+ // All identifiers used here have age fields, which indicate a specific
+ // revision given a uuid or signature.
+ int age_;
+};
+
+class MSSymbolServerConverter {
+ public:
+ enum LocateResult {
+ LOCATE_FAILURE = 0,
+ LOCATE_NOT_FOUND, // Authoritative: the file is not present.
+ LOCATE_RETRY, // Transient (network?) error, try again later.
+ LOCATE_SUCCESS
+ };
+
+ // Create a new object. local_cache is the location (pathname) of a local
+ // symbol store used to hold downloaded and converted symbol files. This
+ // directory will be created by LocateSymbolFile when it successfully
+ // retrieves a symbol file. symbol_servers contains a list of locations (URLs
+ // or pathnames) of the upstream symbol server stores, given in order of
+ // preference, with the first string in the vector identifying the first
+ // store to try. The vector must contain at least one string. None of the
+ // strings passed to this constructor may contain asterisk ('*') or semicolon
+ // (';') characters, as the symbol engine uses these characters as separators.
+ MSSymbolServerConverter(const string &local_cache,
+ const vector<string> &symbol_servers);
+
+ // Locates the PE file (DLL or EXE) specified by the identifying information
+ // in |missing|, by checking the symbol stores identified when the object
+ // was created. When returning LOCATE_SUCCESS, pe_file is set to
+ // the pathname of the decompressed PE file as it is stored in the
+ // local cache.
+ LocateResult LocatePEFile(const MissingSymbolInfo &missing, string *pe_file);
+
+ // Locates the symbol file specified by the identifying information in
+ // |missing|, by checking the symbol stores identified when the object
+ // was created. When returning LOCATE_SUCCESS, symbol_file is set to
+ // the pathname of the decompressed symbol file as it is stored in the
+ // local cache.
+ LocateResult LocateSymbolFile(const MissingSymbolInfo &missing,
+ string *symbol_file);
+
+ // Calls LocateSymbolFile and converts the returned symbol file to the
+ // dumped-symbol format, storing it adjacent to the symbol file. The
+ // only conversion supported is from pdb files. Returns the return
+ // value of LocateSymbolFile, or if LocateSymbolFile succeeds but
+ // conversion fails, returns LOCATE_FAILURE. The pathname to the
+ // pdb file and to the converted symbol file are returned in
+ // |converted_symbol_file|, |symbol_file|, and |pe_file|. |symbol_file| and
+ // |pe_file| are optional and may be NULL. If only the converted symbol file
+ // is desired, set |keep_symbol_file| and |keep_pe_file| to false to indicate
+ // that the original symbol file (pdb) and executable file (exe, dll) should
+ // be deleted after conversion.
+ LocateResult LocateAndConvertSymbolFile(const MissingSymbolInfo &missing,
+ bool keep_symbol_file,
+ bool keep_pe_file,
+ string *converted_symbol_file,
+ string *symbol_file,
+ string *pe_file);
+
+ // Calls LocatePEFile and converts the returned PE file to the
+ // dumped-symbol format, storing it adjacent to the PE file. The
+ // only conversion supported is from PE files. Returns the return
+ // value of LocatePEFile, or if LocatePEFile succeeds but
+ // conversion fails, returns LOCATE_FAILURE. The pathname to the
+ // PE file and to the converted symbol file are returned in
+ // |converted_symbol_file| and |pe_file|. |pe_file| is optional and may be
+ // NULL. If only the converted symbol file is desired, set |keep_pe_file|
+ // to false to indicate that the executable file (exe, dll) should be deleted
+ // after conversion.
+ // NOTE: Currrently only supports x64 PEs.
+ LocateResult LocateAndConvertPEFile(const MissingSymbolInfo &missing,
+ bool keep_pe_file,
+ string *converted_symbol_file,
+ string *pe_file);
+
+ private:
+ // Locates the PDB or PE file (DLL or EXE) specified by the identifying
+ // information in |debug_or_code_file| and |debug_or_code_id|, by checking
+ // the symbol stores identified when the object was created. When
+ // returning LOCATE_SUCCESS, file_name is set to the pathname of the
+ // decompressed PDB or PE file file as it is stored in the local cache.
+ LocateResult LocateFile(const string &debug_or_code_file,
+ const string &debug_or_code_id,
+ const string &version, string *file_name);
+
+ // Called by various SymSrv functions to report status as progress is made
+ // and to allow the callback to influence processing. Messages sent to this
+ // callback can be used to distinguish between the various failure modes
+ // that SymFindFileInPath might encounter.
+ static BOOL CALLBACK SymCallback(HANDLE process, ULONG action, ULONG64 data,
+ ULONG64 context);
+
+ // Called by SymFindFileInPath (in LocateSymbolFile) after a candidate
+ // symbol file is located, when it's present in the local cache.
+ // SymFindFileInPath actually seems to accept NULL for a callback function
+ // and behave properly for our needs in that case, but the documentation
+ // doesn't mention it, so this little callback is provided.
+ static BOOL CALLBACK SymFindFileInPathCallback(const char *filename,
+ void *context);
+
+ // The search path used by SymSrv, built based on the arguments to the
+ // constructor.
+ string symbol_path_;
+
+ // SymCallback will set at least one of these failure variables if
+ // SymFindFileInPath fails for an expected reason.
+ bool fail_dns_; // DNS failures (fail_not_found_ will also be set).
+ bool fail_timeout_; // Timeouts (fail_not_found_ will also be set).
+ bool fail_not_found_; // The file could not be found. If this is the only
+ // fail_* member set, then it is authoritative.
+};
+
+} // namespace google_breakpad
+
+#endif // TOOLS_WINDOWS_MS_SYMBOL_SERVER_CONVERTER_H_
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/windows/converter/ms_symbol_server_converter.vcproj b/toolkit/crashreporter/google-breakpad/src/tools/windows/converter/ms_symbol_server_converter.vcproj
new file mode 100644
index 0000000000..ee1263a147
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/windows/converter/ms_symbol_server_converter.vcproj
@@ -0,0 +1,368 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Purify|Win32">
+ <Configuration>Purify</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Purify|x64">
+ <Configuration>Purify</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{1463C4CD-23FC-4DE9-BFDE-283338200157}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>ms_symbol_server_converter</RootNamespace>
+ <IgnoreWarnCompileDuplicatedFilename>true</IgnoreWarnCompileDuplicatedFilename>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props"/>
+ <PropertyGroup Label="Configuration">
+ <CharacterSet>Unicode</CharacterSet>
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props"/>
+ <ImportGroup Label="ExtensionSettings"/>
+ <ImportGroup Label="PropertySheets">
+ <Import Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props"/>
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros"/>
+ <PropertyGroup>
+ <ExecutablePath>$(ExecutablePath);$(MSBuildProjectDirectory)\..\..\..\third_party\cygwin\bin\;$(MSBuildProjectDirectory)\..\..\..\third_party\python_26\</ExecutablePath>
+ <OutDir>$(SolutionDir)$(Configuration)\</OutDir>
+ <IntDir>$(OutDir)obj\$(ProjectName)\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Purify|Win32'">false</LinkIncremental>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Purify|x64'">false</LinkIncremental>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</LinkIncremental>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</LinkIncremental>
+ <TargetName>$(ProjectName)</TargetName>
+ <TargetPath>$(OutDir)lib\$(ProjectName)$(TargetExt)</TargetPath>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <AdditionalIncludeDirectories>..\..\..;$(VSInstallDir)\DIA SDK\include;..\..\..\third_party\platformsdk_win7\files\Include;$(VSInstallDir)\VC\atlmfc\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AdditionalOptions>/MP %(AdditionalOptions)</AdditionalOptions>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <BufferSecurityCheck>true</BufferSecurityCheck>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <DisableSpecificWarnings>4100;4127;4396;4503;4512;4819;4995;4702;4800;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ <ExceptionHandling>false</ExceptionHandling>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <MinimalRebuild>false</MinimalRebuild>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>_DEBUG;_WIN32_WINNT=0x0600;WINVER=0x0600;WIN32;_WINDOWS;_HAS_EXCEPTIONS=0;NOMINMAX;_CRT_RAND_S;CERT_CHAIN_PARA_HAS_EXTRA_FIELDS;WIN32_LEAN_AND_MEAN;_SECURE_ATL;CHROMIUM_BUILD;TOOLKIT_VIEWS=1;ENABLE_GPU=1;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+ <RuntimeTypeInfo>false</RuntimeTypeInfo>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <WarningLevel>Level4</WarningLevel>
+ </ClCompile>
+ <Lib>
+ <AdditionalLibraryDirectories>../../../third_party/platformsdk_win7/files/Lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalOptions>/ignore:4221 %(AdditionalOptions)</AdditionalOptions>
+ <OutputFile>$(OutDir)lib\$(ProjectName)$(TargetExt)</OutputFile>
+ </Lib>
+ <Link>
+ <AdditionalDependencies>wininet.lib;version.lib;msimg32.lib;ws2_32.lib;usp10.lib;psapi.lib;dbghelp.lib;$(VSInstallDir)\DIA SDK\lib\diaguids.lib;imagehlp.lib</AdditionalDependencies>
+ <AdditionalLibraryDirectories>../../../third_party/platformsdk_win7/files/Lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalOptions>/safeseh /dynamicbase /ignore:4199 /ignore:4221 /nxcompat %(AdditionalOptions)</AdditionalOptions>
+ <DelayLoadDLLs>dbghelp.dll;dwmapi.dll;uxtheme.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
+ <FixedBaseAddress>false</FixedBaseAddress>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ImportLibrary>$(OutDir)lib\$(TargetName).lib</ImportLibrary>
+ <MapFileName>$(OutDir)$(TargetName).map</MapFileName>
+ <SubSystem>Console</SubSystem>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Link>
+ <Midl>
+ <DllDataFileName>dlldata.c</DllDataFileName>
+ <GenerateStublessProxies>true</GenerateStublessProxies>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <OutputDirectory>$(IntDir)</OutputDirectory>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ </Midl>
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>../../..;..\..\..;$(VSInstallDir)\DIA SDK\include;..\..\..\third_party\platformsdk_win7\files\Include;$(VSInstallDir)\VC\atlmfc\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <Culture>0x0409</Culture>
+ <PreprocessorDefinitions>_DEBUG;_WIN32_WINNT=0x0600;WINVER=0x0600;WIN32;_WINDOWS;_HAS_EXCEPTIONS=0;NOMINMAX;_CRT_RAND_S;CERT_CHAIN_PARA_HAS_EXTRA_FIELDS;WIN32_LEAN_AND_MEAN;_SECURE_ATL;CHROMIUM_BUILD;TOOLKIT_VIEWS=1;ENABLE_GPU=1;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ResourceCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <AdditionalIncludeDirectories>..\..\..;$(VSInstallDir)\DIA SDK\include;..\..\..\third_party\platformsdk_win7\files\Include;$(VSInstallDir)\VC\atlmfc\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AdditionalOptions>/MP %(AdditionalOptions)</AdditionalOptions>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <BufferSecurityCheck>true</BufferSecurityCheck>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <DisableSpecificWarnings>4100;4127;4396;4503;4512;4819;4995;4702;4800;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ <ExceptionHandling>false</ExceptionHandling>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <MinimalRebuild>false</MinimalRebuild>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>_DEBUG;_WIN32_WINNT=0x0600;WINVER=0x0600;WIN32;_WINDOWS;_HAS_EXCEPTIONS=0;NOMINMAX;_CRT_RAND_S;CERT_CHAIN_PARA_HAS_EXTRA_FIELDS;WIN32_LEAN_AND_MEAN;_SECURE_ATL;CHROMIUM_BUILD;TOOLKIT_VIEWS=1;ENABLE_GPU=1;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;NO_TCMALLOC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+ <RuntimeTypeInfo>false</RuntimeTypeInfo>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <WarningLevel>Level4</WarningLevel>
+ </ClCompile>
+ <Lib>
+ <AdditionalLibraryDirectories>../../../third_party/platformsdk_win7/files/Lib/x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalOptions>/ignore:4221 %(AdditionalOptions)</AdditionalOptions>
+ <OutputFile>$(OutDir)lib\$(ProjectName)$(TargetExt)</OutputFile>
+ </Lib>
+ <Link>
+ <AdditionalDependencies>wininet.lib;version.lib;msimg32.lib;ws2_32.lib;usp10.lib;psapi.lib;dbghelp.lib;$(VSInstallDir)\DIA SDK\lib\diaguids.lib;imagehlp.lib</AdditionalDependencies>
+ <AdditionalLibraryDirectories>../../../third_party/platformsdk_win7/files/Lib/x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalOptions>/dynamicbase /ignore:4199 /ignore:4221 /nxcompat %(AdditionalOptions)</AdditionalOptions>
+ <DelayLoadDLLs>dbghelp.dll;dwmapi.dll;uxtheme.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
+ <FixedBaseAddress>false</FixedBaseAddress>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ImportLibrary>$(OutDir)lib\$(TargetName).lib</ImportLibrary>
+ <MapFileName>$(OutDir)$(TargetName).map</MapFileName>
+ <SubSystem>Console</SubSystem>
+ <TargetMachine>MachineX64</TargetMachine>
+ </Link>
+ <Midl>
+ <DllDataFileName>dlldata.c</DllDataFileName>
+ <GenerateStublessProxies>true</GenerateStublessProxies>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <OutputDirectory>$(IntDir)</OutputDirectory>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ </Midl>
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>../../..;..\..\..;$(VSInstallDir)\DIA SDK\include;..\..\..\third_party\platformsdk_win7\files\Include;$(VSInstallDir)\VC\atlmfc\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <Culture>0x0409</Culture>
+ <PreprocessorDefinitions>_DEBUG;_WIN32_WINNT=0x0600;WINVER=0x0600;WIN32;_WINDOWS;_HAS_EXCEPTIONS=0;NOMINMAX;_CRT_RAND_S;CERT_CHAIN_PARA_HAS_EXTRA_FIELDS;WIN32_LEAN_AND_MEAN;_SECURE_ATL;CHROMIUM_BUILD;TOOLKIT_VIEWS=1;ENABLE_GPU=1;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;NO_TCMALLOC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ResourceCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Purify|Win32'">
+ <ClCompile>
+ <AdditionalIncludeDirectories>..\..\..;$(VSInstallDir)\DIA SDK\include;..\..\..\third_party\platformsdk_win7\files\Include;$(VSInstallDir)\VC\atlmfc\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AdditionalOptions>/MP %(AdditionalOptions)</AdditionalOptions>
+ <BufferSecurityCheck>true</BufferSecurityCheck>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <DisableSpecificWarnings>4100;4127;4396;4503;4512;4819;4995;4702;4800;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ <ExceptionHandling>false</ExceptionHandling>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <MinimalRebuild>false</MinimalRebuild>
+ <Optimization>MaxSpeed</Optimization>
+ <PreprocessorDefinitions>_WIN32_WINNT=0x0600;WINVER=0x0600;WIN32;_WINDOWS;_HAS_EXCEPTIONS=0;NOMINMAX;_CRT_RAND_S;CERT_CHAIN_PARA_HAS_EXTRA_FIELDS;WIN32_LEAN_AND_MEAN;_SECURE_ATL;CHROMIUM_BUILD;TOOLKIT_VIEWS=1;ENABLE_GPU=1;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;NDEBUG;NVALGRIND;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ <RuntimeTypeInfo>false</RuntimeTypeInfo>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <WarningLevel>Level4</WarningLevel>
+ </ClCompile>
+ <Lib>
+ <AdditionalLibraryDirectories>../../../third_party/platformsdk_win7/files/Lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalOptions>/ignore:4221 %(AdditionalOptions)</AdditionalOptions>
+ <OutputFile>$(OutDir)lib\$(ProjectName)$(TargetExt)</OutputFile>
+ </Lib>
+ <Link>
+ <AdditionalDependencies>wininet.lib;version.lib;msimg32.lib;ws2_32.lib;usp10.lib;psapi.lib;dbghelp.lib;$(VSInstallDir)\DIA SDK\lib\diaguids.lib;imagehlp.lib</AdditionalDependencies>
+ <AdditionalLibraryDirectories>../../../third_party/platformsdk_win7/files/Lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalOptions>/safeseh /dynamicbase /ignore:4199 /ignore:4221 /nxcompat %(AdditionalOptions)</AdditionalOptions>
+ <DelayLoadDLLs>dbghelp.dll;dwmapi.dll;uxtheme.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
+ <FixedBaseAddress>false</FixedBaseAddress>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ImportLibrary>$(OutDir)lib\$(TargetName).lib</ImportLibrary>
+ <MapFileName>$(OutDir)$(TargetName).map</MapFileName>
+ <SubSystem>Console</SubSystem>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Link>
+ <Midl>
+ <DllDataFileName>dlldata.c</DllDataFileName>
+ <GenerateStublessProxies>true</GenerateStublessProxies>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <OutputDirectory>$(IntDir)</OutputDirectory>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ </Midl>
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>../../..;..\..\..;$(VSInstallDir)\DIA SDK\include;..\..\..\third_party\platformsdk_win7\files\Include;$(VSInstallDir)\VC\atlmfc\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <Culture>0x0409</Culture>
+ <PreprocessorDefinitions>_WIN32_WINNT=0x0600;WINVER=0x0600;WIN32;_WINDOWS;_HAS_EXCEPTIONS=0;NOMINMAX;_CRT_RAND_S;CERT_CHAIN_PARA_HAS_EXTRA_FIELDS;WIN32_LEAN_AND_MEAN;_SECURE_ATL;CHROMIUM_BUILD;TOOLKIT_VIEWS=1;ENABLE_GPU=1;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;NDEBUG;NVALGRIND;%(PreprocessorDefinitions);%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ResourceCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Purify|x64'">
+ <ClCompile>
+ <AdditionalIncludeDirectories>..\..\..;$(VSInstallDir)\DIA SDK\include;..\..\..\third_party\platformsdk_win7\files\Include;$(VSInstallDir)\VC\atlmfc\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AdditionalOptions>/MP %(AdditionalOptions)</AdditionalOptions>
+ <BufferSecurityCheck>false</BufferSecurityCheck>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <DisableSpecificWarnings>4100;4127;4396;4503;4512;4819;4995;4702;4800;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ <ExceptionHandling>false</ExceptionHandling>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <MinimalRebuild>false</MinimalRebuild>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>_WIN32_WINNT=0x0600;WINVER=0x0600;WIN32;_WINDOWS;_HAS_EXCEPTIONS=0;NOMINMAX;_CRT_RAND_S;CERT_CHAIN_PARA_HAS_EXTRA_FIELDS;WIN32_LEAN_AND_MEAN;_SECURE_ATL;CHROMIUM_BUILD;TOOLKIT_VIEWS=1;ENABLE_GPU=1;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;NO_TCMALLOC;NDEBUG;NVALGRIND;PURIFY;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ <RuntimeTypeInfo>false</RuntimeTypeInfo>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <WarningLevel>Level4</WarningLevel>
+ </ClCompile>
+ <Lib>
+ <AdditionalLibraryDirectories>../../../third_party/platformsdk_win7/files/Lib/x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalOptions>/ignore:4221 %(AdditionalOptions)</AdditionalOptions>
+ <OutputFile>$(OutDir)lib\$(ProjectName)$(TargetExt)</OutputFile>
+ </Lib>
+ <Link>
+ <AdditionalDependencies>wininet.lib;version.lib;msimg32.lib;ws2_32.lib;usp10.lib;psapi.lib;dbghelp.lib;$(VSInstallDir)\DIA SDK\lib\diaguids.lib;imagehlp.lib</AdditionalDependencies>
+ <AdditionalLibraryDirectories>../../../third_party/platformsdk_win7/files/Lib/x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalOptions>/dynamicbase /ignore:4199 /ignore:4221 /nxcompat %(AdditionalOptions)</AdditionalOptions>
+ <DelayLoadDLLs>dbghelp.dll;dwmapi.dll;uxtheme.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
+ <EnableCOMDATFolding>false</EnableCOMDATFolding>
+ <FixedBaseAddress>false</FixedBaseAddress>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ImportLibrary>$(OutDir)lib\$(TargetName).lib</ImportLibrary>
+ <MapFileName>$(OutDir)$(TargetName).map</MapFileName>
+ <SubSystem>Console</SubSystem>
+ <TargetMachine>MachineX64</TargetMachine>
+ </Link>
+ <Midl>
+ <DllDataFileName>dlldata.c</DllDataFileName>
+ <GenerateStublessProxies>true</GenerateStublessProxies>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <OutputDirectory>$(IntDir)</OutputDirectory>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ </Midl>
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>../../..;..\..\..;$(VSInstallDir)\DIA SDK\include;..\..\..\third_party\platformsdk_win7\files\Include;$(VSInstallDir)\VC\atlmfc\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <Culture>0x0409</Culture>
+ <PreprocessorDefinitions>_WIN32_WINNT=0x0600;WINVER=0x0600;WIN32;_WINDOWS;_HAS_EXCEPTIONS=0;NOMINMAX;_CRT_RAND_S;CERT_CHAIN_PARA_HAS_EXTRA_FIELDS;WIN32_LEAN_AND_MEAN;_SECURE_ATL;CHROMIUM_BUILD;TOOLKIT_VIEWS=1;ENABLE_GPU=1;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;NO_TCMALLOC;NDEBUG;NVALGRIND;PURIFY;%(PreprocessorDefinitions);%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ResourceCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <AdditionalIncludeDirectories>..\..\..;$(VSInstallDir)\DIA SDK\include;..\..\..\third_party\platformsdk_win7\files\Include;$(VSInstallDir)\VC\atlmfc\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AdditionalOptions>/MP %(AdditionalOptions)</AdditionalOptions>
+ <BufferSecurityCheck>true</BufferSecurityCheck>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <DisableSpecificWarnings>4100;4127;4396;4503;4512;4819;4995;4702;4800;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ <ExceptionHandling>false</ExceptionHandling>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <MinimalRebuild>false</MinimalRebuild>
+ <OmitFramePointers>true</OmitFramePointers>
+ <Optimization>MaxSpeed</Optimization>
+ <PreprocessorDefinitions>_WIN32_WINNT=0x0600;WINVER=0x0600;WIN32;_WINDOWS;_HAS_EXCEPTIONS=0;NOMINMAX;_CRT_RAND_S;CERT_CHAIN_PARA_HAS_EXTRA_FIELDS;WIN32_LEAN_AND_MEAN;_SECURE_ATL;CHROMIUM_BUILD;TOOLKIT_VIEWS=1;ENABLE_GPU=1;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;NDEBUG;NVALGRIND;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ <RuntimeTypeInfo>false</RuntimeTypeInfo>
+ <StringPooling>true</StringPooling>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <WarningLevel>Level4</WarningLevel>
+ </ClCompile>
+ <Lib>
+ <AdditionalLibraryDirectories>../../../third_party/platformsdk_win7/files/Lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalOptions>/ignore:4221 %(AdditionalOptions)</AdditionalOptions>
+ <OutputFile>$(OutDir)lib\$(ProjectName)$(TargetExt)</OutputFile>
+ </Lib>
+ <Link>
+ <AdditionalDependencies>wininet.lib;version.lib;msimg32.lib;ws2_32.lib;usp10.lib;psapi.lib;dbghelp.lib;$(VSInstallDir)\DIA SDK\lib\diaguids.lib;imagehlp.lib</AdditionalDependencies>
+ <AdditionalLibraryDirectories>../../../third_party/platformsdk_win7/files/Lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalOptions>/safeseh /dynamicbase /ignore:4199 /ignore:4221 /nxcompat %(AdditionalOptions)</AdditionalOptions>
+ <DelayLoadDLLs>dbghelp.dll;dwmapi.dll;uxtheme.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <FixedBaseAddress>false</FixedBaseAddress>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ImportLibrary>$(OutDir)lib\$(TargetName).lib</ImportLibrary>
+ <MapFileName>$(OutDir)$(TargetName).map</MapFileName>
+ <OptimizeReferences>true</OptimizeReferences>
+ <SubSystem>Console</SubSystem>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Link>
+ <Midl>
+ <DllDataFileName>dlldata.c</DllDataFileName>
+ <GenerateStublessProxies>true</GenerateStublessProxies>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <OutputDirectory>$(IntDir)</OutputDirectory>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ </Midl>
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>../../..;..\..\..;$(VSInstallDir)\DIA SDK\include;..\..\..\third_party\platformsdk_win7\files\Include;$(VSInstallDir)\VC\atlmfc\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <Culture>0x0409</Culture>
+ <PreprocessorDefinitions>_WIN32_WINNT=0x0600;WINVER=0x0600;WIN32;_WINDOWS;_HAS_EXCEPTIONS=0;NOMINMAX;_CRT_RAND_S;CERT_CHAIN_PARA_HAS_EXTRA_FIELDS;WIN32_LEAN_AND_MEAN;_SECURE_ATL;CHROMIUM_BUILD;TOOLKIT_VIEWS=1;ENABLE_GPU=1;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;NDEBUG;NVALGRIND;%(PreprocessorDefinitions);%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ResourceCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <AdditionalIncludeDirectories>..\..\..;$(VSInstallDir)\DIA SDK\include;..\..\..\third_party\platformsdk_win7\files\Include;$(VSInstallDir)\VC\atlmfc\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AdditionalOptions>/MP %(AdditionalOptions)</AdditionalOptions>
+ <BufferSecurityCheck>true</BufferSecurityCheck>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <DisableSpecificWarnings>4100;4127;4396;4503;4512;4819;4995;4702;4800;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ <ExceptionHandling>false</ExceptionHandling>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <MinimalRebuild>false</MinimalRebuild>
+ <Optimization>MaxSpeed</Optimization>
+ <PreprocessorDefinitions>_WIN32_WINNT=0x0600;WINVER=0x0600;WIN32;_WINDOWS;_HAS_EXCEPTIONS=0;NOMINMAX;_CRT_RAND_S;CERT_CHAIN_PARA_HAS_EXTRA_FIELDS;WIN32_LEAN_AND_MEAN;_SECURE_ATL;CHROMIUM_BUILD;TOOLKIT_VIEWS=1;ENABLE_GPU=1;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;NO_TCMALLOC;NDEBUG;NVALGRIND;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ <RuntimeTypeInfo>false</RuntimeTypeInfo>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <WarningLevel>Level4</WarningLevel>
+ </ClCompile>
+ <Lib>
+ <AdditionalLibraryDirectories>../../../third_party/platformsdk_win7/files/Lib/x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalOptions>/ignore:4221 %(AdditionalOptions)</AdditionalOptions>
+ <OutputFile>$(OutDir)lib\$(ProjectName)$(TargetExt)</OutputFile>
+ </Lib>
+ <Link>
+ <AdditionalDependencies>wininet.lib;version.lib;msimg32.lib;ws2_32.lib;usp10.lib;psapi.lib;dbghelp.lib;$(VSInstallDir)\DIA SDK\lib\diaguids.lib;imagehlp.lib</AdditionalDependencies>
+ <AdditionalLibraryDirectories>../../../third_party/platformsdk_win7/files/Lib/x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalOptions>/dynamicbase /ignore:4199 /ignore:4221 /nxcompat %(AdditionalOptions)</AdditionalOptions>
+ <DelayLoadDLLs>dbghelp.dll;dwmapi.dll;uxtheme.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
+ <FixedBaseAddress>false</FixedBaseAddress>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ImportLibrary>$(OutDir)lib\$(TargetName).lib</ImportLibrary>
+ <MapFileName>$(OutDir)$(TargetName).map</MapFileName>
+ <SubSystem>Console</SubSystem>
+ <TargetMachine>MachineX64</TargetMachine>
+ </Link>
+ <Midl>
+ <DllDataFileName>dlldata.c</DllDataFileName>
+ <GenerateStublessProxies>true</GenerateStublessProxies>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <OutputDirectory>$(IntDir)</OutputDirectory>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ </Midl>
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>../../..;..\..\..;$(VSInstallDir)\DIA SDK\include;..\..\..\third_party\platformsdk_win7\files\Include;$(VSInstallDir)\VC\atlmfc\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <Culture>0x0409</Culture>
+ <PreprocessorDefinitions>_WIN32_WINNT=0x0600;WINVER=0x0600;WIN32;_WINDOWS;_HAS_EXCEPTIONS=0;NOMINMAX;_CRT_RAND_S;CERT_CHAIN_PARA_HAS_EXTRA_FIELDS;WIN32_LEAN_AND_MEAN;_SECURE_ATL;CHROMIUM_BUILD;TOOLKIT_VIEWS=1;ENABLE_GPU=1;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;NO_TCMALLOC;NDEBUG;NVALGRIND;%(PreprocessorDefinitions);%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ResourceCompile>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <None Include="ms_symbol_server_converter.gyp"/>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="ms_symbol_server_converter.cc"/>
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets"/>
+ <ImportGroup Label="ExtensionTargets"/>
+</Project>
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/configure.cmd b/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/configure.cmd
new file mode 100644
index 0000000000..5464a61ed7
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/configure.cmd
@@ -0,0 +1,33 @@
+@if "%ECHOON%"=="" @echo off
+SETLOCAL
+
+REM ******************************************************************
+REM Please, make sure to run this in an Elevated Command Prompt.
+REM Usage:
+REM configure.cmd
+REM ******************************************************************
+
+REM ******************************************************************
+REM Initialize
+REM ******************************************************************
+SET SCRIPT_LOCATION=%~dp0
+
+REM ******************************************************************
+REM Go to script location
+REM ******************************************************************
+pushd %SCRIPT_LOCATION%
+
+REM ******************************************************************
+REM Register msdia140.dll.
+REM ******************************************************************
+SET MSG=Failed to register msdia140.dll. Make sure to run this in elevated command prompt.
+%systemroot%\SysWoW64\regsvr32.exe /s msdia140.dll & if errorlevel 1 echo %MSG% & goto :fail
+
+:success
+echo Configuration was successful.
+ENDLOCAL
+exit /b 0
+
+:fail
+ENDLOCAL
+exit /b 1
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/converter.cc b/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/converter.cc
new file mode 100644
index 0000000000..5b70903a4d
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/converter.cc
@@ -0,0 +1,807 @@
+// Copyright 2019 Google Inc. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#pragma comment(lib, "winhttp.lib")
+#pragma comment(lib, "wininet.lib")
+#pragma comment(lib, "diaguids.lib")
+#pragma comment(lib, "imagehlp.lib")
+
+#include <cassert>
+#include <cstdio>
+#include <ctime>
+#include <map>
+#include <regex>
+#include <string>
+#include <vector>
+
+#include "tools/windows/converter_exe/escaping.h"
+#include "tools/windows/converter_exe/http_download.h"
+#include "tools/windows/converter_exe/tokenizer.h"
+#include "common/windows/http_upload.h"
+#include "common/windows/string_utils-inl.h"
+#include "tools/windows/converter/ms_symbol_server_converter.h"
+
+using strings::WebSafeBase64Unescape;
+using strings::WebSafeBase64Escape;
+
+namespace {
+
+using std::map;
+using std::string;
+using std::vector;
+using std::wstring;
+using crash::HTTPDownload;
+using crash::Tokenizer;
+using google_breakpad::HTTPUpload;
+using google_breakpad::MissingSymbolInfo;
+using google_breakpad::MSSymbolServerConverter;
+using google_breakpad::WindowsStringUtils;
+
+const char *kMissingStringDelimiters = "|";
+const char *kLocalCachePath = "c:\\symbols";
+const char *kNoExeMSSSServer = "http://msdl.microsoft.com/download/symbols/";
+
+// Windows stdio doesn't do line buffering. Use this function to flush after
+// writing to stdout and stderr so that a log will be available if the
+// converter crashes.
+static int FprintfFlush(FILE *file, const char *format, ...) {
+ va_list arguments;
+ va_start(arguments, format);
+ int retval = vfprintf(file, format, arguments);
+ va_end(arguments);
+ fflush(file);
+ return retval;
+}
+
+static string CurrentDateAndTime() {
+ const string kUnknownDateAndTime = R"(????-??-?? ??:??:??)";
+
+ time_t current_time;
+ time(&current_time);
+
+ // localtime_s is safer but is only available in MSVC8. Use localtime
+ // in earlier environments.
+ struct tm *time_pointer;
+#if _MSC_VER >= 1400 // MSVC 2005/8
+ struct tm time_struct;
+ time_pointer = &time_struct;
+ if (localtime_s(time_pointer, &current_time) != 0) {
+ return kUnknownDateAndTime;
+ }
+#else // _MSC_VER >= 1400
+ time_pointer = localtime(&current_time);
+ if (!time_pointer) {
+ return kUnknownDateAndTime;
+ }
+#endif // _MSC_VER >= 1400
+
+ char buffer[256];
+ if (!strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", time_pointer)) {
+ return kUnknownDateAndTime;
+ }
+
+ return string(buffer);
+}
+
+// ParseMissingString turns |missing_string| into a MissingSymbolInfo
+// structure. It returns true on success, and false if no such conversion
+// is possible.
+static bool ParseMissingString(const string &missing_string,
+ MissingSymbolInfo *missing_info) {
+ assert(missing_info);
+
+ vector<string> tokens;
+ Tokenizer::Tokenize(kMissingStringDelimiters, missing_string, &tokens);
+ if (tokens.size() != 5) {
+ return false;
+ }
+
+ missing_info->debug_file = tokens[0];
+ missing_info->debug_identifier = tokens[1];
+ missing_info->version = tokens[2];
+ missing_info->code_file = tokens[3];
+ missing_info->code_identifier = tokens[4];
+
+ return true;
+}
+
+// StringMapToWStringMap takes each element in a map that associates
+// (narrow) strings to strings and converts the keys and values to wstrings.
+// Returns true on success and false on failure, printing an error message.
+static bool StringMapToWStringMap(const map<string, string> &smap,
+ map<wstring, wstring> *wsmap) {
+ assert(wsmap);
+ wsmap->clear();
+
+ for (map<string, string>::const_iterator iterator = smap.begin();
+ iterator != smap.end();
+ ++iterator) {
+ wstring key;
+ if (!WindowsStringUtils::safe_mbstowcs(iterator->first, &key)) {
+ FprintfFlush(stderr,
+ "StringMapToWStringMap: safe_mbstowcs failed for key %s\n",
+ iterator->first.c_str());
+ return false;
+ }
+
+ wstring value;
+ if (!WindowsStringUtils::safe_mbstowcs(iterator->second, &value)) {
+ FprintfFlush(stderr, "StringMapToWStringMap: safe_mbstowcs failed "
+ "for value %s\n",
+ iterator->second.c_str());
+ return false;
+ }
+
+ wsmap->insert(make_pair(key, value));
+ }
+
+ return true;
+}
+
+// MissingSymbolInfoToParameters turns a MissingSymbolInfo structure into a
+// map of parameters suitable for passing to HTTPDownload or HTTPUpload.
+// Returns true on success and false on failure, printing an error message.
+static bool MissingSymbolInfoToParameters(const MissingSymbolInfo &missing_info,
+ map<wstring, wstring> *wparameters) {
+ assert(wparameters);
+
+ map<string, string> parameters;
+ string encoded_param;
+ // Indicate the params are encoded.
+ parameters["encoded"] = "true"; // The string value here does not matter.
+
+ WebSafeBase64Escape(missing_info.code_file, &encoded_param);
+ parameters["code_file"] = encoded_param;
+
+ WebSafeBase64Escape(missing_info.code_identifier, &encoded_param);
+ parameters["code_identifier"] = encoded_param;
+
+ WebSafeBase64Escape(missing_info.debug_file, &encoded_param);
+ parameters["debug_file"] = encoded_param;
+
+ WebSafeBase64Escape(missing_info.debug_identifier, &encoded_param);
+ parameters["debug_identifier"] = encoded_param;
+
+ if (!missing_info.version.empty()) {
+ // The version is optional.
+ WebSafeBase64Escape(missing_info.version, &encoded_param);
+ parameters["version"] = encoded_param;
+ }
+
+ WebSafeBase64Escape("WinSymConv", &encoded_param);
+ parameters["product"] = encoded_param;
+
+ if (!StringMapToWStringMap(parameters, wparameters)) {
+ // StringMapToWStringMap will have printed an error.
+ return false;
+ }
+
+ return true;
+}
+
+// UploadSymbolFile sends |converted_file| as identified by |missing_info|
+// to the symbol server rooted at |upload_symbol_url|. Returns true on
+// success and false on failure, printing an error message.
+static bool UploadSymbolFile(const wstring &upload_symbol_url,
+ const MissingSymbolInfo &missing_info,
+ const string &converted_file) {
+ map<wstring, wstring> parameters;
+ if (!MissingSymbolInfoToParameters(missing_info, &parameters)) {
+ // MissingSymbolInfoToParameters or a callee will have printed an error.
+ return false;
+ }
+
+ wstring converted_file_w;
+
+ if (!WindowsStringUtils::safe_mbstowcs(converted_file, &converted_file_w)) {
+ FprintfFlush(stderr, "UploadSymbolFile: safe_mbstowcs failed for %s\n",
+ converted_file.c_str());
+ return false;
+ }
+ map<wstring, wstring> files;
+ files[L"symbol_file"] = converted_file_w;
+
+ FprintfFlush(stderr, "Uploading %s\n", converted_file.c_str());
+ if (!HTTPUpload::SendMultipartPostRequest(
+ upload_symbol_url, parameters,
+ files, NULL, NULL, NULL)) {
+ FprintfFlush(stderr, "UploadSymbolFile: HTTPUpload::SendRequest failed "
+ "for %s %s %s\n",
+ missing_info.debug_file.c_str(),
+ missing_info.debug_identifier.c_str(),
+ missing_info.version.c_str());
+ return false;
+ }
+
+ return true;
+}
+
+// SendFetchFailedPing informs the symbol server based at
+// |fetch_symbol_failure_url| that the symbol file identified by
+// |missing_info| could authoritatively not be located. Returns
+// true on success and false on failure.
+static bool SendFetchFailedPing(const wstring &fetch_symbol_failure_url,
+ const MissingSymbolInfo &missing_info) {
+ map<wstring, wstring> parameters;
+ if (!MissingSymbolInfoToParameters(missing_info, &parameters)) {
+ // MissingSymbolInfoToParameters or a callee will have printed an error.
+ return false;
+ }
+
+ string content;
+ if (!HTTPDownload::Download(fetch_symbol_failure_url,
+ &parameters,
+ &content,
+ NULL)) {
+ FprintfFlush(stderr, "SendFetchFailedPing: HTTPDownload::Download failed "
+ "for %s %s %s\n",
+ missing_info.debug_file.c_str(),
+ missing_info.debug_identifier.c_str(),
+ missing_info.version.c_str());
+ return false;
+ }
+
+ return true;
+}
+
+// Returns true if it's safe to make an external request for the symbol
+// file described in missing_info. It's considered safe to make an
+// external request unless the symbol file's debug_file string matches
+// the given blacklist regular expression.
+// The debug_file name is used from the MissingSymbolInfo struct,
+// matched against the blacklist_regex.
+static bool SafeToMakeExternalRequest(const MissingSymbolInfo &missing_info,
+ std::regex blacklist_regex) {
+ string file_name = missing_info.debug_file;
+ // Use regex_search because we want to match substrings.
+ if (std::regex_search(file_name, blacklist_regex)) {
+ FprintfFlush(stderr, "Not safe to make external request for file %s\n",
+ file_name.c_str());
+ return false;
+ }
+
+ return true;
+}
+
+// Converter options derived from command line parameters.
+struct ConverterOptions {
+ ConverterOptions()
+ : report_fetch_failures(true) {
+ }
+
+ ~ConverterOptions() {
+ }
+
+ // Names of MS Symbol Supplier Servers that are internal to Google, and may
+ // have symbols for any request.
+ vector<string> full_internal_msss_servers;
+
+ // Names of MS Symbol Supplier Servers that are internal to Google, and
+ // shouldn't be checked for symbols for any .exe files.
+ vector<string> full_external_msss_servers;
+
+ // Names of MS Symbol Supplier Servers that are external to Google, and may
+ // have symbols for any request.
+ vector<string> no_exe_internal_msss_servers;
+
+ // Names of MS Symbol Supplier Servers that are external to Google, and
+ // shouldn't be checked for symbols for any .exe files.
+ vector<string> no_exe_external_msss_servers;
+
+ // Temporary local storage for symbols.
+ string local_cache_path;
+
+ // URL for uploading symbols.
+ wstring upload_symbols_url;
+
+ // URL to fetch list of missing symbols.
+ wstring missing_symbols_url;
+
+ // URL to report symbol fetch failure.
+ wstring fetch_symbol_failure_url;
+
+ // Are symbol fetch failures reported.
+ bool report_fetch_failures;
+
+ // File containing the list of missing symbols. Fetch failures are not
+ // reported if such file is provided.
+ string missing_symbols_file;
+
+ // Regex used to blacklist files to prevent external symbol requests.
+ // Owned and cleaned up by this struct.
+ std::regex blacklist_regex;
+
+ private:
+ // DISABLE_COPY_AND_ASSIGN
+ ConverterOptions(const ConverterOptions&);
+ ConverterOptions& operator=(const ConverterOptions&);
+};
+
+// ConverMissingSymbolFile takes a single MissingSymbolInfo structure and
+// attempts to locate it from the symbol servers provided in the
+// |options.*_msss_servers| arguments. "Full" servers are those that will be
+// queried for all symbol files; "No-EXE" servers will only be queried for
+// modules whose missing symbol data indicates are not main program executables.
+// Results will be sent to the |options.upload_symbols_url| on success or
+// |options.fetch_symbol_failure_url| on failure, and the local cache will be
+// stored at |options.local_cache_path|. Because nothing can be done even in
+// the event of a failure, this function returns no value, although it
+// may result in error messages being printed.
+static void ConvertMissingSymbolFile(const MissingSymbolInfo &missing_info,
+ const ConverterOptions &options) {
+ string time_string = CurrentDateAndTime();
+ FprintfFlush(stdout, "converter: %s: attempting %s %s %s\n",
+ time_string.c_str(),
+ missing_info.debug_file.c_str(),
+ missing_info.debug_identifier.c_str(),
+ missing_info.version.c_str());
+
+ // The first lookup is always to internal symbol servers.
+ // Always ask the symbol servers identified as "full."
+ vector<string> msss_servers = options.full_internal_msss_servers;
+
+ // If the file is not an .exe file, also ask an additional set of symbol
+ // servers, such as Microsoft's public symbol server.
+ bool is_exe = false;
+
+ if (missing_info.code_file.length() >= 4) {
+ string code_extension =
+ missing_info.code_file.substr(missing_info.code_file.size() - 4);
+
+ // Firefox is a special case: .dll-only servers should be consulted for
+ // its symbols. This enables us to get its symbols from Mozilla's
+ // symbol server when crashes occur in Google extension code hosted by a
+ // Firefox process.
+ if (_stricmp(code_extension.c_str(), ".exe") == 0 &&
+ _stricmp(missing_info.code_file.c_str(), "firefox.exe") != 0) {
+ is_exe = true;
+ }
+ }
+
+ if (!is_exe) {
+ msss_servers.insert(msss_servers.end(),
+ options.no_exe_internal_msss_servers.begin(),
+ options.no_exe_internal_msss_servers.end());
+ }
+
+ // If there are any suitable internal symbol servers, make a request.
+ MSSymbolServerConverter::LocateResult located =
+ MSSymbolServerConverter::LOCATE_FAILURE;
+ string converted_file;
+ if (msss_servers.size() > 0) {
+ // Attempt to fetch the symbol file and convert it.
+ FprintfFlush(stderr, "Making internal request for %s (%s)\n",
+ missing_info.debug_file.c_str(),
+ missing_info.debug_identifier.c_str());
+ MSSymbolServerConverter converter(options.local_cache_path, msss_servers);
+ located = converter.LocateAndConvertSymbolFile(missing_info,
+ false, // keep_symbol_file
+ false, // keep_pe_file
+ &converted_file,
+ NULL, // symbol_file
+ NULL); // pe_file
+ switch (located) {
+ case MSSymbolServerConverter::LOCATE_SUCCESS:
+ FprintfFlush(stderr, "LocateResult = LOCATE_SUCCESS\n");
+ // Upload it. Don't bother checking the return value. If this
+ // succeeds, it should disappear from the missing symbol list.
+ // If it fails, something will print an error message indicating
+ // the cause of the failure, and the item will remain on the
+ // missing symbol list.
+ UploadSymbolFile(options.upload_symbols_url, missing_info,
+ converted_file);
+ remove(converted_file.c_str());
+
+ // Note: this does leave some directories behind that could be
+ // cleaned up. The directories inside options.local_cache_path for
+ // debug_file/debug_identifier can be removed at this point.
+ break;
+
+ case MSSymbolServerConverter::LOCATE_NOT_FOUND:
+ FprintfFlush(stderr, "LocateResult = LOCATE_NOT_FOUND\n");
+ // The symbol file definitively did not exist. Fall through,
+ // so we can attempt an external query if it's safe to do so.
+ break;
+
+ case MSSymbolServerConverter::LOCATE_RETRY:
+ FprintfFlush(stderr, "LocateResult = LOCATE_RETRY\n");
+ // Fall through in case we should make an external request.
+ // If not, or if an external request fails in the same way,
+ // we'll leave the entry in the symbol file list and
+ // try again on a future pass. Print a message so that there's
+ // a record.
+ break;
+
+ case MSSymbolServerConverter::LOCATE_FAILURE:
+ FprintfFlush(stderr, "LocateResult = LOCATE_FAILURE\n");
+ // LocateAndConvertSymbolFile printed an error message.
+ break;
+
+ default:
+ FprintfFlush(
+ stderr,
+ "FATAL: Unexpected return value '%d' from "
+ "LocateAndConvertSymbolFile()\n",
+ located);
+ assert(0);
+ break;
+ }
+ } else {
+ // No suitable internal symbol servers. This is fine because the converter
+ // is mainly used for downloading and converting of external symbols.
+ }
+
+ // Make a request to an external server if the internal request didn't
+ // succeed, and it's safe to do so.
+ if (located != MSSymbolServerConverter::LOCATE_SUCCESS &&
+ SafeToMakeExternalRequest(missing_info, options.blacklist_regex)) {
+ msss_servers = options.full_external_msss_servers;
+ if (!is_exe) {
+ msss_servers.insert(msss_servers.end(),
+ options.no_exe_external_msss_servers.begin(),
+ options.no_exe_external_msss_servers.end());
+ }
+ if (msss_servers.size() > 0) {
+ FprintfFlush(stderr, "Making external request for %s (%s)\n",
+ missing_info.debug_file.c_str(),
+ missing_info.debug_identifier.c_str());
+ MSSymbolServerConverter external_converter(options.local_cache_path,
+ msss_servers);
+ located = external_converter.LocateAndConvertSymbolFile(
+ missing_info,
+ false, // keep_symbol_file
+ false, // keep_pe_file
+ &converted_file,
+ NULL, // symbol_file
+ NULL); // pe_file
+ } else {
+ FprintfFlush(stderr, "ERROR: No suitable external symbol servers.\n");
+ }
+ }
+
+ // Final handling for this symbol file is based on the result from the
+ // external request (if performed above), or on the result from the
+ // previous internal lookup.
+ switch (located) {
+ case MSSymbolServerConverter::LOCATE_SUCCESS:
+ FprintfFlush(stderr, "LocateResult = LOCATE_SUCCESS\n");
+ // Upload it. Don't bother checking the return value. If this
+ // succeeds, it should disappear from the missing symbol list.
+ // If it fails, something will print an error message indicating
+ // the cause of the failure, and the item will remain on the
+ // missing symbol list.
+ UploadSymbolFile(options.upload_symbols_url, missing_info,
+ converted_file);
+ remove(converted_file.c_str());
+
+ // Note: this does leave some directories behind that could be
+ // cleaned up. The directories inside options.local_cache_path for
+ // debug_file/debug_identifier can be removed at this point.
+ break;
+
+ case MSSymbolServerConverter::LOCATE_NOT_FOUND:
+ // The symbol file definitively didn't exist. Inform the server.
+ // If this fails, something will print an error message indicating
+ // the cause of the failure, but there's really nothing more to
+ // do. If this succeeds, the entry should be removed from the
+ // missing symbols list.
+ if (!options.report_fetch_failures) {
+ FprintfFlush(stderr, "SendFetchFailedPing skipped\n");
+ } else if (SendFetchFailedPing(options.fetch_symbol_failure_url,
+ missing_info)) {
+ FprintfFlush(stderr, "SendFetchFailedPing succeeded\n");
+ } else {
+ FprintfFlush(stderr, "SendFetchFailedPing failed\n");
+ }
+ break;
+
+ case MSSymbolServerConverter::LOCATE_RETRY:
+ FprintfFlush(stderr, "LocateResult = LOCATE_RETRY\n");
+ // Nothing to do but leave the entry in the symbol file list and
+ // try again on a future pass. Print a message so that there's
+ // a record.
+ FprintfFlush(stderr, "ConvertMissingSymbolFile: deferring retry "
+ "for %s %s %s\n",
+ missing_info.debug_file.c_str(),
+ missing_info.debug_identifier.c_str(),
+ missing_info.version.c_str());
+ break;
+
+ case MSSymbolServerConverter::LOCATE_FAILURE:
+ FprintfFlush(stderr, "LocateResult = LOCATE_FAILURE\n");
+ // LocateAndConvertSymbolFile printed an error message.
+
+ // This is due to a bad debug file name, so fetch failed.
+ if (!options.report_fetch_failures) {
+ FprintfFlush(stderr, "SendFetchFailedPing skipped\n");
+ } else if (SendFetchFailedPing(options.fetch_symbol_failure_url,
+ missing_info)) {
+ FprintfFlush(stderr, "SendFetchFailedPing succeeded\n");
+ } else {
+ FprintfFlush(stderr, "SendFetchFailedPing failed\n");
+ }
+ break;
+
+ default:
+ FprintfFlush(
+ stderr,
+ "FATAL: Unexpected return value '%d' from "
+ "LocateAndConvertSymbolFile()\n",
+ located);
+ assert(0);
+ break;
+ }
+}
+
+
+// Reads the contents of file |file_name| and populates |contents|.
+// Returns true on success.
+static bool ReadFile(string file_name, string *contents) {
+ char buffer[1024 * 8];
+ FILE *fp = fopen(file_name.c_str(), "rt");
+ if (!fp) {
+ return false;
+ }
+ contents->clear();
+ while (fgets(buffer, sizeof(buffer), fp) != NULL) {
+ contents->append(buffer);
+ }
+ fclose(fp);
+ return true;
+}
+
+// ConvertMissingSymbolsList obtains a missing symbol list from
+// |options.missing_symbols_url| or |options.missing_symbols_file| and calls
+// ConvertMissingSymbolFile for each missing symbol file in the list.
+static bool ConvertMissingSymbolsList(const ConverterOptions &options) {
+ // Set param to indicate requesting for encoded response.
+ map<wstring, wstring> parameters;
+ parameters[L"product"] = L"WinSymConv";
+ parameters[L"encoded"] = L"true";
+ // Get the missing symbol list.
+ string missing_symbol_list;
+ if (!options.missing_symbols_file.empty()) {
+ if (!ReadFile(options.missing_symbols_file, &missing_symbol_list)) {
+ return false;
+ }
+ } else if (!HTTPDownload::Download(options.missing_symbols_url, &parameters,
+ &missing_symbol_list, NULL)) {
+ return false;
+ }
+
+ // Tokenize the content into a vector.
+ vector<string> missing_symbol_lines;
+ Tokenizer::Tokenize("\n", missing_symbol_list, &missing_symbol_lines);
+
+ FprintfFlush(stderr, "Found %d missing symbol files in list.\n",
+ missing_symbol_lines.size() - 1); // last line is empty.
+ int convert_attempts = 0;
+ for (vector<string>::const_iterator iterator = missing_symbol_lines.begin();
+ iterator != missing_symbol_lines.end();
+ ++iterator) {
+ // Decode symbol line.
+ const string &encoded_line = *iterator;
+ // Skip lines that are blank.
+ if (encoded_line.empty()) {
+ continue;
+ }
+
+ string line;
+ if (!WebSafeBase64Unescape(encoded_line, &line)) {
+ // If decoding fails, assume the line is not encoded.
+ // This is helpful when the program connects to a debug server without
+ // encoding.
+ line = encoded_line;
+ }
+
+ FprintfFlush(stderr, "\nLine: %s\n", line.c_str());
+
+ // Turn each element into a MissingSymbolInfo structure.
+ MissingSymbolInfo missing_info;
+ if (!ParseMissingString(line, &missing_info)) {
+ FprintfFlush(stderr, "ConvertMissingSymbols: ParseMissingString failed "
+ "for %s from %ws\n",
+ line.c_str(), options.missing_symbols_url.c_str());
+ continue;
+ }
+
+ ++convert_attempts;
+ ConvertMissingSymbolFile(missing_info, options);
+ }
+
+ // Say something reassuring, since ConvertMissingSymbolFile was never called
+ // and therefore never reported any progress.
+ if (convert_attempts == 0) {
+ string current_time = CurrentDateAndTime();
+ FprintfFlush(stdout, "converter: %s: nothing to convert\n",
+ current_time.c_str());
+ }
+
+ return true;
+}
+
+// usage prints the usage message. It returns 1 as a convenience, to be used
+// as a return value from main.
+static int usage(const char *program_name) {
+ FprintfFlush(stderr,
+ "usage: %s [options]\n"
+ " -f <full_msss_server> MS servers to ask for all symbols\n"
+ " -n <no_exe_msss_server> same, but prevent asking for EXEs\n"
+ " -l <local_cache_path> Temporary local storage for symbols\n"
+ " -s <upload_url> URL for uploading symbols\n"
+ " -m <missing_symbols_url> URL to fetch list of missing symbols\n"
+ " -mf <missing_symbols_file> File containing the list of missing\n"
+ " symbols. Fetch failures are not\n"
+ " reported if such file is provided.\n"
+ " -t <fetch_failure_url> URL to report symbol fetch failure\n"
+ " -b <regex> Regex used to blacklist files to\n"
+ " prevent external symbol requests\n"
+ " Note that any server specified by -f or -n that starts with \\filer\n"
+ " will be treated as internal, and all others as external.\n",
+ program_name);
+
+ return 1;
+}
+
+// "Internal" servers consist only of those whose names start with
+// the literal string "\\filer\".
+static bool IsInternalServer(const string &server_name) {
+ if (server_name.find("\\\\filer\\") == 0) {
+ return true;
+ }
+ return false;
+}
+
+// Adds a server with the given name to the list of internal or external
+// servers, as appropriate.
+static void AddServer(const string &server_name,
+ vector<string> *internal_servers,
+ vector<string> *external_servers) {
+ if (IsInternalServer(server_name)) {
+ internal_servers->push_back(server_name);
+ } else {
+ external_servers->push_back(server_name);
+ }
+}
+
+} // namespace
+
+int main(int argc, char **argv) {
+ string time_string = CurrentDateAndTime();
+ FprintfFlush(stdout, "converter: %s: starting\n", time_string.c_str());
+
+ ConverterOptions options;
+ options.report_fetch_failures = true;
+
+ // All arguments are paired.
+ if (argc % 2 != 1) {
+ return usage(argv[0]);
+ }
+
+ string blacklist_regex_str;
+ bool have_any_msss_servers = false;
+ for (int argi = 1; argi < argc; argi += 2) {
+ string option = argv[argi];
+ string value = argv[argi + 1];
+
+ if (option == "-f") {
+ AddServer(value, &options.full_internal_msss_servers,
+ &options.full_external_msss_servers);
+ have_any_msss_servers = true;
+ } else if (option == "-n") {
+ AddServer(value, &options.no_exe_internal_msss_servers,
+ &options.no_exe_external_msss_servers);
+ have_any_msss_servers = true;
+ } else if (option == "-l") {
+ if (!options.local_cache_path.empty()) {
+ return usage(argv[0]);
+ }
+ options.local_cache_path = value;
+ } else if (option == "-s") {
+ if (!WindowsStringUtils::safe_mbstowcs(value,
+ &options.upload_symbols_url)) {
+ FprintfFlush(stderr, "main: safe_mbstowcs failed for %s\n",
+ value.c_str());
+ return 1;
+ }
+ } else if (option == "-m") {
+ if (!WindowsStringUtils::safe_mbstowcs(value,
+ &options.missing_symbols_url)) {
+ FprintfFlush(stderr, "main: safe_mbstowcs failed for %s\n",
+ value.c_str());
+ return 1;
+ }
+ } else if (option == "-mf") {
+ options.missing_symbols_file = value;
+ printf("Getting the list of missing symbols from a file. Fetch failures"
+ " will not be reported.\n");
+ options.report_fetch_failures = false;
+ } else if (option == "-t") {
+ if (!WindowsStringUtils::safe_mbstowcs(
+ value,
+ &options.fetch_symbol_failure_url)) {
+ FprintfFlush(stderr, "main: safe_mbstowcs failed for %s\n",
+ value.c_str());
+ return 1;
+ }
+ } else if (option == "-b") {
+ blacklist_regex_str = value;
+ } else {
+ return usage(argv[0]);
+ }
+ }
+
+ if (blacklist_regex_str.empty()) {
+ FprintfFlush(stderr, "No blacklist specified.\n");
+ return usage(argv[0]);
+ }
+
+ // Compile the blacklist regular expression for later use.
+ options.blacklist_regex = std::regex(blacklist_regex_str.c_str(),
+ std::regex_constants::icase);
+
+ // Set the defaults. If the user specified any MSSS servers, don't use
+ // any default.
+ if (!have_any_msss_servers) {
+ AddServer(kNoExeMSSSServer, &options.no_exe_internal_msss_servers,
+ &options.no_exe_external_msss_servers);
+ }
+
+ if (options.local_cache_path.empty()) {
+ options.local_cache_path = kLocalCachePath;
+ }
+
+ if (options.upload_symbols_url.empty()) {
+ FprintfFlush(stderr, "No upload symbols URL specified.\n");
+ return usage(argv[0]);
+ }
+ if (options.missing_symbols_url.empty() &&
+ options.missing_symbols_file.empty()) {
+ FprintfFlush(stderr, "No missing symbols URL or file specified.\n");
+ return usage(argv[0]);
+ }
+ if (options.fetch_symbol_failure_url.empty()) {
+ FprintfFlush(stderr, "No fetch symbol failure URL specified.\n");
+ return usage(argv[0]);
+ }
+
+ FprintfFlush(stdout,
+ "# of Symbol Servers (int/ext): %d/%d full, %d/%d no_exe\n",
+ options.full_internal_msss_servers.size(),
+ options.full_external_msss_servers.size(),
+ options.no_exe_internal_msss_servers.size(),
+ options.no_exe_external_msss_servers.size());
+
+ if (!ConvertMissingSymbolsList(options)) {
+ return 1;
+ }
+
+ time_string = CurrentDateAndTime();
+ FprintfFlush(stdout, "converter: %s: finished\n", time_string.c_str());
+ return 0;
+}
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/converter.gyp b/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/converter.gyp
new file mode 100644
index 0000000000..fe443d1b40
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/converter.gyp
@@ -0,0 +1,57 @@
+# Copyright 2013 Google Inc. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+{
+ 'includes': [
+ '../../../build/common.gypi',
+ ],
+ 'targets': [
+ {
+ 'target_name': 'converter_exe',
+ 'type': 'executable',
+ 'sources': [
+ 'converter.cc',
+ 'escaping.cc',
+ 'escaping.h',
+ 'http_client.h',
+ 'http_download.cc',
+ 'http_download.h',
+ 'tokenizer.cc',
+ 'tokenizer.h',
+ 'winhttp_client.cc',
+ 'winhttp_client.h',
+ 'wininet_client.cc',
+ 'wininet_client.h',
+ ],
+ 'dependencies': [
+ '../../../common/windows/common_windows.gyp:common_windows_lib',
+ '../converter/ms_symbol_server_converter.gyp:ms_symbol_server_converter',
+ ],
+ },
+ ],
+}
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/escaping.cc b/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/escaping.cc
new file mode 100644
index 0000000000..74a7203ab4
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/escaping.cc
@@ -0,0 +1,757 @@
+// Copyright 2019 Google Inc. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "tools/windows/converter_exe/escaping.h"
+
+#include <assert.h>
+
+#define kApb kAsciiPropertyBits
+
+const unsigned char kAsciiPropertyBits[256] = {
+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, // 0x00
+ 0x40, 0x68, 0x48, 0x48, 0x48, 0x48, 0x40, 0x40,
+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, // 0x10
+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
+ 0x28, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, // 0x20
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x84, 0x84, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x05, // 0x40
+ 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
+ 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, // 0x50
+ 0x05, 0x05, 0x05, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x05, // 0x60
+ 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
+ 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, // 0x70
+ 0x05, 0x05, 0x05, 0x10, 0x10, 0x10, 0x10, 0x40,
+};
+
+// Use !! to suppress the warning C4800 of forcing 'int' to 'bool'.
+static inline bool ascii_isspace(unsigned char c) { return !!(kApb[c] & 0x08); }
+
+///////////////////////////////////
+// scoped_array
+///////////////////////////////////
+// scoped_array<C> is like scoped_ptr<C>, except that the caller must allocate
+// with new [] and the destructor deletes objects with delete [].
+//
+// As with scoped_ptr<C>, a scoped_array<C> either points to an object
+// or is NULL. A scoped_array<C> owns the object that it points to.
+// scoped_array<T> is thread-compatible, and once you index into it,
+// the returned objects have only the threadsafety guarantees of T.
+//
+// Size: sizeof(scoped_array<C>) == sizeof(C*)
+template <class C>
+class scoped_array {
+ public:
+
+ // The element type
+ typedef C element_type;
+
+ // Constructor. Defaults to intializing with NULL.
+ // There is no way to create an uninitialized scoped_array.
+ // The input parameter must be allocated with new [].
+ explicit scoped_array(C* p = NULL) : array_(p) { }
+
+ // Destructor. If there is a C object, delete it.
+ // We don't need to test ptr_ == NULL because C++ does that for us.
+ ~scoped_array() {
+ enum { type_must_be_complete = sizeof(C) };
+ delete[] array_;
+ }
+
+ // Reset. Deletes the current owned object, if any.
+ // Then takes ownership of a new object, if given.
+ // this->reset(this->get()) works.
+ void reset(C* p = NULL) {
+ if (p != array_) {
+ enum { type_must_be_complete = sizeof(C) };
+ delete[] array_;
+ array_ = p;
+ }
+ }
+
+ // Get one element of the current object.
+ // Will assert() if there is no current object, or index i is negative.
+ C& operator[](std::ptrdiff_t i) const {
+ assert(i >= 0);
+ assert(array_ != NULL);
+ return array_[i];
+ }
+
+ // Get a pointer to the zeroth element of the current object.
+ // If there is no current object, return NULL.
+ C* get() const {
+ return array_;
+ }
+
+ // Comparison operators.
+ // These return whether a scoped_array and a raw pointer refer to
+ // the same array, not just to two different but equal arrays.
+ bool operator==(const C* p) const { return array_ == p; }
+ bool operator!=(const C* p) const { return array_ != p; }
+
+ // Swap two scoped arrays.
+ void swap(scoped_array& p2) {
+ C* tmp = array_;
+ array_ = p2.array_;
+ p2.array_ = tmp;
+ }
+
+ // Release an array.
+ // The return value is the current pointer held by this object.
+ // If this object holds a NULL pointer, the return value is NULL.
+ // After this operation, this object will hold a NULL pointer,
+ // and will not own the object any more.
+ C* release() {
+ C* retVal = array_;
+ array_ = NULL;
+ return retVal;
+ }
+
+ private:
+ C* array_;
+
+ // Forbid comparison of different scoped_array types.
+ template <class C2> bool operator==(scoped_array<C2> const& p2) const;
+ template <class C2> bool operator!=(scoped_array<C2> const& p2) const;
+
+ // Disallow evil constructors
+ scoped_array(const scoped_array&);
+ void operator=(const scoped_array&);
+};
+
+
+///////////////////////////////////
+// Escape methods
+///////////////////////////////////
+
+namespace strings {
+
+// Return a mutable char* pointing to a string's internal buffer,
+// which may not be null-terminated. Writing through this pointer will
+// modify the string.
+//
+// string_as_array(&str)[i] is valid for 0 <= i < str.size() until the
+// next call to a string method that invalidates iterators.
+//
+// As of 2006-04, there is no standard-blessed way of getting a
+// mutable reference to a string's internal buffer. However, issue 530
+// (http://www.open-std.org/JTC1/SC22/WG21/docs/lwg-active.html#530)
+// proposes this as the method. According to Matt Austern, this should
+// already work on all current implementations.
+inline char* string_as_array(string* str) {
+ // DO NOT USE const_cast<char*>(str->data())! See the unittest for why.
+ return str->empty() ? NULL : &*str->begin();
+}
+
+int CalculateBase64EscapedLen(int input_len, bool do_padding) {
+ // these formulae were copied from comments that used to go with the base64
+ // encoding functions
+ int intermediate_result = 8 * input_len + 5;
+ assert(intermediate_result > 0); // make sure we didn't overflow
+ int len = intermediate_result / 6;
+ if (do_padding) len = ((len + 3) / 4) * 4;
+ return len;
+}
+
+// Base64Escape does padding, so this calculation includes padding.
+int CalculateBase64EscapedLen(int input_len) {
+ return CalculateBase64EscapedLen(input_len, true);
+}
+
+// ----------------------------------------------------------------------
+// int Base64Unescape() - base64 decoder
+// int Base64Escape() - base64 encoder
+// int WebSafeBase64Unescape() - Google's variation of base64 decoder
+// int WebSafeBase64Escape() - Google's variation of base64 encoder
+//
+// Check out
+// http://www.cis.ohio-state.edu/htbin/rfc/rfc2045.html for formal
+// description, but what we care about is that...
+// Take the encoded stuff in groups of 4 characters and turn each
+// character into a code 0 to 63 thus:
+// A-Z map to 0 to 25
+// a-z map to 26 to 51
+// 0-9 map to 52 to 61
+// +(- for WebSafe) maps to 62
+// /(_ for WebSafe) maps to 63
+// There will be four numbers, all less than 64 which can be represented
+// by a 6 digit binary number (aaaaaa, bbbbbb, cccccc, dddddd respectively).
+// Arrange the 6 digit binary numbers into three bytes as such:
+// aaaaaabb bbbbcccc ccdddddd
+// Equals signs (one or two) are used at the end of the encoded block to
+// indicate that the text was not an integer multiple of three bytes long.
+// ----------------------------------------------------------------------
+
+int Base64UnescapeInternal(const char *src, int szsrc,
+ char *dest, int szdest,
+ const signed char* unbase64) {
+ static const char kPad64 = '=';
+
+ int decode = 0;
+ int destidx = 0;
+ int state = 0;
+ unsigned int ch = 0;
+ unsigned int temp = 0;
+
+ // The GET_INPUT macro gets the next input character, skipping
+ // over any whitespace, and stopping when we reach the end of the
+ // string or when we read any non-data character. The arguments are
+ // an arbitrary identifier (used as a label for goto) and the number
+ // of data bytes that must remain in the input to avoid aborting the
+ // loop.
+#define GET_INPUT(label, remain) \
+ label: \
+ --szsrc; \
+ ch = *src++; \
+ decode = unbase64[ch]; \
+ if (decode < 0) { \
+ if (ascii_isspace((char)ch) && szsrc >= remain) \
+ goto label; \
+ state = 4 - remain; \
+ break; \
+ }
+
+ // if dest is null, we're just checking to see if it's legal input
+ // rather than producing output. (I suspect this could just be done
+ // with a regexp...). We duplicate the loop so this test can be
+ // outside it instead of in every iteration.
+
+ if (dest) {
+ // This loop consumes 4 input bytes and produces 3 output bytes
+ // per iteration. We can't know at the start that there is enough
+ // data left in the string for a full iteration, so the loop may
+ // break out in the middle; if so 'state' will be set to the
+ // number of input bytes read.
+
+ while (szsrc >= 4) {
+ // We'll start by optimistically assuming that the next four
+ // bytes of the string (src[0..3]) are four good data bytes
+ // (that is, no nulls, whitespace, padding chars, or illegal
+ // chars). We need to test src[0..2] for nulls individually
+ // before constructing temp to preserve the property that we
+ // never read past a null in the string (no matter how long
+ // szsrc claims the string is).
+
+ if (!src[0] || !src[1] || !src[2] ||
+ (temp = ((unbase64[static_cast<int>(src[0])] << 18) |
+ (unbase64[static_cast<int>(src[1])] << 12) |
+ (unbase64[static_cast<int>(src[2])] << 6) |
+ (unbase64[static_cast<int>(src[3])]))) & 0x80000000) {
+ // Iff any of those four characters was bad (null, illegal,
+ // whitespace, padding), then temp's high bit will be set
+ // (because unbase64[] is -1 for all bad characters).
+ //
+ // We'll back up and resort to the slower decoder, which knows
+ // how to handle those cases.
+
+ GET_INPUT(first, 4);
+ temp = decode;
+ GET_INPUT(second, 3);
+ temp = (temp << 6) | decode;
+ GET_INPUT(third, 2);
+ temp = (temp << 6) | decode;
+ GET_INPUT(fourth, 1);
+ temp = (temp << 6) | decode;
+ } else {
+ // We really did have four good data bytes, so advance four
+ // characters in the string.
+
+ szsrc -= 4;
+ src += 4;
+ decode = -1;
+ ch = '\0';
+ }
+
+ // temp has 24 bits of input, so write that out as three bytes.
+
+ if (destidx+3 > szdest) return -1;
+ dest[destidx+2] = (char)temp;
+ temp >>= 8;
+ dest[destidx+1] = (char)temp;
+ temp >>= 8;
+ dest[destidx] = (char)temp;
+ destidx += 3;
+ }
+ } else {
+ while (szsrc >= 4) {
+ if (!src[0] || !src[1] || !src[2] ||
+ (temp = ((unbase64[static_cast<int>(src[0])] << 18) |
+ (unbase64[static_cast<int>(src[1])] << 12) |
+ (unbase64[static_cast<int>(src[2])] << 6) |
+ (unbase64[static_cast<int>(src[3])]))) & 0x80000000) {
+ GET_INPUT(first_no_dest, 4);
+ GET_INPUT(second_no_dest, 3);
+ GET_INPUT(third_no_dest, 2);
+ GET_INPUT(fourth_no_dest, 1);
+ } else {
+ szsrc -= 4;
+ src += 4;
+ decode = -1;
+ ch = '\0';
+ }
+ destidx += 3;
+ }
+ }
+
+#undef GET_INPUT
+
+ // if the loop terminated because we read a bad character, return
+ // now.
+ if (decode < 0 && ch != '\0' && ch != kPad64 && !ascii_isspace((char)ch))
+ return -1;
+
+ if (ch == kPad64) {
+ // if we stopped by hitting an '=', un-read that character -- we'll
+ // look at it again when we count to check for the proper number of
+ // equals signs at the end.
+ ++szsrc;
+ --src;
+ } else {
+ // This loop consumes 1 input byte per iteration. It's used to
+ // clean up the 0-3 input bytes remaining when the first, faster
+ // loop finishes. 'temp' contains the data from 'state' input
+ // characters read by the first loop.
+ while (szsrc > 0) {
+ --szsrc;
+ ch = *src++;
+ decode = unbase64[ch];
+ if (decode < 0) {
+ if (ascii_isspace((char)ch)) {
+ continue;
+ } else if (ch == '\0') {
+ break;
+ } else if (ch == kPad64) {
+ // back up one character; we'll read it again when we check
+ // for the correct number of equals signs at the end.
+ ++szsrc;
+ --src;
+ break;
+ } else {
+ return -1;
+ }
+ }
+
+ // Each input character gives us six bits of output.
+ temp = (temp << 6) | decode;
+ ++state;
+ if (state == 4) {
+ // If we've accumulated 24 bits of output, write that out as
+ // three bytes.
+ if (dest) {
+ if (destidx+3 > szdest) return -1;
+ dest[destidx+2] = (char)temp;
+ temp >>= 8;
+ dest[destidx+1] = (char)temp;
+ temp >>= 8;
+ dest[destidx] = (char)temp;
+ }
+ destidx += 3;
+ state = 0;
+ temp = 0;
+ }
+ }
+ }
+
+ // Process the leftover data contained in 'temp' at the end of the input.
+ int expected_equals = 0;
+ switch (state) {
+ case 0:
+ // Nothing left over; output is a multiple of 3 bytes.
+ break;
+
+ case 1:
+ // Bad input; we have 6 bits left over.
+ return -1;
+
+ case 2:
+ // Produce one more output byte from the 12 input bits we have left.
+ if (dest) {
+ if (destidx+1 > szdest) return -1;
+ temp >>= 4;
+ dest[destidx] = (char)temp;
+ }
+ ++destidx;
+ expected_equals = 2;
+ break;
+
+ case 3:
+ // Produce two more output bytes from the 18 input bits we have left.
+ if (dest) {
+ if (destidx+2 > szdest) return -1;
+ temp >>= 2;
+ dest[destidx+1] = (char)temp;
+ temp >>= 8;
+ dest[destidx] = (char)temp;
+ }
+ destidx += 2;
+ expected_equals = 1;
+ break;
+
+ default:
+ // state should have no other values at this point.
+ fprintf(stdout, "This can't happen; base64 decoder state = %d", state);
+ }
+
+ // The remainder of the string should be all whitespace, mixed with
+ // exactly 0 equals signs, or exactly 'expected_equals' equals
+ // signs. (Always accepting 0 equals signs is a google extension
+ // not covered in the RFC.)
+
+ int equals = 0;
+ while (szsrc > 0 && *src) {
+ if (*src == kPad64)
+ ++equals;
+ else if (!ascii_isspace(*src))
+ return -1;
+ --szsrc;
+ ++src;
+ }
+
+ return (equals == 0 || equals == expected_equals) ? destidx : -1;
+}
+
+int Base64Unescape(const char *src, int szsrc, char *dest, int szdest) {
+ static const signed char UnBase64[] = {
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 62/*+*/, -1, -1, -1, 63/*/ */,
+ 52/*0*/, 53/*1*/, 54/*2*/, 55/*3*/, 56/*4*/, 57/*5*/, 58/*6*/, 59/*7*/,
+ 60/*8*/, 61/*9*/, -1, -1, -1, -1, -1, -1,
+ -1, 0/*A*/, 1/*B*/, 2/*C*/, 3/*D*/, 4/*E*/, 5/*F*/, 6/*G*/,
+ 7/*H*/, 8/*I*/, 9/*J*/, 10/*K*/, 11/*L*/, 12/*M*/, 13/*N*/, 14/*O*/,
+ 15/*P*/, 16/*Q*/, 17/*R*/, 18/*S*/, 19/*T*/, 20/*U*/, 21/*V*/, 22/*W*/,
+ 23/*X*/, 24/*Y*/, 25/*Z*/, -1, -1, -1, -1, -1,
+ -1, 26/*a*/, 27/*b*/, 28/*c*/, 29/*d*/, 30/*e*/, 31/*f*/, 32/*g*/,
+ 33/*h*/, 34/*i*/, 35/*j*/, 36/*k*/, 37/*l*/, 38/*m*/, 39/*n*/, 40/*o*/,
+ 41/*p*/, 42/*q*/, 43/*r*/, 44/*s*/, 45/*t*/, 46/*u*/, 47/*v*/, 48/*w*/,
+ 49/*x*/, 50/*y*/, 51/*z*/, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1
+ };
+ // The above array was generated by the following code
+ // #include <sys/time.h>
+ // #include <stdlib.h>
+ // #include <string.h>
+ // main()
+ // {
+ // static const char Base64[] =
+ // "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+ // char *pos;
+ // int idx, i, j;
+ // printf(" ");
+ // for (i = 0; i < 255; i += 8) {
+ // for (j = i; j < i + 8; j++) {
+ // pos = strchr(Base64, j);
+ // if ((pos == NULL) || (j == 0))
+ // idx = -1;
+ // else
+ // idx = pos - Base64;
+ // if (idx == -1)
+ // printf(" %2d, ", idx);
+ // else
+ // printf(" %2d/*%c*/,", idx, j);
+ // }
+ // printf("\n ");
+ // }
+ // }
+
+ return Base64UnescapeInternal(src, szsrc, dest, szdest, UnBase64);
+}
+
+bool Base64Unescape(const char *src, int slen, string* dest) {
+ // Determine the size of the output string. Base64 encodes every 3 bytes into
+ // 4 characters. any leftover chars are added directly for good measure.
+ // This is documented in the base64 RFC: http://www.ietf.org/rfc/rfc3548.txt
+ const int dest_len = 3 * (slen / 4) + (slen % 4);
+
+ dest->resize(dest_len);
+
+ // We are getting the destination buffer by getting the beginning of the
+ // string and converting it into a char *.
+ const int len = Base64Unescape(src, slen,
+ string_as_array(dest), dest->size());
+ if (len < 0) {
+ return false;
+ }
+
+ // could be shorter if there was padding
+ assert(len <= dest_len);
+ dest->resize(len);
+
+ return true;
+}
+
+// Base64Escape
+//
+// NOTE: We have to use an unsigned type for src because code built
+// in the the /google tree treats characters as signed unless
+// otherwised specified.
+//
+// TODO(who?): Move this function to use the char* type for "src"
+int Base64EscapeInternal(const unsigned char *src, int szsrc,
+ char *dest, int szdest, const char *base64,
+ bool do_padding) {
+ static const char kPad64 = '=';
+
+ if (szsrc <= 0) return 0;
+
+ char *cur_dest = dest;
+ const unsigned char *cur_src = src;
+
+ // Three bytes of data encodes to four characters of cyphertext.
+ // So we can pump through three-byte chunks atomically.
+ while (szsrc > 2) { /* keep going until we have less than 24 bits */
+ if ((szdest -= 4) < 0) return 0;
+ cur_dest[0] = base64[cur_src[0] >> 2];
+ cur_dest[1] = base64[((cur_src[0] & 0x03) << 4) + (cur_src[1] >> 4)];
+ cur_dest[2] = base64[((cur_src[1] & 0x0f) << 2) + (cur_src[2] >> 6)];
+ cur_dest[3] = base64[cur_src[2] & 0x3f];
+
+ cur_dest += 4;
+ cur_src += 3;
+ szsrc -= 3;
+ }
+
+ /* now deal with the tail (<=2 bytes) */
+ switch (szsrc) {
+ case 0:
+ // Nothing left; nothing more to do.
+ break;
+ case 1:
+ // One byte left: this encodes to two characters, and (optionally)
+ // two pad characters to round out the four-character cypherblock.
+ if ((szdest -= 2) < 0) return 0;
+ cur_dest[0] = base64[cur_src[0] >> 2];
+ cur_dest[1] = base64[(cur_src[0] & 0x03) << 4];
+ cur_dest += 2;
+ if (do_padding) {
+ if ((szdest -= 2) < 0) return 0;
+ cur_dest[0] = kPad64;
+ cur_dest[1] = kPad64;
+ cur_dest += 2;
+ }
+ break;
+ case 2:
+ // Two bytes left: this encodes to three characters, and (optionally)
+ // one pad character to round out the four-character cypherblock.
+ if ((szdest -= 3) < 0) return 0;
+ cur_dest[0] = base64[cur_src[0] >> 2];
+ cur_dest[1] = base64[((cur_src[0] & 0x03) << 4) + (cur_src[1] >> 4)];
+ cur_dest[2] = base64[(cur_src[1] & 0x0f) << 2];
+ cur_dest += 3;
+ if (do_padding) {
+ if ((szdest -= 1) < 0) return 0;
+ cur_dest[0] = kPad64;
+ cur_dest += 1;
+ }
+ break;
+ default:
+ // Should not be reached: blocks of 3 bytes are handled
+ // in the while loop before this switch statement.
+ fprintf(stderr, "Logic problem? szsrc = %d", szsrc);
+ assert(false);
+ break;
+ }
+ return (cur_dest - dest);
+}
+
+static const char kBase64Chars[] =
+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+static const char kWebSafeBase64Chars[] =
+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
+
+int Base64Escape(const unsigned char *src, int szsrc, char *dest, int szdest) {
+ return Base64EscapeInternal(src, szsrc, dest, szdest, kBase64Chars, true);
+}
+
+void Base64Escape(const unsigned char *src, int szsrc,
+ string* dest, bool do_padding) {
+ const int max_escaped_size =
+ CalculateBase64EscapedLen(szsrc, do_padding);
+ dest->clear();
+ dest->resize(max_escaped_size + 1, '\0');
+ const int escaped_len = Base64EscapeInternal(src, szsrc,
+ &*dest->begin(), dest->size(),
+ kBase64Chars,
+ do_padding);
+ assert(max_escaped_size <= escaped_len);
+ dest->resize(escaped_len);
+}
+
+void Base64Escape(const string& src, string* dest) {
+ Base64Escape(reinterpret_cast<const unsigned char*>(src.c_str()),
+ src.size(), dest, true);
+}
+
+////////////////////////////////////////////////////
+// WebSafe methods
+////////////////////////////////////////////////////
+
+int WebSafeBase64Unescape(const char *src, int szsrc, char *dest, int szdest) {
+ static const signed char UnBase64[] = {
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 62/*-*/, -1, -1,
+ 52/*0*/, 53/*1*/, 54/*2*/, 55/*3*/, 56/*4*/, 57/*5*/, 58/*6*/, 59/*7*/,
+ 60/*8*/, 61/*9*/, -1, -1, -1, -1, -1, -1,
+ -1, 0/*A*/, 1/*B*/, 2/*C*/, 3/*D*/, 4/*E*/, 5/*F*/, 6/*G*/,
+ 7/*H*/, 8/*I*/, 9/*J*/, 10/*K*/, 11/*L*/, 12/*M*/, 13/*N*/, 14/*O*/,
+ 15/*P*/, 16/*Q*/, 17/*R*/, 18/*S*/, 19/*T*/, 20/*U*/, 21/*V*/, 22/*W*/,
+ 23/*X*/, 24/*Y*/, 25/*Z*/, -1, -1, -1, -1, 63/*_*/,
+ -1, 26/*a*/, 27/*b*/, 28/*c*/, 29/*d*/, 30/*e*/, 31/*f*/, 32/*g*/,
+ 33/*h*/, 34/*i*/, 35/*j*/, 36/*k*/, 37/*l*/, 38/*m*/, 39/*n*/, 40/*o*/,
+ 41/*p*/, 42/*q*/, 43/*r*/, 44/*s*/, 45/*t*/, 46/*u*/, 47/*v*/, 48/*w*/,
+ 49/*x*/, 50/*y*/, 51/*z*/, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1
+ };
+ // The above array was generated by the following code
+ // #include <sys/time.h>
+ // #include <stdlib.h>
+ // #include <string.h>
+ // main()
+ // {
+ // static const char Base64[] =
+ // "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
+ // char *pos;
+ // int idx, i, j;
+ // printf(" ");
+ // for (i = 0; i < 255; i += 8) {
+ // for (j = i; j < i + 8; j++) {
+ // pos = strchr(Base64, j);
+ // if ((pos == NULL) || (j == 0))
+ // idx = -1;
+ // else
+ // idx = pos - Base64;
+ // if (idx == -1)
+ // printf(" %2d, ", idx);
+ // else
+ // printf(" %2d/*%c*/,", idx, j);
+ // }
+ // printf("\n ");
+ // }
+ // }
+
+ return Base64UnescapeInternal(src, szsrc, dest, szdest, UnBase64);
+}
+
+bool WebSafeBase64Unescape(const char *src, int slen, string* dest) {
+ int dest_len = 3 * (slen / 4) + (slen % 4);
+ dest->clear();
+ dest->resize(dest_len);
+ int len = WebSafeBase64Unescape(src, slen, &*dest->begin(), dest->size());
+ if (len < 0) {
+ dest->clear();
+ return false;
+ }
+ // could be shorter if there was padding
+ assert(len <= dest_len);
+ dest->resize(len);
+ return true;
+}
+
+bool WebSafeBase64Unescape(const string& src, string* dest) {
+ return WebSafeBase64Unescape(src.data(), src.size(), dest);
+}
+
+int WebSafeBase64Escape(const unsigned char *src, int szsrc, char *dest,
+ int szdest, bool do_padding) {
+ return Base64EscapeInternal(src, szsrc, dest, szdest,
+ kWebSafeBase64Chars, do_padding);
+}
+
+void WebSafeBase64Escape(const unsigned char *src, int szsrc,
+ string *dest, bool do_padding) {
+ const int max_escaped_size =
+ CalculateBase64EscapedLen(szsrc, do_padding);
+ dest->clear();
+ dest->resize(max_escaped_size + 1, '\0');
+ const int escaped_len = Base64EscapeInternal(src, szsrc,
+ &*dest->begin(), dest->size(),
+ kWebSafeBase64Chars,
+ do_padding);
+ assert(max_escaped_size <= escaped_len);
+ dest->resize(escaped_len);
+}
+
+void WebSafeBase64EscapeInternal(const string& src,
+ string* dest,
+ bool do_padding) {
+ int encoded_len = CalculateBase64EscapedLen(src.size());
+ scoped_array<char> buf(new char[encoded_len]);
+ int len = WebSafeBase64Escape(reinterpret_cast<const unsigned char*>(src.c_str()),
+ src.size(), buf.get(),
+ encoded_len, do_padding);
+ dest->assign(buf.get(), len);
+}
+
+void WebSafeBase64Escape(const string& src, string* dest) {
+ WebSafeBase64EscapeInternal(src, dest, false);
+}
+
+void WebSafeBase64EscapeWithPadding(const string& src, string* dest) {
+ WebSafeBase64EscapeInternal(src, dest, true);
+}
+
+} // namespace strings
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/escaping.h b/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/escaping.h
new file mode 100644
index 0000000000..c8aa90b7b2
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/escaping.h
@@ -0,0 +1,99 @@
+// Copyright 2019 Google Inc. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Base64 escaping methods to encode/decode strings.
+
+#ifndef TOOLS_WINDOWS_CONVERTER_EXE_ESCAPING_H_
+#define TOOLS_WINDOWS_CONVERTER_EXE_ESCAPING_H_
+
+#include <string>
+
+namespace strings {
+
+using std::string;
+
+// ----------------------------------------------------------------------
+// Base64Escape()
+// WebSafeBase64Escape()
+// Encode "src" to "dest" using base64 encoding.
+// src is not null terminated, instead specify len.
+// 'dest' should have at least CalculateBase64EscapedLen() length.
+// RETURNS the length of dest.
+// The WebSafe variation use '-' instead of '+' and '_' instead of '/'
+// so that we can place the out in the URL or cookies without having
+// to escape them. It also has an extra parameter "do_padding",
+// which when set to false will prevent padding with "=".
+// ----------------------------------------------------------------------
+void Base64Escape(const string& src, string* dest);
+int Base64Escape(const unsigned char* src, int slen, char* dest, int szdest);
+// Encode src into dest with padding.
+void Base64Escape(const unsigned char* src, int szsrc,
+ string* dest, bool do_padding);
+
+int WebSafeBase64Escape(const unsigned char* src, int slen, char* dest,
+ int szdest, bool do_padding);
+// Encode src into dest web-safely without padding.
+void WebSafeBase64Escape(const string& src, string* dest);
+// Encode src into dest web-safely with padding.
+void WebSafeBase64EscapeWithPadding(const string& src, string* dest);
+void WebSafeBase64Escape(const unsigned char* src, int szsrc,
+ string* dest, bool do_padding);
+
+// ----------------------------------------------------------------------
+// Base64Unescape()
+// WebSafeBase64Unescape()
+// Copies "src" to "dest", where src is in base64 and is written to its
+// ASCII equivalents. src is not null terminated, instead specify len.
+// I recommend that slen<szdest, but we honor szdest anyway.
+// RETURNS the length of dest, or -1 if src contains invalid chars.
+// The WebSafe variation use '-' instead of '+' and '_' instead of '/'.
+// The variations that store into a string clear the string first, and
+// return false (with dest empty) if src contains invalid chars; for
+// these versions src and dest must be different strings.
+// ----------------------------------------------------------------------
+int Base64Unescape(const char* src, int slen, char* dest, int szdest);
+bool Base64Unescape(const char* src, int slen, string* dest);
+inline bool Base64Unescape(const string& src, string* dest) {
+ return Base64Unescape(src.data(), src.size(), dest);
+}
+
+
+int WebSafeBase64Unescape(const char* src, int slen, char* dest, int szdest);
+bool WebSafeBase64Unescape(const char* src, int slen, string* dest);
+bool WebSafeBase64Unescape(const string& src, string* dest);
+
+// Return the length to use for the output buffer given to the base64 escape
+// routines. Make sure to use the same value for do_padding in both.
+// This function may return incorrect results if given input_len values that
+// are extremely high, which should happen rarely.
+int CalculateBase64EscapedLen(int input_len, bool do_padding);
+// Use this version when calling Base64Escape without a do_padding arg.
+int CalculateBase64EscapedLen(int input_len);
+} // namespace strings
+
+#endif // TOOLS_WINDOWS_CONVERTER_EXE_ESCAPING_H_
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/http_client.h b/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/http_client.h
new file mode 100644
index 0000000000..3e7aa8a764
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/http_client.h
@@ -0,0 +1,96 @@
+// Copyright 2019 Google Inc. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef TOOLS_CRASH_CONVERTER_WINDOWS_HTTP_CLIENT_H_
+#define TOOLS_CRASH_CONVERTER_WINDOWS_HTTP_CLIENT_H_
+
+#include <tchar.h>
+#include <windows.h>
+#include <vector>
+
+typedef void* HttpHandle;
+
+namespace crash {
+
+// HttpClient provides an abstract layer for HTTP APIs. The actual
+// implementation can be based on either WinHttp or WinInet.
+class HttpClient {
+ public:
+ enum AccessType {
+ ACCESS_TYPE_PRECONFIG,
+ ACCESS_TYPE_DIRECT,
+ ACCESS_TYPE_PROXY,
+ };
+
+ virtual ~HttpClient() {}
+
+ virtual bool CrackUrl(const TCHAR* url,
+ DWORD flags,
+ TCHAR* scheme,
+ size_t scheme_buffer_length,
+ TCHAR* host,
+ size_t host_buffer_length,
+ TCHAR* uri,
+ size_t uri_buffer_length,
+ int* port) const = 0;
+ virtual bool Open(const TCHAR* user_agent,
+ DWORD access_type,
+ const TCHAR* proxy_name,
+ const TCHAR* proxy_bypass,
+ HttpHandle* session_handle) const = 0;
+ virtual bool Connect(HttpHandle session_handle,
+ const TCHAR* server,
+ int port,
+ HttpHandle* connection_handle) const = 0;
+ virtual bool OpenRequest(HttpHandle connection_handle,
+ const TCHAR* verb,
+ const TCHAR* uri,
+ const TCHAR* version,
+ const TCHAR* referrer,
+ bool is_secure,
+ HttpHandle* request_handle) const = 0;
+ virtual bool SendRequest(HttpHandle request_handle,
+ const TCHAR* headers,
+ DWORD headers_length) const = 0;
+ virtual bool ReceiveResponse(HttpHandle request_handle) const = 0;
+ virtual bool GetHttpStatusCode(HttpHandle request_handle,
+ int* status_code) const = 0;
+ virtual bool GetContentLength(HttpHandle request_handle,
+ DWORD* content_length) const = 0;
+ virtual bool ReadData(HttpHandle request_handle,
+ void* buffer,
+ DWORD buffer_length,
+ DWORD* bytes_read) const = 0;
+ virtual bool Close(HttpHandle handle) const = 0;
+
+ static const DWORD kUnknownContentLength = (DWORD)-1;
+};
+
+} // namespace crash
+
+#endif // TOOLS_CRASH_CONVERTER_WINDOWS_HTTP_CLIENT_H_
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/http_download.cc b/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/http_download.cc
new file mode 100644
index 0000000000..5afc1ccc14
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/http_download.cc
@@ -0,0 +1,326 @@
+// Copyright 2019 Google Inc. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <assert.h>
+#include <stdio.h>
+#include <Windows.h>
+#include <WinInet.h>
+
+#include <vector>
+
+#include "tools/windows/converter_exe/http_download.h"
+#include "tools/windows/converter_exe/winhttp_client.h"
+#include "tools/windows/converter_exe/wininet_client.h"
+
+namespace crash {
+static const std::vector<char>::size_type kVectorChunkSize = 4096; // 4 KB
+
+using std::vector;
+
+// Class that atuo closes the contained HttpHandle when the object
+// goes out of scope.
+class AutoHttpHandle {
+ public:
+ AutoHttpHandle() : handle_(NULL) {}
+ explicit AutoHttpHandle(HttpHandle handle) : handle_(handle) {}
+ ~AutoHttpHandle() {
+ if (handle_) {
+ InternetCloseHandle(handle_);
+ }
+ }
+
+ HttpHandle get() { return handle_; }
+ HttpHandle* get_handle_addr () { return &handle_; }
+
+ private:
+ HttpHandle handle_;
+};
+
+// Template class for auto releasing the contained pointer when
+// the object goes out of scope.
+template<typename T>
+class AutoPtr {
+ public:
+ explicit AutoPtr(T* ptr) : ptr_(ptr) {}
+ ~AutoPtr() {
+ if (ptr_) {
+ delete ptr_;
+ }
+ }
+
+ T* get() { return ptr_; }
+ T* operator -> () { return ptr_; }
+
+ private:
+ T* ptr_;
+};
+
+// CheckParameters ensures that the parameters in |parameters| are safe for
+// use in an HTTP URL. Returns true if they are, false if unsafe characters
+// are present.
+static bool CheckParameters(const map<wstring, wstring> *parameters) {
+ for (map<wstring, wstring>::const_iterator iterator = parameters->begin();
+ iterator != parameters->end();
+ ++iterator) {
+ const wstring &key = iterator->first;
+ if (key.empty()) {
+ // Disallow empty parameter names.
+ return false;
+ }
+ for (unsigned int i = 0; i < key.size(); ++i) {
+ wchar_t c = key[i];
+ if (c < 32 || c == '"' || c == '?' || c == '&' || c > 127) {
+ return false;
+ }
+ }
+
+ const wstring &value = iterator->second;
+ for (unsigned int i = 0; i < value.size(); ++i) {
+ wchar_t c = value[i];
+ if (c < 32 || c == '"' || c == '?' || c == '&' || c > 127) {
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+HttpClient* HTTPDownload::CreateHttpClient(const wchar_t* url) {
+ const TCHAR* kHttpApiPolicyEnvironmentVariable = TEXT("USE_WINHTTP");
+ TCHAR buffer[2] = {0};
+ HttpClient* http_client = NULL;
+
+ if (::GetEnvironmentVariable(kHttpApiPolicyEnvironmentVariable,
+ buffer,
+ sizeof(buffer)/sizeof(buffer[0])) > 0) {
+ fprintf(stdout,
+ "Environment variable [%ws] is set, use WinHttp\n",
+ kHttpApiPolicyEnvironmentVariable);
+ http_client = CreateWinHttpClient(url);
+ if (http_client == NULL) {
+ fprintf(stderr, "WinHttpClient not created, Is the protocol HTTPS? "
+ "Fall back to WinInet API.\n");
+ }
+ } else {
+ fprintf(stderr,
+ "Environment variable [%ws] is NOT set, use WinInet API\n",
+ kHttpApiPolicyEnvironmentVariable);
+ }
+
+ if (http_client == NULL) {
+ return CreateWinInetClient(url);
+ }
+
+ return http_client;
+}
+
+// static
+bool HTTPDownload::Download(const wstring &url,
+ const map<wstring, wstring> *parameters,
+ string *content, int *status_code) {
+ assert(content);
+ AutoPtr<HttpClient> http_client(CreateHttpClient(url.c_str()));
+
+ if (!http_client.get()) {
+ fprintf(stderr, "Failed to create any http client.\n");
+ return false;
+ }
+
+ if (status_code) {
+ *status_code = 0;
+ }
+
+ wchar_t scheme[16] = {0};
+ wchar_t host[256] = {0};
+ wchar_t path[256] = {0};
+ int port = 0;
+ if (!http_client->CrackUrl(url.c_str(),
+ 0,
+ scheme,
+ sizeof(scheme)/sizeof(scheme[0]),
+ host,
+ sizeof(host)/sizeof(host[0]),
+ path,
+ sizeof(path)/sizeof(path[0]),
+ &port)) {
+ fprintf(stderr,
+ "HTTPDownload::Download: InternetCrackUrl: error %lu for %ws\n",
+ GetLastError(), url.c_str());
+ return false;
+ }
+
+ bool secure = false;
+ if (_wcsicmp(scheme, L"https") == 0) {
+ secure = true;
+ } else if (wcscmp(scheme, L"http") != 0) {
+ fprintf(stderr,
+ "HTTPDownload::Download: scheme must be http or https for %ws\n",
+ url.c_str());
+ return false;
+ }
+
+ AutoHttpHandle internet;
+ if (!http_client->Open(NULL, // user agent
+ HttpClient::ACCESS_TYPE_PRECONFIG,
+ NULL, // proxy name
+ NULL, // proxy bypass
+ internet.get_handle_addr())) {
+ fprintf(stderr,
+ "HTTPDownload::Download: Open: error %lu for %ws\n",
+ GetLastError(), url.c_str());
+ return false;
+ }
+
+ AutoHttpHandle connection;
+ if (!http_client->Connect(internet.get(),
+ host,
+ port,
+ connection.get_handle_addr())) {
+ fprintf(stderr,
+ "HTTPDownload::Download: InternetConnect: error %lu for %ws\n",
+ GetLastError(), url.c_str());
+ return false;
+ }
+
+ wstring request_string = path;
+ if (parameters) {
+ // TODO(mmentovai): escape bad characters in parameters instead of
+ // forbidding them.
+ if (!CheckParameters(parameters)) {
+ fprintf(stderr,
+ "HTTPDownload::Download: invalid characters in parameters\n");
+ return false;
+ }
+
+ bool added_parameter = false;
+ for (map<wstring, wstring>::const_iterator iterator = parameters->begin();
+ iterator != parameters->end();
+ ++iterator) {
+ request_string.append(added_parameter ? L"&" : L"?");
+ request_string.append(iterator->first);
+ request_string.append(L"=");
+ request_string.append(iterator->second);
+ added_parameter = true;
+ }
+ }
+
+ AutoHttpHandle request;
+ if (!http_client->OpenRequest(connection.get(),
+ L"GET",
+ request_string.c_str(),
+ NULL, // version
+ NULL, // referer
+ secure,
+ request.get_handle_addr())) {
+ fprintf(stderr,
+ "HttpClient::OpenRequest: error %lu for %ws, request: %ws\n",
+ GetLastError(), url.c_str(), request_string.c_str());
+ return false;
+ }
+
+ if (!http_client->SendRequest(request.get(), NULL, 0)) {
+ fprintf(stderr,
+ "HttpClient::SendRequest: error %lu for %ws\n",
+ GetLastError(), url.c_str());
+ return false;
+ }
+
+ if (!http_client->ReceiveResponse(request.get())) {
+ fprintf(stderr,
+ "HttpClient::ReceiveResponse: error %lu for %ws\n",
+ GetLastError(), url.c_str());
+ return false;
+ }
+
+ int http_status = 0;
+ if (!http_client->GetHttpStatusCode(request.get(), &http_status)) {
+ fprintf(stderr,
+ "HttpClient::GetHttpStatusCode: error %lu for %ws\n",
+ GetLastError(), url.c_str());
+ return false;
+ }
+ if (http_status != 200) {
+ fprintf(stderr,
+ "HTTPDownload::Download: HTTP status code %d for %ws\n",
+ http_status, url.c_str());
+ return false;
+ }
+
+ DWORD content_length = 0;
+ vector<char>::size_type buffer_size = 0;
+ http_client->GetContentLength(request.get(), &content_length);
+ if (content_length == HttpClient::kUnknownContentLength) {
+ buffer_size = kVectorChunkSize;
+ } else {
+ buffer_size = content_length;
+ }
+
+ if (content_length != 0) {
+ vector<char> response_buffer = vector<char>(buffer_size+1);
+ DWORD size_read;
+ DWORD total_read = 0;
+ bool read_result;
+ do {
+ if (content_length == HttpClient::kUnknownContentLength
+ && buffer_size == total_read) {
+ // The content length wasn't specified in the response header, so we
+ // have to keep growing the buffer until we're done reading.
+ buffer_size += kVectorChunkSize;
+ response_buffer.resize(buffer_size);
+ }
+ read_result = !!http_client->ReadData(
+ request.get(),
+ &response_buffer[total_read],
+ static_cast<DWORD>(buffer_size) - total_read,
+ &size_read);
+ total_read += size_read;
+ } while (read_result && (size_read != 0));
+
+ if (!read_result) {
+ fprintf(stderr,
+ "HttpClient::ReadData: error %lu for %ws\n",
+ GetLastError(),
+ url.c_str());
+ return false;
+ } else if (size_read != 0) {
+ fprintf(stderr,
+ "HttpClient::ReadData: error %lu/%lu for %ws\n",
+ total_read,
+ content_length,
+ url.c_str());
+ return false;
+ }
+ content->assign(&response_buffer[0], total_read);
+ } else {
+ content->clear();
+ }
+ return true;
+}
+
+} // namespace crash
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/http_download.h b/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/http_download.h
new file mode 100644
index 0000000000..2d705d5ece
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/http_download.h
@@ -0,0 +1,62 @@
+// Copyright 2019 Google Inc. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef TOOLS_WINDOWS_CONVERTER_EXE_HTTP_DOWNLOAD_H_
+#define TOOLS_WINDOWS_CONVERTER_EXE_HTTP_DOWNLOAD_H_
+
+#include <map>
+#include <string>
+#include "tools/windows/converter_exe/winhttp_client.h"
+
+namespace crash {
+
+using std::map;
+using std::string;
+using std::wstring;
+
+class HTTPDownload {
+ public:
+ // Retrieves the resource located at |url|, a http or https URL, via WinInet.
+ // The request is fetched with GET request; the optional |parameters| are
+ // appended to the URL. Returns true on success, placing the content of the
+ // retrieved resource in |content|. Returns false on failure. HTTP status
+ // codes other than 200 cause Download to return false. If |status_code| is
+ // supplied, it will be set to the value of the HTTP status code, if an HTTP
+ // transaction occurs. If Download fails before a transaction can occur,
+ // |status_code| will be set to 0. Any failures will result in messages
+ // being printed to stderr.
+ static bool Download(const wstring &url,
+ const map<wstring, wstring> *parameters,
+ string *content, int *status_code);
+ private:
+ static HttpClient* CreateHttpClient(const wchar_t*);
+};
+
+} // namespace crash
+
+#endif // TOOLS_WINDOWS_CONVERTER_EXE_HTTP_DOWNLOAD_H_
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/missing_symbols_test.txt b/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/missing_symbols_test.txt
new file mode 100644
index 0000000000..91641fca96
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/missing_symbols_test.txt
@@ -0,0 +1,5 @@
+msctf.pdb|6A5BABB8E88644C696530BFE3C90F32F2|6.1.7600.16385|msctf.dll|4A5BDFAA109000
+imm32.pdb|98F27BA5AEE541ECBEE00CD03AD50FEE2|6.1.7600.16385|imm32.dll|4A5BDF402e000
+amd_opencl64.pdb|3D306D0FCCB14F47AF322A5ACDF5EEA81||amd_opencl64.dll|587901FB1E000
+igd10iumd64.pdb|B2B72475BB0846D8ADE4344FAE0CCE361 ||igd10iumd64.dll|568D69FBD99000
+NvCameraWhitelisting64.pdb|3C364C4D3FBF4180B021D52D469C6DAB1||NvCameraWhitelisting64.dll|5B8ED23485000 \ No newline at end of file
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/symsrv.yes b/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/symsrv.yes
new file mode 100644
index 0000000000..1d01dda71b
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/symsrv.yes
@@ -0,0 +1,2 @@
+See breakpad/tools/windows/converter/ms_symbol_server_converter.h for a
+description of this file's function.
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/tokenizer.cc b/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/tokenizer.cc
new file mode 100644
index 0000000000..992694cd0c
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/tokenizer.cc
@@ -0,0 +1,61 @@
+// Copyright 2019 Google Inc. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <assert.h>
+
+#include "tools/windows/converter_exe/tokenizer.h"
+
+namespace crash {
+
+// static
+void Tokenizer::Tokenize(const string &delimiters, const string &input,
+ vector<string> *output) {
+ assert(output);
+ output->clear();
+
+ string::size_type position = 0; // Where to begin looking for a delimiter
+ string::size_type new_position; // Position of found delimiter
+ string token;
+
+ while ((new_position = input.find_first_of(delimiters, position)) !=
+ string::npos) {
+ token = input.substr(position, new_position - position);
+ output->push_back(token);
+
+ // Next time, begin looking right after this delimiter.
+ position = new_position + 1;
+ }
+
+ // There are no more delimiters in the string. Take everything from the
+ // final delimiter up to the end of the string as a token. This may be
+ // an empty string.
+ token = input.substr(position);
+ output->push_back(token);
+}
+
+} // namespace crash
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/tokenizer.h b/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/tokenizer.h
new file mode 100644
index 0000000000..f4bbcfd0e8
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/tokenizer.h
@@ -0,0 +1,51 @@
+// Copyright 2019 Google Inc. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef TOOLS_WINDOWS_CONVERTER_EXE_TOKENIZER_H_
+#define TOOLS_WINDOWS_CONVERTER_EXE_TOKENIZER_H_
+
+#include <string>
+#include <vector>
+
+namespace crash {
+
+using std::string;
+using std::vector;
+
+class Tokenizer {
+ public:
+ // Splits |input| into a series of tokens delimited in the input string by
+ // any of the characters in |delimiters|. The tokens are passed back in the
+ // |output| vector.
+ static void Tokenize(const string &delimiters, const string &input,
+ vector<string> *output);
+};
+
+} // namespace crash
+
+#endif // TOOLS_WINDOWS_CONVERTER_EXE_TOKENIZER_H_
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/winhttp_client.cc b/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/winhttp_client.cc
new file mode 100644
index 0000000000..8a8ade3b6c
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/winhttp_client.cc
@@ -0,0 +1,307 @@
+// Copyright 2019 Google Inc. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "tools/windows/converter_exe/winhttp_client.h"
+
+#include <assert.h>
+#include <stdlib.h>
+#include <windows.h>
+#include <winhttp.h>
+#include <vector>
+
+namespace crash {
+
+namespace internal {
+
+// This class implements HttpClient based on WinInet APIs.
+class WinHttpClient : public HttpClient {
+ public:
+ virtual ~WinHttpClient() {}
+ virtual bool CrackUrl(const TCHAR* url,
+ DWORD flags,
+ TCHAR* scheme,
+ size_t scheme_buffer_length,
+ TCHAR* host,
+ size_t host_buffer_length,
+ TCHAR* uri,
+ size_t uri_buffer_length,
+ int* port) const;
+ virtual bool Open(const TCHAR* user_agent,
+ DWORD access_type,
+ const TCHAR* proxy_name,
+ const TCHAR* proxy_bypass,
+ HttpHandle* session_handle) const;
+ virtual bool Connect(HttpHandle session_handle,
+ const TCHAR* server,
+ int port,
+ HttpHandle* connection_handle) const;
+ virtual bool OpenRequest(HttpHandle connection_handle,
+ const TCHAR* verb,
+ const TCHAR* uri,
+ const TCHAR* version,
+ const TCHAR* referrer,
+ bool is_secure,
+ HttpHandle* request_handle) const;
+ virtual bool SendRequest(HttpHandle request_handle,
+ const TCHAR* headers,
+ DWORD headers_length) const;
+ virtual bool ReceiveResponse(HttpHandle request_handle) const;
+ virtual bool GetHttpStatusCode(HttpHandle request_handle,
+ int* status_code) const;
+ virtual bool GetContentLength(HttpHandle request_handle,
+ DWORD* content_length) const;
+ virtual bool ReadData(HttpHandle request_handle,
+ void* buffer,
+ DWORD buffer_length,
+ DWORD* bytes_read) const;
+ virtual bool Close(HttpHandle handle) const;
+
+ private:
+ static DWORD MapAccessType(DWORD access_type);
+ static HINTERNET ToHINTERNET(HttpHandle handle);
+ static HttpHandle FromHINTERNET(HINTERNET handle);
+};
+
+bool WinHttpClient::CrackUrl(const TCHAR* url,
+ DWORD flags,
+ TCHAR* scheme,
+ size_t scheme_buffer_length,
+ TCHAR* host,
+ size_t host_buffer_length,
+ TCHAR* uri,
+ size_t uri_buffer_length,
+ int* port) const {
+ assert(url);
+ assert(scheme);
+ assert(host);
+ assert(uri);
+ assert(port);
+
+ URL_COMPONENTS url_comp = {0};
+ url_comp.dwStructSize = sizeof(url_comp);
+ url_comp.lpszScheme = scheme;
+ url_comp.dwSchemeLength = static_cast<DWORD>(scheme_buffer_length);
+ url_comp.lpszHostName = host;
+ url_comp.dwHostNameLength = static_cast<DWORD>(host_buffer_length);
+ url_comp.lpszUrlPath = uri;
+ url_comp.dwUrlPathLength = static_cast<DWORD>(uri_buffer_length);
+
+ bool result = !!::WinHttpCrackUrl(url, 0, flags, &url_comp);
+ if (result) {
+ *port = static_cast<int>(url_comp.nPort);
+ }
+ return result;
+}
+
+bool WinHttpClient::Open(const TCHAR* user_agent,
+ DWORD access_type,
+ const TCHAR* proxy_name,
+ const TCHAR* proxy_bypass,
+ HttpHandle* session_handle) const {
+ *session_handle = FromHINTERNET(::WinHttpOpen(user_agent,
+ MapAccessType(access_type),
+ proxy_name,
+ proxy_bypass,
+ 0));
+
+ return !!(*session_handle);
+}
+
+bool WinHttpClient::Connect(HttpHandle session_handle,
+ const TCHAR* server,
+ int port,
+ HttpHandle* connection_handle) const {
+ assert(server);
+
+ // Uses NULL user name and password to connect.
+ *connection_handle = FromHINTERNET(::WinHttpConnect(
+ ToHINTERNET(session_handle),
+ server,
+ static_cast<INTERNET_PORT>(port),
+ NULL));
+ return !!(*connection_handle);
+}
+
+bool WinHttpClient::OpenRequest(HttpHandle connection_handle,
+ const TCHAR* verb,
+ const TCHAR* uri,
+ const TCHAR* version,
+ const TCHAR* referrer,
+ bool is_secure,
+ HttpHandle* request_handle) const {
+ assert(connection_handle);
+ assert(verb);
+ assert(uri);
+ assert(request_handle);
+
+ *request_handle = FromHINTERNET(::WinHttpOpenRequest(
+ ToHINTERNET(connection_handle),
+ verb,
+ uri,
+ version,
+ referrer,
+ WINHTTP_DEFAULT_ACCEPT_TYPES,
+ is_secure ? WINHTTP_FLAG_SECURE : 0));
+ return !!(*request_handle);
+}
+
+bool WinHttpClient::SendRequest(HttpHandle request_handle,
+ const TCHAR* headers,
+ DWORD headers_length) const {
+ assert(request_handle);
+
+ return !!::WinHttpSendRequest(ToHINTERNET(request_handle),
+ headers,
+ headers_length,
+ NULL,
+ 0,
+ WINHTTP_IGNORE_REQUEST_TOTAL_LENGTH,
+ NULL);
+}
+
+bool WinHttpClient::ReceiveResponse(HttpHandle request_handle) const {
+ assert(request_handle);
+
+ return !!::WinHttpReceiveResponse(ToHINTERNET(request_handle), NULL);
+}
+
+bool WinHttpClient::GetHttpStatusCode(HttpHandle request_handle,
+ int* status_code) const {
+ TCHAR http_status_string[4] = {0};
+ DWORD http_status_string_size = sizeof(http_status_string);
+ if (!::WinHttpQueryHeaders(ToHINTERNET(request_handle),
+ WINHTTP_QUERY_STATUS_CODE,
+ WINHTTP_HEADER_NAME_BY_INDEX,
+ static_cast<void *>(&http_status_string),
+ &http_status_string_size, 0)) {
+ return false;
+ }
+
+ *status_code = static_cast<DWORD>(_tcstol(http_status_string, NULL, 10));
+ return true;
+}
+
+bool WinHttpClient::GetContentLength(HttpHandle request_handle,
+ DWORD* content_length) const {
+ assert(request_handle);
+ assert(content_length);
+
+ TCHAR content_length_string[11] = {0};
+ DWORD content_length_string_size = sizeof(content_length_string);
+ if (!::WinHttpQueryHeaders(ToHINTERNET(request_handle),
+ WINHTTP_QUERY_CONTENT_LENGTH,
+ WINHTTP_HEADER_NAME_BY_INDEX,
+ static_cast<void *>(&content_length_string),
+ &content_length_string_size, 0)) {
+ *content_length = kUnknownContentLength;
+ } else {
+ *content_length =
+ static_cast<DWORD>(wcstol(content_length_string, NULL, 10));
+ }
+ return true;
+}
+
+bool WinHttpClient::ReadData(HttpHandle request_handle,
+ void* buffer,
+ DWORD buffer_length,
+ DWORD* bytes_read) const {
+ assert(request_handle);
+ assert(buffer);
+ assert(bytes_read);
+
+ DWORD bytes_read_local = 0;
+ if (!::WinHttpReadData(ToHINTERNET(request_handle),
+ buffer,
+ buffer_length,
+ &bytes_read_local)) {
+ return false;
+ }
+ *bytes_read = bytes_read_local;
+ return true;
+}
+
+bool WinHttpClient::Close(HttpHandle handle) const {
+ assert(handle);
+ return !!::WinHttpCloseHandle(ToHINTERNET(handle));
+}
+
+DWORD WinHttpClient::MapAccessType(DWORD access_type) {
+ switch (static_cast<AccessType>(access_type)) {
+ case ACCESS_TYPE_PRECONFIG:
+ default:
+ return WINHTTP_ACCESS_TYPE_DEFAULT_PROXY;
+ case ACCESS_TYPE_DIRECT:
+ return WINHTTP_ACCESS_TYPE_NO_PROXY;
+ case ACCESS_TYPE_PROXY:
+ return WINHTTP_ACCESS_TYPE_NAMED_PROXY;
+ }
+}
+
+
+HINTERNET WinHttpClient::ToHINTERNET(HttpHandle handle) {
+ return static_cast<HINTERNET>(handle);
+}
+
+HttpHandle WinHttpClient::FromHINTERNET(HINTERNET handle) {
+ return static_cast<HttpHandle>(handle);
+}
+
+} // namespace internal
+
+HttpClient* CreateWinHttpClient(const TCHAR* url) {
+ assert(url);
+
+ internal::WinHttpClient winhttp;
+ wchar_t scheme[16] = {0};
+ wchar_t host[256] = {0};
+ wchar_t path[256] = {0};
+ int port = 0;
+
+ if (!winhttp.CrackUrl(url,
+ 0,
+ scheme,
+ sizeof(scheme)/sizeof(scheme[0]),
+ host,
+ sizeof(host)/sizeof(host[0]),
+ path,
+ sizeof(path)/sizeof(path[0]),
+ &port)) {
+ return NULL;
+ }
+
+ if (_wcsicmp(scheme, L"https") == 0) {
+ // Winhttp under WINE doesn't support wildcard certificates, so avoid
+ // to use it if the scheme is https. The caller should fall back to
+ // use wininet if NULL is returned.
+ return NULL;
+ }
+
+ return new internal::WinHttpClient();
+}
+
+} // namespace crash
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/winhttp_client.h b/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/winhttp_client.h
new file mode 100644
index 0000000000..819d610f1c
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/winhttp_client.h
@@ -0,0 +1,40 @@
+// Copyright 2019 Google Inc. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef TOOLS_WINDOWS_CONVERTER_EXE_WINHTTP_CLIENT_H_
+#define TOOLS_WINDOWS_CONVERTER_EXE_WINHTTP_CLIENT_H_
+
+#include "tools/windows/converter_exe/http_client.h"
+
+namespace crash {
+
+HttpClient* CreateWinHttpClient(const TCHAR* url);
+
+} // namespace crash
+
+#endif // TOOLS_WINDOWS_CONVERTER_EXE_WINHTTP_CLIENT_H_
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/wininet_client.cc b/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/wininet_client.cc
new file mode 100644
index 0000000000..3e542db25f
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/wininet_client.cc
@@ -0,0 +1,278 @@
+// Copyright 2019 Google Inc. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "tools/windows/converter_exe/wininet_client.h"
+
+#include <assert.h>
+#include <stdlib.h>
+#include <windows.h>
+#include <wininet.h>
+
+namespace crash {
+
+namespace internal {
+
+// This class implements HttpClient based on WinInet APIs.
+class WinInetClient : public HttpClient {
+ public:
+ virtual ~WinInetClient() {}
+ virtual bool CrackUrl(const TCHAR* url,
+ DWORD flags,
+ TCHAR* scheme,
+ size_t scheme_buffer_length,
+ TCHAR* host,
+ size_t host_buffer_length,
+ TCHAR* uri,
+ size_t uri_buffer_length,
+ int* port) const;
+ virtual bool Open(const TCHAR* user_agent,
+ DWORD access_type,
+ const TCHAR* proxy_name,
+ const TCHAR* proxy_bypass,
+ HttpHandle* session_handle) const;
+ virtual bool Connect(HttpHandle session_handle,
+ const TCHAR* server,
+ int port,
+ HttpHandle* connection_handle) const;
+ virtual bool OpenRequest(HttpHandle connection_handle,
+ const TCHAR* verb,
+ const TCHAR* uri,
+ const TCHAR* version,
+ const TCHAR* referrer,
+ bool is_secure,
+ HttpHandle* request_handle) const;
+ virtual bool SendRequest(HttpHandle request_handle,
+ const TCHAR* headers,
+ DWORD headers_length) const;
+ virtual bool ReceiveResponse(HttpHandle request_handle) const;
+ virtual bool GetHttpStatusCode(HttpHandle request_handle,
+ int* status_code) const;
+ virtual bool GetContentLength(HttpHandle request_handle,
+ DWORD* content_length) const;
+ virtual bool ReadData(HttpHandle request_handle,
+ void* buffer,
+ DWORD buffer_length,
+ DWORD* bytes_read) const;
+ virtual bool Close(HttpHandle handle) const;
+
+ private:
+ static DWORD MapAccessType(DWORD access_type);
+ static HINTERNET ToHINTERNET(HttpHandle handle);
+ static HttpHandle FromHINTERNET(HINTERNET handle);
+};
+
+bool WinInetClient::CrackUrl(const TCHAR* url,
+ DWORD flags,
+ TCHAR* scheme,
+ size_t scheme_buffer_length,
+ TCHAR* host,
+ size_t host_buffer_length,
+ TCHAR* uri,
+ size_t uri_buffer_length,
+ int* port) const {
+ assert(url);
+ assert(scheme);
+ assert(host);
+ assert(uri);
+ assert(port);
+
+ URL_COMPONENTS url_comp = {0};
+ url_comp.dwStructSize = sizeof(url_comp);
+ url_comp.lpszScheme = scheme;
+ url_comp.dwSchemeLength = static_cast<DWORD>(scheme_buffer_length);
+ url_comp.lpszHostName = host;
+ url_comp.dwHostNameLength = static_cast<DWORD>(host_buffer_length);
+ url_comp.lpszUrlPath = uri;
+ url_comp.dwUrlPathLength = static_cast<DWORD>(uri_buffer_length);
+
+ bool result = !!::InternetCrackUrl(url, 0, flags, &url_comp);
+ if (result) {
+ *port = static_cast<int>(url_comp.nPort);
+ }
+ return result;
+}
+
+bool WinInetClient::Open(const TCHAR* user_agent,
+ DWORD access_type,
+ const TCHAR* proxy_name,
+ const TCHAR* proxy_bypass,
+ HttpHandle* session_handle) const {
+ *session_handle = FromHINTERNET(::InternetOpen(user_agent,
+ MapAccessType(access_type),
+ proxy_name,
+ proxy_bypass,
+ 0));
+ return !!(*session_handle);
+}
+
+bool WinInetClient::Connect(HttpHandle session_handle,
+ const TCHAR* server,
+ int port,
+ HttpHandle* connection_handle) const {
+ assert(server);
+
+ // Uses NULL user name and password to connect. Always uses http service.
+ *connection_handle = FromHINTERNET(::InternetConnect(
+ ToHINTERNET(session_handle),
+ server,
+ static_cast<INTERNET_PORT>(port),
+ NULL,
+ NULL,
+ INTERNET_SERVICE_HTTP,
+ 0,
+ 0));
+ return !!(*connection_handle);
+}
+
+bool WinInetClient::OpenRequest(HttpHandle connection_handle,
+ const TCHAR* verb,
+ const TCHAR* uri,
+ const TCHAR* version,
+ const TCHAR* referrer,
+ bool is_secure,
+ HttpHandle* request_handle) const {
+ assert(connection_handle);
+ assert(verb);
+ assert(uri);
+
+ *request_handle = FromHINTERNET(::HttpOpenRequest(
+ ToHINTERNET(connection_handle),
+ verb,
+ uri,
+ version,
+ referrer,
+ NULL,
+ is_secure ? INTERNET_FLAG_SECURE : 0,
+ NULL));
+ return !!(*request_handle);
+}
+
+bool WinInetClient::SendRequest(HttpHandle request_handle,
+ const TCHAR* headers,
+ DWORD headers_length) const {
+ assert(request_handle);
+
+ return !!::HttpSendRequest(ToHINTERNET(request_handle),
+ headers,
+ headers_length,
+ NULL,
+ 0);
+}
+
+bool WinInetClient::ReceiveResponse(HttpHandle) const {
+ return true;
+}
+
+bool WinInetClient::GetHttpStatusCode(HttpHandle request_handle,
+ int* status_code) const {
+ assert(request_handle);
+
+ TCHAR http_status_string[4] = {0};
+ DWORD http_status_string_size = sizeof(http_status_string);
+ if (!::HttpQueryInfo(ToHINTERNET(request_handle),
+ HTTP_QUERY_STATUS_CODE,
+ static_cast<void *>(&http_status_string),
+ &http_status_string_size,
+ 0)) {
+ return false;
+ }
+
+ *status_code = _tcstol(http_status_string, NULL, 10);
+ return true;
+}
+
+bool WinInetClient::GetContentLength(HttpHandle request_handle,
+ DWORD* content_length) const {
+ assert(request_handle);
+ assert(content_length);
+
+ TCHAR content_length_string[11];
+ DWORD content_length_string_size = sizeof(content_length_string);
+ if (!::HttpQueryInfo(ToHINTERNET(request_handle),
+ HTTP_QUERY_CONTENT_LENGTH,
+ static_cast<void *>(&content_length_string),
+ &content_length_string_size,
+ 0)) {
+ *content_length = kUnknownContentLength;
+ } else {
+ *content_length = wcstol(content_length_string, NULL, 10);
+ }
+ return true;
+}
+
+bool WinInetClient::ReadData(HttpHandle request_handle,
+ void* buffer,
+ DWORD buffer_length,
+ DWORD* bytes_read) const {
+ assert(request_handle);
+ assert(buffer);
+ assert(bytes_read);
+
+ DWORD bytes_read_local = 0;
+ if (!::InternetReadFile(ToHINTERNET(request_handle),
+ buffer,
+ buffer_length,
+ &bytes_read_local)) {
+ return false;
+ }
+ *bytes_read = bytes_read_local;
+ return true;
+}
+
+bool WinInetClient::Close(HttpHandle handle) const {
+ assert(handle);
+ return !!::InternetCloseHandle(ToHINTERNET(handle));
+}
+
+DWORD WinInetClient::MapAccessType(DWORD access_type) {
+ switch (static_cast<AccessType>(access_type)) {
+ case ACCESS_TYPE_PRECONFIG:
+ default:
+ return INTERNET_OPEN_TYPE_PRECONFIG;
+ case ACCESS_TYPE_DIRECT:
+ return INTERNET_OPEN_TYPE_DIRECT;
+ case ACCESS_TYPE_PROXY:
+ return INTERNET_OPEN_TYPE_PROXY;
+ }
+}
+
+HINTERNET WinInetClient::ToHINTERNET(HttpHandle handle) {
+ return static_cast<HINTERNET>(handle);
+}
+
+HttpHandle WinInetClient::FromHINTERNET(HINTERNET handle) {
+ return static_cast<HttpHandle>(handle);
+}
+
+} // namespace internal
+
+HttpClient* CreateWinInetClient(const TCHAR*) {
+ return new internal::WinInetClient();
+}
+
+} // namespace crash
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/wininet_client.h b/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/wininet_client.h
new file mode 100644
index 0000000000..bd04b605dc
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/wininet_client.h
@@ -0,0 +1,40 @@
+// Copyright 2019 Google Inc. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef TOOLS_WINDOWS_CONVERTER_EXE_WININET_CLIENT_H_
+#define TOOLS_WINDOWS_CONVERTER_EXE_WININET_CLIENT_H_
+
+#include "tools/windows/converter_exe/http_client.h"
+
+namespace crash {
+
+HttpClient* CreateWinInetClient(const TCHAR* url);
+
+} // namespace crash
+
+#endif // TOOLS_WINDOWS_CONVERTER_EXE_WININET_CLIENT_H_
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/winsymconv.cmd b/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/winsymconv.cmd
new file mode 100644
index 0000000000..bea84b589f
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/winsymconv.cmd
@@ -0,0 +1,86 @@
+@if "%ECHOON%"=="" @echo off
+SETLOCAL
+
+REM ******************************************************************
+REM Usage:
+REM winsymconv
+REM ******************************************************************
+
+REM ******************************************************************
+REM Initialize
+REM ******************************************************************
+SET SCRIPT_LOCATION=%~dp0
+SET DBGHELP_WINHTTP=
+SET USE_WINHTTP=
+
+REM ******************************************************************
+REM Go to script location
+REM ******************************************************************
+pushd %SCRIPT_LOCATION%
+
+REM ******************************************************************
+REM Make sure the symbol file directory exists
+REM ******************************************************************
+SET SYMBOL_DIR=%SCRIPT_LOCATION%symbol
+if NOT EXIST %SYMBOL_DIR% MKDIR %SYMBOL_DIR%
+if NOT EXIST %SYMBOL_DIR% echo Failed to create directory '%SYMBOL_DIR%' & goto :fail
+
+:restart
+
+REM ******************************************************************
+REM Convert missing Windows symbols on the staging instance.
+REM ******************************************************************
+echo Converting missing Windows symbols on staging instance ...
+
+google_converter.exe ^
+ -n http://msdl.microsoft.com/download/symbols ^
+ -n http://symbols.mozilla.org/firefox ^
+ -n http://chromium-browser-symsrv.commondatastorage.googleapis.com ^
+ -n https://download.amd.com/dir/bin ^
+ -n https://driver-symbols.nvidia.com ^
+ -n https://software.intel.com/sites/downloads/symbols ^
+ -l %SYMBOL_DIR% ^
+ -s https://clients2.google.com/cr/staging_symbol ^
+ -m https://clients2.google.com/cr/staging_symbol/missingsymbols ^
+ -t https://clients2.google.com/cr/staging_symbol/fetchfailed ^
+ -b "google|chrome|internal|private" ^
+ > %SCRIPT_LOCATION%last_cycle_staging.txt
+
+REM ******************************************************************
+REM Convert missing Windows symbols on the production instance.
+REM ******************************************************************
+echo Converting missing Windows symbols on production instance ...
+
+google_converter.exe ^
+ -n http://msdl.microsoft.com/download/symbols ^
+ -n http://symbols.mozilla.org/firefox ^
+ -n http://chromium-browser-symsrv.commondatastorage.googleapis.com ^
+ -n https://download.amd.com/dir/bin ^
+ -n https://driver-symbols.nvidia.com ^
+ -n https://software.intel.com/sites/downloads/symbols ^
+ -l %SYMBOL_DIR% ^
+ -s https://clients2.google.com/cr/symbol ^
+ -m https://clients2.google.com/cr/symbol/missingsymbols ^
+ -t https://clients2.google.com/cr/symbol/fetchfailed ^
+ -b "google|chrome|internal|private" ^
+ > %SCRIPT_LOCATION%last_cycle_prod.txt
+
+REM ******************************************************************
+REM Sleep for 5 minutes ...
+REM ******************************************************************
+echo Sleeping for 5 minutes ...
+
+%SCRIPT_LOCATION%sleep.exe 300
+
+REM ******************************************
+REM Restart work loop ...
+REM ******************************************
+goto :restart
+
+:success
+ENDLOCAL
+exit /b 0
+
+:fail
+ENDLOCAL
+exit /b 1
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/winsymconv_test.cmd b/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/winsymconv_test.cmd
new file mode 100644
index 0000000000..c177706608
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/windows/converter_exe/winsymconv_test.cmd
@@ -0,0 +1,72 @@
+@if "%ECHOON%"=="" @echo off
+SETLOCAL
+
+REM ******************************************************************
+REM Usage:
+REM winsymconv_test
+REM ******************************************************************
+
+REM ******************************************************************
+REM Initialize
+REM ******************************************************************
+SET SCRIPT_LOCATION=%~dp0
+SET DBGHELP_WINHTTP=
+SET USE_WINHTTP=
+
+REM ******************************************************************
+REM Go to script location
+REM ******************************************************************
+pushd %SCRIPT_LOCATION%
+
+REM ******************************************************************
+REM Make sure the symbol file directory exists
+REM ******************************************************************
+SET SYMBOL_DIR=%SCRIPT_LOCATION%symbol
+if NOT EXIST %SYMBOL_DIR% MKDIR %SYMBOL_DIR%
+if NOT EXIST %SYMBOL_DIR% echo Failed to create directory '%SYMBOL_DIR%' & goto :fail
+
+REM ******************************************************************
+REM Testing on the staging instance.
+REM ******************************************************************
+echo Testing on the staging instance ...
+
+google_converter.exe ^
+ -n http://msdl.microsoft.com/download/symbols ^
+ -n http://symbols.mozilla.org/firefox ^
+ -n http://chromium-browser-symsrv.commondatastorage.googleapis.com ^
+ -n https://download.amd.com/dir/bin ^
+ -n https://driver-symbols.nvidia.com ^
+ -n https://software.intel.com/sites/downloads/symbols ^
+ -l %SYMBOL_DIR% ^
+ -s https://clients2.google.com/cr/staging_symbol ^
+ -mf %SCRIPT_LOCATION%missing_symbols_test.txt ^
+ -t https://clients2.google.com/cr/staging_symbol/fetchfailed ^
+ -b "google|chrome|internal|private" ^
+ > %SCRIPT_LOCATION%last_cycle_staging.txt
+
+REM ******************************************************************
+REM Testing on the production instance.
+REM ******************************************************************
+echo Testing on the production instance ...
+
+google_converter.exe ^
+ -n http://msdl.microsoft.com/download/symbols ^
+ -n http://symbols.mozilla.org/firefox ^
+ -n http://chromium-browser-symsrv.commondatastorage.googleapis.com ^
+ -n https://download.amd.com/dir/bin ^
+ -n https://driver-symbols.nvidia.com ^
+ -n https://software.intel.com/sites/downloads/symbols ^
+ -l %SYMBOL_DIR% ^
+ -s https://clients2.google.com/cr/symbol ^
+ -mf %SCRIPT_LOCATION%missing_symbols_test.txt ^
+ -t https://clients2.google.com/cr/symbol/fetchfailed ^
+ -b "google|chrome|internal|private" ^
+ > %SCRIPT_LOCATION%last_cycle_prod.txt
+
+:success
+ENDLOCAL
+exit /b 0
+
+:fail
+ENDLOCAL
+exit /b 1
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/windows/dump_syms/dump_syms.cc b/toolkit/crashreporter/google-breakpad/src/tools/windows/dump_syms/dump_syms.cc
new file mode 100644
index 0000000000..5b7d177753
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/windows/dump_syms/dump_syms.cc
@@ -0,0 +1,73 @@
+// Copyright (c) 2006, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Windows utility to dump the line number data from a pdb file to
+// a text-based format that we can use from the minidump processor.
+
+#include <stdio.h>
+#include <wchar.h>
+
+#include <string>
+
+#include "common/windows/pdb_source_line_writer.h"
+#include "common/windows/pe_source_line_writer.h"
+
+using std::wstring;
+using google_breakpad::PDBSourceLineWriter;
+using google_breakpad::PESourceLineWriter;
+using std::unique_ptr;
+
+int wmain(int argc, wchar_t **argv) {
+ bool success;
+ if (argc == 2) {
+ PDBSourceLineWriter pdb_writer;
+ if (!pdb_writer.Open(wstring(argv[1]), PDBSourceLineWriter::ANY_FILE)) {
+ fprintf(stderr, "Open failed.\n");
+ return 1;
+ }
+ success = pdb_writer.WriteSymbols(stdout);
+ } else if (argc == 3 && wcscmp(argv[1], L"--pe") == 0) {
+ PESourceLineWriter pe_writer(argv[2]);
+ success = pe_writer.WriteSymbols(stdout);
+ } else {
+ fprintf(stderr, "Usage: %ws [--pe] <file.[pdb|exe|dll]>\n", argv[0]);
+ fprintf(stderr, "Options:\n");
+ fprintf(stderr, "--pe:\tRead debugging information from PE file and do "
+ "not attempt to locate matching PDB file.\n"
+ "\tThis is only supported for PE32+ (64 bit) PE files.\n");
+ return 1;
+ }
+
+ if (!success) {
+ fprintf(stderr, "WriteSymbols failed.\n");
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/windows/dump_syms/dump_syms.gyp b/toolkit/crashreporter/google-breakpad/src/tools/windows/dump_syms/dump_syms.gyp
new file mode 100644
index 0000000000..b815574b29
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/windows/dump_syms/dump_syms.gyp
@@ -0,0 +1,64 @@
+# Copyright 2013 Google Inc. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+{
+ 'includes': [
+ '../../../build/common.gypi',
+ ],
+ 'targets': [
+ {
+ 'target_name': 'dump_syms',
+ 'type': 'executable',
+ 'sources': [
+ 'dump_syms.cc',
+ ],
+ 'dependencies': [
+ '../../../common/windows/common_windows.gyp:common_windows_lib',
+ ],
+ },
+ {
+ 'target_name': 'dump_syms_unittest',
+ 'type': 'executable',
+ 'sources': [
+ 'dump_syms_unittest.cc',
+ ],
+ 'dependencies': [
+ '<(DEPTH)/client/windows/unittests/testing.gyp:gmock',
+ '<(DEPTH)/client/windows/unittests/testing.gyp:gtest',
+ 'dump_syms',
+ ],
+ 'msvs_settings': {
+ 'VCLinkerTool': {
+ 'AdditionalDependencies': [
+ 'shell32.lib',
+ ],
+ },
+ },
+ },
+ ],
+}
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/windows/dump_syms/dump_syms.vcproj b/toolkit/crashreporter/google-breakpad/src/tools/windows/dump_syms/dump_syms.vcproj
new file mode 100644
index 0000000000..2fbe301ed8
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/windows/dump_syms/dump_syms.vcproj
@@ -0,0 +1,242 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="dump_syms"
+ ProjectGUID="{792E1530-E2C5-4289-992E-317BA30E9D9F}"
+ RootNamespace="dumpsyms"
+ Keyword="Win32Proj"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="Debug"
+ IntermediateDirectory="Debug"
+ ConfigurationType="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="&quot;$(VSInstallDir)\DIA SDK\include&quot;;..\..\.."
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;WIN32_LEAN_AND_MEAN"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="&quot;$(VSInstallDir)\DIA SDK\lib\diaguids.lib&quot; imagehlp.lib"
+ LinkIncremental="2"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="Release"
+ IntermediateDirectory="Release"
+ ConfigurationType="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="&quot;$(VSInstallDir)\DIA SDK\include&quot;;..\..\.."
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;WIN32_LEAN_AND_MEAN"
+ RuntimeLibrary="2"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="&quot;$(VSInstallDir)\DIA SDK\lib\diaguids.lib&quot; imagehlp.lib"
+ LinkIncremental="2"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath="..\..\..\common\windows\dia_util.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\common\windows\guid_string.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\common\windows\omap_internal.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\common\windows\omap.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\common\windows\pdb_source_line_writer.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\common\windows\string_utils-inl.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ </Filter>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath="..\..\..\common\windows\dia_util.cc"
+ >
+ </File>
+ <File
+ RelativePath=".\dump_syms.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\common\windows\guid_string.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\common\windows\omap.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\common\windows\pdb_source_line_writer.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\common\windows\string_utils.cc"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject> \ No newline at end of file
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/windows/dump_syms/dump_syms_unittest.cc b/toolkit/crashreporter/google-breakpad/src/tools/windows/dump_syms/dump_syms_unittest.cc
new file mode 100644
index 0000000000..766e5c09d0
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/windows/dump_syms/dump_syms_unittest.cc
@@ -0,0 +1,244 @@
+// Copyright 2003 Google Inc. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <Windows.h>
+#include <shellapi.h>
+
+#include <string>
+#include <utility>
+
+#include "breakpad_googletest_includes.h"
+
+namespace tools {
+namespace windows {
+namespace dump_syms {
+
+namespace {
+
+// Root names of PDB and dumped symbol files to be regression tested. These are
+// specified in complexity of the resulting dumped symbol files.
+const wchar_t* kRootNames[] = {
+ // A PDB file with no OMAP data.
+ L"dump_syms_regtest",
+ // A PDB file with OMAP data for an image that has been function-level
+ // reordered.
+ L"omap_reorder_funcs",
+ // A PDB file with OMAP data for an image that had new content injected, all
+ // of it with source data.
+ L"omap_stretched_filled",
+ // A PDB file with OMAP data for an image that had new content injected, but
+ // without source data.
+ L"omap_stretched",
+ // A PDB file with OMAP data for an image that has been basic block reordered.
+ L"omap_reorder_bbs",
+ // A 64bit PDB file with no OMAP data.
+ L"dump_syms_regtest64",
+};
+
+const wchar_t* kPEOnlyRootNames[] = {
+ L"pe_only_symbol_test",
+};
+
+void TrimLastComponent(const std::wstring& path,
+ std::wstring* trimmed,
+ std::wstring* component) {
+ size_t len = path.size();
+ while (len > 0 && path[len - 1] != '\\')
+ --len;
+
+ if (component != NULL)
+ component->assign(path.c_str() + len, path.c_str() + path.size());
+
+ while (len > 0 && path[len - 1] == '\\')
+ --len;
+
+ if (trimmed != NULL)
+ trimmed->assign(path.c_str(), len);
+}
+
+// Get the directory of the current executable.
+bool GetSelfDirectory(std::wstring* self_dir) {
+ std::wstring command_line = GetCommandLineW();
+
+ int num_args = 0;
+ wchar_t** args = NULL;
+ args = ::CommandLineToArgvW(command_line.c_str(), &num_args);
+ if (args == NULL)
+ return false;
+
+ *self_dir = args[0];
+ TrimLastComponent(*self_dir, self_dir, NULL);
+
+ return true;
+}
+
+void RunCommand(const std::wstring& command_line,
+ std::string* stdout_string) {
+ // Create a PIPE for the child process stdout.
+ HANDLE child_stdout_read = 0;
+ HANDLE child_stdout_write = 0;
+ SECURITY_ATTRIBUTES sec_attr_stdout = {};
+ sec_attr_stdout.nLength = sizeof(sec_attr_stdout);
+ sec_attr_stdout.bInheritHandle = TRUE;
+ ASSERT_TRUE(::CreatePipe(&child_stdout_read, &child_stdout_write,
+ &sec_attr_stdout, 0));
+ ASSERT_TRUE(::SetHandleInformation(child_stdout_read, HANDLE_FLAG_INHERIT,
+ 0));
+
+ // Create a PIPE for the child process stdin.
+ HANDLE child_stdin_read = 0;
+ HANDLE child_stdin_write = 0;
+ SECURITY_ATTRIBUTES sec_attr_stdin = {};
+ sec_attr_stdin.nLength = sizeof(sec_attr_stdin);
+ sec_attr_stdin.bInheritHandle = TRUE;
+ ASSERT_TRUE(::CreatePipe(&child_stdin_read, &child_stdin_write,
+ &sec_attr_stdin, 0));
+ ASSERT_TRUE(::SetHandleInformation(child_stdin_write, HANDLE_FLAG_INHERIT,
+ 0));
+
+ // Startup the child.
+ STARTUPINFO startup_info = {};
+ PROCESS_INFORMATION process_info = {};
+ startup_info.cb = sizeof(STARTUPINFO);
+ startup_info.hStdError = NULL;
+ startup_info.hStdInput = child_stdin_read;
+ startup_info.hStdOutput = child_stdout_write;
+ startup_info.dwFlags = STARTF_USESTDHANDLES;
+ ASSERT_TRUE(::CreateProcessW(NULL, (LPWSTR)command_line.c_str(), NULL, NULL,
+ TRUE, 0, NULL, NULL,
+ &startup_info, &process_info));
+
+ // Collect the output.
+ ASSERT_TRUE(::CloseHandle(child_stdout_write));
+ char buffer[4096] = {};
+ DWORD bytes_read = 0;
+ while (::ReadFile(child_stdout_read, buffer, sizeof(buffer), &bytes_read,
+ NULL) && bytes_read > 0) {
+ stdout_string->append(buffer, bytes_read);
+ }
+
+ // Wait for the process to finish.
+ ::WaitForSingleObject(process_info.hProcess, INFINITE);
+
+ // Shut down all of our handles.
+ ASSERT_TRUE(::CloseHandle(process_info.hThread));
+ ASSERT_TRUE(::CloseHandle(process_info.hProcess));
+ ASSERT_TRUE(::CloseHandle(child_stdin_write));
+ ASSERT_TRUE(::CloseHandle(child_stdin_read));
+ ASSERT_TRUE(::CloseHandle(child_stdout_read));
+}
+
+void GetFileContents(const std::wstring& path, std::string* content) {
+ FILE* f = ::_wfopen(path.c_str(), L"rb");
+ ASSERT_TRUE(f != NULL);
+
+ char buffer[4096] = {};
+ while (true) {
+ size_t bytes_read = ::fread(buffer, 1, sizeof(buffer), f);
+ if (bytes_read == 0)
+ break;
+ content->append(buffer, bytes_read);
+ }
+}
+
+class DumpSymsRegressionTest : public testing::TestWithParam<const wchar_t *> {
+ public:
+ virtual void SetUp() {
+ std::wstring self_dir;
+ ASSERT_TRUE(GetSelfDirectory(&self_dir));
+ dump_syms_exe = self_dir + L"\\dump_syms.exe";
+
+ TrimLastComponent(self_dir, &testdata_dir, NULL);
+ testdata_dir += L"\\testdata";
+ }
+
+ std::wstring dump_syms_exe;
+ std::wstring testdata_dir;
+};
+
+class DumpSymsPEOnlyRegressionTest : public testing::TestWithParam<const wchar_t *> {
+public:
+ virtual void SetUp() {
+ std::wstring self_dir;
+ ASSERT_TRUE(GetSelfDirectory(&self_dir));
+ dump_syms_exe = self_dir + L"\\dump_syms.exe";
+
+ TrimLastComponent(self_dir, &testdata_dir, NULL);
+ testdata_dir += L"\\testdata";
+ }
+
+ std::wstring dump_syms_exe;
+ std::wstring testdata_dir;
+};
+
+} //namespace
+
+TEST_P(DumpSymsRegressionTest, EnsureDumpedSymbolsMatch) {
+ const wchar_t* root_name = GetParam();
+ std::wstring root_path = testdata_dir + L"\\" + root_name;
+
+ std::wstring sym_path = root_path + L".sym";
+ std::string expected_symbols;
+ ASSERT_NO_FATAL_FAILURE(GetFileContents(sym_path, &expected_symbols));
+
+ std::wstring pdb_path = root_path + L".pdb";
+ std::wstring command_line = L"\"" + dump_syms_exe + L"\" \"" +
+ pdb_path + L"\"";
+ std::string symbols;
+ ASSERT_NO_FATAL_FAILURE(RunCommand(command_line, &symbols));
+
+ EXPECT_EQ(expected_symbols, symbols);
+}
+
+INSTANTIATE_TEST_CASE_P(DumpSyms, DumpSymsRegressionTest,
+ testing::ValuesIn(kRootNames));
+
+TEST_P(DumpSymsPEOnlyRegressionTest, EnsurePEOnlyDumpedSymbolsMatch) {
+ const wchar_t* root_name = GetParam();
+ std::wstring root_path = testdata_dir + L"\\" + root_name;
+
+ std::wstring sym_path = root_path + L".sym";
+ std::string expected_symbols;
+ ASSERT_NO_FATAL_FAILURE(GetFileContents(sym_path, &expected_symbols));
+
+ std::wstring dll_path = root_path + L".dll";
+ std::wstring command_line = L"\"" + dump_syms_exe + L"\" --pe \"" +
+ dll_path + L"\"";
+ std::string symbols;
+ ASSERT_NO_FATAL_FAILURE(RunCommand(command_line, &symbols));
+
+ EXPECT_EQ(expected_symbols, symbols);
+}
+
+INSTANTIATE_TEST_CASE_P(PEOnlyDumpSyms, DumpSymsPEOnlyRegressionTest,
+ testing::ValuesIn(kPEOnlyRootNames));
+
+
+} // namespace dump_syms
+} // namespace windows
+} // namespace tools
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/windows/dump_syms/run_regtest.sh b/toolkit/crashreporter/google-breakpad/src/tools/windows/dump_syms/run_regtest.sh
new file mode 100755
index 0000000000..1f20f64fd5
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/windows/dump_syms/run_regtest.sh
@@ -0,0 +1,53 @@
+#!/bin/sh
+
+# Copyright (c) 2006, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Release/dump_syms.exe testdata/dump_syms_regtest.pdb | \
+ tr -d '\015' > \
+ testdata/dump_syms_regtest.new
+status=$?
+
+if [ $status -ne 0 ] ; then
+ echo "FAIL, dump_syms.exe failed"
+ exit $status
+fi
+
+diff -u testdata/dump_syms_regtest.new testdata/dump_syms_regtest.sym > \
+ testdata/dump_syms_regtest.diff
+status=$?
+
+if [ $status -eq 0 ] ; then
+ rm testdata/dump_syms_regtest.diff testdata/dump_syms_regtest.new
+ echo "PASS"
+else
+ echo "FAIL, see testdata/dump_syms_regtest.[new|diff]"
+fi
+
+exit $status
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/windows/refresh_binaries.bat b/toolkit/crashreporter/google-breakpad/src/tools/windows/refresh_binaries.bat
new file mode 100644
index 0000000000..bf18d5079d
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/windows/refresh_binaries.bat
@@ -0,0 +1,23 @@
+REM This batch file is meant to facilitate regenerating prebuilt binaries for
+REM the Windows tools.
+REM You MUST run it from a Visual Studio xxxx Command Prompt. To do this,
+REM navigate to:
+REM
+REM Start->Programs->Microsoft Visual Studio XXXX->Tools->
+REM Visual Studio Command Prompt
+REM
+REM Then run this batch file. It performs an SVN update, edits the
+REM README.binaries file to contain
+REM the revision number, and builds the tools. You must run 'svn commit' to
+REM commit the pending edits to the repository.
+
+pushd %~dp0
+if %VisualStudioVersion% == 14.0 set GYP_MSVS_VERSION=2015
+gyp tools_windows.gyp
+msbuild tools_windows.sln /p:Configuration=Release /t:Clean,Build
+copy Release\symupload.exe binaries\
+copy Release\dump_syms.exe binaries\
+git add binaries
+git commit -m "Built Windows binaries"
+echo Done!
+popd
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/windows/symupload/symupload.cc b/toolkit/crashreporter/google-breakpad/src/tools/windows/symupload/symupload.cc
new file mode 100644
index 0000000000..7e3029326d
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/windows/symupload/symupload.cc
@@ -0,0 +1,394 @@
+// Copyright (c) 2006, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Tool to upload an exe/dll and its associated symbols to an HTTP server.
+// The PDB file is located automatically, using the path embedded in the
+// executable. The upload is sent as a multipart/form-data POST request,
+// with the following parameters:
+// code_file: the basename of the module, e.g. "app.exe"
+// debug_file: the basename of the debugging file, e.g. "app.pdb"
+// debug_identifier: the debug file's identifier, usually consisting of
+// the guid and age embedded in the pdb, e.g.
+// "11111111BBBB3333DDDD555555555555F"
+// product: the HTTP-friendly product name, e.g. "MyApp"
+// version: the file version of the module, e.g. "1.2.3.4"
+// os: the operating system that the module was built for, always
+// "windows" in this implementation.
+// cpu: the CPU that the module was built for, typically "x86".
+// symbol_file: the contents of the breakpad-format symbol file
+
+#include <windows.h>
+#include <dbghelp.h>
+#include <wininet.h>
+
+#include <cstdio>
+#include <map>
+#include <string>
+#include <vector>
+
+#include "common/windows/string_utils-inl.h"
+
+#include "common/windows/http_upload.h"
+#include "common/windows/pdb_source_line_writer.h"
+#include "common/windows/symbol_collector_client.h"
+
+using std::string;
+using std::wstring;
+using std::vector;
+using std::map;
+using google_breakpad::HTTPUpload;
+using google_breakpad::SymbolCollectorClient;
+using google_breakpad::SymbolStatus;
+using google_breakpad::UploadUrlResponse;
+using google_breakpad::CompleteUploadResult;
+using google_breakpad::PDBModuleInfo;
+using google_breakpad::PDBSourceLineWriter;
+using google_breakpad::WindowsStringUtils;
+
+// Extracts the file version information for the given filename,
+// as a string, for example, "1.2.3.4". Returns true on success.
+static bool GetFileVersionString(const wchar_t *filename, wstring *version) {
+ DWORD handle;
+ DWORD version_size = GetFileVersionInfoSize(filename, &handle);
+ if (version_size < sizeof(VS_FIXEDFILEINFO)) {
+ return false;
+ }
+
+ vector<char> version_info(version_size);
+ if (!GetFileVersionInfo(filename, handle, version_size, &version_info[0])) {
+ return false;
+ }
+
+ void *file_info_buffer = NULL;
+ unsigned int file_info_length;
+ if (!VerQueryValue(&version_info[0], L"\\",
+ &file_info_buffer, &file_info_length)) {
+ return false;
+ }
+
+ // The maximum value of each version component is 65535 (0xffff),
+ // so the max length is 24, including the terminating null.
+ wchar_t ver_string[24];
+ VS_FIXEDFILEINFO *file_info =
+ reinterpret_cast<VS_FIXEDFILEINFO*>(file_info_buffer);
+ swprintf(ver_string, sizeof(ver_string) / sizeof(ver_string[0]),
+ L"%d.%d.%d.%d",
+ file_info->dwFileVersionMS >> 16,
+ file_info->dwFileVersionMS & 0xffff,
+ file_info->dwFileVersionLS >> 16,
+ file_info->dwFileVersionLS & 0xffff);
+
+ // remove when VC++7.1 is no longer supported
+ ver_string[sizeof(ver_string) / sizeof(ver_string[0]) - 1] = L'\0';
+
+ *version = ver_string;
+ return true;
+}
+
+// Creates a new temporary file and writes the symbol data from the given
+// exe/dll file to it. Returns the path to the temp file in temp_file_path
+// and information about the pdb in pdb_info.
+static bool DumpSymbolsToTempFile(const wchar_t *file,
+ wstring *temp_file_path,
+ PDBModuleInfo *pdb_info) {
+ google_breakpad::PDBSourceLineWriter writer;
+ // Use EXE_FILE to get information out of the exe/dll in addition to the
+ // pdb. The name and version number of the exe/dll are of value, and
+ // there's no way to locate an exe/dll given a pdb.
+ if (!writer.Open(file, PDBSourceLineWriter::EXE_FILE)) {
+ return false;
+ }
+
+ wchar_t temp_path[_MAX_PATH];
+ if (GetTempPath(_MAX_PATH, temp_path) == 0) {
+ return false;
+ }
+
+ wchar_t temp_filename[_MAX_PATH];
+ if (GetTempFileName(temp_path, L"sym", 0, temp_filename) == 0) {
+ return false;
+ }
+
+ FILE *temp_file = NULL;
+#if _MSC_VER >= 1400 // MSVC 2005/8
+ if (_wfopen_s(&temp_file, temp_filename, L"w") != 0)
+#else // _MSC_VER >= 1400
+ // _wfopen_s was introduced in MSVC8. Use _wfopen for earlier environments.
+ // Don't use it with MSVC8 and later, because it's deprecated.
+ if (!(temp_file = _wfopen(temp_filename, L"w")))
+#endif // _MSC_VER >= 1400
+ {
+ return false;
+ }
+
+ bool success = writer.WriteSymbols(temp_file);
+ fclose(temp_file);
+ if (!success) {
+ _wunlink(temp_filename);
+ return false;
+ }
+
+ *temp_file_path = temp_filename;
+
+ return writer.GetModuleInfo(pdb_info);
+}
+
+static bool DoSymUploadV2(
+ const wchar_t* api_url,
+ const wchar_t* api_key,
+ const wstring& debug_file,
+ const wstring& debug_id,
+ const wstring& symbol_file,
+ bool force) {
+ wstring url(api_url);
+ wstring key(api_key);
+
+ if (!force) {
+ SymbolStatus symbolStatus = SymbolCollectorClient::CheckSymbolStatus(
+ url,
+ key,
+ debug_file,
+ debug_id);
+ if (symbolStatus == SymbolStatus::Found) {
+ wprintf(L"Symbol file already exists, upload aborted."
+ L" Use \"-f\" to overwrite.\n");
+ return true;
+ }
+ else if (symbolStatus == SymbolStatus::Unknown) {
+ wprintf(L"Failed to get check for existing symbol.\n");
+ return false;
+ }
+ }
+
+ UploadUrlResponse uploadUrlResponse;
+ if (!SymbolCollectorClient::CreateUploadUrl(
+ url,
+ key,
+ &uploadUrlResponse)) {
+ wprintf(L"Failed to create upload URL.\n");
+ return false;
+ }
+
+ wstring signed_url = uploadUrlResponse.upload_url;
+ wstring upload_key = uploadUrlResponse.upload_key;
+ wstring response;
+ int response_code;
+ bool success = HTTPUpload::SendPutRequest(
+ signed_url,
+ symbol_file,
+ /* timeout = */ NULL,
+ &response,
+ &response_code);
+ if (!success) {
+ wprintf(L"Failed to send symbol file.\n");
+ wprintf(L"Response code: %ld\n", response_code);
+ wprintf(L"Response:\n");
+ wprintf(L"%s\n", response.c_str());
+ return false;
+ }
+ else if (response_code == 0) {
+ wprintf(L"Failed to send symbol file: No response code\n");
+ return false;
+ }
+ else if (response_code != 200) {
+ wprintf(L"Failed to send symbol file: Response code %ld\n", response_code);
+ wprintf(L"Response:\n");
+ wprintf(L"%s\n", response.c_str());
+ return false;
+ }
+
+ CompleteUploadResult completeUploadResult =
+ SymbolCollectorClient::CompleteUpload(
+ url,
+ key,
+ upload_key,
+ debug_file,
+ debug_id);
+ if (completeUploadResult == CompleteUploadResult::Error) {
+ wprintf(L"Failed to complete upload.\n");
+ return false;
+ }
+ else if (completeUploadResult == CompleteUploadResult::DuplicateData) {
+ wprintf(L"Uploaded file checksum matched existing file checksum,"
+ L" no change necessary.\n");
+ }
+ else {
+ wprintf(L"Successfully sent the symbol file.\n");
+ }
+
+ return true;
+}
+
+__declspec(noreturn) void printUsageAndExit() {
+ wprintf(L"Usage:\n\n"
+ L" symupload [--timeout NN] [--product product_name] ^\n"
+ L" <file.exe|file.dll> <symbol upload URL> ^\n"
+ L" [...<symbol upload URLs>]\n\n");
+ wprintf(L" - Timeout is in milliseconds, or can be 0 to be unlimited.\n");
+ wprintf(L" - product_name is an HTTP-friendly product name. It must only\n"
+ L" contain an ascii subset: alphanumeric and punctuation.\n"
+ L" This string is case-sensitive.\n\n");
+ wprintf(L"Example:\n\n"
+ L" symupload.exe --timeout 0 --product Chrome ^\n"
+ L" chrome.dll http://no.free.symbol.server.for.you\n");
+ wprintf(L"\n");
+ wprintf(L"sym-upload-v2 usage:\n"
+ L" symupload -p [-f] <file.exe|file.dll> <API-URL> <API-key>\n");
+ wprintf(L"\n");
+ wprintf(L"sym_upload_v2 Options:\n");
+ wprintf(L" <API-URL> is the sym_upload_v2 API URL.\n");
+ wprintf(L" <API-key> is a secret used to authenticate with the API.\n");
+ wprintf(L" -p:\t Use sym_upload_v2 protocol.\n");
+ wprintf(L" -f:\t Force symbol upload if already exists.\n");
+
+ exit(0);
+}
+
+int wmain(int argc, wchar_t *argv[]) {
+ const wchar_t *module;
+ const wchar_t *product = nullptr;
+ int timeout = -1;
+ int currentarg = 1;
+ bool use_sym_upload_v2 = false;
+ bool force = false;
+ const wchar_t* api_url = nullptr;
+ const wchar_t* api_key = nullptr;
+ while (argc > currentarg + 1) {
+ if (!wcscmp(L"--timeout", argv[currentarg])) {
+ timeout = _wtoi(argv[currentarg + 1]);
+ currentarg += 2;
+ continue;
+ }
+ if (!wcscmp(L"--product", argv[currentarg])) {
+ product = argv[currentarg + 1];
+ currentarg += 2;
+ continue;
+ }
+ if (!wcscmp(L"-p", argv[currentarg])) {
+ use_sym_upload_v2 = true;
+ ++currentarg;
+ continue;
+ }
+ if (!wcscmp(L"-f", argv[currentarg])) {
+ force = true;
+ ++currentarg;
+ continue;
+ }
+ break;
+ }
+
+ if (argc >= currentarg + 2)
+ module = argv[currentarg++];
+ else
+ printUsageAndExit();
+
+ wstring symbol_file;
+ PDBModuleInfo pdb_info;
+ if (!DumpSymbolsToTempFile(module, &symbol_file, &pdb_info)) {
+ fwprintf(stderr, L"Could not get symbol data from %s\n", module);
+ return 1;
+ }
+
+ wstring code_file = WindowsStringUtils::GetBaseName(wstring(module));
+ wstring file_version;
+ // Don't make a missing version a hard error. Issue a warning, and let the
+ // server decide whether to reject files without versions.
+ if (!GetFileVersionString(module, &file_version)) {
+ fwprintf(stderr, L"Warning: Could not get file version for %s\n", module);
+ }
+
+ bool success = true;
+
+ if (use_sym_upload_v2) {
+ if (argc >= currentarg + 2) {
+ api_url = argv[currentarg++];
+ api_key = argv[currentarg++];
+
+ success = DoSymUploadV2(
+ api_url,
+ api_key,
+ pdb_info.debug_file,
+ pdb_info.debug_identifier,
+ symbol_file,
+ force);
+ } else {
+ printUsageAndExit();
+ }
+ } else {
+ map<wstring, wstring> parameters;
+ parameters[L"code_file"] = code_file;
+ parameters[L"debug_file"] = pdb_info.debug_file;
+ parameters[L"debug_identifier"] = pdb_info.debug_identifier;
+ parameters[L"os"] = L"windows"; // This version of symupload is Windows-only
+ parameters[L"cpu"] = pdb_info.cpu;
+
+ map<wstring, wstring> files;
+ files[L"symbol_file"] = symbol_file;
+
+ if (!file_version.empty()) {
+ parameters[L"version"] = file_version;
+ }
+
+ // Don't make a missing product name a hard error. Issue a warning and let
+ // the server decide whether to reject files without product name.
+ if (product) {
+ parameters[L"product"] = product;
+ }
+ else {
+ fwprintf(
+ stderr,
+ L"Warning: No product name (flag --product) was specified for %s\n",
+ module);
+ }
+
+ while (currentarg < argc) {
+ int response_code;
+ if (!HTTPUpload::SendMultipartPostRequest(argv[currentarg], parameters, files,
+ timeout == -1 ? NULL : &timeout,
+ nullptr, &response_code)) {
+ success = false;
+ fwprintf(stderr,
+ L"Symbol file upload to %s failed. Response code = %ld\n",
+ argv[currentarg], response_code);
+ }
+ currentarg++;
+ }
+ }
+
+ _wunlink(symbol_file.c_str());
+
+ if (success) {
+ wprintf(L"Uploaded breakpad symbols for windows-%s/%s/%s (%s %s)\n",
+ pdb_info.cpu.c_str(), pdb_info.debug_file.c_str(),
+ pdb_info.debug_identifier.c_str(), code_file.c_str(),
+ file_version.c_str());
+ }
+
+ return success ? 0 : 1;
+}
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/windows/symupload/symupload.gyp b/toolkit/crashreporter/google-breakpad/src/tools/windows/symupload/symupload.gyp
new file mode 100644
index 0000000000..4567a4bdfd
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/windows/symupload/symupload.gyp
@@ -0,0 +1,50 @@
+# Copyright 2013 Google Inc. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+{
+ 'includes': [
+ '../../../build/common.gypi',
+ ],
+ 'targets': [
+ {
+ 'target_name': 'symupload',
+ 'type': 'executable',
+ 'sources': [
+ 'symupload.cc',
+ ],
+ 'dependencies': [
+ '../../../common/windows/common_windows.gyp:common_windows_lib',
+ ],
+ 'msvs_settings': {
+ 'VCLinkerTool': {
+ 'LargeAddressAware': '2',
+ },
+ },
+ },
+ ],
+}
diff --git a/toolkit/crashreporter/google-breakpad/src/tools/windows/tools_windows.gyp b/toolkit/crashreporter/google-breakpad/src/tools/windows/tools_windows.gyp
new file mode 100644
index 0000000000..17b88b4a7a
--- /dev/null
+++ b/toolkit/crashreporter/google-breakpad/src/tools/windows/tools_windows.gyp
@@ -0,0 +1,46 @@
+# Copyright 2017 Google Inc. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+{
+ 'includes': [
+ '../../build/common.gypi',
+ ],
+ 'targets': [
+ {
+ 'target_name': 'build_all',
+ 'type': 'none',
+ 'dependencies': [
+ './converter/ms_symbol_server_converter.gyp:*',
+ './converter_exe/converter.gyp:*',
+ './dump_syms/dump_syms.gyp:*',
+ './symupload/symupload.gyp:*',
+ ],
+ },
+ ],
+}
diff --git a/toolkit/crashreporter/injector/injector.cpp b/toolkit/crashreporter/injector/injector.cpp
new file mode 100644
index 0000000000..7fda400410
--- /dev/null
+++ b/toolkit/crashreporter/injector/injector.cpp
@@ -0,0 +1,35 @@
+/* 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 <windows.h>
+
+#include "windows/handler/exception_handler.h"
+
+using google_breakpad::ExceptionHandler;
+using std::wstring;
+
+extern "C" BOOL WINAPI DummyEntryPoint(HINSTANCE instance, DWORD reason,
+ void* reserved) {
+ __debugbreak();
+
+ return FALSE; // We're being loaded remotely, this shouldn't happen!
+}
+
+// support.microsoft.com/kb/94248
+extern "C" BOOL WINAPI _CRT_INIT(HINSTANCE hinstDLL, DWORD fdwReason,
+ LPVOID lpReserved);
+
+extern "C" __declspec(dllexport) DWORD Start(void* context) {
+ // Because the remote DLL injector does not call DllMain, we have to
+ // initialize the CRT manually
+ _CRT_INIT(nullptr, DLL_PROCESS_ATTACH, nullptr);
+
+ HANDLE hCrashPipe = reinterpret_cast<HANDLE>(context);
+
+ ExceptionHandler* e = new (std::nothrow) ExceptionHandler(
+ wstring(), nullptr, nullptr, nullptr, ExceptionHandler::HANDLER_ALL,
+ MiniDumpNormal, hCrashPipe, nullptr);
+ if (e) e->set_handle_debug_exceptions(true);
+ return 1;
+}
diff --git a/toolkit/crashreporter/injector/moz.build b/toolkit/crashreporter/injector/moz.build
new file mode 100644
index 0000000000..05aa9af37d
--- /dev/null
+++ b/toolkit/crashreporter/injector/moz.build
@@ -0,0 +1,27 @@
+# -*- 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/.
+
+SOURCES += [
+ "injector.cpp",
+]
+
+SharedLibrary("breakpadinjector")
+
+include("/ipc/chromium/chromium-config.mozbuild")
+
+LOCAL_INCLUDES += [
+ "/toolkit/crashreporter/breakpad-client",
+ "/toolkit/crashreporter/google-breakpad/src",
+]
+
+USE_STATIC_LIBS = True
+
+if CONFIG["CC_TYPE"] in ("clang", "gcc"):
+ LDFLAGS += ["-Wl,-e,_DummyEntryPoint@12"]
+else:
+ LDFLAGS += ["-ENTRY:DummyEntryPoint"]
+
+DisableStlWrapping()
diff --git a/toolkit/crashreporter/jar.mn b/toolkit/crashreporter/jar.mn
new file mode 100644
index 0000000000..641fcaa2fe
--- /dev/null
+++ b/toolkit/crashreporter/jar.mn
@@ -0,0 +1,10 @@
+# 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/.
+
+toolkit.jar:
+#ifdef MOZ_CRASHREPORTER
+ content/global/crashes.html (content/crashes.html)
+ content/global/crashes.js (content/crashes.js)
+ content/global/crashes.css (content/crashes.css)
+#endif
diff --git a/toolkit/crashreporter/mac_utils.h b/toolkit/crashreporter/mac_utils.h
new file mode 100644
index 0000000000..839baad558
--- /dev/null
+++ b/toolkit/crashreporter/mac_utils.h
@@ -0,0 +1,14 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/. */
+
+#ifndef toolkit_breakpad_mac_utils_h__
+#define toolkit_breakpad_mac_utils_h__
+
+#include "nsString.h"
+
+// Given an Objective-C NSException object, put exception info into a string.
+void GetObjCExceptionInfo(void* inException, nsACString& outString);
+
+#endif /* toolkit_breakpad_mac_utils_h__ */
diff --git a/toolkit/crashreporter/mac_utils.mm b/toolkit/crashreporter/mac_utils.mm
new file mode 100644
index 0000000000..dfceb1013f
--- /dev/null
+++ b/toolkit/crashreporter/mac_utils.mm
@@ -0,0 +1,29 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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 <Foundation/Foundation.h>
+
+#include "mac_utils.h"
+#include "nsXPCOM.h"
+#include "mozilla/MacStringHelpers.h"
+#include "mozilla/Unused.h"
+
+void GetObjCExceptionInfo(void* inException, nsACString& outString) {
+ NSException* e = (NSException*)inException;
+
+ NSString* name = [e name];
+ NSString* reason = [e reason];
+ NSArray* stackAddresses = [e callStackReturnAddresses];
+
+ outString.AssignLiteral("\nObj-C Exception data:\n");
+ outString.Append([name UTF8String]);
+ outString.AppendLiteral(": ");
+ outString.Append([reason UTF8String]);
+ outString.AppendLiteral("\n\nThrown at stack:\n");
+ for (NSNumber* address in stackAddresses) {
+ outString.AppendPrintf("0x%lx\n", [address unsignedIntegerValue]);
+ }
+ outString.AppendLiteral("\n");
+}
diff --git a/toolkit/crashreporter/minidump-analyzer/MinidumpAnalyzerUtils.h b/toolkit/crashreporter/minidump-analyzer/MinidumpAnalyzerUtils.h
new file mode 100644
index 0000000000..2fb8319be8
--- /dev/null
+++ b/toolkit/crashreporter/minidump-analyzer/MinidumpAnalyzerUtils.h
@@ -0,0 +1,115 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/. */
+
+#ifndef MinidumpAnalyzerUtils_h
+#define MinidumpAnalyzerUtils_h
+
+#ifdef XP_WIN
+# include <windows.h>
+#endif
+
+#include <algorithm>
+#include <map>
+#include <memory>
+#include <string>
+
+namespace CrashReporter {
+
+struct MinidumpAnalyzerOptions {
+ bool fullMinidump;
+ std::string forceUseModule;
+};
+
+extern MinidumpAnalyzerOptions gMinidumpAnalyzerOptions;
+
+#ifdef XP_WIN
+
+static inline std::string WideToMBCP(const std::wstring& wide, unsigned int cp,
+ bool* success = nullptr) {
+ int bufferCharLen = WideCharToMultiByte(cp, 0, wide.c_str(), wide.length(),
+ nullptr, 0, nullptr, nullptr);
+ if (!bufferCharLen) {
+ if (success) {
+ *success = false;
+ }
+
+ return "";
+ }
+
+ auto buffer = std::make_unique<char[]>(bufferCharLen);
+ if (!buffer) {
+ if (success) {
+ *success = false;
+ }
+
+ return "";
+ }
+
+ int result =
+ WideCharToMultiByte(cp, 0, wide.c_str(), wide.length(), buffer.get(),
+ bufferCharLen, nullptr, nullptr);
+ if (success) {
+ *success = result > 0;
+ }
+
+ return std::string(buffer.get(), result);
+}
+
+static inline std::wstring MBCPToWide(const std::string& aMbStr,
+ unsigned int aCodepage,
+ bool* aSuccess = nullptr) {
+ int bufferCharLen = MultiByteToWideChar(aCodepage, 0, aMbStr.c_str(),
+ aMbStr.length(), nullptr, 0);
+ if (!bufferCharLen) {
+ if (aSuccess) {
+ *aSuccess = false;
+ }
+
+ return L"";
+ }
+
+ auto buffer = std::make_unique<wchar_t[]>(bufferCharLen);
+ if (!buffer) {
+ if (aSuccess) {
+ *aSuccess = false;
+ }
+
+ return L"";
+ }
+
+ int result =
+ MultiByteToWideChar(aCodepage, 0, aMbStr.c_str(), aMbStr.length(),
+ buffer.get(), bufferCharLen);
+ if (aSuccess) {
+ *aSuccess = result > 0;
+ }
+
+ return std::wstring(buffer.get(), result);
+}
+
+static inline std::string WideToUTF8(const std::wstring& aWide,
+ bool* aSuccess = nullptr) {
+ return WideToMBCP(aWide, CP_UTF8, aSuccess);
+}
+
+static inline std::wstring UTF8ToWide(const std::string& aUtf8Str,
+ bool* aSuccess = nullptr) {
+ return MBCPToWide(aUtf8Str, CP_UTF8, aSuccess);
+}
+
+static inline std::string WideToMBCS(const std::wstring& aWide,
+ bool* aSuccess = nullptr) {
+ return WideToMBCP(aWide, CP_ACP, aSuccess);
+}
+
+static inline std::string UTF8ToMBCS(const std::string& aUtf8) {
+ return WideToMBCS(UTF8ToWide(aUtf8));
+}
+
+#endif // XP_WIN
+
+} // namespace CrashReporter
+
+#endif // MinidumpAnalyzerUtils_h
diff --git a/toolkit/crashreporter/minidump-analyzer/MozStackFrameSymbolizer.cpp b/toolkit/crashreporter/minidump-analyzer/MozStackFrameSymbolizer.cpp
new file mode 100644
index 0000000000..dbc4183429
--- /dev/null
+++ b/toolkit/crashreporter/minidump-analyzer/MozStackFrameSymbolizer.cpp
@@ -0,0 +1,117 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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 XP_WIN && HAVE_64BIT_BUILD
+
+# include "MozStackFrameSymbolizer.h"
+
+# include "MinidumpAnalyzerUtils.h"
+
+# include "processor/cfi_frame_info.h"
+
+# include <iostream>
+# include <sstream>
+# include <fstream>
+
+namespace CrashReporter {
+
+extern MinidumpAnalyzerOptions gMinidumpAnalyzerOptions;
+
+using google_breakpad::CFIFrameInfo;
+
+MozStackFrameSymbolizer::MozStackFrameSymbolizer()
+ : StackFrameSymbolizer(nullptr, nullptr) {}
+
+MozStackFrameSymbolizer::SymbolizerResult
+MozStackFrameSymbolizer::FillSourceLineInfo(const CodeModules* modules,
+ const CodeModules* unloaded_modules,
+ const SystemInfo* system_info,
+ StackFrame* stack_frame) {
+ SymbolizerResult ret = StackFrameSymbolizer::FillSourceLineInfo(
+ modules, unloaded_modules, system_info, stack_frame);
+
+ if (ret == kNoError && this->HasImplementation() &&
+ stack_frame->function_name.empty()) {
+ // Breakpad's Stackwalker::InstructionAddressSeemsValid only considers an
+ // address valid if it has associated symbols.
+ //
+ // This makes sense for complete & accurate symbols, but ours may be
+ // incomplete or wrong. Returning a function name tells Breakpad we
+ // recognize this address as code, so it's OK to use in stack scanning.
+ // This function is only called with addresses that land in this module.
+ //
+ // This allows us to fall back to stack scanning in the case where we were
+ // unable to provide CFI.
+ stack_frame->function_name = "<unknown code>";
+ }
+ return ret;
+}
+
+CFIFrameInfo* MozStackFrameSymbolizer::FindCFIFrameInfo(
+ const StackFrame* frame) {
+ std::string modulePath;
+
+ // For unit testing, support loading a specified module instead of
+ // the real one.
+ bool moduleHasBeenReplaced = false;
+ if (gMinidumpAnalyzerOptions.forceUseModule.size() > 0) {
+ modulePath = gMinidumpAnalyzerOptions.forceUseModule;
+ moduleHasBeenReplaced = true;
+ } else {
+ if (!frame->module) {
+ return nullptr;
+ }
+ modulePath = frame->module->code_file();
+ }
+
+ // Get/create the unwind parser.
+ auto itMod = mModuleMap.find(modulePath);
+ std::shared_ptr<ModuleUnwindParser> unwindParser;
+ if (itMod != mModuleMap.end()) {
+ unwindParser = itMod->second;
+ } else {
+ unwindParser.reset(new ModuleUnwindParser(modulePath));
+ mModuleMap[modulePath] = unwindParser;
+ }
+
+ UnwindCFI cfi;
+ DWORD offsetAddr;
+
+ if (moduleHasBeenReplaced) {
+ // If we are replacing a module, addresses will never line up.
+ // So just act like the 1st entry is correct.
+ offsetAddr = unwindParser->GetAnyOffsetAddr();
+ } else {
+ offsetAddr = frame->instruction - frame->module->base_address();
+ }
+
+ if (!unwindParser->GetCFI(offsetAddr, cfi)) {
+ return nullptr;
+ }
+
+ std::unique_ptr<CFIFrameInfo> rules(new CFIFrameInfo());
+
+ static const size_t exprSize = 50;
+ char expr[exprSize];
+ if (cfi.stackSize == 0) {
+ snprintf(expr, exprSize, "$rsp");
+ } else {
+ snprintf(expr, exprSize, "$rsp %d +", cfi.stackSize);
+ }
+ rules->SetCFARule(expr);
+
+ if (cfi.ripOffset == 0) {
+ snprintf(expr, exprSize, ".cfa ^");
+ } else {
+ snprintf(expr, exprSize, ".cfa %d - ^", cfi.ripOffset);
+ }
+ rules->SetRARule(expr);
+
+ return rules.release();
+}
+
+} // namespace CrashReporter
+
+#endif // XP_WIN && HAVE_64BIT_BUILD
diff --git a/toolkit/crashreporter/minidump-analyzer/MozStackFrameSymbolizer.h b/toolkit/crashreporter/minidump-analyzer/MozStackFrameSymbolizer.h
new file mode 100644
index 0000000000..dfe4299d85
--- /dev/null
+++ b/toolkit/crashreporter/minidump-analyzer/MozStackFrameSymbolizer.h
@@ -0,0 +1,48 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/. */
+
+#ifndef MozStackFrameSymbolizer_h
+#define MozStackFrameSymbolizer_h
+
+#if XP_WIN && HAVE_64BIT_BUILD
+
+# include "Win64ModuleUnwindMetadata.h"
+
+# include "google_breakpad/processor/stack_frame_symbolizer.h"
+# include "google_breakpad/processor/stack_frame.h"
+
+# include <memory>
+
+namespace CrashReporter {
+
+using google_breakpad::CodeModule;
+using google_breakpad::CodeModules;
+using google_breakpad::SourceLineResolverInterface;
+using google_breakpad::StackFrame;
+using google_breakpad::StackFrameSymbolizer;
+using google_breakpad::SymbolSupplier;
+using google_breakpad::SystemInfo;
+
+class MozStackFrameSymbolizer : public StackFrameSymbolizer {
+ using google_breakpad::StackFrameSymbolizer::SymbolizerResult;
+
+ std::map<std::string, std::shared_ptr<ModuleUnwindParser>> mModuleMap;
+
+ public:
+ MozStackFrameSymbolizer();
+
+ virtual SymbolizerResult FillSourceLineInfo(
+ const CodeModules* modules, const CodeModules* unloaded_modules,
+ const SystemInfo* system_info, StackFrame* stack_frame);
+
+ virtual class google_breakpad::CFIFrameInfo* FindCFIFrameInfo(
+ const StackFrame* frame);
+};
+
+} // namespace CrashReporter
+
+#endif // XP_WIN && HAVE_64BIT_BUILD
+
+#endif // MozStackFrameSymbolizer_h
diff --git a/toolkit/crashreporter/minidump-analyzer/Win64ModuleUnwindMetadata.cpp b/toolkit/crashreporter/minidump-analyzer/Win64ModuleUnwindMetadata.cpp
new file mode 100644
index 0000000000..4978415e86
--- /dev/null
+++ b/toolkit/crashreporter/minidump-analyzer/Win64ModuleUnwindMetadata.cpp
@@ -0,0 +1,227 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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 XP_WIN && HAVE_64BIT_BUILD
+
+# include "Win64ModuleUnwindMetadata.h"
+
+# include "MinidumpAnalyzerUtils.h"
+
+# include <windows.h>
+# include <winnt.h>
+# include <imagehlp.h>
+# include <iostream>
+# include <set>
+# include <sstream>
+# include <string>
+
+# include "mozilla/WindowsUnwindInfo.h"
+
+using namespace mozilla;
+
+namespace CrashReporter {
+
+ModuleUnwindParser::~ModuleUnwindParser() {
+ if (mImg) {
+ ImageUnload(mImg);
+ }
+}
+
+void* ModuleUnwindParser::RvaToVa(ULONG aRva) {
+ return ImageRvaToVa(mImg->FileHeader, mImg->MappedAddress, aRva,
+ &mImg->LastRvaSection);
+}
+
+ModuleUnwindParser::ModuleUnwindParser(const std::string& aPath)
+ : mPath(aPath) {
+ // Convert wchar to native charset because ImageLoad only takes
+ // a PSTR as input.
+ std::string code_file = UTF8ToMBCS(aPath);
+
+ mImg = ImageLoad((PSTR)code_file.c_str(), NULL);
+ if (!mImg || !mImg->FileHeader) {
+ return;
+ }
+
+ PIMAGE_OPTIONAL_HEADER64 optional_header = &mImg->FileHeader->OptionalHeader;
+ if (optional_header->Magic != IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
+ return;
+ }
+
+ DWORD exception_rva =
+ optional_header->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION]
+ .VirtualAddress;
+
+ DWORD exception_size =
+ optional_header->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size;
+
+ auto funcs = (PIMAGE_RUNTIME_FUNCTION_ENTRY)RvaToVa(exception_rva);
+ if (!funcs) {
+ return;
+ }
+
+ for (DWORD i = 0; i < exception_size / sizeof(*funcs); i++) {
+ mUnwindMap[funcs[i].BeginAddress] = &funcs[i];
+ }
+}
+
+bool ModuleUnwindParser::GenerateCFIForFunction(
+ IMAGE_RUNTIME_FUNCTION_ENTRY& aFunc, UnwindCFI& aRet) {
+ DWORD unwind_rva = aFunc.UnwindInfoAddress;
+ // Holds RVA to all visited IMAGE_RUNTIME_FUNCTION_ENTRY, to avoid
+ // circular references.
+ std::set<DWORD> visited;
+
+ // Follow chained function entries
+ while (unwind_rva & 0x1) {
+ unwind_rva ^= 0x1;
+
+ if (visited.end() != visited.find(unwind_rva)) {
+ return false;
+ }
+ visited.insert(unwind_rva);
+
+ auto chained_func = (PIMAGE_RUNTIME_FUNCTION_ENTRY)RvaToVa(unwind_rva);
+ if (!chained_func) {
+ return false;
+ }
+ unwind_rva = chained_func->UnwindInfoAddress;
+ }
+
+ visited.insert(unwind_rva);
+
+ auto unwind_info = (UnwindInfo*)RvaToVa(unwind_rva);
+ if (!unwind_info) {
+ return false;
+ }
+
+ DWORD stack_size = 8; // minimal stack size is 8 for RIP
+ DWORD rip_offset = 8;
+ do {
+ for (uint8_t 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:
+ // To correctly track RSP when it's been transferred to another
+ // register, we would need to emit CFI records for every unwind op.
+ // For simplicity, don't emit CFI records for this function as
+ // we know it will be incorrect after this point.
+ return false;
+ case UWOP_SAVE_NONVOL:
+ case UWOP_SAVE_XMM: // also v2 UWOP_EPILOG
+ case UWOP_SAVE_XMM128: {
+ c++; // skip slot with offset
+ break;
+ }
+ case UWOP_SAVE_NONVOL_FAR:
+ case UWOP_SAVE_XMM_FAR: // also v2 UWOP_SPARE
+ 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;
+ }
+ default: {
+ return false;
+ }
+ }
+ }
+
+ if (unwind_info->flags & UNW_FLAG_CHAININFO) {
+ auto chained_func = (PIMAGE_RUNTIME_FUNCTION_ENTRY)((
+ unwind_info->unwind_code + ((unwind_info->count_of_codes + 1) & ~1)));
+
+ if (visited.end() != visited.find(chained_func->UnwindInfoAddress)) {
+ return false; // Circular reference
+ }
+
+ visited.insert(chained_func->UnwindInfoAddress);
+
+ unwind_info = (UnwindInfo*)RvaToVa(chained_func->UnwindInfoAddress);
+ } else {
+ unwind_info = nullptr;
+ }
+ } while (unwind_info);
+
+ aRet.beginAddress = aFunc.BeginAddress;
+ aRet.size = aFunc.EndAddress - aFunc.BeginAddress;
+ aRet.stackSize = stack_size;
+ aRet.ripOffset = rip_offset;
+ return true;
+}
+
+// For unit testing we sometimes need any address that's valid in this module.
+// Just return the first address we know of.
+DWORD
+ModuleUnwindParser::GetAnyOffsetAddr() const {
+ if (mUnwindMap.size() < 1) {
+ return 0;
+ }
+ return mUnwindMap.begin()->first;
+}
+
+bool ModuleUnwindParser::GetCFI(DWORD aAddress, UnwindCFI& aRet) {
+ // Figure out the begin address of the requested address.
+ auto itUW = mUnwindMap.lower_bound(aAddress + 1);
+ if (itUW == mUnwindMap.begin()) {
+ return false; // address before this module.
+ }
+ --itUW;
+
+ // Ensure that the function entry is big enough to contain this address.
+ IMAGE_RUNTIME_FUNCTION_ENTRY& func = *itUW->second;
+ if (aAddress > func.EndAddress) {
+ return false;
+ }
+
+ // Do we have CFI for this function already?
+ auto itCFI = mCFIMap.find(aAddress);
+ if (itCFI != mCFIMap.end()) {
+ aRet = itCFI->second;
+ return true;
+ }
+
+ // No, generate it.
+ if (!GenerateCFIForFunction(func, aRet)) {
+ return false;
+ }
+
+ mCFIMap[func.BeginAddress] = aRet;
+ return true;
+}
+
+} // namespace CrashReporter
+
+#endif // XP_WIN && HAVE_64BIT_BUILD
diff --git a/toolkit/crashreporter/minidump-analyzer/Win64ModuleUnwindMetadata.h b/toolkit/crashreporter/minidump-analyzer/Win64ModuleUnwindMetadata.h
new file mode 100644
index 0000000000..3ce9dd7bb4
--- /dev/null
+++ b/toolkit/crashreporter/minidump-analyzer/Win64ModuleUnwindMetadata.h
@@ -0,0 +1,56 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/. */
+
+#ifndef Win64ModuleUnwindMetadata_h
+#define Win64ModuleUnwindMetadata_h
+
+#if XP_WIN && HAVE_64BIT_BUILD
+
+# include <functional>
+# include <map>
+# include <string>
+
+# include <windows.h>
+# include <winnt.h>
+# include <imagehlp.h>
+
+namespace CrashReporter {
+
+struct UnwindCFI {
+ uint32_t beginAddress;
+ uint32_t size;
+ uint32_t stackSize;
+ uint32_t ripOffset;
+};
+
+// Does lazy-parsing of unwind info.
+class ModuleUnwindParser {
+ PLOADED_IMAGE mImg;
+ std::string mPath;
+
+ // Maps begin address to exception record.
+ // Populated upon construction.
+ std::map<DWORD, PIMAGE_RUNTIME_FUNCTION_ENTRY> mUnwindMap;
+
+ // Maps begin address to CFI.
+ // Populated as needed.
+ std::map<DWORD, UnwindCFI> mCFIMap;
+
+ bool GenerateCFIForFunction(IMAGE_RUNTIME_FUNCTION_ENTRY& aFunc,
+ UnwindCFI& aRet);
+ void* RvaToVa(ULONG aRva);
+
+ public:
+ explicit ModuleUnwindParser(const std::string& aPath);
+ ~ModuleUnwindParser();
+ bool GetCFI(DWORD aAddress, UnwindCFI& aRet);
+ DWORD GetAnyOffsetAddr() const;
+};
+
+} // namespace CrashReporter
+
+#endif // XP_WIN && HAVE_64BIT_BUILD
+
+#endif // Win64ModuleUnwindMetadata_h
diff --git a/toolkit/crashreporter/minidump-analyzer/minidump-analyzer.cpp b/toolkit/crashreporter/minidump-analyzer/minidump-analyzer.cpp
new file mode 100644
index 0000000000..a90b7edcbb
--- /dev/null
+++ b/toolkit/crashreporter/minidump-analyzer/minidump-analyzer.cpp
@@ -0,0 +1,604 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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 <cstdio>
+#include <cstring>
+#include <string>
+#include <sstream>
+
+#include "json/json.h"
+#include "google_breakpad/processor/basic_source_line_resolver.h"
+#include "google_breakpad/processor/call_stack.h"
+#include "google_breakpad/processor/code_module.h"
+#include "google_breakpad/processor/code_modules.h"
+#include "google_breakpad/processor/minidump.h"
+#include "google_breakpad/processor/minidump_processor.h"
+#include "google_breakpad/processor/process_state.h"
+#include "google_breakpad/processor/stack_frame.h"
+#include "processor/pathname_stripper.h"
+
+#include "mozilla/FStream.h"
+#include "mozilla/Unused.h"
+
+#if defined(XP_WIN)
+
+# include <windows.h>
+# include "mozilla/glue/WindowsDllServices.h"
+
+#elif defined(XP_UNIX) || defined(XP_MACOSX)
+
+# include <sys/types.h>
+# include <sys/stat.h>
+# include <unistd.h>
+
+#endif
+
+#include "MinidumpAnalyzerUtils.h"
+
+#if XP_WIN && HAVE_64BIT_BUILD && defined(_M_X64)
+# include "MozStackFrameSymbolizer.h"
+#endif
+
+namespace CrashReporter {
+
+#if defined(XP_WIN)
+
+static mozilla::glue::BasicDllServices gDllServices;
+
+#endif
+
+using std::hex;
+using std::ios;
+using std::ios_base;
+using std::map;
+using std::showbase;
+using std::string;
+using std::stringstream;
+using std::wstring;
+
+using google_breakpad::BasicSourceLineResolver;
+using google_breakpad::CallStack;
+using google_breakpad::CodeModule;
+using google_breakpad::CodeModules;
+using google_breakpad::Minidump;
+using google_breakpad::MinidumpProcessor;
+using google_breakpad::PathnameStripper;
+using google_breakpad::ProcessResult;
+using google_breakpad::ProcessState;
+using google_breakpad::StackFrame;
+
+using mozilla::IFStream;
+using mozilla::OFStream;
+using mozilla::Unused;
+
+MinidumpAnalyzerOptions gMinidumpAnalyzerOptions;
+
+// Path of the minidump to be analyzed.
+static string gMinidumpPath;
+
+struct ModuleCompare {
+ bool operator()(const CodeModule* aLhs, const CodeModule* aRhs) const {
+ return aLhs->base_address() < aRhs->base_address();
+ }
+};
+
+typedef map<const CodeModule*, unsigned int, ModuleCompare> OrderedModulesMap;
+
+static void AddModulesFromCallStack(OrderedModulesMap& aOrderedModules,
+ const CallStack* aStack) {
+ int frameCount = aStack->frames()->size();
+
+ for (int frameIndex = 0; frameIndex < frameCount; ++frameIndex) {
+ const StackFrame* frame = aStack->frames()->at(frameIndex);
+
+ if (frame->module) {
+ aOrderedModules.insert(
+ std::pair<const CodeModule*, unsigned int>(frame->module, 0));
+ }
+ }
+}
+
+static void PopulateModuleList(const ProcessState& aProcessState,
+ OrderedModulesMap& aOrderedModules,
+ bool aFullStacks) {
+ int threadCount = aProcessState.threads()->size();
+ int requestingThread = aProcessState.requesting_thread();
+
+ if (!aFullStacks && (requestingThread != -1)) {
+ AddModulesFromCallStack(aOrderedModules,
+ aProcessState.threads()->at(requestingThread));
+ } else {
+ for (int threadIndex = 0; threadIndex < threadCount; ++threadIndex) {
+ AddModulesFromCallStack(aOrderedModules,
+ aProcessState.threads()->at(threadIndex));
+ }
+ }
+
+ int moduleCount = 0;
+ for (auto& itr : aOrderedModules) {
+ itr.second = moduleCount++;
+ }
+}
+
+static const char kExtraDataExtension[] = ".extra";
+
+static string ToHex(uint64_t aValue) {
+ stringstream output;
+
+ output << hex << showbase << aValue;
+
+ return output.str();
+}
+
+// Convert the stack frame trust value into a readable string.
+
+static string FrameTrust(const StackFrame::FrameTrust aTrust) {
+ switch (aTrust) {
+ case StackFrame::FRAME_TRUST_NONE:
+ return "none";
+ case StackFrame::FRAME_TRUST_SCAN:
+ return "scan";
+ case StackFrame::FRAME_TRUST_CFI_SCAN:
+ return "cfi_scan";
+ case StackFrame::FRAME_TRUST_FP:
+ return "frame_pointer";
+ case StackFrame::FRAME_TRUST_CFI:
+ return "cfi";
+ case StackFrame::FRAME_TRUST_PREWALKED:
+ return "prewalked";
+ case StackFrame::FRAME_TRUST_CONTEXT:
+ return "context";
+ }
+
+ return "none";
+}
+
+// Convert the result value of the minidump processing step into a readable
+// string.
+
+static string ResultString(ProcessResult aResult) {
+ switch (aResult) {
+ case google_breakpad::PROCESS_OK:
+ return "OK";
+ case google_breakpad::PROCESS_ERROR_MINIDUMP_NOT_FOUND:
+ return "ERROR_MINIDUMP_NOT_FOUND";
+ case google_breakpad::PROCESS_ERROR_NO_MINIDUMP_HEADER:
+ return "ERROR_NO_MINIDUMP_HEADER";
+ case google_breakpad::PROCESS_ERROR_NO_THREAD_LIST:
+ return "ERROR_NO_THREAD_LIST";
+ case google_breakpad::PROCESS_ERROR_GETTING_THREAD:
+ return "ERROR_GETTING_THREAD";
+ case google_breakpad::PROCESS_ERROR_GETTING_THREAD_ID:
+ return "ERROR_GETTING_THREAD_ID";
+ case google_breakpad::PROCESS_ERROR_DUPLICATE_REQUESTING_THREADS:
+ return "ERROR_DUPLICATE_REQUESTING_THREADS";
+ case google_breakpad::PROCESS_SYMBOL_SUPPLIER_INTERRUPTED:
+ return "SYMBOL_SUPPLIER_INTERRUPTED";
+ default:
+ return "";
+ }
+}
+
+// Convert the list of stack frames to JSON and append them to the array
+// specified in the |aNode| parameter.
+
+static void ConvertStackToJSON(const ProcessState& aProcessState,
+ const OrderedModulesMap& aOrderedModules,
+ const CallStack* aStack, Json::Value& aNode) {
+ int frameCount = aStack->frames()->size();
+
+ for (int frameIndex = 0; frameIndex < frameCount; ++frameIndex) {
+ const StackFrame* frame = aStack->frames()->at(frameIndex);
+ Json::Value frameNode;
+
+ if (frame->module) {
+ const auto& itr = aOrderedModules.find(frame->module);
+
+ if (itr != aOrderedModules.end()) {
+ frameNode["module_index"] = (*itr).second;
+ }
+ }
+
+ frameNode["trust"] = FrameTrust(frame->trust);
+ // The 'ip' field is equivalent to socorro's 'offset' field
+ frameNode["ip"] = ToHex(frame->instruction);
+
+ aNode.append(frameNode);
+ }
+}
+
+// Extract the list of certifications subjects from the list of modules and
+// store it in the |aCertSubjects| parameter
+
+static void RetrieveCertSubjects(const CodeModules* modules,
+ Json::Value& aCertSubjects) {
+#if defined(XP_WIN)
+ if (modules) {
+ for (size_t i = 0; i < modules->module_count(); i++) {
+ const CodeModule* module = modules->GetModuleAtIndex(i);
+ auto certSubject = gDllServices.GetBinaryOrgName(
+ UTF8ToWide(module->code_file()).c_str());
+ if (certSubject) {
+ string strSubject(WideToUTF8(certSubject.get()));
+ // Json::Value::operator[] creates and returns a null member if the key
+ // does not exist.
+ Json::Value& subjectNode = aCertSubjects[strSubject];
+ if (!subjectNode) {
+ // If the member is null, we want to convert that to an array.
+ subjectNode = Json::Value(Json::arrayValue);
+ }
+
+ // Now we're guaranteed that subjectNode is an array. Add the new entry.
+ subjectNode.append(PathnameStripper::File(module->code_file()));
+ }
+ }
+ }
+#endif // defined(XP_WIN)
+}
+
+// Convert the list of modules to JSON and append them to the array specified
+// in the |aNode| parameter.
+
+static int ConvertModulesToJSON(const ProcessState& aProcessState,
+ const OrderedModulesMap& aOrderedModules,
+ Json::Value& aNode) {
+ const CodeModules* modules = aProcessState.modules();
+
+ if (!modules) {
+ return -1;
+ }
+
+ uint64_t mainAddress = 0;
+ const CodeModule* mainModule = modules->GetMainModule();
+
+ if (mainModule) {
+ mainAddress = mainModule->base_address();
+ }
+
+ int mainModuleIndex = -1;
+
+ for (const auto& itr : aOrderedModules) {
+ const CodeModule* module = itr.first;
+
+ if ((module->base_address() == mainAddress) && mainModule) {
+ mainModuleIndex = itr.second;
+ }
+
+ Json::Value moduleNode;
+ moduleNode["filename"] = PathnameStripper::File(module->code_file());
+ moduleNode["code_id"] = PathnameStripper::File(module->code_identifier());
+ moduleNode["version"] = module->version();
+ moduleNode["debug_file"] = PathnameStripper::File(module->debug_file());
+ moduleNode["debug_id"] = module->debug_identifier();
+ moduleNode["base_addr"] = ToHex(module->base_address());
+ moduleNode["end_addr"] = ToHex(module->base_address() + module->size());
+
+ aNode.append(moduleNode);
+ }
+
+ return mainModuleIndex;
+}
+
+// Convert the list of unloaded modules to JSON and append them to the array
+// specified in the |aNode| parameter. Return the number of unloaded modules
+// that were found.
+
+static size_t ConvertUnloadedModulesToJSON(const ProcessState& aProcessState,
+ Json::Value& aNode) {
+ const CodeModules* unloadedModules = aProcessState.unloaded_modules();
+ if (!unloadedModules) {
+ return 0;
+ }
+
+ const size_t unloadedModulesLen = unloadedModules->module_count();
+ for (size_t i = 0; i < unloadedModulesLen; i++) {
+ const CodeModule* unloadedModule = unloadedModules->GetModuleAtIndex(i);
+
+ Json::Value unloadedModuleNode;
+ unloadedModuleNode["filename"] =
+ PathnameStripper::File(unloadedModule->code_file());
+ unloadedModuleNode["code_id"] =
+ PathnameStripper::File(unloadedModule->code_identifier());
+ unloadedModuleNode["base_addr"] = ToHex(unloadedModule->base_address());
+ unloadedModuleNode["end_addr"] =
+ ToHex(unloadedModule->base_address() + unloadedModule->size());
+
+ aNode.append(unloadedModuleNode);
+ }
+
+ return unloadedModulesLen;
+}
+
+// Convert the process state to JSON, this includes information about the
+// crash, the module list and stack traces for every thread
+
+static void ConvertProcessStateToJSON(const ProcessState& aProcessState,
+ Json::Value& aStackTraces,
+ const bool aFullStacks,
+ Json::Value& aCertSubjects) {
+ // Crash info
+ Json::Value crashInfo;
+ int requestingThread = aProcessState.requesting_thread();
+
+ if (aProcessState.crashed()) {
+ crashInfo["type"] = aProcessState.crash_reason();
+ crashInfo["address"] = ToHex(aProcessState.crash_address());
+
+ if (requestingThread != -1) {
+ // Record the crashing thread index only if this is a full minidump
+ // and all threads' stacks are present, otherwise only the crashing
+ // thread stack is written out and this field is set to 0.
+ crashInfo["crashing_thread"] = aFullStacks ? requestingThread : 0;
+ }
+ } else {
+ crashInfo["type"] = Json::Value(Json::nullValue);
+ // Add assertion info, if available
+ string assertion = aProcessState.assertion();
+
+ if (!assertion.empty()) {
+ crashInfo["assertion"] = assertion;
+ }
+ }
+
+ aStackTraces["crash_info"] = crashInfo;
+
+ // Modules
+ OrderedModulesMap orderedModules;
+ PopulateModuleList(aProcessState, orderedModules, aFullStacks);
+
+ Json::Value modules(Json::arrayValue);
+ int mainModule = ConvertModulesToJSON(aProcessState, orderedModules, modules);
+
+ if (mainModule != -1) {
+ aStackTraces["main_module"] = mainModule;
+ }
+
+ aStackTraces["modules"] = modules;
+
+ Json::Value unloadedModules(Json::arrayValue);
+ size_t unloadedModulesLen =
+ ConvertUnloadedModulesToJSON(aProcessState, unloadedModules);
+
+ if (unloadedModulesLen > 0) {
+ aStackTraces["unloaded_modules"] = unloadedModules;
+ }
+
+ RetrieveCertSubjects(aProcessState.modules(), aCertSubjects);
+ RetrieveCertSubjects(aProcessState.unloaded_modules(), aCertSubjects);
+
+ // Threads
+ Json::Value threads(Json::arrayValue);
+ int threadCount = aProcessState.threads()->size();
+
+ if (!aFullStacks && (requestingThread != -1)) {
+ // Only add the crashing thread
+ Json::Value thread;
+ Json::Value stack(Json::arrayValue);
+ const CallStack* rawStack = aProcessState.threads()->at(requestingThread);
+
+ ConvertStackToJSON(aProcessState, orderedModules, rawStack, stack);
+ thread["frames"] = stack;
+ threads.append(thread);
+ } else {
+ for (int threadIndex = 0; threadIndex < threadCount; ++threadIndex) {
+ Json::Value thread;
+ Json::Value stack(Json::arrayValue);
+ const CallStack* rawStack = aProcessState.threads()->at(threadIndex);
+
+ ConvertStackToJSON(aProcessState, orderedModules, rawStack, stack);
+ thread["frames"] = stack;
+ threads.append(thread);
+ }
+ }
+
+ aStackTraces["threads"] = threads;
+}
+
+// Process the minidump file and append the JSON-formatted stack traces to
+// the node specified in |aStackTraces|. We also populate |aCertSubjects| with
+// information about the certificates used to sign modules, when present and
+// supported by the underlying OS.
+static bool ProcessMinidump(Json::Value& aStackTraces,
+ Json::Value& aCertSubjects, const string& aDumpFile,
+ const bool aFullStacks) {
+#if XP_WIN && HAVE_64BIT_BUILD && defined(_M_X64)
+ MozStackFrameSymbolizer symbolizer;
+ MinidumpProcessor minidumpProcessor(&symbolizer, false);
+#else
+ BasicSourceLineResolver resolver;
+ // We don't have a valid symbol resolver so we pass nullptr instead.
+ MinidumpProcessor minidumpProcessor(nullptr, &resolver);
+#endif
+
+ // Process the minidump.
+#if defined(XP_WIN)
+ // Breakpad invokes std::ifstream directly, so this path needs to be ANSI
+ Minidump dump(UTF8ToMBCS(aDumpFile));
+#else
+ Minidump dump(aDumpFile);
+#endif // defined(XP_WIN)
+ if (!dump.Read()) {
+ return false;
+ }
+
+ ProcessResult rv;
+ ProcessState processState;
+ rv = minidumpProcessor.Process(&dump, &processState);
+ aStackTraces["status"] = ResultString(rv);
+
+ ConvertProcessStateToJSON(processState, aStackTraces, aFullStacks,
+ aCertSubjects);
+
+ return true;
+}
+
+static bool ReadExtraFile(const string& aExtraDataPath, Json::Value& aExtra) {
+ IFStream f(
+#if defined(XP_WIN)
+ UTF8ToWide(aExtraDataPath).c_str(),
+#else
+ aExtraDataPath.c_str(),
+#endif // defined(XP_WIN)
+ ios::in);
+ if (!f.is_open()) {
+ return false;
+ }
+
+ Json::CharReaderBuilder builder;
+ return parseFromStream(builder, f, &aExtra, nullptr);
+}
+
+// Update the extra data file by adding the StackTraces and ModuleSignatureInfo
+// fields that contain the JSON outputs of this program.
+static bool UpdateExtraDataFile(const string& aDumpPath,
+ const Json::Value& aStackTraces,
+ const Json::Value& aCertSubjects) {
+ string extraDataPath(aDumpPath);
+ int dot = extraDataPath.rfind('.');
+
+ if (dot < 0) {
+ return false; // Not a valid dump path
+ }
+
+ extraDataPath.replace(dot, extraDataPath.length() - dot, kExtraDataExtension);
+
+ Json::Value extra;
+ if (!ReadExtraFile(extraDataPath, extra)) {
+ return false;
+ }
+
+ OFStream f(
+#if defined(XP_WIN)
+ UTF8ToWide(extraDataPath).c_str(),
+#else
+ extraDataPath.c_str(),
+#endif // defined(XP_WIN)
+ ios::out | ios::trunc);
+
+ bool res = false;
+ if (f.is_open()) {
+ Json::StreamWriterBuilder builder;
+ builder["indentation"] = "";
+
+ // The StackTraces field is not stored as a string because it's not a
+ // crash annotation. It's only used by the crash reporter client which
+ // strips it before submitting the other annotations to Socorro.
+ extra["StackTraces"] = aStackTraces;
+
+ if (!!aCertSubjects) {
+ extra["ModuleSignatureInfo"] = Json::writeString(builder, aCertSubjects);
+ }
+
+ std::unique_ptr<Json::StreamWriter> writer(builder.newStreamWriter());
+ writer->write(extra, &f);
+ f << "\n";
+ res = !f.fail();
+ f.close();
+ }
+
+ return res;
+}
+
+static bool GenerateStacks(const string& aDumpPath, const bool aFullStacks) {
+ Json::Value stackTraces;
+ Json::Value certSubjects;
+
+ if (!ProcessMinidump(stackTraces, certSubjects, aDumpPath, aFullStacks)) {
+ return false;
+ }
+
+ return UpdateExtraDataFile(aDumpPath, stackTraces, certSubjects);
+}
+
+} // namespace CrashReporter
+
+using namespace CrashReporter;
+
+#if defined(XP_WIN)
+# define XP_LITERAL(s) L##s
+#else
+# define XP_LITERAL(s) s
+#endif
+
+template <typename CharT>
+struct CharTraits;
+
+template <>
+struct CharTraits<char> {
+ static int compare(const char* left, const char* right) {
+ return strcmp(left, right);
+ }
+
+ static string& assign(string& left, const char* right) {
+ left = right;
+ return left;
+ }
+};
+
+#if defined(XP_WIN)
+
+template <>
+struct CharTraits<wchar_t> {
+ static int compare(const wchar_t* left, const wchar_t* right) {
+ return wcscmp(left, right);
+ }
+
+ static string& assign(string& left, const wchar_t* right) {
+ left = WideToUTF8(right);
+ return left;
+ }
+};
+
+#endif // defined(XP_WIN)
+
+static void LowerPriority() {
+#if defined(XP_WIN)
+ Unused << SetPriorityClass(GetCurrentProcess(),
+ PROCESS_MODE_BACKGROUND_BEGIN);
+#else // Linux, MacOS X, etc...
+ Unused << nice(20);
+#endif
+}
+
+template <typename CharT, typename Traits = CharTraits<CharT>>
+static void ParseArguments(int argc, CharT** argv) {
+ if (argc <= 1) {
+ exit(EXIT_FAILURE);
+ }
+
+ for (int i = 1; i < argc - 1; i++) {
+ if (!Traits::compare(argv[i], XP_LITERAL("--full"))) {
+ gMinidumpAnalyzerOptions.fullMinidump = true;
+ } else if (!Traits::compare(argv[i], XP_LITERAL("--force-use-module")) &&
+ (i < argc - 2)) {
+ Traits::assign(gMinidumpAnalyzerOptions.forceUseModule, argv[i + 1]);
+ ++i;
+ } else {
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ Traits::assign(gMinidumpPath, argv[argc - 1]);
+}
+
+#if defined(XP_WIN)
+// WARNING: Windows does *NOT* use UTF8 for char strings off the command line!
+// Using wmain here so that the CRT doesn't need to perform a wasteful and
+// lossy UTF-16 to MBCS conversion; ParseArguments will convert to UTF8
+// directly.
+extern "C" int wmain(int argc, wchar_t** argv)
+#else
+int main(int argc, char** argv)
+#endif
+{
+ LowerPriority();
+ ParseArguments(argc, argv);
+
+ if (!GenerateStacks(gMinidumpPath, gMinidumpAnalyzerOptions.fullMinidump)) {
+ exit(EXIT_FAILURE);
+ }
+
+ exit(EXIT_SUCCESS);
+}
diff --git a/toolkit/crashreporter/minidump-analyzer/minidump-analyzer.exe.manifest b/toolkit/crashreporter/minidump-analyzer/minidump-analyzer.exe.manifest
new file mode 100644
index 0000000000..731502e805
--- /dev/null
+++ b/toolkit/crashreporter/minidump-analyzer/minidump-analyzer.exe.manifest
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
+<assemblyIdentity
+ version="1.0.0.0"
+ processorArchitecture="*"
+ name="minidump-analyzer"
+ type="win32"
+/>
+<dependency>
+ <dependentAssembly>
+ <assemblyIdentity
+ type="win32"
+ name="mozglue"
+ version="1.0.0.0"
+ language="*"
+ />
+ </dependentAssembly>
+</dependency>
+</assembly>
diff --git a/toolkit/crashreporter/minidump-analyzer/moz.build b/toolkit/crashreporter/minidump-analyzer/moz.build
new file mode 100644
index 0000000000..b6b3cebfea
--- /dev/null
+++ b/toolkit/crashreporter/minidump-analyzer/moz.build
@@ -0,0 +1,43 @@
+# -*- 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/.
+
+GeckoProgram("minidump-analyzer", linkage=None)
+
+if CONFIG["OS_TARGET"] == "WINNT":
+ DEFINES["UNICODE"] = True
+ DEFINES["_UNICODE"] = True
+
+ if CONFIG["CPU_ARCH"] == "x86_64":
+ UNIFIED_SOURCES += [
+ "MozStackFrameSymbolizer.cpp",
+ "Win64ModuleUnwindMetadata.cpp",
+ ]
+
+ OS_LIBS += ["dbghelp", "imagehlp"]
+
+if CONFIG["OS_TARGET"] == "WINNT" and CONFIG["CC_TYPE"] in ("gcc", "clang"):
+ # This allows us to use wmain as the entry point on mingw
+ LDFLAGS += [
+ "-municode",
+ ]
+
+UNIFIED_SOURCES += [
+ "minidump-analyzer.cpp",
+]
+
+USE_LIBS += [
+ "breakpad_processor",
+ "jsoncpp",
+]
+
+LOCAL_INCLUDES += [
+ "/toolkit/components/jsoncpp/include",
+]
+
+if CONFIG["OS_TARGET"] != "WINNT":
+ DisableStlWrapping()
+
+include("/toolkit/crashreporter/crashreporter.mozbuild")
diff --git a/toolkit/crashreporter/moz.build b/toolkit/crashreporter/moz.build
new file mode 100644
index 0000000000..4e3b77caa7
--- /dev/null
+++ b/toolkit/crashreporter/moz.build
@@ -0,0 +1,139 @@
+# -*- 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/.
+
+SPHINX_TREES["crashreporter"] = "docs"
+
+with Files("docs/**"):
+ SCHEDULES.exclusive = ["docs"]
+
+EXPORTS += [
+ "!CrashAnnotations.h",
+ "nsExceptionHandler.h",
+]
+
+JAR_MANIFESTS += ["jar.mn"]
+
+UNIFIED_SOURCES = [
+ "CrashAnnotations.cpp",
+ "nsExceptionHandlerUtils.cpp",
+]
+
+FINAL_LIBRARY = "xul"
+
+if CONFIG["MOZ_CRASHREPORTER"]:
+ if CONFIG["OS_ARCH"] == "WINNT":
+ DIRS += [
+ "breakpad-windows-libxul",
+ "google-breakpad/src/common",
+ "google-breakpad/src/processor",
+ "mozwer",
+ "mozwer-rust",
+ ]
+
+ if CONFIG["MOZ_CRASHREPORTER_INJECTOR"]:
+ DIRS += ["breakpad-windows-standalone"]
+
+ elif CONFIG["OS_ARCH"] == "Darwin":
+ DIRS += [
+ "breakpad-client",
+ "breakpad-client/mac/crash_generation",
+ "breakpad-client/mac/handler",
+ "google-breakpad/src/common",
+ "google-breakpad/src/common/mac",
+ "google-breakpad/src/processor",
+ ]
+
+ elif CONFIG["OS_ARCH"] == "Linux":
+ DIRS += [
+ "breakpad-client",
+ "breakpad-client/linux/",
+ "google-breakpad/src/common",
+ "google-breakpad/src/common/linux",
+ "google-breakpad/src/processor",
+ ]
+
+ if CONFIG["MOZ_OXIDIZED_BREAKPAD"]:
+ DIRS += ["rust_minidump_writer_linux"]
+
+ if CONFIG["OS_TARGET"] != "Android":
+ DIRS += ["minidump-analyzer"]
+
+ DIRS += [
+ "client",
+ ]
+
+ if CONFIG["MOZ_CRASHREPORTER_INJECTOR"]:
+ DIRS += ["injector"]
+ UNIFIED_SOURCES += [
+ "InjectCrashReporter.cpp",
+ "LoadLibraryRemote.cpp",
+ ]
+
+ TEST_DIRS += ["test"]
+
+ UNIFIED_SOURCES += [
+ "nsExceptionHandler.cpp",
+ ]
+
+ if CONFIG["OS_ARCH"] == "Darwin":
+ UNIFIED_SOURCES += [
+ "mac_utils.mm",
+ ]
+
+ EXTRA_JS_MODULES += [
+ "CrashReports.sys.mjs",
+ "CrashSubmit.sys.mjs",
+ ]
+
+ include("/ipc/chromium/chromium-config.mozbuild")
+
+ if CONFIG["OS_TARGET"] == "Android":
+ DEFINES["ANDROID_NDK_MAJOR_VERSION"] = CONFIG["ANDROID_NDK_MAJOR_VERSION"]
+ DEFINES["ANDROID_NDK_MINOR_VERSION"] = CONFIG["ANDROID_NDK_MINOR_VERSION"]
+ DEFINES["ANDROID_PACKAGE_NAME"] = '"%s"' % CONFIG["ANDROID_PACKAGE_NAME"]
+ # NDK5 workarounds
+ DEFINES["_STLP_CONST_CONSTRUCTOR_BUG"] = True
+ DEFINES["_STLP_NO_MEMBER_TEMPLATES"] = True
+ LOCAL_INCLUDES += [
+ "/toolkit/crashreporter/google-breakpad/src/common/android/include",
+ ]
+
+ DEFINES["UNICODE"] = True
+ DEFINES["_UNICODE"] = True
+
+ if CONFIG["MOZ_PHC"]:
+ DEFINES["MOZ_PHC"] = True
+
+ LOCAL_INCLUDES += [
+ "google-breakpad/src",
+ ]
+
+ PYTHON_UNITTEST_MANIFESTS += [
+ "tools/python.ini",
+ ]
+
+ include("/toolkit/crashreporter/crashreporter.mozbuild")
+
+ if CONFIG["CC_TYPE"] in ("clang", "gcc"):
+ CXXFLAGS += ["-Wno-error=stack-protector"]
+else:
+ UNIFIED_SOURCES += [
+ "nsDummyExceptionHandler.cpp",
+ ]
+
+# Generate CrashAnnotations.h
+GeneratedFile(
+ "CrashAnnotations.h",
+ script="generate_crash_reporter_sources.py",
+ entry_point="emit_header",
+ inputs=[
+ "CrashAnnotations.h.in",
+ "CrashAnnotations.yaml",
+ ],
+)
+
+with Files("**"):
+ BUG_COMPONENT = ("Toolkit", "Crash Reporting")
diff --git a/toolkit/crashreporter/mozwer-rust/Cargo.toml b/toolkit/crashreporter/mozwer-rust/Cargo.toml
new file mode 100644
index 0000000000..6b960d827d
--- /dev/null
+++ b/toolkit/crashreporter/mozwer-rust/Cargo.toml
@@ -0,0 +1,20 @@
+[package]
+name = "mozwer_s"
+version = "0.1.0"
+authors = ["Gabriele Svelto <gsvelto@mozilla.com>"]
+edition = "2018"
+license = "MPL-2.0"
+
+[dependencies]
+libc = "0.2.0"
+mozilla-central-workspace-hack = { path = "../../../build/workspace-hack" }
+rust-ini = "0.10"
+serde = { version = "1.0", features = ["derive"] }
+serde_json = { version = "1.0" }
+uuid = { version = "1.0", features = ["v4"] }
+winapi = "0.3"
+
+[lib]
+name = "mozwer_s"
+crate-type = ["staticlib"]
+path = "lib.rs"
diff --git a/toolkit/crashreporter/mozwer-rust/lib.rs b/toolkit/crashreporter/mozwer-rust/lib.rs
new file mode 100644
index 0000000000..fab6c4f85c
--- /dev/null
+++ b/toolkit/crashreporter/mozwer-rust/lib.rs
@@ -0,0 +1,1005 @@
+/* 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 https://mozilla.org/MPL/2.0/. */
+
+extern crate ini;
+extern crate winapi;
+
+use ini::Ini;
+use libc::time;
+use serde::Serialize;
+use serde_json::ser::to_writer;
+use std::convert::TryInto;
+use std::ffi::OsString;
+use std::fs::{read_to_string, File};
+use std::io::{BufRead, BufReader, Write};
+use std::mem::{size_of, zeroed};
+use std::os::windows::ffi::{OsStrExt, OsStringExt};
+use std::os::windows::io::AsRawHandle;
+use std::path::{Path, PathBuf};
+use std::ptr::{addr_of_mut, null, null_mut};
+use std::slice::from_raw_parts;
+use uuid::Uuid;
+use winapi::shared::basetsd::{SIZE_T, ULONG_PTR};
+use winapi::shared::minwindef::{
+ BOOL, BYTE, DWORD, FALSE, FILETIME, LPVOID, MAX_PATH, PBOOL, PDWORD, PULONG, TRUE, ULONG, WORD,
+};
+use winapi::shared::ntdef::{NTSTATUS, STRING, UNICODE_STRING};
+use winapi::shared::ntstatus::STATUS_SUCCESS;
+use winapi::shared::winerror::{E_UNEXPECTED, S_OK};
+use winapi::um::combaseapi::CoTaskMemFree;
+use winapi::um::handleapi::CloseHandle;
+use winapi::um::knownfolders::FOLDERID_RoamingAppData;
+use winapi::um::memoryapi::{ReadProcessMemory, WriteProcessMemory};
+use winapi::um::minwinbase::LPTHREAD_START_ROUTINE;
+use winapi::um::processthreadsapi::{
+ CreateProcessW, CreateRemoteThread, GetProcessId, GetProcessTimes, GetThreadId, OpenProcess,
+ TerminateProcess, PROCESS_INFORMATION, STARTUPINFOW,
+};
+use winapi::um::psapi::K32GetModuleFileNameExW;
+use winapi::um::shlobj::SHGetKnownFolderPath;
+use winapi::um::synchapi::WaitForSingleObject;
+use winapi::um::winbase::{
+ VerifyVersionInfoW, CREATE_NO_WINDOW, CREATE_UNICODE_ENVIRONMENT, NORMAL_PRIORITY_CLASS,
+ WAIT_OBJECT_0,
+};
+use winapi::um::winnt::{
+ VerSetConditionMask, CONTEXT, DWORDLONG, EXCEPTION_POINTERS, EXCEPTION_RECORD, HANDLE, HRESULT,
+ LIST_ENTRY, LPOSVERSIONINFOEXW, OSVERSIONINFOEXW, PCWSTR, PEXCEPTION_POINTERS,
+ PROCESS_ALL_ACCESS, PVOID, PWSTR, VER_GREATER_EQUAL, VER_MAJORVERSION, VER_MINORVERSION,
+ VER_SERVICEPACKMAJOR, VER_SERVICEPACKMINOR,
+};
+use winapi::STRUCT;
+
+/* The following struct must be kept in sync with the identically named one in
+ * nsExceptionHandler.h. There is one copy of this structure for every child
+ * process and they are all stored within the main process'. WER will use it to
+ * communicate with the main process when a child process is encountered. */
+#[repr(C)]
+struct WindowsErrorReportingData {
+ wer_notify_proc: LPTHREAD_START_ROUTINE,
+ child_pid: DWORD,
+ minidump_name: [u8; 40],
+ oom_allocation_size: usize,
+}
+
+/* The following struct must be kept in sync with the identically named one in
+ * nsExceptionHandler.h. A copy of this is stored in every process and a pointer
+ * to it is passed to the runtime exception module. We will read it to gather
+ * information about the crashed process. */
+#[repr(C)]
+struct InProcessWindowsErrorReportingData {
+ process_type: u32,
+ oom_allocation_size_ptr: *mut usize,
+}
+
+// This value comes from GeckoProcessTypes.h
+static MAIN_PROCESS_TYPE: u32 = 0;
+
+#[no_mangle]
+pub extern "C" fn OutOfProcessExceptionEventCallback(
+ context: PVOID,
+ exception_information: PWER_RUNTIME_EXCEPTION_INFORMATION,
+ b_ownership_claimed: PBOOL,
+ _wsz_event_name: PWSTR,
+ _pch_size: PDWORD,
+ _dw_signature_count: PDWORD,
+) -> HRESULT {
+ let result = out_of_process_exception_event_callback(context, exception_information);
+
+ match result {
+ Ok(_) => {
+ unsafe {
+ // Inform WER that we claim ownership of this crash
+ *b_ownership_claimed = TRUE;
+ // Make sure that the process shuts down
+ TerminateProcess((*exception_information).hProcess, 1);
+ }
+ S_OK
+ }
+ Err(_) => E_UNEXPECTED,
+ }
+}
+
+#[no_mangle]
+pub extern "C" fn OutOfProcessExceptionEventSignatureCallback(
+ _context: PVOID,
+ _exception_information: PWER_RUNTIME_EXCEPTION_INFORMATION,
+ _w_index: DWORD,
+ _wsz_name: PWSTR,
+ _ch_name: PDWORD,
+ _wsz_value: PWSTR,
+ _ch_value: PDWORD,
+) -> HRESULT {
+ S_OK
+}
+
+#[no_mangle]
+pub extern "C" fn OutOfProcessExceptionEventDebuggerLaunchCallback(
+ _context: PVOID,
+ _exception_information: PWER_RUNTIME_EXCEPTION_INFORMATION,
+ b_is_custom_debugger: PBOOL,
+ _wsz_debugger_launch: PWSTR,
+ _ch_debugger_launch: PDWORD,
+ _b_is_debugger_autolaunch: PBOOL,
+) -> HRESULT {
+ unsafe {
+ *b_is_custom_debugger = FALSE;
+ }
+
+ S_OK
+}
+
+fn out_of_process_exception_event_callback(
+ context: PVOID,
+ exception_information: PWER_RUNTIME_EXCEPTION_INFORMATION,
+) -> Result<(), ()> {
+ let is_fatal = unsafe { (*exception_information).bIsFatal } != FALSE;
+ if !is_fatal {
+ return Ok(());
+ }
+
+ let process = unsafe { (*exception_information).hProcess };
+ let application_info = ApplicationInformation::from_process(process)?;
+ let wer_data = read_from_process::<InProcessWindowsErrorReportingData>(
+ process,
+ context as *mut InProcessWindowsErrorReportingData,
+ )?;
+ let process = unsafe { (*exception_information).hProcess };
+ let startup_time = get_startup_time(process)?;
+ let oom_allocation_size = get_oom_allocation_size(process, &wer_data);
+ let crash_report = CrashReport::new(&application_info, startup_time, oom_allocation_size);
+ crash_report.write_minidump(exception_information)?;
+ if wer_data.process_type == MAIN_PROCESS_TYPE {
+ handle_main_process_crash(crash_report, process, &application_info)
+ } else {
+ handle_child_process_crash(crash_report, process)
+ }
+}
+
+fn handle_main_process_crash(
+ crash_report: CrashReport,
+ process: HANDLE,
+ application_information: &ApplicationInformation,
+) -> Result<(), ()> {
+ crash_report.write_extra_file()?;
+ crash_report.write_event_file()?;
+
+ let mut environment = read_environment_block(process)?;
+ launch_crash_reporter_client(
+ &application_information.install_path,
+ &mut environment,
+ &crash_report,
+ );
+
+ Ok(())
+}
+
+fn handle_child_process_crash(crash_report: CrashReport, child_process: HANDLE) -> Result<(), ()> {
+ let command_line = read_command_line(child_process)?;
+ let (parent_pid, data_ptr) = parse_child_data(&command_line)?;
+
+ let parent_process = get_process_handle(parent_pid)?;
+ let mut wer_data: WindowsErrorReportingData = read_from_process(parent_process, data_ptr)?;
+ wer_data.child_pid = get_process_id(child_process)?;
+ wer_data.minidump_name = crash_report.get_minidump_name();
+ wer_data.oom_allocation_size = crash_report.oom_allocation_size;
+ let wer_notify_proc = wer_data.wer_notify_proc;
+ write_to_process(parent_process, wer_data, data_ptr)?;
+ notify_main_process(parent_process, wer_notify_proc, data_ptr)
+}
+
+fn read_from_process<T>(process: HANDLE, data_ptr: *mut T) -> Result<T, ()> {
+ let mut data: T = unsafe { zeroed() };
+ let res = unsafe {
+ ReadProcessMemory(
+ process,
+ data_ptr as *mut _,
+ addr_of_mut!(data) as *mut _,
+ size_of::<T>() as SIZE_T,
+ null_mut(),
+ )
+ };
+
+ bool_ok_or_err(res, data)
+}
+
+fn read_array_from_process<T: Clone + Default>(
+ process: HANDLE,
+ data_ptr: LPVOID,
+ count: usize,
+) -> Result<Vec<T>, ()> {
+ let mut array = vec![Default::default(); count];
+ let size = size_of::<T>() as SIZE_T;
+ let size = size.checked_mul(count).ok_or(())?;
+ let res = unsafe {
+ ReadProcessMemory(
+ process,
+ data_ptr,
+ array.as_mut_ptr() as *mut _,
+ size,
+ null_mut(),
+ )
+ };
+
+ bool_ok_or_err(res, array)
+}
+
+fn write_to_process<T>(process: HANDLE, mut data: T, data_ptr: *mut T) -> Result<(), ()> {
+ let res = unsafe {
+ WriteProcessMemory(
+ process,
+ data_ptr as LPVOID,
+ addr_of_mut!(data) as *mut _,
+ size_of::<T>() as SIZE_T,
+ null_mut(),
+ )
+ };
+
+ bool_ok_or_err(res, ())
+}
+
+fn notify_main_process(
+ process: HANDLE,
+ wer_notify_proc: LPTHREAD_START_ROUTINE,
+ data_ptr: *mut WindowsErrorReportingData,
+) -> Result<(), ()> {
+ let thread = unsafe {
+ CreateRemoteThread(
+ process,
+ null_mut(),
+ 0,
+ wer_notify_proc,
+ data_ptr as LPVOID,
+ 0,
+ null_mut(),
+ )
+ };
+
+ if thread == null_mut() {
+ return Err(());
+ }
+
+ // Don't wait forever as we want the process to get killed eventually
+ let res = unsafe { WaitForSingleObject(thread, 5000) };
+ if res != WAIT_OBJECT_0 {
+ return Err(());
+ }
+
+ let res = unsafe { CloseHandle(thread) };
+ bool_ok_or_err(res, ())
+}
+
+fn get_startup_time(process: HANDLE) -> Result<u64, ()> {
+ let mut create_time: FILETIME = Default::default();
+ let mut exit_time: FILETIME = Default::default();
+ let mut kernel_time: FILETIME = Default::default();
+ let mut user_time: FILETIME = Default::default();
+ unsafe {
+ if GetProcessTimes(
+ process,
+ &mut create_time as *mut _,
+ &mut exit_time as *mut _,
+ &mut kernel_time as *mut _,
+ &mut user_time as *mut _,
+ ) == 0
+ {
+ return Err(());
+ }
+ }
+ let start_time_in_ticks =
+ ((create_time.dwHighDateTime as u64) << 32) + create_time.dwLowDateTime as u64;
+ let windows_tick: u64 = 10000000;
+ let sec_to_unix_epoch = 11644473600;
+ Ok((start_time_in_ticks / windows_tick) - sec_to_unix_epoch)
+}
+
+fn get_oom_allocation_size(
+ process: HANDLE,
+ wer_data: &InProcessWindowsErrorReportingData,
+) -> usize {
+ read_from_process(process, wer_data.oom_allocation_size_ptr).unwrap_or(0)
+}
+
+fn parse_child_data(command_line: &str) -> Result<(DWORD, *mut WindowsErrorReportingData), ()> {
+ let mut itr = command_line.rsplit(' ');
+ let address = itr.nth(1).ok_or(())?;
+ let address = usize::from_str_radix(address, 16).map_err(|_err| (()))?;
+ let address = address as *mut WindowsErrorReportingData;
+ let parent_pid = itr.nth(2).ok_or(())?;
+ let parent_pid = u32::from_str_radix(parent_pid, 10).map_err(|_err| (()))?;
+
+ Ok((parent_pid, address))
+}
+
+fn get_process_id(process: HANDLE) -> Result<DWORD, ()> {
+ match unsafe { GetProcessId(process) } {
+ 0 => Err(()),
+ pid => Ok(pid),
+ }
+}
+
+fn get_process_handle(pid: DWORD) -> Result<HANDLE, ()> {
+ let handle = unsafe { OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid) };
+ if handle != null_mut() {
+ Ok(handle)
+ } else {
+ Err(())
+ }
+}
+
+fn launch_crash_reporter_client(
+ install_path: &Path,
+ environment: &mut Vec<u16>,
+ crash_report: &CrashReport,
+) {
+ // Prepare the command line
+ let client_path = install_path.join("crashreporter.exe");
+
+ let mut cmd_line = OsString::from("\"");
+ cmd_line.push(client_path);
+ cmd_line.push("\" \"");
+ cmd_line.push(crash_report.get_minidump_path());
+ cmd_line.push("\"\0");
+ let mut cmd_line: Vec<u16> = cmd_line.encode_wide().collect();
+
+ let mut pi: PROCESS_INFORMATION = Default::default();
+ let mut si = STARTUPINFOW {
+ cb: size_of::<STARTUPINFOW>().try_into().unwrap(),
+ ..Default::default()
+ };
+
+ unsafe {
+ if CreateProcessW(
+ null_mut(),
+ cmd_line.as_mut_ptr(),
+ null_mut(),
+ null_mut(),
+ FALSE,
+ NORMAL_PRIORITY_CLASS | CREATE_NO_WINDOW | CREATE_UNICODE_ENVIRONMENT,
+ environment.as_mut_ptr() as *mut _,
+ null_mut(),
+ &mut si,
+ &mut pi,
+ ) != 0
+ {
+ CloseHandle(pi.hProcess);
+ CloseHandle(pi.hThread);
+ }
+ }
+}
+
+#[derive(Debug)]
+struct ApplicationData {
+ vendor: Option<String>,
+ name: String,
+ version: String,
+ build_id: String,
+ product_id: String,
+ server_url: String,
+}
+
+impl ApplicationData {
+ fn load_from_disk(install_path: &Path) -> Result<ApplicationData, ()> {
+ let ini_path = ApplicationData::get_path(install_path);
+ let conf = Ini::load_from_file(ini_path).map_err(|_e| ())?;
+
+ // Parse the "App" section
+ let app_section = conf.section(Some("App")).ok_or(())?;
+ let vendor = app_section.get("Vendor").map(|s| s.to_owned());
+ let name = app_section.get("Name").ok_or(())?.to_owned();
+ let version = app_section.get("Version").ok_or(())?.to_owned();
+ let build_id = app_section.get("BuildID").ok_or(())?.to_owned();
+ let product_id = app_section.get("ID").ok_or(())?.to_owned();
+
+ // Parse the "Crash Reporter" section
+ let crash_reporter_section = conf.section(Some("Crash Reporter")).ok_or(())?;
+ let server_url = crash_reporter_section
+ .get("ServerURL")
+ .ok_or(())?
+ .to_owned();
+
+ // InstallTime<build_id>
+
+ Ok(ApplicationData {
+ vendor,
+ name,
+ version,
+ build_id,
+ product_id,
+ server_url,
+ })
+ }
+
+ fn get_path(install_path: &Path) -> PathBuf {
+ install_path.join("application.ini")
+ }
+}
+
+#[derive(Serialize)]
+#[allow(non_snake_case)]
+struct Annotations {
+ BuildID: String,
+ CrashTime: String,
+ InstallTime: String,
+ #[serde(skip_serializing_if = "Option::is_none")]
+ OOMAllocationSize: Option<String>,
+ ProductID: String,
+ ProductName: String,
+ ReleaseChannel: String,
+ ServerURL: String,
+ StartupTime: String,
+ UptimeTS: String,
+ #[serde(skip_serializing_if = "Option::is_none")]
+ Vendor: Option<String>,
+ Version: String,
+ WindowsErrorReporting: String,
+}
+
+impl Annotations {
+ fn from_application_data(
+ application_data: &ApplicationData,
+ release_channel: String,
+ install_time: String,
+ crash_time: u64,
+ startup_time: u64,
+ oom_allocation_size: usize,
+ ) -> Annotations {
+ let oom_allocation_size = if oom_allocation_size != 0 {
+ Some(oom_allocation_size.to_string())
+ } else {
+ None
+ };
+ Annotations {
+ BuildID: application_data.build_id.clone(),
+ CrashTime: crash_time.to_string(),
+ InstallTime: install_time,
+ OOMAllocationSize: oom_allocation_size,
+ ProductID: application_data.product_id.clone(),
+ ProductName: application_data.name.clone(),
+ ReleaseChannel: release_channel,
+ ServerURL: application_data.server_url.clone(),
+ StartupTime: startup_time.to_string(),
+ UptimeTS: (crash_time - startup_time).to_string() + ".0",
+ Vendor: application_data.vendor.clone(),
+ Version: application_data.version.clone(),
+ WindowsErrorReporting: "1".to_string(),
+ }
+ }
+}
+
+/// Encapsulates the information about the application that crashed. This includes the install path as well as version information
+struct ApplicationInformation {
+ install_path: PathBuf,
+ application_data: ApplicationData,
+ release_channel: String,
+ crash_reports_dir: PathBuf,
+ install_time: String,
+}
+
+impl ApplicationInformation {
+ fn from_process(process: HANDLE) -> Result<ApplicationInformation, ()> {
+ let mut install_path = ApplicationInformation::get_application_path(process)?;
+ install_path.pop();
+ let application_data = ApplicationData::load_from_disk(install_path.as_ref())?;
+ let release_channel = ApplicationInformation::get_release_channel(install_path.as_ref())?;
+ let crash_reports_dir = ApplicationInformation::get_crash_reports_dir(&application_data)?;
+ let install_time = ApplicationInformation::get_install_time(
+ &crash_reports_dir,
+ &application_data.build_id,
+ )?;
+
+ Ok(ApplicationInformation {
+ install_path,
+ application_data,
+ release_channel,
+ crash_reports_dir,
+ install_time,
+ })
+ }
+
+ fn get_application_path(process: HANDLE) -> Result<PathBuf, ()> {
+ let mut path: [u16; MAX_PATH + 1] = [0; MAX_PATH + 1];
+ unsafe {
+ let res = K32GetModuleFileNameExW(
+ process,
+ null_mut(),
+ (&mut path).as_mut_ptr(),
+ (MAX_PATH + 1) as DWORD,
+ );
+
+ if res == 0 {
+ return Err(());
+ }
+
+ let application_path = PathBuf::from(OsString::from_wide(&path[0..res as usize]));
+ Ok(application_path)
+ }
+ }
+
+ fn get_release_channel(install_path: &Path) -> Result<String, ()> {
+ let channel_prefs =
+ File::open(install_path.join("defaults/pref/channel-prefs.js")).map_err(|_e| ())?;
+ let lines = BufReader::new(channel_prefs).lines();
+ let line = lines
+ .filter_map(Result::ok)
+ .find(|line| line.contains("app.update.channel"))
+ .ok_or(())?;
+ line.split("\"").nth(3).map(|s| s.to_string()).ok_or(())
+ }
+
+ fn get_crash_reports_dir(application_data: &ApplicationData) -> Result<PathBuf, ()> {
+ let mut psz_path: PWSTR = null_mut();
+ unsafe {
+ let res = SHGetKnownFolderPath(
+ &FOLDERID_RoamingAppData as *const _,
+ 0,
+ null_mut(),
+ &mut psz_path as *mut _,
+ );
+
+ if res == S_OK {
+ let mut len = 0;
+ while psz_path.offset(len).read() != 0 {
+ len += 1;
+ }
+ let str = OsString::from_wide(from_raw_parts(psz_path, len as usize));
+ CoTaskMemFree(psz_path as _);
+ let mut path = PathBuf::from(str);
+ if let Some(vendor) = &application_data.vendor {
+ path.push(vendor);
+ }
+ path.push(&application_data.name);
+ path.push("Crash Reports");
+ Ok(path)
+ } else {
+ Err(())
+ }
+ }
+ }
+
+ fn get_install_time(crash_reports_path: &Path, build_id: &str) -> Result<String, ()> {
+ let file_name = "InstallTime".to_owned() + build_id;
+ let file_path = crash_reports_path.join(file_name);
+ read_to_string(file_path).map_err(|_e| ())
+ }
+}
+
+struct CrashReport {
+ uuid: String,
+ crash_reports_path: PathBuf,
+ release_channel: String,
+ annotations: Annotations,
+ crash_time: u64,
+ oom_allocation_size: usize,
+}
+
+impl CrashReport {
+ fn new(
+ application_information: &ApplicationInformation,
+ startup_time: u64,
+ oom_allocation_size: usize,
+ ) -> CrashReport {
+ let uuid = Uuid::new_v4()
+ .as_hyphenated()
+ .encode_lower(&mut Uuid::encode_buffer())
+ .to_owned();
+ let crash_reports_path = application_information.crash_reports_dir.clone();
+ let crash_time: u64 = unsafe { time(null_mut()) as u64 };
+ let annotations = Annotations::from_application_data(
+ &application_information.application_data,
+ application_information.release_channel.clone(),
+ application_information.install_time.clone(),
+ crash_time,
+ startup_time,
+ oom_allocation_size,
+ );
+ CrashReport {
+ uuid,
+ crash_reports_path,
+ release_channel: application_information.release_channel.clone(),
+ annotations,
+ crash_time,
+ oom_allocation_size,
+ }
+ }
+
+ fn is_nightly(&self) -> bool {
+ self.release_channel == "nightly" || self.release_channel == "default"
+ }
+
+ fn get_minidump_type(&self) -> MINIDUMP_TYPE {
+ let mut minidump_type = MiniDumpWithFullMemoryInfo | MiniDumpWithUnloadedModules;
+ if self.is_nightly() {
+ // This is Nightly only because this doubles the size of minidumps based
+ // on the experimental data.
+ minidump_type = minidump_type | MiniDumpWithProcessThreadData;
+
+ // dbghelp.dll on Win7 can't handle overlapping memory regions so we only
+ // enable this feature on Win8 or later.
+ if is_windows8_or_later() {
+ // This allows us to examine heap objects referenced from stack objects
+ // at the cost of further doubling the size of minidumps.
+ minidump_type = minidump_type | MiniDumpWithIndirectlyReferencedMemory
+ }
+ }
+ minidump_type
+ }
+
+ fn get_pending_path(&self) -> PathBuf {
+ self.crash_reports_path.join("pending")
+ }
+
+ fn get_events_path(&self) -> PathBuf {
+ self.crash_reports_path.join("events")
+ }
+
+ fn get_minidump_path(&self) -> PathBuf {
+ self.get_pending_path().join(self.uuid.to_string() + ".dmp")
+ }
+
+ fn get_minidump_name(&self) -> [u8; 40] {
+ let bytes = (self.uuid.to_string() + ".dmp").into_bytes();
+ bytes[0..40].try_into().unwrap()
+ }
+
+ fn get_extra_file_path(&self) -> PathBuf {
+ self.get_pending_path()
+ .join(self.uuid.to_string() + ".extra")
+ }
+
+ fn get_event_file_path(&self) -> PathBuf {
+ self.get_events_path().join(self.uuid.to_string())
+ }
+
+ fn write_minidump(
+ &self,
+ exception_information: PWER_RUNTIME_EXCEPTION_INFORMATION,
+ ) -> Result<(), ()> {
+ let minidump_path = self.get_minidump_path();
+ let minidump_file = File::create(minidump_path).map_err(|_e| ())?;
+ let minidump_type: MINIDUMP_TYPE = self.get_minidump_type();
+
+ unsafe {
+ let mut exception_pointers = EXCEPTION_POINTERS {
+ ExceptionRecord: &mut ((*exception_information).exceptionRecord),
+ ContextRecord: &mut ((*exception_information).context),
+ };
+
+ let mut exception = MINIDUMP_EXCEPTION_INFORMATION {
+ ThreadId: GetThreadId((*exception_information).hThread),
+ ExceptionPointers: &mut exception_pointers,
+ ClientPointers: FALSE,
+ };
+
+ let res = MiniDumpWriteDump(
+ (*exception_information).hProcess,
+ get_process_id((*exception_information).hProcess)?,
+ minidump_file.as_raw_handle() as _,
+ minidump_type,
+ &mut exception,
+ /* userStream */ null(),
+ /* callback */ null(),
+ );
+
+ bool_ok_or_err(res, ())
+ }
+ }
+
+ fn write_extra_file(&self) -> Result<(), ()> {
+ let extra_file = File::create(self.get_extra_file_path()).map_err(|_e| ())?;
+ to_writer(extra_file, &self.annotations).map_err(|_e| ())
+ }
+
+ fn write_event_file(&self) -> Result<(), ()> {
+ let mut event_file = File::create(self.get_event_file_path()).map_err(|_e| ())?;
+ writeln!(event_file, "crash.main.3").map_err(|_e| ())?;
+ writeln!(event_file, "{}", self.crash_time).map_err(|_e| ())?;
+ writeln!(event_file, "{}", self.uuid).map_err(|_e| ())?;
+ to_writer(event_file, &self.annotations).map_err(|_e| ())
+ }
+}
+
+fn is_windows8_or_later() -> bool {
+ let mut info = OSVERSIONINFOEXW {
+ dwOSVersionInfoSize: size_of::<OSVERSIONINFOEXW>().try_into().unwrap(),
+ dwMajorVersion: 6,
+ dwMinorVersion: 2,
+ ..Default::default()
+ };
+
+ unsafe {
+ let mut mask: DWORDLONG = 0;
+ mask = VerSetConditionMask(mask, VER_MAJORVERSION, VER_GREATER_EQUAL);
+ mask = VerSetConditionMask(mask, VER_MINORVERSION, VER_GREATER_EQUAL);
+ mask = VerSetConditionMask(mask, VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL);
+ mask = VerSetConditionMask(mask, VER_SERVICEPACKMINOR, VER_GREATER_EQUAL);
+
+ let res = VerifyVersionInfoW(
+ &mut info as LPOSVERSIONINFOEXW,
+ VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
+ mask,
+ );
+
+ res != FALSE
+ }
+}
+
+fn bool_ok_or_err<T>(res: BOOL, data: T) -> Result<T, ()> {
+ match res {
+ FALSE => Err(()),
+ _ => Ok(data),
+ }
+}
+
+fn read_environment_block(process: HANDLE) -> Result<Vec<u16>, ()> {
+ let upp = read_user_process_parameters(process)?;
+
+ // Read the environment
+ let buffer = upp.Environment;
+ let length = upp.EnvironmentSize;
+ let count = length as usize / 2;
+ read_array_from_process::<u16>(process, buffer, count)
+}
+
+fn read_command_line(process: HANDLE) -> Result<String, ()> {
+ let upp = read_user_process_parameters(process)?;
+
+ // Read the command-line
+ let buffer = upp.CommandLine.Buffer;
+ let length = upp.CommandLine.Length;
+ let count = (length as usize) / 2;
+ let command_line = read_array_from_process::<u16>(process, buffer as *mut _, count)?;
+ String::from_utf16(&command_line).map_err(|_err| ())
+}
+
+fn read_user_process_parameters(process: HANDLE) -> Result<RTL_USER_PROCESS_PARAMETERS, ()> {
+ let mut pbi: PROCESS_BASIC_INFORMATION = unsafe { zeroed() };
+ let mut length: ULONG = 0;
+ let result = unsafe {
+ NtQueryInformationProcess(
+ process,
+ ProcessBasicInformation,
+ &mut pbi as *mut _ as _,
+ size_of::<PROCESS_BASIC_INFORMATION>().try_into().unwrap(),
+ &mut length,
+ )
+ };
+
+ if result != STATUS_SUCCESS {
+ return Err(());
+ }
+
+ // Read the process environment block
+ let peb: PEB = read_from_process(process, pbi.PebBaseAddress)?;
+
+ // Read the user process parameters
+ read_from_process::<RTL_USER_PROCESS_PARAMETERS>(process, peb.ProcessParameters)
+}
+
+/******************************************************************************
+ * The stuff below should be migrated to the winapi crate, see bug 1696414 *
+ ******************************************************************************/
+
+// we can't use winapi's ENUM macro directly because it doesn't support
+// attributes, so let's define this one here until we migrate this code
+macro_rules! ENUM {
+ {enum $name:ident { $($variant:ident = $value:expr,)+ }} => {
+ #[allow(non_camel_case_types)] pub type $name = u32;
+ $(#[allow(non_upper_case_globals)] pub const $variant: $name = $value;)+
+ };
+}
+
+// winapi doesn't export the FN macro, so we duplicate it here
+macro_rules! FN {
+ (stdcall $func:ident($($t:ty,)*) -> $ret:ty) => (
+ #[allow(non_camel_case_types)] pub type $func = Option<unsafe extern "system" fn($($t,)*) -> $ret>;
+ );
+ (stdcall $func:ident($($p:ident: $t:ty,)*) -> $ret:ty) => (
+ #[allow(non_camel_case_types)] pub type $func = Option<unsafe extern "system" fn($($p: $t,)*) -> $ret>;
+ );
+}
+
+// From um/WerApi.h
+
+STRUCT! {#[allow(non_snake_case)] struct WER_RUNTIME_EXCEPTION_INFORMATION
+{
+ dwSize: DWORD,
+ hProcess: HANDLE,
+ hThread: HANDLE,
+ exceptionRecord: EXCEPTION_RECORD,
+ context: CONTEXT,
+ pwszReportId: PCWSTR,
+ bIsFatal: BOOL,
+ dwReserved: DWORD,
+}}
+
+#[allow(non_camel_case_types)]
+pub type PWER_RUNTIME_EXCEPTION_INFORMATION = *mut WER_RUNTIME_EXCEPTION_INFORMATION;
+
+// From minidumpapiset.hProcess
+
+STRUCT! {#[allow(non_snake_case)] #[repr(packed(4))] struct MINIDUMP_EXCEPTION_INFORMATION {
+ ThreadId: DWORD,
+ ExceptionPointers: PEXCEPTION_POINTERS,
+ ClientPointers: BOOL,
+}}
+
+#[allow(non_camel_case_types)]
+pub type PMINIDUMP_EXCEPTION_INFORMATION = *mut MINIDUMP_EXCEPTION_INFORMATION;
+
+ENUM! { enum MINIDUMP_TYPE {
+ MiniDumpNormal = 0x00000000,
+ MiniDumpWithDataSegs = 0x00000001,
+ MiniDumpWithFullMemory = 0x00000002,
+ MiniDumpWithHandleData = 0x00000004,
+ MiniDumpFilterMemory = 0x00000008,
+ MiniDumpScanMemory = 0x00000010,
+ MiniDumpWithUnloadedModules = 0x00000020,
+ MiniDumpWithIndirectlyReferencedMemory = 0x00000040,
+ MiniDumpFilterModulePaths = 0x00000080,
+ MiniDumpWithProcessThreadData = 0x00000100,
+ MiniDumpWithPrivateReadWriteMemory = 0x00000200,
+ MiniDumpWithoutOptionalData = 0x00000400,
+ MiniDumpWithFullMemoryInfo = 0x00000800,
+ MiniDumpWithThreadInfo = 0x00001000,
+ MiniDumpWithCodeSegs = 0x00002000,
+ MiniDumpWithoutAuxiliaryState = 0x00004000,
+ MiniDumpWithFullAuxiliaryState = 0x00008000,
+ MiniDumpWithPrivateWriteCopyMemory = 0x00010000,
+ MiniDumpIgnoreInaccessibleMemory = 0x00020000,
+ MiniDumpWithTokenInformation = 0x00040000,
+ MiniDumpWithModuleHeaders = 0x00080000,
+ MiniDumpFilterTriage = 0x00100000,
+ MiniDumpWithAvxXStateContext = 0x00200000,
+ MiniDumpWithIptTrace = 0x00400000,
+ MiniDumpScanInaccessiblePartialPages = 0x00800000,
+ MiniDumpValidTypeFlags = 0x00ffffff,
+}}
+
+// We don't actually need the following three structs so we use placeholders
+STRUCT! {#[allow(non_snake_case)] struct MINIDUMP_CALLBACK_INPUT {
+ dummy: u32,
+}}
+
+#[allow(non_camel_case_types)]
+pub type PMINIDUMP_CALLBACK_INPUT = *const MINIDUMP_CALLBACK_INPUT;
+
+STRUCT! {#[allow(non_snake_case)] struct MINIDUMP_USER_STREAM_INFORMATION {
+ dummy: u32,
+}}
+
+#[allow(non_camel_case_types)]
+pub type PMINIDUMP_USER_STREAM_INFORMATION = *const MINIDUMP_USER_STREAM_INFORMATION;
+
+STRUCT! {#[allow(non_snake_case)] struct MINIDUMP_CALLBACK_OUTPUT {
+ dummy: u32,
+}}
+
+#[allow(non_camel_case_types)]
+pub type PMINIDUMP_CALLBACK_OUTPUT = *const MINIDUMP_CALLBACK_OUTPUT;
+
+// MiniDumpWriteDump() function and structs
+FN! {stdcall MINIDUMP_CALLBACK_ROUTINE(
+CallbackParam: PVOID,
+CallbackInput: PMINIDUMP_CALLBACK_INPUT,
+CallbackOutput: PMINIDUMP_CALLBACK_OUTPUT,
+) -> BOOL}
+
+STRUCT! {#[allow(non_snake_case)] #[repr(packed(4))] struct MINIDUMP_CALLBACK_INFORMATION {
+ CallbackRoutine: MINIDUMP_CALLBACK_ROUTINE,
+ CallbackParam: PVOID,
+}}
+
+#[allow(non_camel_case_types)]
+pub type PMINIDUMP_CALLBACK_INFORMATION = *const MINIDUMP_CALLBACK_INFORMATION;
+
+extern "system" {
+ pub fn MiniDumpWriteDump(
+ hProcess: HANDLE,
+ ProcessId: DWORD,
+ hFile: HANDLE,
+ DumpType: MINIDUMP_TYPE,
+ Exceptionparam: PMINIDUMP_EXCEPTION_INFORMATION,
+ UserStreamParam: PMINIDUMP_USER_STREAM_INFORMATION,
+ CallbackParam: PMINIDUMP_CALLBACK_INFORMATION,
+ ) -> BOOL;
+}
+
+// From um/winternl.h
+
+STRUCT! {#[allow(non_snake_case)] struct PEB_LDR_DATA {
+ Reserved1: [BYTE; 8],
+ Reserved2: [PVOID; 3],
+ InMemoryOrderModuleList: LIST_ENTRY,
+}}
+
+#[allow(non_camel_case_types)]
+pub type PPEB_LDR_DATA = *mut PEB_LDR_DATA;
+
+STRUCT! {#[allow(non_snake_case)] struct RTL_DRIVE_LETTER_CURDIR {
+ Flags: WORD,
+ Length: WORD,
+ TimeStamp: ULONG,
+ DosPath: STRING,
+}}
+
+STRUCT! {#[allow(non_snake_case)] struct RTL_USER_PROCESS_PARAMETERS {
+ Reserved1: [BYTE; 16],
+ Reserved2: [PVOID; 10],
+ ImagePathName: UNICODE_STRING,
+ CommandLine: UNICODE_STRING,
+ // Everything below this point is undocumented
+ Environment: PVOID,
+ StartingX: ULONG,
+ StartingY: ULONG,
+ CountX: ULONG,
+ CountY: ULONG,
+ CountCharsX: ULONG,
+ CountCharsY: ULONG,
+ FillAttribute: ULONG,
+ WindowFlags: ULONG,
+ ShowWindowFlags: ULONG,
+ WindowTitle: UNICODE_STRING,
+ DesktopInfo: UNICODE_STRING,
+ ShellInfo: UNICODE_STRING,
+ RuntimeData: UNICODE_STRING,
+ CurrentDirectores: [RTL_DRIVE_LETTER_CURDIR; 32],
+ EnvironmentSize: ULONG,
+}}
+
+#[allow(non_camel_case_types)]
+pub type PRTL_USER_PROCESS_PARAMETERS = *mut RTL_USER_PROCESS_PARAMETERS;
+
+FN! {stdcall PPS_POST_PROCESS_INIT_ROUTINE() -> ()}
+
+STRUCT! {#[allow(non_snake_case)] struct PEB {
+ Reserved1: [BYTE; 2],
+ BeingDebugged: BYTE,
+ Reserved2: [BYTE; 1],
+ Reserved3: [PVOID; 2],
+ Ldr: PPEB_LDR_DATA,
+ ProcessParameters: PRTL_USER_PROCESS_PARAMETERS,
+ Reserved4: [PVOID; 3],
+ AtlThunkSListPtr: PVOID,
+ Reserved5: PVOID,
+ Reserved6: ULONG,
+ Reserved7: PVOID,
+ Reserved8: ULONG,
+ AtlThunkSListPtr32: ULONG,
+ Reserved9: [PVOID; 45],
+ Reserved10: [BYTE; 96],
+ PostProcessInitRoutine: PPS_POST_PROCESS_INIT_ROUTINE,
+ Reserved11: [BYTE; 128],
+ Reserved12: [PVOID; 1],
+ SessionId: ULONG,
+}}
+
+#[allow(non_camel_case_types)]
+pub type PPEB = *mut PEB;
+
+STRUCT! {#[allow(non_snake_case)] struct PROCESS_BASIC_INFORMATION {
+ Reserved1: PVOID,
+ PebBaseAddress: PPEB,
+ Reserved2: [PVOID; 2],
+ UniqueProcessId: ULONG_PTR,
+ Reserved3: PVOID,
+}}
+
+ENUM! {enum PROCESSINFOCLASS {
+ ProcessBasicInformation = 0,
+ ProcessDebugPort = 7,
+ ProcessWow64Information = 26,
+ ProcessImageFileName = 27,
+ ProcessBreakOnTermination = 29,
+}}
+
+extern "system" {
+ pub fn NtQueryInformationProcess(
+ ProcessHandle: HANDLE,
+ ProcessInformationClass: PROCESSINFOCLASS,
+ ProcessInformation: PVOID,
+ ProcessInformationLength: ULONG,
+ ReturnLength: PULONG,
+ ) -> NTSTATUS;
+}
diff --git a/toolkit/crashreporter/mozwer-rust/moz.build b/toolkit/crashreporter/mozwer-rust/moz.build
new file mode 100644
index 0000000000..dc37e8cced
--- /dev/null
+++ b/toolkit/crashreporter/mozwer-rust/moz.build
@@ -0,0 +1,11 @@
+RustLibrary("mozwer_s")
+
+OS_LIBS += [
+ "dbghelp",
+ "kernel32",
+ "ntdll",
+ "ole32",
+ "shell32",
+ "userenv",
+ "ws2_32",
+]
diff --git a/toolkit/crashreporter/mozwer/moz.build b/toolkit/crashreporter/mozwer/moz.build
new file mode 100644
index 0000000000..1f6418fd48
--- /dev/null
+++ b/toolkit/crashreporter/mozwer/moz.build
@@ -0,0 +1,17 @@
+UNIFIED_SOURCES = [
+ "mozwer.cpp",
+]
+
+USE_LIBS += [
+ "mozwer_s",
+]
+
+OS_LIBS += [
+ "advapi32",
+ "bcrypt",
+]
+
+DEFFILE = "mozwer.def"
+USE_STATIC_LIBS = True
+
+SharedLibrary("mozwer")
diff --git a/toolkit/crashreporter/mozwer/mozwer.cpp b/toolkit/crashreporter/mozwer/mozwer.cpp
new file mode 100644
index 0000000000..4f4c184949
--- /dev/null
+++ b/toolkit/crashreporter/mozwer/mozwer.cpp
@@ -0,0 +1,20 @@
+/* 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 <windows.h>
+
+#include "nscore.h"
+
+extern "C" {
+
+NS_EXPORT_(BOOL)
+DllMain(HINSTANCE DllInstance, DWORD Reason, LPVOID Reserved) {
+ UNREFERENCED_PARAMETER(DllInstance);
+ UNREFERENCED_PARAMETER(Reason);
+ UNREFERENCED_PARAMETER(Reserved);
+
+ return TRUE;
+}
+
+} /* extern "C" */
diff --git a/toolkit/crashreporter/mozwer/mozwer.def b/toolkit/crashreporter/mozwer/mozwer.def
new file mode 100644
index 0000000000..b9ea6ed3ac
--- /dev/null
+++ b/toolkit/crashreporter/mozwer/mozwer.def
@@ -0,0 +1,5 @@
+LIBRARY
+EXPORTS
+ OutOfProcessExceptionEventCallback
+ OutOfProcessExceptionEventSignatureCallback
+ OutOfProcessExceptionEventDebuggerLaunchCallback
diff --git a/toolkit/crashreporter/nsDummyExceptionHandler.cpp b/toolkit/crashreporter/nsDummyExceptionHandler.cpp
new file mode 100644
index 0000000000..3d077d1a8b
--- /dev/null
+++ b/toolkit/crashreporter/nsDummyExceptionHandler.cpp
@@ -0,0 +1,263 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* 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 <functional>
+
+#include "nsExceptionHandler.h"
+#include "nsExceptionHandlerUtils.h"
+#include "prio.h"
+
+namespace CrashReporter {
+
+void AnnotateOOMAllocationSize(size_t size) {}
+
+void AnnotateTexturesSize(size_t size) {}
+
+void AnnotatePendingIPC(size_t aNumOfPendingIPC, uint32_t aTopPendingIPCCount,
+ const char* aTopPendingIPCName,
+ uint32_t aTopPendingIPCType) {}
+
+nsresult SetExceptionHandler(nsIFile* aXREDirectory, bool force /*=false*/) {
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+bool GetEnabled() { return false; }
+
+bool GetMinidumpPath(nsAString& aPath) { return false; }
+
+nsresult SetMinidumpPath(const nsAString& aPath) {
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+nsresult SetupExtraData(nsIFile* aAppDataDirectory,
+ const nsACString& aBuildID) {
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+nsresult UnsetExceptionHandler() { return NS_ERROR_NOT_IMPLEMENTED; }
+
+nsresult AnnotateCrashReport(Annotation key, bool data) {
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+nsresult AnnotateCrashReport(Annotation key, int data) {
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+nsresult AnnotateCrashReport(Annotation key, unsigned int data) {
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+nsresult AnnotateCrashReport(Annotation key, const nsACString& data) {
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+nsresult AppendToCrashReportAnnotation(Annotation key, const nsACString& data) {
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+nsresult RemoveCrashReportAnnotation(Annotation key) {
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+AutoAnnotateCrashReport::AutoAnnotateCrashReport(Annotation key, bool data) {}
+
+AutoAnnotateCrashReport::AutoAnnotateCrashReport(Annotation key, int data) {}
+
+AutoAnnotateCrashReport::AutoAnnotateCrashReport(Annotation key,
+ unsigned data) {}
+
+AutoAnnotateCrashReport::AutoAnnotateCrashReport(Annotation key,
+ const nsACString& data) {}
+
+AutoAnnotateCrashReport::~AutoAnnotateCrashReport() {}
+
+void MergeCrashAnnotations(AnnotationTable& aDst, const AnnotationTable& aSrc) {
+}
+
+nsresult SetGarbageCollecting(bool collecting) {
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+void SetEventloopNestingLevel(uint32_t level) {}
+
+void SetMinidumpAnalysisAllThreads() {}
+
+nsresult AppendAppNotesToCrashReport(const nsACString& data) {
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+bool GetAnnotation(const nsACString& key, nsACString& data) { return false; }
+
+void GetAnnotation(uint32_t childPid, Annotation annotation,
+ nsACString& outStr) {
+ return;
+}
+
+nsresult RegisterAppMemory(void* ptr, size_t length) {
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+nsresult UnregisterAppMemory(void* ptr) { return NS_ERROR_NOT_IMPLEMENTED; }
+
+void SetIncludeContextHeap(bool aValue) {}
+
+bool GetServerURL(nsACString& aServerURL) { return false; }
+
+nsresult SetServerURL(const nsACString& aServerURL) {
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+nsresult SetRestartArgs(int argc, char** argv) {
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+#if !defined(XP_WIN)
+int GetAnnotationTimeCrashFd() { return 7; }
+#endif
+
+void RegisterChildCrashAnnotationFileDescriptor(ProcessId aProcess,
+ PRFileDesc* aFd) {
+ // The real implementation of this function takes ownership of aFd
+ // and closes it when the process exits; if we don't close it, it
+ // causes a leak. With no crash reporter we'll never write to the
+ // pipe, so it's safe to close the read end immediately.
+ PR_Close(aFd);
+}
+
+void DeregisterChildCrashAnnotationFileDescriptor(ProcessId aProcess) {}
+
+#ifdef XP_WIN
+nsresult WriteMinidumpForException(EXCEPTION_POINTERS* aExceptionInfo) {
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+#endif
+
+#ifdef XP_LINUX
+bool WriteMinidumpForSigInfo(int signo, siginfo_t* info, void* uc) {
+ return false;
+}
+#endif
+
+#ifdef XP_MACOSX
+nsresult AppendObjCExceptionInfoToAppNotes(void* inException) {
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+#endif
+
+nsresult GetSubmitReports(bool* aSubmitReports) {
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+nsresult SetSubmitReports(bool aSubmitReports) {
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+void SetProfileDirectory(nsIFile* aDir) {}
+
+void SetUserAppDataDirectory(nsIFile* aDir) {}
+
+void UpdateCrashEventsDir() {}
+
+bool GetCrashEventsDir(nsAString& aPath) { return false; }
+
+void SetMemoryReportFile(nsIFile* aFile) {}
+
+nsresult GetDefaultMemoryReportFile(nsIFile** aFile) {
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+void DeleteMinidumpFilesForID(const nsAString& aId,
+ const Maybe<nsString>& aAdditionalMinidump) {}
+
+bool GetMinidumpForID(const nsAString& id, nsIFile** minidump,
+ const Maybe<nsString>& aAdditionalMinidump) {
+ return false;
+}
+
+bool GetIDFromMinidump(nsIFile* minidump, nsAString& id) { return false; }
+
+bool GetExtraFileForID(const nsAString& id, nsIFile** extraFile) {
+ return false;
+}
+
+bool GetExtraFileForMinidump(nsIFile* minidump, nsIFile** extraFile) {
+ return false;
+}
+
+bool WriteExtraFile(const nsAString& id, const AnnotationTable& annotations) {
+ return false;
+}
+
+void OOPInit() {}
+
+#if defined(XP_WIN) || defined(XP_MACOSX)
+const char* GetChildNotificationPipe() { return nullptr; }
+#endif
+
+#ifdef MOZ_CRASHREPORTER_INJECTOR
+void InjectCrashReporterIntoProcess(DWORD processID,
+ InjectorCrashCallback* cb) {}
+
+void UnregisterInjectorCallback(DWORD processID) {}
+
+#endif // MOZ_CRASHREPORTER_INJECTOR
+
+bool GetLastRunCrashID(nsAString& id) { return false; }
+
+#if !defined(XP_WIN) && !defined(XP_MACOSX)
+
+bool CreateNotificationPipeForChild(int* childCrashFd, int* childCrashRemapFd) {
+ return false;
+}
+
+#endif // !defined(XP_WIN) && !defined(XP_MACOSX)
+
+bool SetRemoteExceptionHandler(const char* aCrashPipe,
+ FileHandle aCrashTimeAnnotationFile) {
+ return false;
+}
+
+bool TakeMinidumpForChild(uint32_t childPid, nsIFile** dump,
+ AnnotationTable& aAnnotations, uint32_t* aSequence) {
+ return false;
+}
+
+bool FinalizeOrphanedMinidump(uint32_t aChildPid, GeckoProcessType aType,
+ nsString* aDumpId) {
+ return false;
+}
+
+#if defined(XP_WIN)
+
+DWORD WINAPI WerNotifyProc(LPVOID aParameter) { return 0; }
+
+#endif // defined(XP_WIN)
+
+ThreadId CurrentThreadId() { return -1; }
+
+bool TakeMinidump(nsIFile** aResult, bool aMoveToPending) { return false; }
+
+bool CreateMinidumpsAndPair(ProcessHandle aTargetPid,
+ ThreadId aTargetBlamedThread,
+ const nsACString& aIncomingPairName,
+ AnnotationTable& aTargetAnnotations,
+ nsIFile** aTargetDumpOut) {
+ return false;
+}
+
+bool UnsetRemoteExceptionHandler(bool wasSet) { return false; }
+
+#if defined(MOZ_WIDGET_ANDROID)
+void SetNotificationPipeForChild(FileHandle childCrashFd) {}
+
+void SetCrashAnnotationPipeForChild(FileHandle childCrashAnnotationFd) {}
+
+void AddLibraryMapping(const char* library_name, uintptr_t start_address,
+ size_t mapping_length, size_t file_offset) {}
+#endif
+
+} // namespace CrashReporter
diff --git a/toolkit/crashreporter/nsExceptionHandler.cpp b/toolkit/crashreporter/nsExceptionHandler.cpp
new file mode 100644
index 0000000000..aca9248147
--- /dev/null
+++ b/toolkit/crashreporter/nsExceptionHandler.cpp
@@ -0,0 +1,3864 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* 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 "nsExceptionHandler.h"
+#include "nsExceptionHandlerUtils.h"
+
+#include "nsAppDirectoryServiceDefs.h"
+#include "nsComponentManagerUtils.h"
+#include "nsDirectoryServiceDefs.h"
+#include "nsDirectoryService.h"
+#include "nsString.h"
+#include "nsTHashMap.h"
+#include "mozilla/ArrayUtils.h"
+#include "mozilla/DebugOnly.h"
+#include "mozilla/EnumeratedRange.h"
+#include "mozilla/Services.h"
+#include "nsIObserverService.h"
+#include "mozilla/Unused.h"
+#include "mozilla/UniquePtr.h"
+#include "mozilla/Printf.h"
+#include "mozilla/RuntimeExceptionModule.h"
+#include "mozilla/ScopeExit.h"
+#include "mozilla/Sprintf.h"
+#include "mozilla/StaticMutex.h"
+#include "mozilla/SyncRunnable.h"
+#include "mozilla/TimeStamp.h"
+
+#include "nsPrintfCString.h"
+#include "nsThreadUtils.h"
+#include "nsThread.h"
+#include "jsfriendapi.h"
+#include "private/pprio.h"
+#include "base/process_util.h"
+#include "common/basictypes.h"
+
+#if defined(XP_WIN)
+# ifdef WIN32_LEAN_AND_MEAN
+# undef WIN32_LEAN_AND_MEAN
+# endif
+
+# include "nsXULAppAPI.h"
+# include "nsIXULAppInfo.h"
+# include "nsIWindowsRegKey.h"
+# include "breakpad-client/windows/crash_generation/client_info.h"
+# include "breakpad-client/windows/crash_generation/crash_generation_server.h"
+# include "breakpad-client/windows/handler/exception_handler.h"
+# include <dbghelp.h>
+# include <string.h>
+# include "nsDirectoryServiceUtils.h"
+
+# include "nsWindowsDllInterceptor.h"
+# include "mozilla/WindowsDllBlocklist.h"
+# include "mozilla/WindowsVersion.h"
+# include "psapi.h" // For PERFORMANCE_INFORMATION and K32GetPerformanceInfo()
+#elif defined(XP_MACOSX)
+# include "breakpad-client/mac/crash_generation/client_info.h"
+# include "breakpad-client/mac/crash_generation/crash_generation_server.h"
+# include "breakpad-client/mac/handler/exception_handler.h"
+# include <string>
+# include <Carbon/Carbon.h>
+# include <CoreFoundation/CoreFoundation.h>
+# include <crt_externs.h>
+# include <fcntl.h>
+# include <mach/mach.h>
+# include <mach/vm_statistics.h>
+# include <sys/sysctl.h>
+# include <sys/types.h>
+# include <spawn.h>
+# include <unistd.h>
+# include "mac_utils.h"
+#elif defined(XP_LINUX)
+# include "nsIINIParser.h"
+# include "common/linux/linux_libc_support.h"
+# include "third_party/lss/linux_syscall_support.h"
+# include "breakpad-client/linux/crash_generation/client_info.h"
+# include "breakpad-client/linux/crash_generation/crash_generation_server.h"
+# include "breakpad-client/linux/handler/exception_handler.h"
+# include "common/linux/eintr_wrapper.h"
+# include <fcntl.h>
+# include <sys/types.h>
+# include "sys/sysinfo.h"
+# include <sys/wait.h>
+# include <unistd.h>
+#else
+# error "Not yet implemented for this platform"
+#endif // defined(XP_WIN)
+
+#ifdef MOZ_CRASHREPORTER_INJECTOR
+# include "InjectCrashReporter.h"
+using mozilla::InjectCrashRunnable;
+#endif
+
+#include <stdlib.h>
+#include <time.h>
+#include <prenv.h>
+#include <prio.h>
+#include "mozilla/Mutex.h"
+#include "nsDebug.h"
+#include "nsCRT.h"
+#include "nsIFile.h"
+#include <map>
+#include <vector>
+
+#include "mozilla/IOInterposer.h"
+#include "mozilla/mozalloc_oom.h"
+
+#if defined(XP_MACOSX)
+CFStringRef reporterClientAppID = CFSTR("org.mozilla.crashreporter");
+#endif
+#if defined(MOZ_WIDGET_ANDROID)
+# include "common/linux/file_id.h"
+#endif
+
+using google_breakpad::ClientInfo;
+using google_breakpad::CrashGenerationServer;
+#ifdef XP_LINUX
+using google_breakpad::MinidumpDescriptor;
+#elif defined(XP_WIN)
+using google_breakpad::ExceptionHandler;
+#endif
+#if defined(MOZ_WIDGET_ANDROID)
+using google_breakpad::auto_wasteful_vector;
+using google_breakpad::FileID;
+using google_breakpad::kDefaultBuildIdSize;
+using google_breakpad::PageAllocator;
+#endif
+using namespace mozilla;
+
+namespace CrashReporter {
+
+#ifdef XP_WIN
+typedef wchar_t XP_CHAR;
+typedef std::wstring xpstring;
+# define XP_TEXT(x) L##x
+# define CONVERT_XP_CHAR_TO_UTF16(x) x
+# define XP_STRLEN(x) wcslen(x)
+# define my_strlen strlen
+# define my_memchr memchr
+# define CRASH_REPORTER_FILENAME u"crashreporter.exe"_ns
+# define XP_PATH_SEPARATOR L"\\"
+# define XP_PATH_SEPARATOR_CHAR L'\\'
+# define XP_PATH_MAX (MAX_PATH + 1)
+// "<reporter path>" "<minidump path>"
+# define CMDLINE_SIZE ((XP_PATH_MAX * 2) + 6)
+# define XP_TTOA(time, buffer) _i64toa((time), (buffer), 10)
+# define XP_STOA(size, buffer) _ui64toa((size), (buffer), 10)
+#else
+typedef char XP_CHAR;
+typedef std::string xpstring;
+# define XP_TEXT(x) x
+# define CONVERT_XP_CHAR_TO_UTF16(x) NS_ConvertUTF8toUTF16(x)
+# define CRASH_REPORTER_FILENAME u"crashreporter"_ns
+# define XP_PATH_SEPARATOR "/"
+# define XP_PATH_SEPARATOR_CHAR '/'
+# define XP_PATH_MAX PATH_MAX
+# ifdef XP_LINUX
+# define XP_STRLEN(x) my_strlen(x)
+# define XP_TTOA(time, buffer) \
+ my_u64tostring(uint64_t(time), (buffer), sizeof(buffer))
+# define XP_STOA(size, buffer) \
+ my_u64tostring((size), (buffer), sizeof(buffer))
+# else
+# define XP_STRLEN(x) strlen(x)
+# define XP_TTOA(time, buffer) sprintf(buffer, "%" PRIu64, uint64_t(time))
+# define XP_STOA(size, buffer) sprintf(buffer, "%zu", size_t(size))
+# define my_strlen strlen
+# define my_memchr memchr
+# define sys_close close
+# define sys_fork fork
+# define sys_open open
+# define sys_read read
+# define sys_write write
+# endif
+#endif // XP_WIN
+
+#if defined(__GNUC__)
+# define MAYBE_UNUSED __attribute__((unused))
+#else
+# define MAYBE_UNUSED
+#endif // defined(__GNUC__)
+
+#ifndef XP_LINUX
+static const XP_CHAR dumpFileExtension[] = XP_TEXT(".dmp");
+#endif
+
+static const XP_CHAR extraFileExtension[] = XP_TEXT(".extra");
+static const XP_CHAR memoryReportExtension[] = XP_TEXT(".memory.json.gz");
+static xpstring* defaultMemoryReportPath = nullptr;
+
+static const char kCrashMainID[] = "crash.main.3\n";
+
+static google_breakpad::ExceptionHandler* gExceptionHandler = nullptr;
+static mozilla::Atomic<bool> gEncounteredChildException(false);
+
+static xpstring pendingDirectory;
+static xpstring crashReporterPath;
+static xpstring memoryReportPath;
+
+// Where crash events should go.
+static xpstring eventsDirectory;
+
+// If this is false, we don't launch the crash reporter
+static bool doReport = true;
+
+// if this is true, we pass the exception on to the OS crash reporter
+static bool showOSCrashReporter = false;
+
+// The time of the last recorded crash, as a time_t value.
+static time_t lastCrashTime = 0;
+// The pathname of a file to store the crash time in
+static XP_CHAR lastCrashTimeFilename[XP_PATH_MAX] = {0};
+
+#if defined(MOZ_WIDGET_ANDROID)
+// on Android 4.2 and above there is a user serial number associated
+// with the current process that gets lost when we fork so we need to
+// explicitly pass it to am
+static char* androidUserSerial = nullptr;
+
+// Before Android 8 we needed to use "startservice" to start the crash reporting
+// service. After Android 8 we need to use "start-foreground-service"
+static const char* androidStartServiceCommand = nullptr;
+#endif
+
+// this holds additional data sent via the API
+static Mutex* crashReporterAPILock;
+static Mutex* notesFieldLock;
+static AnnotationTable crashReporterAPIData_Table;
+static nsCString* notesField = nullptr;
+static bool isGarbageCollecting;
+static uint32_t eventloopNestingLevel = 0;
+static time_t inactiveStateStart = 0;
+
+static
+#if defined(XP_UNIX)
+ pthread_t
+#elif defined(XP_WIN) // defined(XP_UNIX)
+ DWORD
+#endif // defined(XP_WIN)
+ gMainThreadId = 0;
+
+// Avoid a race during application termination.
+static Mutex* dumpSafetyLock;
+static bool isSafeToDump = false;
+
+// Whether to include heap regions of the crash context.
+static bool sIncludeContextHeap = false;
+
+// OOP crash reporting
+static CrashGenerationServer* crashServer; // chrome process has this
+static StaticMutex processMapLock MOZ_UNANNOTATED;
+static std::map<ProcessId, PRFileDesc*> processToCrashFd;
+
+static std::terminate_handler oldTerminateHandler = nullptr;
+
+#if defined(XP_WIN) || defined(XP_MACOSX)
+// If crash reporting is disabled, we hand out this "null" pipe to the
+// child process and don't attempt to connect to a parent server.
+static const char kNullNotifyPipe[] = "-";
+static char* childCrashNotifyPipe;
+
+#elif defined(XP_LINUX)
+static int serverSocketFd = -1;
+static int clientSocketFd = -1;
+
+// On Linux these file descriptors are created in the parent process and
+// remapped in the child ones. See PosixProcessLauncher::DoSetup() for more
+// details.
+static FileHandle gMagicChildCrashReportFd =
+# if defined(MOZ_WIDGET_ANDROID)
+ // On android the fd is set at the time of child creation.
+ kInvalidFileHandle
+# else
+ 4
+# endif // defined(MOZ_WIDGET_ANDROID)
+ ;
+#endif
+
+static FileHandle gChildCrashAnnotationReportFd =
+#if (defined(XP_LINUX) || defined(XP_MACOSX)) && !defined(MOZ_WIDGET_ANDROID)
+ 7
+#else
+ kInvalidFileHandle
+#endif
+ ;
+
+// |dumpMapLock| must protect all access to |pidToMinidump|.
+static Mutex* dumpMapLock;
+struct ChildProcessData : public nsUint32HashKey {
+ explicit ChildProcessData(KeyTypePointer aKey)
+ : nsUint32HashKey(aKey),
+ sequence(0),
+ annotations(nullptr),
+ minidumpOnly(false)
+#ifdef MOZ_CRASHREPORTER_INJECTOR
+ ,
+ callback(nullptr)
+#endif
+ {
+ }
+
+ nsCOMPtr<nsIFile> minidump;
+ // Each crashing process is assigned an increasing sequence number to
+ // indicate which process crashed first.
+ uint32_t sequence;
+ UniquePtr<AnnotationTable> annotations;
+ bool minidumpOnly; // If true then no annotations are present
+#ifdef MOZ_CRASHREPORTER_INJECTOR
+ InjectorCrashCallback* callback;
+#endif
+};
+
+typedef nsTHashtable<ChildProcessData> ChildMinidumpMap;
+static ChildMinidumpMap* pidToMinidump;
+static uint32_t crashSequence;
+static bool OOPInitialized();
+
+#ifdef MOZ_CRASHREPORTER_INJECTOR
+static nsIThread* sInjectorThread;
+
+class ReportInjectedCrash : public Runnable {
+ public:
+ explicit ReportInjectedCrash(uint32_t pid)
+ : Runnable("ReportInjectedCrash"), mPID(pid) {}
+
+ NS_IMETHOD Run() override;
+
+ private:
+ uint32_t mPID;
+};
+#endif // MOZ_CRASHREPORTER_INJECTOR
+
+void RecordMainThreadId() {
+ gMainThreadId =
+#if defined(XP_UNIX)
+ pthread_self()
+#elif defined(XP_WIN) // defined(XP_UNIX)
+ GetCurrentThreadId()
+#endif // defined(XP_WIN)
+ ;
+}
+
+bool SignalSafeIsMainThread() {
+ // We can't rely on NS_IsMainThread() because we are in a signal handler, and
+ // sTLSIsMainThread is a thread local variable and it can be lazy allocated
+ // i.e., we could hit code path where this variable has not been accessed
+ // before and needs to be allocated right now, which will lead to spinlock
+ // deadlock effectively hanging the process, as in bug 1756407.
+
+#if defined(XP_UNIX)
+ pthread_t th = pthread_self();
+ return pthread_equal(th, gMainThreadId);
+#elif defined(XP_WIN) // defined(XP_UNIX)
+ DWORD th = GetCurrentThreadId();
+ return th == gMainThreadId;
+#endif // defined(XP_WIN)
+}
+
+#if defined(XP_WIN)
+// the following are used to prevent other DLLs reverting the last chance
+// exception handler to the windows default. Any attempt to change the
+// unhandled exception filter or to reset it is ignored and our crash
+// reporter is loaded instead (in case it became unloaded somehow)
+typedef LPTOP_LEVEL_EXCEPTION_FILTER(WINAPI* SetUnhandledExceptionFilter_func)(
+ LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter);
+static WindowsDllInterceptor::FuncHookType<SetUnhandledExceptionFilter_func>
+ stub_SetUnhandledExceptionFilter;
+static LPTOP_LEVEL_EXCEPTION_FILTER previousUnhandledExceptionFilter = nullptr;
+static WindowsDllInterceptor gKernel32Intercept;
+static bool gBlockUnhandledExceptionFilter = true;
+
+static LPTOP_LEVEL_EXCEPTION_FILTER GetUnhandledExceptionFilter() {
+ // Set a dummy value to get the current filter, then restore
+ LPTOP_LEVEL_EXCEPTION_FILTER current = SetUnhandledExceptionFilter(nullptr);
+ SetUnhandledExceptionFilter(current);
+ return current;
+}
+
+static LPTOP_LEVEL_EXCEPTION_FILTER WINAPI patched_SetUnhandledExceptionFilter(
+ LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter) {
+ if (!gBlockUnhandledExceptionFilter) {
+ // don't intercept
+ return stub_SetUnhandledExceptionFilter(lpTopLevelExceptionFilter);
+ }
+
+ if (lpTopLevelExceptionFilter == previousUnhandledExceptionFilter) {
+ // OK to swap back and forth between the previous filter
+ previousUnhandledExceptionFilter =
+ stub_SetUnhandledExceptionFilter(lpTopLevelExceptionFilter);
+ return previousUnhandledExceptionFilter;
+ }
+
+ // intercept attempts to change the filter
+ return nullptr;
+}
+
+# if defined(HAVE_64BIT_BUILD)
+static LPTOP_LEVEL_EXCEPTION_FILTER sUnhandledExceptionFilter = nullptr;
+
+static long JitExceptionHandler(void* exceptionRecord, void* context) {
+ EXCEPTION_POINTERS pointers = {(PEXCEPTION_RECORD)exceptionRecord,
+ (PCONTEXT)context};
+ return sUnhandledExceptionFilter(&pointers);
+}
+
+static void SetJitExceptionHandler() {
+ sUnhandledExceptionFilter = GetUnhandledExceptionFilter();
+ if (sUnhandledExceptionFilter)
+ js::SetJitExceptionHandler(JitExceptionHandler);
+}
+# endif
+
+/**
+ * Reserve some VM space. In the event that we crash because VM space is
+ * being leaked without leaking memory, freeing this space before taking
+ * the minidump will allow us to collect a minidump.
+ *
+ * This size is bigger than xul.dll plus some extra for MinidumpWriteDump
+ * allocations.
+ */
+static const SIZE_T kReserveSize = 0x5000000; // 80 MB
+static void* gBreakpadReservedVM;
+#endif
+
+#ifdef XP_LINUX
+static inline void my_u64tostring(uint64_t aValue, char* aBuffer,
+ size_t aBufferLength) {
+ my_memset(aBuffer, 0, aBufferLength);
+ my_uitos(aBuffer, aValue, my_uint_len(aValue));
+}
+#endif
+
+#ifdef XP_WIN
+static void CreateFileFromPath(const xpstring& path, nsIFile** file) {
+ NS_NewLocalFile(nsDependentString(path.c_str()), false, file);
+}
+
+static xpstring* CreatePathFromFile(nsIFile* file) {
+ nsAutoString path;
+ nsresult rv = file->GetPath(path);
+ if (NS_FAILED(rv)) {
+ return nullptr;
+ }
+ return new xpstring(static_cast<wchar_t*>(path.get()), path.Length());
+}
+#else
+static void CreateFileFromPath(const xpstring& path, nsIFile** file) {
+ NS_NewNativeLocalFile(nsDependentCString(path.c_str()), false, file);
+}
+
+MAYBE_UNUSED static xpstring* CreatePathFromFile(nsIFile* file) {
+ nsAutoCString path;
+ nsresult rv = file->GetNativePath(path);
+ if (NS_FAILED(rv)) {
+ return nullptr;
+ }
+ return new xpstring(path.get(), path.Length());
+}
+#endif
+
+static time_t GetCurrentTimeForCrashTime() {
+#ifdef XP_LINUX
+ struct kernel_timeval tv;
+ sys_gettimeofday(&tv, nullptr);
+ return tv.tv_sec;
+#else
+ return time(nullptr);
+#endif
+}
+
+static XP_CHAR* Concat(XP_CHAR* str, const XP_CHAR* toAppend, size_t* size) {
+ size_t appendLen = XP_STRLEN(toAppend);
+ if (appendLen >= *size) {
+ appendLen = *size - 1;
+ }
+
+ memcpy(str, toAppend, appendLen * sizeof(XP_CHAR));
+ str += appendLen;
+ *str = '\0';
+ *size -= appendLen;
+
+ return str;
+}
+
+void AnnotateOOMAllocationSize(size_t size) { gOOMAllocationSize = size; }
+
+static size_t gTexturesSize = 0;
+
+void AnnotateTexturesSize(size_t size) { gTexturesSize = size; }
+
+#ifndef XP_WIN
+// Like Windows CopyFile for *nix
+//
+// This function is not declared static even though it's not used outside of
+// this file because of an issue in Fennec which prevents breakpad's exception
+// handler from invoking the MinidumpCallback function. See bug 1424304.
+bool copy_file(const char* from, const char* to) {
+ const int kBufSize = 4096;
+ int fdfrom = sys_open(from, O_RDONLY, 0);
+ if (fdfrom < 0) {
+ return false;
+ }
+
+ bool ok = false;
+
+ int fdto = sys_open(to, O_WRONLY | O_CREAT, 0666);
+ if (fdto < 0) {
+ sys_close(fdfrom);
+ return false;
+ }
+
+ char buf[kBufSize];
+ while (true) {
+ int r = sys_read(fdfrom, buf, kBufSize);
+ if (r == 0) {
+ ok = true;
+ break;
+ }
+ if (r < 0) {
+ break;
+ }
+ char* wbuf = buf;
+ while (r) {
+ int w = sys_write(fdto, wbuf, r);
+ if (w > 0) {
+ r -= w;
+ wbuf += w;
+ } else if (errno != EINTR) {
+ break;
+ }
+ }
+ if (r) {
+ break;
+ }
+ }
+
+ sys_close(fdfrom);
+ sys_close(fdto);
+
+ return ok;
+}
+#endif
+
+/**
+ * The PlatformWriter class provides a tool to create and write to a file that
+ * is safe to call from within an exception handler. To use it this way the
+ * file path needs to be provided as a bare C string.
+ */
+class PlatformWriter {
+ public:
+ PlatformWriter() : mBuffer{}, mPos(0), mFD(kInvalidFileHandle) {}
+ explicit PlatformWriter(const XP_CHAR* aPath) : PlatformWriter() {
+ Open(aPath);
+ }
+
+ ~PlatformWriter() {
+ if (Valid()) {
+ Flush();
+#ifdef XP_WIN
+ CloseHandle(mFD);
+#elif defined(XP_UNIX)
+ sys_close(mFD);
+#endif
+ }
+ }
+
+ void Open(const XP_CHAR* aPath) {
+#ifdef XP_WIN
+ mFD = CreateFile(aPath, GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL, nullptr);
+#elif defined(XP_UNIX)
+ mFD = sys_open(aPath, O_WRONLY | O_CREAT | O_TRUNC, 0600);
+#endif
+ }
+
+ void OpenHandle(FileHandle aFD) { mFD = aFD; }
+ bool Valid() { return mFD != kInvalidFileHandle; }
+
+ void WriteBuffer(const char* aBuffer, size_t aLen) {
+ if (!Valid()) {
+ return;
+ }
+
+ while (aLen-- > 0) {
+ WriteChar(*aBuffer++);
+ }
+ }
+
+ void WriteString(const char* aStr) { WriteBuffer(aStr, my_strlen(aStr)); }
+
+ template <int N>
+ void WriteLiteral(const char (&aStr)[N]) {
+ WriteBuffer(aStr, N - 1);
+ }
+
+ FileHandle FileDesc() { return mFD; }
+
+ private:
+ PlatformWriter(const PlatformWriter&) = delete;
+
+ const PlatformWriter& operator=(const PlatformWriter&) = delete;
+
+ void WriteChar(char aChar) {
+ if (mPos == kBufferSize) {
+ Flush();
+ }
+
+ mBuffer[mPos++] = aChar;
+ }
+
+ void Flush() {
+ if (mPos > 0) {
+ char* buffer = mBuffer;
+ size_t length = mPos;
+ while (length > 0) {
+#ifdef XP_WIN
+ DWORD written_bytes = 0;
+ if (!WriteFile(mFD, buffer, length, &written_bytes, nullptr)) {
+ break;
+ }
+#elif defined(XP_UNIX)
+ ssize_t written_bytes = sys_write(mFD, buffer, length);
+ if (written_bytes < 0) {
+ if (errno == EAGAIN) {
+ continue;
+ }
+
+ break;
+ }
+#endif
+ buffer += written_bytes;
+ length -= written_bytes;
+ }
+
+ mPos = 0;
+ }
+ }
+
+ static const size_t kBufferSize = 512;
+
+ char mBuffer[kBufferSize];
+ size_t mPos;
+ FileHandle mFD;
+};
+
+class JSONAnnotationWriter : public AnnotationWriter {
+ public:
+ explicit JSONAnnotationWriter(PlatformWriter& aPlatformWriter)
+ : mWriter(aPlatformWriter), mEmpty(true) {
+ mWriter.WriteBuffer("{", 1);
+ }
+
+ ~JSONAnnotationWriter() { mWriter.WriteBuffer("}", 1); }
+
+ void Write(Annotation aAnnotation, const char* aValue,
+ size_t aLen = 0) override {
+ size_t len = aLen ? aLen : my_strlen(aValue);
+ const char* annotationStr = AnnotationToString(aAnnotation);
+
+ WritePrefix();
+ mWriter.WriteBuffer(annotationStr, my_strlen(annotationStr));
+ WriteSeparator();
+ WriteEscapedString(aValue, len);
+ WriteSuffix();
+ };
+
+ void Write(Annotation aAnnotation, uint64_t aValue) override {
+ char buffer[32] = {};
+ XP_STOA(aValue, buffer);
+ Write(aAnnotation, buffer);
+ };
+
+ private:
+ void WritePrefix() {
+ if (mEmpty) {
+ mWriter.WriteBuffer("\"", 1);
+ mEmpty = false;
+ } else {
+ mWriter.WriteBuffer(",\"", 2);
+ }
+ }
+
+ void WriteSeparator() { mWriter.WriteBuffer("\":\"", 3); }
+ void WriteSuffix() { mWriter.WriteBuffer("\"", 1); }
+ void WriteEscapedString(const char* aStr, size_t aLen) {
+ for (size_t i = 0; i < aLen; i++) {
+ uint8_t c = aStr[i];
+ if (c <= 0x1f || c == '\\' || c == '\"') {
+ mWriter.WriteBuffer("\\u00", 4);
+ WriteHexDigitAsAsciiChar((c & 0x00f0) >> 4);
+ WriteHexDigitAsAsciiChar(c & 0x000f);
+ } else {
+ mWriter.WriteBuffer(aStr + i, 1);
+ }
+ }
+ }
+
+ void WriteHexDigitAsAsciiChar(uint8_t u) {
+ char buf[1];
+ buf[0] = static_cast<unsigned>((u < 10) ? '0' + u : 'a' + (u - 10));
+ mWriter.WriteBuffer(buf, 1);
+ }
+
+ PlatformWriter& mWriter;
+ bool mEmpty;
+};
+
+class BinaryAnnotationWriter : public AnnotationWriter {
+ public:
+ explicit BinaryAnnotationWriter(PlatformWriter& aPlatformWriter)
+ : mPlatformWriter(aPlatformWriter) {}
+
+ void Write(Annotation aAnnotation, const char* aValue,
+ size_t aLen = 0) override {
+ uint64_t len = aLen ? aLen : my_strlen(aValue);
+ mPlatformWriter.WriteBuffer((const char*)&aAnnotation, sizeof(aAnnotation));
+ mPlatformWriter.WriteBuffer((const char*)&len, sizeof(len));
+ mPlatformWriter.WriteBuffer(aValue, len);
+ };
+
+ void Write(Annotation aAnnotation, uint64_t aValue) override {
+ char buffer[32] = {};
+ XP_STOA(aValue, buffer);
+ Write(aAnnotation, buffer);
+ };
+
+ private:
+ PlatformWriter& mPlatformWriter;
+};
+
+#ifdef MOZ_PHC
+// The stack traces are encoded as a comma-separated list of decimal
+// (not hexadecimal!) addresses, e.g. "12345678,12345679,12345680".
+static void WritePHCStackTrace(AnnotationWriter& aWriter,
+ const Annotation aName,
+ const Maybe<phc::StackTrace>& aStack) {
+ if (aStack.isNothing()) {
+ return;
+ }
+
+ // 21 is the max length of a 64-bit decimal address entry, including the
+ // trailing comma or '\0'. And then we add another 32 just to be safe.
+ char addrsString[mozilla::phc::StackTrace::kMaxFrames * 21 + 32];
+ char addrString[32];
+ char* p = addrsString;
+ *p = 0;
+ for (size_t i = 0; i < aStack->mLength; i++) {
+ if (i != 0) {
+ strcat(addrsString, ",");
+ p++;
+ }
+ XP_STOA(uintptr_t(aStack->mPcs[i]), addrString);
+ strcat(addrsString, addrString);
+ }
+ aWriter.Write(aName, addrsString);
+}
+
+static void WritePHCAddrInfo(AnnotationWriter& writer,
+ const phc::AddrInfo* aAddrInfo) {
+ // Is this a PHC allocation needing special treatment?
+ if (aAddrInfo && aAddrInfo->mKind != phc::AddrInfo::Kind::Unknown) {
+ const char* kindString;
+ switch (aAddrInfo->mKind) {
+ case phc::AddrInfo::Kind::Unknown:
+ kindString = "Unknown(?!)";
+ break;
+ case phc::AddrInfo::Kind::NeverAllocatedPage:
+ kindString = "NeverAllocatedPage";
+ break;
+ case phc::AddrInfo::Kind::InUsePage:
+ kindString = "InUsePage(?!)";
+ break;
+ case phc::AddrInfo::Kind::FreedPage:
+ kindString = "FreedPage";
+ break;
+ case phc::AddrInfo::Kind::GuardPage:
+ kindString = "GuardPage";
+ break;
+ default:
+ kindString = "Unmatched(?!)";
+ break;
+ }
+ writer.Write(Annotation::PHCKind, kindString);
+ writer.Write(Annotation::PHCBaseAddress, uintptr_t(aAddrInfo->mBaseAddr));
+ writer.Write(Annotation::PHCUsableSize, aAddrInfo->mUsableSize);
+
+ WritePHCStackTrace(writer, Annotation::PHCAllocStack,
+ aAddrInfo->mAllocStack);
+ WritePHCStackTrace(writer, Annotation::PHCFreeStack, aAddrInfo->mFreeStack);
+ }
+}
+#endif
+
+/**
+ * If minidump_id is null, we assume that dump_path contains the full
+ * dump file path.
+ */
+static void OpenAPIData(PlatformWriter& aWriter, const XP_CHAR* dump_path,
+ const XP_CHAR* minidump_id = nullptr) {
+ static XP_CHAR extraDataPath[XP_PATH_MAX];
+ size_t size = XP_PATH_MAX;
+ XP_CHAR* p;
+ if (minidump_id) {
+ p = Concat(extraDataPath, dump_path, &size);
+ p = Concat(p, XP_PATH_SEPARATOR, &size);
+ p = Concat(p, minidump_id, &size);
+ } else {
+ p = Concat(extraDataPath, dump_path, &size);
+ // Skip back past the .dmp extension, if any.
+ if (*(p - 4) == XP_TEXT('.')) {
+ p -= 4;
+ size += 4;
+ }
+ }
+ Concat(p, extraFileExtension, &size);
+ aWriter.Open(extraDataPath);
+}
+
+#ifdef XP_WIN
+static void AnnotateMemoryStatus(AnnotationWriter& aWriter) {
+ MEMORYSTATUSEX statex;
+ statex.dwLength = sizeof(statex);
+ if (GlobalMemoryStatusEx(&statex)) {
+ aWriter.Write(Annotation::SystemMemoryUsePercentage, statex.dwMemoryLoad);
+ aWriter.Write(Annotation::TotalVirtualMemory, statex.ullTotalVirtual);
+ aWriter.Write(Annotation::AvailableVirtualMemory, statex.ullAvailVirtual);
+ aWriter.Write(Annotation::TotalPhysicalMemory, statex.ullTotalPhys);
+ aWriter.Write(Annotation::AvailablePhysicalMemory, statex.ullAvailPhys);
+ }
+
+ PERFORMANCE_INFORMATION info;
+ if (K32GetPerformanceInfo(&info, sizeof(info))) {
+ aWriter.Write(Annotation::TotalPageFile, info.CommitLimit * info.PageSize);
+ aWriter.Write(Annotation::AvailablePageFile,
+ (info.CommitLimit - info.CommitTotal) * info.PageSize);
+ }
+}
+#elif XP_MACOSX
+// Extract the total physical memory of the system.
+static void WritePhysicalMemoryStatus(AnnotationWriter& aWriter) {
+ uint64_t physicalMemoryByteSize = 0;
+ const size_t NAME_LEN = 2;
+ int name[NAME_LEN] = {/* Hardware */ CTL_HW,
+ /* 64-bit physical memory size */ HW_MEMSIZE};
+ size_t infoByteSize = sizeof(physicalMemoryByteSize);
+ if (sysctl(name, NAME_LEN, &physicalMemoryByteSize, &infoByteSize,
+ /* We do not replace data */ nullptr,
+ /* We do not replace data */ 0) != -1) {
+ aWriter.Write(Annotation::TotalPhysicalMemory, physicalMemoryByteSize);
+ }
+}
+
+// Extract available and purgeable physical memory.
+static void WriteAvailableMemoryStatus(AnnotationWriter& aWriter) {
+ auto host = mach_host_self();
+ vm_statistics64_data_t stats;
+ unsigned int count = HOST_VM_INFO64_COUNT;
+ if (host_statistics64(host, HOST_VM_INFO64, (host_info64_t)&stats, &count) ==
+ KERN_SUCCESS) {
+ aWriter.Write(Annotation::AvailablePhysicalMemory,
+ stats.free_count * vm_page_size);
+ aWriter.Write(Annotation::PurgeablePhysicalMemory,
+ stats.purgeable_count * vm_page_size);
+ }
+}
+
+// Extract the status of the swap.
+static void WriteSwapFileStatus(AnnotationWriter& aWriter) {
+ const size_t NAME_LEN = 2;
+ int name[] = {/* Hardware */ CTL_VM,
+ /* 64-bit physical memory size */ VM_SWAPUSAGE};
+ struct xsw_usage swapUsage;
+ size_t infoByteSize = sizeof(swapUsage);
+ if (sysctl(name, NAME_LEN, &swapUsage, &infoByteSize,
+ /* We do not replace data */ nullptr,
+ /* We do not replace data */ 0) != -1) {
+ aWriter.Write(Annotation::AvailableSwapMemory, swapUsage.xsu_avail);
+ }
+}
+static void AnnotateMemoryStatus(AnnotationWriter& aWriter) {
+ WritePhysicalMemoryStatus(aWriter);
+ WriteAvailableMemoryStatus(aWriter);
+ WriteSwapFileStatus(aWriter);
+}
+
+#elif XP_LINUX
+
+static void AnnotateMemoryStatus(AnnotationWriter& aWriter) {
+ // We can't simply call `sysinfo` as this requires libc.
+ // So we need to parse /proc/meminfo.
+
+ // We read the entire file to memory prior to parsing
+ // as it makes the parser code a little bit simpler.
+ // As /proc/meminfo is synchronized via `proc_create_single`,
+ // there's no risk of race condition regardless of how we
+ // read it.
+
+ // The buffer in which we're going to load the entire file.
+ // A typical size for /proc/meminfo is 1KiB, so 4KiB should
+ // be large enough until further notice.
+ const size_t BUFFER_SIZE_BYTES = 4096;
+ char buffer[BUFFER_SIZE_BYTES];
+
+ size_t bufferLen = 0;
+ {
+ // Read and load into memory.
+ int fd = sys_open("/proc/meminfo", O_RDONLY, /* chmod */ 0);
+ if (fd == -1) {
+ // No /proc/meminfo? Well, fail silently.
+ return;
+ }
+ auto Guard = MakeScopeExit([fd]() { mozilla::Unused << sys_close(fd); });
+
+ ssize_t bytesRead = 0;
+ do {
+ if ((bytesRead = sys_read(fd, buffer + bufferLen,
+ BUFFER_SIZE_BYTES - bufferLen)) < 0) {
+ if ((errno == EAGAIN) || (errno == EINTR)) {
+ continue;
+ }
+
+ // Cannot read for some reason. Let's give up.
+ return;
+ }
+
+ bufferLen += bytesRead;
+
+ if (bufferLen == BUFFER_SIZE_BYTES) {
+ // The file is too large, bail out
+ return;
+ }
+ } while (bytesRead != 0);
+ }
+
+ // Each line of /proc/meminfo looks like
+ // SomeLabel: number unit
+ // The last line is empty.
+ // Let's write a parser.
+ // Note that we don't care about writing a normative parser, so
+ // we happily skip whitespaces without checking that it's necessary.
+
+ // A stack-allocated structure containing a 0-terminated string.
+ // We could avoid the memory copies and make it a slice at the cost
+ // of a slightly more complicated parser. Since we're not in a
+ // performance-critical section, we didn't.
+ struct DataBuffer {
+ DataBuffer() : data{0}, pos(0) {}
+ // Clear the buffer.
+ void reset() {
+ pos = 0;
+ data[0] = 0;
+ }
+ // Append a character.
+ //
+ // In case of error (if c is '\0' or the buffer is full), does nothing.
+ void append(char c) {
+ if (c == 0 || pos >= sizeof(data) - 1) {
+ return;
+ }
+ data[pos++] = c;
+ data[pos] = 0;
+ }
+ // Compare the buffer against a nul-terminated string.
+ bool operator==(const char* s) const {
+ for (size_t i = 0; i < pos; ++i) {
+ if (s[i] != data[i]) {
+ // Note: Since `data` never contains a '0' in positions [0,pos)
+ // this will bailout once we have reached the end of `s`.
+ return false;
+ }
+ }
+ return true;
+ }
+
+ // A NUL-terminated string of `pos + 1` chars (the +1 is for the 0).
+ char data[256];
+
+ // Invariant: < 256.
+ size_t pos;
+ };
+
+ // A DataBuffer holding the string representation of a non-negative number.
+ struct NumberBuffer : DataBuffer {
+ // If possible, convert the string into a number.
+ // Returns `true` in case of success, `false` in case of failure.
+ bool asNumber(size_t* number) {
+ int result;
+ if (!my_strtoui(&result, data)) {
+ return false;
+ }
+ *number = result;
+ return true;
+ }
+ };
+
+ // A DataBuffer holding the string representation of a unit. As of this
+ // writing, we only support unit `kB`, which seems to be the only unit used in
+ // `/proc/meminfo`.
+ struct UnitBuffer : DataBuffer {
+ // If possible, convert the string into a multiplier, e.g. `kB => 1024`.
+ // Return `true` in case of success, `false` in case of failure.
+ bool asMultiplier(size_t* multiplier) {
+ if (*this == "kB") {
+ *multiplier = 1024;
+ return true;
+ }
+ // Other units don't seem to be specified/used.
+ return false;
+ }
+ };
+
+ // The state of the mini-parser.
+ enum class State {
+ // Reading the label, including the trailing ':'.
+ Label,
+ // Reading the number, ignoring any whitespace.
+ Number,
+ // Reading the unit, ignoring any whitespace.
+ Unit,
+ };
+
+ // A single measure being read from /proc/meminfo, e.g.
+ // the total physical memory available on the system.
+ struct Measure {
+ Measure() : state(State::Label) {}
+ // Reset the measure for a new read.
+ void reset() {
+ state = State::Label;
+ label.reset();
+ number.reset();
+ unit.reset();
+ }
+ // Attempt to convert the measure into a number.
+ // Return `true` if both the number and the multiplier could be
+ // converted, `false` otherwise.
+ // In case of overflow, produces the maximal possible `size_t`.
+ bool asValue(size_t* result) {
+ size_t numberAsSize = 0;
+ if (!number.asNumber(&numberAsSize)) {
+ return false;
+ }
+ size_t unitAsMultiplier = 0;
+ if (!unit.asMultiplier(&unitAsMultiplier)) {
+ return false;
+ }
+ if (numberAsSize * unitAsMultiplier >= numberAsSize) {
+ *result = numberAsSize * unitAsMultiplier;
+ } else {
+ // Overflow. Unlikely, but just in case, let's return
+ // the maximal possible value.
+ *result = size_t(-1);
+ }
+ return true;
+ }
+
+ // The label being read, e.g. `MemFree`. Does not include the trailing ':'.
+ DataBuffer label;
+
+ // The number being read, e.g. "1024".
+ NumberBuffer number;
+
+ // The unit being read, e.g. "kB".
+ UnitBuffer unit;
+
+ // What we're reading at the moment.
+ State state;
+ };
+
+ // A value we wish to store for later processing.
+ // e.g. to compute `AvailablePageFile`, we need to
+ // store `CommitLimit` and `Committed_AS`.
+ struct ValueStore {
+ ValueStore() : value(0), found(false) {}
+ size_t value;
+ bool found;
+ };
+ ValueStore commitLimit;
+ ValueStore committedAS;
+ ValueStore memTotal;
+ ValueStore swapTotal;
+
+ // The current measure.
+ Measure measure;
+
+ for (size_t pos = 0; pos < size_t(bufferLen); ++pos) {
+ const char c = buffer[pos];
+ switch (measure.state) {
+ case State::Label:
+ if (c == ':') {
+ // We have finished reading the label.
+ measure.state = State::Number;
+ } else {
+ measure.label.append(c);
+ }
+ break;
+ case State::Number:
+ if (c == ' ') {
+ // Ignore whitespace
+ } else if ('0' <= c && c <= '9') {
+ // Accumulate numbers.
+ measure.number.append(c);
+ } else {
+ // We have jumped to the unit.
+ measure.unit.append(c);
+ measure.state = State::Unit;
+ }
+ break;
+ case State::Unit:
+ if (c == ' ') {
+ // Ignore whitespace
+ } else if (c == '\n') {
+ // Flush line.
+ // - If this one of the measures we're interested in, write it.
+ // - Once we're done, reset the parser.
+ auto Guard = MakeScopeExit([&measure]() { measure.reset(); });
+
+ struct PointOfInterest {
+ // The label we're looking for, e.g. "MemTotal".
+ const char* label;
+ // If non-nullptr, store the value at this address.
+ ValueStore* dest;
+ // If other than Annotation::Count, write the value for this
+ // annotation.
+ Annotation annotation;
+ };
+ const PointOfInterest POINTS_OF_INTEREST[] = {
+ {"MemTotal", &memTotal, Annotation::TotalPhysicalMemory},
+ {"MemFree", nullptr, Annotation::AvailablePhysicalMemory},
+ {"MemAvailable", nullptr, Annotation::AvailableVirtualMemory},
+ {"SwapFree", nullptr, Annotation::AvailableSwapMemory},
+ {"SwapTotal", &swapTotal, Annotation::Count},
+ {"CommitLimit", &commitLimit, Annotation::Count},
+ {"Committed_AS", &committedAS, Annotation::Count},
+ };
+ for (const auto& pointOfInterest : POINTS_OF_INTEREST) {
+ if (measure.label == pointOfInterest.label) {
+ size_t value;
+ if (measure.asValue(&value)) {
+ if (pointOfInterest.dest != nullptr) {
+ pointOfInterest.dest->found = true;
+ pointOfInterest.dest->value = value;
+ }
+ if (pointOfInterest.annotation != Annotation::Count) {
+ aWriter.Write(pointOfInterest.annotation, value);
+ }
+ }
+ break;
+ }
+ }
+ // Otherwise, ignore.
+ } else {
+ measure.unit.append(c);
+ }
+ break;
+ }
+ }
+
+ if (commitLimit.found && committedAS.found) {
+ // If available, attempt to determine the available virtual memory.
+ // As `commitLimit` is not guaranteed to be larger than `committedAS`,
+ // we return `0` in case the commit limit has already been exceeded.
+ uint64_t availablePageFile = (committedAS.value <= commitLimit.value)
+ ? (commitLimit.value - committedAS.value)
+ : 0;
+ aWriter.Write(Annotation::AvailablePageFile, availablePageFile);
+ }
+ if (memTotal.found && swapTotal.found) {
+ // If available, attempt to determine the available virtual memory.
+ aWriter.Write(Annotation::TotalPageFile, memTotal.value + swapTotal.value);
+ }
+}
+
+#else
+
+static void AnnotateMemoryStatus(AnnotationTable&) {
+ // No memory data for other platforms yet.
+}
+
+#endif // XP_WIN || XP_MACOSX || XP_LINUX || else
+
+#if !defined(MOZ_WIDGET_ANDROID)
+
+/**
+ * Launches the program specified in aProgramPath with aMinidumpPath as its
+ * sole argument.
+ *
+ * @param aProgramPath The path of the program to be launched
+ * @param aMinidumpPath The path of the minidump file, passed as an argument
+ * to the launched program
+ */
+static bool LaunchProgram(const XP_CHAR* aProgramPath,
+ const XP_CHAR* aMinidumpPath) {
+# ifdef XP_WIN
+ XP_CHAR cmdLine[CMDLINE_SIZE];
+ XP_CHAR* p;
+
+ size_t size = CMDLINE_SIZE;
+ p = Concat(cmdLine, L"\"", &size);
+ p = Concat(p, aProgramPath, &size);
+ p = Concat(p, L"\" \"", &size);
+ p = Concat(p, aMinidumpPath, &size);
+ Concat(p, L"\"", &size);
+
+ PROCESS_INFORMATION pi = {};
+ STARTUPINFO si = {};
+ si.cb = sizeof(si);
+
+ // If CreateProcess() fails don't do anything.
+ if (CreateProcess(
+ /* lpApplicationName */ nullptr, (LPWSTR)cmdLine,
+ /* lpProcessAttributes */ nullptr, /* lpThreadAttributes */ nullptr,
+ /* bInheritHandles */ FALSE,
+ NORMAL_PRIORITY_CLASS | CREATE_NO_WINDOW | CREATE_BREAKAWAY_FROM_JOB,
+ /* lpEnvironment */ nullptr, /* lpCurrentDirectory */ nullptr, &si,
+ &pi)) {
+ CloseHandle(pi.hProcess);
+ CloseHandle(pi.hThread);
+ }
+# elif defined(XP_MACOSX)
+ pid_t pid = 0;
+ char* const my_argv[] = {const_cast<char*>(aProgramPath),
+ const_cast<char*>(aMinidumpPath), nullptr};
+
+ char** env = nullptr;
+ char*** nsEnv = _NSGetEnviron();
+ if (nsEnv) {
+ env = *nsEnv;
+ }
+
+ int rv = posix_spawnp(&pid, my_argv[0], nullptr, nullptr, my_argv, env);
+
+ if (rv != 0) {
+ return false;
+ }
+# else // !XP_MACOSX
+ pid_t pid = sys_fork();
+
+ if (pid == -1) {
+ return false;
+ } else if (pid == 0) {
+ Unused << execl(aProgramPath, aProgramPath, aMinidumpPath, nullptr);
+ _exit(1);
+ }
+# endif // XP_MACOSX
+
+ return true;
+}
+
+#else
+
+/**
+ * Launch the crash reporter activity on Android
+ *
+ * @param aProgramPath The path of the program to be launched
+ * @param aMinidumpPath The path to the crash minidump file
+ */
+
+static bool LaunchCrashHandlerService(const XP_CHAR* aProgramPath,
+ const XP_CHAR* aMinidumpPath) {
+ static XP_CHAR extrasPath[XP_PATH_MAX];
+ size_t size = XP_PATH_MAX;
+
+ XP_CHAR* p = Concat(extrasPath, aMinidumpPath, &size);
+ p = Concat(p - 3, "extra", &size);
+
+ pid_t pid = sys_fork();
+
+ if (pid == -1)
+ return false;
+ else if (pid == 0) {
+ // Invoke the crash handler service using am
+ if (androidUserSerial) {
+ Unused << execlp("/system/bin/am", "/system/bin/am",
+ androidStartServiceCommand, "--user", androidUserSerial,
+ "-a", "org.mozilla.gecko.ACTION_CRASHED", "-n",
+ aProgramPath, "--es", "minidumpPath", aMinidumpPath,
+ "--es", "extrasPath", extrasPath, "--ez", "fatal",
+ "true", "--es", "processType", "MAIN", (char*)0);
+ } else {
+ Unused << execlp(
+ "/system/bin/am", "/system/bin/am", androidStartServiceCommand, "-a",
+ "org.mozilla.gecko.ACTION_CRASHED", "-n", aProgramPath, "--es",
+ "minidumpPath", aMinidumpPath, "--es", "extrasPath", extrasPath,
+ "--ez", "fatal", "true", "--es", "processType", "MAIN", (char*)0);
+ }
+ _exit(1);
+
+ } else {
+ // We need to wait on the 'am start' command above to finish, otherwise
+ // everything will be killed by the ActivityManager as soon as the signal
+ // handler exits
+ int status;
+ Unused << HANDLE_EINTR(sys_waitpid(pid, &status, __WALL));
+ }
+
+ return true;
+}
+
+#endif
+
+static void WriteMainThreadRunnableName(AnnotationWriter& aWriter) {
+#ifdef MOZ_COLLECTING_RUNNABLE_TELEMETRY
+ // Only try to collect this information if the main thread is crashing.
+ if (!SignalSafeIsMainThread()) {
+ return;
+ }
+
+ // NOTE: Use `my_memchr` over `strlen` to ensure we don't run off the end of
+ // the buffer if it contains no null bytes. This is used instead of `strnlen`,
+ // as breakpad's linux support library doesn't export a `my_strnlen` function.
+ const char* buf = nsThread::sMainThreadRunnableName.begin();
+ size_t len = nsThread::kRunnableNameBufSize;
+ if (const void* end = my_memchr(buf, '\0', len)) {
+ len = static_cast<const char*>(end) - buf;
+ }
+
+ if (len > 0) {
+ aWriter.Write(Annotation::MainThreadRunnableName, buf, len);
+ }
+#endif
+}
+
+static void WriteOOMAllocationSize(AnnotationWriter& aWriter) {
+ if (gOOMAllocationSize) {
+ aWriter.Write(Annotation::OOMAllocationSize, gOOMAllocationSize);
+ }
+}
+
+static void WriteMozCrashReason(AnnotationWriter& aWriter) {
+ if (gMozCrashReason != nullptr) {
+ aWriter.Write(Annotation::MozCrashReason, gMozCrashReason);
+ }
+}
+
+static void WriteAnnotations(AnnotationWriter& aWriter,
+ const AnnotationTable& aAnnotations) {
+ for (auto key : MakeEnumeratedRange(Annotation::Count)) {
+ const nsCString& value = aAnnotations[key];
+ if (!value.IsEmpty()) {
+ aWriter.Write(key, value.get(), value.Length());
+ }
+ }
+}
+
+static void WriteSynthesizedAnnotations(AnnotationWriter& aWriter) {
+ AnnotateMemoryStatus(aWriter);
+}
+
+static void WriteAnnotationsForMainProcessCrash(PlatformWriter& pw,
+ const phc::AddrInfo* addrInfo,
+ time_t crashTime) {
+ JSONAnnotationWriter writer(pw);
+ WriteAnnotations(writer, crashReporterAPIData_Table);
+ WriteSynthesizedAnnotations(writer);
+ writer.Write(Annotation::CrashTime, uint64_t(crashTime));
+
+ if (inactiveStateStart) {
+ writer.Write(Annotation::LastInteractionDuration,
+ crashTime - inactiveStateStart);
+ }
+
+ double uptimeTS = (TimeStamp::NowLoRes() - TimeStamp::ProcessCreation())
+ .ToSecondsSigDigits();
+ char uptimeTSString[64] = {};
+ SimpleNoCLibDtoA(uptimeTS, uptimeTSString, sizeof(uptimeTSString));
+ writer.Write(Annotation::UptimeTS, uptimeTSString);
+
+ // calculate time since last crash (if possible).
+ if (lastCrashTime != 0) {
+ uint64_t timeSinceLastCrash = crashTime - lastCrashTime;
+
+ if (timeSinceLastCrash != 0) {
+ writer.Write(Annotation::SecondsSinceLastCrash, timeSinceLastCrash);
+ }
+ }
+
+ if (isGarbageCollecting) {
+ writer.Write(Annotation::IsGarbageCollecting, "1");
+ }
+
+ if (eventloopNestingLevel > 0) {
+ writer.Write(Annotation::EventLoopNestingLevel, eventloopNestingLevel);
+ }
+
+#if defined(XP_WIN) && defined(HAS_DLL_BLOCKLIST)
+ // HACK: The DLL blocklist code will manually write its annotations as JSON
+ DllBlocklist_WriteNotes(writer);
+#endif // defined(XP_WIN) && defined(HAS_DLL_BLOCKLIST)
+
+ WriteMozCrashReason(writer);
+
+ WriteMainThreadRunnableName(writer);
+
+ WriteOOMAllocationSize(writer);
+
+ if (gTexturesSize) {
+ writer.Write(Annotation::TextureUsage, gTexturesSize);
+ }
+
+#ifdef MOZ_PHC
+ WritePHCAddrInfo(writer, addrInfo);
+#endif
+}
+
+static void WriteCrashEventFile(time_t crashTime, const char* crashTimeString,
+ const phc::AddrInfo* addrInfo,
+#ifdef XP_LINUX
+ const MinidumpDescriptor& descriptor
+#else
+ const XP_CHAR* minidump_id
+#endif
+) {
+ // Minidump IDs are UUIDs (36) + NULL.
+ static char id_ascii[37] = {};
+#ifdef XP_LINUX
+ const char* index = strrchr(descriptor.path(), '/');
+ MOZ_ASSERT(index);
+ MOZ_ASSERT(strlen(index) == 1 + 36 + 4); // "/" + UUID + ".dmp"
+ for (uint32_t i = 0; i < 36; i++) {
+ id_ascii[i] = *(index + 1 + i);
+ }
+#else
+ MOZ_ASSERT(XP_STRLEN(minidump_id) == 36);
+ for (uint32_t i = 0; i < 36; i++) {
+ id_ascii[i] = *((char*)(minidump_id + i));
+ }
+#endif
+
+ PlatformWriter eventFile;
+
+ if (!eventsDirectory.empty()) {
+ static XP_CHAR crashEventPath[XP_PATH_MAX];
+ size_t size = XP_PATH_MAX;
+ XP_CHAR* p;
+ p = Concat(crashEventPath, eventsDirectory.c_str(), &size);
+ p = Concat(p, XP_PATH_SEPARATOR, &size);
+#ifdef XP_LINUX
+ Concat(p, id_ascii, &size);
+#else
+ Concat(p, minidump_id, &size);
+#endif
+
+ eventFile.Open(crashEventPath);
+ eventFile.WriteLiteral(kCrashMainID);
+ eventFile.WriteString(crashTimeString);
+ eventFile.WriteLiteral("\n");
+ eventFile.WriteString(id_ascii);
+ eventFile.WriteLiteral("\n");
+ WriteAnnotationsForMainProcessCrash(eventFile, addrInfo, crashTime);
+ }
+}
+
+// Callback invoked from breakpad's exception handler, this writes out the
+// last annotations after a crash occurs and launches the crash reporter client.
+//
+// This function is not declared static even though it's not used outside of
+// this file because of an issue in Fennec which prevents breakpad's exception
+// handler from invoking it. See bug 1424304.
+bool MinidumpCallback(
+#ifdef XP_LINUX
+ const MinidumpDescriptor& descriptor,
+#else
+ const XP_CHAR* dump_path, const XP_CHAR* minidump_id,
+#endif
+ void* context,
+#ifdef XP_WIN
+ EXCEPTION_POINTERS* exinfo, MDRawAssertionInfo* assertion,
+#endif
+ const phc::AddrInfo* addrInfo, bool succeeded) {
+ bool returnValue = showOSCrashReporter ? false : succeeded;
+
+ static XP_CHAR minidumpPath[XP_PATH_MAX];
+ size_t size = XP_PATH_MAX;
+ XP_CHAR* p;
+#ifndef XP_LINUX
+ p = Concat(minidumpPath, dump_path, &size);
+ p = Concat(p, XP_PATH_SEPARATOR, &size);
+ p = Concat(p, minidump_id, &size);
+ Concat(p, dumpFileExtension, &size);
+#else
+ Concat(minidumpPath, descriptor.path(), &size);
+#endif
+
+ static XP_CHAR memoryReportLocalPath[XP_PATH_MAX];
+ size = XP_PATH_MAX;
+#ifndef XP_LINUX
+ p = Concat(memoryReportLocalPath, dump_path, &size);
+ p = Concat(p, XP_PATH_SEPARATOR, &size);
+ p = Concat(p, minidump_id, &size);
+#else
+ p = Concat(memoryReportLocalPath, descriptor.path(), &size);
+ // Skip back past the .dmp extension
+ p -= 4;
+#endif
+ Concat(p, memoryReportExtension, &size);
+
+ if (!memoryReportPath.empty()) {
+#ifdef XP_WIN
+ CopyFile(memoryReportPath.c_str(), memoryReportLocalPath, false);
+#else
+ copy_file(memoryReportPath.c_str(), memoryReportLocalPath);
+#endif
+ }
+
+ time_t crashTime = GetCurrentTimeForCrashTime();
+ char crashTimeString[32];
+ XP_TTOA(crashTime, crashTimeString);
+
+ // write crash time to file
+ if (lastCrashTimeFilename[0] != 0) {
+ PlatformWriter lastCrashFile(lastCrashTimeFilename);
+ lastCrashFile.WriteString(crashTimeString);
+ }
+
+ WriteCrashEventFile(crashTime, crashTimeString, addrInfo,
+#ifdef XP_LINUX
+ descriptor
+#else
+ minidump_id
+#endif
+ );
+
+ {
+ PlatformWriter apiData;
+#ifdef XP_LINUX
+ OpenAPIData(apiData, descriptor.path());
+#else
+ OpenAPIData(apiData, dump_path, minidump_id);
+#endif
+ WriteAnnotationsForMainProcessCrash(apiData, addrInfo, crashTime);
+ }
+
+ if (!doReport) {
+#ifdef XP_WIN
+ TerminateProcess(GetCurrentProcess(), 1);
+#endif // XP_WIN
+ return returnValue;
+ }
+
+#if defined(MOZ_WIDGET_ANDROID) // Android
+ returnValue =
+ LaunchCrashHandlerService(crashReporterPath.c_str(), minidumpPath);
+#else // Windows, Mac, Linux, etc...
+ returnValue = LaunchProgram(crashReporterPath.c_str(), minidumpPath);
+# ifdef XP_WIN
+ TerminateProcess(GetCurrentProcess(), 1);
+# endif
+#endif
+
+ return returnValue;
+}
+
+#if defined(XP_MACOSX) || defined(__ANDROID__) || defined(XP_LINUX)
+static size_t EnsureTrailingSlash(XP_CHAR* aBuf, size_t aBufLen) {
+ size_t len = XP_STRLEN(aBuf);
+ if ((len + 1) < aBufLen && len > 0 &&
+ aBuf[len - 1] != XP_PATH_SEPARATOR_CHAR) {
+ aBuf[len] = XP_PATH_SEPARATOR_CHAR;
+ ++len;
+ aBuf[len] = 0;
+ }
+ return len;
+}
+#endif
+
+#if defined(XP_WIN)
+
+static size_t BuildTempPath(wchar_t* aBuf, size_t aBufLen) {
+ // first figure out buffer size
+ DWORD pathLen = GetTempPath(0, nullptr);
+ if (pathLen == 0 || pathLen >= aBufLen) {
+ return 0;
+ }
+
+ return GetTempPath(pathLen, aBuf);
+}
+
+static size_t BuildTempPath(char16_t* aBuf, size_t aBufLen) {
+ return BuildTempPath(reinterpret_cast<wchar_t*>(aBuf), aBufLen);
+}
+
+#elif defined(XP_MACOSX)
+
+static size_t BuildTempPath(char* aBuf, size_t aBufLen) {
+ if (aBufLen < PATH_MAX) {
+ return 0;
+ }
+
+ FSRef fsRef;
+ OSErr err =
+ FSFindFolder(kUserDomain, kTemporaryFolderType, kCreateFolder, &fsRef);
+ if (err != noErr) {
+ return 0;
+ }
+
+ OSStatus status = FSRefMakePath(&fsRef, (UInt8*)aBuf, PATH_MAX);
+ if (status != noErr) {
+ return 0;
+ }
+
+ return EnsureTrailingSlash(aBuf, aBufLen);
+}
+
+#elif defined(__ANDROID__)
+
+static size_t BuildTempPath(char* aBuf, size_t aBufLen) {
+ // GeckoAppShell sets this in the environment
+ const char* tempenv = PR_GetEnv("TMPDIR");
+ if (!tempenv) {
+ return false;
+ }
+ size_t size = aBufLen;
+ Concat(aBuf, tempenv, &size);
+ return EnsureTrailingSlash(aBuf, aBufLen);
+}
+
+#elif defined(XP_UNIX)
+
+static size_t BuildTempPath(char* aBuf, size_t aBufLen) {
+ const char* tempenv = PR_GetEnv("TMPDIR");
+ const char* tmpPath = "/tmp/";
+ if (!tempenv) {
+ tempenv = tmpPath;
+ }
+ size_t size = aBufLen;
+ Concat(aBuf, tempenv, &size);
+ return EnsureTrailingSlash(aBuf, aBufLen);
+}
+
+#else
+# error "Implement this for your platform"
+#endif
+
+template <typename CharT, size_t N>
+static size_t BuildTempPath(CharT (&aBuf)[N]) {
+ static_assert(N >= XP_PATH_MAX, "char array length is too small");
+ return BuildTempPath(&aBuf[0], N);
+}
+
+template <typename PathStringT>
+static bool BuildTempPath(PathStringT& aResult) {
+ aResult.SetLength(XP_PATH_MAX);
+ size_t actualLen = BuildTempPath(aResult.BeginWriting(), XP_PATH_MAX);
+ if (!actualLen) {
+ return false;
+ }
+ aResult.SetLength(actualLen);
+ return true;
+}
+
+FileHandle GetAnnotationTimeCrashFd() { return gChildCrashAnnotationReportFd; }
+
+static void PrepareChildExceptionTimeAnnotations(
+ const phc::AddrInfo* addrInfo) {
+ MOZ_ASSERT(!XRE_IsParentProcess());
+
+ PlatformWriter apiData;
+ apiData.OpenHandle(GetAnnotationTimeCrashFd());
+ BinaryAnnotationWriter writer(apiData);
+
+ WriteMozCrashReason(writer);
+
+ WriteMainThreadRunnableName(writer);
+
+ WriteOOMAllocationSize(writer);
+
+#ifdef MOZ_PHC
+ WritePHCAddrInfo(writer, addrInfo);
+#endif
+
+ WriteAnnotations(writer, crashReporterAPIData_Table);
+}
+
+#ifdef XP_WIN
+
+static void ReserveBreakpadVM() {
+ if (!gBreakpadReservedVM) {
+ gBreakpadReservedVM =
+ VirtualAlloc(nullptr, kReserveSize, MEM_RESERVE, PAGE_NOACCESS);
+ }
+}
+
+static void FreeBreakpadVM() {
+ if (gBreakpadReservedVM) {
+ VirtualFree(gBreakpadReservedVM, 0, MEM_RELEASE);
+ }
+}
+
+static bool IsCrashingException(EXCEPTION_POINTERS* exinfo) {
+ if (!exinfo) {
+ return true;
+ }
+
+ PEXCEPTION_RECORD e = (PEXCEPTION_RECORD)exinfo->ExceptionRecord;
+ switch (e->ExceptionCode) {
+ case STATUS_FLOAT_DENORMAL_OPERAND:
+ case STATUS_FLOAT_DIVIDE_BY_ZERO:
+ case STATUS_FLOAT_INEXACT_RESULT:
+ case STATUS_FLOAT_INVALID_OPERATION:
+ case STATUS_FLOAT_OVERFLOW:
+ case STATUS_FLOAT_STACK_CHECK:
+ case STATUS_FLOAT_UNDERFLOW:
+ case STATUS_FLOAT_MULTIPLE_FAULTS:
+ case STATUS_FLOAT_MULTIPLE_TRAPS:
+ return false; // Don't write minidump, continue exception search
+ default:
+ return true;
+ }
+}
+
+#endif // XP_WIN
+
+// Do various actions to prepare the child process for minidump generation.
+// This includes disabling the I/O interposer and DLL blocklist which both
+// would get in the way. We also free the address space we had reserved in
+// 32-bit builds to free room for the minidump generation to do its work.
+static void PrepareForMinidump() {
+ mozilla::IOInterposer::Disable();
+#if defined(XP_WIN)
+# if defined(DEBUG) && defined(HAS_DLL_BLOCKLIST)
+ DllBlocklist_Shutdown();
+# endif
+ FreeBreakpadVM();
+#endif // XP_WIN
+}
+
+#ifdef XP_WIN
+
+/**
+ * Filters out floating point exceptions which are handled by nsSigHandlers.cpp
+ * and should not be handled as crashes.
+ */
+static ExceptionHandler::FilterResult Filter(void* context,
+ EXCEPTION_POINTERS* exinfo,
+ MDRawAssertionInfo* assertion) {
+ if (!IsCrashingException(exinfo)) {
+ return ExceptionHandler::FilterResult::ContinueSearch;
+ }
+
+ PrepareForMinidump();
+ return ExceptionHandler::FilterResult::HandleException;
+}
+
+static ExceptionHandler::FilterResult ChildFilter(
+ void* context, EXCEPTION_POINTERS* exinfo, MDRawAssertionInfo* assertion) {
+ if (!IsCrashingException(exinfo)) {
+ return ExceptionHandler::FilterResult::ContinueSearch;
+ }
+
+ if (gEncounteredChildException.exchange(true)) {
+ return ExceptionHandler::FilterResult::AbortWithoutMinidump;
+ }
+
+ PrepareForMinidump();
+ return ExceptionHandler::FilterResult::HandleException;
+}
+
+static MINIDUMP_TYPE GetMinidumpType() {
+ MINIDUMP_TYPE minidump_type = static_cast<MINIDUMP_TYPE>(
+ MiniDumpWithFullMemoryInfo | MiniDumpWithUnloadedModules);
+
+# ifdef NIGHTLY_BUILD
+ // This is Nightly only because this doubles the size of minidumps based
+ // on the experimental data.
+ minidump_type =
+ static_cast<MINIDUMP_TYPE>(minidump_type | MiniDumpWithProcessThreadData);
+
+ // dbghelp.dll on Win7 can't handle overlapping memory regions so we only
+ // enable this feature on Win8 or later.
+ if (IsWin8OrLater()) {
+ minidump_type = static_cast<MINIDUMP_TYPE>(
+ minidump_type |
+ // This allows us to examine heap objects referenced from stack objects
+ // at the cost of further doubling the size of minidumps.
+ MiniDumpWithIndirectlyReferencedMemory);
+ }
+# endif
+
+ const char* e = PR_GetEnv("MOZ_CRASHREPORTER_FULLDUMP");
+ if (e && *e) {
+ minidump_type = MiniDumpWithFullMemory;
+ }
+
+ return minidump_type;
+}
+
+#else
+
+static bool Filter(void* context) {
+ PrepareForMinidump();
+ return true;
+}
+
+static bool ChildFilter(void* context) {
+ if (gEncounteredChildException.exchange(true)) {
+ return false;
+ }
+
+ PrepareForMinidump();
+ return true;
+}
+
+#endif // !defined(XP_WIN)
+
+static bool ChildMinidumpCallback(
+#if defined(XP_WIN)
+ const wchar_t* dump_path, const wchar_t* minidump_id,
+#elif defined(XP_LINUX)
+ const MinidumpDescriptor& descriptor,
+#else // defined(XP_MACOSX)
+ const char* dump_dir, const char* minidump_id,
+#endif
+ void* context,
+#if defined(XP_WIN)
+ EXCEPTION_POINTERS* exinfo, MDRawAssertionInfo* assertion,
+#endif // defined(XP_WIN)
+ const mozilla::phc::AddrInfo* addr_info, bool succeeded) {
+
+ PrepareChildExceptionTimeAnnotations(addr_info);
+ return succeeded;
+}
+
+static bool ShouldReport() {
+ // this environment variable prevents us from launching
+ // the crash reporter client
+ const char* envvar = PR_GetEnv("MOZ_CRASHREPORTER_NO_REPORT");
+ if (envvar && *envvar) {
+ return false;
+ }
+
+ envvar = PR_GetEnv("MOZ_CRASHREPORTER_FULLDUMP");
+ if (envvar && *envvar) {
+ return false;
+ }
+
+ return true;
+}
+
+static void TerminateHandler() { MOZ_CRASH("Unhandled exception"); }
+
+#if !defined(MOZ_WIDGET_ANDROID)
+
+// Locate the specified executable and store its path as a native string in
+// the |aPath| so we can later invoke it from within the exception handler.
+static nsresult LocateExecutable(nsIFile* aXREDirectory, const nsAString& aName,
+ PathString& aPath) {
+ nsCOMPtr<nsIFile> exePath;
+ nsresult rv = aXREDirectory->Clone(getter_AddRefs(exePath));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+# ifdef XP_MACOSX
+ exePath->SetNativeLeafName("MacOS"_ns);
+ exePath->Append(u"crashreporter.app"_ns);
+ exePath->Append(u"Contents"_ns);
+ exePath->Append(u"MacOS"_ns);
+# endif
+
+ exePath->Append(aName);
+ aPath = exePath->NativePath();
+ return NS_OK;
+}
+
+#endif // !defined(MOZ_WIDGET_ANDROID)
+
+#if defined(XP_WIN)
+
+DWORD WINAPI FlushContentProcessAnnotationsThreadFunc(LPVOID aContext) {
+ PrepareChildExceptionTimeAnnotations(nullptr);
+ return 0;
+}
+
+#else
+
+static const int kAnnotationSignal = SIGUSR2;
+
+static void AnnotationSignalHandler(int aSignal, siginfo_t* aInfo,
+ void* aContext) {
+ PrepareChildExceptionTimeAnnotations(nullptr);
+}
+
+#endif // defined(XP_WIN)
+
+static void InitChildAnnotationsFlusher() {
+#if !defined(XP_WIN)
+ struct sigaction oldSigAction = {};
+ struct sigaction sigAction = {};
+ sigAction.sa_sigaction = AnnotationSignalHandler;
+ sigAction.sa_flags = SA_RESTART | SA_SIGINFO;
+ sigemptyset(&sigAction.sa_mask);
+ mozilla::DebugOnly<int> rv =
+ sigaction(kAnnotationSignal, &sigAction, &oldSigAction);
+ MOZ_ASSERT(rv == 0, "Failed to install the crash reporter's SIGUSR2 handler");
+ MOZ_ASSERT(oldSigAction.sa_sigaction == nullptr,
+ "A SIGUSR2 handler was already present");
+#endif // !defined(XP_WIN)
+}
+
+static bool FlushContentProcessAnnotations(ProcessHandle aTargetPid) {
+#if defined(XP_WIN)
+ nsAutoHandle hThread(CreateRemoteThread(
+ aTargetPid, nullptr, 0, FlushContentProcessAnnotationsThreadFunc, nullptr,
+ 0, nullptr));
+ return !!hThread;
+#else // POSIX platforms
+ return kill(aTargetPid, kAnnotationSignal) == 0;
+#endif
+}
+
+static void InitializeAnnotationFacilities() {
+ crashReporterAPILock = new Mutex("crashReporterAPILock");
+ notesFieldLock = new Mutex("notesFieldLock");
+ notesField = new nsCString();
+ if (!XRE_IsParentProcess()) {
+ InitChildAnnotationsFlusher();
+ }
+}
+
+static void TeardownAnnotationFacilities() {
+ std::fill(crashReporterAPIData_Table.begin(),
+ crashReporterAPIData_Table.end(), ""_ns);
+
+ delete crashReporterAPILock;
+ crashReporterAPILock = nullptr;
+
+ delete notesFieldLock;
+ notesFieldLock = nullptr;
+
+ delete notesField;
+ notesField = nullptr;
+}
+
+nsresult SetExceptionHandler(nsIFile* aXREDirectory, bool force /*=false*/) {
+ if (gExceptionHandler) return NS_ERROR_ALREADY_INITIALIZED;
+
+#if defined(DEBUG)
+ // In debug builds, disable the crash reporter by default, and allow to
+ // enable it with the MOZ_CRASHREPORTER environment variable.
+ const char* envvar = PR_GetEnv("MOZ_CRASHREPORTER");
+ if ((!envvar || !*envvar) && !force) return NS_OK;
+#else
+ // In other builds, enable the crash reporter by default, and allow
+ // disabling it with the MOZ_CRASHREPORTER_DISABLE environment variable.
+ const char* envvar = PR_GetEnv("MOZ_CRASHREPORTER_DISABLE");
+ if (envvar && *envvar && !force) return NS_OK;
+#endif
+
+ // this environment variable prevents us from launching
+ // the crash reporter client
+ doReport = ShouldReport();
+
+ RegisterRuntimeExceptionModule();
+ InitializeAnnotationFacilities();
+
+#if !defined(MOZ_WIDGET_ANDROID)
+ // Locate the crash reporter executable
+ PathString crashReporterPath_temp;
+ nsresult rv = LocateExecutable(aXREDirectory, CRASH_REPORTER_FILENAME,
+ crashReporterPath_temp);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+
+ crashReporterPath = crashReporterPath_temp.get();
+#else
+ // On Android, we launch a service defined via MOZ_ANDROID_CRASH_HANDLER
+ const char* androidCrashHandler = PR_GetEnv("MOZ_ANDROID_CRASH_HANDLER");
+ if (androidCrashHandler) {
+ crashReporterPath = xpstring(androidCrashHandler);
+ } else {
+ NS_WARNING("No Android crash handler set");
+ }
+
+ const char* deviceAndroidVersion =
+ PR_GetEnv("MOZ_ANDROID_DEVICE_SDK_VERSION");
+ if (deviceAndroidVersion != nullptr) {
+ const int deviceSdkVersion = atol(deviceAndroidVersion);
+ if (deviceSdkVersion >= 26) {
+ androidStartServiceCommand = (char*)"start-foreground-service";
+ } else {
+ androidStartServiceCommand = (char*)"startservice";
+ }
+ }
+#endif // !defined(MOZ_WIDGET_ANDROID)
+
+ // get temp path to use for minidump path
+ PathString tempPath;
+ if (!BuildTempPath(tempPath)) {
+ return NS_ERROR_FAILURE;
+ }
+
+#ifdef XP_WIN
+ ReserveBreakpadVM();
+
+ // Pre-load psapi.dll to prevent it from being loaded during exception
+ // handling.
+ ::LoadLibraryW(L"psapi.dll");
+#endif // XP_WIN
+
+#ifdef MOZ_WIDGET_ANDROID
+ androidUserSerial = getenv("MOZ_ANDROID_USER_SERIAL_NUMBER");
+#endif
+
+ // Initialize the flag and mutex used to avoid dump processing
+ // once browser termination has begun.
+ NS_ASSERTION(!dumpSafetyLock, "Shouldn't have a lock yet");
+ // Do not deallocate this lock while it is still possible for
+ // isSafeToDump to be tested on another thread.
+ dumpSafetyLock = new Mutex("dumpSafetyLock");
+ MutexAutoLock lock(*dumpSafetyLock);
+ isSafeToDump = true;
+
+ // now set the exception handler
+#ifdef XP_LINUX
+ MinidumpDescriptor descriptor(tempPath.get());
+#endif
+
+#ifdef XP_WIN
+ previousUnhandledExceptionFilter = GetUnhandledExceptionFilter();
+#endif
+
+ gExceptionHandler = new google_breakpad::ExceptionHandler(
+#ifdef XP_LINUX
+ descriptor,
+#elif defined(XP_WIN)
+ std::wstring(tempPath.get()),
+#else
+ tempPath.get(),
+#endif
+
+ Filter, MinidumpCallback, nullptr,
+#ifdef XP_WIN
+ google_breakpad::ExceptionHandler::HANDLER_ALL, GetMinidumpType(),
+ (const wchar_t*)nullptr, nullptr);
+#else
+ true
+# ifdef XP_MACOSX
+ ,
+ nullptr
+# endif
+# ifdef XP_LINUX
+ ,
+ -1
+# endif
+ );
+#endif // XP_WIN
+
+ if (!gExceptionHandler) return NS_ERROR_OUT_OF_MEMORY;
+
+#ifdef XP_WIN
+ gExceptionHandler->set_handle_debug_exceptions(true);
+
+ // Initially set sIncludeContextHeap to true for debugging startup crashes
+ // even if the controlling pref value is false.
+ SetIncludeContextHeap(true);
+# if defined(HAVE_64BIT_BUILD)
+ // Tell JS about the new filter before we disable SetUnhandledExceptionFilter
+ SetJitExceptionHandler();
+# endif
+
+ RecordMainThreadId();
+
+ // protect the crash reporter from being unloaded
+ gBlockUnhandledExceptionFilter = true;
+ gKernel32Intercept.Init("kernel32.dll");
+ DebugOnly<bool> ok = stub_SetUnhandledExceptionFilter.Set(
+ gKernel32Intercept, "SetUnhandledExceptionFilter",
+ &patched_SetUnhandledExceptionFilter);
+
+# ifdef DEBUG
+ if (!ok)
+ printf_stderr(
+ "SetUnhandledExceptionFilter hook failed; crash reporter is "
+ "vulnerable.\n");
+# endif
+#endif
+
+ // store application start time
+ char timeString[32];
+ time_t startupTime = time(nullptr);
+ XP_TTOA(startupTime, timeString);
+ AnnotateCrashReport(Annotation::StartupTime, nsDependentCString(timeString));
+
+#if defined(XP_MACOSX)
+ // On OS X, many testers like to see the OS crash reporting dialog
+ // since it offers immediate stack traces. We allow them to set
+ // a default to pass exceptions to the OS handler.
+ Boolean keyExistsAndHasValidFormat = false;
+ Boolean prefValue = ::CFPreferencesGetAppBooleanValue(
+ CFSTR("OSCrashReporter"), kCFPreferencesCurrentApplication,
+ &keyExistsAndHasValidFormat);
+ if (keyExistsAndHasValidFormat) showOSCrashReporter = prefValue;
+#endif
+
+ oldTerminateHandler = std::set_terminate(&TerminateHandler);
+
+ return NS_OK;
+}
+
+bool GetEnabled() { return gExceptionHandler != nullptr; }
+
+bool GetMinidumpPath(nsAString& aPath) {
+ if (!gExceptionHandler) return false;
+
+#ifndef XP_LINUX
+ aPath = CONVERT_XP_CHAR_TO_UTF16(gExceptionHandler->dump_path().c_str());
+#else
+ aPath = CONVERT_XP_CHAR_TO_UTF16(
+ gExceptionHandler->minidump_descriptor().directory().c_str());
+#endif
+ return true;
+}
+
+nsresult SetMinidumpPath(const nsAString& aPath) {
+ if (!gExceptionHandler) return NS_ERROR_NOT_INITIALIZED;
+
+#ifdef XP_WIN
+ gExceptionHandler->set_dump_path(
+ std::wstring(char16ptr_t(aPath.BeginReading())));
+#elif defined(XP_LINUX)
+ gExceptionHandler->set_minidump_descriptor(
+ MinidumpDescriptor(NS_ConvertUTF16toUTF8(aPath).BeginReading()));
+#else
+ gExceptionHandler->set_dump_path(NS_ConvertUTF16toUTF8(aPath).BeginReading());
+#endif
+ return NS_OK;
+}
+
+static nsresult WriteDataToFile(nsIFile* aFile, const nsACString& data) {
+ PRFileDesc* fd;
+ nsresult rv = aFile->OpenNSPRFileDesc(PR_WRONLY | PR_CREATE_FILE, 00600, &fd);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = NS_OK;
+ if (PR_Write(fd, data.Data(), data.Length()) == -1) {
+ rv = NS_ERROR_FAILURE;
+ }
+ PR_Close(fd);
+ return rv;
+}
+
+static nsresult GetFileContents(nsIFile* aFile, nsACString& data) {
+ PRFileDesc* fd;
+ nsresult rv = aFile->OpenNSPRFileDesc(PR_RDONLY, 0, &fd);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = NS_OK;
+ int32_t filesize = PR_Available(fd);
+ if (filesize <= 0) {
+ rv = NS_ERROR_FILE_NOT_FOUND;
+ } else {
+ data.SetLength(filesize);
+ if (PR_Read(fd, data.BeginWriting(), filesize) == -1) {
+ rv = NS_ERROR_FAILURE;
+ }
+ }
+ PR_Close(fd);
+ return rv;
+}
+
+// Function typedef for initializing a piece of data that we
+// don't already have.
+typedef nsresult (*InitDataFunc)(nsACString&);
+
+// Attempt to read aFile's contents into aContents, if aFile
+// does not exist, create it and initialize its contents
+// by calling aInitFunc for the data.
+static nsresult GetOrInit(nsIFile* aDir, const nsACString& filename,
+ nsACString& aContents, InitDataFunc aInitFunc) {
+ bool exists;
+
+ nsCOMPtr<nsIFile> dataFile;
+ nsresult rv = aDir->Clone(getter_AddRefs(dataFile));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = dataFile->AppendNative(filename);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = dataFile->Exists(&exists);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ if (!exists) {
+ if (aInitFunc) {
+ // get the initial value and write it to the file
+ rv = aInitFunc(aContents);
+ NS_ENSURE_SUCCESS(rv, rv);
+ rv = WriteDataToFile(dataFile, aContents);
+ } else {
+ // didn't pass in an init func
+ rv = NS_ERROR_FAILURE;
+ }
+ } else {
+ // just get the file's contents
+ rv = GetFileContents(dataFile, aContents);
+ }
+
+ return rv;
+}
+
+// Init the "install time" data. We're taking an easy way out here
+// and just setting this to "the time when this version was first run".
+static nsresult InitInstallTime(nsACString& aInstallTime) {
+ time_t t = time(nullptr);
+ aInstallTime = nsPrintfCString("%" PRIu64, static_cast<uint64_t>(t));
+
+ return NS_OK;
+}
+
+// Ensure a directory exists and create it if missing.
+static nsresult EnsureDirectoryExists(nsIFile* dir) {
+ nsresult rv = dir->Create(nsIFile::DIRECTORY_TYPE, 0700);
+
+ if (NS_WARN_IF(NS_FAILED(rv) && rv != NS_ERROR_FILE_ALREADY_EXISTS)) {
+ return rv;
+ }
+
+ return NS_OK;
+}
+
+// Creates a directory that will be accessible by the crash reporter. The
+// directory will live under Firefox default data directory and will use the
+// specified name. The directory path will be passed to the crashreporter via
+// the specified environment variable.
+static nsresult SetupCrashReporterDirectory(nsIFile* aAppDataDirectory,
+ const char* aDirName,
+ const XP_CHAR* aEnvVarName,
+ nsIFile** aDirectory = nullptr) {
+ nsCOMPtr<nsIFile> directory;
+ nsresult rv = aAppDataDirectory->Clone(getter_AddRefs(directory));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = directory->AppendNative(nsDependentCString(aDirName));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ EnsureDirectoryExists(directory);
+ xpstring* directoryPath = CreatePathFromFile(directory);
+
+ if (!directoryPath) {
+ return NS_ERROR_FAILURE;
+ }
+
+#if defined(XP_WIN)
+ SetEnvironmentVariableW(aEnvVarName, directoryPath->c_str());
+#else
+ setenv(aEnvVarName, directoryPath->c_str(), /* overwrite */ 1);
+#endif
+
+ delete directoryPath;
+
+ if (aDirectory) {
+ directory.forget(aDirectory);
+ }
+
+ return NS_OK;
+}
+
+// Annotate the crash report with a Unique User ID and time
+// since install. Also do some prep work for recording
+// time since last crash, which must be calculated at
+// crash time.
+// If any piece of data doesn't exist, initialize it first.
+nsresult SetupExtraData(nsIFile* aAppDataDirectory,
+ const nsACString& aBuildID) {
+ nsCOMPtr<nsIFile> dataDirectory;
+ nsresult rv =
+ SetupCrashReporterDirectory(aAppDataDirectory, "Crash Reports",
+ XP_TEXT("MOZ_CRASHREPORTER_DATA_DIRECTORY"),
+ getter_AddRefs(dataDirectory));
+
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+
+ rv = SetupCrashReporterDirectory(aAppDataDirectory, "Pending Pings",
+ XP_TEXT("MOZ_CRASHREPORTER_PING_DIRECTORY"));
+
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+
+ nsAutoCString data;
+ if (NS_SUCCEEDED(GetOrInit(dataDirectory, "InstallTime"_ns + aBuildID, data,
+ InitInstallTime)))
+ AnnotateCrashReport(Annotation::InstallTime, data);
+
+ // this is a little different, since we can't init it with anything,
+ // since it's stored at crash time, and we can't annotate the
+ // crash report with the stored value, since we really want
+ // (now - LastCrash), so we just get a value if it exists,
+ // and store it in a time_t value.
+ if (NS_SUCCEEDED(GetOrInit(dataDirectory, "LastCrash"_ns, data, nullptr))) {
+ lastCrashTime = (time_t)atol(data.get());
+ }
+
+ // not really the best place to init this, but I have the path I need here
+ nsCOMPtr<nsIFile> lastCrashFile;
+ rv = dataDirectory->Clone(getter_AddRefs(lastCrashFile));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = lastCrashFile->AppendNative("LastCrash"_ns);
+ NS_ENSURE_SUCCESS(rv, rv);
+ memset(lastCrashTimeFilename, 0, sizeof(lastCrashTimeFilename));
+
+ PathString filename;
+#if defined(XP_WIN)
+ rv = lastCrashFile->GetPath(filename);
+#else
+ rv = lastCrashFile->GetNativePath(filename);
+#endif
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ if (filename.Length() < XP_PATH_MAX) {
+#if defined(XP_WIN)
+ wcsncpy(lastCrashTimeFilename, filename.get(), filename.Length());
+#else
+ strncpy(lastCrashTimeFilename, filename.get(), filename.Length());
+#endif
+ }
+
+ return NS_OK;
+}
+
+static void OOPDeinit();
+
+nsresult UnsetExceptionHandler() {
+ if (isSafeToDump) {
+ MutexAutoLock lock(*dumpSafetyLock);
+ isSafeToDump = false;
+ }
+
+#ifdef XP_WIN
+ // allow SetUnhandledExceptionFilter
+ gBlockUnhandledExceptionFilter = false;
+#endif
+
+ delete gExceptionHandler;
+
+ TeardownAnnotationFacilities();
+
+ if (!gExceptionHandler) return NS_ERROR_NOT_INITIALIZED;
+
+ gExceptionHandler = nullptr;
+
+ OOPDeinit();
+
+ delete dumpSafetyLock;
+ dumpSafetyLock = nullptr;
+
+ std::set_terminate(oldTerminateHandler);
+
+ return NS_OK;
+}
+
+nsresult AnnotateCrashReport(Annotation key, bool data) {
+ return AnnotateCrashReport(key, data ? "1"_ns : "0"_ns);
+}
+
+nsresult AnnotateCrashReport(Annotation key, int data) {
+ nsAutoCString dataString;
+ dataString.AppendInt(data);
+
+ return AnnotateCrashReport(key, dataString);
+}
+
+nsresult AnnotateCrashReport(Annotation key, unsigned int data) {
+ nsAutoCString dataString;
+ dataString.AppendInt(data);
+
+ return AnnotateCrashReport(key, dataString);
+}
+
+nsresult AnnotateCrashReport(Annotation key, const nsACString& data) {
+ if (!GetEnabled()) return NS_ERROR_NOT_INITIALIZED;
+
+ MutexAutoLock lock(*crashReporterAPILock);
+ crashReporterAPIData_Table[key] = data;
+
+ return NS_OK;
+}
+
+nsresult AppendToCrashReportAnnotation(Annotation key, const nsACString& data) {
+ if (!GetEnabled()) return NS_ERROR_NOT_INITIALIZED;
+
+ MutexAutoLock lock(*crashReporterAPILock);
+ nsAutoCString newString(crashReporterAPIData_Table[key]);
+ newString.Append(" - "_ns);
+ newString.Append(data);
+ crashReporterAPIData_Table[key] = newString;
+
+ return NS_OK;
+}
+
+nsresult RemoveCrashReportAnnotation(Annotation key) {
+ return AnnotateCrashReport(key, ""_ns);
+}
+
+AutoAnnotateCrashReport::AutoAnnotateCrashReport(Annotation key, bool data)
+ : AutoAnnotateCrashReport(key, data ? "1"_ns : "0"_ns) {}
+
+AutoAnnotateCrashReport::AutoAnnotateCrashReport(Annotation key, int data)
+ : AutoAnnotateCrashReport(key, nsPrintfCString("%d", data)) {}
+
+AutoAnnotateCrashReport::AutoAnnotateCrashReport(Annotation key, unsigned data)
+ : AutoAnnotateCrashReport(key, nsPrintfCString("%u", data)) {}
+
+AutoAnnotateCrashReport::AutoAnnotateCrashReport(Annotation key,
+ const nsACString& data)
+ : mKey(key) {
+ if (GetEnabled()) {
+ MutexAutoLock lock(*crashReporterAPILock);
+ auto& entry = crashReporterAPIData_Table[mKey];
+ mPrevious = std::move(entry);
+ entry = data;
+ }
+}
+
+AutoAnnotateCrashReport::~AutoAnnotateCrashReport() {
+ if (GetEnabled()) {
+ MutexAutoLock lock(*crashReporterAPILock);
+ crashReporterAPIData_Table[mKey] = std::move(mPrevious);
+ }
+}
+
+void MergeCrashAnnotations(AnnotationTable& aDst, const AnnotationTable& aSrc) {
+ for (auto key : MakeEnumeratedRange(Annotation::Count)) {
+ const nsCString& value = aSrc[key];
+ if (!value.IsEmpty()) {
+ aDst[key] = value;
+ }
+ }
+}
+
+static void MergeContentCrashAnnotations(AnnotationTable& aDst) {
+ MutexAutoLock lock(*crashReporterAPILock);
+ MergeCrashAnnotations(aDst, crashReporterAPIData_Table);
+}
+
+// Adds crash time, uptime and memory report annotations
+static void AddCommonAnnotations(AnnotationTable& aAnnotations) {
+ const time_t crashTime = time(nullptr);
+ nsAutoCString crashTimeStr;
+ crashTimeStr.AppendInt(static_cast<uint64_t>(crashTime));
+ aAnnotations[Annotation::CrashTime] = crashTimeStr;
+
+ if (inactiveStateStart) {
+ nsAutoCString inactiveDuration;
+ inactiveDuration.AppendInt(
+ static_cast<uint64_t>(crashTime - inactiveStateStart));
+ aAnnotations[Annotation::LastInteractionDuration] = inactiveDuration;
+ }
+
+ double uptimeTS = (TimeStamp::NowLoRes() - TimeStamp::ProcessCreation())
+ .ToSecondsSigDigits();
+ nsAutoCString uptimeStr;
+ uptimeStr.AppendFloat(uptimeTS);
+ aAnnotations[Annotation::UptimeTS] = uptimeStr;
+}
+
+nsresult SetGarbageCollecting(bool collecting) {
+ if (!GetEnabled()) return NS_ERROR_NOT_INITIALIZED;
+
+ isGarbageCollecting = collecting;
+
+ return NS_OK;
+}
+
+void SetEventloopNestingLevel(uint32_t level) { eventloopNestingLevel = level; }
+
+void ClearInactiveStateStart() { inactiveStateStart = 0; }
+void SetInactiveStateStart() {
+ if (!inactiveStateStart) {
+ inactiveStateStart = GetCurrentTimeForCrashTime();
+ }
+}
+
+void SetMinidumpAnalysisAllThreads() {
+ char* env = strdup("MOZ_CRASHREPORTER_DUMP_ALL_THREADS=1");
+ PR_SetEnv(env);
+}
+
+nsresult AppendAppNotesToCrashReport(const nsACString& data) {
+ if (!GetEnabled()) return NS_ERROR_NOT_INITIALIZED;
+
+ MutexAutoLock lock(*notesFieldLock);
+
+ notesField->Append(data);
+ return AnnotateCrashReport(Annotation::Notes, *notesField);
+}
+
+// Returns true if found, false if not found.
+static bool GetAnnotation(CrashReporter::Annotation key, nsACString& data) {
+ if (!gExceptionHandler) return false;
+
+ MutexAutoLock lock(*crashReporterAPILock);
+ const nsCString& entry = crashReporterAPIData_Table[key];
+ if (entry.IsEmpty()) {
+ return false;
+ }
+
+ data = entry;
+ return true;
+}
+
+nsresult RegisterAppMemory(void* ptr, size_t length) {
+ if (!GetEnabled()) return NS_ERROR_NOT_INITIALIZED;
+
+#if defined(XP_LINUX) || defined(XP_WIN)
+ gExceptionHandler->RegisterAppMemory(ptr, length);
+ return NS_OK;
+#else
+ return NS_ERROR_NOT_IMPLEMENTED;
+#endif
+}
+
+nsresult UnregisterAppMemory(void* ptr) {
+ if (!GetEnabled()) return NS_ERROR_NOT_INITIALIZED;
+
+#if defined(XP_LINUX) || defined(XP_WIN)
+ gExceptionHandler->UnregisterAppMemory(ptr);
+ return NS_OK;
+#else
+ return NS_ERROR_NOT_IMPLEMENTED;
+#endif
+}
+
+void SetIncludeContextHeap(bool aValue) {
+ sIncludeContextHeap = aValue;
+
+#ifdef XP_WIN
+ if (gExceptionHandler) {
+ gExceptionHandler->set_include_context_heap(sIncludeContextHeap);
+ }
+#endif
+}
+
+bool GetServerURL(nsACString& aServerURL) {
+ if (!gExceptionHandler) return false;
+
+ return GetAnnotation(CrashReporter::Annotation::ServerURL, aServerURL);
+}
+
+nsresult SetServerURL(const nsACString& aServerURL) {
+ // store server URL with the API data
+ // the client knows to handle this specially
+ return AnnotateCrashReport(Annotation::ServerURL, aServerURL);
+}
+
+nsresult SetRestartArgs(int argc, char** argv) {
+ if (!gExceptionHandler) return NS_OK;
+
+ int i;
+ nsAutoCString envVar;
+ char* env;
+ char* argv0 = getenv("MOZ_APP_LAUNCHER");
+ for (i = 0; i < argc; i++) {
+ envVar = "MOZ_CRASHREPORTER_RESTART_ARG_";
+ envVar.AppendInt(i);
+ envVar += "=";
+ if (argv0 && i == 0) {
+ // Is there a request to suppress default binary launcher?
+ envVar += argv0;
+ } else {
+ envVar += argv[i];
+ }
+
+ // PR_SetEnv() wants the string to be available for the lifetime
+ // of the app, so dup it here. This conversion is not lossy.
+ env = ToNewCString(envVar, mozilla::fallible);
+ if (!env) return NS_ERROR_OUT_OF_MEMORY;
+
+ PR_SetEnv(env);
+ }
+
+ // make sure the arg list is terminated
+ envVar = "MOZ_CRASHREPORTER_RESTART_ARG_";
+ envVar.AppendInt(i);
+ envVar += "=";
+
+ // PR_SetEnv() wants the string to be available for the lifetime
+ // of the app, so dup it here. This conversion is not lossy.
+ env = ToNewCString(envVar, mozilla::fallible);
+ if (!env) return NS_ERROR_OUT_OF_MEMORY;
+
+ PR_SetEnv(env);
+
+ // make sure we save the info in XUL_APP_FILE for the reporter
+ const char* appfile = PR_GetEnv("XUL_APP_FILE");
+ if (appfile && *appfile) {
+ envVar = "MOZ_CRASHREPORTER_RESTART_XUL_APP_FILE=";
+ envVar += appfile;
+
+ // PR_SetEnv() wants the string to be available for the lifetime
+ // of the app, so dup it here. This conversion is not lossy.
+ env = ToNewCString(envVar);
+ PR_SetEnv(env);
+ }
+
+ return NS_OK;
+}
+
+#ifdef XP_WIN
+nsresult WriteMinidumpForException(EXCEPTION_POINTERS* aExceptionInfo) {
+ if (!gExceptionHandler) return NS_ERROR_NOT_INITIALIZED;
+
+ return gExceptionHandler->WriteMinidumpForException(aExceptionInfo)
+ ? NS_OK
+ : NS_ERROR_FAILURE;
+}
+#endif
+
+#ifdef XP_LINUX
+bool WriteMinidumpForSigInfo(int signo, siginfo_t* info, void* uc) {
+ if (!gExceptionHandler) {
+ // Crash reporting is disabled.
+ return false;
+ }
+ return gExceptionHandler->HandleSignal(signo, info, uc);
+}
+#endif
+
+#ifdef XP_MACOSX
+nsresult AppendObjCExceptionInfoToAppNotes(void* inException) {
+ nsAutoCString excString;
+ GetObjCExceptionInfo(inException, excString);
+ AppendAppNotesToCrashReport(excString);
+ return NS_OK;
+}
+#endif
+
+/*
+ * Combined code to get/set the crash reporter submission pref on
+ * different platforms.
+ */
+static nsresult PrefSubmitReports(bool* aSubmitReports, bool writePref) {
+ nsresult rv;
+#if defined(XP_WIN)
+ /*
+ * NOTE! This needs to stay in sync with the preference checking code
+ * in toolkit/crashreporter/client/crashreporter_win.cpp
+ */
+ nsCOMPtr<nsIXULAppInfo> appinfo =
+ do_GetService("@mozilla.org/xre/app-info;1", &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsAutoCString appVendor, appName;
+ rv = appinfo->GetVendor(appVendor);
+ NS_ENSURE_SUCCESS(rv, rv);
+ rv = appinfo->GetName(appName);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr<nsIWindowsRegKey> regKey(
+ do_CreateInstance("@mozilla.org/windows-registry-key;1", &rv));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsAutoCString regPath;
+
+ regPath.AppendLiteral("Software\\");
+
+ // We need to ensure the registry keys are created so we can properly
+ // write values to it
+
+ // Create appVendor key
+ if (!appVendor.IsEmpty()) {
+ regPath.Append(appVendor);
+ regKey->Create(nsIWindowsRegKey::ROOT_KEY_CURRENT_USER,
+ NS_ConvertUTF8toUTF16(regPath),
+ nsIWindowsRegKey::ACCESS_SET_VALUE);
+ regPath.Append('\\');
+ }
+
+ // Create appName key
+ regPath.Append(appName);
+ regKey->Create(nsIWindowsRegKey::ROOT_KEY_CURRENT_USER,
+ NS_ConvertUTF8toUTF16(regPath),
+ nsIWindowsRegKey::ACCESS_SET_VALUE);
+ regPath.Append('\\');
+
+ // Create Crash Reporter key
+ regPath.AppendLiteral("Crash Reporter");
+ regKey->Create(nsIWindowsRegKey::ROOT_KEY_CURRENT_USER,
+ NS_ConvertUTF8toUTF16(regPath),
+ nsIWindowsRegKey::ACCESS_SET_VALUE);
+
+ // If we're saving the pref value, just write it to ROOT_KEY_CURRENT_USER
+ // and we're done.
+ if (writePref) {
+ rv = regKey->Open(nsIWindowsRegKey::ROOT_KEY_CURRENT_USER,
+ NS_ConvertUTF8toUTF16(regPath),
+ nsIWindowsRegKey::ACCESS_SET_VALUE);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ uint32_t value = *aSubmitReports ? 1 : 0;
+ rv = regKey->WriteIntValue(u"SubmitCrashReport"_ns, value);
+ regKey->Close();
+ return rv;
+ }
+
+ // We're reading the pref value, so we need to first look under
+ // ROOT_KEY_LOCAL_MACHINE to see if it's set there, and then fall back to
+ // ROOT_KEY_CURRENT_USER. If it's not set in either place, the pref defaults
+ // to "true".
+ uint32_t value;
+ rv = regKey->Open(nsIWindowsRegKey::ROOT_KEY_LOCAL_MACHINE,
+ NS_ConvertUTF8toUTF16(regPath),
+ nsIWindowsRegKey::ACCESS_QUERY_VALUE);
+ if (NS_SUCCEEDED(rv)) {
+ rv = regKey->ReadIntValue(u"SubmitCrashReport"_ns, &value);
+ regKey->Close();
+ if (NS_SUCCEEDED(rv)) {
+ *aSubmitReports = !!value;
+ return NS_OK;
+ }
+ }
+
+ rv = regKey->Open(nsIWindowsRegKey::ROOT_KEY_CURRENT_USER,
+ NS_ConvertUTF8toUTF16(regPath),
+ nsIWindowsRegKey::ACCESS_QUERY_VALUE);
+ if (NS_FAILED(rv)) {
+ *aSubmitReports = true;
+ return NS_OK;
+ }
+
+ rv = regKey->ReadIntValue(u"SubmitCrashReport"_ns, &value);
+ // default to true on failure
+ if (NS_FAILED(rv)) {
+ value = 1;
+ rv = NS_OK;
+ }
+ regKey->Close();
+
+ *aSubmitReports = !!value;
+ return NS_OK;
+#elif defined(XP_MACOSX)
+ rv = NS_OK;
+ if (writePref) {
+ CFPropertyListRef cfValue =
+ (CFPropertyListRef)(*aSubmitReports ? kCFBooleanTrue : kCFBooleanFalse);
+ ::CFPreferencesSetAppValue(CFSTR("submitReport"), cfValue,
+ reporterClientAppID);
+ if (!::CFPreferencesAppSynchronize(reporterClientAppID))
+ rv = NS_ERROR_FAILURE;
+ } else {
+ *aSubmitReports = true;
+ Boolean keyExistsAndHasValidFormat = false;
+ Boolean prefValue = ::CFPreferencesGetAppBooleanValue(
+ CFSTR("submitReport"), reporterClientAppID,
+ &keyExistsAndHasValidFormat);
+ if (keyExistsAndHasValidFormat) *aSubmitReports = !!prefValue;
+ }
+ return rv;
+#elif defined(XP_UNIX)
+ /*
+ * NOTE! This needs to stay in sync with the preference checking code
+ * in toolkit/crashreporter/client/crashreporter_linux.cpp
+ */
+ nsCOMPtr<nsIFile> reporterINI;
+ rv = NS_GetSpecialDirectory("UAppData", getter_AddRefs(reporterINI));
+ NS_ENSURE_SUCCESS(rv, rv);
+ reporterINI->AppendNative("Crash Reports"_ns);
+ reporterINI->AppendNative("crashreporter.ini"_ns);
+
+ bool exists;
+ rv = reporterINI->Exists(&exists);
+ NS_ENSURE_SUCCESS(rv, rv);
+ if (!exists) {
+ if (!writePref) {
+ // If reading the pref, default to true if .ini doesn't exist.
+ *aSubmitReports = true;
+ return NS_OK;
+ }
+ // Create the file so the INI processor can write to it.
+ rv = reporterINI->Create(nsIFile::NORMAL_FILE_TYPE, 0600);
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+
+ nsCOMPtr<nsIINIParserFactory> iniFactory =
+ do_GetService("@mozilla.org/xpcom/ini-parser-factory;1", &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr<nsIINIParser> iniParser;
+ rv = iniFactory->CreateINIParser(reporterINI, getter_AddRefs(iniParser));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ // If we're writing the pref, just set and we're done.
+ if (writePref) {
+ nsCOMPtr<nsIINIParserWriter> iniWriter = do_QueryInterface(iniParser);
+ NS_ENSURE_TRUE(iniWriter, NS_ERROR_FAILURE);
+
+ rv = iniWriter->SetString("Crash Reporter"_ns, "SubmitReport"_ns,
+ *aSubmitReports ? "1"_ns : "0"_ns);
+ NS_ENSURE_SUCCESS(rv, rv);
+ rv = iniWriter->WriteFile(reporterINI);
+ return rv;
+ }
+
+ nsAutoCString submitReportValue;
+ rv = iniParser->GetString("Crash Reporter"_ns, "SubmitReport"_ns,
+ submitReportValue);
+
+ // Default to "true" if the pref can't be found.
+ if (NS_FAILED(rv))
+ *aSubmitReports = true;
+ else if (submitReportValue.EqualsASCII("0"))
+ *aSubmitReports = false;
+ else
+ *aSubmitReports = true;
+
+ return NS_OK;
+#else
+ return NS_ERROR_NOT_IMPLEMENTED;
+#endif
+}
+
+nsresult GetSubmitReports(bool* aSubmitReports) {
+ return PrefSubmitReports(aSubmitReports, false);
+}
+
+nsresult SetSubmitReports(bool aSubmitReports) {
+ nsresult rv;
+
+ nsCOMPtr<nsIObserverService> obsServ =
+ mozilla::services::GetObserverService();
+ if (!obsServ) {
+ return NS_ERROR_FAILURE;
+ }
+
+ rv = PrefSubmitReports(&aSubmitReports, true);
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+
+ obsServ->NotifyObservers(nullptr, "submit-reports-pref-changed", nullptr);
+ return NS_OK;
+}
+
+static void SetCrashEventsDir(nsIFile* aDir) {
+ static const XP_CHAR eventsDirectoryEnv[] =
+ XP_TEXT("MOZ_CRASHREPORTER_EVENTS_DIRECTORY");
+
+ nsCOMPtr<nsIFile> eventsDir = aDir;
+
+ const char* env = PR_GetEnv("CRASHES_EVENTS_DIR");
+ if (env && *env) {
+ NS_NewNativeLocalFile(nsDependentCString(env), false,
+ getter_AddRefs(eventsDir));
+ EnsureDirectoryExists(eventsDir);
+ }
+
+ xpstring* path = CreatePathFromFile(eventsDir);
+ if (!path) {
+ return; // There's no clean failure from this
+ }
+
+ eventsDirectory = xpstring(*path);
+#ifdef XP_WIN
+ SetEnvironmentVariableW(eventsDirectoryEnv, path->c_str());
+#else
+ setenv(eventsDirectoryEnv, path->c_str(), /* overwrite */ 1);
+#endif
+
+ delete path;
+}
+
+void SetProfileDirectory(nsIFile* aDir) {
+ nsCOMPtr<nsIFile> dir;
+ aDir->Clone(getter_AddRefs(dir));
+
+ dir->Append(u"crashes"_ns);
+ EnsureDirectoryExists(dir);
+ dir->Append(u"events"_ns);
+ EnsureDirectoryExists(dir);
+ SetCrashEventsDir(dir);
+}
+
+void SetUserAppDataDirectory(nsIFile* aDir) {
+ nsCOMPtr<nsIFile> dir;
+ aDir->Clone(getter_AddRefs(dir));
+
+ dir->Append(u"Crash Reports"_ns);
+ EnsureDirectoryExists(dir);
+ dir->Append(u"events"_ns);
+ EnsureDirectoryExists(dir);
+ SetCrashEventsDir(dir);
+}
+
+void UpdateCrashEventsDir() {
+ const char* env = PR_GetEnv("CRASHES_EVENTS_DIR");
+ if (env && *env) {
+ SetCrashEventsDir(nullptr);
+ }
+
+ nsCOMPtr<nsIFile> eventsDir;
+ nsresult rv = NS_GetSpecialDirectory("ProfD", getter_AddRefs(eventsDir));
+ if (NS_SUCCEEDED(rv)) {
+ SetProfileDirectory(eventsDir);
+ return;
+ }
+
+ rv = NS_GetSpecialDirectory("UAppData", getter_AddRefs(eventsDir));
+ if (NS_SUCCEEDED(rv)) {
+ SetUserAppDataDirectory(eventsDir);
+ return;
+ }
+
+ NS_WARNING(
+ "Couldn't get the user appdata directory. Crash events may not be "
+ "produced.");
+}
+
+bool GetCrashEventsDir(nsAString& aPath) {
+ if (eventsDirectory.empty()) {
+ return false;
+ }
+ aPath = CONVERT_XP_CHAR_TO_UTF16(eventsDirectory.c_str());
+ return true;
+}
+
+void SetMemoryReportFile(nsIFile* aFile) {
+ if (!gExceptionHandler) {
+ return;
+ }
+
+ PathString path;
+#ifdef XP_WIN
+ aFile->GetPath(path);
+#else
+ aFile->GetNativePath(path);
+#endif
+ memoryReportPath = xpstring(path.get());
+}
+
+nsresult GetDefaultMemoryReportFile(nsIFile** aFile) {
+ nsCOMPtr<nsIFile> defaultMemoryReportFile;
+ if (!defaultMemoryReportPath) {
+ nsresult rv = NS_GetSpecialDirectory(
+ NS_APP_PROFILE_DIR_STARTUP, getter_AddRefs(defaultMemoryReportFile));
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+ defaultMemoryReportFile->AppendNative("memory-report.json.gz"_ns);
+ defaultMemoryReportPath = CreatePathFromFile(defaultMemoryReportFile);
+ if (!defaultMemoryReportPath) {
+ return NS_ERROR_FAILURE;
+ }
+ } else {
+ CreateFileFromPath(*defaultMemoryReportPath,
+ getter_AddRefs(defaultMemoryReportFile));
+ if (!defaultMemoryReportFile) {
+ return NS_ERROR_FAILURE;
+ }
+ }
+ defaultMemoryReportFile.forget(aFile);
+ return NS_OK;
+}
+
+static void FindPendingDir() {
+ if (!pendingDirectory.empty()) {
+ return;
+ }
+ nsCOMPtr<nsIFile> pendingDir;
+ nsresult rv = NS_GetSpecialDirectory("UAppData", getter_AddRefs(pendingDir));
+ if (NS_FAILED(rv)) {
+ NS_WARNING(
+ "Couldn't get the user appdata directory, crash dumps will go in an "
+ "unusual location");
+ } else {
+ pendingDir->Append(u"Crash Reports"_ns);
+ pendingDir->Append(u"pending"_ns);
+
+ PathString path;
+#ifdef XP_WIN
+ pendingDir->GetPath(path);
+#else
+ pendingDir->GetNativePath(path);
+#endif
+ pendingDirectory = xpstring(path.get());
+ }
+}
+
+// The "pending" dir is Crash Reports/pending, from which minidumps
+// can be submitted. Because this method may be called off the main thread,
+// we store the pending directory as a path.
+static bool GetPendingDir(nsIFile** dir) {
+ // MOZ_ASSERT(OOPInitialized());
+ if (pendingDirectory.empty()) {
+ return false;
+ }
+
+ nsCOMPtr<nsIFile> pending = do_CreateInstance(NS_LOCAL_FILE_CONTRACTID);
+ if (!pending) {
+ NS_WARNING("Can't set up pending directory during shutdown.");
+ return false;
+ }
+#ifdef XP_WIN
+ pending->InitWithPath(nsDependentString(pendingDirectory.c_str()));
+#else
+ pending->InitWithNativePath(nsDependentCString(pendingDirectory.c_str()));
+#endif
+ pending.swap(*dir);
+ return true;
+}
+
+// The "limbo" dir is where minidumps go to wait for something else to
+// use them. If we're |ShouldReport()|, then the "something else" is
+// a minidump submitter, and they're coming from the
+// Crash Reports/pending/ dir. Otherwise, we don't know what the
+// "somthing else" is, but the minidumps stay in [profile]/minidumps/
+// limbo.
+static bool GetMinidumpLimboDir(nsIFile** dir) {
+ if (ShouldReport()) {
+ return GetPendingDir(dir);
+ } else {
+#ifndef XP_LINUX
+ CreateFileFromPath(gExceptionHandler->dump_path(), dir);
+#else
+ CreateFileFromPath(gExceptionHandler->minidump_descriptor().directory(),
+ dir);
+#endif
+ return nullptr != *dir;
+ }
+}
+
+void DeleteMinidumpFilesForID(const nsAString& aId,
+ const Maybe<nsString>& aAdditionalMinidump) {
+ nsCOMPtr<nsIFile> minidumpFile;
+ if (GetMinidumpForID(aId, getter_AddRefs(minidumpFile))) {
+ minidumpFile->Remove(false);
+ }
+
+ nsCOMPtr<nsIFile> extraFile;
+ if (GetExtraFileForID(aId, getter_AddRefs(extraFile))) {
+ extraFile->Remove(false);
+ }
+
+ if (aAdditionalMinidump && GetMinidumpForID(aId, getter_AddRefs(minidumpFile),
+ aAdditionalMinidump)) {
+ minidumpFile->Remove(false);
+ }
+}
+
+bool GetMinidumpForID(const nsAString& id, nsIFile** minidump,
+ const Maybe<nsString>& aAdditionalMinidump) {
+ if (!GetMinidumpLimboDir(minidump)) {
+ return false;
+ }
+
+ nsAutoString fileName(id);
+
+ if (aAdditionalMinidump) {
+ fileName.Append('-');
+ fileName.Append(*aAdditionalMinidump);
+ }
+
+ fileName.Append(u".dmp"_ns);
+ (*minidump)->Append(fileName);
+
+ bool exists;
+ if (NS_FAILED((*minidump)->Exists(&exists)) || !exists) {
+ return false;
+ }
+
+ return true;
+}
+
+bool GetIDFromMinidump(nsIFile* minidump, nsAString& id) {
+ if (minidump && NS_SUCCEEDED(minidump->GetLeafName(id))) {
+ id.ReplaceLiteral(id.Length() - 4, 4, u"");
+ return true;
+ }
+ return false;
+}
+
+bool GetExtraFileForID(const nsAString& id, nsIFile** extraFile) {
+ if (!GetMinidumpLimboDir(extraFile)) {
+ return false;
+ }
+
+ (*extraFile)->Append(id + u".extra"_ns);
+
+ bool exists;
+ if (NS_FAILED((*extraFile)->Exists(&exists)) || !exists) {
+ return false;
+ }
+
+ return true;
+}
+
+bool GetExtraFileForMinidump(nsIFile* minidump, nsIFile** extraFile) {
+ nsAutoString leafName;
+ nsresult rv = minidump->GetLeafName(leafName);
+ if (NS_FAILED(rv)) return false;
+
+ nsCOMPtr<nsIFile> extraF;
+ rv = minidump->Clone(getter_AddRefs(extraF));
+ if (NS_FAILED(rv)) return false;
+
+ leafName.Replace(leafName.Length() - 3, 3, u"extra"_ns);
+ rv = extraF->SetLeafName(leafName);
+ if (NS_FAILED(rv)) return false;
+
+ *extraFile = nullptr;
+ extraF.swap(*extraFile);
+ return true;
+}
+
+static void ReadAndValidateExceptionTimeAnnotations(
+ PRFileDesc* aFd, AnnotationTable& aAnnotations) {
+ PRInt32 res;
+ do {
+ uint32_t rawAnnotation;
+ res = PR_Read(aFd, &rawAnnotation, sizeof(rawAnnotation));
+ if ((res != sizeof(rawAnnotation)) ||
+ (rawAnnotation >= static_cast<uint32_t>(Annotation::Count))) {
+ return;
+ }
+
+ uint64_t len;
+ res = PR_Read(aFd, &len, sizeof(len));
+ if (res != sizeof(len) || (len == 0)) {
+ return;
+ }
+
+ char c;
+ nsAutoCString value;
+ do {
+ res = PR_Read(aFd, &c, 1);
+ if (res != 1) {
+ return;
+ }
+
+ len--;
+ value.Append(c);
+ } while (len > 0);
+
+ // Looks good, save the (annotation, value) pair
+ aAnnotations[static_cast<Annotation>(rawAnnotation)] = value;
+ } while (res > 0);
+}
+
+static bool WriteExtraFile(PlatformWriter& pw,
+ const AnnotationTable& aAnnotations) {
+ if (!pw.Valid()) {
+ return false;
+ }
+
+ JSONAnnotationWriter writer(pw);
+ WriteAnnotations(writer, aAnnotations);
+ WriteSynthesizedAnnotations(writer);
+
+ return true;
+}
+
+bool WriteExtraFile(const nsAString& id, const AnnotationTable& annotations) {
+ nsCOMPtr<nsIFile> extra;
+ if (!GetMinidumpLimboDir(getter_AddRefs(extra))) {
+ return false;
+ }
+
+ extra->Append(id + u".extra"_ns);
+ PathString path;
+#ifdef XP_WIN
+ NS_ENSURE_SUCCESS(extra->GetPath(path), false);
+#elif defined(XP_UNIX)
+ NS_ENSURE_SUCCESS(extra->GetNativePath(path), false);
+#endif
+
+ PlatformWriter pw(path.get());
+ return WriteExtraFile(pw, annotations);
+}
+
+static void ReadExceptionTimeAnnotations(AnnotationTable& aAnnotations,
+ ProcessId aPid) {
+ // Read exception-time annotations
+ StaticMutexAutoLock pidMapLock(processMapLock);
+ if (aPid && processToCrashFd.count(aPid)) {
+ PRFileDesc* prFd = processToCrashFd[aPid];
+ processToCrashFd.erase(aPid);
+ ReadAndValidateExceptionTimeAnnotations(prFd, aAnnotations);
+ PR_Close(prFd);
+ }
+}
+
+static void PopulateContentProcessAnnotations(AnnotationTable& aAnnotations) {
+ MergeContentCrashAnnotations(aAnnotations);
+ AddCommonAnnotations(aAnnotations);
+}
+
+// It really only makes sense to call this function when
+// ShouldReport() is true.
+// Uses dumpFile's filename to generate memoryReport's filename (same name with
+// a different extension)
+static bool MoveToPending(nsIFile* dumpFile, nsIFile* extraFile,
+ nsIFile* memoryReport) {
+ nsCOMPtr<nsIFile> pendingDir;
+ if (!GetPendingDir(getter_AddRefs(pendingDir))) return false;
+
+ if (NS_FAILED(dumpFile->MoveTo(pendingDir, u""_ns))) {
+ return false;
+ }
+
+ if (extraFile && NS_FAILED(extraFile->MoveTo(pendingDir, u""_ns))) {
+ return false;
+ }
+
+ if (memoryReport) {
+ nsAutoString leafName;
+ nsresult rv = dumpFile->GetLeafName(leafName);
+ if (NS_FAILED(rv)) {
+ return false;
+ }
+ // Generate the correct memory report filename from the dumpFile's name
+ leafName.Replace(
+ leafName.Length() - 4, 4,
+ static_cast<nsString>(CONVERT_XP_CHAR_TO_UTF16(memoryReportExtension)));
+ if (NS_FAILED(memoryReport->MoveTo(pendingDir, leafName))) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+static void MaybeAnnotateDumperError(const ClientInfo& aClientInfo,
+ AnnotationTable& aAnnotations) {
+#if defined(MOZ_OXIDIZED_BREAKPAD)
+ if (aClientInfo.had_error()) {
+ aAnnotations[Annotation::DumperError] = *aClientInfo.error_msg();
+ }
+#endif
+}
+
+static void OnChildProcessDumpRequested(
+ void* aContext, const ClientInfo& aClientInfo,
+ const xpstring& aFilePath) MOZ_NO_THREAD_SAFETY_ANALYSIS {
+ nsCOMPtr<nsIFile> minidump;
+
+ // Hold the mutex until the current dump request is complete, to
+ // prevent UnsetExceptionHandler() from pulling the rug out from
+ // under us.
+ MutexAutoLock lock(*dumpSafetyLock);
+ if (!isSafeToDump) return;
+
+ CreateFileFromPath(aFilePath, getter_AddRefs(minidump));
+
+ ProcessId pid = aClientInfo.pid();
+ if (ShouldReport()) {
+ nsCOMPtr<nsIFile> memoryReport;
+ if (!memoryReportPath.empty()) {
+ CreateFileFromPath(memoryReportPath, getter_AddRefs(memoryReport));
+ MOZ_ASSERT(memoryReport);
+ }
+ MoveToPending(minidump, nullptr, memoryReport);
+ }
+
+ {
+#ifdef MOZ_CRASHREPORTER_INJECTOR
+ bool runCallback;
+#endif
+ {
+ dumpMapLock->Lock();
+ ChildProcessData* pd = pidToMinidump->PutEntry(pid);
+ MOZ_ASSERT(!pd->minidump);
+ pd->minidump = minidump;
+ pd->sequence = ++crashSequence;
+ pd->annotations = MakeUnique<AnnotationTable>();
+ PopulateContentProcessAnnotations(*(pd->annotations));
+ MaybeAnnotateDumperError(aClientInfo, *(pd->annotations));
+
+#ifdef MOZ_CRASHREPORTER_INJECTOR
+ runCallback = nullptr != pd->callback;
+#endif
+ }
+#ifdef MOZ_CRASHREPORTER_INJECTOR
+ if (runCallback) NS_DispatchToMainThread(new ReportInjectedCrash(pid));
+#endif
+ }
+}
+
+static void OnChildProcessDumpWritten(void* aContext,
+ const ClientInfo& aClientInfo)
+ MOZ_NO_THREAD_SAFETY_ANALYSIS {
+ ProcessId pid = aClientInfo.pid();
+ ChildProcessData* pd = pidToMinidump->GetEntry(pid);
+ MOZ_ASSERT(pd);
+ if (!pd->minidumpOnly) {
+ ReadExceptionTimeAnnotations(*(pd->annotations), pid);
+ }
+ dumpMapLock->Unlock();
+}
+
+static bool OOPInitialized() { return pidToMinidump != nullptr; }
+
+void OOPInit() {
+ class ProxyToMainThread : public Runnable {
+ public:
+ ProxyToMainThread() : Runnable("nsExceptionHandler::ProxyToMainThread") {}
+ NS_IMETHOD Run() override {
+ OOPInit();
+ return NS_OK;
+ }
+ };
+ if (!NS_IsMainThread()) {
+ // This logic needs to run on the main thread
+ nsCOMPtr<nsIThread> mainThread = do_GetMainThread();
+ mozilla::SyncRunnable::DispatchToThread(mainThread,
+ new ProxyToMainThread());
+ return;
+ }
+
+ if (OOPInitialized()) return;
+
+ MOZ_ASSERT(NS_IsMainThread());
+
+ MOZ_ASSERT(gExceptionHandler != nullptr,
+ "attempt to initialize OOP crash reporter before in-process "
+ "crashreporter!");
+
+#if defined(XP_WIN)
+ childCrashNotifyPipe =
+ mozilla::Smprintf("\\\\.\\pipe\\gecko-crash-server-pipe.%i",
+ static_cast<int>(::GetCurrentProcessId()))
+ .release();
+
+ const std::wstring dumpPath = gExceptionHandler->dump_path();
+ crashServer = new CrashGenerationServer(
+ std::wstring(NS_ConvertASCIItoUTF16(childCrashNotifyPipe).get()),
+ nullptr, // default security attributes
+ nullptr, nullptr, // we don't care about process connect here
+ OnChildProcessDumpRequested, nullptr, OnChildProcessDumpWritten, nullptr,
+ nullptr, // we don't care about process exit here
+ nullptr, nullptr, // we don't care about upload request here
+ true, // automatically generate dumps
+ &dumpPath);
+
+ if (sIncludeContextHeap) {
+ crashServer->set_include_context_heap(sIncludeContextHeap);
+ }
+
+#elif defined(XP_LINUX)
+ if (!CrashGenerationServer::CreateReportChannel(&serverSocketFd,
+ &clientSocketFd))
+ MOZ_CRASH("can't create crash reporter socketpair()");
+
+ const std::string dumpPath =
+ gExceptionHandler->minidump_descriptor().directory();
+ crashServer = new CrashGenerationServer(
+ serverSocketFd, OnChildProcessDumpRequested, nullptr,
+ OnChildProcessDumpWritten, nullptr, true, &dumpPath);
+
+#elif defined(XP_MACOSX)
+ childCrashNotifyPipe = mozilla::Smprintf("gecko-crash-server-pipe.%i",
+ static_cast<int>(getpid()))
+ .release();
+ const std::string dumpPath = gExceptionHandler->dump_path();
+
+ crashServer = new CrashGenerationServer(
+ childCrashNotifyPipe, nullptr, nullptr, OnChildProcessDumpRequested,
+ nullptr, OnChildProcessDumpWritten, nullptr,
+ true, // automatically generate dumps
+ dumpPath);
+#endif
+
+ if (!crashServer->Start()) MOZ_CRASH("can't start crash reporter server()");
+
+ pidToMinidump = new ChildMinidumpMap();
+
+ dumpMapLock = new Mutex("CrashReporter::dumpMapLock");
+
+ FindPendingDir();
+ UpdateCrashEventsDir();
+}
+
+static void OOPDeinit() {
+ if (!OOPInitialized()) {
+ NS_WARNING("OOPDeinit() without successful OOPInit()");
+ return;
+ }
+
+#ifdef MOZ_CRASHREPORTER_INJECTOR
+ if (sInjectorThread) {
+ sInjectorThread->Shutdown();
+ NS_RELEASE(sInjectorThread);
+ }
+#endif
+
+ delete crashServer;
+ crashServer = nullptr;
+
+ delete dumpMapLock;
+ dumpMapLock = nullptr;
+
+ delete pidToMinidump;
+ pidToMinidump = nullptr;
+
+#if defined(XP_WIN) || defined(XP_MACOSX)
+ free(childCrashNotifyPipe);
+ childCrashNotifyPipe = nullptr;
+#endif
+}
+
+#if defined(XP_WIN) || defined(XP_MACOSX)
+// Parent-side API for children
+const char* GetChildNotificationPipe() {
+ if (!GetEnabled()) return kNullNotifyPipe;
+
+ MOZ_ASSERT(OOPInitialized());
+
+ return childCrashNotifyPipe;
+}
+#endif
+
+#ifdef MOZ_CRASHREPORTER_INJECTOR
+void InjectCrashReporterIntoProcess(DWORD processID,
+ InjectorCrashCallback* cb) {
+ if (!GetEnabled()) return;
+
+ if (!OOPInitialized()) OOPInit();
+
+ if (!sInjectorThread) {
+ if (NS_FAILED(NS_NewNamedThread("CrashRep Inject", &sInjectorThread)))
+ return;
+ }
+
+ {
+ MutexAutoLock lock(*dumpMapLock);
+ ChildProcessData* pd = pidToMinidump->PutEntry(processID);
+ MOZ_ASSERT(!pd->minidump && !pd->callback);
+ pd->callback = cb;
+ pd->minidumpOnly = true;
+ }
+
+ nsCOMPtr<nsIRunnable> r = new InjectCrashRunnable(processID);
+ sInjectorThread->Dispatch(r, nsIEventTarget::DISPATCH_NORMAL);
+}
+
+NS_IMETHODIMP
+ReportInjectedCrash::Run() {
+ // Crash reporting may have been disabled after this method was dispatched
+ if (!OOPInitialized()) return NS_OK;
+
+ InjectorCrashCallback* cb;
+ {
+ MutexAutoLock lock(*dumpMapLock);
+ ChildProcessData* pd = pidToMinidump->GetEntry(mPID);
+ if (!pd || !pd->callback) return NS_OK;
+
+ MOZ_ASSERT(pd->minidump);
+
+ cb = pd->callback;
+ }
+
+ cb->OnCrash(mPID);
+ return NS_OK;
+}
+
+void UnregisterInjectorCallback(DWORD processID) {
+ if (!OOPInitialized()) return;
+
+ MutexAutoLock lock(*dumpMapLock);
+ pidToMinidump->RemoveEntry(processID);
+}
+
+#endif // MOZ_CRASHREPORTER_INJECTOR
+
+void RegisterChildCrashAnnotationFileDescriptor(ProcessId aProcess,
+ PRFileDesc* aFd) {
+ StaticMutexAutoLock pidMapLock(processMapLock);
+ processToCrashFd[aProcess] = aFd;
+}
+
+void DeregisterChildCrashAnnotationFileDescriptor(ProcessId aProcess) {
+ StaticMutexAutoLock pidMapLock(processMapLock);
+ auto it = processToCrashFd.find(aProcess);
+ if (it != processToCrashFd.end()) {
+ PR_Close(it->second);
+ processToCrashFd.erase(it);
+ }
+}
+
+#if defined(XP_LINUX)
+
+// Parent-side API for children
+bool CreateNotificationPipeForChild(int* childCrashFd, int* childCrashRemapFd) {
+ if (!GetEnabled()) {
+ *childCrashFd = -1;
+ *childCrashRemapFd = -1;
+ return true;
+ }
+
+ MOZ_ASSERT(OOPInitialized());
+
+ *childCrashFd = clientSocketFd;
+ *childCrashRemapFd = gMagicChildCrashReportFd;
+
+ return true;
+}
+
+#endif // defined(XP_LINUX)
+
+bool SetRemoteExceptionHandler(const char* aCrashPipe,
+ FileHandle aCrashTimeAnnotationFile) {
+ MOZ_ASSERT(!gExceptionHandler, "crash client already init'd");
+ RegisterRuntimeExceptionModule();
+ InitializeAnnotationFacilities();
+
+#if defined(XP_WIN)
+ gChildCrashAnnotationReportFd = aCrashTimeAnnotationFile;
+ gExceptionHandler = new google_breakpad::ExceptionHandler(
+ L"", ChildFilter, ChildMinidumpCallback,
+ nullptr, // no callback context
+ google_breakpad::ExceptionHandler::HANDLER_ALL, GetMinidumpType(),
+ NS_ConvertASCIItoUTF16(aCrashPipe).get(), nullptr);
+ gExceptionHandler->set_handle_debug_exceptions(true);
+
+# if defined(HAVE_64BIT_BUILD)
+ SetJitExceptionHandler();
+# endif
+#elif defined(XP_LINUX)
+ // MinidumpDescriptor requires a non-empty path.
+ google_breakpad::MinidumpDescriptor path(".");
+
+ gExceptionHandler = new google_breakpad::ExceptionHandler(
+ path, ChildFilter, ChildMinidumpCallback,
+ nullptr, // no callback context
+ true, // install signal handlers
+ gMagicChildCrashReportFd);
+#elif defined(XP_MACOSX)
+ gExceptionHandler = new google_breakpad::ExceptionHandler(
+ "", ChildFilter, ChildMinidumpCallback,
+ nullptr, // no callback context
+ true, // install signal handlers
+ aCrashPipe);
+#endif
+
+ RecordMainThreadId();
+
+ oldTerminateHandler = std::set_terminate(&TerminateHandler);
+
+ // we either do remote or nothing, no fallback to regular crash reporting
+ return gExceptionHandler->IsOutOfProcess();
+}
+
+void GetAnnotation(uint32_t childPid, Annotation annotation,
+ nsACString& outStr) {
+ if (!GetEnabled()) {
+ return;
+ }
+
+ MutexAutoLock lock(*dumpMapLock);
+
+ ChildProcessData* pd = pidToMinidump->GetEntry(childPid);
+ if (!pd) {
+ return;
+ }
+
+ outStr = (*pd->annotations)[annotation];
+}
+
+bool TakeMinidumpForChild(uint32_t childPid, nsIFile** dump,
+ AnnotationTable& aAnnotations, uint32_t* aSequence) {
+ if (!GetEnabled()) return false;
+
+ MutexAutoLock lock(*dumpMapLock);
+
+ ChildProcessData* pd = pidToMinidump->GetEntry(childPid);
+ if (!pd) return false;
+
+ NS_IF_ADDREF(*dump = pd->minidump);
+ // Only plugin process minidumps taken using the injector don't have
+ // annotations.
+ if (!pd->minidumpOnly) {
+ aAnnotations = *(pd->annotations);
+ }
+ if (aSequence) {
+ *aSequence = pd->sequence;
+ }
+
+ pidToMinidump->RemoveEntry(pd);
+
+ return !!*dump;
+}
+
+bool FinalizeOrphanedMinidump(uint32_t aChildPid, GeckoProcessType aType,
+ nsString* aDumpId) {
+ AnnotationTable annotations;
+ nsCOMPtr<nsIFile> minidump;
+
+ if (!TakeMinidumpForChild(aChildPid, getter_AddRefs(minidump), annotations)) {
+ return false;
+ }
+
+ nsAutoString id;
+ if (!GetIDFromMinidump(minidump, id)) {
+ return false;
+ }
+
+ if (aDumpId) {
+ *aDumpId = id;
+ }
+
+ annotations[Annotation::ProcessType] =
+ XRE_ChildProcessTypeToAnnotation(aType);
+
+ return WriteExtraFile(id, annotations);
+}
+
+#ifdef XP_WIN
+
+// Function invoked by the WER runtime exception handler running in an
+// external process. This function isn't used anywhere inside Gecko directly
+// but rather invoked via CreateRemoteThread() in the main process.
+DWORD WINAPI WerNotifyProc(LPVOID aParameter) {
+ const WindowsErrorReportingData* werData =
+ static_cast<const WindowsErrorReportingData*>(aParameter);
+
+ // Hold the mutex until the current dump request is complete, to
+ // prevent UnsetExceptionHandler() from pulling the rug out from
+ // under us.
+ MutexAutoLock safetyLock(*dumpSafetyLock);
+ if (!isSafeToDump || !ShouldReport()) {
+ return S_OK;
+ }
+
+ ProcessId pid = werData->mChildPid;
+ nsCOMPtr<nsIFile> minidump;
+ if (!GetPendingDir(getter_AddRefs(minidump))) {
+ return S_OK;
+ }
+ xpstring minidump_native_name(werData->mMinidumpFile,
+ werData->mMinidumpFile + 40);
+ nsString minidump_name(minidump_native_name.c_str());
+ minidump->Append(minidump_name);
+
+ {
+ MutexAutoLock lock(*dumpMapLock);
+ ChildProcessData* pd = pidToMinidump->PutEntry(pid);
+ MOZ_ASSERT(!pd->minidump);
+ pd->minidump = minidump;
+ pd->sequence = ++crashSequence;
+ pd->annotations = MakeUnique<AnnotationTable>();
+ (*pd->annotations)[Annotation::WindowsErrorReporting] = "1"_ns;
+ if (werData->mOOMAllocationSize > 0) {
+ char buffer[32] = {};
+ XP_STOA(werData->mOOMAllocationSize, buffer);
+ (*pd->annotations)[Annotation::OOMAllocationSize] = buffer;
+ }
+
+ PopulateContentProcessAnnotations(*(pd->annotations));
+ }
+
+ return S_OK;
+}
+
+#endif // XP_WIN
+
+//-----------------------------------------------------------------------------
+// CreateMinidumpsAndPair() and helpers
+//
+
+/*
+ * Renames the stand alone dump file aDumpFile to:
+ * |aOwnerDumpFile-aDumpFileProcessType.dmp|
+ * and moves it into the same directory as aOwnerDumpFile. Does not
+ * modify aOwnerDumpFile in any way.
+ *
+ * @param aDumpFile - the dump file to associate with aOwnerDumpFile.
+ * @param aOwnerDumpFile - the new owner of aDumpFile.
+ * @param aDumpFileProcessType - process name associated with aDumpFile.
+ */
+static void RenameAdditionalHangMinidump(nsIFile* minidump,
+ nsIFile* childMinidump,
+ const nsACString& name) {
+ nsCOMPtr<nsIFile> directory;
+ childMinidump->GetParent(getter_AddRefs(directory));
+ if (!directory) return;
+
+ nsAutoCString leafName;
+ childMinidump->GetNativeLeafName(leafName);
+
+ // turn "<id>.dmp" into "<id>-<name>.dmp
+ leafName.Insert("-"_ns + name, leafName.Length() - 4);
+
+ if (NS_FAILED(minidump->MoveToNative(directory, leafName))) {
+ NS_WARNING("RenameAdditionalHangMinidump failed to move minidump.");
+ }
+}
+
+// Stores the minidump in the nsIFile pointed by the |context| parameter.
+static bool PairedDumpCallback(
+#ifdef XP_LINUX
+ const MinidumpDescriptor& descriptor,
+#else
+ const XP_CHAR* dump_path, const XP_CHAR* minidump_id,
+#endif
+ void* context,
+#ifdef XP_WIN
+ EXCEPTION_POINTERS* /*unused*/, MDRawAssertionInfo* /*unused*/,
+#endif
+ const phc::AddrInfo* addrInfo, bool succeeded) {
+ XP_CHAR* path = static_cast<XP_CHAR*>(context);
+ size_t size = XP_PATH_MAX;
+
+#ifdef XP_LINUX
+ Concat(path, descriptor.path(), &size);
+#else
+ path = Concat(path, dump_path, &size);
+ path = Concat(path, XP_PATH_SEPARATOR, &size);
+ path = Concat(path, minidump_id, &size);
+ Concat(path, dumpFileExtension, &size);
+#endif
+
+ return true;
+}
+
+ThreadId CurrentThreadId() {
+#if defined(XP_WIN)
+ return ::GetCurrentThreadId();
+#elif defined(XP_LINUX)
+ return sys_gettid();
+#elif defined(XP_MACOSX)
+ // Just return an index, since Mach ports can't be directly serialized
+ thread_act_port_array_t threads_for_task;
+ mach_msg_type_number_t thread_count;
+
+ if (task_threads(mach_task_self(), &threads_for_task, &thread_count))
+ return -1;
+
+ for (unsigned int i = 0; i < thread_count; ++i) {
+ if (threads_for_task[i] == mach_thread_self()) return i;
+ }
+ abort();
+#else
+# error "Unsupported platform"
+#endif
+}
+
+#ifdef XP_MACOSX
+static mach_port_t GetChildThread(ProcessHandle childPid,
+ ThreadId childBlamedThread) {
+ mach_port_t childThread = MACH_PORT_NULL;
+ thread_act_port_array_t threads_for_task;
+ mach_msg_type_number_t thread_count;
+
+ if (task_threads(childPid, &threads_for_task, &thread_count) ==
+ KERN_SUCCESS &&
+ childBlamedThread < thread_count) {
+ childThread = threads_for_task[childBlamedThread];
+ }
+
+ return childThread;
+}
+#endif
+
+bool CreateMinidumpsAndPair(ProcessHandle aTargetHandle,
+ ThreadId aTargetBlamedThread,
+ const nsACString& aIncomingPairName,
+ AnnotationTable& aTargetAnnotations,
+ nsIFile** aMainDumpOut) {
+ if (!GetEnabled()) {
+ return false;
+ }
+
+ AutoIOInterposerDisable disableIOInterposition;
+
+#ifdef XP_MACOSX
+ mach_port_t targetThread = GetChildThread(aTargetHandle, aTargetBlamedThread);
+#else
+ ThreadId targetThread = aTargetBlamedThread;
+#endif
+
+ xpstring dump_path;
+#ifndef XP_LINUX
+ dump_path = gExceptionHandler->dump_path();
+#else
+ dump_path = gExceptionHandler->minidump_descriptor().directory();
+#endif
+
+ // Ugly, but due to Breakpad limitations we can't allocate memory in the
+ // callback when generating a dump of the calling process.
+ XP_CHAR minidumpPath[XP_PATH_MAX] = {};
+
+ // dump the target
+ if (!google_breakpad::ExceptionHandler::WriteMinidumpForChild(
+ aTargetHandle, targetThread, dump_path, PairedDumpCallback,
+ static_cast<void*>(minidumpPath)
+#ifdef XP_WIN
+ ,
+ GetMinidumpType()
+#endif
+ )) {
+ return false;
+ }
+
+ nsCOMPtr<nsIFile> targetMinidump;
+ CreateFileFromPath(xpstring(minidumpPath), getter_AddRefs(targetMinidump));
+
+ // Create a dump of this process.
+ if (!google_breakpad::ExceptionHandler::WriteMinidump(
+ dump_path,
+#ifdef XP_MACOSX
+ true,
+#endif
+ PairedDumpCallback, static_cast<void*>(minidumpPath)
+#ifdef XP_WIN
+ ,
+ GetMinidumpType()
+#endif
+ )) {
+ targetMinidump->Remove(false);
+ return false;
+ }
+
+ nsCOMPtr<nsIFile> incomingDump;
+ CreateFileFromPath(xpstring(minidumpPath), getter_AddRefs(incomingDump));
+
+ RenameAdditionalHangMinidump(incomingDump, targetMinidump, aIncomingPairName);
+
+ if (ShouldReport()) {
+ MoveToPending(targetMinidump, nullptr, nullptr);
+ MoveToPending(incomingDump, nullptr, nullptr);
+ }
+#if defined(DEBUG) && defined(HAS_DLL_BLOCKLIST)
+ DllBlocklist_Shutdown();
+#endif
+
+ PopulateContentProcessAnnotations(aTargetAnnotations);
+ if (FlushContentProcessAnnotations(aTargetHandle)) {
+ ProcessId targetPid = base::GetProcId(aTargetHandle);
+ ReadExceptionTimeAnnotations(aTargetAnnotations, targetPid);
+ }
+
+ targetMinidump.forget(aMainDumpOut);
+
+ return true;
+}
+
+bool UnsetRemoteExceptionHandler(bool wasSet) {
+ // On Linux we don't unset breakpad's exception handler if the sandbox is
+ // enabled because it requires invoking `sigaltstack` and we don't want to
+ // allow that syscall in the sandbox. See bug 1622452.
+#if !defined(XP_LINUX) || !defined(MOZ_SANDBOX)
+ if (wasSet) {
+ std::set_terminate(oldTerminateHandler);
+ delete gExceptionHandler;
+ gExceptionHandler = nullptr;
+ }
+#endif
+ TeardownAnnotationFacilities();
+
+ return true;
+}
+
+#if defined(MOZ_WIDGET_ANDROID)
+void SetNotificationPipeForChild(int childCrashFd) {
+ gMagicChildCrashReportFd = childCrashFd;
+}
+
+void SetCrashAnnotationPipeForChild(int childCrashAnnotationFd) {
+ gChildCrashAnnotationReportFd = childCrashAnnotationFd;
+}
+#endif
+
+} // namespace CrashReporter
diff --git a/toolkit/crashreporter/nsExceptionHandler.h b/toolkit/crashreporter/nsExceptionHandler.h
new file mode 100644
index 0000000000..1212ae2e51
--- /dev/null
+++ b/toolkit/crashreporter/nsExceptionHandler.h
@@ -0,0 +1,342 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/. */
+
+// This header has two implementations, the real one in nsExceptionHandler.cpp
+// and a dummy in nsDummyExceptionHandler.cpp. The latter is used in builds
+// configured with --disable-crashreporter. If you add or remove a function
+// from this header you must update both implementations otherwise you'll break
+// builds that disable the crash reporter.
+
+#ifndef nsExceptionHandler_h__
+#define nsExceptionHandler_h__
+
+#include "mozilla/Assertions.h"
+#include "mozilla/EnumeratedArray.h"
+#include "mozilla/Maybe.h"
+
+#include "CrashAnnotations.h"
+
+#include <stddef.h>
+#include <stdint.h>
+#include "nsError.h"
+#include "nsString.h"
+#include "nsXULAppAPI.h"
+#include "prio.h"
+
+#if defined(XP_WIN)
+# ifdef WIN32_LEAN_AND_MEAN
+# undef WIN32_LEAN_AND_MEAN
+# endif
+# include <windows.h>
+#endif
+
+#if defined(XP_MACOSX)
+# include <mach/mach.h>
+#endif
+
+#if defined(XP_LINUX)
+# include <signal.h>
+#endif
+
+class nsIFile;
+
+namespace CrashReporter {
+
+using mozilla::Maybe;
+using mozilla::Nothing;
+
+/**
+ * Returns true if the crash reporter is using the dummy implementation.
+ */
+static inline bool IsDummy() {
+#ifdef MOZ_CRASHREPORTER
+ return false;
+#else
+ return true;
+#endif
+}
+
+nsresult SetExceptionHandler(nsIFile* aXREDirectory, bool force = false);
+nsresult UnsetExceptionHandler();
+
+/**
+ * Tell the crash reporter to recalculate where crash events files should go.
+ * SetCrashEventsDir is used before XPCOM is initialized from the startup
+ * code.
+ *
+ * UpdateCrashEventsDir uses the directory service to re-set the
+ * crash event directory based on the current profile.
+ *
+ * 1. If environment variable is present, use it. We don't expect
+ * the environment variable except for tests and other atypical setups.
+ * 2. <profile>/crashes/events
+ * 3. <UAppData>/Crash Reports/events
+ */
+void SetUserAppDataDirectory(nsIFile* aDir);
+void SetProfileDirectory(nsIFile* aDir);
+void UpdateCrashEventsDir();
+void SetMemoryReportFile(nsIFile* aFile);
+nsresult GetDefaultMemoryReportFile(nsIFile** aFile);
+
+/**
+ * Get the path where crash event files should be written.
+ */
+bool GetCrashEventsDir(nsAString& aPath);
+
+bool GetEnabled();
+bool GetServerURL(nsACString& aServerURL);
+nsresult SetServerURL(const nsACString& aServerURL);
+bool GetMinidumpPath(nsAString& aPath);
+nsresult SetMinidumpPath(const nsAString& aPath);
+
+// These functions are thread safe and can be called in both the parent and
+// child processes. Annotations added in the main process will be included in
+// child process crashes too unless the child process sets its own annotations.
+// If it does the child-provided annotation overrides the one set in the parent.
+nsresult AnnotateCrashReport(Annotation key, bool data);
+nsresult AnnotateCrashReport(Annotation key, int data);
+nsresult AnnotateCrashReport(Annotation key, unsigned int data);
+nsresult AnnotateCrashReport(Annotation key, const nsACString& data);
+nsresult AppendToCrashReportAnnotation(Annotation key, const nsACString& data);
+nsresult RemoveCrashReportAnnotation(Annotation key);
+nsresult AppendAppNotesToCrashReport(const nsACString& data);
+
+// RAII class for setting a crash annotation during a limited scope of time.
+// Will reset the named annotation to its previous value when destroyed.
+//
+// This type's behavior is identical to that of AnnotateCrashReport().
+class MOZ_RAII AutoAnnotateCrashReport final {
+ public:
+ AutoAnnotateCrashReport(Annotation key, bool data);
+ AutoAnnotateCrashReport(Annotation key, int data);
+ AutoAnnotateCrashReport(Annotation key, unsigned int data);
+ AutoAnnotateCrashReport(Annotation key, const nsACString& data);
+ ~AutoAnnotateCrashReport();
+
+#ifdef MOZ_CRASHREPORTER
+ private:
+ Annotation mKey;
+ nsCString mPrevious;
+#endif
+};
+
+void AnnotateOOMAllocationSize(size_t size);
+void AnnotateTexturesSize(size_t size);
+nsresult SetGarbageCollecting(bool collecting);
+void SetEventloopNestingLevel(uint32_t level);
+void SetMinidumpAnalysisAllThreads();
+void ClearInactiveStateStart();
+void SetInactiveStateStart();
+
+nsresult SetRestartArgs(int argc, char** argv);
+nsresult SetupExtraData(nsIFile* aAppDataDirectory, const nsACString& aBuildID);
+// Registers an additional memory region to be included in the minidump
+nsresult RegisterAppMemory(void* ptr, size_t length);
+nsresult UnregisterAppMemory(void* ptr);
+
+// Include heap regions of the crash context.
+void SetIncludeContextHeap(bool aValue);
+
+void GetAnnotation(uint32_t childPid, Annotation annotation,
+ nsACString& outStr);
+
+// Functions for working with minidumps and .extras
+typedef mozilla::EnumeratedArray<Annotation, Annotation::Count, nsCString>
+ AnnotationTable;
+void DeleteMinidumpFilesForID(
+ const nsAString& aId,
+ const Maybe<nsString>& aAdditionalMinidump = Nothing());
+bool GetMinidumpForID(const nsAString& id, nsIFile** minidump,
+ const Maybe<nsString>& aAdditionalMinidump = Nothing());
+bool GetIDFromMinidump(nsIFile* minidump, nsAString& id);
+bool GetExtraFileForID(const nsAString& id, nsIFile** extraFile);
+bool GetExtraFileForMinidump(nsIFile* minidump, nsIFile** extraFile);
+bool WriteExtraFile(const nsAString& id, const AnnotationTable& annotations);
+
+/**
+ * Copies the non-empty annotations in the source table to the destination
+ * overwriting the corresponding entries.
+ */
+void MergeCrashAnnotations(AnnotationTable& aDst, const AnnotationTable& aSrc);
+
+#ifdef XP_WIN
+nsresult WriteMinidumpForException(EXCEPTION_POINTERS* aExceptionInfo);
+#endif
+#ifdef XP_LINUX
+bool WriteMinidumpForSigInfo(int signo, siginfo_t* info, void* uc);
+#endif
+#ifdef XP_MACOSX
+nsresult AppendObjCExceptionInfoToAppNotes(void* inException);
+#endif
+nsresult GetSubmitReports(bool* aSubmitReport);
+nsresult SetSubmitReports(bool aSubmitReport);
+
+// Out-of-process crash reporter API.
+
+#ifdef XP_WIN
+// This data is stored in the parent process, there is one copy for each child
+// process. The mChildPid and mMinidumpFile fields are filled by the WER runtime
+// exception module when the associated child process crashes.
+struct WindowsErrorReportingData {
+ // Points to the WerNotifyProc function.
+ LPTHREAD_START_ROUTINE mWerNotifyProc;
+ // PID of the child process that crashed.
+ DWORD mChildPid;
+ // Filename of the generated minidump; this is not a 0-terminated string
+ char mMinidumpFile[40];
+ // OOM allocation size for the crash (ignore if zero)
+ size_t mOOMAllocationSize;
+};
+#endif // XP_WIN
+
+// Initializes out-of-process crash reporting. This method must be called
+// before the platform-specific notification pipe APIs are called. If called
+// from off the main thread, this method will synchronously proxy to the main
+// thread.
+void OOPInit();
+
+// Return true if a dump was found for |childPid|, and return the
+// path in |dump|. The caller owns the last reference to |dump| if it
+// is non-nullptr. The annotations for the crash will be stored in
+// |aAnnotations|. The sequence parameter will be filled with an ordinal
+// indicating which remote process crashed first.
+bool TakeMinidumpForChild(uint32_t childPid, nsIFile** dump,
+ AnnotationTable& aAnnotations,
+ uint32_t* aSequence = nullptr);
+
+/**
+ * If a dump was found for |childPid| then write a minimal .extra file to
+ * complete it and remove it from the list of pending crash dumps. It's
+ * required to call this method after a non-main process crash if the crash
+ * report could not be finalized via the CrashReporterHost (for example because
+ * it wasn't instanced yet).
+ *
+ * @param aChildPid The pid of the crashed child process
+ * @param aType The type of the crashed process
+ * @param aDumpId A string that will be filled with the dump ID
+ */
+[[nodiscard]] bool FinalizeOrphanedMinidump(uint32_t aChildPid,
+ GeckoProcessType aType,
+ nsString* aDumpId = nullptr);
+
+#if defined(XP_WIN)
+typedef HANDLE ProcessHandle;
+typedef DWORD ProcessId;
+typedef DWORD ThreadId;
+typedef HANDLE FileHandle;
+const FileHandle kInvalidFileHandle = INVALID_HANDLE_VALUE;
+#elif defined(XP_MACOSX)
+typedef task_t ProcessHandle;
+typedef pid_t ProcessId;
+typedef mach_port_t ThreadId;
+typedef int FileHandle;
+const FileHandle kInvalidFileHandle = -1;
+#else
+typedef int ProcessHandle;
+typedef pid_t ProcessId;
+typedef int ThreadId;
+typedef int FileHandle;
+const FileHandle kInvalidFileHandle = -1;
+#endif
+
+#if !defined(XP_WIN)
+FileHandle GetAnnotationTimeCrashFd();
+#endif
+void RegisterChildCrashAnnotationFileDescriptor(ProcessId aProcess,
+ PRFileDesc* aFd);
+void DeregisterChildCrashAnnotationFileDescriptor(ProcessId aProcess);
+
+// Return the current thread's ID.
+//
+// XXX: this is a somewhat out-of-place interface to expose through
+// crashreporter, but it takes significant work to call sys_gettid()
+// correctly on Linux and breakpad has already jumped through those
+// hoops for us.
+ThreadId CurrentThreadId();
+
+/*
+ * Take a minidump of the target process and pair it with a new minidump of the
+ * calling process and thread. The caller will own both dumps after this call.
+ * If this function fails it will attempt to delete any files that were created.
+ *
+ * The .extra information created will not include an 'additional_minidumps'
+ * annotation.
+ *
+ * @param aTargetPid The target process for the minidump.
+ * @param aTargetBlamedThread The target thread for the minidump.
+ * @param aIncomingPairName The name to apply to the paired dump the caller
+ * passes in.
+ * @param aTargetDumpOut The target minidump file paired up with the new one.
+ * @param aTargetAnnotations The crash annotations of the target process.
+ * @return bool indicating success or failure
+ */
+bool CreateMinidumpsAndPair(ProcessHandle aTargetPid,
+ ThreadId aTargetBlamedThread,
+ const nsACString& aIncomingPairName,
+ AnnotationTable& aTargetAnnotations,
+ nsIFile** aTargetDumpOut);
+
+#if defined(XP_WIN) || defined(XP_MACOSX)
+// Parent-side API for children
+const char* GetChildNotificationPipe();
+
+# ifdef MOZ_CRASHREPORTER_INJECTOR
+// Inject a crash report client into an arbitrary process, and inform the
+// callback object when it crashes. Parent process only.
+
+class InjectorCrashCallback {
+ public:
+ InjectorCrashCallback() {}
+
+ /**
+ * Inform the callback of a crash. The client code should call
+ * TakeMinidumpForChild to remove it from the PID mapping table.
+ *
+ * The callback will not be fired if the client has already called
+ * TakeMinidumpForChild for this process ID.
+ */
+ virtual void OnCrash(DWORD processID) = 0;
+};
+
+// This method implies OOPInit
+void InjectCrashReporterIntoProcess(DWORD processID, InjectorCrashCallback* cb);
+void UnregisterInjectorCallback(DWORD processID);
+# endif
+#else
+// Parent-side API for children
+
+// Set the outparams for crash reporter server's fd (|childCrashFd|)
+// and the magic fd number it should be remapped to
+// (|childCrashRemapFd|) before exec() in the child process.
+// |SetRemoteExceptionHandler()| in the child process expects to find
+// the server at |childCrashRemapFd|. Return true if successful.
+//
+// If crash reporting is disabled, both outparams will be set to -1
+// and |true| will be returned.
+bool CreateNotificationPipeForChild(int* childCrashFd, int* childCrashRemapFd);
+
+#endif // XP_WIN
+
+// Windows Error Reporting helper
+#if defined(XP_WIN)
+DWORD WINAPI WerNotifyProc(LPVOID aParameter);
+#endif
+
+// Child-side API
+bool SetRemoteExceptionHandler(
+ const char* aCrashPipe = nullptr,
+ FileHandle aCrashTimeAnnotationFile = kInvalidFileHandle);
+bool UnsetRemoteExceptionHandler(bool wasSet = true);
+
+#if defined(MOZ_WIDGET_ANDROID)
+// Android creates child process as services so we must explicitly set
+// the handle for the pipe since it can't get remapped to a default value.
+void SetNotificationPipeForChild(FileHandle childCrashFd);
+void SetCrashAnnotationPipeForChild(FileHandle childCrashAnnotationFd);
+#endif
+
+} // namespace CrashReporter
+
+#endif /* nsExceptionHandler_h__ */
diff --git a/toolkit/crashreporter/nsExceptionHandlerUtils.cpp b/toolkit/crashreporter/nsExceptionHandlerUtils.cpp
new file mode 100644
index 0000000000..e7f70e599b
--- /dev/null
+++ b/toolkit/crashreporter/nsExceptionHandlerUtils.cpp
@@ -0,0 +1,51 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* 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 "nsExceptionHandlerUtils.h"
+
+#include <algorithm>
+
+#include "double-conversion/double-conversion.h"
+
+// Format a non-negative double to a string, without using C-library functions,
+// which need to be avoided (.e.g. bug 1240160, comment 10). Return false if
+// we failed to get the formatting done correctly.
+bool SimpleNoCLibDtoA(double aValue, char* aBuffer, int aBufferLength) {
+ // aBufferLength is the size of the buffer. Be paranoid.
+ aBuffer[aBufferLength - 1] = '\0';
+
+ if (aValue < 0) {
+ return false;
+ }
+
+ int length, point, i;
+ bool sign;
+ bool ok = true;
+ double_conversion::DoubleToStringConverter::DoubleToAscii(
+ aValue, double_conversion::DoubleToStringConverter::SHORTEST, 8, aBuffer,
+ aBufferLength, &sign, &length, &point);
+
+ // length does not account for the 0 terminator.
+ if (length > point && (length + 1) < (aBufferLength - 1)) {
+ // We have to insert a decimal point. Not worried about adding a leading
+ // zero in the < 1 (point == 0) case.
+ aBuffer[length + 1] = '\0';
+ for (i = length; i > std::max(point, 0); i -= 1) {
+ aBuffer[i] = aBuffer[i - 1];
+ }
+ aBuffer[i] = '.'; // Not worried about locales
+ } else if (length < point) {
+ // Trailing zeros scenario
+ for (i = length; i < point; i += 1) {
+ if (i >= aBufferLength - 2) {
+ ok = false;
+ }
+ aBuffer[i] = '0';
+ }
+ aBuffer[i] = '\0';
+ }
+ return ok;
+}
diff --git a/toolkit/crashreporter/nsExceptionHandlerUtils.h b/toolkit/crashreporter/nsExceptionHandlerUtils.h
new file mode 100644
index 0000000000..e6578a6fa4
--- /dev/null
+++ b/toolkit/crashreporter/nsExceptionHandlerUtils.h
@@ -0,0 +1,12 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* 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/. */
+
+#ifndef nsExceptionHandlerUtils_h__
+#define nsExceptionHandlerUtils_h__
+
+bool SimpleNoCLibDtoA(double aValue, char* aBuffer, int aBufferLength);
+
+#endif // nsExceptionHandlerUtils_h__
diff --git a/toolkit/crashreporter/rust_minidump_writer_linux/Cargo.toml b/toolkit/crashreporter/rust_minidump_writer_linux/Cargo.toml
new file mode 100644
index 0000000000..b6028f6af9
--- /dev/null
+++ b/toolkit/crashreporter/rust_minidump_writer_linux/Cargo.toml
@@ -0,0 +1,15 @@
+[package]
+name = "rust_minidump_writer_linux"
+version = "0.1.0"
+authors = ["Martin Sirringhaus"]
+edition = "2018"
+license = "MPL-2.0"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+crash-context = "0.6.0"
+minidump-writer = "0.8.0"
+libc = "0.2.74"
+anyhow = "1.0"
+nsstring = { path = "../../../xpcom/rust/nsstring/" }
diff --git a/toolkit/crashreporter/rust_minidump_writer_linux/cbindgen.toml b/toolkit/crashreporter/rust_minidump_writer_linux/cbindgen.toml
new file mode 100644
index 0000000000..e858d0bf0a
--- /dev/null
+++ b/toolkit/crashreporter/rust_minidump_writer_linux/cbindgen.toml
@@ -0,0 +1,15 @@
+header = """/* 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/. */"""
+autogen_warning = """/* DO NOT MODIFY THIS MANUALLY! This file was generated using cbindgen. See RunCbindgen.py */
+"""
+include_version = true
+braces = "SameLine"
+line_length = 100
+tab_width = 2
+language = "C++"
+include_guard = "rust_minidump_writer_linux_ffi_generated_h"
+sys_includes = ["sys/signalfd.h"]
+
+[export.rename]
+"fpregset_t" = "struct _libc_fpstate"
diff --git a/toolkit/crashreporter/rust_minidump_writer_linux/moz.build b/toolkit/crashreporter/rust_minidump_writer_linux/moz.build
new file mode 100644
index 0000000000..834a97de28
--- /dev/null
+++ b/toolkit/crashreporter/rust_minidump_writer_linux/moz.build
@@ -0,0 +1,17 @@
+# -*- 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["COMPILE_ENVIRONMENT"]:
+ # This tells mach to run cbindgen and that this header-file should be created
+ CbindgenHeader(
+ "rust_minidump_writer_linux_ffi_generated.h",
+ inputs=["/toolkit/crashreporter/rust_minidump_writer_linux"],
+ )
+
+ # This tells mach to copy that generated file to obj/dist/includes/mozilla/toolkit/crashreporter/
+ EXPORTS.mozilla.toolkit.crashreporter += [
+ "!rust_minidump_writer_linux_ffi_generated.h",
+ ]
diff --git a/toolkit/crashreporter/rust_minidump_writer_linux/src/lib.rs b/toolkit/crashreporter/rust_minidump_writer_linux/src/lib.rs
new file mode 100644
index 0000000000..92a0795f41
--- /dev/null
+++ b/toolkit/crashreporter/rust_minidump_writer_linux/src/lib.rs
@@ -0,0 +1,132 @@
+/* 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/. */
+extern crate minidump_writer;
+
+use anyhow;
+use libc::pid_t;
+use minidump_writer::crash_context::CrashContext;
+use minidump_writer::minidump_writer::MinidumpWriter;
+use nsstring::nsCString;
+use std::ffi::CStr;
+use std::mem::{self, MaybeUninit};
+use std::os::raw::c_char;
+
+// This function will be exposed to C++
+#[no_mangle]
+pub unsafe extern "C" fn write_minidump_linux(
+ dump_path: *const c_char,
+ child: pid_t,
+ child_blamed_thread: pid_t,
+ error_msg: &mut nsCString,
+) -> bool {
+ assert!(!dump_path.is_null());
+ let c_path = CStr::from_ptr(dump_path);
+ let path = match c_path.to_str() {
+ Ok(s) => s,
+ Err(x) => {
+ error_msg.assign(&format!(
+ "Wrapper error. Path not convertable: {:#}",
+ anyhow::Error::new(x)
+ ));
+ return false;
+ }
+ };
+
+ let mut dump_file = match std::fs::OpenOptions::new()
+ .create(true) // Create file if it doesn't exist
+ .write(true) // Truncate file
+ .open(path)
+ {
+ Ok(f) => f,
+ Err(x) => {
+ error_msg.assign(&format!(
+ "Wrapper error when opening minidump destination at {:?}: {:#}",
+ path,
+ anyhow::Error::new(x)
+ ));
+ return false;
+ }
+ };
+
+ match MinidumpWriter::new(child, child_blamed_thread).dump(&mut dump_file) {
+ Ok(_) => {
+ return true;
+ }
+ Err(x) => {
+ error_msg.assign(&format!("{:#}", anyhow::Error::new(x)));
+ return false;
+ }
+ }
+}
+
+// This function will be exposed to C++
+#[no_mangle]
+pub unsafe extern "C" fn write_minidump_linux_with_context(
+ dump_path: *const c_char,
+ child: pid_t,
+ ucontext: *const crash_context::ucontext_t,
+ float_state: *const crash_context::fpregset_t,
+ siginfo: *const libc::signalfd_siginfo,
+ child_thread: libc::pid_t,
+ error_msg: &mut nsCString,
+) -> bool {
+ let c_path = CStr::from_ptr(dump_path);
+
+ let mut crash_context: MaybeUninit<crash_context::CrashContext> = mem::MaybeUninit::zeroed();
+ let mut cc = &mut *crash_context.as_mut_ptr();
+
+ core::ptr::copy_nonoverlapping(siginfo, &mut cc.siginfo, 1);
+ core::ptr::copy_nonoverlapping(ucontext, &mut cc.context, 1);
+
+ #[cfg(not(target_arch = "arm"))]
+ core::ptr::copy_nonoverlapping(float_state, &mut cc.float_state, 1);
+ // core::ptr::copy_nonoverlapping(float_state, ((&mut cc.float_state) as *mut crash_context::fpregset_t).cast(), 1);
+
+ cc.pid = child;
+ cc.tid = child_thread;
+ let crash_context = crash_context.assume_init();
+ let crash_context = CrashContext {
+ inner: crash_context,
+ };
+
+ let path = match c_path.to_str() {
+ Ok(s) => s,
+ Err(x) => {
+ error_msg.assign(&format!(
+ "Wrapper error. Path not convertable: {:#}",
+ anyhow::Error::new(x)
+ ));
+ return false;
+ }
+ };
+
+ let mut dump_file = match std::fs::OpenOptions::new()
+ .create(true) // Create file if it doesn't exist
+ .write(true) // Truncate file
+ .open(path)
+ {
+ Ok(f) => f,
+ Err(x) => {
+ error_msg.assign(&format!(
+ "Wrapper error when opening minidump destination at {:?}: {:#}",
+ path,
+ anyhow::Error::new(x)
+ ));
+ return false;
+ }
+ };
+
+ match MinidumpWriter::new(child, child_thread)
+ .set_crash_context(crash_context)
+ .dump(&mut dump_file)
+ {
+ Ok(_) => {
+ return true;
+ }
+ Err(x) => {
+ error_msg.assign(&format!("{:#}", anyhow::Error::new(x)));
+ return false;
+ }
+ }
+}
diff --git a/toolkit/crashreporter/test/CrashTestUtils.sys.mjs b/toolkit/crashreporter/test/CrashTestUtils.sys.mjs
new file mode 100644
index 0000000000..99f5bf4a48
--- /dev/null
+++ b/toolkit/crashreporter/test/CrashTestUtils.sys.mjs
@@ -0,0 +1,100 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+export var CrashTestUtils = {
+ // These will be defined using ctypes APIs below.
+ crash: null,
+ dumpHasStream: null,
+ dumpHasInstructionPointerMemory: null,
+ dumpWin64CFITestSymbols: null,
+
+ // Constants for crash()
+ // Keep these in sync with nsTestCrasher.cpp!
+ CRASH_INVALID_POINTER_DEREF: 0,
+ CRASH_PURE_VIRTUAL_CALL: 1,
+ CRASH_RUNTIMEABORT: 2,
+ CRASH_OOM: 3,
+ CRASH_MOZ_CRASH: 4,
+ CRASH_ABORT: 5,
+ CRASH_UNCAUGHT_EXCEPTION: 6,
+ CRASH_X64CFI_NO_MANS_LAND: 7,
+ CRASH_X64CFI_LAUNCHER: 8,
+ CRASH_X64CFI_UNKNOWN_OPCODE: 9,
+ CRASH_X64CFI_PUSH_NONVOL: 10,
+ CRASH_X64CFI_ALLOC_SMALL: 11,
+ CRASH_X64CFI_ALLOC_LARGE: 12,
+ CRASH_X64CFI_SAVE_NONVOL: 15,
+ CRASH_X64CFI_SAVE_NONVOL_FAR: 16,
+ CRASH_X64CFI_SAVE_XMM128: 17,
+ CRASH_X64CFI_SAVE_XMM128_FAR: 18,
+ CRASH_X64CFI_EPILOG: 19,
+ CRASH_X64CFI_EOF: 20,
+ CRASH_PHC_USE_AFTER_FREE: 21,
+ CRASH_PHC_DOUBLE_FREE: 22,
+ CRASH_PHC_BOUNDS_VIOLATION: 23,
+ CRASH_HEAP_CORRUPTION: 24,
+ CRASH_EXC_GUARD: 25,
+ CRASH_STACK_OVERFLOW: 26,
+
+ // Constants for dumpHasStream()
+ // From google_breakpad/common/minidump_format.h
+ MD_THREAD_LIST_STREAM: 3,
+ MD_MEMORY_INFO_LIST_STREAM: 16,
+};
+
+// Grab APIs from the testcrasher shared library
+import { ctypes } from "resource://gre/modules/ctypes.sys.mjs";
+
+var dir = Services.dirsvc.get("CurWorkD", Ci.nsIFile);
+var file = dir.clone();
+file = file.parent;
+file.append(ctypes.libraryName("testcrasher"));
+var lib = ctypes.open(file.path);
+CrashTestUtils.crash = lib.declare(
+ "Crash",
+ ctypes.default_abi,
+ ctypes.void_t,
+ ctypes.int16_t
+);
+CrashTestUtils.saveAppMemory = lib.declare(
+ "SaveAppMemory",
+ ctypes.default_abi,
+ ctypes.uint64_t
+);
+
+try {
+ CrashTestUtils.TryOverrideExceptionHandler = lib.declare(
+ "TryOverrideExceptionHandler",
+ ctypes.default_abi,
+ ctypes.void_t
+ );
+} catch (ex) {}
+
+CrashTestUtils.dumpHasStream = lib.declare(
+ "DumpHasStream",
+ ctypes.default_abi,
+ ctypes.bool,
+ ctypes.char.ptr,
+ ctypes.uint32_t
+);
+
+CrashTestUtils.dumpHasInstructionPointerMemory = lib.declare(
+ "DumpHasInstructionPointerMemory",
+ ctypes.default_abi,
+ ctypes.bool,
+ ctypes.char.ptr
+);
+
+CrashTestUtils.dumpCheckMemory = lib.declare(
+ "DumpCheckMemory",
+ ctypes.default_abi,
+ ctypes.bool,
+ ctypes.char.ptr
+);
+
+CrashTestUtils.getWin64CFITestFnAddrOffset = lib.declare(
+ "GetWin64CFITestFnAddrOffset",
+ ctypes.default_abi,
+ ctypes.int32_t,
+ ctypes.int16_t
+);
diff --git a/toolkit/crashreporter/test/ExceptionThrower.cpp b/toolkit/crashreporter/test/ExceptionThrower.cpp
new file mode 100644
index 0000000000..7404d13c47
--- /dev/null
+++ b/toolkit/crashreporter/test/ExceptionThrower.cpp
@@ -0,0 +1,3 @@
+#include "ExceptionThrower.h"
+
+void ThrowException() { throw 1; }
diff --git a/toolkit/crashreporter/test/ExceptionThrower.h b/toolkit/crashreporter/test/ExceptionThrower.h
new file mode 100644
index 0000000000..e8d30aee4b
--- /dev/null
+++ b/toolkit/crashreporter/test/ExceptionThrower.h
@@ -0,0 +1 @@
+void ThrowException();
diff --git a/toolkit/crashreporter/test/browser/browser.ini b/toolkit/crashreporter/test/browser/browser.ini
new file mode 100644
index 0000000000..9db7711873
--- /dev/null
+++ b/toolkit/crashreporter/test/browser/browser.ini
@@ -0,0 +1,15 @@
+[DEFAULT]
+support-files =
+ head.js
+
+[browser_aboutCrashes.js]
+[browser_aboutCrashesResubmit.js]
+https_first_disabled = true
+[browser_bug471404.js]
+[browser_clearReports.js]
+[browser_cpu_microcode.js]
+skip-if = os != 'win'
+reason = Windows-specific crash annotation
+[browser_sandbox_crash.js]
+skip-if = (os != 'linux') || release_or_beta
+reason = Linux-specific crash type, release/beta builds do not crash on sandbox violations
diff --git a/toolkit/crashreporter/test/browser/browser_aboutCrashes.js b/toolkit/crashreporter/test/browser/browser_aboutCrashes.js
new file mode 100644
index 0000000000..1885be4ca3
--- /dev/null
+++ b/toolkit/crashreporter/test/browser/browser_aboutCrashes.js
@@ -0,0 +1,82 @@
+add_task(async function test() {
+ const appD = make_fake_appdir();
+ const crD = appD.clone();
+ crD.append("Crash Reports");
+ const crashes = add_fake_crashes(crD, 5);
+ // sanity check
+ const appDtest = Services.dirsvc.get("UAppData", Ci.nsIFile);
+ ok(appD.equals(appDtest), "directory service provider registered ok");
+
+ await BrowserTestUtils.withNewTab(
+ { gBrowser, url: "about:crashes" },
+ browser => {
+ info("about:crashes loaded");
+ return SpecialPowers.spawn(browser, [crashes], crashes => {
+ const doc = content.document;
+
+ const submitted = doc.getElementById("reportListSubmitted");
+ Assert.ok(
+ !submitted.classList.contains("hidden"),
+ "the submitted crash list is visible"
+ );
+ const unsubmitted = doc.getElementById("reportListUnsubmitted");
+ Assert.ok(
+ unsubmitted.classList.contains("hidden"),
+ "the unsubmitted crash list is hidden"
+ );
+
+ const crashIds = doc.getElementsByClassName("crash-id");
+ Assert.equal(
+ crashIds.length,
+ crashes.length,
+ "about:crashes lists correct number of crash reports"
+ );
+ for (let i = 0; i < crashes.length; i++) {
+ Assert.equal(
+ crashIds[i].textContent,
+ crashes[i].id,
+ i + ": crash ID is correct"
+ );
+ }
+ });
+ }
+ );
+
+ clear_fake_crashes(crD, crashes);
+ const pendingCrash = addPendingCrashreport(crD, Date.now(), { foo: "bar" });
+ await BrowserTestUtils.withNewTab(
+ { gBrowser, url: "about:crashes" },
+ browser => {
+ info("about:crashes loaded");
+ return SpecialPowers.spawn(browser, [pendingCrash], pendingCrash => {
+ const doc = content.document;
+
+ const submitted = doc.getElementById("reportListSubmitted");
+ Assert.ok(
+ submitted.classList.contains("hidden"),
+ "the submitted crash list is hidden"
+ );
+ const unsubmitted = doc.getElementById("reportListUnsubmitted");
+ Assert.ok(
+ !unsubmitted.classList.contains("hidden"),
+ "the unsubmitted crash list is visible"
+ );
+
+ const crashIds = doc.getElementsByClassName("crash-id");
+ Assert.equal(
+ crashIds.length,
+ 1,
+ "about:crashes lists correct number of crash reports"
+ );
+ const pendingRow = doc.getElementById(pendingCrash.id);
+ Assert.equal(
+ pendingRow.cells[0].textContent,
+ pendingCrash.id,
+ "about:crashes lists pending crash IDs correctly"
+ );
+ });
+ }
+ );
+
+ cleanup_fake_appdir();
+});
diff --git a/toolkit/crashreporter/test/browser/browser_aboutCrashesResubmit.js b/toolkit/crashreporter/test/browser/browser_aboutCrashesResubmit.js
new file mode 100644
index 0000000000..93a21d451d
--- /dev/null
+++ b/toolkit/crashreporter/test/browser/browser_aboutCrashesResubmit.js
@@ -0,0 +1,202 @@
+function cleanup_and_finish() {
+ try {
+ cleanup_fake_appdir();
+ } catch (ex) {}
+ Services.prefs.clearUserPref("breakpad.reportURL");
+ BrowserTestUtils.removeTab(gBrowser.selectedTab);
+ finish();
+}
+
+/*
+ * check_crash_list
+ *
+ * Check that the list of crashes displayed by about:crashes matches
+ * the list of crashes that we placed in the pending+submitted directories.
+ *
+ * This function is run in a separate JS context via SpecialPowers.spawn, so
+ * it has no access to other functions or variables in this file.
+ */
+function check_crash_list(crashes) {
+ const doc = content.document;
+ const crashIdNodes = Array.from(doc.getElementsByClassName("crash-id"));
+ const pageCrashIds = new Set(crashIdNodes.map(node => node.textContent));
+ const crashIds = new Set(crashes.map(crash => crash.id));
+ Assert.deepEqual(
+ pageCrashIds,
+ crashIds,
+ "about:crashes lists the correct crash reports."
+ );
+}
+
+/*
+ * check_submit_pending
+ *
+ * Click on a pending crash in about:crashes, wait for it to be submitted (which
+ * should redirect us to the crash report page). Verify that the data provided
+ * by our test crash report server matches the data we submitted.
+ * Additionally, click "back" and verify that the link now points to our new
+ */
+function check_submit_pending(tab, crashes) {
+ const browser = gBrowser.getBrowserForTab(tab);
+ let SubmittedCrash = null;
+ let CrashID = null;
+ let CrashURL = null;
+ function csp_onsuccess() {
+ const crashLinks = content.document.getElementsByClassName("crash-link");
+ // Get the last link since it is appended to the end of the list
+ const link = crashLinks[crashLinks.length - 1];
+ link.click();
+ }
+ function csp_onload() {
+ // loaded the crash report page
+ ok(true, "got submission onload");
+
+ SpecialPowers.spawn(browser, [], function () {
+ // grab the Crash ID here to verify later
+ let CrashID = content.location.search.split("=")[1];
+ let CrashURL = content.location.toString();
+
+ // check the JSON content vs. what we submitted
+ let result = JSON.parse(content.document.documentElement.textContent);
+ Assert.equal(
+ result.upload_file_minidump,
+ "MDMP",
+ "minidump file sent properly"
+ );
+ Assert.equal(
+ result.memory_report,
+ "Let's pretend this is a memory report",
+ "memory report sent properly"
+ );
+ Assert.equal(
+ +result.Throttleable,
+ 0,
+ "correctly sent as non-throttleable"
+ );
+ Assert.equal(
+ result.SubmittedFrom,
+ "AboutCrashes",
+ "correctly flagged as sent from about:crashes"
+ );
+ // we checked these, they're set by the submission process,
+ // so they won't be in the "extra" data.
+ delete result.upload_file_minidump;
+ delete result.memory_report;
+ delete result.Throttleable;
+ delete result.SubmittedFrom;
+
+ return { id: CrashID, url: CrashURL, result };
+ }).then(({ id, url, result }) => {
+ // Likewise, this is discarded before it gets to the server
+ delete SubmittedCrash.extra.ServerURL;
+
+ CrashID = id;
+ CrashURL = url;
+ for (let x in result) {
+ if (x in SubmittedCrash.extra) {
+ is(
+ result[x],
+ SubmittedCrash.extra[x],
+ "submitted value for " + x + " matches expected"
+ );
+ } else {
+ ok(false, "property " + x + " missing from submitted data!");
+ }
+ }
+ for (let y in SubmittedCrash.extra) {
+ if (!(y in result)) {
+ ok(false, "property " + y + " missing from result data!");
+ }
+ }
+
+ // We can listen for pageshow like this because the tab is not remote.
+ BrowserTestUtils.waitForEvent(browser, "pageshow", true).then(
+ csp_pageshow
+ );
+
+ // now navigate back
+ browser.goBack();
+ });
+ }
+ function csp_fail() {
+ browser.removeEventListener("CrashSubmitFailed", csp_fail, true);
+ ok(false, "failed to submit crash report!");
+ cleanup_and_finish();
+ }
+ browser.addEventListener("CrashSubmitSucceeded", csp_onsuccess, true);
+ browser.addEventListener("CrashSubmitFailed", csp_fail, true);
+ BrowserTestUtils.browserLoaded(
+ browser,
+ false,
+ url => url !== "about:crashes"
+ ).then(csp_onload);
+ function csp_pageshow() {
+ SpecialPowers.spawn(
+ browser,
+ [{ CrashID, CrashURL }],
+ function ({ CrashID, CrashURL }) {
+ Assert.equal(
+ content.location.href,
+ "about:crashes",
+ "navigated back successfully"
+ );
+ const link = content.document
+ .getElementById(CrashID)
+ .getElementsByClassName("crash-link")[0];
+ Assert.notEqual(link, null, "crash report link changed correctly");
+ if (link) {
+ Assert.equal(
+ link.href,
+ CrashURL,
+ "crash report link points to correct href"
+ );
+ }
+ }
+ ).then(cleanup_and_finish);
+ }
+
+ // try submitting the pending report
+ for (const crash of crashes) {
+ if (crash.pending) {
+ SubmittedCrash = crash;
+ break;
+ }
+ }
+
+ SpecialPowers.spawn(browser, [SubmittedCrash.id], id => {
+ const submitButton = content.document
+ .getElementById(id)
+ .getElementsByClassName("submit-button")[0];
+ submitButton.click();
+ });
+}
+
+function test() {
+ waitForExplicitFinish();
+ const appD = make_fake_appdir();
+ const crD = appD.clone();
+ crD.append("Crash Reports");
+ const crashes = add_fake_crashes(crD, 1);
+ // we don't need much data here, it's not going to a real Socorro
+ crashes.push(
+ addPendingCrashreport(crD, crashes[crashes.length - 1].date + 60000, {
+ ServerURL:
+ "http://example.com/browser/toolkit/crashreporter/test/browser/crashreport.sjs",
+ ProductName: "Test App",
+ Foo: "ABC=XYZ", // test that we don't truncat eat = (bug 512853)
+ })
+ );
+ crashes.sort((a, b) => b.date - a.date);
+
+ // set this pref so we can link to our test server
+ Services.prefs.setCharPref(
+ "breakpad.reportURL",
+ "http://example.com/browser/toolkit/crashreporter/test/browser/crashreport.sjs?id="
+ );
+
+ BrowserTestUtils.openNewForegroundTab(gBrowser, "about:crashes").then(tab => {
+ SpecialPowers.spawn(tab.linkedBrowser, [crashes], check_crash_list).then(
+ () => check_submit_pending(tab, crashes)
+ );
+ });
+}
diff --git a/toolkit/crashreporter/test/browser/browser_bug471404.js b/toolkit/crashreporter/test/browser/browser_bug471404.js
new file mode 100644
index 0000000000..0ab7f19a4d
--- /dev/null
+++ b/toolkit/crashreporter/test/browser/browser_bug471404.js
@@ -0,0 +1,61 @@
+function check_clear_visible(browser, aVisible) {
+ return SpecialPowers.spawn(browser, [aVisible], function (aVisible) {
+ const doc = content.document;
+ let visible = false;
+ const reportListSubmitted = doc.getElementById("reportListSubmitted");
+ if (reportListSubmitted) {
+ const style = doc.defaultView.getComputedStyle(reportListSubmitted);
+ if (style.display !== "none" && style.visibility === "visible") {
+ visible = true;
+ }
+ }
+ Assert.equal(
+ visible,
+ aVisible,
+ "clear submitted reports button is " + (aVisible ? "visible" : "hidden")
+ );
+ });
+}
+
+// each test here has a setup (run before loading about:crashes) and onload (run after about:crashes loads)
+var _tests = [
+ {
+ setup: null,
+ onload(browser) {
+ return check_clear_visible(browser, false);
+ },
+ },
+ {
+ setup(crD) {
+ return add_fake_crashes(crD, 1);
+ },
+ onload(browser) {
+ return check_clear_visible(browser, true);
+ },
+ },
+];
+
+add_task(async function test() {
+ let appD = make_fake_appdir();
+ let crD = appD.clone();
+ crD.append("Crash Reports");
+
+ await BrowserTestUtils.withNewTab(
+ { gBrowser, url: "about:blank" },
+ async function (browser) {
+ for (let test of _tests) {
+ // Run setup before loading about:crashes.
+ if (test.setup) {
+ await test.setup(crD);
+ }
+
+ BrowserTestUtils.loadURIString(browser, "about:crashes");
+ await BrowserTestUtils.browserLoaded(browser).then(() =>
+ test.onload(browser)
+ );
+ }
+ }
+ );
+
+ cleanup_fake_appdir();
+});
diff --git a/toolkit/crashreporter/test/browser/browser_clearReports.js b/toolkit/crashreporter/test/browser/browser_clearReports.js
new file mode 100644
index 0000000000..2f780f1955
--- /dev/null
+++ b/toolkit/crashreporter/test/browser/browser_clearReports.js
@@ -0,0 +1,134 @@
+/* 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/. */
+
+function clickClearReports() {
+ const doc = content.document;
+ const reportListUnsubmitted = doc.getElementById("reportListUnsubmitted");
+ const reportListSubmitted = doc.getElementById("reportListSubmitted");
+ if (!reportListUnsubmitted || !reportListSubmitted) {
+ Assert.ok(false, "Report list not found");
+ }
+
+ const unsubmittedStyle = doc.defaultView.getComputedStyle(
+ reportListUnsubmitted
+ );
+ const submittedStyle = doc.defaultView.getComputedStyle(reportListSubmitted);
+ Assert.notEqual(
+ unsubmittedStyle.display,
+ "none",
+ "Unsubmitted report list is visible"
+ );
+ Assert.notEqual(
+ submittedStyle.display,
+ "none",
+ "Submitted report list is visible"
+ );
+
+ const clearUnsubmittedButton = doc.getElementById("clearUnsubmittedReports");
+ const clearSubmittedButton = doc.getElementById("clearSubmittedReports");
+ clearUnsubmittedButton.click();
+ clearSubmittedButton.click();
+}
+
+var promptShown = false;
+
+var oldPrompt = Services.prompt;
+Services.prompt = {
+ confirm() {
+ promptShown = true;
+ return true;
+ },
+};
+
+registerCleanupFunction(function () {
+ Services.prompt = oldPrompt;
+});
+
+add_task(async function test() {
+ let appD = make_fake_appdir();
+ let crD = appD.clone();
+ crD.append("Crash Reports");
+
+ // Add crashes to submitted dir
+ let submitdir = crD.clone();
+ submitdir.append("submitted");
+
+ let file1 = submitdir.clone();
+ file1.append("bp-nontxt");
+ file1.create(Ci.nsIFile.NORMAL_FILE_TYPE, 0o666);
+ let file2 = submitdir.clone();
+ file2.append("nonbp-file.txt");
+ file2.create(Ci.nsIFile.NORMAL_FILE_TYPE, 0o666);
+ add_fake_crashes(crD, 5);
+
+ // Add crashes to pending dir
+ let pendingdir = crD.clone();
+ pendingdir.append("pending");
+
+ let crashes = add_fake_crashes(crD, 2);
+ addPendingCrashreport(crD, crashes[0].date);
+ addPendingCrashreport(crD, crashes[1].date);
+
+ // Add crashes to reports dir
+ let report1 = crD.clone();
+ report1.append("NotInstallTime777");
+ report1.create(Ci.nsIFile.NORMAL_FILE_TYPE, 0o666);
+ let report2 = crD.clone();
+ report2.append("InstallTime" + Services.appinfo.appBuildID);
+ report2.create(Ci.nsIFile.NORMAL_FILE_TYPE, 0o666);
+ let report3 = crD.clone();
+ report3.append("InstallTimeNew");
+ report3.create(Ci.nsIFile.NORMAL_FILE_TYPE, 0o666);
+ let report4 = crD.clone();
+ report4.append("InstallTimeOld");
+ report4.create(Ci.nsIFile.NORMAL_FILE_TYPE, 0o666);
+ report4.lastModifiedTime = Date.now() - 63172000000;
+
+ registerCleanupFunction(function () {
+ cleanup_fake_appdir();
+ });
+
+ await BrowserTestUtils.withNewTab(
+ { gBrowser, url: "about:crashes" },
+ async function (browser) {
+ let dirs = [submitdir, pendingdir, crD];
+ let existing = [
+ file1.path,
+ file2.path,
+ report1.path,
+ report2.path,
+ report3.path,
+ submitdir.path,
+ pendingdir.path,
+ ];
+
+ SpecialPowers.spawn(browser, [], clickClearReports);
+ await BrowserTestUtils.waitForCondition(
+ () =>
+ content.document
+ .getElementById("reportListUnsubmitted")
+ .classList.contains("hidden") &&
+ content.document
+ .getElementById("reportListSubmitted")
+ .classList.contains("hidden")
+ );
+
+ for (let dir of dirs) {
+ let entries = dir.directoryEntries;
+ while (entries.hasMoreElements()) {
+ let file = entries.nextFile;
+ let index = existing.indexOf(file.path);
+ isnot(index, -1, file.leafName + " exists");
+
+ if (index != -1) {
+ existing.splice(index, 1);
+ }
+ }
+ }
+
+ is(existing.length, 0, "All the files that should still exist exist");
+ ok(promptShown, "Prompt shown");
+ }
+ );
+});
diff --git a/toolkit/crashreporter/test/browser/browser_cpu_microcode.js b/toolkit/crashreporter/test/browser/browser_cpu_microcode.js
new file mode 100644
index 0000000000..e4efd1c86d
--- /dev/null
+++ b/toolkit/crashreporter/test/browser/browser_cpu_microcode.js
@@ -0,0 +1,25 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+/* global BrowserTestUtils, ok, gBrowser, add_task */
+
+"use strict";
+
+/**
+ * Checks that we set the CPUMicrocodeVersion annotation.
+ */
+add_task(async function test_cpu_microcode_version_annotation() {
+ await BrowserTestUtils.withNewTab(
+ {
+ gBrowser,
+ },
+ async function (browser) {
+ // Crash the tab
+ let annotations = await BrowserTestUtils.crashFrame(browser);
+
+ ok(
+ "CPUMicrocodeVersion" in annotations,
+ "contains CPU microcode version"
+ );
+ }
+ );
+});
diff --git a/toolkit/crashreporter/test/browser/browser_sandbox_crash.js b/toolkit/crashreporter/test/browser/browser_sandbox_crash.js
new file mode 100644
index 0000000000..4cd3d782e5
--- /dev/null
+++ b/toolkit/crashreporter/test/browser/browser_sandbox_crash.js
@@ -0,0 +1,77 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+/* global BrowserTestUtils, ok, gBrowser, add_task */
+
+"use strict";
+
+/**
+ * Checks that we set the CPUMicrocodeVersion annotation.
+ * This is a Windows-specific crash annotation.
+ */
+if (AppConstants.platform == "win") {
+ add_task(async function test_cpu_microcode_version_annotation() {
+ await BrowserTestUtils.withNewTab(
+ {
+ gBrowser,
+ },
+ async function (browser) {
+ // Crash the tab
+ let annotations = await BrowserTestUtils.crashFrame(browser);
+
+ ok(
+ "CPUMicrocodeVersion" in annotations,
+ "contains CPU microcode version"
+ );
+ }
+ );
+ });
+}
+
+/**
+ * Checks that Linux sandbox violations are reported as SIGSYS crashes with
+ * the syscall number provided in the address field of the minidump's exception
+ * stream.
+ */
+if (AppConstants.platform == "linux") {
+ add_task(async function test_sandbox_violation_is_sigsys() {
+ await BrowserTestUtils.withNewTab(
+ {
+ gBrowser,
+ },
+ async function (browser) {
+ // Crash the tab
+ let annotations = await BrowserTestUtils.crashFrame(
+ browser,
+ true,
+ true,
+ /* Default browsing context */ null,
+ { crashType: "CRASH_SYSCALL" }
+ );
+
+ Assert.equal(
+ annotations.StackTraces.crash_info.type,
+ "SIGSYS",
+ "The crash type is SIGSYS"
+ );
+
+ function chroot_syscall_number() {
+ // We crash by calling chroot(), see BrowserTestUtilsChild.sys.mjs
+ switch (Services.sysinfo.get("arch")) {
+ case "x86-64":
+ return "0xa1";
+ case "aarch64":
+ return "0x33";
+ default:
+ return "0x3d";
+ }
+ }
+
+ Assert.equal(
+ annotations.StackTraces.crash_info.address,
+ chroot_syscall_number(),
+ "The address corresponds to the chroot() syscall number"
+ );
+ }
+ );
+ });
+}
diff --git a/toolkit/crashreporter/test/browser/crashreport.sjs b/toolkit/crashreporter/test/browser/crashreport.sjs
new file mode 100644
index 0000000000..908455c9e6
--- /dev/null
+++ b/toolkit/crashreporter/test/browser/crashreport.sjs
@@ -0,0 +1,176 @@
+const CC = Components.Constructor;
+
+const BinaryInputStream = CC(
+ "@mozilla.org/binaryinputstream;1",
+ "nsIBinaryInputStream",
+ "setInputStream"
+);
+
+function parseHeaders(data, start) {
+ let headers = {};
+
+ while (true) {
+ let end = data.indexOf("\r\n", start);
+ if (end == -1) {
+ end = data.length;
+ }
+ let line = data.substring(start, end);
+ start = end + 2;
+ if (line == "") {
+ // empty line, we're done
+ break;
+ }
+
+ //XXX: this doesn't handle multi-line headers. do we care?
+ let [name, value] = line.split(":");
+ //XXX: not normalized, should probably use nsHttpHeaders or something
+ headers[name] = value.trimLeft();
+ }
+ return [headers, start];
+}
+
+function parseMultipartForm(request) {
+ let boundary = null;
+ // See if this is a multipart/form-data request, and if so, find the
+ // boundary string
+ if (request.hasHeader("Content-Type")) {
+ var contenttype = request.getHeader("Content-Type");
+ var bits = contenttype.split(";");
+ if (bits[0] == "multipart/form-data") {
+ for (var i = 1; i < bits.length; i++) {
+ var b = bits[i].trimLeft();
+ if (b.indexOf("boundary=") == 0) {
+ // grab everything after boundary=
+ boundary = "--" + b.substring(9);
+ break;
+ }
+ }
+ }
+ }
+ if (boundary == null) {
+ return null;
+ }
+
+ let body = new BinaryInputStream(request.bodyInputStream);
+ let avail;
+ let bytes = [];
+ while ((avail = body.available()) > 0) {
+ let readBytes = body.readByteArray(avail);
+ for (let b of readBytes) {
+ bytes.push(b);
+ }
+ }
+ let data = "";
+ for (let b of bytes) {
+ data += String.fromCharCode(b);
+ }
+ let formData = {};
+ let start = 0;
+ while (true) {
+ // read first line
+ let end = data.indexOf("\r\n", start);
+ if (end == -1) {
+ end = data.length;
+ }
+
+ let line = data.substring(start, end);
+ // look for closing boundary delimiter line
+ if (line == boundary + "--") {
+ break;
+ }
+
+ if (line != boundary) {
+ dump("expected boundary line but didn't find it!");
+ break;
+ }
+
+ // parse headers
+ start = end + 2;
+ let headers = null;
+ [headers, start] = parseHeaders(data, start);
+
+ // find next boundary string
+ end = data.indexOf("\r\n" + boundary, start);
+ if (end == -1) {
+ dump("couldn't find next boundary string\n");
+ break;
+ }
+
+ // read part data, stick in formData using Content-Disposition header
+ let part = data.substring(start, end);
+ start = end + 2;
+
+ if ("Content-Disposition" in headers) {
+ let bits = headers["Content-Disposition"].split(";");
+ if (bits[0] == "form-data") {
+ for (let i = 0; i < bits.length; i++) {
+ let b = bits[i].trimLeft();
+ if (b.indexOf("name=") == 0) {
+ //TODO: handle non-ascii here?
+ let name = b.substring(6, b.length - 1);
+ //TODO: handle multiple-value properties?
+ if (
+ "Content-Type" in headers &&
+ headers["Content-Type"] == "application/json"
+ ) {
+ formData = Object.assign(formData, JSON.parse(part));
+ } else {
+ formData[name] = part;
+ }
+ }
+ //TODO: handle filename= ?
+ //TODO: handle multipart/mixed for multi-file uploads?
+ }
+ }
+ }
+ }
+ return formData;
+}
+
+function handleRequest(request, response) {
+ if (request.method == "GET") {
+ let id = null;
+ for (let p of request.queryString.split("&")) {
+ let [key, value] = p.split("=");
+ if (key == "id") {
+ id = value;
+ }
+ }
+ if (id == null) {
+ response.setStatusLine(request.httpVersion, 400, "Bad Request");
+ response.write("Missing id parameter");
+ } else {
+ let data = getState(id);
+ if (data == "") {
+ response.setStatusLine(request.httpVersion, 404, "Not Found");
+ response.write("Not Found");
+ } else {
+ response.setHeader("Content-Type", "text/plain", false);
+ response.write(data);
+ }
+ }
+ } else if (request.method == "POST") {
+ let formData = parseMultipartForm(request);
+
+ if (formData && "upload_file_minidump" in formData) {
+ response.setHeader("Content-Type", "text/plain", false);
+
+ let uuid = Services.uuid.generateUUID().toString();
+ // ditch the {}, add bp- prefix
+ uuid = "bp-" + uuid.substring(1, uuid.length - 1);
+
+ let d = JSON.stringify(formData);
+ //dump('saving crash report ' + uuid + ': ' + d + '\n');
+ setState(uuid, d);
+
+ response.write("CrashID=" + uuid + "\n");
+ } else {
+ dump("*** crashreport.sjs: Malformed request?\n");
+ response.setStatusLine(request.httpVersion, 400, "Bad Request");
+ response.write("Missing minidump file");
+ }
+ } else {
+ response.setStatusLine(request.httpVersion, 405, "Method not allowed");
+ response.write("Can't handle HTTP method " + request.method);
+ }
+}
diff --git a/toolkit/crashreporter/test/browser/head.js b/toolkit/crashreporter/test/browser/head.js
new file mode 100644
index 0000000000..fea602a028
--- /dev/null
+++ b/toolkit/crashreporter/test/browser/head.js
@@ -0,0 +1,163 @@
+function create_subdir(dir, subdirname) {
+ let subdir = dir.clone();
+ subdir.append(subdirname);
+ if (subdir.exists()) {
+ subdir.remove(true);
+ }
+ subdir.create(Ci.nsIFile.DIRECTORY_TYPE, 0o755);
+ return subdir;
+}
+
+function generate_uuid() {
+ let uuidGenerator = Services.uuid;
+ let uuid = uuidGenerator.generateUUID().toString();
+ // ditch the {}
+ return uuid.substring(1, uuid.length - 1);
+}
+
+// need to hold on to this to unregister for cleanup
+var _provider = null;
+
+function make_fake_appdir() {
+ // Create a directory inside the profile and register it as UAppData, so
+ // we can stick fake crash reports inside there. We put it inside the profile
+ // just because we know that will get cleaned up after the mochitest run.
+ let profD = Services.dirsvc.get("ProfD", Ci.nsIFile);
+ // create a subdir just to keep our files out of the way
+ let appD = create_subdir(profD, "UAppData");
+
+ let crashesDir = create_subdir(appD, "Crash Reports");
+ create_subdir(crashesDir, "pending");
+ create_subdir(crashesDir, "submitted");
+
+ _provider = {
+ getFile(prop, persistent) {
+ persistent.value = true;
+ if (prop == "UAppData") {
+ return appD.clone();
+ }
+ // Depending on timing we can get requests for other files.
+ // When we threw an exception here, in the world before bug 997440, this got lost
+ // because of the arbitrary JSContext being used in nsXPCWrappedJS::CallMethod.
+ // After bug 997440 this gets reported to our window and causes the tests to fail.
+ // So, we'll just dump out a message to the logs.
+ dump(
+ "WARNING: make_fake_appdir - fake nsIDirectoryServiceProvider - Unexpected getFile for: '" +
+ prop +
+ "'\n"
+ );
+ return null;
+ },
+ QueryInterface: ChromeUtils.generateQI(["nsIDirectoryServiceProvider"]),
+ };
+ // register our new provider
+ Services.dirsvc
+ .QueryInterface(Ci.nsIDirectoryService)
+ .registerProvider(_provider);
+ // and undefine the old value
+ try {
+ Services.dirsvc.undefine("UAppData");
+ } catch (ex) {} // it's ok if this fails, the value might not be cached yet
+ return appD.clone();
+}
+
+function cleanup_fake_appdir() {
+ Services.dirsvc
+ .QueryInterface(Ci.nsIDirectoryService)
+ .unregisterProvider(_provider);
+ // undefine our value so future calls get the real value
+ try {
+ Services.dirsvc.undefine("UAppData");
+ } catch (ex) {
+ dump("cleanup_fake_appdir: dirSvc.undefine failed: " + ex.message + "\n");
+ }
+}
+
+function add_fake_crashes(crD, count) {
+ let results = [];
+ let submitdir = crD.clone();
+ submitdir.append("submitted");
+ // create them from oldest to newest, to ensure that about:crashes
+ // displays them in the correct order
+ let date = Date.now() - count * 60000;
+ for (let i = 0; i < count; i++) {
+ let uuid = "bp-" + generate_uuid();
+ let fn = uuid + ".txt";
+ let file = submitdir.clone();
+ file.append(fn);
+ file.create(Ci.nsIFile.NORMAL_FILE_TYPE, 0o666);
+ file.lastModifiedTime = date;
+ results.push({ id: uuid, date, pending: false });
+
+ date += 60000;
+ }
+ // we want them sorted newest to oldest, since that's the order
+ // that about:crashes lists them in
+ results.sort((a, b) => b.date - a.date);
+ return results;
+}
+
+function clear_fake_crashes(crD, crashes) {
+ let submitdir = crD.clone();
+ submitdir.append("submitted");
+ for (let i of crashes) {
+ let fn = i.id + ".txt";
+ let file = submitdir.clone();
+ file.append(fn);
+ file.remove(false);
+ }
+}
+
+function writeDataToFile(file, data) {
+ var fstream = Cc["@mozilla.org/network/file-output-stream;1"].createInstance(
+ Ci.nsIFileOutputStream
+ );
+ // open, write, truncate
+ fstream.init(file, -1, -1, 0);
+ var os = Cc["@mozilla.org/intl/converter-output-stream;1"].createInstance(
+ Ci.nsIConverterOutputStream
+ );
+ os.init(fstream, "UTF-8");
+ os.writeString(data);
+ os.close();
+ fstream.close();
+}
+
+function writeCrashReportFile(dir, uuid, suffix, date, data) {
+ let file = dir.clone();
+ file.append(uuid + suffix);
+ writeDataToFile(file, data);
+ file.lastModifiedTime = date;
+}
+
+function writeMinidumpFile(dir, uuid, date) {
+ // that's the start of a valid minidump, anyway
+ writeCrashReportFile(dir, uuid, ".dmp", date, "MDMP");
+}
+
+function writeExtraFile(dir, uuid, date, data) {
+ writeCrashReportFile(dir, uuid, ".extra", date, JSON.stringify(data));
+}
+
+function writeMemoryReport(dir, uuid, date) {
+ let data = "Let's pretend this is a memory report";
+ writeCrashReportFile(dir, uuid, ".memory.json.gz", date, data);
+}
+
+function addPendingCrashreport(crD, date, extra) {
+ let pendingdir = crD.clone();
+ pendingdir.append("pending");
+ let uuid = generate_uuid();
+ writeMinidumpFile(pendingdir, uuid, date);
+ writeExtraFile(pendingdir, uuid, date, extra);
+ writeMemoryReport(pendingdir, uuid, date);
+ return { id: uuid, date, pending: true, extra };
+}
+
+function addIncompletePendingCrashreport(crD, date) {
+ let pendingdir = crD.clone();
+ pendingdir.append("pending");
+ let uuid = generate_uuid();
+ writeMinidumpFile(pendingdir, uuid, date);
+ return { id: uuid, date, pending: true };
+}
diff --git a/toolkit/crashreporter/test/dumputils.cpp b/toolkit/crashreporter/test/dumputils.cpp
new file mode 100644
index 0000000000..fedaa6532a
--- /dev/null
+++ b/toolkit/crashreporter/test/dumputils.cpp
@@ -0,0 +1,83 @@
+#include <stdio.h>
+
+#include "google_breakpad/processor/minidump.h"
+#include "nscore.h"
+
+using namespace google_breakpad;
+
+// Return true if the specified minidump contains a stream of |stream_type|.
+extern "C" NS_EXPORT bool DumpHasStream(const char* dump_file,
+ uint32_t stream_type) {
+ Minidump dump(dump_file);
+ if (!dump.Read()) return false;
+
+ uint32_t length;
+ if (!dump.SeekToStreamType(stream_type, &length) || length == 0) return false;
+
+ return true;
+}
+
+// Return true if the specified minidump contains a memory region
+// that contains the instruction pointer from the exception record.
+extern "C" NS_EXPORT bool DumpHasInstructionPointerMemory(
+ const char* dump_file) {
+ Minidump minidump(dump_file);
+ if (!minidump.Read()) return false;
+
+ MinidumpException* exception = minidump.GetException();
+ MinidumpMemoryList* memory_list = minidump.GetMemoryList();
+ if (!exception || !memory_list) {
+ return false;
+ }
+
+ MinidumpContext* context = exception->GetContext();
+ if (!context) return false;
+
+ uint64_t instruction_pointer;
+ if (!context->GetInstructionPointer(&instruction_pointer)) {
+ return false;
+ }
+
+ MinidumpMemoryRegion* region =
+ memory_list->GetMemoryRegionForAddress(instruction_pointer);
+ return region != nullptr;
+}
+
+// This function tests for a very specific condition. It finds
+// an address in a file, "crash-addr", in the CWD. It checks
+// that the minidump has a memory region starting at that
+// address. The region must be 32 bytes long and contain the
+// values 0 to 31 as bytes, in ascending order.
+extern "C" NS_EXPORT bool DumpCheckMemory(const char* dump_file) {
+ Minidump dump(dump_file);
+ if (!dump.Read()) return false;
+
+ MinidumpMemoryList* memory_list = dump.GetMemoryList();
+ if (!memory_list) {
+ return false;
+ }
+
+ void* addr;
+ FILE* fp = fopen("crash-addr", "r");
+ if (!fp) return false;
+ if (fscanf(fp, "%p", &addr) != 1) {
+ fclose(fp);
+ return false;
+ }
+ fclose(fp);
+
+ remove("crash-addr");
+
+ MinidumpMemoryRegion* region =
+ memory_list->GetMemoryRegionForAddress(uint64_t(addr));
+ if (!region) return false;
+
+ const uint8_t* chars = region->GetMemory();
+ if (region->GetSize() != 32) return false;
+
+ for (int i = 0; i < 32; i++) {
+ if (chars[i] != i) return false;
+ }
+
+ return true;
+}
diff --git a/toolkit/crashreporter/test/moz.build b/toolkit/crashreporter/test/moz.build
new file mode 100644
index 0000000000..70678af74a
--- /dev/null
+++ b/toolkit/crashreporter/test/moz.build
@@ -0,0 +1,67 @@
+# -*- 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/.
+FINAL_TARGET = "_tests/xpcshell/toolkit/crashreporter/test"
+
+XPCSHELL_TESTS_MANIFESTS += ["unit/xpcshell.ini", "unit_ipc/xpcshell.ini"]
+if CONFIG["MOZ_PHC"]:
+ XPCSHELL_TESTS_MANIFESTS += ["unit/xpcshell-phc.ini", "unit_ipc/xpcshell-phc.ini"]
+
+BROWSER_CHROME_MANIFESTS += ["browser/browser.ini"]
+
+UNIFIED_SOURCES += [
+ "../google-breakpad/src/processor/basic_code_modules.cc",
+ "../google-breakpad/src/processor/convert_old_arm64_context.cc",
+ "../google-breakpad/src/processor/dump_context.cc",
+ "../google-breakpad/src/processor/dump_object.cc",
+ "../google-breakpad/src/processor/logging.cc",
+ "../google-breakpad/src/processor/minidump.cc",
+ "../google-breakpad/src/processor/pathname_stripper.cc",
+ "../google-breakpad/src/processor/proc_maps_linux.cc",
+ "dumputils.cpp",
+ "nsTestCrasher.cpp",
+]
+
+SOURCES += [
+ "ExceptionThrower.cpp",
+]
+
+if CONFIG["OS_TARGET"] == "WINNT" and CONFIG["CPU_ARCH"] == "x86_64":
+ if CONFIG["CC_TYPE"] not in ("gcc", "clang"):
+ SOURCES += [
+ "win64UnwindInfoTests.asm",
+ ]
+
+if CONFIG["CC_TYPE"] == "clang-cl":
+ SOURCES["ExceptionThrower.cpp"].flags += [
+ "-Xclang",
+ "-fcxx-exceptions",
+ ]
+else:
+ SOURCES["ExceptionThrower.cpp"].flags += [
+ "-fexceptions",
+ ]
+
+if CONFIG["MOZ_PHC"]:
+ DEFINES["MOZ_PHC"] = True
+
+GeckoSharedLibrary("testcrasher")
+
+DEFINES["SHARED_LIBRARY"] = "%s%s%s" % (
+ CONFIG["DLL_PREFIX"],
+ LIBRARY_NAME,
+ CONFIG["DLL_SUFFIX"],
+)
+
+TEST_HARNESS_FILES.xpcshell.toolkit.crashreporter.test.unit += [
+ "CrashTestUtils.sys.mjs"
+]
+TEST_HARNESS_FILES.xpcshell.toolkit.crashreporter.test.unit_ipc += [
+ "CrashTestUtils.sys.mjs"
+]
+
+include("/toolkit/crashreporter/crashreporter.mozbuild")
+
+NO_PGO = True
diff --git a/toolkit/crashreporter/test/nsTestCrasher.cpp b/toolkit/crashreporter/test/nsTestCrasher.cpp
new file mode 100644
index 0000000000..d8de2ed63e
--- /dev/null
+++ b/toolkit/crashreporter/test/nsTestCrasher.cpp
@@ -0,0 +1,364 @@
+#include "mozilla/Assertions.h"
+
+#include <stdio.h>
+#include <map>
+
+#include "nscore.h"
+#include "mozilla/Unused.h"
+#include "ExceptionThrower.h"
+
+#ifdef XP_WIN
+# include <malloc.h>
+# include <windows.h>
+#elif defined(XP_MACOSX)
+# include <sys/types.h>
+# include <sys/fcntl.h>
+# include <unistd.h>
+# include <dlfcn.h> // For dlsym()
+// See https://github.com/apple/darwin-xnu/blob/main/bsd/sys/guarded.h
+# define GUARD_CLOSE (1u << 0)
+# define GUARD_DUP (1u << 1)
+# define GUARD_SOCKET_IPC (1u << 2)
+# define GUARD_FILEPORT (1u << 3)
+# define GUARD_WRITE (1u << 4)
+typedef uint64_t guardid_t;
+typedef int (*guarded_open_np_t)(const char*, const guardid_t*, u_int, int,
+ ...);
+#endif
+
+#ifndef XP_WIN
+# include <pthread.h>
+#endif
+
+#ifdef MOZ_PHC
+# include "replace_malloc_bridge.h"
+#endif
+
+/*
+ * This pure virtual call example is from MSDN
+ */
+class A;
+
+void fcn(A*);
+
+class A {
+ public:
+ virtual void f() = 0;
+ A() { fcn(this); }
+};
+
+class B : A {
+ void f() override {}
+
+ public:
+ void use() {}
+};
+
+void fcn(A* p) { p->f(); }
+
+void PureVirtualCall() {
+ // generates a pure virtual function call
+ B b;
+ b.use(); // make sure b's actually used
+}
+
+extern "C" {
+#if XP_WIN && HAVE_64BIT_BUILD && defined(_M_X64) && !defined(__MINGW32__)
+// Implementation in win64unwindInfoTests.asm
+uint64_t x64CrashCFITest_NO_MANS_LAND(uint64_t returnpfn, void*);
+uint64_t x64CrashCFITest_Launcher(uint64_t returnpfn, void* testProc);
+uint64_t x64CrashCFITest_UnknownOpcode(uint64_t returnpfn, void*);
+uint64_t x64CrashCFITest_PUSH_NONVOL(uint64_t returnpfn, void*);
+uint64_t x64CrashCFITest_ALLOC_SMALL(uint64_t returnpfn, void*);
+uint64_t x64CrashCFITest_ALLOC_LARGE(uint64_t returnpfn, void*);
+uint64_t x64CrashCFITest_SAVE_NONVOL(uint64_t returnpfn, void*);
+uint64_t x64CrashCFITest_SAVE_NONVOL_FAR(uint64_t returnpfn, void*);
+uint64_t x64CrashCFITest_SAVE_XMM128(uint64_t returnpfn, void*);
+uint64_t x64CrashCFITest_SAVE_XMM128_FAR(uint64_t returnpfn, void*);
+uint64_t x64CrashCFITest_EPILOG(uint64_t returnpfn, void*);
+uint64_t x64CrashCFITest_EOF(uint64_t returnpfn, void*);
+#endif // XP_WIN && HAVE_64BIT_BUILD && !defined(__MINGW32__)
+}
+
+// Keep these in sync with CrashTestUtils.jsm!
+const int16_t CRASH_INVALID_POINTER_DEREF = 0;
+const int16_t CRASH_PURE_VIRTUAL_CALL = 1;
+const int16_t CRASH_OOM = 3;
+const int16_t CRASH_MOZ_CRASH = 4;
+const int16_t CRASH_ABORT = 5;
+const int16_t CRASH_UNCAUGHT_EXCEPTION = 6;
+#if XP_WIN && HAVE_64BIT_BUILD && defined(_M_X64) && !defined(__MINGW32__)
+const int16_t CRASH_X64CFI_NO_MANS_LAND = 7;
+const int16_t CRASH_X64CFI_LAUNCHER = 8;
+const int16_t CRASH_X64CFI_UNKNOWN_OPCODE = 9;
+const int16_t CRASH_X64CFI_PUSH_NONVOL = 10;
+const int16_t CRASH_X64CFI_ALLOC_SMALL = 11;
+const int16_t CRASH_X64CFI_ALLOC_LARGE = 12;
+const int16_t CRASH_X64CFI_SAVE_NONVOL = 15;
+const int16_t CRASH_X64CFI_SAVE_NONVOL_FAR = 16;
+const int16_t CRASH_X64CFI_SAVE_XMM128 = 17;
+const int16_t CRASH_X64CFI_SAVE_XMM128_FAR = 18;
+const int16_t CRASH_X64CFI_EPILOG = 19;
+const int16_t CRASH_X64CFI_EOF = 20;
+#endif
+const int16_t CRASH_PHC_USE_AFTER_FREE = 21;
+const int16_t CRASH_PHC_DOUBLE_FREE = 22;
+const int16_t CRASH_PHC_BOUNDS_VIOLATION = 23;
+#if XP_WIN
+const int16_t CRASH_HEAP_CORRUPTION = 24;
+#endif
+#ifdef XP_MACOSX
+const int16_t CRASH_EXC_GUARD = 25;
+#endif
+#ifndef XP_WIN
+const int16_t CRASH_STACK_OVERFLOW = 26;
+#endif
+
+#if XP_WIN && HAVE_64BIT_BUILD && defined(_M_X64) && !defined(__MINGW32__)
+
+typedef decltype(&x64CrashCFITest_UnknownOpcode) win64CFITestFnPtr_t;
+
+static std::map<int16_t, win64CFITestFnPtr_t> GetWin64CFITestMap() {
+ std::map<int16_t, win64CFITestFnPtr_t> ret = {
+ {CRASH_X64CFI_NO_MANS_LAND, x64CrashCFITest_NO_MANS_LAND},
+ {CRASH_X64CFI_LAUNCHER, x64CrashCFITest_Launcher},
+ {CRASH_X64CFI_UNKNOWN_OPCODE, x64CrashCFITest_UnknownOpcode},
+ {CRASH_X64CFI_PUSH_NONVOL, x64CrashCFITest_PUSH_NONVOL},
+ {CRASH_X64CFI_ALLOC_SMALL, x64CrashCFITest_ALLOC_SMALL},
+ {CRASH_X64CFI_ALLOC_LARGE, x64CrashCFITest_ALLOC_LARGE},
+ {CRASH_X64CFI_SAVE_NONVOL, x64CrashCFITest_SAVE_NONVOL},
+ {CRASH_X64CFI_SAVE_NONVOL_FAR, x64CrashCFITest_SAVE_NONVOL_FAR},
+ {CRASH_X64CFI_SAVE_XMM128, x64CrashCFITest_SAVE_XMM128},
+ {CRASH_X64CFI_SAVE_XMM128_FAR, x64CrashCFITest_SAVE_XMM128_FAR},
+ {CRASH_X64CFI_EPILOG, x64CrashCFITest_EPILOG},
+ {CRASH_X64CFI_EOF, x64CrashCFITest_EOF}};
+ // ret values point to jump table entries, not the actual function bodies.
+ // Get the correct pointer by calling the function with returnpfn=1
+ for (auto it = ret.begin(); it != ret.end(); ++it) {
+ it->second = (win64CFITestFnPtr_t)it->second(1, nullptr);
+ }
+ return ret;
+}
+
+// This ensures tests have enough committed stack space.
+// Must not be inlined, or the stack space would not be freed for the caller
+// to use.
+void MOZ_NEVER_INLINE ReserveStack() {
+ // We must actually use the memory in some way that the compiler can't
+ // optimize away.
+ static const size_t elements = (1024000 / sizeof(FILETIME)) + 1;
+ FILETIME stackmem[elements];
+ ::GetSystemTimeAsFileTime(&stackmem[0]);
+ ::GetSystemTimeAsFileTime(&stackmem[elements - 1]);
+}
+
+#endif // XP_WIN && HAVE_64BIT_BUILD
+
+#ifdef MOZ_PHC
+uint8_t* GetPHCAllocation(size_t aSize) {
+ // A crude but effective way to get a PHC allocation.
+ for (int i = 0; i < 2000000; i++) {
+ uint8_t* p = (uint8_t*)malloc(aSize);
+ if (ReplaceMalloc::IsPHCAllocation(p, nullptr)) {
+ return p;
+ }
+ free(p);
+ }
+ // This failure doesn't seem to occur in practice...
+ MOZ_CRASH("failed to get a PHC allocation");
+}
+#endif
+
+#ifndef XP_WIN
+static int64_t recurse(int64_t aRandom) {
+ char buff[256] = {};
+ int64_t result = aRandom;
+
+ strncpy(buff, "This is gibberish", sizeof(buff));
+
+ for (auto& c : buff) {
+ result += c;
+ }
+
+ if (result == 0) {
+ return result;
+ }
+
+ return recurse(result) + 1;
+}
+
+static void* overflow_stack(void* aInput) {
+ int64_t result = recurse(*((int64_t*)(aInput)));
+
+ return (void*)result;
+}
+#endif // XP_WIN
+
+extern "C" NS_EXPORT void Crash(int16_t how) {
+ switch (how) {
+ case CRASH_INVALID_POINTER_DEREF: {
+ volatile int* foo = (int*)0x42;
+ *foo = 0;
+ // not reached
+ break;
+ }
+ case CRASH_PURE_VIRTUAL_CALL: {
+ PureVirtualCall();
+ // not reached
+ break;
+ }
+ case CRASH_OOM: {
+ mozilla::Unused << moz_xmalloc((size_t)-1);
+ mozilla::Unused << moz_xmalloc((size_t)-1);
+ mozilla::Unused << moz_xmalloc((size_t)-1);
+ break;
+ }
+ case CRASH_MOZ_CRASH: {
+ MOZ_CRASH();
+ break;
+ }
+ case CRASH_ABORT: {
+ abort();
+ break;
+ }
+ case CRASH_UNCAUGHT_EXCEPTION: {
+ ThrowException();
+ break;
+ }
+#if XP_WIN && HAVE_64BIT_BUILD && defined(_M_X64) && !defined(__MINGW32__)
+ case CRASH_X64CFI_UNKNOWN_OPCODE:
+ case CRASH_X64CFI_PUSH_NONVOL:
+ case CRASH_X64CFI_ALLOC_SMALL:
+ case CRASH_X64CFI_ALLOC_LARGE:
+ case CRASH_X64CFI_SAVE_NONVOL:
+ case CRASH_X64CFI_SAVE_NONVOL_FAR:
+ case CRASH_X64CFI_SAVE_XMM128:
+ case CRASH_X64CFI_SAVE_XMM128_FAR:
+ case CRASH_X64CFI_EPILOG: {
+ auto m = GetWin64CFITestMap();
+ if (m.find(how) == m.end()) {
+ break;
+ }
+ auto pfnTest = m[how];
+ auto pfnLauncher = m[CRASH_X64CFI_LAUNCHER];
+ ReserveStack();
+ pfnLauncher(0, reinterpret_cast<void*>(pfnTest));
+ break;
+ }
+#endif // XP_WIN && HAVE_64BIT_BUILD && !defined(__MINGW32__)
+#ifdef MOZ_PHC
+ case CRASH_PHC_USE_AFTER_FREE: {
+ // Do a UAF, triggering a crash.
+ uint8_t* p = GetPHCAllocation(32);
+ free(p);
+ p[0] = 0;
+ // not reached
+ }
+ case CRASH_PHC_DOUBLE_FREE: {
+ // Do a double free, triggering a crash.
+ uint8_t* p = GetPHCAllocation(64);
+ free(p);
+ free(p);
+ // not reached
+ }
+ case CRASH_PHC_BOUNDS_VIOLATION: {
+ // Do a bounds violation, triggering a crash.
+ uint8_t* p = GetPHCAllocation(96);
+ p[96] = 0;
+ // not reached
+ }
+#endif
+#if XP_WIN
+ case CRASH_HEAP_CORRUPTION: {
+ // We override the HeapFree() function in mozglue so that we can force
+ // the code calling it to use our allocator instead of the Windows one.
+ // Since we need to call the real HeapFree() we get its pointer directly.
+ HMODULE kernel32 = LoadLibraryW(L"Kernel32.dll");
+ if (kernel32) {
+ typedef BOOL (*HeapFreeT)(HANDLE, DWORD, LPVOID);
+ HeapFreeT heapFree = (HeapFreeT)GetProcAddress(kernel32, "HeapFree");
+ if (heapFree) {
+ HANDLE heap = GetProcessHeap();
+ LPVOID badPointer = (LPVOID)3;
+ heapFree(heap, 0, badPointer);
+ break; // This should be unreachable
+ }
+ }
+ }
+#endif // XP_WIN
+#ifdef XP_MACOSX
+ case CRASH_EXC_GUARD: {
+ guarded_open_np_t dl_guarded_open_np;
+ void* kernellib =
+ (void*)dlopen("/usr/lib/system/libsystem_kernel.dylib", RTLD_GLOBAL);
+ dl_guarded_open_np =
+ (guarded_open_np_t)dlsym(kernellib, "guarded_open_np");
+ const guardid_t guard = 0x123456789ABCDEFULL;
+ // Guard the file descriptor against regular close() calls
+ int fd = dl_guarded_open_np(
+ "/tmp/try.txt", &guard,
+ GUARD_CLOSE | GUARD_DUP | GUARD_SOCKET_IPC | GUARD_FILEPORT,
+ O_CREAT | O_CLOEXEC | O_RDWR, 0666);
+
+ if (fd != -1) {
+ close(fd);
+ // not reached
+ }
+ }
+#endif // XP_MACOSX
+#ifndef XP_WIN
+ case CRASH_STACK_OVERFLOW: {
+ pthread_t thread_id;
+ int64_t data = 1337;
+ int rv = pthread_create(&thread_id, nullptr, overflow_stack, &data);
+ if (!rv) {
+ pthread_join(thread_id, nullptr);
+ }
+
+ break; // This should be unreachable
+ }
+#endif // XP_WIN
+ default:
+ break;
+ }
+}
+
+char testData[32];
+
+extern "C" NS_EXPORT uint64_t SaveAppMemory() {
+ for (size_t i = 0; i < sizeof(testData); i++) testData[i] = i;
+
+ FILE* fp = fopen("crash-addr", "w");
+ if (!fp) return 0;
+ fprintf(fp, "%p\n", (void*)testData);
+ fclose(fp);
+
+ return (int64_t)testData;
+}
+
+#ifdef XP_WIN
+static LONG WINAPI HandleException(EXCEPTION_POINTERS* exinfo) {
+ TerminateProcess(GetCurrentProcess(), 0);
+ return 0;
+}
+
+extern "C" NS_EXPORT void TryOverrideExceptionHandler() {
+ SetUnhandledExceptionFilter(HandleException);
+}
+#endif
+
+extern "C" NS_EXPORT uint32_t GetWin64CFITestFnAddrOffset(int16_t fnid) {
+#if XP_WIN && HAVE_64BIT_BUILD && defined(_M_X64) && !defined(__MINGW32__)
+ // fnid uses the same constants as Crash().
+ // Returns the RVA of the requested function.
+ // Returns 0 on failure.
+ auto m = GetWin64CFITestMap();
+ if (m.find(fnid) == m.end()) {
+ return 0;
+ }
+ uint64_t moduleBase = (uint64_t)GetModuleHandleW(L"testcrasher.dll");
+ return ((uint64_t)m[fnid]) - moduleBase;
+#else
+ return 0;
+#endif // XP_WIN && HAVE_64BIT_BUILD && !defined(__MINGW32__)
+}
diff --git a/toolkit/crashreporter/test/unit/crasher_subprocess_head.js b/toolkit/crashreporter/test/unit/crasher_subprocess_head.js
new file mode 100644
index 0000000000..19525bb605
--- /dev/null
+++ b/toolkit/crashreporter/test/unit/crasher_subprocess_head.js
@@ -0,0 +1,29 @@
+// enable crash reporting first
+var cwd = Services.dirsvc.get("CurWorkD", Ci.nsIFile);
+
+// get the temp dir
+var _tmpd = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
+_tmpd.initWithPath(Services.env.get("XPCSHELL_TEST_TEMP_DIR"));
+
+// Allow `crashReporter` to be used as an alias in the tests.
+var crashReporter = Services.appinfo;
+
+// We need to call this or crash events go in an undefined location.
+Services.appinfo.UpdateCrashEventsDir();
+
+// Setting the minidump path is not allowed in content processes
+var processType = Services.appinfo.processType;
+if (processType == Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT) {
+ Services.appinfo.minidumpPath = _tmpd;
+}
+
+var protocolHandler = Services.io
+ .getProtocolHandler("resource")
+ .QueryInterface(Ci.nsIResProtocolHandler);
+var curDirURI = Services.io.newFileURI(cwd);
+protocolHandler.setSubstitution("test", curDirURI);
+const { CrashTestUtils } = ChromeUtils.importESModule(
+ "resource://test/CrashTestUtils.sys.mjs"
+);
+var crashType = CrashTestUtils.CRASH_INVALID_POINTER_DEREF;
+var shouldDelay = false;
diff --git a/toolkit/crashreporter/test/unit/crasher_subprocess_tail.js b/toolkit/crashreporter/test/unit/crasher_subprocess_tail.js
new file mode 100644
index 0000000000..c9e415b567
--- /dev/null
+++ b/toolkit/crashreporter/test/unit/crasher_subprocess_tail.js
@@ -0,0 +1,20 @@
+/* import-globals-from crasher_subprocess_head.js */
+
+// Let the event loop process a bit before crashing.
+if (shouldDelay) {
+ let shouldCrashNow = false;
+
+ Services.tm.dispatchToMainThread({
+ run: () => {
+ shouldCrashNow = true;
+ },
+ });
+
+ Services.tm.spinEventLoopUntil(
+ "Test(crasher_subprocess_tail.js:shouldDelay)",
+ () => shouldCrashNow
+ );
+}
+
+// now actually crash
+CrashTestUtils.crash(crashType);
diff --git a/toolkit/crashreporter/test/unit/head_crashreporter.js b/toolkit/crashreporter/test/unit/head_crashreporter.js
new file mode 100644
index 0000000000..c37c8acf8c
--- /dev/null
+++ b/toolkit/crashreporter/test/unit/head_crashreporter.js
@@ -0,0 +1,347 @@
+const { makeFakeAppDir } = ChromeUtils.importESModule(
+ "resource://testing-common/AppData.sys.mjs"
+);
+var { AppConstants } = ChromeUtils.importESModule(
+ "resource://gre/modules/AppConstants.sys.mjs"
+);
+
+function getEventDir() {
+ return PathUtils.join(do_get_tempdir().path, "crash-events");
+}
+
+function sendCommandAsync(command) {
+ return new Promise(resolve => {
+ sendCommand(command, resolve);
+ });
+}
+
+/*
+ * Run an xpcshell subprocess and crash it.
+ *
+ * @param setup
+ * A string of JavaScript code to execute in the subprocess
+ * before crashing. If this is a function and not a string,
+ * it will have .toSource() called on it, and turned into
+ * a call to itself. (for programmer convenience)
+ * This code will be evaluted between crasher_subprocess_head.js
+ * and crasher_subprocess_tail.js, so it will have access
+ * to everything defined in crasher_subprocess_head.js,
+ * which includes "crashReporter", a variable holding
+ * the crash reporter service.
+ *
+ * @param callback
+ * A JavaScript function to be called after the subprocess
+ * crashes. It will be passed (minidump, extra, extrafile), where
+ * - minidump is an nsIFile of the minidump file produced,
+ * - extra is an object containing the key,value pairs from
+ * the .extra file.
+ * - extrafile is an nsIFile of the extra file
+ *
+ * @param canReturnZero
+ * If true, the subprocess may return with a zero exit code.
+ * Certain types of crashes may not cause the process to
+ * exit with an error.
+ *
+ */
+async function do_crash(setup, callback, canReturnZero) {
+ // get current process filename (xpcshell)
+ let bin = Services.dirsvc.get("XREExeF", Ci.nsIFile);
+ if (!bin.exists()) {
+ // weird, can't find xpcshell binary?
+ do_throw("Can't find xpcshell binary!");
+ }
+ // get Gre dir (GreD)
+ let greD = Services.dirsvc.get("GreD", Ci.nsIFile);
+ let headfile = do_get_file("crasher_subprocess_head.js");
+ let tailfile = do_get_file("crasher_subprocess_tail.js");
+ // run xpcshell -g GreD -f head -e "some setup code" -f tail
+ let process = Cc["@mozilla.org/process/util;1"].createInstance(Ci.nsIProcess);
+ process.init(bin);
+ let args = ["-g", greD.path, "-f", headfile.path];
+ if (setup) {
+ if (typeof setup == "function") {
+ // funky, but convenient
+ setup = "(" + setup.toSource() + ")();";
+ }
+ args.push("-e", setup);
+ }
+ args.push("-f", tailfile.path);
+
+ let crashD = do_get_tempdir();
+ crashD.append("crash-events");
+ if (!crashD.exists()) {
+ crashD.create(crashD.DIRECTORY_TYPE, 0o700);
+ }
+
+ Services.env.set("CRASHES_EVENTS_DIR", crashD.path);
+
+ try {
+ process.run(true, args, args.length);
+ } catch (ex) {
+ // on Windows we exit with a -1 status when crashing.
+ } finally {
+ Services.env.set("CRASHES_EVENTS_DIR", "");
+ }
+
+ if (!canReturnZero) {
+ // should exit with an error (should have crashed)
+ Assert.notEqual(process.exitValue, 0);
+ }
+
+ await handleMinidump(callback);
+}
+
+function getMinidump() {
+ let en = do_get_tempdir().directoryEntries;
+ while (en.hasMoreElements()) {
+ let f = en.nextFile;
+ if (f.leafName.substr(-4) == ".dmp") {
+ return f;
+ }
+ }
+
+ return null;
+}
+
+function getMinidumpAnalyzerPath() {
+ const binSuffix = AppConstants.platform === "win" ? ".exe" : "";
+ const exeName = "minidump-analyzer" + binSuffix;
+
+ let exe = Services.dirsvc.get("GreBinD", Ci.nsIFile);
+ exe.append(exeName);
+
+ return exe;
+}
+
+function runMinidumpAnalyzer(dumpFile, additionalArgs) {
+ let bin = getMinidumpAnalyzerPath();
+ let process = Cc["@mozilla.org/process/util;1"].createInstance(Ci.nsIProcess);
+ process.init(bin);
+ let args = [];
+ if (additionalArgs) {
+ args = args.concat(additionalArgs);
+ }
+ args.push(dumpFile.path);
+ process.run(true /* blocking */, args, args.length);
+}
+
+async function handleMinidump(callback) {
+ // find minidump
+ let minidump = getMinidump();
+
+ if (minidump == null) {
+ do_throw("No minidump found!");
+ }
+
+ let extrafile = minidump.clone();
+ extrafile.leafName = extrafile.leafName.slice(0, -4) + ".extra";
+
+ let memoryfile = minidump.clone();
+ memoryfile.leafName = memoryfile.leafName.slice(0, -4) + ".memory.json.gz";
+
+ let cleanup = async function () {
+ for (let file of [minidump, extrafile, memoryfile]) {
+ while (file.exists()) {
+ try {
+ file.remove(false);
+ } catch (e) {
+ // On Windows the file may be locked, wait briefly and try again
+ await new Promise(resolve => do_timeout(50, resolve));
+ }
+ }
+ }
+ };
+
+ // Just in case, don't let these files linger.
+ registerCleanupFunction(cleanup);
+
+ Assert.ok(extrafile.exists());
+ let extra = await IOUtils.readJSON(extrafile.path);
+
+ if (callback) {
+ await callback(minidump, extra, extrafile, memoryfile);
+ }
+
+ await cleanup();
+}
+
+function spinEventLoop() {
+ return new Promise(resolve => {
+ executeSoon(resolve);
+ });
+}
+
+/**
+ * Helper for testing a content process crash.
+ *
+ * This variant accepts a setup function which runs in the content process
+ * to set data as needed _before_ the crash. The tail file triggers a generic
+ * crash after setup.
+ */
+async function do_content_crash(setup, callback) {
+ do_load_child_test_harness();
+
+ // Setting the minidump path won't work in the child, so we need to do
+ // that here.
+ Services.appinfo.minidumpPath = do_get_tempdir();
+
+ /* import-globals-from ../unit/crasher_subprocess_head.js */
+ /* import-globals-from ../unit/crasher_subprocess_tail.js */
+
+ let headfile = do_get_file("../unit/crasher_subprocess_head.js");
+ let tailfile = do_get_file("../unit/crasher_subprocess_tail.js");
+ if (setup) {
+ if (typeof setup == "function") {
+ // funky, but convenient
+ setup = "(" + setup.toSource() + ")();";
+ }
+ }
+
+ do_get_profile();
+ await makeFakeAppDir();
+ await sendCommandAsync('load("' + headfile.path.replace(/\\/g, "/") + '");');
+ if (setup) {
+ await sendCommandAsync(setup);
+ }
+ await sendCommandAsync('load("' + tailfile.path.replace(/\\/g, "/") + '");');
+ await spinEventLoop();
+
+ let minidump = getMinidump();
+ let id = minidump.leafName.slice(0, -4);
+ await Services.crashmanager.ensureCrashIsPresent(id);
+ try {
+ await handleMinidump(callback);
+ } catch (x) {
+ do_report_unexpected_exception(x);
+ }
+}
+
+/**
+ * Helper for testing a content process crash.
+ *
+ * This variant accepts a trigger function which runs in the content process
+ * and does something to _trigger_ the crash.
+ */
+async function do_triggered_content_crash(trigger, callback) {
+ do_load_child_test_harness();
+
+ // Setting the minidump path won't work in the child, so we need to do
+ // that here.
+ Services.appinfo.minidumpPath = do_get_tempdir();
+
+ /* import-globals-from ../unit/crasher_subprocess_head.js */
+
+ let headfile = do_get_file("../unit/crasher_subprocess_head.js");
+ if (trigger) {
+ if (typeof trigger == "function") {
+ // funky, but convenient
+ trigger = "(" + trigger.toSource() + ")();";
+ }
+ }
+
+ do_get_profile();
+ await makeFakeAppDir();
+ await sendCommandAsync('load("' + headfile.path.replace(/\\/g, "/") + '");');
+ await sendCommandAsync(trigger);
+ await spinEventLoop();
+ let id = getMinidump().leafName.slice(0, -4);
+ await Services.crashmanager.ensureCrashIsPresent(id);
+ try {
+ await handleMinidump(callback);
+ } catch (x) {
+ do_report_unexpected_exception(x);
+ }
+}
+
+/*
+ * Run the `crash` backgroundtask subprocess, crashing it in the
+ * specified manner.
+ *
+ * @param crashType Integer `CrashTestUtils.CRASH_...` code.
+ * @param crashExtras Dictionary of key-value pairs to include in
+ * minidump extras.
+ *
+ * @param callback
+ * A JavaScript function to be called after the subprocess
+ * crashes. It will be passed (minidump, extra, extrafile), where
+ * - minidump is an nsIFile of the minidump file produced,
+ * - extra is an object containing the key,value pairs from
+ * the .extra file.
+ * - extrafile is an nsIFile of the extra file
+ *
+ * @param canReturnZero
+ * If true, the subprocess may return with a zero exit code.
+ * Certain types of crashes may not cause the process to
+ * exit with an error.
+ *
+ */
+async function do_backgroundtask_crash(
+ crashType,
+ crashExtras,
+ callback,
+ canReturnZero
+) {
+ Assert.ok(AppConstants.MOZ_BACKGROUNDTASKS);
+
+ // Get full path to application (not xpcshell)
+ let bin = Services.dirsvc.get("GreBinD", Ci.nsIFile);
+ if (AppConstants.platform === "win") {
+ bin.append(AppConstants.MOZ_APP_NAME + ".exe");
+ } else {
+ bin.append(AppConstants.MOZ_APP_NAME);
+ }
+
+ // run `application --backgroundtask crash ...`.
+ let process = Cc["@mozilla.org/process/util;1"].createInstance(Ci.nsIProcess);
+ process.init(bin);
+
+ let args = ["--backgroundtask", "crash"];
+ args.push(crashType.toString());
+
+ // Sorted to be deterministic.
+ let sorted = Object.entries(crashExtras).sort((a, b) => a[0] < b[0]);
+ for (let [key, value] of sorted) {
+ args.push(key);
+ args.push(value);
+ }
+
+ let crashD = do_get_tempdir();
+ crashD.append("crash-events");
+ if (!crashD.exists()) {
+ crashD.create(crashD.DIRECTORY_TYPE, 0o700);
+ }
+
+ Services.env.set("CRASHES_EVENTS_DIR", crashD.path);
+
+ // Ensure `resource://testing-common` gets mapped.
+ let protocolHandler = Services.io
+ .getProtocolHandler("resource")
+ .QueryInterface(Ci.nsIResProtocolHandler);
+
+ let uri = protocolHandler.getSubstitution("testing-common");
+ Assert.ok(uri, "resource://testing-common is not substituted");
+
+ // The equivalent of _TESTING_MODULES_DIR in xpcshell.
+ Services.env.set("XPCSHELL_TESTING_MODULES_URI", uri.spec);
+
+ try {
+ process.run(true, args, args.length);
+ } catch (ex) {
+ // on Windows we exit with a -1 status when crashing.
+ } finally {
+ Services.env.set("CRASHES_EVENTS_DIR", "");
+ Services.env.set("XPCSHELL_TESTING_MODULES_URI", "");
+ }
+
+ if (!canReturnZero) {
+ // should exit with an error (should have crashed)
+ Assert.notEqual(process.exitValue, 0);
+ }
+
+ await handleMinidump(callback);
+}
+
+// Import binary APIs via js-ctypes.
+var { CrashTestUtils } = ChromeUtils.importESModule(
+ "resource://test/CrashTestUtils.sys.mjs"
+);
diff --git a/toolkit/crashreporter/test/unit/head_win64cfi.js b/toolkit/crashreporter/test/unit/head_win64cfi.js
new file mode 100644
index 0000000000..4df99213db
--- /dev/null
+++ b/toolkit/crashreporter/test/unit/head_win64cfi.js
@@ -0,0 +1,215 @@
+/* import-globals-from head_crashreporter.js */
+
+let gTestCrasherSyms = null;
+let gModules = null;
+
+// Returns the offset (int) of an IP with a given base address.
+// This is effectively (ip - base), except a bit more complication due to
+// Javascript's shaky handling of 64-bit integers.
+// base & ip are passed as hex strings.
+function getModuleOffset(base, ip) {
+ let i = 0;
+ // Find where the two addresses diverge, which enables us to perform a 32-bit
+ // subtraction.
+ // e.g. "0x1111111111112222"
+ // - "0x1111111111111111"
+ // becomes 2222 - 1111
+ for (; i < base.length; ++i) {
+ if (base[i] != ip[i]) {
+ break;
+ }
+ }
+ if (i == base.length) {
+ return 0;
+ }
+ let lhs2 = "0x" + base.substring(i);
+ let rhs2 = "0x" + ip.substring(i);
+ return parseInt(rhs2) - parseInt(lhs2);
+}
+
+// Uses gTestCrasherSyms to convert an address to a symbol.
+function findNearestTestCrasherSymbol(addr) {
+ addr += 1; // Breakpad sometimes offsets addresses; correct for this.
+ let closestDistance = null;
+ let closestSym = null;
+ for (let sym in gTestCrasherSyms) {
+ if (addr >= gTestCrasherSyms[sym]) {
+ let thisDistance = addr - gTestCrasherSyms[sym];
+ if (closestDistance === null || thisDistance < closestDistance) {
+ closestDistance = thisDistance;
+ closestSym = sym;
+ }
+ }
+ }
+ if (closestSym === null) {
+ return null;
+ }
+ return { symbol: closestSym, offset: closestDistance };
+}
+
+// Populate known symbols for testcrasher.dll.
+// Use the same prop names as from CrashTestUtils to avoid the need for mapping.
+function initTestCrasherSymbols() {
+ gTestCrasherSyms = {};
+ for (let k in CrashTestUtils) {
+ // Not all keys here are valid symbol names. getWin64CFITestFnAddrOffset
+ // will return 0 in those cases, no need to filter here.
+ if (Number.isInteger(CrashTestUtils[k])) {
+ let t = CrashTestUtils.getWin64CFITestFnAddrOffset(CrashTestUtils[k]);
+ if (t > 0) {
+ gTestCrasherSyms[k] = t;
+ }
+ }
+ }
+}
+
+function stackFrameToString(frameIndex, frame) {
+ // Calculate the module offset.
+ let ip = frame.ip;
+ let symbol = "";
+ let moduleOffset = "unknown_offset";
+ let filename = "unknown_module";
+
+ if (
+ typeof frame.module_index !== "undefined" &&
+ frame.module_index >= 0 &&
+ frame.module_index < gModules.length
+ ) {
+ let base = gModules[frame.module_index].base_addr;
+ moduleOffset = getModuleOffset(base, ip);
+ filename = gModules[frame.module_index].filename;
+
+ if (filename === "testcrasher.dll") {
+ let nearestSym = findNearestTestCrasherSymbol(moduleOffset);
+ if (nearestSym !== null) {
+ symbol = nearestSym.symbol + "+" + nearestSym.offset.toString(16);
+ }
+ }
+ }
+
+ let ret =
+ "frames[" +
+ frameIndex +
+ "] ip=" +
+ ip +
+ " " +
+ symbol +
+ ", module:" +
+ filename +
+ ", trust:" +
+ frame.trust +
+ ", moduleOffset:" +
+ moduleOffset.toString(16);
+ return ret;
+}
+
+function dumpStackFrames(frames, maxFrames) {
+ for (let i = 0; i < Math.min(maxFrames, frames.length); ++i) {
+ info(stackFrameToString(i, frames[i]));
+ }
+}
+
+// Test that the top of the given stack (from extra data) matches the given
+// expected frames.
+//
+// expected is { symbol: "", trust: "" }
+function assertStack(stack, expected) {
+ for (let i = 0; i < stack.length; ++i) {
+ if (i >= expected.length) {
+ ok("Top stack frames were expected");
+ return;
+ }
+ let frame = stack[i];
+ let expectedFrame = expected[i];
+ let dumpThisFrame = function () {
+ info(" Actual frame: " + stackFrameToString(i, frame));
+ info(
+ "Expected { symbol: " +
+ expectedFrame.symbol +
+ ", trust: " +
+ expectedFrame.trust +
+ "}"
+ );
+ };
+
+ if (expectedFrame.trust) {
+ if (expectedFrame.trust.startsWith("!")) {
+ // A "!" prefix on the frame trust matching is a logical "not".
+ if (frame.trust === expectedFrame.trust.substring(1)) {
+ dumpThisFrame();
+ info("Expected frame trust matched when it should not have.");
+ ok(false);
+ }
+ } else if (frame.trust !== expectedFrame.trust) {
+ dumpThisFrame();
+ info("Expected frame trust did not match.");
+ ok(false);
+ }
+ }
+
+ if (expectedFrame.symbol) {
+ if (typeof frame.module_index === "undefined") {
+ // Without a module_index, it happened in an unknown module. Currently
+ // you can't specify an expected "unknown" module.
+ info("Unknown symbol in unknown module.");
+ ok(false);
+ }
+ if (frame.module_index < 0 || frame.module_index >= gModules.length) {
+ dumpThisFrame();
+ info("Unknown module.");
+ ok(false);
+ return;
+ }
+ let base = gModules[frame.module_index].base_addr;
+ let moduleOffset = getModuleOffset(base, frame.ip);
+ let filename = gModules[frame.module_index].filename;
+ if (filename == "testcrasher.dll") {
+ let nearestSym = findNearestTestCrasherSymbol(moduleOffset);
+ if (nearestSym === null) {
+ dumpThisFrame();
+ info("Unknown symbol.");
+ ok(false);
+ return;
+ }
+
+ if (nearestSym.symbol !== expectedFrame.symbol) {
+ dumpThisFrame();
+ info("Mismatching symbol.");
+ ok(false);
+ }
+ }
+ }
+ }
+}
+
+// Performs a crash, runs minidump-analyzer, and checks expected stack analysis.
+//
+// how: The crash to perform. Constants defined in both CrashTestUtils.jsm
+// and nsTestCrasher.cpp (i.e. CRASH_X64CFI_PUSH_NONVOL)
+// expectedStack: An array of {"symbol", "trust"} where trust is "cfi",
+// "context", "scan", et al. May be null if you don't need to check the stack.
+// minidumpAnalyzerArgs: An array of additional arguments to pass to
+// minidump-analyzer.exe.
+async function do_x64CFITest(how, expectedStack, minidumpAnalyzerArgs) {
+ // Setup is run in the subprocess so we cannot use any closures.
+ let setupFn = "crashType = CrashTestUtils." + how + ";";
+
+ let callbackFn = async function (minidumpFile, extra, extraFile) {
+ runMinidumpAnalyzer(minidumpFile, minidumpAnalyzerArgs);
+
+ // Refresh updated extra data
+ extra = await IOUtils.readJSON(extraFile.path);
+
+ initTestCrasherSymbols();
+ let stackTraces = extra.StackTraces;
+ let crashingThreadIndex = stackTraces.crash_info.crashing_thread;
+ gModules = stackTraces.modules;
+ let crashingFrames = stackTraces.threads[crashingThreadIndex].frames;
+
+ dumpStackFrames(crashingFrames, 10);
+
+ assertStack(crashingFrames, expectedStack);
+ };
+
+ do_crash(setupFn, callbackFn, true, true);
+}
diff --git a/toolkit/crashreporter/test/unit/test_crash_AsyncShutdown.js b/toolkit/crashreporter/test/unit/test_crash_AsyncShutdown.js
new file mode 100644
index 0000000000..66cc937f28
--- /dev/null
+++ b/toolkit/crashreporter/test/unit/test_crash_AsyncShutdown.js
@@ -0,0 +1,75 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+// Test that AsyncShutdown report errors correctly
+
+// Note: these functions are evaluated in their own process, hence the need
+// to import modules into each function.
+
+function setup_crash() {
+ const { AsyncShutdown } = ChromeUtils.importESModule(
+ "resource://gre/modules/AsyncShutdown.sys.mjs"
+ );
+ const { PromiseUtils } = ChromeUtils.importESModule(
+ "resource://gre/modules/PromiseUtils.sys.mjs"
+ );
+
+ Services.prefs.setBoolPref("toolkit.asyncshutdown.testing", true);
+ Services.prefs.setIntPref("toolkit.asyncshutdown.crash_timeout", 10);
+
+ let TOPIC = "testing-async-shutdown-crash";
+ let phase = AsyncShutdown._getPhase(TOPIC);
+ phase.addBlocker("A blocker that is never satisfied", function () {
+ dump("Installing blocker\n");
+ let deferred = PromiseUtils.defer();
+ return deferred.promise;
+ });
+
+ Services.obs.notifyObservers(null, TOPIC);
+ dump(new Error().stack + "\n");
+ dump("Waiting for crash\n");
+}
+
+function after_crash(mdump, extra) {
+ info("after crash: " + extra.AsyncShutdownTimeout);
+ let data = JSON.parse(extra.AsyncShutdownTimeout);
+ Assert.equal(data.phase, "testing-async-shutdown-crash");
+ Assert.equal(data.conditions[0].name, "A blocker that is never satisfied");
+ // This test spawns subprocesses by using argument "-e" of xpcshell, so
+ // this is the filename known to xpcshell.
+ Assert.equal(data.conditions[0].filename, "-e");
+}
+
+// Test that AsyncShutdown + IOUtils reports errors correctly.,
+
+function setup_ioutils_crash() {
+ const { PromiseUtils } = ChromeUtils.importESModule(
+ "resource://gre/modules/PromiseUtils.sys.mjs"
+ );
+
+ Services.prefs.setIntPref("toolkit.asyncshutdown.crash_timeout", 1);
+
+ IOUtils.profileBeforeChange.addBlocker(
+ "Adding a blocker that will never be resolved",
+ () => PromiseUtils.defer().promise
+ );
+
+ Services.startup.advanceShutdownPhase(
+ Services.startup.SHUTDOWN_PHASE_APPSHUTDOWN
+ );
+ dump("Waiting for crash\n");
+}
+
+function after_ioutils_crash(mdump, extra) {
+ info("after IOUtils crash: " + extra.AsyncShutdownTimeout);
+ let data = JSON.parse(extra.AsyncShutdownTimeout);
+ Assert.equal(
+ data.phase,
+ "IOUtils: waiting for profileBeforeChange IO to complete"
+ );
+}
+
+add_task(async function run_test() {
+ await do_crash(setup_crash, after_crash);
+ await do_crash(setup_ioutils_crash, after_ioutils_crash);
+});
diff --git a/toolkit/crashreporter/test/unit/test_crash_abort.js b/toolkit/crashreporter/test/unit/test_crash_abort.js
new file mode 100644
index 0000000000..aa602dacb4
--- /dev/null
+++ b/toolkit/crashreporter/test/unit/test_crash_abort.js
@@ -0,0 +1,17 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+add_task(async function run_test() {
+ // Try crashing with an abort().
+ await do_crash(
+ function () {
+ crashType = CrashTestUtils.CRASH_ABORT;
+ crashReporter.annotateCrashReport("TestKey", "TestValue");
+ },
+ function (mdump, extra) {
+ Assert.equal(extra.TestKey, "TestValue");
+ },
+ // process will exit with a zero exit status
+ true
+ );
+});
diff --git a/toolkit/crashreporter/test/unit/test_crash_after_js_large_allocation_failure.js b/toolkit/crashreporter/test/unit/test_crash_after_js_large_allocation_failure.js
new file mode 100644
index 0000000000..611ba9b6ac
--- /dev/null
+++ b/toolkit/crashreporter/test/unit/test_crash_after_js_large_allocation_failure.js
@@ -0,0 +1,23 @@
+add_task(async function run_test() {
+ if (!("@mozilla.org/toolkit/crash-reporter;1" in Cc)) {
+ dump(
+ "INFO | test_crash_after_js_large_allocation_failure.js | Can't test crashreporter in a non-libxul build.\n"
+ );
+ return;
+ }
+
+ await do_crash(
+ function () {
+ crashType = CrashTestUtils.CRASH_MOZ_CRASH;
+ crashReporter.annotateCrashReport("TestKey", "Yes");
+ Cu.getJSTestingFunctions().reportLargeAllocationFailure();
+ Cu.forceGC();
+ },
+ function (mdump, extra) {
+ Assert.equal(extra.TestKey, "Yes");
+ Assert.equal(false, "JSOutOfMemory" in extra);
+ Assert.equal(extra.JSLargeAllocationFailure, "Recovered");
+ },
+ true
+ );
+});
diff --git a/toolkit/crashreporter/test/unit/test_crash_after_js_large_allocation_failure_reporting.js b/toolkit/crashreporter/test/unit/test_crash_after_js_large_allocation_failure_reporting.js
new file mode 100644
index 0000000000..cdae0f2d8e
--- /dev/null
+++ b/toolkit/crashreporter/test/unit/test_crash_after_js_large_allocation_failure_reporting.js
@@ -0,0 +1,27 @@
+add_task(async function run_test() {
+ if (!("@mozilla.org/toolkit/crash-reporter;1" in Cc)) {
+ dump(
+ "INFO | test_crash_after_js_oom_reporting.js | Can't test crashreporter in a non-libxul build.\n"
+ );
+ return;
+ }
+
+ await do_crash(
+ function () {
+ crashType = CrashTestUtils.CRASH_MOZ_CRASH;
+ crashReporter.annotateCrashReport("TestKey", "Yes");
+
+ function crashWhileReporting() {
+ CrashTestUtils.crash(crashType);
+ }
+
+ Services.obs.addObserver(crashWhileReporting, "memory-pressure");
+ Cu.getJSTestingFunctions().reportLargeAllocationFailure();
+ },
+ function (mdump, extra) {
+ Assert.equal(extra.TestKey, "Yes");
+ Assert.equal(extra.JSLargeAllocationFailure, "Reporting");
+ },
+ true
+ );
+});
diff --git a/toolkit/crashreporter/test/unit/test_crash_after_js_oom_recovered.js b/toolkit/crashreporter/test/unit/test_crash_after_js_oom_recovered.js
new file mode 100644
index 0000000000..7b2491bc0b
--- /dev/null
+++ b/toolkit/crashreporter/test/unit/test_crash_after_js_oom_recovered.js
@@ -0,0 +1,22 @@
+add_task(async function run_test() {
+ if (!("@mozilla.org/toolkit/crash-reporter;1" in Cc)) {
+ dump(
+ "INFO | test_crash_after_js_oom_recovered.js | Can't test crashreporter in a non-libxul build.\n"
+ );
+ return;
+ }
+
+ await do_crash(
+ function () {
+ crashType = CrashTestUtils.CRASH_MOZ_CRASH;
+ crashReporter.annotateCrashReport("TestKey", "Yes");
+ Cu.getJSTestingFunctions().reportOutOfMemory();
+ Cu.forceGC();
+ },
+ function (mdump, extra) {
+ Assert.equal(extra.TestKey, "Yes");
+ Assert.equal(extra.JSOutOfMemory, "Recovered");
+ },
+ true
+ );
+});
diff --git a/toolkit/crashreporter/test/unit/test_crash_after_js_oom_reported.js b/toolkit/crashreporter/test/unit/test_crash_after_js_oom_reported.js
new file mode 100644
index 0000000000..8796aee3c0
--- /dev/null
+++ b/toolkit/crashreporter/test/unit/test_crash_after_js_oom_reported.js
@@ -0,0 +1,36 @@
+add_task(async function run_test() {
+ if (!("@mozilla.org/toolkit/crash-reporter;1" in Cc)) {
+ dump(
+ "INFO | test_crash_after_js_oom_reported.js | Can't test crashreporter in a non-libxul build.\n"
+ );
+ return;
+ }
+
+ await do_crash(
+ function () {
+ crashType = CrashTestUtils.CRASH_MOZ_CRASH;
+ crashReporter.annotateCrashReport("TestKey", "Yes");
+
+ // GC now to avoid having it happen randomly later, which would make the
+ // test bogusly fail. See comment below.
+ Cu.forceGC();
+
+ Cu.getJSTestingFunctions().reportOutOfMemory();
+ },
+ function (mdump, extra) {
+ Assert.equal(extra.TestKey, "Yes");
+
+ // The JSOutOfMemory field is absent if the JS engine never reported OOM,
+ // "Reported" if it did, and "Recovered" if it reported OOM but
+ // subsequently completed a full GC cycle. Since this test calls
+ // reportOutOfMemory() and then crashes, we expect "Reported".
+ //
+ // Theoretically, GC can happen any time, so it is just possible that
+ // this property could be "Recovered" even if the implementation is
+ // correct. More likely, though, that indicates a bug, so only accept
+ // "Reported".
+ Assert.equal(extra.JSOutOfMemory, "Reported");
+ },
+ true
+ );
+});
diff --git a/toolkit/crashreporter/test/unit/test_crash_after_js_oom_reported_2.js b/toolkit/crashreporter/test/unit/test_crash_after_js_oom_reported_2.js
new file mode 100644
index 0000000000..ba67981444
--- /dev/null
+++ b/toolkit/crashreporter/test/unit/test_crash_after_js_oom_reported_2.js
@@ -0,0 +1,28 @@
+add_task(async function run_test() {
+ if (!("@mozilla.org/toolkit/crash-reporter;1" in Cc)) {
+ dump(
+ "INFO | test_crash_after_js_oom_reported_2.js | Can't test crashreporter in a non-libxul build.\n"
+ );
+ return;
+ }
+
+ await do_crash(
+ function () {
+ crashType = CrashTestUtils.CRASH_MOZ_CRASH;
+ crashReporter.annotateCrashReport("TestKey", "Yes");
+ Cu.getJSTestingFunctions().reportOutOfMemory();
+ Cu.forceGC(); // recover from first OOM
+ Cu.getJSTestingFunctions().reportOutOfMemory();
+ },
+ function (mdump, extra) {
+ Assert.equal(extra.TestKey, "Yes");
+
+ // Technically, GC can happen at any time, but it would be really
+ // peculiar for it to happen again heuristically right after a GC was
+ // forced. If extra.JSOutOfMemory is "Recovered" here, that's most
+ // likely a bug in the error reporting machinery.
+ Assert.equal(extra.JSOutOfMemory, "Reported");
+ },
+ true
+ );
+});
diff --git a/toolkit/crashreporter/test/unit/test_crash_backgroundtask_moz_crash.js b/toolkit/crashreporter/test/unit/test_crash_backgroundtask_moz_crash.js
new file mode 100644
index 0000000000..847e260925
--- /dev/null
+++ b/toolkit/crashreporter/test/unit/test_crash_backgroundtask_moz_crash.js
@@ -0,0 +1,25 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+add_task(async function run_test() {
+ if (!AppConstants.MOZ_BACKGROUNDTASKS) {
+ return;
+ }
+
+ // Try crashing background task with a runtime abort
+ await do_backgroundtask_crash(
+ CrashTestUtils.CRASH_MOZ_CRASH,
+ { TestKey: "TestValue" },
+ function (mdump, extra) {
+ Assert.equal(extra.TestKey, "TestValue");
+ Assert.equal(extra.BackgroundTaskMode, "1");
+ Assert.equal(extra.BackgroundTaskName, "crash");
+ Assert.equal(extra.HeadlessMode, "1");
+ Assert.equal(false, "OOMAllocationSize" in extra);
+ Assert.equal(false, "JSOutOfMemory" in extra);
+ Assert.equal(false, "JSLargeAllocationFailure" in extra);
+ },
+ // process will exit with a zero exit status
+ true
+ );
+});
diff --git a/toolkit/crashreporter/test/unit/test_crash_exc_guard.js b/toolkit/crashreporter/test/unit/test_crash_exc_guard.js
new file mode 100644
index 0000000000..f7daffe68c
--- /dev/null
+++ b/toolkit/crashreporter/test/unit/test_crash_exc_guard.js
@@ -0,0 +1,30 @@
+add_task(async function run_test() {
+ if (!("@mozilla.org/toolkit/crash-reporter;1" in Cc)) {
+ dump(
+ "INFO | test_crash_exc_guard.js | Can't test crashreporter in a non-libxul build.\n"
+ );
+ return;
+ }
+
+ // Try crashing by closing a guarded file descriptor
+ await do_crash(
+ function () {
+ crashType = CrashTestUtils.CRASH_EXC_GUARD;
+ crashReporter.annotateCrashReport("TestKey", "TestValue");
+ },
+ async function (mdump, extra, extraFile) {
+ runMinidumpAnalyzer(mdump);
+
+ // Refresh updated extra data
+ extra = await IOUtils.readJSON(extraFile.path);
+
+ Assert.equal(
+ extra.StackTraces.crash_info.type,
+ "EXC_GUARD / GUARD_TYPE_FD / GUARD_EXC_CLOSE"
+ );
+ Assert.equal(extra.TestKey, "TestValue");
+ },
+ // process will exit with a zero exit status
+ true
+ );
+});
diff --git a/toolkit/crashreporter/test/unit/test_crash_heap_corruption.js b/toolkit/crashreporter/test/unit/test_crash_heap_corruption.js
new file mode 100644
index 0000000000..0530b8b074
--- /dev/null
+++ b/toolkit/crashreporter/test/unit/test_crash_heap_corruption.js
@@ -0,0 +1,27 @@
+add_task(async function run_test() {
+ if (!("@mozilla.org/toolkit/crash-reporter;1" in Cc)) {
+ dump(
+ "INFO | test_crash_heap_corruption.js | Can't test crashreporter in a non-libxul build.\n"
+ );
+ return;
+ }
+
+ // Try crashing with a STATUS_HEAP_CORRUPTION exception
+ await do_crash(
+ function () {
+ crashType = CrashTestUtils.CRASH_HEAP_CORRUPTION;
+ crashReporter.annotateCrashReport("TestKey", "TestValue");
+ },
+ async function (mdump, extra, extraFile) {
+ runMinidumpAnalyzer(mdump);
+
+ // Refresh updated extra data
+ extra = await IOUtils.readJSON(extraFile.path);
+
+ Assert.equal(extra.StackTraces.crash_info.type, "STATUS_HEAP_CORRUPTION");
+ Assert.equal(extra.TestKey, "TestValue");
+ },
+ // process will exit with a zero exit status
+ true
+ );
+});
diff --git a/toolkit/crashreporter/test/unit/test_crash_modules.js b/toolkit/crashreporter/test/unit/test_crash_modules.js
new file mode 100644
index 0000000000..dd14e77dab
--- /dev/null
+++ b/toolkit/crashreporter/test/unit/test_crash_modules.js
@@ -0,0 +1,44 @@
+add_task(async function run_test() {
+ if (!("@mozilla.org/toolkit/crash-reporter;1" in Cc)) {
+ dump(
+ "INFO | test_crash_modules.js | Can't test crashreporter in a non-libxul build.\n"
+ );
+ return;
+ }
+
+ await do_crash(
+ function () {
+ const { ctypes } = ChromeUtils.importESModule(
+ "resource://gre/modules/ctypes.sys.mjs"
+ );
+ // Load and unload a DLL so that it will show up as unloaded in the minidump
+ let lib = ctypes.open("wininet");
+ lib.close();
+ },
+ async function (mdump, extra, extraFile) {
+ runMinidumpAnalyzer(mdump);
+
+ // Refresh updated extra data
+ extra = await IOUtils.readJSON(extraFile.path);
+
+ // Check unloaded modules
+ const unloadedModules = extra.StackTraces.unloaded_modules;
+ Assert.ok(!!unloadedModules, "The unloaded_modules field exists");
+ Assert.notEqual(unloadedModules.find(e => e.filename == "wininet.DLL"));
+
+ // Check the module signature information
+ const sigInfo = JSON.parse(extra.ModuleSignatureInfo);
+ Assert.ok(
+ !!sigInfo["Microsoft Windows"],
+ "The module signature info contains valid data"
+ );
+ Assert.greater(
+ sigInfo["Microsoft Windows"].length,
+ 0,
+ "Multiple signed binaries were found"
+ );
+ },
+ // process will exit with a zero exit status
+ true
+ );
+});
diff --git a/toolkit/crashreporter/test/unit/test_crash_moz_crash.js b/toolkit/crashreporter/test/unit/test_crash_moz_crash.js
new file mode 100644
index 0000000000..6016957d44
--- /dev/null
+++ b/toolkit/crashreporter/test/unit/test_crash_moz_crash.js
@@ -0,0 +1,17 @@
+add_task(async function run_test() {
+ // Try crashing with a runtime abort
+ await do_crash(
+ function () {
+ crashType = CrashTestUtils.CRASH_MOZ_CRASH;
+ crashReporter.annotateCrashReport("TestKey", "TestValue");
+ },
+ function (mdump, extra) {
+ Assert.equal(extra.TestKey, "TestValue");
+ Assert.equal(false, "OOMAllocationSize" in extra);
+ Assert.equal(false, "JSOutOfMemory" in extra);
+ Assert.equal(false, "JSLargeAllocationFailure" in extra);
+ },
+ // process will exit with a zero exit status
+ true
+ );
+});
diff --git a/toolkit/crashreporter/test/unit/test_crash_oom.js b/toolkit/crashreporter/test/unit/test_crash_oom.js
new file mode 100644
index 0000000000..3b32da4ab8
--- /dev/null
+++ b/toolkit/crashreporter/test/unit/test_crash_oom.js
@@ -0,0 +1,21 @@
+add_task(async function run_test() {
+ if (!("@mozilla.org/toolkit/crash-reporter;1" in Cc)) {
+ dump(
+ "INFO | test_crash_oom.js | Can't test crashreporter in a non-libxul build.\n"
+ );
+ return;
+ }
+
+ await do_crash(
+ function () {
+ crashType = CrashTestUtils.CRASH_OOM;
+ },
+ function (mdump, extra) {
+ Assert.ok("OOMAllocationSize" in extra);
+ Assert.ok(Number(extra.OOMAllocationSize) > 0);
+ Assert.ok("TotalPhysicalMemory" in extra);
+ Assert.ok(Number(extra.TotalPhysicalMemory) >= 0);
+ },
+ true
+ );
+});
diff --git a/toolkit/crashreporter/test/unit/test_crash_phc.js b/toolkit/crashreporter/test/unit/test_crash_phc.js
new file mode 100644
index 0000000000..54bc8ec34e
--- /dev/null
+++ b/toolkit/crashreporter/test/unit/test_crash_phc.js
@@ -0,0 +1,59 @@
+function check(extra, kind, size, hasFreeStack) {
+ Assert.equal(extra.PHCKind, kind);
+
+ // This is a string holding a decimal address.
+ Assert.ok(/^\d+$/.test(extra.PHCBaseAddress));
+
+ Assert.equal(extra.PHCUsableSize, size);
+
+ // These are strings holding comma-separated lists of decimal addresses.
+ // Sometimes on Mac they have a single entry.
+ Assert.ok(/^(\d+,)*\d+$/.test(extra.PHCAllocStack));
+ if (hasFreeStack) {
+ Assert.ok(/^(\d+,)*\d+$/.test(extra.PHCFreeStack));
+ } else {
+ Assert.ok(!extra.hasOwnProperty("PHCFreeStack"));
+ }
+}
+
+add_task(async function run_test() {
+ if (!("@mozilla.org/toolkit/crash-reporter;1" in Cc)) {
+ dump(
+ "INFO | test_crash_phc.js | Can't test crashreporter in a non-libxul build.\n"
+ );
+ return;
+ }
+
+ await do_crash(
+ function () {
+ crashType = CrashTestUtils.CRASH_PHC_USE_AFTER_FREE;
+ },
+ function (mdump, extra) {
+ // CRASH_PHC_USE_AFTER_FREE uses 32 for the size.
+ check(extra, "FreedPage", 32, /* hasFreeStack */ true);
+ },
+ true
+ );
+
+ await do_crash(
+ function () {
+ crashType = CrashTestUtils.CRASH_PHC_DOUBLE_FREE;
+ },
+ function (mdump, extra) {
+ // CRASH_PHC_DOUBLE_FREE uses 64 for the size.
+ check(extra, "FreedPage", 64, /* hasFreeStack */ true);
+ },
+ true
+ );
+
+ do_crash(
+ function () {
+ crashType = CrashTestUtils.CRASH_PHC_BOUNDS_VIOLATION;
+ },
+ function (mdump, extra) {
+ // CRASH_PHC_BOUNDS_VIOLATION uses 96 for the size.
+ check(extra, "GuardPage", 96, /* hasFreeStack */ false);
+ },
+ true
+ );
+});
diff --git a/toolkit/crashreporter/test/unit/test_crash_purevirtual.js b/toolkit/crashreporter/test/unit/test_crash_purevirtual.js
new file mode 100644
index 0000000000..e482eaa415
--- /dev/null
+++ b/toolkit/crashreporter/test/unit/test_crash_purevirtual.js
@@ -0,0 +1,29 @@
+add_task(async function run_test() {
+ if (!("@mozilla.org/toolkit/crash-reporter;1" in Cc)) {
+ dump(
+ "INFO | test_crash_purevirtual.js | Can't test crashreporter in a non-libxul build.\n"
+ );
+ return;
+ }
+
+ var isOSX = "nsILocalFileMac" in Ci;
+ if (isOSX) {
+ dump(
+ "INFO | test_crash_purevirtual.js | TODO: purecalls not caught on OS X\n"
+ );
+ return;
+ }
+
+ // Try crashing with a pure virtual call
+ await do_crash(
+ function () {
+ crashType = CrashTestUtils.CRASH_PURE_VIRTUAL_CALL;
+ crashReporter.annotateCrashReport("TestKey", "TestValue");
+ },
+ function (mdump, extra) {
+ Assert.equal(extra.TestKey, "TestValue");
+ },
+ // process will exit with a zero exit status
+ true
+ );
+});
diff --git a/toolkit/crashreporter/test/unit/test_crash_rust_panic.js b/toolkit/crashreporter/test/unit/test_crash_rust_panic.js
new file mode 100644
index 0000000000..dff1d6281a
--- /dev/null
+++ b/toolkit/crashreporter/test/unit/test_crash_rust_panic.js
@@ -0,0 +1,15 @@
+add_task(async function run_test() {
+ // Try crashing with a Rust panic
+ await do_crash(
+ function () {
+ Cc["@mozilla.org/xpcom/debug;1"]
+ .getService(Ci.nsIDebug2)
+ .rustPanic("OH NO");
+ },
+ function (mdump, extra) {
+ Assert.equal(extra.MozCrashReason, "OH NO");
+ },
+ // process will exit with a zero exit status
+ true
+ );
+});
diff --git a/toolkit/crashreporter/test/unit/test_crash_rust_panic_multiline.js b/toolkit/crashreporter/test/unit/test_crash_rust_panic_multiline.js
new file mode 100644
index 0000000000..3908c76a2e
--- /dev/null
+++ b/toolkit/crashreporter/test/unit/test_crash_rust_panic_multiline.js
@@ -0,0 +1,15 @@
+add_task(async function run_test() {
+ // Try crashing with a Rust panic
+ await do_crash(
+ function () {
+ Cc["@mozilla.org/xpcom/debug;1"]
+ .getService(Ci.nsIDebug2)
+ .rustPanic("OH NO\nOH NOES!");
+ },
+ function (mdump, extra) {
+ Assert.equal(extra.MozCrashReason, "OH NO\nOH NOES!");
+ },
+ // process will exit with a zero exit status
+ true
+ );
+});
diff --git a/toolkit/crashreporter/test/unit/test_crash_stack_overflow.js b/toolkit/crashreporter/test/unit/test_crash_stack_overflow.js
new file mode 100644
index 0000000000..a47c217238
--- /dev/null
+++ b/toolkit/crashreporter/test/unit/test_crash_stack_overflow.js
@@ -0,0 +1,21 @@
+add_task(async function run_test() {
+ if (!("@mozilla.org/toolkit/crash-reporter;1" in Cc)) {
+ dump(
+ "INFO | test_crash_stack_overflow.js | Can't test crashreporter in a non-libxul build.\n"
+ );
+ return;
+ }
+
+ // Try crashing by overflowing a thread's stack
+ await do_crash(
+ function () {
+ crashType = CrashTestUtils.CRASH_STACK_OVERFLOW;
+ crashReporter.annotateCrashReport("TestKey", "TestValue");
+ },
+ async function (mdump, extra, extraFile) {
+ Assert.equal(extra.TestKey, "TestValue");
+ },
+ // process will exit with a zero exit status
+ true
+ );
+});
diff --git a/toolkit/crashreporter/test/unit/test_crash_terminator.js b/toolkit/crashreporter/test/unit/test_crash_terminator.js
new file mode 100644
index 0000000000..c051a7e277
--- /dev/null
+++ b/toolkit/crashreporter/test/unit/test_crash_terminator.js
@@ -0,0 +1,39 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Test that the Shutdown Terminator report errors correctly
+
+function setup_crash() {
+ Services.prefs.setBoolPref("toolkit.terminator.testing", true);
+ Services.prefs.setIntPref("toolkit.asyncshutdown.crash_timeout", 150);
+
+ // Initialize the terminator
+ // (normally, this is done through the manifest file, but xpcshell
+ // doesn't take them into account).
+ let terminator = Cc[
+ "@mozilla.org/toolkit/shutdown-terminator;1"
+ ].createInstance(Ci.nsIObserver);
+ terminator.observe(null, "terminator-test-profile-after-change", null);
+
+ // Inform the terminator that shutdown has started
+ // Pick an arbitrary notification
+ terminator.observe(null, "terminator-test-profile-before-change", null);
+ terminator.observe(null, "terminator-test-xpcom-will-shutdown", null);
+
+ dump("Waiting (actively) for the crash\n");
+ Services.tm.spinEventLoopUntil(
+ "Test(test_crash_terminator.js:setup_crash())",
+ () => false
+ );
+}
+
+function after_crash(mdump, extra) {
+ info("Crash signature: " + JSON.stringify(extra, null, "\t"));
+ Assert.equal(extra.ShutdownProgress, "xpcom-will-shutdown");
+}
+
+add_task(async function run_test() {
+ await do_crash(setup_crash, after_crash);
+});
diff --git a/toolkit/crashreporter/test/unit/test_crash_uncaught_exception.js b/toolkit/crashreporter/test/unit/test_crash_uncaught_exception.js
new file mode 100644
index 0000000000..bfcd2b0ef2
--- /dev/null
+++ b/toolkit/crashreporter/test/unit/test_crash_uncaught_exception.js
@@ -0,0 +1,17 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+add_task(async function run_test() {
+ // Try crashing with an uncaught exception.
+ await do_crash(
+ function () {
+ crashType = CrashTestUtils.CRASH_UNCAUGHT_EXCEPTION;
+ crashReporter.annotateCrashReport("TestKey", "TestValue");
+ },
+ function (mdump, extra) {
+ Assert.equal(extra.TestKey, "TestValue");
+ },
+ // process will exit with a zero exit status
+ true
+ );
+});
diff --git a/toolkit/crashreporter/test/unit/test_crash_win64cfi_alloc_large.js b/toolkit/crashreporter/test/unit/test_crash_win64cfi_alloc_large.js
new file mode 100644
index 0000000000..a16fe20b4c
--- /dev/null
+++ b/toolkit/crashreporter/test/unit/test_crash_win64cfi_alloc_large.js
@@ -0,0 +1,6 @@
+add_task(async function run_test() {
+ await do_x64CFITest("CRASH_X64CFI_ALLOC_LARGE", [
+ { symbol: "CRASH_X64CFI_ALLOC_LARGE", trust: "context" },
+ { symbol: "CRASH_X64CFI_LAUNCHER", trust: "cfi" },
+ ]);
+});
diff --git a/toolkit/crashreporter/test/unit/test_crash_win64cfi_alloc_small.js b/toolkit/crashreporter/test/unit/test_crash_win64cfi_alloc_small.js
new file mode 100644
index 0000000000..0b321bac6f
--- /dev/null
+++ b/toolkit/crashreporter/test/unit/test_crash_win64cfi_alloc_small.js
@@ -0,0 +1,6 @@
+add_task(async function run_test() {
+ await do_x64CFITest("CRASH_X64CFI_ALLOC_SMALL", [
+ { symbol: "CRASH_X64CFI_ALLOC_SMALL", trust: "context" },
+ { symbol: "CRASH_X64CFI_LAUNCHER", trust: "cfi" },
+ ]);
+});
diff --git a/toolkit/crashreporter/test/unit/test_crash_win64cfi_epilog.js b/toolkit/crashreporter/test/unit/test_crash_win64cfi_epilog.js
new file mode 100644
index 0000000000..423b67f6f9
--- /dev/null
+++ b/toolkit/crashreporter/test/unit/test_crash_win64cfi_epilog.js
@@ -0,0 +1,6 @@
+add_task(async function run_test() {
+ await do_x64CFITest("CRASH_X64CFI_EPILOG", [
+ { symbol: "CRASH_X64CFI_EPILOG", trust: "context" },
+ { symbol: "CRASH_X64CFI_LAUNCHER", trust: "cfi" },
+ ]);
+});
diff --git a/toolkit/crashreporter/test/unit/test_crash_win64cfi_infinite_code_chain.exe b/toolkit/crashreporter/test/unit/test_crash_win64cfi_infinite_code_chain.exe
new file mode 100644
index 0000000000..5283cc5df7
--- /dev/null
+++ b/toolkit/crashreporter/test/unit/test_crash_win64cfi_infinite_code_chain.exe
Binary files differ
diff --git a/toolkit/crashreporter/test/unit/test_crash_win64cfi_infinite_code_chain.js b/toolkit/crashreporter/test/unit/test_crash_win64cfi_infinite_code_chain.js
new file mode 100644
index 0000000000..a8a900c995
--- /dev/null
+++ b/toolkit/crashreporter/test/unit/test_crash_win64cfi_infinite_code_chain.js
@@ -0,0 +1,22 @@
+add_task(async function run_test() {
+ // Test that minidump-analyzer gracefully handles chained
+ // unwind code entries that form a circular reference
+ // (infinite loop).
+ let exe = do_get_file("test_crash_win64cfi_infinite_code_chain.exe");
+ ok(exe);
+
+ // Perform a crash. The PE used for unwind info should fail, resulting in
+ // fallback behavior, calculating the first frame from thread context.
+ // Further frames would be calculated with either frame_pointer or scan trust,
+ // but should not be calculated via CFI. If we see CFI here that would be an
+ // indication that either our alternative EXE was not used, or we failed to
+ // abandon unwind info parsing.
+ await do_x64CFITest(
+ "CRASH_X64CFI_ALLOC_SMALL",
+ [
+ { symbol: "CRASH_X64CFI_ALLOC_SMALL", trust: "context" },
+ { symbol: null, trust: "!cfi" },
+ ],
+ ["--force-use-module", exe.path]
+ );
+});
diff --git a/toolkit/crashreporter/test/unit/test_crash_win64cfi_infinite_entry_chain.exe b/toolkit/crashreporter/test/unit/test_crash_win64cfi_infinite_entry_chain.exe
new file mode 100644
index 0000000000..de48576f65
--- /dev/null
+++ b/toolkit/crashreporter/test/unit/test_crash_win64cfi_infinite_entry_chain.exe
Binary files differ
diff --git a/toolkit/crashreporter/test/unit/test_crash_win64cfi_infinite_entry_chain.js b/toolkit/crashreporter/test/unit/test_crash_win64cfi_infinite_entry_chain.js
new file mode 100644
index 0000000000..de3d31f0ef
--- /dev/null
+++ b/toolkit/crashreporter/test/unit/test_crash_win64cfi_infinite_entry_chain.js
@@ -0,0 +1,22 @@
+add_task(async function run_test() {
+ // Test that minidump-analyzer gracefully handles chained
+ // IMAGE_RUNTIME_FUNCTION_ENTRY items that form a circular reference
+ // (infinite loop).
+ let exe = do_get_file("test_crash_win64cfi_infinite_entry_chain.exe");
+ ok(exe);
+
+ // Perform a crash. The PE used for unwind info should fail, resulting in
+ // fallback behavior, calculating the first frame from thread context.
+ // Further frames would be calculated with either frame_pointer or scan trust,
+ // but should not be calculated via CFI. If we see CFI here that would be an
+ // indication that either our alternative EXE was not used, or we failed to
+ // abandon unwind info parsing.
+ await do_x64CFITest(
+ "CRASH_X64CFI_ALLOC_SMALL",
+ [
+ { symbol: "CRASH_X64CFI_ALLOC_SMALL", trust: "context" },
+ { symbol: null, trust: "!cfi" },
+ ],
+ ["--force-use-module", exe.path]
+ );
+});
diff --git a/toolkit/crashreporter/test/unit/test_crash_win64cfi_invalid_exception_rva.exe b/toolkit/crashreporter/test/unit/test_crash_win64cfi_invalid_exception_rva.exe
new file mode 100644
index 0000000000..ab4ce326bd
--- /dev/null
+++ b/toolkit/crashreporter/test/unit/test_crash_win64cfi_invalid_exception_rva.exe
Binary files differ
diff --git a/toolkit/crashreporter/test/unit/test_crash_win64cfi_invalid_exception_rva.js b/toolkit/crashreporter/test/unit/test_crash_win64cfi_invalid_exception_rva.js
new file mode 100644
index 0000000000..3d1eb02011
--- /dev/null
+++ b/toolkit/crashreporter/test/unit/test_crash_win64cfi_invalid_exception_rva.js
@@ -0,0 +1,21 @@
+add_task(async function run_test() {
+ // Test that minidump-analyzer gracefully handles an invalid pointer to the
+ // exception unwind information.
+ let exe = do_get_file("test_crash_win64cfi_invalid_exception_rva.exe");
+ ok(exe);
+
+ // Perform a crash. The PE used for unwind info should fail, resulting in
+ // fallback behavior, calculating the first frame from thread context.
+ // Further frames would be calculated with either frame_pointer or scan trust,
+ // but should not be calculated via CFI. If we see CFI here that would be an
+ // indication that either our alternative EXE was not used, or we failed to
+ // abandon unwind info parsing.
+ await do_x64CFITest(
+ "CRASH_X64CFI_ALLOC_SMALL",
+ [
+ { symbol: "CRASH_X64CFI_ALLOC_SMALL", trust: "context" },
+ { symbol: null, trust: "!cfi" },
+ ],
+ ["--force-use-module", exe.path]
+ );
+});
diff --git a/toolkit/crashreporter/test/unit/test_crash_win64cfi_not_a_pe.exe b/toolkit/crashreporter/test/unit/test_crash_win64cfi_not_a_pe.exe
new file mode 100644
index 0000000000..5fa1d76ffc
--- /dev/null
+++ b/toolkit/crashreporter/test/unit/test_crash_win64cfi_not_a_pe.exe
@@ -0,0 +1 @@
+this is not a valid PE file. \ No newline at end of file
diff --git a/toolkit/crashreporter/test/unit/test_crash_win64cfi_not_a_pe.js b/toolkit/crashreporter/test/unit/test_crash_win64cfi_not_a_pe.js
new file mode 100644
index 0000000000..5fcbee9cbe
--- /dev/null
+++ b/toolkit/crashreporter/test/unit/test_crash_win64cfi_not_a_pe.js
@@ -0,0 +1,20 @@
+add_task(async function run_test() {
+ // Test that minidump-analyzer gracefully handles corrupt PE files.
+ let exe = do_get_file("test_crash_win64cfi_not_a_pe.exe");
+ ok(exe);
+
+ // Perform a crash. The PE used for unwind info should fail, resulting in
+ // fallback behavior, calculating the first frame from thread context.
+ // Further frames would be calculated with either frame_pointer or scan trust,
+ // but should not be calculated via CFI. If we see CFI here that would be an
+ // indication that either our alternative EXE was not used, or we failed to
+ // abandon unwind info parsing.
+ await do_x64CFITest(
+ "CRASH_X64CFI_ALLOC_SMALL",
+ [
+ { symbol: "CRASH_X64CFI_ALLOC_SMALL", trust: "context" },
+ { symbol: null, trust: "!cfi" },
+ ],
+ ["--force-use-module", exe.path]
+ );
+});
diff --git a/toolkit/crashreporter/test/unit/test_crash_win64cfi_push_nonvol.js b/toolkit/crashreporter/test/unit/test_crash_win64cfi_push_nonvol.js
new file mode 100644
index 0000000000..e875ab3434
--- /dev/null
+++ b/toolkit/crashreporter/test/unit/test_crash_win64cfi_push_nonvol.js
@@ -0,0 +1,6 @@
+add_task(async function run_test() {
+ await do_x64CFITest("CRASH_X64CFI_PUSH_NONVOL", [
+ { symbol: "CRASH_X64CFI_PUSH_NONVOL", trust: "context" },
+ { symbol: "CRASH_X64CFI_LAUNCHER", trust: "cfi" },
+ ]);
+});
diff --git a/toolkit/crashreporter/test/unit/test_crash_win64cfi_save_nonvol.js b/toolkit/crashreporter/test/unit/test_crash_win64cfi_save_nonvol.js
new file mode 100644
index 0000000000..9bc309834a
--- /dev/null
+++ b/toolkit/crashreporter/test/unit/test_crash_win64cfi_save_nonvol.js
@@ -0,0 +1,6 @@
+add_task(async function run_test() {
+ await do_x64CFITest("CRASH_X64CFI_SAVE_NONVOL", [
+ { symbol: "CRASH_X64CFI_SAVE_NONVOL", trust: "context" },
+ { symbol: "CRASH_X64CFI_LAUNCHER", trust: "cfi" },
+ ]);
+});
diff --git a/toolkit/crashreporter/test/unit/test_crash_win64cfi_save_nonvol_far.js b/toolkit/crashreporter/test/unit/test_crash_win64cfi_save_nonvol_far.js
new file mode 100644
index 0000000000..b87b4b35b4
--- /dev/null
+++ b/toolkit/crashreporter/test/unit/test_crash_win64cfi_save_nonvol_far.js
@@ -0,0 +1,6 @@
+add_task(async function run_test() {
+ await do_x64CFITest("CRASH_X64CFI_SAVE_NONVOL_FAR", [
+ { symbol: "CRASH_X64CFI_SAVE_NONVOL_FAR", trust: "context" },
+ { symbol: "CRASH_X64CFI_LAUNCHER", trust: "cfi" },
+ ]);
+});
diff --git a/toolkit/crashreporter/test/unit/test_crash_win64cfi_save_xmm128.js b/toolkit/crashreporter/test/unit/test_crash_win64cfi_save_xmm128.js
new file mode 100644
index 0000000000..22d09f157a
--- /dev/null
+++ b/toolkit/crashreporter/test/unit/test_crash_win64cfi_save_xmm128.js
@@ -0,0 +1,6 @@
+add_task(async function run_test() {
+ await do_x64CFITest("CRASH_X64CFI_SAVE_XMM128", [
+ { symbol: "CRASH_X64CFI_SAVE_XMM128", trust: "context" },
+ { symbol: "CRASH_X64CFI_LAUNCHER", trust: "cfi" },
+ ]);
+});
diff --git a/toolkit/crashreporter/test/unit/test_crash_win64cfi_save_xmm128_far.js b/toolkit/crashreporter/test/unit/test_crash_win64cfi_save_xmm128_far.js
new file mode 100644
index 0000000000..bd5f16baa8
--- /dev/null
+++ b/toolkit/crashreporter/test/unit/test_crash_win64cfi_save_xmm128_far.js
@@ -0,0 +1,6 @@
+add_task(async function run_test() {
+ await do_x64CFITest("CRASH_X64CFI_SAVE_XMM128_FAR", [
+ { symbol: "CRASH_X64CFI_SAVE_XMM128_FAR", trust: "context" },
+ { symbol: "CRASH_X64CFI_LAUNCHER", trust: "cfi" },
+ ]);
+});
diff --git a/toolkit/crashreporter/test/unit/test_crash_win64cfi_unknown_op.js b/toolkit/crashreporter/test/unit/test_crash_win64cfi_unknown_op.js
new file mode 100644
index 0000000000..cdcd8c2aad
--- /dev/null
+++ b/toolkit/crashreporter/test/unit/test_crash_win64cfi_unknown_op.js
@@ -0,0 +1,12 @@
+add_task(async function run_test() {
+ // In the case of an unknown unwind code or missing CFI,
+ // make certain we can still walk the stack via stack scan. The crashing
+ // function places NO_MANS_LAND on the stack so it will get picked up via
+ // stack scan.
+ await do_x64CFITest("CRASH_X64CFI_UNKNOWN_OPCODE", [
+ { symbol: "CRASH_X64CFI_UNKNOWN_OPCODE", trust: "context" },
+ // Trust may either be scan or frame_pointer; we don't really care as
+ // long as the address is expected.
+ { symbol: "CRASH_X64CFI_NO_MANS_LAND", trust: null },
+ ]);
+});
diff --git a/toolkit/crashreporter/test/unit/test_crash_with_memory_report.js b/toolkit/crashreporter/test/unit/test_crash_with_memory_report.js
new file mode 100644
index 0000000000..e10e6697df
--- /dev/null
+++ b/toolkit/crashreporter/test/unit/test_crash_with_memory_report.js
@@ -0,0 +1,49 @@
+add_task(async function run_test() {
+ if (!("@mozilla.org/toolkit/crash-reporter;1" in Cc)) {
+ dump(
+ "INFO | test_crash_oom.js | Can't test crashreporter in a non-libxul build.\n"
+ );
+ return;
+ }
+
+ // This was shamelessly copied and stripped down from do_get_profile() in
+ // head.js so that nsICrashReporter::saveMemoryReport can use a profile
+ // within the crasher subprocess.
+
+ await do_crash(
+ function () {
+ // Delay crashing so that the memory report has time to complete.
+ shouldDelay = true;
+
+ let profd = Services.env.get("XPCSHELL_TEST_PROFILE_DIR");
+ let file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
+ file.initWithPath(profd);
+
+ let provider = {
+ getFile(prop, persistent) {
+ persistent.value = true;
+ if (
+ prop == "ProfD" ||
+ prop == "ProfLD" ||
+ prop == "ProfDS" ||
+ prop == "ProfLDS" ||
+ prop == "TmpD"
+ ) {
+ return file.clone();
+ }
+ throw Components.Exception("", Cr.NS_ERROR_FAILURE);
+ },
+ QueryInterface: ChromeUtils.generateQI(["nsIDirectoryServiceProvider"]),
+ };
+ Services.dirsvc
+ .QueryInterface(Ci.nsIDirectoryService)
+ .registerProvider(provider);
+
+ crashReporter.saveMemoryReport();
+ },
+ function (mdump, extra, extrafile, memoryfile) {
+ Assert.ok(memoryfile.exists());
+ },
+ true
+ );
+});
diff --git a/toolkit/crashreporter/test/unit/test_crashreporter.js b/toolkit/crashreporter/test/unit/test_crashreporter.js
new file mode 100644
index 0000000000..d1a8b10316
--- /dev/null
+++ b/toolkit/crashreporter/test/unit/test_crashreporter.js
@@ -0,0 +1,90 @@
+function run_test() {
+ dump("INFO | test_crashreporter.js | Get crashreporter service.\n");
+ var cr = Services.appinfo;
+ Assert.ok(Services.appinfo.crashReporterEnabled);
+
+ try {
+ cr.serverURL;
+ do_throw("Getting serverURL when not set should have thrown!");
+ } catch (ex) {
+ Assert.equal(ex.result, Cr.NS_ERROR_FAILURE);
+ }
+
+ // check setting/getting serverURL
+
+ // try it with two different URLs, just for kicks
+ var testspecs = [
+ "http://example.com/submit",
+ "https://example.org/anothersubmit",
+ ];
+ for (var i = 0; i < testspecs.length; ++i) {
+ cr.serverURL = Services.io.newURI(testspecs[i]);
+ Assert.equal(cr.serverURL.spec, testspecs[i]);
+ }
+
+ // should not allow setting non-http/https URLs
+ try {
+ cr.serverURL = Services.io.newURI("ftp://example.com/submit");
+ do_throw("Setting serverURL to a non-http(s) URL should have thrown!");
+ } catch (ex) {
+ Assert.equal(ex.result, Cr.NS_ERROR_INVALID_ARG);
+ }
+
+ // check getting/setting minidumpPath
+ // it should be $TEMP by default, but I'm not sure if we can exactly test that
+ // this will at least test that it doesn't throw
+ Assert.notEqual(cr.minidumpPath.path, "");
+ var cwd = do_get_cwd();
+ cr.minidumpPath = cwd;
+ Assert.equal(cr.minidumpPath.path, cwd.path);
+
+ // Test annotateCrashReport()
+ try {
+ cr.annotateCrashReport(undefined, "");
+ do_throw(
+ "Calling annotateCrashReport() with an undefined key should have thrown!"
+ );
+ } catch (ex) {
+ Assert.equal(ex.result, Cr.NS_ERROR_INVALID_ARG);
+ }
+ try {
+ cr.annotateCrashReport("foobar", "");
+ do_throw(
+ "Calling annotateCrashReport() with a bogus key should have thrown!"
+ );
+ } catch (ex) {
+ Assert.equal(ex.result, Cr.NS_ERROR_INVALID_ARG);
+ }
+ cr.annotateCrashReport("TestKey", "testData1");
+ // Replace previous data.
+ cr.annotateCrashReport("TestKey", "testData2");
+ // Allow nul chars in annotations.
+ cr.annotateCrashReport("TestKey", "da\0ta");
+
+ cr.appendAppNotesToCrashReport("additional testData3");
+ // Add more data.
+ cr.appendAppNotesToCrashReport("additional testData4");
+
+ // Test removeCrashReportAnnotation()
+ try {
+ cr.removeCrashReportAnnotation(undefined);
+ do_throw(
+ "Calling removeCrashReportAnnotation() with an undefined key should have thrown!"
+ );
+ } catch (ex) {
+ Assert.equal(ex.result, Cr.NS_ERROR_INVALID_ARG);
+ }
+ try {
+ cr.removeCrashReportAnnotation("foobar");
+ do_throw(
+ "Calling removeCrashReportAnnotation() with a bogus key should have thrown!"
+ );
+ } catch (ex) {
+ Assert.equal(ex.result, Cr.NS_ERROR_INVALID_ARG);
+ }
+ cr.removeCrashReportAnnotation("TestKey");
+
+ // Testing setting the minidumpPath field
+ cr.minidumpPath = cwd;
+ Assert.equal(cr.minidumpPath.path, cwd.path);
+}
diff --git a/toolkit/crashreporter/test/unit/test_crashreporter_appmem.js b/toolkit/crashreporter/test/unit/test_crashreporter_appmem.js
new file mode 100644
index 0000000000..f42fe10f0c
--- /dev/null
+++ b/toolkit/crashreporter/test/unit/test_crashreporter_appmem.js
@@ -0,0 +1,13 @@
+add_task(async function run_test() {
+ await do_crash(
+ function () {
+ let appAddr = CrashTestUtils.saveAppMemory();
+ crashReporter.registerAppMemory(appAddr, 32);
+ },
+ function (mdump, extra) {
+ Assert.ok(mdump.exists());
+ Assert.ok(mdump.fileSize > 0);
+ Assert.ok(CrashTestUtils.dumpCheckMemory(mdump.path));
+ }
+ );
+});
diff --git a/toolkit/crashreporter/test/unit/test_crashreporter_crash.js b/toolkit/crashreporter/test/unit/test_crashreporter_crash.js
new file mode 100644
index 0000000000..4d0abbc2ef
--- /dev/null
+++ b/toolkit/crashreporter/test/unit/test_crashreporter_crash.js
@@ -0,0 +1,223 @@
+add_task(async function run_test() {
+ var is_win7_or_newer = false;
+ var is_windows = false;
+ var ph = Cc["@mozilla.org/network/protocol;1?name=http"].getService(
+ Ci.nsIHttpProtocolHandler
+ );
+ var match = ph.userAgent.match(/Windows NT (\d+).(\d+)/);
+ if (match) {
+ is_windows = true;
+ }
+ if (
+ match &&
+ (parseInt(match[1]) > 6 ||
+ (parseInt(match[1]) == 6 && parseInt(match[2]) >= 1))
+ ) {
+ is_win7_or_newer = true;
+ }
+
+ // try a basic crash
+ await do_content_crash(null, function (mdump, extra) {
+ Assert.ok(mdump.exists());
+ Assert.ok(mdump.fileSize > 0);
+ Assert.ok("StartupTime" in extra);
+ Assert.ok("CrashTime" in extra);
+ Assert.ok(
+ CrashTestUtils.dumpHasStream(
+ mdump.path,
+ CrashTestUtils.MD_THREAD_LIST_STREAM
+ )
+ );
+ Assert.ok(CrashTestUtils.dumpHasInstructionPointerMemory(mdump.path));
+ if (is_windows) {
+ [
+ "SystemMemoryUsePercentage",
+ "TotalVirtualMemory",
+ "AvailableVirtualMemory",
+ "AvailablePageFile",
+ "AvailablePhysicalMemory",
+ ].forEach(function (prop) {
+ Assert.ok(/^\d+$/.test(extra[prop].toString()));
+ });
+ }
+ if (is_win7_or_newer) {
+ Assert.ok(
+ CrashTestUtils.dumpHasStream(
+ mdump.path,
+ CrashTestUtils.MD_MEMORY_INFO_LIST_STREAM
+ )
+ );
+ }
+ });
+
+ // check setting some basic data
+ await do_crash(
+ function () {
+ // Add various annotations
+ crashReporter.annotateCrashReport("TestKey", "TestValue");
+ crashReporter.annotateCrashReport(
+ "TestUnicode",
+ "\u{1F4A9}\n\u{0000}Escape"
+ );
+ crashReporter.annotateCrashReport("Add-ons", "test%40mozilla.org:0.1");
+ crashReporter.appendAppNotesToCrashReport("Junk");
+ crashReporter.appendAppNotesToCrashReport("MoreJunk");
+
+ // TelemetrySession setup will trigger the session annotation
+ let { TelemetryController } = ChromeUtils.importESModule(
+ "resource://gre/modules/TelemetryController.sys.mjs"
+ );
+ TelemetryController.testSetup();
+ },
+ function (mdump, extra) {
+ Assert.equal(extra.TestKey, "TestValue");
+ Assert.equal(extra.TestUnicode, "\u{1F4A9}\n\u{0000}Escape");
+ Assert.ok(
+ extra.Notes.endsWith("JunkMoreJunk"),
+ "Should include our notes"
+ );
+ Assert.equal(extra["Add-ons"], "test%40mozilla.org:0.1");
+ const UUID_REGEX =
+ /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
+ Assert.ok(
+ "TelemetrySessionId" in extra,
+ "The TelemetrySessionId field is present in the extra file"
+ );
+ Assert.ok(
+ UUID_REGEX.test(extra.TelemetrySessionId),
+ "The TelemetrySessionId is a UUID"
+ );
+ Assert.ok(
+ !("TelemetryClientId" in extra),
+ "The TelemetryClientId field is omitted by default"
+ );
+ Assert.ok(
+ !("TelemetryServerURL" in extra),
+ "The TelemetryServerURL field is omitted by default"
+ );
+ }
+ );
+
+ await do_crash(
+ function () {
+ // Enable the FHR, official policy bypass (since we're in a test) and
+ // specify a telemetry server & client ID.
+ Services.prefs.setBoolPref(
+ "datareporting.policy.dataSubmissionPolicyBypassNotification",
+ true
+ );
+ Services.prefs.setBoolPref(
+ "datareporting.healthreport.uploadEnabled",
+ true
+ );
+ Services.prefs.setCharPref(
+ "toolkit.telemetry.server",
+ "http://a.telemetry.server"
+ );
+ Services.prefs.setIntPref("telemetry.fog.test.localhost_port", -1);
+ Services.prefs.setCharPref(
+ "toolkit.telemetry.cachedClientID",
+ "f3582dee-22b9-4d73-96d1-79ef5bf2fc24"
+ );
+
+ // TelemetrySession setup will trigger the session annotation
+ let { TelemetryController } = ChromeUtils.importESModule(
+ "resource://gre/modules/TelemetryController.sys.mjs"
+ );
+ let { TelemetrySend } = ChromeUtils.importESModule(
+ "resource://gre/modules/TelemetrySend.sys.mjs"
+ );
+ TelemetrySend.setTestModeEnabled(true);
+ TelemetryController.testSetup();
+ },
+ function (mdump, extra) {
+ Assert.ok(
+ "TelemetryClientId" in extra,
+ "The TelemetryClientId field is present when the FHR is on"
+ );
+ Assert.equal(
+ extra.TelemetryClientId,
+ "f3582dee-22b9-4d73-96d1-79ef5bf2fc24",
+ "The TelemetryClientId matches the expected value"
+ );
+ Assert.ok(
+ "TelemetryServerURL" in extra,
+ "The TelemetryServerURL field is present when the FHR is on"
+ );
+ Assert.equal(
+ extra.TelemetryServerURL,
+ "http://a.telemetry.server",
+ "The TelemetryServerURL matches the expected value"
+ );
+ }
+ );
+
+ await do_crash(
+ function () {
+ // Disable the FHR upload, no telemetry annotations should be present.
+ Services.prefs.setBoolPref(
+ "datareporting.policy.dataSubmissionPolicyBypassNotification",
+ true
+ );
+ Services.prefs.setBoolPref(
+ "datareporting.healthreport.uploadEnabled",
+ false
+ );
+
+ // TelemetrySession setup will trigger the session annotation
+ let { TelemetryController } = ChromeUtils.importESModule(
+ "resource://gre/modules/TelemetryController.sys.mjs"
+ );
+ let { TelemetrySend } = ChromeUtils.importESModule(
+ "resource://gre/modules/TelemetrySend.sys.mjs"
+ );
+ TelemetrySend.setTestModeEnabled(true);
+ TelemetryController.testSetup();
+ },
+ function (mdump, extra) {
+ Assert.ok(
+ !("TelemetryClientId" in extra),
+ "The TelemetryClientId field is omitted when FHR upload is disabled"
+ );
+ Assert.ok(
+ !("TelemetryServerURL" in extra),
+ "The TelemetryServerURL field is omitted when FHR upload is disabled"
+ );
+ }
+ );
+
+ await do_crash(
+ function () {
+ // No telemetry annotations should be present if the user has not been
+ // notified yet
+ Services.prefs.setBoolPref(
+ "datareporting.policy.dataSubmissionPolicyBypassNotification",
+ false
+ );
+ Services.prefs.setBoolPref(
+ "datareporting.healthreport.uploadEnabled",
+ true
+ );
+
+ // TelemetrySession setup will trigger the session annotation
+ let { TelemetryController } = ChromeUtils.importESModule(
+ "resource://gre/modules/TelemetryController.sys.mjs"
+ );
+ let { TelemetrySend } = ChromeUtils.importESModule(
+ "resource://gre/modules/TelemetrySend.sys.mjs"
+ );
+ TelemetrySend.setTestModeEnabled(true);
+ TelemetryController.testSetup();
+ },
+ function (mdump, extra) {
+ Assert.ok(
+ !("TelemetryClientId" in extra),
+ "The TelemetryClientId field is omitted when FHR upload is disabled"
+ );
+ Assert.ok(
+ !("TelemetryServerURL" in extra),
+ "The TelemetryServerURL field is omitted when FHR upload is disabled"
+ );
+ }
+ );
+});
diff --git a/toolkit/crashreporter/test/unit/test_event_files.js b/toolkit/crashreporter/test/unit/test_event_files.js
new file mode 100644
index 0000000000..844d7700ff
--- /dev/null
+++ b/toolkit/crashreporter/test/unit/test_event_files.js
@@ -0,0 +1,56 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+add_task(async function test_setup() {
+ do_get_profile();
+ await makeFakeAppDir();
+});
+
+add_task(async function test_main_process_crash() {
+ let cm = Services.crashmanager;
+ Assert.ok(cm, "CrashManager available.");
+
+ let basename;
+ let count = await new Promise((resolve, reject) => {
+ do_crash(
+ function () {
+ // TelemetrySession setup will trigger the session annotation
+ let { TelemetryController } = ChromeUtils.importESModule(
+ "resource://gre/modules/TelemetryController.sys.mjs"
+ );
+ TelemetryController.testSetup();
+ crashType = CrashTestUtils.CRASH_MOZ_CRASH;
+ crashReporter.annotateCrashReport("ShutdownProgress", "event-test");
+ },
+ (minidump, extra) => {
+ basename = minidump.leafName;
+ Object.defineProperty(cm, "_eventsDirs", { value: [getEventDir()] });
+ cm.aggregateEventsFiles().then(resolve, reject);
+ },
+ true
+ );
+ });
+ Assert.equal(count, 1, "A single crash event file was seen.");
+ let crashes = await cm.getCrashes();
+ Assert.equal(crashes.length, 1);
+ let crash = crashes[0];
+ Assert.ok(
+ crash.isOfType(
+ cm.processTypes[Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT],
+ cm.CRASH_TYPE_CRASH
+ )
+ );
+ Assert.equal(crash.id + ".dmp", basename, "ID recorded properly");
+ Assert.equal(crash.metadata.ShutdownProgress, "event-test");
+ Assert.ok("TelemetrySessionId" in crash.metadata);
+ Assert.ok("UptimeTS" in crash.metadata);
+ Assert.ok(
+ /^[0-9a-f]{8}\-([0-9a-f]{4}\-){3}[0-9a-f]{12}$/.test(
+ crash.metadata.TelemetrySessionId
+ )
+ );
+ Assert.ok("CrashTime" in crash.metadata);
+ Assert.ok(/^\d+$/.test(crash.metadata.CrashTime));
+});
diff --git a/toolkit/crashreporter/test/unit/test_kill.js b/toolkit/crashreporter/test/unit/test_kill.js
new file mode 100644
index 0000000000..3d8830bd22
--- /dev/null
+++ b/toolkit/crashreporter/test/unit/test_kill.js
@@ -0,0 +1,43 @@
+// Test that calling Services.processtools.kill doesn't create a crash report.
+add_task(async function run_test() {
+ if (!("@mozilla.org/toolkit/crash-reporter;1" in Cc)) {
+ dump(
+ "INFO | test_kill.js | Can't test crashreporter in a non-libxul build.\n"
+ );
+ return;
+ }
+
+ // Let's launch a child process and kill it (from within, it's simpler).
+
+ do_load_child_test_harness();
+
+ // Setting the minidump path won't work in the child, so we need to do
+ // that here.
+ Services.appinfo.minidumpPath = do_get_tempdir();
+ let headfile = do_get_file("../unit/crasher_subprocess_head.js");
+ const CRASH_THEN_WAIT =
+ "const ProcessTools = Cc['@mozilla.org/processtools-service;1'].getService(Ci.nsIProcessToolsService);\
+ console.log('Child process commiting ritual self-sacrifice');\
+ ProcessTools.kill(ProcessTools.pid);\
+ console.error('Oops, I should be dead');\
+ while (true) {} ;";
+ do_get_profile();
+ await makeFakeAppDir();
+ await sendCommandAsync('load("' + headfile.path.replace(/\\/g, "/") + '");');
+ await sendCommandAsync(CRASH_THEN_WAIT);
+
+ // Let's wait a little to give the child process a chance to create a minidump.
+ let { setTimeout } = ChromeUtils.importESModule(
+ "resource://gre/modules/Timer.sys.mjs"
+ );
+ // eslint-disable-next-line mozilla/no-arbitrary-setTimeout
+ await new Promise(resolve => setTimeout(resolve, 100));
+
+ // Now make sure that we have no minidump.
+ let minidump = getMinidump();
+ Assert.equal(
+ minidump,
+ null,
+ `There should be no minidump ${minidump == null ? "null" : minidump.path}`
+ );
+});
diff --git a/toolkit/crashreporter/test/unit/test_oom_annotation.js b/toolkit/crashreporter/test/unit/test_oom_annotation.js
new file mode 100644
index 0000000000..029497429a
--- /dev/null
+++ b/toolkit/crashreporter/test/unit/test_oom_annotation.js
@@ -0,0 +1,71 @@
+add_task(async function run_test() {
+ if (!("@mozilla.org/toolkit/crash-reporter;1" in Cc)) {
+ dump(
+ "INFO | test_crash_oom.js | Can't test crashreporter in a non-libxul build.\n"
+ );
+ return;
+ }
+
+ await do_content_crash(
+ function () {
+ crashType = CrashTestUtils.CRASH_OOM;
+ crashReporter.annotateCrashReport("TestKey", "Yes");
+ },
+ function (mdump, extra) {
+ const { AppConstants } = ChromeUtils.importESModule(
+ "resource://gre/modules/AppConstants.sys.mjs"
+ );
+ Assert.equal(extra.TestKey, "Yes");
+
+ // A list of pairs [annotation name, must be > 0]
+ let annotations;
+ switch (AppConstants.platform) {
+ case "win":
+ annotations = [
+ ["OOMAllocationSize", true],
+ ["SystemMemoryUsePercentage", false],
+ ["TotalVirtualMemory", true],
+ ["AvailableVirtualMemory", false],
+ ["TotalPageFile", false],
+ ["AvailablePageFile", false],
+ ["TotalPhysicalMemory", true],
+ ["AvailablePhysicalMemory", false],
+ ];
+ break;
+ case "linux":
+ annotations = [
+ ["OOMAllocationSize", true],
+ ["AvailablePageFile", false],
+ ["AvailablePhysicalMemory", false],
+ ["AvailableSwapMemory", false],
+ ["AvailableVirtualMemory", false],
+ ["TotalPageFile", false],
+ ["TotalPhysicalMemory", true],
+ ];
+ break;
+ case "macosx":
+ annotations = [
+ ["OOMAllocationSize", true],
+ ["AvailablePhysicalMemory", false],
+ ["AvailableSwapMemory", false],
+ ["PurgeablePhysicalMemory", false],
+ ["TotalPhysicalMemory", true],
+ ];
+ break;
+ default:
+ annotations = [];
+ }
+ for (let [label, shouldBeGreaterThanZero] of annotations) {
+ Assert.ok(label in extra, `Annotation ${label} is present`);
+
+ // All these annotations should represent non-negative numbers.
+ // A few of them (e.g. physical memory) are guaranteed to be positive.
+ if (shouldBeGreaterThanZero) {
+ Assert.ok(Number(extra[label]) > 0);
+ } else {
+ Assert.ok(Number(extra[label]) >= 0);
+ }
+ }
+ }
+ );
+});
diff --git a/toolkit/crashreporter/test/unit/test_override_exception_handler.js b/toolkit/crashreporter/test/unit/test_override_exception_handler.js
new file mode 100644
index 0000000000..1b4dec8a61
--- /dev/null
+++ b/toolkit/crashreporter/test/unit/test_override_exception_handler.js
@@ -0,0 +1,11 @@
+add_task(async function run_test() {
+ // Ensure that attempting to override the exception handler doesn't cause
+ // us to lose our exception handler.
+ await do_crash(
+ function () {
+ CrashTestUtils.TryOverrideExceptionHandler();
+ },
+ function (mdump, extra) {},
+ true
+ );
+});
diff --git a/toolkit/crashreporter/test/unit/xpcshell-phc.ini b/toolkit/crashreporter/test/unit/xpcshell-phc.ini
new file mode 100644
index 0000000000..d1d0ada544
--- /dev/null
+++ b/toolkit/crashreporter/test/unit/xpcshell-phc.ini
@@ -0,0 +1,11 @@
+[DEFAULT]
+head = head_crashreporter.js
+skip-if =
+ toolkit == "android" # 1536217
+ os == "win" && msix # https://bugzilla.mozilla.org/show_bug.cgi?id=1807922
+support-files =
+ crasher_subprocess_head.js
+ crasher_subprocess_tail.js
+
+[test_crash_phc.js]
+
diff --git a/toolkit/crashreporter/test/unit/xpcshell.ini b/toolkit/crashreporter/test/unit/xpcshell.ini
new file mode 100644
index 0000000000..8ba9e894ba
--- /dev/null
+++ b/toolkit/crashreporter/test/unit/xpcshell.ini
@@ -0,0 +1,131 @@
+[DEFAULT]
+head = head_crashreporter.js
+skip-if =
+ toolkit == 'android'
+ os == 'win' && msix # https://bugzilla.mozilla.org/show_bug.cgi?id=1807922
+support-files =
+ crasher_subprocess_head.js
+ crasher_subprocess_tail.js
+
+[test_crash_moz_crash.js]
+[test_crash_purevirtual.js]
+[test_crash_rust_panic.js]
+[test_crash_rust_panic_multiline.js]
+[test_crash_after_js_oom_reported.js]
+[test_crash_after_js_oom_recovered.js]
+[test_crash_after_js_oom_reported_2.js]
+[test_crash_after_js_large_allocation_failure.js]
+[test_crash_after_js_large_allocation_failure_reporting.js]
+[test_crash_oom.js]
+[test_oom_annotation.js]
+run-sequentially = very high failure rate in parallel
+[test_kill.js]
+
+[test_crash_abort.js]
+skip-if = os == 'win'
+
+[test_crash_uncaught_exception.js]
+
+[test_crash_with_memory_report.js]
+[test_crashreporter.js]
+[test_crashreporter_crash.js]
+run-sequentially = very high failure rate in parallel
+[test_override_exception_handler.js]
+skip-if = os != 'win'
+
+[test_crashreporter_appmem.js]
+# we need to skip this due to bug 838613
+skip-if = (os != 'win' && os != 'linux') || (os=='linux' && bits==32)
+
+[test_crash_AsyncShutdown.js]
+[test_event_files.js]
+[test_crash_terminator.js]
+
+[test_crash_backgroundtask_moz_crash.js]
+
+[test_crash_heap_corruption.js]
+skip-if = os != 'win'
+reason = Test covering Windows-specific crash type
+run-sequentially = very high failure rate in parallel
+
+[test_crash_exc_guard.js]
+skip-if = os != 'mac'
+reason = Test covering macOS-specific crash type
+
+[test_crash_modules.js]
+skip-if = os != 'win'
+reason = Test covering Windows-specific module handling
+run-sequentially = very high failure rate in parallel
+
+[test_crash_win64cfi_unknown_op.js]
+head = head_crashreporter.js head_win64cfi.js
+skip-if = !(os == 'win' && bits == 64 && processor == 'x86_64')
+reason = Windows test specific to the x86-64 architecture
+
+[test_crash_win64cfi_push_nonvol.js]
+head = head_crashreporter.js head_win64cfi.js
+skip-if = !(os == 'win' && bits == 64 && processor == 'x86_64')
+reason = Windows test specific to the x86-64 architecture
+
+[test_crash_win64cfi_alloc_small.js]
+head = head_crashreporter.js head_win64cfi.js
+skip-if = !(os == 'win' && bits == 64 && processor == 'x86_64')
+reason = Windows test specific to the x86-64 architecture
+
+[test_crash_win64cfi_alloc_large.js]
+head = head_crashreporter.js head_win64cfi.js
+skip-if = !(os == 'win' && bits == 64 && processor == 'x86_64')
+reason = Windows test specific to the x86-64 architecture
+
+[test_crash_win64cfi_save_nonvol.js]
+head = head_crashreporter.js head_win64cfi.js
+skip-if = !(os == 'win' && bits == 64 && processor == 'x86_64')
+reason = Windows test specific to the x86-64 architecture
+
+[test_crash_win64cfi_save_nonvol_far.js]
+head = head_crashreporter.js head_win64cfi.js
+skip-if = !(os == 'win' && bits == 64 && processor == 'x86_64')
+reason = Windows test specific to the x86-64 architecture
+
+[test_crash_win64cfi_save_xmm128.js]
+head = head_crashreporter.js head_win64cfi.js
+skip-if = !(os == 'win' && bits == 64 && processor == 'x86_64')
+reason = Windows test specific to the x86-64 architecture
+
+[test_crash_win64cfi_save_xmm128_far.js]
+head = head_crashreporter.js head_win64cfi.js
+skip-if = !(os == 'win' && bits == 64 && processor == 'x86_64')
+reason = Windows test specific to the x86-64 architecture
+
+[test_crash_win64cfi_epilog.js]
+head = head_crashreporter.js head_win64cfi.js
+skip-if = !(os == 'win' && bits == 64 && processor == 'x86_64')
+reason = Windows test specific to the x86-64 architecture
+
+[test_crash_win64cfi_infinite_entry_chain.js]
+head = head_crashreporter.js head_win64cfi.js
+skip-if = !(os == 'win' && bits == 64 && processor == 'x86_64')
+reason = Windows test specific to the x86-64 architecture
+support-files = test_crash_win64cfi_infinite_entry_chain.exe
+
+[test_crash_win64cfi_infinite_code_chain.js]
+head = head_crashreporter.js head_win64cfi.js
+skip-if = !(os == 'win' && bits == 64 && processor == 'x86_64')
+reason = Windows test specific to the x86-64 architecture
+support-files = test_crash_win64cfi_infinite_code_chain.exe
+
+[test_crash_win64cfi_invalid_exception_rva.js]
+head = head_crashreporter.js head_win64cfi.js
+skip-if = !(os == 'win' && bits == 64 && processor == 'x86_64')
+reason = Windows test specific to the x86-64 architecture
+support-files = test_crash_win64cfi_invalid_exception_rva.exe
+
+[test_crash_win64cfi_not_a_pe.js]
+head = head_crashreporter.js head_win64cfi.js
+skip-if = !(os == 'win' && bits == 64 && processor == 'x86_64')
+reason = Windows test specific to the x86-64 architecture
+support-files = test_crash_win64cfi_not_a_pe.exe
+
+[test_crash_stack_overflow.js]
+skip-if = os != 'linux'
+reason = Still broken on macOS and not yet supported on Windows
diff --git a/toolkit/crashreporter/test/unit_ipc/test_content_annotation.js b/toolkit/crashreporter/test/unit_ipc/test_content_annotation.js
new file mode 100644
index 0000000000..badc15c27d
--- /dev/null
+++ b/toolkit/crashreporter/test/unit_ipc/test_content_annotation.js
@@ -0,0 +1,33 @@
+/* import-globals-from ../unit/head_crashreporter.js */
+load("../unit/head_crashreporter.js");
+
+add_task(async function run_test() {
+ if (!("@mozilla.org/toolkit/crash-reporter;1" in Cc)) {
+ dump(
+ "INFO | test_content_annotation.js | Can't test crashreporter in a non-libxul build.\n"
+ );
+ return;
+ }
+
+ // TelemetrySession setup will trigger the session annotation
+ let { TelemetryController } = ChromeUtils.importESModule(
+ "resource://gre/modules/TelemetryController.sys.mjs"
+ );
+ TelemetryController.testSetup();
+
+ // Try crashing with a runtime abort
+ await do_content_crash(
+ function () {
+ crashType = CrashTestUtils.CRASH_MOZ_CRASH;
+ crashReporter.annotateCrashReport("TestKey", "TestValue");
+ crashReporter.appendAppNotesToCrashReport("!!!foo!!!");
+ },
+ function (mdump, extra) {
+ Assert.equal(extra.TestKey, "TestValue");
+ Assert.ok("ProcessType" in extra);
+ Assert.ok("StartupTime" in extra);
+ Assert.ok("TelemetrySessionId" in extra);
+ Assert.notEqual(extra.Notes.indexOf("!!!foo!!!"), -1);
+ }
+ );
+});
diff --git a/toolkit/crashreporter/test/unit_ipc/test_content_exception_time_annotation.js b/toolkit/crashreporter/test/unit_ipc/test_content_exception_time_annotation.js
new file mode 100644
index 0000000000..95205a6017
--- /dev/null
+++ b/toolkit/crashreporter/test/unit_ipc/test_content_exception_time_annotation.js
@@ -0,0 +1,21 @@
+/* import-globals-from ../unit/head_crashreporter.js */
+load("../unit/head_crashreporter.js");
+
+add_task(async function run_test() {
+ if (!("@mozilla.org/toolkit/crash-reporter;1" in Cc)) {
+ dump(
+ "INFO | test_content_annotation.js | Can't test crashreporter in a non-libxul build.\n"
+ );
+ return;
+ }
+
+ // Try crashing with an OOM
+ await do_content_crash(
+ function () {
+ crashType = CrashTestUtils.CRASH_OOM;
+ },
+ function (mdump, extra) {
+ Assert.ok("OOMAllocationSize" in extra);
+ }
+ );
+});
diff --git a/toolkit/crashreporter/test/unit_ipc/test_content_large_annotation.js b/toolkit/crashreporter/test/unit_ipc/test_content_large_annotation.js
new file mode 100644
index 0000000000..92875ccd99
--- /dev/null
+++ b/toolkit/crashreporter/test/unit_ipc/test_content_large_annotation.js
@@ -0,0 +1,25 @@
+/* import-globals-from ../unit/head_crashreporter.js */
+load("../unit/head_crashreporter.js");
+
+add_task(async function run_test() {
+ if (!("@mozilla.org/toolkit/crash-reporter;1" in Cc)) {
+ dump(
+ "INFO | test_content_large_annotation.js | Can't test crashreporter in a non-libxul build.\n"
+ );
+ return;
+ }
+
+ // Try crashing with a runtime abort
+ await do_content_crash(
+ function () {
+ crashType = CrashTestUtils.CRASH_MOZ_CRASH;
+ crashReporter.annotateCrashReport("TestKey", "a".repeat(65536));
+ },
+ function (mdump, extra) {
+ Assert.ok(
+ extra.TestKey == "a".repeat(65536),
+ "The TestKey annotation matches the expected value"
+ );
+ }
+ );
+});
diff --git a/toolkit/crashreporter/test/unit_ipc/test_content_memory_list.js b/toolkit/crashreporter/test/unit_ipc/test_content_memory_list.js
new file mode 100644
index 0000000000..733d224160
--- /dev/null
+++ b/toolkit/crashreporter/test/unit_ipc/test_content_memory_list.js
@@ -0,0 +1,33 @@
+// Any copyright is dedicated to the Public Domain.
+// http://creativecommons.org/publicdomain/zero/1.0/
+
+/* import-globals-from ../unit/head_crashreporter.js */
+load("../unit/head_crashreporter.js");
+
+add_task(async function run_test() {
+ var is_win7_or_newer = false;
+ var ph = Cc["@mozilla.org/network/protocol;1?name=http"].getService(
+ Ci.nsIHttpProtocolHandler
+ );
+ var match = ph.userAgent.match(/Windows NT (\d+).(\d+)/);
+ if (
+ match &&
+ (parseInt(match[1]) > 6 ||
+ (parseInt(match[1]) == 6 && parseInt(match[2]) >= 1))
+ ) {
+ is_win7_or_newer = true;
+ }
+
+ await do_content_crash(null, function (mdump, extra) {
+ Assert.ok(mdump.exists());
+ Assert.ok(mdump.fileSize > 0);
+ if (is_win7_or_newer) {
+ Assert.ok(
+ CrashTestUtils.dumpHasStream(
+ mdump.path,
+ CrashTestUtils.MD_MEMORY_INFO_LIST_STREAM
+ )
+ );
+ }
+ });
+});
diff --git a/toolkit/crashreporter/test/unit_ipc/test_content_oom_annotation.js b/toolkit/crashreporter/test/unit_ipc/test_content_oom_annotation.js
new file mode 100644
index 0000000000..d17e01f5f5
--- /dev/null
+++ b/toolkit/crashreporter/test/unit_ipc/test_content_oom_annotation.js
@@ -0,0 +1,33 @@
+/* import-globals-from ../unit/head_crashreporter.js */
+load("../unit/head_crashreporter.js");
+
+add_task(async function run_test() {
+ if (!("@mozilla.org/toolkit/crash-reporter;1" in Cc)) {
+ dump(
+ "INFO | test_content_annotation.js | Can't test crashreporter in a non-libxul build.\n"
+ );
+ return;
+ }
+
+ // Try crashing with an OOM
+ await do_content_crash(
+ function () {
+ crashType = CrashTestUtils.CRASH_OOM;
+ },
+ function (mdump, extra) {
+ Assert.ok("TotalPhysicalMemory" in extra);
+ Assert.ok("AvailablePhysicalMemory" in extra);
+
+ if (mozinfo.os == "win") {
+ Assert.ok("SystemMemoryUsePercentage" in extra);
+ Assert.ok("TotalVirtualMemory" in extra);
+ Assert.ok("AvailableVirtualMemory" in extra);
+ Assert.ok("TotalPageFile" in extra);
+ Assert.ok("AvailablePageFile" in extra);
+ } else if (mozinfo.os == "linux") {
+ Assert.ok("TotalPageFile" in extra);
+ Assert.ok("AvailablePageFile" in extra);
+ }
+ }
+ );
+});
diff --git a/toolkit/crashreporter/test/unit_ipc/test_content_phc.js b/toolkit/crashreporter/test/unit_ipc/test_content_phc.js
new file mode 100644
index 0000000000..1b54448135
--- /dev/null
+++ b/toolkit/crashreporter/test/unit_ipc/test_content_phc.js
@@ -0,0 +1,31 @@
+/* import-globals-from ../unit/head_crashreporter.js */
+load("../unit/head_crashreporter.js");
+
+add_task(async function run_test() {
+ if (!("@mozilla.org/toolkit/crash-reporter;1" in Cc)) {
+ dump(
+ "INFO | test_content_phc.js | Can't test crashreporter in a non-libxul build.\n"
+ );
+ return;
+ }
+
+ await do_content_crash(
+ function () {
+ crashType = CrashTestUtils.CRASH_PHC_USE_AFTER_FREE;
+ },
+ function (mdump, extra) {
+ Assert.equal(extra.PHCKind, "FreedPage");
+
+ // This is a string holding a decimal address.
+ Assert.ok(/^\d+$/.test(extra.PHCBaseAddress));
+
+ // CRASH_PHC_USE_AFTER_FREE uses 32 for the size.
+ Assert.equal(extra.PHCUsableSize, 32);
+
+ // These are strings holding comma-separated lists of decimal addresses.
+ // Sometimes on Mac they have a single entry.
+ Assert.ok(/^(\d+,)*\d+$/.test(extra.PHCAllocStack));
+ Assert.ok(/^(\d+,)*\d+$/.test(extra.PHCFreeStack));
+ }
+ );
+});
diff --git a/toolkit/crashreporter/test/unit_ipc/test_content_phc2.js b/toolkit/crashreporter/test/unit_ipc/test_content_phc2.js
new file mode 100644
index 0000000000..0db9165b14
--- /dev/null
+++ b/toolkit/crashreporter/test/unit_ipc/test_content_phc2.js
@@ -0,0 +1,34 @@
+/* import-globals-from ../unit/head_crashreporter.js */
+load("../unit/head_crashreporter.js");
+
+add_task(async function run_test() {
+ if (!("@mozilla.org/toolkit/crash-reporter;1" in Cc)) {
+ dump(
+ "INFO | test_content_phc.js | Can't test crashreporter in a non-libxul build.\n"
+ );
+ return;
+ }
+
+ // For some unknown reason, having multiple do_content_crash() calls in a
+ // single test doesn't work. That explains why this test exists separately
+ // from test_content_phc.js.
+ await do_content_crash(
+ function () {
+ crashType = CrashTestUtils.CRASH_PHC_DOUBLE_FREE;
+ },
+ function (mdump, extra) {
+ Assert.equal(extra.PHCKind, "FreedPage");
+
+ // This is a string holding a decimal address.
+ Assert.ok(/^\d+$/.test(extra.PHCBaseAddress));
+
+ // CRASH_PHC_DOUBLE_FREE uses 64 for the size.
+ Assert.equal(extra.PHCUsableSize, 64);
+
+ // These are strings holding comma-separated lists of decimal addresses.
+ // Sometimes on Mac they have a single entry.
+ Assert.ok(/^(\d+,)*\d+$/.test(extra.PHCAllocStack));
+ Assert.ok(/^(\d+,)*\d+$/.test(extra.PHCFreeStack));
+ }
+ );
+});
diff --git a/toolkit/crashreporter/test/unit_ipc/test_content_phc3.js b/toolkit/crashreporter/test/unit_ipc/test_content_phc3.js
new file mode 100644
index 0000000000..ab6b81f834
--- /dev/null
+++ b/toolkit/crashreporter/test/unit_ipc/test_content_phc3.js
@@ -0,0 +1,35 @@
+/* import-globals-from ../unit/head_crashreporter.js */
+load("../unit/head_crashreporter.js");
+
+add_task(async function run_test() {
+ if (!("@mozilla.org/toolkit/crash-reporter;1" in Cc)) {
+ dump(
+ "INFO | test_content_phc.js | Can't test crashreporter in a non-libxul build.\n"
+ );
+ return;
+ }
+
+ // For some unknown reason, having multiple do_content_crash() calls in a
+ // single test doesn't work. That explains why this test exists separately
+ // from test_content_phc.js.
+ await do_content_crash(
+ function () {
+ crashType = CrashTestUtils.CRASH_PHC_BOUNDS_VIOLATION;
+ },
+ function (mdump, extra) {
+ Assert.equal(extra.PHCKind, "GuardPage");
+
+ // This is a string holding a decimal address.
+ Assert.ok(/^\d+$/.test(extra.PHCBaseAddress));
+
+ // CRASH_PHC_BOUNDS_VIOLATION uses 96 for the size.
+ Assert.equal(extra.PHCUsableSize, 96);
+
+ // This is a string holding a comma-separated list of decimal addresses.
+ // Sometimes on Mac it has a single entry.
+ Assert.ok(/^(\d+,)*\d+$/.test(extra.PHCAllocStack));
+
+ Assert.ok(!extra.hasOwnProperty("PHCFreeStack"));
+ }
+ );
+});
diff --git a/toolkit/crashreporter/test/unit_ipc/test_content_rust_panic.js b/toolkit/crashreporter/test/unit_ipc/test_content_rust_panic.js
new file mode 100644
index 0000000000..91b9b86bb6
--- /dev/null
+++ b/toolkit/crashreporter/test/unit_ipc/test_content_rust_panic.js
@@ -0,0 +1,23 @@
+/* import-globals-from ../unit/head_crashreporter.js */
+load("../unit/head_crashreporter.js");
+
+add_task(async function run_test() {
+ if (!("@mozilla.org/toolkit/crash-reporter;1" in Cc)) {
+ dump(
+ "INFO | test_content_rust_panic.js | Can't test crashreporter in a non-libxul build.\n"
+ );
+ return;
+ }
+
+ // Try crashing with a Rust panic
+ await do_triggered_content_crash(
+ function () {
+ Cc["@mozilla.org/xpcom/debug;1"]
+ .getService(Ci.nsIDebug2)
+ .rustPanic("OH NO");
+ },
+ function (mdump, extra) {
+ Assert.equal(extra.MozCrashReason, "OH NO");
+ }
+ );
+});
diff --git a/toolkit/crashreporter/test/unit_ipc/test_content_rust_panic_multiline.js b/toolkit/crashreporter/test/unit_ipc/test_content_rust_panic_multiline.js
new file mode 100644
index 0000000000..393afa42ab
--- /dev/null
+++ b/toolkit/crashreporter/test/unit_ipc/test_content_rust_panic_multiline.js
@@ -0,0 +1,23 @@
+/* import-globals-from ../unit/head_crashreporter.js */
+load("../unit/head_crashreporter.js");
+
+add_task(async function run_test() {
+ if (!("@mozilla.org/toolkit/crash-reporter;1" in Cc)) {
+ dump(
+ "INFO | test_content_rust_panic.js | Can't test crashreporter in a non-libxul build.\n"
+ );
+ return;
+ }
+
+ // Try crashing with a Rust panic
+ await do_triggered_content_crash(
+ function () {
+ Cc["@mozilla.org/xpcom/debug;1"]
+ .getService(Ci.nsIDebug2)
+ .rustPanic("OH NO\nOH NOES!");
+ },
+ function (mdump, extra) {
+ Assert.equal(extra.MozCrashReason, "OH NO\nOH NOES!");
+ }
+ );
+});
diff --git a/toolkit/crashreporter/test/unit_ipc/xpcshell-phc.ini b/toolkit/crashreporter/test/unit_ipc/xpcshell-phc.ini
new file mode 100644
index 0000000000..45a5b1108d
--- /dev/null
+++ b/toolkit/crashreporter/test/unit_ipc/xpcshell-phc.ini
@@ -0,0 +1,11 @@
+[DEFAULT]
+head =
+skip-if = toolkit == "android" # 1536217
+support-files =
+ !/toolkit/crashreporter/test/unit/crasher_subprocess_head.js
+ !/toolkit/crashreporter/test/unit/crasher_subprocess_tail.js
+ !/toolkit/crashreporter/test/unit/head_crashreporter.js
+
+[test_content_phc.js]
+[test_content_phc2.js]
+[test_content_phc3.js]
diff --git a/toolkit/crashreporter/test/unit_ipc/xpcshell.ini b/toolkit/crashreporter/test/unit_ipc/xpcshell.ini
new file mode 100644
index 0000000000..af8d1c21c4
--- /dev/null
+++ b/toolkit/crashreporter/test/unit_ipc/xpcshell.ini
@@ -0,0 +1,17 @@
+[DEFAULT]
+run-sequentially = very high failure rate in parallel
+head =
+skip-if = toolkit == 'android'
+support-files =
+ !/toolkit/crashreporter/test/unit/crasher_subprocess_head.js
+ !/toolkit/crashreporter/test/unit/crasher_subprocess_tail.js
+ !/toolkit/crashreporter/test/unit/head_crashreporter.js
+
+[test_content_annotation.js]
+[test_content_large_annotation.js]
+[test_content_exception_time_annotation.js]
+[test_content_oom_annotation.js]
+[test_content_memory_list.js]
+skip-if = os != 'win'
+[test_content_rust_panic.js]
+[test_content_rust_panic_multiline.js]
diff --git a/toolkit/crashreporter/test/win64UnwindInfoTests.asm b/toolkit/crashreporter/test/win64UnwindInfoTests.asm
new file mode 100644
index 0000000000..4dd5ce7646
--- /dev/null
+++ b/toolkit/crashreporter/test/win64UnwindInfoTests.asm
@@ -0,0 +1,378 @@
+; 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/.
+
+; Comments indicate stack memory layout during execution.
+; For example at the top of a function, where RIP just points to the return
+; address, the stack looks like
+; rip = [ra]
+; And after pushing rax to the stack,
+; rip = [rax][ra]
+; And then, after allocating 20h bytes on the stack,
+; rip = [..20..][rax][ra]
+; And then, after pushing a function pointer,
+; rip = [pfn][..20..][rax][ra]
+
+include ksamd64.inc
+
+.code
+
+; It helps to add padding between functions so they're not right up against
+; each other. Adds clarity to debugging, and gives a bit of leeway when
+; searching for symbols (e.g. a function whose last instruction is CALL
+; would push a return address that's in the next function.)
+PaddingBetweenFunctions macro
+ repeat 10h
+ int 3
+ endm
+endm
+
+DoCrash macro
+ mov rax, 7
+ mov byte ptr [rax], 9
+endm
+
+PaddingBetweenFunctions
+
+; There is no rip addressing mode in x64. The only way to get the value
+; of rip is to call a function, and pop it from the stack.
+WhoCalledMe proc
+ pop rax ; rax is now ra
+ push rax ; Restore ra so this function can return.
+ sub rax, 5 ; Correct for the size of the call instruction
+ ret
+WhoCalledMe endp
+
+PaddingBetweenFunctions
+
+; Any function that we expect to test against on the stack, we'll need its
+; real address. If we use function pointers in C, we'll get the address to jump
+; table entries. This bit of code at the beginning of each function will
+; return the real address we'd expect to see in stack traces.
+;
+; rcx (1st arg) = mode
+; rax (return) = address of either NO_MANS_LAND or this function.
+;
+; When mode is 0, we place the address of NO_MANS_LAND in RAX, for the function
+; to use as it wants. This is just for convenience because almost all functions
+; here need this address at some point.
+;
+; When mode is 1, the address of this function is returned.
+TestHeader macro
+ call WhoCalledMe
+ test rcx, rcx
+ je continue_test
+ ret
+continue_test:
+ inc rcx
+ call x64CrashCFITest_NO_MANS_LAND
+ xor rcx, rcx
+endm
+
+; The point of this is to add a stack frame to test against.
+; void* x64CrashCFITest_Launcher(int getAddress, void* pTestFn)
+x64CrashCFITest_Launcher proc frame
+ TestHeader
+
+ .endprolog
+ call rdx
+ ret
+x64CrashCFITest_Launcher endp
+
+PaddingBetweenFunctions
+
+; void* x64CrashCFITest_NO_MANS_LAND(uint64_t mode);
+; Not meant to be called. Only when mode = 1 in order to return its address.
+; Place this function's address on the stack so the stack scanning algorithm
+; thinks this is a return address, and places it on the stack trace.
+x64CrashCFITest_NO_MANS_LAND proc frame
+ TestHeader
+ .endprolog
+ ret
+x64CrashCFITest_NO_MANS_LAND endp
+
+PaddingBetweenFunctions
+
+; Test that we:
+; - handle unknown opcodes gracefully
+; - fall back to other stack unwind strategies if CFI doesn't work
+;
+; In order to properly unwind this frame, we'd need to fully support
+; SET_FPREG with offsets, plus restoring registers via PUSH_NONVOL.
+; To do this, sprinkle the stack with bad return addresses
+; and stack pointers.
+x64CrashCFITest_UnknownOpcode proc frame
+ TestHeader
+
+ push rax
+ .allocstack 8
+
+ push rbp
+ .pushreg rbp
+
+ push rax
+ push rsp
+ push rax
+ push rsp
+ .allocstack 20h
+ ; rsp = [rsp][pfn][rsp][pfn][rbp][pfn][ra]
+
+ lea rbp, [rsp+10h]
+ .setframe rbp, 10h
+ ; rsp = [rsp][pfn] [rsp][pfn][rbp][pfn][ra]
+ ; rbp = ^
+
+ .endprolog
+
+ ; Now modify RSP so measuring stack size from unwind ops will not help
+ ; finding the return address.
+ push rax
+ push rsp
+ ; rsp = [rsp][pfn][rsp][pfn] [rsp][pfn][rbp][pfn][ra]
+
+ DoCrash
+
+x64CrashCFITest_UnknownOpcode endp
+
+PaddingBetweenFunctions
+
+; void* x64CrashCFITest_PUSH_NONVOL(uint64_t mode);
+;
+; Test correct handling of PUSH_NONVOL unwind code.
+;
+x64CrashCFITest_PUSH_NONVOL proc frame
+ TestHeader
+
+ push r10
+ .pushreg r10
+ push r15
+ .pushreg r15
+ push rbx
+ .pushreg rbx
+ push rsi
+ .pushreg rsi
+ push rbp
+ .pushreg rbp
+ ; rsp = [rbp][rsi][rbx][r15][r10][ra]
+
+ push rax
+ .allocstack 8
+ ; rsp = [pfn][rbp][rsi][rbx][r15][r10][ra]
+
+ .endprolog
+
+ DoCrash
+
+x64CrashCFITest_PUSH_NONVOL endp
+
+PaddingBetweenFunctions
+
+; void* x64CrashCFITest_ALLOC_SMALL(uint64_t mode);
+;
+; Small allocations are between 8bytes and 512kb-8bytes
+;
+x64CrashCFITest_ALLOC_SMALL proc frame
+ TestHeader
+
+ push rax
+ push rax
+ push rax
+ push rax
+ .allocstack 20h
+ ; rsp = [pfn][pfn][pfn][pfn][ra]
+
+ .endprolog
+
+ DoCrash
+
+x64CrashCFITest_ALLOC_SMALL endp
+
+PaddingBetweenFunctions
+
+; void* x64CrashCFITest_ALLOC_LARGE(uint64_t mode);
+;
+; Allocations between 512kb and 4gb
+; Note: ReserveStackSpace() in nsTestCrasher.cpp pre-allocates stack
+; space for this.
+x64CrashCFITest_ALLOC_LARGE proc frame
+ TestHeader
+
+ sub rsp, 0a000h
+ .allocstack 0a000h
+ ; rsp = [..640kb..][ra]
+
+ mov qword ptr [rsp], rax
+ ; rsp = [pfn][..640kb-8..][ra]
+
+ .endprolog
+
+ DoCrash
+
+x64CrashCFITest_ALLOC_LARGE endp
+
+PaddingBetweenFunctions
+
+; void* x64CrashCFITest_SAVE_NONVOL(uint64_t mode);
+;
+; Test correct handling of SAVE_NONVOL unwind code.
+;
+x64CrashCFITest_SAVE_NONVOL proc frame
+ TestHeader
+
+ sub rsp, 30h
+ .allocstack 30h
+ ; rsp = [..30..][ra]
+
+ mov qword ptr [rsp+28h], r10
+ .savereg r10, 28h
+ mov qword ptr [rsp+20h], rbp
+ .savereg rbp, 20h
+ mov qword ptr [rsp+18h], rsi
+ .savereg rsi, 18h
+ mov qword ptr [rsp+10h], rbx
+ .savereg rbx, 10h
+ mov qword ptr [rsp+8], r15
+ .savereg r15, 8
+ ; rsp = [r15][rbx][rsi][rbp][r10][ra]
+
+ mov qword ptr [rsp], rax
+
+ ; rsp = [pfn][r15][rbx][rsi][rbp][r10][ra]
+
+ .endprolog
+
+ DoCrash
+
+x64CrashCFITest_SAVE_NONVOL endp
+
+PaddingBetweenFunctions
+
+; void* x64CrashCFITest_SAVE_NONVOL_FAR(uint64_t mode);
+;
+; Similar to the test above but adding 640kb to most offsets.
+; Note: ReserveStackSpace() in nsTestCrasher.cpp pre-allocates stack
+; space for this.
+x64CrashCFITest_SAVE_NONVOL_FAR proc frame
+ TestHeader
+
+ sub rsp, 0a0030h
+ .allocstack 0a0030h
+ ; rsp = [..640k..][..30..][ra]
+
+ mov qword ptr [rsp+28h+0a0000h], r10
+ .savereg r10, 28h+0a0000h
+ mov qword ptr [rsp+20h+0a0000h], rbp
+ .savereg rbp, 20h+0a0000h
+ mov qword ptr [rsp+18h+0a0000h], rsi
+ .savereg rsi, 18h+0a0000h
+ mov qword ptr [rsp+10h+0a0000h], rbx
+ .savereg rbx, 10h+0a0000h
+ mov qword ptr [rsp+8+0a0000h], r15
+ .savereg r15, 8+0a0000h
+ ; rsp = [..640k..][..8..][r15][rbx][rsi][rbp][r10][ra]
+
+ mov qword ptr [rsp], rax
+
+ ; rsp = [pfn][..640k..][r15][rbx][rsi][rbp][r10][ra]
+
+ .endprolog
+
+ DoCrash
+
+x64CrashCFITest_SAVE_NONVOL_FAR endp
+
+PaddingBetweenFunctions
+
+; void* x64CrashCFITest_SAVE_XMM128(uint64_t mode);
+;
+; Test correct handling of SAVE_XMM128 unwind code.
+x64CrashCFITest_SAVE_XMM128 proc frame
+ TestHeader
+
+ sub rsp, 30h
+ .allocstack 30h
+ ; rsp = [..30..][ra]
+
+ movdqu [rsp+20h], xmm6
+ .savexmm128 xmm6, 20h
+ ; rsp = [..20..][xmm6][ra]
+
+ movdqu [rsp+10h], xmm15
+ .savexmm128 xmm15, 10h
+ ; rsp = [..10..][xmm15][xmm6][ra]
+
+ mov qword ptr [rsp], rax
+ ; rsp = [pfn][..8..][xmm15][xmm6][ra]
+
+ .endprolog
+
+ DoCrash
+
+x64CrashCFITest_SAVE_XMM128 endp
+
+PaddingBetweenFunctions
+
+; void* x64CrashCFITest_SAVE_XMM128(uint64_t mode);
+;
+; Similar to the test above but adding 640kb to most offsets.
+; Note: ReserveStackSpace() in nsTestCrasher.cpp pre-allocates stack
+; space for this.
+x64CrashCFITest_SAVE_XMM128_FAR proc frame
+ TestHeader
+
+ sub rsp, 0a0030h
+ .allocstack 0a0030h
+ ; rsp = [..640kb..][..30..][ra]
+
+ movdqu [rsp+20h+0a0000h], xmm6
+ .savexmm128 xmm6, 20h+0a0000h
+ ; rsp = [..640kb..][..20..][xmm6][ra]
+
+ movdqu [rsp+10h+0a0000h], xmm6
+ .savexmm128 xmm15, 10h+0a0000h
+ ; rsp = [..640kb..][..10..][xmm15][xmm6][ra]
+
+ mov qword ptr [rsp], rax
+ ; rsp = [pfn][..640kb..][..8..][xmm15][xmm6][ra]
+
+ .endprolog
+
+ DoCrash
+
+x64CrashCFITest_SAVE_XMM128_FAR endp
+
+PaddingBetweenFunctions
+
+; void* x64CrashCFITest_EPILOG(uint64_t mode);
+;
+; The epilog unwind op will also set the unwind version to 2.
+; Test that we don't choke on UWOP_EPILOG or version 2 unwind info.
+x64CrashCFITest_EPILOG proc frame
+ TestHeader
+
+ push rax
+ .allocstack 8
+ ; rsp = [pfn][ra]
+
+ .endprolog
+
+ DoCrash
+
+ .beginepilog
+
+ ret
+
+x64CrashCFITest_EPILOG endp
+
+PaddingBetweenFunctions
+
+; Having an EOF symbol at the end of this file contains symbolication to this
+; file. So addresses beyond this file don't get mistakenly symbolicated as a
+; meaningful function name.
+x64CrashCFITest_EOF proc frame
+ TestHeader
+ .endprolog
+ ret
+x64CrashCFITest_EOF endp
+
+end
diff --git a/toolkit/crashreporter/tools/python.ini b/toolkit/crashreporter/tools/python.ini
new file mode 100644
index 0000000000..d715bfe094
--- /dev/null
+++ b/toolkit/crashreporter/tools/python.ini
@@ -0,0 +1,3 @@
+[DEFAULT]
+
+[unit-symbolstore.py]
diff --git a/toolkit/crashreporter/tools/symbolstore.py b/toolkit/crashreporter/tools/symbolstore.py
new file mode 100755
index 0000000000..5dd5570a84
--- /dev/null
+++ b/toolkit/crashreporter/tools/symbolstore.py
@@ -0,0 +1,1096 @@
+#!/bin/env 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/.
+#
+# Usage: symbolstore.py <params> <dump_syms path> <symbol store path>
+# <debug info files or dirs>
+# Runs dump_syms on each debug info file specified on the command line,
+# then places the resulting symbol file in the proper directory
+# structure in the symbol store path. Accepts multiple files
+# on the command line, so can be called as part of a pipe using
+# find <dir> | xargs symbolstore.pl <dump_syms> <storepath>
+# But really, you might just want to pass it <dir>.
+#
+# Parameters accepted:
+# -c : Copy debug info files to the same directory structure
+# as sym files. On Windows, this will also copy
+# binaries into the symbol store.
+# -a "<archs>" : Run dump_syms -a <arch> for each space separated
+# cpu architecture in <archs> (only on OS X)
+# -s <srcdir> : Use <srcdir> as the top source directory to
+# generate relative filenames.
+
+import ctypes
+import errno
+import os
+import platform
+import re
+import shutil
+import subprocess
+import sys
+import textwrap
+import time
+from optparse import OptionParser
+from pathlib import Path
+
+import buildconfig
+from mozbuild.generated_sources import (
+ GENERATED_SOURCE_EXTS,
+ get_filename_with_digest,
+ get_s3_region_and_bucket,
+)
+from mozbuild.util import memoize
+from mozpack import executables
+from mozpack.copier import FileRegistry
+from mozpack.manifests import InstallManifest, UnreadableInstallManifest
+
+# Utility classes
+
+
+class VCSFileInfo:
+ """A base class for version-controlled file information. Ensures that the
+ following attributes are generated only once (successfully):
+
+ self.root
+ self.clean_root
+ self.revision
+ self.filename
+
+ The attributes are generated by a single call to the GetRoot,
+ GetRevision, and GetFilename methods. Those methods are explicitly not
+ implemented here and must be implemented in derived classes."""
+
+ def __init__(self, file):
+ if not file:
+ raise ValueError
+ self.file = file
+
+ def __getattr__(self, name):
+ """__getattr__ is only called for attributes that are not set on self,
+ so setting self.[attr] will prevent future calls to the GetRoot,
+ GetRevision, and GetFilename methods. We don't set the values on
+ failure on the off chance that a future call might succeed."""
+
+ if name == "root":
+ root = self.GetRoot()
+ if root:
+ self.root = root
+ return root
+
+ elif name == "clean_root":
+ clean_root = self.GetCleanRoot()
+ if clean_root:
+ self.clean_root = clean_root
+ return clean_root
+
+ elif name == "revision":
+ revision = self.GetRevision()
+ if revision:
+ self.revision = revision
+ return revision
+
+ elif name == "filename":
+ filename = self.GetFilename()
+ if filename:
+ self.filename = filename
+ return filename
+
+ raise AttributeError
+
+ def GetRoot(self):
+ """This method should return the unmodified root for the file or 'None'
+ on failure."""
+ raise NotImplementedError
+
+ def GetCleanRoot(self):
+ """This method should return the repository root for the file or 'None'
+ on failure."""
+ raise NotImplementedError
+
+ def GetRevision(self):
+ """This method should return the revision number for the file or 'None'
+ on failure."""
+ raise NotImplementedError
+
+ def GetFilename(self):
+ """This method should return the repository-specific filename for the
+ file or 'None' on failure."""
+ raise NotImplementedError
+
+
+# This regex separates protocol and optional username/password from a url.
+# For instance, all the following urls will be transformed into
+# 'foo.com/bar':
+#
+# http://foo.com/bar
+# svn+ssh://user@foo.com/bar
+# svn+ssh://user:pass@foo.com/bar
+#
+rootRegex = re.compile(r"^\S+?:/+(?:[^\s/]*@)?(\S+)$")
+
+
+def read_output(*args):
+ (stdout, _) = subprocess.Popen(
+ args=args, universal_newlines=True, stdout=subprocess.PIPE
+ ).communicate()
+ return stdout.rstrip()
+
+
+class HGRepoInfo:
+ def __init__(self, path):
+ self.path = path
+
+ rev = os.environ.get("MOZ_SOURCE_CHANGESET")
+ if not rev:
+ rev = read_output("hg", "-R", path, "parent", "--template={node}")
+
+ # Look for the default hg path. If MOZ_SOURCE_REPO is set, we
+ # don't bother asking hg.
+ hg_root = os.environ.get("MOZ_SOURCE_REPO")
+ if hg_root:
+ root = hg_root
+ else:
+ root = read_output("hg", "-R", path, "showconfig", "paths.default")
+ if not root:
+ print("Failed to get HG Repo for %s" % path, file=sys.stderr)
+ cleanroot = None
+ if root:
+ match = rootRegex.match(root)
+ if match:
+ cleanroot = match.group(1)
+ if cleanroot.endswith("/"):
+ cleanroot = cleanroot[:-1]
+ if cleanroot is None:
+ print(
+ textwrap.dedent(
+ """\
+ Could not determine repo info for %s. This is either not a clone of the web-based
+ repository, or you have not specified MOZ_SOURCE_REPO, or the clone is corrupt."""
+ )
+ % path,
+ sys.stderr,
+ )
+ sys.exit(1)
+ self.rev = rev
+ self.root = root
+ self.cleanroot = cleanroot
+
+ def GetFileInfo(self, file):
+ return HGFileInfo(file, self)
+
+
+class HGFileInfo(VCSFileInfo):
+ def __init__(self, file, repo):
+ VCSFileInfo.__init__(self, file)
+ self.repo = repo
+ self.file = os.path.relpath(file, repo.path)
+
+ def GetRoot(self):
+ return self.repo.root
+
+ def GetCleanRoot(self):
+ return self.repo.cleanroot
+
+ def GetRevision(self):
+ return self.repo.rev
+
+ def GetFilename(self):
+ if self.revision and self.clean_root:
+ return "hg:%s:%s:%s" % (self.clean_root, self.file, self.revision)
+ return self.file
+
+
+class GitRepoInfo:
+ """
+ Info about a local git repository. Does not currently
+ support discovering info about a git clone, the info must be
+ provided out-of-band.
+ """
+
+ def __init__(self, path, rev, root):
+ self.path = path
+ cleanroot = None
+ if root:
+ match = rootRegex.match(root)
+ if match:
+ cleanroot = match.group(1)
+ if cleanroot.endswith("/"):
+ cleanroot = cleanroot[:-1]
+ if cleanroot is None:
+ print(
+ textwrap.dedent(
+ """\
+ Could not determine repo info for %s (%s). This is either not a clone of a web-based
+ repository, or you have not specified MOZ_SOURCE_REPO, or the clone is corrupt."""
+ )
+ % (path, root),
+ file=sys.stderr,
+ )
+ sys.exit(1)
+ self.rev = rev
+ self.cleanroot = cleanroot
+
+ def GetFileInfo(self, file):
+ return GitFileInfo(file, self)
+
+
+class GitFileInfo(VCSFileInfo):
+ def __init__(self, file, repo):
+ VCSFileInfo.__init__(self, file)
+ self.repo = repo
+ self.file = os.path.relpath(file, repo.path)
+
+ def GetRoot(self):
+ return self.repo.path
+
+ def GetCleanRoot(self):
+ return self.repo.cleanroot
+
+ def GetRevision(self):
+ return self.repo.rev
+
+ def GetFilename(self):
+ if self.revision and self.clean_root:
+ return "git:%s:%s:%s" % (self.clean_root, self.file, self.revision)
+ return self.file
+
+
+# Utility functions
+
+
+# A cache of files for which VCS info has already been determined. Used to
+# prevent extra filesystem activity or process launching.
+vcsFileInfoCache = {}
+
+if platform.system() == "Windows":
+
+ def realpath(path):
+ """
+ Normalize a path using `GetFinalPathNameByHandleW` to get the
+ path with all components in the case they exist in on-disk, so
+ that making links to a case-sensitive server (hg.mozilla.org) works.
+
+ This function also resolves any symlinks in the path.
+ """
+ # Return the original path if something fails, which can happen for paths that
+ # don't exist on this system (like paths from the CRT).
+ result = path
+
+ ctypes.windll.kernel32.SetErrorMode(ctypes.c_uint(1))
+ handle = ctypes.windll.kernel32.CreateFileW(
+ path,
+ # GENERIC_READ
+ 0x80000000,
+ # FILE_SHARE_READ
+ 1,
+ None,
+ # OPEN_EXISTING
+ 3,
+ # FILE_FLAG_BACKUP_SEMANTICS
+ # This is necessary to open
+ # directory handles.
+ 0x02000000,
+ None,
+ )
+ if handle != -1:
+ size = ctypes.windll.kernel32.GetFinalPathNameByHandleW(handle, None, 0, 0)
+ buf = ctypes.create_unicode_buffer(size)
+ if (
+ ctypes.windll.kernel32.GetFinalPathNameByHandleW(handle, buf, size, 0)
+ > 0
+ ):
+ # The return value of GetFinalPathNameByHandleW uses the
+ # '\\?\' prefix.
+ result = buf.value[4:]
+ ctypes.windll.kernel32.CloseHandle(handle)
+ return result
+
+
+else:
+ # Just use the os.path version otherwise.
+ realpath = os.path.realpath
+
+
+def IsInDir(file, dir):
+ try:
+ Path(file).relative_to(dir)
+ return True
+ except ValueError:
+ return False
+
+
+def GetVCSFilenameFromSrcdir(file, srcdir):
+ if srcdir not in Dumper.srcdirRepoInfo:
+ # Not in cache, so find it adnd cache it
+ if os.path.isdir(os.path.join(srcdir, ".hg")):
+ Dumper.srcdirRepoInfo[srcdir] = HGRepoInfo(srcdir)
+ else:
+ # Unknown VCS or file is not in a repo.
+ return None
+ return Dumper.srcdirRepoInfo[srcdir].GetFileInfo(file)
+
+
+def GetVCSFilename(file, srcdirs):
+ """Given a full path to a file, and the top source directory,
+ look for version control information about this file, and return
+ a tuple containing
+ 1) a specially formatted filename that contains the VCS type,
+ VCS location, relative filename, and revision number, formatted like:
+ vcs:vcs location:filename:revision
+ For example:
+ cvs:cvs.mozilla.org/cvsroot:mozilla/browser/app/nsBrowserApp.cpp:1.36
+ 2) the unmodified root information if it exists"""
+ (path, filename) = os.path.split(file)
+ if path == "" or filename == "":
+ return (file, None)
+
+ fileInfo = None
+ root = ""
+ if file in vcsFileInfoCache:
+ # Already cached this info, use it.
+ fileInfo = vcsFileInfoCache[file]
+ else:
+ for srcdir in srcdirs:
+ if not IsInDir(file, srcdir):
+ continue
+ fileInfo = GetVCSFilenameFromSrcdir(file, srcdir)
+ if fileInfo:
+ vcsFileInfoCache[file] = fileInfo
+ break
+
+ if fileInfo:
+ file = fileInfo.filename
+ root = fileInfo.root
+
+ # we want forward slashes on win32 paths
+ return (file.replace("\\", "/"), root)
+
+
+def validate_install_manifests(install_manifest_args):
+ args = []
+ for arg in install_manifest_args:
+ bits = arg.split(",")
+ if len(bits) != 2:
+ raise ValueError(
+ "Invalid format for --install-manifest: " "specify manifest,target_dir"
+ )
+ manifest_file, destination = [os.path.abspath(b) for b in bits]
+ if not os.path.isfile(manifest_file):
+ raise IOError(errno.ENOENT, "Manifest file not found", manifest_file)
+ if not os.path.isdir(destination):
+ raise IOError(errno.ENOENT, "Install directory not found", destination)
+ try:
+ manifest = InstallManifest(manifest_file)
+ except UnreadableInstallManifest:
+ raise IOError(errno.EINVAL, "Error parsing manifest file", manifest_file)
+ args.append((manifest, destination))
+ return args
+
+
+def make_file_mapping(install_manifests):
+ file_mapping = {}
+ for manifest, destination in install_manifests:
+ destination = os.path.abspath(destination)
+ reg = FileRegistry()
+ manifest.populate_registry(reg)
+ for dst, src in reg:
+ if hasattr(src, "path"):
+ # Any paths that get compared to source file names need to go through realpath.
+ abs_dest = realpath(os.path.join(destination, dst))
+ file_mapping[abs_dest] = realpath(src.path)
+ return file_mapping
+
+
+@memoize
+def get_generated_file_s3_path(filename, rel_path, bucket):
+ """Given a filename, return a path formatted similarly to
+ GetVCSFilename but representing a file available in an s3 bucket."""
+ with open(filename, "rb") as f:
+ path = get_filename_with_digest(rel_path, f.read())
+ return "s3:{bucket}:{path}:".format(bucket=bucket, path=path)
+
+
+def GetPlatformSpecificDumper(**kwargs):
+ """This function simply returns a instance of a subclass of Dumper
+ that is appropriate for the current platform."""
+ return {"WINNT": Dumper_Win32, "Linux": Dumper_Linux, "Darwin": Dumper_Mac}[
+ buildconfig.substs["OS_ARCH"]
+ ](**kwargs)
+
+
+def SourceIndex(fileStream, outputPath, vcs_root, s3_bucket):
+ """Takes a list of files, writes info to a data block in a .stream file"""
+ # Creates a .pdb.stream file in the mozilla\objdir to be used for source indexing
+ # Create the srcsrv data block that indexes the pdb file
+ result = True
+ pdbStreamFile = open(outputPath, "w")
+ pdbStreamFile.write(
+ "SRCSRV: ini ------------------------------------------------\r\n"
+ + "VERSION=2\r\n"
+ + "INDEXVERSION=2\r\n"
+ + "VERCTRL=http\r\n"
+ + "SRCSRV: variables ------------------------------------------\r\n"
+ + "SRCSRVVERCTRL=http\r\n"
+ + "RUST_GITHUB_TARGET=https://github.com/rust-lang/rust/raw/%var4%/%var3%\r\n"
+ )
+ pdbStreamFile.write("HGSERVER=" + vcs_root + "\r\n")
+ pdbStreamFile.write("HG_TARGET=%hgserver%/raw-file/%var4%/%var3%\r\n")
+
+ if s3_bucket:
+ pdbStreamFile.write("S3_BUCKET=" + s3_bucket + "\r\n")
+ pdbStreamFile.write("S3_TARGET=https://%s3_bucket%.s3.amazonaws.com/%var3%\r\n")
+
+ # Allow each entry to choose its template via "var2".
+ # Possible values for var2 are: HG_TARGET / S3_TARGET / RUST_GITHUB_TARGET
+ pdbStreamFile.write("SRCSRVTRG=%fnvar%(%var2%)\r\n")
+
+ pdbStreamFile.write(
+ "SRCSRV: source files ---------------------------------------\r\n"
+ )
+ pdbStreamFile.write(fileStream)
+ pdbStreamFile.write(
+ "SRCSRV: end ------------------------------------------------\r\n\n"
+ )
+ pdbStreamFile.close()
+ return result
+
+
+class Dumper:
+ """This class can dump symbols from a file with debug info, and
+ store the output in a directory structure that is valid for use as
+ a Breakpad symbol server. Requires a path to a dump_syms binary--
+ |dump_syms| and a directory to store symbols in--|symbol_path|.
+ Optionally takes a list of processor architectures to process from
+ each debug file--|archs|, the full path to the top source
+ directory--|srcdir|, for generating relative source file names,
+ and an option to copy debug info files alongside the dumped
+ symbol files--|copy_debug|, mostly useful for creating a
+ Microsoft Symbol Server from the resulting output.
+
+ You don't want to use this directly if you intend to process files.
+ Instead, call GetPlatformSpecificDumper to get an instance of a
+ subclass."""
+
+ srcdirRepoInfo = {}
+
+ def __init__(
+ self,
+ dump_syms,
+ symbol_path,
+ archs=None,
+ srcdirs=[],
+ copy_debug=False,
+ vcsinfo=False,
+ srcsrv=False,
+ s3_bucket=None,
+ file_mapping=None,
+ ):
+ # popen likes absolute paths, at least on windows
+ self.dump_syms = os.path.abspath(dump_syms)
+ self.symbol_path = symbol_path
+ if archs is None:
+ # makes the loop logic simpler
+ self.archs = [""]
+ else:
+ self.archs = ["-a %s" % a for a in archs.split()]
+ # Any paths that get compared to source file names need to go through realpath.
+ self.srcdirs = [realpath(s) for s in srcdirs]
+ self.copy_debug = copy_debug
+ self.vcsinfo = vcsinfo
+ self.srcsrv = srcsrv
+ self.s3_bucket = s3_bucket
+ self.file_mapping = file_mapping or {}
+ # Add a static mapping for Rust sources. Since Rust 1.30 official Rust builds map
+ # source paths to start with "/rust/<sha>/".
+ rust_sha = buildconfig.substs["RUSTC_COMMIT"]
+ rust_srcdir = "/rustc/" + rust_sha
+ self.srcdirs.append(rust_srcdir)
+ Dumper.srcdirRepoInfo[rust_srcdir] = GitRepoInfo(
+ rust_srcdir, rust_sha, "https://github.com/rust-lang/rust/"
+ )
+
+ # subclasses override this
+ def ShouldProcess(self, file):
+ return True
+
+ # This is a no-op except on Win32
+ def SourceServerIndexing(
+ self, debug_file, guid, sourceFileStream, vcs_root, s3_bucket
+ ):
+ return ""
+
+ # subclasses override this if they want to support this
+ def CopyExeAndDebugInfo(self, file, debug_file, guid, code_file, code_id):
+ """This function will copy a library or executable and the file holding the
+ debug information to |symbol_path|"""
+ pass
+
+ def Process(self, file_to_process, count_ctors=False):
+ """Process the given file."""
+ if self.ShouldProcess(os.path.abspath(file_to_process)):
+ self.ProcessFile(file_to_process, count_ctors=count_ctors)
+
+ def ProcessFile(self, file, dsymbundle=None, count_ctors=False):
+ """Dump symbols from these files into a symbol file, stored
+ in the proper directory structure in |symbol_path|; processing is performed
+ asynchronously, and Finish must be called to wait for it complete and cleanup.
+ All files after the first are fallbacks in case the first file does not process
+ successfully; if it does, no other files will be touched."""
+ print("Beginning work for file: %s" % file, file=sys.stderr)
+
+ # tries to get the vcs root from the .mozconfig first - if it's not set
+ # the tinderbox vcs path will be assigned further down
+ vcs_root = os.environ.get("MOZ_SOURCE_REPO")
+ for arch_num, arch in enumerate(self.archs):
+ self.ProcessFileWork(
+ file, arch_num, arch, vcs_root, dsymbundle, count_ctors=count_ctors
+ )
+
+ def dump_syms_cmdline(self, file, arch, dsymbundle=None):
+ """
+ Get the commandline used to invoke dump_syms.
+ """
+ # The Mac dumper overrides this.
+ return [self.dump_syms, "--inlines", file]
+
+ def ProcessFileWork(
+ self, file, arch_num, arch, vcs_root, dsymbundle=None, count_ctors=False
+ ):
+ ctors = 0
+ t_start = time.time()
+ print("Processing file: %s" % file, file=sys.stderr)
+
+ sourceFileStream = ""
+ code_id, code_file = None, None
+ try:
+ cmd = self.dump_syms_cmdline(file, arch, dsymbundle=dsymbundle)
+ print(" ".join(cmd), file=sys.stderr)
+ proc = subprocess.Popen(
+ cmd,
+ universal_newlines=True,
+ stdout=subprocess.PIPE,
+ )
+ try:
+ module_line = next(proc.stdout)
+ except StopIteration:
+ module_line = ""
+ if module_line.startswith("MODULE"):
+ # MODULE os cpu guid debug_file
+ (guid, debug_file) = (module_line.split())[3:5]
+ # strip off .pdb extensions, and append .sym
+ sym_file = re.sub("\.pdb$", "", debug_file) + ".sym"
+ # we do want forward slashes here
+ rel_path = os.path.join(debug_file, guid, sym_file).replace("\\", "/")
+ full_path = os.path.normpath(os.path.join(self.symbol_path, rel_path))
+ try:
+ os.makedirs(os.path.dirname(full_path))
+ except OSError: # already exists
+ pass
+ f = open(full_path, "w")
+ f.write(module_line)
+ # now process the rest of the output
+ for line in proc.stdout:
+ if line.startswith("FILE"):
+ # FILE index filename
+ (x, index, filename) = line.rstrip().split(None, 2)
+ # We want original file paths for the source server.
+ sourcepath = filename
+ filename = realpath(filename)
+ if filename in self.file_mapping:
+ filename = self.file_mapping[filename]
+ if self.vcsinfo:
+ try:
+ gen_path = Path(filename)
+ rel_gen_path = gen_path.relative_to(
+ buildconfig.topobjdir
+ )
+ except ValueError:
+ gen_path = None
+ if (
+ gen_path
+ and gen_path.exists()
+ and gen_path.suffix in GENERATED_SOURCE_EXTS
+ and self.s3_bucket
+ ):
+ filename = get_generated_file_s3_path(
+ filename, str(rel_gen_path), self.s3_bucket
+ )
+ rootname = ""
+ else:
+ (filename, rootname) = GetVCSFilename(
+ filename, self.srcdirs
+ )
+ # sets vcs_root in case the loop through files were to end
+ # on an empty rootname
+ if vcs_root is None:
+ if rootname:
+ vcs_root = rootname
+ # Emit an entry for the file mapping for the srcsrv stream
+ if filename.startswith("hg:"):
+ (vcs, repo, source_file, revision) = filename.split(":", 3)
+ sourceFileStream += sourcepath + "*HG_TARGET*" + source_file
+ sourceFileStream += "*" + revision + "\r\n"
+ elif filename.startswith("s3:"):
+ (vcs, bucket, source_file, nothing) = filename.split(":", 3)
+ sourceFileStream += sourcepath + "*S3_TARGET*"
+ sourceFileStream += source_file + "\r\n"
+ elif filename.startswith("git:github.com/rust-lang/rust:"):
+ (vcs, repo, source_file, revision) = filename.split(":", 3)
+ sourceFileStream += sourcepath + "*RUST_GITHUB_TARGET*"
+ sourceFileStream += source_file + "*" + revision + "\r\n"
+ f.write("FILE %s %s\n" % (index, filename))
+ elif line.startswith("INFO CODE_ID "):
+ # INFO CODE_ID code_id code_file
+ # This gives some info we can use to
+ # store binaries in the symbol store.
+ bits = line.rstrip().split(None, 3)
+ if len(bits) == 4:
+ code_id, code_file = bits[2:]
+ f.write(line)
+ else:
+ if count_ctors and line.startswith("FUNC "):
+ # Static initializers, as created by clang and gcc
+ # have symbols that start with "_GLOBAL_sub"
+ if "_GLOBAL__sub_" in line:
+ ctors += 1
+ # MSVC creates `dynamic initializer for '...'`
+ # symbols.
+ elif "`dynamic initializer for '" in line:
+ ctors += 1
+
+ # pass through all other lines unchanged
+ f.write(line)
+ f.close()
+ retcode = proc.wait()
+ if retcode != 0:
+ raise RuntimeError(
+ "dump_syms failed with error code %d while processing %s\n"
+ % (retcode, file)
+ )
+ # we output relative paths so callers can get a list of what
+ # was generated
+ print(rel_path)
+ if self.srcsrv and vcs_root:
+ # add source server indexing to the pdb file
+ self.SourceServerIndexing(
+ debug_file, guid, sourceFileStream, vcs_root, self.s3_bucket
+ )
+ # only copy debug the first time if we have multiple architectures
+ if self.copy_debug and arch_num == 0:
+ self.CopyExeAndDebugInfo(file, debug_file, guid, code_file, code_id)
+ else:
+ # For some reason, we didn't see the MODULE line as the first
+ # line of output, this is strictly required so fail irrespective
+ # of the process' return code.
+ retcode = proc.wait()
+ message = [
+ "dump_syms failed to produce the expected output",
+ "file: %s" % file,
+ "return code: %d" % retcode,
+ "first line of output: %s" % module_line,
+ ]
+ raise RuntimeError("\n----------\n".join(message))
+ except Exception as e:
+ print("Unexpected error: %s" % str(e), file=sys.stderr)
+ raise
+
+ if dsymbundle:
+ shutil.rmtree(dsymbundle)
+
+ if count_ctors:
+ import json
+
+ perfherder_data = {
+ "framework": {"name": "build_metrics"},
+ "suites": [
+ {
+ "name": "compiler_metrics",
+ "subtests": [
+ {
+ "name": "num_static_constructors",
+ "value": ctors,
+ "alertChangeType": "absolute",
+ "alertThreshold": 3,
+ }
+ ],
+ }
+ ],
+ }
+ perfherder_extra_options = os.environ.get("PERFHERDER_EXTRA_OPTIONS", "")
+ for opt in perfherder_extra_options.split():
+ for suite in perfherder_data["suites"]:
+ if opt not in suite.get("extraOptions", []):
+ suite.setdefault("extraOptions", []).append(opt)
+
+ if "asan" not in perfherder_extra_options.lower():
+ print(
+ "PERFHERDER_DATA: %s" % json.dumps(perfherder_data), file=sys.stderr
+ )
+
+ elapsed = time.time() - t_start
+ print("Finished processing %s in %.2fs" % (file, elapsed), file=sys.stderr)
+
+
+# Platform-specific subclasses. For the most part, these just have
+# logic to determine what files to extract symbols from.
+
+
+def locate_pdb(path):
+ """Given a path to a binary, attempt to locate the matching pdb file with simple heuristics:
+ * Look for a pdb file with the same base name next to the binary
+ * Look for a pdb file with the same base name in the cwd
+
+ Returns the path to the pdb file if it exists, or None if it could not be located.
+ """
+ path, ext = os.path.splitext(path)
+ pdb = path + ".pdb"
+ if os.path.isfile(pdb):
+ return pdb
+ # If there's no pdb next to the file, see if there's a pdb with the same root name
+ # in the cwd. We build some binaries directly into dist/bin, but put the pdb files
+ # in the relative objdir, which is the cwd when running this script.
+ base = os.path.basename(pdb)
+ pdb = os.path.join(os.getcwd(), base)
+ if os.path.isfile(pdb):
+ return pdb
+ return None
+
+
+class Dumper_Win32(Dumper):
+ fixedFilenameCaseCache = {}
+
+ def ShouldProcess(self, file):
+ """This function will allow processing of exe or dll files that have pdb
+ files with the same base name next to them."""
+ if file.endswith(".exe") or file.endswith(".dll"):
+ if locate_pdb(file) is not None:
+ return True
+ return False
+
+ def CopyExeAndDebugInfo(self, file, debug_file, guid, code_file, code_id):
+ """This function will copy the executable or dll and pdb files to |symbol_path|"""
+ pdb_file = locate_pdb(file)
+
+ rel_path = os.path.join(debug_file, guid, debug_file).replace("\\", "/")
+ full_path = os.path.normpath(os.path.join(self.symbol_path, rel_path))
+ shutil.copyfile(pdb_file, full_path)
+ print(rel_path)
+
+ # Copy the binary file as well
+ if code_file and code_id:
+ full_code_path = os.path.join(os.path.dirname(file), code_file)
+ if os.path.exists(full_code_path):
+ rel_path = os.path.join(code_file, code_id, code_file).replace(
+ "\\", "/"
+ )
+ full_path = os.path.normpath(os.path.join(self.symbol_path, rel_path))
+ try:
+ os.makedirs(os.path.dirname(full_path))
+ except OSError as e:
+ if e.errno != errno.EEXIST:
+ raise
+ shutil.copyfile(full_code_path, full_path)
+ print(rel_path)
+
+ def SourceServerIndexing(
+ self, debug_file, guid, sourceFileStream, vcs_root, s3_bucket
+ ):
+ # Creates a .pdb.stream file in the mozilla\objdir to be used for source indexing
+ streamFilename = debug_file + ".stream"
+ stream_output_path = os.path.abspath(streamFilename)
+ # Call SourceIndex to create the .stream file
+ result = SourceIndex(sourceFileStream, stream_output_path, vcs_root, s3_bucket)
+ if self.copy_debug:
+ pdbstr = buildconfig.substs["PDBSTR"]
+ wine = buildconfig.substs.get("WINE")
+ if wine:
+ cmd = [wine, pdbstr]
+ else:
+ cmd = [pdbstr]
+ subprocess.call(
+ cmd
+ + [
+ "-w",
+ "-p:" + os.path.basename(debug_file),
+ "-i:" + os.path.basename(streamFilename),
+ "-s:srcsrv",
+ ],
+ cwd=os.path.dirname(stream_output_path),
+ )
+ # clean up all the .stream files when done
+ os.remove(stream_output_path)
+ return result
+
+
+class Dumper_Linux(Dumper):
+ objcopy = os.environ["OBJCOPY"] if "OBJCOPY" in os.environ else "objcopy"
+
+ def ShouldProcess(self, file):
+ """This function will allow processing of files that are
+ executable, or end with the .so extension, and additionally
+ file(1) reports as being ELF files. It expects to find the file
+ command in PATH."""
+ if file.endswith(".so") or os.access(file, os.X_OK):
+ return executables.get_type(file) == executables.ELF
+ return False
+
+ def CopyExeAndDebugInfo(self, file, debug_file, guid, code_file, code_id):
+ # We want to strip out the debug info, and add a
+ # .gnu_debuglink section to the object, so the debugger can
+ # actually load our debug info later.
+ # In some odd cases, the object might already have an irrelevant
+ # .gnu_debuglink section, and objcopy doesn't want to add one in
+ # such cases, so we make it remove it any existing one first.
+ file_dbg = file + ".dbg"
+ if (
+ subprocess.call([self.objcopy, "--only-keep-debug", file, file_dbg]) == 0
+ and subprocess.call(
+ [
+ self.objcopy,
+ "--remove-section",
+ ".gnu_debuglink",
+ "--add-gnu-debuglink=%s" % file_dbg,
+ file,
+ ]
+ )
+ == 0
+ ):
+ rel_path = os.path.join(debug_file, guid, debug_file + ".dbg")
+ full_path = os.path.normpath(os.path.join(self.symbol_path, rel_path))
+ shutil.move(file_dbg, full_path)
+ print(rel_path)
+ else:
+ if os.path.isfile(file_dbg):
+ os.unlink(file_dbg)
+
+
+class Dumper_Solaris(Dumper):
+ def ShouldProcess(self, file):
+ """This function will allow processing of files that are
+ executable, or end with the .so extension, and additionally
+ file(1) reports as being ELF files. It expects to find the file
+ command in PATH."""
+ if file.endswith(".so") or os.access(file, os.X_OK):
+ return executables.get_type(file) == executables.ELF
+ return False
+
+
+class Dumper_Mac(Dumper):
+ def ShouldProcess(self, file):
+ """This function will allow processing of files that are
+ executable, or end with the .dylib extension, and additionally
+ file(1) reports as being Mach-O files. It expects to find the file
+ command in PATH."""
+ if file.endswith(".dylib") or os.access(file, os.X_OK):
+ return executables.get_type(file) == executables.MACHO
+ return False
+
+ def ProcessFile(self, file, count_ctors=False):
+ print("Starting Mac pre-processing on file: %s" % file, file=sys.stderr)
+ dsymbundle = self.GenerateDSYM(file)
+ if dsymbundle:
+ # kick off new jobs per-arch with our new list of files
+ Dumper.ProcessFile(
+ self, file, dsymbundle=dsymbundle, count_ctors=count_ctors
+ )
+
+ def dump_syms_cmdline(self, file, arch, dsymbundle=None):
+ """
+ Get the commandline used to invoke dump_syms.
+ """
+ # dump_syms wants the path to the original binary and the .dSYM
+ # in order to dump all the symbols.
+ if dsymbundle:
+ # This is the .dSYM bundle.
+ return (
+ [self.dump_syms]
+ + arch.split()
+ + ["--inlines", "-j", "2", dsymbundle, file]
+ )
+ return Dumper.dump_syms_cmdline(self, file, arch)
+
+ def GenerateDSYM(self, file):
+ """dump_syms on Mac needs to be run on a dSYM bundle produced
+ by dsymutil(1), so run dsymutil here and pass the bundle name
+ down to the superclass method instead."""
+ t_start = time.time()
+ print("Running Mac pre-processing on file: %s" % (file,), file=sys.stderr)
+
+ dsymbundle = file + ".dSYM"
+ if os.path.exists(dsymbundle):
+ shutil.rmtree(dsymbundle)
+ dsymutil = buildconfig.substs["DSYMUTIL"]
+ # dsymutil takes --arch=foo instead of -a foo like everything else
+ cmd = (
+ [dsymutil] + [a.replace("-a ", "--arch=") for a in self.archs if a] + [file]
+ )
+ print(" ".join(cmd), file=sys.stderr)
+
+ dsymutil_proc = subprocess.Popen(
+ cmd, universal_newlines=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE
+ )
+ dsymout, dsymerr = dsymutil_proc.communicate()
+ if dsymutil_proc.returncode != 0:
+ raise RuntimeError("Error running dsymutil: %s" % dsymerr)
+
+ # Regular dsymutil won't produce a .dSYM for files without symbols.
+ if not os.path.exists(dsymbundle):
+ print("No symbols found in file: %s" % (file,), file=sys.stderr)
+ return False
+
+ # llvm-dsymutil will produce a .dSYM for files without symbols or
+ # debug information, but only sometimes will it warn you about this.
+ # We don't want to run dump_syms on such bundles, because asserts
+ # will fire in debug mode and who knows what will happen in release.
+ #
+ # So we check for the error message and bail if it appears. If it
+ # doesn't, we carefully check the bundled DWARF to see if dump_syms
+ # will be OK with it.
+ if "warning: no debug symbols in" in dsymerr:
+ print(dsymerr, file=sys.stderr)
+ return False
+
+ contents_dir = os.path.join(dsymbundle, "Contents", "Resources", "DWARF")
+ if not os.path.exists(contents_dir):
+ print(
+ "No DWARF information in .dSYM bundle %s" % (dsymbundle,),
+ file=sys.stderr,
+ )
+ return False
+
+ files = os.listdir(contents_dir)
+ if len(files) != 1:
+ print("Unexpected files in .dSYM bundle %s" % (files,), file=sys.stderr)
+ return False
+
+ otool_out = subprocess.check_output(
+ [buildconfig.substs["OTOOL"], "-l", os.path.join(contents_dir, files[0])],
+ universal_newlines=True,
+ )
+ if "sectname __debug_info" not in otool_out:
+ print("No symbols in .dSYM bundle %s" % (dsymbundle,), file=sys.stderr)
+ return False
+
+ elapsed = time.time() - t_start
+ print("Finished processing %s in %.2fs" % (file, elapsed), file=sys.stderr)
+ return dsymbundle
+
+ def CopyExeAndDebugInfo(self, file, debug_file, guid, code_file, code_id):
+ """ProcessFile has already produced a dSYM bundle, so we should just
+ copy that to the destination directory. However, we'll package it
+ into a .tar because it's a bundle, so it's a directory. |file| here is
+ the original filename."""
+ dsymbundle = file + ".dSYM"
+ rel_path = os.path.join(debug_file, guid, os.path.basename(dsymbundle) + ".tar")
+ full_path = os.path.abspath(os.path.join(self.symbol_path, rel_path))
+ success = subprocess.call(
+ ["tar", "cf", full_path, os.path.basename(dsymbundle)],
+ cwd=os.path.dirname(dsymbundle),
+ stdout=open(os.devnull, "w"),
+ stderr=subprocess.STDOUT,
+ )
+ if success == 0 and os.path.exists(full_path):
+ print(rel_path)
+
+
+# Entry point if called as a standalone program
+
+
+def main():
+ parser = OptionParser(
+ usage="usage: %prog [options] <dump_syms binary> <symbol store path> <debug info files>"
+ )
+ parser.add_option(
+ "-c",
+ "--copy",
+ action="store_true",
+ dest="copy_debug",
+ default=False,
+ help="Copy debug info files into the same directory structure as symbol files",
+ )
+ parser.add_option(
+ "-a",
+ "--archs",
+ action="store",
+ dest="archs",
+ help="Run dump_syms -a <arch> for each space separated"
+ + "cpu architecture in ARCHS (only on OS X)",
+ )
+ parser.add_option(
+ "-s",
+ "--srcdir",
+ action="append",
+ dest="srcdir",
+ default=[],
+ help="Use SRCDIR to determine relative paths to source files",
+ )
+ parser.add_option(
+ "-v",
+ "--vcs-info",
+ action="store_true",
+ dest="vcsinfo",
+ help="Try to retrieve VCS info for each FILE listed in the output",
+ )
+ parser.add_option(
+ "-i",
+ "--source-index",
+ action="store_true",
+ dest="srcsrv",
+ default=False,
+ help="Add source index information to debug files, making them suitable"
+ + " for use in a source server.",
+ )
+ parser.add_option(
+ "--install-manifest",
+ action="append",
+ dest="install_manifests",
+ default=[],
+ help="""Use this install manifest to map filenames back
+to canonical locations in the source repository. Specify
+<install manifest filename>,<install destination> as a comma-separated pair.""",
+ )
+ parser.add_option(
+ "--count-ctors",
+ action="store_true",
+ dest="count_ctors",
+ default=False,
+ help="Count static initializers",
+ )
+ (options, args) = parser.parse_args()
+
+ # check to see if the pdbstr.exe exists
+ if options.srcsrv:
+ if "PDBSTR" not in buildconfig.substs:
+ print("pdbstr was not found by configure.\n", file=sys.stderr)
+ sys.exit(1)
+
+ if len(args) < 3:
+ parser.error("not enough arguments")
+ exit(1)
+
+ try:
+ manifests = validate_install_manifests(options.install_manifests)
+ except (IOError, ValueError) as e:
+ parser.error(str(e))
+ exit(1)
+ file_mapping = make_file_mapping(manifests)
+ _, bucket = get_s3_region_and_bucket()
+ dumper = GetPlatformSpecificDumper(
+ dump_syms=args[0],
+ symbol_path=args[1],
+ copy_debug=options.copy_debug,
+ archs=options.archs,
+ srcdirs=options.srcdir,
+ vcsinfo=options.vcsinfo,
+ srcsrv=options.srcsrv,
+ s3_bucket=bucket,
+ file_mapping=file_mapping,
+ )
+
+ dumper.Process(args[2], options.count_ctors)
+
+
+# run main if run directly
+if __name__ == "__main__":
+ main()
diff --git a/toolkit/crashreporter/tools/unit-symbolstore.py b/toolkit/crashreporter/tools/unit-symbolstore.py
new file mode 100755
index 0000000000..ed59b012bb
--- /dev/null
+++ b/toolkit/crashreporter/tools/unit-symbolstore.py
@@ -0,0 +1,613 @@
+#!/usr/bin/env 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/.
+
+import os
+import shutil
+import struct
+import subprocess
+import sys
+import tempfile
+import unittest
+from unittest import mock
+from unittest.mock import patch
+
+import buildconfig
+import mozpack.path as mozpath
+import mozunit
+import symbolstore
+from mozpack.manifests import InstallManifest
+from symbolstore import realpath
+
+# Some simple functions to mock out files that the platform-specific dumpers will accept.
+# dump_syms itself will not be run (we mock that call out), but we can't override
+# the ShouldProcessFile method since we actually want to test that.
+
+
+def write_elf(filename):
+ open(filename, "wb").write(
+ struct.pack("<7B45x", 0x7F, ord("E"), ord("L"), ord("F"), 1, 1, 1)
+ )
+
+
+def write_macho(filename):
+ open(filename, "wb").write(struct.pack("<I28x", 0xFEEDFACE))
+
+
+def write_dll(filename):
+ open(filename, "w").write("aaa")
+ # write out a fake PDB too
+ open(os.path.splitext(filename)[0] + ".pdb", "w").write("aaa")
+
+
+def target_platform():
+ return buildconfig.substs["OS_TARGET"]
+
+
+def host_platform():
+ return buildconfig.substs["HOST_OS_ARCH"]
+
+
+writer = {
+ "WINNT": write_dll,
+ "Linux": write_elf,
+ "Sunos5": write_elf,
+ "Darwin": write_macho,
+}[target_platform()]
+extension = {"WINNT": ".dll", "Linux": ".so", "Sunos5": ".so", "Darwin": ".dylib"}[
+ target_platform()
+]
+file_output = [
+ {"WINNT": "bogus data", "Linux": "ELF executable", "Darwin": "Mach-O executable"}[
+ target_platform()
+ ]
+]
+
+
+def add_extension(files):
+ return [f + extension for f in files]
+
+
+class HelperMixin(object):
+ """
+ Test that passing filenames to exclude from processing works.
+ """
+
+ def setUp(self):
+ self.test_dir = tempfile.mkdtemp()
+ if not self.test_dir.endswith(os.sep):
+ self.test_dir += os.sep
+ symbolstore.srcdirRepoInfo = {}
+ symbolstore.vcsFileInfoCache = {}
+
+ # Remove environment variables that can influence tests.
+ for e in ("MOZ_SOURCE_CHANGESET", "MOZ_SOURCE_REPO"):
+ try:
+ del os.environ[e]
+ except KeyError:
+ pass
+
+ def tearDown(self):
+ shutil.rmtree(self.test_dir)
+ symbolstore.srcdirRepoInfo = {}
+ symbolstore.vcsFileInfoCache = {}
+
+ def make_dirs(self, f):
+ d = os.path.dirname(f)
+ if d and not os.path.exists(d):
+ os.makedirs(d)
+
+ def make_file(self, path):
+ self.make_dirs(path)
+ with open(path, "wb"):
+ pass
+
+ def add_test_files(self, files):
+ for f in files:
+ f = os.path.join(self.test_dir, f)
+ self.make_dirs(f)
+ writer(f)
+
+
+def mock_dump_syms(module_id, filename, extra=[]):
+ return (
+ ["MODULE os x86 %s %s" % (module_id, filename)]
+ + extra
+ + ["FILE 0 foo.c", "PUBLIC xyz 123"]
+ )
+
+
+class TestCopyDebug(HelperMixin, unittest.TestCase):
+ def setUp(self):
+ HelperMixin.setUp(self)
+ self.symbol_dir = tempfile.mkdtemp()
+ self.mock_call = patch("subprocess.call").start()
+ self.stdouts = []
+ self.mock_popen = patch("subprocess.Popen").start()
+ stdout_iter = self.next_mock_stdout()
+
+ def next_popen(*args, **kwargs):
+ m = mock.MagicMock()
+ # Get the iterators over whatever output was provided.
+ stdout_ = next(stdout_iter)
+ # Eager evaluation for communicate(), below.
+ stdout_ = list(stdout_)
+ # stdout is really an iterator, so back to iterators we go.
+ m.stdout = iter(stdout_)
+ m.wait.return_value = 0
+ # communicate returns the full text of stdout and stderr.
+ m.communicate.return_value = ("\n".join(stdout_), "")
+ return m
+
+ self.mock_popen.side_effect = next_popen
+ shutil.rmtree = patch("shutil.rmtree").start()
+
+ def tearDown(self):
+ HelperMixin.tearDown(self)
+ patch.stopall()
+ shutil.rmtree(self.symbol_dir)
+
+ def next_mock_stdout(self):
+ if not self.stdouts:
+ yield iter([])
+ for s in self.stdouts:
+ yield iter(s)
+
+ def test_copy_debug_universal(self):
+ """
+ Test that dumping symbols for multiple architectures only copies debug symbols once
+ per file.
+ """
+ copied = []
+
+ def mock_copy_debug(filename, debug_file, guid, code_file, code_id):
+ copied.append(
+ filename[len(self.symbol_dir) :]
+ if filename.startswith(self.symbol_dir)
+ else filename
+ )
+
+ self.add_test_files(add_extension(["foo"]))
+ # Windows doesn't call file(1) to figure out if the file should be processed.
+ if target_platform() != "WINNT":
+ self.stdouts.append(file_output)
+ self.stdouts.append(mock_dump_syms("X" * 33, add_extension(["foo"])[0]))
+ self.stdouts.append(mock_dump_syms("Y" * 33, add_extension(["foo"])[0]))
+
+ def mock_dsymutil(args, **kwargs):
+ filename = args[-1]
+ os.makedirs(filename + ".dSYM")
+ return 0
+
+ self.mock_call.side_effect = mock_dsymutil
+ d = symbolstore.GetPlatformSpecificDumper(
+ dump_syms="dump_syms",
+ symbol_path=self.symbol_dir,
+ copy_debug=True,
+ archs="abc xyz",
+ )
+ d.CopyDebug = mock_copy_debug
+ d.Process(os.path.join(self.test_dir, add_extension(["foo"])[0]))
+ self.assertEqual(1, len(copied))
+
+ def test_copy_debug_copies_binaries(self):
+ """
+ Test that CopyDebug copies binaries as well on Windows.
+ """
+ test_file = os.path.join(self.test_dir, "foo.dll")
+ write_dll(test_file)
+ code_file = "foo.dll"
+ code_id = "abc123"
+ self.stdouts.append(
+ mock_dump_syms(
+ "X" * 33, "foo.pdb", ["INFO CODE_ID %s %s" % (code_id, code_file)]
+ )
+ )
+
+ def mock_compress(args, **kwargs):
+ filename = args[-1]
+ open(filename, "w").write("stuff")
+ return 0
+
+ self.mock_call.side_effect = mock_compress
+ d = symbolstore.Dumper_Win32(
+ dump_syms="dump_syms", symbol_path=self.symbol_dir, copy_debug=True
+ )
+ d.Process(test_file)
+ self.assertTrue(
+ os.path.isfile(os.path.join(self.symbol_dir, code_file, code_id, code_file))
+ )
+
+
+class TestGetVCSFilename(HelperMixin, unittest.TestCase):
+ def setUp(self):
+ HelperMixin.setUp(self)
+
+ def tearDown(self):
+ HelperMixin.tearDown(self)
+
+ @patch("subprocess.Popen")
+ def testVCSFilenameHg(self, mock_Popen):
+ # mock calls to `hg parent` and `hg showconfig paths.default`
+ mock_communicate = mock_Popen.return_value.communicate
+ mock_communicate.side_effect = [
+ ("abcd1234", ""),
+ ("http://example.com/repo", ""),
+ ]
+ os.mkdir(os.path.join(self.test_dir, ".hg"))
+ filename = os.path.join(self.test_dir, "foo.c")
+ self.assertEqual(
+ "hg:example.com/repo:foo.c:abcd1234",
+ symbolstore.GetVCSFilename(filename, [self.test_dir])[0],
+ )
+
+ @patch("subprocess.Popen")
+ def testVCSFilenameHgMultiple(self, mock_Popen):
+ # mock calls to `hg parent` and `hg showconfig paths.default`
+ mock_communicate = mock_Popen.return_value.communicate
+ mock_communicate.side_effect = [
+ ("abcd1234", ""),
+ ("http://example.com/repo", ""),
+ ("0987ffff", ""),
+ ("http://example.com/other", ""),
+ ]
+ srcdir1 = os.path.join(self.test_dir, "one")
+ srcdir2 = os.path.join(self.test_dir, "two")
+ os.makedirs(os.path.join(srcdir1, ".hg"))
+ os.makedirs(os.path.join(srcdir2, ".hg"))
+ filename1 = os.path.join(srcdir1, "foo.c")
+ filename2 = os.path.join(srcdir2, "bar.c")
+ self.assertEqual(
+ "hg:example.com/repo:foo.c:abcd1234",
+ symbolstore.GetVCSFilename(filename1, [srcdir1, srcdir2])[0],
+ )
+ self.assertEqual(
+ "hg:example.com/other:bar.c:0987ffff",
+ symbolstore.GetVCSFilename(filename2, [srcdir1, srcdir2])[0],
+ )
+
+ def testVCSFilenameEnv(self):
+ # repo URL and changeset read from environment variables if defined.
+ os.environ["MOZ_SOURCE_REPO"] = "https://somewhere.com/repo"
+ os.environ["MOZ_SOURCE_CHANGESET"] = "abcdef0123456"
+ os.mkdir(os.path.join(self.test_dir, ".hg"))
+ filename = os.path.join(self.test_dir, "foo.c")
+ self.assertEqual(
+ "hg:somewhere.com/repo:foo.c:abcdef0123456",
+ symbolstore.GetVCSFilename(filename, [self.test_dir])[0],
+ )
+
+
+# SHA-512 of a zero-byte file
+EMPTY_SHA512 = (
+ "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff"
+)
+EMPTY_SHA512 += "8318d2877eec2f63b931bd47417a81a538327af927da3e"
+
+
+class TestGeneratedFilePath(HelperMixin, unittest.TestCase):
+ def setUp(self):
+ HelperMixin.setUp(self)
+
+ def tearDown(self):
+ HelperMixin.tearDown(self)
+
+ def test_generated_file_path(self):
+ # Make an empty generated file
+ g = os.path.join(self.test_dir, "generated")
+ rel_path = "a/b/generated"
+ with open(g, "wb"):
+ pass
+ expected = "s3:bucket:{}/{}:".format(EMPTY_SHA512, rel_path)
+ self.assertEqual(
+ expected, symbolstore.get_generated_file_s3_path(g, rel_path, "bucket")
+ )
+
+
+if host_platform() == "WINNT":
+
+ class TestRealpath(HelperMixin, unittest.TestCase):
+ def test_realpath(self):
+ # self.test_dir is going to be 8.3 paths...
+ junk = os.path.join(self.test_dir, "x")
+ with open(junk, "w") as o:
+ o.write("x")
+ fixed_dir = os.path.dirname(realpath(junk))
+ files = [
+ "one\\two.c",
+ "three\\Four.d",
+ "Five\\Six.e",
+ "seven\\Eight\\nine.F",
+ ]
+ for rel_path in files:
+ full_path = os.path.normpath(os.path.join(self.test_dir, rel_path))
+ self.make_dirs(full_path)
+ with open(full_path, "w") as o:
+ o.write("x")
+ fixed_path = realpath(full_path.lower())
+ fixed_path = os.path.relpath(fixed_path, fixed_dir)
+ self.assertEqual(rel_path, fixed_path)
+
+
+if target_platform() == "WINNT":
+
+ class TestSourceServer(HelperMixin, unittest.TestCase):
+ @patch("subprocess.call")
+ @patch("subprocess.Popen")
+ @patch.dict("buildconfig.substs._dict", {"PDBSTR": "pdbstr"})
+ def test_HGSERVER(self, mock_Popen, mock_call):
+ """
+ Test that HGSERVER gets set correctly in the source server index.
+ """
+ symbolpath = os.path.join(self.test_dir, "symbols")
+ os.makedirs(symbolpath)
+ srcdir = os.path.join(self.test_dir, "srcdir")
+ os.makedirs(os.path.join(srcdir, ".hg"))
+ sourcefile = os.path.join(srcdir, "foo.c")
+ test_files = add_extension(["foo"])
+ self.add_test_files(test_files)
+ # mock calls to `dump_syms`, `hg parent` and
+ # `hg showconfig paths.default`
+ mock_Popen.return_value.stdout = iter(
+ [
+ "MODULE os x86 %s %s" % ("X" * 33, test_files[0]),
+ "FILE 0 %s" % sourcefile,
+ "PUBLIC xyz 123",
+ ]
+ )
+ mock_Popen.return_value.wait.return_value = 0
+ mock_communicate = mock_Popen.return_value.communicate
+ mock_communicate.side_effect = [
+ ("abcd1234", ""),
+ ("http://example.com/repo", ""),
+ ]
+ # And mock the call to pdbstr to capture the srcsrv stream data.
+ global srcsrv_stream
+ srcsrv_stream = None
+
+ def mock_pdbstr(args, cwd="", **kwargs):
+ for arg in args:
+ if arg.startswith("-i:"):
+ global srcsrv_stream
+ srcsrv_stream = open(os.path.join(cwd, arg[3:]), "r").read()
+ return 0
+
+ mock_call.side_effect = mock_pdbstr
+ d = symbolstore.GetPlatformSpecificDumper(
+ dump_syms="dump_syms",
+ symbol_path=symbolpath,
+ srcdirs=[srcdir],
+ vcsinfo=True,
+ srcsrv=True,
+ copy_debug=True,
+ )
+ # stub out CopyDebug
+ d.CopyDebug = lambda *args: True
+ d.Process(os.path.join(self.test_dir, test_files[0]))
+ self.assertNotEqual(srcsrv_stream, None)
+ hgserver = [
+ x.rstrip()
+ for x in srcsrv_stream.splitlines()
+ if x.startswith("HGSERVER=")
+ ]
+ self.assertEqual(len(hgserver), 1)
+ self.assertEqual(hgserver[0].split("=")[1], "http://example.com/repo")
+
+
+class TestInstallManifest(HelperMixin, unittest.TestCase):
+ def setUp(self):
+ HelperMixin.setUp(self)
+ self.srcdir = os.path.join(self.test_dir, "src")
+ os.mkdir(self.srcdir)
+ self.objdir = os.path.join(self.test_dir, "obj")
+ os.mkdir(self.objdir)
+ self.manifest = InstallManifest()
+ self.canonical_mapping = {}
+ for s in ["src1", "src2"]:
+ srcfile = realpath(os.path.join(self.srcdir, s))
+ objfile = realpath(os.path.join(self.objdir, s))
+ self.canonical_mapping[objfile] = srcfile
+ self.manifest.add_copy(srcfile, s)
+ self.manifest_file = os.path.join(self.test_dir, "install-manifest")
+ self.manifest.write(self.manifest_file)
+
+ def testMakeFileMapping(self):
+ """
+ Test that valid arguments are validated.
+ """
+ arg = "%s,%s" % (self.manifest_file, self.objdir)
+ ret = symbolstore.validate_install_manifests([arg])
+ self.assertEqual(len(ret), 1)
+ manifest, dest = ret[0]
+ self.assertTrue(isinstance(manifest, InstallManifest))
+ self.assertEqual(dest, self.objdir)
+
+ file_mapping = symbolstore.make_file_mapping(ret)
+ for obj, src in self.canonical_mapping.items():
+ self.assertTrue(obj in file_mapping)
+ self.assertEqual(file_mapping[obj], src)
+
+ def testMissingFiles(self):
+ """
+ Test that missing manifest files or install directories give errors.
+ """
+ missing_manifest = os.path.join(self.test_dir, "missing-manifest")
+ arg = "%s,%s" % (missing_manifest, self.objdir)
+ with self.assertRaises(IOError) as e:
+ symbolstore.validate_install_manifests([arg])
+ self.assertEqual(e.filename, missing_manifest)
+
+ missing_install_dir = os.path.join(self.test_dir, "missing-dir")
+ arg = "%s,%s" % (self.manifest_file, missing_install_dir)
+ with self.assertRaises(IOError) as e:
+ symbolstore.validate_install_manifests([arg])
+ self.assertEqual(e.filename, missing_install_dir)
+
+ def testBadManifest(self):
+ """
+ Test that a bad manifest file give errors.
+ """
+ bad_manifest = os.path.join(self.test_dir, "bad-manifest")
+ with open(bad_manifest, "w") as f:
+ f.write("junk\n")
+ arg = "%s,%s" % (bad_manifest, self.objdir)
+ with self.assertRaises(IOError) as e:
+ symbolstore.validate_install_manifests([arg])
+ self.assertEqual(e.filename, bad_manifest)
+
+ def testBadArgument(self):
+ """
+ Test that a bad manifest argument gives an error.
+ """
+ with self.assertRaises(ValueError):
+ symbolstore.validate_install_manifests(["foo"])
+
+
+class TestFileMapping(HelperMixin, unittest.TestCase):
+ def setUp(self):
+ HelperMixin.setUp(self)
+ self.srcdir = os.path.join(self.test_dir, "src")
+ os.mkdir(self.srcdir)
+ self.objdir = os.path.join(self.test_dir, "obj")
+ os.mkdir(self.objdir)
+ self.symboldir = os.path.join(self.test_dir, "symbols")
+ os.mkdir(self.symboldir)
+
+ @patch("subprocess.Popen")
+ def testFileMapping(self, mock_Popen):
+ files = [("a/b", "mozilla/b"), ("c/d", "foo/d")]
+ if os.sep != "/":
+ files = [[f.replace("/", os.sep) for f in x] for x in files]
+ file_mapping = {}
+ dumped_files = []
+ expected_files = []
+ self.make_dirs(os.path.join(self.objdir, "x", "y"))
+ for s, o in files:
+ srcfile = os.path.join(self.srcdir, s)
+ self.make_file(srcfile)
+ expected_files.append(realpath(srcfile))
+ objfile = os.path.join(self.objdir, o)
+ self.make_file(objfile)
+ file_mapping[realpath(objfile)] = realpath(srcfile)
+ dumped_files.append(os.path.join(self.objdir, "x", "y", "..", "..", o))
+ # mock the dump_syms output
+ file_id = ("X" * 33, "somefile")
+
+ def mk_output(files):
+ return iter(
+ ["MODULE os x86 %s %s\n" % file_id]
+ + ["FILE %d %s\n" % (i, s) for i, s in enumerate(files)]
+ + ["PUBLIC xyz 123\n"]
+ )
+
+ mock_Popen.return_value.stdout = mk_output(dumped_files)
+ mock_Popen.return_value.wait.return_value = 0
+
+ d = symbolstore.Dumper("dump_syms", self.symboldir, file_mapping=file_mapping)
+ f = os.path.join(self.objdir, "somefile")
+ open(f, "w").write("blah")
+ d.Process(f)
+ expected_output = "".join(mk_output(expected_files))
+ symbol_file = os.path.join(
+ self.symboldir, file_id[1], file_id[0], file_id[1] + ".sym"
+ )
+ self.assertEqual(open(symbol_file, "r").read(), expected_output)
+
+
+class TestFunctional(HelperMixin, unittest.TestCase):
+ """Functional tests of symbolstore.py, calling it with a real
+ dump_syms binary and passing in a real binary to dump symbols from.
+
+ Since the rest of the tests in this file mock almost everything and
+ don't use the actual process pool like buildsymbols does, this tests
+ that the way symbolstore.py gets called in buildsymbols works.
+ """
+
+ def setUp(self):
+ HelperMixin.setUp(self)
+ self.skip_test = False
+ if buildconfig.substs["MOZ_BUILD_APP"] != "browser":
+ self.skip_test = True
+ if buildconfig.substs.get("ENABLE_STRIP"):
+ self.skip_test = True
+ # Bug 1608146.
+ if buildconfig.substs.get("MOZ_CODE_COVERAGE"):
+ self.skip_test = True
+ self.topsrcdir = buildconfig.topsrcdir
+ self.script_path = os.path.join(
+ self.topsrcdir, "toolkit", "crashreporter", "tools", "symbolstore.py"
+ )
+ self.dump_syms = buildconfig.substs.get("DUMP_SYMS")
+ if not self.dump_syms:
+ self.skip_test = True
+
+ if target_platform() == "WINNT":
+ self.target_bin = os.path.join(
+ buildconfig.topobjdir, "dist", "bin", "firefox.exe"
+ )
+ else:
+ self.target_bin = os.path.join(
+ buildconfig.topobjdir, "dist", "bin", "firefox-bin"
+ )
+
+ def tearDown(self):
+ HelperMixin.tearDown(self)
+
+ def testSymbolstore(self):
+ if self.skip_test:
+ raise unittest.SkipTest("Skipping test in non-Firefox product")
+ dist_include_manifest = os.path.join(
+ buildconfig.topobjdir, "_build_manifests/install/dist_include"
+ )
+ dist_include = os.path.join(buildconfig.topobjdir, "dist/include")
+ browser_app = os.path.join(buildconfig.topobjdir, "browser/app")
+ output = subprocess.check_output(
+ [
+ sys.executable,
+ self.script_path,
+ "--vcs-info",
+ "-s",
+ self.topsrcdir,
+ "--install-manifest=%s,%s" % (dist_include_manifest, dist_include),
+ self.dump_syms,
+ self.test_dir,
+ self.target_bin,
+ ],
+ universal_newlines=True,
+ stderr=None,
+ cwd=browser_app,
+ )
+ lines = [l for l in output.splitlines() if l.strip()]
+ self.assertEqual(
+ 1,
+ len(lines),
+ "should have one filename in the output; got %s" % repr(output),
+ )
+ symbol_file = os.path.join(self.test_dir, lines[0])
+ self.assertTrue(os.path.isfile(symbol_file))
+ symlines = open(symbol_file, "r").readlines()
+ file_lines = [l for l in symlines if l.startswith("FILE")]
+
+ def check_hg_path(lines, match):
+ match_lines = [l for l in file_lines if match in l]
+ self.assertTrue(
+ len(match_lines) >= 1, "should have a FILE line for " + match
+ )
+ # Skip this check for local git repositories.
+ if not os.path.isdir(mozpath.join(self.topsrcdir, ".hg")):
+ return
+ for line in match_lines:
+ filename = line.split(None, 2)[2]
+ self.assertEqual("hg:", filename[:3])
+
+ # Check that nsBrowserApp.cpp is listed as a FILE line, and that
+ # it was properly mapped to the source repo.
+ check_hg_path(file_lines, "nsBrowserApp.cpp")
+ # Also check Sprintf.h to verify that files from dist/include
+ # are properly mapped.
+ check_hg_path(file_lines, "mfbt/Sprintf.h")
+
+
+if __name__ == "__main__":
+ mozunit.main()
diff --git a/toolkit/crashreporter/tools/upload_symbols.py b/toolkit/crashreporter/tools/upload_symbols.py
new file mode 100644
index 0000000000..eff1f43b2b
--- /dev/null
+++ b/toolkit/crashreporter/tools/upload_symbols.py
@@ -0,0 +1,306 @@
+#!/usr/bin/env python3
+#
+# 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/.
+#
+# This script uploads a symbol archive file from a path or URL passed on the commandline
+# to the symbol server at https://symbols.mozilla.org/ .
+#
+# Using this script requires you to have generated an authentication
+# token in the symbol server web interface. You must store the token in a Taskcluster
+# secret as the JSON blob `{"token": "<token>"}` and set the `SYMBOL_SECRET`
+# environment variable to the name of the Taskcluster secret. Alternately,
+# you can put the token in a file and set `SOCORRO_SYMBOL_UPLOAD_TOKEN_FILE`
+# environment variable to the path to the file.
+
+import argparse
+import logging
+import os
+import sys
+import tempfile
+
+import redo
+import requests
+
+log = logging.getLogger("upload-symbols")
+log.setLevel(logging.INFO)
+
+DEFAULT_URL = "https://symbols.mozilla.org/upload/"
+MAX_RETRIES = 7
+MAX_ZIP_SIZE = 500000000 # 500 MB
+
+
+def print_error(r):
+ if r.status_code < 400:
+ log.error("Error: bad auth token? ({0}: {1})".format(r.status_code, r.reason))
+ else:
+ log.error("Error: got HTTP response {0}: {1}".format(r.status_code, r.reason))
+
+ log.error(
+ "Response body:\n{sep}\n{body}\n{sep}\n".format(sep="=" * 20, body=r.text)
+ )
+
+
+def get_taskcluster_secret(secret_name):
+ secrets_url = "http://taskcluster/secrets/v1/secret/{}".format(secret_name)
+ log.info(
+ 'Using symbol upload token from the secrets service: "{}"'.format(secrets_url)
+ )
+ res = requests.get(secrets_url)
+ res.raise_for_status()
+ secret = res.json()
+ auth_token = secret["secret"]["token"]
+
+ return auth_token
+
+
+def main():
+ logging.basicConfig()
+ parser = argparse.ArgumentParser(
+ description="Upload symbols in ZIP using token from Taskcluster secrets service."
+ )
+ parser.add_argument(
+ "archive", help="Symbols archive file - URL or path to local file"
+ )
+ parser.add_argument(
+ "--ignore-missing", help="No error on missing files", action="store_true"
+ )
+ args = parser.parse_args()
+
+ def check_file_exists(url):
+ for i, _ in enumerate(redo.retrier(attempts=MAX_RETRIES), start=1):
+ try:
+ resp = requests.head(url, allow_redirects=True)
+ return resp.status_code == requests.codes.ok
+ except requests.exceptions.RequestException as e:
+ log.error("Error: {0}".format(e))
+ log.info("Retrying...")
+ return False
+
+ if args.archive.startswith("http"):
+ is_existing = check_file_exists(args.archive)
+ else:
+ is_existing = os.path.isfile(args.archive)
+
+ if not is_existing:
+ if args.ignore_missing:
+ log.info('Archive file "{0}" does not exist!'.format(args.archive))
+ return 0
+ else:
+ log.error('Error: archive file "{0}" does not exist!'.format(args.archive))
+ return 1
+
+ try:
+ tmpdir = None
+ if args.archive.endswith(".tar.zst"):
+ tmpdir = tempfile.TemporaryDirectory()
+ zip_paths = convert_zst_archive(args.archive, tmpdir)
+ else:
+ zip_paths = [args.archive]
+
+ for zip_path in zip_paths:
+ result = upload_symbols(zip_path)
+ if result:
+ return result
+ return 0
+ finally:
+ if tmpdir:
+ tmpdir.cleanup()
+
+
+def convert_zst_archive(zst_archive, tmpdir):
+ """
+ Convert a .tar.zst file to a zip file
+
+ Our build tasks output .tar.zst files, but the tecken server only allows
+ .zip files to be uploaded.
+
+ :param zst_archive: path or URL to a .tar.zst source file
+ :param tmpdir: TemporaryDirectory to store the output zip file in
+ :returns: path to output zip file
+ """
+ import concurrent.futures
+ import gzip
+ import itertools
+ import tarfile
+
+ import zstandard
+ from mozpack.files import File
+ from mozpack.mozjar import Deflater, JarWriter
+
+ def iter_files_from_tar(reader):
+ ctx = zstandard.ZstdDecompressor()
+ uncompressed = ctx.stream_reader(reader)
+ with tarfile.open(mode="r|", fileobj=uncompressed, bufsize=1024 * 1024) as tar:
+ while True:
+ info = tar.next()
+ if info is None:
+ break
+ data = tar.extractfile(info).read()
+ yield (info.name, data)
+
+ def prepare_from(archive, tmpdir):
+ if archive.startswith("http"):
+ resp = requests.get(archive, allow_redirects=True, stream=True)
+ resp.raise_for_status()
+ reader = resp.raw
+ # Work around taskcluster generic-worker possibly gzipping the tar.zst.
+ if resp.headers.get("Content-Encoding") == "gzip":
+ reader = gzip.GzipFile(fileobj=reader)
+ else:
+ reader = open(archive, "rb")
+
+ def handle_file(data):
+ name, data = data
+ log.info("Compressing %s", name)
+ path = os.path.join(tmpdir, name.lstrip("/"))
+ if name.endswith(".dbg"):
+ os.makedirs(os.path.dirname(path), exist_ok=True)
+ with open(path, "wb") as fh:
+ with gzip.GzipFile(fileobj=fh, mode="wb", compresslevel=5) as c:
+ c.write(data)
+ return (name + ".gz", File(path))
+ elif name.endswith(".dSYM.tar"):
+ import bz2
+
+ os.makedirs(os.path.dirname(path), exist_ok=True)
+ with open(path, "wb") as fh:
+ fh.write(bz2.compress(data))
+ return (name + ".bz2", File(path))
+ elif name.endswith((".pdb", ".exe", ".dll")):
+ import subprocess
+
+ makecab = os.environ.get("MAKECAB", "makecab")
+ os.makedirs(os.path.dirname(path), exist_ok=True)
+ with open(path, "wb") as fh:
+ fh.write(data)
+
+ subprocess.check_call(
+ [makecab, "-D", "CompressionType=MSZIP", path, path + "_"],
+ stdout=subprocess.DEVNULL,
+ stderr=subprocess.STDOUT,
+ )
+
+ return (name[:-1] + "_", File(path + "_"))
+ else:
+ deflater = Deflater(compress_level=5)
+ deflater.write(data)
+ return (name, deflater)
+
+ with concurrent.futures.ThreadPoolExecutor(
+ max_workers=os.cpu_count()
+ ) as executor:
+ yield from executor.map(handle_file, iter_files_from_tar(reader))
+
+ reader.close()
+
+ zip_paths_iter = iter(
+ os.path.join(tmpdir.name, "symbols{}.zip".format("" if i == 1 else i))
+ for i in itertools.count(start=1)
+ )
+ zip_path = next(zip_paths_iter)
+ log.info('Preparing symbol archive "{0}" from "{1}"'.format(zip_path, zst_archive))
+ for i, _ in enumerate(redo.retrier(attempts=MAX_RETRIES), start=1):
+ zip_paths = []
+ jar = None
+ try:
+ for name, data in prepare_from(zst_archive, tmpdir.name):
+ if not jar:
+ jar = JarWriter(zip_path)
+ zip_paths.append(zip_path)
+ size = 0
+ log.info("Adding %s", name)
+ jar.add(name, data, compress=not isinstance(data, File))
+ size += data.size() if isinstance(data, File) else data.compressed_size
+ if size > MAX_ZIP_SIZE:
+ jar.finish()
+ jar = None
+ zip_path = next(zip_paths_iter)
+ log.info('Continuing with symbol archive "{}"'.format(zip_path))
+ if jar:
+ jar.finish()
+ return zip_paths
+ except requests.exceptions.RequestException as e:
+ log.error("Error: {0}".format(e))
+ log.info("Retrying...")
+
+ return []
+
+
+def upload_symbols(zip_path):
+ """
+ Upload symbols to the tecken server
+
+ :param zip_path: path to the zip file to upload
+ :returns: 0 indicates the upload was successful, non-zero indicates an
+ error that should be used for the script's exit code
+ """
+ secret_name = os.environ.get("SYMBOL_SECRET")
+ if secret_name is not None:
+ auth_token = get_taskcluster_secret(secret_name)
+ elif "SOCORRO_SYMBOL_UPLOAD_TOKEN_FILE" in os.environ:
+ token_file = os.environ["SOCORRO_SYMBOL_UPLOAD_TOKEN_FILE"]
+
+ if not os.path.isfile(token_file):
+ log.error(
+ 'SOCORRO_SYMBOL_UPLOAD_TOKEN_FILE "{0}" does not exist!'.format(
+ token_file
+ )
+ )
+ return 1
+ auth_token = open(token_file, "r").read().strip()
+ else:
+ log.error(
+ "You must set the SYMBOL_SECRET or SOCORRO_SYMBOL_UPLOAD_TOKEN_FILE "
+ "environment variables!"
+ )
+ return 1
+
+ # Allow overwriting of the upload url with an environmental variable
+ if "SOCORRO_SYMBOL_UPLOAD_URL" in os.environ:
+ url = os.environ["SOCORRO_SYMBOL_UPLOAD_URL"]
+ else:
+ url = DEFAULT_URL
+
+ log.info('Uploading symbol file "{0}" to "{1}"'.format(zip_path, url))
+
+ for i, _ in enumerate(redo.retrier(attempts=MAX_RETRIES), start=1):
+ log.info("Attempt %d of %d..." % (i, MAX_RETRIES))
+ try:
+ if zip_path.startswith("http"):
+ zip_arg = {"data": {"url": zip_path}}
+ else:
+ zip_arg = {"files": {"symbols.zip": open(zip_path, "rb")}}
+ r = requests.post(
+ url,
+ headers={"Auth-Token": auth_token},
+ allow_redirects=False,
+ # Allow a longer read timeout because uploading by URL means the server
+ # has to fetch the entire zip file, which can take a while. The load balancer
+ # in front of symbols.mozilla.org has a 300 second timeout, so we'll use that.
+ timeout=(300, 300),
+ **zip_arg
+ )
+ # 408, 429 or any 5XX is likely to be a transient failure.
+ # Break out for success or other error codes.
+ if r.ok or (r.status_code < 500 and (r.status_code not in (408, 429))):
+ break
+ print_error(r)
+ except requests.exceptions.RequestException as e:
+ log.error("Error: {0}".format(e))
+ log.info("Retrying...")
+ else:
+ log.warning("Maximum retries hit, giving up!")
+ return 1
+
+ if r.status_code >= 200 and r.status_code < 300:
+ log.info("Uploaded successfully!")
+ return 0
+
+ print_error(r)
+ return 1
+
+
+if __name__ == "__main__":
+ sys.exit(main())
diff --git a/toolkit/crashreporter/update-breakpad.sh b/toolkit/crashreporter/update-breakpad.sh
new file mode 100755
index 0000000000..67c17338d4
--- /dev/null
+++ b/toolkit/crashreporter/update-breakpad.sh
@@ -0,0 +1,72 @@
+#!/bin/bash
+# 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/.
+
+set -v -e -x
+
+# Usage: update-breakpad.sh <path to breakpad git clone> [rev, defaults to HEAD]
+
+if [ $# -lt 1 ]; then
+ echo "Usage: update-breakpad.sh /path/to/breakpad/src [rev]"
+ exit 1
+fi
+
+crashreporter_dir=`realpath $(dirname $0)`
+repo=${crashreporter_dir}/../..
+rm -rf ${crashreporter_dir}/google-breakpad
+
+breakpad_repo=$1
+rev=${2-HEAD}
+(cd $breakpad_repo; git archive --prefix=toolkit/crashreporter/google-breakpad/ $rev) | (cd $repo; tar xf -)
+# Breakpad uses gclient for externals, so manually export what we need.
+lss_rev=$(cd $breakpad_repo; git show ${rev}:DEPS | python -c "import sys; exec(sys.stdin.read()); sys.stdout.write('%s\n' % deps['src/src/third_party/lss'].split('@')[1])")
+(cd $breakpad_repo/src/third_party/lss; git archive --prefix=toolkit/crashreporter/google-breakpad/src/third_party/lss/ $lss_rev) | (cd $repo; tar xf -)
+
+# remove some extraneous bits
+# We've forked src/client toolkit/crashreporter/breakpad-client.
+rm -rf \
+ ${crashreporter_dir}/google-breakpad/appveyor.yml \
+ ${crashreporter_dir}/google-breakpad/autotools/ \
+ ${crashreporter_dir}/google-breakpad/docs/ \
+ ${crashreporter_dir}/google-breakpad/m4/ \
+ ${crashreporter_dir}/google-breakpad/scripts/ \
+ ${crashreporter_dir}/google-breakpad/src/client/ \
+ ${crashreporter_dir}/google-breakpad/src/processor/testdata/ \
+ ${crashreporter_dir}/google-breakpad/src/testing/ \
+ ${crashreporter_dir}/google-breakpad/src/third_party/linux \
+ ${crashreporter_dir}/google-breakpad/src/third_party/protobuf \
+ ${crashreporter_dir}/google-breakpad/src/tools/gyp/ \
+ ${crashreporter_dir}/google-breakpad/src/tools/windows/dump_syms/testdata/ \
+ ${crashreporter_dir}/google-breakpad/.github/mistaken-pull-closer.yml \
+ ${crashreporter_dir}/google-breakpad/.travis.yml
+
+# restore our Makefile.ins
+hg -R ${repo} st -n | grep "Makefile\.in$" | xargs hg revert --no-backup
+# and moz.build files
+hg -R ${repo} st -n | grep "moz\.build$" | xargs hg revert --no-backup
+# and some other makefiles
+hg -R ${repo} st -n | grep "objs\.mozbuild$" | xargs hg revert --no-backup
+
+# Record git rev
+(cd $breakpad_repo; git rev-parse $rev) > ${crashreporter_dir}/google-breakpad/GIT-INFO
+
+# Apply any local patches
+shopt -s nullglob
+for p in ${crashreporter_dir}/breakpad-patches/*.patch; do
+ if grep -q -e "--git" $p; then
+ patch_opts="-p1"
+ else
+ patch_opts="-p0"
+ fi
+ echo "Applying $p"
+ if ! filterdiff -x '*/Makefile*' $p | \
+ patch -d ${crashreporter_dir}/google-breakpad ${patch_opts}; then
+ echo "Failed to apply $p"
+ exit 1
+ fi
+done
+# remove any .orig files that snuck in
+find ${crashreporter_dir}/google-breakpad -name "*.orig" -exec rm '{}' \;
+
+hg addremove ${crashreporter_dir}/google-breakpad/